This the multi-page printable view of this section.Click here to print.
Notes about the Sinclair ZX Spectrum operating system & memory
CC BY-SA
Peter Mount, Area51.dev & Contributors
Notes about the Sinclair ZX Spectrum operating system & memory
Title | Sinclair ZX Spectrum OS |
---|---|
Subtitle | Notes about the Sinclair ZX Spectrum operating system & memory |
Author | Peter Mount, Area51.dev & Contributors |
Copyright | CC BY-SA |
This license is acceptable for Free Cultural Works.
The licensor cannot revoke these freedoms as long as you follow the license terms.
You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation.
No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material.
You can read the full license here: https://creativecommons.org/licenses/by-sa/4.0/
The following table is an overview of the Spectrum Memory map for both 48K and 128K/+2 machines. The +2A and +3 are similar to the 128K but have additional ROM's and alternate all RAM memory layouts. The specifics for the individual machines are listed in their own sections.
Address | 48K | 128K / +2 | |||||||
---|---|---|---|---|---|---|---|---|---|
0000 | ROM | ROM 0 128K Editor |
ROM 1 48K Editor |
||||||
1000 | |||||||||
2000 | |||||||||
3000 | |||||||||
4000 | Screen | RAM Bank 5 | |||||||
5000 | OS vars & free memory | ||||||||
6000 | |||||||||
7000 | |||||||||
8000 | free memory | RAM Bank 2 | |||||||
9000 | |||||||||
A000 | |||||||||
B000 | |||||||||
C000 | RAM Bank 0 | RAM Bank 1 | RAM Bank 2 | RAM Bank 3 | RAM Bank 4 | RAM Bank 5 Screen #1 |
RAM Bank 6 | RAM Bank 7 Screen #2 |
|
D000 | |||||||||
E000 | |||||||||
F000 |
Some memory is contended with the ULA, with the latter having priority whenever the screen is being updated. Time critical code needs to run in uncontended RAM.
On the 48K memory between 0x4000…0x7FFF is contended with the ULS whilst 0x8000…0xFFFF is not.
On the 128K and +2, odd numbered RAM banks are contended with the ULA. Time critical code should run in even numbered RAM banks.
The memory of the +2A and +3 are similar to the 128K and +2. The main difference is that these models have four ROMs rather than two and additional memory configurations.
The memory is paged by writing to port 0x7FFD and port 0x1FFD. Port 0x7FFD is almost identical to the 128 except that ROM is now the lower bit.
Both of these ports are write only, so a copy is stored in ram at address 0x5B5C for 7FFD and 0x5B67 for port 1FFD.
Port | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Ram Copy |
---|---|---|---|---|---|---|---|---|---|
1FFD | Printer Strobe |
Disk Motor |
1ROM | 0 | 5B67 | ||||
Memory Mode | 1 | ||||||||
7FFD | DIS | 0ROM | SCR | RAM | 5B5C |
Rom ID | Rom Selected |
---|---|
0 | 128K editor, menu system and self test |
1 | 128k syntax checker |
2 | +3DOS |
3 | 48K Basic |
The IDs are such that, if 128K code changes rom (as they don't know about the new register) then they would still get the correct rom as bit 0 is from the original port and bit1 would normally be clear at that point.
In special mode, the RAM bits are ignored and bits 1 and 2 of port 0x1FFD control a memory map layout
Address | Mode 0 | Mode 1 | Mode 2 | Mode 3 |
---|---|---|---|---|
0000 | Bank 0 |
Bank 4 |
Bank 4 |
Bank 4 |
4000 | Bank 1 |
Bank 5 Screen #1 |
Bank 5 Screen #1 |
Bank 7 Screen #2 |
8000 | Bank 2 |
Bank 6 |
Bank 6 |
Bank 6 |
C000 | Bank 3 |
Bank 7 Screen #2 |
Bank 3 |
Bank 3 |
On the Plus 3 ram bankes 1, 3, 4 and 6 are used for the disk cache and RAM disk. Bank 7 contains the editor scratch pads and +3DOS workspace.
The memory of the 128K and +2 is organised like below. Note the +2A and +3 are different.
0000 3FFF |
ROM 0 128k Editor |
ROM 1 48K Basic |
||||||
40007FFF | Bank 5 Screen #1 |
|||||||
8000 BFFF |
Bank 2 |
|||||||
C000 FFFF |
Bank 0 |
Bank 1 |
Bank 2 |
Bank 3 |
Bank 4 |
Bank 5 Screen #1 |
Bank 6 |
Bank 7 Screen #2 |
RAM Banks 1, 3, 4 and 6 and most of 7 are used for the ram disk. The rest of bank 7 contains editor scratch pads.
The memory is paged by writing to port 0x7FFD.
This port is write only, so a copy is stored in ram at address 0x5B5C.
Port | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | Ram Copy |
---|---|---|---|---|---|---|---|---|---|
7FFD | DIS | ROM | SCR | RAM | 5B5C |
Address | Content | ||||||||
---|---|---|---|---|---|---|---|---|---|
0x0000 | ROM | ||||||||
0x4000 | Screen Memory | Contended RAM | |||||||
0x5800 | Screen Colour data | ||||||||
0x5B00 | Printer buffer | ||||||||
0x5C00 | System Variables | ||||||||
0x5CC0 | Reserved | ||||||||
0x5CCB | Available Memory | ||||||||
0x8000 | Un-Contended RAM | ||||||||
0xA000 | |||||||||
0xC000 | |||||||||
0xE000 | |||||||||
0xFF58 | Reserved | ||||||||
0xFFFF |
The following table shows the memory map of the Spectrum as seen by BASIC.
Address | 48K | 128K | ||||||
---|---|---|---|---|---|---|---|---|
4000 | Display File | |||||||
5800 | Display Attributes | |||||||
5B00 | Printer Buffer | |||||||
5C00 | System variables | |||||||
5CB6 CHANS |
Channel Information | |||||||
PROG | 0x80h | |||||||
Basic Program | ||||||||
VARS | Variables | |||||||
0x80h | ||||||||
Command or program line being edited | ||||||||
NL | ||||||||
0x80h | ||||||||
WORKSP | INPUT data | |||||||
NL | ||||||||
Temporary workspace | ||||||||
STKBOT | Calculator stack | |||||||
STKEND | ||||||||
Spare | ||||||||
SP | Machine stack | |||||||
Gosub stack | ||||||||
RAMTOP | ||||||||
0x3E | ||||||||
UDG | User defined graphics | |||||||
PRAMT |
Unlike most manufacturers, the spectrum rom doesn't have many standard rom entry points with most of them undocumented. This meant that the addresses changed between the different machines.
For example, all 48K Spectrum's had the same ROM, so you were almost guaranteed to be able to use the same routine on different machines. However, the 128K introduced 2 roms so there had to be differences. With the +2A/+3 came 4 roms and to complicate things there exists an English and Spanish version of these roms with different addresses.
Unless otherwise specified, the entry points in this section will be for the 48K Spectrum as that has more documentation available.
The only common entry points (known so far) are the RST entry points, as these are also used by the
processor's RST
instruction.
Calculator | Enter the floating point calculator |
---|---|
Collect Character restarts | Collect Character and Collect Next Character restarts |
ERROR | Error restart |
Make BC Spaces | Creates BC free locations in the workspace |
Maskable Interrupt | The Maskable Interrupt Handler |
PRINT_A | Write A to current output channel |
START | Restart the machine |
Even this isn't standardised in documentation, with some calls referenced by different numbers.
For example, the calculator is referenced as RST 5
, RST 40
and RST $28
in different places even though they are identical instructions.
Address | OP Code | RST Instruction | Action | |||||
---|---|---|---|---|---|---|---|---|
48K | 128K | +2 | +2A/+3 | |||||
0000 | C7 | RST 0 | Reset machine | |||||
0008 | CF | RST 1 | RST 8 | Error handler | Unavailable | Error handler | ||
0010 | D7 | RST 2 | RST $10 | RST 16 | Print A | |||
0018 | DF | RST 3 | RST $18 | RST 24 | Get Character | |||
0020 | E7 | RST 4 | RST $20 | RST 32 | ||||
0028 | EF | RST 5 | RST $28 | RST 40 | Calculator | Call ROM1 | Call ROM3 | |
0030 | F7 | RST 6 | RST $30 | RST 48 | Reserve Workspace | Unavailable as used by RST 5 | ||
0038 | FF | RST 7 | RST $38 | RST 56 | Maskable Interrupt Handler |
A 128K machine running in 48K mode will have the RST instructions as the 48K machine.
Clear the screen | Clear the whole display area |
---|
On the 128K and +2 Spectrum's there is a vector table at 0x0100 to common routines.
Previously the ROM was just a single program and not an Operating System.
Address | Routine | |||||||
---|---|---|---|---|---|---|---|---|
128K | +2 | |||||||
0100 | BASIC interpreter parser | |||||||
0103 | Line Run entry point | |||||||
0106 | Transfer bytes to logical RAM bank 4 | |||||||
0109 | Transfer bytes from logical RAM bank 4 | |||||||
010C | 128K error routine | |||||||
010F | Error routine | |||||||
0112 | Return statement | |||||||
0115 | Next statement | |||||||
0118 | Scan Keyboard | |||||||
011B | Play music strings | |||||||
011E | MIDI byte output | |||||||
0121 | RS232 byte input | |||||||
0124 | RS232 text output | |||||||
0127 | RS232 byte output | |||||||
012A | COPY screen dump | |||||||
012D | RST 5 keypad scan routine in ROM 1 |
Function | Address | Description |
---|---|---|
RST_5 | 0028 | FP Calculator |
The only way to use this on later Spectrum's is to page in the 48K ROM before making the call.
RST 5
on a 48K Spectrum enters the floating point calculator.
Function | Address | Description |
---|---|---|
CL_ALL | 0DAF | Clear the screen |
This entry point is only available on the 48K Spectrum.
The only way to use this on later Spectrum's is to page in the 48K ROM before making the call.
It's advisable to write your own as noted below.
This entry point clears the screen.
Unless you need to keep compatibility with BASIC, it's better and faster to use your own routine for this. An example of how to do this is available in the examples section: Clear Screen Example
Function | Address | Description |
---|---|---|
RST_3 | 0018 | Collect character |
RST_4 | 0020 | Collect Next character |
RST 3
returns the character addressed by CHADD
returning it if it's printable.
If it is not printable then CHADD
is incremented until a printable character is found.
RST 4
increments CHADD
first before returning the next printable character.
These two resets are used in multiple places in the ROM, the BASIC tokenizer being one of them.
Function | Address | Description |
---|---|---|
RST_1 | 0008 | Report an error |
RST 1
can be used to stop a program with an error
Function | Address | Description |
---|---|---|
RST_6 | 0030 | FP Calculator |
RST 6
reserves memory in the workspace
BC
holds the number of bytes to create
DE
holds the first byte of the new free space.
HL
holds the last byte of the new free space.
Function | Address | Description |
---|---|---|
RST_7 | 0038 | Maskable Interrupt Handler |
RST 7
is also the Maskable Interrupt handler
It increments the real time clock in the FRAMES
variable once every 20ms (UK).
It also scans the keyboard.
Function | Address | Description |
---|---|---|
RST_2 | 0010 | Print A to the output stream |
RST 2
is usually used to write to the current channel, usually the screen.
Internally, RST 2
calls the routine in the CHURCHL
vector,
returning with all registers preserved unless an error occurred.
Because the rom code uses the CHURCHL
vector you can easily replace the
current output channel with your own code.
My Teletext emulator does this to allow code to write to the new screen using RST 2
.
Function | Address | Description |
---|---|---|
RST_0 | 0000 | Start the computer |
Called when the machine is first started, RST 0
can be used to restart the machine.
The screen has a fixed resolution of 256x192 pixels or 32x24 characters. Colour is restricted to 8x8 pixel squares equivalent to each character.
It is located in memory at address 0x4000…0x5AFF and is split into two parts:
Address | Name | Content | |||||||
---|---|---|---|---|---|---|---|---|---|
4000 | DISPLAYFILE | Screen Memory | |||||||
57FF | |||||||||
5800 | DISPLAYATTR | Screen Colour data | |||||||
5AFF |
The 128K Spectrum's have a second screen in RAM Bank #7 which can be used as an alternate to the default one which is in RAM Bank #5. The memory layout is the same except for where it appears in the memory map.
This section will refer to the default memory location as used by all Spectrum's.
If you want to use the alternate screen then you need to change the base address to that of the correct bank. These are shown in the memory map's:
Address | Len | Name | Description |
---|---|---|---|
4000 | 6144 | DISPLAYFILE | The start of the standard Spectrum's standard screen |
The display file contains the pixel data for the screen.
Arranged in a map of 192 rows, each 32 bytes long. Each byte contains 8 pixels.
Be aware, the rows are not stored linearly, but in a way that has been optimised for the ULA.
The first 256 bytes in memory represents the first byte of each character in the first 8 rows, then the second byte of each character, and so on. Once the first 8 rows have been done it repeats twice more for the next 8 rows then the last 8.
Although the memory map for the spectrum screen seems weird with its layout, it's actually pretty logical. You can tell this weirdness is down to how the ULA works internally.
If you have:
R
with the screen row (0…23)C
with the column (0…31)N
for the byte offset within the character (0…7)then you can calculate the address using the following table:
Screen Address | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
MSB | LSB | ||||||||||||||
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | 1 | 0 | R4 | R3 | N2 | N1 | N0 | R2 | R1 | R0 | C4 | C3 | C2 | C1 | C0 |
The formula is simple: $$ Address = \left( \overbrace{ ( 0x40 | ( R \And 0x18 ) | N ) }^{MSB} \ll 8 \right) | \left( \overbrace{ ( ( R \And 0x07) \ll 5 ) | C }^{LSB} \right) $$
1lsb := ((R << 5) AND 0xC0) OR C
2msb := 0x40 OR (R AND 0x18) OR N
An example routine in Z80 Machine Code for this calculation is available to download.
If you calculate the address of the top row of the character (i.e. N
=0) then, when rendering the
character to the screen you just need to increment the upper byte of the address.
This works as the lower 3 bits of the upper byte represent the row for the character.
The adjacent table shows the addresses for each row of the first 5 characters on row 0 of the screen.
Char Row | Address | |||||
---|---|---|---|---|---|---|
Char 0 | Char 1 | Char 2 | Char 3 | Char 4 | ||
0 | 4000 | 4001 | 4002 | 4003 | 4004 | |
1 | 4100 | 4101 | 4102 | 4103 | 4104 | |
2 | 4200 | 4201 | 4202 | 4203 | 4204 | |
3 | 4300 | 4301 | 4302 | 4303 | 4304 | |
4 | 4400 | 4401 | 4402 | 4403 | 4404 | |
5 | 4500 | 4501 | 4502 | 4503 | 4504 | |
6 | 4600 | 4601 | 4602 | 4603 | 4604 | |
7 | 4700 | 4701 | 4702 | 4703 | 4704 |
You can get the address of the next character simply by adding one to the lower byte of the address. Be careful however when wrapping around the end of the line as, after the first 8 lines the address will fail.
Ideally you should calculate the address again at the start of each line.
This might explain why the original spectrum editor was 8 lines long, as you only needed to set the high byte to an appropriate 8-line block in memory and set the low byte to the offset in the line being edited to get that characters screen address.
As mentioned above, you could use one third of the screen as a simple editor which is capable of displaying 256 characters.
Address | MSB | Rows | Screen position | |
---|---|---|---|---|
4000 | 0x40 | 0 | 7 | Top third |
4800 | 0x48 | 8 | 15 | Middle third |
5000 | 0x50 | 16 | 23 | Bottom third |
As long as you restrict yourself to one third of the screen you can simply calculate the address within this simple editor by selecting the high byte for the required section of the screen and use the characters position in the line as the low byte.
Address | Len | Name | Description |
---|---|---|---|
5800 | 768 | DISPLAYATTR | The display attributes holding colour information |
The display attribute section contains the colour information and occupies addresses 0x5800…0x5AFF.
It's a direct map of the characters on the screen, arranged in 24 rows, each 32 characters long. Each byte consists of the Foreground (INK) and Background (PAPER) colour for all pixels contained within the equivalent position in the Display File.
Function | Address | Description |
---|---|---|
SWAP | 5B00 | Paging subroutine |
STOO | 5B10 | Paging subroutine. Entered with interrupts disabled and AF, BC on the stack. |
YOUNGER | 5B21 | Paging subroutine |
REGNUOY | 5B2A | Paging subroutine |
ONERR | 5B3A | Paging subroutine |
RAMRST | 5B5D | RST 8 instruction used by ROM 1 to report old errors to ROM 3 |
Address | Len | Name | Description | Default | ||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
5B52 | 2 | OLDHL | Temp store while switching roms | |||||||||
5B54 | 2 | OLDBC | Temp store while switching roms | |||||||||
5B56 | 2 | OLDAF | Temp store while switching roms | |||||||||
5B58 | 2 | TARGET | Subroutine address in ROM 3 | |||||||||
5B5A | 2 | RETADDR | Return address in ROM1 | |||||||||
5B5C | 1 | BANKM | Copy last byte output to Port 7FFD | |||||||||
5B5E | 1 | RAMERR | Error passed from ROM 1 to 3 via RAMRST. Also used by SAVE/LOAD as temp drive store | |||||||||
5B5F | 2 | BAUD | RS232 bit period in T states/26. Set by FORMAT LINE | |||||||||
5B61 | 2 | SERFL | Second-character-received flag & data | |||||||||
5B63 | 1 | COL | Current column from 1 to width | |||||||||
5B64 | 1 | WIDTH | Paper column width | 80 | ||||||||
5B65 | 1 | TVPARS | Number of inline parameters expected by RS232 | |||||||||
5B66 | 1 | FLAGS3 | Various Flags
| |||||||||
5B67 | 1 | BANK678 | Copy of last byte output to port 1FFD | |||||||||
5B68 | 1 | XLOC | Hold X location when using the unexpanded COPY command | |||||||||
5B69 | 1 | YLOC | Hold Y location when using the unexpanded COPY command | |||||||||
5B6A | 2 | OLDSP | Old SP (stack pointer) when TSTACK is in use. | |||||||||
5B6C | 2 | SYNRET | Return address for ONERR | |||||||||
5B6E | 5 | LASTTV | Last value printed by calculator | |||||||||
5B73 | 2 | RCLINE | Current line being renumbered | |||||||||
5B75 | 2 | RCSTART | Starting line number for renumbering | 10 | ||||||||
5B77 | 2 | RCSTEP | Incremental value for renumbering | 10 | ||||||||
5B79 | 1 | LODDRV | Drive for LOAD VERIFY or MERGE
| |||||||||
5B7A | 1 | SAVDRV | Drive for SAVE
| |||||||||
5B7B | 1 | DUMPLF | Holds the number of 1/216ths user for line feeds in 'COPY EXP'. If a dump cannot fit A4 set to 8 to reduce size of dump. | 9 | ||||||||
5B7C | 8 | STRIP1 | Stripe 1 bitmap | |||||||||
5B84 | 8 | STRIP2 | Strip2 2 bitmap. Extends to 5B8B | |||||||||
5BFF | -115 | TSTACK | Temp stack (Grows DOWN from here). Used when Page 7 is switched in at top of memory while editing or using +3DOS. It can grow down to STRIP1 safely giving 115 bytes | |||||||||
5C00 | 8 | KSTATE | Used for reading keyboard | |||||||||
5C08 | 1 | LASTK | Stores newly pressed key | |||||||||
5C09 | 1 | REPDEL | Time in 1/50s before key repeats | 35 | ||||||||
5C0A | 1 | REPPER | Delay in 1/50s between key repeats | 5 | ||||||||
5C0D | 1 | KDATA | Stores 2nd byte of colour controls entered from keyboard | |||||||||
5C0E | 2 | TVDATA | Stores bytes of colour, AT and TAB controls going to TV | |||||||||
5C10 | 38 | STRMS | Addresses of channels attached to streams | |||||||||
5C36 | 2 | CHARS | 256 less than address of character set starting with space and up to (C). | |||||||||
5C38 | 1 | RASP | Length of warning buzz | |||||||||
5C39 | 1 | PIP | Length of keyboard click | |||||||||
5C3A | 1 | ERRNR | 1 less than report code. Starts at 255 for -1 | |||||||||
5C3B | 1 | FLAGS | Various flags for BASIC | |||||||||
5C3C | 1 | TVFLAG | Flags associated with the TV | |||||||||
5C3D | 2 | ERRSP | Address of item on machine stack to be used as error return | |||||||||
5C3F | 2 | LISTSP | Address of return address from automatic listing | |||||||||
5C41 | 1 | MODE | Specifies K, L, C, E or G cursor | |||||||||
5C42 | 2 | NEWPPC | Line to be jumped to | |||||||||
5C44 | 1 | NSPPC | Statement number in line to be jumped to. Poking first NEWPPC then NSPPC forces a jump to a specific statement in a line. | |||||||||
5C45 | 2 | PPC | Line number of statement currently being executed | |||||||||
5C47 | 1 | SUBPPC | Number within line of statement currently being executed | |||||||||
5C48 | 1 | BORDCR | Border colour multiplied by 8; also contains attributes normally used for lower half of the screen | |||||||||
5C49 | 2 | EPPC | Number of current line (with program cursor) | |||||||||
5C4B | 2 | VARS | Address of variables | |||||||||
5C4D | 2 | DEST | Address of variable in assignment | |||||||||
5C4F | 2 | CHANS | Address of channel data | |||||||||
5C51 | 2 | CHURCHL | Address of information currently being used for IO | |||||||||
5C53 | 2 | PROG | Address of BASIC program | |||||||||
5C55 | 2 | NXTLIN | Address of next line in program | |||||||||
5C57 | 2 | DATADD | Address of terminator of last DATA item | |||||||||
5C59 | 2 | ELINE | Address of command being typed in | |||||||||
5C5B | 2 | KCUR | Address of cursor | |||||||||
5C5D | 2 | CHADD | Address of next character after the argument of PEEK or the NEWLINE at the end of a POKE statement. | |||||||||
5C5F | 2 | XPTR | Address of character after the [] marker | |||||||||
5C61 | 2 | WORKSP | Address of temporary workspace | |||||||||
5C63 | 2 | STKBOT | Address of bottom of calculator stack | |||||||||
5C65 | 2 | STKEND | Address of start of space space | |||||||||
5C67 | 1 | BREG | Calculators B register | |||||||||
5C68 | 2 | MEM | Address of area used for calculators memory, usually MEMBOT | MEMBOT | ||||||||
5C6A | 1 | FLAGS2 | More flags
| |||||||||
5C6B | 1 | DFSZ | Number of lines (including one blank) in lower part of the screen | |||||||||
5C6C | 2 | STOP | Number of the top program line in automatic listings | |||||||||
5C6E | 2 | OLDPPC | Line number to which CONTINUE jumps | |||||||||
5C70 | 1 | OSPPC | Number within line of statement to which CONTINUE jumps | |||||||||
5C71 | 1 | FLAGX | Various flags | |||||||||
5C72 | 2 | STRLEN | Length of string type destination in assignment | |||||||||
5C74 | 2 | TADDR | Address of next item in syntax table | |||||||||
5C76 | 2 | SEED | The seed for the RNG. Variable set using RANDOMIZE | |||||||||
5C78 | 3 | FRAMES | 3 byte (least significant first) frame counter incremented every 20ms | |||||||||
5C7B | 2 | UDG | Address of first user defined graphic | |||||||||
5C7D | 1 | COORDX | X coordinate of last point plotted | |||||||||
5C7E | 1 | COORDY | Y coordinate of last point plotted | |||||||||
5C7F | 1 | PPOSN | 33 column number of printer position | |||||||||
5C80 | 2 | PRCC | Full address of next position for LPRINT. Only used for ZX printer, not in 128K mode. | |||||||||
5C82 | 2 | ECHOE | 33 column number & 24 line number of end of input buffer | |||||||||
5C84 | 2 | DFCC | Address in display file of PRINT position | |||||||||
5C86 | 2 | DFCCL | Like DFCC but for lower part of screen | |||||||||
5C88 | 2 | SPOSN | 33 col & 24 line number for PRINT position | |||||||||
5C8A | 2 | SPOSNL | Like SPOSN but for lower part of screen | |||||||||
5C8C | 1 | SCRCT | Counts scrolls, always 1 more than number of scrolls to perform before scroll. | |||||||||
5C8D | 1 | ATTRP | Permanent current colours | |||||||||
5C8E | 1 | MASKP | Used for transparent colour. Any bit that is 1 shows bit taken from screen and not ATTRP | |||||||||
5C8F | 1 | ATTRT | Like ATTRP but for temporary colours | |||||||||
5C90 | 1 | MASKT | Like MASKP but for temporary colours | |||||||||
5C91 | 1 | PFLAG | More flags | |||||||||
5C92 | 30 | MEMBOT | Calculators memory area used to store numbers not convenient to store on the calculator stack | |||||||||
5CB0 | 2 | NMIADD | Address of users NMI routine. Older machines NMI didn't work well so was marked as UNUSED so can cause issues on +3 if user code uses this | |||||||||
5CB2 | 2 | RAMTOP | Address of last byte of BASIC system area | |||||||||
5CB4 | 2 | PRAMT | Address of last byte of physical RAM | |||||||||
5CB6 | SYSVAREND | Start of Channel information, usually value in (CHANS) | ||||||||||
5CC0 | 12 | RESERVED_MMAP | Marked reserved in 48k memory map | |||||||||
5CCB | BASE_AVAIL_MEM | Base of available memory |
Name | Value | Description |
---|---|---|
BAS_CODE | 175 | CODE |
BAS_CLEAR | 253 | CLEAR statement |
BAS_LOAD | 239 | LOAD statement |
BAS_PRINT | 245 | PRINT statement |
BAS_RANDOMIZE | 249 | RANDOMIZE statement |
BAS_USR | 192 | USR function |
This table is currently incomplete, but it is enough for the Machine Code examples.
+3DOS is the Disk Operating System of the Spectrum +3. It is contained in ROM 2 on those machines and provides support for:
The +2A (not the +2) has the exact same ROM's as the +3, it just has a Cassette tape instead of a 3" floppy drive. As such, +3DOS is available but only provides:
Another method to determine if a machine is a +3 or a +2A is to inspect bit 4 of FLAGS3 (0x5B66). If the bit is set then a disk interface is present, hence a +3. If the bit is reset then no disk is present, hence a +2A or a +3 with no disk interface or the interface disabled.
+3DOS uses the CP/M file structure, subject to the following restrictions:
Function | Address | Description |
---|---|---|
DOS_INITIALISE | 0100 | Initialise +3DOS |
None
Function | Address | Description |
---|---|---|
DOS_VERSION | 0103 | Return DOS issue and version numbers |
Get the DOS issue and version numbers.
None
Function | Address | Description |
---|---|---|
DOS_OPEN | 0106 | Open and/or Create a file |
Create and/or open a file
Register | Content |
---|---|
B | File number 0…15 |
C | Access mode required |
D | Create action |
E | Open action |
HL | Address of filename, no wildcards. Terminated with 0xFF |
Open | Action | |||||||
---|---|---|---|---|---|---|---|---|
0 | Error - File already exists. | |||||||
1 |
Open the file, read the header (if any). Position file pointer after header. | |||||||
2 |
Open the file, ignore any header. Position file pointer at 000000h (0). | |||||||
3 |
Assume given filename is 'filename.type'.
| |||||||
4 |
Erase existing version. Follow create action. |
Create | Action | |||||||
---|---|---|---|---|---|---|---|---|
0 | Error - File does not exists. | |||||||
1 |
Create and open new file with a header. Position file pointer after header. | |||||||
2 |
Create and open new file without a header. Position file pointer at 000000h (0). |
This was only discovered during testing by looking at the ROM 2 disassembly.
Function | Address | Description |
---|---|---|
DOS_CLOSE | 0109 | Close a file |
Close a file
Register | Content |
---|---|
B | File number 0…15 |
Function | Address | Description |
---|---|---|
DOS_ABANDON | 010C | Abandon a file |
Abandon a file
Similar to DOS CLOSE, except that any header, or data, or directory data yet to be written to disk is discarded. This routine should only be used to force a file closed in the event that DOS CLOSE is unable to close the file (for example, if the media is damaged or permanently changed or removed).
Register | Content |
---|---|
B | File number 0…15 |
Function | Address | Description |
---|---|---|
DOS_REF_HEAD | 010F | Point to header data for this file |
Point at the header data for this file.
The header data area is 8 bytes long and may be used by the caller for any purpose whatsoever. It is available even if the file does not have a header; however, only files with a header and opened with write access will have the header data recorded on disk.
Note that +3 BASIC uses these 8 bytes (see the note under DOS OPEN which gives the details). If creating a file that will subsequently be LOADed within BASIC, then those bytes should be filled with the relevant values.
Register | Content |
---|---|
B | File number 0…15 |
The address in IX is the +3 BASIC Header structure which is 8 bytes long. (IX+0) is the file type, (IX+1) the file length and (IX+3) param 1.
Function | Address | Description |
---|---|---|
DOS_READ | 0112 | Read bytes from a file into memory |
Read bytes from a file into memory, advancing the file pointer in the process.
This routine does not consider any soft-EOF in the file. Attempting to read past the EOF will produce an error.
Register | Content |
---|---|
B | File number 0…15 |
C | Page number for addresses 0xC000…0xFFFF |
DE | Number of bytes to read. 0 means 64K |
HL | Address of where to write the bytes to |
The value of C is only used when HL is within the upper 16K of memory (0xC000…0xFFFF). If HL is in this range then C is the RAM bank to use. For most purposes C should be set to 0 which is the default RAM bank mapped to that region.
Function | Address | Description |
---|---|---|
DOS_WRITE | 0115 | Write bytes from memory into a file |
Write bytes from memory into a file, advancing the file pointer in the process.
Register | Content |
---|---|
B | File number 0…15 |
C | Page number for addresses 0xC000…0xFFFF |
DE | Number of bytes to write. 0 means 64K |
HL | Address of where to read the bytes from |
The value of C is only used when HL is within the upper 16K of memory (0xC000…0xFFFF). If HL is in this range then C is the RAM bank to use. For most purposes C should be set to 0 which is the default RAM bank mapped to that region.
Function | Address | Description |
---|---|---|
DOS_READ_BYTE | 0118 | Read byte from a file, check for soft-EOF |
Read a byte from a file, advancing the file pointer in the process. It tests for a soft EOF (0x1A) but it is possible to read past this. Reading to the hard EOF will return an error.
Register | Content |
---|---|
B | File number 0…15 |
Function | Address | Description |
---|---|---|
DOS_WRITE_BYTE | 011B | Write byte to a file |
Write a byte to a file, advancing the file pointer in the process.
Register | Content |
---|---|
B | File number 0…15 |
C | Byte to write |
Function | Address | Description |
---|---|---|
DOS_CATALOG | 011E | Get the disk catalog |
Fills a buffer with part of the directory (sorted).
The filename specifies the drive, user and a (possibly ambiguous) filename.
Since the size of a directory is variable (and may be quite large), this routine permits the directory to be catalogued in a number of small sections. The caller passes a buffer pre-loaded with the first required filename, or zeroes for the start of the directory. The buffer is loaded with part (or all, if it fits) of the directory sorted in ASCII order. If more of the directory is required, this routine is re-called with the buffer re-initialised with the last file previously returned. This procedure is followed repeatedly until all of the directory has been catalogued.
Note that +3DOS format disks (which are the same as single-sided, single track AMSTRAD PCW range format disks) may have a maximum of 64 directory entries.
Register | Content |
---|---|
B | n+1 size of buffer in entries, must be >= 2 |
C |
Filter: Bit 0 = include system files if set Bits 1…7 reserved |
DE | Address of buffer, first entry initialised |
HL | Address of filename, wildcards permitted |
The buffer passed to this routine consists of 2 or more entries, with the first one initialised with the first filename required. It is valid for the first entry to be all zero's.
If the buffer is too small for the directory then it can be called again with entry 0 being a copy of entry n from the previous call.
Bytes | Length | Content | |
---|---|---|---|
0 | 7 | 8 | Filename in ASCII, left justified, space padding |
8 | 10 | 3 | Type in ASCII, left justified, space padding |
11 | 12 | 2 | File size in KB |
The file size is the disk space allocated, not the actual file size.
Function | Address | Description |
---|---|---|
DOS_FREE_SPACE | 0121 | Get free space on drive |
Return the amount of free space on a drive.
Register | Content |
---|---|
A | Drive letter A…P |
Function | Address | Description |
---|---|---|
DOS_DELETE | 0124 | Delete a file |
Delete an existing file.
The file must not be open on any file number.
Register | Content |
---|---|
HL | Address of filename, wildcards are permitted. |
Function | Address | Description |
---|---|---|
DOS_RENAME | 0127 | Get free space on drive |
Return the amount of free space on a drive.
Register | Content |
---|---|
A | Drive letter A…P |
Function | Address | Description |
---|---|---|
DOS_BOOT | 012A | Boot from disk |
Boot from Disk
This routine loads a single bootstrap sector from the disk in drive A: into memory and enters it. This is for loading games or other operating systems.
None
When the bootstrap runs with the following memory configuration:
The bootstrap sector is on side 0, track 0, sector 1 of the disk. It is loaded into memory at 0xFE00 and entered at 0xFE10. Interrupts are disabled, and SP = 0xFE00.
The sum of all bytes in the sector must equal 3 MOD 256. Byte 15 in the sector can be used to adjust the sum to achive this. Bytes 0…15 of the sector hold the disk specification.
Memory Range | RAM Bank | |
---|---|---|
0x0000 | 0x3FFF | Bank 4 |
0x4000 | 0x7FFF | Bank 7 |
0x8000 | 0xBFFF | Bank 6 |
0xC000 | 0xFFFF | Bank 3 |
Function | Address | Description |
---|---|---|
DOS_SET_DRIVE | 012D | Set the default drive |
Set the default drive (i.e. the drive implied by all filenames that do not specify a drive).
The default drive is initially A:
Does not access the drive, but merely checks that there is a driver for it (which does not imply that the drive exists).
This only affects routines that take filename parameters.
Register | Content |
---|---|
A | Drive letter A…P, 0xFF to get the default drive |
Function | Address | Description |
---|---|---|
DOS_SET_USER | 0130 | Set the default user |
Set the default user area, i.e. the user area implied by all filenames that do not specify a user number.
The default user number is initially 0.
This only affects routines that take filename parameters.
Register | Content |
---|---|
A | User 0…15, 0xFF to get the default user |
Function | Address | Description |
---|---|---|
DOS_GET_POSITION | 0133 | Get the file pointer |
Returns the current position in the file
Register | Content |
---|---|
B | File number 0…15 |
Function | Address | Description |
---|---|---|
DOS_SET_POSITION | 0136 | Set the file pointer |
Sets the file pointer. This does not access the disk, nor does it check if the file pointer is >= 8 megabytes.
Register | Content |
---|---|
B | File number 0…15 |
E HL |
File pointer 0x000000…0xFFFFFF (16Mb) E is most significant byte, L least |
Function | Address | Description |
---|---|---|
DOS_GET_EOF | 0139 | Get the end of file (EOF) position |
Get the end of file (EOF) file position greater than all written byte positions. Does not affect the file pointer. Does not consider soft-EOF.
Register | Content |
---|---|
B | File number 0…15 |
Function | Address | Description |
---|---|---|
DOS_GET_1346 | 013C | Set current cache/ramdisk location |
Get the current location of the cache and RAMdisk.
Pages 1, 3, 4, 6 are considered as an array of 128 sector buffers (numbered 0...127), each of 512 bytes. The cache and RAMdisk occupy two separate (contiguous) areas of this array.
Any unused sector buffers may be used by the caller.
Note that the sizes may be smaller than those specified in DOS_SET_1346, as there is an (unpublished) maximum size of cache and a minimum size of RAMdisk (4 sectors).
None
Function | Address | Description |
---|---|---|
DOS_SET_1346 | 013F | Rebuild the sector cache and RAM disk |
Rebuild the sector cache and RAM disk.
This routine is used to make some store available to the user, or to return store to DOS. Note that if the RAM disk is moved, or its size is changed, then all files thereon are erased.
Pages 1, 3, 4, 6 are considered as an array of 128 sector buffers (numbered 0...127), each of 512 bytes. The cache and RAMdisk occupy two separate (contiguous) areas of this array.
The location and size of the cache and RAMdisk can be specified separately; any remaining buffers are unused by DOS and are available to the caller.
Note that the sizes actually used may be smaller than those specified as in practice, there is a maximum cache size and a minimum size of RAMdisk (4 sectors).
A cache size of 0 will still work but will seriously impair the floppy disk performance.
This routine will fail if there are any files open on drive M:
Register | Content |
---|---|
D | First buffer for cache |
E | Number of cache sector buffers |
H | First buffer for RAM disk |
L | Number of RAM disk sector buffers |
Note: E + L <= 128 |
Function | Address | Description |
---|---|---|
DOS_FLUSH | 0142 | Write any pending data to this drive |
Write any pending headers, data, directory entries for this drive.
This routine ensures that the disk is up-to-date. It can be called at any time, even when files are open.
Register | Content |
---|---|
A | Drive A…P |
Function | Address | Description |
---|---|---|
DOS_SET_ACCESS | 0145 | Change access mode of an open file |
Try to change the access mode of an open file.
This routine will fail if the file is already open, in an incompatible access mode, or if write access is required for a read-only file or disk.
Register | Content |
---|---|
B | File number 0…15 |
C |
Access mode required: Bits 0…2: 1 = exclusive read 2 = exclusive write 3 = exclusive read/write 5 = shared read Bits 3…7 =0 as reserved |
Function | Address | Description |
---|---|---|
DOS_SET_ATTRIBUTES | 0148 | Set a files attributes |
Set a file's attributes.
Only the file attributes f1'...f4', t1'...t3' can be set or cleared. The interface attributes f5'...f8' are always 0.
This routine first sets the attributes specified in D, then clears those attributes specified in E, i.e. E has priority.
Register | Content |
---|---|
D | Attributes to set |
E | Attributes to clear |
HL | Address of filename, wildcards permitted |
Bit | Attribute | Bit | Attribute | |
---|---|---|---|---|
0 | t3 | Archive | 3 | f4 |
1 | t2 | System | 4 | f3 |
2 | t1 | Read Only | 5 | f2 |
6 | f1 |
Function | Address | Description |
---|---|---|
DOS_OPEN_DRIVE | 014B | Open drive as a single file |
Open the disk in this drive as a single file.
The whole disk is presented as a single file regardless of any real files on the disk. This routine can be used to examine/poke directories, files, etc. It should not be used by the uninitiated, the faint-hearted, or by anyone who values their files!
Sets file pointer to 0x000000 (0).
If there are any files open on this drive from other file numbers with shared-read access, then the disk can only be opened with shared-read access from this file number.
If there are any file open on this drive from other file numbers with exclusive access, then the disk cannot be opened from this file number.
Register | Content |
---|---|
A | Drive A…P |
B | File number 0…15 |
C |
Access mode required: Bits 0…2: 1 = exclusive read 2 = exclusive write 3 = exclusive read/write 5 = shared read All other bits are reserved |
Function | Address | Description |
---|---|---|
DOS_SET_MESSAGE | 014E | Enable/disable disk error messages |
Enable/disable disk error messages.
This should be used to make +3DOS aware of your own ALERT subroutine. When +3DOS detects an error, it will call your ALERT subroutine, passing to it the values documented below. The ALERT subroutine should print the text of the message that +3DOS passes it, then should wait for the user to press a key. If the key is in the reply string (that +3DOS also passes - version V1.0 only), then a 'ret' should be made with A = 0, 1 or 2, or containing the character (depending on the version of +3DOS).
Register | Content |
---|---|
A | Enable 0xff or disable 0x00 |
HL | Address of ALERT routine if enabled |
Note that if you are substituting your own ALERT subroutine, the 'entry conditions' are the conditions passed to your subroutine and the 'exit conditions' are the values that your subroutine must produce and the registers you are allowed to corrupt.
There are two routine interfaces for ALERT, depending on which version of +3DOS is installed.
If you provide an ALERT function, you should have two subroutines, or one with switchable entry and exit conditions, and check the +3DOS version number before deciding which one to use.
Register | Content |
---|---|
DE | Address of reply string in page 7 terminated by 0xFF |
HL | Address of error message in page 7 terminated by 0xFF |
The second version allows the user to provide non-UK error messages and is generally more flexible, is present in +3DOS versions V1.1 and upwards.
Register | Content |
---|---|
B | Error number |
C | Drive A…P |
D | Logical track if required by message |
E | Logical sector if required by message |
HL | Address of UK error message in page 7 terminated by 0xFF |
Function | Address | Description |
---|---|---|
DOS_REF_XDPB | 0151 | Point at XDPB for this drive |
Point at the XDPB for this drive. (The XDPB is required by the floppy disk driver routines.)
Register | Content |
---|---|
A | Drive letter A…P |
Function | Address | Description |
---|---|---|
DOS_MAP_A | 0154 | Map drive B to unit 0 or 1 |
Map drive B: to unit 0 or unit 1. This routine will fail if drive B: has files open.
If mapping B: to unit 0, then each time unit 0 is accessed, a check is made that the drive mapping is correct. If it isn't, then a reverse call to CHANGE DISK is made, to ask the user to change the disk in unit 0.
If mapping B: to unit 1, then if unit 1 does not exist, drive B: is disabled.
Register | Content |
---|---|
C | Unit 0 or 1 |
HL | Address of change disk routine if unit = 0 |
If you are substituting your own CHANGE DISK subroutine, the 'entry conditions' are the conditions passed to your subroutine, and the 'exit conditions' are registers you are allowed to corrupt.
Register | Content |
---|---|
A | Logical drive A…P |
HL | Address of message in page 7 terminated by 0xFF |
The following are the floppy disk driver routines. The unit number is 0…3 for the uPD765A. On the +3, unit 0 is drive A: and unit 1 is drive B:, or optionally, both A: and B: may be mapped onto unit 0. Units 2 and 3 are not used.
With the exception of DD_INTERFACE, none of these routines may be called if the floppy disk interface is not present.
All routines assume that interrupts are enabled on entry, and will still be enabled on exit.
Function | Address | Description |
---|---|---|
DD_INTERFACE | 0157 | Check for the disk drive interface |
Is the floppy disk drive interface present?
This information is also held by BASIC in bit 4 of the FLAGS3 system variable.
None
Function | Address | Description |
---|---|---|
DD_INIT | 015A | Initialise the disk driver |
Initialise the disk driver
None
Function | Address | Description |
---|---|---|
DD_SETUP | 015D | Setup disk parameters |
Set up disk parameters. Send a specify command.
Register | Content |
---|---|
HL | Address of parameter block |
Byte | Content |
---|---|
0 | Motor on time, unit=100ms |
1 | Motor off time, unit=100ms |
2 | Write off time, unit=10ms |
3 | Head settle time, unit=ms |
4 | Step rate, unit=ms |
5 | Head unload time, unit=32ms, 32…480 |
6 | (Head load time *2)+1, unit=4ms, 4…508 |
Function | Address | Description |
---|---|---|
DD_SET_RETRY | 0160 | Set try/retry count |
Set the try and retry count. A value of 1 will try the operation once with no retries.
Register | Content |
---|---|
A | Try/Retry count >= 1 |
Function | Address | Description |
---|---|---|
DD_READ_SECTOR | 0163 | Read a sector |
Read a sector
Register | Content |
---|---|
B | Page for 0xC000…0xFFFF |
C | Unit 0 or 1 |
D | Logical track, 0 base |
E | logical sector, 0 base |
HL | Address of buffer |
IX | Address of XDPB |
Function | Address | Description |
---|---|---|
DD_WRITE_SECTOR | 0166 | Write a sector |
Write a sector
Register | Content |
---|---|
B | Page for 0xC000…0xFFFF |
C | Unit 0 or 1 |
D | Logical track, 0 base |
E | logical sector, 0 base |
HL | Address of buffer |
IX | Address of XDPB |
Function | Address | Description |
---|---|---|
DD_CHECK_SECTOR | 0169 | Check a sector |
Check a sector. (Uses the uPD765A scan equal command.)
Checks that the sector on disk is the same as the copy in memory.
Note that FFh (255) on disk or in memory always matches anything (see uPD765A specification for further details).
Register | Content |
---|---|
B | Page for 0xC000…0xFFFF |
C | Unit 0 or 1 |
D | Logical track, 0 base |
E | logical sector, 0 base |
HL | Address of buffer |
IX | Address of XDPB |
Function | Address | Description |
---|---|---|
DD_FORMAT | 016C | Format a track |
Format a track. (Uses the uPD765A format track command.)
Register | Content |
---|---|
B | Page for 0xC000…0xFFFF |
C | Unit 0 or 1 |
D | Logical track, 0 base |
E | Filler byte, usually 0xE5 |
HL | Address of format buffer |
IX | Address of XDPB |
The format buffer contains 4 bytes for each sector:
Byte | Content | Range |
---|---|---|
C | Track Number | 0…39 |
H | Head Number | Always 0 on a standard +3 single sided drive |
R | Sector Number | 0…255 |
N | Log2(sectorSize)-7 | 2 for 512 byte sectors |
Function | Address | Description |
---|---|---|
DD_READ_ID | 016F | Read a sector identifier |
Read a sector identifier
Register | Content |
---|---|
C | Unit 0 or 1 |
D | Logical track, 0 base |
IX | Address of XDPB |
Function | Address | Description |
---|---|---|
DD_TEST_UNSUITABLE | 0172 | Check disk is suitable to write to |
Check that disk is suitable to write to. A single track disk will not work in a double track drive, and vice versa.
Register | Content |
---|---|
C | Unit 0 or 1 |
IX | Address of XDPB |
Function | Address | Description |
---|---|---|
DD_LOGIN | 0175 | Login a new disk |
Log in a new disk. Initialise the XDPB. This routine does not affect or consider the freeze flag.
Register | Content |
---|---|
C | Unit 0 or 1 |
IX | Address of XDPB |
Function | Address | Description |
---|---|---|
DD_SEL_FORMAT | 0178 | Select a standard format |
Initialise an XDPB for a standard format. This routine does not affect or consider the freeze flag.
Register | Content |
---|---|
A |
Disk type: 0 = Spectrum +3 (Amstrad PCW DD, SS, ST) 1 = Amstrad CPC range system format 2 = Amstrad CPC range data-only format 3 = Amstrad PCW range DD, SS, DT Any other value returns an error |
IX | Address of XDPB |
Function | Address | Description |
---|---|---|
DD_ASK_1 | 017B | Check to see if unit 1 is present |
Check to see if unit 1 is present. BASIC holds this information in bit 5 of the FLAGS3 system variable.
Turn motor on.
Fetch drive status.
If unit 1 is not-ready and write-protected, then unit 1 is missing. Start motor off timeout.
Note that this routine can be fooled by disks which are almost, but not quite, inserted in the drive.
This routine assumes that when a disk is not in the drive, then write-protect is true. This is indeed the case for 3 inch and 8 inch disk drives, but is not the case for 5 1/4 inch disk drives.
None
Function | Address | Description |
---|---|---|
DD_DRIVE_STATUS | 017E | Check drive status |
Issue a sense drive status command.
Register | Content |
---|---|
C |
Unit/head Bits 0…1 Unit 0…3 Bit 2 Head Bits 3…7 = 0 |
Function | Address | Description |
---|---|---|
DD_EQUIPMENT | 0181 | Ask what type of drive |
Ask what type of drive this is (i.e. single/double track, single/double sided).
Track information can only be determined once a disk has been seen and had its type identified during logging in.
Side information can only be detected after a double sided disk has been seen and has its type identified during logging in.
Register | Content |
---|---|
C | Unit 0 or 1 |
IX | Address of XDPB |
Function | Address | Description |
---|---|---|
DD_ENCODE | 0184 | Set copy protection encode routine |
Set the copy protection ENCODE subroutine.
Copy protected disks have some of their track and sector numbers encoded on disk. Before each disk access, the ENCODE subroutine is called to encode the physical track and sector numbers.
These encoded track and sector numbers must match those in the sector identifier.
Note that tracks 0…2 on either side of a disk should not be encoded.
Register | Content |
---|---|
A | Enable 0xFF or disable 0x00 |
HL | If enabled address of ENCODE routine |
If you are substituting your own ENCODE subroutine, the 'entry conditions' are the conditions passed to your subroutine, and the 'exit conditions' are the values that your subroutine must produce and the registers you are allowed to corrupt.
Register | Content |
---|---|
C |
Unit/Side Bits 0…1 = unit, Bit 2 = side |
D | Physical track |
E | Physical sector |
IX | Address of DPB |
Function | Address | Description |
---|---|---|
DD_L_XDPB | 0187 | Initialise XDPB for a given format |
Initialise an XDPB for a given format.
This routine does not affect or consider the freeze flag.
Register | Content |
---|---|
DE | Address of source disk specification |
IX | Address of destination XDPB |
Function | Address | Description |
---|---|---|
DD_L_DPB | 018A | Initialise DPB for a given format |
Initialise an DPB for a given format.
This routine does not affect or consider the freeze flag.
Register | Content |
---|---|
DE | Address of source disk specification |
IX | Address of destination DPB |
Function | Address | Description |
---|---|---|
DD_L_SEEK | 018D | Seek to required track |
Seek to required track. Retry if failure.
Register | Content |
---|---|
C | Unit/head: Bits 0…1 unit, Bit 2 head |
D | Track |
IX | Address of destination XDPB |
Function | Address | Description |
---|---|---|
DD_L_READ | 0190 | Low level uPD765A read command |
Low level uPD765A read command.
Register | Content |
---|---|
HL | Address of parameter block |
Bytes | Length | Content | |
---|---|---|---|
0 | 0 | 1 | Page for 0xC000…0xFFFF |
1 | 2 | 2 | Address of buffer |
3 | 4 | 2 | Number of bytes to transfer |
5 | 5 | 1 | Number of command bytes n |
6 | 5+n | n | Command bytes |
Function | Address | Description |
---|---|---|
DD_L_WRITE | 0193 | Low level uPD765A write command |
Low level uPD765A write command.
Register | Content |
---|---|
HL | Address of parameter block |
Bytes | Length | Content | |
---|---|---|---|
0 | 0 | 1 | Page for 0xC000…0xFFFF |
1 | 2 | 2 | Address of buffer |
3 | 4 | 2 | Number of bytes to transfer |
5 | 5 | 1 | Number of command bytes n |
6 | 5+n | n | Command bytes |
Function | Address | Description |
---|---|---|
DD_L_ON_MOTOR | 0196 | Turn on motor |
Turn on the motor. Wait for the motor on time as set by DD SETUP.
None
Function | Address | Description |
---|---|---|
DD_L_T_OFF_MOTOR | 0199 | Start motor off timeout |
Start motor off timeout.
None
Function | Address | Description |
---|---|---|
DD_L_OFF_MOTOR | 019C | Turn off motor |
Turn off the motor.
None
Tape files have headers which contain some system information. +3DOS files may, or may not, have headers. All files created by BASIC's SAVE command will have headers.
The +3DOS header mechanism provides a dedicated 8 byte area in each headed file reserved for BASIC's use. The remainder of the header is reserved for +3DOS. This 8 byte header is utilised in files created by BASIC commands (see DOS OPEN description).
+3DOS files may have a single header in the first 128 bytes of the file - the header record. These headers are detected by a 'signature' and checksum. If the signature and checksum are as expected, then a header is present; if not, there is no header. Thus, it is possible, but unlikely, that a file without a header could be mistaken for one with a header.
Bytes | Length | Content | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
0 | 7 | 8 | +3DOS Signature | "PLUS3DOS" | ||||||
8 | 1 | Soft-EOF | 0x1A | |||||||
9 | 1 | Issue | 0x01 | |||||||
10 | 1 | Version | 0x00 | |||||||
11 | 14 | 4 | Length of file including header | |||||||
15 | 22 | 8 | +3 BASIC Header | |||||||
23 | 126 | 104 | Reserved | 0x00 | ||||||
127 | 1 | Checksum | Sum bytes 0…126 AND 0xFF |
Bytes | Length | Content | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | File Type | ||||||||
1 | 2 | 2 | File Length | |||||||
3 | 4 | 2 | Param 1 | |||||||
5 | 6 | 2 | Param 2 | |||||||
7 | 1 | Unused = 0x00 |
Type | File Description | Param 1 | Param 2 | ||||||
---|---|---|---|---|---|---|---|---|---|
0 | BASIC Program | Line number to start | Start of variable area relative to program start | ||||||
1 | Number Array |
Variable name, e.g. if DIM a() then this is 0x80 a=0x81, y=0x99
|
|||||||
2 | Character Array |
Variable name, e.g. if DIM a$() then this is 0x80 a=0xC1, y=0xD9
|
|||||||
3 | CODE | Start when saved | 32768 |
When a call to a +3DOS API fails then the carry flag will be false and the Accumulator will contain the error code. The errors are in two categories, Recoverable (Green) and Non-recoverable (Red):
Code | Error | ||||||||
---|---|---|---|---|---|---|---|---|---|
0 | 0x00 | Drive not ready | |||||||
1 | 0x01 | Disk is write protected | |||||||
2 | 0x02 | Seek fail | |||||||
3 | 0x03 | CRC data error | |||||||
4 | 0x04 | No data | |||||||
5 | 0x05 | Missing address mark | |||||||
6 | 0x06 | Unrecognised disk format | |||||||
7 | 0x07 | Unknown disk error | |||||||
8 | 0x08 | Disk changed whilst +3DOS was using it | |||||||
9 | 0x09 | Unsuitable media for drive | |||||||
20 | 0x14 | Bad filename | |||||||
21 | 0x15 | Bad parameter | |||||||
22 | 0x16 | Drive not found | |||||||
23 | 0x17 | File not found | |||||||
24 | 0x18 | File already exists | |||||||
25 | 0x19 | End of file | |||||||
26 | 0x1A | Disk full | |||||||
27 | 0x1B | Directory full | |||||||
28 | 0x1C | Read-only file | |||||||
29 | 0x1D | File number not open (or open with wrong access) | |||||||
30 | 0x1E | Access denied (file is in use already) | |||||||
31 | 0x1F | Cannot rename between drives | |||||||
32 | 0x20 | Extent missing (which should be there) | |||||||
33 | 0x21 | Uncached (software error) | |||||||
34 | 0x22 | File too big (trying to read or write past 8 megabytes) | |||||||
35 | 0x23 | Disk not bootable (boot sector is not acceptable to DOS BOOT) | |||||||
36 | 0x24 | Drive in use (trying to re-map or remove a drive with files open) |
Function | Address | Description |
---|---|---|
RST_0 | 0000 | Start the computer |
RST_1 | 0008 | Report an error |
RST_2 | 0010 | Print A to the output stream |
RST_3 | 0018 | Collect character |
RST_4 | 0020 | Collect Next character |
RST_5 | 0028 | FP Calculator |
RST_6 | 0030 | FP Calculator |
RST_7 | 0038 | Maskable Interrupt Handler |
DOS_INITIALISE | 0100 | Initialise +3DOS |
DOS_VERSION | 0103 | Return DOS issue and version numbers |
DOS_OPEN | 0106 | Open and/or Create a file |
DOS_CLOSE | 0109 | Close a file |
DOS_ABANDON | 010C | Abandon a file |
DOS_REF_HEAD | 010F | Point to header data for this file |
DOS_READ | 0112 | Read bytes from a file into memory |
DOS_WRITE | 0115 | Write bytes from memory into a file |
DOS_READ_BYTE | 0118 | Read byte from a file, check for soft-EOF |
DOS_WRITE_BYTE | 011B | Write byte to a file |
DOS_CATALOG | 011E | Get the disk catalog |
DOS_FREE_SPACE | 0121 | Get free space on drive |
DOS_DELETE | 0124 | Delete a file |
DOS_RENAME | 0127 | Get free space on drive |
DOS_BOOT | 012A | Boot from disk |
DOS_SET_DRIVE | 012D | Set the default drive |
DOS_SET_USER | 0130 | Set the default user |
DOS_GET_POSITION | 0133 | Get the file pointer |
DOS_SET_POSITION | 0136 | Set the file pointer |
DOS_GET_EOF | 0139 | Get the end of file (EOF) position |
DOS_GET_1346 | 013C | Set current cache/ramdisk location |
DOS_SET_1346 | 013F | Rebuild the sector cache and RAM disk |
DOS_FLUSH | 0142 | Write any pending data to this drive |
DOS_SET_ACCESS | 0145 | Change access mode of an open file |
DOS_SET_ATTRIBUTES | 0148 | Set a files attributes |
DOS_OPEN_DRIVE | 014B | Open drive as a single file |
DOS_SET_MESSAGE | 014E | Enable/disable disk error messages |
DOS_REF_XDPB | 0151 | Point at XDPB for this drive |
DOS_MAP_A | 0154 | Map drive B to unit 0 or 1 |
DD_INTERFACE | 0157 | Check for the disk drive interface |
DD_INIT | 015A | Initialise the disk driver |
DD_SETUP | 015D | Setup disk parameters |
DD_SET_RETRY | 0160 | Set try/retry count |
DD_READ_SECTOR | 0163 | Read a sector |
DD_WRITE_SECTOR | 0166 | Write a sector |
DD_CHECK_SECTOR | 0169 | Check a sector |
DD_FORMAT | 016C | Format a track |
DD_READ_ID | 016F | Read a sector identifier |
DD_TEST_UNSUITABLE | 0172 | Check disk is suitable to write to |
DD_LOGIN | 0175 | Login a new disk |
DD_SEL_FORMAT | 0178 | Select a standard format |
DD_ASK_1 | 017B | Check to see if unit 1 is present |
DD_DRIVE_STATUS | 017E | Check drive status |
DD_EQUIPMENT | 0181 | Ask what type of drive |
DD_ENCODE | 0184 | Set copy protection encode routine |
DD_L_XDPB | 0187 | Initialise XDPB for a given format |
DD_L_DPB | 018A | Initialise DPB for a given format |
DD_L_SEEK | 018D | Seek to required track |
DD_L_READ | 0190 | Low level uPD765A read command |
DD_L_WRITE | 0193 | Low level uPD765A write command |
DD_L_ON_MOTOR | 0196 | Turn on motor |
DD_L_T_OFF_MOTOR | 0199 | Start motor off timeout |
DD_L_OFF_MOTOR | 019C | Turn off motor |
CL_ALL | 0DAF | Clear the screen |
SWAP | 5B00 | Paging subroutine |
STOO | 5B10 | Paging subroutine. Entered with interrupts disabled and AF, BC on the stack. |
YOUNGER | 5B21 | Paging subroutine |
REGNUOY | 5B2A | Paging subroutine |
ONERR | 5B3A | Paging subroutine |
RAMRST | 5B5D | RST 8 instruction used by ROM 1 to report old errors to ROM 3 |
Function | Address | Description |
---|---|---|
CL_ALL | 0DAF | Clear the screen |
DD_ASK_1 | 017B | Check to see if unit 1 is present |
DD_CHECK_SECTOR | 0169 | Check a sector |
DD_DRIVE_STATUS | 017E | Check drive status |
DD_ENCODE | 0184 | Set copy protection encode routine |
DD_EQUIPMENT | 0181 | Ask what type of drive |
DD_FORMAT | 016C | Format a track |
DD_INIT | 015A | Initialise the disk driver |
DD_INTERFACE | 0157 | Check for the disk drive interface |
DD_L_DPB | 018A | Initialise DPB for a given format |
DD_L_OFF_MOTOR | 019C | Turn off motor |
DD_L_ON_MOTOR | 0196 | Turn on motor |
DD_L_READ | 0190 | Low level uPD765A read command |
DD_L_SEEK | 018D | Seek to required track |
DD_L_T_OFF_MOTOR | 0199 | Start motor off timeout |
DD_L_WRITE | 0193 | Low level uPD765A write command |
DD_L_XDPB | 0187 | Initialise XDPB for a given format |
DD_LOGIN | 0175 | Login a new disk |
DD_READ_ID | 016F | Read a sector identifier |
DD_READ_SECTOR | 0163 | Read a sector |
DD_SEL_FORMAT | 0178 | Select a standard format |
DD_SET_RETRY | 0160 | Set try/retry count |
DD_SETUP | 015D | Setup disk parameters |
DD_TEST_UNSUITABLE | 0172 | Check disk is suitable to write to |
DD_WRITE_SECTOR | 0166 | Write a sector |
DOS_ABANDON | 010C | Abandon a file |
DOS_BOOT | 012A | Boot from disk |
DOS_CATALOG | 011E | Get the disk catalog |
DOS_CLOSE | 0109 | Close a file |
DOS_DELETE | 0124 | Delete a file |
DOS_FLUSH | 0142 | Write any pending data to this drive |
DOS_FREE_SPACE | 0121 | Get free space on drive |
DOS_GET_1346 | 013C | Set current cache/ramdisk location |
DOS_GET_EOF | 0139 | Get the end of file (EOF) position |
DOS_GET_POSITION | 0133 | Get the file pointer |
DOS_INITIALISE | 0100 | Initialise +3DOS |
DOS_MAP_A | 0154 | Map drive B to unit 0 or 1 |
DOS_OPEN | 0106 | Open and/or Create a file |
DOS_OPEN_DRIVE | 014B | Open drive as a single file |
DOS_READ | 0112 | Read bytes from a file into memory |
DOS_READ_BYTE | 0118 | Read byte from a file, check for soft-EOF |
DOS_REF_HEAD | 010F | Point to header data for this file |
DOS_REF_XDPB | 0151 | Point at XDPB for this drive |
DOS_RENAME | 0127 | Get free space on drive |
DOS_SET_1346 | 013F | Rebuild the sector cache and RAM disk |
DOS_SET_ACCESS | 0145 | Change access mode of an open file |
DOS_SET_ATTRIBUTES | 0148 | Set a files attributes |
DOS_SET_DRIVE | 012D | Set the default drive |
DOS_SET_MESSAGE | 014E | Enable/disable disk error messages |
DOS_SET_POSITION | 0136 | Set the file pointer |
DOS_SET_USER | 0130 | Set the default user |
DOS_VERSION | 0103 | Return DOS issue and version numbers |
DOS_WRITE | 0115 | Write bytes from memory into a file |
DOS_WRITE_BYTE | 011B | Write byte to a file |
ONERR | 5B3A | Paging subroutine |
RAMRST | 5B5D | RST 8 instruction used by ROM 1 to report old errors to ROM 3 |
REGNUOY | 5B2A | Paging subroutine |
RST_0 | 0000 | Start the computer |
RST_1 | 0008 | Report an error |
RST_2 | 0010 | Print A to the output stream |
RST_3 | 0018 | Collect character |
RST_4 | 0020 | Collect Next character |
RST_5 | 0028 | FP Calculator |
RST_6 | 0030 | FP Calculator |
RST_7 | 0038 | Maskable Interrupt Handler |
STOO | 5B10 | Paging subroutine. Entered with interrupts disabled and AF, BC on the stack. |
SWAP | 5B00 | Paging subroutine |
YOUNGER | 5B21 | Paging subroutine |