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 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_1 0x37 /* LD A,<unitno> */
#define UNIT_NO_OFFSET_2 0xb4 /* LD a,80h | <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 */ #define CPU_INDEX_8080 4 /* index of default PC register */

View File

@ -35,7 +35,6 @@
Address Mode Function Address Mode Function
------- ---- -------- ------- ---- --------
10 Out Selects and enables Controller and Drive 10 Out Selects and enables Controller and Drive
10 In Indicates status of Drive and Controller 10 In Indicates status of Drive and Controller
11 Out Controls Disk Function 11 Out Controls Disk Function
@ -157,6 +156,9 @@
#define MINI_DISK_SIZE (MINI_DISK_TRACKS * MINI_DISK_SECT * DSK_SECTSIZE) #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 dsk10(const int32 port, const int32 io, const int32 data);
int32 dsk11(const int32 port, const int32 io, const int32 data); int32 dsk11(const int32 port, const int32 io, const int32 data);
int32 dsk12(const int32 port, const int32 io, const int32 data); int32 dsk12(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, 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, 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,
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 }, "Number of tracks register array"), REG_CIRC },
{ BRDATAD (SECTPERTRACK, sectors_per_track, 10, 32, NUM_OF_DSK, { BRDATAD (SECTPERTRACK, sectors_per_track, 10, 32, NUM_OF_DSK,
"Number of sectors per track register array"), REG_CIRC }, "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, { DRDATAD (IN9COUNT, in9_count, 4,
"Count of IN(9) register"), REG_RO }, "Count of IN(9) register"), REG_RO },
{ DRDATAD (IN9MESSAGE, in9_message, 4, { DRDATAD (IN9MESSAGE, in9_message, 4,
@ -413,6 +418,7 @@ static t_stat dsk_attach(UNIT *uptr, CONST char *cptr) {
tracks to 16, otherwise, 32 sectors per track. */ tracks to 16, otherwise, 32 sectors per track. */
imageSize = sim_fsize(uptr -> fileref); imageSize = sim_fsize(uptr -> fileref);
current_imageSize[thisUnitIndex] = imageSize;
sectors_per_track[thisUnitIndex] = (((MINI_DISK_SIZE - MINI_DISK_DELTA < imageSize) && sectors_per_track[thisUnitIndex] = (((MINI_DISK_SIZE - MINI_DISK_DELTA < imageSize) &&
(imageSize < MINI_DISK_SIZE + MINI_DISK_DELTA)) ? (imageSize < MINI_DISK_SIZE + MINI_DISK_DELTA)) ?
MINI_DISK_SECT : DSK_SECT); 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 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) { static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
if (cpu_unit.flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED)) { if (cpu_unit.flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED)) {
@ -434,14 +446,25 @@ static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
const t_bool result = (install_bootrom(alt_bootrom_dsk, BOOTROM_SIZE_DSK, const t_bool result = (install_bootrom(alt_bootrom_dsk, BOOTROM_SIZE_DSK,
ALTAIR_ROM_LOW, TRUE) == SCPE_OK); ALTAIR_ROM_LOW, TRUE) == SCPE_OK);
ASSURE(result); ASSURE(result);
} else { } 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 */ /* check whether we are really modifying an LD A,<> instruction */
if ((bootrom_dsk[UNIT_NO_OFFSET_1 - 1] == LDA_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_2 - 1] == LDA_INSTRUCTION)) {
bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */ bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */
bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */ bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */
} else { /* Attempt to modify non LD A,<> instructions is refused. */ } else { /* Attempt to modify non LD A,<> instructions is refused. */
sim_printf("Incorrect boot ROM offsets detected.\n"); sim_printf("Incorrect boot ROM unit number offset detected.\n");
return SCPE_IERR; return SCPE_IERR;
} }
install_ALTAIRbootROM(); /* install modified ROM */ install_ALTAIRbootROM(); /* install modified ROM */