Updated AltairZ80 from Peter Schorn

This commit is contained in:
Mark Pizzolato 2013-04-13 16:47:59 -07:00
parent 400281f3b0
commit ee3d98a125
11 changed files with 745 additions and 494 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
/* altairz80_cpu_opt.c: MITS Altair CPU (8080 and Z80)
Copyright (c) 2002-2011, Peter Schorn
Copyright (c) 2002-2013, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

View file

@ -1,6 +1,6 @@
/* altairz80_defs.h: MITS Altair simulator definitions
Copyright (c) 2002-2011, Peter Schorn
Copyright (c) 2002-2013, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),

Binary file not shown.

View file

@ -1,6 +1,6 @@
/* altairz80_dsk.c: MITS Altair 88-DISK Simulator
Copyright (c) 2002-2011, Peter Schorn
Copyright (c) 2002-2013, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -483,6 +483,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
current_disk, PCX);
}
current_track[current_disk]++;
current_flag[current_disk] &= 0xbf; /* mwd 1/29/13: track zero now false */
if (current_track[current_disk] > (tracks[current_disk] - 1))
current_track[current_disk] = (tracks[current_disk] - 1);
if (dirty) /* implies that current_disk < NUM_OF_DSK */

View file

@ -1,6 +1,6 @@
/* altairz80_hdsk.c: simulated hard disk device to increase capacity
Copyright (c) 2002-2011, Peter Schorn
Copyright (c) 2002-2013, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -28,6 +28,7 @@
#include "altairz80_defs.h"
#include <assert.h>
#include "sim_imd.h"
/* Debug flags */
#define READ_MSG (1 << 0)
@ -43,6 +44,9 @@ static t_stat show_format(FILE *st, UNIT *uptr, int32 val, void *desc);
static t_stat hdsk_reset(DEVICE *dptr);
static t_stat hdsk_attach(UNIT *uptr, char *cptr);
static t_stat hdsk_detach(UNIT *uptr);
static uint32 is_imd(const UNIT *uptr);
static void assignFormat(UNIT *uptr);
static void verifyDiskInfo(const DISK_INFO info, const char unitChar);
#define UNIT_V_HDSK_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_HDSK_WLK (1 << UNIT_V_HDSK_WLK)
@ -118,6 +122,7 @@ typedef struct {
#define SPT16 16
#define SPT32 32
#define SPT26 26
#define SPT52 52
static HDSK_INFO hdsk_info_data = { { 0x0000, 0, 0xFD, 1 } };
@ -126,18 +131,18 @@ static int32 standard8[SPT26] = { 0, 6, 12, 18, 24, 4, 10, 16,
19, 25, 5, 11, 17, 23, 3, 9,
15, 21 };
static int32 appple_ii_DOS[SPT16] = { 0, 6, 12, 3, 9, 15, 14, 5,
static int32 apple_ii_DOS[SPT16] = { 0, 6, 12, 3, 9, 15, 14, 5,
11, 2, 8, 7, 13, 4, 10, 1 };
static int32 appple_ii_DOS2[SPT32] = { 0, 1, 12, 13, 24, 25, 6, 7,
static int32 apple_ii_DOS2[SPT32] = { 0, 1, 12, 13, 24, 25, 6, 7,
18, 19, 30, 31, 28, 29, 10, 11,
22, 23, 4, 5, 16, 17, 14, 15,
26, 27, 8, 9, 20, 21, 2, 3 };
static int32 appple_ii_PRODOS[SPT16] = { 0, 9, 3, 12, 6, 15, 1, 10,
static int32 apple_ii_PRODOS[SPT16] = { 0, 9, 3, 12, 6, 15, 1, 10,
4, 13, 7, 8, 2, 11, 5, 14 };
static int32 appple_ii_PRODOS2[SPT32] = { 0, 1, 18, 19, 6, 7, 24, 25,
static int32 apple_ii_PRODOS2[SPT32] = { 0, 1, 18, 19, 6, 7, 24, 25,
12, 13, 30, 31, 2, 3, 20, 21,
8, 9, 26, 27, 14, 15, 16, 17,
4, 5, 22, 23, 10, 11, 28, 29 };
@ -197,17 +202,44 @@ static DPB dpb[] = {
{ "SSSD8S", 256256, SPT26, 0x03, 0x07, 0x00, 242, 0x003F,
0xC0, 0x00, 0x0000, 0x0002, 0x00, 0x00, 0, 0, standard8 }, /* Standard 8" SS SD with skew */
{ "SSDD8", 512512, SPT52, 0x04, 0x0F, 0x01, 242, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, NULL }, /* Standard 8" SS DD */
{ "SSDD8S", 512512, SPT52, 0x04, 0x0F, 0x01, 242, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, standard8 }, /* Standard 8" SS DD with skew */
{ "DSDD8", 1025024, SPT52, 0x04, 0x0F, 0x00, 493, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, NULL }, /* Standard 8" DS DD */
{ "DSDD8S", 1025024, SPT52, 0x04, 0x0F, 0x00, 493, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x01, 0x01, 0, 0, NULL }, /* Standard 8" DS DD with skew */
{"512SSDD8",591360, 60, 0x04, 0x0F, 0x00, 280, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Standard 8" SS DD with 512 byte sectors */
{"512DSDD8",1182720, 60, 0x04, 0x0F, 0x00, 569, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Standard 8" DS DD with 512 byte sectors */
#if 0
/* CP/M 3 BIOS currently does not support physical sector size 1024 */
{"1024SSDD8",630784, 64, 0x04, 0x0F, 0x00, 299, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x03, 0x07, 0, 0, NULL }, /* Standard 8" SS DD with 1024 byte sectors */
{"1024DSDD8",1261568, 64, 0x04, 0x0F, 0x00, 607, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x03, 0x07, 0, 0, NULL }, /* Standard 8" DS DD with 1024 byte sectors */
#endif
{ "APPLE-DO",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F,
0xC0, 0x00, 0x0000, 0x0003, 0x01, 0x01, 0, 0, appple_ii_DOS }, /* Apple II DOS 3.3 */
0xC0, 0x00, 0x0000, 0x0003, 0x01, 0x01, 0, 0, apple_ii_DOS }, /* Apple II DOS 3.3 */
{ "APPLE-PO",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F,
0xC0, 0x00, 0x0000, 0x0003, 0x01, 0x01, 0, 0, appple_ii_PRODOS }, /* Apple II PRODOS */
0xC0, 0x00, 0x0000, 0x0003, 0x01, 0x01, 0, 0, apple_ii_PRODOS }, /* Apple II PRODOS */
{ "APPLE-D2",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F,
0xC0, 0x00, 0x0000, 0x0003, 0x00, 0x00, 0, 0, appple_ii_DOS2 }, /* Apple II DOS 3.3, deblocked */
0xC0, 0x00, 0x0000, 0x0003, 0x00, 0x00, 0, 0, apple_ii_DOS2 }, /* Apple II DOS 3.3, deblocked */
{ "APPLE-P2",143360, SPT32, 0x03, 0x07, 0x00, 127, 0x003F,
0xC0, 0x00, 0x0000, 0x0003, 0x00, 0x00, 0, 0, appple_ii_PRODOS2 }, /* Apple II PRODOS, deblocked */
0xC0, 0x00, 0x0000, 0x0003, 0x00, 0x00, 0, 0, apple_ii_PRODOS2 }, /* Apple II PRODOS, deblocked */
{ "MITS", 337568, SPT32, 0x03, 0x07, 0x00, 254, 0x00FF,
0xFF, 0x00, 0x0000, 0x0006, 0x00, 0x00, 137, 3, mits }, /* MITS Altair original */
@ -215,6 +247,20 @@ static DPB dpb[] = {
{ "MITS2", 1113536, SPT32, 0x04, 0x0F, 0x00, 0x1EF, 0x00FF,
0xF0, 0x00, 0x0000, 0x0006, 0x00, 0x00, 137, 3, mits }, /* MITS Altair original, extra */
/*
dw 40 ;#128 byte records/track
db 4,0fh ;block shift mask (2K)
db 1 ;extent mask
dw 194 ;maximun block number
dw 127 ;max number of dir entry - 1
db 0C0H,00h ;alloc vector for directory
dw 0020h ;checksum size
dw 2 ;offset for sys tracks
db 2,3 ;physical sector shift (512 sector)
*/
{ "V1050", 409600, 40, 0x04, 0x0F, 0x01, 194, 0x007F,
0xC0, 0x00, 0x0000, 0x0002, 0x02, 0x03, 0, 0, NULL }, /* Visual Technology Visual 1050, http://www.metabarn.com/v1050/index.html */
{ "", 0 }
};
@ -228,6 +274,7 @@ static UNIT hdsk_unit[] = {
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) },
{ UDATA (NULL, UNIT_FIX + UNIT_ATTABLE + UNIT_DISABLE + UNIT_ROABLE, HDSK_CAPACITY) }
};
static DISK_INFO* hdsk_imd[HDSK_NUMBER];
static REG hdsk_reg[] = {
{ DRDATA (HDCMD, hdskLastCommand, 32), REG_RO },
@ -267,63 +314,128 @@ DEVICE hdsk_dev = {
/* Reset routine */
static t_stat hdsk_reset(DEVICE *dptr) {
PNP_INFO *pnp = (PNP_INFO *)dptr->ctxt;
if (dptr->flags & DEV_DIS) {
sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &hdsk_io, TRUE);
PNP_INFO *pnp = (PNP_INFO *)dptr -> ctxt;
if (dptr -> flags & DEV_DIS) {
sim_map_resource(pnp -> io_base, pnp -> io_size, RESOURCE_TYPE_IO, &hdsk_io, TRUE);
} else {
/* Connect HDSK at base address */
if (sim_map_resource(pnp->io_base, pnp->io_size, RESOURCE_TYPE_IO, &hdsk_io, FALSE) != 0) {
printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp->mem_base);
dptr->flags |= DEV_DIS;
if (sim_map_resource(pnp -> io_base, pnp -> io_size, RESOURCE_TYPE_IO, &hdsk_io, FALSE) != 0) {
printf("%s: error mapping I/O resource at 0x%04x\n", __FUNCTION__, pnp -> mem_base);
dptr -> flags |= DEV_DIS;
return SCPE_ARG;
}
}
return SCPE_OK;
}
/* Attach routine */
static t_stat hdsk_attach(UNIT *uptr, char *cptr) {
t_stat r;
#ifdef _WIN32
#define strcasecmp _stricmp
#endif
static uint32 is_imd(const UNIT *uptr) {
return ((uptr != NULL) && (uptr -> filename != NULL) && (strlen(uptr -> filename) > 3) &&
(strcasecmp(".IMD", uptr -> filename + strlen(uptr -> filename) - 4) == 0));
}
static void assignFormat(UNIT *uptr) {
uint32 i;
char unitChar;
r = attach_unit(uptr, cptr); /* attach unit */
if ( r != SCPE_OK) /* error? */
return r;
/* Step 1: Determine capacity of this disk */
uptr -> capac = sim_fsize(uptr -> fileref); /* the file length is a good indication */
if (uptr -> capac == 0) { /* file does not exist or has length 0 */
uptr -> capac = uptr -> HDSK_NUMBER_OF_TRACKS *
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE;
if (uptr -> capac == 0)
uptr -> capac = HDSK_CAPACITY;
} /* post condition: uptr -> capac > 0 */
assert(uptr -> capac);
/* Step 2: Determine format based on disk capacity */
uptr -> HDSK_FORMAT_TYPE = -1; /* default to unknown format type */
for (i = 0; dpb[i].capac != 0; i++) { /* find disk parameter block */
if (dpb[i].capac == uptr -> capac) { /* found if correct capacity */
uptr -> HDSK_FORMAT_TYPE = -1; /* default to unknown format type */
for (i = 0; dpb[i].capac != 0; i++) { /* find disk parameter block */
if (dpb[i].capac == uptr -> capac) { /* found if correct capacity */
uptr -> HDSK_FORMAT_TYPE = i;
break;
}
}
}
/* Step 3: Set number of sectors per track and sector size */
if (uptr -> HDSK_FORMAT_TYPE == -1) { /* Case 1: no disk parameter block found*/
for (i = 0; i < hdsk_dev.numunits; i++) /* find affected unit number */
if (&hdsk_unit[i] == uptr)
break; /* found */
unitChar = '0' + i;
static void verifyDiskInfo(const DISK_INFO info, const char unitChar) {
uint32 track, head;
if (info.ntracks < 1)
printf("HDSK%c (IMD): WARNING: Number of tracks is 0.\n", unitChar);
if (info.nsides < 1) {
printf("HDSK%c (IMD): WARNING: Number of sides is 0.\n", unitChar);
return;
}
for (track = 0; track < info.ntracks / info.nsides; track++)
for (head = 0; head < info.nsides; head++) {
if (info.track[track][head].nsects != info.track[1][0].nsects)
printf("HDSK%c (IMD): WARNING: For track %i and head %i expected number of sectors "
"%i but got %i.\n", unitChar, track, head,
info.track[1][0].nsects, info.track[track][head].nsects);
if (info.track[track][head].sectsize != info.track[1][0].sectsize)
printf("HDSK%c (IMD): WARNING: For track %i and head %i expected sector size "
"%i but got %i.\n", unitChar, track, head,
info.track[1][0].sectsize, info.track[track][head].sectsize);
if (info.track[track][head].start_sector != info.track[1][0].start_sector)
printf("HDSK%c (IMD): WARNING: For track %i and head %i expected start sector "
"%i but got %i.\n", unitChar, track, head,
info.track[1][0].start_sector, info.track[track][head].start_sector);
}
}
/* Attach routine */
static t_stat hdsk_attach(UNIT *uptr, char *cptr) {
int32 thisUnitIndex;
char unitChar;
const t_stat r = attach_unit(uptr, cptr); /* attach unit */
if (r != SCPE_OK) /* error? */
return r;
assert(uptr != NULL);
thisUnitIndex = find_unit_index(uptr);
unitChar = '0' + thisUnitIndex;
assert((0 <= thisUnitIndex) && (thisUnitIndex < HDSK_NUMBER));
if (is_imd(uptr)) {
if ((sim_fsize(uptr -> fileref) == 0) &&
(diskCreate(uptr -> fileref, "$Id: SIMH hdsk.c $") != SCPE_OK)) {
printf("HDSK%c (IMD): Failed to create IMD disk.\n", unitChar);
detach_unit(uptr);
return SCPE_OPENERR;
}
hdsk_imd[thisUnitIndex] = diskOpen(uptr -> fileref, sim_deb && (hdsk_dev.dctrl & VERBOSE_MSG));
if (hdsk_imd[thisUnitIndex] == NULL)
return SCPE_IOERR;
verifyDiskInfo(*hdsk_imd[thisUnitIndex], '0' + thisUnitIndex);
uptr -> HDSK_NUMBER_OF_TRACKS = hdsk_imd[thisUnitIndex] -> ntracks;
uptr -> HDSK_SECTORS_PER_TRACK = hdsk_imd[thisUnitIndex] -> track[1][0].nsects;
uptr -> HDSK_SECTOR_SIZE = hdsk_imd[thisUnitIndex] -> track[1][0].sectsize;
uptr -> capac = ((uptr -> HDSK_NUMBER_OF_TRACKS) *
(uptr -> HDSK_SECTORS_PER_TRACK) *
(uptr -> HDSK_SECTOR_SIZE));
assignFormat(uptr);
if (uptr -> HDSK_FORMAT_TYPE == -1) { /* Case 1: no disk parameter block found*/
uptr -> HDSK_FORMAT_TYPE = 0;
printf("HDSK%c (IMD): WARNING: Unsupported disk capacity, assuming HDSK type "
"with capacity %iKB.\n", unitChar, uptr -> capac / 1000);
uptr -> flags |= UNIT_HDSK_WLK;
printf("HDSK%c (IMD): WARNING: Forcing WRTLCK.\n", unitChar);
}
return SCPE_OK;
}
/* Step 1: Determine capacity of this disk */
uptr -> capac = sim_fsize(uptr -> fileref); /* the file length is a good indication */
if (uptr -> capac == 0) { /* file does not exist or has length 0 */
uptr -> capac = (uptr -> HDSK_NUMBER_OF_TRACKS *
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE);
if (uptr -> capac == 0)
uptr -> capac = HDSK_CAPACITY;
} /* post condition: uptr -> capac > 0 */
assert(uptr -> capac);
/* Step 2: Determine format based on disk capacity */
assignFormat(uptr);
/* Step 3: Set number of sectors per track and sector size */
if (uptr -> HDSK_FORMAT_TYPE == -1) { /* Case 1: no disk parameter block found */
uptr -> HDSK_FORMAT_TYPE = 0;
printf("HDSK%c: WARNING: Unsupported disk capacity, assuming HDSK type with capacity %iKB.\n",
unitChar, uptr -> capac / 1000);
unitChar, uptr -> capac / 1000);
uptr -> flags |= UNIT_HDSK_WLK;
printf("HDSK%c: WARNING: Forcing WRTLCK.\n", unitChar);
/* check whether capacity corresponds to setting of tracks, sectors per track and sector size */
/* check whether capacity corresponds to setting of tracks, sectors per track and sector size */
if (uptr -> capac != (uint32)(uptr -> HDSK_NUMBER_OF_TRACKS *
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE)) {
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE)) {
printf("HDSK%c: WARNING: Fixing geometry.\n", unitChar);
if (uptr -> HDSK_SECTORS_PER_TRACK == 0)
uptr -> HDSK_SECTORS_PER_TRACK = 32;
@ -331,27 +443,35 @@ static t_stat hdsk_attach(UNIT *uptr, char *cptr) {
uptr -> HDSK_SECTOR_SIZE = 128;
}
}
else { /* Case 2: disk parameter block found */
else { /* Case 2: disk parameter block found */
uptr -> HDSK_SECTORS_PER_TRACK = dpb[uptr -> HDSK_FORMAT_TYPE].spt >> dpb[uptr -> HDSK_FORMAT_TYPE].psh;
uptr -> HDSK_SECTOR_SIZE = (128 << dpb[uptr -> HDSK_FORMAT_TYPE].psh);
}
assert((uptr -> HDSK_SECTORS_PER_TRACK) && (uptr -> HDSK_SECTOR_SIZE) && (uptr -> HDSK_FORMAT_TYPE >= 0));
/* Step 4: Number of tracks is smallest number to accomodate capacity */
/* Step 4: Number of tracks is smallest number to accomodate capacity */
uptr -> HDSK_NUMBER_OF_TRACKS = (uptr -> capac + uptr -> HDSK_SECTORS_PER_TRACK *
uptr -> HDSK_SECTOR_SIZE - 1) / (uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE);
uptr -> HDSK_SECTOR_SIZE - 1) / (uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE);
assert( ( (t_addr) ((uptr -> HDSK_NUMBER_OF_TRACKS - 1) * uptr -> HDSK_SECTORS_PER_TRACK *
uptr -> HDSK_SECTOR_SIZE) < uptr -> capac) &&
(uptr -> capac <= (t_addr) (uptr -> HDSK_NUMBER_OF_TRACKS *
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE) ) );
uptr -> HDSK_SECTOR_SIZE) < uptr -> capac) &&
(uptr -> capac <= (t_addr) (uptr -> HDSK_NUMBER_OF_TRACKS *
uptr -> HDSK_SECTORS_PER_TRACK * uptr -> HDSK_SECTOR_SIZE) ) );
return SCPE_OK;
}
static t_stat hdsk_detach(UNIT *uptr) {
t_stat result;
int32 unitIndex;
if (uptr == NULL)
return SCPE_IERR;
if (is_imd(uptr)) {
unitIndex = find_unit_index(uptr);
if (unitIndex == -1)
return SCPE_IERR;
assert((0 <= unitIndex) && (unitIndex < HDSK_NUMBER));
diskClose(&hdsk_imd[unitIndex]);
}
result = detach_unit(uptr);
uptr -> capac = HDSK_CAPACITY;
uptr -> HDSK_FORMAT_TYPE = 0;
@ -490,7 +610,7 @@ static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
install_ALTAIRbootROM(); /* install modified ROM */
}
assert(install_bootrom(bootrom_hdsk, BOOTROM_SIZE_HDSK, HDSK_BOOT_ADDRESS, FALSE) == SCPE_OK);
*((int32 *) sim_PC->loc) = HDSK_BOOT_ADDRESS;
*((int32 *) sim_PC -> loc) = HDSK_BOOT_ADDRESS;
return SCPE_OK;
}
@ -603,22 +723,57 @@ static int32 doSeek(void) {
return CPM_OK;
}
uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */
static uint8 hdskbuf[HDSK_MAX_SECTOR_SIZE] = { 0 }; /* data buffer */
/* pre-condition: checkParameters has been executed to repair any faulty parameters */
static int32 doRead(void) {
int32 i;
t_stat result;
DISK_INFO *thisDisk;
int32 hostSector;
int32 sectorSize;
uint32 flags;
uint32 readlen;
uint32 cylinder;
uint32 head;
UNIT *uptr = &hdsk_dev.units[selectedDisk];
if (doSeek())
return CPM_ERROR;
if (is_imd(uptr)) {
thisDisk = hdsk_imd[selectedDisk];
hostSector = ((dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ?
selectedSector : dpb[uptr -> HDSK_FORMAT_TYPE].skew[selectedSector]) + thisDisk -> track[1][0].start_sector;
sectorSize = ((dpb[uptr -> HDSK_FORMAT_TYPE].physicalSectorSize == 0) ?
uptr -> HDSK_SECTOR_SIZE :
dpb[uptr -> HDSK_FORMAT_TYPE].physicalSectorSize);
flags = 0;
readlen = 0;
cylinder = selectedTrack;
head = 0;
if (cylinder >= thisDisk -> ntracks / thisDisk -> nsides) {
head = 1;
cylinder -= thisDisk -> ntracks / thisDisk -> nsides;
}
result = sectRead(thisDisk, cylinder, head, hostSector, hdskbuf, sectorSize,
&flags, &readlen);
if (result != SCPE_OK) {
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = CPM_EMPTY;
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d (IMD): " ADDRESS_FORMAT
" . Could not read Sector=%02d Track=%04d.\n",
selectedDisk, PCX, selectedSector, selectedTrack);
return CPM_ERROR;
}
} else {
if (doSeek())
return CPM_ERROR;
if (sim_fread(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref) != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = CPM_EMPTY;
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Could not read Sector=%02d Track=%04d.\n",
selectedDisk, PCX, selectedSector, selectedTrack);
return CPM_OK; /* allows the creation of empty hard disks */
if (sim_fread(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref) != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = CPM_EMPTY;
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Could not read Sector=%02d Track=%04d.\n",
selectedDisk, PCX, selectedSector, selectedTrack);
return CPM_OK; /* allows the creation of empty hard disks */
}
}
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
PutBYTEWrapper(selectedDMA + i, hdskbuf[i]);
@ -628,19 +783,54 @@ static int32 doRead(void) {
/* pre-condition: checkParameters has been executed to repair any faulty parameters */
static int32 doWrite(void) {
int32 i;
t_stat result;
DISK_INFO *thisDisk;
int32 hostSector;
int32 sectorSize;
uint32 flags;
uint32 writelen;
uint32 cylinder;
uint32 head;
size_t rtn;
UNIT *uptr = &hdsk_dev.units[selectedDisk];
if (((uptr -> flags) & UNIT_HDSK_WLK) == 0) { /* write enabled */
if (doSeek())
return CPM_ERROR;
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
rtn = sim_fwrite(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref);
if (rtn != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Could not write Sector=%02d Track=%04d Result=%zd.\n",
selectedDisk, PCX, selectedSector, selectedTrack, rtn);
return CPM_ERROR;
if (is_imd(uptr)) {
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
thisDisk = hdsk_imd[selectedDisk];
hostSector = ((dpb[uptr -> HDSK_FORMAT_TYPE].skew == NULL) ?
selectedSector : dpb[uptr -> HDSK_FORMAT_TYPE].skew[selectedSector]) + thisDisk -> track[1][0].start_sector;
sectorSize = ((dpb[uptr -> HDSK_FORMAT_TYPE].physicalSectorSize == 0) ?
uptr -> HDSK_SECTOR_SIZE :
dpb[uptr -> HDSK_FORMAT_TYPE].physicalSectorSize);
flags = 0;
writelen = 0;
cylinder = selectedTrack;
head = 0;
if (cylinder >= thisDisk -> ntracks / thisDisk -> nsides) {
head = 1;
cylinder -= thisDisk -> ntracks / thisDisk -> nsides;
}
result = sectWrite(thisDisk, cylinder, head, hostSector, hdskbuf,
sectorSize, &flags, &writelen);
if (result != SCPE_OK) {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d (IMD): " ADDRESS_FORMAT
" . Could not write Sector=%02d Track=%04d.\n",
selectedDisk, PCX, selectedSector, selectedTrack);
return CPM_ERROR;
}
} else {
if (doSeek())
return CPM_ERROR;
for (i = 0; i < uptr -> HDSK_SECTOR_SIZE; i++)
hdskbuf[i] = GetBYTEWrapper(selectedDMA + i);
rtn = sim_fwrite(hdskbuf, 1, uptr -> HDSK_SECTOR_SIZE, uptr -> fileref);
if (rtn != (size_t)(uptr -> HDSK_SECTOR_SIZE)) {
sim_debug(VERBOSE_MSG, &hdsk_dev, "HDSK%d: " ADDRESS_FORMAT
" Could not write Sector=%02d Track=%04d Result=%zd.\n",
selectedDisk, PCX, selectedSector, selectedTrack, rtn);
return CPM_ERROR;
}
}
}
else {

View file

@ -1,6 +1,6 @@
/* altairz80_net.c: networking capability
Copyright (c) 2002-2011, Peter Schorn
Copyright (c) 2002-2013, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -77,16 +77,14 @@ static struct {
static UNIT net_unit = {
UDATA (&net_svc, UNIT_ATTABLE, 0),
0, /* wait, set in attach */
0, /* u3 = Port */
0, /* u4 = IP of host */
0, /* u3, unused */
0, /* u4, unused */
0, /* u5, unused */
0, /* u6, unused */
};
static REG net_reg[] = {
{ DRDATA (POLL, net_unit.wait, 32) },
{ HRDATA (IPHOST, net_unit.u4, 32), REG_RO },
{ DRDATA (PORT, net_unit.u3, 32), REG_RO },
{ NULL }
};

View file

@ -1,6 +1,6 @@
/* altairz80_sio.c: MITS Altair serial I/O card
Copyright (c) 2002-2011, Peter Schorn
Copyright (c) 2002-2013, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -64,27 +64,27 @@
uint8 *URLContents(const char *URL, uint32 *length);
#ifndef URL_READER_SUPPORT
#define RESULT_BUFFER_LENGTH 1024
#define RESULT_BUFFER_LENGTH 1024
#define RESULT_LEAD_IN "URL is not supported on this platform. START URL \""
#define RESULT_LEAD_OUT "\" URL END."
uint8 *URLContents(const char *URL, uint32 *length) {
char str[RESULT_BUFFER_LENGTH] = RESULT_LEAD_IN;
char str[RESULT_BUFFER_LENGTH] = RESULT_LEAD_IN;
char *result;
strncat(str, URL, RESULT_BUFFER_LENGTH - strlen(RESULT_LEAD_IN) - strlen(RESULT_LEAD_OUT) - 1);
strcat(str, RESULT_LEAD_OUT);
result = malloc(strlen(str));
strcpy(result, str);
*length = strlen(str);
return (uint8*)result;
strncat(str, URL, RESULT_BUFFER_LENGTH - strlen(RESULT_LEAD_IN) - strlen(RESULT_LEAD_OUT) - 1);
strcat(str, RESULT_LEAD_OUT);
result = (char*)malloc(strlen(str));
strcpy(result, str);
*length = strlen(str);
return (uint8*)result;
}
#endif
/* Debug flags */
#define IN_MSG (1 << 0)
#define OUT_MSG (1 << 1)
#define CMD_MSG (1 << 2)
#define VERBOSE_MSG (1 << 3)
#define BUFFER_EMPTY_MSG (1 << 4)
#define IN_MSG (1 << 0)
#define OUT_MSG (1 << 1)
#define CMD_MSG (1 << 2)
#define VERBOSE_MSG (1 << 3)
#define BUFFER_EMPTY_MSG (1 << 4)
#define UNIT_V_SIO_ANSI (UNIT_V_UF + 0) /* ANSI mode, strip bit 8 on output */
#define UNIT_SIO_ANSI (1 << UNIT_V_SIO_ANSI)
@ -172,12 +172,12 @@ extern volatile int32 stop_cpu;
/* Debug Flags */
static DEBTAB generic_dt[] = {
{ "IN", IN_MSG },
{ "OUT", OUT_MSG },
{ "CMD", CMD_MSG },
{ "VERBOSE", VERBOSE_MSG },
{ "BUFFEREMPTY", BUFFER_EMPTY_MSG },
{ NULL, 0 }
{ "IN", IN_MSG },
{ "OUT", OUT_MSG },
{ "CMD", CMD_MSG },
{ "VERBOSE", VERBOSE_MSG },
{ "BUFFEREMPTY", BUFFER_EMPTY_MSG },
{ NULL, 0 }
};
/* SIMH pseudo device status registers */
@ -225,10 +225,10 @@ static int32 lastCPMStatus = 0; /* result of last attachCPM comm
static int32 lastCommand = 0; /* most recent command processed on port 0xfeh */
static int32 getCommonPos = 0; /* determines state for sending the 'common' register */
/* CPU Clock Frequency related */
/* CPU Clock Frequency related */
static uint32 newClockFrequency;
static int32 setClockFrequencyPos = 0; /* determines state for sending the clock frequency */
static int32 getClockFrequencyPos = 0; /* determines state for receiving the clock frequency */
static int32 setClockFrequencyPos = 0; /* determines state for sending the clock frequency */
static int32 getClockFrequencyPos = 0; /* determines state for receiving the clock frequency */
/* support for wild card expansion */
#if UNIX_PLATFORM
@ -274,7 +274,7 @@ static UNIT sio_unit = {
100000, /* wait */
FALSE, /* u3 = FALSE, no character available in buffer */
FALSE, /* u4 = FALSE, terminal input is not attached to a file */
0, /* u5 = 0, not used */
0, /* u5 = 0, not used */
0 /* u6 = 0, not used */
};
@ -456,7 +456,7 @@ static t_stat sio_reset(DEVICE *dptr) {
int32 i;
sim_debug(VERBOSE_MSG, &sio_dev, "SIO: " ADDRESS_FORMAT " Reset\n", PCX);
sio_unit.u3 = FALSE; /* no character in terminal input buffer */
sio_unit.buf = 0;
sio_unit.buf = 0;
resetSIOWarningFlags();
if (sio_unit.u4) /* is terminal input attached to a file? */
rewind(sio_unit.fileref); /* yes, rewind input */
@ -472,7 +472,7 @@ static t_stat ptr_reset(DEVICE *dptr) {
sim_debug(VERBOSE_MSG, &ptr_dev, "PTR: " ADDRESS_FORMAT " Reset\n", PCX);
resetSIOWarningFlags();
ptr_unit.u3 = FALSE; /* End Of File not yet reached */
ptr_unit.buf = 0;
ptr_unit.buf = 0;
if (ptr_unit.flags & UNIT_ATT) /* attached? */
rewind(ptr_unit.fileref);
sim_map_resource(0x12, 1, RESOURCE_TYPE_IO, &sio1s, dptr->flags & DEV_DIS);
@ -650,18 +650,18 @@ static int32 sio0sCore(const int32 port, const int32 io, const int32 data) {
pollConnection();
if (io == 0) { /* IN */
if (sio_unit.u4) { /* attached to a file? */
if (sio_unit.u3) /* character available? */
return spi.sio_can_read | spi.sio_can_write;
ch = getc(sio_unit.fileref);
if (ch == EOF) {
if (sio_unit.u3) /* character available? */
return spi.sio_can_read | spi.sio_can_write;
ch = getc(sio_unit.fileref);
if (ch == EOF) {
sio_detach(&sio_unit); /* detach file and switch to keyboard input */
return spi.sio_cannot_read | spi.sio_can_write;
}
else {
sio_unit.u3 = TRUE; /* indicate character available */
sio_unit.buf = ch; /* store character in buffer */
return spi.sio_can_read | spi.sio_can_write;
}
return spi.sio_cannot_read | spi.sio_can_write;
}
else {
sio_unit.u3 = TRUE; /* indicate character available */
sio_unit.buf = ch; /* store character in buffer */
return spi.sio_can_read | spi.sio_can_write;
}
}
if (sio_unit.flags & UNIT_ATT) { /* attached to a port? */
if (tmxr_rqln(&TerminalLines[spi.terminalLine]))
@ -692,8 +692,8 @@ static int32 sio0sCore(const int32 port, const int32 io, const int32 data) {
return spi.sio_cannot_read | spi.sio_can_write;
} /* OUT follows, no fall-through from IN */
if (spi.hasReset && (data == spi.sio_reset)) { /* reset command */
if (!sio_unit.u4) /* only reset for regular console I/O */
sio_unit.u3 = FALSE; /* indicate that no character is available */
if (!sio_unit.u4) /* only reset for regular console I/O */
sio_unit.u3 = FALSE; /* indicate that no character is available */
sim_debug(CMD_MSG, &sio_dev, "\tSIO_S: " ADDRESS_FORMAT
" Command OUT(0x%03x) = 0x%02x\n", PCX, port, data);
}
@ -723,7 +723,7 @@ static int32 sio0dCore(const int32 port, const int32 io, const int32 data) {
if ((sio_unit.flags & UNIT_ATT) && (!sio_unit.u4))
return mapCharacter(tmxr_getc_ln(&TerminalLines[spi.terminalLine]));
if (!sio_unit.u3) {
sim_debug(BUFFER_EMPTY_MSG, &sio_dev, "\tSIO_D: " ADDRESS_FORMAT
sim_debug(BUFFER_EMPTY_MSG, &sio_dev, "\tSIO_D: " ADDRESS_FORMAT
" IN(0x%03x) for empty character buffer\n", PCX, port);
}
sio_unit.u3 = FALSE; /* no character is available any more */
@ -733,8 +733,10 @@ static int32 sio0dCore(const int32 port, const int32 io, const int32 data) {
ch = sio_unit.flags & UNIT_SIO_ANSI ? data & 0x7f : data; /* clear highest bit in ANSI mode */
if ((ch != CONTROLG_CHAR) || !(sio_unit.flags & UNIT_SIO_BELL)) {
voidSleep();
if ((sio_unit.flags & UNIT_ATT) && (!sio_unit.u4)) /* attached to a port and not to a file */
if ((sio_unit.flags & UNIT_ATT) && (!sio_unit.u4)) { /* attached to a port and not to a file */
tmxr_putc_ln(&TerminalLines[spi.terminalLine], ch); /* status ignored */
tmxr_poll_tx(&altairTMXR); /* poll xmt */
}
else
sim_putchar(ch);
}
@ -743,15 +745,15 @@ static int32 sio0dCore(const int32 port, const int32 io, const int32 data) {
}
static char* printable(char* result, int32 data, const int32 isIn) {
result[0] = 0;
data &= 0x7f;
if ((0x20 <= data) && (data < 0x7f))
sprintf(result, isIn ? " <-\"%c\"" : " ->\"%c\"", data);
return result;
result[0] = 0;
data &= 0x7f;
if ((0x20 <= data) && (data < 0x7f))
sprintf(result, isIn ? " <-\"%c\"" : " ->\"%c\"", data);
return result;
}
int32 sio0d(const int32 port, const int32 io, const int32 data) {
char buffer[8];
char buffer[8];
const int32 result = sio0dCore(port, io, data);
if (io == 0) {
sim_debug(IN_MSG, &sio_dev, "\tSIO_D: " ADDRESS_FORMAT
@ -797,7 +799,7 @@ int32 sio1s(const int32 port, const int32 io, const int32 data) {
" IN(0x%02x) = 0x%02x\n", PCX, port, result);
sim_debug(IN_MSG, &ptp_dev, "PTP_S: " ADDRESS_FORMAT
" IN(0x%02x) = 0x%02x\n", PCX, port, result);
}
}
else if (io) {
sim_debug(OUT_MSG, &ptr_dev, "PTR_S: " ADDRESS_FORMAT
" OUT(0x%02x) = 0x%02x\n", PCX, port, data);
@ -1068,7 +1070,7 @@ static int32 fromBCD(const int32 x) {
out (0feh),a
ld a,<p2>
out (0feh),a
... ; send all parameters
... ; send all parameters
in a,(0feh) ; <A> contains first byte of result
in a,(0feh) ; <A> contains second byte of result
...
@ -1106,10 +1108,10 @@ enum simhPseudoDeviceCommands { /* do not change order or remove commands, add o
SIMHSleepCmd, /* 27 let SIMH sleep for SIMHSleep microseconds */
getHostOSPathSeparatorCmd, /* 28 obtain the file path separator of the OS under which SIMH runs */
getHostFilenamesCmd, /* 29 perform wildcard expansion and obtain list of file names */
readURLCmd, /* 30 read the contents of an URL */
getCPUClockFrequency, /* 31 get the clock frequency of the CPU */
setCPUClockFrequency, /* 32 set the clock frequency of the CPU */
kSimhPseudoDeviceCommands
readURLCmd, /* 30 read the contents of an URL */
getCPUClockFrequency, /* 31 get the clock frequency of the CPU */
setCPUClockFrequency, /* 32 set the clock frequency of the CPU */
kSimhPseudoDeviceCommands
};
static char *cmdNames[kSimhPseudoDeviceCommands] = {
@ -1143,9 +1145,9 @@ static char *cmdNames[kSimhPseudoDeviceCommands] = {
"SIMHSleep",
"getHostOSPathSeparator",
"getHostFilenames",
"readURL",
"getCPUClockFrequency",
"setCPUClockFrequency",
"readURL",
"getCPUClockFrequency",
"setCPUClockFrequency",
};
#define CPM_COMMAND_LINE_LENGTH 128
@ -1155,7 +1157,7 @@ static struct tm currentTime;
static int32 currentTimeValid = FALSE;
static char version[] = "SIMH004";
#define URL_MAX_LENGTH 1024
#define URL_MAX_LENGTH 1024
static uint32 urlPointer;
static char urlStore[URL_MAX_LENGTH];
static uint8 *urlResult = NULL;
@ -1182,13 +1184,13 @@ static t_stat simh_dev_reset(DEVICE *dptr) {
lastCommand = 0;
lastCPMStatus = SCPE_OK;
timerInterrupt = FALSE;
urlPointer = 0;
getClockFrequencyPos = 0;
setClockFrequencyPos = 0;
if (urlResult != NULL) {
free(urlResult);
urlResult = NULL;
}
urlPointer = 0;
getClockFrequencyPos = 0;
setClockFrequencyPos = 0;
if (urlResult != NULL) {
free(urlResult);
urlResult = NULL;
}
if (simh_unit.flags & UNIT_SIMH_TIMERON)
simh_dev_set_timeron(NULL, 0, NULL, NULL);
return SCPE_OK;
@ -1319,25 +1321,25 @@ static void setClockCPM3(void) {
static int32 simh_in(const int32 port) {
int32 result = 0;
switch(lastCommand) {
case readURLCmd:
case readURLCmd:
if (isInReadPhase) {
if (showAvailability) {
if (resultPointer < resultLength)
result = 1;
else {
if (urlResult != NULL)
free(urlResult);
urlResult = NULL;
lastCommand = 0;
}
}
else if (resultPointer < resultLength)
result = urlResult[resultPointer++];
showAvailability = 1 - showAvailability;
if (showAvailability) {
if (resultPointer < resultLength)
result = 1;
else {
if (urlResult != NULL)
free(urlResult);
urlResult = NULL;
lastCommand = 0;
}
}
else if (resultPointer < resultLength)
result = urlResult[resultPointer++];
showAvailability = 1 - showAvailability;
}
else
lastCommand = 0;
break;
break;
case getHostFilenamesCmd:
#if UNIX_PLATFORM
@ -1479,7 +1481,7 @@ static int32 simh_in(const int32 port) {
}
break;
case getCPUClockFrequency:
case getCPUClockFrequency:
if (getClockFrequencyPos == 0) {
result = getClockFrequency() & 0xff;
getClockFrequencyPos = 1;
@ -1542,7 +1544,7 @@ void do_SIMH_sleep(void) {
static int32 simh_out(const int32 port, const int32 data) {
time_t now;
switch(lastCommand) {
case readURLCmd:
case readURLCmd:
if (isInReadPhase)
lastCommand = 0;
else {
@ -1559,8 +1561,8 @@ static int32 simh_out(const int32 port, const int32 data) {
showAvailability = 1;
isInReadPhase = TRUE;
}
}
break;
}
break;
case setClockZSDOSCmd:
if (setClockZSDOSPos == 0) {
@ -1586,16 +1588,16 @@ static int32 simh_out(const int32 port, const int32 data) {
}
break;
case setCPUClockFrequency:
if (setClockFrequencyPos == 0) {
newClockFrequency = data;
setClockFrequencyPos = 1;
}
else {
setClockFrequency((data << 8) | newClockFrequency);
case setCPUClockFrequency:
if (setClockFrequencyPos == 0) {
newClockFrequency = data;
setClockFrequencyPos = 1;
}
else {
setClockFrequency((data << 8) | newClockFrequency);
setClockFrequencyPos = lastCommand = 0;
}
break;
}
break;
case setBankSelectCmd:
if (cpu_unit.flags & UNIT_CPU_BANKED)
@ -1644,10 +1646,10 @@ static int32 simh_out(const int32 port, const int32 data) {
lastCommand = data;
switch(data) {
case readURLCmd:
urlPointer = 0;
case readURLCmd:
urlPointer = 0;
isInReadPhase = FALSE;
break;
break;
case getHostFilenamesCmd:
#if UNIX_PLATFORM
@ -1758,17 +1760,17 @@ static int32 simh_out(const int32 port, const int32 data) {
setClockCPM3Pos = 0;
break;
case getCommonCmd:
getCommonPos = 0;
break;
case getCommonCmd:
getCommonPos = 0;
break;
case getCPUClockFrequency:
getClockFrequencyPos = 0;
break;
case getCPUClockFrequency:
getClockFrequencyPos = 0;
break;
case setCPUClockFrequency:
setClockFrequencyPos = 0;
break;
case setCPUClockFrequency:
setClockFrequencyPos = 0;
break;
case getBankSelectCmd:
case setBankSelectCmd:

View file

@ -1,6 +1,6 @@
/* altairz80_sys.c: MITS Altair system interface
Copyright (c) 2002-2011, Peter Schorn
Copyright (c) 2002-2013, Peter Schorn
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@ -138,13 +138,13 @@ const char *sim_stop_messages[] = {
static char *const Mnemonics8080[] = {
/* 0/8 1/9 2/A 3/B 4/C 5/D 6/E 7/F */
"NOP", "LXI B,#h", "STAX B", "INX B", "INR B", "DCR B", "MVI B,*h", "RLC", /* 00-07 */
"DB 09h", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */
"DB 10h", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */
"DB 18h", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */
"DB 20h", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */
"DB 28h", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */
"DB 30h", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */
"DB 38h", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */
"_NOP", "DAD B", "LDAX B", "DCX B", "INR C", "DCR C", "MVI C,*h", "RRC", /* 08-0f */
"_NOP", "LXI D,#h", "STAX D", "INX D", "INR D", "DCR D", "MVI D,*h", "RAL", /* 10-17 */
"_NOP", "DAD D", "LDAX D", "DCX D", "INR E", "DCR E", "MVI E,*h", "RAR", /* 18-1f */
"_NOP", "LXI H,#h", "SHLD #h", "INX H", "INR H", "DCR H", "MVI H,*h", "DAA", /* 20-27 */
"_NOP", "DAD H", "LHLD #h", "DCX H", "INR L", "DCR L", "MVI L,*h", "CMA", /* 28-2f */
"_NOP", "LXI SP,#h", "STA #h", "INX SP", "INR M", "DCR M", "MVI M,*h", "STC", /* 30-37 */
"_NOP", "DAD SP", "LDA #h", "DCX SP", "INR A", "DCR A", "MVI A,*h", "CMC", /* 38-3f */
"MOV B,B", "MOV B,C", "MOV B,D", "MOV B,E", "MOV B,H", "MOV B,L", "MOV B,M", "MOV B,A", /* 40-47 */
"MOV C,B", "MOV C,C", "MOV C,D", "MOV C,E", "MOV C,H", "MOV C,L", "MOV C,M", "MOV C,A", /* 48-4f */
"MOV D,B", "MOV D,C", "MOV D,D", "MOV D,E", "MOV D,H", "MOV D,L", "MOV D,M", "MOV D,A", /* 50-57 */
@ -162,13 +162,13 @@ static char *const Mnemonics8080[] = {
"ORA B", "ORA C", "ORA D", "ORA E", "ORA H", "ORA L", "ORA M", "ORA A", /* b0-b7 */
"CMP B", "CMP C", "CMP D", "CMP E", "CMP H", "CMP L", "CMP M", "CMP A", /* b8-bf */
"RNZ", "POP B", "JNZ #h", "JMP #h", "CNZ #h", "PUSH B", "ADI *h", "RST 0", /* c0-c7 */
"RZ", "RET", "JZ #h", "DB CBh", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */
"RZ", "RET", "JZ #h", "_JMP #h", "CZ #h", "CALL #h", "ACI *h", "RST 1", /* c8-cf */
"RNC", "POP D", "JNC #h", "OUT *h", "CNC #h", "PUSH D", "SUI *h", "RST 2", /* d0-d7 */
"RC", "DB D9h", "JC #h", "IN *h", "CC #h", "DB DDh", "SBI *h", "RST 3", /* d8-df */
"RC", "_RET", "JC #h", "IN *h", "CC #h", "_CALL #h", "SBI *h", "RST 3", /* d8-df */
"RPO", "POP H", "JPO #h", "XTHL", "CPO #h", "PUSH H", "ANI *h", "RST 4", /* e0-e7 */
"RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "DB EDh", "XRI *h", "RST 5", /* e8-ef */
"RPE", "PCHL", "JPE #h", "XCHG", "CPE #h", "_CALL #h", "XRI *h", "RST 5", /* e8-ef */
"RP", "POP PSW", "JP #h", "DI", "CP #h", "PUSH PSW", "ORI *h", "RST 6", /* f0-f7 */
"RM", "SPHL", "JM #h", "EI", "CM #h", "DB FDh", "CPI *h", "RST 7" /* f8-ff */
"RM", "SPHL", "JM #h", "EI", "CM #h", "_CALL #h", "CPI *h", "RST 7" /* f8-ff */
};
static char *const MnemonicsZ80[256] = {

View file

@ -2,7 +2,7 @@
IMSAI FIF Disk Controller by Ernie Price
Based on altairz80_dsk.c, Copyright (c) 2002-2011, Peter Schorn
Based on altairz80_dsk.c, Copyright (c) 2002-2013, Peter Schorn
Plug-n-Play added by Howard M. Harte

View file

@ -759,7 +759,7 @@ t_stat trackWrite(DISK_INFO *myDisk,
* sector record type as the first byte, and fill the sector
* data with the fillbyte.
*/
dataLen = (128 << sectorLen)+1;
dataLen = sectorLen + 1;
sectorData = malloc(dataLen);
memset(sectorData, fillbyte, dataLen);
sectorData[0] = SECT_RECORD_NORM;