Skip to content

Commit

Permalink
Fix #45
Browse files Browse the repository at this point in the history
  • Loading branch information
JesseTG committed Aug 17, 2023
1 parent eaf2210 commit a3893da
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 61 deletions.
2 changes: 1 addition & 1 deletion melondsds_libretro.info
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ corename = "melonDS DS"
categories = "Emulator"
license = "GPLv3"
permissions = ""
display_version = "0.3.2"
display_version = "0.3.3"

# Hardware Information
manufacturer = "Nintendo"
Expand Down
55 changes: 20 additions & 35 deletions src/libretro/libretro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,6 @@ namespace melonds {
const optional<retro_game_info>& gba_info
);
static void set_up_direct_boot(const retro_game_info &nds_info);
static void install_sram(
const optional<retro_game_info>& nds_info,
const optional<retro_game_info>& gba_info
);
static void ValidateFirmware();

// functions for running games
Expand Down Expand Up @@ -223,33 +219,6 @@ PUBLIC_SYMBOL bool retro_load_game(const struct retro_game_info *info) {
return melonds::handle_load_game(melonds::MELONDSDS_GAME_TYPE_NDS, info, 1);
}

static void melonds::install_sram(
const optional<retro_game_info>& nds_info,
const optional<retro_game_info>& gba_info
) {
ZoneScopedN("melonds::install_sram");
// Nintendo DS SRAM is loaded by the frontend
// and copied into NdsSaveManager via the pointer returned by retro_get_memory.
// This is where we install the SRAM data into the emulated DS.
if (nds_info && sram::NdsSaveManager->SramLength() > 0) {
// If we're loading a NDS game that has SRAM...
NDS::LoadSave(sram::NdsSaveManager->Sram(), sram::NdsSaveManager->SramLength());
}

// GBA SRAM is selected by the user explicitly (due to libretro limits) and loaded by the frontend,
// but is not processed by retro_get_memory (again due to libretro limits).
if (gba_info && sram::GbaSaveManager->SramLength() > 0) {
// If we're loading a GBA game that has existing SRAM...
// TODO: Decide what to do about SRAM files that append extra metadata like the RTC
GBACart::LoadSave(sram::GbaSaveManager->Sram(), sram::GbaSaveManager->SramLength());
}

// We could've installed the GBA's SRAM in retro_load_game (since it's not processed by retro_get_memory),
// but doing so here helps keep things tidier since the NDS SRAM is installed here too.
}



PUBLIC_SYMBOL void retro_get_system_av_info(struct retro_system_av_info *info) {
ZoneScopedN("retro_get_system_av_info");
using melonds::screenLayout;
Expand Down Expand Up @@ -300,14 +269,30 @@ PUBLIC_SYMBOL void retro_run(void) {
}

if (!first_frame_run) {
using namespace sram;
// Apply the save data from the core's SRAM buffer to the cart's SRAM;
// we need to do this in the first frame of retro_run because
// retro_get_memory_data is used to copy the loaded SRAM
// in between retro_load and the first retro_run call.
install_sram(
retro::content::get_loaded_nds_info(),
retro::content::get_loaded_gba_info()
);

// Nintendo DS SRAM is loaded by the frontend
// and copied into NdsSaveManager via the pointer returned by retro_get_memory.
// This is where we install the SRAM data into the emulated DS.
if (retro::content::get_loaded_nds_info() && NdsSaveManager && NdsSaveManager->SramLength() > 0) {
// If we're loading a NDS game that has SRAM...
NDS::LoadSave(NdsSaveManager->Sram(), NdsSaveManager->SramLength());
}

// GBA SRAM is selected by the user explicitly (due to libretro limits) and loaded by the frontend,
// but is not processed by retro_get_memory (again due to libretro limits).
if (retro::content::get_loaded_nds_info() && GbaSaveManager && GbaSaveManager->SramLength() > 0) {
// If we're loading a GBA game that has existing SRAM...
// TODO: Decide what to do about SRAM files that append extra metadata like the RTC
GBACart::LoadSave(GbaSaveManager->Sram(), GbaSaveManager->SramLength());
}

// We could've installed the GBA's SRAM in retro_load_game (since it's not processed by retro_get_memory),
// but doing so here helps keep things tidier since the NDS SRAM is installed here too.

// This has to be deferred even if we're not using OpenGL,
// because libretro doesn't set the SRAM until after retro_load_game
Expand Down
25 changes: 7 additions & 18 deletions src/libretro/sram.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,6 @@ void melonds::sram::init() {
ZoneScopedN("melonds::sram::init");
retro_assert(NdsSaveManager == nullptr);
retro_assert(GbaSaveManager == nullptr);
NdsSaveManager = make_unique<SaveManager>();
GbaSaveManager = make_unique<SaveManager>();
}

void melonds::sram::deinit() noexcept {
Expand All @@ -58,10 +56,9 @@ void melonds::sram::deinit() noexcept {
GbaSaveManager = nullptr;
}

melonds::sram::SaveManager::SaveManager() :
_sram(nullptr),
_sram_length(0),
_buffer_length(0) {
melonds::sram::SaveManager::SaveManager(u32 initialLength) :
_sram(new u8[initialLength]),
_sram_length(initialLength) {
}

melonds::sram::SaveManager::~SaveManager() {
Expand Down Expand Up @@ -93,16 +90,6 @@ void melonds::sram::SaveManager::Flush(const u8 *savedata, u32 savelen, u32 writ
}
}

void melonds::sram::SaveManager::SetSaveSize(u32 savelen) {
ZoneScopedN("melonds::sram::SaveManager::SetSaveSize");
if (_sram_length != savelen) {
delete[] _sram;

_sram_length = savelen;
_sram = new u8[_sram_length];
}
}

void melonds::sram::FlushGbaSram(const retro_game_info& gba_save_info) noexcept {
ZoneScopedN("melonds::sram::FlushSram");
const char* save_data_path = gba_save_info.path;
Expand Down Expand Up @@ -178,9 +165,9 @@ void melonds::sram::InitNdsSave(const NdsCart &nds_cart) {
else {
// Get the length of the ROM's SRAM, if any
u32 sram_length = nds_cart.GetSaveMemoryLength();
sram::NdsSaveManager->SetSaveSize(sram_length);

if (sram_length > 0) {
sram::NdsSaveManager = make_unique<SaveManager>(sram_length);
retro::log(RETRO_LOG_DEBUG, "Allocated %u-byte SRAM buffer for loaded NDS ROM.", sram_length);
} else {
retro::log(RETRO_LOG_DEBUG, "Loaded NDS ROM does not use SRAM.");
Expand Down Expand Up @@ -253,8 +240,10 @@ void melonds::sram::InitGbaSram(GbaCart& gba_cart, const struct retro_game_info&
throw std::runtime_error("Failed to read GBA save file");
}

sram::GbaSaveManager->SetSaveSize(gba_save_file_size);
sram::GbaSaveManager = make_unique<SaveManager>(gba_save_file_size);
gba_cart.SetupSave(gba_save_file_size);
// LoadSave's subclasses will call Platform::WriteGBASave.
// The data will be in the buffer soon enough.
gba_cart.LoadSave(static_cast<const u8*>(gba_save_data), gba_save_file_size);
retro::debug("Allocated %u-byte GBA SRAM", gba_cart.GetSaveMemoryLength());
// Actually installing the SRAM will be done later, after NDS::Reset is called
Expand Down
8 changes: 1 addition & 7 deletions src/libretro/sram.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace melonds::sram {
/// An intermediate save buffer used as a staging ground between retro_get_memory and NDSCart::LoadSave.
class SaveManager {
public:
SaveManager();
SaveManager(u32 initialLength);

~SaveManager();

Expand All @@ -63,11 +63,6 @@ namespace melonds::sram {
/// \param writelen Length of the updated data.
void Flush(const u8 *savedata, u32 savelen, u32 writeoffset, u32 writelen);

/// Allocates a buffer for SRAM of the given length.
/// Does nothing if the SRAM buffer is already of the given length.
/// Will clear whatever data is in the buffer.
void SetSaveSize(u32 savelen);

[[nodiscard]] const u8 *Sram() const {
return _sram;
}
Expand All @@ -83,7 +78,6 @@ namespace melonds::sram {
private:
u8 *_sram;
u32 _sram_length;
u32 _buffer_length;
};

extern std::unique_ptr<SaveManager> NdsSaveManager;
Expand Down

0 comments on commit a3893da

Please sign in to comment.