Shipwright/soh/include/z64save.h
Christopher Leggett 7b08f98b8c
Dual OTR MQ and Vanilla Support (#1694)
* Changes OTR Extraction to have specific mq and nonmq paths.

Also updates the game to load resources according to whether or not
Master Quest or Vanilla is loaded.

* Removes unneeded code from the last commit.

* Fixes some weird formatting in ZRom.c

* Loads oot-mq.otr and patches oot.otr on top, if both are present.

If only one or the other are present, it becomes the only and main OTR.

* Adds ImGui Logic for whether or an MQ Checkbox.

Checkbox checked only specifies whether new saves should be MQ or not.
Checkbox is disabled or force-enabled according to which OTRs are loaded.
Also as a necessity includes tracking what game versions have been loaded
from the OTRs.

* Adds MQ settings logic for Randomizer's ImGui menu.

* Writes Master Quest dungeons to the spoiler log

* Loads MQ Dungeons from spoiler, persists in save, and loads when appropriate.

* Adds logic to prevent loading or creating incompatible rando saves.

* Fixdes some linux build issues and new rando save issues

* Makes appimage create both vanilla and mq otrs

If either rom is present, it makes the corresponding OTR. If both are present,
it will make both. If one OTR is present but both roms are present, it will
create the missing OTR.

* Makes it so a randomized save file will not be marked as MQ.

* Refactors to load all OTRs from MainPath or a specific list.

Also adds the ability to take a std::unordered_set of hashes to
validate each OTR's version file against.

* Fixes a syntax error

* Makes ExtractAssets output Vanilla and MQ OTRs if both roms are present

* Fixes asset generation bug.

* Partially working fix for dual OTR extract_assets

Currently the cmake ExtractAssets target will return with a 1 if you
only end up exporting one type of OTR isntead of both. Haven't found
a great way to only attempt to copy a file if it exists from within
cmake. It does actually correctly copy the OTR that is generated,
despite the error from copying the other one.

Pushing as is for now but will keep investigating.

* Adds oot-mq.otr to the gitignore.

* Makes ExtractAssets not fail on only one rom/OTR.

* Removes PatchesPath from the constructors requiring OTRFiles vector.

* Renames OOT_UNKNOWN to just UNKNOWN to remove OOT specific reference.

* Removes randomizing MQ Dungeons and re-disables MQ rando.

Doing this so the PR can get merged quicker with just the Dual OTR
support and won't need to wait on rando logic to be updated. That
will happen in another PR directly after the merge.

* Update mac startup script for dual otr

* Update soh/macosx/soh-macos.sh

* Update soh/macosx/soh-macos.sh

* Update soh/macosx/soh-macos.sh

* Implements new BinaryReader to fix Linux build issue.

BinaryReader itself comes from https://github.com/Moneyl/BinaryTools
I added a wrapper to adapt it to the ABI from ZAPD's Binary Reader and
add Endianness checking. I also had to copy a handful of other bits and
pieces from ZAPD to make it all function as expected.

* A few edits to the updatream BinaryReader to compile it on Linux.

* Adds the Endianness to the first byte of the version file.

* Fixes Jenkins

* Addresses some of Kenix's comments

* Renames `ReadNullTerminatedString` to `ReadCString`

* Refactors Archive::LoadFile into a private method with more arguments.

* Removes BitConverter and extends existing endianness.h instead.

* Fixes an endianness issue with the version file.

Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
2022-10-16 23:07:35 -04:00

232 lines
7.6 KiB
C

#ifndef Z64SAVE_H
#define Z64SAVE_H
#include "ultra64.h"
#include "z64math.h"
#include "z64audio.h"
#include "soh/Enhancements/randomizer/randomizerTypes.h"
#include "soh/Enhancements/randomizer/randomizer_inf.h"
typedef struct {
/* 0x00 */ u8 buttonItems[8];
/* 0x04 */ u8 cButtonSlots[7];
/* 0x08 */ u16 equipment;
} ItemEquips; // size = 0x0A
typedef struct {
/* 0x00 */ u8 items[24];
/* 0x18 */ s8 ammo[16];
/* 0x28 */ u16 equipment;
/* 0x2C */ u32 upgrades;
/* 0x30 */ u32 questItems;
/* 0x34 */ u8 dungeonItems[20];
/* 0x48 */ s8 dungeonKeys[19];
/* 0x5B */ s8 defenseHearts;
/* 0x5C */ s16 gsTokens;
} Inventory; // size = 0x5E
typedef struct {
/* 0x00 */ u32 chest;
/* 0x04 */ u32 swch;
/* 0x08 */ u32 clear;
/* 0x0C */ u32 collect;
/* 0x10 */ u32 unk;
/* 0x14 */ u32 rooms;
/* 0x18 */ u32 floors;
} SavedSceneFlags; // size = 0x1C
typedef struct {
/* 0x00 */ s16 scene;
/* 0x02 */ Vec3s pos;
/* 0x08 */ s16 angle;
} HorseData; // size = 0x0A
typedef struct {
/* 0x00 */ Vec3f pos;
/* 0x0C */ s16 yaw;
/* 0x0E */ s16 playerParams;
/* 0x10 */ s16 entranceIndex;
/* 0x12 */ u8 roomIndex;
/* 0x13 */ s8 data;
/* 0x14 */ u32 tempSwchFlags;
/* 0x18 */ u32 tempCollectFlags;
} RespawnData; // size = 0x1C
typedef struct {
/* 0x00 */ Vec3i pos;
/* 0x0C */ s32 yaw;
/* 0x10 */ s32 playerParams;
/* 0x14 */ s32 entranceIndex;
/* 0x18 */ s32 roomIndex;
/* 0x1C */ s32 set;
/* 0x20 */ s32 tempSwchFlags;
/* 0x24 */ s32 tempCollectFlags;
} FaroresWindData; // size = 0x28
typedef struct {
RandomizerCheck check;
RandomizerGetData get;
} ItemLocationRando;
typedef struct {
RandomizerCheck check;
char hintText[200];
} HintLocationRando;
typedef struct {
RandomizerSettingKey key;
u8 value;
} RandoSetting;
typedef struct {
/* 0x0000 */ s32 entranceIndex; // start of `save` substruct, originally called "memory"
/* 0x0004 */ s32 linkAge; // 0: Adult; 1: Child
/* 0x0008 */ s32 cutsceneIndex;
/* 0x000C */ u16 dayTime; // "zelda_time"
/* 0x0010 */ s32 nightFlag;
/* 0x0014 */ s32 totalDays;
/* 0x0018 */ s32 bgsDayCount; // increments with totalDays, can be cleared with `Environment_ClearBgsDayCount`
/* 0x0022 */ u16 deaths;
/* 0x0024 */ char playerName[8];
/* 0x002C */ s16 n64ddFlag;
/* 0x002E */ s16 healthCapacity; // "max_life"
/* 0x0030 */ s16 health; // "now_life"
/* 0x0032 */ s8 magicLevel;
/* 0x0033 */ s8 magic;
/* 0x0034 */ s16 rupees;
/* 0x0036 */ u16 swordHealth;
/* 0x0038 */ u16 naviTimer;
/* 0x003A */ u8 magicAcquired;
/* 0x003C */ u8 doubleMagic;
/* 0x003D */ u8 doubleDefense;
/* 0x003E */ u8 bgsFlag;
/* 0x003F */ u8 ocarinaGameRoundNum;
/* 0x0040 */ ItemEquips childEquips;
/* 0x004A */ ItemEquips adultEquips;
/* 0x0054 */ u32 unk_54; // this may be incorrect, currently used for alignement
/* 0x0066 */ s16 savedSceneNum;
/* 0x0068 */ ItemEquips equips;
/* 0x0074 */ Inventory inventory;
/* 0x00D4 */ SavedSceneFlags sceneFlags[124];
/* 0x0E64 */ FaroresWindData fw;
/* 0x0E9C */ s32 gsFlags[6];
/* 0x0EB8 */ s32 highScores[7];
/* 0x0ED4 */ u16 eventChkInf[14]; // "event_chk_inf"
/* 0x0EF0 */ u16 itemGetInf[4]; // "item_get_inf"
/* 0x0EF8 */ u16 infTable[30]; // "inf_table"
/* 0x0F38 */ u32 worldMapAreaData; // "area_arrival"
/* 0x0F40 */ u8 scarecrowCustomSongSet;
/* 0x0F41 */ OcarinaNote scarecrowCustomSong[108];
/* 0x12C5 */ u8 scarecrowSpawnSongSet;
/* 0x12C6 */ OcarinaNote scarecrowSpawnSong[16];
/* 0x1346 */ char unk_1346[0x02];
/* 0x1348 */ HorseData horseData;
/* 0x1354 */ s32 fileNum; // "file_no"
/* 0x1358 */ char unk_1358[0x0004];
/* 0x135C */ s32 gameMode;
/* 0x1360 */ s32 sceneSetupIndex;
/* 0x1364 */ s32 respawnFlag; // "restart_flag"
/* 0x1368 */ RespawnData respawn[3]; // "restart_data"
/* 0x13BC */ f32 entranceSpeed;
/* 0x13C0 */ u16 entranceSound;
/* 0x13C3 */ u8 unk_13C3;
/* 0x13C4 */ s16 dogParams;
/* 0x13C6 */ u8 textTriggerFlags;
/* 0x13C7 */ u8 showTitleCard;
/* 0x13C8 */ s16 nayrusLoveTimer;
/* 0x13CC */ s16 rupeeAccumulator;
/* 0x13CE */ s16 timer1State;
/* 0x13D0 */ s16 timer1Value;
/* 0x13D2 */ s16 timer2State;
/* 0x13D4 */ s16 timer2Value;
/* 0x13D6 */ s16 timerX[2];
/* 0x13DA */ s16 timerY[2];
/* 0x13E0 */ u8 seqId;
/* 0x13E1 */ u8 natureAmbienceId;
/* 0x13E2 */ u8 buttonStatus[9];
/* 0x13E7 */ u8 unk_13E7; // alpha related
/* 0x13E8 */ u16 unk_13E8; // alpha type?
/* 0x13EA */ u16 unk_13EA; // also alpha type?
/* 0x13EC */ u16 unk_13EC; // alpha type counter?
/* 0x13EE */ u16 unk_13EE; // previous alpha type?
/* 0x13F0 */ s16 unk_13F0; // magic related
/* 0x13F2 */ s16 unk_13F2; // magic related
/* 0x13F4 */ s16 unk_13F4; // magic related
/* 0x13F6 */ s16 unk_13F6; // magic related
/* 0x13F8 */ s16 unk_13F8; // magic related
/* 0x13FA */ u16 eventInf[4]; // "event_inf"
/* 0x1402 */ u16 mapIndex; // intended for maps/minimaps but commonly used as the dungeon index
/* 0x1404 */ u16 minigameState;
/* 0x1406 */ u16 minigameScore; // "yabusame_total"
/* 0x1409 */ u8 language; // NTSC 0: Japanese; 1: English | PAL 0: English; 1: German; 2: French
/* 0x140A */ u8 audioSetting;
/* 0x140C */ u8 zTargetSetting; // 0: Switch; 1: Hold
/* 0x140E */ u16 forcedSeqId; // immediately start playing the sequence if set
/* 0x1410 */ u8 unk_1410; // transition related
/* 0x1412 */ u16 nextCutsceneIndex;
/* 0x1414 */ u8 cutsceneTrigger;
/* 0x1415 */ u8 chamberCutsceneNum;
/* 0x1416 */ u16 nextDayTime; // "next_zelda_time"
/* 0x1418 */ u8 fadeDuration;
/* 0x1419 */ u8 unk_1419; // transition related
/* 0x141A */ u16 skyboxTime;
/* 0x141C */ u8 dogIsLost;
/* 0x141D */ u8 nextTransition;
/* 0x1420 */ s16 worldMapArea;
/* 0x1422 */ s16 sunsSongState; // controls the effects of suns song
/* 0x1424 */ s16 healthAccumulator;
uint32_t isMasterQuest;
RandoSetting randoSettings[300];
ItemLocationRando itemLocations[RC_MAX];
HintLocationRando hintLocations[50];
char childAltarText[250];
char adultAltarText[750];
char ganonHintText[150];
char ganonText[250];
u8 seedIcons[5];
u16 randomizerInf[8];
u8 temporaryWeapon;
u16 adultTradeItems;
u8 pendingIceTrapCount;
u8 mqDungeonCount;
} SaveContext; // size = 0x1428
typedef enum {
/* 0x00 */ RESPAWN_MODE_DOWN, /* Normal Void Outs */
/* 0x01 */ RESPAWN_MODE_RETURN, /* Grotto Returnpoints */
/* 0x02 */ RESPAWN_MODE_TOP /* Farore's Wind */
} RespawnMode;
typedef enum {
/* 0x00 */ BTN_ENABLED,
/* 0xFF */ BTN_DISABLED = 0xFF
} ButtonStatus;
typedef enum {
/* 0x00 */ CHAMBER_CS_FOREST,
/* 0x01 */ CHAMBER_CS_FIRE,
/* 0x02 */ CHAMBER_CS_WATER,
/* 0x03 */ CHAMBER_CS_SPIRIT,
/* 0x04 */ CHAMBER_CS_SHADOW,
/* 0x05 */ CHAMBER_CS_LIGHT
} ChamberCutsceneNum;
typedef enum {
/* 0x00 */ HS_HBA, // horseback archery
/* 0x01 */ HS_POE_POINTS,
/* 0x02 */ HS_FISHING,
/* 0x03 */ HS_HORSE_RACE,
/* 0x04 */ HS_MARATHON,
/* 0x05 */ HS_UNK_05,
/* 0x06 */ HS_DAMPE_RACE
} HighScores;
typedef enum {
/* 0 */ SUNSSONG_INACTIVE,
/* 1 */ SUNSSONG_START, // the suns ocarina effect signals that the song has finished playing
/* 2 */ SUNSSONG_SPEED_TIME, // suns was played where time passes, speed up the advancement of time
/* 3 */ SUNSSONG_SPECIAL // time does not advance, but signals the song was played. used for freezing redeads
} SunsSongState;
#endif