diff options
author | Adrian Siekierka <kontakt@asie.pl> | 2023-12-15 08:19:53 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-15 08:19:53 +0100 |
commit | 6f47c9ed4c0e5b1035089805f272c6965343f113 (patch) | |
tree | fadad3548cea8de7fe5ae380d4ff857909c9cb27 /src/NDSCart.h | |
parent | 9bfc9c08ffe88de4b54734d6fd03182c0a51e181 (diff) |
Support emulating R4 Revolution/M3DS Simply cartridges. (#1854)
* Support emulating R4 Revolution/M3DS Simply cartridges.
* NDSCartR4: Write state information to savestate file.
* NDSCart: Use strncmp instead of strcmp for R4 detection.
* NDSCartR4: stylistic improvements
* NDSCartR4: rudimentary Ace3DS support
* NDSCartR4: fix boot when firmware enabled
* NDSCartR4: Fix for namespace changes
---------
Co-authored-by: RSDuck <RSDuck@users.noreply.github.com>
Diffstat (limited to 'src/NDSCart.h')
-rw-r--r-- | src/NDSCart.h | 87 |
1 files changed, 75 insertions, 12 deletions
diff --git a/src/NDSCart.h b/src/NDSCart.h index dcbc1eb..7d482ab 100644 --- a/src/NDSCart.h +++ b/src/NDSCart.h @@ -45,6 +45,7 @@ enum CartType RetailIR = 0x103, RetailBT = 0x104, Homebrew = 0x201, + UnlicensedR4 = 0x301 }; class NDSCartSlot; @@ -236,19 +237,13 @@ public: u8 SPIWrite(u8 val, u32 pos, bool last) override; }; -// CartHomebrew -- homebrew 'cart' (no SRAM, DLDI) -class CartHomebrew : public CartCommon +// CartSD -- any 'cart' with an SD card slot +class CartSD : public CartCommon { public: - 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; - - void Reset() override; - void SetupDirectBoot(const std::string& romname, NDS& nds) override; - - int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, const u8* cmd, u8* data, u32 len) override; - void ROMCommandFinish(const u8* cmd, u8* data, u32 len) override; + CartSD(const u8* rom, u32 len, u32 chipid, ROMListEntry romparams, std::optional<FATStorage>&& sdcard = std::nullopt); + CartSD(std::unique_ptr<u8[]>&& rom, u32 len, u32 chipid, ROMListEntry romparams, std::optional<FATStorage>&& sdcard = std::nullopt); + ~CartSD() override; [[nodiscard]] const std::optional<FATStorage>& GetSDCard() const noexcept { return SD; } void SetSDCard(FATStorage&& sdcard) noexcept { SD = std::move(sdcard); } @@ -260,7 +255,7 @@ public: // it just leaves behind an optional with a moved-from value } -private: +protected: void ApplyDLDIPatchAt(u8* binary, u32 dldioffset, const u8* patch, u32 patchlen, bool readonly) const; void ApplyDLDIPatch(const u8* patch, u32 patchlen, bool readonly); void ReadROM_B7(u32 addr, u32 len, u8* data, u32 offset) const; @@ -268,6 +263,74 @@ private: std::optional<FATStorage> SD {}; }; +// CartHomebrew -- homebrew 'cart' (no SRAM, DLDI) +class CartHomebrew : public CartSD +{ +public: + 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; + + void Reset() override; + void SetupDirectBoot(const std::string& romname, NDS& nds) override; + + int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, const u8* cmd, u8* data, u32 len) override; + void ROMCommandFinish(const u8* cmd, u8* data, u32 len) override; +}; + +// CartR4 -- unlicensed R4 'cart' (NDSCartR4.cpp) +enum CartR4Type +{ + /* non-SDHC carts */ + CartR4TypeM3Simply = 0, + CartR4TypeR4 = 1, + /* SDHC carts */ + CartR4TypeAce3DS = 2 +}; + +enum CartR4Language +{ + CartR4LanguageJapanese = (7 << 3) | 1, + CartR4LanguageEnglish = (7 << 3) | 2, + CartR4LanguageFrench = (2 << 3) | 2, + CartR4LanguageKorean = (4 << 3) | 2, + CartR4LanguageSimplifiedChinese = (6 << 3) | 3, + CartR4LanguageTraditionalChinese = (7 << 3) | 3 +}; + +class CartR4 : public CartSD +{ +public: + CartR4(std::unique_ptr<u8[]>&& rom, u32 len, u32 chipid, ROMListEntry romparams, CartR4Type ctype, CartR4Language clanguage, + std::optional<FATStorage>&& sdcard = std::nullopt); + ~CartR4() override; + + void Reset() override; + + void DoSavestate(Savestate* file) override; + + int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, const u8* cmd, u8* data, u32 len) override; + void ROMCommandFinish(const u8* cmd, u8* data, u32 len) override; + +private: + inline u32 GetAdjustedSector(u32 sector) const + { + return R4CartType >= CartR4TypeAce3DS ? sector : sector >> 9; + } + + u16 GetEncryptionKey(u16 sector); + void ReadSDToBuffer(u32 sector, bool rom); + u64 SDFATEntrySectorGet(u32 entry, u32 addr); + + s32 EncryptionKey; + u32 FATEntryOffset[2]; + u8 Buffer[512]; + u8 InitStatus; + CartR4Type R4CartType; + CartR4Language CartLanguage; + bool BufferInitialized; +}; + class NDSCartSlot { public: |