Skip to main content

Tutorial 7: Writing ROM Modules

Source

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, 0xAA for 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.