TRS-80 DOS - DOSPLUS 3.5 for the Model III - Disassembled

Overview

DOSPLUS 3.5 is the disk operating system Micro-Systems Software published in 1983 for the TRS-80 Model I and Model III. This page covers the Model III version, from its master diskette; the Model I version has its own page. Each file is disassembled from its bytes, with the DOSPLUS 3.5 technical manual (T/1 on) used as a source of claims to check, and every difference the bytes show is noted on the file's page.

The master is a double density diskette of 40 cylinders, one side, 18 sectors to a track, a granule of 6 sectors and 3 granules to a cylinder; the directory is cylinder 20 (14H). DOSPLUS has a resident part, SYS0/SYS, at 4000H-4DFFH, and overlays: SYS1/SYS-SYS8/SYS (the system routines) load at 4E00H-51FFH and SYS9/SYS-SYS16/SYS (the library commands) at 5200H-5BFFH. A program or the system reaches an overlay routine by putting a request code in Register A and executing RST 28H: the high four bits of the code are the system number less 1, the low four bits the routine in the overlay's table. Most files differ from the Model I files only in a few bytes; SYS0/SYS, SYS1/SYS, SYS3/SYS, SYS11/SYS, SYS12/SYS, SYS13/SYS and SYS16/SYS have their own lengths.

Pages are added here as they are finished: BOOT/SYS, the SYS files in order, then BASIC/CMD, ERROR/OVL and TBASIC/CMD, then the other /CMD files of the master. DIR/SYS gets no page of its own; its structure (the allocation table, the hash index table and the directory entries) is described in the manual and in the SYS0/SYS introduction when it is done.

Passwords

DOSPLUS 3.5 turns an eight-character password into a 16-bit code with SYS2/SYS’s routine at 516EH and keeps only the code; the open routine compares codes, never the words. A directory entry holds two of them, an update code at +10H (full access) and an access code at +12H (the file’s protection level), and the GAT holds the disk’s master code at +CEH–+CFH. The notable codes:

PasswordCodeUsed for
BOD, SMT, …CAA5Back door: SYS2/SYS (4EF2H) compares this code before any password and grants full access to any file at any protection level, even level 7. Several three-letter words hash to it
PASSWORD42E0The master code of a disk with no password set; the master code PROT and FORMAT expect by default
(eight spaces)4296A password of all spaces

These are the codes as DOSPLUS holds them, the byte-reverse of the usual Model I convention (PASSWORD is E042 there, 42E0 here). The hash routine and the compare are on the SYS2/SYS page, and the codes are collected with every DOS’s passwords on the DOS Tips page.

BOOT/SYS - The Boot Sector

BOOT/SYS is granule 0 of cylinder 0, six sectors. Sector 0 is data (00H, FEH and the directory cylinder, 14H); the boot sector is sector 1, which the ROM reads into 4300H and runs. It reads sector 2 (the copy of the diskette's drive control table and the boot settings) into 5200H, reads directory sector 4 to find SYS0/SYS, loads it block by block through the buffer at 5300H and jumps to its transfer address, 4E00H, with Index Register IX pointing to 5200H. The floppy disk controller is worked through ports F0H-F4H: the drive select byte to port F4H carries the side and the wait state bit, and the end of each read comes as a non maskable interrupt (vector 4049H, JP 43DDH, enabled through port E4H). A failed read or a wrong directory entry displays DISK ERROR! and stops. Sectors 3-5 are 6CH.

A disassembly of BOOT/SYS can be found here.

SYS0/SYS - The Resident System

The resident part of DOSPLUS: 36 load blocks at 400CH-50F2H, 3337 bytes, transfer address 4E00H. It stays in memory up to 4DFFH; 4E00H-50F2H is the start-up, which runs once and is overwritten by the first low overlay. Its addresses differ from the Model I version in most places, and the Model III ROM does part of its work: GTTIME@ and GTDATE@ (3036H, 3033H), the clock task in interrupt slot 7 (3529H), the keyboard scan (3024H) and the cassette interrupts.

Address RangeFunction
400CH-4035HRST 28H, RST 30H and RST 38H vectors, EXIT@, ABORT@ and the character I/O vector 4033H
428DH-42EDHFILPTR@ and RAMDIR@; the system variables (SFLAG1$ 4297H, OVLYL$ and OVLYH$ 429DH-429EH, LOW$, DODCB$, BREAK$), the eight interrupt slots, the system file control block
4400H-455AHThe entry points (HMEM$ at 4411H), the DCB table, DCTTBL, the NIL control block and the drive control tables of drives 0-3
455BH-46A3HCharacter I/O for files, FORCE, JOIN and NIL; PRINT@ and DSPLY@; LOCDCT% and LOCDCB%; the interrupt handler, the clock task and its eight slots, SET@ and RESET@
46A4H-4915HDISKIO% and the floppy disk driver (functions 0-9), the sector transfer ended by the NMI, drive selection and the geometry table
4916H-4AF1HDirectory entry I/O, MULT@ and DIVD@, the overlay request handler and loader, RUN@, LOAD@ and the program loader
4AF2H-4DC9HPOSN@, REW@, PEOF@, BKSP@, READ@, WRITE@, character I/O on a file, CKEOF@, the record locator
4DCAH-4DE8HThe keyboard driver, with DO file input
4E00H-50F2HThe start-up and its texts

The interrupt handler reads port E0H and serves the first source whose bit is 0 through the vectors in the ROM's RAM; the clock task at 4657H runs the fast slots 4-7 on every tick and one of the slow slots 0-3 in turn. The disk driver works the controller at ports F0H-F4H: each sector transfer holds the processor in wait states for every byte and is ended by the NMI from the controller (enabled through port E4H, vector 4049H set to JP 4842H). The start-up tests memory for HMEM$ (4411H), enables the I/O bus through port ECH, installs the clock and NMI vectors and the ROM's clock task, takes the step rate, the cursor and caps switches and the boot port from BOOT/SYS sector 2, displays the heading and the logo, asks for the date and the time, and runs the AUTO command from the allocation table of drive 0: an asterisk before it makes it non-breakable, an exclamation mark invisible; ENTER held at boot skips it and D starts DEBUG@. Differences from the manual: FCB+01H bit 5 is reversed, VER@ has no code of its own, SHIFT + up arrow only skips the keyboard driver.

A disassembly of SYS0/SYS can be found here.

SYS1/SYS - The Command Interpreter

The command interpreter, a low overlay of 4 load blocks at 4E00H-51F5H, 1014 bytes. Its routine table at 4E00H serves the request codes 03H (CMD@, the command level), 05H (CMNDI@), 06H (FSPEC@), 07H (FEXT@), 08H (PARAM@), 09H (the address of the library table, used by no file of the diskette), 0AH (BOOT, a RST 00H to the ROM's reset) and 0BH (CLS).

The command level resets the stack (41E5H), EXIT@, ABORT@ (a JP to EXIT@, or to DEBUG@ with DEBUG on), BREAK$ and the ROM's READY vector at 4203H (JP 402DH), runs the next command of a line that holds several separated by semicolons, and otherwise displays the DOS PLUS prompt (not while a DO file runs) and reads a line of up to 63 characters. A line beginning with a period is a comment; a slash runs the last command again. CMNDI@ clears the ROM's count of protected screen lines (4214H), takes the command name with FSPEC@, looks it up in the table of the 39 library commands (5103H, bit 7 set on each first character) and gives a library command its request code from 51B6H-51DCH through RST 28H; any other name is run with RUN@ as a program, with /CMD added when it has no extension.

FSPEC@ copies name, /extension, .password and :drive (or @device) into a file control block, ends it with 03H and skips the words TO, FROM and USING. PARAM@ reads NAME or NAME=value parameters, with or without parentheses, by a caller's table of 8 byte entries; a name may be shortened, and a value is Y, YES or ON (FFFFH), N, NO or OFF (0000H), a hexadecimal number ending with H or a decimal number. For a name not in the table PARAM@ returns Register A = FFH, not the character the manual says.

A disassembly of SYS1/SYS can be found here.

SYS2/SYS - Opening and Creating Files

The low overlay of OPEN@ (request code 13H) and INIT@ (14H), 5 load blocks at 4E00H-51CCH, 973 bytes; the fifth block is a patch to the name character test so that the characters < and > are taken in a name. Other overlays request its password code (15H), the file control block builder (16H), the hash index code (17H), the name buffer address (18H) and the drive byte (19H).

OPEN@ opens a device (@ and a two character name from the DCB table: the control block gets 90H and the DCB address) or a file: the hash index code of the name is looked for in the hash index table of the drive named or of drives 0-7, and the directory entry at that logical file number is compared. The password code (8 characters, 4296H for none) gives full access when it is CAA5H (a fixed code, any file), the diskette's master password or the entry's update password (+10H), and the file's protection level when it is the access password (+12H); level 7 files open only with CAA5H. INIT@ creates a file that is not found, in a free hash index entry chosen from the refresh register, and returns the C FLAG.

A disassembly of SYS2/SYS can be found here.

SYS3/SYS - Closing and Removing Files

The low overlay of CLOSE@ (request code 23H) and KILL@ (24H), 3 load blocks at 4E00H-50DCH, 733 bytes: the Model I code with the Model III addresses of SYS0/SYS, and 5 bytes more in the code that is not reached. Other overlays request its routine 25H, which frees the space and entries of a file by its logical file number (SYS14/SYS), and 26H, which puts an open file's specification back into its control block (SYS11/SYS). The granule allocation table is read into 5100H, after the overlay.

CLOSE@ closes only an open file; a device or a control block that is not open comes back at once (the code that would put back a device's name is not reached). The last buffer is written; a written file's entry gets the modified flag, the date, the end of file byte and the number of sectors; and, unless the entry is non-shrinkable, the granules beyond the end of the file are given back, even when it was only read, freeing extended entries left empty. The control block then holds name/extension:drive again. A Disk space full error on the last buffer still closes the file. KILL@ needs access level 0 or 1, frees the granules of every entry of the file, clears bit 4 (active) of each entry and its hash index byte, and clears the control block.

A disassembly of SYS3/SYS can be found here.

SYS4/SYS - The Granule System

The low overlay that allocates disk space, 3 load blocks at 4E00H-5051H, 594 bytes. Its only caller is SYS0/SYS's record locator (request code 33H), when the granule of a file it needs is not among the five segments in the file control block: SYS4/SYS walks the segments of the file's directory entries (following FEH links to extended entries) to the segment that holds the granule, and returns it for the control block's list (a segment already in the list gets its new count; otherwise the list moves on one place).

When the file ends before the granule, the missing granules are added: next to the last segment while those granules are free (up to 32 in a segment), otherwise as a new segment at the first free granule from there to the last cylinder and then from cylinder 0 (error 1BH, Disk space full, when there is none). A file with no space yet starts at a cylinder chosen by the directory sector of its entry, which spreads files over the diskette. When the entry has no descriptor left, an extended entry is made in a free hash index slot with the file's hash code (error 1EH when the directory is full) and linked with FEH. The tables go through 5100H.

A disassembly of SYS4/SYS can be found here.

SYS5/SYS - Error Messages

The low overlay of ERROR@ (request code 43H), 3 load blocks at 4E00H-50F0H, 753 bytes, the same as the Model I but for the addresses of the last error byte (4299H) and the request save word (429AH). It displays the message of error number bits 5-0 of Register A, framed by an asterisk, a space, an asterisk and a space when bit 6 is clear, stores the code to the last error byte and returns to the caller when bit 7 is set, or leaves through ABORT@ (EXIT@, or DEBUG@ with DEBUG on). The messages are built from a table of 64 words with a list of word numbers for each of the errors 00H-3FH (33H-3FH: Unknown error code); the first letter is a capital and the rest lower case.

A disassembly of SYS5/SYS can be found here.

SYS6/SYS - The DEBUG Monitor

The low overlay of the DEBUG monitor (request code 53H from DEBUG@, reached by RST 30H, BREAK with DEBUG on, and the start-up's D key), 5 load blocks at 4E00H-51FDH, 1022 bytes, the Model I code with its variables at 4265H-4286H (Model I 405DH-407EH). It saves all the program's registers, takes its two RST 30H breakpoints out, and shows either the registers (each with the 16 bytes it points to, or the flags) and four lines of memory, or a full screen of 256 bytes.

Commands: A and H (bytes as characters or hexadecimal), D (display address), ; and - (next and previous page), S and X (full screen or registers), U (update until a key), M (change memory), R (change a register), G (go, with up to two breakpoints), O (to EXIT@), and I and C (single step; C runs a call whole). The single step finds each instruction's length and target in three mask tables; a JP (IX) step takes its target from IY, because the test looks at the wrong byte.

A disassembly of SYS6/SYS can be found here.

SYS7/SYS - EVAL@, WILD@ and LOCDEV@

The low overlay of the command line routines (request codes 63H EVAL@, 64H WILD@, 65H LOCDEV@, and 66H, one field, requested by SYS11/SYS), 4 load blocks at 4E00H-51E4H, 997 bytes, the Model I code with the Model III addresses of SYS0/SYS; the wildmask is kept at 42B0H-42BAH, outside the overlay. EVAL@ takes the source, destination and wildmask fields of a command line into 33 byte blocks, by the keywords FROM, TO and USING or else by the order of the fields (a field with a wildcard is the wildmask), and the parameters, which may be logical values, numbers or quoted strings, into a parameter block of 9 byte entries; every error returns 2EH, Invalid parameter.

WILD@ sets the wildmask from a file specification (* and ! fill with ?) or compares an 11 byte name and extension with it. LOCDEV@ finds the number of a drive (after a colon, in DCTTBL, returned with bit 3 set) or of a device (in the DCB table) from its two character name, or returns error 29H.

A disassembly of SYS7/SYS can be found here.

SYS8/SYS - SORT@, CAT@, FILPTR@ and RAMDIR@

The low overlay of four service routines (request codes 73H SORT@, 74H CAT@, 75H FILPTR@, 76H RAMDIR@), 9 load blocks at 4E00H-5176H, 873 bytes, four of them patches over earlier bytes, the Model I code with the Model III addresses of SYS0/SYS (CAT@'s drive digit at 4271H). SORT@ is a Shell sort of a list of equal entries by a key, ascending or descending (a self-modified jump), with its own error codes 01H-05H. CAT@ clears the screen and lists the files of a drive four to a line under FILE CATALOG: and the diskette's name, pausing every screen; it shows only entries whose flag byte is 10H.

FILPTR@ loads the drive and logical file number of an open file into Register Pair BC, but SYS0/SYS's file routine wrapper restores BC on the way out, so they do not reach the caller. RAMDIR@ copies all file entries, or one by its logical file number (range checked by a patch), as 22 byte records ended by +, or stores the kilobytes used and free.

A disassembly of SYS8/SYS can be found here.

SYS9/SYS - The Library Commands CAT, DIR and FREE

The first high overlay (request codes 83H CAT, 84H DIR, 85H FREE), 6 load blocks at 5200H-577FH, 1402 bytes, no patches, the Model I code with the Model III addresses of SYS0/SYS (HMEM$ 4411H, SFLAG1$ 4297H, the buffer 4300H). The three commands share one entry: CAT enters inside DIR's LD A,AFH and FREE inside a second one, which sets the flags that choose DIR's long listing and FREE's map. EVAL@ takes a source drive, a destination (the display by default, a device, or a file opened by INIT@), a wildmask and the parameters INVIS, SYSTEM, KILL and ALPHA, whose values are stored straight into instruction operands. Each drive starts with the summary line Drive: name diskname - Space: free/total entries and the free kilobytes; FREE alone shows every ready drive, CAT and DIR drive 0, or every drive with a wildmask.

FREE with a drive draws the map of its granules, a line for six or seven cylinders: L locked out, D the directory, x in use, a period free. CAT lists four names to a line; DIR gives each file its seven attributes (protection level, P, S, K, I, ! and +), record length, sectors, records, kilobytes of all its extents and the date. ALPHA reads the whole directory into memory and sorts it with SORT@. The SPACE BAR pauses and BREAK ends the output.

A disassembly of SYS9/SYS can be found here.

SYS10/SYS - The Library Commands COPY, APPEND and LIST

The second high overlay (request codes 93H COPY, 94H APPEND, 95H LIST), 7 load blocks at 5200H-585FH, 1632 bytes, no patches, the Model I code with the Model III addresses of SYS0/SYS (HMEM$ 4411H, SFLAG1$ 4297H, the buffer 4300H) and prompts ending [ENTER]. Every switch of the three commands is the operand of an instruction that EVAL@ stores the value into. COPY makes a device copy when either side is a device, a file copy when the source is a file, and a wildmask copy of a whole directory when the source is a drive (SYSTEM, INVIS, MOD and the wildmask choose the files; SPW and DPW give the master passwords).

A file copy asks Copy ? (QUERY) and Overwrite ? (OVER), passes over files by OLD and NEW, writes the destination once at the source's last sector to give it its full size, then moves the data through all of memory from 5A00H (one page with TINY), closes it with the source's end, kills the source (KILL) or clears its modified flag, and gives the copy the source's flag byte, record length and passwords. With PROMPT it asks for the source, destination and system disks, and loads SYS2/SYS, SYS4/SYS and SYS3/SYS before the system disk can be taken out. LIST and APPEND use the device copy loop; LIST lists to @DO by default, and APPEND opens an existing file, goes to its end and backs up four bytes (CMD) or one (STRIP).

A disassembly of SYS10/SYS can be found here.

SYS11/SYS - The Library Commands ASSIGN, FILTER, FORCE, JOIN and RESET

The third high overlay (request codes A3H FORCE, A4H RESET, A5H ASSIGN, A6H JOIN, A7H FILTER), 6 load blocks at 5200H-5779H, 1402 bytes, no patches: the Model I code with the Model III addresses of SYS0/SYS, except that the reading of the filter file is six bytes longer (a quoted space or period is allowed). FORCE and JOIN share their code (JOIN enters inside FORCE's second instruction). Without fields they list the six devices with their directions, drivers, FORCE, NIL and JOIN targets; with fields the source device is reset, then routed to a device or to a file opened in 288 bytes below HMEM$: its driver and type are saved in its DCB table entry and its DCB points to the target. RESET undoes this for one device or for devices 0-5 (not the drives).

ASSIGN copies the DCB or drive control table of another device or drive over the first one's, or RUNs a driver program with Index Register IX at the DCB and Register Pair HL at its parameters; a device or drive that shares SYS0/SYS's NIL block first gets 20 bytes of its own. FILTER reads a file of old=new pairs (hexadecimal or quoted codes, comments after a period) into a table below HMEM$ and switches the device's filter bit on, unless NO or OFF is given; MAP lists the table.

A disassembly of SYS11/SYS can be found here.

SYS12/SYS - The Library Commands AUTO, BREAK, CLOCK, DATE, DEBUG, ERROR, I, LIB, PAUSE, SCREEN, TIME and VERIFY

The fourth high overlay (request codes B3H-BEH), 5 load blocks at 5200H-5647H, 1087 bytes, no patches: the Model I code with the Model III addresses of SYS0/SYS, except SCREEN (codes sent as they are) and CLOCK (bit 0 of 4210H, the ROM's time display flag). AUTO writes the command into +E0H of a diskette's GAT; DATE and TIME set DATE$ and TIME$ from up to three numbers or show them, DATE with the weekday (counted from 1900), the month's name, 19yy and the day of the year. DEBUG, VERIFY and BREAK set bits 2, 3 and 0 of SFLAG1$.

ERROR shows the message of an error code or of the last error; I has the drive given, or drives 1-7, logged again (MOUNT reads the GAT at once and sets the sides); LIB lists the library commands from SYS1/SYS's table; PAUSE waits for ENTER; SCREEN sends the 16 lines of the screen to @PR, a device or a file.

A disassembly of SYS12/SYS can be found here.

SYS13/SYS - The Library Commands DO, FORMS and RS232

The fifth high overlay (request codes C3H-C5H), 5 load blocks at 5200H-567FH, 1152 bytes, no patches: the Model I code with the Model III addresses of SYS0/SYS, except RS232, which works on the ROM's RS-232 initialisation block at 41F5H. DO takes the file and HIGH and BREAK through EVAL@, sets HMEM$ and the BREAK key flag, takes 288 bytes below HMEM$ for the first DO and opens the file (extension TXT). FORMS shows or sets the page length, lines and width of @PR and sends CODE (high byte first) and TOP (0CH) to the printer.

RS232 shows or sets the baud rate (41F8H), the control byte (41F9H) and the wait switch (41FAH, the WAIT parameter, shown as ,Wait), then has the ROM's 005AH set up the interface. Against the manual: ODD=N gives odd parity, STOPS=0 sets every bit, CODE sends its high byte first.

A disassembly of SYS13/SYS can be found here.

SYS14/SYS - The Library Commands ATTRIB, KILL and PROT

The sixth high overlay (request codes D3H-D5H), 6 load blocks at 5200H-57A4H, 1445 bytes, no patches: the Model I code byte for byte with the Model III addresses of SYS0/SYS. ATTRIB sets a file's protection level, invisible, non-shrinkable and modified bits, record length and update and access password codes, for one file or for every file of a wildmask (with the master password). KILL kills a file, the files of a wildmask (QUERY, ECHO, SYSTEM, INVIS), or disables a drive or a device (NIL bit).

PROT checks the master password, sets a new one (MPW), the diskette name and date in the GAT, zeroes the free directory entries (CLEAN) and gives the files the master password or none (LOCK, only for the codes UPDATE and ACCESS name). Against the manual: LOCK alone changes nothing.

A disassembly of SYS14/SYS can be found here.

SYS15/SYS - The Library Commands BUILD, CLEAR, CREATE, DUMP, LOAD and RENAME

The seventh high overlay (request codes E3H-E8H), 7 load blocks at 5200H-58D6H, 1751 bytes, no patches: the Model I code byte for byte with the Model III addresses of SYS0/SYS. BUILD writes lines typed at the keyboard to a file (default TXT) or a device, APPEND showing the file first. CLEAR fills memory (5C00H to the top of memory by default) or every sector of a file with a one or two byte value. CREATE makes a new file with LRL and gives it SIZE records, GRANS granules or KILO kilobytes in advance, then DATA, VERIFY and KEEP. DUMP writes memory as a load module (CMD, with RELO and TRA) or as data (CIM).

LOAD loads a load module or, with START, a core image file, with PROMPT for single drive use and RUN. RENAME renames a file (its entry and hash index byte) or a device or drive (its table name). Against the manual: LOAD adds no extension, RUN without TRA goes to 402DH, and a record other than 01H/02H whose fourth byte is 1EH or more ends LOAD; BUILD drops a line ended by BREAK.

A disassembly of SYS15/SYS can be found here.

SYS16/SYS - The Library Commands CONFIG and SYSTEM

The last high overlay (request codes F3H-F4H), 7 load blocks at 5200H-58A6H, 1703 bytes, no patches: the Model I code with the Model III addresses of SYS0/SYS, without the density change before the boot sector is read, with the ROM's 005AH for the RS-232 interface and its own table of system areas. CONFIG lists the eight drives of DCTTBL with their drive control tables or changes one drive's table (SIDES, SIZE, STEP, PDRIVE, WPROT, COFFST, HOFFST, TSIZE, MDELAY, HLOAD, SKIP).

SYSTEM shows LOW$, HIGH$ and TOP$, sets the boot options in the boot sector (TIME, DATE, LOGO, STEP, PORT, MODE, and with SAVE BLINK, CAPS, CURSOR) and HIGH$, and writes a configuration file (CFG): a load module whose loader puts the saved system areas and the memory above HIGH$ back. Against the manual: CONFIG's S is SIDES, not STEP.

A disassembly of SYS16/SYS can be found here.

BASIC/CMD - Extended Disk BASIC 1.7

DOSPLUS Extended Disk BASIC, version 1.7: the disk extension of the Model III's Level II ROM BASIC. A load module of 22 blocks at 5200H-6DE1H (4821 bytes, transfer 5200H), in the DOS's command overlay area, so a DOS command used from BASIC through CMD"command" loads over part of it. Its first block loads at 5C00H, before the start-up block at 5200H. The Model I and Model III files are the same length and differ in only eleven bytes, all ROM entry points (HMEM$, the error vector, SFLAG1$, and the ROM's divide and CKEOF addresses); the DOSPLUS code is identical.

The start-up points the ROM's RST 10H vector at BASIC's own character fetch and copies 49 Disk BASIC link vectors into the ROM's hook table at 4152H-41E4H, so the ROM reaches BASIC's file I/O, its functions (CVI/CVS/CVD, MKI$/MKS$/MKD$, FN, EOF, LOC, LOF, INSTR, USR, TIME$, &H), its statements (OPEN, CLOSE, FIELD, GET, PUT, LSET, RSET, LOAD, RUN, MERGE, SAVE, KILL, DEF, NAME, LINE INPUT, CMD) and the hooks that redirect PRINT and INPUT to a file. Every file operation goes through SYS0/SYS's entry points, and a DOS error is mapped to the matching Disk BASIC error. A program is saved compressed (beginning with FFH) or as ASCII; one loaded under an access level of 6 or 7 may not be listed. Against the manual: OPEN parses a random file's record length but keeps the length the file was created with, MERGE and LOAD,V need an ASCII and a compressed file respectively, and the shorthand expands a letter only when it stands alone as a statement's word.

A disassembly of BASIC/CMD can be found here.

ERROR/OVL - The Long Error Messages of BASIC

The overlay of Extended Disk BASIC that shows an error in words: 4 load blocks at 5200H-5526H, 807 bytes, transfer 5200H, with no comment records; the file is identical in the Model I and Model III masters, and the ROM routines it uses are at the same addresses in both ROMs. BASIC/CMD's error hook (link 41A6H) loads it into the high overlay area on the first error with no ON ERROR GOTO handler and returns into it with the error offset in Register E; without the file BASIC keeps the ROM's two letter codes, and the disk errors show as UE.

ERROR/OVL finds the message in its list of 44 (the ROM's errors 00H-2CH, Undefined user function 2EH, the disk errors 64H-8AH, error codes 51-70; Unprintable error for every other offset, ? for the unused codes 57, 60 and 61), shows it, lets BASIC/CMD wipe a run only program, and then goes back to the DOS for an error during the start-up of BASIC (line FFFEH), to READY in direct mode, or shows in and the line number, then --> and the statement in error with the rest of its line, as the manual's example shows.

A disassembly of ERROR/OVL can be found here.

TBASIC/CMD - Tiny Disk BASIC 1.7

DOSPLUS Tiny Disk BASIC, version 1.7: a load module of 17 blocks at 5200H-61B7H (3732 bytes, transfer 5730H), wholly resident, with its file areas from 61B7H. The Model III file differs from the Model I file only in four SYS0/SYS addresses (HMEM$, SFLAG1$, CKEOF@, DIVD@). It is BASIC/CMD's code at new addresses without the parts that need an overlay or more memory: no long error messages (ERROR/OVL), no DOS commands through CMD (CMD keeps D, E, R, S and T), no INPUT @, no line editor keys, shorthand, DI or DU, no labels (NAME is Illegal function call) and no RST 10H hook.

Its error hook shows ? and a two letter code from its own table at 5200H, which, unlike the ROM's, has codes for the disk errors (FO, IE, BN, FF, BM, AO, IO, FE, DF, EF, RN, NM, MM, DS, FL, WP, AD), then Error and the ROM's in and line number. Against the manual: BASIC/CMD without ERROR/OVL shows UE for every disk error, so the two BASICs do not use the same abbreviated messages, and the heading in the file is TBASIC - DOSPLUS Tiny disk BASIC - 1.7.

A disassembly of TBASIC/CMD can be found here.

SR/CMD - Global Search and Replace of BASIC Text

A load module of 3 blocks at 5200H-5426H (551 bytes, transfer 5200H), identical in both masters, run from Extended Disk BASIC as CMD"SR",search[,replace][,range]: BASIC/CMD's CMD passes SR to CMNDI@ as a DOS command, and SR takes the strings from BASIC's text after it (run from the DOS command level it only shows its heading). Each line in the range is expanded as LIST shows it and searched; the search mode lists each line with a match once, the replace mode replaces every match, tokenizes the line again and puts it back, then relinks the program and clears the variables. A line that would pass 255 characters keeps its old text (Line too long to edit), and an Out of memory during a change loses the line being changed.

A disassembly of SR/CMD can be found here.

O/CMD - CMD"O", the Sort of BASIC Arrays

A load module of 4 blocks at 5200H-554FH (835 bytes, transfer 5200H), identical in both masters; its heading calls it SORT - BASIC Multi key/array sort - 1.7. Extended Disk BASIC's CMD"O" runs it as a DOS command; it takes CMD"O",count,[+|-]primary(start)[+key|-key...][,tag,...] from BASIC's text (up to ten key arrays and twenty tag arrays, each existing and one dimensional), sorts them with a Shell sort (gaps n/2 down to 1), the keys in their order deciding and the later arrays moving with them, and returns straight into the ROM's statement loop. Against the manual: the limits on the arrays are not stated, the sort does not keep the order of equal elements, and the test for an array named twice does not work (it compares both address bytes with the high byte only).

A disassembly of O/CMD can be found here.

REF/CMD - CMD"REF", the Cross Reference of a BASIC Program

A load module of 4 blocks at 5200H-55DFH (992 bytes, transfer 5200H), identical in both masters; its heading reads REF - BASIC Program refrencer - 1.7. Extended Disk BASIC's CMD"REF" runs it as a DOS command; it takes the options L, V, K and P, or S= with one item, and for each kind (line numbers, variables, keywords, always in that order) passes over the program once for every item, each pass finding the least key above the one listed last with the lines it occurs in. Strings, and the rest of a line after DATA or REM, are passed over; the AS of FIELD is not a variable; a variable and an array of the same name are listed apart; an item lists up to 774 lines. The end is READY.

A disassembly of REF/CMD can be found here.

RENUM/CMD - CMD"RENUM", the Renumberer of a BASIC Program

A load module of 5 blocks at 5200H-5695H (1174 bytes, transfer 5200H), identical in both masters; its heading reads RENUM - BASIC program renumberer - 1.7. Extended Disk BASIC's CMD"RENUM",nln,inc,sln,eln (10, 10, 0 and 65529 as loaded) or CMD"RENUM",! runs it as a DOS command. A first walk stores each line's new number in its link and builds an index of 128 line addresses for a binary search; a first pass checks every reference after GOTO, GOSUB, EDIT, RUN, THEN, ELSE, RESUME, ERL, DELETE, LIST and LLIST (labels, ON ERROR GOTO 0 and RESUME 0 are left alone) and shows Syntax error or Undefined line with the line; after a message, or for !, nothing is changed. Otherwise the program is moved up and written back down with the new references, the new numbers go into the lines, the links are rebuilt, the variables cleared and READY shown. Strings, REM and DATA are not passed over.

A disassembly of RENUM/CMD can be found here.

BACKUP/CMD - BACKUP, the Mirror Image Floppy Backup

A load module of 16 blocks at 5200H-5CB3H (2730 bytes, transfer 5200H), the same length as the Model I file and different in 47 bytes (the SYS0/SYS addresses and the prompts ending [ENTER]); the last four blocks patch 53B3H-53CBH and the version digit, so its heading reads BACKUP - DOSPLUS Floppy backup - 3.51. BACKUP [FROM] :sd [TO] :dd (DATE="string",USE="string") takes the drives and the date from the command line or the prompts, refuses rigid drives and a copy between 8 inch and 5 inch drives, and finds the source's density and format from its GAT. A blank destination, or one with fewer cylinders, another density or another count of sides, is formatted (interleave 2 or 3 with a skew, sectors of 6CH) and verified, with flawed granules locked out; otherwise only what differs is formatted. The allocated granules are copied in runs as large as memory allows (read, write, verify by reading back), then the directory cylinder with the modified flags cleared on both diskettes (the 3.51 patch leaves extended entries alone). With one drive it prompts for each disk; at the end it prompts for the system disk when drive 0 was used.

A disassembly of BACKUP/CMD can be found here.

FORMAT/CMD - FORMAT, the Floppy Formatter

A load module of 10 blocks at 5200H-5BA9H (2474 bytes, transfer 5200H), the same length as the Model I file and different in 45 bytes (the SYS0/SYS addresses, the [ENTER] prompt and double density for ENTER alone); its heading reads FORMAT - DOSPLUS Floppy formatter - 3.50. FORMAT :d (NAME,DATE,PW,CYLS,SIDES,DEN,USE) takes what the command line does not give from prompts (defaults DATA, the system date or 00/00/00, eight spaces, 40 cylinders, 1 side, double density); refuses rigid drives; asks before formatting a diskette that holds data (anything but N formats). Every cylinder is formatted with the interleave and skew of BACKUP/CMD, every granule verified and the flawed ones locked out; the directory goes on the free cylinder nearest the middle, with the GAT, the HIT and the entries of BOOT/SYS and DIR/SYS; no boot code is written. 20 to 96 cylinders are accepted, though the prompt says 35-96.

A disassembly of FORMAT/CMD can be found here.

HELP/CMD - HELP, the Syntax Help

A load module of 9 blocks at 5200H-590EH and 5A32H-5A3BH (1817 bytes, transfer 5200H); the code is that of the Model I file, the texts show optional parts in [ ] instead of angle brackets and are 8 bytes longer (CONFIG without HC, CREATE DATA=value, SYSTEM with MODE and PORT). HELP [FROM] command [TO] fs/@ds: EVAL@ takes the name and the output, which is @DO, a device, or a file opened by INIT@ (a drive :d as the output is taken as device d). The name must match one of 49 words of the dictionary in full; its tokenized text is shown with tabs every 15 columns, and any other name, or none, shows the list of the 39 library commands and 9 utilities in columns of 12.

The 89 word dictionary (5350H) holds the command names and the parts of the syntax lines, which the texts name by a byte of 80H and up. The FORMAT text gives SIZE=value, a parameter FORMAT/CMD does not have (it takes SIDES).

A disassembly of HELP/CMD can be found here.

TRAP/CMD - TRAP, the Disk Error Trap

A load module of 2 blocks at 5200H-534BH (332 bytes, transfer 5200H), on the Model III master only; its heading reads TRAP - DOSPLUS Disk error trapper - 3.50. TRAP lowers HMEM$ by 110 bytes, copies its resident part (52E0H-534DH) above it and hooks DISKIO% through the operand of its JP (4489H). An error of a read, write, verify or format (functions 03H-09H, not the code 06H) shows the message and Abort,Cont,Retry,Ignore ?: A or BREAK aborts, C returns the error, I returns success, any other reply retries.

The installation moves the prompt address of the resident part but stores the distance instead of the moved buffer address (LD (530FH),BC at 5227H), so each reply writes two bytes at the new place less 52E0H, in the memory of the program that called DISKIO%.

A disassembly of TRAP/CMD can be found here.

CRUNCH/CMD - CRUNCH, the BASIC Program Cruncher

A load module of 2 blocks at 5200H-53AEH (431 bytes, transfer 5200H), on the Model III master only; its heading reads CRUNCH - BASIC program cruncher - 1.7. CRUNCH source destination (LINE) copies a tokenized BASIC program (first byte FFH, else Incorrect file type) without the spaces outside strings and DATA, without remarks (REM and the apostrophe), with repeated colons made one and every link written as FFFFH; a line that is empty or only a remark is dropped, or kept with no text when LINE is given.

A line whose text starts with a colon not followed by a remark gets the colon written before its link, which breaks the destination file. The manual has no CRUNCH section; it uses CRUNCH only in a JCL example.

A disassembly of CRUNCH/CMD can be found here.

RESTORE/CMD - RESTORE, Bringing Back a Killed File

A load module of 3 blocks at 5200H-5430H (561 bytes, transfer 5200H), on the Model III master only; its heading reads RESTORE - DOSPLUS File restoration - 3.50. RESTORE filespec (or an asterisk prompt) needs OPEN@ to fail with File not in directory, takes the hash code, name and drive from SYS2/SYS (requests 17H-19H), finds the first inactive entry with the name, sets the granules of its extents in the GAT, sets the entry and its extended entries active and puts the hash code back in the HIT; the GAT and the HIT are written, with no message.

When a granule is in use by now, or the chain of extended entries is broken, the entries already set active are made inactive again and Disk space has been re-allocated ends RESTORE. The manual has no RESTORE section.

A disassembly of RESTORE/CMD can be found here.

MAP/CMD - MAP, the Disk and File Mapper

A load module of 3 blocks at 5200H-54D0H (721 bytes, transfer 5200H), on the Model III master only; its heading reads MAP - DOSPLUS Disk/file mapper - 3.50. MAP :dr (drive 0 when none is given; an asterisk prompt when nothing is given) shows the diskette name and date from the GAT, then every active file that passes SYSTEM, INVIS and the wildmask with one line per extent, the first and last cylinder and sector in decimal (or hexadecimal with HEX), following the links to extended entries. The output goes to the display, a device (through a FORCE control block MAP makes) or a file; the SPACE BAR pauses and BREAK ends the listing.

The three switches are stored by EVAL@ straight into the operands of LD DE instructions. With HEX the digits of the numbers go to the display by the ROM's 0033H, not to the chosen output.

A disassembly of MAP/CMD can be found here.

DISKDUMP/CMD - DISKDUMP, the File Sector Display and Editor

A load module of 4 blocks at 5200H-55A9H (938 bytes, transfer 5200H), on the Model III master only; its heading reads DISKDUMP - DOSPLUS File dump/edit - 3.50. DISKDUMP filespec (or an asterisk prompt) opens the file with 256 byte records and writes one sector at a time straight into the video RAM, in hexadecimal with the characters or as characters alone (CLEAR). Keys: ; the next sector, minus the previous, = the first, + the last, G a sector, F a byte (flashing blocks), P the byte of a load address (GET@ through the load module), M the modify mode with the arrows, @ fill, ENTER to write by WRITE@, BREAK to undo.

Numbers are typed blind and end at a space or ENTER. The manual's colon for the next sector is a semicolon in the bytes, and its F command is described as G.

A disassembly of DISKDUMP/CMD can be found here.

LABEL/CMD - LABEL, the BASIC Label Resolver

A load module of 4 blocks at 5700H-5AE5H (998 bytes, transfer 5700H), on the Model III master only, described in the addendum; its heading reads LABEL - DOSPLUS Label resolver - 3.50. LABEL source destination (or two prompts) reads a tokenized BASIC program (first byte FFH): the first pass tables each label given by NAME at the start of a line with its line number; the second pass writes a copy without the NAME statements, with each label after GOTO, GOSUB, EDIT, RESUME, LIST, LLIST, DELETE or AUTO replaced by its line number, or kept with the message Undefined Label:.

Labels after THEN, ELSE, RUN or RESTORE are not resolved, and the Out of memory test compares the table with the current line number instead of HMEM$.

A disassembly of LABEL/CMD can be found here.

CONVERT/CMD - CONVERT, Files from TRSDOS and Model I Directories

A load module of 5 blocks at 5200H-56B5H (1206 bytes, transfer 5200H), on the Model III master only; its heading reads CONVERT - DOSPLUS File conversion - 3.50. CONVERT :sd :dd [wildmask] reads a double density TRSDOS diskette itself (boot sector FEH, directory sectors 3-18 of 48 byte entries, six granules of three sectors a cylinder) and copies each file that passes SYSTEM, INVIS, the wildmask, QUERY and OVER by INIT@, WRITE@ and CLOSE@; with CAT or DIR it lists the names four a row. CONVERT :dr alone rewrites the ten directory sectors of a Model I single density diskette with DWRITA.

V13 is in the parameter table but changes nothing; V12 takes the TRSDOS sector count as it is. A file already on the destination is overwritten without a question unless OVER is given, and the source may not be drive 0.

A disassembly of CONVERT/CMD can be found here.

PATCH/CMD - PATCH, Patching Load Modules

A load module of 6 blocks at 5200H-56C9H and 59D1H-59DAH (1236 bytes, transfer 5200H), on the Model III master only; its heading reads PATCH - DOSPLUS Patch Utility - 3.50. PATCH module [patchfile] takes lines A=address,F=find,C=change from the file or after an asterisk; each address is found by reading the module as it loads, F must match, and the C bytes become a type 01H record. The records are written before the transfer record behind a type 07H record with the patch name (the patch file's name, or NONAME between asterisks), so the old records stay as they were.

PATCH module name (KILL), also PULL, REMOVE, OUT or YANK, drops the named 07H record and the 01H records after it. An empty C= copies 65536 bytes with its LDIR.

A disassembly of PATCH/CMD can be found here.

SYSGEN/CMD - SYSGEN, Making a System Disk

A load module of 6 blocks at 5200H-567FH and 568AH-5743H (1338 bytes, transfer 5200H), on the Model III master only; its heading reads SYSGEN - DOSPLUS System generation - 3.52. SYSGEN :dr [bootfile] (XFER=value) needs a drive other than 0 whose HIT shows only BOOT/SYS and DIR/SYS; it writes drive 0's boot sectors (or the bootstrap file), a new configuration sector with fixed settings, and each active system file of logical file numbers 02H-14H into free granules from two cylinders below the directory, then the GAT and the HIT, and ends without a message.

An 8 inch floppy whose cylinder 0 is double density gets cylinder 0 formatted again in single density with 16 sectors.

A disassembly of SYSGEN/CMD can be found here.

TAPE/CMD - TAPE, the Disk and Tape Manager

A load module of 7 blocks at 5200H-58BFH (1728 bytes, transfer 5200H), on the Model III master only; its heading reads TAPE - DOSPLUS Disk/tape manager - 3.50. One letter commands after an asterisk: L and R read up to ten programs from disk load modules or system tapes into a store at 5B42H, M maps them (to the printer only with M-P), O sets an offset, S and W write them all as one load module or system tape at their addresses plus the offset; B sets the cassette speed, H lists the letters, I empties the store, Q returns to the DOS.

With -A and an offset, a 23 byte loader is written too, which sets the ROM's I/O drivers back by 0069H, moves the program to its own addresses and starts it. R does not set its name pointer back after a header with another name.

A disassembly of TAPE/CMD can be found here.

DIRCHECK/CMD - DIRCHECK, the Directory Checker

A load module of 8 blocks at 5200H-5979H (1914 bytes, transfer 5200H), on the Model III master only; its heading reads DIRCHECK - DOSPLUS directory checker - 3.50. DIRCHECK :dr reads the whole directory cylinder (HMEM$ must be 7F00H or above), builds its own GAT and HIT from the file entries and their extents, and reports each fault as a line, then DIRCHECK complete, nnn total errors; the output may go to a device or a file.

It checks the extents (past the cylinder count, granules used twice, the fifth pair, links to extended entries), the sector counts, BOOT/SYS and DIR/SYS, the lock out table and every GAT and HIT byte. GAT, HIT and FILES write its own GAT, its own HIT or the repaired entries back; CYL0 counts all of cylinder 0 as in use. The message Cylinder count of nnn invalid shows a byte that is not yet set.

A disassembly of DIRCHECK/CMD can be found here.

DISKZAP/CMD - DISKZAP, the Disk Zapper and Editor

A load module of 12 blocks at 5200H-5D1DH (2846 bytes, transfer 5200H), on the Model III master only; its heading reads DISKZAP - DOSPLUS Disk zapper/editor - 3.50. A menu of Set (its own geometry for each drive, put into the DCT), Fill, Copy (as many sectors a pass as the pages up to HMEM$ hold, with their address marks), Print (the screen of each sector), Verify, Format (tracks built with an interleave and written by DFORMT) and Display, which steps through the sectors, flashes a value (F) and has a modify mode with fill and write back.

It needs HMEM$ at 89F8H or above. ENTER at Fill data fills with the low byte of the sector count, not 00H, and ENTER at Interleave factor gives an interleave of 93; the density questions take D for double.

A disassembly of DISKZAP/CMD can be found here.

JCL/CMD - JCL, the Job Control Language

A load module of 14 blocks at 5200H-5EBEH (2960 bytes, transfer 5200H), on the Model III master only; its heading reads JCL - DOSPLUS Job control language - 3.50. The installer relocates the resident part 5538H-603FH by the file JCL/RLD up to the old HMEM$, puts the queue (QUEUE) and the procedure area (PROC) below it, lowers HMEM$, gives KI and DO JCL's drivers and points CMNDI@ at the resident part, which takes EX. Procedures run in levels with their own variables; the commands /OPTION, /IF, /GOTO, /EXIT, /READ, /TYPE, /QUEUE, /QLOAD, /RESUME, /PRINT, /DOS, /DEBUG, /RUN, /PURGE and /CANCEL, with /JUMP and /VOFF as bytes in the queue.

QBYTE is off when EX starts and /GOTO needs the minus sign. From the bytes: LE tests for greater and GT returns through a stray stack word, /EXIT passes $ERR on to /RUN from an empty variable, and the count of /DOS is never counted down.

A disassembly of JCL/CMD can be found here.

CODIR/CMD - CODIR, CO-DIR 2.1, the Cursor Oriented Directory

A load module of 30 blocks at 8000H-8EA0H (3745 bytes, transfer 8000H), on the Model III master only and written for both models (the byte 49H at 0125H picks the Model III command buffer and HMEM$); its title reads CO-DIR 2.1 - Cursor Oriented DIR. (C) 1983 by Hunt K. Brand. It runs CAT with a hook in the display driver that saves the screens from 9000H up to HMEM$ less 80H, then two blinking cursors pick a file and a key runs Kill, Clear, List, Copy, Diskdump, Rename, Load, Do, BASIC or the program itself on it; D, A and F list another drive or its free space, S searches, G shows the size.

The title is tested by one letter only; a space at a drive question cancels it; files marked killed are passed over, system files are not tested.

A disassembly of CODIR/CMD can be found here.