From f431f7df724bcd3eddb6882589b2772f480b1ff3 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Sun, 14 Aug 2022 12:29:56 -0500 Subject: [PATCH 01/17] Add Bombchus in Logic rando setting and implement progressive chus --- .../Enhancements/randomizer/randomizer.cpp | 25 ++++++++++++++++++- .../Enhancements/randomizer/randomizerTypes.h | 3 ++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ca86793cc1..100d36c173 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1452,6 +1452,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "Shuffle Dungeon Items:Gerudo Fortress Keys", RSK_GERUDO_KEYS }, { "Shuffle Dungeon Items:Boss Keys", RSK_BOSS_KEYSANITY }, { "Shuffle Dungeon Items:Ganon's Boss Key", RSK_GANONS_BOSS_KEY }, + { "World Settings:Bombchus in Logic", RSK_BOMBCHUS_IN_LOGIC }, { "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS }, { "Misc Settings:Hint Clarity", RSK_HINT_CLARITY }, { "Misc Settings:Hint Distribution", RSK_HINT_DISTRIBUTION }, @@ -2229,7 +2230,13 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) return GI_RUPEE_BLUE; case RG_PROGRESSIVE_BOMBCHUS: - return GI_BOMBCHUS_20; //todo progressive? + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE) { + return GI_BOMBCHUS_20; + } + if (AMMO(ITEM_BOMBCHU) < 5) { + return GI_BOMBCHUS_10; + } + return GI_BOMBCHUS_5; case RG_PROGRESSIVE_MAGIC_METER: switch (gSaveContext.magicLevel) { @@ -3540,6 +3547,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 0); cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0); cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0); + cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVar_GetS32("gRandomizeBombchusInLogic", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); // if we skip child zelda, we start with zelda's letter, and malon starts @@ -4153,6 +4161,21 @@ void DrawRandoEditor(bool& open) { "This setting does not effect the item earned from playing\n" "the Song of Storms and the frog song minigame." ); + PaddedSeparator(); + + // Bombchus in Logic + // TODO: add to world settings after entrance rando gets merged + SohImGui::EnhancementCheckbox(Settings::BombchusInLogic.GetName().c_str(), "gRandomizeBombchusInLogic"); + InsertHelpHoverText( + "Bombchus are properly considered in logic.\n" + "\n" + "The first Bombchu pack will always be 20, and subsequent packs will be" + "5 or 10 based on how many you have.\n" + "Once found, they can be replenished at the Kokiri shop, Bazaar, or Bombchu" + "shop.\n" + "\n" + "Bombchu Bowling is opened by obtaining Bombchus." + ); } ImGui::PopItemWidth(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index b09b9dab24..4209766155 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1008,5 +1008,6 @@ typedef enum { RSK_COMPLETE_MASK_QUEST, RSK_ENABLE_GLITCH_CUTSCENES, RSK_SKULLS_SUNS_SONG, - RSK_SHUFFLE_ADULT_TRADE + RSK_SHUFFLE_ADULT_TRADE, + RSK_BOMBCHUS_IN_LOGIC } RandomizerSettingKey; From 8cb50a2ee16ff205e4fcd8fd58b98e8eb88fefc1 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Sun, 14 Aug 2022 12:30:22 -0500 Subject: [PATCH 02/17] Open Bombchu Bowling with chus --- .../randomizer/3drando/settings.cpp | 2 ++ .../Enhancements/randomizer/randomizer.cpp | 5 ++-- .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 26 ++++++++++++------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 71aa70b323..1482a5cdb2 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2551,6 +2551,8 @@ namespace Settings { MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]); + BombchusInLogic.SetSelectedIndex(cvarSettings[RSK_BOMBCHUS_IN_LOGIC]); + StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]); StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 100d36c173..95401a34ef 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1688,6 +1688,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { case RSK_STARTING_KOKIRI_SWORD: case RSK_COMPLETE_MASK_QUEST: case RSK_ENABLE_GLITCH_CUTSCENES: + case RSK_BOMBCHUS_IN_LOGIC: if(it.value() == "Off") { gSaveContext.randoSettings[index].value = 0; } else if(it.value() == "On") { @@ -4169,9 +4170,9 @@ void DrawRandoEditor(bool& open) { InsertHelpHoverText( "Bombchus are properly considered in logic.\n" "\n" - "The first Bombchu pack will always be 20, and subsequent packs will be" + "The first Bombchu pack will always be 20, and subsequent packs will be " "5 or 10 based on how many you have.\n" - "Once found, they can be replenished at the Kokiri shop, Bazaar, or Bombchu" + "Once found, they can be replenished at the Kokiri shop, Bazaar, or Bombchu " "shop.\n" "\n" "Bombchu Bowling is opened by obtaining Bombchus." diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index dc22f9dab6..28a63bbf62 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -143,13 +143,14 @@ void EnBomBowMan_BlinkAwake(EnBomBowlMan* this, GlobalContext* globalCtx) { } } - // Check for Bomb Bag if Rando is enabled - // RANDOTODO: Check for bombchu pack instead of bomb bag if bombchus are in logic + // Check for Bomb Bag or Bombchus if Rando is enabled, depending on whether bombchus are considered in logic if (gSaveContext.n64ddFlag) { - if (INV_CONTENT(ITEM_BOMB) != ITEM_NONE) { - this->actor.textId = 0xBF; - } else { + u8 bombchusInLogic = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC); + if ((!bombchusInLogic && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) || + (bombchusInLogic && INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE)) { this->actor.textId = 0x7058; + } else { + this->actor.textId = 0xBF; } } } @@ -177,11 +178,16 @@ void EnBomBowMan_CheckBeatenDC(EnBomBowlMan* this, GlobalContext* globalCtx) { this->eyeMode = CHU_GIRL_EYES_AWAKE; this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20; - // Check for beaten Dodongo's Cavern if not rando'd - // check for bomb bag if rando'd - if ((!gSaveContext.n64ddFlag && - !((gSaveContext.eventChkInf[2] & 0x20) || BREG(2))) || - (gSaveContext.n64ddFlag && (INV_CONTENT(ITEM_BOMB) == ITEM_NONE))) { + // Check if beaten Dodongo's Cavern if not rando'd + // check for bomb bag or bombchus if rando'd depending on whether chus are in logic + bool bombchuBowlingClosed; + if (gSaveContext.n64ddFlag) { + u8 explosive = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) ? ITEM_BOMBCHU : ITEM_BOMB; + bombchuBowlingClosed = (INV_CONTENT(explosive) == ITEM_NONE); + } else { + bombchuBowlingClosed = !((gSaveContext.eventChkInf[2] & 0x20) || BREG(2)); + } + if (bombchuBowlingClosed) { this->actionFunc = EnBomBowMan_WaitNotBeatenDC; } else { this->actor.textId = 0x18; From e8df2f2e470719b5d2efd9e83eca0d73605fa456 Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Wed, 17 Aug 2022 11:36:41 -0500 Subject: [PATCH 03/17] Open bombchu shop with chus --- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 5a1a36be7a..f32404cc11 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -633,8 +633,16 @@ s32 EnGirlA_CanBuy_Unk20(GlobalContext* globalCtx, EnGirlA* this) { } s32 EnGirlA_CanBuy_Bombchus(GlobalContext* globalCtx, EnGirlA* this) { - // When in rando, don't allow buying bombchus when the player doesn't have a bomb bag - if (AMMO(ITEM_BOMBCHU) >= 50 || (gSaveContext.n64ddFlag && CUR_CAPACITY(UPG_BOMB_BAG) == 0)) { + // When in rando, don't allow buying bombchus when the player doesn't have required explosives + // If bombchus are in logic, the player needs to have bombchus; otherwise they need a bomb bag + if (gSaveContext.n64ddFlag) { + u8 bombchusInLogic = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC); + if ((!bombchusInLogic && CUR_CAPACITY(UPG_BOMB_BAG) == 0) || + (bombchusInLogic && INV_CONTENT(ITEM_BOMBCHU) == ITEM_NONE)) { + return CANBUY_RESULT_CANT_GET_NOW; + } + } + if (AMMO(ITEM_BOMBCHU) >= 50) { return CANBUY_RESULT_CANT_GET_NOW; } if (gSaveContext.rupees < this->basePrice) { @@ -861,6 +869,11 @@ void EnGirlA_BuyEvent_ZoraTunic(GlobalContext* globalCtx, EnGirlA* this) { } void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this) { + Rupees_ChangeBy(-this->basePrice); + + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC)) { + return; + } switch (this->actor.params) { case SI_BOMBCHU_10_2: gSaveContext.itemGetInf[0] |= 0x40; @@ -887,7 +900,6 @@ void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this) gSaveContext.itemGetInf[0] |= 0x20; break; } - Rupees_ChangeBy(-this->basePrice); } void EnGirlA_Noop(EnGirlA* this, GlobalContext* globalCtx) { From 170b7595725936692bc429518de2c999ea46ffe7 Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Thu, 18 Aug 2022 10:38:49 -0500 Subject: [PATCH 04/17] Make Bombchus buyable without a wallet --- .../custom-message/CustomMessageTypes.h | 2 ++ soh/soh/OTRGlobals.cpp | 3 +++ soh/soh/z_message_OTR.cpp | 22 ++++++++++++++++++- .../overlays/actors/ovl_En_GirlA/z_en_girla.c | 7 +++++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 1859e83a52..f9a4f7936e 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -1,6 +1,8 @@ #pragma once typedef enum { + TEXT_BUY_BOMBCHU_10_PROMPT = 0x8C, + TEXT_BUY_BOMBCHU_10_DESC = 0xBC, TEXT_GS_NO_FREEZE = 0xB4, TEXT_GS_FREEZE = 0xB5, TEXT_RANDOMIZER_CUSTOM_ITEM = 0xF8, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 3611c97de2..699c3f103c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1540,6 +1540,9 @@ extern "C" int CustomMessage_RetrieveIfExists(GlobalContext* globalCtx) { } } else if (textId == TEXT_SCRUB_POH || textId == TEXT_SCRUB_STICK_UPGRADE || textId == TEXT_SCRUB_NUT_UPGRADE) { messageEntry = Randomizer_GetScrubMessage(textId); + } else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && + (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index c6be439644..5cfc99395c 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -111,5 +111,25 @@ extern "C" void OTRMessage_Init() TEXTBOX_TYPE_BLUE, TEXTBOX_POS_BOTTOM, "You got a %rGold Skulltula Token%w!&You've collected %r\x19%w tokens&in total!", "Du erhälst ein %rGoldene&Skulltula-Symbol%w! Du hast&insgesamt %r\x19%w symbol gesammelt!", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r\x19\%w symboles en tout!" }); + "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r\x19\%w symboles en tout!" + } + ); + CustomMessageManager::Instance->CreateMessage( + customMessageTableID, TEXT_BUY_BOMBCHU_10_DESC, + { + TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, + "\x08%rBombchu (10 pieces) 99 Rupees&%wThis looks like a toy mouse, but&it's actually a self-propelled time&bomb!\x09\x0A", + "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als Distanzwaffe&einsetzen kannst!\x09\x0A", + "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est &destructrice!!!\x09\x0A", + } + ); + CustomMessageManager::Instance->CreateMessage( + customMessageTableID, TEXT_BUY_BOMBCHU_10_PROMPT, + { + TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM, + "\x08\Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", + "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", + "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w", + } + ); } diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index f32404cc11..54af786a64 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -1065,7 +1065,12 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, GlobalContext* globalCtx) { this->canBuyFunc = itemEntry->canBuyFunc; this->itemGiveFunc = itemEntry->itemGiveFunc; this->buyEventFunc = itemEntry->buyEventFunc; - this->basePrice = itemEntry->price; + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && + this->getItemId == GI_BOMBCHUS_10) { + this->basePrice = 99; + } else { + this->basePrice = itemEntry->price; + } this->itemCount = itemEntry->count; this->hiliteFunc = itemEntry->hiliteFunc; this->giDrawId = itemEntry->giDrawId; From 58aed3dc07fef3a98a208ac377529fa13f83ea99 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Mon, 22 Aug 2022 10:41:59 -0500 Subject: [PATCH 05/17] Correct bombchus in logic description to only include chu shop --- soh/soh/Enhancements/randomizer/randomizer.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 95401a34ef..8616208d3f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4172,8 +4172,7 @@ void DrawRandoEditor(bool& open) { "\n" "The first Bombchu pack will always be 20, and subsequent packs will be " "5 or 10 based on how many you have.\n" - "Once found, they can be replenished at the Kokiri shop, Bazaar, or Bombchu " - "shop.\n" + "Once found, they can be replenished at the Bombchu shop.\n" "\n" "Bombchu Bowling is opened by obtaining Bombchus." ); From 6a900022c07c470b7d5471e2993181b5b6d91b0f Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Tue, 23 Aug 2022 07:47:21 -0500 Subject: [PATCH 06/17] Pass vanilla ammo drops to logic --- soh/soh/Enhancements/randomizer/3drando/settings.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 1482a5cdb2..9bff10b1ce 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2552,6 +2552,7 @@ namespace Settings { MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]); BombchusInLogic.SetSelectedIndex(cvarSettings[RSK_BOMBCHUS_IN_LOGIC]); + AmmoDrops.SetSelectedIndex(AMMODROPS_VANILLA); // Ensure logic knows bombchu drops aren't implemented yet StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]); StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]); From 05136c13b7cc9e4a0431e5b8adf33d38cf198902 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Fri, 26 Aug 2022 20:46:19 -0400 Subject: [PATCH 07/17] Fixes Link getting Song as pocket item (#1326) --- soh/src/code/z_sram.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index 952ce8e3ce..c71bb4defd 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -703,6 +703,8 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { if (getItem.modIndex == MOD_NONE) { if (getItem.itemId >= ITEM_MEDALLION_FOREST && getItem.itemId <= ITEM_ZORA_SAPPHIRE) { GiveLinkDungeonReward(getItem.getItemId); + } else if (getItem.itemId >= ITEM_SONG_MINUET && getItem.itemId <= ITEM_SONG_STORMS) { + GiveLinkSong(getItem.getItemId); } else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED || giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) { GiveLinkRupeesByGetItemId(giid); From a572c11f4f41a011733507296189161b758df7d0 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Sat, 27 Aug 2022 03:27:20 -0400 Subject: [PATCH 08/17] Fixes ice trap gidata not getting cleared after trap is sprung. (#1322) --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index cd2950d657..e2c823012c 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6121,6 +6121,8 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) { this->actor.colChkInfo.damage = 0; func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20); Player_SetPendingFlag(this, globalCtx); + this->getItemId == GI_NONE; + this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; return 1; } @@ -12866,6 +12868,8 @@ void func_8084E6D4(Player* this, GlobalContext* globalCtx) { } else { this->actor.colChkInfo.damage = 0; func_80837C0C(globalCtx, this, 3, 0.0f, 0.0f, 0, 20); + this->getItemId == GI_NONE; + this->getItemEntry = (GetItemEntry)GET_ITEM_NONE; } return; } From 776219fb52730541c402c1fd63b7b9bd470cdb22 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 31 Aug 2022 09:25:47 -0400 Subject: [PATCH 09/17] Backports a fix for sheik checks from rando-next (#1340) * Fixes some Sheik checks I had accidentally set the wrong flag for. * Removes duplicate switch case from cherry-pick --- soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 90e401f06f..30ab5d06ea 100644 --- a/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/soh/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -298,7 +298,7 @@ void GivePlayerRandoRewardSheikSong(EnXc* sheik, GlobalContext* globalCtx, Rando } } else if (check != RC_SHEIK_AT_TEMPLE) { if (GiveItemEntryFromActor(&sheik->actor, globalCtx, getItemEntry, 10000.0f, 100.0f)) { - player->pendingFlag.flagID = 0x55; + player->pendingFlag.flagID = (0x5 << 4) | (sheikType & 0xF) >> 1; player->pendingFlag.flagType = FLAG_EVENT_CHECK_INF; } } From bf505dba5cef0aaffb4576c9b4c4f430e9bceb43 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 31 Aug 2022 09:25:58 -0400 Subject: [PATCH 10/17] Fixes keys, maps, and compasses on develop-zhora rando (#1338) * Fixes keys, maps, and compasses on develop-zhora rando. * Adds randotodo comment as a note to adapt for the keysanity situation. --- .../Enhancements/randomizer/randomizer.cpp | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 1fc95a04fc..4958503619 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2209,6 +2209,42 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_BUY_BOMBS_535: case RG_BUY_RED_POTION_40: case RG_BUY_RED_POTION_50: + //RANDO TODO: Fix this to return false if keysanity is on. + case RG_FOREST_TEMPLE_SMALL_KEY: + case RG_FIRE_TEMPLE_SMALL_KEY: + case RG_WATER_TEMPLE_SMALL_KEY: + case RG_SPIRIT_TEMPLE_SMALL_KEY: + case RG_SHADOW_TEMPLE_SMALL_KEY: + case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + case RG_GERUDO_FORTRESS_SMALL_KEY: + case RG_GANONS_CASTLE_SMALL_KEY: + case RG_FOREST_TEMPLE_BOSS_KEY: + case RG_FIRE_TEMPLE_BOSS_KEY: + case RG_WATER_TEMPLE_BOSS_KEY: + case RG_SPIRIT_TEMPLE_BOSS_KEY: + case RG_SHADOW_TEMPLE_BOSS_KEY: + case RG_GANONS_CASTLE_BOSS_KEY: + case RG_DEKU_TREE_COMPASS: + case RG_DODONGOS_CAVERN_COMPASS: + case RG_JABU_JABUS_BELLY_COMPASS: + case RG_FOREST_TEMPLE_COMPASS: + case RG_FIRE_TEMPLE_COMPASS: + case RG_WATER_TEMPLE_COMPASS: + case RG_SPIRIT_TEMPLE_COMPASS: + case RG_SHADOW_TEMPLE_COMPASS: + case RG_BOTTOM_OF_THE_WELL_COMPASS: + case RG_ICE_CAVERN_COMPASS: + case RG_DEKU_TREE_MAP: + case RG_DODONGOS_CAVERN_MAP: + case RG_JABU_JABUS_BELLY_MAP: + case RG_FOREST_TEMPLE_MAP: + case RG_FIRE_TEMPLE_MAP: + case RG_WATER_TEMPLE_MAP: + case RG_SPIRIT_TEMPLE_MAP: + case RG_SHADOW_TEMPLE_MAP: + case RG_BOTTOM_OF_THE_WELL_MAP: + case RG_ICE_CAVERN_MAP: return true; default: return false; From 042d6f3865fd187642eb8aa48f8c01f9d5b6c399 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 31 Aug 2022 10:57:59 -0400 Subject: [PATCH 11/17] Fixes a few bugs related to chests. --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 2631e39b99..2ac6e0fc25 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -6108,7 +6108,7 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) { } GetItemEntry giEntry; - if (this->getItemEntry.objectId == OBJECT_INVALID) { + if (this->getItemEntry.objectId == OBJECT_INVALID || (this->getItemId != this->getItemEntry.getItemId)) { giEntry = ItemTable_Retrieve(this->getItemId); } else { giEntry = this->getItemEntry; @@ -6165,7 +6165,7 @@ s32 func_8083E5A8(Player* this, GlobalContext* globalCtx) { } } else if (CHECK_BTN_ALL(sControlInput->press.button, BTN_A) && !(this->stateFlags1 & PLAYER_STATE1_11) && !(this->stateFlags2 & PLAYER_STATE2_10)) { - if (this->getItemId != GI_NONE && this->getItemEntry.objectId != OBJECT_INVALID) { + if (this->getItemId != GI_NONE) { GetItemEntry giEntry; if (this->getItemEntry.objectId == OBJECT_INVALID) { giEntry = ItemTable_Retrieve(-this->getItemId); @@ -9687,8 +9687,8 @@ void func_808473D4(GlobalContext* globalCtx, Player* this) { else if ((!(this->stateFlags1 & PLAYER_STATE1_11) || (heldActor == NULL)) && (interactRangeActor != NULL) && ((!sp1C && (this->getItemId == GI_NONE)) || - ((this->getItemId < 0 && this->getItemEntry.getItemId < 0) && !(this->stateFlags1 & PLAYER_STATE1_27)))) { - if (this->getItemId < 0 && this->getItemEntry.getItemId < 0) { + (this->getItemId < 0 && !(this->stateFlags1 & PLAYER_STATE1_27)))) { + if (this->getItemId < 0) { doAction = DO_ACTION_OPEN; } else if ((interactRangeActor->id == ACTOR_BG_TOKI_SWD) && LINK_IS_ADULT) { doAction = DO_ACTION_DROP; From 1f12caa5c9e02f108560ffe3f73f624ce42f4422 Mon Sep 17 00:00:00 2001 From: briaguya Date: Wed, 31 Aug 2022 18:15:09 -0400 Subject: [PATCH 12/17] fix oot ice trap check optimization issues --- soh/soh/OTRGlobals.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7d7a86268f..8867862602 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1652,15 +1652,14 @@ extern "C" GetItemEntry Randomizer_GetItemFromKnownCheck(RandomizerCheck randomi return ItemTable_RetrieveEntry(getItemModIndex, itemID); } -extern "C" bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor) { - return gSaveContext.n64ddFlag && (actor->parent != NULL) && - Randomizer_GetItemFromKnownCheck(randomizerCheck, ogId).getItemId == RG_ICE_TRAP; -} - extern "C" bool Randomizer_ItemIsIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId) { return gSaveContext.n64ddFlag && Randomizer_GetItemFromKnownCheck(randomizerCheck, ogId).getItemId == RG_ICE_TRAP; } +extern "C" bool Randomizer_ObtainedFreestandingIceTrap(RandomizerCheck randomizerCheck, GetItemID ogId, Actor* actor) { + return Randomizer_ItemIsIceTrap(randomizerCheck, ogId) && actor->parent != NULL; +} + extern "C" CustomMessageEntry Randomizer_GetCustomGetItemMessage(Player* player) { s16 giid; if (player->getItemEntry.objectId != OBJECT_INVALID) { From 584a4ad818df3046c2e13d0ab1c2e6a7f6c67fa6 Mon Sep 17 00:00:00 2001 From: louist103 <35883445+louist103@users.noreply.github.com> Date: Wed, 31 Aug 2022 22:59:38 -0400 Subject: [PATCH 13/17] Linux crash handler (#1209) * crash handler linux * cleanups * missing underscore * more cleanups * cleanups * 32 bit --- .gitignore | 2 + libultraship/libultraship/CMakeLists.txt | 7 + libultraship/libultraship/CrashHandler.cpp | 172 +++++++++++++++++++++ libultraship/libultraship/CrashHandler.h | 18 +++ soh/include/functions.h | 2 +- soh/include/segment_symbols.h | 12 +- soh/soh/OTRGlobals.h | 2 + soh/src/code/fault.c | 2 +- soh/src/code/main.c | 12 +- 9 files changed, 218 insertions(+), 11 deletions(-) create mode 100644 libultraship/libultraship/CrashHandler.cpp create mode 100644 libultraship/libultraship/CrashHandler.h diff --git a/.gitignore b/.gitignore index 1df76208d2..98fe2b6370 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ __pycache__/ .idea/ cmake-build-debug venv/ +.cache/ # Project-specific ignores build/ @@ -410,6 +411,7 @@ oot.otr *.sav shipofharkinian.ini shipofharkinian.json +imgui.ini # Switch Stuff diff --git a/libultraship/libultraship/CMakeLists.txt b/libultraship/libultraship/CMakeLists.txt index b599936601..aec229bfb9 100644 --- a/libultraship/libultraship/CMakeLists.txt +++ b/libultraship/libultraship/CMakeLists.txt @@ -334,6 +334,12 @@ set(Source_Files__Resources__mpq ) source_group("Source Files\\Resources\\mpq" FILES ${Source_Files__Resources__mpq}) +set(Source_Files__Crash_Handler + "CrashHandler.cpp" + "CrashHandler.h" +) +source_group("Source Files\\Crash Handler" FILES ${Source_Files__Crash_Handler}) + if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") set(Source_Files__Darwin "OSXFolderManager.mm" @@ -388,6 +394,7 @@ set(ALL_FILES ${Source_Files__Resources__Factories} ${Source_Files__Resources__Files} ${Source_Files__Resources__mpq} + ${Source_Files__Crash_Handler} ${Source_Files__Darwin} ${Source_Files__NintendoSwitch} ${Source_Files__CafeOS} diff --git a/libultraship/libultraship/CrashHandler.cpp b/libultraship/libultraship/CrashHandler.cpp new file mode 100644 index 0000000000..f8d66beab8 --- /dev/null +++ b/libultraship/libultraship/CrashHandler.cpp @@ -0,0 +1,172 @@ +#include "spdlog/spdlog.h" +#include "Utils/StringHelper.h" +#include "CrashHandler.h" + +#if defined(__linux__) +#include +#include +#include // for __cxa_demangle +#include // for dladdr +#include +#include + +extern "C" void DeinitOTR(void); + + +static void PrintRegisters(ucontext_t* ctx) { + char regbuffer[1024]; + SPDLOG_CRITICAL("Registers:"); +#if defined(__x86_64__) + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RAX]); + SPDLOG_CRITICAL("RAX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDI]); + SPDLOG_CRITICAL("RDI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSI]); + SPDLOG_CRITICAL("RSI: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RDX]); + SPDLOG_CRITICAL("RDX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RCX]); + SPDLOG_CRITICAL("RCX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R8]); + SPDLOG_CRITICAL("R8 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R9]); + SPDLOG_CRITICAL("R9 : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R10]); + SPDLOG_CRITICAL("R10: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R11]); + SPDLOG_CRITICAL("R11: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RSP]); + SPDLOG_CRITICAL("RSP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBX]); + SPDLOG_CRITICAL("RBX: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RBP]); + SPDLOG_CRITICAL("RBP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R12]); + SPDLOG_CRITICAL("R12: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R13]); + SPDLOG_CRITICAL("R13: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R14]); + SPDLOG_CRITICAL("R14: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_R15]); + SPDLOG_CRITICAL("R15: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_RIP]); + SPDLOG_CRITICAL("RIP: {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer), "0x%016llX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFLAGS: {} ", regbuffer); +#else + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDI]); + SPDLOG_CRITICAL("EDI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESI]); + SPDLOG_CRITICAL("ESI : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBP]); + SPDLOG_CRITICAL("EBP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ESP]); + SPDLOG_CRITICAL("ESP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EBX]); + SPDLOG_CRITICAL("EBX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EDX]); + SPDLOG_CRITICAL("EDX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_ECX]); + SPDLOG_CRITICAL("ECX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EAX]); + SPDLOG_CRITICAL("EAX : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EIP]); + SPDLOG_CRITICAL("EIP : {} ", regbuffer); + snprintf(regbuffer, std::size(regbuffer),"0x%08lX", ctx->uc_mcontext.gregs[REG_EFL]); + SPDLOG_CRITICAL("EFL : {} ", regbuffer); +#endif +} + +static void ErrorHandler(int sig, siginfo_t* sigInfo, void* data) +{ + std::array arr; + ucontext_t* ctx = static_cast(data); + constexpr size_t nMaxFrames = arr.size(); + size_t size = backtrace(arr.data(), nMaxFrames); + char** symbols = backtrace_symbols(arr.data(), nMaxFrames); + + SPDLOG_CRITICAL("(Signal: {})\n", sig); + + switch (sig) { + case SIGILL: + SPDLOG_CRITICAL("ILLEGAL INSTRUCTION"); + break; + case SIGABRT: + SPDLOG_CRITICAL("ABORT"); + break; + case SIGFPE: + SPDLOG_CRITICAL("ERRONEUS ARITHEMETIC OPERATION"); + break; + case SIGSEGV: + SPDLOG_CRITICAL("INVALID ACCESS TO STORAGE"); + break; + } + + PrintRegisters(ctx); + + SPDLOG_CRITICAL("Traceback:\n"); + for (size_t i = 1; i < size; i++) + { + Dl_info info; + int gotAddress = dladdr(arr[i], &info); + std::string functionName(symbols[i]); + + if (gotAddress != 0 && info.dli_sname != nullptr) + { + FILE* pipe; + int32_t status; + char* demangled = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); + const char* nameFound = info.dli_sname; + + if (status == 0) + { + nameFound = demangled; + } + #if 0 + char command[256]; + char addrLine[128]; + snprintf(command, sizeof(command), "addr2line -e soh.elf %s + 0x%lX", nameFound, (uintptr_t)arr[i] - (uintptr_t)info.dli_saddr); + pipe = popen(command, "r"); + fgets(addrLine, 128, pipe); + #endif + + functionName = StringHelper::Sprintf("%s (+0x%X)", nameFound, + (char*)arr[i] - (char*)info.dli_saddr); + free(demangled); + } + + SPDLOG_CRITICAL("{} {}", i, functionName.c_str()); + } + + free(symbols); + DeinitOTR(); + exit(1); +} + +static void ShutdownHandler(int sig, siginfo_t* sigInfo, void* data) { + DeinitOTR(); + exit(1); +} + +extern "C" void SetupHandlerLinux() { + struct sigaction action; + struct sigaction shutdownAction; + + action.sa_flags = SA_SIGINFO; + action.sa_sigaction = ErrorHandler; + + sigaction(SIGILL, &action, nullptr); + sigaction(SIGABRT, &action, nullptr); + sigaction(SIGFPE, &action, nullptr); + sigaction(SIGSEGV, &action, nullptr); + + shutdownAction.sa_flags = SA_SIGINFO; + shutdownAction.sa_sigaction = ShutdownHandler; + sigaction(SIGINT, &shutdownAction, nullptr); + sigaction(SIGTERM, &shutdownAction, nullptr); + sigaction(SIGQUIT, &shutdownAction, nullptr); + sigaction(SIGKILL, &shutdownAction, nullptr); + + +} +#endif diff --git a/libultraship/libultraship/CrashHandler.h b/libultraship/libultraship/CrashHandler.h new file mode 100644 index 0000000000..e068a4e389 --- /dev/null +++ b/libultraship/libultraship/CrashHandler.h @@ -0,0 +1,18 @@ +#ifndef CRASH_HANDLER_H +#define CRASH_HANDLER_H + +#ifdef __linux__ + +#ifdef __cplusplus +extern "C" { +#endif + +void SetupHandlerLinux(void); + +#ifdef __cplusplus +} +#endif + +#endif // __linux__ + +#endif // CRASH_HANDLER_H \ No newline at end of file diff --git a/soh/include/functions.h b/soh/include/functions.h index a336cb1efb..6339cff647 100644 --- a/soh/include/functions.h +++ b/soh/include/functions.h @@ -1656,7 +1656,7 @@ void PadMgr_HandleRetraceMsg(PadMgr* padmgr); void PadMgr_HandlePreNMI(PadMgr* padmgr); // This function must remain commented out, because it is called incorrectly in // fault.c (actual bug in game), and the compiler notices and won't compile it -// void PadMgr_RequestPadData(PadMgr* padmgr, Input* inputs, s32 mode); +void PadMgr_RequestPadData(PadMgr* padmgr, Input* inputs, s32 mode); void PadMgr_Init(PadMgr* padmgr, OSMesgQueue* siIntMsgQ, IrqMgr* irqMgr, OSId id, OSPri priority, void* stack); void Sched_SwapFrameBuffer(CfbInfo* cfbInfo); void func_800C84E4(SchedContext* sc, CfbInfo* cfbInfo); diff --git a/soh/include/segment_symbols.h b/soh/include/segment_symbols.h index 81fe348010..3b50b4eaad 100644 --- a/soh/include/segment_symbols.h +++ b/soh/include/segment_symbols.h @@ -3,20 +3,20 @@ #include "z64.h" -#define DECLARE_SEGMENT(name) \ - //extern u8 _##name##SegmentStart[]; \ +#define DECLARE_SEGMENT(name) + //extern u8 _##name##SegmentStart[]; //extern u8 _##name##SegmentEnd[]; -#define DECLARE_ROM_SEGMENT(name) \ - //extern u8 _##name##SegmentRomStart[]; \ +#define DECLARE_ROM_SEGMENT(name) + //extern u8 _##name##SegmentRomStart[]; //extern u8 _##name##SegmentRomEnd[]; #define DECLARE_BSS_SEGMENT(name) \ extern u8 _##name##SegmentBssStart[]; \ extern u8 _##name##SegmentBssEnd[]; -#define DECLARE_OVERLAY_SEGMENT(name) \ - //DECLARE_SEGMENT(ovl_##name) \ +#define DECLARE_OVERLAY_SEGMENT(name) + //DECLARE_SEGMENT(ovl_##name) //DECLARE_ROM_SEGMENT(ovl_##name) DECLARE_SEGMENT(boot) diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index dc304358db..089394e330 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -32,6 +32,8 @@ private: #endif #ifndef __cplusplus +void InitOTR(void); +void DeinitOTR(void); void VanillaItemTable_Init(); void OTRAudio_Init(); void InitAudio(); diff --git a/soh/src/code/fault.c b/soh/src/code/fault.c index c55a63a001..f7414766a4 100644 --- a/soh/src/code/fault.c +++ b/soh/src/code/fault.c @@ -293,7 +293,7 @@ void Fault_Sleep(u32 duration) { void Fault_PadCallback(Input* input) { //! @bug This function is not called correctly and thus will crash from reading a bad pointer at 0x800C7E4C - PadMgr_RequestPadData(input, 0); + PadMgr_RequestPadData(&gPadMgr, input, 0); } void Fault_UpdatePadImpl() diff --git a/soh/src/code/main.c b/soh/src/code/main.c index ccfdc2019f..8e9fe1776a 100644 --- a/soh/src/code/main.c +++ b/soh/src/code/main.c @@ -3,6 +3,8 @@ #include #include "soh/OTRGlobals.h" +#include "../libultraship/CrashHandler.h" + s32 gScreenWidth = SCREEN_WIDTH; s32 gScreenHeight = SCREEN_HEIGHT; @@ -38,6 +40,10 @@ void Main_LogSystemHeap(void) { int main(int argc, char** argv) { +#ifdef __linux__ + SetupHandlerLinux(); +#endif + GameConsole_Init(); InitOTR(); BootCommands_Init(); @@ -64,14 +70,14 @@ void Main(void* arg) { Fault_Init(); SysCfb_Init(0); Heaps_Alloc(); - sysHeap = gSystemHeap; + sysHeap = (uintptr_t)gSystemHeap; fb = SysCfb_GetFbPtr(0); gSystemHeapSize = 1024 * 1024 * 4; // "System heap initalization" osSyncPrintf("システムヒープ初期化 %08x-%08x %08x\n", sysHeap, fb, gSystemHeapSize); - SystemHeap_Init(sysHeap, gSystemHeapSize); // initializes the system heap + SystemHeap_Init((void*)sysHeap, gSystemHeapSize); // initializes the system heap if (osMemSize >= 0x800000) { - debugHeap = SysCfb_GetFbEnd(); + debugHeap = (void*)SysCfb_GetFbEnd(); debugHeapSize = (0x80600000 - (uintptr_t)debugHeap); } else { debugHeapSize = 0x400; From cfaed3ded0ea32d63b6efe9f6b8eed9f021391e5 Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Wed, 31 Aug 2022 22:07:34 -0500 Subject: [PATCH 14/17] Make Biggoron ignore whether you have BGS in rando --- soh/src/overlays/actors/ovl_En_Go/z_en_go.c | 4 ++-- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 58124ef23a..3cadd6afee 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -95,7 +95,7 @@ u16 EnGo_GetTextID(GlobalContext* globalCtx, Actor* thisx) { switch (thisx->params & 0xF0) { case 0x90: - if (gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { @@ -859,7 +859,7 @@ void func_80A405CC(EnGo* this, GlobalContext* globalCtx) { void EnGo_BiggoronActionFunc(EnGo* this, GlobalContext* globalCtx) { if (((this->actor.params & 0xF0) == 0x90) && (this->unk_1E0.unk_00 == 2)) { - if (gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { this->unk_1E0.unk_00 = 0; } else { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index 9f6ff147e4..db11549618 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -595,7 +595,7 @@ s16 EnGo2_GetStateGoronCityLink(GlobalContext* globalCtx, EnGo2* this) { u16 EnGo2_GetTextIdGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { Player* player = GET_PLAYER(globalCtx); - if (gSaveContext.bgsFlag) { + if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK; return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { @@ -622,10 +622,6 @@ s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { } if(gSaveContext.n64ddFlag) { - if (INV_CONTENT(ITEM_CLAIM_CHECK) != ITEM_CLAIM_CHECK) { - return 0; - } - EnGo2_GetItemEntry(this, globalCtx, Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS)); Flags_SetTreasure(globalCtx, 0x1F); } else { @@ -1063,7 +1059,7 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, GlobalContext* globalCtx, Player* play u16 textId; if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) { - if (gSaveContext.bgsFlag) { + if ((!gSaveContext.n64ddFlag && gSaveContext.bgsFlag)) { if (func_8002F368(globalCtx) == EXCH_ITEM_CLAIM_CHECK) { this->actor.textId = 0x3003; } else { @@ -1071,16 +1067,20 @@ void EnGo2_BiggoronSetTextId(EnGo2* this, GlobalContext* globalCtx, Player* play } player->actor.textId = this->actor.textId; - } else if (!gSaveContext.bgsFlag && (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK)) { + } else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) { if (func_8002F368(globalCtx) == EXCH_ITEM_CLAIM_CHECK) { - if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { + if (gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F)) { + textId = 0x3003; + } else if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { textId = 0x305E; } else { textId = 0x305D; } this->actor.textId = textId; } else { - if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { + if (gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F)) { + textId = 0x305E; + } else if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { textId = 0x3002; } else { textId = 0x305D; From 0a744cde0132dd7ad5de27e1e6d849bba24b4720 Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 1 Sep 2022 08:11:17 -0500 Subject: [PATCH 15/17] Clarify comments --- .../actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 8 +++++--- soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c | 4 ++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 28a63bbf62..6bb097d896 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -143,7 +143,8 @@ void EnBomBowMan_BlinkAwake(EnBomBowlMan* this, GlobalContext* globalCtx) { } } - // Check for Bomb Bag or Bombchus if Rando is enabled, depending on whether bombchus are considered in logic + // In randomizer, only check for bomb bag when bombchus aren't in logic + // and only check for bombchus when bombchus are in logic if (gSaveContext.n64ddFlag) { u8 bombchusInLogic = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC); if ((!bombchusInLogic && INV_CONTENT(ITEM_BOMB) == ITEM_NONE) || @@ -178,13 +179,14 @@ void EnBomBowMan_CheckBeatenDC(EnBomBowlMan* this, GlobalContext* globalCtx) { this->eyeMode = CHU_GIRL_EYES_AWAKE; this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20; - // Check if beaten Dodongo's Cavern if not rando'd - // check for bomb bag or bombchus if rando'd depending on whether chus are in logic bool bombchuBowlingClosed; if (gSaveContext.n64ddFlag) { + // when rando'd, check if we have bombchus if chus are in logic + // and check if we have a bomb bag if chus aren't in logic u8 explosive = Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) ? ITEM_BOMBCHU : ITEM_BOMB; bombchuBowlingClosed = (INV_CONTENT(explosive) == ITEM_NONE); } else { + // if not rando'd, check if we have beaten Dodongo's Cavern bombchuBowlingClosed = !((gSaveContext.eventChkInf[2] & 0x20) || BREG(2)); } if (bombchuBowlingClosed) { diff --git a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c index 54af786a64..cbc2e97499 100644 --- a/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c +++ b/soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.c @@ -871,9 +871,12 @@ void EnGirlA_BuyEvent_ZoraTunic(GlobalContext* globalCtx, EnGirlA* this) { void EnGirlA_BuyEvent_ObtainBombchuPack(GlobalContext* globalCtx, EnGirlA* this) { Rupees_ChangeBy(-this->basePrice); + // Normally, buying a bombchu pack sets a flag indicating the pack is now sold out + // If they're in logic for rando, skip setting that flag so they can be purchased repeatedly if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC)) { return; } + switch (this->actor.params) { case SI_BOMBCHU_10_2: gSaveContext.itemGetInf[0] |= 0x40; @@ -1065,6 +1068,7 @@ void EnGirlA_InitializeItemAction(EnGirlA* this, GlobalContext* globalCtx) { this->canBuyFunc = itemEntry->canBuyFunc; this->itemGiveFunc = itemEntry->itemGiveFunc; this->buyEventFunc = itemEntry->buyEventFunc; + // If chus are in logic, make the 10 pack affordable without a wallet upgrade if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && this->getItemId == GI_BOMBCHUS_10) { this->basePrice = 99; From c84654b202a84159b028f78a3e64d0a605d5a46a Mon Sep 17 00:00:00 2001 From: lil David <1337lilDavid@gmail.com> Date: Thu, 1 Sep 2022 09:23:08 -0500 Subject: [PATCH 16/17] Always check n64ddFlag before bgsFlag that order is consistent with the existing condition in EnGo2_GetStateGoronDmtBiggoron --- soh/src/overlays/actors/ovl_En_Go/z_en_go.c | 4 ++-- soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c index 3cadd6afee..4e803af0a4 100644 --- a/soh/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/soh/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -95,7 +95,7 @@ u16 EnGo_GetTextID(GlobalContext* globalCtx, Actor* thisx) { switch (thisx->params & 0xF0) { case 0x90: - if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { + if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) { return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) { @@ -859,7 +859,7 @@ void func_80A405CC(EnGo* this, GlobalContext* globalCtx) { void EnGo_BiggoronActionFunc(EnGo* this, GlobalContext* globalCtx) { if (((this->actor.params & 0xF0) == 0x90) && (this->unk_1E0.unk_00 == 2)) { - if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { + if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) { this->unk_1E0.unk_00 = 0; } else { if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) { diff --git a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c index db11549618..c8b635902a 100644 --- a/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c +++ b/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c @@ -595,7 +595,7 @@ s16 EnGo2_GetStateGoronCityLink(GlobalContext* globalCtx, EnGo2* this) { u16 EnGo2_GetTextIdGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) { Player* player = GET_PLAYER(globalCtx); - if (gSaveContext.bgsFlag && !gSaveContext.n64ddFlag) { + if (!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) { player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK; return 0x305E; } else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) { From a55eb572db92b04565d3bb58bad02591bff01f65 Mon Sep 17 00:00:00 2001 From: briaguya Date: Thu, 1 Sep 2022 12:06:41 -0400 Subject: [PATCH 17/17] fix keysanity related build issue --- .../Enhancements/randomizer/randomizer.cpp | 37 ------------------- 1 file changed, 37 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5af2cb9e7c..d1548ea9b0 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1701,43 +1701,6 @@ bool Randomizer::IsItemVanilla(RandomizerGet randoGet) { case RG_BUY_BOMBS_535: case RG_BUY_RED_POTION_40: case RG_BUY_RED_POTION_50: - //RANDO TODO: Fix this to return false if keysanity is on. - case RG_FOREST_TEMPLE_SMALL_KEY: - case RG_FIRE_TEMPLE_SMALL_KEY: - case RG_WATER_TEMPLE_SMALL_KEY: - case RG_SPIRIT_TEMPLE_SMALL_KEY: - case RG_SHADOW_TEMPLE_SMALL_KEY: - case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: - case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: - case RG_GERUDO_FORTRESS_SMALL_KEY: - case RG_GANONS_CASTLE_SMALL_KEY: - case RG_FOREST_TEMPLE_BOSS_KEY: - case RG_FIRE_TEMPLE_BOSS_KEY: - case RG_WATER_TEMPLE_BOSS_KEY: - case RG_SPIRIT_TEMPLE_BOSS_KEY: - case RG_SHADOW_TEMPLE_BOSS_KEY: - case RG_GANONS_CASTLE_BOSS_KEY: - case RG_DEKU_TREE_COMPASS: - case RG_DODONGOS_CAVERN_COMPASS: - case RG_JABU_JABUS_BELLY_COMPASS: - case RG_FOREST_TEMPLE_COMPASS: - case RG_FIRE_TEMPLE_COMPASS: - case RG_WATER_TEMPLE_COMPASS: - case RG_SPIRIT_TEMPLE_COMPASS: - case RG_SHADOW_TEMPLE_COMPASS: - case RG_BOTTOM_OF_THE_WELL_COMPASS: - case RG_ICE_CAVERN_COMPASS: - case RG_DEKU_TREE_MAP: - case RG_DODONGOS_CAVERN_MAP: - case RG_JABU_JABUS_BELLY_MAP: - case RG_FOREST_TEMPLE_MAP: - case RG_FIRE_TEMPLE_MAP: - case RG_WATER_TEMPLE_MAP: - case RG_SPIRIT_TEMPLE_MAP: - case RG_SHADOW_TEMPLE_MAP: - case RG_BOTTOM_OF_THE_WELL_MAP: - case RG_ICE_CAVERN_MAP: - return true; case RG_FOREST_TEMPLE_SMALL_KEY: case RG_FIRE_TEMPLE_SMALL_KEY: case RG_WATER_TEMPLE_SMALL_KEY: