diff options
Diffstat (limited to 'src/DSi_SD.cpp')
-rw-r--r-- | src/DSi_SD.cpp | 202 |
1 files changed, 109 insertions, 93 deletions
diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp index 4cbf595..ff88def 100644 --- a/src/DSi_SD.cpp +++ b/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( Event_DSi_SDMMCTransfer, + Transfer_TX, MemberEventFunc(DSi_SDHost, FinishTX)); + DSi.RegisterEventFunc( Event_DSi_SDMMCTransfer, + Transfer_RX, MemberEventFunc(DSi_SDHost, FinishRX)); + + 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)); +} - DSi.RegisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer, +// 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(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer, + DSi.RegisterEventFunc(Event_DSi_SDIOTransfer, Transfer_RX, MemberEventFunc(DSi_SDHost, FinishRX)); - Ports[0] = nullptr; + 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) - { - DSi_MMCStorage* sd; - DSi_MMCStorage* mmc; +FATStorage* DSi_SDHost::GetSDCard() noexcept +{ + if (Num != 0) return nullptr; + return static_cast<DSi_MMCStorage*>(Ports[0].get())->GetSDCard(); +} - if (Platform::GetConfigBool(Platform::DSiSD_Enable)) +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) + { + 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()); } } } |