mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2025-10-30 08:02:29 +00:00
Add custom save type
This commit is contained in:
parent
1361c48f59
commit
a22e2afe88
4 changed files with 70 additions and 5 deletions
|
|
@ -16,6 +16,7 @@ namespace recomp {
|
||||||
Sram,
|
Sram,
|
||||||
Flashram,
|
Flashram,
|
||||||
AllowAll, // Allows all save types to work and reports eeprom size as 16kbit.
|
AllowAll, // Allows all save types to work and reports eeprom size as 16kbit.
|
||||||
|
Custom, // Custom save type for recomp with a configurable size.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct GameEntry {
|
struct GameEntry {
|
||||||
|
|
@ -25,6 +26,7 @@ namespace recomp {
|
||||||
std::string mod_game_id;
|
std::string mod_game_id;
|
||||||
std::span<const char> cache_data;
|
std::span<const char> cache_data;
|
||||||
SaveType save_type = SaveType::None;
|
SaveType save_type = SaveType::None;
|
||||||
|
uint32_t custom_save_size = 0;
|
||||||
bool is_enabled;
|
bool is_enabled;
|
||||||
|
|
||||||
gpr entrypoint_address;
|
gpr entrypoint_address;
|
||||||
|
|
@ -99,6 +101,7 @@ namespace recomp {
|
||||||
bool eeprom_allowed();
|
bool eeprom_allowed();
|
||||||
bool sram_allowed();
|
bool sram_allowed();
|
||||||
bool flashram_allowed();
|
bool flashram_allowed();
|
||||||
|
bool custom_saving_allowed();
|
||||||
|
|
||||||
void start_game(const std::u8string& game_id);
|
void start_game(const std::u8string& game_id);
|
||||||
std::u8string current_game_id();
|
std::u8string current_game_id();
|
||||||
|
|
|
||||||
|
|
@ -186,9 +186,12 @@ void save_clear(uint32_t start, uint32_t size, char value) {
|
||||||
save_context.write_sempahore.signal();
|
save_context.write_sempahore.signal();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t get_save_size(recomp::SaveType save_type) {
|
size_t get_save_size(recomp::SaveType save_type, uint32_t custom_save_size) {
|
||||||
switch (save_type) {
|
switch (save_type) {
|
||||||
case recomp::SaveType::AllowAll:
|
case recomp::SaveType::AllowAll:
|
||||||
|
return std::max(custom_save_size, 0x20000U);
|
||||||
|
case recomp::SaveType::Custom:
|
||||||
|
return custom_save_size;
|
||||||
case recomp::SaveType::Flashram:
|
case recomp::SaveType::Flashram:
|
||||||
return 0x20000;
|
return 0x20000;
|
||||||
case recomp::SaveType::Sram:
|
case recomp::SaveType::Sram:
|
||||||
|
|
@ -203,13 +206,38 @@ size_t get_save_size(recomp::SaveType save_type) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ultramodern::init_saving(RDRAM_ARG1) {
|
void ultramodern::init_saving(RDRAM_ARG uint32_t custom_save_size) {
|
||||||
std::filesystem::path save_file_path = get_save_file_path();
|
std::filesystem::path save_file_path = get_save_file_path();
|
||||||
|
|
||||||
// Ensure the save file directory exists.
|
// Ensure the save file directory exists.
|
||||||
std::filesystem::create_directories(save_file_path.parent_path());
|
std::filesystem::create_directories(save_file_path.parent_path());
|
||||||
|
|
||||||
save_context.save_buffer.resize(get_save_size(recomp::get_save_type()));
|
recomp::SaveType save_type = recomp::get_save_type();
|
||||||
|
if (save_type == recomp::SaveType::Custom) {
|
||||||
|
if (custom_save_size == 0) {
|
||||||
|
ultramodern::error_handling::message_box(
|
||||||
|
"The current game's GameEntry uses the \"Custom\" save type, but\n"
|
||||||
|
"the custom save size has not been specified.\n"
|
||||||
|
"\n"
|
||||||
|
"This can be done by setting \"custom_save_size\" in the\n"
|
||||||
|
"GameEntry passed to \"recomp::register_game\"."
|
||||||
|
);
|
||||||
|
ULTRAMODERN_QUICK_EXIT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (save_type != recomp::SaveType::AllowAll) {
|
||||||
|
if (custom_save_size != 0) {
|
||||||
|
ultramodern::error_handling::message_box(
|
||||||
|
"The current game's GameEntry \"custom_save_size\" has been set, but\n"
|
||||||
|
"the current game does not use the \"Custom\" save type.\n"
|
||||||
|
"\n"
|
||||||
|
"Only the \"Custom\" save type has a configurable saving size.\n"
|
||||||
|
);
|
||||||
|
ULTRAMODERN_QUICK_EXIT();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
save_context.save_buffer.resize(get_save_size(save_type, custom_save_size));
|
||||||
|
|
||||||
// Read the save file if it exists.
|
// Read the save file if it exists.
|
||||||
std::ifstream save_file = recomp::open_input_file_with_backup(save_file_path, std::ios_base::binary);
|
std::ifstream save_file = recomp::open_input_file_with_backup(save_file_path, std::ios_base::binary);
|
||||||
|
|
@ -361,3 +389,31 @@ extern "C" void osEPiRawStartDma_recomp(RDRAM_ARG recomp_context * ctx) {
|
||||||
);
|
);
|
||||||
ULTRAMODERN_QUICK_EXIT();
|
ULTRAMODERN_QUICK_EXIT();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom recomp saving mechanism.
|
||||||
|
|
||||||
|
// Called from the recompiled code as `void recomp_save_write(void* rdram_address, u32 offset, u32 count);`
|
||||||
|
extern "C" void recomp_save_write(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
if (!recomp::custom_saving_allowed()) {
|
||||||
|
ultramodern::error_handling::message_box("Attempted to use custom saving with other save type");
|
||||||
|
ULTRAMODERN_QUICK_EXIT();
|
||||||
|
}
|
||||||
|
int32_t rdram_address = ctx->r4;
|
||||||
|
uint32_t offset = ctx->r5;
|
||||||
|
uint32_t count = ctx->r6;
|
||||||
|
|
||||||
|
save_write(rdram, rdram_address, offset, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from the recompiled code as `void recomp_save_read(void* rdram_address, u32 offset, u32 count);`
|
||||||
|
extern "C" void recomp_save_read(uint8_t* rdram, recomp_context* ctx) {
|
||||||
|
if (!recomp::custom_saving_allowed()) {
|
||||||
|
ultramodern::error_handling::message_box("Attempted to use custom saving with other save type");
|
||||||
|
ULTRAMODERN_QUICK_EXIT();
|
||||||
|
}
|
||||||
|
int32_t rdram_address = ctx->r4;
|
||||||
|
uint32_t offset = ctx->r5;
|
||||||
|
uint32_t count = ctx->r6;
|
||||||
|
|
||||||
|
save_read(rdram, rdram_address, offset, count);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -550,7 +550,7 @@ bool wait_for_game_started(uint8_t* rdram, recomp_context* context) {
|
||||||
recomp::init_heap(rdram, recomp::mod_rdram_start + mod_ram_used);
|
recomp::init_heap(rdram, recomp::mod_rdram_start + mod_ram_used);
|
||||||
|
|
||||||
save_type = game_entry.save_type;
|
save_type = game_entry.save_type;
|
||||||
ultramodern::init_saving(rdram);
|
ultramodern::init_saving(rdram, game_entry.custom_save_size);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
game_entry.entrypoint(rdram, context);
|
game_entry.entrypoint(rdram, context);
|
||||||
|
|
@ -591,6 +591,12 @@ bool recomp::flashram_allowed() {
|
||||||
save_type == SaveType::AllowAll;
|
save_type == SaveType::AllowAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool recomp::custom_saving_allowed() {
|
||||||
|
return
|
||||||
|
save_type == SaveType::Custom ||
|
||||||
|
save_type == SaveType::AllowAll;
|
||||||
|
}
|
||||||
|
|
||||||
void recomp::start(
|
void recomp::start(
|
||||||
const recomp::Version& version,
|
const recomp::Version& version,
|
||||||
ultramodern::renderer::WindowHandle window_handle,
|
ultramodern::renderer::WindowHandle window_handle,
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ constexpr uint32_t save_size = 1024 * 1024 / 8; // Maximum save size, 1Mbit for
|
||||||
|
|
||||||
// Initialization.
|
// Initialization.
|
||||||
void preinit(RDRAM_ARG renderer::WindowHandle window_handle);
|
void preinit(RDRAM_ARG renderer::WindowHandle window_handle);
|
||||||
void init_saving(RDRAM_ARG1);
|
void init_saving(RDRAM_ARG uint32_t custom_save_size);
|
||||||
void init_events(RDRAM_ARG renderer::WindowHandle window_handle);
|
void init_events(RDRAM_ARG renderer::WindowHandle window_handle);
|
||||||
void init_timers(RDRAM_ARG1);
|
void init_timers(RDRAM_ARG1);
|
||||||
void init_thread_cleanup();
|
void init_thread_cleanup();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue