mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-26 15:50:00 -06:00
Refactor how save data (including SD cards) is initialized (#1898)
* Remove `FATStorage::Open` and `FATStorage::Close` - That's what the constructor and destructor are for, respectively * Add `FATStorage::IsReadOnly` * Slight cleanup of `FATStorage` - Make it move-constructible and move-assignable - Represent the absence of a sync directory with `std::optional`, not an empty string - Add `FATStorageArgs` for later use * Refactor `CartHomebrew` to accept an optional `FATStorageArgs` - `CartHomebrew` uses it to load an SD card image - Not passing a `FATStorage` directly because we won't know if we need to load the card until we parse the ROM - Store the `FATStorage` inside a `std::optional` instead of a pointer - `CartHomebrew::Reset` no longer reloads the SD card; the frontend needs to set it with the `SetSDCard` method * Close `NANDImage::CurFile` when move-assigning - Whoops * Add `Args.h` - To construct a `NDS` or `DSi` with arguments - Mostly intended for system files * Fix incorrect `final` placement * Refactor how `DSi`'s NAND and SD card are set - Provide them via a `DSiArgs` argument in the constructor - Give `DSi_MMCStorage` ownership of the `NANDImage` or `FATStorage` as needed, and expose getters/setters - Replace `DSi_SDHost::Ports` with a `array<unique_ptr, 2>` to reduce the risk of leaks - Store `DSi_MMCStorage`'s disk images in a `std::variant` - The SD card and NAND image are no longer reset in `Reset()`; the frontend will need to do that itself * Add getters/setters on `DSi` itself for its storage media * Remove newly-unused `Platform::ConfigEntry`s * Use `DSi::SetNAND` in the frontend * Add `EmuThread::NeedToRecreateConsole` * Document `NDSArgs` and give its fields default values * Refactor how system files are loaded upon construction - Pass `NDSArgs&&` into `NDS`'s constructor - Use `std::array` for the emulator's BIOS images and the built-in FreeBIOS, to simplify copying and comparison - Initialize the BIOS, firmware, and SD cards from `NDSArgs` or `DSiArgs` - Add a new default constructor for `NDS` (not `DSi`) that initializes the DS with default system files - Embed `FirmwareMem::Firmware` directly instead of in a `unique_ptr` - `SPIHost` now takes a `Firmware&&` that it forwards to `FirmwareMem` - Add `Firmware` getters/setters plus `const` variants for `NDS`, `Firmware`, and `FirmwareMem` - Simplify installation of firmware * Initialize the DSi BIOS in the constructor - Change `DSi::ARM9iBIOS` and `ARM7iBIOS` to `std::array` * Update the frontend to reflect the core's changes * Remove `DSi_SDHost::CloseHandles` * Pass `nullopt` instead of the empty string when folder sync is off * Deduplicate ROM extraction logic - `LoadGBAROM` and `LoadROM` now delegate to `LoadROMData` - Also use `unique_ptr` instead of `new[]` * Oops, missed some `get()`'s * Move `NDS::IsLoadedARM9BIOSBuiltIn` to the header - So it's likelier to be inlined - Same for the ARM7 version * Remove `NDS::SetConsoleType` * Add `NDS::SetFirmware` * Move `GBACart::SetupSave` to be `protected` - It was only ever used inside the class * Rename `GBACart::LoadSave` to `SetSaveMemory` - Same for the cart slot * Declare `GBACartSlot` as a friend of `GBACart::CartCommon` * Revise `GBACartSlot`'s getters and setters - Rename `InsertROM` and `LoadROM` to `SetCart` - Add a `GetCart` method * Clean up getters and setters for NDS and GBA carts * Clean up how carts are inserted into the slots - Remove setters that operate directly on pointers, to simplify error-handling (use ParseROM instead) - Add overloads for all carts that accept a `const u8*` (to copy the ROM data) and a `unique_ptr<u8[]>` (to move the ROM data) - Store all ROM and RAM data in `unique_ptr` - Default-initialize all fields - Simplify constructors and destructors, inheriting where applicable * Refactor GBA save data insertion - Make `SetupSave` private and non-virtual and move its logic to be in `SetSaveMemory` - Add overloads for setting save data in the constructor - Update the SRAM completely in `SetSaveMemory` * Clean up `NDSCart::CartCommon::SetSaveMemory` - Move its declaration next to the other `SaveMemory` methods - Move its (empty) implementation to the header * Add some comments * Add Utils.cpp and Utils.h * Rename some functions in Utils for clarity * Add `GBACart::ParseROM` and `NDSCart::ParseROM` overloads that accept `unique_ptr<u8[]>` - The `u8*` overloads delegate to these new overloads - Also move `SetupSave` for both kinds of carts to be private non-virtual methods * Finalize the `NDSCart` refactor - Add `NDSCartArgs` to pass to `ParseROM` - Add SRAM arguments for all retail carts - Initialize SRAM inside the constructor - Delegate to other constructors where possible * Replace `ROMManager::NDSSave` and `GBASave` with `unique_ptr` * Make both cart slots return the previously-inserted cart in `EjectCart` - Primarily intended for reusing carts when resetting the console * Make `NDS::EjectCart` return the old cart * Initialize both cart slots with the provided ROM (if any) * Make `NDS::EjectGBACart` return the ejected cart * Clean up some comments in Args.h * Rename `ROMManager::LoadBIOS` to `BootToMenu` - Clarifies the intent * Add `ROMManager::LoadDLDISDCard` * Add a doc comment * Refactor how the `NDS` is created or updated - Rewrite `CreateConsole` to read from `Config` and load system files, but accept carts as arguments - Fail without creating an `NDS` if any required system file doesn't load - Add `UpdateConsole`, which delegates to `CreateConsole` if switching modes or starting the app - Use `std::variant` to indicate whether a cart should be removed, inserted, or reused - Load all system files (plus SD cards) in `UpdateConsole` - Eject the cart and reinsert it into the new console if applicable * Respect some more `Config` settings in the `Load*` functions * Remove `InstallNAND` in favor of `LoadNAND` * Fix some potential bugs in `LoadROMData` * Oops, forgot to delete the definition of `InstallNAND` * Add functions to get `FATStorageArgs` - Not the cards themselves, but to get the arguments you _would_ use to load the cards * Refactor `ROMManager::LoadROM` - Load the ROM and save data before trying to initialize the console * Clean up `ROMManager::Reset` and `BootToMenu` - Let `EmuThread::UpdateConsole` do the heavy lifting * Clean up `LoadGBAROM` * Remove some unused functions * Set the default DSi BIOS to be broken in `DSiArgs` * Respect `Config::DSiFullBIOSBoot` when loading DSi BIOS files * Remove some more unused functions * Remove redundant `virtual` specifiers * Refactor `NDSCart::CartCommon::Type()` to return a member instead of a constant - One less virtual dispatch - The cart type is read in `NDSCartSlot::DoSavestate`, which is a path downstream (due to rewinding) * Remove a hash that I computed for debugging purposes * Make `ByteSwap` `constexpr` * Remove an unused `#include` * Remove unnecessary functions from the NDS carts - Mostly overrides that added nothing * Default-initialize all NDSCart fields * Make `GBACart::Type()` not rely on virtual dispatch - `GBACartSlot::DoSavestate` calls it, and savestates can be a hot path downstream * Don't forget to reset the base class in `CartGameSolarSensor::Reset()` * Remove redundant `virtual` specifiers * Default-initialize some fields in `GBACart` * Fix ROMs not loading from archives in the frontend - Whoops * Change how the `Firmware` member is declared * Forgot an include in Utils.cpp * Rename `FirmwareMem::Firmware` to `FirmwareData` to fix a build error on Linux - One of these days I'll convince you people to let me use `camelCaseMemberNames` * Add `override` to places in `DSi_MMCStorage` that warrant it * Fix firmware saving on the frontend - Remove `GetConfigString` and `ConfigEntry::WifiSettingsPath` while I'm at it * Add a non-const `GetNAND()`
This commit is contained in:
228
src/NDSCart.h
228
src/NDSCart.h
@ -22,7 +22,7 @@
|
||||
#include <array>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <array>
|
||||
#include <variant>
|
||||
|
||||
#include "types.h"
|
||||
#include "Savestate.h"
|
||||
@ -49,14 +49,32 @@ enum CartType
|
||||
|
||||
class NDSCartSlot;
|
||||
|
||||
/// Arguments used to create and populate an NDS cart of unknown type.
|
||||
/// Different carts take different subsets of these arguments,
|
||||
/// but we won't know which ones to use
|
||||
/// until we parse the header at runtime.
|
||||
struct NDSCartArgs
|
||||
{
|
||||
/// The arguments used to load a homebrew SD card image.
|
||||
/// If \c nullopt, then the cart will not have an SD card.
|
||||
/// Ignored for retail ROMs.
|
||||
std::optional<FATStorageArgs> SDCard = std::nullopt;
|
||||
|
||||
/// Save RAM to load into the cartridge.
|
||||
/// If \c nullopt, then the cart's SRAM buffer will be empty.
|
||||
/// Ignored for homebrew ROMs.
|
||||
std::optional<std::pair<std::unique_ptr<u8[]>, u32>> SRAM = std::nullopt;
|
||||
};
|
||||
|
||||
// CartCommon -- base code shared by all cart types
|
||||
class CartCommon
|
||||
{
|
||||
public:
|
||||
CartCommon(u8* rom, u32 len, u32 chipid, bool badDSiDump, ROMListEntry romparams);
|
||||
CartCommon(const u8* rom, u32 len, u32 chipid, bool badDSiDump, ROMListEntry romparams, CartType type);
|
||||
CartCommon(std::unique_ptr<u8[]>&& rom, u32 len, u32 chipid, bool badDSiDump, ROMListEntry romparams, CartType type);
|
||||
virtual ~CartCommon();
|
||||
|
||||
virtual u32 Type() const = 0;
|
||||
[[nodiscard]] u32 Type() const { return CartType; };
|
||||
[[nodiscard]] u32 Checksum() const;
|
||||
|
||||
virtual void Reset();
|
||||
@ -64,16 +82,16 @@ public:
|
||||
|
||||
virtual void DoSavestate(Savestate* file);
|
||||
|
||||
virtual void SetupSave(u32 type);
|
||||
virtual void LoadSave(const u8* savedata, u32 savelen);
|
||||
|
||||
virtual int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len);
|
||||
virtual void ROMCommandFinish(u8* cmd, u8* data, u32 len);
|
||||
|
||||
virtual u8 SPIWrite(u8 val, u32 pos, bool last);
|
||||
|
||||
virtual u8* GetSaveMemory() const;
|
||||
virtual u32 GetSaveMemoryLength() const;
|
||||
virtual u8* GetSaveMemory() { return nullptr; }
|
||||
virtual const u8* GetSaveMemory() const { return nullptr; }
|
||||
virtual u32 GetSaveMemoryLength() const { return 0; }
|
||||
virtual void SetSaveMemory(const u8* savedata, u32 savelen) {};
|
||||
|
||||
[[nodiscard]] const NDSHeader& GetHeader() const { return Header; }
|
||||
[[nodiscard]] NDSHeader& GetHeader() { return Header; }
|
||||
@ -82,48 +100,65 @@ public:
|
||||
[[nodiscard]] const NDSBanner* Banner() const;
|
||||
[[nodiscard]] const ROMListEntry& GetROMParams() const { return ROMParams; };
|
||||
[[nodiscard]] u32 ID() const { return ChipID; }
|
||||
[[nodiscard]] const u8* GetROM() const { return ROM; }
|
||||
[[nodiscard]] const u8* GetROM() const { return ROM.get(); }
|
||||
[[nodiscard]] u32 GetROMLength() const { return ROMLength; }
|
||||
protected:
|
||||
void ReadROM(u32 addr, u32 len, u8* data, u32 offset);
|
||||
|
||||
u8* ROM;
|
||||
u32 ROMLength;
|
||||
u32 ChipID;
|
||||
bool IsDSi;
|
||||
bool DSiMode;
|
||||
u32 DSiBase;
|
||||
std::unique_ptr<u8[]> ROM = nullptr;
|
||||
u32 ROMLength = 0;
|
||||
u32 ChipID = 0;
|
||||
bool IsDSi = false;
|
||||
bool DSiMode = false;
|
||||
u32 DSiBase = 0;
|
||||
|
||||
u32 CmdEncMode;
|
||||
u32 DataEncMode;
|
||||
u32 CmdEncMode = 0;
|
||||
u32 DataEncMode = 0;
|
||||
// Kept separate from the ROM data so we can decrypt the modcrypt area
|
||||
// without touching the overall ROM data
|
||||
NDSHeader Header;
|
||||
ROMListEntry ROMParams;
|
||||
NDSHeader Header {};
|
||||
ROMListEntry ROMParams {};
|
||||
const melonDS::NDSCart::CartType CartType = Default;
|
||||
};
|
||||
|
||||
// CartRetail -- regular retail cart (ROM, SPI SRAM)
|
||||
class CartRetail : public CartCommon
|
||||
{
|
||||
public:
|
||||
CartRetail(u8* rom, u32 len, u32 chipid, bool badDSiDump, ROMListEntry romparams);
|
||||
virtual ~CartRetail() override;
|
||||
CartRetail(
|
||||
const u8* rom,
|
||||
u32 len,
|
||||
u32 chipid,
|
||||
bool badDSiDump,
|
||||
ROMListEntry romparams,
|
||||
std::unique_ptr<u8[]>&& sram,
|
||||
u32 sramlen,
|
||||
melonDS::NDSCart::CartType type = CartType::Retail
|
||||
);
|
||||
CartRetail(
|
||||
std::unique_ptr<u8[]>&& rom,
|
||||
u32 len, u32 chipid,
|
||||
bool badDSiDump,
|
||||
ROMListEntry romparams,
|
||||
std::unique_ptr<u8[]>&& sram,
|
||||
u32 sramlen,
|
||||
melonDS::NDSCart::CartType type = CartType::Retail
|
||||
);
|
||||
~CartRetail() override;
|
||||
|
||||
virtual u32 Type() const override { return CartType::Retail; }
|
||||
void Reset() override;
|
||||
|
||||
virtual void Reset() override;
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
virtual void DoSavestate(Savestate* file) override;
|
||||
void SetSaveMemory(const u8* savedata, u32 savelen) override;
|
||||
|
||||
virtual void SetupSave(u32 type) override;
|
||||
virtual void LoadSave(const u8* savedata, u32 savelen) override;
|
||||
int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
|
||||
virtual int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
u8 SPIWrite(u8 val, u32 pos, bool last) override;
|
||||
|
||||
virtual u8 SPIWrite(u8 val, u32 pos, bool last) override;
|
||||
|
||||
virtual u8* GetSaveMemory() const override;
|
||||
virtual u32 GetSaveMemoryLength() const override;
|
||||
u8* GetSaveMemory() override { return SRAM.get(); }
|
||||
const u8* GetSaveMemory() const override { return SRAM.get(); }
|
||||
u32 GetSaveMemoryLength() const override { return SRAMLength; }
|
||||
|
||||
protected:
|
||||
void ReadROM_B7(u32 addr, u32 len, u8* data, u32 offset);
|
||||
@ -132,30 +167,29 @@ protected:
|
||||
u8 SRAMWrite_EEPROM(u8 val, u32 pos, bool last);
|
||||
u8 SRAMWrite_FLASH(u8 val, u32 pos, bool last);
|
||||
|
||||
u8* SRAM;
|
||||
u32 SRAMLength;
|
||||
u32 SRAMType;
|
||||
std::unique_ptr<u8[]> SRAM = nullptr;
|
||||
u32 SRAMLength = 0;
|
||||
u32 SRAMType = 0;
|
||||
|
||||
u8 SRAMCmd;
|
||||
u32 SRAMAddr;
|
||||
u32 SRAMFirstAddr;
|
||||
u8 SRAMStatus;
|
||||
u8 SRAMCmd = 0;
|
||||
u32 SRAMAddr = 0;
|
||||
u32 SRAMFirstAddr = 0;
|
||||
u8 SRAMStatus = 0;
|
||||
};
|
||||
|
||||
// CartRetailNAND -- retail cart with NAND SRAM (WarioWare DIY, Jam with the Band, ...)
|
||||
class CartRetailNAND : public CartRetail
|
||||
{
|
||||
public:
|
||||
CartRetailNAND(u8* rom, u32 len, u32 chipid, ROMListEntry romparams);
|
||||
CartRetailNAND(const u8* rom, u32 len, u32 chipid, ROMListEntry romparams, std::unique_ptr<u8[]>&& sram, u32 sramlen);
|
||||
CartRetailNAND(std::unique_ptr<u8[]>&& rom, u32 len, u32 chipid, ROMListEntry romparams, std::unique_ptr<u8[]>&& sram, u32 sramlen);
|
||||
~CartRetailNAND() override;
|
||||
|
||||
virtual u32 Type() const override { return CartType::RetailNAND; }
|
||||
|
||||
void Reset() override;
|
||||
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
void LoadSave(const u8* savedata, u32 savelen) override;
|
||||
void SetSaveMemory(const u8* savedata, u32 savelen) override;
|
||||
|
||||
int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
void ROMCommandFinish(u8* cmd, u8* data, u32 len) override;
|
||||
@ -165,22 +199,21 @@ public:
|
||||
private:
|
||||
void BuildSRAMID();
|
||||
|
||||
u32 SRAMBase;
|
||||
u32 SRAMWindow;
|
||||
u32 SRAMBase = 0;
|
||||
u32 SRAMWindow = 0;
|
||||
|
||||
u8 SRAMWriteBuffer[0x800];
|
||||
u32 SRAMWritePos;
|
||||
u8 SRAMWriteBuffer[0x800] {};
|
||||
u32 SRAMWritePos = 0;
|
||||
};
|
||||
|
||||
// CartRetailIR -- SPI IR device and SRAM
|
||||
class CartRetailIR : public CartRetail
|
||||
{
|
||||
public:
|
||||
CartRetailIR(u8* rom, u32 len, u32 chipid, u32 irversion, bool badDSiDump, ROMListEntry romparams);
|
||||
CartRetailIR(const u8* rom, u32 len, u32 chipid, u32 irversion, bool badDSiDump, ROMListEntry romparams, std::unique_ptr<u8[]>&& sram, u32 sramlen);
|
||||
CartRetailIR(std::unique_ptr<u8[]>&& rom, u32 len, u32 chipid, u32 irversion, bool badDSiDump, ROMListEntry romparams, std::unique_ptr<u8[]>&& sram, u32 sramlen);
|
||||
~CartRetailIR() override;
|
||||
|
||||
virtual u32 Type() const override { return CartType::RetailIR; }
|
||||
|
||||
void Reset() override;
|
||||
|
||||
void DoSavestate(Savestate* file) override;
|
||||
@ -188,23 +221,18 @@ public:
|
||||
u8 SPIWrite(u8 val, u32 pos, bool last) override;
|
||||
|
||||
private:
|
||||
u32 IRVersion;
|
||||
u8 IRCmd;
|
||||
u32 IRVersion = 0;
|
||||
u8 IRCmd = 0;
|
||||
};
|
||||
|
||||
// CartRetailBT - Pok<6F>mon Typing Adventure (SPI BT controller)
|
||||
class CartRetailBT : public CartRetail
|
||||
{
|
||||
public:
|
||||
CartRetailBT(u8* rom, u32 len, u32 chipid, ROMListEntry romparams);
|
||||
CartRetailBT(const u8* rom, u32 len, u32 chipid, ROMListEntry romparams, std::unique_ptr<u8[]>&& sram, u32 sramlen);
|
||||
CartRetailBT(std::unique_ptr<u8[]>&& rom, u32 len, u32 chipid, ROMListEntry romparams, std::unique_ptr<u8[]>&& sram, u32 sramlen);
|
||||
~CartRetailBT() override;
|
||||
|
||||
virtual u32 Type() const override { return CartType::RetailBT; }
|
||||
|
||||
void Reset() override;
|
||||
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
u8 SPIWrite(u8 val, u32 pos, bool last) override;
|
||||
};
|
||||
|
||||
@ -212,32 +240,38 @@ public:
|
||||
class CartHomebrew : public CartCommon
|
||||
{
|
||||
public:
|
||||
CartHomebrew(u8* rom, u32 len, u32 chipid, ROMListEntry romparams);
|
||||
CartHomebrew(const u8* rom, u32 len, u32 chipid, ROMListEntry romparams, std::optional<FATStorage>&& sdcard = std::nullopt);
|
||||
CartHomebrew(std::unique_ptr<u8[]>&& rom, u32 len, u32 chipid, ROMListEntry romparams, std::optional<FATStorage>&& sdcard = std::nullopt);
|
||||
~CartHomebrew() override;
|
||||
|
||||
virtual u32 Type() const override { return CartType::Homebrew; }
|
||||
|
||||
void Reset() override;
|
||||
void SetupDirectBoot(const std::string& romname, NDS& nds) override;
|
||||
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
void ROMCommandFinish(u8* cmd, u8* data, u32 len) override;
|
||||
|
||||
[[nodiscard]] const std::optional<FATStorage>& GetSDCard() const noexcept { return SD; }
|
||||
void SetSDCard(FATStorage&& sdcard) noexcept { SD = std::move(sdcard); }
|
||||
void SetSDCard(std::optional<FATStorage>&& sdcard) noexcept
|
||||
{
|
||||
SD = std::move(sdcard);
|
||||
sdcard = std::nullopt;
|
||||
// moving from an optional doesn't set it to nullopt,
|
||||
// it just leaves behind an optional with a moved-from value
|
||||
}
|
||||
|
||||
private:
|
||||
void ApplyDLDIPatchAt(u8* binary, u32 dldioffset, const u8* patch, u32 patchlen, bool readonly);
|
||||
void ApplyDLDIPatch(const u8* patch, u32 patchlen, bool readonly);
|
||||
void ReadROM_B7(u32 addr, u32 len, u8* data, u32 offset);
|
||||
|
||||
FATStorage* SD;
|
||||
bool ReadOnly;
|
||||
std::optional<FATStorage> SD {};
|
||||
};
|
||||
|
||||
class NDSCartSlot
|
||||
{
|
||||
public:
|
||||
NDSCartSlot(melonDS::NDS& nds) noexcept;
|
||||
explicit NDSCartSlot(melonDS::NDS& nds, std::unique_ptr<CartCommon>&& rom = nullptr) noexcept;
|
||||
~NDSCartSlot() noexcept;
|
||||
void Reset() noexcept;
|
||||
void ResetCart() noexcept;
|
||||
@ -252,25 +286,16 @@ public:
|
||||
/// If the provided cart is not valid,
|
||||
/// then the currently-loaded ROM will not be ejected.
|
||||
///
|
||||
/// @param cart Movable reference to the cart.
|
||||
/// @returns \c true if the cart was successfully loaded,
|
||||
/// \c false otherwise.
|
||||
/// @param cart Movable reference to the cart,
|
||||
/// or \c nullptr to eject the cart.
|
||||
/// @post If the cart was successfully loaded,
|
||||
/// then \c cart will be \c nullptr
|
||||
/// and \c Cart will contain the object that \c cart previously pointed to.
|
||||
/// Otherwise, \c cart and \c Cart will be both be unchanged.
|
||||
bool InsertROM(std::unique_ptr<CartCommon>&& cart) noexcept;
|
||||
void SetCart(std::unique_ptr<CartCommon>&& cart) noexcept;
|
||||
[[nodiscard]] CartCommon* GetCart() noexcept { return Cart.get(); }
|
||||
[[nodiscard]] const CartCommon* GetCart() const noexcept { return Cart.get(); }
|
||||
|
||||
/// Parses a ROM image and loads it into the emulator.
|
||||
/// This function is equivalent to calling ::ParseROM() and ::InsertROM() in sequence.
|
||||
/// @param romdata Pointer to the ROM image.
|
||||
/// The cart emulator maintains its own copy of this data,
|
||||
/// so the caller is free to discard this data after calling this function.
|
||||
/// @param romlen The length of the ROM image, in bytes.
|
||||
/// @returns \c true if the ROM image was successfully loaded,
|
||||
/// \c false if not.
|
||||
bool LoadROM(const u8* romdata, u32 romlen) noexcept;
|
||||
void LoadSave(const u8* savedata, u32 savelen) noexcept;
|
||||
void SetupDirectBoot(const std::string& romname) noexcept;
|
||||
|
||||
/// This function is intended to allow frontends to save and load SRAM
|
||||
@ -282,11 +307,15 @@ public:
|
||||
/// @returns Pointer to this cart's SRAM if a cart is loaded and supports SRAM, otherwise \c nullptr.
|
||||
[[nodiscard]] const u8* GetSaveMemory() const noexcept { return Cart ? Cart->GetSaveMemory() : nullptr; }
|
||||
[[nodiscard]] u8* GetSaveMemory() noexcept { return Cart ? Cart->GetSaveMemory() : nullptr; }
|
||||
void SetSaveMemory(const u8* savedata, u32 savelen) noexcept;
|
||||
|
||||
/// @returns The length of the buffer returned by ::GetSaveMemory()
|
||||
/// if a cart is loaded and supports SRAM, otherwise zero.
|
||||
[[nodiscard]] u32 GetSaveMemoryLength() const noexcept { return Cart ? Cart->GetSaveMemoryLength() : 0; }
|
||||
void EjectCart() noexcept;
|
||||
|
||||
/// @return The cart that was in the slot before it was ejected,
|
||||
/// or \c nullptr if the slot was already empty.
|
||||
std::unique_ptr<CartCommon> EjectCart() noexcept;
|
||||
u32 ReadROMData() noexcept;
|
||||
void WriteROMData(u32 val) noexcept;
|
||||
void WriteSPICnt(u16 val) noexcept;
|
||||
@ -294,9 +323,6 @@ public:
|
||||
[[nodiscard]] u8 ReadSPIData() const noexcept;
|
||||
void WriteSPIData(u8 val) noexcept;
|
||||
|
||||
[[nodiscard]] CartCommon* GetCart() noexcept { return Cart.get(); }
|
||||
[[nodiscard]] const CartCommon* GetCart() const noexcept { return Cart.get(); }
|
||||
|
||||
[[nodiscard]] u8 GetROMCommand(u8 index) const noexcept { return ROMCommand[index]; }
|
||||
void SetROMCommand(u8 index, u8 val) noexcept { ROMCommand[index] = val; }
|
||||
|
||||
@ -306,27 +332,27 @@ public:
|
||||
private:
|
||||
friend class CartCommon;
|
||||
melonDS::NDS& NDS;
|
||||
u16 SPICnt {};
|
||||
u32 ROMCnt {};
|
||||
u16 SPICnt = 0;
|
||||
u32 ROMCnt = 0;
|
||||
std::array<u8, 8> ROMCommand {};
|
||||
u8 SPIData;
|
||||
u32 SPIDataPos;
|
||||
bool SPIHold;
|
||||
u8 SPIData = 0;
|
||||
u32 SPIDataPos = 0;
|
||||
bool SPIHold = false;
|
||||
|
||||
u32 ROMData;
|
||||
u32 ROMData = 0;
|
||||
|
||||
std::array<u8, 0x4000> TransferData;
|
||||
u32 TransferPos;
|
||||
u32 TransferLen;
|
||||
u32 TransferDir;
|
||||
std::array<u8, 8> TransferCmd;
|
||||
std::array<u8, 0x4000> TransferData {};
|
||||
u32 TransferPos = 0;
|
||||
u32 TransferLen = 0;
|
||||
u32 TransferDir = 0;
|
||||
std::array<u8, 8> TransferCmd {};
|
||||
|
||||
std::unique_ptr<CartCommon> Cart;
|
||||
std::unique_ptr<CartCommon> Cart = nullptr;
|
||||
|
||||
std::array<u32, 0x412> Key1_KeyBuf;
|
||||
std::array<u32, 0x412> Key1_KeyBuf {};
|
||||
|
||||
u64 Key2_X;
|
||||
u64 Key2_Y;
|
||||
u64 Key2_X = 0;
|
||||
u64 Key2_Y = 0;
|
||||
|
||||
void Key1_Encrypt(u32* data) noexcept;
|
||||
void Key1_Decrypt(u32* data) noexcept;
|
||||
@ -346,9 +372,13 @@ private:
|
||||
/// The returned cartridge will contain a copy of this data,
|
||||
/// so the caller may deallocate \c romdata after this function returns.
|
||||
/// @param romlen The length of the ROM data in bytes.
|
||||
/// @param sdcard The arguments to use for initializing the SD card.
|
||||
/// Ignored if the parsed ROM is not homebrew.
|
||||
/// If not given, the cart will not have an SD card.
|
||||
/// @returns A \c NDSCart::CartCommon object representing the parsed ROM,
|
||||
/// or \c nullptr if the ROM data couldn't be parsed.
|
||||
std::unique_ptr<CartCommon> ParseROM(const u8* romdata, u32 romlen);
|
||||
std::unique_ptr<CartCommon> ParseROM(const u8* romdata, u32 romlen, std::optional<NDSCartArgs>&& args = std::nullopt);
|
||||
std::unique_ptr<CartCommon> ParseROM(std::unique_ptr<u8[]>&& romdata, u32 romlen, std::optional<NDSCartArgs>&& args = std::nullopt);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user