1
0
mirror of https://github.com/simh/simh.git synced 2026-01-11 23:52:58 +00:00

AltairZ80: Improved choice of boot ROM

This commit is contained in:
Peter Schorn 2025-10-21 11:07:02 +02:00 committed by Mark Pizzolato
parent a9e4370b38
commit 589bb5610f
2 changed files with 60 additions and 35 deletions

View File

@ -52,6 +52,8 @@
#define LDA_INSTRUCTION 0x3e /* op-code for LD A,<8-bit value> instruction */
#define UNIT_NO_OFFSET_1 0x37 /* LD A,<unitno> */
#define UNIT_NO_OFFSET_2 0xb4 /* LD a,80h | <unitno> */
#define LDB_INSTRUCTION 0x06 /* op-code for LD B,<8-bit value> instruction */
#define START_SECTOR_OFFSET 0x57 /* LD B,<start_sector_offset> */
#define CPU_INDEX_8080 4 /* index of default PC register */

View File

@ -33,15 +33,14 @@
The controller is interfaced to the CPU by use of 3 I/O addresses,
standardly, these are device numbers 10, 11, and 12 (octal).
Address Mode Function
------- ---- --------
10 Out Selects and enables Controller and Drive
10 In Indicates status of Drive and Controller
11 Out Controls Disk Function
11 In Indicates current sector position of disk
12 Out Write data
12 In Read data
Address Mode Function
------- ---- --------
10 Out Selects and enables Controller and Drive
10 In Indicates status of Drive and Controller
11 Out Controls Disk Function
11 In Indicates current sector position of disk
12 Out Write data
12 In Read data
Drive Select Out (Device 10 OUT):
@ -141,21 +140,24 @@
#define TRACK_STUCK_MSG (1 << 5)
#define VERBOSE_MSG (1 << 6)
#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
#define DSK_SECTSIZE 137 /* size of sector */
#define DSK_SECT 32 /* sectors per track */
#define DSK_SECTSIZE 137 /* size of sector */
#define DSK_SECT 32 /* sectors per track */
#define MAX_TRACKS 2048 /* number of tracks,
original Altair has 77 tracks only */
original Altair has 77 tracks only */
#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT)
#define MAX_DSK_SIZE (DSK_TRACSIZE * MAX_TRACKS)
#define NUM_OF_DSK_MASK (NUM_OF_DSK - 1)
#define BOOTROM_SIZE_DSK 256 /* size of boot rom */
#define BOOTROM_SIZE_DSK 256 /* size of boot rom */
#define MINI_DISK_SECT 16 /* mini disk sectors per track */
#define MINI_DISK_TRACKS 35 /* number of tracks on mini disk */
#define MINI_DISK_SECT 16 /* mini disk sectors per track */
#define MINI_DISK_TRACKS 35 /* number of tracks on mini disk */
#define MINI_DISK_SIZE (MINI_DISK_TRACKS * MINI_DISK_SECT * DSK_SECTSIZE)
#define MINI_DISK_DELTA 4096 /* threshold for detecting mini disks */
#define MINI_DISK_DELTA 4096 /* threshold for detecting mini disks */
#define ALTAIR_DISK_SIZE 337664 /* size of regular Altair disks */
#define ALTAIR_DISK_DELTA 256 /* threshold for detecting regular Altair disks */
int32 dsk10(const int32 port, const int32 io, const int32 data);
int32 dsk11(const int32 port, const int32 io, const int32 data);
@ -187,6 +189,7 @@ static int32 sectors_per_track [NUM_OF_DSK] = { DSK_SECT, DSK_SECT, DSK_SECT, DS
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT,
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT,
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT };
static int32 current_imageSize [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int32 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
@ -310,6 +313,8 @@ static REG dsk_reg[] = {
"Number of tracks register array"), REG_CIRC },
{ BRDATAD (SECTPERTRACK, sectors_per_track, 10, 32, NUM_OF_DSK,
"Number of sectors per track register array"), REG_CIRC },
{ BRDATAD (IMAGESIZE, current_imageSize, 10, 32, NUM_OF_DSK,
"Size of disk image array"), REG_CIRC + REG_RO },
{ DRDATAD (IN9COUNT, in9_count, 4,
"Count of IN(9) register"), REG_RO },
{ DRDATAD (IN9MESSAGE, in9_message, 4,
@ -378,12 +383,12 @@ static const char* selectInOut(const int32 io) {
static t_stat dsk_reset(DEVICE *dptr) {
int32 i;
for (i = 0; i < NUM_OF_DSK; i++) {
warnLock[i] = 0;
warnAttached[i] = 0;
current_track[i] = 0;
current_sector[i] = 0;
current_byte[i] = 0;
current_flag[i] = 0;
warnLock[i] = 0;
warnAttached[i] = 0;
current_track[i] = 0;
current_sector[i] = 0;
current_byte[i] = 0;
current_flag[i] = 0;
}
warnDSK10 = 0;
warnDSK11 = 0;
@ -413,6 +418,7 @@ static t_stat dsk_attach(UNIT *uptr, CONST char *cptr) {
tracks to 16, otherwise, 32 sectors per track. */
imageSize = sim_fsize(uptr -> fileref);
current_imageSize[thisUnitIndex] = imageSize;
sectors_per_track[thisUnitIndex] = (((MINI_DISK_SIZE - MINI_DISK_DELTA < imageSize) &&
(imageSize < MINI_DISK_SIZE + MINI_DISK_DELTA)) ?
MINI_DISK_SECT : DSK_SECT);
@ -426,7 +432,13 @@ void install_ALTAIRbootROM(void) {
}
/* The boot routine modifies the boot ROM in such a way that subsequently
the specified disk is used for boot purposes.
the specified disk is used for boot purposes. Furthermore, it determines based on the
size of the attached disk image which boot ROM should be used. The logic is:
- If the size is close to MINI_DISK_SIZE, the ROM for mini disk support is used
- If the size is close to ALTAIR_DISK_SIZE, the standard ROM is modified to start
loading at track 0, sector 0
- Otherwise the standard ROM is is modified to start loading at track 0, sector 8
See DSKBOOT.MAC on the cpm2.dsk for the source code of the boot ROM.
*/
static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
if (cpu_unit.flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED)) {
@ -434,18 +446,29 @@ static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
const t_bool result = (install_bootrom(alt_bootrom_dsk, BOOTROM_SIZE_DSK,
ALTAIR_ROM_LOW, TRUE) == SCPE_OK);
ASSURE(result);
} else {
/* check whether we are really modifying an LD A,<> instruction */
} else { /* patch standard ROM with correct unit number and first track */
/* check whether we are really modifying an LD B,<> instruction */
if (bootrom_dsk[START_SECTOR_OFFSET - 1] == LDB_INSTRUCTION)
bootrom_dsk[START_SECTOR_OFFSET] =
(ALTAIR_DISK_SIZE - ALTAIR_DISK_DELTA < current_imageSize[unitno]) &&
(current_imageSize[unitno] < ALTAIR_DISK_SIZE + ALTAIR_DISK_DELTA) ? 0 : 8;
else { /* Attempt to modify non LD B,<> instructions is refused. */
sim_printf("Incorrect boot ROM first sector offset detected.\n");
return SCPE_IERR;
}
/* check whether we are really modifying an LD A,<> instruction */
if ((bootrom_dsk[UNIT_NO_OFFSET_1 - 1] == LDA_INSTRUCTION) &&
(bootrom_dsk[UNIT_NO_OFFSET_2 - 1] == LDA_INSTRUCTION)) {
bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */
bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */
} else { /* Attempt to modify non LD A,<> instructions is refused. */
sim_printf("Incorrect boot ROM offsets detected.\n");
return SCPE_IERR;
bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */
bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */
} else { /* Attempt to modify non LD A,<> instructions is refused. */
sim_printf("Incorrect boot ROM unit number offset detected.\n");
return SCPE_IERR;
}
install_ALTAIRbootROM(); /* install modified ROM */
}
install_ALTAIRbootROM(); /* install modified ROM */
}
}
*((int32 *) sim_PC->loc) = ALTAIR_ROM_LOW;
return SCPE_OK;
@ -546,7 +569,7 @@ int32 dsk10(const int32 port, const int32 io, const int32 data) {
}
current_disk = NUM_OF_DSK;
} else {
current_sector[current_disk] = 0xff; /* reset internal counters */
current_sector[current_disk] = 0xff; /* reset internal counters */
current_byte[current_disk] = 0xff;
if (data & 0x80) /* disable drive? */
current_flag[current_disk] = 0; /* yes, clear all flags */
@ -572,7 +595,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
" Attempt of %s 0x09 on unattached disk - ignored.\n",
current_disk, PCX, selectInOut(io));
}
return 0xff; /* no drive selected - can do nothing */
return 0xff; /* no drive selected - can do nothing */
}
/* now current_disk < NUM_OF_DSK */