mirror of
https://github.com/pret/pokegold-spaceworld.git
synced 2026-04-26 08:13:44 -05:00
Some checks failed
CI / build (push) Has been cancelled
* Sporadic constantifying and function naming * Added bank 14 * Delete .DS_Store files * Delete EOL whitespace * Use Tab indents instead of four spaces * Identify some routines * Identify more stuff * Identified party and box structs * Identified wBattleMon and wEnemyMon structs * Macro'd landmarks, cleaned up comments --------- Co-authored-by: vulcandth <vulcandth@gmail.com>
1448 lines
23 KiB
NASM
1448 lines
23 KiB
NASM
INCLUDE "constants.asm"
|
|
|
|
; MinigamePikachuDoMovement.Jumptable constants
|
|
const_def
|
|
const MINIGAME_PIKACHU_INIT ; 00
|
|
const MINIGAME_PIKACHU_CONTROL ; 01
|
|
const MINIGAME_PIKACHU_JUMPING ; 02
|
|
const MINIGAME_PIKACHU_FALLING ; 03
|
|
|
|
; PikachuMiniGame_PerformGameFunction.Jumptable constants
|
|
const_def
|
|
const PIKACHU_MINIGAME_SETUP ; 00
|
|
const PIKACHU_MINIGAME_NOTE_SPAWNER ; 01
|
|
const PIKACHU_MINIGAME_SET_NEXT_SCENE_TIMER ; 02
|
|
const PIKACHU_MINIGAME_WAIT_AND_GOTO_NEXT ; 03
|
|
const PIKACHU_MINIGAME_SHOW_JIGGLYPUFF ; 04
|
|
const PIKACHU_MINIGAME_FADE_OUT ; 05
|
|
|
|
SECTION "engine/games/pikachu_minigame.asm@Pikachu Minigame", ROMX
|
|
|
|
PikachuMiniGame::
|
|
ld a, HIGH(vBGMap1)
|
|
ldh [hBGMapAddress + 1], a
|
|
call .Init
|
|
call DelayFrame
|
|
.loop
|
|
call PikachuMiniGame_RunFrame
|
|
jr nc, .loop
|
|
|
|
; exit
|
|
ld a, HIGH(vBGMap0)
|
|
ldh [hBGMapAddress + 1], a
|
|
ld de, MUSIC_NONE
|
|
call PlayMusic
|
|
ret
|
|
|
|
.Init:
|
|
call DisableLCD
|
|
ld b, SGB_PIKACHU_MINIGAME
|
|
call GetSGBLayout
|
|
callfar InitEffectObject
|
|
call PikachuMiniGame_ClearBothTilemaps
|
|
|
|
ld hl, IntroForestGFX
|
|
ld de, vChars2
|
|
ld bc, $80 tiles
|
|
ld a, BANK(IntroForestGFX)
|
|
call FarCopyData
|
|
|
|
ld hl, IntroJigglypuffPikachuGFX
|
|
ld de, vChars0
|
|
ld bc, $90 tiles
|
|
ld a, BANK(IntroJigglypuffPikachuGFX)
|
|
call FarCopyData
|
|
|
|
; Metatiles
|
|
ld a, LOW(PikachuMiniGame_Meta)
|
|
ld [wPikachuMinigameTilesPointer], a
|
|
ld a, HIGH(PikachuMiniGame_Meta)
|
|
ld [wPikachuMinigameTilesPointer + 1], a
|
|
|
|
; BG map destination
|
|
ld hl, vBGMap0
|
|
ld a, l
|
|
ld [wPikachuMinigameBGMapPointer], a
|
|
ld a, h
|
|
ld [wPikachuMinigameBGMapPointer + 1], a
|
|
|
|
; Block map
|
|
ld de, PikachuMiniGame_Blockmap
|
|
ld a, e
|
|
ld [wPikachuMinigameTilemapPointer], a
|
|
ld a, d
|
|
ld [wPikachuMinigameTilemapPointer + 1], a
|
|
call PikachuMiniGame_DrawBackground
|
|
|
|
ld hl, wSpriteAnimDict
|
|
ld a, SPRITE_ANIM_INDEX_GS_INTRO_OMANYTE
|
|
ld [hli], a
|
|
ld a, SPRITE_ANIM_DICT_DEFAULT
|
|
ld [hli], a
|
|
call PikachuMiniGame_LoadFont
|
|
|
|
xor a
|
|
ldh [hSCY], a
|
|
ld [wGlobalAnimYOffset], a
|
|
ldh [hSCX], a
|
|
ld [wGlobalAnimXOffset], a
|
|
ld [wPikachuMinigameJumptableIndex], a
|
|
ld [wPikachuMinigameScrollSpeed], a
|
|
ld [wPikachuMinigameScore], a
|
|
ld [wPikachuMinigameScore + 1], a
|
|
ld [wPikachuMinigameNoteCounter], a
|
|
ld [wPikachuMinigameNoteCounter + 1], a
|
|
ld [wPikachuMinigameTimeFrames], a
|
|
ld [wPikachuMinigameTimeSeconds], a
|
|
ld [wc613], a
|
|
ld [wc614], a
|
|
ld [wPikachuMinigameNoteTimer], a
|
|
ld [wPikachuMinigameSpawnTypeIndex], a
|
|
ld [wPikachuMinigameSpawnDataIndex], a
|
|
ld [wPikachuMinigameRedrawTimer], a
|
|
ld [wPikachuMinigameColumnFlags], a
|
|
ld [wPikachuMinigameSavedColumnPointer], a
|
|
ld [wPikachuMinigameSavedColumnPointer + 1], a
|
|
ld [wPikachuMinigameRepeatColumnCounter], a
|
|
ld [wPikachuMinigameRepeatColumnCounter2], a
|
|
|
|
ld a, LOW(PikachuMiniGame_Columns)
|
|
ld [wPikachuMinigameColumnPointer], a
|
|
ld a, HIGH(PikachuMiniGame_Columns)
|
|
ld [wPikachuMinigameColumnPointer + 1], a
|
|
|
|
; Set status bar position
|
|
ld a, $7c
|
|
ldh [hWY], a
|
|
|
|
ld a, $e3
|
|
ldh [rLCDC], a
|
|
|
|
ld a, [wSGB]
|
|
and a
|
|
jr nz, .not_sgb
|
|
|
|
ld a, %10010100
|
|
ldh [rBGP], a
|
|
ld a, %11100100
|
|
ldh [rOBP0], a
|
|
jr .load_pikachu
|
|
|
|
.not_sgb
|
|
; Normal palette if on GB / GBC
|
|
ld a, %11100100
|
|
ldh [rBGP], a
|
|
ldh [rOBP0], a
|
|
|
|
.load_pikachu
|
|
depixel 14, 11
|
|
ld a, SPRITE_ANIM_INDEX_MINIGAME_PIKACHU
|
|
call InitSpriteAnimStruct
|
|
|
|
; Save pointer to the newly initialized Pikachu object
|
|
ld a, c
|
|
ld [wPikachuMinigamePikachuObjectPointer], a
|
|
ld a, b
|
|
ld [wPikachuMinigamePikachuObjectPointer + 1], a
|
|
|
|
; load Pikachu's tail object
|
|
depixel 14, 11
|
|
ld a, SPRITE_ANIM_INDEX_MINIGAME_PIKACHU_TAIL
|
|
call InitSpriteAnimStruct
|
|
|
|
ld a, c
|
|
ld [wPikachuMinigamePikachuTailObjectPointer], a
|
|
ld a, b
|
|
ld [wPikachuMinigamePikachuTailObjectPointer + 1], a
|
|
ret
|
|
|
|
PikachuMiniGame_ClearBothTilemaps:
|
|
ld hl, vBGMap1
|
|
ld bc, SCREEN_WIDTH * BG_MAP_HEIGHT
|
|
.clear_bgmap
|
|
ld [hl], 0
|
|
inc hl
|
|
dec bc
|
|
ld a, b
|
|
or c
|
|
jr nz, .clear_bgmap
|
|
|
|
ld hl, wTileMap
|
|
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
|
|
.clear_tilemap
|
|
ld [hl], 0
|
|
inc hl
|
|
dec bc
|
|
ld a, b
|
|
or c
|
|
jr nz, .clear_tilemap
|
|
|
|
ld a, 7
|
|
ldh [hWX], a
|
|
ret
|
|
|
|
PikachuMiniGame_LoadFont:
|
|
ld hl, FontGFX
|
|
ld de, vFont tile $10
|
|
ld bc, 112 * LEN_1BPP_TILE
|
|
ld a, BANK(FontGFX)
|
|
call FarCopyDataDouble
|
|
|
|
ld hl, FontGFX tile $39
|
|
ld de, vChars2 tile $32
|
|
ld bc, 16 * LEN_1BPP_TILE
|
|
ld a, BANK(FontGFX)
|
|
call FarCopyDataDouble
|
|
ret
|
|
|
|
PikachuMiniGame_BlinkText:
|
|
; Blink the window text according to the current X scroll position.
|
|
; 00 - 7f = hide text
|
|
; 80 - ff = show text
|
|
|
|
ldh a, [hSCX]
|
|
ld d, a
|
|
and $7f
|
|
ret nz
|
|
bit 7, d
|
|
jr nz, .DisplayText
|
|
|
|
; clear dakutens
|
|
xor a
|
|
hlcoord 5, 0
|
|
ld [hl], a
|
|
hlcoord 13, 0
|
|
ld [hl], a
|
|
|
|
; clear text
|
|
hlcoord 1, 1
|
|
ld c, 15
|
|
.text_clear
|
|
ld [hli], a
|
|
dec c
|
|
jr nz, .text_clear
|
|
ret
|
|
|
|
.DisplayText:
|
|
decoord 1, 1
|
|
ld hl, .text
|
|
|
|
.render_text
|
|
ld a, [hli]
|
|
and a
|
|
jr z, .render_dakutens
|
|
|
|
; Tiles are shifted so add $10 to each character
|
|
add $10
|
|
ld [de], a
|
|
inc de
|
|
jr .render_text
|
|
|
|
.render_dakutens
|
|
; Render dakuten marks separately
|
|
ld a, "゙" + $10
|
|
|
|
hlcoord 5, 0
|
|
ld [hl], a
|
|
|
|
hlcoord 13, 0
|
|
ld [hl], a
|
|
|
|
ret
|
|
|
|
.text
|
|
db "スタートホタン▶タイトルかめん"
|
|
db 0 ; terminator
|
|
|
|
PikachuMiniGame_Copy128Tiles: ; unreferenced?
|
|
ld bc, $80 tiles
|
|
.loop
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
dec bc
|
|
ld a, c
|
|
or b
|
|
jr nz, .loop
|
|
ret
|
|
|
|
PikachuMiniGame_DrawBackground:
|
|
ld b, BG_MAP_HEIGHT / 2
|
|
|
|
.outer_loop
|
|
push hl
|
|
ld c, BG_MAP_WIDTH / 2
|
|
|
|
.inner_loop
|
|
call PikachuMiniGame_Draw2x2Tile
|
|
dec c
|
|
jr nz, .inner_loop
|
|
pop hl
|
|
push bc
|
|
ld bc, BG_MAP_HEIGHT * 2
|
|
add hl, bc
|
|
pop bc
|
|
dec b
|
|
jr nz, .outer_loop
|
|
ret
|
|
|
|
PikachuMiniGame_Draw2x2Tile:
|
|
push bc
|
|
push de
|
|
push hl
|
|
|
|
push hl
|
|
|
|
push hl
|
|
ld a, [de]
|
|
ld l, a
|
|
ld h, 0
|
|
ld a, [wPikachuMinigameTilesPointer]
|
|
ld e, a
|
|
ld a, [wPikachuMinigameTilesPointer + 1]
|
|
ld d, a
|
|
add hl, hl
|
|
add hl, hl
|
|
add hl, de
|
|
ld e, l
|
|
ld d, h
|
|
pop hl
|
|
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
pop hl
|
|
|
|
ld bc, BG_MAP_WIDTH
|
|
add hl, bc
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
pop hl
|
|
|
|
inc hl
|
|
inc hl
|
|
|
|
pop de
|
|
inc de
|
|
|
|
pop bc
|
|
ret
|
|
|
|
|
|
PikachuMiniGame_RunFrame:
|
|
; Run a single frame of the minigame
|
|
|
|
call GetJoypad
|
|
ld hl, hJoyState
|
|
ld a, [hl]
|
|
|
|
; Skip minigame on pressing Start
|
|
and START
|
|
jr nz, .Done
|
|
|
|
ld a, [wPikachuMinigameJumptableIndex]
|
|
bit 7, a
|
|
jr nz, .Done
|
|
|
|
ld a, [wPikachuMinigameNoteCaught]
|
|
and a
|
|
jr z, .skip_playing_sfx
|
|
|
|
xor a
|
|
ld [wPikachuMinigameNoteCaught], a
|
|
ld de, SFX_PAY_DAY
|
|
call PlaySFX
|
|
|
|
.skip_playing_sfx
|
|
call PikachuMiniGame_PerformGameFunction
|
|
farcall EffectObjectJumpNoDelay
|
|
|
|
ld a, 1
|
|
ldh [hBGMapMode], a
|
|
|
|
call PikachuMiniGame_ScrollScene
|
|
call PikachuMiniGame_UpdateBlocks
|
|
|
|
; Print minigame score, starting from the last digit
|
|
decoord 18, 1
|
|
ld hl, wPikachuMinigameScore
|
|
call PikachuMiniGame_PrintBCD
|
|
|
|
call PikachuMiniGame_BlinkText
|
|
|
|
call DelayFrame
|
|
and a
|
|
ret
|
|
|
|
.Done:
|
|
callfar InitEffectObject
|
|
|
|
ld hl, wShadowOAM
|
|
ld c, SPRITEOAMSTRUCT_LENGTH * NUM_SPRITE_OAM_STRUCTS
|
|
xor a
|
|
.clear_oam
|
|
ld [hli], a
|
|
dec c
|
|
jr nz, .clear_oam
|
|
|
|
call DelayFrame
|
|
|
|
xor a
|
|
ldh [hSCX], a
|
|
ldh [hSCY], a
|
|
|
|
ld a, 144
|
|
ldh [hWY], a
|
|
scf
|
|
ret
|
|
|
|
|
|
PikachuMiniGame_RunTimer:
|
|
ld hl, wPikachuMinigameTimeFrames
|
|
|
|
; Run BCD frame counter
|
|
ld a, [hl]
|
|
add 1
|
|
daa
|
|
ld [hl], a
|
|
cp $60
|
|
ret c
|
|
|
|
; Clear frame counter upon passing one second and increment the
|
|
; seconds counter instead
|
|
ld [hl], 0
|
|
ld hl, wPikachuMinigameTimeSeconds
|
|
ld a, [hl]
|
|
add 1
|
|
daa
|
|
ld [hl], a
|
|
cp $60
|
|
ret c
|
|
|
|
; When gameplay time reaches 1 minute, end the game here
|
|
ld a, PIKACHU_MINIGAME_SET_NEXT_SCENE_TIMER
|
|
ld [wPikachuMinigameJumptableIndex], a
|
|
ret
|
|
|
|
|
|
PikachuMiniGame_UpdateBlocks:
|
|
ldh a, [hSCX]
|
|
ld e, a
|
|
and 7
|
|
ret nz
|
|
|
|
ld a, $48
|
|
add e
|
|
and $f8
|
|
ld e, a
|
|
srl e
|
|
srl e
|
|
srl e
|
|
ld d, 0
|
|
hlbgcoord 0, 8
|
|
add hl, de
|
|
ld de, wPikachuMinigameColumnBuffer
|
|
ld a, e
|
|
ld [wVBCopyDst], a
|
|
ld a, d
|
|
ld [wVBCopyDst + 1], a
|
|
ld a, l
|
|
ld [wVBCopySrc], a
|
|
ld a, h
|
|
ld [wVBCopySrc + 1], a
|
|
ld a, 1
|
|
ld [wVBCopySize], a
|
|
ret
|
|
|
|
|
|
PikachuMiniGame_PrintBCD:
|
|
; Print the BCD number in HL to DE, least-significant
|
|
; digit first.
|
|
|
|
push hl
|
|
push de
|
|
push bc
|
|
|
|
ld c, [hl]
|
|
inc hl
|
|
ld b, [hl]
|
|
|
|
ld l, e
|
|
ld h, d
|
|
|
|
; in the thousandths range?
|
|
ld a, b
|
|
swap a
|
|
and $f
|
|
jr nz, .four_digits
|
|
|
|
; in the hundredths range?
|
|
ld a, b
|
|
and $f
|
|
jr nz, .three_digits
|
|
|
|
; in the tenths range?
|
|
ld a, c
|
|
swap a
|
|
and $f
|
|
jr nz, .two_digits
|
|
|
|
; got one digit
|
|
ld a, c
|
|
call .PlaceDigit
|
|
jr .finished
|
|
|
|
.two_digits
|
|
ld a, c
|
|
call .PlaceDigit
|
|
ld a, c
|
|
swap a
|
|
call .PlaceDigit
|
|
jr .finished
|
|
|
|
.three_digits
|
|
ld a, c
|
|
call .PlaceDigit
|
|
ld a, c
|
|
swap a
|
|
call .PlaceDigit
|
|
ld a, b
|
|
call .PlaceDigit
|
|
jr .finished
|
|
|
|
.four_digits
|
|
ld a, c
|
|
call .PlaceDigit
|
|
ld a, c
|
|
swap a
|
|
call .PlaceDigit
|
|
ld a, b
|
|
call .PlaceDigit
|
|
ld a, b
|
|
swap a
|
|
call .PlaceDigit
|
|
|
|
.finished
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
ret
|
|
|
|
.PlaceDigit:
|
|
and $0f
|
|
add $36
|
|
ld [hld], a
|
|
ret
|
|
|
|
PikachuMiniGame_PerformGameFunction:
|
|
jumptable .Jumptable, wPikachuMinigameJumptableIndex
|
|
|
|
.Jumptable:
|
|
dw PikachuMiniGame_SetupScene
|
|
dw PikachuMiniGame_NoteSpawner
|
|
dw PikachuMiniGame_SetNextSceneTimer
|
|
dw PikachuMiniGame_WaitAndGotoNextScene
|
|
dw PikachuMiniGame_ShowJigglypuff
|
|
dw PikachuMiniGame_FadeOut
|
|
|
|
PikachuMiniGame_SetupScene:
|
|
; Set scroll speed and joypad enable here
|
|
ld a, 4
|
|
ld [wPikachuMinigameScrollSpeed], a
|
|
|
|
ld a, D_LEFT | D_RIGHT | A_BUTTON
|
|
ld [wPikachuMinigameControlEnable], a
|
|
|
|
ld hl, wPikachuMinigameJumptableIndex
|
|
inc [hl]
|
|
ret
|
|
|
|
PikachuMiniGame_SetNextSceneTimer:
|
|
ld a, 64
|
|
ld [wPikachuMinigameSceneTimer], a
|
|
ld hl, wPikachuMinigameJumptableIndex
|
|
inc [hl]
|
|
|
|
PikachuMiniGame_WaitAndGotoNextScene:
|
|
ld hl, wPikachuMinigameSceneTimer
|
|
ld a, [hl]
|
|
and a
|
|
jr z, .next_scene
|
|
dec [hl]
|
|
ret
|
|
|
|
.next_scene
|
|
ld hl, wPikachuMinigameJumptableIndex
|
|
inc [hl]
|
|
|
|
PikachuMiniGame_ShowJigglypuff:
|
|
depixel 14, 24
|
|
ld a, SPRITE_ANIM_INDEX_MINIGAME_JIGGLYPUFF
|
|
call InitSpriteAnimStruct
|
|
|
|
xor a
|
|
ld [wPikachuMinigameSceneTimer], a
|
|
ld hl, wPikachuMinigameJumptableIndex
|
|
inc [hl]
|
|
|
|
PikachuMiniGame_FadeOut:
|
|
ld a, [wPikachuMinigameScrollSpeed]
|
|
and a
|
|
ret nz
|
|
|
|
ld a, [wPikachuMinigameSceneTimer]
|
|
srl a
|
|
srl a
|
|
srl a
|
|
srl a
|
|
|
|
ld e, a
|
|
ld d, 0
|
|
ld hl, .DMGPals
|
|
add hl, de
|
|
|
|
ld a, [hl]
|
|
cp -1
|
|
jr z, .end_minigame
|
|
|
|
ldh [rBGP], a
|
|
|
|
ld hl, .Obj_SGBPals
|
|
add hl, de
|
|
|
|
ld a, [wSGB]
|
|
and a
|
|
jr z, .not_sgb
|
|
|
|
ld a, [hl]
|
|
ldh [rBGP], a
|
|
|
|
.not_sgb
|
|
ld a, [hl]
|
|
ldh [rOBP0], a
|
|
|
|
; from this point, the timer increments*instead
|
|
ld hl, wPikachuMinigameSceneTimer
|
|
inc [hl]
|
|
ret
|
|
|
|
.end_minigame
|
|
; once everything fades out, the minigame ends here
|
|
; leading to the title screen
|
|
|
|
ld hl, wPikachuMinigameJumptableIndex
|
|
set 7, [hl]
|
|
ret
|
|
|
|
.DMGPals:
|
|
db $94, $94
|
|
db $94, $94
|
|
db $94, $50
|
|
db $40, $00
|
|
db -1
|
|
|
|
.Obj_SGBPals:
|
|
db $e4, $e4
|
|
db $e4, $e4
|
|
db $e4, $90
|
|
db $40, $00
|
|
db -1
|
|
|
|
PikachuMiniGame_NoteSpawner:
|
|
; Spawn notes from the left side of the screen.
|
|
;
|
|
call PikachuMiniGame_RunTimer
|
|
ldh a, [hSCX]
|
|
and $20
|
|
ld hl, wPikachuMinigameNoteTimer
|
|
cp [hl]
|
|
jr nz, .spawn_note
|
|
ret
|
|
|
|
.spawn_note
|
|
ld a, [hl]
|
|
xor $20
|
|
ld [hl], a
|
|
|
|
call .DetermineSpawnType
|
|
jr c, .next_scene
|
|
|
|
; Skip spawning if y = $FF
|
|
call .DetermineSpawnPosition
|
|
ret c
|
|
|
|
ldh a, [hSCX]
|
|
and $1f
|
|
ld e, a
|
|
ld a, 0
|
|
sub e
|
|
ld e, a
|
|
ld a, 3
|
|
ld [wSpriteAnimCount], a
|
|
|
|
ld a, SPRITE_ANIM_INDEX_MINIGAME_NOTE
|
|
call InitSpriteAnimStruct
|
|
|
|
; add one to the note counter
|
|
ld hl, wPikachuMinigameNoteCounter
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld a, 1
|
|
add e
|
|
daa
|
|
ld e, a
|
|
ld a, d
|
|
adc 0
|
|
daa
|
|
ld d, a
|
|
ld [hl], d
|
|
dec hl
|
|
ld [hl], e
|
|
ret
|
|
|
|
.next_scene ; can this be reached?
|
|
ld hl, wPikachuMinigameJumptableIndex
|
|
inc [hl]
|
|
ret
|
|
|
|
.DetermineSpawnType:
|
|
ld a, [wPikachuMinigameSpawnTypeIndex]
|
|
ld l, a
|
|
ld h, 0
|
|
ld de, .SpawnTypes
|
|
add hl, de
|
|
ld a, [hl]
|
|
cp -1
|
|
jr nz, .got_type
|
|
xor a
|
|
ld [wPikachuMinigameSpawnTypeIndex], a
|
|
.got_type
|
|
and a
|
|
ret
|
|
|
|
.SpawnTypes:
|
|
; or .SpawnPositions indices
|
|
db $00, $01, $02, $03, $04, $05, $06, $00, $01, $02, $03, $04, $05, $06
|
|
db -1
|
|
|
|
.DetermineSpawnPosition:
|
|
; a = spawn type (index of spawn data)
|
|
|
|
; returns d = Y-starting position of a note
|
|
; carry, if no note is to be spawned
|
|
|
|
ld l, a
|
|
ld h, 0
|
|
add hl, hl
|
|
add hl, hl
|
|
add hl, hl
|
|
ld de, .SpawnPositions
|
|
add hl, de
|
|
|
|
ld a, [wPikachuMinigameSpawnDataIndex]
|
|
and 7
|
|
ld e, a
|
|
inc a
|
|
cp 8
|
|
jr c, .determine_y_coords
|
|
|
|
; next spawn type
|
|
push hl
|
|
ld hl, wPikachuMinigameSpawnTypeIndex
|
|
inc [hl]
|
|
pop hl
|
|
|
|
.determine_y_coords
|
|
ld [wPikachuMinigameSpawnDataIndex], a
|
|
ld d, 0
|
|
add hl, de
|
|
ld a, [hl]
|
|
cp $ff
|
|
jr z, .skip_spawning_note
|
|
ld d, a
|
|
and a
|
|
ret
|
|
|
|
.skip_spawning_note
|
|
scf
|
|
ret
|
|
|
|
.SpawnPositions:
|
|
db $70, $60, $50, $48, $48, $48, $48, $38 ; 00
|
|
db $28, $20, $28, $ff, $ff, $ff, $48, $48 ; 01
|
|
db $70, $70, $ff, $58, $ff, $ff, $48, $38 ; 02
|
|
db $28, $20, $28, $38, $48, $ff, $ff, $ff ; 03
|
|
db $70, $70, $70, $70, $60, $50, $48, $38 ; 04
|
|
db $ff, $28, $30, $38, $48, $48, $48, $48 ; 05
|
|
db $ff, $ff, $ff, $ff, $ff, $ff, $ff, $ff ; 06
|
|
|
|
MinigamePikachuDoMovement::
|
|
; called from sprite animation routine
|
|
ld a, [wPikachuMinigamePikachuObjectPointer]
|
|
ld c, a
|
|
ld a, [wPikachuMinigamePikachuObjectPointer + 1]
|
|
ld b, a
|
|
call MinigamePikachuCheckFloorCollision
|
|
call .ResetScoreModifiersAndCheckNoteCollision
|
|
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
ld e, [hl]
|
|
ld d, 0
|
|
ld hl, .Jumptable
|
|
add hl, de
|
|
add hl, de
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
jp hl
|
|
|
|
.Jumptable:
|
|
dw .InitPikachuMovement
|
|
dw .ControlPikachu
|
|
dw .PikachuJumping
|
|
dw .FallDown
|
|
|
|
.InitPikachuMovement:
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
ld [hl], MINIGAME_PIKACHU_CONTROL
|
|
ld a, 2
|
|
ld [wPikachuMinigamePikachuNextAnim], a
|
|
ret
|
|
|
|
.ControlPikachu:
|
|
ldh a, [hJoyState]
|
|
ld hl, wPikachuMinigameControlEnable
|
|
and [hl]
|
|
ld d, a
|
|
|
|
and A_BUTTON
|
|
jr nz, .do_jump
|
|
|
|
; Don't animate Pikachu when the screen is still
|
|
ld a, [wPikachuMinigameScrollSpeed]
|
|
and a
|
|
ret nz
|
|
|
|
ld a, 1
|
|
ld [wPikachuMinigamePikachuNextAnim], a
|
|
ret
|
|
|
|
.do_jump
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
inc [hl]
|
|
ld a, 64
|
|
ld [wPikachuMinigamePikachuYOffset], a
|
|
ld a, 3
|
|
ld [wPikachuMinigamePikachuNextAnim], a
|
|
ld a, $10
|
|
ld [wc606], a
|
|
ret
|
|
|
|
.PikachuJumping:
|
|
ld hl, wPikachuMinigamePikachuYOffset
|
|
ld a, [hl]
|
|
cp 32
|
|
jr c, .fall_down_from_jump
|
|
dec [hl]
|
|
ld d, $30
|
|
ld e, a
|
|
farcall BattleAnim_Sine_e
|
|
ld a, e
|
|
ld hl, SPRITEANIMSTRUCT_YOFFSET
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
.fall_down_from_jump
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
ld [hl], MINIGAME_PIKACHU_FALLING
|
|
ret
|
|
|
|
.FallDown:
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, bc
|
|
inc [hl]
|
|
inc [hl]
|
|
inc [hl]
|
|
inc [hl]
|
|
ret
|
|
|
|
.ResetScoreModifiersAndCheckNoteCollision:
|
|
xor a
|
|
ld [wPikachuMinigameScoreModifier], a
|
|
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, SPRITEANIMSTRUCT_YOFFSET
|
|
add hl, bc
|
|
add [hl]
|
|
|
|
; Set the Y-collision range between Pikachu and note
|
|
; between y-$10 and y+$10
|
|
|
|
add $10
|
|
ld e, a
|
|
sub $10 * 2
|
|
ld d, a
|
|
push bc
|
|
|
|
; Check if the Pikachu object collides with any of the note
|
|
; objects.
|
|
|
|
ld bc, wSpriteAnim1
|
|
ld a, NUM_SPRITE_ANIM_STRUCTS
|
|
.check_note_object
|
|
push af
|
|
push de
|
|
ld hl, SPRITEANIMSTRUCT_INDEX
|
|
add hl, bc
|
|
ld a, [hl]
|
|
and a
|
|
; Deinitialized object, get the next object
|
|
jr z, .get_next_object
|
|
|
|
; Is the current object a note?
|
|
ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp 7
|
|
jr nz, .get_next_object
|
|
|
|
; Check if note collides with Pikachu
|
|
call .IsNoteColliding
|
|
|
|
.get_next_object
|
|
ld hl, SPRITEANIMSTRUCT_LENGTH
|
|
add hl, bc
|
|
ld c, l
|
|
ld b, h
|
|
pop de
|
|
pop af
|
|
dec a
|
|
jr nz, .check_note_object
|
|
pop bc
|
|
call PikachuMiniGame_AddToScore
|
|
ret
|
|
|
|
.IsNoteColliding:
|
|
; Is the note object within $48 - $68 (middle of the screen)?
|
|
ld a, $48
|
|
ld hl, SPRITEANIMSTRUCT_XCOORD
|
|
add hl, bc
|
|
cp [hl]
|
|
ret nc
|
|
|
|
ld a, $68
|
|
cp [hl]
|
|
ret c
|
|
|
|
; Is the note object within collision range?
|
|
ld a, d
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, bc
|
|
cp [hl]
|
|
ret nc
|
|
|
|
ld a, e
|
|
cp [hl]
|
|
ret c
|
|
|
|
; Pikachu caught a note
|
|
ld a, 1
|
|
ld [wPikachuMinigameNoteCaught], a
|
|
|
|
; Delete the note object
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
inc [hl]
|
|
|
|
ld hl, wPikachuMinigameScoreModifier
|
|
inc [hl]
|
|
ret
|
|
|
|
PikachuMiniGame_AddToScore:
|
|
ld hl, wPikachuMinigameScore
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld a, [wPikachuMinigameScoreModifier]
|
|
add e
|
|
daa
|
|
ld e, a
|
|
ld a, d
|
|
adc 0
|
|
daa
|
|
ld d, a
|
|
ld [hl], d
|
|
dec hl
|
|
ld [hl], e
|
|
ret
|
|
|
|
CopyPikachuObjDataToTailObj::
|
|
; copies the object data for Pikachu to Pikachu's tail object
|
|
; called from sprite animation routine
|
|
|
|
ld a, [wPikachuMinigamePikachuObjectPointer]
|
|
ld e, a
|
|
ld a, [wPikachuMinigamePikachuObjectPointer + 1]
|
|
ld d, a
|
|
|
|
ld a, [wPikachuMinigamePikachuTailObjectPointer]
|
|
ld c, a
|
|
ld a, [wPikachuMinigamePikachuTailObjectPointer + 1]
|
|
ld b, a
|
|
|
|
ld hl, SPRITEANIMSTRUCT_DURATIONOFFSET
|
|
add hl, de
|
|
ld a, [hl]
|
|
|
|
ld hl, SPRITEANIMSTRUCT_DURATIONOFFSET
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, de
|
|
ld a, [hl]
|
|
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ld hl, SPRITEANIMSTRUCT_YOFFSET
|
|
add hl, de
|
|
ld a, [hl]
|
|
|
|
ld hl, SPRITEANIMSTRUCT_YOFFSET
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ld hl, SPRITEANIMSTRUCT_XCOORD
|
|
add hl, de
|
|
ld a, [hl]
|
|
|
|
ld hl, SPRITEANIMSTRUCT_XCOORD
|
|
add hl, bc
|
|
ld [hl], a
|
|
|
|
ld hl, SPRITEANIMSTRUCT_XOFFSET
|
|
add hl, de
|
|
ld a, [hl]
|
|
|
|
ld hl, SPRITEANIMSTRUCT_XOFFSET
|
|
add hl, bc
|
|
ld [hl], a
|
|
ret
|
|
|
|
MinigamePikachuCheckFloorCollision:
|
|
ld hl, SPRITEANIMSTRUCT_YOFFSET
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, bc
|
|
add [hl]
|
|
ld d, a
|
|
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
ld a, [hl]
|
|
|
|
; Pikachu is jumping
|
|
cp MINIGAME_PIKACHU_JUMPING
|
|
jr z, .jumping
|
|
|
|
; Pikachu is falling
|
|
cp MINIGAME_PIKACHU_FALLING
|
|
jr z, .falling
|
|
|
|
ld a, d
|
|
cp $70
|
|
ret z
|
|
|
|
call .CheckCollidingFloor
|
|
ret nz
|
|
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
ld [hl], MINIGAME_PIKACHU_FALLING
|
|
ret
|
|
|
|
.jumping
|
|
ld a, [wPikachuMinigamePikachuYOffset]
|
|
cp $3e
|
|
ret nc
|
|
|
|
call .CheckCollidingFloor
|
|
ret z
|
|
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
ld [hl], MINIGAME_PIKACHU_INIT
|
|
ld hl, SPRITEANIMSTRUCT_YOFFSET
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [hl], 0
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, bc
|
|
add [hl]
|
|
and %11111000
|
|
ld [hl], a
|
|
ret
|
|
|
|
.falling
|
|
ld a, d
|
|
cp $70
|
|
jr z, .landed
|
|
call .CheckCollidingFloor
|
|
ret z
|
|
|
|
.landed
|
|
ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
|
|
add hl, bc
|
|
ld [hl], MINIGAME_PIKACHU_INIT
|
|
ld hl, SPRITEANIMSTRUCT_YOFFSET
|
|
add hl, bc
|
|
ld a, [hl]
|
|
ld [hl], 0
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, bc
|
|
add [hl]
|
|
and %11111000
|
|
ld [hl], a
|
|
ret
|
|
|
|
.CheckCollidingFloor:
|
|
; Returns z if we collided with a platform.
|
|
|
|
ld a, d
|
|
cp 64
|
|
jr z, .check_tile_below
|
|
xor a
|
|
ret
|
|
.check_tile_below
|
|
ld hl, wPikachuMinigameColumnBuffer
|
|
ld a, $16
|
|
cp [hl]
|
|
ret nz
|
|
inc hl
|
|
cp [hl]
|
|
ret nz
|
|
inc hl
|
|
cp [hl]
|
|
ret
|
|
|
|
|
|
PikachuMiniGame_ScrollScene:
|
|
ld hl, wPikachuMinigameScrollSpeed
|
|
ldh a, [hSCX]
|
|
sub [hl]
|
|
ldh [hSCX], a
|
|
and $10
|
|
ld hl, wPikachuMinigameRedrawTimer
|
|
cp [hl]
|
|
jr nz, .new_column
|
|
ret
|
|
.new_column
|
|
ld a, [hl]
|
|
xor $10
|
|
ld [hl], a
|
|
xor a
|
|
ldh [hBGMapMode], a
|
|
call PikachuMiniGame_RenderColumn
|
|
ldh a, [hSCX]
|
|
and $f0
|
|
srl a
|
|
srl a
|
|
srl a
|
|
ld e, a
|
|
ld d, 0
|
|
ld hl, vBGMap0
|
|
add hl, de
|
|
ld a, l
|
|
ldh [hRedrawRowOrColumnDest], a
|
|
ld a, h
|
|
ldh [hRedrawRowOrColumnDest + 1], a
|
|
ld a, $01
|
|
ldh [hRedrawRowOrColumnMode], a
|
|
ret
|
|
|
|
|
|
PikachuMiniGame_RenderColumn:
|
|
call PikachuMiniGame_GetNextColumn
|
|
ret nc
|
|
|
|
ld l, a
|
|
ld h, 0
|
|
add hl, hl
|
|
add hl, hl
|
|
add hl, hl
|
|
ld de, .ColumnSet
|
|
add hl, de
|
|
ld e, l
|
|
ld d, h
|
|
call PikachuMiniGame_UpdateColumn
|
|
ret
|
|
|
|
.ColumnSet:
|
|
; The "level" block set
|
|
; top to bottom
|
|
|
|
db $05, $0d, $02, $09, $14, $14, $14, $0b ; 00
|
|
db $04, $0c, $02, $08, $14, $14, $14, $0b ; 01
|
|
db $05, $0d, $02, $09, $15, $14, $14, $0b ; 02
|
|
db $04, $0c, $02, $08, $15, $14, $14, $0b ; 03
|
|
|
|
PikachuMiniGame_UpdateColumn:
|
|
push de
|
|
ld hl, wRedrawRowOrColumnSrcTiles
|
|
ld c, 8
|
|
.update
|
|
ld a, [de]
|
|
call PikachuMiniGame_DrawTileToBuffer
|
|
inc de
|
|
dec c
|
|
jr nz, .update
|
|
pop de
|
|
ret
|
|
|
|
PikachuMiniGame_DrawTileToBuffer:
|
|
push bc
|
|
push de
|
|
push hl
|
|
ld l, a
|
|
ld h, 0
|
|
ld a, [wPikachuMinigameTilesPointer]
|
|
ld e, a
|
|
ld a, [wPikachuMinigameTilesPointer + 1]
|
|
ld d, a
|
|
add hl, hl
|
|
add hl, hl
|
|
add hl, de
|
|
ld e, l
|
|
ld d, h
|
|
pop hl
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
ld a, [de]
|
|
inc de
|
|
ld [hli], a
|
|
pop de
|
|
pop bc
|
|
ret
|
|
|
|
PikachuMiniGame_GetNextColumn:
|
|
call .GetNextByte
|
|
cp $f0
|
|
ret c
|
|
|
|
call .GetColumnCommand
|
|
jr PikachuMiniGame_GetNextColumn
|
|
|
|
.GetColumnCommand:
|
|
sub $f0
|
|
ld e, a
|
|
ld d, 0
|
|
ld hl, .Jumptable
|
|
add hl, de
|
|
add hl, de
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
jp hl
|
|
|
|
.Jumptable:
|
|
dw .DummyCommand ; f0
|
|
dw .DummyCommand ; f1
|
|
dw .DummyCommand ; f2
|
|
dw .DummyCommand ; f3
|
|
dw .DummyCommand ; f4
|
|
dw .DummyCommand ; f5
|
|
dw .DummyCommand ; f6
|
|
dw .DummyCommand ; f7
|
|
dw .DummyCommand ; f8
|
|
dw .CommandF9 ; f9
|
|
dw .CommandFA ; fa
|
|
dw .CommandFB ; fb
|
|
dw .JumpCommand ; fc
|
|
dw .CommandFD ; fd
|
|
dw .CallCommand ; fe
|
|
dw .ReturnCommand ; ff
|
|
|
|
.DummyCommand:
|
|
ret
|
|
|
|
.ReturnCommand:
|
|
; End level subpart
|
|
|
|
ld hl, wPikachuMinigameColumnFlags
|
|
res 0, [hl]
|
|
|
|
ld hl, wPikachuMinigameSavedColumnPointer
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld hl, wPikachuMinigameColumnPointer
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
ret
|
|
|
|
.CallCommand:
|
|
; Call a level subpart
|
|
|
|
call .GetNextByte
|
|
ld e, a
|
|
call .GetNextByte
|
|
ld hl, wPikachuMinigameColumnPointer
|
|
ld c, [hl]
|
|
inc hl
|
|
ld b, [hl]
|
|
|
|
ld hl, wPikachuMinigameSavedColumnPointer
|
|
ld [hl], c
|
|
inc hl
|
|
ld [hl], b
|
|
|
|
ld hl, wPikachuMinigameColumnPointer + 1
|
|
ld [hld], a
|
|
ld [hl], e
|
|
|
|
ld hl, wPikachuMinigameColumnFlags
|
|
set 0, [hl]
|
|
ret
|
|
|
|
.JumpCommand:
|
|
; Jump to another part of the level
|
|
|
|
call .GetNextByte
|
|
ld e, a
|
|
call .GetNextByte
|
|
ld hl, wPikachuMinigameColumnPointer + 1
|
|
ld [hld], a
|
|
ld [hl], e
|
|
ret
|
|
|
|
.CommandFD:
|
|
call .GetNextByte
|
|
ld hl, wPikachuMinigameColumnFlags
|
|
bit 1, [hl]
|
|
jr nz, .flag_set
|
|
and a
|
|
jr z, .update_pointer
|
|
dec a
|
|
ld [wPikachuMinigameRepeatColumnCounter], a
|
|
set 1, [hl]
|
|
.flag_set
|
|
ld hl, wPikachuMinigameRepeatColumnCounter
|
|
ld a, [hl]
|
|
and a
|
|
jr z, .done
|
|
dec [hl]
|
|
.update_pointer
|
|
call .GetNextByte
|
|
ld e, a
|
|
call .GetNextByte
|
|
ld hl, wPikachuMinigameColumnPointer + 1
|
|
ld [hld], a
|
|
ld [hl], e
|
|
ret
|
|
.done
|
|
ld hl, wPikachuMinigameColumnFlags
|
|
res 2, [hl]
|
|
call .ReplaceColumnPointer
|
|
ret
|
|
|
|
.CommandF9:
|
|
call .GetNextByte
|
|
ld [wPikachuMinigameRepeatColumnCounter2], a
|
|
ret
|
|
|
|
.CommandFA:
|
|
ld hl, wPikachuMinigameRepeatColumnCounter2
|
|
inc [hl]
|
|
ret
|
|
|
|
.CommandFB:
|
|
call .GetNextByte
|
|
ld hl, wPikachuMinigameRepeatColumnCounter2
|
|
cp [hl]
|
|
jr z, .got_match
|
|
call .ReplaceColumnPointer
|
|
ret
|
|
.got_match
|
|
call .GetNextByte
|
|
ld e, a
|
|
call .GetNextByte
|
|
ld hl, wPikachuMinigameColumnPointer + 1
|
|
ld [hld], a
|
|
ld [hl], e
|
|
ret
|
|
|
|
.ReplaceColumnPointer:
|
|
ld hl, wPikachuMinigameColumnPointer
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
inc de
|
|
inc de
|
|
ld [hl], d
|
|
dec hl
|
|
ld [hl], e
|
|
ret
|
|
|
|
.GetNextByte:
|
|
push hl
|
|
push de
|
|
ld hl, wPikachuMinigameColumnPointer
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
ld a, [de]
|
|
inc de
|
|
ld [hl], d
|
|
dec hl
|
|
ld [hl], e
|
|
pop de
|
|
pop hl
|
|
ret
|
|
|
|
PikachuMiniGame_Columns:
|
|
; Essentially the "level design" of the minigame
|
|
; See also PikachuMiniGame_RenderColumn.ColumnSet
|
|
|
|
db $00, $01
|
|
db $00, $01
|
|
db $00, $01
|
|
db $00, $01
|
|
db $02, $03
|
|
db $02, $03
|
|
db $02, $03
|
|
db $02, $03
|
|
db $FC
|
|
dw PikachuMiniGame_Columns
|
|
db $FF
|
|
|
|
PikachuMiniGame_Blockmap:
|
|
INCBIN "gfx/minigames/pikachu_blockmap.bin"
|
|
|
|
PikachuMiniGame_Meta:
|
|
INCBIN "gfx/minigames/pikachu_blockset.bin"
|