Skip to content

Commit a4ebfa7

Browse files
committed
AltairZ80: Improved choice of boot ROM
1 parent 5ce7d86 commit a4ebfa7

2 files changed

Lines changed: 61 additions & 36 deletions

File tree

AltairZ80/altairz80_defs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
#define LDA_INSTRUCTION 0x3e /* op-code for LD A,<8-bit value> instruction */
5353
#define UNIT_NO_OFFSET_1 0x37 /* LD A,<unitno> */
5454
#define UNIT_NO_OFFSET_2 0xb4 /* LD a,80h | <unitno> */
55+
#define LDB_INSTRUCTION 0x06 /* op-code for LD B,<8-bit value> instruction */
56+
#define START_SECTOR_OFFSET 0x57 /* LD B,<start_sector_offset> */
5557

5658
#define CPU_INDEX_8080 4 /* index of default PC register */
5759

AltairZ80/altairz80_dsk.c

Lines changed: 59 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/* altairz80_dsk.c: MITS Altair 88-DISK Simulator
22
3-
Copyright (c) 2002-2023, Peter Schorn
3+
Copyright (c) 2002-2026, Peter Schorn
44
55
Permission is hereby granted, free of charge, to any person obtaining a
66
copy of this software and associated documentation files (the "Software"),
@@ -33,15 +33,14 @@
3333
The controller is interfaced to the CPU by use of 3 I/O addresses,
3434
standardly, these are device numbers 10, 11, and 12 (octal).
3535
36-
Address Mode Function
37-
------- ---- --------
38-
39-
10 Out Selects and enables Controller and Drive
40-
10 In Indicates status of Drive and Controller
41-
11 Out Controls Disk Function
42-
11 In Indicates current sector position of disk
43-
12 Out Write data
44-
12 In Read data
36+
Address Mode Function
37+
------- ---- --------
38+
10 Out Selects and enables Controller and Drive
39+
10 In Indicates status of Drive and Controller
40+
11 Out Controls Disk Function
41+
11 In Indicates current sector position of disk
42+
12 Out Write data
43+
12 In Read data
4544
4645
Drive Select Out (Device 10 OUT):
4746
@@ -141,21 +140,24 @@
141140
#define TRACK_STUCK_MSG (1 << 5)
142141
#define VERBOSE_MSG (1 << 6)
143142

144-
#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
143+
#define UNIT_V_DSK_WLK (UNIT_V_UF + 0) /* write locked */
145144
#define UNIT_DSK_WLK (1 << UNIT_V_DSK_WLK)
146-
#define DSK_SECTSIZE 137 /* size of sector */
147-
#define DSK_SECT 32 /* sectors per track */
145+
#define DSK_SECTSIZE 137 /* size of sector */
146+
#define DSK_SECT 32 /* sectors per track */
148147
#define MAX_TRACKS 2048 /* number of tracks,
149-
original Altair has 77 tracks only */
148+
original Altair has 77 tracks only */
150149
#define DSK_TRACSIZE (DSK_SECTSIZE * DSK_SECT)
151150
#define MAX_DSK_SIZE (DSK_TRACSIZE * MAX_TRACKS)
152151
#define NUM_OF_DSK_MASK (NUM_OF_DSK - 1)
153-
#define BOOTROM_SIZE_DSK 256 /* size of boot rom */
152+
#define BOOTROM_SIZE_DSK 256 /* size of boot rom */
154153

155-
#define MINI_DISK_SECT 16 /* mini disk sectors per track */
156-
#define MINI_DISK_TRACKS 35 /* number of tracks on mini disk */
154+
#define MINI_DISK_SECT 16 /* mini disk sectors per track */
155+
#define MINI_DISK_TRACKS 35 /* number of tracks on mini disk */
157156
#define MINI_DISK_SIZE (MINI_DISK_TRACKS * MINI_DISK_SECT * DSK_SECTSIZE)
158-
#define MINI_DISK_DELTA 4096 /* threshold for detecting mini disks */
157+
#define MINI_DISK_DELTA 4096 /* threshold for detecting mini disks */
158+
159+
#define ALTAIR_DISK_SIZE 337664 /* size of regular Altair disks */
160+
#define ALTAIR_DISK_DELTA 256 /* threshold for detecting regular Altair disks */
159161

160162
int32 dsk10(const int32 port, const int32 io, const int32 data);
161163
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
187189
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT,
188190
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT,
189191
DSK_SECT, DSK_SECT, DSK_SECT, DSK_SECT };
192+
static int32 current_imageSize [NUM_OF_DSK] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
190193
static int32 tracks [NUM_OF_DSK] = { MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
191194
MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
192195
MAX_TRACKS, MAX_TRACKS, MAX_TRACKS, MAX_TRACKS,
@@ -310,6 +313,8 @@ static REG dsk_reg[] = {
310313
"Number of tracks register array"), REG_CIRC },
311314
{ BRDATAD (SECTPERTRACK, sectors_per_track, 10, 32, NUM_OF_DSK,
312315
"Number of sectors per track register array"), REG_CIRC },
316+
{ BRDATAD (IMAGESIZE, current_imageSize, 10, 32, NUM_OF_DSK,
317+
"Size of disk image array"), REG_CIRC + REG_RO },
313318
{ DRDATAD (IN9COUNT, in9_count, 4,
314319
"Count of IN(9) register"), REG_RO },
315320
{ DRDATAD (IN9MESSAGE, in9_message, 4,
@@ -378,12 +383,12 @@ static const char* selectInOut(const int32 io) {
378383
static t_stat dsk_reset(DEVICE *dptr) {
379384
int32 i;
380385
for (i = 0; i < NUM_OF_DSK; i++) {
381-
warnLock[i] = 0;
382-
warnAttached[i] = 0;
383-
current_track[i] = 0;
384-
current_sector[i] = 0;
385-
current_byte[i] = 0;
386-
current_flag[i] = 0;
386+
warnLock[i] = 0;
387+
warnAttached[i] = 0;
388+
current_track[i] = 0;
389+
current_sector[i] = 0;
390+
current_byte[i] = 0;
391+
current_flag[i] = 0;
387392
}
388393
warnDSK10 = 0;
389394
warnDSK11 = 0;
@@ -413,6 +418,7 @@ static t_stat dsk_attach(UNIT *uptr, CONST char *cptr) {
413418
tracks to 16, otherwise, 32 sectors per track. */
414419

415420
imageSize = sim_fsize(uptr -> fileref);
421+
current_imageSize[thisUnitIndex] = imageSize;
416422
sectors_per_track[thisUnitIndex] = (((MINI_DISK_SIZE - MINI_DISK_DELTA < imageSize) &&
417423
(imageSize < MINI_DISK_SIZE + MINI_DISK_DELTA)) ?
418424
MINI_DISK_SECT : DSK_SECT);
@@ -426,26 +432,43 @@ void install_ALTAIRbootROM(void) {
426432
}
427433

428434
/* The boot routine modifies the boot ROM in such a way that subsequently
429-
the specified disk is used for boot purposes.
435+
the specified disk is used for boot purposes. Furthermore, it determines based on the
436+
size of the attached disk image which boot ROM should be used. The logic is:
437+
- If the size is close to MINI_DISK_SIZE, the ROM for mini disk support is used
438+
- If the size is close to ALTAIR_DISK_SIZE, the standard ROM is modified to start
439+
loading at track 0, sector 0
440+
- Otherwise the standard ROM is is modified to start loading at track 0, sector 8
441+
See DSKBOOT.MAC on the cpm2.dsk for the source code of the boot ROM.
430442
*/
431443
static t_stat dsk_boot(int32 unitno, DEVICE *dptr) {
432444
if (cpu_unit.flags & (UNIT_CPU_ALTAIRROM | UNIT_CPU_BANKED)) {
433445
if (sectors_per_track[unitno] == MINI_DISK_SECT) {
434446
const t_bool result = (install_bootrom(alt_bootrom_dsk, BOOTROM_SIZE_DSK,
435447
ALTAIR_ROM_LOW, TRUE) == SCPE_OK);
436448
ASSURE(result);
437-
} else {
438-
/* check whether we are really modifying an LD A,<> instruction */
449+
} else { /* patch standard ROM with correct unit number and first track */
450+
451+
/* check whether we are really modifying an LD B,<> instruction */
452+
if (bootrom_dsk[START_SECTOR_OFFSET - 1] == LDB_INSTRUCTION)
453+
bootrom_dsk[START_SECTOR_OFFSET] =
454+
(ALTAIR_DISK_SIZE - ALTAIR_DISK_DELTA < current_imageSize[unitno]) &&
455+
(current_imageSize[unitno] < ALTAIR_DISK_SIZE + ALTAIR_DISK_DELTA) ? 0 : 8;
456+
else { /* Attempt to modify non LD B,<> instructions is refused. */
457+
sim_printf("Incorrect boot ROM first sector offset detected.\n");
458+
return SCPE_IERR;
459+
}
460+
461+
/* check whether we are really modifying an LD A,<> instruction */
439462
if ((bootrom_dsk[UNIT_NO_OFFSET_1 - 1] == LDA_INSTRUCTION) &&
440463
(bootrom_dsk[UNIT_NO_OFFSET_2 - 1] == LDA_INSTRUCTION)) {
441-
bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */
442-
bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */
443-
} else { /* Attempt to modify non LD A,<> instructions is refused. */
444-
sim_printf("Incorrect boot ROM offsets detected.\n");
445-
return SCPE_IERR;
464+
bootrom_dsk[UNIT_NO_OFFSET_1] = unitno & 0xff; /* LD A,<unitno> */
465+
bootrom_dsk[UNIT_NO_OFFSET_2] = 0x80 | (unitno & 0xff); /* LD a,80h | <unitno> */
466+
} else { /* Attempt to modify non LD A,<> instructions is refused. */
467+
sim_printf("Incorrect boot ROM unit number offset detected.\n");
468+
return SCPE_IERR;
469+
}
470+
install_ALTAIRbootROM(); /* install modified ROM */
446471
}
447-
install_ALTAIRbootROM(); /* install modified ROM */
448-
}
449472
}
450473
*((int32 *) sim_PC->loc) = ALTAIR_ROM_LOW;
451474
return SCPE_OK;
@@ -546,7 +569,7 @@ int32 dsk10(const int32 port, const int32 io, const int32 data) {
546569
}
547570
current_disk = NUM_OF_DSK;
548571
} else {
549-
current_sector[current_disk] = 0xff; /* reset internal counters */
572+
current_sector[current_disk] = 0xff; /* reset internal counters */
550573
current_byte[current_disk] = 0xff;
551574
if (data & 0x80) /* disable drive? */
552575
current_flag[current_disk] = 0; /* yes, clear all flags */
@@ -572,7 +595,7 @@ int32 dsk11(const int32 port, const int32 io, const int32 data) {
572595
" Attempt of %s 0x09 on unattached disk - ignored.\n",
573596
current_disk, PCX, selectInOut(io));
574597
}
575-
return 0xff; /* no drive selected - can do nothing */
598+
return 0xff; /* no drive selected - can do nothing */
576599
}
577600

578601
/* now current_disk < NUM_OF_DSK */

0 commit comments

Comments
 (0)