From 440b3566745bbf967210bd6c51e791e1df472ff2 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Fri, 3 Nov 2023 20:17:00 +0100 Subject: [PATCH] get this started: refactor SPI in OOP --- src/DSi.cpp | 11 +- src/DSi_I2C.cpp | 2 +- src/DSi_NAND.h | 2 +- src/DSi_NWifi.cpp | 16 +- src/DSi_SPI_TSC.cpp | 67 +- src/DSi_SPI_TSC.h | 33 +- src/NDS.cpp | 57 +- src/NDS.h | 4 + src/Platform.h | 7 +- src/SPI.cpp | 358 +++----- src/SPI.h | 159 +++- src/SPI_Firmware.cpp | 99 ++- src/SPI_Firmware.h | 796 +++++++++--------- src/Wifi.cpp | 13 +- src/frontend/qt_sdl/Platform.cpp | 16 +- .../PowerManagement/PowerManagementDialog.cpp | 12 +- src/frontend/qt_sdl/ROMManager.cpp | 49 +- 17 files changed, 855 insertions(+), 846 deletions(-) diff --git a/src/DSi.cpp b/src/DSi.cpp index 17bfb8ff..0a62db2d 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -403,6 +403,7 @@ void SetupDirectBoot() NDSHeader& header = NDSCart::Cart->GetHeader(); const u8* cartrom = NDSCart::Cart->GetROM(); u32 cartid = NDSCart::Cart->ID(); + DSi_TSC* tsc = (DSi_TSC*)NDS::SPI->GetTSC(); // TODO: add controls for forcing DS or DSi mode? if (!(header.UnitCode & 0x02)) @@ -429,7 +430,7 @@ void SetupDirectBoot() NDS::MapSharedWRAM(3); - DSi_SPI_TSC::SetMode(0x00); + tsc->SetMode(0x00); Set_SCFG_Clock9(0x0000); } else @@ -481,7 +482,7 @@ void SetupDirectBoot() NDS::MapSharedWRAM(mbk[11] >> 24); if (!(header.AppFlags & (1<<0))) - DSi_SPI_TSC::SetMode(0x00); + tsc->SetMode(0x00); } // setup main RAM data @@ -552,12 +553,12 @@ void SetupDirectBoot() } } - SPI_Firmware::WifiBoard nwifiver = SPI_Firmware::GetFirmware()->Header().WifiBoard; + Firmware::WifiBoard nwifiver = NDS::SPI->GetFirmware()->GetHeader().WifiBoard; ARM9Write8(0x020005E0, static_cast(nwifiver)); // TODO: these should be taken from the wifi firmware in NAND // but, hey, this works too. - if (nwifiver == SPI_Firmware::WifiBoard::W015) + if (nwifiver == Firmware::WifiBoard::W015) { ARM9Write16(0x020005E2, 0xB57E); ARM9Write32(0x020005E4, 0x00500400); @@ -642,7 +643,7 @@ void SetupDirectBoot() NDS::ARM7BIOSProt = 0x20; - SPI_Firmware::SetupDirectBoot(true); + NDS::SPI->GetFirmwareMem()->SetupDirectBoot(true); NDS::ARM9->CP15Write(0x100, 0x00056078); NDS::ARM9->CP15Write(0x200, 0x0000004A); diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp index c4ad50c5..26f3e4b8 100644 --- a/src/DSi_I2C.cpp +++ b/src/DSi_I2C.cpp @@ -144,7 +144,7 @@ u8 GetBatteryLevel() { return Registers[0x20] & 0xF; } void SetBatteryLevel(u8 batteryLevel) { Registers[0x20] = ((Registers[0x20] & 0xF0) | (batteryLevel & 0x0F)); - SPI_Powerman::SetBatteryLevelOkay(batteryLevel > batteryLevel_Low ? true : false); + //SPI_Powerman::SetBatteryLevelOkay(batteryLevel > batteryLevel_Low ? true : false); if (batteryLevel <= 1) { diff --git a/src/DSi_NAND.h b/src/DSi_NAND.h index 0077eacb..99a9ee7c 100644 --- a/src/DSi_NAND.h +++ b/src/DSi_NAND.h @@ -161,7 +161,7 @@ union DSiFirmwareSystemSettings u32 ConfigFlags; u8 Zero02; u8 CountryCode; - SPI_Firmware::Language Language; + Firmware::Language Language; u8 RTCYear; u32 RTCOffset; u8 Zero3[4]; diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp index 558cd6f7..d95def5a 100644 --- a/src/DSi_NWifi.cpp +++ b/src/DSi_NWifi.cpp @@ -145,7 +145,6 @@ DSi_NWifi::~DSi_NWifi() void DSi_NWifi::Reset() { - using namespace SPI_Firmware; TransferCmd = 0xFFFFFFFF; RemSize = 0; @@ -162,26 +161,28 @@ void DSi_NWifi::Reset() for (int i = 0; i < 9; i++) Mailbox[i].Clear(); - MacAddress mac = GetFirmware()->Header().MacAddress; + const Firmware* fw = NDS::SPI->GetFirmware(); + + MacAddress mac = fw->GetHeader().MacAddress; Log(LogLevel::Info, "NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - WifiBoard type = GetFirmware()->Header().WifiBoard; + Firmware::WifiBoard type = fw->GetHeader().WifiBoard; switch (type) { - case WifiBoard::W015: // AR6002 + case Firmware::WifiBoard::W015: // AR6002 ROMID = 0x20000188; ChipID = 0x02000001; HostIntAddr = 0x00500400; break; - case WifiBoard::W024: // AR6013 + case Firmware::WifiBoard::W024: // AR6013 ROMID = 0x23000024; ChipID = 0x0D000000; HostIntAddr = 0x00520000; break; - case WifiBoard::W028: // AR6014 (3DS) + case Firmware::WifiBoard::W028: // AR6014 (3DS) ROMID = 0x2300006F; ChipID = 0x0D000001; HostIntAddr = 0x00520000; @@ -893,9 +894,8 @@ void DSi_NWifi::HTC_Command() case 0x0004: // setup complete { - SPI_Firmware::MacAddress mac = SPI_Firmware::GetFirmware()->Header().MacAddress; u8 ready_evt[12]; - memcpy(&ready_evt[0], &mac, mac.size()); + memcpy(&ready_evt[0], &EEPROM[0xA], 6); // MAC address ready_evt[6] = 0x02; ready_evt[7] = 0; *(u32*)&ready_evt[8] = 0x2300006C; diff --git a/src/DSi_SPI_TSC.cpp b/src/DSi_SPI_TSC.cpp index c690f9c9..13044405 100644 --- a/src/DSi_SPI_TSC.cpp +++ b/src/DSi_SPI_TSC.cpp @@ -19,38 +19,25 @@ #include #include #include "DSi.h" -#include "SPI.h" #include "DSi_SPI_TSC.h" #include "Platform.h" using Platform::Log; using Platform::LogLevel; -namespace DSi_SPI_TSC -{ -u32 DataPos; -u8 Index; -u8 Bank; -u8 Data; - -u8 Bank3Regs[0x80]; -u8 TSCMode; - -u16 TouchX, TouchY; - - -bool Init() -{ - return true; -} - -void DeInit() +DSi_TSC::DSi_TSC(SPIHost* host) : TSC(host) { } -void Reset() +DSi_TSC::~DSi_TSC() { +} + +void DSi_TSC::Reset() +{ + TSC::Reset(); + DataPos = 0; Bank = 0; @@ -72,8 +59,10 @@ void Reset() TSCMode = 0x01; // DSi mode } -void DoSavestate(Savestate* file) +void DSi_TSC::DoSavestate(Savestate* file) { + TSC::DoSavestate(file); + file->Section("SPTi"); file->Var32(&DataPos); @@ -85,19 +74,14 @@ void DoSavestate(Savestate* file) file->Var8(&TSCMode); } -void SetMode(u8 mode) +void DSi_TSC::SetMode(u8 mode) { TSCMode = mode; } -void SetTouchCoords(u16 x, u16 y) +void DSi_TSC::SetTouchCoords(u16 x, u16 y) { - if (TSCMode == 0x00) - { - if (y == 0xFFF) NDS::KeyInput |= (1 << (16+6)); - else NDS::KeyInput &= ~(1 << (16+6)); - return SPI_TSC::SetTouchCoords(x, y); - } + if (TSCMode == 0x00) return TSC::SetTouchCoords(x, y); TouchX = x; TouchY = y; @@ -135,24 +119,17 @@ void SetTouchCoords(u16 x, u16 y) } } -void MicInputFrame(s16* data, int samples) +void DSi_TSC::MicInputFrame(s16* data, int samples) { - if (TSCMode == 0x00) return SPI_TSC::MicInputFrame(data, samples); + if (TSCMode == 0x00) return TSC::MicInputFrame(data, samples); // otherwise we don't handle mic input // TODO: handle it where it needs to be } -u8 Read() +void DSi_TSC::Write(u8 val) { - if (TSCMode == 0x00) return SPI_TSC::Read(); - - return Data; -} - -void Write(u8 val, u32 hold) -{ - if (TSCMode == 0x00) return SPI_TSC::Write(val, hold); + if (TSCMode == 0x00) return TSC::Write(val); #define READWRITE(var) { if (Index & 0x01) Data = var; else var = val; } @@ -233,8 +210,12 @@ void Write(u8 val, u32 hold) Index += (1<<1); // increment index } - if (hold) DataPos++; - else DataPos = 0; + DataPos++; } +void DSi_TSC::Release() +{ + if (TSCMode == 0x00) return TSC::Release(); + + DataPos = 0; } diff --git a/src/DSi_SPI_TSC.h b/src/DSi_SPI_TSC.h index 7a3acf43..c7b9bfe6 100644 --- a/src/DSi_SPI_TSC.h +++ b/src/DSi_SPI_TSC.h @@ -21,26 +21,33 @@ #include "types.h" #include "Savestate.h" +#include "SPI.h" -namespace DSi_SPI_TSC +class DSi_TSC : public TSC { +public: + DSi_TSC(SPIHost* host); + ~DSi_TSC() override; -extern u32 DataPos; + void Reset() override; -bool Init(); -void DeInit(); -void Reset(); -void DoSavestate(Savestate* file); + void DoSavestate(Savestate* file) override; -// 00=DS-mode 01=normal -void SetMode(u8 mode); + // 00=DS-mode 01=normal + void SetMode(u8 mode); -void SetTouchCoords(u16 x, u16 y); -void MicInputFrame(s16* data, int samples); + void SetTouchCoords(u16 x, u16 y) override; + void MicInputFrame(s16* data, int samples) override; -u8 Read(); -void Write(u8 val, u32 hold); + void Write(u8 val) override; + void Release() override; -} +private: + u8 Index; + u8 Bank; + + u8 Bank3Regs[0x80]; + u8 TSCMode; +}; #endif // DSI_SPI_TSC diff --git a/src/NDS.cpp b/src/NDS.cpp index 0efd0e99..9b9e1e71 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -178,6 +178,8 @@ u32 KeyInput; u16 KeyCnt[2]; u16 RCnt; +SPIHost* SPI; + bool Running; bool RunningGame; @@ -215,11 +217,12 @@ bool Init() DMAs[6] = new DMA(1, 2); DMAs[7] = new DMA(1, 3); + SPI = new SPIHost(); + if (!NDSCart::Init()) return false; if (!GBACart::Init()) return false; if (!GPU::Init()) return false; if (!SPU::Init()) return false; - if (!SPI::Init()) return false; if (!RTC::Init()) return false; if (!Wifi::Init()) return false; @@ -248,11 +251,13 @@ void DeInit() DMAs[i] = nullptr; } + delete SPI; + SPI = nullptr; + NDSCart::DeInit(); GBACart::DeInit(); GPU::DeInit(); SPU::DeInit(); - SPI::DeInit(); RTC::DeInit(); Wifi::DeInit(); @@ -389,7 +394,7 @@ bool NeedsDirectBoot() return true; // DSi/3DS firmwares aren't bootable - if (!SPI_Firmware::GetFirmware()->IsBootable()) + if (!SPI->GetFirmware()->IsBootable()) return true; return false; @@ -465,7 +470,7 @@ void SetupDirectBoot(const std::string& romname) ARM7BIOSProt = 0x1204; - SPI_Firmware::SetupDirectBoot(false); + SPI->GetFirmwareMem()->SetupDirectBoot(false); ARM9->CP15Write(0x100, 0x00012078); ARM9->CP15Write(0x200, 0x00000042); @@ -641,7 +646,7 @@ void Reset() GBACart::Reset(); GPU::Reset(); SPU::Reset(); - SPI::Reset(); + SPI->Reset(); RTC::Reset(); Wifi::Reset(); @@ -843,7 +848,7 @@ bool DoSavestate(Savestate* file) GBACart::DoSavestate(file); GPU::DoSavestate(file); SPU::DoSavestate(file); - SPI::DoSavestate(file); + SPI->DoSavestate(file); RTC::DoSavestate(file); Wifi::DoSavestate(file); @@ -1279,28 +1284,12 @@ void CancelEvent(u32 id) void TouchScreen(u16 x, u16 y) { - if (ConsoleType == 1) - { - DSi_SPI_TSC::SetTouchCoords(x, y); - } - else - { - SPI_TSC::SetTouchCoords(x, y); - KeyInput &= ~(1 << (16+6)); - } + SPI->GetTSC()->SetTouchCoords(x, y); } void ReleaseScreen() { - if (ConsoleType == 1) - { - DSi_SPI_TSC::SetTouchCoords(0x000, 0xFFF); - } - else - { - SPI_TSC::SetTouchCoords(0x000, 0xFFF); - KeyInput |= (1 << (16+6)); - } + SPI->GetTSC()->SetTouchCoords(0x000, 0xFFF); } @@ -1383,7 +1372,7 @@ void CamInputFrame(int cam, u32* data, int width, int height, bool rgb) void MicInputFrame(s16* data, int samples) { - return SPI_TSC::MicInputFrame(data, samples); + return SPI->GetTSC()->MicInputFrame(data, samples); } /*int ImportSRAM(u8* data, u32 length) @@ -3917,7 +3906,7 @@ u8 ARM7IORead8(u32 addr) return NDSCart::ROMCommand[7]; return 0; - case 0x040001C2: return SPI::ReadData(); + case 0x040001C2: return SPI->ReadData(); case 0x04000208: return IME[1]; @@ -4005,8 +3994,8 @@ u16 ARM7IORead16(u32 addr) (NDSCart::ROMCommand[7] << 8); return 0; - case 0x040001C0: return SPI::Cnt; - case 0x040001C2: return SPI::ReadData(); + case 0x040001C0: return SPI->ReadCnt(); + case 0x040001C2: return SPI->ReadData(); case 0x04000204: return ExMemCnt[1]; case 0x04000206: @@ -4088,7 +4077,7 @@ u32 ARM7IORead32(u32 addr) return 0; case 0x040001C0: - return SPI::Cnt | (SPI::ReadData() << 16); + return SPI->ReadCnt() | (SPI->ReadData() << 16); case 0x04000208: return IME[1]; case 0x04000210: return IE[1]; @@ -4181,7 +4170,7 @@ void ARM7IOWrite8(u32 addr, u8 val) case 0x040001AF: if (ExMemCnt[0] & (1<<11)) NDSCart::ROMCommand[7] = val; return; case 0x040001C2: - SPI::WriteData(val); + SPI->WriteData(val); return; case 0x04000208: IME[1] = val & 0x1; UpdateIRQ(1); return; @@ -4309,10 +4298,10 @@ void ARM7IOWrite16(u32 addr, u16 val) case 0x040001BA: ROMSeed1[12] = val & 0x7F; return; case 0x040001C0: - SPI::WriteCnt(val); + SPI->WriteCnt(val); return; case 0x040001C2: - SPI::WriteData(val & 0xFF); + SPI->WriteData(val & 0xFF); return; case 0x04000204: @@ -4462,8 +4451,8 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x040001B4: *(u32*)&ROMSeed1[8] = val; return; case 0x040001C0: - SPI::WriteCnt(val & 0xFFFF); - SPI::WriteData((val >> 16) & 0xFF); + SPI->WriteCnt(val & 0xFFFF); + SPI->WriteData((val >> 16) & 0xFF); return; case 0x04000208: IME[1] = val & 0x1; UpdateIRQ(1); return; diff --git a/src/NDS.h b/src/NDS.h index 89ebb1ce..b0126ed3 100644 --- a/src/NDS.h +++ b/src/NDS.h @@ -30,6 +30,8 @@ // with this enabled, to make sure it doesn't desync //#define DEBUG_CHECK_DESYNC +class SPIHost; + namespace NDS { @@ -246,6 +248,8 @@ extern MemRegion SWRAM_ARM7; extern u32 KeyInput; extern u16 RCnt; +extern SPIHost* SPI; + const u32 ARM7WRAMSize = 0x10000; extern u8* ARM7WRAM; diff --git a/src/Platform.h b/src/Platform.h index 144fce19..7fa8fbd7 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -24,10 +24,7 @@ #include #include -namespace SPI_Firmware -{ - class Firmware; -} +class Firmware; namespace Platform { @@ -335,7 +332,7 @@ void WriteGBASave(const u8* savedata, u32 savelen, u32 writeoffset, u32 writelen /// @param firmware The firmware that was just written. /// @param writeoffset The offset of the first byte that was written to firmware. /// @param writelen The number of bytes that were written to firmware. -void WriteFirmware(const SPI_Firmware::Firmware& firmware, u32 writeoffset, u32 writelen); +void WriteFirmware(const Firmware& firmware, u32 writeoffset, u32 writelen); // called when the RTC date/time is changed and the frontend might need to take it into account void WriteDateTime(int year, int month, int day, int hour, int minute, int second); diff --git a/src/SPI.cpp b/src/SPI.cpp index 1a4c12e5..8eb8b0e0 100644 --- a/src/SPI.cpp +++ b/src/SPI.cpp @@ -29,18 +29,6 @@ using namespace Platform; -namespace SPI_Firmware -{ - -std::unique_ptr Firmware; - -u32 Hold; -u8 CurCmd; -u32 DataPos; -u8 Data; - -u8 StatusReg; -u32 Addr; u16 CRC16(const u8* data, u32 len, u32 start) { @@ -65,7 +53,9 @@ u16 CRC16(const u8* data, u32 len, u32 start) return start & 0xFFFF; } -bool VerifyCRC16(u32 start, u32 offset, u32 len, u32 crcoffset) + + +bool FirmwareMem::VerifyCRC16(u32 start, u32 offset, u32 len, u32 crcoffset) { u16 crc_stored = *(u16*)&Firmware->Buffer()[crcoffset]; u16 crc_calced = CRC16(&Firmware->Buffer()[offset], len, start); @@ -73,40 +63,16 @@ bool VerifyCRC16(u32 start, u32 offset, u32 len, u32 crcoffset) } -bool Init() +FirmwareMem::FirmwareMem(SPIHost* host) : SPIDevice(host) { - return true; } -void DeInit() +FirmwareMem::~FirmwareMem() { RemoveFirmware(); } -u32 FixFirmwareLength(u32 originalLength) -{ - if (originalLength != 0x20000 && originalLength != 0x40000 && originalLength != 0x80000) - { - Log(LogLevel::Warn, "Bad firmware size %d, ", originalLength); - - // pick the nearest power-of-two length - originalLength |= (originalLength >> 1); - originalLength |= (originalLength >> 2); - originalLength |= (originalLength >> 4); - originalLength |= (originalLength >> 8); - originalLength |= (originalLength >> 16); - originalLength++; - - // ensure it's a sane length - if (originalLength > 0x80000) originalLength = 0x80000; - else if (originalLength < 0x20000) originalLength = 0x20000; - - Log(LogLevel::Debug, "assuming %d\n", originalLength); - } - return originalLength; -} - -void Reset() +void FirmwareMem::Reset() { if (!Firmware) { @@ -115,7 +81,7 @@ void Reset() } // fix touchscreen coords - for (UserData& u : Firmware->UserData()) + for (auto& u : Firmware->GetUserData()) { u.TouchCalibrationADC1[0] = 0; u.TouchCalibrationADC1[1] = 0; @@ -132,7 +98,7 @@ void Reset() // disable autoboot //Firmware[userdata+0x64] &= 0xBF; - MacAddress mac = Firmware->Header().MacAddress; + MacAddress mac = Firmware->GetHeader().MacAddress; Log(LogLevel::Info, "MAC: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); // verify shit @@ -150,14 +116,14 @@ void Reset() StatusReg = 0x00; } -void DoSavestate(Savestate* file) +void FirmwareMem::DoSavestate(Savestate* file) { file->Section("SPFW"); // CHECKME/TODO: trust the firmware to stay the same????? // embedding the whole firmware in the savestate would be derpo tho?? - file->Var32(&Hold); + file->Bool32(&Hold); file->Var8(&CurCmd); file->Var32(&DataPos); file->Var8(&Data); @@ -166,10 +132,10 @@ void DoSavestate(Savestate* file) file->Var32(&Addr); } -void SetupDirectBoot(bool dsi) +void FirmwareMem::SetupDirectBoot(bool dsi) { - const FirmwareHeader& header = Firmware->Header(); - const UserData& userdata = Firmware->EffectiveUserData(); + const auto& header = Firmware->GetHeader(); + const auto& userdata = Firmware->GetEffectiveUserData(); if (dsi) { for (u32 i = 0; i < 6; i += 2) @@ -194,17 +160,17 @@ void SetupDirectBoot(bool dsi) } } -const class Firmware* GetFirmware() +const class Firmware* FirmwareMem::GetFirmware() { return Firmware.get(); } -bool IsLoadedFirmwareBuiltIn() +bool FirmwareMem::IsLoadedFirmwareBuiltIn() { - return Firmware->Header().Identifier == GENERATED_FIRMWARE_IDENTIFIER; + return Firmware->GetHeader().Identifier == GENERATED_FIRMWARE_IDENTIFIER; } -bool InstallFirmware(class Firmware&& firmware) +bool FirmwareMem::InstallFirmware(class Firmware&& firmware) { if (!firmware.Buffer()) { @@ -214,13 +180,13 @@ bool InstallFirmware(class Firmware&& firmware) Firmware = std::make_unique(std::move(firmware)); - FirmwareIdentifier id = Firmware->Header().Identifier; + FirmwareIdentifier id = Firmware->GetHeader().Identifier; Log(LogLevel::Debug, "Installed firmware (Identifier: %c%c%c%c)\n", id[0], id[1], id[2], id[3]); return true; } -bool InstallFirmware(std::unique_ptr&& firmware) +bool FirmwareMem::InstallFirmware(std::unique_ptr&& firmware) { if (!firmware) { @@ -236,40 +202,42 @@ bool InstallFirmware(std::unique_ptr&& firmware) Firmware = std::move(firmware); - FirmwareIdentifier id = Firmware->Header().Identifier; + FirmwareIdentifier id = Firmware->GetHeader().Identifier; Log(LogLevel::Debug, "Installed firmware (Identifier: %c%c%c%c)\n", id[0], id[1], id[2], id[3]); return true; } -void RemoveFirmware() +void FirmwareMem::RemoveFirmware() { Firmware.reset(); Log(LogLevel::Debug, "Removed installed firmware (if any)\n"); } -u8 Read() +void FirmwareMem::Write(u8 val) { - return Data; -} - -void Write(u8 val, u32 hold) -{ - if (!hold) - { - if (!Hold) // commands with no paramters - CurCmd = val; - - Hold = 0; - } - - if (hold && (!Hold)) + if (!Hold) { CurCmd = val; - Hold = 1; + Hold = true; Data = 0; DataPos = 1; Addr = 0; + + // handle commands with no parameters + switch (CurCmd) + { + case 0x04: // write disable + StatusReg &= ~(1<<1); + Data = 0; + break; + + case 0x06: // write enable + StatusReg |= (1<<1); + Data = 0; + break; + } + return; } @@ -293,20 +261,10 @@ void Write(u8 val, u32 hold) } break; - case 0x04: // write disable - StatusReg &= ~(1<<1); - Data = 0; - break; - case 0x05: // read status reg Data = StatusReg; break; - case 0x06: // write enable - StatusReg |= (1<<1); - Data = 0; - break; - case 0x0A: // write { // TODO: what happens if you write too many bytes? (max 256, they say) @@ -345,45 +303,38 @@ void Write(u8 val, u32 hold) Data = 0xFF; break; } +} - if (!hold && (CurCmd == 0x02 || CurCmd == 0x0A)) +void FirmwareMem::Release() +{ + if (CurCmd == 0x02 || CurCmd == 0x0A) { // If the SPI firmware chip just finished a write... // We only notify the frontend of changes to the Wi-fi/userdata settings region // (although it might still decide to flush the whole thing) - u32 wifioffset = Firmware->WifiAccessPointOffset(); + u32 wifioffset = Firmware->GetWifiAccessPointOffset(); // Request that the start of the Wi-fi/userdata settings region // through the end of the firmware blob be flushed to disk Platform::WriteFirmware(*Firmware, wifioffset, Firmware->Length() - wifioffset); } + + SPIDevice::Release(); + CurCmd = 0; } -} - -namespace SPI_Powerman -{ - -u32 Hold; -u32 DataPos; -u8 Index; -u8 Data; - -u8 Registers[8]; -u8 RegMasks[8]; -bool Init() -{ - return true; -} - -void DeInit() +PowerMan::PowerMan(SPIHost* host) : SPIDevice(host) { } -void Reset() +PowerMan::~PowerMan() { - Hold = 0; +} + +void PowerMan::Reset() +{ + Hold = false; Index = 0; Data = 0; @@ -399,14 +350,11 @@ void Reset() RegMasks[4] = 0x0F; } -bool GetBatteryLevelOkay() { return !Registers[1]; } -void SetBatteryLevelOkay(bool okay) { Registers[1] = okay ? 0x00 : 0x01; } - -void DoSavestate(Savestate* file) +void PowerMan::DoSavestate(Savestate* file) { file->Section("SPPW"); - file->Var32(&Hold); + file->Bool32(&Hold); file->Var32(&DataPos); file->Var8(&Index); file->Var8(&Data); @@ -415,22 +363,15 @@ void DoSavestate(Savestate* file) file->VarArray(RegMasks, 8); // is that needed?? } -u8 Read() -{ - return Data; -} +bool PowerMan::GetBatteryLevelOkay() { return !Registers[1]; } +void PowerMan::SetBatteryLevelOkay(bool okay) { Registers[1] = okay ? 0x00 : 0x01; } -void Write(u8 val, u32 hold) +void PowerMan::Write(u8 val) { - if (!hold) - { - Hold = 0; - } - - if (hold && (!Hold)) + if (!Hold) { Index = val; - Hold = 1; + Hold = true; Data = 0; DataPos = 1; return; @@ -465,35 +406,19 @@ void Write(u8 val, u32 hold) Data = 0; } -} -namespace SPI_TSC -{ - -u32 DataPos; -u8 ControlByte; -u8 Data; - -u16 ConvResult; - -u16 TouchX, TouchY; - -s16 MicBuffer[1024]; -int MicBufferLen; - - -bool Init() -{ - return true; -} - -void DeInit() +TSC::TSC(SPIHost* host) : SPIDevice(host) { } -void Reset() +TSC::~TSC() { +} + +void TSC::Reset() +{ + Hold = false; ControlByte = 0; Data = 0; @@ -502,7 +427,7 @@ void Reset() MicBufferLen = 0; } -void DoSavestate(Savestate* file) +void TSC::DoSavestate(Savestate* file) { file->Section("SPTS"); @@ -513,7 +438,7 @@ void DoSavestate(Savestate* file) file->Var16(&ConvResult); } -void SetTouchCoords(u16 x, u16 y) +void TSC::SetTouchCoords(u16 x, u16 y) { // scr.x = (adc.x-adc.x1) * (scr.x2-scr.x1) / (adc.x2-adc.x1) + (scr.x1-1) // scr.y = (adc.y-adc.y1) * (scr.y2-scr.y1) / (adc.y2-adc.y1) + (scr.y1-1) @@ -522,13 +447,19 @@ void SetTouchCoords(u16 x, u16 y) TouchX = x; TouchY = y; - if (y == 0xFFF) return; + if (y == 0xFFF) + { + // released + NDS::KeyInput |= (1 << (16+6)); + return; + } TouchX <<= 4; TouchY <<= 4; + NDS::KeyInput &= ~(1 << (16+6)); } -void MicInputFrame(s16* data, int samples) +void TSC::MicInputFrame(s16* data, int samples) { if (!data) { @@ -541,12 +472,7 @@ void MicInputFrame(s16* data, int samples) MicBufferLen = samples; } -u8 Read() -{ - return Data; -} - -void Write(u8 val, u32 hold) +void TSC::Write(u8 val) { if (DataPos == 1) Data = (ConvResult >> 5) & 0xFF; @@ -599,79 +525,71 @@ void Write(u8 val, u32 hold) DataPos++; } + + +SPIHost::SPIHost() +{ + NDS::RegisterEventFunc(NDS::Event_SPITransfer, 0, MemberEventFunc(SPIHost, TransferDone)); + + Devices[SPIDevice_FirmwareMem] = new FirmwareMem(this); + Devices[SPIDevice_PowerMan] = new PowerMan(this); + Devices[SPIDevice_TSC] = nullptr; } - -namespace SPI +SPIHost::~SPIHost() { + for (int i = 0; i < SPIDevice_MAX; i++) + { + if (Devices[i]) + delete Devices[i]; -u16 Cnt; - -u32 CurDevice; // remove me - - -bool Init() -{ - NDS::RegisterEventFunc(NDS::Event_SPITransfer, 0, TransferDone); - - if (!SPI_Firmware::Init()) return false; - if (!SPI_Powerman::Init()) return false; - if (!SPI_TSC::Init()) return false; - if (!DSi_SPI_TSC::Init()) return false; - - return true; -} - -void DeInit() -{ - SPI_Firmware::DeInit(); - SPI_Powerman::DeInit(); - SPI_TSC::DeInit(); - DSi_SPI_TSC::DeInit(); + Devices[i] = nullptr; + } NDS::UnregisterEventFunc(NDS::Event_SPITransfer, 0); } -void Reset() +void SPIHost::Reset() { Cnt = 0; - SPI_Firmware::Reset(); - SPI_Powerman::Reset(); - SPI_TSC::Reset(); - if (NDS::ConsoleType == 1) DSi_SPI_TSC::Reset(); + if (Devices[SPIDevice_TSC]) + delete Devices[SPIDevice_TSC]; + + if (NDS::ConsoleType == 1) + Devices[SPIDevice_TSC] = new DSi_TSC(this); + else + Devices[SPIDevice_TSC] = new TSC(this); + + for (int i = 0; i < SPIDevice_MAX; i++) + { + Devices[i]->Reset(); + } } -void DoSavestate(Savestate* file) +void SPIHost::DoSavestate(Savestate* file) { file->Section("SPIG"); file->Var16(&Cnt); - file->Var32(&CurDevice); - SPI_Firmware::DoSavestate(file); - SPI_Powerman::DoSavestate(file); - SPI_TSC::DoSavestate(file); - if (NDS::ConsoleType == 1) DSi_SPI_TSC::DoSavestate(file); + for (int i = 0; i < SPIDevice_MAX; i++) + { + Devices[i]->DoSavestate(file); + } } -void WriteCnt(u16 val) +void SPIHost::WriteCnt(u16 val) { // turning it off should clear chipselect // TODO: confirm on hardware. libnds expects this, though. if ((Cnt & (1<<15)) && !(val & (1<<15))) { - switch (Cnt & 0x0300) + int dev = (Cnt >> 8) & 0x3; + if (dev < SPIDevice_MAX) { - case 0x0000: SPI_Powerman::Hold = 0; break; - case 0x0100: SPI_Firmware::Hold = 0; break; - case 0x0200: - if (NDS::ConsoleType == 1) - DSi_SPI_TSC::DataPos = 0; - else - SPI_TSC::DataPos = 0; - break; + Devices[dev]->Release(); } } @@ -682,7 +600,7 @@ void WriteCnt(u16 val) if (Cnt & (1<<7)) Log(LogLevel::Warn, "!! CHANGING SPICNT DURING TRANSFER: %04X\n", val); } -void TransferDone(u32 param) +void SPIHost::TransferDone(u32 param) { Cnt &= ~(1<<7); @@ -690,46 +608,40 @@ void TransferDone(u32 param) NDS::SetIRQ(1, NDS::IRQ_SPI); } -u8 ReadData() +u8 SPIHost::ReadData() { if (!(Cnt & (1<<15))) return 0; if (Cnt & (1<<7)) return 0; // checkme - switch (Cnt & 0x0300) + int dev = (Cnt >> 8) & 0x3; + if (dev < SPIDevice_MAX) { - case 0x0000: return SPI_Powerman::Read(); - case 0x0100: return SPI_Firmware::Read(); - case 0x0200: - if (NDS::ConsoleType == 1) - return DSi_SPI_TSC::Read(); - else - return SPI_TSC::Read(); - default: return 0; + return Devices[dev]->Read(); } + + return 0; } -void WriteData(u8 val) +void SPIHost::WriteData(u8 val) { if (!(Cnt & (1<<15))) return; if (Cnt & (1<<7)) return; Cnt |= (1<<7); - switch (Cnt & 0x0300) + + int dev = (Cnt >> 8) & 0x3; + if (dev < SPIDevice_MAX) { - case 0x0000: SPI_Powerman::Write(val, Cnt&(1<<11)); break; - case 0x0100: SPI_Firmware::Write(val, Cnt&(1<<11)); break; - case 0x0200: - if (NDS::ConsoleType == 1) - DSi_SPI_TSC::Write(val, Cnt&(1<<11)); - else - SPI_TSC::Write(val, Cnt&(1<<11)); - break; - default: Log(LogLevel::Warn, "SPI to unknown device %04X %02X\n", Cnt, val); break; + Devices[dev]->Write(val); + if (!(Cnt & (1<<11))) // release chipselect + Devices[dev]->Release(); + } + else + { + Log(LogLevel::Warn, "SPI to unknown device %04X %02X\n", Cnt, val); } // SPI transfers one bit per cycle -> 8 cycles per byte u32 delay = 8 * (8 << (Cnt & 0x3)); NDS::ScheduleEvent(NDS::Event_SPITransfer, false, delay, 0, 0); } - -} diff --git a/src/SPI.h b/src/SPI.h index d8152038..4578ad5f 100644 --- a/src/SPI.h +++ b/src/SPI.h @@ -28,61 +28,150 @@ #include "Savestate.h" #include "SPI_Firmware.h" -namespace SPI_Firmware +enum { + SPIDevice_PowerMan = 0, + SPIDevice_FirmwareMem, + SPIDevice_TSC, + + SPIDevice_MAX +}; u16 CRC16(const u8* data, u32 len, u32 start); -void SetupDirectBoot(bool dsi); -u32 FixFirmwareLength(u32 originalLength); +class SPIHost; -/// @return A pointer to the installed firmware blob if one exists, otherwise \c nullptr. -/// @warning The pointer refers to memory that melonDS owns. Do not deallocate it yourself. -/// @see InstallFirmware -const Firmware* GetFirmware(); - -bool IsLoadedFirmwareBuiltIn(); -bool InstallFirmware(Firmware&& firmware); -bool InstallFirmware(std::unique_ptr&& firmware); -void RemoveFirmware(); -} - -namespace SPI_Powerman +class SPIDevice { +public: + SPIDevice(SPIHost* host) : Host(host), Hold(false), DataPos(0) {} + virtual ~SPIDevice() {} -bool GetBatteryLevelOkay(); -void SetBatteryLevelOkay(bool okay); + virtual void Reset() = 0; -} + virtual void DoSavestate(Savestate* file) = 0; -namespace SPI_TSC + virtual u8 Read() { return Data; } + virtual void Write(u8 val) = 0; + virtual void Release() { Hold = false; DataPos = 0; } + +protected: + SPIHost* Host; + + bool Hold; + u32 DataPos; + u8 Data; +}; + +class FirmwareMem : public SPIDevice { +public: + FirmwareMem(SPIHost* host); + ~FirmwareMem() override; -void SetTouchCoords(u16 x, u16 y); -void MicInputFrame(s16* data, int samples); + void Reset() override; -u8 Read(); -void Write(u8 val, u32 hold); + void DoSavestate(Savestate* file) override; -} + void SetupDirectBoot(bool dsi); -namespace SPI + const class Firmware* GetFirmware(); + bool IsLoadedFirmwareBuiltIn(); + bool InstallFirmware(class Firmware&& firmware); + bool InstallFirmware(std::unique_ptr&& firmware); + void RemoveFirmware(); + + void Write(u8 val) override; + void Release() override; + +private: + std::unique_ptr Firmware; + + u8 CurCmd; + + u8 StatusReg; + u32 Addr; + + bool VerifyCRC16(u32 start, u32 offset, u32 len, u32 crcoffset); +}; + +class PowerMan : public SPIDevice { +public: + PowerMan(SPIHost* host); + ~PowerMan() override; -extern u16 Cnt; + void Reset() override; -bool Init(); -void DeInit(); -void Reset(); -void DoSavestate(Savestate* file); + void DoSavestate(Savestate* file) override; -void WriteCnt(u16 val); + bool GetBatteryLevelOkay(); + void SetBatteryLevelOkay(bool okay); -u8 ReadData(); -void WriteData(u8 val); + void Write(u8 val) override; -void TransferDone(u32 param); +private: + u8 Index; -} + u8 Registers[8]; + u8 RegMasks[8]; +}; + +class TSC : public SPIDevice +{ +public: + TSC(SPIHost* host); + virtual ~TSC() override; + + virtual void Reset() override; + + virtual void DoSavestate(Savestate* file) override; + + virtual void SetTouchCoords(u16 x, u16 y); + virtual void MicInputFrame(s16* data, int samples); + + virtual void Write(u8 val) override; + +protected: + u8 ControlByte; + + u16 ConvResult; + + u16 TouchX, TouchY; + + s16 MicBuffer[1024]; + int MicBufferLen; +}; + + +class SPIHost +{ +public: + SPIHost(); + ~SPIHost(); + + void Reset(); + + void DoSavestate(Savestate* file); + + FirmwareMem* GetFirmwareMem() { return (FirmwareMem*)Devices[SPIDevice_FirmwareMem]; } + PowerMan* GetPowerMan() { return (PowerMan*)Devices[SPIDevice_PowerMan]; } + TSC* GetTSC() { return (TSC*)Devices[SPIDevice_TSC]; } + + const Firmware* GetFirmware() { return GetFirmwareMem()->GetFirmware(); } + + u16 ReadCnt() { return Cnt; } + void WriteCnt(u16 val); + + u8 ReadData(); + void WriteData(u8 val); + + void TransferDone(u32 param); + +private: + u16 Cnt; + + SPIDevice* Devices[3]; +}; #endif diff --git a/src/SPI_Firmware.cpp b/src/SPI_Firmware.cpp index 44fbfe7d..943a0b32 100644 --- a/src/SPI_Firmware.cpp +++ b/src/SPI_Firmware.cpp @@ -18,6 +18,10 @@ #include "SPI_Firmware.h" #include "SPI.h" +#include "Platform.h" + +using Platform::Log; +using Platform::LogLevel; #include @@ -49,7 +53,7 @@ constexpr u8 CHANDATA[0x3C] constexpr u8 DEFAULT_UNUSED3[6] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 }; -SPI_Firmware::WifiAccessPoint::WifiAccessPoint() +Firmware::WifiAccessPoint::WifiAccessPoint() { memset(Bytes, 0, sizeof(Bytes)); Status = AccessPointStatus::NotConfigured; @@ -57,7 +61,7 @@ SPI_Firmware::WifiAccessPoint::WifiAccessPoint() UpdateChecksum(); } -SPI_Firmware::WifiAccessPoint::WifiAccessPoint(int consoletype) +Firmware::WifiAccessPoint::WifiAccessPoint(int consoletype) { memset(Bytes, 0, sizeof(Bytes)); strncpy(SSID, DEFAULT_SSID, sizeof(SSID)); @@ -67,25 +71,25 @@ SPI_Firmware::WifiAccessPoint::WifiAccessPoint(int consoletype) UpdateChecksum(); } -void SPI_Firmware::WifiAccessPoint::UpdateChecksum() +void Firmware::WifiAccessPoint::UpdateChecksum() { Checksum = CRC16(Bytes, 0xFE, 0x0000); } -SPI_Firmware::ExtendedWifiAccessPoint::ExtendedWifiAccessPoint() +Firmware::ExtendedWifiAccessPoint::ExtendedWifiAccessPoint() { Data.Base = WifiAccessPoint(); UpdateChecksum(); } -void SPI_Firmware::ExtendedWifiAccessPoint::UpdateChecksum() +void Firmware::ExtendedWifiAccessPoint::UpdateChecksum() { Data.Base.UpdateChecksum(); Data.ExtendedChecksum = CRC16(&Bytes[0x100], 0xFE, 0x0000); } -SPI_Firmware::FirmwareHeader::FirmwareHeader(int consoletype) +Firmware::FirmwareHeader::FirmwareHeader(int consoletype) { if (consoletype == 1) { @@ -143,12 +147,12 @@ SPI_Firmware::FirmwareHeader::FirmwareHeader(int consoletype) } -void SPI_Firmware::FirmwareHeader::UpdateChecksum() +void Firmware::FirmwareHeader::UpdateChecksum() { - WifiConfigChecksum = SPI_Firmware::CRC16(&Bytes[0x2C], WifiConfigLength, 0x0000); + WifiConfigChecksum = CRC16(&Bytes[0x2C], WifiConfigLength, 0x0000); } -SPI_Firmware::UserData::UserData() +Firmware::UserData::UserData() { memset(Bytes, 0, 0x74); Version = 5; @@ -160,7 +164,7 @@ SPI_Firmware::UserData::UserData() Checksum = CRC16(Bytes, 0x70, 0xFFFF); } -void SPI_Firmware::UserData::UpdateChecksum() +void Firmware::UserData::UpdateChecksum() { Checksum = CRC16(Bytes, 0x70, 0xFFFF); if (ExtendedSettings.Unknown0 == 0x01) @@ -169,7 +173,30 @@ void SPI_Firmware::UserData::UpdateChecksum() } } -SPI_Firmware::Firmware::Firmware(int consoletype) +u32 Firmware::FixFirmwareLength(u32 originalLength) +{ + if (originalLength != 0x20000 && originalLength != 0x40000 && originalLength != 0x80000) + { + Log(LogLevel::Warn, "Bad firmware size %d, ", originalLength); + + // pick the nearest power-of-two length + originalLength |= (originalLength >> 1); + originalLength |= (originalLength >> 2); + originalLength |= (originalLength >> 4); + originalLength |= (originalLength >> 8); + originalLength |= (originalLength >> 16); + originalLength++; + + // ensure it's a sane length + if (originalLength > 0x80000) originalLength = 0x80000; + else if (originalLength < 0x20000) originalLength = 0x20000; + + Log(LogLevel::Debug, "assuming %d\n", originalLength); + } + return originalLength; +} + +Firmware::Firmware(int consoletype) { FirmwareBufferLength = DEFAULT_FIRMWARE_LENGTH; FirmwareBuffer = new u8[FirmwareBufferLength]; @@ -184,16 +211,16 @@ SPI_Firmware::Firmware::Firmware(int consoletype) // user data header.UserSettingsOffset = (0x7FE00 & FirmwareMask) >> 3; - std::array& settings = *reinterpret_cast*>(UserDataPosition()); + std::array& settings = *reinterpret_cast*>(GetUserDataPosition()); settings = { - SPI_Firmware::UserData(), - SPI_Firmware::UserData(), + UserData(), + UserData(), }; // wifi access points // TODO: WFC ID?? - std::array& accesspoints = *reinterpret_cast*>(WifiAccessPointPosition()); + std::array& accesspoints = *reinterpret_cast*>(GetWifiAccessPointPosition()); accesspoints = { WifiAccessPoint(consoletype), @@ -203,7 +230,7 @@ SPI_Firmware::Firmware::Firmware(int consoletype) if (consoletype == 1) { - std::array& extendedaccesspoints = *reinterpret_cast*>(ExtendedAccessPointPosition()); + std::array& extendedaccesspoints = *reinterpret_cast*>(GetExtendedAccessPointPosition()); extendedaccesspoints = { ExtendedWifiAccessPoint(), @@ -213,7 +240,7 @@ SPI_Firmware::Firmware::Firmware(int consoletype) } } -SPI_Firmware::Firmware::Firmware(Platform::FileHandle* file) : FirmwareBuffer(nullptr), FirmwareBufferLength(0), FirmwareMask(0) +Firmware::Firmware(Platform::FileHandle* file) : FirmwareBuffer(nullptr), FirmwareBufferLength(0), FirmwareMask(0) { if (file) { @@ -239,7 +266,7 @@ SPI_Firmware::Firmware::Firmware(Platform::FileHandle* file) : FirmwareBuffer(nu } } -SPI_Firmware::Firmware::Firmware(const u8* data, u32 length) : FirmwareBuffer(nullptr), FirmwareBufferLength(FixFirmwareLength(length)) +Firmware::Firmware(const u8* data, u32 length) : FirmwareBuffer(nullptr), FirmwareBufferLength(FixFirmwareLength(length)) { if (data) { @@ -249,14 +276,14 @@ SPI_Firmware::Firmware::Firmware(const u8* data, u32 length) : FirmwareBuffer(nu } } -SPI_Firmware::Firmware::Firmware(const Firmware& other) : FirmwareBuffer(nullptr), FirmwareBufferLength(other.FirmwareBufferLength) +Firmware::Firmware(const Firmware& other) : FirmwareBuffer(nullptr), FirmwareBufferLength(other.FirmwareBufferLength) { FirmwareBuffer = new u8[FirmwareBufferLength]; memcpy(FirmwareBuffer, other.FirmwareBuffer, FirmwareBufferLength); FirmwareMask = other.FirmwareMask; } -SPI_Firmware::Firmware::Firmware(Firmware&& other) noexcept +Firmware::Firmware(Firmware&& other) noexcept { FirmwareBuffer = other.FirmwareBuffer; FirmwareBufferLength = other.FirmwareBufferLength; @@ -266,7 +293,7 @@ SPI_Firmware::Firmware::Firmware(Firmware&& other) noexcept other.FirmwareMask = 0; } -SPI_Firmware::Firmware& SPI_Firmware::Firmware::operator=(const Firmware& other) +Firmware& Firmware::operator=(const Firmware& other) { if (this != &other) { @@ -280,7 +307,7 @@ SPI_Firmware::Firmware& SPI_Firmware::Firmware::operator=(const Firmware& other) return *this; } -SPI_Firmware::Firmware& SPI_Firmware::Firmware::operator=(Firmware&& other) noexcept +Firmware& Firmware::operator=(Firmware&& other) noexcept { if (this != &other) { @@ -296,21 +323,21 @@ SPI_Firmware::Firmware& SPI_Firmware::Firmware::operator=(Firmware&& other) noex return *this; } -SPI_Firmware::Firmware::~Firmware() +Firmware::~Firmware() { delete[] FirmwareBuffer; } -bool SPI_Firmware::Firmware::IsBootable() const +bool Firmware::IsBootable() const { return FirmwareBufferLength != DEFAULT_FIRMWARE_LENGTH && - Header().Identifier != GENERATED_FIRMWARE_IDENTIFIER + GetHeader().Identifier != GENERATED_FIRMWARE_IDENTIFIER ; } -const SPI_Firmware::UserData& SPI_Firmware::Firmware::EffectiveUserData() const { - const std::array& userdata = UserData(); +const Firmware::UserData& Firmware::GetEffectiveUserData() const { + const std::array& userdata = GetUserData(); bool userdata0ChecksumOk = userdata[0].ChecksumValid(); bool userdata1ChecksumOk = userdata[1].ChecksumValid(); @@ -332,8 +359,8 @@ const SPI_Firmware::UserData& SPI_Firmware::Firmware::EffectiveUserData() const } } -SPI_Firmware::UserData& SPI_Firmware::Firmware::EffectiveUserData() { - std::array& userdata = UserData(); +Firmware::UserData& Firmware::GetEffectiveUserData() { + std::array& userdata = GetUserData(); bool userdata0ChecksumOk = userdata[0].ChecksumValid(); bool userdata1ChecksumOk = userdata[1].ChecksumValid(); @@ -355,25 +382,25 @@ SPI_Firmware::UserData& SPI_Firmware::Firmware::EffectiveUserData() { } } -void SPI_Firmware::Firmware::UpdateChecksums() +void Firmware::UpdateChecksums() { - Header().UpdateChecksum(); + GetHeader().UpdateChecksum(); - for (SPI_Firmware::WifiAccessPoint& ap : AccessPoints()) + for (auto& ap : GetAccessPoints()) { ap.UpdateChecksum(); } - if (Header().ConsoleType == FirmwareConsoleType::DSi) + if (GetHeader().ConsoleType == FirmwareConsoleType::DSi) { - for (SPI_Firmware::ExtendedWifiAccessPoint& eap : ExtendedAccessPoints()) + for (auto& eap : GetExtendedAccessPoints()) { eap.UpdateChecksum(); } } - for (SPI_Firmware::UserData& u : UserData()) + for (auto& u : GetUserData()) { u.UpdateChecksum(); } -} \ No newline at end of file +} diff --git a/src/SPI_Firmware.h b/src/SPI_Firmware.h index 85576047..ad66a0a4 100644 --- a/src/SPI_Firmware.h +++ b/src/SPI_Firmware.h @@ -24,10 +24,10 @@ #include "types.h" #include "Platform.h" -namespace SPI_Firmware -{ - u16 CRC16(const u8* data, u32 len, u32 start); + + + using MacAddress = std::array; using IpAddress = std::array; @@ -44,382 +44,384 @@ constexpr const char* const DEFAULT_SSID = "melonAP"; */ constexpr int EXTENDED_WIFI_SETTINGS_OFFSET = -0xA00; -enum class WepMode : u8 -{ - None = 0, - Hex5 = 1, - Hex13 = 2, - Hex16 = 3, - Ascii5 = 5, - Ascii13 = 6, - Ascii16 = 7, -}; - -enum class WpaMode : u8 -{ - Normal = 0, - WPA_WPA2 = 0x10, - WPS_WPA = 0x13, - Unused = 0xff, -}; - -enum class WpaSecurity : u8 -{ - None = 0, - WPA_TKIP = 4, - WPA2_TKIP = 5, - WPA_AES = 6, - WPA2_AES = 7, -}; - -enum class AccessPointStatus : u8 -{ - Normal = 0, - Aoss = 1, - NotConfigured = 0xff -}; - -/** - * @see https://problemkaputt.de/gbatek.htm#dsfirmwarewifiinternetaccesspoints - */ -union WifiAccessPoint -{ - /** - * Constructs an unconfigured access point. - */ - WifiAccessPoint(); - - /** - * Constructs an access point configured with melonDS's defaults. - */ - explicit WifiAccessPoint(int consoletype); - void UpdateChecksum(); - u8 Bytes[256]; - struct - { - char ProxyUsername[32]; - char ProxyPassword[32]; - char SSID[32]; - char SSIDWEP64[32]; - u8 WEPKey1[16]; - u8 WEPKey2[16]; - u8 WEPKey3[16]; - u8 WEPKey4[16]; - IpAddress Address; - IpAddress Gateway; - IpAddress PrimaryDns; - IpAddress SecondaryDns; - u8 SubnetMask; - u8 Unknown0[21]; - enum WepMode WepMode; - AccessPointStatus Status; - u8 SSIDLength; - u8 Unknown1; - u16 Mtu; - u8 Unknown2[3]; - u8 ConnectionConfigured; - u8 NintendoWFCID[6]; - u8 Unknown3[8]; - u16 Checksum; - }; -}; - -static_assert(sizeof(WifiAccessPoint) == 256, "WifiAccessPoint should be 256 bytes"); - -union ExtendedWifiAccessPoint -{ - ExtendedWifiAccessPoint(); - void UpdateChecksum(); - u8 Bytes[512]; - struct - { - WifiAccessPoint Base; - - // DSi-specific entries now - u8 PrecomputedPSK[32]; - char WPAPassword[64]; - char Unused0[33]; - WpaSecurity Security; - bool ProxyEnabled; - bool ProxyAuthentication; - char ProxyName[48]; - u8 Unused1[52]; - u16 ProxyPort; - u8 Unused2[20]; - u16 ExtendedChecksum; - } Data; -}; - -static_assert(sizeof(ExtendedWifiAccessPoint) == 512, "WifiAccessPoint should be 512 bytes"); - - -enum class FirmwareConsoleType : u8 -{ - DS = 0xFF, - DSLite = 0x20, - DSi = 0x57, - iQueDS = 0x43, - iQueDSLite = 0x63, -}; - -enum class WifiVersion : u8 -{ - V1_4 = 0, - V5 = 3, - V6_7 = 5, - W006 = 6, - W015 = 15, - W024 = 24, - N3DS = 34, -}; - -enum RFChipType : u8 -{ - Type2 = 0x2, - Type3 = 0x3, -}; - -enum class WifiBoard : u8 -{ - W015 = 0x1, - W024 = 0x2, - W028 = 0x3, - Unused = 0xff, -}; - -enum Language : u8 -{ - Japanese = 0, - English = 1, - French = 2, - German = 3, - Italian = 4, - Spanish = 5, - Chinese = 6, - Reserved = 7, -}; - -enum GBAScreen : u8 -{ - Upper = 0, - Lower = (1 << 3), -}; - -enum BacklightLevel : u8 -{ - Low = 0, - Medium = 1 << 4, - High = 2 << 4, - Max = 3 << 4 -}; - -enum BootMenu : u8 -{ - Manual = 0, - Autostart = 1 << 6, -}; - using FirmwareIdentifier = std::array; using MacAddress = std::array; constexpr FirmwareIdentifier GENERATED_FIRMWARE_IDENTIFIER = {'M', 'E', 'L', 'N'}; -/** - * @note GBATek says the header is actually 511 bytes; - * this header struct is 512 bytes due to padding, - * but the last byte is just the first byte of the firmware's code. - * It doesn't affect the offset of any of the fields, - * so leaving that last byte in there is harmless. - * @see https://problemkaputt.de/gbatek.htm#dsfirmwareheader - * @see https://problemkaputt.de/gbatek.htm#dsfirmwarewificalibrationdata -*/ -union FirmwareHeader -{ - explicit FirmwareHeader(int consoletype); - void UpdateChecksum(); - u8 Bytes[512]; - struct - { - u16 ARM9GUICodeOffset; - u16 ARM7WifiCodeOffset; - u16 GUIWifiCodeChecksum; - u16 BootCodeChecksum; - - FirmwareIdentifier Identifier; - - u16 ARM9BootCodeROMAddress; - u16 ARM9BootCodeRAMAddress; - u16 ARM7BootCodeRAMAddress; - u16 ARM7BootCodeROMAddress; - u16 ShiftAmounts; - u16 DataGfxRomAddress; - - u8 BuildMinute; - u8 BuildHour; - u8 BuildDay; - u8 BuildMonth; - u8 BuildYear; - - FirmwareConsoleType ConsoleType; - - u8 Unused0[2]; - - u16 UserSettingsOffset; - u8 Unknown0[2]; - u8 Unknown1[2]; - u16 DataGfxChecksum; - u8 Unused2[2]; - - // Begin wi-fi settings - u16 WifiConfigChecksum; - u16 WifiConfigLength; - u8 Unused1; - enum WifiVersion WifiVersion; - - u8 Unused3[6]; - - SPI_Firmware::MacAddress MacAddress; - - u16 EnabledChannels; - - u8 Unknown2[2]; - - enum RFChipType RFChipType; - u8 RFBitsPerEntry; - u8 RFEntries; - u8 Unknown3; - - u8 InitialValues[32]; - u8 InitialBBValues[105]; - u8 Unused4; - union - { - struct - { - u8 InitialRFValues[36]; - u8 InitialRF56Values[84]; - u8 InitialBB1EValues[14]; - u8 InitialRf9Values[14]; - } Type2Config; - - struct - { - u8 InitialRFValues[41]; - u8 BBIndicesPerChannel; - u8 BBIndex1; - u8 BBData1[14]; - u8 BBIndex2; - u8 BBData2[14]; - u8 RFIndex1; - u8 RFData1[14]; - u8 RFIndex2; - u8 RFData2[14]; - u8 Unused0[46]; - } Type3Config; - }; - - u8 Unknown4; - u8 Unused5; - u8 Unused6[153]; - enum WifiBoard WifiBoard; - u8 WifiFlash; - u8 Unused7; - }; -}; - -static_assert(sizeof(FirmwareHeader) == 512, "FirmwareHeader should be 512 bytes"); - -struct ExtendedUserSettings -{ - char ID[8]; - u16 Checksum; - u16 ChecksumLength; - u8 Version; - u8 UpdateCount; - u8 BootMenuFlags; - u8 GBABorder; - u16 TemperatureCalibration0; - u16 TemperatureCalibration1; - u16 TemperatureCalibrationDegrees; - u8 TemperatureFlags; - u8 BacklightIntensity; - u32 DateCenturyOffset; - u8 DateMonthRecovery; - u8 DateDayRecovery; - u8 DateYearRecovery; - u8 DateTimeFlags; - char DateSeparator; - char TimeSeparator; - char DecimalSeparator; - char ThousandsSeparator; - u8 DaylightSavingsTimeNth; - u8 DaylightSavingsTimeDay; - u8 DaylightSavingsTimeOfMonth; - u8 DaylightSavingsTimeFlags; -}; - -static_assert(sizeof(ExtendedUserSettings) == 0x28, "ExtendedUserSettings should be 40 bytes"); - -union UserData -{ - UserData(); - void UpdateChecksum(); - [[nodiscard]] bool ChecksumValid() const - { - bool baseChecksumOk = Checksum == CRC16(Bytes, 0x70, 0xFFFF); - bool extendedChecksumOk = Bytes[0x74] != 1 || ExtendedSettings.Checksum == CRC16(Bytes + 0x74, 0x8A, 0xFFFF); - // For our purposes, the extended checksum is OK if we're not using extended data - - return baseChecksumOk && extendedChecksumOk; - } - - u8 Bytes[256]; - struct - { - u16 Version; - u8 FavoriteColor; - u8 BirthdayMonth; - u8 BirthdayDay; - u8 Unused0; - char16_t Nickname[10]; - u16 NameLength; - char16_t Message[26]; - u16 MessageLength; - u8 AlarmHour; - u8 AlarmMinute; - u8 Unknown0[2]; - u8 AlarmFlags; - u8 Unused1; - u16 TouchCalibrationADC1[2]; - u8 TouchCalibrationPixel1[2]; - u16 TouchCalibrationADC2[2]; - u8 TouchCalibrationPixel2[2]; - u16 Settings; - u8 Year; - u8 RTCClockAdjust; - u32 RTCOffset; - u8 Unused2[4]; - u16 UpdateCounter; - u16 Checksum; - union - { - u8 Unused3[0x8C]; - struct - { - u8 Unknown0; - Language ExtendedLanguage; // padded - u16 SupportedLanguageMask; - u8 Unused0[0x86]; - u16 Checksum; - } ExtendedSettings; - }; - }; -}; -static_assert(sizeof(UserData) == 256, "UserData should be 256 bytes"); class Firmware { public: + + enum class WepMode : u8 + { + None = 0, + Hex5 = 1, + Hex13 = 2, + Hex16 = 3, + Ascii5 = 5, + Ascii13 = 6, + Ascii16 = 7, + }; + + enum class WpaMode : u8 + { + Normal = 0, + WPA_WPA2 = 0x10, + WPS_WPA = 0x13, + Unused = 0xff, + }; + + enum class WpaSecurity : u8 + { + None = 0, + WPA_TKIP = 4, + WPA2_TKIP = 5, + WPA_AES = 6, + WPA2_AES = 7, + }; + + enum class AccessPointStatus : u8 + { + Normal = 0, + Aoss = 1, + NotConfigured = 0xff + }; + + /** + * @see https://problemkaputt.de/gbatek.htm#dsfirmwarewifiinternetaccesspoints + */ + union WifiAccessPoint + { + /** + * Constructs an unconfigured access point. + */ + WifiAccessPoint(); + + /** + * Constructs an access point configured with melonDS's defaults. + */ + explicit WifiAccessPoint(int consoletype); + void UpdateChecksum(); + u8 Bytes[256]; + struct + { + char ProxyUsername[32]; + char ProxyPassword[32]; + char SSID[32]; + char SSIDWEP64[32]; + u8 WEPKey1[16]; + u8 WEPKey2[16]; + u8 WEPKey3[16]; + u8 WEPKey4[16]; + IpAddress Address; + IpAddress Gateway; + IpAddress PrimaryDns; + IpAddress SecondaryDns; + u8 SubnetMask; + u8 Unknown0[21]; + enum WepMode WepMode; + AccessPointStatus Status; + u8 SSIDLength; + u8 Unknown1; + u16 Mtu; + u8 Unknown2[3]; + u8 ConnectionConfigured; + u8 NintendoWFCID[6]; + u8 Unknown3[8]; + u16 Checksum; + }; + }; + + static_assert(sizeof(WifiAccessPoint) == 256, "WifiAccessPoint should be 256 bytes"); + + union ExtendedWifiAccessPoint + { + ExtendedWifiAccessPoint(); + void UpdateChecksum(); + u8 Bytes[512]; + struct + { + WifiAccessPoint Base; + + // DSi-specific entries now + u8 PrecomputedPSK[32]; + char WPAPassword[64]; + char Unused0[33]; + WpaSecurity Security; + bool ProxyEnabled; + bool ProxyAuthentication; + char ProxyName[48]; + u8 Unused1[52]; + u16 ProxyPort; + u8 Unused2[20]; + u16 ExtendedChecksum; + } Data; + }; + + static_assert(sizeof(ExtendedWifiAccessPoint) == 512, "WifiAccessPoint should be 512 bytes"); + + + enum class FirmwareConsoleType : u8 + { + DS = 0xFF, + DSLite = 0x20, + DSi = 0x57, + iQueDS = 0x43, + iQueDSLite = 0x63, + }; + + enum class WifiVersion : u8 + { + V1_4 = 0, + V5 = 3, + V6_7 = 5, + W006 = 6, + W015 = 15, + W024 = 24, + N3DS = 34, + }; + + enum RFChipType : u8 + { + Type2 = 0x2, + Type3 = 0x3, + }; + + enum class WifiBoard : u8 + { + W015 = 0x1, + W024 = 0x2, + W028 = 0x3, + Unused = 0xff, + }; + + enum Language : u8 + { + Japanese = 0, + English = 1, + French = 2, + German = 3, + Italian = 4, + Spanish = 5, + Chinese = 6, + Reserved = 7, + }; + + enum GBAScreen : u8 + { + Upper = 0, + Lower = (1 << 3), + }; + + enum BacklightLevel : u8 + { + Low = 0, + Medium = 1 << 4, + High = 2 << 4, + Max = 3 << 4 + }; + + enum BootMenu : u8 + { + Manual = 0, + Autostart = 1 << 6, + }; + + /** + * @note GBATek says the header is actually 511 bytes; + * this header struct is 512 bytes due to padding, + * but the last byte is just the first byte of the firmware's code. + * It doesn't affect the offset of any of the fields, + * so leaving that last byte in there is harmless. + * @see https://problemkaputt.de/gbatek.htm#dsfirmwareheader + * @see https://problemkaputt.de/gbatek.htm#dsfirmwarewificalibrationdata + */ + union FirmwareHeader + { + explicit FirmwareHeader(int consoletype); + void UpdateChecksum(); + u8 Bytes[512]; + struct + { + u16 ARM9GUICodeOffset; + u16 ARM7WifiCodeOffset; + u16 GUIWifiCodeChecksum; + u16 BootCodeChecksum; + + FirmwareIdentifier Identifier; + + u16 ARM9BootCodeROMAddress; + u16 ARM9BootCodeRAMAddress; + u16 ARM7BootCodeRAMAddress; + u16 ARM7BootCodeROMAddress; + u16 ShiftAmounts; + u16 DataGfxRomAddress; + + u8 BuildMinute; + u8 BuildHour; + u8 BuildDay; + u8 BuildMonth; + u8 BuildYear; + + FirmwareConsoleType ConsoleType; + + u8 Unused0[2]; + + u16 UserSettingsOffset; + u8 Unknown0[2]; + u8 Unknown1[2]; + u16 DataGfxChecksum; + u8 Unused2[2]; + + // Begin wi-fi settings + u16 WifiConfigChecksum; + u16 WifiConfigLength; + u8 Unused1; + enum WifiVersion WifiVersion; + + u8 Unused3[6]; + + MacAddress MacAddress; + + u16 EnabledChannels; + + u8 Unknown2[2]; + + enum RFChipType RFChipType; + u8 RFBitsPerEntry; + u8 RFEntries; + u8 Unknown3; + + u8 InitialValues[32]; + u8 InitialBBValues[105]; + u8 Unused4; + union + { + struct + { + u8 InitialRFValues[36]; + u8 InitialRF56Values[84]; + u8 InitialBB1EValues[14]; + u8 InitialRf9Values[14]; + } Type2Config; + + struct + { + u8 InitialRFValues[41]; + u8 BBIndicesPerChannel; + u8 BBIndex1; + u8 BBData1[14]; + u8 BBIndex2; + u8 BBData2[14]; + u8 RFIndex1; + u8 RFData1[14]; + u8 RFIndex2; + u8 RFData2[14]; + u8 Unused0[46]; + } Type3Config; + }; + + u8 Unknown4; + u8 Unused5; + u8 Unused6[153]; + enum WifiBoard WifiBoard; + u8 WifiFlash; + u8 Unused7; + }; + }; + + static_assert(sizeof(FirmwareHeader) == 512, "FirmwareHeader should be 512 bytes"); + + struct ExtendedUserSettings + { + char ID[8]; + u16 Checksum; + u16 ChecksumLength; + u8 Version; + u8 UpdateCount; + u8 BootMenuFlags; + u8 GBABorder; + u16 TemperatureCalibration0; + u16 TemperatureCalibration1; + u16 TemperatureCalibrationDegrees; + u8 TemperatureFlags; + u8 BacklightIntensity; + u32 DateCenturyOffset; + u8 DateMonthRecovery; + u8 DateDayRecovery; + u8 DateYearRecovery; + u8 DateTimeFlags; + char DateSeparator; + char TimeSeparator; + char DecimalSeparator; + char ThousandsSeparator; + u8 DaylightSavingsTimeNth; + u8 DaylightSavingsTimeDay; + u8 DaylightSavingsTimeOfMonth; + u8 DaylightSavingsTimeFlags; + }; + + static_assert(sizeof(ExtendedUserSettings) == 0x28, "ExtendedUserSettings should be 40 bytes"); + + union UserData + { + UserData(); + void UpdateChecksum(); + [[nodiscard]] bool ChecksumValid() const + { + bool baseChecksumOk = Checksum == CRC16(Bytes, 0x70, 0xFFFF); + bool extendedChecksumOk = Bytes[0x74] != 1 || ExtendedSettings.Checksum == CRC16(Bytes + 0x74, 0x8A, 0xFFFF); + // For our purposes, the extended checksum is OK if we're not using extended data + + return baseChecksumOk && extendedChecksumOk; + } + + u8 Bytes[256]; + struct + { + u16 Version; + u8 FavoriteColor; + u8 BirthdayMonth; + u8 BirthdayDay; + u8 Unused0; + char16_t Nickname[10]; + u16 NameLength; + char16_t Message[26]; + u16 MessageLength; + u8 AlarmHour; + u8 AlarmMinute; + u8 Unknown0[2]; + u8 AlarmFlags; + u8 Unused1; + u16 TouchCalibrationADC1[2]; + u8 TouchCalibrationPixel1[2]; + u16 TouchCalibrationADC2[2]; + u8 TouchCalibrationPixel2[2]; + u16 Settings; + u8 Year; + u8 RTCClockAdjust; + u32 RTCOffset; + u8 Unused2[4]; + u16 UpdateCounter; + u16 Checksum; + union + { + u8 Unused3[0x8C]; + struct + { + u8 Unknown0; + Language ExtendedLanguage; // padded + u16 SupportedLanguageMask; + u8 Unused0[0x86]; + u16 Checksum; + } ExtendedSettings; + }; + }; + }; + static_assert(sizeof(UserData) == 256, "UserData should be 256 bytes"); + /** * Constructs a default firmware blob * filled with data necessary for booting and configuring NDS games. @@ -449,28 +451,28 @@ public: Firmware& operator=(Firmware&& other) noexcept; ~Firmware(); - [[nodiscard]] FirmwareHeader& Header() { return *reinterpret_cast(FirmwareBuffer); } - [[nodiscard]] const FirmwareHeader& Header() const { return *reinterpret_cast(FirmwareBuffer); } + [[nodiscard]] FirmwareHeader& GetHeader() { return *reinterpret_cast(FirmwareBuffer); } + [[nodiscard]] const FirmwareHeader& GetHeader() const { return *reinterpret_cast(FirmwareBuffer); } /// @return The offset of the first basic Wi-fi settings block in the firmware /// (not the extended Wi-fi settings block used by the DSi). /// @see WifiAccessPointPosition - [[nodiscard]] u32 WifiAccessPointOffset() const { return UserDataOffset() - 0x400; } + [[nodiscard]] u32 GetWifiAccessPointOffset() const { return GetUserDataOffset() - 0x400; } /// @return The address of the first basic Wi-fi settings block in the firmware. - [[nodiscard]] u8* WifiAccessPointPosition() { return FirmwareBuffer + WifiAccessPointOffset(); } - [[nodiscard]] const u8* WifiAccessPointPosition() const { return FirmwareBuffer + WifiAccessPointOffset(); } + [[nodiscard]] u8* GetWifiAccessPointPosition() { return FirmwareBuffer + GetWifiAccessPointOffset(); } + [[nodiscard]] const u8* GetWifiAccessPointPosition() const { return FirmwareBuffer + GetWifiAccessPointOffset(); } - [[nodiscard]] const std::array& AccessPoints() const + [[nodiscard]] const std::array& GetAccessPoints() const { // An std::array is a wrapper around a C array, so this cast is fine. - return *reinterpret_cast*>(WifiAccessPointPosition()); + return *reinterpret_cast*>(GetWifiAccessPointPosition()); } - [[nodiscard]] std::array& AccessPoints() + [[nodiscard]] std::array& GetAccessPoints() { // An std::array is a wrapper around a C array, so this cast is fine. - return *reinterpret_cast*>(WifiAccessPointPosition()); + return *reinterpret_cast*>(GetWifiAccessPointPosition()); } /// @returns \c true if this firmware image contains bootable code. @@ -481,20 +483,20 @@ public: /// @return The address of the first extended Wi-fi settings block in the firmware. /// @warning Only meaningful if this is DSi firmware. - [[nodiscard]] u32 ExtendedAccessPointOffset() const { return UserDataOffset() + EXTENDED_WIFI_SETTINGS_OFFSET; } - [[nodiscard]] u8* ExtendedAccessPointPosition() { return FirmwareBuffer + ExtendedAccessPointOffset(); } - [[nodiscard]] const u8* ExtendedAccessPointPosition() const { return FirmwareBuffer + ExtendedAccessPointOffset(); } + [[nodiscard]] u32 GetExtendedAccessPointOffset() const { return GetUserDataOffset() + EXTENDED_WIFI_SETTINGS_OFFSET; } + [[nodiscard]] u8* GetExtendedAccessPointPosition() { return FirmwareBuffer + GetExtendedAccessPointOffset(); } + [[nodiscard]] const u8* GetExtendedAccessPointPosition() const { return FirmwareBuffer + GetExtendedAccessPointOffset(); } - [[nodiscard]] const std::array& ExtendedAccessPoints() const + [[nodiscard]] const std::array& GetExtendedAccessPoints() const { // An std::array is a wrapper around a C array, so this cast is fine. - return *reinterpret_cast*>(ExtendedAccessPointPosition()); + return *reinterpret_cast*>(GetExtendedAccessPointPosition()); } - [[nodiscard]] std::array& ExtendedAccessPoints() + [[nodiscard]] std::array& GetExtendedAccessPoints() { // An std::array is a wrapper around a C array, so this cast is fine. - return *reinterpret_cast*>(ExtendedAccessPointPosition()); + return *reinterpret_cast*>(GetExtendedAccessPointPosition()); } /// @return The pointer to the firmware buffer, @@ -508,21 +510,21 @@ public: /// @return The offset of the first user data section in the firmware. /// @see UserDataPosition - [[nodiscard]] u32 UserDataOffset() const { return Header().UserSettingsOffset << 3; } + [[nodiscard]] u32 GetUserDataOffset() const { return GetHeader().UserSettingsOffset << 3; } /// @return The address of the first user data section in the firmware. /// @see UserDataOffset - [[nodiscard]] u8* UserDataPosition() { return FirmwareBuffer + UserDataOffset(); } - [[nodiscard]] const u8* UserDataPosition() const { return FirmwareBuffer + UserDataOffset(); } + [[nodiscard]] u8* GetUserDataPosition() { return FirmwareBuffer + GetUserDataOffset(); } + [[nodiscard]] const u8* GetUserDataPosition() const { return FirmwareBuffer + GetUserDataOffset(); } /// @return Reference to the two user data sections. /// @note Either \c UserData object could be the "effective" one, /// so prefer using \c EffectiveUserData() if you're not modifying both. - [[nodiscard]] const std::array& UserData() const + [[nodiscard]] const std::array& GetUserData() const { // An std::array is a wrapper around a C array, so this cast is fine. - return *reinterpret_cast*>(UserDataPosition()); + return *reinterpret_cast*>(GetUserDataPosition()); }; /** @@ -531,10 +533,10 @@ public: * so prefer using \c EffectiveUserData() if you're not modifying both. * @warning Remember to call UserData::UpdateChecksum() after modifying any of its fields. */ - [[nodiscard]] std::array& UserData() + [[nodiscard]] std::array& GetUserData() { // An std::array is a wrapper around a C array, so this cast is fine. - return *reinterpret_cast*>(UserDataPosition()); + return *reinterpret_cast*>(GetUserDataPosition()); } /** @@ -543,13 +545,16 @@ public: * Specifically, the firmware will use whichever one has the valid checksum * (or the newer one if they're both valid). */ - [[nodiscard]] const union UserData& EffectiveUserData() const; + [[nodiscard]] const union UserData& GetEffectiveUserData() const; /** * @return Reference to whichever of the two user data sections * has the highest update counter. */ - [[nodiscard]] union UserData& EffectiveUserData(); + [[nodiscard]] union UserData& GetEffectiveUserData(); + + /// Fix the given firmware length to an acceptable length + u32 FixFirmwareLength(u32 originalLength); /// Updates the checksums of all used sections of the firmware. void UpdateChecksums(); @@ -558,6 +563,5 @@ private: u32 FirmwareBufferLength; u32 FirmwareMask; }; -} #endif //MELONDS_SPI_FIRMWARE_H diff --git a/src/Wifi.cpp b/src/Wifi.cpp index c5a67abf..7f57c4bb 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -180,7 +180,6 @@ void DeInit() void Reset() { - using namespace SPI_Firmware; memset(RAM, 0, 0x2000); memset(IO, 0, 0x1000); @@ -220,15 +219,17 @@ void Reset() } #undef BBREG_FIXED - RFVersion = GetFirmware()->Header().RFChipType; + const Firmware* fw = NDS::SPI->GetFirmware(); + + RFVersion = fw->GetHeader().RFChipType; memset(RFRegs, 0, 4*0x40); - FirmwareConsoleType console = GetFirmware()->Header().ConsoleType; - if (console == FirmwareConsoleType::DS) + Firmware::FirmwareConsoleType console = fw->GetHeader().ConsoleType; + if (console == Firmware::FirmwareConsoleType::DS) IOPORT(0x000) = 0x1440; - else if (console == FirmwareConsoleType::DSLite) + else if (console == Firmware::FirmwareConsoleType::DSLite) IOPORT(0x000) = 0xC340; - else if (NDS::ConsoleType == 1 && console == FirmwareConsoleType::DSi) + else if (NDS::ConsoleType == 1 && console == Firmware::FirmwareConsoleType::DSi) IOPORT(0x000) = 0xC340; // DSi has the modern DS-wifi variant else { diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 252594c7..951e1f54 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -580,31 +580,31 @@ void WriteGBASave(const u8* savedata, u32 savelen, u32 writeoffset, u32 writelen ROMManager::GBASave->RequestFlush(savedata, savelen, writeoffset, writelen); } -void WriteFirmware(const SPI_Firmware::Firmware& firmware, u32 writeoffset, u32 writelen) +void WriteFirmware(const Firmware& firmware, u32 writeoffset, u32 writelen) { if (!ROMManager::FirmwareSave) return; - if (firmware.Header().Identifier != SPI_Firmware::GENERATED_FIRMWARE_IDENTIFIER) + if (firmware.GetHeader().Identifier != GENERATED_FIRMWARE_IDENTIFIER) { // If this is not the default built-in firmware... // ...then write the whole thing back. ROMManager::FirmwareSave->RequestFlush(firmware.Buffer(), firmware.Length(), writeoffset, writelen); } else { - u32 eapstart = firmware.ExtendedAccessPointOffset(); - u32 eapend = eapstart + sizeof(firmware.ExtendedAccessPoints()); + u32 eapstart = firmware.GetExtendedAccessPointOffset(); + u32 eapend = eapstart + sizeof(firmware.GetExtendedAccessPoints()); - u32 apstart = firmware.WifiAccessPointOffset(); - u32 apend = apstart + sizeof(firmware.AccessPoints()); + u32 apstart = firmware.GetWifiAccessPointOffset(); + u32 apend = apstart + sizeof(firmware.GetAccessPoints()); // assert that the extended access points come just before the regular ones assert(eapend == apstart); if (eapstart <= writeoffset && writeoffset < apend) { // If we're writing to the access points... - const u8* buffer = firmware.ExtendedAccessPointPosition(); - u32 length = sizeof(firmware.ExtendedAccessPoints()) + sizeof(firmware.AccessPoints()); + const u8* buffer = firmware.GetExtendedAccessPointPosition(); + u32 length = sizeof(firmware.GetExtendedAccessPoints()) + sizeof(firmware.GetAccessPoints()); ROMManager::FirmwareSave->RequestFlush(buffer, length, writeoffset - eapstart, writelen); } } diff --git a/src/frontend/qt_sdl/PowerManagement/PowerManagementDialog.cpp b/src/frontend/qt_sdl/PowerManagement/PowerManagementDialog.cpp index 89f74e5f..033c2fef 100644 --- a/src/frontend/qt_sdl/PowerManagement/PowerManagementDialog.cpp +++ b/src/frontend/qt_sdl/PowerManagement/PowerManagementDialog.cpp @@ -49,7 +49,7 @@ PowerManagementDialog::PowerManagementDialog(QWidget* parent) : QDialog(parent), { ui->grpDSiBattery->setEnabled(false); - oldDSBatteryLevel = SPI_Powerman::GetBatteryLevelOkay(); + oldDSBatteryLevel = NDS::SPI->GetPowerMan()->GetBatteryLevelOkay(); } updateDSBatteryLevelControls(); @@ -91,7 +91,7 @@ void PowerManagementDialog::done(int r) } else { - Config::DSBatteryLevelOkay = SPI_Powerman::GetBatteryLevelOkay(); + Config::DSBatteryLevelOkay = NDS::SPI->GetPowerMan()->GetBatteryLevelOkay(); } } else @@ -103,7 +103,7 @@ void PowerManagementDialog::done(int r) } else { - SPI_Powerman::SetBatteryLevelOkay(oldDSBatteryLevel); + NDS::SPI->GetPowerMan()->SetBatteryLevelOkay(oldDSBatteryLevel); } } @@ -114,17 +114,17 @@ void PowerManagementDialog::done(int r) void PowerManagementDialog::on_rbDSBatteryLow_clicked() { - SPI_Powerman::SetBatteryLevelOkay(false); + NDS::SPI->GetPowerMan()->SetBatteryLevelOkay(false); } void PowerManagementDialog::on_rbDSBatteryOkay_clicked() { - SPI_Powerman::SetBatteryLevelOkay(true); + NDS::SPI->GetPowerMan()->SetBatteryLevelOkay(true); } void PowerManagementDialog::updateDSBatteryLevelControls() { - if (SPI_Powerman::GetBatteryLevelOkay()) + if (NDS::SPI->GetPowerMan()->GetBatteryLevelOkay()) ui->rbDSBatteryOkay->setChecked(true); else ui->rbDSBatteryLow->setChecked(true); diff --git a/src/frontend/qt_sdl/ROMManager.cpp b/src/frontend/qt_sdl/ROMManager.cpp index 648ab676..9b4b49c0 100644 --- a/src/frontend/qt_sdl/ROMManager.cpp +++ b/src/frontend/qt_sdl/ROMManager.cpp @@ -588,7 +588,7 @@ void SetBatteryLevels() } else { - SPI_Powerman::SetBatteryLevelOkay(Config::DSBatteryLevelOkay); + NDS::SPI->GetPowerMan()->SetBatteryLevelOkay(Config::DSBatteryLevelOkay); } } @@ -792,10 +792,10 @@ void ClearBackupState() // We want both the firmware object and the path that was used to load it, // since we'll need to give it to the save manager later -pair, string> LoadFirmwareFromFile() +pair, string> LoadFirmwareFromFile() { string loadedpath; - unique_ptr firmware = nullptr; + unique_ptr firmware = nullptr; string firmwarepath = Config::ConsoleType == 0 ? Config::FirmwarePath : Config::DSiFirmwarePath; Log(LogLevel::Debug, "SPI firmware: loading from file %s\n", firmwarepath.c_str()); @@ -812,7 +812,7 @@ pair, string> LoadFirmwareFromFile() if (f) { - firmware = make_unique(f); + firmware = make_unique(f); if (!firmware->Buffer()) { Log(LogLevel::Warn, "Couldn't read firmware file!\n"); @@ -826,9 +826,8 @@ pair, string> LoadFirmwareFromFile() return std::make_pair(std::move(firmware), loadedpath); } -pair, string> GenerateDefaultFirmware() +pair, string> GenerateDefaultFirmware() { - using namespace SPI_Firmware; // Construct the default firmware... string settingspath; std::unique_ptr firmware = std::make_unique(Config::ConsoleType); @@ -850,27 +849,27 @@ pair, string> GenerateDefaultFirmware() // and if we didn't keep them then the player would have to reset them in each session. if (f) { // If we have Wi-fi settings to load... - constexpr unsigned TOTAL_WFC_SETTINGS_SIZE = 3 * (sizeof(WifiAccessPoint) + sizeof(ExtendedWifiAccessPoint)); + constexpr unsigned TOTAL_WFC_SETTINGS_SIZE = 3 * (sizeof(Firmware::WifiAccessPoint) + sizeof(Firmware::ExtendedWifiAccessPoint)); // The access point and extended access point segments might // be in different locations depending on the firmware revision, // but our generated firmware always keeps them next to each other. // (Extended access points first, then regular ones.) - if (!FileRead(firmware->ExtendedAccessPointPosition(), TOTAL_WFC_SETTINGS_SIZE, 1, f)) + if (!FileRead(firmware->GetExtendedAccessPointPosition(), TOTAL_WFC_SETTINGS_SIZE, 1, f)) { // If we couldn't read the Wi-fi settings from this file... Platform::Log(Platform::LogLevel::Warn, "Failed to read Wi-fi settings from \"%s\"; using defaults instead\n", wfcsettingspath.c_str()); - firmware->AccessPoints() = { - WifiAccessPoint(Config::ConsoleType), - WifiAccessPoint(), - WifiAccessPoint(), + firmware->GetAccessPoints() = { + Firmware::WifiAccessPoint(Config::ConsoleType), + Firmware::WifiAccessPoint(), + Firmware::WifiAccessPoint(), }; - firmware->ExtendedAccessPoints() = { - ExtendedWifiAccessPoint(), - ExtendedWifiAccessPoint(), - ExtendedWifiAccessPoint(), + firmware->GetExtendedAccessPoints() = { + Firmware::ExtendedWifiAccessPoint(), + Firmware::ExtendedWifiAccessPoint(), + Firmware::ExtendedWifiAccessPoint(), }; } @@ -884,10 +883,9 @@ pair, string> GenerateDefaultFirmware() return std::make_pair(std::move(firmware), std::move(wfcsettingspath)); } -void LoadUserSettingsFromConfig(SPI_Firmware::Firmware& firmware) +void LoadUserSettingsFromConfig(Firmware& firmware) { - using namespace SPI_Firmware; - UserData& currentData = firmware.EffectiveUserData(); + auto& currentData = firmware.GetEffectiveUserData(); // setting up username std::string orig_username = Config::FirmwareUsername; @@ -899,10 +897,10 @@ void LoadUserSettingsFromConfig(SPI_Firmware::Firmware& firmware) memcpy(currentData.Nickname, username.data(), usernameLength * sizeof(char16_t)); } - auto language = static_cast(Config::FirmwareLanguage); - if (language != Language::Reserved) + auto language = static_cast(Config::FirmwareLanguage); + if (language != Firmware::Language::Reserved) { // If the frontend specifies a language (rather than using the existing value)... - currentData.Settings &= ~Language::Reserved; // ..clear the existing language... + currentData.Settings &= ~Firmware::Language::Reserved; // ..clear the existing language... currentData.Settings |= language; // ...and set the new one. } @@ -937,7 +935,7 @@ void LoadUserSettingsFromConfig(SPI_Firmware::Firmware& firmware) MacAddress mac; bool rep = false; - auto& header = firmware.Header(); + auto& header = firmware.GetHeader(); memcpy(&mac, header.MacAddress.data(), sizeof(MacAddress)); @@ -1035,7 +1033,7 @@ bool InstallNAND(const u8* es_keyY) memcpy(&settings.Nickname, username.data(), usernameLength * sizeof(char16_t)); // setting language - settings.Language = static_cast(Config::FirmwareLanguage); + settings.Language = static_cast(Config::FirmwareLanguage); // setting up color settings.FavoriteColor = Config::FirmwareFavouriteColour; @@ -1074,7 +1072,6 @@ bool InstallNAND(const u8* es_keyY) bool InstallFirmware() { - using namespace SPI_Firmware; FirmwareSave.reset(); unique_ptr firmware; string firmwarepath; @@ -1105,7 +1102,7 @@ bool InstallFirmware() FirmwareSave = std::make_unique(firmwarepath); - return InstallFirmware(std::move(firmware)); + return NDS::SPI->GetFirmwareMem()->InstallFirmware(std::move(firmware)); } bool LoadROM(QStringList filepath, bool reset)