mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-11-16 11:27:33 -08:00
1276 lines
30 KiB
NASM
Executable File
1276 lines
30 KiB
NASM
Executable File
LevelSelectionMenu::
|
|
xor a
|
|
ldh [hInMenu], a
|
|
ldh [hMapAnims], a
|
|
ldh [hSCY], a
|
|
ldh [hSCX], a
|
|
ldh [hLCDStatIntRequired], a
|
|
ld a, 1 << DONT_CLEAR_SHADOW_OAM_IN_SPRITE_ANIMS_F
|
|
ld [wStateFlags], a
|
|
|
|
call ClearBGPalettes
|
|
call ClearTilemap
|
|
call ClearSprites
|
|
ld de, MUSIC_NONE
|
|
call PlayMusic
|
|
call DelayFrame
|
|
call DisableLCD
|
|
call LevelSelectionMenu_LoadGFX
|
|
farcall ClearSpriteAnims
|
|
ld a, LCDC_DEFAULT
|
|
ldh [rLCDC], a
|
|
|
|
ld a, [wLevelSelectionMenuEntryEventQueue]
|
|
bit LSMEVENT_SHOW_UNLOCKED_LEVELS, a
|
|
jp z, .load_default_landmark
|
|
|
|
ld a, [wLastUnlockedLevelsCount]
|
|
and a
|
|
jp z, .load_default_landmark
|
|
|
|
ld hl, wLastUnlockedLevels
|
|
.show_unlocked_levels_loop
|
|
ld a, [hli]
|
|
cp $ff
|
|
jp z, .load_default_landmark
|
|
|
|
push hl
|
|
; perform level-to-landmark lookup of wLastUnlockedLevels[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
|
|
|
|
; load and draw gfx involved in the show unlocked levels event
|
|
call LevelSelectionMenu_DrawTilemapAndAttrmap
|
|
call LevelSelectionMenu_DrawTimeOfDaySymbol
|
|
ld b, CGB_LEVEL_SELECTION_MENU
|
|
call GetCGBLayout ; apply and commit pals
|
|
call SetDefaultBGPAndOBP
|
|
ld c, 20 ;
|
|
call DelayFrames ; page shown --> page and textbox shown
|
|
|
|
call LevelSelectionMenu_PrintLevelAndLandmarkNameAndStageIndicators
|
|
call LevelSelectionMenu_DrawStageTrophies
|
|
call LevelSelectionMenu_RefreshTextboxAttrs
|
|
|
|
; play animation that highlights landmark of unlocked level
|
|
ld a, [wLevelSelectionMenuCurrentLandmark]
|
|
call LevelSelectionMenu_GetLandmarkCoords
|
|
ld a, SPRITE_ANIM_OBJ_LEVEL_SELECTION_MENU_HIGHLIGHT_LEVEL
|
|
call InitSpriteAnimStruct
|
|
ld a, (15 + 1) * 6 ; %01100000
|
|
.highlight_level_anim_loop
|
|
ld [wFrameCounter], a
|
|
ld a, [wFrameCounter]
|
|
and %11111
|
|
ld de, SFX_POKEBALLS_PLACED_ON_TABLE
|
|
call z, PlaySFX
|
|
farcall PlaySpriteAnimationsAndDelayFrame
|
|
ld a, [wFrameCounter]
|
|
dec a
|
|
jr nz, .highlight_level_anim_loop
|
|
farcall ClearSpriteAnims
|
|
|
|
; fade to the next unlocked level, or to the regular level selection menu
|
|
ld b, RGBFADE_TO_BLACK_6BGP_1OBP1
|
|
call DoRGBFadeEffect
|
|
ld c, 30 ;
|
|
call DelayFrames ; black screen --> next landmark shown
|
|
.invalid_level
|
|
pop hl
|
|
jp .show_unlocked_levels_loop
|
|
|
|
.load_default_landmark
|
|
ld a, [wDefaultLevelSelectionMenuLandmark]
|
|
ld [wLevelSelectionMenuCurrentLandmark], a
|
|
call LevelSelectionMenu_GetLandmarkPage
|
|
ld [wLevelSelectionMenuCurrentPage], a
|
|
ld a, TRUE
|
|
ld [wLevelSelectionMenuStandingStill], a
|
|
|
|
call LevelSelectionMenu_DrawTilemapAndAttrmap
|
|
call LevelSelectionMenu_DrawTimeOfDaySymbol
|
|
ld b, CGB_LEVEL_SELECTION_MENU
|
|
call GetCGBLayout ; apply and commit pals
|
|
call SetDefaultBGPAndOBP
|
|
|
|
ld de, MUSIC_GAME_CORNER
|
|
call PlayMusic
|
|
call DelayFrame ; wait for pal update
|
|
|
|
call LevelSelectionMenu_InitPlayerSprite
|
|
call LevelSelectionMenu_InitLandmark
|
|
call LevelSelectionMenu_PrintLevelAndLandmarkNameAndStageIndicators
|
|
call LevelSelectionMenu_DrawDirectionalArrows
|
|
call LevelSelectionMenu_DrawStageTrophies
|
|
call LevelSelectionMenu_RefreshTextboxAttrs
|
|
|
|
ld a, [wLevelSelectionMenuEntryEventQueue]
|
|
bit LSMEVENT_SHOW_CLEARED_LEVEL, a
|
|
jr z, .check_animate_tod
|
|
ld a, [wLastClearedLevelStage]
|
|
cp NUM_LEVEL_STAGES
|
|
jr nc, .check_animate_tod
|
|
|
|
call LevelSelectionMenu_Delay10Frames
|
|
|
|
; the previous LevelSelectionMenu_DrawStageTrophies showed this stage trophy empty
|
|
; due to wLastClearedLevelStage being set to a non-$ff value.
|
|
; redisplay stage trophies to show the stage being cleared.
|
|
ld a, $ff
|
|
ld [wLastClearedLevelStage], a
|
|
call LevelSelectionMenu_DrawStageTrophies
|
|
ld de, SFX_FORESIGHT
|
|
call PlaySFX
|
|
|
|
call LevelSelectionMenu_Delay10Frames
|
|
call LevelSelectionMenu_Delay10Frames
|
|
|
|
.check_animate_tod
|
|
ld a, [wLevelSelectionMenuEntryEventQueue]
|
|
bit LSMEVENT_ANIMATE_TIME_OF_DAY, a
|
|
jp z, .main_loop
|
|
|
|
call LevelSelectionMenu_Delay10Frames
|
|
|
|
ld bc, SPRITEOAMSTRUCT_LENGTH
|
|
ld e, 3 * TILE_WIDTH
|
|
.tod_symbol_upwards_loop
|
|
farcall PlaySpriteAnimationsAndDelayFrame
|
|
ld hl, wShadowOAM + $4 * SPRITEOAMSTRUCT_LENGTH + SPRITEOAMSTRUCT_YCOORD
|
|
dec [hl]
|
|
add hl, bc
|
|
dec [hl]
|
|
add hl, bc
|
|
dec [hl]
|
|
add hl, bc
|
|
dec [hl]
|
|
dec e
|
|
jr nz, .tod_symbol_upwards_loop
|
|
|
|
ld a, [wTimeOfDay]
|
|
ld [wLevelSelectionMenuStartingToD], a
|
|
|
|
cp NITE_F
|
|
ld e, -4
|
|
jr z, .change_tod_symbol
|
|
cp EVE_F
|
|
ld e, -2
|
|
jr z, .change_tod_symbol
|
|
cp DAY_F
|
|
ld e, 4
|
|
jr z, .change_tod_symbol
|
|
ld e, 2
|
|
.change_tod_symbol
|
|
ld hl, wShadowOAM + $4 * SPRITEOAMSTRUCT_LENGTH + SPRITEOAMSTRUCT_TILE_ID
|
|
ld bc, SPRITEOAMSTRUCT_LENGTH
|
|
ld d, 2 * 2
|
|
.change_tod_symbol_loop
|
|
ld a, [hl]
|
|
add e
|
|
ld [hl], a
|
|
add hl, bc
|
|
dec d
|
|
jr nz, .change_tod_symbol_loop
|
|
|
|
call AdvanceTimeOfDay
|
|
|
|
xor a
|
|
ld [wLevelSelectionMenuToDFadeStep], a
|
|
ld b, CGB_LEVEL_SELECTION_MENU_TOD_CHANGE
|
|
call GetCGBLayout
|
|
call LevelSelectionMenu_Delay4Frames
|
|
ld a, 1
|
|
ld [wLevelSelectionMenuToDFadeStep], a
|
|
ld b, CGB_LEVEL_SELECTION_MENU_TOD_CHANGE
|
|
call GetCGBLayout
|
|
call LevelSelectionMenu_Delay4Frames
|
|
ld a, 2
|
|
ld [wLevelSelectionMenuToDFadeStep], a
|
|
ld b, CGB_LEVEL_SELECTION_MENU_TOD_CHANGE
|
|
call GetCGBLayout
|
|
call LevelSelectionMenu_Delay4Frames
|
|
ld a, 3
|
|
ld [wLevelSelectionMenuToDFadeStep], a
|
|
ld b, CGB_LEVEL_SELECTION_MENU_TOD_CHANGE
|
|
call GetCGBLayout
|
|
|
|
ld bc, SPRITEOAMSTRUCT_LENGTH
|
|
ld e, 3 * TILE_WIDTH
|
|
.tod_symbol_downwards_loop
|
|
farcall PlaySpriteAnimationsAndDelayFrame
|
|
ld hl, wShadowOAM + $4 * SPRITEOAMSTRUCT_LENGTH + SPRITEOAMSTRUCT_YCOORD
|
|
inc [hl]
|
|
add hl, bc
|
|
inc [hl]
|
|
add hl, bc
|
|
inc [hl]
|
|
add hl, bc
|
|
inc [hl]
|
|
dec e
|
|
jr nz, .tod_symbol_downwards_loop
|
|
|
|
.main_loop
|
|
farcall PlaySpriteAnimations
|
|
call DelayFrame
|
|
call GetJoypad
|
|
call LevelSelectionMenu_GetValidKeys
|
|
ld hl, hJoyPressed
|
|
ld a, [hl]
|
|
and c
|
|
bit A_BUTTON_F, a
|
|
jp nz, .enter_level
|
|
bit B_BUTTON_F, a
|
|
jp nz, .exit
|
|
bit D_DOWN_F, a
|
|
jr nz, .pressed_down
|
|
bit D_UP_F, a
|
|
jr nz, .pressed_up
|
|
bit D_LEFT_F, a
|
|
jr nz, .pressed_left
|
|
bit D_RIGHT_F, a
|
|
jr nz, .pressed_right
|
|
jr .main_loop
|
|
|
|
.pressed_down
|
|
ld c, DOWN
|
|
jr .start_movement
|
|
.pressed_up
|
|
ld c, UP
|
|
jr .start_movement
|
|
.pressed_left
|
|
ld c, LEFT
|
|
jr .start_movement
|
|
.pressed_right
|
|
ld c, RIGHT
|
|
jr .start_movement
|
|
|
|
.start_movement
|
|
ld e, c ; copy direction to e for later (for LevelSelectionMenu_SetAnimSeqAndFrameset)
|
|
; make hl point to the beginning of the transition data for the chosen direction at c
|
|
ld hl, wLevelSelectionMenuLandmarkTransitionsPointer
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
ld b, -1
|
|
call AdvanceNEntries
|
|
ld bc, wLevelSelectionMenuLandmarkTransitionsPointer
|
|
ld a, l
|
|
ld [bc], a
|
|
inc bc
|
|
ld a, h
|
|
ld [bc], a
|
|
|
|
; clear textbox and non-player sprites, as we are about to move out of current landmark
|
|
call LevelSelectionMenu_Delay10Frames
|
|
call LevelSelectionMenu_ClearTextboxOAM ; preserves e
|
|
call LevelSelectionMenu_ClearTextbox ; preserves e
|
|
call LevelSelectionMenu_RefreshTextboxAttrs ; preserves e
|
|
; begin transition
|
|
xor a ; FALSE
|
|
ld [wLevelSelectionMenuStandingStill], a
|
|
ld a, 1 << 7 ; "first step of movement" flag
|
|
ld [wLevelSelectionMenuMovementStepsLeft], a
|
|
call LevelSelectionMenu_SetAnimSeqAndFrameset
|
|
|
|
; perform all movements to transition to the new landmark
|
|
.wait_transition_loop
|
|
; wait until the sprite anim has signaled end of all movements
|
|
; by setting wLevelSelectionMenuStandingStill to TRUE
|
|
farcall PlaySpriteAnimations
|
|
call DelayFrame
|
|
call LevelSelectionMenu_DoPageChangeEvent
|
|
ld a, [wLevelSelectionMenuStandingStill]
|
|
and a
|
|
jr z, .wait_transition_loop
|
|
|
|
call LevelSelectionMenu_InitLandmark
|
|
call LevelSelectionMenu_PrintLevelAndLandmarkNameAndStageIndicators
|
|
call LevelSelectionMenu_DrawDirectionalArrows
|
|
call LevelSelectionMenu_DrawStageTrophies
|
|
call LevelSelectionMenu_RefreshTextboxAttrs
|
|
jp .main_loop
|
|
|
|
.enter_level
|
|
ld a, [wLevelSelectionMenuCurrentLandmark]
|
|
call LevelSelectionMenu_GetLandmarkSpawnPoint
|
|
ld [wDefaultSpawnpoint], a
|
|
call LevelSelectionMenu_Delay10Frames
|
|
ld de, SFX_WARP_TO
|
|
call PlaySFX
|
|
call LevelSelectionMenu_Delay10Frames
|
|
call .EnterLevelFadeOut
|
|
call WaitSFX
|
|
scf
|
|
ret
|
|
|
|
.EnterLevelFadeOut:
|
|
ld b, RGBFADE_TO_WHITE_6BGP_6OBP
|
|
call DoRGBFadeEffect
|
|
jp ClearBGPalettes
|
|
|
|
.exit
|
|
call LevelSelectionMenu_Delay10Frames
|
|
call ClearBGPalettes
|
|
call ClearTilemap
|
|
farcall ClearSpriteAnims
|
|
call ClearSprites
|
|
xor a
|
|
ld [wStateFlags], a
|
|
ret ; nc
|
|
|
|
LevelSelectionMenu_LoadGFX:
|
|
; load inverted font
|
|
farcall LoadInversedFont
|
|
; load gfx for the background tiles, and for the player and directional arrow sprites
|
|
ld hl, LevelSelectionMenuGFX
|
|
ld de, vTiles2
|
|
call Decompress
|
|
farcall GetPlayerIcon
|
|
ld h, d
|
|
ld l, e
|
|
ld a, b
|
|
ld de, vTiles0
|
|
ld bc, 24 tiles
|
|
call FarCopyBytes
|
|
ld hl, LevelSelectionMenuDirectionalArrowsGFX
|
|
; ld de, vTiles0 + 24 tiles
|
|
ld bc, NUM_DIRECTIONS tiles
|
|
call FarCopyBytes
|
|
ld hl, LevelSelectionMenuStageTrophiesGFX
|
|
; ld de, vTiles0 + (24 + NUM_DIRECTIONS) tiles
|
|
ld bc, NUM_LEVEL_STAGES * 2 tiles
|
|
call FarCopyBytes
|
|
ld hl, LevelSelectionMenuTimeOfDaySymbolsGFX
|
|
; ld de, vTiles0 + (24 + NUM_DIRECTIONS + NUM_LEVEL_STAGES * 2) tiles
|
|
ld bc, NUM_DAYTIMES * 4 tiles
|
|
call FarCopyBytes
|
|
ld hl, LevelSelectionMenuLevelHighlighterGFX
|
|
; ld de, vTiles0 + (24 + NUM_DIRECTIONS + NUM_LEVEL_STAGES * 2 + NUM_DAYTIMES * 4) tiles
|
|
ld bc, 8 tiles
|
|
call FarCopyBytes
|
|
ret
|
|
|
|
LevelSelectionMenu_InitTilemap:
|
|
; init tilemap of page at wLevelSelectionMenuCurrentPage
|
|
ld hl, .Tilemaps
|
|
ld bc, 2
|
|
ld a, [wLevelSelectionMenuCurrentPage]
|
|
call AddNTimes
|
|
ld e, [hl]
|
|
inc hl
|
|
ld d, [hl]
|
|
hlcoord 0, 0
|
|
.loop
|
|
ld a, [de]
|
|
cp $ff ; tilemaps are $ff-terminated
|
|
ret z
|
|
ld a, [de]
|
|
ld [hli], a
|
|
inc de
|
|
jr .loop
|
|
|
|
.Tilemaps:
|
|
dw LevelSelectionMenuPage1Tilemap
|
|
dw LevelSelectionMenuPage2Tilemap
|
|
dw LevelSelectionMenuPage3Tilemap
|
|
dw LevelSelectionMenuPage4Tilemap
|
|
|
|
LevelSelectionMenu_InitAttrmap:
|
|
; assign attrs based on tile ids according to LevelSelectionMenuAttrmap
|
|
hlcoord 0, 0
|
|
decoord 0, 0, wAttrmap
|
|
ld bc, SCREEN_WIDTH * SCREEN_HEIGHT
|
|
.loop
|
|
push hl
|
|
ld a, [hl] ; tile id
|
|
ld hl, LevelSelectionMenuAttrmap
|
|
add l
|
|
ld l, a
|
|
ld a, h
|
|
adc 0
|
|
ld h, a
|
|
ld a, [hl] ; attr value
|
|
ld [de], a
|
|
pop hl
|
|
inc hl
|
|
inc de
|
|
dec bc
|
|
ld a, b
|
|
or c
|
|
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
|
|
depixel 0, 0
|
|
; all the SPRITE_ANIM_* related to the level selection menu are sorted by direction, then by gender
|
|
ld a, SPRITE_ANIM_OBJ_LEVEL_SELECTION_MENU_WALK_DOWN
|
|
call InitSpriteAnimStruct
|
|
ld hl, SPRITEANIMSTRUCT_TILE_ID
|
|
add hl, bc
|
|
ld [hl], $00
|
|
ld a, [wLevelSelectionMenuCurrentLandmark]
|
|
call LevelSelectionMenu_GetLandmarkCoords
|
|
; wSpriteAnim1*Coord contain the coord of the bottom right object of the player sprite
|
|
ld hl, SPRITEANIMSTRUCT_XCOORD
|
|
add hl, bc
|
|
ld [hl], e
|
|
ld hl, SPRITEANIMSTRUCT_YCOORD
|
|
add hl, bc
|
|
ld [hl], d
|
|
ret
|
|
|
|
LevelSelectionMenu_InitLandmark:
|
|
; make wLevelSelectionMenuLandmarkTransitionsPointer point
|
|
; to the start of the transition data of the current landmark.
|
|
ld a, [wLevelSelectionMenuCurrentLandmark]
|
|
ld e, a
|
|
ld hl, LevelSelectionMenu_LandmarkTransitions
|
|
ld b, -1
|
|
rept NUM_DIRECTIONS
|
|
ld c, e
|
|
call AdvanceNEntries
|
|
endr
|
|
ld de, wLevelSelectionMenuLandmarkTransitionsPointer
|
|
ld a, l
|
|
ld [de], a
|
|
inc de
|
|
ld a, h
|
|
ld [de], a
|
|
ret
|
|
|
|
LevelSelectionMenu_PrintLevelAndLandmarkNameAndStageIndicators:
|
|
; level indicator and level numbers are 8x16.
|
|
; botton half of their graphics are $10 tiles after the top half.
|
|
hlcoord LSMTEXTBOX_X_COORD, LSMTEXTBOX_Y_COORD
|
|
ld a, LSMTEXTBOX_LEVEL_INDICATOR_TILE
|
|
ld [hl], a
|
|
add $10
|
|
ld bc, SCREEN_WIDTH
|
|
add hl, bc
|
|
ld [hl], a
|
|
; get level from landmark and copy it to wCurLevel
|
|
ld a, [wLevelSelectionMenuCurrentLandmark]
|
|
ld e, a
|
|
ld d, 0
|
|
ld hl, LandmarkToLevelTable
|
|
add hl, de
|
|
ld a, [hl]
|
|
ld [wCurLevel], a
|
|
ld c, 0
|
|
.loop1
|
|
ld e, a
|
|
sub 10
|
|
jr c, .next1
|
|
inc c
|
|
jr .loop1
|
|
.next1
|
|
; c = first digit ; e = second digit
|
|
hlcoord LSMTEXTBOX_X_COORD + 1, LSMTEXTBOX_Y_COORD
|
|
ld a, LSMTEXTBOX_LEVEL_NUMBERS_FIRST_TILE
|
|
add c
|
|
ld [hli], a
|
|
ld a, LSMTEXTBOX_LEVEL_NUMBERS_FIRST_TILE
|
|
add e
|
|
ld [hl], a
|
|
hlcoord LSMTEXTBOX_X_COORD + 1, LSMTEXTBOX_Y_COORD + 1
|
|
ld a, LSMTEXTBOX_LEVEL_NUMBERS_FIRST_TILE + $10
|
|
add c
|
|
ld [hli], a
|
|
ld a, LSMTEXTBOX_LEVEL_NUMBERS_FIRST_TILE + $10
|
|
add e
|
|
ld [hl], a
|
|
|
|
ld a, [wLevelSelectionMenuCurrentLandmark]
|
|
call LevelSelectionMenu_GetLandmarkName
|
|
ld hl, wStringBuffer1
|
|
decoord LSMTEXTBOX_X_COORD + 4, LSMTEXTBOX_Y_COORD
|
|
ld bc, LSMTEXTBOX_MAX_TEXT_ROW_LENGTH
|
|
call CopyBytes
|
|
ld hl, wStringBuffer2
|
|
decoord LSMTEXTBOX_X_COORD + 4, LSMTEXTBOX_Y_COORD + 1
|
|
ld bc, LSMTEXTBOX_MAX_TEXT_ROW_LENGTH
|
|
call CopyBytes
|
|
|
|
ld de, 0 ; e tracks number of already printed stages, to know where to print current one (in descending order)
|
|
ld a, [wLevelSelectionMenuCurrentLandmark]
|
|
call LevelSelectionMenu_GetLandmarkLevelStages
|
|
bit STAGE_4_F, a
|
|
push af
|
|
ld a, LSMTEXTBOX_STAGE_4_INDICATOR_TILE
|
|
call nz, .PrintStageTile
|
|
pop af
|
|
bit STAGE_3_F, a
|
|
push af
|
|
ld a, LSMTEXTBOX_STAGE_3_INDICATOR_TILE
|
|
call nz, .PrintStageTile
|
|
pop af
|
|
bit STAGE_2_F, a
|
|
push af
|
|
ld a, LSMTEXTBOX_STAGE_2_INDICATOR_TILE
|
|
call nz, .PrintStageTile
|
|
pop af
|
|
bit STAGE_1_F, a
|
|
ld a, LSMTEXTBOX_STAGE_1_INDICATOR_TILE
|
|
call nz, .PrintStageTile
|
|
|
|
ld a, 2
|
|
ld [hBGMapThird], a
|
|
dec a ; ld a ,1
|
|
ld [hBGMapMode], a
|
|
call DelayFrame
|
|
xor a
|
|
ld [hBGMapMode], a
|
|
ret
|
|
|
|
.PrintStageTile:
|
|
hlcoord LSMTEXTBOX_X_COORD + (LSMTEXTBOX_WIDTH - 1), LSMTEXTBOX_Y_COORD
|
|
add hl, de
|
|
ld [hl], a
|
|
ld bc, SCREEN_WIDTH
|
|
add hl, bc
|
|
add $10
|
|
ld [hl], a
|
|
dec de
|
|
ret
|
|
|
|
LevelSelectionMenu_ClearTextbox:
|
|
hlcoord LSMTEXTBOX_X_COORD, LSMTEXTBOX_Y_COORD
|
|
ld a, LSMTEXTBOX_BLACK_TILE
|
|
lb bc, LSMTEXTBOX_HEIGHT, LSMTEXTBOX_WIDTH
|
|
call FillBoxWithByte
|
|
ld a, 2
|
|
ld [hBGMapThird], a
|
|
dec a ; ld a, 1
|
|
ld [hBGMapMode], a
|
|
call DelayFrame
|
|
xor a
|
|
ld [hBGMapMode], a
|
|
ret
|
|
|
|
LevelSelectionMenu_RefreshTextboxAttrs:
|
|
; OAM priority changes in the textbox depending on whether a landmark is shown
|
|
; (stage trophies OAM has priority) or player is moving (all BG has priority).
|
|
; Assumes affected tiles are only in the textbox, which is in the bottom third of screen.
|
|
push de
|
|
hlcoord LSMTEXTBOX_X_COORD, LSMTEXTBOX_Y_COORD
|
|
decoord LSMTEXTBOX_X_COORD, LSMTEXTBOX_Y_COORD, wAttrmap
|
|
ld bc, SCREEN_WIDTH * (SCREEN_HEIGHT - LSMTEXTBOX_Y_COORD)
|
|
call LevelSelectionMenu_InitAttrmap.loop
|
|
ld a, 2
|
|
ld [hBGMapThird], a
|
|
ld [hBGMapMode], a
|
|
call DelayFrame
|
|
xor a
|
|
ld [hBGMapMode], a
|
|
pop de
|
|
ret
|
|
|
|
LevelSelectionMenu_DrawTimeOfDaySymbol:
|
|
ld hl, .OAM
|
|
ld de, wShadowOAM + $4 * SPRITEOAMSTRUCT_LENGTH ; always goes after player sprite
|
|
ld a, [wTimeOfDay]
|
|
add a
|
|
ld c, a
|
|
call .CopyObject
|
|
call .CopyObject
|
|
call .CopyObject
|
|
call .CopyObject
|
|
ret
|
|
|
|
.CopyObject:
|
|
ld a, [hli]
|
|
ld [de], a
|
|
inc de
|
|
ld a, [hli]
|
|
ld [de], a
|
|
inc de
|
|
ld a, [hli]
|
|
add c
|
|
ld [de], a
|
|
inc de
|
|
ld a, [hli]
|
|
ld [de], a
|
|
inc de
|
|
ret
|
|
|
|
.OAM:
|
|
db 3 * TILE_WIDTH, 2 * TILE_WIDTH, 24 + NUM_DIRECTIONS + NUM_LEVEL_STAGES * 2 + 0, PAL_LSM_TOD
|
|
db 3 * TILE_WIDTH, 3 * TILE_WIDTH, 24 + NUM_DIRECTIONS + NUM_LEVEL_STAGES * 2 + 1, PAL_LSM_TOD
|
|
db 4 * TILE_WIDTH, 2 * TILE_WIDTH, 24 + NUM_DIRECTIONS + NUM_LEVEL_STAGES * 2 + 8, PAL_LSM_TOD
|
|
db 4 * TILE_WIDTH, 3 * TILE_WIDTH, 24 + NUM_DIRECTIONS + NUM_LEVEL_STAGES * 2 + 9, PAL_LSM_TOD
|
|
|
|
LevelSelectionMenu_DrawDirectionalArrows:
|
|
; Draw directional arrows OAM around player sprite for the valid directions.
|
|
; Objects are drawn in OAM after player sprite objects in wWalkingDirection order.
|
|
; Depends on wLevelSelectionMenuLandmarkTransitionsPointer being initialized.
|
|
call LevelSelectionMenu_GetValidDirections
|
|
ld hl, .OAM
|
|
ld de, wShadowOAM + ($4 + $4) * SPRITEOAMSTRUCT_LENGTH ; always goes after player sprite and ToD symbol
|
|
bit D_DOWN_F, c
|
|
jr z, .next1
|
|
call .DrawArrow
|
|
.next1
|
|
ld hl, .OAM + $3
|
|
bit D_UP_F, c
|
|
jr z, .next2
|
|
call .DrawArrow
|
|
.next2
|
|
ld hl, .OAM + $6
|
|
bit D_LEFT_F, c
|
|
jr z, .next3
|
|
call .DrawArrow
|
|
.next3
|
|
ld hl, .OAM + $9
|
|
bit D_RIGHT_F, c
|
|
call nz, .DrawArrow
|
|
ret
|
|
|
|
.DrawArrow:
|
|
ld a, [wSpriteAnim1YCoord]
|
|
add [hl]
|
|
ld [de], a ; y coord
|
|
inc hl
|
|
inc de
|
|
ld a, [wSpriteAnim1XCoord]
|
|
add [hl]
|
|
ld [de], a ; x coord
|
|
inc hl
|
|
inc de
|
|
ld a, [hli]
|
|
ld [de], a ; tile id
|
|
inc de
|
|
xor a ; PAL_LSM_PLAYER
|
|
ld [de], a ; attr (uses the same pal as player sprite)
|
|
inc de
|
|
ret
|
|
|
|
.OAM:
|
|
; y offset against wSpriteAnim1YCoord, x offset against wSpriteAnim1XCoord, tile id
|
|
; tiles have been loaded to vTiles0 after the player sprites
|
|
db 8, -4, 24 + DOWN
|
|
db -16, -4, 24 + UP
|
|
db -4, -16, 24 + LEFT
|
|
db -4, 8, 24 + RIGHT
|
|
|
|
LevelSelectionMenu_DrawStageTrophies:
|
|
; Draw stage trophies OAM of cleared level stages.
|
|
; These objects go after player sprite, ToD symbol, and arrows in OAM.
|
|
ld de, wShadowOAM + ($4 + $4 + NUM_DIRECTIONS + $0) * SPRITEOAMSTRUCT_LENGTH
|
|
bccoord LSMTEXTBOX_X_COORD + (LSMTEXTBOX_WIDTH - 1), LSMTEXTBOX_Y_COORD
|
|
ld a, 6
|
|
call .draw_stage_trophy
|
|
ret c
|
|
ld de, wShadowOAM + ($4 + $4 + NUM_DIRECTIONS + $2) * SPRITEOAMSTRUCT_LENGTH
|
|
bccoord LSMTEXTBOX_X_COORD + (LSMTEXTBOX_WIDTH - 2), LSMTEXTBOX_Y_COORD
|
|
ld a, 4
|
|
call .draw_stage_trophy
|
|
ret c
|
|
ld de, wShadowOAM + ($4 + $4 + NUM_DIRECTIONS + $4) * SPRITEOAMSTRUCT_LENGTH
|
|
bccoord LSMTEXTBOX_X_COORD + (LSMTEXTBOX_WIDTH - 3), LSMTEXTBOX_Y_COORD
|
|
ld a, 2
|
|
call .draw_stage_trophy
|
|
ret c
|
|
ld de, wShadowOAM + ($4 + $4 + NUM_DIRECTIONS + $6) * SPRITEOAMSTRUCT_LENGTH
|
|
bccoord LSMTEXTBOX_X_COORD + (LSMTEXTBOX_WIDTH - 4), LSMTEXTBOX_Y_COORD
|
|
xor a
|
|
call .draw_stage_trophy
|
|
ret
|
|
|
|
.draw_stage_trophy:
|
|
; input:
|
|
; - de: wShadowOAM address
|
|
; - bc: current tile address in wTilemap
|
|
; - a: .BaseOAMCoords entry to use
|
|
; if current tile is not a stage indicator tile, return carry to signal to not keep going
|
|
push af
|
|
ld a, [bc]
|
|
sub LSMTEXTBOX_STAGE_1_INDICATOR_TILE
|
|
jr c, .ret_c
|
|
cp STAGE_4_F + 1
|
|
jr nc, .ret_c
|
|
call .IsLevelStageCleared
|
|
jr z, .ret_nc ; this level has not been cleared, but there are more levels yet to check, so return nc
|
|
add a
|
|
add a
|
|
ld c, a
|
|
ld b, 0
|
|
ld hl, .BaseOAMTilesAttrs
|
|
add hl, bc
|
|
pop af
|
|
push hl
|
|
add a
|
|
ld c, a
|
|
ld b, 0
|
|
ld hl, .BaseOAMCoords
|
|
add hl, bc
|
|
pop bc
|
|
call .CopyObject
|
|
call .CopyObject
|
|
xor a
|
|
ret ; nc
|
|
|
|
.ret_c:
|
|
pop af
|
|
scf
|
|
ret
|
|
|
|
.ret_nc
|
|
pop af
|
|
xor a
|
|
ret
|
|
|
|
.IsLevelStageCleared:
|
|
; return z if a is equal to wLastClearedLevelStage (for LSMEVENT_SHOW_CLEARED_LEVEL animation).
|
|
; else, return nz if [wCurLevel]'s stage in a has been cleared
|
|
; return z otherwise.
|
|
; preserve a and de.
|
|
ld hl, wLastClearedLevelStage
|
|
cp [hl]
|
|
ret z
|
|
ld c, a
|
|
push bc
|
|
push de
|
|
call GetClearedLevelsStageAddress
|
|
ld b, CHECK_FLAG
|
|
ld d, 0
|
|
ld a, [wCurLevel]
|
|
ld e, a
|
|
call FlagAction
|
|
pop de
|
|
pop bc
|
|
ld a, c
|
|
ret
|
|
|
|
.CopyObject:
|
|
ld a, [hli]
|
|
ld [de], a
|
|
inc de
|
|
ld a, [hli]
|
|
ld [de], a
|
|
inc de
|
|
ld a, [bc]
|
|
ld [de], a
|
|
inc bc
|
|
inc de
|
|
ld a, [bc]
|
|
ld [de], a
|
|
inc bc
|
|
inc de
|
|
ret
|
|
|
|
.BaseOAMCoords:
|
|
db 17 * TILE_WIDTH, 16 * TILE_WIDTH
|
|
db 18 * TILE_WIDTH, 16 * TILE_WIDTH
|
|
db 17 * TILE_WIDTH, 17 * TILE_WIDTH
|
|
db 18 * TILE_WIDTH, 17 * TILE_WIDTH
|
|
db 17 * TILE_WIDTH, 18 * TILE_WIDTH
|
|
db 18 * TILE_WIDTH, 18 * TILE_WIDTH
|
|
db 17 * TILE_WIDTH, 19 * TILE_WIDTH
|
|
db 18 * TILE_WIDTH, 19 * TILE_WIDTH
|
|
|
|
.BaseOAMTilesAttrs:
|
|
db 24 + NUM_DIRECTIONS + 0, PAL_LSM_TROPHY_1
|
|
db 24 + NUM_DIRECTIONS + 4, PAL_LSM_TROPHY_1
|
|
db 24 + NUM_DIRECTIONS + 1, PAL_LSM_TROPHY_2
|
|
db 24 + NUM_DIRECTIONS + 5, PAL_LSM_TROPHY_2
|
|
db 24 + NUM_DIRECTIONS + 2, PAL_LSM_TROPHY_3
|
|
db 24 + NUM_DIRECTIONS + 6, PAL_LSM_TROPHY_3
|
|
db 24 + NUM_DIRECTIONS + 3, PAL_LSM_TROPHY_4
|
|
db 24 + NUM_DIRECTIONS + 7, PAL_LSM_TROPHY_4
|
|
|
|
LevelSelectionMenu_ClearTextboxOAM:
|
|
ld hl, wShadowOAM + $8 * SPRITEOAMSTRUCT_LENGTH
|
|
ld bc, wShadowOAMEnd - (wShadowOAM + $8 * SPRITEOAMSTRUCT_LENGTH)
|
|
xor a
|
|
jp ByteFill
|
|
|
|
LevelSelectionMenu_SetAnimSeqAndFrameset:
|
|
; Set the animation sequence and frameset for this movement.
|
|
; direction (in wWalkingDirection order) is provided in e.
|
|
ld bc, wSpriteAnim1
|
|
ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
|
|
add hl, bc
|
|
ld a, SPRITE_ANIM_FUNC_LEVEL_SELECTION_MENU_WALK_DOWN
|
|
add e ; add direction
|
|
ld [hl], a
|
|
ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
|
|
add hl, bc
|
|
ld a, SPRITE_ANIM_FRAMESET_LEVEL_SELECTION_MENU_WALK_DOWN
|
|
add e ; add direction
|
|
ld [hl], a
|
|
ret
|
|
|
|
LevelSelectionMenu_DoPageChangeEvent:
|
|
ld de, .Events
|
|
ld bc, wSpriteAnim1
|
|
.loop
|
|
ld a, [de] ; SPRITE_ANIM_FUNC_* or $00 table terminator
|
|
and a
|
|
ret z
|
|
inc de
|
|
ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
|
|
add hl, bc
|
|
cp [hl]
|
|
jr nz, .next1
|
|
ld a, [de] ; SPRITEANIMSTRUCT_YCOORD or SPRITEANIMSTRUCT_XCOORD
|
|
ld l, a
|
|
ld h, 0
|
|
add hl, bc
|
|
inc de
|
|
ld a, [de] ; X/Y coordinate
|
|
cp [hl]
|
|
jr nz, .next2
|
|
|
|
; this entry matches
|
|
inc de
|
|
ld a, [de]
|
|
ld l, a
|
|
inc de
|
|
ld a, [de]
|
|
ld h, a
|
|
jp hl
|
|
|
|
.next1
|
|
inc de
|
|
.next2
|
|
inc de
|
|
inc de
|
|
inc de
|
|
jr .loop
|
|
|
|
; LEVELSELECTIONMENU_PAGE_EDGE_* represent values when the player sprite is at:
|
|
; UU
|
|
; =========UU=========
|
|
; =------------------=
|
|
; =------------------=
|
|
; =------------------=
|
|
; =------------------=
|
|
; =------------------=
|
|
; =------------------=
|
|
; =------------------=
|
|
;LL------------------RR
|
|
;LL------------------RR
|
|
; =------------------=
|
|
; =------------------=
|
|
; =------------------=
|
|
; =------------------=
|
|
; =========DD=========
|
|
; =========DD=========
|
|
; ====================
|
|
; ====================
|
|
; for movements spanning two pages, when one edge is reached, the page change occurs
|
|
; and the player appears in the other page at the coordinate of the new edge.
|
|
; hence, for calculating movement length, it's as if both pages were adjacent without the border frame.
|
|
DEF PAGE_EDGE_DOWN EQU $88
|
|
DEF PAGE_EDGE_UP EQU $10
|
|
DEF PAGE_EDGE_LEFT EQU $08
|
|
DEF PAGE_EDGE_RIGHT EQU $a8
|
|
|
|
MACRO page_change_event
|
|
; SPRITE_ANIM_FUNC_* to match, Match object's X or Y, X/Y coordinate, Action if both SPRITE_ANIM_FUNC_* and X/Y match
|
|
db \1, \2, \3
|
|
dw \4
|
|
ENDM
|
|
|
|
.Events:
|
|
page_change_event SPRITE_ANIM_FUNC_LEVEL_SELECTION_MENU_WALK_DOWN, SPRITEANIMSTRUCT_YCOORD, PAGE_EDGE_DOWN, .PageChangeDown
|
|
page_change_event SPRITE_ANIM_FUNC_LEVEL_SELECTION_MENU_WALK_UP, SPRITEANIMSTRUCT_YCOORD, PAGE_EDGE_UP, .PageChangeUp
|
|
page_change_event SPRITE_ANIM_FUNC_LEVEL_SELECTION_MENU_WALK_LEFT, SPRITEANIMSTRUCT_XCOORD, PAGE_EDGE_LEFT, .PageChangeLeft
|
|
page_change_event SPRITE_ANIM_FUNC_LEVEL_SELECTION_MENU_WALK_RIGHT, SPRITEANIMSTRUCT_XCOORD, PAGE_EDGE_RIGHT, .PageChangeRight
|
|
db $0
|
|
|
|
.PageChangeDown:
|
|
call .PageChangeFadeOut
|
|
ld a, PAGE_EDGE_UP
|
|
ld [wSpriteAnim1YCoord], a ; respawn in opposite edge
|
|
ld e, DOWN
|
|
jr .PageChange_Common
|
|
|
|
.PageChangeUp:
|
|
call .PageChangeFadeOut
|
|
ld a, PAGE_EDGE_DOWN
|
|
ld [wSpriteAnim1YCoord], a ; respawn in opposite edge
|
|
ld e, UP
|
|
jr .PageChange_Common
|
|
|
|
.PageChangeLeft:
|
|
call .PageChangeFadeOut
|
|
ld a, PAGE_EDGE_RIGHT
|
|
ld [wSpriteAnim1XCoord], a ; respawn in opposite edge
|
|
ld e, LEFT
|
|
jr .PageChange_Common
|
|
|
|
.PageChangeRight:
|
|
call .PageChangeFadeOut
|
|
ld a, PAGE_EDGE_LEFT
|
|
ld [wSpriteAnim1XCoord], a ; respawn in opposite edge
|
|
ld e, RIGHT
|
|
jr .PageChange_Common
|
|
|
|
.PageChange_Common:
|
|
; set new page and redraw screen
|
|
call LevelSelectionMenu_GetNewPage
|
|
ld [wLevelSelectionMenuCurrentPage], a
|
|
call LevelSelectionMenu_DrawTilemapAndAttrmap
|
|
call .PageChangeFadeIn
|
|
; adjust steps left for the "duplicate" movement of the player leaving and entering a page
|
|
ld hl, wLevelSelectionMenuMovementStepsLeft
|
|
ld a, [hl]
|
|
add 2 * TILE_WIDTH
|
|
ld [hl], a
|
|
ret
|
|
|
|
.PageChangeFadeOut:
|
|
ld b, RGBFADE_TO_BLACK_6BGP_1OBP1
|
|
jp DoRGBFadeEffect
|
|
|
|
.PageChangeFadeIn:
|
|
ld b, RGBFADE_TO_LIGHTER_6BGP_1OBP1
|
|
jp DoRGBFadeEffect
|
|
|
|
LevelSelectionMenu_GetLandmarkPage:
|
|
; Return page number (a) of landmark a.
|
|
push hl
|
|
ld hl, LevelSelectionMenu_Landmarks
|
|
ld bc, LevelSelectionMenu_Landmarks.landmark2 - LevelSelectionMenu_Landmarks.landmark1
|
|
call AddNTimes
|
|
ld a, [hl]
|
|
pop hl
|
|
ret
|
|
|
|
LevelSelectionMenu_GetLandmarkCoords::
|
|
; Return coordinates (d, e) of landmark a.
|
|
push hl
|
|
push bc
|
|
ld hl, LevelSelectionMenu_Landmarks + $1
|
|
ld bc, LevelSelectionMenu_Landmarks.landmark2 - LevelSelectionMenu_Landmarks.landmark1
|
|
call AddNTimes
|
|
ld a, [hli]
|
|
ld e, a
|
|
ld d, [hl]
|
|
pop bc
|
|
pop hl
|
|
ret
|
|
|
|
LevelSelectionMenu_GetLandmarkName::
|
|
; Copy the name of landmark a to wStringBuffer1 (tow row) and wStringBuffer2 (bottom row).
|
|
push hl
|
|
push de
|
|
push bc
|
|
|
|
ld hl, LevelSelectionMenu_Landmarks + $3
|
|
ld bc, LevelSelectionMenu_Landmarks.landmark2 - LevelSelectionMenu_Landmarks.landmark1
|
|
call AddNTimes
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
|
|
ld de, wStringBuffer1
|
|
call .copy
|
|
ld de, wStringBuffer2
|
|
call .copy
|
|
|
|
pop bc
|
|
pop de
|
|
pop hl
|
|
ret
|
|
|
|
.copy
|
|
ld c, LSMTEXTBOX_MAX_TEXT_ROW_LENGTH
|
|
.copy_loop
|
|
ld a, [hli]
|
|
ld [de], a
|
|
inc de
|
|
dec c
|
|
jr nz, .copy_loop
|
|
ret
|
|
|
|
LevelSelectionMenu_GetLandmarkSpawnPoint:
|
|
; Return SPAWN_* (a) of landmark a.
|
|
ld hl, LevelSelectionMenu_Landmarks + $5
|
|
ld bc, LevelSelectionMenu_Landmarks.landmark2 - LevelSelectionMenu_Landmarks.landmark1
|
|
call AddNTimes
|
|
ld a, [hl]
|
|
ret
|
|
|
|
LevelSelectionMenu_GetLandmarkLevelStages:
|
|
; Return STAGE_* flags (a) of landmark a.
|
|
ld hl, LevelSelectionMenu_Landmarks + $6
|
|
ld bc, LevelSelectionMenu_Landmarks.landmark2 - LevelSelectionMenu_Landmarks.landmark1
|
|
call AddNTimes
|
|
ld a, [hl]
|
|
ret
|
|
|
|
LevelSelectionMenu_GetValidKeys:
|
|
call LevelSelectionMenu_GetValidDirections
|
|
ld a, c
|
|
or A_BUTTON | B_BUTTON | SELECT | START
|
|
ld c, a
|
|
ret
|
|
|
|
LevelSelectionMenu_GetValidDirections:
|
|
; Return the valid directions according to landmark transitions and unlocked levels.
|
|
; Depends on wLevelSelectionMenuLandmarkTransitionsPointer being initialized.
|
|
; Return the result in c as a mask of D_<DIR>_F.
|
|
ld hl, wLevelSelectionMenuLandmarkTransitionsPointer
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
ld c, 0
|
|
ld a, [hli]
|
|
inc a
|
|
jr z, .next1
|
|
.loop1
|
|
ld a, [hli]
|
|
inc a
|
|
jr nz, .loop1
|
|
call .IsLevelUnlocked
|
|
jr z, .next1
|
|
set D_DOWN_F, c
|
|
.next1
|
|
ld a, [hli]
|
|
inc a
|
|
jr z, .next2
|
|
.loop2
|
|
ld a, [hli]
|
|
inc a
|
|
jr nz, .loop2
|
|
call .IsLevelUnlocked
|
|
jr z, .next2
|
|
set D_UP_F, c
|
|
.next2
|
|
ld a, [hli]
|
|
inc a
|
|
jr z, .next3
|
|
.loop3
|
|
ld a, [hli]
|
|
inc a
|
|
jr nz, .loop3
|
|
call .IsLevelUnlocked
|
|
jr z, .next3
|
|
set D_LEFT_F, c
|
|
.next3
|
|
ld a, [hli]
|
|
inc a
|
|
ret z
|
|
.loop4
|
|
ld a, [hli]
|
|
inc a
|
|
jr nz, .loop4
|
|
call .IsLevelUnlocked
|
|
ret z
|
|
set D_RIGHT_F, c
|
|
ret
|
|
|
|
.IsLevelUnlocked:
|
|
push hl
|
|
push bc
|
|
; the landmark byte of this transition is two bytes back
|
|
dec hl
|
|
dec hl
|
|
; use LandmarkToLevelTable to find the level that this landmark belongs to
|
|
ld e, [hl]
|
|
ld d, 0
|
|
ld hl, LandmarkToLevelTable
|
|
add hl, de
|
|
; find if said level has been unlocked
|
|
ld e, [hl]
|
|
ld b, CHECK_FLAG
|
|
call UnlockedLevelsFlagAction
|
|
pop bc
|
|
pop hl
|
|
ret
|
|
|
|
LevelSelectionMenu_GetNewPage:
|
|
; return in a the new page that the player is ending up at during this movement involving page change.
|
|
; direction (in wWalkingDirection order) is provided in e.
|
|
ld hl, LevelSelectionMenu_PageGrid - 1
|
|
ld c, LEVELSELECTIONMENU_PAGE_GRID_WIDTH * LEVELSELECTIONMENU_PAGE_GRID_HEIGHT + 1
|
|
.loop
|
|
inc hl
|
|
dec c
|
|
jr z, .out_of_bounds
|
|
ld a, [wLevelSelectionMenuCurrentPage]
|
|
cp [hl]
|
|
jr nz, .loop
|
|
|
|
; find the next page in the grid according to movement direction
|
|
ld a, e
|
|
ld bc, LEVELSELECTIONMENU_PAGE_GRID_WIDTH
|
|
cp DOWN
|
|
jr z, .ok
|
|
ld bc, -LEVELSELECTIONMENU_PAGE_GRID_WIDTH
|
|
cp UP
|
|
jr z, .ok
|
|
ld bc, -1
|
|
cp LEFT
|
|
jr z, .ok
|
|
ld bc, 1
|
|
.ok
|
|
add hl, bc
|
|
ld a, [hl]
|
|
cp -1
|
|
jr z, .out_of_bounds
|
|
ret
|
|
|
|
.out_of_bounds
|
|
ld a, 1
|
|
ret
|
|
|
|
LevelSelectionMenu_Delay4Frames:
|
|
ld a, 4
|
|
jr LevelSelectionMenu_Delay10Frames.loop
|
|
|
|
LevelSelectionMenu_Delay10Frames:
|
|
; Delay 10 frames while playing sprite anims
|
|
ld a, 10
|
|
.loop
|
|
push af
|
|
farcall PlaySpriteAnimationsAndDelayFrame
|
|
pop af
|
|
dec a
|
|
jr nz, .loop
|
|
ret
|
|
|
|
_LevelSelectionMenuHandleTransition:
|
|
; Called from the corresponding SPRITE_ANIM_FUNC_LEVEL_SELECTION_MENU_* animation sequence.
|
|
; This function is here because LevelSelectionMenu_LandmarkTransitions is in this bank.
|
|
; Applies the animation to the player sprite for the current frame.
|
|
ld hl, wLevelSelectionMenuLandmarkTransitionsPointer
|
|
ld a, [hli]
|
|
ld h, [hl]
|
|
ld l, a
|
|
; hl is now somewhere in LevelSelectionMenu_LandmarkTransitions for this transition
|
|
ld de, wLevelSelectionMenuMovementStepsLeft
|
|
ld a, [de]
|
|
bit 7, a
|
|
jr z, .not_first_step
|
|
; if first step of movement, extract the number of steps left of the current movement
|
|
; of the transition, and copy it to wLevelSelectionMenuMovementStepsLeft (clearing bit 7)
|
|
ld a, [hl]
|
|
and %00111111
|
|
ld [de], a
|
|
.not_first_step
|
|
and a
|
|
jr z, .movement_over
|
|
|
|
; one less step left to finish this movement
|
|
dec a
|
|
ld [de], a
|
|
.done
|
|
; return carry to signal back to apply a displacement during this frame
|
|
scf
|
|
ret
|
|
|
|
.movement_over
|
|
; advance pointer to the next movement
|
|
ld hl, wLevelSelectionMenuLandmarkTransitionsPointer
|
|
ld a, [hli]
|
|
ld d, [hl]
|
|
ld e, a
|
|
inc de
|
|
dec hl
|
|
ld [hl], e
|
|
inc hl
|
|
ld [hl], d
|
|
; check if we just ran the last movement of the transition
|
|
; that would be the case if the next byte is the landmark, and the one after it is -1
|
|
inc de
|
|
ld a, [de]
|
|
dec de
|
|
inc a
|
|
jr z, .all_movements_over
|
|
; more movements left. which direction is the next movement?
|
|
ld a, [de]
|
|
and %11000000
|
|
swap a
|
|
srl a
|
|
srl a
|
|
ld e, a ; DOWN / UP / LEFT / RIGHT
|
|
call LevelSelectionMenu_SetAnimSeqAndFrameset
|
|
ld a, 1 << 7 ; "first step of movement" flag
|
|
ld [wLevelSelectionMenuMovementStepsLeft], a
|
|
; return nc to signal back not to apply a displacement during this frame
|
|
xor a
|
|
ret
|
|
|
|
.all_movements_over
|
|
; all movements of this transition are over
|
|
; hl is now pointing to the destination landmark byte of this tranisiton
|
|
; end the movement state
|
|
ld a, TRUE
|
|
ld [wLevelSelectionMenuStandingStill], a
|
|
; set new landmark
|
|
ld a, [de]
|
|
ld [wLevelSelectionMenuCurrentLandmark], a
|
|
ld [wDefaultLevelSelectionMenuLandmark], a
|
|
; make the player sprite face down as the default state
|
|
ld hl, SPRITEANIMSTRUCT_ANIM_SEQ_ID
|
|
add hl, bc
|
|
ld a, SPRITE_ANIM_FUNC_LEVEL_SELECTION_MENU_WALK_DOWN
|
|
ld [hl], a
|
|
ld hl, SPRITEANIMSTRUCT_FRAMESET_ID
|
|
add hl, bc
|
|
ld a, SPRITE_ANIM_FRAMESET_LEVEL_SELECTION_MENU_WALK_DOWN
|
|
ld [hl], a
|
|
; return nc to signal back not to apply a displacement during this frame
|
|
xor a
|
|
ret
|
|
|
|
INCLUDE "data/levels/level_selection_menu.asm"
|
|
|
|
LevelSelectionMenuGFX:
|
|
INCBIN "gfx/level_selection_menu/background.2bpp.lz"
|
|
|
|
LevelSelectionMenuPage1Tilemap:
|
|
INCBIN "gfx/level_selection_menu/page_1.tilemap"
|
|
|
|
LevelSelectionMenuPage2Tilemap:
|
|
INCBIN "gfx/level_selection_menu/page_2.tilemap"
|
|
|
|
LevelSelectionMenuPage3Tilemap:
|
|
INCBIN "gfx/level_selection_menu/page_3.tilemap"
|
|
|
|
LevelSelectionMenuPage4Tilemap:
|
|
INCBIN "gfx/level_selection_menu/page_4.tilemap"
|
|
|
|
LevelSelectionMenuAttrmap:
|
|
INCLUDE "gfx/level_selection_menu/attrmap.asm"
|
|
|
|
LevelSelectionMenuDirectionalArrowsGFX:
|
|
INCBIN "gfx/level_selection_menu/directional_arrows.2bpp"
|
|
|
|
LevelSelectionMenuStageTrophiesGFX:
|
|
INCBIN "gfx/level_selection_menu/stage_trophies.2bpp"
|
|
|
|
LevelSelectionMenuTimeOfDaySymbolsGFX:
|
|
INCBIN "gfx/level_selection_menu/time_of_day_symbols.2bpp"
|
|
|
|
LevelSelectionMenuLevelHighlighterGFX:
|
|
INCBIN "gfx/level_selection_menu/level_highlighter.2bpp"
|