This is a sub-page of Notes:Pokémon Gold and Silver/Memory Game Disassembly.
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.