Tutorial 7: Writing ROM Modules
Adapted from Spectranet: Tutorial 7.
Most of the Spectranet flash ROM is available to users. On classic hardware pages 0x00 to 0x03 are reserved for Spectranet itself, leaving pages 0x04 to 0x1F for modules and data. ROM modules are organized as 4K pages.
Module discovery
On reset, the Spectranet ROM scans flash pages looking for executable modules. A page is treated as a code module when its first byte is 0xAA. The second byte is the module ID. If the module provides a reset vector, that routine is called during startup.
This allows modules to initialize themselves, register BASIC extensions, or perform setup work.
Module header
A ROM module starts with a 16-byte table:
- byte 0: page signature,
0xAAfor a module - byte 1: ROM ID
- bytes 2-3: reset vector
- bytes 4-5: mount vector
- bytes 6-13: reserved vectors
- bytes 14-15: address of the identity string
Code begins at byte 16, which is address 0x2010 because modules are mapped into paging area B and assembled with ORG 0x2000.
Installing modules
Classic Spectranet includes a ROM programmer utility. It is available from the NMI menu as "Add and remove ROM modules". When adding a module, the Spectrum listens on TCP port 2000, and the ethup utility sends the module over the network.
Calling modules
MODULECALL lets programs call a module by ID. HL contains the call value: H is the ROM ID, and L is a function or command byte interpreted by the module.
include "spectranet.asm"
org 0x8000
ld hl, 0xFE00
call MODULECALL
ret
The call to MODULECALL is trapped by the Spectranet hardware, so it must be a real CALL instruction. Conditional calls and jumps do not trigger the paging mechanism.
If the Spectranet is already paged in, use the no-page form, such as RST MODULECALL_NOPAGE, to avoid the normal page-in/page-out gateway.
BASIC extensions from modules
A ROM module can register BASIC extensions from its reset vector. When the extension structure uses page value 0xFF, the ROM registration code records the current page in area B, so the module does not need to know where it was installed.