aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/DSi.cpp11
-rw-r--r--src/DSi_I2C.cpp2
-rw-r--r--src/DSi_NAND.h2
-rw-r--r--src/DSi_NWifi.cpp16
-rw-r--r--src/DSi_SPI_TSC.cpp61
-rw-r--r--src/DSi_SPI_TSC.h33
-rw-r--r--src/NDS.cpp57
-rw-r--r--src/NDS.h4
-rw-r--r--src/Platform.h7
-rw-r--r--src/SPI.cpp338
-rw-r--r--src/SPI.h155
-rw-r--r--src/SPI_Firmware.cpp99
-rw-r--r--src/SPI_Firmware.h706
-rw-r--r--src/Wifi.cpp13
-rw-r--r--src/frontend/qt_sdl/Platform.cpp16
-rw-r--r--src/frontend/qt_sdl/PowerManagement/PowerManagementDialog.cpp12
-rw-r--r--src/frontend/qt_sdl/ROMManager.cpp49
17 files changed, 795 insertions, 786 deletions
diff --git a/src/DSi.cpp b/src/DSi.cpp
index 17bfb8f..0a62db2 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<u8>(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 c4ad50c..26f3e4b 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 0077eac..99a9ee7 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 558cd6f..d95def5 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 c690f9c..1304440 100644
--- a/src/DSi_SPI_TSC.cpp
+++ b/src/DSi_SPI_TSC.cpp
@@ -19,38 +19,25 @@
#include <stdio.h>
#include <string.h>
#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()
+DSi_TSC::DSi_TSC(SPIHost* host) : TSC(host)
{
- return true;
}
-void DeInit()
+DSi_TSC::~DSi_TSC()
{
}
-void Reset()
+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()
-{
- if (TSCMode == 0x00) return SPI_TSC::Read();
-
- return Data;
-}
-
-void Write(u8 val, u32 hold)
+void DSi_TSC::Write(u8 val)
{
- 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 7a3acf4..c7b9bfe 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 0efd0e9..9b9e1e7 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 89ebb1c..b0126ed 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 144fce1..7fa8fbd 100644
--- a/src/Platform.h
+++ b/src/Platform.h
@@ -24,10 +24,7 @@
#include <functional>
#include <string>
-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 1a4c12e..8eb8b0e 100644
--- a/src/SPI.cpp
+++ b/src/SPI.cpp
@@ -29,18 +29,6 @@
using namespace Platform;
-namespace SPI_Firmware
-{
-
-std::unique_ptr<Firmware> 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<class 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;
}
-bool InstallFirmware(std::unique_ptr<class Firmware>&& firmware)
+bool FirmwareMem::InstallFirmware(std::unique_ptr<class Firmware>&& firmware)
{
if (!firmware)
{
@@ -236,40 +202,42 @@ bool InstallFirmware(std::unique_ptr<class Firmware>&& 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()
-{
- return Data;
-}
-
-void Write(u8 val, u32 hold)
+void FirmwareMem::Write(u8 val)
{
- 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()
+PowerMan::PowerMan(SPIHost* host) : SPIDevice(host)
{
- return true;
}
-void DeInit()
+PowerMan::~PowerMan()
{
}
-void Reset()
+void PowerMan::Reset()
{
- Hold = 0;
+ 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()
+TSC::TSC(SPIHost* host) : SPIDevice(host)
{
- return true;
}
-void DeInit()
+TSC::~TSC()
{
}
-void Reset()
+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++;
}
-}
-
-
-namespace SPI
-{
-
-u16 Cnt;
-
-u32 CurDevice; // remove me
-bool Init()
+SPIHost::SPIHost()
{
- 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;
+ NDS::RegisterEventFunc(NDS::Event_SPITransfer, 0, MemberEventFunc(SPIHost, TransferDone));
- return true;
+ Devices[SPIDevice_FirmwareMem] = new FirmwareMem(this);
+ Devices[SPIDevice_PowerMan] = new PowerMan(this);
+ Devices[SPIDevice_TSC] = nullptr;
}
-void DeInit()
+SPIHost::~SPIHost()
{
- SPI_Firmware::DeInit();
- SPI_Powerman::DeInit();
- SPI_TSC::DeInit();
- DSi_SPI_TSC::DeInit();
+ for (int i = 0; i < SPIDevice_MAX; i++)
+ {
+ if (Devices[i])
+ delete Devices[i];
+
+ 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 d815203..4578ad5 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;
+
+class SPIDevice
+{
+public:
+ SPIDevice(SPIHost* host) : Host(host), Hold(false), DataPos(0) {}
+ virtual ~SPIDevice() {}
+
+ virtual void Reset() = 0;
+
+ virtual void DoSavestate(Savestate* file) = 0;
+
+ 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 Reset() override;
+
+ void DoSavestate(Savestate* file) override;
+
+ void SetupDirectBoot(bool dsi);
+
+ const class Firmware* GetFirmware();
+ bool IsLoadedFirmwareBuiltIn();
+ bool InstallFirmware(class Firmware&& firmware);
+ bool InstallFirmware(std::unique_ptr<class Firmware>&& firmware);
+ void RemoveFirmware();
+
+ void Write(u8 val) override;
+ void Release() override;
-/// @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();
+private:
+ std::unique_ptr<Firmware> Firmware;
-bool IsLoadedFirmwareBuiltIn();
-bool InstallFirmware(Firmware&& firmware);
-bool InstallFirmware(std::unique_ptr<Firmware>&& firmware);
-void RemoveFirmware();
-}
+ u8 CurCmd;
-namespace SPI_Powerman
+ u8 StatusReg;
+ u32 Addr;
+
+ bool VerifyCRC16(u32 start, u32 offset, u32 len, u32 crcoffset);
+};
+
+class PowerMan : public SPIDevice
{
+public:
+ PowerMan(SPIHost* host);
+ ~PowerMan() override;
+
+ void Reset() override;
+
+ void DoSavestate(Savestate* file) override;
-bool GetBatteryLevelOkay();
-void SetBatteryLevelOkay(bool okay);
+ bool GetBatteryLevelOkay();
+ void SetBatteryLevelOkay(bool okay);
-}
+ void Write(u8 val) override;
-namespace SPI_TSC
+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;
-void SetTouchCoords(u16 x, u16 y);
-void MicInputFrame(s16* data, int samples);
+ virtual void SetTouchCoords(u16 x, u16 y);
+ virtual void MicInputFrame(s16* data, int samples);
-u8 Read();
-void Write(u8 val, u32 hold);
+ virtual void Write(u8 val) override;
-}
+protected:
+ u8 ControlByte;
-namespace SPI
+ 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]; }
-extern u16 Cnt;
+ const Firmware* GetFirmware() { return GetFirmwareMem()->GetFirmware(); }
-bool Init();
-void DeInit();
-void Reset();
-void DoSavestate(Savestate* file);
+ u16 ReadCnt() { return Cnt; }
+ void WriteCnt(u16 val);
-void WriteCnt(u16 val);
+ u8 ReadData();
+ void WriteData(u8 val);
-u8 ReadData();
-void WriteData(u8 val);
+ void TransferDone(u32 param);
-void TransferDone(u32 param);
+private:
+ u16 Cnt;
-}
+ SPIDevice* Devices[3];
+};
#endif
diff --git a/src/SPI_Firmware.cpp b/src/SPI_Firmware.cpp
index 44fbfe7..943a0b3 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 <string.h>
@@ -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<union UserData, 2>& settings = *reinterpret_cast<std::array<union UserData, 2>*>(UserDataPosition());
+ std::array<UserData, 2>& settings = *reinterpret_cast<std::array<UserData, 2>*>(GetUserDataPosition());
settings = {
- SPI_Firmware::UserData(),
- SPI_Firmware::UserData(),
+ UserData(),
+ UserData(),
};
// wifi access points
// TODO: WFC ID??
- std::array<WifiAccessPoint, 3>& accesspoints = *reinterpret_cast<std::array<WifiAccessPoint, 3>*>(WifiAccessPointPosition());
+ std::array<WifiAccessPoint, 3>& accesspoints = *reinterpret_cast<std::array<WifiAccessPoint, 3>*>(GetWifiAccessPointPosition());
accesspoints = {
WifiAccessPoint(consoletype),
@@ -203,7 +230,7 @@ SPI_Firmware::Firmware::Firmware(int consoletype)
if (consoletype == 1)
{
- std::array<ExtendedWifiAccessPoint, 3>& extendedaccesspoints = *reinterpret_cast<std::array<ExtendedWifiAccessPoint, 3>*>(ExtendedAccessPointPosition());
+ std::array<ExtendedWifiAccessPoint, 3>& extendedaccesspoints = *reinterpret_cast<std::array<ExtendedWifiAccessPoint, 3>*>(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<union UserData, 2>& userdata = UserData();
+const Firmware::UserData& Firmware::GetEffectiveUserData() const {
+ const std::array<union UserData, 2>& 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<union UserData, 2>& userdata = UserData();
+Firmware::UserData& Firmware::GetEffectiveUserData() {
+ std::array<union UserData, 2>& 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 8557604..ad66a0a 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<u8, 6>;
using IpAddress = std::array<u8, 4>;
@@ -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,
-};
+using FirmwareIdentifier = std::array<u8, 4>;
+using MacAddress = std::array<u8, 6>;
-enum class WpaMode : u8
-{
- Normal = 0,
- WPA_WPA2 = 0x10,
- WPS_WPA = 0x13,
- Unused = 0xff,
-};
+constexpr FirmwareIdentifier GENERATED_FIRMWARE_IDENTIFIER = {'M', 'E', 'L', 'N'};
-enum class WpaSecurity : u8
-{
- None = 0,
- WPA_TKIP = 4,
- WPA2_TKIP = 5,
- WPA_AES = 6,
- WPA2_AES = 7,
-};
-enum class AccessPointStatus : u8
+class Firmware
{
- Normal = 0,
- Aoss = 1,
- NotConfigured = 0xff
-};
+public:
-/**
- * @see https://problemkaputt.de/gbatek.htm#dsfirmwarewifiinternetaccesspoints
- */
-union WifiAccessPoint
-{
- /**
- * Constructs an unconfigured access point.
- */
- WifiAccessPoint();
+ enum class WepMode : u8
+ {
+ None = 0,
+ Hex5 = 1,
+ Hex13 = 2,
+ Hex16 = 3,
+ Ascii5 = 5,
+ Ascii13 = 6,
+ Ascii16 = 7,
+ };
- /**
- * Constructs an access point configured with melonDS's defaults.
- */
- explicit WifiAccessPoint(int consoletype);
- void UpdateChecksum();
- u8 Bytes[256];
- struct
+ enum class WpaMode : u8
{
- 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;
+ Normal = 0,
+ WPA_WPA2 = 0x10,
+ WPS_WPA = 0x13,
+ Unused = 0xff,
};
-};
-static_assert(sizeof(WifiAccessPoint) == 256, "WifiAccessPoint should be 256 bytes");
+ enum class WpaSecurity : u8
+ {
+ None = 0,
+ WPA_TKIP = 4,
+ WPA2_TKIP = 5,
+ WPA_AES = 6,
+ WPA2_AES = 7,
+ };
-union ExtendedWifiAccessPoint
-{
- ExtendedWifiAccessPoint();
- void UpdateChecksum();
- u8 Bytes[512];
- struct
+ enum class AccessPointStatus : u8
{
- 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;
-};
+ Normal = 0,
+ Aoss = 1,
+ NotConfigured = 0xff
+ };
-static_assert(sizeof(ExtendedWifiAccessPoint) == 512, "WifiAccessPoint should be 512 bytes");
+ /**
+ * @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");
-enum class FirmwareConsoleType : u8
-{
- DS = 0xFF,
- DSLite = 0x20,
- DSi = 0x57,
- iQueDS = 0x43,
- iQueDSLite = 0x63,
-};
+ 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;
+ };
-enum class WifiVersion : u8
-{
- V1_4 = 0,
- V5 = 3,
- V6_7 = 5,
- W006 = 6,
- W015 = 15,
- W024 = 24,
- N3DS = 34,
-};
+ static_assert(sizeof(ExtendedWifiAccessPoint) == 512, "WifiAccessPoint should be 512 bytes");
-enum RFChipType : u8
-{
- Type2 = 0x2,
- Type3 = 0x3,
-};
-enum class WifiBoard : u8
-{
- W015 = 0x1,
- W024 = 0x2,
- W028 = 0x3,
- Unused = 0xff,
-};
+ enum class FirmwareConsoleType : u8
+ {
+ DS = 0xFF,
+ DSLite = 0x20,
+ DSi = 0x57,
+ iQueDS = 0x43,
+ iQueDSLite = 0x63,
+ };
-enum Language : u8
-{
- Japanese = 0,
- English = 1,
- French = 2,
- German = 3,
- Italian = 4,
- Spanish = 5,
- Chinese = 6,
- Reserved = 7,
-};
+ enum class WifiVersion : u8
+ {
+ V1_4 = 0,
+ V5 = 3,
+ V6_7 = 5,
+ W006 = 6,
+ W015 = 15,
+ W024 = 24,
+ N3DS = 34,
+ };
-enum GBAScreen : u8
-{
- Upper = 0,
- Lower = (1 << 3),
-};
+ enum RFChipType : u8
+ {
+ Type2 = 0x2,
+ Type3 = 0x3,
+ };
-enum BacklightLevel : u8
-{
- Low = 0,
- Medium = 1 << 4,
- High = 2 << 4,
- Max = 3 << 4
-};
+ enum class WifiBoard : u8
+ {
+ W015 = 0x1,
+ W024 = 0x2,
+ W028 = 0x3,
+ Unused = 0xff,
+ };
-enum BootMenu : u8
-{
- Manual = 0,
- Autostart = 1 << 6,
-};
+ enum Language : u8
+ {
+ Japanese = 0,
+ English = 1,
+ French = 2,
+ German = 3,
+ Italian = 4,
+ Spanish = 5,
+ Chinese = 6,
+ Reserved = 7,
+ };
-using FirmwareIdentifier = std::array<u8, 4>;
-using MacAddress = std::array<u8, 6>;
+ enum GBAScreen : u8
+ {
+ Upper = 0,
+ Lower = (1 << 3),
+ };
-constexpr FirmwareIdentifier GENERATED_FIRMWARE_IDENTIFIER = {'M', 'E', 'L', 'N'};
+ enum BacklightLevel : u8
+ {
+ Low = 0,
+ Medium = 1 << 4,
+ High = 2 << 4,
+ Max = 3 << 4
+ };
-/**
- * @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
+ enum BootMenu : u8
{
- u16 ARM9GUICodeOffset;
- u16 ARM7WifiCodeOffset;
- u16 GUIWifiCodeChecksum;
- u16 BootCodeChecksum;
+ Manual = 0,
+ Autostart = 1 << 6,
+ };
- FirmwareIdentifier Identifier;
+ /**
+ * @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;
- u16 ARM9BootCodeROMAddress;
- u16 ARM9BootCodeRAMAddress;
- u16 ARM7BootCodeRAMAddress;
- u16 ARM7BootCodeROMAddress;
- u16 ShiftAmounts;
- u16 DataGfxRomAddress;
+ FirmwareIdentifier Identifier;
- u8 BuildMinute;
- u8 BuildHour;
- u8 BuildDay;
- u8 BuildMonth;
- u8 BuildYear;
+ u16 ARM9BootCodeROMAddress;
+ u16 ARM9BootCodeRAMAddress;
+ u16 ARM7BootCodeRAMAddress;
+ u16 ARM7BootCodeROMAddress;
+ u16 ShiftAmounts;
+ u16 DataGfxRomAddress;
- FirmwareConsoleType ConsoleType;
+ u8 BuildMinute;
+ u8 BuildHour;
+ u8 BuildDay;
+ u8 BuildMonth;
+ u8 BuildYear;
- u8 Unused0[2];
+ FirmwareConsoleType ConsoleType;
- u16 UserSettingsOffset;
- u8 Unknown0[2];
- u8 Unknown1[2];
- u16 DataGfxChecksum;
- u8 Unused2[2];
+ u8 Unused0[2];
- // Begin wi-fi settings
- u16 WifiConfigChecksum;
- u16 WifiConfigLength;
- u8 Unused1;
- enum WifiVersion WifiVersion;
+ u16 UserSettingsOffset;
+ u8 Unknown0[2];
+ u8 Unknown1[2];
+ u16 DataGfxChecksum;
+ u8 Unused2[2];
- u8 Unused3[6];
+ // Begin wi-fi settings
+ u16 WifiConfigChecksum;
+ u16 WifiConfigLength;
+ u8 Unused1;
+ enum WifiVersion WifiVersion;
- SPI_Firmware::MacAddress MacAddress;
+ u8 Unused3[6];
- u16 EnabledChannels;
+ MacAddress MacAddress;
- u8 Unknown2[2];
+ u16 EnabledChannels;
- enum RFChipType RFChipType;
- u8 RFBitsPerEntry;
- u8 RFEntries;
- u8 Unknown3;
+ u8 Unknown2[2];
- u8 InitialValues[32];
- u8 InitialBBValues[105];
- u8 Unused4;
- union
- {
- struct
- {
- u8 InitialRFValues[36];
- u8 InitialRF56Values[84];
- u8 InitialBB1EValues[14];
- u8 InitialRf9Values[14];
- } Type2Config;
+ enum RFChipType RFChipType;
+ u8 RFBitsPerEntry;
+ u8 RFEntries;
+ u8 Unknown3;
- struct
+ u8 InitialValues[32];
+ u8 InitialBBValues[105];
+ u8 Unused4;
+ union
{
- 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;
+ 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;
};
-
- u8 Unknown4;
- u8 Unused5;
- u8 Unused6[153];
- enum WifiBoard WifiBoard;
- u8 WifiFlash;
- u8 Unused7;
};
-};
-static_assert(sizeof(FirmwareHeader) == 512, "FirmwareHeader should be 512 bytes");
+ 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;
-};
+ 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");
+ static_assert(sizeof(ExtendedUserSettings) == 0x28, "ExtendedUserSettings should be 40 bytes");
-union UserData
-{
- UserData();
- void UpdateChecksum();
- [[nodiscard]] bool ChecksumValid() const
+ union UserData
{
- 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
+ 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;
- }
+ 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 Bytes[256];
+ struct
{
- u8 Unused3[0x8C];
- 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 Unknown0;
- Language ExtendedLanguage; // padded
- u16 SupportedLanguageMask;
- u8 Unused0[0x86];
- u16 Checksum;
- } ExtendedSettings;
+ 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");
+ static_assert(sizeof(UserData) == 256, "UserData should be 256 bytes");
-class Firmware
-{
-public:
/**
* 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<FirmwareHeader*>(FirmwareBuffer); }
- [[nodiscard]] const FirmwareHeader& Header() const { return *reinterpret_cast<const FirmwareHeader*>(FirmwareBuffer); }
+ [[nodiscard]] FirmwareHeader& GetHeader() { return *reinterpret_cast<FirmwareHeader*>(FirmwareBuffer); }
+ [[nodiscard]] const FirmwareHeader& GetHeader() const { return *reinterpret_cast<const FirmwareHeader*>(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<WifiAccessPoint, 3>& AccessPoints() const
+ [[nodiscard]] const std::array<WifiAccessPoint, 3>& GetAccessPoints() const
{
// An std::array is a wrapper around a C array, so this cast is fine.
- return *reinterpret_cast<const std::array<WifiAccessPoint, 3>*>(WifiAccessPointPosition());
+ return *reinterpret_cast<const std::array<WifiAccessPoint, 3>*>(GetWifiAccessPointPosition());
}
- [[nodiscard]] std::array<WifiAccessPoint, 3>& AccessPoints()
+ [[nodiscard]] std::array<WifiAccessPoint, 3>& GetAccessPoints()
{
// An std::array is a wrapper around a C array, so this cast is fine.
- return *reinterpret_cast<std::array<WifiAccessPoint, 3>*>(WifiAccessPointPosition());
+ return *reinterpret_cast<std::array<WifiAccessPoint, 3>*>(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<ExtendedWifiAccessPoint, 3>& ExtendedAccessPoints() const
+ [[nodiscard]] const std::array<ExtendedWifiAccessPoint, 3>& GetExtendedAccessPoints() const
{
// An std::array is a wrapper around a C array, so this cast is fine.
- return *reinterpret_cast<const std::array<ExtendedWifiAccessPoint, 3>*>(ExtendedAccessPointPosition());
+ return *reinterpret_cast<const std::array<ExtendedWifiAccessPoint, 3>*>(GetExtendedAccessPointPosition());
}
- [[nodiscard]] std::array<ExtendedWifiAccessPoint, 3>& ExtendedAccessPoints()
+ [[nodiscard]] std::array<ExtendedWifiAccessPoint, 3>& GetExtendedAccessPoints()
{
// An std::array is a wrapper around a C array, so this cast is fine.
- return *reinterpret_cast<std::array<ExtendedWifiAccessPoint, 3>*>(ExtendedAccessPointPosition());
+ return *reinterpret_cast<std::array<ExtendedWifiAccessPoint, 3>*>(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<union UserData, 2>& UserData() const
+ [[nodiscard]] const std::array<union UserData, 2>& GetUserData() const
{
// An std::array is a wrapper around a C array, so this cast is fine.
- return *reinterpret_cast<const std::array<union UserData, 2>*>(UserDataPosition());
+ return *reinterpret_cast<const std::array<union UserData, 2>*>(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<union UserData, 2>& UserData()
+ [[nodiscard]] std::array<union UserData, 2>& GetUserData()
{
// An std::array is a wrapper around a C array, so this cast is fine.
- return *reinterpret_cast<std::array<union UserData, 2>*>(UserDataPosition());
+ return *reinterpret_cast<std::array<union UserData, 2>*>(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 c5a67ab..7f57c4b 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 252594c..951e1f5 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 89f74e5..033c2fe 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 648ab67..9b4b49c 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<unique_ptr<SPI_Firmware::Firmware>, string> LoadFirmwareFromFile()
+pair<unique_ptr<Firmware>, string> LoadFirmwareFromFile()
{
string loadedpath;
- unique_ptr<SPI_Firmware::Firmware> firmware = nullptr;
+ unique_ptr<Firmware> 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<unique_ptr<SPI_Firmware::Firmware>, string> LoadFirmwareFromFile()
if (f)
{
- firmware = make_unique<SPI_Firmware::Firmware>(f);
+ firmware = make_unique<Firmware>(f);
if (!firmware->Buffer())
{
Log(LogLevel::Warn, "Couldn't read firmware file!\n");
@@ -826,9 +826,8 @@ pair<unique_ptr<SPI_Firmware::Firmware>, string> LoadFirmwareFromFile()
return std::make_pair(std::move(firmware), loadedpath);
}
-pair<unique_ptr<SPI_Firmware::Firmware>, string> GenerateDefaultFirmware()
+pair<unique_ptr<Firmware>, string> GenerateDefaultFirmware()
{
- using namespace SPI_Firmware;
// Construct the default firmware...
string settingspath;
std::unique_ptr<Firmware> firmware = std::make_unique<Firmware>(Config::ConsoleType);
@@ -850,27 +849,27 @@ pair<unique_ptr<SPI_Firmware::Firmware>, 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<unique_ptr<SPI_Firmware::Firmware>, 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<Language>(Config::FirmwareLanguage);
- if (language != Language::Reserved)
+ auto language = static_cast<Firmware::Language>(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<SPI_Firmware::Language>(Config::FirmwareLanguage);
+ settings.Language = static_cast<Firmware::Language>(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> firmware;
string firmwarepath;
@@ -1105,7 +1102,7 @@ bool InstallFirmware()
FirmwareSave = std::make_unique<SaveManager>(firmwarepath);
- return InstallFirmware(std::move(firmware));
+ return NDS::SPI->GetFirmwareMem()->InstallFirmware(std::move(firmware));
}
bool LoadROM(QStringList filepath, bool reset)