mirror of
https://github.com/Zelda64Recomp/Zelda64Recomp
synced 2026-08-26 16:36:33 -04:00
Prototype quicksave functionality, disabled for now
This commit is contained in:
@@ -210,6 +210,24 @@ void recomp::poll_inputs() {
|
||||
InputState.cur_controllers.push_back(controller);
|
||||
}
|
||||
}
|
||||
|
||||
// Quicksaving is disabled for now and will likely have more limited functionality
|
||||
// when restored, rather than allowing saving and loading at any point in time.
|
||||
#if 0
|
||||
if (InputState.keys) {
|
||||
static bool save_was_held = false;
|
||||
static bool load_was_held = false;
|
||||
bool save_is_held = InputState.keys[SDL_SCANCODE_F5] != 0;
|
||||
bool load_is_held = InputState.keys[SDL_SCANCODE_F7] != 0;
|
||||
if (save_is_held && !save_was_held) {
|
||||
recomp::quicksave_save();
|
||||
}
|
||||
else if (load_is_held && !load_was_held) {
|
||||
recomp::quicksave_load();
|
||||
}
|
||||
save_was_held = save_is_held;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool controller_button_state(int32_t input_id) {
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
// Quicksaving is disabled for now
|
||||
|
||||
#if 0
|
||||
|
||||
#include "recomp_helpers.h"
|
||||
#include "recomp_input.h"
|
||||
#include "../ultramodern/ultramodern.hpp"
|
||||
|
||||
enum class QuicksaveAction {
|
||||
None,
|
||||
Save,
|
||||
Load
|
||||
};
|
||||
|
||||
std::atomic<QuicksaveAction> cur_quicksave_action = QuicksaveAction::None;
|
||||
|
||||
void recomp::quicksave_save() {
|
||||
cur_quicksave_action.store(QuicksaveAction::Save);
|
||||
}
|
||||
|
||||
void recomp::quicksave_load() {
|
||||
cur_quicksave_action.store(QuicksaveAction::Load);
|
||||
}
|
||||
|
||||
uint8_t saved_rdram[ultramodern::rdram_size];
|
||||
|
||||
thread_local recomp_context saved_context;
|
||||
|
||||
void save_context(recomp_context* ctx) {
|
||||
saved_context = *ctx;
|
||||
}
|
||||
|
||||
void load_context(recomp_context* ctx) {
|
||||
*ctx = saved_context;
|
||||
|
||||
// Restore the pointer to the odd floats for correctly handling mips3 float mode.
|
||||
if (ctx->mips3_float_mode) {
|
||||
// FR = 1, odd single floats point to their own registers
|
||||
ctx->f_odd = &ctx->f1.u32l;
|
||||
}
|
||||
else {
|
||||
// FR = 0, odd single floats point to the upper half of the previous register
|
||||
ctx->f_odd = &ctx->f0.u32h;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void recomp_handle_quicksave_actions(uint8_t* rdram, recomp_context* ctx) {
|
||||
QuicksaveAction action = cur_quicksave_action.load();
|
||||
|
||||
if (action != QuicksaveAction::None) {
|
||||
PTR(OSMesgQueue) quicksave_enter_mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
PTR(OSMesgQueue) quicksave_exit_mq = _arg<1, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
|
||||
printf("saving context for thread %d\n", TO_PTR(OSThread, ultramodern::this_thread())->id);
|
||||
|
||||
// Save or load the thread's context as needed based on the action.
|
||||
if (action == QuicksaveAction::Save) {
|
||||
save_context(ctx);
|
||||
}
|
||||
else if (action == QuicksaveAction::Load) {
|
||||
load_context(ctx);
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// Tell the main thread that one of the other permanent threads is ready for performing a quicksave action.
|
||||
osSendMesg(rdram, quicksave_enter_mq, NULLPTR, OS_MESG_NOBLOCK);
|
||||
// Wait for the main thread to signal that other permanent threads are safe to continue.
|
||||
osRecvMesg(rdram, quicksave_exit_mq, NULLPTR, OS_MESG_BLOCK);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void wake_threads_for_quicksave_action(uint8_t* rdram, recomp_context* ctx);
|
||||
|
||||
extern "C" void recomp_handle_quicksave_actions_main(uint8_t* rdram, recomp_context* ctx) {
|
||||
QuicksaveAction action = cur_quicksave_action.load();
|
||||
|
||||
if (action != QuicksaveAction::None) {
|
||||
PTR(OSMesgQueue) quicksave_enter_mq = _arg<0, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
PTR(OSMesgQueue) quicksave_exit_mq = _arg<1, PTR(OSMesgQueue)>(rdram, ctx);
|
||||
|
||||
wake_threads_for_quicksave_action(rdram, ctx);
|
||||
|
||||
// Wait for all other permanent threads (hence the minus 1) to signal that they're ready for a quicksave action.
|
||||
for (uint32_t i = 0; i < ultramodern::permanent_thread_count() - 1; i++) {
|
||||
osRecvMesg(rdram, quicksave_enter_mq, NULLPTR, OS_MESG_BLOCK);
|
||||
}
|
||||
|
||||
// Allow any temporary threads to complete by lowering this thread's priority to 0.
|
||||
// TODO this won't cause all temporary threads to complete if any are blocked by permanent threads
|
||||
// or events like timers. Situations like that will need to be handed on a case-by-case basis for a given game.
|
||||
if (ultramodern::temporary_thread_count() != 0) {
|
||||
OSPri old_pri = osGetThreadPri(rdram, NULLPTR);
|
||||
osSetThreadPri(rdram, NULLPTR, 0);
|
||||
|
||||
osSetThreadPri(rdram, NULLPTR, old_pri);
|
||||
}
|
||||
|
||||
if (action == QuicksaveAction::Save) {
|
||||
std::copy(rdram, rdram + ultramodern::rdram_size, saved_rdram);
|
||||
}
|
||||
else if (action == QuicksaveAction::Load) {
|
||||
std::copy(saved_rdram, saved_rdram + ultramodern::rdram_size, rdram);
|
||||
}
|
||||
else {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
printf("Quicksave action complete\n");
|
||||
|
||||
cur_quicksave_action.store(QuicksaveAction::None);
|
||||
|
||||
// Tell all other permanent threads that they're good to continue.
|
||||
for (uint32_t i = 0; i < ultramodern::permanent_thread_count() - 1; i++) {
|
||||
osSendMesg(rdram, quicksave_exit_mq, NULLPTR, OS_MESG_BLOCK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -175,9 +175,9 @@ EXPORT extern "C" void init() {
|
||||
// Load overlays in the first 1MB
|
||||
load_overlays(0x1000, (int32_t)entrypoint, 1024 * 1024);
|
||||
|
||||
// Allocate rdram_buffer (16MB to give room for any extra addressable data used by recomp)
|
||||
rdram_buffer = std::make_unique<uint8_t[]>(16 * 1024 * 1024);
|
||||
std::memset(rdram_buffer.get(), 0, 8 * 1024 * 1024);
|
||||
// Allocate rdram_buffer
|
||||
rdram_buffer = std::make_unique<uint8_t[]>(ultramodern::rdram_size);
|
||||
std::memset(rdram_buffer.get(), 0, ultramodern::rdram_size);
|
||||
|
||||
// Initial 1MB DMA (rom address 0x1000 = physical address 0x10001000)
|
||||
do_rom_read(rdram_buffer.get(), entrypoint, 0x10001000, 0x100000);
|
||||
|
||||
Reference in New Issue
Block a user