mirror of https://github.com/zeldaret/mm.git
1703 lines
70 KiB
C
1703 lines
70 KiB
C
#include "global.h"
|
|
#include "overlays/gamestates/ovl_file_choose/z_file_choose.h"
|
|
|
|
void func_80146EBC(SramContext* sramCtx, s32 curPage, s32 numPages);
|
|
void func_80147314(SramContext* sramCtx, s32 fileNum);
|
|
void func_80147414(SramContext* sramCtx, s32 fileNum, s32 arg2);
|
|
|
|
#define CHECK_NEWF(newf) \
|
|
((newf)[0] != 'Z' || (newf)[1] != 'E' || (newf)[2] != 'L' || (newf)[3] != 'D' || (newf)[4] != 'A' || \
|
|
(newf)[5] != '3')
|
|
|
|
// default scene flags (?)
|
|
// indices of subarray:
|
|
// - 0: switch0
|
|
// - 1: switch1
|
|
// - 2: chest
|
|
// - 3: collectible
|
|
u32 D_801C5FC0[SCENE_MAX][4] = {
|
|
{ 0xC00, 0, 0, 0x40000000 }, // SCENE_20SICHITAI2
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_1
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_2
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_3
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_4
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_5
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_6
|
|
{ 0, 0, 0, 0xC04 }, // SCENE_KAKUSIANA
|
|
{ 0, 0, 0, 0 }, // SCENE_SPOT00
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_9
|
|
{ 0, 0, 0, 0 }, // SCENE_WITCH_SHOP
|
|
{ 0, 0, 0, 0x80000000 }, // SCENE_LAST_BS
|
|
{ 0, 0, 0, 0x80000000 }, // SCENE_HAKASHITA
|
|
{ 0, 0, 0, 0 }, // SCENE_AYASHIISHOP
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_E
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_F
|
|
{ 0, 0, 0, 0 }, // SCENE_OMOYA
|
|
{ 0, 0, 0, 0 }, // SCENE_BOWLING
|
|
{ 0, 0, 0, 0 }, // SCENE_SONCHONOIE
|
|
{ 0x100000, 0, 0, 0x40000002 }, // SCENE_IKANA
|
|
{ 0, 0, 0, 0 }, // SCENE_KAIZOKU
|
|
{ 0, 0, 0, 0 }, // SCENE_MILK_BAR
|
|
{ 0x4000000, 0, 0, 0 }, // SCENE_INISIE_N
|
|
{ 2, 0, 0, 0 }, // SCENE_TAKARAYA
|
|
{ 0x4000000, 0, 0, 0 }, // SCENE_INISIE_R
|
|
{ 0, 0, 0, 0 }, // SCENE_OKUJOU
|
|
{ 0xF, 0, 0, 0 }, // SCENE_OPENINGDAN
|
|
{ 0x70B000, 0, 0, 0 }, // SCENE_MITURIN
|
|
{ 0, 0, 0, 0 }, // SCENE_13HUBUKINOMITI
|
|
{ 0, 0x80000000, 0, 0x400 }, // SCENE_CASTLE
|
|
{ 0, 0, 0, 0 }, // SCENE_DEKUTES
|
|
{ 0, 0, 0, 0x80000000 }, // SCENE_MITURIN_BS
|
|
{ 0, 0, 0, 0 }, // SCENE_SYATEKI_MIZU
|
|
{ 0x1A00020, 0, 0, 0 }, // SCENE_HAKUGIN
|
|
{ 0x400, 0, 0, 0 }, // SCENE_ROMANYMAE
|
|
{ 0, 0, 0, 0x1000 }, // SCENE_PIRATE
|
|
{ 0, 0, 0, 0 }, // SCENE_SYATEKI_MORI
|
|
{ 0, 0, 0, 2 }, // SCENE_SINKAI
|
|
{ 0x400, 0, 0, 0 }, // SCENE_YOUSEI_IZUMI
|
|
{ 0, 0, 0, 0 }, // SCENE_KINSTA1
|
|
{ 0, 0, 0, 0x80000000 }, // SCENE_KINDAN2
|
|
{ 0, 0, 0, 0 }, // SCENE_TENMON_DAI
|
|
{ 0, 0, 0, 2 }, // SCENE_LAST_DEKU
|
|
{ 0, 0, 0, 0x40000000 }, // SCENE_22DEKUCITY
|
|
{ 0, 0, 0, 0 }, // SCENE_KAJIYA
|
|
{ 0x10, 0, 0, 0 }, // SCENE_00KEIKOKU
|
|
{ 3, 0, 0, 0 }, // SCENE_POSTHOUSE
|
|
{ 0, 0, 0, 0 }, // SCENE_LABO
|
|
{ 0, 0, 0, 0x80000000 }, // SCENE_DANPEI2TEST
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_31
|
|
{ 0, 0, 0, 0 }, // SCENE_16GORON_HOUSE
|
|
{ 0, 0, 0, 0 }, // SCENE_33ZORACITY
|
|
{ 0, 0, 0, 0 }, // SCENE_8ITEMSHOP
|
|
{ 0, 0, 0, 0 }, // SCENE_F01
|
|
{ 0, 0, 0, 0x80000000 }, // SCENE_INISIE_BS
|
|
{ 0x100400, 0, 0, 0x22 }, // SCENE_30GYOSON
|
|
{ 0x400, 0, 0, 0x80 }, // SCENE_31MISAKI
|
|
{ 0, 0, 0, 0 }, // SCENE_TAKARAKUJI
|
|
{ 0, 0, 0, 0 }, // SCENE_UNSET_3A
|
|
{ 0x400, 0, 0, 0 }, // SCENE_TORIDE
|
|
{ 0, 0, 0, 0 }, // SCENE_FISHERMAN
|
|
{ 0, 0, 0, 0 }, // SCENE_GORONSHOP
|
|
{ 0, 0, 0, 0 }, // SCENE_DEKU_KING
|
|
{ 0, 0, 0, 2 }, // SCENE_LAST_GORON
|
|
{ 0, 0, 0, 0x80000002 }, // SCENE_24KEMONOMITI
|
|
{ 0, 0, 0, 0 }, // SCENE_F01_B
|
|
{ 0, 0, 0, 0 }, // SCENE_F01C
|
|
{ 0, 0, 0, 0 }, // SCENE_BOTI
|
|
{ 0, 0, 0, 0x80000000 }, // SCENE_HAKUGIN_BS
|
|
{ 0xC00, 0, 0, 0x40000000 }, // SCENE_20SICHITAI
|
|
{ 0x102, 0, 0, 0x400 }, // SCENE_21MITURINMAE
|
|
{ 0, 0, 0, 2 }, // SCENE_LAST_ZORA
|
|
{ 0, 0, 0, 0x40000000 }, // SCENE_11GORONNOSATO2
|
|
{ 0x70, 0, 0, 0 }, // SCENE_SEA
|
|
{ 0, 0, 0, 0 }, // SCENE_35TAKI
|
|
{ 0, 0, 0, 0 }, // SCENE_REDEAD
|
|
{ 0, 0, 0, 0x40000000 }, // SCENE_BANDROOM
|
|
{ 0, 0, 0, 0x40000000 }, // SCENE_11GORONNOSATO
|
|
{ 0, 0, 0, 0 }, // SCENE_GORON_HAKA
|
|
{ 0, 0, 0, 0 }, // SCENE_SECOM
|
|
{ 0x100000, 0, 0, 0x80000000 }, // SCENE_10YUKIYAMANOMURA
|
|
{ 0, 0, 0, 0 }, // SCENE_TOUGITES
|
|
{ 0, 0, 0, 0 }, // SCENE_DANPEI
|
|
{ 0, 0, 0, 0 }, // SCENE_IKANAMAE
|
|
{ 0, 0, 0, 0 }, // SCENE_DOUJOU
|
|
{ 0, 0, 0, 0 }, // SCENE_MUSICHOUSE
|
|
{ 0, 0, 0, 0 }, // SCENE_IKNINSIDE
|
|
{ 0, 0, 0, 0 }, // SCENE_MAP_SHOP
|
|
{ 0x400, 0, 0, 0 }, // SCENE_F40
|
|
{ 0x400, 0, 0, 0 }, // SCENE_F41
|
|
{ 0x100000, 0, 0, 0x80000000 }, // SCENE_10YUKIYAMANOMURA2
|
|
{ 0, 0, 0, 0x100 }, // SCENE_14YUKIDAMANOMITI
|
|
{ 0x400, 0, 0, 0 }, // SCENE_12HAKUGINMAE
|
|
{ 0, 0, 0, 0x80 }, // SCENE_17SETUGEN
|
|
{ 0, 0, 0, 0x80 }, // SCENE_17SETUGEN2
|
|
{ 0, 0, 0, 0x80000000 }, // SCENE_SEA_BS
|
|
{ 0, 0, 0, 0x400 }, // SCENE_RANDOM
|
|
{ 0, 0, 0, 0 }, // SCENE_YADOYA
|
|
{ 0, 0, 0, 0 }, // SCENE_KONPEKI_ENT
|
|
{ 1, 0, 0, 0 }, // SCENE_INSIDETOWER
|
|
{ 0, 0, 0, 0 }, // SCENE_26SARUNOMORI
|
|
{ 0, 0, 0, 0 }, // SCENE_LOST_WOODS
|
|
{ 0, 0, 0, 2 }, // SCENE_LAST_LINK
|
|
{ 0, 0, 0, 0 }, // SCENE_SOUGEN
|
|
{ 0, 0, 0, 0 }, // SCENE_BOMYA
|
|
{ 0, 0, 0, 0 }, // SCENE_KYOJINNOMA
|
|
{ 0, 0, 0, 0 }, // SCENE_KOEPONARACE
|
|
{ 0, 0, 0, 0 }, // SCENE_GORONRACE
|
|
{ 1, 0, 0, 0 }, // SCENE_TOWN
|
|
{ 0, 0, 0, 0 }, // SCENE_ICHIBA
|
|
{ 0, 0, 0, 0x400 }, // SCENE_BACKTOWN
|
|
{ 0x100000, 0, 0, 0x400 }, // SCENE_CLOCKTOWER
|
|
{ 0, 0, 1, 0 }, // SCENE_ALLEY
|
|
};
|
|
|
|
// Related to weekEventReg
|
|
u16 D_801C66D0[ARRAY_COUNT(gSaveContext.save.weekEventReg)] = {
|
|
0xFFFC, 0xFFFF, 0xFFFF, 0xFFFF, 0, 0, 0, 0xC000, 0xC00, 0, 0xC0, 0, 0x300,
|
|
0x3000, 0xC000, 0xC00, 0, 0, 0, 0, 0, 0, 0xC00C, 0xC00C, 0xC008, 3,
|
|
0x3000, 0, 0, 0, 0xFF00, 0xC3F, 0x3F, 0, 0, 0xCFFF, 0, 0, 0xC00,
|
|
0xC00, 0, 0xC0, 0, 0, 0, 0, 0, 0, 0, 0, 0x3C, 0x20,
|
|
0, 0x300C, 0x3000, 0, 0xC, 0xC0, 0, 0xFF0, 0x300, 0, 0, 0xC00, 0,
|
|
0, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xC0, 0, 0xC000, 0, 3,
|
|
0, 0xC000, 0, 0xC0, 0x300, 0, 0, 0, 0xC000, 0xFFF0, 0, 0, 0x300,
|
|
0, 0xC000, 0xF0, 0, 0, 0, 0, 0, 0,
|
|
};
|
|
|
|
// used in other files
|
|
s32 D_801C6798[] = {
|
|
0x00000020, 0x00001470, 0x000028C0, 0x00003D10, 0x00005160, 0x000065B0,
|
|
};
|
|
|
|
u8 gAmmoItems[] = {
|
|
ITEM_NONE, // SLOT_OCARINA
|
|
ITEM_BOW, // SLOT_BOW
|
|
ITEM_NONE, // SLOT_ARROW_FIRE
|
|
ITEM_NONE, // SLOT_ARROW_ICE
|
|
ITEM_NONE, // SLOT_ARROW_LIGHT
|
|
ITEM_NONE, // SLOT_TRADE_DEED
|
|
ITEM_BOMB, // SLOT_BOMB
|
|
ITEM_BOMBCHU, // SLOT_BOMBCHU
|
|
ITEM_STICK, // SLOT_STICK
|
|
ITEM_NUT, // SLOT_NUT
|
|
ITEM_MAGIC_BEANS, // SLOT_MAGIC_BEANS
|
|
ITEM_NONE, // SLOT_TRADE_KEY_MAMA
|
|
ITEM_POWDER_KEG, // SLOT_POWDER_KEG
|
|
ITEM_PICTO_BOX, // SLOT_PICTO_BOX
|
|
ITEM_NONE, // SLOT_LENS
|
|
ITEM_NONE, // SLOT_HOOKSHOT
|
|
ITEM_NONE, // SLOT_SWORD_GREAT_FAIRY
|
|
ITEM_NONE, // SLOT_TRADE_COUPLE
|
|
ITEM_NONE, // SLOT_BOTTLE_1
|
|
ITEM_NONE, // SLOT_BOTTLE_2
|
|
ITEM_NONE, // SLOT_BOTTLE_3
|
|
ITEM_NONE, // SLOT_BOTTLE_4
|
|
ITEM_NONE, // SLOT_BOTTLE_5
|
|
ITEM_NONE, // SLOT_BOTTLE_6
|
|
};
|
|
|
|
s32 D_801C67C8[] = { 0, 0x40, 0x80, 0xC0, 0x100, 0x180, 0x200, 0x280 };
|
|
|
|
s32 D_801C67E8[] = { 0x300, 0x380 };
|
|
|
|
s32 D_801C67F0[] = { 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80 };
|
|
|
|
s32 D_801C6810[] = { 1, 1 };
|
|
|
|
s32 D_801C6818[] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 };
|
|
|
|
s32 D_801C6838[] = { 1, 1 };
|
|
|
|
s32 D_801C6840[] = { 0x100, 0x180, 0x200, 0x280 };
|
|
|
|
s32 D_801C6850[] = { 0x80, 0x80, 0x80, 0x80, 0x300, 0x380, 1, 1 };
|
|
|
|
s32 D_801C6870[] = {
|
|
sizeof(Save),
|
|
sizeof(Save),
|
|
sizeof(Save),
|
|
sizeof(Save),
|
|
offsetof(SaveContext, fileNum),
|
|
offsetof(SaveContext, fileNum),
|
|
offsetof(SaveContext, fileNum),
|
|
offsetof(SaveContext, fileNum),
|
|
};
|
|
|
|
u8 D_801C6890[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 };
|
|
|
|
u16 D_801F6AF0;
|
|
u8 D_801F6AF2;
|
|
|
|
void Sram_ActivateOwl(u8 owlId) {
|
|
gSaveContext.save.playerData.owlActivationFlags =
|
|
((void)0, gSaveContext.save.playerData.owlActivationFlags) | (u16)gBitFlags[owlId];
|
|
|
|
if (gSaveContext.save.playerData.unk_20 == 0xFF) {
|
|
gSaveContext.save.playerData.unk_20 = owlId;
|
|
}
|
|
}
|
|
|
|
void Sram_ClearHighscores(void) {
|
|
gSaveContext.save.unk_EE8 = (gSaveContext.save.unk_EE8 & 0xFFFF) | 0x130000;
|
|
gSaveContext.save.unk_EE8 = (gSaveContext.save.unk_EE8 & 0xFFFF0000) | 0xA;
|
|
gSaveContext.save.horseBackBalloonHighScore = 6000; // 60 seconds
|
|
SET_TOWN_SHOOTING_GALLERY_HIGH_SCORE(39);
|
|
SET_SWAMP_SHOOTING_GALLERY_HIGH_SCORE(10);
|
|
|
|
gSaveContext.save.dekuPlaygroundHighScores[0] = 7500; // 75 seconds
|
|
gSaveContext.save.dekuPlaygroundHighScores[1] = 7500; // 75 seconds
|
|
gSaveContext.save.dekuPlaygroundHighScores[2] = 7600; // 76 seconds
|
|
}
|
|
|
|
/**
|
|
* Clears specific weekEventReg flags. Used by the "Dawn of the First Day" message
|
|
*/
|
|
void Sram_ClearFlagsAtDawnOfTheFirstDay(void) {
|
|
// Unconfirmed: "Link the Goron Claims His Reservation: 4:30 PM"
|
|
gSaveContext.save.weekEventReg[55] &= (u8)~2;
|
|
// Unconfirmed: "Postman fleeing town"
|
|
gSaveContext.save.weekEventReg[90] &= (u8)~1;
|
|
// Unconfirmed: "Postman is about to flee"
|
|
gSaveContext.save.weekEventReg[89] &= (u8)~0x40;
|
|
// Unconfirmed: "Postman has delivered priority mail"
|
|
gSaveContext.save.weekEventReg[89] &= (u8)~8;
|
|
// Unconfirmed: "Postman showing priority mail to Madame"
|
|
gSaveContext.save.weekEventReg[85] &= (u8)~0x80;
|
|
}
|
|
|
|
/**
|
|
* Used by Song of Time (when clicking "Yes") and (indirectly) by the "Dawn of the New Day" cutscene
|
|
*/
|
|
void Sram_SaveEndOfCycle(PlayState* play) {
|
|
s16 sceneNum;
|
|
s32 j;
|
|
s32 i;
|
|
u8 slot;
|
|
u8 item;
|
|
|
|
gSaveContext.save.daySpeed = 0;
|
|
gSaveContext.save.daysElapsed = 0;
|
|
gSaveContext.save.day = 0;
|
|
gSaveContext.save.time = CLOCK_TIME(6, 0) - 1;
|
|
|
|
gSaveContext.save.playerData.deaths++;
|
|
if (gSaveContext.save.playerData.deaths > 999) {
|
|
gSaveContext.save.playerData.deaths = 999;
|
|
}
|
|
|
|
sceneNum = Play_GetOriginalSceneNumber(play->sceneNum);
|
|
Play_SaveCycleSceneFlags(&play->state);
|
|
|
|
play->actorCtx.flags.chest &= D_801C5FC0[sceneNum][2];
|
|
play->actorCtx.flags.switches[0] &= D_801C5FC0[sceneNum][0];
|
|
play->actorCtx.flags.switches[1] &= D_801C5FC0[sceneNum][1];
|
|
play->actorCtx.flags.collectible[0] &= D_801C5FC0[sceneNum][3];
|
|
play->actorCtx.flags.clearedRoom = 0;
|
|
|
|
for (i = 0; i < SCENE_MAX; i++) {
|
|
gSaveContext.cycleSceneFlags[i].switch0 = ((void)0, gSaveContext.cycleSceneFlags[i].switch0) & D_801C5FC0[i][0];
|
|
gSaveContext.cycleSceneFlags[i].switch1 = ((void)0, gSaveContext.cycleSceneFlags[i].switch1) & D_801C5FC0[i][1];
|
|
gSaveContext.cycleSceneFlags[i].chest = ((void)0, gSaveContext.cycleSceneFlags[i].chest) & D_801C5FC0[i][2];
|
|
gSaveContext.cycleSceneFlags[i].collectible =
|
|
((void)0, gSaveContext.cycleSceneFlags[i].collectible) & D_801C5FC0[i][3];
|
|
gSaveContext.cycleSceneFlags[i].clearedRoom = 0;
|
|
gSaveContext.save.permanentSceneFlags[i].unk_14 = 0;
|
|
gSaveContext.save.permanentSceneFlags[i].rooms = 0;
|
|
}
|
|
|
|
for (; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
|
gSaveContext.cycleSceneFlags[i].chest = 0;
|
|
gSaveContext.cycleSceneFlags[i].switch0 = 0;
|
|
gSaveContext.cycleSceneFlags[i].switch1 = 0;
|
|
gSaveContext.cycleSceneFlags[i].clearedRoom = 0;
|
|
gSaveContext.cycleSceneFlags[i].collectible = 0;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.maskMaskBit); i++) {
|
|
gSaveContext.maskMaskBit[i] = 0;
|
|
}
|
|
|
|
if (gSaveContext.save.weekEventReg[84] & 0x20) {
|
|
Inventory_DeleteItem(ITEM_MASK_FIERCE_DEITY, SLOT(ITEM_MASK_FIERCE_DEITY));
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(D_801C66D0); i++) {
|
|
u16 phi_v1_3 = D_801C66D0[i];
|
|
|
|
for (j = 0; j < ARRAY_COUNT(D_801C6890); j++) {
|
|
if ((phi_v1_3 & 3) == 0) {
|
|
gSaveContext.save.weekEventReg[i] =
|
|
((void)0, gSaveContext.save.weekEventReg[i]) & (0xFF ^ D_801C6890[j]);
|
|
}
|
|
phi_v1_3 >>= 2;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.eventInf); i++) {
|
|
gSaveContext.eventInf[i] = 0;
|
|
}
|
|
|
|
gSaveContext.eventInf[7] &= (u8)~1;
|
|
gSaveContext.eventInf[7] &= (u8)~2;
|
|
gSaveContext.eventInf[7] &= (u8)~4;
|
|
gSaveContext.eventInf[7] &= (u8)~8;
|
|
gSaveContext.eventInf[7] &= (u8)~0x10;
|
|
|
|
if (gSaveContext.save.playerData.rupees != 0) {
|
|
gSaveContext.eventInf[7] |= 1;
|
|
}
|
|
|
|
if (INV_CONTENT(ITEM_BOMB) == ITEM_BOMB) {
|
|
item = INV_CONTENT(ITEM_BOMB);
|
|
if (AMMO(item) != 0) {
|
|
gSaveContext.eventInf[7] |= 2;
|
|
}
|
|
}
|
|
if (INV_CONTENT(ITEM_NUT) == ITEM_NUT) {
|
|
item = INV_CONTENT(ITEM_NUT);
|
|
if (AMMO(item) != 0) {
|
|
gSaveContext.eventInf[7] |= 4;
|
|
}
|
|
}
|
|
if (INV_CONTENT(ITEM_STICK) == ITEM_STICK) {
|
|
item = INV_CONTENT(ITEM_STICK);
|
|
if (AMMO(item) != 0) {
|
|
gSaveContext.eventInf[7] |= 8;
|
|
}
|
|
}
|
|
if (INV_CONTENT(ITEM_BOW) == ITEM_BOW) {
|
|
item = INV_CONTENT(ITEM_BOW);
|
|
if (AMMO(item) != 0) {
|
|
gSaveContext.eventInf[7] |= 0x10;
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gAmmoItems); i++) {
|
|
if (gAmmoItems[i] != ITEM_NONE) {
|
|
if ((gSaveContext.save.inventory.items[i] != ITEM_NONE) && (i != SLOT_PICTO_BOX)) {
|
|
item = gSaveContext.save.inventory.items[i];
|
|
AMMO(item) = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_6; i++) {
|
|
// Check for all bottled items
|
|
if (gSaveContext.save.inventory.items[i] >= ITEM_POTION_RED) {
|
|
if (gSaveContext.save.inventory.items[i] <= ITEM_OBABA_DRINK) {
|
|
for (j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++) {
|
|
if (GET_CUR_FORM_BTN_ITEM(j) == gSaveContext.save.inventory.items[i]) {
|
|
SET_CUR_FORM_BTN_ITEM(j, ITEM_BOTTLE);
|
|
Interface_LoadItemIconImpl(play, j);
|
|
}
|
|
}
|
|
gSaveContext.save.inventory.items[i] = ITEM_BOTTLE;
|
|
}
|
|
}
|
|
}
|
|
|
|
REMOVE_QUEST_ITEM(QUEST_PICTOGRAPH);
|
|
|
|
if (gSaveContext.save.playerData.health < 0x30) {
|
|
gSaveContext.save.playerData.health = 0x30;
|
|
}
|
|
|
|
if (GET_CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) <= EQUIP_VALUE_SWORD_RAZOR) {
|
|
SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_KOKIRI);
|
|
|
|
if (CUR_FORM == 0) {
|
|
if ((STOLEN_ITEM_1 >= ITEM_SWORD_GILDED) || (STOLEN_ITEM_2 >= ITEM_SWORD_GILDED)) {
|
|
BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_SWORD_GILDED;
|
|
SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_GILDED);
|
|
} else {
|
|
BUTTON_ITEM_EQUIP(CUR_FORM, EQUIP_SLOT_B) = ITEM_SWORD_KOKIRI;
|
|
}
|
|
} else {
|
|
if ((STOLEN_ITEM_1 >= ITEM_SWORD_GILDED) || (STOLEN_ITEM_2 >= ITEM_SWORD_GILDED)) {
|
|
BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_B) = ITEM_SWORD_GILDED;
|
|
SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_GILDED);
|
|
} else {
|
|
BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_B) = ITEM_SWORD_KOKIRI;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((STOLEN_ITEM_1 == ITEM_SWORD_GREAT_FAIRY) || (STOLEN_ITEM_2 == ITEM_SWORD_GREAT_FAIRY)) {
|
|
INV_CONTENT(ITEM_SWORD_GREAT_FAIRY) = ITEM_SWORD_GREAT_FAIRY;
|
|
}
|
|
|
|
if (STOLEN_ITEM_1 == ITEM_BOTTLE) {
|
|
slot = SLOT(ITEM_BOTTLE);
|
|
for (i = BOTTLE_FIRST; i < BOTTLE_MAX; i++) {
|
|
if (gSaveContext.save.inventory.items[slot + i] == ITEM_NONE) {
|
|
gSaveContext.save.inventory.items[slot + i] = ITEM_BOTTLE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (STOLEN_ITEM_2 == ITEM_BOTTLE) {
|
|
slot = SLOT(ITEM_BOTTLE);
|
|
for (i = BOTTLE_FIRST; i < BOTTLE_MAX; i++) {
|
|
if (gSaveContext.save.inventory.items[slot + i] == ITEM_NONE) {
|
|
gSaveContext.save.inventory.items[slot + i] = ITEM_BOTTLE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
SET_STOLEN_ITEM_1(STOLEN_ITEM_NONE);
|
|
SET_STOLEN_ITEM_2(STOLEN_ITEM_NONE);
|
|
|
|
Inventory_DeleteItem(ITEM_OCARINA_FAIRY, SLOT_TRADE_DEED);
|
|
Inventory_DeleteItem(ITEM_SLINGSHOT, SLOT_TRADE_KEY_MAMA);
|
|
Inventory_DeleteItem(ITEM_LONGSHOT, SLOT_TRADE_COUPLE);
|
|
|
|
for (j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++) {
|
|
if (GET_CUR_FORM_BTN_ITEM(j) >= ITEM_MOON_TEAR && GET_CUR_FORM_BTN_ITEM(j) <= ITEM_PENDANT_OF_MEMORIES) {
|
|
SET_CUR_FORM_BTN_ITEM(j, ITEM_NONE);
|
|
Interface_LoadItemIconImpl(play, j);
|
|
}
|
|
}
|
|
|
|
gSaveContext.save.skullTokenCount &= ~0xFFFF0000;
|
|
gSaveContext.save.skullTokenCount &= ~0x0000FFFF;
|
|
gSaveContext.save.unk_EC4 = 0;
|
|
|
|
gSaveContext.save.unk_E88[0] = 0;
|
|
gSaveContext.save.unk_E88[1] = 0;
|
|
gSaveContext.save.unk_E88[2] = 0;
|
|
gSaveContext.save.unk_E88[3] = 0;
|
|
gSaveContext.save.unk_E88[4] = 0;
|
|
gSaveContext.save.unk_E88[5] = 0;
|
|
gSaveContext.save.unk_E88[6] = 0;
|
|
|
|
Sram_ClearHighscores();
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
gSaveContext.save.inventory.dungeonItems[i] &= (u8)~1; // remove boss key
|
|
DUNGEON_KEY_COUNT(i) = 0;
|
|
gSaveContext.save.inventory.strayFairies[i] = 0;
|
|
}
|
|
|
|
gSaveContext.save.playerData.rupees = 0;
|
|
gSaveContext.save.unk_F65 = 0;
|
|
gSaveContext.powderKegTimer = 0;
|
|
gSaveContext.unk_1014 = 0;
|
|
gSaveContext.jinxTimer = 0;
|
|
gSaveContext.rupeeAccumulator = 0;
|
|
|
|
func_800F3B2C(play);
|
|
}
|
|
|
|
void Sram_IncrementDay(void) {
|
|
if (CURRENT_DAY <= 3) {
|
|
gSaveContext.save.day++;
|
|
gSaveContext.save.daysElapsed++;
|
|
}
|
|
|
|
gSaveContext.save.bombersCaughtNum = 0;
|
|
gSaveContext.save.bombersCaughtOrder[0] = 0;
|
|
gSaveContext.save.bombersCaughtOrder[1] = 0;
|
|
gSaveContext.save.bombersCaughtOrder[2] = 0;
|
|
gSaveContext.save.bombersCaughtOrder[3] = 0;
|
|
gSaveContext.save.bombersCaughtOrder[4] = 0;
|
|
|
|
// Unconfirmed: "Bombers Hide & Seek started on Day 1???"
|
|
gSaveContext.save.weekEventReg[73] &= (u8)~0x10;
|
|
// Unconfirmed: "Bombers Hide & Seek in Progress"
|
|
gSaveContext.save.weekEventReg[85] &= (u8)~2;
|
|
}
|
|
|
|
u16 Sram_CalcChecksum(void* data, size_t count) {
|
|
u8* dataPtr = data;
|
|
u16 chkSum = 0;
|
|
|
|
while (count-- > 0) {
|
|
chkSum += *dataPtr;
|
|
dataPtr++;
|
|
}
|
|
return chkSum;
|
|
}
|
|
|
|
// Resets `Save` substruct
|
|
void Sram_ResetSave(void) {
|
|
gSaveContext.save.entrance = ENTRANCE(CUTSCENE, 0);
|
|
gSaveContext.save.equippedMask = 0;
|
|
gSaveContext.save.isFirstCycle = false;
|
|
gSaveContext.save.unk_06 = 0;
|
|
gSaveContext.save.linkAge = 0;
|
|
gSaveContext.save.isNight = false;
|
|
gSaveContext.save.daySpeed = 0;
|
|
gSaveContext.save.snowheadCleared = 0;
|
|
gSaveContext.save.hasTatl = false;
|
|
gSaveContext.save.isOwlSave = false;
|
|
|
|
// Instead of bloating all save context accesses with an extra sub-struct, the size of the would-be sub-struct
|
|
// is calculated manually
|
|
bzero(&gSaveContext.save.playerData, sizeof(Save) - offsetof(Save, playerData));
|
|
}
|
|
|
|
/**
|
|
* Initializes with random values the following fields:
|
|
* - lotteryCodes
|
|
* - spiderHouseMaskOrder
|
|
* - bomberCode
|
|
*/
|
|
void Sram_GenerateRandomSaveFields(void) {
|
|
s32 randBombers;
|
|
s16 sp2A;
|
|
s16 pad;
|
|
s16 i;
|
|
s16 j;
|
|
s32 k;
|
|
s16 randSpiderHouse;
|
|
|
|
Sram_ClearHighscores();
|
|
|
|
gSaveContext.save.lotteryCodes[0][0] = Rand_S16Offset(0, 10);
|
|
gSaveContext.save.lotteryCodes[0][1] = Rand_S16Offset(0, 10);
|
|
gSaveContext.save.lotteryCodes[0][2] = Rand_S16Offset(0, 10);
|
|
gSaveContext.save.lotteryCodes[1][0] = Rand_S16Offset(0, 10);
|
|
gSaveContext.save.lotteryCodes[1][1] = Rand_S16Offset(0, 10);
|
|
gSaveContext.save.lotteryCodes[1][2] = Rand_S16Offset(0, 10);
|
|
gSaveContext.save.lotteryCodes[2][0] = Rand_S16Offset(0, 10);
|
|
gSaveContext.save.lotteryCodes[2][1] = Rand_S16Offset(0, 10);
|
|
gSaveContext.save.lotteryCodes[2][2] = Rand_S16Offset(0, 10);
|
|
|
|
// Needed to match...
|
|
for (i = 0; i < 3; i++) {
|
|
for (j = 0; j < 3; j++) {}
|
|
}
|
|
|
|
i = 0;
|
|
sp2A = Rand_S16Offset(0, 16) & 3;
|
|
k = 6;
|
|
while (i != k) {
|
|
randSpiderHouse = Rand_S16Offset(0, 16) & 3;
|
|
if (sp2A != randSpiderHouse) {
|
|
gSaveContext.save.spiderHouseMaskOrder[i] = randSpiderHouse;
|
|
i++;
|
|
sp2A = randSpiderHouse;
|
|
}
|
|
}
|
|
|
|
do {
|
|
randBombers = Rand_S16Offset(0, 6);
|
|
} while (randBombers <= 0 || randBombers >= 6);
|
|
|
|
gSaveContext.save.bomberCode[0] = randBombers;
|
|
|
|
i = 1;
|
|
while (i != 5) {
|
|
k = false;
|
|
|
|
do {
|
|
randBombers = Rand_S16Offset(0, 6);
|
|
} while (randBombers <= 0 || randBombers >= 6);
|
|
|
|
sp2A = 0;
|
|
do {
|
|
if (randBombers == gSaveContext.save.bomberCode[sp2A]) {
|
|
k = true;
|
|
}
|
|
sp2A++;
|
|
} while (sp2A < i);
|
|
|
|
if (k == false) {
|
|
gSaveContext.save.bomberCode[i] = randBombers;
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
|
|
SavePlayerData sSaveDefaultPlayerData = {
|
|
{ '\0', '\0', '\0', '\0', '\0', '\0' }, // newf
|
|
0, // deaths
|
|
{ 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E }, // playerName " "
|
|
0x30, // healthCapacity
|
|
0x30, // health
|
|
0, // magicLevel
|
|
0x30, // magic
|
|
0, // rupees
|
|
0, // swordHealth
|
|
0, // tatlTimer
|
|
0, // magicAcquired
|
|
0, // doubleMagic
|
|
0, // doubleDefense
|
|
0, // unk_1F
|
|
0xFF, // unk_20
|
|
0x0000, // owlActivationFlags
|
|
0xFF, // unk_24
|
|
SCENE_SPOT00, // savedSceneNum
|
|
};
|
|
|
|
ItemEquips sSaveDefaultItemEquips = {
|
|
{
|
|
{ ITEM_SWORD_KOKIRI, ITEM_NONE, ITEM_NONE, ITEM_NONE },
|
|
{ ITEM_SWORD_KOKIRI, ITEM_NONE, ITEM_NONE, ITEM_NONE },
|
|
{ ITEM_SWORD_KOKIRI, ITEM_NONE, ITEM_NONE, ITEM_NONE },
|
|
{ ITEM_FD, ITEM_NONE, ITEM_NONE, ITEM_NONE },
|
|
},
|
|
{
|
|
{ SLOT_OCARINA, SLOT_NONE, SLOT_NONE, SLOT_NONE },
|
|
{ SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE },
|
|
{ SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE },
|
|
{ SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE },
|
|
},
|
|
0x11,
|
|
};
|
|
|
|
Inventory sSaveDefaultInventory = {
|
|
// items
|
|
{
|
|
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
|
|
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
|
|
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
|
|
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
|
|
ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE, ITEM_NONE,
|
|
},
|
|
// ammo
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
// upgrades
|
|
0x120000,
|
|
// questItems
|
|
0,
|
|
// dungeonItems
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
// dungeonKeys
|
|
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
|
|
// defenceHearts
|
|
0,
|
|
// strayFairies
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
// dekuPlaygroundPlayerName
|
|
{
|
|
// "LINK "
|
|
{ 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
|
|
// "LINK "
|
|
{ 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
|
|
// "LINK "
|
|
{ 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
|
|
},
|
|
};
|
|
|
|
u16 sSaveDefaultChecksum = 0;
|
|
|
|
/**
|
|
* Initialize new save.
|
|
* This save has an empty inventory with 3 hearts, sword and shield.
|
|
*/
|
|
void Sram_InitNewSave(void) {
|
|
gSaveContext.save.playerForm = PLAYER_FORM_HUMAN;
|
|
gSaveContext.save.daysElapsed = 0;
|
|
gSaveContext.save.day = 0;
|
|
gSaveContext.save.time = CLOCK_TIME(6, 0) - 1;
|
|
Sram_ResetSave();
|
|
|
|
Lib_MemCpy(&gSaveContext.save.playerData, &sSaveDefaultPlayerData, sizeof(SavePlayerData));
|
|
Lib_MemCpy(&gSaveContext.save.equips, &sSaveDefaultItemEquips, sizeof(ItemEquips));
|
|
Lib_MemCpy(&gSaveContext.save.inventory, &sSaveDefaultInventory, sizeof(Inventory));
|
|
Lib_MemCpy(&gSaveContext.save.checksum, &sSaveDefaultChecksum, sizeof(gSaveContext.save.checksum));
|
|
|
|
gSaveContext.save.horseData.scene = SCENE_F01;
|
|
gSaveContext.save.horseData.pos.x = -1420;
|
|
gSaveContext.save.horseData.pos.y = 257;
|
|
gSaveContext.save.horseData.pos.z = -1285;
|
|
gSaveContext.save.horseData.yaw = -0x7554;
|
|
|
|
gSaveContext.nextCutsceneIndex = 0;
|
|
gSaveContext.save.playerData.magicLevel = 0;
|
|
Sram_GenerateRandomSaveFields();
|
|
}
|
|
|
|
SavePlayerData sSaveDebugPlayerData = {
|
|
{ 'Z', 'E', 'L', 'D', 'A', '3' }, // newf
|
|
0x0000, // deaths
|
|
{ 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E }, // playerName "LINK "
|
|
0x80, // healthCapacity
|
|
0x80, // health
|
|
0, // magicLevel
|
|
0x30, // magic
|
|
0x32, // rupees
|
|
0x64, // swordHealth
|
|
0, // tatlTimer
|
|
1, // magicAcquired
|
|
0, // doubleMagic
|
|
0, // doubleDefense
|
|
0, // unk_1F
|
|
0xFF, // unk_20
|
|
0, // owlActivationFlags
|
|
0xFF, // unk_24
|
|
SCENE_SPOT00, // savedSceneNum
|
|
};
|
|
|
|
ItemEquips sSaveDebugItemEquips = {
|
|
{
|
|
{ ITEM_SWORD_KOKIRI, ITEM_BOW, ITEM_POTION_RED, ITEM_OCARINA },
|
|
{ ITEM_SWORD_KOKIRI, ITEM_BOW, ITEM_MASK_GORON, ITEM_OCARINA },
|
|
{ ITEM_SWORD_KOKIRI, ITEM_BOW, ITEM_MASK_ZORA, ITEM_OCARINA },
|
|
{ ITEM_NUT, ITEM_NUT, ITEM_MASK_DEKU, ITEM_OCARINA },
|
|
},
|
|
{
|
|
{ SLOT_OCARINA, SLOT_BOW, SLOT_BOTTLE_2, SLOT_OCARINA },
|
|
{ SLOT_OCARINA, SLOT_MAGIC_BEANS, SLOT_MASK_GORON, SLOT_BOMBCHU },
|
|
{ SLOT_OCARINA, SLOT_POWDER_KEG, SLOT_MASK_ZORA, SLOT_BOMBCHU },
|
|
{ SLOT_OCARINA, SLOT_BOW, SLOT_MASK_DEKU, SLOT_BOMBCHU },
|
|
},
|
|
0x11,
|
|
};
|
|
|
|
Inventory sSaveDebugInventory = {
|
|
// items
|
|
{
|
|
ITEM_OCARINA,
|
|
ITEM_BOW,
|
|
ITEM_ARROW_FIRE,
|
|
ITEM_ARROW_ICE,
|
|
ITEM_ARROW_LIGHT,
|
|
ITEM_MOON_TEAR,
|
|
ITEM_BOMB,
|
|
ITEM_BOMBCHU,
|
|
ITEM_STICK,
|
|
ITEM_NUT,
|
|
ITEM_MAGIC_BEANS,
|
|
ITEM_ROOM_KEY,
|
|
ITEM_POWDER_KEG,
|
|
ITEM_PICTO_BOX,
|
|
ITEM_LENS,
|
|
ITEM_HOOKSHOT,
|
|
ITEM_SWORD_GREAT_FAIRY,
|
|
ITEM_LETTER_TO_KAFEI,
|
|
ITEM_BOTTLE,
|
|
ITEM_POTION_RED,
|
|
ITEM_POTION_GREEN,
|
|
ITEM_POTION_BLUE,
|
|
ITEM_NONE,
|
|
ITEM_NONE,
|
|
ITEM_MASK_POSTMAN,
|
|
ITEM_MASK_ALL_NIGHT,
|
|
ITEM_MASK_BLAST,
|
|
ITEM_MASK_STONE,
|
|
ITEM_MASK_GREAT_FAIRY,
|
|
ITEM_MASK_DEKU,
|
|
ITEM_MASK_KEATON,
|
|
ITEM_MASK_BREMEN,
|
|
ITEM_MASK_BUNNY,
|
|
ITEM_MASK_DON_GERO,
|
|
ITEM_MASK_SCENTS,
|
|
ITEM_MASK_GORON,
|
|
ITEM_MASK_ROMANI,
|
|
ITEM_MASK_CIRCUS_LEADER,
|
|
ITEM_MASK_KAFEIS_MASK,
|
|
ITEM_MASK_COUPLE,
|
|
ITEM_MASK_TRUTH,
|
|
ITEM_MASK_ZORA,
|
|
ITEM_MASK_KAMARO,
|
|
ITEM_MASK_GIBDO,
|
|
ITEM_MASK_GARO,
|
|
ITEM_MASK_CAPTAIN,
|
|
ITEM_MASK_GIANT,
|
|
ITEM_MASK_FIERCE_DEITY,
|
|
},
|
|
// ammo
|
|
{ 1, 30, 1, 1, 1, 1, 30, 30, 30, 30, 1, 1, 1, 1, 30, 1, 1, 1, 1, 1, 1, 1, 0, 0 },
|
|
// upgrades
|
|
0x120009,
|
|
// questItems
|
|
(1 << QUEST_SONG_SONATA) | (1 << QUEST_SONG_LULLABY) | (1 << QUEST_SONG_BOSSA_NOVA) | (1 << QUEST_SONG_ELEGY) |
|
|
(1 << QUEST_SONG_OATH) | (1 << QUEST_SONG_TIME) | (1 << QUEST_SONG_HEALING) | (1 << QUEST_SONG_EPONA) |
|
|
(1 << QUEST_SONG_SOARING) | (1 << QUEST_SONG_STORMS) | (1 << QUEST_BOMBERS_NOTEBOOK) |
|
|
(1 << QUEST_SONG_LULLABY_INTRO),
|
|
// dungeonItems
|
|
{ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 },
|
|
// dungeonKeys
|
|
{ 8, 8, 8, 8, 8, 8, 8, 8, 8 },
|
|
// defenceHearts
|
|
0,
|
|
// strayFairies
|
|
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
|
|
// dekuPlaygroundPlayerName
|
|
{
|
|
// "LINK "
|
|
{ 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
|
|
// "LINK "
|
|
{ 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
|
|
// "LINK "
|
|
{ 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
|
|
},
|
|
};
|
|
|
|
u16 sSaveDebugChecksum = 0;
|
|
|
|
u8 D_801C6A48[] = {
|
|
ITEM_MASK_FIERCE_DEITY, ITEM_MASK_GORON, ITEM_MASK_ZORA, ITEM_MASK_DEKU, ITEM_MASK_FIERCE_DEITY,
|
|
};
|
|
|
|
u8 D_801C6A50[] = {
|
|
SLOT_MASK_FIERCE_DEITY, SLOT_MASK_GORON, SLOT_MASK_ZORA, SLOT_MASK_DEKU, SLOT_MASK_FIERCE_DEITY,
|
|
};
|
|
|
|
/**
|
|
* Initialize debug save. This is also used on the Title Screen
|
|
* This save has a mostly full inventory, every mask and 10 hearts.
|
|
*
|
|
* Some noteable flags that are set:
|
|
* TODO: Investigate the flags
|
|
*/
|
|
void Sram_InitDebugSave(void) {
|
|
Sram_ResetSave();
|
|
|
|
Lib_MemCpy(&gSaveContext.save.playerData, &sSaveDebugPlayerData, sizeof(SavePlayerData));
|
|
Lib_MemCpy(&gSaveContext.save.equips, &sSaveDebugItemEquips, sizeof(ItemEquips));
|
|
Lib_MemCpy(&gSaveContext.save.inventory, &sSaveDebugInventory, sizeof(Inventory));
|
|
Lib_MemCpy(&gSaveContext.save.checksum, &sSaveDebugChecksum, sizeof(gSaveContext.save.checksum));
|
|
|
|
if (gSaveContext.save.playerForm != PLAYER_FORM_HUMAN) {
|
|
BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_C_DOWN) = D_801C6A48[((void)0, gSaveContext.save.playerForm)];
|
|
C_SLOT_EQUIP(0, EQUIP_SLOT_C_DOWN) = D_801C6A50[((void)0, gSaveContext.save.playerForm)];
|
|
}
|
|
|
|
gSaveContext.save.hasTatl = true;
|
|
|
|
gSaveContext.save.horseData.scene = SCENE_F01;
|
|
gSaveContext.save.horseData.pos.x = -1420;
|
|
gSaveContext.save.horseData.pos.y = 257;
|
|
gSaveContext.save.horseData.pos.z = -1285;
|
|
gSaveContext.save.horseData.yaw = -0x7554;
|
|
|
|
gSaveContext.save.entrance = ENTRANCE(CUTSCENE, 0);
|
|
gSaveContext.save.isFirstCycle = true;
|
|
|
|
//
|
|
gSaveContext.save.weekEventReg[0x0F] |= 0x20;
|
|
// Unconfirmed: "Entered South Clock Town"
|
|
gSaveContext.save.weekEventReg[0x3B] |= 0x04;
|
|
// Unconfirmed: "Tatl's Second Cycle Text?"
|
|
gSaveContext.save.weekEventReg[0x1F] |= 0x04;
|
|
|
|
gSaveContext.cycleSceneFlags[SCENE_INSIDETOWER].switch0 = 1;
|
|
gSaveContext.save.permanentSceneFlags[SCENE_INSIDETOWER].switch0 = 1;
|
|
gSaveContext.save.playerData.magicLevel = 0;
|
|
|
|
Sram_GenerateRandomSaveFields();
|
|
}
|
|
|
|
// Unused
|
|
void func_80144A94(SramContext* sramCtx) {
|
|
s32 i;
|
|
s32 cutscene = gSaveContext.save.cutscene;
|
|
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[gSaveContext.fileNum * 2], D_801C67F0[gSaveContext.fileNum * 2]) !=
|
|
0) {
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[gSaveContext.fileNum * 2 + 1],
|
|
D_801C67F0[gSaveContext.fileNum * 2 + 1]);
|
|
}
|
|
Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
|
|
if (CHECK_NEWF(gSaveContext.save.playerData.newf)) {
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[gSaveContext.fileNum * 2 + 1],
|
|
D_801C67F0[gSaveContext.fileNum * 2 + 1]);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, sizeof(Save));
|
|
}
|
|
gSaveContext.save.cutscene = cutscene;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.eventInf); i++) {
|
|
gSaveContext.eventInf[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
|
gSaveContext.cycleSceneFlags[i].chest = gSaveContext.save.permanentSceneFlags[i].chest;
|
|
gSaveContext.cycleSceneFlags[i].switch0 = gSaveContext.save.permanentSceneFlags[i].switch0;
|
|
gSaveContext.cycleSceneFlags[i].switch1 = gSaveContext.save.permanentSceneFlags[i].switch1;
|
|
gSaveContext.cycleSceneFlags[i].clearedRoom = gSaveContext.save.permanentSceneFlags[i].clearedRoom;
|
|
gSaveContext.cycleSceneFlags[i].collectible = gSaveContext.save.permanentSceneFlags[i].collectible;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.unk_3DD0); i++) {
|
|
gSaveContext.unk_3DD0[i] = 0;
|
|
gSaveContext.unk_3DE0[i] = 0;
|
|
gSaveContext.unk_3E18[i] = 0;
|
|
gSaveContext.unk_3E50[i] = 0;
|
|
gSaveContext.unk_3E88[i] = 0;
|
|
gSaveContext.unk_3EC0[i] = 0;
|
|
}
|
|
|
|
D_801BDAA0 = 1;
|
|
D_801BDA9C = 0;
|
|
gSaveContext.powderKegTimer = 0;
|
|
gSaveContext.unk_1014 = 0;
|
|
gSaveContext.jinxTimer = 0;
|
|
}
|
|
|
|
u16 D_801C6A58[] = {
|
|
ENTRANCE(GREAT_BAY_COAST, 11), ENTRANCE(ZORA_CAPE, 6),
|
|
ENTRANCE(SNOWHEAD, 3), ENTRANCE(MOUNTAIN_VILLAGE_WINTER, 8),
|
|
ENTRANCE(SOUTH_CLOCK_TOWN, 9), ENTRANCE(MILK_ROAD, 4),
|
|
ENTRANCE(WOODFALL, 4), ENTRANCE(SOUTHERN_SWAMP_POISONED, 10),
|
|
ENTRANCE(IKANA_CANYON, 4), ENTRANCE(STONE_TOWER, 3),
|
|
};
|
|
|
|
void Sram_OpenSave(FileChooseContext* fileChooseCtx, SramContext* sramCtx) {
|
|
s32 i;
|
|
s32 pad;
|
|
s32 phi_t1;
|
|
s32 pad1;
|
|
s32 fileNum;
|
|
|
|
if (gSaveContext.unk_3F3F) {
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
|
|
if (gSaveContext.fileNum == 0xFF) {
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[0], D_801C67F0[0]);
|
|
} else if (fileChooseCtx->unk_2446A[gSaveContext.fileNum] != 0) {
|
|
phi_t1 = gSaveContext.fileNum + 2;
|
|
phi_t1 *= 2;
|
|
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[phi_t1], D_801C67F0[phi_t1]) != 0) {
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[phi_t1 + 1], D_801C67F0[phi_t1 + 1]);
|
|
}
|
|
} else {
|
|
phi_t1 = gSaveContext.fileNum;
|
|
phi_t1 *= 2;
|
|
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[phi_t1], D_801C67F0[phi_t1]) != 0) {
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[phi_t1 + 1], D_801C67F0[phi_t1 + 1]);
|
|
}
|
|
}
|
|
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[phi_t1]);
|
|
|
|
if (CHECK_NEWF(gSaveContext.save.playerData.newf)) {
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[phi_t1 + 1], D_801C67F0[phi_t1 + 1]);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[phi_t1]);
|
|
}
|
|
}
|
|
|
|
gSaveContext.save.playerData.magicLevel = 0;
|
|
|
|
if (!gSaveContext.save.isOwlSave) {
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.eventInf); i++) {
|
|
gSaveContext.eventInf[i] = 0;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
|
gSaveContext.cycleSceneFlags[i].chest = gSaveContext.save.permanentSceneFlags[i].chest;
|
|
gSaveContext.cycleSceneFlags[i].switch0 = gSaveContext.save.permanentSceneFlags[i].switch0;
|
|
gSaveContext.cycleSceneFlags[i].switch1 = gSaveContext.save.permanentSceneFlags[i].switch1;
|
|
gSaveContext.cycleSceneFlags[i].clearedRoom = gSaveContext.save.permanentSceneFlags[i].clearedRoom;
|
|
gSaveContext.cycleSceneFlags[i].collectible = gSaveContext.save.permanentSceneFlags[i].collectible;
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.unk_3DD0); i++) {
|
|
gSaveContext.unk_3DD0[i] = 0;
|
|
gSaveContext.unk_3DE0[i] = 0;
|
|
gSaveContext.unk_3E18[i] = 0;
|
|
gSaveContext.unk_3E50[i] = 0;
|
|
gSaveContext.unk_3E88[i] = 0;
|
|
gSaveContext.unk_3EC0[i] = 0;
|
|
}
|
|
|
|
if (gSaveContext.save.isFirstCycle) {
|
|
gSaveContext.save.entrance = ENTRANCE(SOUTH_CLOCK_TOWN, 0);
|
|
gSaveContext.save.day = 0;
|
|
gSaveContext.save.time = 0x3FFF;
|
|
} else {
|
|
gSaveContext.save.entrance = ENTRANCE(CUTSCENE, 0);
|
|
gSaveContext.nextCutsceneIndex = 0;
|
|
gSaveContext.save.playerForm = PLAYER_FORM_HUMAN;
|
|
}
|
|
} else {
|
|
gSaveContext.save.entrance = D_801C6A58[(void)0, gSaveContext.save.owlSaveLocation];
|
|
if ((gSaveContext.save.entrance == ENTRANCE(SOUTHERN_SWAMP_POISONED, 10)) &&
|
|
(gSaveContext.save.weekEventReg[20] & 2)) {
|
|
// Unconfirmed weekEventReg: "Woodfall Temple Prison Entrance raised / Water cleansed"
|
|
gSaveContext.save.entrance = ENTRANCE(SOUTHERN_SWAMP_CLEARED, 10);
|
|
} else if ((gSaveContext.save.entrance == ENTRANCE(MOUNTAIN_VILLAGE_WINTER, 8)) &&
|
|
(gSaveContext.save.weekEventReg[33] & 0x80)) {
|
|
// Unconfirmed weekEventReg: "Mountain Village Unfrozen"
|
|
gSaveContext.save.entrance = ENTRANCE(MOUNTAIN_VILLAGE_SPRING, 8);
|
|
}
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
|
gSaveContext.cycleSceneFlags[i].chest = gSaveContext.save.permanentSceneFlags[i].chest;
|
|
gSaveContext.cycleSceneFlags[i].switch0 = gSaveContext.save.permanentSceneFlags[i].switch0;
|
|
gSaveContext.cycleSceneFlags[i].switch1 = gSaveContext.save.permanentSceneFlags[i].switch1;
|
|
gSaveContext.cycleSceneFlags[i].clearedRoom = gSaveContext.save.permanentSceneFlags[i].clearedRoom;
|
|
gSaveContext.cycleSceneFlags[i].collectible = gSaveContext.save.permanentSceneFlags[i].collectible;
|
|
}
|
|
|
|
if (gSaveContext.save.unk_F65) {
|
|
Lib_MemCpy(gScarecrowSpawnSongPtr, gSaveContext.save.scarecrowSpawnSong,
|
|
sizeof(gSaveContext.save.scarecrowSpawnSong));
|
|
|
|
for (i = 0; i != ARRAY_COUNT(gSaveContext.save.scarecrowSpawnSong); i++) {}
|
|
}
|
|
|
|
fileNum = gSaveContext.fileNum;
|
|
func_80147314(sramCtx, fileNum);
|
|
}
|
|
}
|
|
|
|
// Similar to func_80145698, but accounts for owl saves?
|
|
void func_8014546C(SramContext* sramCtx) {
|
|
s32 i;
|
|
|
|
if (gSaveContext.save.isOwlSave) {
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
|
gSaveContext.save.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
|
|
gSaveContext.save.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
|
|
gSaveContext.save.permanentSceneFlags[i].switch1 = gSaveContext.cycleSceneFlags[i].switch1;
|
|
gSaveContext.save.permanentSceneFlags[i].clearedRoom = gSaveContext.cycleSceneFlags[i].clearedRoom;
|
|
gSaveContext.save.permanentSceneFlags[i].collectible = gSaveContext.cycleSceneFlags[i].collectible;
|
|
}
|
|
|
|
gSaveContext.save.checksum = 0;
|
|
gSaveContext.save.checksum = Sram_CalcChecksum(&gSaveContext, offsetof(SaveContext, fileNum));
|
|
|
|
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, offsetof(SaveContext, fileNum));
|
|
} else {
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
|
gSaveContext.save.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
|
|
gSaveContext.save.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
|
|
gSaveContext.save.permanentSceneFlags[i].switch1 = gSaveContext.cycleSceneFlags[i].switch1;
|
|
gSaveContext.save.permanentSceneFlags[i].clearedRoom = gSaveContext.cycleSceneFlags[i].clearedRoom;
|
|
gSaveContext.save.permanentSceneFlags[i].collectible = gSaveContext.cycleSceneFlags[i].collectible;
|
|
}
|
|
|
|
gSaveContext.save.checksum = 0;
|
|
gSaveContext.save.checksum = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save));
|
|
|
|
if (gSaveContext.unk_3F3F) {
|
|
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, sizeof(Save));
|
|
Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save permanent scene flags, calculate checksum, copy save context to the save buffer
|
|
*/
|
|
void func_80145698(SramContext* sramCtx) {
|
|
s32 i;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
|
|
gSaveContext.save.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
|
|
gSaveContext.save.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
|
|
gSaveContext.save.permanentSceneFlags[i].switch1 = gSaveContext.cycleSceneFlags[i].switch1;
|
|
gSaveContext.save.permanentSceneFlags[i].clearedRoom = gSaveContext.cycleSceneFlags[i].clearedRoom;
|
|
gSaveContext.save.permanentSceneFlags[i].collectible = gSaveContext.cycleSceneFlags[i].collectible;
|
|
}
|
|
|
|
gSaveContext.save.checksum = 0;
|
|
gSaveContext.save.checksum = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save));
|
|
if (gSaveContext.unk_3F3F) {
|
|
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, sizeof(Save));
|
|
Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
|
|
}
|
|
}
|
|
|
|
// Verifies save and use backup if corrupted?
|
|
#ifdef NON_EQUIVALENT
|
|
void func_801457CC(FileChooseContext* fileChooseCtx2, SramContext* sramCtx) {
|
|
FileChooseContext* fileChooseCtx = fileChooseCtx2;
|
|
u16 sp7A;
|
|
// u16 sp78;
|
|
u16 sp76;
|
|
// u16 sp74;
|
|
u16 sp6E; //!
|
|
// s32 sp68;
|
|
// u16 sp66;
|
|
u16 phi_s2; //!
|
|
u16 sp64;
|
|
// s32 sp60;
|
|
// s32 sp5C;
|
|
// s32 sp58;
|
|
// u32 new_var;
|
|
u16 phi_s2_3;
|
|
// s16 fakevar;
|
|
|
|
u16 temp_s2;
|
|
u16 temp_v0_2;
|
|
u16 phi_a0; // maskCount
|
|
|
|
if (gSaveContext.unk_3F3F) {
|
|
D_801F6AF0 = gSaveContext.save.time;
|
|
D_801F6AF2 = gSaveContext.unk_3F3F;
|
|
sp64 = 0;
|
|
|
|
for (sp76 = 0; sp76 < 5; sp76++, sp64 += 2) {
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
|
|
phi_s2 = false;
|
|
sp6E = 0;
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[sp64], D_801C67F0[sp64])) {
|
|
sp6E = 1;
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) {
|
|
phi_s2 = true;
|
|
}
|
|
}
|
|
|
|
if (sp76 < 2) {
|
|
fileChooseCtx->unk_24468[sp76] = 0;
|
|
if (phi_s2) {
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
} else {
|
|
// Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
temp_s2 = gSaveContext.save.checksum;
|
|
gSaveContext.save.checksum = 0;
|
|
temp_v0_2 = Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]);
|
|
gSaveContext.save.checksum = temp_s2;
|
|
|
|
if (CHECK_NEWF(gSaveContext.save.playerData.newf) || (temp_s2 != temp_v0_2)) {
|
|
sp6E = 1;
|
|
if (CHECK_NEWF2(gSaveContext.save.playerData.newf)) {}
|
|
|
|
phi_s2 = false;
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) {
|
|
phi_s2 = true;
|
|
}
|
|
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
temp_s2 = gSaveContext.save.checksum;
|
|
gSaveContext.save.checksum = 0;
|
|
if (phi_s2 || CHECK_NEWF(gSaveContext.save.playerData.newf) ||
|
|
(temp_s2 != Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]))) {
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
|
|
sp6E = 999;
|
|
}
|
|
}
|
|
}
|
|
|
|
gSaveContext.save.checksum = 0;
|
|
gSaveContext.save.checksum =
|
|
Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64 & 0xFFFFFFFF]); // TODO: Needed?
|
|
|
|
for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.playerData.newf); sp7A++) {
|
|
fileChooseCtx->newf[sp76][sp7A] = gSaveContext.save.playerData.newf[sp7A];
|
|
}
|
|
|
|
if (!CHECK_NEWF(fileChooseCtx->newf[sp76])) {
|
|
fileChooseCtx->unk_2440C[sp76] = gSaveContext.save.playerData.deaths;
|
|
|
|
for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.playerData.playerName); sp7A++) {
|
|
fileChooseCtx->unk_24414[sp76][sp7A] = gSaveContext.save.playerData.playerName[sp7A];
|
|
}
|
|
|
|
fileChooseCtx->healthCapacity[sp76] = gSaveContext.save.playerData.healthCapacity;
|
|
fileChooseCtx->health[sp76] = gSaveContext.save.playerData.health;
|
|
fileChooseCtx->unk_24454[sp76] = gSaveContext.save.inventory.defenseHearts;
|
|
fileChooseCtx->unk_24444[sp76] = gSaveContext.save.inventory.questItems;
|
|
fileChooseCtx->unk_24458[sp76] = gSaveContext.save.time;
|
|
fileChooseCtx->unk_24460[sp76] = gSaveContext.save.day;
|
|
fileChooseCtx->unk_24468[sp76] = gSaveContext.save.isOwlSave;
|
|
fileChooseCtx->rupees[sp76] = gSaveContext.save.playerData.rupees;
|
|
fileChooseCtx->unk_24474[sp76] = CUR_UPG_VALUE(4);
|
|
|
|
for (sp7A = 0, phi_a0 = 0; sp7A < 24; sp7A++) {
|
|
if (gSaveContext.save.inventory.items[sp7A + 24] != 0xFF) {
|
|
phi_a0++;
|
|
}
|
|
}
|
|
fileChooseCtx->maskCount[sp76] = phi_a0;
|
|
fileChooseCtx->heartPieceCount[sp76] =
|
|
((gSaveContext.save.inventory.questItems & 0xF0000000) >> 0x1C);
|
|
}
|
|
|
|
if (sp6E == 1) {
|
|
Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
|
|
func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C6818[sp64]);
|
|
} else if (sp6E == 0) { // TODO: == 0?
|
|
temp_s2 = gSaveContext.save.checksum;
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) {
|
|
phi_s2_3 = 1;
|
|
} else {
|
|
Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
|
|
phi_s2_3 = gSaveContext.save.checksum;
|
|
gSaveContext.save.checksum = 0;
|
|
sp7A = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save));
|
|
}
|
|
|
|
if (CHECK_NEWF(gSaveContext.save.playerData.newf) || (phi_s2_3 != sp7A) || (phi_s2_3 != temp_s2)) {
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[sp64], D_801C67F0[sp64]);
|
|
Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
|
|
Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
|
|
func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C6818[sp64]);
|
|
}
|
|
}
|
|
} else if (sp76 < 4) {
|
|
fileChooseCtx->unk_24468[sp76] = 0;
|
|
|
|
if (!CHECK_NEWF(fileChooseCtx->newf2[(s32)sp76])) { // TODO: Needed?
|
|
if (phi_s2) {
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf,
|
|
D_801C6870[sp64]); // TODO: Needed?
|
|
} else {
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
temp_s2 = gSaveContext.save.checksum;
|
|
|
|
gSaveContext.save.checksum = 0;
|
|
temp_v0_2 = Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]);
|
|
gSaveContext.save.checksum = temp_s2;
|
|
if (CHECK_NEWF(gSaveContext.save.playerData.newf) || (temp_s2 != temp_v0_2)) {
|
|
sp6E = 1;
|
|
if ((gSaveContext.save.playerData.newf[0] == 'Z') &&
|
|
(gSaveContext.save.playerData.newf[1] == 'E')) {
|
|
phi_s2 = false;
|
|
}
|
|
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) {
|
|
phi_s2 = true;
|
|
}
|
|
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
temp_s2 = gSaveContext.save.checksum;
|
|
gSaveContext.save.checksum = 0;
|
|
if (phi_s2 || CHECK_NEWF(gSaveContext.save.playerData.newf) ||
|
|
(temp_s2 != Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]))) {
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
sp6E = 999;
|
|
}
|
|
}
|
|
}
|
|
|
|
gSaveContext.save.checksum = 0;
|
|
gSaveContext.save.checksum =
|
|
Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64 & 0xFFFFFFFF]); // TODO: Needed?
|
|
|
|
for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.playerData.newf); sp7A++) {
|
|
fileChooseCtx->newf[sp76][sp7A] = gSaveContext.save.playerData.newf[sp7A];
|
|
}
|
|
|
|
if (!CHECK_NEWF(fileChooseCtx->newf[sp76])) {
|
|
fileChooseCtx->unk_2440C[sp76] = gSaveContext.save.playerData.deaths;
|
|
|
|
for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.playerData.playerName); sp7A++) {
|
|
phi_s2 += 0; // TODO: Needed?
|
|
fileChooseCtx->unk_24414[sp76][sp7A] = gSaveContext.save.playerData.playerName[sp7A];
|
|
}
|
|
|
|
fileChooseCtx->healthCapacity[sp76] = gSaveContext.save.playerData.healthCapacity;
|
|
fileChooseCtx->health[sp76] = gSaveContext.save.playerData.health;
|
|
fileChooseCtx->unk_24454[sp76] = gSaveContext.save.inventory.defenseHearts;
|
|
fileChooseCtx->unk_24444[sp76] = gSaveContext.save.inventory.questItems;
|
|
fileChooseCtx->unk_24458[sp76] = gSaveContext.save.time;
|
|
fileChooseCtx->unk_24460[sp76] = gSaveContext.save.day;
|
|
fileChooseCtx->unk_24468[sp76] = gSaveContext.save.isOwlSave;
|
|
fileChooseCtx->rupees[sp76] = gSaveContext.save.playerData.rupees;
|
|
fileChooseCtx->unk_24474[sp76] = CUR_UPG_VALUE(4);
|
|
|
|
for (sp7A = 0, phi_a0 = 0; sp7A < 24; sp7A++) {
|
|
if (gSaveContext.save.inventory.items[sp7A + 24] != 0xFF) {
|
|
phi_a0++;
|
|
}
|
|
}
|
|
fileChooseCtx->maskCount[sp76] = phi_a0;
|
|
fileChooseCtx->heartPieceCount[sp76] =
|
|
((gSaveContext.save.inventory.questItems & 0xF0000000) >> 0x1C);
|
|
}
|
|
|
|
if (sp6E == 1) {
|
|
func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C67F0[sp64]);
|
|
func_80146EBC(sramCtx, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1]);
|
|
} else if (!sp6E) { // TODO: == 0?
|
|
temp_s2 = gSaveContext.save.checksum;
|
|
if (func_80185968(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) {
|
|
phi_s2_3 = 1;
|
|
} else {
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
phi_s2_3 = gSaveContext.save.checksum;
|
|
gSaveContext.save.checksum = 0;
|
|
// phi_s2_3 = gSaveContext.save.checksum;
|
|
sp7A = Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]);
|
|
}
|
|
|
|
if (CHECK_NEWF(gSaveContext.save.playerData.newf) || (phi_s2_3 != sp7A) ||
|
|
(phi_s2_3 != temp_s2)) {
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[sp64], D_801C67F0[sp64]);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C67F0[sp64]);
|
|
func_80146EBC(sramCtx, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1]);
|
|
}
|
|
}
|
|
} else {
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]);
|
|
func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C67F0[sp64]);
|
|
func_80146EBC(sramCtx, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1]);
|
|
}
|
|
} else {
|
|
if (phi_s2) {
|
|
gSaveContext.options.optionId = 0xA51D;
|
|
gSaveContext.options.language = 1;
|
|
gSaveContext.options.audioSetting = 0;
|
|
gSaveContext.options.languageSetting = 0;
|
|
gSaveContext.options.zTargetSetting = 0;
|
|
} else {
|
|
Lib_MemCpy(&gSaveContext.options, sramCtx->saveBuf, sizeof(SaveOptions));
|
|
if (gSaveContext.options.optionId != 0xA51D) {
|
|
gSaveContext.options.optionId = 0xA51D;
|
|
gSaveContext.options.language = 1;
|
|
gSaveContext.options.audioSetting = 0;
|
|
gSaveContext.options.languageSetting = 0;
|
|
gSaveContext.options.zTargetSetting = 0;
|
|
}
|
|
}
|
|
func_801A3D98(gSaveContext.options.audioSetting);
|
|
}
|
|
}
|
|
|
|
gSaveContext.save.time = D_801F6AF0;
|
|
gSaveContext.unk_3F3F = D_801F6AF2;
|
|
}
|
|
|
|
gSaveContext.options.language = 1;
|
|
}
|
|
#else
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_sram_NES/func_801457CC.s")
|
|
#endif
|
|
|
|
void func_80146580(FileChooseContext* fileChooseCtx2, SramContext* sramCtx, s32 fileNum) {
|
|
FileChooseContext* fileChooseCtx = fileChooseCtx2;
|
|
s32 pad;
|
|
|
|
if (gSaveContext.unk_3F3F) {
|
|
if (fileChooseCtx->unk_2446A[fileNum]) {
|
|
func_80147314(sramCtx, fileNum);
|
|
fileChooseCtx->unk_2446A[fileNum] = 0;
|
|
}
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, sizeof(Save));
|
|
}
|
|
|
|
gSaveContext.save.time = D_801F6AF0;
|
|
gSaveContext.unk_3F3F = D_801F6AF2;
|
|
}
|
|
|
|
#ifdef NON_MATCHING
|
|
// v0/v1
|
|
void func_80146628(FileChooseContext* fileChooseCtx2, SramContext* sramCtx) {
|
|
FileChooseContext* fileChooseCtx = fileChooseCtx2;
|
|
u16 i;
|
|
s16 maskCount;
|
|
|
|
if (gSaveContext.unk_3F3F) {
|
|
if (fileChooseCtx->unk_2446A[fileChooseCtx->unk_2448E]) {
|
|
func_80147414(sramCtx, fileChooseCtx->unk_2448E, fileChooseCtx->fileNum);
|
|
fileChooseCtx->unk_24410[fileChooseCtx->fileNum] = gSaveContext.save.playerData.deaths;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.save.playerData.playerName); i++) {
|
|
fileChooseCtx->unk_24424[fileChooseCtx->fileNum][i] = gSaveContext.save.playerData.playerName[i];
|
|
}
|
|
|
|
fileChooseCtx->unk_24438[fileChooseCtx->fileNum] = gSaveContext.save.playerData.healthCapacity;
|
|
fileChooseCtx->unk_24440[fileChooseCtx->fileNum] = gSaveContext.save.playerData.health;
|
|
fileChooseCtx->unk_24456[fileChooseCtx->fileNum] = gSaveContext.save.inventory.defenseHearts;
|
|
fileChooseCtx->unk_2444C[fileChooseCtx->fileNum] = gSaveContext.save.inventory.questItems;
|
|
fileChooseCtx->unk_2445C[fileChooseCtx->fileNum] = gSaveContext.save.time;
|
|
fileChooseCtx->unk_24464[fileChooseCtx->fileNum] = gSaveContext.save.day;
|
|
fileChooseCtx->unk_2446A[fileChooseCtx->fileNum] = gSaveContext.save.isOwlSave;
|
|
fileChooseCtx->unk_24470[fileChooseCtx->fileNum] = gSaveContext.save.playerData.rupees;
|
|
// = CUR_UPG_VALUE(UPG_WALLET);
|
|
fileChooseCtx->unk_24476[fileChooseCtx->fileNum] =
|
|
(gSaveContext.save.inventory.upgrades & gUpgradeMasks[4]) >> gUpgradeShifts[4];
|
|
|
|
for (i = 0, maskCount = 0; i < 24; i++) {
|
|
if (gSaveContext.save.inventory.items[i + 24] != ITEM_NONE) {
|
|
maskCount++;
|
|
}
|
|
}
|
|
|
|
fileChooseCtx->unk_2447A[fileChooseCtx->fileNum] = maskCount;
|
|
fileChooseCtx->unk_2447E[fileChooseCtx->fileNum] =
|
|
(gSaveContext.save.inventory.questItems & 0xF0000000) >> 0x1C;
|
|
}
|
|
|
|
// clear buffer
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
// read to buffer
|
|
func_80185968(sramCtx->saveBuf, D_801C67C8[fileChooseCtx->unk_2448E * 2],
|
|
D_801C67F0[fileChooseCtx->unk_2448E * 2]);
|
|
|
|
if (1) {}
|
|
func_80185968(&sramCtx->saveBuf[0x2000], D_801C67C8[fileChooseCtx->unk_2448E * 2 + 1],
|
|
D_801C67F0[fileChooseCtx->unk_2448E * 2 + 1]);
|
|
if (1) {}
|
|
|
|
// copy buffer to save context
|
|
Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
|
|
|
|
fileChooseCtx->unk_2440C[fileChooseCtx->fileNum] = gSaveContext.save.playerData.deaths;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.save.playerData.playerName); i++) {
|
|
fileChooseCtx->unk_24414[fileChooseCtx->fileNum][i] = gSaveContext.save.playerData.playerName[i];
|
|
}
|
|
|
|
fileChooseCtx->healthCapacity[fileChooseCtx->fileNum] = gSaveContext.save.playerData.healthCapacity;
|
|
fileChooseCtx->health[fileChooseCtx->fileNum] = gSaveContext.save.playerData.health;
|
|
fileChooseCtx->unk_24454[fileChooseCtx->fileNum] = gSaveContext.save.inventory.defenseHearts;
|
|
fileChooseCtx->unk_24444[fileChooseCtx->fileNum] = gSaveContext.save.inventory.questItems;
|
|
fileChooseCtx->unk_24458[fileChooseCtx->fileNum] = gSaveContext.save.time;
|
|
fileChooseCtx->unk_24460[fileChooseCtx->fileNum] = gSaveContext.save.day;
|
|
fileChooseCtx->unk_24468[fileChooseCtx->fileNum] = gSaveContext.save.isOwlSave;
|
|
fileChooseCtx->rupees[fileChooseCtx->fileNum] = gSaveContext.save.playerData.rupees;
|
|
// = CUR_UPG_VALUE(UPG_WALLET);
|
|
fileChooseCtx->unk_24474[fileChooseCtx->fileNum] =
|
|
(gSaveContext.save.inventory.upgrades & gUpgradeMasks[4]) >> gUpgradeShifts[4];
|
|
|
|
for (i = 0, maskCount = 0; i < 24; i++) {
|
|
if (gSaveContext.save.inventory.items[i + 24] != ITEM_NONE) {
|
|
maskCount++;
|
|
}
|
|
}
|
|
|
|
fileChooseCtx->maskCount[fileChooseCtx->fileNum] = maskCount;
|
|
fileChooseCtx->heartPieceCount[fileChooseCtx->fileNum] =
|
|
(gSaveContext.save.inventory.questItems & 0xF0000000) >> 0x1C;
|
|
}
|
|
|
|
gSaveContext.save.time = D_801F6AF0;
|
|
gSaveContext.unk_3F3F = D_801F6AF2;
|
|
}
|
|
#else
|
|
#pragma GLOBAL_ASM("asm/non_matchings/code/z_sram_NES/func_80146628.s")
|
|
#endif
|
|
|
|
void Sram_InitSave(FileChooseContext* fileChooseCtx2, SramContext* sramCtx) {
|
|
s32 phi_v0;
|
|
u16 i;
|
|
FileChooseContext* fileChooseCtx = fileChooseCtx2;
|
|
s16 maskCount;
|
|
|
|
if (gSaveContext.unk_3F3F) {
|
|
Sram_InitNewSave();
|
|
if (fileChooseCtx->unk_24480 == 0) {
|
|
gSaveContext.save.cutscene = 0xFFF0;
|
|
}
|
|
|
|
for (phi_v0 = 0; phi_v0 < ARRAY_COUNT(gSaveContext.save.playerData.playerName); phi_v0++) {
|
|
gSaveContext.save.playerData.playerName[phi_v0] =
|
|
fileChooseCtx->unk_24414[fileChooseCtx->unk_24480][phi_v0];
|
|
}
|
|
|
|
gSaveContext.save.playerData.newf[0] = 'Z';
|
|
gSaveContext.save.playerData.newf[1] = 'E';
|
|
gSaveContext.save.playerData.newf[2] = 'L';
|
|
gSaveContext.save.playerData.newf[3] = 'D';
|
|
gSaveContext.save.playerData.newf[4] = 'A';
|
|
gSaveContext.save.playerData.newf[5] = '3';
|
|
|
|
gSaveContext.save.checksum = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save));
|
|
|
|
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext.save, sizeof(Save));
|
|
Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.save.playerData.newf); i++) {
|
|
fileChooseCtx->newf[fileChooseCtx->unk_24480][i] = gSaveContext.save.playerData.newf[i];
|
|
}
|
|
|
|
fileChooseCtx->unk_2440C[fileChooseCtx->unk_24480] = gSaveContext.save.playerData.deaths;
|
|
|
|
for (i = 0; i < ARRAY_COUNT(gSaveContext.save.playerData.playerName); i++) {
|
|
fileChooseCtx->unk_24414[fileChooseCtx->unk_24480][i] = gSaveContext.save.playerData.playerName[i];
|
|
}
|
|
|
|
fileChooseCtx->healthCapacity[fileChooseCtx->unk_24480] = gSaveContext.save.playerData.healthCapacity;
|
|
fileChooseCtx->health[fileChooseCtx->unk_24480] = gSaveContext.save.playerData.health;
|
|
fileChooseCtx->unk_24454[fileChooseCtx->unk_24480] = gSaveContext.save.inventory.defenseHearts;
|
|
fileChooseCtx->unk_24444[fileChooseCtx->unk_24480] = gSaveContext.save.inventory.questItems;
|
|
fileChooseCtx->unk_24458[fileChooseCtx->unk_24480] = gSaveContext.save.time;
|
|
fileChooseCtx->unk_24460[fileChooseCtx->unk_24480] = gSaveContext.save.day;
|
|
fileChooseCtx->unk_24468[fileChooseCtx->unk_24480] = gSaveContext.save.isOwlSave;
|
|
fileChooseCtx->rupees[fileChooseCtx->unk_24480] = gSaveContext.save.playerData.rupees;
|
|
fileChooseCtx->unk_24474[fileChooseCtx->unk_24480] = CUR_UPG_VALUE(UPG_WALLET);
|
|
|
|
for (i = 0, maskCount = 0; i < 24; i++) {
|
|
if (gSaveContext.save.inventory.items[i + 24] != ITEM_NONE) {
|
|
maskCount++;
|
|
}
|
|
}
|
|
|
|
fileChooseCtx->maskCount[fileChooseCtx->unk_24480] = maskCount;
|
|
fileChooseCtx->heartPieceCount[fileChooseCtx->unk_24480] =
|
|
(gSaveContext.save.inventory.questItems & 0xF0000000) >> 0x1C;
|
|
}
|
|
|
|
gSaveContext.save.time = D_801F6AF0;
|
|
gSaveContext.unk_3F3F = D_801F6AF2;
|
|
}
|
|
|
|
void func_80146DF8(SramContext* sramCtx) {
|
|
if (gSaveContext.unk_3F3F) {
|
|
// TODO: macros for languages
|
|
gSaveContext.options.language = 1;
|
|
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext.options, sizeof(SaveOptions));
|
|
}
|
|
}
|
|
|
|
void Sram_InitSram(GameState* gameState, SramContext* sramCtx) {
|
|
if (gSaveContext.save.entrance) {} // Required to match
|
|
|
|
func_801A3D98(gSaveContext.options.audioSetting);
|
|
}
|
|
|
|
void Sram_Alloc(GameState* gamestate, SramContext* sramCtx) {
|
|
if (gSaveContext.unk_3F3F) {
|
|
sramCtx->saveBuf = THA_AllocEndAlign16(&gamestate->heap, SAVE_BUFFER_SIZE);
|
|
sramCtx->status = 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Synchronous flash write
|
|
*/
|
|
void func_80146EBC(SramContext* sramCtx, s32 curPage, s32 numPages) {
|
|
sramCtx->curPage = curPage;
|
|
sramCtx->numPages = numPages;
|
|
func_80185F64(sramCtx->saveBuf, curPage, numPages);
|
|
}
|
|
|
|
/**
|
|
* Saves the game on the very first time Player enters South Clock Town from the Clock Tower
|
|
*/
|
|
void Sram_SaveSpecialEnterClockTown(PlayState* play) {
|
|
s32 pad[2];
|
|
SramContext* sramCtx = &play->sramCtx;
|
|
|
|
gSaveContext.save.isFirstCycle = true;
|
|
gSaveContext.save.isOwlSave = false;
|
|
func_80145698(sramCtx);
|
|
func_80185F64(sramCtx->saveBuf, D_801C67C8[gSaveContext.fileNum * 2], D_801C6818[gSaveContext.fileNum * 2]);
|
|
}
|
|
|
|
/**
|
|
* Saves when beating the game, after showing the "Dawn of the New Day" message
|
|
*/
|
|
void Sram_SaveSpecialNewDay(PlayState* play) {
|
|
s32 cutscene = gSaveContext.save.cutscene;
|
|
s32 day;
|
|
u16 time = gSaveContext.save.time;
|
|
|
|
day = gSaveContext.save.day;
|
|
|
|
// Unconfirmed: "Obtained Fierce Deity Mask?"
|
|
gSaveContext.save.weekEventReg[84] &= (u8)~0x20;
|
|
|
|
Sram_SaveEndOfCycle(play);
|
|
func_8014546C(&play->sramCtx);
|
|
|
|
gSaveContext.save.day = day;
|
|
gSaveContext.save.time = time;
|
|
gSaveContext.save.cutscene = cutscene;
|
|
func_80185F64(play->sramCtx.saveBuf, D_801C67C8[gSaveContext.fileNum * 2], D_801C67F0[gSaveContext.fileNum * 2]);
|
|
}
|
|
|
|
void func_80147008(SramContext* sramCtx, u32 curPage, u32 numPages) {
|
|
sramCtx->curPage = curPage;
|
|
sramCtx->numPages = numPages;
|
|
sramCtx->status = 1;
|
|
}
|
|
|
|
void func_80147020(SramContext* sramCtx) {
|
|
// async flash write
|
|
func_80185DDC(sramCtx->saveBuf, sramCtx->curPage, sramCtx->numPages);
|
|
|
|
sramCtx->unk_18 = osGetTime();
|
|
sramCtx->status = 2;
|
|
}
|
|
|
|
void func_80147068(SramContext* sramCtx) {
|
|
if (sramCtx->status == 2) {
|
|
if (func_80185EC4() != 0) { // if task running
|
|
if (func_80185F04() == 0) { // wait for task done
|
|
// task success
|
|
sramCtx->status = 4;
|
|
} else {
|
|
// task failure
|
|
sramCtx->status = 4;
|
|
}
|
|
}
|
|
} else if (((osGetTime() - sramCtx->unk_18) * 0x40) / 3000 / 10000 >= 200) {
|
|
sramCtx->status = 0;
|
|
}
|
|
}
|
|
|
|
void func_80147138(SramContext* sramCtx, s32 curPage, s32 numPages) {
|
|
sramCtx->curPage = curPage;
|
|
sramCtx->numPages = numPages;
|
|
sramCtx->status = 6;
|
|
}
|
|
|
|
void func_80147150(SramContext* sramCtx) {
|
|
func_80185DDC(sramCtx->saveBuf, sramCtx->curPage, sramCtx->numPages);
|
|
|
|
sramCtx->unk_18 = osGetTime();
|
|
sramCtx->status = 7;
|
|
}
|
|
|
|
void func_80147198(SramContext* sramCtx) {
|
|
if (sramCtx->status == 7) {
|
|
if (func_80185EC4() != 0) { // Is task running
|
|
if (func_80185F04() == 0) { // Wait for task done
|
|
func_80185DDC(sramCtx->saveBuf, sramCtx->curPage + 0x80, sramCtx->numPages);
|
|
sramCtx->status = 8;
|
|
} else {
|
|
func_80185DDC(sramCtx->saveBuf, sramCtx->curPage + 0x80, sramCtx->numPages);
|
|
sramCtx->status = 8;
|
|
}
|
|
}
|
|
} else if (sramCtx->status == 8) {
|
|
if (func_80185EC4() != 0) { // Is task running
|
|
if (func_80185F04() == 0) { // Wait for task done
|
|
sramCtx->status = 4;
|
|
} else {
|
|
sramCtx->status = 4;
|
|
}
|
|
}
|
|
} else if (((osGetTime() - sramCtx->unk_18) * 0x40) / 3000 / 10000 >= 200) {
|
|
sramCtx->status = 0;
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
gSaveContext.save.isOwlSave = false;
|
|
gSaveContext.save.checksum = 0;
|
|
// flash read to buffer then copy to save context
|
|
func_80185968(sramCtx->saveBuf, sramCtx->curPage, sramCtx->numPages);
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, offsetof(SaveContext, fileNum));
|
|
}
|
|
}
|
|
|
|
void func_80147314(SramContext* sramCtx, s32 fileNum) {
|
|
s32 pad;
|
|
|
|
gSaveContext.save.isOwlSave = false;
|
|
|
|
gSaveContext.save.playerData.newf[0] = '\0';
|
|
gSaveContext.save.playerData.newf[1] = '\0';
|
|
gSaveContext.save.playerData.newf[2] = '\0';
|
|
gSaveContext.save.playerData.newf[3] = '\0';
|
|
gSaveContext.save.playerData.newf[4] = '\0';
|
|
gSaveContext.save.playerData.newf[5] = '\0';
|
|
|
|
gSaveContext.save.checksum = 0;
|
|
gSaveContext.save.checksum = Sram_CalcChecksum(&gSaveContext, offsetof(SaveContext, fileNum));
|
|
|
|
Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, offsetof(SaveContext, fileNum));
|
|
func_80146EBC(sramCtx, D_801C6840[fileNum * 2], D_801C6850[fileNum * 2]);
|
|
func_80146EBC(sramCtx, D_801C6840[fileNum * 2 + 1], D_801C6850[fileNum * 2]);
|
|
|
|
gSaveContext.save.isOwlSave = true;
|
|
|
|
gSaveContext.save.playerData.newf[0] = 'Z';
|
|
gSaveContext.save.playerData.newf[1] = 'E';
|
|
gSaveContext.save.playerData.newf[2] = 'L';
|
|
gSaveContext.save.playerData.newf[3] = 'D';
|
|
gSaveContext.save.playerData.newf[4] = 'A';
|
|
gSaveContext.save.playerData.newf[5] = '3';
|
|
}
|
|
|
|
void func_80147414(SramContext* sramCtx, s32 fileNum, s32 arg2) {
|
|
s32 pad;
|
|
|
|
// Clear save buffer
|
|
bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
|
|
|
|
// Read save file
|
|
if (func_80185968(sramCtx->saveBuf, D_801C6840[fileNum * 2], D_801C6850[fileNum * 2]) != 0) {
|
|
// If failed, read backup save file
|
|
func_80185968(sramCtx->saveBuf, D_801C6840[fileNum * 2 + 1], D_801C6850[fileNum * 2 + 1]);
|
|
}
|
|
|
|
// Copy buffer to save context
|
|
Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, offsetof(SaveContext, fileNum));
|
|
|
|
func_80146EBC(sramCtx, D_801C6840[arg2 * 2], D_801C6850[arg2 * 2]);
|
|
func_80146EBC(sramCtx, D_801C6840[arg2 * 2 + 1], D_801C6850[arg2 * 2]);
|
|
}
|
|
|
|
void Sram_nop8014750C(UNK_TYPE4 arg0) {
|
|
}
|