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

Page Customization

Introduction / Summary

NEWDOS/80 v2.0 – SYS19/SYS – RUN/LOAD/MERGE/SAVE/DELETE Overlay

SYS19/SYS is a BASIC/CMD overlay module for the TRS-80 Model III NEWDOS/80 v2.0 Disk Operating System. It occupies the shared overlay region at 5200H–56E7H (1,256 bytes; 1,105 bytes of active code, 151 bytes of NOP padding). The overlay entry point is 5200H, which contains a CP A / RET presence-detection stub identical to SYS18.

SYS19 implements four major BASIC statement extensions:

Run/Load With V OptionRUN "filespec",V and LOAD "filespec",V load a new BASIC program while preserving all existing variables, DEFFN definitions (except those in the deleted range), and open file areas. The V option works by relocating the existing variable/array/string data upward in memory via LDDR before loading the new program, then compacting everything back via three-stage LDIR after the load completes. The R option (RUN "filespec",R) is also handled, providing run-after-load without variable preservation.
MergeMERGE "filespec" merges lines from a disk file into the currently loaded BASIC program. Supports both ASCII text files (read byte-by-byte via 60F2H, tokenized via ROM 1BC0H) and packed/tokenized program files (read sector-by-sector via SVC 4436H). The merge algorithm walks both the old program and the new file simultaneously, comparing line numbers and inserting lines in sorted order. Duplicate line numbers in MERGE mode trigger an "Illegal Function Call" error. MERGE can be executed as a direct statement or as a program statement (with restrictions).
Cmd“F”,DeleteCMD"F",DELETE ln1-ln2 dynamically deletes a range of BASIC program lines during program execution. Variables are retained (except DEFFN variables in the deleted range). String variables whose data resided in the deleted text area are relocated to the string space. The operation rebuilds the program using the merge/compaction engine. CMD"F",DELETE must be executed as a program statement (not direct), must be the last statement on its line, and must be followed by a continuation line where execution resumes.
SaveSAVE "filespec" and SAVE "filespec",A save the current BASIC program to disk. The default (no option) saves in packed binary format with an FFH start marker. The A option saves in ASCII text format. Both paths use the DOS file write routines at 4439H and 6370H.

Memory Map

Address ranges and functional areas within SYS19/SYS

AddressDescription
5200H-5201HOverlay presence stub (CP A / RET).
5202H-5254HRUN/LOAD/MERGE entry point and option parser (R/V detection, mode flag storage, FCB mode check, keyboard intercept configuration).
5255H-526EHMode branch: V-option path (ROM 1DF8H init, LDDR relocation setup) vs standard path (ROM 1B4DH fresh init).
5271H-5288HCommon file load sequence (enable guard, set 4289H bit 6, SVC 4436H read, error dispatch).
5289H-52CFHMERGE post-load memory calculation (SP safety margin, LDDR block move, pointer updates, line chain walk init).
52D0H-530EHMerge main line copy loop for packed data (INC L / CALL Z page crossing, line header read, 53B4H comparison, byte-by-byte text copy).
5310H-5331HEnd-of-merge finalization and post-load mode dispatch (3-way: 00H→1A19H warm start, 01H→1D1EH V-option run, 02H→5322H CMD"F",DELETE continuation).
5334H-5358HCMD"F",DELETE entry point (direct-mode prohibition, line range parsing, mode 02H).
535BH-53B2HMERGE-from-file line reader (byte-by-byte file I/O via 60F2H, CR/LF handling, line number parse via 1E5AH, tokenization via 1BC0H, 53B4H insertion).
53B4H-53CCHLine number comparison and insertion routine (SBC HL,BC comparison, 4-byte header write with H-byte link placeholders).
53CDH-53ECHDuplicate line handler (FFFFH sentinel check, mode 02H error, old line skip, next-line advance via 53EEH).
53EEH-53FCHOld program line header reader (link/linenum read, FFFFH sentinel injection on end-of-program).
53FEH-543CHCopy old program lines to output until insertion point (multi-line copy with header writes, byte counting at 5429H).
543EH-5475HMerge compaction: three-stage LDIR (relocate merged text, variables, string stack; update 40F9H/40FBH/40FDH; relink via 1AF8H; set reset vector via 6497H).
5478H-5494HDelta accumulator updater (output-source distance, conditional variable relocator call, delta accumulation via 562AH).
5495H-54B1HMemory region size calculator (string stack / variable-array / gap sizes into self-modifying LDIR operands).
54B2H-54C7HPage boundary / sector read handler (SVC 4436H, merge-source boundary check, out-of-memory exit).
54C8H-54DEHMerge pointer initialization (set 4 pointers, zero delta, compute sizes, jump to compaction).
54DFH-54F1HVariable relocation entry (clear 40F0H, save continuation address, disable guard, ROM 1B8FH reinit, self-modifying JP).
54F2H-5526HVariable/string pointer relocator (walk variable table 40F9H-40FBH, check type nibble, bit 7 string flag, CALL 555BH for string relocation).
5527H-5556HString descriptor stack walk (40FBH-40FDH, type 03H sub-records, ROM 0BAAH string copy).
5558H-559BHString descriptor reader/relocator (range check via 5641H/5649H, delta adjust, string space allocation via ROM 28BFH, LDIR copy).
559CH-55C2HCMD"F",DELETE range parser (RST 08H comma check, B6H DELETE token, ROM 1B10H range parse, ROM 1B2CH line search, merge/compact/relocate flow).
55C5H-55E4HSAVE/MERGE ASCII file handler (A option, SP−384 memory check, 5710H buffer limit, JP 2B2EH ASCII I/O).
55E5H-561DHDefault SAVE path (FFH marker, SVC 4439H write loop, 6370H terminator, JP 2169H cleanup).
5620H-5629HMerge delta accumulator initializer (zero 5642H, return HL=543EH).
562AH-5637HDelta accumulation and return (add 557AH to 5642H, restore DE/HL).
5638H-5640HDelta zero and variable relocate (zero 5642H via BC, JP 54F2H).
5641H-564EHRange comparison utilities (lower and upper bound checks, out-of-range exit to 5599H).
5651H-56E7HNOP padding (151 bytes of 00H).

SYS19 — Variables and Self-Modifying Code

Self-Modifying Code Locations

SYS19 makes extensive use of self-modifying code for mode switching, pointer tracking, and parameter passing. The following locations have their operand bytes modified at runtime.

AddressDescription
5255HBranch override opcode. Operand of JR Z,526BH at 5255H. Written by: 5228H. Initial value: 28H (JR Z). Runtime values: 18H (JR unconditional, for default/R mode - always branches to standard path at 526BH), 3EH (LD A,nn for V mode - consumes 14H displacement byte and falls through to V-option path at 5257H).
5315HMode flag. Operand of LD A,00H at 5314H. Written by: 5220H, 5355H. Values: 00H = standard load (no option), 01H = R or V option, 02H = CMD"F",DELETE mode. Read by: 5316H (post-load dispatch), 53D3H (duplicate line handler), 5242H (V-option validation).
5429HCurrent program position byte count. Operand of LD BC,0000H at 5428H. Written by: 52C3H, 5437H, 54CEH. Values: the accumulated byte count of old program lines copied during the merge. Read by: 548AH (delta updater).
5442HMerge output position. Operand of LD DE,0000H at 5441H. Written by: 52E6H, 535FH, 5408H, 54D2H. Values: the current write address in the merge output area. Read by: 547BH (delta updater), 543EH (compaction).
5459HVariable/array area size. Operand of LD BC,0000H at 5458H. Written by: 54AEH (via 5495H). Values: 40FBH − 40F9H. Used by: second LDIR in merge compaction at 545FH.
5466HString stack size. Operand of LD BC,0000H at 5465H. Written by: 549FH (via 5495H). Values: 40FDH − 40FBH. Used by: third LDIR in merge compaction at 546CH.
547FHMerge source start. Operand of LD DE,0000H at 547EH. Written by: 52C6H, 5404H, 54CBH. Values: the start address of the current block of old program text being processed. Read by: 5478H (delta updater).
5488HString space start snapshot. Operand of LD DE,0000H at 5487H. Written by: 54A7H (via 5495H). Values: 40F9H value at time of calculation. Read by: 5487H (delta updater), passed to 54F2H.
5512HString relocation mode flag. Operand of LD A,00H at 5511H. Written by: earlier variable walker code. Controls whether the string descriptor relocator at 5513H performs relocation or read-only scanning.
5565HRelocator lower bound (string space start). Operand of LD HL,0000H at 5564H. Written by: 54F8H (via 54F2H). Read by: 5564H (string descriptor relocator).
556CHRelocator upper bound reference (program position). Operand of LD HL,0000H at 556BH. Written by: 54F5H (via 54F2H). Read by: 556BH (string descriptor relocator).
5574HRelocation flag. Operand of OR 00H at 5573H. Written by: 54F2H. Values: nonzero if relocation delta should be applied, 00H if not. Read by: 5573H.
5576HString length. Operand of LD A,00H at 5575H. Written by: 5560H. Values: the byte length of the current string being relocated. Read by: 5575H.
557AHMerge delta (output − source distance). Operand of LD HL,0000H at 5579H. Written by: 5484H (via 5478H). Values: the signed distance between the merge output and source positions. Read by: 5579H (string address adjustment), 562DH (delta accumulation).
53DCHCurrent merge position. Operand of LD HL,0000H at 53DBH. Written by: 52B2H, 53EEH, 54C8H. Values: the address of the current position in the old program data during the merge walk. Read by: 53FEH, 5444H, 54BEH.
54F0HVariable relocation continuation address. Operand of JP 0000H at 54EFH. Written by: 54E6H. Values: the address to jump to after BASIC reinit (file load sequence for V-option, post-delete handler for CMD"F",DELETE).
5642HDelta accumulator (running total). Operand of LD BC,0000H at 5641H. Written by: 5623H, 5632H, 563AH. Values: the cumulative relocation delta across all merge iterations. Read by: 5641H (lower bound range check), 562AH (delta accumulation).

External Writes to BASIC/CMD Addresses

SYS19 modifies several locations in the BASIC/CMD main module (5700H-684BH range) and DOS/BASIC system RAM to control mode switching, keyboard interception, and program state.

AddressDescription
4289H
Bit 6
DOS state flags. SET at 5277H to signal that a program load is in progress.
4478HExecution hook byte. Written at 5252H. Values: C3H (JP enables keyboard intercept hook for V-option), C9H (RET disables hook for standard/ASCII loads).
40F0HBASIC program line chain head pointer. Cleared to 0000H at 54E2H to empty the program before variable-preserving reload.
40F9HString space start pointer. Updated at 52B8H (MERGE relocation), 5454H (compaction stage 1).
40FBHArray end / variable top pointer. Updated at 52BDH (MERGE relocation), 5461H (compaction stage 2).
40FDHString stack pointer. Updated at 52AAH (MERGE relocation), 546EH (compaction stage 3).
5710HSYS19 communication byte in FCB work area. Written at 55D5H (ASCII SAVE buffer limit) and 55EDH (packed SAVE file start). Read by file I/O routines to determine buffer boundaries.
5FA8HClose-all-files return byte. Written at 5224H. Values: C9H (RET makes close-all return unconditionally, preserving open files for V-option), C8H (RETZ normal close behavior).
63FAHKeyboard intercept flag. Written at 524EH. Values: C9H (RET enable intercept for V-option), 00H (disable for standard/ASCII).
6427HReset vector. Written at 52DAH. Value: 543EH (merge compaction handler address, installed as the reset handler during merge operations).

Major Routine Reference

Entry points and functional units within SYS19/SYS.

AddressRoutineDescription
5200HOverlay Presence StubCP A / RET. Returns with Z set to confirm SYS19 is loaded.
5202HMain Entry PointRUN/LOAD/MERGE option parser. Parses R/V options, stores mode flags to 5315H/5FA8H/5255H, branches to V-option or standard path.
5255HMode BranchSelf-modifying JR Z/LD A. Splits V-option path (5257H: ROM 1DF8H, LDDR relocation) from standard path (526BH: ROM 1B4DH fresh init).
5271HCommon File LoadEnable guard, set 4289H bit 6, SVC 4436H read, error dispatch (1CH→5314H, other→5DEFH).
5289HMerge Memory CalculationCompute total memory requirement, SP−160 safety check, LDDR block move upward, update 40F9H/40FBH/40FDH.
52C0HInitialize Merge Line WalkSet pointers 5429H/547FH, begin reading old program link/linenum chain.
52E6HMerge Main Loop (Packed)Walk old program with INC L / CALL Z,54B2H page crossing, read line headers, call 53B4H, copy text bytes.
5314HPost-Load Mode Dispatch3-way dispatch: 00H→ROM 1A19H, 01H→ROM 1D1EH, 02H→5322H.
5322HCMD"F",DELETE Post-Delete HandlerRead continuation line from 57B8H, search via ROM 1B2CH, execute at found line.
5334HCMD"F",DELETE Entry40A2H direct-mode check, CALL 5D78H, FCB mode adjust, store mode 02H, enter merge flow.
535BHMerge-From-File ReaderByte-by-byte file read via 60F2H, CR/LF line assembly, parse line number (1E5AH), tokenize (1BC0H), insert via 53B4H.
53B4HLine Comparison and InsertionSBC HL,BC comparison of old vs new line numbers. Less: old line first (53BFH). Equal: duplicate handler (53CDH). Greater: insert new line (53FEH).
53EEHOld Line Header ReaderSave position to 53DCH, read link/linenum, inject FFFFH sentinel on end-of-program.
53FEHCopy Old Lines Until InsertionLoop: write old line header + text to output, count bytes in 5429H, advance via 53EEH, compare until old ≥ new.
543EHMerge CompactionThree-stage LDIR: (1) merged text from 53DCH to 5442H, (2) variable/array area (5459H bytes), (3) string stack (5466H bytes). Update 40F9H/40FBH/40FDH, relink via 1AF8H, JP 6497H.
5478HDelta Accumulator UpdaterCalculate 5442H−547FH, store to 557AH, conditional CALL NZ 54F2H, JP 562AH accumulate.
5495HRegion Size CalculatorCompute 40FDH−40FBH → 5466H, 40FBH−40F9H → 5459H, 40F9H → 5488H.
54B2HPage Boundary HandlerSVC 4436H sector read, merge boundary check (53DCH−256 vs DE), out-of-memory at 54C5H.
54C8HMerge Pointer InitSet 53DCH/547FH/5429H/5442H, zero delta via 5638H, compute sizes via 5495H, JP 543EH.
54DFHVariable Relocation EntryClear 40F0H, save continuation at 54F0H, CALL 6392H disable guard, CALL 1B8FH reinit, self-modifying JP.
54F2HVariable/String RelocatorWalk variable table (40F9H-40FBH), check type nibble and bit 7 string flag, CALL 555BH for string relocation. Walk string stack (40FBH-40FDH), handle type 03H with sub-records via ROM 0BAAH.
5558H / 555BHString Descriptor Reader/RelocatorRead 3-byte descriptor, range check via 5641H/5649H, apply delta from 557AH or allocate new string via ROM 28BFH + LDIR copy.
559CHCMD"F",DELETE Range ParserRST 08H ⇒ 2CH, CP B6H DELETE token, ROM 1B10H range parse, ROM 1B2CH line search, CALL 54C8H + 54DFH, JP 5322H.
55C5HASCII SAVE/MERGE HandlerComma check, RST 08H ⇒ 41H (A option), SP−384 memory check, store 5710H, JP 2B2EH.
55E5HPacked SAVE PathFFH marker at (40A4H−1), SVC 4439H write loop, restore original byte, 6370H terminator, JP 2169H.
5620HDelta InitializerZero 5642H, return HL=543EH.
562AHDelta AccumulationAdd 557AH to 5642H, POP DE/HL, RET.
5638HDelta Zero + RelocateZero 5642H, JP 54F2H.
5641H / 5649HRange Check UtilitiesLower/upper bound comparisons for string relocation range. Out-of-range exits via 564EH to 5599H.

ROM Routines Called

AddressRoutineDescription
5200HOverlay Presence StubCP A / RET. Returns with Z set to confirm SYS19 is loaded.
5202HMain Entry PointRUN/LOAD/MERGE option parser. Parses R/V options, stores mode flags to 5315H/5FA8H/5255H, branches to V-option or standard path.
5255HMode BranchSelf-modifying JR Z/LD A. Splits V-option path (5257H: ROM 1DF8H, LDDR relocation) from standard path (526BH: ROM 1B4DH fresh init).
5271HCommon File LoadEnable guard, set 4289H bit 6, SVC 4436H read, error dispatch (1CH→5314H, other→5DEFH).
5289HMerge Memory CalculationCompute total memory requirement, SP−160 safety check, LDDR block move upward, update 40F9H/40FBH/40FDH.
52C0HInitialize Merge Line WalkSet pointers 5429H/547FH, begin reading old program link/linenum chain.
52E6HMerge Main Loop (Packed)Walk old program with INC L / CALL Z,54B2H page crossing, read line headers, call 53B4H, copy text bytes.
5314HPost-Load Mode Dispatch3-way dispatch: 00H→ROM 1A19H, 01H→ROM 1D1EH, 02H→5322H.
5322HCMD"F",DELETE Post-Delete HandlerRead continuation line from 57B8H, search via ROM 1B2CH, execute at found line.
5334HCMD"F",DELETE Entry40A2H direct-mode check, CALL 5D78H, FCB mode adjust, store mode 02H, enter merge flow.
535BHMerge-From-File ReaderByte-by-byte file read via 60F2H, CR/LF line assembly, parse line number (1E5AH), tokenize (1BC0H), insert via 53B4H.
53B4HLine Comparison and InsertionSBC HL,BC comparison of old vs new line numbers. Less: old line first (53BFH). Equal: duplicate handler (53CDH). Greater: insert new line (53FEH).
53EEHOld Line Header ReaderSave position to 53DCH, read link/linenum, inject FFFFH sentinel on end-of-program.
53FEHCopy Old Lines Until InsertionLoop: write old line header + text to output, count bytes in 5429H, advance via 53EEH, compare until old ≥ new.
543EHMerge CompactionThree-stage LDIR: (1) merged text from 53DCH to 5442H, (2) variable/array area (5459H bytes), (3) string stack (5466H bytes). Update 40F9H/40FBH/40FDH, relink via 1AF8H, JP 6497H.
5478HDelta Accumulator UpdaterCalculate 5442H−547FH, store to 557AH, conditional CALL NZ 54F2H, JP 562AH accumulate.
5495HRegion Size CalculatorCompute 40FDH−40FBH → 5466H, 40FBH−40F9H → 5459H, 40F9H → 5488H.
54B2HPage Boundary HandlerSVC 4436H sector read, merge boundary check (53DCH−256 vs DE), out-of-memory at 54C5H.
54C8HMerge Pointer InitSet 53DCH/547FH/5429H/5442H, zero delta via 5638H, compute sizes via 5495H, JP 543EH.
54DFHVariable Relocation EntryClear 40F0H, save continuation at 54F0H, CALL 6392H disable guard, CALL 1B8FH reinit, self-modifying JP.
54F2HVariable/String RelocatorWalk variable table (40F9H-40FBH), check type nibble and bit 7 string flag, CALL 555BH for string relocation. Walk string stack (40FBH-40FDH), handle type 03H with sub-records via ROM 0BAAH.
5558H/555BHString Descriptor Reader/RelocatorRead 3-byte descriptor, range check via 5641H/5649H, apply delta from 557AH or allocate new string via ROM 28BFH + LDIR copy.
559CHCMD"F",DELETE Range ParserRST 08H ⇒ 2CH, CP B6H DELETE token, ROM 1B10H range parse, ROM 1B2CH line search, CALL 54C8H + 54DFH, JP 5322H.
55C5HASCII SAVE/MERGE HandlerComma check, RST 08H ⇒ 41H (A option), SP−384 memory check, store 5710H, JP 2B2EH.
55E5HPacked SAVE PathFFH marker at (40A4H−1), SVC 4439H write loop, restore original byte, 6370H terminator, JP 2169H.
5620HDelta InitializerZero 5642H, return HL=543EH.
562AHDelta AccumulationAdd 557AH to 5642H, POP DE/HL, RET.
5638HDelta Zero + RelocateZero 5642H, JP 54F2H.
5641H/5649HRange Check UtilitiesLower/upper bound comparisons for string relocation range. Out-of-range exits via 564EH to 5599H.

ROM entry points (0000H-37FFH) used by SYS19

AddressDescription
0BAAHString block copy (string descriptor stack relocation, at 5545H).
1997HBASIC syntax error handler, ?SN ERROR (at 521CH, 5352H, 55A0H, 55CDH).
197AHOut of memory error handler, ?OM ERROR (at 54C5H, 55DDH).
1A19HBASIC warm start / command loop (at 5317H, mode 00H exit).
1AF8HBASIC program relink routine (at 5472H, merge compaction).
1B10HLine number range parser (at 55A5H, CMD"F",DELETE).
1B2CHBASIC line search by line number in DE (at 5326H, 55ACH).
1B4DHBASIC init routine, clear variables and files (at 526EH, standard path).
1B8FHBASIC system reinitialization (at 54ECH, variable relocation entry).
1BC0HBASIC line tokenizer (at 53A3H, MERGE-from-file).
1D1EHProgram execution with variable preservation (at 531FH, 532EH).
1DF8HBASIC runtime init preserving variables (at 5257H, V-option).
1E4AH"Illegal Function Call" error (at 53D8H, duplicate line in DELETE mode).
1E5AHBASIC expression evaluator, ASCII to integer (at 5393H).
2169HPost-SAVE cleanup (at 561DH).
28BFHString space allocation (at 5588H, string relocator).
2B2EHASCII SAVE/LOAD processing (at 55E2H).

BASIC/CMD Routines Called (SYS0 Range)

Routines in the BASIC/CMD main module (4000H-56FFH range, accessed via the SYS0 page) called by SYS19.

AddressDescription
4436HRead disk sector / move logical record from FCB buffer (at 527CH, 54B6H).
4439HWrite without verify a sector to disk (at 5602H, packed SAVE).
5D78HLine+Var routine (at 533DH, 55B7H).
5DB8HError/recovery path (at 5390H).
5DBBHError exit (at 53D0H, end-of-merge sentinel match).
5DEFHError translator (at 5283H, 54B9H, 5606H).
6240HDOS operation (at 5610H, SAVE finalize).
6368HComma checker (at 5206H, 55C5H).
6370HFile write + filter (at 5617H, SAVE terminator).
6386HEnable guard (at 5271H).
6392HDisable guard (at 526BH, 54E9H).
6497HSet reset vector (at 5475H, merge compaction exit).
60F2HFile read (at 536CH, MERGE-from-file byte read).

RST Vectors Used

VectorDescription
RST 08HInline character match (at 559CH ⇒ 2CH comma, at 55CAH ⇒ 41H letter A).
RST 10HFetch next non-space character (at 521BH, 5351H, 538BH, 55A4H, 55B4H).
RST 18H16-bit compare HL vs DE (at 52A4H, 5503H, 552BH, 55DCH, 54C2H).

Key Analysis Notes

Architectural observations and design patterns discovered during the disassembly analysis

  1. The overlay stub at 5200H (CP A / RET) is identical to SYS18. Both overlays share the same 5200H-56E7H address range and are loaded on demand. Only one can be resident at a time.
  2. The option parser at 5202H-5228H uses an elegant opcode-patching scheme: Register B carries the opcode byte (18H=JR, 3EH=LD A,nn) that will be written to 5255H. When 3EH, it converts the JR Z,526BH instruction into LD A,14H, consuming the branch displacement as an immediate operand and causing fall-through to the V-option path. This avoids a separate conditional branch instruction.
  3. The MERGE memory relocation uses a two-phase approach: (a) LDDR at 52AFH moves all existing data (variables, arrays, string descriptors, string stack) upward to create a gap at the program area for the merged lines, then (b) three-stage LDIR at 543EH-546EH compacts everything back down after the merge is complete. The SP−160 safety margin at 529BH and the 256-byte boundary check at 54BDH prevent the relocation from colliding with the stack.
  4. The merge line comparison at 53B4H-53BBH uses SBC HL,BC + ADD HL,BC to perform a non-destructive comparison. The SBC sets the carry and zero flags based on old_line − new_line, then ADD restores HL to its original value. Three outcomes: carry (old < new → copy old first), zero (duplicate → error or skip), neither (old > new → insert new line).
  5. The 4-byte line header written at 53C3H-53CAH and 541CH-5424H uses LD (HL),H for both link pointer bytes. This writes the current page address (H) as a temporary placeholder. The actual link pointers are fixed by ROM 1AF8H (relink) during the compaction phase at 5472H.
  6. The FFFFH sentinel (set at 52D3H and 53F9H) ensures that the merge algorithm terminates correctly when one program is exhausted before the other. Since FFFFH (65535) is higher than any valid BASIC line number (max 65529), any remaining lines from the other source will always compare as "less than" and be appended.
  7. The variable/string relocator at 54F2H-559BH is a sophisticated pointer-adjustment engine. It walks two data structures (variable table and string descriptor stack), identifies string pointers that fall within the relocated address range (using 5641H/5649H for lower/upper bound checks), and either adjusts the pointer by the merge delta (at 5579H) or allocates new string space (via ROM 28BFH at 5588H) and copies the string data (via LDIR at 5590H). This ensures that strings whose data resided in the deleted or relocated text area remain accessible after the merge/delete.
  8. The delta accumulator at 5642H tracks the cumulative address offset caused by all merge insertions. Each call to 5478H computes the local delta (output position − source position), stores it at 557AH, and the call to 562AH adds it to the running total at 5642H. The accumulated delta is used by the range check at 5641H to determine the correct lower bound for string pointer relocation.
  9. CMD"F",DELETE shares most of its code with MERGE. The mode flag at 5315H (value 02H) controls the behavioral differences: the post-load dispatch at 5314H routes to the continuation-line handler at 5322H, and the duplicate-line check at 53CDH raises an "Illegal Function Call" error instead of skipping the old line.
  10. The SAVE path at 55E5H-561DH temporarily writes FFH to the byte before the program start (40A4H−1), saves the original byte in C, writes the program data in 256-byte chunks via SVC 4439H, then restores the original byte. The FFH marker identifies the start of a packed BASIC program file.
  11. The INC L / CALL Z,54B2H pattern in the packed merge loop (52E6H-530EH) is an efficient page-boundary handler. INC L only affects the low byte of HL, so when L wraps from FFH to 00H, the Z flag triggers a sector read. This avoids a full 16-bit increment and comparison on every byte, at the cost of assuming page-aligned data boundaries.
  12. SYS19 is the companion to SYS18 (BASIC direct statement executor). SYS18 handles LIST, EDIT, DELETE (direct mode), DI, DU, AUTO, RENEW, and dispatches RENUM/REF. SYS19 handles the program-mode file operations: RUN/LOAD with options, MERGE, CMD"F",DELETE, and SAVE. Both share the 5200H overlay space.

Disassembly

5200H - Overlay Presence Stub

SYS19 Overlay Detection Stub. This two-byte sequence serves as a presence test for the SYS19 overlay. Callers execute CALL 5200H and test the Z flag on return. CP A always sets Z (any value compared against itself is equal), so if SYS19 is loaded, Z is set. If SYS19 is not loaded, the memory at 5200H contains whatever was previously there (from a different overlay or uninitialized RAM), and the test fails.

5200
CP A BF
Compare Register A against itself. This always sets the Z FLAG (Zero), because any value equals itself. This is the overlay presence test — callers CALL 5200H and check Z to confirm SYS19 is loaded.
5201
RET C9
RETURN to the caller with the Z FLAG set, confirming SYS19 is present in memory.

5202H - RUN/LOAD/MERGE Entry Point and Option Parser

Main entry point for SYS19. This routine handles the extended RUN, LOAD, and MERGE statements with optional V (variable-preserving) and R modifiers. On entry, the BASIC statement parser has already consumed the filespec and the comma separator; HL points to the next character in the BASIC text. The code parses any trailing option letter, stores mode flags into three self-modifying code targets (5315H, 5FA8H, 5255H), then branches to the V-option path (variable-preserving load) or the standard load path.

5202
LD BC,18C8H 01 C8 18
Load Register Pair BC with the default mode values: Register B = 18H and Register C = C8H. These are opcode bytes that will be stored into self-modifying code locations later. C8H is the opcode for RET Z (the default value written to 5FA8H, which is the close-all-files return at the end of BASIC/CMD). 18H is the opcode for JR (a relative jump, the default value written to 5255H). These defaults represent the standard (non-V, non-R) behavior.
5205
POP DE D1
Restore Register Pair DE from the stack. DE holds the return context saved by the calling BASIC statement handler before entering SYS19.
5206
GOSUB to 6368H, the Comma Checker routine in BASIC/CMD. This routine checks whether the next character in the BASIC text (pointed to by HL) is a comma (2CH). If a comma is found, it advances HL past it, fetches the next non-space character into Register A, and returns with the NZ FLAG set. If no comma is found (end of statement), it returns with the Z FLAG set.
5209
NO OPTIONS — use defaults
If the Z FLAG has been set (no comma found — no option letter follows the filespec), JUMP forward to 521AH to skip option parsing and proceed with default mode values in BC.

A comma was found after the filespec, and Register A now holds the first character of the option. Check whether it is R (52H) or V (56H).

520B
CP 52H FE 52
Compare Register A against 52H (ASCII R). If Register A equals 52H, the Z FLAG is set; otherwise the NZ FLAG is set.
520D
R OPTION
If the Z FLAG has been set (the option letter is R), JUMP forward to 5215H. The R option uses the same C=C9H value as the default but sets D=01H to signal run-after-load. Register B retains its default 18H.
520F
CP 56H FE 56
Compare Register A against 56H (ASCII V). If Register A equals 56H, the Z FLAG is set; otherwise the NZ FLAG is set.
5211
UNKNOWN OPTION — ignore
If the NZ FLAG has been set (the option letter is neither R nor V), JUMP forward to 521AH to treat the unknown character as end-of-statement. The defaults in BC remain unchanged.

The option letter is V (variable-preserving mode). Override the defaults: B = 3EH (the opcode for LD A,nn — a two-byte NOP that skips the next byte), C = C9H (RET Z opcode, same as default).

5213
LD B,3EH 06 3E
Load Register B with 3EH. 3EH is the opcode for LD A,nn. When stored at self-modifying code target 5255H, it converts the JR Z instruction there into LD A,14H (consuming the next byte as an immediate operand instead of executing a branch). This disables the branch at 5255H, causing execution to fall through into the V-option path at 5257H.
5215
LD C,C9H 0E C9
SELF-MODIFYING CODE TARGET
Load Register C with C9H, the opcode for RET. This is stored at 5FA8H (the close-all-files return in BASIC/CMD). For both the R and V options, 5FA8H receives C9H to keep the existing close-all behavior.
5217
LD D,01H 16 01
Load Register D with 01H, signaling that an option (R or V) was specified. This value is stored at 5315H (the mode flag variable) to distinguish option-present from the default no-option case (D=00H).
5219
INC HL 23
INCrement Register Pair HL by 1, advancing the BASIC text pointer past the option letter (R or V) so that the end-of-statement check at 521BH sees the next character.

All paths converge here. Register D holds the mode flag (00H = no option, 01H = R or V option). Register C holds the close-all opcode (C8H or C9H). Register B holds the branch override opcode (18H = JR for default/R, 3EH = LD A for V). Now verify end-of-statement and store the mode values.

521A
DEC HL 2B
DECrement Register Pair HL by 1, backing up the BASIC text pointer by one position. This compensates for RST 10H's auto-advance behavior, ensuring the pointer is correctly positioned for the end-of-statement check.
521B
RST 10H D7
Fetch the next non-space character from the BASIC text at (HL) into Register A, advancing HL past any spaces. If the character is a digit (30H–39H), the CARRY FLAG is set. If the statement has ended (colon 3AH or end-of-line 00H), the Z FLAG is set.
521C
ERROR EXIT
If the NZ FLAG has been set (additional characters remain after the option — the statement is malformed), JUMP to ROM 1997H, the BASIC Syntax Error handler (?SN ERROR). A valid RUN/LOAD/MERGE statement must end after the optional letter.

521FH - Store Mode Flags to Self-Modifying Code Targets

Stores the parsed option values (from Registers B, C, D) into three self-modifying code locations that control behavior throughout SYS19 and BASIC/CMD. Then checks the FCB status flags to determine whether variable-preserving mode can actually be applied.

521F
LD A,D 7A
Load Register A with the contents of Register D, which holds the mode flag: 00H if no option was specified, 01H if R or V was specified.
5220
LD (5315H),A 32 15 53
SELF-MODIFYING CODE
Store Register A (the mode flag, 00H or 01H) to memory location 5315H. This is the operand of a LD A,00H instruction at 5314H. At runtime, 5314H will load this stored value into Register A to test which mode is active.
5223
LD A,C 79
Load Register A with the contents of Register C, which holds the close-all-files opcode: C8H (RET Z, the default) or C9H (RET, for R/V options).
5224
LD (5FA8H),A 32 A8 5F
SELF-MODIFYING CODE — BASIC/CMD 5FA8H
Store Register A (the close-all opcode, C8H or C9H) to memory location 5FA8H. This is a self-modifying code target in the BASIC/CMD close-all-files routine at 5FA7H. Writing C9H (RET) makes the close-all routine return unconditionally without closing files, preserving open file areas during RUN/LOAD with the V option. Writing C8H (RET Z) restores normal close behavior.
5227
LD A,B 78
Load Register A with the contents of Register B, which holds the branch override opcode: 18H (JR, for default/R mode) or 3EH (LD A,nn, for V mode).
5228
LD (5255H),A 32 55 52
SELF-MODIFYING CODE
Store Register A (the branch override opcode, 18H or 3EH) to memory location 5255H. This is the opcode byte of the JR Z,526BH instruction at 5255H. When 18H (JR), the branch executes normally, skipping the V-option code at 5257H–526AH. When 3EH (LD A,nn), the branch is disabled: the 14H displacement byte becomes the immediate operand of LD A, and execution falls through to 5257H (the V-option path).

Now check the FCB status flags (IX+0EH) to determine whether this file is in a mode that supports variable preservation. The low 3 bits of IX+0EH encode the file access mode. A value of 06H means the file is open for both read and write (mode 6 = read+write+special), which is required for V-option behavior. Values below 06H indicate simpler access modes.

522B
LD A,(IX+0EH) DD 7E 0E
Fetch the FCB tertiary flags byte from IX+0EH into Register A. IX points to the current FCB (File Control Block). The low 3 bits of this byte encode the file access mode: bit 0 = read, bit 1 = write, bit 2 = random.
522E
AND 07H E6 07
Mask Register A with 07H to isolate the low 3 bits (the file access mode). This clears any higher flag bits.
5230
CP 06H FE 06
Compare Register A (the file access mode, 0–7) against 06H. If Register A < 06H, the CARRY FLAG is set. If Register A >= 06H, the NO CARRY FLAG is set. Mode 06H means read+write (bits 1 and 2 set), indicating a packed BASIC program file.
5232
PACKED FILE PATH
If the NO CARRY FLAG has been set (the file access mode is 06H or 07H — a packed file), JUMP forward to 5240H to check whether the V-option flag is set. Packed files can support variable-preserving mode.

The file access mode is less than 06H (an ASCII or simpler file mode). Check the DOS flags at 428CH to see if this is a MERGE operation (bit 6 set).

5234
LD A,(428CH) 3A 8C 42
Fetch the DOS state byte from memory location 428CH into Register A. Bit 6 of this byte indicates whether a MERGE operation is in progress.
5237
BIT 6,A CB 77
Test bit 6 of Register A (the DOS state byte at 428CH). If bit 6 is set, the NZ FLAG is set, indicating a MERGE operation. If bit 6 is clear, the Z FLAG is set.
5239
MERGE PATH
If the NZ FLAG has been set (bit 6 of 428CH is set — this is a MERGE operation), JUMP forward to 5255H. MERGE uses an ASCII file mode (not packed), so it skips the packed-file V-option logic and goes directly to the branch decision at 5255H.

Not a MERGE, and the file is not a packed program file. This is an ASCII LOAD. Disable the keyboard intercept and force standard (non-V) mode regardless of what was parsed, since ASCII loads cannot preserve variables.

523B
LD B,C9H 06 C9
Load Register B with C9H. This will overwrite 4478H (the execution hook) with C9H (RET), disabling the keyboard intercept for ASCII loads.
523D
XOR A AF
Set Register A to 00H and clear all flags. A=00H will be written to 63FAH to disable the keyboard intercept flag.
523E
FORCE STANDARD MODE
JUMP forward to 524EH to store A=00H into the keyboard intercept flag at 63FAH and B=C9H into the execution hook at 4478H. This forces standard mode for ASCII file loads.

5240H - Packed File V-Option Validation

For packed BASIC program files (access mode >= 06H), this section validates whether the V-option can be applied. If the mode is exactly 06H and the V flag is set, the FCB access mode is decremented and the execution hook is configured for variable-preserving behavior. If the mode is not exactly 06H, execution falls through to the branch decision.

5240
MODE 07H — skip V-option
If the NZ FLAG has been set (the file access mode from the CP 06H at 5230H is not equal to 06H — it is 07H), JUMP forward to 5255H. Mode 07H (all three low bits set) indicates a special access mode that does not support V-option modification.

The file access mode is exactly 06H (packed program file, read+write). Check whether the V-option flag at 5315H was set by the parser.

5242
LD A,(5315H) 3A 15 53
Fetch the mode flag from self-modifying code location 5315H into Register A. This value was stored at 5220H: 00H if no option was specified, 01H if R or V was specified.
5245
OR A B7
OR Register A with itself to set the flags. If A is 00H (no option), the Z FLAG is set. If A is 01H (option present), the NZ FLAG is set.
5246
NO OPTION — use defaults
If the Z FLAG has been set (no R or V option was specified), JUMP forward to 5255H. Without an explicit option, no variable-preservation modifications are needed.

The V-option (or R-option) was specified and the file is a packed program. Decrement IX+0EH to change the access mode from 06H to 05H, signaling to downstream routines that variable-preserving load is active. Then configure the execution hook for V-mode behavior.

5248
DEC (IX+0EH) DD 35 0E
DECrement the FCB tertiary flags byte at IX+0EH by 1. This changes the access mode from 06H to 05H. The decremented value (05H = read + random, without write) signals to the file loading routines that variable preservation is requested.
524B
LD B,C3H 06 C3
Load Register B with C3H, the opcode for JP nn. This will be stored at 4478H (the execution hook in BASIC/CMD). Writing C3H enables the execution hook as an unconditional jump (JP) to the address that follows at 4479H–447AH, activating the keyboard intercept during variable-preserving execution.
524D
LD A,C 79
Load Register A with the contents of Register C, which holds C9H (the RET opcode). This value will be stored at 63FAH as the keyboard intercept flag.
524E
LD (63FAH),A 32 FA 63
SELF-MODIFYING CODE — BASIC/CMD 63FAH
Store Register A to memory location 63FAH, the Keyboard Intercept Flag in BASIC/CMD. For V-option mode, A=C9H (enabling the intercept). For ASCII loads forced to standard mode, A=00H (disabling the intercept).
5251
LD A,B 78
Load Register A with the contents of Register B, which holds the execution hook opcode: C3H (JP) for V-option, C9H (RET) for forced standard mode from the ASCII path at 523BH, or the original B value (18H) if this instruction is reached from another path.
5252
LD (4478H),A 32 78 44
SELF-MODIFYING CODE — BASIC/CMD 4478H
Store Register A to memory location 4478H, the Execution Hook byte in BASIC/CMD. Writing C3H (JP) activates the hook as an unconditional jump to the handler address at 4479H–447AH. Writing C9H (RET) deactivates the hook, making it return immediately.

5255H - Mode Branch: V-Option vs Standard Load

This is the key decision point that splits execution between the V-option (variable-preserving) path and the standard (non-V) path. The opcode at 5255H is self-modifying: when the V-option is active, the opcode has been changed from 28H (JR Z) to 3EH (LD A,nn), which disables the branch and causes execution to fall through into the V-option initialization code at 5257H. When the V-option is not active, the original JR Z branches to 526BH for standard load behavior.

5255
[SELF-MODIFYING CODE] The opcode byte 28H at this address is overwritten by the value stored at 5228H. When B=18H (default/R mode): the opcode becomes 18H (JR 526BH), an unconditional jump to the standard load path. When B=3EH (V mode): the opcode becomes 3EH (LD A,14H), consuming the 14H displacement byte as an immediate operand and falling through to 5257H, the V-option path. The Z FLAG from the preceding LD (4478H),A at 5252H determines whether the original 28H (JR Z) branches or not — but only if the opcode has not been modified.

V-option path. The file is a packed BASIC program and the V-option was specified. Before loading the new program, save the current BASIC state. CALL 1DF8H initializes the ROM BASIC for a new program load while preserving variables. Then set up the merge pointers for variable-preserving reload.

5257
GOSUB to ROM routine at 1DF8H. This ROM routine initializes the BASIC runtime for loading a new program while preserving the existing variable table. It resets the program pointer without clearing variables or closing files.
525A
LD DE,(40A4H) ED 5B A4 40
Load Register Pair DE with the contents of memory locations 40A4H–40A5H, which hold the BASIC Program Start Address. This is the address where the BASIC program text begins in memory.
525E
LD HL,(40F9H) 2A F9 40
Load Register Pair HL with the contents of memory locations 40F9H–40FAH, which hold the String Space Start pointer. This marks the bottom of the string storage area, which sits above the BASIC program and variable tables in memory.
5261
DEC HL 2B
DECrement Register Pair HL by 1. Back up 2 bytes from the string space start to point to the last byte of the variable/array area. Combined with the next DEC, this positions HL at the end of the data that needs to be preserved during the merge/reload.
5262
DEC HL 2B
DECrement Register Pair HL by 1 again. HL now points 2 bytes below the string space start, which is the last used byte of the BASIC variable/array storage area.
5263
GOSUB to 54C8H, the Merge Pointer Initialization routine. This stores the current BASIC program start (DE), string space end (HL), and program start into the self-modifying pointer variables at 53DCH, 547FH, 5429H, and 5442H. It also calls 5495H to calculate memory region sizes and 543EH to begin the merge relocation sequence.
5266
V-OPTION SETUP COMPLETE
GOSUB to 54DFH, the Variable Relocation routine. This routine clears the BASIC program line chain (writes 0000H to 40F0H), saves and restores the merge context, disables the guard flag via CALL 6392H, calls ROM 1B8FH for BASIC system reinitialization, then jumps to the entry address stored at 54F0H to complete the variable-preserving reload.
5269
JUMP forward to 5271H to continue with the file load sequence. This skips the standard (non-V) initialization at 526BH–526EH and proceeds directly to enabling the guard flag and loading the program file.

526BH - Standard Load Path (Non-V Mode)

Standard (non-variable-preserving) RUN/LOAD path. Disables the guard flag and calls ROM 1B4DH to initialize the BASIC runtime for a fresh program load, clearing all variables and closing all files. Then falls through to the common file-load sequence at 5271H.

526B
GOSUB to 6392H, the Disable Guard routine in BASIC/CMD. This writes 00H to the guard flag at 6382H, disabling the guard check. The guard flag is a self-modifying code byte that, when C9H (RET), causes certain routines to return early as a reentrancy guard.
526E
GOSUB to ROM routine at 1B4DH, the BASIC Init routine. This resets the BASIC runtime state for a fresh program: clears all variables, resets the program pointer, deallocates string space, and closes all open files. After this call, the BASIC environment is clean and ready to load a new program.

5271H - Common File Load Sequence

Common path for both V-option and standard modes. Enables the guard flag, sets bit 6 of the DOS state flags at 4289H, then calls SVC 4436H to load the program file using the filespec at 570DH. On success (Z flag), continues to the MERGE path. On error 1CH (position error), redirects to the MERGE-after-load handler. On any other error, dispatches to the BASIC/CMD error translator at 5DEFH.

5271
GOSUB to 6386H, the Enable Guard routine in BASIC/CMD. This writes C9H (RET) to the guard flag at 6382H, enabling the reentrancy guard so that certain routines return early if called recursively during the file load.
5274
LD HL,4289H 21 89 42
Point Register Pair HL to memory location 4289H, the DOS State Flags byte. This byte contains various status bits used by the DOS and BASIC/CMD.
5277
SET 6,(HL) CB F6
SET bit 6 of the byte at (HL), which is the DOS state flags at 4289H. Bit 6 signals to the file I/O routines that a program load operation is in progress. This prevents certain cleanup actions from interfering with the load.
5279
LD DE,570DH 11 0D 57
Point Register Pair DE to memory location 570DH, the Filename Buffer in the BASIC/CMD FCB work area. This buffer contains the filespec (drive, filename, extension) of the program file to be loaded, set up by the RUN/LOAD/MERGE statement handler before calling SYS19.
527C
GOSUB to 4436H to READ a disk sector or move a logical record from the FCB’s buffer to the caller’s buffer. This SVC entry reads the program file identified by the filespec at DE=570DH. On success, the Z FLAG is set and the program text has been loaded into memory starting at the BASIC program area (40A4H). On error, Register A holds the error code and the NZ FLAG is set.
527F
SUCCESS PATH
If the Z FLAG has been set (the file read completed successfully with no error), JUMP forward to 5289H to begin the MERGE post-load processing sequence.

The file read returned an error. Check whether it is error code 1CH (position error — before start of file), which is expected when the file has been fully read and the position is at EOF. Any other error is fatal.

5281
CP 1CH FE 1C
Compare Register A (the error code from the file read) against 1CH (decimal 28 — Position Error, Before Start Of File). If Register A equals 1CH, the Z FLAG is set; otherwise the NZ FLAG is set.
5283
ERROR EXIT
If the NZ FLAG has been set (the error code is not 1CH — an unexpected error occurred during the file read), JUMP to 5DEFH, the Error Translator routine in BASIC/CMD. This translates the DOS error code in Register A to a BASIC error number and dispatches to the appropriate error handler.
5286
JUMP forward to 5314H, the Post-Load Mode Dispatch routine. The file read returned error 1CH, which signals that the entire file has been loaded (the read position reached EOF). At 5314H, the mode flag stored at 5315H determines the next action: 00H continues with a normal BASIC warm start, 01H (V-option) enters the RUN-with-variables path, 02H enters the CMD"F",DELETE completion path.

5289H - MERGE Post-Load: Memory Size Calculation

After a successful file read (for MERGE), this section calculates whether enough memory is available to accommodate the merged program. It computes the total size of the new program text plus the existing data (variables, arrays, strings) and checks that the result fits below the current stack pointer with a safety margin of 160 bytes (A0H). If memory is sufficient, it performs an LDDR block move to relocate the existing data upward to make room for the merged text, then updates all the BASIC memory pointers (string space, variable start, array end, string stack).

5289
GOSUB to 5495H, the Memory Region Size Calculator. This routine computes the sizes of three memory regions above the BASIC program: (1) 40FDH−40FBH = string stack size (stored at 5466H), (2) 40F9H = string space start (stored at 5488H), and (3) 40FBH−40F9H = variable/array area size (stored at 5459H). Returns with HL = (40FDH), DE = (40FBH), and BC = string stack size in 54A2H–54A3H.
528C
PUSH HL E5
Save Register Pair HL onto the stack. HL holds the value from (40FDH), the String Stack Top pointer (the highest address used by the string descriptor stack).
528D
ADD HL,BC 09
ADD Register Pair BC (the string stack size from the calculator) to Register Pair HL (the string stack top from 40FDH). The result in HL is the total end of used memory: string stack top + string stack size = the absolute upper limit of data that must be relocated.
528E
LD B,H 44
Copy Register H to Register B, transferring the high byte of the total data end address to BC.
528F
LD C,L 4D
Copy Register L to Register C. Now BC = HL = the total data end address (string stack top + string stack size).
5290
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the contents of memory locations 40A4H–40A5H, the BASIC Program Start Address. This is where the BASIC program text begins in memory.
5293
EX DE,HL EB
Exchange Register Pairs DE and HL. After this: DE = BASIC program start (40A4H value), HL = the value previously in DE (the string stack top from the 5495H call, which is 40FBH). Wait — DE was loaded at 5495H. Let me re-trace: after 5495H, HL = 40FDH value, DE = 40FBH value, BC = string stack size. At 528CH, HL was pushed. At 528DH, HL = 40FDH + BC. At 528E–528FH, BC = 40FDH + string_stack_size. At 5290H, HL = 40A4H value. Now EX DE,HL: DE = 40A4H value (program start), HL = 40FBH value (array end / variable top).
5294
OR A B7
Clear the CARRY FLAG in preparation for the 16-bit subtraction that follows. OR A does not change Register A but resets the carry.
5295
SBC HL,DE ED 52
SUBtract Register Pair DE (the BASIC program start address, from 40A4H) from Register Pair HL (the array end pointer, from 40FBH) with borrow. The result HL = 40FBH − 40A4H = the size of the BASIC program text + variable area. This is the amount of data between the program start and the end of the array table.
5297
PUSH HL E5
Save Register Pair HL onto the stack. HL holds the program + variable area size (40FBH − 40A4H). This will be used later to recalculate the variable start after the LDDR relocation.
5298
ADD HL,BC 09
ADD Register Pair BC (the total data end address from 528E–528FH) to Register Pair HL (the program + variable size). The result is the projected total memory requirement: where the end of all data would be after the merged program is in place.
5299
LD B,H 44
Copy Register H to Register B, transferring the high byte of the projected memory end to BC.
529A
LD C,L 4D
Copy Register L to Register C. Now BC = the projected total memory end after the merge.

Calculate the maximum safe memory address by subtracting 160 bytes (A0H) from the current stack pointer. This reserves 160 bytes of stack safety margin to prevent the relocated data from colliding with the stack during the LDDR move.

529B
LD HL,FF60H 21 60 FF
Load Register Pair HL with FF60H. This is −160 in two's complement (FF60H = 65,376 decimal, which when added to SP gives SP − 160). The 160-byte margin ensures the block move does not overwrite the active stack.
529E
ADD HL,SP 39
ADD the current Stack Pointer value to Register Pair HL. Result: HL = SP − 160, the lowest safe address for the top of relocated data.
529F
EX DE,HL EB
Exchange Register Pairs DE and HL. After this: DE = SP − 160 (safe memory ceiling), HL = the previous DE (BASIC program start from 40A4H, still in DE from the 5293H exchange).
52A0
LD HL,(40FDH) 2A FD 40
Load Register Pair HL with the contents of memory locations 40FDH–40FEH, the String Stack Pointer. This is the current top of the string descriptor stack, the highest address actively used by BASIC data structures.
52A3
INC H 24
INCrement Register H by 1, adding 256 to the string stack pointer. This provides an additional 256-byte safety margin above the string stack for the memory sufficiency check.
52A4
RST 18H DF
Compare Register Pair HL (string stack + 256) against Register Pair DE (SP − 160). RST 18H performs a 16-bit comparison: if HL < DE, the CARRY FLAG is set. If HL >= DE, the NO CARRY FLAG is set. This checks whether there is enough room between the string stack top and the stack pointer for the merged data.
52A5
OUT OF MEMORY ERROR
If the NO CARRY FLAG has been set (the string stack + 256 is at or above SP − 160 — there is not enough memory for the merge), JUMP to 54C5H. That address contains JP 197AH, which dispatches to the ROM Out of Memory error handler.

Memory check passed. There is enough room for the merge. Proceed with the LDDR block move to relocate the existing data (variables, arrays, string descriptors) upward in memory to make room for the merged program text. The move goes from high addresses to low addresses (LDDR = block move decrementing).

52A8
DEC H 25
DECrement Register H by 1, undoing the INC H at 52A3H. HL is restored to the actual string stack pointer value from (40FDH).
52A9
DEC HL 2B
DECrement Register Pair HL by 1. HL now points to the last byte of the string stack area, one below the string stack pointer. This is the source end address for the LDDR block move.
52AA
LD (40FDH),DE ED 53 FD 40
Store Register Pair DE (which holds SP − 160, the safe memory ceiling) to memory locations 40FDH–40FEH, updating the String Stack Pointer to its new relocated position. The string stack will be moved to end at this new address after the LDDR.
52AE
DEC DE 1B
DECrement Register Pair DE by 1. DE now points to the destination end address for the LDDR block move (one below the new string stack pointer).
52AF
LDDR ED B8
Execute the LDDR (Load, Decrement, Repeat) block move instruction.
Source
HL = last byte of the old string stack area (40FDH − 1).
Destination
DE = last byte of the new string stack position (SP − 161).
Byte Count
BC = the projected total memory end from 5298H–529AH.
Direction
Decrementing (high to low). This moves the entire data block (variables, arrays, string descriptors, string stack) upward in memory to create a gap at the bottom for the merged program text. After completion, DE points to the byte before the first relocated byte, and HL points to the byte before the first source byte.
52B1
INC DE 13
INCrement Register Pair DE by 1. DE now points to the first byte of the relocated data block. This is the new base address where the string space / variable area starts after relocation.
52B2
LD (53DCH),DE ED 53 DC 53
SELF-MODIFYING CODE
Store Register Pair DE (the new data base address after relocation) to memory location 53DCH. This is a self-modifying pointer variable used by the MERGE line chain walker as the Current Merge Position — the address where new merged line data will be inserted.

Update the BASIC memory management pointers to reflect the new data positions after the LDDR move.

52B6
POP HL E1
Restore Register Pair HL from the stack. HL holds the program + variable area size (40FBH − 40A4H), saved at 5297H.
52B7
ADD HL,DE 19
ADD Register Pair DE (the new data base address) to Register Pair HL (the program + variable size). The result HL = new_base + (old_40FBH − old_40A4H) = the new string space start position.
52B8
LD (40F9H),HL 22 F9 40
Store Register Pair HL (the new string space start) to memory locations 40F9H–40FAH, updating the String Space Start pointer to its new relocated position.
52BB
POP BC C1
Restore Register Pair BC from the stack. BC holds the string stack top value saved at 528CH (the old 40FDH value).
52BC
ADD HL,BC 09
ADD Register Pair BC (the old string stack top) to Register Pair HL (the new string space start). The result HL = new_string_space + old_string_stack = the new array end / variable top pointer.
52BD
LD (40FBH),HL 22 FB 40
Store Register Pair HL (the new variable/array end pointer) to memory locations 40FBH–40FCH, updating the Array End / Variable Top pointer to its new relocated position.

52C0H - Initialize MERGE Line Chain Walk

After relocating the existing data upward, initialize the pointers for walking the BASIC program line chain during the MERGE operation. The code stores the program start address into the merge tracking variables at 5429H and 547FH, then begins reading the first line’s link pointer and line number from the program text.

52C0
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the contents of memory locations 40A4H–40A5H, the BASIC Program Start Address. HL now points to the first byte of the BASIC program text (the link pointer of the first line).
52C3
LD (5429H),HL 22 29 54
SELF-MODIFYING CODE
Store Register Pair HL (the BASIC program start) to memory location 5429H. This self-modifying pointer variable tracks the Current Program Position during the merge — it records how much of the existing program has been copied to the merge output area.
52C6
LD (547FH),HL 22 7F 54
SELF-MODIFYING CODE
Store Register Pair HL (the BASIC program start) to memory location 547FH. This self-modifying pointer variable holds the Merge Source Start — the beginning of the current block of existing program text that needs to be copied during the merge output phase.
52C9
EX DE,HL EB
Exchange Register Pairs DE and HL. After this: DE = BASIC program start (the value just stored), HL = the new data base address from the LDDR relocation (still in DE from 52B2H and subsequent arithmetic). Actually, at this point, HL was loaded from (40A4H) at 52C0H, so after EX DE,HL: DE = 40A4H value (program start), HL = whatever was in DE. Tracing back: after 52BDH, HL was updated. Let me re-trace the register state at 52C9H. After 52BDH: HL = new_40FBH value. After 52BBH POP BC: BC = old 40FDH. After 52BCH ADD HL,BC: HL = new_40FBH + old_40FDH... This needs reconsideration. The EX DE,HL swaps so that the merge line walk can use HL as the read pointer and DE as something else. The key point: at 52CAH, HL is used as a pointer to read from the program text, so HL must equal the program start. Since 52C0H loaded HL = (40A4H) and 52C3H/52C6H only stored HL, HL still = (40A4H). Then EX DE,HL puts the program start into DE and something into HL. But 52CAH does LD A,(HL) — so HL must point to the data. Wait: re-reading: 52C0H loads HL=(40A4H). 52C3H stores it. 52C6H stores it. 52C9H EX DE,HL — now DE = program start, HL = old DE. What was in DE? After 52BDH, the most recent DE change was... Let me trace from 52B2H: DE = new data base. 52B6H POP HL. 52B7H ADD HL,DE. 52B8H store HL. 52BBH POP BC. 52BCH ADD HL,BC. 52BDH store HL. At this point DE still = new data base from 52B2H/52B1H. So at 52C9H: EX DE,HL gives HL = new data base, DE = program start. But 52CAH does LD A,(HL) reading the first byte... That would be reading from the relocated data area, not the program. This does not make sense for reading program lines. Let me reconsider: perhaps HL at 52C9H is meant to read from the NEW merged file data that was loaded. The MERGE reads a file into the program area, and the existing program was relocated upward. So the program area (40A4H onward) now contains the NEWLY LOADED merged text, and the OLD program was moved up. HL = new data base (the old program relocated up), DE = 40A4H (where the new merged text sits). The EX sets HL = new data base (old program, relocated) and DE = 40A4H (new merged text). At 52CAH, LD A,(HL) reads the first byte of the OLD program at its new location. This makes sense: the merge walks the OLD program lines to interleave them with the new file.

Begin reading the first line of the OLD program (now relocated upward after the LDDR). The BASIC line structure is: [link_low][link_high][linenum_low][linenum_high][tokenized text...][00H]. HL points to the first byte of the relocated old program. Read the link pointer (2 bytes) and line number low byte.

52CA
LD A,(HL) 7E
Fetch the low byte of the first line’s link pointer from (HL) into Register A. HL points to the start of the relocated old BASIC program. The link pointer is the address of the next line in the chain (2 bytes, little-endian). If this is 0000H, the program is empty.
52CB
INC HL 23
INCrement Register Pair HL by 1, advancing to the high byte of the link pointer.
52CC
OR (HL) B6
OR Register A (the link pointer low byte) with the byte at (HL) (the link pointer high byte). If both bytes are 00H (link = 0000H, meaning end of program), the result is 00H and the Z FLAG is set. If either byte is nonzero (a valid link exists), the NZ FLAG is set.
52CD
INC HL 23
INCrement Register Pair HL by 1, advancing to the low byte of the line number field (offset +2 from line start).
52CE
LD C,(HL) 4E
Fetch the low byte of the line number from (HL) into Register C. The line number is stored as a 16-bit value at offsets +2 and +3 of the BASIC line structure.
52CF
INC HL 23
INCrement Register Pair HL by 1, advancing to the high byte of the line number field (offset +3 from line start). The next instruction (at 52D0H, in the following chunk) will load the high byte into Register B, giving BC = the complete 16-bit line number of the first old program line.

52D0H - Complete Line Number Read and End-of-Program Check

Continues the BASIC line chain walk started at 52CAH. Loads the high byte of the current line number into Register B (completing BC = full 16-bit line number), then checks whether the link pointer was 0000H (end of program). If so, sets BC = FFFFH as a sentinel that will always compare higher than any real line number, ensuring that all remaining file lines are appended at the end. Pushes the line number and initializes the merge delta accumulator.

52D0
LD B,(HL) 46
Fetch the high byte of the current line number from (HL) into Register B. Combined with the LD C,(HL) at 52CEH, Register Pair BC now holds the complete 16-bit line number of the current old program line. HL has been advanced past the 4-byte line header (link_low, link_high, linenum_low, linenum_high) and now points to the first byte of the tokenized line text.
52D1
VALID LINE — continue
If the NZ FLAG has been set (the link pointer OR at 52CCH produced a nonzero result, meaning the program has more lines), JUMP forward to 52D6H to continue with the valid line number in BC.

The link pointer was 0000H (end of the old program). Set BC to the maximum sentinel value FFFFH (65535). This ensures that during the merge comparison, every remaining line from the merge file will have a line number less than FFFFH, so all file lines will be appended at the end of the merged output.

52D3
LD BC,FFFFH 01 FF FF
Load Register Pair BC with FFFFH (65535 decimal), the end-of-program sentinel. No old program line can have a line number this high, so the merge comparison at 53B7H will always find that the file line number is less than FFFFH, causing all remaining file lines to be inserted.
52D6
PUSH BC C5
Save Register Pair BC (the current old program line number, or FFFFH sentinel) onto the stack. This value will be used by the line comparison routine at 53B4H/53B7H to determine whether the next file line should be inserted before or after the current old program line.
52D7
GOSUB to 5620H, the Merge Delta Accumulator Initializer. This routine loads HL with 0000H, stores it to the delta accumulator at 5642H, loads HL with the address of the merge compaction routine at 543EH, and returns. The return value in HL (543EH) is the merge completion handler address.
52DA
LD (6427H),HL 22 27 64
SELF-MODIFYING CODE — BASIC/CMD 6427H
Store Register Pair HL (which holds 543EH, the merge compaction handler address returned by 5620H) to memory location 6427H, the Reset Vector in BASIC/CMD. This installs the merge compaction routine as the handler that will be called when the merge operation completes or when the system needs to finalize the merged program.

52DDH - PDRIVE Table Check: ASCII vs Packed Merge

Checks the first byte of the PDRIVE table at 4300H to determine whether the current operation is merging from an ASCII file or a packed file. If the first PDRIVE entry is not FFH (the table contains valid drive entries), the file is being read as a packed/tokenized program, and execution branches to the MERGE-from-file reader at 535BH. If the first entry is FFH (the default uninitialized state), the program data has already been loaded into the program area, and the merge proceeds inline.

52DD
LD HL,4300H 21 00 43
Point Register Pair HL to memory location 4300H, the start of the PDRIVE Table. The PDRIVE table contains four 16-byte drive parameter entries at 4300H–433FH.
52E0
LD A,(HL) 7E
Fetch the first byte of the PDRIVE table from (HL) into Register A. If this byte is FFH, the PDRIVE entry is uninitialized (no drive parameters configured at this slot). If it is any other value, the entry contains valid drive configuration data.
52E1
CP FFH FE FF
Compare Register A against FFH. If Register A equals FFH, the Z FLAG is set (PDRIVE entry is uninitialized). If Register A does not equal FFH, the NZ FLAG is set (valid PDRIVE entry exists).
52E3
MERGE FROM FILE PATH
If the NZ FLAG has been set (the PDRIVE table contains a valid entry — a file is being read from disk), JUMP to 535BH, the MERGE-From-File Line Reader. That routine reads lines from the open file one at a time and merges them into the existing program.

52E6H - Merge Main Line Copy Loop (Packed Data)

Main merge loop for packed (in-memory) program data. Walks the relocated old program line by line, reading each line’s link pointer and line number through a series of INC L / CALL Z,54B2H steps. The INC L advances through the 4-byte line header (link_low, link_high, linenum_low, linenum_high), while CALL Z,54B2H handles page boundary crossings (when L wraps to 00H, a new sector must be read). Once the line number is loaded into BC, calls 53B4H to compare it against the current merge file line and decide whether to insert the file line or copy the old program line. After the line comparison, copies the tokenized line text byte by byte to the merge output area at (DE), then loops back for the next line.

52E6
LD (5442H),DE ED 53 42 54
SELF-MODIFYING CODE
Store Register Pair DE (the current merge output write pointer) to memory location 5442H. This self-modifying variable tracks the Merge Output Position — where the next byte of merged program data will be written.
52EA
INC L 2C
INCrement Register L by 1, advancing the read pointer within the current page. HL is walking through the relocated old program data. If L wraps from FFH to 00H, the Z FLAG is set, triggering the page boundary handler.
52EB
If the Z FLAG has been set (Register L wrapped to 00H — the read pointer crossed a 256-byte page boundary), GOSUB to 54B2H, the Page Boundary / Sector Read Handler. This routine reads the next sector from the file (via SVC 4436H at the filespec 570DH), handles read errors by jumping to 5DEFH, and checks whether the merge destination has caught up to the source position. Returns with HL updated to the new read position.
52EE
LD C,(HL) 4E
Fetch the low byte of the next line’s link pointer from (HL) into Register C. This is the first byte of the 4-byte line header: [link_low].
52EF
INC L 2C
INCrement Register L by 1, advancing to the high byte of the link pointer.
52F0
If the Z FLAG has been set (page boundary crossing), GOSUB to 54B2H for the page boundary handler.
52F3
LD A,C 79
Load Register A with the contents of Register C (the link pointer low byte).
52F4
OR (HL) B6
OR Register A (link low byte) with the byte at (HL) (the link pointer high byte). If both bytes are 00H (link = 0000H, end of program), the result is 00H and the Z FLAG is set. If the link is nonzero, the NZ FLAG is set.
52F5
END OF OLD PROGRAM
If the Z FLAG has been set (the link pointer is 0000H — all old program lines have been processed), JUMP forward to 5310H to finalize the merge and dispatch to the post-load mode handler.
52F7
INC L 2C
INCrement Register L by 1, advancing to the low byte of the line number field (offset +2 in the line header).
52F8
If the Z FLAG has been set (page boundary crossing), GOSUB to 54B2H for the page boundary handler.
52FB
LD C,(HL) 4E
Fetch the low byte of the line number from (HL) into Register C.
52FC
INC L 2C
INCrement Register L by 1, advancing to the high byte of the line number field (offset +3 in the line header).
52FD
If the Z FLAG has been set (page boundary crossing), GOSUB to 54B2H for the page boundary handler.
5300
LD B,(HL) 46
Fetch the high byte of the line number from (HL) into Register B. BC now holds the complete 16-bit line number of the current old program line.
5301
GOSUB to 53B4H, the Line Number Comparison and Insertion routine. This compares the old program line number in BC against the current merge file line number (on the stack). If the file line number is less than or equal to BC, the file line is inserted into the output first. If the old line number is less, the old line header is written to the output. Returns with the merge output pointer updated in DE.

[LOOP BODY] Copy the tokenized line text byte by byte from the old program (at HL) to the merge output area (at DE). Each byte is read from (HL), checked for the end-of-line marker (00H), stored to (DE), and both pointers are advanced. The loop continues until a 00H terminator is found.

5304
INC L 2C
INCrement Register L by 1, advancing the read pointer to the next byte of the tokenized line text.
5305
If the Z FLAG has been set (page boundary crossing), GOSUB to 54B2H for the page boundary handler.
5308
LD A,(HL) 7E
Fetch the next byte of the tokenized line text from (HL) into Register A.
5309
OR A B7
OR Register A with itself to set the flags. If the byte is 00H (end-of-line terminator), the Z FLAG is set. Otherwise, the NZ FLAG is set.
530A
LD (DE),A 12
Store Register A (the current line text byte, or 00H terminator) to the merge output at (DE).
530B
INC DE 13
INCrement Register Pair DE by 1, advancing the merge output write pointer to the next position.
530C
LOOP — copy line text
If the NZ FLAG has been set (the byte was not the 00H end-of-line terminator), JUMP back to 5304H to copy the next byte.
530E
LOOP — next line
JUMP back to 52E6H to save the updated output pointer and begin processing the next old program line.

5310H - End of Merge / Merge Finalization

Reached when all old program lines have been processed (link pointer = 0000H at 52F5H) or when the MERGE-from-file reader finishes reading all file lines. Pops the saved line number, calls the merge compaction routine at 543EH to relocate the merged data back to its final position, then falls through to the post-load mode dispatch at 5314H.

5310
POP AF F1
Pop and discard the saved line number from the stack (pushed at 52D6H). The line number is no longer needed because all lines have been processed.
5311
GOSUB to 543EH, the Merge Compaction routine. This performs the final memory compaction after the merge: calls the delta accumulator updater at 5478H, then uses up to three LDIR block moves to relocate the merged program text, variables, arrays, and string stack back to their final positions in memory. Updates the BASIC memory pointers 40F9H, 40FBH, and 40FDH, calls ROM 1AF8H to relink the BASIC program line chain, and jumps to 6497H to set the reset vector.

5314H - Post-Load Mode Dispatch

After the file has been loaded (or merge completed), this dispatch reads the mode flag from self-modifying location 5315H and branches to the appropriate handler. Mode 00H (no option) goes to ROM 1A19H for a standard BASIC warm start. Mode 01H (V-option or R-option) goes to ROM 1D1EH for variable-preserving run continuation. Mode 02H (CMD"F",DELETE) goes to the RUN-after-delete handler at 5322H.

5314
LD A,00H 3E 00
[SELF-MODIFYING CODE] Load Register A with the mode flag. The operand byte at 5315H was written by 5220H (or 5355H for CMD"F",DELETE mode). Values: 00H = no option (standard load), 01H = R or V option (variable-preserving), 02H = CMD"F",DELETE mode.
5316
OR A B7
OR Register A with itself to set the flags. If A = 00H (no option), the Z FLAG is set. If A is nonzero (01H or 02H), the NZ FLAG is set.
5317
STANDARD LOAD COMPLETE
If the Z FLAG has been set (mode = 00H, standard load with no option), JUMP to ROM 1A19H. This is the BASIC Warm Start entry that restarts the BASIC command loop after a successful program load. It displays the READY prompt and waits for user input.

Mode is nonzero (01H or 02H). Check which mode.

531A
LD HL,(40A4H) 2A A4 40
Load Register Pair HL with the contents of memory locations 40A4H–40A5H, the BASIC Program Start Address. HL points to the beginning of the newly loaded program text.
531D
DEC HL 2B
DECrement Register Pair HL by 1. HL now points one byte before the BASIC program start. This positions HL for ROM 1D1EH, which expects HL to point to the byte before the program text (the standard BASIC text pointer convention, where HL is pre-decremented before the first RST 10H fetch).
531E
DEC A 3D
DECrement Register A by 1. If A was 01H (V/R option), it becomes 00H and the Z FLAG is set. If A was 02H (CMD"F",DELETE mode), it becomes 01H and the NZ FLAG is set.
531F
V-OPTION / R-OPTION RUN
If the Z FLAG has been set (original mode was 01H — V or R option), JUMP to ROM 1D1EH. This ROM routine initiates program execution while preserving variables. HL points to one byte before the program text, and execution begins at the first line.

5322H - CMD"F",DELETE Post-Delete Run Handler

After CMD"F",DELETE has completed the line deletion (mode = 02H), this routine reads the continuation line number from the self-modifying variable at 57B8H, searches for that line in the BASIC program via ROM 1B2CH, and positions HL just before the found line for execution to continue. If the continuation line is not found exactly, it checks whether a higher-numbered line exists (for JP Z,1D1EH) or reports a syntax error.

5322
LD DE,(57B8H) ED 5B B8 57
SELF-MODIFYING CODE — BASIC/CMD 57B8H
Load Register Pair DE with the contents of memory locations 57B8H–57B9H. This is the LOAD/SAVE Flag storage in BASIC/CMD, which CMD"F",DELETE has repurposed to hold the continuation line number — the line number where execution should resume after the deletion.
5326
GOSUB to ROM routine at 1B2CH, the BASIC Line Search. This searches the BASIC program line chain for the line with number DE. On return: if the exact line is found, the Z FLAG is set and BC points to the line. If the exact line is not found, the NZ FLAG is set, BC points to the next higher-numbered line (or end of program), and the CARRY FLAG indicates whether the requested line is beyond all existing lines.
5329
LD H,B 60
Copy Register B (high byte of the line address from 1B2CH) to Register H.
532A
LD L,C 69
Copy Register C (low byte of the line address from 1B2CH) to Register L. HL now holds the address of the found (or next-higher) BASIC line.
532B
DEC HL 2B
DECrement Register Pair HL by 1. HL now points one byte before the found line, conforming to the BASIC text pointer convention expected by ROM 1D1EH (the execution entry that pre-increments before fetching).
532C
LINE FOUND OR BEYOND
If the NO CARRY FLAG has been set (the requested continuation line number is within or beyond the program range — 1B2CH found it or found a higher line), JUMP forward to 5331H. The CARRY FLAG is clear when 1B2CH found the line or a line beyond it.
532E
CONTINUE EXECUTION AT LINE
If the Z FLAG has been set (the exact continuation line was found by 1B2CH, AND the CARRY FLAG is set meaning the line is before the end), JUMP to ROM 1D1EH to begin execution at the continuation line with HL pointing one byte before it.
5331
ERROR EXIT
JUMP to ROM 1997H, the BASIC Syntax Error handler (?SN ERROR). The continuation line specified after the CMD"F",DELETE range was not found in the program (it was deleted or never existed).

5334H - CMD"F",DELETE Entry Point

Entry point for the CMD"F",DELETE statement handler. This routine is reached from the BASIC/CMD CMD"F" dispatcher when the DELETE keyword is recognized. It checks whether 40A2H is FFFFH (indicating direct-mode execution, which is prohibited), parses the line number range parameters, adjusts the FCB access mode for V-option behavior, stores mode flag 02H to 5315H, and then jumps back to 5266H to enter the common merge/delete flow which will delete the specified lines by rebuilding the program without them.

5334
LD DE,(40A2H) ED 5B A2 40
Load Register Pair DE with the contents of memory locations 40A2H–40A3H, the System Configuration word. When BASIC is executing a direct (immediate) command, this value is set to FFFFH. When executing a program statement, it holds a different value.
5338
LD A,D 7A
Load Register A with the contents of Register D (the high byte of the 40A2H value).
5339
AND E A3
AND Register A (high byte) with Register E (low byte). If both bytes are FFH (direct mode, 40A2H = FFFFH), the result is FFH. If either byte is not FFH, the result is less than FFH.
533A
INC A 3C
INCrement Register A by 1. If A was FFH (from FFFFH AND), it wraps to 00H and the Z FLAG is set. If A was anything else, the result is nonzero and the NZ FLAG is set. This tests whether 40A2H = FFFFH (direct mode).
533B
DIRECT MODE PATH
If the Z FLAG has been set (40A2H = FFFFH — CMD"F",DELETE is being executed as a direct statement, which is prohibited), JUMP forward to 5350H. That path checks for end-of-statement and either processes the remaining parameters or reports a syntax error.

CMD"F",DELETE is being executed as a program statement (40A2H ≠ FFFFH). Parse the line number range parameters. CALL 5D78H to read the first line number and variable context.

533D
GOSUB to 5D78H, the Line+Var routine in BASIC/CMD. This routine evaluates a line number expression from the BASIC text and returns the result in DE. It also sets up IX to point to the current FCB and establishes the variable context for the CMD"F",DELETE operation.
5340
LD A,(IX+0EH) DD 7E 0E
Fetch the FCB tertiary flags byte from IX+0EH into Register A. The low 3 bits encode the file access mode.
5343
AND 07H E6 07
Mask Register A with 07H to isolate the low 3 bits (file access mode).
5345
CP 06H FE 06
Compare Register A (the file access mode) against 06H. Mode 06H means read+write (packed program file).
5347
NOT MODE 06H
If the NZ FLAG has been set (the file access mode is not 06H), JUMP forward to 534CH to skip the mode decrement.
5349
DEC (IX+0EH) DD 35 0E
DECrement the FCB tertiary flags byte at IX+0EH by 1, changing the access mode from 06H to 05H. This signals to downstream routines that variable-preserving behavior is active for the CMD"F",DELETE operation, just as in the V-option path at 5248H.
534C
LD A,02H 3E 02
Load Register A with 02H, the mode flag value for CMD"F",DELETE. This distinguishes the DELETE path from V-option (01H) and standard (00H) modes in the post-load dispatch at 5314H.
534E
JUMP forward to 5355H to store the mode flag and enter the common merge/delete flow.

5350H - Direct Mode CMD"F",DELETE Redirect

When CMD"F",DELETE is executed as a direct statement (prohibited per the manual), this path checks for end-of-statement. If valid end-of-statement, it falls through to store the mode flag. If not, it reports a syntax error. This allows certain limited direct-mode operations while blocking the full DELETE operation.

5350
DEC HL 2B
DECrement Register Pair HL by 1, backing up the BASIC text pointer by one position to prepare for the RST 10H fetch.
5351
RST 10H D7
Fetch the next non-space character from the BASIC text at (HL) into Register A. If the statement has ended (colon 3AH or end-of-line 00H), the Z FLAG is set.
5352
ERROR EXIT
If the NZ FLAG has been set (additional characters remain — the statement is malformed for direct mode), JUMP to ROM 1997H, the BASIC Syntax Error handler (?SN ERROR).
5355
LD (5315H),A 32 15 53
SELF-MODIFYING CODE
Store Register A (the mode flag: 02H for CMD"F",DELETE, or 00H for direct-mode pass-through) to memory location 5315H, the self-modifying mode flag operand at 5314H.
5358
ENTER COMMON MERGE FLOW
JUMP back to 5266H, the CALL 54DFH instruction in the V-option path. This enters the common variable relocation and merge flow. For CMD"F",DELETE, the merge will rebuild the program without the deleted lines, then the post-load dispatch at 5314H will route to the CMD"F",DELETE handler at 5322H (mode 02H).

535BH - MERGE-From-File Line Reader

Handles MERGE when lines are being read from an open disk file (the PDRIVE table at 4300H had a valid entry). Decrements IX+17H to adjust the file position, reads lines from the file one byte at a time via CALL 60F2H (the BASIC/CMD File Read routine), assembles each line in the buffer at (40A7H), parses the line number, and calls 53B4H to insert the line into the merge output at the correct position in the sorted line chain. Loops until the file is exhausted.

535B
DEC (IX+17H) DD 35 17
DECrement the FCB byte at IX+17H by 1. This adjusts a file position counter or sector reference in the FCB to account for the overlay load, ensuring the file read position is correctly aligned for reading the merge source file.
535E
PUSH DE D5
Save Register Pair DE onto the stack. DE holds the current merge output write pointer (the position where the next merged line will be written in the output area).
535F
LD (5442H),DE ED 53 42 54
SELF-MODIFYING CODE
Store Register Pair DE (the merge output pointer) to self-modifying location 5442H, the Merge Output Position tracker.
5363
GOSUB to 54BDH, the Merge Source Boundary Check. This routine loads HL from the merge position variable at 53DCH, decrements H by 256 (DEC H), compares HL against DE via RST 18H, and returns with NC if the merge output has not caught up to the merge source. If it has (C flag set), the routine pops the return and jumps to 54C5H (out of memory error at 197AH).

[LINE READ LOOP START] Read one line from the merge source file, byte by byte, into the buffer at (40A7H). Register E serves as a byte counter (initialized to F0H = 240, the maximum line length). Each byte is read via CALL 60F2H and stored to the buffer.

5366
LD E,F0H 1E F0
Load Register E with F0H (240 decimal), the maximum number of bytes to read for a single BASIC line. This serves as a countdown buffer overflow guard.
5368
LD HL,(40A7H) 2A A7 40
Load Register Pair HL with the contents of memory locations 40A7H–40A8H, the Line Input Buffer Pointer. HL points to the buffer where the file line bytes will be assembled.
536B
PUSH HL E5
Save Register Pair HL (the buffer start address) onto the stack. This will be restored at 5389H after the line is complete, providing the start of the assembled line for parsing.
536C
GOSUB to 60F2H, the File Read routine in BASIC/CMD. This reads one byte from the currently open file into Register A. On success, the Z FLAG is set and A holds the byte read. On error, the NZ FLAG is set and A holds the error code. On EOF, A = 00H and Z is set.
536F
FILE READ ERROR / EOF — finalize merge
If the NZ FLAG has been set (a file read error occurred), JUMP to 5310H to finalize the merge. Read errors at this point are treated as end-of-file — whatever lines have been successfully merged are kept.
5372
OR A B7
OR Register A (the byte read from the file) with itself to set the flags. If A = 00H (EOF indicator or null byte), the Z FLAG is set. Otherwise, the NZ FLAG is set.
5373
SKIP NULLS
If the Z FLAG has been set (the byte is 00H — a null byte from the file), JUMP back to 536CH to read the next byte, skipping null bytes.
5375
CP 0DH FE 0D
Compare Register A against 0DH (ASCII carriage return). If Register A equals 0DH, the Z FLAG is set.
5377
LD (HL),A 77
Store Register A (the file byte) to the buffer at (HL). The byte is stored regardless of whether it is a CR or not — the CR check at 5378H determines whether the line is complete.
5378
END OF LINE
If the Z FLAG has been set (the byte is 0DH, carriage return — end of line), JUMP forward to 5387H to null-terminate the buffer and process the assembled line.
537A
CP 0AH FE 0A
Compare Register A against 0AH (ASCII line feed). If Register A equals 0AH, the Z FLAG is set.
537C
NORMAL BYTE
If the NZ FLAG has been set (the byte is not a line feed), JUMP forward to 5383H to accept the byte and continue reading.

The byte is a line feed (0AH). If this is the very first byte read (E still equals F0H, meaning no other bytes have been stored), skip it — it is a trailing LF from the previous line’s CR+LF sequence. Otherwise, treat LF as a normal byte.

537E
LD A,E 7B
Load Register A with the contents of Register E (the remaining byte count). E was initialized to F0H (240) and is decremented as bytes are stored.
537F
CP F0H FE F0
Compare Register A against F0H (240 — the initial value). If A equals F0H, the Z FLAG is set, meaning no bytes have been stored yet (the LF is the first character).
5381
SKIP LEADING LF
If the Z FLAG has been set (no bytes stored yet — this LF is a leading LF), JUMP back to 536CH to skip it and read the next byte.
5383
INC HL 23
INCrement Register Pair HL by 1, advancing the buffer write pointer to the next position.
5384
DEC E 1D
DECrement Register E by 1, reducing the remaining byte count. E counts down from F0H (240) to prevent buffer overflow.
5385
LOOP — read next byte
If the NZ FLAG has been set (the byte count has not reached zero — the buffer is not full), JUMP back to 536CH to read the next byte.

The buffer is full (E reached 00H) or a carriage return was found. Null-terminate the buffer and process the assembled line.

5387
XOR A AF
Set Register A to 00H and clear all flags. This provides the null terminator for the assembled line buffer.
5388
LD (HL),A 77
Store 00H (null terminator) to the buffer at (HL), marking the end of the assembled line text.
5389
POP HL E1
Restore Register Pair HL from the stack. HL now points to the start of the assembled line in the buffer (saved at 536BH).

538AH - Parse Assembled Line and Insert into Merge

After a complete line has been assembled in the buffer, parse the line number from the ASCII text, strip trailing spaces, tokenize the line via ROM 1BC0H, and insert it into the merge output via 53B4H. Then copy the tokenized line text byte by byte to the merge output and loop back for the next file line.

538A
DEC HL 2B
DECrement Register Pair HL by 1, backing up the buffer pointer by one position. This compensates for the RST 10H auto-advance that follows.
538B
RST 10H D7
Fetch the next non-space character from the buffer at (HL) into Register A, advancing HL past any spaces. If the character is a digit (30H–39H), the CARRY FLAG is set. If the buffer is empty (00H terminator), the Z FLAG is set.
538C
INC A 3C
INCrement Register A by 1. This converts a 00H (null terminator / empty line) to 01H, and adjusts the CARRY FLAG status. The purpose is to distinguish an empty line (A was 00H, now 01H) from a non-empty line.
538D
DEC A 3D
DECrement Register A by 1, restoring the original value. The Z FLAG now indicates whether the line was empty (A = 00H after INC/DEC). The INC/DEC sequence sets Z without affecting A if the original value was 00H, but it clears the CARRY FLAG that RST 10H may have set for a digit.
538E
SKIP EMPTY LINE
If the Z FLAG has been set (the assembled line is empty — only contained whitespace or was null-terminated immediately), JUMP back to 5366H to read the next line from the file, discarding this empty line.
5390
ERROR EXIT — no line number
If the NO CARRY FLAG has been set (the first non-space character is not a digit — the line does not start with a line number), JUMP to 5DB8H, the Error/Recovery Path in BASIC/CMD. A MERGE line must begin with a line number.

The line starts with a digit. Parse the ASCII line number into a binary value in DE.

5393
GOSUB to ROM routine at 1E5AH, the BASIC Expression Evaluator (ASCII to integer). This parses the decimal line number from the text at (HL) and returns the binary value in Register Pair DE. HL is advanced past the digits.

Strip trailing spaces from the parsed line. The line number has been consumed; HL now points to the first character after the line number. Back up past any trailing spaces to find the true end of the line number field.

5396
DEC HL 2B
DECrement Register Pair HL by 1, backing up one position past the character after the line number.
5397
LD A,20H 3E 20
Load Register A with 20H (ASCII space). This is the comparison value for the trailing space strip loop.
5399
CP (HL) BE
Compare Register A (20H, space) against the byte at (HL). If the byte at (HL) is a space, the Z FLAG is set.
539A
NO MORE TRAILING SPACES
If the NZ FLAG has been set (the byte at (HL) is not a space), JUMP forward to 53A1H. HL points to the last non-space character before the line text.
539C
DEC HL 2B
DECrement Register Pair HL by 1, moving backward past the trailing space.
539D
CP (HL) BE
Compare Register A (20H, space) against the byte at (HL). If the byte is a space, the Z FLAG is set.
539E
LOOP — strip trailing spaces
If the Z FLAG has been set (another trailing space found), JUMP back to 539CH to continue stripping.
53A0
INC HL 23
INCrement Register Pair HL by 1, advancing past the last non-space character. HL now points to the first space (or end of line number).
53A1
INC HL 23
INCrement Register Pair HL by 1. HL now points to the start of the actual line text (after the line number and any separator spaces).
53A2
PUSH DE D5
Save Register Pair DE (the parsed binary line number) onto the stack for the tokenizer call.
53A3
GOSUB to ROM routine at 1BC0H, the BASIC Line Tokenizer. This tokenizes the ASCII line text at (HL), converting keywords to single-byte tokens. On return, HL points to the tokenized output and BC holds the byte count of the tokenized line (including the 4-byte header and null terminator).
53A6
POP BC C1
Restore the parsed line number from the stack into Register Pair BC (saved as DE at 53A2H, but POP restores to the target register pair — this POP restores the line number into BC, not DE, because the tokenizer consumed DE).
53A7
POP DE D1
Restore Register Pair DE from the stack. DE holds the merge output write pointer (saved at 535EH).
53A8
GOSUB to 53B4H, the Line Number Comparison and Insertion routine. This compares the tokenized line’s line number (now in BC) against the current old program line number (on the stack from 52D6H). If the old line number is less than or equal to BC, the old line is written to the output first. The file line’s 4-byte header (link placeholder + line number) is written to the output. Returns with DE pointing to the next write position.

[COPY LOOP] Copy the tokenized line text byte by byte from the tokenizer output (at HL) to the merge output area (at DE). Continue until the 00H terminator is found.

53AB
INC HL 23
INCrement Register Pair HL by 1, advancing the read pointer to the next byte of the tokenized line text.
53AC
LD A,(HL) 7E
Fetch the next byte of the tokenized line text from (HL) into Register A.
53AD
OR A B7
OR Register A with itself to set the flags. If A = 00H (end-of-line terminator), the Z FLAG is set.
53AE
LD (DE),A 12
Store Register A (the tokenized line byte or 00H terminator) to the merge output at (DE).
53AF
INC DE 13
INCrement Register Pair DE by 1, advancing the merge output write pointer.
53B0
LOOP — copy tokenized text
If the NZ FLAG has been set (the byte was not the 00H terminator), JUMP back to 53ABH to copy the next byte.
53B2
LOOP — next file line
JUMP back to 535EH to save the updated output pointer and read the next line from the merge source file.

53B4H - Line Number Comparison and Insertion

Core merge insertion routine. Called with the new line number in BC (from the merge source) and the old program line number on the stack (pushed at 52D6H or re-pushed during the merge loop). Uses EX (SP),HL to access the old line number, compares it against BC via SBC HL,BC, and decides: if the old line is less than the new line, the old line’s 4-byte header is written to the output and control returns to copy the old line’s text. If the old line equals the new line (duplicate), execution branches to 53CDH for duplicate handling. If the old line is greater, execution branches to 53FEH to insert the new line first.

53B4
POP AF F1
Pop the return address from the stack into AF. The return address is saved temporarily so that the next stack entry (the old line number) can be accessed via EX (SP),HL.
53B5
EX (SP),HL E3
Exchange Register Pair HL with the value on top of the stack. HL receives the old program line number (pushed at 52D6H or during the loop), and the stack now holds the previous HL value (the current source read pointer).
53B6
PUSH AF F5
Save the return address (retrieved at 53B4H) back onto the stack, restoring the stack structure for the eventual RET at 53CCH.
53B7
OR A B7
Clear the CARRY FLAG in preparation for the 16-bit subtraction that follows.
53B8
SBC HL,BC ED 42
SUBtract Register Pair BC (the new/file line number) from Register Pair HL (the old program line number) with borrow. Result: HL = old_line − new_line. If old < new, the CARRY FLAG is set. If old = new, the Z FLAG is set. If old > new, neither flag is set.
53BA
ADD HL,BC 09
ADD Register Pair BC back to HL, restoring HL to the original old program line number value. The flags from the SBC are preserved by ADD (the Z flag is not preserved, but the CARRY flag is what matters for the JR C test).
53BB
OLD LINE FIRST — insert new line later
If the CARRY FLAG has been set (the old program line number is less than the new/file line number — the new line belongs AFTER the current old line), JUMP forward to 53FEH. That routine copies old program lines to the output until the correct insertion point is reached, then inserts the new line.
53BD
DUPLICATE LINE
If the Z FLAG has been set (the old program line number equals the new/file line number — duplicate line), JUMP forward to 53CDH for duplicate line handling.

The old program line number is greater than the new/file line number. The new line should be inserted HERE, before the current old line. Write the 4-byte line header for the new line to the merge output: [link_placeholder_H][link_placeholder_H][linenum_low][linenum_high]. The link pointer is set to the high byte of the current output address as a placeholder (will be fixed by the relink at 1AF8H).

53BF
POP AF F1
Pop the return address from the stack into AF.
53C0
EX (SP),HL E3
Exchange Register Pair HL with the top of stack. HL receives the source read pointer (saved at 53B5H), and the stack now holds the old line number for future comparisons.
53C1
EX DE,HL EB
Exchange Register Pairs DE and HL. After this: HL = merge output pointer (was in DE), DE = source read pointer (was in HL). The output pointer is needed in HL for the header writes.
53C2
PUSH AF F5
Save the return address back onto the stack.
53C3
LD (HL),H 74
Store Register H (the high byte of the current output address) to (HL) as the low byte of the link pointer placeholder. The link pointer will be corrected by the BASIC relink routine (1AF8H) after the merge completes.
53C4
INC HL 23
INCrement Register Pair HL by 1, advancing the output pointer to the link pointer high byte position.
53C5
LD (HL),H 74
Store Register H to (HL) as the high byte of the link pointer placeholder.
53C6
INC HL 23
INCrement Register Pair HL by 1, advancing to the line number low byte position.
53C7
LD (HL),C 71
Store Register C (the low byte of the new line number in BC) to (HL).
53C8
INC HL 23
INCrement Register Pair HL by 1, advancing to the line number high byte position.
53C9
LD (HL),B 70
Store Register B (the high byte of the new line number) to (HL). The complete 4-byte header [H][H][C][B] has been written.
53CA
INC HL 23
INCrement Register Pair HL by 1, advancing past the 4-byte header to the position where the tokenized line text will be written.
53CB
EX DE,HL EB
Exchange Register Pairs DE and HL. DE = output pointer (after header), HL = source read pointer. The caller will now copy the line text to (DE).
53CC
RET C9
RETURN to the caller (either the packed merge loop at 5304H or the ASCII merge line copy at 53ABH) to copy the tokenized line text bytes to the output.

53CDH - Duplicate Line Number Handler

Reached when the old program line number equals the new/file line number (a duplicate). If BC = FFFFH (the end-of-program sentinel), this means both programs have been exhausted and the merge is complete — jump to the error exit at 5DBBH. Otherwise, check the mode flag at 5315H: if mode is 02H (CMD"F",DELETE), report an “Illegal Function Call” error since DELETE cannot process duplicate lines. For MERGE mode, skip the old program line (advance past its text) and re-enter the comparison loop with the NEXT old program line.

53CD
LD A,B 78
Load Register A with the contents of Register B (the high byte of the line number).
53CE
AND C A1
AND Register A with Register C (the low byte of the line number). If both bytes are FFH (BC = FFFFH, the end-of-program sentinel), the result is FFH.
53CF
INC A 3C
INCrement Register A by 1. If A was FFH (from FFFFH AND), it wraps to 00H and the Z FLAG is set. This tests for BC = FFFFH (both programs exhausted).
53D0
MERGE COMPLETE / ERROR EXIT
If the Z FLAG has been set (BC = FFFFH — both programs have ended with matching sentinel values), JUMP to 5DBBH in BASIC/CMD. This is an error recovery exit that handles the end-of-merge condition.
53D3
LD A,(5315H) 3A 15 53
Fetch the mode flag from self-modifying location 5315H into Register A. Values: 00H = standard, 01H = V/R option, 02H = CMD"F",DELETE.
53D6
CP 02H FE 02
Compare Register A against 02H. If A equals 02H (CMD"F",DELETE mode), the Z FLAG is set.
53D8
ERROR EXIT
If the Z FLAG has been set (mode is CMD"F",DELETE and a duplicate line was encountered), JUMP to ROM 1E4AH, the “Illegal Function Call” error handler. The NEWDOS/80 manual states that MERGE must not contain a line with the same number as an existing line.

Duplicate line in MERGE mode. Skip past the old program line’s text to advance to the next line in the old program chain, then re-enter the comparison at 53B7H.

53DB
LD HL,0000H 21 00 00
[SELF-MODIFYING CODE] Load Register Pair HL with the address stored at 53DCH–53DDH. This is the Current Merge Position pointer, written by 52B2H, 53EEH, and 54C8H. At runtime, HL is loaded with the address of the current position in the old program data.
53DE
INC HL 23
INCrement Register Pair HL by 1 (skip byte 1 of line header — link low).
53DF
INC HL 23
INCrement Register Pair HL by 1 (skip byte 2 — link high).
53E0
INC HL 23
INCrement Register Pair HL by 1 (skip byte 3 — linenum low).
53E1
INC HL 23
INCrement Register Pair HL by 1 (skip byte 4 — linenum high). HL now points to the first byte of the tokenized line text.
53E2
LD A,(HL) 7E
Fetch the next byte of the old program line text from (HL) into Register A.
53E3
OR A B7
OR Register A with itself to test for the 00H end-of-line terminator. If A = 00H, the Z FLAG is set.
53E4
INC HL 23
INCrement Register Pair HL by 1, advancing past the current byte.
53E5
LOOP — skip line text
If the NZ FLAG has been set (the byte is not the 00H terminator), JUMP back to 53E2H to continue scanning past the line text.

The 00H terminator was found. HL now points to the start of the NEXT old program line. Read the next line’s header via CALL 53EEH, then re-enter the comparison loop.

53E7
GOSUB to 53EEH, the Old Program Line Header Reader. This saves HL to 53DCH, reads the 2-byte link pointer and the line number low byte into A, and returns with HL advanced past the 3-byte prefix. If the link is 0000H (end of program), it pops the return address and loads HL = FFFFH for the sentinel re-entry.
53EA
LD H,(HL) 66
Fetch the high byte of the line number from (HL) into Register H. Combined with the low byte in A (from 53EEH), this gives the complete line number with low byte in A and high byte in H.
53EB
LD L,A 6F
Load Register L with Register A (the line number low byte). Now HL = the complete 16-bit line number of the next old program line (H = high byte, L = low byte).
53EC
LOOP — compare next old line
JUMP back to 53B7H to re-enter the comparison loop with the new old-program line number in HL (which will be compared against BC).

53EEH - Old Program Line Header Reader

Reads the 4-byte header of the next old program line. Saves HL (start of line) to 53DCH, reads the 2-byte link pointer, and returns with A = line number low byte and HL pointing to the line number high byte. If the link pointer is 0000H (end of program), pops the caller’s return address and injects HL = FFFFH into the comparison loop at 53B7H, effectively ending the old program scan.

53EE
LD (53DCH),HL 22 DC 53
SELF-MODIFYING CODE
Store Register Pair HL (the start address of the current old program line) to memory location 53DCH, the Current Merge Position self-modifying variable.
53F1
LD A,(HL) 7E
Fetch the low byte of the link pointer from (HL) into Register A.
53F2
INC HL 23
INCrement Register Pair HL by 1, advancing to the link pointer high byte.
53F3
OR (HL) B6
OR Register A (link low byte) with the byte at (HL) (link high byte). If both are 00H (end of program), the Z FLAG is set.
53F4
INC HL 23
INCrement Register Pair HL by 1, advancing to the line number low byte.
53F5
LD A,(HL) 7E
Fetch the line number low byte from (HL) into Register A.
53F6
INC HL 23
INCrement Register Pair HL by 1, advancing to the line number high byte. HL now points to the high byte, A holds the low byte.
53F7
RET NZ C0
If the NZ FLAG has been set (the link pointer was nonzero — a valid next line exists), RETURN to the caller. A = line number low byte, HL points to line number high byte.

The link pointer was 0000H (end of old program). Pop the caller’s return address and inject HL = FFFFH as the sentinel, jumping directly to the comparison at 53B7H.

53F8
POP HL E1
Pop and discard the caller’s return address. This prevents returning to 53EAH (or wherever the caller was) and instead allows the JR at 53FCH to redirect flow.
53F9
LD HL,FFFFH 21 FF FF
Load Register Pair HL with FFFFH, the end-of-program sentinel. This value is always greater than any real line number, so the comparison at 53B7H will cause all remaining file lines to be appended.
53FC
END OF OLD PROGRAM — append remaining file lines
JUMP back to 53B7H to re-enter the comparison loop with HL = FFFFH.

53FEH - Copy Old Program Lines to Output Until Insertion Point

Reached when the old program line number is less than the new/file line number (the old line should appear first in the output). Copies old program lines — including their full text and 4-byte headers — to the merge output, advancing through the old program chain until the old line number exceeds the new line number. At that point, writes the new line’s header and returns to the caller to copy the new line’s text.

53FE
LD HL,(53DCH) 2A DC 53
Load Register Pair HL with the contents of 53DCH, the Current Merge Position pointer. HL points to the start of the current old program line (the one whose line number was less than the new line).
5401
GOSUB to 5478H, the Delta Accumulator Updater. This calculates the distance between the current merge output pointer and the merge source pointer, accumulates the delta into 5642H, and updates the self-modifying pointers. Returns via JP 562AH with DE and HL restored from the stack.
5404
LD (547FH),DE ED 53 7F 54
SELF-MODIFYING CODE
Store Register Pair DE (the current merge output pointer, returned from the delta updater) to self-modifying location 547FH, the Merge Source Start pointer.
5408
LD (5442H),DE ED 53 42 54
SELF-MODIFYING CODE
Store Register Pair DE to self-modifying location 5442H, the Merge Output Position.
540C
GOSUB to 53EEH, the Old Program Line Header Reader. Read the next old line’s link pointer and line number. Returns with A = linenum low, HL = pointer to linenum high. If end of program, redirects to 53B7H with FFFFH.
540F
PUSH HL E5
Save Register Pair HL (pointing to the line number high byte of the next old line) onto the stack.
5410
LD H,(HL) 66
Fetch the line number high byte from (HL) into Register H.
5411
LD L,A 6F
Load Register L with Register A (the line number low byte). HL now holds the complete 16-bit line number of the next old program line.
5412
OR A B7
Clear the CARRY FLAG for the subtraction.
5413
SBC HL,BC ED 42
SUBtract Register Pair BC (the new/file line number) from HL (the next old line number). If the old line number is still less than the new line, the CARRY FLAG is set.
5415
ADD HL,BC 09
Restore HL to the old line number value.
5416
OLD LINE STILL FIRST
If the CARRY FLAG has been set (the next old line is STILL less than the new line), JUMP forward to 541BH to write this old line’s header and copy its text, then loop back to check the following line.

The next old line number is greater than or equal to the new line number. The insertion point has been found. Pop the saved pointer and re-enter the comparison at 53B7H with this old line number, which will cause the new line to be written.

5418
POP AF F1
Pop and discard the saved HL from 540FH.
5419
INSERTION POINT FOUND
JUMP back to 53B7H to re-enter the comparison loop with HL = the next old line number. Since old >= new, the comparison will cause the new line’s header to be written.

The old line is still less than the new line. Write the old line’s 4-byte header to the output and copy its text.

541B
EX DE,HL EB
Exchange DE and HL. HL = merge output pointer, DE = old line number.
541C
LD (HL),H 74
Store Register H (high byte of output address) as link pointer low byte placeholder.
541D
INC HL 23
Advance output pointer.
541E
LD (HL),H 74
Store Register H as link pointer high byte placeholder.
541F
INC HL 23
Advance output pointer.
5420
LD (HL),E 73
Store Register E (old line number low byte from DE) to output.
5421
INC HL 23
Advance output pointer.
5422
LD (HL),D 72
Store Register D (old line number high byte) to output.
5423
INC HL 23
Advance output pointer past the 4-byte header.
5424
EX DE,HL EB
Exchange DE and HL. DE = output pointer (after header), HL = old line number.
5425
POP HL E1
Restore the saved pointer from 540FH. HL now points to the line number high byte of the current old line.
5426
INC HL 23
INCrement HL past the line number high byte, positioning HL at the first byte of the tokenized line text.
5427
PUSH BC C5
Save Register Pair BC (the new/file line number) onto the stack for later restoration.
5428
LD BC,0000H 01 00 00
[SELF-MODIFYING CODE] Load Register Pair BC from the self-modifying operand at 5429H. This is the Current Program Position tracker, written by 52C3H, 54C8H, and 5437H. At runtime, BC holds the byte count accumulated during the line copy (initialized to 0000H and incremented for each byte).

[LINE TEXT COPY LOOP] Count and copy the tokenized line text byte by byte. BC counts the total bytes (including the 4-byte header accounted for by the 5 INC BC instructions, plus the text bytes), and the bytes are copied from (HL) to (DE).

542B
INC BC 03
INCrement BC by 1 (count byte 1 of the 4-byte header that was already written).
542C
INC BC 03
INCrement BC by 1 (count byte 2).
542D
INC BC 03
INCrement BC by 1 (count byte 3).
542E
INC BC 03
INCrement BC by 1 (count byte 4).
542F
INC BC 03
INCrement BC by 1 (count the current text byte about to be copied). This pre-increment means BC counts the null terminator as well.
5430
LD A,(HL) 7E
Fetch the next byte of the old line text from (HL).
5431
OR A B7
Test for the 00H end-of-line terminator.
5432
LD (DE),A 12
Store the byte to the merge output at (DE).
5433
INC HL 23
Advance the source read pointer.
5434
INC DE 13
Advance the merge output write pointer.
5435
LOOP — copy old line text
If the NZ FLAG has been set (the byte was not the 00H terminator), JUMP back to 542FH to count and copy the next byte.
5437
LD (5429H),BC ED 43 29 54
SELF-MODIFYING CODE
Store Register Pair BC (the accumulated byte count for this line) to self-modifying location 5429H, the Current Program Position counter.
543B
POP BC C1
Restore Register Pair BC (the new/file line number, saved at 5427H).
543C
LOOP — check next old line against new line
JUMP back to 5404H to update the merge pointers and check the next old program line.

543EH - Merge Compaction: Three-Stage LDIR

Final memory compaction routine called after all lines have been merged. Performs up to three LDIR block moves to relocate the merged program text, the variable/array area, and the string stack back to their final contiguous positions. Updates the BASIC memory pointers (40F9H, 40FBH, 40FDH), relinks the program line chain via ROM 1AF8H, and sets the reset vector via JP 6497H. The three LDIR moves correspond to: (1) merged data → string space, (2) variable/array area, (3) string stack. Each region’s size is loaded from a self-modifying operand set by 5495H.

543E
GOSUB to 5478H, the Delta Accumulator Updater. Final call to calculate and accumulate the merge delta before compaction. Returns with DE and HL restored.
5441
LD DE,0000H 11 00 00
[SELF-MODIFYING CODE] Load Register Pair DE from the operand at 5442H, the Merge Output Position. At runtime, DE holds the address where the merged program data ends — this is the source for the first LDIR.
5444
LD BC,(53DCH) ED 4B DC 53
Load Register Pair BC from self-modifying location 53DCH, the Current Merge Position. BC holds the start address of the relocated data block (the beginning of string space after the LDDR at 52AFH).
5448
LD HL,(40F9H) 2A F9 40
Load Register Pair HL from memory locations 40F9H–40FAH, the String Space Start pointer. This marks the end of the first region to move.
544B
PUSH BC C5
Save BC (the relocated data start address) onto the stack for use as the LDIR source.
544C
OR A B7
Clear the CARRY FLAG for the subtraction.
544D
SBC HL,BC ED 42
SUBtract BC (relocated data start) from HL (string space start). Result: HL = 40F9H − 53DCH = the byte count of the first region (merged program text + any gap).
544F
LD B,H 44
Copy the byte count high byte to B.
5450
LD C,L 4D
Copy the byte count low byte to C. BC = first region byte count.
5451
POP HL E1
Restore HL from the stack. HL = relocated data start address (the LDIR source).
5452
LDIR ED B0
Execute LDIR (Load, Increment, Repeat).
Source
HL = relocated data start (53DCH value).
Destination
DE = merge output end (5442H value).
Byte Count
BC = first region size.
Direction
Incrementing. Moves the first data block (merged program text) from the relocated position back to immediately after the merged output. After completion, DE points to the new string space start.
5454
LD (40F9H),DE ED 53 F9 40
Store Register Pair DE (the new string space start after the first LDIR) to 40F9H, updating the String Space Start pointer.
5458
LD BC,0000H 01 00 00
[SELF-MODIFYING CODE] Load Register Pair BC from the operand at 5459H. This holds the variable/array area size (40FBH − 40F9H), calculated by 5495H and stored at 54AEH.
545B
LD A,B 78
Load Register A with the high byte of BC (the variable/array size).
545C
OR C B1
OR Register A with Register C. If BC = 0000H (no variable/array data), the Z FLAG is set.
545D
SKIP EMPTY REGION
If the Z FLAG has been set (no variable/array data to move), JUMP forward to 5461H to skip the second LDIR.
545F
LDIR ED B0
Execute LDIR. Move the variable/array region from the relocated position to immediately after the string space. Source continues from where the first LDIR left off (HL), destination continues at DE.
5461
LD (40FBH),DE ED 53 FB 40
Store Register Pair DE (the new array end / variable top) to 40FBH, updating the Array End pointer.
5465
LD BC,0000H 01 00 00
[SELF-MODIFYING CODE] Load Register Pair BC from the operand at 5466H. This holds the string stack size (40FDH − 40FBH), calculated by 5495H and stored at 549FH.
5468
LD A,B 78
Load Register A with the high byte of BC (the string stack size).
5469
OR C B1
OR Register A with Register C. If BC = 0000H (no string stack data), the Z FLAG is set.
546A
SKIP EMPTY REGION
If the Z FLAG has been set (no string stack data to move), JUMP forward to 546EH to skip the third LDIR.
546C
LDIR ED B0
Execute LDIR. Move the string stack region to its final position immediately after the variable/array area.
546E
LD (40FDH),DE ED 53 FD 40
Store Register Pair DE (the new string stack top) to 40FDH, updating the String Stack Pointer.
5472
GOSUB to ROM routine at 1AF8H, the BASIC Program Relink routine. This walks the entire BASIC program line chain and recalculates all link pointers, fixing the placeholder values (H bytes) that were written during the merge.
5475
MERGE COMPLETE
JUMP to 6497H, the Set Reset Vector routine in BASIC/CMD. This stores the current execution context into the reset vector at 6427H, completing the merge operation. Control then returns to the post-load dispatch or warm start.

5478H - Delta Accumulator Updater

Calculates the distance (delta) between the merge output pointer (5442H) and the merge source pointer (547FH), stores the result at 557AH, then conditionally calls the variable/string relocator at 54F2H if 5429H is nonzero. Exits via JP 562AH which accumulates the delta into 5642H and restores DE/HL from the stack.

5478
PUSH HL E5
Save Register Pair HL onto the stack.
5479
PUSH DE D5
Save Register Pair DE onto the stack.
547A
PUSH BC C5
Save Register Pair BC onto the stack.
547B
LD HL,(5442H) 2A 42 54
Load Register Pair HL from self-modifying location 5442H, the Merge Output Position (where output data ends).
547E
LD DE,0000H 11 00 00
[SELF-MODIFYING CODE] Load Register Pair DE from the operand at 547FH, the Merge Source Start pointer. This is the position where the current block of old program text started.
5481
OR A B7
Clear the CARRY FLAG.
5482
SBC HL,DE ED 52
SUBtract DE (merge source start) from HL (merge output end). Result: HL = the delta (how much the merge output has grown relative to the source).
5484
LD (557AH),HL 22 7A 55
SELF-MODIFYING CODE
Store the delta value to self-modifying location 557AH. This is used by the delta accumulation at 562AH and by the variable relocator.
5487
LD DE,0000H 11 00 00
[SELF-MODIFYING CODE] Load Register Pair DE from the operand at 5488H. This holds the String Space Start value (40F9H) saved by 5495H, used as a parameter for the relocator.
548A
LD HL,(5429H) 2A 29 54
Load Register Pair HL from self-modifying location 5429H, the Current Program Position byte count.
548D
LD A,H 7C
Load Register A with the high byte of HL (the byte count high byte).
548E
If the NZ FLAG has been set (H is nonzero, meaning the byte count is at least 256 — substantial data has been processed), GOSUB to 54F2H, the Variable/String Relocator. This routine adjusts string pointers and variable references that may have been invalidated by the memory relocation.
5491
POP BC C1
Restore Register Pair BC from the stack.
5492
JUMP to 562AH, the Delta Accumulation and Return routine. This adds the delta at 557AH to the running total at 5642H, then pops DE and HL from the stack and returns.

5495H - Memory Region Size Calculator

Calculates the sizes of the three memory regions above the BASIC program (string stack, variable/array area, and the gap between them) and stores the results into self-modifying operands for the three-stage LDIR compaction at 543EH. Called during merge initialization at 5289H and during the merge pointer init at 54D9H.

5495
LD HL,(40FDH) 2A FD 40
Load Register Pair HL from 40FDH, the String Stack Pointer (top of string descriptor stack).
5498
LD DE,(40FBH) ED 5B FB 40
Load Register Pair DE from 40FBH, the Array End / Variable Top pointer.
549C
OR A B7
Clear the CARRY FLAG.
549D
SBC HL,DE ED 52
SUBtract DE (array end) from HL (string stack pointer). Result: HL = 40FDH − 40FBH = string stack size.
549F
LD (5466H),HL 22 66 54
SELF-MODIFYING CODE
Store the string stack size to self-modifying operand at 5466H (the third LDIR’s BC at 5465H).
54A2
LD B,H 44
Copy string stack size high byte to B.
54A3
LD C,L 4D
Copy string stack size low byte to C. BC = string stack size.
54A4
LD HL,(40F9H) 2A F9 40
Load Register Pair HL from 40F9H, the String Space Start pointer.
54A7
LD (5488H),HL 22 88 54
SELF-MODIFYING CODE
Store the string space start value to self-modifying operand at 5488H (used by the delta updater at 5487H).
54AA
EX DE,HL EB
Exchange DE and HL. DE = string space start (40F9H), HL = array end (40FBH).
54AB
OR A B7
Clear the CARRY FLAG.
54AC
SBC HL,DE ED 52
SUBtract DE (string space start) from HL (array end). Result: HL = 40FBH − 40F9H = variable/array area size.
54AE
LD (5459H),HL 22 59 54
SELF-MODIFYING CODE
Store the variable/array area size to self-modifying operand at 5459H (the second LDIR’s BC at 5458H).
54B1
RET C9
RETURN to the caller.

54B2H - Page Boundary / Sector Read Handler

Called conditionally (CALL Z) when INC L wraps from FFH to 00H during the merge line copy loop. Reads the next sector from the file via SVC 4436H, then checks whether the merge output has caught up to the merge source (53DCH), which would indicate an out-of-memory condition.

54B2
PUSH DE D5
Save Register Pair DE (the merge output pointer) onto the stack.
54B3
LD DE,570DH 11 0D 57
Point Register Pair DE to 570DH, the Filename Buffer.
54B6
GOSUB to 4436H to READ a disk sector or move a logical record from the FCB’s buffer to the caller’s buffer. Reads the next sector of the program file.
54B9
ERROR EXIT
If the NZ FLAG has been set (file read error), JUMP to 5DEFH, the Error Translator.
54BC
POP DE D1
Restore Register Pair DE (the merge output pointer).
54BD
PUSH HL E5
Save Register Pair HL (the current read position).
54BE
LD HL,(53DCH) 2A DC 53
Load HL from 53DCH, the Current Merge Position.
54C1
DEC H 25
DECrement Register H by 1, subtracting 256 from the merge position for the safety margin comparison.
54C2
RST 18H DF
Compare HL (merge position − 256) against DE (output pointer). If HL < DE (output has caught up to within 256 bytes of the source), the CARRY FLAG is set.
54C3
POP HL E1
Restore Register Pair HL.
54C4
RET NC D0
SPACE OK
If the NO CARRY FLAG has been set (the output has NOT caught up — sufficient space remains), RETURN to the caller to continue the merge.
54C5
OUT OF MEMORY ERROR
JUMP to ROM 197AH, the Out of Memory error handler (?OM ERROR). The merge output has overtaken the source data, meaning there is not enough memory to complete the merge.

54C8H - Merge Pointer Initialization

Initializes all four merge tracking pointers (53DCH, 547FH, 5429H, 5442H) from the current HL/DE values, zeros the delta accumulator via CALL 5638H, calculates region sizes via CALL 5495H, then jumps to the merge compaction at 543EH. Called during V-option setup at 5263H and by the CMD"F",DELETE handler at 55BCH.

54C8
LD (53DCH),HL 22 DC 53
SELF-MODIFYING CODE
Store HL to 53DCH, the Current Merge Position.
54CB
LD (547FH),HL 22 7F 54
SELF-MODIFYING CODE
Store HL to 547FH, the Merge Source Start.
54CE
LD (5429H),HL 22 29 54
SELF-MODIFYING CODE
Store HL to 5429H, the Current Program Position.
54D1
EX DE,HL EB
Exchange DE and HL. HL now holds the merge output pointer (was in DE).
54D2
LD (5442H),HL 22 42 54
SELF-MODIFYING CODE
Store HL to 5442H, the Merge Output Position.
54D5
XOR A AF
Set Register A to 00H.
54D6
GOSUB to 5638H, the Delta Zero and Relocate routine. Zeroes the delta accumulator at 5642H (stores A=00H via BC) and calls 54F2H to initialize the variable relocator pointers.
54D9
GOSUB to 5495H, the Memory Region Size Calculator. Computes and stores the sizes for the three LDIR stages.
54DC
BEGIN COMPACTION
JUMP to 543EH, the Merge Compaction routine, to perform the three-stage LDIR relocation.

54DFH - Variable Relocation Entry

Entry point for the variable relocation sequence used by the V-option (variable-preserving RUN/LOAD) and CMD"F",DELETE paths. Clears the BASIC program line chain by writing 0000H to 40F0H, saves the merge context, disables the guard flag, reinitializes the BASIC system via ROM 1B8FH, and jumps to the address stored at 54F0H to continue execution.

54DF
LD HL,0000H 21 00 00
Load Register Pair HL with 0000H.
54E2
LD (40F0H),HL 22 F0 40
Store 0000H to memory location 40F0H. This clears the BASIC program line chain head pointer, effectively emptying the program so that the reload can build a fresh chain.
54E5
POP HL E1
Restore Register Pair HL from the stack. HL holds the return context from the caller.
54E6
LD (54F0H),HL 22 F0 54
SELF-MODIFYING CODE
Store HL to self-modifying location 54F0H. This is the operand of a JP instruction at 54EFH, setting the continuation address for after the BASIC reinit.
54E9
GOSUB to 6392H, the Disable Guard routine in BASIC/CMD.
54EC
GOSUB to ROM routine at 1B8FH for BASIC System Reinitialization. This reinitializes the BASIC runtime without clearing variables or closing files (the V-option behavior).
54EF
JP 0000H C3 00 00
[SELF-MODIFYING CODE] Jump to the address stored at 54F0H. This was set by 54E6H to the continuation address. For V-option RUN/LOAD, this is the address of the file load sequence. For CMD"F",DELETE, this is the address of the post-delete handler.

54F2H - Variable/String Pointer Relocator

Adjusts internal variable and string pointers that reference the BASIC program text, accounting for the address changes caused by the merge relocation. Walks the variable table (40F9H–40FBH) and string descriptor stack (40FBH–40FDH), adjusting any pointers that fall within the relocated range. Uses the self-modifying operands at 5565H, 556CH, 5574H, and 5576H to track the relocation parameters. Calls 555BH/5558H for individual string descriptor relocation, and ROM 0BAAH for string copy operations.

54F2
LD (5574H),A 32 74 55
SELF-MODIFYING CODE
Store Register A (the high byte of the program position count from 548DH) to self-modifying location 5574H. This value is used as a flag/parameter by the string relocator at 5573H.
54F5
LD (556CH),HL 22 6C 55
SELF-MODIFYING CODE
Store Register Pair HL (the program position from 5429H) to self-modifying location 556CH.
54F8
LD (5565H),DE ED 53 65 55
SELF-MODIFYING CODE
Store Register Pair DE (the string space start from 5488H) to self-modifying location 5565H.

[VARIABLE TABLE WALK] Walk the variable table entries from 40F9H (string space start) through 40FBH (array end), checking each variable descriptor. The variable type is encoded in the low nibble of the first byte of each entry.

54FC
LD HL,(40F9H) 2A F9 40
Load HL from 40F9H, the String Space Start. This is the beginning of the variable table.
54FF
LD DE,(40FBH) ED 5B FB 40
Load DE from 40FBH, the Array End pointer. DE marks the end of the variable table.
5503
RST 18H DF
Compare HL against DE. If HL = DE, the Z FLAG is set (all variable entries processed). If HL < DE, the CARRY FLAG is set.
5504
VARIABLES DONE
If the Z FLAG has been set (end of variable table), JUMP forward to 5527H to begin walking the string descriptor stack.
5506
LD A,(HL) 7E
Fetch the first byte of the variable entry from (HL). The low nibble encodes the variable type.
5507
AND 0FH E6 0F
Mask with 0FH to isolate the variable type code.
5509
INC HL 23
Advance HL past byte 1.
550A
INC HL 23
Advance HL past byte 2.
550B
BIT 7,(HL) CB 7E
Test bit 7 of the byte at (HL) (byte 3 of the variable entry). Bit 7 set indicates this entry contains a string descriptor that may need relocation.
550D
INC HL 23
Advance HL past byte 3.
550E
NOT A STRING
If the Z FLAG has been set (bit 7 clear — no string descriptor in this entry), JUMP to 551BH to check the variable type and skip the appropriate number of bytes.

Bit 7 is set — this entry contains a string descriptor. Call 555BH to relocate the string pointer if it falls within the relocated range.

5510
PUSH AF F5
Save the variable type code.
5511
LD A,00H 3E 00
[SELF-MODIFYING CODE] Load A from self-modifying operand at 5512H. This flag controls the relocation mode. Written by earlier code.
5513
GOSUB to 555BH, the String Descriptor Relocator. Reads the string length and address from (HL), checks whether the string address falls within the relocated range, and adjusts it if necessary.
5516
POP AF F1
Restore the variable type code.
5517
DEC A 3D
DECrement A by 1 (adjust the type code for the skip calculation).
5518
DEC A 3D
DECrement A by 1 again. Two decrements account for the bytes already consumed by the string descriptor relocation.
5519
JUMP to 5520H to skip the remaining bytes of this variable entry.
551B
CP 03H FE 03
Compare the variable type code against 03H (string type). If equal, the Z FLAG is set.
551D
If the Z FLAG has been set (variable type is 03H, string), GOSUB to 5558H, the String Descriptor Reader. This reads the string length and address from the current position without relocating.
5520
LD C,A 4F
Load Register C with the remaining byte skip count.
5521
LD B,00H 06 00
Load Register B with 00H. BC = skip count (0–255 bytes).
5523
ADD HL,BC 09
ADD BC to HL, skipping past the remaining bytes of this variable entry.
5524
LOOP — next variable
JUMP back to 54FFH to process the next variable entry.
5526
ADD HL,BC 09
ADD BC to HL (alternate entry for cases where BC was already set). Falls through to 5527H.

5527H - String Descriptor Stack Walk

After the variable table walk completes, walks the string descriptor stack from 40FBH through 40FDH. Each string descriptor stack entry is a 5-byte record: [type][length][addr_low][addr_high][extra]. For type 03H (string), the entry contains a string count and multiple sub-records that need relocation via ROM 0BAAH (string copy).

5527
LD DE,(40FDH) ED 5B FD 40
Load DE from 40FDH, the String Stack Pointer (end of string descriptor stack).
552B
RST 18H DF
Compare HL against DE. If HL = DE, the Z FLAG is set (end of stack).
552C
RET Z C8
If the Z FLAG has been set (all stack entries processed), RETURN. The entire relocation is complete.
552D
LD A,(HL) 7E
Fetch the type byte of the current stack entry.
552E
AND 0FH E6 0F
Isolate the type code in the low nibble.
5530
CP 03H FE 03
Compare against 03H (string type).
5532
INC HL 23
Advance past byte 1.
5533
INC HL 23
Advance past byte 2.
5534
INC HL 23
Advance past byte 3.
5535
LD C,(HL) 4E
Fetch the low byte of the string address into C.
5536
INC HL 23
Advance past byte 4.
5537
LD B,(HL) 46
Fetch the high byte of the string address into B. BC = string address.
5538
INC HL 23
Advance past byte 5.
5539
NOT STRING — skip
If the NZ FLAG has been set (type is not 03H — not a string), JUMP back to 5526H to skip this entry and continue.

Type is 03H (string). Process the string sub-records. Each sub-record has: [length][addr_low][addr_high]. The count of sub-records is read, and each one is processed via ROM 0BAAH for string relocation.

553B
LD DE,0001H 11 01 00
Load DE with 0001H as the initial string relocation count.
553E
LD A,(HL) 7E
Fetch the sub-record count byte.
553F
INC HL 23
Advance past the count byte.
5540
LD C,(HL) 4E
Fetch the string address low byte into C.
5541
INC HL 23
Advance.
5542
LD B,(HL) 46
Fetch the string address high byte into B. BC = string source address.
5543
PUSH AF F5
Save the sub-record count.
5544
INC HL 23
Advance past the address high byte.
5545
GOSUB to ROM routine at 0BAAH for String Block Copy. Copies the string data from the address in BC to the destination, adjusting for the relocation delta. On return, DE is updated with the copied string’s new location.
5548
POP AF F1
Restore the sub-record count.
5549
DEC A 3D
DECrement the sub-record count by 1.
554A
LOOP — next sub-record
If the NZ FLAG has been set (more sub-records remain), JUMP back to 5540H to process the next one.
554C
PUSH DE D5
Save the updated string destination.
554D
GOSUB to 5558H, the String Descriptor Reader. Read the next string descriptor’s length and address.
5550
POP DE D1
Restore the string destination.
5551
DEC DE 1B
DECrement DE by 1 (adjust string relocation count).
5552
LD A,D 7A
Load A with the high byte of DE.
5553
OR E B3
OR with the low byte. If DE = 0000H, the Z FLAG is set.
5554
LOOP — next string
If the NZ FLAG has been set (more strings to process), JUMP back to 554CH.
5556
NEXT STACK ENTRY
JUMP back to 5527H to continue walking the string descriptor stack.

5558H - String Descriptor Reader / Relocator

Reads a 3-byte string descriptor (length + 2-byte address) from (HL) and optionally relocates the string pointer if it falls within the relocated range. Entry at 5558H reads without relocating; entry at 555BH performs the full relocation check. Uses self-modifying operands at 5564H–5576H to store relocation parameters, and calls 5641H/5649H for range comparison.

5558
LD A,(HL) 7E
Fetch the string length byte from (HL) into Register A.
5559
OR A B7
Test whether the string length is zero. If A = 00H, the Z FLAG is set.
555A
INC HL 23
Advance past the length byte.
555B
LD E,(HL) 5E
Fetch the string address low byte into E.
555C
INC HL 23
Advance.
555D
LD D,(HL) 56
Fetch the string address high byte into D. DE = string address.
555E
INC HL 23
Advance past the address high byte.
555F
RET Z C8
If the Z FLAG has been set (string length was zero), RETURN. No relocation needed for zero-length strings.
5560
LD (5576H),A 32 76 55
SELF-MODIFYING CODE
Store the string length to self-modifying location 5576H.
5563
PUSH HL E5
Save the current read position.
5564
LD HL,0000H 21 00 00
[SELF-MODIFYING CODE] Load HL from operand at 5565H (string space start, set by 54F8H).
5567
NOP 00
No operation. Alignment padding.
5568
GOSUB to 5641H, the Lower Bound Range Check. Checks whether the string address in DE is at or above the lower bound in HL+BC. If out of range, jumps to 5599H via 564EH.
556B
LD HL,0000H 21 00 00
[SELF-MODIFYING CODE] Load HL from operand at 556CH (program position, set by 54F5H).
556E
ADD HL,BC 09
ADD BC to HL to calculate the upper bound of the relocation range.
556F
GOSUB to 5649H, the Upper Bound Range Check. Checks whether the string address in DE is below the upper bound. If out of range, jumps to 5599H.
5572
XOR A AF
Set Register A to 00H.
5573
OR 00H F6 00
[SELF-MODIFYING CODE] OR Register A with the value at 5574H (the relocation flag, set by 54F2H). If the flag is nonzero, the NZ FLAG is set.
5575
LD A,00H 3E 00
[SELF-MODIFYING CODE] Load A from operand at 5576H (the string length, set by 5560H).
5577
NO RELOCATION
If the Z FLAG has been set (relocation flag is zero — no adjustment needed), JUMP to 5580H.

The string address falls within the relocated range and needs adjustment. Add the relocation delta to DE.

5579
LD HL,0000H 21 00 00
[SELF-MODIFYING CODE] Load HL from operand at 557AH (the merge delta, set by 5484H).
557C
ADD HL,DE 19
ADD DE (original string address) to HL (the merge delta). Result: HL = relocated string address.
557D
EX DE,HL EB
Exchange DE and HL. DE = relocated address, HL = original.
557E
JUMP to 5593H to write the relocated address back to the descriptor.
5580
OR A B7
Set flags from A (string length). If A = 00H, the Z FLAG is set.
5581
If the NZ FLAG has been set (string length is nonzero), JUMP to 5587H to perform the string copy relocation.
5583
LD D,A 57
Set D = 00H.
5584
LD E,A 5F
Set E = 00H. DE = 0000H (null string address).
5585
JUMP to 5593H to write the null address.
5587
PUSH DE D5
Save the original string address.
5588
GOSUB to ROM routine at 28BFH for String Space Allocation. Allocates A bytes in the string space and returns DE = allocated address.
558B
POP HL E1
Restore the original string address into HL (was in DE before PUSH).
558C
PUSH DE D5
Save the new allocated address.
558D
LD C,A 4F
Load C with the string length.
558E
LD B,00H 06 00
Load B with 00H. BC = string length for LDIR.
5590
LDIR ED B0
Execute LDIR. Copy the string data from HL (original address) to DE (new allocated address), BC bytes.
5592
POP DE D1
Restore the new allocated address into DE.
5593
POP HL E1
Restore the read position (saved at 5563H).
5594
PUSH HL E5
Re-save it (will be restored at 5599H).
5595
DEC HL 2B
Back up to the string address high byte in the descriptor.
5596
LD (HL),D 72
Write the (relocated) string address high byte.
5597
DEC HL 2B
Back up to the string address low byte.
5598
LD (HL),E 73
Write the (relocated) string address low byte.
5599
POP HL E1
Restore the read position.
559A
XOR A AF
Set A to 00H and clear flags.
559B
RET C9
RETURN to the caller.

559CH - CMD“F”,DELETE Range Parser

Parses the line number range for the CMD"F",DELETE statement. Expects a comma separator (RST 08H ⇒ 2CH), then the DELETE keyword token (B6H), then the first line number, a dash separator, and the second line number. Searches for the start and end lines in the BASIC program chain, sets up the merge pointers, and enters the variable relocation and compaction flow to rebuild the program without the deleted lines.

559C
RST 08H ⇒ 2CH CF 2C
Check that the next character in the BASIC text is a comma (2CH). RST 08H compares the byte at (HL) against the inline byte 2CH. If it matches, HL is advanced past the comma. If it does not match, a Syntax Error is raised.
559E
CP B6H FE B6
Compare Register A (the character after the comma) against B6H. B6H is the BASIC token for the DELETE keyword.
55A0
ERROR EXIT
If the NZ FLAG has been set (the token is not DELETE), JUMP to 1997H for Syntax Error.
55A3
PUSH HL E5
Save the BASIC text pointer.
55A4
RST 10H D7
Fetch the next non-space character (the start of the first line number) into A.
55A5
GOSUB to ROM routine at 1B10H for Line Number Range Parser. Parses a “ln1-ln2” range from the BASIC text. Returns with DE = first line number and BC = second line number (or the range limits).
55A8
POP DE D1
Restore the saved text pointer into DE.
55A9
POP HL E1
Pop the next stack value into HL. This retrieves the context from the CMD"F" dispatcher.
55AA
PUSH BC C5
Save the second line number (end of range) onto the stack.
55AB
PUSH HL E5
Save the context from the CMD"F" dispatcher.
55AC
GOSUB to ROM 1B2CH, the BASIC Line Search. Search for the first line number (in DE). Returns with BC pointing to the found line, Z set if exact match.
55AF
EXACT MATCH
If the Z FLAG has been set (exact line found), JUMP to 55B3H.
55B1
LD H,B 60
Copy the found line address high byte to H.
55B2
LD L,C 69
Copy the found line address low byte to L. HL = start of the first line in the delete range.
55B3
EX (SP),HL E3
Exchange HL with the top of stack. HL gets the CMD"F" context, stack gets the delete start address.
55B4
RST 10H D7
Fetch the next non-space character from the BASIC text.
55B5
SKIP TO END OF STATEMENT
If the NZ FLAG has been set (not end of statement), JUMP back to 55B4H to consume the remaining text.
55B7
GOSUB to 5D78H, the Line+Var routine in BASIC/CMD. Sets up the variable context and IX pointer for the deletion operation.
55BA
POP HL E1
Restore the delete start address from the stack.
55BB
POP DE D1
Restore the second line number (end of delete range) into DE.
55BC
GOSUB to 54C8H, the Merge Pointer Initialization. Sets up all four merge pointers from HL (delete start) and DE (end marker), zeros the delta, calculates region sizes, and performs the three-stage LDIR compaction.
55BF
GOSUB to 54DFH, the Variable Relocation Entry. Clears the program chain, reinitializes BASIC, and jumps to the continuation address.
55C2
DELETE COMPLETE — continue execution
JUMP to 5322H, the CMD"F",DELETE Post-Delete Run Handler. Searches for the continuation line and begins execution.

55C5H - SAVE / MERGE ASCII File Handler

Handles the SAVE and MERGE paths for ASCII format files. Checks for a comma and the “A” option (41H), verifies memory space, and either writes the program to a file (SAVE) or reads from a file and enters the BASIC editor (MERGE/LOAD ASCII). Uses 5710H to communicate the buffer limit address.

55C5
GOSUB to 6368H, the Comma Checker. Check for a trailing comma and option letter.
55C8
NO OPTION
If the Z FLAG has been set (no comma — no option), JUMP to 55E5H for the default SAVE/MERGE path.
55CA
RST 08H ⇒ 41H CF 41
Check that the next character is A (41H, the ASCII format option). If not, raises a Syntax Error.
55CC
OR A B7
Set flags from A.
55CD
ERROR EXIT
If the NZ FLAG has been set (additional characters after “A”), JUMP to 1997H for Syntax Error.
55D0
PUSH HL E5
Save the BASIC text pointer.
55D1
LD HL,FE80H 21 80 FE
Load HL with FE80H (−384 in two’s complement). This will be added to SP to calculate the available buffer space.
55D4
ADD HL,SP 39
ADD SP to HL. Result: HL = SP − 384, the maximum safe buffer address.
55D5
LD (5710H),HL 22 10 57
EXTERNAL WRITE — BASIC/CMD 5710H
Store HL (the buffer limit) to memory location 5710H, the SYS19 Communication Byte in the FCB work area. This tells the file write routines the maximum address they can use for buffering.
55D8
LD DE,(40F9H) ED 5B F9 40
Load DE from 40F9H, the String Space Start.
55DC
RST 18H DF
Compare HL (buffer limit) against DE (string space start). If HL < DE, the CARRY FLAG is set (not enough memory).
55DD
ERROR EXIT
If the CARRY FLAG has been set (buffer limit is below string space — not enough memory), JUMP to 197AH for Out of Memory error.
55E0
POP HL E1
Restore the BASIC text pointer.
55E1
XOR A AF
Set A to 00H.
55E2
ASCII SAVE/LOAD
JUMP to ROM routine at 2B2EH for ASCII SAVE/LOAD Processing. This ROM routine handles the actual ASCII file I/O based on the context established by SYS19.

55E5H - Default SAVE Path (No Option)

SAVE without the “A” option (packed binary format). Reads the byte before the program start, temporarily writes FFH as an end-of-file marker, computes the file size, writes the program to disk via SVC 4439H, restores the original byte, and then writes a terminator record. Uses the DOS file write routine at 6370H to complete the save.

55E5
PUSH HL E5
Save the BASIC text pointer.
55E6
LD HL,(40A4H) 2A A4 40
Load HL from 40A4H, the BASIC Program Start Address.
55E9
DEC HL 2B
DECrement HL by 1. HL now points to the byte immediately before the program start.
55EA
LD C,(HL) 4E
Fetch the original byte at (HL) into Register C (saved for later restoration).
55EB
LD (HL),FFH 36 FF
Write FFH to (HL) as a temporary start-of-file marker. The program file format begins with FFH before the first line.
55ED
LD (5710H),HL 22 10 57
EXTERNAL WRITE — BASIC/CMD 5710H
Store HL (the address of the FFH marker, one before program start) to 5710H. This tells the write routines where the file data begins.
55F0
EX DE,HL EB
Exchange DE and HL. DE = marker address, HL = (previous DE value).
55F1
LD HL,(40F9H) 2A F9 40
Load HL from 40F9H, the String Space Start (end of program + variables).
55F4
DEC H 25
DECrement H by 1, subtracting 256 from the string space start. This gives an approximate end-of-program address (the program data typically does not extend into the last 256 bytes before string space).
55F5
OR A B7
Clear the CARRY FLAG.
55F6
SBC HL,DE ED 52
SUBtract DE (file start address) from HL (approx file end). Result: HL = approximate file size.
55F8
PUSH AF F5
Save the flags (carry status from the subtraction).
55F9
VALID SIZE
If the NO CARRY FLAG has been set (file end >= file start — valid size), JUMP to 55FEH.
55FB
LD (IX+00H),L DD 75 00
Store the low byte of the size to IX+00H (the FCB status byte), adjusting the FCB for an undersized file.
55FD
LD (DE),A 12
Store A to (DE) as a file marker byte.
55FE
EX DE,HL EB
Exchange DE and HL. DE = file size, HL = file start address.
55FF
LD DE,570DH 11 0D 57
Point DE to 570DH, the Filename Buffer.
5602
GOSUB to 4439H to WRITE without verify a sector to disk or move a logical record from the caller’s buffer to the FCB’s buffer. Writes the program data to the file.
5605
LD (HL),C 71
Restore the original byte (saved in C at 55EAH) to the position before the program start, undoing the FFH marker.
5606
ERROR EXIT
If the NZ FLAG has been set (write error), JUMP to 5DEFH for error handling.
5609
INC H 24
INCrement H by 1, advancing HL by 256 bytes (adjusting the pointer past the data that was written).
560A
LD C,(HL) 4E
Fetch the byte at the new (HL) position into C (save for later use).
560B
POP AF F1
Restore the flags saved at 55F8H.
560C
If the CARRY FLAG has been set (from the size calculation), JUMP to 5610H.
560E
LOOP — write more data
If the NZ FLAG has been set (more data to write), JUMP back to 55EDH to write the next sector.
5610
GOSUB to 6240H, the DOS Op routine in BASIC/CMD. Performs a DOS operation to finalize the file write.
5613
LD (IX+11H),11H DD 36 11 00
Store 11H to IX+11H in the FCB. This sets a file attribute or position marker for the terminator record. Note: the hex bytes DD 36 11 00 decode as LD (IX+11H),00H — the actual immediate value stored is 00H, not 11H. The disassembler shows the mnemonic offset (11H) in the operand field.
5617
GOSUB to 6370H, the File Write+Filter routine in BASIC/CMD. Writes a byte to the file with error filtering.
561A
LOOP — write terminator
If the Z FLAG has been set (more bytes to write), JUMP back to 5617H.
561C
POP HL E1
Restore the BASIC text pointer (saved at 55E5H).
561D
SAVE COMPLETE
JUMP to ROM routine at 2169H. This ROM routine performs post-SAVE cleanup and returns to the BASIC command loop.

5620H - Merge Delta Accumulator Initializer

Initializes the merge delta accumulator at 5642H to 0000H and returns HL pointing to 543EH (the merge compaction routine address). Called at 52D7H to set up the delta tracking before the merge loop begins.

5620
LD HL,0000H 21 00 00
Load HL with 0000H.
5623
LD (5642H),HL 22 42 56
SELF-MODIFYING CODE
Store 0000H to the delta accumulator at 5642H.
5626
LD HL,543EH 21 3E 54
Load HL with 543EH, the address of the Merge Compaction routine. This will be stored to 6427H by the caller at 52DAH.
5629
RET C9
RETURN to the caller.

562AH - Delta Accumulation and Return

Adds the current merge delta (from 557AH) to the running total at 5642H, then restores DE and HL from the stack and returns. Called from the delta updater at 5492H.

562A
LD HL,(5642H) 2A 42 56
Load HL from the delta accumulator at 5642H (the running total of all merge deltas).
562D
LD DE,(557AH) ED 5B 7A 55
Load DE from 557AH (the current merge delta from the last 5478H call).
5631
ADD HL,DE 19
ADD the current delta to the running total.
5632
LD (5642H),HL 22 42 56
SELF-MODIFYING CODE
Store the updated running total back to 5642H.
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.

5638H - Delta Zero and Variable Relocate

Zeros the delta accumulator at 5642H by storing A (expected to be 00H) via BC, then calls the variable/string relocator at 54F2H. Called from 54D6H during merge pointer initialization.

5638
LD B,A 47
Copy A (00H) to B.
5639
LD C,A 4F
Copy A (00H) to C. BC = 0000H.
563A
LD (5642H),BC ED 43 42 56
SELF-MODIFYING CODE
Store BC (0000H) to the delta accumulator at 5642H, zeroing the running total.
563E
JUMP to 54F2H, the Variable/String Pointer Relocator, to initialize the relocation parameters and walk the variable and string tables.

5641H - Lower Bound Range Check

Checks whether the string address in DE is at or above the lower bound calculated from HL + BC. If DE is below the range, exits via 564EH which pops the return address and jumps to 5599H (skip relocation).

5641
LD BC,0000H 01 00 00
[SELF-MODIFYING CODE] Load BC from operand at 5642H (the delta accumulator). This value is added to HL to form the lower bound.
5644
ADD HL,BC 09
ADD BC to HL, forming the lower bound of the relocation range.
5645
SBC HL,DE ED 52
SUBtract DE (string address) from HL (lower bound). If HL > DE, the result is positive and CARRY is clear. If HL ≤ DE, CARRY is set.
5647
JUMP to 564CH for the common range check exit.

5649H - Upper Bound Range Check

Checks whether the string address in DE is below the upper bound in HL. Complements the carry flag so that the exit logic at 564CH works consistently for both bounds.

5649
SBC HL,DE ED 52
SUBtract DE (string address) from HL (upper bound).
564B
CCF 3F
Complement the CARRY FLAG. This inverts the carry so that the RET NC at 564CH has the correct polarity for both lower and upper bound checks.
564C
RET NC D0
If the NO CARRY FLAG has been set (the string address is within the valid range), RETURN to the caller to continue with the relocation check.
564D
POP AF F1
Pop and discard the return address from the stack. This skips the rest of the relocation check for this string.
564E
JUMP to 5599H, the Relocator Return (POP HL / XOR A / RET). This exits the string descriptor relocator without modifying the address, since the string was outside the relocation range.

5651H - NOP Padding

Unused/reserved area filled with NOP instructions (00H bytes). This padding extends from 5651H through 56E7H (151 bytes), filling the remainder of the SYS19 overlay space. The overlay occupies 5200H–56E7H (1,256 bytes total), matching the SYS18 overlay region.

5651–56E7
NOP × 151 00 × 151
Reserved/unused area — 151 bytes of 00H (NOP) padding. This fills the remainder of the SYS19 overlay from 5651H to 56E7H. The active code ends at 5650H; the remaining space is available for future expansion.