diff --git a/code/oot.ld b/code/oot.ld index 22438c7b..f04597d8 100644 --- a/code/oot.ld +++ b/code/oot.ld @@ -844,6 +844,10 @@ SECTIONS *(.patch_ActorDraw) } + .patch_OcarinaNoteSound_Player 0x2D6A04 : { + *(.patch_OcarinaNoteSound_Player) + } + .patch_CamUpdate 0x2D84C8 : { *(.patch_CamUpdate) } @@ -1734,6 +1738,10 @@ SECTIONS *(.patch_EnableFW) } + .patch_OcarinaNoteSound_Npc 0x477C08 + region_offset : { + *(.patch_OcarinaNoteSound_Npc) + } + .patch_StoreTargetActorType 0x479984 + region_offset : { *(.patch_StoreTargetActorType) } diff --git a/code/src/hooks.s b/code/src/hooks.s index e953f54a..3b960805 100644 --- a/code/src/hooks.s +++ b/code/src/hooks.s @@ -2467,3 +2467,23 @@ hook_DrawHeartIcon: cmp r0,#0x0 pop {r0-r12, lr} bx lr + +.global hook_OcarinaNoteSound_Player +hook_OcarinaNoteSound_Player: + push {r0,r2,r3,lr} + bl 0x2CFE00 @ original instruction, sets vibrato + mov r0,#0x0 @ default ocarina instrument + bl OcarinaNotes_OverrideInstrument + cpy r1,r0 + pop {r0,r2,r3,lr} + b 0x2CFD24 @ set instrument + +.global hook_OcarinaNoteSound_Npc +hook_OcarinaNoteSound_Npc: + and r1,r0,#0xFF @ instrument + push {r0, r2-r12, lr} + cpy r0,r1 + bl OcarinaNotes_OverrideInstrument + cpy r1,r0 + pop {r0, r2-r12, lr} + bx lr diff --git a/code/src/ocarina_notes.c b/code/src/ocarina_notes.c index eb762c2b..9cf92fae 100644 --- a/code/src/ocarina_notes.c +++ b/code/src/ocarina_notes.c @@ -1,6 +1,7 @@ #include "ocarina_notes.h" #include "savefile.h" #include "settings.h" +#include "common.h" s32 OcarinaNotes_IsButtonOwned(OcarinaNoteButton button) { return (gSettingsContext.shuffleOcarinaButtons == OFF) || @@ -81,3 +82,13 @@ u32 OcarinaNotes_HandleInputs(u32 ocarinaInputs) { ocarinaInputs &= ownedBtnsMask; return ocarinaInputs; } + +s32 OcarinaNotes_OverrideInstrument(u32 instrument) { + if (instrument != OCARINA_INSTRUMENT_DEFAULT) { + return instrument; + } + if (gSettingsContext.ocarinaNoteInstrument == OCARINA_INSTR_SETTING_SCENE_SPECIFIC) { + return Hash(gGlobalContext->sceneNum) % OCARINA_INSTRUMENT_MAX; + } + return gSettingsContext.ocarinaNoteInstrument - OCARINA_INSTR_SETTING_DEFAULT; +} diff --git a/code/src/ocarina_notes.h b/code/src/ocarina_notes.h index ebb20873..fbf8f2ed 100644 --- a/code/src/ocarina_notes.h +++ b/code/src/ocarina_notes.h @@ -4,6 +4,17 @@ #include "z3D/z3D.h" #include "input.h" +// These values are one less than in OoT decomp +typedef enum OcarinaInstrumentId { + OCARINA_INSTRUMENT_DEFAULT, + OCARINA_INSTRUMENT_MALON, + OCARINA_INSTRUMENT_WHISTLE, // Impa + OCARINA_INSTRUMENT_HARP, // Sheik + OCARINA_INSTRUMENT_GRIND_ORGAN, // Windmill Man + OCARINA_INSTRUMENT_FLUTE, // Skull Kid + OCARINA_INSTRUMENT_MAX, +} OcarinaInstrumentId; + typedef enum OcarinaNoteButton { OCARINA_BUTTON_L, OCARINA_BUTTON_R, diff --git a/code/src/patches.s b/code/src/patches.s index 2d100e3c..e0fb6119 100644 --- a/code/src/patches.s +++ b/code/src/patches.s @@ -2536,3 +2536,13 @@ AfterInvalidatingRoomObjects_patch: .global DrawHeartIcon_patch DrawHeartIcon_patch: bl hook_DrawHeartIcon + +.section .patch_OcarinaNoteSound_Player +.global OcarinaNoteSound_Player_patch +OcarinaNoteSound_Player_patch: + b hook_OcarinaNoteSound_Player + +.section .patch_OcarinaNoteSound_Npc +.global OcarinaNoteSound_Npc_patch +OcarinaNoteSound_Npc_patch: + bl hook_OcarinaNoteSound_Npc diff --git a/code/src/settings.h b/code/src/settings.h index 67dfee1b..6ff8881f 100644 --- a/code/src/settings.h +++ b/code/src/settings.h @@ -447,6 +447,12 @@ typedef enum { SHUFFLESFX_CHAOS, } ShuffleSFXSetting; +typedef enum { + OCARINA_INSTR_SETTING_RANDOM_CHOICE, + OCARINA_INSTR_SETTING_SCENE_SPECIFIC, + OCARINA_INSTR_SETTING_DEFAULT, +} OcarinaNoteInstrumentSetting; + typedef enum { DUNGEON_NEITHER, DUNGEON_BARREN, @@ -699,6 +705,8 @@ typedef struct { u8 shuffleSFXLinkVoice; u8 shuffleSFXCategorically; + u8 ocarinaNoteInstrument; + union { u8 dungeonModes[12]; struct { diff --git a/source/descriptions.cpp b/source/descriptions.cpp index de19370e..e0dae846 100644 --- a/source/descriptions.cpp +++ b/source/descriptions.cpp @@ -1321,6 +1321,13 @@ string_view shuffleSFXCategorically = "Sound effects will be shuffled in categ "\n" // "The sound may get annoying fast when disabled."; // /*------------------------------ // +| OCARINA INSTRUMENT | // +------------------------------*/ // +string_view ocarinaInstrDesc = "Change the instrument used when playing the\n" // + "ocarina."; // +string_view ocarinaInstrRandomDesc = "A random instrument from the list will be chosen."; +string_view ocarinaInstrSceneDesc = "The instrument will be different in each scene."; // +/*------------------------------ // | RANDOM TRAP DAMAGE TYPE | // ------------------------------*/ // string_view randomTrapDmgDesc = "All traps will be the base game ice trap"; // diff --git a/source/descriptions.hpp b/source/descriptions.hpp index 42f98567..989c1563 100644 --- a/source/descriptions.hpp +++ b/source/descriptions.hpp @@ -417,6 +417,10 @@ extern string_view shuffleSFXSceneSpecific; extern string_view shuffleSFXChaos; extern string_view shuffleSFXCategorically; +extern string_view ocarinaInstrRandomDesc; +extern string_view ocarinaInstrSceneDesc; +extern string_view ocarinaInstrDesc; + extern string_view randomTrapDmgDesc; extern string_view basicTrapDmgDesc; extern string_view advancedTrapDmgDesc; diff --git a/source/settings.cpp b/source/settings.cpp index 39ded1ff..c809e308 100644 --- a/source/settings.cpp +++ b/source/settings.cpp @@ -1331,6 +1331,10 @@ Option ShuffleSFXFootsteps = Option::Bool(2, "Include Footsteps", {"No", Option ShuffleSFXLinkVoice = Option::Bool(2, "Include Link's Voice", {"No", "Yes"}, {""}, OptionCategory::Cosmetic, ON); Option ShuffleSFXCategorically = Option::Bool(2, "Categorical Shuffle", {"Off", "On"}, {shuffleSFXCategorically}, OptionCategory::Cosmetic, ON); +Option OcarinaNoteInstrument = Option::U8 ("Ocarina Instrument", {"Random Choice", "Scene Specific", + "Default", "Malon", "Whistle", "Harp", + "Grind Organ", "Flute"}, {ocarinaInstrRandomDesc, ocarinaInstrSceneDesc, ocarinaInstrDesc}, OptionCategory::Cosmetic, OCARINA_INSTR_SETTING_DEFAULT); + std::vector audioOptions = { &ShuffleMusic, &ShuffleBGM, @@ -1341,6 +1345,7 @@ std::vector audioOptions = { &ShuffleSFXFootsteps, &ShuffleSFXLinkVoice, &ShuffleSFXCategorically, + &OcarinaNoteInstrument, }; Menu preferences = Menu::SubMenu("Misc Preferences", &preferenceOptions); @@ -1652,6 +1657,7 @@ SettingsContext FillContext() { ctx.shuffleSFXFootsteps = (ShuffleSFXFootsteps) ? 1 : 0; ctx.shuffleSFXLinkVoice = (ShuffleSFXLinkVoice) ? 1 : 0; ctx.shuffleSFXCategorically = (ShuffleSFXCategorically) ? 1 : 0; + ctx.ocarinaNoteInstrument = OcarinaNoteInstrument.Value(); ctx.linksPocketRewardBitMask = LinksPocketRewardBitMask; @@ -3238,6 +3244,11 @@ void UpdateSettings() { if (ShuffleSFX.IsNot(SHUFFLESFX_OFF)) { SFX::ShuffleSequences(ShuffleSFXCategorically.Value()); } + + if (OcarinaNoteInstrument.Is(OCARINA_INSTR_SETTING_RANDOM_CHOICE)) { + size_t randomIndex = Random(OCARINA_INSTR_SETTING_DEFAULT, OcarinaNoteInstrument.GetOptionCount(), true); + OcarinaNoteInstrument.SetSelectedIndex(randomIndex); + } } // If this is an option menu, return the options diff --git a/source/settings.hpp b/source/settings.hpp index cf2d7797..89478e2d 100644 --- a/source/settings.hpp +++ b/source/settings.hpp @@ -825,6 +825,8 @@ extern Option ShuffleSFXFootsteps; extern Option ShuffleSFXLinkVoice; extern Option ShuffleSFXCategorically; +extern Option OcarinaNoteInstrument; + extern u32 LinksPocketRewardBitMask; extern std::array rDungeonRewardOverrides;