If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Notes:Pokémon Gold and Silver/Memory Game Disassembly

From The Cutting Room Floor
Jump to navigation Jump to search
Other languages:
English • ‎polski

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.