TRS-80 DOS - LDOS 5.3.1 for the Model III - Disassembled

Overview

LDOS 5.3.1 is the 1991 MISOSYS release of LDOS, the disk operating system Logical Systems wrote for the TRS-80 Model I and Model III. These pages disassemble the Model III system diskette (LDOS 5.3.1, L-10-030): its boot file, the resident system SYS0/SYS and the system overlays SYS1/SYS to SYS12/SYS, Disk BASIC with its four overlays, and the other commands of the diskette (/CMD files). Each page is written from the bytes of the file itself; the manuals are used only for the claims the pages check against the code. DIR/SYS, the directory, has no page.

The disassembly of the Model I system diskette of the same release is on its own index page. Many system overlays of the two models hold nearly the same bytes at the same addresses; where they differ, the pages of each model describe that model's code.

BOOT/SYS

Purpose:

BOOT/SYS is cylinder 0, sectors 0-4, 1280 bytes; it is not a load module. Sector 1 is the boot sector: the Model III ROM reads it into 4300H and jumps to it. It reads sector 4 of the directory cylinder (the cylinder named by its own byte 02H) into 5100H, checks that the directory entry of SYS0/SYS is in use, finds the first sector of SYS0/SYS from the entry's first extent and loads SYS0/SYS record by record through the same buffer, then jumps to its transfer address, 4E00H. Each sector is read with the CPU held in wait states, and the end of the command arrives as an NMI through the vector at 4049H; a sector gets five tries. On an error it displays Disk error or No system, waits for ENTER and restarts.

Sector 0 is a byte for byte copy of sector 1. Sector 2 is the system information sector that SYS0/SYS reads into 4300H at start-up: the configuration byte, the days of the months, two blocks of eight drive code table entries, the date and time prompt switches and the names of the days and months. Sector 3 holds the granule allocation table of an empty diskette named LDOS-513, dated 09/29/86, and sector 4 the format fill.

Disassembly:

A disassembly of BOOT/SYS can be found here.

SYS0/SYS

Purpose:

SYS0/SYS is the resident part of the system, the file the boot sector loads: a load module of 34 load blocks (3985 bytes) with its transfer address at 4E00H. Four blocks put the sign-on lines and the LDOS logo into video memory. 4000H-4DFFH stays resident, fitted around the Model III ROM's own RAM: the ROM's device control blocks and clock bytes (TIME$ 4217H, DATE$ 421AH) are kept, SYS0/SYS's keyboard and printer drivers sit over the ROM's RS-232 blocks at 41E5H, and the ROM's real time clock routine runs after the tasks on every clock interrupt.

The resident part holds the supervisor call vectors (4400H-4470H and the stubs at 4203H and 4285H-42B7H), the interrupt service routine with its latch vectors and twelve task slots, the floppy disk driver for the controller at ports F0H-F4H (wait states for the data, the NMI to end a write, a density change on a record not found), the drive code tables at 4700H, the disk primitives, the file system (@POSN, @READ, @WRITE, @CKEOF and the others), the extent search, the directory routines, the arithmetic, the RST 28H dispatcher that loads system files into 4E00H through SFCB$ (42A1H), @RUN, @LOAD, the module loader, @DSPLY and @PRINT and the keyboard scan for BREAK, SHIFT @ and ENTER.

4E00H-50FFH is the reset, overwritten afterwards by the system files: it takes over the ROM's clock vector and the NMI, finds the top of memory, installs its drivers (the video driver only when RIGHT ARROW is not held), sets up drive 0 from the boot sector, reads the system information sector, asks for the date and the time, copies the drive tables of drives 1-7, shows the diskette's name and date, and runs the AUTO command or LDOS Ready, after loading CONFIG/SYS from a copy of its last part at 405DH.

Disassembly:

A disassembly of SYS0/SYS can be found here.

SYS1/SYS

Purpose:

SYS1/SYS is the command interpreter: a system file of four load blocks for 4E00H-51FEH (1023 bytes) and the overlay length at 4BC8H, loaded by the supervisor dispatcher for every request code whose bits 3-0 are 3. Bits 6-4 of the code pick the function: the LDOS Ready command loop (93H, from @EXIT, @ABORT and @CMD), a command line given by a program with a return to it (A3H) or followed by LDOS Ready (B3H, @CMNDI), @FSPEC (C3H), @FEXT (D3H) and @PARAM (E3H).

The loop sets the stack at 41E5H, arms the BREAK trap when DEBUG is on, displays LDOS Ready and reads a line of up to 63 characters into INBUF$ (4225H) through the ROM's line input. Before every command line is carried out, SYS1/SYS makes the BREAK vector at 4203H a jump to 4206H. The line goes to the job log (@LOGER); a line that starts with a period is a comment, and a line that starts with ! is always run as a program. Otherwise the first word is taken as a file specification into CFCB$ (4485H) and looked up in the table of 35 library commands: a library command is run by its member of SYS6/SYS (request 88H) or SYS7/SYS (request 89H) at 5200H, BOOT by an RST 00H that restarts the computer through the ROM, and any other word gets /CMD and is run by @RUN with 402DH (@EXIT) as its return address.

@FSPEC copies NAME/EXT.PASSWORD:D or a device name such as *KI, in capitals, and passes over the words TO, ON, OVER and USING; @FEXT adds a default extension to a specification that has none; @PARAM reads a parameter list (NAME=value, with decimal, X'hex', quoted text and Y, N, ON and OFF values) against the caller's table.

Disassembly:

A disassembly of SYS1/SYS can be found here.

SYS2/SYS

Purpose:

SYS2/SYS opens files and devices: a system file of six load blocks for 4E00H-51FEH and the overlay length at 4BC8H (0400H, its work cell 51FFH included), loaded by the supervisor dispatcher for every request code whose bits 3-0 are 4. Bits 6-4 of the code pick the function: @OPEN (94H), @INIT (A4H, open or create), @CKDRV (C4H, check a drive), the one byte hash code of a file name for the Hash Index Table (D4H) and the 16 bit hash code of a password (E4H); request 84H only loads the file.

@OPEN takes the specification apart into the work area at 51E1H-51FFH, hashes the name and the password, and searches the HIT of the drive named, or of drives 0-7 in turn, following every match to its directory record. The access comes from the password: the master password RS0LT0FF or the file's own password give every access, otherwise the protection level of the attribute decides, level 7 refused and level 6 execute only. The control block is then filled with the buffer, the record length, the ending record number and the extents. @INIT creates a file that is on no diskette in a free directory record picked from the HIT. @CKDRV waits up to half a second (15 ticks of the Model III's clock) for the index hole, reads the allocation table and sets the drive code table's highest cylinder and two sided bit and the date stamping flag of the drive.

A device specification such as *PR is looked up in the table of device names of SYS0/SYS at 42ECH; unlike the Model I version, the control block is made a device control block of its own whose driver is a six byte copy, LD HL with the device's block and JP 4D62H, so a request on it goes on to the driver of the device.

Disassembly:

A disassembly of SYS2/SYS can be found here.

SYS3/SYS

Purpose:

SYS3/SYS closes files and devices and serves @FNAME: a system file of three load blocks for 4E00H-50A5H and the overlay length at 4BC8H (02A6H, 678 bytes), loaded by the supervisor dispatcher for every request code whose bits 3-0 are 5. Bits 6-4 of the code pick the function: @CLOSE (95H) and @FNAME (A5H).

@CLOSE writes the file's buffer when it was changed and puts the end of file byte and the ending record number into the directory record. When the file was written the record gets the MOD flag and the date, and the time as well on a diskette with the directory date format of this release (bit n of 475DH, set by @CKDRV). Then the granules of the extents are counted, across the extension records, and those the file no longer needs are freed in the allocation table, which SYS3/SYS reads into the page above itself at 5100H; an extension record left with no extent is freed in the directory and the HIT. On a write protected diskette nothing is written and the close goes on. Last, the control block gets the file specification NAME/EXT:d back, so it can be opened again.

A device is closed by turning its control block back into the specification *XX. @FNAME writes the file specification of a directory record into a buffer.

Disassembly:

A disassembly of SYS3/SYS can be found here.

SYS4/SYS

Purpose:

SYS4/SYS holds the system error dictionary and serves @ERROR (4409H, request 96H): a system file of four load blocks for 4E00H-51AEH and the overlay length at 4BC8H (03AFH, 943 bytes), loaded by the supervisor dispatcher for every request code whose bits 3-0 are 6.

The error number comes in bits 5-0 of Register A, bit 6 asks for the short message and bit 7 for a return to the program instead of the end at @ABORT; bit 6 of SFLAG$ forces the full message. The text of each of the 46 messages is built from a dictionary of 56 words stored once each, through an index table and a definition table of word numbers. The full message is built in the system buffer at 4300H and displayed through @LOGOT with the error number in decimal, followed by a line naming the device or the file of the latest file call (JDCB$) and a line with the address of the program's call (JRET$ less 3). Bits 6 and 7 of the command interpreter's status byte 4758H suppress the message or have the short text built in the program's own buffer, as TED/CMD uses it.

Disassembly:

A disassembly of SYS4/SYS can be found here.

SYS5/SYS

Purpose:

SYS5/SYS is DEBUG, the system debugger: a system file of four load blocks for 4E00H-51FEH and the overlay length at 4BC8H (03FFH, 1023 bytes), loaded by the supervisor dispatcher for request 87H, which comes from 440DH: the RST 30H vector at 400FH (a breakpoint), the BREAK trap armed by DEBUG (ON) or G, and the @DEBUG call itself.

On entry every register of the stopped program is saved in the cells 405DH-407CH, which DEBUG shares with the end of the reset of SYS0/SYS and with some library commands, and the two breakpoints are taken out. The command loop draws the register screen (twelve register pairs and four lines of memory) or the full screen of 256 bytes of memory, in hexadecimal or as characters, and reads one key: X and S choose the screen, A and H the mode, D, ; and - set and move the memory display address, U keeps redrawing, M changes memory, R changes a register pair by its name, G runs the program on with up to two breakpoints (F7H, RST 30H, written over the first byte of an instruction), and C and I single step one instruction by planting breakpoints at the next instruction and at the target of a jump, call or return, from three tables of instruction kinds. A letter it does not know goes through the word at 4400H to SYS9/SYS's extended commands when DEBUG (EXT) has loaded them.

Disassembly:

A disassembly of SYS5/SYS can be found here.

SYS6/SYS

Purpose:

SYS6/SYS is Library A: fifteen members in one file of 15625 bytes, each a separate program for one or more of the commands MEMORY, DIR, KILL, LIB, CLS, TOF, DO, SPOOL, APPEND, COPY, LIST, RENAME, DEVICE, LINK, RESET, ROUTE, SET, FILTER, LOAD and RUN. SYS1/SYS issues request 88H with the member byte of the command, and the overlay loader of SYS0/SYS finds the member's header and loads only that member: fourteen of them at 5200H, the member of FILTER and SET at 5A00H. The members hold 15081 loaded bytes.

Eight members are the Model I code at the same addresses with the Model III addresses of the resident cells. The others were rewritten where they touch the device control blocks: on the Model III the names of the devices are kept in a table of SYS0/SYS at 42ECH-42FFH, JL, SI, SO and the spare blocks are six bytes each at 42C2H-42EBH, and a routed device goes through one of four route routines at 4D53H-4D61H of SYS0/SYS, whose operand ROUTE sets to the destination. KILL, SPOOL, DEVICE, LINK, RESET, ROUTE and FILTER and SET look devices up, list them, follow their routes and reset them through these tables; RESET's templates are the ROM's power-up blocks, and DEVICE shows the Model III stepping rates (6, 12, 20 and 30 milliseconds for a 5 inch drive).

Disassembly:

A disassembly of SYS6/SYS can be found here.

SYS7/SYS

Purpose:

SYS7/SYS is Library B: thirteen members in one file of 12423 bytes, each a separate program for one or more of the commands AUTO, TIME, DATE, CREATE, VERIFY, DEBUG, FREE, SYSTEM, BUILD, ATTRIB, DUMP, PURGE, FORMS and SETCOM, and the member SYSGEN that SYSTEM (SYSGEN) runs. SYS1/SYS issues request 89H with the member byte of the command, and the overlay loader of SYS0/SYS loads only that member at 5200H. The members hold 11993 loaded bytes.

Most members are the Model I code with the Model III addresses of the resident cells. TIME (CLOCK) switches the ROM's clock display, DEBUG sets the ROM video driver's switch at 4024H, and SYSGEN saves the Model III resident cells into CONFIG/SYS: the device blocks and their table of names, the route routines, the interrupt vector and the copies of the interrupt mask and of port ECH. SYSTEM was shortened from 3303 to 2892 bytes: it has no UPDATE, BLINK sets the ROM's cursor character and blink switch instead of loading a module, FAST and SLOW switch bit 6 of port ECH and the tick pattern of the clock task, BASIC2 restores the ROM's power-up tables, and the table of supervisor calls of SVC holds the Model III addresses.

Disassembly:

A disassembly of SYS7/SYS can be found here.

SYS8/SYS

Purpose:

SYS8/SYS is @ALLOC, the dynamic allocation of disk space to a file as it is written: a system file of three load blocks for 4E00H-5095H and the overlay length at 4BC8H (0296H, 662 bytes), loaded by the supervisor dispatcher for request 9AH, which SYS0/SYS issues (its 4AB3H) when the record it positions to lies in a granule that none of the five extent slots of the file control block holds.

It walks the extents of the file's directory record and its extension records, counting granules up to the one wanted. When the file has too few, it reads the granule allocation table into 5100H and allocates the granules missing: it grows the last extent while the next granule is free, otherwise starts a new extent at the first free granule from cylinder 1 on (the byte at 4767H; the random start the code still prepares is not used), and when the four extents of a record are full it finds a free record in the hash index table, read into 4300H, and links it as an extension record. The table, the hash index table and the directory sectors are written back with the deleted data mark and verified. It then brings the control block's extent slots up to date. The code is the Model I file's at the same addresses; only the operands that name the resident routines, TIMER$ and the 4300H buffer differ.

Disassembly:

A disassembly of SYS8/SYS can be found here.

SYS9/SYS

Purpose:

SYS9/SYS holds the extended commands of DEBUG: a system file of four load blocks for 4E00H-51FDH and the overlay length at 4BC8H (03FEH, 1022 bytes), loaded by the supervisor dispatcher for request 8BH, which DEBUG (EXT) issues. The code at 4E00H runs only while the word at 4400H still holds 4876H: it lowers HIGH$ (4411H) by 03D8H, copies the 984 bytes 4E26H-51FDH, a module named EXTDBG with a link word, above the new HIGH$, and points 4400H at the copy, so that DEBUG (SYS5/SYS) hands every key it does not know to it.

The module adds the commands B (move a block), E (examine and change memory), F (fill), J (skip a byte of the program), L and W (locate a byte or a word), N (next record of a load module), O (leave for LDOS Ready), Q (port input and output), T (type text into memory), V (compare two blocks), P (print a block) and the drive keys 0-7 (read and write sectors, with the deleted data mark for directory sectors). It uses DEBUG's cells 405EH-4064H and the saved PC 407BH, and SYS5/SYS's key reader and number routines at 5189H-51F1H, which are in the overlay area while DEBUG runs. The code is the Model I file's at the same addresses; only the operands that name 4400H and HIGH$ differ.

Disassembly:

A disassembly of SYS9/SYS can be found here.

SYS10/SYS

Purpose:

SYS10/SYS carries two services: a system file of two load blocks for 4E00H-4F72H and the overlay length at 4BC8H (0173H, 371 bytes), loaded by the supervisor dispatcher for request 9CH, which @KILL (442CH) issues to delete the file whose control block is at Register Pair DE, and for request BCH, the search for a module kept in memory above HIGH$ by its name.

To delete a file it reads the granule allocation table into 5000H, frees the granules of every extent of the file's directory record and its extension records, clears each record's in use bit and its byte in the hash index table (read into 4300H), writes the sectors back with the deleted data mark and verified, then writes the allocation table and clears the control block; a device's control block is only turned back into its specification. The module search walks the chain of module headers (a JR, the link word, the name length and the name) from HIGH$ (4411H), starting from HIGH$ less the top of memory at 4415H. The code is the Model I file's at the same addresses; only the operands that name the resident routines, HIGH$, the top of memory and the 4300H buffer differ.

Disassembly:

A disassembly of SYS10/SYS can be found here.

SYS11/SYS

Purpose:

SYS11/SYS carries out the execution phase of the Job Control Language: a system file of load blocks for 4E00H-5180H and 5187H-51FBH (5181H-5186H are not loaded) and the overlay length at 4BC8H (03FCH, 1020 bytes). It answers five requests: 9DH from DO starts the job compiled into SYSTEM/JCL and open in JFCB$ (4265H), ADH and BDH are put over @EXIT and @ABORT for the length of the job (the six bytes DO keeps at 406BH; the old ones are saved at 4065H), and CDH comes from @DOKEY (42B5H), which the keyboard driver calls while a job runs so that the job file is read as the keyboard.

Bit 5 of SFLAG$ is set while a job runs and the keyboard driver is kept in KIJCL$ (42BEH). Every line of the job file is a command run through @CMNDI or the answer to a key request; lines beginning with two slashes are directives, logged and looked up by name in a table of ten: ABORT, ALERT (tones on the cassette port), DELAY, EXIT, FLASH, INPUT (the keys go to the operator through request DDH, stored into @DOKEY's operand at 42B6H), KEYIN and the labels, PAUSE, STOP and WAIT (until TIME$ shows the time given). At the end of the job, or on BREAK, Job done or Job aborted is shown and logged, @EXIT and @ABORT and the keyboard driver are put back. The code is the Model I file's at the same addresses; only the operands that name the resident system cells and routines differ.

Disassembly:

A disassembly of SYS11/SYS can be found here.

SYS12/SYS

Purpose:

SYS12/SYS holds the two directory services that programs call: a system file of three load blocks for 4E00H-50FDH and the overlay length at 4BC8H (02FEH, 766 bytes), loaded by the supervisor dispatcher for request AEH from @DODIR (4419H) and request 9EH from @RAMDIR (4290H). Both check the drive number, enter the file prologue of SYS0/SYS (49F1H) and test that the drive is there and turning: its code table must start with a JP and the index pulse must go off, on and off within 15 ticks of TIMER$, half a second at the Model III's 30 a second.

@RAMDIR puts into a buffer a 22 byte record of every visible file, or of one directory record, or the space used and free in K. @DODIR shows the visible files of a drive as NAME/EXT:d, four to a line, or lists 18 bytes of each directory record into a buffer, optionally only the files whose extension matches a mask kept in CFCB$ (4485H), or gives the diskette's name, date, capacity and free space. The lists read the hash index table into 5100H and the directory sectors into 4300H. The code is the Model I file's at the same addresses; only the operands that name the resident routines, CFCB$, TIMER$ and the 4300H buffer differ, and the half second test adds 0FH ticks instead of 14H.

Disassembly:

A disassembly of SYS12/SYS can be found here.

BASIC/CMD

Purpose:

BASIC/CMD is the disk BASIC of LDOS (its banner still says LBASIC): a load module of 5438 bytes with the image of 49 vectors at 4E00H-4E9EH and the code and data at 5200H-660FH, run at 52ECH as BASIC [*] [(FILES=n,MEM=a,BLK=sw,EXT=sw,HIGH|LOW)] [command]. The start copies the vectors to 4152H-41E4H, where the Model III ROM's BASIC jumps for the disk keywords and calls at its exits, and the restart vectors to 4000H, reads the parameters with @PARAM, lays out the file buffers above the file and goes to READY; BASIC with an asterisk goes back to the program in memory.

It adds the file statements and functions (OPEN, CLOSE, FIELD, LSET, RSET, GET, PUT, LOAD, MERGE, RUN, SAVE, KILL, EOF, LOC, LOF, MKI$ to CVD, INPUT# and PRINT#), DEF FN and FN, DEF USR and USR, INPUT@ with its field editor, LINE INPUT, INSTR, MID$ =, &H and the CMD statement (an LDOS command and back, the printer's status, the screen print, the last error, DEBUG, and the overlays BASIC/OV1 to BASIC/OV4 for CMD"N", CMD"X", CMD"V" and the sort and error texts). The Model III file differs from the Model I file in the parameters HIGH and LOW (the cassette speed at 4211H), TIME$ (the ROM's own at 3030H), CMD"R" and CMD"T" (the clock display through ROM 0298H and 02A1H instead of the interrupts), the screen print, the wide character bit (4210H bit 2), the BREAK vector at 4203H pointed at READY, and the addresses of the Model III resident area.

Disassembly:

A disassembly of BASIC/CMD can be found here.

BASIC/OV1

Purpose:

BASIC/OV1 renumbers the BASIC program in memory and changes the line numbers it refers to: CMD"N [!]first,new,increment,last". BASIC/CMD runs it with @RUN when CMD is given an N and a space (its 547CH); the file of 1264 bytes loads over BASIC/CMD at 5200H-56A4H, so when it is done it runs BASIC/CMD again with an asterisk, which goes back to the program in memory.

The code is the Model I file's at the same addresses; only the operands that name HIGH$ (4411H), CFCB$ (4485H) and INBUF$ (4225H) differ.

Disassembly:

A disassembly of BASIC/OV1 can be found here.

BASIC/OV2

Purpose:

BASIC/OV2 is the cross reference of CMD"X": it lists the variables of the BASIC program in memory and the line numbers it refers to, each with the lines where it is met, on the video, a device or a file: CMD"X [devspec or filespec] [-V or -L or =entry] [<title>]". BASIC/CMD runs it with @RUN (its 547CH); the file of 1647 bytes loads over BASIC/CMD at 5200H-581BH and runs BASIC/CMD again with an asterisk when it is done.

The code is the Model I file's at the same addresses; only the operands that name @FEXT, @KITSK, KFLAG$, CFCB$ and INBUF$ differ.

Disassembly:

A disassembly of BASIC/OV2 can be found here.

BASIC/OV3

Purpose:

BASIC/OV3 is the overlay BASIC/CMD calls back into while BASIC runs: the texts of the BASIC errors, LDOS errors turned into BASIC errors, the sort of a string array for CMD"O", the parking of the variables for a RUN with V, and the moving or copying of a program line for the M and C commands at READY. BASIC/CMD's 54DEH loads the 1229 byte file at 4E00H-5281H, the overlay area of LDOS, and calls it with a function number in Register A'; OVRLY$ (4414H) holds 01H while it is there.

The code is the Model I file's at the same addresses; the operands that differ name OVRLY$ and the cells of BASIC/CMD it changes, which are at other addresses in the Model III BASIC/CMD.

Disassembly:

A disassembly of BASIC/OV3 can be found here.

BASIC/OV4

Purpose:

BASIC/OV4 is CMD"V": it lists the variables and arrays of the BASIC program in memory with their values, and the functions made by DEF FN with their definitions, on the video or the printer: CMD"V [*DO or *PR] [-S] [-A] [=letter]". BASIC/CMD runs it with @RUN (its 547CH and 5490H); the file of 960 bytes loads over BASIC/CMD at 5200H and runs BASIC/CMD again with an asterisk when it is done.

The code is the Model I file's at the same addresses; only the operands that name CFCB$, INBUF$, @DIV and @LOGOT differ. Its call to the ROM's listing routine at 2B85H reaches the Model III ROM's JP 069AH, which clears 409FH and goes on in the same routine.

Disassembly:

A disassembly of BASIC/OV4 can be found here.

DATECONV/CMD

Purpose:

DATECONV/CMD puts the directory of a diskette written by an earlier release into the date format of LDOS 5.3: DATECONV :d. A load module of 695 bytes, three load blocks for 5200H-5473H and the transfer address 5200H. It checks the drive with @CKDRV (4209H), reads the allocation table, refuses a system diskette whose system information sector does not start with 53H or 63H, then reads each sector of directory records into 5500H, gives every dated file the time 00:00 and the year of its date in bytes +12H-+13H, writes the sector back with the deleted data mark and verifies it, and finally sets bit 3 of the configuration byte of the allocation table. On a diskette already in this format only the records whose +12H-+13H still hold 4296H, the hash of a blank password, are changed. BREAK is tested after every record.

The code is the Model I file's at the same addresses; only the operands that name @CKDRV, @LOGOT, SFLAG$, @DIV and KFLAG$ differ.

Disassembly:

A disassembly of DATECONV/CMD can be found here.

PATCH/CMD

Purpose:

PATCH/CMD changes the bytes of a disk file or adds load records to a program from patch lines: PATCH filespec1 [USING] filespec2 (parms) takes them from a file (/FIX by default), PATCH filespec (lines) from the command line. A load module of 2379 bytes, nine load blocks for 5200H-5AEFH and the transfer address 5200H. D lines write data into a record of the file, each checked first against its F line; X lines become new load blocks, named by a record of type 07H, put before the transfer record of the program or at the end of a library member (L lines); REMOVE swaps every D line with its F line, YANK turns the load blocks of a named patch into records the loader passes over. The lines are read into memory from 5F00H and gone through twice: the first pass only checks, the second does the work.

The code is the Model I file's at the same addresses; only the operands that name @FEXT, @PARAM, @LOGOT, @RWRIT and @RREAD differ.

Disassembly:

A disassembly of PATCH/CMD can be found here.

FORMAT/CMD

Purpose:

FORMAT/CMD formats a diskette: FORMAT :d (NAME="name",MPW="password",SDEN,DDEN,SIDES=n,CYL=n,STEP=n,ABS,QUERY=N,SYSTEM,WAIT=n,DIR=n). A load module of 4845 bytes, 23 load blocks with 4698 bytes in 6000H-7565H, and the transfer address 6D00H. The front end at 6D00H reads the parameters and the replies, copies the target drive's drive code table to a working copy and changes it, checks the diskette and the memory, and jumps to the engine at 6000H. The engine builds each track from one of four templates over the front end, writes every cylinder, verifies every sector and locks out bad cylinders, chooses the directory cylinder, and writes the two boot sectors, the allocation table and its copy, the system information sector and the directory, calling the drive's driver itself through the working table.

The code is the Model I file's, moved down (the engine's tables by 5FH, the allocation table image to 6900H, the buffer to 6C00H, the front end to 6D00H), with these changes: no second pass over cylinder 0 in single density, so SYSTEM is accepted only for a hard disk; both boot sector images hold the Model III boot sector that runs at 4300H, the step rate going into their Seek command; a hard disk's directory search starts from its table's directory cylinder; the drive tables always come from the second block of the system information sector; the date comes from the ROM's @DATE at 3033H; the half second index test adds 0FH ticks instead of 14H; and the operands name the Model III's resident vectors and cells.

Disassembly:

A disassembly of FORMAT/CMD can be found here.

BACKUP/CMD

Purpose:

BACKUP/CMD copies a diskette: BACKUP [-][partspec]:s :d (parameters). A load module of 5880 bytes, 27 load blocks with 5717 bytes in six parts between 5200H and 7021H, and the transfer address 5A00H. The front end at 5A00H reads the command line and the parameters, mounts both diskettes, checks the source's master password and chooses the way to copy; the engine selector at 6C00H then moves one of two engines over the front end to 5A00H: the mirror image engine, which copies cylinder by cylinder, or the file by file engine, which copies through the file system for a backup by class (a partspec or SYS, INV, MOD, QUERY, DATE, NEW or OLD) or for diskettes of different formats. The endings, the diskette prompts and the calls of the drive's driver lie below 5A00H, shared by both engines.

The code is the Model I file's at the same addresses; only the operands that name the resident vectors and cells (@LOGOT, HIGH$, @CKDRV, KFLAG$, LDRV$, @PARAM, SFLAG$, @MULT, TIMER$, DIRCYL, the dispatcher's loader and the 4300H sector buffer), the stack at 41E5H and the ROM's @DATE at 3033H differ, and the half second index test adds 0FH ticks instead of 14H.

Disassembly:

A disassembly of BACKUP/CMD can be found here.

LOG/CMD

Purpose:

LOG/CMD logs in the diskette of one drive: LOG :d. A load module of 194 bytes, one load block for 5200H-5286H and the transfer address 5200H. For drive 0 (also when no drive is given) it first shows Exchange disks and hit <ENTER> and waits for a key, so that another diskette, double sided or with another directory cylinder, can be put into drive 0; drives 1-7 must pass @CKDRV (4209H). It then reads the copy of the boot sector (cylinder 0, sector 0) and stores its byte 02H, the directory cylinder, at +09H of the drive code table, reads the allocation table from that cylinder and copies bit 5 of its configuration byte, two sides, into bit 5 of +04H of the table, and ends at @EXIT.

The Model I diskette of the release has no LOG/CMD; the page is written from the bytes of the Model III file.

Disassembly:

A disassembly of LOG/CMD can be found here.

HITAPE/CMD

Purpose:

HITAPE/CMD lets the ROM read 1500 baud cassettes under LDOS: HITAPE, or HITAPE (OFF). A load module of 456 bytes, two load blocks with 393 bytes in 5200H-5388H, and the transfer address 5200H. It copies a module of 28 bytes, named $HT, to the top of the free memory, lowers HIGH$ below it and points the RST 38H vector at 4012H at it; the module sends the cassette's rising and falling edge interrupts to the ROM's routines at 3365H and 3369H and every other interrupt on into SYS0/SYS's interrupt service. It installs only at LDOS command level, and a second run points the vector at the module again.

There is no Model I version (the Model I has no 1500 baud cassette); the page is written from the bytes. HITAPE (OFF), which the manual does not name, gives HIGH$ back when the module is the newest, but takes the vector to restore from the wrong word (the ROM's 0008H-0009H), so it leaves JP 00C3H at 4012H.

Disassembly:

A disassembly of HITAPE/CMD can be found here.

REPAIR/CMD

Purpose:

REPAIR/CMD makes a diskette written by another operating system readable under LDOS: REPAIR :d. A load module of 517 bytes, two load blocks with 454 bytes in 5200H-53C5H, and the transfer address 5200H; every sector goes through a buffer at 5400H. It clears bit 7 of the directory cylinder byte of the boot sector (byte 02H), rebuilds the GAT's excess cylinder byte (CCH, from the lock out table) and configuration byte (CDH, from the drive code table), puts the hash of DIR/SYS into the HIT, gives DIR/SYS a blank access password, and rewrites every directory sector with the deleted data mark of the LDOS directory. A drive with its own kind of driver (a hard disk) gets -Nothing done-.

There is no Model I page; the page is written from the bytes. Against the manual's list: the granules go into byte CDH, not CCH; no system information sector is written (the loop over cylinder 0 runs once, for the boot sector); bit 3 of CDH, the 5.3 directory date format, ends clear; the drive is not checked with @CKDRV.

Disassembly:

A disassembly of REPAIR/CMD can be found here.

CONV/CMD

Purpose:

CONV/CMD copies files from a TRSDOS 1.3 diskette onto an LDOS diskette: CONV [-][name][/ext]:s [:d] (VIS, INV, SYS, NEW, OLD, QUERY, DIR). A load module of 1491 bytes, six load blocks with 1412 bytes in 5200H-5783H, and the transfer address 5200H. It reads the TRSDOS diskette sector by sector through RDSECT, with the highest sector of the source drive's code table set to 18 (put back at the end): the boot sector for the directory track and the version, the 80 directory records, and each file by its extents. The files are chosen by class, by a name with $ for any character, and by NEW, OLD and the questions; each is opened as NAME/EXT.P3UF:d (P3UF has the same hash code as RS0LT0FF, the password of the LDOS system files), created by @INIT when new, given its full length by @POSN and @WRITE, and written by @WRITE from a buffer that reaches up to HIGH$ less 256.

There is no Model I page; the page is written from the bytes. Not in the manual: DIR (or no destination) lists the matching files in four columns, and a minus sign before the name takes the files that do not match. After the early errors the drive code table is restored from bytes that were never saved, and BREAK leaves the source drive with 18 sectors a track.

Disassembly:

A disassembly of CONV/CMD can be found here.

HELP/CMD

Purpose:

HELP/CMD displays the help texts of the /HLP files (DOS/HLP, BASIC/HLP): HELP [filespec [keyword]] [(P,V,B,S)], or HELP with an asterisk and a keyword for the global scan of every HELP file. A load module of 2399 bytes, nine load blocks with 2288 bytes in 5200H-5AEFH, three small blocks for cells beyond it (5B18H, 5C90H, 6093H-6098H), and the transfer address 5200H; HIGH$ must be at least 6497H. The file is read one byte at a time with @READ; its last two bytes point to the keyword index, which is in alphabetical order with bit 7 on the last letter of each keyword and the offset of its text after it. The texts are compressed (a byte of 80H or more is a character and a space, a second one a run of spaces) and end with 0CH; 7FH marks places that blink while HELP waits for a key. Without a keyword the index is listed in columns of 16; without a file @DODIR finds the /HLP files of drives 0-7. The screen is saved at 5C91H and put back at the end unless V is given.

There is no Model I page; the page is written from the bytes. The list of the files on line shows only the names, without /HLP and the drive; the manual's R parameter is passed over, as is any letter but P, V, B and S; ENTER alone at the category prompt ends with Source File Read Error, hidden by the restored screen.

Disassembly:

A disassembly of HELP/CMD can be found here.

CMDFILE/CMD

Purpose:

CMDFILE/CMD reads command files from disk and SYSTEM files from cassette into one memory image from 6000H, joins them, offsets the image to a new base address (with an optional driver of 19 bytes that disables the interrupts or not, moves the program back with LDIR or LDDR and jumps to it, and an optional record that loads 3024H into the keyboard device control block), changes the transfer address, and writes the image to disk as a command file (with @VER) or to tape as a SYSTEM file. It can take one ISAM member out of a library file such as SYS6/SYS. A load module of 2931 bytes, twelve load blocks with 2828 bytes in 5400H-5AA9H and 5AB7H-5F18H, and the transfer address 5400H. The same file runs on both models: it tests ROM 0125H and on the Model I writes the Model I addresses of HIGH$, @FEXT, @CKDRV, @DODIR, the ROM keyboard driver and the key wait into six operands.

There is no Model I page; the page is written from the bytes. ENTER at the restrict prompt offsets every block, those below 4200H too, although the manual says they are never offset; the end of the first block of a tape is not counted in the highest address; a drive after Q that is not ready gives error 20H; the blink call before each tape block does nothing in ROM 3.1.

Disassembly:

A disassembly of CMDFILE/CMD can be found here.

LCOMM/CMD

Purpose:

LCOMM/CMD is the terminal program: it talks to a device set to a serial driver (usually the CL device), with the functions given by CLEAR and the keys of the top row through KI/DVR (devices KI, DO, PR, CL, FS and FR, DTD, ON, OFF, ID, RES, REWND, PEOF, DUPLX, ECHO, ECOLF, ACCLF, DCC, CLS, 8-B, HNDSH, a DOS command through @CMNDR, EXIT, the menu). Six buffers are chains of 256 byte pages kept in a page table at 6900H and taken from 6C00H, over the start-up, up to HIGH$; task 8 reads and writes the line and task 9 the printer on every clock tick. A load module of 2646 bytes, thirteen load blocks with 2539 bytes in 6000H-674AH, 67EBH-6802H, 6804H-681DH and 6C00H-6E6DH, and the transfer address 6C00H.

There is no Model I page; the page is written from the bytes. The NULL parameter is stored one byte above the place the start-up reads, so received nulls are always kept, and NULL alone or NULL=ON makes LCOMM send FFH for a null; the FS buffer takes a page and is never used; RES of FR does not empty its buffer.

Disassembly:

A disassembly of LCOMM/CMD can be found here.

QFB/CMD

Purpose:

QFB/CMD is the quick format and backup: QFB :s :d (QUERY, ALL, V1, V2) makes a mirror image copy of a floppy disk in one pass, cylinder by cylinder: the destination is formatted with the Write Track command from one of six format tables (5 and 8 inch, single and double density, two with a closer interleave for FAST), the source cylinder is read into memory from 6700H, written, and with V1 read back and compared by the sum of its bytes; V2 reads the whole disk back at the end. Only the cylinders in use are copied unless ALL is given. While it copies, the RST 38H vector holds a RET and the clock stops. One file for the Model I and the Model III; a load module of 4121 bytes without a copyright record, seventeen load blocks with 4049 bytes in 5200H-5697H, 570CH-5CF0H and 5CF3H-6246H, and the transfer address 5200H.

There is no Model I page; the page is written from the bytes. The memory test masks the sectors of a track with 0FH, so that 18 sectors count as 2; an error of the second pass gives no message and the disk is still counted as made; a disk whose allocation table has bit 4 of byte CDH set is refused as having protected files.

Disassembly:

A disassembly of QFB/CMD can be found here.

FED/CMD

Purpose:

FED/CMD is the file editor (FED - File Editor Version 1.0.2, 1987 MISOSYS): FED (filespec) opens a file and shows one record of 256 bytes at a time in hex and as characters, all of it (the 256 byte mode) or a window of 128 bytes (the 128 byte mode, T). The semicolon, the minus sign, B, E and R move through the file and the arrow keys through the record; H and A change bytes in the edit buffer and S writes the record back with @VER (DIR/SYS with the deleted data mark, by setting SYS0's WRSECT to 0EH for the write); C and F find a string, G repeats the search, L locates a load address, Z goes to the next load block and M works out where the byte at the cursor loads; D, P and O print; ENTER alone shows the help screen. The screen is built in an image at 5562H and copied to video memory; every buffer is below the file, from 5200H. One file for the Model I and the Model III: only the address of the BREAK switch is chosen by the ROM. A load module of 6918 bytes: a copyright record, thirty load blocks with 6747 bytes in 59A8H-5BDBH, 5C0EH-6030H, 6063H-68F8H and 68FEH-746BH, and the transfer address 6063H.

There is no Model I page; the page is written from the bytes. While D prints, the box of the record number shows the record of the last scan of Z, L or M, not the record being printed; an asterisk, an error or M clears the last search, so that G then shows an asterisk; S of DIR/SYS takes only error 06H of @VER as the good end.

Disassembly:

A disassembly of FED/CMD can be found here.

TED/CMD

Purpose:

TED/CMD is the full screen text editor (TED 1.2 - (c) 1991 MISOSYS, Inc): TED [filename[/TXT]] edits a text of all free memory, from 5D00H to HIGH$, on 14 lines of 64 characters, with the status line at the bottom of the screen. Single keys move the cursor, switch between overstrike and insert entry, delete (with CTRL D and the arrow keys), mark, copy, move, delete and print a block (CTRL B and B, E, C, M, D, P), search and replace (CTRL S, CTRL G, CTRL R), page (CTRL N, CTRL U), show a directory (CTRL Q), print the text (CTRL P), and LOAD and FILE a file (CTRL L, CTRL F). TED needs KI/DVR (bit 4 of DFLAG$) and asks it for its special key codes (bit 6 of KFLAG$).

The Model III file has the same code at the same addresses as the Model I file except at 564AH-565CH, where the LD C,A that chooses the prompt is missing: CTRL F prompts Load Filespec? as CTRL L does (it still files the text). Also found: the reply limit of 23 characters is not used (the last byte of the prompt, A0H, is taken as the limit), and two parts of the file are never reached (5508H and the routine at 5831H).

Disassembly:

A disassembly of TED/CMD can be found here.