diff --git a/AltairZ80/altairz80_doc.pdf b/AltairZ80/altairz80_doc.pdf
index 3497e9b3..0c824e71 100644
Binary files a/AltairZ80/altairz80_doc.pdf and b/AltairZ80/altairz80_doc.pdf differ
diff --git a/AltairZ80/altairz80_hdsk.c b/AltairZ80/altairz80_hdsk.c
index 1d67939e..7fa0d749 100644
--- a/AltairZ80/altairz80_hdsk.c
+++ b/AltairZ80/altairz80_hdsk.c
@@ -595,6 +595,7 @@ static int32 bootrom_hdsk[BOOTROM_SIZE_HDSK] = {
};
static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
+ t_bool installSuccessful;
if (MEMORYSIZE < 24*KB) {
printf("Need at least 24KB RAM to boot from hard disk.\n");
return SCPE_ARG;
@@ -609,9 +610,9 @@ static t_stat hdsk_boot(int32 unitno, DEVICE *dptr) {
}
install_ALTAIRbootROM(); /* install modified ROM */
}
- const t_bool result = (install_bootrom(bootrom_hdsk, BOOTROM_SIZE_HDSK, HDSK_BOOT_ADDRESS,
- FALSE) == SCPE_OK);
- assert(result);
+ installSuccessful = (install_bootrom(bootrom_hdsk, BOOTROM_SIZE_HDSK, HDSK_BOOT_ADDRESS,
+ FALSE) == SCPE_OK);
+ assert(installSuccessful);
*((int32 *) sim_PC -> loc) = HDSK_BOOT_ADDRESS;
return SCPE_OK;
}
diff --git a/AltairZ80/altairz80_mhdsk.c b/AltairZ80/altairz80_mhdsk.c
index c4f33321..68eb3de6 100755
--- a/AltairZ80/altairz80_mhdsk.c
+++ b/AltairZ80/altairz80_mhdsk.c
@@ -25,92 +25,92 @@
------------------------------------------------------------------------------
- The 88-HDSK from MITS/Pertec consists of a 5mb removable platter and
- a fixed 5mb platter. Each platter is double sided. Head 0 and 1 are the
- top and bottom surface of the removable platter and head 2 and 3 are the
- top and bottom surface of the fixed platter. Hard disk BASIC treats the
- two platters as two separate drives. Each platter has 406 cylinders
- with 24 sectors per track and 256 bytes per sector.
+ The 88-HDSK from MITS/Pertec consists of a 5mb removable platter and
+ a fixed 5mb platter. Each platter is double sided. Head 0 and 1 are the
+ top and bottom surface of the removable platter and head 2 and 3 are the
+ top and bottom surface of the fixed platter. Hard disk BASIC treats the
+ two platters as two separate drives. Each platter has 406 cylinders
+ with 24 sectors per track and 256 bytes per sector.
- The disk image file starts with head 0, track 0, sector 0 (0,0,0) through
- (0,0,23), followed by head 1, track 0, sector 0 (1,0,0) through (1,0,23).
- The pattern then repeats starting with (0,1,0).
+ The disk image file starts with head 0, track 0, sector 0 (0,0,0) through
+ (0,0,23), followed by head 1, track 0, sector 0 (1,0,0) through (1,0,23).
+ The pattern then repeats starting with (0,1,0).
- The external hard disk is accessed through eight ports of a 4-PIO card
- at I/O addresses A0h-A7h.
+ The external hard disk is accessed through eight ports of a 4-PIO card
+ at I/O addresses A0h-A7h.
- Written by Mike Douglas March, 2014
- Disk images provided by Martin Eberhard
+ Written by Mike Douglas March, 2014
+ Disk images provided by Martin Eberhard
-------------------------------------------------------------------------------
*/
#include "altairz80_defs.h"
/** Typedefs & Defines **************************************/
-#define HDSK_SECTOR_SIZE 256 /* size of sector */
-#define HDSK_SECTORS_PER_TRACK 24 /* sectors per track */
-#define HDSK_NUM_HEADS 2 /* heads per disk */
-#define HDSK_NUM_TRACKS 406 /* tracks per surface */
-#define HDSK_TRACK_SIZE (HDSK_SECTOR_SIZE * HDSK_SECTORS_PER_TRACK)
-#define HDSK_CYLINDER_SIZE (HDSK_TRACK_SIZE * 2)
-#define HDSK_CAPACITY (HDSK_CYLINDER_SIZE * HDSK_NUM_TRACKS)
-#define HDSK_NUMBER 8 /* number of hard disks */
-#define IO_IN 0 /* I/O operation is input */
-#define IO_OUT 1 /* I/O operation is output */
-#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
-#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
+#define HDSK_SECTOR_SIZE 256 /* size of sector */
+#define HDSK_SECTORS_PER_TRACK 24 /* sectors per track */
+#define HDSK_NUM_HEADS 2 /* heads per disk */
+#define HDSK_NUM_TRACKS 406 /* tracks per surface */
+#define HDSK_TRACK_SIZE (HDSK_SECTOR_SIZE * HDSK_SECTORS_PER_TRACK)
+#define HDSK_CYLINDER_SIZE (HDSK_TRACK_SIZE * 2)
+#define HDSK_CAPACITY (HDSK_CYLINDER_SIZE * HDSK_NUM_TRACKS)
+#define HDSK_NUMBER 8 /* number of hard disks */
+#define IO_IN 0 /* I/O operation is input */
+#define IO_OUT 1 /* I/O operation is output */
+#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
+#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
// Disk controller commands are in upper nibble of command high byte.
-#define CMD_SHIFT 4 // shift right 4 places
-#define CMD_MASK 0x0f // mask after shifting
-#define CMD_SEEK 0 // seek to track
-#define CMD_WRITE_SEC 2 // write sector from buf n
-#define CMD_READ_SEC 3 // read sector into buf n
-#define CMD_WRITE_BUF 4 // load buffer n from CPU
-#define CMD_READ_BUF 5 // read buffer n into CPU
-#define CMD_READ_STATUS 6 // read controller IV byte
-#define CMD_SET_IV_BYTE 8 // set controller IV byte
-#define CMD_READ_UNFMT 10 // read unformatted sector
-#define CMD_FORMAT 12
-#define CMD_INITIALIZE 14
+#define CMD_SHIFT 4 // shift right 4 places
+#define CMD_MASK 0x0f // mask after shifting
+#define CMD_SEEK 0 // seek to track
+#define CMD_WRITE_SEC 2 // write sector from buf n
+#define CMD_READ_SEC 3 // read sector into buf n
+#define CMD_WRITE_BUF 4 // load buffer n from CPU
+#define CMD_READ_BUF 5 // read buffer n into CPU
+#define CMD_READ_STATUS 6 // read controller IV byte
+#define CMD_SET_IV_BYTE 8 // set controller IV byte
+#define CMD_READ_UNFMT 10 // read unformatted sector
+#define CMD_FORMAT 12
+#define CMD_INITIALIZE 14
// Other disk controller bit fields
-#define UNIT_SHIFT 2 // shift right 2 places
-#define UNIT_MASK 0x03 // mask after shifting
+#define UNIT_SHIFT 2 // shift right 2 places
+#define UNIT_MASK 0x03 // mask after shifting
-#define BUFFER_MASK 0x03 // mask - no shift needed
+#define BUFFER_MASK 0x03 // mask - no shift needed
-#define TRACK_SHIFTH 8 // shift left 8 places into MSbyte
-#define TRACK_MASKH 0x01 // msb of track number
-#define TRACK_MASKL 0xff // entire lsb of track number
+#define TRACK_SHIFTH 8 // shift left 8 places into MSbyte
+#define TRACK_MASKH 0x01 // msb of track number
+#define TRACK_MASKL 0xff // entire lsb of track number
-#define HEAD_SHIFT 5 // shift right 5 places
-#define HEAD_MASK 0x03 // mask after shifting (no heads 4-7)
+#define HEAD_SHIFT 5 // shift right 5 places
+#define HEAD_MASK 0x03 // mask after shifting (no heads 4-7)
-#define SECTOR_MASK 0x1f // mask - no shift needed
+#define SECTOR_MASK 0x1f // mask - no shift needed
// Command status equates
-#define CSTAT_WRITE_PROTECT 0x80 // disk is write protected
-#define CSTAT_NOT_READY 0x01 // drive not ready
-#define CSTAT_BAD_SECTOR 0x02 // invalid sector number
+#define CSTAT_WRITE_PROTECT 0x80 // disk is write protected
+#define CSTAT_NOT_READY 0x01 // drive not ready
+#define CSTAT_BAD_SECTOR 0x02 // invalid sector number
/** Module Globals - Private ********************************/
-static uint32 selectedDisk = 0; // current active disk
-static uint32 selectedSector = 0; // current sector
-static uint32 selectedTrack = 0; // current track
-static uint32 selectedHead = 0; // current head
-static uint32 selectedBuffer = 0; // current buffer # in use
-static uint32 bufferIdx = 0; // current index into selected buffer
-static uint32 maxBufferIdx = 256; // maximum buffer index allowed
-static uint32 cmdLowByte = 0; // low byte of command
+static uint32 selectedDisk = 0; // current active disk
+static uint32 selectedSector = 0; // current sector
+static uint32 selectedTrack = 0; // current track
+static uint32 selectedHead = 0; // current head
+static uint32 selectedBuffer = 0; // current buffer # in use
+static uint32 bufferIdx = 0; // current index into selected buffer
+static uint32 maxBufferIdx = 256; // maximum buffer index allowed
+static uint32 cmdLowByte = 0; // low byte of command
// Controller status bytes
-static uint8 cstat = 0; // command status from controller
+static uint8 cstat = 0; // command status from controller
// The hard disk controller support four 256 byte disk buffers */
@@ -168,166 +168,166 @@ DEVICE mhdsk_dev = {
----------------------------------------------------------------------------------*/
static t_stat dsk_reset(DEVICE *dptr) {
- sim_map_resource(0xA0, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
- sim_map_resource(0xA1, 1, RESOURCE_TYPE_IO, &hdCstat, dptr->flags & DEV_DIS);
- sim_map_resource(0xA2, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
- sim_map_resource(0xA3, 1, RESOURCE_TYPE_IO, &hdAcmd, dptr->flags & DEV_DIS);
- sim_map_resource(0xA4, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
- sim_map_resource(0xA5, 1, RESOURCE_TYPE_IO, &hdCdata, dptr->flags & DEV_DIS);
- sim_map_resource(0xA6, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
- sim_map_resource(0xA7, 1, RESOURCE_TYPE_IO, &hdAdata, dptr->flags & DEV_DIS);
+ sim_map_resource(0xA0, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
+ sim_map_resource(0xA1, 1, RESOURCE_TYPE_IO, &hdCstat, dptr->flags & DEV_DIS);
+ sim_map_resource(0xA2, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
+ sim_map_resource(0xA3, 1, RESOURCE_TYPE_IO, &hdAcmd, dptr->flags & DEV_DIS);
+ sim_map_resource(0xA4, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
+ sim_map_resource(0xA5, 1, RESOURCE_TYPE_IO, &hdCdata, dptr->flags & DEV_DIS);
+ sim_map_resource(0xA6, 1, RESOURCE_TYPE_IO, &hdReturnReady, dptr->flags & DEV_DIS);
+ sim_map_resource(0xA7, 1, RESOURCE_TYPE_IO, &hdAdata, dptr->flags & DEV_DIS);
- selectedSector = 0; // current sector
- selectedTrack = 0; // current track
- selectedHead = 0; // current head
- selectedBuffer = 0; // current buffer # in use
- bufferIdx = 0; // current index into selected buffer
- maxBufferIdx = 256; // maximum buffer index allowed
- cmdLowByte = 0; // low byte of command
+ selectedSector = 0; // current sector
+ selectedTrack = 0; // current track
+ selectedHead = 0; // current head
+ selectedBuffer = 0; // current buffer # in use
+ bufferIdx = 0; // current index into selected buffer
+ maxBufferIdx = 256; // maximum buffer index allowed
+ cmdLowByte = 0; // low byte of command
- return SCPE_OK;
+ return SCPE_OK;
}
/*-------------------------------------------------------------------------------------
hdReturnReady - common I/O handler for several hard disk status ports which set
- bit 7 when the corresponding hard disk function is ready. In the emulator,
- we're always ready for the next step, so we simply return ready all the time.
+ bit 7 when the corresponding hard disk function is ready. In the emulator,
+ we're always ready for the next step, so we simply return ready all the time.
- 0xA0 - CREADY register. Accessed through the status/control register of 4-PIO
- port 1-A. Returns the "ready for command" status byte.
+ 0xA0 - CREADY register. Accessed through the status/control register of 4-PIO
+ port 1-A. Returns the "ready for command" status byte.
- 0xA2 - ACSTA register. Accessed through the status/control register of 4-PIO
- port 1-B. Returns the "command received" status byte.
-
- 0xA4 - CDSTA register. Accessed through the status/control register of 4-PIO
- port 2-A. Returns the "command data available" status byte.
+ 0xA2 - ACSTA register. Accessed through the status/control register of 4-PIO
+ port 1-B. Returns the "command received" status byte.
+
+ 0xA4 - CDSTA register. Accessed through the status/control register of 4-PIO
+ port 2-A. Returns the "command data available" status byte.
- 0xA6 - ADSTA register. Accessed through the status/control register of 4-PIO
- port 2-B. Returns the "available to write" status byte.
-
+ 0xA6 - ADSTA register. Accessed through the status/control register of 4-PIO
+ port 2-B. Returns the "available to write" status byte.
+
---------------------------------------------------------------------------------------*/
static int32 hdReturnReady(const int32 port, const int32 io, const int32 data)
{
- return(0x80); // always indicate ready
+ return(0x80); // always indicate ready
// output operations have no effect
}
/*------------------------------------------------------------
hdCstat (0xA1) CSTAT register. Accessed through the
- data register of 4-PIO port 1-A.
+ data register of 4-PIO port 1-A.
- Comments: Returns error code byte of the most recent
- operation. Reading this byte also clears
- the CRDY bit, but this isn't actually done
- in the emulation since we're always ready.
+ Comments: Returns error code byte of the most recent
+ operation. Reading this byte also clears
+ the CRDY bit, but this isn't actually done
+ in the emulation since we're always ready.
-------------------------------------------------------------*/
static int32 hdCstat(const int32 port, const int32 io, const int32 data)
{
- return(cstat);
+ return(cstat);
// output operations have no effect
}
/*------------------------------------------------------------
hdAcmd (0xA3) ACMD register. Accessed through the
- data register of 4-PIO port 1-B.
+ data register of 4-PIO port 1-B.
- Comments: The high byte of a command is written to
- this register and initiates the command.
- The low byte of a command is assumed to
- have already been written and stored in
- cmdLowByte;
+ Comments: The high byte of a command is written to
+ this register and initiates the command.
+ The low byte of a command is assumed to
+ have already been written and stored in
+ cmdLowByte;
-------------------------------------------------------------*/
static int32 hdAcmd(const int32 port, const int32 io, const int32 data)
{
- uint32 command; // command field from command msb
- uint32 unit; // unit number from command msb
- uint32 buffer; // buffer number from command msb
+ uint32 command; // command field from command msb
+ uint32 unit; // unit number from command msb
+ uint32 buffer; // buffer number from command msb
// if not an OUT command, exit
- if (io != IO_OUT)
- return(0);
+ if (io != IO_OUT)
+ return(0);
// extract command and possible unit and buffer fields.
- cstat = 0; // assume command success
- command = (data >> CMD_SHIFT) & CMD_MASK;
- unit = (data >> UNIT_SHIFT) & UNIT_MASK;
- buffer = data & BUFFER_MASK;
+ cstat = 0; // assume command success
+ command = (data >> CMD_SHIFT) & CMD_MASK;
+ unit = (data >> UNIT_SHIFT) & UNIT_MASK;
+ buffer = data & BUFFER_MASK;
// SEEK command. Updated selectedTrack.
- if (command == CMD_SEEK) {
- selectedTrack = cmdLowByte + ((data & TRACK_MASKH) << TRACK_SHIFTH);
- if (selectedTrack >= HDSK_NUM_TRACKS)
- selectedTrack = HDSK_NUM_TRACKS-1;
- }
+ if (command == CMD_SEEK) {
+ selectedTrack = cmdLowByte + ((data & TRACK_MASKH) << TRACK_SHIFTH);
+ if (selectedTrack >= HDSK_NUM_TRACKS)
+ selectedTrack = HDSK_NUM_TRACKS-1;
+ }
// READ, READ UNFORMATTED or WRITE SECTOR command.
- else if ((command==CMD_WRITE_SEC) || (command==CMD_READ_SEC) || (command==CMD_READ_UNFMT)) {
- selectedHead = (cmdLowByte >> HEAD_SHIFT) & HEAD_MASK;
- selectedDisk = (selectedHead >> 1) + unit * 2 ;
- selectedSector = cmdLowByte & SECTOR_MASK;
- selectedBuffer = buffer;
- if (mhdsk_dev.units[selectedDisk].fileref == NULL) // make sure a file is attached
- cstat = CSTAT_NOT_READY;
- else {
- if (command == CMD_WRITE_SEC)
- doWrite();
- else
- doRead();
- }
- }
+ else if ((command==CMD_WRITE_SEC) || (command==CMD_READ_SEC) || (command==CMD_READ_UNFMT)) {
+ selectedHead = (cmdLowByte >> HEAD_SHIFT) & HEAD_MASK;
+ selectedDisk = (selectedHead >> 1) + unit * 2 ;
+ selectedSector = cmdLowByte & SECTOR_MASK;
+ selectedBuffer = buffer;
+ if (mhdsk_dev.units[selectedDisk].fileref == NULL) // make sure a file is attached
+ cstat = CSTAT_NOT_READY;
+ else {
+ if (command == CMD_WRITE_SEC)
+ doWrite();
+ else
+ doRead();
+ }
+ }
// READ or WRITE BUFFER command. Initiates reading/loading specified buffer.
- else if ((command == CMD_WRITE_BUF) || (command == CMD_READ_BUF)) {
- selectedBuffer = buffer;
- maxBufferIdx = cmdLowByte;
- if (maxBufferIdx == 0)
- maxBufferIdx = 256;
- bufferIdx = 0;
- }
+ else if ((command == CMD_WRITE_BUF) || (command == CMD_READ_BUF)) {
+ selectedBuffer = buffer;
+ maxBufferIdx = cmdLowByte;
+ if (maxBufferIdx == 0)
+ maxBufferIdx = 256;
+ bufferIdx = 0;
+ }
// READ STATUS command (read IV byte)
- else if (command == CMD_READ_STATUS) {
- }
+ else if (command == CMD_READ_STATUS) {
+ }
// SET IV byte command
- else if (command == CMD_SET_IV_BYTE) {
- }
+ else if (command == CMD_SET_IV_BYTE) {
+ }
// FORMAT command
- else if (command == CMD_FORMAT) {
- }
+ else if (command == CMD_FORMAT) {
+ }
// INITIALIZE command
- else if (command == CMD_INITIALIZE) {
- }
+ else if (command == CMD_INITIALIZE) {
+ }
- return(0);
+ return(0);
}
/*------------------------------------------------------------
hdCdata (0xA5) Cdata register. Accessed through the
- data register of 4-PIO port 1-B.
-
- Comments: Returns data from the read buffer
+ data register of 4-PIO port 1-B.
+
+ Comments: Returns data from the read buffer
-------------------------------------------------------------*/
static int32 hdCdata(const int32 port, const int32 io, const int32 data)
{
- if (io == IO_IN) {
- if (bufferIdx < maxBufferIdx)
- return(diskBuf[selectedBuffer][bufferIdx++]);
- }
- return(0);
+ if (io == IO_IN) {
+ if (bufferIdx < maxBufferIdx)
+ return(diskBuf[selectedBuffer][bufferIdx++]);
+ }
+ return(0);
// output operations have no effect
}
@@ -335,70 +335,70 @@ static int32 hdCdata(const int32 port, const int32 io, const int32 data)
/*------------------------------------------------------------
hdAdata (0xA7) ADATA register. Accessed through the
- data register of 4-PIO port 2-B.
-
- Comments: Accepts data into the current buffer
- and is also the low byte of a command.
+ data register of 4-PIO port 2-B.
+
+ Comments: Accepts data into the current buffer
+ and is also the low byte of a command.
-------------------------------------------------------------*/
static int32 hdAdata(const int32 port, const int32 io, const int32 data)
{
- if (io == IO_OUT) {
- cmdLowByte = data & 0xff;
- if (bufferIdx < maxBufferIdx)
- diskBuf[selectedBuffer][bufferIdx++] = data;
- }
- return(0);
+ if (io == IO_OUT) {
+ cmdLowByte = data & 0xff;
+ if (bufferIdx < maxBufferIdx)
+ diskBuf[selectedBuffer][bufferIdx++] = data;
+ }
+ return(0);
}
/*-- doRead -------------------------------------------------
- Performs read from MITS Hard Disk image file
-
- Params: nothing
- Uses: selectedTrack, selectedHead, selectedSector
- selectedDisk, diskBuf[], mhdsk_dev
- Returns: nothing (updates cstat directly)
- Comments:
+ Performs read from MITS Hard Disk image file
+
+ Params: nothing
+ Uses: selectedTrack, selectedHead, selectedSector
+ selectedDisk, diskBuf[], mhdsk_dev
+ Returns: nothing (updates cstat directly)
+ Comments:
-------------------------------------------------------------*/
static void doRead(void)
{
- UNIT *uptr;
- uint32 fileOffset;
-
- uptr = mhdsk_dev.units + selectedDisk;
- fileOffset = HDSK_CYLINDER_SIZE * selectedTrack +
- HDSK_TRACK_SIZE * (selectedHead & 0x01) +
- HDSK_SECTOR_SIZE * selectedSector;
- if (sim_fseek(uptr->fileref, fileOffset, SEEK_SET))
- cstat = CSTAT_NOT_READY; /* seek error */
- else if (sim_fread(diskBuf[selectedBuffer], 1, HDSK_SECTOR_SIZE, uptr->fileref) != HDSK_SECTOR_SIZE)
- cstat = CSTAT_NOT_READY; /* write error */
+ UNIT *uptr;
+ uint32 fileOffset;
+
+ uptr = mhdsk_dev.units + selectedDisk;
+ fileOffset = HDSK_CYLINDER_SIZE * selectedTrack +
+ HDSK_TRACK_SIZE * (selectedHead & 0x01) +
+ HDSK_SECTOR_SIZE * selectedSector;
+ if (sim_fseek(uptr->fileref, fileOffset, SEEK_SET))
+ cstat = CSTAT_NOT_READY; /* seek error */
+ else if (sim_fread(diskBuf[selectedBuffer], 1, HDSK_SECTOR_SIZE, uptr->fileref) != HDSK_SECTOR_SIZE)
+ cstat = CSTAT_NOT_READY; /* write error */
}
/*-- doWrite ------------------------------------------------
- Performs write to MITS Hard Disk image file
-
- Params: none
- Uses: selectedTrack, selectedHead, selectedSector
- selectedDisk, diskBuf[], mhdsk_dev
- Returns: nothing (updates cstat directly)
- Comments:
+ Performs write to MITS Hard Disk image file
+
+ Params: none
+ Uses: selectedTrack, selectedHead, selectedSector
+ selectedDisk, diskBuf[], mhdsk_dev
+ Returns: nothing (updates cstat directly)
+ Comments:
-------------------------------------------------------------*/
static void doWrite(void)
{
- UNIT *uptr;
- uint32 fileOffset;
-
- uptr = mhdsk_dev.units + selectedDisk;
- if (((uptr->flags) & UNIT_DSK_WLK) == 0) { /* write enabled */
- fileOffset = HDSK_CYLINDER_SIZE * selectedTrack +
- HDSK_TRACK_SIZE * (selectedHead & 0x01) +
- HDSK_SECTOR_SIZE * selectedSector;
- if (sim_fseek(uptr->fileref, fileOffset, SEEK_SET))
- cstat = CSTAT_NOT_READY; /* seek error */
- else if (sim_fwrite(diskBuf[selectedBuffer], 1, HDSK_SECTOR_SIZE, uptr->fileref) != HDSK_SECTOR_SIZE)
- cstat = CSTAT_NOT_READY; /* write error */
+ UNIT *uptr;
+ uint32 fileOffset;
+
+ uptr = mhdsk_dev.units + selectedDisk;
+ if (((uptr->flags) & UNIT_DSK_WLK) == 0) { /* write enabled */
+ fileOffset = HDSK_CYLINDER_SIZE * selectedTrack +
+ HDSK_TRACK_SIZE * (selectedHead & 0x01) +
+ HDSK_SECTOR_SIZE * selectedSector;
+ if (sim_fseek(uptr->fileref, fileOffset, SEEK_SET))
+ cstat = CSTAT_NOT_READY; /* seek error */
+ else if (sim_fwrite(diskBuf[selectedBuffer], 1, HDSK_SECTOR_SIZE, uptr->fileref) != HDSK_SECTOR_SIZE)
+ cstat = CSTAT_NOT_READY; /* write error */
}
else
- cstat = CSTAT_WRITE_PROTECT;
-}
\ No newline at end of file
+ cstat = CSTAT_WRITE_PROTECT;
+}
diff --git a/Visual Studio Projects/AltairZ80.vcproj b/Visual Studio Projects/AltairZ80.vcproj
index f7ebeecc..a37e5099 100644
--- a/Visual Studio Projects/AltairZ80.vcproj
+++ b/Visual Studio Projects/AltairZ80.vcproj
@@ -197,6 +197,10 @@
RelativePath="..\AltairZ80\altairz80_hdsk.c"
>
+
+
diff --git a/descrip.mms b/descrip.mms
index 73c5ebed..6abd1298 100644
--- a/descrip.mms
+++ b/descrip.mms
@@ -330,7 +330,7 @@ ALTAIRZ80_SOURCE2 = $(ALTAIRZ80_DIR)S100_DISK1A.C,$(ALTAIRZ80_DIR)S100_DISK2.C,\
$(ALTAIRZ80_DIR)S100_SCP300F.C,$(ALTAIRZ80_DIR)SIM_IMD.C,\
$(ALTAIRZ80_DIR)WD179X.C,$(ALTAIRZ80_DIR)S100_DISK3.C,\
$(ALTAIRZ80_DIR)S100_ADCS6.C,$(ALTAIRZ80_DIR)S100_HDC1001.C,\
- $(ALTAIRZ80_DIR)S100_IF3.C
+ $(ALTAIRZ80_DIR)S100_IF3.C,$(ALTAIRZ80_DIR)ALTAIRZ80_MHDSK.C
ALTAIRZ80_OPTIONS = /INCL=($(SIMH_DIR),$(ALTAIRZ80_DIR))/DEF=($(CC_DEFS))
#
diff --git a/makefile b/makefile
index f8afd828..25903b28 100644
--- a/makefile
+++ b/makefile
@@ -1011,9 +1011,9 @@ ALTAIRZ80 = ${ALTAIRZ80D}/altairz80_cpu.c ${ALTAIRZ80D}/altairz80_cpu_nommu.c \
${ALTAIRZ80D}/altairz80_hdsk.c ${ALTAIRZ80D}/altairz80_net.c \
${ALTAIRZ80D}/flashwriter2.c ${ALTAIRZ80D}/i86_decode.c \
${ALTAIRZ80D}/i86_ops.c ${ALTAIRZ80D}/i86_prim_ops.c \
- ${ALTAIRZ80D}/i8272.c ${ALTAIRZ80D}/insnsd.c \
+ ${ALTAIRZ80D}/i8272.c ${ALTAIRZ80D}/insnsd.c ${ALTAIRZ80D}/altairz80_mhdsk.c \
${ALTAIRZ80D}/mfdc.c ${ALTAIRZ80D}/n8vem.c ${ALTAIRZ80D}/vfdhd.c \
- ${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c ${ALTAIRZ80D}/s100_disk3.c\
+ ${ALTAIRZ80D}/s100_disk1a.c ${ALTAIRZ80D}/s100_disk2.c ${ALTAIRZ80D}/s100_disk3.c \
${ALTAIRZ80D}/s100_fif.c ${ALTAIRZ80D}/s100_mdriveh.c \
${ALTAIRZ80D}/s100_mdsad.c ${ALTAIRZ80D}/s100_selchan.c \
${ALTAIRZ80D}/s100_ss1.c ${ALTAIRZ80D}/s100_64fdc.c \