TRS-80 DOS - NEWDOS/80 v2.0 for the Model I - SYS19/SYS Disassembled

Page Customization

Introduction/Summary

NEWDOS/80 v2.0 SYS19/SYS Disassembly - BASIC LOAD, RUN, MERGE, SAVE and CMD"F",DELETE (Model I)

SYS19/SYS moves BASIC programs between memory and the diskette: LOAD and RUN with a file name (with the R and V options), MERGE, SAVE (as memory image or, with A, as text) and CMD"F",DELETE. It is one of the three BASIC overlays that load at 5200H, here 5200H-56E7H (1,256 bytes in five load records, transfer address 5200H); 5651H-56E7H are unused zero bytes. BASIC loads it with RST 28H code 35H (function 1 of directory slot 15H) through its overlay loader at 576CH, after opening the file in its work area at 5700H (the FCB at 570DH, the sector buffer at 4200H).

The page shows every byte of the file once, in address order. Calls into BASIC/CMD are linked only where the BASIC page has a row with the right bytes at that address.

Entry Points

AddressFrom BASICStatement
5202H574FHLOAD "file"[,R | ,V] (vector 4188H) and RUN "file"[,R | ,V] (link 41C7H) (5202H).
5334H5731HMERGE "file" (vector 418BH) (5334H).
559CH5736HCMD"F",DELETE range (559CH).
55C5H5741HSAVE "file"[,A] (vector 41A0H) (55C5H).

Variables

Locations inside SYS19 whose contents change while it runs (operands written by the code itself; 0000H or 00H in the file):

Address RangePurpose
5255H
1 byte
Opcode written at 5228H: 18H (JR 526BH, clear the program and variables) or 3EH (LD A,nn, option V keeps them).
5315H
1 byte
Mode after the load: 0 LOAD or MERGE as a command, 1 RUN, 2 MERGE in a program (operand of 5314H; written at 5220H and 5355H).
53DCH-53DDH
2 bytes
Address of the next old line not yet merged (operand of 53DBH; written at 52B2H, 53EEH and 54C8H).
5429H-542AH
2 bytes
The address the next old line had before the program was moved up; the start of the range of string pointers still to move (operand of 5428H; written at 52C3H, 5437H and 54CEH).
5442H-5443H
2 bytes
The program pointer, where the next line of the new program goes (operand of 5441H; written at 52E6H, 535FH, 5408H and 54D2H).
5459H-545AH
2 bytes
Size of the simple variables (operand of 5458H; written at 54AEH).
5466H-5467H
2 bytes
Size of the arrays (operand of 5465H; written at 549FH).
547FH-5480H
2 bytes
The program pointer when the last old line was placed (operand of 547EH; written at 52C6H, 5404H and 54CBH).
5488H-5489H
2 bytes
Start of the simple variables before the move, the end of the range of string pointers to move (operand of 5487H; written at 54A7H).
54F0H-54F1H
2 bytes
Return address of 54DFH, kept while STKINI resets the stack (operand of the JP at 54EFH; written at 54E6H).
5565H-5566H
2 bytes
End of the range 54F2H works on (operand of 5564H; written at 54F8H).
556CH-556DH
2 bytes
Start of that range (operand of 556BH; written at 54F5H).
5574H
1 byte
54F2H's mode: 0 copy the strings into the string space, other values move them by 557AH (operand of 5573H; written at 54F2H).
5576H
1 byte
Length of the string being fixed, 0 for a DEF FN pointer (operand of 5575H; written at 5560H).
557AH-557BH
2 bytes
Distance the old lines not yet copied have moved since the last old line was placed (operand of 5579H; written at 5484H).
5642H-5643H
2 bytes
Offset: the total distance applied so far, added to both ends of the range (operand of 5641H; written at 5623H, 5632H and 563AH).

Locations outside SYS19 that it reads or writes:

Address RangePurpose
40A2H-40A3H
2 bytes
The ROM's current line number (FFFFH for a direct command), read by MERGE (5334H).
40A4H-40A5H
2 bytes
The ROM's pointer to the start of the program, where the new program is built.
40A7H-40A8H
2 bytes
The ROM's pointer to the input buffer, where a text file's lines are collected (5368H).
40F0H-40F1H
2 bytes
The ROM's ON ERROR GOTO address, cleared at 54E2H.
40F9H-40FEH
6 bytes
The ROM's pointers to the start of the simple variables, the start of the arrays and the end of the arrays; moved and rewritten by the load.
4200H-42FFH
256 bytes
The FCB's sector buffer, from which a tokenized file is read.
4312H
1 byte
Opcode of SYS0's BREAK hook: C9H (RET, BREAK enabled) or C3H (JP 45B0H, BREAK disabled), written at 5252H.
4369H
1 byte
SYS0's system state; bit 6 set at 5277H (an overlay function is running).
436CH
1 byte
SYS0's SYSTEM options; bit 6 = AB (RUN ONLY), read at 5234H.
570DH-572DH
33 bytes
The FCB of the file (in BASIC's work area at 5700H, Index Register IX = 5700H): +1 access level (570EH), +3/+4 buffer address (5710H-5711H), +5 byte position (5712H), NEXT (5717H).
57B8H-57B9H
2 bytes
Number of the line after the statement, stored by BASIC 5D9FH and read at 5322H.
5FCFH
1 byte
First instruction of BASIC's close-all-files routine: C8H (RET Z) normally, C9H (RET) for R and V, written at 5224H.
6421H
1 byte
BASIC's RUN ONLY flag, written at 524EH.
644EH-644FH
2 bytes
Operand of the CALL at BASIC 644DH in the statement-end clean-up: 543EH during the load (52DAH), 64BDH again after it (BASIC 64BEH).

How a Program Is Loaded

The program in memory and its variables are first moved up to just below the stack (160 bytes of room are kept). The file's lines, tokenized (the file starts with FFH) or text (tokenized by the ROM's CRUNCH as they are read), are then built up from the program's start, and the old lines are copied in among them by line number (53B4H): for LOAD and RUN the old program has been cleared first (NEW), so only MERGE and the V option keep old lines or variables. At the end the rest of the old lines and the variables are moved down behind the new program and the line links are rebuilt (543EH). String variables whose text lies in a program line are kept valid (54F2H): copied to the string space when their line is deleted, moved when the line moves. If an error stops the load, BASIC's end of statement (6445H) calls 543EH so that memory is put back in order.

R also leaves the open files open (BASIC 5FCFH made a RET). A program with the access level EXEC can be RUN but not LOADed; RUNning it sets BASIC to RUN ONLY and disables BREAK. MERGE in a running program may not replace existing lines (ILLEGAL FUNCTION CALL) and continues with the line after the statement, as CMD"F",DELETE does.

Disassembly

5200H - Load Entry

BASIC/CMD loads SYS19 through its overlay loader at 576CH with RST 28H code 35H (function 1 of directory slot 15H) into 5200H-56E7H. After loading, the SYS0 dispatcher calls 5200H, which must return with the Z FLAG set (no error); BASIC/CMD then jumps to the entry address it put in Register Pair BC (5202H, 5334H, 559CH or 55C5H).

5200
CP A BF
Compare Register A with itself. The result is always equal, so the Z FLAG is set: the load succeeded with no error.
5201
RET C9
RETURN to the SYS0 dispatcher with the Z FLAG set, which tells BASIC/CMD's loader the overlay is in place.

5202H - LOAD and RUN with a File Name

Entered from BASIC 574FH for LOAD "file" (BASIC 574AH, the ROM vector 4188H, Register A = 0) and RUN "file" (BASIC 5746H, the ROM link 41C7H, Register A = 1). BASIC has opened the file in its work area 5700H-572DH (BASIC 609AH; Index Register IX = 5700H, the FCB at 570DH, its sector buffer at 4200H) and pushed Register Pair AF. Options after the name: R (run it, and leave the open files open) and V (run it and keep the variables). A program whose access level is EXEC can be RUN but not LOADed: it is read at level READ, BREAK is disabled and BASIC is set to RUN ONLY. Register Pair HL is BASIC's text pointer after the file name.

5202
LD BC,18C8H 01 C8 18
Load Register Pair BC with 18C8H: Register B = 18H, the opcode JR, for 5255H (the program is cleared); Register C = C8H, the opcode RET Z, for BASIC 5FCFH (open files are closed as usual).
5205
POP DE D1
Restore Register Pair DE from the stack: Register D = the Register A BASIC pushed, 00H for LOAD or 01H for RUN.
5206
CALL 638FH CD 8F 63
GOSUB to BASIC 638FH, which returns with the Z FLAG set if the statement ends at Register Pair HL; otherwise it requires a comma and returns Register A = the next character (the option letter).
5209
If the Z FLAG is set (no option), JUMP to 521AH.
520B
CP 52H FE 52
Compare Register A (the option letter) against 52H, the letter R.
520D
If the Z FLAG is set (option R), JUMP to 5215H.
520F
CP 56H FE 56
Compare Register A (the option letter) against 56H, the letter V.
5211
If the NZ FLAG is set (neither R nor V), JUMP to 521AH, where the leftover character gives SYNTAX ERROR.
5213
LD B,3EH 06 3E
Option V: load Register B with 3EH, the opcode LD A,nn: at 5255H the jump becomes a harmless load, so the variables are kept.
5215
LD C,C9H 0E C9
Options R and V: load Register C with C9H, the opcode RET, for BASIC 5FCFH: BASIC's close-all-files routine then closes nothing.
5217
LD D,01H 16 01
Load Register D with 01H: R and V both run the program.
5219
INC HL 23
Increment Register Pair HL (the text pointer) past the option letter.
521A
DEC HL 2B
Decrement Register Pair HL so the RST 10H that follows fetches the current character again.
521B
RST 10H D7
RST 10H: move Register Pair HL on and load Register A with the character. The Z FLAG is set at the end of the statement.
521C
If the NZ FLAG is set (something else follows), JUMP to the ROM's SNERR at 1997H to report SYNTAX ERROR.
521F
LD A,D 7A
Load Register A with Register D, the mode: 00H load, 01H run.
5220
LD (5315H),A 32 15 53
Self-Modifying Code
Store Register A (the mode) at 5315H, the operand of the LD A,00H at 5314H, which chooses what happens after the load.
5223
LD A,C 79
Load Register A with Register C: C8H (RET Z) normally, C9H (RET) for R or V.
5224
LD (5FCFH),A 32 CF 5F
Store Register A at 5FCFH in BASIC/CMD, the first instruction of its close-all-files routine at 5FB6H (the ROM link 41BBH, which NEW and RUN call). With C9H there, the open files stay open.
5227
LD A,B 78
Load Register A with Register B: 18H (JR) normally, 3EH (LD A,nn) for V.
5228
LD (5255H),A 32 55 52
Self-Modifying Code
Store Register A at 5255H, the opcode of the instruction there: JR 526BH (18H) clears the program and variables; LD A,14H (3EH) goes on at 5257H for V.
522B
LD A,(IX+0EH) DD 7E 0E
Load Register A with the byte at Index Register IX + 0EH (570EH), byte 1 of the FCB at 570DH, whose bits 0-2 hold the file's access level.
522E
AND 07H E6 07
AND Register A with 07H, keeping the access level (0-7).
5230
CP 06H FE 06
Compare Register A (the access level) against 06H: the NO CARRY FLAG is set for EXEC (6) or LOCK (7), the Z FLAG for EXEC.
5232
If the NO CARRY FLAG is set (EXEC or LOCK), JUMP to 5240H.
5234
LD A,(436CH) 3A 6C 43
Load Register A with the byte at 436CH, SYS0's SYSTEM option byte.
5237
BIT 6,A CB 77
Test bit 6 of Register A, the SYSTEM option AB (RUN ONLY).
5239
If the NZ FLAG is set (the system runs in RUN ONLY mode), JUMP to 5255H, leaving the RUN ONLY and BREAK settings as they are.
523B
LD B,C9H 06 C9
Load Register B with C9H, the opcode RET, for the BREAK hook at 4312H: BREAK is enabled.
523D
XOR A AF
Load Register A with 00H (XOR A with itself), for 6421H: direct commands allowed. This also sets the Z FLAG.
523E
JUMP to 524EH to store Register A at 6421H and Register B at 4312H.
5240
If the NZ FLAG is set (access level LOCK), JUMP to 5255H; the read will fail with FILE ACCESS DENIED.
5242
LD A,(5315H) 3A 15 53
EXEC: load Register A with the byte at 5315H, the mode just stored (00H load, 01H run).
5245
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set for LOAD.
5246
If the Z FLAG is set (LOAD of an EXEC program), JUMP to 5255H; the read will fail with FILE ACCESS DENIED.
5248
DEC (IX+0EH) DD 35 0E
RUN of an EXEC program: decrement the byte at Index Register IX + 0EH (570EH, the FCB's access level) from EXEC to READ, so the file can be read.
524B
LD B,C3H 06 C3
Load Register B with C3H, the opcode JP, for the BREAK hook at 4312H: it then jumps to 45B0H and BREAK is disabled.
524D
LD A,C 79
Load Register A with Register C (C8H or C9H, never 0), for 6421H: RUN ONLY is set.
524E
LD (6421H),A 32 21 64
Store Register A at 6421H, BASIC/CMD's RUN ONLY flag: 00H allows direct commands, anything else stops the program from being listed or changed.
5251
LD A,B 78
Load Register A with Register B: C9H (BREAK enabled) or C3H (BREAK disabled).
5252
LD (4312H),A 32 12 43
Store Register A at 4312H, the opcode of SYS0's BREAK hook.
5255
Self-Modifying Code
This opcode is written at 5228H: JR 526BH (18H) for LOAD, RUN and R, a JUMP to the code that clears the program and variables; or LD A,14H (3EH) for V, which takes the offset byte as its operand and goes on at 5257H. The file holds 28H, JR Z,526BH, which is never executed.
5257
V: GOSUB to the ROM's TROFF at 1DF8H, which switches trace off.
525A
LD DE,(40A4H) ED 5B A4 40
Load Register Pair DE with the 16-bit value at 40A4H, the ROM's pointer to the start of the BASIC program.
525E
LD HL,(40F9H) 2A F9 40
Load Register Pair HL with the 16-bit value at 40F9H, the ROM's pointer to the start of the simple variables (just past the program).
5261
DEC HL 2B
Decrement Register Pair HL (the start of the variables): 1 of 2.
5262
DEC HL 2B
Decrement Register Pair HL: HL = the program's end marker, the last byte of the program.
5263
GOSUB to 54C8H, which deletes the program from Register Pair DE (its start) to Register Pair HL (its end) but keeps the variables; their strings in the program are copied to the string space first.
5266
GOSUB to 54DFH, which switches off ON ERROR GOTO, marks no file area in use and resets BASIC's stack.
5269
JUMP to 5271H to read the file, skipping NEW.
526B
LOAD, RUN and R: GOSUB to BASIC 63B9H, which marks no file area in use.
526E
GOSUB to 1B4DH in the ROM's NEW routine, which clears the program and the variables.
5271
CALL 63ADH CD AD 63
GOSUB to BASIC 63ADH, which marks a file area in use (BASIC 63A9H = C9H).
5274
LD HL,4369H 21 69 43
Load Register Pair HL with 4369H, SYS0's system state byte.
5277
SET 6,(HL) CB F6
Set bit 6 of the byte at Register Pair HL (4369H): an overlay function is running, so the DOS key combinations stay off until BASIC's statement end.
5279
LD DE,570DH 11 0D 57
Load Register Pair DE with 570DH, the FCB of the open file.
527C
GOSUB to SYS0 4436H, which reads the file's first sector into its buffer at 4200H; the Z FLAG is set without error, else Register A holds the DOS error code.
527F
If the Z FLAG is set (the sector was read), JUMP to 5289H.
5281
CP 1CH FE 1C
Compare Register A (the DOS error code) against 1CH, the end of the file: an empty file.
5283
JP NZ,5E16H C2 16 5E
If the NZ FLAG is set (another error), JUMP to BASIC 5E16H, which turns the DOS error in Register A into a BASIC error.
5286
An empty file: JUMP to 5314H; there is nothing to load.

5289H - Make Room and Read a Tokenized File

The program in memory (for MERGE and V) and its variables are moved up to just below the stack, keeping 160 bytes free; the new program is then built from the program's start (40A4H), and the old lines are copied in among the new ones by line number (53B4H). While this runs, BASIC's statement-end clean-up calls 543EH, so an error during the load still puts memory back in order. A file starting with FFH is a tokenized program, read line by line straight from the sector buffer at 4200H.

5289
GOSUB to 5495H, which returns Register Pair HL = the size of the simple variables and Register Pair BC = the size of the arrays (and stores both for 543EH).
528C
PUSH HL E5
Save Register Pair HL (the size of the simple variables) on the stack.
528D
ADD HL,BC 09
Add Register Pair BC (the arrays' size) to Register Pair HL: HL = the size of all variables.
528E
LD B,H 44
Load Register B with Register H, the high byte of the size of all variables.
528F
LD C,L 4D
Load Register C with Register L. Register Pair BC now holds the size of all variables.
5290
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the 16-bit value at 40A4H, the ROM's pointer to the start of the program.
5293
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the program's start, HL = the start of the simple variables (40F9H, still in Register Pair DE from 5495H).
5294
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
5295
SBC HL,DE ED 52
Subtract Register Pair DE (the program's start) from Register Pair HL (the start of the variables): HL = the program's size in bytes.
5297
PUSH HL E5
Save Register Pair HL (the program's size) on the stack.
5298
ADD HL,BC 09
Add Register Pair BC (the variables' size) to Register Pair HL: HL = the size of the program and variables together.
5299
LD B,H 44
Load Register B with Register H, the high byte of that size.
529A
LD C,L 4D
Load Register C with Register L. Register Pair BC now holds the bytes to move.
529B
LD HL,FF60H 21 60 FF
Load Register Pair HL with FF60H, which is -160.
529E
ADD HL,SP 39
Add the Stack Pointer SP to Register Pair HL: HL = 160 bytes below BASIC's stack, where the moved block will end.
529F
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = SP - 160, HL = the program's start.
52A0
LD HL,(40FDH) 2A FD 40
Load Register Pair HL with the 16-bit value at 40FDH, the ROM's pointer to the end of the arrays (the end of the block to move).
52A3
INC H 24
Increment Register H: HL = the end of the arrays plus 256, the least room wanted.
52A4
RST 18H DF
RST 18H: compare Register Pair HL (the end of the arrays + 256) with Register Pair DE (SP - 160). The NO CARRY FLAG is set if there is not that much room.
52A5
If the NO CARRY FLAG is set (too little memory), JUMP to 54C5H, which reports OUT OF MEMORY.
52A8
DEC H 25
Decrement Register H: HL = the end of the arrays again.
52A9
DEC HL 2B
Decrement Register Pair HL: HL = the last byte of the arrays, where the move starts (it copies downwards).
52AA
LD (40FDH),DE ED 53 FD 40
Store Register Pair DE (SP - 160) at 40FDH: the end of the arrays is now 160 bytes below the stack.
52AE
DEC DE 1B
Decrement Register Pair DE: DE = the last byte of the new place.
52AF
LDDR ED B8
LDDR: copy BC bytes (the program and variables) from Register Pair HL downwards to Register Pair DE, moving them up in memory so they end just below SP - 160.
52B1
INC DE 13
Increment Register Pair DE: DE = the first byte of the moved program, the first old line.
52B2
LD (53DCH),DE ED 53 DC 53
Self-Modifying Code
Store Register Pair DE (the first old line) at 53DCH, the operand of the LD HL,0000H at 53DBH: the next old line to put in.
52B6
POP HL E1
Restore Register Pair HL from the stack: the program's size.
52B7
ADD HL,DE 19
Add Register Pair DE (the moved program's start) to Register Pair HL: HL = the moved start of the simple variables.
52B8
LD (40F9H),HL 22 F9 40
Store Register Pair HL at 40F9H, the ROM's pointer to the start of the simple variables.
52BB
POP BC C1
Restore Register Pair BC from the stack: the size of the simple variables.
52BC
ADD HL,BC 09
Add Register Pair BC to Register Pair HL: HL = the moved start of the arrays.
52BD
LD (40FBH),HL 22 FB 40
Store Register Pair HL at 40FBH, the ROM's pointer to the start of the arrays.
52C0
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the 16-bit value at 40A4H, the ROM's pointer to the program's start, where the new program is built.
52C3
LD (5429H),HL 22 29 54
Self-Modifying Code
Store Register Pair HL at 5429H, the operand of the LD BC,0000H at 5428H, the start of the range whose string pointers 5478H moves.
52C6
LD (547FH),HL 22 7F 54
Self-Modifying Code
Store Register Pair HL at 547FH, the operand of the LD DE,0000H at 547EH: the program pointer when the current run of old lines began.
52C9
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = the first old line, DE = the program's start, the program pointer where the new program goes.
52CA
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the low byte of the first old line's link.
52CB
INC HL 23
Increment Register Pair HL to the high byte of the link.
52CC
OR (HL) B6
OR Register A with the byte at Register Pair HL: the Z FLAG is set if the link is 0000H, no old program.
52CD
INC HL 23
Increment Register Pair HL to the low byte of the old line's number.
52CE
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the low byte of the first old line's number.
52CF
INC HL 23
Increment Register Pair HL to the high byte of the old line's number.
52D0
LD B,(HL) 46
Load Register B with the byte at Register Pair HL. Register Pair BC now holds the first old line's number.
52D1
If the NZ FLAG is set (there is an old line), JUMP to 52D6H.
52D3
LD BC,FFFFH 01 FF FF
Load Register Pair BC with FFFFH: no old lines, higher than any line number.
52D6
PUSH BC C5
Push Register Pair BC (the next old line's number) on the stack; 53B4H keeps it there.
52D7
GOSUB to 5620H, which clears the offset at 5642H and returns Register Pair HL = 543EH.
52DA
LD (644EH),HL 22 4E 64
Store Register Pair HL (543EH) at 644EH, the operand of the CALL at BASIC 644DH in BASIC's statement-end clean-up at 6445H: if an error stops the load, the clean-up calls 543EH, which puts the program and variables back together.
52DD
LD HL,4200H 21 00 42
Load Register Pair HL with 4200H, the first byte of the file in the sector buffer.
52E0
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the file's first byte.
52E1
CP FFH FE FF
Compare Register A against FFH, the mark of a tokenized program.
52E3
If the NZ FLAG is set (a text file), JUMP to 535BH.

TOKENIZED LINE LOOP
Register Pair HL = the position in the sector buffer (Register L wraps to 00H at the end of a sector, when 54B2H reads the next one), Register Pair DE = the program pointer.

52E6
LD (5442H),DE ED 53 42 54
Self-Modifying Code
Store Register Pair DE (the program pointer) at 5442H, the operand of the LD DE,0000H at 5441H, so 543EH and 5478H know how far the new program reaches.
52EA
INC L 2C
Increment Register L, the position in the sector buffer; the Z FLAG is set when it wraps to 00H.
52EB
If the Z FLAG is set (the sector is used up), GOSUB to 54B2H to read the next sector into 4200H.
52EE
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the low byte of the line's link.
52EF
INC L 2C
Increment Register L, the position in the sector buffer.
52F0
If the Z FLAG is set (the sector is used up), GOSUB to 54B2H.
52F3
LD A,C 79
Load Register A with Register C, the low byte of the link.
52F4
OR (HL) B6
OR Register A with the byte at Register Pair HL, the high byte of the link: the Z FLAG is set for a 0000H link, the end of the program.
52F5
If the Z FLAG is set (the end of the file's program), JUMP to 5310H.
52F7
INC L 2C
Increment Register L, the position in the sector buffer.
52F8
If the Z FLAG is set (the sector is used up), GOSUB to 54B2H.
52FB
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the low byte of the line number.
52FC
INC L 2C
Increment Register L, the position in the sector buffer.
52FD
If the Z FLAG is set (the sector is used up), GOSUB to 54B2H.
5300
LD B,(HL) 46
Load Register B with the byte at Register Pair HL. Register Pair BC now holds the new line's number.
5301
GOSUB to 53B4H with Register Pair BC = the new line's number and Register Pair DE = the program pointer: the old lines that come first are copied in, and the new line's link and number are stored.

COPY THE LINE'S TEXT
Register Pair HL = the sector buffer, Register Pair DE = the program pointer.

5304
INC L 2C
Increment Register L, the position in the sector buffer.
5305
If the Z FLAG is set (the sector is used up), GOSUB to 54B2H.
5308
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, a byte of the line's text.
5309
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set at the 00H that ends the line.
530A
LD (DE),A 12
Store Register A at Register Pair DE, in the new program.
530B
INC DE 13
Increment Register Pair DE, the program pointer.
530C
If the NZ FLAG is set (not the end of the line), LOOP back to 5304H.
530E
JUMP to 52E6H for the next line of the file, Register Pair HL still in the sector buffer.
5310
POP AF F1
The end of the file: restore Register Pair AF from the stack, discarding the next old line's number.
5311
GOSUB to 543EH, which puts the rest of the old program and the variables behind the new lines and rebuilds the links.
5314
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the mode; the operand 5315H holds 0 (LOAD, or MERGE typed as a command), 1 (RUN) or 2 (MERGE in a running program), stored at 5220H or 5355H.
5316
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set for mode 0.
5317
If the Z FLAG is set (LOAD), JUMP to the ROM's READY at 1A19H, which shows READY.
531A
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the 16-bit value at 40A4H, the ROM's pointer to the program's start.
531D
DEC HL 2B
Decrement Register Pair HL, one byte before the first line, as NEWSTT wants it.
531E
DEC A 3D
Decrement Register A (the mode): the Z FLAG is set for mode 1.
531F
If the Z FLAG is set (RUN), JUMP to the ROM's NEWSTT at 1D1EH, which starts the program at its first line.
5322
LD DE,(57B8H) ED 5B B8 57
MERGE in a program (or CMD"F",DELETE): load Register Pair DE with the 16-bit value at 57B8H, the number of the line after the statement, stored by BASIC 5D9FH.
5326
GOSUB to the ROM's FNDLIN at 1B2CH, which finds the line whose number is in Register Pair DE: Register Pair BC = its address; the CARRY FLAG and the Z FLAG are both set only if the line exists (no CARRY: not found).
5329
LD H,B 60
Load Register H with Register B, the high byte of the line's address.
532A
LD L,C 69
Load Register L with Register C. Register Pair HL now holds the line's address.
532B
DEC HL 2B
Decrement Register Pair HL, one byte before the line, as NEWSTT wants it.
532C
If the NO CARRY FLAG is set (FNDLIN did not find the line), JUMP to 5331H.
532E
If the Z FLAG is set (the line exists; FNDLIN returns CARRY with Z for a line found), JUMP to the ROM's NEWSTT at 1D1EH to go on with that line.
5331
JUMP to the ROM's SNERR at 1997H to report SYNTAX ERROR.

5334H - MERGE

Entered from BASIC 5731H for MERGE "file" (BASIC 572EH, the ROM vector 418BH), with the file open in the work area as for LOAD. The file's lines are put in among the program's lines. Typed as a command, MERGE ends at READY; in a running program its lines may not replace existing ones (ILLEGAL FUNCTION CALL) and the program goes on with the line after the MERGE statement. Register Pair HL is BASIC's text pointer after the file name.

5334
LD DE,(40A2H) ED 5B A2 40
Load Register Pair DE with the 16-bit value at 40A2H, the ROM's current line number (FFFFH while a direct command runs).
5338
LD A,D 7A
Load Register A with Register D, the high byte of the current line number.
5339
AND E A3
AND Register A with Register E, the low byte: FFH only if both are FFH.
533A
INC A 3C
Increment Register A: the Z FLAG is set if the line number is FFFFH, a direct command.
533B
If the Z FLAG is set (MERGE typed as a command), JUMP to 5350H.
533D
CALL 5D9FH CD 9F 5D
GOSUB to BASIC 5D9FH, which steps Register Pair HL to the next program line and stores its number at 57B8H, where 5322H finds it after the merge.
5340
LD A,(IX+0EH) DD 7E 0E
Load Register A with the byte at Index Register IX + 0EH (570EH), the FCB byte whose bits 0-2 hold the file's access level.
5343
AND 07H E6 07
AND Register A with 07H, keeping the access level.
5345
CP 06H FE 06
Compare Register A (the access level) against 06H, EXEC.
5347
If the NZ FLAG is set (not EXEC), JUMP to 534CH.
5349
DEC (IX+0EH) DD 35 0E
EXEC: decrement the byte at Index Register IX + 0EH (570EH), lowering the access level to READ so the file can be read by a running program.
534C
LD A,02H 3E 02
Load Register A with 02H, mode 2: MERGE in a running program.
534E
JUMP to 5355H to store the mode in Register A.
5350
DEC HL 2B
MERGE typed as a command: decrement Register Pair HL (the text pointer) so the RST 10H that follows fetches the current character again.
5351
RST 10H D7
RST 10H: move Register Pair HL on and load Register A with the character; Register A = 00H and the Z FLAG is set at the end of the statement.
5352
If the NZ FLAG is set (something follows the file name), JUMP to the ROM's SNERR at 1997H to report SYNTAX ERROR.
5355
LD (5315H),A 32 15 53
Self-Modifying Code
Store Register A (the mode: 00H for a command, 02H in a program) at 5315H, the operand of the LD A,00H at 5314H.
5358
JUMP to 5266H, which resets ON ERROR and BASIC's stack and reads the file, keeping the program and variables.

535BH - Load a Text File

A file that does not start with FFH is BASIC text. Each line (ended by a carriage return, at most 240 characters, 00H bytes and a line feed at the start skipped) is read into BASIC's input buffer, must start with a line number (else error 84H DIRECT STATEMENT IN FILE), and is tokenized by the ROM's CRUNCH; then it is put in like a tokenized line. Register Pair DE is the program pointer.

535B
DEC (IX+17H) DD 35 17
Decrement the byte at Index Register IX + 17H (5717H), the middle byte of the FCB's NEXT position (FCB + 10), so the first sector is read again as text through BASIC's byte reader.

TEXT LINE LOOP
Register Pair DE (saved on the stack while reading) = the program pointer.

535E
PUSH DE D5
Save Register Pair DE (the program pointer) on the stack.
535F
LD (5442H),DE ED 53 42 54
Self-Modifying Code
Store Register Pair DE (the program pointer) at 5442H, the operand of the LD DE,0000H at 5441H.
5363
GOSUB to 54BDH, which reports OUT OF MEMORY if the new program at Register Pair DE has come within 256 bytes of the old lines not yet merged.
5366
LD E,F0H 1E F0
Load Register E with F0H (240), the most characters a line may have.
5368
LD HL,(40A7H) 2A A7 40
Load Register Pair HL with the 16-bit value at 40A7H, the ROM's pointer to the input buffer, where the line is collected.
536B
PUSH HL E5
Save Register Pair HL (the start of the input buffer) on the stack.

CHARACTER LOOP
Register Pair HL = where the next character goes, Register E = the characters still allowed.

536C
CALL 6119H CD 19 61
GOSUB to BASIC 6119H, which reads the next byte of the file into Register A through the FCB; the NZ FLAG is set at the end of the file.
536F
If the NZ FLAG is set (the end of the file), JUMP to 5310H to finish the load.
5372
OR A B7
OR Register A (the byte) with itself to set the flags: the Z FLAG is set for 00H.
5373
If the Z FLAG is set (a 00H byte), LOOP back to 536CH; it is skipped.
5375
CP 0DH FE 0D
Compare Register A against 0DH, a carriage return.
5377
LD (HL),A 77
Store Register A (the character) at Register Pair HL in the input buffer. LD does not change the flags.
5378
If the Z FLAG is set (a carriage return, the end of the line), JUMP to 5387H.
537A
CP 0AH FE 0A
Compare Register A (the character) against 0AH, a line feed.
537C
If the NZ FLAG is set (not a line feed), JUMP to 5383H to keep it.
537E
LD A,E 7B
Load Register A with Register E, the characters still allowed.
537F
CP F0H FE F0
Compare Register A against F0H: the Z FLAG is set if no character has been stored yet.
5381
If the Z FLAG is set (a line feed at the start of the line), LOOP back to 536CH; it is skipped.
5383
INC HL 23
Increment Register Pair HL to the next place in the input buffer.
5384
DEC E 1D
Decrement Register E, the characters still allowed.
5385
If the NZ FLAG is set (room is left), LOOP back to 536CH; after 240 characters the line ends.
5387
XOR A AF
Load Register A with 00H (XOR A with itself).
5388
LD (HL),A 77
Store Register A (00H) at Register Pair HL, ending the line in the input buffer (over the carriage return).
5389
POP HL E1
Restore Register Pair HL from the stack: the start of the input buffer.
538A
DEC HL 2B
Decrement Register Pair HL so the RST 10H that follows fetches the first character.
538B
RST 10H D7
RST 10H: move Register Pair HL to the first non-blank character and load it into Register A; the CARRY FLAG is set for a digit, the Z FLAG for 00H.
538C
INC A 3C
Increment Register A (the first character of the line).
538D
DEC A 3D
Decrement Register A back to the character: the Z FLAG is set if it is 00H; the CARRY FLAG from RST 10H is kept.
538E
If the Z FLAG is set (an empty line), JUMP to 5366H for the next line.
5390
JP NC,5DDFH D2 DF 5D
If the NO CARRY FLAG is set (the line does not start with a digit), JUMP to BASIC 5DDFH, which raises error 84H DIRECT STATEMENT IN FILE.
5393
GOSUB to the ROM's LINGET at 1E5AH, which converts the digits at Register Pair HL into the line number in Register Pair DE; HL is left after the number.
5396
DEC HL 2B
Decrement Register Pair HL, the character before the one after the number.
5397
LD A,20H 3E 20
Load Register A with 20H, a space, to look for spaces after the number.
5399
CP (HL) BE
Compare Register A (a space) with the byte at Register Pair HL.
539A
If the NZ FLAG is set (no space there), JUMP to 53A1H.
539C
DEC HL 2B
Decrement Register Pair HL back over the spaces LINGET passed.
539D
CP (HL) BE
Compare Register A (a space) with the byte at Register Pair HL.
539E
If the Z FLAG is set (another space), LOOP back to 539CH.
53A0
INC HL 23
Increment Register Pair HL to the first space after the digits.
53A1
INC HL 23
Increment Register Pair HL: HL = the line's text after the number, keeping one space for a following space.
53A2
PUSH DE D5
Save Register Pair DE (the line number) on the stack.
53A3
GOSUB to the ROM's CRUNCH at 1BC0H, which tokenizes the text at Register Pair HL in place and returns HL one byte before the tokenized line.
53A6
POP BC C1
Restore Register Pair BC from the stack: the new line's number.
53A7
POP DE D1
Restore Register Pair DE from the stack: the program pointer (pushed at 535EH).
53A8
GOSUB to 53B4H with Register Pair BC = the new line's number and Register Pair DE = the program pointer: the old lines that come first are copied in, and the new line's link and number are stored.

COPY THE TOKENIZED LINE
Register Pair HL = the tokenized line, Register Pair DE = the program pointer.

53AB
INC HL 23
Increment Register Pair HL to the next byte of the tokenized line.
53AC
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL.
53AD
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set at the 00H that ends the line.
53AE
LD (DE),A 12
Store Register A at Register Pair DE, in the new program.
53AF
INC DE 13
Increment Register Pair DE, the program pointer.
53B0
If the NZ FLAG is set (more of the line), LOOP back to 53ABH.
53B2
JUMP to 535EH for the next line of the file, with Register Pair DE the program pointer.

53B4H - Put In a Line

Called with Register Pair BC = the new line's number and Register Pair DE = the program pointer; the next old line's number lies on the stack below the return address. Old lines with smaller numbers are copied in first (53FEH); an old line with the same number is dropped, the new one replacing it (not allowed in mode 2); then the new line's header (a non-zero dummy link and the number) is stored. The real links are made at the end by the ROM's LINKER (543EH). Register Pair HL (the caller's position in the file data) is kept on the stack meanwhile.

53B4
POP AF F1
Restore Register Pair AF from the stack: Register Pair AF takes the return address.
53B5
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (at the Stack Pointer SP): HL = the next old line's number, and the caller's Register Pair HL is saved.
53B6
PUSH AF F5
Push Register Pair AF (the return address) back on the stack.

NUMBER COMPARE
Register Pair HL = the next old line's number, Register Pair BC = the new line's number.

53B7
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
53B8
SBC HL,BC ED 42
Subtract Register Pair BC (the new line's number) from Register Pair HL (the old line's number): the CARRY FLAG is set if the old line comes first, the Z FLAG if the numbers are equal.
53BA
ADD HL,BC 09
Add Register Pair BC back: HL = the old line's number again. ADD HL,BC leaves the Z FLAG of the subtraction and sets the CARRY FLAG exactly when the subtraction borrowed, so both flags still give the result of the compare.
53BB
If the CARRY FLAG is set (the old line's number is smaller), JUMP to 53FEH to copy the old lines that come first.
53BD
If the Z FLAG is set (the same number), JUMP to 53CDH to drop the old line.
53BF
POP AF F1
The new line comes first: restore Register Pair AF from the stack, Register Pair AF takes the return address.
53C0
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (at the Stack Pointer SP): the next old line's number is saved again, and HL = the caller's Register Pair HL.
53C1
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = the program pointer, DE = the caller's position.
53C2
PUSH AF F5
Push Register Pair AF (the return address) on the stack.
53C3
LD (HL),H 74
Store Register H (the high byte of the program pointer, never 0) at Register Pair HL: the low byte of a dummy link that only has to be non-zero.
53C4
INC HL 23
Increment Register Pair HL to the link's high byte.
53C5
LD (HL),H 74
Store Register H at Register Pair HL: the high byte of the dummy link.
53C6
INC HL 23
Increment Register Pair HL to the line number.
53C7
LD (HL),C 71
Store Register C (the low byte of the new line's number) at Register Pair HL.
53C8
INC HL 23
Increment Register Pair HL to the high byte of the line number.
53C9
LD (HL),B 70
Store Register B (the high byte of the new line's number) at Register Pair HL.
53CA
INC HL 23
Increment Register Pair HL to where the line's text goes.
53CB
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the program pointer (at the text), HL = the caller's position.
53CC
RET C9
RETURN to the caller, which copies the line's text to Register Pair DE.
53CD
LD A,B 78
The same number: load Register A with Register B, the high byte of the line number.
53CE
AND C A1
AND Register A with Register C, the low byte: FFH only for line 65535.
53CF
INC A 3C
Increment Register A: the Z FLAG is set for 65535 (the number that stands for "no more old lines").
53D0
JP Z,5DE2H CA E2 5D
If the Z FLAG is set (the file has a line 65535), JUMP to BASIC 5DE2H, which raises error 8CH SEQ # OVERFLOW.
53D3
LD A,(5315H) 3A 15 53
Load Register A with the byte at 5315H, the mode (the operand of 5314H).
53D6
CP 02H FE 02
Compare Register A against 02H, MERGE in a running program.
53D8
If the Z FLAG is set (a running program may not replace a line), JUMP to the ROM's FCERR at 1E4AH to report ILLEGAL FUNCTION CALL.
53DB
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with the address of the next old line; the operand 53DCH (0000H in the file) was stored at 52B2H or 53EEH.
53DE
INC HL 23
Increment Register Pair HL: 1 of 4 over the old line's link and number.
53DF
INC HL 23
Increment Register Pair HL: 2 of 4 over the old line's link and number.
53E0
INC HL 23
Increment Register Pair HL: 3 of 4 over the old line's link and number.
53E1
INC HL 23
Increment Register Pair HL: 4 of 4, HL = the old line's text.
53E2
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, a byte of the old line's text.
53E3
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set at the 00H that ends the line.
53E4
INC HL 23
Increment Register Pair HL to the next byte (the flags are not changed).
53E5
If the NZ FLAG is set (not the end), LOOP back to 53E2H. HL is then the line after the dropped one.
53E7
GOSUB to 53EEH with Register Pair HL = the next old line: it becomes the next old line (53DCH), Register A returns the low byte of its number and HL points at the high byte.
53EA
LD H,(HL) 66
Load Register H with the byte at Register Pair HL, the high byte of the next old line's number.
53EB
LD L,A 6F
Load Register L with Register A. Register Pair HL now holds the next old line's number.
53EC
JUMP to 53B7H to compare it with the new line's number in Register Pair BC.
53EE
LD (53DCH),HL 22 DC 53
Self-Modifying Code
Store Register Pair HL (the next old line's address) at 53DCH, the operand of 53DBH.
53F1
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the low byte of the old line's link.
53F2
INC HL 23
Increment Register Pair HL to the high byte of the old line's link.
53F3
OR (HL) B6
OR Register A with the byte at Register Pair HL: the Z FLAG is set for a 0000H link, the end of the old program.
53F4
INC HL 23
Increment Register Pair HL to the low byte of the line number.
53F5
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the low byte of the old line's number. LD does not change the flags.
53F6
INC HL 23
Increment Register Pair HL to the high byte of the number.
53F7
RET NZ C0
If the NZ FLAG is set (there is a line), RETURN with Register A = the low byte of its number and Register Pair HL at the high byte.
53F8
POP HL E1
No more old lines: restore Register Pair HL from the stack, discarding the return address.
53F9
LD HL,FFFFH 21 FF FF
Load Register Pair HL with FFFFH (65535), which is higher than any new line.
53FC
JUMP to 53B7H to compare it with the new line's number in Register Pair BC.
53FE
LD HL,(53DCH) 2A DC 53
An old line comes first: load Register Pair HL with the 16-bit value at 53DCH, the address of the next old line.
5401
GOSUB to 5478H, which moves the string pointers of the variables that point into the old lines not yet copied by the bytes of new lines inserted since the last old line.

COPY THE OLD LINES THAT COME FIRST
Register Pair HL = the old line, Register Pair DE = the program pointer, Register Pair BC = the new line's number.

5404
LD (547FH),DE ED 53 7F 54
Self-Modifying Code
Store Register Pair DE (the program pointer) at 547FH, the operand of 547EH: the program pointer when this old line is placed.
5408
LD (5442H),DE ED 53 42 54
Self-Modifying Code
Store Register Pair DE (the program pointer) at 5442H, the operand of 5441H.
540C
GOSUB to 53EEH: the old line at Register Pair HL becomes the next old line (53DCH); Register A = the low byte of its number, HL at the high byte.
540F
PUSH HL E5
Save Register Pair HL (the high byte of the old line's number) on the stack.
5410
LD H,(HL) 66
Load Register H with the byte at Register Pair HL, the high byte of the old line's number.
5411
LD L,A 6F
Load Register L with Register A. Register Pair HL now holds the old line's number.
5412
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
5413
SBC HL,BC ED 42
Subtract Register Pair BC (the new line's number) from Register Pair HL (the old line's number): the CARRY FLAG is set if the old line comes first.
5415
ADD HL,BC 09
Add Register Pair BC back: HL = the old line's number again, with the CARRY FLAG still showing the compare.
5416
If the CARRY FLAG is set (the old line still comes first), JUMP to 541BH to copy it.
5418
POP AF F1
Restore Register Pair AF from the stack, discarding the saved pointer into the old line.
5419
JUMP to 53B7H with Register Pair HL = the old line's number, to compare again (equal, or the new line comes first now).
541B
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = the program pointer, DE = the old line's number.
541C
LD (HL),H 74
Store Register H (the high byte of the program pointer, never 0) at Register Pair HL: the low byte of a dummy link.
541D
INC HL 23
Increment Register Pair HL to the link's high byte.
541E
LD (HL),H 74
Store Register H at Register Pair HL: the high byte of the dummy link.
541F
INC HL 23
Increment Register Pair HL to the line number.
5420
LD (HL),E 73
Store Register E (the low byte of the old line's number) at Register Pair HL.
5421
INC HL 23
Increment Register Pair HL to the high byte of the line number.
5422
LD (HL),D 72
Store Register D (the high byte of the old line's number) at Register Pair HL.
5423
INC HL 23
Increment Register Pair HL to where the line's text goes.
5424
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the program pointer at the text.
5425
POP HL E1
Restore Register Pair HL from the stack: the high byte of the old line's number.
5426
INC HL 23
Increment Register Pair HL to the old line's text.
5427
PUSH BC C5
Save Register Pair BC (the new line's number) on the stack.
5428
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the address the old line had before the move, in the operand 5429H (0000H in the file; stored at 52C3H, 54CEH and 5437H); it grows by the length of every old line copied.
542B
INC BC 03
Increment Register Pair BC: 1 of 4, for the old line's link and number.
542C
INC BC 03
Increment Register Pair BC: 2 of 4, for the old line's link and number.
542D
INC BC 03
Increment Register Pair BC: 3 of 4, for the old line's link and number.
542E
INC BC 03
Increment Register Pair BC: 4 of 4, for the old line's link and number.

COPY THE OLD LINE'S TEXT
Register Pair HL = the old line, Register Pair DE = the program pointer, Register Pair BC = the old address counter.

542F
INC BC 03
Increment Register Pair BC, counting one byte of the old line's text.
5430
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, a byte of the old line's text.
5431
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set at the 00H that ends the line.
5432
LD (DE),A 12
Store Register A at Register Pair DE, in the new program.
5433
INC HL 23
Increment Register Pair HL to the next byte of the old line.
5434
INC DE 13
Increment Register Pair DE, the program pointer.
5435
If the NZ FLAG is set (more of the line), LOOP back to 542FH.
5437
LD (5429H),BC ED 43 29 54
Self-Modifying Code
Store Register Pair BC (the old address of the next old line) at 5429H, the operand of 5428H.
543B
POP BC C1
Restore Register Pair BC from the stack: the new line's number.
543C
JUMP to 5404H for the next old line, with Register Pair HL at it.

543EH - Close Up

Moves the old lines that are left (from 53DCH) down behind the new program, then the simple variables and the arrays; stores the new pointers at 40F9H, 40FBH and 40FDH; rebuilds the line links with the ROM's LINKER; and puts BASIC's statement-end CALL at 644DH back (64BEH). Also reached from BASIC's clean-up at 6445H if an error ends the load (the CALL was pointed here at 52DAH).

543E
GOSUB to 5478H, which moves the string pointers into the old lines left by the new bytes inserted since the last old line.
5441
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the program pointer, the end of the new program so far; the operand 5442H (0000H in the file) was stored at 52E6H, 535FH, 5408H or 54D2H.
5444
LD BC,(53DCH) ED 4B DC 53
Load Register Pair BC with the 16-bit value at 53DCH, the address of the next old line not yet merged.
5448
LD HL,(40F9H) 2A F9 40
Load Register Pair HL with the 16-bit value at 40F9H, the ROM's pointer to the start of the simple variables (the moved variables, just after the old lines).
544B
PUSH BC C5
Save Register Pair BC (the next old line) on the stack.
544C
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
544D
SBC HL,BC ED 42
Subtract Register Pair BC (the next old line) from Register Pair HL (the start of the variables): HL = the bytes of old lines left.
544F
LD B,H 44
Load Register B with Register H, the high byte of that count.
5450
LD C,L 4D
Load Register C with Register L. Register Pair BC now holds the bytes of old lines left.
5451
POP HL E1
Restore Register Pair HL from the stack: the next old line, the first to move.
5452
LDIR ED B0
LDIR: copy BC bytes (the old lines left) from Register Pair HL to Register Pair DE, down behind the new program. DE ends just past them.
5454
LD (40F9H),DE ED 53 F9 40
Store Register Pair DE (the end of the program) at 40F9H, the ROM's pointer to the start of the simple variables.
5458
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the size of the simple variables; the operand 5459H (0000H in the file) was stored at 54AEH.
545B
LD A,B 78
Load Register A with Register B, the high byte of the size.
545C
OR C B1
OR Register A with Register C, the low byte: the Z FLAG is set if there are no simple variables.
545D
If the Z FLAG is set (none), JUMP to 5461H; LDIR with BC = 0 would copy 65,536 bytes.
545F
LDIR ED B0
LDIR: copy BC bytes (the simple variables) from Register Pair HL (where they were moved) to Register Pair DE, behind the program.
5461
LD (40FBH),DE ED 53 FB 40
Store Register Pair DE at 40FBH, the ROM's pointer to the start of the arrays.
5465
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the size of the arrays; the operand 5466H (0000H in the file) was stored at 549FH.
5468
LD A,B 78
Load Register A with Register B, the high byte of the size.
5469
OR C B1
OR Register A with Register C, the low byte: the Z FLAG is set if there are no arrays.
546A
If the Z FLAG is set (no arrays), JUMP to 546EH, skipping the LDIR.
546C
LDIR ED B0
LDIR: copy BC bytes (the arrays) from Register Pair HL to Register Pair DE, behind the simple variables.
546E
LD (40FDH),DE ED 53 FD 40
Store Register Pair DE at 40FDH, the ROM's pointer to the end of the arrays (the start of free memory).
5472
GOSUB to the ROM's LINKER at 1AF8H, which rebuilds every line's link from the program start at 40A4H, replacing the dummy links.
5475
JP 64BEH C3 BE 64
JUMP to BASIC 64BEH, which stores 64BDH back at 644EH (the statement-end CALL does nothing again) and returns.

5478H - Move the String Pointers into the Old Lines

Called before each run of old lines is copied and before the close-up. The new bytes put in since the last old line was placed (the program pointer 5442H minus 547FH) push the old lines not yet copied further along; every string or DEF FN pointer of a variable that points into them (the range from 5429H to 5488H, in the addresses they had before the move, corrected by the offset 5642H) is moved by that distance, which is then added to the offset. Register Pairs HL, DE and BC are kept.

5478
PUSH HL E5
Save Register Pair HL on the stack; 562AH restores it at the end.
5479
PUSH DE D5
Save Register Pair DE on the stack; 562AH restores it at the end.
547A
PUSH BC C5
Save Register Pair BC on the stack; it is restored at 5491H.
547B
LD HL,(5442H) 2A 42 54
Load Register Pair HL with the 16-bit value at 5442H, the program pointer (the end of the new program so far).
547E
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the program pointer when the last old line was placed; the operand 547FH (0000H in the file) was stored at 52C6H, 5404H or 54CBH.
5481
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
5482
SBC HL,DE ED 52
Subtract Register Pair DE from Register Pair HL: HL = the bytes of new lines put in since then, the distance the old lines not yet copied will move.
5484
LD (557AH),HL 22 7A 55
Self-Modifying Code
Store Register Pair HL (the distance) at 557AH, the operand of the LD HL,0000H at 5579H, which 54F2H adds to each pointer it moves.
5487
LD DE,0000H 11 00 00
Self-Modifying Code
Load Register Pair DE with the end of the range, the start of the simple variables before the move; the operand 5488H (0000H in the file) was stored at 54A7H.
548A
LD HL,(5429H) 2A 29 54
Load Register Pair HL with the 16-bit value at 5429H, the operand of 5428H: the address (before the move) of the next old line, the start of the range.
548D
LD A,H 7C
Load Register A with Register H, the high byte of the start: never 0 in RAM, so it serves as a non-zero mode (move the pointers).
548E
If the NZ FLAG is set (the distance computed at 5482H is not zero; the loads since then do not change the flags), GOSUB to 54F2H with Register A = the mode, Register Pair HL = the range start and Register Pair DE = the range end, to move the pointers by 557AH.
5491
POP BC C1
Restore Register Pair BC from the stack (saved at 547AH).
5492
JUMP to 562AH, which adds the distance (557AH) to the offset at 5642H, restores Register Pairs DE and HL and returns.
5495
LD HL,(40FDH) 2A FD 40
Load Register Pair HL with the 16-bit value at 40FDH, the ROM's pointer to the end of the arrays.
5498
LD DE,(40FBH) ED 5B FB 40
Load Register Pair DE with the 16-bit value at 40FBH, the ROM's pointer to the start of the arrays.
549C
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
549D
SBC HL,DE ED 52
Subtract Register Pair DE from Register Pair HL: HL = the size of the arrays in bytes.
549F
LD (5466H),HL 22 66 54
Self-Modifying Code
Store Register Pair HL (the arrays' size) at 5466H, the operand of the LD BC,0000H at 5465H.
54A2
LD B,H 44
Load Register B with Register H, the high byte of the arrays' size.
54A3
LD C,L 4D
Load Register C with Register L. Register Pair BC now holds the arrays' size.
54A4
LD HL,(40F9H) 2A F9 40
Load Register Pair HL with the 16-bit value at 40F9H, the ROM's pointer to the start of the simple variables.
54A7
LD (5488H),HL 22 88 54
Self-Modifying Code
Store Register Pair HL (the start of the simple variables) at 5488H, the operand of the LD DE,0000H at 5487H.
54AA
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the start of the simple variables, HL = the start of the arrays.
54AB
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
54AC
SBC HL,DE ED 52
Subtract Register Pair DE from Register Pair HL: HL = the size of the simple variables.
54AE
LD (5459H),HL 22 59 54
Self-Modifying Code
Store Register Pair HL (the simple variables' size) at 5459H, the operand of the LD BC,0000H at 5458H.
54B1
RET C9
RETURN with Register Pair HL = the simple variables' size, Register Pair BC = the arrays' size, Register Pair DE = the start of the simple variables.

54B2H - Read the Next Sector, Check the Room

54B2H reads the next sector of the file into 4200H (called when Register L wraps to 00H, so Register Pair HL is 4200H again afterwards). 54BDH checks that the new program (Register Pair DE) is still at least 256 bytes below the next old line, else OUT OF MEMORY.

54B2
PUSH DE D5
Save Register Pair DE (the program pointer) on the stack.
54B3
LD DE,570DH 11 0D 57
Load Register Pair DE with 570DH, the FCB of the file being loaded.
54B6
GOSUB to SYS0 4436H, which reads the next sector of the file into its buffer at 4200H; the NZ FLAG is set on an error, with the DOS error code in Register A.
54B9
JP NZ,5E16H C2 16 5E
If the NZ FLAG is set (a read error), JUMP to BASIC 5E16H, which turns the DOS error in Register A into a BASIC error.
54BC
POP DE D1
Restore Register Pair DE from the stack: the program pointer.
54BD
PUSH HL E5
Save Register Pair HL (the position in the sector buffer, or the input buffer) on the stack.
54BE
LD HL,(53DCH) 2A DC 53
Load Register Pair HL with the 16-bit value at 53DCH, the address of the next old line not yet merged.
54C1
DEC H 25
Decrement Register H: HL = the next old line minus 256.
54C2
RST 18H DF
RST 18H: compare Register Pair HL (the next old line - 256) with Register Pair DE (the program pointer). The NO CARRY FLAG is set if at least 256 bytes are free between them.
54C3
POP HL E1
Restore Register Pair HL from the stack. POP does not change the flags.
54C4
RET NC D0
If the NO CARRY FLAG is set (enough room), RETURN.
54C5
JUMP to the ROM's OMERR at 197AH to report OUT OF MEMORY.

54C8H - Delete Lines, Keeping the Variables

Called with Register Pair HL = the last byte and Register Pair DE = the first line of the part of the program to delete (from 5263H for V, from 55BCH for CMD"F",DELETE). Strings of variables whose text lies in that part are copied to the string space first (54F2H with mode 0); then 543EH closes the program up, treating the rest of the program as the old lines left.

54C8
LD (53DCH),HL 22 DC 53
Self-Modifying Code
Store Register Pair HL (the end of the part to delete) at 53DCH, the operand of 53DBH: the rest of the program counts as the next old line.
54CB
LD (547FH),HL 22 7F 54
Self-Modifying Code
Store Register Pair HL at 547FH, the operand of 547EH.
54CE
LD (5429H),HL 22 29 54
Self-Modifying Code
Store Register Pair HL at 5429H, the operand of 5428H.
54D1
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = the first line to delete, DE = the end of the part.
54D2
LD (5442H),HL 22 42 54
Self-Modifying Code
Store Register Pair HL (the first line to delete) at 5442H, the operand of 5441H: the close-up moves the rest of the program down to here.
54D5
XOR A AF
Load Register A with 00H (XOR A with itself): mode 0, copy the strings into the string space.
54D6
GOSUB to 5638H, which clears the offset at 5642H and runs 54F2H with Register A = 0, Register Pair HL = the start and Register Pair DE = the end of the part deleted.
54D9
GOSUB to 5495H, which stores the sizes of the simple variables and the arrays for the close-up.
54DC
JUMP to 543EH to close up the program and the variables.
54DF
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, for the ON ERROR GOTO address.
54E2
LD (40F0H),HL 22 F0 40
Store Register Pair HL (0000H) at 40F0H, the ROM's ON ERROR GOTO address: error trapping is switched off.
54E5
POP HL E1
Restore Register Pair HL from the stack: this routine's return address (STKINI below resets the stack, so it cannot stay there).
54E6
LD (54F0H),HL 22 F0 54
Self-Modifying Code
Store Register Pair HL (the return address) at 54F0H, the operand of the JP 0000H at 54EFH.
54E9
GOSUB to BASIC 63B9H, which marks no file area in use.
54EC
GOSUB to the ROM's STKINI at 1B8FH, which resets BASIC's stack to just below the string space (40A0H), discarding every GOSUB and FOR, and frees the string temporaries.
54EF
JP 0000H C3 00 00
Self-Modifying Code
JUMP back to the caller; the operand 54F0H (0000H in the file) was stored at 54E6H.

54F2H - Fix the String Pointers of the Variables

Walks the simple variables (from 40F9H to 40FBH) and the arrays (to 40FDH). Every string, and every DEF FN pointer (bit 7 of the name's first character), whose text lies after the start and up to the end of the range (both corrected by the offset at 5642H) is either copied into the string space (mode 0, used when lines are deleted; a DEF FN pointer becomes 0000H) or moved by the distance at 557AH (any other mode). Called with Register A = the mode, Register Pair HL = the start and Register Pair DE = the end of the range.

54F2
LD (5574H),A 32 74 55
Self-Modifying Code
Store Register A (the mode) at 5574H, the operand of the OR 00H at 5573H.
54F5
LD (556CH),HL 22 6C 55
Self-Modifying Code
Store Register Pair HL (the start of the range) at 556CH, the operand of the LD HL,0000H at 556BH.
54F8
LD (5565H),DE ED 53 65 55
Self-Modifying Code
Store Register Pair DE (the end of the range) at 5565H, the operand of the LD HL,0000H at 5564H.
54FC
LD HL,(40F9H) 2A F9 40
Load Register Pair HL with the 16-bit value at 40F9H, the ROM's pointer to the start of the simple variables.

SIMPLE VARIABLE LOOP
Register Pair HL = the variable entry (type byte, second name character, first name character, value).

54FF
LD DE,(40FBH) ED 5B FB 40
Load Register Pair DE with the 16-bit value at 40FBH, the ROM's pointer to the start of the arrays, the end of the simple variables.
5503
RST 18H DF
RST 18H: compare Register Pair HL (the variable) with Register Pair DE (the end). The Z FLAG is set at the end.
5504
If the Z FLAG is set (all simple variables done), JUMP to 5527H for the arrays.
5506
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the variable's type byte.
5507
AND 0FH E6 0F
AND Register A with 0FH: Register A = the length of the value (2, 3, 4 or 8).
5509
INC HL 23
Increment Register Pair HL to the second name character.
550A
INC HL 23
Increment Register Pair HL to the first name character.
550B
BIT 7,(HL) CB 7E
Test bit 7 of the byte at Register Pair HL, the first name character: set for a user function (DEF FN), whose value starts with a pointer into its DEF statement.
550D
INC HL 23
Increment Register Pair HL to the value (the flags are not changed).
550E
If the Z FLAG is set (an ordinary variable), JUMP to 551BH.
5510
PUSH AF F5
A DEF FN entry: save Register Pair AF (Register A = the value's length) on the stack.
5511
LD A,00H 3E 00
Load Register A with 00H: the DEF pointer is treated as the address of a string of length 0.
5513
GOSUB to 555BH, which fixes the pointer at Register Pair HL (the NZ FLAG from the bit test lets it go on) and returns HL past it.
5516
POP AF F1
Restore Register Pair AF from the stack: Register A = the value's length.
5517
DEC A 3D
Decrement Register A: 1 of 2 for the pointer already passed.
5518
DEC A 3D
Decrement Register A: Register A = the bytes of the value still to skip.
5519
JUMP to 5520H to skip the rest of the DEF FN value (Register A bytes).
551B
CP 03H FE 03
Compare Register A (the value's length) against 03H, a string (its value is a 3-byte descriptor).
551D
If the Z FLAG is set (a string variable), GOSUB to 5558H to fix the string; it returns with Register Pair HL past the descriptor and Register A = 0.
5520
LD C,A 4F
Load Register C with Register A, the bytes still to skip.
5521
LD B,00H 06 00
Load Register B with 00H, so Register Pair BC = the bytes to skip.
5523
ADD HL,BC 09
Add Register Pair BC to Register Pair HL: HL = the next variable entry.
5524
LOOP back to 54FFH for the next simple variable.
5526
ADD HL,BC 09
Not a string array: add Register Pair BC (its length word) to Register Pair HL (its dimension count byte): HL = the next array entry.

ARRAY LOOP
Register Pair HL = the array entry (type, name, 2-byte length, dimension count, dimensions, elements).

5527
LD DE,(40FDH) ED 5B FD 40
Load Register Pair DE with the 16-bit value at 40FDH, the ROM's pointer to the end of the arrays.
552B
RST 18H DF
RST 18H: compare Register Pair HL (the array entry) with Register Pair DE (the end). The Z FLAG is set at the end.
552C
RET Z C8
If the Z FLAG is set (all arrays done), RETURN.
552D
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the array's type byte.
552E
AND 0FH E6 0F
AND Register A with 0FH: Register A = the element length.
5530
CP 03H FE 03
Compare Register A against 03H: the Z FLAG is set for a string array.
5532
INC HL 23
Increment Register Pair HL to the second name character (the flags are not changed).
5533
INC HL 23
Increment Register Pair HL to the first name character.
5534
INC HL 23
Increment Register Pair HL to the low byte of the array's length word.
5535
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the low byte of the length (the bytes after the length word).
5536
INC HL 23
Increment Register Pair HL to the high byte of the array's length.
5537
LD B,(HL) 46
Load Register B with the byte at Register Pair HL. Register Pair BC now holds the array's length.
5538
INC HL 23
Increment Register Pair HL to the number of dimensions.
5539
If the NZ FLAG is set (not a string array), JUMP to 5526H to skip it.
553B
LD DE,0001H 11 01 00
Load Register Pair DE with 0001H, the start of the product of the dimensions.
553E
LD A,(HL) 7E
Load Register A with the byte at Register Pair HL, the number of dimensions.
553F
INC HL 23
Increment Register Pair HL to the first dimension word.

COUNT THE ELEMENTS
Register A = the dimensions left, Register Pair DE = the product so far.

5540
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the low byte of this dimension's size.
5541
INC HL 23
Increment Register Pair HL to the high byte of this dimension's size.
5542
LD B,(HL) 46
Load Register B with the byte at Register Pair HL. Register Pair BC now holds this dimension's size.
5543
PUSH AF F5
Save Register Pair AF (Register A = the dimensions left) on the stack.
5544
INC HL 23
Increment Register Pair HL to the next dimension word (or the first element).
5545
GOSUB to the ROM's UMULT at 0BAAH: Register Pair DE = Register Pair DE times Register Pair BC.
5548
POP AF F1
Restore Register Pair AF from the stack: Register A = the dimensions left.
5549
DEC A 3D
Decrement Register A, the dimensions still to multiply in.
554A
If the NZ FLAG is set (more dimensions), LOOP back to 5540H. Register Pair DE then holds the number of elements and HL points at the first element.

ELEMENT LOOP
Register Pair HL = the element's descriptor, Register Pair DE (on the stack) = the elements left.

554C
PUSH DE D5
Save Register Pair DE (the elements left) on the stack.
554D
GOSUB to 5558H, which fixes the string whose descriptor is at Register Pair HL and returns HL past it.
5550
POP DE D1
Restore Register Pair DE from the stack: the elements left.
5551
DEC DE 1B
Decrement Register Pair DE, the elements left to fix.
5552
LD A,D 7A
Load Register A with Register D, the high byte of the elements left.
5553
OR E B3
OR Register A with Register E, the low byte: the Z FLAG is set when none are left.
5554
If the NZ FLAG is set (more elements), LOOP back to 554CH.
5556
JUMP to 5527H for the next array, now at Register Pair HL.
5558
LD A,(HL) 7E
Fix one string: load Register A with the byte at Register Pair HL, the string's length (byte 0 of its descriptor).
5559
OR A B7
OR Register A with itself to set the flags: the Z FLAG is set for an empty string.
555A
INC HL 23
Increment Register Pair HL to the low byte of the text address.
555B
LD E,(HL) 5E
Load Register E with the byte at Register Pair HL, the low byte of the text address (for a DEF FN entry, entered here from 5513H, the pointer to the DEF).
555C
INC HL 23
Increment Register Pair HL to the high byte of the text address.
555D
LD D,(HL) 56
Load Register D with the byte at Register Pair HL. Register Pair DE now holds the text address.
555E
INC HL 23
Increment Register Pair HL past the descriptor (the flags are not changed).
555F
RET Z C8
If the Z FLAG is set (an empty string, nothing to fix), RETURN with Register A = 0.
5560
LD (5576H),A 32 76 55
Self-Modifying Code
Store Register A (the string's length, 0 for a DEF FN pointer) at 5576H, the operand of the LD A,00H at 5575H.
5563
PUSH HL E5
Save Register Pair HL (the address past the descriptor) on the stack.
5564
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with the end of the range; the operand 5565H (0000H in the file) was stored at 54F8H.
5567
NOP 00
NOP: no operation; execution goes on to the range test at 5568H.
5568
GOSUB to 5641H, which adds the offset (5642H) to Register Pair HL and returns only if the text address in Register Pair DE is not past that end; otherwise it abandons this string (5599H).
556B
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with the start of the range; the operand 556CH (0000H in the file) was stored at 54F5H.
556E
ADD HL,BC 09
Add Register Pair BC (the offset, loaded at 5641H) to Register Pair HL: HL = the corrected start of the range.
556F
GOSUB to 5649H, which returns only if the text address in Register Pair DE lies after the start in Register Pair HL; otherwise it abandons this string (5599H).
5572
XOR A AF
Load Register A with 00H (XOR A with itself).
5573
OR 00H F6 00
Self-Modifying Code
OR Register A with the mode, the operand 5574H stored at 54F2H: the Z FLAG is set for mode 0 (copy into the string space).
5575
LD A,00H 3E 00
Self-Modifying Code
Load Register A with the string's length, the operand 5576H stored at 5560H. LD does not change the flags.
5577
If the Z FLAG is set (mode 0), JUMP to 5580H to copy the string.
5579
LD HL,0000H 21 00 00
Self-Modifying Code
Load Register Pair HL with the distance the old lines move; the operand 557AH (0000H in the file) was stored at 5484H.
557C
ADD HL,DE 19
Add Register Pair DE (the old text address) to Register Pair HL: HL = the text's address after the move.
557D
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the new text address.
557E
JUMP to 5593H to store the new address in Register Pair DE in the descriptor.
5580
OR A B7
Mode 0: OR Register A (the string's length) with itself: the Z FLAG is set for a DEF FN pointer (length 0).
5581
If the NZ FLAG is set (a real string), JUMP to 5587H to copy it.
5583
LD D,A 57
A DEF FN pointer into deleted lines: load Register D with Register A (00H).
5584
LD E,A 5F
Load Register E with Register A. Register Pair DE = 0000H: the function counts as not defined.
5585
JUMP to 5593H to store Register Pair DE (0000H).
5587
PUSH DE D5
Save Register Pair DE (the old text address) on the stack.
5588
GOSUB to the ROM's GETSPA at 28BFH, which reserves Register A bytes (the length) in the string space and returns Register Pair DE = their address.
558B
POP HL E1
Restore Register Pair HL from the stack: the old text address.
558C
PUSH DE D5
Save Register Pair DE (the new text address) on the stack.
558D
LD C,A 4F
Load Register C with Register A, the string's length.
558E
LD B,00H 06 00
Load Register B with 00H, so Register Pair BC = the length.
5590
LDIR ED B0
LDIR: copy BC bytes (the string) from Register Pair HL (its text in the program) to Register Pair DE (the string space).
5592
POP DE D1
Restore Register Pair DE from the stack: the new text address.
5593
POP HL E1
Restore Register Pair HL from the stack: the address just past the descriptor.
5594
PUSH HL E5
Save Register Pair HL (the address past the descriptor) on the stack again.
5595
DEC HL 2B
Decrement Register Pair HL to the high byte of the text address in the descriptor.
5596
LD (HL),D 72
Store Register D (the high byte of the new address) at Register Pair HL.
5597
DEC HL 2B
Decrement Register Pair HL to the low byte of the text address in the descriptor.
5598
LD (HL),E 73
Store Register E (the low byte of the new address) at Register Pair HL.
5599
POP HL E1
Restore Register Pair HL from the stack: the address past the descriptor (5641H/5649H also come here when the string is out of range).
559A
XOR A AF
Load Register A with 00H (XOR A with itself): no more bytes of this value to skip.
559B
RET C9
RETURN with Register Pair HL past the descriptor and Register A = 0.

559CH - CMD"F",DELETE

Entered from BASIC 5736H for CMD"F" (from the CMD letter dispatch at BASIC 57CEH). CMD"F",DELETE range in a running program deletes the lines of the range (written as for the ROM's LIST and DELETE) without losing the variables (their strings in those lines are copied to the string space) and goes on with the line after the statement. Register Pair HL is BASIC's text pointer after the CMD string, Register A its next character.

559C
RST 08H CF
RST 08H: the character at Register Pair HL must be the byte that follows (a comma), else SYNTAX ERROR; then RST 10H moves HL on and loads Register A.
559D
DEFB 2CH 2C
Data byte 2CH (a comma), the character the RST 08H at 559CH requires after CMD"F". RST 08H returns past this byte, to 559EH.
559E
CP B6H FE B6
Compare Register A (the next character) against B6H, the BASIC token for DELETE.
55A0
If the NZ FLAG is set (not DELETE), JUMP to the ROM's SNERR at 1997H to report SYNTAX ERROR.
55A3
PUSH HL E5
Save Register Pair HL (BASIC's text pointer at the DELETE token) on the stack.
55A4
RST 10H D7
RST 10H: move Register Pair HL past DELETE to the range; Register A holds its first character.
55A5
GOSUB to the ROM's SCNLIN at 1B10H, which reads the line range at Register Pair HL: Register Pair BC returns the address of the first line of the range, and the last line's number is left on the stack.
55A8
POP DE D1
Restore Register Pair DE from the stack: the number of the last line of the range.
55A9
POP HL E1
Restore Register Pair HL from the stack: BASIC's text pointer at DELETE.
55AA
PUSH BC C5
Save Register Pair BC (the first line of the range) on the stack.
55AB
PUSH HL E5
Save Register Pair HL (the text pointer) on the stack.
55AC
GOSUB to the ROM's FNDLIN at 1B2CH, which looks for the line whose number is in Register Pair DE (the last of the range). With the Z FLAG set, Register Pair HL returns the first line after it (or the program's end); otherwise Register Pair BC holds the first line with a higher number.
55AF
If the Z FLAG is set, JUMP to 55B3H with Register Pair HL = the first line after the range.
55B1
LD H,B 60
Load Register H with Register B, the high byte of the first line after the range.
55B2
LD L,C 69
Load Register L with Register C. Register Pair HL now holds the first line after the range.
55B3
EX (SP),HL E3
Exchange Register Pair HL with the word at the top of the stack (at the Stack Pointer SP): HL = the text pointer, and the first line after the range is saved.
55B4
RST 10H D7
RST 10H: move Register Pair HL on and load Register A with the next character; the Z FLAG is set at the end of the statement.
55B5
If the NZ FLAG is set (not yet the end), LOOP back to 55B4H, skipping the range already read.
55B7
CALL 5D9FH CD 9F 5D
GOSUB to BASIC 5D9FH, which steps Register Pair HL to the next program line and stores its number at 57B8H, where 5322H finds it.
55BA
POP HL E1
Restore Register Pair HL from the stack: the first line after the range, the end of the part to delete.
55BB
POP DE D1
Restore Register Pair DE from the stack: the first line of the range.
55BC
GOSUB to 54C8H, which deletes the program from Register Pair DE up to Register Pair HL, keeping the variables.
55BF
GOSUB to 54DFH, which switches off ON ERROR GOTO, marks no file area in use and resets BASIC's stack.
55C2
JUMP to 5322H, which goes on with the line whose number is at 57B8H.

55C5H - SAVE

Entered from BASIC 5741H for SAVE (BASIC 573BH, the ROM vector 41A0H) with the file opened new in BASIC's work area (Index Register IX = 5700H, the FCB at 570DH). SAVE "file" writes the program as it is in memory, after an FFH byte, 256 bytes a sector straight from memory, then reads the file back to check it. SAVE "file",A writes it as text through the ROM's LIST. Register Pair HL is BASIC's text pointer after the file name.

55C5
CALL 638FH CD 8F 63
GOSUB to BASIC 638FH, which returns with the Z FLAG set if the statement ends at Register Pair HL, otherwise it requires a comma and returns Register A = the next character.
55C8
If the Z FLAG is set (no ,A), JUMP to 55E5H to save the program as it is in memory.
55CA
RST 08H CF
RST 08H: the character at Register Pair HL must be the byte that follows (the letter A), else SYNTAX ERROR; then RST 10H moves HL on and loads Register A.
55CB
DEFB 41H 41
Data byte 41H (the letter A), the character the RST 08H at 55CAH requires for a text save. RST 08H returns past this byte, to 55CCH.
55CC
OR A B7
OR Register A (the character after A) with itself to set the flags: the Z FLAG is set if it is 00H, the end of the line.
55CD
If the NZ FLAG is set (something follows), JUMP to the ROM's SNERR at 1997H to report SYNTAX ERROR.
55D0
PUSH HL E5
Save Register Pair HL (BASIC's text pointer) on the stack.
55D1
LD HL,FE80H 21 80 FE
Load Register Pair HL with FE80H, which is -384.
55D4
ADD HL,SP 39
Add the Stack Pointer SP to Register Pair HL: HL = 384 bytes below the stack, room for a 256-byte sector buffer.
55D5
LD (5710H),HL 22 10 57
Store Register Pair HL at 5710H-5711H, the buffer address in the FCB at 570DH (FCB + 3): the listing is collected there.
55D8
LD DE,(40F9H) ED 5B F9 40
Load Register Pair DE with the 16-bit value at 40F9H, the ROM's pointer to the start of the simple variables, the end of the program.
55DC
RST 18H DF
RST 18H: compare Register Pair HL (the buffer) with Register Pair DE (the end of the program). The CARRY FLAG is set if the buffer would lie inside the program.
55DD
If the CARRY FLAG is set (too little memory), JUMP to the ROM's OMERR at 197AH to report OUT OF MEMORY.
55E0
POP HL E1
Restore Register Pair HL from the stack: BASIC's text pointer.
55E1
XOR A AF
Load Register A with 00H (XOR A with itself), which also sets the Z FLAG: no line range follows.
55E2
JUMP to the ROM's LIST at 2B2EH, which lists the whole program; BASIC's output link (41C1H) sends the text into the open file.
55E5
PUSH HL E5
A memory-image save: save Register Pair HL (BASIC's text pointer) on the stack.
55E6
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the 16-bit value at 40A4H, the ROM's pointer to the start of the program.
55E9
DEC HL 2B
Decrement Register Pair HL: HL = the byte just before the program.
55EA
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, keeping that byte to put back after the write.
55EB
LD (HL),FFH 36 FF
Store FFH at Register Pair HL: the file's first byte marks a tokenized program.

SECTOR WRITE LOOP
Register Pair HL = the 256 bytes of memory written as the next sector, Register C = their first byte (put back after the write).

55ED
LD (5710H),HL 22 10 57
Store Register Pair HL at 5710H-5711H, the buffer address in the FCB: the sector is written straight from memory.
55F0
EX DE,HL EB
Exchange Register Pairs DE and HL: DE = the start of this sector in memory.
55F1
LD HL,(40F9H) 2A F9 40
Load Register Pair HL with the 16-bit value at 40F9H, the end of the program.
55F4
DEC H 25
Decrement Register H: HL = the end of the program minus 256.
55F5
OR A B7
OR Register A with itself to clear the CARRY FLAG for the subtraction.
55F6
SBC HL,DE ED 52
Subtract Register Pair DE (this sector's start) from Register Pair HL: the CARRY FLAG is set if less than a whole sector of program is left (this is the last sector), the Z FLAG if exactly one sector is left.
55F8
PUSH AF F5
Save Register Pair AF (these flags) on the stack.
55F9
If the NO CARRY FLAG is set (a whole sector or more), JUMP to 55FEH.
55FB
LD (IX+12H),L DD 75 12
The last sector: store Register L (the bytes of program in it) at Index Register IX + 12H (5712H), FCB + 5, the byte position that becomes the file's end.
55FE
EX DE,HL EB
Exchange Register Pairs DE and HL: HL = this sector's start in memory.
55FF
LD DE,570DH 11 0D 57
Load Register Pair DE with 570DH, the FCB of the file being saved.
5602
GOSUB to SYS0 4439H, which writes the 256 bytes at the FCB's buffer address as the next sector; the NZ FLAG is set on an error, with the DOS error code in Register A.
5605
LD (HL),C 71
Store Register C (the kept byte) back at Register Pair HL, the first byte of the sector (for the first sector this restores the byte before the program). LD does not change the flags.
5606
JP NZ,5E16H C2 16 5E
If the NZ FLAG is set (a write error), JUMP to BASIC 5E16H, which turns the DOS error in Register A into a BASIC error.
5609
INC H 24
Increment Register H: HL = the next 256 bytes of the program.
560A
LD C,(HL) 4E
Load Register C with the byte at Register Pair HL, the first byte of the next sector, kept to be put back after its write.
560B
POP AF F1
Restore Register Pair AF from the stack: the flags from 55F6H.
560C
If the CARRY FLAG is set (that was the last sector), JUMP to 5610H.
560E
If the NZ FLAG is set (more than one sector was left), LOOP back to 55EDH for the next sector. With exactly one full sector left, it was the last and execution goes on to the check.
5610
CALL 6267H CD 67 62
GOSUB to BASIC 6267H, which rewinds the file through SYS0 443FH.
5613
LD (IX+11H),00H DD 36 11 00
Store 00H at Index Register IX + 11H (5711H), the high byte of the FCB's buffer address: the sectors read back go to 00xxH, the ROM, and are lost; only the read itself is checked.

READ-BACK CHECK
Every sector is read again; a read error other than the end of the file stops SAVE with a BASIC error.

5617
CALL 6397H CD 97 63
GOSUB to BASIC 6397H, which reads the next sector through SYS0 4436H: the Z FLAG is set if it was read, the NZ FLAG at the end of the file (DOS errors 1CH/1DH), and any other error is raised as a BASIC error through 5E16H.
561A
If the Z FLAG is set (a sector was read), LOOP back to 5617H.
561C
POP HL E1
The whole file read back: restore Register Pair HL from the stack, BASIC's text pointer.
561D
JUMP to the ROM's FINPRT at 2169H, which ends the statement.

5620H - Small Helpers

5620H clears the offset at 5642H and returns Register Pair HL = 543EH. 562AH adds the last distance (557AH) to the offset and finishes 5478H. 5638H clears the offset and runs 54F2H. 5641H and 5649H are the two range tests used at 5568H and 556FH; when a string is out of range they abandon it by jumping to 5599H.

5620
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H, to clear the offset.
5623
LD (5642H),HL 22 42 56
Store Register Pair HL (0000H) at 5642H, the offset operand of the LD BC,0000H at 5641H: no distance moved yet.
5626
LD HL,543EH 21 3E 54
Load Register Pair HL with 543EH, the close-up routine, for BASIC's statement-end CALL (stored at 52DAH).
5629
RET C9
RETURN with Register Pair HL = 543EH, the close-up routine.
562A
LD HL,(5642H) 2A 42 56
Load Register Pair HL with the 16-bit value at 5642H, the offset: the distance the old lines have moved so far.
562D
LD DE,(557AH) ED 5B 7A 55
Load Register Pair DE with the 16-bit value at 557AH, the distance just applied at 5478H.
5631
ADD HL,DE 19
Add Register Pair DE to Register Pair HL: HL = the new total offset.
5632
LD (5642H),HL 22 42 56
Self-Modifying Code
Store Register Pair HL (the total offset) at 5642H, the operand of 5641H.
5635
POP DE D1
Restore Register Pair DE from the stack (saved at 5479H).
5636
POP HL E1
Restore Register Pair HL from the stack (saved at 5478H).
5637
RET C9
RETURN to the caller of 5478H with Register Pairs HL, DE and BC as they were.
5638
LD B,A 47
Load Register B with Register A (00H, from 54D5H).
5639
LD C,A 4F
Load Register C with Register A. Register Pair BC = 0000H.
563A
LD (5642H),BC ED 43 42 56
Self-Modifying Code
Store Register Pair BC (0000H) at 5642H, the offset operand of 5641H.
563E
JUMP to 54F2H with Register A = 0 (copy mode), Register Pair HL = the start and Register Pair DE = the end of the range.
5641
LD BC,0000H 01 00 00
Self-Modifying Code
Load Register Pair BC with the offset, the operand 5642H (0000H in the file), stored at 5623H, 5632H and 563AH.
5644
ADD HL,BC 09
Add Register Pair BC (the offset) to Register Pair HL (the end of the range): HL = the corrected end. The CARRY FLAG is clear afterwards for addresses in RAM.
5645
SBC HL,DE ED 52
Subtract Register Pair DE (the string's text address) from Register Pair HL (the corrected end): the CARRY FLAG is set if the text lies past the end.
5647
JUMP to 564CH with the CARRY FLAG from the subtraction.
5649
SBC HL,DE ED 52
Subtract Register Pair DE (the string's text address) from Register Pair HL (the corrected start; the CARRY FLAG is clear after ADD at 556EH): the CARRY FLAG is set if the text lies after the start.
564B
CCF 3F
Complement the CARRY FLAG: now the CARRY FLAG is set if the text does not lie after the start.
564C
RET NC D0
If the NO CARRY FLAG is set (the text is inside the range on this side), RETURN to the caller, which goes on with the string.
564D
POP AF F1
Out of range: restore Register Pair AF from the stack, discarding the return address into 5558H's code.
564E
JUMP to 5599H, which leaves the string alone and returns from 5558H with Register Pair HL past its descriptor.

5651H - Unused Bytes

5651H-56E7H fill the last load record; nothing reads or executes them.

5651-56E7
NOP x 151 00 x 151
151 zero bytes that fill the end of the file (up to 56E7H). No code jumps, calls or reads here.