3C00H - Encoded Banner Lines (Video Memory)
The first load block of SYS0/SYS goes straight into video memory: screen lines 0 and 1 (the top two lines), 3C00H-3C7FH. Each byte is stored as its two's complement (00H less the character), so the screen shows graphics characters while the file loads; the reset at 4E06H-4E12H negates each byte back (NEG) and the lines read VTOS - VIRTUAL TECHNOLOGY'S OPERATING SYSTEM - VER 4.0.2 and COPYRIGHT (C) 1980 RANDOLPH COOK, ALL RIGHTS RESERVED. The bytes stay encoded on the diskette, so the notice cannot be read in the file with a text search.
3C00-3C0F
DEFB AAH,ACH,B1H,ADH,E0H,D3H,E0H,AAH,B7H,AEH,ACH,ABH,BFH,B4H,E0H,ACH AA AC B1 AD E0 D3 E0 AA B7 AE AC AB BF B4 E0 AC
Screen line 0, columns 0-15 (3C00H-3C0FH): 16 encoded characters. The reset negates each byte (4E0BH) to give the text "VTOS - VIRTUAL T" (E0H is the encoding of a space, 20H).
3C10-3C1F
DEFB BBH,BDH,B8H,B2H,B1H,B4H,B1H,B9H,A7H,D9H,ADH,E0H,B1H,B0H,BBH,AEH BB BD B8 B2 B1 B4 B1 B9 A7 D9 AD E0 B1 B0 BB AE
Screen line 0, columns 16-31 (3C10H-3C1FH): 16 encoded characters. The reset negates each byte (4E0BH) to give the text "ECHNOLOGY'S OPER" (E0H is the encoding of a space, 20H).
3C20-3C2F
DEFB BFH,ACH,B7H,B2H,B9H,E0H,ADH,A7H,ADH,ACH,BBH,B3H,E0H,D3H,E0H,AAH BF AC B7 B2 B9 E0 AD A7 AD AC BB B3 E0 D3 E0 AA
Screen line 0, columns 32-47 (3C20H-3C2FH): 16 encoded characters. The reset negates each byte (4E0BH) to give the text "ATING SYSTEM - V" (E0H is the encoding of a space, 20H).
3C30-3C3F
DEFB BBH,AEH,E0H,CCH,D2H,D0H,D2H,CEH,E0H,E0H,E0H,E0H,E0H,E0H,E0H,E0H BB AE E0 CC D2 D0 D2 CE E0 E0 E0 E0 E0 E0 E0 E0
Screen line 0, columns 48-63 (3C30H-3C3FH): 16 encoded characters. The reset negates each byte (4E0BH) to give the text "ER 4.0.2 " (E0H is the encoding of a space, 20H).
3C40-3C4F
DEFB BDH,B1H,B0H,A7H,AEH,B7H,B9H,B8H,ACH,E0H,D8H,BDH,D7H,E0H,CFH,C7H BD B1 B0 A7 AE B7 B9 B8 AC E0 D8 BD D7 E0 CF C7
Screen line 1, columns 0-15 (3C40H-3C4FH): 16 encoded characters. The reset negates each byte (4E0BH) to give the text "COPYRIGHT (C) 19" (E0H is the encoding of a space, 20H).
3C50-3C5F
DEFB C8H,D0H,E0H,AEH,BFH,B2H,BCH,B1H,B4H,B0H,B8H,E0H,BDH,B1H,B1H,B5H C8 D0 E0 AE BF B2 BC B1 B4 B0 B8 E0 BD B1 B1 B5
Screen line 1, columns 16-31 (3C50H-3C5FH): 16 encoded characters. The reset negates each byte (4E0BH) to give the text "80 RANDOLPH COOK" (E0H is the encoding of a space, 20H).
3C60-3C6F
DEFB D4H,E0H,BFH,B4H,B4H,E0H,AEH,B7H,B9H,B8H,ACH,ADH,E0H,AEH,BBH,ADH D4 E0 BF B4 B4 E0 AE B7 B9 B8 AC AD E0 AE BB AD
Screen line 1, columns 32-47 (3C60H-3C6FH): 16 encoded characters. The reset negates each byte (4E0BH) to give the text ", ALL RIGHTS RES" (E0H is the encoding of a space, 20H).
3C70-3C7F
DEFB BBH,AEH,AAH,BBH,BCH,E0H,E0H,E0H,E0H,E0H,E0H,E0H,E0H,E0H,E0H,E0H BB AE AA BB BC E0 E0 E0 E0 E0 E0 E0 E0 E0 E0 E0
Screen line 1, columns 48-63 (3C70H-3C7FH): 16 encoded characters. The reset negates each byte (4E0BH) to give the text "ERVED " (E0H is the encoding of a space, 20H).
3CD1H - VTOS SERIAL # Label (Video Memory)
A load block of 13 bytes into screen line 3 (3CC0H-3CFFH; line 0 is the top line), at columns 17-29. The reset puts the serial number, bytes C0H-C7H of the system information sector, right after it at 3CDEH-3CE5H (4F7CH-4F85H).
3CD1-3CDD
DEFM "VTOS SERIAL #" 56 54 4F 53 20 53 45 52 49 41 4C 20 23
Screen line 3, columns 17-29 (3CD1H-3CDDH): the text VTOS SERIAL # in plain ASCII, loaded as it is shown. The eight characters of the serial number follow at 3CDEH-3CE5H, copied there by the LDIR at 4F85H (QS91215N on this diskette).
3CDE-3CE5
DEFS 8
Screen line 3, columns 30-37 (3CDEH-3CE5H): not in the file. The reset copies the serial number, bytes C0H-C7H of the system information sector read to 42C0H-42C7H, here (Register Pair HL = 42C0H, Register Pair DE = 3CDEH, Register Pair BC = 0008H at 4F7CH-4F85H).
3D40H - VTOS Banner Graphics (Video Memory)
A load block of 320 bytes into screen lines 5-9 (3D40H-3E7FH; line 0 is the top line). The bytes are TRS-80 graphics characters (80H-BFH: bit 7 set, bits 5-0 the six blocks of a 2 by 3 cell) and spaces (20H); together they draw the letters VTOS five lines high, with the text TM after the S on line 5. They are shown as they are loaded: nothing in SYS0/SYS changes them.
3D40-3D4F
DEFB AAH,BFH,20H,20H,20H,20H,20H,20H,20H,BFH,95H,20H,20H,20H,20H,20H AA BF 20 20 20 20 20 20 20 BF 95 20 20 20 20 20
Screen line 5, columns 0-15 (3D40H-3D4FH): 4 graphics characters and 12 spaces of the large letter V.
3D50-3D5F
DEFB 20H,8FH,8FH,8FH,8FH,BFH,9FH,8FH,8FH,8FH,85H,20H,20H,20H,20H,20H 20 8F 8F 8F 8F BF 9F 8F 8F 8F 85 20 20 20 20 20
Screen line 5, columns 16-31 (3D50H-3D5FH): 10 graphics characters and 6 spaces of the large letter T.
3D60-3D6F
DEFB 20H,BFH,9FH,8FH,8FH,8FH,8FH,8FH,AFH,BFH,20H,20H,20H,20H,20H,20H 20 BF 9F 8F 8F 8F 8F 8F AF BF 20 20 20 20 20 20
Screen line 5, columns 32-47 (3D60H-3D6FH): 9 graphics characters and 7 spaces of the large letter O.
3D70-3D7F
DEFB 20H,BFH,9FH,8FH,8FH,8FH,8FH,8FH,8FH,8FH,20H,20H,54H,4DH,20H,20H 20 BF 9F 8F 8F 8F 8F 8F 8F 8F 20 20 54 4D 20 20
Screen line 5, columns 48-63 (3D70H-3D7FH): 9 graphics characters and 5 spaces of the large letter S. The bytes 54H 4DH at 3D7CH-3D7DH are the plain characters T and M.
3D80-3D8F
DEFB 20H,AAH,BFH,20H,20H,20H,20H,20H,BFH,95H,20H,20H,20H,20H,20H,20H 20 AA BF 20 20 20 20 20 BF 95 20 20 20 20 20 20
Screen line 6, columns 0-15 (3D80H-3D8FH): 4 graphics characters and 12 spaces of the large letter V.
3D90-3D9F
DEFB 20H,20H,20H,20H,20H,BFH,95H,20H,20H,20H,20H,20H,20H,20H,20H,20H 20 20 20 20 20 BF 95 20 20 20 20 20 20 20 20 20
Screen line 6, columns 16-31 (3D90H-3D9FH): 2 graphics characters and 14 spaces of the large letter T.
3DA0-3DAF
DEFB 20H,BFH,95H,20H,20H,20H,20H,20H,AAH,BFH,20H,20H,20H,20H,20H,20H 20 BF 95 20 20 20 20 20 AA BF 20 20 20 20 20 20
Screen line 6, columns 32-47 (3DA0H-3DAFH): 4 graphics characters and 12 spaces of the large letter O.
3DB0-3DBF
DEFB 20H,BFH,95H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H 20 BF 95 20 20 20 20 20 20 20 20 20 20 20 20 20
Screen line 6, columns 48-63 (3DB0H-3DBFH): 2 graphics characters and 14 spaces of the large letter S.
3DC0-3DCF
DEFB 20H,20H,BFH,95H,20H,20H,20H,BFH,95H,20H,20H,20H,20H,20H,20H,20H 20 20 BF 95 20 20 20 BF 95 20 20 20 20 20 20 20
Screen line 7, columns 0-15 (3DC0H-3DCFH): 4 graphics characters and 12 spaces of the large letter V.
3DD0-3DDF
DEFB 20H,20H,20H,20H,20H,BFH,95H,20H,20H,20H,20H,20H,20H,20H,20H,20H 20 20 20 20 20 BF 95 20 20 20 20 20 20 20 20 20
Screen line 7, columns 16-31 (3DD0H-3DDFH): 2 graphics characters and 14 spaces of the large letter T.
3DE0-3DEF
DEFB 20H,BFH,95H,20H,20H,20H,20H,20H,AAH,BFH,20H,20H,20H,20H,20H,20H 20 BF 95 20 20 20 20 20 AA BF 20 20 20 20 20 20
Screen line 7, columns 32-47 (3DE0H-3DEFH): 4 graphics characters and 12 spaces of the large letter O.
3DF0-3DFF
DEFB 20H,8FH,8FH,8FH,8FH,8FH,8FH,8FH,AFH,BFH,20H,20H,20H,20H,20H,20H 20 8F 8F 8F 8F 8F 8F 8F AF BF 20 20 20 20 20 20
Screen line 7, columns 48-63 (3DF0H-3DFFH): 9 graphics characters and 7 spaces of the large letter S.
3E00-3E0F
DEFB 20H,20H,20H,BFH,95H,20H,BFH,95H,20H,20H,20H,20H,20H,20H,20H,20H 20 20 20 BF 95 20 BF 95 20 20 20 20 20 20 20 20
Screen line 8, columns 0-15 (3E00H-3E0FH): 4 graphics characters and 12 spaces of the large letter V.
3E10-3E1F
DEFB 20H,20H,20H,20H,20H,BFH,95H,20H,20H,20H,20H,20H,20H,20H,20H,20H 20 20 20 20 20 BF 95 20 20 20 20 20 20 20 20 20
Screen line 8, columns 16-31 (3E10H-3E1FH): 2 graphics characters and 14 spaces of the large letter T.
3E20-3E2F
DEFB 20H,BFH,95H,20H,20H,20H,20H,20H,AAH,BFH,20H,20H,20H,20H,20H,20H 20 BF 95 20 20 20 20 20 AA BF 20 20 20 20 20 20
Screen line 8, columns 32-47 (3E20H-3E2FH): 4 graphics characters and 12 spaces of the large letter O.
3E30-3E3F
DEFB 20H,20H,20H,20H,20H,20H,20H,20H,AAH,BFH,20H,20H,20H,20H,20H,20H 20 20 20 20 20 20 20 20 AA BF 20 20 20 20 20 20
Screen line 8, columns 48-63 (3E30H-3E3FH): 2 graphics characters and 14 spaces of the large letter S.
3E40-3E4F
DEFB 20H,20H,20H,20H,AAH,BFH,20H,20H,20H,20H,20H,20H,20H,20H,20H,20H 20 20 20 20 AA BF 20 20 20 20 20 20 20 20 20 20
Screen line 9, columns 0-15 (3E40H-3E4FH): 2 graphics characters and 14 spaces of the large letter V.
3E50-3E5F
DEFB 20H,20H,20H,20H,20H,BFH,95H,20H,20H,20H,20H,20H,20H,20H,20H,20H 20 20 20 20 20 BF 95 20 20 20 20 20 20 20 20 20
Screen line 9, columns 16-31 (3E50H-3E5FH): 2 graphics characters and 14 spaces of the large letter T.
3E60-3E6F
DEFB 20H,BFH,BDH,BCH,BCH,BCH,BCH,BCH,BEH,BFH,20H,20H,20H,20H,20H,20H 20 BF BD BC BC BC BC BC BE BF 20 20 20 20 20 20
Screen line 9, columns 32-47 (3E60H-3E6FH): 9 graphics characters and 7 spaces of the large letter O.
3E70-3E7F
DEFB 20H,BCH,BCH,BCH,BCH,BCH,BCH,BCH,BEH,BFH,20H,20H,20H,20H,20H,20H 20 BC BC BC BC BC BC BC BE BF 20 20 20 20 20 20
Screen line 9, columns 48-63 (3E70H-3E7FH): 9 graphics characters and 7 spaces of the large letter S.
400CH - Restart Vectors
The Model I ROM sends RST 28H, RST 30H and RST 38H through three jumps in RAM: RST 28H jumps to 400CH, RST 30H to 400FH and RST 38H (the maskable interrupt in interrupt mode 1) to 4012H. The ROM's power up copy puts RET or EI and RET there; SYS0/SYS loads its own three jumps over them.
400C
RST 28H vector: JUMP to 4C31H, the request handler. A program puts a request code in Register A and executes RST 28H: a code with bit 7 set loads and runs a system overlay (4C36H), a code with bit 7 clear goes on to the address held at 4310H (4C28H). The ROM's BREAK key test at 0453H-0456H also arrives here, with Register A = 01H.
400F
RST 30H vector: JUMP to 44B4H, the entry to the DEBUG monitor (request code 87H, SYS5/SYS). A breakpoint byte F7H (RST 30H) in a program being debugged arrives here, and the program loader jumps here (4CE0H) to start a program under DEBUG when bit 7 of 430FH is set.
4012
RST 38H vector: JUMP to 4518H, the interrupt service routine. The reset selects interrupt mode 1 (IM 1 at 4E01H), so every interrupt of the expansion interface (the real time clock and the disk controller) arrives through the ROM's 0038H to this jump.
4015H - Device Control Block of the Keyboard (KI)
The ROM's character I/O routine (03C2H) works through 8 byte device control blocks: +00H the type (bit 0 input, bit 1 output, bit 2 control), +01H-+02H the driver address, +03H-+05H the driver's own bytes, +06H-+07H the two letter name. SYS0/SYS adds two types of its own (44C4H): 10H, a block routed to the block whose address is in +01H-+02H, and 08H in bit 3, a device that takes nothing and gives nothing (NIL). A type of 11H or more is the first byte of an open file's control block (48E1H).
4015
DEFB 01H 01
Type byte of the KI block: 01H, input only (bit 0). The ROM's input call (0013H, Register B = 01H) finds bit 0 set and calls the driver at 4016H.
4016-4017
DEFS 2
Driver address of the KI block, not in the file. The ROM's power up copy puts 03E3H there (its keyboard scan); the reset stores 439CH, SYS0/SYS's own keyboard driver, at 4E48H-4E4DH unless the up arrow key is held during the boot, and copies whichever address is there to 43B8H (4E4EH-4E53H).
4018
DEFB 00H 00
KI block +03H: the code of the key being held, 00H when none. The keyboard driver stores it at 4C03H (Index Register IX = 4015H) and the repeat routine at 41E5H (file 50E0H) and 4C14H read it.
4019
DEFB 00H 00
KI block +04H: the value of the tick counter 4040H at which the held key repeats. The driver sets it to 4040H + 1EH (30 ticks) when a key goes down (4C0CH-4C11H) and to 4040H + 03H after each repeat (file 50F3H-50F8H).
401A
DEFB 00H 00
KI block +05H: 00H. Nothing in SYS0/SYS reads or writes it; the driver uses only +03H and +04H.
401B-401C
DEFM "KI" 4B 49
KI block +06H-+07H: the device name KI, which the device commands of SYS6/SYS and SYS10/SYS compare against (SYS10/SYS walks the blocks by these names, its 4E79H-4E95H).
401D
DEFB 07H 07
Type byte of the DO block (display output): 07H, input, output and control. The ROM's display call 0033H points Register Pair DE at 401DH; the text routine at 44DDH does the same.
401E-401F
DEFS 2
Driver address of the DO block, not in the file. The ROM's power up copy puts 0458H there (its display driver); the reset copies whatever address is there to 43BAH (4E54H-4E57H).
4020-4021
DEFW 3C00H 00 3C
DO block +03H-+04H: the cursor address, 3C00H in the file (the top left corner of the screen). The reset sets it to 3ED7H (4EF2H), 3F14H (4F02H), 3F17H (4F62H) and 3F40H (from 4FFCH) before each text it displays.
4022
DEFB 00H 00
DO block +05H: 00H. The ROM's display driver keeps the character under the cursor here; SYS0/SYS does not use it.
4023-4024
DEFM "DO" 44 4F
DO block +06H-+07H: the device name DO, used by the device commands.
4025
DEFB 06H 06
Type byte of the PR block (printer output): 06H, output and control. The routine at 44F2H points Register Pair DE here to print a text.
4026-4027
DEFS 2
Driver address of the PR block, not in the file. The ROM's power up copy puts 058DH there (its printer driver); the reset copies whatever address is there to 43BCH (4E5AH-4E5DH).
4028
DEFB 42H 42
PR block +03H: 42H (66), the lines of a page. The ROM's printer driver (058DH-05D0H) compares the line count at +04H with it after each carriage return and, on a form feed (0CH), sends line feeds until the page ends. The ROM's power up copy has 43H here.
4029
DEFB 00H 00
PR block +04H: 00H, the count of lines printed on the page, which the ROM's printer driver counts up and resets.
402A
DEFB 00H 00
PR block +05H: 00H, not used by the ROM's printer driver or by SYS0/SYS.
402B-402C
DEFM "PR" 50 52
PR block +06H-+07H: the device name PR, used by the device commands.
402DH - The Two Exits to the Command Level
Every program leaves through one of these two entries. 402DH (request 93H) is the normal exit: SYS1/SYS displays VTOS READY and waits for a command. 4030H (request A3H) is the abort exit; SYS1/SYS handles it the same way (its 4E00H-4E08H take both codes to 4E38H). Both load SYS1/SYS through RST 28H.
402D
LD A,93H 3E 93
Load Register A with 93H, the request code of the normal exit: bit 7 set (a system overlay), bits 3-0 = 3 (SYS1/SYS, whose directory entry code is 03H) and bits 6-4 = 1 (its function 1, VTOS READY and the command prompt).
402F
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which loads SYS1/SYS (unless it is the overlay already in memory, 430EH) and runs it with Register A = 93H. The return address pushed by RST 28H is discarded (4C36H), so nothing comes back here.
4030
LD A,A3H 3E A3
Load Register A with A3H, the request code of the abort exit: SYS1/SYS (bits 3-0 = 3), function 2 (bits 6-4). SYS0/SYS jumps here itself after a load error (4CB7H).
4032
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS1/SYS with Register A = A3H. The return address pushed by RST 28H is discarded.
4033
JUMP to 44C4H. The ROM's character I/O routine jumps to 4033H (its 03D1H) when the type byte of the device control block at Index Register IX does not have the bit of the request in Register B; SYS0/SYS's dispatcher at 44C4H then follows routes, ignores NIL devices and passes characters to open files.
4036H - Keyboard Image
Seven bytes, one for each row of the keyboard matrix 3801H-3840H, holding the keys found down at the last scan; the driver at 439CH compares each row with its byte. The patch SYS0D carried as FFH in all seven (its record in the file): every key counts as already down when the system starts, so a key held during the boot does not start repeating once VTOS READY is shown.
4036-403C
DEFB FFH x 7 FF x 7
Rows 0-6 of the keyboard (3801H, 3802H, 3804H, 3808H, 3810H, 3820H, 3840H): FFH, every key marked as down. The driver at 439CH (Register Pair HL = 4036H, then 4037H ... 403CH) stores each row it reads here (4BBCH); 4039H (row 3) and 403AH (row 4) and 403CH (row 6) are tested by name at 4BC6H, 4BF0H and 4BD0H.
403D
DEFS 1
Not in the file. SYS0/SYS neither reads nor writes 403DH; the keyboard image ends at 403CH (row 6), and row 7 (3880H, the SHIFT key) is read directly from the matrix.
403E
DEFB 40H 40
40H, the system version (4.0). BASIC/CMD (its 5C68H-5C6DH) and PATCH/CMD (its 5208H-520DH) compare it with 40H and refuse to run when it is less. SYS0/SYS does not read it.
403F
DEFB 01H 01
01H. No file on this diskette reads or writes 403FH.
4040
DEFB 00H 00
The tick counter: the clock task routine at 4578H adds 1 at every clock interrupt (458FH) and takes bits 2-0 as the number of the task slot to run. The key repeat (file 50E5H, 50F3H, 4C0CH) and SYS2/SYS, SYS8/SYS read it.
4041-4043
DEFS 3
Not in the file: the time of day, 4041H seconds, 4042H minutes, 4043H hours, binary. The clock task at 45CAH counts them up once a second against the limits 60, 60 and 24 at 45E6H; the TIME routine at 4DB9H shows them as HH:MM:SS.
4044-4046
DEFS 3
Not in the file: the date, 4044H year (binary, 80-87), 4045H day, 4046H month. The reset sets them from 4306H-4307H (4E94H-4EC0H) or clears them (4F56H-4F5CH); the clock task adds 1 to the day at midnight (45E4H); the DATE routine at 4DD4H shows them as MM/DD/YY.
4047-4048
DEFS 2
Not in the file. The reset stores 5200H here (4E14H-4E17H), the lowest address above SYS0/SYS's buffers. No file on this diskette reads 4047H.
4049-404A
DEFS 2
Not in the file: the highest address of usable memory. The reset finds the top of memory (4E1AH-4E29H: the first address down from FFFFH, in steps of 1K, whose byte can be changed) and stores it here (4E2BH). Programs and drivers that reserve memory at the top lower it (SYS9/SYS 4E0DH-4E16H, KSM/DVR, PR2/DVR, RS232/DVR, the filters).
404BH - Interrupt Latch Copy, Enable Mask and Interrupt Vectors
The interrupt service routine at 4518H reads the interrupt latch 37E0H, keeps it at 404BH, masks it with 404CH and calls, for each bit that is set, the routine whose address is in the vector table 404DH-405CH (bit 0 first).
404B
DEFB 00H 00
Copy of the interrupt latch: the interrupt service routine stores the value read from 37E0H here at 4522H (bit 7 the real time clock, bit 6 the disk controller). Nothing in SYS0/SYS reads it back.
404C
DEFB 00H 00
The mask of interrupts that are served: 00H in the file. The reset sets it to C0H (4E85H-4E8CH: bits 7 and 6, the clock and the disk controller); the interrupt service routine ANDs the latch with it (4524H).
404D-404E
DEFW 453CH 3C 45
Vector for latch bit 0: 453CH, a RET, so an interrupt with this bit set is ignored.
404F-4050
DEFW 453CH 3C 45
Vector for latch bit 1: 453CH, a RET, so an interrupt with this bit set is ignored.
4051-4052
DEFW 453CH 3C 45
Vector for latch bit 2: 453CH, a RET, so an interrupt with this bit set is ignored.
4053-4054
DEFW 453CH 3C 45
Vector for latch bit 3: 453CH, a RET, so an interrupt with this bit set is ignored.
4055-4056
DEFW 453CH 3C 45
Vector for latch bit 4: 453CH, a RET, so an interrupt with this bit set is ignored.
4057-4058
DEFW 453CH 3C 45
Vector for latch bit 5: 453CH, a RET, so an interrupt with this bit set is ignored.
4059-405A
DEFW 4646H 46 46
Vector for latch bit 6, the disk controller: 4646H, the routine that waits while the controller is busy and selects the current drive again (4309H) at each pass.
405B-405C
DEFW 4578H 78 45
Vector for latch bit 7, the real time clock: 4578H, the task dispatcher, which runs the four fast task slots and one of the eight slow slots at each clock interrupt.
405DH - Memory SYS0/SYS Uses Below 4300H
Three areas outside the file: the end of the reset, which runs at 405DH after being copied there, the key repeat routine copied to 41E5H, and the sector buffer at 4200H.
405D-407C
DEFS 32
Not in the file: the last 32 bytes of the reset (file 4FEEH-500DH) are copied here (4FD5H-4FDFH) and run here, since the area from 4E00H up is taken by the overlays and by CONFIG/SYS. The code sets the fast clock, displays the AUTO command and executes it, or goes to VTOS READY. After the boot the DEBUG monitor SYS5/SYS keeps its cells in the same 32 bytes (its 4E17H-4E2FH, 4E9AH, 4ECBH).
41E5-41FF
DEFS 27
Not in the file: the key repeat routine, copied from 50E0H-50FAH by the reset (4E36H-4E3FH, the patch SYS0D). The keyboard driver jumps here when no key has changed (43B1H).
4200-42FF
DEFS 256
Not in the file: the sector buffer. The reset reads the system information sector here (4F70H) and then the allocation table (4F9FH); the directory routines read each directory sector here (4B37H-4B3EH: Register H = 42H); the overlay and program loader reads every sector of a file here (4CE6H, 4DA6H).
4300H - Keyboard Hook and System Cells
4300H-4302H is a hook the keyboard driver calls before every scan (439CH): RET in the file. 4306H-4317H are cells SYS0/SYS and the overlays share: the date kept across a reset, the current drive, the control block and return address of the last file request, the overlay in memory, the system flags, the request hook and the BREAK key vector.
4300
RET C9
Return. The keyboard driver calls 4300H at 439CH before each scan of the keyboard; with RET here the call does nothing. SYS6/SYS puts a JP to code of its own here (its 53EBH-53F0H: C3H into 4300H, the address into 4301H-4302H) and calls the hook itself (its 53A9H); CONFIG/SYS saves and restores the three bytes.
4301-4302
DEFW 0000H 00 00
The operand bytes of the hook: 0000H. They become the jump address when SYS6/SYS writes C3H at 4300H (its 53EBH); SYS6/SYS also reads them back (its 5380H).
4303
GOSUB to 4030H, the abort exit (request A3H). No file on this diskette calls or jumps to 4303H, and SYS0/SYS does not reach it: the three bytes are only the next part of the area after the hook.
4306-4307
DEFS 2
Not in the file, so a reset keeps what is there: the date. 4306H holds the month OR 50H (51H-5CH), 4307H the day in bits 7-3 and the year less 80 in bits 2-0. The DATE command of SYS6/SYS writes them (its 5213H-5227H); the reset (4E94H-4EC0H) turns them into 4044H-4046H, or clears them when the month is not 1-12 (4F4FH-4F53H).
4308
DEFB FFH FF
The current drive number, FFH in the file. Every call to the disk driver through 4750H-4778H stores the drive in Register C here first (477BH); 4750H (select again) reads it back.
4309
DEFB FFH FF
The value last written to the drive select latch 37E1H (bits 3-0, one bit a drive), FFH in the file. The select routine stores it (462BH); the wait at 4646H writes it to the latch again on each pass, so the motors keep running while the controller is busy.
430A-430B
DEFW 0000H 00 00
The address of the control block of the last file request. The request entry check (49F1H) stores Register Pair DE here; SYS4/SYS reads it to name the file in an error message (its 4E9EH).
430C-430D
DEFW 0000H 00 00
The return address of the CALL 49EBH (or 49E9H) at the start of the last file request, that is the address in SYS0/SYS just after that call (47B3H for 4442H, for example). Stored at 49EEH; SYS4/SYS reads it (its 4F2EH).
430E
DEFB 02H 02
The request code of the overlay in memory at 4E00H. 02H in the file (bits 3-0 = 2, the directory entry code of SYS0/SYS itself, so the first request with bits 3-0 other than 2 loads its overlay). The request handler stores each new code (4C65H) and compares bits 3-0 with the next (4C5EH-4C62H); the file routines keep the code before SYS8/SYS (4A98H) and load SYS1/SYS again after it when that was SYS1/SYS (4AA2H-4AA8H); otherwise 430EH keeps SYS8/SYS's code.
430F
DEFB 00H 00
System flags. The reset sets 01H (4E8EH-4E90H). Bits SYS0/SYS uses: bit 2 set while a program is loaded and run by 4433H (4CCFH); bit 1 set (by SYS2/SYS, its 4F4DH) makes 4433H start the program directly even when bit 7 asks for DEBUG (4CDBH); bit 3 the fast clock (462FH, and port FEH at 405DH); bit 4 set by a non breakable AUTO command (4FB4H), which makes the interrupt routine ignore BREAK (4561H-4566H); bit 7 starts DEBUG before a program runs (4CDEH).
4310-4311
DEFW 4C2FH 2F 4C
The address a request with bit 7 of Register A clear goes on to (4C28H): 4C2FH in the file, OR A and RET, so such a request returns at once. SYS9/SYS replaces it (its 4E07H-4E22H).
4312
DEFB 00H 00
00H. No file on this diskette reads or writes 4312H.
4313-4314
DEFW 0000H 00 00
0000H. SYS0/SYS does not use 4313H; BASIC/CMD and its overlays keep a word here (BASIC/CMD 5BB8H, 5C1CH, 5C25H).
4315-4317
DEFS 3
Not in the file: the BREAK key vector. 4315H is C3H when BREAK is to interrupt the running program, anything else (C9H from the reset, 4E80H-4E82H) when it is not; 4316H-4317H hold the address it goes to. The interrupt routine tests and clears 4315H (4568H-4570H); the request handler blocks it while an overlay runs (4C3AH-4C4EH). SYS1/SYS, SYS5/SYS and BASIC/CMD set it.
4318H - Command Line Buffer and Two Control Blocks
4318H-4357H is the command line buffer of SYS1/SYS (64 bytes, its 4E20H-4E2BH and 4E4FH-4E54H). During the boot the reset copies the AUTO command into its first 32 bytes, and 4338H-4357H serves as the control block of CONFIG/SYS, whose name is loaded there. 4358H-4377H is the control block SYS6/SYS and SYS7/SYS use for the file of DO commands.
4318-431A
DEFB 00H,FFH,C7H 00 FF C7
The first three bytes of the command line buffer as the file loads them: 00H, FFH, C7H. The reset copies the 32 bytes of the AUTO command over 4318H-4337H (4FCDH-4FD3H) before anything reads them.
431B-4337
DEFS 29
Not in the file: the rest of the first 32 bytes of the command line buffer, filled by the reset with the AUTO command from the allocation table (32 bytes from 42E0H, or from 42E1H when the command starts with an asterisk, which takes 4300H as its last byte; 4FA8H-4FD3H). The code at 405DH (file 4FEEH) displays and executes it.
4338-4348
DEFM "CONFIG/SYS.CCC:0",03H 43 4F 4E 46 49 47 2F 53 59 53 2E 43 43 43 3A 30 03
The file specification of CONFIG/SYS: name CONFIG, extension SYS, password CCC, drive 0, ended by 03H. The reset loads the file with 4430H and Register Pair DE = 4338H (4FE7H-4FEAH) when byte 01H of the system information sector is 00H and neither CLEAR nor 9 is held; the open (SYS2/SYS) turns these bytes into a file control block.
4349-4357
DEFS 15
Not in the file: the rest of the 32 byte control block at 4338H, filled by SYS2/SYS when CONFIG/SYS is opened. After the boot 4338H-4357H is the second half of the command line buffer again (SYS1/SYS copies 63 bytes and 03H to 4318H).
4358-4377
DEFS 32
Not in the file: the 32 byte control block of the file of DO commands. SYS6/SYS opens the file there (its 5237H, 5244H and others: Register Pair DE = 4358H) and SYS7/SYS reads the commands from it and stores 00H at 4358H when it closes it (its 4EA9H).
4378H - Write a Line to the Job Log (JL)
Reached through 447EH (a text alone) and 447BH (after the text has been displayed). When the JL device has a type other than 08H (NIL), the current time and two spaces go to it, then the text at Register Pair HL. The JL device is the device control block at 43C0H.
4378
LD A,(43C0H) 3A C0 43
Fetch the type byte of the JL device control block from 43C0H into Register A: 08H in the file (NIL, the device is not routed anywhere), 10H when ROUTE has sent JL to another device, or the first byte of a file control block when it goes to a file.
437B
XOR 08H EE 08
Exclusive OR Register A (the JL type) with 08H: Register A becomes 00H and the Z FLAG is set when the type is exactly 08H, a JL device that takes nothing.
437D
RET Z C8
If the Z FLAG is set (JL is NIL), RETURN at once: nothing is logged. Register Pair HL still points at the caller's text.
437E
PUSH HL E5
Save Register Pair HL, the address of the caller's text (ended by 0DH or 03H), to the stack for the second write below.
437F
LD HL,4391H 21 91 43
Point Register Pair HL to 4391H, the time template HH:MM:SS followed by two spaces and 03H.
4382
PUSH HL E5
Save Register Pair HL (4391H) to the stack: the TIME routine below moves Register Pair HL past the eight characters it writes.
4383
GOSUB to 446DH (JP 4DB9H), which writes the time of day from 4043H, 4042H, 4041H as HH:MM:SS into 4391H-4398H, Register Pair HL being the place to write.
4386
POP HL E1
Restore Register Pair HL from the stack: 4391H, the start of the time stamp now filled in.
4387
LD DE,43C0H 11 C0 43
Point Register Pair DE to 43C0H, the JL device control block, for the text output below.
438A
GOSUB to 4479H (JR 44E0H), which sends the text at Register Pair HL (4391H: the time and two spaces, up to the 03H) to the device at Register Pair DE (43C0H) one character at a time through the ROM's 001BH.
438D
POP HL E1
Restore Register Pair HL from the stack: the address of the caller's text saved at 437EH.
438E
JUMP to 4479H to send the caller's text at Register Pair HL to the JL device at Register Pair DE (43C0H, still in Register Pair DE after 44E0H); 44E0H returns to the caller.
4391-439B
DEFM "HH:MM:SS ",03H 48 48 3A 4D 4D 3A 53 53 20 20 03
The time stamp template of the job log: eight characters that 4DB9H overwrites with the time, two spaces and 03H, the end of text 44E2H stops at.
439CH - Keyboard Driver
The driver of the KI device (its address is put at 4016H by the reset, 4E48H-4E4DH). The ROM's input call reaches it through 03C2H with Index Register IX = 4015H, the KI block. Rows 0-6 of the keyboard matrix (3801H-3840H) are compared with the image at 4036H-403CH. A row that changed goes to 4BBCH; with no change the repeat routine at 41E5H decides whether the held key repeats. The SHIFT row (3880H) is read only when a key is decoded.
439C
GOSUB to 4300H, the keyboard hook: a RET in the file, a jump to SYS6/SYS's code when it has installed one.
439F
LD HL,4036H 21 36 40
Point Register Pair HL to 4036H, the image of row 0 of the keyboard, which holds the keys found down at the last scan.
43A2
LD BC,3801H 01 01 38
Load Register Pair BC with 3801H: Register B = 38H and Register C = 01H make the address of row 0 of the keyboard matrix; Register C is the row's select bit and moves left for each row.
43A5
LD D,00H 16 00
Load Register D with 00H, the number of the row being scanned (0-6), which the ROM's key decode at 03FAH uses.
43A7
LD A,(BC) 0A
Fetch the row at Register Pair BC (3801H, 3802H ... 3840H) into Register A: one bit for each key of the row, 1 = down.
43A8
LD E,A 5F
Copy Register A (the row as read now) into Register E, for the image update and the decode at 4BBCH.
43A9
XOR (HL) AE
Exclusive OR Register A with the image byte at Register Pair HL (the same row at the last scan): the bits that are now 1 are the keys that went down or came up.
43AA
If the NZ FLAG is set (a key of this row changed), JUMP to 4BBCH with Register A = the changed bits, Register E = the row now, Register D = the row number and Register Pair HL = its image byte.
43AD
INC D 14
Increment Register D, the row number, for the next row.
43AE
INC L 2C
Increment Register L, so Register Pair HL points at the image byte of the next row (4037H ... 403CH).
43AF
RLC C CB 01
Rotate Register C left: the select bit moves to the next row (02H, 04H ... 40H). After row 6 it becomes 80H and sets the S FLAG.
43B1
If the M FLAG is set (Register C = 80H: rows 0-6 are done and none changed), JUMP to 41E5H, the key repeat routine the reset copied there from 50E0H-50FAH, with Index Register IX still at the KI block.
43B4
JUMP back to 43A7H to read the next row at Register Pair BC.
43B6-43B7
DEFS 2
Not in the file. No file on this diskette reads or writes 43B6H-43B7H.
43B8-43BF
DEFS 8
Not in the file: the drivers the system started with. The reset copies the driver addresses of KI (4016H), DO (401EH) and PR (4026H) to 43B8H, 43BAH and 43BCH (4E4EH-4E5DH), so the device commands can put them back, and stores 0000H at 43BEH-43BFH (4E60H-4E63H), where SYS7/SYS keeps the KI driver while a file of DO commands takes the keyboard (its 4E1DH-4E20H, 4EACH-4EAFH).
43C0H - Device Control Blocks of JL, SI and LO
Three more blocks of 8 bytes in the format of 4015H. JL (job log) is NIL (type 08H); SI (source input) is routed (type 10H) to the KI block at 4015H, LO (listing output) to the DO block at 401DH. The five blocks 43D8H-43FFH after them are free (the reset clears them, 4E66H-4E6CH). SYS10/SYS walks 4015H-402CH and then 43C0H-43FFH by name (its 4E79H-4E9AH).
43C0
DEFB 08H 08
Type byte of the JL block: 08H, bit 3 alone, a NIL device. 4378H returns without logging while it is 08H; the dispatcher at 44C4H returns 00H for any request to it.
43C1-43C2
DEFW 0000H 00 00
JL block +01H-+02H: 0000H. For a routed type (10H) this would be the address of the block it goes to; for a file, part of the control block.
43C3-43C5
DEFB 00H,00H,00H 00 00 00
JL block +03H-+05H: three bytes of 00H, the driver's own bytes, not used by SYS0/SYS.
43C6-43C7
DEFM "JL" 4A 4C
JL block +06H-+07H: the device name JL (job log).
43C8
DEFB 10H 10
Type byte of the SI block: 10H, routed. The dispatcher (44CDH-44CFH) takes +01H-+02H as the block to go on to.
43C9-43CA
DEFW 4015H 15 40
SI block +01H-+02H: 4015H, the KI block. Source input comes from the keyboard.
43CB-43CD
DEFB 00H,00H,00H 00 00 00
SI block +03H-+05H: three bytes of 00H, not used while the block is routed.
43CE-43CF
DEFM "SI" 53 49
SI block +06H-+07H: the device name SI (source input).
43D0
DEFB 10H 10
Type byte of the LO block: 10H, routed. The dispatcher (44CDH-44CFH) goes on to the block at +01H-+02H.
43D1-43D2
DEFW 401DH 1D 40
LO block +01H-+02H: 401DH, the DO block. Listing output goes to the display.
43D3-43D5
DEFB 00H,00H,00H 00 00 00
LO block +03H-+05H: three bytes of 00H, not used while the block is routed.
43D6-43D7
DEFM "LO" 4C 4F
LO block +06H-+07H: the device name LO (listing output).
43D8-43FF
DEFS 40
Not in the file: five free device control blocks of 8 bytes. The reset fills them with 00H (4E66H-4E6CH: Register Pair HL from 43D8H up until Register L wraps to 00H); the device commands create new devices here.
4400H - Entry Points of the System
Programs reach the system through fixed addresses from 4400H up. Some load Register A with a request code and execute RST 28H, which loads the system overlay the code names and runs it; the others jump to a routine in SYS0/SYS. A request code with bit 7 set names an overlay in bits 3-0 (3 SYS1/SYS, 4 SYS2/SYS, 5 SYS3/SYS, 6 SYS4/SYS, 7 SYS5/SYS, 8 SYS6/SYS, 9 SYS7/SYS, AH SYS8/SYS, BH SYS9/SYS, CH SYS10/SYS: the directory entry code is the nibble below 8 and the nibble plus 18H from 8 up, 4C6FH-4C77H) and a function of that overlay in bits 6-4. The bytes between the entries are not in the file.
4400
LD A,93H 3E 93
Load Register A with 93H: SYS1/SYS (bits 3-0 = 3), function 1, the VTOS READY prompt. The boot goes here when there is no AUTO command (405DH code, file 5005H).
4402
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which loads SYS1/SYS and runs it with Register A = 93H. The return address is discarded: nothing comes back.
4403-4404
DEFS 2
Not in the file, and not used: the two bytes between the entries 4400H and 4405H.
4405
LD A,B3H 3E B3
Load Register A with B3H: SYS1/SYS function 3, which executes the command line at Register Pair HL (SYS1/SYS copies 63 bytes to the buffer at 4318H and puts 03H after them, its 4E20H-4E2BH). The boot jumps here to run the AUTO command (file 500BH, run at 407AH).
4407
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS1/SYS with Register A = B3H and Register Pair HL pointing at the command line. The return address is discarded.
4408
DEFS 1
Not in the file, and not used: the byte between the entries 4405H and 4409H.
4409
JUMP to 44B0H to display an error message. A program jumps or calls here with the error code in Register A (bits 5-0 the error, 00H-29H; bit 6 set: the text of the message alone; bit 7 set: return to the caller after the message instead of going to the abort exit 4030H). SYS0/SYS jumps here itself at 4CD4H and 4FA5H.
440C
DEFS 1
Not in the file, and not used: the byte between the entries 4409H and 440DH.
440D
JUMP to 44B4H, the entry to the DEBUG monitor (SYS5/SYS). The reset jumps here when the D key (or the down arrow) is held during the boot (4FC0H-4FC5H).
4410
JUMP to 45AEH: install a task. Register A = the task slot (0-11), Register Pair DE = the address of the task's control block, whose first two bytes are the address of its routine. SYS0/SYS installs its clock this way (4F92H-4F97H); SYS6/SYS installs the clock display (4DABH) and the trace (4DDBH).
4413
JUMP to 45ABH: remove the task in slot Register A (0-11) by putting the empty control block 45BBH into the slot.
4416
JUMP to 45BDH: called from inside a running task, it stores the address after the call as the task's routine address, so the task goes on from there the next time its slot runs, and returns to the dispatcher.
4419
JUMP to 45A6H: called from inside a running task, it removes that task from its slot and returns to the dispatcher.
441C
LD A,C3H 3E C3
Load Register A with C3H: SYS1/SYS function 4 (its 4FCEH), which takes a file specification from the text at Register Pair HL into the control block at Register Pair DE (SYS1/SYS's own 4E6EH-4E71H, PATCH/CMD 5210H-5213H).
441E
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS1/SYS with Register A = C3H and returns to the caller of 441CH.
441F
DEFS 1
Not in the file, and not used: the byte between the entries 441CH and 4420H.
4420
LD A,A4H 3E A4
Load Register A with A4H: SYS2/SYS function 2 (its 4E61H), called with the control block at Register Pair DE (BACKUP/CMD 6640H, BASIC/CMD 64C8H, VTCOMM/CMD 53F0H).
4422
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS2/SYS with Register A = A4H and returns to the caller of 4420H.
4423
DEFS 1
Not in the file, and not used: the byte between the entries 4420H and 4424H.
4424
LD A,94H 3E 94
Load Register A with 94H: SYS2/SYS function 1 (its 4E69H), the open: the file named in the control block at Register Pair DE, with the sector buffer at Register Pair HL and the record length in Register B (00H for 256). SYS0/SYS's own loader opens a program this way (4CE4H-4CE9H).
4426
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS2/SYS with Register A = 94H and returns to the caller of 4424H.
4427
DEFS 1
Not in the file, and not used: the byte between the entries 4424H and 4428H.
4428
LD A,95H 3E 95
Load Register A with 95H: SYS3/SYS function 1 (its 4E0DH), the close of the file whose control block is at Register Pair DE.
442A
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS3/SYS with Register A = 95H and returns to the caller of 4428H.
442B
DEFS 1
Not in the file, and not used: the byte between the entries 4428H and 442CH.
442C
LD A,9CH 3E 9C
Load Register A with 9CH: SYS10/SYS function 1 (its 4E05H), for the file whose control block is at Register Pair DE (BASIC/CMD 6537H).
442E
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS10/SYS with Register A = 9CH and returns to the caller of 442CH.
442F
DEFS 1
Not in the file, and not used: the byte between the entries 442CH and 4430H.
4430
JUMP to 4CE4H: load a program file. Register Pair DE = a control block holding the file specification; on return the Z FLAG is set and Register Pair HL holds the transfer address, or the NZ FLAG is set with an error code in Register A. The reset loads CONFIG/SYS this way (4FEAH).
4433
JUMP to 4CCBH: load a program file (Register Pair DE as for 4430H) and run it; a load error goes to the error message at 4409H. SYS1/SYS runs commands this way (its 4E8BH).
4436
JUMP to 48A4H: read the next record of the open file at Register Pair DE into the area at Register Pair HL (a whole sector into the file's buffer when the record length is 256).
4439
JUMP to 48C0H: write a record from the area at Register Pair HL to the open file at Register Pair DE. SYS6/SYS points this entry at 48DBH when VERIFY is on (its 526AH-5272H).
443C
JUMP to 48DBH: write a record as 4439H does and read every sector written back to check it.
443F
JUMP to 4826H: rewind the open file at Register Pair DE, so the next read or write is at its first byte.
4442
JUMP to 47B0H: position the open file at Register Pair DE to the record number in Register Pair BC.
4445
JUMP to 47FEH: move the position of the open file at Register Pair DE back by one record.
4448
JUMP to 482DH: position the open file at Register Pair DE to its end of file.
444B
JUMP to 4A12H: compare the position of the open file at Register Pair DE with its end of file (Z FLAG: before the end; error 1CH at the end; error 1DH past it). SYS7/SYS uses it on the file of DO commands.
444E
JUMP to 4883H: write any changed buffer of the open file at Register Pair DE and store its ending record number in its directory record.
4451
JUMP to 483FH: move the head of the drive to the sector of the current position of the open file at Register Pair DE.
4454
JUMP to 481AH: set the position of the open file at Register Pair DE back to the sector its buffer was read from, to be read again.
4457
JUMP to 4993H: write the buffer of the open file at Register Pair DE to the sector it was read from.
445A
JUMP to 484EH: give the record number of the current position of the open file at Register Pair DE, in Register Pair BC (Register A the bits above 16).
445D
JUMP to 4875H: give the number of records of the open file at Register Pair DE (its end of file as a record number), in Register Pair BC.
4460
JUMP to 47F5H, a routine for moving the position on by one record. No file on this diskette uses it, and as it stands it cannot return to its caller (47F5H).
4463-4466
DEFS 4
Not in the file, and not used: the four bytes between the entries 4460H and 4467H.
4467
JUMP to 44DDH: display the text at Register Pair HL, ended by 03H (not displayed) or 0DH (displayed).
446A
JUMP to 44F2H: print the text at Register Pair HL on the PR device, ended by 03H or 0DH.
446D
JUMP to 4DB9H: write the time of day as HH:MM:SS at Register Pair HL.
4470
JUMP to 4DD4H: write the date as MM/DD/YY at Register Pair HL.
4473
LD A,D3H 3E D3
Load Register A with D3H: SYS1/SYS function 5 (its 5042H), called with a control block at Register Pair DE and a default extension at Register Pair HL (BACKUP/CMD 5A0AH-5A10H, PATCH/CMD 5220H-5223H).
4475
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS1/SYS with Register A = D3H and returns to the caller of 4473H.
4476
LD A,E3H 3E E3
Load Register A with E3H: SYS1/SYS function 6 (its 510FH), which reads a list of parameters in parentheses from the text at Register Pair HL against the parameter table at Register Pair DE (BACKUP/CMD 598EH-5991H, FORMAT/CMD 6D2EH-6D31H).
4478
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS1/SYS with Register A = E3H and returns to the caller of 4476H.
4479
JUMP to 44E0H: send the text at Register Pair HL to the device whose control block is at Register Pair DE.
447B
GOSUB to 44DDH to display the text at Register Pair HL, then go on below to write it to the job log as well.
447E
JUMP to 44F7H (JP 4378H): write the text at Register Pair HL, with the time in front, to the job log device JL when JL is not NIL. 447BH arrives here after the display.
4480H - Control Block of the Program to Run
A 32 byte control block SYS1/SYS uses for the program a command names (its 4E6EH: Register Pair DE = 4480H for the file specification; 4E8BH: JP 4433H to load and run it). The file loads only its first 13 bytes, a file specification.
4480-448C
DEFM "BACKUP/CMD:0",03H 42 41 43 4B 55 50 2F 43 4D 44 3A 30 03
The file specification BACKUP/CMD on drive 0, ended by 03H, as the file loads it. SYS1/SYS writes the name of each command's program over it.
448D-449F
DEFS 19
Not in the file: the rest of the 32 byte control block at 4480H, filled when SYS2/SYS opens the program file.
44A0H - Control Block of the System Overlays
The control block the request handler loads the overlays with (4C77H-4C9DH). It is left open: the handler puts the directory entry code at +07H, sets +01H to 00H and the record number to 0000H, and copies the first extent of the overlay's directory record to +0EH-+0FH; the loader reads it sector by sector into the buffer at 4200H.
44A0
DEFB 80H 80
+00H: 80H, bit 7 set: an open file, as the request entry check at 49EBH requires.
44A1
DEFB 00H 00
+01H: the access byte. The handler stores 00H (4C7BH): bits 2-0 = 0, full access; bit 7 clear, whole sectors.
44A2
DEFB 00H 00
+02H: 00H. SYS0/SYS does not use this byte of a control block.
44A3-44A4
DEFW 4200H 00 42
+03H-+04H: 4200H, the address of the sector buffer.
44A5
DEFB 00H 00
+05H: the offset of the next byte in the buffer, 00H; the loader reads the buffer itself (4D8EH-4DA8H), so this byte stays 00H.
44A6
DEFB 00H 00
+06H: the drive, 00H: the overlays are always read from drive 0.
44A7
DEFB 00H 00
+07H: the directory entry code of the overlay, stored by the handler at 4C77H (bits 3-0 of the request code below 8, or the nibble plus 18H) and read back at 4C84H for the directory read.
44A8
DEFB 00H 00
+08H: the offset of the end of file in the last sector, 00H; unused here since the ending record number is FFFFH.
44A9
DEFB 00H 00
+09H: the record length, 00H (256: whole sectors).
44AA-44AB
DEFW 0000H 00 00
+0AH-+0BH: the next record number, set to 0000H by the handler before each load (4C7EH-4C80H) and counted up by each sector read (4970H).
44AC-44AD
DEFW FFFFH FF FF
+0CH-+0DH: the ending record number, FFFFH, so the end of file test at 4A15H never stops an overlay load.
44AE-44AF
DEFW 0000H 00 00
+0EH-+0FH: the first extent, copied by the handler from bytes 16H-17H of the overlay's directory record (4C8DH-4C95H): the cylinder, then the first granule in bits 7-5 and the count of granules less one in bits 4-0.
44B0H - Requests Reached Through Other Entries
Short request stubs that other entries jump to: the error message (4409H), DEBUG (400FH, 440DH) and three requests used by SYS6/SYS and SYS7/SYS.
44B0
PUSH AF F5
Save Register Pair AF to the stack: Register A holds the error code passed to 4409H. SYS4/SYS takes it back from the stack (its 4E05H).
44B1
LD A,86H 3E 86
Load Register A with 86H: SYS4/SYS (bits 3-0 = 6), function 0, the error message display.
44B3
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS4/SYS with Register A = 86H; the error code is on the stack. SYS4/SYS returns to the caller when bit 7 of the code is set and goes to 4030H when it is not.
44B4
PUSH AF F5
Save Register Pair AF to the stack for DEBUG, which shows the registers as they were (SYS5/SYS takes it back at its 4E00H-4E02H).
44B5
LD A,87H 3E 87
Load Register A with 87H: SYS5/SYS (bits 3-0 = 7), function 0, the DEBUG monitor.
44B7
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS5/SYS with Register A = 87H.
44B8
LD A,C4H 3E C4
Load Register A with C4H: SYS2/SYS function 4 (its 5147H). SYS6/SYS calls this entry.
44BA
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS2/SYS with Register A = C4H.
44BB
LD A,B5H 3E B5
Load Register A with B5H: SYS3/SYS function 3 (its 4FCBH). SYS6/SYS calls this entry.
44BD
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS3/SYS with Register A = B5H.
44BE
LD A,C9H 3E C9
Load Register A with C9H: SYS7/SYS function 4 (its 4EC8H). No file on this diskette calls 44BEH; SYS7/SYS loads the address 44BEH into Register Pair DE (its 4E48H).
44C0
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which runs SYS7/SYS with Register A = C9H.
44C1H - Character I/O for Routed, NIL and File Devices
The ROM's character I/O routine (03C2H) jumps to 4033H and so to 44C4H when the type byte of the block at Index Register IX lacks the bit of the request in Register B (01H input, 02H output, 04H control); Register C holds the character. A type of 10H is followed to the block at +01H-+02H; a type of 11H and up is an open file; a type with bit 3 set is NIL; any other type calls the driver at +01H-+02H as the ROM would.
44C1
PUSH HL E5
Save Register Pair HL (the address in +01H-+02H of a routed block: the block it goes to) to the stack, to move it into Index Register IX.
44C2
POP IX DD E1
Restore Index Register IX from the stack: Index Register IX now points at the device control block the route leads to.
44C4
LD L,(IX+01H) DD 6E 01
Fetch byte +01H of the block at Index Register IX into Register L: the low byte of the driver address, or of the address of the block a route leads to.
44C7
LD H,(IX+02H) DD 66 02
Fetch byte +02H of the block at Index Register IX into Register H: Register Pair HL = the driver address (or the route's block).
44CA
LD A,(IX+00H) DD 7E 00
Fetch byte +00H, the type byte of the block at Index Register IX, into Register A.
44CD
CP 10H FE 10
Compare Register A (the type) against 10H, a routed block.
44CF
If the Z FLAG is set (type 10H), JUMP back to 44C1H to follow the route to the block at Register Pair HL.
44D1
If the NC FLAG is set (type above 10H: the block is the first byte of an open file's control block, 80H and up), JUMP to 48E1H to read or write the character in Register C through the file.
44D4
AND 08H E6 08
Mask Register A (the type, below 10H) to bit 3, the NIL bit.
44D6
XOR 08H EE 08
Exclusive OR Register A with 08H: Register A = 00H and the Z FLAG set when bit 3 was set.
44D8
RET Z C8
If the Z FLAG is set (a NIL device), RETURN with Register A = 00H: no character comes in and nothing goes out.
44D9
LD A,B 78
Load Register A with Register B, the request (01H input, 02H output, 04H control).
44DA
CP 02H FE 02
Compare Register A against 02H, setting the flags the ROM sets before it calls a driver (03D4H): Z for an output request, C for an input request.
44DC
JP (HL) E9
JUMP to the driver at Register Pair HL (from +01H-+02H of the block at Index Register IX), with Register C the character and the flags from the compare.
44DDH - Display or Print a Text
44DDH displays the text at Register Pair HL on the DO device, 44F2H prints it on the PR device, 44E0H sends it to the device at Register Pair DE. The text ends at 03H (not sent) or 0DH (sent). Register Pair HL is returned unchanged.
44DD
LD DE,401DH 11 1D 40
Point Register Pair DE to 401DH, the DO (display) device control block.
44E0
PUSH HL E5
Save Register Pair HL (the start of the text) to the stack, to return it unchanged.
44E1
LD A,(HL) 7E
Fetch the next character of the text from Register Pair HL into Register A.
44E2
CP 03H FE 03
Compare Register A against 03H, the end of text that is not sent.
44E4
If the Z FLAG is set (03H), JUMP to 44F0H to return.
44E6
PUSH AF F5
Save Register Pair AF (the character in Register A) to the stack: the ROM's output routine does not keep Register A.
44E7
GOSUB to the ROM's 001BH to send Register A to the device whose control block is at Register Pair DE (Register B = 02H, an output request, through 03C2H).
44EA
POP AF F1
Restore Register Pair AF from the stack: Register A is the character just sent.
44EB
INC HL 23
Increment Register Pair HL to the next character of the text.
44EC
CP 0DH FE 0D
Compare Register A (the character sent) against 0DH, the carriage return that ends a line.
44EE
If the NZ FLAG is set (not 0DH), JUMP back to 44E1H for the next character.
44F0
POP HL E1
Restore Register Pair HL from the stack: the start of the text, as the caller passed it.
44F1
RET C9
RETURN to the caller with Register Pair HL at the start of the text and Register Pair DE still the device control block.
44F2
LD DE,4025H 11 25 40
Point Register Pair DE to 4025H, the PR (printer) device control block.
44F5
JUMP to 44E0H to send the text at Register Pair HL to the printer.
44F7
JUMP to 4378H to write the text at Register Pair HL to the job log (reached from 447EH).
44FA
PUSH HL E5
Save Register Pair HL (the caller's record area) to the stack. 44FAH-44FFH is the patch SYS0C (its record in the file): the record read at 48A7H calls here first.
44FB
GOSUB to 4988H to write the buffer of the file at Index Register IX back to its sector when it holds changed bytes in record mode (bits 7 and 4 of +01H).
44FE
POP HL E1
Restore Register Pair HL from the stack: the caller's record area.
44FF
RET C9
RETURN to 48AAH with the Z FLAG set when the buffer did not need writing or was written, the NZ FLAG and an error code in Register A when the write failed.
4500H - Task Slots
Twelve slots of two bytes, slot n at 4500H + 2n. Each holds the address of a task control block, whose first two bytes are the address of the task's routine; the routine runs with Index Register IX pointing at its control block. At every clock interrupt (40 a second) the dispatcher at 4578H runs slots 8-11 and then one of slots 0-7 in turn, so a task in slots 0-7 runs 5 times a second. An empty slot holds 45BBH, a control block whose routine is a RET.
4500-4501
DEFW 45BBH BB 45
Slot 0: 45BBH, empty. Tasks are installed with 4410H (Register A = 0) and removed with 4413H.
4502-4503
DEFW 45BBH BB 45
Slot 1: 45BBH, empty. Slots 0-7 run when bits 2-0 of the tick counter 4040H equal the slot number.
4504-4505
DEFW 45BBH BB 45
Slot 2: 45BBH, empty, run 5 times a second when a task is installed.
4506-4507
DEFW 45BBH BB 45
Slot 3: 45BBH, empty, run 5 times a second when a task is installed.
4508-4509
DEFW 45BBH BB 45
Slot 4: 45BBH, empty, run 5 times a second when a task is installed.
450A-450B
DEFW 45BBH BB 45
Slot 5: 45BBH, empty, run 5 times a second when a task is installed.
450C-450D
DEFW 45BBH BB 45
Slot 6: 45BBH, empty. SYS6/SYS installs the clock display 4DABH here (its 5244H-524BH: Register A = 06H).
450E-450F
DEFW 45BBH BB 45
Slot 7: 45BBH, empty in the file. The reset installs the clock 45C7H here (4F92H-4F97H: Register A = 07H).
4510-4511
DEFW 45BBH BB 45
Slot 8: 45BBH, empty. Slots 8-11 run at every clock interrupt (4578H-4589H).
4512-4513
DEFW 45BBH BB 45
Slot 9: 45BBH, empty. SYS6/SYS installs a task of its own here (its 53E0H-53E2H: Register A = 09H).
4514-4515
DEFW 45BBH BB 45
Slot 10: 45BBH, empty. SYS6/SYS installs a task of its own here (its 53A1H-53A3H: Register A = 0AH).
4516-4517
DEFW 45BBH BB 45
Slot 11: 45BBH, empty. SYS6/SYS installs the trace display 4DDBH here (its 525AH-5261H: Register A = 0BH).
4518H - Interrupt Service Routine
Reached from 0038H through 4012H at every interrupt of the expansion interface. The latch at 37E0H is read twice and ORed (a bit set in either read counts), kept at 404BH and masked with 404CH; for each bit left, from bit 0 up, the routine whose address is in the vector table 404DH-405CH is called with all registers saved. Then the BREAK key is tested: SHIFT and BREAK select the current drive again; BREAK alone goes to the address at 4316H when 4315H holds C3H.
4518
PUSH HL E5
Save Register Pair HL of the interrupted program to the stack.
4519
PUSH AF F5
Save Register Pair AF of the interrupted program to the stack.
451A
LD HL,37E0H 21 E0 37
Point Register Pair HL to 37E0H, the interrupt latch of the expansion interface (bit 7 the real time clock, bit 6 the disk controller).
451D
LD A,(HL) 7E
Fetch the interrupt latch at Register Pair HL (37E0H) into Register A.
451E
OR (HL) B6
OR Register A with the latch read a second time at Register Pair HL (37E0H): a bit set in either read stays set in Register A.
451F
LD HL,404BH 21 4B 40
Point Register Pair HL to 404BH, the copy of the latch.
4522
LD (HL),A 77
Store Register A (the latch bits) to 404BH at Register Pair HL.
4523
INC L 2C
Increment Register L: Register Pair HL = 404CH, the mask of interrupts that are served (C0H after the reset).
4524
AND (HL) A6
AND Register A (the latch bits) with the mask at Register Pair HL (404CH): only the bits of interrupts that are served remain.
4525
If the Z FLAG is set (no served interrupt is pending), JUMP to 452FH to test the BREAK key.
4527
INC L 2C
Increment Register L: Register Pair HL = the low byte of the vector of the next latch bit (404DH for bit 0, then 404FH, 4051H ... 405BH).
4528
RRA 1F
Rotate Register A right through the carry: the lowest latch bit left goes into the CARRY FLAG.
4529
If the C FLAG is set (this interrupt is pending), JUMP to 453DH to call the routine at the vector Register Pair HL points at.
452B
INC L 2C
Increment Register L past the high byte of the vector (Register Pair HL = 404EH, 4050H ... ).
452C
OR A B7
OR Register A with itself: the Z FLAG is set when no latch bit is left in Register A.
452D
If the NZ FLAG is set (bits are left), JUMP back to 4527H for the next vector.
452F
LD A,(3840H) 3A 40 38
Fetch row 6 of the keyboard from 3840H into Register A (bit 2 is the BREAK key).
4532
AND 04H E6 04
Mask Register A (keyboard row 6) to bit 2, the BREAK key: the NZ FLAG is set while BREAK is down.
4534
If the NZ FLAG is set (BREAK is down), JUMP to 4554H.
4536
CALL NZ,0000H C4 00 00
Self-Modifying Code
GOSUB to the address at 4537H-4538H (0000H in the file) if the NZ FLAG is set. The AND 04H at 4532H leaves the Z FLAG set whenever this row is reached (BREAK not down), so as CALL NZ (C4H, as in the file) the call is never made. SYSTEM (JKL), member 13 of SYS6/SYS, changes it: its task (slot 4, copied below the top of memory) stores the address of its screen print routine at 4537H-4538H and CCH (CALL Z) at 4536H when J, K and L are held, so this row then calls the print with Register Pair HL and Register Pair AF saved by 4518H; the print routine stores C4H back at 4536H first and 0000H at 4537H-4538H when it ends, returning to 4539H.
4539
POP AF F1
Restore Register Pair AF of the interrupted program from the stack.
453A
POP HL E1
Restore Register Pair HL of the interrupted program from the stack.
453B
EI FB
Enable interrupts again: the CPU disabled them when it took the interrupt.
453C
RET C9
RETURN to the interrupted program. 453CH is also the vector of latch bits 0-5 (404DH-4058H), a routine that returns at once.
453D
PUSH AF F5
Save Register Pair AF to the stack: Register A holds the latch bits still to be served.
453E
PUSH BC C5
Save Register Pair BC of the interrupted program to the stack.
453F
PUSH DE D5
Save Register Pair DE of the interrupted program to the stack.
4540
PUSH HL E5
Save Register Pair HL (the address of the vector, 404DH-405BH) to the stack.
4541
PUSH IX DD E5
Save Index Register IX of the interrupted program to the stack.
4543
LD DE,454CH 11 4C 45
Load Register Pair DE with 454CH, the return address for the routine about to be called.
4546
PUSH DE D5
Save Register Pair DE (454CH) to the stack, so the routine's RET comes back to 454CH.
4547
LD E,(HL) 5E
Fetch the low byte of the vector from Register Pair HL into Register E.
4548
INC L 2C
Increment Register L to the high byte of the vector.
4549
LD D,(HL) 56
Fetch the high byte of the vector from Register Pair HL into Register D: Register Pair DE = the routine's address (453CH, 4646H or 4578H).
454A
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the routine's address.
454B
JP (HL) E9
JUMP to the routine at Register Pair HL; it returns to 454CH.
454C
POP IX DD E1
Restore Index Register IX of the interrupted program from the stack.
454E
POP HL E1
Restore Register Pair HL from the stack: the address of the low byte of the vector just served.
454F
POP DE D1
Restore Register Pair DE of the interrupted program from the stack.
4550
POP BC C1
Restore Register Pair BC of the interrupted program from the stack.
4551
POP AF F1
Restore Register Pair AF from the stack: Register A holds the latch bits still to be served.
4552
JUMP back to 452BH to step Register Pair HL past this vector and test the next latch bit.
4554
LD A,(3880H) 3A 80 38
Fetch row 7 of the keyboard from 3880H into Register A (bit 0 is the SHIFT key).
4557
RRCA 0F
Rotate Register A right: bit 0 (SHIFT) goes into the CARRY FLAG.
4558
If the NC FLAG is set (BREAK without SHIFT), JUMP to 4561H to interrupt the program if that is allowed.
455A
PUSH BC C5
Save Register Pair BC of the interrupted program to the stack, around the drive call.
455B
GOSUB to 4750H (SHIFT and BREAK held): the disk driver is called with function 01H for the current drive at 4308H, which selects it again and restarts its motor time out.
455E
POP BC C1
Restore Register Pair BC of the interrupted program from the stack.
455F
JUMP to 4539H to return to the interrupted program.
4561
LD A,(430FH) 3A 0F 43
Fetch the system flags from 430FH into Register A.
4564
BIT 4,A CB 67
Test bit 4 of Register A (set by a non breakable AUTO command, 4FB4H).
4566
If the NZ FLAG is set (BREAK is to be ignored), JUMP to 4539H to return to the interrupted program.
4568
LD HL,4315H 21 15 43
Point Register Pair HL to 4315H, the BREAK key vector.
456B
LD A,C3H 3E C3
Load Register A with C3H, the value 4315H holds when BREAK may interrupt the program.
456D
SUB (HL) 96
SUBtract the byte at Register Pair HL (4315H) from Register A: Register A = 00H and the Z FLAG set when 4315H holds C3H.
456E
If the NZ FLAG is set (4315H is not C3H: BREAK is not armed), JUMP to 4539H to return to the interrupted program.
4570
LD (HL),A 77
Store Register A (00H) to 4315H at Register Pair HL: the vector is disarmed, so one press of BREAK is taken only once.
4571
LD HL,(4316H) 2A 16 43
Fetch the address of the BREAK routine from 4316H-4317H into Register Pair HL.
4574
POP AF F1
Restore Register Pair AF of the interrupted program from the stack.
4575
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): Register Pair HL gets back the interrupted program's value and the stack holds the BREAK routine's address, above the interrupted program counter.
4576
EI FB
Enable interrupts again; the next instruction, the RET, still runs before any interrupt is taken.
4577
RET C9
RETURN, which jumps to the BREAK routine (the address from 4316H); the interrupted program counter is the next word on the stack.
4578H - Task Dispatcher
The vector of latch bit 7, the real time clock, called 40 times a second from 454BH. Slots 8, 9, 10 and 11 are run every time; then the tick counter 4040H is counted up and the slot given by its bits 2-0 is run. A task routine is entered with Index Register IX at its control block and 45BEH-45BFH holding the address of its slot.
4578
LD A,08H 3E 08
Load Register A with 08H, slot 8, the first of the four slots run at every clock interrupt.
457A
GOSUB to 4593H to run the task in slot Register A (8).
457D
LD A,09H 3E 09
Load Register A with 09H, slot 9, the second of the four slots run at every clock interrupt.
457F
GOSUB to 4593H to run the task in slot Register A (9).
4582
LD A,0AH 3E 0A
Load Register A with 0AH, slot 10, the third of the four slots run at every clock interrupt.
4584
GOSUB to 4593H to run the task in slot Register A (10).
4587
LD A,0BH 3E 0B
Load Register A with 0BH, slot 11, the last of the four slots run at every clock interrupt.
4589
GOSUB to 4593H to run the task in slot Register A (11).
458C
LD HL,4040H 21 40 40
Point Register Pair HL to 4040H, the tick counter.
458F
INC (HL) 34
Increment the tick counter at Register Pair HL (4040H).
4590
LD A,(HL) 7E
Fetch the new tick count from Register Pair HL (4040H) into Register A.
4591
AND 07H E6 07
Mask Register A to bits 2-0: one of slots 0-7, each in turn, and fall into 4593H to run it (its RET goes back to 454CH).
4593
RLCA 07
Rotate Register A (the slot number) left: Register A = slot x 2, the offset of the slot in the table at 4500H.
4594
LD L,A 6F
Copy Register A (slot x 2) into Register L, the low byte of the slot address.
4595
LD H,45H 26 45
Load Register H with 45H: Register Pair HL = 4500H + slot x 2, the slot.
4597
LD (45BEH),HL 22 BE 45
Store Register Pair HL (the slot's address) to 45BEH-45BFH, the operand of LD HL at 45BDH, so a task can suspend or remove itself through 4416H or 4419H.
459A
LD E,(HL) 5E
Fetch the low byte of the task control block's address from the slot at Register Pair HL into Register E.
459B
INC L 2C
Increment Register L to the slot's second byte.
459C
LD D,(HL) 56
Fetch the high byte from Register Pair HL into Register D: Register Pair DE = the task control block.
459D
PUSH DE D5
Save Register Pair DE (the task control block) to the stack, to move it into Index Register IX.
459E
POP IX DD E1
Restore Index Register IX from the stack: Index Register IX = the task control block, for the task's own use.
45A0
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the task control block.
45A1
LD E,(HL) 5E
Fetch byte +00H of the task control block at Register Pair HL into Register E: the low byte of the routine address.
45A2
INC HL 23
Increment Register Pair HL to byte +01H of the task control block, the high byte of the routine address.
45A3
LD D,(HL) 56
Fetch byte +01H from Register Pair HL into Register D: Register Pair DE = the task's routine.
45A4
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the task's routine.
45A5
JP (HL) E9
JUMP to the task's routine at Register Pair HL (for slots 8-11 it returns to the CALL above; for slots 0-7 to 454CH).
45A6
POP DE D1
Discard the top of the stack into Register Pair DE: the return address into the task that called 4419H, so the RET below goes back to the dispatcher instead.
45A7
LD A,(45BEH) 3A BE 45
Fetch the low byte of the running slot's address from 45BEH into Register A (slot x 2).
45AA
RRCA 0F
Rotate Register A right: Register A = the number of the running slot. Fall into 45ABH to empty it.
45AB
LD DE,45BBH 11 BB 45
Load Register Pair DE with 45BBH, the empty task control block (entry 4413H).
45AE
CP 0CH FE 0C
Compare Register A (the slot) against 0CH (entry 4410H: Register Pair DE the task control block to install).
45B0
RET NC D0
If the NC FLAG is set (slot 12 or more), RETURN without changing anything.
45B1
RLCA 07
Rotate Register A left: Register A = slot x 2.
45B2
LD L,A 6F
Copy Register A (slot x 2) into Register L, the low byte of the slot address.
45B3
LD H,45H 26 45
Load Register H with 45H: Register Pair HL = the slot at 4500H + slot x 2.
45B5
DI F3
Disable interrupts, so the dispatcher cannot run the slot while it holds half an address.
45B6
LD (HL),E 73
Store Register E (low byte of the control block address, or of the resume address from 45BDH) to the address at Register Pair HL.
45B7
INC L 2C
Increment Register L to the second byte of the slot (or of the task control block).
45B8
LD (HL),D 72
Store Register D (high byte) to the address at Register Pair HL.
45B9
EI FB
Enable interrupts again: the slot (or the routine address) now holds a whole address.
45BA
RET C9
RETURN to the caller (or, after 4416H and 4419H, to the dispatcher). 45BAH is also the routine of the empty task control block at 45BBH.
45BB-45BC
DEFW 45BAH BA 45
The empty task control block: its routine address is 45BAH, a RET. Slots hold 45BBH when they are empty, so the dispatcher can always call through them.
45BD
LD HL,0000H 21 00 00
Load Register Pair HL with the address of the running slot (operand 45BEH-45BFH, 0000H in the file, written by 4597H at each task call). Entry 4416H.
45C0
LD E,(HL) 5E
Fetch the low byte of the task control block's address from the slot at Register Pair HL into Register E.
45C1
INC HL 23
Increment Register Pair HL to the slot's second byte.
45C2
LD D,(HL) 56
Fetch the high byte from Register Pair HL into Register D: Register Pair DE = the task control block.
45C3
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the task control block.
45C4
POP DE D1
Restore Register Pair DE from the stack: the return address of the task's CALL 4416H, where the task is to go on next time.
45C5
JUMP to 45B5H to store Register Pair DE as the routine address at +00H-+01H of the control block at Register Pair HL and return to the dispatcher.
45C7H - The Clock Task
The reset installs this control block in slot 7 (4F92H-4F97H), so its routine runs 5 times a second; every fifth time it adds one second to the time of day at 4041H-4043H, carrying into minutes, hours and, at midnight, the day at 4045H.
45C7-45C8
DEFW 45CAH CA 45
Task control block +00H-+01H: 45CAH, the address of the clock routine.
45C9
DEFB 05H 05
Task control block +02H: the count of calls left before the next second, 05H.
45CA
DEC (IX+02H) DD 35 02
Decrement byte +02H of the task control block at Index Register IX (45C9H), the count of calls left.
45CD
RET NZ C0
If the NZ FLAG is set (a fifth of a second only), RETURN to the dispatcher.
45CE
LD (IX+02H),05H DD 36 02 05
Store 05H to byte +02H of the task control block at Index Register IX: five more calls to the next second.
45D2
LD B,03H 06 03
Load Register B with 03H: seconds, minutes and hours.
45D4
LD HL,4041H 21 41 40
Point Register Pair HL to 4041H, the seconds.
45D7
LD DE,45E6H 11 E6 45
Point Register Pair DE to 45E6H, the limits 60, 60 and 24.
45DA
INC (HL) 34
Increment the counter at Register Pair HL (4041H seconds, 4042H minutes or 4043H hours).
45DB
LD A,(DE) 1A
Fetch the limit from Register Pair DE into Register A.
45DC
SUB (HL) 96
SUBtract the counter at Register Pair HL from Register A: Register A = 00H and the Z FLAG set when the counter reached its limit.
45DD
RET NZ C0
If the NZ FLAG is set (below the limit), RETURN: the time is updated.
45DE
LD (HL),A 77
Store Register A (00H) to the counter at Register Pair HL: it starts again from 0 and the next counter is carried into.
45DF
INC L 2C
Increment Register L to the next counter (4042H, 4043H, then 4044H).
45E0
INC E 1C
Increment Register E to the next limit (45E7H, 45E8H).
45E1
Decrement Register B and JUMP to 45DAH while it is not zero.
45E3
INC L 2C
Increment Register L: Register Pair HL goes from 4044H (the year) to 4045H, the day.
45E4
INC (HL) 34
Increment the day at Register Pair HL (4045H). The day is not compared with the length of the month, and the month and year never change here.
45E5
RET C9
RETURN to the dispatcher with the day counted up and the time at 00:00:00.
45E6-45E8
DEFB 3CH,3CH,18H 3C 3C 18
The limits of the clock: 3CH (60 seconds), 3CH (60 minutes), 18H (24 hours), read through Register Pair DE at 45DBH.
45E9
DEFS 1
Not in the file, and not used by SYS0/SYS: the byte between the clock limits and the patch area.
45EA
GOSUB to 4BA9H to divide Register Pair HL (the sector number) by Register A (the record length): Register Pair HL = the quotient, Register A = the remainder. 45EAH-45F0H is the patch SYS0B (its record in the file), called from 4866H.
45ED
LD B,L 45
Copy Register L (low byte of the quotient) into Register B.
45EE
LD C,H 4C
Copy Register H (high byte of the quotient) into Register C.
45EF
LD H,A 67
Copy Register A (the remainder) into Register H, the high byte of the dividend for the second division at 486BH.
45F0
RET C9
RETURN to 4869H with Register B and Register C the quotient (low byte in Register B) and Register H the remainder.
45F1-45FF
DEFS 15
Not in the file, and not used by SYS0/SYS: the bytes between the patch area and the disk driver at 4600H.
4600H - The Floppy Disk Driver
Every drive code table that exists starts with JP 4600H, so every disk call reaches this driver through 478DH (JP (IY)). Index Register IY = the drive code table, Register B = the function, Register Pair DE = the cylinder (Register D) and sector (Register E), Register Pair HL = the buffer. Functions below 08H move the head: 01H select, 05H step in, 06H seek, 07H wait while the controller is busy, the others (00H, 02H-04H) restore to cylinder 0. Functions 08H and up (bit 3 set) transfer a sector: 08H, 09H and 0BH read, 0AH reads without storing, 0CH and 0DH write, 0EH writes with the data mark FAH, 0FH and up write a track. The driver returns the Z FLAG on success, or the NZ FLAG with an error code in Register A (01H-07H reading, 09H-0FH writing).
4600
LD A,B 78
Copy Register B (the function) into Register A for the compares below.
4601
BIT 3,B CB 58
Test bit 3 of Register B: set for the sector functions 08H and up.
4603
If the NZ FLAG is set (a sector function), JUMP to 4678H.
4605
CP 07H FE 07
Compare Register A (the function) against 07H, wait while busy.
4607
If the Z FLAG is set (function 07H), JUMP to 4646H to wait until the controller is not busy.
4609
CP 06H FE 06
Compare Register A (the function) against 06H, seek.
460B
If the Z FLAG is set (function 06H), JUMP to 4654H to seek to cylinder Register D.
460D
DEC A 3D
Decrement Register A (the function): Register A = 00H for function 01H.
460E
If the Z FLAG is set (function 01H), JUMP to 4621H to select the drive.
4610
INC (IY+05H) FD 34 05
Increment byte +05H of the drive code table at Index Register IY, the cylinder the head is on: the step in of function 05H moves it one cylinder in.
4613
CP 04H FE 04
Compare Register A (the function less one) against 04H: the Z FLAG is set for function 05H.
4615
LD B,58H 06 58
Load Register B with 58H, the controller's Step In command with the track register updated (bit 4); bits 1-0 get the stepping rate at 466CH.
4617
If the Z FLAG is set (function 05H), JUMP to 4666H to give the Step In command.
4619
LD (IY+05H),00H FD 36 05 00
Store 00H to byte +05H of the drive code table at Index Register IY: the head will be on cylinder 0. Every other function below 08H comes here, and so does the sector loop after RECORD NOT FOUND (46EEH).
461D
LD B,08H 06 08
Load Register B with 08H, the controller's Restore command (head to cylinder 0, the head loaded); the stepping rate goes into bits 1-0 at 466CH.
461F
JUMP to 4666H to select the drive and give the Restore command in Register B (08H).
4621
GOSUB to 4646H to wait until the controller is not busy (Register A returns with the status, bit 0 clear). Function 01H, select.
4624
RLCA 07
Rotate Register A (the status) left: bit 7, NOT READY, goes into the CARRY FLAG.
4625
LD A,(IY+04H) FD 7E 04
Fetch byte +04H of the drive code table at Index Register IY into Register A: the drive's select byte (bits 3-0 one bit for drives 0-3: 01H, 02H, 04H, 08H).
4628
LD (37E1H),A 32 E1 37
Store Register A (the select byte) to the drive select latch at 37E1H: the drive is selected and the motor time out starts again.
462B
LD (4309H),A 32 09 43
Store Register A (the select byte) to 4309H, so the busy wait at 4646H can write it again.
462E
RET NC D0
If the NC FLAG is set (the drive was ready), RETURN with the drive selected.
462F
LD A,(430FH) 3A 0F 43
Fetch the system flags from 430FH into Register A (the drive was not ready: its motor was off and must come up to speed).
4632
BIT 3,A CB 5F
Test bit 3 of Register A, the fast clock (set and cleared by SYS6/SYS, its 521BH, 5228H).
4634
If the NZ FLAG is set (the fast clock is on), GOSUB to 4637H, so the wait below is made twice.
4637
BIT 2,(IY+03H) FD CB 03 56
Test bit 2 of byte +03H of the drive code table at Index Register IY: 1 for the shorter wait for a drive that is not ready.
463B
If the Z FLAG is set (bit 2 clear, the longer wait), GOSUB to 463EH for one more delay first.
463E
PUSH BC C5
Save Register Pair BC to the stack (Register B the function, or the controller command when reached through 4666H; Register C the caller's).
463F
LD B,7FH 06 7F
Load Register B with 7FH: with Register C, a count of 7F00H-7FFFH for the ROM's delay.
4641
GOSUB to the ROM's 0060H, which counts Register Pair BC down to zero: the drive's motor comes up to speed meanwhile.
4644
POP BC C1
Restore Register Pair BC from the stack: Register B and Register C as they were before the delay.
4645
RET C9
RETURN (to 4637H after the CALL NZ at 4634H, to 463EH after the CALL Z at 463BH, or to the caller of the select).
4646
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A. Function 07H, wait while busy; also the vector of latch bit 6, the disk controller's interrupt.
4649
BIT 0,A CB 47
Test bit 0 of Register A (the status), BUSY: set while the controller is still carrying out a command.
464B
RET Z C8
If the Z FLAG is set (not busy), RETURN with the status in Register A.
464C
LD A,(4309H) 3A 09 43
Fetch the select byte last written from 4309H into Register A.
464F
LD (37E1H),A 32 E1 37
Store Register A to the drive select latch at 37E1H again, so the motor time out does not stop the drive while the controller is busy.
4652
JUMP back to 4646H to read the status again until BUSY is off.
4654
GOSUB to 4646H to wait until the controller is not busy. Function 06H, seek to cylinder Register D (Register E the sector for the transfer that follows).
4657
LD A,(IY+05H) FD 7E 05
Fetch byte +05H of the drive code table at Index Register IY into Register A: the cylinder the head is on now.
465A
LD (37EDH),A 32 ED 37
Store Register A (the present cylinder) to the controller's track register at 37EDH, so the seek steps from there.
465D
LD (37EEH),DE ED 53 EE 37
Store Register Pair DE to 37EEH-37EFH: Register E (the sector) to the sector register, Register D (the cylinder wanted) to the data register, where the Seek command takes its target from.
4661
LD (IY+05H),D FD 72 05
Store Register D (the cylinder wanted) to byte +05H of the drive code table at Index Register IY: the head will be there.
4664
LD B,18H 06 18
Load Register B with 18H, the controller's Seek command with the head loaded (bit 3); the stepping rate goes into bits 1-0 below.
4666
GOSUB to 4621H to wait until the controller is not busy and select the drive (with the motor wait when it was not ready).
4669
LD A,(IY+03H) FD 7E 03
Fetch byte +03H of the drive code table at Index Register IY into Register A.
466C
AND 03H E6 03
Mask Register A to bits 1-0, the stepping rate of the drive.
466E
OR B B0
OR Register A with Register B, the command (08H, 18H or 58H): the stepping rate goes into its bits 1-0.
466F
LD (37ECH),A 32 EC 37
Store Register A (the command) to the controller's command register at 37ECH. The sector loop calls here with its read or write command (46C4H).
4672
LD B,08H 06 08
Load Register B with 08H, a count for the short wait before the status is valid.
4674
Decrement Register B and JUMP to 4674H while it is not zero: 8 passes of DJNZ.
4676
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A): success.
4677
RET C9
RETURN with Register A = 00H and the Z FLAG set; the command runs on in the controller.
4678
BIT 2,B CB 50
Test bit 2 of Register B (the function): set for the writes 0CH-0FH, clear for the reads 08H-0BH.
467A
LD B,05H 06 05
Load Register B with 05H, the number of tries for a write or a read without storing. LD does not change the flags of the BIT test.
467C
If the NZ FLAG is set (a write function), JUMP to 4692H.
467E
LD C,88H 0E 88
Load Register C with 88H, the controller's Read Sector command (one sector, bit 3 set for the IBM sector length code, the data mark returned in the status).
4680
CP 0AH FE 0A
Compare Register A (the function) against 0AH, the read without storing.
4682
If the Z FLAG is set (function 0AH), JUMP to 468CH with 5 tries.
4684
LD B,0AH 06 0A
Load Register B with 0AH: 10 tries for a read.
4686
GOSUB to 46A4H, which takes the three bytes after this CALL as data and goes on to the sector loop without returning: error base 01H and the transfer code 1AH 02H.
4689-468B
DEFB 01H,1AH,02H 01 1A 02
Data for 46A4H: 01H, the error base of a read (01H plus the number of the status bit gives the error code); 1AH 02H, the opcodes LD A,(DE) and LD (BC),A, copied to 46D4H-46D5H: each byte goes from the data register into the buffer.
468C
GOSUB to 46A4H with the three bytes below: function 0AH, a read that does not store the bytes.
468F-4691
DEFB 01H,1AH,00H 01 1A 00
Data for 46A4H: 01H, the error base of a read; 1AH 00H, the opcodes LD A,(DE) and NOP: each byte is taken from the data register and thrown away, so only the controller's checks count.
4692
LD C,A8H 0E A8
Load Register C with A8H, the controller's Write Sector command (one sector, data mark FBH). Writes come here with 5 tries in Register B.
4694
CP 0EH FE 0E
Compare Register A (the function) against 0EH.
4696
If the C FLAG is set (function 0CH or 0DH), JUMP to 469EH with the Write Sector command A8H.
4698
LD C,A9H 0E A9
Load Register C with A9H: Write Sector with bits 1-0 = 01, the data mark FAH, which the directory sectors carry.
469A
If the Z FLAG is set (function 0EH), JUMP to 469EH with the command A9H.
469C
LD C,F4H 0E F4
Load Register C with F4H, the controller's Write Track command (function 0FH and up): the buffer holds a whole track image.
469E
GOSUB to 46A4H with the three bytes below: the writes.
46A1-46A3
DEFB 09H,0AH,12H 09 0A 12
Data for 46A4H: 09H, the error base of a write; 0AH 12H, the opcodes LD A,(BC) and LD (DE),A: each byte goes from the buffer into the data register.
46A4
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): Register Pair HL = the address of the three data bytes after the CALL, the stack holds the buffer address.
46A5
LD A,(HL) 7E
Fetch the first data byte from Register Pair HL into Register A: the error base, 01H or 09H.
46A6
INC HL 23
Increment Register Pair HL to the first opcode byte.
46A7
LD (46F9H),A 32 F9 46
Store Register A (the error base) to 46F9H, the operand of LD A,00H at 46F8H, where the error code is counted.
46AA
LD A,(HL) 7E
Fetch the first opcode from Register Pair HL into Register A (1AH or 0AH).
46AB
INC HL 23
Increment Register Pair HL to the second opcode byte.
46AC
LD H,(HL) 66
Fetch the second opcode from Register Pair HL into Register H (02H, 00H or 12H).
46AD
LD L,A 6F
Copy Register A (the first opcode) into Register L: Register Pair HL = the two opcodes.
46AE
LD (46D4H),HL 22 D4 46
Store Register Pair HL (the two opcodes) to 46D4H-46D5H, inside the transfer loop.
46B1
POP HL E1
Restore Register Pair HL from the stack: the buffer address. The return address of the CALL was taken by EX (SP),HL, so the code goes on here, into the sector loop.
46B2
PUSH BC C5
Save Register Pair BC to the stack: Register B the tries left, Register C the command. Each try starts here.
46B3
BIT 4,C CB 61
Test bit 4 of Register C (the command): set only in F4H, Write Track.
46B5
If the Z FLAG is set (a sector command), GOSUB to 4654H to seek to cylinder Register D with sector Register E in the sector register.
46B8
PUSH DE D5
Save Register Pair DE (the cylinder and sector) to the stack.
46B9
PUSH HL E5
Save Register Pair HL (the buffer address) to the stack.
46BA
LD HL,37ECH 21 EC 37
Point Register Pair HL to 37ECH, the controller's command and status register.
46BD
LD DE,37EFH 11 EF 37
Point Register Pair DE to 37EFH, the controller's data register.
46C0
GOSUB to 4646H to wait until the controller is not busy (after the seek).
46C3
LD A,C 79
Copy Register C (the read or write command) into Register A.
46C4
GOSUB to 466FH to write the command in Register A to 37ECH and wait the short delay.
46C7
POP BC C1
Restore Register Pair BC from the stack: the buffer address saved at 46B9H. Register Pair BC is the pointer into the buffer from here.
46C8
PUSH BC C5
Save Register Pair BC (the buffer address) to the stack again, for the next try.
46C9
JUMP to 46CEH to read the status from 37ECH and wait for the first DATA REQUEST.
46CB
RRCA 0F
Rotate Register A (the status) right: bit 0, BUSY, goes into the CARRY FLAG.
46CC
If the NC FLAG is set (no longer busy: the command has ended), JUMP to 46DAH.
46CE
LD A,(HL) 7E
Fetch the status from 37ECH at Register Pair HL into Register A.
46CF
BIT 1,A CB 4F
Test bit 1 of Register A (the status), DATA REQUEST: a byte is waiting in the data register, or one is wanted.
46D1
If the Z FLAG is set (no byte waiting), JUMP to 46CBH to test BUSY.
46D3
DI F3
Disable interrupts: no interrupt may come between the bytes of the transfer. They stay off until 46DAH.
46D4
NOP 00
No operation in the file. 46D4H-46D5H receive the two opcodes from 46AEH: LD A,(DE) and LD (BC),A for a read (data register at Register Pair DE into the buffer at Register Pair BC), LD A,(DE) and NOP for a read without storing, LD A,(BC) and LD (DE),A for a write.
46D5
NOP 00
No operation in the file: the second opcode written by 46AEH (02H, 00H or 12H).
46D6
INC BC 03
Increment Register Pair BC, the pointer into the buffer, to the next byte.
46D7
JUMP back to 46CEH for the next DATA REQUEST.
46DA
EI FB
Enable interrupts again: the command has ended.
46DB
LD A,(HL) 7E
Fetch the final status from 37ECH at Register Pair HL into Register A.
46DC
AND 7CH E6 7C
Mask Register A with 7CH: bit 2 LOST DATA, bit 3 CRC ERROR, bit 4 RECORD NOT FOUND, bits 5-6 the data mark read (a read) or WRITE FAULT and WRITE PROTECT (a write). The Z FLAG is set when none is set.
46DE
POP HL E1
Restore Register Pair HL from the stack: the buffer address.
46DF
POP DE D1
Restore Register Pair DE from the stack: the cylinder and sector.
46E0
POP BC C1
Restore Register Pair BC from the stack: the tries left and the command.
46E1
RET Z C8
If the Z FLAG is set (no error bit), RETURN with Register A = 00H.
46E2
BIT 2,A CB 57
Test bit 2 of Register A (the error bits), LOST DATA: a byte was not taken or given in time.
46E4
If the NZ FLAG is set (a byte was lost), JUMP to 46B2H to try again; this try is not counted.
46E6
PUSH AF F5
Save Register Pair AF (the error bits in Register A) to the stack.
46E7
AND 18H E6 18
Mask Register A to bits 4 and 3, RECORD NOT FOUND and CRC ERROR, the errors worth another try.
46E9
If the Z FLAG is set (only bits 5 or 6: a data mark or a write fault or write protect), JUMP to 46F6H to give the error at once.
46EB
BIT 4,A CB 67
Test bit 4 of Register A (the error bits), RECORD NOT FOUND: no sector with this cylinder and sector number was found.
46ED
PUSH BC C5
Save Register Pair BC (the tries left and the command) to the stack.
46EE
If the NZ FLAG is set (RECORD NOT FOUND), GOSUB to 4619H to restore the head to cylinder 0, so the next seek steps from a known place.
46F1
POP BC C1
Restore Register Pair BC from the stack: the tries left and the command.
46F2
POP AF F1
Restore Register Pair AF from the stack: Register A holds the error bits.
46F3
Decrement Register B (the tries left) and JUMP to 46B2H to try again while it is not zero.
46F5
LD B,F1H 06 F1
Load Register B with F1H. The tries are used up; the byte F1H is here only to skip the POP AF at 46F6H, which the JR Z at 46E9H enters (Register Pair AF is already off the stack on this path). Register B is replaced at once.
46F7
LD B,A 47
Copy Register A (the error bits of the status) into Register B. 46F6H enters with POP AF (F1H) just before this row.
46F8
LD A,00H 3E 00
Load Register A with the error base: the operand at 46F9H is 00H in the file, 01H for a read or 09H for a write after 46A7H.
46FA
RRC B CB 08
Rotate Register B right: the lowest status bit goes into the CARRY FLAG.
46FC
RET C D8
If the C FLAG is set (the lowest error bit is found), RETURN with Register A = the error code and the NZ FLAG (the rotated bit is now bit 7 of Register B). A read gives 03H lost data, 04H CRC error, 05H record not found, 06H for status bit 5 (the data mark FAH of the directory, or F8H), 07H for bit 6 alone; a write 0BH-0FH, 0FH write protected.
46FD
INC A 3C
Increment Register A, the error code, for the next bit.
46FE
JUMP back to 46FAH to test the next bit of Register B.
4700H - Drive Code Tables
Ten bytes for each of the drives 0-7. +00H-+02H a jump to the driver (C9H for a drive that does not exist: the call returns at once with error 20H, 4783H-4786H); +03H bits 1-0 the stepping rate, bit 2 the shorter wait for a drive that is not ready; +04H the select byte for 37E1H; +05H the cylinder the head is on; +06H the last cylinder; +07H bits 4-0 the highest sector number of a track; +08H bits 4-0 the sectors of a granule less one, bits 7-5 the granules of a cylinder less one; +09H the directory cylinder. The reset copies drives 1-7 from the system information sector (4F87H-4F90H) and drive 0 from Index Register IY after a boot through a driver (4E6EH-4E7BH).
4700-4702
DEFB C3H,00H,46H C3 00 46
Drive 0, +00H-+02H: JP 4600H, the floppy disk driver.
4703
DEFB 83H 83
Drive 0, +03H: 83H. Bits 1-0 = 3, the slowest stepping rate (40 ms in the drive display of SYS6/SYS); bit 2 clear, the longer motor wait (4637H); bit 7 set, which SYS0/SYS does not test.
4704
DEFB 01H 01
Drive 0, +04H: 01H, the select byte (bit 0, drive 0) written to 37E1H and 4309H at 4628H-462BH.
4705
DEFB 01H 01
Drive 0, +05H: 01H, taken as the cylinder the head is on; the first seek loads it into the track register (4657H-465AH) and stores the new cylinder.
4706-4709
DEFB 22H,09H,24H,11H 22 09 24 11
Drive 0, +06H-+09H: 22H, the last cylinder (34: 35 cylinders); 09H, sectors 0-9 on a track; 24H, 5 sectors a granule (bits 4-0 = 4) and 2 granules a cylinder (bits 7-5 = 1); 11H, the directory on cylinder 17.
470A-470C
DEFB C3H,00H,46H C3 00 46
Drive 1, +00H-+02H: JP 4600H, the floppy disk driver. The reset copies drives 1-7 from bytes 2AH-6FH of the system information sector over this table (4F87H-4F90H).
470D-4713
DEFB 03H,02H,11H,22H,09H,24H,11H 03 02 11 22 09 24 11
Drive 1, +03H-+09H: 03H stepping rate 3, the longer motor wait; 02H select bit 1; 11H the head taken to be on cylinder 17; 22H last cylinder 34; 09H sectors 0-9; 24H 5 sectors a granule, 2 granules a cylinder; 11H directory cylinder 17.
4714-4716
DEFB C3H,00H,46H C3 00 46
Drive 2, +00H-+02H: JP 4600H, the floppy disk driver.
4717-471D
DEFB 03H,04H,11H,22H,09H,24H,11H 03 04 11 22 09 24 11
Drive 2, +03H-+09H: 03H stepping rate 3; 04H select bit 2; 11H head on cylinder 17; 22H last cylinder 34; 09H sectors 0-9; 24H 5 sectors a granule, 2 granules a cylinder; 11H directory cylinder 17.
471E-4720
DEFB C3H,00H,46H C3 00 46
Drive 3, +00H-+02H: JP 4600H, the floppy disk driver.
4721-4727
DEFB 03H,08H,11H,22H,09H,24H,11H 03 08 11 22 09 24 11
Drive 3, +03H-+09H: 03H stepping rate 3; 08H select bit 3; 11H head on cylinder 17; 22H last cylinder 34; 09H sectors 0-9; 24H 5 sectors a granule, 2 granules a cylinder; 11H directory cylinder 17.
4728-4731
DEFB C9H,00H,00H,00H,00H,00H,00H,00H,00H,00H C9 00 00 00 00 00 00 00 00 00
Drive 4: C9H (RET) in +00H and nine bytes of 00H. A call through it returns at once with Register A = 20H and the NZ FLAG (4783H-4786H): error 20H, ILLEGAL DRIVE NUMBER.
4732-473B
DEFB C9H,00H,00H,00H,00H,00H,00H,00H,00H,00H C9 00 00 00 00 00 00 00 00 00
Drive 5: C9H (RET) in +00H and nine bytes of 00H, a drive that does not exist (error 20H on any call).
473C-4745
DEFB C9H,00H,00H,00H,00H,00H,00H,00H,00H,00H C9 00 00 00 00 00 00 00 00 00
Drive 6: C9H (RET) in +00H and nine bytes of 00H, a drive that does not exist (error 20H on any call).
4746-474F
DEFB C9H,00H,00H,00H,00H,00H,00H,00H,00H,00H C9 00 00 00 00 00 00 00 00 00
Drive 7: C9H (RET) in +00H and nine bytes of 00H, a drive that does not exist (error 20H on any call).
4750H - Calls to the Disk Driver
One entry for each driver function used by the system. Each saves Register Pair BC, puts the function in Register B and goes to 477AH, which records the drive in Register C at 4308H, points Index Register IY at its drive code table and calls through the table's first three bytes. Register Pair DE (cylinder and sector) and Register Pair HL (buffer) pass straight to the driver. Index Register IY and Register Pair BC are returned unchanged.
4750
LD A,(4308H) 3A 08 43
Fetch the current drive number from 4308H into Register A. Function 01H, select the current drive again (the SHIFT and BREAK keys, 455BH).
4753
LD C,A 4F
Copy Register A (the current drive) into Register C, where 477AH takes the drive from.
4754
PUSH BC C5
Save Register Pair BC to the stack (popped at 478BH).
4755
LD B,01H 06 01
Load Register B with 01H, the driver's select function.
4757
JUMP to 477AH to call the driver for the drive in Register C.
4759
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack. Function 07H, wait while the controller is busy.
475A
LD B,07H 06 07
Load Register B with 07H, the driver's wait function.
475C
JUMP to 477AH to call the driver for the drive in Register C.
475E
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack. Function 06H, seek to cylinder Register D.
475F
LD B,06H 06 06
Load Register B with 06H, the driver's seek function.
4761
JUMP to 477AH to call the driver for the drive in Register C.
4763
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack. Function 0DH, write the sector at Register Pair DE from the buffer at Register Pair HL.
4764
LD B,0DH 06 0D
Load Register B with 0DH, the driver's sector write with the data mark FBH.
4766
JUMP to 477AH to call the driver for the drive in Register C.
4768
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack. Function 0EH, write a sector with the data mark FAH (the directory).
4769
LD B,0EH 06 0E
Load Register B with 0EH, the driver's sector write with the data mark FAH.
476B
JUMP to 477AH to call the driver for the drive in Register C.
476D
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack. Function 0FH, write a whole track from the buffer at Register Pair HL.
476E
LD B,0FH 06 0F
Load Register B with 0FH, the driver's Write Track function.
4770
JUMP to 477AH to call the driver for the drive in Register C.
4772
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack. Function 0AH, read the sector at Register Pair DE without storing it (a check after a write).
4773
LD B,0AH 06 0A
Load Register B with 0AH, the driver's read that does not store.
4775
JUMP to 477AH to call the driver for the drive in Register C.
4777
PUSH BC C5
Save Register Pair BC (Register C the drive) to the stack. Function 09H, read the sector at Register Pair DE into the buffer at Register Pair HL.
4778
LD B,09H 06 09
Load Register B with 09H, the driver's sector read; fall into 477AH.
477A
LD A,C 79
Copy Register C (the drive number passed by the caller, or from 4308H) into Register A.
477B
LD (4308H),A 32 08 43
Store Register A (the drive) to 4308H, the current drive.
477E
PUSH IY FD E5
Save Index Register IY (the caller's) to the stack.
4780
GOSUB to 478FH to point Index Register IY at the drive code table of the drive in Register C (4700H + 10 x drive).
4783
LD A,20H 3E 20
Load Register A with 20H, the error code ILLEGAL DRIVE NUMBER, for a table that holds C9H (RET).
4785
OR A B7
OR Register A with itself: the NZ FLAG is set, so a drive that returns at once returns error 20H.
4786
GOSUB to 478DH, which jumps through the drive code table at Index Register IY: to the driver at 4600H, or to a RET.
4789
POP IY FD E1
Restore Index Register IY (the caller's) from the stack.
478B
POP BC C1
Restore Register Pair BC (saved by the entry) from the stack.
478C
RET C9
RETURN with the driver's result: the Z FLAG on success, the NZ FLAG and the error code in Register A.
478D
JP (IY) FD E9
JUMP to the address in Index Register IY, the first byte of the drive code table: its JP 4600H, or C9H.
478F
PUSH HL E5
Save Register Pair HL to the stack. Point Index Register IY at the drive code table of the drive in Register C (SYS2/SYS, SYS6/SYS, SYS9/SYS and BACKUP/CMD call it too).
4790
GOSUB to 47A0H: Register Pair HL = the drive code table of the drive in Register C.
4793
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): the caller's Register Pair HL comes back, the table address goes onto the stack.
4794
POP IY FD E1
Restore Index Register IY from the stack: Index Register IY = the drive code table.
4796
RET C9
RETURN with Index Register IY at the table and Register Pair HL unchanged.
4797
PUSH HL E5
Save Register Pair HL to the stack. Fetch byte Register A (an offset 00H-09H) of the drive code table of the drive in Register C into Register A.
4798
LD H,A 67
Copy Register A (the offset) into Register H, which 47A0H adds to the table's low byte.
4799
GOSUB to 47A0H: Register Pair HL = the table, Register A = the low byte of the table address plus the offset.
479C
LD L,A 6F
Copy Register A (low byte of the byte's address) into Register L: Register Pair HL = the byte (Register H = 47H).
479D
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A.
479E
POP HL E1
Restore Register Pair HL from the stack: the caller's value, unchanged.
479F
RET C9
RETURN with Register A = the byte of the drive code table.
47A0
LD A,C 79
Copy Register C (the drive) into Register A. Work out the address of the drive's table.
47A1
AND 07H E6 07
Mask Register A (the drive) to bits 2-0: drives 0-7, eight tables of 10 bytes.
47A3
ADD A,A 87
Add Register A to itself: Register A = drive x 2.
47A4
LD L,A 6F
Copy Register A (drive x 2) into Register L, kept to make drive x 10 below.
47A5
ADD A,A 87
Add Register A to itself: Register A = drive x 4.
47A6
ADD A,A 87
Add Register A to itself: Register A = drive x 8.
47A7
ADD A,L 85
Add Register L (drive x 2) to Register A: Register A = drive x 10, the offset of the drive's table.
47A8
ADD A,00H C6 00
Add 00H to Register A: the operand at 47A9H is the low byte of the first table (4700H).
47AA
LD L,A 6F
Copy Register A (the table's low byte) into Register L.
47AB
ADD A,H 84
Add Register H (an offset into the table, from 4797H) to Register A.
47AC
LD H,47H 26 47
Load Register H with 47H: Register Pair HL = 4700H + drive x 10.
47AE
RET C9
RETURN with Register Pair HL = the drive code table and Register A = its low byte plus the offset in Register H.
47AF
DEFS 1
Not in the file, and not used by SYS0/SYS: the byte between 47AEH and the file routines at 47B0H.
47B0H - Position to a Record (4442H)
Each file request starts with CALL 49EBH, which checks that Register Pair DE points at an open file control block, points Index Register IX at it, saves Register Pairs BC, DE, HL and Index Register IX and arranges for them to be restored on the way out. A file's position is the next record number at +0AH-+0BH (a sector of the file) and the byte offset at +05H; bit 5 of +01H set means the sector at +0AH-+0BH must be read before the next byte, bit 5 clear means the buffer holds the sector before it. Register Pair BC = the record number; in record mode (bit 7 of +01H, a record length other than 256) it is multiplied by the record length to give the sector and offset.
47B0
GOSUB to 49EBH to check the control block at Register Pair DE: on return Index Register IX = the control block, Register A = 00H; when the file is not open 49EBH returns to this routine's caller with error 26H.
47B3
SET 6,(IX+01H) DD CB 01 F6
Set bit 6 of byte +01H of the control block at Index Register IX: the file has been positioned, so a write inside it no longer moves the end of file back (4930H, 49D2H).
47B7
BIT 7,(IX+01H) DD CB 01 7E
Test bit 7 of byte +01H of the control block at Index Register IX: set by the open when the record length is not 256 (record mode).
47BB
If the Z FLAG is set (whole sectors), JUMP to 47DFH with Register Pair BC as the sector number and Register A = 00H as the offset.
47BD
LD H,B 60
Copy Register B (high byte of the record number) into Register H.
47BE
LD L,C 69
Copy Register C (low byte of the record number) into Register L: Register Pair HL = the record number.
47BF
LD A,(IX+09H) DD 7E 09
Fetch the record length from byte +09H of the control block at Index Register IX into Register A.
47C2
OR A B7
OR Register A (the record length) with itself: the Z FLAG is set for 00H, a length of 256.
47C3
If the Z FLAG is set (256 byte records), JUMP to 47DFH: Register Pair BC is the sector number and Register A = 00H the offset.
47C5
GOSUB to 4B8FH to multiply Register Pair HL (the record number) by Register A (the record length): Register A = the low byte of the product (the offset in the sector), Register Pair HL = the rest (the sector).
47C8
LD B,H 44
Copy Register H (high byte of the sector) into Register B.
47C9
LD C,L 4D
Copy Register L (low byte of the sector) into Register C: Register Pair BC = the sector that holds the record.
47CA
LD (IX+05H),A DD 77 05
Store Register A (the offset of the record in its sector) to byte +05H of the control block at Index Register IX.
47CD
BIT 5,(IX+01H) DD CB 01 6E
Test bit 5 of byte +01H of the control block at Index Register IX: set when the buffer does not hold the sector before +0AH-+0BH.
47D1
If the NZ FLAG is set (the buffer is not usable), JUMP to 47E2H to set the position.
47D3
LD L,(IX+0AH) DD 6E 0A
Fetch the low byte of the next record number from +0AH of the control block at Index Register IX into Register L.
47D6
LD H,(IX+0BH) DD 66 0B
Fetch the high byte from +0BH of the control block at Index Register IX into Register H: Register Pair HL = the next record number.
47D9
SCF 37
Set the CARRY FLAG, so the subtraction below takes one more away.
47DA
SBC HL,BC ED 42
SUBtract Register Pair BC (the sector wanted) and the carry from Register Pair HL: Register Pair HL = next record number less one less the sector wanted.
47DC
RET Z C8
If the Z FLAG is set (the buffer already holds the sector wanted), RETURN: only the offset at +05H changed.
47DD
JUMP to 47E2H to set the position to the sector in Register Pair BC.
47DF
LD (IX+05H),A DD 77 05
Store Register A (the offset: 00H, or the end of file offset from 482DH) to byte +05H of the control block at Index Register IX.
47E2
PUSH BC C5
Save Register Pair BC (the sector to position to) to the stack.
47E3
GOSUB to 4988H to write the buffer back to its sector first when it holds changed bytes in record mode.
47E6
POP BC C1
Restore Register Pair BC (the sector) from the stack.
47E7
RET NZ C0
If the NZ FLAG is set (the write back failed), RETURN with the error code in Register A.
47E8
LD (IX+0AH),C DD 71 0A
Store Register C (low byte of the sector) to the next record number, byte +0AH of the control block at Index Register IX.
47EB
LD (IX+0BH),B DD 70 0B
Store Register B (high byte of the sector) to byte +0BH of the control block at Index Register IX.
47EE
SET 5,(IX+01H) DD CB 01 EE
Set bit 5 of byte +01H of the control block at Index Register IX: the sector at +0AH-+0BH is to be read before the next byte.
47F2
JUMP to 4A15H to compare the new position with the end of file and return the result: the Z FLAG before the end, error 1CH at it, error 1DH past it.
47F5H - Move On One Record (4460H)
The entry 4460H leads here. The routine calls 4851H, the end of the record number routine, which takes its own return address off the stack and puts the record number in its place (4870H-4873H): back here Register Pair BC holds 47FBH and Register Pair HL 4A0CH, and the RET that ends the request finds the record number where its return address should be. No file on this diskette uses 4460H.
47F5
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
47F8
GOSUB to 4851H to work out the record number of the current position; its exit (4870H) pops this call's return address into Register Pair BC, puts the record number on the stack in place of 4A0CH (the address that would restore the registers) and returns here with Register Pair BC = 47FBH and Register Pair HL = 4A0CH.
47FB
INC BC 03
Increment Register Pair BC (47FBH from 4870H, not a record number): Register Pair BC = 47FCH.
47FC
JUMP to 47DFH to store Register A as the offset and position to the sector in Register Pair BC (47FCH).
47FEH - Back One Record (4445H)
The offset at +05H is moved back by the record length. When it stays in the same sector the position is set; when it goes below 0, the routine sets the next record number to one less and marks the sector to be read.
47FE
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
4801
LD A,(IX+09H) DD 7E 09
Fetch the record length from byte +09H of the control block at Index Register IX into Register A.
4804
NEG ED 44
Negate Register A: Register A = 256 less the record length (00H stays 00H for 256 byte records).
4806
ADD A,(IX+05H) DD 86 05
Add byte +05H of the control block at Index Register IX (the offset) to Register A: the CARRY FLAG is set when the offset is at least the record length.
4809
LD (IX+05H),A DD 77 05
Store Register A (the new offset) to byte +05H of the control block at Index Register IX.
480C
RET Z C8
If the Z FLAG is set (the new offset is 00H, or the record length is 256 and the offset was 00H), RETURN with the Z FLAG.
480D
If the NC FLAG is set (the offset went below 0: the record starts before the buffer's offset 00H), JUMP to 4811H. The next record number less one is the sector before only when bit 5 of +01H is set (offset 00H); with bit 5 clear it is the sector already in the buffer.
480F
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A): the record starts in the same sector.
4810
RET C9
RETURN with Register A = 00H and the Z FLAG set: success.
4811
LD C,(IX+0AH) DD 4E 0A
Fetch the low byte of the next record number from +0AH of the control block at Index Register IX into Register C.
4814
LD B,(IX+0BH) DD 46 0B
Fetch the high byte from +0BH of the control block at Index Register IX into Register B: Register Pair BC = the next record number.
4817
DEC BC 0B
Decrement Register Pair BC (the next record number): it now names the sector the buffer was read from, or the one before it when bit 5 of +01H was set.
4818
JUMP to 47E2H to make Register Pair BC the next record number with the sector to be read.
481AH - Back to the Buffer's Sector (4454H)
The next record number less one is the sector the buffer was read from; it becomes the next record number, marked to be read again, and the offset stays.
481A
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
481D
LD C,(IX+0AH) DD 4E 0A
Fetch the low byte of the next record number from +0AH of the control block at Index Register IX into Register C.
4820
LD B,(IX+0BH) DD 46 0B
Fetch the high byte from +0BH of the control block at Index Register IX into Register B: Register Pair BC = the next record number.
4823
DEC BC 0B
Decrement Register Pair BC: the sector the buffer holds.
4824
JUMP to 47E2H to make Register Pair BC the next record number with the sector to be read.
4826H - Rewind (443FH)
The position goes to sector 0, offset 0.
4826
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it; Register A returns 00H.
4829
LD B,A 47
Copy Register A (00H) into Register B, the high byte of the sector.
482A
LD C,A 4F
Copy Register A (00H) into Register C: Register Pair BC = 0000H, the first sector.
482B
JUMP to 47DFH to store Register A (00H) as the offset and position to sector Register Pair BC (0000H).
482DH - Position to the End of File (4448H)
The ending record number at +0CH-+0DH and the end of file offset at +08H give the end: when the offset is 00H the end is the start of the sector +0CH-+0DH, otherwise it is that offset in the sector before.
482D
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
4830
LD C,(IX+0CH) DD 4E 0C
Fetch the low byte of the ending record number from +0CH of the control block at Index Register IX into Register C.
4833
LD B,(IX+0DH) DD 46 0D
Fetch the high byte from +0DH of the control block at Index Register IX into Register B: Register Pair BC = the ending record number.
4836
LD A,(IX+08H) DD 7E 08
Fetch the end of file offset from byte +08H of the control block at Index Register IX into Register A.
4839
OR A B7
OR Register A (the end of file offset) with itself: the Z FLAG is set when the file ends at a sector boundary.
483A
If the Z FLAG is set, JUMP to 47DFH to position to sector Register Pair BC (the ending record number) at offset 00H.
483C
DEC BC 0B
Decrement Register Pair BC: the end is inside the sector before the ending record number.
483D
JUMP to 47DFH to position to sector Register Pair BC at offset Register A (the end of file offset).
483FH - Move the Head to the Position (4451H)
When the position is before the end of file, its cylinder and sector are worked out and the drive seeks there, so a later read starts sooner.
483F
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
4842
GOSUB to 4A15H to compare the position with the end of file: the Z FLAG when it is before the end.
4845
If the Z FLAG is set (before the end), GOSUB to 4A3CH to work out the cylinder (Register D) and sector (Register E) of the next record number.
4848
RET NZ C0
If the NZ FLAG is set (at or past the end, or no sector found), RETURN with the error code in Register A.
4849
GOSUB to 475EH to seek the drive at Register C (reloaded from +06H at 4AEEH) to cylinder Register D, sector Register E.
484C
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A): success, whatever the seek returned.
484D
RET C9
RETURN with Register A = 00H and the Z FLAG set.
484EH - Record Number of the Position (445AH)
Register Pair BC returns the number of the record at the current position (Register A the bits above 16, with the Z FLAG when they are 0). In record mode the byte position (sector x 256 + offset) is divided by the record length in two steps; the second step is the patch SYS0B at 4863H and 45EAH. 4851H is also called from 47F8H.
484E
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
4851
LD L,(IX+0AH) DD 6E 0A
Fetch the low byte of the next record number from +0AH of the control block at Index Register IX into Register L.
4854
LD H,(IX+0BH) DD 66 0B
Fetch the high byte from +0BH of the control block at Index Register IX into Register H: Register Pair HL = the next record number.
4857
LD D,(IX+05H) DD 56 05
Fetch the offset from byte +05H of the control block at Index Register IX into Register D.
485A
LD E,(IX+09H) DD 5E 09
Fetch the record length from byte +09H of the control block at Index Register IX into Register E. 4875H arrives here with the ending record number and end of file offset.
485D
LD A,D 7A
Copy Register D (the offset) into Register A.
485E
OR A B7
OR Register A with itself: the Z FLAG is set when the offset is 00H.
485F
If the Z FLAG is set (offset 00H), JUMP to 4862H, keeping Register Pair HL as the sector.
4861
DEC HL 2B
Decrement Register Pair HL: with an offset inside a sector, the position is in the sector before the next record number.
4862
LD A,E 7B
Copy Register E (the record length) into Register A.
4863
OR A B7
OR Register A (the record length) with itself: the Z FLAG is set for 256 byte records.
4864
If the Z FLAG is set (256 byte records: the record number is the sector), JUMP to 4870H with Register Pair HL.
4866
GOSUB to 45EAH, which divides Register Pair HL (the sector) by Register A (the record length): Register B and Register C the quotient (low byte in Register B), Register H the remainder.
4869
LD L,D 6A
Copy Register D (the offset) into Register L: Register Pair HL = remainder x 256 + offset.
486A
LD A,E 7B
Copy Register E (the record length) into Register A, the divisor.
486B
GOSUB to 4BA9H to divide Register Pair HL by Register A: Register L = the low byte of the record number.
486E
LD A,C 79
Copy Register C (the high byte of the first quotient) into Register A: bits 23-16 of the record number.
486F
LD H,B 60
Copy Register B (the low byte of the first quotient) into Register H: Register Pair HL = bits 15-0 of the record number.
4870
POP BC C1
Restore Register Pair BC from the stack: from the request entry (484EH) this is 4A0CH, the address that restores the caller's registers; from 47F8H it is the return address 47FBH.
4871
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): from 484EH the record number takes the place of the saved Register Pair BC and Register Pair HL gets that saved value; from 47F8H the record number takes the place of 4A0CH and Register Pair HL gets 4A0CH.
4872
PUSH BC C5
Save Register Pair BC (4A0CH, or 47FBH) to the stack again.
4873
OR A B7
OR Register A (bits 23-16 of the record number; 00H for 256 byte records) with itself: the Z FLAG is set when they are 0.
4874
RET C9
RETURN to 4A0CH, whose POP BC hands the record number to the caller in Register Pair BC (or to 47FBH).
4875H - Number of Records of the File (445DH)
The same calculation as 4851H with the end of file in place of the position: the ending record number and the end of file offset.
4875
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
4878
LD L,(IX+0CH) DD 6E 0C
Fetch the low byte of the ending record number from +0CH of the control block at Index Register IX into Register L.
487B
LD H,(IX+0DH) DD 66 0D
Fetch the high byte from +0DH of the control block at Index Register IX into Register H: Register Pair HL = the ending record number.
487E
LD D,(IX+08H) DD 56 08
Fetch the end of file offset from byte +08H of the control block at Index Register IX into Register D.
4881
JUMP to 485AH to turn Register Pair HL and Register D into a record number in Register Pair BC.
4883H - Write the Ending Record Number to the Directory (444EH)
Any changed buffer is written first; then the file's directory record is read, the ending record number stored in its bytes 14H-15H, and the directory sector written back. 4889H is also called after each sector write when bit 3 of +01H is set (49E3H).
4883
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
4886
GOSUB to 4988H to write the buffer back when it holds changed bytes in record mode.
4889
LD B,(IX+07H) DD 46 07
Fetch the directory entry code from byte +07H of the control block at Index Register IX into Register B.
488C
LD C,(IX+06H) DD 4E 06
Fetch the drive from byte +06H of the control block at Index Register IX into Register C.
488F
GOSUB to 4B10H to read the directory sector of entry Register B on drive Register C into 4200H: Register Pair HL returns the address of the record.
4892
RET NZ C0
If the NZ FLAG is set (the directory sector could not be read), RETURN with error 11H in Register A.
4893
LD DE,0014H 11 14 00
Load Register Pair DE with 0014H, the offset of the record count in a directory record.
4896
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = byte 14H of the directory record.
4897
LD A,(IX+0CH) DD 7E 0C
Fetch the low byte of the ending record number from +0CH of the control block at Index Register IX into Register A.
489A
LD (HL),A 77
Store Register A to byte 14H of the directory record at Register Pair HL.
489B
INC HL 23
Increment Register Pair HL to byte 15H of the directory record, the high byte of the count.
489C
LD A,(IX+0DH) DD 7E 0D
Fetch the high byte of the ending record number from +0DH of the control block at Index Register IX into Register A.
489F
LD (HL),A 77
Store Register A to byte 15H of the directory record at Register Pair HL.
48A0
GOSUB to 4B1FH to write the directory sector at 4200H back (Register B and Register C are still the entry code and the drive).
48A3
RET C9
RETURN with the result of the write: the Z FLAG, or error 12H (or 0FH, write protected) in Register A.
48A4H - Read a Record (4436H)
In record mode the record length's worth of bytes is taken one at a time (48F1H) into the area at Register Pair HL; with 256 byte records the next sector is read into the file's buffer.
48A4
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it.
48A7
GOSUB to 44FAH (the patch SYS0C) to write the buffer back first when it holds changed bytes.
48AA
RET NZ C0
If the NZ FLAG is set (the write back failed), RETURN with the error code in Register A.
48AB
LD B,(IX+09H) DD 46 09
Fetch the record length from byte +09H of the control block at Index Register IX into Register B, the count of bytes to read.
48AE
LD A,B 78
Copy Register B (the record length) into Register A.
48AF
OR A B7
OR Register A with itself: the Z FLAG is set for 00H, 256 byte records.
48B0
If the Z FLAG is set (256 byte records), JUMP to 4949H to read the next sector into the file's buffer.
48B3
PUSH HL E5
Save Register Pair HL (the pointer into the caller's record area) to the stack.
48B4
PUSH BC C5
Save Register Pair BC (Register B the bytes still to read) to the stack.
48B5
GOSUB to 48F1H to take the next byte of the file into Register A.
48B8
POP BC C1
Restore Register Pair BC (the count) from the stack.
48B9
POP HL E1
Restore Register Pair HL (the record area pointer) from the stack.
48BA
RET NZ C0
If the NZ FLAG is set (end of file or a read error), RETURN with the error code in Register A.
48BB
LD (HL),A 77
Store Register A (the byte) to the caller's record area at Register Pair HL.
48BC
INC HL 23
Increment Register Pair HL to the next place in the record area.
48BD
Decrement Register B and JUMP to 48B3H while bytes of the record are left.
48BF
RET C9
RETURN with the Z FLAG set: the record has been read.
48C0H - Write a Record (4439H, 443CH)
In record mode the record length's worth of bytes goes one at a time (4910H) from the area at Register Pair HL; with 256 byte records the file's buffer is written as the next sector. 443CH (48DBH) writes the same way with every sector read back to check it: the flag is the operand at 49C7H.
48C0
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it; Register A returns 00H.
48C3
LD (49C7H),A 32 C7 49
Store Register A (00H here, 01H from 48DBH) to 49C7H, the operand of LD A,00H at 49C6H: a sector written is read back when it is not 00H.
48C6
LD B,(IX+09H) DD 46 09
Fetch the record length from byte +09H of the control block at Index Register IX into Register B, the count of bytes to write.
48C9
LD A,B 78
Copy Register B (the record length) into Register A.
48CA
OR A B7
OR Register A with itself: the Z FLAG is set for 00H, 256 byte records.
48CB
If the Z FLAG is set (256 byte records), JUMP to 49A3H to write the file's buffer as the next sector.
48CE
LD A,(HL) 7E
Fetch the next byte of the record from Register Pair HL into Register A.
48CF
INC HL 23
Increment Register Pair HL to the next byte of the record area.
48D0
PUSH HL E5
Save Register Pair HL (the record area pointer) to the stack.
48D1
PUSH BC C5
Save Register Pair BC (Register B the bytes still to write) to the stack.
48D2
GOSUB to 4910H to put Register A into the file at its position.
48D5
POP BC C1
Restore Register Pair BC (the count) from the stack.
48D6
POP HL E1
Restore Register Pair HL (the record area pointer) from the stack.
48D7
RET NZ C0
If the NZ FLAG is set (a write error), RETURN with the error code in Register A.
48D8
Decrement Register B and JUMP to 48CEH while bytes of the record are left.
48DA
RET C9
RETURN with the Z FLAG set: the record has been written.
48DB
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it; Register A returns 00H.
48DE
INC A 3C
Increment Register A: 01H, the read back flag.
48DF
JUMP to 48C3H to store the flag and write the record.
48E1H - Character I/O Through a File
The dispatcher at 44D1H jumps here when a device control block is routed to a file: Index Register IX is the file's control block, Register B the request (01H input, 02H output, 04H control), Register C the character. 48F1H takes the next byte of a file (also called by 48B5H), 4910H puts a byte into it (also called by 48D2H).
48E1
PUSH IX DD E5
Save Index Register IX (the file's control block) to the stack.
48E3
POP DE D1
Restore Register Pair DE from the stack: Register Pair DE = the file's control block, as 49EBH expects.
48E4
GOSUB to 49EBH to check the control block at Register Pair DE and save the registers.
48E7
SET 7,(IX+01H) DD CB 01 FE
Set bit 7 of byte +01H of the control block at Index Register IX: the file is used byte by byte, so its buffer is written back when changed (4988H).
48EB
LD A,B 78
Copy Register B (the request) into Register A.
48EC
CP 02H FE 02
Compare Register A against 02H: the C FLAG is set for an input request (01H).
48EE
LD A,C 79
Copy Register C (the character to write) into Register A. LD does not change the flags.
48EF
If the NC FLAG is set (an output or control request), JUMP to 4910H to put Register A into the file.
48F1
GOSUB to 4A15H to compare the position with the end of file (an input request, or 48B5H): Register Pair HL = the next record number, Register C = the offset.
48F4
RET NZ C0
If the NZ FLAG is set (at or past the end of file), RETURN with error 1CH or 1DH in Register A.
48F5
BIT 5,(IX+01H) DD CB 01 6E
Test bit 5 of byte +01H of the control block at Index Register IX: set when the sector at +0AH-+0BH must be read first.
48F9
If the Z FLAG is set (the buffer holds the sector), JUMP to 48FFH.
48FB
GOSUB to 4949H to read the next sector into the buffer.
48FE
RET NZ C0
If the NZ FLAG is set (the read failed), RETURN with the error code in Register A.
48FF
GOSUB to 497AH: Register Pair DE = the address of the byte at the offset in the buffer.
4902
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A), the success the caller gets.
4903
LD A,(DE) 1A
Fetch the byte from the buffer at Register Pair DE into Register A. LD does not change the Z FLAG.
4904
PUSH AF F5
Save Register Pair AF (the byte and the Z FLAG) to the stack.
4905
INC (IX+05H) DD 34 05
Increment the offset, byte +05H of the control block at Index Register IX.
4908
If the NZ FLAG is set (still inside the sector), JUMP to 490EH.
490A
SET 5,(IX+01H) DD CB 01 EE
Set bit 5 of byte +01H of the control block at Index Register IX: the offset passed the end of the sector, so the next sector is to be read before the next byte.
490E
POP AF F1
Restore Register Pair AF from the stack: Register A = the byte, the Z FLAG set.
490F
RET C9
RETURN with the byte in Register A and the Z FLAG set.
4910
PUSH AF F5
Save Register Pair AF (Register A the byte to write) to the stack.
4911
BIT 5,(IX+01H) DD CB 01 6E
Test bit 5 of byte +01H of the control block at Index Register IX: set when the sector at +0AH-+0BH must be read first.
4915
If the Z FLAG is set (the buffer holds the sector), JUMP to 491FH.
4917
GOSUB to 494DH to read the sector at the next record number (no end of file test: a write may go past the end).
491A
If the Z FLAG is set (the sector was read), JUMP to 491FH.
491C
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word, the byte saved at 4910H): the read failed, so the saved Register Pair AF is dropped.
491D
POP HL E1
Restore Register Pair HL from the stack: Register Pair HL back to its value, the stack back to the caller's return address.
491E
RET C9
RETURN with the error code from 494DH in Register A and the NZ FLAG.
491F
GOSUB to 497AH: Register Pair DE = the address of the byte at the offset in the buffer.
4922
POP AF F1
Restore Register Pair AF from the stack: Register A = the byte to write.
4923
LD (DE),A 12
Store Register A (the byte) into the buffer at Register Pair DE.
4924
SET 4,(IX+01H) DD CB 01 E6
Set bit 4 of byte +01H of the control block at Index Register IX: the buffer holds a changed byte.
4928
INC (IX+05H) DD 34 05
Increment the offset, byte +05H of the control block at Index Register IX.
492B
GOSUB to 4A15H to compare the new position with the end of file: Register Pair HL = the next record number, Register C = the offset.
492E
If the NZ FLAG is set (the write reached or passed the end of file), JUMP to 4936H to move the end of file there.
4930
BIT 6,(IX+01H) DD CB 01 76
Test bit 6 of byte +01H of the control block at Index Register IX: set when the file has been positioned (47B3H).
4934
If the NZ FLAG is set (positioned: a write inside the file leaves the end of file), JUMP to 493FH.
4936
LD (IX+08H),C DD 71 08
Store Register C (the offset) to byte +08H of the control block at Index Register IX, the end of file offset.
4939
LD (IX+0CH),L DD 75 0C
Store Register L (low byte of the next record number) to +0CH of the control block at Index Register IX, the ending record number.
493C
LD (IX+0DH),H DD 74 0D
Store Register H (high byte) to +0DH of the control block at Index Register IX: the end of file is now the position after this byte.
493F
LD A,C 79
Copy Register C (the offset) into Register A.
4940
OR A B7
OR Register A with itself: the Z FLAG is set when the offset went round to 00H, the end of the sector.
4941
If the NZ FLAG is set (still inside the sector), JUMP to 4978H to return with Register A = 00H.
4943
SET 5,(IX+01H) DD CB 01 EE
Set bit 5 of byte +01H of the control block at Index Register IX: the next byte belongs to the next sector.
4947
JUMP to 4996H to write the full buffer to its sector.
4949H - Read the Next Sector
4949H checks the end of file first; 494DH starts at the access check. The sector at the next record number is found (4A3CH, which asks SYS8/SYS for space when the file has none there) and read into the buffer, and the next record number goes up by one. A sector with a system data mark (error 06H) is taken as read.
4949
GOSUB to 4A15H to compare the position with the end of file.
494C
RET NZ C0
If the NZ FLAG is set (at or past the end of file), RETURN with error 1CH or 1DH in Register A.
494D
LD A,(IX+01H) DD 7E 01
Fetch the access byte, byte +01H of the control block at Index Register IX, into Register A.
4950
AND 07H E6 07
Mask Register A to bits 2-0, the access level the file was opened with (0 full access, larger numbers less).
4952
CP 06H FE 06
Compare Register A (the access level) against 06H.
4954
If the C FLAG is set (access level 0-5: reading is allowed), JUMP to 495AH.
4956
LD A,25H 3E 25
Load Register A with 25H, the error code ILLEGAL ACCESS ATTEMPTED TO PROTECTED FILE.
4958
OR A B7
OR Register A with itself: the NZ FLAG is set.
4959
RET C9
RETURN with error 25H in Register A and the NZ FLAG.
495A
GOSUB to 4A3CH to work out the cylinder (Register D) and sector (Register E) of the next record number, Register C the drive.
495D
RET NZ C0
If the NZ FLAG is set (no sector: an error from SYS8/SYS), RETURN with the error code in Register A.
495E
RES 5,(IX+01H) DD CB 01 AE
Reset bit 5 of byte +01H of the control block at Index Register IX: the buffer is about to hold the sector.
4962
LD L,(IX+03H) DD 6E 03
Fetch the low byte of the buffer address from +03H of the control block at Index Register IX into Register L.
4965
LD H,(IX+04H) DD 66 04
Fetch the high byte from +04H of the control block at Index Register IX into Register H: Register Pair HL = the file's buffer.
4968
GOSUB to 4777H to read cylinder Register D, sector Register E of drive Register C into the buffer at Register Pair HL.
496B
If the Z FLAG is set (the sector was read without error), JUMP to 4970H.
496D
CP 06H FE 06
Compare Register A (the error code) against 06H, the system data mark the directory carries.
496F
RET NZ C0
If the NZ FLAG is set (any other error), RETURN with the error code in Register A.
4970
INC (IX+0AH) DD 34 0A
Increment the low byte of the next record number, byte +0AH of the control block at Index Register IX.
4973
If the NZ FLAG is set (no carry into the high byte), JUMP to 4978H.
4975
INC (IX+0BH) DD 34 0B
Increment the high byte of the next record number, byte +0BH of the control block at Index Register IX.
4978
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A): success.
4979
RET C9
RETURN with Register A = 00H and the Z FLAG set.
497A
LD A,(IX+05H) DD 7E 05
Fetch the offset from byte +05H of the control block at Index Register IX into Register A. Work out the address of the byte at the offset in the buffer.
497D
ADD A,(IX+03H) DD 86 03
Add the low byte of the buffer address, byte +03H of the control block at Index Register IX, to Register A.
4980
LD E,A 5F
Copy Register A (low byte of the address) into Register E.
4981
LD A,(IX+04H) DD 7E 04
Fetch the high byte of the buffer address from +04H of the control block at Index Register IX into Register A.
4984
ADC A,00H CE 00
Add 00H and the CARRY FLAG to Register A: the carry from the low byte.
4986
LD D,A 57
Copy Register A (high byte of the address) into Register D: Register Pair DE = buffer + offset.
4987
RET C9
RETURN with Register Pair DE = the address of the byte at the offset.
4988H - Write Back a Changed Buffer
When bits 7 and 4 of +01H are both set (the file is used in records or bytes, and the buffer holds changed bytes), the buffer is written to the sector it was read from (4996H). SYS3/SYS calls 4988H before it closes a file (its 4E16H). 4993H (entry 4457H) writes the buffer in any case.
4988
LD A,(IX+01H) DD 7E 01
Fetch the access byte, byte +01H of the control block at Index Register IX, into Register A.
498B
AND 90H E6 90
Mask Register A to bits 7 and 4: record mode and buffer changed.
498D
CP 90H FE 90
Compare Register A against 90H, both bits set.
498F
If the Z FLAG is set (a changed buffer in record mode), JUMP to 4996H to write it back.
4991
JUMP to 4978H to return with Register A = 00H and the Z FLAG: nothing to write.
4993
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it (entry 4457H).
4996
LD C,(IX+0AH) DD 4E 0A
Fetch the low byte of the next record number from +0AH of the control block at Index Register IX into Register C.
4999
LD B,(IX+0BH) DD 46 0B
Fetch the high byte from +0BH of the control block at Index Register IX into Register B: Register Pair BC = the next record number.
499C
DEC BC 0B
Decrement Register Pair BC: the sector the buffer was read from.
499D
LD (IX+0AH),C DD 71 0A
Store Register C to byte +0AH of the control block at Index Register IX: the next record number goes back to that sector.
49A0
LD (IX+0BH),B DD 70 0B
Store Register B to byte +0BH of the control block at Index Register IX.
49A3
LD A,(IX+01H) DD 7E 01
Fetch the access byte, byte +01H of the control block at Index Register IX, into Register A (256 byte records arrive here from 48CBH).
49A6
AND 07H E6 07
Mask Register A to bits 2-0, the access level.
49A8
CP 05H FE 05
Compare Register A (the access level) against 05H.
49AA
If the C FLAG is set (access level 0-4: writing is allowed), JUMP to 49B0H.
49AC
LD A,25H 3E 25
Load Register A with 25H, the error code ILLEGAL ACCESS ATTEMPTED TO PROTECTED FILE.
49AE
OR A B7
OR Register A with itself: the NZ FLAG is set.
49AF
RET C9
RETURN with error 25H in Register A and the NZ FLAG.
49B0
GOSUB to 4A3CH to work out the cylinder (Register D) and sector (Register E) of the next record number, asking SYS8/SYS for space when the file has none there.
49B3
RET NZ C0
If the NZ FLAG is set (no space), RETURN with the error code in Register A.
49B4
LD L,(IX+03H) DD 6E 03
Fetch the low byte of the buffer address from +03H of the control block at Index Register IX into Register L.
49B7
LD H,(IX+04H) DD 66 04
Fetch the high byte from +04H of the control block at Index Register IX into Register H: Register Pair HL = the file's buffer.
49BA
SET 2,(IX+00H) DD CB 00 D6
Set bit 2 of byte +00H of the control block at Index Register IX: the file has been written to.
49BE
GOSUB to 4763H to write the buffer at Register Pair HL to cylinder Register D, sector Register E of drive Register C.
49C1
RET NZ C0
If the NZ FLAG is set (the write failed), RETURN with the error code in Register A.
49C2
RES 4,(IX+01H) DD CB 01 A6
Reset bit 4 of byte +01H of the control block at Index Register IX: the buffer now matches the sector.
49C6
LD A,00H 3E 00
Load Register A with the read back flag: the operand at 49C7H is 00H in the file, set by 48C3H (01H for 443CH).
49C8
OR A B7
OR Register A with itself: the NZ FLAG is set when the sector is to be read back.
49C9
If the NZ FLAG is set, GOSUB to 4772H to read the sector just written without storing it, so the controller checks it.
49CC
RET NZ C0
If the NZ FLAG is set (the check failed), RETURN with the error code in Register A.
49CD
GOSUB to 4A15H to compare the position with the end of file: Register Pair HL = the next record number.
49D0
If the NZ FLAG is set (the sector written reaches or passes the end of file), JUMP to 49D8H.
49D2
BIT 6,(IX+01H) DD CB 01 76
Test bit 6 of byte +01H of the control block at Index Register IX: set when the file has been positioned.
49D6
If the NZ FLAG is set (positioned), JUMP to 4970H to count the next record number up and return.
49D8
INC HL 23
Increment Register Pair HL: one past the sector written.
49D9
LD (IX+0CH),L DD 75 0C
Store Register L to +0CH of the control block at Index Register IX, the ending record number.
49DC
LD (IX+0DH),H DD 74 0D
Store Register H to +0DH of the control block at Index Register IX.
49DF
BIT 3,(IX+01H) DD CB 01 5E
Test bit 3 of byte +01H of the control block at Index Register IX: set when the directory is to follow the end of file at each write.
49E3
If the NZ FLAG is set, GOSUB to 4889H to store the ending record number in the file's directory record.
49E6
RET NZ C0
If the NZ FLAG is set (the directory write failed), RETURN with the error code in Register A.
49E7
JUMP to 4970H to count the next record number up and return with the Z FLAG.
49E9H - Start of Every File Request
CALL 49EBH (or 49E9H) at the start of a file routine: Register Pair DE = the file's control block. 49EBH tests bit 7 of its first byte (open); 49E9H skips the test (the open and SYS10/SYS use it before the file is open). The address after the CALL goes to 430CH, Register Pair DE to 430AH. When the file is open, Index Register IX is set to the control block, Register Pairs BC, DE, HL and Index Register IX are saved, 4A0CH is put on the stack to restore them, and the routine goes on after its CALL with Register A = 00H; its RET then goes through 4A0CH. When the file is not open, the routine's caller gets error 26H.
49E9
SCF 37
Set the CARRY FLAG, so the test of bit 7 below is passed. Entry 49E9H: the next bytes, read from here, are an instruction that writes Register Pair HL to 071AH in the ROM (no effect), stepping over 49EBH-49ECH.
49EA
LD (071AH),HL 22 1A 07
Store Register Pair HL to 071AH: an address in the ROM, so nothing changes. From 49E9H this row only skips the next two bytes; entry 49EBH starts inside it with 1AH 07H, LD A,(DE) and RLCA: byte +00H of the control block at Register Pair DE is fetched into Register A and its bit 7 (open) rotated into the CARRY FLAG.
49ED
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): Register Pair HL = the return address, the place in the file routine after its CALL; the stack holds the caller's Register Pair HL.
49EE
LD (430CH),HL 22 0C 43
Store Register Pair HL (the return address) to 430CH, for the error message of SYS4/SYS.
49F1
LD (430AH),DE ED 53 0A 43
Store Register Pair DE (the control block) to 430AH, for the error message of SYS4/SYS.
49F5
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word) again: the caller's Register Pair HL comes back, the return address is on the stack.
49F6
If the NC FLAG is set (bit 7 of the first byte clear: the file is not open), JUMP to 4A07H.
49F8
POP AF F1
Restore Register Pair AF from the stack: it takes the return address (the rest of the file routine) off the stack, to be pushed again on top of the saved registers.
49F9
PUSH DE D5
Save Register Pair DE (the control block) to the stack.
49FA
EX (SP),IX DD E3
Exchange Index Register IX with the top of the stack (the Stack Pointer's word): Index Register IX = the control block, the stack holds the caller's Index Register IX.
49FC
PUSH HL E5
Save Register Pair HL (the caller's) to the stack.
49FD
PUSH DE D5
Save Register Pair DE (the control block) to the stack.
49FE
PUSH BC C5
Save Register Pair BC (the caller's) to the stack.
49FF
PUSH HL E5
Save Register Pair HL to the stack once more, as a place for the address of the restore code.
4A00
LD HL,4A0CH 21 0C 4A
Load Register Pair HL with 4A0CH, the code that restores the saved registers.
4A03
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): the stack holds 4A0CH, Register Pair HL is the caller's value again.
4A04
PUSH AF F5
Save Register Pair AF (holding the return address taken at 49F8H) to the stack: the rest of the file routine.
4A05
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A).
4A06
RET C9
RETURN, which jumps to the rest of the file routine with Register A = 00H; its own RET will come to 4A0CH.
4A07
POP AF F1
Restore Register Pair AF from the stack: the return address into the file routine is dropped, so the RET below goes to the routine's caller.
4A08
LD A,26H 3E 26
Load Register A with 26H, the error code FILE NOT OPEN.
4A0A
OR A B7
OR Register A with itself: the NZ FLAG is set.
4A0B
RET C9
RETURN to the caller of the file routine with error 26H in Register A and the NZ FLAG.
4A0C
POP BC C1
Restore Register Pair BC (the caller's, or the record number placed by 4870H) from the stack. Every file routine ends here except 47F5H, whose stack no longer holds 4A0CH.
4A0D
POP DE D1
Restore Register Pair DE (the control block) from the stack.
4A0E
POP HL E1
Restore Register Pair HL (the caller's) from the stack.
4A0F
POP IX DD E1
Restore Index Register IX (the caller's) from the stack.
4A11
RET C9
RETURN to the caller of the file routine with Register A and the flags from the routine.
4A12H - Compare the Position with the End of File (444BH)
Register Pair HL = the next record number, Register C = the offset. Before the end: Register A = 00H and the Z FLAG. At the end exactly: error 1CH (END OF FILE ENCOUNTERED). Past it: error 1DH (RECORD NUMBER OUT OF RANGE). The offsets are compared less one, so an end of file offset of 00H counts as 256.
4A12
GOSUB to 49EBH to check the control block at Register Pair DE and point Index Register IX at it (entry 444BH).
4A15
LD L,(IX+0AH) DD 6E 0A
Fetch the low byte of the next record number from +0AH of the control block at Index Register IX into Register L.
4A18
LD H,(IX+0BH) DD 66 0B
Fetch the high byte from +0BH of the control block at Index Register IX into Register H: Register Pair HL = the next record number.
4A1B
LD C,(IX+05H) DD 4E 05
Fetch the offset from byte +05H of the control block at Index Register IX into Register C.
4A1E
LD A,H 7C
Copy Register H (high byte of the next record number) into Register A.
4A1F
CP (IX+0DH) DD BE 0D
Compare Register A against the high byte of the ending record number, +0DH of the control block at Index Register IX.
4A22
If the NZ FLAG is set (the high bytes differ), JUMP to 4A37H with the CARRY FLAG set when the position is the lower.
4A24
LD A,L 7D
Copy Register L (low byte of the next record number) into Register A.
4A25
CP (IX+0CH) DD BE 0C
Compare Register A against the low byte of the ending record number, +0CH of the control block at Index Register IX.
4A28
If the NZ FLAG is set (the low bytes differ), JUMP to 4A37H with the CARRY FLAG set when the position is the lower.
4A2A
DEC C 0D
Decrement Register C (the offset), so an offset of 00H counts as 256.
4A2B
LD A,(IX+08H) DD 7E 08
Fetch the end of file offset from byte +08H of the control block at Index Register IX into Register A.
4A2E
DEC A 3D
Decrement Register A (the end of file offset), so 00H counts as 256.
4A2F
SUB C 91
SUBtract Register C (the offset less one) from Register A (the end of file offset less one): the CARRY FLAG is set when the position is past the end of file, the Z FLAG when it is at it.
4A30
CCF 3F
Complement the CARRY FLAG: now set when the position is before the end of file.
4A31
INC BC 03
Increment Register Pair BC: Register C gets back the offset (when the offset is 00H the carry out of Register C also adds 1 to Register B). INC BC does not change the flags.
4A32
If the NZ FLAG is set (not at the end of file exactly), JUMP to 4A37H.
4A34
OR 1CH F6 1C
OR Register A (00H) with 1CH: Register A = 1CH, the NZ FLAG set and the CARRY FLAG clear.
4A36
RET C9
RETURN with error 1CH, END OF FILE ENCOUNTERED.
4A37
LD A,1DH 3E 1D
Load Register A with 1DH, the error code RECORD NUMBER OUT OF RANGE. LD does not change the flags.
4A39
RET NC D0
If the NC FLAG is set (the position is past the end of file), RETURN with error 1DH and the NZ FLAG.
4A3A
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A): the position is before the end of file.
4A3B
RET C9
RETURN with Register A = 00H and the Z FLAG set.
4A3CH - Cylinder and Sector of the Next Record Number
The next record number is divided by the sectors of a granule: the quotient is the granule of the file, the remainder the sector inside it (kept at 4B0CH). The extents at +0EH-+1FH are searched for that granule: the first extent is cylinder and granule byte (+0EH-+0FH), each of the other four is the count of the file's granules before it (two bytes), cylinder and granule byte; a cylinder of FFH means no extent. An extent found third or later is moved to the second place. When no extent holds the granule, SYS8/SYS is asked for space (request 9AH). The result: Register D = cylinder, Register E = sector, Register C = the drive, the Z FLAG.
4A3C
LD L,(IX+0AH) DD 6E 0A
Fetch the low byte of the next record number from +0AH of the control block at Index Register IX into Register L.
4A3F
LD H,(IX+0BH) DD 66 0B
Fetch the high byte from +0BH of the control block at Index Register IX into Register H: Register Pair HL = the next record number.
4A42
LD C,(IX+06H) DD 4E 06
Fetch the drive from byte +06H of the control block at Index Register IX into Register C.
4A45
LD A,08H 3E 08
Load Register A with 08H, the offset of the granule byte in a drive code table.
4A47
GOSUB to 4797H to fetch byte +08H of the drive code table of drive Register C into Register A.
4A4A
AND 1FH E6 1F
Mask Register A to bits 4-0: the sectors of a granule less one.
4A4C
INC A 3C
Increment Register A: the sectors of a granule (5 on this diskette's drives).
4A4D
GOSUB to 4BA9H to divide Register Pair HL (the next record number) by Register A: Register Pair HL = the granule of the file, Register A = the sector inside the granule.
4A50
LD (4B0CH),A 32 0C 4B
Store Register A (the sector inside the granule) to 4B0CH, the operand of ADD A,00H at 4B0BH.
4A53
PUSH IX DD E5
Save Index Register IX (the control block) to the stack.
4A55
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): Register Pair HL = the control block, the stack holds the granule of the file.
4A56
LD BC,000EH 01 0E 00
Load Register Pair BC with 000EH, the offset of the extents in a control block.
4A59
ADD HL,BC 09
Add Register Pair BC to Register Pair HL: Register Pair HL = +0EH of the control block, the first extent.
4A5A
POP BC C1
Restore Register Pair BC from the stack: Register Pair BC = the granule of the file wanted.
4A5B
LD A,05H 3E 05
Load Register A with 05H, the number of extents in a control block.
4A5D
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: the first extent has no granules of the file before it.
4A60
PUSH AF F5
Save Register Pair AF (Register A the extents left) to the stack.
4A61
LD A,(HL) 7E
Fetch the cylinder of the extent at Register Pair HL into Register A.
4A62
INC HL 23
Increment Register Pair HL to the extent's granule byte.
4A63
INC A 3C
Increment Register A: 00H (and the Z FLAG) for a cylinder of FFH, an empty extent.
4A64
If the Z FLAG is set (empty extent), JUMP to 4A71H for the next extent.
4A66
PUSH HL E5
Save Register Pair HL (the extent's granule byte) to the stack.
4A67
LD H,D 62
Copy Register D (high byte of the granules before the extent) into Register H.
4A68
LD L,E 6B
Copy Register E into Register L: Register Pair HL = the granules of the file before this extent.
4A69
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A) for the subtraction.
4A6A
SBC HL,BC ED 42
SUBtract Register Pair BC (the granule wanted) from Register Pair HL (the granules before the extent): the CARRY FLAG is set when the granule wanted is beyond the extent's first.
4A6C
If the C FLAG is set, JUMP to 4A7CH to see whether the granule is inside this extent.
4A6E
POP HL E1
Restore Register Pair HL from the stack: the extent's granule byte.
4A6F
If the Z FLAG is set (the granule wanted is the extent's first), JUMP to 4ABCH with Register A = 00H, the granule's place in the extent.
4A71
INC HL 23
Increment Register Pair HL past the granule byte, to the next extent's count.
4A72
POP AF F1
Restore Register Pair AF from the stack: Register A = the extents left.
4A73
DEC A 3D
Decrement Register A, the count of extents still to be searched.
4A74
If the Z FLAG is set (all five extents searched), JUMP to 4A8FH to ask SYS8/SYS for space.
4A76
LD E,(HL) 5E
Fetch the low byte of the count of granules before the next extent from Register Pair HL into Register E.
4A77
INC HL 23
Increment Register Pair HL to the high byte of the count of granules before the next extent.
4A78
LD D,(HL) 56
Fetch the high byte from Register Pair HL into Register D: Register Pair DE = the granules of the file before the next extent.
4A79
INC HL 23
Increment Register Pair HL to the next extent's cylinder.
4A7A
JUMP back to 4A60H to test the next extent with Register Pair DE its count of granules before it.
4A7C
INC H 24
Increment Register H: Register Pair HL holds the granules before the extent less the granule wanted, a negative number; Register H becomes 00H (the Z FLAG) when the difference is below 256.
4A7D
LD A,L 7D
Copy Register L (the low byte, 256 less the granule's place in the extent) into Register A.
4A7E
POP HL E1
Restore Register Pair HL from the stack: the extent's granule byte.
4A7F
If the NZ FLAG is set (256 granules or more beyond the extent's first), JUMP to 4A71H for the next extent.
4A81
PUSH DE D5
Save Register Pair DE (the granules before the extent) to the stack.
4A82
LD E,A 5F
Copy Register A (256 less the granule's place) into Register E.
4A83
LD A,(HL) 7E
Fetch the extent's granule byte from Register Pair HL into Register A.
4A84
AND 1FH E6 1F
Mask Register A to bits 4-0: the extent's granules less one.
4A86
ADD A,E 83
Add Register E to Register A: the CARRY FLAG is set when the granule's place is not more than the extent's granules less one, that is when the granule is inside this extent.
4A87
LD A,E 7B
Copy Register E (256 less the granule's place) into Register A. LD does not change the flags.
4A88
POP DE D1
Restore Register Pair DE (the granules before the extent) from the stack.
4A89
If the NC FLAG is set (the granule is beyond this extent), JUMP to 4A71H for the next extent.
4A8B
NEG ED 44
Negate Register A: Register A = the granule's place in the extent.
4A8D
JUMP to 4ABCH with the extent found: Register Pair HL at its granule byte, Register A the granule's place in it.
4A8F
LD A,(4B0CH) 3A 0C 4B
Fetch the sector inside the granule from 4B0CH into Register A. None of the extents holds the granule: SYS8/SYS must find space.
4A92
LD (4AB1H),A 32 B1 4A
Store Register A (the sector inside the granule) to 4AB1H, the operand of LD A,00H at 4AB0H, to put it back after SYS8/SYS.
4A95
LD (0028H),A 32 28 00
Store Register A to 0028H, an address in the ROM: nothing changes.
4A98
LD A,(430EH) 3A 0E 43
Fetch the request code of the overlay in memory from 430EH into Register A.
4A9B
LD (4AA3H),A 32 A3 4A
Store Register A (that request code) to 4AA3H, the operand of LD A,00H at 4AA2H, to put the overlay back after SYS8/SYS.
4A9E
GOSUB to 4AB9H, request 9AH: SYS8/SYS is loaded over the overlay area and given the control block at Index Register IX and the granule wanted in Register Pair BC (it sets Register Pairs DE and HL itself).
4AA1
PUSH AF F5
Save Register Pair AF (the result of SYS8/SYS) to the stack.
4AA2
LD A,00H 3E 00
Load Register A with the request code saved at 4A9BH (operand 4AA3H, 00H in the file).
4AA4
AND 8FH E6 8F
Mask Register A (the request code saved) to bit 7 and bits 3-0, the overlay it names.
4AA6
CP 83H FE 83
Compare Register A against 83H: a request for SYS1/SYS (bits 3-0 = 3, bit 7 set).
4AA8
If the Z FLAG is set (SYS1/SYS was the overlay in memory), GOSUB to 4C53H to load SYS1/SYS again with the request code in Register A, since SYS8/SYS was loaded over it.
4AAB
POP AF F1
Restore Register Pair AF (the result of SYS8/SYS) from the stack.
4AAC
RET NZ C0
If the NZ FLAG is set (SYS8/SYS found no space), RETURN with the error code in Register A.
4AAD
LD (4AECH),A 32 EC 4A
Store Register A (from SYS8/SYS: the granule's place in its extent) to 4AECH, the operand of ADD A,00H at 4AEBH.
4AB0
LD A,00H 3E 00
Load Register A with the sector inside the granule saved at 4A92H (operand 4AB1H, 00H in the file).
4AB2
LD (4B0CH),A 32 0C 4B
Store Register A to 4B0CH, the operand of ADD A,00H at 4B0BH.
4AB5
If the NC FLAG is set (SYS8/SYS returned the extent in Register Pair HL: Register H the granule byte, Register L the cylinder), JUMP to 4AE5H.
4AB7
JUMP to 4ADCH to store the new extent from Register Pairs BC and DE at Register Pair HL.
4AB9
LD A,9AH 3E 9A
Load Register A with 9AH: SYS8/SYS (bits 3-0 = AH), function 1, which allocates space to the file.
4ABB
RST 28H EF
RST 28H to 400CH and the request handler at 4C31H, which loads and runs SYS8/SYS; it returns to 4AA1H, since the handler drops the address pushed by RST 28H.
4ABC
LD (4AECH),A 32 EC 4A
Store Register A (the granule's place in the extent) to 4AECH, the operand of ADD A,00H at 4AEBH.
4ABF
LD B,(HL) 46
Fetch the extent's granule byte from Register Pair HL into Register B.
4AC0
DEC HL 2B
Decrement Register Pair HL to the extent's cylinder.
4AC1
LD C,(HL) 4E
Fetch the extent's cylinder from Register Pair HL into Register C.
4AC2
INC HL 23
Increment Register Pair HL back to the granule byte.
4AC3
POP AF F1
Restore Register Pair AF from the stack: Register A = the extents left, 5 for the first extent down to 1 for the fifth.
4AC4
CPL 2F
Complement Register A (the extents left): 5 becomes FAH, 1 becomes FEH.
4AC5
ADD A,04H C6 04
Add 04H to Register A: the CARRY FLAG is set for the third, fourth and fifth extents (Register A then 00H, 01H, 02H).
4AC7
If the NC FLAG is set (the first or second extent), JUMP to 4AE3H: the extents stay where they are.
4AC9
INC A 3C
Increment Register A: 1, 2 or 3, the extents between the second place and this one.
4ACA
RLCA 07
Rotate Register A left (1, 2 or 3 becomes 2, 4 or 6).
4ACB
RLCA 07
Rotate Register A left again: Register A = 4, 8 or 12, the bytes of those extents.
4ACC
PUSH BC C5
Save Register Pair BC (Register C the cylinder, Register B the granule byte of the extent found) to the stack.
4ACD
PUSH DE D5
Save Register Pair DE (the granules before the extent found) to the stack.
4ACE
LD C,A 4F
Copy Register A (the byte count) into Register C.
4ACF
LD B,00H 06 00
Load Register B with 00H: Register Pair BC = the byte count for LDDR.
4AD1
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the granule byte of the extent found, the destination of the move.
4AD2
LD HL,FFFCH 21 FC FF
Load Register Pair HL with FFFCH (minus 4, the size of an extent with its count).
4AD5
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = the granule byte of the extent before, the source of the move.
4AD6
LDDR ED B8
Move Register Pair BC bytes from Register Pair HL down to Register Pair DE, both counting down (LDDR): the extents from the second place on move up by one extent.
4AD8
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair HL = the granule byte of the second extent's place, where the extent found goes.
4AD9
POP DE D1
Restore Register Pair DE from the stack: the granules before the extent found.
4ADA
POP BC C1
Restore Register Pair BC from the stack: the extent's cylinder (Register C) and granule byte (Register B).
4ADB
LD (DE),A 12
Store Register A to the address in Register Pair DE, which holds a count of granules (a value that addresses the ROM), so nothing changes.
4ADC
LD (HL),B 70
Store Register B (the granule byte) at Register Pair HL. SYS8/SYS's new extent arrives here from 4AB7H.
4ADD
DEC HL 2B
Decrement Register Pair HL to the cylinder's place.
4ADE
LD (HL),C 71
Store Register C (the cylinder) at Register Pair HL.
4ADF
DEC HL 2B
Decrement Register Pair HL to the high byte of the count.
4AE0
LD (HL),D 72
Store Register D (high byte of the granules before the extent) at Register Pair HL.
4AE1
DEC HL 2B
Decrement Register Pair HL to the low byte of the count.
4AE2
LD (HL),E 73
Store Register E (low byte of the granules before the extent) at Register Pair HL.
4AE3
LD H,B 60
Copy Register B (the extent's granule byte) into Register H.
4AE4
LD L,C 69
Copy Register C (the extent's cylinder) into Register L.
4AE5
LD A,H 7C
Copy Register H (the extent's granule byte) into Register A.
4AE6
RLCA 07
Rotate Register A (the granule byte) left, the first of three.
4AE7
RLCA 07
Rotate Register A (the granule byte) left, the second of three.
4AE8
RLCA 07
Rotate Register A left: bits 7-5 of the granule byte are now bits 2-0.
4AE9
AND 07H E6 07
Mask Register A to bits 2-0: the extent's first granule on its cylinder.
4AEB
ADD A,00H C6 00
Add the granule's place in the extent (the operand at 4AECH, set at 4ABCH or 4AADH) to Register A: the granule counted from the start of the extent's cylinder.
4AED
LD E,A 5F
Copy Register A (the granule counted from the extent's cylinder) into Register E, the dividend for 4B7BH.
4AEE
LD C,(IX+06H) DD 4E 06
Fetch the drive from byte +06H of the control block at Index Register IX into Register C.
4AF1
LD A,08H 3E 08
Load Register A with 08H, the offset of the granule byte in a drive code table.
4AF3
GOSUB to 4797H to fetch byte +08H of the drive code table of drive Register C into Register A.
4AF6
PUSH AF F5
Save Register Pair AF (the granule byte of the drive) to the stack.
4AF7
RLCA 07
Rotate Register A (the drive's granule byte) left, the first of three.
4AF8
RLCA 07
Rotate Register A (the drive's granule byte) left, the second of three.
4AF9
RLCA 07
Rotate Register A left: bits 7-5 are now bits 2-0.
4AFA
AND 07H E6 07
Mask Register A to bits 2-0: the granules of a cylinder less one.
4AFC
INC A 3C
Increment Register A: the granules of a cylinder (2 on this diskette's drives).
4AFD
GOSUB to 4B7BH to divide Register E (the granule from the extent's cylinder) by Register A: Register A = the cylinders on from the extent's cylinder, Register E = the granule on that cylinder.
4B00
ADD A,L 85
Add Register L (the extent's cylinder) to Register A.
4B01
LD D,A 57
Copy Register A into Register D: the cylinder of the sector.
4B02
POP AF F1
Restore Register Pair AF from the stack: the granule byte of the drive.
4B03
AND 1FH E6 1F
Mask Register A to bits 4-0: the sectors of a granule less one.
4B05
INC A 3C
Increment Register A: the sectors of a granule.
4B06
PUSH DE D5
Save Register Pair DE (Register D the cylinder) to the stack.
4B07
GOSUB to 4B6CH to multiply Register A (sectors of a granule) by Register E (the granule on the cylinder): Register A = the granule's first sector.
4B0A
POP DE D1
Restore Register Pair DE from the stack: Register D = the cylinder.
4B0B
ADD A,00H C6 00
Add the sector inside the granule (the operand at 4B0CH, set at 4A50H or 4AB2H) to Register A.
4B0D
LD E,A 5F
Copy Register A into Register E: the sector on the cylinder in Register D.
4B0E
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A): success.
4B0F
RET C9
RETURN with Register D = cylinder, Register E = sector, Register C = drive, the Z FLAG.
4B10H - Read and Write a Directory Sector
Register B = a directory entry code (bits 4-0 the sector less 2, bits 7-5 the record in it), Register C = the drive. 4B10H reads the sector into 4200H and returns Register Pair HL at the record (error 11H, DIRECTORY READ ERROR); 4B1FH writes 4200H back with the data mark FAH and reads it back (error 12H, DIRECTORY WRITE ERROR, or 0FH). SYS2/SYS, SYS3/SYS, SYS4/SYS, SYS6/SYS, SYS8/SYS and SYS10/SYS call them.
4B10
PUSH DE D5
Save Register Pair DE (the caller's) to the stack.
4B11
GOSUB to 4B37H: Register D = the directory cylinder, Register E = the sector, Register Pair HL = 4200H plus the record's offset.
4B14
PUSH HL E5
Save Register Pair HL (the record's address) to the stack.
4B15
LD L,00H 2E 00
Load Register L with 00H: Register Pair HL = 4200H, the buffer.
4B17
GOSUB to 4B45H to read the directory sector Register D, Register E of drive Register C into 4200H.
4B1A
POP HL E1
Restore Register Pair HL from the stack: the record's address in 4200H-42FFH.
4B1B
LD A,11H 3E 11
Load Register A with 11H, the error code DIRECTORY READ ERROR. LD does not change the flags of the read.
4B1D
POP DE D1
Restore Register Pair DE (the caller's) from the stack.
4B1E
RET C9
RETURN with the Z FLAG (read) or the NZ FLAG with Register A = 11H.
4B1F
PUSH DE D5
Save Register Pair DE (the caller's) to the stack.
4B20
GOSUB to 4B37H: Register D = the directory cylinder, Register E = the sector of entry Register B.
4B23
LD L,00H 2E 00
Load Register L with 00H: Register Pair HL = 4200H, the buffer.
4B25
GOSUB to 4768H to write the buffer at Register Pair HL to Register D, Register E of drive Register C with the data mark FAH.
4B28
If the Z FLAG is set (written), GOSUB to 4772H to read the sector back without storing it.
4B2B
CP 06H FE 06
Compare Register A against 06H: the read back of a sector with the data mark FAH ends with error 06H, which means the write is good.
4B2D
POP DE D1
Restore Register Pair DE (the caller's) from the stack.
4B2E
RET Z C8
If the Z FLAG is set (error 06H from the read back), RETURN with the Z FLAG: the sector was written.
4B2F
CP 0FH FE 0F
Compare Register A against 0FH, WRITE PROTECTED DISK.
4B31
LD A,12H 3E 12
Load Register A with 12H, the error code DIRECTORY WRITE ERROR. LD does not change the flags.
4B33
RET NZ C0
If the NZ FLAG is set (any other error), RETURN with error 12H.
4B34
SUB 03H D6 03
SUBtract 03H from Register A: Register A = 0FH, with the NZ FLAG.
4B36
RET C9
RETURN with error 0FH, WRITE PROTECTED DISK, and the NZ FLAG.
4B37
GOSUB to 4B65H to fetch the directory cylinder of drive Register C into Register D.
4B3A
LD A,B 78
Copy Register B (the directory entry code) into Register A.
4B3B
AND E0H E6 E0
Mask Register A to bits 7-5: the record number times 32, the offset of the record in the sector.
4B3D
LD L,A 6F
Copy Register A (the record's offset) into Register L.
4B3E
LD H,42H 26 42
Load Register H with 42H: Register Pair HL = 4200H plus the offset, the record in the buffer.
4B40
XOR B A8
Exclusive OR Register A with Register B: Register A = bits 4-0 of the entry code.
4B41
ADD A,02H C6 02
Add 02H to Register A: the directory records start in sector 2.
4B43
LD E,A 5F
Copy Register A into Register E: the sector of the directory that holds the record.
4B44
RET C9
RETURN with Register D = the directory cylinder, Register E = the sector, Register Pair HL = the record's address.
4B45
GOSUB to 4777H to read cylinder Register D, sector Register E of drive Register C into the buffer at Register Pair HL.
4B48
SUB 06H D6 06
SUBtract 06H from Register A: 00H and the Z FLAG for error 06H, the system data mark a directory sector has.
4B4A
RET Z C8
If the Z FLAG is set (a directory sector), RETURN with Register A = 00H and the Z FLAG: read.
4B4B
ADD A,06H C6 06
Add 06H back to Register A: the result of the read again.
4B4D
RET NZ C0
If the NZ FLAG is set (an error), RETURN with the error code in Register A.
4B4E
PUSH DE D5
Save Register Pair DE (the cylinder and sector) to the stack: the sector was read with an ordinary data mark, so Register D is not the directory cylinder of this diskette.
4B4F
LD DE,0000H 11 00 00
Load Register Pair DE with 0000H: cylinder 0, sector 0, the boot sector.
4B52
GOSUB to 4777H to read the boot sector of drive Register C into the buffer at Register Pair HL.
4B55
POP DE D1
Restore Register Pair DE (the sector wanted) from the stack.
4B56
RET NZ C0
If the NZ FLAG is set (the boot sector could not be read), RETURN with the error code in Register A.
4B57
PUSH HL E5
Save Register Pair HL (the buffer) to the stack.
4B58
INC HL 23
Increment Register Pair HL to byte 1 of the boot sector.
4B59
INC HL 23
Increment Register Pair HL to byte 2 of the boot sector, the directory cylinder.
4B5A
LD D,(HL) 56
Fetch the directory cylinder from byte 2 at Register Pair HL into Register D.
4B5B
LD H,09H 26 09
Load Register H with 09H, the offset of the directory cylinder in a drive code table, for 47A0H.
4B5D
GOSUB to 47A0H: Register A = the low byte of byte +09H of the drive code table of drive Register C (Register H = 47H).
4B60
LD L,A 6F
Copy Register A into Register L: Register Pair HL = byte +09H of the drive's table.
4B61
LD (HL),D 72
Store Register D (the directory cylinder from the boot sector) to byte +09H at Register Pair HL.
4B62
POP HL E1
Restore Register Pair HL (the buffer) from the stack.
4B63
JUMP back to 4B45H to read the directory sector again on cylinder Register D.
4B65
LD A,09H 3E 09
Load Register A with 09H, the offset of the directory cylinder in a drive code table.
4B67
GOSUB to 4797H to fetch byte +09H of the drive code table of drive Register C into Register A.
4B6A
LD D,A 57
Copy Register A (the directory cylinder) into Register D.
4B6B
RET C9
RETURN with Register D = the directory cylinder of drive Register C.
4B6CH - Arithmetic
4B6CH: Register A = Register A x Register E (8 bits). 4B7BH: Register A = Register E / Register A, Register E = the remainder. 4B8FH: Register A and Register Pair HL = Register Pair HL x Register A (24 bits: Register A the low byte, Register Pair HL the high bytes). 4BA9H: Register Pair HL = Register Pair HL / Register A, Register A = the remainder.
4B6C
PUSH BC C5
Save Register Pair BC (the caller's) to the stack. Multiply Register A by Register E.
4B6D
LD D,A 57
Copy Register A (the multiplicand) into Register D.
4B6E
XOR A AF
Set Register A (the product) to 00H (XOR A), which also clears the CARRY FLAG.
4B6F
LD B,08H 06 08
Load Register B with 08H, the bits of the multiplier in Register E.
4B71
ADD A,A 87
Add Register A to itself: the product moves one bit left.
4B72
SLA E CB 23
Shift Register E (the multiplier) left: its top bit goes into the CARRY FLAG.
4B74
If the NC FLAG is set (the bit is 0), JUMP to 4B77H.
4B76
ADD A,D 82
Add Register D (the multiplicand) to Register A (the product).
4B77
Decrement Register B and JUMP to 4B71H while bits are left.
4B79
POP BC C1
Restore Register Pair BC (the caller's) from the stack.
4B7A
RET C9
RETURN with Register A = the product (low 8 bits), Register D = the multiplicand, Register E = 00H.
4B7B
PUSH BC C5
Save Register Pair BC (the caller's) to the stack. Divide Register E by Register A.
4B7C
LD C,A 4F
Copy Register A (the divisor) into Register C.
4B7D
LD B,08H 06 08
Load Register B with 08H, the bits of the dividend in Register E.
4B7F
XOR A AF
Set Register A (the remainder) to 00H (XOR A), which also clears the CARRY FLAG.
4B80
SLA E CB 23
Shift Register E (the dividend, becoming the quotient) left: its top bit goes into the CARRY FLAG.
4B82
RLA 17
Rotate Register A (the remainder) left through the carry: it takes that bit.
4B83
CP C B9
Compare Register A (the remainder) against Register C (the divisor).
4B84
If the C FLAG is set (the remainder is less than the divisor), JUMP to 4B88H.
4B86
SUB C 91
SUBtract Register C (the divisor) from Register A (the remainder).
4B87
INC E 1C
Increment Register E: a 1 bit of the quotient.
4B88
Decrement Register B and JUMP to 4B80H while bits are left.
4B8A
LD C,A 4F
Copy Register A (the remainder) into Register C.
4B8B
LD A,E 7B
Copy Register E (the quotient) into Register A.
4B8C
LD E,C 59
Copy Register C (the remainder) into Register E.
4B8D
POP BC C1
Restore Register Pair BC (the caller's) from the stack.
4B8E
RET C9
RETURN with Register A = the quotient and Register E = the remainder.
4B8F
PUSH BC C5
Save Register Pair BC (the caller's) to the stack. Multiply Register Pair HL by Register A.
4B90
EX DE,HL EB
Exchange Register Pairs DE and HL: Register Pair DE = the multiplicand (the caller's Register Pair HL).
4B91
LD C,A 4F
Copy Register A (the multiplier) into Register C.
4B92
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H: the low 16 bits of the product.
4B95
LD A,L 7D
Copy Register L (00H) into Register A: the high 8 bits of the product.
4B96
LD B,08H 06 08
Load Register B with 08H, the bits of the multiplier in Register C.
4B98
ADD HL,HL 29
Add Register Pair HL to itself: the product's low 16 bits move one bit left.
4B99
RLA 17
Rotate Register A (the product's high byte) left through the carry from Register Pair HL.
4B9A
RLC C CB 01
Rotate Register C (the multiplier) left: its top bit goes into the CARRY FLAG.
4B9C
If the NC FLAG is set (the bit is 0), JUMP to 4BA1H.
4B9E
ADD HL,DE 19
Add Register Pair DE (the multiplicand) to Register Pair HL.
4B9F
ADC A,00H CE 00
Add 00H and the CARRY FLAG to Register A: the carry into the high byte.
4BA1
Decrement Register B and JUMP to 4B98H while bits are left.
4BA3
LD C,A 4F
Copy Register A (bits 23-16 of the product) into Register C.
4BA4
LD A,L 7D
Copy Register L (bits 7-0 of the product) into Register A.
4BA5
LD L,H 6C
Copy Register H (bits 15-8 of the product) into Register L.
4BA6
LD H,C 61
Copy Register C (bits 23-16) into Register H.
4BA7
POP BC C1
Restore Register Pair BC (the caller's) from the stack.
4BA8
RET C9
RETURN with Register A = bits 7-0 of the product and Register Pair HL = bits 23-8; Register Pair DE holds the multiplicand.
4BA9
PUSH DE D5
Save Register Pair DE (the caller's) to the stack. Divide Register Pair HL by Register A.
4BAA
LD D,A 57
Copy Register A (the divisor) into Register D.
4BAB
LD E,10H 1E 10
Load Register E with 10H, the 16 bits of the dividend.
4BAD
XOR A AF
Set Register A (the remainder) to 00H (XOR A), which also clears the CARRY FLAG.
4BAE
ADD HL,HL 29
Add Register Pair HL to itself: the dividend (becoming the quotient) moves one bit left, its top bit into the CARRY FLAG.
4BAF
RLA 17
Rotate Register A (the remainder) left through the carry: it takes that bit.
4BB0
If the C FLAG is set (the remainder passed 255), JUMP to 4BB5H to subtract.
4BB2
CP D BA
Compare Register A (the remainder) against Register D (the divisor).
4BB3
If the C FLAG is set (the remainder is less than the divisor), JUMP to 4BB7H.
4BB5
SUB D 92
SUBtract Register D (the divisor) from Register A (the remainder).
4BB6
INC L 2C
Increment Register L: a 1 bit of the quotient.
4BB7
DEC E 1D
Decrement Register E, the count of dividend bits still to be taken.
4BB8
If the NZ FLAG is set (bits are left), JUMP back to 4BAEH.
4BBA
POP DE D1
Restore Register Pair DE (the caller's) from the stack.
4BBB
RET C9
RETURN with Register Pair HL = the quotient and Register A = the remainder.
4BBCH - Keyboard Driver: a Key Changed
Entered from 43AAH when a row of the keyboard differs from its image: Register A = the bits that changed, Register E = the row now, Register D = the row number, Register Pair HL = the row's image byte, Register Pair BC = the row's address, Index Register IX = the KI block (4015H). The ROM decodes the key (03FAH); the code then gets the system's own changes (4BC3H-4BFFH, the patch SYS0E2): CLEAR held adds 80H (the second character set), SHIFT and CLEAR give 1FH, CLEAR alone gives nothing, SHIFT and 0 turn the reversal of upper and lower case on or off (letters A-Z only), and the code 1AH counts only with the Z key down. The key is kept at +03H of the KI block and its first repeat set 30 ticks ahead.
4BBC
LD (HL),E 73
Store Register E (the row as read now) to the image byte at Register Pair HL (4036H-403CH).
4BBD
AND E A3
AND Register A (the changed bits) with Register E (the row now): the bits of keys that went down. The Z FLAG is set when keys only came up.
4BBE
If the Z FLAG is set (no key went down), JUMP to 4C02H to keep no key.
4BC0
GOSUB to the ROM's 03FAH, which waits (0500H counts), reads the row at Register Pair BC again and, when the key is still down, decodes it with SHIFT into its character in Register A (00H when it went away); for BREAK (01H) the ROM gives RST 28H.
4BC3
LD BC,1A9FH 01 9F 1A
Load Register Pair BC with 1A9FH: Register B = 1AH, the count of letters and also the code of control Z (the down arrow held with Z, which the ROM turns into 1AH); Register C = 9FH, the CLEAR key's code 1FH with the 80H of the second character set.
4BC6
LD HL,4039H 21 39 40
Point Register Pair HL to 4039H, the image of keyboard row 3 (bit 2 the Z key).
4BC9
CP B B8
Compare Register A (the character) against Register B (1AH).
4BCA
If the NZ FLAG is set (not 1AH), JUMP to 4BD0H.
4BCC
BIT 2,(HL) CB 56
Test bit 2 of the image at Register Pair HL (4039H): the Z key.
4BCE
If the Z FLAG is set (1AH without the Z key), JUMP to 4C02H to keep no key; with Z down the code 1AH stays.
4BD0
LD L,3CH 2E 3C
Load Register L with 3CH: Register Pair HL = 403CH, the image of keyboard row 6 (bit 1 the CLEAR key).
4BD2
BIT 1,(HL) CB 4E
Test bit 1 of the image at Register Pair HL (403CH): the CLEAR key.
4BD4
LD HL,3880H 21 80 38
Point Register Pair HL to 3880H, keyboard row 7 (bit 0 the SHIFT key). LD does not change the flags of the BIT test.
4BD7
If the Z FLAG is set (CLEAR not down), JUMP to 4BDAH.
4BD9
OR L B5
OR Register A (the character) with Register L (80H): with CLEAR down the key gives the second character set, 80H and up.
4BDA
LD D,A 57
Copy Register A (the character) into Register D.
4BDB
RES 5,A CB AF
Reset bit 5 of Register A: a lower case letter becomes upper case for the test below.
4BDD
SUB 41H D6 41
SUBtract 41H (the letter A) from Register A: the letters A-Z become 00H-19H.
4BDF
CP B B8
Compare Register A against Register B (1AH): the C FLAG is set for a letter A-Z (not for one with the 80H bit).
4BE0
LD A,D 7A
Copy Register D (the character) back into Register A. LD does not change the flags.
4BE1
If the NC FLAG is set (not a letter), JUMP to 4BE5H: no case reversal.
4BE3
XOR 00H EE 00
Exclusive OR Register A (a letter) with the case reversal flag, the operand at 4BE4H: 00H in the file, 20H when SHIFT 0 has turned the reversal on (4BFBH).
4BE5
BIT 0,(HL) CB 46
Test bit 0 of the byte at Register Pair HL (3880H): the SHIFT key.
4BE7
If the Z FLAG is set (SHIFT not down), JUMP to 4BFFH.
4BE9
CP C B9
Compare Register A against Register C (9FH): SHIFT with CLEAR.
4BEA
If the Z FLAG is set, JUMP to 4BFEH to give 1FH.
4BEC
CP 20H FE 20
Compare Register A against 20H: with SHIFT down the ROM gives 20H for SHIFT 0 and for SHIFT space.
4BEE
If the NZ FLAG is set (any other key), JUMP to 4C03H to keep the character.
4BF0
LD HL,403AH 21 3A 40
Point Register Pair HL to 403AH, the image of keyboard row 4 (bit 0 the 0 key).
4BF3
BIT 0,(HL) CB 46
Test bit 0 of the image at Register Pair HL (403AH): the 0 key.
4BF5
If the Z FLAG is set (SHIFT space), JUMP to 4C03H to keep 20H.
4BF7
LD HL,4BE4H 21 E4 4B
Point Register Pair HL to 4BE4H, the case reversal flag (SHIFT 0 was pressed).
4BFA
XOR (HL) AE
Exclusive OR Register A (20H) with the flag at Register Pair HL: 00H becomes 20H and 20H becomes 00H.
4BFB
LD (HL),A 77
Store Register A (the new flag) to 4BE4H at Register Pair HL.
4BFC
JUMP to 4C02H: SHIFT 0 only switches the case reversal and gives no key.
4BFE
XOR L AD
Exclusive OR Register A (9FH) with Register L (80H of 3880H): Register A = 1FH, the CLEAR code, for SHIFT and CLEAR.
4BFF
CP C B9
Compare Register A against Register C (9FH): CLEAR alone.
4C00
If the NZ FLAG is set (any other key), JUMP to 4C03H to keep the character.
4C02
XOR A AF
Set Register A to 00H (XOR A): no key, which is stored as the key held below.
4C03
LD (IX+03H),A DD 77 03
Store Register A (the key, or 00H) to byte +03H of the KI block at Index Register IX (4018H), the key held.
4C06
LD BC,0333H 01 33 03
Load Register Pair BC with 0333H, a count for the ROM's delay.
4C09
GOSUB to the ROM's 0060H, which counts Register Pair BC (0333H) down to zero: the keys settle.
4C0C
LD A,(4040H) 3A 40 40
Fetch the tick counter from 4040H into Register A.
4C0F
ADD A,1EH C6 1E
Add 1EH (30 ticks) to Register A: the time of the first repeat.
4C11
LD (IX+04H),A DD 77 04
Store Register A to byte +04H of the KI block at Index Register IX (4019H), the tick at which the key repeats. The repeat routine jumps here with the tick plus 3 (file 50F8H).
4C14
LD A,(IX+03H) DD 7E 03
Fetch the key held from byte +03H of the KI block at Index Register IX into Register A.
4C17
OR A B7
OR Register A with itself: the Z FLAG is set when there is no key.
4C18
RET Z C8
If the Z FLAG is set, RETURN with Register A = 00H: no key.
4C19
LD HL,3840H 21 40 38
Point Register Pair HL to 3840H, keyboard row 6 (bit 4 the down arrow).
4C1C
BIT 4,(HL) CB 66
Test bit 4 of the row at Register Pair HL (3840H): the down arrow.
4C1E
If the Z FLAG is set (the down arrow is not down), JUMP to 4C26H.
4C20
LD L,80H 2E 80
Load Register L with 80H: Register Pair HL = 3880H, keyboard row 7.
4C22
BIT 0,(HL) CB 46
Test bit 0 of the row at Register Pair HL (3880H): the SHIFT key.
4C24
SCF 37
Set the CARRY FLAG, kept when the RET NZ below is taken.
4C25
RET NZ C0
If the NZ FLAG is set (SHIFT and the down arrow are down), RETURN with the key in Register A and the CARRY FLAG set.
4C26
OR A B7
OR Register A (the key) with itself: the NZ FLAG is set and the CARRY FLAG cleared.
4C27
RET C9
RETURN with the key in Register A and the NZ FLAG set.
4C28H - Requests With Bit 7 Clear
A request code below 80H (from 4C33H) goes on to the address at 4310H, with the stack as the code that executed RST 28H left it. The ROM's keyboard routine executes RST 28H with Register A = 01H for BREAK (its 0456H); a non breakable AUTO command (4FB9H-4FBBH) or SYS6/SYS (its 525BH, 5268H) puts C8H (RET Z) at 4C2DH, and then BREAK becomes 00H, no key.
4C28
LD HL,(4310H) 2A 10 43
Fetch the address held at 4310H-4311H into Register Pair HL (4C2FH in the file; SYS9/SYS replaces it).
4C2B
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word, the caller's Register Pair HL saved at 4C31H): the caller's Register Pair HL comes back and the address from 4310H becomes the place the RET below goes to.
4C2C
DEC A 3D
Decrement Register A (the request code): 00H and the Z FLAG for 01H, the BREAK key.
4C2D
NOP 00
No operation in the file. The byte becomes C8H (RET Z) for a non breakable AUTO command (4FBBH) or from SYS6/SYS: then BREAK goes on with Register A = 00H.
4C2E
INC A 3C
Increment Register A back to the request code.
4C2F
OR A B7
OR Register A with itself, setting the flags from the request code. 4310H holds 4C2FH in the file, so the RET below is also where a request below 80H returns from.
4C30
RET C9
RETURN to the address from 4310H (the return address of RST 28H was dropped). From the default 4C2FH this RET runs a second time and returns to the address below on the stack, the caller of the code that executed RST 28H.
4C31H - The Request Handler (RST 28H)
Reached from 400CH. A request code with bit 7 clear goes to 4C28H. Otherwise the return address of RST 28H is dropped, the overlay the code names is loaded when it is not in memory (4C53H), the BREAK vector 4315H is set to C9H while it runs, and the overlay is called at its entry with Register A = the request code; its result comes back to the caller of the code that executed RST 28H.
4C31
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): Register Pair HL = the return address of RST 28H, the stack holds the caller's Register Pair HL.
4C32
OR A B7
OR Register A (the request code) with itself: the S FLAG is set when bit 7 is set.
4C33
If the P FLAG is set (bit 7 clear), JUMP to 4C28H.
4C36
POP HL E1
Restore Register Pair HL from the stack: the caller's value. The return address of RST 28H, in Register Pair HL until now, is dropped.
4C37
GOSUB to 4C53H to load the overlay of request code Register A (member Register B for code 88H) unless it is in memory; its entry goes to 4C49H.
4C3A
LD A,(4315H) 3A 15 43
Fetch the BREAK vector byte from 4315H into Register A.
4C3D
LD (4C4DH),A 32 4D 4C
Store Register A to 4C4DH, the operand of LD A,00H at 4C4CH, to put it back afterwards.
4C40
LD A,C9H 3E C9
Load Register A with C9H, a value other than C3H: BREAK will not interrupt the overlay.
4C42
LD (4315H),A 32 15 43
Store Register A (C9H) to 4315H, the BREAK vector byte: BREAK is off while the overlay runs.
4C45
LD A,(430EH) 3A 0E 43
Fetch the request code from 430EH into Register A, for the overlay to see: the new code stored at 4C65H, or for request 88H (which skips that store) the code of the overlay before.
4C48
CALL 0000H CD 00 00
GOSUB to the overlay's entry: the operand 4C49H-4C4AH (0000H in the file) is stored at 4CA4H, 4E00H for an overlay or the transfer address of a member of SYS6/SYS.
4C4B
PUSH AF F5
Save Register Pair AF (the overlay's result) to the stack.
4C4C
LD A,00H 3E 00
Load Register A with the BREAK vector byte saved at 4C3DH (operand 4C4DH, 00H in the file; SYS2/SYS stores C9H there, its 4F4FH-4F52H, to leave BREAK off).
4C4E
LD (4315H),A 32 15 43
Store Register A to 4315H: the BREAK vector as it was.
4C51
POP AF F1
Restore Register Pair AF (the overlay's result) from the stack.
4C52
RET C9
RETURN to the caller of the request entry with the overlay's result in Register A and the flags.
4C53H - Load the Overlay of a Request Code
Register A = the request code, Register B = the member wanted (used by records of type 08H, the members of SYS6/SYS). When bits 3-0 name the overlay in memory (430EH) and the code is not 88H, nothing is read and the entry is 4E00H. Otherwise the overlay's directory record is read (directory entry code: bits 3-0, plus 18H from 8 up), its first extent copied to the system control block 44A0H and the file loaded from drive 0. A load error displays SYSTEM ERROR nn and goes to the abort exit. On return 4C49H holds the entry.
4C53
PUSH HL E5
Save Register Pair HL (the caller's) to the stack.
4C54
LD H,A 67
Copy Register A (the request code) into Register H.
4C55
LD A,B 78
Copy Register B (the member wanted) into Register A.
4C56
LD (4C99H),A 32 99 4C
Store Register A (the member wanted) to 4C99H, the operand of LD B,00H at 4C98H.
4C59
LD A,H 7C
Copy Register H (the request code) back into Register A.
4C5A
CP 88H FE 88
Compare Register A against 88H, function 0 of SYS6/SYS, the library of commands: it is always loaded, since each command is a different member.
4C5C
If the Z FLAG is set (88H), JUMP to 4C6DH to load it.
4C5E
LD A,(430EH) 3A 0E 43
Fetch the request code of the overlay in memory from 430EH into Register A.
4C61
XOR H AC
Exclusive OR Register A with Register H (the new request code).
4C62
AND 0FH E6 0F
Mask Register A to bits 3-0: the Z FLAG is set when both codes name the same overlay.
4C64
LD A,H 7C
Copy Register H (the new request code) into Register A. LD does not change the flags.
4C65
LD (430EH),A 32 0E 43
Store Register A (the new request code) to 430EH.
4C68
LD HL,4E00H 21 00 4E
Load Register Pair HL with 4E00H, the entry of every overlay. LD does not change the flags.
4C6B
If the Z FLAG is set (the overlay is in memory), JUMP to 4CA4H to make 4E00H the entry.
4C6D
PUSH DE D5
Save Register Pair DE (the caller's) to the stack.
4C6E
PUSH BC C5
Save Register Pair BC (the caller's) to the stack.
4C6F
AND 0FH E6 0F
Mask Register A (the request code) to bits 3-0, the overlay number.
4C71
CP 08H FE 08
Compare Register A (the overlay number) against 08H.
4C73
If the C FLAG is set (0-7: the directory entry code is the number itself), JUMP to 4C77H.
4C75
ADD A,18H C6 18
Add 18H to Register A: overlay numbers 8-15 have the directory entry codes 20H-27H (the second record of directory sectors 2-9).
4C77
LD (44A7H),A 32 A7 44
Store Register A (the directory entry code) to 44A7H, byte +07H of the system control block.
4C7A
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A).
4C7B
LD (44A1H),A 32 A1 44
Store Register A (00H) to 44A1H, byte +01H of the system control block: full access, whole sectors.
4C7E
SBC HL,HL ED 62
SUBtract Register Pair HL and the carry from itself: Register Pair HL = 0000H.
4C80
LD (44AAH),HL 22 AA 44
Store Register Pair HL (0000H) to 44AAH-44ABH, the next record number of the system control block.
4C83
LD C,A 4F
Copy Register A (00H) into Register C: drive 0.
4C84
LD A,(44A7H) 3A A7 44
Fetch the directory entry code from 44A7H into Register A.
4C87
LD B,A 47
Copy Register A (the directory entry code) into Register B.
4C88
GOSUB to 4B10H to read the directory sector of entry Register B on drive Register C (0) into 4200H: Register Pair HL = the overlay's directory record.
4C8B
If the NZ FLAG is set (the directory could not be read), JUMP to 4CA9H to display SYSTEM ERROR.
4C8D
LD A,L 7D
Copy Register L (the low byte of the record's address) into Register A.
4C8E
ADD A,16H C6 16
Add 16H to Register A: byte 16H of the record, its first extent.
4C90
LD L,A 6F
Copy Register A into Register L: Register Pair HL = byte 16H of the directory record.
4C91
LD A,(HL) 7E
Fetch byte 16H (the first extent's cylinder) from Register Pair HL into Register A.
4C92
INC L 2C
Increment Register L to byte 17H of the directory record, the granule byte.
4C93
LD H,(HL) 66
Fetch byte 17H (the first extent's granule byte) from Register Pair HL into Register H.
4C94
LD L,A 6F
Copy Register A (the cylinder) into Register L: Register Pair HL = the extent, cylinder in Register L, granule byte in Register H.
4C95
LD (44AEH),HL 22 AE 44
Store Register Pair HL to 44AEH-44AFH, the first extent of the system control block.
4C98
LD B,00H 06 00
Load Register B with the member wanted (operand 4C99H, stored at 4C56H; 00H in the file).
4C9A
LD DE,44A0H 11 A0 44
Point Register Pair DE to 44A0H, the system control block.
4C9D
GOSUB to 4CF8H to load the file of the control block at Register Pair DE: Register Pair HL returns the entry.
4CA0
If the NZ FLAG is set (a load error), JUMP to 4CA9H to display SYSTEM ERROR.
4CA2
POP BC C1
Restore Register Pair BC (the caller's) from the stack.
4CA3
POP DE D1
Restore Register Pair DE (the caller's) from the stack.
4CA4
LD (4C49H),HL 22 49 4C
Store Register Pair HL (the entry: 4E00H, or the transfer address the file gave) to 4C49H, the operand of CALL at 4C48H.
4CA7
POP HL E1
Restore Register Pair HL (the caller's) from the stack.
4CA8
RET C9
RETURN to the request handler (or to 4AABH after the reload of SYS1/SYS) with 4C49H holding the entry of the overlay.
4CA9
AND 3FH E6 3F
Mask Register A (the error code) to bits 5-0.
4CAB
LD HL,4CC8H 21 C8 4C
Point Register Pair HL to 4CC8H, the XX of the text SYSTEM ERROR XX.
4CAE
GOSUB to 4DECH to write Register A (the error code) as two hex digits at Register Pair HL (4CC8H-4CC9H).
4CB1
LD HL,4CBAH 21 BA 4C
Point Register Pair HL to 4CBAH, the text: a line feed, SYSTEM ERROR and the code.
4CB4
GOSUB to 447BH to display the text at Register Pair HL and write it to the job log.
4CB7
JUMP to 4030H, the abort exit (request A3H, SYS1/SYS).
4CBA
DEFB 0AH 0A
0AH, a line feed, so the message starts on a new line.
4CBB-4CC9
DEFM "SYSTEM ERROR XX" 53 59 53 54 45 4D 20 45 52 52 4F 52 20 58 58
The message for an overlay that cannot be loaded; 4CAEH writes the error code in hex over the XX at 4CC8H-4CC9H.
4CCA
DEFB 0DH 0D
0DH, the carriage return that ends the message (44ECH stops after it).
4CCBH - Load and Run a Program (4433H)
The program file at Register Pair DE is loaded through 4430H. A load error goes to the error message at 4409H. Otherwise the program is started at its transfer address: through the DEBUG monitor when bit 7 of 430FH is set, unless bit 1 is set too.
4CCB
PUSH HL E5
Save Register Pair HL (the caller's) to the stack.
4CCC
LD HL,430FH 21 0F 43
Point Register Pair HL to 430FH, the system flags.
4CCF
SET 2,(HL) CB D6
Set bit 2 of the system flags at Register Pair HL (430FH): a program is being loaded to run.
4CD1
GOSUB to 4430H to load the program file named by the control block at Register Pair DE: Register Pair HL = its transfer address.
4CD4
If the NZ FLAG is set (a load error), JUMP to 4409H to display the error (Register A holds the code with bit 6 set).
4CD7
EX (SP),HL E3
Exchange Register Pair HL with the top of the stack (the Stack Pointer's word): the stack holds the transfer address, Register Pair HL the caller's value.
4CD8
LD A,(430FH) 3A 0F 43
Fetch the system flags from 430FH into Register A.
4CDB
BIT 1,A CB 4F
Test bit 1 of Register A (the system flags), set by SYS2/SYS (its 4F4DH).
4CDD
RET NZ C0
If the NZ FLAG is set (bit 1), RETURN, which starts the program at its transfer address.
4CDE
BIT 7,A CB 7F
Test bit 7 of Register A (the system flags): set when DEBUG is to start the program.
4CE0
If the NZ FLAG is set, JUMP to 400FH (the RST 30H vector, DEBUG) with the transfer address on the stack as the place the program is to start.
4CE3
RET C9
RETURN, which starts the program at its transfer address.
4CE4H - Load a Program File (4430H)
The file named by the control block at Register Pair DE is opened with the buffer at 4200H and whole sectors (request 94H, SYS2/SYS), then loaded by 4CF8H. Errors come back with bit 6 set; FILE NOT IN DIRECTORY (18H) is changed to PROGRAM NOT FOUND (1FH).
4CE4
LD B,00H 06 00
Load Register B with 00H, the record length for the open: 256, whole sectors.
4CE6
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the sector buffer for the open.
4CE9
GOSUB to 4424H, request 94H: SYS2/SYS opens the file named by the control block at Register Pair DE.
4CEC
If the Z FLAG is set (open), GOSUB to 4CF8H to load the file (Register B 00H, no member).
4CEF
RET Z C8
If the Z FLAG is set (loaded), RETURN with Register Pair HL = the transfer address.
4CF0
SET 6,A CB F7
Set bit 6 of Register A (the error code): only the text of the message is to be shown.
4CF2
CP 58H FE 58
Compare Register A against 58H: 18H, FILE NOT IN DIRECTORY, with bit 6.
4CF4
RET NZ C0
If the NZ FLAG is set (any other error), RETURN with the error code in Register A.
4CF5
ADD A,07H C6 07
Add 07H to Register A: 5FH, 1FH (PROGRAM NOT FOUND) with bit 6, and the NZ FLAG.
4CF7
RET C9
RETURN with error 5FH in Register A and the NZ FLAG from the ADD.
4CF8H - The Loader
Reads the file of the control block at Register Pair DE byte by byte (4D8EH, through the buffer at 4200H) and acts on each record by its type byte: 01H a load block (length, address, the bytes; each byte stored is read back), 02H the transfer address (the end), 04H the end of a member (its transfer address was saved from its header), 08H a member header (the member wanted is taken by its record and offset), 0AH and anything from 20H up an error (22H), any other type below 20H skipped by its length. Errors come back with bit 6 set.
4CF8
LD A,B 78
Copy Register B (the member wanted) into Register A.
4CF9
LD (4D67H),A 32 67 4D
Store Register A (the member wanted) to 4D67H, the operand of CP 00H at 4D66H.
4CFC
LD BC,42FFH 01 FF 42
Load Register Pair BC with 42FFH: Register B = 42H, the page of the buffer; Register C = FFH, the offset before the first byte, so the first byte asked for reads a sector.
4CFF
GOSUB to 4D8EH to fetch the next byte of the file into Register A: the type of the next record.
4D02
CP 01H FE 01
Compare Register A (the record type) against 01H, a load block. The member header code jumps here with the first type byte of a member.
4D04
If the Z FLAG is set (type 01H), JUMP to 4D36H to load the block.
4D06
CP 02H FE 02
Compare Register A (the record type) against 02H, the transfer address.
4D08
If the Z FLAG is set (type 02H), JUMP to 4D29H.
4D0A
CP 04H FE 04
Compare Register A (the record type) against 04H, the end of a member.
4D0C
If the Z FLAG is set (type 04H), JUMP to 4D5CH.
4D0E
CP 08H FE 08
Compare Register A (the record type) against 08H, a member header.
4D10
If the Z FLAG is set (type 08H), JUMP to 4D5EH.
4D12
CP 0AH FE 0A
Compare Register A (the record type) against 0AH.
4D14
If the Z FLAG is set (type 0AH, not allowed in a load file), JUMP to 4D1AH.
4D16
CP 20H FE 20
Compare Register A (the record type) against 20H.
4D18
If the C FLAG is set (another type below 20H), JUMP to 4D1EH to skip the record.
4D1A
LD A,22H 3E 22
Load Register A with 22H, the error code LOAD FILE FORMAT ERROR.
4D1C
OR A B7
OR Register A with itself: the NZ FLAG is set.
4D1D
RET C9
RETURN with error 22H (LOAD FILE FORMAT ERROR) in Register A and the NZ FLAG.
4D1E
GOSUB to 4D8EH to fetch the record's length byte into Register A.
4D21
LD B,A 47
Copy Register A (the length) into Register B, the count of bytes to skip (00H skips 256).
4D22
GOSUB to 4D8EH to fetch a byte of the record into Register A, to be skipped.
4D25
Decrement Register B and JUMP to 4D22H while bytes of the record are left.
4D27
JUMP back to 4CFFH for the type byte of the next record.
4D29
GOSUB to 4D8EH to fetch the length byte of the transfer record (02H), which is not checked.
4D2C
GOSUB to 4D8EH to fetch the low byte of the transfer address into Register A.
4D2F
LD L,A 6F
Copy Register A (the low byte of the transfer address) into Register L.
4D30
GOSUB to 4D8EH to fetch the high byte of the transfer address into Register A.
4D33
LD H,A 67
Copy Register A into Register H: Register Pair HL = the transfer address.
4D34
XOR A AF
Set Register A to 00H and the Z FLAG (XOR A): the file is loaded.
4D35
RET C9
RETURN with Register Pair HL = the transfer address and the Z FLAG set.
4D36
GOSUB to 4D8EH to fetch the load block's length byte into Register A (it counts the two address bytes).
4D39
LD B,A 47
Copy Register A (the length) into Register B.
4D3A
GOSUB to 4D8EH to fetch the low byte of the load address into Register A.
4D3D
LD L,A 6F
Copy Register A (the low byte of the load address) into Register L.
4D3E
DEC B 05
Decrement Register B: one byte of the length used.
4D3F
GOSUB to 4D8EH to fetch the high byte of the load address into Register A.
4D42
LD H,A 67
Copy Register A into Register H: Register Pair HL = the load address.
4D43
DEC B 05
Decrement Register B: Register B = the count of data bytes (a length of 00H gives 254, 01H gives 255, 02H gives 256).
4D44
GOSUB to 4D8EH to fetch the next data byte into Register A.
4D47
LD (HL),A 77
Store Register A (the data byte) to the address at Register Pair HL.
4D48
CP (HL) BE
Compare Register A against the byte at Register Pair HL: it must read back the same.
4D49
If the NZ FLAG is set (the byte did not stay), JUMP to 4D50H.
4D4B
INC HL 23
Increment Register Pair HL to the next load address.
4D4C
Decrement Register B and JUMP to 4D44H while data bytes are left.
4D4E
JUMP back to 4CFFH for the type byte of the next record.
4D50
LD B,(HL) 46
Fetch the byte at Register Pair HL (what is there instead of the data byte) into Register B.
4D51
CPL 2F
Complement Register A (the data byte that did not stay), to test the memory at Register Pair HL.
4D52
LD (HL),A 77
Store Register A (the complement) to the address at Register Pair HL, a test whether the memory can change at all.
4D53
LD A,(HL) 7E
Fetch the byte at Register Pair HL back into Register A.
4D54
CP B B8
Compare Register A against Register B (the byte that was there before the test).
4D55
LD A,63H 3E 63
Load Register A with 63H: 23H, MEMORY FAULT, with bit 6. LD does not change the flags.
4D57
RET NZ C0
If the NZ FLAG is set (the memory changed: it is memory that did not hold the data byte), RETURN with error 63H.
4D58
LD A,64H 3E 64
Load Register A with 64H: 24H, ATTEMPTED TO LOAD READ ONLY MEMORY, with bit 6.
4D5A
OR A B7
OR Register A with itself: the NZ FLAG is set.
4D5B
RET C9
RETURN with error 64H in Register A: the address does not change, it is not RAM.
4D5C
POP HL E1
Restore Register Pair HL from the stack: the member's transfer address, pushed at 4D72H when its header was found.
4D5D
RET C9
RETURN with Register Pair HL = the member's transfer address and the Z FLAG (from CP 04H): the member is loaded.
4D5E
GOSUB to 4D8EH to fetch the member header's length byte into Register A.
4D61
LD B,A 47
Copy Register A (the length) into Register B.
4D62
GOSUB to 4D8EH to fetch the member's code into Register A.
4D65
DEC B 05
Decrement Register B: one byte of the header used.
4D66
CP 00H FE 00
Compare Register A (the member's code) against the member wanted (the operand at 4D67H, stored at 4CF9H).
4D68
If the NZ FLAG is set (another member), JUMP to 4D22H to skip the Register B bytes left of the header.
4D6A
GOSUB to 4D8EH to fetch the low byte of the member's transfer address into Register A.
4D6D
LD L,A 6F
Copy Register A (the low byte of the member's transfer address) into Register L.
4D6E
GOSUB to 4D8EH to fetch the high byte into Register A.
4D71
LD H,A 67
Copy Register A into Register H: Register Pair HL = the member's transfer address.
4D72
PUSH HL E5
Save Register Pair HL (the member's transfer address) to the stack, for the record of type 04H (4D5CH).
4D73
GOSUB to 4D8EH to fetch the low byte of the member's record number into Register A.
4D76
LD L,A 6F
Copy Register A (the low byte of the member's record number) into Register L.
4D77
GOSUB to 4D8EH to fetch the high byte into Register A.
4D7A
LD H,A 67
Copy Register A into Register H: Register Pair HL = the record (sector) of the file where the member starts.
4D7B
GOSUB to 4D8EH to fetch the member's offset in that sector into Register A.
4D7E
LD C,A 4F
Copy Register A (the offset) into Register C.
4D7F
PUSH BC C5
Save Register Pair BC (Register C the member's offset) to the stack.
4D80
LD B,H 44
Copy Register H (high byte of the member's record) into Register B.
4D81
LD C,L 4D
Copy Register L (low byte) into Register C: Register Pair BC = the member's record.
4D82
GOSUB to 4442H to position the file of the control block at Register Pair DE to record Register Pair BC.
4D85
POP BC C1
Restore Register Pair BC from the stack: Register C = the member's offset.
4D86
If the NZ FLAG is set (the position failed), JUMP to 4DA2H; its RET takes the member's transfer address pushed at 4D72H.
4D88
GOSUB to 4D91H to read the member's sector into the buffer and fetch the byte at offset Register C: the type of its first record.
4D8B
JUMP to 4D02H to act on the record type in Register A.
4D8E
INC C 0C
Increment Register C, the offset of the next byte in the buffer at 4200H. Fetch the next byte of the file.
4D8F
If the NZ FLAG is set (the offset is still inside the sector), JUMP to 4DA5H to fetch the byte.
4D91
PUSH DE D5
Save Register Pair DE (the control block) to the stack. The buffer is used up: read the next sector.
4D92
EX (SP),IX DD E3
Exchange Index Register IX with the top of the stack (the Stack Pointer's word): Index Register IX = the control block, the stack holds the caller's Index Register IX.
4D94
PUSH HL E5
Save Register Pair HL (the load address) to the stack.
4D95
PUSH DE D5
Save Register Pair DE (the control block) to the stack.
4D96
PUSH BC C5
Save Register Pair BC (Register B the count, Register C the offset) to the stack.
4D97
GOSUB to 4949H to read the sector at the next record number of the control block at Index Register IX into its buffer (4200H).
4D9A
POP BC C1
Restore Register Pair BC (Register B the count, Register C the offset) from the stack.
4D9B
POP DE D1
Restore Register Pair DE (the control block) from the stack.
4D9C
POP HL E1
Restore Register Pair HL (the load address) from the stack.
4D9D
POP IX DD E1
Restore Index Register IX (the caller's) from the stack.
4D9F
If the Z FLAG is set (read), JUMP to 4DA5H to fetch the byte.
4DA1
POP BC C1
Restore Register Pair BC from the stack: the return address into the loader is dropped, so the RET below leaves the loader; inside a member (after 4D72H) it takes the member's transfer address instead.
4DA2
OR 40H F6 40
OR Register A (the error code) with 40H: bit 6, the text of the message alone.
4DA4
RET C9
RETURN with the error code in Register A and the NZ FLAG.
4DA5
PUSH BC C5
Save Register Pair BC (the count and offset) to the stack.
4DA6
LD B,42H 06 42
Load Register B with 42H: Register Pair BC = 4200H plus the offset, the byte in the buffer.
4DA8
LD A,(BC) 0A
Fetch the byte at Register Pair BC into Register A.
4DA9
POP BC C1
Restore Register Pair BC (the count and offset) from the stack.
4DAA
RET C9
RETURN with the byte of the file in Register A.
4DABH - The Clock Display Task
SYS6/SYS installs this control block in slot 6 (its 5244H-524BH); its routine writes the time to the top line of the screen, at 3C35H, once a second (every fifth run of the slot).
4DAB-4DAC
DEFW 4DAEH AE 4D
Task control block +00H-+01H: 4DAEH, the address of the routine below.
4DAD
DEFB 05H 05
Task control block +02H: the runs left before the next display, 05H.
4DAE
DEC (IX+02H) DD 35 02
Decrement byte +02H of the task control block at Index Register IX (4DADH).
4DB1
RET NZ C0
If the NZ FLAG is set (not yet the fifth run), RETURN to the dispatcher.
4DB2
LD (IX+02H),05H DD 36 02 05
Store 05H to byte +02H of the task control block at Index Register IX: five more runs.
4DB6
LD HL,3C35H 21 35 3C
Point Register Pair HL to 3C35H, screen line 0, column 53. Fall into 4DB9H to write the time there.
4DB9
LD DE,4043H 11 43 40
Point Register Pair DE to 4043H, the hours (entry 446DH: Register Pair HL is where the time goes).
4DBC
LD C,3AH 0E 3A
Load Register C with 3AH, the character : between hours, minutes and seconds.
4DBE
LD B,03H 06 03
Load Register B with 03H, the count of numbers to write (three).
4DC0
LD A,(DE) 1A
Fetch the number at Register Pair DE (hours, minutes, seconds; or month, day, year) into Register A.
4DC1
DEC DE 1B
Decrement Register Pair DE to the next number.
4DC2
LD (HL),2FH 36 2F
Store 2FH (one less than the digit 0) to the place of the tens digit at Register Pair HL.
4DC4
INC (HL) 34
Increment the tens digit at Register Pair HL.
4DC5
SUB 0AH D6 0A
SUBtract 0AH (10) from Register A, the number being turned into digits.
4DC7
If the NC FLAG is set (10 or more were left), JUMP back to 4DC4H.
4DC9
ADD A,3AH C6 3A
Add 3AH to Register A: the units digit (the remainder less 10, plus 10 and the 30H of the digit 0).
4DCB
INC HL 23
Increment Register Pair HL to the units place.
4DCC
LD (HL),A 77
Store Register A (the units digit) at Register Pair HL.
4DCD
INC HL 23
Increment Register Pair HL past the number just written.
4DCE
DEC B 05
Decrement Register B, the count of numbers still to write.
4DCF
RET Z C8
If the Z FLAG is set (three numbers written), RETURN with Register Pair HL after the last digit.
4DD0
LD (HL),C 71
Store Register C (: or /) at Register Pair HL.
4DD1
INC HL 23
Increment Register Pair HL to the next number's place.
4DD2
JUMP back to 4DC0H for the next number at Register Pair DE.
4DD4
LD DE,4046H 11 46 40
Point Register Pair DE to 4046H, the month (entry 4470H: Register Pair HL is where the date goes).
4DD7
LD C,2FH 0E 2F
Load Register C with 2FH, the character / between month, day and year.
4DD9
JUMP to 4DBEH to write the month, day and year from 4046H down.
4DDBH - The Trace Task
SYS6/SYS installs this control block in slot 11 (its 525AH-5261H), so it runs at every clock interrupt and writes the interrupted program counter in hex at 3C2EH, the top line of the screen. 4DE7H writes Register Pair DE and 4DECH Register A as hex at Register Pair HL; SYS4/SYS and SYS6/SYS call them too.
4DDB-4DDC
DEFW 4DDDH DD 4D
Task control block +00H-+01H: 4DDDH, the address of the routine below.
4DDD
LD HL,0012H 21 12 00
Load Register Pair HL with 0012H (18), the distance from the Stack Pointer to the interrupted program counter in a task of slots 8-11: the CALL from 4589H, the return to 454CH, five register pairs (453DH-4541H) and two (4518H-4519H).
4DE0
ADD HL,SP 39
Add the Stack Pointer to Register Pair HL: Register Pair HL = the address of the interrupted program counter on the stack.
4DE1
LD E,(HL) 5E
Fetch the low byte of the program counter from Register Pair HL into Register E.
4DE2
INC HL 23
Increment Register Pair HL to the high byte of the interrupted program counter.
4DE3
LD D,(HL) 56
Fetch the high byte from Register Pair HL into Register D: Register Pair DE = the interrupted program counter.
4DE4
LD HL,3C2EH 21 2E 3C
Point Register Pair HL to 3C2EH, screen line 0, column 46.
4DE7
LD A,D 7A
Copy Register D (the high byte of Register Pair DE) into Register A (entry 4DE7H: Register Pair DE in hex at Register Pair HL).
4DE8
GOSUB to 4DECH to write Register A as two hex digits at Register Pair HL.
4DEB
LD A,E 7B
Copy Register E (the low byte) into Register A, and fall into 4DECH to write it.
4DEC
PUSH AF F5
Save Register Pair AF (the byte in Register A) to the stack.
4DED
RRA 1F
Rotate Register A right through the carry, the first of four: the high digit moves down.
4DEE
RRA 1F
Rotate Register A right through the carry, the second of four.
4DEF
RRA 1F
Rotate Register A right through the carry, the third of four.
4DF0
RRA 1F
Rotate Register A right through the carry, the fourth: the high digit is in bits 3-0.
4DF1
GOSUB to 4DF5H to write the digit in bits 3-0 of Register A.
4DF4
POP AF F1
Restore Register Pair AF (the byte) from the stack, and fall into 4DF5H for the low digit.
4DF5
AND 0FH E6 0F
Mask Register A to bits 3-0, one hex digit (0-15).
4DF7
ADD A,90H C6 90
Add 90H to Register A (the digit), the first step of turning it into ASCII.
4DF9
DAA 27
Decimal adjust Register A: 90H-99H for the digits 0-9, 00H-05H with the CARRY FLAG for A-F.
4DFA
ADC A,40H CE 40
Add 40H and the CARRY FLAG (from the DAA) to Register A.
4DFC
DAA 27
Decimal adjust Register A: the ASCII character of the digit, 30H-39H or 41H-46H.
4DFD
LD (HL),A 77
Store Register A (the hex digit) at Register Pair HL.
4DFE
INC HL 23
Increment Register Pair HL to the next place.
4DFF
RET C9
RETURN with Register Pair HL after the digit.
4E00H - The Reset: Transfer Address of SYS0/SYS
BOOT/SYS jumps here after loading SYS0/SYS (Index Register IY = 0000H, or a drive code table after a boot through a driver). The reset decodes the banner, finds the top of memory, installs the keyboard driver and the key repeat routine, sets up the devices, the interrupts and the clock, shows the date with its day of the week (or --NO DATE--), checks the system information sector of drive 0, takes the drive code tables, the serial number and the AUTO command from the diskette, loads CONFIG/SYS when the diskette asks for it, and ends in the code it copied to 405DH, which runs the AUTO command or goes to VTOS READY. 4E00H-50FFH is taken by the overlays afterwards, so this code runs only once. It carries the patch SYS0D (4E36H-4E47H, 4EA6H-4EBDH, 4EC3H-4ECEH, 4F2EH, 4FC0H-4FCCH, 50D0H-50D5H).
4E00
DI F3
Disable interrupts while the system is set up; they are turned on at 4E93H.
4E01
IM 1 ED 56
Select interrupt mode 1: an interrupt calls 0038H in the ROM, which jumps to 4012H.
4E03
LD SP,41E0H 31 E0 41
Load the Stack Pointer with 41E0H, the stack sector 0 of BOOT/SYS used (41D2H-41DFH below it); sector 1, the boot through a driver, used 4160H.
4E06
LD L,00H 2E 00
Load Register L with 00H, the low byte of the banner's address.
4E08
LD H,3CH 26 3C
Load Register H with 3CH: Register Pair HL = 3C00H, the encoded banner at the top of the screen.
4E0A
LD A,(HL) 7E
Fetch the first encoded byte from Register Pair HL (3C00H) into Register A.
4E0B
NEG ED 44
Negate Register A: 00H less the encoded byte gives the character.
4E0D
LD (HL),A 77
Store Register A (the character) back to the screen at Register Pair HL.
4E0E
INC HL 23
Increment Register Pair HL to the next place on the screen.
4E0F
LD A,(HL) 7E
Fetch the next byte from the screen at Register Pair HL into Register A.
4E10
CP 20H FE 20
Compare Register A against 20H, a space: no encoded byte is 20H (a space is stored as E0H), and the screen after 3C7FH still holds the spaces BOOT/SYS cleared it to.
4E12
If the NZ FLAG is set (still encoded), JUMP back to 4E0BH to decode it.
4E14
LD HL,5200H 21 00 52
Load Register Pair HL with 5200H, the first address above SYS0/SYS's buffers.
4E17
LD (4047H),HL 22 47 40
Store Register Pair HL (5200H) to 4047H-4048H.
4E1A
LD HL,FFFFH 21 FF FF
Load Register Pair HL with FFFFH, the top of the address space, to find the top of memory.
4E1D
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A.
4E1E
LD B,A 47
Copy Register A (the byte as it was) into Register B.
4E1F
CPL 2F
Complement Register A, to see whether the address will hold another value.
4E20
LD (HL),A 77
Store Register A (the complement) to the address at Register Pair HL.
4E21
CP (HL) BE
Compare Register A against the byte at Register Pair HL: the Z FLAG is set when the complement stayed, that is when there is RAM at Register Pair HL.
4E22
LD (HL),B 70
Store Register B (the byte as it was) back to the address at Register Pair HL. LD does not change the flags.
4E23
If the Z FLAG is set (RAM found), JUMP to 4E2BH.
4E25
LD A,H 7C
Copy Register H (the high byte of the address tried) into Register A.
4E26
SUB 04H D6 04
SUBtract 04H from Register A (the high byte of the address): 1K lower.
4E28
LD H,A 67
Copy Register A into Register H: Register Pair HL = the address 1K below (FBFFH, F7FFH ...).
4E29
JUMP back to 4E1DH to try the address at Register Pair HL.
4E2B
LD (4049H),HL 22 49 40
Store Register Pair HL (the top of memory: 7FFFH, BFFFH or FFFFH for 16K, 32K or 48K) to 4049H-404AH.
4E2E
XOR A AF
Set Register A to 00H (XOR A), the value for the cassette latch.
4E2F
LD (37E4H),A 32 E4 37
Store Register A (00H) to the cassette select latch at 37E4H.
4E32
LD A,FFH 3E FF
Load Register A with FFH, the value for the RS-232-C control register.
4E34
OUT (EAH),A D3 EA
Send Register A (FFH) to port EAH, the control register of the RS-232-C interface: all control bits set, which turns DTR and RTS off.
4E36
LD HL,50E0H 21 E0 50
Point Register Pair HL to 50E0H, the key repeat routine in the file. 4E36H-4E47H is the patch SYS0D.
4E39
LD DE,41E5H 11 E5 41
Point Register Pair DE to 41E5H, where the routine is to run (out of the way of the overlays at 4E00H).
4E3C
LD BC,001BH 01 1B 00
Load Register Pair BC with 001BH, its 27 bytes.
4E3F
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL (50E0H) to Register Pair DE (41E5H), counting up (LDIR).
4E41
LD A,(3840H) 3A 40 38
Fetch row 6 of the keyboard from 3840H into Register A (bit 3 is the up arrow).
4E44
AND 08H E6 08
Mask Register A (keyboard row 6) to bit 3, the up arrow key.
4E46
If the NZ FLAG is set (the up arrow is held), JUMP to 4E4EH: the keyboard driver already at 4016H stays.
4E48
LD HL,439CH 21 9C 43
Load Register Pair HL with 439CH, SYS0/SYS's keyboard driver.
4E4B
LD (4016H),HL 22 16 40
Store Register Pair HL (439CH) to 4016H, the driver address of the KI device control block.
4E4E
LD HL,(4016H) 2A 16 40
Fetch the KI driver address from 4016H into Register Pair HL.
4E51
LD (43B8H),HL 22 B8 43
Store Register Pair HL to 43B8H, the KI driver the system started with.
4E54
LD HL,(401EH) 2A 1E 40
Fetch the DO driver address from 401EH into Register Pair HL.
4E57
LD (43BAH),HL 22 BA 43
Store Register Pair HL to 43BAH, the DO driver the system started with.
4E5A
LD HL,(4026H) 2A 26 40
Fetch the PR driver address from 4026H into Register Pair HL.
4E5D
LD (43BCH),HL 22 BC 43
Store Register Pair HL to 43BCH, the PR driver the system started with.
4E60
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, no saved driver yet.
4E63
LD (43BEH),HL 22 BE 43
Store Register Pair HL (0000H) to 43BEH, the KI driver SYS7/SYS keeps there while it reads DO commands.
4E66
LD HL,43D8H 21 D8 43
Point Register Pair HL to 43D8H, the five free device control blocks.
4E69
LD (HL),00H 36 00
Store 00H to the address at Register Pair HL.
4E6B
INC L 2C
Increment Register L: the Z FLAG is set when it wraps from FFH to 00H, after 43FFH.
4E6C
If the NZ FLAG is set, JUMP back to 4E69H to clear the next byte.
4E6E
PUSH IY FD E5
Save Index Register IY (from BOOT/SYS: 0000H, or a drive code table) to the stack.
4E70
POP HL E1
Restore Register Pair HL from the stack: Register Pair HL = the value of Index Register IY.
4E71
LD A,H 7C
Copy Register H (the high byte of the boot's Index Register IY) into Register A.
4E72
OR L B5
OR Register A with Register L: the Z FLAG is set when Register Pair HL (Index Register IY at the boot) is 0000H.
4E73
If the Z FLAG is set (booted by the ROM through sector 0 of BOOT/SYS), JUMP to 4E7DH: drive 0's table stays as loaded.
4E75
LD DE,4700H 11 00 47
Point Register Pair DE to 4700H, the drive code table of drive 0.
4E78
LD BC,000AH 01 0A 00
Load Register Pair BC with 000AH, the 10 bytes of a table.
4E7B
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL (the table the boot used) to Register Pair DE (4700H), counting up (LDIR).
4E7D
LD A,(37ECH) 3A EC 37
Fetch the controller's status from 37ECH into Register A; the read clears the controller's interrupt request before interrupts are turned on. Register A is not used.
4E80
LD A,C9H 3E C9
Load Register A with C9H, any value other than C3H.
4E82
LD (4315H),A 32 15 43
Store Register A (C9H) to 4315H: the BREAK key vector is not armed.
4E85
LD HL,404CH 21 4C 40
Point Register Pair HL to 404CH, the mask of interrupts that are served.
4E88
LD (HL),00H 36 00
Store 00H to 404CH at Register Pair HL: no interrupt is served for now.
4E8A
SET 7,(HL) CB FE
Set bit 7 of the mask at Register Pair HL (404CH): the real time clock is served.
4E8C
SET 6,(HL) CB F6
Set bit 6 of the mask at Register Pair HL (404CH): the disk controller's interrupt is served. The mask is C0H.
4E8E
LD A,01H 3E 01
Load Register A with 01H, the system flags to start with (bit 0).
4E90
LD (430FH),A 32 0F 43
Store Register A (01H) to the system flags at 430FH.
4E93
EI FB
Enable interrupts: from here the clock interrupt runs the task dispatcher.
4E94
LD A,(4306H) 3A 06 43
Fetch the month byte of the date kept across the reset from 4306H into Register A (the month OR 50H).
4E97
XOR 50H EE 50
Exclusive OR Register A with 50H: Register A = the month, 1-12 when a date is kept.
4E99
LD (4046H),A 32 46 40
Store Register A (the month) to 4046H, the month of the date.
4E9C
LD B,A 47
Copy Register A (the month) into Register B, the count of months for the day of the week below.
4E9D
DEC A 3D
Decrement Register A: 00H-0BH for a month of 1-12.
4E9E
CP 0CH FE 0C
Compare Register A (the month less one) against 0CH.
4EA0
If the NC FLAG is set (the month is not 1-12: no date kept), JUMP to 4F4FH to clear the date and show --NO DATE--.
4EA3
LD A,(4307H) 3A 07 43
Fetch the day and year byte of the date from 4307H into Register A (the day in bits 7-3, the year less 80 in bits 2-0).
4EA6
LD E,A 5F
Copy Register A into Register E. 4EA6H-4EBDH is the patch SYS0D.
4EA7
AND 03H E6 03
Mask Register A to bits 1-0 of the year less 80: 0 for a leap year (1980, 1984).
4EA9
If the NZ FLAG is set (not a leap year), JUMP to 4EAFH.
4EAB
LD HL,5022H 21 22 50
Point Register Pair HL to 5022H, the days of February in the table at 5020H.
4EAE
INC (HL) 34
Increment the days of February at Register Pair HL (5022H): 28 becomes 29.
4EAF
LD A,E 7B
Copy Register E (the day and year byte) into Register A.
4EB0
RRCA 0F
Rotate Register A (the day and year byte) right, the first of three.
4EB1
RRCA 0F
Rotate Register A right, the second of three.
4EB2
RRCA 0F
Rotate Register A right, the third: the day is in bits 4-0.
4EB3
AND 1FH E6 1F
Mask Register A to bits 4-0: the day of the month.
4EB5
LD (4045H),A 32 45 40
Store Register A (the day) to 4045H, the day of the date.
4EB8
LD A,(4307H) 3A 07 43
Fetch the day and year byte from 4307H into Register A again.
4EBB
AND 07H E6 07
Mask Register A to bits 2-0: the year less 80, 0-7.
4EBD
LD E,A 5F
Copy Register A (the year less 80) into Register E.
4EBE
ADD A,50H C6 50
Add 50H (80) to Register A (the year less 80): the year, 80-87.
4EC0
LD (4044H),A 32 44 40
Store Register A (the year) to 4044H, the year of the date.
4EC3
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, the count of days for the day of the week. 4EC3H-4ECEH is the patch SYS0D.
4EC6
LD A,E 7B
Copy Register E (the year less 80) into Register A.
4EC7
ADD A,03H C6 03
Add 03H to Register A (the year less 80), so the division below counts 1980 for the years after it.
4EC9
RRCA 0F
Rotate Register A (the year less 80 plus 3) right.
4ECA
RRCA 0F
Rotate Register A right: (year less 80 plus 3) divided by 4 in bits 1-0.
4ECB
AND 03H E6 03
Mask Register A to bits 1-0: the leap days of the years since 1980 before this one.
4ECD
ADD A,E 83
Add Register E (the year less 80: each year moves the day of the week on by one) to Register A.
4ECE
LD E,A 5F
Copy Register A (the years plus the leap days) into Register E.
4ECF
LD A,(4045H) 3A 45 40
Fetch the day of the month from 4045H into Register A.
4ED2
ADD A,E 83
Add Register E (the years plus the leap days) to Register A (the day).
4ED3
LD E,A 5F
Copy Register A (the day plus the years and leap days) into Register E.
4ED4
LD D,00H 16 00
Load Register D with 00H: Register Pair DE = the sum in Register E.
4ED6
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = the day of the month plus the years and leap days.
4ED7
LD DE,5020H 11 20 50
Point Register Pair DE to 5020H, the table of the days of the months, starting with 00H.
4EDA
LD A,(DE) 1A
Fetch the days of a month from Register Pair DE into Register A.
4EDB
INC DE 13
Increment Register Pair DE to the next month.
4EDC
ADD A,L 85
Add Register L (the low byte of the count of days) to Register A (the days of the month).
4EDD
LD L,A 6F
Copy Register A (the new low byte) into Register L.
4EDE
ADC A,H 8C
Add Register H and the carry to Register A, the first step of carrying into the high byte.
4EDF
SUB L 95
SUBtract Register L from Register A: Register A = Register H plus the carry.
4EE0
LD H,A 67
Copy Register A into Register H: Register Pair HL has the days of the month added.
4EE1
Decrement Register B (the month) and JUMP to 4EDAH while it is not zero: the days of all the months before this one are added (the first table entry is 00H).
4EE3
LD BC,0007H 01 07 00
Load Register Pair BC with 0007H, the days of a week.
4EE6
XOR A AF
Set Register A to 00H and clear the CARRY FLAG (XOR A) for the subtractions below.
4EE7
SBC HL,BC ED 42
SUBtract Register Pair BC (7) and the carry from Register Pair HL.
4EE9
If the NC FLAG is set (not yet below 0), JUMP back to 4EE7H.
4EEB
LD A,L 7D
Copy Register L (the remainder less 7) into Register A.
4EEC
ADD A,08H C6 08
Add 08H to Register A: the remainder plus 1, from 1 (Monday) to 7 (Sunday). 1 January 1980 gives 2, Tuesday.
4EEE
LD B,A 47
Copy Register A (the day of the week) into Register B, the number of the text at 502CH.
4EEF
LD HL,3ED7H 21 D7 3E
Load Register Pair HL with 3ED7H, screen line 11, column 23.
4EF2
LD (4020H),HL 22 20 40
Store Register Pair HL (3ED7H) to 4020H, the cursor of the DO device.
4EF5
LD HL,502CH 21 2C 50
Point Register Pair HL to 502CH, the names of the days.
4EF8
GOSUB to 4F36H to display text number Register B of the list at Register Pair HL: the day of the week.
4EFB
LD A,(4046H) 3A 46 40
Fetch the month from 4046H into Register A, for the month's name.
4EFE
LD B,A 47
Copy Register A (the month) into Register B, the number of the text at 5065H.
4EFF
LD HL,3F14H 21 14 3F
Load Register Pair HL with 3F14H, screen line 12, column 20.
4F02
LD (4020H),HL 22 20 40
Store Register Pair HL (3F14H) to 4020H, the cursor of the DO device.
4F05
LD HL,5065H 21 65 50
Point Register Pair HL to 5065H, the names of the months.
4F08
GOSUB to 4F36H to display text number Register B of the list at Register Pair HL: the month.
4F0B
LD A,(4045H) 3A 45 40
Fetch the day of the month from 4045H into Register A.
4F0E
LD B,FFH 06 FF
Load Register B with FFH, so the first INC gives 0.
4F10
INC B 04
Increment Register B, the tens digit of the day of the month.
4F11
SUB 0AH D6 0A
SUBtract 0AH (10) from Register A, the day of the month.
4F13
If the NC FLAG is set (10 or more were left), JUMP back to 4F10H.
4F15
PUSH AF F5
Save Register Pair AF (Register A the units less 10) to the stack.
4F16
LD A,B 78
Copy Register B (the tens of the day) into Register A.
4F17
ADD A,30H C6 30
Add 30H to Register A (the tens of the day): the tens digit in ASCII.
4F19
CP 30H FE 30
Compare Register A (the tens digit) against 30H, the digit 0.
4F1B
If the NZ FLAG is set (the tens digit is not 0), GOSUB to the ROM's 0033H to display Register A.
4F1E
POP AF F1
Restore Register Pair AF (the units less 10) from the stack.
4F1F
ADD A,3AH C6 3A
Add 3AH to Register A: the units digit (plus 10 and the 30H of the digit 0).
4F21
GOSUB to the ROM's 0033H to display Register A (the units digit).
4F24
LD HL,500EH 21 0E 50
Point Register Pair HL to 500EH, the text , 198 (the year's last digit follows).
4F27
GOSUB to 4467H to display the text at Register Pair HL.
4F2A
LD A,(4307H) 3A 07 43
Fetch the day and year byte from 4307H into Register A.
4F2D
AND 07H E6 07
Mask Register A to bits 2-0: the year less 80, 0-7 (the operand 07H is the patch SYS0D at 4F2EH).
4F2F
ADD A,30H C6 30
Add 30H to Register A: the last digit of the year.
4F31
GOSUB to the ROM's 0033H to display Register A (the last digit of 1980-1987).
4F34
JUMP to 4F6BH to read the system information sector.
4F36
DEC B 05
Decrement Register B, the number of the text wanted.
4F37
If the Z FLAG is set (Register Pair HL is at the text wanted), JUMP to 4467H to display it.
4F3A
LD A,(HL) 7E
Fetch a character of the list from Register Pair HL into Register A.
4F3B
INC HL 23
Increment Register Pair HL to the next character.
4F3C
CP 03H FE 03
Compare Register A against 03H, the end of a text.
4F3E
If the NZ FLAG is set (not the end), JUMP back to 4F3AH.
4F40
JUMP back to 4F36H: Register Pair HL is at the next text.
4F42
GOSUB to 4777H to read cylinder Register D, sector Register E of drive Register C into the buffer at Register Pair HL. The result of the read is not tested: the check below finds a sector that was not read.
4F45
LD L,C0H 2E C0
Load Register L with C0H: Register Pair HL = 42C0H, the 64 checked bytes of the system information sector.
4F47
LD A,C 79
Copy Register C (the drive, 00H) into Register A.
4F48
DEC A 3D
Decrement Register A (the drive, 00H): FFH, the value the check starts from.
4F49
XOR (HL) AE
Exclusive OR Register A with the byte at Register Pair HL.
4F4A
INC L 2C
Increment Register L to the next of the 64 checked bytes.
4F4B
If the NZ FLAG is set (Register L has not wrapped to 00H after 42FFH), JUMP back to 4F49H.
4F4D
OR A B7
OR Register A with itself: the Z FLAG is set when the 64 bytes XOR to FFH.
4F4E
RET Z C8
If the Z FLAG is set (the check is passed), RETURN to 4F76H. Otherwise fall into 4F4FH.
4F4F
XOR A AF
Set Register A to 00H (XOR A). No date was kept (from 4EA0H), or the system information sector failed the check (from 4F4EH).
4F50
LD (4306H),A 32 06 43
Store Register A (00H) to 4306H, the month kept.
4F53
LD (4307H),A 32 07 43
Store Register A (00H) to 4307H, the day and year kept.
4F56
LD (4044H),A 32 44 40
Store Register A (00H) to 4044H, the year of the date.
4F59
LD (4045H),A 32 45 40
Store Register A (00H) to 4045H, the day of the date.
4F5C
LD (4046H),A 32 46 40
Store Register A (00H) to 4046H, the month of the date.
4F5F
LD HL,3F17H 21 17 3F
Load Register Pair HL with 3F17H, screen line 12, column 23.
4F62
LD (4020H),HL 22 20 40
Store Register Pair HL (3F17H) to 4020H, the cursor of the DO device.
4F65
LD HL,5014H 21 14 50
Point Register Pair HL to 5014H, the text --NO DATE--.
4F68
GOSUB to 4467H to display the text at Register Pair HL.
4F6B
LD C,00H 0E 00
Load Register C with 00H, drive 0, for the read of the system information sector.
4F6D
LD DE,0002H 11 02 00
Load Register Pair DE with 0002H: cylinder 0, sector 2, the system information sector.
4F70
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the buffer the sector is read into.
4F73
GOSUB to 4F42H to read the sector and check its 64 bytes; it comes back only when they pass (otherwise 4F4FH-4F73H repeat without end).
4F76
LD A,(4201H) 3A 01 42
Fetch the configuration flag, byte 01H of the system information sector, from 4201H into Register A (00H or C9H).
4F79
LD (4FE1H),A 32 E1 4F
Store Register A to 4FE1H: 00H (NOP) makes the code at 4FE2H load CONFIG/SYS, C9H (RET) skips it.
4F7C
LD HL,42C0H 21 C0 42
Point Register Pair HL to 42C0H, the serial number (bytes C0H-C7H of the sector).
4F7F
LD DE,3CDEH 11 DE 3C
Point Register Pair DE to 3CDEH, screen line 3 after VTOS SERIAL #.
4F82
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H, the eight characters of the serial number.
4F85
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL (42C0H) to Register Pair DE (3CDEH), counting up (LDIR).
4F87
LD HL,422AH 21 2A 42
Point Register Pair HL to 422AH, the drive code tables of drives 1-7 in the sector (bytes 2AH-6FH).
4F8A
LD DE,470AH 11 0A 47
Point Register Pair DE to 470AH, the drive code table of drive 1.
4F8D
LD BC,0046H 01 46 00
Load Register Pair BC with 0046H, 70 bytes: seven tables of 10.
4F90
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL (422AH) to Register Pair DE (470AH), counting up (LDIR).
4F92
LD DE,45C7H 11 C7 45
Point Register Pair DE to 45C7H, the clock's task control block.
4F95
LD A,07H 3E 07
Load Register A with 07H, task slot 7 (run 5 times a second).
4F97
GOSUB to 4410H to install the task at Register Pair DE in slot Register A: the clock runs from now on.
4F9A
LD C,00H 0E 00
Load Register C with 00H, drive 0, for the read of the allocation table.
4F9C
LD DE,1100H 11 00 11
Load Register Pair DE with 1100H: cylinder 11H (17), sector 0, the allocation table of the directory cylinder.
4F9F
LD HL,4200H 21 00 42
Point Register Pair HL to 4200H, the buffer the sector is read into.
4FA2
GOSUB to 4B45H to read the directory sector Register D, Register E of drive Register C (with the directory cylinder taken from the boot sector when cylinder 17 is not the directory).
4FA5
If the NZ FLAG is set (the allocation table could not be read), JUMP to 4409H to display the error.
4FA8
LD HL,42E0H 21 E0 42
Point Register Pair HL to 42E0H, the AUTO command (bytes E0H-FFH of the allocation table).
4FAB
LD A,(HL) 7E
Fetch the first character of the AUTO command from Register Pair HL into Register A.
4FAC
CP 2AH FE 2A
Compare Register A against 2AH, an asterisk: a command that cannot be stopped by BREAK.
4FAE
If the NZ FLAG is set (no asterisk), JUMP to 4FC0H to test the keys held.
4FB0
INC HL 23
Increment Register Pair HL past the asterisk.
4FB1
LD A,(430FH) 3A 0F 43
Fetch the system flags from 430FH into Register A.
4FB4
OR 10H F6 10
OR Register A with 10H: bit 4, BREAK is ignored by the interrupt routine (4561H-4566H).
4FB6
LD (430FH),A 32 0F 43
Store Register A to the system flags at 430FH.
4FB9
LD A,C8H 3E C8
Load Register A with C8H, the opcode RET Z, for 4C2DH.
4FBB
LD (4C2DH),A 32 2D 4C
Store Register A (C8H) to 4C2DH: a BREAK key code from the ROM (request 01H) becomes 00H, no key.
4FBE
JUMP to 4FCDH to copy the command: the keys held are not tested.
4FC0
LD A,(3841H) 3A 41 38
Fetch rows 0 and 6 of the keyboard together from 3841H into Register A. 4FC0H-4FCCH is the patch SYS0D.
4FC3
BIT 4,A CB 67
Test bit 4 of Register A: the D key (row 0) or the down arrow (row 6).
4FC5
If the NZ FLAG is set, JUMP to 440DH: the DEBUG monitor instead of the AUTO command and CONFIG/SYS.
4FC8
BIT 0,A CB 47
Test bit 0 of Register A: the @ key (row 0) or ENTER (row 6).
4FCA
If the NZ FLAG is set, GOSUB to 50D0H, which turns JP Z,4400H at 5005H into JP 4400H: the AUTO command is not run.
4FCD
LD DE,4318H 11 18 43
Point Register Pair DE to 4318H, the command line buffer.
4FD0
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H, the 32 bytes of the AUTO command.
4FD3
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL (42E0H or 42E1H) to Register Pair DE (4318H), counting up (LDIR).
4FD5
LD HL,4FEEH 21 EE 4F
Point Register Pair HL to 4FEEH, the last part of the reset.
4FD8
LD DE,405DH 11 5D 40
Point Register Pair DE to 405DH, where it is to run.
4FDB
PUSH DE D5
Save Register Pair DE (405DH) to the stack: the RET at 4FE1H, or the end of the load of CONFIG/SYS, goes there.
4FDC
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H, the 32 bytes of 4FEEH-500DH.
4FDF
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL (4FEEH) to Register Pair DE (405DH), counting up (LDIR).
4FE1
RET C9
RETURN to 405DH. The byte is C9H in the file; 4F79H stores byte 01H of the system information sector here, and 00H (NOP) lets the code below load CONFIG/SYS.
4FE2
LD A,(3860H) 3A 60 38
Fetch rows 5 and 6 of the keyboard together from 3860H into Register A.
4FE5
BIT 1,A CB 4F
Test bit 1 of Register A: CLEAR (row 6) or the 9 key (row 5).
4FE7
LD DE,4338H 11 38 43
Point Register Pair DE to 4338H, the file specification CONFIG/SYS.CCC:0. LD does not change the flags.
4FEA
If the Z FLAG is set (neither key held), JUMP to 4430H to load CONFIG/SYS; its RET goes to 405DH.
4FED
RET C9
RETURN to 405DH without loading CONFIG/SYS: CLEAR (or 9) is held.
4FEEH - Last Part of the Reset (Runs at 405DH)
Copied to 405DH-407CH by 4FD5H-4FDFH and entered there by the RET at 4FE1H (or after CONFIG/SYS is loaded), since CONFIG/SYS and the overlays load over 4E00H-50FFH. The rows show the file addresses; each comment gives the address the instruction runs at. The only jump inside the part is relative (4FF3H), the others leave it.
4FEE
LD A,(430FH) 3A 0F 43
Runs at 405DH. Fetch the system flags from 430FH into Register A (CONFIG/SYS can have set bit 3).
4FF1
BIT 3,A CB 5F
Runs at 4060H. Test bit 3 of Register A: the fast clock.
4FF3
Runs at 4062H. If the Z FLAG is set (no fast clock), JUMP to 4068H (file 4FF9H).
4FF5
LD A,01H 3E 01
Runs at 4064H. Load Register A with 01H, the value that selects the faster clock.
4FF7
OUT (FEH),A D3 FE
Runs at 4066H. Send Register A (01H) to port FEH, the speed control: the faster clock is switched on.
4FF9
LD HL,3F40H 21 40 3F
Runs at 4068H. Load Register Pair HL with 3F40H, screen line 13, column 0.
4FFC
LD (4020H),HL 22 20 40
Runs at 406BH. Store Register Pair HL (3F40H) to 4020H, the cursor of the DO device.
4FFF
LD HL,4318H 21 18 43
Runs at 406EH. Point Register Pair HL to 4318H, the AUTO command copied into the command line buffer.
5002
LD A,(HL) 7E
Runs at 4071H. Fetch the first character of the command from Register Pair HL into Register A.
5003
CP 0DH FE 0D
Runs at 4072H. Compare Register A against 0DH: an empty command.
5005
Runs at 4074H. If the Z FLAG is set (no AUTO command), JUMP to 4400H, VTOS READY. With @ or ENTER held, 50D0H has made the opcode C3H, an unconditional JP 4400H.
5008
Runs at 4077H. GOSUB to 4467H to display the AUTO command at Register Pair HL.
500B
Runs at 407AH. JUMP to 4405H to execute the command at Register Pair HL (4318H), request B3H.
500EH - Texts and Tables of the Reset
The texts the reset displays and the table of the days of the months used for the day of the week. Each text ends with 03H, which 44E2H stops at and 4F3CH counts.
500E-5013
DEFM ", 198",03H 2C 20 31 39 38 03
The text after the day of the month, displayed at 4F27H: a comma, a space and 198; 4F31H then displays the last digit of the year.
5014-501F
DEFM "--NO DATE--",03H 2D 2D 4E 4F 20 44 41 54 45 2D 2D 03
Displayed at screen line 12, column 23 (4F5FH-4F68H) when no date was kept across the reset, or each time the system information sector fails its check.
5020-502B
DEFB 00H,1FH,1CH,1FH,1EH,1FH,1EH,1FH,1FH,1EH,1FH,1EH 00 1F 1C 1F 1E 1F 1E 1F 1F 1E 1F 1E
The days of the months, added for the day of the week (4ED7H-4EE1H): 00H first (nothing before January), then 31 January, 28 February (5022H, made 29 in a leap year at 4EAEH), 31, 30, 31, 30, 31, 31, 30, 31 and 30 for March to November. December is never needed.
502C-5032
DEFM "MONDAY",03H 4D 4F 4E 44 41 59 03
Day of the week 1 of the list at 502CH, displayed at screen line 11, column 23 when 4EEEH gives Register B = 1 (4EF5H-4EF8H).
5033-503A
DEFM "TUESDAY",03H 54 55 45 53 44 41 59 03
Day of the week 2 of the list at 502CH, displayed at screen line 11, column 23 when 4EEEH gives Register B = 2 (4EF5H-4EF8H).
503B-5044
DEFM "WEDNESDAY",03H 57 45 44 4E 45 53 44 41 59 03
Day of the week 3 of the list at 502CH, displayed at screen line 11, column 23 when 4EEEH gives Register B = 3 (4EF5H-4EF8H).
5045-504D
DEFM "THURSDAY",03H 54 48 55 52 53 44 41 59 03
Day of the week 4 of the list at 502CH, displayed at screen line 11, column 23 when 4EEEH gives Register B = 4 (4EF5H-4EF8H).
504E-5054
DEFM "FRIDAY",03H 46 52 49 44 41 59 03
Day of the week 5 of the list at 502CH, displayed at screen line 11, column 23 when 4EEEH gives Register B = 5 (4EF5H-4EF8H).
5055-505D
DEFM "SATURDAY",03H 53 41 54 55 52 44 41 59 03
Day of the week 6 of the list at 502CH, displayed at screen line 11, column 23 when 4EEEH gives Register B = 6 (4EF5H-4EF8H).
505E-5064
DEFM "SUNDAY",03H 53 55 4E 44 41 59 03
Day of the week 7 of the list at 502CH, displayed at screen line 11, column 23 when 4EEEH gives Register B = 7 (4EF5H-4EF8H).
5065H - Names of the Months
Twelve texts, each ended by 03H; 4F05H-4F08H displays the one the month gives at screen line 12, column 20. The spaces after each name keep the date after it in the same place.
5065-506D
DEFM "JANUARY ",03H 4A 41 4E 55 41 52 59 20 03
Month 1 of the list at 5065H, displayed when the month at 4046H is 1 (Register B at 4EFEH): the name and 1 space.
506E-5077
DEFM "FEBRUARY ",03H 46 45 42 52 55 41 52 59 20 03
Month 2 of the list at 5065H, displayed when the month at 4046H is 2 (Register B at 4EFEH): the name and 1 space.
5078-507E
DEFM "MARCH ",03H 4D 41 52 43 48 20 03
Month 3 of the list at 5065H, displayed when the month at 4046H is 3 (Register B at 4EFEH): the name and 1 space.
507F-5085
DEFM "APRIL ",03H 41 50 52 49 4C 20 03
Month 4 of the list at 5065H, displayed when the month at 4046H is 4 (Register B at 4EFEH): the name and 1 space.
5086-508B
DEFM "MAY ",03H 4D 41 59 20 20 03
Month 5 of the list at 5065H, displayed when the month at 4046H is 5 (Register B at 4EFEH): the name and 2 spaces.
508C-5092
DEFM "JUNE ",03H 4A 55 4E 45 20 20 03
Month 6 of the list at 5065H, displayed when the month at 4046H is 6 (Register B at 4EFEH): the name and 2 spaces.
5093-5099
DEFM "JULY ",03H 4A 55 4C 59 20 20 03
Month 7 of the list at 5065H, displayed when the month at 4046H is 7 (Register B at 4EFEH): the name and 2 spaces.
509A-50A1
DEFM "AUGUST ",03H 41 55 47 55 53 54 20 03
Month 8 of the list at 5065H, displayed when the month at 4046H is 8 (Register B at 4EFEH): the name and 1 space.
50A2-50AC
DEFM "SEPTEMBER ",03H 53 45 50 54 45 4D 42 45 52 20 03
Month 9 of the list at 5065H, displayed when the month at 4046H is 9 (Register B at 4EFEH): the name and 1 space.
50AD-50B5
DEFM "OCTOBER ",03H 4F 43 54 4F 42 45 52 20 03
Month 10 of the list at 5065H, displayed when the month at 4046H is 10 (Register B at 4EFEH): the name and 1 space.
50B6-50BF
DEFM "NOVEMBER ",03H 4E 4F 56 45 4D 42 45 52 20 03
Month 11 of the list at 5065H, displayed when the month at 4046H is 11 (Register B at 4EFEH): the name and 1 space.
50C0-50C9
DEFM "DECEMBER ",03H 44 45 43 45 4D 42 45 52 20 03
Month 12 of the list at 5065H, displayed when the month at 4046H is 12 (Register B at 4EFEH): the name and 1 space.
50CA-50CF
DEFS 6
Not in the file, and not used by SYS0/SYS: the bytes between the names of the months and the patch at 50D0H.
50D0H - Patch SYS0D: Do Not Run the AUTO Command
Called from 4FCAH when the @ key or ENTER is held during the boot. Its own record in the file (the patch SYS0D) put it here.
50D0
LD A,C3H 3E C3
Load Register A with C3H, the opcode JP, for 5005H.
50D2
LD (5005H),A 32 05 50
Store Register A (C3H) to 5005H: JP Z,4400H becomes JP 4400H, so the code copied to 405DH goes to VTOS READY instead of running the AUTO command.
50D5
RET C9
RETURN to 4FCDH; the AUTO command is still copied to 4318H, but not run.
50D6-50DF
DEFS 10
Not in the file, and not used by SYS0/SYS: the bytes between the two patches.
50E0H - Key Repeat Routine (Runs at 41E5H)
Copied to 41E5H-41FFH by the reset (4E36H-4E3FH, the patch SYS0D) and entered there by JP M,41E5H at 43B1H when no row of the keyboard changed, with Index Register IX at the KI block (4015H). While a key is held (+03H, 4018H), it repeats it when the tick counter 4040H is at its repeat tick (+04H, 4019H) or up to 29 ticks past it, and sets the next repeat 3 ticks on. The rows show the file addresses; each comment gives the address the instruction runs at.
50E0
LD A,(IX+03H) DD 7E 03
Runs at 41E5H. Fetch the key held from byte +03H of the KI block at Index Register IX (4018H) into Register A.
50E3
OR A B7
Runs at 41E8H. OR Register A (the key held) with itself: the Z FLAG is set when no key is held.
50E4
RET Z C8
Runs at 41E9H. If the Z FLAG is set (no key held), RETURN with Register A = 00H: no key.
50E5
LD A,(4040H) 3A 40 40
Runs at 41EAH. Fetch the tick counter from 4040H into Register A.
50E8
SUB (IX+04H) DD 96 04
Runs at 41EDH. SUBtract the repeat tick, byte +04H of the KI block at Index Register IX (4019H), from Register A: the ticks past the repeat tick.
50EB
Runs at 41F0H. If the Z FLAG is set (the repeat tick is now), JUMP to 41F8H (file 50F3H) to repeat the key.
50ED
SUB 1EH D6 1E
Runs at 41F2H. SUBtract 1EH (30) from Register A.
50EF
Runs at 41F4H. If the C FLAG is set (1-29 ticks past the repeat tick), JUMP to 41F8H (file 50F3H) to repeat the key.
50F1
XOR A AF
Runs at 41F6H. Set Register A to 00H and the Z FLAG (XOR A): the repeat tick has not come, so no key.
50F2
RET C9
Runs at 41F7H. RETURN with Register A = 00H and the Z FLAG: no key.
50F3
LD A,(4040H) 3A 40 40
Runs at 41F8H. Fetch the tick counter from 4040H into Register A.
50F6
ADD A,03H C6 03
Runs at 41FBH. Add 03H to Register A: the next repeat 3 ticks on.
50F8
Runs at 41FDH. JUMP to 4C11H to store Register A as the repeat tick (+04H of the KI block) and return the key held.