4000H - RST Vectors
The Model I ROM sends every RST instruction from 0008H to 0038H through a jump in RAM. The ROM sets up 4000H-400BH itself (RST 08H to RST 20H, used by BASIC). SYS0's file starts at 400CH and replaces the three vectors that belong to the DOS: RST 28H, RST 30H and RST 38H.
4000-400B
DEFS 12
Not in the file. The ROM's jumps for RST 08H, RST 10H, RST 18H and RST 20H.
400C
RST 28H vector: JUMP to the overlay dispatcher at 4BC2H. Every DOS function reached through RST 28H (Register A = function code) goes there, and so does the ROM's keyboard driver when BREAK is pressed.
400F
RST 30H vector: JUMP to 4609H to enter DEBUG.
4012
RST 38H vector (the maskable interrupt, Interrupt Mode 1): JUMP to the interrupt handler at 45F2H.
4015-402C
DEFS 24
Not in the file. The ROM's device control blocks: keyboard 4015H-401CH, display 401DH-4024H and printer 4025H-402CH. When SYSTEM option AJ is Y,
4E31H puts SYS0's keyboard driver 4516H into 4016H-4017H and its display driver 4505H into 401EH-401FH. The cursor address is at 4020H-4021H and the cursor state at 4022H.
402DH - DOS Exits
The two fixed exits of every program (manual sections 3.2 and 3.3) and the ROM's device dispatch hook.
402D
No-error exit: JUMP to 4400H (DOS READY).
4030
LD A,43H 3E 43
Error-already-displayed exit: load Register A with RST 28H code 43H (SYS1, function 2).
4032
RST 28H EF
Call SYS1 through the dispatcher. Nothing returns here.
4033
The ROM's device dispatcher at
03C2H jumps here when the type byte of the device control block pointed to by DE does not match the requested operation. JUMP to 4ADBH, which handles routed devices and FCBs used as devices.
4036-403D
DEFS 8
Not in the file. The ROM's keyboard row image (4036H-403CH) and 403DH.
403EH - Clock, Date and Memory Size
Variables of the resident DOS. The time and date are binary values.
403E-403F
DEFB 00H, 00H 00 00
Not referenced by SYS0.
4040
DEFB 00H 00
Tick counter: incremented on every 25 ms timer interrupt by
4610H.
4041-4043
DEFB 00H, 00H, 00H 00 00 00
The clock: seconds (4041H), minutes (4042H) and hours (4043H). Advanced once a second by
44CDH, converted to text by 446DH (
44A7H).
4044-4046
DEFB 00H, 00H, 00H 00 00 00
The date: year (4044H), day (4045H) and month (4046H). Converted to text by 4470H (
44C2H).
4047-4048
DEFB 00H, 52H 00 52
Not referenced by SYS0.
4049-404A
DEFW 0FFFFH FF FF
HIMEM, the highest memory address the DOS lets programs use (manual 2.24). Set at reset to the top of memory (
4D10H) or to SYSTEM option AP (
4DB3H).
404B-4052
DEFB 00H x 8 00 x 8
Not referenced by SYS0.
4053H - Disk Interrupt Check
Added by zap 060. The interrupt handler calls it with bit 7 of Register A holding the disk controller's interrupt bit. The controller's status is read only when that bit is set, which clears the disk interrupt.
4053
PUSH AF F5
Save Register A and the flags (the CARRY FLAG holds the clock interrupt bit for the caller).
4054
RLCA 07
Rotate the disk interrupt bit (bit 7) into the CARRY FLAG.
4055
If it is set, GOSUB to 47E8H to read the disk controller's status register at 37ECH, which clears the interrupt.
4058
POP AF F1
Restore Register A and the flags.
405A-405C
DEFB 00H x 3 00 x 3
Not referenced by SYS0.
405D-4062
DEFS 6
Not in the file.
4063H - Convert DE or A to Hexadecimal Text
Two entry points used by DEBUG, SYSTEM and other overlays. 4063H stores Register Pair DE as four hexadecimal digits at HL, 4068H stores Register A as two. HL is left pointing after the digits.
4063
LD A,D 7A
Load Register A with the high byte, Register D.
4064
GOSUB to 4068H to store its two digits.
4067
LD A,E 7B
Load Register A with the low byte, Register E, and fall into 4068H.
4068
PUSH AF F5
Save the byte.
4069
RRCA 0F
Rotate the high nibble into the low nibble (four RRCAs).
406A
RRCA 0F
Continue rotating.
406B
RRCA 0F
Continue rotating.
406C
RRCA 0F
Continue rotating.
406D
GOSUB to 4071H to store the high digit.
4070
POP AF F1
Restore the byte for the low digit.
4071
AND 0FH E6 0F
Keep the low nibble.
4073
ADD A,90H C6 90
The standard conversion of a nibble to ASCII: add 90H.
4075
DAA 27
Decimal adjust. 00H-09H becomes 90H-99H with no carry, 0AH-0FH becomes 00H-05H with the CARRY FLAG set.
4076
ADC A,40H CE 40
Add 40H plus the carry.
4078
DAA 27
Decimal adjust again, giving 30H-39H for 0-9 and 41H-46H for A-F.
4079
LD (HL),A 77
Store the digit at HL.
407A
INC HL 23
Point HL to the next byte.
407CH - Clock Limits
The highest value of each clock byte, used by the once-a-second clock routine at 44CDH.
407C-407E
DEFB 3BH, 3BH, 17H 3B 3B 17
Seconds 59, minutes 59, hours 23.
407F
DEFB 00H 00
Not referenced by SYS0.
4080-41FF
DEFS 384
Not in the file: the ROM's and Level II BASIC's own variables.
4200-42FF
DEFS 256
Not in the file: the DOS sector buffer. It holds the boot sector when SYS0 starts, then the system data sector (
4D3BH), and later the directory sector numbered at
4930H and the sectors of system files being loaded.
4300-4307
DEFS 8
Not in the file. 4300H plus the drive number holds the last track register value of each drive, saved when another drive is selected (
478AH).
4308H - Drive Selection and Overlay Variables
The state of the current drive, the BREAK key hook and the number of the overlay in 4D00H-51FFH.
4308
DEFB 00H 00
The current drive number (0-3).
4309
DEFB 00H 00
The value written to the drive select latch at 37E1H for the current drive: 01H, 02H, 04H or 08H, plus bit 3 (side 2) during a transfer on the second side.
430A-4311
DEFB 11H, 23H, 03H, 23H, 0AH, 02H, 00H, 00H 11 23 03 23 0A 02 00 00
A copy of bytes 0-7 of the current drive's PDRIVE record, made by
4776H on every drive select: 430AH directory lump, 430BH lumps, 430CH TSR and TI flags (bit 7 = TI flag H), 430DH track count, 430EH sectors per track, 430FH granules per lump, 4310H sector register value, 4311H disk I/O flags (bit 0 double density, bit 1 tracks numbered from 1, bit 2 double step, bit 4 sectors numbered from 1, bit 6 double sided).
4312
BREAK key hook. The ROM's keyboard driver executes RST 28H with Register A = 01H when BREAK is pressed, and the dispatcher sends every code below 20H here. As shipped this is JP 45B0H, which clears Register A so that BREAK is ignored. The BREAK command and DOS READY (from SYSTEM option AG) store C3H (disabled) or C9H (enabled, a RET that leaves 01H in Register A) in 4312H.
4315-4316
DEFB 01H, 00H 01 00
Not referenced by SYS0.
4317
DEFB 00H 00
The overlay now in 4D00H-51FFH: the low five bits of its RST 28H code (the directory slot: BOOT 00H, DIR 01H, SYS0 02H ... SYS21 17H), 00H for none. Checked and set by the dispatcher at
4BD8H.
4318-4367
DEFS 80
Not in the file. The DOS command buffer. At reset the AUTO command is copied here from the GAT (
4F08H); the date and time answers are typed here too.
4368H - System Flags, Options and the PDRIVE Table
Most of these bytes are filled in at reset from the system data sector (sector 2 of the system diskette) by the code at 4D4CH.
4368
DEFB 0A5H A5
Not referenced by SYS0.
4369
DEFB 40H 40
DOS flags. Bit 6 is set while an overlay function runs (
4BCDH). The keyboard combinations D-F-G, 1-2-3 and J-K-L are ignored while any of bits 2, 3, 5 or 6 is set (
45BFH); bit 2 is set for RUN-ONLY (option AB), bit 3 by FORMAT and COPY. When bit 5 is set and bits 3 and 6 are clear, the keyboard driver asks SYS9 for the key (
4516H). Bit 4 is set at reset when option AG is Y.
436A
DEFB 00H 00
DOS state flags, used by SYS1, SYS4 and other overlays (SYS4 sets bit 2 for an error at reset).
436B
DEFB 00H 00
Temporary flags used by the overlays.
436C-436D
DEFB 00H, 00H 00 00
SYSTEM options, copied from bytes F0H-F1H of the system data sector. 436CH: bit 7 AA (passwords), bit 6 AB (RUN-ONLY), bit 5 AG (BREAK is a key), bit 4 AI (lower case hardware), bit 1 AR, bit 0 AS. 436DH: bit 7 AT, bit 6 BC, bit 5 BE, bit 4 BK.
436E-436F
DEFB 00H, 00H 00 00
Bytes F2H-F3H of the system data sector.
4370
DEFB 5AH 5A
SYSTEM option AX, the highest character code the printer is sent as is (manual 2.46).
4371-437A
DEFB 11H, 23H, 03H, 23H, 0AH, 02H, 00H, 00H, 11H, 02H 11 23 03 23 0A 02 00 00 11 02
The PDRIVE record of drive 0: bytes 0-9 of its 16-byte record in the system data sector (see
PDRIVE Records). At reset 4D2BH first puts bytes +2, +6 and +7 from the boot sector here.
437B-4384
DEFB 0FFH, 01H, 00H, 01H, 00H, 00H, 00H, 00H, 0FFH, 00H FF 01 00 01 00 00 00 00 FF 00
The PDRIVE record of drive 1. IY points to 4380H inside this record while DOS functions run; it is only a base for IY+d addressing of the variables around it.
4385-438E
DEFB 0FFH, 01H, 00H, 01H, 00H, 00H, 00H, 00H, 0FFH, 00H FF 01 00 01 00 00 00 00 FF 00
The PDRIVE record of drive 2.
438F-4398
DEFB 0FFH, 01H, 00H, 01H, 00H, 00H, 00H, 00H, 0FFH, 00H FF 01 00 01 00 00 00 00 FF 00
The PDRIVE record of drive 3.
4399-439A
DEFW 4371H 71 43
The address of the current drive's PDRIVE record (4371H + 10 x drive), set by
479BH.
439B-439E
DEFB 00H, 00H, 00H, 00H 00 00 00 00
Not referenced by SYS0.
439F
DEFB 04H 04
SYSTEM option AL, the number of drives.
43A0
DEFB 01H 01
SYSTEM option AN, the default drive of DIR.
43A1
DEFB 00H 00
SYSTEM option AO, the first drive searched for a free directory entry when a file is created.
43A2
DEFB 01H 01
SYSTEM option BJ, the CPU speed multiplier for the timing loops.
43A3-43A8
DEFB 00H, 01H, 00H, 00H, 0DH, 0DH 00 01 00 00 0D 0D
Not referenced by SYS0.
43A9-43AA
DEFS 2
Not in the file. The top of memory found at reset (
4D10H).
43AB
DEFS 1
Not in the file. A5H while the DOS is active: set at the end of the reset (
4F15H) and tested by the next reset to tell a restart from a power-on.
43AC-43B1
DEFS 6
Not in the file. A copy of the clock and date (4041H-4046H), made every second (
44D1H) and put back by a reset while the DOS was active (
4D16H).
43B2H - ROUTE Entries and the System File FCB
Four seven-byte ROUTE entries, then the FCB used to load system files. A ROUTE entry holds the address of the device control block it serves (+0), a copy of that block's original type byte (+2), the address of the next entry for the same device (+3, 0000H at the end) and the address of the device control block the I/O is sent to (+5). The list is searched by 4B17H; the entries are managed by the ROUTE command (SYS14).
43B2-43B8
DEFB 00H, 00H, 00H, 0FFH, 0FFH, 0FCH, 4CH 00 00 00 FF FF FC 4C
ROUTE entry 1. Its target 4CFCH, the control block of the NL device (
4CFCH), was put here by zap 043. When SYSTEM option BA is Y,
4EB5H fills in the display's control block 401DH and ends the list, which routes the display to NL.
43B9-43BF
DEFB 00H, 00H, 00H, 0FFH, 0FFH, 00H, 00H 00 00 00 FF FF 00 00
ROUTE entry 2.
43C0-43C6
DEFB 00H, 00H, 00H, 0FFH, 0FFH, 00H, 00H 00 00 00 FF FF 00 00
ROUTE entry 3.
43C7-43CD
DEFB 00H, 00H, 00H, 0FFH, 0FFH, 00H, 00H 00 00 00 FF FF 00 00
ROUTE entry 4.
43CE-43DF
DEFB 80H, 28H, 00H, 00H, 42H, 00H, 00H, 0FFH, 00H, 00H, 00H, 00H, 40H, 00H, 00H, 00H, 0FFH, 0FFH 80 28 00 00 42 00 00 FF 00 00 00 00 40 00 00 00 FF FF
The FCB the dispatcher uses to load a system file into memory (
4C03H): open, sector mode, buffer empty, FCB+1 bit 3 set; buffer 4200H; drive 0; EOF 4000H bytes (64 sectors). The dispatcher clears NEXT (43D8H) and stores the file's first extent at 43DCH-43DDH; 43DEH-43DFH (FFH FFH) ends the extent list, so a system file must be in one extent.
43E0-43FF
DEFS 32
Not in the file and not referenced by SYS0.
4400H - DOS Entry Vectors
The fixed entry points documented in chapter 3 of the manual. Most of them load an RST 28H code into Register A and execute RST 28H: the dispatcher at 4BC2H throws away the RST's own return address, loads the overlay if needed and calls it, so the overlay returns straight to the program that called the vector. The code's bits 0-2 are the directory sector minus 2, bits 3-4 the file in that sector, and bits 5-7 the function number.
4400
LD A,23H 3E 23
DOS READY (same as 402DH): load Register A with code 23H (SYS1, function 1).
4402
RST 28H EF
Call SYS1. Nothing returns here.
4403-4404
DEFB 00H, 00H 00 00
A two-byte parameter a program may leave here for the program that ran it through DOS-CALL or a *name command (manual 3.11 and 3.31).
4405
LD A,63H 3E 63
Enter DOS and execute the command at HL (manual 3.5): load Register A with code 63H (SYS1, function 3).
4407
RST 28H EF
Call SYS1. It does not return here.
4408
RET Z C8
Reached as a return address: SYS1 pushes 402DH and then 4408H, so that a function ending with the Z FLAG set RETurns to DOS READY, and one ending with the NZ FLAG set falls into the error exit. (ASPOOL/MAS at its 572EH looks for this return address on the stack.)
4409
PUSH AF F5
DOS error exit (manual 3.6), with the error code in Register A. Save the error code.
440A
LD A,26H 3E 26
Load Register A with code 26H (SYS4, function 1: display the error or leave through the DOS-CALL level).
440C
RST 28H EF
Call SYS4 with the error code on the stack. With bit 7 of the error code set, SYS4 displays the message and returns to the caller.
440D
Enter DEBUG (manual 3.7): JUMP to 4609H.
4410
LD A,65H 3E 65
Enqueue a user timer routine, DE = the routine (manual 3.8): load Register A with code 65H (SYS3, function 3).
4413
LD A,85H 3E 85
Dequeue a user timer routine, DE = the routine (manual 3.9): load Register A with code 85H (SYS3, function 4).
4416
Keep the drives rotating (manual 3.10): JUMP to 4762H.
4419
LD A,C3H 3E C3
DOS-CALL, execute the command at HL and return (manual 3.11): load Register A with code C3H (SYS1, function 6).
441C
LD A,83H 3E 83
Extract a filespec from HL to DE (manual 3.12): load Register A with code 83H (SYS1, function 4).
441F
NOP 00
Not executed (the RST 28H before it does not return).
4420
LD A,44H 3E 44
Open a file, creating it if needed (manual 3.13): load Register A with code 44H (SYS2, function 2).
4424
LD A,24H 3E 24
Open an existing file (manual 3.14): load Register A with code 24H (SYS2, function 1).
4427
ADD A,D 82
Not executed.
4428
LD A,25H 3E 25
Close a file (manual 3.15): load Register A with code 25H (SYS3, function 1).
442B
LD BC,453EH 01 3E 45
Not executed as this instruction. The kill vector 442CH (manual 3.16) starts inside it: its bytes 3EH 45H at 442CH-442DH are LD A,45H (SYS3, function 2), and the RST 28H follows at 442EH.
4430
LD A,A4H 3E A4
Load a program file (manual 3.17): load Register A with code A4H (SYS2, function 5).
4433
LD A,C4H 3E C4
Load and run a program file (manual 3.18): load Register A with code C4H (SYS2, function 6).
4436
READ a sector or a logical record (manual 3.19): JUMP to 49FCH.
4439
WRITE a sector or a logical record (manual 3.20): JUMP to 4A36H.
443C
WRITE with verify (manual 3.21): JUMP to 4A32H.
443F
Position to the start of the file (manual 3.22): JUMP to 4B4CH.
4442
Position to record BC (manual 3.23): JUMP to 4B73H.
4445
Position back one record (manual 3.24): JUMP to 4B62H.
4448
Position to EOF (manual 3.25): JUMP to 4B54H.
444B
Allocate file space up to NEXT (manual 3.26): JUMP to 4809H.
444E
Position to the byte address in H, L and C (manual 3.27): JUMP to 4B47H.
4451
LD A,C5H 3E C5
Write the EOF to the directory (manual 3.28): load Register A with code C5H (SYS3, function 6).
4454-4456
DEFB 00H x 3 00 x 3
Not executed (after the RST 28H). Referenced by SYS18.
4457
LD A,2AH 3E 2A
Load Register A with error code 2AH (ILLEGAL DOS FUNCTION).
4459
JUMP to the error exit at 4409H.
445B
Select and power up the drive in Register A (manual 3.29): JUMP to 4776H.
445E
Test for a mounted diskette in the drive in Register A (manual 3.30): JUMP to 47ECH.
4461
LD A,2BH 3E 2B
Enqueue a *name routine (manual 3.31): load Register A with code 2BH (SYS9, function 1).
4464
LD A,4BH 3E 4B
Dequeue a *name routine (manual 3.32): load Register A with code 4BH (SYS9, function 2).
4467
Display the message at HL (manual 3.33): JUMP to 4BA6H.
446A
Print the message at HL (manual 3.34): JUMP to 4BBCH.
446D
Put the time as HH:MM:SS at HL (manual 3.35): JUMP to 44A7H.
4470
Put the date as MM/DD/YY at HL (manual 3.36): JUMP to 44C2H.
4473
LD A,A3H 3E A3
Insert the default name extension at HL into the filespec at DE (manual 3.37): load Register A with code A3H (SYS1, function 5).
4476-447A
DEFB 00H x 5 00 x 5
Not referenced.
447B
DEFB 00H 00
On the Model III, 447BH is the vector to enqueue a timer routine (manual 3.40). The Model I uses 4410H.
447C
JUMP to 4457H: this vector returns error 2AH (ILLEGAL DOS FUNCTION).
447E
XOR A AF
Not referenced by any module: clear Register A.
4480H - The DOS FCB
A 32-byte FCB that overlays use for their own files (SYS1 puts filespecs here). As loaded it is already open and addresses sector 2 of the diskette in drive 0 with buffer 4200H, so that the reset code can read the system data sector with one call of 4436H (4D3BH). See FCB Layout.
4480
DEFB 82H 82
+0: bit 7 open; bit 1 NEXT and EOF are sector numbers of the whole diskette, not of a file.
4481
DEFB 20H 20
+1: bit 5, the buffer does not hold the NEXT sector; bit 7 clear (sector mode).
4483-4484
DEFW 4200H 00 42
+3: the buffer address.
4485
DEFB 00H 00
+5: NEXT, low byte.
4486
DEFB 00H 00
+6: drive 0.
4487
DEFB 0FFH FF
+7: the DEC (none).
4488
DEFB 00H 00
+8: EOF, low byte.
448A-448B
DEFW 0002H 02 00
+10: NEXT, middle and high byte: sector 2.
448C-448D
DEFW 0FFFFH FF FF
+12: EOF, middle and high byte.
448E-449F
DEFB 0FFH x 18 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
+14: the extents (none).
44A0-44A3
DEFB 00H, 00H, 28H, 01H 00 00 28 01
The timer routine of the CLOCK command. The CLOCK command (SYS3) enqueues it with 4410H (DE = 44A0H) or dequeues it with 4413H. Bytes 0-1 are the chain pointer, byte 2 the interval (28H = 40 ticks, one second) and byte 3 the countdown. The routine starts at 44A4H.
44A4
LD HL,3C35H 21 35 3C
Point HL to 3C35H, the top right of the screen, and fall into 44A7H to put the time there.
44A7H - Convert the Time or Date to Text
446DH and 4470H come here. Three binary bytes, read downward from DE, are stored at HL as two decimal digits each, separated by Register B. On exit HL points after the last digit.
44A7
LD DE,4043H 11 43 40
Time: point DE to the hours at 4043H (then minutes 4042H and seconds 4041H).
44AA
LD B,3AH 06 3A
The separator is a colon.
44AC
LD C,03H 0E 03
Three values.
44AE
LD (HL),2FH 36 2F
Loop Start
Store 2FH, one below "0", as the tens digit.
44B0
LD A,(DE) 1A
Fetch the value.
44B1
INC (HL) 34
Loop Start
Count the tens digit up.
44B2
SUB 0AH D6 0A
Subtract 10.
44B4
Loop End
LOOP BACK to 44B1H while no borrow.
44B6
INC HL 23
Point HL to the units digit.
44B7
ADD A,3AH C6 3A
Add back 10 and add "0": the units digit.
44B9
LD (HL),A 77
Store it.
44BA
INC HL 23
Point HL past it.
44BB
DEC DE 1B
Point DE to the next value.
44BC
DEC C 0D
Count down the values.
44BD
RET Z C8
All three done: RETurn.
44BE
LD (HL),B 70
Store the separator.
44BF
INC HL 23
Point HL past it.
44C0
Loop End
JUMP back to 44AEH for the next value.
44C2
LD DE,4046H 11 46 40
Date: point DE to the month at 4046H (then the day 4045H and the year 4044H).
44C5
LD B,2FH 06 2F
The separator is a slash.
44C9H - Once-a-Second Clock Routine
The first entry of the timer routine chain, whose head is the operand of the instruction at 461CH. It runs once a second.
44C9-44CC
DEFB 0EBH, 44H, 28H, 01H EB 44 28 01
Chain pointer 44EBH (the cursor routine), interval 28H (40 ticks), countdown 01H.
44CD
LD HL,4041H 21 41 40
Point HL to the clock at 4041H.
44D0
PUSH HL E5
Save the pointer.
44D1
LD DE,43ACH 11 AC 43
Point DE to the copy at 43ACH.
44D4
LD BC,0006H 01 06 00
Six bytes: the time and the date.
44D7
LDIR ED B0
Copy them, so that a reset while the DOS is active can put them back (
4D16H). BC is now 0.
44D9
LD DE,407CH 11 7C 40
Point DE to the limits at 407CH.
44DC
POP HL E1
Restore the pointer to the seconds.
44DD
LD B,03H 06 03
Three values: seconds, minutes, hours.
44DF
INC (HL) 34
Loop Start
Count the value up.
44E0
LD A,(DE) 1A
Fetch its limit.
44E1
SUB (HL) 96
Subtract the new value from the limit.
44E2
RET NC D0
Not past the limit: RETurn.
44E3
LD (HL),C 71
Past the limit: set the value to 0 (Register C is 0).
44E4
INC DE 13
Point DE to the next limit.
44E5
INC HL 23
Point HL to the next value.
44E6
Loop End
DECrement Register B and LOOP BACK to 44DFH to carry into the next value.
44E8
INC HL 23
The hours passed 23: skip the year byte at 4044H.
44E9
INC (HL) 34
Count the day at 4045H up. The month and year are not advanced.
44EBH - Cursor Routine
The second entry of the timer routine chain, run every half second. It shows the cursor character, and when blinking is on (SYSTEM option BH, or the BLINK command) it alternates the cursor and the character under it.
44EB-44EE
DEFB 00H, 00H, 14H, 01H 00 00 14 01
Chain pointer 0000H (end of the chain), interval 14H (20 ticks), countdown 01H.
44EF
PUSH IX DD E5
Copy IX, the device control block the interrupted code was working on, into HL.
44F2
LD DE,401DH 11 1D 40
Point DE to the display's control block at 401DH.
44F5
RST 18H DF
Compare HL with DE through the ROM's RST 18H.
44F6
RET Z C8
The display driver was interrupted: leave the cursor alone and RETurn.
44F7
LD A,(4022H) 3A 22 40
Fetch the cursor byte at 4022H: 00H when the cursor is off, otherwise the character the cursor covers.
44FB
RET Z C8
Cursor off: RETurn.
44FC
LD HL,(4020H) 2A 20 40
Load HL with the cursor address from 4020H.
44FF
CP (HL) BE
Compare the covered character with the screen.
4500
LD (HL),5FH 36 5F
Self-Modifying CodePut the cursor character on the screen. The operand 5FH is replaced at reset by SYSTEM option BI when not 0 (
4E28H).
4502
RET C9
Self-Modifying CodeRETurn. Changed to
RET Z (C8H) for a blinking cursor, at reset by option BH (
4E6AH) or by the BLINK command (SYS3). With RET Z the routine returns only if the screen showed the covered character, so the cursor was just put up.
4503
LD (HL),A 77
Blinking, and the cursor was showing: put the covered character back.
4505H - Display Driver
Put into the display's control block (401EH) at reset when SYSTEM option AJ is Y (4E31H). The ROM's dispatcher at 03C2H enters a driver with IX pointing to the control block, Register C holding the character, and the flags of CP 02H on the request type: the CARRY FLAG set for input (reading the character at the cursor), clear for output. As loaded, everything goes to the ROM's driver. With the lower case driver on (SYSTEM option BF, or the LCDVR command in SYS3), 4505H becomes JR C,4513H and characters 20H-7FH are put on the screen by the ROM's store routine, so lower case letters are not changed to upper case.
4505
Self-Modifying CodeJUMP to 4513H. Changed to
JR C,4513H (38H) by
4E5CH or by LCDVR, so that only input requests go straight to the ROM.
4507
Output: GOSUB to 4853H to load HL with the cursor address from bytes 3-4 of the control block.
450A
LD A,C 79
Load Register A with the character.
450B
SUB 20H D6 20
Subtract 20H.
450D
CP 60H FE 60
Is the character in the range 20H-7FH?
450F
LD A,C 79
Load Register A with the character again.
4510
Yes: JUMP to the ROM at 047DH, which stores Register A at the cursor and advances it.
4513
JUMP to the ROM's display driver at 0458H.
4516H - Keyboard Driver
Put into the keyboard's control block (4016H) at reset when SYSTEM option AJ is Y, unless the up-arrow key is held (4E31H). It scans the keyboard like the ROM's driver but adds the repeat key (options AU and AV), the debounce (option AC), a CLEAR key filter (option AQ), the key combinations D-F-G, 1-2-3 and J-K-L (45BFH) and, with the lower case driver on, the letter case handling at 4594H. It returns the key in Register A, or 00H for none.
4516
LD A,(4369H) 3A 69 43
Fetch the DOS flags at 4369H.
4519
XOR 20H EE 20
Flip bit 5.
451B
AND 68H E6 68
Keep bits 3, 5 and 6. The Z FLAG is now set only when bit 5 was set and bits 3 and 6 were clear.
451D
LD A,CBH 3E CB
Load Register A with code CBH (SYS9, function 6).
451F
In that state, GOSUB to 49DDH to call SYS9 for the key (the chain file supplies it).
4522
RET Z C8
SYS9 supplied a key: RETurn with it.
4523
LD HL,45BEH 21 BE 45
Point HL to 45BEH.
4526
LD (HL),C9H 36 C9
Store a RET there, so that the timer interrupt does not look for the key combinations while the keyboard is being scanned.
4528
PUSH HL E5
Save the pointer to 45BEH.
4529
LD HL,4036H 21 36 40
Self-Modifying Code
Point HL to the saved row image of the last key found (the operand is stored at 4565H; as loaded it is 4036H).
452C
LD A,(HL) 7E
Fetch that row image.
452D
OR A B7
Is the last key still down?
452E
LD A,00H 3E 00
Self-Modifying CodeLoad Register A with the first repeat delay. The operand is SYSTEM option AV, stored at reset (
4E25H).
4530
The key is still down: JUMP to 4535H.
4532
LD (4580H),A 32 80 45
The key was released: the next repeat starts with the full first delay.
4535
XOR A AF
Clear Register A.
4536
OR 00H F6 00
Self-Modifying CodeRegister A = the repeat countdown at 4537H, which the timer interrupt counts down (
4614H).
4538
Self-Modifying CodeJUMP to 4543H (no repeat key). Changed to
JR NZ,4543H (20H) when SYSTEM option AU is Y (
4E1AH): the scan then goes on normally until the countdown reaches 0.
453A
OR (HL) B6
The countdown has run out: look at the last key's row image.
453B
The key is still down: JUMP to 4541H to make it look newly pressed.
453D
DEC A 3D
The key is up: Register A = FFH.
453E
LD (4573H),A 32 73 45
Store FFH as the last key number (the operand at 4573H), so that the next key starts a new repeat.
4541
LD (HL),00H 36 00
Clear the row image, so that the scan below sees the held key as a new key press.
4543
LD L,36H 2E 36
Point HL to the row images at 4036H.
4545
LD BC,3801H 01 01 38
Register Pair BC = 3801H, the address of keyboard row 0.
4548
LD D,FFH 16 FF
Register D counts the key number; it is FFH before row 0.
454A
LD A,(BC) 0A
Loop Start
Read the row.
454B
LD E,A 5F
Keep it in Register E.
454C
XOR (HL) AE
XOR it with the saved image to find the bits that changed.
454D
LD (HL),E 73
Save the new image.
454E
AND E A3
Keep only the changed bits that are now down (the Model I keyboard reads 1 for a key that is down).
454F
A new key in this row: JUMP to 455EH.
4551
LD A,D 7A
No key here. Add 8 to the key number for the next row.
4552
ADD A,08H C6 08
Continue.
4555
INC L 2C
Point HL to the next row image.
4556
RLC C CB 01
Next row address bit (3801H, 3802H, 3804H ... 3840H).
4558
Loop End
LOOP BACK to 454AH until row 6 has been read (row 7, the SHIFT row, is not scanned).
455B
XOR A AF
No key: Register A = 00H.
455E
LD E,A 5F
Save the new key bits in Register E.
455F
INC D 14
Loop Start
Count the key number up.
4560
RRCA 0F
Shift the bits right.
4561
Loop End
LOOP BACK to 455FH until the key's bit has been found.
4563
PUSH BC C5
Save the row address.
4564
PUSH DE D5
Save the key number and bit.
4565
LD (452AH),HL 22 2A 45
Remember this row's image address in the operand at 452AH for the repeat test.
4568
GOSUB to the ROM at 040BH, which converts key number D to its character in Register A (with SHIFT and the ROM's debounce delay).
456B
POP HL E1
Register H = the key number, Register L = its bit.
456C
POP BC C1
Restore the row address.
456D
OR A B7
Is there a character?
456E
LD D,A 57
Keep it in Register D.
456F
No character: JUMP to 4589H.
4571
LD A,H 7C
Load Register A with the key number.
4572
CP FFH FE FF
Self-Modifying Code
Compare it with the last key number (the operand at 4573H, FFH for none).
4574
LD (4573H),A 32 73 45
Store it as the new last key number.
4577
LD A,00H 3E 00
Self-Modifying CodeLoad Register A with the first repeat delay, SYSTEM option AV (stored at
4E22H).
4579
A different key: JUMP to 4581H to start the countdown with the first delay.
457B
LD A,(BC) 0A
The same key again: read its row.
457C
AND L A5
Is it really down?
457D
Self-Modifying CodeDebounce: not down, so JUMP back to 456DH with Register A = 00H (no key). When SYSTEM option AC is N,
4E77H changes the opcode to 3EH and the two bytes become
LD A,0EEH, which is overwritten at once.
457F
LD A,FFH 3E FF
Self-Modifying Code
Load Register A with the delay for a repeat of the same key. As loaded FFH; set to 02H at 4586H and back to the first delay at 4532H.
4581
LD (4537H),A 32 37 45
Store the delay as the repeat countdown at 4537H.
4584
LD A,02H 3E 02
Load Register A with 02H: after the first repeat, the key repeats every 2 ticks.
4586
LD (4580H),A 32 80 45
Store it as the operand at 4580H.
4589
GOSUB to 45BFH to check the key combinations (D-F-G, 1-2-3, J-K-L). It returns the character, from Register D, in Register A.
458C
POP HL E1
Restore the pointer to 45BEH.
458D
LD (HL),00H 36 00
Store a NOP there: the timer interrupt may look for the key combinations again.
458F
CP 1FH FE 1F
Self-Modifying CodeIs it the CLEAR key (1FH)? The operand is changed to 00H when SYSTEM option AQ is Y (
4E92H), which lets CLEAR through.
4591
CLEAR: JUMP to 45B0H to return 00H instead.
4593
RET C9
Self-Modifying Code
RETurn with the character. With the lower case driver on (SYSTEM option BF, or LCDVR in SYS3) this byte is LD C,A (4FH) and the letter case handling at 4594H follows.
4594H - Letter Case Handling
Reached from 4593H only while the lower case driver is on, with the character in Registers A and C. Letters have their case flipped, so that an unshifted letter gives lower case, and SHIFT-0 switches upper case only mode on and off. When the upper case only mode is on (45B4H holds a NOP), letters are converted to upper case instead.
4594
AND DFH E6 DF
Clear bit 5 (the case bit).
4596
SUB 41H D6 41
Subtract "A".
4598
CP 1AH FE 1A
Is it a letter (A-Z)?
459A
LD A,C 79
Load Register A with the character again.
459B
A letter: JUMP to 45B2H.
459D
CP 20H FE 20
Is it the code 20H?
459F
RET NZ C0
Anything else: RETurn with it.
45A0
LD HL,387FH 21 7F 38
Point HL to 387FH, which reads keyboard rows 0-6 together.
45A3
LD A,(HL) 7E
Fetch them.
45A4
INC HL 23
Point HL to 3880H, keyboard row 7 (the SHIFT keys).
45A5
AND (HL) A6
Combine the two: bit 0 is set only with a bit-0 key (such as 0) and the left SHIFT key down.
45A6
RRCA 0F
Move bit 0 into the CARRY FLAG.
45A7
LD A,C 79
Load Register A with the character again.
45A8
RET NC D0
Not SHIFT-0: RETurn with the space.
45A9
LD HL,45B4H 21 B4 45
SHIFT-0: point HL to 45B4H.
45AC
LD A,(HL) 7E
Fetch the byte there.
45AD
XOR C9H EE C9
Switch it between C9H (RET) and 00H (NOP).
45AF
LD (HL),A 77
Store it back. Continue to 45B0H to return no key.
45B0
XOR A AF
Clear Register A (no key). 4312H also jumps here to turn BREAK into no key.
45B2
XOR 20H EE 20
Flip the case of the letter.
45B4
RET C9
Self-Modifying CodeRETurn. Changed to a NOP (00H) by SYSTEM option BG = N (
4E65H), by the LC command (SYS3) or by SHIFT-0: the letter then falls into 45B5H and is made upper case.
45B5H - Convert Lower Case to Upper Case
Converts a lower case letter in Register A to upper case; any other value is returned unchanged. Used by many overlays.
45B5
CP 61H FE 61
Is it below "a"?
45B8
CP 7BH FE 7B
Is it above "z"?
45BA
RET NC D0
Yes: RETurn.
45BB
SUB 20H D6 20
Make it upper case.
45BEH - Check for D-F-G, 1-2-3 and J-K-L
Called by the timer interrupt (4600H) and by the keyboard driver (4589H). D-F-G enters MINI-DOS, 1-2-3 enters DEBUG, J-K-L prints the screen. Each combination is off until the reset code turns it on from SYSTEM options AF, AE and AD, by changing an unconditional JR into JR NZ. On return, Register A holds Register D (the keyboard driver's character).
45BE
NOP 00
Self-Modifying Code
Entry for the timer interrupt. A NOP, or a RET while the keyboard driver is scanning (stored at 4526H; put back to NOP at 458DH and by the dispatcher at 4BD5H).
45BF
LD HL,4369H 21 69 43
Entry for the keyboard driver. Point HL to the DOS flags at 4369H.
45C2
LD A,(HL) 7E
Fetch them.
45C3
AND 6CH E6 6C
Keep bits 2, 3, 5 and 6.
45C5
Any of them set: no combinations; JUMP to 45EDH.
45C7
LD A,(3801H) 3A 01 38
Read keyboard row 0.
45CA
CP D0H FE D0
Are D, F and G (bits 4, 6 and 7) down, and nothing else in the row?
45CC
Self-Modifying CodeJUMP to 45D3H. Changed to
JR NZ,45D3H (20H) when SYSTEM option AF is Y (
4E89H).
45CE
LD A,E3H 3E E3
D-F-G: load Register A with code E3H (SYS1, function 7).
45D0
LD C,04H 0E 04
Sub-function 4: MINI-DOS.
45D3
LD A,(3810H) 3A 10 38
Read keyboard row 4.
45D6
CP 0EH FE 0E
Are 1, 2 and 3 (bits 1, 2 and 3) down, and nothing else in the row?
45D8
Self-Modifying CodeJUMP to 45E8H. Changed to
JR NZ,45E8H (20H) when SYSTEM option AE is Y (
4E9AH).
45DA
LD A,(45BEH) 3A BE 45
1-2-3: fetch the byte at 45BEH.
45DD
SUB C9H D6 C9
Is it a RET? Then the keyboard driver called.
45DF
Yes: JUMP to 440DH to enter DEBUG, which returns into the keyboard driver.
45E2
POP AF F1
Called from the interrupt: throw away the return address into the interrupt handler.
45E3
POP BC C1
Restore Register Pair BC as the interrupt handler saved it.
45E4
POP DE D1
Restore Register Pair DE.
45E5
POP HL E1
Restore Register Pair HL.
45E6
JUMP to 460AH. The interrupted program's AF is still on the stack, so DEBUG is entered as if the interrupted instruction had been a RST 30H.
45E8
LD A,(3802H) 3A 02 38
Read keyboard row 1.
45EB
CP 1CH FE 1C
Are J, K and L (bits 2, 3 and 4) down, and nothing else in the row?
45ED
LD A,D 7A
Load Register A with the character in Register D.
45EE
RET C9
Self-Modifying CodeRETurn. Changed to
RET NZ (C0H) when SYSTEM option AD is Y (
4E80H).
45EF
LD A,A5H 3E A5
J-K-L: load Register A with code A5H (SYS3, function 5: print the screen).
45F1
RST 28H EF
Call SYS3, which returns to the caller of 45BFH.
45F2H - Interrupt Handler
The RST 38H vector at 4012H jumps here on every interrupt. The interrupt latch at 37E0H tells which: bit 7 the 25 ms clock, bit 6 the disk controller.
45F2
PUSH AF F5
Save Register Pair AF.
45F3
PUSH HL E5
Save Register Pair HL.
45F4
PUSH DE D5
Save Register Pair DE.
45F5
PUSH BC C5
Save Register Pair BC.
45F6
LD A,(37E0H) 3A E0 37
Read the interrupt latch at 37E0H.
45F9
RLCA 07
Move the clock bit into the CARRY FLAG and the disk bit into bit 7.
45FA
GOSUB to 4053H to clear a disk interrupt (zap 060).
45FD
A clock interrupt: GOSUB to 4610H.
4600
GOSUB to 45BEH to check the key combinations.
4603
POP BC C1
Restore Register Pair BC.
4604
POP DE D1
Restore Register Pair DE.
4605
POP HL E1
Restore Register Pair HL.
4606
POP AF F1
Restore Register Pair AF.
4607
EI FB
Enable interrupts.
4609H - Enter DEBUG
Reached through RST 30H (400FH) and through 440DH.
4609
PUSH AF F5
Save Register Pair AF.
460A
LD A,27H 3E 27
Load Register A with code 27H (SYS5, function 1: DEBUG).
460C
RST 28H EF
Call SYS5. DEBUG returns to the caller with the registers restored.
460D
LD (HL),B 70
Called from the timer chain loop with HL pointing to byte 3 of a routine whose countdown just reached 0 and Register B holding its interval. Reload the countdown.
460E
INC HL 23
Point HL to the routine's code, byte 4.
460F
JP (HL) E9
JUMP to the routine. It returns to 462DH.
4610H - Timer Tick
Called for every clock interrupt, every 25 ms. Counts the ticks, counts down the repeat key delay and walks the chain of timer routines. The chain is the one the manual describes in section 3.8: each routine starts with a two-byte chain pointer, its interval and its countdown, and its code follows at byte 4.
4610
LD HL,4040H 21 40 40
Point HL to the tick counter at 4040H.
4613
INC (HL) 34
Count it up.
4614
LD HL,4537H 21 37 45
Point HL to the repeat key countdown at 4537H.
4617
LD A,(HL) 7E
Fetch it.
461B
DEC (HL) 35
Count it down.
461C
LD HL,44C9H 21 C9 44
Self-Modifying Code
Point HL to the first routine of the chain, 44C9H. The operand at 461DH-461EH is the chain head, changed by SYS3's enqueue and dequeue functions.
461F
LD A,H 7C
Loop Start
Is HL 0000H?
4621
RET Z C8
End of the chain: RETurn.
4622
LD E,(HL) 5E
Fetch the chain pointer into Register Pair DE.
4624
LD D,(HL) 56
Continue.
4625
PUSH DE D5
Save it as the next routine.
4626
INC HL 23
Point HL to the interval.
4627
LD B,(HL) 46
Fetch it into Register B.
4628
INC HL 23
Point HL to the countdown.
4629
DEC (HL) 35
Count it down.
462A
It reached 0: GOSUB to 460DH to reload it and run the routine.
462D
POP HL E1
Restore the next routine into HL.
462E
Loop End
JUMP back to 461FH.
4630H - Read or Write a Sector
The sector level disk I/O. DE = the sector number on the diskette (counted from 0 across all tracks), HL = the 256-byte buffer, the drive is the current drive (4308H). On exit the Z FLAG is set if all went well; otherwise Register A holds the DOS error code. BC is preserved. Entry points: 4630H read, 4634H verify read, 463CH write with the directory mark, 4640H write.
4630
LD A,88H 3E 88
Read: load Register A with the controller's Read Sector command 88H.
4634
PUSH HL E5
Verify read, used after a write with verify: save HL.
4635
LD H,01H 26 01
Point the buffer into the ROM at 01xxH, where the data read is thrown away. The read still checks the sector's CRC.
4637
GOSUB to 4630H to read the sector.
463C
LD A,A9H 3E A9
Self-Modifying CodeWrite with the directory mark: load Register A with the Write Sector command A9H (data address mark FAH, the mark Model I TRSDOS reads as a protected directory sector).
4DFDH changes the operand to ABH (mark F8H, the one the Model III uses) when SYSTEM option BN is Y.
4640
LD A,A8H 3E A8
Write: load Register A with the Write Sector command A8H (data address mark FBH).
4642
LD (46C4H),A 32 C4 46
Store the command at 46C4H, where the transfer code issues it.
4645
AND 20H E6 20
Bit 5 is set for the write commands.
4647
PUSH BC C5
Save Register Pair BC.
4648
LD BC,021AH 01 1A 02
For a read: the bytes 1AH 02H (LD A,(DE) / LD (BC),A) for the transfer loop, and error code base 00H (Register A is 0 here).
464B
A read: JUMP to 4652H.
464D
LD A,08H 3E 08
For a write: error code base 08H,
464F
LD BC,0A12H 01 12 0A
and the bytes 12H 0AH (LD (DE),A / LD A,(BC)).
4652
LD (4731H),A 32 31 47
Store the error code base as the operand at 4731H.
4655
LD (46FCH),BC ED 43 FC 46
Store the two bytes at 46FCH-46FDH, the heart of the transfer loop.
4659
LD B,0AH 06 0A
Self-Modifying CodeLoad Register B with the number of tries, SYSTEM option AM (stored at
4D83H; the file has 10).
465B
GOSUB to 4773H to select the current drive.
465E
Bad drive number: JUMP to 4678H to return error 20H.
4660
PUSH BC C5
Retry Loop Start
Save the tries count.
4661
PUSH DE D5
Save the sector number.
4662
PUSH HL E5
Save the buffer address.
4663
LD A,(430EH) 3A 0E 43
Load Register A with the sectors per track from 430EH.
4666
EX DE,HL EB
Put the sector number into HL.
4667
GOSUB to 4CB4H to divide HL by Register A: HL = the track, Register A = the sector in the track.
466A
LD D,L 55
Register D = the track.
466B
LD E,A 5F
Register E = the sector.
466C
LD HL,430DH 21 0D 43
Point HL to the track count at 430DH.
466F
LD A,D 7A
Load Register A with the track.
4670
CP (HL) BE
Is it below the track count?
4673
LD A,14H 3E 14
Load Register A with error code 14H (TRACK # TOO HIGH).
4675
POP HL E1
Restore the buffer address.
4676
POP DE D1
Restore the sector number.
4677
POP BC C1
Restore Register Pair BC.
4678
OR A B7
Set the NZ FLAG (Register A holds the error code).
4679
JUMP to 4737H to return.
467C
LD A,(4311H) 3A 11 43
Load Register B with the disk I/O flags of the current drive from 4311H.
4680
BIT 0,B CB 40
Double density (bit 0)?
4684
LD HL,46C4H 21 C4 46
Point HL to the command at 46C4H.
4687
RES 1,(HL) CB 8E
Clear its bit 1, which only the single density controller uses for the data address mark.
4689
LD HL,4309H 21 09 43
Point HL to the select latch value at 4309H.
468C
BIT 1,B CB 48
Tracks numbered from 1 (bit 1)?
4690
INC D 14
Yes: add 1 to the track.
4691
PUSH DE D5
Save the track and sector as they appear in the sector headers.
4692
BIT 2,B CB 50
Double step (bit 2)?
4696
RLC D CB 02
Yes: the head is moved to track x 2.
4698
BIT 6,B CB 70
Double sided (bit 6)?
469C
RRC C CB 09
Halve the sectors per track (Register C, left by 4CB4H) to get the sectors per side.
469E
LD A,E 7B
Load Register A with the sector.
469F
SUB C 91
Subtract the sectors per side.
46A0
The sector is on side 1: JUMP to 46A5H.
46A2
LD E,A 5F
Side 2: Register E = the sector on that side.
46A3
SET 3,(HL) CB DE
Set bit 3 of the select latch value (side 2).
46A5
GOSUB to 4767H to write the select latch.
46A8
BIT 4,B CB 60
Sectors numbered from 1 (bit 4)?
46AC
INC E 1C
Yes: add 1 to the sector.
46AD
LD (37EEH),DE ED 53 EE 37
Write the sector register (37EEH) and the data register (37EFH, the track to seek).
46B1
LD C,18H 0E 18
Load Register C with the Seek command 18H.
46B3
GOSUB to 4747H to issue it with the drive's stepping rate and wait until it ends.
46B6
POP AF F1
Restore the track number the sector headers carry into Register A.
46B7
POP BC C1
Load Register Pair BC with the buffer address.
46B8
PUSH BC C5
Keep it on the stack.
46B9
LD (37EDH),A 32 ED 37
Write that track number into the track register.
46BC
PUSH DE D5
Save Register D, the physical track.
46BD
LD DE,37EFH 11 EF 37
Point DE to the data register at 37EFH.
46C0
LD HL,37ECH 21 EC 37
Point HL to the command and status register at 37ECH.
46C3
LD (HL),00H 36 00
Self-Modifying Code
Issue the command stored at 46C4H by 4642H.
46C5
GOSUB to 47E3H to wait a moment and read the status.
46C8
DI F3
Disable interrupts for the transfer.
46C9
BIT 0,(HL) CB 46
Is the controller busy?
46CB
No: the command has already ended; JUMP to 4717H.
46CD
LD A,(46C4H) 3A C4 46
Fetch the command.
46D0
BIT 5,A CB 6F
Bit 5 set: a write.
46D2
A read: JUMP to 46F6H.
46D4
LD A,83H 3E 83
Loop Start
Load Register A with the mask 83H (not ready, data request and busy).
46D6
AND (HL) A6
Mask the status.
46D7
Loop End
While only busy is set (odd parity), LOOP BACK to 46D4H.
46DA
LD A,(BC) 0A
Fetch the first byte.
46DB
LD (DE),A 12
Give it to the controller.
46DC
INC BC 03
Point BC to the next byte.
46DD
LD A,(BC) 0A
Fetch the second byte.
46DE
LD (46E8H),A 32 E8 46
Store it as the operand at 46E8H.
46E1
INC BC 03
Point BC to the third byte.
46E2
LD A,01H 3E 01
Load Register A with 01H (busy, no data request).
46E4
CP (HL) BE
Loop Start
Is that the status?
46E5
Loop End
Yes: LOOP BACK to 46E4H until the controller asks for the next byte.
46E7
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the second byte (stored at 46DEH).
46E9
LD (DE),A 12
Give it to the controller.
46EA
LD A,(BC) 0A
Fetch the third byte.
46EB
INC BC 03
Point BC to the next byte.
46EC
BIT 1,(HL) CB 4E
Does the controller ask for the next byte?
46F0
BIT 1,(HL) CB 4E
Ask again.
46F4
JUMP to 46FFH to keep polling.
46F6
LD A,83H 3E 83
Read: Loop Start
Load Register A with the mask 83H.
46F8
AND (HL) A6
Mask the status.
46F9
Loop End
While only busy is set, LOOP BACK to 46F6H.
46FC
LD A,(DE) 1A
Self-Modifying Code
Transfer Loop Start
Read: LD A,(DE) takes the byte from the data register. Write: LD (DE),A gives the waiting byte to the controller. The two bytes are stored by 4655H.
46FD
LD (BC),A 02
Read: LD (BC),A stores the byte in the buffer. Write: LD A,(BC) fetches the next byte.
46FE
INC BC 03
Point BC to the next byte.
46FF
BIT 1,(HL) CB 4E
Does the controller ask for a byte (bit 1)?
4701
Yes: LOOP BACK to 46FCH.
4703
BIT 1,(HL) CB 4E
Ask again.
4705
Yes: LOOP BACK to 46FCH.
4707
BIT 1,(HL) CB 4E
Ask again.
4709
Yes: LOOP BACK to 46FCH.
470B
BIT 0,(HL) CB 46
Is the controller still busy?
470D
No: the command has ended; JUMP to 4717H.
470F
BIT 1,(HL) CB 4E
Does it ask for a byte?
4711
Yes: LOOP BACK to 46FCH.
4713
BIT 7,(HL) CB 7E
Is the drive not ready (bit 7)?
4715
Transfer Loop End
Ready: LOOP BACK to 46FFH.
4717
LD A,(HL) 7E
Fetch the final status.
4718
LD (HL),D0H 36 D0
Issue the Force Interrupt command D0H.
471A
INC HL 23
Point HL to the track register.
471B
POP BC C1
Restore the physical track into Register B.
471C
LD (HL),B 70
Put it back into the track register.
471D
POP HL E1
Restore the buffer address.
471E
POP DE D1
Restore the sector number.
471F
POP BC C1
Restore the tries count.
4720
EI FB
Enable interrupts.
4721
AND FCH E6 FC
Drop the busy and data request bits of the status.
4723
Nothing else set: success, JUMP to 4737H with Register A = 0.
4725
LD C,A 4F
Keep the status in Register C.
4726
AND 9CH E6 9C
Keep the bits worth a retry: not ready, record not found, CRC error and lost data.
4728
None of them (only the record type, write fault or write protect bits): JUMP to 4730H, no retry.
472A
LD C,A 4F
Keep these bits in Register C.
472B
ADD A,A 87
Shift bit 7 out.
472C
Only not ready: JUMP to 4730H, no retry.
472E
Tries left: DECrement Register B and JUMP to 473AH to try again.
4730
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the error code base: 00H for a read, 08H for a write (stored at 4652H).
4732
INC A 3C
Loop Start
Count the error code up.
4733
RRC C CB 09
Shift the lowest status bit into the CARRY FLAG.
4735
Loop End
LOOP BACK to 4732H until a set bit is found. The code is the base plus the bit number plus 1: 03H/0BH lost data, 04H/0CH CRC error, 05H/0DH record not found, 06H/0EH record type bit 5 (read: the directory mark) or write fault, 07H/0FH record type bit 6 or write protected, 08H/10H not ready.
4737
EI FB
Enable interrupts.
4738
POP BC C1
Restore Register Pair BC.
473A
BIT 4,C CB 61
Record not found (bit 4)?
473C
Yes: GOSUB to 4742H, which restores the head to track 0 on every other try.
473F
Retry Loop End
JUMP back to 4660H.
4742
BIT 0,B CB 40
Is the tries count odd?
4745
LD C,08H 0E 08
Load Register C with the Restore command 08H and fall into 4747H.
4747H - Issue a Seek Type Command and Wait
Register C holds a Restore (08H), Seek (18H) or Step In (58H) command. The current drive's stepping rate is added, the command is issued, and the routine waits until the controller is no longer busy, reselecting the drive meanwhile so that its motor keeps running. Used by SYS6 as well.
4747
LD A,(430CH) 3A 0C 43
Load Register A with the TSR byte of the current drive from 430CH.
474A
AND 03H E6 03
Keep the stepping rate, bits 0-1.
474C
OR C B1
Add the command.
474D
LD (37ECH),A 32 EC 37
Write it to the command register.
4750
Loop Start
GOSUB to 47E3H to wait a moment and read the status.
4756
RLCA 07
Not ready (bit 7)?
4757
Yes: JUMP to 475EH to stop the command.
4759
GOSUB to 4767H to reselect the drive.
475C
Loop End
JUMP back to 4750H.
475E
LD A,D0H 3E D0
Load Register A with the Force Interrupt command D0H.
4760
JUMP to 474DH to issue it and wait.
4762H - Keep the Drives Rotating
4416H comes here (manual 3.10). If the drives are rotating, the current drive is reselected. 4767H writes the select latch.
4762
LD A,(37ECH) 3A EC 37
Read the status.
4765
RLCA 07
Move the not ready bit into the CARRY FLAG.
4766
RET C D8
Not ready: RETurn.
4767
LD A,(4309H) 3A 09 43
Load Register A with the select latch value from 4309H.
476A
LD (37E1H),A 32 E1 37
Write it to the drive select latch at 37E1H, which also restarts the motor timer.
476EH - Select a Drive
Enter at 476EH for the drive of the FCB at IX, at 4773H for the current drive, or at 4776H with the drive in Register A (445BH, manual 3.29). The drive becomes the current drive: its PDRIVE record is copied to 430AH-4311H, the controller's track and sector registers are set for it, and its motor is started. A motor that was stopped gets a half second to come up to speed. On exit the Z FLAG is set, or the NZ FLAG with error code 20H (ILLEGAL OR MISSING DRIVE #). HL, DE and BC are preserved.
476E
LD A,(IX+06H) DD 7E 06
Load Register A with the FCB's drive number (FCB+6).
4773
LD A,(4308H) 3A 08 43
Load Register A with the current drive from 4308H.
4776
PUSH HL E5
Save Register Pair HL.
4777
PUSH DE D5
Save Register Pair DE.
4778
PUSH BC C5
Save Register Pair BC.
4779
CP 01H FE 01
Self-Modifying CodeCompare the drive with the number of drives, SYSTEM option AL (stored at
4D69H).
477B
LD C,A 4F
Keep the drive in Register C.
477C
LD A,20H 3E 20
Load Register A with error code 20H.
477E
Drive number too high: JUMP to 47DEH to return the error.
4780
GOSUB to 475EH to stop any command and wait until the controller is idle.
4783
LD HL,4308H 21 08 43
Point HL to the current drive at 4308H.
4786
LD A,(HL) 7E
Fetch the old drive.
4787
LD (HL),C 71
Store the new one.
4788
CP C B9
Is it the same drive?
4789
PUSH AF F5
Save the answer.
478A
LD L,A 6F
Point HL to 4300H plus the old drive.
478B
LD A,(37EDH) 3A ED 37
Read the track register.
478E
LD (HL),A 77
Save it for the old drive.
478F
LD L,C 69
Point HL to 4300H plus the new drive.
4790
PUSH HL E5
Save that address.
4791
LD B,C 41
Register B = drive + 1.
4792
LD A,80H 3E 80
Start with 80H.
4795
RLCA 07
Loop Start
Rotate the bit left.
4796
Loop End
LOOP BACK to 4795H. Register A is now 01H, 02H, 04H or 08H.
4798
LD (4309H),A 32 09 43
Store it as the select latch value.
479B
LD A,C 79
Load Register A with the drive.
47A0
ADD A,71H C6 71
Add 71H.
47A2
LD L,A 6F
HL = 4371H + 10 x drive, the drive's PDRIVE record.
47A3
LD (4399H),HL 22 99 43
Store its address at 4399H.
47A6
LD C,08H 0E 08
Eight bytes (Register B is 0).
47A8
LD DE,430AH 11 0A 43
Point DE to 430AH.
47AB
LDIR ED B0
Copy bytes 0-7 of the PDRIVE record there.
47AD
LD HL,37ECH 21 EC 37
Point HL to the status register.
47B0
LD E,(HL) 5E
Keep the status in Register E (bit 7 set: the motors had stopped).
47B1
DI F3
Disable interrupts.
47B2
LD A,(4311H) 3A 11 43
Load Register A with the drive's disk I/O flags.
47B5
OR FEH F6 FE
FEH for single density, FFH for double density (bit 0).
47B7
LD (HL),A 77
Write it to the command register: the density select of the double density adapters.
47B8
LD (HL),D0H 36 D0
Issue the Force Interrupt command D0H.
47BA
EI FB
Enable interrupts.
47BB
INC HL 23
Point HL to the track register.
47BC
POP BC C1
Restore the pointer to 4300H plus the new drive.
47BD
LD A,(BC) 0A
Fetch the new drive's last track.
47BE
LD (HL),A 77
Write it to the track register.
47BF
INC HL 23
Point HL to the sector register.
47C0
LD A,(4310H) 3A 10 43
Load Register A with byte 6 of the drive's PDRIVE record from 4310H.
47C3
LD (HL),A 77
Write it to the sector register.
47C4
GOSUB to 475EH to stop any command and wait.
47C7
GOSUB to 4759H to write the select latch and wait until the controller is idle.
47CA
LD B,80H 06 80
Motor start delay: B = 80H, about half a second through 4CEDH. (Optional zap 004 changes it to FFH; it is not applied.)
47CC
BIT 7,E CB 7B
Had the motors stopped?
47CE
Yes: GOSUB to 4CEDH to wait for them.
47D1
POP AF F1
Restore the same drive answer.
47D2
Same drive: JUMP to 47DDH.
47D4
LD A,(430CH) 3A 0C 43
A different drive: fetch its TSR byte.
47D7
RLCA 07
Move bit 7 (TI flag H) into the CARRY FLAG.
47D8
LD B,0CH 06 0C
Head settle delay: B = 0CH.
47DA
TI flag H: GOSUB to 4CEDH to wait.
47DD
XOR A AF
Success: clear Register A.
47DE
POP BC C1
Restore Register Pair BC.
47DF
POP DE D1
Restore Register Pair DE.
47E0
POP HL E1
Restore Register Pair HL.
47E1
OR A B7
Set the flags: Z for 00H, NZ for an error code.
47E3H - Short Delay and Read the Status
Waits a few microseconds (the controller needs time after a command before its status is valid), then reads the status. 47E8H only reads it.
47E3
LD A,06H 3E 06
Self-Modifying CodeLoad Register A with the loop count, 6 x SYSTEM option BJ (stored at
4D9EH).
47E5
DEC A 3D
Loop Start
Count down.
47E6
Loop End
LOOP BACK to 47E5H until 0.
47E8
LD A,(37ECH) 3A EC 37
Read the status register at 37ECH.
47ECH - Test for a Mounted Diskette
445EH comes here (manual 3.30). Selects the drive in Register A, then waits for the index pulse bit to change, which shows that a diskette is in the drive and turning. On exit the Z FLAG is set, or the NZ FLAG with error code 08H (DEVICE NOT AVAILABLE) or 20H.
47EC
GOSUB to 4776H to select the drive.
47EF
RET NZ C0
Bad drive: RETurn with error 20H.
47F0
PUSH HL E5
Save Register Pair HL.
47F1
PUSH DE D5
Save Register Pair DE.
47F2
PUSH BC C5
Save Register Pair BC.
47F3
LD DE,0000H 11 00 00
Self-Modifying CodeLoad Register Pair DE with the time-out count, 2400H x SYSTEM option BJ (stored at
4DAAH).
47F6
LD HL,37ECH 21 EC 37
Point HL to the status register.
47F9
LD B,(HL) 46
Keep the first status in Register B.
47FA
LD A,(HL) 7E
Loop Start
Read the status.
47FB
XOR B A8
Compare it with the first one.
47FC
AND 02H E6 02
Look only at bit 1, the index pulse.
47FE
It changed: a diskette is turning. JUMP to 47DDH to return with the Z FLAG set.
4800
DEC DE 1B
Count down the time-out.
4803
Loop End
LOOP BACK to 47FAH until the count runs out.
4805
LD A,08H 3E 08
Load Register A with error code 08H (DEVICE NOT AVAILABLE).
4807
JUMP to 47DEH to return the error.
4809H - Allocate, and Find the Sector for NEXT
444BH comes here (manual 3.26). The part from 4810H is used by every read and write: it turns the FCB's NEXT position into a sector number on the diskette. It looks through the extents kept in the FCB, then through the file's directory entries (FPDE and FXDEs), and when the sector lies past the file's last granule it calls SYS2 to allocate more (a read gets error 3EH instead). On exit DE = the sector number, HL = the FCB's buffer and the Z FLAG is set; errors leave through 49CDH.
4809
GOSUB to 4980H: the rest runs as a DOS function with IX = the FCB.
480C
Entry used by the write routines. GOSUB to 49B7H: the file's access level must allow writing (below 5).
480F
XOR A AF
Clear Register A: past the end of the file, allocate.
4810
LD (48BBH),A 32 BB 48
Entry with Register A = B6H from the read routine (4A21H). Store Register A as the offset of the JR at 48BAH: 00H lets the allocation run, B6H turns it into a jump to 4872H with error 3EH.
4813
Loop Start
GOSUB to 476EH to select the FCB's drive.
4816
Bad drive: JUMP to 4872H to leave with the error.
4818
GOSUB to 4968H: Register C = NEXT low, HL = NEXT middle and high, the relative sector.
481B
EX DE,HL EB
Put the relative sector into DE.
481C
LD A,(IX+00H) DD 7E 00
Fetch FCB+0.
481F
RRCA 0F
Rotate bit 0 out.
4820
RRCA 0F
Rotate bit 1 into the CARRY FLAG.
4821
Bit 1 set: NEXT is already a sector of the whole diskette. JUMP to 4853H.
4823
RRCA 0F
Rotate bit 2 into the CARRY FLAG.
4824
LD A,2DH 3E 2D
Load Register A with error code 2DH (BAD FCB DATA).
4826
Bit 2 set: JUMP to 4872H to leave with the error.
4828
EX DE,HL EB
Put the relative sector into HL.
4829
GOSUB to 4CB2H to divide by 5: HL = the granule within the file, Register A = the sector within the granule.
482C
LD C,0EH 0E 0E
Register C = 0EH (Register B is 0).
482E
EX DE,HL EB
Put the granule into DE.
482F
PUSH IX DD E5
Copy the FCB address from IX into HL.
4832
ADD HL,BC 09
Add 0EH: HL points to FCB+14, the first of the FCB's extents.
4833
PUSH AF F5
Save the sector within the granule.
4834
PUSH HL E5
Save the extent pointer.
4835
PUSH DE D5
Save the granule.
4836
LD A,08H 3E 08
Up to eight extents in the FCB.
4838
EX AF,AF' 08
Loop Start
Keep the extent count in AF'.
4839
LD A,(HL) 7E
Fetch the extent's lump number.
483A
INC A 3C
FFH (no more extents)?
483B
INC HL 23
Point HL to the extent's second byte.
483C
No more: JUMP to 4892H to look in the directory.
483E
LD A,(HL) 7E
Fetch the second byte: bits 5-7 the first granule in the lump, bits 0-4 the number of granules minus 1.
483F
GOSUB to 48E9H: subtract the extent's granule count from the granule (in HL). The CARRY FLAG is set if the granule is in this extent.
4842
Not in this extent: JUMP to 4875H.
4844
ADD HL,BC 09
Add the count back: HL = the granule's position in the extent.
4845
EX DE,HL EB
DE = that position, HL = the extent pointer.
4846
XOR (HL) AE
Keep bits 5-7 of the second byte (Register A held bits 0-4).
4847
RLCA 07
Rotate them down to bits 0-2 (three RLCAs).
484A
ADD A,E 83
Add the position: the granule within the lump.
484B
LD E,A 5F
Keep it in Register E.
484C
POP AF F1
Discard the saved granule.
484D
POP AF F1
Discard the saved extent pointer.
484E
POP AF F1
Restore the sector within the granule into Register A.
484F
DEC HL 2B
Point HL back to the extent's lump number.
4850
GOSUB to 4C7CH: DE = (lump x granules per lump + Register E) x 5 + Register A, the sector on the diskette.
4853
LD L,(IX+03H) DD 6E 03
Load HL with the FCB's buffer address (FCB+3). 4B0BH and ASPOOL/MAS call this part too; the display driver (4507H) uses it to fetch the cursor address from a device control block.
4856
LD H,(IX+04H) DD 66 04
Continue.
4859
XOR A AF
Clear Register A and set the Z FLAG.
485B
POP BC C1
The FPDE or FXDE has an FXDE link (FEH): discard the saved extent pointer.
485C
POP BC C1
Restore the granule count before this entry into Register Pair BC.
485D
POP HL E1
Restore the granule sought into HL.
485E
SBC HL,DE ED 52
Subtract the granules still to go (DE): HL = the granules in this entry.
4860
ADD HL,BC 09
Add the count before it: BC = the granules before the next entry.
4863
PUSH AF F5
Save the FXDE's DEC (Register A).
4864
GOSUB to 492FH to read the FXDE's directory sector. HL = the entry.
4867
Read error: JUMP to 4872H.
4869
LD A,FFH 3E FF
Self-Modifying Code
Load Register A with the DEC of the entry that pointed here (stored at 48A0H).
486B
INC HL 23
Point HL to the FXDE's byte 1, the DEC of the entry before it.
486C
CP (HL) BE
Does it point back?
486D
DEC HL 2B
Point HL back to byte 0.
486E
Yes: JUMP to 489FH to go on with this FXDE.
4870
LD A,2CH 3E 2C
Load Register A with error code 2CH (BAD DIRECTORY DATA).
4872
JUMP to 49CDH to leave the DOS function with the error.
4875
EX DE,HL EB
Point HL to the next extent.
4877
BIT 3,(IX+01H) DD CB 01 5E
Is FCB+1 bit 3 set (the FCB was opened by NEWDOS/80 version 2)?
487B
SCF 37
Set the CARRY FLAG.
487C
No: JUMP to 4824H to leave with error 2DH (BAD FCB DATA).
487E
EX AF,AF' 08
Fetch the extent count.
487F
CP 05H FE 05
Four extents looked at (count 5)?
4883
LD C,(HL) 4E
Load Register Pair BC with FCB+22 (16H): the number of granules before the extents kept at FCB+24.
4885
LD B,(HL) 46
Continue.
4886
INC HL 23
Point HL to FCB+24 (18H).
4887
POP DE D1
Fetch the granule sought.
4888
PUSH DE D5
Keep it on the stack.
4889
EX DE,HL EB
Put it into HL.
488A
SBC HL,BC ED 42
Subtract the granules before the second set of extents.
488C
EX DE,HL EB
Put the result into DE.
488D
The granule lies before them (in a directory entry not held in the FCB): JUMP to 4892H.
488F
DEC A 3D
Count the extent.
4890
Loop End
LOOP BACK to 4838H for the next extent.
4892
LD BC,0000H 01 00 00
Look in the directory. No granules counted yet.
4895
POP DE D1
Restore the granule sought into DE.
4896
GOSUB to 494BH to read the file's FPDE and check that it belongs to this FCB.
4899
Error: JUMP to 4867H to leave with it.
489B
LD A,(IX+07H) DD 7E 07
Load Register A with the FCB's DEC (FCB+7).
489F
POP AF F1
Restore the DEC of the entry being looked at.
48A0
LD (486AH),A 32 6A 48
Store it at 486AH, for the back link test of the next FXDE.
48A3
BIT 4,(HL) CB 66
Loop Start
Is the entry in use (bit 4)?
48A5
No: JUMP to 4870H to leave with error 2CH.
48A7
PUSH DE D5
Save the granules to go.
48A8
PUSH BC C5
Save the granules before this entry.
48A9
LD A,L 7D
Point HL to byte 22 (16H) of the entry, its first extent.
48AA
ADD A,16H C6 16
Continue.
48AD
PUSH HL E5
Save the extent pointer.
48AE
LD A,(HL) 7E
Loop Start
Fetch the lump number.
48AF
CP FEH FE FE
Compare it with FEH.
48B1
INC HL 23
Point HL to the second byte.
48B2
LD A,(HL) 7E
Fetch it.
48B3
INC HL 23
Point HL to the next extent.
48B4
Below FEH, a real extent: JUMP to 48C6H.
48B6
FEH, a link to an FXDE (Register A = its DEC): JUMP to 485BH.
48B8
LD A,3EH 3E 3E
FFH, the end of the extents: the granule is past the end of the file. Load Register A with error code 3EH (CAN'T EXTEND FILE VIA READ).
48BA
Self-Modifying Code
Its offset byte at 48BBH is 00H, so this falls through to 48BCH, or B6H for a read, which jumps to 4872H with the error.
48BC
POP AF F1
Discard the extent pointer.
48BD
LD A,64H 3E 64
Load Register A with code 64H (SYS2, function 3: allocate a granule to the file).
48BF
GOSUB to 49DDH to call SYS2.
48C2
POP BC C1
Restore the granules before this entry.
48C3
POP DE D1
Restore the granules to go.
48C4
Loop End
JUMP back to 48A3H to look at the entry again.
48C6
BIT 4,L CB 65
Past byte 31 of the entry (bit 4 of the pointer clear)?
48C8
Yes: JUMP to 4870H to leave with error 2CH.
48CA
GOSUB to 48E9H to subtract the extent's granule count.
48CD
EX DE,HL EB
Put the rest back into DE.
48CE
Loop End
Not in this extent: LOOP BACK to 48AEH.
48D0
POP BC C1
Found. Load Register Pair BC with the entry's extent pointer.
48D1
POP DE D1
Load Register Pair DE with the granules before this entry.
48D2
POP AF F1
Discard the granules to go.
48D3
POP HL E1
Restore the pointer to FCB+14 into HL.
48D4
POP AF F1
Discard the sector within the granule.
48D5
PUSH BC C5
Save the entry's extent pointer.
48D6
LD BC,0008H 01 08 00
Eight bytes.
48D9
LD A,D 7A
Are there granules before this entry?
48DB
No (it is the FPDE): JUMP to 48E2H to copy its extents to FCB+14.
48DD
ADD HL,BC 09
Point HL to FCB+22.
48DE
LD (HL),E 73
Store the granules before this entry there.
48E0
LD (HL),D 72
Continue.
48E1
INC HL 23
Point HL to FCB+24.
48E2
EX DE,HL EB
DE = the destination in the FCB.
48E3
POP HL E1
HL = the entry's extents.
48E4
LDIR ED B0
Copy the four extents into the FCB.
48E6
Loop End
JUMP back to 4813H to look through the FCB's extents again.
48E9
AND 1FH E6 1F
Keep the granule count minus 1 (bits 0-4).
48EB
LD C,A 4F
Register Pair BC = the count minus 1.
48EC
LD B,00H 06 00
Continue.
48EF
EX DE,HL EB
HL = the granule, DE = the extent pointer.
48F0
SBC HL,BC ED 42
Subtract the count. The CARRY FLAG is set if the granule is in the extent.
48F3H - Read a Directory Sector
Enter at 490AH to read directory sector A (0 = GAT, 1 = HIT, 2 and up = FDE sectors) of the current drive into 4200H, or at 48FDH for one attempt. Directory sectors carry the directory mark, so a good read returns controller error 06H; a sector without it gives error 31H (WRONG DISKETTE RECORD TYPE). If the read fails, the boot sector is read to find where the directory is (byte 2, the directory's lump), the drive's PDRIVE record is updated and the read is tried again. On exit the Z FLAG is set, or the NZ FLAG with error 11H (DIRECTORY READ ERROR). DE and BC are preserved.
48F3
LD A,(4202H) 3A 02 42
Fetch byte 2 of the boot sector: the lump where the directory starts.
48F6
LD HL,(4399H) 2A 99 43
Load HL with the address of the current drive's PDRIVE record.
48F9
LD (HL),A 77
Store it as byte 0 of the record.
48FA
LD A,(4930H) 3A 30 49
Load Register A with the directory sector wanted.
48FD
GOSUB to 4C74H to find its sector number (DE) and point HL to 4200H.
4900
GOSUB to 4630H to read it.
4903
An error: JUMP to 4907H.
4905
OR 31H F6 31
No error, so no directory mark: Register A = 31H.
4907
CP 06H FE 06
Error 06H, the directory mark, means success.
490A
PUSH DE D5
Save Register Pair DE.
490B
PUSH BC C5
Save Register Pair BC.
490C
GOSUB to 48FDH to read the sector.
4911
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H, the boot sector. The reset code enters here to read the GAT (
4EF5H).
4914
GOSUB to 4630H to read it into 4200H.
4917
Read: GOSUB to 48F3H to take the directory's lump from it and read the directory sector again.
491A
LD A,11H 3E 11
Load Register A with error code 11H (the flags tell whether it applies).
491C
POP BC C1
Restore Register Pair BC.
491D
POP DE D1
Restore Register Pair DE.
491FH - Write a Directory Sector
Enter at 491FH to write back the directory sector now in 4200H, or at 4922H with its number in Register A. The sector is written with the directory mark and the verify read. On exit the Z FLAG is set, or the NZ FLAG with error 12H (DIRECTORY WRITE ERROR).
491F
LD A,(4930H) 3A 30 49
Load Register A with the number of the directory sector in 4200H.
4922
PUSH DE D5
Save Register Pair DE.
4923
PUSH BC C5
Save Register Pair BC.
4924
GOSUB to 4C74H: DE = the sector number, HL = 4200H.
4927
OR H B4
Set the NZ FLAG (Register H is 42H): write with the directory mark.
4928
GOSUB to 4AB8H to write the sector with verify.
492B
LD A,12H 3E 12
Load Register A with error code 12H.
492FH - Read the Directory Sector of an Entry
Register A holds a DEC (bits 0-4 the FDE sector minus 2, bits 5-7 the entry in the sector). 492FH reads the sector only if it is not already in 4200H, 4936H always reads it, 4933H always reads the sector of the FCB's DEC (FCB+7). On exit HL points to the entry in 4200H and the Z FLAG is set.
492F
LD L,FFH 2E FF
Self-Modifying Code
Load Register L with the directory sector now in 4200H (the operand at 4930H is stored by 4C74H; FFH for none).
4933
LD A,(IX+07H) DD 7E 07
Load Register A with the FCB's DEC.
4936
LD L,FFH 2E FF
Register L = FFH: always read.
4938
PUSH AF F5
Save the DEC.
4939
AND 1FH E6 1F
Keep bits 0-4.
493B
INC A 3C
Add 2: the directory sector.
493D
CP L BD
Is it already in 4200H?
493E
No: GOSUB to 490AH to read it.
4941
POP HL E1
Restore the DEC into Register H.
4942
RET NZ C0
Read error: RETurn.
4943
LD A,E0H 3E E0
Keep bits 5-7 of the DEC.
4945
AND H A4
Times 32 (the bits are already in place): the entry's offset.
4946
LD L,A 6F
Register L = the offset.
4947
LD H,42H 26 42
HL = 4200H + the offset.
4949
CP A BF
Set the Z FLAG.
494BH - Read the FPDE of an Open FCB
Selects the FCB's drive and reads the directory entry of FCB+7. The entry must still belong to the file: it must be an FPDE in use, and its first extent must match the FCB's (unless the FCB has none yet). On exit HL points to the entry and the Z FLAG is set, or the NZ FLAG with Register A = the error (2DH BAD FCB DATA).
494B
GOSUB to 476EH to select the FCB's drive.
494E
Selected: GOSUB to 4933H to read the FCB's directory sector.
4951
RET NZ C0
Error: RETurn.
4952
PUSH HL E5
Save the entry's address.
4953
ADD A,16H C6 16
Add 22 (16H) to the entry's offset in Register A.
4955
LD L,A 6F
Point HL to the entry's first extent.
4956
LD A,(IX+0EH) DD 7E 0E
Fetch the FCB's first extent's lump number (FCB+14).
4959
CP (HL) BE
Are they equal?
495A
POP HL E1
Restore the entry's address.
495D
INC A 3C
Was the FCB's lump FFH (no extents yet)?
495E
No: JUMP to 4965H with the NZ FLAG set.
4960
LD A,(HL) 7E
Fetch the entry's flags.
4961
AND 90H E6 90
Keep bit 7 (FXDE) and bit 4 (in use).
4963
CP 10H FE 10
The Z FLAG is set for an FPDE in use.
4965
LD A,2DH 3E 2D
Load Register A with error code 2DH (the flags tell whether it applies).
4968H - Compare NEXT with EOF
Loads Register C with NEXT's low byte and HL with NEXT's middle and high bytes, and compares NEXT with EOF, highest byte first. The CARRY FLAG is set if NEXT is below EOF and the Z FLAG if they are equal.
4968
LD C,(IX+05H) DD 4E 05
Load Register C with NEXT, low byte (FCB+5).
496B
LD L,(IX+0AH) DD 6E 0A
Load Register L with NEXT, middle byte (FCB+10).
496E
LD H,(IX+0BH) DD 66 0B
Load Register H with NEXT, high byte (FCB+11).
4971
LD A,H 7C
Load Register A with the high byte.
4972
CP (IX+0DH) DD BE 0D
Compare it with EOF, high byte (FCB+13).
4975
RET NZ C0
Different: RETurn.
4976
LD A,L 7D
Load Register A with the middle byte.
4977
CP (IX+0CH) DD BE 0C
Compare it with EOF, middle byte (FCB+12).
497A
RET NZ C0
Different: RETurn.
497B
LD A,C 79
Load Register A with the low byte.
497C
CP (IX+08H) DD BE 08
Compare it with EOF, low byte (FCB+8).
4980H - Run the Rest of a Routine as a DOS Function
Every FCB routine starts with CALL 4980H, DE pointing to the FCB. If the FCB is not open, the routine returns at once with error 26H (FILE NOT OPEN). Otherwise the code after the CALL runs as a subroutine with IX = the FCB and IY = 4380H, and the stack pointer is saved at 49CEH so that any error can leave through 49CDH from any depth. On return all registers except AF are as they were on entry (the caller's AF ends up in AF').
4980
LD A,(DE) 1A
Fetch FCB+0.
4981
RLCA 07
Move bit 7 (open) into the CARRY FLAG.
4982
LD A,26H 3E 26
Load Register A with error code 26H (FILE NOT OPEN).
4984
Not open: JUMP to 4987H with it.
4986
XOR A AF
Open: Register A = 00H.
4987
EX AF,AF' 08
Keep it in AF'.
4988
EX (SP),HL E3
Swap HL with the return address: HL = the code after the CALL.
4989
LD (49A6H),HL 22 A6 49
Store it as the target of the CALL at 49A5H.
498C
POP HL E1
Restore HL. The stack now holds the caller's return address.
498D
PUSH IY FD E5
Save IY.
498F
PUSH HL E5
Save Register Pair HL.
4990
PUSH DE D5
Save Register Pair DE.
4991
PUSH BC C5
Save Register Pair BC.
4992
PUSH AF F5
Save Register Pair AF.
4993
PUSH DE D5
Save DE again,
4994
EX (SP),IX DD E3
and swap it with IX: IX = the FCB, the old IX is saved.
4997
LD HL,(49CEH) 2A CE 49
Load HL with the saved stack pointer of an outer DOS function, if any.
499A
EX (SP),HL E3
Save it and restore HL.
499B
LD (49CEH),SP ED 73 CE 49
Store the stack pointer at 49CEH for the error exit.
499F
LD IY,4380H FD 21 80 43
Point IY to 4380H.
49A3
EX AF,AF' 08
Fetch 00H or error 26H from AF'.
49A5
Self-Modifying Code
Yes: GOSUB to the code after the CALL 4980H (the address stored at 4989H).
49A8
POP HL E1
Restore the outer stack pointer.
49A9
LD (49CEH),HL 22 CE 49
Put it back at 49CEH.
49AC
EX AF,AF' 08
Keep the result (Register A and the flags) in AF'.
49AD
POP IX DD E1
Restore IX.
49AF
POP AF F1
Restore the caller's AF.
49B0
POP BC C1
Restore Register Pair BC.
49B1
POP DE D1
Restore Register Pair DE.
49B2
POP HL E1
Restore Register Pair HL.
49B3
POP IY FD E1
Restore IY.
49B5
EX AF,AF' 08
Swap the result back into AF.
49B6
RET C9
RETurn to the caller.
49B7H - Check the Access Level
The access level (FCB+1 bits 0-2) must be below Register B: 5 for a write (entry 49B7H), 6 for a read (entry 49B9H with B = 6). Otherwise the DOS function ends with error 25H (ILLEGAL ACCESS TRIED TO PROTECTED FILE).
49B7
LD B,05H 06 05
Load Register B with 5.
49B9
LD A,(IX+01H) DD 7E 01
Fetch FCB+1.
49BC
AND 07H E6 07
Keep the access level.
49BE
CP B B8
Compare it with Register B.
49BF
RET C D8
Allowed: RETurn.
49C0
LD A,25H 3E 25
Load Register A with error code 25H.
49C2
JUMP to 49CDH to leave with the error.
49C4
Check that NEXT is below EOF: GOSUB to 4968H.
49C7
RET C D8
Below: RETurn.
49C8
LD A,1CH 3E 1C
Load Register A with error code 1CH (END OF FILE ENCOUNTERED).
49CA
NEXT equals EOF: JUMP to 49CDH with it.
49CC
INC A 3C
NEXT is past EOF: error code 1DH (PAST END OF FILE).
49CDH - Leave a DOS Function with an Error
Register A holds the error code. The stack pointer saved by 4980H is restored, which throws away everything the function pushed, and the function returns to its caller with the NZ FLAG set. SYS2 and SYS3 jump here too.
49CD
LD SP,0000H 31 00 00
Self-Modifying Code
Load the stack pointer saved at 49CEH by 4980H.
49D0
OR A B7
Set the NZ FLAG.
49D1
JUMP to 49A8H to return from the DOS function.
49D3
A return address: SYS1, SYS7, SYS9 and SYS14 push a word holding an RST 28H code (high byte) and a sub-function (low byte), then 49D3H, and jump to a function. When the function returns here with the NZ FLAG set, JUMP to 4409H to leave with the error in Register A.
49D6
XOR A AF
The same without the error test (SYS1): clear Register A and set the Z FLAG.
49D7
The same inside a DOS function (SYS3 uses it after 4A62H): with the NZ FLAG set, JUMP to 49CDH to leave the DOS function with the error.
49D9
EX (SP),HL E3
Swap HL with the word now on top of the stack (the RET that came here removed the return address).
49DA
LD A,H 7C
Register A = its high byte, the RST 28H code.
49DB
LD C,L 4D
Register C = its low byte, the sub-function.
49DC
POP HL E1
Restore HL, dropping the word.
49DD
RST 28H EF
Call the overlay function in Register A (with the sub-function in Register C). Because the dispatcher throws away the RST's return address, CALL 49DDH works as a call of the overlay function that returns to the caller; SYS0, SYS6 and SYS9 use it that way.
49DEH - Move a Logical Record
Called at the start of the READ (with the CARRY FLAG set) and WRITE (CARRY FLAG clear) routines. In sector mode (FCB+1 bit 7 clear) it returns at once. In record mode it replaces the rest of the routine: LRL bytes (0 = 256) are moved one by one between the caller's buffer at HL and the file, through the byte routine at 4AEDH, and the DOS function returns from here.
49DE
BIT 7,(IX+01H) DD CB 01 7E
Record mode?
49E2
RET Z C8
No: RETurn to the sector routine.
49E3
POP DE D1
Drop the return address: the DOS function returns from here.
49E4
LD B,(IX+09H) DD 46 09
Load Register B with the LRL.
49E7
PUSH AF F5
Loop Start
Save the read or write flag.
49E8
PUSH HL E5
Save the buffer pointer.
49E9
PUSH BC C5
Save the count.
49EA
LD C,(HL) 4E
Load Register C with the caller's byte (used when writing).
49EB
GOSUB to 4AEDH to read or write one byte.
49EE
An error: JUMP to 49CDH to leave with it.
49F0
LD E,A 5F
Keep the byte read.
49F1
POP BC C1
Restore the count.
49F2
POP HL E1
Restore the buffer pointer.
49F3
POP AF F1
Restore the read or write flag.
49F4
Writing: JUMP to 49F7H.
49F6
LD (HL),E 73
Reading: store the byte in the caller's buffer.
49F7
INC HL 23
Point HL to the next byte.
49F8
Loop End
DECrement Register B and LOOP BACK to 49E7H.
49FA
XOR A AF
Done: clear Register A and set the Z FLAG.
49FCH - READ
4436H comes here (manual 3.19). In sector mode the sector at NEXT is read into the FCB's buffer and NEXT is advanced by 256, also after error 06H (the sector has the directory mark), which is still returned.
49FC
GOSUB to 4980H: run as a DOS function.
49FF
SCF 37
Set the CARRY FLAG: reading.
4A00
GOSUB to 49DEH, which handles record mode.
4A03
GOSUB to 4A19H to read the sector.
4A08
CP 06H FE 06
Error 06H?
4A0A
RET NZ C0
Any other error: RETurn with it; NEXT is not advanced.
4A0B
INC (IX+0AH) DD 34 0A
Count NEXT's middle byte up (NEXT + 256).
4A0E
No carry: JUMP to 4A13H.
4A10
INC (IX+0BH) DD 34 0B
Count the high byte up.
4A13
SET 5,(IX+01H) DD CB 01 EE
Set FCB+1 bit 5: the buffer does not hold the sector at NEXT.
4A17
OR A B7
Set the flags from Register A: Z for 00H, NZ with error 06H.
4A19
LD B,06H 06 06
Read the sector at NEXT into the FCB's buffer. Register B = 6.
4A1B
GOSUB to 49B9H: the access level must allow reading.
4A1E
GOSUB to 49C4H: NEXT must be below EOF.
4A21
LD A,B6H 3E B6
Register A = B6H: a sector past the file's last granule is error 3EH.
4A23
GOSUB to 4810H to find the sector: DE = its number, HL = the buffer.
4A26
GOSUB to 4630H to read it.
4A29
RES 5,(IX+01H) DD CB 01 AE
Clear FCB+1 bit 5: the buffer holds the sector at NEXT.
4A2D
RES 4,(IX+01H) DD CB 01 A6
Clear FCB+1 bit 4: the buffer has no changes waiting.
4A31
RET C9
RETurn with the flags of the read.
4A32H - WRITE
443CH (write with verify, manual 3.21) enters at 4A32H and 4439H (WRITE, manual 3.20) at 4A36H. In sector mode the FCB's buffer is written to the sector at NEXT, NEXT is advanced by 256 when its low byte is 0, and EOF is set to NEXT if NEXT is past EOF or if FCB+1 bit 6 is clear.
4A32
LD A,F6H 3E F6
With verify: Register A = F6H, the opcode of OR n.
4A36
LD A,E6H 3E E6
Without verify: Register A = E6H, the opcode of AND n.
4A38
LD (4A8BH),A 32 8B 4A
Store the opcode at 4A8BH.
4A3B
GOSUB to 4980H: run as a DOS function.
4A3E
GOSUB to 49DEH, which handles record mode.
4A41
GOSUB to 4A67H to write the buffer.
4A44
RET NZ C0
Error: RETurn with it.
4A45
LD A,(IX+05H) DD 7E 05
Fetch NEXT, low byte.
4A49
Yes: GOSUB to 4A0BH to advance NEXT by 256.
4A4C
GOSUB to 4968H to compare NEXT with EOF.
4A4F
NEXT is at or past EOF: JUMP to 4A57H.
4A51
BIT 6,(IX+01H) DD CB 01 76
NEXT is below EOF. Is FCB+1 bit 6 set (EOF only moves forward)?
4A55
Yes: JUMP to 4A60H and keep EOF.
4A57
LD (IX+08H),C DD 71 08
EOF = NEXT: store the low byte (FCB+8),
4A5A
LD (IX+0CH),L DD 75 0C
the middle byte (FCB+12)
4A5D
LD (IX+0DH),H DD 74 0D
and the high byte (FCB+13).
4A60
XOR A AF
Clear Register A and set the Z FLAG.
4A62
BIT 4,(IX+01H) DD CB 01 66
Write the buffer only if it has changes waiting (FCB+1 bit 4). Used before the FCB moves to another sector.
4A66
RET Z C8
No changes: RETurn with the Z FLAG set.
4A67
GOSUB to 480CH to check the access level and find the sector at NEXT, allocating it if needed. DE = its number, HL = the buffer.
4A6A
BIT 5,(IX+02H) DD CB 02 6E
Has this FCB already marked the file updated (FCB+2 bit 5)?
4A70
BIT 1,(IX+00H) DD CB 00 4E
Does the FCB address whole-diskette sectors (FCB+0 bit 1)?
4A74
Yes: no directory entry to update; JUMP to 4A88H.
4A76
PUSH HL E5
Save the buffer address.
4A77
GOSUB to 494BH to read the file's FPDE.
4A7A
Error: JUMP to 4A7FH (the directory is not written).
4A7C
INC HL 23
Point HL to the FPDE's byte 1.
4A7D
SET 5,(HL) CB EE
Set bit 5: the file has been updated.
4A7F
GOSUB to 491FH to write the directory sector back.
4A82
POP HL E1
Restore the buffer address.
4A83
RET NZ C0
Error: RETurn with it.
4A84
SET 5,(IX+02H) DD CB 02 EE
Remember in FCB+2 bit 5 that the FPDE has been marked.
4A88
LD A,(IX+01H) DD 7E 01
Self-Modifying Code
Fetch FCB+1. The VERIFY command (SYS3) replaces these three bytes with NOP / LD A,0FFH to verify every write, or puts them back.
4A8B
AND 90H E6 90
Self-Modifying Code
Keep bit 7 (record mode) and bit 4 (the buffer was filled by the byte or record routines): those writes are verified. The opcode is stored at 4A38H: for 443CH it is OR 90H, which always gives a non-zero value, so the write is always verified.
4A8D
BIT 0,(IX+00H) DD CB 00 46
Does FCB+0 bit 0 ask for the directory mark? (NZ FLAG = yes.)
4A91
GOSUB to 4AB8H to write the sector (Register A non-zero = verify).
4A94
RET NZ C0
Error: RETurn with it.
4A95
XOR A AF
Clear Register A.
4A96
JUMP to 4A2DH to clear FCB+1 bit 4 and return.
4A98H - Write a Byte to a File
The write half of the byte routine at 4AEDH, entered with the byte in Register C and the Z FLAG set if the FCB's buffer holds the sector at NEXT. The sector is read in first unless NEXT is at EOF on a sector boundary. The byte is stored at NEXT and NEXT is advanced; when the buffer is full it is written with verify, and EOF is brought up to NEXT.
4A98
The buffer holds the sector: JUMP to 4AACH.
4A9A
PUSH BC C5
Save the byte.
4A9B
GOSUB to 480CH to check the access level and find (or allocate) the sector at NEXT.
4A9E
GOSUB to 4968H to compare NEXT with EOF (Register A = NEXT low).
4AA1
Not at EOF: JUMP to 4AA4H to read the sector.
4AA3
OR A B7
At EOF: read the sector only if NEXT's low byte is not 0.
4AA4
GOSUB to 4A21H to read the sector into the buffer.
4AA7
POP BC C1
Restore the byte.
4AA8
RET NZ C0
Error: RETurn with it.
4AA9
GOSUB to 4A29H: the buffer holds the sector, with no changes yet.
4AAC
GOSUB to 4B0BH: HL = the byte's place in the buffer, NEXT's low byte is counted up. The Z FLAG is set if it went round to 0.
4AAF
LD (HL),C 71
Store the byte.
4AB0
SET 4,(IX+01H) DD CB 01 E6
Set FCB+1 bit 4: the buffer has changes waiting.
4AB4
The buffer is full: JUMP to 4A41H to write it, advance NEXT and set EOF.
4AB6
JUMP to 4A4CH to bring EOF up to NEXT.
4AB8H - Write a Sector, Verify and Retry
DE = the sector number, HL = the buffer. Register A non-zero asks for a verify read after the write, and the NZ FLAG asks for the directory mark. When the verify read fails, the write is repeated up to SYSTEM option AW times. On exit the Z FLAG is set or Register A holds the error.
4AB8
LD C,A 4F
Keep the verify flag in Register C.
4AB9
LD B,03H 06 03
Self-Modifying CodeLoad Register B with the number of write tries, SYSTEM option AW (stored at
4D71H).
4ABB
Directory mark wanted: JUMP to 4ACAH.
4ABD
Loop Start
GOSUB to 4640H to write the sector.
4AC0
RET NZ C0
Write error: RETurn with it.
4AC3
Yes: GOSUB to 4634H for the verify read.
4AC6
RET Z C8
Good (or no verify): RETurn.
4AC7
Loop End
DECrement Register B and LOOP BACK to 4ABDH.
4AC9
RET C9
RETurn with the verify error.
4ACA
Loop Start
GOSUB to 463CH to write the sector with the directory mark.
4ACD
RET NZ C0
Write error: RETurn with it.
4AD1
GOSUB to 4634H for the verify read.
4AD4
GOSUB to 4903H: error 06H (the directory mark was read back) means success.
4AD7
RET Z C8
Good: RETurn.
4AD8
Loop End
DECrement Register B and LOOP BACK to 4ACAH.
4ADA
RET C9
RETurn with the error.
4ADBH - Device I/O Through ROUTE or an FCB
Reached through 4033H when the ROM's dispatcher finds that the type byte of the control block at DE does not match the request in Register B (01H input, 02H output). A type byte of C0H marks a device that ROUTE has redirected: the ROUTE list is searched for it. Anything else is taken to be an FCB, and one byte is read from or written to the file (manual 3.38 and 3.39); this is how 0013H and 001BH work with disk files.
4ADB
LD HL,0000H 21 00 00
Self-Modifying CodeLoad HL with the first ROUTE entry (0000H for none). The operand at 4ADCH is stored by
4EB5H and by the ROUTE command (SYS14).
4ADE
LD A,(DE) 1A
Fetch the type byte.
4ADF
CP C0H FE C0
C0H, a routed device?
4AE1
Yes: JUMP to 4B40H to search the ROUTE list. (Zap 020 changed the offset.)
4AE3
An FCB: GOSUB to 4980H to run the rest as a DOS function.
4AE6
SET 7,(IX+01H) DD CB 01 FE
Set FCB+1 bit 7: record mode.
4AEA
LD A,B 78
Load Register A with the request.
4AEB
CP 02H FE 02
Set the CARRY FLAG for input (01H).
4AED
BIT 5,(IX+01H) DD CB 01 6E
Entry from 49EBH. Does the buffer hold the sector at NEXT (FCB+1 bit 5 clear, Z FLAG)?
4AF1
Output: JUMP to 4A98H.
4AF3
Input, and the buffer is empty: GOSUB to 4A19H to read the sector.
4AF6
RET NZ C0
Error: RETurn with it.
4AF7
GOSUB to 49C4H: NEXT must be below EOF.
4AFA
GOSUB to 4B0BH: HL = the byte, NEXT's low byte counted up.
4AFD
Still in the same sector: JUMP to 4B08H.
4AFF
PUSH HL E5
The sector is used up. Save the byte's address.
4B00
GOSUB to 4A62H to write the buffer if it has changes waiting.
4B03
POP HL E1
Restore the byte's address.
4B04
RET NZ C0
Error: RETurn with it.
4B05
GOSUB to 4A0BH to advance NEXT by 256 and mark the buffer empty.
4B08
LD A,(HL) 7E
Fetch the byte.
4B09
CP A BF
Set the Z FLAG.
4B0B
GOSUB to 4853H: HL = the buffer, Register A = 00H.
4B0E
LD E,(IX+05H) DD 5E 05
Register E = NEXT's low byte.
4B11
LD D,A 57
Register D = 0.
4B12
ADD HL,DE 19
HL = the byte's place in the buffer.
4B13
INC (IX+05H) DD 34 05
Count NEXT's low byte up (the Z FLAG is set if it went round to 0).
4B17H - Search the ROUTE List
HL points to a ROUTE entry, DE to the control block the I/O was aimed at, Register B holds the request and Register C the output character. Every entry for this control block gets the request: each is passed to the target device's driver through the ROM at 03D4H (which does CP 02H and jumps to the driver named at IX+1). An output goes to every target; an input returns the first character received. This version is from zap 020.
4B17
LD A,(HL) 7E
Loop Start
Fetch the entry's control block address, low byte.
4B18
CP E BB
Does it match Register E?
4B19
INC HL 23
Point HL to the high byte.
4B1C
LD A,(HL) 7E
Fetch the high byte.
4B1D
CP D BA
Does it match Register D?
4B1E
INC HL 23
Point HL to the saved type byte.
4B1F
Not this device: JUMP to 4B3BH.
4B21
PUSH HL E5
Save the entry pointer.
4B22
PUSH DE D5
Save the control block address.
4B23
PUSH BC C5
Save the request and character.
4B24
LD A,(HL) 7E
Fetch the device's original type byte.
4B25
AND B A0
Keep the request bit (Register A is tested by the ROM's CP 02H).
4B26
INC HL 23
Point HL to byte 5 of the entry.
4B29
LD E,(HL) 5E
Load Register Pair DE with the target control block.
4B2B
LD D,(HL) 56
Continue.
4B2C
PUSH DE D5
Copy it into IX.
4B2D
POP IX DD E1
Continue.
4B2F
CALL 03D4H CD D4 03
GOSUB to the ROM at 03D4H (in
03C2H) to run the target's driver.
4B32
POP BC C1
Restore the request and character.
4B33
POP DE D1
Restore the control block address.
4B34
POP HL E1
Restore the entry pointer.
4B35
BIT 0,B CB 40
Input (bit 0)?
4B37
Output: JUMP to 4B3BH to send it to the next target too.
4B39
OR A B7
Input: was a character received?
4B3A
RET NZ C0
Yes: RETurn with it.
4B3B
INC HL 23
Point HL to the link to the next entry.
4B3C
LD A,(HL) 7E
Fetch its low byte.
4B3E
LD H,(HL) 66
Fetch its high byte.
4B3F
LD L,A 6F
HL = the next entry.
4B40
LD A,H 7C
Is it 0000H?
4B42
Loop End
No: LOOP BACK to 4B17H.
4B44
End of the list: JUMP to 4CF8H.
4B47H - Position an FCB
The positioning vectors of the manual (sections 3.22-3.27) come here. Each works out a new NEXT in Registers H (high), L (middle) and C (low). If the new NEXT is in another sector, the buffer is written first if it has changes waiting and is marked empty. Except for 443FH and 4448H, FCB+1 bit 6 is set, so that later writes do not pull EOF back.
4B47
444EH, position to the byte address in H, L and C: GOSUB to 4980H to run as a DOS function.
4B4C
443FH, position to the start of the file: GOSUB to 4980H.
4B4F
LD H,A 67
Register A is 00H: H = 0,
4B52
JUMP to 4B90H: always write the buffer if needed and mark it empty.
4B54
4448H, position to EOF: GOSUB to 4980H.
4B57
LD C,(IX+08H) DD 4E 08
Register C = EOF, low byte (FCB+8).
4B5A
LD L,(IX+0CH) DD 6E 0C
Register L = EOF, middle byte (FCB+12).
4B5D
LD H,(IX+0DH) DD 66 0D
Register H = EOF, high byte (FCB+13).
4B62
4445H, position back one record: GOSUB to 4980H.
4B65
GOSUB to 4968H: C, L and H = NEXT.
4B68
XOR A AF
Clear Register A.
4B69
SUB (IX+09H) DD 96 09
Subtract the LRL.
4B6C
ADD A,C 81
Add NEXT's low byte: the CARRY FLAG is set if the low byte did not go below 0 (with an LRL of 0, meaning 256, it never is).
4B6D
LD C,A 4F
Store the new low byte.
4B6E
No borrow: JUMP to 4B80H. (Zap 062 changed the offset so that bit 6 gets set.)
4B70
DEC HL 2B
Borrow: step the middle and high bytes back by one.
4B71
JUMP to 4B80H. (Also changed by zap 062.)
4B73
4442H, position to record BC: GOSUB to 4980H.
4B76
LD H,B 60
HL = the record number.
4B78
LD A,(IX+09H) DD 7E 09
Load Register A with the LRL.
4B7B
OR A B7
Is it 0 (256)?
4B7C
LD C,A 4F
Register C = the LRL (00H for 256: then NEXT = record x 256 with HL as it is).
4B7D
Otherwise GOSUB to 4C9DH to multiply: H, L and C = record x LRL.
4B80
SET 6,(IX+01H) DD CB 01 F6
Set FCB+1 bit 6: EOF only moves forward.
4B84
LD A,H 7C
Is the new NEXT's high byte the same as the old one (FCB+11)?
4B85
CP (IX+0BH) DD BE 0B
Continue.
4B8A
LD A,L 7D
And the middle byte (FCB+10)?
4B8B
CP (IX+0AH) DD BE 0A
Continue.
4B8E
The same sector: JUMP to 4BA1H to change only the low byte.
4B90
PUSH HL E5
Save the new middle and high bytes.
4B91
PUSH BC C5
Save the new low byte.
4B92
GOSUB to 4A62H to write the buffer if it has changes waiting.
4B95
POP BC C1
Restore the new low byte.
4B96
POP HL E1
Restore the middle and high bytes.
4B97
RET NZ C0
Error: RETurn with it.
4B98
GOSUB to 4A13H to mark the buffer empty (FCB+1 bit 5).
4B9B
LD (IX+0AH),L DD 75 0A
Store NEXT's middle byte,
4B9E
LD (IX+0BH),H DD 74 0B
and its high byte.
4BA1
LD (IX+05H),C DD 71 05
Store NEXT's low byte.
4BA4
XOR A AF
Clear Register A and set the Z FLAG. 4BA4H is also the driver of the NL device (see
4CFCH): it returns 00H for input and throws output away.
4BA6H - Display or Print a Message
4467H (display, manual 3.33) enters at 4BA6H and 446AH (print, manual 3.34) at 4BBCH. The message at HL is sent through the ROM's output routine at 001BH up to and including a 0DH, or up to but not including a 03H. HL and DE are preserved.
4BA6
PUSH DE D5
Save Register Pair DE.
4BA7
LD DE,401DH 11 1D 40
Point DE to the display's control block at 401DH.
4BAA
PUSH HL E5
Save the message address.
4BAB
LD A,(HL) 7E
Loop Start
Fetch a byte.
4BAC
CP 03H FE 03
Is it 03H, the end of the message?
4BB0
GOSUB to the ROM at 001BH to send it to the device at DE.
4BB3
LD A,(HL) 7E
Fetch the byte again.
4BB4
CP 0DH FE 0D
Was it 0DH?
4BB6
INC HL 23
Point HL to the next byte.
4BB7
Loop End
No: LOOP BACK to 4BABH.
4BB9
POP HL E1
Restore the message address.
4BBA
POP DE D1
Restore Register Pair DE.
4BBC
PUSH DE D5
Print: save Register Pair DE.
4BBD
LD DE,4025H 11 25 40
Point DE to the printer's control block at 4025H.
4BC2H - RST 28H Dispatcher
RST 28H comes here through 400CH with a function code in Register A. Codes below 20H (function 0) are sent to the BREAK hook at 4312H. Any other code names a system file by its directory slot (bits 0-4) and a function in it (bits 5-7). If that file is not the overlay now in 4D00H-51FFH, its directory entry is read from drive 0, and it is loaded through the FCB at 43CEH; a system file that cannot be found gives error 2EH (SYSTEM PROGRAM NOT FOUND), or a HALT if the missing file is SYS4, the error message module. The overlay is then called at its transfer address (4D00H for all of them) with AF, BC, DE and HL as they were at the RST. The return address the RST pushed is thrown away, so the overlay returns to whoever called the routine that executed the RST.
4BC2
INC SP 33
Throw away the return address pushed by the RST.
4BC4
CP 20H FE 20
Is the code below 20H?
4BC6
Yes (BREAK): JUMP to 4312H.
4BC9
PUSH HL E5
Save Register Pair HL.
4BCA
PUSH DE D5
Save Register Pair DE.
4BCB
PUSH BC C5
Save Register Pair BC.
4BCC
PUSH AF F5
Save Register Pair AF.
4BCD
LD HL,4369H 21 69 43
Point HL to the DOS flags at 4369H.
4BD0
SET 6,(HL) CB F6
Set bit 6: an overlay function is running (the key combinations are ignored).
4BD2
LD HL,45BEH 21 BE 45
Point HL to 45BEH.
4BD5
LD (HL),00H 36 00
Store a NOP there, in case the keyboard driver left its RET in place.
4BD7
EI FB
Enable interrupts.
4BD8
AND 1FH E6 1F
Keep bits 0-4 of the code: the overlay's directory slot.
4BDA
LD HL,4317H 21 17 43
Point HL to the number of the overlay now loaded, 4317H.
4BDD
CP (HL) BE
Is it this one?
4BDE
Yes: JUMP to 4C19H to call it.
4BE0
LD (HL),A 77
Store the new number.
4BE1
AND 07H E6 07
Keep bits 0-2: the directory sector minus 2.
4BE3
LD C,A 4F
Keep them in Register C.
4BE4
XOR A AF
Clear Register A.
4BE5
LD (43D8H),A 32 D8 43
Clear NEXT of the load FCB (43D8H).
4BE8
GOSUB to 4776H to select drive 0.
4BEB
LD A,(HL) 7E
Fetch the overlay number.
4BEC
SUB C 91
Subtract the sector bits, leaving the file's position in the sector (bits 3-4).
4BED
RLCA 07
Move it to bits 5-6 (two RLCAs).
4BEF
ADD A,C 81
Add the sector bits: the DEC of the file's directory entry.
4BF0
GOSUB to 4936H to read the entry. HL = the entry.
4BF3
Error: JUMP to 4C0EH.
4BF5
BIT 6,(HL) CB 76
Is it a system file (bit 6)?
4BF9
ADD A,16H C6 16
Add 22 (16H) to the entry's offset.
4BFB
LD L,A 6F
Point HL to the first extent.
4BFC
LD E,(HL) 5E
Fetch it into Register Pair DE.
4BFE
LD D,(HL) 56
Continue.
4BFF
LD (43DCH),DE ED 53 DC 43
Store it as the load FCB's first extent (43DCH).
4C03
LD HL,43CEH 21 CE 43
Point HL to the load FCB at 43CEH.
4C06
GOSUB to 4C28H to load the file. HL = its transfer address.
4C09
LD (4C1EH),HL 22 1E 4C
Store the transfer address as the target of the CALL at 4C1DH.
4C0C
Loaded: JUMP to 4C19H.
4C0E
LD A,(4317H) 3A 17 43
Load Register A with the overlay number.
4C11
CP 06H FE 06
Is it SYS4 (06H)?
4C13
LD A,2EH 3E 2E
Load Register A with error code 2EH (SYSTEM PROGRAM NOT FOUND).
4C15
Not SYS4: JUMP to 4409H to report the error.
4C18
HALT 76
SYS4 itself is missing: HALT.
4C19
POP AF F1
Restore Register Pair AF, the code.
4C1A
POP BC C1
Restore Register Pair BC.
4C1B
POP DE D1
Restore Register Pair DE.
4C1C
POP HL E1
Restore Register Pair HL.
4C1D
Self-Modifying Code
GOSUB to the overlay's transfer address (stored at 4C09H).
4C21
LD HL,4369H 21 69 43
Point HL to the DOS flags.
4C24
RES 6,(HL) CB B6
Clear bit 6: no overlay function is running.
4C28H - Load a Program File
Loads the load module file of the open FCB at HL into memory and returns its transfer address in HL with the Z FLAG set. The file is read a sector at a time into 4200H. Record type 01H is a load block (length, two address bytes, data), 02H is the transfer address (it ends the load), and any other type up to 1FH is skipped. Errors: 22H (LOAD FILE FORMAT ERROR) for a type above 1FH, 24H (TRIED TO LOAD READ ONLY MEMORY) if a loaded byte does not read back, or the read error. Also called by SYS2.
4C28
LD (4C6AH),HL 22 6A 4C
Store the FCB address as the operand at 4C6AH.
4C2B
LD DE,42FFH 11 FF 42
Point DE to 42FFH, so that the first fetch reads a sector.
4C2E
Loop Start
GOSUB to 4C65H to fetch the record type.
4C31
LD C,A 4F
Keep it in Register C.
4C32
LD A,1FH 3E 1F
Load Register A with 1FH.
4C34
CP C B9
Compare it with the type.
4C35
LD A,22H 3E 22
Load Register A with error code 22H.
4C37
RET C D8
Above 1FH: RETurn with the error.
4C38
GOSUB to 4C65H to fetch the record length.
4C3B
LD B,A 47
Keep it in Register B.
4C3C
GOSUB to 4C65H to fetch the first byte of the record.
4C3F
LD L,A 6F
Register L = that byte.
4C40
LD H,C 61
Register H = the type.
4C45
No: JUMP to 4C61H to skip the record. The bytes are stored at HL, an address in the ROM (H is the type), where the stores do nothing, and the read-back check is ignored because Register C is not 0.
4C47
Transfer address: GOSUB to 4C65H to fetch its high byte.
4C4A
LD H,A 67
HL = the transfer address.
4C4B
XOR A AF
Clear Register A and set the Z FLAG.
4C4D
Load block: GOSUB to 4C65H to fetch the address's high byte.
4C50
LD H,A 67
HL = the load address.
4C51
DEC B 05
The length counts the two address bytes: subtract them.
4C53
Loop Start
GOSUB to 4C65H to fetch a data byte.
4C56
LD (HL),A 77
Store it.
4C57
CP (HL) BE
Does it read back?
4C58
INC HL 23
Point HL to the next address.
4C5B
LD A,24H 3E 24
Load Register A with error code 24H.
4C5D
INC C 0C
Is Register C 0 (a load block)?
4C5F
Yes: JUMP to 4CC3H to return the error.
4C61
Loop End
DECrement Register B and LOOP BACK to 4C53H.
4C63
Loop End
JUMP back to 4C2EH for the next record.
4C65
INC E 1C
Fetch the next byte: point DE to it.
4C66
LD A,(DE) 1A
Fetch it.
4C67
RET NZ C0
Still in the sector: RETurn.
4C68
PUSH DE D5
The sector is used up: save the pointer.
4C69
LD DE,0000H 11 00 00
Self-Modifying Code
Point DE to the FCB (stored at 4C28H).
4C6C
GOSUB to 4436H to read the next sector into 4200H.
4C6F
POP DE D1
Restore the pointer (4200H).
4C70
Error: JUMP to 4C9BH, which drops this call's return address, so that 4C28H returns the error.
4C72
LD A,(DE) 1A
Fetch the first byte of the new sector.
4C74H - Sector Number of a Directory Sector
Register A holds a directory sector (0 = GAT). It is stored at 4930H as the sector now in 4200H, and DE is loaded with its sector number on the current drive's diskette: (the directory's lump x granules per lump) x 5 + Register A. HL is set to 4200H. 4C7CH is the general entry, used by 4850H: Register L holds a lump, Register E a granule in the lump and Register A a sector in the granule.
4C74
LD (4930H),A 32 30 49
Store the directory sector at 4930H.
4C77
LD E,00H 1E 00
No granule offset.
4C79
LD HL,(4399H) 2A 99 43
Point HL to the current drive's PDRIVE record, whose byte 0 is the directory's lump.
4C7C
LD C,A 4F
Keep the sector in Register C.
4C7D
LD L,(HL) 6E
Load Register L with the lump.
4C7E
LD A,(430FH) 3A 0F 43
Load Register A with the granules per lump from 430FH.
4C81
GOSUB to 4C92H: HL = lump x granules per lump.
4C84
LD B,A 47
Register B = 0 (the high byte of the product).
4C85
LD D,A 57
Register D = 0.
4C86
ADD HL,DE 19
Add the granule offset in Register E.
4C87
LD A,05H 3E 05
Five sectors per granule.
4C89
GOSUB to 4C94H: HL = granule x 5.
4C8C
ADD HL,BC 09
Add the sector (Register Pair BC).
4C8D
EX DE,HL EB
DE = the sector number.
4C8E
LD HL,4200H 21 00 42
HL = 4200H, the sector buffer.
4C92H - Multiply and Divide
4C92H: HL = L x A. 4C94H: HL x A, with the result in A (high byte), H and L. 4C9DH: HL x A with the result in H (high), L and C (low), used for record x LRL. 4CB2H divides HL by 5 and 4CB4H by Register A: the quotient in HL, the remainder in Register A. Used by several overlays.
4C92
LD H,00H 26 00
Register H = 0.
4C94
PUSH BC C5
Save Register Pair BC.
4C95
GOSUB to 4C9DH to multiply.
4C98
LD A,H 7C
Register A = the high byte.
4C99
LD H,L 65
Register H = the middle byte.
4C9A
LD L,C 69
Register L = the low byte.
4C9B
POP BC C1
Restore Register Pair BC. (4C70H jumps here to drop a return address.)
4C9D
PUSH DE D5
Save Register Pair DE.
4C9E
EX DE,HL EB
DE = the number to multiply.
4C9F
LD C,80H 0E 80
Register C = 80H: its bit falls out after eight shifts, ending the loop.
4CA1
LD HL,0000H 21 00 00
Clear HL.
4CA4
RRCA 0F
Loop Start
Rotate the multiplier's low bit into the CARRY FLAG.
4CA5
Clear: JUMP to 4CA8H.
4CA7
ADD HL,DE 19
Set: add the number.
4CA8
SRL H CB 3C
Shift H, L and C right one bit.
4CAE
Loop End
LOOP BACK to 4CA4H until the marker bit comes out.
4CB0
POP DE D1
Restore Register Pair DE.
4CB2
LD A,05H 3E 05
Load Register A with 5.
4CB4
LD C,A 4F
Keep the divisor in Register C.
4CB5
LD B,10H 06 10
16 bits.
4CB7
XOR A AF
Clear the remainder.
4CB8
ADD HL,HL 29
Loop Start
Shift HL left.
4CB9
RLA 17
Shift the top bit into the remainder.
4CBA
A bit fell out of the remainder: JUMP to 4CBFH to subtract.
4CBC
CP C B9
Is the remainder below the divisor?
4CBF
SUB C 91
Subtract the divisor.
4CC0
INC L 2C
Set the quotient bit.
4CC1
Loop End
DECrement Register B and LOOP BACK to 4CB8H.
4CC3
OR A B7
Set the flags from Register A. (4C5FH jumps here to return error 24H.)
4CC5H - Compare a Keyword and Step Over Separators
4CC5H compares the 00H-terminated string at BC with the text at HL: on a match it returns the Z FLAG with HL after the text, otherwise the NZ FLAG, Register A = 34H and HL unchanged. 4CD5H returns the Z FLAG if HL points to 0DH (the end of the command line). 4CD9H steps over a comma or over spaces and returns the NZ and NO CARRY flags; for any other character it returns the CARRY FLAG with HL unchanged. Register A is 34H (ILLEGAL KEYWORD OR SEPARATOR OR TERMINATOR) whenever the Z FLAG is not set.
4CC5
PUSH HL E5
Save the text pointer.
4CC6
LD A,(BC) 0A
Loop Start
Fetch a character of the keyword.
4CC7
OR A B7
Is it the end (00H)?
4CC8
INC BC 03
Point BC to the next one.
4CCB
EX (SP),HL E3
The whole keyword matched: swap the saved pointer with the current one,
4CCC
POP HL E1
and drop it. HL points after the text.
4CCD
RET C9
RETurn with the Z FLAG set.
4CCE
CP (HL) BE
Compare it with the text.
4CCF
INC HL 23
Point HL to the next character.
4CD0
Loop End
Equal: LOOP BACK to 4CC6H.
4CD2
POP HL E1
Different: restore the text pointer.
4CD3
JUMP to 4CE9H to return the NZ FLAG and 34H.
4CD5
LD A,(HL) 7E
Fetch the character.
4CD6
CP 0DH FE 0D
Is it 0DH?
4CD8
RET Z C8
Yes: RETurn with the Z FLAG set.
4CD9
LD A,(HL) 7E
Fetch the character.
4CDA
CP 2CH FE 2C
Is it a comma?
4CDC
INC HL 23
Point HL past it.
4CDF
CP 20H FE 20
Is it a space?
4CE1
DEC HL 2B
Point HL back to it.
4CE2
SCF 37
Set the CARRY FLAG.
4CE3
Neither: JUMP to 4CEAH.
4CE5
INC HL 23
Loop Start
Point HL to the next character.
4CE6
CP (HL) BE
Is it a space too?
4CE7
Loop End
Yes: LOOP BACK to 4CE5H.
4CE9
OR A B7
Clear the CARRY FLAG (Register A is not 0, so the NZ FLAG is set).
4CEA
LD A,34H 3E 34
Load Register A with 34H.
4CEDH - Delay
Waits about B x 256 passes of the ROM's delay loop at 0060H (14.66 microseconds each on a standard Model I), repeated SYSTEM option BJ times. Used for the motor start and head settle delays, and by SYS5 and SYS6.
4CED
LD D,B 50
Keep the count in Register D.
4CEE
LD E,01H 1E 01
Self-Modifying CodeRegister E = SYSTEM option BJ (stored at
4D8FH).
4CF0
LD B,D 42
Loop Start
Register B = the count (Register C is as the caller left it).
4CF1
GOSUB to the ROM at 0060H to count BC down to 0.
4CF4
DEC E 1D
Count down the passes.
4CF5
Loop End
LOOP BACK to 4CF0H.
4CF8
BIT 0,B CB 40
The end of the ROUTE list (zap 020). An input request (bit 0)?
4CFA
RET NZ C0
Input: RETurn with the NZ FLAG and Register A = 00H (no character).
4CFB
LD A,C 79
Output: return the character in Register A, as the ROM's drivers do.
4CFC
RET C9
RETurn. This byte (C9H) is also byte 0 of the NL device's control block 4CFCH-4CFEH, which ROUTE,NL uses (SYS14's device table and
43B2H).
4CFD-4CFE
DEFW 4BA4H A4 4B
Bytes 1-2 of the NL control block: its driver, 4BA4H (XOR A / RET). Put here by zap 020.
4CFF
DEFB 00H 00
Not referenced.
4D00H - Reset: Memory Size and Clock
BOOT/SYS loads SYS0/SYS and checks that the byte at its transfer address 4D00H is A5H, then jumps to 4D01H. The code from 4D00H to 4FA7H runs once at every reset and is then overwritten by the overlays. It finds the top of memory, restores the clock after a reset while the DOS was active, reads the system data sector and sets the DOS up from the SYSTEM options, shows the banner, asks for the date and time, reads the GAT and runs the AUTO command.
4D00
DEFB 0A5H A5
The byte BOOT/SYS checks before it jumps to 4D01H. A file whose transfer address does not hold A5H gives NO SYS.
4D01
IM 1 ED 56
Interrupt Mode 1: interrupts go to 0038H and from there through 4012H.
4D03
LD HL,FFFFH 21 FF FF
Point HL to FFFFH, the top of the address space.
4D06
LD A,(HL) 7E
Loop Start
Fetch the byte.
4D08
LD (HL),A 77
Store the inverted byte.
4D09
CP (HL) BE
Does it read back? (Only RAM does.)
4D0A
DEC HL 2B
Point HL one byte lower.
4D0B
Loop End
No RAM here: LOOP BACK to 4D06H.
4D0D
CPL 2F
RAM found: invert the byte back to its original value.
4D0E
INC HL 23
Point HL back to it.
4D0F
LD (HL),A 77
Restore it.
4D10
LD (43A9H),HL 22 A9 43
Store the top of memory at 43A9H,
4D13
LD (4049H),HL 22 49 40
and as HIMEM at 4049H.
4D16
LD HL,43ABH 21 AB 43
Point HL to 43ABH.
4D19
LD A,A5H 3E A5
Was the DOS active before this reset (A5H)?
4D1C
No (power-on): JUMP to 4D27H; the clock and date stay 0.
4D1E
INC HL 23
Yes: point HL to the copy at 43ACH,
4D1F
LD DE,4041H 11 41 40
DE to the clock at 4041H,
4D22
LD BC,0006H 01 06 00
six bytes,
4D25
LDIR ED B0
and put the time and date back.
4D27H - Reset: Read the System Data Sector
The boot sector is still in 4200H. Its bytes FDH-FFH describe the system diskette in drive 0, and they are put into drive 0's PDRIVE record so that the DOS can read that diskette. Then sector 2, the system data sector (the third sector of BOOT/SYS), is read into 4200H with the ready-made FCB at 4480H, and the SYSTEM options in it are put where the DOS uses them. See SYSTEM Options. Bad values give error 27H (ILLEGAL INITIALIZATION DATA ON SYSTEM DISKETTE).
4D27
LD IY,4380H FD 21 80 43
Point IY to 4380H.
4D2B
LD BC,(42FEH) ED 4B FE 42
Load Register Pair BC from bytes FEH-FFH of the boot sector: C = PDRIVE byte +2, B = byte +7 for drive 0.
4D2F
LD (IY-08H),B FD 70 F8
Store byte +7 at 4378H.
4D32
LD (IY-0DH),C FD 71 F3
Store byte +2 at 4373H.
4D35
LD A,(42FDH) 3A FD 42
Fetch byte FDH of the boot sector, PDRIVE byte +6.
4D38
LD (IY-09H),A FD 77 F7
Store it at 4377H.
4D3B
LD DE,4480H 11 80 44
Point DE to the FCB at 4480H, which addresses sector 2 of drive 0 with buffer 4200H.
4D3E
GOSUB to 4436H to read the system data sector.
4D41
Read error: JUMP to 4DD3H to report it.
4D44
LD A,(42EFH) 3A EF 42
Fetch byte EFH of the sector.
4D47
CP A5H FE A5
Is it A5H, the mark of a valid system data sector?
4D49
No: JUMP to 4DD1H for error 27H.
4D4C
LD HL,42F8H 21 F8 42
Point HL to bytes F8H-FFH of the sector.
4D4F
LD DE,505BH 11 5B 50
Point DE to 505BH.
4D52
LD BC,0008H 01 08 00
Eight bytes.
4D55
LDIR ED B0
Copy them, for use later in the reset (505CH at
4F23H).
4D57
LD HL,(42F0H) 2A F0 42
Load HL with bytes F0H-F1H, options AA to BK (see the table).
4D5A
LD (436CH),HL 22 6C 43
Store them at 436CH-436DH.
4D5D
LD HL,(42F2H) 2A F2 42
Load HL with bytes F2H-F3H.
4D60
LD (436EH),HL 22 6E 43
Store them at 436EH-436FH.
4D63
LD A,(42A0H) 3A A0 42
Fetch byte A0H, SYSTEM option AL (the number of drives).
4D66
LD (439FH),A 32 9F 43
Store it at 439FH,
4D69
LD (477AH),A 32 7A 47
and as the operand at 477AH, where the drive select routine checks drive numbers.
4D6C
DEC A 3D
Count 1-4 as 0-3.
4D6D
CP 04H FE 04
Is it above 3?
4D6F
Yes: JUMP to 4DD1H for error 27H.
4D71
LD A,(42A1H) 3A A1 42
Fetch byte A1H, option AW (the write tries).
4D74
LD (4ABAH),A 32 BA 4A
Store it as the operand at 4ABAH.
4D77
LD A,(42A2H) 3A A2 42
Fetch byte A2H, option AN (the default drive of DIR).
4D7A
LD (43A0H),A 32 A0 43
Store it at 43A0H.
4D7D
LD A,(42A3H) 3A A3 42
Fetch byte A3H, option AO (the first drive for a new file).
4D80
LD (43A1H),A 32 A1 43
Store it at 43A1H.
4D83
LD A,(42A6H) 3A A6 42
Fetch byte A6H, option AM (the disk I/O tries).
4D86
LD (465AH),A 32 5A 46
Store it as the operand at 465AH.
4D89
LD A,(42A9H) 3A A9 42
Fetch byte A9H, option BJ (the CPU speed multiplier).
4D8C
LD (43A2H),A 32 A2 43
Store it at 43A2H,
4D8F
LD (4CEFH),A 32 EF 4C
and as the operand at 4CEFH (the delay routine).
4D92
LD L,06H 2E 06
Register L = 6, the status delay count for a normal CPU.
4D94
LD DE,2400H 11 00 24
Register Pair DE = 2400H, the index pulse time-out for a normal CPU.
4D97
PUSH AF F5
Save the multiplier.
4D98
GOSUB to 4C92H: A, H and L = 6 x BJ.
4D9B
OR H B4
Is the result above 255?
4D9C
Yes: JUMP to 4DD1H for error 27H.
4D9E
LD A,L 7D
Load Register A with the result.
4D9F
LD (47E4H),A 32 E4 47
Store it as the operand at 47E4H.
4DA2
POP AF F1
Restore the multiplier.
4DA3
EX DE,HL EB
HL = 2400H.
4DA4
GOSUB to 4C94H: A, H and L = 2400H x BJ.
4DA7
OR A B7
Is the result above FFFFH?
4DA8
Yes: JUMP to 4DD1H for error 27H.
4DAA
LD (47F4H),HL 22 F4 47
Store it as the operand at 47F4H.
4DAD
LD A,(42A8H) 3A A8 42
Fetch byte A8H, option AX (the highest printable character).
4DB0
LD (4370H),A 32 70 43
Store it at 4370H.
4DB3
LD HL,(4049H) 2A 49 40
Load HL with the top of memory from 4049H.
4DB6
LD DE,(42D0H) ED 5B D0 42
Load DE with bytes D0H-D1H, option AP (HIMEM).
4DBA
LD A,D 7A
Is option AP 0?
4DBC
Yes: JUMP to 4DC4H to keep the top of memory.
4DBE
OR A B7
Clear the CARRY FLAG.
4DBF
SBC HL,DE ED 52
Subtract AP from the top of memory.
4DC1
AP is above the top of memory: JUMP to 4DC4H. Note that HL now holds the difference, not the top of memory, and that is what gets stored.
4DC4
LD (4049H),HL 22 49 40
Store HIMEM at 4049H.
4DC7
XOR A AF
Register A = 0, the first drive.
4DC8
LD DE,4371H 11 71 43
Point DE to the PDRIVE table at 4371H.
4DCB
LD IX,4200H DD 21 00 42
Point IX to the first PDRIVE record in the sector (at 4200H).
4DD1
LD A,27H 3E 27
Load Register A with error code 27H (ILLEGAL INITIALIZATION DATA ON SYSTEM DISKETTE).
4DD3
PUSH AF F5
Save the error code.
4DD4
LD A,46H 3E 46
Load Register A with code 46H (SYS4, function 2), which sets bit 2 of 436AH and displays the error.
4DD6
RST 28H EF
Call SYS4. The RST 28H does not come back here.
4DD7
LD BC,000AH 01 0A 00
Loop Start
Ten bytes per record.
4DDA
PUSH AF F5
Save the drive number.
4DDB
CP (IY+1FH) FD BE 1F
Is it below the number of drives (439FH)?
4DE0
PUSH IX DD E5
Point HL to the record in the sector,
4DE3
LDIR ED B0
and copy its first ten bytes to the table.
4DE5
LD A,(IX+02H) DD 7E 02
Fetch the record's byte +2.
4DE8
AND 1CH E6 1C
Keep the interface type, bits 2-4.
4DEA
None: JUMP to 4DD1H for error 27H. All ten records must be valid.
4DEC
LD C,10H 0E 10
Records are 16 bytes long (Register B is 0).
4DEE
ADD IX,BC DD 09
Point IX to the next record.
4DF0
POP AF F1
Restore the drive number.
4DF2
CP 0AH FE 0A
Ten records (drives 0-9)?
4DF4
Loop End
No: LOOP BACK to 4DD7H.
4DF6H - Reset: Set Up the Keyboard, Display and Directory Mark
Changes the resident code according to the SYSTEM options. Register C holds byte F8H of the system data sector, Register B byte F9H, Register E byte F0H (436CH) and Register D byte F1H (436DH).
4DF6
LD A,(42FAH) 3A FA 42
Fetch byte FAH of the sector.
4DF9
BIT 7,A CB 7F
Is bit 7, option BN, set?
4DFD
LD A,ABH 3E AB
Yes: Register A = ABH, the command for a write with data address mark F8H.
4DFF
LD (463DH),A 32 3D 46
Store it as the operand at 463DH, the directory mark write.
4E02
LD BC,(42F8H) ED 4B F8 42
Load Register C with byte F8H and Register B with byte F9H.
4E06
LD DE,(436CH) ED 5B 6C 43
Load Register E with 436CH and Register D with 436DH.
4E0A
BIT 6,E CB 73
Option AB (RUN-ONLY), bit 6 of 436CH?
4E0E
SET 2,(IY-17H) FD CB E9 D6
Yes: set bit 2 of 4369H, which turns off D-F-G, 1-2-3 and J-K-L (options AD, AE and AF are forced to N),
4E12
RES 6,(IY-13H) FD CB ED B6
and clear bit 6 of 436DH (option BC is forced to N).
4E16
BIT 0,C CB 41
Option AU (repeat key), bit 0 of byte F8H?
4E1A
LD A,20H 3E 20
Yes: Register A = 20H, the opcode of JR NZ.
4E1C
LD (4538H),A 32 38 45
Store it at 4538H to turn on the repeat key.
4E1F
LD A,(42A7H) 3A A7 42
Fetch byte A7H, option AV (the first repeat delay).
4E22
LD (4578H),A 32 78 45
Store it as the operand at 4578H,
4E25
LD (452FH),A 32 2F 45
and at 452FH.
4E28
LD A,(42A5H) 3A A5 42
Fetch byte A5H, option BI (the cursor character).
4E2C
Yes: JUMP to 4E31H and keep 5FH.
4E2E
LD (4501H),A 32 01 45
Store it as the operand at 4501H.
4E31
BIT 1,C CB 49
Option AJ (keyboard intercept), bit 1 of byte F8H?
4E35
LD A,(3840H) 3A 40 38
Read keyboard row 6.
4E38
BIT 3,A CB 5F
Is the up-arrow key (bit 3) held?
4E3A
Yes: JUMP to 4E48H. The intercept is not installed (the manual says AJ = N is forced).
4E3C
LD HL,4516H 21 16 45
Point HL to the keyboard driver at 4516H.
4E3F
LD (4016H),HL 22 16 40
Store it in the keyboard's control block at 4016H.
4E42
LD HL,4505H 21 05 45
Point HL to the display driver at 4505H.
4E45
LD (401EH),HL 22 1E 40
Store it in the display's control block at 401EH.
4E48
LD HL,3C00H 21 00 3C
Point HL to the first byte of the screen.
4E4B
LD A,61H 3E 61
Register A = 61H, a lower case "a".
4E4D
LD (HL),A 77
Store it.
4E4E
CP (HL) BE
Does it read back? Only with the lower case hardware installed.
4E4F
LD (HL),20H 36 20
Put a space there again.
4E51
No lower case hardware: JUMP to 4E6AH (options BF and BG are ignored).
4E53
BIT 2,B CB 50
Option BF (lower case driver), bit 2 of byte F9H?
4E57
LD A,4FH 3E 4F
Yes: Register A = 4FH, the opcode of LD C,A.
4E59
LD (4593H),A 32 93 45
Store it at 4593H, so that the keyboard driver goes on to the letter case handling.
4E5C
LD A,38H 3E 38
Register A = 38H, the opcode of JR C.
4E5E
LD (4505H),A 32 05 45
Store it at 4505H, so that the display driver puts lower case letters on the screen.
4E61
BIT 1,B CB 48
Option BG (lower case keyboard input), bit 1 of byte F9H?
4E65
LD A,00H 3E 00
No: Register A = 00H, a NOP.
4E67
LD (45B4H),A 32 B4 45
Store it at 45B4H, so that letters are made upper case.
4E6A
BIT 0,B CB 40
Option BH (blinking cursor), bit 0 of byte F9H?
4E6E
LD A,C8H 3E C8
Yes: Register A = C8H, the opcode of RET Z.
4E70
LD (4502H),A 32 02 45
Store it at 4502H in the cursor routine.
4E73
BIT 7,C CB 79
Option AC (debounce), bit 7 of byte F8H?
4E77
LD A,3EH 3E 3E
No: Register A = 3EH, the opcode of LD A,n.
4E79
LD (457DH),A 32 7D 45
Store it at 457DH to skip the debounce test.
4E7C
BIT 6,C CB 71
Option AD (J-K-L), bit 6 of byte F8H?
4E80
LD A,C0H 3E C0
Yes: Register A = C0H, the opcode of RET NZ.
4E82
LD (45EEH),A 32 EE 45
Store it at 45EEH.
4E85
BIT 4,C CB 61
Option AF (D-F-G), bit 4 of byte F8H?
4E89
LD A,20H 3E 20
Yes: Register A = 20H, the opcode of JR NZ.
4E8B
LD (45CCH),A 32 CC 45
Store it at 45CCH.
4E8E
BIT 2,C CB 51
Option AQ (CLEAR key), bit 2 of byte F8H?
4E92
XOR A AF
Yes: Register A = 00H.
4E93
LD (4590H),A 32 90 45
Store it as the operand at 4590H, so that CLEAR is not filtered out.
4E96
BIT 5,C CB 69
Option AE (1-2-3), bit 5 of byte F8H?
4E9A
LD A,20H 3E 20
Yes: Register A = 20H, the opcode of JR NZ.
4E9C
LD (45D8H),A 32 D8 45
Store it at 45D8H.
4E9F
BIT 5,E CB 6B
Option AG (BREAK is a key), bit 5 of 436CH?
4EA3
SET 4,(IY-17H) FD CB E9 E6
Yes: set bit 4 of 4369H.
4EA7H - Reset: Screen, Banner, Date and Time
Clears the screen, routes the display to NL if option BA is Y, shows the banner and, depending on options AY and AZ, asks for the date and time. Then the date and time are displayed.
4EA7
LD HL,4FA8H 21 A8 4F
Point HL to the message at 4FA8H (cursor home, clear the screen).
4EAA
GOSUB to 4467H to display it.
4EAD
LD A,(42F9H) 3A F9 42
Fetch byte F9H of the sector.
4EB0
BIT 5,A CB 6F
Option BA (ROUTE,DO,NL at reset), bit 5?
4EB4
DI F3
Disable interrupts while the display is rerouted.
4EB5
LD HL,43B2H 21 B2 43
Point HL to ROUTE entry 1 at 43B2H.
4EB8
LD (4ADCH),HL 22 DC 4A
Make it the first ROUTE entry (the operand at 4ADCH).
4EBB
LD DE,401DH 11 1D 40
Point DE to the display's control block at 401DH.
4EBE
LD (HL),E 73
Store its address in the entry,
4EC0
LD (HL),D 72
continue,
4EC2
LD A,(DE) 1A
Fetch the control block's type byte,
4EC3
LD (HL),A 77
save it in the entry,
4EC4
INC HL 23
and point HL to the entry's link.
4EC5
LD A,C0H 3E C0
Register A = C0H,
4EC7
LD (DE),A 12
the type byte of a routed device: store it in the control block.
4EC8
XOR A AF
Clear Register A.
4EC9
LD (HL),A 77
The link is 0000H: this is the only entry. Its target is the NL device (
4CFCH).
4ECB
LD (HL),A 77
Continue.
4ECC
EI FB
Enable interrupts.
4ECD
LD HL,4FABH 21 AB 4F
Point HL to the banner at 4FABH.
4ED0
GOSUB to 4467H to display it.
4ED3
LD A,(43ABH) 3A AB 43
Was the DOS active before the reset (43ABH = A5H)?
4ED6
CP A5H FE A5
Continue.
4ED8
LD A,(42F9H) 3A F9 42
Fetch byte F9H of the sector.
4EDB
No (power-on): JUMP to 4EDFH.
4EDD
RES 7,A CB BF
A reset while the DOS was active: ignore option AY (bit 7).
4EDF
AND C0H E6 C0
Keep options AY (bit 7) and AZ (bit 6). After a power-on either one asks for the date and time.
4EE1
Asked for: GOSUB to 4F3DH to ask for the date and time.
4EE4
LD HL,5089H 21 89 50
Point HL to the display line at 5089H.
4EE8
GOSUB to 44C2H to put the date there.
4EEB
LD HL,5093H 21 93 50
Point HL to 5093H.
4EEE
GOSUB to 44A7H to put the time there.
4EF1
POP HL E1
Restore the pointer to the line.
4EF2
GOSUB to 4467H to display the date and time.
4EF5
XOR A AF
Clear Register A: directory sector 0, the GAT.
4EF6
LD (4930H),A 32 30 49
Store it at 4930H as the directory sector to read.
4EF9
LD HL,4F05H 21 05 4F
Point HL to 4F05H
4EFC
PUSH HL E5
and push it as the return address.
4EFE
PUSH BC C5
and BC, as 490AH would have.
4EFF
LD HL,4200H 21 00 42
Point HL to 4200H.
4F02
JUMP to 4911H: read the boot sector of drive 0, take the directory's lump from it, and read the GAT into 4200H. The routine returns to 4F05H.
4F05
Read error: JUMP to 4DD3H to report it.
4F08
LD DE,4318H 11 18 43
Point DE to the command buffer at 4318H.
4F0C
PUSH BC C5
Save Register Pair BC.
4F0D
LD HL,42E0H 21 E0 42
Point HL to bytes E0H-FFH of the GAT, the AUTO command.
4F10
LD BC,0020H 01 20 00
32 bytes.
4F13
LDIR ED B0
Copy the AUTO command into the command buffer.
4F15
LD HL,43ABH 21 AB 43
Point HL to 43ABH.
4F18
LD (HL),A5H 36 A5
Store A5H: the DOS is now active.
4F1A
POP BC C1
Restore Register Pair BC.
4F1B
POP HL E1
Point HL to the command buffer.
4F1C
XOR A AF
Clear Register A.
4F1D
BIT 6,(IY-14H) FD CB EC 76
Option AB (RUN-ONLY), bit 6 of 436CH?
4F21
Yes: the AUTO command cannot be skipped; JUMP to 4F37H.
4F23
LD A,(505CH) 3A 5C 50
Fetch the copy of byte F9H at 505CH.
4F26
BIT 3,A CB 5F
Option BD (ENTER skips the AUTO command), bit 3?
4F2A
LD A,(3840H) 3A 40 38
Read keyboard row 6.
4F2D
RRCA 0F
Move bit 0, the ENTER key, into the CARRY FLAG.
4F2E
ENTER held: JUMP to 4400H, DOS READY.
4F31
LD A,(HL) 7E
Fetch the first character of the AUTO command.
4F32
CP 0DH FE 0D
Is it 0DH (no AUTO command)?
4F34
Yes: JUMP to 4400H, DOS READY.
4F37
GOSUB to 4467H to display the AUTO command.
4F3A
JUMP to 4405H to execute it.
4F3DH - Ask for the Date and Time
Each question is repeated until the answer is valid. The answer is typed into the command buffer at 4318H through the ROM's line input at 0040H and checked by 4F6FH against the table at 509CH.
4F3D
LD HL,5063H 21 63 50
Loop Start
Point HL to DATE? (MM/DD/YY) at 5063H.
4F40
GOSUB to 4F64H to display it and input the answer.
4F43
LD BC,509CH 01 9C 50
Point BC to the date limits at 509CH.
4F46
LD DE,4046H 11 46 40
Point DE to the month at 4046H (the day and year follow downward).
4F49
LD A,2FH 3E 2F
The separator is a slash.
4F4B
GOSUB to 4F6FH to check and store the answer.
4F4E
Loop End
Invalid: LOOP BACK to 4F3DH.
4F50
LD HL,5076H 21 76 50
Loop Start
Point HL to TIME? (HH:MM:SS) at 5076H.
4F53
GOSUB to 4F64H to display it and input the answer.
4F56
LD BC,50A2H 01 A2 50
Point BC to the time limits at 50A2H.
4F59
LD DE,4043H 11 43 40
Point DE to the hours at 4043H.
4F5C
LD A,3AH 3E 3A
The separator is a colon.
4F61
Loop End
Invalid: LOOP BACK to 4F50H.
4F64
GOSUB to 4467H to display the question.
4F67
LD HL,4318H 21 18 43
Point HL to the command buffer.
4F6A
LD B,09H 06 09
At most 9 characters.
4F6C
JUMP to the ROM's line input at 0040H, which returns to the caller.
4F6FH - Check and Store a Date or Time
HL points to the typed answer, DE to the first of three clock bytes (stored downward), BC to three pairs of (lowest value, number of values), and Register A holds the separator. Each value must be two digits and within its range. On exit the Z FLAG is set if all three were valid and the line ends after them. Interrupts are off meanwhile, so that the clock does not change while it is being set.
4F6F
LD (4FA0H),A 32 A0 4F
Store the separator as the operand at 4FA0H.
4F72
DI F3
Disable interrupts.
4F73
PUSH BC C5
Save the limits pointer.
4F74
LD B,03H 06 03
Three values.
4F76
LD A,(HL) 7E
Loop Start
Fetch the first digit.
4F77
SUB 30H D6 30
Convert it from ASCII.
4F79
CP 0AH FE 0A
Is it a digit?
4F7B
INC HL 23
Point HL to the next character.
4F7E
LD C,A 4F
Keep it in Register C.
4F7F
RLCA 07
Times 10 (x4, +1, x2).
4F83
LD C,A 4F
Keep the tens in Register C.
4F84
LD A,(HL) 7E
Fetch the second digit.
4F85
SUB 30H D6 30
Convert it from ASCII.
4F87
CP 0AH FE 0A
Is it a digit?
4F89
INC HL 23
Point HL to the next character.
4F8C
ADD A,C 81
Add the tens.
4F8D
LD (DE),A 12
Store the value.
4F8E
DEC DE 1B
Point DE to the next clock byte.
4F8F
EX (SP),HL E3
Swap the text pointer with the limits pointer.
4F90
SUB (HL) 96
Subtract the lowest value.
4F91
INC HL 23
Point HL to the number of values.
4F92
CP (HL) BE
Is the value in range?
4F93
INC HL 23
Point HL to the next pair.
4F96
EX (SP),HL E3
Swap the pointers back.
4F97
Count the value. Another follows: JUMP to 4F9EH.
4F99
POP BC C1
All three: restore the limits pointer.
4F9A
EI FB
Enable interrupts.
4F9B
JUMP to 4CD5H: the Z FLAG is set if the line ends here.
4F9E
LD A,(HL) 7E
Fetch the separator.
4F9F
CP 00H FE 00
Self-Modifying Code
Is it the right one? The operand at 4FA0H is stored by 4F6FH.
4FA1
INC HL 23
Point HL past it.
4FA2
Loop End
Yes: LOOP BACK to 4F76H.
4FA4
EI FB
Invalid: enable interrupts.
4FA5
POP AF F1
Drop the limits pointer (Register A becomes its high byte, 50H).
4FA6
OR A B7
Set the NZ FLAG.
4FA8H - Reset Messages
The messages displayed by the reset code. The banner uses the Model I graphics characters (80H-BFH; 80H is a blank) and space compression codes (C0H-FFH display 0-63 spaces).
4FA8-4FAA
DEFB 1CH, 1FH, 03H 1C 1F 03
Cursor home, clear to the end of the screen, end of message. Displayed first (
4EA7H).
4FAB-4FD5
DEFB 0BFH, 0B4H, 0C1H, 0BFH, 0C1H, 0BEH, 83H, 83H, 0BDH, 0C1H, 0BFH, 0C2H, 0BFH, 0C1H, 0BFH, 83H, 83H, 0BDH, 0C1H, 0BEH, 83H, 83H, 0BDH, 0C1H, 0BEH, 83H, 83H, 8DH, 0C3H, 0B8H, 87H, 0C1H, 0BEH, 83H, 83H, 0BDH, 0C1H, 0BEH, 83H, 83H, 0BDH, 0C2H, 80H BF B4 C1 BF C1 BE 83 83 BD C1 BF C2 BF C1 BF 83 83 BD C1 BE 83 83 BD C1 BE 83 83 8D C3 B8 87 C1 BE 83 83 BD C1 BE 83 83 BD C2 80
The banner (
4ECDH), line 1: the top of the large
NEWDOS/80 drawn in graphics characters.
4FD6-4FE6
DEFM "MODEL", 80H, "I", 80H, "V2.0", 80H, 80H, 80H, 80H, 0AH 4D 4F 44 45 4C 80 49 80 56 32 2E 30 80 80 80 80 0A
Beside it: MODEL I V2.0, then a line feed.
4FE7-5010
DEFB 0BFH, 82H, 0ADH, 0BFH, 0C1H, 0BFH, 83H, 83H, 0B3H, 0C1H, 0BFH, 9EH, 0ADH, 0BFH, 0C1H, 0BFH, 0C2H, 0BFH, 0C1H, 0BFH, 0C2H, 0BFH, 0C1H, 0B2H, 83H, 83H, 0BDH, 0C1H, 0A0H, 9EH, 81H, 0C2H, 0BEH, 83H, 83H, 0BDH, 0C1H, 0BFH, 0C2H, 0BFH, 0C2H, 80H BF 82 AD BF C1 BF 83 83 B3 C1 BF 9E AD BF C1 BF C2 BF C1 BF C2 BF C1 B2 83 83 BD C1 A0 9E 81 C2 BE 83 83 BD C1 BF C2 BF C2 80
Line 2 of the graphics.
5011-5021
DEFM "ZAPPED", 80H, "THROUGH", 80H, 80H, 0AH 5A 41 50 50 45 44 80 54 48 52 4F 55 47 48 80 80 0A
Beside it: ZAPPED THROUGH, then a line feed.
5022-5049
DEFB 83H, 0C2H, 83H, 0C1H, 82H, 83H, 83H, 81H, 0C1H, 83H, 0C2H, 83H, 0C1H, 83H, 83H, 83H, 81H, 0C1H, 82H, 83H, 83H, 81H, 0C1H, 82H, 83H, 83H, 81H, 0C1H, 83H, 0C4H, 82H, 83H, 83H, 81H, 0C1H, 82H, 83H, 83H, 81H, 0C3H 83 C2 83 C1 82 83 83 81 C1 83 C2 83 C1 83 83 83 81 C1 82 83 83 81 C1 82 83 83 81 C1 83 C4 82 83 83 81 C1 82 83 83 81 C3
Line 3 of the graphics, then three spaces.
504A-505A
DEFM "90", 0C1H, "AND", 0C1H, ",B", 0C1H, "PATCH ", 0DH 39 30 C1 41 4E 44 C1 2C 42 C1 50 41 54 43 48 20 0D
90 AND ,B PATCH, ending the banner with a carriage return. With line 2 it reads ZAPPED THROUGH 90 AND ,B PATCH.
505BH - Reset Data
The copy of the system data sector's bytes F8H-FFH, the date and time questions, the date and time line, and the limits used to check the answers.
505B-5062
DEFB 00H x 8 00 x 8
Filled at reset with bytes F8H-FFH of the system data sector (
4D4CH). 505CH (byte F9H) is read again at
4F23H for option BD.
5063-5075
DEFM "DATE? (MM/DD/YY) ", 03H 44 41 54 45 3F 20 20 28 4D 4D 2F 44 44 2F 59 59 29 20 03
The date question.
5076-5088
DEFM "TIME? (HH:MM:SS) ", 03H 54 49 4D 45 3F 20 20 28 48 48 3A 4D 4D 3A 53 53 29 20 03
The time question.
5089-509B
DEFM "MM/DD/YY HH:MM:SS", 0DH 4D 4D 2F 44 44 2F 59 59 20 20 48 48 3A 4D 4D 3A 53 53 0D
The date and time line: the date is put at 5089H and the time at 5093H (
4EE4H) before it is displayed.
509C-509D
DEFB 01H, 0CH 01 0C
Month: from 1, 12 values.
509E-509F
DEFB 01H, 1FH 01 1F
Day: from 1, 31 values.
50A0-50A1
DEFB 00H, 64H 00 64
Year: from 0, 100 values.
50A2-50A3
DEFB 00H, 18H 00 18
Hours: from 0, 24 values.
50A4-50A5
DEFB 00H, 3CH 00 3C
Minutes: from 0, 60 values.
50A6-50A7
DEFB 00H, 3CH 00 3C
Seconds: from 0, 60 values.
50A8
DEFB 00H 00
Not referenced.
50A9H - Rest of the File
The file continues to 51DAH with bytes that nothing refers to. The overlays load over them.
50A9-50E2
DEFB 00H x 58 00 x 58
Not referenced.
50E3
DEFB 03H 03
Not referenced.
50E4-51DA
DEFB 00H x 247 00 x 247
Not referenced. 51DAH is the last byte of the file.