This commit is contained in:
Wiseguy 2025-04-06 16:54:18 -07:00 committed by GitHub
commit 727d07cf38
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 70 additions and 5 deletions

View file

@ -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 {
@ -24,6 +25,7 @@ namespace recomp {
std::u8string game_id; std::u8string game_id;
std::string mod_game_id; std::string mod_game_id;
SaveType save_type = SaveType::None; SaveType save_type = SaveType::None;
uint32_t custom_save_size = 0;
bool is_enabled; bool is_enabled;
// Only needed for mod function hooking support, not needed if `has_compressed_code` is false. // Only needed for mod function hooking support, not needed if `has_compressed_code` is false.
std::vector<uint8_t> (*decompression_routine)(std::span<const uint8_t> compressed_rom) = nullptr; std::vector<uint8_t> (*decompression_routine)(std::span<const uint8_t> compressed_rom) = nullptr;
@ -106,6 +108,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();

View file

@ -190,9 +190,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:
@ -207,13 +210,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);
@ -365,3 +393,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);
}

View file

@ -624,7 +624,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);
@ -665,6 +665,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,

View file

@ -32,7 +32,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();