We just released a Feb. 5 '89 prototype of DuckTales for the NES!
If you'd like to support our preservation efforts (and this wasn't cheap), please consider donating or supporting us on Patreon. Thank you!
If you'd like to support our preservation efforts (and this wasn't cheap), please consider donating or supporting us on Patreon. Thank you!
Notes:Pokémon Gold and Silver/Memory Game Disassembly
Jump to navigation
Jump to search
This is a sub-page of Notes:Pokémon Gold and Silver.
This is the commented disassembly for the Unused Memory game found in Pokémon Gold and Silver, Japanese v1.0 ROM, at 38:667A.
Disassembly
;; Memory Game Routine entry ;; 38:667A call @6686 ; init call $032E ; wait for screen to come back on @6680: call @66DA ; main loop jr nc, @6680 ret ;; Init @6686: call $0432 ; Disable screen ld b, $08 call $34E5 ; load palette ld hl, $4F99 ld a, $23 rst $8 ; init OAM sprite routine ld hl, $6A46 ld de, $9000 call $0AE9 ; load background gfx ld hl, $48BC ; data source: commented-out gfx ld de, $8000 ld bc, $0040 ld a, $38 call $0DB6 ; copy 0x40 bytes (0x04 tiles) for selector sprite ld a, $08 ld hl, $C508 ldi [hl], a ; OAM sprite tile base select ld [hl], $00 ; OAM sprite group 0x08 based at 0x00 ld hl, $C3A0 ld bc, $0168 xor a, a call $3108 ; clear bg map xor a, a ld [$FF00 + $D2], a ; set X scroll ld [$FF00 + $D1], a ; set Y scroll ld [$FF00 + $4A], a ; hide window ld [$CE57], a ; init main loop state to 0x00 ld a, $01 ld [$FF00 + $D6], a ; set screen update to C3A0 region ld a, $E3 ld [$FF00 + $40], a ; LCD control ld a, $E4 call $0C4A ; bg palettes ld a, $E0 call $0C8F ; obj palettes ret ;; main loop @66DA: ld a, [$CE57] bit 7, a jr nz, @66EF ; exit condition = b7 set call @66F1 ; call subroutines ld hl, $4FAF ld a, $23 rst $8 ; animate OAM sprites call $032E and a, a ; don't exit game ret @66EF: scf ; exit game ret ;; subroutines @66F1: ld a, [$CE57] ld e, a ld d, $00 ld hl, @6700 add hl, de add hl, de ldi a, [hl] ld h, [hl] ld l, a jp [hl] ; jump to pointer [$CE57] in list @6700 @6700: dw @6712 dw @671A dw @673B dw @6761 dw @6780 dw @67AA dw @67D9 dw @67EB dw @681F ;; subroutine 0x00 ;; init @6712: call @6977 ; init field ld hl, $CE57 inc [hl] ; next subroutine ret ;; subroutine 0x01 ;; coin question @671A: call $48BC ; "Bet how many coins?" routine should be here jr nc, @6725 ; but is commented out. ld hl, $CE57 set 7, [hl] ret ;; play game (cont'd 0x01) ;; randomize field @6725: call @68C2 ; randomize field ld hl, $CE57 inc [hl] ; next subroutine xor a, a ld [$C608], a ; clear RAM C603 - C609 ld hl, $C603 ldi [hl], a ; RAM map: [slot1][slot2][slot3][slot4][slot5][counter][taken card offset counter] ldi [hl], a ; taken card offset counter counts in tiles ldi [hl], a ldi [hl], a ld [hl], a ld [$C609], a ;; subroutine 0x02 ;; draw cards @673B: ld hl, $C608 ld a, [hl] cp a, $2D jr nc, @674F inc [hl] call $69A8 ; get card bg offset xor a, a ld [$C5FD], a ; card 0x00 call @694D ; draw card tiles ret ;; finished drawing all cards @674F: ld de, $341C ; coordinates X = 0x1C Y = 0x34 ld a, $1E ; sprite number 0x1E call $3C4C ; load OAM sprite ld a, $05 ld [$C602], a ; load number of turns ld hl, $CE57 inc [hl] ; next subroutine ret ;; subroutine 0x03 ;; current turn @6761: ld a, [$C602] ld hl, $C3B1 add a, $F6 ld [hl], a ; number of turns + Tile 0xF6 ld hl, $C602 ld a, [hl] and a, a jr nz, @6777 ld a, $07 ; no turns left ld [$CE57], a ; goto subroutine 0x07 ret ;; turns left @6777: dec [hl] ; decrease turns left xor a, a ld [$CE58], a ; init card select index to 0x00 ld hl, $CE57 inc [hl] ; next subroutine ;; subroutine 0x04 ;; select first card ld a, [$CE58] and a, a ret z ; exit if no card selected dec a ld e, a ld d, $00 ld hl, $C5D0 add hl, de ld a, [hl] cp a, $FF ret z ; exit if empty spot selected ld [$C5FD], a ; card to draw ld [$C5FE], a ; first selected card ld a, e ld [$C600], a ; first selected card's slot call $69A8 ; get card bg offset call @694D ; draw card xor a, a ld [$CE58], a ; clear selection ld hl, $CE57 inc [hl] ; next subroutine ret ;; subroutine 0x05 ;; select second card ld a, [$CE58] and a, a ret z ; exit if no card selected dec a ld hl, $C600 cp a, [hl] ret z ; exit if first select card's slot selected ld e, a ld d, $00 ld hl, $C5D0 add hl, de ld a, [hl] cp a, $FF ret z ; exit if empty spot selected ld [$C5FD], a ; card to draw ld [$C5FF], a ; second selected card ld a, e ld [$C601], a ; second selected card's slot call $69A8 ; get card bg offset call @694D ; draw card ld a, $40 ld [$C608], a ; delay ld hl, $CE57 inc [hl] ; next subroutine ;; subroutine 0x06 ;; check cards ld hl, $C608 ld a, [hl] and a, a jr z, @67E2 dec [hl] ret ;; end of delay @67E2: call @682F ; check cards ld a, $03 ld [$CE57], a ; return to current turn ret ;; subroutine 0x07 ;; no turns left ;; draw all cards ld a, [$FF00 + $A5] and a, $01 ret z ; wait for A button press xor a, a ld [$C608], a ; clear counter @67F4: ld hl, $C608 ld a, [hl] cp a, $2D jr nc, @6818 inc [hl] push af call $69A8 ; get card bg offset pop af push hl ld e, a ld d, $00 ld hl, $C5D0 add hl, de ld a, [hl] ; get card number pop hl cp a, $FF jr z, @67F4 ; skip empty slots ld [$C5FD], a ; store card number call @694D ; draw card jr @67F4 ;; all cards drawn @6818: call $0A26 ; wait for keypress ld hl, $CE57 inc [hl] ; next subroutine ;; subroutine 0x08 call $48BC ; "Play again?" routine should be here jr nc, @682A ; but is commented out. ld hl, $CE57 set 7, [hl] ; exit game ret ;; new round @682A: xor a, a ld [$CE57], a ; reset game ret ;; check cards @682F: ld hl, $C5FE ldi a, [hl] cp a, [hl] jr nz, @6885 ; cards don't match ld a, [$C600] call $69A8 ; get first selected card's bg offset call @6967 ; erase card ld a, [$C601] call $69A8 ; get second selected card's bg offset call @6967 ; erase card ld a, [$C600] ld e, a ld d, $00 ld hl, $C5D0 add hl, de ld [hl], $FF ; empty first selected card's slot ld a, [$C601] ld e, a ld d, $00 ld hl, $C5D0 add hl, de ld [hl], $FF ; empty second selected card's slot ld hl, $C603 @6863: ldi a, [hl] and a, a jr nz, @6863 dec hl ld a, [$C5FE] ; get current card number ld [hl], a ; write card to taken slot ld [$C5FD], a @686F: ld hl, $C609 ld e, [hl] inc [hl] inc [hl] ld d, $00 ld hl, $C3A5 add hl, de ; get taken card bg offset call @694D ; draw card ld hl, @68A2 call $0F30 ; message win ret ;; cards don't match @6885: xor a, a ld [$C5FD], a ; card 0x00 ld a, [$C600] call $69A8 ; get first selected card's bg offset call @694D ; draw card ld a, [$C601] call $69A8 ; get second selected card's bg offset call @694D ; draw card ld hl, @68BA call $0F30 ; message lose ret ;; messages @68A2: db $08 ; message ASM push bc ld hl, $C4A6 call $694D ; draw card in text box ld hl, @68B2 ; message offset pop bc inc bc inc bc inc bc ; skip 0x03 tiles in message ret @68B2: db $00 ; message 「CARD いただき!」 "CARD, yeah!" db $7F db $B2 db $C0 db $30 db $B7 db $E7 db $57 @68BA: db $00 ; message 「ざんねん…」 "Darn..." db $2B db $DE db $C8 db $DE db $75 db $75 db $57 ;; randomize field @68C2: ld hl, $C5D0 ld bc, $002D xor a, a call $3108 ; clear field call @6926 ; get card distribution ld c, $02 ld b, [hl] call @690A ; card 0x02 ld c, $08 ld b, [hl] call @690A ; card 0x08 ld c, $04 ld b, [hl] call @690A ; card 0x04 ld c, $07 ld b, [hl] call @690A ; card 0x07 ld c, $03 ld b, [hl] call @690A ; card 0x03 ld c, $06 ld b, [hl] call @690A ; card 0x06 ld c, $01 ld b, [hl] call @690A ; card 0x01 ld c, $05 ld hl, $C5D0 ld b, $2D @6900: ld a, [hl] and a, a jr nz, @6905 ld [hl], c ; make rest card 0x05 @6905: inc hl dec b jr nz, @6900 ret ;; set b cards @690A: push hl ld de, $C5D0 @690E: call $305E ; get random index and a, $3F cp a, $2D jr nc, @690E ld l, a ld h, $00 add hl, de ld a, [hl] and a, a jr nz, @690E ; put card if empty ld [hl], c ; else get random index again dec b jr nz, @690E pop hl inc hl ret ;; card distribution @6926: ld a, [$CF14] dec a ld l, a ld h, $00 add hl, hl add hl, hl add hl, hl ld de, @6935 add hl, de ret @6935: db $02 ; begin data 1 coin db $03 db $06 db $06 db $06 db $08 db $08 db $06 db $02 ; begin data 2 coins db $02 db $04 db $06 db $06 db $08 db $08 db $09 db $02 ; begin data 3 coins db $02 db $02 db $04 db $07 db $08 db $08 db $0C ;; draw single card [$C5FD] @694D: ld a, [$C5FD] sla a sla a add a, $04 ; card tile base = 0x04 ldi [hl], a inc a ldd [hl], a ; draw top two tiles inc a ld bc, $0014 add hl, bc ldi [hl], a inc a ld [hl], a ; draw bottom two tiles ld c, $03 call $033C ret ;; erase single card at hl @6967: ld a, $01 ; tile 0x01 = background ldi [hl], a ldd [hl], a ; erase top two tiles ld bc, $0014 add hl, bc ldi [hl], a ld [hl], a ; erase bottom two tiles ld c, $03 call $033C ret ;; init field @6977: ld hl, $C3A0 ld bc, $0168 ld a, $01 call $3108 ; fill map with 0x01 ld hl, $C3A0 ld de, @699C call $0F46 ; string upper left corner ld hl, $C3AF ld de, @69A2 call $0F46 ; string upper right corner ld hl, @699B call $0F30 ; show message ret @699B: db $50 ; empty message @699C: db $C4 ; 「とったもの」 "[Cards] taken" db $DF db $C0 db $D3 db $C9 db $50 @69A2: db $B1 ; 「あとNかい」 "N more turns" db $C4 db $7F db $B6 db $B2 db $50 ;; get card bg offset @69A8: ld d, $00 @69AA: sub a, $09 jr c, @69B1 inc d jr @69AA ; d = a \ 9 @69B1: add a, $09 ; a = a % 9 ld e, a ld hl, $C3C9 ld bc, $0028 @69BA: ld a, d and a, a jr z, @69C2 add hl, bc dec d jr @69BA @69C2: sla e add hl, de ; hl = 0xC328 + 0x0028 * row + 2 * column ret ;; Selector code entry ;; 38:69C6 ld a, [$CE57] cp a, $07 jr nc, @69ED call $09FD ; Read keys ld hl, $FFA5 ld a, [hl] and a, $01 jr nz, @69F4 ; A button ld a, [hl] and a, $20 jr nz, @69FE ; D-pad LEFT ld a, [hl] and a, $10 jr nz, @6A0E ; D-pad RIGHT ld a, [hl] and a, $40 jr nz, @6A1F ; D-pad UP ld a, [hl] and a, $80 jr nz, @6A32 ; D-pad DOWN ret ;; Subroutine ≧0x07 active @69ED: ld hl, $0000 add hl, bc ld [hl], $00 ; Delete OAM sprite ret ;; A button pressed @69F4: ld hl, $000C add hl, bc ld a, [hl] ; load selected slot index to inc a ld [$CE58], a ; card select index register ret ;; D-pad LEFT pressed @69FE: ld hl, $0006 add hl, bc ld a, [hl] and a, a ret z ; exit if already at left edge sub a, $10 ld [hl], a ld hl, $000C add hl, bc dec [hl] ; selected slot index-- ret ;; D-pad RIGHT pressed @6A0E: ld hl, $0006 add hl, bc ld a, [hl] cp a, $80 ret z ; exit if already at right edge add a, $10 ld [hl], a ld hl, $000C add hl, bc inc [hl] ; selected slot index++ ret ;; D-pad UP pressed @6A1F: ld hl, $0007 add hl, bc ld a, [hl] and a, a ret z ; exit if already at top edge sub a, $10 ld [hl], a ld hl, $000C add hl, bc ld a, [hl] sub a, $09 ld [hl], a ; selected slot index - 0x09 (one row) ret ;; D-pad DOWN pressed @6A32: ld hl, $0007 add hl, bc ld a, [hl] cp a, $40 ret z ; exit if already at bottom edge add a, $10 ld [hl], a ld hl, $000C add hl, bc ld a, [hl] add a, $09 ld [hl], a ; selected slot index + 0x09 (one row) ret
Notice
The actual card selection is handled by the OAM selector sprite code, which calls 38:69C6.