TRS-80 DOS - DoubleDOS (Percom DBLDOS)

Background

Percom Doubler Users Manual, 1980

Percom Doubler Users Manual (1980)

Percom Doubler Users Manual, Set 2, with the patch memos

The Manual With the 1980 Patch Memos

DoubleDOS is the double density disk operating system that Percom Data Company of Garland, Texas shipped with its Doubler, the first successful double density adapter for the TRS-80 Model I. Percom itself called it DBLDOS (a trademark of Percom Data Company); dealers' advertisements and the software archives call it DoubleDOS. It was written by James W. (Jim) Stutsman, who had earlier written Percom's MicroDOS / OS-80.

DBLDOS is not a new operating system but Radio Shack's Model I TRSDOS adapted to double density. Its boot screen says so itself:

DBLDOS - DISK OPERATING SYSTEM - VER 4.24
ORIGINAL DOS COPYRIGHTED BY TANDY CORPORATION
DOUBLE DENSITY ADAPTATION COPYRIGHT 1980
BY PERCOM DATA CO. INC.

Every system file carries a copyright record that reads MODIFIED FOR DOUBLE DENSITY OPERATION BY JAMES W STUTSMAN - COPYRIGHT (c) 1980, and the Disk BASIC on the diskette still announces itself as RADIO SHACK DISK BASIC VERSION 1.1, copyright Tandy Corporation 1979. Percom's manual says that all TRSDOS commands work under DBLDOS in exactly the same way with three exceptions: COPY was enhanced, DEVICE was removed, and FORMAT and BACKUP were replaced by a double density utility called DOUBLE. For everything else it sends the user to the Radio Shack TRSDOS and Disk BASIC Reference Manual (catalog 26-2104).

The TRSDOS it was made from is 2.1. Compared byte for byte with Radio Shack's Model I TRSDOS 2.1, 2.2 and 2.3, DBLDOS 4.24's SYS1/SYS to SYS6/SYS keep TRSDOS 2.1's code at the same addresses: SYS3/SYS has 2.1's layout (2.2 and 2.3 rearranged it), SYS6/SYS has 2.1's commands at 2.1's addresses, and BASIC/CMD is 2.1's Disk BASIC with a 233 byte block added at 4D00H. Of the changes Radio Shack made in 2.2, only one is in DBLDOS: the order of two tests in SYS4/SYS at 4E86H-4E91H. Users noticed: a reader's letter in the June 1981 80 Microcomputing complained that DBLDOS gives only TRSDOS 2.1's commands, without 2.3's BASICR and CMD"I", and asked how to put TRSDOS 2.3 into it; the editors suggested the double density DOSPLUS instead. Al Domuret's impression in The Alternate Source (below) that DBLDOS combines TRSDOS 2.3 and NEWDOS 2.1 is not borne out by the bytes.

The hard part was the double density data rate. In a 2008 interview with Matthew Reed (reproduced on this site), Stutsman explained that the Model I's polled disk I/O loop, as TRSDOS wrote it, was too slow to catch every byte of a double density sector, so bytes were lost. He found a different loop that was fast enough; Wayne Smith and Harold Mauch designed the hardware. He called the Doubler the TRS-80 work he was most proud of. Matthew Reed notes that other operating systems later copied Stutsman's double density routines, sometimes byte for byte. In DBLDOS 4.24 that loop is in SYS0/SYS at 4692H-469FH: the two instruction bytes at 4698H are rewritten before each transfer, so that one tight loop serves for reading, writing and the read-back check.

80 Microcomputing reviewed the Doubler in March 1981 (Stewart E. Fason, alongside the double density DOSPLUS). The reviewer called the hardware first class and DBLDOS adequate. He liked the jump from about 49K free on a TRSDOS diskette to more than 118K on a 40 track DBLDOS diskette, and the COPY that converts between the densities with only one drive. He disliked that DBLDOS could neither format nor back up a single density diskette, so that sharing a diskette with a single density user meant formatting it under another DOS and copying it file by file. A December 1982 comparison of the Doubler II and the LNW Doubler 5/8 in 80 Micro (Bruce Powel Douglass) described DBLDOS as TRSDOS patched for double density, with a few of its flaws corrected.

SoftSide's February 1981 issue carried a report from Hardside's service department, which had used the Doubler for about three months: of almost 200 sold, one had come back with a problem. It called DOUBLEDOS an enhanced TRSDOS that corrects some of the problems of the Tandy system, said that Galactic Maillist and Special Delivery ran under it without trouble, and compared it with Circle J Software's DOUBLEZAP 1.1 and 2.0 patches for NEWDOS/80. An April 1981 SoftSide article noted that TRSDOS, DOUBLEDOS and NEWDOS+ cannot mix 35, 40, 77 and 80 track drives.

Creative Computing's June 1982 issue carried Ronald H. Bobo's "Percom Doubler and DOSPLUS: A Winning Combination for Double Density on the TRS-80". He had paid $219.95 for the Doubler and its DOS, and wrote that for many months DBLDOS and Percom's OS-80 were the only double density DOSes for the Model I. He found DBLDOS a bare-bones system, apparently similar to TRSDOS 2.1 and NEWDOS+, good enough to get started, and noted two limits that the code bears out. It cannot read a single density directory: only COPY/CMD switches the controller to single density (a $ before a file name), and SYS0/SYS reads every directory in double density. And a format gives up when too many tracks are locked out: DOUBLE/CMD's flaw table has five places, and a flaw on a sixth track ends the format with TOO MANY FLAWS - USE ANOTHER DISK! (5881H). After the $30 upgrade to the Doubler II he could format many diskettes the first Doubler had rejected.

80-U.S. Journal's July 1982 issue compared the Doubler II and the LNW Doubler for a small business (John Strader, "Don't throw your Model I away - double it!"). He found that DOUBLEDOS offered little beyond reading both densities but worked very well, that Percom's installation manual was the better of the two, and that the DBLDOS diskette came with patches for Electric Pencil and Scripsit; Percom also sold patches for the older NEWDOS. He reported over 135,000 bytes free on a 40 track system diskette and 170,000 on a data diskette, and that Percom's own documentation admitted the first Doubler could become unreliable after a year or so, which the Doubler II's new design was meant to cure. Mail order advertisements in Creative Computing were blunter: in August 1981 one called the Percom DOS a crude TRSDOS patch, set against the LNDoubler's DOSPLUS, and from December 1981 one listed the Doubler II as coming with "DoubleDOS TRSDOS variant".

Readers kept DBLDOS in use well into 1982. A letter in 80-U.S. Journal (July/August 1981, Michael M. Finefrock) reported that a 44 track format on the newer Radio Shack drives worked under DBLDOS too, for 14 more granules. "Grab TRSDOS by the horns" (Michael D. Andreas and Charles P. Knight, 80-U.S. Journal, December 1982) keeps the DOS overlays in high memory so that a data diskette can stay in drive 0; its listing for TRSDOS 2.3 has added lines for NEWDOS 2.1 and for DBLDOS, whose version names itself MEMSYS FOR DOUBLEDOS 4.23 VER 1.0 and also keeps SYS7/SYS. Commercial programs named DBLDOS among the DOSes they supported, among them the Arranger disk catalog (whose 1983 review in Basic Computing catalogued DBLDOS diskettes without trouble), Super Utility Plus 3.0 and Pascal 80.

The Alternate Source, volume 2 number 2 (issue 8, 1981), carried "Doubler, DBLDOS, Double-Zap" by Al Domuret, reprinted in 80 Microcomputing in January 1982. He installed the Doubler with 1978 Shugart drives (Percom told him that Shugarts with a serial number above 80,000 or with a letter in it were rated for double density), found DBLDOS equal to TRSDOS for a contented TRSDOS user and working flawlessly, and preferred NEWDOS/80 with Circle J's DOUBLE-ZAP II only for its automatic density recognition (ADR/CMD). He noticed that DBLDOS formatted a diskette on the first pass almost every time while DOUBLE-ZAP II often failed on the inner tracks, because DBLDOS filled the sectors with E5H where DOUBLE-ZAP II wrote 6DH B6H, a worst case pattern for double density chosen to find marginal tracks. DOUBLE/CMD 1.21 of DBLDOS 4.24 has a routine that fills a sector with 6DH B6H (5C65H), which 4.20 and 4.23 lack. He also observed that DBLDOS, unlike DOUBLE-ZAP II, does not waste the first five sectors of the first double density track on a BOOT/SYS that is never used, that his DBLDOS came with password checking turned off (see the bugs below), and that NEWDOS 2.1's BASIC/CMD and SYS6/SYS could be copied onto a DBLDOS diskette and ran, at the user's own risk. His DBLDOS had a file FRMT/CMD besides DOUBLE/CMD, which none of the archived diskettes has.

Domuret's article ends with zaps for running DBLDOS on a Model I with a speed-up board, which make the waits after a command to the disk controller longer. Every byte they replace is the same in 4.20, 4.23 and 4.24:

FileZap (sector/byte)Where in memoryWhat it changes
Boot sector00/F0, 00/8F4290H, 42F0HThe PUSH BC / POP BC / PUSH BC wait at 4290H becomes a jump to 42F0H, over the end of the copyright text, where PUSH BC and four EX (SP),HL wait longer and jump back to 4293H. Made under a single density DOS, since the boot sector is the only track it can read.
SYS0/SYS01/83, 0C/6E, 03/A943D7H, 4B97H, 45F3HJP 44EFH at 43D7H becomes JP 4B97H; a new load record puts four EX (SP),HL and JP 44EFH into the nine unused bytes 4B97H-4B9FH; the wait PUSH HL / POP HL / PUSH HL / POP HL before the status is read at 45F3H becomes four EX (SP),HL.
DOUBLE/CMD05/D7, 07/4E579FH, 590AHThe PUSH AF / POP AF waits after a command to 37ECH become EX (SP),HL.

Percom Data Company

Harold Mauch, an electrical engineer who had worked for Collins Radio and Texas Instruments, took part in the BYTE magazine symposium of November 1975 that produced the Kansas City Standard for storing data on cassette tape. He co-wrote the final standard with Lee Felsenstein and published "Digital Data on Cassette Recorders" in the March 1976 issue of BYTE. That month he and his wife Lucy started PerCom Data in a portable building in their back yard in Garland, Texas, to sell the CIS-30 cassette interface. The company was incorporated in Texas on January 23, 1978, and by 1979 was at 211 North Kirby in Garland (Roger Arrick's Percom history, Matthew Reed).

Percom built cassette interfaces, mini-disk systems and boards for the SWTPC 6800 and other SS-50 machines (its 6800 disk systems had been in production since November 1977) and moved into the TRS-80 market in 1979: the TFD-100, TFD-200 and TFD-1000 drive systems, MicroDOS (announced May 30, 1979), the Percom Separator data separator for the Expansion Interface, the Speak 2 Me 2 interface for the Texas Instruments Speak & Spell and the Electric Crayon color graphics controller (Percom's 1979 news releases). Stutsman met Mauch at a 6800 user group in 1978; Mauch persuaded him to leave his job and write software for a living. Most of his work was done at home.

In October 1981 Percom moved from Garland to larger quarters in Dallas (11220 Pagemill Road). Harold Mauch died suddenly in August 1982, and the company turned toward business products, including disk drives for the Atari computers and later an early Ethernet card for the IBM PC. Esprit Systems bought Percom in 1984; the corporation was dissolved on October 31, 1985 and the Percom Data trademark was cancelled in 1990 (Wikipedia, Roger Arrick, Matthew Reed).

The Doubler and the Doubler II

Percom announced on June 25, 1980 that it had begun production of a double density disk controller adapter for the Model I, and the Doubler was advertised in 80 Microcomputing from September 1980 at an introductory price of $219.95, DBLDOS and a format conversion utility included. It needs no soldering or trace cutting: the Western Digital 1771 single density controller is taken out of its socket in the Expansion Interface, plugged into the Doubler, and the Doubler goes into the empty socket. The board also carries a data separator and write precompensation. Percom claimed up to 354K of formatted data on a five inch diskette, more than an eight inch single density diskette holds. 80-U.S. Journal (September/October 1980) and Creative Computing (November 1980) printed the announcement as news: the price covered the Doubler, DBLDOS and a utility to convert TRSDOS, OS-80 and other single density files to double density, and the board let a user keep running TRSDOS, NEWDOS and OS-80 single density programs unchanged.

DBLDOS chooses the density by writing a command code the 1771 does not have to the controller's command register 37ECH: FFH selects double density and FEH single density, each followed by a Force Interrupt, D0H (the boot sector does it at 4200H-4203H). Other DOSes that support the Doubler use the same codes, which became the Model I's common way of selecting double density.

On May 22, 1981 Percom announced the Doubler II, with a data separator based on a digital phase locked loop held in ROM, more tolerant of differences between diskettes and drives. It sold for $169.95, and owners of the first Doubler could buy a $30 upgrade kit (Matthew Reed). Mail order dealers sold the Doubler II with DoubleDOS for $153.50 to $159.95 through 1981 and 1982 (80 Microcomputing advertisements). Neither the Doubler nor LNW's LNDoubler was sold after 1984 (Matthew Reed).

Percom's own newsletter, The Percom Peripheral (TRS-80 Computing Edition, 1981, bound into 80-U.S. Journal volume 5 number 3), printed the Doubler II release of May 22, 1981 in full. Harold Mauch announced it as fully software compatible with the first Doubler and supplied with DBLDOS; its "ROM-programmed digital phase-lock loop data separator" needs no trimmer adjustment and does not drift as its parts age, and its write precompensation was refined; up to 364K fit on one side of a five inch diskette, and the board also let a Model I read Model III double density diskettes. The same issue offered the Percom SEPARATOR ($29.95), a plug-in board with a 16 MHz digital data separator for the single density 1771: Percom had traced the Model I's CRC errors and locked out inner tracks to the 1771's own separator, which works at 1 MHz, and found separators at 2 or 4 MHz little better. A dealer still called the Doubler II the favorite double density adapter of the past two years in February 1983 (80-U.S. Journal).

Percom also sold OS-80D, a double density version of OS-80 for the Doubler, and DOUBLEZAP patch programs that made NEWDOS/80 and VTOS 4.0 work with it. Doubler support was soon added to almost every Model I DOS; Model I TRSDOS never had it (Matthew Reed). DOUBLE-ZAP itself came from Circle J Software, whose Jesse Bob Overholt was one of its authors (The Alternate Source; SoftSide, February 1981).

Two drawings of the Doubler II are known: a hand traced schematic annotated in French, and the 2011 "Percom Doubler IIA replica" by Pascal Holdry. Both show the 1791 double density controller and, in a socket beside it, the Expansion Interface's 1771 for single density; a 74LS157 selector passes the step, direction, write data and write gate lines of the controller in use to the drives, so a seek is made by the controller of the density selected (the 1771 in single density, the 1791 in double density). The data separator is digital: a 16 MHz crystal, a 74LS161 counter and a 32 byte 82S123 PROM. Holdry's clean drawing of the original board (with its PROM and 74LS161; his "New PERC" version puts two GALs in their place) wires the clock pins (pin 24) of both controllers together to the CLK pin of the 1771's socket, the Expansion Interface's own 1 MHz clock; the 16 MHz crystal, divided to 4 or 8 MHz, runs only the data separator. So the 1791 runs at 1 MHz, like the 1771.

Versions

The archive has DBLDOS 4.20, three sets of 4.23 and 4.24. The disassembly on this site is of 4.24; the file by file comparison below comes from the disassembly (the disassembly page has the details). Percom's letters and patch memos, bound into the second scan of the manual, give the early history.

VersionDateWhat is known
2.1Summer 1980The first DBLDOS shipped with the Doubler. Percom's letter of September 8, 1980 (signed by Jim Stutsman) owned up to two bugs in it: COPY looped after FILE NOT FOUND, and a write that failed (a write protected diskette, for example) hung the system. The letter came with a listing of the PATCH program to type in. Not in the archive.
4.2 (4.20)September 1980Reconfigured for distribution on a standard 35 track diskette (the DBLDOS Manual Addendum), with PATCH/BAS and the STEPnn/PAT step rate patches on the diskette and the fixes of the September 8 letter built in. The system diskette's date is 09/13/80; the archived image is dated September 26, 1980. Percom's letter of October 10, 1980 told customers that they should have either 2.1 or 4.2, and offered to update a returned original diskette for $5.00.
4.23Late 19804.2 with the patch memos DPM-0001 to DPM-0003 of September 29, 1980 applied: DPM-0003 says that the three memos together raise the version to 4.23. SYS0/SYS's version digit and name record and COPY/CMD's fix for long files are the differences. Archive sets dated December 18, 1980, July 31, 1981, and an 80 track diskette.
4.24Unknown4.23 with a new DOUBLE/CMD, version 1.21 of the FORMAT/BACKUP utility: it adds a routine that fills a sector with the pattern 6DH B6H (5C65H-5C93H). SYS0/SYS's version digit 4 is the only other difference. The system diskette's GAT date is 09/01/80.

Boot Screens

DoubleDOS v4.20 boot screen, Model I

v4.20

DoubleDOS v4.23 boot screen, Model I

v4.23

DoubleDOS v4.24 boot screen, Model I

v4.24

The utilities have version numbers of their own, as Percom's October 1980 letter points out: DOUBLE/CMD was version 1.00 in 2.1, 1.20 after it was reassembled on September 13, 1980 (4.20 and 4.23), and 1.21 in 4.24.

Commands

The commands are TRSDOS 2.1's (see Background), and Percom's manual sends the user to Radio Shack's TRSDOS manual for all but COPY and DOUBLE; the short descriptions below are of the commands as DBLDOS 4.24's own files carry them out. The library commands are DEBUG (in SYS1/SYS) and APPEND, ATTRIB, AUTO, CLOCK, DATE, DIR, DUMP, FREE, KILL, LIB, LIST, LOAD, PRINT, PROT, RENAME, TIME and VERIFY (SYS1/SYS and SYS6/SYS). The library table still holds copy and double, in small letters that no command line can match, so that COPY and DOUBLE run the programs COPY/CMD and DOUBLE/CMD. There is no DEVICE, FORMAT or BACKUP.

COPY
COPY filespec1 TO filespec2, as in TRSDOS, but between the densities: a dollar sign in front of a file name marks a single density file (COPY $SUPERZAP:1 TO $SUPERZAP:0 from the manual's examples). With two drives, a single density file must not be on drive 0 and its drive must be named. COPY :d file1 TO file2 copies with one drive, asking for the source and destination diskettes in turn. The manual says that COPY is the only way to move a file between a single density and a double density diskette.
DOUBLE FORMAT
DOUBLE FORMAT :d formats a double density diskette (single density cylinder 0, double density on the others). It asks for the diskette's name, the date and the number of tracks (18 to 80, default 40), verifies every sector and records up to five flawed sectors in a table on the diskette; with more it says TOO MANY FLAWS - USE ANOTHER DISK!. It does not check whether the diskette is blank.
DOUBLE BACKUP
DOUBLE BACKUP :s TO :d, with one drive or two; Tnn makes the destination larger than the source (T40, T77), with the extra granules added to its GAT. A read error on a sector in the source's flaw table is shown and passed over; any other asks (C)ONTINUE, (R)ETRY, OR (A)BORT?.
BASIC
BASIC F, M, command: the number of files and the memory size are typed on the command line instead of answered at prompts, and a BASIC command after them runs when BASIC is ready (BASIC LOAD "PATCH/BAS"). Disk BASIC's errors are shown in words (Syntax error rather than ?SN ERROR) by the overlay SYS7/SYS.
APPEND
APPEND file1 TO file2 adds file1 to the end of file2, which must already exist. BREAK stops it; SHIFT @ pauses.
ATTRIB
ATTRIB file (I, ACC=password, UPD=password, PROT=level) sets a file's passwords, its protection level (FULL, KILL, RENAME, WRITE, READ, EXEC) and whether it is invisible (I). Only the first letter of each parameter is read. The protection is never enforced (see Bugs).
AUTO
AUTO command stores a command line (up to 32 characters) on the diskette in drive 0, run every time DBLDOS starts; AUTO alone clears it.
BASIC2
Leaves the DOS for the ROM's Level II BASIC, as if the computer had been turned on with BREAK held.
CLOCK
CLOCK shows the time in the top right corner of the screen, kept by the 25 ms interrupt; CLOCK (OFF) removes it.
DATE / TIME
DATE mm/dd/yy and TIME hh:mm:ss set the date and the clock, each number exactly two digits. The values are not checked against their ranges (see Bugs).
DEBUG
DEBUG turns on the machine language monitor of SYS5/SYS, entered before each program runs, by BREAK and when a program ends with an error; DEBUG (OFF) turns it off. Commands include G (go, with breakpoints), I and C (single step), A, H, S and X (display modes) and M (memory).
DIR
DIR :d (A, I, S) lists the files of drive d (0 when none is given), three to a line and 12 lines at a time. A adds each file's record length, records and granules, I shows invisible files, S system files; P marks a file with a password.
DUMP
DUMP file (START=X'aaaa', END=X'bbbb', TRA=X'cccc') saves memory from START to END as a /CMD style program (default extension /CIM) that runs at TRA, or returns to DOS READY. START must be 7000H or above.
FREE
Shows, for every drive 0-3 with a diskette, the diskette's name and date, its free granules and its free directory places.
KILL
KILL file deletes a file and frees its space.
LIB
Lists the library commands.
LIST / PRINT
LIST file shows a text file on the screen, PRINT file sends it to the printer. SHIFT @ pauses, BREAK stops. LIST's LINE parameter does not work (see Bugs).
LOAD
LOAD file loads a program into memory without running it, as for DEBUG.
PROT
PROT :d (PW, LOCK, UNLOCK) asks for the diskette's master password, then changes it (PW), gives every user file the master password (LOCK) or removes the passwords of every user file (UNLOCK).
RENAME
RENAME file1 TO file2 renames a file on its own drive; the new name may not name a drive, and must not already exist.
TRACE
TRACE shows the address being run in the top right corner of the screen; TRACE (OFF) stops it.
VERIFY
VERIFY makes every sector written be read back to check it; VERIFY (OFF) turns that off.

Using the DOS

Start-up
DBLDOS shows its banner and runs the AUTO command, if one is stored. Hold ENTER while it starts to skip the AUTO command and go straight to DOS READY.
DOS READY
Type a command of up to 63 characters and press ENTER. Do not use BREAK to cancel a line: DBLDOS runs what was typed as if ENTER had been pressed (bug B5); erase the line with SHIFT and the left arrow instead.
File names
NAME/EXT.PASSWORD:d: a name of 1-8 letters and digits starting with a letter, an extension of up to 3, a password of up to 8 and the drive 0-3, each part but the name optional (PAYROLL/DAT:1). Without a drive, drives 0-3 are searched in turn. Passwords are stored but never asked for (bug B13).
Programs
Type a program's name to run it; /CMD is added when no extension is given (SCRIPSIT runs SCRIPSIT/CMD). After a library command with a six letter parameter name, type the extension too (bug B8).
Single density
Only COPY reads and writes single density files; put $ just before the name (COPY $GAME/CMD:1 TO GAME/CMD:0). DIR, FREE and the other commands work on double density diskettes only.
Step rate
The system diskette steps the heads at the slowest rate; faster drives can be set with PATCH/BAS and a STEPnn/PAT file (see PATCH/BAS).

Disk BASIC

Starting
BASIC F, M, command keeps the files 0-F (default 3, highest 15) and memory up to M less 1, then runs the command, as in BASIC 5,32457,RUN"MENU". BASIC * returns to the program that was in memory before (after CMD"S" or a crash), with its files and memory size.
CMD"x"
CMD"S" back to DOS READY; CMD"A" back as after an error; CMD"D" enters DEBUG; CMD"E" shows the message of the last DOS error in words; CMD"T" turns off the clock and disk interrupts (for cassette work) and CMD"R" back on. Only one letter is accepted; CMD"X" is refused.
Programs on disk
LOAD "name" loads a program; LOAD "name",R loads and runs it and keeps the files open; RUN "name" loads and runs it with the files closed. SAVE "name" saves it in its compact form, read back to check it; SAVE "name",A saves it as text, which MERGE "name" needs. KILL "name" deletes a file; NAME is not available.
Files
OPEN "m", f, "name" opens file f for output (O), input (I), random records (R) or, in DBLDOS only, output added to the end of an existing file (E). File names may have 23 characters; file 0 is BASIC's own and cannot be opened.
Sequential files
PRINT #f,, INPUT #f, and LINE INPUT #f, write and read text; EOF(f) gives -1 at the end. INPUT #-1 and PRINT #-1 still use the cassette.
Random files
FIELD f, w AS v$, ... divides the 256 byte record (all 256 bytes may be used); LSET and RSET fill the fields, GET f, r and PUT f, r read and write record r (from 1; the next one when r is left out), and MKI$, MKS$ / MKD$, CVI and CVS/CVD convert numbers. LOC(f) is the current record, LOF(f) the last.
More
TIME$ gives the date and time as MM/DD/YY HH:MM:SS; INSTR finds a string in a string; MID$(a$,n,m)= replaces characters in a string; &H and &O are hexadecimal and octal constants; DEFUSRn and USRn set and call up to ten machine language routines. Errors are shown in words (Syntax error, Disk full).

The Doubler's advertisements also name a CONVERT utility on the DBLDOS diskette for converting files between the densities; no file of that name is on any of the archived diskettes, where COPY/CMD does the job.

Diskette Format

A DBLDOS diskette keeps cylinder 0 in single density (ten sectors of 256 bytes; only sector 0, the boot sector, is used), so that the Model I ROM can boot it; every other cylinder is double density with 18 sectors. DBLDOS numbers the sectors from cylinder 1, sector 0 onward and groups them into logical "tracks" of ten sectors, the units of the GAT and of the directory (granules of five sectors). The directory is logical track 17, cylinder 10, sectors 8-17, written with the deleted data mark F8H. Because a logical track does not match a cylinder, other DOSes and utilities treat DBLDOS diskettes as a format of their own: Super Utility Plus needs its R (relative sectoring) modifier for them, and LNW's FORMAT has a separate P (DBLDOS) density. How to recognize a DBLDOS diskette is described on the DOS identification page.

PATCH/BAS and the Patch Files

Percom distributed every fix to DBLDOS as BASIC DATA lines for one program, PATCH/BAS, which is on the system diskette. The step rate patch files STEP06/PAT, STEP12/PAT, STEP20/PAT and STEP30/PAT are such DATA lines saved as ASCII files, ready to be merged into it.

PATCH/BAS

PATCH/BAS, the PERCOM DBLDOS PATCH UTILITY (copyright 1980 Percom Data Company), is a 16 line BASIC program, lines 100-300. It changes bytes of a disk file at places given as a record and an offset, and it reads all of its changes from DATA statements from line 1000 on, in this form:

1000 DATA "filespec",n           the file to change, n patch lines follow
1010 DATA rec,off,len,b1,...,bn,ck one patch line: len bytes from offset off of record rec
...
nnnn DATA "*END*"                after the last file

The program works in two phases:

  1. Phase 1 - patch validation (lines 110-200). For each patch line it adds up the record number, the offset, the length and every data byte (taking 32768 off the sum whenever it passes 32767) and compares the sum with the line's last number, the checksum. A difference is reported as CHECKSUM ERROR IN PATCH TO filespec @ LINE n, where n counts the patch lines after the file's first DATA statement. If any line is wrong it ends with n ERRORS FOUND - CORRECT AND RERUN, before anything is written.
  2. Phase 2 - patch application (lines 210-300). RESTORE starts the DATA again. Each file is opened as a random file with records of 256 bytes (OPEN "R",1,filespec and FIELD #1,1 AS BF$); VARPTR of BF$ gives the address of the file's buffer. For each patch line the record is read with GET, the bytes are POKEd into the buffer at the offset, and the record is written back with PUT. CLOSE ends each file, and END OF PATCH APPLICATION the run.

So a patch line names a place in the file as it is on the diskette, not an address in memory: record r, offset o is byte (r - 1) x 256 + o of the file, counting its load module records too. Phase 2 does not test whether the file exists: OPEN "R" makes a new, empty file when a file name is mistyped, and the GET that follows fails. Percom's memos warned not to interrupt phase 2, since a partly patched program would not work.

Every memo gives the same procedure: boot DBLDOS, start BASIC, LOAD "PATCH/BAS", type the patch lines after AUTO 1000, take the write protect tab off the diskette to be patched and type RUN. The file names in Percom's memos carry a drive number (SYS0/SYS:0).

The PATCH/BAS of DBLDOS 4.20 still ends with three DATA lines, the COPY/CMD fix of the September 8, 1980 letter, with the drive changed to :1 and the checksum 146 instead of 143: run as it is, it stops in phase 1 with a checksum error. The STEPnn/PAT lines, which have the same line numbers, replace those lines when they are merged. 4.23 and 4.24 have PATCH/BAS without them.

The Step Rate Patches: STEP06/PAT, STEP12/PAT, STEP20/PAT, STEP30/PAT

Each file has four lines, all for SYS0/SYS on drive 0:

1000 DATA "SYS0/SYS:0",2
1010 DATA 3,15,1,r,ck
1020 DATA 5,15,1,s,ck
1030 DATA "*END*"
FileBytesStep time (Percom) and the drives it names
STEP06/PAT08H, 18H6 ms. The manual: Percom TFD-40, MPI and Tandon drives (the addendum: MPI drives only, which includes the TFD-100 drives that are not "flippy").
STEP12/PAT09H, 19H12 ms. Not normally used.
STEP20/PAT0AH, 1AH20 ms. Percom TFD-100, Siemens (Wangco, Perkin-Elmer) and Pertec drives.
STEP30/PAT0BH, 1BH30 ms, "standard". Percom TFD-200, Shugart and Micropolis drives. These are the bytes on the system diskette as shipped.

Record 3, offset 15 of SYS0/SYS is byte 020FH of the file, which loads at 444CH: the operand of LD A,0BH, the Restore command used to bring a drive's head to cylinder 0. Record 5, offset 15 is byte 040FH, which loads at 4657H: the operand of LD A,1BH, the Seek command. Only the two low bits of each command change; they are the controller's stepping rate field, 0 to 3. The boot sector, which is not patched, always seeks with rate 3.

The procedure in the manual (section 3.4.1) and the addendum: boot DBLDOS from a copy of the system diskette in drive 0 with its write protect tab off (never the original), type BASIC LOAD "PATCH/BAS", then MERGE "STEPnn/PAT" and RUN, put the tab back on and press RESET: the new rate works only after the next boot. The procedure can be repeated to change the rate again. The manual says in the same section that the system diskette steps at 40 ms, while it lists STEP30/PAT, the bytes the diskette carries, as 30 ms; both figures are right, each for one controller. The Expansion Interface clocks its 1771 at 1 MHz (Radio Shack's Expansion Interface Service Manual, 26-1140), and the 1771's table of stepping rates in the same manual gives 12, 12, 20 and 40 ms at 1 MHz, so rate 3 is 40 ms when the 1771 makes the seek, in single density. The 179x table (in Tandy's Model 4 and 4P Technical Reference Manual) gives 6, 12, 20 and 30 ms at 1 MHz, the very figures of STEP06, STEP12, STEP20 and STEP30, so the file names and the manual's "30 ms (standard)" are the 1791's rates in double density: the Doubler gives its 1791 the Expansion Interface's 1 MHz clock (see The Doubler).

Percom's Patch Memos of 1980

The second scan of the manual (Set 2) has the letters and memos that Percom sent to DBLDOS owners in the autumn of 1980. In each, the record and offset can be turned into a file byte, and from there into the address on the disassembly pages.

MemoFileWhat it fixed, and where the bytes are in 4.24
September 8, 1980 letterCOPY/CMD, SYS0/SYSFor DBLDOS 2.1, with the listing of PATCH. Its COPY/CMD line (record 3, offset 75, 40H) is byte 542FH of COPY/CMD, the operand of OR 40H in COPY's error exit at 542EH: with bit 7 of the error code clear, SYS4/SYS ends the command after the message instead of returning to COPY, which then looped (the byte 2.1 had there is not known). Its SYS0/SYS lines write twelve bytes at record 13, offset 98 and a 2 at record 12, offset 227. In 4.20 to 4.24 those file bytes are 44F4H-44FFH, the end of the small block 44EFH-44FFH that SYS0/SYS loads last: before the first byte of a write, SYS0/SYS now waits until the controller either asks for the byte or has ended the command, the fix for the hang. The 2 lands on a digit of the version at 4F14H. All of these bytes are already in 4.20.
DPM-0001, September 29, 1980DOUBLE/CMDDOUBLE BACKUP version 1.00 copied only 35 tracks of a diskette it had extended to 40 or more. For version 1.00 only: Percom warned that applied to 1.20, which does not need it, the patch would make the DOUBLE commands unusable. It raised DOUBLE to 1.02.
DPM-0002, September 29, 1980COPY/CMDCOPY did not copy every sector of a file larger than its memory buffer (162 sectors on a 48K machine), which broke the Microsoft BASIC compiler. Six lines change the operands at 5243H, 52B0H and 5315H from 5CD8H to 5D00H, replace a JR NZ / RET at 52DCH with JP 5CD8H, and add a ten byte routine at 5CD8H-5CE1H in a new load record. The COPY/CMD of 4.23 and 4.24 has it; that of 4.20 does not.
DPM-0003, September 29, 1980SYS0/SYSPrograms that read the directory themselves, such as the MISOSYS EDTASM, failed: the five bytes at record 1, offset 2, the start of SYS0/SYS's name record, become 11H and SYS0. SYS0/SYS begins at logical sector 0 (cylinder 1, sector 0), so byte 2 of that sector now gives directory track 17 (11H), as such programs expect; 4.20 gave them 53H, the S of the name. The second line sets the version digit at 4F15H to 3: with DPM-0001 to DPM-0003 applied, DBLDOS is 4.23.
Optional patches, September 29, 1980 (also appendix A1 of the manual)Other programsPatches for the Electric Pencil, SCRIPSIT/LC and SCRIPSIT/UC, the MISOSYS DISK*MOD EDTASM, Microsoft's EDIT and (in the manual) Radio Shack's PROFILE 1.0. The memo also lists programs that do not run under DBLDOS at all: Z80ZAP/CMD, the machine language SUPERZAP of NEWDOS/80 (version 3.0, written in BASIC, works) and RSM2D except its disk commands; in general any program that does its own disk I/O.

The memos also note a problem in the Microsoft BASIC compiler: BASCOM/CMD and L80/CMD set the BREAK vector to themselves and leave it there, so BREAK should not be pressed after returning to DBLDOS until DEBUG (OFF) has been typed. The disassembly confirms that DEBUG (OFF) clears the BREAK flag at 4315H (SYS1/SYS 5187H).

Manuals

DBLDOS has no manual of its own beyond the chapter in the Doubler's manual: Percom refers the user to the Radio Shack TRSDOS and Disk BASIC Reference Manual (26-2104) for everything that works as in TRSDOS. Each title below is a download link.

Percom Data Company, 1980, 36 pages, 22,971,446 bytes. Document 050-1060-001-B: the Doubler, its installation and check-out, the DBLDOS commands (COPY between the densities with one or two drives, no DEVICE), DOUBLE FORMAT and DOUBLE BACKUP, DBLDOS BASIC, changing the drive step time with PATCH/BAS and the STEPnn/PAT files, and appendix A1 with the optional patches for other programs.
Percom Data Company, 1980, 46 pages, 43,961,201 bytes. Another copy of the manual, bound with the papers that came with it in the autumn of 1980: Harold Mauch's letter of October 10, 1980, the patch memos DPM-0001, DPM-0002 and DPM-0003 and the optional patches of September 29, 1980, Jim Stutsman's letter of September 8, 1980 with the listing of PATCH, and the DBLDOS Manual Addendum for version 4.2 (the 35 track system diskette, DOUBLE BACKUP Tnn, the step rate patches and the flaw table of DOUBLE FORMAT).

Disassembly

The DoubleDOS 4.24 disassembly covers the boot sector, SYS0/SYS to SYS7/SYS, BASIC/CMD, COPY/CMD and DOUBLE/CMD, every byte on a row with its explanation, and names the differences of 4.20 and 4.23 on each page. DIR/SYS (the directory) and PATCH/BAS are not paged; PATCH/BAS is described above.

DoubleDOS 4.24 Bugs Found in the Disassembly

These are the bugs found so far while disassembling the files of the DBLDOS 4.24 master diskette, 43 in all. Each comes from the bytes themselves, and the address links to the row of the disassembly where it happens; the page of each file explains it in full. All twelve files of the diskette have been disassembled, so the list is complete as far as reading the code goes. Under each one, How it happens says what a user would do to set it off and what he would see. They have not been tried on an emulator. This page is the one list of DoubleDOS's bugs; each disassembly page names its own in its introduction.

Bugs Found in the Code

Each of these 31 gives a wrong result, a hang or lost data in a case that can happen.

FileWhereBug
SYS0/SYS
B2
45E3H-45EDHThe store of 00H at 430EH (forget SYS7/SYS, resident at 4D00H) never runs: when a growing file makes SYS0/SYS read the GAT into 4D00H (4A07H) after a BASIC error, the next BASIC error calls 4D00H, which holds the GAT (SYS7/SYS page).
How it happens: In Disk BASIC, make any error (a typing slip that gives Syntax error is enough) so that SYS7/SYS is loaded at 4D00H to show it; later, let a program write to a disk file until the file needs a new granule, which reads the GAT into 4D00H; the next BASIC error then jumps into the GAT bytes and the computer hangs or runs wild.
In the code: Compares Register B (the tries left, 0AH or 05H at most) with 4DH; Register H, the buffer page here (pushed at 468EH), is the byte that is 4DH for a transfer at 4Dxx.
SYS0/SYS
B3
4B35HAn endless loop when that block also lacks the F8H mark.
How it happens: Put a double density diskette whose directory sectors were written with the ordinary data mark (one formatted by another DOS, or one whose directory was repaired with a zap utility) in a drive and type DIR :n or open a file on it: the command never comes back and only RESET ends it.
In the code: A directory sector read with the ordinary data mark makes it re-read byte 2 of logical sector 0 and try again, with no count.
SYS1/SYS
B5
4E4BHBREAK at DOS READY is handled as ENTER: the buffer as ROM 0040H leaves it is run.
How it happens: At DOS READY, type a command, change your mind and press BREAK to cancel the line: DBLDOS runs what was typed as if ENTER had been pressed.
In the code: CALL 0040H: the C FLAG that ROM 0040H returns for BREAK is not tested.
SYS1/SYS
B7
4FC0HA caller that uses HL afterwards points into the moved text.
How it happens: Only a machine language program that calls the add-a-default-extension routine (request code D3H) itself and then goes on using Register Pair HL; typing commands at DOS READY does not show it.
In the code: When it inserts the default extension, Register Pair HL is not restored.
SYS1/SYS
B8
5095HA program command run after it (SYS1 not reloaded) gets the extension 03H M D; PROT (UNLOCK) does it (SYS6/SYS 54FBH).
How it happens: Type a library command that has a six character parameter name, such as PROT :0 (UNLOCK), then at the next DOS READY run a program by name without its extension, such as BASIC: the name is looked up with a broken extension and the program is not found. Typing the extension (BASIC/CMD) avoids it.
In the code: A parameter name of six characters puts its 03H at 51B5H, the C of the default extension CMD.
SYS1/SYS
B9
50FAHRuns past 0DH through memory when the list is not closed.
How it happens: Leave out the closing parenthesis after a Y, N, ON or OFF value, as in DEBUG (ON: the scan runs on through memory past the end of the line, and the command takes whatever it meets there, from a wrong value to a hang.
In the code: After Y, N, ON or OFF the scan for ',' or ')' has no other end.
SYS1/SYS
B10
5104HValues above 65535 wrap.
How it happens: Type a decimal number above 65535 for a parameter, as START=70000 for DUMP: it is taken as the number less 65536 (70000 becomes 4464) with no error.
In the code: Decimal parameter values have no overflow test.
SYS1/SYS
B11
5130H:;<=>?@ are accepted as hex digits.
How it happens: Mistype a hexadecimal value with one of : ; < = > ? @, as X'5:00': no error is given and the character counts as a digit 3 to 9 (X'5:00' is taken as X'5300').
In the code: X'hex' takes 3AH-40H as the digits 3-9.
SYS1/SYS
B12
513CHA bad X'..' value is taken as good.
How it happens: Mistype a hexadecimal value with a character that is not a digit and leave off the closing quote, as X'52G0: the value is taken as good instead of refused.
In the code: A non-hex character without the closing quote still returns Z.
SYS2/SYS
B13
4EACHPasswords and protection levels are never tested; every file opens with access 00H.
How it happens: Give a file a password or a protection level with PROT or ATTRIB: it can still be opened, listed, changed and killed with no password asked, and a program written to be refused access never is.
In the code: JR 4ECFH passes over the password and protection tests 4EAEH-4ECEH.
SYS2/SYS
B14
4F0DHOpen-or-make (A4H) with no drive named and no room returns error 1AH with Z set: a caller testing Z sees success.
How it happens: Only a program that makes a new file without naming a drive when no diskette in drives 0-3 has room for it: the open reports success though no file was made, and the program then writes to a file that is not open.
In the code: LD A,1AH with no OR A: the Z FLAG of CP 04H at 4F07H stays.
SYS3/SYS
B15
4E10HA write error at close is lost.
How it happens: Close a file when the last changed sector cannot be written (the diskette write protected or taken out, or a bad sector): CLOSE reports no error, and the file is left without its last records.
In the code: The result of writing a changed buffer (4878H) is not tested.
SYS3/SYS
B16
4F23HWith an extra entry in another sector the FCB gets the name of another entry.
How it happens: Only a program that closes a file and then opens it again with the same file control block (TRSDOS puts the name back in it for that): when the file has an extra directory entry in another directory sector, as a file of many extents on a crowded diskette does, it gets another file's name and opens the wrong file.
In the code: The sector read for the name put back in the FCB is that of Register B (the last entry read), not of FCB+07H.
SYS0/SYS
B17
46C8H-46CDHA write to a drive that is not ready gives 10H, ILLEGAL LOGICAL FILE NUMBER (a read gives 08H, DEVICE NOT AVAILABLE).
How it happens: Write to a drive that has no diskette or an open door: the error shown is ILLEGAL LOGICAL FILE NUMBER, which says nothing of the drive, instead of a not ready error.
In the code: The error code is the base (09H for a write) minus one plus the number of the lowest status bit; NOT READY is bit 7.
SYS5/SYS
B23
4E23HEntered by BREAK after a byte F7H, the PC shown and used by G is one too low; after the program's own RST 30H, G runs it again and comes straight back.
How it happens: In DEBUG, stop a program with BREAK (or at a breakpoint) right after an instruction whose last byte is F7H: the PC shown is one too low, and G starts one byte early, in the middle of the instruction. A program that uses RST 30H itself goes straight back to DEBUG every time G is typed.
In the code: The saved PC is moved back by one whenever the byte before it is F7H.
SYS5/SYS
B24
4E2FHEvery entry resets the display to X in hexadecimal and M to 0000H; with fewer than two breakpoints placed, an F7H at the address formed by the left bytes is overwritten.
How it happens: In DEBUG, choose the A display or the S screen, or set M, then type G or step with I or C: the display goes back to X in hexadecimal and M to 0000H each time. With G and fewer than two breakpoints, a byte F7H at an address made from those settings can be replaced by another byte.
In the code: The breakpoint entries share 405DH-405EH (A/H and S/X) and 4060H-4061H (the address of M); each entry clears them and reads all of them as breakpoint addresses.
SYS5/SYS
B25
50CFHA single step of JP (IX) puts breakpoint 2 at the address in IY.
How it happens: In DEBUG, single step (I or C) a JP (IX) instruction while Index Registers IX and IY hold different addresses: the step does not stop at the jump's target and the program runs on (and BREAK does not stop it, B26).
In the code: BIT 5,C tests the opcode E9H (bit 5 always set), not the prefix DDH/FDH.
SYS5/SYS
B26
505DHWhen a stepped instruction reaches neither breakpoint, the program runs on and BREAK does not stop it.
How it happens: In DEBUG, single step (I or C) an instruction that goes to neither place a breakpoint was put, as a JP (IY) or a RET to an address changed on the stack: the program runs on, and BREAK no longer brings DEBUG back; only RESET does.
In the code: I and C do not set the BREAK flag 4315H (only G does, 4FA1H); the dispatcher cleared it and is never returned to.
SYS6/SYS
B27
52B1HA time part above 59/59/23 runs on to 255 and round through 0 in the clock task; a month of 13 or a day of 40 is stored.
How it happens: Type a date or time with a number out of range, as DATE 13/40/80 or TIME 25:61:00: it is taken, the clock shows impossible values and runs on from them.
In the code: DATE and TIME check only that each of the three numbers has two digits.
SYS6/SYS
B28
5469HThe first eight bytes of APPEND (5700H) become 20H; with SYS6/SYS still marked in memory (430FH bit 4), a following APPEND runs the spaces.
How it happens: Give a password of exactly eight characters to PROT or ATTRIB (PW=PASSWORD): the command works, but 256 spaces are written over SYS6/SYS in memory; an APPEND typed next, while SYS6/SYS is still there, runs spaces instead of APPEND and can crash.
In the code: With eight characters typed, Register B is 00H for the fill and DJNZ writes 256 spaces at 5608H-5707H.
SYS6/SYS
B29
5942HLINE is never found: LIST always starts at line 1; a name matching the specification's text would store its value at an address made of those characters.
How it happens: Type LIST filespec (LINE=n): the LINE parameter is ignored and the listing starts at the first line.
In the code: LIST loads its parameter table 598BH into Register Pair BC; the parser 4476H takes the table from Register Pair DE (5551H, the file specification).
SYS6/SYS
B31
583AHA full diskette loses the rest of the dump with no error; the file is closed as if complete.
How it happens: DUMP a block of memory to a diskette that fills up during the dump: there is no disk full message, the file is closed as if complete, and loading it later runs a program with its end missing.
In the code: DUMP tests none of its outputs through 001BH.
SYS6/SYS
B32
58BEHA new file is left in the directory empty.
How it happens: Type DUMP with an END address lower than START (or with START or END left out): the message comes, but a new empty file of that name is left in the directory.
In the code: The END and START checks come after the file is opened or made and its name record started; 58BEH exits without closing it.
SYS6/SYS
B33
5DF1HEOF= is 256 bytes' worth of records too many when the end of file byte is not 00H.
How it happens: Type DIR (A) for a file whose last sector is only partly used: the EOF= figure is too high by a sector's worth of records.
In the code: DIR (A) takes the bytes as entry +14H-+15H (sectors, including the partly used last one) x 256 + the end of file byte.
SYS6/SYS
B34
60BBHFor record lengths 129-255 the quotient (DIR (A) EOF=) is wrong.
How it happens: Type DIR (A) for a file with a record length of 129 to 255: the EOF= figure is wrong.
In the code: The division shifts the remainder with RLA and drops the bit carried out of Register A.
SYS6/SYS
B35
5398HA value with low byte 00H (LOCK=256) gives -NOTHING DONE-.
How it happens: Give one of PROT's flags a value whose low byte is 00H, as LOCK=256: PROT says -NOTHING DONE-. The usual PROT :d (LOCK) is not affected.
In the code: PROT tests only the low bytes of the words of PW, LOCK and UNLOCK for "nothing given".
SYS6/SYS
B36
538AH4B55H reads the directory block from a byte past 4304H-4307H for drives above 3.
How it happens: Type a drive number above 3, or a letter, after the colon of PROT or DIR (DIR :4): no error is given; the directory is looked for at a cylinder taken from an unrelated byte of memory, and the command shows garbage or fails.
In the code: PROT and DIR (5C88H) take any character after the colon as the drive, with no test for 0-3.
DOUBLE/CMD
B37
5585HThe rest of the pass is written one sector early on the destination and its last sector gets stale buffer bytes; the manual says only the bad sector may differ.
How it happens: DOUBLE BACKUP a source diskette with a sector that cannot be read and answer C to (C)ONTINUE, (R)ETRY, OR (A)BORT? (or a source sector in its flaw table): every sector after it in that pass is written one sector early on the copy, so the copy is wrong from the bad sector to the end of the pass, not only at it.
In the code: After a source sector that cannot be read, Register Pair BC still points at its place in the buffer (57E4H moves it on only after a good read) when the pass goes on, for (C)ONTINUE or a sector in the flaw table.
DOUBLE/CMD
B38
58BAHA flaw in sectors 5-9 of cylinder 0 sets bit 1 of GAT byte CBH (21H becomes 23H) and takes a place of the flaw table.
How it happens: DOUBLE FORMAT a diskette with a flaw in sectors 5 to 9 of cylinder 0 (the single density track): the flaw takes a place in the flaw table and sets bit 1 of GAT byte CBH (21H becomes 23H), the byte by which DBLDOS diskettes are told from others.
In the code: The verify after FORMAT turns a flawed sector of cylinder 0 into a logical track with 592DH, which counts from cylinder 1: cylinder 0 gives logical track CBH.
BASIC/CMD
B40
552FHThe room is one byte less than the 56H margin below the string space gives: a program of exactly that size is refused with Out of memory.
How it happens: LOAD a program saved without A whose size leaves exactly 86 bytes (56H) between its end and the string space: LOAD says Out of memory although that is the room it allows; one byte less and it loads.
In the code: LOAD's room test SBC HL,DE takes the C FLAG left set by ADD HL,DE at 5FD4H (DE = FFAAH).
COPY/CMD
B43
5304HIf the destination needs another directory entry in that last write pass (SYS0/SYS 4A6BH, request code B4H), SYS2/SYS is read from drive 0: in a copy with one drive on drive 0 that is the destination diskette (a data diskette gives error 58H, a missing overlay), and with a single density destination SYS0/SYS is still set for single density.
How it happens: COPY :0 a file longer than the buffer (more than 162 sectors with 48K) to a data diskette whose free space is in many small pieces, so that the copy needs a second directory entry during its last pass: COPY stops with an error for a missing overlay, leaving a destination file that is not closed. With two drives the same happens when the destination is in single density.
In the code: A destination open from an earlier pass is written without COPY's copy of SYS2/SYS being put back (JR C,5314H passes over 5306H); after the read pass that reached the source's end SYS3/SYS is at 4E00H (52DFH).

Latent Bugs and Code With No Effect

These 12 do no harm in the files as shipped: wrong code that nothing reaches (latent), or an instruction or test that changes nothing.

FileWhereBug
Boot sector
B1
4260HThe next cylinder would be read from sector 18; SYS0/SYS is 13 sectors on cylinder 1, so it is never reached.
How it happens: Nothing a user does: it would need a SYS0/SYS longer than the 18 sectors of cylinder 1; the shipped one is 13 sectors.
In the code: After sector 17 (E = 12H) LD E,A keeps E at 12H instead of 00H before INC D. (Latent)
SYS1/SYS
B4
4E23HNone.
How it happens: Nothing a user does shows it.
In the code: BIT 5,(4359H); its Z FLAG is overwritten by BIT 7,(430FH) at 4E2BH. (No effect)
SYS1/SYS
B6
4EA2HA stack word is lost each library command; harmless, DOS READY resets SP to 41FCH.
How it happens: Nothing a user does shows it.
In the code: PUSH AF before the RST 28H that loads SYS6/SYS is never popped. (No effect)
SYS4/SYS
B18
4E0EHBit 6 of the error code has no effect; the ERRCOD=nn display 4E14H-4E29H never runs.
How it happens: Nothing a user does: the ERRCOD=nn form of an error message is never shown.
In the code: BIT 6,B, then JR 4E2AH, which does not test it. (No effect)
SYS4/SYS
B19
4E5EHNothing calls 4E73H: the device or file and REFERENCED AT X'nnnn' are never shown.
How it happens: Every error message: the name of the device or file and the REFERENCED AT X'nnnn' line are never shown with it, only the message itself.
In the code: BIT 6,A, then three NOP at 4E60H-4E62H. (No effect)
SYS4/SYS
B20
4EB5HThe copy of a specification would count 256 characters, not 24 (in 4E73H, never run).
How it happens: Nothing a user does: the code is never run (B19).
In the code: LD BC,0018H loads Register B with 00H for the DJNZ at 4EC0H. (Latent)
SYS4/SYS
B21
4EB8H-4EFCHWould write past 4F6FH over REFERENCED AT and show the password (never run).
How it happens: Nothing a user does: the code is never run (B19).
In the code: The specification text (up to 23 characters with a password) and its > and 0DH go to 4F60H, a 16 byte place. (Latent)
SYS4/SYS
B22
4EDAHWould show NAME/:D for a file with no extension (never run).
How it happens: Nothing a user does: the code is never run (B19).
In the code: The / is stored before the extension even when the extension is blank. (Latent)
SYS6/SYS
B30
595AHWould loop for ever on a short file and pass over the wrong count (never run, B29).
How it happens: Nothing a user does: LINE is never found (B29).
In the code: The LINE skip loop does not test the end of file, and DEC C / DEC B counts C + 256 x (B - 1) lines. (Latent)
DOUBLE/CMD
B39
5663HNever taken: 583FH jumps to 56A8H itself on an error and returns only with the Z FLAG.
How it happens: Nothing a user does shows it.
In the code: JP NZ / JR NZ to 56A8H after 56FBH (5663H, 567CH) and after 583FH (576AH). (No effect)
BASIC/CMD
B41
555DHJR C at 5571H is always taken (5573H never runs) and JP NC,2423H at 55C2H is never taken; nothing a program does changes.
How it happens: Nothing a user does shows it.
In the code: SCF right after OR A (TRSDOS 2.1's code in FN) sets the C FLAG on every path. (No effect)
BASIC/CMD
B42
5CE5H294 bytes (to 5E7EH) are copied to 5BADH-5CD2H, past the 240 byte input buffer, over start-up code that has run; the line is empty.
How it happens: Nothing a user does shows it: typing BASIC * gives the empty first command as intended.
In the code: BASIC * gives 5D59H (a byte 00H with no 0DH after it) as the first command; 5D02H copies to the first 0DH. (No effect)

Research To Do

Questions this page cannot answer yet, kept here until they are looked into:

  • DBLDOS 2.1. No copy is known in the archive. The September 8, 1980 letter shows that its SYS0/SYS and COPY/CMD file layout was the one of 4.20 at the patched places.
  • The date of 4.24. The GAT says 09/01/80, earlier than 4.20's 09/13/80, so the GAT date was not kept up to date. Percom's later memos (after DPM-0003) and the date of DOUBLE/CMD 1.21 are still to be found. DOUBLE/CMD 1.21 adds the 6DH B6H fill pattern that Al Domuret's 1981 article credits to Circle J's DOUBLE-ZAP II and that 4.20 and 4.23 do not have, which suggests that 4.24 came after that discussion.
  • CONVERT. The Doubler's advertisements name a CONVERT utility on the DBLDOS diskette; none of the archived diskettes has one. Its announcement (80-U.S. Journal, September/October 1980) describes it as converting TRSDOS, OS-80 and other single density files to double density; in 4.20 to 4.24 COPY/CMD does that itself (a $ before a file name selects single density), so CONVERT may have belonged to 2.1.
  • Versafile. A reader in France wrote to 80 Microcomputing in August 1982 that Radio Shack's Versafile did not run under DBLDOS: writing a record made the earlier records of the file disappear. BASIC/CMD has now been disassembled (the BASIC/CMD page) and its random file code read for this (GET and PUT, the byte input and output, FIELD): no cause of lost records was found there. PUT writes each record with a read back, and GET past the end of a file gives an empty record. The cause, if it is in DBLDOS, may be in SYS0/SYS's file routines or in Versafile itself.
  • FRMT/CMD. Al Domuret's DBLDOS (early 1981) had a file FRMT/CMD besides DOUBLE/CMD; no archived diskette has it. It may have belonged to 2.1.
Disassembly
Percom DoubleDOS 4.24 for the Model I - Disassembled; all the site's disassemblies are listed on the Disassemblies page.
Interview
Interview with Jim Stutsman, the author of MicroDOS and DBLDOS (Matthew Reed, October 2008).
MicroDOS / OS-80
MicroDOS / OS-80, Percom's earlier DOS by the same author, and OS-80D for the Doubler.
DOS Identification
Identifying a TRS-80 DOS from its diskette, with the DoubleDOS boot sector and directory.
RAM Addresses
The DoubleDOS 4.24 section of the RAM Addresses and Routines page.
Outside the Site