5372H - Program Variables
The first ten bytes of the file are the program's variables. They load with the same values that the start-up code at 537CH stores into them, so the program also works when it is restarted from 5889H.
5372
DEFB 01H 01
No-Appendage Flag. 01H = no appendage is to be attached (no new load base has been given, or the appendage was suppressed). 00H = an appendage will be attached. Set at 5381H and 55D7H-55E5H; tested at 5558H, 5597H and 563EH.
5373
DEFB 00H 00
Output Phase Flag. 00H while a source module is being read and set up; set to 01H at 56E6H once a destination is asked for. 5866H uses it to choose between ANOTHER DESTINATION FILE? and ANOTHER SOURCE FILE TO PROCESS?.
5374-5375
DEFW 5E9AH 9A 5E
Module Buffer Pointer. Address of the last byte stored in the module buffer. It starts at 5E9AH, so the first byte goes to 5E9BH. Advanced by 547BH.
5376-5377
DEFW FFFFH FF FF
Lowest Load Address of the object code records that load at 4000H or above. Starts at FFFFH. Updated by 54AFH.
5378-5379
DEFW 0000H 00 00
Highest Load Address: the last byte loaded by any object code record at 4000H or above. Starts at 0000H. Updated by 54C6H.
537A-537B
DEFW 0000H 00 00
Load Offset: the new load base minus the lowest load address (55C5H-55CCH), added to every load address that is moved. Starts at 0000H.
537CH - Program Entry Point and Start-Up
The transfer address of LMOFFSET/CMD. Also reached from 5889H when the operator asks for another source file. Sets the stack, resets every variable, clears the 64-byte appendage patch area and displays the title.
537C
LD SP,5E95H 31 95 5E
Set the Stack Pointer to 5E95H. The stack grows down from 5E94H; the six bytes at 5E95H-5E9AH hold the tape module name (5787H) and the module buffer starts at 5E9BH.
537F
LD A,01H 3E 01
Load Register A with 01H, the starting value of the No-Appendage Flag.
5381
LD (5372H),A 32 72 53
Store Register A (01H) into the No-Appendage Flag at 5372H: no new load base has been given yet.
5384
XOR A AF
Set Register A to 00H, used below to clear the Output Phase Flag and the patch area.
5385
LD (5373H),A 32 73 53
Store Register A (00H) into the Output Phase Flag at 5373H: the output file has not been started.
5388
LD HL,58C6H 21 C6 58
Point Register Pair HL to 58C6H, the 64-byte appendage patch area (not part of the file).
538B
LD B,40H 06 40
Load Register B with 40H, the 64 bytes of the appendage patch area to clear.
538D
LD (HL),A 77
Store Register A (00H) into the patch area byte at Register Pair HL.
538E
INC HL 23
Bump Register Pair HL to the next byte of the appendage patch area.
538F
DECrement Register B and LOOP back to 538DH until all 64 bytes of the patch area are zero.
5391
LD H,A 67
Copy Register A (00H) into Register H, the high byte of Register Pair HL.
5392
LD L,A 6F
Copy Register A (00H) into Register L, so Register Pair HL = 0000H.
5393
LD (5378H),HL 22 78 53
Store Register Pair HL (0000H) into the Highest Load Address at 5378H.
5396
LD (537AH),HL 22 7A 53
Store Register Pair HL (0000H) into the Load Offset at 537AH: no offset yet.
5399
DEC HL 2B
DECrement Register Pair HL from 0000H to FFFFH, the starting value of the lowest load address.
539A
LD (5376H),HL 22 76 53
Store Register Pair HL (FFFFH) into the Lowest Load Address at 5376H, so the first record is always lower.
539D
LD HL,5E9AH 21 9A 5E
Point Register Pair HL to 5E9AH, the byte before the module buffer.
53A0
LD (5374H),HL 22 74 53
Store Register Pair HL (5E9AH) as the Module Buffer Pointer at 5374H: the module buffer is empty.
53A3
GOSUB to 5D15H, which resets the appendage record length at 58C3H to 50H and returns Register Pair HL pointing to the title at 5A3EH.
53A6
GOSUB to the SYS0 routine at 4467H to display the title APPARAT LOAD MODULE OFFSET PROGRAM, VERSION 2.0 on a cleared screen.
53A9H - Ask for the Source: Disk or Tape
Repeats until the reply is exactly one character, D or T.
53A9
LD HL,5ACBH 21 CB 5A
Point Register Pair HL to the message SOURCE FROM DISK OR TAPE? (D OR T) at 5ACBH.
53AC
GOSUB to 5893H to display it and read a reply. Register B = the length of the reply, Register A = its first character.
53AF
DECrement Register B and LOOP back to 53A9H unless the reply was exactly one character long.
53B1
CP 44H FE 44
Compare Register A, the first character of the reply, against D (44H).
53B3
If it is D, JUMP to 54DCH to read the source from disk.
53B6
CP 54H FE 54
Compare Register A, the first character of the reply, against T (54H).
53B8
If it is not T either, JUMP back to 53A9H to ask again.
53BAH - Read a SYSTEM Tape: Find the Leader
The tape is read into the module buffer as load module records. Anything that is not part of a normal SYSTEM tape is kept in marker records (see Module Buffer Records), and a status character is shown in the top line of the screen: an asterisk at 3C3DH when reading starts (the ROM adds two more at 3C3EH-3C3FH when the sync byte is found), P at 3C3CH for bytes before the 55H header byte, I at 3C3DH for bytes between blocks, and C at 3C3EH for a bad checksum.
53BA
LD A,2AH 3E 2A
Load Register A with an asterisk (2AH), the ready sign for the tape.
53BC
LD (3C3DH),A 32 3D 3C
Store Register A (2AH) into video memory at 3C3DH, near the right-hand end of the top line of the screen: the program is ready for the tape.
53BF
GOSUB to 583AH. That address holds only a RET.
53C2
DI F3
Disable interrupts, because the ROM tape routines depend on exact timing loops.
53C3
GOSUB to the ROM routine at 0293H to turn on the cassette motor and find the leader and the A5H sync byte. When it finds the sync byte it puts two asterisks at 3C3EH-3C3FH, so the screen now shows three asterisks.
53C6
LD A,FFH 3E FF
Load Register A with FFH, the marker for bytes before the header.
53C8
GOSUB to 5457H to start an FFH record in the module buffer. Register Pair HL points to its two-byte count and Register Pair BC = 0000H.
Read bytes until the 55H that starts a SYSTEM tape. Every other byte is kept in the FFH record and counted.
53CB
GOSUB to 583BH to check the up-arrow key, which abandons the tape read.
53CE
GOSUB to the ROM routine at 0235H to read a byte from the tape into Register A.
53D1
CP 55H FE 55
Compare Register A, the byte read from the tape, against 55H, the byte that starts a SYSTEM tape header.
53D3
If Register A is 55H (the Z FLAG is set), JUMP to 53DFH to read the name.
53D5
Otherwise GOSUB to 5492H to store the byte in the buffer and add one to the count of the FFH record.
53D8
LD A,50H 3E 50
Load Register A with P (50H), the sign for bytes found before the header.
53DA
LD (3C3CH),A 32 3C 3C
Store Register A (50H) into video memory at 3C3CH: extra bytes were found before the header.
53DD
LOOP back to 53CBH to read the next byte from the tape.
53DFH - Read a SYSTEM Tape: the Name
After the 55H, the bytes up to the first 3CH (object code block) or 78H (entry point) are kept in an FEH record. On a normal tape these are the six bytes of the module name.
53DF
LD A,FEH 3E FE
Load Register A with FEH, the marker for bytes after the header.
53E1
GOSUB to 5457H to start an FEH record. Register Pair HL points to its count, Register Pair BC = 0000H.
53E4
GOSUB to 583BH to check the up-arrow key, which abandons the tape read.
53E7
GOSUB to the ROM routine at 0235H to read a byte from the tape.
53EA
CP 78H FE 78
Compare Register A, the byte read from the tape, against 78H, the byte that starts the entry point block.
53EC
If it is 78H, JUMP to 54CAH to read the entry point and finish.
53EF
CP 3CH FE 3C
Compare Register A, the byte read from the tape, against 3CH, the byte that starts an object code block.
53F1
If it is 3CH, JUMP to 53F8H to read the block.
53F3
Otherwise GOSUB to 5492H to store the byte and count it in the current marker record (FEH, or FDH when reached from 543FH).
53F6
LOOP back to 53E4H to read the next byte from the tape.
53F8H - Read a SYSTEM Tape: Object Code Block
A tape block is 3CH, a count byte (00H = 256), the two-byte load address, the data and a checksum. It is stored in the disk load module format instead: 01H, a length byte equal to the count plus 2, the load address and the data. The checksum (the sum of the address bytes and the data) is checked but not stored.
53F8
LD A,01H 3E 01
Load Register A with 01H, the disk record type for object code.
53FA
GOSUB to 547BH to store it in the module buffer.
53FD
GOSUB to the ROM routine at 0235H to read the count byte from the tape.
5400
LD B,A 47
Copy Register A, the tape count byte, into Register B as the number of data bytes to read.
5401
ADD A,02H C6 02
Add 02H to Register A for the two address bytes, giving the disk length byte (a count of 00H, 256 bytes, gives 02H, which also means 256 data bytes on disk).
5403
GOSUB to 547BH to store Register A, the disk length byte, in the module buffer.
5406
GOSUB to 5467H to read the two-byte load address from the tape into HL, storing both bytes. Register A = H on return.
5409
ADD A,L 85
Add Register L, the low byte of the load address, to Register A, the high byte.
540A
LD C,A 4F
Copy Register A into Register C, which starts the checksum with H + L.
540B
GOSUB to 549BH to check the load address and update the lowest and highest load addresses.
540E
GOSUB to 5478H to read a data byte from the tape and store it.
5411
ADD A,C 81
Add Register C, the checksum so far, to Register A, the data byte just read.
5412
LD C,A 4F
Copy Register A into Register C as the new checksum.
5413
DECrement Register B and LOOP back to 540EH until all the data bytes of the block are read.
5415
GOSUB to the ROM routine at 0235H to read the checksum byte from the tape.
5418
CP C B9
Compare Register A, the checksum read from the tape, with Register C, the checksum computed.
5419
If they differ (the NZ FLAG is set), JUMP to 5442H to record a checksum error.
541B
LD A,(3C3FH) 3A 3F 3C
Fetch the character at 3C3FH, the last of the three asterisks, into Register A.
541E
XOR 0AH EE 0A
Exclusive OR Register A with 0AH, switching it between an asterisk (2AH) and a space (20H).
5420
LD (3C3FH),A 32 3F 3C
Store Register A back into video memory at 3C3FH, so the asterisk blinks once for each good block.
5423
GOSUB to 583BH to check the up-arrow key. Also reached from 5455H after a checksum error.
5426
GOSUB to the ROM routine at 0235H to read the next byte from the tape.
5429
CP 3CH FE 3C
Compare Register A, the byte read from the tape, against 3CH (another object code block).
542B
If it is 3CH, JUMP back to 53F8H to read the block.
542E
CP 78H FE 78
Compare Register A, the byte read from the tape, against 78H (the entry point block).
5430
If Register A is 78H (the Z FLAG is set), JUMP to 54CAH to read the entry point.
Any other byte between blocks is extraneous. Start an FDH record for it and go on reading as at 53F3H.
5433
PUSH AF F5
Save Register Pair AF, holding the extraneous byte in Register A, on the stack.
5434
LD A,49H 3E 49
Load Register A with I (49H), the sign for bytes found between blocks.
5436
LD (3C3DH),A 32 3D 3C
Store Register A (49H) into video memory at 3C3DH: extra bytes were found between blocks.
5439
LD A,FDH 3E FD
Load Register A with FDH, the marker for bytes between blocks.
543B
GOSUB to 5457H to start an FDH record. Register Pair HL points to its count, Register Pair BC = 0000H.
543E
POP AF F1
Restore Register Pair AF from the stack, putting the extraneous byte back in Register A.
543F
JUMP to 53F3H to store and count it, and keep reading until a 3CH or 78H.
5442H - Checksum Error
The block's data is already in the buffer. An FCH record of three bytes follows it: FCH, the checksum read from the tape and the checksum computed. It has no count, and 5733H does not accept it later (see Module Buffer Records).
5442
PUSH AF F5
Save Register Pair AF, holding the checksum read from the tape in Register A, on the stack.
5443
LD A,FCH 3E FC
Load Register A with FCH, the marker for a checksum error.
5445
GOSUB to 547BH to store Register A (FCH) in the module buffer.
5448
POP AF F1
Restore Register Pair AF from the stack, putting the checksum read from the tape back in Register A.
5449
GOSUB to 547BH to store Register A, the checksum read from the tape, in the module buffer.
544C
LD A,C 79
Load Register A with the checksum computed in Register C.
544D
GOSUB to 547BH to store Register A, the checksum computed, in the module buffer.
5450
LD A,43H 3E 43
Load Register A with C (43H), the sign for a checksum error.
5452
LD (3C3EH),A 32 3E 3C
Store Register A (43H) into video memory at 3C3EH: a checksum error was found.
5455
JUMP back to 5423H to read the next block from the tape.
5457H - Start a Marker Record
Stores the marker type in Register A and a two-byte count of zero after it. Returns Register Pair HL pointing to the count and Register Pair BC = 0000H, ready for 5492H.
5457
GOSUB to 547BH to store Register A, the marker type, in the module buffer.
545A
LD HL,(5374H) 2A 74 53
Fetch the Module Buffer Pointer at 5374H into Register Pair HL: the address of the marker just stored.
545D
INC HL 23
Bump Register Pair HL to where the count will go.
545E
XOR A AF
Set Register A to 00H for the two bytes of the count.
545F
LD B,A 47
Copy Register A (00H) into Register B, the high byte of the count in Register Pair BC.
5460
LD C,A 4F
Copy Register A (00H) into Register C, so the count in Register Pair BC is 0000H.
5461
GOSUB to 547BH to store the low byte of the count.
5464
JUMP to 547BH to store the high byte and return.
5467H - Read a Two-Byte Address From the Tape
Reads the low byte and then the high byte into HL, storing both in the module buffer. Returns Register A = H.
5467
GOSUB to 5478H to read and store the low byte.
546A
LD L,A 6F
Copy Register A, the low byte of the address, into Register L.
546B
GOSUB to 5478H to read and store the high byte.
546E
LD H,A 67
Copy Register A, the high byte of the address, into Register H.
546F
RET C9
RETurn with Register Pair HL = the address and Register A = Register H.
5470H - Copy Bytes Into the Module Buffer
Copies Register B bytes from Register Pair HL (00H = 256) to the end of the module buffer. Used to add the appendage (56CDH-56E3H). Returns Register Pair HL pointing past the last byte copied.
5470
LD A,(HL) 7E
Fetch the byte at Register Pair HL into Register A.
5471
INC HL 23
Bump Register Pair HL, the source pointer, to the next byte.
5472
GOSUB to 547BH to store the byte in the module buffer.
5475
LOOP back to 5470H until Register B bytes are copied.
5477
RET C9
RETurn with Register Pair HL pointing past the last byte copied.
5478H - Store a Byte in the Module Buffer
5478H reads a byte from the tape first. 547BH stores the byte in Register A after the last byte in the module buffer. If the buffer has reached the top of memory (the DOS high memory address at 4049H), it stops with INSUFFICIENT RAM MEMORY. All registers are preserved.
5478
GOSUB to the ROM routine at 0235H to read a byte from the tape, then fall into 547BH.
547B
PUSH HL E5
Save Register Pair HL on the stack while the byte is stored.
547C
PUSH DE D5
Save Register Pair DE on the stack while the byte is stored.
547D
LD HL,(5374H) 2A 74 53
Fetch the Module Buffer Pointer at 5374H into Register Pair HL: the address of the last byte stored.
5480
LD DE,(4049H) ED 5B 49 40
Fetch the top of usable memory at 4049H into Register Pair DE.
5484
PUSH AF F5
Save Register Pair AF, holding the byte to store in Register A, on the stack.
5485
RST 18H DF
Compare Register Pair HL with Register Pair DE (RST 18H): the CARRY FLAG is set if Register Pair HL is lower.
5486
If the buffer pointer has reached the top of memory, JUMP to 585CH to report INSUFFICIENT RAM MEMORY.
5489
INC HL 23
Bump Register Pair HL to the next free byte of the module buffer.
548A
POP AF F1
Restore Register Pair AF from the stack, putting the byte to store back in Register A.
548B
LD (HL),A 77
Store Register A into the module buffer at Register Pair HL.
548C
LD (5374H),HL 22 74 53
Store Register Pair HL as the new Module Buffer Pointer at 5374H.
548F
POP DE D1
Restore Register Pair DE, the caller's value, from the stack.
5490
POP HL E1
Restore Register Pair HL, the caller's value, from the stack.
5491
RET C9
RETurn with Register A and the flags unchanged.
5492H - Store a Byte and Count It
Stores Register A in the module buffer, adds one to the count in Register Pair BC and writes the count into the current marker record at Register Pair HL (set up by 5457H).
5492
GOSUB to 547BH to store Register A in the module buffer.
5495
INC BC 03
Add one to the count of the marker record in Register Pair BC.
5496
LD (HL),C 71
Store Register C, the low byte of the count, into the marker record at Register Pair HL.
5497
INC HL 23
Bump Register Pair HL to the high byte of the count.
5498
LD (HL),B 70
Store Register B, the high byte of the count, into the marker record at Register Pair HL.
5499
DEC HL 2B
DECrement Register Pair HL back to the low byte of the count, ready for the next call.
549A
RET C9
RETurn with Register Pair HL pointing to the count and Register Pair BC = the count.
549BH - Check a Load Address
Called for every object code record, with Register Pair HL = the load address and Register B = the number of data bytes (00H = 256). Records below 3C00H, and records in the 3F00H page that run past 3FFFH, stop the program with SOURCE ILLEGAL LOAD-TO-MEMORY ADDRESS. Records that start in the display (3C00H-3FFFH) are accepted but are not counted in the load range, so they are never moved. Records at 4000H or above update the lowest and highest load addresses.
549B
LD A,H 7C
Load Register A with Register H, the high byte of the load address.
549C
CP 3FH FE 3F
Compare Register A, the high byte of the load address, against 3FH.
549E
If the record does not start in the 3F00H page, JUMP to 54A7H.
54A0
LD A,B 78
Load Register A with Register B, the number of data bytes.
54A1
DEC A 3D
DECrement Register A by 1, giving the offset of the record's last byte.
54A2
ADD A,L 85
Add Register L, the low byte of the load address, to Register A. A carry means the record runs past 3FFFH.
54A3
If the record runs past 3FFFH, JUMP to 584BH to report SOURCE ILLEGAL LOAD-TO-MEMORY ADDRESS.
54A6
RET C9
RETurn without updating the load addresses: the record stays inside the display at 3F00H-3FFFH.
54A7
If the high byte is above 3FH (the NC FLAG is still set from the compare at 549CH), JUMP to 54AFH.
54A9
CP 3CH FE 3C
Compare Register A, the high byte of the load address, against 3CH.
54AB
If the record starts below 3C00H (in the ROM), JUMP to 584BH to report SOURCE ILLEGAL LOAD-TO-MEMORY ADDRESS.
54AE
RET C9
RETurn: the record starts in the display at 3C00H-3EFFH.
54AF
LD DE,(5376H) ED 5B 76 53
Fetch the Lowest Load Address at 5376H into Register Pair DE.
54B3
RST 18H DF
Compare Register Pair HL, the load address, with Register Pair DE (RST 18H): the CARRY FLAG is set if Register Pair HL is lower.
54B4
If the load address is not lower, JUMP to 54B9H.
54B6
LD (5376H),HL 22 76 53
Store Register Pair HL as the new Lowest Load Address at 5376H.
54B9
LD DE,(5378H) ED 5B 78 53
Fetch the Highest Load Address at 5378H into Register Pair DE.
54BD
LD A,B 78
Load Register A with Register B, the number of data bytes.
54BE
DEC A 3D
DECrement Register A by 1, giving the offset of the record's last byte.
54BF
ADD A,L 85
Add Register L, the low byte of the load address, to Register A.
54C0
LD L,A 6F
Copy Register A into Register L, the low byte of the record's last address.
54C1
If there was no carry (the NC FLAG is set), JUMP to 54C4H, leaving Register H unchanged.
54C3
INC H 24
Otherwise add the carry to Register H. Register Pair HL = the address of the record's last byte.
54C4
RST 18H DF
Compare Register Pair HL, the record's last address, with Register Pair DE, the highest load address so far (RST 18H).
54C5
RET C D8
If Register Pair HL is lower (the CARRY FLAG is set), RETurn without a change.
54C6
LD (5378H),HL 22 78 53
Store Register Pair HL as the new Highest Load Address at 5378H.
54C9
RET C9
RETurn with the lowest and highest load addresses up to date.
54CAH - Read a SYSTEM Tape: Entry Point
The 78H byte is followed by the two-byte entry point. It is stored as a disk transfer record: 02H, 02H and the address.
54CA
LD A,02H 3E 02
Load Register A with 02H, the disk record type for the transfer address.
54CC
GOSUB to 547BH to store Register A (02H), the record type, in the module buffer.
54CF
GOSUB to 547BH to store 02H again as the length byte.
54D2
GOSUB to 5467H to read the entry point from the tape and store it.
54D5
GOSUB to the ROM routine at 01F8H to turn off the cassette motor.
54D8
EI FB
Enable interrupts again now that the tape read is over.
54D9
JUMP to 5550H to display the load information.
54DCH - Read a Load Module From Disk
Opens the source file and copies it record by record into the module buffer. The file is read through the alternate register set: HL' = the position in the sector buffer at 5200H, DE' = the FCB at 5300H, B' = the bytes left in the sector buffer. Every byte read is stored in the module buffer as it is. Object code records (01H) have their load address checked; a transfer record (02H) ends the file.
54DC
LD HL,5B15H 21 15 5B
Point Register Pair HL to the message SOURCE FILESPEC? at 5B15H.
54DF
GOSUB to 5521H to display it and read the filespec into the FCB at 5300H. If a filespec was typed, the alternate register set is now active with Register Pair HL = 5200H, Register Pair DE = 5300H and B = 00H.
54E2
If the reply was empty, JUMP back to 54DCH to ask again.
54E4
GOSUB to the SYS0 routine at 4424H to open the existing file (FCB at DE, sector buffer at HL, record length 256).
54E7
If the open failed, JUMP to 5855H to display the DOS error.
54EA
INC H 24
INCrement Register H so Register Pair HL = 5300H, the end of the sector buffer at 5200H.
54EB
LD B,01H 06 01
Load Register B with 01H, so the first byte request reads a sector (see 5537H).
54ED
EXX D9
Switch back to the main register set, keeping the file registers in the alternate set.
54EE
GOSUB to 5537H to read the record type from the file (and store it).
54F1
PUSH AF F5
Save Register Pair AF, holding the record type in Register A, on the stack.
54F2
GOSUB to 5537H to read the record length byte.
54F5
LD B,A 47
Copy Register A, the record length byte, into Register B as the number of bytes to copy.
54F6
POP AF F1
Restore Register Pair AF from the stack, putting the record type back in Register A.
54F7
CP 02H FE 02
Compare Register A, the record type, against 02H (transfer address).
54F9
If Register A is 02H (the Z FLAG is set), JUMP to 550EH to copy the transfer record and close the file.
54FB
CP 01H FE 01
Compare Register A, the record type, against 01H (object code).
54FD
If it is any other type (for example the 05H header record), JUMP to 5507H to copy the record unchanged.
54FF
GOSUB to 5547H to read the two-byte load address into Register Pair HL.
5502
DEC B 05
DECrement Register B, the length byte, once for the low address byte already read.
5503
DEC B 05
DECrement Register B again: B = the number of data bytes (00H = 256).
5504
GOSUB to 549BH to check the load address and update the load range.
5507
GOSUB to 5537H to read and store the next byte of the record.
550A
LOOP back to 5507H until Register B bytes are copied (00H = 256).
550C
JUMP back to 54EEH to read the next record from the file.
550E
LD HL,(5374H) 2A 74 53
Fetch the Module Buffer Pointer at 5374H into Register Pair HL; it points to the length byte just stored.
5511
LD (HL),02H 36 02
Store 02H into the length byte at Register Pair HL, whatever length the file had.
5513
GOSUB to 5537H to read and store the low byte of the entry point.
5516
GOSUB to 5537H to read and store the high byte.
5519
EXX D9
Exchange to the alternate register set, so Register Pair DE holds the FCB at 5300H for the close.
551A
GOSUB to the SYS0 routine at 4428H to close the file.
551D
EXX D9
Exchange back to the main register set, keeping the file registers in the alternate set.
551E
JUMP to 5550H to display the load information.
5521H - Ask for a Filespec
Displays the message at Register Pair HL and reads up to 31 characters into the FCB at 5300H. Returns the Z FLAG set if the reply was empty. Otherwise it switches to the alternate register set and loads it for the DOS file routines: Register Pair HL = 5200H (sector buffer), Register Pair DE = 5300H (FCB), B = 00H (record length 256). Used for the source (54DFH) and the destination (56FFH).
5521
GOSUB to the SYS0 routine at 4467H to display the message.
5524
LD HL,5300H 21 00 53
Point Register Pair HL to the FCB at 5300H, which receives the typed filespec.
5527
LD A,1FH 3E 1F
Load Register A with 1FH, the maximum length (31 characters).
5529
GOSUB to 589BH to read up to Register A (1FH) characters into the FCB at 5300H; Register B = the length.
552C
RET Z C8
If the reply was empty, RETurn with the Z FLAG set.
552D
EXX D9
Exchange to the alternate register set, which becomes the file registers.
552E
LD DE,5300H 11 00 53
Point Register Pair DE in the alternate set to the FCB at 5300H.
5531
LD HL,5200H 21 00 52
Point Register Pair HL to the sector buffer at 5200H.
5534
LD B,00H 06 00
Load Register B with 00H (record length 256).
5536
RET C9
RETurn with the NZ FLAG set and the file registers active.
5537H - Read a Byte From the Source File
Returns the next byte of the source file in Register A and stores it in the module buffer (547BH). Uses the alternate register set: B' counts the bytes left in the sector buffer and HL' points into it. When the buffer is empty the next sector is read into 5200H.
5537
EXX D9
Exchange to the alternate register set: Register Pair HL = the buffer position, Register B = the bytes left.
5538
DECrement Register B, the bytes left in the sector buffer; if any are left (the NZ FLAG is set), JUMP to 5541H.
553A
GOSUB to the SYS0 routine at 4436H to read the next sector into 5200H.
553D
If the read failed (including the end of the file), JUMP to 5855H to display the DOS error.
5540
DEC H 25
DECrement Register H to move Register Pair HL back from 5300H to 5200H, the start of the buffer. Register B is now 00H, which counts 256 bytes.
5541
LD A,(HL) 7E
Fetch the byte at Register Pair HL, the position in the sector buffer, into Register A.
5542
INC HL 23
Bump Register Pair HL, the position in the sector buffer, to the next byte.
5543
EXX D9
EXX: switch from the alternate register set back to the main set, keeping Register A, the byte read.
5544
JUMP to 547BH to store the byte in the module buffer and return.
5547H - Read a Two-Byte Address From the File
Reads the low byte and then the high byte into HL, storing both in the module buffer.
5547
GOSUB to 5537H to read the low byte of the address from the file into Register A and store it.
554A
LD L,A 6F
Copy Register A, the low byte of the address, into Register L.
554B
GOSUB to 5537H to read the high byte of the address from the file into Register A and store it.
554E
LD H,A 67
Copy Register A, the high byte of the address, into Register H.
554F
RET C9
RETurn with Register Pair HL = the address read from the file.
5550H - Display the Load Information
Shows MODULE LOADS TO XXXX-XXXX for the module as it will load (the load range plus the offset). When an appendage is to be attached, the end address includes 4EH more bytes, the size of the DOS-enabled appendage; the DOS-disabled appendage is larger (137H bytes), but that choice is only made later (563EH). Then warns if the new start address is in the ROM or the DOS. Also reached from 55DEH and 55E6H after a new load base has been given.
5550
LD HL,(5378H) 2A 78 53
Fetch the Highest Load Address at 5378H into Register Pair HL.
5553
LD DE,(537AH) ED 5B 7A 53
Fetch the Load Offset at 537AH into Register Pair DE.
5557
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = the new address of the module's last byte.
5558
LD A,(5372H) 3A 72 53
Fetch the No-Appendage Flag at 5372H into Register A.
555B
OR A B7
OR Register A with itself to set the flags: NZ means no appendage will be attached.
555C
If there is no appendage (the NZ FLAG is set), JUMP to 5562H to keep the end address as it is.
555E
LD DE,004EH 11 4E 00
Load Register Pair DE with 004EH, the size of the DOS-enabled appendage (78 bytes).
5561
ADD HL,DE 19
Add Register Pair DE (004EH) to Register Pair HL, the end address, for the appendage.
5562
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL, so Register Pair DE = the end address.
5563
LD HL,5B53H 21 53 5B
Point Register Pair HL to the second XXXX in the message at 5B53H.
5566
GOSUB to 5A25H to write Register Pair DE there in hexadecimal.
5569
LD DE,(5376H) ED 5B 76 53
Fetch the Lowest Load Address at 5376H into Register Pair DE.
556D
LD HL,(537AH) 2A 7A 53
Fetch the Load Offset at 537AH into Register Pair HL.
5570
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = the new start address.
5571
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL, so Register Pair DE = the new start address.
5572
PUSH DE D5
Save Register Pair DE, the new start address, on the stack for the overlap tests below.
5573
LD HL,5B4EH 21 4E 5B
Point Register Pair HL to the first XXXX in the message at 5B4EH.
5576
GOSUB to 5A25H to write the start address there.
5579
LD HL,5B3EH 21 3E 5B
Point Register Pair HL to the message MODULE LOADS TO XXXX-XXXX at 5B3EH.
557C
GOSUB to the SYS0 routine at 4467H to display it.
557F
POP DE D1
Restore the start address into Register Pair DE.
5580
LD HL,3FFFH 21 FF 3F
Load Register Pair HL with 3FFFH, the last byte of the display.
5583
RST 18H DF
Compare Register Pair HL (3FFFH) with Register Pair DE, the start address (RST 18H): the NC FLAG is set if the start address is 3FFFH or lower.
5584
LD HL,5B9BH 21 9B 5B
Point Register Pair HL to the message MODULE LOAD WILL OVERLAP ROM at 5B9BH.
5587
If the start address is 3FFFH or lower, GOSUB to the SYS0 routine at 4467H to display it.
558A
LD HL,51FFH 21 FF 51
Load Register Pair HL with 51FFH, the last byte of the DOS area.
558D
RST 18H DF
Compare Register Pair HL (51FFH) with Register Pair DE, the start address (RST 18H): the NC FLAG is set if the start address is 51FFH or lower.
558E
LD HL,5B58H 21 58 5B
Point Register Pair HL to the message MODULE LOAD OVERLAPS DOS (4000-51FF) at 5B58H.
5591
If the start address is 51FFH or lower, GOSUB to the SYS0 routine at 4467H to display it.
5594H - Display the Entry Point and Ask for a New Load Base
With an appendage, the entry point is the first byte of the appendage, just past the module's last byte at its new address. Without one, it is the module's own entry point plus the offset; this is only the value displayed, since 561BH moves the entry point only if it lies inside the load range. The new entry point is also stored in the appendage's transfer record at 5A03H. Also reached from 55C3H when the reply is not valid hexadecimal.
5594
GOSUB to 5771H to fetch the entry point from the module's transfer record into Register Pair DE.
5597
LD A,(5372H) 3A 72 53
Fetch the No-Appendage Flag at 5372H into Register A.
559A
OR A B7
OR Register A with itself to set the flags: NZ means no appendage will be attached.
559B
If there is no appendage, JUMP to 55A2H with Register Pair DE = the module's entry point.
559D
LD DE,(5378H) ED 5B 78 53
Fetch the Highest Load Address at 5378H into Register Pair DE.
55A1
INC DE 13
Add 1: Register Pair DE = the byte after the module, where the appendage starts.
55A2
LD HL,(537AH) 2A 7A 53
Fetch the Load Offset at 537AH into Register Pair HL.
55A5
ADD HL,DE 19
Add Register Pair DE: Register Pair HL = the new entry point.
55A6
LD (5A03H),HL 22 03 5A
Store Register Pair HL, the new entry point, into the appendage's transfer record at 5A03H.
55A9
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL, so Register Pair DE = the new entry point.
55AA
LD HL,5C3AH 21 3A 5C
Point Register Pair HL to the XXXX in the message at 5C3AH.
55AD
GOSUB to 5A25H to write the entry point there.
55B0
LD HL,5C2CH 21 2C 5C
Point Register Pair HL to the message ENTRY POINT = XXXX at 5C2CH.
55B3
GOSUB to the SYS0 routine at 4467H to display it.
55B6
LD HL,5B7DH 21 7D 5B
Point Register Pair HL to the message NEW LOAD BASE ADDRESS (HEX)? at 5B7DH.
55B9
GOSUB to 5893H to display it and read a reply.
55BC
If the reply is empty (ENTER), JUMP to 55E9H to finish the source module.
55BE
LD A,B 78
Copy Register B, the length of the reply, into Register A for the conversion at 5A05H.
55BF
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL, so Register Pair DE points to the reply.
55C0
GOSUB to 5A05H to convert up to four hexadecimal digits into Register Pair HL.
55C3
If the reply is not a valid hexadecimal number, JUMP back to 5594H to ask again.
55C5
LD DE,(5376H) ED 5B 76 53
Fetch the Lowest Load Address at 5376H into Register Pair DE.
55C9
OR A B7
OR Register A with itself to clear the CARRY FLAG before the subtraction.
55CA
SBC HL,DE ED 52
Subtract Register Pair DE, the lowest load address, from Register Pair HL, the new load base.
55CC
LD (537AH),HL 22 7A 53
Store Register Pair HL, the difference, as the Load Offset at 537AH.
55CF
LD HL,5C3FH 21 3F 5C
Point Register Pair HL to the message SHALL APPENDAGE BE SUPPRESSED? (Y OR N) at 5C3FH.
55D2
GOSUB to 5893H to display it and read a reply.
55D5
DECrement Register B and LOOP back to 55CFH unless the reply was exactly one character long.
55D7
LD HL,5372H 21 72 53
Point Register Pair HL to the No-Appendage Flag at 5372H.
55DA
LD (HL),00H 36 00
Store 00H into the No-Appendage Flag at Register Pair HL: attach an appendage.
55DC
CP 4EH FE 4E
Compare Register A, the reply, against N (4EH).
55DE
If it is N, JUMP to 5550H to display the new load information.
55E1
CP 59H FE 59
Compare Register A, the reply, against Y (59H).
55E3
If it is neither, JUMP back to 55CFH to ask again.
55E5
INC (HL) 34
INCrement the No-Appendage Flag at Register Pair HL to 01H: the appendage is suppressed.
55E6
JUMP to 5550H to display the new load information.
55E9H - Move the Load Addresses
The operator has accepted the load base. The module's original entry point is saved in the appendage's move code at 59FFH. Then every record in the module buffer is walked through: marker records (FEH, FFH) are skipped (5733H), every object code record at 4000H or above gets the offset added to its load address, and the transfer address gets the offset only if it lies inside the load range. With an offset of 0000H nothing changes.
55E9
GOSUB to 5771H to fetch the module's entry point into Register Pair DE.
55EC
LD (59FFH),DE ED 53 FF 59
Store Register Pair DE, the original entry point, as the JP target in the appendage's move code at 59FFH.
55F0
LD HL,5E9BH 21 9B 5E
Point Register Pair HL to 5E9BH, the first record in the module buffer.
55F3
DEC HL 2B
Move Register Pair HL back one byte for the end test.
55F4
LD DE,(5374H) ED 5B 74 53
Fetch the Module Buffer Pointer at 5374H, the last byte in the buffer, into Register Pair DE.
55F8
RST 18H DF
Compare Register Pair HL with Register Pair DE, the last byte in the buffer (RST 18H): the NC FLAG is set when no records are left.
55F9
If no records are left (the NC FLAG is set), JUMP to 563EH.
55FB
INC HL 23
Move Register Pair HL forward again to the record.
55FC
GOSUB to 5733H. A marker record is skipped (NC FLAG). Any other record returns the CARRY FLAG set, its type in Register A and Register Pair HL still pointing to it.
55FF
If it was a marker record, JUMP back to 55F3H.
5601
INC HL 23
Bump Register Pair HL to the record's length byte.
5602
LD C,(HL) 4E
Fetch the record's length byte at Register Pair HL into Register C.
5603
LD B,00H 06 00
Set Register B to 00H, so Register Pair BC = the length.
5605
INC HL 23
Point Register Pair HL to the first byte after the length (the load address in a 01H or 02H record).
5606
CP 02H FE 02
Compare Register A, the record type, against 02H (transfer address).
5608
If Register A is 02H (the Z FLAG is set), JUMP to 561BH to move the entry point.
560A
CP 01H FE 01
Compare Register A, the record type, against 01H (object code).
560C
If Register A is 01H (the Z FLAG is set), JUMP to 5615H.
560E
INC C 0C
Any other record is skipped. INCrement Register C...
560F
DEC C 0D
DECrement Register C again, setting the Z FLAG if the length is zero.
5610
If the length in Register C is not zero (the NZ FLAG is set), JUMP to 5613H.
5612
INC B 04
INCrement Register B: a length of 00H means 256 bytes, so Register Pair BC = 0100H.
5613
JUMP to 563BH to step over the record by Register Pair BC bytes.
5615
LD A,C 79
Copy Register C, the length byte, into Register A.
5616
CP 03H FE 03
Compare Register A, the length byte, against 03H.
5618
If Register A is 03H or more (the NC FLAG is set), JUMP to 561BH.
561A
INC B 04
INCrement Register B: a length of 00H, 01H or 02H means 254, 255 or 256 data bytes, so 256 is added to Register Pair BC.
561B
LD E,(HL) 5E
Fetch the low byte of the address at Register Pair HL into Register E.
561C
INC HL 23
Bump Register Pair HL to the high byte of the address.
561D
LD D,(HL) 56
Fetch the high byte of the address at Register Pair HL into Register D, so Register Pair DE = the address.
561E
PUSH HL E5
Save Register Pair HL, the pointer to the high byte, on the stack.
561F
LD A,D 7A
Copy Register D, the high byte of the address, into Register A.
5620
CP 40H FE 40
Compare Register A, the high byte of the address, against 40H.
5622
If the address is below 4000H (a record in the display, or an entry point below 4000H), JUMP to 5637H to leave it unchanged.
5624
LD HL,(5378H) 2A 78 53
Fetch the Highest Load Address at 5378H into Register Pair HL.
5627
RST 18H DF
Compare Register Pair HL, the highest load address, with Register Pair DE, the address (RST 18H): the CARRY FLAG is set if the address is higher.
5628
If the address is above the load range, JUMP to 5637H to leave it unchanged. This only happens for the entry point.
562A
LD HL,(5376H) 2A 76 53
Fetch the Lowest Load Address at 5376H into Register Pair HL.
562D
EX DE,HL EB
Swap: Register Pair HL = the address, Register Pair DE = the lowest load address.
562E
RST 18H DF
Compare Register Pair HL, the address, with Register Pair DE, the lowest load address (RST 18H): the CARRY FLAG is set if the address is lower.
562F
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL back, so Register Pair DE = the address.
5630
If the address is below the load range, JUMP to 5637H to leave it unchanged.
5632
LD HL,(537AH) 2A 7A 53
Fetch the Load Offset at 537AH into Register Pair HL.
5635
ADD HL,DE 19
Add Register Pair DE, the address, to Register Pair HL, the offset.
5636
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL, so Register Pair DE = the new address.
5637
POP HL E1
Restore Register Pair HL, the pointer to the high byte of the address, from the stack.
5638
LD (HL),D 72
Store Register D, the high byte of the address, at Register Pair HL.
5639
DEC HL 2B
DECrement Register Pair HL back to the low byte of the address.
563A
LD (HL),E 73
Store Register E, the low byte of the address, at Register Pair HL.
563B
ADD HL,BC 09
Add the length in Register Pair BC: Register Pair HL now points to the next record.
563C
LOOP back to 55F3H to test for the next record.
563EH - Ask Whether to Disable DOS
Only asked when an appendage is to be attached. The appendage is placed at the byte after the module's new last byte. With N the DOS-enabled appendage is used unchanged. With Y the addresses inside the DOS-disabled appendage are filled in and its first record is lengthened to C1H. The reply is also stored into the instruction at 56D6H, where 00H selects the DOS-enabled appendage. See The Appendages for their layout.
563E
LD A,(5372H) 3A 72 53
Fetch the No-Appendage Flag at 5372H into Register A.
5641
OR A B7
OR Register A with itself to set the flags: NZ means no appendage will be attached.
5642
If there is no appendage, JUMP to 56E6H to ask for the destination.
5645
LD HL,5BB8H 21 B8 5B
Point Register Pair HL to the message DISABLE DOS? (Y OR N) at 5BB8H.
5648
GOSUB to 5893H to display it and read a reply.
564B
DECrement Register B and LOOP back to 5645H unless the reply was exactly one character long.
564D
LD HL,(5378H) 2A 78 53
Fetch the Highest Load Address at 5378H into Register Pair HL.
5650
LD DE,(537AH) ED 5B 7A 53
Fetch the Load Offset at 537AH into Register Pair DE.
5654
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = the new address of the module's last byte.
5655
INC HL 23
Add 1: Register Pair HL = the appendage's load address (called X below).
5656
LD (58C4H),HL 22 C4 58
Store Register Pair HL, the appendage's load address X, as the load address of the appendage's first record at 58C4H.
5659
SUB 4EH D6 4E
Subtract N (4EH) from Register A, the reply: 00H for N, 0BH for Y.
565B
LD (56D7H),A 32 D7 56
Store Register A into the operand of the LD A,00H instruction at 56D6H, the byte at 56D7H.
565E
If the reply was N (the Z FLAG is set), JUMP to 568FH to keep the DOS-enabled appendage.
5660
CP 0BH FE 0B
Compare Register A against 0BH, the result for Y.
5662
If the reply was neither, JUMP back to 5645H to ask again.
DOS is to be disabled. Fill in the addresses the DOS-disabled appendage uses when it runs. Its code starts at X+40H, after the 64-byte patch area.
5664
LD DE,005EH 11 5E 00
Load Register Pair DE with 005EH, the offset of the six bytes at 5924H in the appendage.
5667
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = X+5EH, where the six bytes at 5924H will be.
5668
LD (5912H),HL 22 12 59
Store Register Pair HL at 5912H, the source address of the copy to 42E9H.
566B
LD DE,0006H 11 06 00
Load Register Pair DE with 0006H, the distance from 5924H to the message at 592AH.
566E
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = X+64H, where the message at 592AH will be.
566F
LD (591DH),HL 22 1D 59
Store Register Pair HL at 591DH, the message address for the SYS0 display call.
5672
LD DE,005BH 11 5B 00
Load Register Pair DE with 005BH, the distance from 592AH to the second record at 5985H.
5675
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = X+BFH, the load address of the second record.
5676
LD (5987H),HL 22 87 59
Store Register Pair HL in the second record's header at 5987H.
5679
LD DE,005FH 11 5F 00
Load Register Pair DE with 005FH, the distance from the second record's data to the code at 59E8H.
567C
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = X+11EH, where the code at 59E8H will be.
567D
LD (5928H),HL 22 28 59
Store Register Pair HL at 5928H, the target of the JP that the copy puts at 42ECH.
5680
LD DE,0019H 11 19 00
Load Register Pair DE with 0019H, the distance from 59E8H to the end of the appendage.
5683
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = X+137H, the first byte after the appendage.
5684
LD (59E9H),HL 22 E9 59
Store Register Pair HL at 59E9H, the source address for restoring the screen.
5687
LD (5907H),HL 22 07 59
Store Register Pair HL at 5907H too, the destination address for saving the screen.
568A
LD HL,58C3H 21 C3 58
Point Register Pair HL to the length byte of the appendage's first record at 58C3H.
568D
LD (HL),C1H 36 C1
Store C1H into the length byte at Register Pair HL: 64 patch bytes and 127 code bytes.
568FH - Fill In the Move Code and Add the Appendage
Fills in the move code at 59F3H-5A00H that both appendages end with: LD HL,new start / LD DE,original start / LD BC,length / LDIR or LDDR / JP original entry point. If the module now loads lower than its original address it is copied upward, so LDDR is used with the addresses of the last bytes. Then the transfer record at the end of the module buffer is removed and the appendage records (which end with their own transfer record) are added in its place.
568F
LD DE,(5376H) ED 5B 76 53
Fetch the Lowest Load Address at 5376H into Register Pair DE.
5693
LD HL,(5378H) 2A 78 53
Fetch the Highest Load Address at 5378H into Register Pair HL.
5696
XOR A AF
Set Register A to 00H and clear the CARRY FLAG before the subtraction.
5697
SBC HL,DE ED 52
Subtract Register Pair DE from Register Pair HL: Register Pair HL = the module size minus 1.
5699
If the highest address is below the lowest, there were no object code records at 4000H or above: JUMP to 5850H to report SOURCE MODULE BAD FORMAT.
569C
LD B,H 44
Copy Register H into Register B, the high byte of the size minus 1.
569D
LD C,L 4D
Copy Register L into Register C, so Register Pair BC = the module size minus 1.
569E
INC HL 23
INCrement Register Pair HL by 1, giving the module size.
569F
LD (59FAH),HL 22 FA 59
Store Register Pair HL, the module size, as the byte count of the move code at 59FAH.
56A2
LD DE,(5376H) ED 5B 76 53
Fetch the Lowest Load Address at 5376H into Register Pair DE: the original start, where the module must be moved to.
56A6
LD HL,(537AH) 2A 7A 53
Fetch the Load Offset at 537AH into Register Pair HL.
56A9
LD A,B0H 3E B0
Load Register A with B0H, the second byte of LDIR.
56AB
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: Register Pair HL = the new start, where the module is loaded. The CARRY FLAG is set if the new start is lower than the original.
56AC
If the new start is higher, JUMP to 56B4H: copying upward with LDIR is safe.
56AE
LD A,B8H 3E B8
Otherwise load Register A with B8H, the second byte of LDDR.
56B0
ADD HL,BC 09
Add Register Pair BC to Register Pair HL, pointing it to the last byte at the new address.
56B1
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL, so Register Pair HL = the original start.
56B2
ADD HL,BC 09
Add Register Pair BC to Register Pair HL, pointing it to the last byte at the original address.
56B3
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL back: Register Pair HL = the source, Register Pair DE = the destination.
56B4
LD (59FDH),A 32 FD 59
Store Register A, B0H or B8H, into the second byte of the block move in the move code at 59FDH.
56B7
LD (59F4H),HL 22 F4 59
Store Register Pair HL, the source address, into the move code at 59F4H.
56BA
LD (59F7H),DE ED 53 F7 59
Store Register Pair DE, the destination address, into the move code at 59F7H.
56BE
LD HL,(5374H) 2A 74 53
Fetch the Module Buffer Pointer at 5374H into Register Pair HL.
56C1
LD DE,FFFCH 11 FC FF
Load Register Pair DE with FFFCH, which is minus 4.
56C4
ADD HL,DE 19
Add Register Pair DE to Register Pair HL, subtracting 4: the module's transfer record (the last four bytes) is dropped.
56C5
LD (5374H),HL 22 74 53
Store Register Pair HL as the new Module Buffer Pointer at 5374H.
56C8
LD B,44H 06 44
Load Register B with 44H, the 68 bytes of the record header and the patch area.
56CA
LD HL,58C2H 21 C2 58
Point Register Pair HL to the appendage's first record header at 58C2H.
56CD
GOSUB to 5470H to copy the header and the 64-byte patch area into the module buffer. Register Pair HL returns 5906H.
56D0
EX DE,HL EB
Exchange Register Pair DE and Register Pair HL, keeping 5906H in Register Pair DE.
56D1
LD HL,59F3H 21 F3 59
Point Register Pair HL to the move code at 59F3H.
56D4
LD B,12H 06 12
Load Register B with 12H (18 bytes: the move code and the transfer record).
56D6
LD A,00H 3E 00
Load Register A with the reply stored at 565BH: 00H = DOS-enabled, 0BH = DOS-disabled.
56D8
OR A B7
OR Register A with itself to set the flags: Z means DOS stays enabled.
56D9
If DOS stays enabled, JUMP to 56E3H to copy the move code and the transfer record.
56DB
EX DE,HL EB
Otherwise point Register Pair HL to 5906H (and Register Pair DE to 59F3H).
56DC
LD B,7FH 06 7F
Load Register B with 7FH, the 127 bytes at 5906H-5984H.
56DE
GOSUB to 5470H to copy 5906H-5984H, the rest of the first record.
56E1
LD B,80H 06 80
Load Register B with 80H (128 bytes): the second record (5985H-5A00H) and the transfer record.
56E3
GOSUB to 5470H to copy them into the module buffer.
56E6H - Ask for the Destination: Disk or Tape
Also reached from 587CH when the operator wants the same module written to another file.
56E6
LD HL,5373H 21 73 53
Point Register Pair HL to the Output Phase Flag at 5373H.
56E9
LD (HL),01H 36 01
Store 01H into the Output Phase Flag at Register Pair HL: the module is ready for output.
56EB
LD HL,5AF0H 21 F0 5A
Point Register Pair HL to the message DESTINATION DISK OR TAPE? (D OR T) at 5AF0H.
56EE
GOSUB to 5893H to display it and read a reply.
56F1
DECrement Register B and LOOP back to 56EBH unless the reply was exactly one character long.
56F3
CP 54H FE 54
Compare Register A, the reply, against T (54H).
56F5
If Register A is T (the Z FLAG is set), JUMP to 577AH to write to tape.
56F8
CP 44H FE 44
Compare Register A, the reply, against D (44H).
56FA
If it is neither, JUMP back to 56E6H to ask again.
56FC
LD HL,5B27H 21 27 5B
Point Register Pair HL to the message DESTINATION FILESPEC? at 5B27H.
56FF
GOSUB to 5521H to display it and read the filespec into the FCB at 5300H.
5702
If the reply was empty, JUMP back to 56FCH to ask again.
5704
GOSUB to the SYS0 routine at 4420H to open the file, creating it if it does not exist (FCB at DE, sector buffer at HL, record length 256).
5707
If the open failed, JUMP to 5855H to display the DOS error.
570AH - Write the Module to Disk
Writes every record in the module buffer to the file in load module format. Marker records are skipped. Object code records and other record types are written unchanged; the transfer record is written last and the file is closed. The file registers are in the alternate set: HL' = the position in the sector buffer at 5200H, B' = a byte counter that reaches zero after every 256 bytes.
570A
EXX D9
Switch to the main register set, keeping the file registers in the alternate set.
570B
LD HL,5E9BH 21 9B 5E
Point Register Pair HL to 5E9BH, the first record in the module buffer.
570E
GOSUB to 5733H. A marker record is skipped (NC FLAG); any other record returns the CARRY FLAG set and its type in Register A.
5711
If it was a marker record, JUMP back to 570EH.
5713
CP 01H FE 01
Compare Register A, the record type, against 01H (object code).
5715
If Register A is 01H (the Z FLAG is set), JUMP to 5721H.
5717
CP 02H FE 02
Compare Register A, the record type, against 02H (transfer address).
5719
If it is 02H, JUMP to 5744H to finish the file.
571C
Any other record: GOSUB to 575CH to write the type and the length byte, with Register B = the length.
571F
JUMP to 572CH to write the rest of the record.
5721
GOSUB to 575CH to write the type and the length byte, with Register B = the length.
5724
DEC B 05
DECrement Register B, the length byte, once for the low address byte.
5725
DEC B 05
DECrement Register B again: B = the number of data bytes.
5726
GOSUB to 5760H to write the low byte of the load address.
5729
GOSUB to 5760H to write the high byte of the load address.
572C
GOSUB to 5760H to write the next byte of the record.
572F
LOOP back to 572CH until Register B bytes are written (00H = 256).
5731
JUMP back to 570EH to check the type of the next record in the module buffer.
5733H - Check a Record Type
Register Pair HL points to a record in the module buffer. Types below 20H are load module records: return the CARRY FLAG set, Register A = the type and Register Pair HL unchanged. FEH and FFH are marker records made by the tape reader: step Register Pair HL past the record (type, two-byte count and the bytes) and return with the NC FLAG and Register A = 00H. Any other type, including the FCH and FDH records the tape reader makes for checksum errors and extra bytes, stops the program with BAD MAIN MEMORY.
5733
LD A,(HL) 7E
Fetch the record type at Register Pair HL into Register A.
5734
CP 20H FE 20
Compare Register A, the record type, against 20H.
5736
RET C D8
If it is below 20H, RETurn with the CARRY FLAG set.
5737
CP FEH FE FE
Compare Register A, the record type, against FEH.
5739
If it is 20H-FDH, JUMP to 5846H to report BAD MAIN MEMORY.
573C
INC HL 23
Bump Register Pair HL to the marker record's two-byte count.
573D
LD E,(HL) 5E
Fetch the low byte of the count at Register Pair HL into Register E.
573E
INC HL 23
Bump Register Pair HL to the high byte of the count.
573F
LD D,(HL) 56
Fetch the high byte of the count at Register Pair HL into Register D, so Register Pair DE = the count.
5740
INC HL 23
Point Register Pair HL to the first byte of the marker record.
5741
ADD HL,DE 19
Add Register Pair DE, the count, to Register Pair HL: Register Pair HL now points to the next record.
5742
XOR A AF
Set Register A to 00H and clear the CARRY FLAG.
5743
RET C9
RETurn with the NC FLAG set and Register Pair HL pointing past the marker record.
5744H - Write the Transfer Record and Close the File
The four bytes of the transfer record are written. If the sector buffer holds anything not yet written, it is written, and then the file is closed.
5744
GOSUB to 575CH to write the type (02H) and the length byte.
5747
GOSUB to 575CH again to write the two bytes of the entry point.
574A
EXX D9
Exchange to the alternate register set: Register B = the byte counter, Register Pair DE = the FCB.
574B
LD A,B 78
Copy Register B, the byte counter, into Register A.
574C
OR A B7
OR Register A with itself to set the flags: Z means the sector buffer holds nothing unwritten.
574D
If it is 00H, every byte has already been written: JUMP to 5752H.
574F
Otherwise GOSUB to the SYS0 routine at 443CH to write the partly filled sector. The result is not checked.
5752
GOSUB to the SYS0 routine at 4428H to close the file. The result is not checked.
5755
EXX D9
EXX: switch from the alternate register set (the file registers) back to the main set.
5756
LD HL,5C27H 21 27 5C
Point Register Pair HL to the message DONE at 5C27H. Also reached from 5837H when a tape has been written.
5759
JUMP to 585FH to display it and ask what to do next.
575CH - Write Bytes to the Destination File
575CH writes the byte at Register Pair HL and the one after it, and returns Register B = that second byte (a length). 5760H writes the byte at HL, steps HL, and returns Register A = the next byte. Bytes are collected in the sector buffer at 5200H through the alternate register set; every 256 bytes the sector is written.
575C
GOSUB to 5760H to write the byte at Register Pair HL. Register A returns the next byte.
575F
LD B,A 47
Copy Register A, the second byte, into Register B, then fall into 5760H to write it too.
5760
LD A,(HL) 7E
Fetch the byte at Register Pair HL in the module buffer into Register A.
5761
INC HL 23
Bump Register Pair HL, the module buffer pointer, to the next byte.
5762
EXX D9
Exchange to the alternate register set: Register Pair HL = the sector buffer position, Register B = the byte counter.
5763
LD (HL),A 77
Store Register A into the sector buffer at Register Pair HL.
5764
INC HL 23
Bump Register Pair HL, the sector buffer pointer, to the next byte.
5765
DECrement Register B, the byte counter; if it has not reached zero (the NZ FLAG is set), JUMP to 576EH.
5767
GOSUB to the SYS0 routine at 443CH to write the full sector from 5200H.
576A
If the write failed, JUMP to 5855H to display the DOS error.
576D
DEC H 25
DECrement Register H to move Register Pair HL back from 5300H to 5200H, the start of the buffer.
576E
EXX D9
EXX: switch from the alternate register set (the file registers) back to the main set.
576F
LD A,(HL) 7E
Fetch the next byte of the module buffer at Register Pair HL into Register A.
5770
RET C9
RETurn with Register A = the next byte in the module buffer.
5771H - Fetch the Entry Point
Returns Register Pair DE = the address in the last two bytes of the module buffer, which is the entry point of the module's transfer record.
5771
PUSH HL E5
Save Register Pair HL, the caller's value, on the stack.
5772
LD HL,(5374H) 2A 74 53
Fetch the Module Buffer Pointer at 5374H, the last byte in the buffer, into Register Pair HL.
5775
LD D,(HL) 56
Fetch the high byte of the entry point at Register Pair HL into Register D.
5776
DEC HL 2B
DECrement Register Pair HL back to the low byte of the entry point.
5777
LD E,(HL) 5E
Fetch the low byte of the entry point at Register Pair HL into Register E.
5778
POP HL E1
Restore Register Pair HL, the caller's value, from the stack.
5779
RET C9
RETurn with Register Pair DE = the entry point.
577AH - Write to Tape: Ask for the Name
The name must be one to six characters, each a letter or a digit; it is padded with spaces to six characters at 5E95H. The message says the first character must be a letter, but the check is the same for every character, so a digit is also accepted first.
577A
LD HL,5C79H 21 79 5C
Point Register Pair HL to the message INPUT 1-6 CHAR TAPE MODULE NAME. / 1ST CHAR MUST BE A-Z; OTHERS A-Z OR 0-9 at 5C79H.
577D
GOSUB to 5893H to display it and read a reply. Register Pair HL = the reply, Register B = its length.
5780
If the reply is empty, JUMP back to 577AH to ask again.
5782
LD A,B 78
Copy Register B, the length of the reply, into Register A.
5783
CP 07H FE 07
Compare Register A, the length of the reply, against 07H.
5785
If it is seven characters or more, JUMP back to 577AH to ask again.
5787
LD DE,5E95H 11 95 5E
Point Register Pair DE to the name buffer at 5E95H.
578A
LD C,06H 0E 06
Load Register C with 06H, the length of a tape name.
578C
PUSH DE D5
Save Register Pair DE, the name buffer address, on the stack for 57C8H. If the name is rejected at 57A1H, this word is left on the stack.
578D
LD A,(HL) 7E
Fetch a character of the reply at Register Pair HL into Register A.
578E
LD (DE),A 12
Store Register A into the name buffer at Register Pair DE.
578F
INC DE 13
Bump Register Pair DE, the name buffer pointer, to the next byte.
5790
INC HL 23
Bump Register Pair HL, the reply pointer, to the next character.
5791
SUB 30H D6 30
Subtract the character 0 (30H) from Register A.
5793
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG is set for 0-9.
5795
If it is a digit, JUMP to 579BH (the CARRY FLAG is set).
5797
SUB 11H D6 11
Subtract 11H more from Register A, so it now holds the character minus A (41H).
5799
CP 1AH FE 1A
Compare Register A against 1AH: the CARRY FLAG is set for A-Z.
579B
If the character is a digit or a capital letter, JUMP to 57A3H.
579D
SUB 20H D6 20
Subtract 20H more from Register A, so it now holds the character minus a (61H).
579F
CP 1AH FE 1A
Compare Register A against 1AH. 5893H has already turned lower case letters into capitals, so this never matches.
57A1
If the character is not a letter or a digit, JUMP back to 577AH to ask again.
57A3
DEC C 0D
DECrement Register C, the name characters still to fill.
57A4
If all six characters are filled (the Z FLAG is set), JUMP to 57AFH.
57A6
DECrement Register B and LOOP back to 578DH while the reply has more characters.
57A8
LD A,20H 3E 20
Load Register A with a space (20H) to pad the name.
57AA
LD (DE),A 12
Store Register A, the space, into the name buffer at Register Pair DE.
57AB
DEC C 0D
DECrement Register C, the name characters still to fill.
57AC
INC DE 13
Bump Register Pair DE, the name buffer pointer, to the next byte.
57AD
LOOP back to 57A8H until the name is six characters long.
57AFH - Write to Tape: Header and Name
Waits for ENTER, then writes the leader, the sync byte, the 55H header byte and the six-character name.
57AF
GOSUB to 583AH. That address holds only a RET.
57B2
LD HL,5CC2H 21 C2 5C
Point Register Pair HL to the message REPLY ENTER WHEN TAPE POSITIONED AND IN RECORD MODE at 5CC2H.
57B5
GOSUB to 5893H to display it and read a reply.
57B8
If anything was typed before ENTER, JUMP back to 57B2H to ask again.
57BA
DI F3
Disable interrupts, because the ROM tape routines depend on exact timing loops.
57BB
GOSUB to the ROM routine at 0284H to turn on the cassette motor and write the leader and the A5H sync byte.
57BE
LD A,2AH 3E 2A
Load Register A with an asterisk (2AH), the sign that the tape is being written.
57C0
LD (3C3FH),A 32 3F 3C
Store Register A (2AH) into video memory at 3C3FH, the top right corner of the screen.
57C3
LD A,55H 3E 55
Load Register A with 55H, the byte that starts a SYSTEM tape.
57C5
GOSUB to the ROM routine at 0264H to write it.
57C8
POP HL E1
Restore the address of the name buffer (5E95H) into Register Pair HL.
57C9
LD B,06H 06 06
Load Register B with 06H, the number of name characters to write.
57CB
LD A,(HL) 7E
Fetch a character of the name at Register Pair HL into Register A.
57CC
INC HL 23
Bump Register Pair HL to the next character of the name.
57CD
GOSUB to the ROM routine at 0264H to write it to the tape.
57D0
DECrement Register B and LOOP back to 57CBH until all six characters are written.
57D2H - Write to Tape: the Records
Walks through the module buffer. Each object code record is written as a SYSTEM tape block: 3CH, the data byte count (00H = 256), the load address, the data and a checksum (the sum of the address bytes and the data). Marker records and record types other than 01H and 02H are not written. The transfer record ends the tape.
57D2
LD HL,5E9BH 21 9B 5E
Point Register Pair HL to 5E9BH, the first record in the module buffer.
57D5
LD A,(HL) 7E
Fetch the record type at Register Pair HL into Register A.
57D6
CP 01H FE 01
Compare Register A, the record type, against 01H (object code).
57D8
If Register A is 01H (the Z FLAG is set), JUMP to 57F0H to write a tape block.
57DA
CP 02H FE 02
Compare Register A, the record type, against 02H (transfer address).
57DC
If Register A is 02H (the Z FLAG is set), JUMP to 5827H to write the entry point block.
57DE
GOSUB to 5733H. A marker record is skipped (NC FLAG).
57E1
If it was a marker record, JUMP back to 57D5H.
57E3
INC HL 23
Any other record is skipped. Point Register Pair HL to the length byte.
57E4
LD C,(HL) 4E
Fetch the record's length byte at Register Pair HL into Register C.
57E5
LD B,00H 06 00
Set Register B to 00H, so Register Pair BC = the length.
57E7
INC HL 23
Point Register Pair HL to the first byte after the length.
57E8
LD A,C 79
Copy Register C, the length byte, into Register A.
57E9
OR A B7
OR Register A with itself to set the flags: Z means a length of 00H.
57EA
If the length is not zero (the NZ FLAG is set), JUMP to 57EDH.
57EC
INC B 04
INCrement Register B: a length of 00H means 256 bytes, so Register Pair BC = 0100H.
57ED
ADD HL,BC 09
Add Register Pair BC, the length, to Register Pair HL: Register Pair HL now points to the next record.
57EE
JUMP back to 57D5H to handle the next record.
57F0
LD A,3CH 3E 3C
Load Register A with 3CH, the byte that starts an object code block.
57F2
GOSUB to the ROM routine at 0264H to write it.
57F5
INC HL 23
Bump Register Pair HL to the record's length byte.
57F6
LD B,(HL) 46
Fetch the record's length byte at Register Pair HL into Register B.
57F7
DEC B 05
DECrement Register B once for the low address byte.
57F8
DEC B 05
DECrement Register B again: B = the number of data bytes (00H = 256).
57F9
INC HL 23
Bump Register Pair HL to the low byte of the load address.
57FA
LD A,B 78
Copy Register B, the data byte count, into Register A for writing.
57FB
GOSUB to the ROM routine at 0264H to write it.
57FE
LD E,(HL) 5E
Fetch the low byte of the load address at Register Pair HL into Register E.
57FF
INC HL 23
Bump Register Pair HL to the high byte of the load address.
5800
LD D,(HL) 56
Fetch the high byte of the load address at Register Pair HL into Register D.
5801
LD A,E 7B
Copy Register E, the low byte of the load address, into Register A for writing.
5802
INC HL 23
Point Register Pair HL to the first data byte.
5803
GOSUB to the ROM routine at 0264H to write the low byte of the load address.
5806
LD A,D 7A
Copy Register D, the high byte of the load address, into Register A for writing.
5807
GOSUB to the ROM routine at 0264H to write it.
580A
LD A,D 7A
Copy Register D, the high byte of the load address, into Register A for the checksum.
580B
ADD A,E 83
Add Register E, the low byte of the load address, to Register A.
580C
LD C,A 4F
Copy Register A into Register C, which starts the checksum with D + E.
580D
LD A,(HL) 7E
Fetch a data byte at Register Pair HL into Register A for writing.
580E
GOSUB to the ROM routine at 0264H to write it.
5811
LD A,(HL) 7E
Fetch the same data byte at Register Pair HL into Register A again, since the write changed Register A.
5812
ADD A,C 81
Add Register C, the checksum so far, to Register A, the data byte.
5813
LD C,A 4F
Copy Register A into Register C as the new checksum.
5814
INC HL 23
Bump Register Pair HL to the next data byte of the object code record.
5815
DECrement Register B and LOOP back to 580DH until all the data bytes are written. Register A = the checksum.
5817
GOSUB to the ROM routine at 0264H to write the checksum.
581A
GOSUB to 583BH to check the up-arrow key, which abandons the tape write.
581D
LD A,(3C3FH) 3A 3F 3C
Fetch the character at 3C3FH in video memory into Register A.
5820
XOR 0AH EE 0A
Exclusive OR Register A with 0AH, switching it between an asterisk (2AH) and a space (20H).
5822
LD (3C3FH),A 32 3F 3C
Store Register A back into video memory at 3C3FH, so the asterisk blinks once for each block.
5825
LOOP back to 57D5H to handle the next record.
5827
LD A,78H 3E 78
Load Register A with 78H, the byte that starts the entry point block.
5829
GOSUB to the ROM routine at 0264H to write it.
582C
INC HL 23
Bump Register Pair HL past the record type byte.
582D
INC HL 23
Bump Register Pair HL past the length byte, to the low byte of the entry point.
582E
LD A,(HL) 7E
Fetch the low byte of the entry point at Register Pair HL into Register A.
582F
INC HL 23
Bump Register Pair HL to the high byte of the entry point.
5830
GOSUB to the ROM routine at 0264H to write it.
5833
LD A,(HL) 7E
Fetch the high byte of the entry point at Register Pair HL into Register A.
5834
GOSUB to the ROM routine at 0264H to write it.
5837
JUMP to 5756H to display DONE. The cassette motor is turned off at 5862H.
583AH - Before a Tape Operation
Only a RET. It is called before the tape is read (53BFH) and before the operator is asked to ready the tape for writing (57AFH).
583A
RET C9
RETurn at once; the routine does nothing before a tape operation.
583BH - Check the Up-Arrow Key
Reads keyboard row 6 at 3840H. If the up-arrow key (bit 3) is down, the current function is abandoned with FUNCTION CANCELLED BY OPERATOR. This is a jump, not a return, so the caller's return address is left on the stack; 537CH resets the stack when a new source file is started. Called while the tape is read or written and after every line typed (58A2H).
583B
LD A,(3840H) 3A 40 38
Fetch keyboard row 6 at 3840H into Register A (ENTER, CLEAR, BREAK, up-arrow, down-arrow, left-arrow, right-arrow, space).
583E
AND 08H E6 08
AND Register A with 08H, keeping only bit 3, the up-arrow key.
5840
RET Z C8
If the up-arrow key is not pressed (the Z FLAG is set), RETurn to the caller.
5841
LD HL,5CF6H 21 F6 5C
Point Register Pair HL to the message FUNCTION CANCELLED BY OPERATOR at 5CF6H.
5844
JUMP to 585FH to display the message at Register Pair HL.
5846H - Error Exits
Each loads the address of a message and goes to 585FH. 5855H displays a DOS error instead.
5846
LD HL,5C69H 21 69 5C
Point Register Pair HL to the message BAD MAIN MEMORY at 5C69H (from 5739H).
5849
JUMP to 585FH to display the message at Register Pair HL.
584B
LD HL,5C01H 21 01 5C
Point Register Pair HL to the message SOURCE ILLEGAL LOAD-TO-MEMORY ADDRESS at 5C01H (from 549BH).
584E
JUMP to 585FH to display the message at Register Pair HL.
5850
LD HL,5BD0H 21 D0 5B
Point Register Pair HL to the message SOURCE MODULE BAD FORMAT at 5BD0H (from 5699H).
5853
JUMP to 585FH to display the message at Register Pair HL.
5855
OR C0H F6 C0
A DOS routine returned an error code in Register A. Set bits 6 and 7 of the code.
5857
GOSUB to the SYS0 routine at 4409H to display the DOS error message. It returns here.
585A
JUMP to 5862H to turn off the cassette motor and ask what to do next.
585C
LD HL,5BE9H 21 E9 5B
Point Register Pair HL to the message INSUFFICIENT RAM MEMORY at 5BE9H (from 5486H).
585FH - Display a Message and Ask What to Do Next
Every function ends here: after DONE, an error or a cancel. If a destination was being written, the operator can write the same module to another file; otherwise, or after N, the operator can start another source module or go back to DOS.
585F
GOSUB to the SYS0 routine at 4467H to display the message at Register Pair HL.
5862
GOSUB to the ROM routine at 01F8H to turn off the cassette motor.
5865
EI FB
Enable interrupts again, in case a tape operation disabled them.
5866
LD A,(5373H) 3A 73 53
Fetch the Output Phase Flag at 5373H into Register A.
5869
OR A B7
OR Register A with itself to set the flags: Z means no destination has been asked for yet.
586A
If no destination has been asked for yet, JUMP to 587FH.
586C
LD HL,5A70H 21 70 5A
Point Register Pair HL to the message ANOTHER DESTINATION FILE? (Y OR N) at 5A70H, which starts with a row of eleven asterisks.
586F
GOSUB to 5893H to display it and read a reply.
5872
DECrement Register B and LOOP back to 5866H unless the reply was exactly one character long.
5874
CP 4EH FE 4E
Compare Register A, the reply, against N (4EH).
5876
If Register A is N (the Z FLAG is set), JUMP to 587FH to ask about another source file.
5878
CP 59H FE 59
Compare Register A, the reply, against Y (59H).
587A
If it is neither, JUMP back to 5866H to ask again.
587C
JUMP to 56E6H to ask for another destination for the same module.
587F
LD HL,5AA0H 21 A0 5A
Point Register Pair HL to the message ANOTHER SOURCE FILE TO PROCESS? (Y OR N) at 5AA0H.
5882
GOSUB to 5893H to display it and read a reply.
5885
DECrement Register B and LOOP back to 587FH unless the reply was exactly one character long.
5887
CP 59H FE 59
Compare Register A, the reply, against Y (59H).
5889
If Register A is Y (the Z FLAG is set), JUMP to 537CH to start again.
588C
CP 4EH FE 4E
Compare Register A, the reply, against N (4EH).
588E
If it is neither, JUMP back to 587FH to ask again.
5890
JUMP to 402DH in SYS0 to return to the DOS command level.
5893H - Display a Message and Read a Reply
5893H displays the message at Register Pair HL and reads up to 64 characters into the buffer at 5332H. 589BH reads a line into the buffer at Register Pair HL with the maximum length in Register A. BREAK makes it read the line again; the up-arrow key is checked after every line (583BH). Lower case letters are changed to capitals. Returns Register Pair HL = the buffer, Register B = the number of characters typed, Register A = the first character and the Z FLAG set if nothing was typed.
5893
GOSUB to the SYS0 routine at 4467H to display the message.
5896
LD HL,5332H 21 32 53
Point Register Pair HL to the input buffer at 5332H (just below the program).
5899
LD A,40H 3E 40
Load Register A with 40H, the maximum length (64 characters).
589B
LD B,A 47
Copy Register A, the maximum length, into Register B for the ROM line input.
589C
PUSH HL E5
Save Register Pair HL, the buffer address, on the stack.
589D
PUSH BC C5
Save Register Pair BC, holding the maximum length in Register B, on the stack.
589E
GOSUB to the ROM routine at 0040H to read a line from the keyboard into the buffer. It returns Register B = the number of characters typed and the CARRY FLAG set if BREAK was pressed.
58A1
PUSH AF F5
Save Register Pair AF on the stack; the CARRY FLAG in Register F means BREAK was pressed.
58A2
GOSUB to 583BH to check the up-arrow key, which abandons the current function.
58A5
POP AF F1
Restore Register Pair AF from the stack, with the CARRY FLAG from the ROM line input.
58A6
LD A,B 78
Copy Register B, the number of characters typed, into Register A.
58A7
POP BC C1
Restore Register Pair BC, holding the maximum length in Register B, from the stack.
58A8
POP HL E1
Restore Register Pair HL, the buffer address, from the stack.
58A9
If BREAK was pressed, JUMP back to 589CH to read the line again.
58AB
PUSH HL E5
Save Register Pair HL, the buffer address, on the stack.
58AC
LD B,A 47
Copy Register A, the number of characters typed, into Register B.
58AD
LD A,(HL) 7E
Fetch a character of the reply at Register Pair HL into Register A.
58AE
SUB 61H D6 61
Subtract a (61H) from Register A, so the letters a-z give 00H-19H.
58B0
CP 1AH FE 1A
Compare Register A against 1AH: the CARRY FLAG is set for a-z.
58B2
If it is not a lower case letter, JUMP to 58B7H.
58B4
ADD A,41H C6 41
Add A (41H) to Register A, giving the capital letter.
58B6
LD (HL),A 77
Store Register A, the capital letter, back at Register Pair HL.
58B7
LD A,(HL) 7E
Fetch the character at Register Pair HL into Register A again.
58B8
CP 0DH FE 0D
Compare Register A against a carriage return (0DH), which ends the line.
58BA
INC HL 23
Bump Register Pair HL to the next character of the reply.
58BB
LOOP back to 58ADH until the carriage return.
58BD
POP HL E1
Restore Register Pair HL, the buffer address, from the stack.
58BE
LD A,(HL) 7E
Fetch the first character of the reply at Register Pair HL into Register A.
58BF
CP 0DH FE 0D
Compare Register A against a carriage return (0DH): the Z FLAG is set when nothing was typed.
58C1
RET C9
RETurn with Register A = the first character, Register B = the length and the Z FLAG set for an empty reply.
58C2H - Appendage: First Record Header and Patch Area
The appendage is kept here as ready-made load module records. This header starts its first object code record: type 01H, the length byte and the load address. The length is 50H for the DOS-enabled appendage (5D15H) and C1H for the DOS-disabled one (568DH); the load address is filled in at 5656H. 56CDH copies these four bytes and the 64 patch bytes after them into the module buffer. See The Appendages.
58C2
DEFB 01H 01
Record type 01H (object code) of the appendage's first record.
58C3
DEFB 50H 50
Length byte: 50H (78 data bytes) for the DOS-enabled appendage, changed to C1H (191 data bytes) for the DOS-disabled one.
58C4-58C5
DEFW 0000H 00 00
Load address of the appendage, set at 5656H to the byte after the module's new last byte.
58C6H - Appendage Patch Area
Not part of the file: the file has no load record for 58C6H-5905H. 5388H sets these 64 bytes to zero, and they become the first 64 bytes of every appendage. The manual describes them as a patch area: code patched in here runs first when the output module is started, before the program is moved and before DOS is disabled.
58C6-5905
DEFS 64
Patch Area: 64 bytes, cleared at 5388H, that become the first 64 bytes of every appendage.
5906H - DOS-Disabled Appendage: Save the Screen and Show the Instructions
This code is not run here. From 5906H to 5A00H it is copied into the module being written (56DEH-56E3H), where it runs at X+40H, X being the appendage's load address. The zero operands are filled in at 5664H-5687H. It saves the screen above the appendage, puts a jump at 42E9H (the start of the non-disk BASIC program area), shows the instructions and waits in a loop for the operator to reset the computer into non-disk BASIC.
5906
LD DE,0000H 11 00 00
Point Register Pair DE to X+137H, the byte after the appendage, where the screen is saved. The operand 0000H is filled in at 5687H.
5909
LD HL,3C00H 21 00 3C
Point Register Pair HL to the start of the screen at 3C00H.
590C
LD BC,0400H 01 00 04
Load Register Pair BC with 0400H (1,024 bytes).
590F
LDIR ED B0
Copy Register Pair BC (0400H) bytes from Register Pair HL (3C00H) to Register Pair DE (X+137H), saving the screen above the appendage.
5911
LD HL,0000H 21 00 00
Point Register Pair HL to X+5EH, where the six bytes from 5924H are. The operand 0000H is filled in at 5668H.
5914
LD DE,42E9H 11 E9 42
Point Register Pair DE to 42E9H, the start of the program area of non-disk BASIC.
5917
LD BC,0006H 01 06 00
Load Register Pair BC with 0006H, the six bytes to copy to 42E9H.
591A
LDIR ED B0
Copy Register Pair BC (0006H) bytes from Register Pair HL (X+5EH) to Register Pair DE (42E9H): three NOPs and a jump to the rest of the appendage.
591C
LD HL,0000H 21 00 00
Point Register Pair HL to X+64H, where the message from 592AH is. The operand 0000H is filled in at 566FH.
591F
GOSUB to the SYS0 routine at 4467H to display the instructions. DOS is still in memory at this point.
5922
JUMP to this same instruction (5922H in this copy) for ever. The operator now holds BREAK and presses RESET.
The six bytes copied to 42E9H-42EEH. The displayed instructions end with SYSTEM and /; this jump is where the appendage expects execution to continue.
5924
NOP 00
No operation. This byte is copied to 42E9H, the first byte of the program area of non-disk BASIC.
5925
NOP 00
No operation. This byte is copied to 42EAH, the second byte of the program area of non-disk BASIC.
5926
NOP 00
No operation. This byte is copied to 42EBH, the third byte of the program area of non-disk BASIC.
5927
JUMP to X+11EH, where the code from 59E8H is. The operand 0000H is filled in at 567DH; the jump runs from 42ECH.
592AH - DOS-Disabled Appendage: Instructions to the Operator
Displayed by 591FH. The text is split between the appendage's two records: 5985H-5988H in the middle is the header of the second record, which is not part of the text once the records are loaded. The manual gives the message as RECORD AND THEN PERFORM THE FOLLOWING INSTRUCTIONS and step 4 as ENTER "."; the file has DO THE FOLLOWING: and ENTER "/".
592A-592B
DEFB 1CH,1FH 1C 1F
Cursor home (1CH) and clear to the end of the screen (1FH).
592C-593C
DEFM "DO THE FOLLOWING:" 44 4F 20 54 48 45 20 46 4F 4C 4C 4F 57 49 4E 47 3A
The heading of the screen the DOS-disabled appendage shows: DO THE FOLLOWING:.
593D-593E
DEFB 0AH,0AH 0A 0A
Two line feeds (0AH), leaving a blank line under the heading.
593F-5979
DEFM "1. HOLD DOWN BREAK KEY AND PRESS RESET TO ACTIVATE NON-DISK" 31 2E 20 48 4F 4C 44 20 44 4F 57 4E 20 42 52 45 41 4B 20 4B 45 59 20 41 4E 44 20 50 52 45 53 53 20 52 45 53 45 54 20 54 4F 20 41 43 54 49 56 41 54 45 20 4E 4F 4E 2D 44 49 53 4B
Instruction line 1 of the DOS-disabled appendage: hold down BREAK and press RESET to activate non-disk BASIC.
597A
DEFB 0AH 0A
Line feed (0AH) ending instruction line 1 of the DOS-disabled appendage.
597B-5984
DEFM " BASIC." / DEFB 0AH 20 20 20 42 41 53 49 43 2E 0A
The last byte of the first record is the line feed at 5984H.
5985H - DOS-Disabled Appendage: Second Record Header
The second object code record of the DOS-disabled appendage: type 01H, length 7AH (120 data bytes: 5989H-5A00H) and the load address X+BFH, filled in at 5676H. 56E1H-56E3H copies this header, the record and the transfer record after it.
5985
DEFB 01H 01
Record type 01H (object code) of the appendage's second record.
5986
DEFB 7AH 7A
Length byte: 120 data bytes and 2 address bytes.
5987-5988
DEFW 0000H 00 00
Load address of the second record, set at 5676H to X+BFH.
5989H - DOS-Disabled Appendage: Instructions, Continued
The rest of the message started at 592AH, ended by a carriage return.
5989-59C6
DEFM "2. RELEASE BREAK KEY AND INPUT BASIC INITIALIZATION RESPONSES." 32 2E 20 52 45 4C 45 41 53 45 20 42 52 45 41 4B 20 4B 45 59 20 41 4E 44 20 49 4E 50 55 54 20 42 41 53 49 43 20 49 4E 49 54 49 41 4C 49 5A 41 54 49 4F 4E 20 52 45 53 50 4F 4E 53 45 53 2E
Instruction line 2 of the DOS-disabled appendage: release BREAK and answer the BASIC initialization questions.
59C7
DEFB 0AH 0A
Line feed (0AH) ending instruction line 2 of the DOS-disabled appendage.
59C8-59D9
DEFM "3. ENTER ", 22H, "SYSTEM", 22H, "." 33 2E 20 45 4E 54 45 52 20 22 53 59 53 54 45 4D 22 2E
Instruction line 3 of the DOS-disabled appendage: type SYSTEM (the quotes are part of the text).
59DA
DEFB 0AH 0A
Line feed (0AH) ending instruction line 3 of the DOS-disabled appendage.
59DB-59E7
DEFM "4. ENTER ", 22H, "/", 22H, 0DH 34 2E 20 45 4E 54 45 52 20 22 2F 22 0D
Instruction line 4 of the DOS-disabled appendage: type / (the quotes are part of the text), ended by a carriage return.
59E8H - DOS-Disabled Appendage: Restore the Screen
Reached through the jump at 42ECH after the operator has started non-disk BASIC and answered SYSTEM with /. Runs at X+11EH. Copies the saved screen back and falls into the move code.
59E8
LD HL,0000H 21 00 00
Point Register Pair HL to X+137H, where the screen was saved. The operand 0000H is filled in at 5684H.
59EB
LD DE,3C00H 11 00 3C
Point Register Pair DE to the start of the screen at 3C00H.
59EE
LD BC,0400H 01 00 04
Load Register Pair BC with 0400H (1,024 bytes).
59F1
LDIR ED B0
Copy Register Pair BC (0400H) bytes from Register Pair HL (X+137H) to Register Pair DE (3C00H), putting the saved screen back.
59F3H - Appendage: Move the Program and Start It
The end of both appendages. In the DOS-enabled appendage it runs at X+40H, straight after the patch area; in the DOS-disabled one it follows 59F1H. Moves the program from where the output module loads it back to its original addresses and jumps to the original entry point. The operands are filled in at 55ECH and 569FH-56BAH.
59F3
LD HL,0000H 21 00 00
Point Register Pair HL to the first byte of the program as loaded (the new start), or its last byte when LDDR is used. The operand 0000H is filled in at 56B7H.
59F6
LD DE,0000H 11 00 00
Point Register Pair DE to the first byte of the original load address, or its last byte for LDDR. The operand 0000H is filled in at 56BAH.
59F9
LD BC,0000H 01 00 00
Load Register Pair BC with the size of the program. The operand 0000H is filled in at 569FH.
59FC
LDIR ED B0
Copy Register Pair BC bytes from Register Pair HL to Register Pair DE, moving the program to its original address. The second byte is B0H (LDIR) or B8H (LDDR), set at 56B4H.
59FE
JUMP to the program's original entry point. The operand 0000H is filled in at 55ECH.
The appendage's transfer record, copied with the move code. It becomes the output module's entry point.
5A01
DEFB 02H 02
Record type 02H (transfer address) of the appendage's transfer record.
5A02
DEFB 02H 02
Length byte: 02H, the two bytes of the entry point.
5A03-5A04
DEFW 0000H 00 00
The entry point: the appendage's load address X, set at 55A6H.
5A05H - Convert a Hexadecimal Number
Converts the characters at Register Pair DE into Register Pair HL. Register A = the number of characters. Returns the CARRY FLAG set if there are more than four characters or one of them is not 0-9 or A-F. Used for the new load base (55C0H).
5A05
LD B,A 47
Copy Register A, the number of characters, into Register B as the loop counter.
5A06
ADD A,FBH C6 FB
Add FBH to Register A: the CARRY FLAG is set if there are five or more characters.
5A08
RET C D8
If there are, RETurn with the CARRY FLAG set.
5A09
LD HL,0000H 21 00 00
Set Register Pair HL, the value being built, to 0000H.
5A0C
ADD HL,HL 29
Add Register Pair HL to itself, shifting it left one bit (first of four shifts for the next digit).
5A0D
ADD HL,HL 29
Add Register Pair HL to itself, shifting it left one bit (second of four shifts).
5A0E
ADD HL,HL 29
Add Register Pair HL to itself, shifting it left one bit (third of four shifts).
5A0F
ADD HL,HL 29
Add Register Pair HL to itself, shifting it left one bit; the low four bits are now free for the next digit.
5A10
LD A,(DE) 1A
Fetch the next character at Register Pair DE into Register A.
5A11
SUB 30H D6 30
Subtract the character 0 (30H) from Register A.
5A13
CP 0AH FE 0A
Compare Register A against 0AH: the CARRY FLAG is set for 0-9.
5A15
INC DE 13
Bump Register Pair DE to the next character of the reply.
5A16
If it is a digit, JUMP to 5A20H with its value in Register A.
5A18
SUB 11H D6 11
Subtract 11H more from Register A, so it now holds the character minus A (41H).
5A1A
CP 06H FE 06
Compare Register A against 06H: the CARRY FLAG is set for A-F.
5A1C
CCF 3F
Reverse the CARRY FLAG: it is now set if the character is not A-F.
5A1D
RET C D8
If it is not, RETurn with the CARRY FLAG set.
5A1E
ADD A,0AH C6 0A
Add 0AH to Register A, giving the digit values 0AH-0FH for A-F.
5A20
OR L B5
OR Register A, the digit, with Register L, merging it into the low four bits. This also clears the CARRY FLAG.
5A21
LD L,A 6F
Copy Register A back into Register L, the low byte of the value.
5A22
DECrement Register B, the characters left, and LOOP back to 5A0CH for the next character.
5A24
RET C9
RETurn with the value in Register Pair HL and the CARRY FLAG clear.
5A25H - Write a Hexadecimal Number
5A25H writes Register Pair DE as four hexadecimal characters at HL, 5A2AH writes Register A as two and 5A33H writes the low four bits of Register A as one. Register Pair HL is left pointing past the last character. Used to fill in the XXXX fields of the messages.
5A25
LD A,D 7A
Load Register A with the high byte, Register D.
5A26
GOSUB to 5A2AH to write it as two characters.
5A29
LD A,E 7B
Load Register A with the low byte, Register E, and fall into 5A2AH.
5A2A
PUSH AF F5
Save Register Pair AF, holding the byte in Register A, on the stack for the low digit.
5A2B
RRCA 0F
Rotate Register A right one bit (first of four rotations moving the high four bits down).
5A2C
RRCA 0F
Rotate Register A right one bit (second of four rotations).
5A2D
RRCA 0F
Rotate Register A right one bit (third of four rotations).
5A2E
RRCA 0F
Rotate Register A right one bit; the high four bits are now in the low four bits.
5A2F
GOSUB to 5A33H to write the low four bits of Register A, the high digit, at Register Pair HL.
5A32
POP AF F1
Restore Register Pair AF, putting the byte back in Register A, and fall into 5A33H to write the low digit.
5A33
AND 0FH E6 0F
AND Register A with 0FH, keeping only the low four bits.
5A35
ADD A,90H C6 90
Add 90H to Register A, the first step of the digit to character conversion.
5A37
DAA 27
Decimal adjust Register A: 90H-99H for 0-9, and 00H-05H with the CARRY FLAG set for 0AH-0FH.
5A38
ADC A,40H CE 40
Add 40H and the CARRY FLAG to Register A, the second step of the conversion.
5A3A
DAA 27
Decimal adjust Register A again, giving 0-9 (30H-39H) or A-F (41H-46H).
5A3B
LD (HL),A 77
Store Register A, the character, at Register Pair HL.
5A3C
INC HL 23
Bump Register Pair HL to the next character position.
5A3D
RET C9
RETurn with Register Pair HL pointing past the character written.
5A3EH - Messages
All displayed through the SYS0 routine at 4467H. Messages ended by 03H leave the cursor on the same line for the reply; those ended by 0DH end the line. The XXXX fields are filled in by 5A25H before the message is shown.
5A3E-5A3F
DEFB 1CH,1FH 1C 1F
Cursor home and clear to the end of the screen: the title starts on a clear screen.
5A40-5A6F
DEFM "APPARAT LOAD MODULE OFFSET PROGRAM, VERSION 2.0" / DEFB 0DH 41 50 50 41 52 41 54 20 4C 4F 41 44 20 4D 4F 44 55 4C 45 20 4F 46 46 53 45 54 20 50 52 4F 47 52 41 4D 2C 20 56 45 52 53 49 4F 4E 20 32 2E 30 0D
The title of the program, displayed at 53A6H on a cleared screen.
5A70-5A9F
DEFM 2AH x 11, " ANOTHER DESTINATION FILE? (Y OR N) ", 03H 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 20 41 4E 4F 54 48 45 52 20 44 45 53 54 49 4E 41 54 49 4F 4E 20 46 49 4C 45 3F 20 28 59 20 4F 52 20 4E 29 20 03
Asked at 586CH after a destination has been written or has failed.
5AA0-5ACA
DEFM "ANOTHER SOURCE FILE TO PROCESS? (Y OR N) " / DEFB 03H 41 4E 4F 54 48 45 52 20 53 4F 55 52 43 45 20 46 49 4C 45 20 54 4F 20 50 52 4F 43 45 53 53 3F 20 20 28 59 20 4F 52 20 4E 29 20 03
Asked at 587FH when the operator has finished with a source module.
5ACB-5AEF
DEFM "SOURCE FROM DISK OR TAPE? (D OR T) " / DEFB 03H 53 4F 55 52 43 45 20 46 52 4F 4D 20 44 49 53 4B 20 4F 52 20 54 41 50 45 3F 20 20 28 44 20 4F 52 20 54 29 20 03
Asked at 53A9H at start-up: where the source module comes from.
5AF0-5B14
DEFM "DESTINATION DISK OR TAPE? (D OR T) " / DEFB 03H 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 20 4F 52 20 54 41 50 45 3F 20 20 28 44 20 4F 52 20 54 29 20 03
Asked at 56EBH: where the offset module is to be written.
5B15-5B26
DEFM "SOURCE FILESPEC? " / DEFB 03H 53 4F 55 52 43 45 20 46 49 4C 45 53 50 45 43 3F 20 03
Asked at 54DCH for the name of the source load module file.
5B27-5B3D
DEFM "DESTINATION FILESPEC? " / DEFB 03H 44 45 53 54 49 4E 41 54 49 4F 4E 20 46 49 4C 45 53 50 45 43 3F 20 03
Asked at 56FCH for the name of the file to write.
5B3E-5B57
DEFM "MODULE LOADS TO XXXX-XXXX" / DEFB 0DH 4D 4F 44 55 4C 45 20 4C 4F 41 44 53 20 54 4F 20 58 58 58 58 2D 58 58 58 58 0D
Displayed at 5579H. The first XXXX (5B4EH) is the start address, the second (5B53H) the end address.
5B58-5B7C
DEFM "MODULE LOAD OVERLAPS DOS (4000-51FF)" / DEFB 0DH 4D 4F 44 55 4C 45 20 4C 4F 41 44 20 4F 56 45 52 4C 41 50 53 20 44 4F 53 20 28 34 30 30 30 2D 35 31 46 46 29 0D
Displayed at 5591H when the new start address is 51FFH or lower.
5B7D-5B9A
DEFM "NEW LOAD BASE ADDRESS (HEX)? " / DEFB 03H 4E 45 57 20 4C 4F 41 44 20 42 41 53 45 20 41 44 44 52 45 53 53 20 28 48 45 58 29 3F 20 03
Asked at 55B6H; ENTER alone accepts the load base shown.
5B9B-5BB7
DEFM "MODULE LOAD WILL OVERLAP ROM" / DEFB 0DH 4D 4F 44 55 4C 45 20 4C 4F 41 44 20 57 49 4C 4C 20 4F 56 45 52 4C 41 50 20 52 4F 4D 0D
Displayed at 5587H when the new start address is 3FFFH or lower.
5BB8-5BCF
DEFM "DISABLE DOS? (Y OR N) " / DEFB 03H 44 49 53 41 42 4C 45 20 44 4F 53 3F 20 20 28 59 20 4F 52 20 4E 29 20 03
Asked at 5645H when an appendage is to be attached.
5BD0-5BE8
DEFM "SOURCE MODULE BAD FORMAT" / DEFB 0DH 53 4F 55 52 43 45 20 4D 4F 44 55 4C 45 20 42 41 44 20 46 4F 52 4D 41 54 0D
Error message displayed from 5850H when no object code loads at 4000H or above.
5BE9-5C00
DEFM "INSUFFICIENT RAM MEMORY" / DEFB 0DH 49 4E 53 55 46 46 49 43 49 45 4E 54 20 52 41 4D 20 4D 45 4D 4F 52 59 0D
Error message displayed from 585CH when the module buffer reaches the top of memory.
5C01-5C26
DEFM "SOURCE ILLEGAL LOAD-TO-MEMORY ADDRESS" / DEFB 0DH 53 4F 55 52 43 45 20 49 4C 4C 45 47 41 4C 20 4C 4F 41 44 2D 54 4F 2D 4D 45 4D 4F 52 59 20 41 44 44 52 45 53 53 0D
Error message displayed from 584BH for a record below 3C00H or one running past 3FFFH.
5C27-5C2B
DEFM "DONE" / DEFB 0DH 44 4F 4E 45 0D
Displayed at 5756H when the destination is written.
5C2C-5C3E
DEFM "ENTRY POINT = XXXX" / DEFB 0DH 45 4E 54 52 59 20 50 4F 49 4E 54 20 3D 20 58 58 58 58 0D
Displayed at 55B0H. The XXXX at 5C3AH is filled in with the new entry point.
5C3F-5C68
DEFM "SHALL APPENDAGE BE SUPPRESSED? (Y OR N) " / DEFB 03H 53 48 41 4C 4C 20 41 50 50 45 4E 44 41 47 45 20 42 45 20 53 55 50 50 52 45 53 53 45 44 3F 20 20 28 59 20 4F 52 20 4E 29 20 03
Asked at 55CFH after a new load base has been given.
5C69-5C78
DEFM "BAD MAIN MEMORY" / DEFB 0DH 42 41 44 20 4D 41 49 4E 20 4D 45 4D 4F 52 59 0D
Error message displayed from 5846H for a record type of 20H-FDH in the module buffer.
5C79-5C99
DEFM "INPUT 1-6 CHAR TAPE MODULE NAME." / DEFB 0AH 49 4E 50 55 54 20 31 2D 36 20 43 48 41 52 20 54 41 50 45 20 4D 4F 44 55 4C 45 20 4E 41 4D 45 2E 0A
Asked at 577AH. The line feed starts the second line.
5C9A-5CC1
DEFM "1ST CHAR MUST BE A-Z; OTHERS A-Z OR 0-9" / DEFB 0DH 31 53 54 20 43 48 41 52 20 4D 55 53 54 20 42 45 20 41 2D 5A 3B 20 4F 54 48 45 52 53 20 41 2D 5A 20 4F 52 20 30 2D 39 0D
The second line of the tape module name question, the rules for the name characters; ended by 0DH.
5CC2-5CF5
DEFM "REPLY ENTER WHEN TAPE POSITIONED AND IN RECORD MODE" / DEFB 03H 52 45 50 4C 59 20 45 4E 54 45 52 20 57 48 45 4E 20 54 41 50 45 20 50 4F 53 49 54 49 4F 4E 45 44 20 41 4E 44 20 49 4E 20 52 45 43 4F 52 44 20 4D 4F 44 45 03
Asked at 57B2H before the tape is written; only ENTER is accepted.
5CF6-5D14
DEFM "FUNCTION CANCELLED BY OPERATOR" / DEFB 0DH 46 55 4E 43 54 49 4F 4E 20 43 41 4E 43 45 4C 4C 45 44 20 42 59 20 4F 50 45 52 41 54 4F 52 0D
Displayed at 5841H when the up-arrow key is pressed.
5D15H - Reset the Appendage Length and Point to the Title
Called once at start-up (53A3H). Sets the length byte of the appendage's first record back to 50H, the DOS-enabled size, because 568DH changes it to C1H when DOS is to be disabled. Returns Register Pair HL pointing to the title.
5D15
LD A,50H 3E 50
Load Register A with 50H, the length byte for the DOS-enabled appendage.
5D17
LD (58C3H),A 32 C3 58
Store Register A (50H) as the length byte of the appendage's first record at 58C3H.
5D1A
LD HL,5A3EH 21 3E 5A
Point Register Pair HL to the title at 5A3EH.
5D1D
RET C9
RETurn with Register Pair HL pointing to the title at 5A3EH.
5D1EH - Unused Bytes
The last 100 bytes of the file are zero and nothing refers to them.
5D1E-5D81
DEFB 00H x 100 00 x 100
Unused zero bytes at the end of the file; nothing refers to them.