SamDOS 1.1 was the original DOS for the Sam Drive and external drives via the External Drive Interface.
The disk came with the drive and/or interface and also contained disk copies of the tape based utilities supplied with the SAM Coupé.
Version 1.1 source of many problems highlighted in one of the most corking ROM bugs in ROM 1.0 that prevented correct bootstapping forcing the user to enter a CALL command (CALL 229385 for 256K or on a 512K CALL 491529) after pressing F9 or typing BOOT.
Additionally a correction sheet was sent to fix a bug in the HIDE/PROTECT commands (POKE 235973,0 on a 256K and POKE 498117,0 on 512K.
Version 1.3 has been found which correctly boots on ROM 2 and later but does not load the AUTO file
SamDOS 2.0 was released along with ROM 2.0 and booted correctly, although this episode forced MGT to ship new ROMs to all customers.
It contained the updated tape based utilities as well as some bonus BASIC demonstrations.
Information from Frode Tennebø from the Sam Coupé Scrapbook
SAMDOS has been designed specifically for the SAM Coupe computer. It is similar and mostly compatible with GDOS & G+DOS as used with the MGT DISCiPLE and Plus D Spectrum disk interfaces.
These formats form the MGT file format family, this is described on the MGT Filesystem page.
We use 80 track per side, giving 160 tracks per disk. A track is made up of 10 data sectors, each giving 512 bytes of storage.
The first 4 tracks of the disk are given up to the SAMDOS directory, leaving 156 tracks available for storage. This leaves available 1560 data sectors of 512 bytes (798720 bytes).
Although each data sector can hold 512 bytes, only 510 bytes of them are available for storage. The last two bytes of the data sector are used by the DOS to locate the next part of the file stored. Byte 511 hold the next track used by the file, while byte 512 holds the next sector.
Disk File Header
At the beginning of each disk file there is a file header. The file header is 9 bytes long:
|Byte||SAMDOS type||Plus D type|
|0||File type||File type|
|1-2||Modulo length||Length of file|
|3-4||Offset start||Start address|
|7||Number of pages|
|8||Starting page number|
Details of the Plus D header can be found in the technical information for the Plus D.
Each file type in the SAMDOS is allocated a numeric identifier:
|Number||SAMDOS type||Directory Text|
|1||ZX BASIC||ZX BASIC|
|2||ZX Numeric array||ZX D.ARRAY|
|3||ZX String array||ZX $.ARRAY|
|5||ZX Snapshot 48K||ZX SNP 48k|
|7||ZX Screen||ZX SCREEN$|
|9||ZX Snapshot 128K||ZX SNP 128k|
|11||Execute file||N/A EXECUTE|
|12||ZX Directory (BetaDOS/UNI-DOS)||ZX DIR|
|21||Directory (MasterDOS only)||DIR|
|22||DRiVER Application||DRIVER APP|
|23||DRiVER Boot file||DRIVER BOOT|
Modulo Length & Number of Pages
In the SAMDOS header the length of the file is calculated by multiplying the number of pages (byte 7) by 16384 and adding the modulo length (word 1-2), LSB/MSB, ie the length MOD 16K.
Offset Start & Starting Page Number
Read starting page number (byte 8). AND this with 1FH to get the page number in the range 0 to 31. To find the start, multiply the page number by 16384, add the offset and subtract 4000H (since the ROM occupies 0-3FFFH).
When SAMDOS is paged in it resides at 4000H, and ROM0 is placed at 0-3FFFH.
The first 4 tracks of the disk are allocated to the disk directory, starting at track 0, sector 1. These 4 tracks give us 40 sectors each split into two 256 bytes entries. Each of these entries will identify one file, thus allowing up to 80 entries in the directory.
The format of each directory entry is as follows:
|0||0||Status/File type. This byte is allocated on of the file types listed previously, but is also used as a file status. If the byte is 0 then then file has been erased. If the file is HIDDEN the bit 7 is set. If the file is Protected then bit 6 is set.|
|1-10||1-10||Filename. This filename can be up to 10 characters.|
|11||MSB of the number of sectors used in the file.|
|12||LSB of the number of sectors used in the file.|
|13||Track number for start of file.|
|14||Sector number for start of file.|
|15-209||Sector address map (195 bytes) (detailed further on).|
|210-219||MGT Future and past (10 bytes). These were used in the PLUS D directory but are not used by the SAMDOS. They are allocated to MGT for future use.|
|220||15||Flags (MGT use only).|
|221-231||File type information|
|16-26||If the file type is 17 or 18 then these bytes contain the file type/length and name.|
|16||If the file type is 20 then these bytes contain the screen mode.|
|16-18||If the file type is 16 then these bytes contain the program length excluding variables.|
|19-21||If the file type is 16 then these bytes contain the program length plus numeric variables.|
|22-24||If the file type is 16 then these bytes contain the program lengtrh plus numeric variables and the gap length before string and array variables.|
|232-235||27-30||Spare 4 bytes (reserved).|
|236||31||Start page number, in bits 4-0, bits 7-5 are undefined.|
|237-238||32-33||Page offset (8000H-BFFFH). This is as per file header, although when the ROM passes a file to be saved, it starts it in section C of the addressing map.|
|239||34||Number of pages in length (as per file header).|
|240-241||35-36||Modulo 0 to 16383 length, ie length of file MOD 16384 (as per file header).|
|242-244||37-39||Execution address. Execution address, if CODE file, or line number if an autorunning BASIC program.|
|245-253||40-47||Spare 8 bytes.|
|254-255||For future use by MGT only.|
In SAMDOS, unused entries should be set to value 255, MasterDOS shares this but B-DOS uses value 32.
Sector Address Map
SAMDOS allocates 195 bytes to the sector address map, giving 1560 bits, which is the exact number of sectors available for storage on the drive.
A sector address map is calculated for each directory entry. When a field is created a directory entry is made for that file. A sector address map is created by setting the specific bit(s) corresponding to the sector(s) allocated to the file. (Bit 0 of the first byt is allocated to trac4 sector 1). For example, if the file uses 5 sectors then fice corresponding bits in the sector adress map are set and svaed as part of the directory entry.
Bit Address Map (BAM)
The bit address map is not stored on the disk by SAMDOS. It is genereated by performing a bitwise OR of each file’s sector address map. This then gives SAMDOS a usage map of the disk.
When a file is created the first thing SAMDOS does is calculate the BAM and then by looking at the available sectors (ie bits not set), it can work out if there is room for the file. If there is room for the file, then the directory entry is created, including the sector address map specific to the new file, and the file is stored in the sectors which have been specified in the file’s sector address map.
|INIT||128||Initialise and look for AUTO file
This routine looks for an AUTO file on the current disk, and initalises the DVARS.
|HGTHD||129||Get file header
Get file header. This routine should be called with IX pointing to the UIFA, which should contain the file type and filename required. When completed the complete file header will be transferred in DIFA form to IX+80 bytes.
Load file in UIFA pointed to by IX register. The C register contains the number of 16K pages used by the file, while DE must contain the length modulo 16K. The HL register pair must point to a destination between 8000H to BFFFH, while the destination page must be paged in using the HMPR register. These values can be obtained from the header loaded by HGTHD.
Verify the memory to the file stored on the disk. Again the IX register must be a pointer to the file UIFA. Use as HLOAD, but verifies rather than loads.
Save the file whose UIFA is pointed to by the IX register. The UIFA must be a complete UIFA, including file length, etc.
|HVAR||139||Get address of DVAR
This routine calls the jump table thus unstacking the number following the DVAR into BC. The routine supplies the address of the DVAR by putting it onto the BASIC floating point calculator stack.
|HOFLE||147||Open a File
Open a file on the disk. IX must point to the UIFA. The routine will create a sector address map, and save the header to the disk and reset pointer RPT.
|SBYT||148||Save a byte
Save the byte in the Accumulator to the RAM pointed to by the pointer RPT. If the sector is full the data will be stored in the next sector pointed to by the sector address map.
|HWSAD||149||Write a sector to the disk
D contains the track number, and E contains the sector number. The Accumulator holds the drive number (1 or 2). Writes the sector pointed to by the DE register pair. The Accumulator contains the drive number, while the HL register pair is the pointer to the source data which must be resident in the 64K address map.
|HSVBK||150||Save a block of data
Save a block of data to the disk where the DE register pair points to the start of the data, and the BC register pair holds the byte count.
|CFSM||152||Close file sector map
Close file sector map. This routine empties the RAM and copies the header area on to the directory, closes the file, then updates the directory.
|HGFLE||158||Get a file from disk
Get a file from the disk. The IX register must point to the UIFA. The return is made with the first sector of the file loaded into RAM and RPT pointing to the first byte.
|LBYT||159||Load a byte
Load the byte pointed to by RPT from RAM, place it in the Accumulator, and increment the RPT. When the sector has all been read then the next sector is loaded from the disk and the pointer adjusted.
|HRSAD||160||Read a sector from the disk
D contains the track number, and E contains the sector number. The Accumulator holds the drive number (1 or 2). Reads the sector pointed to by the DE register pair. The Accumulator contains the drive number, while the HL register pair is the pointer to the destination (Note: the destination is absolute 0x4000 to 0xfe00, mapping to page 0,1 or 2 only)
|HLDBK||161||Load a block of data from disk
Load a block of data from the disk to the memory pointed to by DE with the block count in BC.
|REST||164||Restore disk drive to track 0
Restore disk drive to track 0. The Accumulator holds the drive number, ie 1 or 2.
|PCAT||165||Perform a directory listing
Perform a directory listing to current stream.
|HERAZ||166||Erase a file from disk
Erase a file from the disk. Register IX must point to the UIFA of the file to be erased.
Source code available on GitHub.