diff --git a/Core/sram.asm b/Core/sram.asm index 40ccf99..1cae272 100644 --- a/Core/sram.asm +++ b/Core/sram.asm @@ -87,6 +87,12 @@ MagicBeanProg = $7EF39B JournalState = $7EF39C +; State machine for Link's House intro sequence (custom_tag.asm) +; 0x00 - Telepathic Plea phase +; 0x01 - Wake Up Player phase +; 0x02 - End (intro complete) +StoryState = $7EF39E + ; 7EF403 - 7EF4FD Unused block ; .... .cpw diff --git a/Docs/Core/MemoryMap.md b/Docs/Core/MemoryMap.md index c165d8f..cc9d464 100644 --- a/Docs/Core/MemoryMap.md +++ b/Docs/Core/MemoryMap.md @@ -26,6 +26,7 @@ The following blocks were marked "unused" in vanilla ALTTP but are now utilized | `$7EF39B` | `MagicBeanProg` | Multi-day growth cycle tracking for magic bean side-quest (`.dts fwpb`). | ✓ | | `$7EF39C` | `JournalState` | Current state of the player's journal. | ✓ | | `$7EF39D` | `SRAM_StormsActive` | Flag indicating if the Song of Storms effect is active. | ✓ | +| `$7EF39E` | `StoryState` | State machine for Link's House intro sequence (0-2). | ✓ | #### **Block $7EF403-$7EF4FD** - Partially Repurposed @@ -135,6 +136,7 @@ This section details the layout of the save file memory. | `$7EF39B` | `MagicBeanProg` | Tracks the multi-day growth cycle of the magic bean side-quest. | | `$7EF39C` | `JournalState` | The current state of the player's journal. | | `$7EF39D` | `SRAM_StormsActive`| A flag indicating if the Song of Storms effect is active. | +| `$7EF39E` | `StoryState` | State machine for Link's House intro sequence (0=Telepathy, 1=WakeUp, 2=End). | | `$7EF410` | `Dreams` | A bitfield tracking the collection of the three "Dreams" (Courage, Power, Wisdom). | | `$7EF347` | `ZoraMask` | Flag indicating if the player has obtained the Zora Mask. | | `$7EF348` | `BunnyHood` | Flag indicating if the player has obtained the Bunny Hood. | diff --git a/Dungeons/custom_tag.asm b/Dungeons/custom_tag.asm index 9a7c26e..9934859 100644 --- a/Dungeons/custom_tag.asm +++ b/Dungeons/custom_tag.asm @@ -2,7 +2,7 @@ ; Custom Tag ; Provide custom room behavior based on room ID -StoryState = $7C +; StoryState is now defined in Core/sram.asm at $7EF39E (persistent SRAM) RoomTag_Return = $01CC5A ; override routine 0x39 "Holes(7)" @@ -27,9 +27,16 @@ CustomTag: HouseTag_Main: { - LDA.w StoryState - JSL $008781 + LDA.l StoryState ; Must use long addressing for SRAM ($7EF39E) + CMP.b #$03 : BCC .valid_state + ; If state is invalid (>= 3), force reset to 0 (Intro) + LDA.b #$00 : STA.l StoryState + .valid_state + ASL A : TAX + JSR (.jump_table, X) + RTS + .jump_table dw HouseTag_TelepathicPlea dw HouseTag_WakeUpPlayer dw HouseTag_End @@ -48,7 +55,7 @@ HouseTag_Main: ; "Accept our quest, Link!" LDA.b #$1F : LDY.b #$00 JSL Sprite_ShowMessageUnconditional - INC.b StoryState + LDA.l StoryState : INC A : STA.l StoryState ; Long addressing for SRAM RTS } @@ -71,7 +78,7 @@ HouseTag_Main: ;LDA.b #$01 : STA $02E4 STZ $02E4 ; awake from slumber - INC.b StoryState + LDA.l StoryState : INC A : STA.l StoryState ; Long addressing for SRAM ; Make it so Link's uncle never respawns in the house again. LDA $7EF3C6 : ORA.b #$10 : STA $7EF3C6 @@ -86,7 +93,7 @@ HouseTag_Main: HouseTag_End: { LDA $B6 : BNE .hasMetFarore - LDA #$00 : STA.w StoryState + LDA #$00 : STA.l StoryState ; Long addressing for SRAM .hasMetFarore RTS } diff --git a/Menu/menu.asm b/Menu/menu.asm index 5937dee..d1b65cc 100644 --- a/Menu/menu.asm +++ b/Menu/menu.asm @@ -1,820 +1,895 @@ -; ========================================================= -; The Legend of Zelda: Oracle of Secrets -; ------------ Custom Menu ------------ -; -; - Navigate between two menus with L and R -; - New item layout and draw routines -; - Detailed quest status screen -; - Player name, location names -; - Custom HUD with new magic meter -; ========================================================= - -pushpc -; Free ROM in Bank 00 -org $0098AB : db $6C -org $0098AC : db $64 - -; Module RunInterface 0E.01: Item Menu -org $00F877 : db Menu_Entry>>0 -org $00F883 : db Menu_Entry>>8 -org $00F88F : db Menu_Entry>>16 - -; NMI_DoUpdates.skip_sprite_updates -; Stored to VMADDR -org $808B6B : LDX.w #$6040 - -; UpdateEquippedItem -org $8DDFB2 : LDA.l Menu_ItemIndex, X -pullpc - -; ========================================================= -; Menu Bank - -org $2D8000 -incsrc "menu_gfx_table.asm" -incsrc "menu_text.asm" -incsrc "menu_palette.asm" - -; ========================================================= -; SUBROUTINE TABLE - -Menu_Entry: -{ - PHB : PHK : PLB - LDA.w $0200 : ASL : TAX - JSR (.vectors,X) - - SEP #$20 - PLB - RTL - - .vectors - dw Menu_InitGraphics ; 00 - dw Menu_UploadRight ; 01 - dw Menu_UploadLeft ; 02 - dw Menu_ScrollDown ; 03 - dw Menu_ItemScreen ; 04 - dw Menu_ScrollTo ; 05 - dw Menu_StatsScreen ; 06 - dw Menu_ScrollFrom ; 07 - dw Menu_ScrollUp ; 08 - dw Menu_RingBox ; 09 - dw Menu_Exit ; 0A - dw Menu_InitiateScrollDown ; 0B - dw Menu_MagicBag ; 0C - dw Menu_SongMenu ; 0D - dw Menu_Journal ; 0E -} - -; ========================================================= -; 00 MENU INIT GRAPHICS - -Menu_InitGraphics: -{ - LDA.w $0780 : STA.w $00 - LDA.w $0202 - CMP.b #$10 : BNE .not_fishing - JSL DismissRodFromMenu - .not_fishing - CMP.b #$06 : BEQ .bottle - CMP.b #$0C : BEQ .bottle - CMP.b #$12 : BEQ .bottle - CMP.b #$18 : BEQ .bottle - CMP.b #$15 : BEQ .wolf_shovel - BRA + - .bottle - LDA $3A : AND.b #$80 : STA $3A - LDA $50 : AND.b #$FE : STA $50 - LDA.b #$80 : STA $44 : STA $45 - BRA + - .wolf_shovel - LDA.b $3A : AND.b #$80 : STA.b $3A - LDA.b $50 : AND.b #$FE : STA.b $50 - + - STZ.w $030D ; SWEAT - STZ.w $0300 ; ITEMSTEP - STZ.w $037A ; USEY2 - STZ.w $0301 ; USEY1 - STZ.w $020C ; Stats Screen Cursor Index - INC $0200 -} - -; ========================================================= -; 01 MENU UPLOAD RIGHT - -incsrc "menu_draw.asm" - -Menu_UploadRight: -{ - JSR Menu_DrawBackground - JSR Menu_DrawQuestItems - JSR Menu_DrawCharacterName - JSR Menu_DrawBigKey - JSR Menu_DrawBigChestKey - - JSR Menu_DrawQuestIcons - JSR Menu_DrawTriforceIcons - JSR Menu_DrawPendantIcons - JSR Menu_DrawMagicRings - JSR Menu_DrawPlaytimeLabel - - JSR Menu_DrawHeartPieces - JSR Menu_DrawQuestStatus - JSR Menu_DrawAreaNameTXT - JSR DrawLocationName - - SEP #$30 - LDA.b #$23 : STA.w $0116 - LDA.b #$01 : STA.b $17 - INC.w $0200 - RTS -} - -; ========================================================= -; 02 MENU UPLOAD LEFT - -Menu_UploadLeft: -{ - JSR Menu_DrawBackground - JSR DrawYItems - JSR Menu_DrawSelect - JSR Menu_DrawItemName - ; INSERT PALETTE ------- - - LDX.w #$3E - .loop - LDA.w Menu_Palette, X - STA.l $7EC502, X - DEX : DEX - BPL .loop - SEP #$30 - ;----------------------- - - LDA.b #$22 : STA.w $0116 - LDA.b #$01 : STA.b $17 : STA.b $15 ; added for palette - INC.w $0200 - RTS -} - -; ========================================================= -; 03 MENU SCROLL DOWN - -Menu_Scroll: - dw 0, -3, -5, -7, -10, -12, -15, -20 - dw -28, -40, -50, -60, -75, -90, -100 - dw -125, -150, -175, -190, -200, -210 - dw -220, -225, -230, -232, -234, -238 - -Menu_ScrollDown: -{ - LDA.b #$11 : STA.w $012F - SEP #$10 - REP #$20 - - LDX.w MenuScrollLevelV - INX : INX - LDA.w Menu_Scroll, X - STA.b $EA - CMP.w #$FF12 : BNE .notDoneScrolling - JMP Menu_InitItemScreen - - .notDoneScrolling - STX.w MenuScrollLevelV - RTS -} - -; ========================================================= -; 04 MENU ITEM SCREEN - -incsrc "menu_select_item.asm" - -Menu_CheckForSpecialMenus: -{ - LDA.w $0202 : CMP.b #$05 : BNE + - LDA.b $F6 : BIT.b #$80 : BEQ + - STZ.w $020B - LDA.b #$0C : STA.w $0200 ; Magic Bag - + - LDA.w $0202 : CMP.b #$0D : BNE ++ - LDA.b $F6 : BIT.b #$80 : BEQ ++ - LDA.b #$0D : STA.w $0200 - JSR Menu_DeleteCursor - JSR Menu_DrawSongMenu - SEP #$30 - JMP .exit - ++ - LDA.w $0202 : CMP.b #$0E : BNE ++ - LDA.b $F6 : BIT.b #$80 : BEQ ++ - LDA.b #$0E : STA.w $0200 - JSR Menu_DeleteCursor - JSL Menu_DrawJournal - SEP #$30 - JMP .exit - ++ - - LDA.b $F6 : BIT.b #$40 : BEQ +++ - JSR Menu_DeleteCursor - JSR Menu_DrawRingBox - STZ.w $020B - LDA.b #$09 : STA.w $0200 ; Ring Box - JMP .exit - +++ - .exit - - RTS -} - - -Menu_ItemScreen: -{ - JSR Menu_CheckHScroll - - INC $0207 - LDA.w $0202 : BEQ .do_no_input - ; Scroll through joypad 1 inputs - ASL : TAY : LDA.b $F4 - LSR : BCS .move_right - LSR : BCS .move_left - LSR : BCS .move_down - LSR : BCS .move_up - JSR Menu_CheckForSpecialMenus - .do_no_input - BRA .no_inputs - - .move_right - JSR Menu_DeleteCursor - JSR Menu_FindNextItem - BRA .draw_cursor - - .move_left - JSR Menu_DeleteCursor - JSR Menu_FindPrevItem - BRA .draw_cursor - - .move_down - JSR Menu_DeleteCursor - JSR Menu_FindNextDownItem - BRA .draw_cursor - - .move_up - JSR Menu_DeleteCursor - JSR Menu_FindNextUpItem - BRA .draw_cursor - - .draw_cursor - LDA.b #$20 : STA.w $012F ; cursor move sound effect - - .no_inputs - SEP #$30 - LDA.w $0202 : ASL : TAY - REP #$10 - LDX.w Menu_ItemCursorPositions-2, Y - JSR Menu_DrawCursor - - JSR Menu_DrawItemName - SEP #$20 - .exit - LDA.b #$22 : STA.w $0116 - LDA.b #$01 : STA.b $17 - - RTS -} - -; ========================================================= -; 05 MENU SCROLL TO - -Menu_ScrollTo: -{ - SEP #$20 - JSR Menu_ScrollHorizontal : BCC .not_done - INC.w $0200 - .not_done - RTS -} - -; ========================================================= -; 06 MENU STATS SCREEN - -incsrc "menu_scroll.asm" - -Menu_StatsScreen: -{ - JSR Menu_CheckHScroll - JSR Menu_StatsScreen_Input - RTS -} - -; ========================================================= -; 07 MENU SCROLL FROM - -Menu_ScrollFrom: -{ - JSR Menu_ScrollHorizontal : BCC .not_done - JMP Menu_InitItemScreen - .not_done - RTS -} - -; ========================================================= -; 08 MENU SCROLL UP - -Menu_ScrollUp: -{ - SEP #$10 - REP #$20 - - LDX.w MenuScrollLevelV - LDA.w Menu_Scroll, X - STA.b $EA : BNE .notDoneScrolling - STZ.b $E4 - LDA.w #$000A : STA.w $0200 - RTS - - .notDoneScrolling - DEX : DEX : STX.w MenuScrollLevelV - RTS -} - -; ========================================================= -; CHECK BOTTLE - -Menu_CheckBottle: -{ - LDA.w $0202 : CMP.b #$06 : BNE .not_first - LDA.b #$0001 : JMP .prepare_bottle - .not_first - - LDA.w $0202 : CMP.b #$0C : BNE .not_second - LDA.b #$0002 : JMP .prepare_bottle - .not_second - - LDA.w $0202 : CMP.b #$12 : BNE .not_third - LDA.b #$0003 : JMP .prepare_bottle - .not_third - - LDA.w $0202 : CMP.b #$18 : BNE .not_any - LDA.b #$0004 - .prepare_bottle - STA.l BottleIndex - .not_any - RTS -} - -; ========================================================= -; 0A MENU EXIT - -Menu_Exit: -{ - JSL LinkState_ResetMaskAnimated - JSR Menu_CheckBottle - REP #$20 - - ; reset submodule - STZ $0200 - - ; go back to the submodule we came from - LDA.w $010C : STA.b $10 - - ; set $0303 by using $0202 to index table on exit - ; set $0304 to prevent item + 1 animation exploits - LDX $0202 - LDA.w Menu_ItemIndex, X : STA $0303 : STA.w $0304 - - LDX.b #$3E - .loop - LDA.l $7EC300, X - STA.l $7EC500, X - DEX : DEX - BPL .loop - - INC.b $15 - INC.b $16 - - RTS -} - -; ========================================================= -; 0B MENU COPY TO RIGHT - -Menu_InitiateScrollDown: -{ - REP #$20 - - ; Clear out the whole buffer. - LDX.b #$FE ; $1700-17FF - - .loop - LDA.w #$387F - STA.w $1000, X : STA.w $1100, X - STA.w $1200, X : STA.w $1300, X - STA.w $1400, X : STA.w $1500, X - STA.w $1600, X : STA.w $1700, X - DEX : DEX : BNE .loop - - ; TODO: The BPL wasn't working so figure out why and - ; fix it instead of doing this abomination. - STA.w $1000 : STA.w $1100 - STA.w $1200 : STA.w $1300 - STA.w $1400 : STA.w $1500 - STA.w $1600 : STA.w $1700 - - SEP #$20 - - JSL RebuildHUD_long - - ; Draw one frame of the clock so it doesn't just - ; pop in when scrolling down. - JSL DrawClockToHudLong - - ; The whole HUD fits on 4 rows so I'm only going to - ; copy 4 here. Also we start 2 in because thats the - ; left we need to go. - - LDX.b #$3A - .loop1 - LDA $7EC702, X : STA $1082, X - DEX : BNE .loop1 - - LDX.b #$3A - .loop2 - LDA $7EC742, X : STA $10C2, X - DEX : BNE .loop2 - - LDX.b #$3A - .loop3 - LDA $7EC782, X : STA $1102, X - DEX : BNE .loop3 - - LDX.b #$3A - .loop4 - LDA $7EC7C2, X : STA $1142, X - DEX : BNE .loop4 - - LDA.b #$24 : STA.w $0116 - LDA.b #$01 : STA.b $17 - LDA.b #$08 : STA.w $0200 - LDA.b #$12 : STA.w $012F ; play menu exit sound effect - - RTS -} - -; ========================================================= -; 0C MENU MAGIC BAG - -Menu_MagicBag: -{ - JSR Menu_DrawMagicBag - JSR Menu_DrawMagicItems - SEP #$30 - - INC $0207 - LDA.b $F4 - LSR : BCS .move_right - LSR : BCS .move_left - LSR : BCS .move_down - LSR : BCS .move_up - BRA .continue - - .move_up - .move_right - REP #$30 - LDX.w Menu_MagicBagCursorPositions-2, Y - JSR Menu_DeleteCursor_AltEntry - INC.w $020B - LDA.w $020B : CMP.b #$06 : BCS .zero - BRA .continue - - .move_down - .move_left - REP #$30 - LDX.w Menu_MagicBagCursorPositions-2, Y - JSR Menu_DeleteCursor_AltEntry - LDA.w $020B : CMP.b #$00 : BEQ .continue - DEC.w $020B - BRA .continue - .zero - STZ.w $020B - .continue - JSR DrawCollectibleNamesAndCount - LDA.w $020B - ASL : TAY - REP #$10 - LDX.w Menu_MagicBagCursorPositions, Y - JSR Menu_DrawCursor - JSR MagicBag_ConsumeItem - JSR Submenu_Return - - LDA.b #$22 : STA.w $0116 - LDA.b #$01 : STA.b $17 - - RTS -} - -Menu_MagicBagCursorPositions: - dw menu_offset(8,6) ; banana - dw menu_offset(8,10) ; pineapple - dw menu_offset(8,14) ; goron rock meat - dw menu_offset(12,6) ; seashells - dw menu_offset(12,10) ; honeycombs - dw menu_offset(12,14) ; deku sticks - -MagicBag_ConsumeItem: -{ - ; Check for A button press - LDA.b $F6 : BIT.b #$80 : BEQ .exit - - REP #$30 - ; Calculate SRAM address for current item (4 bytes per entry) - LDA.w $020B : ASL #2 : TAX - LDA.l .sram_addresses, X : STA $00 - LDA.l .sram_addresses+2, X : STA $02 - SEP #$30 - - ; Handle Consumption - PHB : LDA $02 : PHA : PLB - LDA ($00) : BEQ .error_dbr - - ; Call Handler - JSL Link_ConsumeMagicBagItem - BCC .failed_use_dbr - - ; Success -> Decrement - LDA ($00) : DEC A : STA ($00) - PLB - - ; Sound - LDA.b #$35 : STA.w $012F - BRA .exit - -.failed_use_dbr - PLB -.error_dbr - ; Error Sound - LDA.b #$3C : STA.w $012E - BRA .exit - -.exit - RTS - -.sram_addresses - dd Bananas - dd Pineapples - dd RockMeat - dd Seashells - dd Honeycomb - dd DekuSticks -} - -; ========================================================= -; 0D MENU SONG MENU - -Menu_SongMenu: -{ - REP #$30 - JSR Menu_DrawMusicNotes - - INC $0207 - LDA.w CurrentSong : BEQ + - ASL : TAY - LDA.b $F4 - LSR : BCS .move_right - LSR : BCS .move_left - LSR : BCS .move_down - LSR : BCS .move_up - + - JMP .continue - - .move_right - .move_up - REP #$30 - LDX.w Menu_SongIconCursorPositions-2, Y - JSR Menu_DeleteCursor_AltEntry - LDA.w CurrentSong : CMP.b #$04 : BEQ .reset - INC.w CurrentSong - LDA.w CurrentSong - PHA - LDA $7EF34C : CMP.b #$01 : BEQ .max_1 - CMP.b #$02 : BEQ .max_2 - CMP.b #$03 : BEQ .max_3 - PLA - CMP.b #$05 : BCS .wrap_to_min - JMP .continue - .max_1 - PLA : CMP.b #$02 : BCS .wrap_to_min - .max_2 - PLA : CMP.b #$03 : BCS .wrap_to_min - JMP .continue - .max_3 - PLA : CMP.b #$04 : BCS .wrap_to_min - JMP .continue - .wrap_to_max - LDA $7EF34C : CMP.b #$01 : BEQ .wrap_to_min - CMP.b #$02 : BEQ .set_max_to_2 - CMP.b #$03 : BEQ .set_max_to_3 - LDA #$04 : STA.w CurrentSong : JMP .continue - - .set_max_to_3 - LDA #$03 : STA.w CurrentSong : JMP .continue - - .set_max_to_2 - LDA #$02 : STA.w CurrentSong : JMP .continue - - .wrap_to_min - LDA #$01 : STA.w CurrentSong - BRA .continue - - .move_left - .move_down - REP #$30 - LDX.w Menu_SongIconCursorPositions-2, Y - JSR Menu_DeleteCursor_AltEntry - LDA.w CurrentSong : CMP.b #$01 : BEQ .reset - DEC.w CurrentSong - LDA.w CurrentSong - CMP #$00 : BEQ .wrap_to_max - BRA .continue - .reset - LDA #$01 : STA.w CurrentSong - - .continue - - JSR Menu_DrawItemName - SEP #$30 - LDA.w CurrentSong : ASL : TAY - REP #$10 - LDX.w Menu_SongIconCursorPositions-2, Y - JSR Menu_DrawCursor - JSR Submenu_Return - SEP #$20 - - LDA.b #$22 : STA.w $0116 - LDA.b #$01 : STA.b $17 - - RTS -} - -Menu_SongIconCursorPositions: - dw menu_offset(8,4) - dw menu_offset(8,8) - dw menu_offset(8,12) - dw menu_offset(8,16) - -; ========================================================= -; 09 MENU RING BOX - -Menu_RingBox: -{ - JSR Menu_DrawRingBox - JSR Menu_DrawMagicRingsInBox - INC $0207 - - LDA.b $F4 - LSR : BCS .move_right - LSR : BCS .move_left - LSR : BCS .move_down - LSR : BCS .move_up - BRA .continue - - .move_up - .move_right - REP #$30 - LDX.w Menu_RingIconCursorPositions-2, Y - JSR Menu_DeleteCursor_AltEntry - INC.w $020B - LDA.w $020B : CMP.b #$06 : BCS .zero - BRA .continue - .move_left - .move_down - REP #$30 - LDX.w Menu_RingIconCursorPositions-2, Y - JSR Menu_DeleteCursor_AltEntry - LDA.w $020B : CMP.b #$00 : BEQ .continue - DEC.w $020B - BRA .continue - .zero - STZ.w $020B - .continue - - JSR DrawMagicRingNames - LDA.w $020B : ASL : TAY - REP #$10 - LDX.w Menu_RingIconCursorPositions, Y - JSR Menu_DrawCursor - JSR RingMenu_Controls - SEP #$20 - - LDA.b #$22 : STA.w $0116 - LDA.b #$01 : STA.b $17 - - RTS -} - -Menu_RingIconCursorPositions: - dw menu_offset(8,6) - dw menu_offset(8,10) - dw menu_offset(8,14) - dw menu_offset(12,6) - dw menu_offset(12,10) - dw menu_offset(12,14) - -RingMenu_StoreRingToSlotStack: -{ - ; TODO: Check how many ring slots we currently have - - ; Check if the ring is already in a slot - STA.b $00 - LDA.b $00 : CMP.l RingSlot1 : BEQ .return - LDA.b $00 : CMP.l RingSlot2 : BEQ .return - LDA.b $00 : CMP.l RingSlot3 : BEQ .return - PHA - ; Check the SRAM for an available ring slot - ; If none is available we shift the stack - ; $7EF38C-7EF38E (Size 03) - - LDA.l RingSlot1 : BEQ .slot1_available - LDA.l RingSlot2 : BEQ .slot2_available - LDA.l RingSlot3 : BEQ .slot3_available - - ; Shift the stack - LDA.l RingSlot2 : STA.l RingSlot1 - LDA.l RingSlot3 : STA.l RingSlot2 - .slot3_available - PLA : STA.l RingSlot3 - .return - RTS - - .slot1_available - PLA : STA.l RingSlot1 - RTS - .slot2_available - PLA : STA.l RingSlot2 - RTS -} - -RingMenu_Controls: -{ - ; Load the current ring selected (0-5) into A - REP #$30 - LDA.w $020B - AND.w #$00FF - SEP #$30 - ; Set the current ring to the cursor position - TAY ; Transfer A to Y for indexing - LDA.b $F6 : BIT.b #$80 : BEQ + ; Check if the confirm button is pressed - LDA .rings, Y ; Load the ring bitmask - AND.l MAGICRINGS ; Check if the ring is owned - BEQ + ; If not, skip setting the ring - INY #2 - TYA ; Transfer Y to A - JSR RingMenu_StoreRingToSlotStack - + - - ; Return to item menu if player presses X - LDA.b $F6 : BIT.b #$40 : BEQ + - LDA.b #$01 : STA.w $0200 - + - - ; Close the menu if the player presses start - LDA.b $F4 : BIT.b #$10 : BEQ + - LDA.b #$08 : STA.w $0200 - + - RTS - - .rings - db $20, $10, $08, $04, $02, $01 -} - -Menu_Journal: -{ - JSL Journal_Handler - - JSR Submenu_Return - - LDA.b #$22 : STA.w $0116 - LDA.b #$01 : STA.b $17 - RTS -} - -Submenu_Return: -{ - ; Return to the item menu if they press A - LDA.b $F6 : BIT.b #$80 : BEQ + - LDA.b #$02 : STA.w $0200 - + - - ; Close the menu if the player presses start - LDA.b $F4 : BIT.b #$10 : BEQ + - LDA.b #$08 : STA.w $0200 - + - RTS -} - -menu_frame: incbin "tilemaps/menu_frame.tilemap" -quest_icons: incbin "tilemaps/quest_icons.tilemap" -incsrc "menu_map_names.asm" -%log_end("Menu/menu.asm", !LOG_MENU) -incsrc "menu_hud.asm" -%log_end("Menu/menu_hud.asm", !LOG_MENU) -incsrc "menu_journal.asm" -%log_end("Menu/menu_journal.asm", !LOG_MENU) - +; ========================================================= +; The Legend of Zelda: Oracle of Secrets +; ------------ Custom Menu ------------ +; +; - Navigate between two menus with L and R +; - New item layout and draw routines +; - Detailed quest status screen +; - Player name, location names +; - Custom HUD with new magic meter +; ========================================================= + +pushpc +; Free ROM in Bank 00 +org $0098AB : db $6C +org $0098AC : db $64 + +; Module RunInterface 0E.01: Item Menu +org $00F877 : db Menu_Entry>>0 +org $00F883 : db Menu_Entry>>8 +org $00F88F : db Menu_Entry>>16 + +; NMI_DoUpdates.skip_sprite_updates +; Stored to VMADDR +org $808B6B : LDX.w #$6040 + +; UpdateEquippedItem +org $8DDFB2 : LDA.l Menu_ItemIndex, X +pullpc + +; ========================================================= +; Menu Bank + +org $2D8000 +incsrc "menu_gfx_table.asm" +incsrc "menu_text.asm" +incsrc "menu_palette.asm" + +; ========================================================= +; SUBROUTINE TABLE + +Menu_Entry: +{ + PHB : PHK : PLB + LDA.w $0200 : ASL : TAX + JSR (.vectors,X) + + SEP #$20 + PLB + RTL + + .vectors + dw Menu_InitGraphics ; 00 + dw Menu_UploadRight ; 01 + dw Menu_UploadLeft ; 02 + dw Menu_ScrollDown ; 03 + dw Menu_ItemScreen ; 04 + dw Menu_ScrollTo ; 05 + dw Menu_StatsScreen ; 06 + dw Menu_ScrollFrom ; 07 + dw Menu_ScrollUp ; 08 + dw Menu_RingBox ; 09 + dw Menu_Exit ; 0A + dw Menu_InitiateScrollDown ; 0B + dw Menu_MagicBag ; 0C + dw Menu_SongMenu ; 0D + dw Menu_Journal ; 0E + dw Menu_SubmenuReturn ; 0F +} + +; ========================================================= +; 00 MENU INIT GRAPHICS + +Menu_InitGraphics: +{ + LDA.w $0780 : STA.w $00 + LDA.w $0202 + CMP.b #$10 : BNE .not_fishing + JSL DismissRodFromMenu + .not_fishing + CMP.b #$06 : BEQ .bottle + CMP.b #$0C : BEQ .bottle + CMP.b #$12 : BEQ .bottle + CMP.b #$18 : BEQ .bottle + CMP.b #$15 : BEQ .wolf_shovel + BRA + + .bottle + LDA $3A : AND.b #$80 : STA $3A + LDA $50 : AND.b #$FE : STA $50 + LDA.b #$80 : STA $44 : STA $45 + BRA + + .wolf_shovel + LDA.b $3A : AND.b #$80 : STA.b $3A + LDA.b $50 : AND.b #$FE : STA.b $50 + + + STZ.w $030D ; SWEAT + STZ.w $0300 ; ITEMSTEP + STZ.w $037A ; USEY2 + STZ.w $0301 ; USEY1 + STZ.w $020C ; Stats Screen Cursor Index + INC $0200 +} + +; ========================================================= +; 01 MENU UPLOAD RIGHT + +incsrc "menu_draw.asm" + +Menu_UploadRight: +{ + JSR Menu_DrawBackground + JSR Menu_DrawQuestItems + JSR Menu_DrawCharacterName + JSR Menu_DrawBigKey + JSR Menu_DrawBigChestKey + + JSR Menu_DrawQuestIcons + JSR Menu_DrawTriforceIcons + JSR Menu_DrawPendantIcons + JSR Menu_DrawMagicRings + JSR Menu_DrawPlaytimeLabel + + JSR Menu_DrawHeartPieces + JSR Menu_DrawQuestStatus + JSR Menu_DrawAreaNameTXT + JSR DrawLocationName + + SEP #$30 + LDA.b #$23 : STA.w $0116 + LDA.b #$01 : STA.b $17 + INC.w $0200 + RTS +} + +; ========================================================= +; 02 MENU UPLOAD LEFT + +Menu_UploadLeft: +{ + JSR Menu_DrawBackground + JSR DrawYItems + JSR Menu_DrawSelect + JSR Menu_DrawRingPrompt + JSR Menu_DrawItemName + ; INSERT PALETTE ------- + + REP #$30 + LDX.w #$3E + .loop + LDA.w Menu_Palette, X + STA.l $7EC502, X + DEX : DEX + BPL .loop + SEP #$30 + ;----------------------- + + LDA.b #$22 : STA.w $0116 + LDA.b #$01 : STA.b $17 : STA.b $15 ; added for palette + INC.w $0200 + RTS +} + +; ========================================================= +; 03 MENU SCROLL DOWN + +Menu_Scroll: + dw 0, -3, -5, -7, -10, -12, -15, -20 + dw -28, -40, -50, -60, -75, -90, -100 + dw -125, -150, -175, -190, -200, -210 + dw -220, -225, -230, -232, -234, -238 + +Menu_ScrollDown: +{ + LDA.b #$11 : STA.w $012F + SEP #$10 + REP #$20 + + LDX.w MenuScrollLevelV + INX : INX + LDA.w Menu_Scroll, X + STA.b $EA + CMP.w #$FF12 : BNE .notDoneScrolling + JMP Menu_InitItemScreen + + .notDoneScrolling + STX.w MenuScrollLevelV + RTS +} + +; ========================================================= +; 04 MENU ITEM SCREEN + +incsrc "menu_select_item.asm" + +Menu_CheckForSpecialMenus: +{ + LDA.w $0202 : CMP.b #$05 : BNE + + LDA.b $F6 : BIT.b #$80 : BEQ + + STZ.w $020B + LDA.b #$0C : STA.w $0200 ; Magic Bag + + + LDA.w $0202 : CMP.b #$0D : BNE ++ + LDA.b $F6 : BIT.b #$80 : BEQ ++ + LDA.b #$0D : STA.w $0200 + JSR Menu_DeleteCursor + JSR Menu_DrawSongMenu + SEP #$30 + JMP .exit + ++ + LDA.w $0202 : CMP.b #$0E : BNE ++ + LDA.b $F6 : BIT.b #$80 : BEQ ++ + LDA.b #$0E : STA.w $0200 + JSR Menu_DeleteCursor + JSL Menu_DrawJournal + SEP #$30 + JMP .exit + ++ + + LDA.b $F6 : BIT.b #$40 : BEQ +++ + JSR Menu_DeleteCursor + JSR Menu_DrawRingBox + STZ.w $020B + LDA.b #$09 : STA.w $0200 ; Ring Box + JMP .exit + +++ + .exit + + RTS +} + + +Menu_ItemScreen: +{ + JSR Menu_CheckHScroll + + INC $0207 + LDA.w $0202 : BEQ .do_no_input + ; Scroll through joypad 1 inputs + ASL : TAY : LDA.b $F4 + LSR : BCS .move_right + LSR : BCS .move_left + LSR : BCS .move_down + LSR : BCS .move_up + JSR Menu_CheckForSpecialMenus + .do_no_input + BRA .no_inputs + + .move_right + JSR Menu_DeleteCursor + JSR Menu_FindNextItem + BRA .draw_cursor + + .move_left + JSR Menu_DeleteCursor + JSR Menu_FindPrevItem + BRA .draw_cursor + + .move_down + JSR Menu_DeleteCursor + JSR Menu_FindNextDownItem + BRA .draw_cursor + + .move_up + JSR Menu_DeleteCursor + JSR Menu_FindNextUpItem + BRA .draw_cursor + + .draw_cursor + LDA.b #$20 : STA.w $012F ; cursor move sound effect + + .no_inputs + SEP #$30 + LDA.w $0202 : ASL : TAY + REP #$10 + LDX.w Menu_ItemCursorPositions-2, Y + JSR Menu_DrawCursor + + JSR Menu_DrawItemName + SEP #$20 + .exit + LDA.b #$22 : STA.w $0116 + LDA.b #$01 : STA.b $17 + + RTS +} + +; ========================================================= +; 05 MENU SCROLL TO + +Menu_ScrollTo: +{ + SEP #$20 + JSR Menu_ScrollHorizontal : BCC .not_done + JSR Menu_RefreshQuestScreen + INC.w $0200 + .not_done + RTS +} + +; ========================================================= +; 06 MENU STATS SCREEN + +incsrc "menu_scroll.asm" + +Menu_StatsScreen: +{ + JSR Menu_CheckHScroll + ; JSR Menu_StatsScreen_Input ; Selection disabled per user request + RTS +} + +; ========================================================= +; 07 MENU SCROLL FROM + +Menu_ScrollFrom: +{ + JSR Menu_ScrollHorizontal : BCC .not_done + JSR Menu_RefreshInventoryScreen + JMP Menu_InitItemScreen + .not_done + SEP #$20 ; Restore 8-bit A if scroll not done + RTS +} + +; ========================================================= +; 08 MENU SCROLL UP + +Menu_ScrollUp: +{ + SEP #$10 + REP #$20 + + LDX.w MenuScrollLevelV + LDA.w Menu_Scroll, X + STA.b $EA : BNE .notDoneScrolling + STZ.b $E4 + LDA.w #$000A : STA.w $0200 + RTS + + .notDoneScrolling + DEX : DEX : STX.w MenuScrollLevelV + RTS +} + +; ========================================================= +; CHECK BOTTLE + +Menu_CheckBottle: +{ + LDA.w $0202 : CMP.b #$06 : BNE .not_first + LDA.b #$0001 : JMP .prepare_bottle + .not_first + + LDA.w $0202 : CMP.b #$0C : BNE .not_second + LDA.b #$0002 : JMP .prepare_bottle + .not_second + + LDA.w $0202 : CMP.b #$12 : BNE .not_third + LDA.b #$0003 : JMP .prepare_bottle + .not_third + + LDA.w $0202 : CMP.b #$18 : BNE .not_any + LDA.b #$0004 + .prepare_bottle + STA.l BottleIndex + .not_any + RTS +} + +; ========================================================= +; 0A MENU EXIT + +Menu_Exit: +{ + JSL LinkState_ResetMaskAnimated + JSR Menu_CheckBottle + REP #$20 + + ; reset submodule + STZ $0200 + + ; go back to the submodule we came from + LDA.w $010C : STA.b $10 + + ; Check H-Scroll ($E4) to see if we are on the Quest Screen + ; If $E4 is not 0, we are likely on the Quest Screen (256) + ; In that case, skip item selection. + LDA.b $E4 : BNE .quest_screen_exit + + ; set $0303 by using $0202 to index table on exit + ; set $0304 to prevent item + 1 animation exploits + LDX $0202 + LDA.w Menu_ItemIndex, X : STA $0303 : STA.w $0304 + + .quest_screen_exit + + LDX.b #$3E + .loop + LDA.l $7EC300, X + STA.l $7EC500, X + DEX : DEX + BPL .loop + + INC.b $15 + INC.b $16 + + RTS +} + +; ========================================================= +; REFRESH SCREENS +; ========================================================= + +Menu_RefreshQuestScreen: +{ + JSR Menu_DrawBackground + JSR Menu_DrawQuestItems + JSR Menu_DrawCharacterName + JSR Menu_DrawBigKey + JSR Menu_DrawBigChestKey + + JSR Menu_DrawQuestIcons + JSR Menu_DrawTriforceIcons + JSR Menu_DrawPendantIcons + JSR Menu_DrawMagicRings + JSR Menu_DrawPlaytimeLabel + + JSR Menu_DrawHeartPieces + JSR Menu_DrawQuestStatus + JSR Menu_DrawAreaNameTXT + JSR DrawLocationName + SEP #$30 ; Restore 8-bit mode before return + RTS +} + +Menu_RefreshInventoryScreen: +{ + JSR Menu_DrawBackground + JSR DrawYItems + JSR Menu_DrawSelect + JSR Menu_DrawRingPrompt + JSR Menu_DrawItemName + + ; Palette restore if needed (mimicking Menu_UploadLeft) + REP #$30 + LDX.w #$3E + .loop + LDA.w Menu_Palette, X + STA.l $7EC502, X + DEX : DEX + BPL .loop + SEP #$30 + + RTS +} + +; ========================================================= +; 0B MENU COPY TO RIGHT + +Menu_InitiateScrollDown: +{ + REP #$20 + + ; Clear out the whole buffer. + LDX.b #$FE ; $1700-17FF + + .loop + LDA.w #$387F + STA.w $1000, X : STA.w $1100, X + STA.w $1200, X : STA.w $1300, X + STA.w $1400, X : STA.w $1500, X + STA.w $1600, X : STA.w $1700, X + DEX : DEX : BNE .loop + + ; TODO: The BPL wasn't working so figure out why and + ; fix it instead of doing this abomination. + STA.w $1000 : STA.w $1100 + STA.w $1200 : STA.w $1300 + STA.w $1400 : STA.w $1500 + STA.w $1600 : STA.w $1700 + + SEP #$20 + + JSL RebuildHUD_long + + ; Draw one frame of the clock so it doesn't just + ; pop in when scrolling down. + JSL DrawClockToHudLong + + ; The whole HUD fits on 4 rows so I'm only going to + ; copy 4 here. Also we start 2 in because thats the + ; left we need to go. + + LDX.b #$3A + .loop1 + LDA $7EC702, X : STA $1082, X + DEX : BNE .loop1 + + LDX.b #$3A + .loop2 + LDA $7EC742, X : STA $10C2, X + DEX : BNE .loop2 + + LDX.b #$3A + .loop3 + LDA $7EC782, X : STA $1102, X + DEX : BNE .loop3 + + LDX.b #$3A + .loop4 + LDA $7EC7C2, X : STA $1142, X + DEX : BNE .loop4 + + LDA.b #$24 : STA.w $0116 + LDA.b #$01 : STA.b $17 + LDA.b #$08 : STA.w $0200 + LDA.b #$12 : STA.w $012F ; play menu exit sound effect + + RTS +} + +; ========================================================= +; 0C MENU MAGIC BAG + +Menu_MagicBag: +{ + JSR Menu_DrawMagicBag + JSR Menu_DrawMagicItems + SEP #$30 + + INC $0207 + LDA.b $F4 + LSR : BCS .move_right + LSR : BCS .move_left + LSR : BCS .move_down + LSR : BCS .move_up + BRA .continue + + .move_up + .move_right + REP #$30 + LDA.w $020B : ASL : TAY ; Y = current index * 2 + LDX.w Menu_MagicBagCursorPositions, Y + JSR Menu_DeleteCursor_AltEntry + SEP #$20 ; Back to 8-bit A after JSR + INC.w $020B + LDA.w $020B : CMP.b #$06 : BCC .continue + STZ.w $020B ; Wrap to 0 + BRA .continue + + .move_down + .move_left + REP #$30 + LDA.w $020B : ASL : TAY ; Y = current index * 2 + LDX.w Menu_MagicBagCursorPositions, Y + JSR Menu_DeleteCursor_AltEntry + SEP #$20 ; Back to 8-bit A after JSR + LDA.w $020B : BEQ .continue ; Already at 0, don't decrement + DEC.w $020B + BRA .continue + .zero + STZ.w $020B + .continue + JSR DrawCollectibleNamesAndCount + LDA.w $020B + ASL : TAY + REP #$10 + LDX.w Menu_MagicBagCursorPositions, Y + JSR Menu_DrawCursor + JSR MagicBag_ConsumeItem + JSR Submenu_Return + SEP #$20 ; Ensure 8-bit A mode + + ; Trigger VRAM tilemap upload + LDA.b #$22 : STA.w $0116 + LDA.b #$01 : STA.b $17 + RTS +} + +Menu_MagicBagCursorPositions: + dw menu_offset(8,6) ; banana + dw menu_offset(8,10) ; pineapple + dw menu_offset(8,14) ; goron rock meat + dw menu_offset(12,6) ; seashells + dw menu_offset(12,10) ; honeycombs + dw menu_offset(12,14) ; deku sticks + +MagicBag_ConsumeItem: +{ + ; Check for A button press + LDA.b $F6 : BIT.b #$80 : BEQ .exit + + REP #$30 + ; Calculate SRAM address for current item (4 bytes per entry) + LDA.w $020B : ASL #2 : TAX + LDA.l .sram_addresses, X : STA $00 + LDA.l .sram_addresses+2, X : STA $02 + SEP #$30 + + ; Handle Consumption + PHB : LDA $02 : PHA : PLB + LDA ($00) : BEQ .error_dbr + + ; Call Handler + JSL Link_ConsumeMagicBagItem + BCC .failed_use_dbr + + ; Success -> Decrement + LDA ($00) : DEC A : STA ($00) + PLB + + ; Sound + LDA.b #$35 : STA.w $012F + BRA .exit + +.failed_use_dbr +.error_dbr + PLB ; Restore data bank (was pushed at line 597) + ; Error Sound + LDA.b #$3C : STA.w $012E + BRA .exit + +.exit + RTS + +.sram_addresses + dd Bananas + dd Pineapples + dd RockMeat + dd Seashells + dd Honeycomb + dd DekuSticks +} + +; ========================================================= +; 0D MENU SONG MENU + +Menu_SongMenu: +{ + REP #$30 + JSR Menu_DrawMusicNotes + + INC $0207 + LDA.w CurrentSong : BEQ + + ASL : TAY + LDA.b $F4 + LSR : BCS .move_right + LSR : BCS .move_left + LSR : BCS .move_down + LSR : BCS .move_up + + + JMP .continue + + .move_right + .move_up + REP #$30 + LDX.w Menu_SongIconCursorPositions-2, Y + JSR Menu_DeleteCursor_AltEntry + LDA.w CurrentSong : CMP.b #$04 : BEQ .reset + INC.w CurrentSong + LDA.w CurrentSong + PHA + LDA $7EF34C : CMP.b #$01 : BEQ .max_1 + CMP.b #$02 : BEQ .max_2 + CMP.b #$03 : BEQ .max_3 + PLA + CMP.b #$05 : BCS .wrap_to_min + JMP .continue + .max_1 + PLA : CMP.b #$02 : BCS .wrap_to_min + .max_2 + PLA : CMP.b #$03 : BCS .wrap_to_min + JMP .continue + .max_3 + PLA : CMP.b #$04 : BCS .wrap_to_min + JMP .continue + .wrap_to_max + LDA $7EF34C : CMP.b #$01 : BEQ .wrap_to_min + CMP.b #$02 : BEQ .set_max_to_2 + CMP.b #$03 : BEQ .set_max_to_3 + LDA #$04 : STA.w CurrentSong : JMP .continue + + .set_max_to_3 + LDA #$03 : STA.w CurrentSong : JMP .continue + + .set_max_to_2 + LDA #$02 : STA.w CurrentSong : JMP .continue + + .wrap_to_min + LDA #$01 : STA.w CurrentSong + BRA .continue + + .move_left + .move_down + REP #$30 + LDX.w Menu_SongIconCursorPositions-2, Y + JSR Menu_DeleteCursor_AltEntry + LDA.w CurrentSong : CMP.b #$01 : BEQ .reset + DEC.w CurrentSong + LDA.w CurrentSong + CMP #$00 : BEQ .wrap_to_max + BRA .continue + .reset + LDA #$01 : STA.w CurrentSong + + .continue + + JSR Menu_DrawItemName + SEP #$30 + LDA.w CurrentSong : ASL : TAY + REP #$10 + LDX.w Menu_SongIconCursorPositions-2, Y + JSR Menu_DrawCursor + JSR Submenu_Return + SEP #$20 + + LDA.b #$22 : STA.w $0116 + LDA.b #$01 : STA.b $17 + + RTS +} + +Menu_SongIconCursorPositions: + dw menu_offset(8,4) + dw menu_offset(8,8) + dw menu_offset(8,12) + dw menu_offset(8,16) + +; ========================================================= +; 09 MENU RING BOX + +Menu_RingBox: +{ + JSR Menu_DrawRingBox + JSR Menu_DrawMagicRingsInBox + INC $0207 + + LDA.b $F4 + LSR : BCS .move_right + LSR : BCS .move_left + LSR : BCS .move_down + LSR : BCS .move_up + BRA .continue + + .move_up + .move_right + REP #$30 + LDX.w Menu_RingIconCursorPositions-2, Y + JSR Menu_DeleteCursor_AltEntry + INC.w $020B + LDA.w $020B : CMP.b #$06 : BCS .zero + BRA .continue + .move_left + .move_down + REP #$30 + LDX.w Menu_RingIconCursorPositions-2, Y + JSR Menu_DeleteCursor_AltEntry + LDA.w $020B : CMP.b #$00 : BEQ .continue + DEC.w $020B + BRA .continue + .zero + STZ.w $020B + .continue + + JSR DrawMagicRingNames + LDA.w $020B : ASL : TAY + REP #$10 + LDX.w Menu_RingIconCursorPositions, Y + JSR Menu_DrawCursor + JSR RingMenu_Controls + SEP #$20 + + LDA.b #$22 : STA.w $0116 + LDA.b #$01 : STA.b $17 + + RTS +} + +Menu_RingIconCursorPositions: + dw menu_offset(8,6) + dw menu_offset(8,10) + dw menu_offset(8,14) + dw menu_offset(12,6) + dw menu_offset(12,10) + dw menu_offset(12,14) + +RingMenu_StoreRingToSlotStack: +{ + ; TODO: Check how many ring slots we currently have + + ; Check if the ring is already in a slot + STA.b $00 + LDA.b $00 : CMP.l RingSlot1 : BEQ .return + LDA.b $00 : CMP.l RingSlot2 : BEQ .return + LDA.b $00 : CMP.l RingSlot3 : BEQ .return + PHA + ; Check the SRAM for an available ring slot + ; If none is available we shift the stack + ; $7EF38C-7EF38E (Size 03) + + LDA.l RingSlot1 : BEQ .slot1_available + LDA.l RingSlot2 : BEQ .slot2_available + LDA.l RingSlot3 : BEQ .slot3_available + + ; Shift the stack + LDA.l RingSlot2 : STA.l RingSlot1 + LDA.l RingSlot3 : STA.l RingSlot2 + .slot3_available + PLA : STA.l RingSlot3 + .return + RTS + + .slot1_available + PLA : STA.l RingSlot1 + RTS + .slot2_available + PLA : STA.l RingSlot2 + RTS +} + +RingMenu_Controls: +{ + ; Load the current ring selected (0-5) into A + REP #$30 + LDA.w $020B + AND.w #$00FF + SEP #$30 + ; Set the current ring to the cursor position + TAY ; Transfer A to Y for indexing + LDA.b $F6 : BIT.b #$80 : BEQ + ; Check if the confirm button is pressed + LDA .rings, Y ; Load the ring bitmask + AND.l MAGICRINGS ; Check if the ring is owned + BEQ + ; If not, skip setting the ring + INY #2 + TYA ; Transfer Y to A + JSR RingMenu_StoreRingToSlotStack + + + + ; Return to item menu if player presses X + LDA.b $F6 : BIT.b #$40 : BEQ + + LDA.b #$0F : STA.w $0200 + + + + ; Close the menu if the player presses start + LDA.b $F4 : BIT.b #$10 : BEQ + + LDA.b #$08 : STA.w $0200 + + + RTS + + .rings + db $20, $10, $08, $04, $02, $01 +} + +Menu_Journal: +{ + JSL Journal_Handler + + JSR Submenu_Return + + LDA.b #$22 : STA.w $0116 + LDA.b #$01 : STA.b $17 + RTS +} + +Menu_SubmenuReturn: +{ + STZ.w $0116 ; Clear VRAM flag to prevent partial upload + JSR Menu_RefreshInventoryScreen + LDA.b #$22 : STA.w $0116 + LDA.b #$01 : STA.b $17 : STA.b $15 + LDA.b #$04 : STA.w $0200 ; Set state to Item Screen + RTS +} + +Submenu_Return: +{ + ; Return to the item menu if they press A + LDA.b $F6 : BIT.b #$80 : BEQ + + LDA.b #$0F : STA.w $0200 + + + + ; Close the menu if the player presses start + LDA.b $F4 : BIT.b #$10 : BEQ + + LDA.b #$08 : STA.w $0200 + + + RTS +} + +menu_frame: incbin "tilemaps/menu_frame.tilemap" +quest_icons: incbin "tilemaps/quest_icons.tilemap" +incsrc "menu_map_names.asm" +%log_end("Menu/menu.asm", !LOG_MENU) +incsrc "menu_hud.asm" +%log_end("Menu/menu_hud.asm", !LOG_MENU) +incsrc "menu_journal.asm" +%log_end("Menu/menu_journal.asm", !LOG_MENU) \ No newline at end of file diff --git a/Menu/menu_gfx_table.asm b/Menu/menu_gfx_table.asm index 884b579..982691b 100644 --- a/Menu/menu_gfx_table.asm +++ b/Menu/menu_gfx_table.asm @@ -210,3 +210,7 @@ AreaNameTXT: dw $255C, $2554, $241C, $2430 dw $2430, $2430, $2430, $2430 dw $2430, $2430, $2430, $2430 + +RingPromptTXT: + dw $2567, $256B, $2417, $2561 + dw $2558, $255D, $2556, $2562 diff --git a/Menu/menu_journal.asm b/Menu/menu_journal.asm index 329e7e4..c815068 100644 --- a/Menu/menu_journal.asm +++ b/Menu/menu_journal.asm @@ -1,8 +1,4 @@ ; Book of Secrets Journal Menu -; Journal States -JOURNAL_STATE_FIRST_PAGE = $0000 -JOURNAL_STATE_MIDDLE_PAGE = $0001 -JOURNAL_STATE_LAST_PAGE = $0002 ; --------------------------------------------------------- ; Journal Handler @@ -16,7 +12,6 @@ Journal_Handler: REP #$30 JSR Journal_PrevPage JSL Menu_DrawJournal - JSR Journal_DrawEntry BRA .draw_page .check_right @@ -25,7 +20,6 @@ Journal_Handler: REP #$30 JSR Journal_NextPage JSL Menu_DrawJournal - JSR Journal_DrawEntry .draw_page SEP #$30 PLB @@ -39,14 +33,15 @@ Journal_Handler: Journal_PrevPage: { LDA.l JournalState - AND.w #$00FF : CMP.w #JOURNAL_STATE_FIRST_PAGE - BEQ .wrap_to_last + AND.w #$00FF : BEQ .wrap_to_last DEC A STA.l JournalState RTS .wrap_to_last - LDA.w #JOURNAL_STATE_LAST_PAGE + ; Find total count to wrap to last + JSR Journal_CountUnlocked + DEC A STA.l JournalState RTS } @@ -54,18 +49,115 @@ Journal_PrevPage: Journal_NextPage: { LDA.l JournalState - AND.w #$00FF : CMP.w #JOURNAL_STATE_LAST_PAGE - BEQ .wrap_to_first - INC A + AND.w #$00FF : INC A : STA.b $00 + + ; Check if next page exists + LDA.b $00 + JSR Journal_GetNthEntry + CPX.w #$0000 : BEQ .wrap_to_first + LDA.b $00 STA.l JournalState RTS .wrap_to_first - LDA.w #JOURNAL_STATE_FIRST_PAGE + LDA.w #$0000 STA.l JournalState RTS } +; --------------------------------------------------------- +; Entry Logic +; --------------------------------------------------------- + +; Input: A = Index (N) +; Output: X = Text Pointer (or 0 if not found) +Journal_GetNthEntry: +{ + PHA + LDY.w #$0000 ; Master List Index + + .loop + ; Check if we reached end of list + LDA.w Journal_MasterList, Y : BEQ .end_of_list + + ; Check Flag + ; Format: dd dd dd mm (Address Long, Mask) + ; But we can't indirect long easily without setup. + ; Let's read address to $00. + + LDA.w Journal_MasterList, Y : STA.b $02 + LDA.w Journal_MasterList+2, Y : STA.b $04 ; Get mask in low byte of $04 + + SEP #$20 + ; $04 = Bank, $05 = Mask (from 16-bit read above) + + PHB + LDA.b $04 : PHA : PLB ; Set DB to address bank + LDA.b ($02) ; Load flag value at address + PLB ; Restore original data bank + + AND.w Journal_MasterList+3, Y ; Apply mask (A is 8-bit, addr is 16-bit) + ; Wait, 16-bit read of +2 gets Bank and Mask. + ; $02-$03 = Addr Low + ; $04 = Bank + ; $05 = Mask + ; The AND above reads from ROM directly. + + BEQ .locked + ; Unlocked + PLA : DEC A : PHA ; Decrement target index + BMI .found + + .locked + REP #$20 + TYA : CLC : ADC.w #$0006 : TAY ; Next Entry (4 bytes header + 2 bytes ptr = 6) + BRA .loop + + .found + REP #$20 + PLA ; Clean stack + LDA.w Journal_MasterList+4, Y : TAX + RTS + + .end_of_list + REP #$20 + PLA ; Clean stack + LDX.w #$0000 + RTS +} + +Journal_CountUnlocked: +{ + LDY.w #$0000 ; Master List Index + LDA.w #$0000 : STA.b $06 ; Counter + + .loop + LDA.w Journal_MasterList, Y : BEQ .done + + ; Check Flag + LDA.w Journal_MasterList, Y : STA.b $02 + LDA.w Journal_MasterList+2, Y : STA.b $04 + + SEP #$20 + PHB ; Save current data bank + LDA.b $04 : PHA : PLB ; Set DB to address bank + LDA.b ($02) ; Load flag value + PLB ; Restore original data bank + AND.w Journal_MasterList+3, Y ; Apply mask (A is 8-bit, addr is 16-bit) + BEQ .locked + REP #$20 + INC.b $06 + + .locked + REP #$20 + TYA : CLC : ADC.w #$0006 : TAY + BRA .loop + + .done + LDA.b $06 + RTS +} + ; --------------------------------------------------------- ; Entry Drawing ; --------------------------------------------------------- @@ -73,47 +165,51 @@ Journal_NextPage: Journal_DrawEntry: { REP #$30 - ; Calculate pointer to the text based on JournalState (Page #) - ; Entry = JournalEntries[JournalState] - LDA.l JournalState : AND.w #$00FF : ASL : TAX - LDA.w JournalEntries, X : STA.b $00 ; Store pointer in $00 (Direct Page) + LDA.l JournalState : AND.w #$00FF + JSR Journal_GetNthEntry + STX.b $00 ; Store Text Pointer + + CPX.w #$0000 : BNE .valid + ; Draw "Empty" if no entry found (shouldn't happen with correct logic) + RTS + .valid LDX.w #$0000 ; Text Offset LDY.w #$0000 ; VRAM Offset .loop - ; Read from Indirect Address ($00) + Y (offset) - ; We need to be careful with addressing. - ; $00 is 16-bit pointer. We need to read from Bank 2D (current bank). - ; LDA ($00), Y works if Y is index. - ; But our X is the text offset index, Y is VRAM index. - ; Let's swap registers. - PHY ; Save VRAM offset TXY ; Y = Text Offset - LDA ($00), Y ; Read word from text table + LDA ($00), Y ; Read word from text PLY ; Restore VRAM offset - STA.w $1292, Y ; Write to VRAM buffer + CMP.w #$FFFF : BEQ .done ; Check for terminator + + STA.w $1292, Y ; Write to VRAM buffer (Row 1) INY #2 ; Next VRAM word INX #2 ; Next Text word - CPY.w #$0060 ; Copy 3 lines (32 bytes * 3 approx? No, original was $1F bytes -> 16 chars/1 line) - ; Original loop: CPY #$001F. That's 32 bytes (16 chars). - ; The BookEntries had 3 lines defined but the loop only did 1 line? - ; Original: - ; .loop - ; LDA.w BookEntries, X : STA.w $1292, Y - ; INY #2 : INX #2 - ; CPY.w #$001F : BCC .loop - ; Yes, it only copied the first line ($00 to $1E). - ; We should probably copy more lines. - ; Let's copy 6 lines ($60 bytes? No, $1F is 31. So 16 chars * 2 bytes = 32 bytes = $20) - ; Let's copy 3 lines = $60 bytes. - - CPY.w #$0060 : BCC .loop - + ; Wrap logic for multiple lines + ; Line 1 ends at $1292 + $20 (32 bytes) = $12B2? + ; Let's just assume the text includes padding or we handle newlines? + ; Simplified: The text data is pre-formatted to 16 chars per line. + ; We just copy linear data to linear VRAM. + ; But VRAM is linear in rows? Yes, usually. + ; However, to jump to next line in tilemap we need to add stride. + ; Row Width = $40 bytes (32 tiles * 2 bytes). + ; If we write 16 chars (32 bytes), we need to skip 32 bytes to reach next line. + + CPY.w #$0020 : BNE .check_line_2 + TYA : CLC : ADC.w #$0020 : TAY ; Skip to next line start + .check_line_2 + CPY.w #$0060 : BNE .check_line_3 ; End of Line 2 ($20 + $40 = $60) + TYA : CLC : ADC.w #$0020 : TAY + .check_line_3 + + BRA .loop + + .done SEP #$30 RTS } @@ -122,25 +218,30 @@ Journal_DrawEntry: ; Data Tables ; --------------------------------------------------------- -JournalEntries: - dw Entry_Page1 - dw Entry_Page2 - dw Entry_Page3 +; Format: Address(3), Mask(1), TextPtr(2) = 6 bytes +Journal_MasterList: + dl $7EF3D6 : db $02 : dw Entry_QuestStart ; OOSPROG bit 1 (Quest Start) + dl $7EF3D6 : db $10 : dw Entry_MetElder ; OOSPROG bit 4 (Met Elder) + dl $7EF3C6 : db $04 : dw Entry_MakuTree ; OOSPROG2 bit 2 (Maku Tree) + dw $0000 ; Terminator -Entry_Page1: - dw "QUEST_LOG:_I____" - dw "Must_find_the___" +Entry_QuestStart: + dw "Quest_Started___" + dw "Find_the_3_gems_" + dw "to_save_Hyrule__" + dw $FFFF + +Entry_MetElder: + dw "Spoke_to_Elder__" + dw "He_mentioned_a__" dw "missing_girl____" + dw $FFFF -Entry_Page2: - dw "QUEST_LOG:_II___" - dw "The_Mushroom_is_" - dw "key_to_the_woods" - -Entry_Page3: - dw "QUEST_LOG:_III__" - dw "Zora_River_flows" - dw "from_the_north__" +Entry_MakuTree: + dw "Met_Maku_Tree___" + dw "He_needs_his____" + dw "memory_back_____" + dw $FFFF ; --------------------------------------------------------- ; Background Drawing @@ -149,17 +250,44 @@ Entry_Page3: Menu_DrawJournal: { PHB : PHK : PLB - LDA.l JournalState - ASL : TAX - JSR (.page_drawers, X) + + ; Logic to choose background based on page number? + ; For now just cycle them 1-2-3-1-2-3 + LDA.l JournalState : AND.w #$00FF + CLC : ADC.b #$01 ; Make 1-based? + ; Modulo 3? + ; Simple: + ; 0 -> First + ; Last -> Last + ; Else -> Middle + + ; But we don't know which is last without counting. + ; Let's just use First for 0, Last for Last, Middle for others. + + LDA.l JournalState : AND.w #$00FF : BEQ .first + + PHA + JSR Journal_CountUnlocked : DEC A : STA.b $02 + PLA + CMP.b $02 : BEQ .last + + BRA .middle + + .first + JSR Journal_DrawFirstPage + BRA .exit + .last + JSR Journal_DrawLastPage + BRA .exit + .middle + JSR Journal_DrawMiddlePage + .exit + + JSR Journal_DrawEntry + SEP #$30 PLB RTL - - .page_drawers - dw Journal_DrawFirstPage - dw Journal_DrawMiddlePage - dw Journal_DrawLastPage } Journal_DrawFirstPage: diff --git a/Menu/menu_text.asm b/Menu/menu_text.asm index 9a14f7f..9d57e5e 100644 --- a/Menu/menu_text.asm +++ b/Menu/menu_text.asm @@ -119,7 +119,7 @@ Menu_ItemNames: dw "MIRROR_OF_TIME " dw "____BOTTLE____ " dw "___OCARINA____ " - dw "_SECRET_TOME__ " + dw "TOME__L:REVEAL__" dw "___SOMARIA____ " dw "_FISHING_ROD__ " dw "_ROCS_FEATHER_ " @@ -423,7 +423,7 @@ Menu_DrawSelect: .loop LDA.w SelectItemTXT, X : STA.w $1194, X - DEX #2 : BPL .loop + DEX : DEX : BPL .loop RTS } @@ -437,7 +437,7 @@ Menu_DrawQuestStatus: .loop LDA.w QuestStatusTXT, X : STA.w $1194, X - DEX #2 : BPL .loop + DEX : DEX : BPL .loop RTS } @@ -528,3 +528,16 @@ Menu_DrawCharacterName: LDA.w #$1D : BRA .write_to_screen } + +Menu_DrawRingPrompt: +{ + REP #$30 + LDX.w #$0E + + .loop + LDA.w RingPromptTXT, X : STA.w $1254, X + DEX : DEX : BPL .loop + + SEP #$30 ; Restore 8-bit mode before return + RTS +}