summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakaRikka <38417346+TakaRikka@users.noreply.github.com>2021-05-12 19:54:57 -0700
committerGitHub <noreply@github.com>2021-05-12 19:54:57 -0700
commite6cdc717dfaac36f40585ccbfb918d15e022424b (patch)
tree1489bfac14980fc05b16ffabf066935e6905fece
parent75bfbe7915077ee9fe8502070dbff5195d74a271 (diff)
parent5c7589aa1615183fe390b23101de97858aa760a5 (diff)
Merge pull request #46 from Pheenoh/save_fix
Save Manager + misc fixes and improvements
-rw-r--r--Makefile3
-rw-r--r--external/misc/generate-patches.sh40
-rw-r--r--include/menus/cheats_menu.h1
-rw-r--r--include/menus/memory_menu.h1
-rw-r--r--include/menus/practice_menu.h19
-rw-r--r--include/save_injector.h27
-rw-r--r--include/save_manager.h (renamed from include/saves.h)102
-rw-r--r--include/utils/card.h1
-rw-r--r--include/utils/loading.h31
-rw-r--r--src/commands.cpp79
-rw-r--r--src/fs.cpp1
-rw-r--r--src/gz_flags.cpp3
-rw-r--r--src/lib.cpp18
-rw-r--r--src/menus/ad_saves_menu.cpp26
-rw-r--r--src/menus/any_saves_menu.cpp34
-rw-r--r--src/menus/hundo_saves_menu.cpp85
-rw-r--r--src/menus/memfiles_menu.cpp4
-rw-r--r--src/menus/practice_menu.cpp7
-rw-r--r--src/menus/settings_menu.cpp4
-rw-r--r--src/save_injector.cpp57
-rw-r--r--src/save_manager.cpp182
-rw-r--r--src/utils/card.cpp17
-rw-r--r--src/utils/loading.cpp119
23 files changed, 477 insertions, 384 deletions
diff --git a/Makefile b/Makefile
index 243eb3d..afd7fd0 100644
--- a/Makefile
+++ b/Makefile
@@ -30,12 +30,13 @@ EXTERNAL := external
DATA := data
INCLUDES := include external
MAKEFILES := $(shell find . -mindepth 2 -name Makefile)
+GZ_VERSION ?= 0.4
#---------------------------------------------------------------------------------
# options for code generation
#---------------------------------------------------------------------------------
-CFLAGS = -g -c -O2 -Wall $(MACHDEP) $(INCLUDE) -D $(PLATFORM)_$(REGION) -D $(PLATFORM)_PLATFORM
+CFLAGS = -g -c -O2 -Wall $(MACHDEP) $(INCLUDE) -D $(PLATFORM)_$(REGION) -D $(PLATFORM)_PLATFORM -D GZ_VERSION=$(GZ_VERSION)
CXXFLAGS = $(CFLAGS)
#---------------------------------------------------------------------------------
diff --git a/external/misc/generate-patches.sh b/external/misc/generate-patches.sh
new file mode 100644
index 0000000..41d55ab
--- /dev/null
+++ b/external/misc/generate-patches.sh
@@ -0,0 +1,40 @@
+#!/bin/bash
+export GZ_VERSION=$1
+
+if [ -z $GZ_VERSION ]
+then
+ echo "You need to specify a version. Ex: generate-patches.sh 1.0"
+ exit 1
+fi
+
+make clean
+
+# This can be optimized but too lazy atm
+export PLATFORM="GCN"
+export REGION="NTSCU"
+make
+romhack build --raw --patch
+mv ./build/tpgz.patch ./$GZ_VERSION-gcn-ntscu.patch
+make clean
+export REGION="NTSCJ"
+make
+romhack build --raw --patch
+mv ./build/tpgz.patch ./$GZ_VERSION-gcn-ntscj.patch
+make clean
+export REGION="PAL"
+make
+romhack build --raw --patch
+mv ./build/tpgz.patch ./$GZ_VERSION-gcn-pal.patch
+make clean
+export PLATFORM="WII"
+export REGION="NTSCU_10"
+make
+romhack build --raw --patch
+mv ./build/tpgzw.patch ./$GZ_VERSION-wii-ntscu-10.patch
+make clean
+export PLATFORM="WII"
+export REGION="PAL"
+make
+romhack build --raw --patch
+mv ./build/tpgzw.patch ./$GZ_VERSION-wii-pal.patch
+make clean \ No newline at end of file
diff --git a/include/menus/cheats_menu.h b/include/menus/cheats_menu.h
index af15797..6cafffc 100644
--- a/include/menus/cheats_menu.h
+++ b/include/menus/cheats_menu.h
@@ -1,3 +1,4 @@
+#pragma once
#include "menu.h"
class CheatsMenu : public Menu {
diff --git a/include/menus/memory_menu.h b/include/menus/memory_menu.h
index 93c165c..4682551 100644
--- a/include/menus/memory_menu.h
+++ b/include/menus/memory_menu.h
@@ -1,3 +1,4 @@
+#pragma once
#include "menu.h"
#define MAX_WATCHES 10
diff --git a/include/menus/practice_menu.h b/include/menus/practice_menu.h
index e00a9b4..7a0b327 100644
--- a/include/menus/practice_menu.h
+++ b/include/menus/practice_menu.h
@@ -1,4 +1,6 @@
+#pragma once
#include "menu.h"
+#include "save_manager.h"
#define ANY_INDEX 0
#define HUNDO_INDEX 1
@@ -8,21 +10,8 @@
extern bool inject_save_flag;
extern int last_save_index;
extern char last_category[5];
-CameraMatrix camera;
-uint16_t angle = 0;
-Vec3 position = {0, 0, 0};
-
-struct PracticeSaveInfo {
- uint8_t requirements;
- uint8_t _p0[1];
- uint16_t angle;
- Vec3 position;
- Vec3 cam_pos;
- Vec3 cam_target;
- uint32_t counter;
- char filename[32];
- uint8_t _p1[4];
-} __attribute__((packed));
+extern special* last_special_ptr;
+extern int last_special_size;
class PracticeMenu : public Menu {
public:
diff --git a/include/save_injector.h b/include/save_injector.h
deleted file mode 100644
index 4f5951f..0000000
--- a/include/save_injector.h
+++ /dev/null
@@ -1,27 +0,0 @@
-#pragma once
-
-#include "libtp_c/include/tp.h"
-
-// index into qlog where these exist
-#define SPAWN_INDEX 96
-#define ROOM_INDEX 97
-#define STAGE_INDEX 88
-
-struct PracticeFile {
- void (*inject_options_before_load)();
- void (*inject_options_during_load)();
- void (*inject_options_after_load)();
- int inject_options_after_counter = 0;
-};
-
-extern PracticeFile practice_file;
-
-namespace SaveInjector {
-
-void inject_save(void* buffer);
-void inject_memfile(void* buffer);
-void inject_default_before();
-void inject_default_during();
-void inject_default_after();
-
-} // namespace SaveInjector \ No newline at end of file
diff --git a/include/saves.h b/include/save_manager.h
index 83fd8ab..2e1ab91 100644
--- a/include/saves.h
+++ b/include/save_manager.h
@@ -7,11 +7,96 @@
#include "menus/scene_menu.h"
#include "menus/settings_menu.h"
#include "menus/tools_menu.h"
+#include "menus/hundo_saves_menu.h"
#include "libtp_c/include/system.h"
#define GZ_SAVE_VERSION_NUMBER 0
#define GZ_SAVE_ENTRIES_AMNT 10
+#ifdef GCN_NTSCU
+#define sTmpBuf 0x803ecf40
+#endif
+#ifdef GCN_PAL
+#define sTmpBuf 0x803eeee0
+#endif
+#ifdef GCN_NTSCJ
+#define sTmpBuf 0x803e7080
+#endif
+#ifdef WII_NTSCU_10
+#define sTmpBuf 0x8046a3e0
+#endif
+#ifdef WII_PAL
+#define sTmpBuf 0x804522e0
+#endif
+
+// index into qlog where these exist
+#define SPAWN_INDEX 96
+#define ROOM_INDEX 97
+#define STAGE_INDEX 88
+
+struct AreaReload {
+ uint8_t temp_flags[0x20];
+ uint16_t tears;
+};
+
+typedef void (*LoadingCallback)(void);
+
+class special {
+public:
+ special(int i_idx, LoadingCallback cb_during, LoadingCallback cb_after) {
+ idx = i_idx;
+ CallbackDuring = cb_during;
+ CallbackAfter = cb_after;
+ }
+
+ uint32_t idx;
+ LoadingCallback CallbackDuring;
+ LoadingCallback CallbackAfter;
+
+private:
+};
+
+struct PracticeFileOpts {
+ void (*inject_options_before_load)();
+ void (*inject_options_during_load)();
+ void (*inject_options_after_load)();
+ int inject_options_after_counter = 0;
+};
+
+struct PracticeSaveInfo {
+ uint8_t requirements;
+ uint8_t _p0[1];
+ uint16_t angle;
+ Vec3 position;
+ Vec3 cam_pos;
+ Vec3 cam_target;
+ uint32_t counter;
+ char filename[32];
+ uint8_t _p1[4];
+} __attribute__((packed));
+
+class SaveManager {
+public:
+ PracticeFileOpts mPracticeFileOpts;
+ PracticeSaveInfo mPracticeSaveInfo __attribute__((aligned(32)));
+ AreaReload mAreaReloadOpts;
+ special* mSpecials;
+ bool loading_initiated = false;
+
+public:
+ static void inject_save(void* buffer);
+ static void inject_memfile(void* buffer);
+ static void inject_default_before();
+ static void inject_default_during();
+ static void inject_default_after();
+ static void load_save(uint32_t id, char* category, special* i_specials = nullptr, int size = 0);
+ static void load_save_file(const char* fileName);
+ static void trigger_load();
+ static void default_load();
+};
+
+extern SaveManager gSaveManager;
+
// These numbers can only change when we change the GZ_SAVE_VERSION_NUMBER,
// otherwise, only new entries can be added.
enum GZSaveIndex {
@@ -52,21 +137,4 @@ struct GZSaveFile {
uint32_t offsets[GZ_SAVE_ENTRIES_AMNT];
uint32_t sizes[GZ_SAVE_ENTRIES_AMNT];
GZSaveLayout data;
-};
-
-typedef void (*LoadingCallback)(void);
-
-class special {
-public:
- special(int i_idx, LoadingCallback cb_during, LoadingCallback cb_after) {
- idx = i_idx;
- CallbackDuring = cb_during;
- CallbackAfter = cb_after;
- }
-
- uint32_t idx;
- LoadingCallback CallbackDuring;
- LoadingCallback CallbackAfter;
-
-private:
}; \ No newline at end of file
diff --git a/include/utils/card.h b/include/utils/card.h
index d2c6df5..e0a1985 100644
--- a/include/utils/card.h
+++ b/include/utils/card.h
@@ -1,7 +1,6 @@
#include "font.h"
#include "gcn_c/include/card.h"
#include "menu.h"
-#include "save_injector.h"
namespace Utilities {
int32_t card_write(CardInfo* card_info, void* data, int32_t size, int32_t offset,
diff --git a/include/utils/loading.h b/include/utils/loading.h
index 0dc0e14..07a880a 100644
--- a/include/utils/loading.h
+++ b/include/utils/loading.h
@@ -1,35 +1,8 @@
#pragma once
-#include <stdint.h>
-#include "saves.h"
-
-struct AreaReload {
- uint8_t temp_flags[0x20];
- uint16_t tears;
-};
-
-extern AreaReload g_area_reload;
-AreaReload g_area_reload;
-
-#ifdef GCN_NTSCU
-#define sTmpBuf 0x803ecf40
-#endif
-#ifdef GCN_PAL
-#define sTmpBuf 0x803eeee0
-#endif
-#ifdef GCN_NTSCJ
-#define sTmpBuf 0x803e7080
-#endif
-#ifdef WII_NTSCU_10
-#define sTmpBuf 0x8046a3e0
-#endif
-#ifdef WII_PAL
-#define sTmpBuf 0x804522e0
-#endif
+#include "save_manager.h"
namespace Utilities {
-void load_save(uint32_t id, char* category, special* i_specials = nullptr, int size = 0);
-void load_save_file(const char* fileName);
void set_camera_angle_position();
void set_angle_position();
-void trigger_load();
+
} // namespace Utilities \ No newline at end of file
diff --git a/src/commands.cpp b/src/commands.cpp
index 675a500..f85c6ac 100644
--- a/src/commands.cpp
+++ b/src/commands.cpp
@@ -12,8 +12,9 @@
#include "libtp_c/include/tp.h"
#include "menus/practice_menu.h"
#include "menus/settings_menu.h"
+#include "menus/hundo_saves_menu.h"
#include "movelink.h"
-#include "save_injector.h"
+
#include "timer.h"
#include "utils/loading.h"
@@ -36,21 +37,31 @@ static int button_last_frame;
static int button_this_frame;
void store_position() {
- saved_x = tp_zelAudio.link_debug_ptr->position.x;
- saved_y = tp_zelAudio.link_debug_ptr->position.y;
- saved_z = tp_zelAudio.link_debug_ptr->position.z;
- saved_angle = tp_zelAudio.link_debug_ptr->facing;
- saved_pos = tp_matrixInfo.matrix_info->pos;
- saved_target = tp_matrixInfo.matrix_info->target;
+ if (tp_zelAudio.link_debug_ptr) {
+ saved_x = tp_zelAudio.link_debug_ptr->position.x;
+ saved_y = tp_zelAudio.link_debug_ptr->position.y;
+ saved_z = tp_zelAudio.link_debug_ptr->position.z;
+ saved_angle = tp_zelAudio.link_debug_ptr->facing;
+ }
+
+ if (tp_matrixInfo.matrix_info) {
+ saved_pos = tp_matrixInfo.matrix_info->pos;
+ saved_target = tp_matrixInfo.matrix_info->target;
+ }
}
void load_position() {
- tp_zelAudio.link_debug_ptr->position.x = saved_x;
- tp_zelAudio.link_debug_ptr->position.y = saved_y;
- tp_zelAudio.link_debug_ptr->position.z = saved_z;
- tp_zelAudio.link_debug_ptr->facing = saved_angle;
- tp_matrixInfo.matrix_info->pos = saved_pos;
- tp_matrixInfo.matrix_info->target = saved_target;
+ if (tp_zelAudio.link_debug_ptr) {
+ tp_zelAudio.link_debug_ptr->position.x = saved_x;
+ tp_zelAudio.link_debug_ptr->position.y = saved_y;
+ tp_zelAudio.link_debug_ptr->position.z = saved_z;
+ tp_zelAudio.link_debug_ptr->facing = saved_angle;
+ }
+
+ if (tp_matrixInfo.matrix_info) {
+ tp_matrixInfo.matrix_info->pos = saved_pos;
+ tp_matrixInfo.matrix_info->target = saved_target;
+ }
}
void moon_jump() {
@@ -72,23 +83,30 @@ void hit_reset() {
void reload_area() {
inject_save_flag = true;
if (g_area_reload_behavior == LOAD_AREA) {
- tp_memcpy(tp_gameInfo.temp_flags.flags, g_area_reload.temp_flags,
- sizeof(g_area_reload.temp_flags)); // restore last set of saved temp flags
- tp_gameInfo.inventory.tears = g_area_reload.tears; // restore last tear count
- practice_file.inject_options_before_load = SaveInjector::inject_default_before;
- practice_file.inject_options_during_load = nullptr;
- practice_file.inject_options_after_load = nullptr;
+ tp_memcpy(
+ tp_gameInfo.temp_flags.flags, gSaveManager.mAreaReloadOpts.temp_flags,
+ sizeof(
+ gSaveManager.mAreaReloadOpts.temp_flags)); // restore last set of saved temp flags
+ tp_gameInfo.inventory.tears =
+ gSaveManager.mAreaReloadOpts.tears; // restore last tear count
+ gSaveManager.mPracticeFileOpts.inject_options_before_load =
+ SaveManager::inject_default_before;
+ gSaveManager.mPracticeFileOpts.inject_options_during_load = nullptr;
+ gSaveManager.mPracticeFileOpts.inject_options_after_load = nullptr;
} else {
- Utilities::load_save(last_save_index, last_category, nullptr, 0xFF);
+ SaveManager::load_save(last_save_index, last_category, last_special_ptr, 0xFF);
}
} // namespace Commands
void gorge_void() {
if (button_this_frame == GORGE_VOID_BUTTONS && button_last_frame != GORGE_VOID_BUTTONS) {
- Utilities::load_save_file("tpgz/save_files/any/gorge_void.bin");
- practice_file.inject_options_before_load = SaveInjector::inject_default_before;
- practice_file.inject_options_during_load = GorgeVoidIndicator::warp_to_gorge;
- practice_file.inject_options_after_load = GorgeVoidIndicator::prep_rupee_roll;
+ SaveManager::load_save_file("tpgz/save_files/any/gorge_void.bin");
+ gSaveManager.mPracticeFileOpts.inject_options_before_load =
+ SaveManager::inject_default_before;
+ gSaveManager.mPracticeFileOpts.inject_options_during_load =
+ GorgeVoidIndicator::warp_to_gorge;
+ gSaveManager.mPracticeFileOpts.inject_options_after_load =
+ GorgeVoidIndicator::prep_rupee_roll;
inject_save_flag = true;
}
}
@@ -96,11 +114,14 @@ void gorge_void() {
#ifdef WII_PLATFORM
void back_in_time() {
if (button_this_frame == BACK_IN_TIME_BUTTONS && button_last_frame != BACK_IN_TIME_BUTTONS) {
- Utilities::load_save_file("tpgz/save_files/any/ordon_gate_clip.bin");
- practice_file.inject_options_before_load = SaveInjector::inject_default_before;
- practice_file.inject_options_during_load = SaveInjector::inject_default_during;
- practice_file.inject_options_after_load = BiTIndicator::set_camera_angle_position;
- practice_file.inject_options_after_counter = 10;
+ SaveManager::load_save_file("tpgz/save_files/any/ordon_gate_clip.bin");
+ gSaveManager.mPracticeFileOpts.inject_options_before_load =
+ gSaveManager.inject_default_before;
+ gSaveManager.mPracticeFileOpts.inject_options_during_load =
+ gSaveManager.inject_default_during;
+ gSaveManager.mPracticeFileOpts.inject_options_after_load =
+ BiTIndicator::set_camera_angle_position;
+ gSaveManager.mPracticeFileOpts.inject_options_after_counter = 10;
inject_save_flag = true;
}
}
diff --git a/src/fs.cpp b/src/fs.cpp
index 985e8e5..06de68f 100644
--- a/src/fs.cpp
+++ b/src/fs.cpp
@@ -2,7 +2,6 @@
#include "font.h"
#include "gcn_c/include/dvd.h"
#include "libtp_c/include/system.h"
-#include "save_injector.h"
void loadFile(const char* filePath, void* buffer, signed long length, signed long offset) {
DVDFileInfo fileInfo;
diff --git a/src/gz_flags.cpp b/src/gz_flags.cpp
index 8203041..c4b23a0 100644
--- a/src/gz_flags.cpp
+++ b/src/gz_flags.cpp
@@ -14,6 +14,7 @@
#include "utils/link.h"
#include "utils/loading.h"
#include "flaglog.h"
+#include "save_manager.h"
#include "menus/memfiles_menu.h"
bool inject_save_flag = false;
@@ -25,7 +26,7 @@ GZFlag GZ_Flags[MAX_GZ_FLAGS] = {
#endif
{&ToolItems[Tools::ROLL_INDEX].active, RollIndicator::run},
{&g_flag_log_active, FlagLog::run},
- {&inject_save_flag, Utilities::trigger_load},
+ {&inject_save_flag, SaveManager::trigger_load},
{&SceneItems[Scene::FREEZE_ACTOR_INDEX].active, Actor::freeze_actors, Actor::unfreeze_actors},
{&SceneItems[Scene::HIDE_ACTOR_INDEX].active, Actor::hide_actors, Actor::show_actors},
{&SceneItems[Scene::FREEZE_CAMERA_INDEX].active, System::lock_camera, System::unlock_camera},
diff --git a/src/lib.cpp b/src/lib.cpp
index c60be21..bb1f40a 100644
--- a/src/lib.cpp
+++ b/src/lib.cpp
@@ -29,6 +29,9 @@ bool last_frame_was_loading = false;
extern "C" {
+#define Q(x) #x
+#define QUOTE(x) Q(x)
+
#if (GCN_NTSCU)
#define main_tampoline ((void (*)(void))0x803737b4)
#endif
@@ -44,6 +47,9 @@ extern "C" {
#if (WII_PAL)
#define main_tampoline ((void (*)(void))0x803b929c)
#endif
+#ifdef GZ_VERSION
+#define INTERNAL_GZ_VERSION QUOTE(GZ_VERSION)
+#endif
void apply_lib_hooks() {
Hook::apply_hooks();
@@ -91,7 +97,7 @@ void game_loop() {
MenuRendering::set_menu(MN_MAIN_MENU_INDEX);
fifo_visible = false;
}
- if (tp_fopScnRq.isLoading == 1) {
+ if (tp_fopScnRq.isLoading) {
MenuRendering::close_active_menus();
move_link_active = false;
last_frame_was_loading = true;
@@ -99,10 +105,10 @@ void game_loop() {
}
// save temp flags and tears after every loading zone
- if (last_frame_was_loading && tp_fopScnRq.isLoading != 1) {
- tp_memcpy(g_area_reload.temp_flags, tp_gameInfo.temp_flags.flags,
+ if (last_frame_was_loading && !tp_fopScnRq.isLoading) {
+ tp_memcpy(gSaveManager.mAreaReloadOpts.temp_flags, tp_gameInfo.temp_flags.flags,
sizeof(tp_gameInfo.temp_flags.flags));
- g_area_reload.tears = tp_gameInfo.inventory.tears;
+ gSaveManager.mAreaReloadOpts.tears = tp_gameInfo.inventory.tears;
last_frame_was_loading = false;
}
@@ -119,8 +125,8 @@ void draw() {
setupRendering();
// Consolas.setupRendering();
if (MenuRendering::is_menu_open()) {
- Font::gz_renderChars("tpgz v0.3", sprite_offsets[MENU_INDEX].x + 35.0f, 25.0f, cursor_rgba,
- g_drop_shadows);
+ Font::gz_renderChars("tpgz v" INTERNAL_GZ_VERSION, sprite_offsets[MENU_INDEX].x + 35.0f,
+ 25.0f, cursor_rgba, g_drop_shadows);
if (gzIconTex.loadCode == TexCode::TEX_OK) {
Draw::draw_rect(0xFFFFFFFF, {sprite_offsets[MENU_INDEX].x, 5.0f}, {30, 30},
&gzIconTex._texObj);
diff --git a/src/menus/ad_saves_menu.cpp b/src/menus/ad_saves_menu.cpp
index 6baa8d2..16b2f0f 100644
--- a/src/menus/ad_saves_menu.cpp
+++ b/src/menus/ad_saves_menu.cpp
@@ -7,7 +7,7 @@
#include "libtp_c/include/tp.h"
#include "menus/practice_menu.h"
#include "rollcheck.h"
-#include "save_injector.h"
+
#include "utils/cursor.h"
#include "utils/lines.h"
#include "utils/loading.h"
@@ -72,9 +72,9 @@ Line lines[LINES] = {
{"horseback ganon", AD_HORSEBACK_INDEX, "The horseback Ganondorf fight"}};
void default_load() {
- practice_file.inject_options_before_load = SaveInjector::inject_default_before;
- practice_file.inject_options_during_load = SaveInjector::inject_default_during;
- practice_file.inject_options_after_load = SaveInjector::inject_default_after;
+ gSaveManager.mPracticeFileOpts.inject_options_before_load = SaveManager::inject_default_before;
+ gSaveManager.mPracticeFileOpts.inject_options_during_load = SaveManager::inject_default_during;
+ gSaveManager.mPracticeFileOpts.inject_options_after_load = SaveManager::inject_default_after;
inject_save_flag = true;
fifo_visible = true;
MenuRendering::set_menu(MN_NONE_INDEX);
@@ -82,14 +82,14 @@ void default_load() {
}
void hugo() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.temp_flags.flags[14] = 128; // midna trigger off
tp_gameInfo.temp_flags.flags[12] = 0; // hugo alive
}
void karg_oob() {
- practice_file.inject_options_before_load = nullptr;
- SaveInjector::inject_default_during();
+ gSaveManager.mPracticeFileOpts.inject_options_before_load = nullptr;
+ gSaveManager.inject_default_during();
tp_gameInfo.respawn_animation = 0xA; // spawn on kargorok
tp_gameInfo.link.is_wolf = false;
}
@@ -100,18 +100,18 @@ void morpheel() {
}
void stallord() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.boss_room_event_flags = 48; // turn off intro cs, start fight
tp_gameInfo.warp.entrance.spawn = 0x01; // spawn at in front of stally
}
void argorok() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.boss_room_event_flags = 1;
}
void palace1() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.dungeon_temp_flags.switch_bitfield[0] = 0; // reset palace switches
}
@@ -120,13 +120,13 @@ void palace2() {
}
void lakebed_bk_skip_during() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.temp_flags.flags[11] = 18; // bridge turned
tp_gameInfo.temp_flags.flags[20] = 223; // dungeon intro cs off
}
void bossflags() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
TP::set_boss_flags();
}
@@ -157,7 +157,7 @@ void ADSavesMenu::render() {
}
if (current_input == SELECTION_BUTTON && a_held == false) {
- Utilities::load_save(cursor.y, (char*)"ad", ADSpecials, AD_SPECIALS_AMNT);
+ SaveManager::load_save(cursor.y, (char*)"ad", ADSpecials, AD_SPECIALS_AMNT);
init_once = false;
}
diff --git a/src/menus/any_saves_menu.cpp b/src/menus/any_saves_menu.cpp
index d298bdf..2e97ba3 100644
--- a/src/menus/any_saves_menu.cpp
+++ b/src/menus/any_saves_menu.cpp
@@ -7,7 +7,7 @@
#include "libtp_c/include/tp.h"
#include "menus/practice_menu.h"
#include "rollcheck.h"
-#include "save_injector.h"
+
#include "utils/cursor.h"
#include "utils/lines.h"
#include "utils/loading.h"
@@ -70,25 +70,15 @@ Line lines[LINES] = {
{"beast ganon", BEAST_GANON_INDEX, "The Beast Ganon fight"},
{"horseback ganon", HORSEBACK_GANON_INDEX, "The horseback Ganondorf fight"}};
-void default_load() {
- practice_file.inject_options_before_load = SaveInjector::inject_default_before;
- practice_file.inject_options_during_load = SaveInjector::inject_default_during;
- practice_file.inject_options_after_load = SaveInjector::inject_default_after;
- inject_save_flag = true;
- fifo_visible = true;
- MenuRendering::set_menu(MN_NONE_INDEX);
- init_once = false;
-}
-
void hugo() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.temp_flags.flags[14] = 128; // midna trigger off
tp_gameInfo.temp_flags.flags[12] = 0; // hugo alive
}
void karg_oob() {
- practice_file.inject_options_before_load = nullptr;
- SaveInjector::inject_default_during();
+ gSaveManager.mPracticeFileOpts.inject_options_before_load = nullptr;
+ gSaveManager.inject_default_during();
tp_gameInfo.respawn_animation = 0xA; // spawn on kargorok
tp_gameInfo.link.is_wolf = false;
}
@@ -99,23 +89,23 @@ void morpheel() {
}
void stallord() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.boss_room_event_flags = 48; // turn off intro cs, start fight
tp_gameInfo.warp.entrance.spawn = 0x01; // spawn at in front of stally
}
void fan_tower() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.dungeon_temp_flags.switch_bitfield[0] = 0; // reset city switches
}
void argorok() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.boss_room_event_flags = 1;
}
void palace1() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.dungeon_temp_flags.switch_bitfield[0] = 0; // reset palace switches
}
@@ -124,13 +114,13 @@ void palace2() {
}
void lakebed_bk_skip_during() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.temp_flags.flags[11] = 18; // bridge turned
tp_gameInfo.temp_flags.flags[20] = 223; // dungeon intro cs off
}
void bossflags() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
TP::set_boss_flags();
}
@@ -139,7 +129,7 @@ void darkhammer() {
}
void waterfall_sidehop() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.spawn_speed = 10.0f; // link spawns swimming forward
}
@@ -175,7 +165,7 @@ void AnySavesMenu::render() {
}
if (current_input == SELECTION_BUTTON && a_held == false) {
- Utilities::load_save(cursor.y, (char*)"any", AnySpecials, ANY_SPECIALS_AMNT);
+ SaveManager::load_save(cursor.y, (char*)"any", AnySpecials, ANY_SPECIALS_AMNT);
init_once = false;
}
diff --git a/src/menus/hundo_saves_menu.cpp b/src/menus/hundo_saves_menu.cpp
index 3d4b69a..cc97c9d 100644
--- a/src/menus/hundo_saves_menu.cpp
+++ b/src/menus/hundo_saves_menu.cpp
@@ -1,4 +1,3 @@
-#include "menus/hundo_saves_menu.h"
#include "controller.h"
#include "fifo_queue.h"
#include "gorge.h"
@@ -7,7 +6,7 @@
#include "libtp_c/include/tp.h"
#include "menus/practice_menu.h"
#include "rollcheck.h"
-#include "save_injector.h"
+
#include "utils/cursor.h"
#include "utils/lines.h"
#include "utils/loading.h"
@@ -106,9 +105,9 @@ Line lines[LINES] = {
{"horseback ganon", HND_HORSEBACK_GANON_INDEX, "the horseback ganon fight"}};
void default_load() {
- practice_file.inject_options_before_load = SaveInjector::inject_default_before;
- practice_file.inject_options_during_load = SaveInjector::inject_default_during;
- practice_file.inject_options_after_load = SaveInjector::inject_default_after;
+ gSaveManager.mPracticeFileOpts.inject_options_before_load = SaveManager::inject_default_before;
+ gSaveManager.mPracticeFileOpts.inject_options_during_load = SaveManager::inject_default_during;
+ gSaveManager.mPracticeFileOpts.inject_options_after_load = SaveManager::inject_default_after;
inject_save_flag = true;
fifo_visible = true;
MenuRendering::set_menu(MN_NONE_INDEX);
@@ -116,39 +115,39 @@ void default_load() {
}
void set_camera_angle_position() {
- tp_matrixInfo.matrix_info->target = camera.target;
- tp_matrixInfo.matrix_info->pos = camera.pos;
- tp_zelAudio.link_debug_ptr->facing = angle;
- tp_zelAudio.link_debug_ptr->position = position;
+ tp_matrixInfo.matrix_info->target = gSaveManager.mPracticeSaveInfo.cam_target;
+ tp_matrixInfo.matrix_info->pos = gSaveManager.mPracticeSaveInfo.cam_pos;
+ tp_zelAudio.link_debug_ptr->facing = gSaveManager.mPracticeSaveInfo.angle;
+ tp_zelAudio.link_debug_ptr->position = gSaveManager.mPracticeSaveInfo.position;
}
void set_angle_position() {
- tp_zelAudio.link_debug_ptr->facing = angle;
- tp_zelAudio.link_debug_ptr->position = position;
+ tp_zelAudio.link_debug_ptr->facing = gSaveManager.mPracticeSaveInfo.angle;
+ tp_zelAudio.link_debug_ptr->position = gSaveManager.mPracticeSaveInfo.position;
}
void goats_1() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.warp.entrance.state = 0x5;
}
void goats_2() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.warp.entrance.state = 0x4;
}
void purple_mist() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.link.is_wolf = false;
}
void kb2_skip() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.warp.entrance.state = 0x3;
}
void escort() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.warp.entrance.room = 0xD;
tp_gameInfo.warp.entrance.spawn = 0x62;
tp_gameInfo.warp.entrance.state = 0x2;
@@ -156,26 +155,26 @@ void escort() {
}
void dangoro() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.boss_room_event_flags = 32; // turn off intro cs, start fight
}
void morpheel() {
tp_zelAudio.link_debug_ptr->current_item = 68; // clawshot
tp_zelAudio.link_debug_ptr->current_boots = 2; // ib
- angle = 10754;
- position = {-1193.0f, -23999.0f, -770.0f};
+ gSaveManager.mPracticeSaveInfo.angle = 10754;
+ gSaveManager.mPracticeSaveInfo.position = {-1193.0f, -23999.0f, -770.0f};
set_angle_position();
}
void karg_oob() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.respawn_animation = 0xA; // spawn on kargorok
tp_gameInfo.link.is_wolf = false;
}
void iza_1_skip() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.respawn_animation = 0xA; // spawn on kargorok
tp_strcpy((char*)tp_gameInfo.warp.entrance.stage, "F_SP112"); // set stage to river
tp_gameInfo.warp.entrance.room = 0x1;
@@ -184,79 +183,79 @@ void iza_1_skip() {
}
void stallord() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.boss_room_event_flags = 48; // turn off intro cs, start fight
tp_gameInfo.warp.entrance.spawn = 0x01; // spawn at in front of stally
}
void spr_bosskey() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.warp.entrance.room = 0xB; // boss key room
tp_gameInfo.warp.entrance.spawn = 0x00; // default spawn
}
void tot_early_poe() {
- SaveInjector::inject_default_during();
- angle = 49299;
- position = {-2462.85f, 2750.0f, -7.10f};
+ gSaveManager.inject_default_during();
+ gSaveManager.mPracticeSaveInfo.angle = 49299;
+ gSaveManager.mPracticeSaveInfo.position = {-2462.85f, 2750.0f, -7.10f};
set_angle_position();
}
void tot_early_hp() {
- SaveInjector::inject_default_during();
- angle = 49152;
- position = {-8000.50f, 5100.0f, -3226.17f};
+ gSaveManager.inject_default_during();
+ gSaveManager.mPracticeSaveInfo.angle = 49152;
+ gSaveManager.mPracticeSaveInfo.position = {-8000.50f, 5100.0f, -3226.17f};
set_angle_position();
}
void hugo_archery() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
// tp_gameInfo.temp_flags.flags[14] = 0xC0; // start archery minigame
}
void cits_poe_cycle() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.warp.entrance.spawn = 0x0;
- angle = 71;
- position = {-14005.31f, 3000.0f, -15854.05f};
+ gSaveManager.mPracticeSaveInfo.angle = 71;
+ gSaveManager.mPracticeSaveInfo.position = {-14005.31f, 3000.0f, -15854.05f};
set_angle_position();
}
void fan_tower() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.dungeon_temp_flags.switch_bitfield[0] = 0; // reset city switches
}
void argorok() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.boss_room_event_flags = 1;
}
void palace1() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.dungeon_temp_flags.switch_bitfield[0] = 0; // reset palace switches
}
void palace2() {
tp_zelAudio.link_debug_ptr->current_item = 3; // master sword
- SaveInjector::inject_default_during();
- angle = 32731;
- position = {251.83f, -200.0f, 10993.50f};
+ gSaveManager.inject_default_during();
+ gSaveManager.mPracticeSaveInfo.angle = 32731;
+ gSaveManager.mPracticeSaveInfo.position = {251.83f, -200.0f, 10993.50f};
set_angle_position();
}
void lakebed_bk_skip_during() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.temp_flags.flags[20] = 223; // dungeon intro cs off
}
void bossflags() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
TP::set_boss_flags();
}
void cave_of_ordeals() {
- SaveInjector::inject_default_during();
+ gSaveManager.inject_default_during();
tp_gameInfo.dungeon_temp_flags.switch_bitfield[0] = 0; // reset all CoO doors
}
@@ -302,7 +301,7 @@ void HundoSavesMenu::render() {
}
if (current_input == SELECTION_BUTTON && a_held == false) {
- Utilities::load_save(cursor.y, (char*)"hundo", HundoSpecials, HND_SPECIALS_AMNT);
+ SaveManager::load_save(cursor.y, (char*)"hundo", HundoSpecials, HND_SPECIALS_AMNT);
init_once = false;
}
diff --git a/src/menus/memfiles_menu.cpp b/src/menus/memfiles_menu.cpp
index e5613d3..4c48057 100644
--- a/src/menus/memfiles_menu.cpp
+++ b/src/menus/memfiles_menu.cpp
@@ -102,7 +102,9 @@ void MemfilesMenu::render() {
card.sector_size = SECTOR_SIZE;
tp_sprintf(card.file_name_buffer, card.file_name);
card.card_result = CARDProbeEx(0, NULL, &card.sector_size);
- Utilities::load_memfile(card);
+ if (card.card_result == Ready) {
+ Utilities::load_memfile(card);
+ }
set_position_data = true;
break;
}
diff --git a/src/menus/practice_menu.cpp b/src/menus/practice_menu.cpp
index 1077dcb..f052582 100644
--- a/src/menus/practice_menu.cpp
+++ b/src/menus/practice_menu.cpp
@@ -2,7 +2,7 @@
#include "controller.h"
#include "font.h"
#include "libtp_c/include/tp.h"
-#include "save_injector.h"
+
#include "utils/cursor.h"
#include "utils/lines.h"
@@ -10,7 +10,10 @@
static Cursor cursor = {0, 0};
bool init_once = false;
-PracticeFile practice_file;
+char last_category[5];
+int last_save_index;
+int last_special_size;
+special* last_special_ptr;
Line lines[LINES] = {{"any%", ANY_INDEX, "Any% practice saves", false},
{"100%", HUNDO_INDEX, "100% practice saves", false},
diff --git a/src/menus/settings_menu.cpp b/src/menus/settings_menu.cpp
index 9c99e86..1e22e93 100644
--- a/src/menus/settings_menu.cpp
+++ b/src/menus/settings_menu.cpp
@@ -88,7 +88,9 @@ void SettingsMenu::render() {
card.sector_size = SECTOR_SIZE;
tp_sprintf(card.file_name_buffer, card.file_name);
card.card_result = CARDProbeEx(0, NULL, &card.sector_size);
- Utilities::load_mem_card(card);
+ if (card.card_result == Ready) {
+ Utilities::load_mem_card(card);
+ }
break;
};
case SWAP_EQUIPS_INDEX: {
diff --git a/src/save_injector.cpp b/src/save_injector.cpp
deleted file mode 100644
index ff23c0a..0000000
--- a/src/save_injector.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-#include "save_injector.h"
-#include "fs.h"
-#include "libtp_c/include/system.h"
-#include "libtp_c/include/tp.h"
-#include "menus/settings_menu.h"
-#include "menu.h"
-
-namespace SaveInjector {
-
-// inject qlog bytes into RAM
-void inject_save(void* buffer) {
- tp_memcpy((void*)&tp_gameInfo, buffer, 2392);
- tp_getSave(&tp_gameInfo, tp_gameInfo.dungeon_temp_flags.mStageNum);
-};
-
-void inject_memfile(void* buffer) {
- tp_memcpy((void*)&tp_gameInfo, buffer, 3818);
- tp_getSave(&tp_gameInfo, tp_gameInfo.dungeon_temp_flags.mStageNum);
-};
-
-void inject_default_before() {
- tp_gameInfo.spawn_speed = 0.0f;
- tp_gameInfo.loading_animation = 13; // instant load
- tp_gameInfo.respawn_animation = 0;
- tp_gameInfo.warp.entrance.void_flag = 0;
-}
-
-void inject_default_during() {
- int state = tp_getLayerNo((char*)tp_gameInfo.player.player_stage,
- tp_gameInfo.player.player_room_id, 0xFF);
- tp_gameInfo.warp.entrance.spawn = tp_gameInfo.player.player_spawn_id;
- tp_gameInfo.special_spawn_id = tp_gameInfo.player.player_spawn_id;
- tp_gameInfo.warp.entrance.room = tp_gameInfo.player.player_room_id;
- tp_strcpy((char*)tp_gameInfo.warp.entrance.stage, (char*)tp_gameInfo.player.player_stage);
- tp_gameInfo.warp.entrance.state = state;
-
- // fixes some bug causing link to auto drown, figure out later
- tp_gameInfo.link_air_meter = 600;
- tp_gameInfo.link_air_meter_2 = 600;
- tp_gameInfo.link_max_air_meter = 600;
-
-#ifdef GCN_PLATFORM
- if (g_swap_equips_flag) {
- uint8_t tmp = tp_gameInfo.link.item_on_x;
- uint8_t tmp_mix = tp_gameInfo.link.slot_x_combo_item;
-
- tp_gameInfo.link.item_on_x = tp_gameInfo.link.item_on_y;
- tp_gameInfo.link.item_on_y = tmp;
- tp_gameInfo.link.slot_x_combo_item = tp_gameInfo.link.slot_y_combo_item;
- tp_gameInfo.link.slot_y_combo_item = tmp_mix;
- }
-#endif
- // add wii swap equip logic here later
-}
-
-void inject_default_after() {}
-} // namespace SaveInjector \ No newline at end of file
diff --git a/src/save_manager.cpp b/src/save_manager.cpp
new file mode 100644
index 0000000..87fb0c1
--- /dev/null
+++ b/src/save_manager.cpp
@@ -0,0 +1,182 @@
+
+#include "fs.h"
+#include "libtp_c/include/system.h"
+#include "libtp_c/include/tp.h"
+#include "libtp_c/include/gc/OSCache.h"
+#include "menus/settings_menu.h"
+#include "menus/practice_menu.h"
+#include "save_manager.h"
+#include "menu.h"
+#include "utils/loading.h"
+#include "fifo_queue.h"
+
+int apply_after_counter = 0;
+int injection_counter = 0;
+char currentFileName[80];
+SaveManager gSaveManager;
+
+void SaveManager::inject_save(void* buffer) {
+ tp_memcpy((void*)&tp_gameInfo, buffer, 2392);
+ tp_getSave(&tp_gameInfo, tp_gameInfo.dungeon_temp_flags.mStageNum);
+};
+
+void SaveManager::inject_memfile(void* buffer) {
+ tp_memcpy((void*)&tp_gameInfo, buffer, 3818);
+ tp_getSave(&tp_gameInfo, tp_gameInfo.dungeon_temp_flags.mStageNum);
+};
+
+void SaveManager::inject_default_before() {
+ tp_gameInfo.spawn_speed = 0.0f;
+ tp_gameInfo.loading_animation = 13; // instant load
+ tp_gameInfo.respawn_animation = 0;
+ tp_gameInfo.warp.entrance.void_flag = 0;
+}
+
+void SaveManager::inject_default_during() {
+ // Load the save file over game info
+ SaveManager::load_save_file(currentFileName);
+
+ // Get default state based on file info
+ int state = tp_getLayerNo((char*)tp_gameInfo.player.player_stage,
+ tp_gameInfo.player.player_room_id, 0xFF);
+
+ // Next stage info
+ tp_gameInfo.special_spawn_id = tp_gameInfo.player.player_spawn_id;
+ tp_gameInfo.warp.entrance.room = tp_gameInfo.player.player_room_id;
+ tp_gameInfo.warp.entrance.spawn = tp_gameInfo.player.player_spawn_id;
+ tp_strcpy((char*)tp_gameInfo.warp.entrance.stage, (char*)tp_gameInfo.player.player_stage);
+ tp_gameInfo.warp.entrance.state = state;
+
+ // fixes some bug causing link to auto drown, figure out later
+ tp_gameInfo.link_air_meter = 600;
+ tp_gameInfo.link_air_meter_2 = 600;
+ tp_gameInfo.link_max_air_meter = 600;
+
+#ifdef GCN_PLATFORM
+ if (g_swap_equips_flag) {
+ uint8_t tmp = tp_gameInfo.link.item_on_x;
+ uint8_t tmp_mix = tp_gameInfo.link.slot_x_combo_item;
+
+ tp_gameInfo.link.item_on_x = tp_gameInfo.link.item_on_y;
+ tp_gameInfo.link.item_on_y = tmp;
+ tp_gameInfo.link.slot_x_combo_item = tp_gameInfo.link.slot_y_combo_item;
+ tp_gameInfo.link.slot_y_combo_item = tmp_mix;
+ }
+#endif
+ // add wii swap equip logic here later
+}
+
+void SaveManager::inject_default_after() {}
+
+void SaveManager::default_load() {
+ gSaveManager.mPracticeFileOpts.inject_options_during_load = SaveManager::inject_default_during;
+ gSaveManager.mPracticeFileOpts.inject_options_after_load = SaveManager::inject_default_after;
+ inject_save_flag = true;
+ fifo_visible = true;
+ MenuRendering::set_menu(MN_NONE_INDEX);
+}
+
+void SaveManager::load_save(uint32_t id, char* category, special i_specials[], int size) {
+ SaveManager::inject_default_before();
+
+ // Load the corresponding file path and properties
+ tp_sprintf(currentFileName, "tpgz/save_files/%s.bin", category);
+ loadFile(currentFileName, &gSaveManager.mPracticeSaveInfo,
+ sizeof(gSaveManager.mPracticeSaveInfo), id * sizeof(gSaveManager.mPracticeSaveInfo));
+ tp_sprintf(currentFileName, "tpgz/save_files/%s/%s.bin", category,
+ gSaveManager.mPracticeSaveInfo.filename);
+
+ // 0xFF is used to identify a call from file reload, which doesn't need to run the default load
+ if (size != 0xFF) {
+ SaveManager::default_load();
+ } else {
+ size = last_special_size;
+ }
+
+ if (gSaveManager.mPracticeSaveInfo.requirements) {
+ gSaveManager.mPracticeFileOpts.inject_options_after_load =
+ gSaveManager.mPracticeSaveInfo.requirements & REQ_CAM ?
+ Utilities::set_camera_angle_position :
+ Utilities::set_angle_position;
+ gSaveManager.mPracticeFileOpts.inject_options_after_counter =
+ gSaveManager.mPracticeSaveInfo.counter;
+ }
+
+ tp_bossFlags = 0;
+
+ // If the selected file was a special, run the special callbacks
+ if (i_specials) {
+ for (int i = 0; i < size; ++i) {
+ if (id == i_specials[i].idx) {
+ if (i_specials[i].CallbackDuring) {
+ gSaveManager.mPracticeFileOpts.inject_options_during_load =
+ i_specials[i].CallbackDuring;
+ }
+ if (i_specials[i].CallbackAfter) {
+ gSaveManager.mPracticeFileOpts.inject_options_after_load =
+ i_specials[i].CallbackAfter;
+ }
+ }
+ }
+ }
+
+ // Store all the info in case file reload is used
+ last_save_index = id;
+ tp_strcpy(last_category, category);
+ last_special_ptr = i_specials;
+ last_special_size = size;
+}
+
+void SaveManager::load_save_file(const char* fileName) {
+ loadFile(fileName, (void*)sTmpBuf, 2400, 0);
+ SaveManager::inject_save((void*)sTmpBuf);
+}
+
+void SaveManager::trigger_load() {
+ // Loading hasn't started yet, run the before load function and initiate loading
+ if (!tp_fopScnRq.isLoading && !gSaveManager.loading_initiated) {
+ // Patch out setWaterDropColor call temporarily (prevents a crash in some scenarios)
+ *reinterpret_cast<uint32_t*>(0x800CCE08) = 0x60000000; // nop
+ gc::os_cache::DCFlushRange((void*)(0x800CCE08), sizeof(uint32_t));
+ gc::os_cache::ICInvalidateRange((void*)(0x800CCE08), sizeof(uint32_t));
+
+ // Trigger loading
+ tp_gameInfo.warp.enabled = true;
+ }
+
+ // Loading has started, run the during load function
+ if (tp_fopScnRq.isLoading && tp_gameInfo.warp.enabled) {
+ if (gSaveManager.mPracticeFileOpts.inject_options_during_load) {
+ gSaveManager.mPracticeFileOpts.inject_options_during_load();
+ }
+ gSaveManager.loading_initiated = true;
+ tp_gameInfo.warp.enabled = false;
+ }
+
+ if (gSaveManager.loading_initiated) {
+ // Loading has completed, run the after load function
+ if (!tp_fopScnRq.isLoading) {
+ // Patch back in setWaterDropColor call
+ *reinterpret_cast<uint32_t*>(0x800CCE08) =
+ 0x4BFFF55D; // bl daAlink_c::setWaterDropColor
+ gc::os_cache::DCFlushRange((void*)(0x800CCE08), sizeof(uint32_t));
+ gc::os_cache::ICInvalidateRange((void*)(0x800CCE08), sizeof(uint32_t));
+
+ if (gSaveManager.mPracticeFileOpts.inject_options_after_load) {
+ gSaveManager.mPracticeFileOpts.inject_options_after_load();
+ }
+
+ if (gSaveManager.mPracticeFileOpts.inject_options_after_counter ==
+ apply_after_counter) {
+ apply_after_counter = 0;
+ gSaveManager.mPracticeFileOpts.inject_options_after_load = nullptr;
+ gSaveManager.mPracticeFileOpts.inject_options_after_counter = 0;
+ gSaveManager.loading_initiated = false;
+
+ inject_save_flag = false;
+ } else {
+ apply_after_counter++;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/utils/card.cpp b/src/utils/card.cpp
index 3f6f68b..fb00acb 100644
--- a/src/utils/card.cpp
+++ b/src/utils/card.cpp
@@ -5,10 +5,10 @@
#include "libtp_c/include/math.h"
#include "libtp_c/include/system.h"
#include "menus/practice_menu.h"
-#include "save_injector.h"
+
#include "libtp_c/include/tp.h"
#include "menus/memfiles_menu.h"
-#include "saves.h"
+#include "save_manager.h"
namespace Utilities {
/**
@@ -283,10 +283,10 @@ void load_memfile(Card& card) {
if (card.card_result == Ready) {
tp_osReport("loaded memfile!");
FIFOQueue::push("loaded memfile!", Queue);
- SaveInjector::inject_default_before();
- SaveInjector::inject_memfile((void*)sTmpBuf);
- SaveInjector::inject_default_during();
- SaveInjector::inject_default_after();
+ SaveManager::inject_default_before();
+ SaveManager::inject_memfile((void*)sTmpBuf);
+ SaveManager::inject_default_during();
+ SaveManager::inject_default_after();
load_position_data(posData);
inject_save_flag = true;
fifo_visible = true;
@@ -313,10 +313,9 @@ void load_gz_card(bool& card_load) {
card.card_result = CARDProbeEx(0, NULL, &card.sector_size);
if (card.card_result == Ready) {
Utilities::load_mem_card(card);
- card_load = false;
- } else {
- card_load = false;
}
+
+ card_load = false;
}
}
} // namespace Utilities \ No newline at end of file
diff --git a/src/utils/loading.cpp b/src/utils/loading.cpp
index ccf591e..6da3fb8 100644
--- a/src/utils/loading.cpp
+++ b/src/utils/loading.cpp
@@ -4,123 +4,24 @@
#include "libtp_c/include/system.h"
#include "libtp_c/include/tp.h"
#include "menus/practice_menu.h"
-#include "save_injector.h"
-#include "menus/any_saves_menu.h"
-bool loading_initiated = false;
-int apply_after_counter = 0;
-char last_category[5];
-int last_save_index;
+#include "menus/any_saves_menu.h"
+#include "save_manager.h"
namespace Utilities {
void set_camera_angle_position() {
- tp_matrixInfo.matrix_info->target = camera.target;
- tp_matrixInfo.matrix_info->pos = camera.pos;
- tp_zelAudio.link_debug_ptr->facing = angle;
- tp_zelAudio.link_debug_ptr->position = position;
+ tp_matrixInfo.matrix_info->target = gSaveManager.mPracticeSaveInfo.cam_target;
+ tp_matrixInfo.matrix_info->pos = gSaveManager.mPracticeSaveInfo.cam_pos;
+ tp_zelAudio.link_debug_ptr->facing = gSaveManager.mPracticeSaveInfo.angle;
+ tp_zelAudio.link_debug_ptr->position = gSaveManager.mPracticeSaveInfo.position;
+ tp_osReport("%d", gSaveManager.mPracticeSaveInfo.angle);
+ tp_osReport("0x%08X", &gSaveManager.mPracticeSaveInfo.angle);
}
void set_angle_position() {
- tp_zelAudio.link_debug_ptr->facing = angle;
- tp_zelAudio.link_debug_ptr->position = position;
-}
-
-void default_load() {
- practice_file.inject_options_during_load = SaveInjector::inject_default_during;
- practice_file.inject_options_after_load = SaveInjector::inject_default_after;
- inject_save_flag = true;
- fifo_visible = true;
- MenuRendering::set_menu(MN_NONE_INDEX);
-}
-
-void load_save(uint32_t id, char* category, special i_specials[], int size) {
- SaveInjector::inject_default_before();
- // Load the corresponding file path and properties
- PracticeSaveInfo saveinfo __attribute__((aligned(32)));
- char buf[80];
- tp_sprintf(buf, "tpgz/save_files/%s.bin", category);
- loadFile(buf, &saveinfo, sizeof(saveinfo), id * sizeof(saveinfo));
- tp_sprintf(buf, "tpgz/save_files/%s/%s.bin", category, saveinfo.filename);
-
- // Load the file into memory
- Utilities::load_save_file(buf);
-
- if (g_area_reload_behavior == LOAD_AREA || size != 0xFF) {
- default_load();
- }
-
- if (saveinfo.requirements & REQ_CAM) {
- camera.target = saveinfo.cam_target;
- camera.pos = saveinfo.cam_pos;
- }
-
- if (saveinfo.requirements & REQ_POS) {
- angle = saveinfo.angle;
- position = saveinfo.position;
- }
-
- if (saveinfo.requirements != 0) {
- practice_file.inject_options_after_load = saveinfo.requirements & REQ_CAM ?
- Utilities::set_camera_angle_position :
- Utilities::set_angle_position;
- }
-
- practice_file.inject_options_after_counter = saveinfo.counter;
-
- tp_bossFlags = 0;
-
- for (int i = 0; i < size; ++i) {
- if (id == i_specials[i].idx) {
- if (i_specials[i].CallbackDuring) {
- practice_file.inject_options_during_load = i_specials[i].CallbackDuring;
- }
- if (i_specials[i].CallbackAfter) {
- practice_file.inject_options_after_load = i_specials[i].CallbackAfter;
- }
- }
- }
-
- // store last save file index and category in case file reload is used
- last_save_index = id;
- tp_strcpy(last_category, category);
+ tp_zelAudio.link_debug_ptr->facing = gSaveManager.mPracticeSaveInfo.angle;
+ tp_zelAudio.link_debug_ptr->position = gSaveManager.mPracticeSaveInfo.position;
}
-void load_save_file(const char* fileName) {
- loadFile(fileName, (void*)sTmpBuf, 2400, 0);
- SaveInjector::inject_save((void*)sTmpBuf);
-}
-
-void trigger_load() {
- if (!tp_fopScnRq.isLoading && !loading_initiated) {
- if (practice_file.inject_options_before_load) {
- practice_file.inject_options_before_load();
- }
- tp_gameInfo.warp.enabled = true;
- }
-
- if (tp_fopScnRq.isLoading && tp_gameInfo.warp.enabled) {
- if (practice_file.inject_options_during_load) {
- practice_file.inject_options_during_load();
- }
- loading_initiated = true;
- tp_gameInfo.warp.enabled = false;
- }
-
- if (loading_initiated) {
- if (!tp_fopScnRq.isLoading) {
- if (practice_file.inject_options_after_load) {
- practice_file.inject_options_after_load();
- }
- if (practice_file.inject_options_after_counter == apply_after_counter) {
- apply_after_counter = 0;
- practice_file.inject_options_after_counter = 0;
- loading_initiated = false;
- inject_save_flag = false;
- } else {
- apply_after_counter++;
- }
- }
- }
-}
} // namespace Utilities \ No newline at end of file