TRS-80 DOS - VTOS v4.0.2 for the Model I - SYS6/SYS Disassembled

Page Customization

Introduction:

VTOS 4.0 SYS6/SYS - Library Command Overlay (Model I)

SYS6/SYS holds the library commands of VTOS 4.0: ALLOC, APPEND, ATTRIB, AUTO, BUILD, CHAIN, CLOCK, COPY, DATE, DEBUG, DEVICE, DIR, DUMP, FILTER, FREE, KILL, LIB, LINK, LIST, LOAD, MEMORY, PRINT, PROT, PURGE, RENAME, RESET, ROUTE, RUN, SET, SPOOL, SYSTEM, TIME, TRACE, VERIFY and XFER, plus SYSGEN (run by SYSTEM (SYSGEN)) and O!, which displays the copyright notice. SYS1 finds the command in its command table (4EADH) and calls SYS6 with RST 28H, A = 88H and Register B = the command's ISAM number (SYS1 4EA2H).

SYS6/SYS is a partitioned data set (PDS): a directory of 37 ISAM entries, each giving an ISAM number, an entry (transfer) address and a triad pointer to the member that holds the code, followed by the 29 members. Only the member for the command is loaded. Every member loads at 5200H, except SET/FILTER, which loads at 5A00H, and each command is entered at its own address, so one member can serve several commands:

  • DATE (15H, 5200H) and TIME (16H, 522DH)
  • DEBUG (14H, 5200H), CLOCK (17H, 5241H), TRACE (1AH, 5257H) and VERIFY (1BH, 5267H)
  • APPEND (31H, 5200H) and COPY (32H, 5270H)
  • LIST (41H, 5200H) and PRINT (42H, 5206H)
  • SET (65H, 5A01H) and FILTER (66H, 5A00H)
  • LOAD (81H, 5200H) and RUN (82H, 520DH)
  • SPOOL (A2H) is entered at 5208H.

The sections below follow the order of the members in the file. Each gives the member's offset in the file, what it loads, and its code. Bytes that belong to a member's work areas but are not loaded from the file (FCBs, buffers, gaps between load blocks) are shown as DEFS rows without bytes.

About this disassembly

This page was rebuilt on 2026-09-25 from a byte-accurate listing of the 29 members of SYS6/SYS. Every row's bytes come from that listing, every loaded byte is on exactly one row, and the comments were written from the code. Branches to other VTOS modules link to the VTOS SYS0, SYS1 and SYS2 pages; calls into the ROM link to the Model I ROM (version 1.3) page.

Things worth knowing that the code shows:

  • The SYSTEM option shown by earlier versions of this page as SLOWER is named LOWER in the parameter table (56B9H). It installs a display driver that goes straight to the ROM display routines.
  • DATE accepts only years 80-87, and MEMORY only a value above 5200H and not above the current top of memory.
  • ATTRIB: giving PROT also makes an invisible file visible, unless I is given as well.
  • PROT pads a typed password one byte too far (5608H); PURGE, which has the same routine, does not.
  • DUMP's output routine executes RST 30H (the DEBUG entry) when a write fails, before reporting the error.
  • Several members contain code that nothing jumps to (for example PROT 520DH-5218H and XFER 52F0H-530DH); it is marked where it occurs.

How the SYS6 File Is Processed into ISAM Entries and PDS Members

SYS6/SYS is a Partitioned Data Set (PDS). The raw sys6.hex is not a flat binary — it is a structured container that begins with identification records, followed by a directory of commands (ISAM entries), and then the actual code for each command (the PDS members).

Here are the very first bytes from sys6.hex (shown exactly as they appear, grouped for readability):

05 06 53 59 53 36 20 20
1F 91 0D 2A 20 2A 20 2A 20 4E 20 4F 20 54 20 49 20 43 20 45 20 2A 20 2A 20 2A 0D ...
08 06 11 00 52 01 00 C9
08 06 15 00 52 02 00 1D
08 06 16 2D 52 02 00 1D
08 06 13 00 52 02 00 B2 ...

Step-by-Step Breakdown of the First Records

  1. Type 05H – Filename Header
    05 06 53 59 53 36 20 20
    • 05 = header record type
    • 06 = length of data
    • 53 59 53 36 20 20 = ASCII "SYS6 "
    This simply identifies the file as SYS6.
  2. Type 1FH – Copyright Block
    1F 91 0D 2A 20 2A ...
    This is a long informational block containing the copyright notice. The loader ignores this for normal execution.
     * * * N O T I C E * * * 
    * PROPRIETARY PROGRAM *
    * COPYRIGHT (C) 1980 *
    * BY RANDOLPH COOK *
    * ALL RIGHTS RESERVED *
    * * * N O T I C E * * *
  3. ISAM Directory Begins (Type 08H records)
    After the copyright and some padding, the real directory starts. Here is a consecutive snippet containing the first few ISAM entries:
    08 06 11 00 52 01 00 C9 ← ISAM 11H (AUTO)
    08 06 15 00 52 02 00 1D ← ISAM 15H (DATE)
    08 06 16 2D 52 02 00 1D ← ISAM 16H (TIME)
    08 06 13 00 52 02 00 B2 ← ISAM 13H (ALLOC)

    Take this real record from later in the directory:

    08 06 31 00 52 1D 00 FD
    • 08 = ISAM directory entry type
    • 06 = 6 data bytes follow
    • 31 = ISAM number = 31H (APPEND main)
    • 00 52 = Transfer / entry address = 5200H
    • 1D 00 FD = Triad pointer = NRN 1DH 00H / RBO FDH — this tells the loader exactly where on disk (or in the hex file) the code for this member begins.
      Since the TRS-80 uses 256 byte sectors, this math is easily shortcut to just the first byte and the last ... so this would be byte 1DFDH

      Specifically, the formula is File Offset = (NRN × 256) + RBO where NRN (Next Record Number) is the 2 byte logical record (sector group) in the file where the PDS member starts in lower-endian format (for a TRS-80 generally, this will always be nnH) and a 1 byte RBO (Relative Byte Offset) which is the byte offset within that record where the first byte of the member's code is located.

      The loader seeks to that byte offset in the file, then begins reading the load records (type 01H) that contain the actual Z80 code. It loads those bytes into memory starting at the address specified inside the load blocks (usually 5200H), and finally jumps to the transfer address from the ISAM record.

      This structure allows VTOS to load only the needed command into the overlay area at 5200H+, keeping memory usage efficient, and By including a transfer address in this code, you can use the identical routine at the Triad Pointer for different purposes, because it is loaded elsewhere.

      Examples:
      • AUTO triad 01 00 C9 → NRN=01 00 = 0001H (= go to record 1 of the SYS6 file), RBO=C9H (= 201 bytes to skip) → offset = (1 × 256) + 201 = 457 decimal (01C9H)
      • DATE/TIME triad 02 00 1D → NRN=02 00 = 0002H (= go to record 2 of the SYS6 file), RBO=1DH (= 29 bytes to skip) → offset = (2 × 256) + 29 = 541 decimal (021DH) as the exact byte to start

Utility

Tim Mann has developed, as part of his XTRS emulator, some routines which can assist in processing ISAM and PDS files:

SYS0 Routines Used by the Members

AddressWhat the members use it for
402DHExit to VTOS READY.
4030HExit to VTOS READY after a message has been displayed.
4300HCalled by SYSTEM (53A9H) as the SYS0 keyboard routine does.
4409HError handler: displays the error in Register A (bit 6 set = the message only).
4410HAdd a timer task: A = the slot, DE = the task block.
4413HRemove the timer task in slot A.
4416HUsed by a timer task to wait for its next run: the address after the CALL becomes the task's vector.
441CHRead a filespec (or device name) from the command line at HL into the FCB at DE.
4420HOpen a file, creating it if it does not exist (B = record length, HL = buffer).
4424HOpen an existing file.
4428HClose a file.
442CHKill a file.
4430HLoad a program file.
4436HRead a record.
4439HWrite a record.
443FHPosition a file to record 0.
4442HPosition a file to record BC.
4448HPosition a file to its end.
444EHWrite the ending record number into the file's directory entry.
4454HPosition a file back one sector.
4467HDisplay the text at HL (ending with 03H or 0DH).
446AHPrint the text at HL.
4473HGive the filespec in the FCB at DE the default extension at HL if it has none.
4476HScan the parameters in parentheses with the table at DE (six-character names, each followed by the address that receives the value).
4479HSend the text at HL to the device whose control block is at DE.
447BHDisplay the text at HL and copy it to the job log device when that is active.
447EHCopy a line, with the time, to the job log device (used by CHAIN).
44B8HSYS2, request 40H: check that drive C is there and ready.
44BBHSYS3, request 30H: build the file name of directory entry B on drive C as text.
4763HDisk driver: write a sector (function 0DH).
4768HDisk driver: write a system sector (function 0EH).
4772HDisk driver: verify a sector (function 0AH); a system sector verifies with error 06H.
4777HDisk driver: read a sector (function 09H).
478FHPoint IY to the drive control table of drive C.
4797HFetch byte A of the drive control table of drive C.
4B10HRead the directory sector that holds entry B of drive C into 4200H; HL = the entry.
4B1FHWrite that directory sector back.
4B45HRead sector E of track D of drive C into the buffer at HL.
4B65HRegister D = the directory track of drive C.
4B6CHMultiply: A = A × E.
4B8FHMultiply DE by A (24-bit result).
4DE7HPut DE at HL as four hexadecimal digits.
4DECHPut A at HL as two hexadecimal digits.

Full ISAM/PDS Breakdown

The directory follows the header record (05H, 0000H-0007H) and the copyright record (1FH, 91H bytes of data, 0008H-009AH). Each entry is eight bytes: type 08H, length 06H, the ISAM number, the entry address and the triad. The 37 entries run from 009BH to 01C2H.

Offset RangeLibrary
Command
Hex BytesExplanation
009B-00A2AUTO08 06 11 00 52
01 00 C9
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 11 = ISAM 11H
  • 00 52 = entry address 5200H
  • 01 00 C9 = triad: record 0001H, byte C9H → member at offset (1 × 256) + 201 = 457 (01C9H)
00A3-00AADATE08 06 15 00 52
02 00 1D
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 15 = ISAM 15H
  • 00 52 = entry address 5200H
  • 02 00 1D = triad: record 0002H, byte 1DH → member at offset (2 × 256) + 29 = 541 (021DH)
00AB-00B2TIME08 06 16 2D 52
02 00 1D
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 16 = ISAM 16H
  • 2D 52 = entry address 522DH
  • 02 00 1D = triad: record 0002H, byte 1DH → member at offset (2 × 256) + 29 = 541 (021DH)
00B3-00BAALLOC08 06 13 00 52
02 00 B2
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 13 = ISAM 13H
  • 00 52 = entry address 5200H
  • 02 00 B2 = triad: record 0002H, byte B2H → member at offset (2 × 256) + 178 = 690 (02B2H)
00BB-00C2KILL08 06 18 00 52
03 00 71
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 18 = ISAM 18H
  • 00 52 = entry address 5200H
  • 03 00 71 = triad: record 0003H, byte 71H → member at offset (3 × 256) + 113 = 881 (0371H)
00C3-00CALIB08 06 19 00 52
03 00 B1
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 19 = ISAM 19H
  • 00 52 = entry address 5200H
  • 03 00 B1 = triad: record 0003H, byte B1H → member at offset (3 × 256) + 177 = 945 (03B1H)
00CB-00D2DEBUG08 06 14 00 52
03 00 E8
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 14 = ISAM 14H
  • 00 52 = entry address 5200H
  • 03 00 E8 = triad: record 0003H, byte E8H → member at offset (3 × 256) + 232 = 1000 (03E8H)
00D3-00DACLOCK08 06 17 41 52
03 00 E8
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 17 = ISAM 17H
  • 41 52 = entry address 5241H
  • 03 00 E8 = triad: record 0003H, byte E8H → member at offset (3 × 256) + 232 = 1000 (03E8H)
00DB-00E2TRACE08 06 1A 57 52
03 00 E8
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 1A = ISAM 1AH
  • 57 52 = entry address 5257H
  • 03 00 E8 = triad: record 0003H, byte E8H → member at offset (3 × 256) + 232 = 1000 (03E8H)
00E3-00EAVERIFY08 06 1B 67 52
03 00 E8
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 1B = ISAM 1BH
  • 67 52 = entry address 5267H
  • 03 00 E8 = triad: record 0003H, byte E8H → member at offset (3 × 256) + 232 = 1000 (03E8H) (the triad was missing from the earlier table; VERIFY is in the DEBUG member, 5267H)
00EB-00F2O!
(Copyright Notice)
08 06 1D 00 52
04 00 E2
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 1D = ISAM 1DH
  • 00 52 = entry address 5200H
  • 04 00 E2 = triad: record 0004H, byte E2H → member at offset (4 × 256) + 226 = 1250 (04E2H)
00F3-00FAMEMORY08 06 1E 00 52
05 00 35
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 1E = ISAM 1EH
  • 00 52 = entry address 5200H
  • 05 00 35 = triad: record 0005H, byte 35H → member at offset (5 × 256) + 53 = 1333 (0535H)
00FB-0102SYSTEM's SYSGEN Command08 06 1C 00 52
05 00 C3
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 1C = ISAM 1CH
  • 00 52 = entry address 5200H
  • 05 00 C3 = triad: record 0005H, byte C3H → member at offset (5 × 256) + 195 = 1475 (05C3H)
0103-010ADIR08 06 21 00 52
08 00 27
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 21 = ISAM 21H
  • 00 52 = entry address 5200H
  • 08 00 27 = triad: record 0008H, byte 27H → member at offset (8 × 256) + 39 = 2087 (0827H)
010B-0112FREE08 06 22 00 52
0D 00 43
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 22 = ISAM 22H
  • 00 52 = entry address 5200H
  • 0D 00 43 = triad: record 000DH, byte 43H → member at offset (13 × 256) + 67 = 3395 (0D43H)
0113-011ACHAIN08 06 91 00 52
0F 00 20
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 91 = ISAM 91H
  • 00 52 = entry address 5200H
  • 0F 00 20 = triad: record 000FH, byte 20H → member at offset (15 × 256) + 32 = 3872 (0F20H)
011B-0122SYSTEM08 06 A1 00 52
14 00 B9
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • A1 = ISAM A1H
  • 00 52 = entry address 5200H
  • 14 00 B9 = triad: record 0014H, byte B9H → member at offset (20 × 256) + 185 = 5305 (14B9H)
0123-012ASPOOL08 06 A2 08 52
19 00 D7
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • A2 = ISAM A2H
  • 08 52 = entry address 5208H
  • 19 00 D7 = triad: record 0019H, byte D7H → member at offset (25 × 256) + 215 = 6615 (19D7H)
012B-0132APPEND08 06 31 00 52
1D 00 FD
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 31 = ISAM 31H
  • 00 52 = entry address 5200H
  • 1D 00 FD = triad: record 001DH, byte FDH → member at offset (29 × 256) + 253 = 7677 (1DFDH)
0133-013ACOPY08 06 32 70 52
1D 00 FD
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 32 = ISAM 32H
  • 70 52 = entry address 5270H
  • 1D 00 FD = triad: record 001DH, byte FDH → member at offset (29 × 256) + 253 = 7677 (1DFDH)
013B-0142BUILD08 06 33 00 52
20 00 A9
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 33 = ISAM 33H
  • 00 52 = entry address 5200H
  • 20 00 A9 = triad: record 0020H, byte A9H → member at offset (32 × 256) + 169 = 8361 (20A9H)
0143-014ALIST08 06 41 00 52
21 00 7C
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 41 = ISAM 41H
  • 00 52 = entry address 5200H
  • 21 00 7C = triad: record 0021H, byte 7CH → member at offset (33 × 256) + 124 = 8572 (217CH)
014B-0152PRINT08 06 42 06 52
21 00 7C
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 42 = ISAM 42H
  • 06 52 = entry address 5206H
  • 21 00 7C = triad: record 0021H, byte 7CH → member at offset (33 × 256) + 124 = 8572 (217CH)
0153-015AATTRIB08 06 51 00 52
24 00 A7
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 51 = ISAM 51H
  • 00 52 = entry address 5200H
  • 24 00 A7 = triad: record 0024H, byte A7H → member at offset (36 × 256) + 167 = 9383 (24A7H)
015B-0162PROT08 06 52 00 52
26 00 8D
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 52 = ISAM 52H
  • 00 52 = entry address 5200H
  • 26 00 8D = triad: record 0026H, byte 8DH → member at offset (38 × 256) + 141 = 9869 (268DH)
0163-016ARENAME08 06 53 00 52
29 00 BB
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 53 = ISAM 53H
  • 00 52 = entry address 5200H
  • 29 00 BB = triad: record 0029H, byte BBH → member at offset (41 × 256) + 187 = 10683 (29BBH)
016B-0172DEVICE08 06 61 00 52
2B 00 60
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 61 = ISAM 61H
  • 00 52 = entry address 5200H
  • 2B 00 60 = triad: record 002BH, byte 60H → member at offset (43 × 256) + 96 = 11104 (2B60H)
0173-017ALINK08 06 62 00 52
2D 00 C7
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 62 = ISAM 62H
  • 00 52 = entry address 5200H
  • 2D 00 C7 = triad: record 002DH, byte C7H → member at offset (45 × 256) + 199 = 11719 (2DC7H)
017B-0182RESET08 06 63 00 52
2E 00 D6
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 63 = ISAM 63H
  • 00 52 = entry address 5200H
  • 2E 00 D6 = triad: record 002EH, byte D6H → member at offset (46 × 256) + 214 = 11990 (2ED6H)
0183-018AROUTE08 06 64 00 52
30 00 CA
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 64 = ISAM 64H
  • 00 52 = entry address 5200H
  • 30 00 CA = triad: record 0030H, byte CAH → member at offset (48 × 256) + 202 = 12490 (30CAH)
018B-0192SET08 06 65 01 5A
32 00 6C
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 65 = ISAM 65H
  • 01 5A = entry address 5A01H
  • 32 00 6C = triad: record 0032H, byte 6CH → member at offset (50 × 256) + 108 = 12908 (326CH)
0193-019AFILTER08 06 66 00 5A
32 00 6C
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 66 = ISAM 66H
  • 00 5A = entry address 5A00H
  • 32 00 6C = triad: record 0032H, byte 6CH → member at offset (50 × 256) + 108 = 12908 (326CH)
019B-01A2DUMP08 06 71 00 52
33 00 91
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 71 = ISAM 71H
  • 00 52 = entry address 5200H
  • 33 00 91 = triad: record 0033H, byte 91H → member at offset (51 × 256) + 145 = 13201 (3391H)
01A3-01AAPURGE08 06 72 00 52
35 00 26
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 72 = ISAM 72H
  • 00 52 = entry address 5200H
  • 35 00 26 = triad: record 0035H, byte 26H → member at offset (53 × 256) + 38 = 13606 (3526H)
01AB-01B2XFER08 06 73 00 52
37 00 81
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 73 = ISAM 73H
  • 00 52 = entry address 5200H
  • 37 00 81 = triad: record 0037H, byte 81H → member at offset (55 × 256) + 129 = 14209 (3781H)
01B3-01BALOAD08 06 81 00 52
3A 00 5E
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 81 = ISAM 81H
  • 00 52 = entry address 5200H
  • 3A 00 5E = triad: record 003AH, byte 5EH → member at offset (58 × 256) + 94 = 14942 (3A5EH)
01BB-01C2RUN08 06 82 0D 52
3A 00 5E
  • 08 = ISAM directory entry (type 08H)
  • 06 = six data bytes
  • 82 = ISAM 82H
  • 0D 52 = entry address 520DH
  • 3A 00 5E = triad: record 003AH, byte 5EH → member at offset (58 × 256) + 94 = 14942 (3A5EH)

The six bytes 01C3H-01C8H between the directory and the first member (AUTO, 01C9H) are not in the listing this page was rebuilt from. The table of them on earlier versions of this page could not be checked and did not agree with the member offsets (it placed a record across 01C9H), so it has been removed.

ISAM 11H - AUTO - Offset 01C9

AUTO stores a command line that VTOS runs every time the system starts. The member loads at 5200H-524CH (77 bytes) and is entered at 5200H with HL pointing to the rest of the command line after AUTO. It copies 32 bytes from there into the GAT sector of drive 0 at offset E0H (42E0H while the sector is in the buffer at 4200H) and writes the sector back. AUTO with nothing after it stores just the carriage return, which leaves no command. Error codes returned: 14H (GAT read error) and 15H (GAT write error).

5200H - AUTO Command

Read the GAT of drive 0, put the command line into it at offset E0H and write it back.

5200
LD C,00H 0E 00
Load Register C with 00H to select drive 0.
5202
GOSUB to 5221H to read the GAT sector of drive 0 into the buffer at 4200H. HL and DE are preserved.
5205
If that failed (NZ, Register A = 14H), JUMP to the error exit at 521CH.
5208
LD D,42H 16 42
Load Register D with 42H.
520A
LD E,E0H 1E E0
Load Register E with E0H, so DE = 42E0H: offset E0H of the GAT, where the AUTO command is kept.
520C
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H: 32 bytes.
520F
LDIR ED B0
Copy 32 bytes from the command line at (HL) into the GAT buffer at 42E0H. The bytes after the carriage return that ends the typed line are copied as well; only the text up to the carriage return is used.
5211
LD C,00H 0E 00
Load Register C with 00H to select drive 0 again (the LDIR cleared BC).
5213
GOSUB to 5234H to write the GAT back to drive 0 and verify it.
5216
If that failed (NZ, Register A = 15H), JUMP to the error exit at 521CH.
5219
JUMP to 402DH: back to VTOS READY.

521CH - Error Exit

Reached with the error code in Register A.

521C
OR 40H F6 40
Set bit 6 of the error code, so that the error display shows only the message, without the extended file information.
521E
JUMP to the SYS0 error handler at 4409H to display the error and return to VTOS READY.

5221H - Read the GAT

Reads sector 0 of the directory track of the drive in Register C into 4200H. Returns Z if it was read, or NZ with Register A = 14H (GAT read error). DE and HL are preserved.

5221
PUSH DE D5
Save Register Pair DE.
5222
PUSH HL E5
Save Register Pair HL.
5223
GOSUB to the SYS0 routine at 4B65H, which returns the directory track of drive C in Register D.
5226
LD E,00H 1E 00
Load Register E with 00H: sector 0, the GAT.
5228
LD HL,4200H 21 00 42
Point HL to the sector buffer at 4200H.
522B
GOSUB to the SYS0 routine at 4B45H to read sector D,E of drive C into (HL). The directory track is written with the system data address mark, so the read returns error 06H; 4B45H treats that as success and returns Z.
522E
POP HL E1
Restore HL.
522F
POP DE D1
Restore DE.
5230
RET Z C8
If the sector was read (Z), RETURN.
5231
LD A,14H 3E 14
Load Register A with 14H: GAT read error. The flags are still NZ.
5233
RET C9
RETURN with NZ.

5234H - Write the GAT

Writes the buffer at 4200H back to sector 0 of the directory track of the drive in Register C, then reads it back to verify it. Returns Z if all went well, or NZ with Register A = 15H (GAT write error). DE and HL are preserved.

5234
PUSH DE D5
Save Register Pair DE.
5235
PUSH HL E5
Save Register Pair HL.
5236
GOSUB to 4B65H to get the directory track of drive C in Register D.
5239
LD E,00H 1E 00
Load Register E with 00H: sector 0, the GAT.
523B
LD HL,4200H 21 00 42
Point HL to the sector buffer at 4200H.
523E
GOSUB to the SYS0 routine at 4768H, which calls the disk driver with function 0EH to write a system sector (with the system data address mark).
5241
If the write failed (NZ), JUMP to 5248H with NZ still set.
5243
GOSUB to the SYS0 routine at 4772H, which calls the disk driver with function 0AH to verify (read back) the sector just written.
5246
CP 06H FE 06
A system sector that reads back correctly returns error 06H (attempted to read system data record). Compare Register A against 06H: Z means the sector was written and verified.
5248
LD A,15H 3E 15
Load Register A with 15H: GAT write error. The LD does not change the flags, so Register A only matters if NZ is set.
524A
POP HL E1
Restore HL.
524B
POP DE D1
Restore DE.
524C
RET C9
RETURN: Z = success, NZ = failure with Register A = 15H.

ISAM 15H (DATE) and 16H (TIME) - Offset 021D

One member serves both commands. It loads at 5200H-524BH and 524FH-528CH (138 bytes); the three bytes at 524CH-524EH are not in the file and hold the three numbers typed. DATE (ISAM 15H) enters at 5200H and TIME (ISAM 16H) at 522DH, both with HL pointing to what follows the command name. Each expects three fields of exactly two digits, separated by / for DATE (DATE MM/DD/YY) and : for TIME (TIME HH:MM:SS). The values are not range-checked. Anything else gives BAD FORMAT.

5200H - DATE Command (ISAM 15H)

Stores month, day and year in 4046H, 4045H and 4044H (the order in which the SYS0 routine at 4470H shows them as MM/DD/YY), and the packed form of the date in 4306H-4307H.

5200
LD C,2FH 0E 2F
Load Register C with / (2FH), the separator between the date fields.
5202
GOSUB to 525AH to read the three fields. The first (month) goes to 524EH, the second (day) to 524DH and the third (year) to 524CH.
5205
If they were not three valid fields (NZ), JUMP to 5243H to display BAD FORMAT.
5208
LD HL,524CH 21 4C 52
Point HL to the fields at 524CH (year, day, month).
520B
LD DE,4044H 11 44 40
Point DE to the system date at 4044H.
520E
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H.
5211
LDIR ED B0
Copy the three bytes: 4044H = year, 4045H = day, 4046H = month.
5213
LD DE,4044H 11 44 40
Point DE to 4044H again to build the packed date.
5216
LD A,(DE) 1A
Fetch the year.
5217
SUB 50H D6 50
Subtract 50H (80). The packed form has only three bits for the year, so only 80 to 87 are kept correctly.
5219
LD B,A 47
Save year - 80 in Register B.
521A
INC DE 13
Point DE to 4045H.
521B
LD A,(DE) 1A
Fetch the day.
521C
RLCA 07
Rotate it left three times: day x 8, the day in bits 3-7.
521D
RLCA 07
(second rotate)
521E
RLCA 07
(third rotate)
521F
OR B B0
Combine with year - 80 in bits 0-2.
5220
LD (4307H),A 32 07 43
Store it in 4307H: day x 8 + (year - 80).
5223
INC DE 13
Point DE to 4046H.
5224
LD A,(DE) 1A
Fetch the month.
5225
OR 50H F6 50
Set bits 4 and 6 (OR 50H).
5227
LD (4306H),A 32 06 43
Store it in 4306H: month + 50H. The SYS0 start-up code at 4E94H unpacks 4306H-4307H into 4044H-4046H again.
522A
JUMP to 402DH: back to VTOS READY.

522DH - TIME Command (ISAM 16H)

Stores hours, minutes and seconds in 4043H, 4042H and 4041H, the clock that the interrupt routine advances.

522D
LD C,3AH 0E 3A
Load Register C with : (3AH), the separator between the time fields.
522F
GOSUB to 525AH to read the three fields: hours to 524EH, minutes to 524DH, seconds to 524CH.
5232
If they were not three valid fields (NZ), JUMP to 5243H to display BAD FORMAT.
5235
LD HL,524CH 21 4C 52
Point HL to the fields at 524CH (seconds, minutes, hours).
5238
LD DE,4041H 11 41 40
Point DE to the clock at 4041H.
523B
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H.
523E
LDIR ED B0
Copy the three bytes: 4041H = seconds, 4042H = minutes, 4043H = hours.
5240
JUMP to 402DH: back to VTOS READY.

5243H - BAD FORMAT Exit

Shared by DATE and TIME.

5243
LD HL,524FH 21 4F 52
Point HL to the message BAD FORMAT at 524FH.
5246
GOSUB to the SYS0 routine at 447BH to display the message (447BH also copies it, with the time, to the job log device when that is active).
5249
JUMP to 4030H: back to VTOS READY without a further error message.
524C-524E
DEFS 3
The three fields read by 525AH: 524CH = third field, 524DH = second, 524EH = first. Not in the file (the gap between the two load records).
524F-5259
DEFM "BAD FORMAT",0DH 42 41 44 20 46 4F 52 4D 41 54 0D
Message displayed at 5246H.

525AH - Read Three Two-Digit Fields

HL points to the text, Register C holds the separator. Stores the three values from 524EH downward. Returns Z if all three fields were two digits each and the first two were followed by the separator; otherwise returns NZ. What follows the third field is not checked.

525A
LD DE,524EH 11 4E 52
Point DE to 524EH, where the first field goes.
525D
LD B,03H 06 03
Load Register B with 03H: three fields.
525F
PUSH DE D5
Save the store pointer.
5260
GOSUB to 526FH to read one two-digit number into Register A.
5263
POP DE D1
Restore the store pointer.
5264
RET NZ C0
If it was not two digits (NZ), RETURN with NZ.
5265
LD (DE),A 12
Store the value.
5266
DEC DE 1B
Move the store pointer down one byte.
5267
DEC B 05
Count the field.
5268
RET Z C8
If this was the third field, RETURN with Z.
5269
LD A,(HL) 7E
Fetch the character after the field.
526A
INC HL 23
Move past it.
526B
CP C B9
Compare it against the separator in Register C.
526C
If it matches, LOOP back to 525FH for the next field.
526E
RET C9
RETURN with NZ: the separator is missing.

526FH - Read a Two-Digit Number

Returns Z with the value (0-99) in Register A, or NZ if either of the next two characters is not a digit.

526F
GOSUB to 5286H to read the tens digit.
5272
If it is not a digit (NC), JUMP to 5284H.
5274
LD E,A 5F
Save the digit in Register E.
5275
RLCA 07
Rotate left twice: digit x 4 (the digit is below 10, so no bits are lost).
5276
RLCA 07
(second rotate)
5277
ADD A,E 83
Add the digit: x 5.
5278
RLCA 07
Rotate left: x 10.
5279
LD E,A 5F
Save the tens value in Register E.
527A
GOSUB to 5286H to read the units digit.
527D
If it is not a digit (NC), JUMP to 5284H.
527F
ADD A,E 83
Add the tens value.
5280
LD E,A 5F
Save the result in Register E.
5281
XOR A AF
Set the Z flag.
5282
LD A,E 7B
Load Register A with the value.
5283
RET C9
RETURN with Z.
5284
OR A B7
Register A is at least 0AH here, so OR A gives NZ.
5285
RET C9
RETURN with NZ.

5286H - Read One Digit

Fetches the character at (HL) and moves HL past it. Returns Carry set with the digit value (0-9) in Register A if it was 0-9, or No Carry otherwise.

5286
LD A,(HL) 7E
Fetch the character.
5287
INC HL 23
Move HL past it.
5288
SUB 30H D6 30
Subtract 30H (0). Characters below 0 wrap round to a value of D0H or more.
528A
CP 0AH FE 0A
Compare against 0AH: Carry only for 0-9.
528C
RET C9
RETURN.

ISAM 13H - ALLOC - Offset 02B2

ALLOC (ALLOC filespec (SIZE=n)) opens the file, creating it if it does not exist, allocates disk space for it and marks it so that the space is kept when the file is closed. SIZE (or S) is the size in K: the program writes one sector of E5H at record n x 4 - 1, which makes the DOS allocate everything up to it, then puts back the file's old end of file. Without SIZE only the mark is set. The member loads at 5200H-52A2H and 52C3H-52D3H (180 bytes). 52A3H-52C2H (the FCB) is not in the file, and the 256-byte sector buffer at 52D4H lies past the end of the member.

5200H - ALLOC Command

HL points to the text after ALLOC.

5200
LD DE,52A3H 11 A3 52
Point DE to the FCB at 52A3H.
5203
GOSUB to the SYS0 routine at 441CH to copy the filespec at (HL) into the FCB. HL is left after it.
5206
If there was no valid filespec (NZ), JUMP to 526EH to display FILE SPEC REQUIRED.
5208
LD DE,52C3H 11 C3 52
Point DE to the parameter table at 52C3H.
520B
GOSUB to the SYS0 routine at 4476H to read the parameters in parentheses. A value given for SIZE or S is stored straight into the operand of the LD BC at 521DH.
520E
If a parameter was not recognized (NZ), JUMP to 528AH to display PARAMETER ERROR.
5210
LD DE,52A3H 11 A3 52
Point DE to the FCB.
5213
LD HL,52D4H 21 D4 52
Point HL to the sector buffer at 52D4H.
5216
LD B,00H 06 00
Load Register B with 00H: record length 256.
5218
GOSUB to the SYS0 routine at 4420H to open the file, creating it if it is not on the disk.
521B
If that failed (NZ), JUMP to the error exit at 5269H.
521D
LD BC,0000H 01 00 00
Load Register Pair BC with the SIZE value. The operand (521EH-521FH) is 0000H in the file and is filled in by the parameter scan at 520BH.
5220
LD A,B 78
Test whether SIZE is zero.
5221
OR C B1
(OR the low byte)
5222
If no SIZE was given, JUMP to 5253H to set the directory flag only.
5224
LD HL,(52AFH) 2A AF 52
Fetch the file's current ending record number from the FCB (52AFH-52B0H, FCB+0CH).
5227
PUSH HL E5
Save it.
5228
SLA C CB 21
Multiply SIZE by 4 (four 256-byte sectors per K): shift the low byte left...
522A
RL B CB 10
...and carry into the high byte.
522C
SLA C CB 21
Shift left again...
522E
RL B CB 10
...and carry again: BC = SIZE x 4.
5230
DEC BC 0B
Subtract 1: BC = the number of the last record of the requested size.
5231
GOSUB to the SYS0 routine at 4442H to position the file (FCB in DE) to record BC.
5234
LD HL,52D4H 21 D4 52
Point HL to the sector buffer at 52D4H.
5237
LD DE,52D5H 11 D5 52
Point DE to 52D5H.
523A
LD BC,00FFH 01 FF 00
Load Register Pair BC with 00FFH.
523D
LD (HL),E5H 36 E5
Store E5H (the value a newly formatted sector holds) in the first byte of the buffer.
523F
LDIR ED B0
Copy it along the rest of the buffer: all 256 bytes are now E5H.
5241
LD DE,52A3H 11 A3 52
Point DE to the FCB.
5244
GOSUB to the SYS0 routine at 4439H to write the buffer as that record. The DOS allocates all the space up to it.
5247
POP HL E1
Restore the old ending record number.
5248
LD (52AFH),HL 22 AF 52
Put it back into the FCB, so that the file keeps its old end of file (the space stays allocated).
524B
PUSH AF F5
Save the result of the write (Z = written).
524C
GOSUB to the SYS0 routine at 443FH to position the file back to record 0.
524F
GOSUB to the SYS0 routine at 444EH, which writes the FCB's ending record number into the file's directory entry.
5252
POP AF F1
Restore the result of the write.

5253H - Set the Keep-Space Flag

Sets bit 7 of byte 1 of the file's directory entry. The SYS3 close routine does not release unused space of a file with this bit set (4E97H in SYS3).

5253
PUSH AF F5
Save the flags (Z = no errors so far, or Z from the SIZE test when there was no SIZE).
5254
LD BC,(52A9H) ED 4B A9 52
Load Register Pair BC from the FCB at 52A9H-52AAH: C = the drive number (FCB+06H), B = the directory entry code (FCB+07H).
5258
GOSUB to the SYS0 routine at 4B10H to read the directory sector that holds entry B of drive C. HL points to the entry.
525B
If the read failed (NZ, Register A = 11H), JUMP to 5269H.
525D
INC HL 23
Point HL to byte 1 of the entry.
525E
SET 7,(HL) CB FE
Set bit 7: keep the allocated space.
5260
GOSUB to the SYS0 routine at 4B1FH to write the directory sector back.
5263
If the write failed (NZ, Register A = 12H), JUMP to 5269H.
5265
POP AF F1
Restore the saved flags.
5266
If all went well (Z), JUMP to 402DH: back to VTOS READY. The file is not closed.

5269H - Error Exit

Register A holds the error code: from the open, the write, or the directory read or write.

5269
OR 40H F6 40
Set bit 6 of the error code, so that the error display shows only the message.
526B
JUMP to the SYS0 error handler at 4409H.

526EH - Message Exits

Display a message and return to VTOS READY through 4030H.

526E
LD HL,5277H 21 77 52
Point HL to FILE SPEC REQUIRED at 5277H.
5271
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5274
JUMP to 4030H: back to VTOS READY.
5277-5289
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Message displayed at 5271H.
528A
LD HL,5293H 21 93 52
Point HL to PARAMETER ERROR at 5293H.
528D
GOSUB to 447BH to display it.
5290
JUMP to 4030H: back to VTOS READY.
5293-52A2
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Message displayed at 528DH.
52A3-52C2
DEFS 32
FCB for the file. Not in the file (the gap between the two load records).

52C3H - Parameter Table

Used by the SYS0 parameter scan at 4476H: 6-character names padded with spaces, each followed by the address that receives the value, ended by 00H.

52C3-52CA
DEFM "SIZE " : DEFW 521EH 53 49 5A 45 20 20 1E 52
SIZE=n: stored in the operand of the LD BC at 521DH.
52CB-52D2
DEFM "S " : DEFW 521EH 53 20 20 20 20 20 1E 52
S=n: the short form, same address.
52D3
DEFB 00H 00
End of the table.

ISAM 18H - KILL - Offset 0371

KILL (KILL filespec) deletes a file. The member loads at 5200H-5238H (57 bytes); the 32-byte FCB at 5239H lies just past its end.

5200H - KILL Command

HL points to the text after KILL.

5200
LD DE,5239H 11 39 52
Point DE to the FCB at 5239H.
5203
GOSUB to the SYS0 routine at 441CH to copy the filespec at (HL) into the FCB.
5206
If there was no valid filespec (NZ), JUMP to 521DH to display FILE SPEC REQUIRED.
5209
GOSUB to the SYS0 routine at 4424H to open the existing file. HL and Register B are not set up for it; KILL never reads the file.
520C
If the file could not be opened (NZ, for example file not in directory), JUMP to the error exit at 5218H.
520F
GOSUB to the SYS0 routine at 442CH to kill the open file: its space is released and its directory entry freed.
5212
If that failed (NZ), JUMP to 5218H.
5215
JUMP to 402DH: back to VTOS READY.

5218H - Error Exit

Register A holds the error code from the open or the kill.

5218
OR 40H F6 40
Set bit 6 of the error code, so that only the message is displayed.
521A
JUMP to the SYS0 error handler at 4409H.

521DH - No Filespec

521D
LD HL,5226H 21 26 52
Point HL to FILE SPEC REQUIRED at 5226H.
5220
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5223
JUMP to 4030H: back to VTOS READY.
5226-5238
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Message displayed at 5220H.

ISAM 19H - LIB - Offset 03B1

LIB lists the names of the library commands, four to a line. It reads them from the command table of SYS1 at 4EADH, which is still in memory because SYS1 has just dispatched the command. The table has 8-byte entries (six characters of name and a two-byte handler) and ends with 00H, so BOOT is listed as well. The member loads at 5200H-522FH (48 bytes).

5200H - LIB Command

The spaces are sent as the Model I space compression codes: a character from C0H to FFH displays (code - C0H) spaces.

5200
LD HL,4EADH 21 AD 4E
Point HL to the first entry of the SYS1 command table at 4EADH.
5203
LD C,04H 0E 04
Load Register C with 04H: four names on this line.
5205
LD A,C2H 3E C2
Load Register A with C2H: two spaces.
5207
GOSUB to the ROM routine at 0033H to display it at the start of the line.
520A
LD B,06H 06 06
Load Register B with 06H: six characters of name.
520C
LD A,(HL) 7E
Fetch a character of the name.
520D
INC HL 23
Move to the next byte.
520E
GOSUB to 0033H to display it.
5211
LOOP back to 520CH until all six characters have been displayed.
5213
LD A,C8H 3E C8
Load Register A with C8H: eight spaces.
5215
GOSUB to 0033H to display them after the name.
5218
INC HL 23
Skip the first byte of the handler...
5219
INC HL 23
...and the second. HL points to the next entry.
521A
LD A,(HL) 7E
Fetch its first byte.
521B
OR A B7
Test for 00H, the end of the table.
521C
If this is the end, JUMP to 5228H.
521E
DEC C 0D
Count the name just shown.
521F
If the line holds fewer than four names, LOOP back to 520AH for the next one.
5221
LD A,0DH 3E 0D
Load Register A with a carriage return.
5223
GOSUB to 0033H to end the line.
5226
LOOP back to 5203H to start a new line.
5228
LD A,0DH 3E 0D
Load Register A with a carriage return.
522A
GOSUB to 0033H to end the last line.
522D
JUMP to 402DH: back to VTOS READY.

DEBUG (14H) / CLOCK (17H) / TRACE (1AH) / VERIFY (1BH) - Offset 03E8

One member holds four commands, each switched on or off: DEBUG (ISAM 14H, entry 5200H), CLOCK (ISAM 17H, entry 5241H), TRACE (ISAM 1AH, entry 5257H) and VERIFY (ISAM 1BH, entry 5267H). Each command is on unless (OFF), (NO) or (N) is given; ON, YES and Y are accepted and have no further effect. DEBUG also takes (EXT) or (E), which loads the extended debugger in SYS9. The member loads at 5200H-52F2H (243 bytes).

5200H - DEBUG Command (ISAM 14H)

DEBUG ON sets bit 7 of the system flags at 430FH and arms the BREAK key: 4315H-4317H become JP 400FH, the DEBUG entry. DEBUG OFF clears bit 7 and puts a RET at 4315H.

5200
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H.
5203
LD (523CH),BC ED 43 3C 52
Clear the EXT value at 523CH (the parameter scan clears it again).
5207
GOSUB to 5276H to read the parameters with the DEBUG table (EXT, E, ON, OFF, YES, NO, Y, N). Returns Z if OFF was given.
520A
LD HL,430FH 21 0F 43
Point HL to the system flags at 430FH.
520D
DI F3
Disable interrupts while 4315H-4317H are changed.
520E
If OFF was given (Z), JUMP to 522CH.
5210
LD A,(523CH) 3A 3C 52
Fetch the low byte of the EXT value: FFH if EXT or E was given, 00H if not.
5213
OR A B7
Test it.
5214
PUSH HL E5
Save HL (430FH).
5215
If EXT was given, GOSUB to 523EH to have SYS9 set up the extended debugger.
5218
POP HL E1
Restore HL (430FH).
5219
SET 7,(HL) CB FE
Set bit 7 of 430FH: DEBUG is on.
521B
LD HL,400FH 21 0F 40
Point HL to 400FH, the DEBUG entry vector.
521E
LD A,C3H 3E C3
Load Register A with C3H, the opcode of JP.
5220
LD (4316H),HL 22 16 43
Store 400FH as the jump address at 4316H-4317H.
5223
LD (4315H),A 32 15 43
Store the JP opcode at 4315H. The BREAK key now enters DEBUG through JP 400FH.
5226
LD A,CDH 3E CD
Load Register A with CDH. Register A is not used after this.
5228
EI FB
Enable interrupts.
5229
JUMP to 402DH: back to VTOS READY.
522C
RES 7,(HL) CB BE
Clear bit 7 of 430FH: DEBUG is off.
522E
LD A,C9H 3E C9
Load Register A with C9H, the opcode of RET.
5230
LD (4315H),A 32 15 43
Store it at 4315H: the BREAK key no longer enters DEBUG.
5233
LD A,3EH 3E 3E
Load Register A with 3EH. Neither this nor the next instruction has any effect.
5235
LD HL,EFA3H 21 A3 EF
Load HL with EFA3H (not used).
5238
EI FB
Enable interrupts.
5239
JUMP to 402DH: back to VTOS READY.
523C-523D
DEFW 0000H 00 00
EXT value. Receives the value of EXT or E from the parameter scan: FFFFH when the keyword is given without a value.

523EH - Load the Extended Debugger

Called from 5215H when EXT was given.

523E
LD A,8BH 3E 8B
Load Register A with 8BH: SYS9, request 00H.
5240
RST 28H EF
Call the overlay through RST 28H. The RST 28H handler does not come back to the byte after it: SYS9 returns straight to the caller of this routine, at 5218H.

5241H - CLOCK Command (ISAM 17H)

CLOCK ON adds a timer task in slot 6 whose task block at 4DABH points to the SYS0 routine at 4DAEH, which shows the time at the top right of the screen. CLOCK OFF removes it.

5241
GOSUB to 527BH to read the parameters (ON, OFF, YES, NO, Y, N). Returns Z if OFF was given.
5244
LD DE,4DABH 11 AB 4D
Point DE to the clock task block at 4DABH.
5247
LD A,06H 3E 06
Load Register A with 06H: task slot 6.
5249
If OFF was given (Z), JUMP to 5251H to remove the task.
524B
GOSUB to the SYS0 routine at 4410H to put the task block DE into slot A.
524E
JUMP to 402DH: back to VTOS READY.
5251
GOSUB to the SYS0 routine at 4413H to remove the task in slot A (the slot gets the dummy task block at 45BBH).
5254
JUMP to 402DH: back to VTOS READY.

5257H - TRACE Command (ISAM 1AH)

TRACE ON adds a timer task in slot 11. Its task block is the two bytes at 4DDBH (DDH 4DH), which point to the SYS0 routine at 4DDDH: it fetches the interrupted program's address from the stack and shows it in hexadecimal at 3C2EH, at the top of the screen. TRACE OFF removes the task.

5257
GOSUB to 527BH to read the parameters. Returns Z if OFF was given.
525A
LD DE,4DDBH 11 DB 4D
Point DE to the trace task block at 4DDBH.
525D
LD A,0BH 3E 0B
Load Register A with 0BH: task slot 11.
525F
If OFF was given (Z), JUMP to 5251H to remove the task.
5261
GOSUB to the SYS0 routine at 4410H to put the task block into slot 11.
5264
JUMP to 402DH: back to VTOS READY.

5267H - VERIFY Command (ISAM 1BH)

Changes the SYS0 jump vector for writing a record, JP 48C0H at 4439H. VERIFY ON makes it jump to 48DBH, the routine behind 443CH that writes and then verifies; VERIFY OFF puts back 48C0H.

5267
GOSUB to 527BH to read the parameters. Returns Z if OFF was given.
526A
LD HL,48C0H 21 C0 48
Point HL to 48C0H, the plain write routine.
526D
If OFF was given (Z), JUMP to 5272H.
526F
LD HL,48DBH 21 DB 48
Point HL to 48DBH, write with verify.
5272
LD (443AH),HL 22 3A 44
Store it as the address of the jump at 4439H (its operand is at 443AH-443BH).
5275
RET C9
RETURN. SYS1 left 402DH on the stack before it dispatched the command, so this goes back to VTOS READY.

5276H - Read the Parameters

Two entries: 5276H with the DEBUG table at 52B2H and 527BH with the ON/OFF table at 52C2H. The scan stores FFFFH (or the value given) at the address of each keyword it finds: OFF, NO and N go to 5290H, the operand of the LD BC at 528FH; ON, YES and Y go to the spare bytes at 5297H. Returns Z if OFF, NO or N was given, NZ otherwise.

5276
LD DE,52B2H 11 B2 52
Point DE to the DEBUG parameter table at 52B2H.
5279
JUMP to 527EH.
527B
LD DE,52C2H 11 C2 52
Point DE to the ON/OFF parameter table at 52C2H.
527E
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H.
5281
LD (5290H),BC ED 43 90 52
Clear the operand of the LD BC at 528FH.
5285
LD (523CH),BC ED 43 3C 52
Clear the EXT value at 523CH.
5289
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses (HL = the text after the command name).
528C
If a parameter was not recognized (NZ), JUMP to 5299H.
528F
LD BC,0000H 01 00 00
Load Register Pair BC with the OFF value. The operand (5290H-5291H) is 0000H unless OFF, NO or N was given.
5292
LD A,B 78
Combine the two bytes...
5293
OR C B1
(OR the low byte)
5294
XOR FFH EE FF
...and complement: A = 00H (Z) if the OFF value was FFFFH, otherwise non-zero (NZ).
5296
RET C9
RETURN.
5297-5298
DEFW 0000H 00 00
Receives the value of ON, YES or Y. Nothing reads it.

5299H - PARAMETER ERROR

Reached from 528CH. The return address of the scan routine is left on the stack; 4030H resets the stack.

5299
LD HL,52A2H 21 A2 52
Point HL to PARAMETER ERROR at 52A2H.
529C
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
529F
JUMP to 4030H: back to VTOS READY.
52A2-52B1
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Message displayed at 529CH.

52B2H - Parameter Tables

6-character names padded with spaces, each followed by the address that receives the value. The DEBUG table starts at 52B2H and runs on into the ON/OFF table at 52C2H; both end at 52F2H.

52B2-52B9
DEFM "EXT " : DEFW 523CH 45 58 54 20 20 20 3C 52
EXT: load the extended debugger.
52BA-52C1
DEFM "E " : DEFW 523CH 45 20 20 20 20 20 3C 52
E: short form of EXT.
52C2-52C9
DEFM "ON " : DEFW 5297H 4F 4E 20 20 20 20 97 52
ON: accepted, not used.
52CA-52D1
DEFM "OFF " : DEFW 5290H 4F 46 46 20 20 20 90 52
OFF: switch the function off.
52D2-52D9
DEFM "YES " : DEFW 5297H 59 45 53 20 20 20 97 52
YES: same as ON.
52DA-52E1
DEFM "NO " : DEFW 5290H 4E 4F 20 20 20 20 90 52
NO: same as OFF.
52E2-52E9
DEFM "Y " : DEFW 5297H 59 20 20 20 20 20 97 52
Y: same as ON.
52EA-52F1
DEFM "N " : DEFW 5290H 4E 20 20 20 20 20 90 52
N: same as OFF.
52F2
DEFB 00H 00
End of the tables.

ISAM 1DH - O! (Copyright Notice) - Offset 04E2

ISAM 1DH displays the copyright notice COPYRIGHT (C) 1980 BY RANDOLPH V. COOK, ALL RIGHTS RESERVED. The text is stored with 90H added to every character, so it cannot be read in a dump of the file. The member loads at 5200H-524BH (76 bytes).

5200H - Display the Copyright Notice

The first byte of the text block is the key; each following byte has the key subtracted and is displayed, until a 00H byte.

5200
LD HL,520EH 21 0E 52
Point HL to the key at 520EH.
5203
LD B,(HL) 46
Load Register B with the key, 90H.
5204
INC HL 23
Move to the next byte of the text.
5205
LD A,(HL) 7E
Fetch it.
5206
OR A B7
Test for 00H, the end of the text.
5207
RET Z C8
At the end, RETURN (to 402DH, left on the stack by SYS1: VTOS READY).
5208
SUB B 90
Subtract the key, giving the ASCII character.
5209
GOSUB to the ROM routine at 0033H to display it.
520C
LOOP back to 5204H for the next character.
520E
DEFB 90H 90
The key subtracted from every character of the text.
520F-524A
DEFM "COPYRIGHT (C) 1980 BY RANDOLPH V. COOK, ALL RIGHTS RESERVED",0DH + 90H D3 DF E0 E9 E2 D9 D7 D8 E4 B0 B8 D3 B9 B0 C1 C9 C8 C0 B0 D2 E9 B0 E2 D1 DE D4 DF DC E0 D8 B0 E6 BE B0 D3 DF DF DB BC B0 D1 DC DC B0 E2 D9 D7 D8 E4 E3 B0 E2 D5 E3 D5 E2 E6 D5 D4 9D
The notice, each byte plus 90H (for example D3H - 90H = 43H, C). It ends with 9DH, a carriage return.
524B
DEFB 00H 00
End of the text.

ISAM 1EH - MEMORY - Offset 0535

MEMORY shows or lowers the top of the memory available to programs, the address kept at 4049H-404AH. MEMORY alone displays it as HIGH = X'nnnn'. MEMORY (HIGH=n) or (H=n) sets it to n, which must be above 5200H and not above the current value; otherwise RANGE ERROR is displayed. The member loads at 5200H-5286H (135 bytes).

5200H - MEMORY Command

HL points to the text after MEMORY.

5200
LD DE,5267H 11 67 52
Point DE to the parameter table at 5267H.
5203
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses. A value for HIGH or H is stored straight into the operand of the LD BC at 5208H.
5206
If a parameter was not recognized (NZ), JUMP to 5239H to display PARAMETER ERROR.
5208
LD BC,0000H 01 00 00
Load Register Pair BC with the HIGH value. The operand (5209H-520AH) is 0000H in the file.
520B
LD A,B 78
Test whether it is zero...
520C
OR C B1
(OR the low byte)
520D
...and if no value was given, JUMP to 5226H to display the current value.
520F
LD HL,5200H 21 00 52
Point HL to 5200H.
5212
XOR A AF
Clear the Carry flag.
5213
SBC HL,BC ED 42
Subtract the new value from 5200H.
5215
If the new value is 5200H or lower (No Carry), JUMP to 5252H to display RANGE ERROR.
5217
LD HL,(4049H) 2A 49 40
Fetch the current top of memory from 4049H.
521A
XOR A AF
Clear the Carry flag.
521B
SBC HL,BC ED 42
Subtract the new value from it.
521D
If the new value is higher than the current one (Carry), JUMP to 5252H. The top of memory can only be lowered.
521F
LD (4049H),BC ED 43 49 40
Store the new value at 4049H.
5223
JUMP to 402DH: back to VTOS READY.
5226
LD DE,(4049H) ED 5B 49 40
Fetch the current top of memory from 4049H into DE.
522A
LD HL,5281H 21 81 52
Point HL to the digits of the display line at 5281H.
522D
GOSUB to the SYS0 routine at 4DE7H to write DE there as four hexadecimal digits.
5230
LD HL,5278H 21 78 52
Point HL to the line HIGH = X'nnnn' at 5278H.
5233
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5236
JUMP to 402DH: back to VTOS READY.

5239H - Message Exits

Display a message and return to VTOS READY through 4030H.

5239
LD HL,5242H 21 42 52
Point HL to PARAMETER ERROR at 5242H.
523C
GOSUB to 447BH to display it.
523F
JUMP to 4030H: back to VTOS READY.
5242-5251
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Message displayed at 523CH.
5252
LD HL,525BH 21 5B 52
Point HL to RANGE ERROR at 525BH.
5255
GOSUB to 447BH to display it.
5258
JUMP to 4030H: back to VTOS READY.
525B-5266
DEFM "RANGE ERROR",0DH 52 41 4E 47 45 20 45 52 52 4F 52 0D
Message displayed at 5255H.

5267H - Parameter Table and Display Line

5267-526E
DEFM "HIGH " : DEFW 5209H 48 49 47 48 20 20 09 52
HIGH=n: stored in the operand of the LD BC at 5208H.
526F-5276
DEFM "H " : DEFW 5209H 48 20 20 20 20 20 09 52
H=n: the short form.
5277
DEFB 00H 00
End of the parameter table.
5278-5280
DEFM "HIGH = X'" 48 49 47 48 20 3D 20 58 27
Start of the line displayed at 5233H.
5281-5284
DEFM "XXXX" 58 58 58 58
Replaced with the four hexadecimal digits at 522DH.
5285-5286
DEFM "'",0DH 27 0D
End of the line.

ISAM 1CH - SYSGEN (called by SYSTEM) - Offset 05C3

There is no SYSGEN command in the SYS1 table: this member is run by the SYSTEM member (ISAM A1H, 5622H there) when SYSTEM (SYSGEN) or SYSTEM (SYSGEN=NO) is given, with HL holding the value of the SYSGEN parameter. A non-zero value saves the current configuration in the file CONFIG/SYS.CCC:0; 0000H (NO or OFF) deletes the file. The file is written as a load module: every saved area of memory becomes a load record, so loading the file puts the areas back. The member loads at 5200H-53A2H and 53B2H-5464H (598 bytes). 53A3H-53B1H (the end of the FCB) is not in the file, and the file buffer at 5500H lies past the member.

5200H - SYSGEN Entry

HL = the SYSGEN value from SYSTEM.

5200
LD A,(430FH) 3A 0F 43
Fetch the system flags from 430FH.
5203
BIT 5,A CB 6F
Test bit 5, which is set while a chain (DO) file is being run.
5205
If it is set, JUMP to 535DH to display SYSGEN INVALID DURING PROGRAM CHAINING.
5208
LD A,H 7C
Test the SYSGEN value...
5209
OR L B5
(OR the low byte)
520A
...and if it is 0000H (SYSGEN=NO), JUMP to 5329H to delete the configuration.

520DH - Save the Configuration

Creates CONFIG/SYS.CCC:0 and writes: a 05H header record with the name CONFIG, a load record that shows *** CONFIGURING *** near the bottom of the screen, a load record that puts a RET at 4012H (the interrupt hook) while the rest loads, the system areas listed at 542FH, the memory above the top of memory, the real bytes of 4012H-4014H, a record that clears the banner again, and a transfer record.

520D
LD DE,5392H 11 92 53
Point DE to the FCB at 5392H, which holds the filespec CONFIG/SYS.CCC:0.
5210
LD HL,5500H 21 00 55
Point HL to the file buffer at 5500H.
5213
LD B,00H 06 00
Load Register B with 00H: record length 256.
5215
GOSUB to the SYS0 routine at 4420H to open the file, creating it if it does not exist.
5218
If that failed (NZ), JUMP to the error exit at 538DH.
521B
LD A,05H 3E 05
Load Register A with 05H: header record type.
521D
GOSUB to 53B2H to write it to the file.
5220
LD A,06H 3E 06
Load Register A with 06H: six bytes of name follow.
5222
GOSUB to 53B2H to write it.
5225
LD B,06H 06 06
Load Register B with 06H.
5227
LD HL,53BDH 21 BD 53
Point HL to 53BDH, the word CONFIG inside the message USER CONFIGURATION BUILT.
522A
LD A,(HL) 7E
Fetch a character of the name.
522B
INC HL 23
Move to the next.
522C
GOSUB to 53B2H to write it.
522F
LOOP back to 522AH for all six characters.
5231
LD B,13H 06 13
Load Register B with 13H: 19 bytes.
5233
LD DE,3F93H 11 93 3F
Load DE with 3F93H, a position on the second-to-last line of the screen.
5236
LD HL,5409H 21 09 54
Point HL to *** CONFIGURING *** at 5409H.
5239
GOSUB to 5307H to write it as a load record for 3F93H: the banner is shown while the file loads.
523C
LD B,01H 06 01
Load Register B with 01H: one byte.
523E
LD DE,4012H 11 12 40
Load DE with 4012H, the interrupt (RST 38H) hook.
5241
LD HL,5408H 21 08 54
Point HL to the C9H byte at 5408H.
5244
GOSUB to 5307H to write a load record that puts a RET at 4012H, so no interrupt task runs while the areas are being loaded.
5247
XOR A AF
Set Register A to 00H.
5248
LD (4018H),A 32 18 40
Store it at 4018H (in memory, before the area from 4015H is saved).
524B
LD HL,542FH 21 2F 54
Point HL to the table of system areas at 542FH.
524E
LD C,(HL) 4E
Fetch the length of the area into BC...
524F
INC HL 23
(next byte)
5250
LD B,(HL) 46
(high byte of the length)
5251
INC HL 23
(next byte)
5252
LD A,B 78
Test the length...
5253
OR C B1
(OR the low byte)
5254
...and at the end of the table (length 0000H), JUMP to 5261H.
5256
LD E,(HL) 5E
Fetch the address of the area into DE.
5257
INC HL 23
(next byte)
5258
LD D,(HL) 56
(high byte of the address)
5259
INC HL 23
Move to the next table entry.
525A
PUSH HL E5
Save the table pointer.
525B
GOSUB to 52CEH to write BC bytes from DE as load records.
525E
POP HL E1
Restore the table pointer.
525F
LOOP back to 524EH for the next area.
5261
LD HL,FFFFH 21 FF FF
Point HL to FFFFH to find the end of memory.
5264
LD A,(HL) 7E
Fetch the byte there.
5265
LD B,A 47
Keep it in Register B.
5266
CPL 2F
Complement it.
5267
LD (HL),A 77
Store the complement.
5268
CP (HL) BE
Read it back and compare: Z if there is memory at this address.
5269
LD (HL),B 70
Put the original byte back.
526A
If there is memory here, JUMP to 5272H.
526C
LD A,H 7C
Otherwise move down 1K...
526D
SUB 04H D6 04
(subtract 04H from the high byte)
526F
LD H,A 67
(store it)
5270
...and LOOP back to 5264H to try again (BFFFH, 7FFFH and so on in 1K steps).
5272
LD DE,(4049H) ED 5B 49 40
Load DE with the top of memory available to programs, from 4049H.
5276
XOR A AF
Clear the Carry flag.
5277
SBC HL,DE ED 52
Subtract it from the end of memory: the number of bytes above the top of memory, where drivers and filters are kept.
5279
LD B,H 44
Put the count in BC...
527A
LD C,L 4D
(low byte)
527B
INC DE 13
...and point DE to the first byte above the top of memory.
527C
If there are any such bytes (NZ), GOSUB to 52CEH to save them as load records.
527F
LD B,03H 06 03
Load Register B with 03H.
5281
LD DE,4012H 11 12 40
Load DE with 4012H.
5284
LD HL,4012H 21 12 40
Point HL to 4012H as well.
5287
GOSUB to 5307H to write the three bytes now at 4012H-4014H: the real interrupt hook goes back last.
528A
LD B,13H 06 13
Load Register B with 13H: 19 bytes.
528C
LD DE,3F93H 11 93 3F
Load DE with 3F93H, where the banner was shown.
528F
LD HL,541CH 21 1C 54
Point HL to the 19 spaces at 541CH.
5292
GOSUB to 5307H to write them as a load record that clears the banner.
5295
LD A,02H 3E 02
Load Register A with 02H: transfer record type.
5297
GOSUB to 53B2H to write it.
529A
LD A,02H 3E 02
Load Register A with 02H: two bytes follow.
529C
GOSUB to 53B2H to write it.
529F
XOR A AF
Set Register A to 00H.
52A0
GOSUB to 53B2H to write the low byte of the transfer address...
52A3
XOR A AF
Set Register A to 00H.
52A4
...and GOSUB to 53B2H to write the high byte: transfer address 0000H.
52A7
GOSUB to the SYS0 routine at 4428H to close the file.
52AA
If that failed (NZ), JUMP to 538DH.
52AD
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
52B0
LD DE,0002H 11 02 00
Load DE with 0002H: track 0, sector 2.
52B3
LD C,00H 0E 00
Load Register C with 00H: drive 0.
52B5
GOSUB to the SYS0 routine at 4777H to read the sector (disk driver function 09H).
52B8
If that failed (NZ), JUMP to 538DH.
52BB
XOR A AF
Set Register A to 00H.
52BC
LD (4201H),A 32 01 42
Store it in byte 1 of the sector. SYSGEN=NO stores C9H (RET) here instead, so this byte is the switch in the system's start-up code that enables loading of the configuration file.
52BF
GOSUB to the SYS0 routine at 4763H to write the sector back (disk driver function 0DH).
52C2
If that failed (NZ), JUMP to 538DH.
52C5
LD HL,53B8H 21 B8 53
Point HL to USER CONFIGURATION BUILT at 53B8H.
52C8
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
52CB
JUMP to 402DH: back to VTOS READY.

52CEH - Save an Area of Memory

DE = the address of the area, BC = its length. Writes it as load records (type 01H) of at most 254 bytes each, with the same load address, to the file whose FCB is at 5392H.

52CE
EX DE,HL EB
HL = the address of the area.
52CF
LD DE,5392H 11 92 53
Point DE to the FCB at 5392H.
52D2
PUSH HL E5
Save the address.
52D3
PUSH BC C5
Save the length still to be written.
52D4
LD H,B 60
HL = the length...
52D5
LD L,C 69
(low byte)
52D6
LD BC,00FEH 01 FE 00
Load Register Pair BC with 00FEH: 254 bytes, the most a record can hold.
52D9
XOR A AF
Clear the Carry flag.
52DA
SBC HL,BC ED 42
Subtract 254 from the length.
52DC
If the length is 254 or more (No Carry), JUMP to 52E4H: this record takes 254 bytes (BC) and HL holds the rest.
52DE
POP BC C1
Otherwise restore the length into BC: this is the last record.
52DF
LD HL,0000H 21 00 00
HL = 0000H: nothing after it.
52E2
JUMP to 52E5H.
52E4
POP AF F1
Discard the saved length.
52E5
EX (SP),HL E3
Swap: the bytes left after this record go onto the stack, HL = the address of this record's data.
52E6
LD B,C 41
Register B = the number of data bytes in this record.
52E7
LD A,01H 3E 01
Load Register A with 01H: load record type.
52E9
GOSUB to 53B2H to write it.
52EC
LD A,B 78
Fetch the number of data bytes...
52ED
ADD A,02H C6 02
...plus 2 for the address: the record length byte.
52EF
GOSUB to 53B2H to write it.
52F2
LD A,L 7D
Low byte of the load address.
52F3
GOSUB to 53B2H to write it.
52F6
LD A,H 7C
High byte of the load address.
52F7
GOSUB to 53B2H to write it.
52FA
LD A,(HL) 7E
Fetch a data byte.
52FB
INC HL 23
Move to the next.
52FC
GOSUB to 53B2H to write it.
52FF
LOOP back to 52FAH for all the bytes of the record. HL now points to the next part of the area.
5301
POP BC C1
Fetch the number of bytes still to be written.
5302
LD A,B 78
Test it...
5303
OR C B1
(OR the low byte)
5304
...and if any remain, LOOP back to 52D2H for the next record.
5306
RET C9
RETURN.

5307H - Write a Load Record

B = number of bytes, DE = the load address, HL = where the data is now. Writes one load record (type 01H) to the file.

5307
PUSH HL E5
Save the data address.
5308
LD H,D 62
HL = the load address...
5309
LD L,E 6B
(low byte)
530A
LD DE,5392H 11 92 53
Point DE to the FCB at 5392H.
530D
LD A,01H 3E 01
Load Register A with 01H: load record type.
530F
GOSUB to 53B2H to write it.
5312
LD A,B 78
Fetch the number of bytes...
5313
ADD A,02H C6 02
...plus 2 for the address.
5315
GOSUB to 53B2H to write the record length.
5318
LD A,L 7D
Low byte of the load address.
5319
GOSUB to 53B2H to write it.
531C
LD A,H 7C
High byte of the load address.
531D
GOSUB to 53B2H to write it.
5320
POP HL E1
Restore the data address.
5321
LD A,(HL) 7E
Fetch a data byte.
5322
INC HL 23
Move to the next.
5323
GOSUB to 53B2H to write it.
5326
LOOP back to 5321H for all B bytes.
5328
RET C9
RETURN.

5329H - Delete the Configuration

Reached when the SYSGEN value is 0000H.

5329
LD DE,5392H 11 92 53
Point DE to the FCB at 5392H with the filespec CONFIG/SYS.CCC:0.
532C
GOSUB to the SYS0 routine at 4424H to open it. HL and Register B are not set up; the file is only going to be killed.
532F
LD HL,53ECH 21 EC 53
Point HL to NO USER CONFIGURATION FOUND at 53ECH.
5332
If the file could not be opened (NZ), JUMP to 5360H to display it.
5335
GOSUB to the SYS0 routine at 442CH to kill the file.
5338
If that failed (NZ), JUMP to 538DH.
533B
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
533E
LD DE,0002H 11 02 00
Load DE with 0002H: track 0, sector 2.
5341
LD C,00H 0E 00
Load Register C with 00H: drive 0.
5343
GOSUB to 4777H to read the sector.
5346
If that failed (NZ), JUMP to 538DH.
5349
LD A,C9H 3E C9
Load Register A with C9H.
534B
LD (4201H),A 32 01 42
Store it in byte 1 of the sector (see 52BCH).
534E
GOSUB to 4763H to write the sector back.
5351
If that failed (NZ), JUMP to 538DH.
5354
LD HL,53D1H 21 D1 53
Point HL to USER CONFIGURATION DELETED at 53D1H.
5357
GOSUB to 447BH to display it.
535A
JUMP to 402DH: back to VTOS READY.

535DH - Message and Error Exits

535D
LD HL,5366H 21 66 53
Point HL to SYSGEN INVALID DURING PROGRAM CHAINING at 5366H.
5360
GOSUB to 447BH to display the message at HL.
5363
JUMP to 4030H: back to VTOS READY.
5366-538C
DEFM "SYSGEN INVALID DURING PROGRAM CHAINING",0DH 53 59 53 47 45 4E 20 49 4E 56 41 4C 49 44 20 44 55 52 49 4E 47 20 50 52 4F 47 52 41 4D 20 43 48 41 49 4E 49 4E 47 0D
Message displayed at 5360H.
538D
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
538F
JUMP to the SYS0 error handler at 4409H.

5392H - FCB

The filespec is stored in the FCB itself; opening the file replaces it with the FCB data.

5392-53A2
DEFM "CONFIG/SYS.CCC:0",00H 43 4F 4E 46 49 47 2F 53 59 53 2E 43 43 43 3A 30 00
Filespec of the configuration file (password CCC).
53A3-53B1
DEFS 15
The rest of the 32-byte FCB. Not in the file.

53B2H - Write a Byte to the File

Writes Register A to the file whose FCB is at DE. Errors end the command.

53B2
GOSUB to the ROM routine at 001BH to output the byte to the file (DE = its FCB).
53B5
RET Z C8
If it was written (Z), RETURN.
53B6
Otherwise JUMP to the error exit at 538DH.
53B8-53D0
DEFM "USER CONFIGURATION BUILT",0DH 55 53 45 52 20 43 4F 4E 46 49 47 55 52 41 54 49 4F 4E 20 42 55 49 4C 54 0D
Displayed at 52C8H. The word CONFIG at 53BDH is also the name in the header record.
53D1-53EB
DEFM "USER CONFIGURATION DELETED",0DH 55 53 45 52 20 43 4F 4E 46 49 47 55 52 41 54 49 4F 4E 20 44 45 4C 45 54 45 44 0D
Displayed at 5357H.
53EC-5407
DEFM "NO USER CONFIGURATION FOUND",0DH 4E 4F 20 55 53 45 52 20 43 4F 4E 46 49 47 55 52 41 54 49 4F 4E 20 46 4F 55 4E 44 0D
Displayed from 5332H.
5408
DEFB C9H C9
The RET put at 4012H by the record written at 5244H.
5409-541B
DEFM "*** CONFIGURING ***" 2A 2A 2A 20 43 4F 4E 46 49 47 55 52 49 4E 47 20 2A 2A 2A
The banner written at 5239H.
541C-542E
DEFM 19 spaces 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
Written at 5292H to clear the banner.

542FH - Table of Saved System Areas

Each entry is a length and an address; the table ends with a length of 0000H.

542F-5432
DEFW 0004H,4047H 04 00 47 40
4047H-404AH, including the top of memory at 4049H.
5433-5436
DEFW 0012H,404BH 12 00 4B 40
404BH-405CH.
5437-543A
DEFW 0018H,4015H 18 00 15 40
4015H-402CH: the three device control blocks at 4015H, 401DH and 4025H.
543B-543E
DEFW 0003H,4300H 03 00 00 43
4300H-4302H.
543F-5442
DEFW 0001H,430FH 01 00 0F 43
430FH: the system flags.
5443-5446
DEFW 0002H,4310H 02 00 10 43
4310H-4311H.
5447-544A
DEFW 0003H,4315H 03 00 15 43
4315H-4317H: the BREAK key jump.
544B-544E
DEFW 0048H,43B8H 48 00 B8 43
43B8H-43FFH, including the device control blocks at 43C0H.
544F-5452
DEFW 0003H,4BC0H 03 00 C0 4B
4BC0H-4BC2H.
5453-5456
DEFW 0003H,439CH 03 00 9C 43
439CH-439EH.
5457-545A
DEFW 0050H,4700H 50 00 00 47
4700H-474FH: the drive control table (10 bytes for each of drives 0-7).
545B-545E
DEFW 0003H,4439H 03 00 39 44
4439H-443BH: the jump for writing a record, which VERIFY changes.
545F-5462
DEFW 0018H,4500H 18 00 00 45
4500H-4517H: the task table (slots 0-11).
5463-5464
DEFW 0000H 00 00
End of the table.

ISAM 21H - DIR - Offset 0827

DIR (DIR name/ext:d (A,I,S,P)) lists the files on one drive, or on every drive that is ready when no drive is given. The name and extension are a pattern: characters that are left out match anything, so DIR /CMD lists every file with the extension CMD. The entries are found through the hash index table (sector 1 of the directory track). Normally three names are shown on a line, each followed by S (system file), I (invisible), P (password protected) and + (updated) where they apply. System and invisible files are only listed with S and I. A adds the protection level, the number of records (EOF=), the space allocated in K (SIZ= or, for files marked by ALLOC, SIZ:) and the date, one file to a line. P also sends the listing to the printer. SHIFT and @ pause the listing, BREAK stops it. The member loads at 5200H-5701H (1,282 bytes) and uses 5800H-58FFH for the hash index table and 5900H-59FFH for extended directory entries.

5200H - DIR Command

HL points to the text after DIR.

5200
JUMP over a subroutine and work bytes to 5213H.

5203H - Fetch the Ending Record Number

Entry: Register A = offset of the ending record number in the directory entry at 42xxH (entry+14H). Returns DE = the number of 256-byte sectors that hold data: the ending record number, minus 1 if the last sector is only partly used (the EOF byte at 5211H is not 00H). HL is left pointing to 5211H.

5203
LD L,A 6F
Point HL to the ending record number in the entry.
5204
LD E,(HL) 5E
Fetch the low byte...
5205
INC L 2C
...next byte...
5206
LD D,(HL) 56
...and the high byte into DE.
5207
LD HL,5211H 21 11 52
Point HL to the EOF byte at 5211H.
520A
LD A,(HL) 7E
Fetch it.
520B
OR A B7
Test it.
520C
RET Z C8
If the file ends on a sector boundary (00H), RETURN with DE unchanged.
520D
DEC DE 1B
Otherwise the last sector counts in the EOF byte instead: subtract 1.
520E
RET C9
RETURN.
520F-5211
DEFB 00H,00H,00H 00 00 00
Work area: a 24-bit number, high byte first. 5211H first receives the EOF byte of the entry (5435H); then 5440H-5452H make the three bytes (sectors x 256) + EOF + record length - 1, which is divided by the record length at 5455H.
5212
DEFB 00H 00
Not used.

5213H - Read the Pattern and Drive

Copies up to eight name characters to 56F6H and up to three extension characters to 56FEH (both start as spaces, which match anything), then a drive number after :.

5213
LD A,(HL) 7E
Fetch a character of the command line.
5214
INC HL 23
Move past it.
5215
CP 20H FE 20
Is it a space?
5217
If so, LOOP back to 5213H to skip it.
5219
LD DE,56F6H 11 F6 56
Point DE to the name part of the pattern at 56F6H.
521C
LD B,08H 06 08
Load Register B with 08H: at most eight characters.
521E
CP 41H FE 41
Compare the character against A.
5220
If it is A or above, JUMP to 522AH to take it.
5222
CP 3AH FE 3A
Compare it against :.
5224
If it is between : and @, JUMP to 5230H: the name has ended.
5226
CP 30H FE 30
Compare it against 0.
5228
If it is below 0, JUMP to 5230H: the name has ended.
522A
LD (DE),A 12
Store the character in the pattern.
522B
INC DE 13
Move the store pointer on.
522C
LD A,(HL) 7E
Fetch the next character.
522D
INC HL 23
Move past it.
522E
LOOP back to 521EH for up to eight characters.
5230
CP 2FH FE 2F
Is the character after the name a /?
5232
If not, JUMP to 524DH.
5234
LD DE,56FEH 11 FE 56
Point DE to the extension part of the pattern at 56FEH.
5237
LD B,03H 06 03
Load Register B with 03H: at most three characters.
5239
LD A,(HL) 7E
Fetch the character after the /.
523A
INC HL 23
Move past it.
523B
CP 41H FE 41
Compare it against A.
523D
If it is A or above, JUMP to 5247H to take it.
523F
CP 3AH FE 3A
Compare it against :.
5241
If it is between : and @, JUMP to 524DH.
5243
CP 30H FE 30
Compare it against 0.
5245
If it is below 0, JUMP to 524DH.
5247
LD (DE),A 12
Store the character in the pattern.
5248
INC DE 13
Move the store pointer on.
5249
LD A,(HL) 7E
Fetch the next character.
524A
INC HL 23
Move past it.
524B
LOOP back to 523BH for up to three characters.
524D
CP 3AH FE 3A
Is the next character a :?
524F
LD C,00H 0E 00
Load Register C with 00H: start at drive 0.
5251
If there is no :, JUMP to 525CH. The byte at 52E7H stays FFH: every drive is listed.
5253
LD A,(HL) 7E
Fetch the drive digit.
5254
INC HL 23
Move past it...
5255
INC HL 23
...and past the next character.
5256
SUB 30H D6 30
Convert the digit to a number.
5258
LD C,A 4F
Register C = the drive.
5259
LD (52E7H),A 32 E7 52
Store it at 52E7H (the operand of the LD A at 52E6H): only this drive is listed.
525C
DEC HL 2B
Step HL back one character, to the character after the drive (or after the name).
525D
LD DE,562FH 11 2F 56
Point DE to the parameter table at 562FH.
5260
PUSH BC C5
Save the drive number.
5261
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
5264
POP BC C1
Restore the drive number.
5265
If a parameter was not recognized (NZ), JUMP to 5584H to display PARAMETER ERROR.

5268H - List One Drive

Register C = the drive. Displays the heading, then scans the hash index table.

5268
PUSH BC C5
Save the drive number.
5269
LD A,03H 3E 03
Load Register A with 03H...
526B
LD (53F5H),A 32 F5 53
...and store it as the names-per-line counter at 53F5H.
526E
LD A,C 79
Convert the drive number...
526F
ADD A,30H C6 30
...to its digit...
5271
LD (568AH),A 32 8A 56
...and put it in the heading at 568AH.
5274
GOSUB to 44B8H, which calls SYS2 (request 40H) to select drive C and check that it is ready.
5277
If it is not (NZ), JUMP to 52F6H.
527A
LD HL,5670H 21 70 56
Point HL to the heading FILE DIRECTORY --- DRIVE n at 5670H.
527D
GOSUB to 556CH to display it (and print it if P was given).
5280
POP BC C1
Restore the drive number...
5281
PUSH BC C5
...and save it again.
5282
GOSUB to 4B65H to get the directory track of drive C in Register D.
5285
LD E,00H 1E 00
Load Register E with 00H: the GAT.
5287
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
528A
GOSUB to 4B45H to read it.
528D
If that failed (NZ), JUMP to the error exit at 559DH.
5290
LD HL,42D0H 21 D0 42
Point HL to offset D0H of the GAT: the disk name.
5293
LD DE,5691H 11 91 56
Point DE to the name field of the second heading line at 5691H.
5296
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H.
5299
LDIR ED B0
Copy the eight characters of the disk name.
529B
LD DE,569DH 11 9D 56
Point DE to the date field at 569DH. HL is now at offset D8H of the GAT: the date the disk was formatted.
529E
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H.
52A1
LDIR ED B0
Copy the eight characters of the date (MM/DD/YY).
52A3
LD HL,5691H 21 91 56
Point HL to the second heading line at 5691H.
52A6
GOSUB to 556CH to display it.
52A9
LD A,0DH 3E 0D
Load Register A with a carriage return...
52AB
...and GOSUB to 5577H to output it: an empty line.
52AE
POP BC C1
Restore the drive number...
52AF
PUSH BC C5
...and save it again.
52B0
LD A,08H 3E 08
Load Register A with 08H: offset 8 of the drive control table.
52B2
GOSUB to the SYS0 routine at 4797H to fetch that byte for drive C.
52B5
AND 1FH E6 1F
Keep bits 0-4: the number of sectors per granule, minus 1.
52B7
INC A 3C
Add 1.
52B8
LD (5466H),A 32 66 54
Store the sectors per granule at 5466H (the operand of the LD A at 5465H).
52BB
POP BC C1
Restore the drive number.
52BC
GOSUB to 4B65H to get the directory track in Register D.
52BF
LD E,01H 1E 01
Load Register E with 01H: the hash index table (HIT).
52C1
LD HL,5800H 21 00 58
Point HL to the buffer at 5800H.
52C4
GOSUB to 4B45H to read it.
52C7
LD A,16H 3E 16
Load Register A with 16H (HIT read error). The LD does not change the flags.
52C9
If the read failed (NZ), JUMP to 559DH with error 16H.
52CC
LD HL,5800H 21 00 58
Point HL to the first byte of the hash index table.
52CF
JUMP to 5308H to examine it.

52D2H - Next Entry of the Hash Index Table

The position in the table is the directory entry code: bits 0-4 give the directory sector (from sector 2 on) and bits 5-7 the entry within it. The table is walked in the order 00H, 20H, 40H ... E0H, 01H, 21H ..., so the entries are visited sector by sector.

52D2
POP BC C1
Restore the drive (C) and the table position (B).
52D3
LD H,58H 26 58
Point H to the table at 5800H...
52D5
LD L,B 68
...and L to the position.
52D6
LD A,L 7D
Move to the next entry of the same sector...
52D7
ADD A,20H C6 20
(add 20H)
52D9
LD L,A 6F
(store it)
52DA
If there was no overflow, JUMP to 5308H.
52DC
INC L 2C
After E0H, go on to the next sector (low bits + 1).
52DD
BIT 5,L CB 6D
When the low bits reach 20H, the whole table has been seen...
52DF
...otherwise JUMP to 5308H.
52E1
LD A,0DH 3E 0D
Load Register A with a carriage return...
52E3
...and GOSUB to 5577H to end the last line.
52E6
LD A,FFH 3E FF
Load Register A with the drive given in the command (FFH if none was given; stored at 5259H).
52E8
INC A 3C
Add 1.
52E9
If a drive was given (NZ), JUMP to 402DH: back to VTOS READY.
52EC
INC C 0C
Next drive.
52ED
LD A,C 79
Fetch it.
52EE
CP 08H FE 08
Is it below 8?
52F0
If so, JUMP back to 5268H to list it.
52F3
JUMP to 402DH: all drives have been listed.

52F6H - Drive Not Ready

52F6
POP BC C1
Restore the drive number.
52F7
LD A,(52E7H) 3A E7 52
Fetch the drive given in the command (FFH if none).
52FA
INC A 3C
Add 1.
52FB
LD A,20H 3E 20
Load Register A with 20H (illegal drive number). The LD does not change the flags.
52FD
If a drive was given (NZ), JUMP to 559DH to report the error.
5300
INC C 0C
Otherwise go on with the next drive.
5301
LD A,C 79
Fetch it.
5302
CP 08H FE 08
Is it below 8?
5304
If so, JUMP back to 5268H.
5307
RET C9
RETURN: SYS1 left 402DH on the stack, so this goes back to VTOS READY.

5308H - Examine a Directory Entry

HL points into the hash index table at 5800H. An entry in use has a non-zero hash byte. Reads the directory sector that holds the entry, unless it is already in the buffer at 4200H, and decides whether the file is to be listed.

5308
LD A,(HL) 7E
Fetch the hash byte.
5309
OR A B7
Test it.
530A
If the entry is free (00H), JUMP back to 52D6H for the next one.
530C
LD B,L 45
Register B = the directory entry code.
530D
PUSH BC C5
Save the drive (C) and the code (B).
530E
LD A,L 7D
Copy the code...
530F
AND E0H E6 E0
...keep bits 5-7...
5311
LD L,A 6F
...as the offset of the entry within its sector (00H, 20H ... E0H).
5312
XOR B A8
XOR with the code: A = the directory sector (bits 0-4).
5313
CP FFH FE FF
Compare it against the sector now in the buffer (the operand at 5314H, FFH to begin with).
5315
If it is the same sector, JUMP to 5320H.
5317
LD (5314H),A 32 14 53
Remember the new sector at 5314H. (5314H is not reset for the next drive, although the buffer at 4200H has been used for that drive's GAT in the meantime.)
531A
GOSUB to the SYS0 routine at 4B10H to read the directory sector that holds entry B of drive C.
531D
If that failed (NZ, Register A = 11H), JUMP to 559DH.
5320
LD H,42H 26 42
HL = the entry at 42xxH.
5322
LD A,(HL) 7E
Fetch byte 0 of the entry: the attributes.
5323
BIT 4,A CB 67
Test bit 4: entry in use.
5325
If it is not in use, JUMP to 52D2H for the next entry.
5328
BIT 7,A CB 7F
Test bit 7: an extended entry (a continuation of another file's entry).
532A
If so, JUMP to 52D2H: it is not listed on its own.
532D
BIT 6,A CB 77
Test bit 6: a system file.
532F
If it is not a system file, JUMP to 533BH.
5331
LD DE,0000H 11 00 00
Load DE with the S value (the operand at 5332H is set by the parameter scan).
5334
LD A,D 7A
Test it...
5335
OR E B3
(OR the low byte)
5336
...and if S was not given, JUMP to 52D2H: system files are skipped.
5339
JUMP to 5347H.
533B
BIT 3,A CB 5F
Test bit 3: an invisible file.
533D
If it is visible, JUMP to 5347H.
533F
LD DE,0000H 11 00 00
Load DE with the I value (the operand at 5340H is set by the parameter scan).
5342
LD A,D 7A
Test it...
5343
OR E B3
(OR the low byte)
5344
...and if I was not given, JUMP to 52D2H: invisible files are skipped.
5347
LD A,L 7D
Point HL to the name in the entry (entry+05H)...
5348
ADD A,05H C6 05
Add 05H...
534A
LD L,A 6F
...giving L.
534B
LD DE,56F6H 11 F6 56
Point DE to the pattern at 56F6H.
534E
LD B,0BH 06 0B
Load Register B with 0BH: eight characters of name and three of extension.
5350
LD A,(DE) 1A
Fetch a character of the pattern.
5351
CP (HL) BE
Compare it with the entry.
5352
If they are the same, JUMP to 5359H.
5354
CP 20H FE 20
Otherwise the pattern character must be a space (matches anything)...
5356
...or the file is skipped: JUMP to 52D2H.
5359
INC HL 23
Move on in the entry...
535A
INC DE 13
...and in the pattern.
535B
LOOP back to 5350H for all eleven characters.

535DH - Show the Name and Flags

Each file takes a field of 20 characters (Register C counts what is left of it).

535D
LD A,L 7D
Point HL back to the name in the entry:
535E
AND E0H E6 E0
the start of the entry...
5360
ADD A,05H C6 05
...plus 05H.
5362
LD L,A 6F
Store it in L.
5363
LD C,14H 0E 14
Load Register C with 14H: 20 characters.
5365
LD B,08H 06 08
Load Register B with 08H: up to eight characters of name.
5367
LD A,(HL) 7E
Fetch a character of the name.
5368
INC HL 23
Move to the next.
5369
CP 20H FE 20
Is it a space?
536B
If so, the name has ended: JUMP to 5375H.
536D
GOSUB to 5577H to output the character.
5370
DEC C 0D
Count it in the field.
5371
LOOP back to 5367H for up to eight characters.
5373
JUMP to 5379H: HL points to the extension.
5375
LD A,L 7D
Point HL past the rest of the name to the extension:
5376
ADD A,B 80
add the number of characters left...
5377
DEC A 3D
...minus 1.
5378
LD L,A 6F
Store it in L.
5379
LD A,(HL) 7E
Fetch the first character of the extension.
537A
CP 20H FE 20
Is it a space?
537C
If there is no extension, JUMP to 5392H.
537E
LD A,2FH 3E 2F
Load Register A with /...
5380
...and GOSUB to 5577H to output it.
5383
DEC C 0D
Count it.
5384
LD B,03H 06 03
Load Register B with 03H.
5386
LD A,(HL) 7E
Fetch a character of the extension.
5387
INC HL 23
Move to the next.
5388
CP 20H FE 20
Is it a space?
538A
If so, JUMP to 5392H.
538C
GOSUB to 5577H to output it.
538F
DEC C 0D
Count it.
5390
LOOP back to 5386H for up to three characters.
5392
LD A,20H 3E 20
Load Register A with a space...
5394
...and GOSUB to 5577H to output it.
5397
DEC C 0D
Count it.
5398
LD A,L 7D
Point HL back to the start of the entry:
5399
AND E0H E6 E0
Keep bits 5-7...
539B
LD L,A 6F
...giving L.
539C
LD B,(HL) 46
Register B = the attributes (byte 0).
539D
BIT 6,B CB 70
Test bit 6: system file.
539F
LD A,53H 3E 53
Load Register A with S.
53A1
If it is a system file, GOSUB to 5410H to output it.
53A4
BIT 3,B CB 58
Test bit 3: invisible.
53A6
LD A,49H 3E 49
Load Register A with I.
53A8
If it is invisible, GOSUB to 5410H to output it.
53AB
PUSH HL E5
Save the pointer to the entry.
53AC
LD A,L 7D
Point HL to the update password hash at entry+10H:
53AD
ADD A,10H C6 10
Add 10H...
53AF
LD L,A 6F
...giving L.
53B0
LD E,(HL) 5E
Fetch it into DE...
53B1
INC L 2C
Next byte.
53B2
LD D,(HL) 56
High byte.
53B3
PUSH HL E5
Save HL.
53B4
LD HL,4296H 21 96 42
Load HL with 4296H, the hash of a blank password.
53B7
SBC HL,DE ED 52
Compare (the Carry flag is clear here: ADD 10H did not overflow).
53B9
POP HL E1
Restore HL.
53BA
If there is no update password, JUMP to 53D0H: no P.
53BC
LD A,B 78
Fetch the attributes...
53BD
AND 07H E6 07
...and keep bits 0-2, the protection level.
53BF
LD A,50H 3E 50
Load Register A with P. The LD does not change the flags.
53C1
If the protection level is not 0, JUMP to 53D2H: P.
53C3
INC L 2C
Point HL to the access password hash at entry+12H...
53C4
LD E,(HL) 5E
...and fetch it into DE.
53C5
INC L 2C
Next byte.
53C6
LD D,(HL) 56
High byte.
53C7
LD HL,4296H 21 96 42
Load HL with 4296H, the hash of a blank password.
53CA
SBC HL,DE ED 52
Compare.
53CC
LD A,50H 3E 50
Load Register A with P.
53CE
If there is an access password, JUMP to 53D2H: P.
53D0
LD A,20H 3E 20
Load Register A with a space: not protected.
53D2
LD (5416H),A 32 16 54
Store the flag at 5416H (the operand of the LD A at 5415H), where the A listing looks at it.
53D5
CP 20H FE 20
Is it a space?
53D7
If not, GOSUB to 5410H to output the P.
53DA
POP HL E1
Restore the pointer to the entry.
53DB
INC HL 23
Point HL to byte 1 of the entry.
53DC
BIT 6,(HL) CB 76
Test bit 6: the file has been written to (set by the DOS when the file is closed after a write).
53DE
LD A,2BH 3E 2B
Load Register A with +.
53E0
If it is set, GOSUB to 5410H to output it.
53E3
DEC HL 2B
Point HL back to the start of the entry.
53E4
LD A,20H 3E 20
Load Register A with a space...
53E6
...and GOSUB to 5577H to output it.
53E9
DEC C 0D
Count it.
53EA
LOOP back to 53E4H until the 20-character field is full.
53EC
LD DE,0000H 11 00 00
Load DE with the A value (the operand at 53EDH is set by the parameter scan).
53EF
LD A,D 7A
Test it...
53F0
OR E B3
(OR the low byte)
53F1
...and if A was given, GOSUB to 5414H to show the details on the same line.
53F4
LD A,03H 3E 03
Load Register A with the names-per-line counter (the operand at 53F5H: 3, or 1 after an A line).
53F6
DEC A 3D
Count this file.
53F7
LD (53F5H),A 32 F5 53
Store the counter.
53FA
If the line is not full, JUMP to 52D2H for the next entry.
53FD
LD A,03H 3E 03
Load Register A with 03H...
53FF
LD (53F5H),A 32 F5 53
...and reset the counter.
5402
LD A,0DH 3E 0D
Load Register A with a carriage return...
5404
...and GOSUB to 5577H to end the line.
5407
GOSUB to 5603H to check for a pause or BREAK.
540A
If BREAK was pressed (NZ), JUMP to 4030H: back to VTOS READY.
540D
JUMP to 52D2H for the next entry.

5410H - Output a Flag Character

Counts the character in the field (Register C) and outputs it.

5410
DEC C 0D
Count the character.
5411
JUMP to 5577H to output it.

5414H - Show the Details (A)

HL points to the directory entry. Fills in and displays prot / EOF=nnnnn / SIZ=nnnnn.n K DD-MMM-YY.

5414
PUSH HL E5
Save the pointer to the entry.
5415
LD A,00H 3E 00
Load Register A with the P flag (stored at 53D2H: P or a space).
5417
SUB 20H D6 20
Subtract a space.
5419
If the file is not protected, JUMP to 541EH with A = 0: ALL.
541B
LD A,(HL) 7E
Fetch the attributes...
541C
AND 07H E6 07
...and keep the protection level.
541E
RLCA 07
Multiply by 4:
541F
RLCA 07
four characters per name.
5420
LD C,A 4F
BC = the offset...
5421
LD B,00H 06 00
Register B = 00H.
5423
LD HL,5650H 21 50 56
Point HL to the protection names at 5650H...
5426
ADD HL,BC 09
...and add the offset.
5427
LD DE,56A6H 11 A6 56
Point DE to the start of the details line at 56A6H.
542A
LD BC,0004H 01 04 00
Load Register Pair BC with 0004H.
542D
LDIR ED B0
Copy the name of the protection level.
542F
POP HL E1
Restore the pointer to the entry...
5430
PUSH HL E5
...and save it again.
5431
INC L 2C
Point HL to byte 3 of the entry:
5432
INC L 2C
Byte 2.
5433
INC L 2C
Byte 3.
5434
LD A,(HL) 7E
the EOF byte (the offset of the end of the file within its last sector).
5435
LD (5211H),A 32 11 52
Store it at 5211H.
5438
INC L 2C
Point HL to byte 4: the record length.
5439
LD A,(HL) 7E
Fetch it.
543A
LD (5454H),A 32 54 54
Store it at 5454H (the operand of the LD C at 5453H).
543D
LD A,L 7D
Compute the offset of the ending record number (entry+14H)...
543E
ADD A,10H C6 10
Add 10H: entry+14H.
5440
...and GOSUB to 5203H: DE = the sectors in use (see there), HL = 5211H.
5443
LD A,(5454H) 3A 54 54
Fetch the record length.
5446
DEC A 3D
Subtract 1...
5447
ADD A,(HL) 86
...and add the EOF byte.
5448
LD (HL),A 77
Store the low byte of the 24-bit number at 5211H.
5449
DEC HL 2B
Point to 5210H.
544A
LD A,E 7B
Middle byte: the low byte of the sector count plus the carry.
544B
ADC A,00H CE 00
Add the carry.
544D
LD (HL),A 77
Store it at 5210H.
544E
DEC HL 2B
Point to 520FH.
544F
LD A,D 7A
High byte: the high byte of the sector count plus the carry.
5450
ADC A,00H CE 00
Add the carry.
5452
LD (HL),A 77
Store it at 520FH. 520FH-5211H = the bytes in the file + record length - 1.
5453
LD C,00H 0E 00
Load Register C with the record length (the operand at 5454H; 00H means 256).
5455
GOSUB to 55DDH to divide: DE = the number of records, rounded up.
5458
EX DE,HL EB
HL = the number of records.
5459
LD DE,56B1H 11 B1 56
Point DE to the EOF= field at 56B1H.
545C
GOSUB to 55A2H to write it as five digits.
545F
POP HL E1
Restore the pointer to the entry...
5460
PUSH HL E5
...and save it again.
5461
GOSUB to 550AH to add up the granules allocated to the file: DE = the count.
5464
EX DE,HL EB
HL = the granules.
5465
LD A,00H 3E 00
Load Register A with the sectors per granule (the operand at 5466H, stored at 52B8H).
5467
GOSUB to the SYS0 routine at 4B8FH to multiply: the 24-bit product (the sectors allocated) comes back with bits 8-23 in HL and bits 0-7 in A.
546A
PUSH AF F5
Save the low byte.
546B
LD H,L 65
HL = the sectors allocated (bits 0-15)...
546C
LD L,A 6F
Register L = bits 0-7.
546D
SRL H CB 3C
...divided by 4: the number of whole K.
546F
RR L CB 1D
Rotate the bit into L.
5471
SRL H CB 3C
Shift right again...
5473
RR L CB 1D
...and rotate into L: HL = sectors / 4.
5475
LD DE,56BDH 11 BD 56
Point DE to the SIZ field at 56BDH.
5478
GOSUB to 55A2H to write the K as five digits.
547B
POP AF F1
Restore the low byte of the sector count...
547C
AND 03H E6 03
...and keep the sectors left over (0-3 quarters of a K).
547E
LD B,A 47
Register B = the quarters.
547F
LD A,30H 3E 30
Load Register A with 0. The LD does not change the flags.
5481
If there are none, JUMP to 548FH: .0.
5483
DEC B 05
Count down.
5484
LD A,32H 3E 32
One quarter: 2.
5486
If it was one quarter, JUMP to 548FH.
5488
DEC B 05
Count down.
5489
LD A,35H 3E 35
Two quarters: 5.
548B
If it was two quarters, JUMP to 548FH.
548D
LD A,38H 3E 38
Three quarters: 8.
548F
LD (56C3H),A 32 C3 56
Store the digit after the decimal point at 56C3H.
5492
LD HL,56C7H 21 C7 56
Point HL to the space at 56C7H.
5495
LD DE,56C8H 11 C8 56
Point DE to the date field at 56C8H.
5498
LD BC,0009H 01 09 00
Load Register Pair BC with 0009H.
549B
LDIR ED B0
Fill the date field with spaces.
549D
POP HL E1
Restore the pointer to the entry.
549E
LD DE,56C8H 11 C8 56
Point DE to the date field.
54A1
INC HL 23
Point HL to byte 1 of the entry.
54A2
BIT 7,(HL) CB 7E
Test bit 7, which ALLOC sets to keep the space allocated.
54A4
LD A,3DH 3E 3D
Load Register A with =.
54A6
If it is clear, JUMP to 54AAH.
54A8
LD A,3AH 3E 3A
Load Register A with :.
54AA
LD (56BCH),A 32 BC 56
Store it after SIZ at 56BCH.
54AD
INC HL 23
Point HL to byte 2 of the entry: day x 8 + year - 80 (the same packing as 4307H, see DATE).
54AE
LD A,(HL) 7E
Fetch it.
54AF
OR A B7
Test it.
54B0
If the file has no date (00H), JUMP to 54FEH: the field stays blank.
54B2
RRCA 0F
Shift the day...
54B3
RRCA 0F
(second rotate)
54B4
RRCA 0F
(third rotate)
54B5
AND 1FH E6 1F
...down into bits 0-4.
54B7
LD B,FFH 06 FF
Register B counts the tens, starting at -1.
54B9
INC B 04
Count a ten...
54BA
SUB 0AH D6 0A
...subtract 10...
54BC
...and LOOP back to 54B9H while nothing is borrowed.
54BE
ADD A,0AH C6 0A
Add the last 10 back: the units.
54C0
PUSH AF F5
Save them.
54C1
LD A,B 78
Fetch the tens...
54C2
ADD A,30H C6 30
...as a digit...
54C4
LD (DE),A 12
...and store it.
54C5
INC DE 13
Move to the units.
54C6
POP AF F1
Restore the units...
54C7
ADD A,30H C6 30
...as a digit...
54C9
LD (DE),A 12
...and store it.
54CA
INC DE 13
Move on.
54CB
INC DE 13
Skip the -.
54CC
PUSH HL E5
Save the pointer to byte 2.
54CD
DEC HL 2B
Point HL to byte 1 of the entry.
54CE
LD A,(HL) 7E
Fetch it.
54CF
AND 0FH E6 0F
Keep bits 0-3: the month.
54D1
DEC A 3D
Month - 1...
54D2
LD C,A 4F
Save it in C.
54D3
RLCA 07
...times 3...
54D4
ADD A,C 81
Add it: x 3.
54D5
LD C,A 4F
BC = the offset...
54D6
LD B,00H 06 00
(B = 00H)
54D8
LD HL,56D2H 21 D2 56
...indexes the month names at 56D2H.
54DB
ADD HL,BC 09
Add the offset.
54DC
LD BC,0003H 01 03 00
Load Register Pair BC with 0003H.
54DF
LDIR ED B0
Copy the three letters of the month.
54E1
INC DE 13
Skip the -.
54E2
LD A,38H 3E 38
Load Register A with 8: the years are 80-87.
54E4
LD (DE),A 12
Store it.
54E5
INC DE 13
Move to the last digit.
54E6
POP HL E1
Restore the pointer to byte 2...
54E7
PUSH HL E5
...and save it again.
54E8
LD A,(HL) 7E
Fetch the date byte...
54E9
AND 07H E6 07
...and keep bits 0-2: year - 80.
54EB
ADD A,30H C6 30
As a digit...
54ED
LD (DE),A 12
...store it.
54EE
POP HL E1
Restore the pointer...
54EF
DEC HL 2B
...and point HL to byte 1 of the entry.
54F0
BIT 4,(HL) CB 66
Test bit 4.
54F2
LD A,2DH 3E 2D
Load Register A with -.
54F4
If bit 4 is clear, JUMP to 54F8H.
54F6
LD A,2BH 3E 2B
Otherwise use +.
54F8
LD (56CAH),A 32 CA 56
Store it as the first separator of the date...
54FB
LD (56CEH),A 32 CE 56
...and as the second.
54FE
LD HL,56A6H 21 A6 56
Point HL to the details line at 56A6H.
5501
GOSUB to 556CH to display it (and print it if P was given). It ends with 03H, so the cursor stays on the line; the carriage return comes from 5402H.
5504
LD A,01H 3E 01
Load Register A with 01H...
5506
LD (53F5H),A 32 F5 53
...and set the names-per-line counter to 1, so that the line ends after this file.
5509
RET C9
RETURN.

550AH - Count the Granules of a File

HL points to the directory entry. Adds up the granules of every extent (bits 0-4 of the second byte of each two-byte extent, plus 1) until an FFH byte. An FEH byte links to an extended entry, whose code is in the byte after it; that entry is read and its extents are added as well. Returns DE = the granules and BC = the number of extents.

550A
LD DE,0000H 11 00 00
DE = 0000H: no granules yet.
550D
LD BC,0000H 01 00 00
BC = 0000H: no extents yet.
5510
LD A,L 7D
Point HL to the extents at entry+16H.
5511
ADD A,16H C6 16
Add 16H...
5513
LD L,A 6F
...giving L.
5514
LD A,(HL) 7E
Fetch the first byte of an extent (the cylinder).
5515
INC L 2C
Move to the second byte.
5516
CP FEH FE FE
Is it FEH or FFH?
5518
If so, JUMP to 5527H.
551A
INC BC 03
Count the extent.
551B
LD A,(HL) 7E
Fetch the second byte.
551C
INC L 2C
Move to the next extent.
551D
AND 1FH E6 1F
Keep bits 0-4: granules - 1.
551F
INC A 3C
Add 1.
5520
ADD A,E 83
Add the granules to the count.
5521
LD E,A 5F
Store the low byte.
5522
If there is no carry, LOOP back to 5514H.
5524
INC D 14
Carry into D.
5525
LOOP back to 5514H.
5527
RET NZ C0
If this is FFH (the end), RETURN.
5528
LD A,(HL) 7E
FEH: fetch the code of the extended entry.
5529
AND 1FH E6 1F
Keep bits 0-4: its directory sector.
552B
PUSH AF F5
Save it.
552C
XOR (HL) AE
XOR with the code: bits 5-7, the entry's place in the sector.
552D
NOP 00
(spare byte)
552E
NOP 00
(spare byte)
552F
LD L,A 6F
L = the offset of the entry within the sector.
5530
POP AF F1
Restore the sector.
5531
PUSH HL E5
Save HL.
5532
LD HL,5314H 21 14 53
Point HL to 5314H, the sector now in the buffer at 4200H.
5535
CP (HL) BE
Compare.
5536
POP HL E1
Restore HL.
5537
LD H,42H 26 42
H = 42H.
5539
If the extended entry is in the sector at 4200H, LOOP back to 5510H to count its extents.
553B
CP 00H FE 00
Compare the sector against the one last read into 5900H (the operand at 553CH, 00H to begin with).
553D
LD H,59H 26 59
H = 59H.
553F
If it is the same, JUMP to 5520H. This lands inside the counting loop with Register A holding the sector number, and HL at the start of the entry rather than at its extents; 5510H would have been correct.
5541
LD (553CH),A 32 3C 55
Remember the sector at 553CH.
5544
PUSH BC C5
Save the extent count.
5545
PUSH DE D5
Save the granule count.
5546
OR L B5
Put the entry's place back in: B = the directory entry code.
5547
LD B,A 47
Register B = the code.
5548
LD A,(568AH) 3A 8A 56
Fetch the drive digit from the heading...
554B
SUB 30H D6 30
...convert it...
554D
LD C,A 4F
...into Register C.
554E
GOSUB to 4B65H to get the directory track in Register D.
5551
LD A,B 78
Fetch the code again...
5552
AND 1FH E6 1F
...keep the sector bits...
5554
ADD A,02H C6 02
...plus 2 (the first directory sector).
5556
LD E,A 5F
Register E = the sector.
5557
LD HL,5900H 21 00 59
Point HL to the buffer at 5900H.
555A
GOSUB to 4B45H to read it.
555D
LD A,11H 3E 11
Load Register A with 11H (directory read error). The LD does not change the flags.
555F
If the read failed (NZ), JUMP to 559DH.
5562
LD A,B 78
Fetch the code...
5563
AND E0H E6 E0
...keep bits 5-7...
5565
ADD A,16H C6 16
...and add 16H:
5567
LD L,A 6F
HL = the extents of the extended entry at 59xxH.
5568
POP DE D1
Restore the granule count.
5569
POP BC C1
Restore the extent count.
556A
LOOP back to 5514H.

556CH - Output Routines

556CH displays the text at HL; 5577H outputs the character in Register A. Both also send it to the printer when P was given.

556C
GOSUB to the SYS0 routine at 4467H to display the text at HL.
556F
LD A,(557DH) 3A 7D 55
Fetch the low byte of the P value (the operand at 557DH).
5572
OR A B7
Test it.
5573
If P was given, JUMP to the SYS0 routine at 446AH to print the same text.
5576
RET C9
RETURN.
5577
PUSH AF F5
Save the character.
5578
GOSUB to the ROM routine at 0033H to display it.
557B
POP AF F1
Restore it.
557C
LD DE,0000H 11 00 00
Load DE with the P value (the operand at 557DH is set by the parameter scan: FFFFH if P was given).
557F
INC E 1C
Add 1 to the low byte: 00H only if P was given.
5580
If so, JUMP to the ROM routine at 003BH to print the character as well; it returns to the caller.
5583
RET C9
RETURN.

5584H - Error Exits

5584
LD HL,558DH 21 8D 55
Point HL to PARAMETER ERROR at 558DH.
5587
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
558A
JUMP to 4030H: back to VTOS READY.
558D-559C
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Message displayed at 5587H.
559D
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
559F
JUMP to the SYS0 error handler at 4409H.

55A2H - Write a Number in Decimal

HL = the number, DE = where the five characters go. Leading zeros are written as spaces.

55A2
LD A,20H 3E 20
Load Register A with a space: the character for leading zeros.
55A4
LD BC,2710H 01 10 27
BC = 10000...
55A7
...GOSUB to 55C2H for the ten-thousands digit.
55AA
LD BC,03E8H 01 E8 03
BC = 1000...
55AD
...for the thousands.
55B0
LD BC,0064H 01 64 00
BC = 100...
55B3
...for the hundreds.
55B6
LD BC,000AH 01 0A 00
BC = 10...
55B9
...for the tens.
55BC
LD A,L 7D
What is left is the units:
55BD
ADD A,30H C6 30
as a digit...
55BF
LD (DE),A 12
...store it (always, even if it is 0).
55C0
INC DE 13
Move the pointer on.
55C1
RET C9
RETURN.
55C2
PUSH DE D5
Save the output pointer.
55C3
LD E,A 5F
Register E = the character for a zero digit (a space until a non-zero digit has been written).
55C4
LD D,FFH 16 FF
Register D counts, starting at -1.
55C6
XOR A AF
Clear the Carry flag.
55C7
INC D 14
Count...
55C8
SBC HL,BC ED 42
...subtract BC...
55CA
...and LOOP back to 55C7H while nothing is borrowed.
55CC
ADD HL,BC 09
Add the last BC back.
55CD
LD A,E 7B
Register A = the character for a zero digit.
55CE
LD B,D 42
Register B = the digit.
55CF
POP DE D1
Restore the output pointer.
55D0
LD (DE),A 12
Store the zero character.
55D1
INC B 04
Test the digit:
55D2
DEC B 05
(restore it: Z if 0)
55D3
if it is 0, JUMP to 55DBH.
55D5
LD A,B 78
Otherwise make it...
55D6
ADD A,30H C6 30
...a digit...
55D8
LD (DE),A 12
...and store it.
55D9
LD A,30H 3E 30
From now on zeros are shown as 0.
55DB
INC DE 13
Move the output pointer on.
55DC
RET C9
RETURN with Register A = the character for a zero digit.

55DDH - Divide a 24-Bit Number

HL points to a 24-bit number (high byte first), Register C = the divisor. Returns DE = the quotient (16 bits). A divisor of 0 stands for 256: then DE is simply the two high bytes.

55DD
LD DE,0000H 11 00 00
DE = 0000H.
55E0
LD A,C 79
Is the divisor 0?
55E1
OR A B7
Test it.
55E2
If so, JUMP to 55FFH.
55E4
XOR A AF
Clear the remainder.
55E5
LD B,03H 06 03
Load Register B with 03H: three bytes.
55E7
PUSH BC C5
Save the byte counter.
55E8
PUSH HL E5
Save the pointer.
55E9
LD H,(HL) 66
Register H = the next byte.
55EA
LD B,08H 06 08
Load Register B with 08H: eight bits.
55EC
EX DE,HL EB
Shift the quotient in DE left...
55ED
ADD HL,HL 29
(ADD HL,HL on the swapped pair)
55EE
EX DE,HL EB
(swap back)
55EF
RLC H CB 04
...and the next bit of the dividend...
55F1
RLA 17
...into the remainder.
55F2
CP C B9
Is the remainder at least the divisor?
55F3
If not, JUMP to 55F7H.
55F5
SUB C 91
Subtract the divisor...
55F6
INC DE 13
...and set this bit of the quotient.
55F7
LOOP back to 55ECH for eight bits.
55F9
POP HL E1
Restore the pointer...
55FA
INC HL 23
...and move to the next byte.
55FB
POP BC C1
Restore the byte counter.
55FC
LOOP back to 55E7H for three bytes.
55FE
RET C9
RETURN.
55FF
LD D,(HL) 56
Divisor 256: D = the high byte...
5600
INC HL 23
Next byte.
5601
LD E,(HL) 5E
...E = the middle byte.
5602
RET C9
RETURN.

5603H - Pause and BREAK Check

Returns NZ if BREAK is pressed. SHIFT and @ together pause until another key is pressed (BREAK still stops). Does nothing while a chain (DO) file is running (bit 5 of 430FH).

5603
LD A,(430FH) 3A 0F 43
Fetch the system flags.
5606
AND 20H E6 20
Keep bit 5...
5608
XOR 20H EE 20
...and invert it.
560A
RET Z C8
If a chain file is running, RETURN with Z.
560B
LD A,(3840H) 3A 40 38
Read keyboard row 6.
560E
AND 04H E6 04
Keep bit 2, the BREAK key.
5610
RET NZ C0
If BREAK is pressed, RETURN with NZ.
5611
LD A,(3801H) 3A 01 38
Read keyboard row 0.
5614
AND 01H E6 01
Keep bit 0, the @ key.
5616
RET Z C8
If @ is not pressed, RETURN with Z.
5617
LD A,(3880H) 3A 80 38
Read keyboard row 7.
561A
AND 01H E6 01
Keep bit 0, SHIFT.
561C
RET Z C8
If SHIFT is not pressed, RETURN with Z.
561D
LD A,(3840H) 3A 40 38
Read keyboard row 6 again.
5620
AND 04H E6 04
Keep bit 2, BREAK.
5622
RET NZ C0
If BREAK is pressed, RETURN with NZ.
5623
GOSUB to the ROM routine at 002BH to scan the keyboard: Register A = the key, or 00H.
5626
OR A B7
Test the key.
5627
If no key was pressed, LOOP back to 561DH.
5629
CP 60H FE 60
Is it 60H, SHIFT and @ (the key that caused the pause)?
562B
If so, LOOP back to 561DH to keep waiting.
562D
XOR A AF
Any other key: Z...
562E
RET C9
...RETURN.

562FH - Parameter Table

562F-5636
DEFM "A " : DEFW 53EDH 41 20 20 20 20 20 ED 53
A: show the details; stored in the operand of the LD DE at 53ECH.
5637-563E
DEFM "I " : DEFW 5340H 49 20 20 20 20 20 40 53
I: include invisible files; operand of the LD DE at 533FH.
563F-5646
DEFM "P " : DEFW 557DH 50 20 20 20 20 20 7D 55
P: print as well; operand of the LD DE at 557CH.
5647-564E
DEFM "S " : DEFW 5332H 53 20 20 20 20 20 32 53
S: include system files; operand of the LD DE at 5331H.
564F
DEFB 00H 00
End of the table.

5650H - Text

5650-566F
DEFM "ALL KILLNAME~~~~WRITREADEXECNO " 41 4C 4C 20 4B 49 4C 4C 4E 41 4D 45 7E 7E 7E 7E 57 52 49 54 52 45 41 44 45 58 45 43 4E 4F 20 20
The protection levels 0-7 (ALL, KILL, NAME, level 3 not used, WRIT, READ, EXEC, NO), four characters each.
5670-5690
DEFM 0AH,"FILE DIRECTORY --- DRIVE X ",03H 0A 46 49 4C 45 20 44 49 52 45 43 54 4F 52 59 20 2D 2D 2D 20 44 52 49 56 45 20 58 20 20 20 20 20 03
First heading line. The X at 568AH is replaced with the drive number; 5548H reads it back.
5691-56A5
DEFM "NNNNNNNN -- MM/DD/YY",0DH 4E 4E 4E 4E 4E 4E 4E 4E 20 2D 2D 20 4D 4D 2F 44 44 2F 59 59 0D
Second heading line: the disk name (5691H) and date (569DH) are copied from the GAT.
56A6-56D1
DEFM "PROT / EOF= / SIZ? . K DD-MMM-YY",03H 50 52 4F 54 20 2F 20 45 4F 46 3D 20 20 20 20 20 20 2F 20 53 49 5A 3F 20 20 20 20 20 2E 20 20 4B 20 20 44 44 2D 4D 4D 4D 2D 59 59 03
The details line: protection at 56A6H, records at 56B1H, = or : at 56BCH, K at 56BDH, the fraction at 56C3H and the date at 56C8H.
56D2-56F5
DEFM "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC" 4A 41 4E 46 45 42 4D 41 52 41 50 52 4D 41 59 4A 55 4E 4A 55 4C 41 55 47 53 45 50 4F 43 54 4E 4F 56 44 45 43
Month names for the date.
56F6-5700
DEFM 11 spaces 20 20 20 20 20 20 20 20 20 20 20
The pattern: eight characters of name (56F6H) and three of extension (56FEH). A space matches anything.
5701
DEFB 00H 00
Not used.

ISAM 22H - FREE - Offset 0D43

FREE shows, for every drive that is ready, one line: DRIVE n - diskname mm/dd/yy FILES=fff/ttt, SPACE=fffff/ttttt K. FILES gives the free directory entries and the directory's capacity, SPACE the free and total space in K. FREE (P) also prints the lines. The member loads at 5200H-53D1H (466 bytes).

5200H - FREE Command

HL points to the text after FREE.

5200
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H...
5203
LD (5312H),BC ED 43 12 53
...and clear the P value (the operand of the LD DE at 5311H).
5207
LD DE,5389H 11 89 53
Point DE to the parameter table at 5389H.
520A
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
520D
If a parameter was not recognized (NZ), JUMP to 5319H to display PARAMETER ERROR.
5210
LD C,00H 0E 00
Load Register C with 00H: start at drive 0.
5212
LD A,(5312H) 3A 12 53
Fetch the low byte of the P value.
5215
OR A B7
Test it.
5216
If P was not given, JUMP to 5222H.
5218
LD A,20H 3E 20
Load Register A with a space...
521A
...and GOSUB to the ROM routine at 003BH to print it.
521D
LD A,0DH 3E 0D
Load Register A with a carriage return...
521F
...and print it, so the printed lines start on a new line.

5222H - One Drive

Register C = the drive.

5222
PUSH BC C5
Save the drive number.
5223
GOSUB to 44B8H, which calls SYS2 (request 40H) to select drive C and check that it is ready.
5226
If it is not (NZ), JUMP to 5303H to go on with the next drive.
5229
LD A,C 79
Fetch the drive number...
522A
ADD A,30H C6 30
...as a digit...
522C
LD (5398H),A 32 98 53
...and put it in the line at 5398H.
522F
GOSUB to 5376H to read the GAT into 4200H.
5232
If that failed (NZ, Register A = 14H), JUMP to the error exit at 5332H.
5235
GOSUB to the SYS0 routine at 478FH to point IY to the drive control table of drive C.
5238
LD H,00H 26 00
H = 00H...
523A
LD L,(IY+06H) FD 6E 06
...L = the highest cylinder number (DCT+06H)...
523D
INC HL 23
...plus 1: HL = the number of cylinders.
523E
LD A,(IY+08H) FD 7E 08
Fetch DCT+08H.
5241
AND 1FH E6 1F
Keep bits 0-4: sectors per granule - 1.
5243
INC A 3C
Add 1.
5244
LD E,A 5F
Register E = the sectors per granule.
5245
PUSH AF F5
Save it (used again at 52BAH).
5246
LD A,(IY+08H) FD 7E 08
Fetch DCT+08H again.
5249
AND E0H E6 E0
Keep bits 5-7: granules per cylinder - 1...
524B
RLCA 07
...rotate them...
524C
RLCA 07
(second rotate)
524D
RLCA 07
...down to bits 0-2...
524E
INC A 3C
...and add 1.
524F
GOSUB to the SYS0 routine at 4B6CH to multiply: A = granules x sectors per granule = sectors per cylinder.
5252
BIT 5,(IY+04H) FD CB 04 6E
Test bit 5 of DCT+04H: a two-sided drive.
5256
If it is one-sided, JUMP to 5259H.
5258
ADD A,A 87
Two sides: double the sectors per cylinder.
5259
PUSH AF F5
Save the sectors per cylinder.
525A
PUSH HL E5
Save the number of cylinders.
525B
LD HL,0100H 21 00 01
HL = 0100H: the directory can hold at most 256 entries.
525E
SUB 02H D6 02
The directory cylinder holds the GAT and the HIT and then the directory sectors: sectors - 2.
5260
CP 1EH FE 1E
Are there 30 or more directory sectors?
5262
If so (No Carry), JUMP to 526DH with the limit of 256.
5264
SLA A CB 27
Otherwise multiply by 8 (eight entries per sector)...
5266
SLA A CB 27
(x 4)
5268
SLA A CB 27
(x 8)
526A
LD L,A 6F
...into HL.
526B
LD H,00H 26 00
H = 00H.
526D
LD (52E6H),HL 22 E6 52
Store the capacity at 52E6H (the operand of the LD DE at 52E5H).
5270
LD DE,53B9H 11 B9 53
Point DE to the total after FILES= at 53B9H.
5273
GOSUB to 5337H to write it as three digits.
5276
POP HL E1
Restore the number of cylinders.
5277
POP AF F1
Restore the sectors per cylinder.
5278
GOSUB to the SYS0 routine at 4B8FH to multiply: the total sectors, bits 8-23 in HL and bits 0-7 in A.
527B
LD H,L 65
HL = the total sectors...
527C
LD L,A 6F
(low byte)
527D
INC HL 23
...plus 2 (to round)...
527E
INC HL 23
(+2)
527F
SRL H CB 3C
...divided by 4: the total space in K.
5281
RR L CB 1D
(shift)
5283
SRL H CB 3C
(shift again)
5285
RR L CB 1D
(and rotate)
5287
LD DE,53CAH 11 CA 53
Point DE to the total space at 53CAH.
528A
GOSUB to 533BH to write it as five digits.
528D
LD HL,42D0H 21 D0 42
Point HL to offset D0H of the GAT: the disk name.
5290
LD DE,539CH 11 9C 53
Point DE to the name field at 539CH.
5293
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H.
5296
LDIR ED B0
Copy the name.
5298
LD DE,53A5H 11 A5 53
Point DE to the date field at 53A5H. HL is at GAT+D8H, the date.
529B
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H.
529E
LDIR ED B0
Copy the date.
52A0
LD HL,4200H 21 00 42
Point HL to the start of the GAT: one byte of allocation bits per cylinder.
52A3
LD DE,0000H 11 00 00
DE counts the free granules.
52A6
LD A,(42CCH) 3A CC 42
Fetch GAT+CCH: the number of cylinders beyond 35.
52A9
ADD A,23H C6 23
Add 35 (23H)...
52AB
LD B,A 47
...Register B = the number of cylinders.
52AC
LD A,(HL) 7E
Fetch the allocation byte.
52AD
SCF 37
Set the Carry flag...
52AE
RRA 1F
...and shift a 1 in from the left: the lowest bit comes out into Carry.
52AF
If the bit was 1 (granule in use), JUMP to 52B2H.
52B1
INC DE 13
A 0 bit is a free granule: count it.
52B2
CP FFH FE FF
When the byte has become FFH, every 0 bit has been counted...
52B4
...otherwise LOOP back to 52ADH.
52B6
INC L 2C
Next cylinder.
52B7
LOOP back to 52ACH for every cylinder.
52B9
EX DE,HL EB
HL = the free granules.
52BA
POP AF F1
Restore the sectors per granule.
52BB
GOSUB to 4B8FH to multiply: the free sectors.
52BE
LD H,L 65
HL = the free sectors...
52BF
LD L,A 6F
(low byte)
52C0
INC HL 23
...plus 2...
52C1
INC HL 23
(+2)
52C2
SRL H CB 3C
...divided by 4: the free space in K.
52C4
RR L CB 1D
(shift)
52C6
SRL H CB 3C
(shift again)
52C8
RR L CB 1D
(and rotate)
52CA
LD DE,53C4H 11 C4 53
Point DE to the free space at 53C4H.
52CD
GOSUB to 533BH to write it as five digits.
52D0
POP BC C1
Restore the drive number...
52D1
PUSH BC C5
...and save it again.
52D2
GOSUB to 4B65H to get the directory track in Register D.
52D5
LD E,01H 1E 01
Load Register E with 01H: the hash index table (HIT).
52D7
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
52DA
GOSUB to 4B45H to read it.
52DD
LD A,16H 3E 16
Load Register A with 16H (HIT read error). The LD does not change the flags.
52DF
If the read failed (NZ), JUMP to 5332H.
52E2
LD HL,4200H 21 00 42
Point HL to the start of the HIT.
52E5
LD DE,0000H 11 00 00
Load DE with the capacity of the directory (the operand at 52E6H, stored at 526DH).
52E8
DEC DE 1B
Count every position of the table as used...
52E9
LD A,L 7D
...then test the position:
52EA
AND D8H E6 D8
if bits 3, 4, 6 and 7 are all 0 (positions 00H-07H and 20H-27H, the first two entries of the first eight directory sectors, kept for system files)...
52EC
...it stays counted: JUMP to 52F3H.
52EE
LD A,(HL) 7E
Otherwise fetch the hash byte.
52EF
OR A B7
Test it.
52F0
If the entry is in use, JUMP to 52F3H.
52F2
INC DE 13
A free entry: take it off again. Positions past the end of the directory are always 00H, so they cancel out as well.
52F3
INC L 2C
Next position.
52F4
LOOP back to 52E8H for all 256 positions. DE = the free entries.
52F6
EX DE,HL EB
HL = the free entries.
52F7
LD DE,53B5H 11 B5 53
Point DE to the field after FILES= at 53B5H.
52FA
GOSUB to 5337H to write it as three digits.
52FD
LD HL,5392H 21 92 53
Point HL to the line at 5392H.
5300
GOSUB to 530EH to display it (and print it if P was given).
5303
POP BC C1
Restore the drive number.
5304
INC C 0C
Next drive.
5305
LD A,C 79
Fetch it.
5306
CP 08H FE 08
Is it 8?
5308
If not, JUMP back to 5222H.
530B
JUMP to 402DH: back to VTOS READY.

530EH - Display a Line

Displays the text at HL and, if P was given, prints it.

530E
GOSUB to the SYS0 routine at 4467H to display it.
5311
LD DE,0000H 11 00 00
Load DE with the P value (the operand at 5312H is set by the parameter scan: FFFFH if P was given).
5314
INC E 1C
Add 1 to the low byte: 00H only if P was given.
5315
If so, JUMP to the SYS0 routine at 446AH to print the same text.
5318
RET C9
RETURN.

5319H - Error Exits

5319
LD HL,5322H 21 22 53
Point HL to PARAMETER ERROR at 5322H.
531C
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
531F
JUMP to 4030H: back to VTOS READY.
5322-5331
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Message displayed at 531CH.
5332
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
5334
JUMP to the SYS0 error handler at 4409H.

5337H - Write a Number in Decimal

5337H writes HL as three digits (for numbers up to 999) and 533BH as five digits, at DE. Leading zeros become spaces.

5337
LD A,20H 3E 20
Load Register A with a space: the character for leading zeros.
5339
JUMP to 5349H to start at the hundreds.
533B
LD A,20H 3E 20
Load Register A with a space.
533D
LD BC,2710H 01 10 27
BC = 10000...
5340
...GOSUB to 535BH for the ten-thousands digit.
5343
LD BC,03E8H 01 E8 03
BC = 1000...
5346
...for the thousands.
5349
LD BC,0064H 01 64 00
BC = 100...
534C
...for the hundreds.
534F
LD BC,000AH 01 0A 00
BC = 10...
5352
...for the tens.
5355
LD A,L 7D
What is left is the units:
5356
ADD A,30H C6 30
as a digit...
5358
LD (DE),A 12
...store it (always).
5359
INC DE 13
Move the pointer on.
535A
RET C9
RETURN.
535B
PUSH DE D5
Save the output pointer.
535C
LD E,A 5F
Register E = the character for a zero digit.
535D
LD D,FFH 16 FF
Register D counts, starting at -1.
535F
XOR A AF
Clear the Carry flag.
5360
INC D 14
Count...
5361
SBC HL,BC ED 42
...subtract BC...
5363
...and LOOP back to 5360H while nothing is borrowed.
5365
ADD HL,BC 09
Add the last BC back.
5366
LD A,E 7B
Register A = the character for a zero digit.
5367
LD B,D 42
Register B = the digit.
5368
POP DE D1
Restore the output pointer.
5369
LD (DE),A 12
Store the zero character.
536A
INC B 04
Test the digit:
536B
DEC B 05
(restore it: Z if 0)
536C
if it is 0, JUMP to 5374H.
536E
LD A,B 78
Otherwise make it...
536F
ADD A,30H C6 30
...a digit...
5371
LD (DE),A 12
...and store it.
5372
LD A,30H 3E 30
From now on zeros are shown as 0.
5374
INC DE 13
Move the output pointer on.
5375
RET C9
RETURN.

5376H - Read the GAT

Reads sector 0 of the directory track of drive C into 4200H. Returns Z, or NZ with Register A = 14H (GAT read error). DE and HL are preserved.

5376
PUSH DE D5
Save DE.
5377
PUSH HL E5
Save HL.
5378
GOSUB to 4B65H to get the directory track in Register D.
537B
LD E,00H 1E 00
Load Register E with 00H: the GAT.
537D
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
5380
GOSUB to 4B45H to read it.
5383
POP HL E1
Restore HL.
5384
POP DE D1
Restore DE.
5385
RET Z C8
If the read succeeded (Z), RETURN.
5386
LD A,14H 3E 14
Load Register A with 14H: GAT read error.
5388
RET C9
RETURN with NZ.

5389H - Parameter Table and Display Line

5389-5390
DEFM "P " : DEFW 5312H 50 20 20 20 20 20 12 53
P: print as well; stored in the operand of the LD DE at 5311H.
5391
DEFB 00H 00
End of the table.
5392-5399
DEFM "DRIVE X " 44 52 49 56 45 20 58 20
The drive digit goes to 5398H.
539A-53A4
DEFM "- NNNNNNNN " 2D 20 4E 4E 4E 4E 4E 4E 4E 4E 20
The disk name goes to 539CH.
53A5-53AE
DEFM "MM/DD/YY " 4D 4D 2F 44 44 2F 59 59 20 20
The date goes to 53A5H.
53AF-53BB
DEFM "FILES=XXX/XXX" 46 49 4C 45 53 3D 58 58 58 2F 58 58 58
Free entries at 53B5H, capacity at 53B9H.
53BC-53D1
DEFM ", SPACE= / K",0DH 2C 20 53 50 41 43 45 3D 20 20 20 20 20 2F 20 20 20 20 20 20 4B 0D
Free K at 53C4H, total K at 53CAH.

ISAM 91H - CHAIN - Offset 0F20

CHAIN runs a job control (JCL) file. It first compiles the file into SYSTEM/JCL: symbols given on the command line or set in the file are substituted wherever #name# appears, the directives //IF, //ELSE, //END, //SET, //RESET, //ASSIGN, //INCLUDE and //QUIT are carried out, and lines in a false //IF block are dropped. Then it hands SYSTEM/JCL to SYS7, which feeds its lines to the system as if they were typed. The forms are CHAIN filespec (name, name=value, ...) (default extension JCL; a ; on the line asks for more parameters with ?), CHAIN $ filespec ... (compile only), CHAIN = filespec (run a file that is already compiled) and CHAIN * (run SYSTEM/JCL again). SYS1 also runs CHAIN for a command line that starts with !. The member loads at 5200H-56D1H, 571BH-57B3H, 58F4H-58F6H, 5916H-5919H and 5C00H (1,395 bytes). The areas between are its buffers; the symbol table starts at 5C00H and grows upward.

5200H - CHAIN Command

HL points to the text after CHAIN.

5200
LD A,(HL) 7E
Fetch the first character.
5201
CP 2AH FE 2A
Is it *?
5203
If so, JUMP to 52D7H to run SYSTEM/JCL again.
5206
CP 3DH FE 3D
Is it =?
5208
If so, JUMP to 52BFH to run a compiled file.
520B
CP 24H FE 24
Is it $?
520D
If not, JUMP to 5219H.
520F
LD (52A9H),A 32 A9 52
Store the $ at 52A9H (the operand of the LD A at 52A8H): compile only.
5212
INC HL 23
Move past it.
5213
LD A,(HL) 7E
Fetch the next character.
5214
CP 20H FE 20
Is it a space?
5216
If not, JUMP to 5219H.
5218
INC HL 23
Skip the space.
5219
LD DE,56D2H 11 D2 56
Point DE to the FCB for the source file at 56D2H.
521C
GOSUB to the SYS0 routine at 441CH to copy the filespec into it.
521F
If there is none (NZ), JUMP to 56AEH to display FILE SPEC REQUIRED!.
5222
PUSH HL E5
Save the command line pointer.
5223
LD DE,56D2H 11 D2 56
Point DE to the FCB again.
5226
LD HL,5722H 21 22 57
Point HL to the default extension JCL at 5722H.
5229
GOSUB to the SYS0 routine at 4473H to add it if the filespec has no extension.
522C
LD B,00H 06 00
Load Register B with 00H: record length 256.
522E
LD HL,5A00H 21 00 5A
Point HL to the source buffer at 5A00H.
5231
GOSUB to the SYS0 routine at 4424H to open the source file.
5234
If that failed (NZ), JUMP to the error exit at 56A9H.
5237
LD DE,4358H 11 58 43
Point DE to the system JCL FCB at 4358H.
523A
LD HL,571BH 21 1B 57
Point HL to the filespec SYSTEM/JCL at 571BH.
523D
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H.
5240
LDIR ED B0
Copy it into the FCB (with the 22 bytes that follow it).
5242
LD B,00H 06 00
Load Register B with 00H: record length 256.
5244
LD DE,4358H 11 58 43
Point DE to the FCB at 4358H.
5247
LD HL,5B00H 21 00 5B
Point HL to the output buffer at 5B00H.
524A
GOSUB to the SYS0 routine at 4420H to open SYSTEM/JCL, creating it if necessary.
524D
If that failed (NZ), JUMP to 56B7H to display CANT CREATE SYSTEM/JCL FILE!.
5250
POP HL E1
Restore the command line pointer.

5251H - Read the Rest of the Command Line

Parameters in parentheses define symbols. A ; asks for another line from the keyboard.

5251
LD A,(HL) 7E
Fetch a character.
5252
CP 0DH FE 0D
Is it a carriage return?
5254
If so, JUMP to 5312H to compile the file.
5257
INC HL 23
Move past it.
5258
CP 20H FE 20
Is it a space...
525A
...then skip it.
525C
CP 2CH FE 2C
Is it a comma...
525E
...then skip it.
5260
CP 28H FE 28
Is it (?
5262
If so, JUMP to 52E1H to read the parameters.
5264
CP 3BH FE 3B
Is it ;?
5266
If not, JUMP to 56C0H to display PARAMETER ERROR.
5269
LD A,3FH 3E 3F
Load Register A with ?...
526B
...and GOSUB to the ROM routine at 0033H to display it as a prompt.
526E
LD HL,4318H 21 18 43
Point HL to the command buffer at 4318H.
5271
LD B,3FH 06 3F
Load Register B with 3FH: up to 63 characters.
5273
GOSUB to the ROM routine at 0040H to read a line.
5276
If BREAK was pressed (Carry), JUMP to 56C0H.
5279
GOSUB to the SYS0 routine at 447EH, which copies the line, with the time, to the job log device when that is active.
527C
LOOP back to 5251H to read the new line.

527EH - End of a Source File

Reached when the file being read ends. If it was included by //INCLUDE, the file that included it is taken back from the stack at 57B4H and reading goes on there. Otherwise the compilation is finished.

527E
LD HL,(57B2H) 2A B2 57
Fetch the pointer to the top of the include stack.
5281
LD DE,57B4H 11 B4 57
Point DE to the bottom of the stack at 57B4H.
5284
XOR A AF
Clear the Carry flag.
5285
SBC HL,DE ED 52
Compare.
5287
If the stack is empty, JUMP to 52A2H: all done.
5289
LD HL,(57B2H) 2A B2 57
Fetch the pointer again...
528C
DEC HL 2B
...and point HL to the last byte on the stack.
528D
LD DE,56F1H 11 F1 56
Point DE to the last byte of the source FCB at 56F1H.
5290
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H.
5293
LDDR ED B8
Copy the saved FCB back, working downward.
5295
INC HL 23
HL = the new top of the stack...
5296
LD (57B2H),HL 22 B2 57
...store it.
5299
LD DE,56D2H 11 D2 56
Point DE to the source FCB.
529C
GOSUB to the SYS0 routine at 4454H, which positions the file back one sector so that its sector is read into the buffer at 5A00H again (the included file used the same buffer).
529F
JUMP to 5312H to go on reading it.
52A2
LD DE,4358H 11 58 43
Point DE to the SYSTEM/JCL FCB at 4358H.
52A5
GOSUB to the SYS0 routine at 4428H to close it.
52A8
LD A,00H 3E 00
Load Register A with the $ flag (the operand at 52A9H is 00H unless $ was given).
52AA
OR A B7
Test it.
52AB
If $ was given, JUMP to 402DH: back to VTOS READY without running the file.

52AEH - Run SYSTEM/JCL

Opens the file named in the FCB at 4358H and passes it to SYS7.

52AE
LD DE,4358H 11 58 43
Point DE to the FCB at 4358H.
52B1
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
52B4
LD B,00H 06 00
Load Register B with 00H: record length 256.
52B6
GOSUB to the SYS0 routine at 4424H to open the file.
52B9
If that failed (NZ), JUMP to 56A9H.
52BC
LD A,99H 3E 99
Load Register A with 99H: SYS7, request 10H.
52BE
RST 28H EF
Call the overlay through RST 28H. SYS7 takes the following command lines from the file.
52BF
INC HL 23
=: move past it.
52C0
LD A,(HL) 7E
Fetch the next character.
52C1
CP 20H FE 20
Is it a space?
52C3
If not, JUMP to 52C6H.
52C5
INC HL 23
Skip the space.
52C6
LD DE,4358H 11 58 43
Point DE to the FCB at 4358H.
52C9
GOSUB to 441CH to copy the filespec into it.
52CC
If there is none (NZ), JUMP to 56A9H.
52CF
LD HL,5722H 21 22 57
Point HL to the default extension JCL.
52D2
GOSUB to 4473H to add it if necessary.
52D5
JUMP to 52AEH to run the file.
52D7
LD HL,571BH 21 1B 57
*: point HL to SYSTEM/JCL at 571BH.
52DA
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H.
52DD
LDIR ED B0
Copy 32 bytes to the address in DE. DE is not loaded by this member before the copy; 52AEH then opens the FCB at 4358H.
52DF
JUMP to 52AEH.

52E1H - Read the Parameters

Each parameter is a name, optionally followed by = and a value. A name that is already defined gives MULTIPLY DEFINED PARAMETER!.

52E1
GOSUB to 5577H to read a name into 56F2H. Register A = the character that ended it; Z if the name is not empty.
52E4
If it is empty, JUMP to 52F5H to look at that character.
52E6
PUSH AF F5
Save it.
52E7
GOSUB to 5628H to look the name up in the symbol table.
52EA
If it is already there (Z), JUMP to 56C9H.
52ED
GOSUB to 560BH to add it at the end of the table (DE), with an empty value.
52F0
POP AF F1
Restore the character after the name.
52F1
CP 3DH FE 3D
Is it =?
52F3
If so, JUMP to 5305H to read the value.
52F5
CP 20H FE 20
Is it a space...
52F7
...then read the next parameter.
52F9
CP 2CH FE 2C
Is it a comma...
52FB
...then read the next parameter.
52FD
CP 29H FE 29
Is it )?
52FF
If so, JUMP back to 5251H for the rest of the line.
5302
Otherwise JUMP to 56C0H to display PARAMETER ERROR.
5305
GOSUB to 5582H to read the value into 56FBH (its length goes to 56FAH).
5308
PUSH AF F5
Save the character that ended it.
5309
GOSUB to 561DH to copy the length and value into the new entry.
530C
POP AF F1
Restore the character.
530D
JUMP to 52F5H.

530FH - Compile One Line

530FH writes the line just built; 5312H reads the next line of the source file into 5919H and builds the output line at 5959H, substituting symbols.

530F
GOSUB to 5406H to write the output line to SYSTEM/JCL (unless inside a false //IF block).
5312
GOSUB to 53E8H to read a line of the source file into 5919H.
5315
At the end of the file (NZ), JUMP to 527EH.
5318
LD HL,5919H 21 19 59
Point HL to the source line at 5919H.
531B
LD DE,5959H 11 59 59
Point DE to the output line at 5959H.
531E
LD A,(HL) 7E
Fetch the first character.
531F
INC HL 23
Move past it.
5320
CP 50H FE 50
Is it P?
5322
If so, GOSUB to 5340H: a line beginning PAUSE becomes //PAUSE.
5325
CP 2FH FE 2F
Is it /?
5327
If not, JUMP to 532DH.
5329
CP (HL) BE
Is the next one / as well?
532A
If so, JUMP to 53B8H: a directive.
532D
CP 23H FE 23
Is it #?
532F
If so, JUMP to 533BH for a symbol.
5331
LD (DE),A 12
Otherwise copy the character to the output line.
5332
INC DE 13
Move on.
5333
CP 0DH FE 0D
Is it the carriage return?
5335
If so, the line is complete: JUMP to 530FH.
5337
LD A,(HL) 7E
Fetch the next character.
5338
INC HL 23
Move past it.
5339
LOOP back to 532DH.
533B
GOSUB to 536FH to substitute the symbol.
533E
LOOP back to 5337H.

5340H - PAUSE Line

Called with HL just past a P at the start of the line. If AUSE follows, the whole line is moved up two bytes and // put in front of it; Register A is then /, so the caller treats it as a directive. Otherwise Register A is P again and HL is unchanged.

5340
PUSH HL E5
Save the pointer.
5341
LD A,41H 3E 41
Load Register A with A...
5343
...and GOSUB to 5367H to compare it with the next character.
5346
LD A,55H 3E 55
U...
5348
(compare)
534B
LD A,53H 3E 53
S...
534D
(compare)
5350
LD A,45H 3E 45
E...
5352
(compare)
5355
LD HL,5955H 21 55 59
All four match. Point HL to 5955H...
5358
LD DE,5957H 11 57 59
...and DE to 5957H.
535B
LD BC,003DH 01 3D 00
Load Register Pair BC with 003DH.
535E
LDDR ED B8
Move the line up two bytes (5919H-5955H to 591BH-5957H).
5360
LD A,2FH 3E 2F
Load Register A with /.
5362
LD (DE),A 12
Store it at 591AH...
5363
DEC DE 1B
Point to 5919H.
5364
LD (DE),A 12
...and at 5919H.
5365
POP HL E1
Restore the pointer: HL = 591AH, the second /.
5366
RET C9
RETURN with Register A = /.
5367
CP (HL) BE
Compare Register A with the next character.
5368
INC HL 23
Move past it.
5369
RET Z C8
If it matches, RETURN.
536A
POP HL E1
Otherwise discard this return address...
536B
POP HL E1
...and restore the saved pointer.
536C
LD A,50H 3E 50
Load Register A with P again.
536E
RET C9
RETURN straight to the caller of 5340H.

536FH - Substitute a Symbol

Called with HL just past a #. ## gives a single #. #name# is replaced by the value of the symbol; a symbol that is not defined, or has an empty value, is copied as it stands. A missing closing # is an error.

536F
CP (HL) BE
Is the next character also #?
5370
If not, JUMP to 5376H.
5372
INC HL 23
Move past it.
5373
LD (DE),A 12
Put one # in the output.
5374
INC DE 13
Move on.
5375
RET C9
RETURN.
5376
PUSH HL E5
Save the source pointer.
5377
PUSH DE D5
Save the output pointer.
5378
GOSUB to 5577H to read the name into 56F2H.
537B
CP 23H FE 23
It must end with #...
537D
...or JUMP to 53A9H: invalid format.
537F
EX (SP),HL E3
Swap: the pointer after the name goes onto the stack, HL = the output pointer.
5380
PUSH HL E5
Save the output pointer again.
5381
GOSUB to 5628H to look the name up. DE = its value if it is found.
5384
If it is not defined (NZ), JUMP to 5395H.
5386
LD A,(DE) 1A
Fetch the length of the value.
5387
OR A B7
Test it.
5388
If it is empty, JUMP to 5395H.
538A
LD B,00H 06 00
BC = the length...
538C
LD C,A 4F
(length)
538D
INC DE 13
Point DE to the value text.
538E
POP HL E1
Restore the output pointer.
538F
EX DE,HL EB
Swap: HL = the value, DE = the output.
5390
LDIR ED B0
Copy the value into the output line.
5392
POP HL E1
Restore the source pointer (after the closing #).
5393
POP AF F1
Discard the saved output pointer.
5394
RET C9
RETURN.
5395
POP DE D1
Restore the output pointer.
5396
POP AF F1
Discard the pointer after the name.
5397
POP HL E1
Restore the source pointer (just after the first #).
5398
LD A,23H 3E 23
Load Register A with #.
539A
LD (DE),A 12
Store the character in the output.
539B
INC DE 13
Move on.
539C
LD A,(HL) 7E
Fetch the next character of the name.
539D
INC HL 23
Move past it.
539E
CP 0DH FE 0D
Is it the carriage return?
53A0
If so, JUMP to 53A9H: invalid format.
53A2
CP 23H FE 23
Is it the closing #?
53A4
If not, LOOP back to 539AH.
53A6
LD (DE),A 12
Store the closing #.
53A7
INC DE 13
Move on.
53A8
RET C9
RETURN.

53A9H - Invalid JCL Format

Displays --> followed by the source line (the line buffer at 5919H follows the arrow directly), then INVALID JCL FORMAT, PROCESSING ABORTED!.

53A9
LD HL,5916H 21 16 59
Point HL to the arrow at 5916H.
53AC
GOSUB to the SYS0 routine at 447BH to display it and the line.
53AF
LD HL,578AH 21 8A 57
Point HL to the message at 578AH.
53B2
GOSUB to 447BH to display it.
53B5
JUMP to 4030H: back to VTOS READY.

53B8H - A Directive Line

HL points to the second /. IF, ELSE and END are always carried out; SET, RESET, ASSIGN, INCLUDE and QUIT only outside a false //IF block. Any other // line (for example //PAUSE, or //. comments) is copied to SYSTEM/JCL like an ordinary line.

53B8
INC HL 23
Move past the /.
53B9
GOSUB to 5577H to read the keyword into 56F2H.
53BC
If there is none, JUMP to 53D5H.
53BE
GOSUB to 563AH to look for it among IF, ELSE and END. DE = the handler.
53C1
If it is not one of them, JUMP to 53C5H.
53C3
PUSH DE D5
Push the handler address...
53C4
RET C9
...and RETURN into it.
53C5
LD DE,(58F4H) ED 5B F4 58
Fetch the pointer to the current //IF condition.
53C9
LD A,(DE) 1A
Fetch the condition: 00H = true, FFH = false.
53CA
OR A B7
Test it.
53CB
If the block is false, JUMP to 5312H to skip the line.
53CE
GOSUB to 564DH to look for the keyword among SET, RESET, ASSIGN, INCLUDE and QUIT.
53D1
If it is not one of them, JUMP to 53D5H.
53D3
PUSH DE D5
Push the handler address...
53D4
RET C9
...and RETURN into it.
53D5
LD DE,5919H 11 19 59
DE = 5919H...
53D8
XOR A AF
Clear the Carry flag.
53D9
SBC HL,DE ED 52
...BC = the number of characters read so far...
53DB
LD B,H 44
(high byte)
53DC
LD C,L 4D
(low byte)
53DD
LD HL,5919H 21 19 59
Point HL to the source line...
53E0
LD DE,5959H 11 59 59
...and DE to the output line.
53E3
LDIR ED B0
Copy them unchanged.
53E5
JUMP to 5337H to copy the rest of the line.

53E8H - Read a Source Line

Reads characters from the source file into 5919H up to a carriage return. Returns Z with the line, or NZ with Register A = 1CH at the end of the file. Other errors end the command.

53E8
LD HL,5919H 21 19 59
Point HL to the line buffer at 5919H.
53EB
LD DE,56D2H 11 D2 56
Point DE to the source FCB at 56D2H.
53EE
GOSUB to the ROM routine at 0013H to read a byte from the file.
53F1
If there was an error (NZ), JUMP to 53FDH.
53F3
OR A B7
Test the byte.
53F4
A 00H byte also ends the file: JUMP to 5402H.
53F6
LD (HL),A 77
Store the character.
53F7
INC HL 23
Move on.
53F8
CP 0DH FE 0D
Is it the carriage return?
53FA
If not, LOOP back to 53EEH.
53FC
RET C9
RETURN with Z.
53FD
CP 1CH FE 1C
Is the error 1CH (end of file)?
53FF
If not, JUMP to the error exit at 56A9H.
5402
LD A,1CH 3E 1C
Load Register A with 1CH.
5404
OR A B7
Set NZ.
5405
RET C9
RETURN.

5406H - Write the Output Line

Writes the line at 5959H to SYSTEM/JCL, unless the current //IF condition is false. A line that starts with //. is only displayed now, not written.

5406
LD HL,(58F4H) 2A F4 58
Fetch the pointer to the current condition.
5409
LD A,(HL) 7E
Fetch the condition.
540A
OR A B7
Test it.
540B
RET NZ C0
If the block is false, RETURN.
540C
LD HL,5959H 21 59 59
Point HL to the output line.
540F
LD DE,4358H 11 58 43
Point DE to the SYSTEM/JCL FCB at 4358H.
5412
LD A,(HL) 7E
Fetch the first character.
5413
CP 2FH FE 2F
Is it /?
5415
If not, JUMP to 5427H.
5417
INC HL 23
Look at the second character...
5418
CP (HL) BE
Is the second one / too?
5419
DEC HL 2B
...and point back to the first.
541A
If not, JUMP to 5427H.
541C
LD A,(595BH) 3A 5B 59
Fetch the third character (595BH).
541F
CP 2EH FE 2E
Is it .?
5421
If not, JUMP to 5427H.
5423
GOSUB to the SYS0 routine at 4467H to display the comment.
5426
RET C9
RETURN.
5427
LD A,(HL) 7E
Fetch a character.
5428
GOSUB to the ROM routine at 001BH to write it to the file.
542B
If that failed (NZ), JUMP to 56A9H.
542E
LD A,(HL) 7E
Fetch it again.
542F
INC HL 23
Move on.
5430
CP 0DH FE 0D
Is it the carriage return?
5432
If not, LOOP back to 5427H.
5434
RET C9
RETURN.

5435H - Directive Tables

Names padded with spaces, each followed by the address of its handler; each table ends with 00H.

5435-543C
DEFM "IF " : DEFW 5481H 49 46 20 20 20 20 81 54
//IF.
543D-5444
DEFM "ELSE " : DEFW 54A2H 45 4C 53 45 20 20 A2 54
//ELSE.
5445-544C
DEFM "END " : DEFW 54BAH 45 4E 44 20 20 20 BA 54
//END.
544D
DEFB 00H 00
End of the first table.
544E-5457
DEFM "SET " : DEFW 54F6H 53 45 54 20 20 20 20 20 F6 54
//SET.
5458-5461
DEFM "RESET " : DEFW 5505H 52 45 53 45 54 20 20 20 05 55
//RESET.
5462-546B
DEFM "ASSIGN " : DEFW 551AH 41 53 53 49 47 4E 20 20 1A 55
//ASSIGN.
546C-5475
DEFM "INCLUDE " : DEFW 5539H 49 4E 43 4C 55 44 45 20 39 55
//INCLUDE.
5476-547F
DEFM "QUIT " : DEFW 5568H 51 55 49 54 20 20 20 20 68 55
//QUIT.
5480
DEFB 00H 00
End of the second table.

5481H - //IF

//IF a.b,c: terms joined by . must all be true; alternatives are separated by commas. A term is a symbol name, true if it is defined. Pushes the result on the condition stack at 58F6H; inside a false block the result is always false.

5481
GOSUB to 54D0H to evaluate one alternative.
5484
If it is true (Z), JUMP to 5491H.
5486
CP 0DH FE 0D
Did it end the line?
5488
If so, JUMP to 5494H: false.
548A
CP 2CH FE 2C
Is a comma next?
548C
If so, LOOP back to 5481H to try the next alternative.
548E
Otherwise JUMP to 53A9H: invalid format.
5491
XOR A AF
Register A = 00H: true.
5492
JUMP to 5496H.
5494
LD A,FFH 3E FF
Register A = FFH: false.
5496
LD HL,(58F4H) 2A F4 58
Fetch the pointer to the current condition.
5499
OR (HL) B6
Combine with it: false if the enclosing block is false.
549A
INC HL 23
Move up the stack.
549B
LD (HL),A 77
Store the new condition.
549C
LD (58F4H),HL 22 F4 58
Store the pointer.
549F
JUMP to 5312H for the next line.

54A2H - //ELSE

Inverts the current condition (it stays false if the enclosing block is false).

54A2
LD HL,(58F4H) 2A F4 58
Fetch the pointer to the current condition.
54A5
LD DE,58F6H 11 F6 58
Point DE to the bottom of the stack at 58F6H.
54A8
XOR A AF
Clear the Carry flag.
54A9
SBC HL,DE ED 52
Compare.
54AB
If there is no //IF, JUMP to 53A9H: invalid format.
54AE
LD HL,(58F4H) 2A F4 58
Fetch the pointer again.
54B1
LD A,(HL) 7E
Fetch the condition.
54B2
CPL 2F
Invert it.
54B3
DEC HL 2B
Point to the enclosing condition.
54B4
OR (HL) B6
Combine with it.
54B5
INC HL 23
Back to the current condition.
54B6
LD (HL),A 77
Store the new condition.
54B7
JUMP to 5312H for the next line.

54BAH - //END

Drops the current condition.

54BA
LD HL,(58F4H) 2A F4 58
Fetch the pointer to the current condition.
54BD
LD DE,58F6H 11 F6 58
Point DE to the bottom of the stack.
54C0
XOR A AF
Clear the Carry flag.
54C1
SBC HL,DE ED 52
Compare.
54C3
If there is no //IF, JUMP to 53A9H.
54C6
LD HL,(58F4H) 2A F4 58
Fetch the pointer again.
54C9
DEC HL 2B
Move down the stack.
54CA
LD (58F4H),HL 22 F4 58
Store it.
54CD
JUMP to 5312H for the next line.

54D0H - Evaluate One Alternative

Evaluates terms joined by .. Returns Z if they are all true; NZ, with Register A = the character after the false term, as soon as one is false.

54D0
GOSUB to 54DAH to evaluate a term.
54D3
RET NZ C0
If it is false (NZ), RETURN.
54D4
CP 2EH FE 2E
Is a . next?
54D6
If so, LOOP back to 54D0H.
54D8
XOR A AF
All true: Z.
54D9
RET C9
RETURN.
54DA
LD A,(HL) 7E
Fetch the first character of the term.
54DB
CP 2DH FE 2D
Is it - (not)?
54DD
If not, JUMP to 54E9H to test the name.
54DF
GOSUB to 54E9H. HL still points to the -, which ends the name at once, so the name is not read and this returns NZ.
54E2
If NZ, JUMP to 54E7H: the term counts as true. (If the name had been read, a defined name would give NZ here and an undefined one Z, the reverse of the test.)
54E4
OR 01H F6 01
Defined: set NZ (false).
54E6
RET C9
RETURN.
54E7
XOR A AF
Z: true.
54E8
RET C9
RETURN.
54E9
GOSUB to 5577H to read the name into 56F2H.
54EC
RET NZ C0
If it is empty, RETURN with NZ.
54ED
PUSH AF F5
Save the character after it.
54EE
PUSH HL E5
Save the pointer.
54EF
GOSUB to 5628H to look the name up: Z if it is defined.
54F2
POP HL E1
Restore the pointer.
54F3
POP BC C1
Restore the character after the name...
54F4
LD A,B 78
...into Register A (the flags are kept).
54F5
RET C9
RETURN: Z = defined.

54F6H - //SET, //RESET, //ASSIGN

//SET name defines a symbol with an empty value. //RESET name removes one (its first character is made a space, so it can no longer be found). //ASSIGN name=value defines it, or changes its value.

54F6
GOSUB to 5577H to read the name.
54F9
If there is none, JUMP to 53A9H.
54FC
GOSUB to 5628H to look it up.
54FF
If it is not defined (NZ), GOSUB to 560BH to add it.
5502
JUMP to 5312H for the next line.
5505
//RESET: GOSUB to 5577H to read the name.
5508
If there is none, JUMP to 53A9H.
550B
GOSUB to 5628H to look it up.
550E
If it is not defined, JUMP to 5312H: nothing to do.
5511
LD HL,FFF8H 21 F8 FF
DE points to its value; HL = DE - 8...
5514
ADD HL,DE 19
...the start of its entry.
5515
LD (HL),20H 36 20
Make the first character of the name a space.
551A
//ASSIGN: GOSUB to 5577H to read the name.
551D
If there is none, JUMP to 53A9H.
5520
PUSH AF F5
Save the character after it.
5521
GOSUB to 5628H to look it up.
5524
If it is not defined, GOSUB to 560BH to add it.
5527
POP AF F1
Restore the character after the name.
5528
CP 3DH FE 3D
It must be =...
552A
...or JUMP to 53A9H.
552D
GOSUB to 5582H to read the value.
5530
If that failed, JUMP to 53A9H.
5533
GOSUB to 561DH to store it in the entry.

5539H - //INCLUDE and //QUIT

//INCLUDE filespec saves the FCB of the current source file on the stack at 57B4H and opens the named file (default extension JCL) in its place. //QUIT displays its line and stops: SYSTEM/JCL is closed and nothing is run.

5539
PUSH HL E5
Save the line pointer.
553A
LD DE,(57B2H) ED 5B B2 57
Fetch the pointer to the top of the include stack.
553E
LD HL,56D2H 21 D2 56
Point HL to the source FCB.
5541
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H.
5544
LDIR ED B0
Copy the FCB onto the stack.
5546
LD (57B2H),DE ED 53 B2 57
Store the new top of the stack. There is no check for overflow.
554A
POP HL E1
Restore the line pointer.
554B
LD DE,56D2H 11 D2 56
Point DE to the source FCB.
554E
GOSUB to 441CH to copy the new filespec into it.
5551
If there is none, JUMP to 53A9H.
5554
LD HL,5722H 21 22 57
Point HL to the default extension JCL.
5557
GOSUB to 4473H to add it if necessary.
555A
LD HL,5A00H 21 00 5A
Point HL to the source buffer at 5A00H.
555D
LD B,00H 06 00
Load Register B with 00H: record length 256.
555F
GOSUB to 4424H to open the file.
5562
If that failed, JUMP to 53A9H.
5565
JUMP to 5312H to read from it.
5568
LD HL,5919H 21 19 59
//QUIT: point HL to the line.
556B
GOSUB to 447BH to display it.
556E
LD DE,4358H 11 58 43
Point DE to the SYSTEM/JCL FCB.
5571
GOSUB to 4428H to close it.
5574
JUMP to 402DH: back to VTOS READY.

5577H - Read a Name or a Value

5577H reads a name of up to eight characters into 56F2H, padded with spaces. 5582H reads a value of up to 32 characters into 56FBH (substituting #symbols#) and stores its length at 56FAH. Both return Register A = the character that ended the text and Z if it was not empty.

5577
PUSH DE D5
Save DE.
5578
LD B,08H 06 08
Load Register B with 08H.
557A
LD DE,56F2H 11 F2 56
Point DE to the name buffer at 56F2H.
557D
GOSUB to 55C0H to read it.
5580
POP DE D1
Restore DE.
5581
RET C9
RETURN.
5582
PUSH DE D5
Save DE.
5583
LD B,20H 06 20
Load Register B with 20H: 32 characters.
5585
LD DE,56FBH 11 FB 56
Point DE to the value buffer at 56FBH.
5588
GOSUB to 55A1H to read it.
558B
PUSH AF F5
Save the result.
558C
PUSH HL E5
Save the line pointer.
558D
EX DE,HL EB
HL = where the value ends.
558E
LD DE,56FBH 11 FB 56
Point DE to its start.
5591
XOR A AF
Clear the Carry flag.
5592
SBC HL,DE ED 52
Subtract: the length.
5594
LD A,L 7D
Register A = the length.
5595
CP 21H FE 21
Is it more than 32?
5597
If so, JUMP to the error exit at 56A9H (with the length in Register A).
559A
LD (56FAH),A 32 FA 56
Store the length at 56FAH.
559D
POP HL E1
Restore the line pointer.
559E
POP AF F1
Restore the result.
559F
POP DE D1
Restore DE.
55A0
RET C9
RETURN.
55A1
GOSUB to 55C0H to read letters and digits.
55A4
CP 20H FE 20
A space...
55A6
RET Z C8
...ends the value.
55A7
CP 2CH FE 2C
A comma...
55A9
RET Z C8
...ends it.
55AA
CP 0DH FE 0D
A carriage return...
55AC
RET Z C8
...ends it.
55AD
CP 3DH FE 3D
=...
55AF
RET Z C8
...ends it.
55B0
CP 28H FE 28
(...
55B2
RET Z C8
...ends it.
55B3
CP 29H FE 29
)...
55B5
RET Z C8
...ends it.
55B6
CP 23H FE 23
Is it #?
55B8
If not, LOOP back to 55A1H: the character is dropped and reading goes on.
55BA
GOSUB to 536FH to put the symbol's value into the buffer.
55BD
LD A,(HL) 7E
Fetch the next character.
55BE
JUMP to 55A4H to test it.

55C0H - Read Letters and Digits

Copies letters and digits from (HL) to (DE), lower case changed to capitals, up to B characters (extra ones are dropped), and pads the rest of the field with spaces. Stops at any other character, which is skipped unless it is 03H, a carriage return or (. Returns Register A = that character, Z if something was copied.

55C0
LD A,B 78
Put a non-zero value...
55C1
LD (5607H),A 32 07 56
...in the operand at 5607H: nothing copied yet.
55C4
INC B 04
B = the field length + 1.
55C5
LD A,(HL) 7E
Fetch a character.
55C6
CP 03H FE 03
03H...
55C8
...ends it (not skipped).
55CA
CP 0DH FE 0D
A carriage return...
55CC
...ends it.
55CE
CP 28H FE 28
(...
55D0
...ends it.
55D2
INC HL 23
Move past the character.
55D3
CP 30H FE 30
Below 0?
55D5
Then it ends the text.
55D7
CP 3AH FE 3A
A digit?
55D9
Then take it.
55DB
CP 41H FE 41
Below A?
55DD
Then it ends the text.
55DF
CP 5BH FE 5B
A capital letter?
55E1
Then take it.
55E3
CP 61H FE 61
Below a?
55E5
Then it ends the text.
55E7
CP 7BH FE 7B
Above z?
55E9
Then it ends the text.
55EB
SUB 20H D6 20
Change the lower case letter to a capital.
55ED
DEC B 05
Count it.
55EE
If the field is full, JUMP to 55F8H to drop it.
55F0
LD (DE),A 12
Store it.
55F1
XOR A AF
Clear the operand at 5607H: something has been copied.
55F2
LD (5607H),A 32 07 56
(store it)
55F5
INC DE 13
Move on.
55F6
LOOP back to 55C5H.
55F8
INC B 04
Undo the count.
55F9
LOOP back to 55C5H.
55FB
LD C,A 4F
Keep the character that ended the text.
55FC
PUSH DE D5
Save the store pointer.
55FD
JUMP to 5603H.
55FF
LD A,20H 3E 20
Load Register A with a space...
5601
LD (DE),A 12
...and store it.
5602
INC DE 13
Move on.
5603
LOOP back to 55FFH to fill the rest of the field.
5605
POP DE D1
Restore the store pointer (just after the text).
5606
LD A,00H 3E 00
Load Register A with the flag (the operand at 5607H).
5608
OR A B7
Z if something was copied.
5609
LD A,C 79
Register A = the character that ended the text.
560A
RET C9
RETURN.

560BH - Symbol Table Routines

The table at 5C00H holds 41-byte entries: 8 characters of name, a length byte and 32 characters of value. It ends with a 00H byte.

560B
PUSH HL E5
Save HL. (DE = the end of the table, from 5628H.)
560C
LD HL,56F2H 21 F2 56
Point HL to the name at 56F2H.
560F
LD BC,0008H 01 08 00
Load Register Pair BC with 0008H.
5612
LDIR ED B0
Copy the name into the new entry.
5614
XOR A AF
Register A = 00H.
5615
LD (DE),A 12
Store it as the length: an empty value.
5616
LD HL,0021H 21 21 00
HL = DE + 21H...
5619
ADD HL,DE 19
(add DE)
561A
LD (HL),A 77
...the byte after the entry: a new end marker.
561B
POP HL E1
Restore HL.
561C
RET C9
RETURN.
561D
PUSH HL E5
Save HL. (DE = the length byte of the entry.)
561E
LD HL,56FAH 21 FA 56
Point HL to the length at 56FAH.
5621
LD BC,0021H 01 21 00
Load Register Pair BC with 0021H.
5624
LDIR ED B0
Copy the length and the 32 characters of value.
5626
POP HL E1
Restore HL.
5627
RET C9
RETURN.
5628
PUSH HL E5
Look up the name at 56F2H in the symbol table. Save HL.
5629
LD DE,56F2H 11 F2 56
Point DE to the name.
562C
LD HL,5C00H 21 00 5C
Point HL to the table at 5C00H.
562F
LD B,08H 06 08
Load Register B with 08H: the name length.
5631
LD C,29H 0E 29
Load Register C with 29H: the entry length.
5633
GOSUB to 5660H to search.
5636
LD D,H 54
DE = the length byte of the entry found, or the end of the table.
5637
LD E,L 5D
(low byte)
5638
POP HL E1
Restore HL.
5639
RET C9
RETURN: Z if found.
563A
PUSH HL E5
Look up the keyword at 56F2H among IF, ELSE and END. Save HL.
563B
LD DE,56F2H 11 F2 56
Point DE to the keyword.
563E
LD HL,5435H 21 35 54
Point HL to the table at 5435H.
5641
LD B,06H 06 06
Load Register B with 06H.
5643
LD C,08H 0E 08
Load Register C with 08H.
5645
GOSUB to 5660H to search.
5648
LD E,(HL) 5E
DE = the handler address...
5649
INC HL 23
(next byte)
564A
LD D,(HL) 56
(high byte)
564B
POP HL E1
Restore HL.
564C
RET C9
RETURN: Z if found.
564D
PUSH HL E5
Look up the keyword among SET, RESET, ASSIGN, INCLUDE and QUIT. Save HL.
564E
LD DE,56F2H 11 F2 56
Point DE to the keyword.
5651
LD HL,544EH 21 4E 54
Point HL to the table at 544EH.
5654
LD B,08H 06 08
Load Register B with 08H.
5656
LD C,0AH 0E 0A
Load Register C with 0AH.
5658
GOSUB to 5660H to search.
565B
LD E,(HL) 5E
DE = the handler address...
565C
INC HL 23
(next byte)
565D
LD D,(HL) 56
(high byte)
565E
POP HL E1
Restore HL.
565F
RET C9
RETURN: Z if found.

5660H - Search a Table

HL = the table, DE = the name (ended by a space or carriage return), B = the length of the names in the table, C = the length of an entry. Returns Z with HL just after the matching name, or NZ with HL at the 00H that ends the table.

5660
LD A,(HL) 7E
Fetch the first byte of the entry.
5661
OR A B7
Test it.
5662
If it is not the end, JUMP to 5666H.
5664
INC A 3C
Make NZ.
5665
RET C9
RETURN: not found.
5666
LD A,(DE) 1A
Fetch the first character of the name.
5667
CP (HL) BE
Compare it with the entry.
5668
If they match, JUMP to 5671H.
566A
PUSH BC C5
Save BC.
566B
LD B,00H 06 00
BC = the entry length...
566D
ADD HL,BC 09
...add it to HL: the next entry.
566E
POP BC C1
Restore BC.
566F
LOOP back to 5660H.
5671
PUSH HL E5
Save the entry pointer.
5672
PUSH DE D5
Save the name pointer.
5673
PUSH BC C5
Save the lengths.
5674
INC DE 13
Next character of the name...
5675
INC HL 23
...and of the entry.
5676
LD A,(DE) 1A
Fetch the name character.
5677
CP 20H FE 20
A space...
5679
...ends the name: JUMP to 569FH.
567B
CP 0DH FE 0D
A carriage return...
567D
...ends it too.
567F
CP (HL) BE
Compare with the entry.
5680
If they differ, JUMP to 568FH.
5682
LOOP back to 5674H for the length of the names.
5684
POP BC C1
Match. Restore the lengths.
5685
POP DE D1
Restore the name pointer.
5686
POP HL E1
Restore the entry pointer.
5687
PUSH BC C5
Save the lengths.
5688
LD C,B 48
BC = the name length...
5689
LD B,00H 06 00
(B = 00H)
568B
ADD HL,BC 09
...HL = just after the name.
568C
POP BC C1
Restore the lengths.
568D
XOR A AF
Z: found.
568E
RET C9
RETURN.
568F
CP 30H FE 30
They differ. If the name character is below 0...
5691
...the name has ended: JUMP to 569FH.
5693
CP 3AH FE 3A
A digit...
5695
...means a different name: JUMP to 56A4H.
5697
CP 41H FE 41
Below A...
5699
...the name has ended.
569B
CP 5BH FE 5B
A letter...
569D
...means a different name.
569F
LD A,(HL) 7E
The name has ended: the rest of the entry's name must be a space.
56A0
CP 20H FE 20
Is it a space?
56A2
If it is, JUMP to 5684H: found.
56A4
POP BC C1
Not this entry: restore the lengths...
56A5
POP DE D1
...the name pointer...
56A6
POP HL E1
...and the entry pointer.
56A7
JUMP to 566AH for the next entry.

56A9H - Error Exits

56A9
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
56AB
JUMP to the SYS0 error handler at 4409H.
56AE
LD HL,5726H 21 26 57
Point HL to FILE SPEC REQUIRED! at 5726H.
56B1
GOSUB to the SYS0 routine at 447BH to display it.
56B4
JUMP to 4030H: back to VTOS READY.
56B7
LD HL,573AH 21 3A 57
Point HL to CANT CREATE SYSTEM/JCL FILE! at 573AH.
56BA
GOSUB to 447BH to display it.
56BD
JUMP to 4030H.
56C0
LD HL,575EH 21 5E 57
Point HL to PARAMETER ERROR at 575EH.
56C3
GOSUB to 447BH to display it.
56C6
JUMP to 4030H.
56C9
LD HL,576EH 21 6E 57
Point HL to MULTIPLY DEFINED PARAMETER! at 576EH.
56CC
GOSUB to 447BH to display it.
56CF
JUMP to 4030H.
56D2-56F1
DEFS 32
FCB of the source file (the JCL file, or an included one).
56F2-56F9
DEFS 8
Name or keyword just read, padded with spaces.
56FA
DEFS 1
Length of the value just read.
56FB-571A
DEFS 32
Value just read.

571BH - Text

571B-5725
DEFM "SYSTEM/JCL",03H 53 59 53 54 45 4D 2F 4A 43 4C 03
Filespec of the compiled file. JCL at 5722H is also the default extension.
5726-5739
DEFM "FILE SPEC REQUIRED!",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 21 0D
Displayed at 56B1H.
573A-575D
DEFM "CANT CREATE SYSTEM",01H x 7,"/JCL FILE!",0DH 43 41 4E 54 20 43 52 45 41 54 45 20 53 59 53 54 45 4D 01 01 01 01 01 01 01 2F 4A 43 4C 20 46 49 4C 45 21 0D
Displayed at 56BAH. The seven 01H bytes are not printable characters.
575E-576D
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 56C3H.
576E-5789
DEFM "MULTIPLY DEFINED PARAMETER!",0DH 4D 55 4C 54 49 50 4C 59 20 44 45 46 49 4E 45 44 20 50 41 52 41 4D 45 54 45 52 21 0D
Displayed at 56CCH.
578A-57B1
DEFM "INVALID JCL FORMAT, PROCESSING ABORTED!",0DH 49 4E 56 41 4C 49 44 20 4A 43 4C 20 46 4F 52 4D 41 54 2C 20 50 52 4F 43 45 53 53 49 4E 47 20 41 42 4F 52 54 45 44 21 0D
Displayed at 53B2H.
57B2-57B3
DEFW 57B4H B4 57
Pointer to the top of the include stack.
57B4-58F3
DEFS 320
Include stack: the saved FCBs of the files that contain //INCLUDE lines, 32 bytes each (room for ten).
58F4-58F5
DEFW 58F6H F6 58
Pointer to the current //IF condition.
58F6
DEFB 00H 00
Bottom of the condition stack: outside any //IF the condition is true (00H).
58F7-5915
DEFS 31
The rest of the condition stack.
5916-5918
DEFM "-->" 2D 2D 3E
Displayed in front of a bad line at 53ACH.
5919
DEFB 00H 00
First byte of the source line buffer (5919H-5958H); the output line is built at 5959H.
591A-5BFF
DEFS 742
The rest of the source line buffer, the output line from 5959H, the source file buffer at 5A00H and the SYSTEM/JCL buffer at 5B00H.
5C00
DEFB 00H 00
The symbol table, empty to begin with. It grows upward from here.

ISAM A1H - SYSTEM - Offset 14B9

SYSTEM (SYSTEM (option, option, ...)) changes system settings. The options are handled in this order: FAST and SLOW (CPU speed through port FEH), BASIC2 (leave the DOS for Level II BASIC), BREAK (BREAK key on or off; this ends the command), BLINK, SMALL and LARGE (blinking cursor), TYPE (type-ahead), LOWER (a display driver that goes straight to the ROM display routines, presumably for lower-case display), JKL with GRAPHIC (print the screen when J, K and L are pressed together), ALIVE (a changing character in the top right corner), DRIVE=n with ENABLE, DISABLE, STEP=n and DELAY, and SYSGEN (runs ISAM 1CH). BLINK, TYPE, LOWER, JKL and ALIVE copy a routine into memory below the top of memory, lower the top of memory (4049H) accordingly, and install it as a timer task or driver. TYPE, LOWER and JKL are refused while a program has taken over the DOS exit at 402DH. The member loads at 5200H-52C4H, 52CCH-53D6H, 53D9H-5523H and 5526H-5709H (1,279 bytes); 52C5H-52CBH, 53D7H-53D8H and 5524H-5525H belong to the routines that are copied and are filled in at run time.

5200H - SYSTEM Command: FAST and SLOW

HL points to the text after SYSTEM. The parameter scan stores each option's value straight into the operand of the LD BC (or LD HL) that tests it. Options that were not given keep the value in the file: 0000H, 0001H or FFFFH.

5200
LD DE,5679H 11 79 56
Point DE to the parameter table at 5679H.
5203
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
5206
If a parameter was not recognized (NZ), JUMP to 5660H to display PARAMETER ERROR.
5209
LD BC,0000H 01 00 00
Load BC with the SLOW value (0000H unless SLOW was given).
520C
LD A,B 78
Test it...
520D
OR C B1
(OR the low byte)
520E
...and if SLOW was given, JUMP to 5224H.
5210
LD BC,0000H 01 00 00
Load BC with the FAST value (0000H unless FAST was given).
5213
LD A,B 78
Test it...
5214
OR C B1
(OR the low byte)
5215
...and if it was not given, JUMP to 522EH.
5217
LD HL,430FH 21 0F 43
Point HL to the system flags at 430FH.
521A
DI F3
Disable interrupts.
521B
SET 3,(HL) CB DE
Set bit 3: fast.
521D
LD A,01H 3E 01
Load Register A with 01H.
521F
EI FB
Enable interrupts.
5220
OUT (FEH),A D3 FE
Send 01H to port FEH to switch a speed-up board to the fast clock.
5222
JUMP to 522EH.
5224
LD HL,430FH 21 0F 43
SLOW: point HL to 430FH.
5227
DI F3
Disable interrupts.
5228
RES 3,(HL) CB 9E
Clear bit 3.
522A
XOR A AF
Register A = 00H.
522B
EI FB
Enable interrupts.
522C
OUT (FEH),A D3 FE
Send 00H to port FEH: normal speed.

522EH - BASIC2

Leaves the DOS for the Level II BASIC in ROM, as if the computer had been started without disks: the ROM's initial values are copied to 4000H-4035H, 4036H-405CH is cleared and the ROM start-up at 0075H is entered (it asks MEMORY SIZE?).

522E
LD BC,0000H 01 00 00
Load BC with the BASIC2 value.
5231
LD A,B 78
Test it...
5232
OR C B1
(OR the low byte)
5233
...and if it was not given, JUMP to 524BH.
5235
LD HL,06D2H 21 D2 06
Point HL to the table of initial values in the ROM at 06D2H.
5238
LD DE,4000H 11 00 40
Point DE to 4000H.
523B
LD BC,0036H 01 36 00
Load Register Pair BC with 0036H.
523E
LDIR ED B0
Copy the 54 bytes to 4000H-4035H.
5240
XOR A AF
Register A = 00H.
5241
LD B,27H 06 27
Load Register B with 27H: 39 bytes.
5243
LD (DE),A 12
Clear a byte...
5244
INC DE 13
...move on...
5245
...and LOOP back to 5243H: 4036H-405CH is cleared.
5247
DI F3
Disable interrupts.
5248
JUMP to the ROM at 0075H.

524BH - BREAK

BREAK=NO puts C8H (RET Z) at 4C2DH in SYS0 and sets bit 4 of 430FH; BREAK alone puts back 00H (NOP) and clears bit 4. Either way the command ends here, so options that come after BREAK in the list above are not looked at.

524B
LD BC,0001H 01 01 00
Load BC with the BREAK value (0001H if BREAK was not given).
524E
LD A,B 78
Test it...
524F
OR C B1
(OR the low byte)
5250
...and if it is 0000H (BREAK=NO), JUMP to 5262H.
5252
INC A 3C
Add 1 to the combined byte: 00H only if the value was FFFFH (BREAK alone).
5253
If BREAK was not given, JUMP to 526FH.
5255
LD A,00H 3E 00
Load Register A with 00H (NOP).
5257
LD HL,430FH 21 0F 43
Point HL to 430FH.
525A
DI F3
Disable interrupts.
525B
LD (4C2DH),A 32 2D 4C
Store it at 4C2DH.
525E
EI FB
Enable interrupts.
525F
RES 4,(HL) CB A6
Clear bit 4 of 430FH.
5261
RET C9
RETURN: SYS1 left 402DH on the stack, so this goes back to VTOS READY.
5262
LD A,C8H 3E C8
Load Register A with C8H (RET Z).
5264
LD HL,430FH 21 0F 43
Point HL to 430FH.
5267
DI F3
Disable interrupts.
5268
LD (4C2DH),A 32 2D 4C
Store it at 4C2DH.
526B
EI FB
Enable interrupts.
526C
SET 4,(HL) CB E6
Set bit 4 of 430FH.
526E
RET C9
RETURN to VTOS READY.

526FH - BLINK

BLINK installs the blinking cursor routine at 52C7H as timer task 5; BLINK=NO removes the task. The cursor character is 8FH (a full block), 88H with SMALL, or the value given with BLINK=n. LARGE is accepted, but its value goes to 52C5H, which nothing reads.

526F
LD BC,0001H 01 01 00
Load BC with the BLINK value (0001H if BLINK was not given).
5272
LD A,B 78
Combine the two bytes.
5273
OR C B1
(OR the low byte)
5274
DEC A 3D
Subtract 1...
5275
...and if BLINK was not given, JUMP to 5305H.
5278
INC A 3C
Add the 1 back.
5279
If a value other than NO was given, JUMP to 5283H.
527B
LD A,05H 3E 05
BLINK=NO: Register A = 05H, task slot 5.
527D
GOSUB to the SYS0 routine at 4413H to remove the task.
5283-5285
NOP x 3 00 x 3
Spare bytes.
5286
CP FFH FE FF
Is the combined value FFH (BLINK alone)?
5288
If not, JUMP to 5295H: Register A is the character given.
528A
LD BC,0000H 01 00 00
Load BC with the SMALL value.
528D
LD A,B 78
Test it...
528E
OR C B1
(OR the low byte)
528F
LD A,8FH 3E 8F
Load Register A with 8FH (the LD does not change the flags).
5291
If SMALL was not given, JUMP to 5295H.
5293
LD A,88H 3E 88
Load Register A with 88H.
5295
LD (52E6H),A 32 E6 52
Store the cursor character in the routine at 52E6H...
5298
LD (52F3H),A 32 F3 52
...at 52F3H...
529B
LD (52FCH),A 32 FC 52
...and at 52FCH.
529E
LD BC,003EH 01 3E 00
Load Register Pair BC with 003EH: 62 bytes.
52A1
LD HL,(4049H) 2A 49 40
Fetch the top of memory.
52A4
XOR A AF
Clear the Carry flag.
52A5
SBC HL,BC ED 42
Lower it by 62 bytes...
52A7
LD (4049H),HL 22 49 40
...and store it.
52AA
INC HL 23
HL = the first byte of the space: the task block.
52AB
PUSH HL E5
Save it.
52AC
EX DE,HL EB
DE = the task block.
52AD
LD HL,52C7H 21 C7 52
Point HL to the routine at 52C7H.
52B0
LDIR ED B0
Copy the 62 bytes.
52B2
POP DE D1
Restore the task block address...
52B3
PUSH DE D5
...and save it again.
52B4
LD HL,0005H 21 05 00
HL = the task block + 5...
52B7
ADD HL,DE 19
(add DE)
52B8
EX DE,HL EB
...into DE; HL = the task block.
52B9
LD (HL),E 73
Store it as the first two bytes of the block: the task's entry is block + 5 (the copy of 52CCH).
52BA
INC HL 23
(next byte)
52BB
LD (HL),D 72
(high byte)
52BC
LD A,05H 3E 05
Register A = 05H: task slot 5.
52BE
POP DE D1
Restore the task block address.
52BF
GOSUB to the SYS0 routine at 4410H to install the task.
52C5-52C6
DEFS 2
Receives the LARGE value. Not in the file, and not used.

52C7H - Blinking Cursor Task (copied)

This routine is copied below the top of memory and runs as timer task 5 with IX pointing to its first byte. It shows the cursor character at the cursor position (4020H) on one run and puts back the character underneath on the next, using the SYS0 routine at 4416H, which ends the task for this run and makes the next run continue after the CALL.

52C7-52C8
DEFS 2
Address of the task's entry, set at 52B9H.
52C9-52CA
DEFS 2
IX+02H-03H: the screen address where the cursor was shown.
52CB
DEFS 1
IX+04H: the character that was under it.
52CC
GOSUB to the SYS0 routine at 4416H: wait for the next run.
52CF
LD A,(4022H) 3A 22 40
Fetch 4022H, which is non-zero while the cursor is shown.
52D2
OR A B7
Test it.
52D3
RET Z C8
If there is no cursor, RETURN (the next run starts at 52CFH again).
52D4
LD (IX+04H),A DD 77 04
Store it at IX+04H.
52D7
LD BC,(4020H) ED 4B 20 40
Fetch the cursor address from 4020H.
52DB
LD (IX+02H),C DD 71 02
Store it at IX+02H...
52DE
LD (IX+03H),B DD 70 03
...and IX+03H.
52E1
LD A,(BC) 0A
Fetch the character at the cursor.
52E2
LD (IX+04H),A DD 77 04
Keep it at IX+04H.
52E5
LD A,8FH 3E 8F
Load Register A with the cursor character (the operand at 52E6H, set at 5295H).
52E7
LD (BC),A 02
Show it.
52E8
GOSUB to 4416H: wait for the next run.
52EB
LD C,(IX+02H) DD 4E 02
Fetch the saved address...
52EE
LD B,(IX+03H) DD 46 03
(high byte)
52F1
LD A,(BC) 0A
...and the character there now.
52F2
CP 8FH FE 8F
Is it still the cursor character (the operand at 52F3H)?
52F4
If so, JUMP to 52FFH to put the original character back.
52F6
LD A,C 79
Otherwise the screen may have scrolled: look one line (40H) higher.
52F7
SUB 40H D6 40
(subtract 40H)
52F9
LD C,A 4F
(store it)
52FA
LD A,(BC) 0A
Fetch the character there.
52FB
CP 8FH FE 8F
Is it the cursor character (the operand at 52FCH)?
52FD
If not, JUMP back to 52CCH: the cursor has gone.
52FF
LD A,(IX+04H) DD 7E 04
Fetch the saved character...
5302
LD (BC),A 02
...and put it back.
5303
JUMP back to 52CCH.

5305H - TYPE

TYPE installs type-ahead: a 256-byte key buffer and a new keyboard driver below the top of memory. A timer task (slot 10) reads the keyboard through the old driver and stores the keys in the buffer; the new driver hands them out in order. TYPE=NO removes the task.

5305
LD BC,0001H 01 01 00
Load BC with the TYPE value (0001H if TYPE was not given).
5308
LD A,B 78
Combine the two bytes.
5309
OR C B1
(OR the low byte)
530A
DEC A 3D
Subtract 1...
530B
...and if TYPE was not given, JUMP to 547FH.
530E
INC A 3C
Add the 1 back.
530F
If TYPE was switched on, JUMP to 5319H.
5311
LD A,0AH 3E 0A
TYPE=NO: Register A = 0AH, task slot 10.
5313
GOSUB to 4413H to remove the task.
5319
GOSUB to 5627H to make sure the command was given at VTOS command level.
531C
LD IX,4015H DD 21 15 40
Point IX to the keyboard device control block at 4015H.
5320
LD HL,(4049H) 2A 49 40
Fetch the top of memory.
5323
DEC H 25
Go down 256 bytes.
5324
LD (HL),00H 36 00
Clear the byte there: the read index (header + 2)...
5326
DEC HL 2B
Next byte down...
5327
LD (HL),00H 36 00
...the write index (header + 1)...
5329
DEC HL 2B
Next byte down...
532A
LD (HL),00H 36 00
...and the busy flag. HL = the buffer header; the 256 bytes of data follow the read index.
532C
LD D,H 54
DE = the header - 1...
532D
LD E,L 5D
(low byte)
532E
DEC DE 1B
(minus 1)
532F
LD A,21H 3E 21
Load Register A with 21H.
5331
LD (439CH),A 32 9C 43
Store it at 439CH in SYS0, which changes the CALL 4300H there into LD HL,4300H.
5334
LD (53ADH),HL 22 AD 53
Put the header address into the driver at 53ADH...
5337
LD (53DAH),HL 22 DA 53
...and into the task at 53DAH.
533A
LD HL,(4016H) 2A 16 40
Fetch the address of the current keyboard driver from 4016H.
533D
LD A,(430FH) 3A 0F 43
Fetch the system flags.
5340
BIT 5,A CB 6F
Test bit 5: a chain file is running.
5342
If not, JUMP to 5347H.
5344
LD HL,(43BEH) 2A BE 43
Otherwise the real driver address is the one saved at 43BEH.
5347
LD (53E6H),HL 22 E6 53
Put it into the task's CALL at 53E6H...
534A
LD (53D1H),HL 22 D1 53
...and into the driver's CALL at 53D1H.
534D
EX DE,HL EB
HL = the header - 1.
534E
LD BC,00D6H 01 D6 00
Load Register Pair BC with 00D6H: 214 bytes.
5351
XOR A AF
Clear the Carry flag.
5352
SBC HL,BC ED 42
Go down 214 bytes...
5354
LD (4049H),HL 22 49 40
...and store it as the new top of memory.
5357
INC HL 23
HL = the first byte of the space.
5358
PUSH HL E5
Save it.
5359
EX DE,HL EB
DE = that address.
535A
LD HL,53A9H 21 A9 53
Point HL to the code at 53A9H.
535D
LDIR ED B0
Copy the 214 bytes (53A9H-547EH).
535F
LD (IX+00H),01H DD 36 00 01
Set the device type of the keyboard control block to 01H (input).
5363
POP HL E1
Restore the address of the copy...
5364
PUSH HL E5
...and save it again.
5365
LD A,(430FH) 3A 0F 43
Fetch the system flags.
5368
BIT 5,A CB 6F
Test bit 5: a chain file is running.
536A
If so, JUMP to 5374H.
536C
LD (IX+01H),L DD 75 01
Make the copy the keyboard driver: store its address at 4016H...
536F
LD (IX+02H),H DD 74 02
...(high byte at 4017H).
5372
JUMP to 5377H.
5374
LD (43BEH),HL 22 BE 43
While a chain file runs, store it at 43BEH instead, where the real driver's address is kept.
5377
LD A,(4018H) 3A 18 40
Copy 4018H...
537A
LD (IX+03H),A DD 77 03
...to IX+03H, which is 4018H itself (no change).
537D
LD HL,(4019H) 2A 19 40
Copy 4019H-401AH...
5380
LD (IX+04H),L DD 75 04
...to IX+04H...
5383
LD (IX+05H),H DD 74 05
...and IX+05H, the same addresses (no change).
5386
POP HL E1
Restore the address of the copy...
5387
PUSH HL E5
...and save it again.
5388
LD DE,007DH 11 7D 00
Add 7DH: the copy of the key decoder at 5426H.
538B
ADD HL,DE 19
(add DE)
538C
EX DE,HL EB
DE = its address.
538D
LD HL,4BC1H 21 C1 4B
Point HL to 4BC1H, the address of the CALL 03FAH (the ROM key decoder) at 4BC0H in SYS0.
5390
LD (HL),E 73
Store the new decoder's address there...
5391
INC HL 23
(next byte)
5392
LD (HL),D 72
(high byte)
5393
POP HL E1
Restore the address of the copy.
5394
LD DE,002EH 11 2E 00
Add 2EH: the copy of 53D7H, the task block.
5397
ADD HL,DE 19
(add DE)
5398
LD D,H 54
DE = that address...
5399
LD E,L 5D
(low byte)
539A
INC DE 13
...+ 2...
539B
INC DE 13
...the copy of the task at 53D9H.
539C
LD (HL),E 73
Store it in the task block.
539D
INC HL 23
(next byte)
539E
LD (HL),D 72
(high byte)
539F
DEC HL 2B
HL = the task block.
53A0
EX DE,HL EB
DE = the task block.
53A1
LD A,0AH 3E 0A
Register A = 0AH: task slot 10.
53A3
GOSUB to 4410H to install the task.

53A9H - Type-Ahead Driver (copied)

The new keyboard driver. The buffer header is: busy flag, write index, read index, then 256 bytes of data. Each key takes two bytes: the character and the flags the old driver returned with it. If the buffer is empty, the old driver is called directly.

53A9
GOSUB to 4300H, as the SYS0 keyboard routine does.
53AC
LD HL,0000H 21 00 00
Point HL to the buffer header (the operand, set at 5334H).
53AF
LD (HL),FFH 36 FF
Set the busy flag, so that the task leaves the buffer alone.
53B1
PUSH HL E5
Save the header address.
53B2
INC HL 23
Point to the write index.
53B3
LD A,(HL) 7E
Fetch the write index.
53B4
INC HL 23
Point to the read index.
53B5
CP (HL) BE
Compare it with the read index.
53B6
LD A,00H 3E 00
Register A = 00H (the flags are kept).
53B8
If the buffer is empty, JUMP to 53CCH.
53BA
PUSH HL E5
Save the pointer to the read index.
53BB
LD E,(HL) 5E
E = the read index.
53BC
INC HL 23
Point to the data.
53BD
LD D,00H 16 00
D = 00H.
53BF
ADD HL,DE 19
Point HL to the entry.
53C0
LD B,(HL) 46
B = the character...
53C1
INC HL 23
(next byte)
53C2
LD C,(HL) 4E
...C = its flags.
53C3
POP HL E1
Restore the pointer to the read index.
53C4
INC (HL) 34
Move the read index on by 2...
53C5
INC (HL) 34
(second increment)
53C6
POP HL E1
Restore the header address.
53C7
LD (HL),00H 36 00
Clear the busy flag.
53C9
PUSH BC C5
Move BC...
53CA
POP AF F1
...into AF: the character and its flags.
53CB
RET C9
RETURN.
53CC
LD IX,4015H DD 21 15 40
Point IX to the keyboard control block at 4015H.
53D0
CALL 0000H CD 00 00
GOSUB to the old driver (the operand, set at 534AH).
53D3
POP HL E1
Restore the header address.
53D4
LD (HL),00H 36 00
Clear the busy flag.
53D6
RET C9
RETURN.
53D7-53D8
DEFS 2
The task block: the address of the task, set at 539CH.

53D9H - Type-Ahead Task (copied)

Timer task 10. If the driver is not busy, reads the keyboard through the old driver and adds any key to the buffer. Key code C0H empties the buffer instead.

53D9
LD HL,0000H 21 00 00
Point HL to the buffer header (the operand, set at 5337H).
53DC
LD A,(HL) 7E
Fetch the busy flag.
53DD
OR A B7
Test it.
53DE
RET NZ C0
If the driver is using the buffer, RETURN.
53DF
INC HL 23
Point to the write index.
53E0
PUSH HL E5
Save the pointer.
53E1
LD IX,4015H DD 21 15 40
Point IX to the keyboard control block.
53E5
CALL 0000H CD 00 00
GOSUB to the old driver (the operand, set at 5347H).
53E8
POP HL E1
Restore the pointer.
53E9
INC A 3C
Test for no key...
53EA
DEC A 3D
(restore it)
53EB
RET Z C8
...and RETURN if there is none.
53EC
PUSH AF F5
Move the key and its flags...
53ED
POP BC C1
...into BC.
53EE
CP C0H FE C0
Is it C0H?
53F0
If so, JUMP to 541AH to empty the buffer.
53F2
LD E,(HL) 5E
E = the write index.
53F3
LD A,E 7B
(into A)
53F4
INC HL 23
Point to the read index.
53F5
CP (HL) BE
Compare it with the read index.
53F6
If the buffer is empty, JUMP to 540DH to store the key.
53F8
LD A,(4040H) 3A 40 40
Fetch the tick counter at 4040H...
53FB
ADD A,03H C6 03
...plus 3.
53FD
CP (IX+04H) DD BE 04
Compare it with 4019H (IX+04H).
5400
If they differ, JUMP to 5408H.
5402
ADD A,03H C6 03
Otherwise add 3 more...
5404
LD (IX+04H),A DD 77 04
...store it at 4019H...
5407
RET C9
...and RETURN without storing the key.
5408
LD A,E 7B
Write index + 2...
5409
INC A 3C
(+1)
540A
INC A 3C
(+2)
540B
CP (HL) BE
...compared with the read index:
540C
RET Z C8
if the buffer is full, RETURN.
540D
PUSH HL E5
Save the pointer to the read index.
540E
INC HL 23
Point to the data.
540F
LD D,00H 16 00
D = 00H.
5411
ADD HL,DE 19
Point HL to the free entry.
5412
LD (HL),B 70
Store the character...
5413
INC HL 23
(next byte)
5414
LD (HL),C 71
...and its flags.
5415
POP HL E1
Restore the pointer...
5416
DEC HL 2B
...to the write index.
5417
INC (HL) 34
Move it on by 2.
5418
INC (HL) 34
(second increment)
5419
RET C9
RETURN.
541A
LD (HL),02H 36 02
C0H: write index = 02H...
541C
INC HL 23
(next byte)
541D
LD (HL),00H 36 00
...read index = 00H...
541F
INC HL 23
(next byte)
5420
LD (HL),00H 36 00
...and one entry of character 00H...
5422
INC HL 23
(next byte)
5423
LD (HL),40H 36 40
...with flags 40H (Z set): the next read returns no key.
5425
RET C9
RETURN.

5426H - Key Decoder (copied)

Replaces the ROM key decoder (03FAH) through the CALL at 4BC0H. Entry: Register A = the bits of the key in its keyboard row, Register D = the row number. Works like the ROM routine; with the down arrow held, a letter gives a control code (01H-1AH). If the key is BREAK (01H), RST 28H is executed with A = 01H.

5426
LD E,A 5F
E = the key bits.
5427
LD A,D 7A
Row number...
5428
RLCA 07
...x 8...
5429
RLCA 07
(x 4)
542A
RLCA 07
(x 8)
542B
LD D,A 57
...into D.
542C
LD C,01H 0E 01
C = the bit being tested.
542E
LD A,C 79
Register A = the bit.
542F
AND E A3
Is this the key?
5430
If so, JUMP to 5437H.
5432
INC D 14
Next key code.
5433
RLC C CB 01
Next bit.
5435
LOOP back to 542EH.
5437
LD A,(3880H) 3A 80 38
Read keyboard row 7 (SHIFT).
543A
LD B,A 47
Keep it in B.
543B
LD A,D 7A
Key number...
543C
ADD A,40H C6 40
...+ 40H.
543E
CP 60H FE 60
Rows 0-3 (@ and the letters) give 40H-5FH.
5440
If it is not one of those, JUMP to 5455H.
5442
RRC B CB 08
Is SHIFT pressed?
5444
If not, JUMP to 547AH with the capital letter.
5446
ADD A,20H C6 20
SHIFT: add 20H (lower case).
5448
LD D,A 57
(keep it in D)
5449
LD A,(3840H) 3A 40 38
Read keyboard row 6...
544C
AND 10H E6 10
...and test the down arrow.
544E
If it is not held, JUMP to 5479H.
5450
LD A,D 7A
Down arrow: take 60H off...
5451
SUB 60H D6 60
(subtract)
5453
...giving a control code: JUMP to 547AH.
5455
SUB 70H D6 70
Take 70H off.
5457
If the key is in row 6 (No Carry), JUMP to 5469H.
5459
ADD A,40H C6 40
Rows 4-5: + 40H gives 30H-3FH.
545B
CP 3CH FE 3C
Below 3CH?
545D
If not, JUMP to 5461H.
545F
XOR 10H EE 10
Digits and : ;: toggle bit 4.
5461
RRC B CB 08
Is SHIFT pressed?
5463
If not, JUMP to 547AH.
5465
XOR 10H EE 10
SHIFT: toggle bit 4 again.
5467
JUMP to 547AH.
5469
RLCA 07
Row 6: x 2...
546A
RRC B CB 08
...+ 1 if SHIFT is pressed...
546C
(no SHIFT: skip)
546E
INC A 3C
(+1)
546F
LD HL,0050H 21 50 00
...indexes the ROM table at 0050H.
5472
LD C,A 4F
BC = the index...
5473
LD B,00H 06 00
(B = 00H)
5475
ADD HL,BC 09
...added to HL.
5476
LD A,(HL) 7E
Fetch the character.
5477
JUMP to 547AH.
5479
LD A,D 7A
A = the key.
547A
CP 01H FE 01
Is it BREAK (01H)?
547C
RET NZ C0
If not, RETURN with it.
547D
RST 28H EF
RST 28H with Register A = 01H.
547E
RET C9
RETURN.

547FH - LOWER

Installs a display driver in high memory that goes straight to the ROM display routines (047DH, 04A6H, 0506H), and makes it the driver of the display control block at 401DH. The driver makes the tests for control codes and graphics itself and enters the ROM at 047DH for other characters, skipping the ROM's own handling of the character; the option's name suggests that this is for lower-case display.

547F
LD BC,0000H 01 00 00
Load BC with the LOWER value.
5482
LD A,B 78
Test it...
5483
OR C B1
(OR the low byte)
5484
...and if it was not given, JUMP to 54DDH.
5487
GOSUB to 5627H to make sure the command was given at VTOS command level.
548A
LD IX,401DH DD 21 1D 40
Point IX to the display control block at 401DH.
548E
LD BC,001EH 01 1E 00
Load Register Pair BC with 001EH: 30 bytes.
5491
LD HL,(4049H) 2A 49 40
Fetch the top of memory.
5494
XOR A AF
Clear the Carry flag.
5495
SBC HL,BC ED 42
Lower it by 30 bytes...
5497
LD (4049H),HL 22 49 40
...and store it.
549A
INC HL 23
HL = the first byte of the space.
549B
PUSH HL E5
Save it.
549C
EX DE,HL EB
DE = that address.
549D
LD HL,54BFH 21 BF 54
Point HL to the driver at 54BFH.
54A0
LDIR ED B0
Copy the 30 bytes.
54A2
LD (IX+00H),07H DD 36 00 07
Set the device type to 07H.
54A6
POP HL E1
Restore the address of the copy.
54A7
LD (IX+01H),L DD 75 01
Store it as the driver address at 401EH...
54AA
LD (IX+02H),H DD 74 02
...and 401FH.
54AD
LD A,(4020H) 3A 20 40
Copy 4020H...
54B0
LD (IX+03H),A DD 77 03
...to IX+03H, which is 4020H itself (no change).
54B3
LD HL,(4021H) 2A 21 40
Copy 4021H-4022H...
54B6
LD (IX+04H),L DD 75 04
...to IX+04H...
54B9
LD (IX+05H),H DD 74 05
...and IX+05H, the same addresses (no change).
54BF
LD L,(IX+03H) DD 6E 03
Display driver (copied). HL = the cursor address (IX+03H-04H, which is 4020H-4021H)...
54C2
LD H,(IX+04H) DD 66 04
(high byte)
54C5
Carry set means a read request: JUMP to the ROM at 049AH.
54C8
LD A,(IX+05H) DD 7E 05
Fetch IX+05H (4022H), the character under the cursor while the cursor is shown.
54CB
OR A B7
Test it.
54CC
If there is none, JUMP to 54CFH.
54CE
LD (HL),A 77
Put it back on the screen.
54CF
LD A,C 79
A = the character to display (Register C).
54D0
CP 20H FE 20
Control codes below 20H...
54D2
...go to the ROM at 0506H.
54D5
CP 80H FE 80
Codes 80H and above (graphics and space compression)...
54D7
...go to the ROM at 04A6H.
54DA
Others go to the ROM at 047DH.

54DDH - JKL and GRAPHIC

Installs a timer task (slot 4) that waits for J, K and L to be pressed together and then has the SYS0 interrupt routine print the screen. Characters 80H and above are printed as ., unless GRAPHIC is given as well.

54DD
LD BC,0000H 01 00 00
Load BC with the JKL value.
54E0
LD A,B 78
Test it...
54E1
OR C B1
(OR the low byte)
54E2
...and if it was not given, JUMP to 5572H.
54E5
GOSUB to 5627H to make sure the command was given at VTOS command level.
54E8
LD BC,0000H 01 00 00
Load BC with the GRAPHIC value.
54EB
LD A,B 78
Test it...
54EC
OR C B1
(OR the low byte)
54ED
...and if it was not given, JUMP to 54F5H.
54EF
LD HL,0000H 21 00 00
HL = 0000H...
54F2
LD (5561H),HL 22 61 55
...stored over the LD A,2EH at 5561H: two NOPs, so graphics characters are printed as they are.
54F5
LD BC,004EH 01 4E 00
Load Register Pair BC with 004EH: 78 bytes.
54F8
LD HL,(4049H) 2A 49 40
Fetch the top of memory.
54FB
XOR A AF
Clear the Carry flag.
54FC
SBC HL,BC ED 42
Lower it by 78 bytes...
54FE
LD (4049H),HL 22 49 40
...and store it.
5501
INC HL 23
HL = the first byte of the space: the task block.
5502
PUSH HL E5
Save it.
5503
LD D,H 54
DE = that address...
5504
LD E,L 5D
(low byte)
5505
INC HL 23
HL = block + 2...
5506
INC HL 23
(+2)
5507
LD (5524H),HL 22 24 55
...stored at 5524H: the task's entry (the copy of 5526H).
550A
LD HL,001AH 21 1A 00
HL = block + 1AH...
550D
ADD HL,DE 19
(add DE)
550E
LD (5533H),HL 22 33 55
...stored in the LD HL at 5532H: the copy of the print routine at 553EH.
5511
POP DE D1
Restore the block address...
5512
PUSH DE D5
...and save it again.
5513
LD HL,5524H 21 24 55
Point HL to 5524H.
5516
LD BC,004EH 01 4E 00
Load Register Pair BC with 004EH.
5519
LDIR ED B0
Copy the 78 bytes (5524H-5571H).
551B
POP DE D1
Restore the block address.
551C
LD A,04H 3E 04
Register A = 04H: task slot 4.
551E
GOSUB to 4410H to install the task.
5524-5525
DEFS 2
The task block: the address of the task, set at 5507H.

5526H - JKL Task (copied)

Runs as timer task 4.

5526
LD A,(3802H) 3A 02 38
Read keyboard row 1.
5529
CP 1CH FE 1C
Only J, K and L (1CH) pressed?
552B
RET NZ C0
If not, RETURN.
552C
LD HL,(4537H) 2A 37 45
Fetch the address at 4537H.
552F
LD A,H 7C
Test it...
5530
OR L B5
(OR the low byte)
5531
RET NZ C0
...and if a print is already under way, RETURN.
5532
LD HL,0000H 21 00 00
HL = the print routine (the operand, set at 550EH).
5535
LD (4537H),HL 22 37 45
Store it at 4537H, the address of the CALL at 4536H in the SYS0 interrupt routine.
5538
LD A,CCH 3E CC
Load Register A with CCH (CALL Z)...
553A
LD (4536H),A 32 36 45
...and store it at 4536H: the interrupt routine now calls the print routine.
553D
RET C9
RETURN.
553E
LD A,C4H 3E C4
Print routine (copied). Load Register A with C4H (CALL NZ)...
5540
LD (4536H),A 32 36 45
...and store it at 4536H, so that the routine is not called again while it runs.
5543
PUSH BC C5
Save BC.
5544
PUSH DE D5
Save DE.
5545
LD HL,3C00H 21 00 3C
Point HL to the start of the screen at 3C00H.
5548
LD A,(3840H) 3A 40 38
Read keyboard row 6.
554B
AND 04H E6 04
Is BREAK pressed?
554D
If so, JUMP to 5568H to stop.
554F
LD A,L 7D
At the start of each 64-character line...
5550
AND 3FH E6 3F
(bits 0-5 of the address: Z at the start of a line)
5552
LD A,0DH 3E 0D
Load Register A with a carriage return (the flags are kept).
5554
...print a carriage return.
5557
BIT 6,H CB 74
Past the end of the screen (4000H)?
5559
If so, JUMP to 5568H.
555B
LD A,(HL) 7E
Fetch a character from the screen.
555C
INC HL 23
Move on.
555D
CP 80H FE 80
Is it 80H or above?
555F
If not, JUMP to 5563H.
5561
LD A,2EH 3E 2E
Replace it with . (these two bytes become NOPs with GRAPHIC).
5563
GOSUB to the ROM routine at 003BH to print it.
5566
LOOP back to 5548H.
5568
POP DE D1
Restore DE.
5569
POP BC C1
Restore BC.
556A
LD HL,0000H 21 00 00
HL = 0000H.
556D
DI F3
Disable interrupts.
556E
LD (4537H),HL 22 37 45
Clear the address at 4537H: the print is finished.
5571
RET C9
RETURN.

5572H - ALIVE

Installs a timer task (slot 3) that changes the character in the top right corner of the screen (3C3FH) between 86H and 89H each time it runs.

5572
LD BC,0000H 01 00 00
Load BC with the ALIVE value.
5575
LD A,B 78
Test it...
5576
OR C B1
(OR the low byte)
5577
...and if it was not given, JUMP to 55B4H.
557A
GOSUB to 5627H to make sure the command was given at VTOS command level.
557D
LD HL,(4049H) 2A 49 40
Fetch the top of memory.
5580
LD BC,0011H 01 11 00
Load Register Pair BC with 0011H: 17 bytes.
5583
XOR A AF
Clear the Carry flag.
5584
SBC HL,BC ED 42
Lower the top of memory...
5586
LD (4049H),HL 22 49 40
...and store it.
5589
INC HL 23
HL = the first byte of the space: the task block.
558A
PUSH HL E5
Save it.
558B
INC HL 23
HL = block + 2...
558C
INC HL 23
(+2)
558D
LD (55A3H),HL 22 A3 55
...stored in the task block at 55A3H: the task's entry.
5590
POP DE D1
Restore the block address...
5591
PUSH DE D5
...and save it again.
5592
LD HL,55A3H 21 A3 55
Point HL to 55A3H.
5595
LD BC,0011H 01 11 00
Load Register Pair BC with 0011H.
5598
LDIR ED B0
Copy the 17 bytes.
559A
POP DE D1
Restore the block address.
559B
LD A,03H 3E 03
Register A = 03H: task slot 3.
559D
GOSUB to 4410H to install the task.
55A3-55A4
DEFW 0000H 00 00
The task block: the address of the task, set at 558DH.
55A5
LD A,(3C3FH) 3A 3F 3C
Task (copied): fetch the character in the corner.
55A8
CP 86H FE 86
Is it 86H?
55AA
LD A,89H 3E 89
Load Register A with 89H (the flags are kept).
55AC
If it was 86H, JUMP to 55B0H.
55AE
LD A,86H 3E 86
Otherwise use 86H.
55B0
LD (3C3FH),A 32 3F 3C
Store it.
55B3
RET C9
RETURN.

55B4H - DRIVE, ENABLE, DISABLE, STEP and DELAY

Change the drive control table of drive n (DRIVE=n). DISABLE puts a RET in place of the jump at the start of the table entry, so the drive can no longer be used; ENABLE puts the JP back. STEP=n (0-3) sets the stepping rate in bits 0-1 of DCT+03H. DELAY=NO sets bit 2 of DCT+03H, DELAY clears it. STEP and DELAY are refused (PARAMETER ERROR) if bit 3 of DCT+03H is set.

55B4
LD BC,FFFFH 01 FF FF
Load BC with the DRIVE value (FFFFH if DRIVE was not given).
55B7
INC B 04
Add 1 to the high byte.
55B8
If DRIVE was not given, JUMP to 5619H.
55BB
LD A,C 79
Fetch the drive number.
55BC
CP 08H FE 08
Is it 8 or more?
55BE
If so, JUMP to 5660H to display PARAMETER ERROR.
55C1
GOSUB to the SYS0 routine at 478FH to point IY to the drive control table of drive C.
55C4
LD BC,0000H 01 00 00
Load BC with the DISABLE value.
55C7
LD A,B 78
Test it...
55C8
OR C B1
(OR the low byte)
55C9
...and if it was not given, JUMP to 55D2H.
55CB
LD A,C9H 3E C9
Load Register A with C9H (RET)...
55CD
LD (IY+00H),A FD 77 00
...and put it at DCT+00H.
55D0
JUMP to 55DEH.
55D2
LD BC,0000H 01 00 00
Load BC with the ENABLE value.
55D5
LD A,B 78
Test it...
55D6
OR C B1
(OR the low byte)
55D7
...and if it was not given, JUMP to 55DEH.
55D9
LD A,C3H 3E C3
Load Register A with C3H (JP)...
55DB
LD (IY+00H),A FD 77 00
...and put it at DCT+00H.
55DE
LD BC,FFFFH 01 FF FF
Load BC with the STEP value (FFFFH if STEP was not given).
55E1
INC B 04
Add 1 to the high byte.
55E2
If STEP was not given, JUMP to 55FAH.
55E4
LD A,C 79
Fetch the step rate.
55E5
CP 04H FE 04
Is it 4 or more?
55E7
If so, JUMP to 5660H.
55EA
BIT 3,(IY+03H) FD CB 03 5E
Test bit 3 of DCT+03H.
55EE
If it is set, JUMP to 5660H.
55F1
LD A,(IY+03H) FD 7E 03
Fetch DCT+03H...
55F4
AND FCH E6 FC
...clear bits 0-1...
55F6
OR C B1
...put in the new rate...
55F7
LD (IY+03H),A FD 77 03
...and store it.
55FA
LD BC,0001H 01 01 00
Load BC with the DELAY value (0001H if DELAY was not given).
55FD
LD A,B 78
Combine the two bytes.
55FE
OR C B1
(OR the low byte)
55FF
DEC A 3D
Subtract 1...
5600
...and if DELAY was not given, JUMP to 5619H.
5602
INC A 3C
Add the 1 back.
5603
LD B,00H 06 00
B = 00H for DELAY (the flags are kept)...
5605
...and JUMP to 5609H if DELAY was switched on.
5607
LD B,04H 06 04
B = 04H for DELAY=NO.
5609
BIT 3,(IY+03H) FD CB 03 5E
Test bit 3 of DCT+03H.
560D
If it is set, JUMP to 5660H.
5610
LD A,(IY+03H) FD 7E 03
Fetch DCT+03H...
5613
AND FBH E6 FB
...clear bit 2...
5615
OR B B0
...put in the new value...
5616
LD (IY+03H),A FD 77 03
...and store it.

5619H - SYSGEN

SYSGEN or SYSGEN=NO runs the SYSGEN member (ISAM 1CH) with HL = the value.

5619
LD HL,0001H 21 01 00
Load HL with the SYSGEN value (0001H if SYSGEN was not given).
561C
LD A,H 7C
Combine the two bytes.
561D
OR L B5
(OR the low byte)
561E
DEC A 3D
Subtract 1...
561F
...and if SYSGEN was not given, JUMP to 402DH: back to VTOS READY.
5622
LD B,1CH 06 1C
Load Register B with 1CH: ISAM 1CH, SYSGEN.
5624
LD A,88H 3E 88
Load Register A with 88H: SYS6.
5626
RST 28H EF
Call the overlay through RST 28H: SYS6 loads the SYSGEN member and runs it.

5627H - Check the Command Level

If a program has put a jump (C3H) at 402DH, the DOS exit, the option is refused with CAN'T -- ONLY VALID AT VTOS COMMAND LEVEL.

5627
LD A,(402DH) 3A 2D 40
Fetch the first byte at 402DH.
562A
CP C3H FE C3
Is it C3H (JP)?
562C
RET NZ C0
If not, RETURN.
562D
LD HL,5636H 21 36 56
Point HL to the message at 5636H.
5630
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5633
JUMP to 4030H: back to VTOS READY.
5636-565F
DEFM "CAN'T -- ONLY VALID AT VTOS COMMAND LEVEL",0DH 43 41 4E 27 54 20 2D 2D 20 4F 4E 4C 59 20 56 41 4C 49 44 20 41 54 20 56 54 4F 53 20 43 4F 4D 4D 41 4E 44 20 4C 45 56 45 4C 0D
Displayed at 5630H.
5660
LD HL,5669H 21 69 56
Point HL to PARAMETER ERROR at 5669H.
5663
GOSUB to 447BH to display it.
5666
JUMP to 4030H: back to VTOS READY.
5669-5678
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 5663H.

5679H - Parameter Table

6-character names padded with spaces, each followed by the address that receives the value.

5679-5680
DEFM "FAST " : DEFW 5211H 46 41 53 54 20 20 11 52
FAST: operand of the LD BC at 5210H.
5681-5688
DEFM "SLOW " : DEFW 520AH 53 4C 4F 57 20 20 0A 52
SLOW: operand of the LD BC at 5209H.
5689-5690
DEFM "BASIC2" : DEFW 522FH 42 41 53 49 43 32 2F 52
BASIC2: operand of the LD BC at 522EH.
5691-5698
DEFM "BREAK " : DEFW 524CH 42 52 45 41 4B 20 4C 52
BREAK: operand of the LD BC at 524BH.
5699-56A0
DEFM "BLINK " : DEFW 5270H 42 4C 49 4E 4B 20 70 52
BLINK: operand of the LD BC at 526FH.
56A1-56A8
DEFM "LARGE " : DEFW 52C5H 4C 41 52 47 45 20 C5 52
LARGE: goes to 52C5H, which is not used.
56A9-56B0
DEFM "SMALL " : DEFW 528BH 53 4D 41 4C 4C 20 8B 52
SMALL: operand of the LD BC at 528AH.
56B1-56B8
DEFM "TYPE " : DEFW 5306H 54 59 50 45 20 20 06 53
TYPE: operand of the LD BC at 5305H.
56B9-56C0
DEFM "LOWER " : DEFW 5480H 4C 4F 57 45 52 20 80 54
LOWER: operand of the LD BC at 547FH.
56C1-56C8
DEFM "JKL " : DEFW 54DEH 4A 4B 4C 20 20 20 DE 54
JKL: operand of the LD BC at 54DDH.
56C9-56D0
DEFM "GRAPHI" : DEFW 54E9H 47 52 41 50 48 49 E9 54
GRAPHIC: operand of the LD BC at 54E8H.
56D1-56D8
DEFM "ALIVE " : DEFW 5573H 41 4C 49 56 45 20 73 55
ALIVE: operand of the LD BC at 5572H.
56D9-56E0
DEFM "DRIVE " : DEFW 55B5H 44 52 49 56 45 20 B5 55
DRIVE: operand of the LD BC at 55B4H.
56E1-56E8
DEFM "ENABLE" : DEFW 55D3H 45 4E 41 42 4C 45 D3 55
ENABLE: operand of the LD BC at 55D2H.
56E9-56F0
DEFM "DISABL" : DEFW 55C5H 44 49 53 41 42 4C C5 55
DISABLE: operand of the LD BC at 55C4H.
56F1-56F8
DEFM "STEP " : DEFW 55DFH 53 54 45 50 20 20 DF 55
STEP: operand of the LD BC at 55DEH.
56F9-5700
DEFM "DELAY " : DEFW 55FBH 44 45 4C 41 59 20 FB 55
DELAY: operand of the LD BC at 55FAH.
5701-5708
DEFM "SYSGEN" : DEFW 561AH 53 59 53 47 45 4E 1A 56
SYSGEN: operand of the LD HL at 5619H.
5709
DEFB 00H 00
End of the table.

ISAM A2H - SPOOL - Offset 19D7

SPOOL (SPOOL *PR filespec (MEM=m, DISK=d)) puts a print spooler between a device (normally the printer) and the programs that use it. Characters sent to the device are stored in 256-byte buffers and printed by a timer task while the computer does other work. MEM (or M) is the memory to use, 1-32K (default 1K); DISK (or D) is the space in K to allocate in the spool file (default 4K; DISK=0 for none), which is used when the memory buffers are full. The spool file defaults to PR/SPL (the device name with the extension SPL); SPOOL *PR :d puts it on drive d. The spooler code (54D3H-5629H), its control block and FCB (562AH-5655H), a table of buffer descriptors and the buffers themselves are placed below the top of memory. It is entered at 5208H. The member loads at 5200H-548AH, 54ABH-5574H, 5577H-55B8H, 55BCH-5629H and 5654H-5655H (1,031 bytes).

5200H - Spare Bytes

The member is entered at 5208H.

5200-5207
NOP x 8 00 x 8
Not used.

5208H - SPOOL Command

HL points to the text after SPOOL.

5208
LD A,(402DH) 3A 2D 40
Fetch the first byte at 402DH, the DOS exit.
520B
CP C3H FE C3
Is it C3H (JP), which means a program has taken over the exit?
520D
If so, JUMP to 543FH to display CAN'T -- ONLY VALID AT VTOS COMMAND LEVEL.
5210
LD DE,548BH 11 8B 54
Point DE to the work area at 548BH.
5213
GOSUB to the SYS0 routine at 441CH to read the device name into it.
5216
If there is none (NZ), JUMP to 5421H to display DEVICE SPEC REQUIRED.
5219
LD A,(DE) 1A
Fetch the first character.
521A
CP 2AH FE 2A
Is it *?
521C
If not, JUMP to 5421H.
521F
LD DE,(548CH) ED 5B 8C 54
Fetch the two letters of the device name (548CH-548DH)...
5223
LD (54ABH),DE ED 53 AB 54
...and put them in front of /SPL at 54ABH: the default spool file name.
5227
LD DE,562AH 11 2A 56
Point DE to the spool file's FCB at 562AH.
522A
GOSUB to 441CH to read a filespec into it.
522D
PUSH AF F5
Save the result (Register A = the character after it).
522E
PUSH HL E5
Save the line pointer.
522F
LD HL,54ABH 21 AB 54
Point HL to the default name at 54ABH.
5232
If no filespec was given (NZ), GOSUB to 441CH to use the default.
5235
LD HL,54AEH 21 AE 54
Point HL to the default extension SPL at 54AEH.
5238
GOSUB to the SYS0 routine at 4473H to add it if there is no extension.
523B
POP HL E1
Restore the line pointer.
523C
POP AF F1
Restore the result.
523D
CP 3AH FE 3A
Did the text stop at a :?
523F
If not, JUMP to 525DH.
5241
LD A,(DE) 1A
Find the end of the filespec in the FCB:
5242
CP 0DH FE 0D
a carriage return...
5244
...ends it,
5246
CP 03H FE 03
and so does 03H.
5248
If so, JUMP to 524DH.
524A
INC DE 13
Next character.
524B
LOOP back to 5241H.
524D
LD A,3AH 3E 3A
Load Register A with :...
524F
LD (DE),A 12
...and add it to the filespec.
5250
INC DE 13
(next byte)
5251
LD A,(HL) 7E
Fetch the drive digit from the command line.
5252
CP 0DH FE 0D
A carriage return here...
5254
...is a PARAMETER ERROR: JUMP to 5472H.
5257
INC HL 23
Move past the digit.
5258
LD (DE),A 12
Add it to the filespec.
5259
INC DE 13
(next byte)
525A
LD A,03H 3E 03
Load Register A with 03H...
525C
LD (DE),A 12
...and end the filespec with it.
525D
LD DE,54B2H 11 B2 54
Point DE to the parameter table at 54B2H.
5260
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
5263
If a parameter was not recognized (NZ), JUMP to 5472H.
5266
LD DE,(548CH) ED 5B 8C 54
Fetch the two letters of the device name.
526A
GOSUB to 53F6H to find its device control block.
526D
If there is no such device (NZ, Register A = 08H), JUMP to the error exit at 541CH.
5270
BIT 4,(HL) CB 66
Is this a link to another control block (bit 4 of the type, set by ROUTE)?
5272
If not, JUMP to 527BH.
5274
INC HL 23
Follow the link:
5275
LD A,(HL) 7E
the low byte of the address...
5276
INC HL 23
(next byte)
5277
LD H,(HL) 66
...the high byte...
5278
LD L,A 6F
(into L)
5279
...and LOOP back to 5270H.
527B
LD (536FH),HL 22 6F 53
Store the control block address at 536FH (the operand of the LD HL at 536EH).
527E
LD DE,(5295H) ED 5B 95 52
Fetch the DISK value (the operand at 5295H, 0004H unless DISK was given).
5282
LD A,D 7A
Test it...
5283
OR E B3
(OR the low byte)
5284
...and if it is 0, JUMP to 52C8H: no spool file.
5286
LD DE,562AH 11 2A 56
Point DE to the spool file's FCB.
5289
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
528C
LD B,00H 06 00
Load Register B with 00H: record length 256.
528E
GOSUB to the SYS0 routine at 4420H to open the file, creating it if necessary.
5291
If that failed (NZ), JUMP to 541CH.
5294
LD BC,0004H 01 04 00
Load BC with the DISK value.
5297
LD A,B 78
Test the high byte...
5298
AND F0H E6 F0
...for anything above 0FFFH...
529A
...which is a PARAMETER ERROR: JUMP to 5472H.
529D
SLA C CB 21
Multiply by 4 (four sectors per K)...
529F
RL B CB 10
(and carry into the high byte)
52A1
SLA C CB 21
(shift the low byte)
52A3
RL B CB 10
(and carry into the high byte)
52A5
DEC BC 0B
...minus 1: the last record.
52A6
GOSUB to the SYS0 routine at 4442H to position the file there.
52A9
GOSUB to the SYS0 routine at 4439H to write it, which allocates all the space up to it.
52AC
If that failed (NZ), JUMP to 541CH.
52AF
GOSUB to the SYS0 routine at 443FH to position the file back to record 0.
52B2
GOSUB to the SYS0 routine at 444EH to write the ending record number into the directory.
52B5
LD BC,(5630H) ED 4B 30 56
Fetch the drive (FCB+06H) and directory entry code (FCB+07H).
52B9
GOSUB to the SYS0 routine at 4B10H to read the directory entry.
52BC
If that failed (NZ), JUMP to 541CH.
52BF
INC HL 23
Point HL to byte 1 of the entry.
52C0
SET 7,(HL) CB FE
Set bit 7: keep the space when the file is closed (as ALLOC does).
52C2
GOSUB to the SYS0 routine at 4B1FH to write the entry back.
52C5
If that failed (NZ), JUMP to 541CH.

52C8H - Build the Buffer Descriptor Table

One 4-byte descriptor for each 256-byte memory buffer and each disk record: link (2 bytes, 0000H when free), the page or record, and a flag byte (bit 7 = a disk record). The table ends with FFH FFH. The buffers take the MEM*1K just below the page above the top of memory; the table goes below them.

52C8
LD BC,0001H 01 01 00
Load BC with the MEM value (the operand at 52C9H, 0001H unless MEM was given).
52CB
LD A,B 78
The high byte...
52CC
OR A B7
...must be 0...
52CD
...or it is a PARAMETER ERROR.
52D0
LD A,C 79
The low byte...
52D1
CP 21H FE 21
...must be 32 or less...
52D3
(above 32: PARAMETER ERROR)
52D6
SUB 01H D6 01
...and not 0.
52D8
(0: PARAMETER ERROR)
52DB
LD HL,(5295H) 2A 95 52
Fetch the DISK value.
52DE
ADD HL,BC 09
Add MEM: the total number of K.
52DF
ADD HL,HL 29
x 4: the number of 256-byte blocks...
52E0
ADD HL,HL 29
(x 2)
52E1
INC HL 23
...+ 1 for the end mark...
52E2
ADD HL,HL 29
...x 4 bytes per descriptor.
52E3
ADD HL,HL 29
(x 2)
52E4
PUSH HL E5
Save the size of the table.
52E5
LD HL,(4049H) 2A 49 40
Fetch the top of memory...
52E8
INC HL 23
...plus 1...
52E9
LD L,00H 2E 00
...rounded down to the start of its page.
52EB
LD A,(52C9H) 3A C9 52
Fetch MEM (1-32)...
52EE
RLCA 07
...x 4:
52EF
RLCA 07
the number of pages.
52F0
LD B,A 47
Register B = the number of pages.
52F1
NEG ED 44
Negate it...
52F3
ADD A,H 84
...and go down that many pages from the top.
52F4
LD H,A 67
HL = the first buffer.
52F5
LD (564AH),HL 22 4A 56
Store it as the write position (control block +20H, at 564AH)...
52F8
LD (564CH),HL 22 4C 56
...and as the read position (+22H, at 564CH).
52FB
LD C,H 4C
Register C = the page of the first buffer.
52FC
POP DE D1
Restore the size of the table.
52FD
XOR A AF
Clear the Carry flag.
52FE
SBC HL,DE ED 52
HL = the start of the table, just below the buffers.
5300
PUSH HL E5
Save it.
5301
LD (HL),00H 36 00
Memory descriptor: link = 0000H...
5303
INC HL 23
(next byte)
5304
LD (HL),00H 36 00
(store 00H)
5306
INC HL 23
(next byte)
5307
LD (HL),C 71
...the page...
5308
INC HL 23
(next byte)
5309
LD (HL),00H 36 00
...and a flag byte of 00H.
530B
INC HL 23
(next byte)
530C
INC C 0C
Next page.
530D
LOOP back to 5301H for every memory buffer.
530F
LD DE,(5295H) ED 5B 95 52
Fetch the DISK value.
5313
LD A,D 7A
Test it...
5314
OR E B3
(OR the low byte)
5315
...and if it is 0, JUMP to 5334H.
5317
SLA E CB 23
x 4: the number of disk records...
5319
RL D CB 12
(and carry into the high byte)
531B
SLA E CB 23
(shift the low byte)
531D
RL D CB 12
(and carry into the high byte)
531F
LD BC,0000H 01 00 00
BC = record 0.
5322
LD (HL),00H 36 00
Disk descriptor: link = 0000H...
5324
INC HL 23
(next byte)
5325
LD (HL),00H 36 00
(store 00H)
5327
INC HL 23
(next byte)
5328
LD (HL),C 71
...the record number, low byte...
5329
INC HL 23
(next byte)
532A
LD (HL),B 70
...and high byte...
532B
SET 7,(HL) CB FE
...with bit 7 set (a disk record).
532D
INC HL 23
(next byte)
532E
INC BC 03
Next record.
532F
DEC DE 1B
Count it...
5330
LD A,D 7A
(A = D)
5331
OR E B3
(OR the other byte)
5332
...and LOOP back to 5322H for every record.
5334
LD (HL),00H 36 00
End of the table: 00H 00H FFH FFH.
5336
INC HL 23
(next byte)
5337
LD (HL),00H 36 00
(store 00H)
5339
INC HL 23
(next byte)
533A
LD (HL),FFH 36 FF
(store FFH)
533C
INC HL 23
(next byte)
533D
LD (HL),FFH 36 FF
(store FFH)
533F
POP HL E1
Restore the start of the table.
5340
PUSH HL E5
Save it again.
5341
LD (564EH),HL 22 4E 56
Store it as the table address (+24H, at 564EH)...
5344
LD (5650H),HL 22 50 56
...the last buffer filled (+26H, at 5650H)...
5347
LD (5652H),HL 22 52 56
...and the next buffer to print (+28H, at 5652H).
534A
LD A,H 7C
The first descriptor serves as the head of the queue: its link points to itself.
534B
LD (HL),L 75
(store L)
534C
INC HL 23
(next byte)
534D
LD (HL),A 77
(store A)

534EH - Install the Spooler

Copies the FCB and control block and the spooler code below the table, makes the code the device's driver, adds the output routine as timer task 9, and hooks the refill routine into 4300H.

534E
POP HL E1
Restore the start of the table.
534F
LD BC,002CH 01 2C 00
Load Register Pair BC with 002CH: 44 bytes.
5352
XOR A AF
Clear the Carry flag.
5353
SBC HL,BC ED 42
HL = the place for the control block, just below the table.
5355
PUSH HL E5
Save it.
5356
EX DE,HL EB
DE = that address.
5357
LD HL,562AH 21 2A 56
Point HL to the FCB at 562AH.
535A
LDIR ED B0
Copy the FCB and control block (562AH-5655H).
535C
POP HL E1
Restore its address...
535D
PUSH HL E5
...and save it again.
535E
LD (54DEH),HL 22 DE 54
Put it into the LD IX at 54DCH...
5361
LD (558AH),HL 22 8A 55
...the LD IX at 5588H...
5364
LD (55CAH),HL 22 CA 55
...and the LD IX at 55C8H.
5367
LD BC,0023H 01 23 00
Add 23H...
536A
ADD HL,BC 09
(add BC)
536B
LD (55BEH),HL 22 BE 55
...and put it into the LD A at 55BDH: the page being printed.
536E
LD HL,0000H 21 00 00
Load HL with the device control block (the operand at 536FH, stored at 527BH).
5371
INC HL 23
Point to its driver address:
5372
LD C,(HL) 4E
low byte...
5373
INC HL 23
(next byte)
5374
LD B,(HL) 46
...high byte.
5375
LD (5583H),BC ED 43 83 55
Put the old driver address into the CALL at 5582H...
5379
LD (55A9H),BC ED 43 A9 55
...and the CALL at 55A8H.
537D
LD A,(4300H) 3A 00 43
Fetch the three bytes at 4300H...
5380
LD HL,(4301H) 2A 01 43
(the address part)
5383
LD (55B9H),A 32 B9 55
...and put them at 55B9H-55BBH, after the CALL at 55B6H, so that the hook goes on to whatever was at 4300H.
5386
LD (55BAH),HL 22 BA 55
(the address part)
5389
POP HL E1
Restore the control block address.
538A
LD BC,0157H 01 57 01
Load Register Pair BC with 0157H: 343 bytes of code.
538D
XOR A AF
Clear the Carry flag.
538E
SBC HL,BC ED 42
Go down 343 bytes...
5390
DEC HL 2B
...and one more: the new top of memory.
5391
LD (4049H),HL 22 49 40
Store it.
5394
INC HL 23
HL = the place for the code.
5395
PUSH HL E5
Save it.
5396
LD DE,0009H 11 09 00
Add 09H...
5399
ADD HL,DE 19
(add DE)
539A
LD (54D8H),HL 22 D8 54
...for the CALL at 54D7H: the copy of 54DCH.
539D
POP HL E1
Restore the code address...
539E
PUSH HL E5
...and save it again.
539F
LD DE,00E9H 11 E9 00
Add E9H...
53A2
ADD HL,DE 19
(add DE)
53A3
LD (5514H),HL 22 14 55
...for the CALL at 5513H...
53A6
LD (55B7H),HL 22 B7 55
...and the CALL at 55B6H: the copy of 55BCH.
53A9
POP HL E1
Restore the code address...
53AA
PUSH HL E5
...and save it again.
53AB
LD DE,00A7H 11 A7 00
Add A7H...
53AE
ADD HL,DE 19
(add DE)
53AF
LD (54EEH),HL 22 EE 54
...for the CALL at 54EDH...
53B2
LD (5510H),HL 22 10 55
...the CALL at 550FH...
53B5
LD (5578H),HL 22 78 55
...and the CALL at 5577H: the copy of 557AH.
53B8
POP DE D1
Restore the code address into DE...
53B9
PUSH DE D5
...and save it again.
53BA
LD HL,54D3H 21 D3 54
Point HL to the code at 54D3H.
53BD
LDIR ED B0
Copy the 343 bytes (54D3H-5629H).
53BF
POP HL E1
Restore the code address...
53C0
PUSH HL E5
...and save it again.
53C1
LD DE,(536FH) ED 5B 6F 53
Fetch the device control block address.
53C5
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H...
53C8
ADD HL,BC 09
...and add it (no change).
53C9
EX DE,HL EB
HL = the control block, DE = the code.
53CA
INC HL 23
Point to the driver address...
53CB
LD (HL),E 73
...and make the copy of 54D3H the device's driver.
53CC
INC HL 23
(next byte)
53CD
LD (HL),D 72
(store D)
53CE
POP HL E1
Restore the code address...
53CF
PUSH HL E5
...and save it again.
53D0
LD DE,00A2H 11 A2 00
Add A2H: the copy of 5575H, the task block.
53D3
ADD HL,DE 19
(add DE)
53D4
LD D,H 54
DE = the task block...
53D5
LD E,L 5D
(copy L into E)
53D6
LD BC,0002H 01 02 00
...+ 2...
53D9
ADD HL,BC 09
(add BC)
53DA
EX DE,HL EB
...the copy of 5577H, the task.
53DB
LD (HL),E 73
Store it in the task block.
53DC
INC HL 23
(next byte)
53DD
LD (HL),D 72
(store D)
53DE
DEC HL 2B
HL = the task block...
53DF
EX DE,HL EB
...into DE.
53E0
LD A,09H 3E 09
Register A = 09H: task slot 9.
53E2
GOSUB to the SYS0 routine at 4410H to install the task.
53E5
POP HL E1
Restore the code address...
53E6
PUSH HL E5
...and save it.
53E7
LD DE,00E3H 11 E3 00
Add E3H: the copy of 55B6H.
53EA
ADD HL,DE 19
(add DE)
53EB
LD (4301H),HL 22 01 43
Store it as the address of the jump at 4300H...
53EE
LD A,C3H 3E C3
Load Register A with C3H (JP)...
53F0
LD (4300H),A 32 00 43
...and store it at 4300H. The SYS0 keyboard routine calls 4300H, so the refill routine runs often.
53F3
JUMP to 402DH: back to VTOS READY.

53F6H - Find a Device Control Block

DE = the two letters of the name (E first). Searches the control blocks at 4015H-402CH and then from 43C0H. Returns Z with HL = the block, or NZ with Register A = 08H (device not available).

53F6
LD HL,4015H 21 15 40
Point HL to the first control block at 4015H.
53F9
PUSH HL E5
Save it.
53FA
LD A,L 7D
Point to its name at +06H:
53FB
ADD A,06H C6 06
(add 06H)
53FD
LD L,A 6F
(into L)
53FE
LD A,(HL) 7E
Fetch the first letter.
53FF
INC L 2C
(next byte)
5400
CP E BB
Compare it with Register E.
5401
If they differ, JUMP to 540AH.
5403
LD A,(HL) 7E
Fetch the second letter.
5404
CP D BA
Compare it with Register D.
5405
If they differ, JUMP to 540AH.
5407
POP HL E1
Found: restore the address of the block.
5408
XOR A AF
Z.
5409
RET C9
RETURN.
540A
POP AF F1
Discard the saved address.
540B
INC L 2C
Next block (8 bytes on).
540C
If the address has not passed FFH, JUMP to 5412H.
540E
LD A,08H 3E 08
Not found: Register A = 08H...
5410
OR A B7
...NZ...
5411
RET C9
...RETURN.
5412
LD A,L 7D
Past the first group (402DH)?
5413
CP 2DH FE 2D
(compare with 2DH)
5415
If not, LOOP back to 53F9H.
5417
LD HL,43C0H 21 C0 43
Go on with the second group at 43C0H.
541A
LOOP back to 53F9H.

541CH - Error Exits

541C
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
541E
JUMP to the SYS0 error handler at 4409H.
5421
LD HL,542AH 21 2A 54
Point HL to DEVICE SPEC REQUIRED at 542AH.
5424
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5427
JUMP to 4030H: back to VTOS READY.
542A-543E
DEFM "DEVICE SPEC REQUIRED",0DH 44 45 56 49 43 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5424H.
543F
LD HL,5448H 21 48 54
Point HL to CAN'T -- ONLY VALID AT VTOS COMMAND LEVEL at 5448H.
5442
GOSUB to 447BH to display it.
5445
JUMP to 4030H.
5448-5471
DEFM "CAN'T -- ONLY VALID AT VTOS COMMAND LEVEL",0DH 43 41 4E 27 54 20 2D 2D 20 4F 4E 4C 59 20 56 41 4C 49 44 20 41 54 20 56 54 4F 53 20 43 4F 4D 4D 41 4E 44 20 4C 45 56 45 4C 0D
Displayed at 5442H.
5472
LD HL,547BH 21 7B 54
Point HL to PARAMETER ERROR at 547BH.
5475
GOSUB to 447BH to display it.
5478
JUMP to 4030H.
547B-548A
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 5475H.
548B-54AA
DEFS 32
Work area for the device name (read at 5213H). Not in the file.

54ABH - Default Name and Parameter Table

54AB-54AD
DEFM "XX/" 58 58 2F
The XX is replaced with the device name at 5223H.
54AE-54B1
DEFM "SPL",03H 53 50 4C 03
The default extension, and the end of the default name.
54B2-54B9
DEFM "MEM " : DEFW 52C9H 4D 45 4D 20 20 20 C9 52
MEM: operand of the LD BC at 52C8H.
54BA-54C1
DEFM "M " : DEFW 52C9H 4D 20 20 20 20 20 C9 52
M: the same.
54C2-54C9
DEFM "DISK " : DEFW 5295H 44 49 53 4B 20 20 95 52
DISK: operand of the LD BC at 5294H.
54CA-54D1
DEFM "D " : DEFW 5295H 44 20 20 20 20 20 95 52
D: the same.
54D2
DEFB 00H 00
End of the table.

54D3H - Spooler Driver (copied)

Everything from here to 5629H is copied below the top of memory and runs there. The addresses in the LD IX and CALL instructions shown as 0000H are filled in at 535EH-53B5H. This is the device's new driver: a character in Register C is stored in the current buffer; 00H is ignored.

54D3
LD A,C 79
Fetch the character.
54D4
OR A B7
Test it.
54D5
RET Z C8
If it is 00H, RETURN.
54D6
PUSH AF F5
Save it.
54D7
CALL 0000H CD 00 00
GOSUB to the copy of 54DCH (the address is filled in at 539AH) to store it.
54DA
POP AF F1
Restore it.
54DB
RET C9
RETURN.
54DC
LD IX,0000H DD 21 00 00
Point IX to the control block (filled in at 535EH).
54E0
LD L,(IX+20H) DD 6E 20
Fetch the write position: offset (+20H)...
54E3
LD H,(IX+21H) DD 66 21
...and page (+21H).
54E6
LD (HL),C 71
Store the character.
54E7
DI F3
Disable interrupts.
54E8
INC (IX+20H) DD 34 20
Move the write offset on.
54EB
If the buffer is now full, JUMP to 54F3H.
54ED
CALL 0000H CD 00 00
GOSUB to the copy of 557AH (filled in at 53AFH) to print a character if the device is ready.
54F0
EI FB
Enable interrupts.
54F1
JUMP to 553DH (which goes on to the refill routine).
54F3
LD L,(IX+24H) DD 6E 24
The buffer is full: fetch the address of the descriptor table (+24H)...
54F6
LD H,(IX+25H) DD 66 25
...(+25H).
54F9
LD A,(HL) 7E
Look for a free descriptor (link 0000H):
54FA
INC HL 23
(next byte)
54FB
OR (HL) B6
(OR the high byte)
54FC
if the link is 0000H, JUMP to 5503H.
54FE
INC HL 23
Otherwise move on 4 bytes...
54FF
INC HL 23
(next byte)
5500
INC HL 23
(next byte)
5501
...and LOOP back to 54F9H.
5503
DEC HL 2B
Point back to the start of the descriptor.
5504
PUSH HL E5
Save it.
5505
INC HL 23
Point to its page or record...
5506
INC HL 23
(next byte)
5507
LD B,(HL) 46
...fetch it into B...
5508
INC HL 23
(next byte)
5509
LD A,(HL) 7E
...and fetch the flag byte.
550A
CP FFH FE FF
Is it FFH, the end of the table?
550C
If not, JUMP to 5519H.
550E
POP HL E1
Everything is full. Discard the saved pointer.
550F
CALL 0000H CD 00 00
GOSUB to the copy of 557AH to print.
5512
EI FB
Enable interrupts.
5513
CALL 0000H CD 00 00
GOSUB to the copy of 55BCH to start the next buffer.
5516
DI F3
Disable interrupts.
5517
LOOP back to 54F3H until a descriptor is free.
5519
BIT 7,A CB 7F
Is it a disk record (bit 7)?
551B
If so, JUMP to 553FH.
551D
POP HL E1
A memory buffer: restore the descriptor address...
551E
PUSH HL E5
...and save it again.
551F
LD (HL),L 75
Mark it in use: link = its own address.
5520
LD A,H 7C
(A = H)
5521
INC HL 23
(next byte)
5522
LD (HL),A 77
(store A)
5523
LD (IX+21H),B DD 70 21
Continue writing in its page (+21H).
5526
LD L,(IX+26H) DD 6E 26
Fetch the last descriptor filled (+26H, +27H)...
5529
LD H,(IX+27H) DD 66 27
(high byte)
552C
LD (IX+2AH),L DD 75 2A
...and keep it at +2AH...
552F
LD (IX+2BH),H DD 74 2B
...+2BH.
5532
POP BC C1
Restore the new descriptor's address.
5533
LD (HL),C 71
Link the last descriptor to it...
5534
INC HL 23
(next byte)
5535
LD (HL),B 70
(store B)
5536
LD (IX+26H),C DD 71 26
...and make it the last one (+26H...
5539
LD (IX+27H),B DD 70 27
...+27H).
553C
RET C9
RETURN.
553D
JUMP to 55BCH.
553F
EI FB
A disk record. Enable interrupts.
5540
LD C,B 48
Register C = the low byte of the record number...
5541
AND 0FH E6 0F
...the high byte is in bits 0-3 of the flag byte...
5543
LD B,A 47
...into B.
5544
PUSH IX DD E5
DE = the FCB (the start of the control block).
5546
POP DE D1
(restore DE)
5547
GOSUB to the SYS0 routine at 4442H to position the spool file to the record.
554A
If that failed, JUMP to the SYS0 error handler at 4409H.
554D
LD C,(IX+26H) DD 4E 26
Fetch the last descriptor filled (+26H)...
5550
LD B,(IX+27H) DD 46 27
...(+27H).
5553
POP HL E1
Restore the new descriptor's address...
5554
PUSH HL E5
...and save it again.
5555
LD (HL),C 71
Link it back to the last descriptor...
5556
INC HL 23
(next byte)
5557
LD (HL),B 70
(store B)
5558
POP BC C1
BC = the new descriptor.
5559
LD L,(IX+2AH) DD 6E 2A
Fetch the one saved at +2AH...
555C
LD H,(IX+2BH) DD 66 2B
(high byte)
555F
LD (HL),C 71
...and link it to the new descriptor.
5560
INC HL 23
(next byte)
5561
LD (HL),B 70
(store B)
5562
LD (IX+2AH),C DD 71 2A
Keep the new descriptor at +2AH...
5565
LD (IX+2BH),B DD 70 2B
...+2BH.
5568
LD B,(IX+21H) DD 46 21
The page just filled (+21H)...
556B
LD (IX+04H),B DD 70 04
...is the buffer for the write (FCB+04H, the high byte of the buffer address).
556E
GOSUB to the SYS0 routine at 4439H to write the page to the spool file.
5571
If that failed, JUMP to 4409H.
5574
RET C9
RETURN.
5575-5576
DEFS 2
Task block of the output task: the address of the task, set at 53DBH.

5577H - Output Task (copied)

Timer task 9. Each run calls the print routine twice: once through the CALL and once by going on into it.

5577
CALL 0000H CD 00 00
GOSUB to the copy of 557AH (filled in at 53B5H).
557A
LD C,00H 0E 00
Load Register C with 00H.
557C
PUSH IX DD E5
Save IX.
557E
LD IX,4025H DD 21 25 40
Point IX to the printer control block at 4025H.
5582
CALL 0000H CD 00 00
GOSUB to the device's old driver (filled in at 5375H) with C = 00H: NZ if the device is busy.
5585
POP IX DD E1
Restore IX.
5587
RET NZ C0
If the device is busy, RETURN.
5588
LD IX,0000H DD 21 00 00
Point IX to the control block (filled in at 5361H).
558C
LD A,(IX+23H) DD 7E 23
Fetch the page being printed (+23H).
558F
OR A B7
Test it.
5590
RET Z C8
If there is none (00H), RETURN.
5591
LD H,A 67
H = the page.
5592
CP (IX+21H) DD BE 21
Is it also the page being written?
5595
If not, JUMP to 559EH.
5597
LD A,(IX+22H) DD 7E 22
Then compare the read offset...
559A
CP (IX+20H) DD BE 20
...with the write offset.
559D
RET Z C8
If they are the same, everything has been printed: RETURN.
559E
LD L,(IX+22H) DD 6E 22
L = the read offset.
55A1
LD C,(HL) 4E
Fetch the character.
55A2
PUSH IX DD E5
Save IX.
55A4
LD IX,4025H DD 21 25 40
Point IX to the printer control block at 4025H.
55A8
CALL 0000H CD 00 00
GOSUB to the old driver (filled in at 5379H) to print it.
55AB
POP IX DD E1
Restore IX.
55AD
INC (IX+22H) DD 34 22
Move the read offset on.
55B0
RET NZ C0
If the page is not finished, RETURN.
55B1
LD (IX+23H),00H DD 36 23 00
The page is finished: no page being printed.
55B5
RET C9
RETURN.

55B6H - Hook at 4300H (copied)

4300H jumps here. The refill routine runs, then the three bytes that were at 4300H (copied to 55B9H-55BBH) are executed.

55B6
CALL 0000H CD 00 00
GOSUB to the copy of 55BCH (filled in at 53A6H).
55B9-55BB
DEFS 3
The original contents of 4300H-4302H, put here at 5383H.

55BCH - Start the Next Buffer (copied)

If nothing is being printed, takes the next full buffer from the queue: a memory buffer is printed where it is; a disk record is first read back into the page of the head descriptor.

55BC
PUSH AF F5
Save AF.
55BD
LD A,(0000H) 3A 00 00
Fetch the page being printed (the address is filled in at 536BH).
55C0
OR A B7
Test it.
55C1
If a page is being printed, JUMP to 55F4H.
55C3
PUSH IX DD E5
Save IX...
55C5
PUSH HL E5
...HL...
55C6
PUSH DE D5
...DE...
55C7
PUSH BC C5
...and BC.
55C8
LD IX,0000H DD 21 00 00
Point IX to the control block (filled in at 5364H).
55CC
LD L,(IX+28H) DD 6E 28
Fetch the head of the queue (+28H)...
55CF
LD H,(IX+29H) DD 66 29
...(+29H).
55D2
PUSH HL E5
Save it.
55D3
LD C,(HL) 4E
BC = its link: the next buffer...
55D4
INC HL 23
(next byte)
55D5
LD B,(HL) 46
(fetch the byte into B)
55D6
LD HL,0002H 21 02 00
HL = that descriptor + 2...
55D9
ADD HL,BC 09
(add BC)
55DA
LD A,(HL) 7E
...its page...
55DB
INC HL 23
(next byte)
55DC
BIT 7,(HL) CB 7E
...and is it a disk record?
55DE
If so, JUMP to 55F6H.
55E0
LD (IX+23H),A DD 77 23
Print that page (+23H).
55E3
POP HL E1
Restore the old head...
55E4
LD (HL),00H 36 00
...and free it (link 0000H).
55E6
INC HL 23
(next byte)
55E7
LD (HL),00H 36 00
(store 00H)
55E9
LD (IX+28H),C DD 71 28
The next buffer becomes the head (+28H...
55EC
LD (IX+29H),B DD 70 29
...+29H).
55EF
POP BC C1
Restore BC...
55F0
POP DE D1
...DE...
55F1
POP HL E1
...HL...
55F2
POP IX DD E1
...and IX.
55F4
POP AF F1
Restore AF.
55F5
RET C9
RETURN.
55F6
LD C,A 4F
A disk record: C = the low byte...
55F7
LD A,(HL) 7E
...B = bits 0-3 of the flag byte...
55F8
AND 0FH E6 0F
(keep bits 0-3)
55FA
LD B,A 47
(into B)
55FB
PUSH IX DD E5
DE = the FCB.
55FD
POP DE D1
(restore DE)
55FE
GOSUB to 4442H to position the spool file to the record.
5601
If that failed, JUMP to 4409H.
5604
POP HL E1
Restore the head descriptor...
5605
PUSH HL E5
...and save it again.
5606
INC HL 23
Point to its page...
5607
INC HL 23
(next byte)
5608
LD B,(HL) 46
...fetch it...
5609
LD (IX+04H),B DD 70 04
...and make it the buffer (FCB+04H).
560C
GOSUB to the SYS0 routine at 4436H to read the record into that page.
560F
If that failed, JUMP to 4409H.
5612
POP HL E1
Restore the head descriptor...
5613
PUSH HL E5
...and save it again.
5614
LD A,(HL) 7E
HL = its link (the disk descriptor)...
5615
INC HL 23
(next byte)
5616
LD H,(HL) 66
(fetch the byte into H)
5617
LD L,A 6F
(into L)
5618
LD C,(HL) 4E
...fetch the disk descriptor's link and free it:
5619
LD (HL),00H 36 00
(store 00H)
561B
INC HL 23
(next byte)
561C
LD B,(HL) 46
(fetch the byte into B)
561D
LD (HL),00H 36 00
(store 00H)
561F
POP HL E1
Restore the head descriptor...
5620
LD (HL),C 71
...and link it to the buffer after the disk descriptor.
5621
INC HL 23
(next byte)
5622
LD (HL),B 70
(store B)
5623
INC HL 23
Its page...
5624
LD B,(HL) 46
(fetch the byte into B)
5625
LD (IX+23H),B DD 70 23
...is now the page being printed (+23H).
5628
JUMP to 55EFH to restore the registers.

562AH - FCB and Control Block

Copied below the top of memory at 535AH; the spooler code finds it through IX.

562A-5649
DEFS 32
FCB of the spool file (IX+00H-1FH).
564A-5653
DEFS 10
IX+20H-21H write position (offset, page); +22H-23H read position (offset, page; page 00H when nothing is being printed); +24H-25H the descriptor table; +26H-27H the last buffer filled; +28H-29H the head of the queue. Set at 52F5H-5347H.
5654-5655
DEFW 0000H 00 00
IX+2AH-2BH: the descriptor before the last one filled.

APPEND (31H) / COPY (32H) - Offset 1DFD

One member serves both commands. APPEND (ISAM 31H, entry 5200H; APPEND source destination) adds the source file to the end of the destination file. COPY (ISAM 32H, entry 5270H; COPY source destination) copies a file, or copies between a file and a device (*PR, *KI and so on) one byte at a time. Parts of the destination that are left out (for example COPY FILE/CMD :1) are taken from the source: name, extension and password. Files are copied a sector at a time through the memory from 5500H up to the top of memory. Between devices, SHIFT and @ pause and BREAK stops. The member loads at 5200H-549CH (669 bytes); the source FCB (549DH) and destination FCB (54BDH) lie just past it.

5200H - APPEND Command (ISAM 31H)

HL points to the text after APPEND.

5200
GOSUB to 5349H to set the last buffer page from the top of memory.
5203
LD DE,549DH 11 9D 54
Point DE to the source FCB at 549DH.
5206
GOSUB to the SYS0 routine at 441CH to read the source filespec into it.
5209
If there is none (NZ), JUMP to 5459H to display FILE SPEC REQUIRED.
520C
LD DE,54BDH 11 BD 54
Point DE to the destination FCB at 54BDH.
520F
GOSUB to 441CH to read the destination filespec.
5212
If it was read (Z), JUMP to 521AH.
5214
DEC HL 2B
Otherwise (for example a drive alone, :1) step back to the character that stopped it...
5215
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H.
5218
LDIR ED B0
...and copy the text as it is into the FCB; the missing parts are filled in at 5228H.
521A
LD A,(54BDH) 3A BD 54
Fetch the first character of the destination.
521D
CP 2AH FE 2A
A device (*)...
521F
...cannot be appended to: JUMP to 5459H.
5222
LD HL,549DH 21 9D 54
Point HL to the source filespec.
5225
LD DE,54BDH 11 BD 54
Point DE to the destination filespec.
5228
GOSUB to 53CDH to fill in what the destination leaves out.
522B
LD B,00H 06 00
Load Register B with 00H: record length 256.
522D
LD HL,5500H 21 00 55
Point HL to the buffer at 5500H.
5230
GOSUB to the SYS0 routine at 4424H to open the destination (DE); it must exist.
5233
If that failed (NZ), JUMP to the error exit at 5454H.
5236
LD B,00H 06 00
Load Register B with 00H.
5238
LD DE,549DH 11 9D 54
Point DE to the source FCB.
523B
LD HL,5500H 21 00 55
Point HL to the buffer at 5500H.
523E
GOSUB to 4424H to open the source.
5241
If that failed (NZ), JUMP to 5454H.
5244
LD A,(54C5H) 3A C5 54
Fetch the destination's EOF byte (FCB+08H at 54C5H).
5247
OR A B7
Test it.
5248
If the destination ends on a sector boundary, JUMP to 5259H to append whole sectors.
524A
LD DE,54BDH 11 BD 54
Otherwise point DE to the destination FCB...
524D
...GOSUB to the SYS0 routine at 4448H to position it at its end...
5250
LD HL,5600H 21 00 56
...give it the buffer at 5600H...
5253
LD (54C0H),HL 22 C0 54
...(FCB+03H at 54C0H)...
5256
...and JUMP to 5391H to append a byte at a time.
5259
LD HL,(54C9H) 2A C9 54
Fetch the destination's ending record number (FCB+0CH at 54C9H).
525C
PUSH HL E5
Save it.
525D
LD HL,(54A9H) 2A A9 54
Fetch the source's ending record number (FCB+0CH at 54A9H)...
5260
ADD HL,BC 09
...and add BC (as it was left by the open at 523EH).
5261
LD B,H 44
BC = the result...
5262
LD C,L 4D
(low byte)
5263
...GOSUB to 535BH to allocate the destination up to that record.
5266
POP HL E1
Restore the destination's ending record number...
5267
LD (54C9H),HL 22 C9 54
...and put it back.
526A
GOSUB to 4448H to position the destination at its end.
526D
JUMP to 52DCH to copy the source sector by sector.

5270H - COPY Command (ISAM 32H)

HL points to the text after COPY.

5270
GOSUB to 5349H to set the last buffer page.
5273
LD DE,549DH 11 9D 54
Point DE to the source FCB.
5276
GOSUB to 441CH to read the source filespec.
5279
If there is none (NZ), JUMP to 5459H.
527C
LD DE,54BDH 11 BD 54
Point DE to the destination FCB.
527F
GOSUB to 441CH to read the destination filespec.
5282
If it was read (Z), JUMP to 528AH.
5284
DEC HL 2B
Otherwise step back one character...
5285
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H.
5288
LDIR ED B0
...and copy the text as it is into the FCB.
528A
LD A,(549DH) 3A 9D 54
Fetch the first character of the source.
528D
CP 2AH FE 2A
Is it a device (*)?
528F
If so, JUMP to 5375H to copy a byte at a time.
5292
LD A,(54BDH) 3A BD 54
Fetch the first character of the destination.
5295
CP 2AH FE 2A
Is it a device?
5297
If so, JUMP to 5375H.
529A
LD HL,549DH 21 9D 54
Point HL to the source filespec.
529D
LD DE,54BDH 11 BD 54
Point DE to the destination filespec.
52A0
GOSUB to 53CDH to fill in what the destination leaves out.
52A3
LD B,00H 06 00
Load Register B with 00H: record length 256.
52A5
LD DE,549DH 11 9D 54
Point DE to the source FCB.
52A8
LD HL,5500H 21 00 55
Point HL to the buffer at 5500H.
52AB
GOSUB to 4424H to open the source.
52AE
If that failed (NZ), JUMP to 5454H.
52B1
LD B,00H 06 00
Load Register B with 00H.
52B3
LD DE,54BDH 11 BD 54
Point DE to the destination FCB.
52B6
LD HL,5500H 21 00 55
Point HL to the buffer at 5500H.
52B9
GOSUB to the SYS0 routine at 4420H to open the destination, creating it if necessary.
52BC
If that failed (NZ), JUMP to 5454H.
52BF
LD HL,(54A3H) 2A A3 54
Fetch the source's drive and directory entry code (FCB+06H-07H at 54A3H).
52C2
LD DE,(54C3H) ED 5B C3 54
Fetch the destination's (54C3H).
52C6
XOR A AF
Clear the Carry flag.
52C7
SBC HL,DE ED 52
Compare them.
52C9
If they are the same file, JUMP to 5475H to display DESTINATION FILE SPEC REQUIRED.
52CC
LD BC,(54A9H) ED 4B A9 54
Fetch the source's ending record number.
52D0
GOSUB to 535BH to allocate the destination up to that record in one go.
52D3
LD HL,0000H 21 00 00
HL = 0000H...
52D6
LD (54C9H),HL 22 C9 54
...the destination's ending record number: it is empty again.
52D9
GOSUB to the SYS0 routine at 443FH to position the destination back to record 0.

52DCH - Copy Sector by Sector

Reads source sectors into the pages from 5500H until the last buffer page, then writes them all to the destination, and repeats.

52DC
LD HL,5500H 21 00 55
Point HL to the first buffer page at 5500H.
52DF
LD (54A0H),HL 22 A0 54
Make it the source's buffer (FCB+03H at 54A0H).
52E2
LD DE,549DH 11 9D 54
Point DE to the source FCB.
52E5
GOSUB to the SYS0 routine at 4436H to read the next sector.
52E8
If it was read (Z), JUMP to 52F5H.
52EA
CP 1CH FE 1C
Error 1CH (end of file)...
52EC
...means the source is finished: JUMP to 5312H.
52EE
CP 1DH FE 1D
So does error 1DH (record number out of range).
52F0
If so, JUMP to 5312H.
52F2
Any other error: JUMP to 5454H.
52F5
INC H 24
Next page.
52F6
LD A,H 7C
(A = H)
52F7
CP 60H FE 60
Is it the last buffer page (the operand at 52F8H, set at 5350H)?
52F9
If not, LOOP back to 52DFH to read another sector.
52FB
LD HL,5500H 21 00 55
All pages are full: point HL to the first page...
52FE
LD (54C0H),HL 22 C0 54
...make it the destination's buffer (FCB+03H at 54C0H)...
5301
LD DE,54BDH 11 BD 54
...point DE to the destination FCB...
5304
...and GOSUB to the SYS0 routine at 4439H to write it.
5307
If that failed (NZ), JUMP to 5454H.
530A
INC H 24
Next page.
530B
LD A,H 7C
(A = H)
530C
CP 60H FE 60
Is it the last buffer page (the operand at 530DH)?
530E
If not, LOOP back to 52FEH.
5310
LOOP back to 52DCH to read the next group of sectors.
5312
End of the source: GOSUB to 532CH to write the pages read so far.
5315
LD HL,(54A5H) 2A A5 54
Fetch the source's EOF byte and record length (FCB+08H-09H at 54A5H)...
5318
LD (54C5H),HL 22 C5 54
...and give them to the destination (54C5H).
531B
JUMP to 5320H.
531D
GOSUB to 532CH. (Nothing jumps to this instruction.)
5320
LD DE,54BDH 11 BD 54
Point DE to the destination FCB.
5323
GOSUB to the SYS0 routine at 4428H to close it.
5326
If that failed (NZ), JUMP to 5454H.
5329
JUMP to 402DH: back to VTOS READY.

532CH - Write the Pages Read

H = the page after the last one read. Writes the pages from 5500H up to it.

532C
LD A,H 7C
Fetch the page.
532D
CP 55H FE 55
If nothing has been read (still 55H)...
532F
RET Z C8
...RETURN.
5330
CP 60H FE 60
At the last buffer page (the operand at 5331H) they have already been written...
5332
RET Z C8
...so RETURN.
5333
LD B,H 44
Register B = the page to stop at.
5334
LD HL,5500H 21 00 55
Point HL to the first page.
5337
LD (54C0H),HL 22 C0 54
Make it the destination's buffer.
533A
LD DE,54BDH 11 BD 54
Point DE to the destination FCB.
533D
GOSUB to 4439H to write it.
5340
If that failed (NZ), JUMP to 5454H.
5343
INC H 24
Next page.
5344
LD A,H 7C
(A = H)
5345
CP B B8
Is it the page to stop at?
5346
If not, LOOP back to 5337H.
5348
RET C9
RETURN.

5349H - Set the Last Buffer Page

The buffers run from 5500H up to the page below the one that holds the top of memory. The page number is stored in the three CP instructions that test for it.

5349
PUSH HL E5
Save HL.
534A
LD HL,(4049H) 2A 49 40
Fetch the top of memory...
534D
INC HL 23
...plus 1...
534E
DEC H 25
...one page lower.
534F
LD A,H 7C
Register A = that page.
5350
LD (52F8H),A 32 F8 52
Store it at 52F8H...
5353
LD (530DH),A 32 0D 53
...530DH...
5356
LD (5331H),A 32 31 53
...and 5331H.
5359
POP HL E1
Restore HL.
535A
RET C9
RETURN.

535BH - Allocate the Destination

BC = a record number. Positions the destination to it and writes a sector of E5H, so that the DOS allocates all the space up to it.

535B
LD DE,54BDH 11 BD 54
Point DE to the destination FCB.
535E
GOSUB to the SYS0 routine at 4442H to position it.
5361
LD HL,5500H 21 00 55
Point HL to the buffer at 5500H.
5364
LD DE,5501H 11 01 55
Point DE to 5501H.
5367
LD BC,00FFH 01 FF 00
Load Register Pair BC with 00FFH.
536A
LD (HL),E5H 36 E5
Store E5H in the first byte...
536C
LDIR ED B0
...and copy it along the page.
536E
LD DE,54BDH 11 BD 54
Point DE to the destination FCB.
5371
GOSUB to 4439H to write the sector (an error is not checked).
5374
RET C9
RETURN.

5375H - Copy a Byte at a Time

Used when the source or the destination is a device, and by APPEND when the destination does not end on a sector boundary.

5375
LD B,00H 06 00
Load Register B with 00H: record length 256.
5377
LD DE,549DH 11 9D 54
Point DE to the source.
537A
LD HL,5500H 21 00 55
Point HL to the buffer at 5500H.
537D
GOSUB to 4424H to open it.
5380
If that failed (NZ), JUMP to 5454H.
5383
LD B,00H 06 00
Load Register B with 00H.
5385
LD DE,54BDH 11 BD 54
Point DE to the destination.
5388
LD HL,5600H 21 00 56
Point HL to the buffer at 5600H.
538B
GOSUB to 4420H to open it, creating a file if necessary.
538E
If that failed (NZ), JUMP to 5454H.
5391
LD DE,549DH 11 9D 54
Point DE to the source.
5394
LD A,(DE) 1A
Fetch its first byte.
5395
BIT 7,A CB 7F
Bit 7 is set in the FCB of an open file.
5397
If the source is a device, JUMP to 53ACH.
5399
GOSUB to the ROM routine at 0013H to read a byte from the file.
539C
If there is one (Z), JUMP to 53B7H to write it.
539E
CP 1CH FE 1C
Error 1CH (end of file)...
53A0
...means it is finished: JUMP to 5320H to close the destination.
53A3
Any other error: JUMP to 5454H.
53A6
GOSUB to 5428H to check for a pause or BREAK.
53A9
If BREAK was pressed (NZ), JUMP to 5320H.
53AC
GOSUB to 0013H to read a byte from the device.
53AF
OR A B7
Test it.
53B0
If there was none, LOOP back to 53A6H to wait.
53B2
CP 01H FE 01
Is it BREAK (01H)?
53B4
If so, JUMP to 5320H to finish.
53B7
LD DE,54BDH 11 BD 54
Point DE to the destination.
53BA
GOSUB to the ROM routine at 001BH to write the byte.
53BD
If it was written (Z), JUMP to 53C5H.
53BF
EX DE,HL EB
Otherwise look at the destination:
53C0
BIT 7,(HL) CB 7E
if it is a file (bit 7)...
53C2
EX DE,HL EB
(swap DE and HL)
53C3
...JUMP to 53A3H: an error. A device error is ignored.
53C5
GOSUB to 5428H to check for a pause or BREAK.
53C8
If BREAK was pressed (NZ), JUMP to 5320H.
53CB
LOOP back to 5391H for the next byte.

53CDH - Complete the Destination Filespec

HL = the source filespec, DE = the destination. If the destination has no name, the source's name is put in front; if it has no extension or password, the source's are inserted.

53CD
PUSH DE D5
Save the destination pointer.
53CE
LD A,(DE) 1A
Fetch its first character.
53CF
CP 41H FE 41
Below A (no name)?
53D1
Then GOSUB to 5408H to insert the source's name.
53D4
LD B,2FH 06 2F
Register B = /: the extension.
53D9
LD B,2EH 06 2E
Register B = .: the password.
53DE
POP DE D1
Restore the destination pointer.
53DF
RET C9
RETURN.
53E0
INC DE 13
Move on in the destination.
53E1
LD A,(DE) 1A
Fetch a character of the destination.
53E2
CP B B8
Is it the separator in Register B?
53E3
If so, JUMP to 53F3H: this part is already there.
53E5
CP 41H FE 41
A letter...
53E7
...LOOP back to 53E0H.
53E9
CP 30H FE 30
Below 0...
53EB
...the part is missing: JUMP to 53F5H.
53ED
CP 3AH FE 3A
A digit...
53EF
...LOOP back to 53E0H.
53F1
Anything else: the part is missing.
53F3
INC DE 13
Move past the separator.
53F4
RET C9
RETURN.
53F5
PUSH HL E5
Save the source pointer.
53F6
LD A,(HL) 7E
Look through the source for the same separator:
53F7
INC HL 23
(next byte)
53F8
CP 03H FE 03
Is it 03H?
53FA
If so, JUMP to 5406H.
53FC
CP 0DH FE 0D
Or a carriage return?
53FE
If so, JUMP to 5406H: the source has no such part.
5400
CP B B8
Is it the separator?
5401
If not, LOOP back to 53F6H.
5403
GOSUB to 5414H to insert the separator and the source's part after it into the destination.
5406
POP HL E1
Restore the source pointer.
5407
RET C9
RETURN.
5408
LD A,(HL) 7E
Insert letters and digits from the source (HL) into the destination (DE): fetch one.
5409
CP 30H FE 30
Below 0...
540B
RET C D8
...ends it: RETURN.
540C
CP 3AH FE 3A
A digit?
540E
Then JUMP to 5413H to take it.
5410
CP 41H FE 41
Below A...
5412
RET C D8
...ends it: RETURN.
5413
INC HL 23
Move past it in the source.
5414
PUSH HL E5
Save the source pointer.
5415
LD H,D 62
HL = the destination position.
5416
LD L,E 6B
(low byte)
5417
LD C,(HL) 4E
Take out the character there...
5418
LD (HL),A 77
...and put the new one in its place.
5419
INC HL 23
Move on.
541A
LD A,C 79
The character taken out is to be put in the next place...
541B
CP 03H FE 03
...until the terminator (03H)...
541D
(if so, JUMP to 5423H)
541F
CP 0DH FE 0D
...or carriage return has been moved.
5421
LOOP back to 5417H.
5423
LD (HL),A 77
Store the terminator at the end.
5424
POP HL E1
Restore the source pointer.
5425
INC DE 13
Move past the inserted character.
5426
LOOP back to 5408H for the next one.

5428H - Pause and BREAK Check

Returns NZ if BREAK is pressed. SHIFT and @ pause until another key is pressed. Does nothing while a chain (DO) file is running.

5428
LD A,(430FH) 3A 0F 43
Fetch the system flags.
542B
AND 20H E6 20
Keep bit 5...
542D
XOR 20H EE 20
...and invert it.
542F
RET Z C8
If a chain file is running, RETURN with Z.
5430
LD A,(3840H) 3A 40 38
Read keyboard row 6.
5433
AND 04H E6 04
Keep bit 2, BREAK.
5435
RET NZ C0
If BREAK is pressed, RETURN with NZ.
5436
LD A,(3801H) 3A 01 38
Read keyboard row 0.
5439
AND 01H E6 01
Keep bit 0, @.
543B
RET Z C8
If @ is not pressed, RETURN with Z.
543C
LD A,(3880H) 3A 80 38
Read keyboard row 7.
543F
AND 01H E6 01
Keep bit 0, SHIFT.
5441
RET Z C8
If SHIFT is not pressed, RETURN with Z.
5442
LD A,(3840H) 3A 40 38
Read keyboard row 6.
5445
AND 04H E6 04
Keep bit 2, BREAK.
5447
RET NZ C0
If BREAK is pressed, RETURN with NZ.
5448
GOSUB to the ROM routine at 002BH to scan the keyboard.
544B
OR A B7
Test the key.
544C
If there is none, LOOP back to 5442H.
544E
CP 60H FE 60
Is it 60H (SHIFT and @ again)?
5450
If so, LOOP back to 5442H.
5452
XOR A AF
Any other key: Z...
5453
RET C9
...RETURN.

5454H - Error Exits

5454
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
5456
JUMP to the SYS0 error handler at 4409H.
5459
LD HL,5462H 21 62 54
Point HL to FILE SPEC REQUIRED at 5462H.
545C
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
545F
JUMP to 4030H: back to VTOS READY.
5462-5474
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 545CH.
5475
LD HL,547EH 21 7E 54
Point HL to DESTINATION FILE SPEC REQUIRED at 547EH.
5478
GOSUB to 447BH to display it.
547B
JUMP to 4030H.
547E-549C
DEFM "DESTINATION FILE SPEC REQUIRED",0DH 44 45 53 54 49 4E 41 54 49 4F 4E 20 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5478H.

ISAM 33H - BUILD - Offset 20A9

BUILD (BUILD filespec) creates a new text file from lines typed at the keyboard; it refuses a file that already exists. BREAK on an empty line ends the input. If the extension is KSM (a keystroke multiply file), each line is prompted with its letter, A=> to Z=>, and input ends after Z. The lines are collected from 5400H upward and written to the file at the end, each ending with a carriage return. The member loads at 5200H-52CBH (204 bytes); the FCB (52CCH), the file buffer (5300H) and the text (5400H) lie past it.

5200H - BUILD Command

HL points to the text after BUILD.

5200
LD DE,52CCH 11 CC 52
Point DE to the FCB at 52CCH.
5203
GOSUB to the SYS0 routine at 441CH to read the filespec into it.
5206
If there is none (NZ), JUMP to 5293H to display FILE SPEC REQUIRED.
5209
LD HL,52CCH 21 CC 52
Point HL to the filespec.
520C
LD A,(HL) 7E
Fetch a character.
520D
INC HL 23
Move on.
520E
CP 0DH FE 0D
At the carriage return...
5210
...there is no extension: JUMP to 522CH.
5212
CP 2FH FE 2F
Is it /?
5214
If not, LOOP back to 520CH.
5216
LD A,(HL) 7E
First letter of the extension...
5217
INC HL 23
(next byte)
5218
CP 4BH FE 4B
...K?
521A
If not, JUMP to 522CH.
521C
LD A,(HL) 7E
Second letter...
521D
INC HL 23
(next byte)
521E
CP 53H FE 53
...S?
5220
If not, JUMP to 522CH.
5222
LD A,(HL) 7E
Third letter...
5223
CP 4DH FE 4D
...M?
5225
If not, JUMP to 522CH.
5227
LD A,FFH 3E FF
Load Register A with FFH...
5229
LD (523EH),A 32 3E 52
...and store it at 523EH: KSM mode.
522C
LD HL,5300H 21 00 53
Point HL to the file buffer at 5300H.
522F
LD B,00H 06 00
Load Register B with 00H: record length 256.
5231
GOSUB to the SYS0 routine at 4420H to open the file, creating it if it does not exist.
5234
If that failed (NZ), JUMP to the error exit at 528EH.
5237
No Carry means the file already existed: JUMP to 52AFH to display FILE ALREADY EXISTS.
523A
LD HL,5400H 21 00 54
Point HL to the text area at 5400H.
523D
LD A,00H 3E 00
Load Register A with the KSM flag (the operand at 523EH).
523F
OR A B7
Test it.
5240
If this is not a KSM file, JUMP to 5260H.
5242
LD A,00H 3E 00
Load Register A with the line counter (the operand at 5243H)...
5244
INC A 3C
...add 1...
5245
LD (5243H),A 32 43 52
...and store it.
5248
CP 1BH FE 1B
After the 26th line (Z)...
524A
...input ends: JUMP to 5272H.
524C
ADD A,40H C6 40
Make the letter...
524E
...and GOSUB to the ROM routine at 0033H to display it.
5251
LD A,3DH 3E 3D
Load Register A with =...
5253
...and display it.
5256
LD A,3EH 3E 3E
Load Register A with >...
5258
...and display it.
525B
LD A,20H 3E 20
Load Register A with a space...
525D
...and display it.
5260
LD B,FFH 06 FF
Load Register B with FFH: up to 255 characters.
5262
GOSUB to the ROM routine at 0040H to read a line into (HL). Register B = the number of characters.
5265
If BREAK was pressed (Carry), JUMP to 526EH.
5267
LD C,B 48
C = the length...
5268
LD B,00H 06 00
(B = 00H)
526A
ADD HL,BC 09
...HL = past the line...
526B
INC HL 23
...and its carriage return.
526C
LOOP back to 523DH for the next line.
526E
LD A,B 78
BREAK: were any characters typed?
526F
OR A B7
(test the count)
5270
If so, JUMP to 5267H to keep them as a line.
5272
LD (HL),03H 36 03
End of the text: store 03H after it.
5274
LD HL,5400H 21 00 54
Point HL to the start of the text.
5277
LD DE,52CCH 11 CC 52
Point DE to the FCB.
527A
LD A,(HL) 7E
Fetch a byte.
527B
INC HL 23
Move on.
527C
CP 03H FE 03
Is it the 03H at the end?
527E
If so, JUMP to 5287H.
5280
GOSUB to the ROM routine at 001BH to write it to the file.
5283
If that failed (NZ), JUMP to 528EH.
5285
LOOP back to 527AH.
5287
GOSUB to the SYS0 routine at 4428H to close the file.
528A
If that worked (Z), JUMP to 402DH: back to VTOS READY.
528D
NOP 00
(a spare byte; execution falls through to the error exit)

528EH - Error Exits

528E
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
5290
JUMP to the SYS0 error handler at 4409H.
5293
LD HL,529CH 21 9C 52
Point HL to FILE SPEC REQUIRED at 529CH.
5296
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5299
JUMP to 4030H: back to VTOS READY.
529C-52AE
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5296H.
52AF
LD HL,52B8H 21 B8 52
Point HL to FILE ALREADY EXISTS at 52B8H.
52B2
GOSUB to 447BH to display it.
52B5
JUMP to 4030H.
52B8-52CB
DEFM "FILE ALREADY EXISTS",0DH 46 49 4C 45 20 41 4C 52 45 41 44 59 20 45 58 49 53 54 53 0D
Displayed at 52B2H.

ISAM 41H - LIST and PRINT - Offset 217C

LIST (ISAM 41H, entry 5200H) shows a file on the display and PRINT (ISAM 42H, entry 5206H) sends it to the printer. A text file is shown line by line, starting at LINE=n; NUM puts a five-digit line number in front of each line. HEX shows the file in hexadecimal and ASCII, 16 bytes to a line, record by record, starting at record REC=n, with records of LRL=n bytes (default 256). The default extension is TXT, but a file without an extension is also found. SHIFT and @ pause and BREAK stops. The member loads at 5200H-5517H (792 bytes); the 16-byte hex line buffer (5518H), the FCB (5528H), a copy of the filespec (5548H) and the file buffer (5600H) lie past it.

5200H - LIST and PRINT Commands

HL points to the text after the command name.

5200
XOR A AF
LIST: Register A = 00H...
5201
LD DE,401DH 11 1D 40
...and the output device is the display, whose control block is at 401DH.
5204
JUMP to 520BH.

5206H - PRINT Command (ISAM 42H)

The same as LIST, but the output goes to the printer.

5206
LD A,FFH 3E FF
PRINT: Register A = FFH...
5208
LD DE,4025H 11 25 40
...and the output device is the printer (4025H).
520B
LD (5380H),A 32 80 53
Store the flag at 5380H (the operand of the LD A at 537FH): it selects the layout of the HEX lines.
520E
PUSH DE D5
Keep the output device on the stack for the whole command.
520F
LD BC,0000H 01 00 00
BC = 0000H...
5212
LD (52ADH),BC ED 43 AD 52
...clear the NUM value (5282H is LINE; this is the operand at 52ADH)...
5216
LD (527AH),BC ED 43 7A 52
...the HEX value (527AH)...
521A
LD (5329H),BC ED 43 29 53
...and the LRL value (5329H).
521E
LD BC,0001H 01 01 00
BC = 0001H...
5221
LD (5282H),BC ED 43 82 52
...the default LINE value (5282H).
5225
LD DE,5528H 11 28 55
Point DE to the FCB at 5528H.
5228
GOSUB to the SYS0 routine at 441CH to read the filespec.
522B
If there is none (NZ), JUMP to 54A3H to display FILE SPEC REQUIRED.
522E
LD A,(DE) 1A
Fetch the first character.
522F
CP 2AH FE 2A
A device (*)...
5231
...is not accepted: JUMP to 54A3H.
5234
LD DE,54EFH 11 EF 54
Point DE to the parameter table at 54EFH.
5237
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
523A
If a parameter was not recognized (NZ), JUMP to 54BFH to display PARAMETER ERROR.
523D
LD BC,0020H 01 20 00
Load Register Pair BC with 0020H.
5240
LD DE,5548H 11 48 55
Point DE to 5548H...
5243
LD HL,5528H 21 28 55
...and HL to the FCB...
5246
LDIR ED B0
...and keep a copy of the filespec.
5248
LD DE,5528H 11 28 55
Point DE to the FCB.
524B
LD HL,54ECH 21 EC 54
Point HL to the default extension TXT at 54ECH.
524E
GOSUB to the SYS0 routine at 4473H to add it if there is no extension.
5251
LD A,(5329H) 3A 29 53
Fetch the LRL value...
5254
LD B,A 47
...as the record length.
5255
LD HL,5600H 21 00 56
Point HL to the file buffer at 5600H.
5258
GOSUB to the SYS0 routine at 4424H to open the file.
525B
If it was opened (Z), JUMP to 5279H.
525E
LD BC,0020H 01 20 00
Otherwise try again without the default extension: BC = 0020H...
5261
LD DE,5528H 11 28 55
Point DE to the FCB...
5264
LD HL,5548H 21 48 55
...and HL to the saved filespec...
5267
LDIR ED B0
...copy the filespec back.
5269
LD A,(5329H) 3A 29 53
Fetch the LRL value...
526C
LD B,A 47
(into B)
526D
LD DE,5528H 11 28 55
Point DE to the FCB.
5270
LD HL,5600H 21 00 56
Point HL to the file buffer.
5273
GOSUB to 4424H to open the file.
5276
If that failed (NZ), JUMP to the error exit at 549EH.
5279
LD BC,0000H 01 00 00
Load BC with the HEX value (the operand at 527AH).
527C
LD A,B 78
Test it...
527D
OR C B1
(OR the low byte)
527E
...and if HEX was given, JUMP to 530EH.

5281H - List a Text File

5281
LD BC,0000H 01 00 00
Load BC with the LINE value (the operand at 5282H, 0001H by default).
5284
DEC BC 0B
Lines to skip = LINE - 1.
5285
LD A,B 78
(A = B)
5286
OR C B1
(OR the other byte)
5287
If there are none, JUMP to 5298H.
5289
GOSUB to the ROM routine at 0013H to read a byte from the file.
528C
If that failed (NZ), JUMP to 549EH.
528F
CP 0DH FE 0D
Is it the carriage return that ends a line?
5291
If not, LOOP back to 5289H.
5293
DEC BC 0B
Count the line.
5294
LD A,B 78
(A = B)
5295
OR C B1
(OR the other byte)
5296
LOOP back to 5289H until all have been skipped.
5298
LD HL,(5282H) 2A 82 52
Fetch the LINE value...
529B
LD BC,54D8H 01 D8 54
...point BC to the number field at 54D8H...
529E
...and GOSUB to 542BH to write it there as five digits.
52A1
LD DE,5528H 11 28 55
Point DE to the FCB.
52A4
GOSUB to 0013H to read the first byte of a line.
52A7
At the end of the file (NZ), JUMP to 52F6H.
52A9
LD (52C2H),A 32 C2 52
Keep it at 52C2H (the operand of the LD A at 52C1H).
52AC
LD BC,0000H 01 00 00
Load BC with the NUM value (the operand at 52ADH).
52AF
LD A,B 78
Test it...
52B0
OR C B1
(OR the low byte)
52B1
...and if NUM was not given, JUMP to 52C1H.
52B3
LD HL,54D8H 21 D8 54
Point HL to the line number at 54D8H.
52B6
POP DE D1
Fetch the output device...
52B7
PUSH DE D5
...(and keep it on the stack).
52B8
GOSUB to the SYS0 routine at 4479H to send the line number to it.
52BB
LD HL,54D8H 21 D8 54
Point HL to the line number...
52BE
...and GOSUB to 5461H to add 1 to it.
52C1
LD A,00H 3E 00
Load Register A with the first byte of the line (the operand at 52C2H).
52C3
CP 0DH FE 0D
An empty line?
52C5
Then JUMP to 52E3H.
52C7
POP DE D1
Fetch the output device.
52C8
PUSH DE D5
(save DE)
52C9
PUSH AF F5
Save the byte.
52CA
AND 7FH E6 7F
Clear bit 7...
52CC
...and GOSUB to the ROM routine at 001BH to send it.
52CF
POP AF F1
Restore the byte.
52D0
BIT 7,A CB 7F
If it had bit 7 set...
52D2
...GOSUB to 5472H to check for a pause or BREAK.
52D5
If BREAK was pressed (NZ), JUMP to 52EDH.
52D7
LD DE,5528H 11 28 55
Point DE to the FCB.
52DA
GOSUB to 0013H to read the next byte.
52DD
At the end of the file (NZ), JUMP to 52F6H.
52DF
CP 0DH FE 0D
The end of the line?
52E1
If not, LOOP back to 52C7H.
52E3
POP DE D1
Fetch the output device.
52E4
PUSH DE D5
(save DE)
52E5
GOSUB to 001BH to send the carriage return.
52E8
GOSUB to 5472H to check for a pause or BREAK.
52EB
If there was no BREAK, LOOP back to 52A1H for the next line.
52ED
POP DE D1
BREAK: fetch the output device...
52EE
LD A,0DH 3E 0D
...and send a carriage return.
52F0
(send it)
52F3
JUMP to 4030H: back to VTOS READY.
52F6
POP DE D1
End of the file (or an error). Fetch the output device.
52F7
PUSH AF F5
Save the error code.
52F8
LD A,0DH 3E 0D
Send a carriage return.
52FA
(send it)
52FD
POP AF F1
Restore the error code.
52FE
CP 1CH FE 1C
Error 1CH (end of file)...
5300
...is the normal end: JUMP to 530BH.
5303
CP 1DH FE 1D
So is 1DH (record number out of range).
5305
If so, JUMP to 530BH.
5308
Any other error: JUMP to 549EH.
530B
JUMP to 402DH: back to VTOS READY.

530EH - Hexadecimal Listing

Each record starts with a line rrrrr:oo = (record number, offset in hex) followed by the bytes; each later line of the record starts with the next offset.

530E
LD BC,0000H 01 00 00
Load BC with the REC value (the operand at 530FH).
5311
LD DE,5528H 11 28 55
Point DE to the FCB.
5314
GOSUB to the SYS0 routine at 4442H to position the file to that record.
5317
If that failed (NZ), JUMP to 549EH.
531A
NOP 00
(a spare byte)
531B
LD HL,(530FH) 2A 0F 53
Fetch the REC value...
531E
LD BC,54E0H 01 E0 54
...point BC to the record number at 54E0H...
5321
...and GOSUB to 542BH to write it as five digits.
5324
XOR A AF
Register A = 00H...
5325
LD (532CH),A 32 2C 53
...the offset within the record (the operand at 532CH).
5328
LD BC,0000H 01 00 00
Load BC with the LRL value (the operand at 5329H): C = the bytes in a record (00H = 256), B = 00H.
532B
LD A,00H 3E 00
Load Register A with the offset (the operand at 532CH).
532D
LD HL,54E6H 21 E6 54
Point HL to 54E6H...
5330
...and GOSUB to the SYS0 routine at 4DECH to write the offset there in hexadecimal.
5333
LD HL,54E0H 21 E0 54
Point HL to the line start rrrrr:oo = at 54E0H.
5336
POP DE D1
Fetch the output device...
5337
PUSH DE D5
(save DE)
5338
...and GOSUB to 4479H to send it.
533B
LD A,(532CH) 3A 2C 53
Move the offset on by 16:
533E
ADD A,10H C6 10
(add 10H)
5340
LD (532CH),A 32 2C 53
(store it)
5343
LD B,10H 06 10
Register B = 16 bytes to go on this line.
5345
LD HL,5518H 21 18 55
Point HL to the ASCII buffer at 5518H.
5348
LD DE,5528H 11 28 55
Point DE to the FCB.
534B
GOSUB to 0013H to read a byte.
534E
If there was one (Z), JUMP to 535BH.
5350
PUSH AF F5
Save the error.
5351
CP 1CH FE 1C
Is it end of file (1CH)?
5353
If so, JUMP to 535AH.
5355
CP 1DH FE 1D
Or record number out of range (1DH)?
5357
If neither, JUMP to 549EH.
535A
POP AF F1
Restore the error (NZ).
535B
POP DE D1
Fetch the output device.
535C
PUSH DE D5
(save DE)
535D
At the end of the file (NZ), JUMP to 5379H.
535F
LD (HL),A 77
Keep the byte for the ASCII part.
5360
INC HL 23
(next byte)
5361
GOSUB to 5417H to send it as two hexadecimal digits.
5364
LD A,20H 3E 20
Load Register A with a space...
5366
...and send it.
5369
LD A,B 78
After the eighth byte (B = 9)...
536A
CP 09H FE 09
(compare with 9)
536C
LD A,20H 3E 20
Load Register A with a space (the flags are kept)...
536E
...send an extra space.
5371
DEC B 05
One byte less on this line...
5372
DEC C 0D
...and in the record.
5373
If the record is finished, JUMP to 5379H.
5375
LD A,B 78
If the line is not full...
5376
OR A B7
(test B)
5377
...LOOP back to 5348H.
5379
PUSH AF F5
Save the flags (NZ at the end of the file).
537A
LD A,B 78
Were any bytes shown on this line?
537B
CP 10H FE 10
(compare with 16)
537D
If not, JUMP to 53D7H.
537F
LD A,00H 3E 00
Load Register A with the PRINT flag (the operand at 5380H).
5381
OR A B7
Test it.
5382
For PRINT, JUMP to 53B5H to put the ASCII on the same line.
5384
LD A,0DH 3E 0D
LIST: a carriage return...
5386
...ends the hex line.
5389
PUSH BC C5
Save the counts.
538A
LD B,0CH 06 0C
Twelve spaces...
538C
LD A,20H 3E 20
(a space)
538E
(send it)
5391
...to line up under the hex digits.
5393
POP BC C1
Restore the counts.
5394
LD A,10H 3E 10
B = the number of bytes shown...
5396
SUB B 90
(minus B)
5397
LD B,A 47
(into B)
5398
LD HL,5518H 21 18 55
Point HL to the ASCII buffer.
539B
LD A,(HL) 7E
Fetch a byte.
539C
INC HL 23
(next byte)
539D
GOSUB to 5402H to send it as a character.
53A0
LD A,20H 3E 20
Two spaces...
53A5
(send again)
53A8
LD A,B 78
...and a third after the eighth byte.
53A9
CP 09H FE 09
(compare B with 9)
53AB
LD A,20H 3E 20
(a space)
53AD
(send it if so)
53B0
LOOP back to 539BH.
53B5
PUSH BC C5
PRINT: save the counts.
53B6
LD A,B 78
Spaces for the bytes missing from the line: B x 3...
53B7
RLCA 07
(rotate left)
53B8
ADD A,B 80
(+ B: x 3)
53B9
LD B,A 47
(into B)
53BA
CP 18H FE 18
...+ 1 if fewer than 8 are missing...
53BC
CCF 3F
(Carry = 1 if the result is below 24)
53BD
LD A,03H 3E 03
...+ 3.
53BF
ADC A,B 88
(3 + that + Carry)
53C0
LD B,A 47
(into B)
53C1
LD A,20H 3E 20
Send them.
53C3
(send a space)
53C8
POP BC C1
Restore the counts.
53C9
LD A,10H 3E 10
B = the number of bytes shown...
53CB
SUB B 90
(minus B)
53CC
LD B,A 47
(into B)
53CD
LD HL,5518H 21 18 55
Point HL to the ASCII buffer.
53D0
LD A,(HL) 7E
Fetch a byte.
53D1
INC HL 23
(next byte)
53D2
GOSUB to 5402H to send it as a character.
53D5
LOOP back to 53D0H.
53D7
LD A,0DH 3E 0D
A carriage return...
53D9
...ends the line.
53DC
POP AF F1
Restore the flags.
53DD
LD A,1CH 3E 1C
Load Register A with 1CH (the flags are kept).
53DF
At the end of the file, JUMP to 52F6H.
53E2
GOSUB to 5472H to check for a pause or BREAK.
53E5
If BREAK was pressed, JUMP to 52EDH.
53E8
LD A,C 79
Is the record finished?
53E9
OR A B7
(test C)
53EA
If not, JUMP to 532BH for its next line.
53ED
POP DE D1
End of the record: fetch the output device.
53EE
PUSH DE D5
(save DE)
53EF
LD A,20H 3E 20
Send a space...
53F4
LD A,0DH 3E 0D
...and a carriage return: an empty line.
53F9
LD HL,54E0H 21 E0 54
Point HL to the record number...
53FC
...and GOSUB to 5461H to add 1 to it.
53FF
JUMP to 5324H for the next record.

5402H - Output Routines

5402H sends Register A as a character, with anything other than 20H-5AH and 61H-7AH sent as .. 5417H sends it as two hexadecimal digits. Both send to the device DE.

5402
CP 20H FE 20
Below 20H?
5404
Then JUMP to 5412H.
5406
CP 5BH FE 5B
20H-5AH...
5408
...is sent as it is.
540A
CP 61H FE 61
5BH-60H...
540C
...becomes a dot.
540E
CP 7BH FE 7B
61H-7AH...
5410
...is sent as it is.
5412
LD A,2EH 3E 2E
Load Register A with ..
5414
JUMP to the ROM routine at 001BH to send it.
5417
PUSH AF F5
Save the byte.
5418
RRCA 0F
Move the high digit down...
5419
RRCA 0F
(rotate)
541A
RRCA 0F
(rotate)
541B
RRCA 0F
(rotate)
541C
...and GOSUB to 5420H to send it.
541F
POP AF F1
Restore the byte.
5420
AND 0FH E6 0F
Keep the low 4 bits.
5422
ADD A,90H C6 90
Convert 0-15...
5424
DAA 27
(decimal adjust)
5425
ADC A,40H CE 40
(add 40H with carry)
5427
DAA 27
...to 0-9, A-F.
5428
JUMP to 001BH to send it.

542BH - Write a Five-Digit Number

HL = the number, BC = where the digits go. A zero digit stays a space if the character before it is a space; the character before the first digit is never a space here, so the numbers always have five digits with leading zeros.

542B
LD DE,2710H 11 10 27
DE = 10000...
542E
...GOSUB to 5446H for that digit.
5431
LD DE,03E8H 11 E8 03
DE = 1000.
5434
(the thousands)
5437
LD DE,0064H 11 64 00
DE = 100.
543A
(the hundreds)
543D
LD DE,000AH 11 0A 00
DE = 10.
5440
(the tens)
5443
LD DE,0001H 11 01 00
DE = 1, and fall into the routine for the last digit.
5446
XOR A AF
Register A counts, from 0.
5447
SBC HL,DE ED 52
Subtract DE...
5449
...until it goes below zero...
544B
INC A 3C
...counting each time.
544C
(loop)
544E
ADD HL,DE 19
Add the last DE back.
544F
ADD A,30H C6 30
Make the digit.
5451
CP 30H FE 30
Is it 0?
5453
If not, JUMP to 545EH to store it.
5455
DEC BC 0B
Look at the character before it:
5456
LD A,(BC) 0A
(fetch it)
5457
INC BC 03
(next byte)
5458
CP 20H FE 20
if it is a space...
545A
...store a space.
545C
LD A,30H 3E 30
Otherwise store 0.
545E
LD (BC),A 02
Store the character.
545F
INC BC 03
Move on.
5460
RET C9
RETURN.

5461H - Add 1 to a Five-Digit Number

HL points to the first of the five digits. Spaces count as zeros.

5461
INC HL 23
Point HL to the last digit.
5462
INC HL 23
(next byte)
5463
INC HL 23
(next byte)
5464
INC HL 23
(next byte)
5465
LD A,(HL) 7E
Fetch the digit...
5466
OR 30H F6 30
...(a space becomes 0)...
5468
INC A 3C
...add 1...
5469
LD (HL),A 77
...and store it.
546A
SUB 3AH D6 3A
Past 9?
546C
RET C D8
If not, RETURN.
546D
LD (HL),30H 36 30
Otherwise make it 0...
546F
DEC HL 2B
...and carry into the digit before.
5470
LOOP back to 5465H.

5472H - Pause and BREAK Check

Returns NZ if BREAK is pressed. SHIFT and @ pause until another key is pressed. Does nothing while a chain (DO) file is running.

5472
LD A,(430FH) 3A 0F 43
Fetch the system flags.
5475
AND 20H E6 20
Keep bit 5...
5477
XOR 20H EE 20
...and invert it.
5479
RET Z C8
If a chain file is running, RETURN with Z.
547A
LD A,(3840H) 3A 40 38
Read keyboard row 6.
547D
AND 04H E6 04
Keep bit 2, BREAK.
547F
RET NZ C0
If BREAK is pressed, RETURN with NZ.
5480
LD A,(3801H) 3A 01 38
Read keyboard row 0.
5483
AND 01H E6 01
Keep bit 0, @.
5485
RET Z C8
If @ is not pressed, RETURN with Z.
5486
LD A,(3880H) 3A 80 38
Read keyboard row 7.
5489
AND 01H E6 01
Keep bit 0, SHIFT.
548B
RET Z C8
If SHIFT is not pressed, RETURN with Z.
548C
LD A,(3840H) 3A 40 38
Read keyboard row 6.
548F
AND 04H E6 04
Keep bit 2, BREAK.
5491
RET NZ C0
If BREAK is pressed, RETURN with NZ.
5492
GOSUB to the ROM routine at 002BH to scan the keyboard.
5495
OR A B7
Test the key.
5496
If there is none, LOOP back to 548CH.
5498
CP 60H FE 60
Is it 60H (SHIFT and @ again)?
549A
If so, LOOP back to 548CH.
549C
XOR A AF
Any other key: Z...
549D
RET C9
...RETURN.

549EH - Error Exits

549E
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
54A0
JUMP to the SYS0 error handler at 4409H.
54A3
LD HL,54ACH 21 AC 54
Point HL to FILE SPEC REQUIRED at 54ACH.
54A6
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
54A9
JUMP to 4030H: back to VTOS READY.
54AC-54BE
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 54A6H.
54BF
LD HL,54C8H 21 C8 54
Point HL to PARAMETER ERROR at 54C8H.
54C2
GOSUB to 447BH to display it.
54C5
JUMP to 4030H.
54C8-54D7
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 54C2H.

54D8H - Text and Parameter Table

54D8-54DF
DEFM " . ",03H 20 20 20 20 20 2E 20 03
Line number for NUM: the five digits go to 54D8H.
54E0-54EB
DEFM " :XX = ",03H 20 20 20 20 20 3A 58 58 20 3D 20 03
Start of a HEX line: the record number at 54E0H, the offset at 54E6H.
54EC-54EE
DEFM "TXT" 54 58 54
Default extension.
54EF-54F6
DEFM "LINE " : DEFW 5282H 4C 49 4E 45 20 20 82 52
LINE: operand of the LD BC at 5281H.
54F7-54FE
DEFM "NUM " : DEFW 52ADH 4E 55 4D 20 20 20 AD 52
NUM: operand of the LD BC at 52ACH.
54FF-5506
DEFM "HEX " : DEFW 527AH 48 45 58 20 20 20 7A 52
HEX: operand of the LD BC at 5279H.
5507-550E
DEFM "REC " : DEFW 530FH 52 45 43 20 20 20 0F 53
REC: operand of the LD BC at 530EH.
550F-5516
DEFM "LRL " : DEFW 5329H 4C 52 4C 20 20 20 29 53
LRL: operand of the LD BC at 5328H.
5517
DEFB 00H 00
End of the table.

ISAM 51H - ATTRIB - Offset 24A7

ATTRIB (ATTRIB filespec (I, V, ACC=password, UPD=password, PROT=level)) changes a file's attributes in its directory entry: I makes it invisible, V visible, ACC and UPD set the access and update passwords, and PROT the protection level (ALL or FULL, KILL, NAME or RENAME, WRITE, READ, EXEC; only the first two letters are checked, and the third to tell RENAME from READ). The file must be opened with full access. Without parameters, -NOTHING DONE- is shown. The member uses routines and work bytes of SYS2, which is in memory after the file has been opened. The member loads at 5200H-53DAH (475 bytes); the FCB at 53DBH lies past it.

5200H - ATTRIB Command

HL points to the text after ATTRIB.

5200
LD DE,53DBH 11 DB 53
Point DE to the FCB at 53DBH.
5203
GOSUB to the SYS0 routine at 441CH to read the filespec into it.
5206
If there is none (NZ), JUMP to 5370H to display FILE SPEC REQUIRED.
5209
LD A,(DE) 1A
Fetch the first character.
520A
CP 2AH FE 2A
A device (*)...
520C
...is not accepted: JUMP to 5370H.
520F
PUSH HL E5
Save the line pointer.
5210
LD B,00H 06 00
Load Register B with 00H: record length 256.
5212
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
5215
GOSUB to the SYS0 routine at 4424H to open the file (this loads SYS2).
5218
If that failed (NZ), JUMP to the error exit at 536BH.
521B
POP HL E1
Restore the line pointer.
521C
LD A,(53DCH) 3A DC 53
Fetch FCB+01H...
521F
AND 07H E6 07
...bits 0-2: the access level the password gave.
5221
LD A,25H 3E 25
Load Register A with 25H (illegal access attempted to protected file). The flags are kept.
5223
Unless the access is full (level 0), JUMP back to 5218H to report the error.
5225
PUSH HL E5
Save the line pointer.
5226
GOSUB to 53BDH to change the rest of the line to capitals.
5229
POP HL E1
Restore the line pointer.
522A
LD A,(HL) 7E
Fetch a character.
522B
CP 28H FE 28
Is it (?
522D
If so, JUMP to 5237H to read the parameters.
522F
CP 20H FE 20
Is it a space?
5231
If not, JUMP to 538CH to display -NOTHING DONE-.
5234
INC HL 23
Skip the space...
5235
...and LOOP back to 522AH.

5237H - Read One Parameter

The first letter decides the parameter. Each one sets a bit in the operand at 532FH (bit 0 PROT, bit 1 ACC, bit 2 UPD, bit 3 I or V) to say what is to be changed.

5237
INC HL 23
Move to the parameter.
5238
LD A,(HL) 7E
Fetch its first letter.
5239
CP 49H FE 49
I?
523B
Then JUMP to 52A6H.
523D
CP 56H FE 56
V?
523F
Then JUMP to 52B8H.
5241
CP 41H FE 41
A (ACC)?
5243
Then JUMP to 52CAH.
5246
CP 55H FE 55
U (UPD)?
5248
Then JUMP to 52DFH.
524B
CP 50H FE 50
P (PROT)?
524D
If not, JUMP to 53A4H to display PARAMETER ERROR.
5250
GOSUB to 52F7H to read the value into 51E0H.
5253
PROT needs a value: if there is none (Z), JUMP to 53A4H.
5256
PUSH HL E5
Save the line pointer.
5257
LD B,08H 06 08
Load Register B with 08H: eight names in the table.
5259
LD DE,(51E0H) ED 5B E0 51
Fetch the first two letters of the value: E = the first, D = the second.
525D
LD HL,53CBH 21 CB 53
Point HL to the table of levels at 53CBH.
5260
LD A,(HL) 7E
Fetch the first letter of an entry.
5261
INC HL 23
(next byte)
5262
CP E BB
Does it match?
5263
If so, GOSUB to 526CH to check the second letter; if that matches too, it does not return here.
5266
INC HL 23
Next entry.
5267
LOOP back to 5260H.
5269
No match: JUMP to 53A4H.
526C
LD A,(HL) 7E
Fetch the second letter of the entry.
526D
CP D BA
Does it match?
526E
RET NZ C0
If not, RETURN to the search.
526F
POP AF F1
Match: discard the return address.
5270
LD A,B 78
Register B = 8 for the first entry down to 1 for the last...
5271
SUB 08H D6 08
...B - 8...
5273
...is 0 for AL (ALL): JUMP to 5286H.
5275
ADD A,07H C6 07
Otherwise B - 1: EX 6, RE 5, WR 4, NA 2, KI 1, FU 0.
5277
CP 05H FE 05
Is it 5 (RE)?
5279
If not, JUMP to 5286H.
527B
LD A,(51E2H) 3A E2 51
Look at the third letter of the value...
527E
CP 4EH FE 4E
...is it N (RENAME)?
5280
LD A,05H 3E 05
Level 5, READ (the flags are kept)...
5282
...if it is not N, JUMP to 5286H.
5284
LD A,02H 3E 02
Level 2 for RENAME.
5286
LD (5337H),A 32 37 53
Store the level at 5337H (the operand of the OR at 5336H).
5289
POP HL E1
Restore the line pointer.
528A
LD B,01H 06 01
Register B = 01H: PROT.
528C
LD A,(HL) 7E
Is the next character a quote?
528D
CP 22H FE 22
(compare with the quote)
528F
If not, JUMP to 5292H.
5291
INC HL 23
Skip it.
5292
LD A,(532FH) 3A 2F 53
Fetch the flags (the operand at 532FH)...
5295
OR B B0
...add this parameter's bit...
5296
LD (532FH),A 32 2F 53
...and store them.
5299
LD A,(HL) 7E
Fetch the character after the parameter.
529A
CP 29H FE 29
)?
529C
Then JUMP to 5323H to make the changes.
529F
CP 2CH FE 2C
A comma?
52A1
Then LOOP back to 5237H for the next parameter.
52A3
Otherwise JUMP to 53A4H.
52A6
I: GOSUB to 52F7H to look for a value.
52A9
I takes no value: if there is one (NZ), JUMP to 53A4H.
52AC
LD A,(533FH) 3A 3F 53
Fetch the operand of the OR at 533EH...
52AF
OR 08H F6 08
...set bit 3 (invisible)...
52B1
LD (533FH),A 32 3F 53
...and store it.
52B4
LD B,08H 06 08
Register B = 08H.
52B6
JUMP to 5292H.
52B8
V: GOSUB to 52F7H.
52BB
If there is a value, JUMP to 53A4H.
52BE
LD A,(533FH) 3A 3F 53
Fetch the operand at 533FH...
52C1
AND F7H E6 F7
...clear bit 3 (visible)...
52C3
LD (533FH),A 32 3F 53
...and store it.
52C6
LD B,08H 06 08
Register B = 08H.
52C8
JUMP to 5292H.
52CA
ACC: GOSUB to 52F7H to read the password.
52CD
If there is none, JUMP to 53A4H.
52D0
PUSH HL E5
Save the line pointer.
52D1
LD DE,51E0H 11 E0 51
Point DE to the password at 51E0H.
52D4
GOSUB to 52F4H to compute its hash in HL.
52D7
LD (51F5H),HL 22 F5 51
Keep it at 51F5H.
52DA
POP HL E1
Restore the line pointer.
52DB
LD B,02H 06 02
Register B = 02H: ACC.
52DD
JUMP to 528CH.
52DF
UPD: GOSUB to 52F7H to read the password.
52E2
If there is none, JUMP to 53A4H.
52E5
PUSH HL E5
Save the line pointer.
52E6
LD DE,51E0H 11 E0 51
Point DE to the password.
52E9
GOSUB to 52F4H to compute its hash.
52EC
LD (51F3H),HL 22 F3 51
Keep it at 51F3H.
52EF
POP HL E1
Restore the line pointer.
52F0
LD B,04H 06 04
Register B = 04H: UPD.
52F2
JUMP to 528CH.

52F4H - Parameter Helpers

52F4H computes the password hash of the eight characters at DE (SYS2, request 60H) and returns it in HL. 52F7H looks for = before the end of the parameter; if there is one, it reads the value (a letter followed by letters and digits, with an optional quote before it) into 51E0H, padded to eight characters with spaces, and returns NZ; otherwise it returns Z.

52F4
LD A,E4H 3E E4
Load Register A with E4H: SYS2, request 60H.
52F6
RST 28H EF
Call the overlay through RST 28H; it returns to the caller of 52F4H.
52F7
INC HL 23
Next character.
52F8
LD A,(HL) 7E
(fetch the byte into A)
52F9
CP 0DH FE 0D
A carriage return...
52FB
RET Z C8
...ends the parameter: RETURN with Z.
52FC
CP 29H FE 29
)...
52FE
RET Z C8
...ends it too.
52FF
CP 2CH FE 2C
So does a comma.
5301
RET Z C8
(RETURN with Z)
5302
CP 3DH FE 3D
Is it =?
5304
If not, LOOP back to 52F7H.
5306
INC HL 23
Move past it.
5307
LD A,(HL) 7E
Is the value quoted?
5308
CP 22H FE 22
(compare with the quote)
530A
If not, JUMP to 530DH.
530C
INC HL 23
Skip the quote.
530D
LD DE,51E0H 11 E0 51
Point DE to the buffer at 51E0H (in SYS2).
5310
LD B,08H 06 08
Load Register B with 08H.
5312
PUSH DE D5
Save DE...
5313
PUSH BC C5
...and BC.
5314
LD A,20H 3E 20
Fill the buffer with spaces:
5316
LD (DE),A 12
(store a space)
5317
INC DE 13
(next byte)
5318
(loop for eight bytes)
531A
POP BC C1
Restore BC...
531B
POP DE D1
...and DE.
531C
GOSUB to the SYS2 routine at 50B1H to copy the value into the buffer.
531F
DEC HL 2B
Step back to the character that ended it.
5320
OR 01H F6 01
Set NZ: a value was found.
5322
RET C9
RETURN.

5323H - Change the Directory Entry

5323
LD BC,(53E1H) ED 4B E1 53
Fetch the drive (FCB+06H) and directory entry code (FCB+07H).
5327
GOSUB to the SYS0 routine at 4B10H to read the directory entry.
532A
If that failed (NZ), JUMP to 536BH.
532D
LD A,(HL) 7E
Fetch byte 0 of the entry.
532E
LD D,00H 16 00
Load Register D with the flags (the operand at 532FH).
5330
BIT 0,D CB 42
PROT given?
5332
If not, JUMP to 5338H.
5334
AND F0H E6 F0
Clear bits 0-3 (this also clears bit 3, so the file becomes visible unless I is given too)...
5336
OR 00H F6 00
...and put in the new level (the operand at 5337H).
5338
BIT 3,D CB 5A
I or V given?
533A
If not, JUMP to 5340H.
533C
AND F7H E6 F7
Clear bit 3...
533E
OR 00H F6 00
...and set it again for I (the operand at 533FH is 08H for I, 00H for V).
5340
LD (HL),A 77
Store byte 0.
5341
LD A,L 7D
Point HL to entry+10H, the update password hash.
5342
ADD A,10H C6 10
(add 10H)
5344
LD L,A 6F
(into L)
5345
BIT 2,D CB 52
UPD given?
5347
If not, JUMP to 5353H.
5349
LD A,(51F3H) 3A F3 51
Store the new hash...
534C
LD (HL),A 77
(store A)
534D
LD A,(51F4H) 3A F4 51
(high byte)
5350
INC HL 23
(next byte)
5351
LD (HL),A 77
(store A)
5352
DEC HL 2B
(back one byte)
5353
INC HL 23
Point HL to entry+12H, the access password hash.
5354
INC HL 23
(next byte)
5355
BIT 1,D CB 4A
ACC given?
5357
If not, JUMP to 5362H.
5359
LD A,(51F5H) 3A F5 51
Store the new hash.
535C
LD (HL),A 77
(store A)
535D
LD A,(51F6H) 3A F6 51
(high byte)
5360
INC HL 23
(next byte)
5361
LD (HL),A 77
(store A)
5362
GOSUB to the SYS0 routine at 4B1FH to write the directory sector back.
5365
If that failed (NZ), JUMP to 536BH.
5368
JUMP to 402DH: back to VTOS READY.

536BH - Error Exits

536B
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
536D
JUMP to the SYS0 error handler at 4409H.
5370
LD HL,5379H 21 79 53
Point HL to FILE SPEC REQUIRED at 5379H.
5373
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5376
JUMP to 4030H: back to VTOS READY.
5379-538B
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5373H.
538C
LD HL,5395H 21 95 53
Point HL to -NOTHING DONE- at 5395H.
538F
GOSUB to 447BH to display it.
5392
JUMP to 4030H.
5395-53A3
DEFM "-NOTHING DONE-",0DH 2D 4E 4F 54 48 49 4E 47 20 44 4F 4E 45 2D 0D
Displayed at 538FH.
53A4
LD HL,53ADH 21 AD 53
Point HL to PARAMETER ERROR at 53ADH.
53A7
GOSUB to 447BH to display it.
53AA
JUMP to 4030H.
53AD-53BC
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 53A7H.

53BDH - Change to Capitals

Changes every character from 61H up to capitals by clearing bit 5, until a control character.

53BD
LD A,(HL) 7E
Fetch a character.
53BE
CP 20H FE 20
A control character (below 20H)...
53C0
RET C D8
...ends it: RETURN.
53C1
CP 61H FE 61
Below a?
53C3
Then leave it: JUMP to 53C7H.
53C5
RES 5,(HL) CB AE
Clear bit 5.
53C7
INC HL 23
Next character.
53C8
LOOP back to 53BDH.
53CA
DEFB 0DH 0D
Not used.
53CB-53DA
DEFM "ALEXREWR~~NAKIFU" 41 4C 45 58 52 45 57 52 7E 7E 4E 41 4B 49 46 55
The protection names, two letters each: ALL (0), EXEC (6), READ (5), WRITE (4), not used (3), NAME (2), KILL (1), FULL (0).

ISAM 52H - PROT - Offset 268D

PROT (PROT :d (MPW=password, PW=password, NAME=name, LOCK, UNLOCK)) changes the protection of a whole disk. The disk's master password must be given with MPW or typed in answer to MASTER PASSWORD ?. PW changes the master password, NAME the disk name, LOCK gives every ordinary file the master password as its access and update password, and UNLOCK removes them (the blank password). Values may be given in the command or typed in answer to a prompt. For a disk whose GAT byte CBH is below 30H (an older format), PROT also updates GAT byte CCH and, if necessary, the hash index entry of DIR/SYS, whose password it removes. Not allowed while a chain file is running. The member loads at 5200H-5393H and 5396H-551CH (795 bytes); it reads the GAT into 5700H and the hash index table into 5800H.

5200H - PROT Command

HL points to the text after PROT.

5200
LD A,(430FH) 3A 0F 43
Fetch the system flags.
5203
BIT 5,A CB 6F
Test bit 5: a chain (DO) file is running.
5205
If so, JUMP to 5452H to display INVALID COMMAND DURING PROGRAM CHAINING.
5208
LD BC,0000H 01 00 00
Load Register Pair BC with 0000H.
520B
JUMP to 521BH.
520D
LD A,D 7A
(Nothing jumps to 520DH-521AH.) Test DE for FFFFH...
520E
AND E A3
(AND with the high byte)
520F
INC A 3C
(FFH becomes 00H)
5210
...and JUMP to 53BBH to prompt if so...
5213
LD HL,5600H 21 00 56
...otherwise point HL to 5600H...
5216
...and JUMP to 53A3H to copy the text.
5219-521A
NOP x 2 00 x 2
Not used.
521B
LD (5394H),BC ED 43 94 53
Clear the MPW value at 5394H.
521F
LD C,00H 0E 00
Register C = drive 0.
5221
LD A,(HL) 7E
Fetch the next character.
5222
CP 3AH FE 3A
Is it :?
5224
If not, JUMP to 522CH.
5226
INC HL 23
Fetch the drive digit...
5227
LD A,(HL) 7E
(fetch the byte into A)
5228
SUB 30H D6 30
...as a number...
522A
LD C,A 4F
...into C.
522B
INC HL 23
Move past it.
522C
LD A,C 79
Register A = the drive...
522D
LD (5370H),A 32 70 53
...stored at 5370H (the operand of the LD C at 536FH).
5230
LD DE,54F4H 11 F4 54
Point DE to the parameter table at 54F4H.
5233
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
5236
If a parameter was not recognized (NZ), JUMP to 5439H to display PARAMETER ERROR.
5239
LD A,(5267H) 3A 67 52
Fetch the low byte of the PW value...
523C
LD HL,52EDH 21 ED 52
...and OR in the LOCK value...
523F
OR (HL) B6
(OR in the byte at HL)
5240
LD HL,52F7H 21 F7 52
...the UNLOCK value...
5243
OR (HL) B6
(OR in the byte at HL)
5244
LD HL,524FH 21 4F 52
...and the NAME value.
5247
OR (HL) B6
(OR in the byte at HL)
5248
If none of them was given, JUMP to 5483H to display -NOTHING DONE-.
524B
GOSUB to 5364H to read the GAT and check the master password.
524E
LD DE,0000H 11 00 00
Load DE with the NAME value (the operand at 524FH).
5251
LD A,D 7A
Test it...
5252
OR E B3
(OR the low byte)
5253
...and if NAME was not given, JUMP to 5266H.
5255
LD HL,549BH 21 9B 54
Point HL to the prompt NEW DISK PACK NAME ? at 549BH.
5258
GOSUB to 539CH to get the name into 5600H (from the command, or typed in if the value is 0000H).
525B
LD HL,5600H 21 00 56
Point HL to 5600H...
525E
LD DE,57D0H 11 D0 57
...DE to the disk name in the GAT (57D0H)...
5261
LD BC,0008H 01 08 00
...BC = 0008H...
5264
LDIR ED B0
...and copy the eight characters.
5266
LD DE,0000H 11 00 00
Load DE with the PW value (the operand at 5267H).
5269
LD A,D 7A
Test it...
526A
OR E B3
(OR the low byte)
526B
...and if PW was not given, JUMP to 5276H.
526D
LD HL,54B3H 21 B3 54
Point HL to the prompt NEW MASTER PASSWORD ? at 54B3H.
5270
GOSUB to 5396H to get the new password and compute its hash in HL.
5273
LD (57CEH),HL 22 CE 57
Store it in the GAT at 57CEH.
5276
GOSUB to 4B65H to get the directory track in Register D.
5279
LD E,01H 1E 01
Load Register E with 01H: the hash index table.
527B
LD HL,5800H 21 00 58
Point HL to the buffer at 5800H.
527E
GOSUB to 4B45H to read it.
5281
If that failed (NZ), JUMP to the error exit at 5434H.
5284
LD A,(57CBH) 3A CB 57
Fetch GAT byte CBH.
5287
CP 30H FE 30
Is it 30H or above?
5289
If so, JUMP to 52A7H.
528B
LD A,(57A6H) 3A A6 57
Otherwise set GAT byte CCH (cylinders beyond 35) from GAT bytes A6H, 88H and 83H, which appear to be the lockout bytes of cylinders 70, 40 and 35 (FFH if the cylinder does not exist). Fetch GAT byte A6H...
528E
INC A 3C
(FFH gives Z)
528F
LD A,2AH 3E 2A
Load Register A with 2AH (the flags are kept)...
5291
...and use it if the byte was not FFH.
5293
LD A,(5788H) 3A 88 57
Otherwise GAT byte 88H...
5296
INC A 3C
(FFH gives Z)
5297
LD A,23H 3E 23
...gives 23H...
5299
...if it was not FFH.
529B
LD A,(5783H) 3A 83 57
...otherwise GAT byte 83H...
529E
INC A 3C
(FFH gives Z)
529F
LD A,05H 3E 05
...gives 05H...
52A1
...if it was not FFH...
52A3
XOR A AF
...and otherwise 00H.
52A4
LD (57CCH),A 32 CC 57
Store it at GAT byte CCH (57CCH).
52A7
LD A,(5370H) 3A 70 53
Fetch the drive...
52AA
LD C,A 4F
...into C.
52AB
GOSUB to 541BH to write the GAT back.
52AE
If that failed (NZ), JUMP to 5434H.
52B1
LD A,(57CBH) 3A CB 57
Fetch GAT byte CBH again.
52B4
CP 30H FE 30
Is it 30H or above?
52B6
If so, JUMP to 52E9H.
52B8
LD A,(5801H) 3A 01 58
Fetch the hash index entry of DIR/SYS (the second byte of the table).
52BB
CP 2CH FE 2C
Is it 2CH?
52BD
If not, JUMP to 52E9H.
52BF
LD A,C4H 3E C4
Change it to C4H...
52C1
LD (5801H),A 32 01 58
(store it in the table)
52C4
...and GOSUB to 4768H to write the table back (still sector D,E).
52C7
If that failed (NZ), JUMP to 5434H.
52CA
LD HL,4200H 21 00 42
Point HL to the buffer at 4200H.
52CD
LD E,03H 1E 03
Load Register E with 03H: the second directory sector, which holds DIR/SYS.
52CF
GOSUB to 4B45H to read it.
52D2
If that failed (NZ), JUMP to 5434H.
52D5
PUSH HL E5
Save HL.
52D6
LD HL,4296H 21 96 42
Load HL with 4296H, the hash of a blank password...
52D9
LD (4212H),HL 22 12 42
...and store it as the access password of the first entry (4212H): DIR/SYS can now be read.
52DC
POP HL E1
Restore HL.
52DD
GOSUB to 4768H to write the sector back.
52E0
If that failed (NZ), JUMP to 5434H.
52E3
LD HL,54CBH 21 CB 54
Point HL to NOTE: FILE 'DIR/SYS' IS NOW READ ENABLED at 54CBH.
52E6
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
52E9
LD HL,(57CEH) 2A CE 57
Fetch the master password hash from the GAT.
52EC
LD DE,0000H 11 00 00
Load DE with the LOCK value (the operand at 52EDH).
52EF
LD A,D 7A
Test it...
52F0
OR E B3
(OR the low byte)
52F1
...and if LOCK was given, JUMP to 5300H with HL = the master password.
52F3
LD HL,4296H 21 96 42
Load HL with 4296H, the blank password.
52F6
LD DE,0000H 11 00 00
Load DE with the UNLOCK value (the operand at 52F7H).
52F9
LD A,D 7A
Test it...
52FA
OR E B3
(OR the low byte)
52FB
...and if UNLOCK was given, JUMP to 5300H.
52FD
JUMP to 402DH: back to VTOS READY.

5300H - Set the Passwords of Every File

HL = the password hash to use. Goes through the hash index table sector by sector and gives each ordinary file (in use, and not a system, invisible or extended entry) this hash as its update and access password. The entries kept for system files (positions 00H-07H and 20H-27H) are skipped.

5300
LD (5339H),HL 22 39 53
Store the hash at 5339H (the operand of the LD DE at 5338H).
5303
LD A,(5370H) 3A 70 53
Fetch the drive...
5306
LD C,A 4F
...into C.
5307
GOSUB to 4B65H to get the directory track.
530A
LD HL,5800H 21 00 58
Point HL to the hash index table at 5800H.
530D
LD A,L 7D
Is this position one of those kept for system files?
530E
AND D8H E6 D8
(positions 00H-07H and 20H-27H give Z)
5310
If so, JUMP to 5347H.
5312
LD A,(HL) 7E
Fetch the hash byte.
5313
OR A B7
Test it.
5314
If the entry is free, JUMP to 5347H.
5316
LD B,L 45
Register B = the directory entry code.
5317
PUSH BC C5
Save it and the drive.
5318
LD A,L 7D
Point L to the entry within its sector...
5319
AND E0H E6 E0
(bits 5-7 of the position, times 32)
531B
LD L,A 6F
(into L)
531C
XOR B A8
...and A = the directory sector.
531D
CP FFH FE FF
Is it the sector already in 4200H (the operand at 531EH, FFH to begin with)?
531F
If so, JUMP to 532AH.
5321
LD (531EH),A 32 1E 53
Remember it.
5324
GOSUB to 4B10H to read the directory sector that holds entry B.
5327
If that failed (NZ), JUMP to 5434H.
532A
LD H,42H 26 42
HL = the entry at 42xxH.
532C
LD A,(HL) 7E
Fetch its attributes...
532D
AND F8H E6 F8
...keep bits 3-7...
532F
CP 10H FE 10
...only an entry that is in use and nothing else (10H)...
5331
...is changed: otherwise JUMP to 5343H.
5333
LD A,L 7D
Point to entry+10H...
5334
ADD A,10H C6 10
(add 10H)
5336
LD L,A 6F
(into L)
5337
PUSH DE D5
Save DE.
5338
LD DE,0000H 11 00 00
Load DE with the hash (the operand at 5339H).
533B
LD (HL),E 73
Store it as the update password...
533C
INC L 2C
(next byte)
533D
LD (HL),D 72
(store D)
533E
INC L 2C
(next byte)
533F
LD (HL),E 73
...and as the access password.
5340
INC L 2C
(next byte)
5341
LD (HL),D 72
(store D)
5342
POP DE D1
Restore DE.
5343
POP BC C1
Restore the entry code and drive.
5344
LD H,58H 26 58
Point HL back into the hash index table...
5346
LD L,B 68
(L = the entry code again)
5347
LD A,L 7D
Next entry in the same sector...
5348
ADD A,20H C6 20
(add 20H)
534A
LD L,A 6F
(into L)
534B
...LOOP back to 530DH until all eight have been seen.
534D
LD A,(531EH) 3A 1E 53
If the sector just finished is the one in the buffer...
5350
XOR L AD
(compare with the sector number in L)
5351
(if not, JUMP to 535BH)
5353
PUSH HL E5
...save HL...
5354
...and GOSUB to 4B1FH to write it back.
5357
If that failed (NZ), JUMP to 5434H.
535A
POP HL E1
Restore HL.
535B
LD A,L 7D
Next sector.
535C
INC L 2C
(next byte)
535D
CP 1FH FE 1F
After 32 sectors...
535F
...(otherwise LOOP back to 530DH)...
5361
...JUMP to 402DH: back to VTOS READY.

5364H - Check the Master Password

Reads the GAT of the drive into 5700H and compares the hash of the password given (MPW, or typed in) with the one in the GAT (CEH-CFH). The hash C294H is also accepted.

5364
LD DE,(5394H) ED 5B 94 53
Load DE with the MPW value.
5368
LD HL,53D8H 21 D8 53
Point HL to the prompt MASTER PASSWORD ? at 53D8H.
536B
GOSUB to 5396H to get the password and its hash in HL.
536E
PUSH HL E5
Save the hash.
536F
LD C,00H 0E 00
Load Register C with the drive (the operand at 5370H).
5371
GOSUB to 5408H to read the GAT.
5374
If that failed (NZ), JUMP to 538FH.
5377
POP DE D1
DE = the hash.
5378
LD HL,C294H 21 94 C2
Is it C294H?
537B
XOR A AF
(clear Register A and the Carry flag)
537C
SBC HL,DE ED 52
(compare)
537E
RET Z C8
If so, RETURN.
537F
LD HL,(57CEH) 2A CE 57
Is it the master password of the disk?
5382
XOR A AF
(clear Register A and the Carry flag)
5383
SBC HL,DE ED 52
(compare)
5385
RET Z C8
If so, RETURN.
5386
LD HL,53F0H 21 F0 53
Point HL to INVALID MASTER PASSWORD at 53F0H.
5389
GOSUB to 447BH to display it.
538C
JUMP to 4030H: back to VTOS READY.
538F
OR 40H F6 40
Error exit with the error code in Register A: set bit 6.
5391
JUMP to the SYS0 error handler at 4409H.
5394-5395
DEFS 2
The MPW value (stored by the parameter scan; cleared at 521BH). Not in the file.

5396H - Get a Password or Name

5396H gets the text and returns the hash of its eight characters in HL (SYS2, request 60H). 539CH only gets the text into 5600H, padded with spaces, and returns DE = 5600H. DE = the value from the command: the text itself, or 0000H if none was given, in which case the prompt at HL is displayed and the text is typed in.

5396
GOSUB to 539CH to get the text.
5399
LD A,E4H 3E E4
Load Register A with E4H: SYS2, request 60H (password hash).
539B
RST 28H EF
Call the overlay through RST 28H; it returns to the caller of 5396H.
539C
LD A,D 7A
Was a value given?
539D
OR E B3
(OR the other byte)
539E
If not, JUMP to 53BBH to prompt.
53A0
LD HL,5600H 21 00 56
Point HL to 5600H.
53A3
LD B,08H 06 08
Load Register B with 08H.
53A5
LD A,(DE) 1A
Fetch a character of the value.
53A6
CP 0DH FE 0D
A carriage return...
53A8
...ends it: JUMP to 53CFH to pad.
53AA
CP 2CH FE 2C
So does a comma...
53AC
(a comma ends it too)
53AE
CP 22H FE 22
...and a quote.
53B0
(and so does a quote)
53B2
INC DE 13
Move on.
53B3
LD (HL),A 77
Store the character.
53B4
INC HL 23
(next byte)
53B5
LOOP back to 53A5H for up to eight characters.
53B7
LD DE,5600H 11 00 56
DE = 5600H.
53BA
RET C9
RETURN.
53BB
Display the prompt at HL.
53BE
LD B,08H 06 08
Load Register B with 08H.
53C0
LD HL,5600H 21 00 56
Point HL to 5600H.
53C3
GOSUB to the ROM routine at 0040H to read up to eight characters (BREAK is not checked).
53C6
EX DE,HL EB
DE = 5600H.
53C7
LD H,00H 26 00
HL = 5600H + the number of characters typed...
53C9
LD L,B 68
(L = the count, which 0040H returns in Register B)
53CA
ADD HL,DE 19
(add DE)
53CB
LD A,09H 3E 09
Register B = 9 - that number: one more than needed, so the padding also writes a space at 5608H, just past the buffer.
53CD
SUB B 90
(Register A = 9 - B)
53CE
LD B,A 47
(into B)
53CF
LD (HL),20H 36 20
Fill with spaces...
53D1
INC HL 23
(next byte)
53D4
LD DE,5600H 11 00 56
DE = 5600H.
53D7
RET C9
RETURN.
53D8-53EF
DEFM "MASTER PASSWORD ? ",03H 4D 41 53 54 45 52 20 50 41 53 53 57 4F 52 44 20 3F 20 20 20 20 20 20 03
Prompt displayed at 53BBH.
53F0-5407
DEFM "INVALID MASTER PASSWORD",0DH 49 4E 56 41 4C 49 44 20 4D 41 53 54 45 52 20 50 41 53 53 57 4F 52 44 0D
Displayed at 5389H.

5408H - Read and Write the GAT

5408H reads the GAT of drive C into 5700H (NZ with A = 14H on error). 541BH writes it back and verifies it (NZ with A = 15H on error). DE and HL are preserved.

5408
PUSH DE D5
Save DE.
5409
PUSH HL E5
Save HL.
540A
GOSUB to 4B65H to get the directory track.
540D
LD E,00H 1E 00
Load Register E with 00H: the GAT.
540F
LD HL,5700H 21 00 57
Point HL to 5700H.
5412
GOSUB to 4B45H to read it.
5415
POP HL E1
Restore HL.
5416
POP DE D1
Restore DE.
5417
RET Z C8
If it was read, RETURN.
5418
LD A,14H 3E 14
Load Register A with 14H: GAT read error.
541A
RET C9
RETURN with NZ.
541B
PUSH DE D5
Save DE.
541C
PUSH HL E5
Save HL.
541D
GOSUB to 4B65H to get the directory track.
5420
LD E,00H 1E 00
Load Register E with 00H: the GAT.
5422
LD HL,5700H 21 00 57
Point HL to 5700H.
5425
GOSUB to the SYS0 routine at 4768H to write it as a system sector.
5428
If that failed (NZ), JUMP to 542FH.
542A
GOSUB to the SYS0 routine at 4772H to verify it.
542D
CP 06H FE 06
A system sector that reads back correctly returns error 06H: Z means all is well.
542F
LD A,15H 3E 15
Load Register A with 15H: GAT write error (the flags are kept).
5431
POP HL E1
Restore HL.
5432
POP DE D1
Restore DE.
5433
RET C9
RETURN.

5434H - Error Exits

5434
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
5436
JUMP to the SYS0 error handler at 4409H.
5439
LD HL,5442H 21 42 54
Point HL to PARAMETER ERROR at 5442H.
543C
GOSUB to 447BH to display it.
543F
JUMP to 4030H: back to VTOS READY.
5442-5451
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 543CH.
5452
LD HL,545BH 21 5B 54
Point HL to the message at 545BH.
5455
GOSUB to 447BH to display it.
5458
JUMP to 4030H.
545B-5482
DEFM "INVALID COMMAND DURING PROGRAM CHAINING",0DH 49 4E 56 41 4C 49 44 20 43 4F 4D 4D 41 4E 44 20 44 55 52 49 4E 47 20 50 52 4F 47 52 41 4D 20 43 48 41 49 4E 49 4E 47 0D
Displayed at 5455H.
5483
LD HL,548CH 21 8C 54
Point HL to -NOTHING DONE- at 548CH.
5486
GOSUB to 447BH to display it.
5489
JUMP to 4030H.
548C-549A
DEFM "-NOTHING DONE-",0DH 2D 4E 4F 54 48 49 4E 47 20 44 4F 4E 45 2D 0D
Displayed at 5486H.
549B-54B2
DEFM "NEW DISK PACK NAME ? ",03H 4E 45 57 20 44 49 53 4B 20 50 41 43 4B 20 4E 41 4D 45 20 3F 20 20 20 03
Prompt for NAME.
54B3-54CA
DEFM "NEW MASTER PASSWORD ? ",03H 4E 45 57 20 4D 41 53 54 45 52 20 50 41 53 53 57 4F 52 44 20 3F 20 20 03
Prompt for PW.
54CB-54F3
DEFM "NOTE: FILE 'DIR/SYS' IS NOW READ ENABLED",0DH 4E 4F 54 45 3A 20 46 49 4C 45 20 27 44 49 52 2F 53 59 53 27 20 49 53 20 4E 4F 57 20 52 45 41 44 20 45 4E 41 42 4C 45 44 0D
Displayed at 52E6H.

54F4H - Parameter Table

54F4-54FB
DEFM "PW " : DEFW 5267H 50 57 20 20 20 20 67 52
PW: operand of the LD DE at 5266H.
54FC-5503
DEFM "LOCK " : DEFW 52EDH 4C 4F 43 4B 20 20 ED 52
LOCK: operand of the LD DE at 52ECH.
5504-550B
DEFM "UNLOCK" : DEFW 52F7H 55 4E 4C 4F 43 4B F7 52
UNLOCK: operand of the LD DE at 52F6H.
550C-5513
DEFM "NAME " : DEFW 524FH 4E 41 4D 45 20 20 4F 52
NAME: operand of the LD DE at 524EH.
5514-551B
DEFM "MPW " : DEFW 5394H 4D 50 57 20 20 20 94 53
MPW: stored at 5394H.
551C
DEFB 00H 00
End of the table.

ISAM 53H - RENAME - Offset 29BB

RENAME (RENAME oldspec newspec) gives a file a new name and extension. Parts left out of the new filespec are taken from the old one: the name if the new one starts with /, . or :, and the extension and password if the new one has none. The drive must be the same; it is added to the new filespec if not given. The old file must be opened with at least RENAME access (level 2). The member changes the name in the directory entry and the entry's byte in the hash index table, using routines and buffers of SYS2, which is in memory after the files have been opened. It loads at 5200H-5399H (410 bytes); the FCB of the old file is at 539AH and that of the new one at 53BAH, past the member.

5200H - RENAME Command

HL points to the text after RENAME.

5200
LD DE,539AH 11 9A 53
Point DE to the first FCB at 539AH.
5203
GOSUB to the SYS0 routine at 441CH to read the old filespec into it.
5206
If there is none (NZ), JUMP to 5320H to display FILE SPEC REQUIRED.
5209
LD A,(DE) 1A
Fetch the first character.
520A
CP 2AH FE 2A
A device (*)...
520C
...is not accepted: JUMP to 5320H.
520F
LD DE,53BAH 11 BA 53
Point DE to the second FCB at 53BAH.
5212
GOSUB to 441CH to read the new filespec into it.
5215
If one was read (Z), JUMP to 521DH.
5217
DEC HL 2B
Otherwise step back one character...
5218
LD BC,0020H 01 20 00
...and copy 32 bytes of the command text into the second FCB...
521B
LDIR ED B0
...so that it starts with whatever stopped the scan (a carriage return if the line ended).
521D
LD A,(53BAH) 3A BA 53
Fetch the first character of the new filespec.
5220
CP 0EH FE 0E
Below 0EH (the end of the line)?
5222
Then JUMP to 533CH to display RENAME IT TO WHAT?.
5225
LD HL,539AH 21 9A 53
Point HL to the old filespec...
5228
LD DE,53BAH 11 BA 53
...and DE to the new one.
522B
GOSUB to 52C0H to fill in the parts the new filespec leaves out.
522E
LD DE,539AH 11 9A 53
Point DE to the first FCB.
5231
GOSUB to the SYS0 routine at 4424H to open the old file (this loads SYS2).
5234
If that failed (NZ), JUMP to the error exit at 531BH.
5237
LD A,(539BH) 3A 9B 53
Fetch FCB+01H...
523A
AND 07H E6 07
...bits 0-2: the access level the password gave.
523C
CP 03H FE 03
Level 3 or higher (below RENAME)...
523E
LD A,25H 3E 25
...gives error 25H (illegal access attempted to protected file); the flags are kept...
5243
LD HL,53BAH 21 BA 53
Point HL to the new filespec.
5246
LD A,(HL) 7E
Fetch a character.
5247
INC HL 23
Move on.
5248
CP 0DH FE 0D
A carriage return...
524A
...means no drive was given: JUMP to 525FH.
524C
CP 03H FE 03
So does 03H.
524E
(JUMP to 525FH)
5250
CP 3AH FE 3A
Is it :?
5252
If not, LOOP back to 5246H.
5254
LD A,(53A0H) 3A A0 53
Fetch the drive of the old file (FCB+06H)...
5257
XOR (HL) AE
...compare it with the drive digit given...
5258
AND 07H E6 07
(bits 0-2)
525A
...and if they differ, JUMP to 5358H to display ILLEGAL DRIVE SPECIFICATION.
525D
JUMP to 526EH.
525F
DEC HL 2B
Step back to the end character...
5260
LD (HL),3AH 36 3A
...and put : there...
5262
INC HL 23
(next byte)
5263
LD A,(53A0H) 3A A0 53
...then the drive of the old file...
5266
AND 07H E6 07
(bits 0-2)
5268
ADD A,30H C6 30
(as an ASCII digit)
526A
LD (HL),A 77
(store it)
526B
INC HL 23
(next byte)
526C
LD (HL),0DH 36 0D
...and a carriage return.
526E
LD HL,(51DEH) 2A DE 51
Fetch the hash word at 51DEH in SYS2 (the hash of the old name)...
5271
PUSH HL E5
...and save it.
5272
LD DE,53BAH 11 BA 53
Point DE to the second FCB.
5275
GOSUB to 4424H to open the new file. SYS2 leaves the new name and extension in 51E8H.
5278
POP HL E1
Restore the hash word...
5279
LD (51DEH),HL 22 DE 51
...at 51DEH.
527C
If the file exists (Z), JUMP to 537DH to display DUPLICATE FILE NAME.
527F
CP 18H FE 18
Any error other than 18H (file not in directory)...
5281
...is reported: JUMP to 531BH.
5284
LD BC,(53A0H) ED 4B A0 53
Fetch the drive (FCB+06H) into C and the directory entry code (FCB+07H) into B.
5288
PUSH BC C5
Save them.
5289
GOSUB to the SYS0 routine at 4B10H to read the directory entry of the old file.
528C
If that failed (NZ), JUMP to 531BH.
528F
LD D,H 54
Point DE to entry+05H, the name...
5290
LD A,L 7D
(low byte)
5291
ADD A,05H C6 05
(add 05H)
5293
LD E,A 5F
(into E)
5294
LD HL,51E8H 21 E8 51
...HL to the new name and extension at 51E8H in SYS2...
5297
LD BC,000BH 01 0B 00
...BC = 000BH...
529A
LDIR ED B0
...and copy the eleven characters.
529C
POP BC C1
Restore the drive and entry code.
529D
GOSUB to the SYS0 routine at 4B1FH to write the directory sector back.
52A0
If that failed (NZ), JUMP to 531BH.
52A3
GOSUB to the SYS2 routine at 51B5H to read the hash index table into 4200H.
52A6
If that failed (NZ), JUMP to 531BH.
52A9
LD D,H 54
DE = 4200H + the entry code: the entry's byte in the table.
52AA
LD E,B 58
(E = the entry code)
52AB
PUSH BC C5
Save the drive and entry code.
52AC
LD HL,51E8H 21 E8 51
Point HL to the new name at 51E8H.
52AF
GOSUB to 52BDH to compute its hash.
52B2
POP BC C1
Restore the drive and entry code.
52B3
LD (DE),A 12
Store the hash in the table.
52B4
GOSUB to the SYS2 routine at 51C7H to write the table back.
52B7
If that failed (NZ), JUMP to 531BH.
52BA
JUMP to 402DH: back to VTOS READY.

52BDH - Hash of a File Name

Computes the hash index byte of the eleven characters at HL (SYS2, request 50H) and returns it in Register A.

52BD
LD A,D4H 3E D4
Load Register A with D4H: SYS2, request 50H.
52BF
RST 28H EF
Call the overlay through RST 28H; it returns to the caller of 52BDH.

52C0H - Complete the New Filespec

HL points to the old filespec and DE to the new one (both as typed, ending with 03H or 0DH). A name part that the new filespec lacks is copied from the old one and inserted in the new one at the right place: the name, the extension (after /) and the password (after .).

52C0
PUSH DE D5
Save DE.
52C1
LD A,(DE) 1A
Fetch the first character of the new filespec.
52C2
CP 41H FE 41
If it is not a letter (the name is left out)...
52C4
...GOSUB to 52FBH to insert the old name.
52C7
LD B,2FH 06 2F
Register B = /...
52C9
...GOSUB to 52D4H to see to the extension.
52CC
LD B,2EH 06 2E
Register B = ....
52CE
...GOSUB to 52D4H to see to the password.
52D1
POP DE D1
Restore DE.
52D2
RET C9
RETURN.
52D3
INC DE 13
Move on in the new filespec.
52D4
LD A,(DE) 1A
Fetch a character.
52D5
CP B B8
Is it the separator in B?
52D6
If so, the new filespec has this part: JUMP to 52E6H.
52D8
CP 41H FE 41
A letter...
52DA
...is skipped: LOOP back to 52D3H.
52DC
CP 30H FE 30
Anything below 0...
52DE
...ends the name part: JUMP to 52E8H.
52E0
CP 3AH FE 3A
A digit...
52E2
...is skipped: LOOP back to 52D3H.
52E4
Anything else (3AH-40H) ends it too: JUMP to 52E8H.
52E6
INC DE 13
Move past the separator.
52E7
RET C9
RETURN.
52E8
PUSH HL E5
Save the old filespec pointer.
52E9
LD A,(HL) 7E
Look for the separator in the old filespec.
52EA
INC HL 23
(next byte)
52EB
CP 03H FE 03
Stop at 03H...
52ED
(JUMP to 52F9H)
52EF
CP 0DH FE 0D
...or at a carriage return...
52F1
(JUMP to 52F9H)
52F3
CP B B8
Is it the separator?
52F4
If not, LOOP back to 52E9H.
52F6
Found: GOSUB to 5307H to insert it in the new filespec and then the letters and digits after it.
52F9
POP HL E1
Restore the old filespec pointer.
52FA
RET C9
RETURN.
52FB
LD A,(HL) 7E
Fetch a character of the old filespec.
52FC
CP 30H FE 30
Below 0...
52FE
RET C D8
...ends the part: RETURN.
52FF
CP 3AH FE 3A
A digit...
5301
...is copied: JUMP to 5306H.
5303
CP 41H FE 41
So is a letter; anything else (3AH-40H)...
5305
RET C D8
...ends the part: RETURN.
5306
INC HL 23
Move on in the old filespec.
5307
PUSH HL E5
Save HL.
5308
LD H,D 62
HL = DE, the place in the new filespec.
5309
LD L,E 6B
(L)
530A
LD C,(HL) 4E
Insert the character in Register A there, moving the rest of the new filespec up one place: fetch the byte there...
530B
LD (HL),A 77
...store the one before it...
530C
INC HL 23
(next byte)
530D
LD A,C 79
Register A = the byte moved on.
530E
CP 03H FE 03
Was it 03H...
5310
(JUMP to 5316H)
5312
CP 0DH FE 0D
...or a carriage return, the end?
5314
If not, LOOP back to 530AH.
5316
LD (HL),A 77
Store the end byte.
5317
POP HL E1
Restore HL.
5318
INC DE 13
Move on in the new filespec.
5319
LOOP back to 52FBH for the next character.

531BH - Error Exits

531B
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
531D
JUMP to the SYS0 error handler at 4409H.
5320
LD HL,5329H 21 29 53
Point HL to FILE SPEC REQUIRED at 5329H.
5323
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5326
JUMP to 4030H: back to VTOS READY.
5329-533B
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5323H.
533C
LD HL,5345H 21 45 53
Point HL to RENAME IT TO WHAT? at 5345H.
533F
GOSUB to 447BH to display it.
5342
JUMP to 4030H.
5345-5357
DEFM "RENAME IT TO WHAT?",0DH 52 45 4E 41 4D 45 20 49 54 20 54 4F 20 57 48 41 54 3F 0D
Displayed at 533FH.
5358
LD HL,5361H 21 61 53
Point HL to ILLEGAL DRIVE SPECIFICATION at 5361H.
535B
GOSUB to 447BH to display it.
535E
JUMP to 4030H.
5361-537C
DEFM "ILLEGAL DRIVE SPECIFICATION",0DH 49 4C 4C 45 47 41 4C 20 44 52 49 56 45 20 53 50 45 43 49 46 49 43 41 54 49 4F 4E 0D
Displayed at 535BH.
537D
LD HL,5386H 21 86 53
Point HL to DUPLICATE FILE NAME at 5386H.
5380
GOSUB to 447BH to display it.
5383
JUMP to 4030H.
5386-5399
DEFM "DUPLICATE FILE NAME",0DH 44 55 50 4C 49 43 41 54 45 20 46 49 4C 45 20 4E 41 4D 45 0D
Displayed at 5380H.

ISAM 61H - DEVICE - Offset 2B60

DEVICE lists the disk drives and the devices. For each enabled drive (0-7) it shows the size (5 or 8 inch), floppy or rigid disk, the select address, the number of cylinders, and then either REMOVABLE or FIXED (rigid disks) or the density, sides, step rate and, for 5-inch drives, the head settling delay (floppies). The drive lines are displayed character by character through the ROM routine at 0033H. Then, for each device control block in use (the keyboard at 4015H, the display at 401DH, the printer at 4025H, and the eight blocks from 43C0H to 43F8H), it displays a line with the device name and where it goes: NIL, the driver address X'hhhh', the device or chain of devices it is routed or linked to, or the file it is routed to. The arrows < and > show whether the device does input and output. The member loads at 5200H-53F5H and 541EH-547FH (600 bytes); 53F6H-541DH is the line buffer.

5200H - DEVICE Command: Drives

Register C counts the drives from 0 to 7. For each drive whose drive control table starts with a JP instruction (C3H), a line is displayed. Bits of DCT+03H: bit 2 (floppy) half-second delay or (rigid) fixed disk, bit 3 rigid disk, bit 5 8-inch drive, bit 6 double density, bits 0-1 step rate. DCT+04H: bits 0-3 select address, bit 5 two sides. DCT+06H: the highest cylinder.

5200
LD C,00H 0E 00
Start with drive 0.
5202
PUSH BC C5
Save the drive number.
5203
GOSUB to the SYS0 routine at 478FH to point IY to the drive control table of drive C.
5206
LD A,(IY+00H) FD 7E 00
Fetch its first byte.
5209
CP C3H FE C3
A JP instruction (C3H) means the drive is enabled...
520B
...otherwise JUMP to 52F4H for the next drive.
520E
LD A,3AH 3E 3A
Display : through the ROM routine at 0033H...
5210
(display it)
5213
LD A,C 79
...the drive number...
5214
ADD A,30H C6 30
(as an ASCII digit)
5216
(display it)
5219
LD A,20H 3E 20
...and two spaces.
521B
(display it)
521E
LD A,20H 3E 20
(a second space)
5220
(display it)
5223
BIT 5,(IY+03H) FD CB 03 6E
Test bit 5 of DCT+03H (8-inch drive).
5227
LD A,35H 3E 35
Register A = 5...
5229
...kept for a 5-inch drive...
522B
LD A,38H 3E 38
...otherwise 8.
522D
Display it.
5230
BIT 3,(IY+03H) FD CB 03 5E
Test bit 3 of DCT+03H (rigid disk).
5234
LD HL,542EH 21 2E 54
Point HL to " FLOPPY # at 542EH...
5237
...kept for a floppy...
5239
LD HL,5439H 21 39 54
...otherwise " RIGID # at 5439H.
523C
GOSUB to the SYS0 routine at 4467H to display it.
523F
LD A,(IY+04H) FD 7E 04
Fetch DCT+04H...
5242
AND 0FH E6 0F
...bits 0-3, the select address...
5244
ADD A,90H C6 90
...changed to a hexadecimal digit (0-9, A-F)...
5246
DAA 27
(adjust)
5247
ADC A,40H CE 40
(add 40H with the carry)
5249
DAA 27
(adjust)
524A
...and display it.
524D
LD L,(IY+06H) FD 6E 06
HL = the highest cylinder (DCT+06H)...
5250
LD H,00H 26 00
(high byte 0)
5252
INC HL 23
...plus 1: the number of cylinders.
5253
BIT 3,(IY+03H) FD CB 03 5E
Test bit 3 of DCT+03H (rigid disk)...
5257
...and for a floppy JUMP to 525AH.
5259
ADD HL,HL 29
For a rigid disk double it.
525A
LD DE,544BH 11 4B 54
Point DE to the number field at 544BH.
525D
GOSUB to 53BFH to put the number there as three digits.
5260
LD HL,5444H 21 44 54
Point HL to , CYLS=nnn, at 5444H.
5263
GOSUB to 4467H to display it.
5266
BIT 3,(IY+03H) FD CB 03 5E
Test bit 3 of DCT+03H (rigid disk)...
526A
...and for a floppy JUMP to 527DH.
526C
BIT 2,(IY+03H) FD CB 03 56
Rigid disk: test bit 2 of DCT+03H (fixed disk).
5270
LD HL,5451H 21 51 54
Point HL to REMOVABLE at 5451H...
5273
...if bit 2 is 0...
5275
LD HL,545BH 21 5B 54
...otherwise to FIXED at 545BH.
5278
GOSUB to 4467H to display it.
527B
JUMP to 52EFH to end the line.
527D
BIT 6,(IY+03H) FD CB 03 76
Floppy: test bit 6 of DCT+03H (double density).
5281
LD A,53H 3E 53
Register A = S...
5283
...kept for single density...
5285
LD A,44H 3E 44
...otherwise D.
5287
Display it.
528A
LD HL,5461H 21 61 54
Point HL to DEN, SIDES= at 5461H.
528D
GOSUB to 4467H to display it.
5290
BIT 5,(IY+04H) FD CB 04 6E
Test bit 5 of DCT+04H (two sides).
5294
LD A,31H 3E 31
Register A = 1...
5296
...kept for one side...
5298
LD A,32H 3E 32
...otherwise 2.
529A
Display it.
529D
LD HL,546DH 21 6D 54
Point HL to , STEP= at 546DH.
52A0
GOSUB to 4467H to display it.
52A3
LD A,(IY+03H) FD 7E 03
Fetch DCT+03H...
52A6
AND 23H E6 23
...keep bits 0-1 (step rate) and bit 5 (8-inch)...
52A8
LD B,A 47
...and make them an index of 0-7 with the 8-inch bit as bit 2...
52A9
RRCA 0F
(rotate right)
52AA
RRCA 0F
(rotate right)
52AB
RRCA 0F
(rotate right)
52AC
OR B B0
(OR in the original bits)
52AD
RLCA 07
...times 2...
52AE
AND 0EH E6 0E
(keep bits 1-3)
52B0
ADD A,1EH C6 1E
...into the table of step rates at 541EH...
52B2
LD L,A 6F
(into L)
52B3
LD H,54H 26 54
(the high byte, 54H)
52B5
LD A,(HL) 7E
Fetch the first character...
52B6
INC HL 23
(next byte)
52B7
...and display it.
52BA
LD A,(HL) 7E
Fetch the second character...
52BB
...and display it.
52BE
LD HL,5475H 21 75 54
Point HL to MS at 5475H.
52C1
GOSUB to 4467H to display it.
52C4
BIT 5,(IY+03H) FD CB 03 6E
Test bit 5 of DCT+03H (8-inch drive)...
52C8
...and for an 8-inch drive JUMP to 52EFH to end the line.
52CA
LD HL,5479H 21 79 54
Point HL to , DLY= at 5479H.
52CD
GOSUB to 4467H to display it.
52D0
BIT 2,(IY+03H) FD CB 03 56
Test bit 2 of DCT+03H (half-second delay).
52D4
LD A,20H 3E 20
Register A = space...
52D6
LD B,31H 06 31
...and Register B = 1 for one second...
52D8
...if bit 2 is 0...
52DA
LD A,2EH 3E 2E
...otherwise ....
52DC
LD B,35H 06 35
...and 5 for half a second.
52DE
Display the first character...
52E1
LD A,B 78
...and the second.
52E2
(display it)
52E5
LD A,20H 3E 20
Display a space...
52E7
(display it)
52EA
LD A,53H 3E 53
...and S.
52EC
(display it)
52EF
LD A,0DH 3E 0D
Display a carriage return.
52F1
(display it)
52F4
POP BC C1
Restore the drive number.
52F5
INC C 0C
Next drive.
52F6
LD A,C 79
(into A)
52F7
CP 08H FE 08
After drive 7...
52F9
...(otherwise LOOP back to 5202H)...

52FCH - DEVICE Command: Devices

Goes through the device control blocks, eight bytes each: 4015H, 401DH and 4025H, then 43C0H-43F8H. A block whose type byte (+00H) is 0 is not in use. Bits of the type byte: 0 input, 1 output, 3 NIL, 4 routed or linked (+01H-02H then point to the next block, or to the FCB of a file, whose byte 0 has bit 7 set), otherwise +01H-02H is the driver address. The name is at +06H-07H.

52FC
LD HL,4015H 21 15 40
...point HL to the first device control block, 4015H.
52FF
LD A,(HL) 7E
Fetch its type byte.
5300
OR A B7
Test it.
5301
If it is not in use, JUMP to 5366H.
5303
LD DE,53F6H 11 F6 53
Point DE to the line buffer at 53F6H.
5306
PUSH HL E5
Save the block address.
5307
LD A,L 7D
Point HL to +06H, the name...
5308
ADD A,06H C6 06
(add 06H)
530A
LD L,A 6F
(into L)
530B
LD A,2AH 3E 2A
Put *...
530D
LD (DE),A 12
(store it)
530E
INC DE 13
(next byte)
530F
LD A,(HL) 7E
...and the two letters of the name in the line.
5310
LD (DE),A 12
(store it)
5311
INC DE 13
(next byte)
5312
INC L 2C
(second letter)
5313
LD A,(HL) 7E
(fetch it)
5314
LD (DE),A 12
(store it)
5315
INC DE 13
(next byte)
5316
POP HL E1
Restore the block address...
5317
PUSH HL E5
...and save it again.
5318
BIT 4,(HL) CB 66
Test bit 4 of the type byte (routed or linked).
531A
If not, JUMP to 533FH.
531C
INC L 2C
Fetch +01H-02H...
531D
LD A,(HL) 7E
(low byte)
531E
INC L 2C
(next byte)
531F
LD H,(HL) 66
(high byte)
5320
LD L,A 6F
...HL = the block or FCB it leads to.
5321
BIT 7,(HL) CB 7E
Bit 7 of its first byte set means an open file...
5323
...JUMP to 5378H to show the file name.
5325
PUSH HL E5
Save the address.
5326
GOSUB to 53A0H to put the arrows for this block in the line.
5329
LD A,L 7D
Point HL to its name at +06H...
532A
ADD A,06H C6 06
(add 06H)
532C
LD L,A 6F
(into L)
532D
LD A,2AH 3E 2A
...and put *...
532F
LD (DE),A 12
(store it)
5330
INC DE 13
(next byte)
5331
LD A,(HL) 7E
...and the two letters in the line.
5332
LD (DE),A 12
(store it)
5333
INC DE 13
(next byte)
5334
INC L 2C
(second letter)
5335
LD A,(HL) 7E
(fetch it)
5336
LD (DE),A 12
(store it)
5337
INC DE 13
(next byte)
5338
POP HL E1
Restore the address of the block.
5339
BIT 4,(HL) CB 66
If it is routed or linked too (bit 4)...
533B
...LOOP back to 531CH to follow it.
533D
Otherwise JUMP to 535CH to end the line.
533F
Not routed or linked: GOSUB to 53A0H to put the arrows in the line.
5342
BIT 3,(HL) CB 5E
Bit 3 set (NIL)...
5344
...JUMP to 5396H to put NIL in the line.
5346
LD A,58H 3E 58
Otherwise put X...
5348
LD (DE),A 12
(store it)
5349
INC DE 13
(next byte)
534A
LD A,27H 3E 27
...and a quote...
534C
LD (DE),A 12
(store it)
534D
INC DE 13
(next byte)
534E
INC L 2C
...then the driver address at +01H-02H...
534F
LD A,(HL) 7E
(low byte)
5350
INC L 2C
(next byte)
5351
LD H,(HL) 66
(high byte)
5352
LD L,A 6F
(into HL)
5353
EX DE,HL EB
(DE = the address, HL = the line)
5354
...as four hexadecimal digits through the SYS0 routine at 4DE7H...
5357
EX DE,HL EB
(swap back)
5358
LD A,27H 3E 27
...and a closing quote.
535A
LD (DE),A 12
(store it)
535B
INC DE 13
(next byte)
535C
LD A,0DH 3E 0D
End the line with a carriage return.
535E
LD (DE),A 12
(store it)
535F
LD HL,53F6H 21 F6 53
Point HL to the line buffer at 53F6H.
5362
GOSUB to 4467H to display it.
5365
POP HL E1
Restore the block address.
5366
LD A,L 7D
Next block: add 8.
5367
ADD A,08H C6 08
(add 08H)
5369
LD L,A 6F
(into L)
536A
Past 43F8H (a carry): JUMP to 402DH, back to VTOS READY.
536D
CP 2DH FE 2D
After 4025H (L = 2DH)...
536F
...(otherwise LOOP back to 52FFH)...
5372
LD HL,43C0H 21 C0 43
...continue at 43C0H.
5375
LOOP back to 52FFH.
5378
PUSH HL E5
Routed to a file: save the FCB address.
5379
LD HL,53F1H 21 F1 53
Put <=> from 53F1H in the line.
537C
LD BC,0005H 01 05 00
(5 bytes)
537F
LDIR ED B0
(copy)
5381
POP HL E1
Restore the FCB address.
5382
LD A,L 7D
Point HL to FCB+06H...
5383
ADD A,06H C6 06
(add 06H)
5385
LD L,A 6F
(into L)
5386
LD C,(HL) 4E
...Register C = the drive...
5387
INC HL 23
(next byte)
5388
LD B,(HL) 46
...and Register B = the directory entry code.
5389
PUSH DE D5
Save the line pointer.
538A
GOSUB to the SYS0 routine at 44BBH (SYS3, request 30H) to put the file name, as NAME/EXT:d, in the line, ending with 03H.
538D
POP DE D1
Restore the line pointer.
538E
LD A,(DE) 1A
Look for the 03H at the end...
538F
CP 03H FE 03
(compare with 03H)
5391
...and when found, JUMP to 535CH to end the line there.
5393
INC DE 13
(next byte)
5394
(loop)
5396
LD HL,53EEH 21 EE 53
NIL: copy NIL from 53EEH...
5399
LD BC,0003H 01 03 00
(3 bytes)
539C
LDIR ED B0
(copy)
539E
...and JUMP to 535CH to end the line.

53A0H - Put the Arrows in the Line

HL points to a device control block and DE to the line. Puts <=> in the line, with < only if bit 0 (input) of the type byte is set and > only if bit 1 (output) is set; a space is put in the place of an arrow that is left out.

53A0
LD A,20H 3E 20
A space.
53A2
LD (DE),A 12
(store it)
53A3
INC DE 13
(next byte)
53A4
BIT 0,(HL) CB 46
Bit 0 (input)?
53A6
If not, JUMP to 53AAH with a space.
53A8
LD A,3CH 3E 3C
Otherwise <.
53AA
LD (DE),A 12
(store it)
53AB
INC DE 13
(next byte)
53AC
LD A,3DH 3E 3D
=
53AE
LD (DE),A 12
(store it)
53AF
INC DE 13
(next byte)
53B0
LD A,20H 3E 20
A space...
53B2
BIT 1,(HL) CB 4E
...unless bit 1 (output) is set...
53B4
(JUMP to 53B8H)
53B6
LD A,3EH 3E 3E
...then >.
53B8
LD (DE),A 12
(store it)
53B9
INC DE 13
(next byte)
53BA
LD A,20H 3E 20
A space.
53BC
LD (DE),A 12
(store it)
53BD
INC DE 13
(next byte)
53BE
RET C9
RETURN.

53BFH - Three-Digit Number

Puts the number in HL (0-999) at DE as three decimal digits, with leading zeros shown as spaces.

53BF
LD A,20H 3E 20
Leading zeros are spaces.
53C1
LD BC,0064H 01 64 00
The hundreds...
53C7
LD BC,000AH 01 0A 00
...the tens...
53CD
LD A,L 7D
...and the units, always as a digit.
53CE
ADD A,30H C6 30
(as an ASCII digit)
53D0
LD (DE),A 12
(store it)
53D1
INC DE 13
(next byte)
53D2
RET C9
RETURN.
53D3
PUSH DE D5
One digit: HL divided by BC by subtraction. Save DE.
53D4
LD E,A 5F
Register E = the character for a leading zero (space, then 0 once a digit has been shown).
53D5
LD D,FFH 16 FF
Register D counts, from FFH.
53D7
XOR A AF
Clear the Carry flag.
53D8
INC D 14
Count...
53D9
SBC HL,BC ED 42
(subtract BC)
53DB
(until it goes below 0)
53DD
ADD HL,BC 09
Add back the last subtraction.
53DE
LD A,E 7B
Register A = the character for a zero...
53DF
LD B,D 42
...and Register B = the digit.
53E0
POP DE D1
Restore DE.
53E1
LD (DE),A 12
Store the zero character.
53E2
INC B 04
Is the digit 0?
53E3
DEC B 05
(test B)
53E4
If so, JUMP to 53ECH: Register A is still the zero character.
53E6
LD A,B 78
Otherwise store the digit...
53E7
ADD A,30H C6 30
(as an ASCII digit)
53E9
LD (DE),A 12
(store it)
53EA
LD A,30H 3E 30
...and from now on zeros are shown as 0.
53EC
INC DE 13
Next position.
53ED
RET C9
RETURN with the zero character in Register A.
53EE-53F0
DEFM "NIL" 4E 49 4C
Copied at 5396H.
53F1-53F5
DEFM " <=> " 20 3C 3D 3E 20
Copied at 5378H for a device routed to a file.
53F6-541D
DEFS 40
The line buffer. Not in the file.
541E-542D
DEFM " 6122040 3 61015" 20 36 31 32 32 30 34 30 20 33 20 36 31 30 31 35
The step rates in milliseconds, two characters each: 6, 12, 20, 40 for 5-inch drives and 3, 6, 10, 15 for 8-inch drives.
542E-5438
DEFM 22H," FLOPPY #",03H 22 20 46 4C 4F 50 50 59 20 23 03
Displayed at 523CH (22H is the inch mark after the size).
5439-5443
DEFM 22H," RIGID #",03H 22 20 52 49 47 49 44 20 20 23 03
Displayed at 523CH.
5444-544A
DEFM ", CYLS=" 2C 20 43 59 4C 53 3D
Displayed at 5263H...
544B-544D
DEFM " " 20 20 20
...with the number of cylinders put here at 525DH...
544E-5450
DEFM ", ",03H 2C 20 03
...and this.
5451-545A
DEFM "REMOVABLE",03H 52 45 4D 4F 56 41 42 4C 45 03
Displayed at 5278H.
545B-5460
DEFM "FIXED",03H 46 49 58 45 44 03
Displayed at 5278H.
5461-546C
DEFM "DEN, SIDES=",03H 44 45 4E 2C 20 53 49 44 45 53 3D 03
Displayed at 528DH.
546D-5474
DEFM ", STEP=",03H 2C 20 53 54 45 50 3D 03
Displayed at 52A0H.
5475-5478
DEFM " MS",03H 20 4D 53 03
Displayed at 52C1H.
5479-547F
DEFM ", DLY=",03H 2C 20 44 4C 59 3D 03
Displayed at 52CDH.

ISAM 62H - LINK - Offset 2DC7

LINK (LINK *d1 *d2) links two devices: whatever goes to device d1 also goes to d2, and when d1 has no character to give, d2 is asked for one. LINK lowers the top of memory (4049H) by 30 bytes, copies a small driver there with the addresses of d1's old driver and of d2's control block filled in, and makes it d1's driver. The type byte of d1 is not changed, so DEVICE shows the new driver address. Not allowed while a program has put a jump at 402DH. The member loads at 5200H-5303H (260 bytes); the two FCBs at 5304H and 5324H lie past it.

HL points to the text after LINK.

5200
LD A,(402DH) 3A 2D 40
Fetch the first byte at 402DH, the DOS exit.
5203
CP C3H FE C3
If a program has put a JP (C3H) there...
5205
...JUMP to 52D1H to display CAN'T -- ONLY VALID AT VTOS COMMAND LEVEL.
5208
LD DE,5304H 11 04 53
Point DE to the first FCB at 5304H.
520B
GOSUB to the SYS0 routine at 441CH to read the first device name into it.
520E
If there is none (NZ), JUMP to 52B3H to display DEVICE SPEC REQUIRED.
5211
LD A,(DE) 1A
Fetch its first character.
5212
CP 2AH FE 2A
It must be *...
5214
...otherwise JUMP to 52B3H.
5217
LD DE,5324H 11 24 53
Point DE to the second FCB at 5324H.
521A
GOSUB to 441CH to read the second device name.
521D
If there is none, JUMP to 52B3H.
5220
LD A,(DE) 1A
Fetch its first character.
5221
CP 2AH FE 2A
It must be *...
5223
...otherwise JUMP to 52B3H.
5226
LD DE,(5305H) ED 5B 05 53
Fetch the two letters of the first name.
522A
GOSUB to 5288H to find its device control block.
522D
If there is none, JUMP to the error exit at 52AEH.
5230
PUSH HL E5
Save the address of the first block.
5231
LD DE,(5325H) ED 5B 25 53
Fetch the two letters of the second name.
5235
GOSUB to 5288H to find its device control block.
5238
If there is none, JUMP to 52AEH.
523B
LD (5276H),HL 22 76 52
Put the address of the second block into the driver at 5275H...
523E
LD (5283H),HL 22 83 52
...and at 5282H (the operands of the LD DE instructions).
5241
POP HL E1
Restore the address of the first block.
5242
INC HL 23
Point to +01H, its driver address.
5243
PUSH HL E5
Save that pointer.
5244
LD A,(HL) 7E
Fetch the driver address...
5245
INC HL 23
(next byte)
5246
LD H,(HL) 66
(high byte)
5247
LD L,A 6F
(into HL)
5248
LD (526FH),HL 22 6F 52
...and put it into the driver at 526EH...
524B
LD (527EH),HL 22 7E 52
...and at 527DH (the operands of the CALL instructions).
524E
LD HL,(4049H) 2A 49 40
Fetch the top of memory.
5251
LD BC,001EH 01 1E 00
Load Register Pair BC with 001EH: 30 bytes.
5254
XOR A AF
Clear the Carry flag.
5255
SBC HL,BC ED 42
Lower the top of memory by 30 bytes...
5257
LD (4049H),HL 22 49 40
...and store it.
525A
INC HL 23
HL = the first byte of the space.
525B
PUSH HL E5
Save it.
525C
EX DE,HL EB
DE = that address.
525D
LD HL,526AH 21 6A 52
Point HL to the driver at 526AH.
5260
LDIR ED B0
Copy the 30 bytes.
5262
POP DE D1
Restore the address of the copy.
5263
POP HL E1
Restore the pointer to +01H of the first block.
5264
LD (HL),E 73
Store the address of the copy as its driver...
5265
INC HL 23
(next byte)
5266
LD (HL),D 72
(high byte)
5267
JUMP to 402DH: back to VTOS READY.

Copied below the top of memory and used as the driver of the first device. The Carry flag set means a request for input. Output goes to the old driver of the first device and then, through the ROM routine at 001BH, to the second device; the flags and Register A that the old driver returned are passed back. Input comes from the old driver, or, if that gives no character (A = 0), from the second device through the ROM routine at 0013H.

526A
Carry set (input): JUMP to 527DH.
526C
PUSH AF F5
Output: save AF...
526D
PUSH BC C5
...and BC (Register C is the character).
526E
CALL 0000H CD 00 00
GOSUB to the old driver of the first device (the operand is filled in at 5248H).
5271
POP BC C1
Restore BC.
5272
PUSH AF F5
Save what the old driver returned...
5273
POP HL E1
...into HL...
5274
EX (SP),HL E3
...and swap it with the AF saved at the start, which is discarded.
5275
LD DE,0000H 11 00 00
Point DE to the control block of the second device (filled in at 523BH).
5278
GOSUB to the ROM routine at 001BH to send the byte to it.
527B
POP AF F1
Restore what the old driver returned.
527C
RET C9
RETURN.
5280
OR A B7
If it gave a character...
5281
RET NZ C0
...RETURN with it.
5282
LD DE,0000H 11 00 00
Otherwise point DE to the control block of the second device (filled in at 523EH)...
5285
...and JUMP to the ROM routine at 0013H to get a character from it.

E and D hold the two letters of a device name. Looks through the device control blocks at 4015H, 401DH, 4025H and 43C0H-43F8H for one with that name at +06H-07H. Returns Z with HL = the block, or NZ with A = 08H (device not available).

5288
LD HL,4015H 21 15 40
Start at 4015H.
528C
LD A,L 7D
Point HL to +06H, the name...
528D
ADD A,06H C6 06
(add 06H)
528F
LD L,A 6F
(into L)
5290
LD A,(HL) 7E
Fetch the first letter.
5291
INC L 2C
(next byte)
5292
CP E BB
Does it match?
5293
If not, JUMP to 529CH.
5295
LD A,(HL) 7E
Fetch the second letter.
5296
CP D BA
Does it match?
5297
If not, JUMP to 529CH.
5299
POP HL E1
Found: restore the block address...
529A
XOR A AF
...set Z...
529B
RET C9
...and RETURN.
529D
INC L 2C
Next block (+08H); past 43F8H (L = 00H)...
529E
...(otherwise JUMP to 52A4H)...
52A0
LD A,08H 3E 08
...there is no such device: A = 08H...
52A2
OR A B7
...with NZ...
52A3
RET C9
...RETURN.
52A5
CP 2DH FE 2D
(compare with 2DH)
52A7
...(otherwise LOOP back to 528BH)...
52A9
LD HL,43C0H 21 C0 43
...continue at 43C0H.
52AC
LOOP back to 528BH.

52AE
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
52B0
JUMP to the SYS0 error handler at 4409H.
52B6
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
52B9
JUMP to 4030H: back to VTOS READY.
52D4
GOSUB to 447BH to display it.
52D7
JUMP to 4030H.

ISAM 63H - RESET - Offset 2ED6

RESET puts devices back to their start-up state. RESET *xx resets one device: a file it is routed to is closed; the keyboard (KI), display (DO) and printer (PR) get their original control block back, and any other device becomes NIL (type 08H). Without a device, every device is reset: all routed files are closed, the KI, DO and PR blocks are restored, the blocks at 43C0H-43D7H get their original contents (JL as NIL, SI routed to KI, LO routed to DO) and 43D8H-43FFH are cleared. RESET then also gives back the memory above the top of memory by setting 4049H to the top of RAM, unless a timer task still runs above the top of memory (CAN'T RESET MEMORY, FOREGROUND TASK(S) EXIST) or a program has put a jump at 402DH. The screen is cleared when the display was reset. The member loads at 5200H-530BH and 532CH-5404H (485 bytes); 530CH-532BH holds a copy of an FCB while a file is being closed.

5200H - RESET Command

HL points to the text after RESET.

5200
PUSH HL E5
Save the line pointer.
5201
LD HL,(43B8H) 2A B8 43
Put the original driver addresses of the keyboard (43B8H)...
5204
LD (532DH),HL 22 2D 53
...into the KI image at 532DH...
5207
LD HL,(43BAH) 2A BA 43
...of the display (43BAH)...
520A
LD (5335H),HL 22 35 53
...into the DO image at 5335H...
520D
LD HL,(43BCH) 2A BC 43
...and of the printer (43BCH)...
5210
LD (533DH),HL 22 3D 53
...into the PR image at 533DH.
5213
POP HL E1
Restore the line pointer.
5214
LD DE,5405H 11 05 54
Point DE to the FCB at 5405H.
5217
GOSUB to the SYS0 routine at 441CH to read a device name into it.
521A
If there is none (NZ), JUMP to 525CH to reset everything.
521D
LD A,(DE) 1A
Fetch its first character.
521E
CP 2AH FE 2A
It must be *...
5220
...otherwise JUMP to 5387H to display DEVICE SPEC REQUIRED.
5223
LD DE,(5406H) ED 5B 06 54
Fetch the two letters of the name.
5227
GOSUB to 535CH to find its device control block.
522A
If there is none, JUMP to the error exit at 5382H.
522D
PUSH HL E5
Save the block address.
522E
GOSUB to 52EAH to close a file the device is routed to.
5231
POP HL E1
Restore the block address.
5232
LD (HL),08H 36 08
Make the device NIL (type 08H).
5234
LD A,40H 3E 40
A block in the 43xxH area...
5236
CP H BC
(compare with the high byte)
5237
...is done: JUMP to 402DH, back to VTOS READY.
523A
DI F3
KI, DO or PR: disable interrupts.
523B
LD D,H 54
DE = the block address.
523C
LD E,L 5D
(low byte)
523D
XOR A AF
Clear the Carry flag.
523E
LD BC,4015H 01 15 40
HL = the block address - 4015H...
5241
SBC HL,BC ED 42
(subtract)
5243
LD BC,532CH 01 2C 53
...+ 532CH: the matching original block.
5246
ADD HL,BC 09
(add)
5247
LD BC,0008H 01 08 00
Copy its eight bytes back.
524A
LDIR ED B0
(copy)
524C
EI FB
Enable interrupts.
524D
LD A,25H 3E 25
If the display was reset (DE = 4025H)...
524F
CP E BB
(compare with the low byte)
5250
...(otherwise JUMP to 402DH)...
5253
LD HL,5309H 21 09 53
...clear the screen with the codes at 5309H...
5256
(GOSUB to the SYS0 routine at 4467H)
5259
...and JUMP to 402DH.
525C
LD HL,4015H 21 15 40
Reset everything: start with the block at 4015H.
525F
PUSH HL E5
Save the block address.
5260
GOSUB to 52EAH to close a file it is routed to.
5263
POP HL E1
Restore the block address.
5264
LD A,L 7D
Next block (+08H)...
5265
ADD A,08H C6 08
(add 08H)
5267
LD L,A 6F
(into L)
5268
...until past 43F8H: JUMP to 5273H.
526A
CP 2DH FE 2D
After 4025H (L = 2DH)...
526C
...(otherwise LOOP back to 525FH)...
526E
LD HL,43C0H 21 C0 43
...continue at 43C0H.
5271
LOOP back to 525FH.
5273
LD B,0CH 06 0C
Twelve timer task vectors...
5275
LD HL,4500H 21 00 45
...at 4500H.
5278
LD E,(HL) 5E
Fetch one into DE.
5279
INC HL 23
(next byte)
527A
LD D,(HL) 56
(high byte)
527B
INC HL 23
(next byte)
527C
PUSH HL E5
Save the table pointer.
527D
LD HL,(4049H) 2A 49 40
Fetch the top of memory.
5280
XOR A AF
Clear the Carry flag.
5281
SBC HL,DE ED 52
Is the task above the top of memory?
5283
POP HL E1
Restore the table pointer.
5284
If so, JUMP to 52A2H: the memory cannot be given back.
5286
LOOP back to 5278H for the next vector.
5288
LD A,(402DH) 3A 2D 40
Fetch the first byte at 402DH.
528B
CP C3H FE C3
If a program has put a JP (C3H) there...
528D
...JUMP to 53A5H to display CAN'T -- VALID ONLY AT VTOS COMMAND LEVEL.
5290
DI F3
Disable interrupts.
5291
LD HL,FFFFH 21 FF FF
Find the top of RAM, starting at FFFFH.
5294
LD A,(HL) 7E
Fetch the byte...
5295
LD B,A 47
...keep it...
5296
CPL 2F
...complement it...
5297
LD (HL),A 77
...store it...
5298
CP (HL) BE
...see whether it stuck...
5299
LD (HL),B 70
...and put the original back.
529A
If it stuck, this is RAM: JUMP to 52B1H.
529C
LD A,H 7C
Otherwise go down 1K...
529D
SUB 04H D6 04
(subtract 04H)
529F
LD H,A 67
(into H)
52A0
...and LOOP back to 5294H.
52A2
LD HL,53D8H 21 D8 53
Point HL to CAN'T RESET MEMORY, FOREGROUND TASK(S) EXIST at 53D8H.
52A5
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
52A8
LD A,03H 3E 03
Change the clear-screen codes to an empty text (03H)...
52AA
LD (5309H),A 32 09 53
...so that the message stays on the screen.
52AD
DI F3
Disable interrupts.
52AE
LD HL,(4049H) 2A 49 40
Keep the top of memory as it is.
52B1
LD (4049H),HL 22 49 40
Store the top of memory.
52B4
LD HL,(4020H) 2A 20 40
Keep the cursor address (4020H).
52B7
PUSH HL E5
(save it)
52B8
LD HL,532CH 21 2C 53
Copy the original KI, DO and PR blocks from 532CH...
52BB
LD DE,4015H 11 15 40
...to 4015H...
52BE
LD BC,0018H 01 18 00
...24 bytes.
52C1
LDIR ED B0
(copy)
52C3
POP HL E1
Put the cursor address back.
52C4
LD (4020H),HL 22 20 40
(store it)
52C7
LD HL,0000H 21 00 00
Clear 43BEH-43BFH.
52CA
LD (43BEH),HL 22 BE 43
(store it)
52CD
LD HL,5344H 21 44 53
Copy the original JL, SI and LO blocks from 5344H...
52D0
LD DE,43C0H 11 C0 43
...to 43C0H...
52D3
LD BC,0018H 01 18 00
...24 bytes.
52D6
LDIR ED B0
(copy)
52D8
LD HL,43D8H 21 D8 43
Clear 43D8H-43FFH, the other five blocks.
52DB
XOR A AF
(A = 0)
52DC
LD (HL),A 77
(store it)
52DD
INC L 2C
(next byte)
52DE
(until L wraps to 00H)
52E0
EI FB
Enable interrupts.
52E1
LD HL,5309H 21 09 53
Clear the screen with the codes at 5309H (or display nothing).
52E4
(GOSUB to 4467H)
52E7
JUMP to 402DH: back to VTOS READY.

52EAH - Close a Routed File

HL points to a device control block. The chain of routes and links (bit 4 of the type byte, with the next block at +01H-02H) is followed to its end; if that is an open file (bit 7 of byte 0 of its FCB), the FCB is copied to 530CH and the file is closed from the copy.

52EA
BIT 4,(HL) CB 66
Routed or linked (bit 4)?
52EC
If not, JUMP to 52F5H.
52EE
INC HL 23
Fetch +01H-02H...
52EF
LD A,(HL) 7E
(low byte)
52F0
INC HL 23
(next byte)
52F1
LD H,(HL) 66
(high byte)
52F2
LD L,A 6F
...into HL...
52F3
...and LOOP back to 52EAH.
52F5
BIT 7,(HL) CB 7E
An open file (bit 7)?
52F7
RET Z C8
If not, RETURN.
52F8
LD DE,530CH 11 0C 53
Copy the FCB to 530CH...
52FB
PUSH DE D5
(save the address)
52FC
LD BC,0020H 01 20 00
...32 bytes...
52FF
LDIR ED B0
(copy)
5301
POP DE D1
...and point DE to the copy.
5302
GOSUB to the SYS0 routine at 4428H to close the file.
5305
If that failed (NZ), JUMP to 5382H.
5308
RET C9
RETURN.
5309-530B
DEFB 1CH,1FH,03H 1C 1F 03
Displayed at 5256H and 52E4H: cursor home and clear to the end of the screen. 5309H is changed to 03H at 52AAH.
530C-532B
DEFS 32
The copy of the FCB of a routed file (52F8H). Not in the file.
532C-5333
DEFB 01H : DEFW 0000H : DEFB 00H,00H,00H : DEFM "KI" 01 00 00 00 00 00 4B 49
The original keyboard block (type 01H, input); the driver address is filled in from 43B8H at 5201H.
5334-533B
DEFB 07H : DEFW 0000H : DEFB 00H,3CH,00H : DEFM "DO" 07 00 00 00 3C 00 44 4F
The original display block (type 07H); the driver address is filled in from 43BAH at 5207H.
533C-5343
DEFB 06H : DEFW 0000H : DEFB 42H,00H,00H : DEFM "PR" 06 00 00 42 00 00 50 52
The original printer block (type 06H); the driver address is filled in from 43BCH at 520DH.
5344-534B
DEFB 08H : DEFW 0000H : DEFB 00H,00H,00H : DEFM "JL" 08 00 00 00 00 00 4A 4C
The original JL (job log) block: NIL.
534C-5353
DEFB 10H : DEFW 4015H : DEFB 00H,00H,00H : DEFM "SI" 10 15 40 00 00 00 53 49
The original SI block: routed to the keyboard (4015H).
5354-535B
DEFB 10H : DEFW 401DH : DEFB 00H,00H,00H : DEFM "LO" 10 1D 40 00 00 00 4C 4F
The original LO block: routed to the display (401DH).

535CH - Find a Device Control Block

E and D hold the two letters of a device name. Looks through the device control blocks at 4015H, 401DH, 4025H and 43C0H-43F8H for one with that name at +06H-07H. Returns Z with HL = the block, or NZ with A = 08H (device not available).

535C
LD HL,4015H 21 15 40
Start at 4015H.
535F
PUSH HL E5
Save the block address.
5360
LD A,L 7D
Point HL to +06H, the name...
5361
ADD A,06H C6 06
(add 06H)
5363
LD L,A 6F
(into L)
5364
LD A,(HL) 7E
Fetch the first letter.
5365
INC L 2C
(next byte)
5366
CP E BB
Does it match?
5367
If not, JUMP to 5370H.
5369
LD A,(HL) 7E
Fetch the second letter.
536A
CP D BA
Does it match?
536B
If not, JUMP to 5370H.
536D
POP HL E1
Found: restore the block address...
536E
XOR A AF
...set Z...
536F
RET C9
...and RETURN.
5370
POP AF F1
Discard the saved block address (HL now points to +07H).
5371
INC L 2C
Next block (+08H); past 43F8H (L = 00H)...
5372
...(otherwise JUMP to 5378H)...
5374
LD A,08H 3E 08
...there is no such device: A = 08H...
5376
OR A B7
...with NZ...
5377
RET C9
...RETURN.
5378
LD A,L 7D
After 4025H (L = 2DH)...
5379
CP 2DH FE 2D
(compare with 2DH)
537B
...(otherwise LOOP back to 535FH)...
537D
LD HL,43C0H 21 C0 43
...continue at 43C0H.
5380
LOOP back to 535FH.

5382H - Error Exits

5382
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
5384
JUMP to the SYS0 error handler at 4409H.
5387
LD HL,5390H 21 90 53
Point HL to DEVICE SPEC REQUIRED at 5390H.
538A
GOSUB to 447BH to display it.
538D
JUMP to 4030H: back to VTOS READY.
5390-53A4
DEFM "DEVICE SPEC REQUIRED",0DH 44 45 56 49 43 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 538AH.
53A5
LD HL,53AEH 21 AE 53
Point HL to the message at 53AEH.
53A8
GOSUB to 447BH to display it.
53AB
JUMP to 4030H.
53AE-53D7
DEFM "CAN'T -- VALID ONLY AT VTOS COMMAND LEVEL",0DH 43 41 4E 27 54 20 2D 2D 20 56 41 4C 49 44 20 4F 4E 4C 59 20 41 54 20 56 54 4F 53 20 43 4F 4D 4D 41 4E 44 20 4C 45 56 45 4C 0D
Displayed at 53A8H.
53D8-5404
DEFM "CAN'T RESET MEMORY, FOREGROUND TASK(S) EXIST",0DH 43 41 4E 27 54 20 52 45 53 45 54 20 4D 45 4D 4F 52 59 2C 20 46 4F 52 45 47 52 4F 55 4E 44 20 54 41 53 4B 28 53 29 20 45 58 49 53 54 0D
Displayed at 52A5H.

ISAM 64H - ROUTE - Offset 30CA

ROUTE sends a device somewhere else: ROUTE *xx *yy routes device xx to device yy, ROUTE *xx filespec routes it to a file, and ROUTE *xx (NIL) makes it NIL. If device xx does not exist, a free device control block (one with no name) is given the name. A file that the device was routed to before is closed first. For a file, ROUTE opens it (creating it if necessary), positions it to its end so that output is added, and lowers the top of memory by 288 bytes for its 256-byte buffer and its FCB; this is not allowed while a program has put a jump at 402DH. The type byte of the block becomes 10H (routed) with +01H-02H pointing to the device block or FCB, or 08H (NIL). The member loads at 5200H-532CH, 534DH-5388H and 53C9H-53EEH (399 bytes); 532DH-534CH is the FCB copy used while closing a file and 5389H-53C8H are the two FCBs.

5200H - ROUTE Command

HL points to the text after ROUTE.

5200
LD DE,5389H 11 89 53
Point DE to the first FCB at 5389H.
5203
GOSUB to the SYS0 routine at 441CH to read the device name into it.
5206
If there is none (NZ), JUMP to 5352H to display DEVICE SPEC REQUIRED.
5209
LD A,(DE) 1A
Fetch its first character.
520A
CP 2AH FE 2A
It must be *...
520C
...otherwise JUMP to 5352H.
520F
LD DE,0000H 11 00 00
Clear the NIL value...
5212
LD (5220H),DE ED 53 20 52
...at 5220H (the operand of the LD BC at 521FH).
5216
LD DE,5305H 11 05 53
Point DE to the parameter table at 5305H.
5219
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
521C
If a parameter was not recognized (NZ), JUMP to 5370H to display PARAMETER ERROR.
521F
LD BC,0000H 01 00 00
Load BC with the NIL value.
5222
LD A,B 78
Test it...
5223
OR C B1
(OR the low byte)
5224
...and if NIL was given, JUMP to 52D6H.
5227
LD DE,53A9H 11 A9 53
Point DE to the second FCB at 53A9H.
522A
GOSUB to 441CH to read the destination into it.
522D
If there is none, JUMP to 5352H.
5230
LD A,(DE) 1A
Fetch its first character.
5231
CP 2AH FE 2A
Is it *?
5233
If not, it is a file: JUMP to 526EH.
5235
LD DE,(53AAH) ED 5B AA 53
Fetch the two letters of the destination device.
5239
GOSUB to 53C9H to find its device control block.
523C
If there is none, JUMP to the error exit at 534DH.
523F
PUSH HL E5
Save the destination (a device block, or from 52A1H an FCB).
5240
LD DE,(538AH) ED 5B 8A 53
Fetch the two letters of the device being routed.
5244
GOSUB to 53C9H to find its block.
5247
If it exists, JUMP to 5256H.
5249
PUSH DE D5
Otherwise save the name...
524A
LD DE,0000H 11 00 00
...and look for a free block (name 0000H).
5250
LD A,21H 3E 21
Load Register A with 21H (no device space available); the flags are kept.
5252
If there is no free block, JUMP to 534DH.
5255
POP DE D1
Restore the name.
5256
PUSH HL E5
Save the block address.
5257
GOSUB to 530EH to close a file the device is routed to.
525A
POP HL E1
Restore the block address.
525B
DI F3
Disable interrupts.
525C
LD (HL),10H 36 10
Type 10H: routed.
525E
INC L 2C
(next byte)
525F
POP BC C1
Fetch the destination...
5260
LD (HL),C 71
...and store it at +01H...
5261
INC L 2C
(next byte)
5262
LD (HL),B 70
...and +02H.
5263
LD A,L 7D
Point to +06H...
5264
ADD A,04H C6 04
(add 04H)
5266
LD L,A 6F
(into L)
5267
LD (HL),E 73
...and store the name.
5268
INC L 2C
(next byte)
5269
LD (HL),D 72
(second letter)
526A
EI FB
Enable interrupts.
526B
JUMP to 402DH: back to VTOS READY.
526E
LD A,(402DH) 3A 2D 40
A file: fetch the first byte at 402DH.
5271
CP C3H FE C3
If a program has put a JP (C3H) there...
5273
...JUMP to 52A3H to display CAN'T -- ONLY VALID AT VTOS COMMAND LEVEL.
5276
LD HL,(4049H) 2A 49 40
Fetch the top of memory...
5279
INC HL 23
...plus 1...
527A
DEC H 25
...less 256: the file's buffer.
527B
PUSH HL E5
Save its address.
527C
LD B,00H 06 00
Register B = 00H: record length 256.
527E
GOSUB to the SYS0 routine at 4420H to open the file, or create it.
5281
If that failed (NZ), JUMP to 534DH.
5284
GOSUB to the SYS0 routine at 4448H to position it to its end.
5287
If that went well, JUMP to 528EH.
5289
CP 1CH FE 1C
Error 1CH (end of file)...
528B
...is expected; any other error: JUMP to 534DH.
528E
POP HL E1
Restore the buffer address.
528F
LD BC,0020H 01 20 00
Load BC with 0020H: 32 bytes for the FCB...
5292
XOR A AF
(clear the Carry flag)
5293
SBC HL,BC ED 42
...below the buffer.
5295
PUSH HL E5
Save the FCB address.
5296
DEC HL 2B
The byte below it...
5297
LD (4049H),HL 22 49 40
...is the new top of memory.
529A
POP DE D1
DE = the FCB address.
529B
PUSH DE D5
(save it again as the destination)
529C
LD HL,53A9H 21 A9 53
Copy the FCB from 53A9H...
529F
LDIR ED B0
...32 bytes.
52A1
JUMP to 5240H.
52A3
LD HL,52ACH 21 AC 52
Point HL to the message at 52ACH.
52A6
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
52A9
JUMP to 4030H: back to VTOS READY.
52AC-52D5
DEFM "CAN'T -- ONLY VALID AT VTOS COMMAND LEVEL",0DH 43 41 4E 27 54 20 2D 2D 20 4F 4E 4C 59 20 56 41 4C 49 44 20 41 54 20 56 54 4F 53 20 43 4F 4D 4D 41 4E 44 20 4C 45 56 45 4C 0D
Displayed at 52A6H.
52D6
LD DE,(538AH) ED 5B 8A 53
NIL: fetch the two letters of the device.
52DA
GOSUB to 53C9H to find its block.
52DD
If there is none, JUMP to 52E8H.
52E0
PUSH HL E5
Save the block address.
52E1
GOSUB to 530EH to close a file the device is routed to.
52E4
POP HL E1
Restore the block address.
52E5
LD (HL),08H 36 08
Type 08H: NIL.
52E7
RET C9
RETURN (to the DOS, which called the member).
52E8
LD DE,0000H 11 00 00
Look for a free block (name 0000H).
52EE
LD A,21H 3E 21
Load Register A with 21H (no device space available); the flags are kept.
52F0
If there is none, JUMP to 534DH.
52F3
DI F3
Disable interrupts.
52F4
LD DE,(538AH) ED 5B 8A 53
Fetch the name.
52F8
LD (HL),08H 36 08
Type 08H: NIL.
52FA
LD A,L 7D
Point to +06H...
52FB
ADD A,06H C6 06
(add 06H)
52FD
LD L,A 6F
(into L)
52FE
LD (HL),E 73
...and store the name.
52FF
INC L 2C
(next byte)
5300
LD (HL),D 72
(second letter)
5301
EI FB
Enable interrupts.
5302
JUMP to 402DH.
5305-530C
DEFM "NIL " : DEFW 5220H 4E 49 4C 20 20 20 20 52
NIL: operand of the LD BC at 521FH.
530D
DEFB 00H 00
End of the table.

530EH - Close a Routed File

HL points to a device control block. The chain of routes and links (bit 4 of the type byte) is followed to its end; if that is an open file (bit 7 of byte 0 of its FCB), the FCB is copied to 532DH and the file is closed from the copy.

530E
BIT 4,(HL) CB 66
Routed or linked (bit 4)?
5310
If not, JUMP to 5319H.
5312
INC HL 23
Fetch +01H-02H...
5313
LD A,(HL) 7E
(low byte)
5314
INC HL 23
(next byte)
5315
LD H,(HL) 66
(high byte)
5316
LD L,A 6F
...into HL...
5317
...and LOOP back to 530EH.
5319
BIT 7,(HL) CB 7E
An open file (bit 7)?
531B
RET Z C8
If not, RETURN.
531C
LD DE,532DH 11 2D 53
Copy the FCB to 532DH...
531F
PUSH DE D5
(save the address)
5320
LD BC,0020H 01 20 00
...32 bytes...
5323
LDIR ED B0
(copy)
5325
POP DE D1
...and point DE to the copy.
5326
GOSUB to the SYS0 routine at 4428H to close the file.
5329
If that failed (NZ), JUMP to 534DH.
532C
RET C9
RETURN.
532D-534C
DEFS 32
The copy of the FCB of a routed file (531CH). Not in the file.

534DH - Error Exits

534D
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
534F
JUMP to the SYS0 error handler at 4409H.
5352
LD HL,535BH 21 5B 53
Point HL to DEVICE SPEC REQUIRED at 535BH.
5355
GOSUB to 447BH to display it.
5358
JUMP to 4030H.
535B-536F
DEFM "DEVICE SPEC REQUIRED",0DH 44 45 56 49 43 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5355H.
5370
LD HL,5379H 21 79 53
Point HL to PARAMETER ERROR at 5379H.
5373
GOSUB to 447BH to display it.
5376
JUMP to 4030H.
5379-5388
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 5373H.
5389-53A8
DEFS 32
The FCB of the device being routed. Not in the file.
53A9-53C8
DEFS 32
The FCB of the destination. Not in the file.

53C9H - Find a Device Control Block

E and D hold the two letters of a device name (0000H finds a free block). Looks through the device control blocks at 4015H, 401DH, 4025H and 43C0H-43F8H for one with that name at +06H-07H. Returns Z with HL = the block, or NZ with A = 08H (device not available).

53C9
LD HL,4015H 21 15 40
Start at 4015H.
53CC
PUSH HL E5
Save the block address.
53CD
LD A,L 7D
Point HL to +06H, the name...
53CE
ADD A,06H C6 06
(add 06H)
53D0
LD L,A 6F
(into L)
53D1
LD A,(HL) 7E
Fetch the first letter.
53D2
INC L 2C
(next byte)
53D3
CP E BB
Does it match?
53D4
If not, JUMP to 53DDH.
53D6
LD A,(HL) 7E
Fetch the second letter.
53D7
CP D BA
Does it match?
53D8
If not, JUMP to 53DDH.
53DA
POP HL E1
Found: restore the block address...
53DB
XOR A AF
...set Z...
53DC
RET C9
...and RETURN.
53DD
POP AF F1
Discard the saved block address (HL now points to +07H).
53DE
INC L 2C
Next block (+08H); past 43F8H (L = 00H)...
53DF
...(otherwise JUMP to 53E5H)...
53E1
LD A,08H 3E 08
...there is no such device: A = 08H...
53E3
OR A B7
...with NZ...
53E4
RET C9
...RETURN.
53E5
LD A,L 7D
After 4025H (L = 2DH)...
53E6
CP 2DH FE 2D
(compare with 2DH)
53E8
...(otherwise LOOP back to 53CCH)...
53EA
LD HL,43C0H 21 C0 43
...continue at 43C0H.
53ED
LOOP back to 53CCH.

ISAM 65H (SET) and 66H (FILTER) - Offset 326C

One member serves two commands that load a program for a device. SET (SET *xx filespec, ISAM 65H, entry 5A01H) loads a driver (default extension /DVR) for device xx; if the device does not exist, a free device control block is given its name. FILTER (FILTER *xx filespec, ISAM 66H, entry 5A00H) loads a filter (default extension /FLT) for an existing device. The loaded program is then started at its transfer address with HL pointing to the rest of the command line and DE to the device control block, so that it can install itself. Not allowed while a program has put a jump at 402DH. This member loads at 5A00H-5B19H (282 bytes), above the 5200H area where other members load; the two FCBs at 5B1AH and 5B3AH lie past it.

5A00H - FILTER and SET Commands

FILTER enters at 5A00H, where the OR AFH makes Register A non-zero; SET enters at 5A01H, the AFH byte, which is XOR A and makes it zero. HL points to the text after the command.

5A00
OR AFH F6 AF
FILTER: Register A is made non-zero. SET enters at 5A01H, the operand of this instruction, which executes as XOR A (A = 0).
5A02
LD (5A64H),A 32 64 5A
Store Register A at 5A64H (the operand of the LD A at 5A63H): 0 for SET, non-zero for FILTER.
5A05
LD A,(402DH) 3A 2D 40
Fetch the first byte at 402DH.
5A08
CP C3H FE C3
If a program has put a JP (C3H) there...
5A0A
...JUMP to 5AE7H to display CAN'T -- VALID ONLY AT VTOS COMMAND LEVEL.
5A0D
LD DE,5B1AH 11 1A 5B
Point DE to the first FCB at 5B1AH.
5A10
GOSUB to the SYS0 routine at 441CH to read the device name into it.
5A13
If there is none (NZ), JUMP to 5AC9H to display DEVICE SPEC REQUIRED.
5A16
LD A,(DE) 1A
Fetch its first character.
5A17
CP 2AH FE 2A
It must be *...
5A19
...otherwise JUMP to 5AC9H.
5A1C
LD DE,5B3AH 11 3A 5B
Point DE to the second FCB at 5B3AH.
5A1F
GOSUB to 441CH to read the filespec into it.
5A22
If there is none, JUMP to 5AADH to display FILE SPEC REQUIRED.
5A25
LD A,(DE) 1A
Fetch its first character.
5A26
CP 2AH FE 2A
A device (*)...
5A28
...is not accepted: JUMP to 5AADH.
5A2B
PUSH HL E5
Save the line pointer.
5A2C
LD A,(5A64H) 3A 64 5A
SET or FILTER?
5A2F
OR A B7
(test it)
5A30
LD HL,5A7CH 21 7C 5A
Point HL to the default extension DVR at 5A7CH...
5A33
...for SET...
5A35
LD HL,5A7FH 21 7F 5A
...or FLT at 5A7FH for FILTER.
5A38
GOSUB to the SYS0 routine at 4473H to use it if the filespec has no extension.
5A3B
LD DE,(5B1BH) ED 5B 1B 5B
Fetch the two letters of the device name.
5A3F
GOSUB to 5A82H to find its device control block.
5A42
If it exists, JUMP to 5A59H.
5A44
LD A,(5A64H) 3A 64 5A
SET or FILTER?
5A47
OR A B7
(test it)
5A48
LD A,08H 3E 08
Load Register A with 08H (device not available); the flags are kept.
5A4A
FILTER needs an existing device: JUMP to the error exit at 5AA8H.
5A4C
LD DE,0000H 11 00 00
SET: look for a free block (name 0000H).
5A52
If there is one, JUMP to 5A59H.
5A54
LD A,21H 3E 21
Otherwise load Register A with 21H (no device space available)...
5A56
...and JUMP to 5AA8H.
5A59
PUSH HL E5
Save the block address.
5A5A
LD DE,5B3AH 11 3A 5B
Point DE to the FCB of the program.
5A5D
GOSUB to the SYS0 routine at 4430H to load it; HL returns its transfer address.
5A60
If that failed (NZ), JUMP to 5AA8H.
5A63
LD A,00H 3E 00
Load Register A with the SET/FILTER flag (the operand at 5A64H).
5A65
OR A B7
Test it...
5A66
...and for FILTER JUMP to 5A79H.
5A68
POP DE D1
SET: DE = the block address...
5A69
PUSH DE D5
(keep it on the stack)
5A6A
DI F3
Disable interrupts.
5A6B
LD A,E 7B
Point DE to +06H...
5A6C
ADD A,06H C6 06
(add 06H)
5A6E
LD E,A 5F
(into E)
5A6F
LD A,(5B1BH) 3A 1B 5B
...and store the device name there.
5A72
LD (DE),A 12
(store it)
5A73
INC E 1C
(next byte)
5A74
LD A,(5B1CH) 3A 1C 5B
(second letter)
5A77
EI FB
Enable interrupts.
5A78
LD (DE),A 12
(store it)
5A79
POP DE D1
DE = the device control block.
5A7A
EX (SP),HL E3
Swap the transfer address with the saved line pointer, which goes into HL...
5A7B
RET C9
...and RETURN to the transfer address: the loaded program starts with HL = the rest of the command line and DE = the block.
5A7C-5A7E
DEFM "DVR" 44 56 52
The default extension for SET.
5A7F-5A81
DEFM "FLT" 46 4C 54
The default extension for FILTER.

5A82H - Find a Device Control Block

E and D hold the two letters of a device name (0000H finds a free block). Looks through the device control blocks at 4015H, 401DH, 4025H and 43C0H-43F8H for one with that name at +06H-07H. Returns Z with HL = the block, or NZ with A = 08H (device not available).

5A82
LD HL,4015H 21 15 40
Start at 4015H.
5A85
PUSH HL E5
Save the block address.
5A86
LD A,L 7D
Point HL to +06H, the name...
5A87
ADD A,06H C6 06
(add 06H)
5A89
LD L,A 6F
(into L)
5A8A
LD A,(HL) 7E
Fetch the first letter.
5A8B
INC L 2C
(next byte)
5A8C
CP E BB
Does it match?
5A8D
If not, JUMP to 5A96H.
5A8F
LD A,(HL) 7E
Fetch the second letter.
5A90
CP D BA
Does it match?
5A91
If not, JUMP to 5A96H.
5A93
POP HL E1
Found: restore the block address...
5A94
XOR A AF
...set Z...
5A95
RET C9
...and RETURN.
5A96
POP AF F1
Discard the saved block address (HL now points to +07H).
5A97
INC L 2C
Next block (+08H); past 43F8H (L = 00H)...
5A98
...(otherwise JUMP to 5A9EH)...
5A9A
LD A,08H 3E 08
...there is no such device: A = 08H...
5A9C
OR A B7
...with NZ...
5A9D
RET C9
...RETURN.
5A9E
LD A,L 7D
After 4025H (L = 2DH)...
5A9F
CP 2DH FE 2D
(compare with 2DH)
5AA1
...(otherwise LOOP back to 5A85H)...
5AA3
LD HL,43C0H 21 C0 43
...continue at 43C0H.
5AA6
LOOP back to 5A85H.

5AA8H - Error Exits

5AA8
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
5AAA
JUMP to the SYS0 error handler at 4409H.
5AAD
LD HL,5AB6H 21 B6 5A
Point HL to FILE SPEC REQUIRED at 5AB6H.
5AB0
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5AB3
JUMP to 4030H: back to VTOS READY.
5AB6-5AC8
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5AB0H.
5AC9
LD HL,5AD2H 21 D2 5A
Point HL to DEVICE SPEC REQUIRED at 5AD2H.
5ACC
GOSUB to 447BH to display it.
5ACF
JUMP to 4030H.
5AD2-5AE6
DEFM "DEVICE SPEC REQUIRED",0DH 44 45 56 49 43 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5ACCH.
5AE7
LD HL,5AF0H 21 F0 5A
Point HL to the message at 5AF0H.
5AEA
GOSUB to 447BH to display it.
5AED
JUMP to 4030H.
5AF0-5B19
DEFM "CAN'T -- VALID ONLY AT VTOS COMMAND LEVEL",0DH 43 41 4E 27 54 20 2D 2D 20 56 41 4C 49 44 20 4F 4E 4C 59 20 41 54 20 56 54 4F 53 20 43 4F 4D 4D 41 4E 44 20 4C 45 56 45 4C 0D
Displayed at 5AEAH.

ISAM 71H - DUMP - Offset 3391

DUMP (DUMP filespec (START=X'hhhh', END=X'hhhh', TRA=X'hhhh'), or S=, E= and T=) writes a block of memory to a file in load module format (default extension /CIM), so that it can be loaded or run again. The file starts with a header record (type 05H) holding the first six letters and digits of the file name, then the memory in load records (type 01H) of up to 254 bytes, each with its load address, and ends with a transfer record (type 02H). START and END default to 6000H and TRA to 402DH; START must not be below 6000H and END not below START. The member loads at 5200H-5389H (394 bytes); the name at 538AH, the FCB at 5390H and the buffer at 5400H lie past it.

5200H - DUMP Command

HL points to the text after DUMP.

5200
JUMP over the output routine to 5212H.
5203
Write Register A to the file: GOSUB to the ROM routine at 001BH with DE = the FCB.
5206
RET Z C8
If that went well, RETURN.
5207
RST 30H F7
An error: RST 30H, which goes through 400FH to 44B4H, the DEBUG entry.
5208
RES 7,A CB BF
Then clear bit 7 of the error code...
520A
...and JUMP to the SYS0 error handler at 4409H (with the full message).
520D-5211
DEFB 00H,00H,00H,00H,52H 00 00 00 00 52
Not used.
5212
LD DE,5390H 11 90 53
Point DE to the FCB at 5390H.
5215
GOSUB to the SYS0 routine at 441CH to read the filespec into it.
5218
If there is none (NZ), JUMP to 52EFH to display FILE SPEC REQUIRED.
521B
LD A,(DE) 1A
Fetch the first character.
521C
CP 2AH FE 2A
A device (*)...
521E
...is not accepted: JUMP to 52EFH.
5221
LD DE,5359H 11 59 53
Point DE to the parameter table at 5359H.
5224
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
5227
If a parameter was not recognized (NZ), JUMP to 52F8H to display PARAMETER ERROR.
522A
LD DE,538AH 11 8A 53
Copy the file name for the header record: DE = 538AH...
522D
LD HL,5390H 21 90 53
...HL = the filespec in the FCB...
5230
LD B,06H 06 06
...up to six characters.
5232
LD A,(HL) 7E
Fetch a character.
5233
CP 30H FE 30
Below 0...
5235
...ends the name: JUMP to 524AH.
5237
CP 3AH FE 3A
A digit...
5239
...is copied: JUMP to 5243H.
523B
CP 41H FE 41
Other characters below A...
523D
...end the name.
523F
CP 5BH FE 5B
Above Z...
5243
LD (DE),A 12
Store the character.
5244
INC HL 23
(next character)
5245
INC DE 13
(next place)
5246
LOOP back to 5232H for up to six characters.
5248
JUMP to 5250H.
524A
LD A,20H 3E 20
Fill the rest with spaces.
524C
LD (DE),A 12
(store it)
524D
INC DE 13
(next place)
5250
LD DE,5390H 11 90 53
Point DE to the FCB...
5253
LD HL,5356H 21 56 53
...and HL to the default extension CIM at 5356H.
5256
GOSUB to the SYS0 routine at 4473H to use it if the filespec has no extension.
5259
LD B,00H 06 00
Register B = 00H: record length 256.
525B
LD HL,5400H 21 00 54
Point HL to the buffer at 5400H.
525E
GOSUB to the SYS0 routine at 4420H to open the file, or create it.
5261
If that failed (NZ), JUMP to the error exit at 52EAH.
5264
LD A,05H 3E 05
Write the header record: type 05H...
5269
LD A,06H 3E 06
...length 06H...
526E
LD B,06H 06 06
...and the six characters of the name.
5270
LD HL,538AH 21 8A 53
(from 538AH)
5273
LD A,(HL) 7E
Fetch a character.
5274
INC HL 23
(next byte)
5275
Write it.
527A
LD HL,(529AH) 2A 9A 52
Fetch the END address (the operand at 529AH)...
527D
LD BC,(5294H) ED 4B 94 52
...and the START address (the operand at 5294H).
5281
XOR A AF
Clear the Carry flag.
5282
SBC HL,BC ED 42
Is END below START?
5284
LD HL,5307H 21 07 53
Point HL to END LESS THAN START at 5307H...
5287
...and if so, JUMP to 5301H to display it.
5289
LD HL,5FFFH 21 FF 5F
Is START below 6000H (5FFFH - START does not go below 0)?
528C
SBC HL,BC ED 42
(subtract START)
528E
LD HL,531BH 21 1B 53
Point HL to START LESS THAN X'6000' at 531BH...
5291
...and if so, JUMP to 5301H.
5293
LD HL,6000H 21 00 60
HL = START (the operand at 5294H; 6000H unless START was given).
5296
PUSH HL E5
Save the address.
5297
LD B,H 44
BC = the address.
5298
LD C,L 4D
(low byte)
5299
LD HL,6000H 21 00 60
HL = END (the operand at 529AH; 6000H unless END was given)...
529C
INC HL 23
...plus 1.
529D
XOR A AF
Clear the Carry flag.
529E
SBC HL,BC ED 42
HL = the number of bytes left.
52A0
If none are left, JUMP to 52CBH.
52A2
LD B,FEH 06 FE
Register B = 254 bytes for this record...
52A4
LD A,H 7C
...unless fewer are left:
52A5
OR A B7
(test the high byte)
52A6
(256 or more: JUMP to 52AEH)
52A8
LD A,L 7D
(low byte)
52A9
CP FFH FE FF
(255 left?)
52AB
(then JUMP to 52AEH)
52AD
LD B,L 45
Register B = the number left.
52AE
POP HL E1
Restore the address.
52AF
LD A,01H 3E 01
Write a load record: type 01H...
52B4
LD A,B 78
...the length (the bytes plus 2 for the address)...
52B5
ADD A,02H C6 02
(add 2)
52BA
LD A,L 7D
...the load address, low byte...
52BE
LD A,H 7C
...and high byte...
52C2
LD A,(HL) 7E
...and the bytes.
52C3
INC HL 23
(next byte)
52C9
LOOP back to 5296H for the next record.
52CB
POP HL E1
Discard the address.
52CC
LD A,02H 3E 02
Write the transfer record: type 02H...
52D1
LD A,02H 3E 02
...length 02H...
52D6
LD HL,402DH 21 2D 40
...and the TRA address (the operand at 52D7H; 402DH unless TRA was given), low byte...
52D9
LD A,L 7D
(fetch it)
52DD
LD A,H 7C
...and high byte.
52E1
GOSUB to the SYS0 routine at 4428H to close the file.
52E4
If that failed (NZ), JUMP to 52EAH.
52E7
JUMP to 402DH: back to VTOS READY.

52EAH - Error Exits

52EA
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
52EC
JUMP to the SYS0 error handler at 4409H.
52EF
LD HL,5333H 21 33 53
Point HL to FILE SPEC REQUIRED at 5333H.
52F2
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
52F5
JUMP to 4030H: back to VTOS READY.
52F8
LD HL,5346H 21 46 53
Point HL to PARAMETER ERROR at 5346H.
52FB
GOSUB to 447BH to display it.
52FE
JUMP to 4030H.
5301
GOSUB to 447BH to display the message at HL.
5304
JUMP to 4030H.
5307-531A
DEFM "END LESS THAN START",0DH 45 4E 44 20 4C 45 53 53 20 54 48 41 4E 20 53 54 41 52 54 0D
Displayed from 5287H.
531B-5332
DEFM "START LESS THAN X'6000'",0DH 53 54 41 52 54 20 4C 45 53 53 20 54 48 41 4E 20 58 27 36 30 30 30 27 0D
Displayed from 5291H.
5333-5345
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 52F2H.
5346-5355
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 52FBH.
5356-5358
DEFM "CIM" 43 49 4D
The default extension.

5359H - Parameter Table

5359-5360
DEFM "START " : DEFW 5294H 53 54 41 52 54 20 94 52
START: operand of the LD HL at 5293H.
5361-5368
DEFM "END " : DEFW 529AH 45 4E 44 20 20 20 9A 52
END: operand of the LD HL at 5299H.
5369-5370
DEFM "TRA " : DEFW 52D7H 54 52 41 20 20 20 D7 52
TRA: operand of the LD HL at 52D6H.
5371-5378
DEFM "S " : DEFW 5294H 53 20 20 20 20 20 94 52
S, short for START.
5379-5380
DEFM "E " : DEFW 529AH 45 20 20 20 20 20 9A 52
E, short for END.
5381-5388
DEFM "T " : DEFW 52D7H 54 20 20 20 20 20 D7 52
T, short for TRA.
5389
DEFB 00H 00
End of the table.

ISAM 72H - PURGE - Offset 3526

PURGE (PURGE :d (MPW=password)) goes through the files of a disk and asks, for each one, PURGE FILE: name/ext ?; if the answer starts with Y, the file is killed and *** PURGED *** is shown. The disk's master password must be given with MPW or typed in answer to MASTER PASSWORD ? (the hash C294H is also accepted). All files in use are offered, including system and invisible files, except the first two positions of the hash index table and extended directory entries. Not allowed while a chain file is running. The member loads at 5200H-5343H, 5346H-5419H, 541EH-5440H and 544EH-5456H (580 bytes); the gaps are work areas, and it reads the GAT into 5600H, the hash index table into 5700H and a typed password into 5500H.

5200H - PURGE Command

HL points to the text after PURGE.

5200
LD A,(430FH) 3A 0F 43
Fetch the system flags.
5203
BIT 5,A CB 6F
Test bit 5: a chain (DO) file is running.
5205
If so, JUMP to 53D9H to display INVALID COMMAND DURING PROGRAM CHAINING.
5208
LD C,00H 0E 00
Register C = drive 0.
520A
LD A,(HL) 7E
Fetch the next character.
520B
CP 3AH FE 3A
Is it :?
520D
If not, JUMP to 5215H.
520F
INC HL 23
Move to the drive digit.
5210
LD A,(HL) 7E
Fetch it...
5211
INC HL 23
(move past it)
5212
SUB 30H D6 30
...as a number...
5214
LD C,A 4F
...into C.
5215
LD A,C 79
Store the drive...
5216
LD (5320H),A 32 20 53
...at 5320H (the operand of the LD C at 531FH).
5219
PUSH HL E5
Save the line pointer.
521A
GOSUB to the SYS0 routine at 44B8H (SYS2, request 40H) to check that the drive is there and ready.
521D
POP HL E1
Restore the line pointer.
521E
LD A,20H 3E 20
Load Register A with 20H (illegal drive number); the flags are kept.
5220
If the drive is not ready (NZ), JUMP to the error exit at 53CBH.
5223
LD BC,0000H 01 00 00
Clear the MPW value...
5226
LD (5344H),BC ED 43 44 53
...at 5344H.
522A
LD DE,544EH 11 4E 54
Point DE to the parameter table at 544EH.
522D
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
5230
If a parameter was not recognized (NZ), JUMP to 53D0H to display PARAMETER ERROR.
5233
GOSUB to 5314H to check the master password.
5236
LD A,(5320H) 3A 20 53
Fetch the drive...
5239
LD C,A 4F
...into C.
523A
GOSUB to the SYS0 routine at 4B65H to get the directory track in Register D.
523D
LD E,01H 1E 01
Load Register E with 01H: the hash index table.
523F
LD HL,5700H 21 00 57
Point HL to 5700H.
5242
GOSUB to 4B45H to read it.
5245
LD A,16H 3E 16
Load Register A with 16H (HIT read error); the flags are kept.
5247
If that failed (NZ), JUMP to 53CBH.
524A
LD HL,5700H 21 00 57
Start at the first position of the table...
524D
...JUMP to 5266H.

524FH - Offer Each File

HL goes through the hash index table at 5700H column by column: positions 00H, 20H, 40H ... E0H (the eight entries of directory sector 0), then 01H, 21H ... and so on to 1FH-FFH. A position holds the file's hash (0 if free) and is also its directory entry code. The directory sector holding the entry is read into 4200H only when it is not there already; its number is kept at 5277H.

524F
POP BC C1
Restore the entry code (and the drive in C).
5250
LD H,57H 26 57
Point HL back to the file's position in the table...
5252
LD L,B 68
(L = the entry code)
5253
LD A,L 7D
Next entry of the same sector...
5254
ADD A,20H C6 20
(add 20H)
5256
LD L,A 6F
(into L)
5257
...if it is still within the table, JUMP to 5266H.
5259
INC L 2C
Otherwise go on with the next sector...
525A
CP 1FH FE 1F
...unless the one just finished was the last (1FH).
525C
(otherwise JUMP to 5266H)
525E
LD A,0DH 3E 0D
All done: display a carriage return through the ROM routine at 0033H...
5260
(display it)
5263
...and JUMP to 402DH, back to VTOS READY.
5266
LD A,L 7D
Positions 00H and 01H...
5267
AND FEH E6 FE
(AND FEH)
5269
...are skipped: JUMP to 5253H.
526B
LD A,(HL) 7E
Fetch the hash byte.
526C
OR A B7
Test it.
526D
If the entry is free, JUMP to 5253H.
526F
LD B,L 45
Register B = the entry code.
5270
PUSH BC C5
Save it and the drive.
5271
LD A,L 7D
Point L to the entry within its sector...
5272
AND E0H E6 E0
(bits 5-7)
5274
LD L,A 6F
(into L)
5275
XOR B A8
...and A = the directory sector.
5276
CP FFH FE FF
Is it the sector already in 4200H (the operand at 5277H, FFH to begin with)?
5278
If so, JUMP to 5283H.
527A
LD (5277H),A 32 77 52
Remember it.
527D
GOSUB to the SYS0 routine at 4B10H to read the directory sector that holds entry B.
5280
If that failed (NZ), JUMP to 53CBH.
5283
LD H,42H 26 42
HL = the entry at 42xxH.
5285
LD A,(HL) 7E
Fetch its attributes.
5286
BIT 4,A CB 67
Not in use (bit 4 clear)...
5288
...skip it: JUMP to 524FH.
528B
BIT 7,A CB 7F
An extended entry (bit 7 set)...
528D
...is skipped too.
5290
PUSH HL E5
Save the entry address.
5291
LD HL,541EH 21 1E 54
Point HL to PURGE FILE: at 541EH.
5294
GOSUB to the SYS0 routine at 4467H to display it.
5297
POP HL E1
Restore the entry address.
5298
LD A,L 7D
Point HL to entry+05H, the name...
5299
ADD A,05H C6 05
(add 05H)
529B
LD L,A 6F
(into L)
529C
LD DE,5441H 11 41 54
...and DE to the buffer at 5441H.
529F
LD B,08H 06 08
Copy up to eight characters...
52A1
LD A,(HL) 7E
Fetch one.
52A2
INC HL 23
(next byte)
52A3
CP 20H FE 20
A space...
52A5
...ends the name: JUMP to 52ADH.
52A7
LD (DE),A 12
Store it.
52A8
INC DE 13
(next place)
52AB
All eight: JUMP to 52B1H.
52AD
LD A,L 7D
Point HL to entry+0DH, the extension...
52AE
ADD A,B 80
(add the count left)
52AF
DEC A 3D
(less 1)
52B0
LD L,A 6F
(into L)
52B1
LD A,(HL) 7E
Fetch its first character.
52B2
CP 20H FE 20
A space means none...
52B4
...JUMP to 52C6H.
52B6
LD A,2FH 3E 2F
Put / in the buffer...
52B8
LD (DE),A 12
(store it)
52B9
INC DE 13
(next place)
52BA
LD B,03H 06 03
...and up to three characters.
52BC
LD A,(HL) 7E
Fetch one.
52BD
INC HL 23
(next byte)
52BE
CP 20H FE 20
A space...
52C0
...ends it: JUMP to 52C6H.
52C2
LD (DE),A 12
Store it.
52C3
INC DE 13
(next place)
52C6
LD A,03H 3E 03
End the text with 03H.
52C8
LD (DE),A 12
(store it)
52C9
LD HL,5441H 21 41 54
Point HL to the name at 5441H...
52CC
...and display it.
52CF
PUSH HL E5
Save HL.
52D0
LD HL,542BH 21 2B 54
Point HL to ? at 542BH...
52D3
...and display it.
52D6
LD HL,541AH 21 1A 54
Point HL to the answer buffer at 541AH.
52D9
LD B,03H 06 03
Up to three characters...
52DB
...are read through the ROM routine at 0040H.
52DE
LD A,(541AH) 3A 1A 54
Fetch the first one.
52E1
CP 59H FE 59
Is it Y?
52E3
POP HL E1
Restore HL.
52E4
If not, JUMP to 524FH for the next file.
52E7
POP BC C1
Fetch the entry code and drive...
52E8
PUSH BC C5
(and keep them)
52E9
LD A,B 78
...and make an FCB at 5457H: the entry code at FCB+07H...
52EA
LD (545EH),A 32 5E 54
(store it)
52ED
LD A,(5320H) 3A 20 53
...the drive at FCB+06H...
52F0
LD (545DH),A 32 5D 54
(store it)
52F3
LD A,01H 3E 01
...01H at FCB+01H...
52F5
LD (5458H),A 32 58 54
(store it)
52F8
LD A,80H 3E 80
...and 80H (open) at FCB+00H.
52FA
LD (5457H),A 32 57 54
(store it)
52FD
LD DE,5457H 11 57 54
Point DE to it.
5300
GOSUB to the SYS0 routine at 442CH to kill the file.
5303
If that failed (NZ), JUMP to 53CBH.
5306
LD HL,5430H 21 30 54
Point HL to *** PURGED *** at 5430H.
5309
GOSUB to 4467H to display it.
530C
LD A,FFH 3E FF
The directory sector in 4200H has changed: set 5277H to FFH...
530E
LD (5277H),A 32 77 52
...so that the next file reads it again.
5311
JUMP to 524FH for the next file.

5314H - Check the Master Password

Reads the GAT into 5600H and compares the hash of the password given (MPW, or typed in) with the one in the GAT (CEH-CFH). The hash C294H is also accepted.

5314
LD DE,(5344H) ED 5B 44 53
Load DE with the MPW value.
5318
LD HL,5388H 21 88 53
Point HL to the prompt MASTER PASSWORD ? at 5388H.
531B
GOSUB to 5346H to get the password and its hash in HL.
531E
PUSH HL E5
Save the hash.
531F
LD C,00H 0E 00
Load Register C with the drive (the operand at 5320H).
5321
GOSUB to 53B8H to read the GAT.
5324
If that failed (NZ), JUMP to 533FH.
5327
POP DE D1
DE = the hash.
5328
LD HL,C294H 21 94 C2
Is it C294H?
532B
XOR A AF
(clear Register A and the Carry flag)
532C
SBC HL,DE ED 52
(compare)
532E
RET Z C8
If so, RETURN.
532F
LD HL,(56CEH) 2A CE 56
Is it the master password of the disk?
5332
XOR A AF
(clear Register A and the Carry flag)
5333
SBC HL,DE ED 52
(compare)
5335
RET Z C8
If so, RETURN.
5336
LD HL,53A0H 21 A0 53
Point HL to INVALID MASTER PASSWORD at 53A0H.
5339
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
533C
JUMP to 4030H: back to VTOS READY.
533F
OR 40H F6 40
Error exit with the error code in Register A: set bit 6.
5341
JUMP to the SYS0 error handler at 4409H.
5344-5345
DEFS 2
The MPW value (stored by the parameter scan; cleared at 5226H). Not in the file.

5346H - Get a Password

5346H gets the text and returns the hash of its eight characters in HL (SYS2, request 60H). 534CH only gets the text into 5500H, padded with spaces, and returns DE = 5500H. DE = the value from the command: the text itself, or 0000H if none was given, in which case the prompt at HL is displayed and the text is typed in.

5346
GOSUB to 534CH to get the text.
5349
LD A,E4H 3E E4
Load Register A with E4H: SYS2, request 60H (password hash).
534B
RST 28H EF
Call the overlay through RST 28H; it returns to the caller of 5346H.
534C
LD A,D 7A
Was a value given?
534D
OR E B3
(OR the other byte)
534E
If not, JUMP to 536BH to prompt.
5350
LD HL,5500H 21 00 55
Point HL to 5500H.
5353
LD B,08H 06 08
Load Register B with 08H.
5355
LD A,(DE) 1A
Fetch a character of the value.
5356
CP 0DH FE 0D
A carriage return...
5358
...ends it: JUMP to 537FH to pad.
535A
CP 2CH FE 2C
So does a comma...
535C
(JUMP to 537FH)
535E
CP 22H FE 22
...and a quote.
5360
(JUMP to 537FH)
5362
INC DE 13
Move on.
5363
LD (HL),A 77
Store the character.
5364
INC HL 23
(next byte)
5365
LOOP back to 5355H for up to eight characters.
5367
LD DE,5500H 11 00 55
DE = 5500H.
536A
RET C9
RETURN.
536B
Display the prompt at HL.
536E
LD B,08H 06 08
Load Register B with 08H.
5370
LD HL,5500H 21 00 55
Point HL to 5500H.
5373
GOSUB to the ROM routine at 0040H to read up to eight characters.
5376
EX DE,HL EB
DE = 5500H.
5377
LD H,00H 26 00
HL = 5500H + the number of characters typed...
5379
LD L,B 68
(L = the count, which 0040H returns in Register B)
537A
ADD HL,DE 19
(add DE)
537B
LD A,08H 3E 08
Register B = 8 - that number.
537D
SUB B 90
(subtract)
537E
LD B,A 47
(into B)
537F
LD (HL),20H 36 20
Fill with spaces...
5381
INC HL 23
(next byte)
5384
LD DE,5500H 11 00 55
DE = 5500H.
5387
RET C9
RETURN.
5388-539F
DEFM "MASTER PASSWORD ? ",03H 4D 41 53 54 45 52 20 50 41 53 53 57 4F 52 44 20 3F 20 20 20 20 20 20 03
Prompt displayed at 536BH.
53A0-53B7
DEFM "INVALID MASTER PASSWORD",0DH 49 4E 56 41 4C 49 44 20 4D 41 53 54 45 52 20 50 41 53 53 57 4F 52 44 0D
Displayed at 5339H.

53B8H - Read the GAT

Reads the GAT of drive C into 5600H. Returns NZ with A = 14H (GAT read error) if that fails. DE and HL are preserved.

53B8
PUSH DE D5
Save DE.
53B9
PUSH HL E5
Save HL.
53BA
GOSUB to 4B65H to get the directory track.
53BD
LD E,00H 1E 00
Load Register E with 00H: the GAT.
53BF
LD HL,5600H 21 00 56
Point HL to 5600H.
53C2
GOSUB to 4B45H to read it.
53C5
POP HL E1
Restore HL.
53C6
POP DE D1
Restore DE.
53C7
RET Z C8
If it was read, RETURN.
53C8
LD A,14H 3E 14
Load Register A with 14H: GAT read error.
53CA
RET C9
RETURN with NZ.

53CBH - Error Exits

53CB
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
53CD
JUMP to the SYS0 error handler at 4409H.
53D0
LD HL,53E2H 21 E2 53
Point HL to PARAMETER ERROR at 53E2H.
53D3
GOSUB to 447BH to display it.
53D6
JUMP to 4030H.
53D9
LD HL,53F2H 21 F2 53
Point HL to the message at 53F2H.
53DC
GOSUB to 447BH to display it.
53DF
JUMP to 4030H.
53E2-53F1
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 53D3H.
53F2-5419
DEFM "INVALID COMMAND DURING PROGRAM CHAINING",0DH 49 4E 56 41 4C 49 44 20 43 4F 4D 4D 41 4E 44 20 44 55 52 49 4E 47 20 50 52 4F 47 52 41 4D 20 43 48 41 49 4E 49 4E 47 0D
Displayed at 53DCH.
541A-541D
DEFS 4
The answer typed (52DBH). Not in the file.
541E-542A
DEFM "PURGE FILE: ",03H 50 55 52 47 45 20 46 49 4C 45 3A 20 03
Displayed at 5294H.
542B-542F
DEFM " ? ",03H 20 3F 20 20 03
Displayed at 52D3H after the name.
5430-5440
DEFB E3H,1BH : DEFM "*** PURGED ***",0DH E3 1B 2A 2A 2A 20 50 55 52 47 45 44 20 2A 2A 2A 0D
Displayed at 5309H. E3H is 35 spaces (space compression) and 1BH moves the cursor up a line, so that the text appears on the line of the question.
5441-544D
DEFS 13
The file name as NAME/EXT, ending with 03H (52A1H-52C8H). Not in the file.

544EH - Parameter Table

544E-5455
DEFM "MPW " : DEFW 5344H 4D 50 57 20 20 20 44 53
MPW: stored at 5344H.
5456
DEFB 00H 00
End of the table.

ISAM 73H - XFER - Offset 3781

XFER (XFER filespec) copies a file from one disk to another in the same drive, with the operator changing disks. The source disk is inserted and the file opened; then the destination disk is inserted and the file opened on it, or created. The file is copied through the memory from 5600H up to the top of memory, as many sectors at a time as fit, with a disk change for each load. Each disk is recognised by 18 bytes of its GAT (CEH-DFH: the master password hash, disk name and date), and XFER keeps asking for the right disk until it is inserted; if the two disks have the same bytes, SOURCE AND DESTINATION DISKS ARE THE SAME is shown. When drive 0 is used, the system disk is asked for whenever the DOS needs it, and the overlay needed next (SYS2, SYS8 or SYS3) is loaded in advance. Each prompt blinks until ENTER is pressed. Not allowed while a chain file is running. The member loads at 5200H-54CDH (718 bytes); the source FCB at 54CEH, the destination FCB at 54EEH and the two copies of GAT bytes at 550EH and 5520H lie past it.

5200H - XFER Command

HL points to the text after XFER.

5200
LD A,(430FH) 3A 0F 43
Fetch the system flags.
5203
BIT 5,A CB 6F
Test bit 5: a chain (DO) file is running.
5205
If so, JUMP to 53FEH to display INVALID COMMAND DURING PROGRAM CHAINING.
5208
LD DE,54CEH 11 CE 54
Point DE to the source FCB at 54CEH.
520B
GOSUB to the SYS0 routine at 441CH to read the filespec into it.
520E
If there is none (NZ), JUMP to 53F5H to display FILE SPEC REQUIRED.
5211
LD HL,(4049H) 2A 49 40
Fetch the top of memory...
5214
INC HL 23
...plus 1...
5215
DEC H 25
...less 256...
5216
LD A,H 7C
Its page (Register H)...
5217
LD (52D4H),A 32 D4 52
...is the end of the buffer: store it at 52D4H...
521A
LD (52EBH),A 32 EB 52
...and 52EBH (the operands of the CP instructions).
521D
LD HL,54CEH 21 CE 54
Look through the filespec for the drive: HL = the FCB.
5220
LD C,00H 0E 00
Drive 0 if none is given.
5222
LD A,(HL) 7E
Fetch a character.
5223
INC HL 23
(next byte)
5224
CP 3AH FE 3A
:?
5226
Then JUMP to 522EH.
5228
CP 20H FE 20
A control character (the end)...
522A
...ends the search: JUMP to 5232H.
522C
LOOP back to 5222H.
522E
LD A,(HL) 7E
Fetch the drive digit...
522F
SUB 30H D6 30
...as a number...
5231
LD C,A 4F
...into C.
5232
LD A,C 79
Store the drive...
5233
LD (5358H),A 32 58 53
...at 5358H (the operand of the LD A at 5357H).
5236
LD HL,54CEH 21 CE 54
Copy the source FCB (the filespec)...
5239
LD DE,54EEH 11 EE 54
...to the destination FCB at 54EEH...
523C
LD BC,0020H 01 20 00
...32 bytes.
523F
LDIR ED B0
(copy)
5241
GOSUB to 53D4H to load SYS2, which opens files.
5244
LD HL,548BH 21 8B 54
Point HL to INSERT SOURCE DISK (ENTER) at 548BH...
5247
...and GOSUB to 53A7H to wait for it.
524A
LD A,(5358H) 3A 58 53
Fetch the drive...
524D
LD C,A 4F
...into C.
524E
GOSUB to 53DDH to read the GAT into 4200H.
5251
If that failed (NZ), JUMP to 534FH.
5254
LD HL,42CEH 21 CE 42
Keep the 18 bytes CEH-DFH of the GAT...
5257
LD DE,550EH 11 0E 55
...at 550EH...
525A
LD BC,0012H 01 12 00
(18 bytes)
525D
LDIR ED B0
(copy)
525F
LD DE,54CEH 11 CE 54
Point DE to the source FCB...
5262
LD HL,5600H 21 00 56
...and HL to the buffer at 5600H.
5265
LD B,00H 06 00
Register B = 00H: record length 256.
5267
GOSUB to the SYS0 routine at 4424H to open the file.
526A
If that failed (NZ), JUMP to 534FH.
526D
LD HL,54AAH 21 AA 54
Point HL to INSERT DESTINATION DISK (ENTER) at 54AAH...
5270
...and GOSUB to 53A7H to wait for it.
5273
LD A,(5358H) 3A 58 53
Fetch the drive...
5276
LD C,A 4F
...into C.
5277
GOSUB to 53DDH to read the GAT.
527A
If that failed (NZ), JUMP to 534FH.
527D
LD HL,42CEH 21 CE 42
Keep the 18 bytes CEH-DFH of the GAT...
5280
LD DE,5520H 11 20 55
...at 5520H.
5283
LD BC,0012H 01 12 00
(18 bytes)
5286
LDIR ED B0
(copy)
5288
LD HL,550EH 21 0E 55
Compare the two sets...
528B
LD DE,5520H 11 20 55
(5520H)
528E
LD B,12H 06 12
(18 bytes)
5293
If they differ, JUMP to 52A1H.
5295
The same disk: GOSUB to 5357H to ask for the system disk if needed...
5298
LD HL,5442H 21 42 54
...point HL to SOURCE AND DESTINATION DISKS ARE THE SAME at 5442H...
529B
...GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active)...
529E
...and JUMP to 4030H, back to VTOS READY.
52A1
LD DE,54EEH 11 EE 54
Point DE to the destination FCB...
52A4
LD HL,5600H 21 00 56
...and HL to the buffer at 5600H.
52A7
LD B,00H 06 00
Register B = 00H: record length 256.
52A9
GOSUB to the SYS0 routine at 4420H to open the file, or create it.
52AC
If that failed (NZ), JUMP to 534FH.
52AF
GOSUB to 5357H to ask for the system disk if needed.
52B2
GOSUB to 53D7H to load SYS8.

52B5H - Copy Loop

52B5
GOSUB to 5364H to have the source disk inserted.
52B8
LD HL,5600H 21 00 56
Start at 5600H.
52BB
LD (54D1H),HL 22 D1 54
Point the source FCB's buffer (FCB+03H-04H) at it.
52BE
LD DE,54CEH 11 CE 54
Point DE to the source FCB.
52C1
GOSUB to the SYS0 routine at 4436H to read a sector.
52C4
If it was read, JUMP to 52D1H.
52C6
CP 1CH FE 1C
End of file (1CH)...
52C8
...JUMP to 530EH to finish.
52CA
CP 1DH FE 1D
Record number out of range (1DH)...
52CC
...also.
52CE
Any other error: JUMP to 534FH.
52D1
INC H 24
Next page.
52D2
LD A,H 7C
(fetch it)
52D3
CP 60H FE 60
Until the end of the buffer (the operand at 52D4H)...
52D5
...LOOP back to 52BBH.
52D7
Buffer full: GOSUB to 5381H to have the destination disk inserted.
52DA
LD HL,5600H 21 00 56
Start at 5600H.
52DD
LD (54F1H),HL 22 F1 54
Point the destination FCB's buffer at it.
52E0
LD DE,54EEH 11 EE 54
Point DE to the destination FCB.
52E3
GOSUB to the SYS0 routine at 4439H to write the sector.
52E6
If that failed (NZ), JUMP to 534FH.
52E8
INC H 24
Next page.
52E9
LD A,H 7C
(fetch it)
52EA
CP 60H FE 60
Until the end of the buffer (the operand at 52EBH)...
52EC
...LOOP back to 52DDH.
52EE
LOOP back to 52B5H for the next load.
52F0
(Nothing jumps to 52F0H-530DH, the same ending as 530EH without the copy of the end-of-file byte.) GOSUB to 5333H to write what is in the buffer.
52F3
GOSUB to 5357H to ask for the system disk if needed.
52F6
GOSUB to 53DAH to load SYS3.
52F9
LD A,(5358H) 3A 58 53
Drive 0?
52FC
OR A B7
(test it)
52FD
Then GOSUB to 5381H for the destination disk.
5300
LD DE,54EEH 11 EE 54
Point DE to the destination FCB.
5303
GOSUB to the SYS0 routine at 4428H to close it.
5306
If that failed, JUMP to 534FH.
530B
JUMP to 402DH.
530E
End of the file: GOSUB to 5333H to write what is in the buffer.
5311
LD HL,(54D6H) 2A D6 54
Copy FCB+08H-09H (the end-of-file byte and the record length)...
5314
LD (54F6H),HL 22 F6 54
...to the destination FCB.
5317
GOSUB to 5357H to ask for the system disk if needed.
531A
GOSUB to 53DAH to load SYS3, which closes files.
531D
LD A,(5358H) 3A 58 53
Drive 0?
5320
OR A B7
(test it)
5321
Then GOSUB to 5381H to have the destination disk inserted again.
5324
LD DE,54EEH 11 EE 54
Point DE to the destination FCB.
5327
GOSUB to the SYS0 routine at 4428H to close it.
532A
If that failed (NZ), JUMP to 534FH.
532D
GOSUB to 5357H to ask for the system disk if needed.
5330
JUMP to 402DH: back to VTOS READY.

5333H - Write the Rest

HL points past the last page read. If anything was read, the destination disk is asked for and the pages from 5600H up to HL are written.

5333
LD A,H 7C
Was anything read (H not 56H)?
5334
CP 56H FE 56
(compare with 56H)
5336
RET Z C8
If not, RETURN.
5337
GOSUB to 5381H to have the destination disk inserted.
533A
LD B,H 44
Register B = the page to stop at.
533B
LD HL,5600H 21 00 56
Start at 5600H.
533E
LD (54F1H),HL 22 F1 54
Point the destination FCB's buffer at it.
5341
LD DE,54EEH 11 EE 54
Point DE to the destination FCB.
5344
GOSUB to 4439H to write the sector.
5347
If that failed (NZ), JUMP to 534FH.
5349
INC H 24
Next page...
534A
LD A,H 7C
(fetch it)
534B
CP B B8
...until the page in B.
534E
RET C9
RETURN.
534F
PUSH AF F5
An error: save the error code...
5350
...GOSUB to 5357H to ask for the system disk if needed...
5353
POP AF F1
...restore the error code...
5354
...and JUMP to the error exit at 53F0H.

5357H - Disk Prompts

5357H asks for the system disk when drive 0 is used. 5364H asks for the source disk and 5381H for the destination disk until the disk in the drive has the GAT bytes CEH-DFH kept at 550EH or 5520H. 539EH compares B bytes at DE and HL (Z if the same). 53A7H displays a prompt and waits for ENTER, blinking the prompt: it is erased and shown again about every half second (by the delay count).

5357
LD A,00H 3E 00
Load Register A with the drive (the operand at 5358H).
5359
OR A B7
Test it.
535A
RET NZ C0
Not drive 0: RETURN.
535B
PUSH HL E5
Save HL.
535C
LD HL,546CH 21 6C 54
Point HL to INSERT SYSTEM DISK (ENTER) at 546CH...
535F
...and GOSUB to 53A7H to wait for it.
5362
POP HL E1
Restore HL.
5363
RET C9
RETURN.
5364
PUSH HL E5
Save HL.
5365
LD HL,548BH 21 8B 54
Point HL to INSERT SOURCE DISK (ENTER) at 548BH...
5368
...and GOSUB to 53A7H to wait for it.
536B
LD A,(5358H) 3A 58 53
Fetch the drive...
536E
LD C,A 4F
...into C.
536F
GOSUB to 53DDH to read the GAT.
5372
LD HL,42CEH 21 CE 42
Compare its bytes CEH-DFH...
5375
LD DE,550EH 11 0E 55
...with those of the source disk...
5378
LD B,12H 06 12
(18 bytes)
537D
POP HL E1
Restore HL.
537E
If it is another disk, LOOP back to 5364H.
5380
RET C9
RETURN.
5381
PUSH HL E5
Save HL.
5382
LD HL,54AAH 21 AA 54
Point HL to INSERT DESTINATION DISK (ENTER) at 54AAH...
5385
...and GOSUB to 53A7H to wait for it.
5388
LD A,(5358H) 3A 58 53
Fetch the drive...
538B
LD C,A 4F
...into C.
538C
GOSUB to 53DDH to read the GAT.
538F
LD HL,42CEH 21 CE 42
Compare its bytes CEH-DFH...
5392
LD DE,5520H 11 20 55
...with those of the destination disk...
5395
LD B,12H 06 12
(18 bytes)
539A
POP HL E1
Restore HL.
539B
If it is another disk, LOOP back to 5381H.
539D
RET C9
RETURN.
539E
LD A,(DE) 1A
Fetch a byte at DE.
539F
CP (HL) BE
Compare it with the byte at HL.
53A0
RET NZ C0
If they differ, RETURN with NZ.
53A1
INC HL 23
(next byte)
53A2
INC DE 13
(next byte)
53A3
LOOP back to 539EH for B bytes.
53A5
XOR A AF
All the same: Z.
53A6
RET C9
RETURN.
53A7
GOSUB to the SYS0 routine at 4467H to display the prompt at HL.
53AA
LD A,(3840H) 3A 40 38
Wait until ENTER (bit 0 of 3840H) is released.
53AD
RRCA 0F
(bit 0 into Carry)
53AE
(loop while it is pressed)
53B0
LD BC,4000H 01 00 40
Load BC with 4000H: the time the prompt is shown.
53B3
LD A,(3840H) 3A 40 38
Is ENTER pressed?
53B6
RRCA 0F
(bit 0 into Carry)
53B7
If so, JUMP to 53CBH.
53B9
DEC BC 0B
Count down...
53BA
LD A,B 78
(test BC)
53BB
OR C B1
(OR the low byte)
53BE
LD A,1EH 3E 1E
Time up: erase the line (1EH)...
53C0
...through the ROM routine at 0033H...
53C3
LD BC,3333H 01 33 33
...wait (BC = 3333H)...
53C6
...with the ROM delay routine at 0060H...
53C9
...and LOOP back to 53A7H to show it again.
53CB
GOSUB to the ROM routine at 0049H to take the key.
53CE
LD A,1EH 3E 1E
Erase the line (1EH)...
53D0
(display it)
53D3
RET C9
...and RETURN.

53D4H - Load an Overlay

Each entry calls an overlay with request 00H, which does nothing but leaves the overlay in memory: 53D4H SYS2 (84H), 53D7H SYS8 (8AH), 53DAH SYS3 (85H). The overlay returns to the caller.

53D4
LD A,84H 3E 84
Load Register A with 84H: SYS2, request 00H.
53D6
RST 28H EF
Call it through RST 28H.
53D7
LD A,8AH 3E 8A
Load Register A with 8AH: SYS8, request 00H.
53D9
RST 28H EF
Call it through RST 28H.
53DA
LD A,85H 3E 85
Load Register A with 85H: SYS3, request 00H.
53DC
RST 28H EF
Call it through RST 28H.

53DDH - Read the GAT

Reads the GAT of drive C into 4200H. Returns NZ with A = 14H (GAT read error) if that fails. DE and HL are preserved.

53DD
PUSH DE D5
Save DE.
53DE
PUSH HL E5
Save HL.
53DF
GOSUB to the SYS0 routine at 4B65H to get the directory track.
53E2
LD E,00H 1E 00
Load Register E with 00H: the GAT.
53E4
LD HL,4200H 21 00 42
Point HL to 4200H.
53E7
GOSUB to the SYS0 routine at 4B45H to read it.
53EA
POP HL E1
Restore HL.
53EB
POP DE D1
Restore DE.
53EC
RET Z C8
If it was read, RETURN.
53ED
LD A,14H 3E 14
Load Register A with 14H: GAT read error.
53EF
RET C9
RETURN with NZ.

53F0H - Error Exits

53F0
OR 40H F6 40
Error exit with the error code in Register A: set bit 6, so that only the message is displayed.
53F2
JUMP to the SYS0 error handler at 4409H.
53F5
LD HL,5407H 21 07 54
Point HL to FILE SPEC REQUIRED at 5407H.
53F8
GOSUB to 447BH to display it.
53FB
JUMP to 4030H.
53FE
LD HL,541AH 21 1A 54
Point HL to the message at 541AH.
5401
GOSUB to 447BH to display it.
5404
JUMP to 4030H.
5407-5419
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 53F8H.
541A-5441
DEFM "INVALID COMMAND DURING PROGRAM CHAINING",0DH 49 4E 56 41 4C 49 44 20 43 4F 4D 4D 41 4E 44 20 44 55 52 49 4E 47 20 50 52 4F 47 52 41 4D 20 43 48 41 49 4E 49 4E 47 0D
Displayed at 5401H.
5442-546B
DEFM "SOURCE AND DESTINATION DISKS ARE THE SAME",0DH 53 4F 55 52 43 45 20 41 4E 44 20 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 53 20 41 52 45 20 54 48 45 20 53 41 4D 45 0D
Displayed at 529BH.
546C-548A
DEFB 1DH,1EH : DEFM "INSERT SYSTEM DISK (ENTER)" : DEFB 1DH,03H 1D 1E 49 4E 53 45 52 54 20 53 59 53 54 45 4D 20 44 49 53 4B 20 20 28 45 4E 54 45 52 29 1D 03
Prompt shown at 535FH. 1DH moves the cursor to the start of the line and 1EH erases to the end of the line.
548B-54A9
DEFB 1DH,1EH : DEFM "INSERT SOURCE DISK (ENTER)" : DEFB 1DH,03H 1D 1E 49 4E 53 45 52 54 20 53 4F 55 52 43 45 20 44 49 53 4B 20 20 28 45 4E 54 45 52 29 1D 03
Prompt shown at 5247H and 5368H.
54AA-54CD
DEFB 1DH,1EH : DEFM "INSERT DESTINATION DISK (ENTER)" : DEFB 1DH,03H 1D 1E 49 4E 53 45 52 54 20 44 45 53 54 49 4E 41 54 49 4F 4E 20 44 49 53 4B 20 20 28 45 4E 54 45 52 29 1D 03
Prompt shown at 5270H and 5385H.

ISAM 81H (LOAD) and 82H (RUN) - Offset 3A5E

One member serves two commands. LOAD (LOAD filespec (X), ISAM 81H, entry 5200H) loads a program file (default extension /CMD) into memory and returns to VTOS READY; RUN (ISAM 82H, entry 520DH) loads it and jumps to its transfer address. With X, the program is loaded from a disk that is not the system disk: SYS2 is loaded first, INSERT SOURCE DISK (ENTER) is shown, and after loading INSERT SYSTEM DISK (ENTER). The prompts blink until ENTER is pressed. The member loads at 5200H-52D1H and 52F2H-5324H (261 bytes); 52D2H-52F1H is the FCB.

5200H - LOAD Command

HL points to the text after LOAD.

5200
GOSUB to 5216H to read the filespec and the parameters.
5203
LD DE,402DH 11 2D 40
Push 402DH as the return address...
5206
PUSH DE D5
(push it)
5207
LD DE,52D2H 11 D2 52
...point DE to the FCB at 52D2H...
520A
...and JUMP to 52F2H to load the file.

520DH - RUN Command

HL points to the text after RUN.

520D
GOSUB to 5216H to read the filespec and the parameters.
5210
LD DE,52D2H 11 D2 52
Point DE to the FCB at 52D2H...
5213
...and JUMP to 5300H to load and run the file.

5216H - Read the Filespec

Reads the filespec into the FCB with the default extension /CMD and scans the parameters. With X, SYS2 is loaded and the source disk asked for.

5216
LD DE,52D2H 11 D2 52
Point DE to the FCB at 52D2H.
5219
GOSUB to the SYS0 routine at 441CH to read the filespec into it.
521C
If there is none (NZ), JUMP to 5272H to display FILE SPEC REQUIRED.
521F
LD A,(DE) 1A
Fetch its first character.
5220
CP 2AH FE 2A
A device (*)...
5222
...is not accepted: JUMP to 5272H.
5224
PUSH HL E5
Save the line pointer.
5225
LD HL,52CFH 21 CF 52
Point HL to the default extension CMD at 52CFH.
5228
GOSUB to the SYS0 routine at 4473H to use it if the filespec has no extension.
522B
POP HL E1
Restore the line pointer.
522C
LD DE,52C6H 11 C6 52
Point DE to the parameter table at 52C6H.
522F
GOSUB to the SYS0 routine at 4476H to scan the parameters in parentheses.
5232
If a parameter was not recognized (NZ), JUMP to 527BH to display PARAMETER ERROR.
5234
PUSH HL E5
Save the line pointer.
5235
GOSUB to 526FH to load SYS2, which opens files.
5238
LD DE,0000H 11 00 00
Load DE with the X value (the operand at 5239H).
523B
LD A,D 7A
Test it...
523C
OR E B3
(OR the low byte)
523D
LD HL,52A7H 21 A7 52
...and if X was given, point HL to INSERT SOURCE DISK (ENTER) at 52A7H...
5240
...and GOSUB to 5245H to wait for it.
5243
POP HL E1
Restore the line pointer.
5244
RET C9
RETURN.

5245H - Prompt and Wait for ENTER

Displays the prompt at HL and waits for ENTER, blinking the prompt: it is erased and shown again after a delay.

5245
GOSUB to the SYS0 routine at 4467H to display the prompt.
5248
LD A,(3840H) 3A 40 38
Wait until ENTER (bit 0 of 3840H) is released.
524B
RRCA 0F
(bit 0 into Carry)
524C
(loop while it is pressed)
524E
LD BC,4000H 01 00 40
Load BC with 4000H: the time the prompt is shown.
5251
LD A,(3840H) 3A 40 38
Is ENTER pressed?
5254
RRCA 0F
(bit 0 into Carry)
5255
If so, JUMP to 5269H.
5257
DEC BC 0B
Count down...
5258
LD A,B 78
(test BC)
5259
OR C B1
(OR the low byte)
525C
LD A,1EH 3E 1E
Time up: erase the line (1EH)...
525E
...through the ROM routine at 0033H...
5261
LD BC,3333H 01 33 33
...wait (BC = 3333H)...
5264
...with the ROM delay routine at 0060H...
5267
...and LOOP back to 5245H to show it again.
5269
LD A,1EH 3E 1E
ENTER: erase the line (1EH)...
526B
(display it)
526E
RET C9
...and RETURN.
526F
LD A,84H 3E 84
Load Register A with 84H: SYS2, request 00H, which does nothing but leaves SYS2 in memory.
5271
RST 28H EF
Call it through RST 28H; it returns to the caller of 526FH.

5272H - Error Messages

5272
LD HL,5284H 21 84 52
Point HL to FILE SPEC REQUIRED at 5284H.
5275
GOSUB to the SYS0 routine at 447BH to display it (and copy it to the job log device when that is active).
5278
JUMP to 4030H: back to VTOS READY.
527B
LD HL,5297H 21 97 52
Point HL to PARAMETER ERROR at 5297H.
527E
GOSUB to 447BH to display it.
5281
JUMP to 4030H.
5284-5296
DEFM "FILE SPEC REQUIRED",0DH 46 49 4C 45 20 53 50 45 43 20 52 45 51 55 49 52 45 44 0D
Displayed at 5275H.
5297-52A6
DEFM "PARAMETER ERROR",0DH 50 41 52 41 4D 45 54 45 52 20 45 52 52 4F 52 0D
Displayed at 527EH.
52A7-52C5
DEFB 1DH,1EH : DEFM "INSERT SOURCE DISK (ENTER)" : DEFB 1DH,03H 1D 1E 49 4E 53 45 52 54 20 53 4F 55 52 43 45 20 44 49 53 4B 20 20 28 45 4E 54 45 52 29 1D 03
Prompt shown at 5240H. 1DH moves the cursor to the start of the line and 1EH erases to the end of the line.
52C6-52CD
DEFM "X " : DEFW 5239H 58 20 20 20 20 20 39 52
X: operand of the LD DE at 5238H.
52CE
DEFB 00H 00
End of the parameter table.
52CF-52D1
DEFM "CMD" 43 4D 44
The default extension.
52D2-52F1
DEFS 32
The FCB. Not in the file.

52F2H - Load the File

DE points to the FCB. For LOAD, 402DH is on the stack; for RUN, the transfer address is pushed. With X, the system disk is asked for after loading.

52F2
LOAD: GOSUB to the SYS0 routine at 4430H to load the file (no test for an error follows).
52F5
LD A,(5239H) 3A 39 52
Fetch the X value (low byte)...
52F8
OR A B7
...test it...
52F9
LD HL,5306H 21 06 53
...point HL to INSERT SYSTEM DISK (ENTER) at 5306H...
52FC
...and if X was given, JUMP to 5245H to ask for the system disk, which then RETURNs as below.
52FF
RET C9
RETURN: to 402DH for LOAD, to the program for RUN.
5300
RUN: GOSUB to 4430H to load the file; HL = its transfer address (no test for an error follows).
5303
PUSH HL E5
Push it as the return address.
5304
JUMP to 52F5H.
5306-5324
DEFB 1DH,1EH : DEFM "INSERT SYSTEM DISK (ENTER)" : DEFB 1DH,03H 1D 1E 49 4E 53 45 52 54 20 53 59 53 54 45 4D 20 44 49 53 4B 20 20 28 45 4E 54 45 52 29 1D 03
Prompt shown from 52FCH.