diff options
author | Rangi <35663410+Rangi42@users.noreply.github.com> | 2020-12-17 15:56:19 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-17 15:56:19 -0500 |
commit | b1ae1098d06d9865c767471e539fa65f77101aaa (patch) | |
tree | 4b6d8fc9c449169705e224508a8d5e238fda18ab | |
parent | 9352a537c39471410314be76cf866e058a9349bf (diff) | |
parent | 37e60a9457643720dae714f8d2df0cf5ad31d919 (diff) |
Merge pull request #84 from ZoomTen/pikachu-minigame
Disassemble opening cutscene, Game Freak intro, and Pikachu minigame
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:: @@ -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 Binary files differnew file mode 100644 index 0000000..cf13546 --- /dev/null +++ b/gfx/intro/forest.bin diff --git a/gfx/intro/forest_log.png b/gfx/intro/forest_log.png Binary files differnew file mode 100644 index 0000000..deb5987 --- /dev/null +++ b/gfx/intro/forest_log.png 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 Binary files differnew file mode 100644 index 0000000..7f8675f --- /dev/null +++ b/gfx/intro/water.bin 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 Binary files differnew file mode 100644 index 0000000..cf13546 --- /dev/null +++ b/gfx/minigames/pikachu_blockset.bin 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 @@ -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 Binary files differnew file mode 100644 index 0000000..3080e80 --- /dev/null +++ b/slack/unknown_e7e9f.bin |