Paged ROM Service Calls — Reference

Every paged ROM with a service entry receives these calls from MOS. See paged-roms for the dispatch mechanism (MOS scans ROMs in descending priority; first to set A=0 claims).

Entry to service routine:

  • A = reason code (table below)
  • X = this ROM’s slot number
  • Y = call-specific (see each row)

Exit:

  • Claimed: A=0, registers otherwise restored, RTS.
  • Not claimed: A unchanged, X/Y restored, RTS.
ANameY (entry)Notes
&00No operationHigher-priority ROM already claimed. Ignore.
&01Absolute workspace claimtop of fixed area (starts &0E)Reset only. Increment Y by pages claimed at &E00+.
&02Relative private workspacetop of absolute areaReset only. Store base at &DF0+rom_id. Increment Y by pages claimed.
&03Auto-boot0=boot, ≠0=init onlyReset. Highest FS responds (if no key pressed or own key pressed).
&04Unrecognised * commandoffset to text in &F2/&F3+YMain extension point. Read command via (&F2),Y.
&05Unknown interruptIRQ chain fallback. Service IRQ; RTS (not RTI).
&06BRK occurred&FD/&FE = error pointer, &F0 = SP at BRK.
&07Unknown OSBYTEA/X/Y at OSBYTE saved in &EF/&F0/&F1.
&08Unknown OSWORDSame &EF/&F0/&F1 save. OSWORDs &E0-&FF skip this and go to USERV.
&09*HELP text queryoffset to remainder of HELP cmd in &F2/&F3+YIf Y points to space/CR, print ROM identification.
&0AClaim absolute workspaceIssued by another ROM via OSBYTE &8F. Previous owner saves state, flags loss.
&0BNMI releasedfiling-system ID of previous ownerIssued via OSBYTE &8F.
&0CNMI claim&FFCurrent NMI owner returns its FS id in Y.
&0DRFS initialise15 - next_rom_numOnly claim if &F4 >= invert(Y). Store &F5, set &F6/&F7 = data start.
&0ERFS get bytenegative = OSRDRM available; positive = old OSReturn byte in Y. See naug-ch17-paged-roms for OS-version split.
&0FVectors claimedNotification — issued by a ROM after hooking a vector.
&10Close *SPOOL/*EXECIssued by FS during init.
&11Font implosion/explosionnew OSHWMElectron/Model B only. Language ROMs should adjust HIMEM.
&12Initialise filing systemFS id requestedClaim if your FS matches Y.
&13Char in RS423 bufferElectron only.
&14Char in printer bufferElectron only.
&15100 Hz pollsemaphore valueMaster/Electron only. Decrement Y by units serviced.
&16BEL requestElectron only (external sound).
&17SOUND buffer purgedElectron only.
&18Interactive *HELPMaster only. Issued after &09.
&21-&24Master HAZEL workspace claimsMaster only. As &01/&02 but in HAZEL (&C000-&DBFF).
&25Return FS infooffset in &F2/&F3+YMaster only. Write 11-byte FS info block.
&26*SHUT issuedMaster only. FS should select itself and close files.
&27Reset callMaster only. After power-on / hard / soft reset.
&28Unknown *CONFIGUREoffset in &F2/&F3+YMaster / Master Compact.
&29Unknown *STATUSoffset in &F2/&F3+YMaster / Master Compact.
&2ALanguage about to initMaster only. Activate language-support ROMs.
&2BReport memory sizeB+ only. DFS rewrites startup banner.
&2CCompact joystick calloffset in &200+Y to param blockMaster Compact only.
&FEPost-init Tube call&FF=Tube present, &00=absentAfter OSHWM set.
&FFTube main initBefore message generation. Tube hardware detected.

Implementing a service entry

Typical pattern:

.service
    CMP #&04           ; unknown *command?
    BEQ handle_cmd
    CMP #&09           ; *HELP?
    BEQ handle_help
    CMP #&02           ; private workspace claim?
    BEQ handle_wkspace
    RTS                ; not us — pass on (A unchanged)
 
.handle_cmd
    ; parse command line at (&F2),Y
    ; if matches our command:
    ;   do the work
    ;   LDA #0 : RTS    ; claimed
    ; else:
    ;   LDA #&04 : RTS  ; restore A, pass on

Always preserve A, X, Y across a non-claim path. Use PHA/PHA before testing if you need scratch registers.

Issuing a service call from user code

OSBYTE &8F is the user-facing entry to “tell every paged ROM something happened”:

LDA #&8F
LDX #reason     ; service call reason
LDY #y_param
JSR &FFF4
; on exit: X=0 if any ROM claimed

Common uses:

  • X=&0A — claim absolute workspace from current owner.
  • X=&0C, Y=&FF — claim NMI.
  • X=&0F — notify other ROMs that you’ve changed a vector.
  • X=&04 — invoke an unknown * command (less common; OSCLI is usually easier).

Performance note

Service-call dispatch costs:

  • Page in ROM: write &FE30.
  • JSR ROM service entry.
  • ROM tests A, decides, returns.
  • MOS pages in next ROM, repeats.

A full scan of 16 ROMs is ~hundreds of cycles. For high-frequency events (e.g. character output), service calls are too slow — extended vectors are the right answer (one paging operation per call, no scan).

The 100 Hz polling call (&15) is OK for periodic background work (CMOS RTC updates, mouse polling, etc.) but don’t do per-cycle work in it.

See also

  • paged-roms — ROM header format and dispatch mechanism.
  • paged-rom — Hardware paging register &FE30.
  • calls — OS vector table.

This wiki is curated by Claude following the LLM-Wiki methodology — a human curates source documents, the LLM compiles structured cross-linked markdown. Content may contain errors, omissions, or stale claims. For authoritative information refer to the original source documents in the bbc-documents GitHub archive.