From 6785d543b60a25fcd621b837a73faf3e384dc3be Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 5 May 2026 17:39:20 +0200 Subject: [PATCH 1/4] Implement RBA/BA to padding bytes --- soh/include/z64save.h | 1 + .../Restorations/BottleAdventure.cpp | 56 +++++++++++++++++-- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 35f30c26398..7bc91275c86 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -231,6 +231,7 @@ typedef struct ShipSaveContextData { ShipQuestSaveContextData quest; u8 maskMemory; u8 filenameLanguage; + u8 rbaPaddingBytes[4]; //TODO: Move non-rando specific flags to a new sohInf and move the remaining randomizerInf to ShipRandomizerSaveContextData u16 randomizerInf[(RAND_INF_MAX + 15) / 16]; } ShipSaveContextData; diff --git a/soh/soh/Enhancements/Restorations/BottleAdventure.cpp b/soh/soh/Enhancements/Restorations/BottleAdventure.cpp index 22cc74e6799..d21940595a4 100644 --- a/soh/soh/Enhancements/Restorations/BottleAdventure.cpp +++ b/soh/soh/Enhancements/Restorations/BottleAdventure.cpp @@ -382,12 +382,56 @@ void HandleRBASceneFlags(uint8_t itemToPutInBottle) { // padding bytes void HandleBAPaddingBytes() { - // Reading from padding bytes is not implemented - gSaveContext.equips.buttonItems[0] = 0; + u8 itemOnCRight = gSaveContext.equips.buttonItems[3]; + u8 index; + switch (itemOnCRight) { + case ITEM_MASK_GERUDO: + index = 0; + break; + case ITEM_MASK_TRUTH: + index = 1; + break; + case ITEM_SONG_NOCTURNE: + index = 2; + break; + case ITEM_SONG_PRELUDE: + index = 3; + break; + default: + SPDLOG_WARN("[HandleRBAPaddingBytes] Invalid itemOnCRight (%d)", itemOnCRight); + assert(false); + return; + } + + assert(index >= 0 && index <= 3); + + gSaveContext.equips.buttonItems[0] = gSaveContext.ship.rbaPaddingBytes[index]; } -void HandleRBAPaddingBytes() { - // Writing to padding bytes is not implemented +void HandleRBAPaddingBytes(uint8_t itemToPutInBottle) { + u8 index; + switch (itemToPutInBottle) { + case ITEM_MASK_GERUDO: + index = 0; + break; + case ITEM_MASK_TRUTH: + index = 1; + break; + case ITEM_SONG_NOCTURNE: + index = 2; + break; + case ITEM_SONG_PRELUDE: + index = 3; + break; + default: + SPDLOG_WARN("[HandleRBAPaddingBytes] Invalid itemToPutInBottle (%d)", itemToPutInBottle); + assert(false); + return; + } + + assert(index >= 0 && index <= 3); + + gSaveContext.ship.rbaPaddingBytes[index] = itemToPutInBottle; } // Bottle Adventure @@ -432,7 +476,7 @@ void DoRBA(uint8_t itemToPutInBottle) { } else if (itemOnCRight == ITEM_MASK_GORON || itemOnCRight == ITEM_MASK_ZORA) { HandleRBAInventoryEquipment(itemToPutInBottle); } else if (itemOnCRight == ITEM_MASK_GERUDO || itemOnCRight == ITEM_MASK_TRUTH) { - HandleRBAPaddingBytes(); + HandleRBAPaddingBytes(itemToPutInBottle); } else if (itemOnCRight >= ITEM_SOLD_OUT && itemOnCRight <= ITEM_COJIRO) { HandleRBAInventoryUpgrades(itemToPutInBottle); } else if (itemOnCRight >= ITEM_ODD_MUSHROOM && itemOnCRight <= ITEM_SWORD_BROKEN) { @@ -446,7 +490,7 @@ void DoRBA(uint8_t itemToPutInBottle) { } else if (itemOnCRight == ITEM_SONG_SERENADE || itemOnCRight == ITEM_SONG_REQUIEM) { HandleRBAInventoryGSTokens(itemToPutInBottle); } else if (itemOnCRight == ITEM_SONG_NOCTURNE || itemOnCRight == ITEM_SONG_PRELUDE) { - HandleRBAPaddingBytes(); + HandleRBAPaddingBytes(itemToPutInBottle); } else if (itemOnCRight >= ITEM_SONG_LULLABY) { HandleRBASceneFlags(itemToPutInBottle); } From 9013e5987032bb3ac47725eab2152249d87bdd6e Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 5 May 2026 17:47:34 +0200 Subject: [PATCH 2/4] Limit RBA to padding & ammo (except beans) in rando --- .../Restorations/BottleAdventure.cpp | 50 ++++++++++++++----- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/Restorations/BottleAdventure.cpp b/soh/soh/Enhancements/Restorations/BottleAdventure.cpp index d21940595a4..12efa89e171 100644 --- a/soh/soh/Enhancements/Restorations/BottleAdventure.cpp +++ b/soh/soh/Enhancements/Restorations/BottleAdventure.cpp @@ -398,7 +398,7 @@ void HandleBAPaddingBytes() { index = 3; break; default: - SPDLOG_WARN("[HandleRBAPaddingBytes] Invalid itemOnCRight (%d)", itemOnCRight); + SPDLOG_WARN("[HandleRBAPaddingBytes] Invalid itemOnCRight ({})", itemOnCRight); assert(false); return; } @@ -424,7 +424,7 @@ void HandleRBAPaddingBytes(uint8_t itemToPutInBottle) { index = 3; break; default: - SPDLOG_WARN("[HandleRBAPaddingBytes] Invalid itemToPutInBottle (%d)", itemToPutInBottle); + SPDLOG_WARN("[HandleRBAPaddingBytes] Invalid itemToPutInBottle ({})", itemToPutInBottle); assert(false); return; } @@ -462,6 +462,9 @@ void DoBA() { HandleBAPaddingBytes(); } else if (itemOnCRight >= ITEM_SONG_LULLABY) { HandleBASceneFlags(); + } else { + SPDLOG_WARN("[DoBA] Invalid itemOnCRight ({})", itemOnCRight); + assert(false); } } @@ -470,29 +473,52 @@ void DoRBA(uint8_t itemToPutInBottle) { auto itemOnCRight = gSaveContext.equips.buttonItems[3]; if (itemOnCRight >= ITEM_STICK && itemOnCRight <= ITEM_POTION_BLUE) { - HandleRBAInventoryItems(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryItems(itemToPutInBottle); + } } else if (itemOnCRight >= ITEM_FAIRY && itemOnCRight <= ITEM_MASK_BUNNY) { - HandleRBAInventoryAmmo(itemToPutInBottle); + if (!IS_RANDO || itemOnCRight != ITEM_BEAN) { + HandleRBAInventoryAmmo(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_MASK_GORON || itemOnCRight == ITEM_MASK_ZORA) { - HandleRBAInventoryEquipment(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryEquipment(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_MASK_GERUDO || itemOnCRight == ITEM_MASK_TRUTH) { HandleRBAPaddingBytes(itemToPutInBottle); } else if (itemOnCRight >= ITEM_SOLD_OUT && itemOnCRight <= ITEM_COJIRO) { - HandleRBAInventoryUpgrades(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryUpgrades(itemToPutInBottle); + } } else if (itemOnCRight >= ITEM_ODD_MUSHROOM && itemOnCRight <= ITEM_SWORD_BROKEN) { - HandleRBAInventoryQuestItems(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryQuestItems(itemToPutInBottle); + } } else if (itemOnCRight >= ITEM_PRESCRIPTION && itemOnCRight <= ITEM_BULLET_BAG_30) { - HandleRBAInventoryDungeonItems(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryDungeonItems(itemToPutInBottle); + } } else if (itemOnCRight >= ITEM_BULLET_BAG_40 && itemOnCRight <= ITEM_SWORD_KNIFE) { - HandleRBAInventoryDungeonKeys(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryDungeonKeys(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_SONG_BOLERO) { - HandleRBAInventoryDefenseHearts(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryDefenseHearts(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_SONG_SERENADE || itemOnCRight == ITEM_SONG_REQUIEM) { - HandleRBAInventoryGSTokens(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBAInventoryGSTokens(itemToPutInBottle); + } } else if (itemOnCRight == ITEM_SONG_NOCTURNE || itemOnCRight == ITEM_SONG_PRELUDE) { HandleRBAPaddingBytes(itemToPutInBottle); } else if (itemOnCRight >= ITEM_SONG_LULLABY) { - HandleRBASceneFlags(itemToPutInBottle); + if (!IS_RANDO) { + HandleRBASceneFlags(itemToPutInBottle); + } + } else { + SPDLOG_WARN("[DoRBA] Invalid itemOnCRight ({})", itemOnCRight); + assert(false); } } From 05c349075717f3de3f985a6a9b16a93cb813cebb Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 5 May 2026 17:49:58 +0200 Subject: [PATCH 3/4] Remove unused cvar from ConfigUpdaters.cpp It's always on --- soh/soh/config/ConfigUpdaters.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/soh/soh/config/ConfigUpdaters.cpp b/soh/soh/config/ConfigUpdaters.cpp index 8249bb48d31..e3e0235fb0f 100644 --- a/soh/soh/config/ConfigUpdaters.cpp +++ b/soh/soh/config/ConfigUpdaters.cpp @@ -263,7 +263,6 @@ static const Migration version3Migrations[] = { { "gRedGanonBlood", "gEnhancements.RedGanonBlood" }, { "gRememberSaveLocation", "gEnhancements.RememberSaveLocation" }, { "gRemoveExplosiveLimit", "gEnhancements.RemoveExplosiveLimit" }, - { "gRestoreRBAValues", "gEnhancements.RestoreRBAValues" }, { "gRupeeDash", "gEnhancements.RupeeDash" }, { "gSceneSpecificDirtPathFix", "gEnhancements.SceneSpecificDirtPathFix" }, { "gSeparateArrows", "gEnhancements.SeparateArrows" }, From caff885521d7786ade8650d9663ddd01926c48e4 Mon Sep 17 00:00:00 2001 From: Pepe20129 <72659707+Pepe20129@users.noreply.github.com> Date: Tue, 5 May 2026 18:35:56 +0200 Subject: [PATCH 4/4] Move RBA gauntlet colors to RBA/BA file --- .../Restorations/BottleAdventure.cpp | 22 +++++++++++++++++++ .../vanilla-behavior/GIVanillaBehavior.h | 10 ++++++++- soh/src/code/z_player_lib.c | 9 +++----- 3 files changed, 34 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/Restorations/BottleAdventure.cpp b/soh/soh/Enhancements/Restorations/BottleAdventure.cpp index 12efa89e171..b5066a5792e 100644 --- a/soh/soh/Enhancements/Restorations/BottleAdventure.cpp +++ b/soh/soh/Enhancements/Restorations/BottleAdventure.cpp @@ -2,6 +2,7 @@ #include "soh/ShipInit.hpp" extern "C" { +#include "macros.h" #include "variables.h" } @@ -546,6 +547,27 @@ void RegisterBottleAdventure() { auto itemToPutInBottle = static_cast(va_arg(args, int32_t)); DoRBA(itemToPutInBottle); }); + + static Color_RGB8 sGauntletColors[] = { + // values matching OOB reads on N64 + { 0, 0, 6 }, + { 2, 89, 24 }, + { 6, 2, 90 }, + { 96, 6, 2 }, + }; + + REGISTER_VB_SHOULD(VB_SET_GAUNTLET_COLOR, { + Color_RGB8* color = va_arg(args, Color_RGB8*); + s32 strengthUpgrade = CUR_UPG_VALUE(UPG_STRENGTH); + + if (strengthUpgrade <= 3) { + return; + } + + color = &sGauntletColors[strengthUpgrade - 4]; + + *should = false; + }); } static RegisterShipInitFunc initFunc(RegisterBottleAdventure); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index d1ed4534100..541278b7a6c 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2965,7 +2965,15 @@ typedef enum { // ``` // #### `args` // - `*int32_t (camId)` - VB_SHOULD_LOAD_BG_IMAGE + VB_SHOULD_LOAD_BG_IMAGE, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*Color_RGB8` + VB_SET_GAUNTLET_COLOR, } GIVanillaBehavior; #endif diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 34750ed2cc7..e67e30503b9 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -1019,11 +1019,6 @@ Color_RGB8 sTunicColors[] = { Color_RGB8 sGauntletColors[] = { { 255, 255, 255 }, { 254, 207, 15 }, - // #region SOH [RBA] values matching OOB reads on N64 - { 0, 0, 6 }, - { 2, 89, 24 }, - { 6, 2, 90 }, - { 96, 6, 2 }, }; Gfx* sBootDListGroups[][2] = { @@ -1100,7 +1095,9 @@ void Player_DrawImpl(PlayState* play, void** skeleton, Vec3s* jointTable, s32 dL if (strengthUpgrade >= 2) { // silver or gold gauntlets gDPPipeSync(POLY_OPA_DISP++); - color = &sGauntletColors[strengthUpgrade - 2]; + if (GameInteractor_Should(VB_SET_GAUNTLET_COLOR, true, color, strengthUpgrade)) { + color = &sGauntletColors[strengthUpgrade - 2]; + } if (strengthUpgrade == PLAYER_STR_SILVER_G && CVarGetInteger(CVAR_COSMETIC("Gloves.SilverGauntlets.Changed"), 0)) { sTemp = CVarGetColor24(CVAR_COSMETIC("Gloves.SilverGauntlets.Value"), *color);