; ===== GATEWAY TO APSHAI (1984) DISASSEMBLY LEGEND ===== ; ROM: 12 KB ($8000-$AFFF). VDP $BE/$BF. SN76489A on $FF. ; ; === CART ENTRY (NMI) & GAME LOOPS === ; CART_ENTRY ($8021, NMI handler) ....... 236 ; LOC_8036 (main game loop) .............. 267 ; LOC_8054 (difficulty counter cap) ...... 280 ; LOC_805D (frame entry) ................. 287 ; LOC_80D3 (sprite plane updates) ........ 340 ; LOC_80ED (level display path) .......... 356 ; LOC_80FD (scroll position update) ...... 364 ; LOC_814D (action/combat inner loop) .... 397 ; ; === BOOT & INIT === ; START (clear RAM, SOUND_INIT, VDP en) ... 894 ; LOC_8BFB (title screen / game init) .... 1863 ; SUB_8504 (wait for fire button) ......... 920 ; SUB_8557 (VDP write-addr reset) ......... 987 ; SUB_85A8 (sprite mode / VDP enable) ..... 1021 ; VDP_REG_8DE0 (VDP dungeon init) ......... 1941 ; ; === MISC HELPERS === ; SUB_8512 (read controller / DECODER) .... 932 ; SUB_8534 (LCG random-number advance) .... 958 ; SUB_854A (multiply A x DE via shift) .... 977 ; SUB_8325 (BCD score accumulation) ....... 679 ; SUB_834B (level-segment advance check) .. 709 ; ; === VDP ACCESS === ; VDP_REG_85B4 (set VRAM write address) ... 1028 ; VDP_REG_86E8 (set VRAM read address) .... 1200 ; VDP_DATA_8702 (set addr DE, write A) .... 1225 ; SUB_870A (indexed VRAM tile read) ....... 1232 ; VDP_WRITE_8842 (write A to VRAM at HL) .. 1477 ; SUB_86DD (16-bit table offset DE+=A) .... 1188 ; ; === SOUND === ; SOUND_WRITE_81C1 (fire/event sound) ..... 469 ; SOUND_WRITE_9AE5 (ambient sound queue) .. 2979 ; SOUND_WRITE_9C09 (sound effect trigger) . 3117 ; ; === DUNGEON MAP / RENDER === ; LOC_8E14 (dungeon renderer, 60 rows) .... 1967 ; SUB_AE00 (write 60 map rows to VRAM) .... 5013 ; DELAY_LOOP_AE23 (frame sync+map copy) ... 5041 ; SUB_9F15 (calc scroll $7050/$70CA) ...... 3445 ; ; === STATS & HUD === ; SUB_9E03 (render all 5 stats to HUD) .... 3325 ; VDP_DATA_9E35 (byte to 2 dec digits) .... 3347 ; SUB_9B93 (clear HUD VRAM area) .......... 3055 ; SUB_9BA2 (render score/level/time HUD) .. 3063 ; ; === CHARACTER / EQUIPMENT SCREENS === ; SUB_9C35 (equipment/push-button screen) . 3134 ; SUB_9D14 (inventory list renderer) ....... 3171 ; SUB_9D43 (characteristics screen) ........ 3204 ; SUB_9932 (dungeon level select screen) ... 2859 ; ; === COMBAT & EVENTS === ; SUB_AA3A (enemy/object tick: AI+collide) . 4408 ; SUB_9E51 (tile collision/door/exit check) . 3371 ; VDP_DATA_8255 (door/exit tile detector) ... 564 ; SUB_AD4F (item-pickup event handler) ..... 4889 ; SUB_AD5A (monster-hit event handler) ..... 4898 ; SUB_AD70 (enemy-event: write to VDP) .... 4913 ; ; === GAME OVER === ; LOC_AF2F (lives decrement) ............... 5223 ; LOC_AF3E (game over screen, JP BOOT_UP) .. 5232 ; ; === VRAM BUFFERS === ; SUB_89DC (tile+spr-attr bufs to VRAM) ... 1769 ; VDP_WRITE_9254 (spr pat+attr to VRAM) ... 2610 ; ; === KEY RAM ($7000-$73FA) === ; $7048/$704A viewport tile X/Y ; $704C/$704E player world tile X/Y ; $7050 scroll offset X (0-$70) ; $7057 dungeon level (0-based) ; $7058 agility/difficulty counter (max $08) ; $7059-$705B score BCD (lo/mid/hi bytes) ; $705E inventory item count ; $7064 enemy event pending flag ; $7066 room-transition / event flag (0=play) ; $706E-$7072 STR/AGI/LCK/HEALTH/LIVES stats ; $708F NMI occurred flag (bit 7) ; $70C3 map row decode buffer (from $AA2D) ; $70DF tile render buffer ($200 bytes) ; $72DF sprite attribute buffer ($80 bytes) ; $73F4 map data ROM pointer ; $73F6 HUD VRAM base address ; $73FA tile page VRAM base address ; ; ================================================ ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; BIOS DEFINITIONS ************************** BOOT_UP: EQU $0000 ; BOOT_UP $0000 — cold-start / warm-start entry vector BIOS_NMI: EQU $0066 ; BIOS_NMI $0066 — BIOS NMI handler entry NUMBER_TABLE: EQU $006C ; NUMBER_TABLE $006C — BIOS number-table address PLAY_SONGS: EQU $1F61 ; PLAY_SONGS $1F61 — BIOS PLAY_SONGS ACTIVATEP: EQU $1F64 ; ACTIVATEP $1F64 — BIOS ACTIVATEP REFLECT_VERTICAL: EQU $1F6A ; REFLECT_VERTICAL $1F6A — BIOS REFLECT_VERTICAL REFLECT_HORIZONTAL: EQU $1F6D ; REFLECT_HORIZONTAL $1F6D — BIOS REFLECT_HORIZONTAL ROTATE_90: EQU $1F70 ; ROTATE_90 $1F70 — BIOS ROTATE_90 ENLARGE: EQU $1F73 ; ENLARGE $1F73 — BIOS ENLARGE CONTROLLER_SCAN: EQU $1F76 ; CONTROLLER_SCAN $1F76 — BIOS CONTROLLER_SCAN DECODER: EQU $1F79 ; DECODER $1F79 — BIOS DECODER (read controller or decode value) GAME_OPT: EQU $1F7C ; GAME_OPT $1F7C — BIOS GAME_OPT LOAD_ASCII: EQU $1F7F ; LOAD_ASCII $1F7F — BIOS LOAD_ASCII FILL_VRAM: EQU $1F82 ; FILL_VRAM $1F82 — BIOS FILL_VRAM MODE_1: EQU $1F85 ; MODE_1 $1F85 — BIOS MODE_1 UPDATE_SPINNER: EQU $1F88 ; UPDATE_SPINNER $1F88 — BIOS UPDATE_SPINNER INIT_TABLEP: EQU $1F8B ; INIT_TABLEP $1F8B — BIOS INIT_TABLEP PUT_VRAMP: EQU $1F91 ; PUT_VRAMP $1F91 — BIOS PUT_VRAMP INIT_SPR_ORDERP: EQU $1F94 ; INIT_SPR_ORDERP $1F94 — BIOS INIT_SPR_ORDERP INIT_TIMERP: EQU $1F9A ; INIT_TIMERP $1F9A — BIOS INIT_TIMERP REQUEST_SIGNALP: EQU $1FA0 ; REQUEST_SIGNALP $1FA0 — BIOS REQUEST_SIGNALP TEST_SIGNALP: EQU $1FA3 ; TEST_SIGNALP $1FA3 — BIOS TEST_SIGNALP WRITE_REGISTERP: EQU $1FA6 ; WRITE_REGISTERP $1FA6 — BIOS WRITE_REGISTERP INIT_WRITERP: EQU $1FAF ; INIT_WRITERP $1FAF — BIOS INIT_WRITERP SOUND_INITP: EQU $1FB2 ; SOUND_INITP $1FB2 — BIOS SOUND_INITP PLAY_ITP: EQU $1FB5 ; PLAY_ITP $1FB5 — BIOS PLAY_ITP INIT_TABLE: EQU $1FB8 ; INIT_TABLE $1FB8 — BIOS INIT_TABLE (fill VRAM page with pattern index) GET_VRAM: EQU $1FBB ; GET_VRAM $1FBB — BIOS GET_VRAM PUT_VRAM: EQU $1FBE ; PUT_VRAM $1FBE — BIOS PUT_VRAM INIT_SPR_NM_TBL: EQU $1FC1 ; INIT_SPR_NM_TBL $1FC1 — BIOS INIT_SPR_NM_TBL WR_SPR_NM_TBL: EQU $1FC4 ; WR_SPR_NM_TBL $1FC4 — BIOS WR_SPR_NM_TBL INIT_TIMER: EQU $1FC7 ; INIT_TIMER $1FC7 — BIOS INIT_TIMER FREE_SIGNAL: EQU $1FCA ; FREE_SIGNAL $1FCA — BIOS FREE_SIGNAL REQUEST_SIGNAL: EQU $1FCD ; REQUEST_SIGNAL $1FCD — BIOS REQUEST_SIGNAL TEST_SIGNAL: EQU $1FD0 ; TEST_SIGNAL $1FD0 — BIOS TEST_SIGNAL TIME_MGR: EQU $1FD3 ; TIME_MGR $1FD3 — BIOS TIME_MGR TURN_OFF_SOUND: EQU $1FD6 ; TURN_OFF_SOUND $1FD6 — BIOS TURN_OFF_SOUND WRITE_REGISTER: EQU $1FD9 ; WRITE_REGISTER $1FD9 — BIOS WRITE_REGISTER (BC=value+reg; OUT $BF) READ_REGISTER: EQU $1FDC ; READ_REGISTER $1FDC — BIOS READ_REGISTER (IN $BF -> VDP status) WRITE_VRAM: EQU $1FDF ; WRITE_VRAM $1FDF — BIOS WRITE_VRAM (HL=src, DE=vram addr, BC=count) READ_VRAM: EQU $1FE2 ; READ_VRAM $1FE2 — BIOS READ_VRAM INIT_WRITER: EQU $1FE5 ; INIT_WRITER $1FE5 — BIOS INIT_WRITER WRITER: EQU $1FE8 ; WRITER $1FE8 — BIOS WRITER (RST $10 string output driver) POLLER: EQU $1FEB ; POLLER $1FEB — BIOS POLLER (reads controllers into JOYSTICK_BUFFER each frame) SOUND_INIT: EQU $1FEE ; SOUND_INIT $1FEE — BIOS SOUND_INIT (HL=table, B=count) PLAY_IT: EQU $1FF1 ; PLAY_IT $1FF1 — BIOS PLAY_IT SOUND_MAN: EQU $1FF4 ; SOUND_MAN $1FF4 — BIOS SOUND_MAN (RST $28 — called each frame for music) ACTIVATE: EQU $1FF7 ; ACTIVATE $1FF7 — BIOS ACTIVATE PUTOBJ: EQU $1FFA ; PUTOBJ $1FFA — BIOS PUTOBJ RAND_GEN: EQU $1FFD ; RAND_GEN $1FFD — BIOS RAND_GEN (hardware random number generator) ; I/O PORT DEFINITIONS ********************** KEYBOARD_PORT: EQU $0080 ; KEYBOARD_PORT $80 — keypad/joystick mode-select port DATA_PORT: EQU $00BE ; DATA_PORT $BE — TMS9918A VDP data port (read/write VRAM) CTRL_PORT: EQU $00BF ; CTRL_PORT $BF — TMS9918A VDP control port (register + address writes) JOY_PORT: EQU $00C0 ; JOY_PORT $C0 — joystick direction mode-select port CONTROLLER_02: EQU $00F5 ; CONTROLLER_02 $F5 — player 2 controller read port CONTROLLER_01: EQU $00FC ; CONTROLLER_01 $FC — player 1 controller read port SOUND_PORT: EQU $00FF ; SOUND_PORT $FF — SN76489A sound chip write port ; RAM DEFINITIONS *************************** JOYSTICK_BUFFER: EQU $5A48 ; JOYSTICK_BUFFER $5A48 — BIOS POLLER writes controller state here WORK_BUFFER: EQU $7000 ; WORK_BUFFER $7000 — general RAM workspace ($7000-$7FFF) CONTROLLER_BUFFER: EQU $702B ; CONTROLLER_BUFFER $702B — processed controller input byte STACKTOP: EQU $73B9 ; STACKTOP $73B9 — top of stack FNAME "output\GATEWAY-TO-APSHAI-1984-NEW.ROM" CPU Z80 ORG $8000 ; ROM base address — ColecoVision cartridge space starts at $8000 DW $AA55 ; cart magic word — ColecoVision ROM recognition ($AA55) DB $CA, $70 ; cart header bytes — JP vector lo/hi to CART_ENTRY NMI handler DB $C4, $70 ; cart header continuation DB $00, $27 ; cart header — $0027 = tick-rate or interrupt count DW JOYSTICK_BUFFER ; BIOS POLLER output buffer pointer — JOYSTICK_BUFFER $5A48 DW START ; game start address — BIOS jumps to START after init DB $C3, $A8, $84, $C3, $CD, $85, $C3, $BD; cart header data bytes (RST/JP stubs) DB $85, $C3, $7A, $9A, $C3, $F1, $1F, $C9; cart header data bytes continuation DB $D8, $02, $ED, $4D, $2C ; cart header tail bytes ; ============================================================================= ; NMI HANDLER -- CART_ENTRY ($8021) ; Coleco cart header points $8021 as the NMI vector. On every VSYNC the BIOS ; jumps here. The handler is intentionally minimal: ; PUSH HL / LD HL,$708F / LD (HL),$80 / POP HL / RETN ; Sets bit 7 of RAM $708F as a "NMI occurred" flag, then returns to the ; interrupted code. All real game logic runs synchronously in the main loop ; (LOC_8036); each frame ends with RST $08 (frame-sync BIOS call) which waits ; for the next NMI before returning. ; ============================================================================= CART_ENTRY: ; CART_ENTRY: NMI handler at $8021 — sets $708F=$80 (NMI-occurred flag) then RETN PUSH HL ; save HL — only HL modified by this handler LD HL, $708F ; HL = pointer to NMI-occurred flag byte $708F LD (HL), $80 ; set bit 7 = NMI has fired (frame-sync signal for RST $08) POP HL ; restore HL RETN ; RETN — return from NMI interrupt to interrupted code SUB_802A: ; SUB_802A: JP (IX) indirect dispatch stub — called by BIOS with IX set to handler JP (IX) DB $33, $FF, $FE, $2F, $01, $05, $04, $31 DB $30, $32 ; ============================================================================= ; MAIN GAME LOOP -- LOC_8036 ($8036) ; Entry point after title / init (JP from LOC_8BFB). Loops back to LOC_8054 ; then LOC_805D each frame. Per-frame work: ; SUB_8557 reset VDP write address ; SUB_AE00 render dungeon map rows to VRAM ($9503 map data, 60 rows) ; init $7080/$706C/$7087/$7089/$708B/$7084 = 0 ; SUB_AD4F/AD5A/AD70 process pending monster/collision events ($7088/$7086/$7064) ; SOUND_WRITE_9AE5 queue ambient sound if $7066==0 ; copy $7070-$7072 -> $7075-$7073 (display stat mirrors) ; SUB_9E03 render stats HUD (STRENGTH/AGILITY/LUCK/HEALTH/LIVES) ; SUB_9C35/9D43 show equipment / stats screens when active ; RST $28 x4 sprite attribute table updates (tile sets 6/8/9/0A) ; SUB_9932/VDP_REG_8DE0 dungeon level select display when $7066!=0 ; LOC_80FD player scroll position: calc $7048/$704A, call SUB_9F15 ; LOC_814D action/combat inner loop (movement, SUB_AA3A enemy tick, ; RST $08 frame sync, SUB_9E51 tile collision/door check) ; loops back until $7066!=0 (room transition or death), then JP LOC_8036 ; ============================================================================= LOC_8036: ; LOC_8036: main game loop — entry from LOC_8BFB; per-frame work: VDP reset, map render, events, HUD, combat CALL SUB_8557 ; reset VDP write-address, reload tile pages, LOAD_ASCII CALL SUB_AE00 ; render 60 rows of dungeon map data from $9503 table to VRAM LD A, $01 LD ($7077), A ; RAM $7077 = 1: display layer enable flag LD ($7078), A ; RAM $7078 = 1: second display layer flag LD A, $03 LD ($7070), A ; RAM $7070 = 3: LUCK initial value (debug/reset) LD ($706F), A ; RAM $706F = 3: AGILITY initial value (debug/reset) LD ($706E), A ; RAM $706E = 3: STRENGTH initial value (debug/reset) LD A, $05 LD ($7072), A ; RAM $7072 = 5: LIVES initial value (debug/reset) LOC_8054: ; LOC_8054: cap difficulty counter $7058 at max $08 LD HL, $7058 ; HL = $7058 (agility/difficulty counter) LD A, (HL) CP $08 ; compare to $08 (max difficulty) JR NC, LOC_805D ; already at max — skip INC INC (HL) LOC_805D: ; LOC_805D: frame entry — reset SP, sync frame, process pending events LD SP, STACKTOP ; reset stack to STACKTOP each frame (guard against stack drift) CALL DELAY_LOOP_AE23 ; frame sync: wait NMI x5, then copy map row buffer from $AA2D to RAM $70C3 CALL SUB_918A ; SUB_918A: sprite attribute table write to VRAM XOR A LD B, A ; A = 0 = accumulator for flag clears LD ($7080), A ; RAM $7080 = 0: sprite-scroll update flag LD ($706C), A ; RAM $706C = 0: current action/movement code LD ($7087), A ; RAM $7087 = 0: misc state flag LD ($7089), A ; RAM $7089 = 0: misc state flag LD ($708B), A ; RAM $708B = 0: misc state flag LD ($7084), A ; RAM $7084 = 0: room/transition event flag LD HL, $7088 ; HL = $7088 — item-pickup event flag LD A, (HL) ; A = $7088 value LD (HL), B ; clear $7088 after reading OR A ; check if item-pickup event pending CALL NZ, SUB_AD4F ; process item-pickup: DEC $7079 by 8 (score/health bonus) LD HL, $7086 ; HL = $7086 — monster-hit event flag LD A, (HL) ; A = $7086 value LD (HL), B ; clear $7086 after reading OR A ; check if monster-hit event pending CALL NZ, SUB_AD5A ; process monster-hit: apply $7082 damage to HEALTH $7071/$706E LD HL, $7064 ; HL = $7064 — enemy-event pending flag LD A, (HL) ; A = $7064 value LD (HL), B ; clear $7064 after reading OR A ; check if enemy event pending CALL NZ, SUB_AD70 ; process enemy event: write $7060/$7062 enemy data to VDP via VDP_WRITE_8842 LD HL, $F099 ; HL = $F099 — display timer initial value LD ($705C), HL ; RAM $705C = display timer (counts down each frame) LD A, ($7066) ; A = $7066 (room-transition / event flag; 0=normal play) OR A ; test: if $7066==0 we are in active play CALL Z, SOUND_WRITE_9AE5 ; queue ambient sound when in active-play state ($7066==0) LD A, ($7070) ; A = $7070 (LUCK stat) LD ($7075), A ; RAM $7075 = copy of LUCK (display mirror) LD B, A LD A, ($706F) ; A = $706F (AGILITY stat) LD ($7074), A ; RAM $7074 = copy of AGILITY (display mirror) LD C, A LD A, ($706E) ; A = $706E (STRENGTH stat) LD ($7073), A ; RAM $7073 = copy of STRENGTH (display mirror) ADD A, B ; A = STRENGTH + LUCK ADD A, C ; A += AGILITY -> HEALTH = STR+AGI+LCK LD ($7071), A ; RAM $7071 = computed HEALTH value LD ($7076), A ; RAM $7076 = copy of HEALTH (display mirror) CALL SUB_9E03 ; render all 5 stats (STR/AGI/LCK/HEALTH/LIVES) to VRAM HUD area CALL SUB_9C35 ; equipment/status screen update (show when active) CALL SUB_9D43 ; characteristics screen update (show when active) LD A, ($705E) ; A = $705E (inventory item count) OR A ; check if any items in inventory JR Z, LOC_80D3 ; no items — skip inventory display calls CALL SUB_9C35 ; show equipment screen CALL SUB_9D14 ; render inventory item list LOC_80D3: ; LOC_80D3: update sprite attribute table sets for 4 tile planes (B=6,8,9,$0A) LD B, $06 ; B = $06 — tile plane 6 sprite update RST $28 ; RST $28 = SOUND_MAN BIOS — update sprite attr table for plane B LD B, $08 ; B = $08 — tile plane 8 RST $28 ; RST $28 — update sprite plane 8 LD B, $09 ; B = $09 — tile plane 9 RST $28 ; RST $28 — update sprite plane 9 LD B, $0A ; B = $0A — tile plane $0A RST $28 ; RST $28 — update sprite plane $0A LD A, ($7066) ; A = $7066 (room-transition flag) OR A ; check if in room-transition state JR Z, LOC_80ED ; not transitioning — go to standard scroll path CALL SUB_9C35 ; show equipment screen during transition CALL DELAY_LOOP_922C ; DELAY_LOOP_922C: wait loop during level transition JR LOC_80FD ; skip scroll path when in transition LOC_80ED: ; LOC_80ED: dungeon level display — FILL_VRAM, show level select, init VDP for dungeon LD HL, $3C00 ; HL = $3C00 — level display VRAM address LD DE, $0130 ; DE = $0130 — byte count for level display clear XOR A ; A = 0 — fill with blank CALL FILL_VRAM ; FILL_VRAM: clear dungeon display area CALL SUB_9932 ; show dungeon level select screen (reads $7057, display level number) CALL VDP_REG_8DE0 ; init VDP registers for dungeon display mode (tile pages etc.) LOC_80FD: ; LOC_80FD: scroll position update — copy player world coords to viewport, calc offsets LD HL, ($704C) ; HL = $704C (player X world tile position) LD DE, ($704E) ; DE = $704E (player Y world tile position) LD ($7048), HL ; RAM $7048 = player X copied to viewport X LD ($704A), DE ; RAM $704A = player Y copied to viewport Y ADD HL, DE ; HL = player X + player Y (combined position for scroll calc) SRL H ; SRL H: divide by 2 (high byte) SRL L ; SRL L: divide by 2 (low byte) — get centre tile position CALL SUB_9F15 ; calc scroll offsets $7050/$70CA/$7054 from combined tile position LD A, $03 ; A = 3 — mode/data byte for VDP_DATA_8702 LD DE, $3D44 ; DE = $3D44 — VRAM address for player marker tile CALL VDP_DATA_8702 ; write player position marker tile to VRAM XOR A ; A = 0 — clear room-transition flag LD ($7066), A ; RAM $7066 = 0: clear room-transition (entering game tick loop) LD DE, $3D54 ; DE = $3D54 — VRAM address for another marker CALL VDP_DATA_8702 ; write second marker LD DE, $3D40 ; DE = $3D40 CALL VDP_DATA_8702 ; write third marker LD A, $08 ; A = $08 LD DE, $3D50 ; DE = $3D50 CALL VDP_DATA_8702 ; write fourth marker LD HL, $0F00 ; HL = $0F00 — initial scroll-buffer state LD ($70CC), HL ; RAM $70CC = scroll VRAM pointer (initial value) LD ($70DC), HL ; RAM $70DC = secondary scroll pointer CALL VDP_WRITE_9254 ; VDP_WRITE_9254: write sprite pattern + attribute table to VRAM from RAM buffers CALL SUB_9B93 ; clear HUD VRAM area, set display mode via SUB_85A8 RST $08 ; RST $08 x3: wait 3 VBL frames for display to settle RST $08 RST $08 LD C, $0C ; C = $0C — sprite display mode parameter CALL SUB_85A8 ; SUB_85A8: set sprite mode + enable VDP display (WRITE_REGISTER $07/$01E2) CALL SUB_89DC ; SUB_89DC: write tile render buffer $70DF and sprite attr buffer $72DF to VRAM LOC_814D: ; LOC_814D: action/combat inner loop — runs each frame until room transition CALL SUB_8534 ; player input + action dispatch (random advance + combat result) CALL SUB_AA3A ; enemy/object tick: AI movement, animation, collision detection RST $08 ; RST $08: wait for next VBL (NMI frame sync) CALL SUB_9E51 ; tile collision: scan for door/exit tile, set $7066 to trigger room transition LD A, ($7066) ; A = $7066 (room-transition flag) OR A ; test: non-zero means transition triggered JR NZ, LOC_814D ; loop back to action frame if still in active play CALL VDP_DATA_8255 ; VDP_DATA_8255: door/exit tile check — read $7056 tile code, detect exit tile CALL SUB_834B ; SUB_834B: level-segment advance check (count active enemies) CALL SOUND_WRITE_81C1 ; sound trigger: DECODER read + dispatch sound via JP(IX) table CALL SUB_816B ; SUB_816B: sprite-scroll update gate (bit 3 of $7080) JR LOC_814D ; JR back to LOC_814D: re-enter combat loop SUB_816B: ; SUB_816B: sprite-scroll update gate — RES/SET bit 3 of $7080 CALL SUB_8512 ; read input via SUB_8512 (DECODER: button check) LD HL, $7080 ; HL = $7080 — sprite-scroll flags JR NZ, LOC_8176 ; no button: clear bit 3 (scroll active) RES 3, (HL) RET ; return if no button input LOC_8176: ; LOC_8176: button held — check/set bit 3 of $7080 (scroll already active) BIT 3, (HL) ; test: bit 3 already set? RET NZ ; already active — return (debounce) SET 3, (HL) ; set bit 3: mark scroll as active LD A, ($7084) ; A = $7084 (room/transition event flag) OR A ; check if room event active RET NZ ; room event active — return LD HL, $706C ; HL = $706C (current action code) LD A, (HL) ; A = action code OR A ; test: action code zero? RET Z ; no action — return CP $0A ; CP $0A — min pickup-action threshold JR C, LOC_81A1 CP $28 ; CP $28 — max pickup-action threshold JR NC, LOC_81A1 SUB $0A ; subtract $0A to get item slot PUSH AF ; push item slot LD (HL), $00 ; clear action code CALL SUB_9C04 ; call SUB_9C04 (screen transition cleanup) POP AF ; pop item slot LD DE, $3D30 ; DE = $3D30 — item display VRAM address CALL SUB_870A ; SUB_870A: look up and display item tile CALL SUB_81A4 ; SUB_81A4: increment item display index LD A, L LOC_81A1: ; LOC_81A1: JP LOC_A62F — enemy/object interaction handler JP LOC_A62F SUB_81A4: ; SUB_81A4: cycle item display — iterate slots, display each, decrement count PUSH HL LD HL, $705E ; RAM $705E LOC_81A8: INC A CP (HL) JR NC, LOC_81BE PUSH HL LD DE, $3D30 CALL SUB_870A DEC A LD DE, $3D30 CALL LOC_8714 POP HL INC A JR LOC_81A8 LOC_81BE: DEC (HL) POP HL RET SOUND_WRITE_81C1: ; SOUND_WRITE_81C1: fire/event sound trigger — DECODER read + sound dispatch via table LD HL, $0001 ; HL = $0001 — read player 1 controller CALL DECODER ; DECODER BIOS: HL=$0001 -> read player 1 joystick/button state -> result in HL LD A, L ; A = L (button/direction byte) LD HL, $706A ; HL = $706A (last controller state cache) CP (HL) ; compare to cached value — skip if same RET Z ; same as last frame — return (no change) LD (HL), A ; update cached controller state CP $0A ; check if button pressed (A >= $0A means button or direction change) RET NC ; no button press — return LD HL, $706D ; HL = $706D — sound effect timer LD (HL), $1E ; load $1E (30) into sound timer — debounce for next sound trigger LD DE, $802C ; DE = $802C — sound dispatch table base address CALL SUB_86DD ; table lookup: add A to DE -> (DE) = target address for this button code LD A, (DE) ; A = (DE): load dispatch byte LD HL, $706C ; HL = $706C (current action code register) CP $FF ; compare: $FF means no more items (table end) JR Z, LOC_81F1 ; no more items — branch to LOC_81F1 (handle empty case) CP $FE ; compare: $FE means drop item JR Z, LOC_8220 ; drop item — branch to LOC_8220 LOC_81E8: ; LOC_81E8: store action code in $706C LD (HL), A LOC_81E9: ; LOC_81E9: call SUB_9C04 (screen transition), then dispatch via table SUB_8600 PUSH AF CALL SUB_9C04 POP AF JP SUB_8600 LOC_81F1: LD A, (HL) CP $34 JR C, LOC_81FB INC A CP $37 JR C, LOC_81FF LOC_81FB: LD A, $34 JR LOC_81E8 LOC_81FF: CP $35 EX AF, AF' LD A, ($7081) ; RAM $7081 BIT 3, A JR Z, LOC_81FB EX AF, AF' JR NZ, LOC_8216 LD A, ($707C) ; RAM $707C OR A JR Z, LOC_8216 LD A, $35 JR LOC_81E8 LOC_8216: LD A, ($707D) ; RAM $707D OR A JR Z, LOC_81FB LD A, $36 JR LOC_81E8 LOC_8220: LD A, (HL) SUB $0A JR C, LOC_8229 CP $1E JR C, LOC_8243 LOC_8229: LD A, ($705E) ; RAM $705E DEC A JP P, LOC_8247 LD (HL), $00 CALL SUB_9C04 LD HL, $823A RST $10 RET DB $6E, $6F, $20, $69, $74, $65, $6D, $73 ; "no items" DB $FC LOC_8243: DEC A JP M, LOC_8229 LOC_8247: ADD A, $0A LD (HL), A SUB $0A LD DE, $3D30 CALL SUB_870A LD A, L JR LOC_81E9 VDP_DATA_8255: ; VDP_DATA_8255: door/exit tile detector — reads $7056 (current tile under player) LD A, ($7056) ; A = $7056 (tile code under player position) AND $BE ; mask: keep bits 1-7 (strip bit 0) CP $90 ; compare to $90 (first door/exit tile code) RET C ; below $90 — no door/exit here; return CP $9C ; compare to $9C (special door tile) RET Z ; exactly $9C — door tile; return (handled elsewhere) LD BC, ($7052) ; BC = $7052 (tile data word) RES 0, C ; clear bit 0 of C (align to even tile pair) CP $B8 ; compare to $B8 (passage tile code) JR Z, LOC_82D1 ; exactly $B8 — passage tile; skip to LOC_82D1 LD A, $1F ; A = $1F — tile count/scan parameter LOC_826C: LD DE, $3C30 CALL VDP_DATA_8720 OR A SBC HL, BC JR Z, LOC_827B DEC A RET M JR LOC_826C LOC_827B: LD E, A LD A, ($705E) ; RAM $705E CP $10 LD A, E JR C, LOC_8291 CALL SOUND_WRITE_9C09 LD A, $66 CALL SUB_9FA7 LD A, $67 JP SUB_9FA7 LOC_8291: LD DE, $3C30 CALL VDP_DATA_8730 LD DE, $3C70 CALL SUB_870A DB $EB LD HL, $705E ; RAM $705E LD A, (HL) INC (HL) DB $EB LD DE, $3D30 CALL LOC_8714 LD A, L PUSH BC PUSH AF CALL SOUND_WRITE_9C09 POP AF CALL SUB_8600 LD A, ($706C) ; RAM $706C OR A CALL Z, SUB_9C04 LD B, $08 RST $28 LD B, $01 LOC_82C0: RST $28 POP HL LD A, $8B LD ($7056), A ; RAM $7056 CALL VDP_WRITE_8842 INC L CALL VDP_WRITE_8842 JP LOC_89B3 LOC_82D1: LD A, $0F LOC_82D3: LD DE, $3C90 CALL VDP_DATA_8720 OR A SBC HL, BC JR Z, LOC_82E2 DEC A RET M JR LOC_82D3 LOC_82E2: LD DE, $3C90 CALL VDP_DATA_8730 PUSH BC LD DE, $3CB0 CALL SUB_870A LD H, L LD DE, $3CC0 CALL SUB_870A LD DE, $705F ; RAM $705F LD A, (DE) ADD A, L LD (DE), A PUSH HL LD A, L CALL SUB_8325 CALL SOUND_WRITE_9C09 POP HL PUSH HL LD A, L ADD A, $57 CALL SUB_9FA7 POP AF ADD A, $5E CALL SUB_9FA7 LD B, $08 RST $28 LD B, $03 JR LOC_82C0 DB $00, $00, $10, $00, $25, $00, $50, $00 DB $00, $01, $00, $10 SUB_8325: ; SUB_8325: BCD score accumulation — DEC A, RLCA (slot*2 index), look up score table DEC A ; DEC A: convert 1-based slot to 0-based RLCA ; RLCA: multiply by 2 (word-table index) LD DE, $8319 ; DE = $8319 — score-per-item table base CALL SUB_86DD ; SUB_86DD: add A to DE (index into score table) DB $EB LD E, (HL) INC HL LD D, (HL) LD A, ($7058) ; A = $7058 (agility/difficulty level counter) LD B, A ; B = loop count = difficulty level LOC_8335: ; LOC_8335: BCD add loop — add score word (E,D) to 3-byte BCD score at $7059-$705B LD HL, $7059 ; HL = $7059 — BCD score low byte LD A, (HL) ; A = score low byte ADD A, E ; ADD A, E: add score low byte DAA ; DAA: decimal-adjust for BCD LD (HL), A ; store BCD result back INC HL ; move to mid byte LD A, (HL) ; A = score mid byte ADC A, D ; ADC A, D: add score mid byte + carry from low DAA ; DAA: decimal-adjust mid byte LD (HL), A ; store mid byte INC HL ; advance to high byte LD A, (HL) ; A = score high byte ADC A, $00 ; ADC A, $00: propagate carry to high byte LD (HL), A ; store high byte (no DAA — hundreds digit) DJNZ LOC_8335 ; DJNZ: repeat B times (B = difficulty level) JP SUB_9BA2 ; JP SUB_9BA2: display updated score on HUD SUB_834B: ; SUB_834B: level-segment advance check — count active enemies at $70D1/$70D5/$70D9 LD B, $01 ; B = 1 (initial enemy count) LD A, ($70D1) ; A = $70D1 (enemy 1 alive flag) OR A JR Z, LOC_8384 ; enemy 1 dead — check done INC B ; B = 2 (enemy 1 alive) LD A, ($70D5) ; A = $70D5 (enemy 2 alive flag) OR A JR Z, LOC_8384 ; enemy 2 dead — check done INC B ; B = 3 (enemy 2 alive) LD A, ($70D9) ; A = $70D9 (enemy 3 alive flag) OR A JR Z, LOC_8384 ; enemy 3 dead — check with 1 enemy left LD B, $01 ; B = 1: only one enemy alive LD A, ($70CE) ; A = $70CE (enemy 1 Y position) CP $D8 ; check if $D8 (off-screen sentinel) JR Z, LOC_8379 ; enemy 1 off-screen — goto LOC_8379 INC B ; B = 2 LD A, ($70D2) ; A = $70D2 (enemy 2 Y position) CP $D8 ; check if $D8 (off-screen) JR Z, LOC_8379 ; enemy 2 off-screen — goto LOC_8379 INC B ; B = 3 LD A, ($70D6) ; A = $70D6 (enemy 3 Y position) CP $D8 ; all active/on-screen — return NZ (segment not clear) RET NZ LOC_8379: CALL SUB_9159 RET NZ LD C, A CALL DELAY_LOOP_A8EF LD A, C JR LOC_8389 LOC_8384: CALL SUB_9159 RET NZ LD C, A LOC_8389: LD DE, $3CD0 CALL SUB_870A PUSH HL LD A, B LD DE, $3D58 CALL LOC_8714 LD HL, BOOT_UP LD A, C LD DE, $3CF0 CALL VDP_DATA_8730 LD A, B LD DE, $3D78 CALL LOC_8714 INC L LD DE, $3D70 CALL LOC_8714 LD DE, $3D48 CALL LOC_8714 LD DE, $3D4C CALL LOC_8714 LD DE, $3D40 CALL LOC_8714 LD L, $0F LD DE, $3D74 CALL LOC_8714 LD HL, ($7048) ; RAM $7048 LD DE, ($704A) ; RAM $704A ADD HL, DE SRL H SRL L DB $EB LD HL, $7050 ; RAM $7050 LD A, E SUB (HL) JR Z, LOC_83DF JR NC, LOC_83E1 LOC_83DF: LD A, $01 LOC_83E1: CP $1E JR C, LOC_83E7 LD A, $1E LOC_83E7: LD E, A LD HL, $7051 ; RAM $7051 LD A, D SUB (HL) JR Z, LOC_83F1 JR NC, LOC_83F3 LOC_83F1: LD A, $01 LOC_83F3: CP $11 JR C, LOC_83F9 LD A, $11 LOC_83F9: LD D, A DB $EB LD A, B CALL SUB_A8E3 POP HL LD H, $00 PUSH HL LD DE, $957C ADD HL, DE LD L, (HL) LD A, B LD DE, $3D5C CALL LOC_8714 LD A, L AND $07 LD L, A LD DE, $3D44 LD A, B CALL LOC_8714 POP HL ADD HL, HL ADD HL, HL ADD HL, HL LD DE, $959C ADD HL, DE PUSH HL POP IY LD A, B LD L, (IY+3) LD DE, $3D60 CALL LOC_8714 LD L, (IY+4) LD DE, $3D64 CALL LOC_8714 LD L, (IY+5) LD DE, $3D68 CALL LOC_8714 LD L, (IY+7) LD DE, $3D6C CALL LOC_8714 CALL SUB_AA17 INC HL INC HL INC HL LD A, (IY+6) LD (HL), A LD A, B LD L, (IY+2) LD DE, $3D54 CALL LOC_8714 LD DE, $9463 LD H, $00 ADD HL, DE LD A, (HL) DEC HL SUB (HL) LD L, A LD A, B LD DE, $3D50 CALL LOC_8714 CALL SUB_AD90 CALL SOUND_WRITE_9C13 LD A, (IY+0) CALL SUB_9FA7 LD A, (IY+1) CALL SUB_9FA7 LD B, $09 RST $28 LD B, $24 RST $28 RET ; ============================================================================= ; BOOT ENTRY -- START ($95F3 equivalent: here at $8052 equivalent) ; ColecoVision BIOS jumps here after power-on handshake. ; LD HL,WORK_BUFFER / LD DE,$7001 / LD (HL),L / LD BC,$0FFF / LDIR ; -> zero-fills RAM $7000-$7FFF (all general workspace) ; CALL SOUND_INIT ($89FA sound table) ; CALL READ_REGISTER read VDP status to clear any pending interrupt ; LD BC,$01A2 / CALL WRITE_REGISTER set VDP register 1 = $A2 ; (enable display, sprites 8x8, 16 KB VRAM) ; JP LOC_8BFB -> title screen + game option init ; ============================================================================= START: ; START: BIOS entry — clear RAM $7000-$7FFF, SOUND_INIT, VDP enable, JP LOC_8BFB LD HL, WORK_BUFFER ; HL = WORK_BUFFER ($7000) — RAM workspace start LD DE, $7001 ; DE = $7001 — destination (RAM+1) LD (HL), L ; LD (HL),L: zero the first byte ($7000 = $00) LD BC, $0FFF ; BC = $0FFF — 4095 bytes to fill LDIR ; LDIR: fill $7000-$7FFF with $00 (clear all game state) LD B, $05 ; B = 5 — number of sound table entries LD HL, $89FA ; HL = $89FA — sound init table address CALL SOUND_INIT ; BIOS SOUND_INIT: load 5 sound channels from table at $89FA CALL READ_REGISTER ; BIOS READ_REGISTER: read VDP status to clear any pending interrupt LD BC, $01A2 ; BC = $01A2 — VDP register 1 value $A2 (enable display, 8x8 sprites, 16KB VRAM) CALL WRITE_REGISTER ; BIOS WRITE_REGISTER: init VDP register 1 JP LOC_8BFB ; JP LOC_8BFB: enter title screen / game init sequence DB $21, $8F, $70, $CB, $26, $30, $FC, $CD DB $DC, $1F, $3A, $C3, $70, $CD, $C4, $1F DB $21, $80, $70, $CB, $46, $CB, $86, $C4 DB $DC, $89, $CD, $E2, $84, $3A, $80, $70 DB $E6, $06, $20, $10, $2A, $C6, $70, $3A DB $C8, $70, $22, $C7, $70, $21, $C5, $70 DB $46, $77, $23, $70, $CD, $F4, $1F, $C3 DB $61, $1F, $21, $6B, $70, $7E, $B7, $C8 DB $E6, $3F, $28, $06, $35, $3D, $C0, $C3 DB $E9, $91, $CB, $7E, $28, $07, $CB, $BE DB $CB, $D6, $C3, $F8, $91, $CB, $B6, $CB DB $D6, $C3, $FD, $91 SUB_8504: ; SUB_8504: wait-for-fire-button — RST $08 loop until button pressed, wait release RST $08 ; RST $08: wait for NMI frame sync (BIOS frame-sync call) CALL SUB_8512 ; read controller input (DECODER via SUB_8512) JR NZ, SUB_8504 ; JR NZ: button pressed — wait for release RST $08 ; RST $08: one more frame sync LOC_850B: ; LOC_850B: wait for button press — RST $08 loop until button down RST $08 ; RST $08: wait for NMI CALL SUB_8512 ; read controller JR Z, LOC_850B ; JR Z: no button yet — keep waiting RET ; button pressed — return SUB_8512: ; SUB_8512: read controller via BIOS DECODER — return NZ if button/direction active LD HL, BOOT_UP ; HL = BOOT_UP ($0000) — read player 1 joystick (DECODER arg) CALL DECODER ; BIOS DECODER: read player 1 direction byte -> HL PUSH HL ; PUSH HL (save direction byte) LD HL, $0001 ; HL = $0001 — read player 1 button CALL DECODER ; BIOS DECODER: read player 1 button byte -> HL POP AF ; POP AF — pop direction byte OR H ; OR H: combine direction high byte with button BIT 6, A ; BIT 6,A: test fire button bit 6 RET ; RET: ZF=0 if button pressed DELAY_LOOP_8524: ; DELAY_LOOP_8524: 8-bit multiply HL = HL * DE with 8-bit shift (used for position calc) LD HL, BOOT_UP ; HL = BOOT_UP ($0000) — accumulator zeroed LD B, $08 ; B = $08 — 8 shift iterations LOC_8529: ; LOC_8529: RRCA on A (multiplier byte), accumulate HL RRCA ; RRCA: shift multiplier right, carry set if bit was 1 JR NC, LOC_852D ; JR NC: bit was 0 — skip add ADD HL, DE ; ADD HL,DE: add DE to accumulator when bit set LOC_852D: ; LOC_852D: RR H/RR L — shift accumulator right (divide product by 2) RR H ; RR H: rotate right high byte through carry RR L ; RR L: rotate right low byte through carry DJNZ LOC_8529 ; DJNZ: repeat for all 8 bits RET SUB_8534: ; SUB_8534: advance LCG random-number sequence at $73C8 — return mixed result in A PUSH DE ; PUSH DE: save DE LD HL, ($73C8) ; HL = $73C8 (current RNG state word) LD D, H ; D = H (copy for multiply) LD E, L ; E = L ADD HL, HL ; ADD HL,HL: HL *= 2 ADD HL, DE ; ADD HL,DE: HL *= 3 (original value added back) DB $EB LD H, L ; LD H,L / XOR A / LD L,A: scramble high byte into low, zero high XOR A ; XOR A LD L, A ; LD L,A SBC HL, DE ; SBC HL,DE: subtract previous value INC HL ; INC HL LD ($73C8), HL ; LD ($73C8),HL: store new RNG state ADC A, H ; ADC A,H: mix H into A ADD A, L ; ADD A,L: mix L into A (result byte) POP DE ; POP DE: restore DE RET SUB_854A: ; SUB_854A: multiply A * DE (8x16) using DELAY_LOOP_8524 — result in HL high byte EXX ; EXX: swap to alternate registers LD D, A ; D = A: move multiplier to D CALL SUB_8534 ; call RNG advance (SUB_8534) LD E, $00 ; E = $00 CALL DELAY_LOOP_8524 ; DELAY_LOOP_8524: multiply A by DE (8-bit × 16-bit shift) LD A, H ; A = H (result high byte) EXX ; EXX: restore main registers RET SUB_8557: ; SUB_8557: VDP write-address reset — RST $08, WRITE_REGISTER, clear VRAM pages, LOAD_ASCII RST $08 ; RST $08: wait for NMI frame sync LD BC, $01A2 ; BC = $01A2 — VDP register 1: enable display, 8x8 sprites, 16KB CALL WRITE_REGISTER ; BIOS WRITE_REGISTER: set VDP mode CALL DELAY_LOOP_AE23 ; DELAY_LOOP_AE23: frame sync + copy map row buffer CALL MODE_1 ; BIOS MODE_1: set TMS9918A mode 2 (graphics II) XOR A ; A = 0 — fill value LD HL, $2000 ; HL = $2000 — VRAM pattern table start LD D, H ; D = H, E = L: DE = $2000 LD E, L CALL FILL_VRAM ; BIOS FILL_VRAM: clear $2000-$27FF (pattern table) LD HL, $2800 ; HL = $2800 LD A, $02 ; A = $02 — tile page 2 CALL INIT_TABLE ; BIOS INIT_TABLE: initialise pattern table page 2 LD HL, $2C00 ; HL = $2C00 LD A, $04 ; A = $04 — tile page 4 CALL INIT_TABLE ; BIOS INIT_TABLE: initialise page 4 LD HL, $2000 ; HL = $2000 LD A, $03 ; A = $03 — tile page 3 CALL INIT_TABLE ; BIOS INIT_TABLE: initialise page 3 LD HL, $2B00 ; HL = $2B00 XOR A ; A = 0 CALL INIT_TABLE ; BIOS INIT_TABLE: initialise page 0 at $2B00 LD HL, $3000 ; HL = $3000 LD A, $01 ; A = $01 — tile page 1 CALL INIT_TABLE ; BIOS INIT_TABLE: initialise page 1 CALL LOAD_ASCII ; BIOS LOAD_ASCII: load ASCII character patterns to tile page LD HL, ($73FA) ; HL = $73FA (VRAM tile page base pointer) LD A, $F0 ; A = $F0 — fill value for unused tile row LD DE, $0020 ; DE = $0020 — 32 bytes CALL FILL_VRAM ; BIOS FILL_VRAM: fill one tile row with $F0 LD BC, $01A2 ; BC = $01A2 — VDP register 1 value again JP WRITE_REGISTER ; JP BIOS WRITE_REGISTER: re-apply VDP mode (tail call) SUB_85A8: ; SUB_85A8: set sprite mode and enable VDP display — B=7/$07, then BC=$01E2 LD B, $07 ; B = $07 — VDP register 7 selector CALL WRITE_REGISTER ; BIOS WRITE_REGISTER: set VDP register 7 with C value (sprite mode/colour) RST $08 ; RST $08: wait for NMI LD BC, $01E2 ; BC = $01E2 — VDP register 1: enable display + enable sprites JP WRITE_REGISTER ; JP BIOS WRITE_REGISTER: enable display (tail call) VDP_REG_85B4: ; VDP_REG_85B4: write VDP address register — OUT $BF with E then D|$40 (VRAM addr) LD A, E ; A = E (low byte of VRAM address) OUT ($BF), A ; OUT $BF: write low address byte to VDP control port LD A, D ; A = D (high byte) OR $40 ; OR $40: set bit 6 -> VRAM write mode OUT ($BF), A ; OUT $BF: write high byte | $40 to VDP control port RET DB $F5, $C5, $D5, $E5, $FD, $E5, $CD, $BE DB $1F, $FD, $E1, $E1, $D1, $C1, $F1, $C9 DB $E5, $7E, $23, $FE, $F8, $30, $04, $D3 DB $BE, $18, $F6, $C6, $03, $38, $0A, $3C DB $28, $05, $3C, $28, $12, $18, $EA, $E1 DB $C9, $4E, $23, $47, $EB, $2A, $F6, $73 DB $09, $EB, $CD, $B4, $85, $18, $DA, $01 DB $CE, $85, $C5, $4E, $23, $46, $23, $C5 DB $E3, $18, $CE SUB_8600: ; SUB_8600: item/action dispatch — RLCA x2 (×4), look up handler in table $9388 RLCA ; RLCA: shift A left RLCA ; RLCA: A *= 4 (word pair index) LD DE, $9388 ; DE = $9388 — action dispatch table CALL SUB_86DD ; SUB_86DD: add A to DE (index into dispatch table) LD A, (DE) ; A = (DE): load first handler address byte INC DE ; INC DE: advance to second byte PUSH DE ; PUSH DE CALL SUB_9FA7 ; SUB_9FA7: execute first handler (call with A) POP DE ; POP DE: restore second handler pointer LD A, (DE) ; A = (DE): load second handler address byte JP SUB_9FA7 ; JP SUB_9FA7: execute second handler (tail call) SUB_8613: ; SUB_8613: two-object tile collision check — compare positions at $7040/$7041 area LD A, B ; A = B: move first-object index CALL SUB_AA17 ; SUB_AA17: look up tile data for object B in position table LD A, (HL) ; A = (HL): load tile code CP $D8 ; CP $D8: check for off-screen sentinel RET Z ; off-screen — return (no collision) LD ($7040), A ; RAM $7040 = tile X for object A INC HL ; INC HL LD A, (HL) ; A = (HL): tile Y value LD ($7042), A ; RAM $7042 = tile Y for object A INC HL ; INC HL LD A, (HL) ; A = (HL): tile attribute LD ($7044), A ; RAM $7044 = attribute for object A LD A, C ; A = C: second object index CALL SUB_AA17 ; SUB_AA17: look up tile data for object C LD A, (HL) ; A = (HL): tile code for object B CP $D8 ; CP $D8: off-screen? RET Z ; off-screen — return LD ($7041), A ; RAM $7041 = tile X for object B INC HL LD A, (HL) LD ($7043), A ; RAM $7043 INC HL LD A, (HL) LD ($7045), A ; RAM $7045 LD HL, ($7042) ; RAM $7042 LD A, L SUB H JR NC, LOC_8658 NEG LD HL, ($7040) ; RAM $7040 LD E, L LD L, H LD H, E LD ($7040), HL ; RAM $7040 LD HL, ($7044) ; RAM $7044 LD E, L LD L, H LD H, E LD ($7044), HL ; RAM $7044 LOC_8658: CP $08 JP NC, LOC_86DB LD ($7046), A ; RAM $7046 LD A, ($7044) ; RAM $7044 RRCA LD HL, $9503 CALL SUB_AA1C LD E, (HL) INC HL LD D, (HL) INC HL LD A, (HL) SUB E LD ($7042), DE ; RAM $7042 LD ($7044), A ; RAM $7044 LD A, ($7045) ; RAM $7045 RRCA LD HL, $9503 CALL SUB_AA1C LD E, (HL) INC HL LD D, (HL) INC HL LD A, (HL) SUB E LD HL, ($7040) ; RAM $7040 LD ($7040), DE ; RAM $7040 LD ($7045), A ; RAM $7045 LD A, L SUB H JR NC, LOC_86A6 NEG LD HL, ($7042) ; RAM $7042 LD E, A LD D, $00 ADD HL, DE LD ($7042), HL ; RAM $7042 LD HL, $7044 ; RAM $7044 JR LOC_86B0 LOC_86A6: LD L, A LD H, $00 ADD HL, DE LD ($7040), HL ; RAM $7040 LD HL, $7045 ; RAM $7045 LOC_86B0: LD C, A LD A, (HL) SUB C JR C, LOC_86DB JR Z, LOC_86DB LD (HL), A LD HL, ($7044) ; RAM $7044 LD A, L CP H JR C, LOC_86C0 LD A, H LOC_86C0: LD B, A LD HL, ($7042) ; RAM $7042 LD DE, ($7040) ; RAM $7040 LD A, ($7046) ; RAM $7046 LD C, A INC C LOC_86CD: PUSH BC LD A, (DE) INC DE LD B, C LOC_86D1: ADD A, A DJNZ LOC_86D1 RRA AND (HL) POP BC RET NZ INC HL DJNZ LOC_86CD LOC_86DB: XOR A RET SUB_86DD: ; SUB_86DD: 16-bit table offset — add A to DE as 8-bit offset (carry propagates to D) ADD A, E ; ADD A,E: A + E -> low byte of new offset LD E, A ; LD E,A: store result RET NC ; RET NC: no carry — done INC D ; INC D: carry -> increment high byte RET VDP_REG_86E2: ; VDP_REG_86E2: read VDP data at address HL, return AND $BF (clear bit 6) CALL VDP_REG_86E8 ; call VDP_REG_86E8 (set address and read) AND $BF ; AND $BF: clear bit 6 of read result RET VDP_REG_86E8: ; VDP_REG_86E8: set VRAM read address HL and read one byte into A LD A, H ; A = H AND $01 ; AND $01: keep only bit 0 (bit 14 of 14-bit VRAM addr) RRCA ; RRCA: bit 0 -> bit 7 OR L ; OR L: combine with low address byte OUT ($BF), A ; OUT $BF: write low VRAM address byte to VDP control LD A, H ; A = H RRA ; RRA: shift H right through carry OUT ($BF), A ; OUT $BF: write high VRAM address byte (read mode = no $40 set) JR LOC_86FD VDP_WRITE_86F5: LD A, E OUT ($BF), A ; CTRL_PORT - write VDP register LD A, D OUT ($BF), A ; CTRL_PORT - write VDP register INC DE DEC DE LOC_86FD: INC DE DEC DE IN A, ($BE) ; DATA_PORT - read VRAM RET VDP_DATA_8702: ; VDP_DATA_8702: set VRAM write address DE then write byte A to DATA_PORT $BE PUSH AF ; PUSH AF: save byte to write CALL VDP_REG_85B4 ; VDP_REG_85B4: set VRAM write address to DE POP AF ; POP AF: restore write byte OUT ($BE), A ; OUT $BE: write byte to VDP data port RET SUB_870A: ; SUB_870A: indexed VRAM read — add A to DE (via SUB_86DD), set read addr, return tile byte PUSH AF ; PUSH AF CALL SUB_86DD ; SUB_86DD: DE += A (index into tile data) CALL VDP_WRITE_86F5 ; VDP_WRITE_86F5: set VRAM address DE for read, perform dummy IN LD L, A ; L = A (return tile index value) POP AF ; POP AF RET LOC_8714: PUSH AF CALL SUB_86DD CALL VDP_REG_85B4 LD A, L OUT ($BE), A ; DATA_PORT - write VRAM POP AF RET VDP_DATA_8720: LD H, A RLCA CALL SUB_86DD CALL VDP_WRITE_86F5 LD L, A LD D, H NOP IN A, ($BE) ; DATA_PORT - read VRAM LD H, A LD A, D RET VDP_DATA_8730: PUSH AF RLCA CALL SUB_86DD CALL VDP_REG_85B4 LD A, L OUT ($BE), A ; DATA_PORT - write VRAM PUSH HL POP AF NOP OUT ($BE), A ; DATA_PORT - write VRAM POP AF RET VDP_DATA_8742: CALL VDP_WRITE_8842 LD C, A LD A, E SUB L LD B, A LD A, C RET Z LOC_874B: OUT ($BE), A ; DATA_PORT - write VRAM INC BC DEC BC DJNZ LOC_874B RET DELAY_LOOP_8752: PUSH HL LD C, A LD A, D SUB H LD B, A INC B LD A, C LOC_8759: CALL VDP_WRITE_8842 INC H DJNZ LOC_8759 POP HL RET SUB_8761: LD HL, BOOT_UP LD ($7044), HL ; RAM $7044 LD ($7046), HL ; RAM $7046 CALL SUB_87CE LD HL, ($7048) ; RAM $7048 LD DE, ($704A) ; RAM $704A LD B, H LOC_8775: CALL VDP_REG_86E2 CP $88 JR NZ, LOC_8783 INC H LD A, D CP H JR NC, LOC_8775 JR LOC_8788 LOC_8783: LD A, $01 LD ($7044), A ; RAM $7044 LOC_8788: LD H, B LD B, L LOC_878A: CALL VDP_REG_86E2 CP $88 JR NZ, LOC_8798 INC L LD A, E CP L JR NC, LOC_878A JR LOC_879D LOC_8798: LD A, $01 LD ($7045), A ; RAM $7045 LOC_879D: LD L, B DB $EB LD B, H LOC_87A0: CALL VDP_REG_86E2 CP $88 JR NZ, LOC_87AE DEC H LD A, H CP D JR NC, LOC_87A0 JR LOC_87B3 LOC_87AE: LD A, $01 LD ($7046), A ; RAM $7046 LOC_87B3: LD H, B LOC_87B4: CALL VDP_REG_86E2 CP $88 JR NZ, LOC_87C2 DEC L LD A, L CP E JR NC, LOC_87B4 JR LOC_87C7 LOC_87C2: LD A, $01 LD ($7047), A ; RAM $7047 LOC_87C7: CALL DELAY_LOOP_8830 RET NZ JP SUB_8761 SUB_87CE: CALL SUB_8534 AND $7F LD E, A CALL SUB_8534 AND $3F LD H, A LD L, E CALL VDP_REG_86E2 CP $8B JR NZ, SUB_87CE SUB_87E2: PUSH HL LOC_87E3: DEC H CALL SUB_8807 JR NZ, LOC_87E3 INC H LOC_87EA: DEC L CALL SUB_8807 JR NZ, LOC_87EA DEC H LD ($7048), HL ; RAM $7048 POP HL LOC_87F5: INC H CALL SUB_8807 JR NZ, LOC_87F5 DEC H LOC_87FC: INC L CALL SUB_8807 JR NZ, LOC_87FC INC H LD ($704A), HL ; RAM $704A RET SUB_8807: CALL VDP_REG_86E2 CP $88 RET Z CP $8A RET Z CP $80 RET Z CP $89 RET SUB_8816: LD A, $18 CALL SUB_854A ADD A, $02 CALL SUB_854A ADD A, $07 RET SUB_8823: LD A, $0A CALL SUB_854A ADD A, $02 CALL SUB_854A ADD A, $05 RET DELAY_LOOP_8830: LD BC, $0400 LD HL, $7044 ; RAM $7044 XOR A LOC_8837: CP (HL) INC HL JR Z, LOC_883C INC C LOC_883C: DJNZ LOC_8837 LD A, C CP $04 RET VDP_WRITE_8842: ; VDP_WRITE_8842: write byte A to VRAM at address HL (via VDP_REG_86E8 + DATA_PORT) LD C, A LD A, H AND $01 RRCA OR L OUT ($BF), A ; CTRL_PORT - write VDP register LD A, H RRA OR $40 OUT ($BF), A ; CTRL_PORT - write VDP register LD A, C OUT ($BE), A ; DATA_PORT - write VRAM RET SUB_8854: LD DE, $7051 ; RAM $7051 LD HL, $7080 ; RAM $7080 BIT 2, (HL) JR NZ, LOC_8890 LD A, ($70CA) ; RAM $70CA BIT 1, (HL) JR Z, LOC_8869 CP $4C JR LOC_886B LOC_8869: CP $24 LOC_886B: JR NC, LOC_8878 RES 1, (HL) LD A, (DE) OR A JR Z, LOC_8893 SET 1, (HL) JP LOC_897D LOC_8878: BIT 1, (HL) RES 1, (HL) JR Z, LOC_8882 CP $58 JR LOC_8884 LOC_8882: CP $80 LOC_8884: JR C, LOC_8893 LD A, (DE) CP $2C JR Z, LOC_8893 SET 1, (HL) JP LOC_8931 LOC_8890: BIT 1, (HL) RET NZ LOC_8893: LD A, ($70CB) ; RAM $70CB DEC DE BIT 2, (HL) JR Z, LOC_889F CP $68 JR LOC_88A1 LOC_889F: CP $30 LOC_88A1: JR NC, LOC_88AC RES 2, (HL) LD A, (DE) OR A RET Z SET 2, (HL) JR LOC_88E0 LOC_88AC: BIT 2, (HL) RES 2, (HL) JR Z, LOC_88B6 CP $90 JR LOC_88B8 LOC_88B6: CP $C8 LOC_88B8: RET C LD DE, $7050 ; RAM $7050 LD A, (DE) CP $60 RET Z SET 2, (HL) INC A LD (DE), A LD HL, $70E0 ; RAM $70E0 LD DE, $70DF ; RAM $70DF LD BC, $027F LDIR LD HL, ($7050) ; RAM $7050 LD DE, $001F ADD HL, DE LD DE, $70FE ; RAM $70FE CALL DELAY_LOOP_8996 LD C, $F8 JR LOC_88F5 LOC_88E0: DEC A LD (DE), A LD HL, $735D ; RAM $735D LD DE, $735E ; RAM $735E LD BC, $027F LDDR LD HL, ($7050) ; RAM $7050 CALL DELAY_LOOP_8996 LD C, $08 LOC_88F5: LD B, $04 LD HL, $70DA ; RAM $70DA LOC_88FA: LD A, (HL) CP $D8 JR NZ, LOC_890D LD A, B OR A JR Z, LOC_891D CP $04 PUSH HL PUSH BC CALL NZ, SUB_A89D POP BC JR LOC_891C LOC_890D: INC HL LD A, (HL) ADD A, C LD (HL), A DEC HL LD A, B OR A JR Z, LOC_891D CP $04 PUSH HL CALL NZ, SUB_A80F LOC_891C: POP HL LOC_891D: LD DE, $FFFC ADD HL, DE DEC B JP P, LOC_88FA LD HL, $7055 ; RAM $7055 LOC_8928: LD A, (HL) ADD A, C LD (HL), A LD HL, $7080 ; RAM $7080 SET 0, (HL) RET LOC_8931: INC A LD (DE), A LD HL, $70FF ; RAM $70FF LD DE, $70DF ; RAM $70DF LD BC, $0260 LDIR LD HL, ($7050) ; RAM $7050 LD BC, $1300 ADD HL, BC CALL VDP_DATA_89A7 LD C, $F8 LOC_894A: LD B, $04 LD HL, $70DA ; RAM $70DA LOC_894F: LD A, (HL) CP $D8 JR NZ, LOC_8962 LD A, B OR A JR Z, LOC_8970 CP $04 PUSH HL PUSH BC CALL NZ, SUB_A89D POP BC JR LOC_896F LOC_8962: LD A, (HL) ADD A, C LD (HL), A LD A, B OR A JR Z, LOC_8970 CP $04 PUSH HL CALL NZ, SUB_A80F LOC_896F: POP HL LOC_8970: LD DE, $FFFC ADD HL, DE DEC B JP P, LOC_894F LD HL, $7054 ; RAM $7054 JR LOC_8928 LOC_897D: DEC A LD (DE), A LD HL, $733E ; RAM $733E LD DE, $735E ; RAM $735E LD BC, $0260 LDDR DB $EB INC DE LD HL, ($7050) ; RAM $7050 CALL VDP_DATA_89A7 LD C, $08 JR LOC_894A DELAY_LOOP_8996: LD B, $14 LOC_8998: CALL VDP_REG_86E8 LD (DE), A INC H LD A, E ADD A, $20 LD E, A JR NC, LOC_89A4 INC D LOC_89A4: DJNZ LOC_8998 RET VDP_DATA_89A7: CALL VDP_REG_86E8 LD B, $20 LOC_89AC: LD (DE), A INC DE IN A, ($BE) ; DATA_PORT - read VRAM DJNZ LOC_89AC RET LOC_89B3: LD HL, $70BF ; RAM $70BF LD DE, ($7050) ; RAM $7050 RL E SRL D RR E LD B, $14 LOC_89C2: PUSH BC LD BC, $0020 ADD HL, BC PUSH HL PUSH DE CALL READ_VRAM POP HL LD BC, $0080 ADD HL, BC DB $EB POP HL POP BC DJNZ LOC_89C2 LD HL, $7080 ; RAM $7080 SET 0, (HL) RET SUB_89DC: ; SUB_89DC: copy tile render buffer $70DF ($200 bytes) and sprite attr buffer $72DF ($80 bytes) to VRAM LD HL, ($73F6) ; HL = $73F6 (HUD VRAM base address pointer) LD DE, $0020 ; DE = $0020 ADD HL, DE ; ADD HL,DE: VRAM dest = $73F6 + $0020 DB $EB LD HL, $70DF ; HL = $70DF (tile render buffer, $200 bytes) LD BC, $0200 ; BC = $0200 — 512 bytes PUSH DE ; PUSH DE (save VRAM dest) CALL WRITE_VRAM ; BIOS WRITE_VRAM: copy tile render buffer to VRAM POP DE ; POP DE INC D ; INC D / INC D: advance VRAM dest by $200 INC D LD HL, $72DF ; HL = $72DF (sprite attribute buffer, $80 bytes) LD BC, $0080 ; BC = $0080 — 128 bytes JP WRITE_VRAM ; JP BIOS WRITE_VRAM: copy sprite attr buffer to VRAM (tail call) DB $92, $8A, $90, $70, $BB, $8A, $AE, $70 DB $C1, $8A, $90, $70, $CE, $8A, $9A, $70 DB $E3, $8A, $90, $70, $BA, $8A, $B8, $70 DB $F4, $8A, $9A, $70, $BA, $8A, $90, $70 DB $BA, $8A, $9A, $70, $BA, $8A, $A4, $70 DB $4B, $8B, $A4, $70, $52, $8B, $B8, $70 DB $58, $8B, $A4, $70, $61, $8B, $B8, $70 DB $6C, $8B, $90, $70, $75, $8B, $A4, $70 DB $82, $8B, $B8, $70, $8E, $8B, $A4, $70 DB $9C, $8B, $B8, $70, $A7, $8B, $A4, $70 DB $AE, $8B, $B8, $70, $B4, $8B, $A4, $70 DB $BB, $8B, $B8, $70, $C1, $8B, $A4, $70 DB $CA, $8B, $B8, $70, $D0, $8B, $A4, $70 DB $D7, $8B, $B8, $70, $C1, $8B, $A4, $70 DB $CA, $8B, $B8, $70, $DD, $8B, $A4, $70 DB $E4, $8B, $B8, $70, $94, $8B, $A4, $70 DB $A1, $8B, $B8, $70, $DD, $8B, $A4, $70 DB $E4, $8B, $B8, $70, $EA, $8B, $9A, $70 DB $8D, $8B, $A4, $70, $9B, $8B, $B8, $70 DB $42, $D5, $60, $07, $C2, $11, $40, $BE DB $20, $06, $40, $A9, $20, $06, $40, $A0 DB $20, $06, $40, $8E, $20, $06, $40, $A0 DB $20, $06, $40, $A9, $20, $06, $40, $BE DB $20, $06, $42, $D5, $20, $0C, $26, $16 DB $10, $02, $F5, $05, $E5, $11, $10, $42 DB $FE, $60, $08, $C2, $11, $42, $BE, $20 DB $28, $1B, $38, $10, $82, $FE, $60, $08 DB $C2, $11, $80, $D5, $20, $07, $80, $BE DB $20, $07, $82, $A0, $20, $28, $1B, $38 DB $10, $43, $A0, $A1, $0C, $11, $30, $E6 DB $11, $43, $D0, $03, $30, $11, $F0, $1F DB $33, $10, $83, $47, $A0, $06, $12, $02 DB $C3, $11, $81, $53, $20, $06, $11, $FE DB $81, $47, $30, $06, $11, $02, $81, $53 DB $40, $06, $11, $FE, $81, $47, $50, $06 DB $11, $02, $81, $53, $60, $06, $11, $FE DB $81, $47, $70, $06, $11, $02, $81, $53 DB $80, $06, $11, $FE, $81, $47, $90, $06 DB $11, $02, $81, $53, $A0, $06, $11, $FE DB $81, $47, $B0, $06, $11, $02, $81, $53 DB $C0, $06, $11, $FE, $81, $47, $D0, $06 DB $11, $02, $81, $53, $E0, $06, $11, $FE DB $10, $C1, $00, $F0, $28, $11, $05, $10 DB $02, $23, $28, $1C, $44, $10, $C0, $38 DB $F0, $0E, $C0, $43, $F0, $20, $10, $02 DB $13, $0E, $00, $00, $02, $13, $20, $1E DB $2A, $10, $43, $00, $20, $FF, $11, $79 DB $1C, $FF, $10, $C1, $80, $F0, $06, $11 DB $F0, $C1, $20, $F0, $14, $11, $10, $10 DB $02, $B7, $06, $E6, $11, $02, $17, $14 DB $1A, $22, $10, $28, $C1, $40, $F0, $0E DB $11, $F8, $C1, $20, $F0, $1E, $11, $08 DB $10, $28, $02, $77, $0E, $F8, $22, $02 DB $17, $1E, $1E, $22, $10, $C1, $C0, $F0 DB $14, $11, $F8, $10, $02, $87, $14, $F8 DB $33, $10, $C1, $00, $F0, $06, $11, $10 DB $10, $02, $67, $06, $F5, $11, $10, $C3 DB $1D, $70, $02, $66, $01, $F6, $22, $10 DB $02, $74, $0C, $F6, $22, $10, $C1, $60 DB $F0, $10, $11, $04, $10, $02, $07, $10 DB $1F, $11, $10, $C1, $40, $F0, $0C, $11 DB $FE, $10, $02, $B7, $0C, $FC, $11, $10 DB $83, $38, $30, $30, $11, $02, $15, $CC DB $83, $98, $70, $30, $11, $FE, $15, $CC DB $10 ; ============================================================================= ; TITLE SCREEN / GAME INIT -- LOC_8BFB ($8BFB) ; Reached from START. Sets up the title/intro display, waits for player ; button press, then enters the main game: ; CALL SUB_8557 VDP write-address reset ; RST $18 (x3) load tile/sprite pattern tables to VRAM ; LD HL,($73FA) VRAM scroll base address ; CALL FILL_VRAM (x2) blank playfield ($F0 fill, $70 fill) ; LD C,$01 / CALL SUB_85A8 set sprite mode ; CALL SUB_8504 wait for fire button (RST $08 sync loop) ; JP LOC_8036 enter main game loop ; LOC_8036 is the permanent game loop; LOC_8BFB is only run once per boot. ; ============================================================================= LOC_8BFB: ; LOC_8BFB: title screen / game init — called once from START; VDP setup, wait button, JP LOC_8036 CALL SUB_8557 ; reset VDP write address and reload tile tables LD A, $03 ; A = 3 — sprite/tile load mode LD HL, $8D18 ; HL = $8D18 — tile pattern table address LD DE, $0080 ; DE = $0080 — 128 tiles LD IY, $0040 ; IY = $0040 — stride RST $18 ; RST $18 (INIT_SPRORDERP vector): load sprite pattern data to VRAM LD HL, $8C2F ; HL = $8C2F — RST $10 string: title screen text data RST $10 ; RST $10 (WRITER): render title text to VRAM LD HL, ($73FA) ; HL = $73FA (tile page VRAM base pointer) LD A, $70 ; A = $70 — fill value LD DE, $0015 ; DE = $0015 — byte count PUSH HL ; PUSH HL: save VRAM base CALL FILL_VRAM ; BIOS FILL_VRAM: clear first section of tile page POP HL ; POP HL: restore VRAM base LD A, $F0 ; A = $F0 — alternate fill value LD DE, $0010 ; DE = $0010 CALL FILL_VRAM ; BIOS FILL_VRAM: fill second section LD C, $01 ; C = 1 — sprite mode parameter CALL SUB_85A8 ; SUB_85A8: enable sprites in VDP display mode CALL SUB_8504 ; wait for fire button (RST $08 polling loop) JP LOC_8036 ; JP LOC_8036: enter main game loop (never returns to LOC_8BFB) DB $FD, $07, $82, $80, $80, $80, $81, $82 DB $80, $80, $89, $8B, $93, $00, $8E, $80 DB $80, $8F, $8E, $80, $91, $1E, $1F, $FD DB $26, $84, $80, $83, $00, $00, $84, $80 DB $83, $88, $80, $8C, $94, $8E, $80, $91 DB $96, $95, $80, $91, $FD, $46, $82, $80 DB $80, $80, $81, $82, $85, $00, $82, $85 DB $8D, $80, $80, $91, $00, $8A, $80, $97 DB $FD, $65, $84, $80, $83, $00, $00, $84 DB $80, $83, $87, $80, $83, $8E, $80, $91 DB $00, $8E, $80, $98, $90, $FD, $85, $82 DB $80, $80, $80, $81, $82, $80, $80, $80 DB $86, $8E, $80, $91, $00, $8E, $80, $91 DB $92, $80, $8F, $FD, $A9, $84, $80, $83 DB $FD, $C9, $82, $85, $20, $70, $72, $65 DB $73, $65, $6E, $74, $73, $FE, $29, $47 DB $20, $41, $20, $54, $20, $45, $20, $57 ; " A T E W" DB $20, $41, $20, $59, $FE, $6E, $54, $20 DB $4F, $FE, $AA, $41, $20, $50, $20, $53 DB $20, $48, $20, $41, $20, $49, $FF, $2A DB $1D, $20, $31, $39, $38, $34, $20, $45 DB $50, $59, $58, $FF, $63, $50, $55, $53 DB $48, $20, $53, $49, $44, $45, $20, $42 ; "H SIDE B" DB $55, $54, $54, $4F, $4E, $20, $54, $4F ; "UTTON TO" DB $20, $53, $54, $41, $52, $54, $FF, $A7 DB $63, $6F, $6C, $65, $63, $6F, $20, $76 ; "coleco v" DB $65, $72, $73, $69, $6F, $6E, $20, $62 ; "ersion b" DB $79, $FF, $E9, $6D, $61, $72, $63, $20 DB $66, $65, $72, $67, $75, $73, $6F, $6E ; "ferguson" DB $FC, $FF, $FF, $FF, $FF, $FF, $FF, $FF DB $FF, $FC, $F8, $F8, $F0, $F0, $E0, $E0 DB $C0, $0F, $1F, $1F, $3F, $3F, $7F, $7F DB $FF, $F0, $E0, $E0, $C0, $C0, $80, $80 DB $00, $00, $01, $01, $03, $03, $07, $07 DB $0F, $FF, $FE, $FE, $FC, $FC, $F8, $F8 DB $F0, $FF, $FE, $FE, $FC, $F8, $F0, $C0 DB $00, $00, $01, $01, $03, $03, $07, $0F DB $3F, $1F, $07, $03, $03, $03, $03, $07 DB $07, $E0, $F8, $FC, $FE, $FE, $FF, $FF DB $FF, $0F, $07, $03, $07, $0F, $1F, $3F DB $7F, $3F, $3F, $1F, $1F, $1F, $1F, $0F DB $0F, $0F, $0F, $07, $07, $07, $07, $07 DB $03, $03, $03, $03, $03, $01, $01, $01 DB $01, $00, $01, $03, $07, $0F, $1F, $3F DB $7F, $00, $80, $80, $C0, $C0, $E0, $E0 DB $F0, $F0, $F8, $F8, $FC, $FC, $FE, $FE DB $FF, $FE, $FC, $F8, $F0, $E0, $C0, $80 DB $00, $0F, $07, $07, $03, $03, $01, $01 DB $00, $F0, $F0, $F8, $F8, $F8, $F8, $FC DB $FC, $FC, $FC, $FC, $FE, $FE, $FE, $FE DB $FF, $F0, $F9, $FB, $FF, $FF, $FF, $FF DB $FF, $FF, $7F, $7F, $3F, $3F, $1F, $1F DB $0F, $FE, $FC, $F8, $F0, $E0, $C0, $E0 DB $F0, $FF, $FF, $FF, $FF, $FF, $DF, $9F DB $0F VDP_REG_8DE0: ; VDP_REG_8DE0: init VDP for dungeon display — FILL_VRAM, compute player start position LD A, $BF ; A = $BF — fill byte for pattern clear LD HL, BOOT_UP ; HL = BOOT_UP ($0000) — VRAM address LD DE, $2000 ; DE = $2000 — byte count (8KB pattern table) CALL FILL_VRAM ; BIOS FILL_VRAM: clear all 8KB pattern table with $BF LD A, $10 ; A = $10 — RNG advance count CALL SUB_854A ; SUB_854A: call RNG A times to get position seed in H CPL ; CPL: invert RNG result ADD A, $21 ; ADD A,$21: bias into valid range LD H, A ; H = A (X position) CALL SUB_8823 ; SUB_8823: further position computation ADD A, H ; ADD A,H: combine X LD C, A ; C = A (X position for tile bounds) CALL SUB_8816 ; SUB_8816: another position helper LD L, $03 ; L = 3 ADD A, L ; ADD A,L LD ($7040), HL ; RAM $7040 = player starting HL (tile position) LD ($704C), HL ; RAM $704C = player X world tile position (initial) LD H, C ; H = C LD L, A ; L = A LD ($7042), HL ; RAM $7042 = player starting HL alt LD ($704E), HL ; RAM $704E = player Y world tile position (initial) LD E, $02 ; E = 2 CALL SUB_9077 ; SUB_9077: initialise viewport at position 2 LD B, $3C ; B = $3C — 60 rows: dungeon renderer row count LOC_8E14: ; LOC_8E14: dungeon/room tile renderer — iterate 60 rows; call DELAY_LOOP_8830+SUB_8761 per row LD C, $00 ; C = 0 — current row column counter PUSH BC ; PUSH BC: save row/col counters LOC_8E17: ; LOC_8E17: per-row render loop — DELAY_LOOP_8830 then SUB_8761 for each row segment CALL DELAY_LOOP_8830 ; DELAY_LOOP_8830: timing/sync — NZ if more data in this row JR NZ, LOC_8E21 ; JR NZ: render segment — call SUB_8761 CALL SUB_8761 ; SUB_8761: render one tile row segment to tile buffer $70DF JR LOC_8E17 LOC_8E21: LD B, $0A LOC_8E23: CALL SUB_8534 LD C, $01 RRCA JR C, LOC_8E2D LD C, $FF LOC_8E2D: ADD A, C AND $03 LD HL, $7044 ; RAM $7044 LD E, A XOR A LD D, A ADD HL, DE CP (HL) LD A, E JR NZ, LOC_8E2D RRCA JR NC, LOC_8E9A CALL SUB_8823 LD C, A BIT 1, E JR NZ, LOC_8E57 LD A, ($7049) ; RAM $7049 LD ($7043), A ; RAM $7043 SUB C CP $83 JP PO, LOC_8E8C LD ($7041), A ; RAM $7041 JR LOC_8E65 LOC_8E57: LD A, ($704B) ; RAM $704B LD ($7041), A ; RAM $7041 ADD A, C CP $3D JR NC, LOC_8E8C LD ($7043), A ; RAM $7043 LOC_8E65: CALL SUB_8816 LD C, A LD A, ($7048) ; RAM $7048 ADD A, $06 SUB C JR NC, LOC_8E72 XOR A LOC_8E72: LD D, A LD A, ($704A) ; RAM $704A SUB $05 SUB D CALL SUB_854A ADD A, D CP $03 JR C, LOC_8E8C LD ($7040), A ; RAM $7040 ADD A, C LD ($7042), A ; RAM $7042 CP $7D JR C, LOC_8EE8 LOC_8E8C: DJNZ LOC_8E23 CALL SUB_8761 POP BC DEC C PUSH BC JR NZ, LOC_8E17 POP BC JP LOC_8F9A LOC_8E9A: CALL SUB_8816 LD C, A BIT 1, E JR NZ, LOC_8EB3 LD A, ($7048) ; RAM $7048 LD ($7042), A ; RAM $7042 SUB C CP $83 JP PO, LOC_8E8C LD ($7040), A ; RAM $7040 JR LOC_8EC1 LOC_8EB3: LD A, ($704A) ; RAM $704A LD ($7040), A ; RAM $7040 ADD A, C CP $7D JR NC, LOC_8E8C LD ($7042), A ; RAM $7042 LOC_8EC1: CALL SUB_8823 LD C, A LD A, ($7049) ; RAM $7049 ADD A, $04 SUB C JR NC, LOC_8ECE XOR A LOC_8ECE: LD D, A LD A, ($704B) ; RAM $704B SUB $03 SUB D CALL SUB_854A ADD A, D CP $03 JR C, LOC_8E8C LD ($7041), A ; RAM $7041 ADD A, C CP $3D JR NC, LOC_8E8C LD ($7043), A ; RAM $7043 LOC_8EE8: LD HL, ($7040) ; RAM $7040 INC H INC L LD A, ($7042) ; RAM $7042 SUB L LD D, A LOC_8EF2: LD C, D CALL VDP_REG_86E8 LOC_8EF6: AND $BF CP $BF JR NZ, LOC_8E8C DEC C IN A, ($BE) ; DATA_PORT - read VRAM JR NZ, LOC_8EF6 INC H LD A, ($7043) ; RAM $7043 CP H JR NZ, LOC_8EF2 LD HL, ($7048) ; RAM $7048 LD BC, ($704A) ; RAM $704A BIT 0, E JR Z, LOC_8F55 BIT 1, E JR Z, LOC_8F18 LD H, B LOC_8F18: LD A, ($7040) ; RAM $7040 CP L JR C, LOC_8F1F LD L, A LOC_8F1F: INC L LD A, ($7042) ; RAM $7042 CP C JR NC, LOC_8F27 LD C, A LOC_8F27: DEC C LD A, C SUB L LD D, A CP $06 JR C, LOC_8F4D PUSH HL CALL SUB_8534 POP HL CP $99 JR NC, LOC_8F4D LD A, D SUB $04 CALL SUB_854A ADD A, $05 LD B, A LD A, D SUB B JR Z, LOC_8F4D CALL SUB_854A INC A ADD A, L LD L, A ADD A, B LD C, A LOC_8F4D: CALL SUB_9057 CALL VDP_DATA_8742 JR LOC_8F95 LOC_8F55: BIT 1, E JR Z, LOC_8F5A LD L, C LOC_8F5A: LD A, ($7041) ; RAM $7041 CP H JR C, LOC_8F61 LD H, A LOC_8F61: INC H LD A, ($7043) ; RAM $7043 CP B JR NC, LOC_8F69 LD B, A LOC_8F69: DEC B LD A, B SUB H LD D, A CP $04 JR C, LOC_8F8F PUSH HL CALL SUB_8534 POP HL CP $99 JR NC, LOC_8F8F LD A, D SUB $02 CALL SUB_854A ADD A, $03 LD C, A LD A, D SUB C JR Z, LOC_8F8F CALL SUB_854A INC A ADD A, H LD H, A ADD A, C LD B, A LOC_8F8F: CALL SUB_9057 CALL DELAY_LOOP_8752 LOC_8F95: POP BC DEC B JP NZ, LOC_8E14 LOC_8F9A: LD HL, BOOT_UP LD ($7040), HL ; RAM $7040 LD BC, $0F05 LOC_8FA3: LD A, $07 CALL SUB_854A LD L, A LD A, B LD DE, $3CB0 CALL LOC_8714 LD L, C LD DE, $3CC0 CALL LOC_8714 CALL SUB_90B9 LD DE, $3C90 CALL VDP_DATA_8730 LD A, $F8 CALL SUB_90D9 LD A, C CP $05 JR NZ, LOC_8FD0 CALL SUB_8534 CALL M, SUB_910E LOC_8FD0: DEC C JR NZ, LOC_8FD5 LD C, $05 LOC_8FD5: DJNZ LOC_8FA3 LD A, $06 LD DE, $3CC0 CALL VDP_DATA_8702 CALL SUB_90B9 LD DE, $3C90 XOR A CALL VDP_DATA_8730 LD A, $07 CALL SUB_854A LD DE, $3CB0 CALL VDP_DATA_8702 LD A, $F8 CALL SUB_90D9 CALL SUB_910E LD A, ($7058) ; RAM $7058 PUSH AF LD B, A RLCA RLCA ADD A, B LD C, A LD A, B ADD A, $07 LD B, A LOC_9009: LD A, B SUB $06 JR NC, LOC_9011 ADD A, C JR LOC_9015 LOC_9011: LD A, C CALL SUB_854A LOC_9015: CALL SUB_90E5 DJNZ LOC_9009 LD A, $01 CALL SUB_90E5 POP AF PUSH AF ADD A, $04 LD B, A LOC_9024: CALL SUB_90B9 CALL SUB_910E DJNZ LOC_9024 POP AF RLCA RLCA LD C, A LD B, $02 LOC_9032: PUSH BC LD B, $04 LOC_9035: LD A, C SUB B CALL SUB_912E DJNZ LOC_9035 POP BC DJNZ LOC_9032 LD B, $08 LOC_9041: LD A, C CALL SUB_854A LD L, A LD DE, $957C CALL SUB_86DD LD A, (DE) RLCA JR C, LOC_9041 LD A, L CALL SUB_912E DJNZ LOC_9041 RET SUB_9057: PUSH HL PUSH BC CALL SUB_9077 CALL SUB_8534 LD B, $CA CP $40 JR NC, LOC_9073 LD B, $C0 CP $10 JR NC, LOC_9073 LD A, ($7058) ; RAM $7058 DEC A JR Z, LOC_9073 LD B, $C9 LOC_9073: LD A, B POP DE POP HL RET SUB_9077: LD HL, BOOT_UP LD ($7044), HL ; RAM $7044 LD ($7046), HL ; RAM $7046 LD A, E XOR $02 LD L, A LD DE, $7044 ; RAM $7044 ADD HL, DE LD (HL), $01 LD HL, ($7042) ; RAM $7042 LD ($704A), HL ; RAM $704A DB $EB LD HL, ($7040) ; RAM $7040 LD ($7048), HL ; RAM $7048 LD A, $C8 CALL VDP_DATA_8742 CALL DELAY_LOOP_8752 PUSH HL LD H, D CALL VDP_DATA_8742 POP HL PUSH HL LD L, E CALL DELAY_LOOP_8752 POP HL INC H INC L DEC E LOC_90AE: LD A, $CB CALL VDP_DATA_8742 INC H LD A, H CP D JR NZ, LOC_90AE RET SUB_90B9: LD D, A LOC_90BA: CALL SUB_8534 AND $7E LD E, A CALL SUB_8534 AND $3F LD H, A LD L, E CALL VDP_REG_86E2 CP $8B JR NZ, LOC_90BA INC L CALL VDP_REG_86E2 CP $8B JR NZ, LOC_90BA DEC L LD A, D RET SUB_90D9: PUSH BC CALL VDP_WRITE_8842 INC L INC A CALL VDP_WRITE_8842 DEC L POP BC RET SUB_90E5: PUSH AF ADD A, $06 LD L, A LD A, B LD DE, $3C70 CALL LOC_8714 CALL SUB_90B9 LD DE, $3C30 CALL VDP_DATA_8730 POP AF RLCA RLCA LD DE, $939F CALL SUB_86DD LD A, (DE) OR $40 CALL SUB_90D9 INC DE INC DE INC DE LD A, (DE) RLCA RET NC SUB_910E: LD A, ($7040) ; RAM $7040 CP $10 RET NC LD DE, $3C00 CALL VDP_DATA_8730 LD H, A LD A, ($7058) ; RAM $7058 CALL SUB_854A LD L, A LD A, H LD DE, $3C20 CALL LOC_8714 LD HL, $7040 ; RAM $7040 INC (HL) RET SUB_912E: PUSH AF LOC_912F: CALL SUB_87CE CALL SUB_9159 JR Z, LOC_912F LD HL, ($7048) ; RAM $7048 LD DE, ($704C) ; RAM $704C OR A SBC HL, DE JR Z, LOC_912F LD HL, $7041 ; RAM $7041 LD A, (HL) INC (HL) POP HL LD L, H LD DE, $3CD0 CALL LOC_8714 LD HL, ($7048) ; RAM $7048 LD DE, $3CF0 JP VDP_DATA_8730 SUB_9159: LD A, $1F LOC_915B: LD DE, $3CF0 CALL VDP_DATA_8720 LD DE, ($7048) ; RAM $7048 OR A SBC HL, DE RET Z DEC A JP P, LOC_915B RET DB $59, $51, $71, $E1, $81, $21, $D1, $B1 DB $B1, $B1, $B1, $B1, $B1, $B1, $B1, $B1 DB $53, $73, $E3, $83, $23, $D3, $59, $79 DB $E9, $89, $29, $D9 SUB_918A: LD A, $03 LD DE, $0090 LD HL, $9293 LD IY, $0016 RST $18 LD E, $A8 LD HL, $9343 LD IY, $0004 RST $18 LD E, $B0 LD HL, $9363 LD IY, $0002 RST $18 LD E, $B8 LD HL, $9373 RST $18 LD E, $88 LD HL, $928B DEC IY RST $18 INC E RST $18 LD E, $80 LD HL, $9283 RST $18 LD HL, $9383 LD E, $BF LOC_91C6: RST $18 INC E JR NZ, LOC_91C6 LD A, $F0 LD HL, ($73FA) ; RAM $73FA LD DE, $0010 PUSH DE PUSH HL CALL FILL_VRAM POP HL LD DE, $0002 LD A, $70 CALL FILL_VRAM POP DE PUSH DE POP IY LD HL, $916E JR LOC_91F3 DB $21, $6F, $91, $FD, $21, $06, $00, $11 DB $11, $00 LOC_91F3: LD A, $04 JP PUT_VRAM DB $21, $84, $91, $18, $EF, $21, $7E, $91 DB $18, $EA, $11, $00, $00, $06, $20, $C5 DB $21, $DF, $70, $01, $00, $01, $D5, $CD DB $E2, $1F, $D1, $21, $DF, $71, $06, $00 DB $2B, $CB, $B6, $10, $FB, $01, $00, $01 DB $D5, $CD, $DF, $1F, $D1, $14, $C1, $10 DB $DE, $C3, $B3, $89 DELAY_LOOP_922C: ; DELAY_LOOP_922C: transition delay loop — frame sync with counter LD DE, BOOT_UP LD B, $20 LOC_9231: PUSH BC LD HL, $70DF ; RAM $70DF LD BC, $0100 PUSH DE CALL READ_VRAM POP DE LD HL, $71DF ; RAM $71DF LD B, $00 LOC_9242: DEC HL SET 6, (HL) DJNZ LOC_9242 LD BC, $0100 PUSH DE CALL WRITE_VRAM POP DE INC D POP BC DJNZ LOC_9231 RET VDP_WRITE_9254: ; VDP_WRITE_9254: write sprite pattern and attribute table to VRAM from RAM buffers LD HL, ($7048) ; RAM $7048 LOC_9257: LD A, ($704A) ; RAM $704A SUB L LD B, A CALL VDP_REG_86E8 LD DE, $70DF ; RAM $70DF PUSH DE LD C, B INC B LOC_9265: AND $BF LD (DE), A INC DE IN A, ($BE) ; DATA_PORT - read VRAM DJNZ LOC_9265 POP DE LD A, (DE) LD B, C CALL VDP_WRITE_8842 INC H LOC_9274: INC DE LD A, (DE) OUT ($BE), A ; DATA_PORT - write VRAM DJNZ LOC_9274 LD A, ($704B) ; RAM $704B CP H JR NC, LOC_9257 JP LOC_89B3 DB $FF, $C3, $C3, $C3, $C3, $C3, $C3, $FF DB $CF, $CF, $CF, $CF, $F3, $F3, $F3, $F3 DB $FC, $FF, $CF, $0F, $0F, $3F, $3F, $3F DB $7E, $FE, $E6, $E0, $E0, $F8, $F8, $F8 DB $3C, $0C, $0F, $FF, $0F, $0C, $0F, $00 DB $00, $00, $FE, $FF, $FE, $00, $00, $00 DB $83, $CE, $FF, $FF, $FF, $FF, $FF, $83 DB $00, $7C, $C0, $FF, $C0, $FE, $80, $F8 DB $00, $03, $0F, $0F, $0C, $0C, $3C, $3C DB $00, $C0, $F0, $F0, $30, $30, $3C, $3C DB $00, $00, $00, $00, $01, $02, $04, $08 DB $20, $70, $20, $80, $00, $00, $00, $00 DB $00, $00, $07, $00, $00, $00, $00, $00 DB $C0, $C0, $F8, $C0, $C0, $C0, $C0, $C0 DB $67, $4F, $09, $09, $07, $02, $43, $62 DB $CC, $E4, $20, $20, $C0, $80, $84, $8C DB $00, $00, $00, $F0, $3F, $F0, $00, $00 DB $00, $00, $00, $0C, $FF, $0C, $00, $00 DB $3F, $C0, $30, $0C, $03, $00, $00, $00 DB $C0, $F0, $3C, $0F, $03, $C3, $33, $0C DB $60, $78, $1E, $07, $01, $00, $00, $00 DB $00, $00, $00, $80, $E0, $78, $1E, $04 DB $00, $00, $10, $1F, $FF, $1F, $10, $00 DB $00, $00, $08, $F8, $FF, $F8, $08, $00 DB $00, $0F, $03, $03, $0E, $1C, $0E, $03 DB $00, $E0, $80, $80, $E0, $70, $E0, $80 DB $03, $1F, $1F, $7C, $7C, $1F, $1F, $03 DB $C0, $F8, $F8, $3E, $3E, $F8, $F8, $C0 DB $3C, $43, $40, $20, $11, $0F, $07, $03 DB $3C, $C2, $02, $04, $88, $F0, $E0, $C0 DB $0F, $03, $00, $00, $3F, $32, $3F, $3F DB $C0, $30, $CC, $3C, $FC, $4C, $FC, $FC DB $FF, $CC, $FF, $33, $FF, $CC, $FF, $33 DB $00, $2B, $00, $00, $00, $2A, $2C, $00 DB $00, $2D, $00, $01, $00, $35, $29, $00 DB $00, $2E, $3E, $00, $A0, $32, $00, $04 DB $9E, $33, $00, $05, $92, $34, $57, $01 DB $A8, $3B, $2F, $00, $A4, $36, $3E, $80 DB $AA, $37, $38, $03, $90, $39, $2C, $82 DB $A4, $3A, $00, $00, $A8, $3B, $3C, $00 DB $A4, $3D, $3E, $00, $A4, $38, $3E, $00 DB $92, $3F, $57, $01, $AA, $40, $38, $03 DB $B0, $41, $42, $80, $B0, $43, $44, $00 DB $A4, $45, $3E, $00, $9E, $46, $33, $86 DB $A4, $47, $3E, $00, $96, $48, $00, $03 DB $A4, $49, $3E, $00, $94, $4A, $00, $03 DB $92, $4B, $57, $01, $90, $4C, $2C, $02 DB $B0, $3B, $44, $00, $B0, $4E, $22, $00 DB $AA, $46, $38, $83, $98, $4F, $00, $80 DB $9A, $50, $00, $00, $A4, $23, $3E, $00 DB $A4, $51, $3E, $00, $96, $46, $48, $83 DB $92, $46, $57, $81, $92, $46, $57, $81 DB $90, $52, $2C, $82, $A4, $3B, $3E, $00 DB $A4, $22, $3E, $00, $A4, $28, $3E, $80 DB $A2, $56, $00, $80, $A4, $55, $3E, $80 DB $90, $46, $2C, $82, $00, $65, $6D, $00 DB $00, $69, $30, $00, $00, $6A, $6B, $00 DB $00, $6A, $6C, $00, $00, $6A, $6F, $00 DB $00, $31, $68, $00, $00, $6E, $00, $00 DB $00, $33, $00, $00, $00, $46, $33, $00 DB $08, $10, $18, $20, $26, $2A, $32, $38 DB $3C, $44, $48, $4C, $52, $58, $5E, $64 ; "= $2B — use ambient channel LD C, $01 ; C = 1 CP $15 ; CP $15 RET C ; RET C: code < $15 — no sound LOC_9B01: ; LOC_9B01: play sound — SUB_854A (multiply) then BIOS RST $10 strings for stat gains LD A, $03 ; A = 3 — RNG advance count CALL SUB_854A ; SUB_854A: advance RNG 3 times to get sound-rate byte in A INC A ; INC A: bias LD B, A ; B = A (sound channel count) LD A, C RRCA LOC_9B0A: RLCA DJNZ LOC_9B0A AND $07 PUSH AF CALL SUB_9B93 LD HL, $9B40 RST $10 POP AF RRCA PUSH AF JR NC, LOC_9B24 LD HL, $7070 ; RAM $7070 INC (HL) LD HL, $9B5D RST $10 LOC_9B24: POP AF RRCA PUSH AF JR NC, LOC_9B31 LD HL, $706E ; RAM $706E INC (HL) LD HL, $9B6D RST $10 LOC_9B31: POP AF RRCA JR NC, LOC_9B3D LD HL, $706F ; RAM $706F INC (HL) LD HL, $9B81 RST $10 LOC_9B3D: JP SUB_9C35 DB $FD, $88, $59, $4F, $55, $20, $48, $41 DB $56, $45, $20, $45, $41, $52, $4E, $45 ; "VE EARNE" DB $44, $FD, $CB, $41, $20, $20, $42, $4F DB $4E, $55, $53, $21, $FC, $FE, $69, $42 DB $45, $54, $54, $45, $52, $20, $20, $4C ; "ETTER L" DB $55, $43, $4B, $21, $FC, $FE, $C7, $47 DB $52, $45, $41, $54, $45, $52, $20, $53 ; "REATER S" DB $54, $52, $45, $4E, $47, $54, $48, $21 ; "TRENGTH!" DB $FC, $FF, $28, $48, $49, $47, $48, $45 DB $52, $20, $41, $47, $49, $4C, $49, $54 ; "R AGILIT" DB $59, $21, $FC SUB_9B93: ; SUB_9B93: clear HUD VRAM area ($73F6-based, $0300 bytes) and reset display mode LD HL, ($73F6) ; HL = $73F6 (HUD VRAM base address) LD DE, $0300 ; DE = $0300 — 768 bytes (3 tile rows) XOR A ; A = 0 — fill with blank CALL FILL_VRAM ; BIOS FILL_VRAM: blank the HUD area LD C, $01 ; C = 1 — sprite mode CALL SUB_85A8 ; SUB_85A8: set sprite mode + enable display SUB_9BA2: ; SUB_9BA2: render score/level/time HUD labels — RST $10 string, then 3 BCD digit pairs LD HL, $9BD9 ; HL = $9BD9 — HUD label RST $10 string (SCORE/LEVEL/TIME) RST $10 ; RST $10 (WRITER): render HUD label string LD A, ($705B) ; A = $705B (score high BCD byte) CALL VDP_DATA_9BC9 ; VDP_DATA_9BC9: convert BCD byte to 2 ASCII digits, write to DATA_PORT LD A, ($705A) ; A = $705A (score mid BCD byte) CALL VDP_DATA_9BC9 LD A, ($7059) ; A = $7059 (score low BCD byte) CALL VDP_DATA_9BC9 LD HL, $9BE2 RST $10 LD A, ($7058) ; RAM $7058 CALL VDP_DATA_9E35 LD HL, $9BEB RST $10 LD A, ($705C) ; RAM $705C VDP_DATA_9BC9: LD B, A RRCA RRCA RRCA RRCA CALL VDP_DATA_9BD2 LD A, B VDP_DATA_9BD2: AND $0F ADD A, $30 OUT ($BE), A ; DATA_PORT - write VRAM RET DB $FD, $01, $53, $43, $4F, $52, $45, $3A DB $FC, $FD, $0E, $4C, $45, $56, $45, $4C DB $3A, $FC, $54, $49, $4D, $45, $3A, $FC SUB_9BF1: LD HL, ($73F6) ; RAM $73F6 JR LOC_9BFC SUB_9BF6: LD DE, $0020 LD HL, ($7040) ; RAM $7040 LOC_9BFC: ADD HL, DE LD ($7040), HL ; RAM $7040 DB $EB JP VDP_REG_85B4 SUB_9C04: LD HL, $9C1D RST $10 RET SOUND_WRITE_9C09: ; SOUND_WRITE_9C09: sound effect trigger — LD $708C=$FF, RST $10 with effect table at $9C25 LD A, $FF ; A = $FF — sound effect active marker LD ($708C), A ; RAM $708C = $FF (sound effect channel 1 active) LD HL, $9C25 ; HL = $9C25 — sound effect data string RST $10 ; RST $10 (WRITER): trigger sound via WRITER driver RET SOUND_WRITE_9C13: LD A, $FF LD ($708D), A ; RAM $708D LD HL, $9C2D RST $10 RET DB $FF, $A8, $FB, $5F, $9C, $FF, $A8, $FC DB $FF, $C8, $FB, $5F, $9C, $FF, $C8, $FC DB $FF, $E8, $FB, $5F, $9C, $FF, $E8, $FC SUB_9C35: ; SUB_9C35: equipment/status screen — render via RST $10 strings, wait button press (SUB_8504) LD HL, $9C41 ; HL = $9C41 — "PUSH BUTTON TO GO ON" + equipment list string RST $10 ; RST $10 (WRITER): render equipment screen text CALL SUB_8504 ; SUB_8504: wait for fire-button press + release LOC_9C3C: ; LOC_9C3C: render second screen (characteristics) LD HL, $9C58 ; HL = $9C58 — "SELECT WITH JOYSTICK / DROP WITH BUTTON / YOUR EQUIPMENT IS / YOUR CHARACTERISTICS" string RST $10 ; RST $10: render characteristics labels RET DB $FF, $C6, $50, $55, $53, $48, $20, $42 DB $55, $54, $54, $4F, $4E, $20, $54, $4F ; "UTTON TO" DB $20, $47, $4F, $20, $4F, $4E, $FC, $FF DB $C5, $20, $20, $20, $20, $20, $20, $20 DB $20, $20, $20, $20, $20, $20, $20, $20 ; " " DB $20, $20, $20, $20, $20, $20, $20, $FC DB $FD, $46, $53, $45, $4C, $45, $43, $54 DB $20, $57, $49, $54, $48, $20, $4A, $4F ; " WITH JO" DB $59, $53, $54, $49, $43, $4B, $FD, $88 DB $44, $52, $4F, $50, $20, $57, $49, $54 ; "DROP WIT" DB $48, $20, $42, $55, $54, $54, $4F, $4E ; "H BUTTON" DB $FC, $FD, $66, $59, $4F, $55, $20, $41 DB $52, $45, $20, $43, $41, $52, $52, $59 ; "RE CARRY" DB $49, $4E, $47, $3A, $FC, $FD, $66, $59 DB $4F, $55, $52, $20, $45, $51, $55, $49 ; "OUR EQUI" DB $50, $4D, $45, $4E, $54, $20, $49, $53 ; "PMENT IS" DB $3A, $FC, $FD, $66, $59, $4F, $55, $52 DB $20, $43, $48, $41, $52, $41, $43, $54 ; " CHARACT" DB $45, $52, $49, $53, $54, $49, $43, $53 ; "ERISTICS" DB $FD, $C9, $53, $54, $52, $45, $4E, $47 DB $54, $48, $3A, $20, $FC, $FE, $09, $41 DB $47, $49, $4C, $49, $54, $59, $3A, $20 ; "GILITY: " DB $20, $FC, $FE, $49, $4C, $55, $43, $4B DB $3A, $FE, $53, $FC, $FE, $89, $48, $45 DB $41, $4C, $54, $48, $3A, $FE, $93, $FC DB $FE, $C9, $4C, $49, $56, $45, $53, $3A DB $FE, $D3, $FC SUB_9D14: ; SUB_9D14: inventory list renderer — iterate $705E items, call SUB_870A for each item tile CALL SUB_9B93 ; clear HUD and set display mode LD HL, $9C9A ; HL = $9C9A — inventory header RST $10 string RST $10 ; RST $10: render "YOUR EQUIPMENT IS:" header LD A, ($705E) ; A = $705E (inventory item count) LD C, A ; C = item count LD B, $00 ; B = 0 (item index counter) LOC_9D21: ; LOC_9D21: item render loop — iterate B from 0 to C-1 LD A, B ; A = B (current item index) CP C ; CP C: compare to total count RET NC ; RET NC: done when B >= item count PUSH BC LD DE, $3D30 ; DE = $3D30 — item display VRAM address CALL SUB_870A ; SUB_870A: look up item tile code for index B PUSH HL OR A JR NZ, LOC_9D37 LD DE, $00C7 CALL SUB_9BF1 JR LOC_9D3A LOC_9D37: CALL SUB_9BF6 LOC_9D3A: POP HL LD A, L CALL SUB_8600 POP BC INC B JR LOC_9D21 SUB_9D43: ; SUB_9D43: characteristics screen — clear HUD, render STR/AGI/LCK/HEALTH/LIVES with values CALL SUB_9B93 ; clear HUD area LD HL, $9CAE ; HL = $9CAE — "YOUR CHARACTERISTICS: STRENGTH/AGILITY/LUCK/HEALTH/LIVES" label string RST $10 ; RST $10: render characteristics labels LD DE, $00C7 ; DE = $00C7 — VRAM offset for stat values CALL SUB_9BF1 ; SUB_9BF1: position cursor to stat value area LD A, ($7077) ; A = $7077 (display STRENGTH value) CP $05 PUSH AF JR C, LOC_9D5A LD A, $05 LOC_9D5A: LD DE, $9922 CALL SUB_86DD LD A, (DE) CALL SUB_8600 POP AF CALL NC, VDP_DATA_9DFE CALL SUB_9BF6 LD A, ($7078) ; RAM $7078 CP $05 PUSH AF JR C, LOC_9D75 LD A, $05 LOC_9D75: LD DE, $9927 CALL SUB_86DD LD A, (DE) CALL SUB_8600 POP AF CALL NC, VDP_DATA_9DFE CALL SUB_9BF6 LD A, ($7079) ; RAM $7079 OR A JR Z, LOC_9DA1 CP $03 PUSH AF JR C, LOC_9D93 LD A, $03 LOC_9D93: LD DE, $992C CALL SUB_86DD LD A, (DE) CALL SUB_8600 POP AF CALL NC, VDP_DATA_9DFE LOC_9DA1: CALL SUB_9BF6 LD A, ($707A) ; RAM $707A OR A JR Z, LOC_9DBF CP $02 PUSH AF JR C, LOC_9DB1 LD A, $02 LOC_9DB1: LD DE, $992F CALL SUB_86DD LD A, (DE) CALL SUB_8600 POP AF CALL NC, VDP_DATA_9DFE LOC_9DBF: CALL SUB_9BF6 LD HL, $7081 ; RAM $7081 BIT 4, (HL) JR Z, LOC_9DCE LD A, $1A CALL SUB_8600 LOC_9DCE: CALL SUB_9BF6 LD HL, $7081 ; RAM $7081 BIT 3, (HL) JR Z, LOC_9DDD LD A, $06 CALL SUB_8600 LOC_9DDD: CALL SUB_9BF6 LD A, ($707C) ; RAM $707C OR A JR Z, LOC_9DEE CALL VDP_DATA_9E35 LD A, $07 CALL SUB_8600 LOC_9DEE: CALL SUB_9BF6 LD A, ($707D) ; RAM $707D OR A RET Z CALL VDP_DATA_9E35 LD A, $16 JP SUB_8600 VDP_DATA_9DFE: LD A, $2B OUT ($BE), A ; DATA_PORT - write VRAM RET ; ============================================================================= ; STATS HUD RENDERER -- SUB_9E03 ($9E03) ; Writes the player's five RPG stats to the VRAM HUD area each frame. ; For each stat it calls VDP_DATA_9E35, which converts a byte value to two ; decimal digits (tens / units) and OUTs them to DATA_PORT ($BE). ; $9CC3 label -> $706E (STRENGTH display) ; $9CE6 label -> $706F (AGILITY display) ; $9CF3 label -> $7070 (LUCK display) ; $9CFD label -> $7071 (HEALTH display, computed = STRENGTH+AGILITY+LUCK) ; $9D09 label -> $7072 (LIVES display) ; VDP_DATA_9E35 ($9E35): divides A by 10 repeatedly (INC B / SUB $0A loop), ; leaving quotient in B and remainder+$30 (ASCII) in A. Outputs both digits ; via OUT ($BE). ; ============================================================================= SUB_9E03: ; SUB_9E03: render all 5 stats (STR/AGI/LCK/HEALTH/LIVES) to VRAM HUD each frame CALL SUB_9B93 ; clear HUD area and reset display LD HL, $9CC3 ; HL = $9CC3 — "STRENGTH:" label RST $10 string RST $10 ; RST $10 (WRITER): render STRENGTH label LD A, ($706E) ; A = $706E (STRENGTH stat value) CALL VDP_DATA_9E35 ; VDP_DATA_9E35: convert byte to 2 decimal digits -> OUT $BE LD HL, $9CE6 ; HL = $9CE6 — "AGILITY:" label string RST $10 ; RST $10: render AGILITY label LD A, ($706F) ; A = $706F (AGILITY stat value) CALL VDP_DATA_9E35 ; VDP_DATA_9E35: display AGILITY LD HL, $9CF3 ; HL = $9CF3 — "LUCK:" label RST $10 ; RST $10: render LUCK label LD A, ($7070) ; A = $7070 (LUCK stat value) CALL VDP_DATA_9E35 ; VDP_DATA_9E35: display LUCK LD HL, $9CFD ; HL = $9CFD — "HEALTH:" label RST $10 ; RST $10: render HEALTH label LD A, ($7071) ; A = $7071 (HEALTH = STR+AGI+LCK) CALL VDP_DATA_9E35 ; VDP_DATA_9E35: display HEALTH LD HL, $9D09 ; HL = $9D09 — "LIVES:" label RST $10 ; RST $10: render LIVES label LD A, ($7072) ; A = $7072 (LIVES remaining) VDP_DATA_9E35: ; VDP_DATA_9E35: byte -> 2 decimal digits -> DATA_PORT; B=tens digit, A=units digit (both ASCII) LD B, $2F ; B = $2F (used as tens counter; INC B increments it from $30) LOC_9E37: ; LOC_9E37: repeated INC B / SUB $0A loop — divides A by 10, quotient in B INC B ; INC B: count tens digit SUB $0A ; SUB $0A: subtract 10 JR NC, LOC_9E37 ; JR NC: keep subtracting while A >= 10 ADD A, $3A ; ADD A,$3A: remainder + $3A = units ASCII digit ($30 + remainder) PUSH BC ; PUSH BC: save tens digit in B LD B, A ; B = A: units digit (ASCII) POP AF ; POP AF: A = tens digit CP $30 ; CP $30: is tens digit "0"? JR Z, LOC_9E49 ; JR Z: leading zero — skip tens digit output OUT ($BE), A ; OUT $BE: write tens digit to VDP data port PUSH AF POP AF LOC_9E49: ; LOC_9E49: always write units digit LD A, B ; A = B: units digit OUT ($BE), A ; OUT $BE: write units digit to VDP data port LD HL, $9C6E ; HL = $9C6E — RST $10 string (separator/padding after digit) RST $10 ; RST $10 (WRITER): output separator character RET SUB_9E51: ; SUB_9E51: tile collision / door exit check — scan $0F tiles for code match, trigger room transition LD BC, ($7052) ; BC = $7052 (tile position word) RES 0, C ; RES 0,C: align to even tile boundary LD A, $0F ; A = $0F — scan $0F (15) tile positions LOC_9E59: ; LOC_9E59: scan loop — read tile at address DE, compare to player tile LD DE, $3C00 ; DE = $3C00 — VRAM tile display address CALL VDP_DATA_8720 ; VDP_DATA_8720: read tile value at DE OR A ; OR A: set flags on read tile value SBC HL, BC ; SBC HL,BC: compare tile address to player position BC JR Z, LOC_9E68 ; JR Z: addresses match — player on this tile DEC A ; DEC A: decrement scan counter RET M ; RET M: scanned all tiles — return (no match) JR LOC_9E59 ; JR LOC_9E59: check next tile LOC_9E68: ; LOC_9E68: tile match — check if exit/door tile and trigger transition LD DE, $3C00 ; DE = $3C00 CALL VDP_DATA_8730 ; VDP_DATA_8730: read tile type byte LD DE, $3C20 ; DE = $3C20 — exit tile lookup address CALL SUB_870A ; SUB_870A: check exit tile table LD H, $00 ADD HL, HL PUSH HL LD DE, $9F87 ADD HL, DE LD B, (HL) INC HL LD C, (HL) PUSH BC CALL SOUND_WRITE_9C13 POP BC PUSH BC LD A, B CALL SUB_9FA7 POP BC LD A, C CALL SUB_9FA7 LD HL, $706B ; RAM $706B SET 7, (HL) LD HL, $7056 ; RAM $7056 LD A, (HL) AND $40 OR $8B LD (HL), A POP HL LD DE, $9F97 ADD HL, DE LD E, (HL) INC HL LD D, (HL) PUSH DE LD B, $06 RST $28 LD B, $0A RST $28 LD B, $0B RST $28 LD B, $0C RST $28 RET DB $3A, $70, $70, $FE, $05, $30, $11, $C6 DB $05, $11, $00, $0A, $43, $CD, $24, $85 DB $3E, $64, $CD, $4A, $85, $BD, $30, $22 DB $06, $10, $78, $3D, $11, $00, $3C, $CD DB $20, $87, $11, $48, $70, $1A, $BD, $30 DB $0F, $13, $1A, $BC, $30, $0A, $13, $1A DB $BD, $38, $05, $13, $1A, $BC, $30, $02 DB $10, $E0, $78, $3D, $C9, $CD, $05, $AF DB $CD, $B9, $90, $25, $CD, $E2, $86, $FE DB $8B, $20, $F5, $22, $52, $70, $E5, $CD DB $15, $9F, $E1, $78, $FE, $2D, $30, $E8 DB $79, $FE, $61, $30, $E3, $CD, $E2, $87 DB $C3, $54, $92 SUB_9F15: ; SUB_9F15: calc player scroll offset — HL=combined tile pos -> $7050/$70CA/$7054 LD A, H ; LOC_9F1B: clamp scroll X offset SUB $0A JR NC, LOC_9F1B XOR A LOC_9F1B: ; LOC_9F21: compute VRAM scroll base address $70CA from $7050 CP $2C JR C, LOC_9F21 LD A, $2C LOC_9F21: ; LOC_9F28: clamp scroll Y offset LD B, A LD A, L SUB $10 JR NC, LOC_9F28 XOR A LOC_9F28: ; LOC_9F2E: compute final scroll offsets and update $7054/$70CA CP $70 JR C, LOC_9F2E LD A, $70 LOC_9F2E: LD C, A LD ($7050), BC ; RAM $7050 OR A SBC HL, BC INC H ADD HL, HL ADD HL, HL ADD HL, HL LD A, H LD H, L LD L, A LD ($70CA), HL ; RAM $70CA LD ($7054), HL ; RAM $7054 RET DB $3E, $03, $CD, $4A, $85, $18, $05, $3E DB $07, $CD, $4A, $85, $3C, $C3, $B2, $AE DB $3E, $05, $32, $84, $70, $C9, $3E, $03 DB $32, $85, $70, $C9, $21, $71, $70, $CB DB $3E, $3E, $FF, $CD, $DA, $A3, $AF, $32 DB $7B, $70, $C9, $21, $71, $70, $7E, $CB DB $3E, $32, $82, $70, $3E, $3C, $32, $86 DB $70, $21, $6E, $70, $7E, $36, $01, $32 DB $83, $70, $C9, $21, $29, $22, $29, $23 DB $29, $24, $29, $10, $25, $26, $29, $27 DB $29, $28, $29, $44, $9F, $4B, $9F, $EF DB $9E, $54, $9F, $5A, $9F, $60, $9F, $6F DB $9F, $F3, $AE SUB_9FA7: OR A RET Z DEC A LD DE, $0500 CALL DELAY_LOOP_8524 LD DE, $9FFD ADD HL, DE LD E, (HL) INC HL LD D, (HL) LD B, $09 JR LOC_9FCA LOC_9FBB: RR D RR E DEC C JR Z, LOC_9FCA DJNZ LOC_9FBB INC HL LD D, (HL) LD B, $08 JR LOC_9FBB LOC_9FCA: LD A, E AND $1F JR Z, LOC_9FF8 OR $60 CP $7B JR NZ, LOC_9FD7 LD A, $3F LOC_9FD7: CP $7C JR NZ, LOC_9FDD LD A, $32 LOC_9FDD: CP $7D JR NZ, LOC_9FE3 LD A, $21 LOC_9FE3: CP $7E JR NZ, LOC_9FE9 LD A, $2D LOC_9FE9: CP $7F JR NZ, LOC_9FEF LD A, $20 LOC_9FEF: OUT ($BE), A ; DATA_PORT - write VRAM LD C, $05 DEC B LD A, B CP C JR NZ, LOC_9FBB LOC_9FF8: LD A, $20 OUT ($BE), A ; DATA_PORT - write VRAM RET DB $F3, $86, $06, $01, $00, $32, $50, $00 DB $00, $00, $27, $48, $5A, $24, $00, $D3 DB $85, $55, $00, $00, $A6, $BA, $53, $27 DB $00, $22, $50, $00, $00, $00, $23, $D8 DB $02, $00, $00, $2C, $C8, $53, $00, $00 DB $93, $A5, $56, $00, $00, $13, $26, $52 DB $24, $00, $07, $BD, $CA, $00, $00, $EF DB $C8, $02, $00, $00, $E7, $09, $96, $1C DB $00, $27, $05, $47, $01, $00, $61, $42 DB $00, $00, $00, $F0, $A5, $F9, $1C, $00 DB $AD, $B6, $96, $01, $00, $50, $A6, $32 DB $29, $00, $32, $88, $44, $00, $00, $2D DB $34, $11, $00, $00, $ED, $31, $02, $00 DB $00, $07, $BD, $49, $01, $00, $36, $34 DB $98, $64, $01, $14, $A5, $62, $00, $00 DB $03, $A5, $62, $00, $00, $2C, $8C, $55 DB $32, $00, $37, $48, $99, $9E, $04, $44 DB $86, $F3, $1C, $00, $2C, $D9, $E4, $0E DB $00, $93, $06, $5A, $0B, $00, $37, $E9 DB $20, $09, $00, $82, $25, $B7, $92, $3B DB $30, $51, $00, $00, $00, $93, $3E, $57 DB $00, $00, $B4, $B0, $02, $9F, $A4, $46 DB $96, $A2, $0B, $00, $AE, $14, $C2, $0A DB $00, $A3, $CA, $59, $08, $00, $B7, $84 DB $E5, $CA, $9C, $A4, $04, $8A, $00, $00 DB $54, $06, $08, $00, $00, $AC, $04, $8A DB $8A, $04, $AB, $E4, $09, $00, $00, $41 DB $B6, $27, $01, $00, $24, $9C, $53, $24 DB $00, $B3, $04, $39, $10, $00, $33, $30 DB $5B, $00, $00, $89, $96, $06, $00, $00 DB $AE, $60, $0A, $00, $00, $E2, $5D, $00 DB $00, $00, $41, $CA, $77, $27, $00, $13 DB $3D, $49, $01, $00, $EC, $8D, $40, $0B DB $00, $93, $56, $07, $00, $00, $B3, $05 DB $C6, $00, $00, $13, $A5, $C2, $08, $00 DB $03, $85, $E4, $00, $00, $2D, $40, $00 DB $00, $00, $A8, $04, $96, $DC, $01, $F0 DB $D1, $F4, $1C, $00, $E3, $39, $53, $67 DB $01, $13, $16, $C6, $00, $00, $EC, $B9 DB $03, $00, $00, $2C, $C8, $53, $00, $00 DB $AC, $8E, $05, $00, $00, $03, $05, $D9 DB $00, $00, $E1, $24, $96, $68, $06, $A1 DB $55, $56, $28, $00, $A6, $04, $09, $00 DB $00, $2D, $9C, $34, $00, $00, $24, $CD DB $20, $1B, $00, $A8, $B0, $06, $00, $00 DB $30, $C8, $C0, $B2, $2E, $27, $54, $47 DB $59, $A1, $DC, $A3, $E0, $48, $21, $42 DB $96, $30, $29, $00, $87, $85, $39, $01 DB $00, $93, $CA, $E2, $0E, $45, $37, $38 DB $02, $00, $00, $43, $BE, $39, $01, $00 DB $50, $3E, $5A, $06, $05, $90, $05, $5A DB $00, $00, $26, $C9, $02, $00, $00, $82 DB $85, $49, $01, $00, $B2, $18, $56, $06 DB $05, $93, $06, $63, $00, $00, $F3, $3E DB $49, $00, $00, $AC, $04, $02, $00, $00 DB $49, $3E, $07, $00, $00, $42, $3E, $A7 DB $0B, $00, $33, $31, $5B, $24, $00, $E7 DB $31, $52, $1C, $00, $AA, $5C, $56, $08 DB $00, $AE, $8C, $C5, $C2, $28, $03, $95 DB $49, $01, $00, $E3, $19, $53, $24, $00 DB $03, $05, $96, $46, $01, $73, $14, $48 DB $65, $01, $43, $BE, $EB, $00, $00, $90 DB $85, $58, $0B, $00, $B0, $4E, $F4, $E9 DB $03, $F4, $BD, $DF, $82, $CB, $89, $96 DB $36, $3B, $00, $AC, $D8, $C2, $00, $00 DB $44, $3E, $08, $00, $00, $03, $95, $B1 DB $00, $00, $B3, $42, $C8, $52, $99, $93 DB $06, $5A, $27, $00, $E3, $39, $93, $64 DB $DB, $26, $1D, $44, $01, $00, $B7, $04 DB $F8, $DC, $04, $3A, $7F, $70, $B7, $C0 DB $21, $80, $70, $CB, $66, $C0, $CB, $EE DB $11, $7D, $70, $18, $10, $3A, $7F, $70 DB $B7, $C0, $21, $80, $70, $CB, $66, $C0 DB $CB, $AE, $11, $7C, $70, $CB, $E6, $1A DB $3D, $12, $20, $07, $CD, $04, $9C, $AF DB $32, $6C, $70, $06, $06, $EF, $06, $0A DB $EF, $06, $25, $EF, $06, $26, $EF, $11 DB $B4, $A2, $18, $22, $21, $7F, $70, $7E DB $B7, $C0, $3A, $80, $70, $CB, $67, $C0 DB $06, $06, $EF, $06, $0A, $EF, $CD, $34 DB $85, $E6, $06, $C6, $10, $47, $C5, $EF DB $C1, $04, $EF, $11, $AC, $A2, $21, $7F DB $70, $36, $07, $3A, $67, $70, $07, $CD DB $DD, $86, $2A, $CA, $70, $1A, $84, $67 DB $13, $1A, $85, $6F, $22, $DA, $70, $3E DB $01, $11, $40, $3D, $C3, $02, $87, $08 DB $01, $00, $F2, $FB, $00, $06, $0A, $08 DB $01, $00, $F4, $F8, $01, $00, $0A, $CD DB $04, $9C, $3E, $2E, $32, $6C, $70, $C3 DB $00, $86, $CD, $F5, $A2, $CD, $43, $9D DB $18, $0E, $CD, $F5, $A2, $CD, $03, $9E DB $18, $06, $CD, $F5, $A2, $CD, $14, $9D DB $CD, $35, $9C, $CD, $93, $9B, $0E, $0C DB $CD, $A8, $85, $21, $80, $70, $CB, $C6 DB $AF, $32, $6C, $70, $32, $C4, $70, $C9 DB $3E, $05, $18, $F8, $CD, $F5, $A2, $CD DB $BF, $99, $18, $DF, $3A, $7B, $70, $C6 DB $05, $32, $78, $70, $C9, $3E, $03, $CD DB $2D, $A3, $32, $8B, $70, $C3, $C0, $A4 DB $3E, $03, $C3, $DA, $A3, $06, $03, $78 DB $CD, $17, $AA, $7E, $FE, $D8, $3E, $7F DB $C4, $65, $AE, $10, $F2, $C3, $C0, $A4 DB $57, $1E, $00, $3A, $70, $70, $21, $7B DB $70, $86, $CD, $24, $85, $7D, $C9, $3E DB $05, $CD, $2D, $A3, $32, $8A, $70, $0E DB $20, $C3, $A1, $A4, $3E, $04, $32, $78 DB $70, $C9, $0E, $00, $3E, $03, $32, $77 DB $70, $CD, $34, $85, $E6, $03, $20, $02 DB $3E, $04, $FE, $03, $20, $02, $3E, $08 DB $47, $A1, $20, $ED, $78, $B1, $4F, $78 DB $0F, $30, $0F, $3E, $01, $21, $81, $70 DB $CB, $6E, $28, $01, $3C, $32, $77, $70 DB $18, $1C, $0F, $30, $0C, $21, $71, $70 DB $CB, $3E, $21, $76, $70, $CB, $3E, $18 DB $0D, $0F, $30, $06, $AF, $32, $7B, $70 DB $18, $04, $AF, $32, $70, $70, $79, $FE DB $0F, $C8, $CD, $34, $85, $E6, $22, $28 DB $B0, $C9, $3A, $7B, $70, $4F, $C6, $05 DB $32, $77, $70, $21, $78, $70, $7E, $81 DB $3C, $77, $C9, $3A, $7B, $70, $C6, $02 DB $32, $7A, $70, $C9, $3E, $0A, $CD, $2D DB $A3, $32, $89, $70, $C3, $C0, $A4, $CD DB $C0, $A4, $C3, $EF, $9E, $21, $81, $70 DB $CB, $EE, $C9, $3E, $01, $32, $7B, $70 DB $4F, $21, $7A, $70, $7E, $FE, $02, $38 DB $04, $79, $C6, $02, $77, $21, $78, $70 DB $7E, $FE, $05, $38, $04, $79, $C6, $05 DB $77, $21, $79, $70, $7E, $FE, $03, $38 DB $04, $79, $C6, $03, $77, $21, $77, $70 DB $7E, $FE, $05, $D8, $79, $C6, $05, $77 DB $21, $78, $70, $7E, $81, $3C, $77, $C9 DB $3A, $7B, $70, $C6, $03, $32, $79, $70 DB $C9, $21, $81, $70, $CB, $56, $C0, $CB DB $D6, $21, $6E, $70, $18, $50, $3E, $03 DB $32, $78, $70, $C9, $3E, $04, $32, $77 DB $70, $C9, $21, $81, $70, $CB, $E6, $C9 DB $0E, $20, $C3, $A1, $A4, $3E, $01, $32 DB $7A, $70, $C9, $CD, $B2, $9E, $3C, $C8 DB $3D, $11, $00, $3C, $21, $00, $00, $CD DB $30, $87, $18, $67, $21, $7D, $70, $C3 DB $08, $A5, $0E, $08, $18, $3E, $21, $81 DB $70, $CB, $4E, $C0, $CB, $CE, $21, $6F DB $70, $18, $0B, $21, $81, $70, $CB, $46 DB $C0, $CB, $C6, $21, $70, $70, $7E, $C6 DB $04, $77, $C9, $3E, $02, $32, $79, $70 DB $C9, $3E, $03, $32, $77, $70, $C9, $3A DB $70, $70, $21, $7B, $70, $86, $32, $88 DB $70, $21, $79, $70, $7E, $C6, $08, $77 DB $18, $21, $0E, $10, $06, $03, $78, $CD DB $17, $AA, $7E, $FE, $D8, $28, $12, $78 DB $11, $5C, $3D, $D5, $CD, $0A, $87, $D1 DB $7D, $E6, $C7, $B1, $6F, $78, $CD, $14 DB $87, $10, $E3, $06, $09, $EF, $06, $07 DB $EF, $C9, $3E, $02, $32, $78, $70, $C9 DB $3E, $02, $32, $79, $70, $C9, $3A, $70 DB $70, $21, $6F, $70, $86, $21, $7B, $70 DB $86, $CB, $3F, $32, $87, $70, $18, $DB DB $3A, $76, $70, $32, $71, $70, $AF, $32 DB $85, $70, $21, $80, $70, $CB, $BE, $3A DB $86, $70, $B7, $C8, $3E, $01, $32, $86 DB $70, $C9, $3E, $02, $32, $77, $70, $C9 DB $21, $7C, $70, $E5, $CD, $34, $85, $E1 DB $E6, $03, $C6, $05, $86, $FE, $64, $38 DB $02, $3E, $63, $77, $C9, $21, $81, $70 DB $CB, $DE, $C9, $2A, $48, $70, $ED, $5B DB $4A, $70, $45, $0E, $00, $CD, $53, $A5 DB $6B, $CD, $53, $A5, $68, $24, $7C, $BA DB $38, $F3, $2A, $48, $70, $44, $CD, $53 DB $A5, $62, $CD, $53, $A5, $60, $2C, $7D DB $BB, $38, $F3, $79, $B7, $CA, $C0, $A4 DB $06, $04, $EF, $C3, $B3, $89, $CD, $E2 DB $86, $FE, $89, $C0, $3E, $80, $C3, $42 DB $88, $3A, $64, $70, $B7, $C0, $CD, $B2 DB $9E, $3C, $CA, $C0, $A4, $3D, $11, $00 DB $3C, $CD, $20, $87, $22, $62, $70, $CD DB $E2, $86, $32, $60, $70, $2C, $CD, $E2 DB $86, $32, $61, $70, $2D, $3E, $9C, $CD DB $D9, $90, $3E, $14, $32, $64, $70, $3E DB $05, $32, $65, $70, $06, $0D, $EF, $06 DB $0E, $EF, $C3, $B3, $89, $3A, $67, $70 DB $2A, $52, $70, $0E, $00, $B7, $28, $45 DB $3D, $28, $2A, $3D, $28, $51, $24, $CD DB $E2, $86, $FE, $80, $28, $07, $24, $CD DB $E2, $86, $FE, $80, $C0, $2A, $4A, $70 DB $3A, $48, $70, $95, $2F, $47, $2D, $CD DB $E2, $86, $FE, $80, $3E, $8A, $CC, $42 DB $88, $10, $F3, $18, $51, $25, $CD, $E2 DB $86, $FE, $80, $28, $07, $25, $CD, $E2 DB $86, $FE, $80, $C0, $2A, $4A, $70, $3A DB $49, $70, $67, $18, $D3, $2C, $CD, $E2 DB $86, $FE, $80, $28, $05, $2C, $CD, $E2 DB $86, $C0, $2A, $4A, $70, $18, $14, $2D DB $CD, $E2, $86, $FE, $80, $28, $05, $2D DB $CD, $E2, $86, $C0, $2A, $4A, $70, $3A DB $48, $70, $6F, $3A, $49, $70, $94, $2F DB $47, $25, $CD, $E2, $86, $FE, $80, $3E DB $8A, $CC, $42, $88, $10, $F3, $79, $B7 DB $C8, $06, $08, $EF, $06, $05, $EF, $C3 DB $B3, $89 LOC_A62F: RLCA LD E, A LD D, $00 LD HL, $A63A ADD HL, DE LD E, (HL) INC HL LD D, (HL) DB $EB JP (HL) DB $9A, $A5, $00, $00, $00, $00, $5E, $A5 DB $20, $A5, $1A, $A5, $05, $A5, $FF, $A4 DB $E5, $A4, $D3, $A4, $CD, $A4, $C7, $A4 DB $02, $92, $E5, $A4, $9F, $A4, $8C, $A4 DB $86, $A4, $80, $A4, $70, $A4, $63, $A4 DB $5F, $A4, $59, $A4, $48, $A4, $42, $A4 DB $3D, $A4, $37, $A4, $31, $A4, $2B, $A4 DB $E5, $A4, $1E, $A4, $15, $A4, $D8, $A3 DB $D2, $A3, $CC, $A3, $C1, $A3, $B8, $A3 DB $A7, $A3, $4F, $A3, $49, $A3, $E5, $A4 DB $3C, $A3, $1A, $A3, $15, $A3, $0A, $A3 DB $01, $A3, $54, $80, $F9, $A2, $D7, $A2 DB $CF, $A2, $C7, $A2, $BC, $A2, $69, $A2 DB $3A, $A2, $28, $A2 SUB_A6A8: LD C, A CALL SUB_AA17 LD IX, SUB_A9DA CALL SUB_A966 LD ($7044), A ; RAM $7044 LD A, C LD DE, $3D48 CALL SUB_870A LD A, L LD ($7040), A ; RAM $7040 LD A, C LD DE, $3D5C CALL SUB_870A LD A, L LD ($7043), A ; RAM $7043 RRCA RRCA RRCA AND $07 LD ($7041), A ; RAM $7041 CP $04 RET Z CP $03 JP Z, LOC_A7D6 CP $06 JP Z, LOC_A795 LD A, C LD DE, $3D70 CALL SUB_870A LD A, L OR A JR NZ, LOC_A6F2 DEC A LD ($7040), A ; RAM $7040 JR LOC_A70B LOC_A6F2: DEC A LD L, A LD A, C LD DE, $3D70 CALL LOC_8714 LD A, ($7044) ; RAM $7044 OR A JP Z, LOC_A7AE CALL SUB_A861 CALL LOC_A7AE CALL SUB_A861 LOC_A70B: LD A, C CALL SUB_AA17 LD A, ($70CA) ; RAM $70CA SUB (HL) LD E, $03 JR NC, LOC_A71B LD E, $01 NEG LOC_A71B: LD B, A LD A, ($70CB) ; RAM $70CB INC HL SUB (HL) LD D, $00 JR NC, LOC_A729 LD D, $02 NEG LOC_A729: CP B PUSH AF OR B LD ($7042), A ; RAM $7042 POP AF LD A, E JR C, LOC_A734 LD A, D LOC_A734: LD HL, $7040 ; RAM $7040 CP (HL) LD B, A JR Z, LOC_A742 LD A, ($7044) ; RAM $7044 OR A LD A, B JR Z, LOC_A748 LOC_A742: BIT 0, (HL) LD A, E JR Z, LOC_A748 LD A, D LOC_A748: LD ($7040), A ; RAM $7040 LD A, $08 CALL SUB_854A INC A LD L, A LD A, C LD DE, $3D70 CALL LOC_8714 LD A, ($7041) ; RAM $7041 OR A JR Z, LOC_A7AE CP $02 JR NZ, LOC_A774 LD L, $04 LD A, C LD DE, $3D70 CALL LOC_8714 CALL SUB_8534 RLCA JR C, LOC_A795 JR LOC_A7AE LOC_A774: CP $01 JR NZ, LOC_A77D LOC_A778: CALL SUB_A861 JR LOC_A7AE LOC_A77D: LD A, ($7042) ; RAM $7042 CP $40 LD A, ($7043) ; RAM $7043 JR NC, LOC_A789 SUB $02 LOC_A789: AND $07 LD L, A LD A, C LD DE, $3D44 CALL LOC_8714 JR LOC_A7AE LOC_A795: LD A, ($7044) ; RAM $7044 OR A JR NZ, LOC_A778 CALL SUB_8534 RRCA JR C, LOC_A7AE RRCA LD HL, $7040 ; RAM $7040 LD A, (HL) DEC A JR C, LOC_A7AB INC A INC A LOC_A7AB: AND $03 LD (HL), A LOC_A7AE: LD A, C LD HL, $7040 ; RAM $7040 LD L, (HL) LD DE, $3D48 CALL LOC_8714 DB $EB CALL SUB_AA17 INC E DEC E LD D, $02 JR Z, LOC_A7D3 DEC E LD D, $FE JR Z, LOC_A7CF DEC E JR Z, LOC_A7D3 DEC E RET NZ LD D, $02 LOC_A7CF: LD A, (HL) ADD A, D LD (HL), A RET LOC_A7D3: INC HL JR LOC_A7CF LOC_A7D6: CALL SUB_8534 CP $08 JR NC, LOC_A795 LD HL, ($704A) ; RAM $704A LD DE, $0202 OR A SBC HL, DE LD DE, ($7048) ; RAM $7048 SBC HL, DE LD A, H CALL SUB_854A INC A ADD A, D LD D, A LD A, L CALL SUB_854A INC A ADD A, E LD HL, ($7050) ; RAM $7050 SUB L CP $20 JR NC, LOC_A795 LD E, A LD A, D SUB H LD D, A DB $EB LD A, C CALL SUB_A8E3 LD A, C CALL SUB_AA17 LD B, C SUB_A80F: LD A, (HL) CP $0A JR C, LOC_A82A INC HL PUSH HL INC HL LD D, A LD A, (HL) CALL SUB_AA21 POP HL ADD A, D CP $A6 JR NC, LOC_A82A LD A, (HL) CP $02 JR C, LOC_A82A CP $F6 RET C LOC_A82A: LD A, B CALL SUB_AA17 LD D, (HL) LD (HL), $D8 INC HL LD E, (HL) LD A, D RLCA RLCA RLCA XOR E AND $38 XOR E LD (HL), A LD A, E BIT 7, C JR Z, LOC_A843 ADD A, $08 LOC_A843: AND $F8 RRCA RRCA RRCA LD E, A LD A, D AND $F8 RRCA RRCA RRCA DEC A LD D, A LD HL, ($7050) ; RAM $7050 ADD HL, DE BIT 7, C JR Z, LOC_A85A DEC L LOC_A85A: LD A, B LD DE, $3D7D JP VDP_DATA_8730 SUB_A861: LD HL, $7040 ; RAM $7040 LD A, (HL) XOR $02 LD (HL), A RET SUB_A869: LD HL, ($70DA) ; RAM $70DA LD A, L CP $08 JR C, SUB_A892 CP $A0 JR NC, SUB_A892 LD A, H CP $02 JR C, SUB_A892 CP $F6 JR NC, SUB_A892 LD DE, $0702 ADD HL, DE LD D, L LD E, H CALL SUB_AA01 CALL VDP_REG_86E8 LD A, ($7080) ; RAM $7080 LD B, A CALL SUB_A9DA RET NC SUB_A892: LD A, $D8 LD ($70DA), A ; RAM $70DA LD HL, $7080 ; RAM $7080 RES 4, (HL) RET SUB_A89D: INC HL LD C, (HL) INC HL LD A, (HL) EX AF, AF' INC HL LD A, (HL) OR A RET Z LD A, B LD DE, $3D7D CALL VDP_DATA_8720 LD DE, ($7050) ; RAM $7050 OR A SBC HL, DE LD A, L CP $1F RET NC LD A, H CP $14 RET NC INC H ADD HL, HL ADD HL, HL ADD HL, HL LD A, C RRCA RRCA RRCA AND $07 ADD A, H LD H, A CP $0A RET C PUSH HL EX AF, AF' CALL SUB_AA21 POP HL ADD A, H CP $A6 RET NC LD A, C AND $07 ADD A, L LD L, A CP $F6 RET NC CP $02 RET C LD A, B JR LOC_A8E7 SUB_A8E3: INC H ADD HL, HL ADD HL, HL ADD HL, HL LOC_A8E7: DB $EB CALL SUB_AA17 LD (HL), D INC HL LD (HL), E RET DELAY_LOOP_A8EF: PUSH BC LD C, B LD B, $20 LOC_A8F3: LD A, B DEC A LD DE, $3CF0 CALL VDP_DATA_8720 INC L DEC L JR Z, LOC_A902 DJNZ LOC_A8F3 RET LOC_A902: DEC B LD HL, ($7048) ; RAM $7048 PUSH HL LD HL, ($704A) ; RAM $704A PUSH HL LD A, C LD DE, $3D7D CALL VDP_DATA_8720 CALL SUB_8807 JR NZ, LOC_A92D INC L CALL SUB_8807 JR NZ, LOC_A92D DEC L DEC L CALL SUB_8807 JR NZ, LOC_A92D INC L INC H CALL SUB_8807 JR NZ, LOC_A92D DEC H DEC H LOC_A92D: CALL SUB_87E2 LD HL, ($7048) ; RAM $7048 LD A, B LD DE, $3CF0 CALL VDP_DATA_8730 POP HL LD ($704A), HL ; RAM $704A POP HL LD ($7048), HL ; RAM $7048 LD A, C LD DE, $3D58 CALL SUB_870A LD A, B LD DE, $3CD0 CALL LOC_8714 LD A, C POP BC SUB_A952: ; SUB_A952: sprite position update — advance one sprite by one step toward target PUSH AF CALL SUB_AA17 LD (HL), $D8 INC HL INC HL INC HL LD (HL), $00 LD L, $00 LD DE, $3D78 POP AF JP LOC_8714 SUB_A966: LD D, (HL) INC HL LD E, (HL) INC HL LD A, (HL) CALL SUB_AA21 INC A LD B, A LD A, E CP $02 JR C, LOC_A9D7 CP $F6 JR NC, LOC_A9D7 AND $07 PUSH AF LD A, D CP $0A JR C, LOC_A9D6 ADD A, B CP $A6 JR NC, LOC_A9D6 SUB B AND $07 ADD A, B LD ($7044), A ; RAM $7044 CALL SUB_AA01 CALL SUB_802A JR C, LOC_A9D6 INC HL POP AF PUSH AF JR Z, LOC_A99F CALL SUB_802A JR C, LOC_A9D6 LOC_A99F: LD A, ($7044) ; RAM $7044 CP $09 JR C, LOC_A9D3 LD DE, $001F ADD HL, DE CALL SUB_802A JR C, LOC_A9D6 INC HL POP AF PUSH AF JR Z, LOC_A9B9 CALL SUB_802A JR C, LOC_A9D6 LOC_A9B9: LD A, ($7044) ; RAM $7044 CP $11 JR C, LOC_A9D3 LD DE, $001F ADD HL, DE CALL SUB_802A JR C, LOC_A9D6 INC HL POP AF PUSH AF JR Z, LOC_A9D3 CALL SUB_802A JR C, LOC_A9D6 LOC_A9D3: POP AF XOR A RET LOC_A9D6: POP AF LOC_A9D7: XOR A DEC A RET SUB_A9DA: LD A, (HL) CP $8A RET C CP $C0 CCF RET SUB_A9E2: CALL SUB_AA17 LD D, (HL) INC HL LD E, (HL) LD HL, $0604 ADD HL, DE LD A, L AND $F8 RRCA RRCA RRCA LD L, A LD A, H AND $F8 RRCA RRCA RRCA DEC A LD H, A LD DE, ($7050) ; RAM $7050 ADD HL, DE RET SUB_AA01: LD A, D SUB $08 AND $F8 LD L, A LD A, E AND $F8 RRCA RRCA RRCA LD H, $00 ADD HL, HL ADD HL, HL LD DE, $70DF ; RAM $70DF ADD HL, DE JR SUB_AA1C SUB_AA17: RLCA RLCA LD HL, $70CA ; RAM $70CA SUB_AA1C: ADD A, L LD L, A RET NC INC H RET SUB_AA21: RRCA LD HL, $9505 CALL SUB_AA1C LD A, (HL) DEC HL DEC HL SUB (HL) RET DB $06, $00, $04, $01, $02, $03, $05, $7E DB $E6, $BF, $FE, $8A, $C9 SUB_AA3A: ; SUB_AA3A: enemy/object tick — iterate all objects: AI move, animate, collision with player LD HL, $7066 ; RAM $7066 LD A, (HL) OR A JR Z, LOC_AA76 DEC (HL) JP Z, LOC_AF2F CP $40 RET C RRCA RRCA AND $0F LD ($70CD), A ; RAM $70CD LD A, (HL) CP $C0 RET NZ LD HL, $AA58 RST $10 RET DB $FD, $45, $20, $59, $4F, $55, $20, $48 DB $41, $56, $45, $20, $42, $45, $45, $4E ; "AVE BEEN" DB $20, $53, $4C, $41, $49, $4E, $21, $20 ; " SLAIN! " DB $FD, $25, $FB, $5A, $9C, $FC LOC_AA76: ; LOC_AA76: object update loop — process each active object LD HL, $705D ; RAM $705D DEC (HL) JR NZ, LOC_AA8A LD (HL), $F0 DEC HL LD A, (HL) SUB $01 DAA JP C, LOC_8054 LD (HL), A CALL SUB_9BA2 LOC_AA8A: ; LOC_AA8A: movement phase — check direction, update object position CALL SUB_8854 LD A, ($7084) ; RAM $7084 OR A JP NZ, LOC_AB98 LD DE, $3D40 CALL VDP_WRITE_86F5 DEC A JR Z, LOC_AAA3 CALL P, VDP_DATA_8702 JP P, LOC_AB98 LOC_AAA3: ; LOC_AAA3: collision phase — check object vs player overlap LD DE, $3D44 CALL VDP_WRITE_86F5 LD DE, $3D40 CALL VDP_DATA_8702 LD HL, $707F ; RAM $707F LD A, (HL) OR A JR Z, LOC_AAF6 RLCA JR NC, LOC_AABC INC (HL) JR LOC_AAF6 LOC_AABC: ; LOC_AABC: animation frame update DEC (HL) LD C, (HL) JR NZ, LOC_AAD5 LD A, ($7080) ; RAM $7080 BIT 4, A JR NZ, LOC_AAF6 LD (HL), $FB LD HL, $7080 ; RAM $7080 RES 6, (HL) LD A, $D8 LD ($70DA), A ; RAM $70DA JR LOC_AAF6 LOC_AAD5: DEC C LD A, ($7067) ; RAM $7067 LD HL, $7080 ; RAM $7080 BIT 4, (HL) JR Z, LOC_AAE7 LD ($707E), A ; RAM $707E ADD A, $04 LD C, $00 LOC_AAE7: ADD A, $14 PUSH AF CALL SUB_AD80 LD ($70DC), A ; RAM $70DC POP AF SUB $08 JP LOC_AB92 LOC_AAF6: LD HL, $70CA ; RAM $70CA LD IX, $AA34 CALL SUB_A966 JR Z, LOC_AB08 LD HL, ($7054) ; RAM $7054 LD ($70CA), HL ; RAM $70CA LOC_AB08: LD HL, ($70CA) ; RAM $70CA LD ($7054), HL ; RAM $7054 LD A, ($7067) ; RAM $7067 LD ($7069), A ; RAM $7069 LD HL, BOOT_UP CALL DECODER LD A, L CPL LD ($7068), A ; RAM $7068 RRCA CALL NC, SUB_ADE6 JR NC, LOC_AB35 BIT 1, A CALL Z, SUB_ADF3 JR Z, LOC_AB35 RRCA CALL NC, SUB_ADCD BIT 1, A CALL Z, SUB_ADD9 LOC_AB35: XOR A CALL SUB_A9E2 LD ($7052), HL ; RAM $7052 CALL VDP_REG_86E8 LD ($7056), A ; RAM $7056 CALL SUB_8807 JR Z, LOC_AB54 CALL SUB_87E2 LD HL, $7056 ; RAM $7056 BIT 6, (HL) RES 6, (HL) CALL NZ, VDP_WRITE_9254 LOC_AB54: LD DE, $3D50 CALL VDP_WRITE_86F5 LD C, A LD A, ($7068) ; RAM $7068 INC A LD A, ($7067) ; RAM $7067 LD B, A LD DE, $3D4C JR NZ, LOC_AB6D CPL AND $01 JR LOC_AB79 LOC_AB6D: LD HL, $7069 ; RAM $7069 CP (HL) JR Z, LOC_AB76 XOR A JR LOC_AB79 LOC_AB76: CALL VDP_WRITE_86F5 LOC_AB79: INC A CP C JR C, LOC_AB7E XOR A LOC_AB7E: CALL VDP_DATA_8702 LD C, A AND $03 JR NZ, LOC_AB8B PUSH BC LD B, $02 RST $28 POP BC LOC_AB8B: LD DE, $3D54 CALL VDP_WRITE_86F5 ADD A, B LOC_AB92: CALL SUB_AD80 LD ($70CC), A ; RAM $70CC LOC_AB98: LD B, $03 LOC_AB9A: LD A, B LD DE, $3D78 CALL SUB_870A INC L DEC L JR Z, LOC_ABB5 DEC L JR Z, LOC_ABB0 LD DE, $3D78 CALL LOC_8714 JR LOC_AC26 LOC_ABB0: CALL SUB_A952 JR LOC_AC26 LOC_ABB5: CALL SUB_AA17 LD A, (HL) CP $D8 JR Z, LOC_AC26 LD A, B LD DE, $3D40 CALL SUB_870A DEC L JR Z, LOC_ABD0 JP M, LOC_ABD0 LD A, L CALL VDP_DATA_8702 JR LOC_ABEB LOC_ABD0: LD DE, $3D44 CALL SUB_870A LD DE, $3D40 CALL LOC_8714 LD A, ($7087) ; RAM $7087 OR A JR NZ, LOC_ABEB LD A, B PUSH BC CALL SUB_A6A8 POP BC CALL SUB_AD90 LOC_ABEB: LD A, B LD DE, $3D74 CALL SUB_870A LD A, L OR A JR Z, LOC_ABFC DEC A CALL VDP_DATA_8702 JR LOC_AC26 LOC_ABFC: PUSH BC LD C, A CALL SUB_8613 POP BC JR Z, LOC_AC26 LD A, B LD DE, $3D6C CALL SUB_870A LD DE, $3D74 CALL LOC_8714 LD DE, $3D60 CALL SUB_870A LD A, ($708B) ; RAM $708B OR A LD A, L JR Z, LOC_AC23 CALL LOC_AE65 JR LOC_AC26 LOC_AC23: CALL SUB_AEB2 LOC_AC26: DEC B JP NZ, LOC_AB9A LD A, ($7080) ; RAM $7080 BIT 4, A JR Z, LOC_AC64 LD BC, $0304 LOC_AC34: PUSH BC CALL SUB_8613 POP BC JR Z, LOC_AC43 CALL SUB_AEA6 CALL SUB_A892 JR LOC_AC83 LOC_AC43: DJNZ LOC_AC34 LD A, ($707F) ; RAM $707F OR A JR NZ, LOC_AC83 LD A, ($707E) ; RAM $707E LD HL, $70DA ; RAM $70DA BIT 0, A JR NZ, LOC_AC56 INC HL LOC_AC56: DEC A JR Z, LOC_AC5C DEC A JR NZ, LOC_AC5E LOC_AC5C: DEC (HL) DEC (HL) LOC_AC5E: INC (HL) CALL SUB_A869 JR LOC_AC83 LOC_AC64: BIT 6, A JR NZ, LOC_AC83 LD A, ($707F) ; RAM $707F OR A JR Z, LOC_AC83 CP $07 JR NC, LOC_AC83 LD BC, $0304 LOC_AC75: PUSH BC CALL SUB_8613 POP BC JR Z, LOC_AC81 CALL SUB_AE3E JR LOC_AC83 LOC_AC81: DJNZ LOC_AC75 LOC_AC83: LD HL, $7064 ; RAM $7064 LD A, (HL) OR A JR Z, LOC_ACAD DEC (HL) JR NZ, LOC_ACAD LD (HL), $14 LD HL, $7065 ; RAM $7065 LD A, (HL) DEC A LD (HL), A JR NZ, LOC_AC9A LD ($7064), A ; RAM $7064 LOC_AC9A: RRCA JR C, LOC_ACA2 CALL SUB_AD70 JR LOC_ACAA LOC_ACA2: LD HL, ($7062) ; RAM $7062 LD A, $9C CALL SUB_90D9 LOC_ACAA: CALL LOC_89B3 LOC_ACAD: LD HL, $708C ; RAM $708C LD A, (HL) OR A JR Z, LOC_ACB8 DEC (HL) CALL Z, SOUND_WRITE_9C09 LOC_ACB8: LD HL, $708D ; RAM $708D LD A, (HL) OR A JR Z, LOC_ACC3 DEC (HL) CALL Z, SOUND_WRITE_9C13 LOC_ACC3: LD HL, $706D ; RAM $706D LD A, (HL) OR A JR Z, LOC_ACD2 DEC (HL) JR NZ, LOC_ACD2 LD A, $0F LD ($706A), A ; RAM $706A LOC_ACD2: LD HL, $708E ; RAM $708E DEC (HL) RET NZ LD (HL), $3C LD C, $01 LD HL, $7087 ; RAM $7087 LD A, (HL) SUB C JR C, LOC_ACE3 LD (HL), A LOC_ACE3: LD HL, $7089 ; RAM $7089 LD A, (HL) SUB C JR C, LOC_ACEB LD (HL), A LOC_ACEB: LD HL, $7088 ; RAM $7088 LD A, (HL) SUB C JR C, LOC_ACF6 LD (HL), A CALL Z, SUB_AD4F LOC_ACF6: LD HL, $708A ; RAM $708A LD A, (HL) SUB C JR C, LOC_AD18 LD A, (HL) JR NZ, LOC_AD18 LD B, $03 LOC_AD02: LD A, B LD DE, $3D58 CALL SUB_870A LD H, $00 LD DE, $957C ADD HL, DE LD L, (HL) LD DE, $3D5C CALL LOC_8714 DJNZ LOC_AD02 LOC_AD18: LD HL, $708B ; RAM $708B LD A, (HL) SUB C JR C, LOC_AD20 LD (HL), A LOC_AD20: LD HL, $7086 ; RAM $7086 LD A, (HL) SUB C JR C, LOC_AD2B LD (HL), A CALL Z, SUB_AD5A LOC_AD2B: LD HL, $7084 ; RAM $7084 LD A, (HL) SUB C JR C, LOC_AD33 LD (HL), A LOC_AD33: LD HL, $7080 ; RAM $7080 BIT 7, (HL) RET Z LD HL, $7085 ; RAM $7085 LD A, (HL) SUB C RET C JR NZ, LOC_AD43 LD A, $03 LOC_AD43: LD (HL), A RET NZ LD HL, $7071 ; RAM $7071 LD A, (HL) SUB C LD (HL), A RET NC JP LOC_AEF3 SUB_AD4F: ; SUB_AD4F: item-pickup event handler — decrement $7079 (item health bonus) by 8 LD HL, $7079 ; HL = $7079 (item-health bonus accumulator) LD A, (HL) ; A = current bonus SUB $08 ; SUB $08: subtract 8 (item pickup health decrement?) LD (HL), A ; store result RET NC ; RET NC: no underflow — done LD (HL), $00 ; LD (HL),$00: clamp to 0 on underflow RET SUB_AD5A: ; SUB_AD5A: monster-hit event handler — apply $7082 damage, update HEALTH $7071 and STR $706E LD HL, $7082 ; HL = $7082 (damage byte from monster) LD A, (HL) ; A = $7082 (damage value) SRL (HL) ; SRL (HL): halve the damage value in-place SUB (HL) ; SUB (HL): A = original damage - half damage = half damage amount LD HL, $7071 ; HL = $7071 (HEALTH) ADD A, (HL) ; ADD A,(HL): A = HEALTH + (damage/2) ??? (seems like a heal not damage) LD (HL), A ; LD (HL),A: update HEALTH LD A, ($7083) ; A = $7083 (secondary damage byte) LD HL, $706E ; HL = $706E (STRENGTH) ADD A, (HL) ; ADD A,(HL): A = STRENGTH + secondary damage DEC A ; DEC A LD (HL), A ; LD (HL),A: update STRENGTH RET SUB_AD70: ; SUB_AD70: enemy-event handler — write enemy coords $7060/$7062 to VDP via VDP_WRITE_8842 LD HL, ($7062) ; HL = $7062 (enemy event Y coordinate) LD DE, ($7060) ; DE = $7060 (enemy event X coordinate) LD A, E ; A = E (X low byte) CALL VDP_WRITE_8842 ; VDP_WRITE_8842: write X coordinate to VRAM at HL INC L ; INC L: advance VRAM address LD A, D ; A = D (X high byte / second coord) JP VDP_WRITE_8842 ; JP VDP_WRITE_8842: write second byte (tail call) SUB_AD80: LD DE, $9462 CALL SUB_86DD LD A, (DE) ADD A, C LD DE, $947F CALL SUB_86DD LD A, (DE) RET SUB_AD90: LD A, B LD DE, $3D50 CALL SUB_870A LD C, L LD DE, $3D4C CALL SUB_870A INC L LD A, L CP C JR C, LOC_ADA4 XOR A LOC_ADA4: CALL VDP_DATA_8702 LD C, A LD A, B LD DE, $3D54 CALL SUB_870A INC L DEC L JR NZ, LOC_ADB9 LD DE, $3D48 CALL SUB_870A LOC_ADB9: LD A, L CALL SUB_AD80 LD C, A LD A, B CALL SUB_AA17 INC HL INC HL LD (HL), C RET SUB_ADC6: LD ($7068), A ; RAM $7068 LD ($7067), A ; RAM $7067 RET SUB_ADCD: PUSH AF XOR A CALL SUB_ADC6 LD HL, $70CB ; RAM $70CB INC (HL) INC (HL) POP AF RET SUB_ADD9: PUSH AF LD A, $02 CALL SUB_ADC6 LD HL, $70CB ; RAM $70CB DEC (HL) DEC (HL) POP AF RET SUB_ADE6: PUSH AF LD A, $01 CALL SUB_ADC6 LD HL, $70CA ; RAM $70CA DEC (HL) DEC (HL) POP AF RET SUB_ADF3: PUSH AF LD A, $03 CALL SUB_ADC6 LD HL, $70CA ; RAM $70CA INC (HL) INC (HL) POP AF RET SUB_AE00: ; SUB_AE00: write 60 dungeon map rows to VRAM — loop B=60, read $73F4 ptr, WRITE_VRAM each row LD HL, ($73F4) ; HL = $73F4 (map data pointer, points into ROM dungeon map) LD DE, $9503 ; DE = $9503 — dungeon map data base in ROM LD B, $3C ; B = $3C (60 rows) LOC_AE08: ; LOC_AE08: per-row write loop — read source/dest/count from DE table, call WRITE_VRAM PUSH BC ; PUSH BC: save row counter PUSH HL ; PUSH HL: save map pointer DB $EB ; DB $EB: EX DE,HL (swap map pointer and $9503 table ptr) LD E, (HL) ; E = (HL): load destination VRAM low byte INC HL ; INC HL LD D, (HL) ; D = (HL): load destination VRAM high byte INC HL ; INC HL LD A, (HL) ; A = (HL): load row byte count SUB E ; SUB E: compute byte count - dest offset LD B, $00 ; B = 0 LD C, A ; C = A: BC = byte count DB $E3 ; DB $E3: EX (SP),HL — swap HL with stack (source ptr restore) DB $EB ; DB $EB: EX DE,HL PUSH DE ; PUSH DE: save VRAM dest CALL WRITE_VRAM ; BIOS WRITE_VRAM: copy BC bytes from HL (source) to VRAM at DE POP HL ; POP HL LD DE, $0020 ; DE = $0020 — advance 32 bytes ADD HL, DE ; ADD HL,DE: step VRAM dest to next row POP DE ; POP DE: restore row table pointer POP BC ; POP BC DJNZ LOC_AE08 ; DJNZ: 60 rows total DELAY_LOOP_AE23: ; DELAY_LOOP_AE23: frame sync (x5 via SUB_A952) + copy map row buffer $AA2D to RAM $70C3 LD B, $05 ; B = 5 — frame sync count LOC_AE25: ; LOC_AE25: loop — call SUB_A952 B times (sprite step + NMI sync) LD A, B ; A = B DEC A ; DEC A: pass B-1 as argument CALL SUB_A952 ; SUB_A952: advance sprite position + sync to NMI DJNZ LOC_AE25 ; DJNZ: repeat 5 times LD HL, $70DE ; HL = $70DE (scroll control byte) LD (HL), $D0 ; LD (HL),$D0: set scroll sync byte LD HL, $AA2D ; HL = $AA2D — map row source data (compact run-length encoded) LD DE, $70C3 ; DE = $70C3 — map row decode buffer LD B, $00 ; B = 0 LD C, (HL) ; C = (HL): load source count byte INC C ; INC C: +1 for count LDIR ; LDIR: copy C bytes from $AA2D to $70C3 RET SUB_AE3E: XOR A LD HL, $7081 ; RAM $7081 BIT 5, (HL) JR Z, LOC_AE53 LD A, B LD DE, $3D5C CALL SUB_870A BIT 6, L JR Z, LOC_AE53 LD A, $03 LOC_AE53: LD HL, $7077 ; RAM $7077 ADD A, (HL) LD C, A LD A, ($706E) ; RAM $706E SRL A SRL A ADD A, C LD HL, $7080 ; RAM $7080 SET 6, (HL) LOC_AE65: LD HL, $706B ; RAM $706B SET 6, (HL) LD C, A LD A, B LD DE, $3D64 CALL SUB_870A LD H, L LD DE, $3D68 CALL SUB_870A LD A, C SUB H JR NC, LOC_AE7E XOR A LOC_AE7E: LD C, A LD A, L SUB C LD L, A LD A, B CALL C, SUB_AE9E LD DE, $3D68 CALL LOC_8714 LD L, $18 SUB_AE8E: LD A, $03 CALL SUB_854A RLCA ADD A, L PUSH BC LD B, A PUSH BC RST $28 POP BC INC B RST $28 POP BC RET SUB_AE9E: LD DE, $3D78 LD L, $0F JP LOC_8714 SUB_AEA6: LD A, $04 LD HL, $7080 ; RAM $7080 BIT 5, (HL) JR Z, LOC_AE65 ADD A, A JR LOC_AE65 SUB_AEB2: LD C, A CALL SUB_8534 AND $1F LD HL, $706F ; RAM $706F CP (HL) JR C, LOC_AEE8 LD A, C LD HL, $7078 ; RAM $7078 SUB (HL) JR C, LOC_AEE8 LD HL, $7079 ; RAM $7079 SUB (HL) JR C, LOC_AEE8 LD C, A CALL SUB_8534 AND $1F LD HL, $7070 ; RAM $7070 CP (HL) JR NC, LOC_AEE0 LD A, C LD HL, $7058 ; RAM $7058 SUB (HL) JR NC, LOC_AEDF XOR A LOC_AEDF: LD C, A LOC_AEE0: LD HL, $7071 ; RAM $7071 LD A, (HL) SUB C JR C, LOC_AEF3 LD (HL), A LOC_AEE8: LD L, $1E CALL SUB_AE8E LOC_AEED: LD HL, $706B ; RAM $706B SET 7, (HL) RET LOC_AEF3: PUSH BC LD HL, $7066 ; RAM $7066 DEC (HL) LD A, B CALL SUB_AE9E CALL SUB_AF05 LD B, $0F RST $28 POP BC JR LOC_AEED SUB_AF05: LD BC, $0300 LOC_AF08: LD A, B CALL SUB_AA17 INC HL INC HL INC HL LD A, (HL) LD (HL), $00 OR A JR Z, LOC_AF2A DEC HL DEC HL DEC HL LD A, (HL) CP $D8 CALL NZ, LOC_A82A LD A, B LD DE, $3D78 CALL SUB_870A INC L DEC L CALL Z, DELAY_LOOP_A8EF LOC_AF2A: DJNZ LOC_AF08 JP SUB_A892 LOC_AF2F: ; LOC_AF2F: decrement lives — DEC $7072; if still alive JP LOC_805D to resume DEC (HL) ; DEC (HL): decrement (HL) (some counter) LD HL, $7072 ; HL = $7072 (LIVES remaining) DEC (HL) ; DEC (HL): decrement LIVES JP NZ, LOC_805D ; JP NZ, LOC_805D: lives remain — resume game at frame entry CALL SUB_9C04 ; no lives left — show "PUSH BUTTON TO CONTINUE" LD HL, $AF4D ; HL = $AF4D — game over RST $10 string RST $10 ; RST $10: render "game over" text and "push (*) to play again" LOC_AF3E: ; LOC_AF3E: game over screen — wait for (*) button, JP BOOT_UP (full restart) RST $08 ; RST $08: frame sync LD HL, $0001 ; HL = $0001 — read player 1 controller CALL DECODER ; BIOS DECODER: read controller -> HL LD A, L ; A = L (button byte) CP $0A ; CP $0A — check for fire/(*) button JR NZ, LOC_AF3E ; JR NZ: not pressed — wait JP BOOT_UP ; JP BOOT_UP: full cold restart ($0000) DB $67, $61, $6D, $65, $20, $6F, $76, $65 ; "game ove" DB $72, $FF, $C5, $70, $75, $73, $68, $20 DB $28, $2A, $29, $20, $74, $6F, $20, $70 ; "(*) to p" DB $6C, $61, $79, $20, $61, $67, $61, $69 ; "lay agai" DB $6E, $FC, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF, $00, $FF, $00, $FF, $00 DB $FF, $00, $FF