Skip to content

Instantly share code, notes, and snippets.

@damieng damieng/theghost.asm
Last active Nov 6, 2018

What would you like to do?
Ghost 48K compatibility for +2/+3 Sinclair ZX Spectrums
; Code by Mark Harris, published in Your Sinclair Issue 59
; Disassembly and comments by Damien Guard.
ORG 28000
; Setup pages to allow 48K ROM to be copied to RAM page 4.
LD A,0x14 ; 48K ROM at 0x0000, RAM page 4 at 0xc000
LD BC,0x7ffd ; 128K paging port
OUT (C),A ; Switch the pages
; Copy 48K ROM at 0x0000 to RAM at 0xc000.
LD HL,0x0000
LD DE,0xc000
LD BC,0x4000
; Put RAM copy of the ROM at 0x0000 in special protected paging mode.
LD A,0x05 ; Special paging mode, page 4 at 0xc000
LD BC,0x1ffd ; +2A/+3 special paging port
OUT (C),A ; Switch the pages
; Reduce ROM LOAD delay for contended RAM slowness.
LD A,0x07 ; 154 T states (was 0x16 - 358 T states)
LD (0x05e8),A ; LD_EDGE_1 ROM T-State delay address
; Apply various ROM patches to their original flow as the
; new routines they used at 0x3900-0x3d00 are going to be
; blow away and replaced by an interrupt table for IM2
; compatibility.
LD B,0x00
; Patch KEY_INIT to CALL KEYBOARD not 0x386e.
LD DE,0x004b ; KEY_INIT routine CALL address
LD C,0x02
; Restore original token code handling not 0x3a7e.
LD DE,0x0b52 ; Character print routine
LD C,0x04
; Restore REPORT_G logic not 0x3a29 routine.
LD DE,0x1349 ; REPORT_G 'command and space' logic
LD C,0x04
; Restore STMT-RET logic not 0x3a3b routine.
LD DE,0x1b7d ; STMT-RET break handling
LD C,0x04
; Restore STMT-NEXT logic not 0x3a4b routine.
LD DE,0x1bf4 ; STMT-NEXT
LD C,0x03
; Restore S_INKEY to use KEY_SCAN not 0x3a5a routine.
LD DE,0x2646 ; Key scanning routine
LD C,0x03
; New IM2 interrupt handler that will jump directly to 0xfff4.
LD DE,0x3c3c ; Empty space
LD C,0x03
; Append to the copyright message.
LD DE,0x1547 ; Copyright location after 'AMSTRAD'
LD C,0x09 ; Message to append is 9 bytes
; The original 48K machine ROM does not use 0x386e-0x3d00
; leaving it filled with 0xff bytes.
; Interrupt mode 2 (IM2) requires an interrupt table which is
; used in conjunction with the data bus to determine where to
; jump to.
; Rather than waste 257 bytes of RAM setting up their own
; interrupt table developers would point their IM2 routine at
; this unused space which would jump to 0xffff and put a
; JR instruction there which would read the relative address
; from 0x0000 (the ROM again) which is f3 resulting in a jump
; to 0xfff4.
; This code replaces that table with 0x3c instead which causes
; a jump to 0x3c3c which will have a JP 0xfff4 there.
LD HL,0x3900
LD DE,0x3901
LD BC,0x0300
LD (HL),0x3c
; Call ROM 'NEW' routine to restart.
JP 0x11b7
; Original call address of KEYBOARD in KEY_INIT
DEFW 0x02bf
; Original code at PO_T_UDG
SUB 0xa5
JR NC,0x6ddb
; Original code in REPORT_G
LD DE,0x1536
; Original code in STMT-RET
BIT 7,(IY+10)
; Original code in STMT-NEXT
RST 0x18
CP 0x0d
; Original code in S_INKEY
CALL 0x028e
; Indirect jump to original interrupt handler
JP 0xfff4
; Copyright message suffix
DEFM ' / Miktor'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.