mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-23 06:10:03 -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:
204
src/DSi_SD.cpp
204
src/DSi_SD.cpp
@ -18,6 +18,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "Args.h"
|
||||
#include "DSi.h"
|
||||
#include "DSi_SD.h"
|
||||
#include "DSi_NAND.h"
|
||||
@ -26,6 +27,10 @@
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
using std::holds_alternative;
|
||||
using std::unique_ptr;
|
||||
using std::get_if;
|
||||
using std::get;
|
||||
using namespace Platform;
|
||||
|
||||
// observed IRQ behavior during transfers
|
||||
@ -57,36 +62,38 @@ enum
|
||||
};
|
||||
|
||||
|
||||
DSi_SDHost::DSi_SDHost(melonDS::DSi& dsi, u32 num) : DSi(dsi)
|
||||
DSi_SDHost::DSi_SDHost(melonDS::DSi& dsi, DSi_NAND::NANDImage&& nand, std::optional<FATStorage>&& sdcard) noexcept : DSi(dsi), Num(0)
|
||||
{
|
||||
Num = num;
|
||||
|
||||
DSi.RegisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
DSi.RegisterEventFunc( Event_DSi_SDMMCTransfer,
|
||||
Transfer_TX, MemberEventFunc(DSi_SDHost, FinishTX));
|
||||
DSi.RegisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
DSi.RegisterEventFunc( Event_DSi_SDMMCTransfer,
|
||||
Transfer_RX, MemberEventFunc(DSi_SDHost, FinishRX));
|
||||
|
||||
Ports[0] = nullptr;
|
||||
Ports[0] = sdcard ? std::make_unique<DSi_MMCStorage>(DSi, this, std::move(*sdcard)) : nullptr;
|
||||
sdcard = std::nullopt; // to ensure that sdcard isn't left with a moved-from object
|
||||
Ports[1] = std::make_unique<DSi_MMCStorage>(DSi, this, std::move(nand));
|
||||
}
|
||||
|
||||
// Creates an SDIO host
|
||||
DSi_SDHost::DSi_SDHost(melonDS::DSi& dsi) noexcept : DSi(dsi), Num(1)
|
||||
{
|
||||
DSi.RegisterEventFunc(Event_DSi_SDIOTransfer ,
|
||||
Transfer_TX, MemberEventFunc(DSi_SDHost, FinishTX));
|
||||
DSi.RegisterEventFunc(Event_DSi_SDIOTransfer,
|
||||
Transfer_RX, MemberEventFunc(DSi_SDHost, FinishRX));
|
||||
|
||||
Ports[0] = std::make_unique<DSi_NWifi>(DSi, this);
|
||||
Ports[1] = nullptr;
|
||||
}
|
||||
|
||||
DSi_SDHost::~DSi_SDHost()
|
||||
{
|
||||
if (Ports[0]) delete Ports[0];
|
||||
if (Ports[1]) delete Ports[1];
|
||||
|
||||
DSi.UnregisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
Transfer_TX);
|
||||
DSi.UnregisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
Transfer_RX);
|
||||
}
|
||||
|
||||
void DSi_SDHost::CloseHandles()
|
||||
{
|
||||
if (Ports[0]) delete Ports[0];
|
||||
if (Ports[1]) delete Ports[1];
|
||||
Ports[0] = nullptr;
|
||||
Ports[1] = nullptr;
|
||||
// unique_ptr's destructor will clean up the ports
|
||||
}
|
||||
|
||||
void DSi_SDHost::Reset()
|
||||
@ -129,48 +136,70 @@ void DSi_SDHost::Reset()
|
||||
|
||||
TXReq = false;
|
||||
|
||||
CloseHandles();
|
||||
if (Ports[0]) Ports[0]->Reset();
|
||||
if (Ports[1]) Ports[1]->Reset();
|
||||
}
|
||||
|
||||
if (Num == 0)
|
||||
FATStorage* DSi_SDHost::GetSDCard() noexcept
|
||||
{
|
||||
if (Num != 0) return nullptr;
|
||||
return static_cast<DSi_MMCStorage*>(Ports[0].get())->GetSDCard();
|
||||
}
|
||||
|
||||
const FATStorage* DSi_SDHost::GetSDCard() const noexcept
|
||||
{
|
||||
if (Num != 0) return nullptr;
|
||||
return static_cast<const DSi_MMCStorage*>(Ports[0].get())->GetSDCard();
|
||||
}
|
||||
|
||||
DSi_NAND::NANDImage* DSi_SDHost::GetNAND() noexcept
|
||||
{
|
||||
if (Num != 0) return nullptr;
|
||||
return static_cast<DSi_MMCStorage*>(Ports[1].get())->GetNAND();
|
||||
}
|
||||
|
||||
const DSi_NAND::NANDImage* DSi_SDHost::GetNAND() const noexcept
|
||||
{
|
||||
if (Num != 0) return nullptr;
|
||||
return static_cast<const DSi_MMCStorage*>(Ports[1].get())->GetNAND();
|
||||
}
|
||||
|
||||
void DSi_SDHost::SetSDCard(FATStorage&& sdcard) noexcept
|
||||
{
|
||||
if (Num != 0) return;
|
||||
|
||||
static_cast<DSi_MMCStorage*>(Ports[0].get())->SetSDCard(std::move(sdcard));
|
||||
}
|
||||
|
||||
void DSi_SDHost::SetSDCard(std::optional<FATStorage>&& sdcard) noexcept
|
||||
{
|
||||
if (Num != 0) return;
|
||||
|
||||
if (sdcard)
|
||||
{
|
||||
DSi_MMCStorage* sd;
|
||||
DSi_MMCStorage* mmc;
|
||||
|
||||
if (Platform::GetConfigBool(Platform::DSiSD_Enable))
|
||||
if (!Ports[0])
|
||||
{
|
||||
std::string folderpath;
|
||||
if (Platform::GetConfigBool(Platform::DSiSD_FolderSync))
|
||||
folderpath = Platform::GetConfigString(Platform::DSiSD_FolderPath);
|
||||
else
|
||||
folderpath = "";
|
||||
|
||||
sd = new DSi_MMCStorage(this,
|
||||
false,
|
||||
Platform::GetConfigString(Platform::DSiSD_ImagePath),
|
||||
(u64)Platform::GetConfigInt(Platform::DSiSD_ImageSize) * 1024 * 1024,
|
||||
Platform::GetConfigBool(Platform::DSiSD_ReadOnly),
|
||||
folderpath);
|
||||
u8 sd_cid[16] = {0xBD, 0x12, 0x34, 0x56, 0x78, 0x03, 0x4D, 0x30, 0x30, 0x46, 0x50, 0x41, 0x00, 0x00, 0x15, 0x00};
|
||||
sd->SetCID(sd_cid);
|
||||
Ports[0] = std::make_unique<DSi_MMCStorage>(DSi, this, std::move(*sdcard));
|
||||
}
|
||||
else
|
||||
sd = nullptr;
|
||||
|
||||
mmc = new DSi_MMCStorage(this, *DSi.NANDImage);
|
||||
mmc->SetCID(DSi.NANDImage->GetEMMCID().data());
|
||||
|
||||
Ports[0] = sd;
|
||||
Ports[1] = mmc;
|
||||
{
|
||||
static_cast<DSi_MMCStorage*>(Ports[0].get())->SetSDCard(std::move(*sdcard));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DSi_NWifi* nwifi = new DSi_NWifi(DSi, this);
|
||||
|
||||
Ports[0] = nwifi;
|
||||
Ports[0] = nullptr;
|
||||
}
|
||||
|
||||
if (Ports[0]) Ports[0]->Reset();
|
||||
if (Ports[1]) Ports[1]->Reset();
|
||||
sdcard = std::nullopt;
|
||||
// a moved-from optional isn't empty, it contains a moved-from object
|
||||
}
|
||||
|
||||
void DSi_SDHost::SetNAND(DSi_NAND::NANDImage&& nand) noexcept
|
||||
{
|
||||
if (Num != 0) return;
|
||||
|
||||
static_cast<DSi_MMCStorage*>(Ports[1].get())->SetNAND(std::move(nand));
|
||||
}
|
||||
|
||||
void DSi_SDHost::DoSavestate(Savestate* file)
|
||||
@ -261,7 +290,7 @@ void DSi_SDHost::SetCardIRQ()
|
||||
if (!(CardIRQCtl & (1<<0))) return;
|
||||
|
||||
u16 oldflags = CardIRQStatus & ~CardIRQMask;
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1].get();
|
||||
|
||||
if (dev->IRQ) CardIRQStatus |= (1<<0);
|
||||
else CardIRQStatus &= ~(1<<0);
|
||||
@ -332,7 +361,7 @@ u32 DSi_SDHost::DataRX(u8* data, u32 len)
|
||||
|
||||
void DSi_SDHost::FinishTX(u32 param)
|
||||
{
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1].get();
|
||||
|
||||
if (BlockCountInternal == 0)
|
||||
{
|
||||
@ -419,7 +448,7 @@ u32 DSi_SDHost::GetTransferrableLen(u32 len)
|
||||
|
||||
void DSi_SDHost::CheckRX()
|
||||
{
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1].get();
|
||||
|
||||
CheckSwapFIFO();
|
||||
|
||||
@ -459,7 +488,7 @@ void DSi_SDHost::CheckTX()
|
||||
return;
|
||||
}
|
||||
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1].get();
|
||||
if (dev) dev->ContinueTransfer();
|
||||
}
|
||||
|
||||
@ -550,7 +579,6 @@ u16 DSi_SDHost::ReadFIFO16()
|
||||
return 0;
|
||||
}
|
||||
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
|
||||
u16 ret = DataFIFO[f].Read();
|
||||
|
||||
if (DataFIFO[f].IsEmpty())
|
||||
@ -571,7 +599,6 @@ u32 DSi_SDHost::ReadFIFO32()
|
||||
return 0;
|
||||
}
|
||||
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
|
||||
u32 ret = DataFIFO32.Read();
|
||||
|
||||
if (DataFIFO32.IsEmpty())
|
||||
@ -593,7 +620,7 @@ void DSi_SDHost::Write(u32 addr, u16 val)
|
||||
Command = val;
|
||||
u8 cmd = Command & 0x3F;
|
||||
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1].get();
|
||||
if (dev)
|
||||
{
|
||||
// CHECKME
|
||||
@ -707,7 +734,6 @@ void DSi_SDHost::Write(u32 addr, u16 val)
|
||||
|
||||
void DSi_SDHost::WriteFIFO16(u16 val)
|
||||
{
|
||||
DSi_SDDevice* dev = Ports[PortSelect & 0x1];
|
||||
u32 f = CurFIFO;
|
||||
if (DataFIFO[f].IsFull())
|
||||
{
|
||||
@ -780,34 +806,23 @@ void DSi_SDHost::CheckSwapFIFO()
|
||||
|
||||
#define MMC_DESC (Internal?"NAND":"SDcard")
|
||||
|
||||
DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, DSi_NAND::NANDImage& nand)
|
||||
: DSi_SDDevice(host), Internal(true), NAND(&nand), SD(nullptr)
|
||||
DSi_MMCStorage::DSi_MMCStorage(melonDS::DSi& dsi, DSi_SDHost* host, DSi_NAND::NANDImage&& nand) noexcept
|
||||
: DSi_SDDevice(host), DSi(dsi), Storage(std::move(nand))
|
||||
{
|
||||
ReadOnly = false;
|
||||
SetCID(get<DSi_NAND::NANDImage>(Storage).GetEMMCID().data());
|
||||
}
|
||||
|
||||
DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const std::string& filename, u64 size, bool readonly, const std::string& sourcedir)
|
||||
: DSi_SDDevice(host)
|
||||
DSi_MMCStorage::DSi_MMCStorage(melonDS::DSi& dsi, DSi_SDHost* host, FATStorage&& sdcard) noexcept
|
||||
: DSi_SDDevice(host), DSi(dsi), Storage(std::move(sdcard))
|
||||
{
|
||||
Internal = internal;
|
||||
NAND = nullptr;
|
||||
|
||||
SD = new FATStorage(filename, size, readonly, sourcedir);
|
||||
SD->Open();
|
||||
|
||||
ReadOnly = readonly;
|
||||
ReadOnly = get<FATStorage>(Storage).IsReadOnly();
|
||||
SetCID(DSiSDCardCID);
|
||||
}
|
||||
|
||||
DSi_MMCStorage::~DSi_MMCStorage()
|
||||
{
|
||||
if (SD)
|
||||
{
|
||||
SD->Close();
|
||||
delete SD;
|
||||
}
|
||||
|
||||
// Do not close the NANDImage, it's not owned by this object
|
||||
}
|
||||
// The FATStorage or NANDImage is owned by this object;
|
||||
// std::variant's destructor will clean it up.
|
||||
DSi_MMCStorage::~DSi_MMCStorage() = default;
|
||||
|
||||
void DSi_MMCStorage::Reset()
|
||||
{
|
||||
@ -836,7 +851,7 @@ void DSi_MMCStorage::Reset()
|
||||
|
||||
void DSi_MMCStorage::DoSavestate(Savestate* file)
|
||||
{
|
||||
file->Section(Internal ? "NAND" : "SDCR");
|
||||
file->Section(holds_alternative<DSi_NAND::NANDImage>(Storage) ? "NAND" : "SDCR");
|
||||
|
||||
file->VarArray(CID, 16);
|
||||
file->VarArray(CSD, 16);
|
||||
@ -871,7 +886,7 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param)
|
||||
case 1: // SEND_OP_COND
|
||||
// CHECKME!!
|
||||
// also TODO: it's different for the SD card
|
||||
if (Internal)
|
||||
if (std::holds_alternative<DSi_NAND::NANDImage>(Storage))
|
||||
{
|
||||
param &= ~(1<<30);
|
||||
OCR &= 0xBF000000;
|
||||
@ -895,7 +910,7 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param)
|
||||
return;
|
||||
|
||||
case 3: // get/set RCA
|
||||
if (Internal)
|
||||
if (holds_alternative<DSi_NAND::NANDImage>(Storage))
|
||||
{
|
||||
RCA = param >> 16;
|
||||
Host->SendResponse(CSR|0x10000, true); // huh??
|
||||
@ -930,7 +945,8 @@ void DSi_MMCStorage::SendCMD(u8 cmd, u32 param)
|
||||
|
||||
case 12: // stop operation
|
||||
SetState(0x04);
|
||||
if (NAND) FileFlush(NAND->GetFile());
|
||||
if (auto* nand = get_if<DSi_NAND::NANDImage>(&Storage))
|
||||
FileFlush(nand->GetFile());
|
||||
RWCommand = 0;
|
||||
Host->SendResponse(CSR, true);
|
||||
return;
|
||||
@ -1011,7 +1027,7 @@ void DSi_MMCStorage::SendACMD(u8 cmd, u32 param)
|
||||
// DSi boot2 sets this to 0x40100000 (hardcoded)
|
||||
// then has two codepaths depending on whether bit30 did get set
|
||||
// is it settable at all on the MMC? probably not.
|
||||
if (Internal) param &= ~(1<<30);
|
||||
if (holds_alternative<DSi_NAND::NANDImage>(Storage)) param &= ~(1<<30);
|
||||
OCR &= 0xBF000000;
|
||||
OCR |= (param & 0x40FFFFFF);
|
||||
Host->SendResponse(OCR, true);
|
||||
@ -1057,14 +1073,14 @@ u32 DSi_MMCStorage::ReadBlock(u64 addr)
|
||||
len = Host->GetTransferrableLen(len);
|
||||
|
||||
u8 data[0x200];
|
||||
if (SD)
|
||||
if (auto* sd = std::get_if<FATStorage>(&Storage))
|
||||
{
|
||||
SD->ReadSectors((u32)(addr >> 9), 1, data);
|
||||
sd->ReadSectors((u32)(addr >> 9), 1, data);
|
||||
}
|
||||
else if (NAND)
|
||||
else if (auto* nand = std::get_if<DSi_NAND::NANDImage>(&Storage))
|
||||
{
|
||||
FileSeek(NAND->GetFile(), addr, FileSeekOrigin::Start);
|
||||
FileRead(&data[addr & 0x1FF], 1, len, NAND->GetFile());
|
||||
FileSeek(nand->GetFile(), addr, FileSeekOrigin::Start);
|
||||
FileRead(&data[addr & 0x1FF], 1, len, nand->GetFile());
|
||||
}
|
||||
|
||||
return Host->DataRX(&data[addr & 0x1FF], len);
|
||||
@ -1078,23 +1094,23 @@ u32 DSi_MMCStorage::WriteBlock(u64 addr)
|
||||
u8 data[0x200];
|
||||
if (len < 0x200)
|
||||
{
|
||||
if (SD)
|
||||
if (auto* sd = get_if<FATStorage>(&Storage))
|
||||
{
|
||||
SD->ReadSectors((u32)(addr >> 9), 1, data);
|
||||
sd->ReadSectors((u32)(addr >> 9), 1, data);
|
||||
}
|
||||
}
|
||||
if ((len = Host->DataTX(&data[addr & 0x1FF], len)))
|
||||
{
|
||||
if (!ReadOnly)
|
||||
{
|
||||
if (SD)
|
||||
if (auto* sd = get_if<FATStorage>(&Storage))
|
||||
{
|
||||
SD->WriteSectors((u32)(addr >> 9), 1, data);
|
||||
sd->WriteSectors((u32)(addr >> 9), 1, data);
|
||||
}
|
||||
else if (NAND)
|
||||
else if (auto* nand = get_if<DSi_NAND::NANDImage>(&Storage))
|
||||
{
|
||||
FileSeek(NAND->GetFile(), addr, FileSeekOrigin::Start);
|
||||
FileWrite(&data[addr & 0x1FF], 1, len, NAND->GetFile());
|
||||
FileSeek(nand->GetFile(), addr, FileSeekOrigin::Start);
|
||||
FileWrite(&data[addr & 0x1FF], 1, len, nand->GetFile());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user