summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRangi <35663410+Rangi42@users.noreply.github.com>2020-12-17 15:56:19 -0500
committerGitHub <noreply@github.com>2020-12-17 15:56:19 -0500
commitb1ae1098d06d9865c767471e539fa65f77101aaa (patch)
tree4b6d8fc9c449169705e224508a8d5e238fda18ab
parent9352a537c39471410314be76cf866e058a9349bf (diff)
parent37e60a9457643720dae714f8d2df0cf5ad31d919 (diff)
Merge pull request #84 from ZoomTen/pikachu-minigame
Disassemble opening cutscene, Game Freak intro, and Pikachu minigame
-rw-r--r--constants.asm2
-rw-r--r--constants/sfx_constants.asm5
-rwxr-xr-xconstants/sprite_anim_constants.asm60
-rwxr-xr-xengine/dumps/bank02.asm28
-rw-r--r--engine/games/pikachu_minigame.asm1447
-rw-r--r--engine/menu/text_entry.asm28
-rw-r--r--engine/movie/game_freak_intro.asm341
-rw-r--r--engine/movie/oak_speech.asm (renamed from engine/intro.asm)2
-rw-r--r--engine/movie/opening_cutscene.asm1237
-rw-r--r--engine/movie/title.asm (renamed from engine/title.asm)18
-rw-r--r--gfx/gfx.asm14
-rw-r--r--gfx/gfx.mk6
-rw-r--r--gfx/intro/forest.binbin0 -> 96 bytes
-rw-r--r--gfx/intro/forest_log.pngbin0 -> 5480 bytes
-rw-r--r--gfx/intro/forest_tilemap.bin128
-rw-r--r--gfx/intro/water.binbin0 -> 272 bytes
-rw-r--r--gfx/intro/water_tilemap.bin2
-rw-r--r--gfx/minigames/pikachu_blockmap.bin16
-rw-r--r--gfx/minigames/pikachu_blockset.binbin0 -> 96 bytes
-rw-r--r--layout.link16
-rw-r--r--ram/hram.asm1
-rw-r--r--ram/wram.asm99
-rwxr-xr-xshim.sym3
-rwxr-xr-xslack/slack.asm6
-rw-r--r--slack/unknown_e7e9f.binbin0 -> 353 bytes
25 files changed, 3406 insertions, 53 deletions
diff --git a/constants.asm b/constants.asm
index 5c29a51..1e79e49 100644
--- a/constants.asm
+++ b/constants.asm
@@ -31,9 +31,11 @@ INCLUDE "constants/item_data_constants.asm"
INCLUDE "constants/trainer_constants.asm"
INCLUDE "constants/trainer_data_constants.asm"
INCLUDE "constants/sprite_constants.asm"
+INCLUDE "constants/sprite_anim_constants.asm"
INCLUDE "constants/battle_constants.asm"
INCLUDE "constants/palette_constants.asm"
INCLUDE "constants/music_constants.asm"
+INCLUDE "constants/sfx_constants.asm"
INCLUDE "constants/landmark_constants.asm"
INCLUDE "constants/map_constants.asm"
INCLUDE "constants/map_setup_constants.asm"
diff --git a/constants/sfx_constants.asm b/constants/sfx_constants.asm
new file mode 100644
index 0000000..881ff52
--- /dev/null
+++ b/constants/sfx_constants.asm
@@ -0,0 +1,5 @@
+; TODO
+
+SFX_PAY_DAY EQU $30
+SFX_GAME_FREAK_LOGO_RG EQU $31
+
diff --git a/constants/sprite_anim_constants.asm b/constants/sprite_anim_constants.asm
new file mode 100755
index 0000000..08f6d69
--- /dev/null
+++ b/constants/sprite_anim_constants.asm
@@ -0,0 +1,60 @@
+; sprite_anim_struct members (see macros/wram.asm)
+ const_def
+ const SPRITEANIMSTRUCT_INDEX ; 0
+ const SPRITEANIMSTRUCT_FRAMESET_ID ; 1
+ const SPRITEANIMSTRUCT_ANIM_SEQ_ID ; 2
+ const SPRITEANIMSTRUCT_TILE_ID ; 3
+ const SPRITEANIMSTRUCT_XCOORD ; 4
+ const SPRITEANIMSTRUCT_YCOORD ; 5
+ const SPRITEANIMSTRUCT_XOFFSET ; 6
+ const SPRITEANIMSTRUCT_YOFFSET ; 7
+ const SPRITEANIMSTRUCT_DURATION ; 8
+ const SPRITEANIMSTRUCT_DURATIONOFFSET ; 9
+ const SPRITEANIMSTRUCT_FRAME ; a
+ const SPRITEANIMSTRUCT_JUMPTABLE_INDEX ; b
+ const SPRITEANIMSTRUCT_0C ; c
+ const SPRITEANIMSTRUCT_0D ; d
+ const SPRITEANIMSTRUCT_0E ; e
+ const SPRITEANIMSTRUCT_0F ; f
+SPRITEANIMSTRUCT_LENGTH EQU const_value
+NUM_SPRITE_ANIM_STRUCTS EQU 10 ; see wSpriteAnimationStructs
+
+; wSpriteAnimDict keys
+SPRITE_ANIM_DICT_DEFAULT EQU $00
+SPRITE_ANIM_DICT_GS_SPLASH EQU $27
+
+; wSpriteAnimDict size (see ram/wram.asm)
+NUM_SPRITEANIMDICT_ENTRIES EQU 10
+
+; SpriteAnimSeqData indexes
+SPRITE_ANIM_INDEX_08 EQU $08
+
+SPRITE_ANIM_INDEX_GS_INTRO_BUBBLE EQU $21
+SPRITE_ANIM_INDEX_GS_INTRO_OMANYTE EQU $22
+SPRITE_ANIM_INDEX_GS_INTRO_MAGIKARP EQU $23
+SPRITE_ANIM_INDEX_UNUSED_INTRO_AERODACTYL EQU $24
+SPRITE_ANIM_INDEX_GS_INTRO_LAPRAS EQU $25
+SPRITE_ANIM_INDEX_GS_INTRO_NOTE EQU $26
+SPRITE_ANIM_INDEX_GS_INTRO_SMALLER_NOTE EQU $27
+SPRITE_ANIM_INDEX_GS_INTRO_JIGGLYPUFF EQU $28
+SPRITE_ANIM_INDEX_GS_INTRO_PIKACHU EQU $29
+SPRITE_ANIM_INDEX_GS_INTRO_PIKACHU_TAIL EQU $2a
+SPRITE_ANIM_INDEX_GS_INTRO_FIREBALL EQU $2b
+SPRITE_ANIM_INDEX_GS_INTRO_BLASTOISE EQU $2c
+SPRITE_ANIM_INDEX_GS_INTRO_VENUSAUR EQU $2d
+
+SPRITE_ANIM_INDEX_GS_TITLE_FLAME_NOTE EQU $2e
+
+SPRITE_ANIM_INDEX_MINIGAME_PIKACHU EQU $2f
+SPRITE_ANIM_INDEX_MINIGAME_PIKACHU_TAIL EQU $30
+SPRITE_ANIM_INDEX_MINIGAME_NOTE EQU $31
+SPRITE_ANIM_INDEX_MINIGAME_JIGGLYPUFF EQU $32
+
+SPRITE_ANIM_INDEX_39 EQU $39
+SPRITE_ANIM_INDEX_GAMEFREAK_LOGO EQU $3a
+SPRITE_ANIM_INDEX_GS_INTRO_STAR EQU $3b
+SPRITE_ANIM_INDEX_GS_INTRO_SPARKLE EQU $3c
+SPRITE_ANIM_INDEX_40 EQU $40
+SPRITE_ANIM_INDEX_41 EQU $41
+SPRITE_ANIM_INDEX_44 EQU $44
+SPRITE_ANIM_INDEX_4B EQU $4b
diff --git a/engine/dumps/bank02.asm b/engine/dumps/bank02.asm
index 97590e4..1db4285 100755
--- a/engine/dumps/bank02.asm
+++ b/engine/dumps/bank02.asm
@@ -1150,8 +1150,8 @@ Function886a:
ld hl, vChars0 + $40
lb bc, BANK(GoldSpriteGFX), $04
call Request2bpp
- ld de, $0000
- ld a, $41
+ depixel 0, 0
+ ld a, SPRITE_ANIM_INDEX_41
call InitSpriteAnimStruct
ld hl, $0003
add hl, bc
@@ -1188,8 +1188,8 @@ Function88b3:
ld hl, vChars0 + $c0
lb bc, BANK(PidgeySpriteGFX), $04
call Request2bpp
- ld de, $0000
- ld a, $41
+ depixel 0, 0
+ ld a, SPRITE_ANIM_INDEX_41
call InitSpriteAnimStruct
ld hl, $0003
add hl, bc
@@ -1443,8 +1443,8 @@ Function8c21:
ld hl, wTileMapBackup
ld [hli], a
ld [hl], $7c
- ld de, $241c
- ld a, $44
+ depixel 4, 3, 4, 4
+ ld a, SPRITE_ANIM_INDEX_44
call InitSpriteAnimStruct
call Function8c1c
ret
@@ -1568,8 +1568,8 @@ Function8cb7:
ld hl, Text91c2
call PrintText
call WaitBGMap
- ld de, $4c23
- ld a, $44
+ depixel 9, 4, 4, 3
+ ld a, SPRITE_ANIM_INDEX_44
call InitSpriteAnimStruct
ld hl, $0002
add hl, bc
@@ -1577,8 +1577,8 @@ Function8cb7:
ld hl, $0003
add hl, bc
ld [hl], $7c
- ld de, $4030
- ld a, $4b
+ depixel 8, 6
+ ld a, SPRITE_ANIM_INDEX_4B
call InitSpriteAnimStruct
ld hl, $0003
add hl, bc
@@ -2486,19 +2486,19 @@ Function9604:
ld [hl], e
ret
-Function962d:
+LoadMagikarpPalettes_Intro:
ld hl, Data997c
jp Function964b
-Function9633:
+LoadForestPalettes2_Intro:
ld hl, Data986c
jp Function964b
-Function9639:
+LoadVenusaurPalettes_Intro:
ld hl, Data99ac
jp Function964b
-Function963f:
+LoadCharizardPalettes_Intro:
ld hl, Data99bc
jp Function964b
diff --git a/engine/games/pikachu_minigame.asm b/engine/games/pikachu_minigame.asm
new file mode 100644
index 0000000..de930da
--- /dev/null
+++ b/engine/games/pikachu_minigame.asm
@@ -0,0 +1,1447 @@
+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_BETA_PIKACHU_MINIGAME
+ call GetSGBLayout
+ callab 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
+ callba 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:
+ callab InitEffectObject
+
+ ld hl, wVirtualOAM
+ 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
+ callba 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"
diff --git a/engine/menu/text_entry.asm b/engine/menu/text_entry.asm
index 14dbc85..f6700f2 100644
--- a/engine/menu/text_entry.asm
+++ b/engine/menu/text_entry.asm
@@ -147,8 +147,8 @@ GetNamingScreenSetup:
ld hl, wTileMapBackup
ld [hl+], a
ld [hl], $00
- ld de, $2420
- ld a, $41
+ depixel 4, 4, 4, 0
+ ld a, SPRITE_ANIM_INDEX_41
call InitSpriteAnimStruct
ld hl, $0001
add hl, bc
@@ -180,8 +180,8 @@ GetNamingScreenSetup:
ld hl, wTileMapBackup
ld [hli], a
ld [hl], $00
- ld de, $2420
- ld a, $41
+ depixel 4, 4, 4, 0
+ ld a, SPRITE_ANIM_INDEX_41
call InitSpriteAnimStruct
ret
@@ -301,8 +301,8 @@ NamingScreenJoypadLoop:
dw .ReadButtons
.InitCursor:
- ld de, $5818
- ld a, $39
+ depixel 11, 3, 0, 0
+ ld a, SPRITE_ANIM_INDEX_39
call InitSpriteAnimStruct
ld a, c
ld [wNamingScreenCursorObjectPointer], a
@@ -728,14 +728,14 @@ ComposeMailMessage:
ld hl, wTileMapBackup
ld [hli], a
ld [hl], 0
- ld de, $2420
- ld a, 8
+ depixel 4, 4, 4, 0
+ ld a, SPRITE_ANIM_INDEX_08
call InitSpriteAnimStruct
ld hl, $0002
add hl, bc
ld [hl], 0
- ld de, $5818
- ld a, $39
+ depixel 11, 3, 0, 0
+ ld a, SPRITE_ANIM_INDEX_39
call InitSpriteAnimStruct
ld a, c
ld [wNamingScreenCursorObjectPointer], a
@@ -945,14 +945,14 @@ SetupMail:
ld hl, wTileMapBackup
ld [hli], a
ld [hl], 0
- ld de, $2420
- ld a, 8
+ depixel 4, 4, 4, 0
+ ld a, SPRITE_ANIM_INDEX_08
call InitSpriteAnimStruct
ld hl, $0002
add hl, bc
ld [hl], 0
- ld de, $6018
- ld a, $40
+ depixel 12, 3, 0, 0
+ ld a, SPRITE_ANIM_INDEX_40
call InitSpriteAnimStruct
ld a, c
ld [wNamingScreenCursorObjectPointer], a
diff --git a/engine/movie/game_freak_intro.asm b/engine/movie/game_freak_intro.asm
new file mode 100644
index 0000000..9ae95c9
--- /dev/null
+++ b/engine/movie/game_freak_intro.asm
@@ -0,0 +1,341 @@
+INCLUDE "constants.asm"
+
+SECTION "engine/movie/game_freak_intro.asm", ROMX
+
+GameFreakIntro::
+; Copyright screen and Game Freak logo
+
+ call DisableLCD
+ call ClearVRAM
+
+ ld a, HIGH(vBGMap0)
+ ldh [hBGMapAddress + 1], a
+ xor a
+ ldh [hBGMapAddress], a
+ ldh [hJoyState], a
+ ldh [hSCX], a
+ ldh [hSCY], a
+
+ ld a, $90
+ ldh [hWY], a
+
+ call EnableLCD
+
+ ld c, 10
+ call DelayFrames
+ ld b, SGB_GS_TITLE_SCREEN
+ call GetSGBLayout
+
+ callab IntroCopyRightInfo
+
+ ld a, 1
+ ldh [hBGMapMode], a
+ call WaitBGMap
+ call SetPalettes
+
+ ld c, 3 * 60 ; 3 seconds
+ call DelayFrames
+
+ xor a
+ ldh [hWY], a
+ call ClearTileMap
+
+ call .Init
+.loop
+ call .Frame
+ jr nc, .loop
+
+; this was set if user skipped the GF logo by pressing A
+ ld a, [wJumptableIndex]
+ bit 6, a
+ jr nz, .cancelled
+
+; clear carry flag from .PlayFrame
+ and a
+ ret
+
+.cancelled
+ scf
+ ret
+
+.Init:
+ call DisableLCD
+
+ ld hl, vBGMap0
+ ld bc, BG_MAP_WIDTH * SCREEN_HEIGHT
+ xor a
+ call ByteFill
+
+ ld de, GameFreakLogoGFX
+ ld hl, vChars1
+ lb bc, BANK(GameFreakLogoGFX), 28
+ call Get1bpp
+
+ ld hl, GameFreakLogoSparkleGFX
+ ld de, vChars1 tile $1C
+ ld bc, 5 tiles
+ ld a, BANK(GameFreakLogoSparkleGFX)
+ call FarCopyData
+
+ callba InitEffectObject
+
+ ld hl, wSpriteAnimDict
+ ld a, SPRITE_ANIM_DICT_GS_SPLASH
+ ld [hli], a
+ ld a, $8d
+ ld [hl], a
+
+ xor a
+ ld [wJumptableIndex], a
+ ld [wIntroSceneFrameCounter], a
+ ld [wIntroSceneTimer], a
+ ldh [hSCX], a
+ ldh [hSCY], a
+
+ ld a, 1
+ ldh [hBGMapMode], a
+
+ ld a, SCREEN_HEIGHT_PX
+ ldh [hWY], a
+ call EnableLCD
+
+ ld a, %11100100
+ ld a, %11100100 ; redundant
+ ldh [rOBP0], a
+ ld a, %00100100
+ ldh [rOBP1], a
+ ret
+
+
+.Frame:
+; Play one frame of GameFreakPresents sequence.
+; Return carry when the sequence completes or is canceled.
+ ld hl, hJoypadDown
+ ld a, [hl]
+ and %00001111
+ jr nz, .pressed
+
+ ld a, [wJumptableIndex]
+ bit 7, a
+ jr nz, .Finished
+
+ callba EffectObjectJumpNoDelay
+
+ call GameFreakPresentsScene
+ call DelayFrame
+ and a
+ ret
+
+.pressed
+ ld hl, wJumptableIndex
+ set 6, [hl]
+
+.Finished:
+ callab InitEffectObject
+ call ClearTileMap
+ call ClearSprites
+
+ ld c, 16
+ call DelayFrames
+
+ scf
+ ret
+
+
+GameFreakPresentsScene:
+ jumptable .scenes, wJumptableIndex
+
+.scenes
+ dw GameFreakPresents_Wait64Frames
+ dw GameFreakPresents_Star
+ dw GameFreakPresents_PlaceLogo
+ dw GameFreakPresents_LogoSparkles
+ dw GameFreakPresents_PlacePresents
+ dw GameFreakPresents_WaitForTimer
+ dw GameFreakPresents_SetDoneFlag
+
+GameFreakPresents_NextScene:
+ ld hl, wJumptableIndex
+ inc [hl]
+ ret
+
+GameFreakPresents_Wait64Frames:
+ ld c, $40
+ call DelayFrames
+ call GameFreakPresents_NextScene
+ ret
+
+GameFreakPresents_Star:
+ xor a
+ ld [wIntroSceneFrameCounter], a
+ depixel 10, 11, 4, 0
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_STAR
+ call InitSpriteAnimStruct
+
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], $a0 ; star path radius
+
+ ld de, SFX_GAME_FREAK_LOGO_RG
+ call PlaySFX
+ call GameFreakPresents_NextScene
+ ret
+
+GameFreakPresents_PlaceLogo:
+ ld a, [wIntroSceneFrameCounter]
+ and a
+ ret z
+
+ depixel 10, 11, 4, 0
+ ld a, SPRITE_ANIM_INDEX_GAMEFREAK_LOGO
+ call InitSpriteAnimStruct
+ call GameFreakPresents_NextScene
+
+; set timer for the next scene
+ ld a, 128
+ ld [wIntroSceneTimer], a
+ ret
+
+GameFreakPresents_LogoSparkles:
+ ld hl, wIntroSceneTimer
+ ld a, [hl]
+ and a
+ jr z, .done
+ dec [hl]
+
+; add first text when timer passes half
+ cp 63
+ call z, GameFreakPresents_PlaceGameFreak
+
+; add sparkles continuously
+ call GameFreakPresents_Sparkle
+ ret
+
+.done
+; set timer for the next scene and go there
+ ld [hl], 128
+ call GameFreakPresents_NextScene
+ ret
+
+
+GameFreakPresents_PlaceGameFreak:
+ hlcoord 5, 12
+ ld de, .game_freak
+ call PlaceString
+ ret
+
+.game_freak
+; G A M E F R E A K
+ db $80, $81, $82, $83, $8d, $84, $85, $83, $81, $86
+ db "@"
+
+GameFreakPresents_PlacePresents:
+ hlcoord 7, 13
+ ld de, .presents
+ call PlaceString
+ call GameFreakPresents_NextScene
+ ld a, $80
+ ld [wIntroSceneTimer], a
+ ret
+
+.presents
+; P R E S E N T S
+ db $87, $88, $89, $8a, $8b, $8c
+ db "@"
+
+GameFreakPresents_SetDoneFlag:
+ ld hl, wJumptableIndex
+ set 7, [hl]
+ ret
+
+GameFreakPresents_WaitForTimer:
+ ld hl, wIntroSceneTimer
+ ld a, [hl]
+ and a
+ jr z, .done
+ dec [hl]
+ ret
+.done
+ call GameFreakPresents_NextScene
+ ret
+
+GameFreakPresents_UpdateLogoPal:
+; called from sprite animation routine
+
+; once we reached the final state, leave it alone
+ ldh a, [rOBP1]
+ cp %10010000
+ ret z
+
+; wait 16 frames before next change
+ ld a, [wIntroSceneTimer]
+ and $0f
+ ret nz
+
+; rotate OBP1 by one color slot (2 bits)
+ ld hl, rOBP1
+ rrc [hl]
+ rrc [hl]
+ ret
+
+
+GameFreakPresents_Sparkle:
+; Initialize and configure a sparkle sprite.
+
+; run only every second frame
+ ld d, a
+ and 1
+ ret nz
+
+; shift over so our index is still changing by 1 each time
+ ld a, d
+ srl a
+; set up a new sparkle sprite
+ push af
+ depixel 11, 11
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_SPARKLE
+ call InitSpriteAnimStruct
+ pop af
+
+; take the bottom 4 bits of a as an index into
+; sparkle_vectors (16 entries)
+ and %00001111
+ ld e, a
+ ld d, 0
+ ld hl, .vectors
+ add hl, de
+ add hl, de
+
+; set the angle and distance for this sprite
+ ld e, l
+ ld d, h
+ ld hl, SPRITEANIMSTRUCT_JUMPTABLE_INDEX
+ add hl, bc
+ ld a, [de]
+ ld [hl], a ; angle
+ inc de
+ ld hl, SPRITEANIMSTRUCT_0C
+ add hl, bc
+ ld [hl], 0
+ inc hl ; SPRITEANIMSTRUCT_0D
+ ld a, [de]
+ ld [hl], a ; distance
+ ret
+
+.vectors
+ db $00, $03
+ db $08, $04
+ db $04, $03
+ db $0c, $02
+ db $10, $02
+ db $18, $03
+ db $14, $04
+ db $1c, $03
+ db $20, $02
+ db $28, $02
+ db $24, $03
+ db $2c, $04
+ db $30, $04
+ db $38, $03
+ db $34, $02
+ db $3c, $04
diff --git a/engine/intro.asm b/engine/movie/oak_speech.asm
index 070862d..5941f65 100644
--- a/engine/intro.asm
+++ b/engine/movie/oak_speech.asm
@@ -1,6 +1,6 @@
INCLUDE "constants.asm"
-SECTION "engine/intro.asm", ROMX
+SECTION "engine/movie/oak_speech.asm", ROMX
DemoStart::
ld de, OakPic
diff --git a/engine/movie/opening_cutscene.asm b/engine/movie/opening_cutscene.asm
new file mode 100644
index 0000000..c98050d
--- /dev/null
+++ b/engine/movie/opening_cutscene.asm
@@ -0,0 +1,1237 @@
+INCLUDE "constants.asm"
+
+SECTION "engine/movie/opening_cutscene.asm", ROMX
+
+OpeningCutscene::
+ call .Init
+.loop
+ call .PlayFrame
+ jr nc, .loop
+ ret
+
+.Init:
+ callba InitEffectObject
+ xor a
+ ld [wIntroJumptableIndex], a
+ ldh [hBGMapMode], a
+ ret
+
+.PlayFrame:
+ ld hl, hJoypadDown
+ ld a, [hl]
+ and $f
+ jr nz, .Finish
+
+; check done flag
+ ld a, [wIntroJumptableIndex]
+ bit 7, a
+ jr nz, .Finish
+
+ callba EffectObjectJumpNoDelay
+ call IntroSceneJumper
+ call DelayFrame
+ and a
+ ret
+
+.Finish:
+ callab InitEffectObject
+ call ClearSprites
+ call DelayFrame
+ xor a
+ ldh [hSCX], a
+ ldh [hSCY], a
+ ldh [hLCDCPointer], a
+ ldh [hLYOverrideStart], a
+ ldh [hLYOverrideEnd], a
+ ld a, %11100100
+ ldh [rBGP], a
+ ldh [rOBP0], a
+ scf
+ ret
+
+IntroSceneJumper:
+ jumptable .scenes, wIntroJumptableIndex
+.scenes
+ dw IntroScene1
+ dw IntroScene2
+ dw IntroScene3
+ dw IntroScene4
+ dw IntroScene5
+ dw IntroScene6
+ dw IntroScene7
+ dw IntroScene8
+ dw IntroScene9
+ dw IntroScene10
+ dw IntroScene11
+ dw IntroScene12
+ dw IntroScene13
+ dw IntroScene14
+ dw IntroScene15
+ dw IntroScene16
+ dw IntroScene17
+
+IntroScene1:
+; Set up water cutscene
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ call DisableLCD
+
+ ld b, SGB_GS_INTRO
+ ld c, 0
+ call GetSGBLayout
+
+ callab InitEffectObject
+
+ call Intro_ResetLYOverrides
+
+ ld hl, vChars2
+ ld de, IntroUnderwaterGFX
+ call Intro_Copy128Tiles
+
+; Load water metatiles
+ ld a, LOW(Intro_WaterMeta)
+ ld [wIntroTilesPointer + 0], a
+ ld a, HIGH(Intro_WaterMeta)
+ ld [wIntroTilesPointer + 1], a
+
+; Set destination BG map pointer
+ ld hl, vBGMap0
+ ld a, l
+ ld [wIntroBGMapPointer + 0], a
+ ld a, h
+ ld [wIntroBGMapPointer + 1], a
+
+; Load water tilemap (shifted to starting position)
+ ld de, Intro_WaterTilemap + $F0
+ ld a, e
+ ld [wIntroTilemapPointer + 0], a
+ ld a, d
+ ld [wIntroTilemapPointer + 1], a
+ call Intro_DrawBackground
+
+; draw GFX
+ ld hl, IntroWaterPokemonGFX
+ ld de, vChars0
+ ld bc, $80 tiles
+.draw_gfx
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec bc
+ ld a, b
+ or c
+ jr nz, .draw_gfx
+
+ ld hl, wSpriteAnimDict
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_BUBBLE
+ ld [hli], a
+ ld a, SPRITE_ANIM_DICT_DEFAULT
+ ld [hli], a
+
+ xor a
+ ldh [hSCY], a
+ ld [wGlobalAnimYOffset], a
+ ld [wGlobalAnimXOffset], a
+
+ ld a, $58
+ ldh [hSCX], a
+
+; setup counter for the first scene
+ xor a
+ ld [wIntroFrameCounter2], a
+ ld a, $80
+ ld [wIntroFrameCounter1], a
+
+ ld a, LOW(rSCY)
+ ldh [hLCDCPointer], a
+ call Intro_InitSineLYOverrides
+
+ xor a ; FALSE
+ ld [wIntroSpriteStateFlag], a
+
+ call EnableLCD
+ call DelayFrame
+
+ ld a, %11100100
+ ldh [rBGP], a
+ ld a, %11100000
+ ldh [rOBP0], a
+ call Intro_InitOmanyte
+ ret
+
+IntroScene2:
+ call Intro_UpdateLYOverrides
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ and a
+ jr z, .skip_intro
+ dec [hl]
+ call Intro_InitBubble
+ ret
+
+.skip_intro
+ ld [hl], $10
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+
+IntroScene3:
+; rise towards the surface
+ call IntroScene3_Jumper
+ call IntroScene3_ScrollToSurface
+ ret nc
+; next scene if carry flag is set
+ call Intro_ResetLYOverrides
+ ld hl, hSCY
+ inc [hl]
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+
+IntroScene4:
+; at surface; Lapras surfs to left of screen
+ ld a, [wIntroSpriteStateFlag]
+ and a
+ jr nz, .next
+ ld hl, wIntroFrameCounter2
+ inc [hl]
+ ld a, [hl]
+ and $7
+ jr nz, .skip_move_left
+ ld hl, hSCX
+ dec [hl]
+
+.skip_move_left
+ call Intro_AnimateOceanWaves
+ ret
+
+.next
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ xor a
+ ld [wIntroFrameCounter1], a
+
+IntroScene5:
+; scroll right and fade out to white
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ inc [hl]
+ swap a
+ and $f
+ ld e, a
+ ld d, 0
+ ld hl, .palettes
+ add hl, de
+ ld a, [hl]
+ cp -1
+ jr z, .next
+ ldh [rBGP], a
+ call Intro_AnimateOceanWaves
+ ld hl, hSCX
+ dec [hl]
+ dec [hl]
+ ret
+.next
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ ret
+
+.palettes:
+ dc 3, 2, 1, 0
+ dc 3, 2, 1, 0
+ dc 2, 1, 0, 0
+ dc 1, 0, 0, 0
+ dc 0, 0, 0, 0
+ db -1
+
+IntroScene17:
+; delay a bit before leading into the title screen
+ ld c, 64
+.loop
+ call DelayFrame
+ dec c
+ jr nz, .loop
+; set done flag
+ ld hl, wIntroJumptableIndex
+ set 7, [hl]
+ ret
+
+IntroScene3_ScrollToSurface:
+ ld hl, wIntroFrameCounter2
+ inc [hl]
+ ld a, [hl]
+ and %00000011
+ jr nz, .skip_move_left
+ ld hl, hSCX
+ dec [hl]
+
+.skip_move_left
+ and 1
+ jr nz, .no_carry
+ ld hl, wGlobalAnimYOffset
+ inc [hl]
+ ld hl, hSCY
+ ld a, [hl]
+ dec [hl]
+ and $f
+ call z, Intro_UpdateTilemapAndBGMap
+ ld a, [wIntroFrameCounter1]
+ and a
+ jr z, .carry
+
+.no_carry
+ and a
+ ret
+
+.carry
+ scf
+ ret
+
+IntroScene3_Jumper:
+ jumptable .subroutines, wIntroFrameCounter1
+
+.subroutines:
+ dw .scene3_2
+ dw .scene3_2
+ dw .scene3_2
+ dw .scene3_1
+ dw .scene3_2
+ dw .scene3_2
+ dw .scene3_3
+ dw .scene3_3
+ dw .scene3_3
+ dw .scene3_4
+ dw .scene3_5
+ dw .scene3_6
+ dw .scene3_6
+ dw .scene3_6
+ dw .scene3_6
+ dw .scene3_6
+ dw .scene3_6
+
+.scene3_1:
+ call Intro_InitLapras
+ ld a, %11100100
+ ldh [rOBP0], a
+; fallthrough
+
+.scene3_2:
+ call Intro_AnimateOceanWaves
+ ret
+
+.scene3_3:
+ call Intro_InitMagikarps
+ call Intro_AnimateOceanWaves
+ ret
+
+.scene3_4:
+ ld hl, wIntroFrameCounter2
+ ld a, [hl]
+ and %00011111
+ jr z, .load_palettes
+ call Intro_InitMagikarps
+ ret
+.load_palettes
+ callab LoadMagikarpPalettes_Intro
+ ret
+
+.scene3_5:
+ xor a
+ ldh [hLCDCPointer], a
+ ret
+
+.scene3_6:
+ call Intro_UpdateLYOverrides
+ ret
+
+Intro_InitBubble:
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ and $f
+ ret nz
+
+ ld a, [hl]
+ and $70
+ swap a
+ ld e, a
+ ld d, 0
+ ld hl, .pixel_table
+ add hl, de
+ add hl, de
+ ld e, [hl]
+ inc hl
+ ld d, [hl]
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_BUBBLE
+ call InitSpriteAnimStruct
+ ret
+
+.pixel_table:
+ dbpixel 6, 14, 0, 4
+ dbpixel 14, 18, 0, 4
+ dbpixel 10, 16, 0, 4
+ dbpixel 12, 15, 0, 0
+ dbpixel 4, 13, 0, 0
+ dbpixel 8, 17, 0, 0
+
+Intro_InitMagikarps:
+ depixel 8, 7, 0, 7
+ ld a, [wSGB]
+ and a
+ jr z, .ok
+ depixel 4, 3, 0, 7
+
+.ok
+ ld hl, wIntroFrameCounter2
+ ld a, [hl]
+ and e
+ ret nz
+ ld a, [hl]
+ and d
+ jr nz, .alternate_frame
+
+ depixel 29, 28
+ call .PlaceMagikarp
+
+ depixel 26, 0
+ call .PlaceMagikarp
+
+ depixel 0, 24
+ call .PlaceMagikarp
+ ret
+
+.alternate_frame
+ depixel 28, 30
+ call .PlaceMagikarp
+
+ depixel 31, 24
+ call .PlaceMagikarp
+
+ depixel 2, 28
+ call .PlaceMagikarp
+ ret
+
+.PlaceMagikarp:
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_MAGIKARP
+ call InitSpriteAnimStruct
+ ret
+
+Intro_InitOmanyte:
+ depixel 18, 7
+ call .PlaceOmanyte
+ depixel 14, 10
+ call .PlaceOmanyte
+ depixel 16, 15
+; fallthrough
+
+.PlaceOmanyte:
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_OMANYTE
+ call InitSpriteAnimStruct
+ ret
+
+Intro_InitLapras:
+ ld a, [wIntroFrameCounter2]
+ and %00011111
+ ret nz
+ depixel 16, 24
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_LAPRAS
+ call InitSpriteAnimStruct
+ ret
+
+Intro_UnusedInitAerodactyl: ; unreferenced
+ depixel 2, 0
+ ld a, SPRITE_ANIM_INDEX_UNUSED_INTRO_AERODACTYL
+ call InitSpriteAnimStruct
+ ret
+
+Intro_UpdateTilemapAndBGMap:
+; add new tiles to top as water scene scrolls up to surface
+ push hl
+ push de
+
+ ld a, [wIntroTilemapPointer + 0]
+ ld e, a
+ ld a, [wIntroTilemapPointer + 1]
+ ld d, a
+ ld hl, -BG_MAP_WIDTH / 2
+ add hl, de
+ ld a, l
+ ld e, l
+ ld [wIntroTilemapPointer + 0], a
+ ld a, h
+ ld d, h
+ ld [wIntroTilemapPointer + 1], a
+
+ hlcoord 0, 0
+ ld c, BG_MAP_WIDTH / 2
+.loop
+ call Intro_Draw2x2Tiles
+ dec c
+ jr nz, .loop
+
+ ld a, [wIntroBGMapPointer + 0]
+ ld e, a
+ ld a, [wIntroBGMapPointer + 1]
+ ld d, a
+ ld hl, hCurSpriteYCoord
+ add hl, de
+ ld a, l
+ ld [wIntroBGMapPointer + 0], a
+ ld [wVBCopyDst], a
+ ld a, h
+ and %11111011
+ or %00001000
+ ld [wIntroBGMapPointer + 1], a
+ ld [wVBCopyDst + 1], a
+ ld a, LOW(wTileMap)
+ ld [wVBCopySrc], a
+ ld a, HIGH(wTileMap)
+ ld [wVBCopySrc + 1], a
+ ld a, 4
+ ld [wVBCopySize], a
+ ld hl, wIntroFrameCounter1
+ dec [hl]
+ pop de
+ pop hl
+ ret
+
+Intro_AnimateOceanWaves:
+; uses a 2bpp request to copy tile IDs to the BG map
+ ld hl, wIntroFrameCounter2
+ ld a, [hl]
+ and 3
+ cp 3
+ ret z
+
+ ld a, [hl]
+ and $30
+ swap a
+ ld l, a
+ ld h, 0
+rept 5
+ add hl, hl
+endr
+ ld de, .wave_tiles
+ add hl, de
+ ld a, l
+ ld [wVBCopySrc], a
+ ld a, h
+ ld [wVBCopySrc + 1], a
+ ld a, LOW(vBGMap0 + 15 * BG_MAP_WIDTH)
+ ld [wVBCopyDst], a
+ ld a, HIGH(vBGMap0 + 15 * BG_MAP_WIDTH)
+ ld [wVBCopyDst + 1], a
+ ld a, 2
+ ld [wVBCopySize], a
+ ret
+
+.wave_tiles:
+; Fill an entire bg map row with each frame
+rept 8
+ db $70, $71, $72, $73 ; frame 1
+endr
+
+rept 8
+ db $74, $75, $76, $77 ; frame 2
+endr
+
+rept 8
+ db $78, $79, $7a, $7b ; frame 3
+endr
+
+rept 8
+ db $7c, $7d, $7e, $7f ; frame 4
+endr
+
+Intro_InitSineLYOverrides:
+ ld bc, wLYOverrides2
+ ld a, SCREEN_HEIGHT_PX
+ ld de, BG_MAP_WIDTH * BG_MAP_HEIGHT
+.loop
+ push af
+ push de
+ callba BattleAnim_Sine_e
+ ld a, e
+ ld [bc], a
+ inc bc
+ pop de
+ inc e
+ pop af
+ dec a
+ jr nz, .loop
+ ret
+
+Intro_UpdateLYOverrides:
+ ld bc, wLYOverrides
+ ld e, $10
+
+.loop1
+ ldh a, [hSCY]
+ ld [bc], a
+ inc bc
+ dec e
+ jr nz, .loop1
+
+ ld hl, wLYOverrides2
+ ld de, wLYOverrides2 + 1
+ ld a, [hl]
+ push af
+ ld a, $80
+
+.loop2
+ push af
+ ld a, [de]
+ inc de
+ ld [hli], a
+ push hl
+ ld hl, hSCY
+ add [hl]
+ ld [bc], a
+ inc bc
+ pop hl
+ pop af
+ dec a
+ jr nz, .loop2
+
+ pop af
+ ld [hl], a
+ ret
+
+IntroScene6:
+; Set up grass cutscene (Pikachu / Jigglypuff)
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ call DisableLCD
+ ld b, SGB_GS_INTRO
+ ld c, 1
+ call GetSGBLayout
+ callab InitEffectObject
+ call Intro_ResetLYOverrides
+ ld hl, vChars2
+ ld de, IntroForestGFX
+ call Intro_Copy128Tiles
+ ld a, LOW(Intro_GrassMeta)
+ ld [wIntroTilesPointer + 0], a
+ ld a, HIGH(Intro_GrassMeta)
+ ld [wIntroTilesPointer + 1], a
+ ld hl, vBGMap0
+ ld a, l
+ ld [wIntroBGMapPointer + 0], a
+ ld a, h
+ ld [wIntroBGMapPointer + 1], a
+ ld de, Intro_GrassTilemap
+ ld a, e
+ ld [wIntroTilemapPointer + 0], a
+ ld a, d
+ ld [wIntroTilemapPointer + 1], a
+ call Intro_DrawBackground
+ ld hl, IntroJigglypuffPikachuGFX
+ ld de, vChars0
+ ld bc, 160 tiles ; last 16 tiles actually belong to charizard's gfx
+
+.load
+ ld a, [hli]
+ ld [de], a
+ inc de
+ dec bc
+ ld a, b
+ or c
+ jr nz, .load
+
+ ld hl, wSpriteAnimDict
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_OMANYTE
+ ld [hli], a
+ ld a, SPRITE_ANIM_DICT_DEFAULT
+ ld [hli], a
+ xor a
+ ldh [hSCY], a
+ ld [wGlobalAnimYOffset], a
+ ld a, $60
+ ldh [hSCX], a
+ ld a, $a0
+ ld [wGlobalAnimXOffset], a
+ xor a
+ ld [wIntroFrameCounter2], a
+ call EnableLCD
+ ld a, %11100100
+ ldh [rBGP], a
+ ldh [rOBP0], a
+ call Intro_InitJigglypuff
+ xor a
+ ld [wIntroSpriteStateFlag], a
+ ret
+
+IntroScene7:
+ call Intro_InitNote
+ ld hl, wIntroFrameCounter2
+ ld a, [hl]
+ inc [hl]
+ and $3
+ ret z
+
+ ld hl, hSCX
+ ld a, [hl]
+ and a
+ jr z, .next
+
+ dec [hl]
+ ld hl, wGlobalAnimXOffset
+ inc [hl]
+ ret
+
+.next
+ ld a, $ff
+ ld [wIntroFrameCounter1], a
+ call Intro_InitPikachu
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ ret
+
+IntroScene8:
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ and a
+ jr z, .next
+ dec [hl]
+ call Intro_InitNote
+ ld hl, wIntroFrameCounter2
+ inc [hl]
+ ret
+
+.next
+ xor a
+ ld [wIntroFrameCounter1], a
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ callab LoadForestPalettes2_Intro
+ ret
+
+IntroScene9:
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ inc [hl]
+ swap a
+ and $f
+ ld e, a
+ ld d, 0
+ ld hl, .palettes
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .next
+
+ ldh [rBGP], a
+ ld hl, hSCY
+ inc [hl]
+ ld hl, wGlobalAnimYOffset
+ dec [hl]
+ ret
+
+.next:
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ ret
+
+.palettes:
+; fade out to black
+ dc 3, 2, 1, 0
+ dc 3, 2, 1, 0
+ dc 3, 2, 1, 0
+ dc 3, 2, 1, 0
+ dc 3, 2, 1, 0
+ dc 3, 3, 2, 1
+ dc 3, 3, 3, 2
+ dc 3, 3, 3, 3
+ db 0
+
+Intro_DummyFunction:
+ ret
+
+Intro_InitNote:
+ ld a, [wIntroSpriteStateFlag]
+ and a
+ ret nz
+
+ ld hl, wIntroFrameCounter2
+ ld a, [hl]
+ and $3f
+ ret nz
+
+ ld a, [hl]
+ and $7f
+ jr z, .SmallerNote
+
+ depixel 11, 6, 4, 0
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_NOTE
+ call InitSpriteAnimStruct
+ ret
+
+.SmallerNote:
+ depixel 10, 6, 4, 0
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_SMALLER_NOTE
+ call InitSpriteAnimStruct
+ ret
+
+Intro_InitJigglypuff:
+ depixel 14, 6
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_JIGGLYPUFF
+ call InitSpriteAnimStruct
+ ret
+
+Intro_InitPikachu:
+ depixel 14, 24
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_PIKACHU
+ call InitSpriteAnimStruct
+ depixel 14, 24
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_PIKACHU_TAIL
+ call InitSpriteAnimStruct
+ ret
+
+IntroScene10:
+; Set up fireball cutscene (evolved Kanto starters)
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ ld b, SGB_GS_INTRO
+ ld c, 2
+ call GetSGBLayout
+ callab InitEffectObject
+ call Intro_ResetLYOverrides
+ call Intro_BlankTilemapAndBGMap
+
+ ld hl, vChars2
+ ld de, IntroCharizard1GFX
+ lb bc, BANK(IntroCharizard1GFX), 8 tiles
+ call Request2bpp
+
+ ld hl, vFont
+ ld de, IntroCharizard2GFX tile $40
+ lb bc, BANK(IntroCharizard2GFX), 8 tiles
+ call Request2bpp
+
+ ld hl, vChars0
+ ld de, IntroCharizardFlamesGFX
+ lb bc, BANK(IntroCharizardFlamesGFX), 8 tiles
+ call Request2bpp
+
+ ld hl, wSpriteAnimDict
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_OMANYTE
+ ld [hli], a
+ ld a, SPRITE_ANIM_DICT_DEFAULT
+ ld [hli], a
+
+ ld a, 0
+ call DrawIntroCharizardGraphic
+
+ ld a, $80
+ ldh [hSCY], a
+
+ xor a
+ ldh [hSCX], a
+ ld [wGlobalAnimYOffset], a
+ ld [wGlobalAnimXOffset], a
+
+ xor a
+ ld [wIntroFrameCounter2], a
+ ld a, %00111111
+ ldh [rBGP], a
+ ld a, %11111111
+ ldh [rOBP0], a
+ ret
+
+IntroScene11:
+; scroll up to Charizard silhoutte, flash Blastoise and Venusaur
+ ld hl, wIntroFrameCounter2
+ ld a, [hl]
+ inc [hl]
+ and 1
+ ret z
+ call Intro_CheckSCYEvent
+ ld hl, hSCY
+ ld a, [hl]
+ and a
+ jr z, .next
+ inc [hl]
+ ret
+
+.next
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ xor a
+ ld [wIntroFrameCounter1], a
+
+IntroScene12:
+; load Charizard palettes
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ inc [hl]
+ srl a
+ srl a
+ and 3
+ ld e, a
+ ld d, 0
+ ld hl, .palettes
+ add hl, de
+ ld a, [hl]
+ and a
+ jr z, .next
+ ldh [rBGP], a
+ ldh [rOBP0], a
+ ret
+
+.next
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ ld a, $80
+ ld [wIntroFrameCounter1], a
+ ret
+
+.palettes:
+ dc 1, 2, 2, 2
+ dc 2, 2, 1, 1
+ dc 3, 2, 1, 0
+ dc 0, 0, 0, 0
+
+IntroScene13:
+; Charizard mouth open
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ and a
+ jr z, .next
+
+ dec [hl]
+ ret
+
+.next
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ ld a, 1
+ call DrawIntroCharizardGraphic
+ ld a, 4
+ ld [wIntroFrameCounter1], a
+ ret
+
+IntroScene14:
+; Charizard breathing fire
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ and a
+ jr z, .next
+ dec [hl]
+ ret
+
+.next
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ ld a, 2
+ call DrawIntroCharizardGraphic
+ ld a, 64
+ ld [wIntroFrameCounter1], a
+ xor a
+ ld [wIntroFrameCounter2], a
+; fallthrough
+
+IntroScene15:
+; Charizard mouth wide open / fireball starts
+ call Intro_AnimateFireball
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ and a
+ jr z, .next
+ dec [hl]
+ ret
+.next
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ xor a
+ ld [wIntroFrameCounter1], a
+ ret
+
+IntroScene16:
+; continue fireball / fade out palettes
+ call Intro_AnimateFireball
+ ld hl, wIntroFrameCounter1
+ ld a, [hl]
+ inc [hl]
+ swap a
+ and $7
+ ld e, a
+ ld d, 0
+ ld hl, .palettes
+ add hl, de
+ ld a, [hl]
+ cp -1
+ jr z, .next
+ ldh [rBGP], a
+ ldh [rOBP0], a
+ ret
+.next
+ ld hl, wIntroJumptableIndex
+ inc [hl]
+ ret
+
+.palettes:
+ dc 3, 2, 1, 0
+ dc 2, 1, 0, 0
+ dc 1, 0, 0, 0
+ dc 0, 0, 0, 0
+ db -1
+
+Intro_BlankTilemapAndBGMap:
+ hlcoord 0, 0
+ ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
+
+.blank_tilemap
+ ld [hl], 0
+ inc hl
+ dec bc
+ ld a, b
+ or c
+ jr nz, .blank_tilemap
+
+ ld hl, wc600
+ ld bc, BG_MAP_WIDTH * BG_MAP_HEIGHT
+
+.blank_bgmap
+ ld [hl], 0
+ inc hl
+ dec bc
+ ld a, b
+ or c
+ jr nz, .blank_bgmap
+
+ ld hl, vBGMap0
+ ld de, wc600
+ lb bc, BANK(@), $40
+ call Request2bpp
+ ret
+
+Intro_CheckSCYEvent:
+ ldh a, [hSCY]
+ ld c, a
+ ld hl, .Cuelist
+
+.loop
+ ld a, [hli]
+ cp -1
+ ret z
+ cp c
+ jr z, .value_found
+ inc hl
+ inc hl
+ jr .loop
+
+.value_found
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ jp hl
+
+.Cuelist:
+ dbw $87, Intro_BlastoiseAppears
+ dbw $88, Intro_FlashMonPalette
+ dbw $98, Intro_FlashSilhouette
+ dbw $99, Intro_LoadVenusaurPalette
+ dbw $bf, Intro_VenusaurAppears
+ dbw $c0, Intro_FlashMonPalette
+ dbw $d0, Intro_FlashSilhouette
+ dbw $d1, Intro_LoadCharizardPalette
+ db -1
+
+Intro_BlastoiseAppears:
+ call Intro_LoadBlastoiseObject
+ ret
+
+Intro_VenusaurAppears:
+ call Intro_LoadVenusaurObject
+ ret
+
+Intro_FlashMonPalette:
+ ld a, %11100100
+ ldh [rOBP0], a
+ xor a
+ ldh [rBGP], a
+ ret
+
+Intro_FlashSilhouette:
+ ld a, %11111111
+ ldh [rOBP0], a
+ ld a, %00111111
+ ldh [rBGP], a
+ ret
+
+Intro_LoadVenusaurPalette:
+ callab LoadVenusaurPalettes_Intro
+ ret
+
+Intro_LoadCharizardPalette:
+ callab LoadCharizardPalettes_Intro
+ ret
+
+DrawIntroCharizardGraphic:
+ push af
+ hlcoord 0, 6
+ ld c, SCREEN_WIDTH * 8
+ xor a
+.loop1
+ ld [hli], a
+ dec c
+ jr nz, .loop1
+
+ pop af
+ ld e, a
+ ld d, 0
+ ld hl, .charizard_data
+rept 5
+ add hl, de
+endr
+ ld e, [hl]
+ inc hl
+ ld c, [hl]
+ inc hl
+ ld b, [hl]
+ inc hl
+ ld a, [hli]
+ ld h, [hl]
+ ld l, a
+ ld a, e
+
+.loop2_outer
+ push bc
+ push hl
+.loop2_inner
+ ld [hli], a
+ inc a
+ dec c
+ jr nz, .loop2_inner
+
+ pop hl
+ ld bc, SCREEN_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .loop2_outer
+
+ ld a, 1
+ ldh [hBGMapMode], a
+ call DelayFrame
+ call DelayFrame
+ call DelayFrame
+ xor a
+ ldh [hBGMapMode], a
+ ret
+
+.charizard_data:
+intro_graphic_def: MACRO
+ db \1
+ db \2, \3
+ dwcoord \4, \5
+ENDM
+ intro_graphic_def $00, 8, 8, 10, 6
+ intro_graphic_def $40, 9, 8, 9, 6
+ intro_graphic_def $88, 9, 8, 8, 6
+
+Intro_AnimateFireball:
+ ld hl, wIntroFrameCounter2
+ ld a, [hl]
+ inc [hl]
+ and 3
+ ret nz
+ depixel 12, 10, 4, 4
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_FIREBALL
+ call InitSpriteAnimStruct
+ ld hl, hSCX
+ dec [hl]
+ ld hl, wGlobalAnimXOffset
+ inc [hl]
+ ret
+
+Intro_LoadBlastoiseObject:
+ depixel 22, 1
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_BLASTOISE
+ call InitSpriteAnimStruct
+ ret
+
+Intro_LoadVenusaurObject:
+ depixel 22, 20
+ ld a, SPRITE_ANIM_INDEX_GS_INTRO_VENUSAUR
+ call InitSpriteAnimStruct
+ ret
+
+Intro_Copy128Tiles:
+ ld bc, 128 tiles
+.loop
+ ld a, [de]
+ inc de
+ ld [hli], a
+ dec bc
+ ld a, c
+ or b
+ jr nz, .loop
+ ret
+
+Intro_DrawBackground:
+ ld b, BG_MAP_WIDTH / 2
+.outer_loop
+ push hl
+ ld c, BG_MAP_HEIGHT / 2
+.inner_loop
+ call Intro_Draw2x2Tiles
+ dec c
+ jr nz, .inner_loop
+ pop hl
+ push bc
+ ld bc, 2 * BG_MAP_WIDTH
+ add hl, bc
+ pop bc
+ dec b
+ jr nz, .outer_loop
+ ret
+
+Intro_Draw2x2Tiles:
+ push bc
+ push de
+ push hl
+ push hl
+ push hl
+ ld a, [de]
+ ld l, a
+ ld h, 0
+ ld a, [wIntroTilesPointer + 0]
+ ld e, a
+ ld a, [wIntroTilesPointer + 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
+
+Intro_ResetLYOverrides:
+ ld hl, wLYOverrides
+ xor a
+ ld c, wLYOverrides2 - wLYOverrides
+.loop
+ ld [hli], a
+ dec c
+ jr nz, .loop
+ ret
diff --git a/engine/title.asm b/engine/movie/title.asm
index df47646..d84d8c5 100644
--- a/engine/title.asm
+++ b/engine/movie/title.asm
@@ -1,6 +1,6 @@
INCLUDE "constants.asm"
-SECTION "engine/title.asm@Title screen", ROMX
+SECTION "engine/movie/title.asm@Title screen", ROMX
IntroSequence::
callab GameFreakIntro
@@ -152,7 +152,7 @@ TitleSequenceInit::
ld d, [hl]
inc hl
push hl
- ld a, $2E ; Title fire/note object effect type?
+ ld a, SPRITE_ANIM_INDEX_GS_TITLE_FLAME_NOTE
call InitSpriteAnimStruct
pop hl
pop bc
@@ -161,12 +161,12 @@ TitleSequenceInit::
ret
FirePositionTable::
- dw $4CE0
- dw $58A0
- dw $6490
- dw $70D0
- dw $7CB0
- dw $8800
+ dbpixel 28, 9, 0, 4
+ dbpixel 20, 11, 0, 0
+ dbpixel 18, 12, 0, 4
+ dbpixel 26, 14, 0, 0
+ dbpixel 22, 15, 0, 4
+ dbpixel 0, 17, 0, 0
TitleFireGFX:: INCBIN "gfx/title/fire.2bpp"
TitleNotesGFX:: INCBIN "gfx/title/notes.2bpp"
@@ -627,7 +627,7 @@ SetTitleGfxNext::
jr nz, .loop
ret
-SECTION "engine/title.asm@Title screen TEMPORARY", ROMX
+SECTION "engine/movie/title.asm@Title screen TEMPORARY", ROMX
GameInit::
call ClearWindowData
diff --git a/gfx/gfx.asm b/gfx/gfx.asm
index 44e1c07..8c3fb8a 100644
--- a/gfx/gfx.asm
+++ b/gfx/gfx.asm
@@ -546,12 +546,22 @@ INCBIN "gfx/splash/game_freak_logo_oam.2bpp"
SECTION "gfx.asm@Intro Underwater GFX", ROMX
IntroUnderwaterGFX::
INCBIN "gfx/intro/underwater.2bpp"
-
-SECTION "gfx.asm@Intro Water Mon and Forest GFX", ROMX
+Intro_WaterTilemap::
+INCBIN "gfx/intro/water_tilemap.bin"
+Intro_WaterMeta::
+INCBIN "gfx/intro/water.bin"
IntroWaterPokemonGFX::
INCBIN "gfx/intro/water_pokemon.2bpp"
+
+SECTION "gfx.asm@Intro Forest GFX", ROMX
IntroForestGFX::
INCBIN "gfx/intro/forest.2bpp"
+IntroForestLogGFX::
+INCBIN "gfx/intro/forest_log.2bpp"
+Intro_GrassTilemap::
+INCBIN "gfx/intro/forest_tilemap.bin"
+Intro_GrassMeta::
+INCBIN "gfx/intro/forest.bin"
SECTION "gfx.asm@Intro Mon", ROMX
IntroJigglypuffPikachuGFX::
diff --git a/gfx/gfx.mk b/gfx/gfx.mk
index fe01521..0de08dc 100644
--- a/gfx/gfx.mk
+++ b/gfx/gfx.mk
@@ -17,5 +17,11 @@ $(BUILD)/gfx/minigames/poker.2bpp: tools/gfx += --trim-whitespace
$(BUILD)/gfx/intro/jigglypuff_pikachu.2bpp: tools/gfx += --trim-whitespace
+$(BUILD)/gfx/intro/%.bin: gfx/intro/%.bin
+ cp $< $@
+
+$(BUILD)/gfx/minigames/%.bin: gfx/minigames/%.bin
+ cp $< $@
+
$(BUILD)/gfx/battle_anims/attack_animations_1.2bpp: tools/gfx += --trim-whitespace
$(BUILD)/gfx/battle_anims/attack_animations_2.2bpp: tools/gfx += --trim-whitespace
diff --git a/gfx/intro/forest.bin b/gfx/intro/forest.bin
new file mode 100644
index 0000000..cf13546
--- /dev/null
+++ b/gfx/intro/forest.bin
Binary files differ
diff --git a/gfx/intro/forest_log.png b/gfx/intro/forest_log.png
new file mode 100644
index 0000000..deb5987
--- /dev/null
+++ b/gfx/intro/forest_log.png
Binary files differ
diff --git a/gfx/intro/forest_tilemap.bin b/gfx/intro/forest_tilemap.bin
new file mode 100644
index 0000000..c3a8420
--- /dev/null
+++ b/gfx/intro/forest_tilemap.bin
@@ -0,0 +1,128 @@
+              
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gfx/intro/water.bin b/gfx/intro/water.bin
new file mode 100644
index 0000000..7f8675f
--- /dev/null
+++ b/gfx/intro/water.bin
Binary files differ
diff --git a/gfx/intro/water_tilemap.bin b/gfx/intro/water_tilemap.bin
new file mode 100644
index 0000000..b91bfd7
--- /dev/null
+++ b/gfx/intro/water_tilemap.bin
@@ -0,0 +1,2 @@
+ !"#0123 !"#0123()*+89:;()*+89:;''$%&ABC''$%&ABC'',-.''''',-.''''''''''''''''''''''''''''''''''' 
+  ////// \ No newline at end of file
diff --git a/gfx/minigames/pikachu_blockmap.bin b/gfx/minigames/pikachu_blockmap.bin
new file mode 100644
index 0000000..b905b55
--- /dev/null
+++ b/gfx/minigames/pikachu_blockmap.bin
@@ -0,0 +1,16 @@
+              
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gfx/minigames/pikachu_blockset.bin b/gfx/minigames/pikachu_blockset.bin
new file mode 100644
index 0000000..cf13546
--- /dev/null
+++ b/gfx/minigames/pikachu_blockset.bin
Binary files differ
diff --git a/layout.link b/layout.link
index 17467cc..a52e750 100644
--- a/layout.link
+++ b/layout.link
@@ -102,9 +102,9 @@ ROMX $01
"engine/menu/main_menu.asm@Initialize new game WRAM"
"engine/dumps/bank01.asm@Function5388"
"engine/menu/main_menu.asm@MainMenu"
- "engine/intro.asm"
- "engine/title.asm@Title screen"
- "engine/title.asm@Title screen TEMPORARY"
+ "engine/movie/oak_speech.asm"
+ "engine/movie/title.asm@Title screen"
+ "engine/movie/title.asm@Title screen TEMPORARY"
"engine/predef.asm"
"engine/dumps/bank01.asm@ReanchorBGMap_NoOAMUpdate"
"engine/math/math.asm"
@@ -884,6 +884,7 @@ ROMX $37
ROMX $38
org $4000
+ "engine/games/pikachu_minigame.asm@Pikachu Minigame"
org $5403
"gfx.asm@Poker GFX"
org $5f93
@@ -895,14 +896,13 @@ ROMX $38
ROMX $39
org $4000
- org $41ff
+ "engine/movie/game_freak_intro.asm"
"gfx.asm@Gamefreak Logo GFX"
- org $4adf
+ "engine/movie/opening_cutscene.asm"
"gfx.asm@Intro Underwater GFX"
- org $55ef
- "gfx.asm@Intro Water Mon and Forest GFX"
- org $626f
+ "gfx.asm@Intro Forest GFX"
"gfx.asm@Intro Mon"
+ "slack.asm@Unknowne7e9f"
ROMX $3a
org $4000
diff --git a/ram/hram.asm b/ram/hram.asm
index c0d49a1..da8f685 100644
--- a/ram/hram.asm
+++ b/ram/hram.asm
@@ -138,6 +138,7 @@ ENDU
ds 3 ; TODO
+hCurSpriteYCoord::
hFFC0:: ds 1
ds 6
diff --git a/ram/wram.asm b/ram/wram.asm
index e0356b9..56e87b8 100644
--- a/ram/wram.asm
+++ b/ram/wram.asm
@@ -91,6 +91,26 @@ wTileMapBackup::
NEXTU
+wSpriteAnimDict:: ds 10 * 2 ; NUM_SPRITEANIMDICT_ENTRIES * 2
+
+wSpriteAnimationStructs::
+; field 0: index
+; fields 1-3: loaded from SpriteAnimSeqData
+wSpriteAnim1:: sprite_anim_struct wSpriteAnim1
+wSpriteAnim2:: sprite_anim_struct wSpriteAnim2
+wSpriteAnim3:: sprite_anim_struct wSpriteAnim3
+wSpriteAnim4:: sprite_anim_struct wSpriteAnim4
+wSpriteAnim5:: sprite_anim_struct wSpriteAnim5
+wSpriteAnim6:: sprite_anim_struct wSpriteAnim6
+wSpriteAnim7:: sprite_anim_struct wSpriteAnim7
+wSpriteAnim8:: sprite_anim_struct wSpriteAnim8
+wSpriteAnim9:: sprite_anim_struct wSpriteAnim9
+wSpriteAnim10:: sprite_anim_struct wSpriteAnim10
+wSpriteAnimationStructsEnd::
+
+wSpriteAnimCount:: db
+NEXTU
+
ds 1
wc409:: ds 1
@@ -115,7 +135,10 @@ wSpriteAnimIDBuffer:: db
ds 6
+wGlobalAnimYOffset::
wc4c7:: db
+
+wGlobalAnimXOffset::
wc4c8:: db
ds 7
@@ -149,6 +172,7 @@ wMapBufferEnd::
UNION
+wc600::
wOverworldMapBlocks:: ds 1300
wOverworldMapBlocksEnd::
@@ -161,8 +185,59 @@ wLYOverrides2:: ds SCREEN_HEIGHT_PX
wLYOverrides2End::
NEXTU
-; Battle-related
+; Pikachu minigame
+
+wPikachuMinigamePikachuObjectPointer:: ds 2
+wPikachuMinigamePikachuTailObjectPointer:: ds 2
+wPikachuMinigamePikachuNextAnim:: ds 1
+
+wPikachuMinigameControlEnable:: ds 1
+
+wc606:: ds 1 ; written to, but is this read from?
+
+wPikachuMinigamePikachuYOffset:: ds 1
+wPikachuMinigameNoteTimer:: ds 1
+wPikachuMinigameScore:: ds 2
+wPikachuMinigameNoteCounter:: ds 2 ; not used for anything meaningful?
+
+wPikachuMinigameSpawnTypeIndex:: ds 1
+wPikachuMinigameSpawnDataIndex:: ds 1
+wPikachuMinigameScoreModifier:: ds 1
+
+wPikachuMinigameNoteCaught:: ds 1
+
+; Time keeping
+wPikachuMinigameTimeFrames:: ds 1
+wPikachuMinigameTimeSeconds:: ds 1
+
+; are these two used?
+wc613:: ds 1
+wc614:: ds 1
+
+wPikachuMinigameRedrawTimer:: ds 1
+wc616:: ds 1
+wPikachuMinigameScrollSpeed:: ds 1
+
+wPikachuMinigameColumnFlags:: ds 1
+wPikachuMinigameSavedColumnPointer:: ds 2
+wPikachuMinigameColumnPointer:: ds 2
+
+wPikachuMinigameRepeatColumnCounter:: ds 1
+wPikachuMinigameRepeatColumnCounter2:: ds 1
+
+wPikachuMinigameSceneTimer:: ds 1
+
+wPikachuMinigameJumptableIndex:: ds 1
+
+wPikachuMinigameBGMapPointer:: ds 2
+wPikachuMinigameTilemapPointer:: ds 2
+wPikachuMinigameTilesPointer:: ds 2
+
+wPikachuMinigameColumnBuffer:: ds 16
+
+NEXTU
+; Battle-related
ds $1ea
wActiveBGEffects::
@@ -229,13 +304,31 @@ wca0a:: ds 1
ds 5 ; TODO
+wIntroJumptableIndex::
wca10:: ds 1
+
+UNION
+wIntroBGMapPointer:: ds 2
+NEXTU
wca11:: ds 1
wca12:: ds 1
+ENDU
+
+UNION
+wIntroTilemapPointer:: ds 2
+NEXTU
wca13:: ds 1
wca14:: ds 1
+ENDU
+
+wIntroTilesPointer:: ds 2
+
+wIntroFrameCounter1:: ds 1
+wIntroFrameCounter2:: ds 1
+
+wIntroSpriteStateFlag:: ds 1
- ds $22 ; TODO
+ ds $1d ; TODO
wca37:: ds 1
wca38:: ds 1
@@ -331,10 +424,12 @@ SECTION "CB5E", WRAM0[$CB5E]
wJumptableIndex:: db
wFlyDestination::
+wIntroSceneFrameCounter::
wBattleTransitionCounter:: db
wBattleTransitionSineWaveOffset::
wBattleTransitionSpinQuadrant::
+wIntroSceneTimer::
wcb60:: ds 1
wcb61:: ds 1
diff --git a/shim.sym b/shim.sym
index 397bb7d..7b68e54 100755
--- a/shim.sym
+++ b/shim.sym
@@ -151,9 +151,6 @@
33:625D BattleAnim_Sine_e
33:6263 BattleAnim_Cosine_e
-38:4000 PikachuMiniGame
-39:4000 GameFreakIntro
-39:432F OpeningCutscene
3A:441D Functione841d
3A:45D8 Functione85d8
3A:47F9 Functione87f9
diff --git a/slack/slack.asm b/slack/slack.asm
index f3e450b..0423771 100755
--- a/slack/slack.asm
+++ b/slack/slack.asm
@@ -26,3 +26,9 @@ SECTION "slack.asm@Corrupted Sprites", ROMX
CorruptedSpriteGFX:
INCBIN "slack/sprites_corrupted.2bpp"
+
+SECTION "slack.asm@Unknowne7e9f", ROMX
+
+Unknowne7e9f:
+INCBIN "slack/unknown_e7e9f.bin" ; Loaded as corrupted graphics
+
diff --git a/slack/unknown_e7e9f.bin b/slack/unknown_e7e9f.bin
new file mode 100644
index 0000000..3080e80
--- /dev/null
+++ b/slack/unknown_e7e9f.bin
Binary files differ