;********************************************************************************
;** An Assembly File Listing to generate an 8K ROM for the MICRO-POKEer device **
;********************************************************************************

; -------------------------
; Last updated: 15-NOV-2010
; -------------------------

; This assembly source based on MICRO-POKEer version 1.6 ROM.
; Compiling this source will produce byte-exact ROM image.
; Tested with Sjasm 0.42 but may compile with other Z80 compilers.

        ORG $0000

; -----------------------------------
; KEYBOARD HANDLING RESTART (RST 00H)
; -----------------------------------

L0000:  JP      L0228           ; jump to KEY-MAIN

        DEFB    $00, $00, $00   ; 5 unused bytes
        DEFB    $00, $00

; ----------------------------
; SAVE BYTES RESTART (RST 08H)
; ----------------------------

L0008:  CALL    L14D5           ; wait for 1 second
        JP      L1000           ; jump to SA-BYTES

        DEFB    $00, $00        ; 2 unused bytes

; ----------------------------------
; TURBO LOAD BYTES RESTART (RST 10H)
; ----------------------------------

L0010:  JP      L10C8           ; jump to LD-BYTES TURBO version

        DEFB    $00, $00, $00   ; 5 unused bytes
        DEFB    $00, $00

; ----------------------------------
; TUROB SAVE BYTES RESTART (RST 18H)
; ----------------------------------

L0018:  CALL    L14D5           ; wait for 1 second
        JP      L1190           ; jump to SA-BYTES TURBO version

        DEFB    $00, $00        ; 2 unused bytes

; ------------------------
; UNUSED RESTART (RST 20H)
; ------------------------

L0020:  JP      $1224           ; this jumps to an unused area

        DEFB    $00, $00, $00   ; 5 unused bytes
        DEFB    $00, $00

; ------------------------
; UNUSED RESTART (RST 28H)
; ------------------------

L0028:  DEFB    $00, $00, $00   ; 8 unused bytes
        DEFB    $00, $00, $00
        DEFB    $00, $00

; ---------------------------------------
; THE KEYBOARD SCANNING RESTART (RST 30H)
; ---------------------------------------

L0030:  JP      L1770           ; jump to KEY-SCAN

        DEFB    $00, $00, $00   ; 5 unused bytes
        DEFB    $00, $00

; ------------------------
; UNUSED RESTART (RST 38H)
; ------------------------

L0038:  EI      
        RET     

        DEFB    $00, $00, $00   ; 6 unused bytes
        DEFB    $00, $00, $00

; $0040
        DEFM "MICRO-POKEer 1.6/00"

        DEFB    $00, $00, $00   ; 19 unused bytes
        DEFB    $00, $00, $00
        DEFB    $00, $00, $00
        DEFB    $00, $00, $00
        DEFB    $00, $00, $00
        DEFB    $00, $00, $00
        DEFB    $00

; ------------------------------------
; THE 'NON-MASKABLE INTERRUPT' ROUTINE
; ------------------------------------
; This is the main entry
; saves the current ZX Spectrum state
; and waits for a menu-key press

;; NMI-ENTRY
L0066:  PUSH    AF              ; save registers
        PUSH    HL
        LD      A,I             ; the Parity flag has state of IFF2
        PUSH    AF              ; IFF2 holds IFF1 which was the EI/DI state
        DI                      ; disable interrupts
        LD      A,R
        PUSH    AF
        PUSH    DE
        PUSH    BC
        EX      AF,AF'
        PUSH    AF
        EX      AF,AF'
        EXX     
        PUSH    HL
        PUSH    DE
        PUSH    BC
        EXX     
        PUSH    IX
        PUSH    IY

;; MAIN-KEYS
L007D:  RST     00H             ; Call KEY-MAIN to get
        LD      A,E             ; a keypress
        CP      D               ; wait until a valid
        JR      Z,L007D         ; key is pressed

        LD      A,E
        CP      $0D             ; R
        JR      Z,L00A7         ; jump to SAVE-TOTAL
        CP      $21             ; ENTER
        JP      Z,L052A         ; jump to EXIT-POKER routine
        CP      $1E             ; S
        JP      Z,L018E         ; jump to SAVE-SCREEN
        CP      $1D             ; W
        JP      Z,L130C         ; jump to WARM-RESTART routine
        CP      $19             ; L
        JP      Z,L012E         ; jump to LOAD-SCREEN (or LOAD-SNAPSHOT)
        CP      $10             ; M
        JP      Z,L1313         ; jump to MM-MAIN routine
        CP      $01             ; H
        CALL    Z,L17A8         ; call the SCROLL-MENU subroutine
        JR      L007D           ; or else jump back to MAIN-KEYS

;; SAVE-TOTAL
L00A7:  LD      A,D
        CP      $27             ; caps-shift pressed?
        JR      Z,L00ED         ; jump if capital 'R' pressed

        LD      DE,$11          ; if small 'r' pressed
        LD      IX,L1E94        ; save basic loader header
        LD      A,$00
        RST     08H             ; call save

        LD      DE,$10A         ; save basic loader data
        LD      IX,L026D
        LD      A,$FF
        RST     08H             ; call save

        LD      DE,$11          ; save screen header
        LD      IX,L1EA5
        LD      A,$00
        RST     08H             ; call save

        LD      HL,($5B00)      ; preserve data at $5800
        EXX
        LD      ($5B00),SP      ; save SP after attributes
        LD      DE,$1B02        ; save whole screen + SP
        LD      IX,$4000        ; screen start
        LD      A,$FF
        RST     08H             ; call save
        EXX
        LD      ($5B00),HL      ; restore data at $5800

        LD      DE,$A500        ; save whole memory (48K Spectrum!)
        LD      IX,$5B00        ; after attributes
        LD      A,$0F
        RST     08H             ; call save

        JP      L007D           ; jump back to MAIN-KEYS

; resume here if capital 'R' pressed

;; SAVE-TOTAL-TURBO
L00ED:  LD      DE,$0011        
        LD      IX,L1E94        ; save basic loader header
        LD      A,$00
        RST     18H             ; call turbo save

        LD      DE,$10A         ; save basic loader data
        LD      IX,L026D
        LD      A,$FF
        RST     18H             ; call turbo save

        LD      DE,$11          ; save screen header
        LD      IX,L1EA5
        LD      A,$00
        RST     18H             ; call turbo save

        LD      HL,($5B00)      ; preserve data at $5800
        EXX
        LD      ($5B00),SP      ; save SP after attributes
        LD      DE,$1B02        ; save whole screen + SP
        LD      IX,$4000        ; screen start
        LD      A,$FF
        RST     18H             ; call turbo save
        EXX
        LD      ($5B00),HL      ; restore data at $5800

        LD      DE,$A500        ; save whole memory (48K Spectrum!)
        LD      IX,$5B00        ; after attributes
        LD      A,$0F
        RST     18H             ; call turbo save

        JP      L007D           ; jump back to MAIN-KEYS

;; LOAD-SCREEN
L012E:  LD      A,D
        CP      $27             ; is it caps-shift?
        JP      Z,L014D         ; jump if capital 'L' pressed

        LD      DE,$11          ; if small 'l' pressed
        LD      IX,L0210        ; load screen header
        LD      A,$00
        SCF
        RST     10H             ; call turbo load

        LD      DE,$1B00        ; load screen data
        LD      IX,$4000
        LD      A,$FF
        SCF     
        RST     10H             ; call turbo load

        JP      L007D           ; jump back to MAIN-KEYS

; resume here if capital 'L' pressed

;; LOAD-SNAPSHOT
L014D:  LD      DE,$11          ; skip basic loader by loading it
        LD      IX,L0210        ; load screen header
        LD      A,$00           ; which is incorrect
        SCF                     ; because basic data follows
        RST     10H             ; call turbo load

        LD      DE,$10A         ; load basic loader data
        LD      IX,L026D
        LD      A,$FF
        SCF     
        RST     10H             ; call turbo load

        LD      DE,$11          ; load screen header
        LD      IX,L1EA5
        LD      A,$00
        SCF     
        RST     10H             ; call turbo load

        LD      DE,$1B02        ; load screen data + SP
        LD      IX,$4000
        LD      A,$FF
        SCF     
        RST     10H             ; call turbo load

        LD      HL,($5B00)
        EXX     
        LD      SP,$4009        ; give SP a short buffer
                                ; this will mess the top of
                                ; the screen but there is no
                                ; other place for SP
        LD      DE,$A500        ; load whole snapshot
        LD      IX,$5B00
        LD      A,$0F
        SCF     
        RST     10H             ; call turbo load

        JP      L0528           ; continue program execution
                                ; by jumping to EXIT-LOAD

;; SAVE-SCREEN
L018E:  LD      A,D
        CP      $27             ; is it caps-shift?
        JR      Z,L01AA         ; jump if capital 'S' pressed

        LD      DE,$0011        ; if small 's' pressed
        LD      IX,L0210        ; save screen header
        LD      A,$00
        RST     08H             ; call save

        LD      A,$FF
        LD      DE,$1B00        ; save screen data
        LD      IX,$4000
        RST     08H             ; call save

        JP      L007D           ; jump back to MAIN-KEYS

; resume here if capital 'S' pressed

;; SAVE-SCREEN-TURBO
L01AA:  LD      DE,$0011
        LD      IX,L0210        ; save screen header
        LD      A,$00
        RST     18H             ; call turbo save

        LD      A,$FF
        LD      DE,$1B00        ; save screen data
        LD      IX,$4000
        RST     18H             ; call turbo save

        JP      L007D           ; jump back to MAIN-KEYS

        LD      B,B             ; garbage code
        RST     18H             ; left here
        JP      L007D

        DEFM    "POPALL #52A-TOL MOVE"

; This part (1DA-205) is almost a direct copy of 52A-555
; but this 01DA routine never gets executed

L01DA:  POP     IY              ; restore registers
        POP     IX
        EXX
        POP     BC
        POP     DE
        POP     HL
        EXX
        EX      AF,AF'
        POP     AF
        EX      AF,AF'
        POP     BC
        POP     DE
        POP     AF
        LD      R,A
        POP     AF
        LD      I,A             ; restore EI/DI state by observing
        JP      PO,$0544        ; the restored parity flag
        EI
        JR      L01F5
        DI
L01F5:  POP     HL              ; This POP is late, should be before EI
        CP      $3F             ; Spectrum ROM sets I to $3F in START-NEW routine
        JR      NZ,L01FE        ; if I was not $3F we should restore IM 2 mode.
        IM      1               ; restore interrupt mode 1 - Spectrum ROM default
        JR      L0200
L01FE:  IM      2
L0200:  LD      A,$00           ; exit from MICRO-POKEer by
        OUT     ($7F),A         ; switching back to original Spectrum ROM
        POP     AF              ; this piece of code never gets executed
        RET                     ; these are the same in the original ROM

        POP     DE              ; garbage code
        POP     DE              ;
        JP      $007C           ;
        NOP
        NOP
        NOP
        NOP
        NOP

; screen header descriptor

L0210:  DEFB    $03             ; type code
        DEFM    "SCREEN    "    ; filename
        DEFB    $00, $1B        ; length 6192 bytes
        DEFB    $00, $40        ; start address $4000
        DEFB    $00, $80        ; unused $8000


        DEFB    $00, $00, $00   ; 7 unused bytes
        DEFB    $00, $00, $00
        DEFB    $00

; -------------------------
; KEYBOARD HANDLING ROUTINE
; -------------------------
; Calls the copy of the original Spectrum KEY-SCAN routine
; and produces a key-tone if a non-shift key pressed.
; The key(s) is returned in the DE register pair.
; It produces lower-pitched key-tone for Micro-monitor.

;; KEY-MAIN
L0228:  RST     30H             ; call routine KEY-SCAN: keys in D and E registers
        LD      A,E             ; compare D to E
        CP      D               ; if no keys pressed these are all $FF
        RET     Z               ; return if no key pressed

        CP      $18             ; first key in E - is it symbol shift?
        RET     Z               ; return if just symbol shift pressed

        CP      $27             ; first key in E - is it caps shift?
        RET     Z               ; return if just caps shift pressed

; changes the key tone for different calling addresses

        POP     HL              ; HL = the return address (caller address + 1)
        PUSH    HL              ; called from memory $00xx?
        LD      A,H             ; this must be MAIN-KEYS
        CP      $00             ; return address is $007E
        JR      Z,L0242         ; key-tone will be higher

        LD      A,L             ; possible return addresses: $137B, $13CF, $13EC
        CP      $7D             ; so there is no return address ending with $7D
        JR      Z,L0242

        LD      L,$40           ; tone is lower (called from Micro-monitor)
        JR      L0244

L0242:  LD      L,$28           ; tone is higher

;; KEY-TONE
L0244:  LD      B,$D0           ; cycle 208 times
        LD      C,$07           ; white border and speaker off
L0248:  LD      A,C
        OUT     ($FE),A
        XOR     $F8             ; turns on/off the speaker (why not just XOR $10?)
        LD      C,A             ; with L as the period/frequency
        LD      H,L
L024F:  DEC     H               ; wait for L-times
        JR      NZ,L024F        ; before change speaker state
        DJNZ    L0248

;; KEY-RELEASE
L0254:  XOR     A
        IN      A,($FE)         ; wait for key-release
        AND     $1F             ; before exit routine
        CP      $1F
        JR      NZ,L0254
        EI                      ; enable interrupts
        RET     

        DEFB    $FF, $FF, $FF   ; 14 unused bytes
        DEFB    $FF, $FF, $FF
        DEFB    $FF, $FF, $FF
        DEFB    $00, $00, $00
        DEFB    $00, $00

; ------------
; BASIC LOADER
; ------------     
; This is the Basic Loader which will be put in front of snapshot if "Total RAM SAVE" selected.
; It stores a machine code in the variables area.
; This program loads the screen and then it will call a machine code loader (which calls ZX ROM)
; to load the snapshot data and resume the program execution.
; BUG: No Turbo Loader alternative so "TURBO total RAM SAVE" will fail at load.
; This is the Basic loader listing:
;  10  PRINT  AT 10,4;"V&REW software Hungary"
;  20  PRINT  AT 10,4; OVER 1;"!'|!!"
;  25  LOAD "" CODE 16384
;  40  FOR a=1 TO 66: POKE a+16383, CODE c$(a): NEXT a
;  50  RANDOMIZE  USR 16384
; Note: Line 20 is just a little modification on the copyright text: W&REW software Hungary
; EPROM data $26D-$31B basic program, $31C-$376 variables

;; BASIC-LOADER
L026D:  DEFB    $00, $0A, $2C, $00, $F5, $AC, $31, $30
        DEFB    $0E, $00, $00, $0A, $00, $00, $2C, $34
        DEFB    $0E, $00, $00, $04, $00, $00, $3B, $22
        DEFB    $56, $26, $52, $45, $57, $20, $73, $6F
        DEFB    $66, $74, $77, $61, $72, $65, $20, $48
        DEFB    $75, $6E, $67, $61, $72, $79, $22, $0D
        ;  10  PRINT  AT 10,4;"V&REW software Hungary"

        DEFB    $00, $14, $24, $00, $F5, $AC, $31, $30
        DEFB    $0E, $00, $00, $0A, $00, $00, $2C, $34
        DEFB    $0E, $00, $00, $04, $00, $00, $3B, $DE
        DEFB    $31, $0E, $00, $00, $01, $00, $00, $3B
        DEFB    $22, $21, $27, $7C, $21, $21, $22, $0D
        ;  20  PRINT  AT 10,4; OVER 1;"!'|!!"

        DEFB    $00, $19, $10, $00, $EF, $22, $22, $AF
        DEFB    $31, $36, $33, $38, $34, $0E, $00, $00
        DEFB    $00, $40, $00, $0D
        ;  25  LOAD "" CODE 16384

        DEFB    $00, $28, $2D, $00, $EB, $61, $3D, $31
        DEFB    $0E, $00, $00, $01, $00, $00, $CC, $36
        DEFB    $36, $0E, $00, $00, $42, $00, $00, $3A
        DEFB    $F4, $61, $2B, $31, $36, $33, $38, $33
        DEFB    $0E, $00, $00, $FF, $3F, $00, $2C, $AF
        DEFB    $63, $24, $28, $61, $29, $3A, $F3, $61
        DEFB    $0D
        ;  40  FOR a=1 TO 66: POKE a+16383, CODE c$(a): NEXT a

        DEFB    $00, $32, $0E, $00, $F9, $C0, $31, $36
        DEFB    $33, $38, $34, $0E, $00, $00, $00, $40
        DEFB    $00, $0D
        ;  50  RANDOMIZE  USR 16384

; variables

        DEFB    $C3, $45, $00, $01, $42, $00
        ; c$ = 66 bytes...

; code hiding in variables which restores the cpu state
; and continues the execution of the saved snapshot
; note that this code will be relocated to $4000 (screen start)
; so this will mess up the first 66 bytes of the screen

; $0322
        NOP                     ; starting with some NOPs
        NOP                     ; these are here to make
        NOP                     ; room for a temporary stack
        NOP                     ; see below
        NOP
        NOP
        NOP
        NOP

        LD      HL,($5B00)      ; saved SP when program was frozen
                                ; this is saved along with screen data
        EXX                     ; switch to alternate set
        LD      DE,$A500        ; length $A500
        LD      IX,$5B00        ; start $5B00
        LD      A,$0F
        SCF                     ; load bytes flag
        LD      SP,$4009        ; temporary stack pointer
                                ; because memory from $5B00
                                ; will be overwritten
        CALL    $0556           ; call LD-BYTES from the
                                ; original Spectrum ROM
                                ; to load the snapshot file
        EXX                     ; switch back to main set
        LD      SP,HL           ; restore SP

        POP     IY              ; restore all registers
        POP     IX              ; saved on NMI
        EXX     
        POP     BC
        POP     DE
        POP     HL
        EXX
        EX      AF,AF'
        POP     AF
        EX      AF,AF'
        POP     BC
        POP     DE
        POP     AF
        LD      R,A
        POP     AF
        LD      I,A             ; restore interrupt state
        JP      PO,$4038        ; EI or DI
                                ; note this "weird" absolute jump
                                ; this code will be copied to $4000

        EI      
        JR      L035B
        DI                      ; at $4038
L035B:  POP     HL              ; restore interrupt mode
        CP      $3F             ; IM2 or leave in IM1
        JR      Z,L0362
        IM      2
L0362:  POP     AF
        RET                     ; continue running the
                                ; saved snapshot

; variable data for the FOR loop:

        DEFB    $E1, $00, $00, $43, $00, $00, $00, $00
        DEFB    $42, $00, $00, $00, $00, $01, $00, $00
        DEFB    $28, $00, $02

;; END OF BASIC LOADER


; $0377 - unknown data
        DEFB    $00, $00, $40, $00, $0D, $83, $93, $01, $01

; ----------------------------
; 385 unused bytes: $0380-$500
; ----------------------------

        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF

; garbage data? $501-$527

        DEFB    $00, $00, $00, $00, $00, $00, $00, $00
        DEFB    $00, $00, $00, $00, $00, $00, $00, $00
        DEFB    $00, $E1, $00, $00, $2D, $00, $00, $00
        DEFB    $00, $3C, $00, $00, $00, $00, $01, $00
        DEFB    $00, $FE, $FF, $02, $00, $00, $00

;; EXIT-LOAD
L0528:  EXX                     ; switch back to main set
        LD      SP,HL           ; restore SP from HL

; --------------------------------
; 'EXIT FROM MICRO-POKEer' ROUTINE
; --------------------------------
; Restores the registers, the interrupt mode
; and the interrupt state then switches back
; the original ZX Spectrum ROM

;; EXIT-POKER
L052A:  POP     IY              ; restore all the registers
        POP     IX              ; saved on NMI
        EXX     
        POP     BC
        POP     DE
        POP     HL
        EXX     
        EX      AF,AF'
        POP     AF
        EX      AF,AF'
        POP     BC
        POP     DE
        POP     AF
        LD      R,A
        POP     AF              ; parity flag stores IFF2 (which stores IFF1)
        LD      I,A
        POP     HL
        JP      PO,L0545        ; interrupts was enabled or not?
        EI                      ; restore Enable Interrupts
        JR      L0546
L0545:  DI                      ; restore Disable Interrupts
L0546:  CP      $3F             ; Spectrum ROM sets I to $3F in START-NEW routine
        JR      NZ,L054E        ; if I was not $3F we should restore IM 2 mode.
        IM      1               ; restore interrupt mode 1 - Spectrum ROM default
        JR      L0550
L054E:  IM      2               ; restore interrupt mode 2
L0550:  LD      A,$00           ; exit from MICRO-POKEer by
        OUT     ($7F),A         ; switching back to original Spectrum ROM
        POP     AF              ; this piece of code never gets executed
        RET                     ; these are the same in the original ROM


        DEFB    $00, $5A

; 0558 - doesn't seem to be called

        LD      B,$04           ; push the previous 8 bytes of data
L055A:  LD      E,(HL)          ; pointed by HL on the stack
        DEC     HL
        LD      D,(HL)
        DEC     HL
        PUSH    DE
        DJNZ    L055A
        EXX     
        JP      $00AF           ; jump to ...

        DEFB    $FF, $FF, $FF   ; 11 unused bytes
        DEFB    $FF, $FF, $FF
        DEFB    $FF, $FF, $FF
        DEFB    $FF, $FF

        DEFM    "MONITOR #570-#1E7E-IG"

        DEFB    $FF, $FF, $FF   ; 3 unused bytes

; -------------------------------
; THE 'ZX SPECTRUM CHARACTER SET'
; -------------------------------
; Copy from the original ZX Spectrum ROM

; $20 - Character: ' '          CHR$(32)

L0588:  DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000

; $21 - Character: '!'          CHR$(33)

        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00000000

; $22 - Character: '"'          CHR$(34)

        DEFB    %00000000
        DEFB    %00100100
        DEFB    %00100100
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000

; $23 - Character: '#'          CHR$(35)

        DEFB    %00000000
        DEFB    %00100100
        DEFB    %01111110
        DEFB    %00100100
        DEFB    %00100100
        DEFB    %01111110
        DEFB    %00100100
        DEFB    %00000000

; $24 - Character: '$'          CHR$(36)

        DEFB    %00000000
        DEFB    %00001000
        DEFB    %00111110
        DEFB    %00101000
        DEFB    %00111110
        DEFB    %00001010
        DEFB    %00111110
        DEFB    %00001000

; $25 - Character: '%'          CHR$(37)

        DEFB    %00000000
        DEFB    %01100010
        DEFB    %01100100
        DEFB    %00001000
        DEFB    %00010000
        DEFB    %00100110
        DEFB    %01000110
        DEFB    %00000000

; $26 - Character: '&'          CHR$(38)

        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00101000
        DEFB    %00010000
        DEFB    %00101010
        DEFB    %01000100
        DEFB    %00111010
        DEFB    %00000000

; $27 - Character: '''          CHR$(39)

        DEFB    %00000000
        DEFB    %00001000
        DEFB    %00010000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000

; $28 - Character: '('          CHR$(40)

        DEFB    %00000000
        DEFB    %00000100
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00000100
        DEFB    %00000000

; $29 - Character: ')'          CHR$(41)

        DEFB    %00000000
        DEFB    %00100000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00100000
        DEFB    %00000000

; $2A - Character: '*'          CHR$(42)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00010100
        DEFB    %00001000
        DEFB    %00111110
        DEFB    %00001000
        DEFB    %00010100
        DEFB    %00000000

; $2B - Character: '+'          CHR$(43)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00111110
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00000000

; $2C - Character: ','          CHR$(44)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00010000

; $2D - Character: '-'          CHR$(45)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00111110
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000

; $2E - Character: '.'          CHR$(46)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00011000
        DEFB    %00011000
        DEFB    %00000000

; $2F - Character: '/'          CHR$(47)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000010
        DEFB    %00000100
        DEFB    %00001000
        DEFB    %00010000
        DEFB    %00100000
        DEFB    %00000000

; $30 - Character: '0'          CHR$(48)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000110
        DEFB    %01001010
        DEFB    %01010010
        DEFB    %01100010
        DEFB    %00111100
        DEFB    %00000000

; $31 - Character: '1'          CHR$(49)

        DEFB    %00000000
        DEFB    %00011000
        DEFB    %00101000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00111110
        DEFB    %00000000

; $32 - Character: '2'          CHR$(50)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %00000010
        DEFB    %00111100
        DEFB    %01000000
        DEFB    %01111110
        DEFB    %00000000

; $33 - Character: '3'          CHR$(51)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %00001100
        DEFB    %00000010
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $34 - Character: '4'          CHR$(52)

        DEFB    %00000000
        DEFB    %00001000
        DEFB    %00011000
        DEFB    %00101000
        DEFB    %01001000
        DEFB    %01111110
        DEFB    %00001000
        DEFB    %00000000

; $35 - Character: '5'          CHR$(53)

        DEFB    %00000000
        DEFB    %01111110
        DEFB    %01000000
        DEFB    %01111100
        DEFB    %00000010
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $36 - Character: '6'          CHR$(54)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000000
        DEFB    %01111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $37 - Character: '7'          CHR$(55)

        DEFB    %00000000
        DEFB    %01111110
        DEFB    %00000010
        DEFB    %00000100
        DEFB    %00001000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00000000

; $38 - Character: '8'          CHR$(56)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $39 - Character: '9'          CHR$(57)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00111110
        DEFB    %00000010
        DEFB    %00111100
        DEFB    %00000000

; $3A - Character: ':'          CHR$(58)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00000000

; $3B - Character: ';'          CHR$(59)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00100000

; $3C - Character: '<'          CHR$(60)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000100
        DEFB    %00001000
        DEFB    %00010000
        DEFB    %00001000
        DEFB    %00000100
        DEFB    %00000000

; $3D - Character: '='          CHR$(61)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00111110
        DEFB    %00000000
        DEFB    %00111110
        DEFB    %00000000
        DEFB    %00000000

; $3E - Character: '>'          CHR$(62)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00001000
        DEFB    %00000100
        DEFB    %00001000
        DEFB    %00010000
        DEFB    %00000000

; $3F - Character: '?'          CHR$(63)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %00000100
        DEFB    %00001000
        DEFB    %00000000
        DEFB    %00001000
        DEFB    %00000000

; $40 - Character: '@'          CHR$(64)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01001010
        DEFB    %01010110
        DEFB    %01011110
        DEFB    %01000000
        DEFB    %00111100
        DEFB    %00000000

; $41 - Character: 'A'          CHR$(65)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01111110
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00000000

; $42 - Character: 'B'          CHR$(66)

        DEFB    %00000000
        DEFB    %01111100
        DEFB    %01000010
        DEFB    %01111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01111100
        DEFB    %00000000

; $43 - Character: 'C'          CHR$(67)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $44 - Character: 'D'          CHR$(68)

        DEFB    %00000000
        DEFB    %01111000
        DEFB    %01000100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000100
        DEFB    %01111000
        DEFB    %00000000

; $45 - Character: 'E'          CHR$(69)

        DEFB    %00000000
        DEFB    %01111110
        DEFB    %01000000
        DEFB    %01111100
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01111110
        DEFB    %00000000

; $46 - Character: 'F'          CHR$(70)

        DEFB    %00000000
        DEFB    %01111110
        DEFB    %01000000
        DEFB    %01111100
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %00000000

; $47 - Character: 'G'          CHR$(71)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %01000000
        DEFB    %01001110
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $48 - Character: 'H'          CHR$(72)

        DEFB    %00000000
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01111110
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00000000

; $49 - Character: 'I'          CHR$(73)

        DEFB    %00000000
        DEFB    %00111110
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00111110
        DEFB    %00000000

; $4A - Character: 'J'          CHR$(74)

        DEFB    %00000000
        DEFB    %00000010
        DEFB    %00000010
        DEFB    %00000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $4B - Character: 'K'          CHR$(75)

        DEFB    %00000000
        DEFB    %01000100
        DEFB    %01001000
        DEFB    %01110000
        DEFB    %01001000
        DEFB    %01000100
        DEFB    %01000010
        DEFB    %00000000

; $4C - Character: 'L'          CHR$(76)

        DEFB    %00000000
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01111110
        DEFB    %00000000

; $4D - Character: 'M'          CHR$(77)

        DEFB    %00000000
        DEFB    %01000010
        DEFB    %01100110
        DEFB    %01011010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00000000

; $4E - Character: 'N'          CHR$(78)

        DEFB    %00000000
        DEFB    %01000010
        DEFB    %01100010
        DEFB    %01010010
        DEFB    %01001010
        DEFB    %01000110
        DEFB    %01000010
        DEFB    %00000000

; $4F - Character: 'O'          CHR$(79)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $50 - Character: 'P'          CHR$(80)

        DEFB    %00000000
        DEFB    %01111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01111100
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %00000000

; $51 - Character: 'Q'          CHR$(81)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01010010
        DEFB    %01001010
        DEFB    %00111100
        DEFB    %00000000

; $52 - Character: 'R'          CHR$(82)

        DEFB    %00000000
        DEFB    %01111100
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01111100
        DEFB    %01000100
        DEFB    %01000010
        DEFB    %00000000

; $53 - Character: 'S'          CHR$(83)

        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000000
        DEFB    %00111100
        DEFB    %00000010
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $54 - Character: 'T'          CHR$(84)

        DEFB    %00000000
        DEFB    %11111110
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00000000

; $55 - Character: 'U'          CHR$(85)

        DEFB    %00000000
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00111100
        DEFB    %00000000

; $56 - Character: 'V'          CHR$(86)

        DEFB    %00000000
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %00100100
        DEFB    %00011000
        DEFB    %00000000

; $57 - Character: 'W'          CHR$(87)

        DEFB    %00000000
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01000010
        DEFB    %01011010
        DEFB    %00100100
        DEFB    %00000000

; $58 - Character: 'X'          CHR$(88)

        DEFB    %00000000
        DEFB    %01000010
        DEFB    %00100100
        DEFB    %00011000
        DEFB    %00011000
        DEFB    %00100100
        DEFB    %01000010
        DEFB    %00000000

; $59 - Character: 'Y'          CHR$(89)

        DEFB    %00000000
        DEFB    %10000010
        DEFB    %01000100
        DEFB    %00101000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00000000

; $5A - Character: 'Z'          CHR$(90)

        DEFB    %00000000
        DEFB    %01111110
        DEFB    %00000100
        DEFB    %00001000
        DEFB    %00010000
        DEFB    %00100000
        DEFB    %01111110
        DEFB    %00000000

; $5B - Character: '['          CHR$(91)

        DEFB    %00000000
        DEFB    %00001110
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001110
        DEFB    %00000000

; $5C - Character: '\'          CHR$(92)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01000000
        DEFB    %00100000
        DEFB    %00010000
        DEFB    %00001000
        DEFB    %00000100
        DEFB    %00000000

; $5D - Character: ']'          CHR$(93)

        DEFB    %00000000
        DEFB    %01110000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %01110000
        DEFB    %00000000

; $5E - Character: '^'          CHR$(94)

        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00111000
        DEFB    %01010100
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00000000

; $5F - Character: '_'          CHR$(95)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %11111111

; $60 - Character: 'L'          CHR$(96)

        DEFB    %00000000
        DEFB    %00011100
        DEFB    %00100010
        DEFB    %01111000
        DEFB    %00100000
        DEFB    %00100000
        DEFB    %01111110
        DEFB    %00000000

; $61 - Character: 'a'          CHR$(97)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00111000
        DEFB    %00000100
        DEFB    %00111100
        DEFB    %01000100
        DEFB    %00111100
        DEFB    %00000000

; $62 - Character: 'b'          CHR$(98)

        DEFB    %00000000
        DEFB    %00100000
        DEFB    %00100000
        DEFB    %00111100
        DEFB    %00100010
        DEFB    %00100010
        DEFB    %00111100
        DEFB    %00000000

; $63 - Character: 'c'          CHR$(99)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00011100
        DEFB    %00100000
        DEFB    %00100000
        DEFB    %00100000
        DEFB    %00011100
        DEFB    %00000000

; $64 - Character: 'd'          CHR$(100)

        DEFB    %00000000
        DEFB    %00000100
        DEFB    %00000100
        DEFB    %00111100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00111100
        DEFB    %00000000

; $65 - Character: 'e'          CHR$(101)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00111000
        DEFB    %01000100
        DEFB    %01111000
        DEFB    %01000000
        DEFB    %00111100
        DEFB    %00000000

; $66 - Character: 'f'          CHR$(102)

        DEFB    %00000000
        DEFB    %00001100
        DEFB    %00010000
        DEFB    %00011000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00000000

; $67 - Character: 'g'          CHR$(103)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00111100
        DEFB    %00000100
        DEFB    %00111000

; $68 - Character: 'h'          CHR$(104)

        DEFB    %00000000
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01111000
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00000000

; $69 - Character: 'i'          CHR$(105)

        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00000000
        DEFB    %00110000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00111000
        DEFB    %00000000

; $6A - Character: 'j'          CHR$(106)

        DEFB    %00000000
        DEFB    %00000100
        DEFB    %00000000
        DEFB    %00000100
        DEFB    %00000100
        DEFB    %00000100
        DEFB    %00100100
        DEFB    %00011000

; $6B - Character: 'k'          CHR$(107)

        DEFB    %00000000
        DEFB    %00100000
        DEFB    %00101000
        DEFB    %00110000
        DEFB    %00110000
        DEFB    %00101000
        DEFB    %00100100
        DEFB    %00000000

; $6C - Character: 'l'          CHR$(108)

        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00001100
        DEFB    %00000000

; $6D - Character: 'm'          CHR$(109)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01101000
        DEFB    %01010100
        DEFB    %01010100
        DEFB    %01010100
        DEFB    %01010100
        DEFB    %00000000

; $6E - Character: 'n'          CHR$(110)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01111000
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00000000

; $6F - Character: 'o'          CHR$(111)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00111000
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00111000
        DEFB    %00000000

; $70 - Character: 'p'          CHR$(112)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01111000
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %01111000
        DEFB    %01000000
        DEFB    %01000000

; $71 - Character: 'q'          CHR$(113)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00111100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00111100
        DEFB    %00000100
        DEFB    %00000110

; $72 - Character: 'r'          CHR$(114)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00011100
        DEFB    %00100000
        DEFB    %00100000
        DEFB    %00100000
        DEFB    %00100000
        DEFB    %00000000

; $73 - Character: 's'          CHR$(115)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00111000
        DEFB    %01000000
        DEFB    %00111000
        DEFB    %00000100
        DEFB    %01111000
        DEFB    %00000000

; $74 - Character: 't'          CHR$(116)

        DEFB    %00000000
        DEFB    %00010000
        DEFB    %00111000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %00001100
        DEFB    %00000000

; $75 - Character: 'u'          CHR$(117)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00111000
        DEFB    %00000000

; $76 - Character: 'v'          CHR$(118)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00101000
        DEFB    %00101000
        DEFB    %00010000
        DEFB    %00000000

; $77 - Character: 'w'          CHR$(119)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01000100
        DEFB    %01010100
        DEFB    %01010100
        DEFB    %01010100
        DEFB    %00101000
        DEFB    %00000000

; $78 - Character: 'x'          CHR$(120)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01000100
        DEFB    %00101000
        DEFB    %00010000
        DEFB    %00101000
        DEFB    %01000100
        DEFB    %00000000

; $79 - Character: 'y'          CHR$(121)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %01000100
        DEFB    %00111100
        DEFB    %00000100
        DEFB    %00111000

; $7A - Character: 'z'          CHR$(122)

        DEFB    %00000000
        DEFB    %00000000
        DEFB    %01111100
        DEFB    %00001000
        DEFB    %00010000
        DEFB    %00100000
        DEFB    %01111100
        DEFB    %00000000

; $7B - Character: '{'          CHR$(123)

        DEFB    %00000000
        DEFB    %00001110
        DEFB    %00001000
        DEFB    %00110000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001110
        DEFB    %00000000

; $7C - Character: '|'          CHR$(124)

        DEFB    %00000000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00001000
        DEFB    %00000000

; $7D - Character: '}'          CHR$(125)

        DEFB    %00000000
        DEFB    %01110000
        DEFB    %00010000
        DEFB    %00001100
        DEFB    %00010000
        DEFB    %00010000
        DEFB    %01110000
        DEFB    %00000000

; $7E - Character: '~'          CHR$(126)

        DEFB    %00000000
        DEFB    %00010100
        DEFB    %00101000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000
        DEFB    %00000000

; $7F - Character: '©'          CHR$(127)

        DEFB    %00111100
        DEFB    %01000010
        DEFB    %10011001
        DEFB    %10100001
        DEFB    %10100001
        DEFB    %10011001
        DEFB    %01000010
        DEFB    %00111100

; $80 - First UDG character     CHR$(128)

        DEFB    %11111111
        DEFB    %11111111
        DEFB    %11111111
        DEFB    %11111111
        DEFB    %11111111
        DEFB    %11111111
        DEFB    %11111111
        DEFB    %11111111


; ----------------------
; MICRO-POKEer MENU TEXT
; ----------------------
; scrolling menu text

L0890:  DEFM    "MICRO-POKEer v1.6    "
        DEFM    "Space:exit from HELP   "
        DEFM    "ENTER:Return  "
        DEFM    "r:Total RAM SAVE  "
        DEFM    "R:TURBO total RAM SAVE  "
        DEFM    "s:SCREEN SAVE  "
        DEFM    "S:TURBO SCREEN SAVE  "
        DEFM    "l:TURBO SCREEN LOAD  "
        DEFM    "L:TURBO total RAM LOAD  "
        DEFM    "w:Warm RESET  "
        DEFM    "H:HELP  "
        DEFM    "m:Micro-monitor q/a/o/p/ENTER:move box  "
        DEFM    "input address (dec) q:quit j:jump ENTER:new addr.p:POKE data  "
        DEFM    "MICRO-STUDIO   "
        DEFM    "............................  "
L09EE:  DEFM    "                                  "

; ------------------------------
; 1190 unused bytes: $0A10-$0EB5
; ------------------------------

        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF

; -----------------------------
; MICRO MONITOR CURSOR ROUTINES
; ----------------------------- 
        
;; MM-CURSOR
L0EB6:  LD      BC,$0000        ; initialize to X=0, Y=0
        LD      ($7000),BC

;; MM-SELECT
L0EBD:  CALL    L0EE1           ; calls MM-INVERT to invert
                                ; pixels pointed BC by (Y/X)

;; MM-DELAY
L0EC0:  IM      1               ; set Interrupt Mode 1 and 
        EI                      ; Enable Interrupt to
        LD      B,$03           ; wait for 3/50 second (60 msec)
L0EC5:  HALT
        DJNZ    L0EC5

; Micro-monitor key event handler

;; MM-KEYS
L0EC8:  CALL    L0030           ; KEY-SCAN (RST 30H instead?)
        LD      A,E             ; wait until a key pressed from the
        LD      HL,L0F76        ; MM-TABLE at L0F76
        LD      B,$05           ; table has 5 elements (key-address pairs)

;; MM-TEST
L0ED1:  CP      (HL)            ; key found?
        JR      NZ,L0EDA        ; skip to next element if not
        INC     HL
        LD      E,(HL)          ; DE has the address
        INC     HL              ; associated with the key
        LD      D,(HL)
        EX      DE,HL           ; swap DE-HL, now HL has the address
        JP      (HL)            ; jump to the table address

L0EDA:  INC     HL              ; table has 3 bytes per row
        INC     HL              ; skip to next
        INC     HL              ; row
        DJNZ    L0ED1           ; go back to MM-TEST until no more keys
        JR      L0EC8           ; then start checking at MM-KEYS

; This routine inverts a 5 pixels by 40 pixels box pointed by B/C (Y/X)

;; MM-INVERT
L0EE1:  LD      C,$05           ; process 5 rows
L0EE3:  PUSH    BC
        LD      BC,($7000)      ; get X/Y coords
        CALL    L0F85           ; and get pixel address (PIXEL-ADD)

        LD      B,$05           ; process 5x8=40 pixels
L0EED:  LD      A,(HL)          ; get 8 pixel pointed by B,C (Y,X coords)
        CPL                     ; invert pixels
        LD      (HL),A          ; and put back
        INC     HL              ; next 8 pixels
        DJNZ    L0EED           ; and continue loop

        LD      BC,($7000)
        INC     B               ; next row
        LD      ($7000),BC
        POP     BC
        DEC     C
        JR      NZ,L0EE3        ; continue loop

        LD      HL,$7001        ; point to Y value
        LD      B,$05           ; decrement Y by 5 pixels
L0F05:  DEC     (HL)            ; to restore original value
        DJNZ    L0F05
        RET                     ; return

;; MM-KEYUP
L0F09:  LD      BC,($7000)      ; get X-Y position
        LD      A,B             ; check Y
        CP      $A8             ; is it 168?
        JP      Z,L0EC0         ; do nothing (go back to MM-DELAY)
        CALL    L0EE1           ; if not, invert pixels back
        LD      HL,$7001        ; and
        LD      B,$08           ; increment Y value by 8 pixels
L0F1B:  INC     (HL)
        DJNZ    L0F1B
        JP      L0EBD           ; go back to MM-SELECT
                                ; and invert the new position

;; MM-KEYDOWN
L0F21:  LD      BC,($7000)      ; get X-Y position
        LD      A,B             ; check Y
        CP      $00             ; is it zero?
        JP      Z,L0EC0         ; do nothing (go back to MM-DELAY)
        CALL    L0EE1           ; if not, invert pixels back
        LD      HL,$7001        ; and
        LD      B,$08           ; decrement Y value by 8 pixels
L0F33:  DEC     (HL)
        DJNZ    L0F33
        JP      L0EBD           ; go back to MM-SELECT
                                ; and invert the new position

;; MM-KEYLEFT
L0F39:  LD      BC,($7000)      ; get X-Y positon
        LD      A,C             ; check X
        CP      $00             ; is it zero?
        JP      Z,L0EC0         ; do nothing (go back to MM-DELAY)
        CALL    L0EE1           ; if not, invert pixels back
        LD      HL,$7000        ; and
        LD      B,$08           ; decrement X value by 8 pixels
L0F4B:  DEC     (HL)
        DJNZ    L0F4B
        JP      L0EBD           ; go back to MM-SELECT
                                ; and invert the new position

;; MM-KEYRIGHT
L0F51:  LD      BC,($7000)      ; get X-Y position
        LD      A,C             ; check X
        CP      $D8             ; is it 216?
        JP      Z,L0EC0         ; do nothing (go back to MM-DELAY)
        CALL    L0EE1           ; if not, invert pixels back
        LD      HL,$7000        ; and
        LD      B,$08           ; increment X value by 8
L0F63:  INC     (HL)
        DJNZ    L0F63
        JP      L0EBD           ; go back to MM-SELECT
                                ; and invert the new position

;; MM-ENTER
L0F69:  LD      BC,($7000)      ; get Y/X position in B/C pair
        NOP     
        INC     B               ; increment Y by 4 pixels
        INC     B
        INC     B
        INC     B
        CALL    L0F85           ; call PIXEL-ADD to get screen
        RET                     ; position in HL and return

; Micro-monitor key assignments
; and associated function addresses

;; MM-KEYTAB
L0F76:  DEFB    $25, $09, $0F   ; L0F09 - key 'Q'
        DEFB    $26, $21, $0F   ; L0F21 - key 'A'
        DEFB    $1A, $39, $0F   ; L0F39 - key 'O'
        DEFB    $22, $51, $0F   ; L0F51 - key 'P'
        DEFB    $21, $69, $0F   ; L0F69 - key 'ENTER'


; -----------------
; Get pixel address
; -----------------
; B - y position, C - x position
; HL - the desired screen memory address
; Almost exact copy of the Spectrum ROM routine.
; Copied from $22AA to $0F85

;; PIXEL-ADD
L0F85:  LD      A,$AF           ; load with 175 decimal.
        SUB     B               ; subtract the y value.
        NOP                     ; a 3 byte long conditional
        NOP                     ; JP instruction to REPORT-Bc
        NOP                     ; is zeroed out

; the high byte is derived from Y only.
; the first 3 bits are always 010
; the next 2 bits denote in which third of the screen the byte is.
; the last 3 bits denote in which of the 8 scan lines within a third
; the byte is located. There are 24 discrete values.

        LD      B,A             ; the line number from top of screen to B.
        AND     A               ; clear carry (already clear)
        RRA                     ;                     0xxxxxxx
        SCF                     ; set carry flag
        RRA                     ;                     10xxxxxx
        AND     A               ; clear carry flag
        RRA                     ;                     010xxxxx

        XOR     B
        AND     $F8             ; keep the top 5 bits 11111000
        XOR     B               ;                     010xxbbb
        LD      H,A             ; transfer high byte to H.

; the low byte is derived from both X and Y.

        LD      A,C             ; the x value 0-255.
        RLCA    
        RLCA    
        RLCA    
        XOR     B               ; the y value
        AND     $C7             ; apply mask             11000111
        XOR     B               ; restore unmasked bits  xxyyyxxx
        RLCA                    ; rotate to              xyyyxxxx    
        RLCA                    ; required position.     yyyxxxxx    
        LD      L,A             ; low byte to L.

; finally form the pixel position in A.

        LD      A,C             ; x value to A
        AND     $07             ; mod 8
        RET                     ; return     

; --------------------------
; 90 unused bytes: $FA6-$FFF
; --------------------------

        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF

; =========================================
;
; PORT 254 ($FE)
;
;                      spk mic { border  }  
;          ___ ___ ___ ___ ___ ___ ___ ___ 
; PORT    |   |   |   |   |   |   |   |   |
; 254     |   |   |   |   |   | G | R | B |
; $FE     |___|___|___|___|___|___|___|___|
;           7   6   5   4   3   2   1   0
;

; ----------------------------------
; Save header and program/data bytes
; ----------------------------------
; This is a slightly modified version of the ZX-Spectrum 'Save' ROM routine,
; relocated from $04C2 to $1000.
; All comments are borrowed from the The Incomplete Spectrum ROM Assembly.
; On entry:
; HL points to start of data.
; IX points to descriptor.
; The accumulator is set to $00 for a header, $FF for data.

;; SA-BYTES
L1000:  LD      HL,L107D        ; address: SA/LD-RET
        PUSH    HL              ; is pushed as common exit route.
        LD      HL,$1F80        ; a timing constant H=$1F, L=$80
                                ; inner and outer loop counters
                                ; a five second lead-in is used for a header.
        BIT     7,A             ; test one bit of accumulator.
        JR      Z,L100E         ; skip to SA-FLAG if a header is being saved.

; else is data bytes and a shorter lead-in is used.

        LD      HL,$0C98        ; another timing value H=$0C, L=$98.
                                ; a two second lead-in is used for the data.
;; SA-FLAG
L100E:  EX      AF,AF'          ; save flag
        INC     DE              ; increase length by one.
        DEC     IX              ; decrease start.
        DI                      ; disable interrupts
        LD      A,$02           ; select red for border, microphone bit on.
        LD      B,A             ; also does as an initial slight counter value.

;; SA-LEADER
L1016:  DJNZ    L1016           ; self loop to SA-LEADER for delay.
                                ; after initial loop, count is $A4 (or $A3)

        OUT     ($FE),A         ; output byte $02/$0D to tape port.

        XOR     $0F             ; switch from RED (mic on) to CYAN (mic off).

        LD      B,$0A4          ; hold count. also timed instruction.

        DEC     L               ; originally $80 or $98.
                                ; but subsequently cycles 256 times.
        JR      NZ,L1016        ; back to SA-LEADER until L is zero.

; the outer loop is counted by H

        DEC     B               ; decrement count
        DEC     H               ; originally  twelve or thirty-one.
        JP      P,L1016         ; back to SA-LEADER until H becomes $FF

; now send a sync pulse. At this stage mic is off and A holds value
; for mic on.
; A sync pulse is much shorter than the steady pulses of the lead-in.

        LD      B,$2F           ; another short timed delay.

;; SA-SYNC-1
L1028:  DJNZ    L1028           ; self loop to SA-SYNC-1
        OUT     ($FE),A         ; switch to mic on and red.
        LD      A,$0D           ; prepare mic off - cyan
        LD      B,$37           ; another short timed delay.

;; SA-SYNC-2
L1030:  DJNZ    L1030           ; self loop to SA-SYNC-2

        OUT     ($FE),A         ; output mic off, cyan border.
        LD      BC,$3B0E        ; B=$3B time(*), C=$0E, YELLOW, MIC OFF.

        EX      AF,AF'          ; restore saved flag
                                ; which is 1st byte to be saved.

        LD      L,A             ; and transfer to L.
                                ; the initial parity is A, $FF or $00.
        JP      L1045           ; JUMP forward to SA-START     ->
                                ; the mid entry point of loop.

; During the save loop a parity byte is maintained in H.
; the save loop begins by testing if reduced length is zero and if so
; the final parity byte is saved reducing count to $FFFF.

;; SA-LOOP
L103C:  LD      A,D             ; fetch high byte
        OR      E               ; test against low byte.
        JR      Z,L104C         ; forward to SA-PARITY if zero.

        LD      L,(IX+$00)      ; load currently addressed byte to L.

;; SA-LOOP-P
L1043:  LD      A,H             ; fetch parity byte.
        XOR     L               ; exclusive or with new byte.

; -> the mid entry point of loop.

;; SA-START
L1045:  LD      H,A             ; put parity byte in H.
        LD      A,$01           ; prepare blue, mic=on.
        SCF                     ; set carry flag ready to rotate in.
        JP      L1063           ; JUMP forward to SA-8-BITS

;; SA-PARITY
L104C:  LD      L,H             ; transfer the running parity byte to L and
        JR      L1043           ; back to SA-LOOP-P 
                                ; to output that byte before quitting normally.

; The entry point to save yellow part of bit.
; A bit consists of a period with mic on and blue border followed by 
; a period of mic off with yellow border. 
; Note. since the DJNZ instruction does not affect flags, the zero flag is
; used to indicate which of the two passes is in effect and the carry 
; maintains the state of the bit to be saved.

;; SA-BIT-2
L104F:  LD      A,C             ; fetch 'mic on and yellow' which is 
                                ; held permanently in C.
        BIT     7,B             ; set the zero flag. B holds $3E.

; The entry point to save 1 entire bit. For first bit B holds $3B(*).
; Carry is set if saved bit is 1. zero is reset NZ on entry.

;; SA-BIT-1
L1052:  DJNZ    L1052           ; self loop for delay to SA-BIT-1

        JR      NC,L105A        ; forward to SA-OUT if bit is 0.

; but if bit is 1 then the mic state is held for longer.

        LD      B,$42           ; set timed delay. (66 decimal)

;; SA-SET
L1058:  DJNZ    L1058           ; self loop to SA-SET 
                                ; (roughly an extra 66*13 clock cycles)

;; SA-OUT
L105A:  OUT     ($FE),A         ; blue and mic on OR  yellow and mic off.
        LD      B,$3E           ; set up delay
        JR      NZ,L104F        ; back to SA-BIT-2 if zero reset NZ (first pass)

; proceed when the blue and yellow bands have been output.

        DEC     B               ; change value $3E to $3D.
        XOR     A               ; clear carry flag (ready to rotate in).
        INC     A               ; reset zero flag i.e. NZ.

;; SA-8-BITS
L1063:  RL      L               ; rotate left through carry
                                ; C<76543210<C  
        JP      NZ,L1052        ; JUMP back to SA-BIT-1 
                                ; until all 8 bits done.

; when the initial set carry is passed out again then a byte is complete.

        DEC     DE              ; decrease length
        INC     IX              ; increase byte pointer
        LD      B,$31           ; set up timing.

        LD      A,$7F           ; test the space key and
        IN      A,($FE)         ; return to common exit (to restore border)
        RRA                     ; if a space is pressed
        RET     NC              ; return to SA/LD-RET.

; now test if byte counter has reached $FFFF.

        LD      A,D             ; fetch high byte
        INC     A               ; increment.
        JP      NZ,L103C        ; JUMP to SA-LOOP if more bytes.

        LD      B,$3B           ; a final delay. 

;; SA-DELAY
L107A:  DJNZ    L107A           ; self loop to SA-DELAY
        RET                     ; return to SA/LD-RET

; ------------------------------
; THE 'SAVE/LOAD RETURN' ROUTINE
; ------------------------------
; This is also copied from the Spectrum ROM, modified slightly at the end.
; The Enable Interrupts and the REPORT-Da section is zeroed out by NOPs.

;; SA/LD-RET
L107D:  PUSH    AF              ; preserve accumulator throughout.
        LD      A,($5C48)       ; fetch border colour from BORDCR.
        AND     $38             ; mask off paper bits.
        RRCA                    ; rotate    
        RRCA                    ; to the    
        RRCA                    ; range 0-7.
    
        OUT     ($FE),A         ; change the border colour.
        LD      A,$7F           ; read from port address $7FFE the
        IN      A,($FE)         ; row with the space key at outside.

        RRA                     ; test for space key pressed.

        NOP                     ; EI changed to NOP
        NOP                     ; JR changed to NOP
        INC     BC              ; remnant of JR offset and becomes INC BC

;; REPORT-Da
        NOP                     ; RST 08H changed to NOP
        NOP                     ; DEFB $0C changed to NOP

        NOP                     ; added byte - not exists in original ROM

;; SA/LD-END
        POP     AF              ; restore the accumulator.
        RET                     ; return.

; ----------------------------
; 51 unused bytes: $1095-$10C7
; ----------------------------

        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $00, $00, $00, $00, $00
        DEFB    $00, $00, $00

; ------------------------------------------------------------------
; Load header or block of information - TURBO VERSION (double speed)
; ------------------------------------------------------------------
; This routine is used to load bytes and on entry A is set to $00 for a 
; header or to $FF for data.  IX points to the start of receiving location 
; and DE holds the length of bytes to be loaded. If, on entry the carry flag 
; is set then data is loaded, if reset then it is verified.

; This is a slightly modified version of the ZX-Spectrum 'Load' ROM routine,
; relocated from $0556 to $10C8. Timing constants altered for Turbo Load.
; All comments are borrowed from 'The Incomplete Spectrum ROM Assembly'.

;; LD-BYTES
L10C8:  INC     D               ; reset the zero flag without disturbing carry.
        EX      AF,AF'          ; preserve entry flags.
        DEC     D               ; restore high byte of length.

        DI                      ; disable interrupts
      
        LD      A,$0F           ; make the border white and mic off.
        OUT     ($FE),A         ; output to port.

        LD      HL,L107D        ; address: SA/LD-RET
        PUSH    HL              ; is saved on stack as terminating routine.

; the reading of the EAR bit (D6) will always be preceded by a test of the 
; space key (D0), so store the initial post-test state.

        IN      A,($FE)         ; read the ear state - bit 6.
        RRA                     ; rotate to bit 5.
        AND     $20             ; isolate this bit.
        OR      $02             ; combine with red border colour.
        LD      C,A             ; and store initial state long-term in C.
        CP      A               ; set the zero flag.

;; LD-BREAK
L10DD:  RET     NZ              ; return if at any time space is pressed.

;; LD-START
L10DE:  CALL    L1159           ; routine LD-EDGE-1
        JR      NC,L10DD        ; back to LD-BREAK with time out and no
                                ; edge present on tape.

; but continue when a transition is found on tape.

        LD      HL,$0415        ; set up 16-bit outer loop counter for 
                                ; approx 1 second delay.

;; LD-WAIT
L10E6:  DJNZ    L10E6           ; self loop to LD-WAIT (for 256 times)

        DEC     HL              ; decrease outer loop counter.
        LD      A,H             ; test for
        OR      L               ; zero.
        JR      NZ,L10E6        ; back to LD-WAIT, if not zero, with zero in B.

; continue after delay with H holding zero and B also.
; sample 256 edges to check that we are in the middle of a lead-in section. 

        CALL    L1155           ; routine LD-EDGE-2
        JR      NC,L10DD        ; back to LD-BREAK
                                ; if no edges at all.

;; LD-LEADER
L10F2:  LD      B,$9C           ; set timing value.
        CALL    L1155           ; routine LD-EDGE-2
        JR      NC,L10DD        ; back to LD-BREAK if time-out

        LD      A,$C6           ; two edges must be spaced apart.
        CP      B               ; compare
        JR      NC,L10DE        ; back to LD-START if too close together for a
                                ; lead-in.

        INC     H               ; proceed to test 256 edged sample.
        JR      NZ,L10F2        ; back to LD-LEADER while more to do.

; sample indicates we are in the middle of a two or five second lead-in.
; Now test every edge looking for the terminal sync signal.

;; LD-SYNC
L1101:  LD      B,$C9           ; initial timing value in B.
        CALL    L1159           ; routine LD-EDGE-1
        JR      NC,L10DD        ; back to LD-BREAK with time-out.

        LD      A,B             ; fetch augmented timing value from B.
        CP      $D4             ; compare 
        JR      NC,L1101        ; back to LD-SYNC if gap too big, that is,
                                ; a normal lead-in edge gap.

; but a short gap will be the sync pulse.
; in which case another edge should appear before B rises to $FF

        CALL    L1159           ; routine LD-EDGE-1
        RET     NC              ; return with time-out.

; proceed when the sync at the end of the lead-in is found.
; We are about to load data so change the border colours.

        LD      A,C             ; fetch long-term mask from C
        XOR     $03             ; and make blue/yellow.

        LD      C,A             ; store the new long-term byte.

        LD      H,$00           ; set up parity byte as zero.
        LD      B,$DC           ; timing (dec 220).  <-- original ROM has $B0 here [1446]
        JR      L113A           ; forward to LD-MARKER 
                                ; the loop mid entry point with the alternate
                                ; zero flag reset to indicate first byte 
                                ; is discarded.

; the loading loop loads each byte and is entered at the mid point.

;; LD-LOOP
L111B:  EX      AF,AF'          ; restore entry flags and type in A.
        JR      NZ,L1125        ; forward to LD-FLAG if awaiting initial flag
                                ; which is to be discarded.

        JR      NC,L112F        ; forward to LD-VERIFY if not to be loaded.
        LD      (IX+$00),L      ; place loaded byte at memory location.
        JR      L1134           ; forward to LD-NEXT

;; LD-FLAG
L1125:  RL      C               ; preserve carry (verify) flag in long-term
                                ; state byte. Bit 7 can be lost.

        XOR     L               ; compare type in A with first byte in L.
        RET     NZ              ; return if no match e.g. CODE vs. DATA.

; continue when data type matches.

        LD      A,C             ; fetch byte with stored carry
        RRA                     ; rotate it to carry flag again     
        LD      C,A             ; restore long-term port state.

        INC     DE              ; increment length ??
        JR      L1136           ; forward to LD-DEC.
                                ; but why not to location after ?

; for verification the byte read from tape is compared with that in memory.

;; LD-VERIFY
L112F:  LD      A,(IX+$00)      ; fetch byte from memory.
        XOR     L               ; compare with that on tape
        RET     NZ              ; return if not zero. 

;; LD-NEXT
L1134:  INC     IX              ; increment byte pointer.

;; LD-DEC
L1136:  DEC     DE              ; decrement length.
        EX      AF,AF'          ; store the flags.
        LD      B,$DE           ; timing (dec 222). <-- original ROM has $B2 here [1479]

; when starting to read 8 bits the receiving byte is marked with bit at right.
; when this is rotated out again then 8 bits have been read.

;; LD-MARKER
L113A:  LD      L,$01           ; initialize as %00000001

;; LD-8-BITS
L113C:  CALL    L1155           ; routine LD-EDGE-2 increments B relative to
                                ; gap between 2 edges.
        RET     NC              ; return with time-out.

        LD      A,$E9           ; the comparison byte (dec 233). <-- original ROM has $CB here [1487]
        CP      B               ; compare to incremented value of B.
                                ; if B is higher then bit on tape was set.
                                ; if <= then bit on tape is reset. 

        RL      L               ; rotate the carry bit into L.

        LD      B,$0DC          ; reset the B timer byte (dec 220). <-- original ROM has $B0 here [1492]
        JP      NC,L113C        ; JUMP back to LD-8-BITS

; when carry set then marker bit has been passed out and byte is complete.

        LD      A,H             ; fetch the running parity byte.
        XOR     L               ; include the new byte.
        LD      H,A             ; and store back in parity register.

        LD      A,D             ; check length of
        OR      E               ; expected bytes.
        JR      NZ,L111B        ; back to LD-LOOP 
                                ; while there are more.

; when all bytes loaded then parity byte should be zero.

        LD      A,H             ; fetch parity byte.
        CP      $01             ; set carry if zero.
        RET                     ; return
                                ; in no carry then error as checksum disagrees.

; -------------------------
; Check signal being loaded
; -------------------------
; An edge is a transition from one mic state to another.
; More specifically a change in bit 6 of value input from port $FE.
; Graphically it is a change of border colour, say, blue to yellow.
; The first entry point looks for two adjacent edges. The second entry point
; is used to find a single edge.
; The B register holds a count, up to 256, within which the edge (or edges) 
; must be found. The gap between two edges will be more for a '1' than a '0'

;; LD-EDGE-2
L1155:  CALL    L1159           ; call routine LD-EDGE-1 below.
        RET     NC              ; return if space pressed or time-out.
                                ; else continue and look for another adjacent 
                                ; edge which together represent a bit on the 
                                ; tape.

; this entry point is used to find a single edge from above but also 
; when detecting a read-in signal on the tape.

L1159:  LD      A,$0A           ; a delay value (dec 10). <-- original ROM has $16 here. [1512]

;; LD-DELAY
L115B:  DEC     A               ; decrement counter
        JR      NZ,L115B        ; loop back to LD-DELAY 22 times.

        AND     A               ; clear carry.

;; LD-SAMPLE
L115F:  INC     B               ; increment the time-out counter.
        RET     Z               ; return with failure when $FF passed.

        LD      A,$7F           ; prepare to read keyboard and EAR port
        IN      A,($FE)         ; row $7FFE. bit 6 is EAR, bit 0 is SPACE key.
        RRA                     ; test outer key the space. (bit 6 moves to 5)
        RET     NC              ; return if space pressed.

        XOR     C               ; compare with initial long-term state.
        AND     $20             ; isolate bit 5
        JR      Z,L115F         ; back to LD-SAMPLE if no edge.

; but an edge, a transition of the EAR bit, has been found so switch the
; long-term comparison byte containing both border colour and EAR bit.

        LD      A,C             ; fetch comparison value.
        CPL                     ; switch the bits
        LD      C,A             ; and put back in C for long-term.

        AND     $07             ; isolate new colour bits.
        OR      $08             ; set bit 3 - MIC off.
        OUT     ($FE),A         ; send to port to effect the change of colour.

        SCF                     ; set carry flag signaling edge found within
                                ; time allowed.
        RET                     ; return.

; ----------------------------
; 25 unused bytes: $1177-$118F
; ----------------------------

        DEFB    $00, $00, $00, $00, $00, $00, $00, $00
        DEFB    $00, $00, $00, $00, $00, $00, $00, $00
        DEFB    $00, $00, $00, $00, $00, $00, $00, $00
        DEFB    $00


; -----------------------------------------------------------------
; Save header and program/data bytes - TURBO VERSION (double speed)
; -----------------------------------------------------------------
; This is a slightly modified version of the ZX-Spectrum 'Save' ROM routine,
; relocated from $04C2 to $1190.
; All comments are borrowed from the The Incomplete Spectrum ROM Assembly.
; On entry:
; HL points to start of data.
; IX points to descriptor.
; The accumulator is set to  $00 for a header, $FF for data.

L1190:  LD      HL,L120D        ; address: SA/LD-RET
        PUSH    HL              ; is pushed as common exit route.

        LD      HL,$1F80        ; a timing constant H=$1F, L=$80
                                ; inner and outer loop counters
                                ; a five second lead-in is used for a header.

        BIT     7,A             ; test one bit of accumulator.
        JR      Z,L119E         ; skip to SA-FLAG if a header is being saved.

; else is data bytes and a shorter lead-in is used.

        LD      HL,$0C98        ; another timing value H=$0C, L=$98.
                                ; a two second lead-in is used for the data.

;; SA-FLAG
L119E:  EX      AF,AF'          ; save flag
        INC     DE              ; increase length by one.
        DEC     IX              ; decrease start.

        DI                      ; disable interrupts

        LD      A,$02           ; select red for border, microphone bit on.
        LD      B,A             ; also does as an initial slight counter value.

;; SA-LEADER
L11A6:  DJNZ    L11A6           ; self loop to SA-LEADER for delay.
                                ; after initial loop, count is $A4 (or $A3)

        OUT     ($FE),A         ; output byte $02/$0D to tape port.

        XOR     $0F             ; switch from RED (mic on) to CYAN (mic off).

        LD      B,$A4           ; hold count. also timed instruction.

        DEC     L               ; originally $80 or $98.
                                ; but subsequently cycles 256 times.

        JR      NZ,L11A6        ; back to SA-LEADER until L is zero.

; the outer loop is counted by H

        DEC     B               ; decrement count
        DEC     H               ; originally twelve or thirty-one.
        JP      P,L11A6         ; back to SA-LEADER until H becomes $FF

; now send a sync pulse. At this stage mic is off and A holds value
; for mic on.
; A sync pulse is much shorter than the steady pulses of the lead-in.

        LD      B,$2F           ; another short timed delay.

;; SA-SYNC-1
L11B8:  DJNZ    L11B8           ; self loop to SA-SYNC-1

        OUT     ($FE),A         ; switch to mic on and red.
        LD      A,$0D           ; prepare mic off - cyan
        LD      B,$37           ; another short timed delay.

;; SA-SYNC-2
L11C0:  DJNZ    L11C0           ; self loop to SA-SYNC-2
        OUT     ($FE),A         ; output mic off, cyan border.
        LD      BC,$3B0E        ; B=$3B time(*), C=$0E, YELLOW, MIC OFF.

        EX      AF,AF'          ; restore saved flag
                                ; which is 1st byte to be saved.

        LD      L,A             ; and transfer to L.
                                ; the initial parity is A, $FF or $00.
        JP      L11D5           ; JUMP forward to SA-START
                                ; the mid entry point of loop.

; During the save loop a parity byte is maintained in H.
; the save loop begins by testing if reduced length is zero and if so
; the final parity byte is saved reducing count to $FFFF.

L11CC:  LD      A,D             ; fetch high byte
        OR      E               ; test against low byte.
        JR      Z,L11DC         ; forward to SA-PARITY if zero.

        LD      L,(IX+$00)      ; load currently addressed byte to L.

;; SA-LOOP-P
L11D3:  LD      A,H             ; fetch parity byte.
        XOR     L               ; exclusive or with new byte.

; -> the mid entry point of loop.

;; SA-START
L11D5:  LD      H,A             ; put parity byte in H.
        LD      A,$01           ; prepare blue, mic=on.
        SCF                     ; set carry flag ready to rotate in.
        JP      L11F3           ; JUMP forward to SA-8-BITS

;; SA-PARITY
L11DC:  LD      L,H             ; transfer the running parity byte to L and
        JR      L11D3           ; back to SA-LOOP-P 
                                ; to output that byte before quitting normally.

; The entry point to save yellow part of bit.
; A bit consists of a period with mic on and blue border followed by 
; a period of mic off with yellow border. 
; Note. since the DJNZ instruction does not affect flags, the zero flag is 
; used to indicate which of the two passes is in effect and the carry 
; maintains the state of the bit to be saved.

L11DF:  LD      A,C             ; fetch 'mic on and yellow' which is 
                                ; held permanently in C.
        BIT     7,B             ; set the zero flag. B holds $3E.

; The entry point to save 1 entire bit. For first bit B holds $3B(*).
; Carry is set if saved bit is 1. zero is reset NZ on entry.

L11E2:  DJNZ    L11E2           ; self loop for delay to SA-BIT-1

        JR      NC,L11EA        ; forward to SA-OUT if bit is 0.

; but if bit is 1 then the mic state is held for longer.

        LD      B,$1F           ; set timed delay (dec 31). <-- original ROM has $42 here. [1305]

;; SA-SET
L11E8:  DJNZ    L11E8           ; self loop to SA-SET
                                ; (roughly an extra 31*13 clock cycles)

;; SA-OUT
L11EA:  OUT     ($FE),A         ; blue and mic on OR  yellow and mic off.

        LD      B,$1A           ; set up delay (dec 26) <-- original ROM has $3E here [1311].
        JR      NZ,L11DF        ; back to SA-BIT-2 if zero reset NZ (first pass)

; proceed when the blue and yellow bands have been output.

        DEC     B               ; change value $3E to $3D.
        XOR     A               ; clear carry flag (ready to rotate in).
        INC     A               ; reset zero flag i.e. NZ.

;; SA-8-BITS
L11F3:  RL      L               ; rotate left through carry
                                ; C<76543210<C  
        JP      NZ,L11E2        ; JUMP back to SA-BIT-1 
                                ; until all 8 bits done.

; when the initial set carry is passed out again then a byte is complete.

        DEC     DE              ; decrease length
        INC     IX              ; increase byte pointer
        LD      B,$0D           ; set up timing (dec 13). <-- original ROM has $31 here. [1326]

        LD      A,$7F           ; test the space key and
        IN      A,($FE)         ; return to common exit (to restore border)
        RRA                     ; if a space is pressed
        RET     NC              ; return to SA/LD-RET.

; now test if byte counter has reached $FFFF.

        LD      A,D             ; fetch high byte
        INC     A               ; increment.
        JP      NZ,L11CC        ; JUMP to SA-LOOP if more bytes.

        LD      B,$3B           ; a final delay. 

;; SA-DELAY
L120A:  DJNZ    L120A           ; self loop to SA-DELAY
        RET                     ; return to SA/LD-RET

; ------------------------------
; THE 'SAVE/LOAD RETURN' ROUTINE
; ------------------------------
; The address of this routine is pushed on the stack prior to any load/save
; operation and it handles normal completion with the restoration of the
; border and also abnormal termination when the break key, or to be more
; precise the space key is pressed during a tape operation.

; Another copy of the Spectrum's SAVE/LOAD RETURN Routine.
; The REPORT-Da section is zeroed out by NOPs.

;; SA/LD-RET
L120D:  PUSH    AF              ; preserve accumulator throughout.
        LD      A,($5C48)       ; fetch border colour from BORDCR.
        AND     $38             ; mask off paper bits.
        RRCA                    ; rotate    
        RRCA                    ; to the    
        RRCA                    ; range 0-7.

        OUT     ($FE),A         ; change the border colour.

        LD      A,$7F           ; read from port address $7FFE the
        IN      A,($FE)         ; row with the space key at outside.

        RRA                     ; test for space key pressed.
        EI                      ; enable interrupts
        JR      C,L1222         ; forward to SA/LD-END if not

;; REPORT-Da
        NOP                     ; RST 08H changed to NOP
        NOP                     ; DEBF $0C changed to NOP

;; SA/LD-END
L1222:  POP     AF              ; restore the accumulator.
        RET                     ; return.    

; -----------------------------
; 189 unused bytes: $1224-$12E0
; -----------------------------

        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $00, $00, $00, $00, $00, $00, $00, $00
        DEFB    $00, $00, $00, $00, $00

; Part of the original Spectrum ROM 'LOAD' routine copied here again
; but actually never gets called - considered as garbage.
; The comments are here to recognize the origin.
; Code relocated from $05DF to $12E1.

;; End of LD-8-BITS part (address $12E1)

; when all bytes loaded then parity byte should be zero.

        LD      A,H             ; fetch parity byte.
        CP      $01             ; set carry if zero.
        RET                     ; return
                                ; in no carry then error as checksum disagrees.     

; -------------------------
; Check signal being loaded
; -------------------------
; An edge is a transition from one mic state to another.
; More specifically a change in bit 6 of value input from port $FE.
; Graphically it is a change of border colour, say, blue to yellow.
; The first entry point looks for two adjacent edges. The second entry point
; is used to find a single edge.
; The B register holds a count, up to 256, within which the edge (or edges) 
; must be found. The gap between two edges will be more for a '1' than a '0'
; so the value of B denotes the state of the bit (two edges) read from tape.

;; LD-EDGE-2
        CALL    L12E9           ; call routine LD-EDGE-1 below.
        RET     NC              ; return if space pressed or time-out.
                                ; else continue and look for another adjacent 
                                ; edge which together represent a bit on the 
                                ; tape.

; this entry point is used to find a single edge from above but also 
; when detecting a read-in signal on the tape.

;; LD-EDGE-1
L12E9:  LD      A,$0A           ; a delay value of twenty two. <-- original ROM has $16 here.

;; LD-DELAY
L12EB:  DEC     A               ; decrement counter
        JR      NZ,L12EB        ; loop back to LD-DELAY 22 times.

        AND     A               ; clear carry.

;; LD-SAMPLE
L12EF:  INC     B               ; increment the time-out counter.
        RET     Z               ; return with failure when $FF passed.

        LD      A,$7F           ; prepare to read keyboard and EAR port
        IN      A,($FE)         ; row $7FFE. bit 6 is EAR, bit 0 is SPACE key.
        RRA                     ; test outer key the space. (bit 6 moves to 5)
        RET     NC              ; return if space pressed.

        XOR     C               ; compare with initial long-term state.
        AND     $20             ; isolate bit 5
        JR      Z,L12EF         ; back to LD-SAMPLE if no edge.

; but an edge, a transition of the EAR bit, has been found so switch the
; long-term comparison byte containing both border colour and EAR bit. 

        LD      A,C             ; fetch comparison value.
        CPL                     ; switch the bits     
        LD      C,A             ; and put back in C for long-term.

        AND     $07             ; isolate new colour bits.
        OR      $08             ; set bit 3 - MIC off.
        OUT     ($FE),A         ; send to port to effect the change of colour.

        SCF                     ; set carry flag signaling edge found within
                                ; time allowed.
        RET                     ; return.


        DEFB    $00, $FF, $FF   ; 5 unused bytes
        DEFB    $FF, $FF

; --------------------
; WARM RESTART ROUTINE
; --------------------
; Switch back to Spectrum's IM1 mode and switch back the ROM. 
; The code execution resumed at the MAIN-G routine (L1313).
; Maybe NMI_VECT at L121C would be more appropriate?

;; WARM-RESTART
L130C:  IM      1               ; switch back to Interrupt Mode 1
        EI                      ; and enable interrupts
        LD      A,$00           ; switch back to original Spectrum ROM
        OUT     ($7F),A         ; the code from L1313 in the original ROM
                                ; is the MAIN-G

; ---------------------
; MICRO-MONITOR ROUTINE
; ---------------------

;; MM-MAIN
L1313:  LD      HL,$7000
        LD      B,$04
L1318:  LD      D,(HL)          ; save 4x2 bytes
        INC     HL              ; starting from $7000
        LD      E,(HL)          ; into stack
        INC     HL              ; ($7000-$7007)
        PUSH    DE
        DJNZ    L1318           ; loop until 8 bytes done

L131F:  LD      HL,$7002
        RES     0,(HL)          ; reset bit 0 at $7002
        CALL    L0EB6           ; call MM-CURSOR cursor handler which
                                ; returns cursor screen position in HL
        LD      ($7000),HL      ; store this position at $7000

        LD      C,$05           ; process 5 digits
        CALL    L13BF           ; call MM-INPUT5 to enter a 5 digits long
                                ; decimal value
        LD      A,(HL)          ; get value from the entered memory location
        EXX                     ; switch to alternate set
        LD      L,A
        LD      H,$00
        LD      A,$0A           ; display a ':' character
        CALL    L1442           ; call MM-DISPLAY
        LD      BC,$0064        ; display A/100
        CALL    L134D
        LD      BC,$000A        ; display A/10
        CALL    L134D
        LD      BC,$0001        ; display A/1
        CALL    L134D
        JR      L136B

; calculate A = HL / BC
; display integer part of HL and return the remainder

L134D:  LD      A,$00
        PUSH    HL              ; save original value

L1350:  SCF     
        CCF                     ; reset carry
        SBC     HL,BC           ; HL = HL - BC
        JP      M,L135A
        INC     A
        JR      L1350

L135A:  POP     HL              ; restore original value
        PUSH    AF
        CALL    L1442           ; call MM-DISPLAY
        POP     AF              ; to display integer part
        CP      $00
        RET     Z               ; return if no remainder

L1363:  SCF     
        CCF                     ; reset carry
        SBC     HL,BC           ; HL = HL - BC
        DEC     A
        JR      NZ,L1363
        RET                     ; HL = remainder

L136B:  LD      HL,($7000)      ; get cursor screen address
        DEC     HL              ; decrement X by 8 pixels
        LD      A,($7002)       ; invert bit 0. at $7002
        XOR     $01
        LD      ($7002),A
        LD      ($7000),HL

L137A:  RST     00H             ; CALL KEY-MAIN to
        LD      A,E             ; get a keypress
        CP      $09             ; is it key 'J' ?
        JR      NZ,L1393        ; jump if not

; This JUMP command only modifies the return address from NMI.
; Therefore this jump is enforced after exiting from MICRO-POKEer in main menu.

;; MM-JUMP
        LD      HL,$0000        ; get stack pointer
        ADD     HL,SP           ; into HL' register
        LD      DE,$0020        ; increment HL' by 32
        ADD     HL,DE           ; and store this value
        PUSH    HL              ; on stack
        EXX                     ; switch back to main set
        LD      D,H             ; get HL (entered memory address)
        LD      E,L             ; into DE
        POP     HL              ; get back HL'
        LD      (HL),E          ; which points to SP+32
        INC     HL              ; and store HL (memaddr) into
        LD      (HL),D          ; this address which is the 
                                ; return address from NMI
        JP      L13B0           ; and jump to MM-EXIT

L1393:  CP      $21             ; is it key 'ENTER' ?
        JR      Z,L131F         ; release cell and handle
                                ; cursor box again

        CP      $25             ; is it key 'Q' ?
        JR      Z,L13B0         ; jump to MM-EXIT to quit

        CP      $22             ; is it key 'P' ?
        JR      NZ,L137A        ; wait again if not

;; MM-POKE
        EXX
        PUSH    HL
        LD      C,$03           ; input 3 digits
        LD      IX,$7005
        CALL    L13C3           ; call MM-INPUT
        LD      A,L
        POP     HL              ; store entered decimal value
        LD      (HL),A
        JP      L136B           ; waiting for new command

;; MM-EXIT
L13B0:  LD      B,$04           ; restore the original
        LD      HL,$7007        ; ram content between
L13B5:  POP     DE              ; $7000-$7007 from the
        LD      (HL),E          ; stack
        DEC     HL
        LD      (HL),D
        DEC     HL
        DJNZ    L13B5
        JP      L007D           ; exit from Micro-monitor
                                ; jump back to MAIN-KEYS

;; MM-INPUT5
L13BF:  LD      IX,$7003        ; index register to $7003

;; MM-INPUT
L13C3:  LD      B,$05           ; clear 5 bytes of memory
        LD      HL,$7003        ; between $7003-$7007
L13C8:  LD      (HL),$00        ; these 5 locations will hold
        INC     HL              ; the 5 digits entered
        DJNZ    L13C8           ; loop until 5 bytes done

L13CD:  PUSH    BC              ; save C (B is already zero)

; this routine waits for a numeric key
; and converts to a decimal value (ie. key '5' -> 5)
; then displays it and calculate the entered decimal value (5 digits)

L13CE:  RST     00H             ; get a keypress
        LD      A,E
        CP      D               ; wait until a
        JR      Z,L13CE         ; key is pressed

        LD      HL,L14C0        ; table at L14C0
        LD      B,$0A           ; has 10 items
L13D8:  CP      (HL)            ; compare key
        JR      Z,L13E1         ; a jump if found
        INC     HL              ; skip to next
        INC     HL              ; item
        DJNZ    L13D8           ; and continue
        JR      L13CE           ; else start again

L13E1:  INC     HL              ; get numerical value
        LD      A,(HL)          ; of the key
        LD      (IX+$00),A      ; and store at (IX)
        INC     IX
        CALL    L1442           ; call MM-DISPLAY to
                                ; write digit

L13EB:  RST     00H             ; get a keypress
        LD      A,E
        CP      D               ; wait until the
        JR      NZ,L13EB        ; key is released

        POP     BC              ; restore C value
        DEC     C               ; count digits
        JR      NZ,L13CD        ; input the next number

; HL = decimal value entered

        LD      BC,$0000
        LD      DE,$7003        ; pointer to first digit
        LD      HL,$2710        ; HL = 10000 highest digit
        LD      A,(DE)          ; get first digit
        CALL    L142F           ; HL = HL * A
        ADD     HL,BC
        PUSH    HL
        POP     BC
        LD      HL,$03E8        ; HL = 1000
        INC     DE
        LD      A,(DE)          ; get second digit
        CALL    L142F           ; HL = HL * A
        ADD     HL,BC
        PUSH    HL
        POP     BC
        LD      HL,$0064        ; HL = 100
        INC     DE
        LD      A,(DE)          ; get third digit
        CALL    L142F           ; HL = HL * A
        ADD     HL,BC
        PUSH    HL
        POP     BC
        LD      HL,$000A        ; HL = 10
        INC     DE
        LD      A,(DE)          ; get fourth digit
        CALL    L142F           ; HL = HL * A
        ADD     HL,BC
        PUSH    HL
        POP     BC
        LD      HL,$0001        ; HL = 1
        INC     DE
        LD      A,(DE)          ; get fifth digit
        CALL    L142F           ; HL = HL * A
        ADD     HL,BC
        RET     

; calculate HL = HL * A

L142F:  CP      $00
        JR      NZ,L1437
        LD      HL,$0000        ; handle A = 0 case
        RET     

L1437:  PUSH    DE
        PUSH    HL
        POP     DE
L143A:  DEC     A               ; increment HL
        JR      Z,L1440         ; until A is zero
        ADD     HL,DE
        JR      L143A
L1440:  POP     DE
        RET     

;; MM-DISPLAY
; draws number a number on screen
; inputs: A - number
;         ($7000) - screen address

L1442:  PUSH    DE              ; register A has
        PUSH    HL              ; the number 
        PUSH    BC
        LD      BC,($7000)      ; BC has screen address
        LD      HL,L1489        ; numbers bitmap
        LD      DE,$0005        ; 5 pixels tall
L144F:  CP      $00             ; found the
        JR      Z,L1457         ; corresponding
        ADD     HL,DE           ; bitmap
        DEC     A
        JR      L144F           ; loop until we found

L1457:  PUSH    HL              ; HL has the bitmap address
        POP     DE              ; HL -> DE
        LD      H,B             ; BC -> HL
        LD      L,C
        LD      B,$05           ; process 5 pixels
L145D:  LD      A,($7002)
        BIT     0,A             ; odd/even character position?
        JR      Z,L146C         ; jump if using the left side

        LD      A,(DE)          ; get bitmap data
        RRA                     ; right shift by 4 bits
        RRA                     ; to the right nibble
        RRA                     ; position
        RRA                     ; and merge the two
        OR      (HL)            ; numbers into one byte
        JR      L146D

L146C:  LD      A,(DE)          ; get bitmap data

L146D:  LD      (HL),A          ; draw number(s) on screen
        INC     H               ; next screen row
        INC     DE              ; next bitmap row
        DJNZ    L145D           ; display five rows

        LD      A,($7002)
        BIT     0,A             ; odd/even character position?
        JR      Z,L1480         ; skip if only one side is used yet

        LD      HL,($7000)      ; skip to next byte only if
        INC     HL              ; both left-right side is filled
        LD      ($7000),HL      ; with a 3-pixel wide number

L1480:  XOR     $01             ; swap bitween odd-even
        LD      ($7002),A       ; and store it
        POP     BC
        POP     HL
        POP     DE
        RET     

; --------------------------------------------
; MINI NUMBERS CHARACTER SET FOR MICRO MONITOR
; --------------------------------------------
; Characters are 3 pixels wide and 5 pixels tall.
; Only the first 4 bits are used.

; number '0'

L1489:  DEFB    %11100000
        DEFB    %10100000
        DEFB    %10100000
        DEFB    %10100000
        DEFB    %11100000

; number '1'

        DEFB    %01100000
        DEFB    %10100000
        DEFB    %00100000
        DEFB    %00100000
        DEFB    %00100000

; number '2'

        DEFB    %11100000
        DEFB    %00100000
        DEFB    %11100000
        DEFB    %10000000
        DEFB    %11100000

; number '3'

        DEFB    %11100000
        DEFB    %00100000
        DEFB    %11100000
        DEFB    %00100000
        DEFB    %11100000

; number '4'

        DEFB    %10000000
        DEFB    %10000000
        DEFB    %10100000
        DEFB    %11100000
        DEFB    %00100000

; number '5'

        DEFB    %11100000
        DEFB    %10000000
        DEFB    %11100000
        DEFB    %00100000
        DEFB    %11100000

; number '6'

        DEFB    %11100000
        DEFB    %10000000
        DEFB    %11100000
        DEFB    %10100000
        DEFB    %11100000

; number '7'

        DEFB    %11100000
        DEFB    %00100000
        DEFB    %01000000
        DEFB    %01000000
        DEFB    %01000000

; number '8'

        DEFB    %11100000
        DEFB    %10100000
        DEFB    %11100000
        DEFB    %10100000
        DEFB    %11100000

; number '9'

        DEFB    %11100000
        DEFB    %10100000
        DEFB    %11100000
        DEFB    %00100000
        DEFB    %11100000

; symbol ':'

        DEFB    %00000000
        DEFB    %01000000
        DEFB    %00000000
        DEFB    %01000000
        DEFB    %00000000

; numeric keys conversion table

L14C0:  DEFB    $23,$00         ; key '0'
        DEFB    $24,$01         ; key '1'
        DEFB    $1C,$02         ; key '2'
        DEFB    $14,$03         ; key '3'
        DEFB    $0C,$04         ; key '4'
        DEFB    $04,$05         ; key '5'
        DEFB    $03,$06         ; key '6'
        DEFB    $0B,$07         ; key '7'
        DEFB    $13,$08         ; key '8'
        DEFB    $1B,$09         ; key '9'
        DEFB    $00

;; WAIT-SEC
L14D5:  PUSH    BC
        IM      1               ; select Interrupt Mode 1 to synchronize
        EI                      ; with vertical refresh
        PUSH    AF
        LD      B,$32           ; waits for 50 vertical refresh
L14DC:  HALT                    ; which equals 1 sec on an european Spectrum
        DJNZ    L14DC
        DI                      ; disable interrupts
        POP     AF
        POP     BC
        RET     

; -------------------------------
; 653 unused bytes: $14E3 - $176F
; -------------------------------

        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF

; ----------------------------------------------------------------------------
; THE 'KEYBOARD SCANNING' ROUTINE - COPY FROM THE ORIGINAL ZX SPECTRUM 48K ROM
; ----------------------------------------------------------------------------
; From keyboard and s-inkey$
; Returns 1 or 2 keys in DE, most significant shift first if any
; key values 0-39 else 255

;; KEY-SCAN
L1770:  LD      L,$2F           ; initial key value
                                ; valid values are obtained by subtracting
                                ; eight five times.
        LD      DE,$FFFF        ; a buffer to receive 2 keys.

        LD      BC,$FEFE        ; the commencing port address
                                ; B holds 11111110 initially and is also
                                ; used to count the 8 half-rows
;; KEY-LINE
L1778:  IN      A,(C)           ; read the port to A - bits will be reset
                                ; if a key is pressed else set.
        CPL                     ; complement - pressed key-bits are now set
        AND     $1F             ; apply 00011111 mask to pick up the
                                ; relevant set bits.

        JR      Z,L178D         ; forward to KEY-DONE if zero and therefore
                                ; no keys pressed in row at all.

        LD      H,A             ; transfer row bits to H
        LD      A,L             ; load the initial key value to A

;; KEY-3KEYS
L1781:  INC     D               ; now test the key buffer
        RET     NZ              ; if we have collected 2 keys already
                                ; then too many so quit.

;; KEY-BITS
L1783:  SUB     $08             ; subtract 8 from the key value
                                ; cycling through key values (top = $27)
                                ; e.g. 2F>   27>1F>17>0F>07
                                ;      2E>   26>1E>16>0E>06
        SRL     H               ; shift key bits right into carry.
        JR      NC,L1783        ; back to KEY-BITS if not pressed
                                ; but if pressed we have a value (0-39d)
 
        LD      D,E             ; transfer a possible previous key to D
        LD      E,A             ; transfer the new key to E
        JR      NZ,L1781        ; back to KEY-3KEYS if there were more
                                ; set bits - H was not yet zero.

;; KEY-DONE
L178D:  DEC     L               ; cycles 2F>2E>2D>2C>2B>2A>29>28 for
                                ; each half-row.
        RLC     B               ; form next port address e.g. FEFE > FDFE
        JR      C,L1778         ; back to KEY-LINE if still more rows to do.

        LD      A,D             ; now test if D is still FF ?
        INC     A               ; if it is zero we have at most 1 key
                                ; range now $01-$28  (1-40d)
        RET     Z               ; return if one key or no key.

        CP      $28             ; is it capsshift (was $27) ?
        RET     Z               ; return if so.

        CP      $19             ; is it symbol shift (was $18) ?
        RET     Z               ; return also

        LD      A,E             ; now test E
        LD      E,D             ; but first switch
        LD      D,A             ; the two keys.
        CP      $18             ; is it symbol shift ?
        RET                     ; return (with zero set if it was).
                                ; but with symbol shift now in D

        DEFB    $FF, $FF, $FF   ; 7 unused bytes
        DEFB    $FF, $FF, $FF
        DEFB    $FF

L17A8:  LD      A,D             ; check second key
        CP      $27             ; is it caps shift?
        JP      NZ,L007D        ; if no jump back to MAIN-KEYS
                                ; this allows only capital H keypress

;; SCROLL-MENU
L17AE:  IM      1               ; select Interrupt Mode 1 to synchronize
                                ; with the vertical refresh
        EI                      ; enable interrupts

                                ; this routine will fills up the bottom line
                                ; with extra white paper and black ink
                                ; the two corners will be white ink also
        LD      HL,$5AE0        ; last 'line' of attribute area
        LD      DE,$5AE2        ; address of the next word
        LD      (HL),$7F        ; left corner color: white paper and white ink
        INC     HL
        LD      (HL),$78        ; 01111000 = white paper, black ink
        LD      BC,$001E        ; copy the white paper, black ink color
        LDIR                    ; 30 times
        LD      (HL),$7F        ; right corner color: white paper and white ink

        LD      DE,L0890        ; pointer to menu text
        LD      BC,$015E        ; length of menu text (L09EE-L0890)

;; SCROLL-GETBITMAP
L17C9:  PUSH    BC
        LD      HL,$0488        ; pointer to character set (actually 0588H from chr32)
        LD      A,(DE)          ; get the next character from text
        LD      B,A             ; and calculate the address
        INC     DE              ; of the character bitmap
        PUSH    DE
        LD      DE,$0008        ; every character has 8 rows

;; SCROLL-PUTCHAR
L17D4:  ADD     HL,DE
        DJNZ    L17D4           ; HL contains the character bitmap address
        LD      DE,$50FF        ; first pixel-row of the bottom right corner

        LD      B,$08           ; will copy 8 pixel-rows

L17DC:  LD      A,(HL)          ; copy the character bitmap to the screen
        LD      (DE),A
        INC     HL              ; increment to the next bitmap row
        INC     D               ; increment to the next pixel-row
        DJNZ    L17DC

        LD      H,$08           ; scroll left by 8 pixels

;; SCROLL-CHAR
L17E4:  LD      DE,$50FF        ; first pixel-row of the bottom right corner
        LD      B,$08           ; scroll left all 8 pixel-rows

L17E9:  CALL    L1803           ; call SCROLL-LEFT routine
        INC     D               ; increment to the next pixel-row
        DJNZ    L17E9
        HALT                    ; wait for interrupt (screen refresh)
        DEC     H
        JR      NZ,L17E4

        POP     DE
        POP     BC
        DEC     BC
        LD      A,$7F           ; test the space key
        IN      A,($FE)
        RRA                     ; if a space is pressed
        RET     NC              ; return

        LD      A,B             ; continue drawing menu text
        OR      C               ; until finished
        JR      NZ,L17C9
        JP      L17AE           ; restart the scroller

;; SCROLL-LEFT
L1803:  PUSH    BC              ; scroll the bottom line left
        PUSH    DE              ; with one pixel
        PUSH    HL              ; except the left/right corners
        EX      DE,HL           ; those will hide scroll edges (white on white)
        LD      B,$1F           ; scroll only 30 characters

L1809:  RL      (HL)            ; HL is the screen address
        DEC     HL
        DJNZ    L1809
        POP     HL
        POP     DE
        POP     BC
        RET

; ------------------------------
; 1645 unused bytes: $1812-$1E7E
; ------------------------------

        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF

; $1E7F unused subroutine which
; starts turbo loading from $5B00 (after attributes)
; to the end of memory ($FFFF) then exit from MICRO-POKEer

        LD      HL,($5B00)
        EXX     
        LD      SP,$5A00        ; set stack to $5A00?
        LD      DE,$A500        ; $A500 length
        LD      IX,$5B00        ; load into $5B00
        LD      A,$0F
        SCF                     ; load data flag
        RST     10H             ; call turbo load routine
        JP      L052A           ; jump to EXIT-POKER

L1E94:  DEFB    $00             ; type basic program
        DEFM    "LOADER    "    ; filename
        DEFB    $0A, $01        ; total length 266 bytes (incl vars)
        DEFB    $0A, $00        ; autostart line 10
        DEFB    $AF, $00        ; length of program 175 bytes

L1EA5:  DEFB    $03             ; type code
        DEFM    "SCREEN    "    ; filename
        DEFB    $02, $1B        ; length 6914 bytes
        DEFB    $00, $40        ; start address $4000
        DEFB    $00, $80        ; unused (always $8000)

; $1EB6 - 7 unused bytes

        DEFB    $20, $6D, $02, $0A, $00, $C4, $00

; $1EBD - unused header

        DEFB    $03
        DEFM    "V&REW ª   "
        DEFB    $02, $1B, $00, $40, $00, $80

; -----------------------------
; 306 unused bytes: $1ECE-$1FFF
; -----------------------------

        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF
        DEFB    $FF, $FF

;end

; Acknowledgements
; ----------------
; The MICRO-POKEer device was made by Micro-Studio Hungary.
; The assembly formatting and the original ZX Spectrum ROM
; snippets are based on the Incomplete Spectrum ROM Assembly:
; http://www.wearmouth.demon.co.uk/zx82.htm
; Sjasm 0.42 can be downloaded from http://www.xl2s.tk/
;
; Credits
; -------
; Lajos Bicsak (bitbandit.org) for disassembling the MICRO-POKEer ROM.
;
; Known problems
; --------------
; Snapshots saved by "TURBO total RAM SAVE" option won't work with the
; saved Basic loader since it uses the Spectrum's original ROM loader.
