; COLECOVISION PORT — CONVERTED FROM MSX BY msx2cv.py ; SOURCE: DISASSEMBLY OF SPACE TROUBLE - HAL LABORATORY (1984) [6756] (MSX1 ROM) ; NOTE: Audio (PSG) requires separate conversion. ; COLECOVISION BIOS DEFINITIONS ************* ; (WRITE_REGISTER / FILL_VRAM / PUT_VRAM / WRITE_VRAM are ; implemented inline — no BIOS ROM needed for VDP ops) BOOT_UP: EQU $0000 BIOS_NMI: EQU $0066 PLAY_SONGS: EQU $1F61 ACTIVATEP: EQU $1F64 REFLECT_VERTICAL: EQU $1F6A REFLECT_HORIZONTAL: EQU $1F6D ROTATE_90: EQU $1F70 ENLARGE: EQU $1F73 CONTROLLER_SCAN: EQU $1F76 DECODER: EQU $1F79 GAME_OPT: EQU $1F7C LOAD_ASCII: EQU $1F7F MODE_1: EQU $1F85 UPDATE_SPINNER: EQU $1F88 INIT_TABLEP: EQU $1F8B PUT_VRAMP: EQU $1F91 INIT_SPR_ORDERP: EQU $1F94 INIT_TIMERP: EQU $1F9A REQUEST_SIGNALP: EQU $1FA0 TEST_SIGNALP: EQU $1FA3 WRITE_REGISTERP: EQU $1FA6 INIT_WRITERP: EQU $1FAF SOUND_INITP: EQU $1FB2 PLAY_ITP: EQU $1FB5 INIT_TABLE: EQU $1FB8 GET_VRAM: EQU $1FBB INIT_SPR_NM_TBL: EQU $1FC1 WR_SPR_NM_TBL: EQU $1FC4 INIT_TIMER: EQU $1FC7 FREE_SIGNAL: EQU $1FCA REQUEST_SIGNAL: EQU $1FCD TEST_SIGNAL: EQU $1FD0 TIME_MGR: EQU $1FD3 TURN_OFF_SOUND: EQU $1FD6 READ_REGISTER: EQU $1FDC READ_VRAM: EQU $1FE2 INIT_WRITER: EQU $1FE5 WRITER: EQU $1FE8 POLLER: EQU $1FEB SOUND_INIT: EQU $1FEE PLAY_IT: EQU $1FF1 SOUND_MAN: EQU $1FF4 ACTIVATE: EQU $1FF7 PUTOBJ: EQU $1FFA RAND_GEN: EQU $1FFD ; COLECOVISION I/O PORT DEFINITIONS ********* KEYBOARD_PORT: EQU $80 DATA_PORT: EQU $BE CTRL_PORT: EQU $BF JOY_PORT: EQU $C0 CONTROLLER_02: EQU $F5 CONTROLLER_01: EQU $FC SOUND_PORT: EQU $FF CV_JOYSTICK_BUF: EQU $6FFE ; controller state buffer CV_VDP_RD_SHADOW: EQU $7FF8 ; holds $BE (VDP data port) for LD A,(VDP_RD) CV_VDP_WR_SHADOW: EQU $7FF9 ; holds $BE (VDP data port) for LD A,(VDP_WR) ; DISASSEMBLED WITH z80msx_disasm.py ; OUTPUT FORMAT: tniasm 0.45 (Z80 mode) VDP_RD: EQU CV_VDP_RD_SHADOW ; CV RAM shadow (init'd to $BE) VDP_WR: EQU CV_VDP_WR_SHADOW ; CV RAM shadow (init'd to $BE) RDSLT: EQU $000C WRSLT: EQU $0014 CALBAS: EQU $001C INITXT: EQU $001E INIT32: EQU $0021 INIGRP: EQU $0024 INIMLT: EQU $0027 SETTXT: EQU $002A SETT32: EQU $002D SETGRP: EQU $0030 SETMLT: EQU $0033 CALPAT: EQU $0036 CALATR: EQU $0039 GSPSIZ: EQU $003C GRPPRT: EQU $003F GICINI: EQU $0042 DISSCR: EQU $0045 WRTVDP: EQU $0047 ENASCR: EQU $0048 WRTVRM: EQU $004D SETRD: EQU $0050 SETWRT: EQU $0053 FILVRM: EQU $0056 LDIRVM: EQU $005C LDIRMV: EQU $0061 LDIRVM2: EQU $0064 CHGMOD: EQU $006C CHGCLR: EQU $006F NMI_BIOS: EQU $0072 CLRSPR: EQU $0075 INITSP: EQU $0078 WRTSPR: EQU $007B RDSPR: EQU $007E SPRSAV: EQU $0081 WRTPSG: EQU $0093 RDPSG: EQU $0096 STRTMS: EQU $0099 GTSTCK: EQU $009C GTTRIG: EQU $009F GTPAD: EQU $00A2 GTPDL: EQU $00A5 KILBUF: EQU $00A8 CALBAS2: EQU $00AB CHGCAP: EQU $0132 RDVDP: EQU $013E SNSMAT: EQU $0141 RG0SAV: EQU $3380 ; remapped from $F380 RG1SAV: EQU $3381 ; remapped from $F381 RG2SAV: EQU $3382 ; remapped from $F382 RG3SAV: EQU $3383 ; remapped from $F383 RG4SAV: EQU $3384 ; remapped from $F384 RG5SAV: EQU $3385 ; remapped from $F385 RG6SAV: EQU $3386 ; remapped from $F386 RG7SAV: EQU $3387 ; remapped from $F387 SCRMOD: EQU $33A7 ; remapped from $F3A7 OLDSCR: EQU $33A9 ; remapped from $F3A9 CSRY: EQU $33AE ; remapped from $F3AE CSRX: EQU $33AF ; remapped from $F3AF FORCLR: EQU $33B4 ; remapped from $F3B4 BAKCLR: EQU $33B5 ; remapped from $F3B5 BDRCLR: EQU $33B6 ; remapped from $F3B6 ATRBYT: EQU $33C0 ; remapped from $F3C0 CRTCNT: EQU $33D6 ; remapped from $F3D6 LINLEN: EQU $33D7 ; remapped from $F3D7 BOTTOM: EQU $3CA2 ; remapped from $FCA2 EXPTBL: EQU $3CC4 ; remapped from $FCC4 SLTTBL: EQU $3CC8 ; remapped from $FCC8 EXBRSA: EQU $3CCA ; remapped from $FCCA HOOK_ISR0: EQU $3D9A ; remapped from $FD9A HOOK_ISR1: EQU $3D9B ; remapped from $FD9B MASTER_SLOT: EQU $3FFF ; remapped from $FFFF ; GAME RAM DEFINITIONS (AUTO-DETECTED) ****** RAM_E000: EQU $2000 ; remapped from $E000 RAM_E002: EQU $2002 ; remapped from $E002 RAM_E00C: EQU $200C ; remapped from $E00C RAM_E00D: EQU $200D ; remapped from $E00D RAM_E00E: EQU $200E ; remapped from $E00E RAM_E00F: EQU $200F ; remapped from $E00F RAM_E010: EQU $2010 ; remapped from $E010 RAM_E011: EQU $2011 ; remapped from $E011 RAM_E012: EQU $2012 ; remapped from $E012 RAM_E013: EQU $2013 ; remapped from $E013 RAM_E014: EQU $2014 ; remapped from $E014 RAM_E015: EQU $2015 ; remapped from $E015 RAM_E016: EQU $2016 ; remapped from $E016 RAM_E018: EQU $2018 ; remapped from $E018 RAM_E019: EQU $2019 ; remapped from $E019 RAM_E01A: EQU $201A ; remapped from $E01A RAM_E01B: EQU $201B ; remapped from $E01B RAM_E01C: EQU $201C ; remapped from $E01C RAM_E01E: EQU $201E ; remapped from $E01E RAM_E01F: EQU $201F ; remapped from $E01F RAM_E020: EQU $2020 ; remapped from $E020 RAM_E021: EQU $2021 ; remapped from $E021 RAM_E022: EQU $2022 ; remapped from $E022 RAM_E023: EQU $2023 ; remapped from $E023 RAM_E024: EQU $2024 ; remapped from $E024 RAM_E025: EQU $2025 ; remapped from $E025 RAM_E026: EQU $2026 ; remapped from $E026 RAM_E027: EQU $2027 ; remapped from $E027 RAM_E028: EQU $2028 ; remapped from $E028 RAM_E029: EQU $2029 ; remapped from $E029 RAM_E02A: EQU $202A ; remapped from $E02A RAM_E02B: EQU $202B ; remapped from $E02B RAM_E02C: EQU $202C ; remapped from $E02C RAM_E02D: EQU $202D ; remapped from $E02D RAM_E02F: EQU $202F ; remapped from $E02F RAM_E040: EQU $2040 ; remapped from $E040 RAM_E042: EQU $2042 ; remapped from $E042 RAM_E043: EQU $2043 ; remapped from $E043 RAM_E045: EQU $2045 ; remapped from $E045 RAM_E046: EQU $2046 ; remapped from $E046 RAM_E047: EQU $2047 ; remapped from $E047 RAM_E048: EQU $2048 ; remapped from $E048 RAM_E04A: EQU $204A ; remapped from $E04A RAM_E04C: EQU $204C ; remapped from $E04C RAM_E04E: EQU $204E ; remapped from $E04E RAM_E04F: EQU $204F ; remapped from $E04F RAM_E050: EQU $2050 ; remapped from $E050 RAM_E056: EQU $2056 ; remapped from $E056 RAM_E057: EQU $2057 ; remapped from $E057 RAM_E058: EQU $2058 ; remapped from $E058 RAM_E05A: EQU $205A ; remapped from $E05A RAM_E05B: EQU $205B ; remapped from $E05B RAM_E05C: EQU $205C ; remapped from $E05C RAM_E05D: EQU $205D ; remapped from $E05D RAM_E05E: EQU $205E ; remapped from $E05E RAM_E05F: EQU $205F ; remapped from $E05F RAM_E060: EQU $2060 ; remapped from $E060 RAM_E064: EQU $2064 ; remapped from $E064 RAM_E065: EQU $2065 ; remapped from $E065 RAM_E066: EQU $2066 ; remapped from $E066 RAM_E067: EQU $2067 ; remapped from $E067 RAM_E068: EQU $2068 ; remapped from $E068 RAM_E069: EQU $2069 ; remapped from $E069 RAM_E070: EQU $2070 ; remapped from $E070 RAM_E074: EQU $2074 ; remapped from $E074 RAM_E075: EQU $2075 ; remapped from $E075 RAM_E076: EQU $2076 ; remapped from $E076 RAM_E077: EQU $2077 ; remapped from $E077 RAM_E080: EQU $2080 ; remapped from $E080 RAM_E082: EQU $2082 ; remapped from $E082 RAM_E088: EQU $2088 ; remapped from $E088 RAM_E08A: EQU $208A ; remapped from $E08A RAM_E0B0: EQU $20B0 ; remapped from $E0B0 RAM_E0C0: EQU $20C0 ; remapped from $E0C0 RAM_E0C2: EQU $20C2 ; remapped from $E0C2 RAM_E0C5: EQU $20C5 ; remapped from $E0C5 RAM_E0C8: EQU $20C8 ; remapped from $E0C8 RAM_E0CA: EQU $20CA ; remapped from $E0CA RAM_E0F0: EQU $20F0 ; remapped from $E0F0 RAM_E100: EQU $2100 ; remapped from $E100 RAM_E104: EQU $2104 ; remapped from $E104 RAM_E105: EQU $2105 ; remapped from $E105 RAM_E106: EQU $2106 ; remapped from $E106 RAM_E107: EQU $2107 ; remapped from $E107 RAM_E110: EQU $2110 ; remapped from $E110 RAM_E114: EQU $2114 ; remapped from $E114 RAM_E120: EQU $2120 ; remapped from $E120 RAM_E122: EQU $2122 ; remapped from $E122 RAM_E125: EQU $2125 ; remapped from $E125 RAM_E126: EQU $2126 ; remapped from $E126 RAM_E12B: EQU $212B ; remapped from $E12B RAM_E130: EQU $2130 ; remapped from $E130 RAM_E132: EQU $2132 ; remapped from $E132 RAM_E135: EQU $2135 ; remapped from $E135 RAM_E210: EQU $2210 ; remapped from $E210 RAM_E300: EQU $2300 ; remapped from $E300 RAM_E400: EQU $2400 ; remapped from $E400 RAM_E480: EQU $2480 ; remapped from $E480 RAM_E490: EQU $2490 ; remapped from $E490 RAM_E500: EQU $2500 ; remapped from $E500 RAM_E540: EQU $2540 ; remapped from $E540 RAM_E580: EQU $2580 ; remapped from $E580 RAM_E5C0: EQU $25C0 ; remapped from $E5C0 RAM_E700: EQU $2700 ; remapped from $E700 RAM_E740: EQU $2740 ; remapped from $E740 RAM_E758: EQU $2758 ; remapped from $E758 RAM_F200: EQU $3200 ; remapped from $F200 FNAME "output/Space Trouble - CV.ROM" CPU Z80 ORG $8000 ; ============================================================ ; COLECOVISION CARTRIDGE HEADER ($8000 – $8023) ; ============================================================ DW $AA55 ; cart magic DB $00, $00 ; RST stub padding DB $00, $00 DB $00, $00 DW CV_JOYSTICK_BUF ; BIOS POLLER writes controller state here DW CV_GAME_ENTRY ; game entry point (see CV_GAME_ENTRY label below) DB $C3, $21, $80 ; RST 0 stub: JP $8021 DB $C3, $21, $80 ; RST 1 stub DB $C3, $21, $80 ; RST 2 stub DB $C3, $21, $80 ; RST 3 stub DB $C3, $21, $80 ; RST 4 stub DB $C3, $21, $80 ; RST 5 stub DB $C3, $21, $80 ; RST 6/NMI placeholder ; CART_ENTRY ($8021) — BIOS NMI handler calls this every 60 Hz CART_ENTRY: JP CV_NMI CV_GAME_ENTRY: JP CV_STARTUP ; debug/init code at end of ROM CV_GAME_CODE_START: LD ($3D9F), A LD HL, $893C LD ($3DA0), HL CALL SUB_4C93 CALL SUB_4AA5 DB $FB LD SP, $3200 ; RAM_F200 CV_GAME_RESTART: CALL SUB_4EA2 CALL VDP_DATA_4B97 CALL SUB_4230 LD A, ($200F) ; RAM_E00F LD ($205F), A ; RAM_E05F JR LOC_4038 LOC_402E: LD A, $03 LD ($2040), A ; RAM_E040 LD A, $01 LD ($2042), A ; RAM_E042 LOC_4038: LD A, $01 LD ($201F), A ; RAM_E01F CALL SUB_4C40 CALL DELAY_LOOP_4F84 CALL DELAY_LOOP_4289 CALL SUB_4FA7 CALL SUB_57FB LOC_404C: CALL SUB_49EB CALL DELAY_LOOP_4EE9 CALL SUB_4E1A CALL DELAY_LOOP_43C7 CALL DELAY_LOOP_43A6 CALL DELAY_LOOP_42DF CALL VDP_DATA_4320 CALL SUB_43DD LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_4072 CALL SUB_4242 CALL CV_TITLE_CURSOR_UPDATE JR LOC_407C LOC_4072: CALL SUB_41FA LD A, ($201F) ; RAM_E01F AND A CALL NZ, SUB_4C4B LOC_407C: CALL LOC_49E5 CALL SUB_57BA LOC_4082: LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_4092 LD A, ($2018) ; RAM_E018 CP $03 JP Z, LOC_402E JR LOC_409A LOC_4092: LD A, ($2043) ; RAM_E043 CP $05 JP Z, LOC_4151 LOC_409A: LD A, ($2025) ; RAM_E025 AND A JR NZ, LOC_40C0 CALL DELAY_LOOP_464E LD A, $01 LD ($201C), A ; RAM_E01C LD A, ($2020) ; RAM_E020 LD ($2025), A ; RAM_E025 LD A, ($2100) ; RAM_E100 CP $80 JR NC, LOC_40C0 CALL SUB_44A6 LD IY, $2100 ; RAM_E100 XOR A CALL SUB_4FBA LOC_40C0: LD A, ($2026) ; RAM_E026 AND A JR NZ, LOC_40D8 CALL SUB_4524 LD IY, $2110 ; RAM_E110 LD A, (IY+0) AND A JR Z, LOC_40DF LD A, $01 CALL SUB_4FBA LOC_40D8: LD A, ($2028) ; RAM_E028 AND A CALL Z, SUB_50F5 LOC_40DF: LD A, ($2027) ; RAM_E027 AND A JR NZ, LOC_40EA CALL SUB_4403 JR LOC_4109 LOC_40EA: CALL SUB_57BA LD A, ($2076) ; RAM_E076 AND A CALL NZ, SUB_41FA LD A, ($2066) ; RAM_E066 AND A CALL NZ, LOC_426B LD A, ($2067) ; RAM_E067 AND A CALL NZ, DELAY_LOOP_42DF LD A, ($205A) ; RAM_E05A AND A CALL NZ, DELAY_LOOP_435B LOC_4109: LD A, ($201C) ; RAM_E01C AND A CALL NZ, SUB_45E5 LD A, ($2012) ; RAM_E012 AND A CALL NZ, DELAY_LOOP_45B7 CALL SUB_5923 LD A, ($2014) ; RAM_E014 AND A JP Z, LOC_4082 LOC_4121: LD A, ($200E) ; RAM_E00E AND A JP Z, LOC_402E XOR A LD ($2018), A ; RAM_E018 LD HL, $2043 ; RAM_E043 LD A, (HL) CP $05 JR NZ, LOC_413A XOR A LD (HL), A DEC HL INC (HL) JR LOC_413C LOC_413A: DEC A LD (HL), A LOC_413C: CALL DELAY_LOOP_4F84 CALL SUB_4F26 LD A, B AND A JP NZ, LOC_4038 XOR A LD ($200E), A ; RAM_E00E LD ($2043), A ; RAM_E043 JP LOC_402E LOC_4151: LD A, $C0 LD ($2114), A ; RAM_E114 CALL SUB_4E9A CALL DELAY_LOOP_42DF XOR A LD ($202F), A ; RAM_E02F CALL SUB_53D6 CALL DELAY_LOOP_5351 LD BC, $0038 CALL SUB_5476 CALL SUB_4C8B LOC_416F: CALL SUB_5923 CALL SUB_57BA LD A, ($2025) ; RAM_E025 AND A JR NZ, LOC_416F LD A, ($2020) ; RAM_E020 LD ($2025), A ; RAM_E025 LD A, ($2100) ; RAM_E100 CP $80 JR C, LOC_418D CALL SUB_45E5 JR LOC_41A1 LOC_418D: CALL SUB_44A6 CALL SUB_5424 LD A, C DEC A JR Z, LOC_41AD DEC A JR Z, LOC_41CC LD A, ($205A) ; RAM_E05A AND A CALL NZ, DELAY_LOOP_435B LOC_41A1: CALL DELAY_LOOP_45B7 LD A, ($2014) ; RAM_E014 AND A JR Z, LOC_416F JP LOC_4121 LOC_41AD: CALL SUB_54CE NOP ; was CALL SUB_5515 — bonus items now animate during enemy descent NOP NOP LD BC, $01A0 CALL SUB_5476 CALL DELAY_LOOP_467D CALL SUB_4C40 NOP ; was CALL SUB_54A8 — powerups + aliens now both start from game loop NOP NOP LD HL, $2042 ; RAM_E042 INC (HL) INC HL LD (HL), $00 JP LOC_404C LOC_41CC: LD HL, $995A CALL DELAY_LOOP_5870 LD A, $01 LD ($202F), A ; RAM_E02F CALL SUB_53D6 LD A, $0A LD ($205A), A ; RAM_E05A CALL DELAY_LOOP_435B LD A, ($2100) ; RAM_E100 AND A JP M, LOC_41F1 CALL SUB_5440 LD A, $0F LD ($2107), A ; RAM_E107 LOC_41F1: LD A, ($2020) ; RAM_E020 LD ($2025), A ; RAM_E025 JP LOC_416F SUB_41FA: XOR A LD ($2076), A ; RAM_E076 LD HL, $2075 ; RAM_E075 LD B, $06 CALL SUB_4296 LD HL, $2070 ; RAM_E070 LD B, $06 CALL DELAY_LOOP_42AA LD HL, ($204A) ; RAM_E04A DB $EB LD BC, $0106 CALL DELAY_LOOP_42C2 LD DE, $2070 ; RAM_E070 LD HL, $2000 ; RAM_E000 LD B, $06 LOC_4220: LD A, (DE) CP (HL) RET C JR NZ, LOC_422A INC DE INC HL DJNZ LOC_4220 RET LOC_422A: LD A, (DE) LD (HL), A INC DE INC HL DJNZ LOC_422A SUB_4230: LD HL, $2000 ; RAM_E000 LD B, $06 CALL DELAY_LOOP_42AA LD DE, $1857 LD BC, $0106 CALL DELAY_LOOP_42C2 RET SUB_4242: LD HL, $20B0 ; RAM_E0B0 LD B, $06 CALL DELAY_LOOP_42AA LD HL, ($208A) ; RAM_E08A DB $EB LD BC, $0106 CALL DELAY_LOOP_42C2 LD A, ($200F) ; RAM_E00F AND A RET Z LD HL, $20F0 ; RAM_E0F0 LD B, $06 CALL DELAY_LOOP_42AA LD HL, ($20CA) ; RAM_E0CA DB $EB LD BC, $0106 JP DELAY_LOOP_42C2 LOC_426B: XOR A LD ($2066), A ; RAM_E066 LD HL, $2065 ; RAM_E065 LD B, $06 CALL SUB_4296 LD HL, $2060 ; RAM_E060 LD B, $06 CALL DELAY_LOOP_42AA LD DE, $1937 LD BC, $0106 CALL DELAY_LOOP_42C2 RET DELAY_LOOP_4289: LD HL, $2060 ; RAM_E060 LD B, $06 XOR A LOC_428F: LD (HL), A INC HL DJNZ LOC_428F JP LOC_426B SUB_4296: LD C, $00 LOC_4298: LD A, (HL) ADD A, C LD C, $00 LOC_429C: CP $0A JR C, LOC_42A5 SUB $0A INC C JR LOC_429C LOC_42A5: LD (HL), A DEC HL DJNZ LOC_4298 RET DELAY_LOOP_42AA: LD DE, $2480 ; RAM_E480 LOC_42AD: LD A, (HL) AND A JR NZ, LOC_42B9 LD A, $20 LD (DE), A INC DE INC HL DJNZ LOC_42AD RET LOC_42B9: LD A, (HL) ADD A, $30 LD (DE), A INC HL INC DE DJNZ LOC_42B9 RET DELAY_LOOP_42C2: LD HL, $2480 ; RAM_E480 LOC_42C5: PUSH DE PUSH HL PUSH BC LD B, $00 CALL PUT_VRAM ; LDIRVM ; LDIRVM ; CV: block copy RAM→VRAM POP BC POP HL LD D, $00 LD E, C ADD HL, DE POP DE PUSH HL LD H, $00 LD L, $20 ADD HL, DE DB $EB POP HL DJNZ LOC_42C5 RET DELAY_LOOP_42DF: LD HL, $2480 ; RAM_E480 LD B, $14 LD A, $20 LOC_42E6: LD (HL), A INC HL DJNZ LOC_42E6 LD HL, $2490 ; RAM_E490 LD A, ($205C) ; RAM_E05C AND A LD A, ($2043) ; RAM_E043 JR NZ, LOC_42F7 DEC A LOC_42F7: ADD A, A ADD A, A LD C, A LD A, ($2018) ; RAM_E018 LD D, A AND $02 ADD A, C LD C, A LD B, $00 SBC HL, BC LD A, D AND $01 ADD A, A ADD A, $70 LD (HL), A INC HL INC A LD (HL), A XOR A LD ($2067), A ; RAM_E067 LD ($205C), A ; RAM_E05C LD DE, $1999 LD BC, $0902 JP DELAY_LOOP_42C2 VDP_DATA_4320: XOR A LD ($2077), A ; RAM_E077 LD HL, $2480 ; RAM_E480 LD B, $14 LD A, $98 LOC_432B: LD (HL), A INC HL DJNZ LOC_432B LD A, ($2040) ; RAM_E040 DEC A LD HL, $2480 ; RAM_E480 LD B, $05 LOC_4338: CP B JR NC, LOC_4343 INC HL INC HL INC HL INC HL DJNZ LOC_4338 JR LOC_4351 LOC_4343: LD (HL), $78 INC HL LD (HL), $79 INC HL LD (HL), $7A INC HL LD (HL), $7B INC HL DJNZ LOC_4338 LOC_4351: LD DE, $197C LD BC, $0A02 CALL DELAY_LOOP_42C2 RET DELAY_LOOP_435B: LD C, A XOR A LD ($205A), A ; RAM_E05A LD A, ($2056) ; RAM_E056 LD ($205B), A ; RAM_E05B LD HL, $2050 ; RAM_E050 LD B, $08 LOC_436B: LD A, (HL) CP C JR NC, LOC_4394 LD (HL), $00 SUB C NEG LD C, A INC HL DJNZ LOC_436B LD A, $B0 LD ($2100), A ; RAM_E100 LD A, $20 LD ($2106), A ; RAM_E106 LD A, $09 LD ($2107), A ; RAM_E107 LD A, $03 LD ($2020), A ; RAM_E020 LD HL, $995A CALL DELAY_LOOP_5870 JR DELAY_LOOP_43A6 LOC_4394: SUB C LD (HL), A LD A, ($2056) ; RAM_E056 AND A JR NZ, DELAY_LOOP_43A6 LD HL, $99F9 LD A, ($205B) ; RAM_E05B AND A CALL NZ, DELAY_LOOP_5870 DELAY_LOOP_43A6: LD HL, $2480 ; RAM_E480 LD DE, $2050 ; RAM_E050 LD B, $08 LOC_43AE: LD A, (DE) ADD A, $67 LD (HL), A INC HL INC DE DJNZ LOC_43AE LD DE, $1997 LD BC, $0801 CALL DELAY_LOOP_42C2 LD HL, $99F9 LD A, ($2056) ; RAM_E056 AND A RET DELAY_LOOP_43C7: XOR A LD ($205A), A ; RAM_E05A LD HL, $2050 ; RAM_E050 LD B, $08 LD A, $08 LOC_43D2: LD (HL), A INC HL DJNZ LOC_43D2 LD HL, $012C LD ($2058), HL ; RAM_E058 RET SUB_43DD: LD C, $0A LD A, ($2042) ; RAM_E042 LD B, $00 LOC_43E4: CP C JR C, LOC_43EB INC B SUB C JR LOC_43E4 LOC_43EB: ADD A, $30 LD E, A LD A, B AND A JR NZ, LOC_43F6 LD A, $20 JR LOC_43F8 LOC_43F6: ADD A, $30 LOC_43F8: LD HL, $1ADC CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) INC HL LD A, E JP WRITE_VRAM ; tail-call WRTVRM -> WRITE_VRAM SUB_4403: LD A, ($202C) ; RAM_E02C INC A AND $07 LD ($202C), A ; RAM_E02C JR NZ, LOC_443D LD A, ($204E) ; RAM_E04E AND A JR Z, LOC_4418 DEC A LD ($204E), A ; RAM_E04E LOC_4418: LD A, ($201B) ; RAM_E01B INC A CP $02 JR NZ, LOC_442A LD HL, $2065 ; RAM_E065 INC (HL) LD A, $01 LD ($2066), A ; RAM_E066 XOR A LOC_442A: LD ($201B), A ; RAM_E01B LD A, ($2068) ; RAM_E068 LD D, A LD A, ($2069) ; RAM_E069 LD E, A LD A, ($2015) ; RAM_E015 AND D AND E CALL Z, SUB_4772 LOC_443D: LD B, $0E LD HL, $2132 ; RAM_E132 LOC_4442: PUSH HL LD E, (HL) INC HL LD D, (HL) INC HL LD A, (DE) ADD A, (HL) LD (HL), A INC DE INC HL LD A, (DE) ADD A, (HL) LD (HL), A INC DE DEC HL DEC HL DEC HL LD A, (DE) CP $80 JR NZ, LOC_4488 DEC HL DEC (HL) JR NZ, LOC_447D LD A, ($201A) ; RAM_E01A INC A AND $01 LD ($201A), A ; RAM_E01A JR NZ, LOC_446C LD DE, $2540 ; RAM_E540 JR LOC_446F LOC_446C: LD DE, $25C0 ; RAM_E5C0 LOC_446F: LD A, R AND $03 INC A LD (HL), A JR LOC_4487 DB $13, $1A, $77, $13, $18, $0A LOC_447D: PUSH BC DB $EB LD BC, $0008 AND A SBC HL, BC DB $EB POP BC LOC_4487: INC HL LOC_4488: LD (HL), E INC HL LD (HL), D POP HL LD DE, $0010 ADD HL, DE DJNZ LOC_4442 LD B, $0E LD HL, $2135 ; RAM_E135 CALL PSG_WRITE_4626 LD A, ($2021) ; RAM_E021 LD ($2027), A ; RAM_E027 LOC_44A0: LD A, $01 LD ($2012), A ; RAM_E012 RET SUB_44A6: LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_44B1 CALL SUB_5690 JR LOC_44D3 LOC_44B1: LD A, ($200D) ; RAM_E00D CP $03 JR Z, LOC_44CB CP $02 JR NZ, LOC_44D0 LD A, ($200F) ; RAM_E00F AND A JR Z, LOC_44C7 LD A, ($200E) ; RAM_E00E JR LOC_44D0 LOC_44C7: LD A, $02 JR LOC_44D0 LOC_44CB: CALL SUB_4AC1 JR LOC_44DE LOC_44D0: CALL CV_STICK_CHECK ; $00D5 ; CV: stick direction check LOC_44D3: ADD A, A LD L, A LD H, $00 LD DE, $852F ADD HL, DE LD E, (HL) INC HL LD D, (HL) LOC_44DE: LD HL, $2104 ; RAM_E104 LD A, ($2043) ; RAM_E043 CP $05 JR NZ, LOC_44EA LD E, $FE LOC_44EA: LD A, (HL) ADD A, E LD E, A CP $20 JR C, LOC_44A0 LD A, ($200E) ; RAM_E00E AND A LD A, E JR NZ, LOC_44FE CP $90 JR NC, LOC_44A0 JR LOC_4502 LOC_44FE: CP $A8 JR NC, LOC_44A0 LOC_4502: INC HL LD A, (HL) ADD A, D CP $94 JR NC, LOC_44A0 CP $14 JR C, LOC_44A0 LD (HL), A DEC HL LD (HL), E JR LOC_44A0 DB $00, $00, $FE, $00, $FE, $02, $00, $02 DB $02, $02, $02, $00, $02, $FE, $00, $FE DB $FE, $FE SUB_4524: LD IX, $2110 ; RAM_E110 LD A, (IX+0) AND A JR NZ, LOC_4599 LD A, ($2100) ; RAM_E100 CP $80 JR NC, LOC_45AF LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_4540 CALL SUB_56DE JR LOC_455B LOC_4540: LD A, ($200D) ; RAM_E00D CP $03 JR Z, LOC_4556 CP $02 JR NZ, LOC_4558 LD A, ($200F) ; RAM_E00F AND A JR Z, LOC_4556 LD A, ($200E) ; RAM_E00E JR LOC_4558 LOC_4556: LD A, $02 LOC_4558: CALL CV_FIRE_CHECK ; $00D8 ; CV: fire button check LOC_455B: AND A JR Z, LOC_45AF LD HL, ($2058) ; RAM_E058 LD DE, SETRD AND A SBC HL, DE JR NC, LOC_4574 LD DE, $012C ADD HL, DE LD A, ($205A) ; RAM_E05A INC A LD ($205A), A ; RAM_E05A LOC_4574: LD ($2058), HL ; RAM_E058 LD HL, $998A CALL DELAY_LOOP_5870 LD (IX+0), $01 LD (IX+6), $30 LD (IX+7), $0B LD A, ($2105) ; RAM_E105 ADD A, $04 LD (IX+5), A LD A, ($2104) ; RAM_E104 LD (IX+4), A JR LOC_45AF LOC_4599: LD A, (IX+4) SUB $08 LD (IX+4), A ADD A, $10 CP $C0 JR C, LOC_45AF LD (IX+4), $C0 LD (IX+0), $00 LOC_45AF: LD A, $02 LD ($2026), A ; RAM_E026 JP LOC_44A0 DELAY_LOOP_45B7: LD HL, $1B00 LD A, ($2010) ; RAM_E010 AND A JR NZ, LOC_45C2 LD L, $80 LOC_45C2: CALL CV_SETWRT ; SETWRT ; SETWRT ; CV: use CV_SETWRT shim LD A, (VDP_WR) LD C, A LD HL, $2104 ; RAM_E104 LD DE, RDSLT LD B, $11 LOC_45D1: PUSH BC LD B, $04 LOC_45D4: OUTI JR NZ, LOC_45D4 ADD HL, DE POP BC DJNZ LOC_45D1 XOR A LD ($2012), A ; RAM_E012 INC A LD ($2013), A ; RAM_E013 RET SUB_45E5: LD IX, $2100 ; RAM_E100 LD DE, $0010 LD B, $11 LOC_45EE: LD A, (IX+0) AND A JP P, LOC_461D DEC A CP $80 JR Z, LOC_460B LD (IX+0), A LD A, (IX+6) ADD A, $04 AND $0F ADD A, $20 LD (IX+6), A JR LOC_461D LOC_460B: LD (IX+4), $C0 LD (IX+0), $00 LD A, B CP $11 JR NZ, LOC_461D LD A, $01 LD ($2014), A ; RAM_E014 LOC_461D: ADD IX, DE DJNZ LOC_45EE XOR A LD ($201C), A ; RAM_E01C RET PSG_WRITE_4626: LD A, (HL) CP $A0 JR NC, LOC_4636 DEC HL LD A, (HL) CP $C0 JR Z, LOC_463A LD DE, $0011 JR LOC_464A LOC_4636: DEC HL LD A, $C0 LD (HL), A LOC_463A: DEC HL LD DE, $2700 ; RAM_E700 LD (HL), D DEC HL LD (HL), E DEC HL LD (HL), $FF DEC HL LD (HL), $00 LD DE, $0015 LOC_464A: ADD HL, DE DJNZ PSG_WRITE_4626 RET DELAY_LOOP_464E: LD IX, $2130 ; RAM_E130 LD DE, $0010 LD B, $0E LOC_4657: LD A, (IX+6) CP $84 JR C, LOC_4674 LD A, (IX+10) INC A AND $03 LD (IX+10), A LD HL, $8696 PUSH DE LD E, A LD D, $00 ADD HL, DE POP DE LD A, (HL) LD (IX+7), A LOC_4674: ADD IX, DE DJNZ LOC_4657 RET DB $0F, $0D, $04, $0B DELAY_LOOP_467D: LD A, ($2042) ; RAM_E042 DEC A AND $07 LD E, A LD D, $00 LD HL, $872E ADD HL, DE LD A, (HL) LD C, A LD B, $04 LD HL, $2014 LOC_4691: CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) INC HL LD A, C DJNZ LOC_4691 LD HL, $0500 LD BC, $00C0 XOR A CALL FILL_VRAM ; FILVRM ; FILVRM ; CV: fill VRAM LD HL, $1800 LD A, $A0 LD E, $18 LOC_46A9: LD BC, $0016 CALL FILL_VRAM ; FILVRM ; FILVRM ; CV: fill VRAM LD BC, $0020 ADD HL, BC INC A DEC E JR NZ, LOC_46A9 LD BC, $012C LOC_46BA: PUSH BC LD A, ($2300) ; RAM_E300 AND $03 PUSH AF CALL DELAY_LOOP_4735 PUSH IX LD HL, $0558 LD A, $01 LD C, $00 CALL SUB_4719 POP IX LD HL, $054F XOR A LD C, $00 CALL SUB_4719 POP AF INC A AND $03 LD ($2300), A ; RAM_E300 CALL DELAY_LOOP_4735 PUSH IX LD HL, $0558 LD A, $01 LD C, $FF CALL SUB_4719 POP IX LD HL, $054F XOR A LD C, $FF CALL SUB_4719 LD HL, $99D7 CALL DELAY_LOOP_5870 LD BC, $0002 LD D, $00 CALL SUB_49F2 POP BC DEC BC LD A, B OR C JR NZ, LOC_46BA RET DB $91, $51, $B1, $31, $61, $71, $D1, $F1 SUB_4719: LD B, $0A LOC_471B: LD E, (IX+0) LD D, $00 AND A PUSH HL JR Z, LOC_4727 ADD HL, DE JR LOC_4729 LOC_4727: SBC HL, DE LOC_4729: PUSH AF LD A, C CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) POP AF POP HL INC IX DJNZ LOC_471B RET DELAY_LOOP_4735: LD HL, $0000 LD B, A INC B LD DE, $000A LOC_473D: ADD HL, DE DJNZ LOC_473D SBC HL, DE LD DE, $8767 ADD HL, DE PUSH HL POP IX RET DB $00, $02, $05, $0A, $11, $1B, $29, $3A DB $50, $57, $00, $01, $03, $06, $0C, $14 DB $1E, $2D, $3F, $57, $00, $01, $03, $07 DB $0D, $16, $22, $31, $45, $57, $00, $02 DB $04, $09, $0F, $19, $25, $36, $4A, $57 SUB_4772: LD IX, ($202D) ; RAM_E02D CALL SUB_4899 LD A, ($2015) ; RAM_E015 AND A JR Z, LOC_478D LD A, D AND A JR NZ, LOC_4788 CALL SUB_48DF JR LOC_479B LOC_4788: CALL SUB_48EF JR LOC_479B LOC_478D: LD A, ($2016) ; RAM_E016 LD B, A LD A, R ADD A, B AND $07 JR NZ, LOC_47A1 CALL SUB_48AB LOC_479B: LD HL, $2580 ; RAM_E580 JP LOC_4839 LOC_47A1: LD A, ($2043) ; RAM_E043 CP $04 JR Z, LOC_47F4 CP $03 JR Z, LOC_47E2 CP $02 JR Z, LOC_47C5 LD (IX+6), $10 LD (IX+7), $09 LD (IX+8), $0C LD (IX+9), $01 LD HL, $2580 ; RAM_E580 JR LOC_4839 LOC_47C5: LD (IX+6), $14 LD (IX+7), $05 LD (IX+8), $0E LD (IX+9), $01 LD A, ($2042) ; RAM_E042 ADD A, $01 CP $04 JR C, LOC_4829 LD A, $04 JR LOC_4829 LOC_47E2: LD (IX+6), $18 LD (IX+7), $03 LD (IX+8), $10 LD (IX+9), $02 JR LOC_485C LOC_47F4: LD (IX+6), $1C LD (IX+7), $0A LD (IX+8), $0E LD (IX+9), $02 LD A, (IX+5) CP $5A JR NC, LOC_4811 LD HL, $2540 ; RAM_E540 XOR A JR LOC_4816 LOC_4811: LD HL, $25C0 ; RAM_E5C0 LD A, $01 LOC_4816: LD ($201A), A ; RAM_E01A LD A, R AND $03 INC A LD (IX+1), A LD (IX+2), L LD (IX+3), H JR LOC_4843 LOC_4829: RLCA AND A CALL NZ, SUB_488F LD HL, $8923 LD E, A LD D, $00 ADD HL, DE LOC_4835: LD A, (HL) CALL SUB_4883 LOC_4839: LD (IX+1), $FF LD (IX+2), L LD (IX+3), H LOC_4843: LD HL, ($202D) ; RAM_E02D LD DE, $0010 ADD HL, DE LD DE, $2210 ; RAM_E210 LD A, H CP D JR NZ, LOC_4858 LD A, L CP E JR NZ, LOC_4858 LD HL, $2130 ; RAM_E130 LOC_4858: LD ($202D), HL ; RAM_E02D RET LOC_485C: LD HL, ($2104) ; RAM_E104 LD C, $00 LD A, L SUB (IX+4) LD D, A LD A, H SUB (IX+5) JR NC, LOC_486F INC C NEG LOC_486F: LD HL, $892B LD B, $04 LOC_4874: CP D JR NC, LOC_487D SRL D DEC HL DEC HL DJNZ LOC_4874 LOC_487D: DEC C JR NZ, LOC_4835 INC HL JR LOC_4835 SUB_4883: LD L, A LD H, $00 ADD HL, HL ADD HL, HL ADD HL, HL ADD HL, HL LD DE, $2500 ; RAM_E500 ADD HL, DE RET SUB_488F: LD C, A LD A, R AND $0F LOC_4894: CP C RET C SUB C JR LOC_4894 SUB_4899: INC (IX+0) LD A, R AND $3F ADD A, A ADD A, $14 LD (IX+5), A LD (IX+4), $F0 RET SUB_48AB: LD A, ($2058) ; RAM_E058 LD B, A LD A, ($2075) ; RAM_E075 ADD A, B LD B, A LD A, R ADD A, B NOP ; was RRCA — removed: R2+S always even, RRCA kills bit1, blocks pat=$8C/$88 AND $0F CP $0B JR C, LOC_48C3 LOC_48BE: LD HL, CV_P1_ENT_BE JR LOC_48F7 LOC_48C3: CP $06 JR C, LOC_48CC LOC_48C7: LD HL, CV_P1_ENT_C7 JR LOC_48F7 LOC_48CC: CP $04 JR C, LOC_48D5 LD HL, CV_P1_ENT_CC JR LOC_48F7 LOC_48D5: CP $02 JR C, LOC_48E9 LD A, ($2068) ; RAM_E068 AND A JR NZ, LOC_48BE SUB_48DF: LD A, $01 LD ($2068), A ; RAM_E068 LD HL, CV_P1_ENT_DF JR LOC_48F7 LOC_48E9: LD A, ($2069) ; RAM_E069 AND A JR NZ, LOC_48C7 SUB_48EF: LD A, $01 LD ($2069), A ; RAM_E069 LD HL, CV_P1_ENT_EF LOC_48F7: LD A, (HL) LD (IX+6), A INC HL LD A, (HL) LD (IX+8), A INC HL LD A, (HL) LD (IX+9), A RET DB $08, $08, $07, $09, $06, $0A, $05, $0B DB $04, $0C CV_P1_ENT_BE: DB $84, $0F, $01 CV_P1_ENT_C7: DB $88, $0F, $02 CV_P1_ENT_CC: DB $8C, $0F, $03 CV_P1_ENT_EF: DB $90, $0F, $00 CV_P1_ENT_DF: DB $94, $10, $0C DB $3A, $11, $E0, $A7, $C0, $F3, $3A DB $13, $E0, $A7, $28, $1C, $3A, $10, $E0 DB $3C, $E6, $01, $32, $10, $E0, $57, $3A DB $E4, $F3, $E6, $80, $82, $C6, $36, $47 DB $0E, $05, $CD, $47, $00, $AF, $32, $13 DB $E0, $3A, $0E, $E0, $A7, $CC, $0E, $4A DB $3A, $43, $E0, $4F, $FE, $05, $28, $52 DB $3A, $15, $E0, $A7, $20, $19, $2A, $16 DB $E0, $2B, $7C, $B5, $20, $41, $3A, $18 DB $E0, $3C, $E6, $03, $32, $18, $E0, $20 DB $2E, $3C, $32, $15, $E0, $18, $33, $21 DB $20, $E1, $11, $10, $00, $06, $0F, $7E DB $A7, $20, $27, $19, $10, $F9, $3A, $00 DB $E1, $A7, $FA, $C1, $49, $AF, $32, $68 DB $E0, $32, $69, $E0, $32, $15, $E0, $0C DB $79, $32, $43, $E0, $CD, $6E, $51, $3E DB $01, $32, $67, $E0, $21, $BC, $02, $22 DB $16, $E0, $2A, $58, $E0, $11, $01, $00 DB $A7, $ED, $52, $30, $0B, $11, $2C, $01 DB $19, $3A, $5A, $E0, $3C, $32, $5A, $E0 DB $22, $58, $E0, $06, $07, $21, $25, $E0 DB $7E, $A7, $28, $02, $3D, $77, $23, $10 DB $F7, $3A, $0E, $E0, $A7, $C4, $C4, $58 DB $3A, $0D, $E0, $FE, $03, $20, $08, $3A DB $25, $E0, $FE, $01, $CC, $C1, $4A LOC_49E5: XOR A LD ($2011), A ; RAM_E011 DB $FB RET SUB_49EB: DB $F3 LD A, $01 LD ($2011), A ; RAM_E011 RET SUB_49F2: PUSH HL LOC_49F3: PUSH DE RR D CALL C, SUB_5923 RR D CALL C, SUB_57BA LD HL, $0400 LOC_4A01: DEC HL LD A, H OR L JR NZ, LOC_4A01 POP DE DEC BC LD A, B OR C JR NZ, LOC_49F3 POP HL RET DB $3A, $0D, $E0, $FE, $03, $28, $7A, $AF DB $32, $0D, $E0, $CD, $D8, $00, $A7, $20 DB $32, $3E, $01, $32, $0D, $E0, $CD, $D8 DB $00, $A7, $20, $27, $3E, $02, $32, $0D DB $E0, $CD, $D8, $00, $A7, $20, $1C, $AF DB $CD, $D5, $00, $A7, $20, $23, $3E, $01 DB $CD, $D5, $00, $A7, $20, $1B, $3E, $02 DB $CD, $D5, $00, $A7, $20, $13, $AF, $32 DB $1E, $E0, $C9, $3A, $5F, $E0, $32, $0F DB $E0, $3E, $01, $32, $0E, $E0, $C3, $1A DB $40, $3A, $1E, $E0, $A7, $C0, $3C, $32 DB $1E, $E0, $3A, $5F, $E0, $3C LOC_4A6C: AND $01 LD ($205F), A ; RAM_E05F LD DE, $0000 JR Z, LOC_4A78 LD E, $20 LOC_4A78: LD HL, ($8B95) DEC HL DEC HL PUSH DE PUSH HL LD BC, $0201 LD D, $20 CALL DELAY_LOOP_4C75 POP HL POP DE ADD HL, DE LD A, $74 JP WRITE_VRAM ; tail-call WRTVRM -> WRITE_VRAM DB $3E, $02, $CD, $D8, $00, $A7, $20, $BA DB $CD, $C1, $4A, $7A, $B3, $28, $AE, $18 DB $BF SUB_4AA0: LD A, ($205F) ; RAM_E05F JR LOC_4A6C SUB_4AA5: LD A, $0F LD E, $EF CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim LD E, $CF CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim LD A, $0E CALL CV_RDPSG ; RDPSG ; RDPSG ; CV: use CV_RDPSG shim AND $0F CP $08 RET NZ LD A, $03 LD ($200D), A ; RAM_E00D RET SUB_4AC1: CALL SUB_4ADA LD D, A LD A, $0F LD E, $EF CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim CALL SUB_4ADA LD E, A PUSH DE LD A, $0F LD E, $CF CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim POP DE RET SUB_4ADA: LD A, $0E CALL CV_RDPSG ; RDPSG ; RDPSG ; CV: use CV_RDPSG shim AND $0F XOR $08 BIT 3, A RET Z OR $F0 RET SUB_4AE9: CALL SUB_49EB LD E, (HL) INC HL LD D, (HL) INC HL LD C, (HL) INC HL LD B, $00 CALL PUT_VRAM ; LDIRVM ; LDIRVM ; CV: block copy RAM→VRAM JP LOC_49E5 DB $37, $18, $03, $54, $4F, $50, $77, $18 DB $03, $31, $55, $50, $B7, $18, $03, $32 DB $55, $50, $17, $19, $06, $46, $4C, $49 DB $47, $48, $54, $79, $19, $02, $65, $66 DB $D7, $1A, $05, $52, $4F, $55, $4E, $44 DB $87, $19, $09, $47, $41, $4D, $45, $20 DB $4F, $56, $45, $52, $27, $19, $08, $50 DB $4C, $41, $59, $45, $52, $20, $31, $27 ; "LAYER 1'" DB $19, $08, $50, $4C, $41, $59, $45, $52 DB $20, $32, $88, $19, $05, $53, $54, $41 DB $52, $54, $C2, $19, $12, $28, $43, $29 DB $20, $43, $4C, $4F, $56, $45, $52, $53 ; " CLOVERS" DB $4F, $46, $54, $57, $41, $52, $45, $0A DB $1A, $04, $31, $39, $38, $38, $45, $1A DB $0D, $43, $4F, $4E, $56, $45, $52, $53 ; "CONVERS" DB $49, $4F, $4E, $20, $42, $59, $A8, $1A DB $08, $31, $20, $50, $4C, $41, $59, $45 DB $52, $C8, $1A, $09, $32, $20, $50, $4C DB $41, $59, $45, $52, $53, $69, $18, $05 DB $53, $50, $41, $43, $45 ; "SPACE" VDP_DATA_4B97: CALL SUB_4C35 LD HL, $1816 LD D, $98 LD BC, $180A CALL DELAY_LOOP_4C75 LD HL, $1837 LD D, $20 LD BC, $0607 CALL DELAY_LOOP_4C75 LD HL, $1917 LD D, $20 LD BC, $0207 CALL DELAY_LOOP_4C75 LD HL, $1977 LD D, $20 LD BC, $0A01 CALL DELAY_LOOP_4C75 LD HL, $1979 LD D, $20 LD BC, $0A02 CALL DELAY_LOOP_4C75 LD HL, $1AD7 LD D, $20 LD BC, $0107 CALL DELAY_LOOP_4C75 LD HL, $8B17 CALL SUB_4AE9 LD HL, $8B1D CALL SUB_4AE9 LD HL, $8B29 CALL SUB_4AE9 LD HL, $8B37 CALL SUB_4AE9 LD A, $46 LD HL, $1977 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD A, $45 LD HL, $1A97 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD HL, $8B32 CALL SUB_4AE9 LD A, $30 LD HL, $185D CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD A, $30 LD HL, $189D CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD A, $30 LD HL, $193D CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD A, ($200F) ; RAM_E00F AND A RET Z LD HL, $8B23 CALL SUB_4AE9 LD A, $30 LD HL, $18DD JP WRITE_VRAM ; tail-call WRTVRM -> WRITE_VRAM SUB_4C35: LD HL, $1800 LD D, $20 LD BC, $1820 JP DELAY_LOOP_4C75 SUB_4C40: LD HL, $1800 LD BC, $1816 LD D, $20 JP DELAY_LOOP_4C75 SUB_4C4B: XOR A LD ($201F), A ; RAM_E01F LD A, ($200E) ; RAM_E00E CP $01 JR NZ, LOC_4C5E LD HL, $8B4B CALL SUB_4AE9 JR LOC_4C64 LOC_4C5E: LD HL, $8B56 CALL SUB_4AE9 LOC_4C64: LD HL, $8B61 CALL SUB_4AE9 LD BC, $00C8 LD D, $00 CALL SUB_49F2 JP SUB_4C40 DELAY_LOOP_4C75: CALL SUB_49EB PUSH BC PUSH HL LD A, D LD B, $00 CALL FILL_VRAM ; FILVRM ; FILVRM ; CV: fill VRAM POP HL LD BC, $0020 ADD HL, BC POP BC DJNZ DELAY_LOOP_4C75 JP LOC_49E5 SUB_4C8B: LD BC, RDPSG LD D, $03 JP SUB_49F2 SUB_4C93: LD A, $D0 LD HL, $1B44 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD A, $D0 LD HL, $1BC4 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD HL, $2000 ; RAM_E000 LD BC, $0400 CALL SUB_4F1D LD HL, CV_VDP_INIT_TABLE ; CV fix: label resolves correct table address LD DE, $33DF LD B, $08 LD C, $00 LOC_4CB6: PUSH BC LD A, (DE) AND (HL) INC HL OR (HL) INC HL LD B, A CALL WRITE_REGISTER ; WRTVDP ; WRTVDP ; CV: write VDP register (B=data C=reg) POP BC INC DE INC C DJNZ LOC_4CB6 LD HL, CV_FONT_DATA ; CV fix: was LD HL,($0004) MSX BIOS font ptr -> embedded ASCII font LD DE, $0000 LD BC, $0300 CALL PUT_VRAM ; LDIRVM ; LDIRVM ; CV: block copy RAM→VRAM LD DE, $0328 LD HL, CV_TILE65_DATA LD BC, $0080 CALL PUT_VRAM ; LDIRVM ; LDIRVM ; CV: block copy RAM→VRAM LD DE, $03C0 LD HL, $9B0D LD BC, $0020 CALL PUT_VRAM ; LDIRVM ; LDIRVM ; CV: block copy RAM→VRAM LD DE, $0400 LD HL, $9B2D LD BC, $0020 CALL PUT_VRAM ; LDIRVM ; LDIRVM ; CV: block copy RAM→VRAM LD DE, $3800 LD HL, CV_SPGT_DATA LD BC, $04C0 CALL PUT_VRAM ; LDIRVM ; LDIRVM ; CV: block copy RAM→VRAM LD DE, $8DD5 LD HL, $2000 LD B, $20 LOC_4D09: PUSH HL LD A, (DE) CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) POP HL INC HL INC DE DJNZ LOC_4D09 LD A, $02 LD ($2002), A ; RAM_E002 LD A, $07 CALL CV_RDPSG ; RDPSG ; RDPSG ; CV: use CV_RDPSG shim AND $C0 ADD A, $1C LD E, A LD A, $07 CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim LD E, $00 LD A, $0B CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim LD HL, $2500 ; RAM_E500 LD DE, $8DF5 LD C, $21 LOC_4D36: LD A, (DE) LD B, A INC DE LD A, (DE) INC DE PUSH DE PUSH HL PUSH AF AND $0F CP $08 JR C, LOC_4D46 OR $F0 LOC_4D46: LD E, A POP AF AND $F0 RRA RRA RRA RRA CP $08 JR C, LOC_4D54 OR $F0 LOC_4D54: LD D, A LD A, B LD B, $04 LOC_4D58: LD (HL), $00 RRA JR NC, LOC_4D5E LD (HL), E LOC_4D5E: INC HL LD (HL), $00 RRA JR NC, LOC_4D65 LD (HL), D LOC_4D65: INC HL DJNZ LOC_4D58 LD (HL), $80 POP HL LD DE, $0010 ADD HL, DE POP DE DEC C JR NZ, LOC_4D36 LD BC, $0200 LD HL, $0600 LOC_4D79: XOR A CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) INC HL DEC BC LD A, B OR C JR NZ, LOC_4D79 LD B, $18 LD HL, $0600 LD DE, $0041 LOC_4D8B: LD A, $02 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) ADD HL, DE DJNZ LOC_4D8B LD C, $04 DEC DE LD HL, $0608 LOC_4D99: LD B, $02 LOC_4D9B: LD A, $30 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) INC HL DJNZ LOC_4D9B ADD HL, DE DEC C JR NZ, LOC_4D99 RET CV_VDP_INIT_TABLE: DB $FC, $00, $04, $E2, $F0, $06, $00, $80 DB $F8, $00, $80, $36, $F8, $07, $F0, $07 DB $F1, $F1, $F1, $F1, $F1, $F1, $F1, $F1 DB $F1, $F1, $F1, $F1, $F1, $D1, $81, $FC DB $F1, $C1, $77, $CC, $81, $81, $81, $81 DB $F1, $91, $B1, $71, $F1, $91, $B1, $71 DB $AA, $20, $AB, $21, $BB, $21, $FF, $21 DB $FF, $22, $FF, $12, $77, $12, $57, $12 DB $55, $02, $57, $F2, $77, $F2, $FF, $F2 DB $FF, $E2, $FF, $E1, $BB, $E1, $AB, $E1 DB $AA, $E0, $AB, $EF, $BB, $EF, $FF, $EF DB $FF, $EE, $FF, $FE, $77, $FE, $57, $FE DB $55, $0E, $57, $1E, $77, $1E, $FF, $1E DB $FF, $2E, $FF, $2F, $BB, $2F, $AB, $2F DB $00, $00 SUB_4E1A: LD HL, $2110 ; RAM_E110 LD BC, $0100 CALL SUB_4F1D LD A, $01 LD ($2100), A ; RAM_E100 LD A, $03 LD ($2020), A ; RAM_E020 LD HL, $2106 ; RAM_E106 LD (HL), $00 INC HL LD (HL), $0F INC HL LD (HL), $10 LD HL, $2114 ; RAM_E114 LD (HL), $C0 INC HL INC HL LD (HL), $30 INC HL LD (HL), $0B INC HL LD (HL), $07 LD B, $0E LD IX, $2130 ; RAM_E130 LD DE, $0010 LD HL, $2700 ; RAM_E700 LOC_4E53: LD (IX+0), $00 LD (IX+4), $F0 ; CV fix: same start Y as powerups — simultaneous descent LD (IX+2), L LD (IX+3), H LD (IX+1), $FF ADD IX, DE DJNZ LOC_4E53 LD A, $02 LD ($2022), A ; RAM_E022 LD A, ($2042) ; RAM_E042 LD B, A DEC A JR NZ, LOC_4E79 LD A, $05 JR LOC_4E84 LOC_4E79: DEC A AND $03 JR NZ, LOC_4E82 LD A, $04 JR LOC_4E84 LOC_4E82: LD A, $03 LOC_4E84: LD ($2021), A ; RAM_E021 LD A, B CP $0B JR C, LOC_4E8E LD A, $0A LOC_4E8E: LD ($204F), A ; RAM_E04F LD HL, $2023 ; RAM_E023 LD (HL), $04 INC HL LD (HL), $10 RET SUB_4E9A: LD HL, $2021 ; RAM_E021 LD A, (HL) DEC A DEC HL LD (HL), A RET SUB_4EA2: LD HL, $2010 ; RAM_E010 LD BC, $00F0 CALL SUB_4F1D LD HL, $2080 ; RAM_E080 LD ($2088), HL ; RAM_E088 LD HL, $20C0 ; RAM_E0C0 LD ($20C8), HL ; RAM_E0C8 LD HL, $1897 LD ($208A), HL ; RAM_E08A LD HL, $18D7 LD ($20CA), HL ; RAM_E0CA LD A, $01 LD ($2082), A ; RAM_E082 LD ($20C2), A ; RAM_E0C2 LD A, $03 LD ($2080), A ; RAM_E080 LD ($20C0), A ; RAM_E0C0 LD A, ($200F) ; RAM_E00F AND A JR NZ, LOC_4EDD LD HL, $20C5 ; RAM_E0C5 INC (HL) LOC_4EDD: LD HL, $2080 ; RAM_E080 LD DE, $2040 ; RAM_E040 LD BC, $0040 LDIR RET DELAY_LOOP_4EE9: XOR A LD ($2014), A ; RAM_E014 LD ($205A), A ; RAM_E05A LD ($2012), A ; RAM_E012 LD ($202C), A ; RAM_E02C LD ($2018), A ; RAM_E018 INC A LD ($2015), A ; RAM_E015 LD HL, $2130 ; RAM_E130 LD ($202D), HL ; RAM_E02D LD B, $03 LD A, $08 LD E, $00 LOC_4F09: CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim INC A DJNZ LOC_4F09 LD B, $03 LD HL, $2400 ; RAM_E400 LD DE, $0010 LOC_4F17: LD (HL), $FF ADD HL, DE DJNZ LOC_4F17 RET SUB_4F1D: XOR A LD (HL), A INC HL DEC BC LD A, B OR C JR NZ, SUB_4F1D RET SUB_4F26: LD HL, $2040 ; RAM_E040 DEC (HL) JR NZ, LOC_4F53 LD HL, $2045 ; RAM_E045 INC (HL) LD HL, $8B3F CALL SUB_4AE9 LD A, ($200F) ; RAM_E00F AND A JR Z, LOC_4F4B LD HL, $8B4B LD A, ($200E) ; RAM_E00E DEC A JR Z, LOC_4F48 LD HL, $8B56 LOC_4F48: CALL SUB_4AE9 LOC_4F4B: LD BC, $00C8 LD D, $00 CALL SUB_49F2 LOC_4F53: LD B, $02 LOC_4F55: PUSH BC LD DE, $2040 ; RAM_E040 LD HL, ($2048) ; RAM_E048 DB $EB LD BC, $0040 LDIR LD HL, $200E ; RAM_E00E LD A, (HL) AND $01 INC A LD (HL), A LD HL, $2080 ; RAM_E080 DEC A JR Z, LOC_4F73 LD HL, $20C0 ; RAM_E0C0 LOC_4F73: LD DE, $2040 ; RAM_E040 LD BC, $0040 LDIR POP BC LD A, ($2045) ; RAM_E045 AND A RET Z DJNZ LOC_4F55 RET DELAY_LOOP_4F84: CALL SUB_49EB LD HL, $2010 ; RAM_E010 LD (HL), $00 PUSH HL LD HL, $2104 ; RAM_E104 LD DE, $0010 LD B, $11 LD A, $C0 LOC_4F97: LD (HL), A ADD HL, DE DJNZ LOC_4F97 CALL DELAY_LOOP_45B7 POP HL LD (HL), $01 CALL DELAY_LOOP_45B7 JP LOC_49E5 SUB_4FA7: LD HL, $2104 ; RAM_E104 LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_4FB4 LD (HL), $90 JR LOC_4FB6 LOC_4FB4: LD (HL), $A0 LOC_4FB6: INC HL LD (HL), $50 RET SUB_4FBA: LD ($2019), A ; RAM_E019 LD IX, $2120 ; RAM_E120 LD L, (IY+4) LD A, L ADD A, $10 LD L, A LD H, (IY+5) LD D, (IY+8) LD E, $02 LD B, $0F LOC_4FD2: LD A, (IX+0) AND A JR Z, LOC_4FFF JP M, LOC_4FFF LD A, (IX+4) ADD A, $10 LD C, A SUB D ADD A, E CP L JR NC, LOC_4FFF LD A, C ADD A, (IX+8) SUB E CP L JR C, LOC_4FFF LD A, (IX+5) LD C, A ADD A, (IX+8) SUB E CP H JR C, LOC_4FFF LD A, C SUB D ADD A, E CP H JR C, LOC_5009 LOC_4FFF: PUSH DE LD DE, $0010 ADD IX, DE POP DE DJNZ LOC_4FD2 RET LOC_5009: LD A, (IX+6) CP $84 JR NC, LOC_5088 CP $64 JR NC, LOC_5031 LD A, ($2043) ; RAM_E043 CP $03 JR NZ, LOC_5034 LD A, (IX+7) CP $06 JR Z, LOC_5034 LD (IX+7), $06 LD HL, $2580 ; RAM_E580 LD (IX+2), L LD (IX+3), H JR LOC_5067 LOC_5031: CALL SUB_516E LOC_5034: LD HL, $9978 CALL DELAY_LOOP_5870 LD (IX+0), $84 LD (IX+6), $20 LD (IX+7), $09 LD (IX+1), $FF LD HL, $2700 ; RAM_E700 LD (IX+3), H LD (IX+2), L LD A, ($200E) ; RAM_E00E AND A JR Z, LOC_5067 LD A, ($2075) ; RAM_E075 ADD A, (IX+9) LD ($2075), A ; RAM_E075 LD A, $01 LD ($2076), A ; RAM_E076 LOC_5067: LD A, ($2019) ; RAM_E019 AND A JR NZ, LOC_507F LD (IY+0), $B0 LD (IY+6), $20 LD (IY+7), $09 LD HL, $995A JP DELAY_LOOP_5870 LOC_507F: LD (IY+0), $00 LD (IY+4), $C0 RET LOC_5088: LD A, ($2019) ; RAM_E019 AND A JP NZ, LOC_4FFF LD A, (IX+6) CP $94 JR NZ, LOC_50A8 LD HL, $9A15 CALL DELAY_LOOP_5870 LD A, (IX+9) CALL DELAY_LOOP_557B XOR A CALL DELAY_LOOP_435B JR LOC_50DE LOC_50A8: CP $90 JR NZ, LOC_50BB LD HL, $9A37 CALL DELAY_LOOP_5870 LD A, ($200E) ; RAM_E00E AND A CALL NZ, DELAY_LOOP_5590 JR LOC_50DE LOC_50BB: LD HL, $9A55 CALL DELAY_LOOP_5870 LD C, (IX+9) LD A, ($204F) ; RAM_E04F LD B, A LD HL, $2074 ; RAM_E074 LD A, (HL) LOC_50CC: ADD A, C DJNZ LOC_50CC LD (HL), A LD HL, $2064 ; RAM_E064 LD A, (HL) ADD A, C LD (HL), A LD A, $01 LD ($2076), A ; RAM_E076 LD ($2066), A ; RAM_E066 LOC_50DE: LD HL, $2700 ; RAM_E700 LD A, (HL) LD (IX+1), A INC HL LD (IX+2), L LD (IX+3), H LD (IX+4), $C0 LD (IX+0), $00 RET SUB_50F5: LD IX, $2120 ; RAM_E120 LD A, ($2120) ; RAM_E120 AND A JR NZ, LOC_510E LD A, ($204E) ; RAM_E04E LD B, A LD A, ($2015) ; RAM_E015 OR B JR NZ, LOC_5153 CALL SUB_5179 JR LOC_514E LOC_510E: LD HL, ($2122) ; RAM_E122 LD A, (IX+4) ADD A, (HL) CP $C0 JR Z, LOC_515A LD (IX+4), A INC HL LD A, (IX+5) ADD A, (HL) CP $A0 JR NC, LOC_515A LD (IX+5), A INC HL LD A, (HL) CP $80 JR NZ, LOC_514B DEC (IX+1) JR NZ, LOC_5145 LD HL, ($212B) ; RAM_E12B LD A, (HL) LD (IX+1), A INC HL LD A, (HL) INC HL LD ($212B), HL ; RAM_E12B CALL SUB_4883 JR LOC_514B LOC_5145: LD DE, $0008 AND A SBC HL, DE LOC_514B: LD ($2122), HL ; RAM_E122 LOC_514E: LD A, $03 LD ($2012), A ; RAM_E012 LOC_5153: LD A, ($2022) ; RAM_E022 LD ($2028), A ; RAM_E028 RET LOC_515A: LD (IX+4), $C0 LD (IX+0), $00 LD (IX+1), $FF CALL SUB_516E LD HL, $2700 ; RAM_E700 JR LOC_514B SUB_516E: LD A, $04 CALL SUB_488F ADD A, $04 LD ($204E), A ; RAM_E04E RET SUB_5179: LD HL, ($2104) ; RAM_E104 LD A, ($2016) ; RAM_E016 LD B, A LD A, R ADC A, H ADC A, L ADC A, B RRA AND $07 CP $07 JR NZ, LOC_5197 LD A, R RRA JR NC, LOC_5195 LD A, $08 JR LOC_5197 LOC_5195: LD A, $07 LOC_5197: LD C, A SLA A LD L, A LD H, $00 LD DE, $920B ADD HL, DE LD E, (HL) INC HL LD D, (HL) DB $EB LD DE, $2126 ; RAM_E126 LD B, $04 LOC_51AA: LD A, (HL) LD (DE), A INC HL INC DE DJNZ LOC_51AA LD A, (HL) AND A JR NZ, LOC_51BA CALL SUB_4899 JP LOC_485C LOC_51BA: LD B, A LD A, R AND $03 ADD A, B RLA RLA RLA LD DE, $2125 ; RAM_E125 LD (DE), A DEC DE LD A, C CP $07 JR NC, LOC_51D1 LD A, $F0 JR LOC_51D3 LOC_51D1: LD A, $BE LOC_51D3: LD (DE), A INC HL LD A, R AND $03 ADD A, (HL) LD (IX+1), A INC HL LD A, (HL) INC HL LD ($212B), HL ; RAM_E12B CALL SUB_4883 LD ($2122), HL ; RAM_E122 LD (IX+0), $01 RET DB $1D, $92, $22, $92, $47, $92, $6C, $92 DB $9D, $92, $CC, $92, $0D, $93, $44, $93 DB $59, $93, $64, $0D, $10, $05, $00, $68 DB $07, $0F, $0A, $0F, $04, $0C, $04, $00 DB $01, $14, $05, $0C, $06, $00, $02, $14 DB $08, $0C, $09, $00, $03, $14, $06, $0C DB $09, $00, $03, $14, $06, $0C, $09, $00 DB $03, $14, $FF, $08, $6C, $06, $0F, $0A DB $02, $02, $08, $06, $03, $06, $0D, $06 DB $04, $04, $00, $03, $1C, $03, $14, $04 DB $10, $06, $0C, $06, $04, $04, $00, $03 DB $1C, $03, $14, $04, $10, $06, $0C, $FF DB $03, $70, $05, $0F, $0F, $0F, $03, $0B DB $02, $0D, $04, $03, $04, $0D, $04, $03 DB $04, $0D, $04, $03, $02, $0B, $02, $0C DB $02, $0D, $03, $10, $02, $13, $02, $14 DB $02, $15, $03, $18, $04, $00, $04, $03 DB $04, $0D, $04, $03, $04, $0D, $04, $03 DB $FF, $0B, $74, $0A, $0F, $0F, $07, $04 DB $0B, $02, $04, $03, $1C, $04, $08, $02 DB $04, $03, $1C, $04, $08, $02, $10, $04 DB $0B, $05, $15, $04, $0B, $05, $15, $04 DB $0B, $04, $03, $04, $0D, $04, $05, $05 DB $1B, $04, $05, $05, $1B, $04, $05, $FF DB $0C, $78, $02, $0F, $14, $0F, $02, $08 DB $04, $0D, $02, $04, $04, $0D, $02, $04 DB $04, $0D, $02, $04, $04, $0D, $02, $04 DB $04, $0D, $04, $1C, $04, $04, $04, $1C DB $04, $14, $04, $0C, $04, $14, $04, $1C DB $04, $04, $04, $1C, $04, $14, $04, $0C DB $04, $14, $04, $03, $02, $0C, $04, $03 DB $02, $0C, $04, $03, $02, $0C, $04, $03 DB $FF, $0C, $7C, $08, $0C, $14, $04, $03 DB $08, $02, $03, $04, $0D, $04, $03, $04 DB $0D, $04, $03, $04, $0D, $04, $03, $04 DB $0D, $04, $03, $05, $00, $04, $1D, $04 DB $13, $04, $1D, $04, $13, $04, $1D, $04 DB $13, $04, $1D, $04, $13, $04, $0C, $03 DB $04, $03, $0C, $03, $04, $03, $0C, $FF DB $04, $80, $0E, $0B, $1E, $0F, $05, $18 DB $04, $15, $04, $0B, $04, $15, $04, $0B DB $04, $15, $04, $0B, $FF, $08, $80, $0E DB $0B, $1E, $03, $05, $18, $04, $1B, $04 DB $05, $04, $1B, $04, $05, $04, $1B, $04 DB $05, $FF, $08 DELAY_LOOP_5351: LD IX, $2130 ; RAM_E130 LD HL, $93A1 LD DE, $0010 LD B, $0C LD A, $34 LOC_535F: LD (IX+0), $01 LD (IX+6), A LD C, (HL) LD (IX+7), C INC HL ADD A, $04 ADD IX, DE DJNZ LOC_535F LD A, $04 LD ($2021), A ; RAM_E021 LD ($2027), A ; RAM_E027 LD HL, $2046 ; RAM_E046 LD (HL), $F0 INC HL CALL SUB_5390 LD (HL), A RET DB $03, $06, $03, $03, $06, $03, $03, $03 DB $03, $03, $03, $03 SUB_5390: LD A, R LOC_5392: CP $0B JR C, LOC_539A SUB $0B JR LOC_5392 LOC_539A: ADD A, $03 RLCA RLCA RLCA RET DELAY_LOOP_53A0: LD HL, ($2046) ; RAM_E046 LD DE, $0010 LD IX, $2130 ; RAM_E130 LD C, $04 LOC_53AC: LD B, $03 LD A, H LOC_53AF: LD (IX+4), L LD (IX+5), A ADD IX, DE ADD A, $10 DJNZ LOC_53AF LD A, L CP $C0 JR NC, LOC_53D2 SUB $10 LD L, A LOC_53C3: DEC C JR NZ, LOC_53AC LD A, $01 LD ($2012), A ; RAM_E012 LD A, ($2021) ; RAM_E021 LD ($2027), A ; RAM_E027 RET LOC_53D2: LD L, $C0 JR LOC_53C3 SUB_53D6: LD A, ($202F) ; RAM_E02F LD B, A AND A JR Z, LOC_53E2 LD A, $06 LD ($2107), A ; RAM_E107 LOC_53E2: LD A, $03 LD ($2021), A ; RAM_E021 LD ($2027), A ; RAM_E027 LOC_53EA: CALL SUB_5923 CALL SUB_57BA LD A, ($2027) ; RAM_E027 AND A JR NZ, LOC_53EA LD A, ($2106) ; RAM_E106 INC B DEC B JR Z, LOC_5401 ADD A, $04 AND $0F LOC_5401: LD C, A LD ($2106), A ; RAM_E106 LD A, ($2104) ; RAM_E104 ADD A, $02 CP $A9 JR NC, LOC_541E LD ($2104), A ; RAM_E104 LOC_5411: PUSH BC CALL DELAY_LOOP_45B7 POP BC LD A, ($2021) ; RAM_E021 LD ($2027), A ; RAM_E027 JR LOC_53EA LOC_541E: LD A, C CP $00 JR NZ, LOC_5411 RET SUB_5424: LD C, $00 LD HL, ($2104) ; RAM_E104 LD A, L SUB $08 CP $38 RET NC INC C LD A, ($2047) ; RAM_E047 LD B, A ADD A, $0E CP H JR NC, LOC_543E LD A, B ADD A, $11 CP H RET NC LOC_543E: INC C RET SUB_5440: CALL SUB_5390 LD C, A LD A, ($2047) ; RAM_E047 LD B, A CP C JR Z, SUB_5440 LOC_544B: CALL SUB_5923 CALL SUB_57BA LD A, ($2027) ; RAM_E027 AND A JR NZ, LOC_544B LD A, B CP C RET Z JR C, LOC_5460 SUB $02 JR LOC_5462 LOC_5460: ADD A, $02 LOC_5462: LD ($2047), A ; RAM_E047 LD B, A PUSH BC CALL DELAY_LOOP_53A0 CALL DELAY_LOOP_45B7 POP BC LD A, ($2021) ; RAM_E021 LD ($2027), A ; RAM_E027 JR LOC_544B SUB_5476: CALL SUB_5923 CALL SUB_57BA LD A, ($2027) ; RAM_E027 AND A JR NZ, SUB_5476 LD A, ($2046) ; RAM_E046 CP C JR Z, LOC_54A3 ADD A, $02 LD ($2046), A ; RAM_E046 PUSH BC LD A, B AND A JR Z, LOC_549A LD A, ($2104) ; RAM_E104 ADD A, $02 LD ($2104), A ; RAM_E104 LOC_549A: CALL DELAY_LOOP_53A0 CALL DELAY_LOOP_45B7 POP BC JR SUB_5476 LOC_54A3: XOR A LD ($205A), A ; RAM_E05A RET SUB_54A8: CALL SUB_5923 LD HL, $2029 ; RAM_E029 XOR A LD (HL), A INC HL LD (HL), A CALL SUB_57BA LD A, ($2027) ; RAM_E027 AND A JR NZ, SUB_54A8 LD A, ($2046) ; RAM_E046 CP $F0 RET Z SUB $02 LD ($2046), A ; RAM_E046 CALL DELAY_LOOP_53A0 CALL DELAY_LOOP_45B7 JR SUB_54A8 SUB_54CE: CALL SUB_5923 CALL SUB_57BA LD A, ($2027) ; RAM_E027 AND A JR NZ, SUB_54CE LD A, $05 LD ($2107), A ; RAM_E107 LD A, ($2104) ; RAM_E104 DEC A CP $28 JR C, LOC_54F5 LD ($2104), A ; RAM_E104 CALL DELAY_LOOP_45B7 LD A, ($2021) ; RAM_E021 LD ($2027), A ; RAM_E027 JR SUB_54CE LOC_54F5: LD A, ($2018) ; RAM_E018 INC A LD ($2018), A ; RAM_E018 CALL DELAY_LOOP_42DF LD A, ($2040) ; RAM_E040 CP $06 JR Z, LOC_550D INC A LD ($2040), A ; RAM_E040 CALL VDP_DATA_4320 LOC_550D: LD BC, $00C8 LD D, $02 JP SUB_49F2 SUB_5515: CALL SUB_57BA CALL DELAY_LOOP_5555 AND A JR NZ, LOC_5538 LD HL, $2075 ; RAM_E075 INC (HL) CALL LOC_426B CALL SUB_41FA LD HL, $9A7D CALL DELAY_LOOP_5870 LD BC, $0002 LD D, $02 CALL SUB_49F2 JR SUB_5515 LOC_5538: CALL SUB_57BA LD A, $01 CALL DELAY_LOOP_557B AND A RET NZ CALL DELAY_LOOP_435B LD HL, $9A6B CALL DELAY_LOOP_5870 LD BC, $0005 LD D, $02 CALL SUB_49F2 JR LOC_5538 DELAY_LOOP_5555: LD B, $06 LD HL, $2060 ; RAM_E060 LOC_555A: LD A, (HL) AND A JR NZ, LOC_5563 INC HL DJNZ LOC_555A INC A RET LOC_5563: LD B, $06 LD HL, $2065 ; RAM_E065 DEC (HL) LD C, $00 LOC_556B: LD A, (HL) SUB C LD C, $00 JP P, LOC_5575 ADD A, $0A INC C LOC_5575: LD (HL), A DEC HL DJNZ LOC_556B XOR A RET DELAY_LOOP_557B: LD B, $08 LD HL, $2057 ; RAM_E057 LOC_5580: ADD A, (HL) CP $09 JR C, LOC_558D SUB $08 LD (HL), $08 DEC HL DJNZ LOC_5580 RET LOC_558D: LD (HL), A XOR A RET DELAY_LOOP_5590: LD DE, $2060 ; RAM_E060 LD HL, $2070 ; RAM_E070 LD B, $06 LOC_5598: LD A, (DE) ADD A, (HL) LD (HL), A INC HL INC DE DJNZ LOC_5598 LD A, $01 LD ($2076), A ; RAM_E076 RET SUB_55A5: XOR A LD ($201E), A ; RAM_E01E LD ($204F), A ; RAM_E04F INC A LD ($205D), A ; RAM_E05D LD A, $04 LD ($205E), A ; RAM_E05E LD A, ($2043) ; RAM_E043 AND $03 LD ($2043), A ; RAM_E043 CALL LOC_49E5 LD HL, $8BAC CALL SUB_4AE9 LD HL, $8B69 CALL SUB_4AE9 CALL CV_CREDITS_STUB ; CV: display "1988" + "KAMSHAFT" NOP NOP NOP LD HL, $8B85 CALL SUB_4AE9 LD HL, $8B95 CALL SUB_4AE9 LD HL, $8BA0 CALL SUB_4AE9 CALL SUB_4AA0 CALL DELAY_LOOP_5605 CALL SUB_5645 CALL SUB_4C40 LD HL, $8B95 CALL SUB_4AE9 LD HL, $8BA0 CALL SUB_4AE9 CALL SUB_4AA0 LD A, $64 LD ($202B), A ; RAM_E02B RET DELAY_LOOP_5605: CALL SUB_49EB LD IX, $968F LD HL, $18A0 LD C, $05 LOC_5611: LD B, $05 PUSH HL LOC_5614: PUSH BC LD B, $04 CALL DELAY_LOOP_5632 INC IX POP BC DJNZ LOC_5614 LD B, $02 CALL DELAY_LOOP_5632 INC IX POP HL LD DE, $0020 ADD HL, DE DEC C JR NZ, LOC_5611 CALL LOC_49E5 RET DELAY_LOOP_5632: LD D, (IX+0) LOC_5635: LD A, D AND $03 ADD A, $80 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) INC HL SRL D SRL D DJNZ LOC_5635 RET SUB_5645: LD HL, $968A LD DE, RDPSG LOC_564B: LD A, $03 LD ($2025), A ; RAM_E025 LOC_5650: LD A, ($2025) ; RAM_E025 AND A JR NZ, LOC_5650 LD A, (HL) PUSH HL LD HL, $2010 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) POP HL INC HL LD A, (HL) AND A JR NZ, LOC_5667 LD HL, $968A LOC_5667: DEC DE LD A, D OR E JR NZ, LOC_564B RET DB $81, $91, $F1, $81, $00, $94, $65, $19 ; CV fix: warp colors (med-red/light-red/white/med-red) DB $96, $41, $09, $10, $61, $18, $86, $41 DB $00, $10, $75, $18, $D6, $41, $01, $10 DB $61, $18, $86, $41, $00, $10, $61, $59 DB $96, $65, $09 SUB_5690: LD A, ($205E) ; RAM_E05E DEC A JR NZ, LOC_56D7 LD A, R AND $F8 RRA RRA RRA ADD A, $08 LD ($205E), A ; RAM_E05E LD A, ($2105) ; RAM_E105 CP $94 JR NZ, LOC_56AD LD A, $07 JR LOC_56D3 LOC_56AD: CP $14 JR NZ, LOC_56B5 LD A, $03 JR LOC_56D3 LOC_56B5: LD A, ($2104) ; RAM_E104 CP $20 JR NZ, LOC_56C0 LD A, $05 JR LOC_56D3 LOC_56C0: CP $90 JR NZ, LOC_56C8 LD A, $01 JR LOC_56D3 LOC_56C8: LD A, R AND $0F RRA JR NZ, LOC_56D2 XOR A JR LOC_56D3 LOC_56D2: INC A LOC_56D3: LD ($205D), A ; RAM_E05D RET LOC_56D7: LD ($205E), A ; RAM_E05E LD A, ($205D) ; RAM_E05D RET SUB_56DE: LD A, ($202B) ; RAM_E02B AND A JR NZ, LOC_56EA LD A, $28 LD ($202B), A ; RAM_E02B RET LOC_56EA: XOR A RET SUB_56EC: LD HL, $0000 LD ($204C), HL ; RAM_E04C LOC_56F2: INC A INC C DEC C JR Z, LOC_56FB AND $03 JR LOC_56FD LOC_56FB: AND $07 LOC_56FD: PUSH AF LD (IX+3), A ADD A, A ADD A, A ADD A, A ADD A, $C0 ADD A, C LD (IX+0), A LOC_570A: CALL SUB_5739 DB $EB LD HL, ($204C) ; RAM_E04C ADD HL, DE CALL CV_RDVRM ; $004A ; CV: read VRAM byte (HL=addr → A=data) CP $20 JR NZ, LOC_570A LD (IX+1), L LD (IX+2), H LD HL, ($204C) ; RAM_E04C LD DE, $0020 INC C DEC C JR Z, LOC_572C LD DE, $0080 LOC_572C: ADD HL, DE LD ($204C), HL ; RAM_E04C LD DE, $0004 ADD IX, DE POP AF DJNZ LOC_56F2 RET SUB_5739: LD E, $16 CALL SUB_5746 LD L, A LD H, $00 LD DE, $1800 ADD HL, DE RET SUB_5746: LD A, ($200C) ; RAM_E00C LD D, A LD A, ($2058) ; RAM_E058 ADC A, D LD D, A LD A, R ADC A, D RLA LD ($200C), A ; RAM_E00C LOC_5756: CP E RET C SUB E JR LOC_5756 SUB_575B: LD A, (IX+3) INC A INC C DEC C JR Z, LOC_5767 AND $03 JR LOC_5769 LOC_5767: AND $07 LOC_5769: LD (IX+3), A LD E, (IX+1) LD D, (IX+2) JR NZ, LOC_57AF LD A, $C0 ADD A, C LD (IX+0), A DB $EB LD A, $20 CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD DE, $0020 ADD HL, DE LD DE, $1B00 LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_5790 LD DE, $1A80 LOC_5790: LD A, H CP D JR C, LOC_579B LD A, L CP E JR C, LOC_579B CALL SUB_5739 LOC_579B: LD A, (IX+0) LOC_579E: CALL WRITE_VRAM ; WRTVRM ; WRTVRM ; CV: write VRAM byte (HL=addr A=data) LD (IX+1), L LD (IX+2), H LD DE, $0004 ADD IX, DE DJNZ SUB_575B RET LOC_57AF: LD A, (IX+0) ADD A, $08 LD (IX+0), A DB $EB JR LOC_579E SUB_57BA: PUSH BC PUSH DE LD A, ($202A) ; RAM_E02A AND A JR NZ, LOC_57DB LD BC, $1800 LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_57CE LD BC, $1400 LOC_57CE: LD IX, $2758 ; RAM_E758 CALL SUB_575B LD A, ($2024) ; RAM_E024 LD ($202A), A ; RAM_E02A LOC_57DB: LD A, ($2029) ; RAM_E029 AND A JR NZ, LOC_57F8 LD BC, $0601 LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_57EB DEC B LOC_57EB: LD IX, $2740 ; RAM_E740 CALL SUB_575B LD A, ($2023) ; RAM_E023 LD ($2029), A ; RAM_E029 LOC_57F8: POP DE POP BC RET SUB_57FB: LD BC, $0601 LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_5805 DEC B LOC_5805: LD IX, $2740 ; RAM_E740 CALL SUB_56EC LD BC, $1800 LD A, ($200E) ; RAM_E00E AND A JR NZ, LOC_5818 LD BC, $1400 LOC_5818: LD IX, $2758 ; RAM_E758 JP SUB_56EC DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF DELAY_LOOP_5870: LD A, ($200E) ; RAM_E00E AND A RET Z PUSH IY LD B, $03 LD IY, $2400 ; RAM_E400 LD C, (HL) INC HL LOC_587F: LD E, (HL) INC HL LD D, (HL) INC HL LD A, D OR E JR NZ, LOC_5891 LOC_5887: LD DE, $0010 ADD IY, DE DJNZ LOC_587F POP IY RET LOC_5891: LD A, C AND $0F CP $08 JR C, LOC_589D CP (IY+0) JR LOC_58A2 LOC_589D: CP (IY+0) JR Z, LOC_58A4 LOC_58A2: JR NC, LOC_5887 LOC_58A4: DI ; CV: make priority-write + note-advance atomic LD (IY+0), A LD A, C AND $F0 RRA RRA RRA RRA LD (IY+1), A LD (IY+2), A PUSH HL DB $EB LD A, $0B SUB B LD E, (HL) CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim INC HL CALL SUB_58F1 EI ; CV: re-enable NMI after atomic section POP HL JR LOC_5887 DB $FD, $E5, $FD, $21, $00, $E4, $11, $10 DB $00, $06, $03, $FD, $7E, $00, $FE, $FF DB $28, $14, $FD, $35, $02, $20, $0F, $FD DB $7E, $01, $FD, $77, $02, $FD, $6E, $03 DB $FD, $66, $04, $CD, $F1, $58, $FD, $19 DB $10, $E1, $FD, $E1, $C9 SUB_58F1: PUSH DE LD E, (HL) INC HL LD D, (HL) LD A, D CP $80 JR Z, LOC_5915 LD A, B CP $01 JR Z, LOC_590B INC HL LD A, $03 SUB B ADD A, A CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim INC A LD E, D JR LOC_590D LOC_590B: LD A, $06 LOC_590D: LD (IY+3), L LD (IY+4), H JR LOC_591E LOC_5915: LD (IY+0), $FF LD A, $0B SUB B LD E, $00 LOC_591E: CALL CV_WRTPSG ; WRTPSG ; WRTPSG ; CV: use CV_WRTPSG shim POP DE RET SUB_5923: PUSH BC PUSH DE PUSH HL LD A, ($2120) ; RAM_E120 AND A JR NZ, LOC_5931 LD HL, $99C9 JR LOC_5934 LOC_5931: LD HL, $99BB LOC_5934: CALL DELAY_LOOP_5870 POP HL POP DE POP BC RET DB $61, $00, $00, $00, $00, $61, $99, $0D DB $1F, $1A, $1D, $16, $1A, $12, $16, $0F DB $12, $0A, $0E, $06, $0C, $0A, $05, $07 DB $03, $05, $02, $02, $00, $80, $22, $00 DB $00, $00, $00, $7F, $99, $0C, $05, $1E DB $09, $18, $0C, $05, $0A, $1C, $00, $80 DB $13, $00, $00, $91, $99, $AC, $99, $0C DB $32, $00, $41, $00, $50, $00, $5F, $00 DB $6E, $00, $7D, $00, $8C, $00, $9B, $00 DB $AA, $00, $B9, $00, $C8, $00, $D7, $00 DB $00, $80, $0C, $02, $04, $06, $08, $0A DB $0C, $0E, $10, $12, $14, $16, $18, $00 DB $80, $48, $00, $00, $C2, $99, $00, $00 DB $0B, $A1, $00, $CB, $00, $00, $80, $49 DB $00, $00, $D0, $99, $00, $00, $0B, $82 DB $02, $2E, $03, $00, $80, $1B, $00, $00 DB $DE, $99, $00, $00, $0C, $15, $01, $41 DB $01, $97, $01, $8B, $00, $A1, $00, $CB DB $00, $45, $00, $50, $00, $66, $00, $23 DB $00, $28, $00, $33, $00, $00, $80, $62 DB $00, $9A, $00, $00, $00, $00, $0D, $66 DB $00, $05, $00, $66, $00, $05, $00, $66 DB $00, $05, $00, $66, $00, $05, $00, $66 DB $00, $00, $80, $23, $1C, $9A, $00, $00 DB $00, $00, $0C, $2E, $03, $97, $01, $CB DB $00, $66, $00, $2E, $03, $97, $01, $CB DB $00, $66, $00, $2E, $03, $97, $01, $CB DB $00, $66, $00, $00, $80, $23, $3E, $9A DB $00, $00, $00, $00, $0C, $33, $00, $66 DB $00, $33, $00, $66, $00, $33, $00, $66 DB $00, $33, $00, $66, $00, $33, $00, $66 DB $00, $00, $80, $33, $5C, $9A, $00, $00 DB $00, $00, $0C, $CB, $00, $A1, $00, $8B DB $00, $66, $00, $8B, $00, $8B, $00, $00 DB $80, $28, $72, $9A, $00, $00, $00, $00 DB $0C, $CB, $00, $A1, $00, $8B, $00, $66 DB $00, $00, $80, $29, $84, $9A, $00, $00 DB $00, $00, $0C, $50, $00, $66, $00, $05 DB $00, $00, $80 CV_TILE65_DATA: DB $03, $16, $1D, $17, $06 DB $0E, $06, $02, $C0, $68, $B8, $E8, $60 DB $70, $60, $40, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $7E, $00, $00, $00, $00, $00 DB $00, $7E, $7E, $00, $00, $00, $00, $00 DB $7E, $7E, $7E, $00, $00, $00, $00, $7E DB $7E, $7E, $7E, $00, $00, $00, $7E, $7E DB $7E, $7E, $7E, $00, $00, $7E, $7E, $7E DB $7E, $7E, $7E, $00, $7E, $7E, $7E, $7E DB $7E, $7E, $7E, $7E, $7E, $7E, $7E, $7E ; "~~~~~~~~" DB $7E, $7E, $7E, $00, $00, $00, $00, $01 DB $03, $07, $1F, $00, $00, $00, $00, $80 DB $C0, $E0, $F8, $01, $03, $07, $1F, $00 DB $00, $00, $00, $80, $C0, $E0, $F8, $00 DB $00, $00, $00, $C0, $F0, $FC, $FF, $FF DB $FC, $F0, $C0, $00, $01, $01, $13, $16 DB $3D, $7F, $7F, $00, $80, $80, $C8, $68 DB $BC, $FE, $FE, $7E, $25, $0D, $1F, $1F DB $11, $03, $00, $7E, $A4, $B0, $F8, $F8 DB $88, $C0, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FE, $FE, $FE, $FE, $FE DB $FE, $FE, $FE, $FE, $FC, $F8, $F0, $F0 DB $F8, $FC, $FE CV_SPGT_DATA: DB $01, $01, $03, $16, $34 DB $7D, $FF, $FE, $FD, $45, $0D, $1F, $1F DB $19, $13, $03, $80, $80, $C0, $68, $2C DB $BE, $FF, $7F, $BF, $A2, $B0, $F8, $F8 DB $98, $C8, $C0, $01, $03, $01, $79, $3D DB $1F, $D8, $FF, $FF, $D8, $1F, $3D, $79 DB $01, $03, $01, $C0, $E0, $F0, $F8, $F0 DB $F8, $CC, $67, $67, $CC, $F8, $F0, $F8 DB $F0, $E0, $C0, $03, $13, $19, $1F, $1F DB $0D, $45, $FD, $FE, $FF, $7D, $34, $16 DB $03, $01, $01, $C0, $C8, $98, $F8, $F8 DB $B0, $A2, $BF, $7F, $FF, $BE, $2C, $68 DB $C0, $80, $80, $03, $07, $0F, $1F, $07 DB $1F, $33, $E6, $E6, $33, $1F, $07, $1F DB $0F, $07, $03, $80, $C0, $80, $9E, $BC DB $F8, $1B, $FF, $FF, $1B, $F8, $BC, $9E DB $80, $C0, $80, $0D, $1F, $39, $F7, $7D DB $5B, $DB, $EF, $7B, $3C, $2F, $05, $00 DB $00, $00, $00, $00, $E0, $C0, $60, $B0 DB $B0, $60, $F0, $60, $E0, $80, $80, $00 DB $00, $00, $00, $03, $03, $37, $3F, $1C DB $3B, $F4, $F4, $3B, $1C, $3F, $37, $03 DB $03, $00, $00, $00, $00, $B0, $F0, $E0 DB $70, $BC, $BC, $70, $E0, $F0, $B0, $00 DB $00, $00, $00, $01, $03, $03, $73, $FF DB $FF, $7E, $3D, $1D, $1E, $1F, $3F, $7F DB $7F, $7C, $38, $C0, $E0, $E0, $F0, $FE DB $FF, $7F, $BF, $BE, $78, $F8, $F8, $FC DB $FC, $7C, $38, $10, $0B, $0F, $18, $17 DB $37, $78, $FF, $D4, $7F, $1F, $08, $07 DB $00, $00, $00, $20, $40, $C0, $60, $A0 DB $B0, $78, $FC, $AC, $F8, $E0, $40, $80 DB $00, $00, $00, $00, $00, $00, $08, $04 DB $07, $03, $1D, $06, $07, $0B, $02, $00 DB $00, $00, $00, $00, $00, $00, $90, $A0 DB $E0, $E0, $78, $F0, $C0, $40, $20, $00 DB $00, $00, $00, $00, $00, $02, $22, $12 DB $0D, $0F, $06, $0B, $17, $0E, $13, $21 DB $01, $00, $00, $00, $00, $20, $20, $40 DB $E0, $BC, $D0, $60, $70, $C0, $80, $60 DB $10, $00, $00, $00, $01, $11, $3D, $16 DB $0B, $07, $06, $1A, $7B, $0D, $0A, $13 DB $21, $01, $00, $00, $00, $02, $A4, $58 DB $B8, $50, $DE, $D0, $60, $D0, $B8, $98 DB $04, $00, $00, $41, $21, $11, $1D, $36 DB $0B, $36, $17, $1A, $F7, $1D, $1E, $17 DB $27, $42, $82, $01, $02, $04, $98, $78 DB $90, $DF, $68, $70, $E8, $9C, $E0, $70 DB $30, $08, $04, $10, $38, $7C, $EE, $7C DB $38, $10, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $D4, $D4, $DC, $DC, $DC DB $D4, $74, $3C, $00, $00, $00, $00, $00 DB $00, $00, $00, $FE, $FE, $FF, $FF, $FF DB $FF, $E3, $C3, $00, $00, $00, $00, $00 DB $00, $00, $00, $7F, $7F, $FF, $FF, $FF DB $FF, $C7, $C3, $00, $00, $00, $00, $00 DB $00, $00, $00, $2B, $2B, $3B, $3B, $3B DB $2B, $2E, $3C, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $11, $13, $1E, $1A, $0E DB $06, $03, $01, $DC, $D4, $D4, $DC, $DC DB $DC, $D4, $D4, $DC, $DC, $DC, $D4, $D4 DB $DC, $DC, $DC, $FF, $FF, $FE, $FE, $FE DB $FE, $FF, $FF, $FE, $FE, $FE, $FE, $FF DB $FF, $FE, $FE, $FF, $FF, $7F, $7F, $7F DB $7F, $FF, $FF, $7F, $7F, $7F, $7F, $FF DB $FF, $7F, $7F, $3B, $2B, $2B, $3B, $3B DB $3B, $2B, $2B, $3B, $3B, $3B, $2B, $2B ; ";++;;;++" DB $3B, $3B, $3B, $00, $00, $00, $00, $00 DB $00, $00, $00, $88, $C8, $78, $58, $70 DB $60, $C0, $80, $DB, $FF, $DB, $FF, $7E DB $24, $24, $18, $00, $00, $00, $00, $00 DB $00, $00, $00, $55, $57, $D4, $77, $1D DB $07, $01, $71, $F9, $FB, $EF, $DF, $B0 DB $EF, $DC, $DC, $F7, $AE, $BC, $AD, $AD DB $BF, $B7, $FD, $1B, $DB, $FB, $FB, $01 DB $FF, $F9, $03, $EF, $75, $3D, $B5, $B5 DB $FD, $ED, $BF, $D8, $DB, $DF, $DF, $80 DB $FF, $9F, $C0, $AA, $EA, $AB, $EE, $B8 DB $E0, $80, $8E, $9F, $DF, $F7, $FB, $0D DB $F7, $3B, $3B, $DB, $FF, $DB, $FF, $7E DB $24, $24, $18, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $18, $24, $7E, $FF DB $DB, $FF, $DB, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $08 DB $09, $1F, $F5, $00, $00, $00, $00, $00 DB $00, $00, $00, $47, $58, $7D, $7F, $FE DB $F3, $EE, $DC, $00, $00, $00, $00, $00 DB $00, $00, $00, $E2, $1A, $BE, $FE, $7F DB $CF, $77, $3B, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $00, $00, $00, $10 DB $90, $F8, $AF, $00, $00, $00, $00, $00 DB $00, $00, $00, $00, $18, $24, $7E, $FF DB $DB, $FF, $DB, $04, $04, $05, $0F, $18 DB $3F, $2C, $67, $FE, $FF, $A4, $FF, $7F DB $2F, $12, $01, $20, $20, $A0, $F0, $18 DB $FC, $34, $E6, $7F, $FF, $25, $FF, $FE DB $F4, $48, $80, $01, $01, $03, $07, $0E DB $0C, $07, $1B, $3D, $76, $66, $76, $3E DB $5C, $80, $00, $00, $00, $80, $C0, $E0 DB $60, $C0, $B0, $78, $DC, $CC, $DC, $F8 DB $74, $02, $00, $F8, $FA, $72, $37, $2C DB $36, $33, $31, $7B, $49, $79, $48, $FC DB $FC, $CC, $00, $3E, $BE, $9C, $D8, $68 DB $D8, $98, $18, $BC, $24, $3C, $24, $7E DB $7E, $66, $00, $08, $09, $0F, $3B, $77 DB $EF, $AF, $EE, $A7, $F0, $DF, $77, $3C DB $0F, $01, $00, $20, $20, $E0, $B8, $DC DB $6E, $AA, $6E, $CA, $1E, $F6, $DC, $78 DB $E0, $00, $00, $38, $68, $FA, $E2, $C7 DB $CC, $A8, $B8, $AF, $CD, $C7, $E1, $F9 DB $68, $38, $00, $38, $2C, $BE, $8E, $C6 DB $66, $2A, $2A, $EA, $66, $C6, $1E, $3E DB $2C, $38, $00, $27, $3F, $6B, $EB, $FF DB $04, $03, $01, $1D, $36, $2A, $36, $1D DB $23, $41, $00, $C8, $F8, $AC, $AE, $FE DB $40, $80, $00, $70, $D8, $A8, $D8, $70 DB $88, $04, $00, $06, $46, $29, $1F, $3F DB $D9, $D9, $3F, $1F, $29, $46, $06, $00 DB $00, $00, $00, $00, $20, $40, $80, $C0 DB $B0, $B0, $C0, $80, $40, $20, $00, $00 DB $00, $00, $00, $24, $AE, $BF, $BF, $E4 DB $64, $3F, $FF, $1B, $7B, $4A, $00, $00 DB $00, $00, $00, $80, $A0, $A0, $A0, $E0 DB $C0, $80, $E0, $00, $C0, $40, $00, $00 DB $00, $00, $00, $FF, $E6, $FF, $A0, $A1 DB $E3, $E5, $A1, $E1, $E1, $A7, $A0, $FF DB $E6, $FF, $00, $FE, $CE, $FE, $0A, $0A DB $0E, $0E, $0A, $0E, $0E, $CA, $0A, $FE DB $CE, $FE, $00, $FF, $E6, $FF, $A0, $A3 DB $E4, $E0, $A1, $E2, $E4, $A7, $A0, $FF DB $E6, $FF, $00, $FE, $CE, $FE, $0A, $8A DB $4E, $4E, $8A, $0E, $0E, $CA, $0A, $FE DB $CE, $FE, $00, $FF, $E6, $FF, $A0, $A3 DB $E4, $E0, $A1, $E0, $E4, $A3, $A0, $FF DB $E6, $FF, $00, $FE, $CE, $FE, $0A, $8A DB $4E, $4E, $8A, $4E, $4E, $8A, $0A, $FE DB $CE, $FE, $00, $FF, $E6, $FF, $A0, $A3 DB $E4, $E4, $A3, $E0, $E4, $A3, $A0, $FF DB $E6, $FF, $00, $FE, $CE, $FE, $0A, $8A DB $4E, $0E, $8A, $4E, $4E, $8A, $0A, $FE DB $CE, $FE, $00, $01, $03, $23, $19, $1F DB $0D, $6A, $FD, $FD, $6A, $0D, $1F, $19 DB $23, $03, $01, $80, $C0, $C4, $98, $F8 DB $B0, $56, $BF, $BF, $56, $B0, $F8, $98 DB $C4, $C0, $80, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FF, $FF, $FF, $FF ; ---- mid-instruction label aliases (EQU) ---- INIT: EQU $8021 ; remapped from $4004 ; ============================================================ ; COLECOVISION COMPATIBILITY SHIMS ; REQUIRES: Super Game Module (SGM) expansion ; - SGM RAM enable: OUT ($53), A (bit0=1) -> 24KB at $2000-$7FFF ; - SGM AY-3-8910: port $50=reg select, $51=data write, $52=data read ; - SGM vs MSX audio: MSX $A0/$A1/$A2 -> SGM $50/$51/$52 (same chip) ; ============================================================ ; ---- CV_STARTUP: game entry — debug screen, SGM init, then jump to game ----- ; CV_GAME_ENTRY jumps here (JP CV_STARTUP). After init, JPs to CV_GAME_CODE_START. ; Located at end of ROM so game code starts immediately after the 3-byte JP at ; CV_GAME_ENTRY — this gives the correct +$401D offset for all ROM address literals. CV_STARTUP: DI ; Reset VDP address latch before init IN A, ($BF) ; reset VDP address latch LD SP, $63FF ; initial stack in always-valid CV 1KB RAM CALL SGM_INIT ; enable 24KB SGM RAM at $2000-$7FFF CALL SGM_PSG_TEST ; verify AY-3-8910 present; halts with error if not LD SP, $73FF ; switch to full SGM stack ; Zero-fill $2000-$3FFF (MSX ext RAM area remapped to SGM RAM) ; Ensures VDP register shadow ($33DF+) and all work RAM starts clean. LD HL, $2000 LD DE, $2001 LD BC, $1FFF XOR A LD (HL), A LDIR ; Pre-initialize VDP register shadow RAM to MSX BIOS Screen 1 defaults. ; The game's VDP init (LOC_4CB6) reads these shadows, applies AND/OR masks, ; and writes final values to VDP. With zeroed shadows the critical registers ; get wrong addresses: ; R2 shadow=0 -> AND($04)/OR($E2) -> $E2 -> NT @ $0800 (WRONG, want $1800) ; R3 shadow=0 -> AND($F0)/OR($06) -> $06 -> CT @ $0000 (WRONG, want $2000) ; With MSX BIOS defaults the results are correct: ; R2 shadow=$06 -> $E6 -> NT @ $1800 (R2[3:0]=6, 6x$400=$1800) ; R3 shadow=$FF -> $F6 -> CT @ $2000 (R3 bit7=1 -> CT at $2000) LD A, $E0 LD ($33E0), A ; R1 shadow: 16K=1, BL=1, IE=1 LD A, $06 LD ($33E1), A ; R2 shadow: name table @ $1800 LD A, $FF LD ($33E2), A ; R3 shadow: color table @ $2000 (bit7=1) ; $33E3 stays $00 (R4 shadow: PGT @ $0000 — already zero from LDIR) LD A, $36 LD ($33E4), A ; R5 shadow: sprite attr table base LD A, $07 LD ($33E5), A ; R6 shadow: sprite PGT base LD A, $F1 LD ($33E6), A ; R7 shadow: colors (white fg / dark-blue bg) ; Game uses LD A,(VDP_WR) then OUTI — shadow must hold $BE (CV data port). LD A, $BE LD ($7FF8), A ; CV_VDP_RD_SHADOW LD ($7FF9), A ; CV_VDP_WR_SHADOW ; Force joystick type 3 = PSG R14 path; CV_RDPSG intercepts R14 to return CV data. LD A, $03 LD ($200D), A ; RAM_E00D remapped: joystick type = 3 ; CV fix: tile $74 (VRAM $03A0) is the title-screen cursor (right-pointing triangle). ; On MSX the pattern came from the BIOS character ROM (char 't' = $74 in MSX font). ; CV has no BIOS font above tile $5F, so write the triangle pattern explicitly. LD HL, CV_CURSOR74_DATA LD DE, $03A0 ; VRAM offset for tile $74 pattern LD BC, $0008 CALL PUT_VRAM ; CV fix: tile $98 (VRAM $04C0) needs a solid pattern to show the panel background. ; The game never loads this tile's pattern, so init it here before jumping to game code. LD A, $FF LD HL, $04C0 LD BC, $0008 CALL FILL_VRAM ; MSX overlapping header sets A=$C3 (JP opcode) before the first game instruction ; LD ($3D9F), A. CV_STARTUP emits these bytes rather than placing them in the game ; body (which would shift all data addresses by +2 and break ROM address literals). LD A, $C3 ; game's LD ($3D9F),A expects A = JP opcode ($C3) JP CV_GAME_CODE_START ; jump back to game code (forward ref, always valid) ; SGM I/O PORT DEFINITIONS **************************** SGM_PSG_REG: EQU $50 ; AY-3-8910 register select (same as MSX $A0) SGM_PSG_DAT: EQU $51 ; AY-3-8910 data write (same as MSX $A1) SGM_PSG_READ: EQU $52 ; AY-3-8910 data read (same as MSX $A2) SGM_RAM_ENABLE: EQU $53 ; write $01 to enable 24KB RAM at $2000-$7FFF ; ---- SGM_INIT: enable SGM RAM (call before using $2000-$7FFF RAM) --- ; Detects ADAM system first (ADAM has RAM at $2000 already). ; In OpenMSX ColecoVision_SGM, SGM RAM is pre-mapped — the ADAM detect ; fires as a false positive, skips OUT ($53), and the game runs correctly ; because the RAM is already available. This is the desired behavior. ; On real hardware (non-ADAM): OUT ($53) enables the RAM. ; Returns: Z flag set = SGM RAM enabled, NZ = ADAM or no SGM detected. SGM_INIT: LD HL, $2000 ; test for ADAM RAM at $2000 LD A, $55 LD (HL), A CP (HL) JR NZ, SGM_INIT_ENABLE ; no existing RAM = ColecoVision, safe to enable XOR A ; ADAM or pre-mapped SGM detected — RAM is ready INC A ; NZ = not enabled via OUT (but RAM is present) RET SGM_INIT_ENABLE: LD A, $01 OUT (SGM_RAM_ENABLE), A ; enable 24KB SGM RAM at $2000-$7FFF XOR A ; Z = enabled RET ; ---- NMI handler (called 60 Hz by ColecoVision BIOS) ---------------- ; Checks game's critical-section flag ($2011 = RAM_E011) before reading VDP ; status, because DI does NOT block NMI. Reading $BF mid-transfer resets ; the VDP address latch and corrupts the ongoing VRAM write. CV_NMI: PUSH AF PUSH HL PUSH BC PUSH DE LD HL, $2011 ; game critical-section flag (set by SUB_49EB) LD A, (HL) AND A JP NZ, CV_NMI_SKIP ; inside DI-protected VDP write — skip ack IN A, ($BF) ; CTRL_PORT - read VDP status (ack interrupt) ; Game-start check: MSX H.TIMI hook ($491F) detected fire on title screen and ; set $E00E=1, then did JP $401A (restart). Replicate that here in CV_NMI. LD A, ($200E) ; game mode flag (0 = title/attract) AND A JP NZ, CV_NMI_DEC_TIMERS ; already in-game: skip to timer decrements ; ---- Title screen: 1P/2P selection (joystick up/down) + fire to start ---- ; Read joystick direction in mode $FF: bit0=UP, bit2=DOWN (active-LOW → HIGH after CPL) LD A, $FF OUT ($C0), A ; joystick direction mode NOP NOP NOP NOP IN A, ($FC) ; read controller 1 CPL ; active-HIGH AND $05 ; keep UP(bit0) and DOWN(bit2) LD B, A ; B = direction bits LD A, ($201E) ; debounce: 0=ready for new press AND A JR NZ, CV_NMI_TITLE_HELD ; a direction is held — check for release ; No direction held: register a new UP or DOWN press LD A, B AND $01 ; UP pressed? JR Z, CV_NMI_TITLE_DN XOR A LD ($205F), A ; 0 = 1 player selected INC A LD ($201E), A ; mark direction held JR CV_NMI_TITLE_CURSOR CV_NMI_TITLE_DN: LD A, B AND $04 ; DOWN pressed? JR Z, CV_NMI_TITLE_CURSOR ; neutral — just refresh cursor LD A, $01 LD ($205F), A ; 1 = 2 players selected LD ($201E), A ; mark direction held JR CV_NMI_TITLE_CURSOR CV_NMI_TITLE_HELD: LD A, B AND $05 ; still holding a direction? JR NZ, CV_NMI_TITLE_CURSOR ; yes — nothing new XOR A LD ($201E), A ; direction released: clear debounce CV_NMI_TITLE_CURSOR: ; Skip ALL VDP writes if main code is streaming to VRAM (CV_VDP_BUSY set). ; NMI OUT ($BE) writes advance the VDP auto-increment counter, corrupting the stream. LD A, ($3FFD) ; CV_VDP_BUSY: non-zero while PUT_VRAM/FILL_VRAM streaming OR A JR NZ, CV_NMI_TITLE_FIRE ; streaming in progress — skip tiles AND cursor update ; Write tile $74 cursor triangle to VRAM $03A0 LD A, $A0 OUT ($BF), A LD A, $43 OUT ($BF), A LD HL, CV_CURSOR74_DATA LD B, $08 CV_NMI_TILE74_WR: LD A, (HL) OUT ($BE), A INC HL DJNZ CV_NMI_TILE74_WR CALL SUB_4AA0 ; redraw cursor (safe: $3FFD=0, no streaming) CV_NMI_TITLE_FIRE: ; Now read fire button (mode $80 = bit 6 active-HIGH after CPL) LD A, $80 OUT ($C0), A ; switch to fire-button mode NOP NOP NOP NOP IN A, ($FC) ; read controller 1 CPL ; active-HIGH AND $40 ; bit 6 = fire button JP Z, CV_NMI_DEC_TIMERS ; not pressed: continue normally ; Fire pressed — copy 1P/2P selection and start game (mirrors MSX $E05F→$E00F then JP $401A) LD A, ($205F) LD ($200F), A ; save selected player count → $200F ($E00F) LD A, $01 LD ($200E), A ; set game-start flag ($E00E = 1) POP DE POP BC POP HL POP AF LD SP, $3200 ; reset game stack (discards NMI frame) JP CV_GAME_RESTART ; restart game with $200E=1 CV_NMI_DEC_TIMERS: ; Decrement all VBLANK frame timers $2025-$202B each interrupt. ; MSX BIOS INT handler decrements $E025-$E02B every VBLANK; the game gates ; enemy movement ($E027), bullet timing ($E026/$E028), software-sprite ; update skips ($E029/$E02A), and the title-screen auto-start timer ($E02B). LD HL, $2025 LD B, $07 CV_NMI_DEC_LOOP: LD A, (HL) AND A JR Z, CV_NMI_NEXT DEC (HL) CV_NMI_NEXT: INC HL DJNZ CV_NMI_DEC_LOOP ; Sound advance — in-game only (mirrors MSX $58C4 via H.TIMI hook) LD A, ($200E) AND A JR Z, CV_NMI_PHASE_MGT CALL CV_CHEAT_CHECK ; check 8675309 sequence cheat, then advance sound ; CV fix: repair byte 0 of PGT tiles corrupted by star animation each gameplay frame ; Star animation writes $C1/$C9/$D1/$D9/$20 to byte 0 of tiles $68,$6C,$70,$74,$78,$7C LD A, ($3FFD) ; CV_VDP_BUSY (streaming in progress?) OR A JR NZ, CV_NMI_PHASE_MGT ; skip if busy LD HL, $0340 XOR A CALL WRITE_VRAM ; tile $68 byte 0 = $00 LD HL, $0360 XOR A CALL WRITE_VRAM ; tile $6C byte 0 = $00 LD HL, $0380 XOR A CALL WRITE_VRAM ; tile $70 byte 0 = $00 LD HL, $03A0 LD A, $80 CALL WRITE_VRAM ; tile $74 byte 0 = $80 (cursor triangle top pixel) LD HL, $03C0 XOR A CALL WRITE_VRAM ; tile $78 byte 0 = $00 LD HL, $03E0 XOR A CALL WRITE_VRAM ; tile $7C byte 0 = $00 CV_NMI_PHASE_MGT: ; Enemy wave phase management — mirrors MSX $491F VBlank handler logic. ; Runs unconditionally each NMI (attract + gameplay). $2043=5 skips when all waves done. LD A, ($2043) ; RAM_E043: wave counter (incremented each Phase1→Phase2) CP $05 JR Z, CV_NMI_SKIP ; all waves done — skip phase management LD A, ($2015) ; RAM_E015: 1=Phase1 (special), 0=Phase2 (basic) AND A JR Z, CV_NMI_PHASE2_TICK ; Phase 2 active — run countdown ; Phase 1: scan 15 enemy entities $2120-$21E0 for any active (type != 0) LD HL, $2120 LD DE, $0010 LD B, $0F CV_NMI_SCAN: LD A, (HL) AND A JR NZ, CV_NMI_SKIP ; any entity active → stay in Phase 1 ADD HL, DE DJNZ CV_NMI_SCAN ; All 15 entities inactive: check $2100 bit 7 (set = stay Phase1, clear = transition) LD A, ($2100) AND $80 JR NZ, CV_NMI_SKIP ; bit 7 set → stay in Phase 1 ; MSX behaviour: Phase1 exits instantly when all entity slots are clear. ; At wave start all 15 slots are zeroed → instant Phase1→Phase2 so ; orange-gear enemies (LOC_47A1) begin descending before the powerup box ; (which arrives later via the 1/8-probability SUB_48AB path in Phase2). CV_NMI_DO_P2: ; Transition Phase 1 → Phase 2 (mirrors MSX $491F handler: XOR A clears flags) XOR A LD ($2068), A ; RAM_E068: clear special-enemy flag LD ($2069), A ; RAM_E069: clear special-enemy flag LD ($2015), A ; RAM_E015: 0 = Phase 2 LD A, ($2043) INC A LD ($2043), A ; RAM_E043: increment wave counter CALL SUB_516E ; update entity spawn distance ($204E) LD A, ($200E) ; CV: DELAY_LOOP_42DF updates sprites — only safe during gameplay AND A JR Z, CV_NMI_PHASE2_INIT ; title screen: skip $2067 LD A, $01 LD ($2067), A ; RAM_E067: phase-transition flag (gameplay only) CV_NMI_PHASE2_INIT: ; Initialise Phase 2 countdown timer ($E016 = $02BC = 700 VBlanks ≈ 11.7s) LD HL, $02BC LD ($2016), HL ; RAM_E016 JR CV_NMI_SKIP CV_NMI_PHASE2_TICK: ; Phase 2 → Phase 1 transition: decrement $2016 each VBlank. ; When it reaches 0, cycle $2018 mod 4; on the 4th cycle, set $2015=1 (Phase 1). LD HL, ($2016) DEC HL LD A, H OR L JR NZ, CV_NMI_P2_STORE ; still counting down ; Counter reached 0: cycle the wave-phase counter LD A, ($2018) ; RAM_E018: wave sub-counter (mod 4) INC A AND $03 LD ($2018), A JR NZ, CV_NMI_P2_RELOAD ; mod 4 not zero: reload counter, stay Phase 2 ; $E018 mod 4 == 0: re-enter Phase 1 (special enemies) INC A ; A = 1 LD ($2015), A ; RAM_E015 = 1 → Phase 1 starts JR CV_NMI_SKIP ; leave $2016 as-is (will be set when Phase 1 clears) CV_NMI_P2_RELOAD: LD HL, $02BC ; reload 700-VBlank countdown CV_NMI_P2_STORE: LD ($2016), HL ; RAM_E016 CV_NMI_SKIP: POP DE POP BC POP HL POP AF RETN ; ---- CV_SOUND_ADV: per-frame note advance (replaces MSX $58C4-$58F0 DB block) ---------- ; MSX stored this Z80 subroutine as raw DB bytes after an unconditional JR (unreachable by ; fall-through); it was called each VBlank via the H.TIMI hook (JP $491F at $FD9F/$FDA0). ; On CV, CV_NMI calls this each VBLANK when in-game ($200E != 0). ; IY state per AY channel: $2400/$2410/$2420 (B=3/2/1 = ch A/B/C) ; +0 = priority/status ($FF = inactive) +1 = tempo period ; +2 = tempo countdown +3,+4 = current note pointer (HL) CV_SOUND_ADV: PUSH IY LD IY, $2400 ; AY channel state area (CV $2400 = MSX $E400) LD DE, $0010 LD B, $03 CV_SOUND_ADV_LP: LD A, (IY+0) CP $FF ; $FF = channel inactive / song ended JR Z, CV_SOUND_ADV_NX DEC (IY+2) ; decrement tempo countdown JR NZ, CV_SOUND_ADV_NX ; not yet: nothing this frame LD A, (IY+1) LD (IY+2), A ; reload countdown from tempo period LD L, (IY+3) LD H, (IY+4) ; HL = current note pointer CALL SUB_58F1 ; write next note; B = channel id (3/2/1) CV_SOUND_ADV_NX: ADD IY, DE DJNZ CV_SOUND_ADV_LP POP IY RET ; ---- CV_RDVDP: read VDP status register ----------------------------- ; Replaces MSX RDVDP ($013E) ; Output: A = VDP status byte CV_RDVDP: IN A, ($BF) ; CTRL_PORT - read VDP status RET ; ---- CV_SETRD: set VRAM read address -------------------------------- ; Replaces MSX SETRD ($0050) ; Input: HL = VRAM address CV_SETRD: LD A, L OUT ($BF), A ; CTRL_PORT - low byte of address LD A, H AND $3F ; mask to 14-bit VRAM address OUT ($BF), A ; CTRL_PORT - high byte + read flag RET ; ---- CV_SETWRT: set VRAM write address ------------------------------ ; Replaces MSX SETWRT ($0053) ; Input: HL = VRAM address CV_SETWRT: LD A, L OUT ($BF), A ; CTRL_PORT - low byte LD A, H AND $3F OR $40 ; set write flag OUT ($BF), A ; CTRL_PORT - high byte + write flag RET ; ---- CV_LDIRMV: block copy VRAM→RAM --------------------------------- ; Replaces MSX LDIRMV ($0061) ; Input: BC = byte count, HL = VRAM source addr, DE = RAM dest addr CV_LDIRMV: CALL CV_SETRD CV_LDIRMV_LOOP: IN A, ($BE) ; DATA_PORT - read VRAM byte LD (DE), A INC DE DEC BC LD A, B OR C JR NZ, CV_LDIRMV_LOOP RET ; ---- CV_RDVRM: read one VRAM byte ------------------------------------------ ; Replaces MSX RDVRM ($004A) ; Input: HL = VRAM address ; Output: A = VRAM[HL] (HL preserved) CV_RDVRM: IN A, ($BF) ; reset VDP address latch LD A, L OUT ($BF), A ; CTRL_PORT - low byte of address LD A, H AND $3F ; mask to 14-bit, read mode (no $40) OUT ($BF), A ; CTRL_PORT - high byte IN A, ($BE) ; DATA_PORT - read VRAM byte RET ; ---- WRITE_REGISTER: write TMS9918 VDP register (no BIOS needed) ------- ; Replaces CV BIOS WRITE_REGISTER ($1FD9) — self-contained, no BIOS ROM required ; Input: B = data byte, C = register number (0-7) WRITE_REGISTER: IN A, ($BF) ; reset VDP address latch + ack any pending /INT LD A, B OUT ($BF), A ; write data byte to CTRL_PORT LD A, C OR $80 ; register-select flag OUT ($BF), A ; write register address RET ; ---- WRITE_VRAM: write one byte to VRAM (no BIOS needed) ---------------- ; Replaces CV BIOS WRITE_VRAM ($1FDF) — self-contained ; Input: HL = VRAM address, A = data byte ; Critical section (E011) prevents NMI from resetting VDP latch between ; the two OUT ($BF) address bytes. WRITE_VRAM: PUSH AF ; save data byte PUSH HL ; save VRAM address LD HL, $2011 ; critical section flag INC (HL) ; enter critical section IN A, ($BF) ; reset VDP latch + ack any pending /INT POP HL ; restore VRAM address LD A, L OUT ($BF), A ; VRAM addr low byte LD A, H AND $3F OR $40 ; write-mode bit OUT ($BF), A ; VRAM addr high byte POP AF ; restore data OUT ($BE), A ; write data to DATA_PORT PUSH HL LD HL, $2011 DEC (HL) ; exit critical section POP HL RET ; ---- FILL_VRAM: fill VRAM region with constant (no BIOS needed) ---------- ; Replaces CV BIOS FILL_VRAM ($1F82) — self-contained ; Input: A = fill byte, BC = byte count, HL = VRAM start address ; Critical section protects the 2-byte address setup; streaming writes are safe. FILL_VRAM: PUSH DE PUSH HL ; preserve caller's HL PUSH AF ; save fill byte PUSH HL ; save VRAM address for critical section LD HL, $2011 INC (HL) ; enter critical section IN A, ($BF) ; reset VDP latch + ack /INT POP HL ; restore VRAM address LD A, L OUT ($BF), A ; VRAM addr low LD A, H AND $3F OR $40 OUT ($BF), A ; VRAM addr high + write flag LD HL, $3FFD INC (HL) ; set CV_VDP_BUSY (still inside critical section) LD HL, $2011 DEC (HL) ; exit critical section POP AF ; restore fill byte LD D, A ; save fill byte in D for loop FILL_VRAM_LOOP: LD A, D OUT ($BE), A ; write fill byte DEC BC LD A, B OR C JR NZ, FILL_VRAM_LOOP LD A, D ; restore A = fill byte LD HL, $3FFD DEC (HL) ; clear CV_VDP_BUSY POP HL ; restore caller's HL POP DE RET ; ---- PUT_VRAM: block copy RAM→VRAM (no BIOS needed) --------------------- ; Replaces CV BIOS PUT_VRAM ($1FBE) — self-contained ; Input: BC = byte count, DE = VRAM destination, HL = RAM source ; Critical section protects the 2-byte address setup; streaming writes are safe. PUT_VRAM: PUSH HL ; save RAM source LD HL, $2011 INC (HL) ; enter critical section IN A, ($BF) ; reset VDP latch + ack /INT POP HL ; restore RAM source LD A, E OUT ($BF), A ; VRAM addr low LD A, D AND $3F OR $40 OUT ($BF), A ; VRAM addr high + write flag PUSH HL LD HL, $3FFD INC (HL) ; set CV_VDP_BUSY (still inside critical section) LD HL, $2011 DEC (HL) ; exit critical section POP HL PUT_VRAM_LOOP: LD A, (HL) OUT ($BE), A ; write byte INC HL DEC BC LD A, B OR C JR NZ, PUT_VRAM_LOOP LD HL, $3FFD DEC (HL) ; clear CV_VDP_BUSY RET ; ---- CV_CURSOR74_DATA: right-pointing triangle, 8x8, for tile $74 cursor ---- ; Loaded to VRAM $03A0 by CV_STARTUP before game init runs. CV_CURSOR74_DATA: DB $80,$C0,$E0,$F0,$E0,$C0,$80,$00 ; ---- CV_FONT_DATA: 96-char (0x00-0x5F) standard 8x8 ASCII font ----- ; Replaces MSX BIOS font table pointer (LD HL,($0004)) used in Space Trouble. ; Game copies 768 bytes (PUT_VRAM BC=$0300, DE=$0000) to pattern generator table. ; Characters $20-$5A cover all text used: space, digits, uppercase A-Z. CV_FONT_DATA: ; $00-$07 (control) DB $00,$00,$00,$00,$00,$00,$00,$00 ; 00 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 01 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 02 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 03 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 04 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 05 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 06 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 07 ; $08-$0F DB $00,$00,$00,$00,$00,$00,$00,$00 ; 08 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 09 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 0A DB $00,$00,$00,$00,$00,$00,$00,$00 ; 0B DB $00,$00,$00,$00,$00,$00,$00,$00 ; 0C DB $00,$00,$00,$00,$00,$00,$00,$00 ; 0D DB $00,$00,$00,$00,$00,$00,$00,$00 ; 0E DB $00,$00,$00,$00,$00,$00,$00,$00 ; 0F ; $10-$17 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 10 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 11 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 12 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 13 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 14 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 15 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 16 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 17 ; $18-$1F DB $00,$00,$00,$00,$00,$00,$00,$00 ; 18 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 19 DB $00,$00,$00,$00,$00,$00,$00,$00 ; 1A DB $00,$00,$00,$00,$00,$00,$00,$00 ; 1B DB $00,$00,$00,$00,$00,$00,$00,$00 ; 1C DB $00,$00,$00,$00,$00,$00,$00,$00 ; 1D DB $00,$00,$00,$00,$00,$00,$00,$00 ; 1E DB $00,$00,$00,$00,$00,$00,$00,$00 ; 1F ; $20-$27 (printable) DB $00,$00,$00,$00,$00,$00,$00,$00 ; 20 space DB $00,$18,$18,$18,$18,$00,$18,$00 ; 21 ! DB $00,$66,$66,$24,$00,$00,$00,$00 ; 22 " DB $00,$6C,$FE,$6C,$6C,$FE,$6C,$00 ; 23 # DB $30,$7C,$B0,$78,$1C,$D6,$7C,$10 ; 24 $ DB $60,$66,$0C,$18,$30,$66,$06,$00 ; 25 % DB $38,$6C,$68,$76,$DC,$CE,$7B,$00 ; 26 & DB $00,$18,$18,$10,$00,$00,$00,$00 ; 27 ' ; $28-$2F DB $0C,$18,$30,$30,$30,$18,$0C,$00 ; 28 ( DB $30,$18,$0C,$0C,$0C,$18,$30,$00 ; 29 ) DB $00,$66,$3C,$FF,$3C,$66,$00,$00 ; 2A * DB $00,$30,$30,$FC,$30,$30,$00,$00 ; 2B + DB $00,$00,$00,$00,$00,$18,$18,$30 ; 2C , DB $00,$00,$00,$7E,$00,$00,$00,$00 ; 2D - DB $00,$00,$00,$00,$00,$18,$18,$00 ; 2E . DB $06,$0C,$18,$30,$60,$C0,$80,$00 ; 2F / ; $30-$37 digits DB $3C,$66,$6E,$76,$66,$66,$3C,$00 ; 30 0 DB $18,$78,$18,$18,$18,$18,$7E,$00 ; 31 1 DB $3C,$66,$06,$1C,$38,$60,$7E,$00 ; 32 2 DB $3C,$66,$06,$1C,$06,$66,$3C,$00 ; 33 3 DB $0E,$1E,$36,$66,$7F,$06,$0F,$00 ; 34 4 DB $7E,$60,$7C,$06,$06,$66,$3C,$00 ; 35 5 DB $1C,$30,$60,$7C,$66,$66,$3C,$00 ; 36 6 DB $7E,$66,$06,$0C,$18,$18,$18,$00 ; 37 7 ; $38-$3F DB $3C,$66,$66,$3C,$66,$66,$3C,$00 ; 38 8 DB $3C,$66,$66,$3E,$06,$0C,$38,$00 ; 39 9 DB $00,$00,$18,$18,$00,$18,$18,$00 ; 3A : DB $00,$00,$18,$18,$00,$18,$18,$30 ; 3B ; DB $0C,$18,$30,$60,$30,$18,$0C,$00 ; 3C < DB $00,$00,$7E,$00,$7E,$00,$00,$00 ; 3D = DB $60,$30,$18,$0C,$18,$30,$60,$00 ; 3E > DB $3C,$66,$06,$0C,$18,$00,$18,$00 ; 3F ? ; $40-$47 DB $3C,$66,$6E,$6A,$6C,$60,$3C,$00 ; 40 @ DB $18,$3C,$66,$7E,$66,$66,$66,$00 ; 41 A DB $7C,$66,$66,$7C,$66,$66,$7C,$00 ; 42 B DB $3C,$66,$60,$60,$60,$66,$3C,$00 ; 43 C DB $78,$6C,$66,$66,$66,$6C,$78,$00 ; 44 D DB $7E,$60,$60,$7C,$60,$60,$7E,$00 ; 45 E DB $7E,$60,$60,$7C,$60,$60,$60,$00 ; 46 F DB $3C,$66,$60,$6E,$66,$66,$3C,$00 ; 47 G ; $48-$4F DB $66,$66,$66,$7E,$66,$66,$66,$00 ; 48 H DB $3C,$18,$18,$18,$18,$18,$3C,$00 ; 49 I DB $1E,$0C,$0C,$0C,$6C,$6C,$38,$00 ; 4A J DB $66,$6C,$78,$70,$78,$6C,$66,$00 ; 4B K DB $60,$60,$60,$60,$60,$60,$7E,$00 ; 4C L DB $66,$7E,$7E,$7E,$66,$66,$66,$00 ; 4D M DB $66,$76,$7E,$7E,$6E,$66,$66,$00 ; 4E N DB $3C,$66,$66,$66,$66,$66,$3C,$00 ; 4F O ; $50-$57 DB $7C,$66,$66,$7C,$60,$60,$60,$00 ; 50 P DB $3C,$66,$66,$66,$6E,$3C,$0E,$00 ; 51 Q DB $7C,$66,$66,$7C,$6C,$66,$66,$00 ; 52 R DB $3C,$66,$60,$3C,$06,$66,$3C,$00 ; 53 S DB $7E,$18,$18,$18,$18,$18,$18,$00 ; 54 T DB $66,$66,$66,$66,$66,$66,$3C,$00 ; 55 U DB $66,$66,$66,$66,$3C,$3C,$18,$00 ; 56 V DB $66,$66,$66,$7E,$7E,$7E,$66,$00 ; 57 W ; $58-$5F DB $66,$66,$3C,$18,$3C,$66,$66,$00 ; 58 X DB $66,$66,$3C,$18,$18,$18,$18,$00 ; 59 Y DB $7E,$06,$0C,$18,$30,$60,$7E,$00 ; 5A Z DB $3C,$30,$30,$30,$30,$30,$3C,$00 ; 5B [ DB $C0,$60,$30,$18,$0C,$06,$02,$00 ; 5C backslash DB $3C,$0C,$0C,$0C,$0C,$0C,$3C,$00 ; 5D ] DB $10,$38,$6C,$C6,$00,$00,$00,$00 ; 5E ^ DB $00,$00,$00,$00,$00,$00,$FE,$00 ; 5F _ ; ---- CV_WRTPSG: write PSG register via SGM AY-3-8910 --------------- ; Replaces MSX WRTPSG ($0093): A=register, E=data ; MSX WRTPSG preserves A after the call (does OUT($A0),A then OUT($A1),E without ; touching A again). This is critical: SUB_58F1 does INC A after CALL WRTPSG to ; step from fine-period register to coarse-period register. Our SGM write requires ; LD A,E before OUT($51),A, which would clobber A — so we save/restore it. ; MSX ports: $A0=register select, $A1=data write ; SGM ports: $50=register select, $51=data write (same AY-3-8910 chip!) ; REQUIRES: ColecoVision Super Game Module (SGM) CV_WRTPSG: OUT ($50), A ; SGM AY-3-8910 - select register PUSH AF ; preserve register index in A LD A, E OUT ($51), A ; SGM AY-3-8910 - write data POP AF ; restore A = register index (caller may INC A) RET ; ---- CV_RDPSG: read PSG register via SGM AY-3-8910 ----------------- ; Replaces MSX RDPSG ($0096): A=register, returns A=data ; SPECIAL: R14 (AY I/O Port A = MSX joystick) is intercepted. ; On MSX the AY I/O Port A is wired to joystick ports; on CV+SGM it is not. ; For R14: returns CV controller 1 data remapped to MSX R14 active-LOW format. ; For all other registers: reads SGM AY chip normally. ; ; CV controller (after OUT ($C0),$80 — combined direction+fire mode): ; IN $FC raw bits (active-LOW, 0=pressed): ; bit3=UP bit2=RIGHT bit1=DOWN bit0=LEFT bit6=FIRE (confirmed from real CV games) ; ; MSX AY R14 format (active-LOW, 0=pressed): ; bit0=UP bit1=DOWN bit2=LEFT bit3=RIGHT bit4=TrigA bits5-7=1(not pressed) CV_RDPSG: CP $0E ; register 14 = AY I/O Port A JR Z, CV_RDPSG_JOY OUT ($50), A ; SGM AY-3-8910 - select register IN A, ($52) ; SGM AY-3-8910 - read data RET CV_RDPSG_JOY: ; Read CV controller 1 in combined direction+fire mode LD A, $80 OUT ($C0), A ; $80 to $C0: combined direction+fire read NOP NOP NOP NOP NOP NOP NOP NOP IN A, ($FC) ; raw: bit3=U, bit2=R, bit1=D, bit0=L, bit6=F (active-LOW) PUSH BC LD B, A ; CV bit3 (UP) → MSX bit0 AND $08 RRCA RRCA RRCA ; bit3→bit0 LD C, A ; CV bit1 (DOWN) → MSX bit1 (same position) LD A, B AND $02 OR C LD C, A ; CV bit0 (LEFT) → MSX bit2 LD A, B AND $01 RLCA RLCA ; bit0→bit2 OR C LD C, A ; CV bit2 (RIGHT) → MSX bit3 LD A, B AND $04 RLCA ; bit2→bit3 OR C LD C, A ; CV bit6 (FIRE) → MSX bit4 (TrigA) LD A, B AND $40 RRCA RRCA ; bit6→bit4 OR C OR $E0 ; bits7-5 = 1 (not pressed in active-LOW) POP BC RET ; ---- CV_READ_JOY: read joystick, return MSX-format input bits ------- ; Replaces calls to MSX GTSTCK, GTTRIG, SNSMAT. ; ; Returns A = input bits in MSX sky-Jaguar format (active-HIGH): ; bit 0 = UP ; bit 1 = DOWN ; bit 2 = LEFT ; bit 3 = RIGHT ; bit 4 = TRIGGER_A (fire button 1) ; bit 5 = TRIGGER_B (fire button 2) ; ; ColecoVision controller port $FC in joystick mode (after OUT ($C0),A): ; bit 0 = UP (active-LOW, 0 = pressed) ; bit 1 = RIGHT (active-LOW) ; bit 2 = DOWN (active-LOW) ; bit 3 = LEFT (active-LOW) ; ; After CPL and AND $0F we get active-HIGH directional bits. ; CV order: [bit3=L, bit2=D, bit1=R, bit0=U] ; MSX order: [bit3=R, bit2=L, bit1=D, bit0=U] ; Bit shuffle needed: keep bit0, rotate bits[3:1]: LDR→RLD ; CV_READ_JOY: PUSH BC PUSH HL ; --- Select joystick mode and read all bits at once --- ; ColecoVision port $FC in joystick mode (after OUT $C0,$FF): ; bit0=UP, bit1=RIGHT, bit2=DOWN, bit3=LEFT (active-LOW) ; bit4=RIGHT_FIRE (top button), bit5=LEFT_FIRE (side button) (active-LOW) ; bits 6-7 always 1 LD A, $FF OUT ($C0), A ; JOY_PORT - joystick mode IN A, ($FC) ; CONTROLLER_01 CPL ; active-HIGH: bits 0-5 now 1=pressed LD B, A ; save full byte (directions + fire) ; --- Reshuffle direction bits to MSX format --- ; CV: bit0=U bit1=R bit2=D bit3=L ; MSX: bit0=U bit1=D bit2=L bit3=R AND $01 ; bit0 = UP (same position) LD L, A LD A, B AND $02 ; bit1 = RIGHT (CV) → bit3 (MSX) RLCA RLCA OR L LD L, A LD A, B AND $04 ; bit2 = DOWN (CV) → bit1 (MSX) RRCA OR L LD L, A LD A, B AND $08 ; bit3 = LEFT (CV) → bit2 (MSX) RRCA OR L LD L, A ; --- Fire buttons: bits 4-5 already at MSX positions --- ; CV bit4=RIGHT_FIRE → MSX bit4=TRIGGER_A ; CV bit5=LEFT_FIRE → MSX bit5=TRIGGER_B LD A, B AND $30 ; keep bits 4-5 OR L ; combine with directions POP HL POP BC RET ; ---- CV_FIRE_CHECK: check fire button (replaces MSX BIOS call at $00D8) ----- ; Space Trouble calls $00D8 (unknown MSX BIOS routine) with A=joystick port. ; We intercept and read the CV fire button directly. ; Input: A = port number (ignored — always reads controller 1) ; Output: A = $40 if fire pressed, $00 if not pressed ; CV joystick mode: bit6=fire (side trigger, active-LOW after CPL → $40) CV_FIRE_CHECK: PUSH BC LD A, $80 OUT ($C0), A ; joystick mode (bit6=fire, bits0-3=directions) NOP NOP NOP NOP NOP NOP NOP NOP IN A, ($FC) ; read controller 1 CPL ; active-HIGH AND $40 ; bit 6 = fire button POP BC RET ; ---- CV_STICK_CHECK: read stick direction (replaces MSX BIOS call at $00D5) - ; Space Trouble calls $00D5 (unknown MSX BIOS routine) with A=joystick port. ; We intercept and return MSX GTSTCK-format direction. ; Input: A = port number (ignored — always reads controller 1) ; Output: A = 0=neutral, 1=up, 2=upright, 3=right, 4=downright, ; 5=down, 6=downleft, 7=left, 8=upleft ; CV combined mode bits after CPL+AND $0F: bit3=L, bit2=D, bit1=R, bit0=U CV_STICK_CHECK: PUSH BC PUSH HL LD A, $80 OUT ($C0), A ; combined direction+fire mode NOP NOP NOP NOP NOP NOP NOP NOP IN A, ($FC) CPL AND $0F ; direction bits: bit3=L, bit2=D, bit1=R, bit0=U LD C, A LD B, $00 LD HL, CV_STICK_TABLE ADD HL, BC ; index into table LD A, (HL) ; MSX GTSTCK direction code POP HL POP BC RET CV_STICK_TABLE: ; Index bits: [3=L, 2=D, 1=R, 0=U] Value: MSX GTSTCK code (0=neutral,1=U,2=UR,3=R,4=DR,5=D,6=DL,7=L,8=UL) DB $00, $01, $03, $02, $05, $00, $04, $00 DB $07, $08, $00, $00, $06, $00, $00, $00 ; ---- CV_KEYBOARD_CHECK: title screen fire check (replaces MSX SUB_56DE) ----- ; MSX SUB_56DE checks RAM_E02B flag (set by MSX BIOS NMI keyboard scan). ; On CV there is no keyboard; the flag is never set from hardware. ; This shim checks the CV fire button directly so title screen responds. ; Returns non-zero if fire pressed, $00 if not (game tests non-zero = pressed). CV_KEYBOARD_CHECK: PUSH BC LD A, $80 OUT ($C0), A ; joystick mode (bit6=fire, bits0-3=directions) NOP NOP NOP NOP NOP NOP NOP NOP IN A, ($FC) ; read controller 1 CPL AND $40 ; bit 6 = fire button POP BC RET ; ---- CV_TITLE_CURSOR_UPDATE: attract-mode frame update ---------------------- ; SUB_55A5 already calls SUB_4AA0 which draws the red-triangle cursor (tile $74) ; at col 6 of row 21 (1P) or row 22 (2P) based on $205F. This wrapper exists ; only so the substitution machinery can intercept CALL SUB_55A5 safely from ; the main loop. CV_TITLE_CURSOR_UPDATE: JP SUB_55A5 ; tail-call: cursor drawing is handled inside ; ---- SGM_PSG_TEST: verify SGM AY-3-8910 is present; halts if not ---- ; Source: sgm-dection-code.asm ; Writes $AA to PSG reg 0 and $55 to PSG reg 2, reads back to confirm. ; Pass: returns silently. Fail: calls LDERR (does not return). SGM_PSG_TEST: LD HL, $5502 ; H=$55 (value), L=$02 (reg#) LD DE, $AA00 ; D=$AA (value), E=$00 (reg#) CALL PSG_SET ; write $AA to PSG reg 0 EX DE, HL ; DE=$5502, HL=$AA00 CALL PSG_SET ; write $55 to PSG reg 2 EX DE, HL ; DE=$AA00, HL=$5502 CALL PSG_TST1 ; verify reg 0 = $AA EX DE, HL CALL PSG_TST1 ; verify reg 2 = $55 RET ; PSG confirmed — return silently PSG_TST1: LD A, E OUT (SGM_PSG_REG), A ; select PSG register E LD D, D ; settling delay (NOP) IN A, (SGM_PSG_READ) ; read back register value CP D ; compare with expected value D RET Z ; return if match PSG_TST2: POP DE ; discard PSG_TST1 return address JP LDERR ; PSG not found — display error and halt PSG_SET: LD A, E OUT (SGM_PSG_REG), A ; select PSG register E LD A, D OUT (SGM_PSG_DAT), A ; write value D RET ; ---- LDERR: fatal startup error — display message on screen and halt ---- ; Called when SGM PSG not detected. Uses only built-in 1KB CV RAM ($6000-$63FF). ; Reinitialises VDP, loads Space Trouble font, writes error message, then loops. LDERR: IN A, ($BF) ; reset VDP address latch LD B, $08 LD HL, LDERR_VDP_REGS LDERR_VDP_INIT: LD A, (HL) OUT ($BF), A ; register value INC HL LD A, (HL) OUT ($BF), A ; $80 | register number INC HL DJNZ LDERR_VDP_INIT ; Load Space Trouble font into PGT $0000 (96 chars, 768 bytes) LD HL, CV_FONT_DATA LD DE, $0000 LD BC, $0300 CALL PUT_VRAM ; Clear name table to spaces ($20) LD A, $20 LD HL, $1800 LD BC, $0300 CALL FILL_VRAM ; Set color table (VRAM $2000, 32 entries) — $F1 = white fg / black bg LD A, $F1 LD HL, $2000 LD BC, $0020 CALL FILL_VRAM ; "SGM NOT FOUND," — row 9, col 9 (14 chars, centered in 32) LD HL, $1929 LD DE, LDERR_LINE1 CALL LDVRM ; "THIS GAME REQUIRES IT!" — row 11, col 5 (22 chars, centered in 32) LD HL, $1965 LD DE, LDERR_LINE2 CALL LDVRM LDERR_HALT: JR LDERR_HALT ; halt forever — no SGM, cannot continue LDERR_VDP_REGS: DB $00,$80 ; R0 = $00 (Graphics Mode 1) DB $C0,$81 ; R1 = $C0 (16K, display on, IE off — no NMI) DB $06,$82 ; R2 = $06 (name table @ $1800: 6×$400=$1800) DB $80,$83 ; R3 = $80 (color table @ $2000: $80×$40=$2000) DB $00,$84 ; R4 = $00 (PGT @ $0000) DB $36,$85 ; R5 = $36 (sprite attr table) DB $07,$86 ; R6 = $07 (sprite PGT) DB $F1,$87 ; R7 = $F1 (white fg / black backdrop) ; ---- LDVRM: write null-terminated string to VRAM ---- ; HL = VRAM start address, DE = pointer to null-terminated string LDVRM: LD A, L OUT ($BF), A ; VRAM addr low LD A, H AND $3F OR $40 OUT ($BF), A ; VRAM addr high + write flag LDVRM_LOOP: LD A, (DE) AND A RET Z ; null terminator — done OUT ($BE), A INC DE JR LDVRM_LOOP ; ---- CV_CHEAT_CHECK: keypad sequence 8-6-7-5-3-0-9 = +10 lives (max 99) ---- ; Runs every NMI frame during gameplay. Debounced per-frame key detection. ; RAM: $7FF0 = sequence index (0-6), $7FF1 = last key seen (debounce) CV_CHEAT_CHECK: PUSH AF PUSH BC PUSH HL ; Read keypad LD A, $00 OUT ($80), A ; switch to keypad mode NOP NOP NOP NOP NOP NOP NOP NOP IN A, ($FC) ; read controller 1 OUT ($C0), A ; restore joystick mode AND $0F ; isolate key nibble LD B, A ; B = current key ($0F = no key) ; Debounce: act only on key-DOWN (prev=$0F, current<>$0F) LD A, ($7FF1) ; A = previous key LD C, A ; C = previous key LD A, B LD ($7FF1), A ; store current as new previous LD A, C CP $0F JR NZ, CV_CHEAT_DONE ; prev was a key = held or released, skip LD A, B CP $0F JR Z, CV_CHEAT_DONE ; current = no key, skip ; Newly pressed key: check against expected sequence entry LD A, ($7FF0) ; A = sequence index (0-6) LD L, A LD H, $00 LD DE, CV_CHEAT_SEQ ADD HL, DE ; HL = &CV_CHEAT_SEQ[index] LD A, (HL) ; A = expected code CP B JR NZ, CV_CHEAT_WRONG ; Correct key: advance index LD A, ($7FF0) INC A LD ($7FF0), A CP $07 ; sequence complete? JR NZ, CV_CHEAT_DONE ; Sequence complete: give +10 lives, cap at 99, reset index XOR A LD ($7FF0), A LD A, ($2040) ; lives counter ADD A, $0A ; +10 CP $64 ; >= 100? JR C, CV_CHEAT_SET_LIVES LD A, $63 ; cap at 99 CV_CHEAT_SET_LIVES: LD ($2040), A JR CV_CHEAT_DONE ; Wrong key: reset index to 0; if it matches SEQ[0], set index=1 CV_CHEAT_WRONG: XOR A LD ($7FF0), A ; index = 0 LD HL, CV_CHEAT_SEQ LD A, (HL) ; A = SEQ[0] CP B JR NZ, CV_CHEAT_DONE LD A, $01 LD ($7FF0), A ; wrong key but starts sequence: index = 1 CV_CHEAT_DONE: POP HL POP BC POP AF CALL CV_SOUND_ADV RET ; Keypad codes for sequence 8-6-7-5-3-0-9 (port $FC bits 3:0, keypad mode) CV_CHEAT_SEQ: DB $01, $0E, $05, $03, $0C, $0A, $0B ; ---- CV_CREDITS_STUB: display "1988" then "KAMSHAFT" on title screen ---- ; Replaces LD HL,$8B7E / CALL SUB_4AE9 (which displayed "1988" alone). ; "1988" -> VRAM $1A0A (row 16, col 10), 4 bytes ; "KAMSHAFT" -> VRAM $1A67 (row 19, col 7), 8 bytes CV_CREDITS_STUB: LD HL, CV_CREDITS_1988 CALL SUB_4AE9 LD HL, CV_CREDITS_KAMSHAFT JP SUB_4AE9 ; tail-call — returns to original caller CV_CREDITS_1988: DB $0A, $1A, $04 ; VRAM $1A0A (row 16, col 10), 4 bytes DB $31, $39, $38, $38 ; "1988" CV_CREDITS_KAMSHAFT: DB $67, $1A, $08 ; VRAM $1A67 (row 19, col 7), 8 bytes DB $4B, $41, $4D, $53, $48, $41, $46, $54 ; "KAMSHAFT" ; Error message strings — uppercase ASCII, tile index = ASCII value LDERR_LINE1: DB $53,$47,$4D,$20,$4E,$4F,$54,$20,$46,$4F,$55,$4E,$44,$2C,$00 ; "SGM NOT FOUND," LDERR_LINE2: DB $54,$48,$49,$53,$20,$47,$41,$4D,$45,$20,$52,$45,$51,$55,$49,$52,$45,$53,$20,$49,$54,$21,$00 ; "THIS GAME REQUIRES IT!" ; Pad to 16KB ColecoVision cart boundary DS ($C000 - $), $FF