Introduction by the Editor

This instruction manual is derived from the instruction pamphlet provided for the Larken Disk Editor by Larry Kenny when the program was originally issued in 1988.

Most of the editing was done for the sake of saving the reader's eye-sight and for easier transfer to electronic media such as this web site. Otherwise, this instruction manual is as Larry Kenny wrote it.

There are a few other things that should be noted:

  1. A "disk" usually means a double-sided, double-density 5¼ inch floppy diskette. A few Timex/Sinclair users did have 5¼ inch quad-density drives at that time and 3½ inch drives were just becoming popular.
  2. Any text that has been "struck-out" indicates that this was part of the original pamphlet but the goods and services are no longer being offered.
  3. Finally, I wish to remind the reader that this is copyrighted material. It is provided for users of the original software who require a manual or for personal reference. For reproduction for any other purpose, please write for permission to the e-mail address given below.

David Solly
Bibliotheca Sagittarii
Ottawa, Ontario
© 9 November 1998

The Larken Disk Editor is a useful tool for modifying, repairing or examining the directory, track map and data on a disk.

It is supplied on a 48-TPI, 5¼ inch disk. If you have a different type of drive, return it with a blank disk and $2 and I will put it on your disk.

Organization of Blocks

Side 1: 1357911 13151719->
Side 0: 0246810 12141618->

Block 0 is reserved for the catalog, track map and disk name. The track map is a 165-byte table beginning at address 24 in block 0. The map is used when saving to let LKDOS know what blocks on the disk are available (unused).

The track map is created according to the number of tracks and sides entered when the disk is formatted. Numbers starting from 0 are listed sequentially up to a possible 164 blocks. Any blocks that don't exist on the actual disk, or are reserved (block 0 is reserved for the catalog), are replaced with the number 245. LKDOS uses numbers from 245 through 255 as markers in the catalog.

If a 40-track, single-sided disk was formatted, the track map would show all odd numbered blocks as 245 (used), as well as the even numbered blocks past the 40 track limit.

When a file is saved, the blocks that the file uses are replaced by 245 in the track map. When a file is deleted, the blocks used by the file are restored in the track map with the block number. If you save a file with a name that is already on the disk, the existing file is erased before the new file is saved.

Following the track map are the directory name cells. This is a list of about 100 formatted areas for storing the file name of each file and the blocks used by that file. The length of each cell is 34 bytes, but this may vary if the file is a custom type file.


Each cell begins with a 255 marker, then a nine-character file name. If the cell is not used, or the file has been deleted, then a 254 marker follows the 255. After the file name is a 253, marking the beginning of the block list used by the file.

The end of the block list is marked by a 249. The 249 is a floating marker, and if the file is deleted, it is moved to just after the 253, indicating no blocks used. There is room in each cell for 21 blocks (over 100K), but this can be expanded for sequential files, etc. On the other hand, if you would like more than 100 files per disk for a quad-density drive that has 160 blocks, you can reduce the size of the block area so you can put in more name cells.

The end of the list of 100 or so name cells is marked by a 250. At address 4500 in the catalog block is the disk name. It can be very long (over 500 characters), and ends with a 0.

Markers used by LKDOS in the catalog block
245- Block in use. Only used in track map.
249- Marks the end of the block list in the name cell.
250- Marks the end of the directory name cells.
253- Marks the beginning of the block list in the name cell.
254- Follows the 255 marker if the cell is not in use.
255- Marks the beginning of each directory name cell.

Also, in block 0, address 20 hold the number of sides on the disk, address 21 holds the number of tracks, and address 22 holds the head speed. The head speed is the speed at which the disk drive's head steps from track to track.

Data Blocks

All blocks from block 1 up to the maximum on the disk are data blocks. Each data block contains a 24-byte information header, and then room for 5090 bytes of data.

Header Information
In Block
0- Reserved
1- Block number
2 - 11- File name
12, 13- Start address of file
14, 15- Length of data (in block only)
16- Sum check (CRC) number
17, 18- Auto-run line number for BASIC
20, 21- Variable - Prog (Offset for BASIC)
22, 23- Total length of file
24- Start of data (5090 bytes, maximum)

Disk Editor Commands

When using the Disk Editor, you should have the write protect sticker removed from the disk you want to edit or modify. The routines used in the Disk Editor cannot detect the presence of a write protect sticker.

1. Edit Data on Disk

Selecting this will display a windowed screen, with a prompt to enter a block number to load into the buffer. You can view or edit the directory block by entering block 0; or use other numbers for data blocks. If you enter "n", you can enter the edit mode without loading a block.

Press Enter to scroll the screen, or press the space bar to single-step through the buffer.

The bar across the left side of the screen is the address of the line that can be edited. Press "n" to enter a new number, "c" to enter a character or entire character string or file name.

To go to a new address in the buffer, press "g", then the address. You cannot go beyond the limits of the buffer. The buffer starts at 50000; so, if you want to go to the 4500 th address in the buffer to see the disk name, then enter 54500.

Pressing "f" will let you search for a byte (such as the next 255 marker), or a character by entering that character's code.

To save the buffer back to the disk, press "s". You can load a block or catalog from one disk and then save it to another disk.

To exit to the main menu, press "q".

2. Read Disk Headers

This will print, to the screen or to a printer, the headers of all the tracks. This is useful if you want to find the start and length of a code file, or to find the blocks used by files when you are reconstructing a damaged directory. The printer option prints to the Timex/Sinclair 2040 thermal printer, unless you open channel 3 to a line printer (OPEN #3, "lp") or load a printer driver.

3. Change Disk Speed

This allows the head speed on a disk to be changed. Enter "4" to abort.

4. Reformat Single Block

A block can be damaged by turning on the drive power when a disk is in it, or in numerous other ways. You can reformat a single block using this option. Since the format code is the only code that can only be used on a specific interface, you must insert the Disk Editor disk and load the format code before actually formatting. After the code has been loaded once, though, you can enter "z" to suppress repeated loading of the format code.

5. Initialize Directory

With this, you can initialize the directory and the track map, but not change the disk name. Warning: This will wipe out all files on the disk!

6. Map Out Bad Blocks

A disk that has bad blocks caused by a scratch or other physical defect can be automatically mapped as "used" by this command. However, you should first make certain that the source of the CRC errors is the disk, and not a hardware problem. A disk that clicks while rotating in the drive usually has a surface defect. A common source of false CRC error reports is the board in the command cartridge dock. Sometimes, after sitting in the command cartridge dock for a time, the edge connector on this board becomes dirty or corroded and fails to make proper contact with the computer. Cleaning the edge connector will correct this problem, but take care to shut down and remove the power cable from your Timex/Sinclair 2068 before removing the board from the command cartridge dock. Failing to do this will irreparably damage your computer and put you at risk of receiving an electric shock.

7. Change Disk Name

You can change the disk name without altering anything else on the disk using this option. You can even break the program and load the disk name from a word processor file to address 54500, then save the buffer. Tasword II® can't be used because it formats each line as a 64 character array. Jack Dohany's (but not the original!) version of M-Script® which has been modified for LARKEN I/O works well.

8. Catalog / Go To Drive (Now 0)

This allows you to change drives and display the catalog. If you don't want to change drives, just press enter.

9. Display Track Map

This brings up a graphical representation of the track map. The vertical numbers represent "tens" and the horizontal numbers are "ones". This gives you a picture of the state of the disk. If many files have been deleted, you will see how LKDOS keeps track of unused tracks.

Note: You can break and alter the program as you wish. It is safe to RUN it. Most of the editor (option 1) runs as compiled BASIC (compiled with Time Machine at 60000). The compiled section begins at line 910 and ends at 1450.

LKDOS Machine Language Subroutines

The following information is for using the routines within LKDOS directly to control the disk drive. They're useful for examining or changing data on the disk; also, you can create custom files, simulate random access files, and so forth.

To access LKDOS subroutines within the cartridge directly, you must use machine language.

To call these subroutines, you must first turn on the cartridge with a call to address 98 (decimal). The cartridge is turned off by a memory read from address 100 (decimal).

You should also disable the interrupts before entering, and enable them after you're done.

An example for accessing the cartridge:

        CALL 98
        CALL LKDOS subroutine
        other code
        LD A,(100)

Description of Useful Subroutines

The addresses of these subroutines are on the following pages. The jump table of calls is used so that the addresses of the main routines do not change when a change or revision is made to the LKDOS EPROM. Also, because of the size of LKDOS, it was assembled in two modules. The second module uses the table to link to the first module.

SAVEBF- Saves the buffer to the current track and side as set up by TRACK or NEXTR. The disk should be spinning for 1 second before using this routine. You can load data to and from the buffer using the LDIR command in machine language.
LOADBF- Loads the buffer from the current track and side. No spin-up necessary.
TRACK- Restores the drive head to track 0, then seeks the track held in curtrk. The number in curtrk is actually the block number. Even blocks are side 0 and odd blocks are side 1. The track number is equal to INT(block/2). Example: Block 11 equals track 5, side 1. TRACK also does the one-second spin-up required by save and load routines. It should be the first call in any disk access. The data in the buffer may be erased by the TRACK routine, so only place data in the buffer after calling TRACK.
NEXTR- Increments curtrk by one and moves the head to the next track or side. The drive should be running before this is called.
INDIR- Sets the head on track 0, loads the directory track, then searches for a file name matching the one the user has put at prognm. The temp2 pointer hold the address of the file name if found. Errnu will contain 10 if the file was not found. Clear errnu before calling this command. Pad the file name with spaces if it is less than 10 characters.
WPROT- Does a 0.75 second spin-up, then checks if the disk is write-protected. If it is, then the program is halted and the error statement S - Protect Error is printed. Because this halts the program on an error and could thereby cause loss of data, it's better to check it manually.
DECDP- Prints the contents of temp1 and the accumulator as a decimal number.
DOSER- This will print a standard error message in the same manner as the 2068 does. The HL register should hold the address of the error message and the message should end with a period.
EVALU- This is used to evaluate a numeric expression in a BASIC command. CHADD should point to the start of the number or formula. Use RST #20 to move CHADD. The result will be returned in the BC register. EVALU uses the Sinclair ROM calls to do this very complicated math. It checks to see if you are running in 2068 mode or in ZX Spectrum mode and then makes the appropriate ROM call.
GTFIL- This is like EVALU, but for string expressions. CHADD should point to one character before the string. The result string will be found in prognm. The DE register will point to the quote mark (\") at the end of the string. If you're then going to search for that file with INDIR, replace the quote mark with a space by doing LD A,32 / LD (DE),A right after calling GTFIL.

Saving and Loading Programs from Machine Code

You can access the main operating system directly by the following four subroutines. This will allow you to write or modify fully machine code programs to use the disk just as you can in BASIC. Due to the complexity of saving and loading BASIC or ARRAY files, only CODE files will be described here.

When you send LKDOS a command from BASIC, it scans the line for the information it needs. But in machine code, we must put the information in certain locations before calling LKDOS to use it.

The LKDOS location NmiF is used to tell LKDOS how it is being called: from the NMI, BASIC, or a machine code program. It should be loaded with 11 (decimal) before you call the following routines.

Saving Files from Machine Code

To save an area of memory to disk from machine code, you must first give it a file name, and transfer the file name to prognm. The file name should be a code type; but since there's no syntax checking, any name and extension will work. In other words, you're not limited to .A, .B or .C type files.

Then, call the SV#1 subroutine. This will enter the file name into the directory, and fill the directory work area with free blocks to use for saving. If the file already exists, then the old file is deleted first.

Now, load temp2 with the length of the file and temp4 with the start address of the file. Then call SV#2 to finish the save.

Example: To save a file named test.ZZ, with start address 30000 and a length of 10000 bytes:

Save    DI                 ;Disable interrupt.
        CALL 98            ;Turn on the cartridge.
        LD HL,Name         ;Transfer file name
        LD DE,prognm       ;to program.
        LD BC,10
        LD A,11            ;Set MC save.
        LD (NmiF),A
        CALL SV#1          ;Save name.
        LD HL,30000
        LD (temp4),HL      ;Set start address.
        LD HL,10000
        LD (temp2),HL      ;Set length of save.
        CALL SV#2          ;Second data.
        LD A,(100)         ;Exit cartridge.
Name    DEFM /test.ZZ   /  ;Name of file padded to 10 chars.

The SV#1 main routine first calls the WPROT subroutine to see if the disk is protected. If it is, then the routine will terminate with an error. This will stop the machine code program.

If you don't want your program to be stopped, the best way around this is to find the address of the actual SV#1 routine in the EPROM by reading locations 205 and 206, add 3 to this to skip past the WPROT call, and call the new address directly. This address must be calculated dynamically because it may change with new EPROM revisions.

If you're saving a file from one address, but you want the file's absolute load address (that is, what you get with LOAD "file" CODE, and no address specified) to be different, then you should change the locations Destin and Totlen on the first block of the file to reflect the new start or length. Also, if you're adding data to the end of a file (as in sequential files), you must update Totlen on the first block of the file.

If the file is a BASIC or ARRAY file, the first and last blocks should have their pointers updated.

Loading a File from Disk

Loading a file from machine code is similar to saving. Just use LD#1 instead of SV#1 and LD#2 instead of SV#2. The start and length still go into temp4 and temp2. The file name is also moved into place the same way.

If you want to use the start address and length that the file was saved from to load it, then after calling LD#1 (the first block of the file is now in the buffer), use the Destin and Totlen pointers as your start and length.

You can poke 23728,100 as you do in BASIC so your program will not stop with a File Not Found error.

Selecting Drives from Machine Code

The LKDOS variable Dvsel specifies which drive is currently active. You can change the current drive by changing the value of Dvsel, as follows:
     1 = drive 0
     2 = drive 1
     4 = drive 2
     8 = drive 3
   128 = drive 4 (RAM Disk)

When changing drives, (especially floppies), insert a 0.05 second delay before and after changing drives between any disk call.

Machine Code Programming Guidelines for LKDOS

If you plan on writing a program for yourself or other LKDOS users, then to be fully compatible with other programs or any changes I may make, follow these simple rules: