the cutting room mirror

en

This article has a talk page!This article has a talk page!
view on tcrf.net

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.