From 52bb92028e9383b3013292adcf2021ae1cb53c7b Mon Sep 17 00:00:00 2001 From: xCrystal Date: Sun, 28 Jan 2024 17:57:11 +0100 Subject: [PATCH] Level selection menu: entry transition events (#12) (#35) [commit 1] --- constants/landmark_constants.asm | 6 ++ data/levels/level_selection_menu.asm | 1 + docs/develop/index.md | 3 + engine/menus/cleared_level_screen.asm | 4 +- engine/menus/game_menu.asm | 41 ++++++++++---- engine/menus/level_selection_menu.asm | 80 ++++++++++++++++++++++----- home/time.asm | 2 +- macros/gfx.asm | 8 --- ram/wram.asm | 1 + 9 files changed, 109 insertions(+), 37 deletions(-) diff --git a/constants/landmark_constants.asm b/constants/landmark_constants.asm index 77816024f..e94ebedae 100644 --- a/constants/landmark_constants.asm +++ b/constants/landmark_constants.asm @@ -27,6 +27,12 @@ DEF LSMTEXTBOX_LEVEL_NUMBERS_FIRST_TILE EQU $31 ; and $41 const LSMTEXTBOX_STAGE_3_INDICATOR_TILE ; $3d (and $4d) const LSMTEXTBOX_STAGE_4_INDICATOR_TILE ; $3e (and $4e) +; events when entering Level Selection menu (wLevelSelectionMenuEntryEventQueue) + const_def + const LSMEVENT_SHOW_UNLOCKED_LEVELS ; 0 + const LSMEVENT_ANIMATE_TIME_OF_DAY ; 1 +DEF NUM_LSM_EVENTS EQU const_value + ; used in CaughtData (legacy) const_def $7f, -1 const LANDMARK_EVENT ; $7f diff --git a/data/levels/level_selection_menu.asm b/data/levels/level_selection_menu.asm index 2d169de16..192163977 100755 --- a/data/levels/level_selection_menu.asm +++ b/data/levels/level_selection_menu.asm @@ -131,3 +131,4 @@ if DEF(_DEBUG) db DEBUGLEVEL_5 ; LANDMARK_DEBUGLEVEL_5 endc assert_table_length NUM_LANDMARKS + db $ff diff --git a/docs/develop/index.md b/docs/develop/index.md index 628003b9e..5d0d41379 100755 --- a/docs/develop/index.md +++ b/docs/develop/index.md @@ -100,6 +100,7 @@ - **wCurLevel**: initialized in LevelSelectionMenu (where it is also used), and stays static during the level. - **wDefaultLevelSelectionMenuLandmark**: used to know in which landmark to place the player when entering level selection menu. - **wCurOverworldMiscPal** + - **wLevelSelectionMenuEntryEventQueue**: which events have to be triggered the next time the player enters the level selection menu. - These addresses share memory region with string buffers from *wStringBuffer3* onwards. They are placed in memory in the following order. - **wTempSpaceStruct**: Temporary scope. Same structure as *wCurSpaceStruct* @@ -119,6 +120,8 @@ - **wDisabledSpacesBackups**: preserved on save to **sDisabledSpacesBackups**. - **wMapObjectsBackups**: preserved on save to **sMapObjectsBackups**. +- **wLevelSelectionMenu\*** addresses, union under the *"Miscellaneous WRAM 1"* section. Temporary scope during level selection menu, except for *wLevelSelectionMenuEntryEventQueue*. + - Other WRAM 0 addresses (not preserved on save): - **wText2bpp** - **wWhichHUD** diff --git a/engine/menus/cleared_level_screen.asm b/engine/menus/cleared_level_screen.asm index a2ed4473e..9da8256ac 100755 --- a/engine/menus/cleared_level_screen.asm +++ b/engine/menus/cleared_level_screen.asm @@ -35,9 +35,7 @@ ClearedLevelScreen: ld [wNumTempUnlockedLevels], a ld a, $ff ld [wTempUnlockedLevels], a - call UnlockLevels - ld c, 30 - jp DelayFrames + jp UnlockLevels .LevelCleared1Text: text " L E V E L" diff --git a/engine/menus/game_menu.asm b/engine/menus/game_menu.asm index 764c1f1d4..90716ae44 100755 --- a/engine/menus/game_menu.asm +++ b/engine/menus/game_menu.asm @@ -93,6 +93,22 @@ GameMenuJoypadLoop: ret GameMenu_WorldMap: +; the following 500ms fading delay applies: +; - from post-level screen to level selection menu +; - from overworld to level selection menu +; - from selecting "WORLD MAP" in game menu to level selection menu (save outside ow) +; - from selecting "WORLD MAP" in game menu to overworld (save in ow) + ld a, 8 + ld [wMusicFade], a + ld a, LOW(MUSIC_NONE) + ld [wMusicFadeID], a + ld a, HIGH(MUSIC_NONE) + ld [wMusicFadeID + 1], a + call ClearBGPalettes + call ClearTilemap + ld c, 30 - 8 + call DelayFrames + ld a, [wSaveFileInOverworld] and a jr z, .not_in_overworld @@ -102,6 +118,11 @@ GameMenu_WorldMap: .not_in_overworld farcall LevelSelectionMenu +; dequeue all level selection menu events (which triggered during call above if set). +; game is not saved until player enters a level, so if game is turned off in the middle of +; an event or in the menu, the player will be able to replay the events when they come back. + ld a, 0 + ld [wLevelSelectionMenuEntryEventQueue], a ret nc ; if pressed B, go back to Game Menu farcall ClearSpriteAnims @@ -111,16 +132,6 @@ GameMenu_WorldMap: .SpawnToMap: ldh [hMapEntryMethod], a - ld a, $8 - ld [wMusicFade], a - ld a, LOW(MUSIC_NONE) - ld [wMusicFadeID], a - ld a, HIGH(MUSIC_NONE) - ld [wMusicFadeID + 1], a - call ClearBGPalettes - call ClearTilemap - ld c, 20 - call DelayFrames farcall JumpRoamMons xor a ld [wDontPlayMapMusicOnReload], a ; play map music @@ -137,11 +148,17 @@ GameMenu_WorldMap: ld a, [wExitOverworldReason] cp CLEARED_LEVEL jr nz, .save_and_return - call AdvanceTimeOfDay farcall ClearedLevelScreen + call AdvanceTimeOfDay + ld hl, wLevelSelectionMenuEntryEventQueue + set LSMEVENT_ANIMATE_TIME_OF_DAY, [hl] + ld a, [wNumTempUnlockedLevels] + and a + jr z, .save_and_return + set LSMEVENT_SHOW_UNLOCKED_LEVELS, [hl] .save_and_return farcall AutoSaveGameOutsideOverworld - ret + jp GameMenu_WorldMap GameMenu_Shop: ret diff --git a/engine/menus/level_selection_menu.asm b/engine/menus/level_selection_menu.asm index 55668d3e6..ca8611824 100755 --- a/engine/menus/level_selection_menu.asm +++ b/engine/menus/level_selection_menu.asm @@ -2,6 +2,8 @@ LevelSelectionMenu:: xor a ldh [hInMenu], a ldh [hMapAnims], a + ldh [hSCY], a + ldh [hSCX], a ld a, 1 << 2 ; do not clear wShadowOAM during DoNextFrameForAllSprites ld [wVramState], a @@ -17,6 +19,59 @@ LevelSelectionMenu:: ld a, LCDC_DEFAULT ldh [rLCDC], a + ld a, [wLevelSelectionMenuEntryEventQueue] + bit LSMEVENT_SHOW_UNLOCKED_LEVELS, a + jr z, .load_default_landmark + + ld hl, wTempUnlockedLevels +.show_unlocked_levels_loop + ld a, [hli] + cp $ff + jr z, .load_default_landmark + + push hl +; perform level-to-landmark lookup of wTempUnlockedLevels[i] in $ff-terminated LandmarkToLevelTable. +; stop at the first match and load it to wLevelSelectionMenuCurrentLandmark. + ld hl, LandmarkToLevelTable + ld c, 0 +.level_to_landmark_loop + ld b, [hl] + inc b + jr z, .invalid_level ; if reached $ff byte of LandmarkToLevelTable + cp [hl] + jr z, .match + inc hl + inc c + jr .level_to_landmark_loop +.match + ld a, c + ld [wLevelSelectionMenuCurrentLandmark], a + call LevelSelectionMenu_GetLandmarkPage + ld [wLevelSelectionMenuCurrentPage], a + + call LevelSelectionMenu_DrawTilemapAndAttrmap + call LevelSelectionMenu_DrawTimeOfDaySymbol + ld b, CGB_LEVEL_SELECTION_MENU + call GetCGBLayout ; apply and commit pals + call SetPalettes + ld c, 20 ; + call DelayFrames ; page shown --> page and textbox shown + + call LevelSelectionMenu_PrintLevelAndLandmarkNameAndStageIndicators + call LevelSelectionMenu_DrawStageTrophies + call LevelSelectionMenu_RefreshTextboxAttrs + + ld c, 60 + call DelayFrames + ld b, RGBFADE_TO_BLACK_6BGP_1OBP2 + call DoRGBFadeEffect + ld c, 30 ; + call DelayFrames ; black screen --> next landmark shown +.invalid_level + pop hl + jr .show_unlocked_levels_loop + +.load_default_landmark ld a, [wDefaultLevelSelectionMenuLandmark] ld [wLevelSelectionMenuCurrentLandmark], a call LevelSelectionMenu_GetLandmarkPage @@ -24,11 +79,7 @@ LevelSelectionMenu:: ld a, TRUE ld [wLevelSelectionMenuStandingStill], a - call LevelSelectionMenu_InitTilemap - call LevelSelectionMenu_InitAttrmap - call WaitBGMap2 - xor a - ldh [hBGMapMode], a + call LevelSelectionMenu_DrawTilemapAndAttrmap call LevelSelectionMenu_DrawTimeOfDaySymbol ld b, CGB_LEVEL_SELECTION_MENU call GetCGBLayout ; apply and commit pals @@ -38,7 +89,6 @@ LevelSelectionMenu:: call PlayMusic call DelayFrame ; wait for pal update - ld a, [wLevelSelectionMenuCurrentLandmark] call LevelSelectionMenu_InitPlayerSprite call LevelSelectionMenu_InitLandmark call LevelSelectionMenu_PrintLevelAndLandmarkNameAndStageIndicators @@ -136,6 +186,7 @@ LevelSelectionMenu:: call PlaySFX call LevelSelectionMenu_Delay10Frames call .EnterLevelFadeOut + call WaitSFX scf ret @@ -231,10 +282,17 @@ LevelSelectionMenu_InitAttrmap: jr nz, .loop ret +LevelSelectionMenu_DrawTilemapAndAttrmap: + call LevelSelectionMenu_InitTilemap + call LevelSelectionMenu_InitAttrmap + call WaitBGMap2 + xor a + ldh [hBGMapMode], a + ret + LevelSelectionMenu_InitPlayerSprite: ; initialize the anim struct of the player's sprite. ; because ClearSpriteAnims was called before, it's always loaded to wSpriteAnim1 - push af depixel 0, 0 ; all the SPRITE_ANIM_* related to the level selection menu are sorted by direction, then by gender ld b, SPRITE_ANIM_OBJ_LEVEL_SELECTION_MENU_MALE_WALK_DOWN @@ -244,7 +302,7 @@ LevelSelectionMenu_InitPlayerSprite: ld hl, SPRITEANIMSTRUCT_TILE_ID add hl, bc ld [hl], $00 - pop af + ld a, [wLevelSelectionMenuCurrentLandmark] ld e, a call LevelSelectionMenu_GetLandmarkCoords ; wSpriteAnim1*Coord contain the coord of the bottom right object of the player sprite @@ -747,11 +805,7 @@ ENDM ; set new page and redraw screen call LevelSelectionMenu_GetNewPage ld [wLevelSelectionMenuCurrentPage], a - call LevelSelectionMenu_InitTilemap - call LevelSelectionMenu_InitAttrmap - call WaitBGMap2 - xor a - ldh [hBGMapMode], a + call LevelSelectionMenu_DrawTilemapAndAttrmap call .PageChangeFadeIn ; adjust steps left for the "duplicate" movement of the player leaving and entering a page ld hl, wLevelSelectionMenuMovementStepsLeft diff --git a/home/time.asm b/home/time.asm index 946e4faa8..06bed45bc 100644 --- a/home/time.asm +++ b/home/time.asm @@ -40,4 +40,4 @@ AdvanceTimeOfDay:: ret .TimeOfDayOrder: - db MORN_F, DAY_F, NITE_F, EVE_F, MORN_F + db MORN_F, DAY_F, EVE_F, NITE_F, MORN_F diff --git a/macros/gfx.asm b/macros/gfx.asm index 4a49e7a0c..ea234d2ed 100644 --- a/macros/gfx.asm +++ b/macros/gfx.asm @@ -55,14 +55,6 @@ MACRO rgbpals_fade_apply PURGE fade_from, fade_to, rgbch_red, rgbch_green, rgbch_blue, palred_value, palgreen_value, palblue_value ENDM -/* MACRO rgbpals_fade_end - rept _NARG - for i, - endr - shift - endr -ENDM */ - DEF palettes EQUS "* PALETTE_SIZE" DEF palette EQUS "+ PALETTE_SIZE *" DEF color EQUS "+ PAL_COLOR_SIZE *" diff --git a/ram/wram.asm b/ram/wram.asm index 0678213f8..06d913688 100644 --- a/ram/wram.asm +++ b/ram/wram.asm @@ -2546,6 +2546,7 @@ wKurtApricornQuantity:: db wCurLevel:: db wDefaultLevelSelectionMenuLandmark:: db wCurOverworldMiscPal:: db +wLevelSelectionMenuEntryEventQueue:: flag_array NUM_LSM_EVENTS wPlayerDataEnd::