fix crashes when inserting/ejecting GBA carts/addons with nothing loaded

This commit is contained in:
Arisotura 2024-11-17 15:23:25 +01:00
parent 5e8beb3ab7
commit 0a4287c6ad
7 changed files with 77 additions and 42 deletions

View File

@ -832,6 +832,27 @@ std::unique_ptr<CartCommon> ParseROM(std::unique_ptr<u8[]>&& romdata, u32 romlen
return cart; return cart;
} }
std::unique_ptr<CartCommon> LoadAddon(int type, void* userdata)
{
std::unique_ptr<CartCommon> cart;
switch (type)
{
case GBAAddon_RAMExpansion:
cart = std::make_unique<CartRAMExpansion>();
break;
case GBAAddon_RumblePak:
cart = std::make_unique<CartRumblePak>(userdata);
break;
default:
Log(LogLevel::Warn, "GBACart: !! invalid addon type %d\n", type);
return nullptr;
}
cart->Reset();
return cart;
}
void GBACartSlot::SetCart(std::unique_ptr<CartCommon>&& cart) noexcept void GBACartSlot::SetCart(std::unique_ptr<CartCommon>&& cart) noexcept
{ {
Cart = std::move(cart); Cart = std::move(cart);
@ -864,23 +885,6 @@ void GBACartSlot::SetSaveMemory(const u8* savedata, u32 savelen) noexcept
} }
} }
void GBACartSlot::LoadAddon(void* userdata, int type) noexcept
{
switch (type)
{
case GBAAddon_RAMExpansion:
Cart = std::make_unique<CartRAMExpansion>();
break;
case GBAAddon_RumblePak:
Cart = std::make_unique<CartRumblePak>(userdata);
break;
default:
Log(LogLevel::Warn, "GBACart: !! invalid addon type %d\n", type);
return;
}
}
std::unique_ptr<CartCommon> GBACartSlot::EjectCart() noexcept std::unique_ptr<CartCommon> GBACartSlot::EjectCart() noexcept
{ {
return std::move(Cart); return std::move(Cart);

View File

@ -241,8 +241,6 @@ public:
[[nodiscard]] CartCommon* GetCart() noexcept { return Cart.get(); } [[nodiscard]] CartCommon* GetCart() noexcept { return Cart.get(); }
[[nodiscard]] const CartCommon* GetCart() const noexcept { return Cart.get(); } [[nodiscard]] const CartCommon* GetCart() const noexcept { return Cart.get(); }
void LoadAddon(void* userdata, int type) noexcept;
/// @return The cart that was in the cart slot if any, /// @return The cart that was in the cart slot if any,
/// or \c nullptr if the cart slot was empty. /// or \c nullptr if the cart slot was empty.
std::unique_ptr<CartCommon> EjectCart() noexcept; std::unique_ptr<CartCommon> EjectCart() noexcept;
@ -309,6 +307,8 @@ std::unique_ptr<CartCommon> ParseROM(const u8* romdata, u32 romlen, const u8* sr
/// or \c nullptr if there was an error. /// or \c nullptr if there was an error.
std::unique_ptr<CartCommon> ParseROM(std::unique_ptr<u8[]>&& romdata, u32 romlen, std::unique_ptr<u8[]>&& sramdata, u32 sramlen, void* userdata = nullptr); std::unique_ptr<CartCommon> ParseROM(std::unique_ptr<u8[]>&& romdata, u32 romlen, std::unique_ptr<u8[]>&& sramdata, u32 sramlen, void* userdata = nullptr);
std::unique_ptr<CartCommon> LoadAddon(int type, void* userdata);
} }
#endif // GBACART_H #endif // GBACART_H

View File

@ -752,11 +752,6 @@ void NDS::SetGBASave(const u8* savedata, u32 savelen)
} }
void NDS::LoadGBAAddon(int type)
{
GBACartSlot.LoadAddon(UserData, type);
}
void NDS::LoadBIOS() void NDS::LoadBIOS()
{ {
Reset(); Reset();

View File

@ -384,7 +384,6 @@ public: // TODO: Encapsulate the rest of these members
u32 GetGBASaveLength() const { return GBACartSlot.GetSaveMemoryLength(); } u32 GetGBASaveLength() const { return GBACartSlot.GetSaveMemoryLength(); }
void SetGBASave(const u8* savedata, u32 savelen); void SetGBASave(const u8* savedata, u32 savelen);
void LoadGBAAddon(int type);
std::unique_ptr<GBACart::CartCommon> EjectGBACart() { return GBACartSlot.EjectCart(); } std::unique_ptr<GBACart::CartCommon> EjectGBACart() { return GBACartSlot.EjectCart(); }
u32 RunFrame(); u32 RunFrame();

View File

@ -83,6 +83,8 @@ EmuInstance::EmuInstance(int inst) : deleting(false),
baseGBAROMDir = ""; baseGBAROMDir = "";
baseGBAROMName = ""; baseGBAROMName = "";
baseGBAAssetName = ""; baseGBAAssetName = "";
nextGBACart = nullptr;
changeGBACart = false;
cheatFile = nullptr; cheatFile = nullptr;
cheatsOn = localCfg.GetBool("EnableCheats"); cheatsOn = localCfg.GetBool("EnableCheats");
@ -118,7 +120,7 @@ EmuInstance::EmuInstance(int inst) : deleting(false),
mpAudioMode = globalCfg.GetInt("MP.AudioMode"); mpAudioMode = globalCfg.GetInt("MP.AudioMode");
nds = nullptr; nds = nullptr;
//updateConsole(nullptr, nullptr); //updateConsole(nullptr);
audioInit(); audioInit();
inputInit(); inputInit();
@ -1215,7 +1217,7 @@ void EmuInstance::setDateTime()
time.time().hour(), time.time().minute(), time.time().second()); time.time().hour(), time.time().minute(), time.time().second());
} }
bool EmuInstance::updateConsole(UpdateConsoleNDSArgs&& _ndsargs, UpdateConsoleGBAArgs&& _gbaargs) noexcept bool EmuInstance::updateConsole(UpdateConsoleNDSArgs&& _ndsargs) noexcept
{ {
// update the console type // update the console type
consoleType = globalCfg.GetInt("Emu.ConsoleType"); consoleType = globalCfg.GetInt("Emu.ConsoleType");
@ -1242,14 +1244,14 @@ bool EmuInstance::updateConsole(UpdateConsoleNDSArgs&& _ndsargs, UpdateConsoleGB
} }
std::unique_ptr<GBACart::CartCommon> nextgbacart; std::unique_ptr<GBACart::CartCommon> nextgbacart;
if (std::holds_alternative<Keep>(_gbaargs)) if (!changeGBACart)
{ {
nextgbacart = nds ? nds->EjectGBACart() : nullptr; nextgbacart = nds ? nds->EjectGBACart() : nullptr;
} }
else if (const auto ptr = std::get_if<std::unique_ptr<GBACart::CartCommon>>(&_gbaargs)) else
{ {
nextgbacart = std::move(*ptr); nextgbacart = std::move(nextGBACart);
_gbaargs = {}; changeGBACart = false;
} }
@ -1391,7 +1393,7 @@ bool EmuInstance::updateConsole(UpdateConsoleNDSArgs&& _ndsargs, UpdateConsoleGB
void EmuInstance::reset() void EmuInstance::reset()
{ {
updateConsole(Keep {}, Keep {}); updateConsole(Keep {});
if (consoleType == 1) ejectGBACart(); if (consoleType == 1) ejectGBACart();
@ -1455,7 +1457,7 @@ void EmuInstance::reset()
bool EmuInstance::bootToMenu() bool EmuInstance::bootToMenu()
{ {
// Keep whatever cart is in the console, if any. // Keep whatever cart is in the console, if any.
if (!updateConsole(Keep {}, Keep {})) if (!updateConsole(Keep {}))
// Try to update the console, but keep the existing cart. If that fails... // Try to update the console, but keep the existing cart. If that fails...
return false; return false;
@ -1910,7 +1912,7 @@ bool EmuInstance::loadROM(QStringList filepath, bool reset)
if (reset) if (reset)
{ {
if (!updateConsole(std::move(cart), Keep {})) if (!updateConsole(std::move(cart)))
{ {
QMessageBox::critical(mainWindow, "melonDS", "Failed to load the DS ROM."); QMessageBox::critical(mainWindow, "melonDS", "Failed to load the DS ROM.");
return false; return false;
@ -2043,9 +2045,18 @@ bool EmuInstance::loadGBAROM(QStringList filepath)
return false; return false;
} }
nds->SetGBACart(std::move(cart));
gbaCartType = 0; gbaCartType = 0;
gbaSave = std::make_unique<SaveManager>(savname); if (emuIsActive())
{
nds->SetGBACart(std::move(cart));
gbaSave = std::make_unique<SaveManager>(savname);
}
else
{
nextGBACart = std::move(cart);
changeGBACart = true;
}
return true; return true;
} }
@ -2053,10 +2064,24 @@ void EmuInstance::loadGBAAddon(int type)
{ {
if (consoleType == 1) return; if (consoleType == 1) return;
auto cart = GBACart::LoadAddon(type, this);
if (!cart)
{
QMessageBox::critical(mainWindow, "melonDS", "Failed to load the GBA addon.");
return;
}
if (emuIsActive())
{
nds->SetGBACart(std::move(cart));
}
else
{
nextGBACart = std::move(cart);
changeGBACart = true;
}
gbaSave = nullptr; gbaSave = nullptr;
nds->LoadGBAAddon(type);
gbaCartType = type; gbaCartType = type;
baseGBAROMDir = ""; baseGBAROMDir = "";
baseGBAROMName = ""; baseGBAROMName = "";
@ -2067,7 +2092,15 @@ void EmuInstance::ejectGBACart()
{ {
gbaSave = nullptr; gbaSave = nullptr;
nds->EjectGBACart(); if (emuIsActive())
{
nds->EjectGBACart();
}
else
{
nextGBACart = nullptr;
changeGBACart = true;
}
gbaCartType = -1; gbaCartType = -1;
baseGBAROMDir = ""; baseGBAROMDir = "";

View File

@ -120,7 +120,7 @@ public:
// return: empty string = setup OK, non-empty = error message // return: empty string = setup OK, non-empty = error message
QString verifySetup(); QString verifySetup();
bool updateConsole(UpdateConsoleNDSArgs&& ndsargs, UpdateConsoleGBAArgs&& gbaargs) noexcept; bool updateConsole(UpdateConsoleNDSArgs&& ndsargs) noexcept;
void enableCheats(bool enable); void enableCheats(bool enable);
melonDS::ARCodeFile* getCheatFile(); melonDS::ARCodeFile* getCheatFile();
@ -188,12 +188,14 @@ private:
std::pair<std::unique_ptr<melonDS::Firmware>, std::string> generateDefaultFirmware(); std::pair<std::unique_ptr<melonDS::Firmware>, std::string> generateDefaultFirmware();
bool parseMacAddress(void* data); bool parseMacAddress(void* data);
void customizeFirmware(melonDS::Firmware& firmware, bool overridesettings) noexcept; void customizeFirmware(melonDS::Firmware& firmware, bool overridesettings) noexcept;
bool loadROMData(const QStringList& filepath, std::unique_ptr<melonDS::u8[]>& filedata, melonDS::u32& filelen, std::string& basepath, std::string& romname) noexcept; bool loadROMData(const QStringList& filepath, std::unique_ptr<melonDS::u8[]>& filedata, melonDS::u32& filelen, std::string& basepath, std::string& romname) noexcept;
QString getSavErrorString(std::string& filepath, bool gba); QString getSavErrorString(std::string& filepath, bool gba);
bool loadROM(QStringList filepath, bool reset); bool loadROM(QStringList filepath, bool reset);
void ejectCart(); void ejectCart();
bool cartInserted(); bool cartInserted();
QString cartLabel(); QString cartLabel();
bool loadGBAROM(QStringList filepath); bool loadGBAROM(QStringList filepath);
void loadGBAAddon(int type); void loadGBAAddon(int type);
void ejectGBACart(); void ejectGBACart();
@ -264,6 +266,8 @@ private:
std::string baseGBAROMDir; std::string baseGBAROMDir;
std::string baseGBAROMName; std::string baseGBAROMName;
std::string baseGBAAssetName; std::string baseGBAAssetName;
bool changeGBACart;
std::unique_ptr<melonDS::GBACart::CartCommon> nextGBACart;
// HACK // HACK
public: public:

View File

@ -109,7 +109,7 @@ void EmuThread::run()
Config::Table& globalCfg = emuInstance->getGlobalConfig(); Config::Table& globalCfg = emuInstance->getGlobalConfig();
u32 mainScreenPos[3]; u32 mainScreenPos[3];
//emuInstance->updateConsole(nullptr, nullptr); //emuInstance->updateConsole(nullptr);
// No carts are inserted when melonDS first boots // No carts are inserted when melonDS first boots
mainScreenPos[0] = 0; mainScreenPos[0] = 0;