summaryrefslogtreecommitdiff
path: root/soh/src/code
diff options
context:
space:
mode:
Diffstat (limited to 'soh/src/code')
-rw-r--r--soh/src/code/z_sram.c383
1 files changed, 2 insertions, 381 deletions
diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c
index 3c8b0e74c..beb3ce147 100644
--- a/soh/src/code/z_sram.c
+++ b/soh/src/code/z_sram.c
@@ -2,10 +2,8 @@
#include "vt.h"
#include <string.h>
-#include <soh/Enhancements/randomizer/randomizerTypes.h>
-#include <soh/Enhancements/randomizer/randomizer_inf.h>
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
-#include "soh/Enhancements/randomizer/adult_trade_shuffle.h"
+#include "soh/Enhancements/randomizer/savefile.h"
#define NUM_DUNGEONS 8
#define NUM_COWS 10
@@ -31,91 +29,6 @@ void Sram_InitDebugSave(void) {
Save_InitFile(true);
}
-// RANDOTODO replace most of these GiveLink functions with calls to
-// Item_Give in z_parameter, we'll need to update Item_Give to ensure
-// nothing breaks when calling it without a valid play first
-void GiveLinkRupees(int numOfRupees) {
- int maxRupeeCount;
- if (CUR_UPG_VALUE(UPG_WALLET) == 0) {
- maxRupeeCount = 99;
- } else if (CUR_UPG_VALUE(UPG_WALLET) == 1) {
- maxRupeeCount = 200;
- } else if (CUR_UPG_VALUE(UPG_WALLET) == 2) {
- maxRupeeCount = 500;
- }
-
- int newRupeeCount = gSaveContext.rupees;
- newRupeeCount += numOfRupees;
-
- if (newRupeeCount > maxRupeeCount) {
- gSaveContext.rupees = maxRupeeCount;
- } else {
- gSaveContext.rupees = newRupeeCount;
- }
-}
-
-void GiveLinkDekuSticks(int howManySticks) {
- int maxStickCount;
- if (CUR_UPG_VALUE(UPG_STICKS) == 0) {
- INV_CONTENT(ITEM_STICK) = ITEM_STICK;
- Inventory_ChangeUpgrade(UPG_STICKS, 1);
- maxStickCount = 10;
- } else if (CUR_UPG_VALUE(UPG_STICKS) == 1) {
- maxStickCount = 10;
- } else if (CUR_UPG_VALUE(UPG_STICKS) == 2) {
- maxStickCount = 20;
- } else if (CUR_UPG_VALUE(UPG_STICKS) == 3) {
- maxStickCount = 30;
- }
-
- if ((AMMO(ITEM_STICK) + howManySticks) > maxStickCount) {
- AMMO(ITEM_STICK) = maxStickCount;
- } else {
- AMMO(ITEM_STICK) += howManySticks;
- }
-}
-
-void GiveLinkDekuNuts(int howManyNuts) {
- int maxNutCount;
- if (CUR_UPG_VALUE(UPG_NUTS) == 0) {
- INV_CONTENT(ITEM_NUT) = ITEM_NUT;
- Inventory_ChangeUpgrade(UPG_NUTS, 1);
- maxNutCount = 20;
- } else if (CUR_UPG_VALUE(UPG_NUTS) == 1) {
- maxNutCount = 20;
- } else if (CUR_UPG_VALUE(UPG_NUTS) == 2) {
- maxNutCount = 30;
- } else if (CUR_UPG_VALUE(UPG_NUTS) == 3) {
- maxNutCount = 40;
- }
-
- if ((AMMO(ITEM_NUT) + howManyNuts) > maxNutCount) {
- AMMO(ITEM_NUT) = maxNutCount;
- } else {
- AMMO(ITEM_NUT) += howManyNuts;
- }
-}
-
-void GiveLinksPocketItem() {
- if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING) {
- GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
-
- if (getItemEntry.modIndex == MOD_NONE) {
- if (getItemEntry.getItemId == GI_SWORD_BGS) {
- gSaveContext.bgsFlag = true;
- }
- Item_Give(NULL, getItemEntry.itemId);
- } else if (getItemEntry.modIndex == MOD_RANDOMIZER) {
- if (getItemEntry.getItemId == RG_ICE_TRAP) {
- gSaveContext.pendingIceTrapCount++;
- GameInteractor_ExecuteOnItemReceiveHooks(getItemEntry);
- } else {
- Randomizer_Item_Give(NULL, getItemEntry);
- }
- }
- }
-}
-
/**
* Copy save currently on the buffer to Save Context and complete various tasks to open the save.
* This includes:
@@ -305,299 +218,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
fileChooseCtx->n64ddFlag = 1;
gSaveContext.n64ddFlag = 1;
- // Sets all rando flags to false
- for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) {
- gSaveContext.randomizerInf[i] = 0;
- }
-
- // If any trials aren't required, set them as completed
- for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) {
- if (!Randomizer_IsTrialRequired(i)) {
- Flags_SetRandomizerInf(i);
- }
- }
-
- // Set Cutscene flags to skip them
- gSaveContext.eventChkInf[0xC] |= 0x10; // returned to tot with medallions
- gSaveContext.eventChkInf[0xC] |= 0x20; //sheik at tot pedestal
- gSaveContext.eventChkInf[4] |= 0x20; // master sword pulled
- gSaveContext.eventChkInf[4] |= 0x8000; // entered master sword chamber
- gSaveContext.infTable[0] |= 1;
- if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) {
- gSaveContext.infTable[17] |= 0x400; // Darunia in Fire Temple
- }
- gSaveContext.cutsceneIndex = 0;
- Flags_SetEventChkInf(5);
-
- // Skip boss cutscenes
- gSaveContext.eventChkInf[7] |= 1; // gohma
- gSaveContext.eventChkInf[7] |= 2; // dodongo
- gSaveContext.eventChkInf[7] |= 4; // phantom ganon
- gSaveContext.eventChkInf[7] |= 8; // volvagia
- gSaveContext.eventChkInf[7] |= 0x10; // morpha
- gSaveContext.eventChkInf[7] |= 0x20; // twinrova
- gSaveContext.eventChkInf[7] |= 0x40; // barinade
- gSaveContext.eventChkInf[7] |= 0x80; // bongo bongo
-
- // Skip cutscene before Nabooru fight
- gSaveContext.eventChkInf[3] |= 0x800;
- gSaveContext.eventChkInf[12] |= 1;
-
- // shuffle adult trade quest
- if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) {
- gSaveContext.adultTradeItems = 0;
- }
-
- // Starts pending ice traps out at 0 before potentially incrementing them down the line.
- gSaveContext.pendingIceTrapCount = 0;
-
- // Give Link's pocket item
- GiveLinksPocketItem();
-
- int openForest = Randomizer_GetSettingValue(RSK_FOREST);
- switch (openForest) {
- case RO_FOREST_CLOSED:
- break;
- case RO_FOREST_CLOSED_DEKU:
- Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
- break;
- case RO_FOREST_OPEN:
- Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_KOKIRI_EMERALD_DEKU_TREE_DEAD);
- Flags_SetEventChkInf(EVENTCHKINF_SHOWED_MIDO_SWORD_SHIELD);
- break;
- }
-
- int startingAge = Randomizer_GetSettingValue(RSK_STARTING_AGE);
- switch (startingAge) {
- case RO_AGE_ADULT: //Adult
- gSaveContext.linkAge = 0;
- gSaveContext.entranceIndex = 0x5F4;
- gSaveContext.savedSceneNum = SCENE_SPOT20; //Set scene num manually to ToT
- break;
- case RO_AGE_CHILD: //Child
- gSaveContext.linkAge = 1;
- gSaveContext.savedSceneNum = -1;
- break;
- default:
- break;
- }
-
- if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS)) {
- // Override the spawn entrance so entrance rando can take control,
- // and to prevent remember save location from breaking inital spawn
- gSaveContext.entranceIndex = -1;
- }
-
- int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME);
- switch (doorOfTime) {
- case RO_DOOROFTIME_OPEN:
- gSaveContext.eventChkInf[4] |= 0x800;
- break;
- }
-
- if (Randomizer_GetSettingValue(RSK_KAK_GATE) == RO_KAK_GATE_OPEN) {
- gSaveContext.infTable[7] |= 0x40;
- }
-
- if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) Item_Give(NULL, ITEM_SWORD_KOKIRI);
- if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) Item_Give(NULL, ITEM_SHIELD_DEKU);
-
- if (Randomizer_GetSettingValue(RSK_STARTING_ZELDAS_LULLABY)) Item_Give(NULL, ITEM_SONG_LULLABY);
- if (Randomizer_GetSettingValue(RSK_STARTING_EPONAS_SONG)) Item_Give(NULL, ITEM_SONG_EPONA);
- if (Randomizer_GetSettingValue(RSK_STARTING_SARIAS_SONG)) Item_Give(NULL, ITEM_SONG_SARIA);
- if (Randomizer_GetSettingValue(RSK_STARTING_SUNS_SONG)) Item_Give(NULL, ITEM_SONG_SUN);
- if (Randomizer_GetSettingValue(RSK_STARTING_SONG_OF_TIME)) Item_Give(NULL, ITEM_SONG_TIME);
- if (Randomizer_GetSettingValue(RSK_STARTING_SONG_OF_STORMS)) Item_Give(NULL, ITEM_SONG_STORMS);
- if (Randomizer_GetSettingValue(RSK_STARTING_MINUET_OF_FOREST)) Item_Give(NULL, ITEM_SONG_MINUET);
- if (Randomizer_GetSettingValue(RSK_STARTING_BOLERO_OF_FIRE)) Item_Give(NULL, ITEM_SONG_BOLERO);
- if (Randomizer_GetSettingValue(RSK_STARTING_SERENADE_OF_WATER)) Item_Give(NULL, ITEM_SONG_SERENADE);
- if (Randomizer_GetSettingValue(RSK_STARTING_REQUIEM_OF_SPIRIT)) Item_Give(NULL, ITEM_SONG_REQUIEM);
- if (Randomizer_GetSettingValue(RSK_STARTING_NOCTURNE_OF_SHADOW)) Item_Give(NULL, ITEM_SONG_NOCTURNE);
- if (Randomizer_GetSettingValue(RSK_STARTING_PRELUDE_OF_LIGHT)) Item_Give(NULL, ITEM_SONG_PRELUDE);
-
- if(Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN)) {
- gSaveContext.inventory.questItems |= gBitFlags[QUEST_SKULL_TOKEN];
- gSaveContext.inventory.gsTokens = Randomizer_GetSettingValue(RSK_STARTING_SKULLTULA_TOKEN);
- }
-
- if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) {
- INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
- }
-
- if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
- uint32_t mapBitMask = 1 << 1;
- uint32_t compassBitMask = 1 << 2;
- uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask;
- for(int scene = SCENE_YDAN; scene <= SCENE_ICE_DOUKUTO; scene++) {
- gSaveContext.inventory.dungeonItems[scene] |= startingDungeonItemsBitMask;
- }
- }
-
- if (Randomizer_GetSettingValue(RSK_STARTING_CONSUMABLES)) {
- GiveLinkDekuSticks(10);
- GiveLinkDekuNuts(20);
- }
-
- if(Randomizer_GetSettingValue(RSK_SKIP_CHILD_ZELDA)) {
- GetItemEntry getItem = Randomizer_GetItemFromKnownCheck(RC_SONG_FROM_IMPA, RG_ZELDAS_LULLABY);
- s32 giid = getItem.getItemId;
-
- if (getItem.modIndex == MOD_NONE) {
- if (getItem.getItemId == GI_SWORD_BGS) {
- gSaveContext.bgsFlag = true;
- }
- Item_Give(NULL, getItem.itemId);
- } else if (getItem.modIndex == MOD_RANDOMIZER) {
- if (getItem.getItemId == RG_ICE_TRAP) {
- gSaveContext.pendingIceTrapCount++;
- GameInteractor_ExecuteOnItemReceiveHooks(getItem);
- } else {
- Randomizer_Item_Give(NULL, getItem);
- }
- }
-
- // malon/talon back at ranch
- gSaveContext.eventChkInf[1] |= (1 << 0);
- gSaveContext.eventChkInf[1] |= (1 << 2);
- gSaveContext.eventChkInf[1] |= (1 << 3);
- gSaveContext.eventChkInf[1] |= (1 << 4);
-
- // Set "Got Zelda's Letter" flag. Also ensures Saria is back at SFM. TODO: Is this flag used for anything else?
- Flags_SetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER);
-
- // Got item from impa
- gSaveContext.eventChkInf[5] |= 0x200;
-
- // set this at the end to ensure we always start with the letter
- // this is for the off chance we got the weird egg from impa (which should never happen)
- INV_CONTENT(ITEM_LETTER_ZELDA) = ITEM_LETTER_ZELDA;
- }
-
- if (Randomizer_GetSettingValue(RSK_FULL_WALLETS)) {
- GiveLinkRupees(9001);
- }
-
- if (Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
- gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = FOREST_TEMPLE_SMALL_KEY_MAX; // Forest
- gSaveContext.sohStats.dungeonKeys[SCENE_BMORI1] = FOREST_TEMPLE_SMALL_KEY_MAX; // Forest
- gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = FIRE_TEMPLE_SMALL_KEY_MAX; // Fire
- gSaveContext.sohStats.dungeonKeys[SCENE_HIDAN] = FIRE_TEMPLE_SMALL_KEY_MAX; // Fire
- gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] = WATER_TEMPLE_SMALL_KEY_MAX; // Water
- gSaveContext.sohStats.dungeonKeys[SCENE_MIZUSIN] = WATER_TEMPLE_SMALL_KEY_MAX; // Water
- gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = SPIRIT_TEMPLE_SMALL_KEY_MAX; // Spirit
- gSaveContext.sohStats.dungeonKeys[SCENE_JYASINZOU] = SPIRIT_TEMPLE_SMALL_KEY_MAX; // Spirit
- gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] = SHADOW_TEMPLE_SMALL_KEY_MAX; // Shadow
- gSaveContext.sohStats.dungeonKeys[SCENE_HAKADAN] = SHADOW_TEMPLE_SMALL_KEY_MAX; // Shadow
- gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] = BOTTOM_OF_THE_WELL_SMALL_KEY_MAX; // BotW
- gSaveContext.sohStats.dungeonKeys[SCENE_HAKADANCH] = BOTTOM_OF_THE_WELL_SMALL_KEY_MAX; // BotW
- gSaveContext.inventory.dungeonKeys[SCENE_MEN] = GERUDO_TRAINING_GROUNDS_SMALL_KEY_MAX; // GTG
- gSaveContext.sohStats.dungeonKeys[SCENE_MEN] = GERUDO_TRAINING_GROUNDS_SMALL_KEY_MAX; // GTG
- gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = GANONS_CASTLE_SMALL_KEY_MAX; // Ganon
- gSaveContext.sohStats.dungeonKeys[SCENE_GANONTIKA] = GANONS_CASTLE_SMALL_KEY_MAX; // Ganon
- } else if (Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_VANILLA) {
- // Logic cannot handle vanilla key layout in some dungeons
- // this is because vanilla expects the dungeon major item to be
- // locked behind the keys, which is not always true in rando.
- // We can resolve this by starting with some extra keys
- if (ResourceMgr_IsSceneMasterQuest(SCENE_JYASINZOU)) {
- // MQ Spirit needs 3 keys
- gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 3;
- gSaveContext.sohStats.dungeonKeys[SCENE_JYASINZOU] = 3;
- }
- }
-
- if(Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
- gSaveContext.inventory.dungeonItems[SCENE_BMORI1] |= 1; // Forest
- gSaveContext.inventory.dungeonItems[SCENE_HIDAN] |= 1; // Fire
- gSaveContext.inventory.dungeonItems[SCENE_MIZUSIN] |= 1; // Water
- gSaveContext.inventory.dungeonItems[SCENE_JYASINZOU] |= 1; // Spirit
- gSaveContext.inventory.dungeonItems[SCENE_HAKADAN] |= 1; // Shadow
- }
-
- if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == RO_GANON_BOSS_KEY_STARTWITH) {
- gSaveContext.inventory.dungeonItems[SCENE_GANON] |= 1;
- }
-
- HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT));
-
- if(Randomizer_GetSettingValue(RSK_SKIP_EPONA_RACE)) {
- gSaveContext.eventChkInf[1] |= (1 << 8);
- }
-
- // skip the z target talk instructions by the kokiri shop
- gSaveContext.sceneFlags[85].swch |= (1 << 0x1F);
-
- //Ruto already met in jabu and spawns down the hole immediately
- gSaveContext.infTable[20] |= 2;
- gSaveContext.infTable[20] |= 4;
-
- // Go away ruto (water temple first cutscene)
- gSaveContext.sceneFlags[SCENE_MIZUSIN].swch |= (1 << 0x10);
-
- // Open lowest Vanilla Fire Temple locked door (to prevent key logic lockouts)
- // Not done on keysanity since this lockout is a non issue when Fire keys can be found outside the temple
- u8 keysanity = Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE ||
- Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_OVERWORLD ||
- Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANY_DUNGEON;
- if (!ResourceMgr_IsSceneMasterQuest(SCENE_HIDAN) && !keysanity) {
- gSaveContext.sceneFlags[SCENE_HIDAN].swch |= (1 << 0x17);
- }
-
- // Opens locked Water Temple door in vanilla to prevent softlocks
- // West door on the middle level that leads to the water raising thing
- // Happens in 3DS rando and N64 rando as well
- if (!ResourceMgr_IsSceneMasterQuest(SCENE_MIZUSIN)) {
- gSaveContext.sceneFlags[SCENE_MIZUSIN].swch |= (1 << 0x15);
- }
-
- // Skip intro cutscene when bombing mud wall in Dodongo's cavern
- // this also makes the lower jaw render, and the eyes react to explosives
- Flags_SetEventChkInf(0xB0);
-
- // skip verbose lake owl, skip to "i'm on my way back to the castle"
- gSaveContext.infTable[25] |= 0x20;
-
- if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_FAST ||
- Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_OPEN) {
- gSaveContext.eventChkInf[9] |= 2;
- gSaveContext.eventChkInf[9] |= 4;
- gSaveContext.eventChkInf[9] |= 8;
- gSaveContext.sceneFlags[12].swch |= (1 << 0x02);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x03);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x04);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x06);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x07);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x08);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x10);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x12);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x13);
- gSaveContext.sceneFlags[12].collect |= (1 << 0x0A);
- gSaveContext.sceneFlags[12].collect |= (1 << 0x0E);
- gSaveContext.sceneFlags[12].collect |= (1 << 0x0F);
- }
-
- if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_OPEN) {
- gSaveContext.eventChkInf[9] |= 1;
- gSaveContext.sceneFlags[12].swch |= (1 << 0x01);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x05);
- gSaveContext.sceneFlags[12].swch |= (1 << 0x11);
- gSaveContext.sceneFlags[12].collect |= (1 << 0x0C);
-
- if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) {
- Item_Give(NULL, ITEM_GERUDO_CARD);
- }
- }
-
- // complete mask quest
- if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) {
- gSaveContext.infTable[7] |= 0x80; // Soldier Wears Keaton Mask
- gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask
- gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask
- gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask
- gSaveContext.itemGetInf[3] |= 0x800; // bunny hood related
- gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth
- gSaveContext.eventChkInf[8] |= 0x8000; // sold all masks
- }
+ Randomizer_InitSaveFile();
}
Save_SaveFile();