Refactor `NDS` and `DSi` to be objects (#1893)
* First crack at refactoring NDS and DSi into objects - Remove all global/`static` variables in `NDS` and related classes - Rely more on virtual dispatch when we need to pick methods at runtime - Pass `NDS&` or `DSi&` to its constituent components where necessary - Introduce some headers or move some definitions to break `#include` cycles * Refactor the frontend to accommodate the core's changes * Move up `SchedList`'s declaration - Move it to before the components are initialized so the `map`s inside are initialized - Fields in C++ are initialized in the order they're declared * Fix a crash when allocating memory * Fix JIT-free builds * Fix GDB-free builds * Fix Linux builds - Explicitly qualify some member types in NDS, since they share the same name as their classes * Remove an unnecessary template argument - This was causing the build to fail on macOS * Fix ARM and Android builds * Rename `Constants.h` to `MemConstants.h` * Add `NDS::IsRunning()` * Use an `#include` guard instead of `#pragma once`
This commit is contained in:
parent
c84cb17462
commit
e973236203
|
@ -29,40 +29,11 @@ namespace melonDS
|
|||
using Platform::Log;
|
||||
using Platform::LogLevel;
|
||||
|
||||
|
||||
AREngine::AREngine()
|
||||
AREngine::AREngine(melonDS::NDS& nds) : NDS(nds)
|
||||
{
|
||||
CodeFile = nullptr;
|
||||
}
|
||||
|
||||
AREngine::~AREngine()
|
||||
{
|
||||
}
|
||||
|
||||
void AREngine::Reset()
|
||||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
{
|
||||
BusRead8 = DSi::ARM7Read8;
|
||||
BusRead16 = DSi::ARM7Read16;
|
||||
BusRead32 = DSi::ARM7Read32;
|
||||
BusWrite8 = DSi::ARM7Write8;
|
||||
BusWrite16 = DSi::ARM7Write16;
|
||||
BusWrite32 = DSi::ARM7Write32;
|
||||
}
|
||||
else
|
||||
{
|
||||
BusRead8 = NDS::ARM7Read8;
|
||||
BusRead16 = NDS::ARM7Read16;
|
||||
BusRead32 = NDS::ARM7Read32;
|
||||
BusWrite8 = NDS::ARM7Write8;
|
||||
BusWrite16 = NDS::ARM7Write16;
|
||||
BusWrite32 = NDS::ARM7Write32;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#define case16(x) \
|
||||
case ((x)+0x00): case ((x)+0x01): case ((x)+0x02): case ((x)+0x03): \
|
||||
case ((x)+0x04): case ((x)+0x05): case ((x)+0x06): case ((x)+0x07): \
|
||||
|
@ -113,15 +84,15 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
switch (op)
|
||||
{
|
||||
case16(0x00): // 32-bit write
|
||||
BusWrite32((a & 0x0FFFFFFF) + offset, b);
|
||||
NDS.ARM7Write32((a & 0x0FFFFFFF) + offset, b);
|
||||
break;
|
||||
|
||||
case16(0x10): // 16-bit write
|
||||
BusWrite16((a & 0x0FFFFFFF) + offset, b & 0xFFFF);
|
||||
NDS.ARM7Write16((a & 0x0FFFFFFF) + offset, b & 0xFFFF);
|
||||
break;
|
||||
|
||||
case16(0x20): // 8-bit write
|
||||
BusWrite8((a & 0x0FFFFFFF) + offset, b & 0xFF);
|
||||
NDS.ARM7Write8((a & 0x0FFFFFFF) + offset, b & 0xFF);
|
||||
break;
|
||||
|
||||
case16(0x30): // IF b > u32[a]
|
||||
|
@ -131,7 +102,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
|
||||
u32 addr = a & 0x0FFFFFFF;
|
||||
if (!addr) addr = offset;
|
||||
u32 chk = BusRead32(addr);
|
||||
u32 chk = NDS.ARM7Read32(addr);
|
||||
|
||||
cond = (b > chk) ? 1:0;
|
||||
}
|
||||
|
@ -144,7 +115,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
|
||||
u32 addr = a & 0x0FFFFFFF;
|
||||
if (!addr) addr = offset;
|
||||
u32 chk = BusRead32(addr);
|
||||
u32 chk = NDS.ARM7Read32(addr);
|
||||
|
||||
cond = (b < chk) ? 1:0;
|
||||
}
|
||||
|
@ -157,7 +128,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
|
||||
u32 addr = a & 0x0FFFFFFF;
|
||||
if (!addr) addr = offset;
|
||||
u32 chk = BusRead32(addr);
|
||||
u32 chk = NDS.ARM7Read32(addr);
|
||||
|
||||
cond = (b == chk) ? 1:0;
|
||||
}
|
||||
|
@ -170,7 +141,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
|
||||
u32 addr = a & 0x0FFFFFFF;
|
||||
if (!addr) addr = offset;
|
||||
u32 chk = BusRead32(addr);
|
||||
u32 chk = NDS.ARM7Read32(addr);
|
||||
|
||||
cond = (b != chk) ? 1:0;
|
||||
}
|
||||
|
@ -183,7 +154,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
|
||||
u32 addr = a & 0x0FFFFFFF;
|
||||
if (!addr) addr = offset;
|
||||
u16 val = BusRead16(addr);
|
||||
u16 val = NDS.ARM7Read16(addr);
|
||||
u16 chk = ~(b >> 16);
|
||||
chk &= val;
|
||||
|
||||
|
@ -198,7 +169,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
|
||||
u32 addr = a & 0x0FFFFFFF;
|
||||
if (!addr) addr = offset;
|
||||
u16 val = BusRead16(addr);
|
||||
u16 val = NDS.ARM7Read16(addr);
|
||||
u16 chk = ~(b >> 16);
|
||||
chk &= val;
|
||||
|
||||
|
@ -213,7 +184,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
|
||||
u32 addr = a & 0x0FFFFFFF;
|
||||
if (!addr) addr = offset;
|
||||
u16 val = BusRead16(addr);
|
||||
u16 val = NDS.ARM7Read16(addr);
|
||||
u16 chk = ~(b >> 16);
|
||||
chk &= val;
|
||||
|
||||
|
@ -228,7 +199,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
|
||||
u32 addr = a & 0x0FFFFFFF;
|
||||
if (!addr) addr = offset;
|
||||
u16 val = BusRead16(addr);
|
||||
u16 val = NDS.ARM7Read16(addr);
|
||||
u16 chk = ~(b >> 16);
|
||||
chk &= val;
|
||||
|
||||
|
@ -237,7 +208,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
break;
|
||||
|
||||
case16(0xB0): // offset = u32[a + offset]
|
||||
offset = BusRead32((a & 0x0FFFFFFF) + offset);
|
||||
offset = NDS.ARM7Read32((a & 0x0FFFFFFF) + offset);
|
||||
break;
|
||||
|
||||
case 0xC0: // FOR 0..b
|
||||
|
@ -274,7 +245,7 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
break;
|
||||
|
||||
case 0xC6: // u32[b] = offset
|
||||
BusWrite32(b, offset);
|
||||
NDS.ARM7Write32(b, offset);
|
||||
break;
|
||||
|
||||
case 0xD0: // ENDIF
|
||||
|
@ -323,30 +294,30 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
break;
|
||||
|
||||
case 0xD6: // u32[b+offset] = datareg / offset += 4
|
||||
BusWrite32(b + offset, datareg);
|
||||
NDS.ARM7Write32(b + offset, datareg);
|
||||
offset += 4;
|
||||
break;
|
||||
|
||||
case 0xD7: // u16[b+offset] = datareg / offset += 2
|
||||
BusWrite16(b + offset, datareg & 0xFFFF);
|
||||
NDS.ARM7Write16(b + offset, datareg & 0xFFFF);
|
||||
offset += 2;
|
||||
break;
|
||||
|
||||
case 0xD8: // u8[b+offset] = datareg / offset += 1
|
||||
BusWrite8(b + offset, datareg & 0xFF);
|
||||
NDS.ARM7Write8(b + offset, datareg & 0xFF);
|
||||
offset += 1;
|
||||
break;
|
||||
|
||||
case 0xD9: // datareg = u32[b+offset]
|
||||
datareg = BusRead32(b + offset);
|
||||
datareg = NDS.ARM7Read32(b + offset);
|
||||
break;
|
||||
|
||||
case 0xDA: // datareg = u16[b+offset]
|
||||
datareg = BusRead16(b + offset);
|
||||
datareg = NDS.ARM7Read16(b + offset);
|
||||
break;
|
||||
|
||||
case 0xDB: // datareg = u8[b+offset]
|
||||
datareg = BusRead8(b + offset);
|
||||
datareg = NDS.ARM7Read8(b + offset);
|
||||
break;
|
||||
|
||||
case 0xDC: // offset += b
|
||||
|
@ -361,8 +332,8 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
u32 bytesleft = b;
|
||||
while (bytesleft >= 8)
|
||||
{
|
||||
BusWrite32(dstaddr, *code++); dstaddr += 4;
|
||||
BusWrite32(dstaddr, *code++); dstaddr += 4;
|
||||
NDS.ARM7Write32(dstaddr, *code++); dstaddr += 4;
|
||||
NDS.ARM7Write32(dstaddr, *code++); dstaddr += 4;
|
||||
bytesleft -= 8;
|
||||
}
|
||||
if (bytesleft > 0)
|
||||
|
@ -371,13 +342,13 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
code += 2;
|
||||
if (bytesleft >= 4)
|
||||
{
|
||||
BusWrite32(dstaddr, *(u32*)leftover); dstaddr += 4;
|
||||
NDS.ARM7Write32(dstaddr, *(u32*)leftover); dstaddr += 4;
|
||||
leftover += 4;
|
||||
bytesleft -= 4;
|
||||
}
|
||||
while (bytesleft > 0)
|
||||
{
|
||||
BusWrite8(dstaddr, *leftover++); dstaddr++;
|
||||
NDS.ARM7Write8(dstaddr, *leftover++); dstaddr++;
|
||||
bytesleft--;
|
||||
}
|
||||
}
|
||||
|
@ -393,14 +364,14 @@ void AREngine::RunCheat(ARCode& arcode)
|
|||
u32 bytesleft = b;
|
||||
while (bytesleft >= 4)
|
||||
{
|
||||
BusWrite32(dstaddr, BusRead32(srcaddr));
|
||||
NDS.ARM7Write32(dstaddr, NDS.ARM7Read32(srcaddr));
|
||||
srcaddr += 4;
|
||||
dstaddr += 4;
|
||||
bytesleft -= 4;
|
||||
}
|
||||
while (bytesleft > 0)
|
||||
{
|
||||
BusWrite8(dstaddr, BusRead8(srcaddr));
|
||||
NDS.ARM7Write8(dstaddr, NDS.ARM7Read8(srcaddr));
|
||||
srcaddr++;
|
||||
dstaddr++;
|
||||
bytesleft--;
|
||||
|
|
|
@ -23,12 +23,11 @@
|
|||
|
||||
namespace melonDS
|
||||
{
|
||||
class NDS;
|
||||
class AREngine
|
||||
{
|
||||
public:
|
||||
AREngine();
|
||||
~AREngine();
|
||||
void Reset();
|
||||
AREngine(melonDS::NDS& nds);
|
||||
|
||||
ARCodeFile* GetCodeFile() { return CodeFile; }
|
||||
void SetCodeFile(ARCodeFile* file) { CodeFile = file; }
|
||||
|
@ -36,15 +35,8 @@ public:
|
|||
void RunCheats();
|
||||
void RunCheat(ARCode& arcode);
|
||||
private:
|
||||
melonDS::NDS& NDS;
|
||||
ARCodeFile* CodeFile; // AR code file - frontend is responsible for managing this
|
||||
|
||||
// TEMPORARY
|
||||
u8 (*BusRead8)(u32 addr);
|
||||
u16 (*BusRead16)(u32 addr);
|
||||
u32 (*BusRead32)(u32 addr);
|
||||
void (*BusWrite8)(u32 addr, u8 val);
|
||||
void (*BusWrite16)(u32 addr, u16 val);
|
||||
void (*BusWrite32)(u32 addr, u32 val);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
345
src/ARM.cpp
345
src/ARM.cpp
|
@ -106,13 +106,12 @@ const u32 ARM::ConditionTable[16] =
|
|||
0x0000 // NE
|
||||
};
|
||||
|
||||
ARM::ARM(u32 num, ARMJIT& jit, melonDS::GPU& gpu) :
|
||||
ARM::ARM(u32 num, melonDS::NDS& nds) :
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
GdbStub(this, Platform::GetConfigInt(num ? Platform::GdbPortARM7 : Platform::GdbPortARM9)),
|
||||
#endif
|
||||
JIT(jit),
|
||||
Num(num), // well uh
|
||||
GPU(gpu)
|
||||
NDS(nds)
|
||||
{
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
if (Platform::GetConfigBool(Platform::GdbEnabled)
|
||||
|
@ -130,14 +129,14 @@ ARM::~ARM()
|
|||
// dorp
|
||||
}
|
||||
|
||||
ARMv5::ARMv5(ARMJIT& jit, melonDS::GPU& gpu) : ARM(0, jit, gpu)
|
||||
ARMv5::ARMv5(melonDS::NDS& nds) : ARM(0, nds)
|
||||
{
|
||||
DTCM = JIT.Memory.GetARM9DTCM();
|
||||
DTCM = NDS.JIT.Memory.GetARM9DTCM();
|
||||
|
||||
PU_Map = PU_PrivMap;
|
||||
}
|
||||
|
||||
ARMv4::ARMv4(ARMJIT& jit, melonDS::GPU& gpu) : ARM(1, jit, gpu)
|
||||
ARMv4::ARMv4(melonDS::NDS& nds) : ARM(1, nds)
|
||||
{
|
||||
//
|
||||
}
|
||||
|
@ -198,56 +197,11 @@ void ARM::Reset()
|
|||
|
||||
void ARMv5::Reset()
|
||||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
{
|
||||
BusRead8 = DSi::ARM9Read8;
|
||||
BusRead16 = DSi::ARM9Read16;
|
||||
BusRead32 = DSi::ARM9Read32;
|
||||
BusWrite8 = DSi::ARM9Write8;
|
||||
BusWrite16 = DSi::ARM9Write16;
|
||||
BusWrite32 = DSi::ARM9Write32;
|
||||
GetMemRegion = DSi::ARM9GetMemRegion;
|
||||
}
|
||||
else
|
||||
{
|
||||
BusRead8 = NDS::ARM9Read8;
|
||||
BusRead16 = NDS::ARM9Read16;
|
||||
BusRead32 = NDS::ARM9Read32;
|
||||
BusWrite8 = NDS::ARM9Write8;
|
||||
BusWrite16 = NDS::ARM9Write16;
|
||||
BusWrite32 = NDS::ARM9Write32;
|
||||
GetMemRegion = NDS::ARM9GetMemRegion;
|
||||
}
|
||||
|
||||
PU_Map = PU_PrivMap;
|
||||
|
||||
ARM::Reset();
|
||||
}
|
||||
|
||||
void ARMv4::Reset()
|
||||
{
|
||||
if (NDS::ConsoleType)
|
||||
{
|
||||
BusRead8 = DSi::ARM7Read8;
|
||||
BusRead16 = DSi::ARM7Read16;
|
||||
BusRead32 = DSi::ARM7Read32;
|
||||
BusWrite8 = DSi::ARM7Write8;
|
||||
BusWrite16 = DSi::ARM7Write16;
|
||||
BusWrite32 = DSi::ARM7Write32;
|
||||
}
|
||||
else
|
||||
{
|
||||
BusRead8 = NDS::ARM7Read8;
|
||||
BusRead16 = NDS::ARM7Read16;
|
||||
BusRead32 = NDS::ARM7Read32;
|
||||
BusWrite8 = NDS::ARM7Write8;
|
||||
BusWrite16 = NDS::ARM7Write16;
|
||||
BusWrite32 = NDS::ARM7Write32;
|
||||
}
|
||||
|
||||
ARM::Reset();
|
||||
}
|
||||
|
||||
|
||||
void ARM::DoSavestate(Savestate* file)
|
||||
{
|
||||
|
@ -270,7 +224,7 @@ void ARM::DoSavestate(Savestate* file)
|
|||
file->VarArray(R_UND, 3*sizeof(u32));
|
||||
file->Var32(&CurInstr);
|
||||
#ifdef JIT_ENABLED
|
||||
if (file->Saving && NDS::EnableJIT)
|
||||
if (file->Saving && NDS.EnableJIT)
|
||||
{
|
||||
// hack, the JIT doesn't really pipeline
|
||||
// but we still want JIT save states to be
|
||||
|
@ -396,7 +350,7 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
|
|||
return;
|
||||
}
|
||||
|
||||
NDS::MonitorARM9Jump(addr);
|
||||
NDS.MonitorARM9Jump(addr);
|
||||
}
|
||||
|
||||
void ARMv4::JumpTo(u32 addr, bool restorecpsr)
|
||||
|
@ -424,7 +378,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr)
|
|||
|
||||
NextInstr[0] = CodeRead16(addr);
|
||||
NextInstr[1] = CodeRead16(addr+2);
|
||||
Cycles += NDS::ARM7MemTimings[CodeCycles][0] + NDS::ARM7MemTimings[CodeCycles][1];
|
||||
Cycles += NDS.ARM7MemTimings[CodeCycles][0] + NDS.ARM7MemTimings[CodeCycles][1];
|
||||
|
||||
CPSR |= 0x20;
|
||||
}
|
||||
|
@ -437,7 +391,7 @@ void ARMv4::JumpTo(u32 addr, bool restorecpsr)
|
|||
|
||||
NextInstr[0] = CodeRead32(addr);
|
||||
NextInstr[1] = CodeRead32(addr+4);
|
||||
Cycles += NDS::ARM7MemTimings[CodeCycles][2] + NDS::ARM7MemTimings[CodeCycles][3];
|
||||
Cycles += NDS.ARM7MemTimings[CodeCycles][2] + NDS.ARM7MemTimings[CodeCycles][3];
|
||||
|
||||
CPSR &= ~0x20;
|
||||
}
|
||||
|
@ -582,8 +536,8 @@ void ARM::TriggerIRQ()
|
|||
// normally, those work by hijacking the ARM7 VBlank handler
|
||||
if (Num == 1)
|
||||
{
|
||||
if ((NDS::IF[1] & NDS::IE[1]) & (1<<NDS::IRQ_VBlank))
|
||||
NDS::AREngine->RunCheats();
|
||||
if ((NDS.IF[1] & NDS.IE[1]) & (1<<IRQ_VBlank))
|
||||
NDS.AREngine.RunCheats();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -601,7 +555,7 @@ void ARMv5::PrefetchAbort()
|
|||
if (!(PU_Map[ExceptionBase>>12] & 0x04))
|
||||
{
|
||||
Log(LogLevel::Error, "!!!!! EXCEPTION REGION NOT EXECUTABLE. THIS IS VERY BAD!!\n");
|
||||
NDS::Stop(Platform::StopReason::BadExceptionRegion);
|
||||
NDS.Stop(Platform::StopReason::BadExceptionRegion);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -639,20 +593,20 @@ void ARMv5::Execute()
|
|||
{
|
||||
Halted = 0;
|
||||
}
|
||||
else if (NDS::HaltInterrupted(0))
|
||||
else if (NDS.HaltInterrupted(0))
|
||||
{
|
||||
Halted = 0;
|
||||
if (NDS::IME[0] & 0x1)
|
||||
if (NDS.IME[0] & 0x1)
|
||||
TriggerIRQ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::ARM9Timestamp = NDS::ARM9Target;
|
||||
NDS.ARM9Timestamp = NDS.ARM9Target;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (NDS::ARM9Timestamp < NDS::ARM9Target)
|
||||
while (NDS.ARM9Timestamp < NDS.ARM9Target)
|
||||
{
|
||||
if (CPSR & 0x20) // THUMB
|
||||
{
|
||||
|
@ -696,9 +650,9 @@ void ARMv5::Execute()
|
|||
// TODO optimize this shit!!!
|
||||
if (Halted)
|
||||
{
|
||||
if (Halted == 1 && NDS::ARM9Timestamp < NDS::ARM9Target)
|
||||
if (Halted == 1 && NDS.ARM9Timestamp < NDS.ARM9Target)
|
||||
{
|
||||
NDS::ARM9Timestamp = NDS::ARM9Target;
|
||||
NDS.ARM9Timestamp = NDS.ARM9Target;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -709,7 +663,7 @@ void ARMv5::Execute()
|
|||
}*/
|
||||
if (IRQ) TriggerIRQ();
|
||||
|
||||
NDS::ARM9Timestamp += Cycles;
|
||||
NDS.ARM9Timestamp += Cycles;
|
||||
Cycles = 0;
|
||||
}
|
||||
|
||||
|
@ -726,37 +680,37 @@ void ARMv5::ExecuteJIT()
|
|||
{
|
||||
Halted = 0;
|
||||
}
|
||||
else if (NDS::HaltInterrupted(0))
|
||||
else if (NDS.HaltInterrupted(0))
|
||||
{
|
||||
Halted = 0;
|
||||
if (NDS::IME[0] & 0x1)
|
||||
if (NDS.IME[0] & 0x1)
|
||||
TriggerIRQ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::ARM9Timestamp = NDS::ARM9Target;
|
||||
NDS.ARM9Timestamp = NDS.ARM9Target;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (NDS::ARM9Timestamp < NDS::ARM9Target)
|
||||
while (NDS.ARM9Timestamp < NDS.ARM9Target)
|
||||
{
|
||||
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
|
||||
|
||||
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
|
||||
&& !JIT.SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
|
||||
&& !NDS.JIT.SetupExecutableRegion(0, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
|
||||
{
|
||||
NDS::ARM9Timestamp = NDS::ARM9Target;
|
||||
NDS.ARM9Timestamp = NDS.ARM9Target;
|
||||
Log(LogLevel::Error, "ARMv5 PC in non executable region %08X\n", R[15]);
|
||||
return;
|
||||
}
|
||||
|
||||
JitBlockEntry block = JIT.LookUpBlock(0, FastBlockLookup,
|
||||
JitBlockEntry block = NDS.JIT.LookUpBlock(0, FastBlockLookup,
|
||||
instrAddr - FastBlockLookupStart, instrAddr);
|
||||
if (block)
|
||||
ARM_Dispatch(this, block);
|
||||
else
|
||||
JIT.CompileBlock(this);
|
||||
NDS.JIT.CompileBlock(this);
|
||||
|
||||
if (StopExecution)
|
||||
{
|
||||
|
@ -766,17 +720,17 @@ void ARMv5::ExecuteJIT()
|
|||
|
||||
if (Halted || IdleLoop)
|
||||
{
|
||||
if ((Halted == 1 || IdleLoop) && NDS::ARM9Timestamp < NDS::ARM9Target)
|
||||
if ((Halted == 1 || IdleLoop) && NDS.ARM9Timestamp < NDS.ARM9Target)
|
||||
{
|
||||
Cycles = 0;
|
||||
NDS::ARM9Timestamp = NDS::ARM9Target;
|
||||
NDS.ARM9Timestamp = NDS.ARM9Target;
|
||||
}
|
||||
IdleLoop = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NDS::ARM9Timestamp += Cycles;
|
||||
NDS.ARM9Timestamp += Cycles;
|
||||
Cycles = 0;
|
||||
}
|
||||
|
||||
|
@ -795,20 +749,20 @@ void ARMv4::Execute()
|
|||
{
|
||||
Halted = 0;
|
||||
}
|
||||
else if (NDS::HaltInterrupted(1))
|
||||
else if (NDS.HaltInterrupted(1))
|
||||
{
|
||||
Halted = 0;
|
||||
if (NDS::IME[1] & 0x1)
|
||||
if (NDS.IME[1] & 0x1)
|
||||
TriggerIRQ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::ARM7Timestamp = NDS::ARM7Target;
|
||||
NDS.ARM7Timestamp = NDS.ARM7Target;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (NDS::ARM7Timestamp < NDS::ARM7Target)
|
||||
while (NDS.ARM7Timestamp < NDS.ARM7Target)
|
||||
{
|
||||
if (CPSR & 0x20) // THUMB
|
||||
{
|
||||
|
@ -847,9 +801,9 @@ void ARMv4::Execute()
|
|||
// TODO optimize this shit!!!
|
||||
if (Halted)
|
||||
{
|
||||
if (Halted == 1 && NDS::ARM7Timestamp < NDS::ARM7Target)
|
||||
if (Halted == 1 && NDS.ARM7Timestamp < NDS.ARM7Target)
|
||||
{
|
||||
NDS::ARM7Timestamp = NDS::ARM7Target;
|
||||
NDS.ARM7Timestamp = NDS.ARM7Target;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -860,7 +814,7 @@ void ARMv4::Execute()
|
|||
}*/
|
||||
if (IRQ) TriggerIRQ();
|
||||
|
||||
NDS::ARM7Timestamp += Cycles;
|
||||
NDS.ARM7Timestamp += Cycles;
|
||||
Cycles = 0;
|
||||
}
|
||||
|
||||
|
@ -869,7 +823,9 @@ void ARMv4::Execute()
|
|||
|
||||
if (Halted == 4)
|
||||
{
|
||||
DSi::SoftReset();
|
||||
assert(NDS.ConsoleType == 1);
|
||||
auto& dsi = dynamic_cast<melonDS::DSi&>(NDS);
|
||||
dsi.SoftReset();
|
||||
Halted = 2;
|
||||
}
|
||||
}
|
||||
|
@ -883,37 +839,37 @@ void ARMv4::ExecuteJIT()
|
|||
{
|
||||
Halted = 0;
|
||||
}
|
||||
else if (NDS::HaltInterrupted(1))
|
||||
else if (NDS.HaltInterrupted(1))
|
||||
{
|
||||
Halted = 0;
|
||||
if (NDS::IME[1] & 0x1)
|
||||
if (NDS.IME[1] & 0x1)
|
||||
TriggerIRQ();
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::ARM7Timestamp = NDS::ARM7Target;
|
||||
NDS.ARM7Timestamp = NDS.ARM7Target;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (NDS::ARM7Timestamp < NDS::ARM7Target)
|
||||
while (NDS.ARM7Timestamp < NDS.ARM7Target)
|
||||
{
|
||||
u32 instrAddr = R[15] - ((CPSR&0x20)?2:4);
|
||||
|
||||
if ((instrAddr < FastBlockLookupStart || instrAddr >= (FastBlockLookupStart + FastBlockLookupSize))
|
||||
&& !JIT.SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
|
||||
&& !NDS.JIT.SetupExecutableRegion(1, instrAddr, FastBlockLookup, FastBlockLookupStart, FastBlockLookupSize))
|
||||
{
|
||||
NDS::ARM7Timestamp = NDS::ARM7Target;
|
||||
NDS.ARM7Timestamp = NDS.ARM7Target;
|
||||
Log(LogLevel::Error, "ARMv4 PC in non executable region %08X\n", R[15]);
|
||||
return;
|
||||
}
|
||||
|
||||
JitBlockEntry block = JIT.LookUpBlock(1, FastBlockLookup,
|
||||
JitBlockEntry block = NDS.JIT.LookUpBlock(1, FastBlockLookup,
|
||||
instrAddr - FastBlockLookupStart, instrAddr);
|
||||
if (block)
|
||||
ARM_Dispatch(this, block);
|
||||
else
|
||||
JIT.CompileBlock(this);
|
||||
NDS.JIT.CompileBlock(this);
|
||||
|
||||
if (StopExecution)
|
||||
{
|
||||
|
@ -922,17 +878,17 @@ void ARMv4::ExecuteJIT()
|
|||
|
||||
if (Halted || IdleLoop)
|
||||
{
|
||||
if ((Halted == 1 || IdleLoop) && NDS::ARM7Timestamp < NDS::ARM7Target)
|
||||
if ((Halted == 1 || IdleLoop) && NDS.ARM7Timestamp < NDS.ARM7Target)
|
||||
{
|
||||
Cycles = 0;
|
||||
NDS::ARM7Timestamp = NDS::ARM7Target;
|
||||
NDS.ARM7Timestamp = NDS.ARM7Target;
|
||||
}
|
||||
IdleLoop = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NDS::ARM7Timestamp += Cycles;
|
||||
NDS.ARM7Timestamp += Cycles;
|
||||
Cycles = 0;
|
||||
}
|
||||
|
||||
|
@ -941,7 +897,9 @@ void ARMv4::ExecuteJIT()
|
|||
|
||||
if (Halted == 4)
|
||||
{
|
||||
DSi::SoftReset();
|
||||
assert(NDS.ConsoleType == 1);
|
||||
auto& dsi = dynamic_cast<melonDS::DSi&>(NDS);
|
||||
dsi.SoftReset();
|
||||
Halted = 2;
|
||||
}
|
||||
}
|
||||
|
@ -1136,8 +1094,8 @@ void ARM::WriteMem(u32 addr, int size, u32 v)
|
|||
|
||||
void ARM::ResetGdb()
|
||||
{
|
||||
NDS::Reset();
|
||||
GPU.StartFrame(); // need this to properly kick off the scheduler & frame output
|
||||
NDS.Reset();
|
||||
NDS.GPU.StartFrame(); // need this to properly kick off the scheduler & frame output
|
||||
}
|
||||
int ARM::RemoteCmd(const u8* cmd, size_t len)
|
||||
{
|
||||
|
@ -1193,6 +1151,195 @@ u32 ARMv5::ReadMem(u32 addr, int size)
|
|||
|
||||
return ARM::ReadMem(addr, size);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ARMv4::DataRead8(u32 addr, u32* val)
|
||||
{
|
||||
*val = BusRead8(addr);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS.ARM7MemTimings[addr >> 15][0];
|
||||
}
|
||||
|
||||
void ARMv4::DataRead16(u32 addr, u32* val)
|
||||
{
|
||||
addr &= ~1;
|
||||
|
||||
*val = BusRead16(addr);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS.ARM7MemTimings[addr >> 15][0];
|
||||
}
|
||||
|
||||
void ARMv4::DataRead32(u32 addr, u32* val)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
*val = BusRead32(addr);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS.ARM7MemTimings[addr >> 15][2];
|
||||
}
|
||||
|
||||
void ARMv4::DataRead32S(u32 addr, u32* val)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
*val = BusRead32(addr);
|
||||
DataCycles += NDS.ARM7MemTimings[addr >> 15][3];
|
||||
}
|
||||
|
||||
void ARMv4::DataWrite8(u32 addr, u8 val)
|
||||
{
|
||||
BusWrite8(addr, val);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS.ARM7MemTimings[addr >> 15][0];
|
||||
}
|
||||
|
||||
void ARMv4::DataWrite16(u32 addr, u16 val)
|
||||
{
|
||||
addr &= ~1;
|
||||
|
||||
BusWrite16(addr, val);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS.ARM7MemTimings[addr >> 15][0];
|
||||
}
|
||||
|
||||
void ARMv4::DataWrite32(u32 addr, u32 val)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
BusWrite32(addr, val);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS.ARM7MemTimings[addr >> 15][2];
|
||||
}
|
||||
|
||||
void ARMv4::DataWrite32S(u32 addr, u32 val)
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
BusWrite32(addr, val);
|
||||
DataCycles += NDS.ARM7MemTimings[addr >> 15][3];
|
||||
}
|
||||
|
||||
|
||||
void ARMv4::AddCycles_C()
|
||||
{
|
||||
// code only. this code fetch is sequential.
|
||||
Cycles += NDS.ARM7MemTimings[CodeCycles][(CPSR&0x20)?1:3];
|
||||
}
|
||||
|
||||
void ARMv4::AddCycles_CI(s32 num)
|
||||
{
|
||||
// code+internal. results in a nonseq code fetch.
|
||||
Cycles += NDS.ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2] + num;
|
||||
}
|
||||
|
||||
void ARMv4::AddCycles_CDI()
|
||||
{
|
||||
// LDR/LDM cycles.
|
||||
s32 numC = NDS.ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2];
|
||||
s32 numD = DataCycles;
|
||||
|
||||
if ((DataRegion >> 24) == 0x02) // mainRAM
|
||||
{
|
||||
if (CodeRegion == 0x02)
|
||||
Cycles += numC + numD;
|
||||
else
|
||||
{
|
||||
numC++;
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
}
|
||||
else if (CodeRegion == 0x02)
|
||||
{
|
||||
numD++;
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else
|
||||
{
|
||||
Cycles += numC + numD + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv4::AddCycles_CD()
|
||||
{
|
||||
// TODO: max gain should be 5c when writing to mainRAM
|
||||
s32 numC = NDS.ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2];
|
||||
s32 numD = DataCycles;
|
||||
|
||||
if ((DataRegion >> 24) == 0x02)
|
||||
{
|
||||
if (CodeRegion == 0x02)
|
||||
Cycles += numC + numD;
|
||||
else
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else if (CodeRegion == 0x02)
|
||||
{
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else
|
||||
{
|
||||
Cycles += numC + numD;
|
||||
}
|
||||
}
|
||||
|
||||
u8 ARMv5::BusRead8(u32 addr)
|
||||
{
|
||||
return NDS.ARM9Read8(addr);
|
||||
}
|
||||
|
||||
u16 ARMv5::BusRead16(u32 addr)
|
||||
{
|
||||
return NDS.ARM9Read16(addr);
|
||||
}
|
||||
|
||||
u32 ARMv5::BusRead32(u32 addr)
|
||||
{
|
||||
return NDS.ARM9Read32(addr);
|
||||
}
|
||||
|
||||
void ARMv5::BusWrite8(u32 addr, u8 val)
|
||||
{
|
||||
NDS.ARM9Write8(addr, val);
|
||||
}
|
||||
|
||||
void ARMv5::BusWrite16(u32 addr, u16 val)
|
||||
{
|
||||
NDS.ARM9Write16(addr, val);
|
||||
}
|
||||
|
||||
void ARMv5::BusWrite32(u32 addr, u32 val)
|
||||
{
|
||||
NDS.ARM9Write32(addr, val);
|
||||
}
|
||||
|
||||
u8 ARMv4::BusRead8(u32 addr)
|
||||
{
|
||||
return NDS.ARM7Read8(addr);
|
||||
}
|
||||
|
||||
u16 ARMv4::BusRead16(u32 addr)
|
||||
{
|
||||
return NDS.ARM7Read16(addr);
|
||||
}
|
||||
|
||||
u32 ARMv4::BusRead32(u32 addr)
|
||||
{
|
||||
return NDS.ARM7Read32(addr);
|
||||
}
|
||||
|
||||
void ARMv4::BusWrite8(u32 addr, u8 val)
|
||||
{
|
||||
NDS.ARM7Write8(addr, val);
|
||||
}
|
||||
|
||||
void ARMv4::BusWrite16(u32 addr, u16 val)
|
||||
{
|
||||
NDS.ARM7Write16(addr, val);
|
||||
}
|
||||
|
||||
void ARMv4::BusWrite32(u32 addr, u32 val)
|
||||
{
|
||||
NDS.ARM7Write32(addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
199
src/ARM.h
199
src/ARM.h
|
@ -22,7 +22,7 @@
|
|||
#include <algorithm>
|
||||
|
||||
#include "types.h"
|
||||
#include "NDS.h"
|
||||
#include "MemRegion.h"
|
||||
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
#include "debug/GdbStub.h"
|
||||
|
@ -48,6 +48,8 @@ const u32 DTCMPhysicalSize = 0x4000;
|
|||
class ARMJIT;
|
||||
class GPU;
|
||||
class ARMJIT_Memory;
|
||||
class NDS;
|
||||
class Savestate;
|
||||
|
||||
class ARM
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
|
@ -55,7 +57,7 @@ class ARM
|
|||
#endif
|
||||
{
|
||||
public:
|
||||
ARM(u32 num, ARMJIT& jit, GPU& gpu);
|
||||
ARM(u32 num, NDS& nds);
|
||||
virtual ~ARM(); // destroy shit
|
||||
|
||||
virtual void Reset();
|
||||
|
@ -73,6 +75,7 @@ public:
|
|||
Halted = halt;
|
||||
}
|
||||
|
||||
void NocashPrint(u32 addr) noexcept;
|
||||
virtual void Execute() = 0;
|
||||
#ifdef JIT_ENABLED
|
||||
virtual void ExecuteJIT() = 0;
|
||||
|
@ -174,7 +177,7 @@ public:
|
|||
|
||||
u32 ExceptionBase;
|
||||
|
||||
NDS::MemRegion CodeMem;
|
||||
MemRegion CodeMem;
|
||||
|
||||
#ifdef JIT_ENABLED
|
||||
u32 FastBlockLookupStart, FastBlockLookupSize;
|
||||
|
@ -186,14 +189,14 @@ public:
|
|||
Gdb::GdbStub GdbStub;
|
||||
#endif
|
||||
|
||||
ARMJIT& JIT;
|
||||
melonDS::NDS& NDS;
|
||||
protected:
|
||||
u8 (*BusRead8)(u32 addr);
|
||||
u16 (*BusRead16)(u32 addr);
|
||||
u32 (*BusRead32)(u32 addr);
|
||||
void (*BusWrite8)(u32 addr, u8 val);
|
||||
void (*BusWrite16)(u32 addr, u16 val);
|
||||
void (*BusWrite32)(u32 addr, u32 val);
|
||||
virtual u8 BusRead8(u32 addr) = 0;
|
||||
virtual u16 BusRead16(u32 addr) = 0;
|
||||
virtual u32 BusRead32(u32 addr) = 0;
|
||||
virtual void BusWrite8(u32 addr, u8 val) = 0;
|
||||
virtual void BusWrite16(u32 addr, u16 val) = 0;
|
||||
virtual void BusWrite32(u32 addr, u32 val) = 0;
|
||||
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
bool IsSingleStep;
|
||||
|
@ -217,14 +220,12 @@ protected:
|
|||
void GdbCheckA();
|
||||
void GdbCheckB();
|
||||
void GdbCheckC();
|
||||
private:
|
||||
melonDS::GPU& GPU;
|
||||
};
|
||||
|
||||
class ARMv5 : public ARM
|
||||
{
|
||||
public:
|
||||
ARMv5(ARMJIT& jit, melonDS::GPU& gpu);
|
||||
ARMv5(melonDS::NDS& nds);
|
||||
~ARMv5();
|
||||
|
||||
void Reset() override;
|
||||
|
@ -296,7 +297,7 @@ public:
|
|||
// Cycles += numC + numD;
|
||||
}
|
||||
|
||||
void GetCodeMemRegion(u32 addr, NDS::MemRegion* region);
|
||||
void GetCodeMemRegion(u32 addr, MemRegion* region);
|
||||
|
||||
void CP15Reset();
|
||||
void CP15DoSavestate(Savestate* file);
|
||||
|
@ -357,20 +358,26 @@ public:
|
|||
|
||||
u8* CurICacheLine;
|
||||
|
||||
bool (*GetMemRegion)(u32 addr, bool write, NDS::MemRegion* region);
|
||||
bool (*GetMemRegion)(u32 addr, bool write, MemRegion* region);
|
||||
|
||||
#ifdef GDBSTUB_ENABLED
|
||||
u32 ReadMem(u32 addr, int size) override;
|
||||
void WriteMem(u32 addr, int size, u32 v) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
u8 BusRead8(u32 addr) override;
|
||||
u16 BusRead16(u32 addr) override;
|
||||
u32 BusRead32(u32 addr) override;
|
||||
void BusWrite8(u32 addr, u8 val) override;
|
||||
void BusWrite16(u32 addr, u16 val) override;
|
||||
void BusWrite32(u32 addr, u32 val) override;
|
||||
};
|
||||
|
||||
class ARMv4 : public ARM
|
||||
{
|
||||
public:
|
||||
ARMv4(ARMJIT& jit, melonDS::GPU& gpu);
|
||||
|
||||
void Reset() override;
|
||||
ARMv4(melonDS::NDS& nds);
|
||||
|
||||
void FillPipeline() override;
|
||||
|
||||
|
@ -391,134 +398,25 @@ public:
|
|||
return BusRead32(addr);
|
||||
}
|
||||
|
||||
void DataRead8(u32 addr, u32* val) override
|
||||
{
|
||||
*val = BusRead8(addr);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS::ARM7MemTimings[addr >> 15][0];
|
||||
}
|
||||
|
||||
void DataRead16(u32 addr, u32* val) override
|
||||
{
|
||||
addr &= ~1;
|
||||
|
||||
*val = BusRead16(addr);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS::ARM7MemTimings[addr >> 15][0];
|
||||
}
|
||||
|
||||
void DataRead32(u32 addr, u32* val) override
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
*val = BusRead32(addr);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS::ARM7MemTimings[addr >> 15][2];
|
||||
}
|
||||
|
||||
void DataRead32S(u32 addr, u32* val) override
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
*val = BusRead32(addr);
|
||||
DataCycles += NDS::ARM7MemTimings[addr >> 15][3];
|
||||
}
|
||||
|
||||
void DataWrite8(u32 addr, u8 val) override
|
||||
{
|
||||
BusWrite8(addr, val);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS::ARM7MemTimings[addr >> 15][0];
|
||||
}
|
||||
|
||||
void DataWrite16(u32 addr, u16 val) override
|
||||
{
|
||||
addr &= ~1;
|
||||
|
||||
BusWrite16(addr, val);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS::ARM7MemTimings[addr >> 15][0];
|
||||
}
|
||||
|
||||
void DataWrite32(u32 addr, u32 val) override
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
BusWrite32(addr, val);
|
||||
DataRegion = addr;
|
||||
DataCycles = NDS::ARM7MemTimings[addr >> 15][2];
|
||||
}
|
||||
|
||||
void DataWrite32S(u32 addr, u32 val) override
|
||||
{
|
||||
addr &= ~3;
|
||||
|
||||
BusWrite32(addr, val);
|
||||
DataCycles += NDS::ARM7MemTimings[addr >> 15][3];
|
||||
}
|
||||
|
||||
|
||||
void AddCycles_C() override
|
||||
{
|
||||
// code only. this code fetch is sequential.
|
||||
Cycles += NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?1:3];
|
||||
}
|
||||
|
||||
void AddCycles_CI(s32 num) override
|
||||
{
|
||||
// code+internal. results in a nonseq code fetch.
|
||||
Cycles += NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2] + num;
|
||||
}
|
||||
|
||||
void AddCycles_CDI() override
|
||||
{
|
||||
// LDR/LDM cycles.
|
||||
s32 numC = NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2];
|
||||
s32 numD = DataCycles;
|
||||
|
||||
if ((DataRegion >> 24) == 0x02) // mainRAM
|
||||
{
|
||||
if (CodeRegion == 0x02)
|
||||
Cycles += numC + numD;
|
||||
else
|
||||
{
|
||||
numC++;
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
}
|
||||
else if (CodeRegion == 0x02)
|
||||
{
|
||||
numD++;
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else
|
||||
{
|
||||
Cycles += numC + numD + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void AddCycles_CD() override
|
||||
{
|
||||
// TODO: max gain should be 5c when writing to mainRAM
|
||||
s32 numC = NDS::ARM7MemTimings[CodeCycles][(CPSR&0x20)?0:2];
|
||||
s32 numD = DataCycles;
|
||||
|
||||
if ((DataRegion >> 24) == 0x02)
|
||||
{
|
||||
if (CodeRegion == 0x02)
|
||||
Cycles += numC + numD;
|
||||
else
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else if (CodeRegion == 0x02)
|
||||
{
|
||||
Cycles += std::max(numC + numD - 3, std::max(numC, numD));
|
||||
}
|
||||
else
|
||||
{
|
||||
Cycles += numC + numD;
|
||||
}
|
||||
}
|
||||
void DataRead8(u32 addr, u32* val) override;
|
||||
void DataRead16(u32 addr, u32* val) override;
|
||||
void DataRead32(u32 addr, u32* val) override;
|
||||
void DataRead32S(u32 addr, u32* val) override;
|
||||
void DataWrite8(u32 addr, u8 val) override;
|
||||
void DataWrite16(u32 addr, u16 val) override;
|
||||
void DataWrite32(u32 addr, u32 val) override;
|
||||
void DataWrite32S(u32 addr, u32 val) override;
|
||||
void AddCycles_C() override;
|
||||
void AddCycles_CI(s32 num) override;
|
||||
void AddCycles_CDI() override;
|
||||
void AddCycles_CD() override;
|
||||
protected:
|
||||
u8 BusRead8(u32 addr) override;
|
||||
u16 BusRead16(u32 addr) override;
|
||||
u32 BusRead32(u32 addr) override;
|
||||
void BusWrite8(u32 addr, u8 val) override;
|
||||
void BusWrite16(u32 addr, u16 val) override;
|
||||
void BusWrite32(u32 addr, u32 val) override;
|
||||
};
|
||||
|
||||
namespace ARMInterpreter
|
||||
|
@ -528,14 +426,5 @@ void A_UNK(ARM* cpu);
|
|||
void T_UNK(ARM* cpu);
|
||||
|
||||
}
|
||||
|
||||
namespace NDS
|
||||
{
|
||||
|
||||
extern ARMv5* ARM9;
|
||||
extern ARMv4* ARM7;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
#endif // ARM_H
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include "ARM.h"
|
||||
#include "NDS.h"
|
||||
|
||||
namespace melonDS::ARMInterpreter
|
||||
{
|
||||
|
@ -692,7 +693,7 @@ void A_MOV_REG_LSL_IMM_DBG(ARM* cpu)
|
|||
// but since they serve no purpose ATTOW, we can skip them
|
||||
u32 addr = cpu->R[15] + 4; // Skip 2nd ID and flags
|
||||
// TODO: Pass flags to NocashPrint
|
||||
NDS::NocashPrint(cpu->Num, addr);
|
||||
cpu->NDS.NocashPrint(cpu->Num, addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1561,7 +1562,7 @@ void T_MOV_HIREG(ARM* cpu)
|
|||
// but since they serve no purpose ATTOW, we can skip them
|
||||
u32 addr = cpu->R[15] + 4; // Skip 2nd ID and flags
|
||||
// TODO: Pass flags to NocashPrint
|
||||
NDS::NocashPrint(cpu->Num, addr);
|
||||
cpu->NDS.NocashPrint(cpu->Num, addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -64,20 +64,20 @@ const u32 CodeRegionSizes[ARMJIT_Memory::memregions_Count] =
|
|||
ITCMPhysicalSize,
|
||||
0,
|
||||
sizeof(NDS::ARM9BIOS),
|
||||
NDS::MainRAMMaxSize,
|
||||
NDS::SharedWRAMSize,
|
||||
MainRAMMaxSize,
|
||||
SharedWRAMSize,
|
||||
0,
|
||||
0x100000,
|
||||
sizeof(NDS::ARM7BIOS),
|
||||
NDS::ARM7WRAMSize,
|
||||
ARM7WRAMSize,
|
||||
0,
|
||||
0,
|
||||
0x40000,
|
||||
0x10000,
|
||||
0x10000,
|
||||
DSi::NWRAMSize,
|
||||
DSi::NWRAMSize,
|
||||
DSi::NWRAMSize,
|
||||
NWRAMSize,
|
||||
NWRAMSize,
|
||||
NWRAMSize,
|
||||
};
|
||||
|
||||
u32 ARMJIT::LocaliseCodeAddress(u32 num, u32 addr) const noexcept
|
||||
|
@ -103,11 +103,11 @@ T SlowRead9(u32 addr, ARMv5* cpu)
|
|||
else if ((addr & cpu->DTCMMask) == cpu->DTCMBase)
|
||||
val = *(T*)&cpu->DTCM[addr & 0x3FFF];
|
||||
else if (std::is_same<T, u32>::value)
|
||||
val = (ConsoleType == 0 ? NDS::ARM9Read32 : DSi::ARM9Read32)(addr);
|
||||
val = NDS::Current->ARM9Read32(addr);
|
||||
else if (std::is_same<T, u16>::value)
|
||||
val = (ConsoleType == 0 ? NDS::ARM9Read16 : DSi::ARM9Read16)(addr);
|
||||
val = NDS::Current->ARM9Read16(addr);
|
||||
else
|
||||
val = (ConsoleType == 0 ? NDS::ARM9Read8 : DSi::ARM9Read8)(addr);
|
||||
val = NDS::Current->ARM9Read8(addr);
|
||||
|
||||
if (std::is_same<T, u32>::value)
|
||||
return ROR(val, offset << 3);
|
||||
|
@ -123,11 +123,11 @@ T SlowRead7(u32 addr)
|
|||
|
||||
T val;
|
||||
if (std::is_same<T, u32>::value)
|
||||
val = (ConsoleType == 0 ? NDS::ARM7Read32 : DSi::ARM7Read32)(addr);
|
||||
val = NDS::Current->ARM7Read32(addr);
|
||||
else if (std::is_same<T, u16>::value)
|
||||
val = (ConsoleType == 0 ? NDS::ARM7Read16 : DSi::ARM7Read16)(addr);
|
||||
val = NDS::Current->ARM7Read16(addr);
|
||||
else
|
||||
val = (ConsoleType == 0 ? NDS::ARM7Read8 : DSi::ARM7Read8)(addr);
|
||||
val = NDS::Current->ARM7Read8(addr);
|
||||
|
||||
if (std::is_same<T, u32>::value)
|
||||
return ROR(val, offset << 3);
|
||||
|
@ -142,7 +142,7 @@ void SlowWrite9(u32 addr, ARMv5* cpu, u32 val)
|
|||
|
||||
if (addr < cpu->ITCMSize)
|
||||
{
|
||||
cpu->JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
cpu->NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
*(T*)&cpu->ITCM[addr & 0x7FFF] = val;
|
||||
}
|
||||
else if ((addr & cpu->DTCMMask) == cpu->DTCMBase)
|
||||
|
@ -151,15 +151,15 @@ void SlowWrite9(u32 addr, ARMv5* cpu, u32 val)
|
|||
}
|
||||
else if (std::is_same<T, u32>::value)
|
||||
{
|
||||
(ConsoleType == 0 ? NDS::ARM9Write32 : DSi::ARM9Write32)(addr, val);
|
||||
NDS::Current->ARM9Write32(addr, val);
|
||||
}
|
||||
else if (std::is_same<T, u16>::value)
|
||||
{
|
||||
(ConsoleType == 0 ? NDS::ARM9Write16 : DSi::ARM9Write16)(addr, val);
|
||||
NDS::Current->ARM9Write16(addr, val);
|
||||
}
|
||||
else
|
||||
{
|
||||
(ConsoleType == 0 ? NDS::ARM9Write8 : DSi::ARM9Write8)(addr, val);
|
||||
NDS::Current->ARM9Write8(addr, val);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,11 +169,11 @@ void SlowWrite7(u32 addr, u32 val)
|
|||
addr &= ~(sizeof(T) - 1);
|
||||
|
||||
if (std::is_same<T, u32>::value)
|
||||
(ConsoleType == 0 ? NDS::ARM7Write32 : DSi::ARM7Write32)(addr, val);
|
||||
NDS::Current->ARM7Write32(addr, val);
|
||||
else if (std::is_same<T, u16>::value)
|
||||
(ConsoleType == 0 ? NDS::ARM7Write16 : DSi::ARM7Write16)(addr, val);
|
||||
NDS::Current->ARM7Write16(addr, val);
|
||||
else
|
||||
(ConsoleType == 0 ? NDS::ARM7Write8 : DSi::ARM7Write8)(addr, val);
|
||||
NDS::Current->ARM7Write8(addr, val);
|
||||
}
|
||||
|
||||
template <bool Write, int ConsoleType>
|
||||
|
|
37
src/ARMJIT.h
37
src/ARMJIT.h
|
@ -30,6 +30,7 @@
|
|||
#endif
|
||||
|
||||
#include "ARMJIT_Compiler.h"
|
||||
#include "MemConstants.h"
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
|
@ -39,7 +40,7 @@ class JitBlock;
|
|||
class ARMJIT
|
||||
{
|
||||
public:
|
||||
ARMJIT() noexcept : JITCompiler(*this), Memory(*this) {}
|
||||
ARMJIT(melonDS::NDS& nds) noexcept : NDS(nds), Memory(nds), JITCompiler(nds) {};
|
||||
~ARMJIT() noexcept NOOP_IF_NO_JIT;
|
||||
void InvalidateByAddr(u32) noexcept NOOP_IF_NO_JIT;
|
||||
void CheckAndInvalidateWVRAM(int) noexcept NOOP_IF_NO_JIT;
|
||||
|
@ -72,8 +73,8 @@ public:
|
|||
bool BranchOptimizations = false;
|
||||
bool FastMemory = false;
|
||||
|
||||
melonDS::NDS& NDS;
|
||||
TinyVector<u32> InvalidLiterals {};
|
||||
private:
|
||||
friend class ARMJIT_Memory;
|
||||
void blockSanityCheck(u32 num, u32 blockAddr, JitBlockEntry entry) noexcept;
|
||||
void RetireJitBlock(JitBlock* block) noexcept;
|
||||
|
@ -86,32 +87,32 @@ private:
|
|||
|
||||
|
||||
AddressRange CodeIndexITCM[ITCMPhysicalSize / 512] {};
|
||||
AddressRange CodeIndexMainRAM[NDS::MainRAMMaxSize / 512] {};
|
||||
AddressRange CodeIndexSWRAM[NDS::SharedWRAMSize / 512] {};
|
||||
AddressRange CodeIndexMainRAM[MainRAMMaxSize / 512] {};
|
||||
AddressRange CodeIndexSWRAM[SharedWRAMSize / 512] {};
|
||||
AddressRange CodeIndexVRAM[0x100000 / 512] {};
|
||||
AddressRange CodeIndexARM9BIOS[sizeof(NDS::ARM9BIOS) / 512] {};
|
||||
AddressRange CodeIndexARM7BIOS[sizeof(NDS::ARM7BIOS) / 512] {};
|
||||
AddressRange CodeIndexARM7WRAM[NDS::ARM7WRAMSize / 512] {};
|
||||
AddressRange CodeIndexARM9BIOS[ARM9BIOSSize / 512] {};
|
||||
AddressRange CodeIndexARM7BIOS[ARM7BIOSSize / 512] {};
|
||||
AddressRange CodeIndexARM7WRAM[ARM7WRAMSize / 512] {};
|
||||
AddressRange CodeIndexARM7WVRAM[0x40000 / 512] {};
|
||||
AddressRange CodeIndexBIOS9DSi[0x10000 / 512] {};
|
||||
AddressRange CodeIndexBIOS7DSi[0x10000 / 512] {};
|
||||
AddressRange CodeIndexNWRAM_A[DSi::NWRAMSize / 512] {};
|
||||
AddressRange CodeIndexNWRAM_B[DSi::NWRAMSize / 512] {};
|
||||
AddressRange CodeIndexNWRAM_C[DSi::NWRAMSize / 512] {};
|
||||
AddressRange CodeIndexNWRAM_A[NWRAMSize / 512] {};
|
||||
AddressRange CodeIndexNWRAM_B[NWRAMSize / 512] {};
|
||||
AddressRange CodeIndexNWRAM_C[NWRAMSize / 512] {};
|
||||
|
||||
u64 FastBlockLookupITCM[ITCMPhysicalSize / 2] {};
|
||||
u64 FastBlockLookupMainRAM[NDS::MainRAMMaxSize / 2] {};
|
||||
u64 FastBlockLookupSWRAM[NDS::SharedWRAMSize / 2] {};
|
||||
u64 FastBlockLookupMainRAM[MainRAMMaxSize / 2] {};
|
||||
u64 FastBlockLookupSWRAM[SharedWRAMSize / 2] {};
|
||||
u64 FastBlockLookupVRAM[0x100000 / 2] {};
|
||||
u64 FastBlockLookupARM9BIOS[sizeof(NDS::ARM9BIOS) / 2] {};
|
||||
u64 FastBlockLookupARM7BIOS[sizeof(NDS::ARM7BIOS) / 2] {};
|
||||
u64 FastBlockLookupARM7WRAM[NDS::ARM7WRAMSize / 2] {};
|
||||
u64 FastBlockLookupARM9BIOS[ARM9BIOSSize / 2] {};
|
||||
u64 FastBlockLookupARM7BIOS[ARM7BIOSSize / 2] {};
|
||||
u64 FastBlockLookupARM7WRAM[ARM7WRAMSize / 2] {};
|
||||
u64 FastBlockLookupARM7WVRAM[0x40000 / 2] {};
|
||||
u64 FastBlockLookupBIOS9DSi[0x10000 / 2] {};
|
||||
u64 FastBlockLookupBIOS7DSi[0x10000 / 2] {};
|
||||
u64 FastBlockLookupNWRAM_A[DSi::NWRAMSize / 2] {};
|
||||
u64 FastBlockLookupNWRAM_B[DSi::NWRAMSize / 2] {};
|
||||
u64 FastBlockLookupNWRAM_C[DSi::NWRAMSize / 2] {};
|
||||
u64 FastBlockLookupNWRAM_A[NWRAMSize / 2] {};
|
||||
u64 FastBlockLookupNWRAM_B[NWRAMSize / 2] {};
|
||||
u64 FastBlockLookupNWRAM_C[NWRAMSize / 2] {};
|
||||
|
||||
AddressRange* const CodeMemRegions[ARMJIT_Memory::memregions_Count] =
|
||||
{
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
*/
|
||||
|
||||
#include "ARMJIT_Compiler.h"
|
||||
#include "../NDS.h"
|
||||
|
||||
using namespace Arm64Gen;
|
||||
|
||||
|
@ -132,7 +133,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
u32 compileTimePC = CurCPU->R[15];
|
||||
CurCPU->R[15] = newPC;
|
||||
|
||||
cycles += NDS::ARM7MemTimings[codeCycles][0] + NDS::ARM7MemTimings[codeCycles][1];
|
||||
cycles += NDS.ARM7MemTimings[codeCycles][0] + NDS.ARM7MemTimings[codeCycles][1];
|
||||
|
||||
CurCPU->R[15] = compileTimePC;
|
||||
}
|
||||
|
@ -144,7 +145,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
u32 compileTimePC = CurCPU->R[15];
|
||||
CurCPU->R[15] = newPC;
|
||||
|
||||
cycles += NDS::ARM7MemTimings[codeCycles][2] + NDS::ARM7MemTimings[codeCycles][3];
|
||||
cycles += NDS.ARM7MemTimings[codeCycles][2] + NDS.ARM7MemTimings[codeCycles][3];
|
||||
|
||||
CurCPU->R[15] = compileTimePC;
|
||||
}
|
||||
|
@ -235,7 +236,7 @@ void* Compiler::Gen_JumpTo7(int kind)
|
|||
LSR(W1, W0, 15);
|
||||
STR(INDEX_UNSIGNED, W1, RCPU, offsetof(ARM, CodeCycles));
|
||||
|
||||
MOVP2R(X2, NDS::ARM7MemTimings);
|
||||
MOVP2R(X2, NDS.ARM7MemTimings);
|
||||
LDR(W3, X2, ArithOption(W1, true));
|
||||
|
||||
FixupBranch switchToThumb;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "../ARMJIT_Internal.h"
|
||||
#include "../ARMInterpreter.h"
|
||||
#include "../ARMJIT.h"
|
||||
#include "../NDS.h"
|
||||
|
||||
#if defined(__SWITCH__)
|
||||
#include <switch.h>
|
||||
|
@ -220,7 +221,7 @@ void Compiler::PopRegs(bool saveHiRegs, bool saveRegsToBeChanged)
|
|||
}
|
||||
}
|
||||
|
||||
Compiler::Compiler(ARMJIT& jit) : Arm64Gen::ARM64XEmitter(), JIT(jit)
|
||||
Compiler::Compiler(melonDS::NDS& nds) : Arm64Gen::ARM64XEmitter(), NDS(nds)
|
||||
{
|
||||
#ifdef __SWITCH__
|
||||
JitRWBase = aligned_alloc(0x1000, JitMemSize);
|
||||
|
@ -705,12 +706,12 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
|
|||
if (JitMemMainSize - GetCodeOffset() < 1024 * 16)
|
||||
{
|
||||
Log(LogLevel::Debug, "JIT near memory full, resetting...\n");
|
||||
JIT.ResetBlockCache();
|
||||
NDS.JIT.ResetBlockCache();
|
||||
}
|
||||
if ((JitMemMainSize + JitMemSecondarySize) - OtherCodeRegion < 1024 * 8)
|
||||
{
|
||||
Log(LogLevel::Debug, "JIT far memory full, resetting...\n");
|
||||
JIT.ResetBlockCache();
|
||||
NDS.JIT.ResetBlockCache();
|
||||
}
|
||||
|
||||
JitBlockEntry res = (JitBlockEntry)GetRXPtr();
|
||||
|
@ -723,7 +724,7 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
|
|||
CPSRDirty = false;
|
||||
|
||||
if (hasMemInstr)
|
||||
MOVP2R(RMemBase, Num == 0 ? JIT.Memory.FastMem9Start : JIT.Memory.FastMem7Start);
|
||||
MOVP2R(RMemBase, Num == 0 ? NDS.JIT.Memory.FastMem9Start : NDS.JIT.Memory.FastMem7Start);
|
||||
|
||||
for (int i = 0; i < instrsCount; i++)
|
||||
{
|
||||
|
@ -871,7 +872,7 @@ void Compiler::Reset()
|
|||
void Compiler::Comp_AddCycles_C(bool forceNonConstant)
|
||||
{
|
||||
s32 cycles = Num ?
|
||||
NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 1 : 3]
|
||||
NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 1 : 3]
|
||||
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles);
|
||||
|
||||
if (forceNonConstant)
|
||||
|
@ -885,7 +886,7 @@ void Compiler::Comp_AddCycles_CI(u32 numI)
|
|||
IrregularCycles = true;
|
||||
|
||||
s32 cycles = (Num ?
|
||||
NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
|
||||
NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
|
||||
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles)) + numI;
|
||||
|
||||
if (Thumb || CurInstr.Cond() == 0xE)
|
||||
|
@ -899,7 +900,7 @@ void Compiler::Comp_AddCycles_CI(u32 c, ARM64Reg numI, ArithOption shift)
|
|||
IrregularCycles = true;
|
||||
|
||||
s32 cycles = (Num ?
|
||||
NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
|
||||
NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
|
||||
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles)) + c;
|
||||
|
||||
ADD(RCycles, RCycles, cycles);
|
||||
|
@ -919,7 +920,7 @@ void Compiler::Comp_AddCycles_CDI()
|
|||
|
||||
s32 cycles;
|
||||
|
||||
s32 numC = NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2];
|
||||
s32 numC = NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2];
|
||||
s32 numD = CurInstr.DataCycles;
|
||||
|
||||
if ((CurInstr.DataRegion >> 24) == 0x02) // mainRAM
|
||||
|
@ -964,7 +965,7 @@ void Compiler::Comp_AddCycles_CD()
|
|||
}
|
||||
else
|
||||
{
|
||||
s32 numC = NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2];
|
||||
s32 numC = NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2];
|
||||
s32 numD = CurInstr.DataCycles;
|
||||
|
||||
if ((CurInstr.DataRegion >> 24) == 0x02)
|
||||
|
|
|
@ -96,7 +96,11 @@ class Compiler : public Arm64Gen::ARM64XEmitter
|
|||
public:
|
||||
typedef void (Compiler::*CompileFunc)();
|
||||
|
||||
Compiler(ARMJIT& jit);
|
||||
#ifdef JIT_ENABLED
|
||||
explicit Compiler(melonDS::NDS& nds);
|
||||
#else
|
||||
explicit Compiler(melonDS::NDS& nds) : XEmitter(), NDS(nds) {}
|
||||
#endif
|
||||
~Compiler();
|
||||
|
||||
void PushRegs(bool saveHiRegs, bool saveRegsToBeChanged, bool allowUnload = true);
|
||||
|
@ -242,7 +246,7 @@ public:
|
|||
OtherCodeRegion = offset;
|
||||
}
|
||||
|
||||
ARMJIT& JIT;
|
||||
melonDS::NDS& NDS;
|
||||
ptrdiff_t OtherCodeRegion;
|
||||
|
||||
bool Exit;
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "../ARMJIT.h"
|
||||
|
||||
#include "../ARMJIT_Memory.h"
|
||||
#include "../NDS.h"
|
||||
|
||||
using namespace Arm64Gen;
|
||||
|
||||
|
@ -62,9 +63,9 @@ u8* Compiler::RewriteMemAccess(u8* pc)
|
|||
|
||||
bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
|
||||
{
|
||||
u32 localAddr = JIT.LocaliseCodeAddress(Num, addr);
|
||||
u32 localAddr = NDS.JIT.LocaliseCodeAddress(Num, addr);
|
||||
|
||||
int invalidLiteralIdx = JIT.InvalidLiterals.Find(localAddr);
|
||||
int invalidLiteralIdx = NDS.JIT.InvalidLiterals.Find(localAddr);
|
||||
if (invalidLiteralIdx != -1)
|
||||
{
|
||||
return false;
|
||||
|
@ -111,7 +112,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
|||
if (size == 16)
|
||||
addressMask = ~1;
|
||||
|
||||
if (JIT.LiteralOptimizations && rn == 15 && rd != 15 && offset.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
|
||||
if (NDS.JIT.LiteralOptimizations && rn == 15 && rd != 15 && offset.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
|
||||
{
|
||||
u32 addr = R15 + offset.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
|
||||
|
||||
|
@ -146,7 +147,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
|||
MOV(W0, rnMapped);
|
||||
}
|
||||
|
||||
bool addrIsStatic = JIT.LiteralOptimizations
|
||||
bool addrIsStatic = NDS.JIT.LiteralOptimizations
|
||||
&& RegCache.IsLiteral(rn) && offset.IsImm && !(flags & (memop_Writeback|memop_Post));
|
||||
u32 staticAddress;
|
||||
if (addrIsStatic)
|
||||
|
@ -185,18 +186,18 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
|||
MOV(rnMapped, W0);
|
||||
|
||||
u32 expectedTarget = Num == 0
|
||||
? JIT.Memory.ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
|
||||
: JIT.Memory.ClassifyAddress7(addrIsStatic ? staticAddress : CurInstr.DataRegion);
|
||||
? NDS.JIT.Memory.ClassifyAddress9(addrIsStatic ? staticAddress : CurInstr.DataRegion)
|
||||
: NDS.JIT.Memory.ClassifyAddress7(addrIsStatic ? staticAddress : CurInstr.DataRegion);
|
||||
|
||||
if (JIT.FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || JIT.Memory.IsFastmemCompatible(expectedTarget)))
|
||||
if (NDS.JIT.FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget)))
|
||||
{
|
||||
ptrdiff_t memopStart = GetCodeOffset();
|
||||
LoadStorePatch patch;
|
||||
|
||||
assert((rdMapped >= W8 && rdMapped <= W15) || (rdMapped >= W19 && rdMapped <= W25) || rdMapped == W4);
|
||||
patch.PatchFunc = flags & memop_Store
|
||||
? PatchedStoreFuncs[NDS::ConsoleType][Num][__builtin_ctz(size) - 3][rdMapped]
|
||||
: PatchedLoadFuncs[NDS::ConsoleType][Num][__builtin_ctz(size) - 3][!!(flags & memop_SignExtend)][rdMapped];
|
||||
? PatchedStoreFuncs[NDS.ConsoleType][Num][__builtin_ctz(size) - 3][rdMapped]
|
||||
: PatchedLoadFuncs[NDS.ConsoleType][Num][__builtin_ctz(size) - 3][!!(flags & memop_SignExtend)][rdMapped];
|
||||
|
||||
// take a chance at fastmem
|
||||
if (size > 8)
|
||||
|
@ -225,7 +226,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
|||
{
|
||||
void* func = NULL;
|
||||
if (addrIsStatic)
|
||||
func = JIT.Memory.GetFuncForAddr(CurCPU, staticAddress, flags & memop_Store, size);
|
||||
func = NDS.JIT.Memory.GetFuncForAddr(CurCPU, staticAddress, flags & memop_Store, size);
|
||||
|
||||
PushRegs(false, false);
|
||||
|
||||
|
@ -263,7 +264,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
|||
if (flags & memop_Store)
|
||||
{
|
||||
MOV(W2, rdMapped);
|
||||
switch (size | NDS::ConsoleType)
|
||||
switch (size | NDS.ConsoleType)
|
||||
{
|
||||
case 32: QuickCallFunction(X3, SlowWrite9<u32, 0>); break;
|
||||
case 33: QuickCallFunction(X3, SlowWrite9<u32, 1>); break;
|
||||
|
@ -275,7 +276,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
|||
}
|
||||
else
|
||||
{
|
||||
switch (size | NDS::ConsoleType)
|
||||
switch (size | NDS.ConsoleType)
|
||||
{
|
||||
case 32: QuickCallFunction(X3, SlowRead9<u32, 0>); break;
|
||||
case 33: QuickCallFunction(X3, SlowRead9<u32, 1>); break;
|
||||
|
@ -291,7 +292,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
|||
if (flags & memop_Store)
|
||||
{
|
||||
MOV(W1, rdMapped);
|
||||
switch (size | NDS::ConsoleType)
|
||||
switch (size | NDS.ConsoleType)
|
||||
{
|
||||
case 32: QuickCallFunction(X3, SlowWrite7<u32, 0>); break;
|
||||
case 33: QuickCallFunction(X3, SlowWrite7<u32, 1>); break;
|
||||
|
@ -303,7 +304,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, Op2 offset, int size, int flags)
|
|||
}
|
||||
else
|
||||
{
|
||||
switch (size | NDS::ConsoleType)
|
||||
switch (size | NDS.ConsoleType)
|
||||
{
|
||||
case 32: QuickCallFunction(X3, SlowRead7<u32, 0>); break;
|
||||
case 33: QuickCallFunction(X3, SlowRead7<u32, 1>); break;
|
||||
|
@ -452,7 +453,7 @@ void Compiler::T_Comp_LoadPCRel()
|
|||
u32 offset = ((CurInstr.Instr & 0xFF) << 2);
|
||||
u32 addr = (R15 & ~0x2) + offset;
|
||||
|
||||
if (!JIT.LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
|
||||
if (!NDS.JIT.LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
|
||||
Comp_MemAccess(CurInstr.T_Reg(8), 15, Op2(offset), 32, 0);
|
||||
}
|
||||
|
||||
|
@ -494,11 +495,11 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
|||
Comp_AddCycles_CDI();
|
||||
|
||||
int expectedTarget = Num == 0
|
||||
? JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||
: JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||
? NDS.JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||
: NDS.JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||
|
||||
bool compileFastPath = JIT.FastMemory
|
||||
&& store && !usermode && (CurInstr.Cond() < 0xE || JIT.Memory.IsFastmemCompatible(expectedTarget));
|
||||
bool compileFastPath = NDS.JIT.FastMemory
|
||||
&& store && !usermode && (CurInstr.Cond() < 0xE || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget));
|
||||
|
||||
{
|
||||
s32 offset = decrement
|
||||
|
@ -680,7 +681,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
|||
if (Num == 0)
|
||||
{
|
||||
MOV(X3, RCPU);
|
||||
switch ((u32)store * 2 | NDS::ConsoleType)
|
||||
switch ((u32)store * 2 | NDS.ConsoleType)
|
||||
{
|
||||
case 0: QuickCallFunction(X4, SlowBlockTransfer9<false, 0>); break;
|
||||
case 1: QuickCallFunction(X4, SlowBlockTransfer9<false, 1>); break;
|
||||
|
@ -690,7 +691,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
|||
}
|
||||
else
|
||||
{
|
||||
switch ((u32)store * 2 | NDS::ConsoleType)
|
||||
switch ((u32)store * 2 | NDS.ConsoleType)
|
||||
{
|
||||
case 0: QuickCallFunction(X4, SlowBlockTransfer7<false, 0>); break;
|
||||
case 1: QuickCallFunction(X4, SlowBlockTransfer7<false, 1>); break;
|
||||
|
|
|
@ -159,12 +159,12 @@ LONG ARMJIT_Memory::ExceptionHandler(EXCEPTION_POINTERS* exceptionInfo)
|
|||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
|
||||
u8* curArea = (u8*)(NDS::CurCPU == 0 ? NDS::JIT->Memory.FastMem9Start : NDS::JIT->Memory.FastMem7Start);
|
||||
u8* curArea = (u8*)(NDS::Current->CurCPU == 0 ? NDS::Current->JIT.Memory.FastMem9Start : NDS::Current->JIT.Memory.FastMem7Start);
|
||||
FaultDescription desc {};
|
||||
desc.EmulatedFaultAddr = (u8*)exceptionInfo->ExceptionRecord->ExceptionInformation[1] - curArea;
|
||||
desc.FaultPC = (u8*)exceptionInfo->ContextRecord->CONTEXT_PC;
|
||||
|
||||
if (FaultHandler(desc, *NDS::JIT))
|
||||
if (FaultHandler(desc, *NDS::Current))
|
||||
{
|
||||
exceptionInfo->ContextRecord->CONTEXT_PC = (u64)desc.FaultPC;
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
|
@ -194,12 +194,12 @@ void ARMJIT_Memory::SigsegvHandler(int sig, siginfo_t* info, void* rawContext)
|
|||
ucontext_t* context = (ucontext_t*)rawContext;
|
||||
|
||||
FaultDescription desc {};
|
||||
u8* curArea = (u8*)(NDS::CurCPU == 0 ? NDS::JIT->Memory.FastMem9Start : NDS::JIT->Memory.FastMem7Start);
|
||||
u8* curArea = (u8*)(NDS::Current->CurCPU == 0 ? NDS::Current->JIT.Memory.FastMem9Start : NDS::Current->JIT.Memory.FastMem7Start);
|
||||
|
||||
desc.EmulatedFaultAddr = (u8*)info->si_addr - curArea;
|
||||
desc.FaultPC = (u8*)context->CONTEXT_PC;
|
||||
|
||||
if (FaultHandler(desc, *NDS::JIT))
|
||||
if (FaultHandler(desc, *NDS::Current))
|
||||
{
|
||||
context->CONTEXT_PC = (u64)desc.FaultPC;
|
||||
return;
|
||||
|
@ -319,12 +319,12 @@ void ARMJIT_Memory::SetCodeProtectionRange(u32 addr, u32 size, u32 num, int prot
|
|||
}
|
||||
#endif
|
||||
|
||||
void ARMJIT_Memory::Mapping::Unmap(int region, ARMJIT_Memory& memory) noexcept
|
||||
void ARMJIT_Memory::Mapping::Unmap(int region, melonDS::NDS& nds) noexcept
|
||||
{
|
||||
u32 dtcmStart = NDS::ARM9->DTCMBase;
|
||||
u32 dtcmSize = ~NDS::ARM9->DTCMMask + 1;
|
||||
u32 dtcmStart = nds.ARM9.DTCMBase;
|
||||
u32 dtcmSize = ~nds.ARM9.DTCMMask + 1;
|
||||
bool skipDTCM = Num == 0 && region != memregion_DTCM;
|
||||
u8* statuses = Num == 0 ? memory.MappingStatus9 : memory.MappingStatus7;
|
||||
u8* statuses = Num == 0 ? nds.JIT.Memory.MappingStatus9 : nds.JIT.Memory.MappingStatus7;
|
||||
u32 offset = 0;
|
||||
while (offset < Size)
|
||||
{
|
||||
|
@ -367,20 +367,20 @@ void ARMJIT_Memory::Mapping::Unmap(int region, ARMJIT_Memory& memory) noexcept
|
|||
bool success;
|
||||
if (dtcmStart > Addr)
|
||||
{
|
||||
success = memory.UnmapFromRange(Addr, 0, OffsetsPerRegion[region] + LocalOffset, dtcmStart - Addr);
|
||||
success = nds.JIT.Memory.UnmapFromRange(Addr, 0, OffsetsPerRegion[region] + LocalOffset, dtcmStart - Addr);
|
||||
assert(success);
|
||||
}
|
||||
if (dtcmEnd < Addr + Size)
|
||||
{
|
||||
u32 offset = dtcmStart - Addr + dtcmSize;
|
||||
success = memory.UnmapFromRange(dtcmEnd, 0, OffsetsPerRegion[region] + LocalOffset + offset, Size - offset);
|
||||
success = nds.JIT.Memory.UnmapFromRange(dtcmEnd, 0, OffsetsPerRegion[region] + LocalOffset + offset, Size - offset);
|
||||
assert(success);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
bool succeded = memory.UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
|
||||
bool succeded = nds.JIT.Memory.UnmapFromRange(Addr, Num, OffsetsPerRegion[region] + LocalOffset, Size);
|
||||
assert(succeded);
|
||||
}
|
||||
#endif
|
||||
|
@ -401,7 +401,7 @@ void ARMJIT_Memory::SetCodeProtection(int region, u32 offset, bool protect) noex
|
|||
u32 effectiveAddr = mapping.Addr + (offset - mapping.LocalOffset);
|
||||
if (mapping.Num == 0
|
||||
&& region != memregion_DTCM
|
||||
&& (effectiveAddr & NDS::ARM9->DTCMMask) == NDS::ARM9->DTCMBase)
|
||||
&& (effectiveAddr & NDS.ARM9.DTCMMask) == NDS.ARM9.DTCMBase)
|
||||
continue;
|
||||
|
||||
u8* states = (u8*)(mapping.Num == 0 ? MappingStatus9 : MappingStatus7);
|
||||
|
@ -427,9 +427,9 @@ void ARMJIT_Memory::RemapDTCM(u32 newBase, u32 newSize) noexcept
|
|||
{
|
||||
// this first part could be made more efficient
|
||||
// by unmapping DTCM first and then map the holes
|
||||
u32 oldDTCMBase = NDS::ARM9->DTCMBase;
|
||||
u32 oldDTCMSize = ~NDS::ARM9->DTCMMask + 1;
|
||||
u32 oldDTCMEnd = oldDTCMBase + NDS::ARM9->DTCMMask;
|
||||
u32 oldDTCMBase = NDS.ARM9.DTCMBase;
|
||||
u32 oldDTCMSize = ~NDS.ARM9.DTCMMask + 1;
|
||||
u32 oldDTCMEnd = oldDTCMBase + NDS.ARM9.DTCMMask;
|
||||
|
||||
u32 newEnd = newBase + newSize;
|
||||
|
||||
|
@ -454,7 +454,7 @@ void ARMJIT_Memory::RemapDTCM(u32 newBase, u32 newSize) noexcept
|
|||
|
||||
if (mapping.Num == 0 && overlap)
|
||||
{
|
||||
mapping.Unmap(region, *this);
|
||||
mapping.Unmap(region, NDS);
|
||||
Mappings[region].Remove(i);
|
||||
}
|
||||
else
|
||||
|
@ -466,20 +466,22 @@ void ARMJIT_Memory::RemapDTCM(u32 newBase, u32 newSize) noexcept
|
|||
|
||||
for (int i = 0; i < Mappings[memregion_DTCM].Length; i++)
|
||||
{
|
||||
Mappings[memregion_DTCM][i].Unmap(memregion_DTCM, *this);
|
||||
Mappings[memregion_DTCM][i].Unmap(memregion_DTCM, NDS);
|
||||
}
|
||||
Mappings[memregion_DTCM].Clear();
|
||||
}
|
||||
|
||||
void ARMJIT_Memory::RemapNWRAM(int num) noexcept
|
||||
{
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length;)
|
||||
{
|
||||
Mapping& mapping = Mappings[memregion_SharedWRAM][i];
|
||||
if (DSi::NWRAMStart[mapping.Num][num] < mapping.Addr + mapping.Size
|
||||
&& DSi::NWRAMEnd[mapping.Num][num] > mapping.Addr)
|
||||
if (dsi->NWRAMStart[mapping.Num][num] < mapping.Addr + mapping.Size
|
||||
&& dsi->NWRAMEnd[mapping.Num][num] > mapping.Addr)
|
||||
{
|
||||
mapping.Unmap(memregion_SharedWRAM, *this);
|
||||
mapping.Unmap(memregion_SharedWRAM, NDS);
|
||||
Mappings[memregion_SharedWRAM].Remove(i);
|
||||
}
|
||||
else
|
||||
|
@ -489,7 +491,7 @@ void ARMJIT_Memory::RemapNWRAM(int num) noexcept
|
|||
}
|
||||
for (int i = 0; i < Mappings[memregion_NewSharedWRAM_A + num].Length; i++)
|
||||
{
|
||||
Mappings[memregion_NewSharedWRAM_A + num][i].Unmap(memregion_NewSharedWRAM_A + num, *this);
|
||||
Mappings[memregion_NewSharedWRAM_A + num][i].Unmap(memregion_NewSharedWRAM_A + num, NDS);
|
||||
}
|
||||
Mappings[memregion_NewSharedWRAM_A + num].Clear();
|
||||
}
|
||||
|
@ -502,7 +504,7 @@ void ARMJIT_Memory::RemapSWRAM() noexcept
|
|||
Mapping& mapping = Mappings[memregion_WRAM7][i];
|
||||
if (mapping.Addr + mapping.Size <= 0x03800000)
|
||||
{
|
||||
mapping.Unmap(memregion_WRAM7, *this);
|
||||
mapping.Unmap(memregion_WRAM7, NDS);
|
||||
Mappings[memregion_WRAM7].Remove(i);
|
||||
}
|
||||
else
|
||||
|
@ -510,14 +512,14 @@ void ARMJIT_Memory::RemapSWRAM() noexcept
|
|||
}
|
||||
for (int i = 0; i < Mappings[memregion_SharedWRAM].Length; i++)
|
||||
{
|
||||
Mappings[memregion_SharedWRAM][i].Unmap(memregion_SharedWRAM, *this);
|
||||
Mappings[memregion_SharedWRAM][i].Unmap(memregion_SharedWRAM, NDS);
|
||||
}
|
||||
Mappings[memregion_SharedWRAM].Clear();
|
||||
}
|
||||
|
||||
bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
|
||||
{
|
||||
u32 num = NDS::CurCPU;
|
||||
u32 num = NDS.CurCPU;
|
||||
|
||||
int region = num == 0
|
||||
? ClassifyAddress9(addr)
|
||||
|
@ -533,10 +535,10 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
|
|||
|
||||
u8* states = num == 0 ? MappingStatus9 : MappingStatus7;
|
||||
//printf("mapping mirror %x, %x %x %d %d\n", mirrorStart, mirrorSize, memoryOffset, region, num);
|
||||
bool isExecutable = JIT.CodeMemRegions[region];
|
||||
bool isExecutable = NDS.JIT.CodeMemRegions[region];
|
||||
|
||||
u32 dtcmStart = NDS::ARM9->DTCMBase;
|
||||
u32 dtcmSize = ~NDS::ARM9->DTCMMask + 1;
|
||||
u32 dtcmStart = NDS.ARM9.DTCMBase;
|
||||
u32 dtcmSize = ~NDS.ARM9.DTCMMask + 1;
|
||||
u32 dtcmEnd = dtcmStart + dtcmSize;
|
||||
#ifndef __SWITCH__
|
||||
#ifndef _WIN32
|
||||
|
@ -565,7 +567,7 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
|
|||
}
|
||||
#endif
|
||||
|
||||
AddressRange* range = JIT.CodeMemRegions[region] + memoryOffset / 512;
|
||||
AddressRange* range = NDS.JIT.CodeMemRegions[region] + memoryOffset / 512;
|
||||
|
||||
// this overcomplicated piece of code basically just finds whole pieces of code memory
|
||||
// which can be mapped/protected
|
||||
|
@ -586,7 +588,7 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
|
|||
bool hasCode = isExecutable && PageContainsCode(&range[offset / 512]);
|
||||
while (offset < mirrorSize
|
||||
&& (!isExecutable || PageContainsCode(&range[offset / 512]) == hasCode)
|
||||
&& (!skipDTCM || mirrorStart + offset != NDS::ARM9->DTCMBase))
|
||||
&& (!skipDTCM || mirrorStart + offset != NDS.ARM9.DTCMBase))
|
||||
{
|
||||
assert(states[(mirrorStart + offset) >> 12] == memstate_Unmapped);
|
||||
states[(mirrorStart + offset) >> 12] = hasCode ? memstate_MappedProtected : memstate_MappedRW;
|
||||
|
@ -620,19 +622,19 @@ bool ARMJIT_Memory::MapAtAddress(u32 addr) noexcept
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ARMJIT_Memory::FaultHandler(FaultDescription& faultDesc, ARMJIT& jit)
|
||||
bool ARMJIT_Memory::FaultHandler(FaultDescription& faultDesc, melonDS::NDS& nds)
|
||||
{
|
||||
if (jit.JITCompiler.IsJITFault(faultDesc.FaultPC))
|
||||
if (nds.JIT.JITCompiler.IsJITFault(faultDesc.FaultPC))
|
||||
{
|
||||
bool rewriteToSlowPath = true;
|
||||
|
||||
u8* memStatus = NDS::CurCPU == 0 ? jit.Memory.MappingStatus9 : jit.Memory.MappingStatus7;
|
||||
u8* memStatus = nds.CurCPU == 0 ? nds.JIT.Memory.MappingStatus9 : nds.JIT.Memory.MappingStatus7;
|
||||
|
||||
if (memStatus[faultDesc.EmulatedFaultAddr >> 12] == memstate_Unmapped)
|
||||
rewriteToSlowPath = !jit.Memory.MapAtAddress(faultDesc.EmulatedFaultAddr);
|
||||
rewriteToSlowPath = !nds.JIT.Memory.MapAtAddress(faultDesc.EmulatedFaultAddr);
|
||||
|
||||
if (rewriteToSlowPath)
|
||||
faultDesc.FaultPC = jit.JITCompiler.RewriteMemAccess(faultDesc.FaultPC);
|
||||
faultDesc.FaultPC = nds.JIT.JITCompiler.RewriteMemAccess(faultDesc.FaultPC);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -641,7 +643,7 @@ bool ARMJIT_Memory::FaultHandler(FaultDescription& faultDesc, ARMJIT& jit)
|
|||
|
||||
const u64 AddrSpaceSize = 0x100000000;
|
||||
|
||||
ARMJIT_Memory::ARMJIT_Memory(ARMJIT& jit) noexcept : JIT(jit)
|
||||
ARMJIT_Memory::ARMJIT_Memory(melonDS::NDS& nds) : NDS(nds)
|
||||
{
|
||||
#if defined(__SWITCH__)
|
||||
MemoryBase = (u8*)aligned_alloc(0x1000, MemoryTotalSize);
|
||||
|
@ -815,7 +817,7 @@ void ARMJIT_Memory::Reset() noexcept
|
|||
for (int region = 0; region < memregions_Count; region++)
|
||||
{
|
||||
for (int i = 0; i < Mappings[region].Length; i++)
|
||||
Mappings[region][i].Unmap(region, *this);
|
||||
Mappings[region][i].Unmap(region, NDS);
|
||||
Mappings[region].Clear();
|
||||
}
|
||||
|
||||
|
@ -866,8 +868,8 @@ bool ARMJIT_Memory::GetMirrorLocation(int region, u32 num, u32 addr, u32& memory
|
|||
}
|
||||
return false;
|
||||
case memregion_MainRAM:
|
||||
mirrorStart = addr & ~NDS::MainRAMMask;
|
||||
mirrorSize = NDS::MainRAMMask + 1;
|
||||
mirrorStart = addr & ~NDS.MainRAMMask;
|
||||
mirrorSize = NDS.MainRAMMask + 1;
|
||||
return true;
|
||||
case memregion_BIOS9:
|
||||
if (num == 0)
|
||||
|
@ -886,26 +888,26 @@ bool ARMJIT_Memory::GetMirrorLocation(int region, u32 num, u32 addr, u32& memory
|
|||
}
|
||||
return false;
|
||||
case memregion_SharedWRAM:
|
||||
if (num == 0 && NDS::SWRAM_ARM9.Mem)
|
||||
if (num == 0 && NDS.SWRAM_ARM9.Mem)
|
||||
{
|
||||
mirrorStart = addr & ~NDS::SWRAM_ARM9.Mask;
|
||||
mirrorSize = NDS::SWRAM_ARM9.Mask + 1;
|
||||
memoryOffset = NDS::SWRAM_ARM9.Mem - GetSharedWRAM();
|
||||
mirrorStart = addr & ~NDS.SWRAM_ARM9.Mask;
|
||||
mirrorSize = NDS.SWRAM_ARM9.Mask + 1;
|
||||
memoryOffset = NDS.SWRAM_ARM9.Mem - GetSharedWRAM();
|
||||
return true;
|
||||
}
|
||||
else if (num == 1 && NDS::SWRAM_ARM7.Mem)
|
||||
else if (num == 1 && NDS.SWRAM_ARM7.Mem)
|
||||
{
|
||||
mirrorStart = addr & ~NDS::SWRAM_ARM7.Mask;
|
||||
mirrorSize = NDS::SWRAM_ARM7.Mask + 1;
|
||||
memoryOffset = NDS::SWRAM_ARM7.Mem - GetSharedWRAM();
|
||||
mirrorStart = addr & ~NDS.SWRAM_ARM7.Mask;
|
||||
mirrorSize = NDS.SWRAM_ARM7.Mask + 1;
|
||||
memoryOffset = NDS.SWRAM_ARM7.Mem - GetSharedWRAM();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case memregion_WRAM7:
|
||||
if (num == 1)
|
||||
{
|
||||
mirrorStart = addr & ~(NDS::ARM7WRAMSize - 1);
|
||||
mirrorSize = NDS::ARM7WRAMSize;
|
||||
mirrorStart = addr & ~(ARM7WRAMSize - 1);
|
||||
mirrorSize = ARM7WRAMSize;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -927,7 +929,9 @@ bool ARMJIT_Memory::GetMirrorLocation(int region, u32 num, u32 addr, u32& memory
|
|||
return false;
|
||||
case memregion_NewSharedWRAM_A:
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
u8* ptr = dsi->NWRAMMap_A[num][(addr >> 16) & dsi->NWRAMMask[num][0]];
|
||||
if (ptr)
|
||||
{
|
||||
memoryOffset = ptr - GetNWRAM_A();
|
||||
|
@ -939,7 +943,9 @@ bool ARMJIT_Memory::GetMirrorLocation(int region, u32 num, u32 addr, u32& memory
|
|||
}
|
||||
case memregion_NewSharedWRAM_B:
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
u8* ptr = dsi->NWRAMMap_B[num][(addr >> 15) & dsi->NWRAMMask[num][1]];
|
||||
if (ptr)
|
||||
{
|
||||
memoryOffset = ptr - GetNWRAM_B();
|
||||
|
@ -951,7 +957,9 @@ bool ARMJIT_Memory::GetMirrorLocation(int region, u32 num, u32 addr, u32& memory
|
|||
}
|
||||
case memregion_NewSharedWRAM_C:
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
u8* ptr = dsi->NWRAMMap_C[num][(addr >> 15) & dsi->NWRAMMask[num][2]];
|
||||
if (ptr)
|
||||
{
|
||||
memoryOffset = ptr - GetNWRAM_C();
|
||||
|
@ -964,16 +972,20 @@ bool ARMJIT_Memory::GetMirrorLocation(int region, u32 num, u32 addr, u32& memory
|
|||
case memregion_BIOS9DSi:
|
||||
if (num == 0)
|
||||
{
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
mirrorStart = addr & ~0xFFFF;
|
||||
mirrorSize = DSi::SCFG_BIOS & (1<<0) ? 0x8000 : 0x10000;
|
||||
mirrorSize = dsi->SCFG_BIOS & (1<<0) ? 0x8000 : 0x10000;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
case memregion_BIOS7DSi:
|
||||
if (num == 1)
|
||||
{
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
mirrorStart = addr & ~0xFFFF;
|
||||
mirrorSize = DSi::SCFG_BIOS & (1<<8) ? 0x8000 : 0x10000;
|
||||
mirrorSize = dsi->SCFG_BIOS & (1<<8) ? 0x8000 : 0x10000;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -990,18 +1002,18 @@ u32 ARMJIT_Memory::LocaliseAddress(int region, u32 num, u32 addr) const noexcept
|
|||
case memregion_ITCM:
|
||||
return (addr & (ITCMPhysicalSize - 1)) | (memregion_ITCM << 27);
|
||||
case memregion_MainRAM:
|
||||
return (addr & NDS::MainRAMMask) | (memregion_MainRAM << 27);
|
||||
return (addr & NDS.MainRAMMask) | (memregion_MainRAM << 27);
|
||||
case memregion_BIOS9:
|
||||
return (addr & 0xFFF) | (memregion_BIOS9 << 27);
|
||||
case memregion_BIOS7:
|
||||
return (addr & 0x3FFF) | (memregion_BIOS7 << 27);
|
||||
case memregion_SharedWRAM:
|
||||
if (num == 0)
|
||||
return ((addr & NDS::SWRAM_ARM9.Mask) + (NDS::SWRAM_ARM9.Mem - GetSharedWRAM())) | (memregion_SharedWRAM << 27);
|
||||
return ((addr & NDS.SWRAM_ARM9.Mask) + (NDS.SWRAM_ARM9.Mem - GetSharedWRAM())) | (memregion_SharedWRAM << 27);
|
||||
else
|
||||
return ((addr & NDS::SWRAM_ARM7.Mask) + (NDS::SWRAM_ARM7.Mem - GetSharedWRAM())) | (memregion_SharedWRAM << 27);
|
||||
return ((addr & NDS.SWRAM_ARM7.Mask) + (NDS.SWRAM_ARM7.Mem - GetSharedWRAM())) | (memregion_SharedWRAM << 27);
|
||||
case memregion_WRAM7:
|
||||
return (addr & (NDS::ARM7WRAMSize - 1)) | (memregion_WRAM7 << 27);
|
||||
return (addr & (melonDS::ARM7WRAMSize - 1)) | (memregion_WRAM7 << 27);
|
||||
case memregion_VRAM:
|
||||
// TODO: take mapping properly into account
|
||||
return (addr & 0xFFFFF) | (memregion_VRAM << 27);
|
||||
|
@ -1010,7 +1022,9 @@ u32 ARMJIT_Memory::LocaliseAddress(int region, u32 num, u32 addr) const noexcept
|
|||
return (addr & 0x3FFFF) | (memregion_VWRAM << 27);
|
||||
case memregion_NewSharedWRAM_A:
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_A[num][(addr >> 16) & DSi::NWRAMMask[num][0]];
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
u8* ptr = dsi->NWRAMMap_A[num][(addr >> 16) & dsi->NWRAMMask[num][0]];
|
||||
if (ptr)
|
||||
return (ptr - GetNWRAM_A() + (addr & 0xFFFF)) | (memregion_NewSharedWRAM_A << 27);
|
||||
else
|
||||
|
@ -1018,7 +1032,9 @@ u32 ARMJIT_Memory::LocaliseAddress(int region, u32 num, u32 addr) const noexcept
|
|||
}
|
||||
case memregion_NewSharedWRAM_B:
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_B[num][(addr >> 15) & DSi::NWRAMMask[num][1]];
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
u8* ptr = dsi->NWRAMMap_B[num][(addr >> 15) & dsi->NWRAMMask[num][1]];
|
||||
if (ptr)
|
||||
return (ptr - GetNWRAM_B() + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_B << 27);
|
||||
else
|
||||
|
@ -1026,7 +1042,9 @@ u32 ARMJIT_Memory::LocaliseAddress(int region, u32 num, u32 addr) const noexcept
|
|||
}
|
||||
case memregion_NewSharedWRAM_C:
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_C[num][(addr >> 15) & DSi::NWRAMMask[num][2]];
|
||||
auto* dsi = dynamic_cast<DSi*>(&NDS);
|
||||
assert(dsi != nullptr);
|
||||
u8* ptr = dsi->NWRAMMap_C[num][(addr >> 15) & dsi->NWRAMMask[num][2]];
|
||||
if (ptr)
|
||||
return (ptr - GetNWRAM_C() + (addr & 0x7FFF)) | (memregion_NewSharedWRAM_C << 27);
|
||||
else
|
||||
|
@ -1043,19 +1061,20 @@ u32 ARMJIT_Memory::LocaliseAddress(int region, u32 num, u32 addr) const noexcept
|
|||
|
||||
int ARMJIT_Memory::ClassifyAddress9(u32 addr) const noexcept
|
||||
{
|
||||
if (addr < NDS::ARM9->ITCMSize)
|
||||
if (addr < NDS.ARM9.ITCMSize)
|
||||
{
|
||||
return memregion_ITCM;
|
||||
}
|
||||
else if ((addr & NDS::ARM9->DTCMMask) == NDS::ARM9->DTCMBase)
|
||||
else if ((addr & NDS.ARM9.DTCMMask) == NDS.ARM9.DTCMBase)
|
||||
{
|
||||
return memregion_DTCM;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NDS::ConsoleType == 1 && addr >= 0xFFFF0000 && !(DSi::SCFG_BIOS & (1<<1)))
|
||||
auto& dsi = static_cast<DSi&>(NDS); // ONLY use this if ConsoleType == 1!
|
||||
if (NDS.ConsoleType == 1 && addr >= 0xFFFF0000 && !(dsi.SCFG_BIOS & (1<<1)))
|
||||
{
|
||||
if ((addr >= 0xFFFF8000) && (DSi::SCFG_BIOS & (1<<0)))
|
||||
if ((addr >= 0xFFFF8000) && (dsi.SCFG_BIOS & (1<<0)))
|
||||
return memregion_Other;
|
||||
|
||||
return memregion_BIOS9DSi;
|
||||
|
@ -1070,17 +1089,17 @@ int ARMJIT_Memory::ClassifyAddress9(u32 addr) const noexcept
|
|||
case 0x02000000:
|
||||
return memregion_MainRAM;
|
||||
case 0x03000000:
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (NDS.ConsoleType == 1)
|
||||
{
|
||||
if (addr >= DSi::NWRAMStart[0][0] && addr < DSi::NWRAMEnd[0][0])
|
||||
if (addr >= dsi.NWRAMStart[0][0] && addr < dsi.NWRAMEnd[0][0])
|
||||
return memregion_NewSharedWRAM_A;
|
||||
if (addr >= DSi::NWRAMStart[0][1] && addr < DSi::NWRAMEnd[0][1])
|
||||
if (addr >= dsi.NWRAMStart[0][1] && addr < dsi.NWRAMEnd[0][1])
|
||||
return memregion_NewSharedWRAM_B;
|
||||
if (addr >= DSi::NWRAMStart[0][2] && addr < DSi::NWRAMEnd[0][2])
|
||||
if (addr >= dsi.NWRAMStart[0][2] && addr < dsi.NWRAMEnd[0][2])
|
||||
return memregion_NewSharedWRAM_C;
|
||||
}
|
||||
|
||||
if (NDS::SWRAM_ARM9.Mem)
|
||||
if (NDS.SWRAM_ARM9.Mem)
|
||||
return memregion_SharedWRAM;
|
||||
return memregion_Other;
|
||||
case 0x04000000:
|
||||
|
@ -1088,7 +1107,7 @@ int ARMJIT_Memory::ClassifyAddress9(u32 addr) const noexcept
|
|||
case 0x06000000:
|
||||
return memregion_VRAM;
|
||||
case 0x0C000000:
|
||||
return (NDS::ConsoleType==1) ? memregion_MainRAM : memregion_Other;
|
||||
return (NDS.ConsoleType==1) ? memregion_MainRAM : memregion_Other;
|
||||
default:
|
||||
return memregion_Other;
|
||||
}
|
||||
|
@ -1097,9 +1116,10 @@ int ARMJIT_Memory::ClassifyAddress9(u32 addr) const noexcept
|
|||
|
||||
int ARMJIT_Memory::ClassifyAddress7(u32 addr) const noexcept
|
||||
{
|
||||
if (NDS::ConsoleType == 1 && addr < 0x00010000 && !(DSi::SCFG_BIOS & (1<<9)))
|
||||
auto& dsi = static_cast<DSi&>(NDS);
|
||||
if (NDS.ConsoleType == 1 && addr < 0x00010000 && !(dsi.SCFG_BIOS & (1<<9)))
|
||||
{
|
||||
if (addr >= 0x00008000 && DSi::SCFG_BIOS & (1<<8))
|
||||
if (addr >= 0x00008000 && dsi.SCFG_BIOS & (1<<8))
|
||||
return memregion_Other;
|
||||
|
||||
return memregion_BIOS7DSi;
|
||||
|
@ -1116,17 +1136,17 @@ int ARMJIT_Memory::ClassifyAddress7(u32 addr) const noexcept
|
|||
case 0x02800000:
|
||||
return memregion_MainRAM;
|
||||
case 0x03000000:
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (NDS.ConsoleType == 1)
|
||||
{
|
||||
if (addr >= DSi::NWRAMStart[1][0] && addr < DSi::NWRAMEnd[1][0])
|
||||
if (addr >= dsi.NWRAMStart[1][0] && addr < dsi.NWRAMEnd[1][0])
|
||||
return memregion_NewSharedWRAM_A;
|
||||
if (addr >= DSi::NWRAMStart[1][1] && addr < DSi::NWRAMEnd[1][1])
|
||||
if (addr >= dsi.NWRAMStart[1][1] && addr < dsi.NWRAMEnd[1][1])
|
||||
return memregion_NewSharedWRAM_B;
|
||||
if (addr >= DSi::NWRAMStart[1][2] && addr < DSi::NWRAMEnd[1][2])
|
||||
if (addr >= dsi.NWRAMStart[1][2] && addr < dsi.NWRAMEnd[1][2])
|
||||
return memregion_NewSharedWRAM_C;
|
||||
}
|
||||
|
||||
if (NDS::SWRAM_ARM7.Mem)
|
||||
if (NDS.SWRAM_ARM7.Mem)
|
||||
return memregion_SharedWRAM;
|
||||
return memregion_WRAM7;
|
||||
case 0x03800000:
|
||||
|
@ -1140,7 +1160,7 @@ int ARMJIT_Memory::ClassifyAddress7(u32 addr) const noexcept
|
|||
return memregion_VWRAM;
|
||||
case 0x0C000000:
|
||||
case 0x0C800000:
|
||||
return (NDS::ConsoleType==1) ? memregion_MainRAM : memregion_Other;
|
||||
return (NDS.ConsoleType==1) ? memregion_MainRAM : memregion_Other;
|
||||
default:
|
||||
return memregion_Other;
|
||||
}
|
||||
|
@ -1163,11 +1183,11 @@ void VRAMWrite(u32 addr, T val)
|
|||
{
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: NDS::GPU->WriteVRAM_ABG<T>(addr, val); return;
|
||||
case 0x00200000: NDS::GPU->WriteVRAM_BBG<T>(addr, val); return;
|
||||
case 0x00400000: NDS::GPU->WriteVRAM_AOBJ<T>(addr, val); return;
|
||||
case 0x00600000: NDS::GPU->WriteVRAM_BOBJ<T>(addr, val); return;
|
||||
default: NDS::GPU->WriteVRAM_LCDC<T>(addr, val); return;
|
||||
case 0x00000000: NDS::Current->GPU.WriteVRAM_ABG<T>(addr, val); return;
|
||||
case 0x00200000: NDS::Current->GPU.WriteVRAM_BBG<T>(addr, val); return;
|
||||
case 0x00400000: NDS::Current->GPU.WriteVRAM_AOBJ<T>(addr, val); return;
|
||||
case 0x00600000: NDS::Current->GPU.WriteVRAM_BOBJ<T>(addr, val); return;
|
||||
default: NDS::Current->GPU.WriteVRAM_LCDC<T>(addr, val); return;
|
||||
}
|
||||
}
|
||||
template <typename T>
|
||||
|
@ -1175,59 +1195,119 @@ T VRAMRead(u32 addr)
|
|||
{
|
||||
switch (addr & 0x00E00000)
|
||||
{
|
||||
case 0x00000000: return NDS::GPU->ReadVRAM_ABG<T>(addr);
|
||||
case 0x00200000: return NDS::GPU->ReadVRAM_BBG<T>(addr);
|
||||
case 0x00400000: return NDS::GPU->ReadVRAM_AOBJ<T>(addr);
|
||||
case 0x00600000: return NDS::GPU->ReadVRAM_BOBJ<T>(addr);
|
||||
default: return NDS::GPU->ReadVRAM_LCDC<T>(addr);
|
||||
case 0x00000000: return NDS::Current->GPU.ReadVRAM_ABG<T>(addr);
|
||||
case 0x00200000: return NDS::Current->GPU.ReadVRAM_BBG<T>(addr);
|
||||
case 0x00400000: return NDS::Current->GPU.ReadVRAM_AOBJ<T>(addr);
|
||||
case 0x00600000: return NDS::Current->GPU.ReadVRAM_BOBJ<T>(addr);
|
||||
default: return NDS::Current->GPU.ReadVRAM_LCDC<T>(addr);
|
||||
}
|
||||
}
|
||||
|
||||
static u8 GPU3D_Read8(u32 addr) noexcept
|
||||
{
|
||||
return NDS::GPU->GPU3D.Read8(addr);
|
||||
return NDS::Current->GPU.GPU3D.Read8(addr);
|
||||
}
|
||||
|
||||
static u16 GPU3D_Read16(u32 addr) noexcept
|
||||
{
|
||||
return NDS::GPU->GPU3D.Read16(addr);
|
||||
return NDS::Current->GPU.GPU3D.Read16(addr);
|
||||
}
|
||||
|
||||
static u32 GPU3D_Read32(u32 addr) noexcept
|
||||
{
|
||||
return NDS::GPU->GPU3D.Read32(addr);
|
||||
return NDS::Current->GPU.GPU3D.Read32(addr);
|
||||
}
|
||||
|
||||
static void GPU3D_Write8(u32 addr, u8 val) noexcept
|
||||
{
|
||||
NDS::GPU->GPU3D.Write8(addr, val);
|
||||
NDS::Current->GPU.GPU3D.Write8(addr, val);
|
||||
}
|
||||
|
||||
static void GPU3D_Write16(u32 addr, u16 val) noexcept
|
||||
{
|
||||
NDS::GPU->GPU3D.Write16(addr, val);
|
||||
NDS::Current->GPU.GPU3D.Write16(addr, val);
|
||||
}
|
||||
|
||||
static void GPU3D_Write32(u32 addr, u32 val) noexcept
|
||||
{
|
||||
NDS::GPU->GPU3D.Write32(addr, val);
|
||||
NDS::Current->GPU.GPU3D.Write32(addr, val);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static T GPU_ReadVRAM_ARM7(u32 addr) noexcept
|
||||
{
|
||||
return NDS::GPU->ReadVRAM_ARM7<T>(addr);
|
||||
return NDS::Current->GPU.ReadVRAM_ARM7<T>(addr);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static void GPU_WriteVRAM_ARM7(u32 addr, T val) noexcept
|
||||
{
|
||||
NDS::GPU->WriteVRAM_ARM7<T>(addr, val);
|
||||
NDS::Current->GPU.WriteVRAM_ARM7<T>(addr, val);
|
||||
}
|
||||
|
||||
u32 NDSCartSlot_ReadROMData()
|
||||
{ // TODO: Add a NDS* parameter, when NDS* is eventually implemented
|
||||
return NDS::NDSCartSlot->ReadROMData();
|
||||
return NDS::Current->NDSCartSlot.ReadROMData();
|
||||
}
|
||||
|
||||
static u8 NDS_ARM9IORead8(u32 addr)
|
||||
{
|
||||
return NDS::Current->ARM9IORead8(addr);
|
||||
}
|
||||
|
||||
static u16 NDS_ARM9IORead16(u32 addr)
|
||||
{
|
||||
return NDS::Current->ARM9IORead16(addr);
|
||||
}
|
||||
|
||||
static u32 NDS_ARM9IORead32(u32 addr)
|
||||
{
|
||||
return NDS::Current->ARM9IORead32(addr);
|
||||
}
|
||||
|
||||
static void NDS_ARM9IOWrite8(u32 addr, u8 val)
|
||||
{
|
||||
NDS::Current->ARM9IOWrite8(addr, val);
|
||||
}
|
||||
|
||||
static void NDS_ARM9IOWrite16(u32 addr, u16 val)
|
||||
{
|
||||
NDS::Current->ARM9IOWrite16(addr, val);
|
||||
}
|
||||
|
||||
static void NDS_ARM9IOWrite32(u32 addr, u32 val)
|
||||
{
|
||||
NDS::Current->ARM9IOWrite32(addr, val);
|
||||
}
|
||||
|
||||
static u8 NDS_ARM7IORead8(u32 addr)
|
||||
{
|
||||
return NDS::Current->ARM7IORead8(addr);
|
||||
}
|
||||
|
||||
static u16 NDS_ARM7IORead16(u32 addr)
|
||||
{
|
||||
return NDS::Current->ARM7IORead16(addr);
|
||||
}
|
||||
|
||||
static u32 NDS_ARM7IORead32(u32 addr)
|
||||
{
|
||||
return NDS::Current->ARM7IORead32(addr);
|
||||
}
|
||||
|
||||
static void NDS_ARM7IOWrite8(u32 addr, u8 val)
|
||||
{
|
||||
NDS::Current->ARM7IOWrite8(addr, val);
|
||||
}
|
||||
|
||||
static void NDS_ARM7IOWrite16(u32 addr, u16 val)
|
||||
{
|
||||
NDS::Current->ARM7IOWrite16(addr, val);
|
||||
}
|
||||
|
||||
static void NDS_ARM7IOWrite32(u32 addr, u32 val)
|
||||
{
|
||||
NDS::Current->ARM7IOWrite32(addr, val);
|
||||
}
|
||||
|
||||
void* ARMJIT_Memory::GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) const noexcept
|
||||
|
@ -1237,7 +1317,7 @@ void* ARMJIT_Memory::GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) co
|
|||
switch (addr & 0xFF000000)
|
||||
{
|
||||
case 0x04000000:
|
||||
if (!store && size == 32 && addr == 0x04100010 && NDS::ExMemCnt[0] & (1<<11))
|
||||
if (!store && size == 32 && addr == 0x04100010 && NDS.ExMemCnt[0] & (1<<11))
|
||||
return (void*)NDSCartSlot_ReadROMData;
|
||||
|
||||
/*
|
||||
|
@ -1259,30 +1339,17 @@ void* ARMJIT_Memory::GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) co
|
|||
}
|
||||
}
|
||||
|
||||
if (NDS::ConsoleType == 0)
|
||||
switch (size | store)
|
||||
{
|
||||
switch (size | store)
|
||||
{
|
||||
case 8: return (void*)NDS::ARM9IORead8;
|
||||
case 9: return (void*)NDS::ARM9IOWrite8;
|
||||
case 16: return (void*)NDS::ARM9IORead16;
|
||||
case 17: return (void*)NDS::ARM9IOWrite16;
|
||||
case 32: return (void*)NDS::ARM9IORead32;
|
||||
case 33: return (void*)NDS::ARM9IOWrite32;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size | store)
|
||||
{
|
||||
case 8: return (void*)DSi::ARM9IORead8;
|
||||
case 9: return (void*)DSi::ARM9IOWrite8;
|
||||
case 16: return (void*)DSi::ARM9IORead16;
|
||||
case 17: return (void*)DSi::ARM9IOWrite16;
|
||||
case 32: return (void*)DSi::ARM9IORead32;
|
||||
case 33: return (void*)DSi::ARM9IOWrite32;
|
||||
}
|
||||
case 8: return (void*)NDS_ARM9IORead8;
|
||||
case 9: return (void*)NDS_ARM9IOWrite8;
|
||||
case 16: return (void*)NDS_ARM9IORead16;
|
||||
case 17: return (void*)NDS_ARM9IOWrite16;
|
||||
case 32: return (void*)NDS_ARM9IORead32;
|
||||
case 33: return (void*)NDS_ARM9IOWrite32;
|
||||
}
|
||||
// NDS::Current will delegate to the DSi versions of these methods
|
||||
// if it's really a DSi
|
||||
break;
|
||||
case 0x06000000:
|
||||
switch (size | store)
|
||||
|
@ -1315,29 +1382,14 @@ void* ARMJIT_Memory::GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size) co
|
|||
}
|
||||
}*/
|
||||
|
||||
if (NDS::ConsoleType == 0)
|
||||
switch (size | store)
|
||||
{
|
||||
switch (size | store)
|
||||
{
|
||||
case 8: return (void*)NDS::ARM7IORead8;
|
||||
case 9: return (void*)NDS::ARM7IOWrite8;
|
||||
case 16: return (void*)NDS::ARM7IORead16;
|
||||
case 17: return (void*)NDS::ARM7IOWrite16;
|
||||
case 32: return (void*)NDS::ARM7IORead32;
|
||||
case 33: return (void*)NDS::ARM7IOWrite32;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size | store)
|
||||
{
|
||||
case 8: return (void*)DSi::ARM7IORead8;
|
||||
case 9: return (void*)DSi::ARM7IOWrite8;
|
||||
case 16: return (void*)DSi::ARM7IORead16;
|
||||
case 17: return (void*)DSi::ARM7IOWrite16;
|
||||
case 32: return (void*)DSi::ARM7IORead32;
|
||||
case 33: return (void*)DSi::ARM7IOWrite32;
|
||||
}
|
||||
case 8: return (void*)NDS_ARM7IORead8;
|
||||
case 9: return (void*)NDS_ARM7IOWrite8;
|
||||
case 16: return (void*)NDS_ARM7IORead16;
|
||||
case 17: return (void*)NDS_ARM7IOWrite16;
|
||||
case 32: return (void*)NDS_ARM7IORead32;
|
||||
case 33: return (void*)NDS_ARM7IOWrite32;
|
||||
}
|
||||
break;
|
||||
// TODO: the wifi funcs also ought to check POWCNT
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "TinyVector.h"
|
||||
|
||||
#include "ARM.h"
|
||||
#include "DSi.h"
|
||||
#include "MemConstants.h"
|
||||
|
||||
#if defined(__SWITCH__)
|
||||
#include <switch.h>
|
||||
|
@ -44,6 +44,7 @@
|
|||
|
||||
namespace melonDS
|
||||
{
|
||||
namespace Platform { struct DynamicLibrary; }
|
||||
class Compiler;
|
||||
class ARMJIT;
|
||||
|
||||
|
@ -57,13 +58,13 @@ constexpr u32 RoundUp(u32 size) noexcept
|
|||
}
|
||||
|
||||
const u32 MemBlockMainRAMOffset = 0;
|
||||
const u32 MemBlockSWRAMOffset = RoundUp(NDS::MainRAMMaxSize);
|
||||
const u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(NDS::SharedWRAMSize);
|
||||
const u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(NDS::ARM7WRAMSize);
|
||||
const u32 MemBlockSWRAMOffset = RoundUp(MainRAMMaxSize);
|
||||
const u32 MemBlockARM7WRAMOffset = MemBlockSWRAMOffset + RoundUp(SharedWRAMSize);
|
||||
const u32 MemBlockDTCMOffset = MemBlockARM7WRAMOffset + RoundUp(ARM7WRAMSize);
|
||||
const u32 MemBlockNWRAM_AOffset = MemBlockDTCMOffset + RoundUp(DTCMPhysicalSize);
|
||||
const u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(DSi::NWRAMSize);
|
||||
const u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(DSi::NWRAMSize);
|
||||
const u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(DSi::NWRAMSize);
|
||||
const u32 MemBlockNWRAM_BOffset = MemBlockNWRAM_AOffset + RoundUp(NWRAMSize);
|
||||
const u32 MemBlockNWRAM_COffset = MemBlockNWRAM_BOffset + RoundUp(NWRAMSize);
|
||||
const u32 MemoryTotalSize = MemBlockNWRAM_COffset + RoundUp(NWRAMSize);
|
||||
|
||||
class ARMJIT_Memory
|
||||
{
|
||||
|
@ -96,7 +97,7 @@ public:
|
|||
|
||||
#ifdef JIT_ENABLED
|
||||
public:
|
||||
explicit ARMJIT_Memory(ARMJIT& jit) noexcept;
|
||||
explicit ARMJIT_Memory(melonDS::NDS& nds);
|
||||
~ARMJIT_Memory() noexcept;
|
||||
ARMJIT_Memory(const ARMJIT_Memory&) = delete;
|
||||
ARMJIT_Memory(ARMJIT_Memory&&) = delete;
|
||||
|
@ -144,7 +145,7 @@ private:
|
|||
u32 Size, LocalOffset;
|
||||
u32 Num;
|
||||
|
||||
void Unmap(int region, ARMJIT_Memory& memory) noexcept;
|
||||
void Unmap(int region, NDS& nds) noexcept;
|
||||
};
|
||||
|
||||
struct FaultDescription
|
||||
|
@ -152,12 +153,12 @@ private:
|
|||
u32 EmulatedFaultAddr;
|
||||
u8* FaultPC;
|
||||
};
|
||||
static bool FaultHandler(FaultDescription& faultDesc, ARMJIT& jit);
|
||||
static bool FaultHandler(FaultDescription& faultDesc, melonDS::NDS& nds);
|
||||
bool MapIntoRange(u32 addr, u32 num, u32 offset, u32 size) noexcept;
|
||||
bool UnmapFromRange(u32 addr, u32 num, u32 offset, u32 size) noexcept;
|
||||
void SetCodeProtectionRange(u32 addr, u32 size, u32 num, int protection) noexcept;
|
||||
|
||||
ARMJIT& JIT;
|
||||
melonDS::NDS& NDS;
|
||||
void* FastMem9Start;
|
||||
void* FastMem7Start;
|
||||
u8* MemoryBase = nullptr;
|
||||
|
@ -180,7 +181,7 @@ private:
|
|||
TinyVector<Mapping> Mappings[memregions_Count] {};
|
||||
#else
|
||||
public:
|
||||
explicit ARMJIT_Memory(ARMJIT&) {};
|
||||
explicit ARMJIT_Memory(melonDS::NDS&) {};
|
||||
~ARMJIT_Memory() = default;
|
||||
ARMJIT_Memory(const ARMJIT_Memory&) = delete;
|
||||
ARMJIT_Memory(ARMJIT_Memory&&) = delete;
|
||||
|
@ -214,13 +215,13 @@ public:
|
|||
[[nodiscard]] u8* GetNWRAM_C() noexcept { return NWRAM_C.data(); }
|
||||
[[nodiscard]] const u8* GetNWRAM_C() const noexcept { return NWRAM_C.data(); }
|
||||
private:
|
||||
std::array<u8, NDS::MainRAMMaxSize> MainRAM {};
|
||||
std::array<u8, NDS::ARM7WRAMSize> ARM7WRAM {};
|
||||
std::array<u8, NDS::SharedWRAMSize> SharedWRAM {};
|
||||
std::array<u8, MainRAMMaxSize> MainRAM {};
|
||||
std::array<u8, ARM7WRAMSize> ARM7WRAM {};
|
||||
std::array<u8, SharedWRAMSize> SharedWRAM {};
|
||||
std::array<u8, DTCMPhysicalSize> DTCM {};
|
||||
std::array<u8, DSi::NWRAMSize> NWRAM_A {};
|
||||
std::array<u8, DSi::NWRAMSize> NWRAM_B {};
|
||||
std::array<u8, DSi::NWRAMSize> NWRAM_C {};
|
||||
std::array<u8, NWRAMSize> NWRAM_A {};
|
||||
std::array<u8, NWRAMSize> NWRAM_B {};
|
||||
std::array<u8, NWRAMSize> NWRAM_C {};
|
||||
#endif
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "ARMJIT_Compiler.h"
|
||||
#include "../ARM.h"
|
||||
#include "../NDS.h"
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
|
@ -120,7 +121,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
u32 compileTimePC = CurCPU->R[15];
|
||||
CurCPU->R[15] = newPC;
|
||||
|
||||
cycles += NDS::ARM7MemTimings[codeCycles][0] + NDS::ARM7MemTimings[codeCycles][1];
|
||||
cycles += NDS.ARM7MemTimings[codeCycles][0] + NDS.ARM7MemTimings[codeCycles][1];
|
||||
|
||||
CurCPU->R[15] = compileTimePC;
|
||||
}
|
||||
|
@ -132,7 +133,7 @@ void Compiler::Comp_JumpTo(u32 addr, bool forceNonConstantCycles)
|
|||
u32 compileTimePC = CurCPU->R[15];
|
||||
CurCPU->R[15] = newPC;
|
||||
|
||||
cycles += NDS::ARM7MemTimings[codeCycles][2] + NDS::ARM7MemTimings[codeCycles][3];
|
||||
cycles += NDS.ARM7MemTimings[codeCycles][2] + NDS.ARM7MemTimings[codeCycles][3];
|
||||
|
||||
CurCPU->R[15] = compileTimePC;
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
|
||||
#include "../ARMJIT.h"
|
||||
#include "../ARMInterpreter.h"
|
||||
#include "../NDS.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdarg.h>
|
||||
|
@ -234,7 +235,7 @@ void Compiler::A_Comp_MSR()
|
|||
*/
|
||||
u8 CodeMemory[1024 * 1024 * 32];
|
||||
|
||||
Compiler::Compiler(ARMJIT& jit) : XEmitter(), JIT(jit)
|
||||
Compiler::Compiler(melonDS::NDS& nds) : XEmitter(), NDS(nds)
|
||||
{
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
@ -714,12 +715,12 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
|
|||
if (NearSize - (GetCodePtr() - NearStart) < 1024 * 32) // guess...
|
||||
{
|
||||
Log(LogLevel::Debug, "near reset\n");
|
||||
JIT.ResetBlockCache();
|
||||
NDS.JIT.ResetBlockCache();
|
||||
}
|
||||
if (FarSize - (FarCode - FarStart) < 1024 * 32) // guess...
|
||||
{
|
||||
Log(LogLevel::Debug, "far reset\n");
|
||||
JIT.ResetBlockCache();
|
||||
NDS.JIT.ResetBlockCache();
|
||||
}
|
||||
|
||||
ConstantCycles = 0;
|
||||
|
@ -863,7 +864,7 @@ JitBlockEntry Compiler::CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[]
|
|||
void Compiler::Comp_AddCycles_C(bool forceNonConstant)
|
||||
{
|
||||
s32 cycles = Num ?
|
||||
NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 1 : 3]
|
||||
NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 1 : 3]
|
||||
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles);
|
||||
|
||||
if ((!Thumb && CurInstr.Cond() < 0xE) || forceNonConstant)
|
||||
|
@ -875,7 +876,7 @@ void Compiler::Comp_AddCycles_C(bool forceNonConstant)
|
|||
void Compiler::Comp_AddCycles_CI(u32 i)
|
||||
{
|
||||
s32 cycles = (Num ?
|
||||
NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
|
||||
NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
|
||||
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles)) + i;
|
||||
|
||||
if (!Thumb && CurInstr.Cond() < 0xE)
|
||||
|
@ -887,7 +888,7 @@ void Compiler::Comp_AddCycles_CI(u32 i)
|
|||
void Compiler::Comp_AddCycles_CI(Gen::X64Reg i, int add)
|
||||
{
|
||||
s32 cycles = Num ?
|
||||
NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
|
||||
NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2]
|
||||
: ((R15 & 0x2) ? 0 : CurInstr.CodeCycles);
|
||||
|
||||
if (!Thumb && CurInstr.Cond() < 0xE)
|
||||
|
@ -912,7 +913,7 @@ void Compiler::Comp_AddCycles_CDI()
|
|||
|
||||
s32 cycles;
|
||||
|
||||
s32 numC = NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2];
|
||||
s32 numC = NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2];
|
||||
s32 numD = CurInstr.DataCycles;
|
||||
|
||||
if ((CurInstr.DataRegion >> 24) == 0x02) // mainRAM
|
||||
|
@ -957,7 +958,7 @@ void Compiler::Comp_AddCycles_CD()
|
|||
}
|
||||
else
|
||||
{
|
||||
s32 numC = NDS::ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2];
|
||||
s32 numC = NDS.ARM7MemTimings[CurInstr.CodeCycles][Thumb ? 0 : 2];
|
||||
s32 numD = CurInstr.DataCycles;
|
||||
|
||||
if ((CurInstr.DataRegion >> 4) == 0x02)
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace melonDS
|
|||
{
|
||||
class ARMJIT;
|
||||
class ARMJIT_Memory;
|
||||
class NDS;
|
||||
const Gen::X64Reg RCPU = Gen::RBP;
|
||||
const Gen::X64Reg RCPSR = Gen::R15;
|
||||
|
||||
|
@ -81,9 +82,9 @@ class Compiler : public Gen::XEmitter
|
|||
{
|
||||
public:
|
||||
#ifdef JIT_ENABLED
|
||||
explicit Compiler(ARMJIT& jit);
|
||||
explicit Compiler(melonDS::NDS& nds);
|
||||
#else
|
||||
explicit Compiler(ARMJIT& jit) : XEmitter(), JIT(jit) {}
|
||||
explicit Compiler(melonDS::NDS& nds) : XEmitter(), NDS(nds) {}
|
||||
#endif
|
||||
|
||||
void Reset();
|
||||
|
@ -243,7 +244,7 @@ public:
|
|||
void CreateMethod(const char* namefmt, void* start, ...);
|
||||
#endif
|
||||
|
||||
ARMJIT& JIT;
|
||||
melonDS::NDS& NDS;
|
||||
u8* FarCode {};
|
||||
u8* NearCode {};
|
||||
u32 FarSize {};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "ARMJIT_Compiler.h"
|
||||
#include "../ARMJIT.h"
|
||||
#include "../NDS.h"
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
|
@ -68,9 +69,9 @@ u8* Compiler::RewriteMemAccess(u8* pc)
|
|||
|
||||
bool Compiler::Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr)
|
||||
{
|
||||
u32 localAddr = JIT.LocaliseCodeAddress(Num, addr);
|
||||
u32 localAddr = NDS.JIT.LocaliseCodeAddress(Num, addr);
|
||||
|
||||
int invalidLiteralIdx = JIT.InvalidLiterals.Find(localAddr);
|
||||
int invalidLiteralIdx = NDS.JIT.InvalidLiterals.Find(localAddr);
|
||||
if (invalidLiteralIdx != -1)
|
||||
{
|
||||
return false;
|
||||
|
@ -118,7 +119,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
if (size == 16)
|
||||
addressMask = ~1;
|
||||
|
||||
if (JIT.LiteralOptimizations && rn == 15 && rd != 15 && op2.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
|
||||
if (NDS.JIT.LiteralOptimizations && rn == 15 && rd != 15 && op2.IsImm && !(flags & (memop_Post|memop_Store|memop_Writeback)))
|
||||
{
|
||||
u32 addr = R15 + op2.Imm * ((flags & memop_SubtractOffset) ? -1 : 1);
|
||||
|
||||
|
@ -135,7 +136,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
Comp_AddCycles_CDI();
|
||||
}
|
||||
|
||||
bool addrIsStatic = JIT.LiteralOptimizations
|
||||
bool addrIsStatic = NDS.JIT.LiteralOptimizations
|
||||
&& RegCache.IsLiteral(rn) && op2.IsImm && !(flags & (memop_Writeback|memop_Post));
|
||||
u32 staticAddress;
|
||||
if (addrIsStatic)
|
||||
|
@ -196,10 +197,10 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
MOV(32, rnMapped, R(finalAddr));
|
||||
|
||||
u32 expectedTarget = Num == 0
|
||||
? JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||
: JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||
? NDS.JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||
: NDS.JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||
|
||||
if (JIT.FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || JIT.Memory.IsFastmemCompatible(expectedTarget)))
|
||||
if (NDS.JIT.FastMemory && ((!Thumb && CurInstr.Cond() != 0xE) || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget)))
|
||||
{
|
||||
if (rdMapped.IsImm())
|
||||
{
|
||||
|
@ -212,12 +213,12 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
|
||||
assert(rdMapped.GetSimpleReg() >= 0 && rdMapped.GetSimpleReg() < 16);
|
||||
patch.PatchFunc = flags & memop_Store
|
||||
? PatchedStoreFuncs[NDS::ConsoleType][Num][__builtin_ctz(size) - 3][rdMapped.GetSimpleReg()]
|
||||
: PatchedLoadFuncs[NDS::ConsoleType][Num][__builtin_ctz(size) - 3][!!(flags & memop_SignExtend)][rdMapped.GetSimpleReg()];
|
||||
? PatchedStoreFuncs[NDS.ConsoleType][Num][__builtin_ctz(size) - 3][rdMapped.GetSimpleReg()]
|
||||
: PatchedLoadFuncs[NDS.ConsoleType][Num][__builtin_ctz(size) - 3][!!(flags & memop_SignExtend)][rdMapped.GetSimpleReg()];
|
||||
|
||||
assert(patch.PatchFunc != NULL);
|
||||
|
||||
MOV(64, R(RSCRATCH), ImmPtr(Num == 0 ? JIT.Memory.FastMem9Start : JIT.Memory.FastMem7Start));
|
||||
MOV(64, R(RSCRATCH), ImmPtr(Num == 0 ? NDS.JIT.Memory.FastMem9Start : NDS.JIT.Memory.FastMem7Start));
|
||||
|
||||
X64Reg maskedAddr = RSCRATCH3;
|
||||
if (size > 8)
|
||||
|
@ -268,7 +269,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
|
||||
void* func = NULL;
|
||||
if (addrIsStatic)
|
||||
func = JIT.Memory.GetFuncForAddr(CurCPU, staticAddress, flags & memop_Store, size);
|
||||
func = NDS.JIT.Memory.GetFuncForAddr(CurCPU, staticAddress, flags & memop_Store, size);
|
||||
|
||||
if (func)
|
||||
{
|
||||
|
@ -313,7 +314,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
MOV(32, R(ABI_PARAM1), R(RSCRATCH3));
|
||||
if (flags & memop_Store)
|
||||
{
|
||||
switch (size | NDS::ConsoleType)
|
||||
switch (size | NDS.ConsoleType)
|
||||
{
|
||||
case 32: CALL((void*)&SlowWrite9<u32, 0>); break;
|
||||
case 16: CALL((void*)&SlowWrite9<u16, 0>); break;
|
||||
|
@ -325,7 +326,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
}
|
||||
else
|
||||
{
|
||||
switch (size | NDS::ConsoleType)
|
||||
switch (size | NDS.ConsoleType)
|
||||
{
|
||||
case 32: CALL((void*)&SlowRead9<u32, 0>); break;
|
||||
case 16: CALL((void*)&SlowRead9<u16, 0>); break;
|
||||
|
@ -344,7 +345,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
{
|
||||
MOV(32, R(ABI_PARAM2), rdMapped);
|
||||
|
||||
switch (size | NDS::ConsoleType)
|
||||
switch (size | NDS.ConsoleType)
|
||||
{
|
||||
case 32: CALL((void*)&SlowWrite7<u32, 0>); break;
|
||||
case 16: CALL((void*)&SlowWrite7<u16, 0>); break;
|
||||
|
@ -356,7 +357,7 @@ void Compiler::Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flag
|
|||
}
|
||||
else
|
||||
{
|
||||
switch (size | NDS::ConsoleType)
|
||||
switch (size | NDS.ConsoleType)
|
||||
{
|
||||
case 32: CALL((void*)&SlowRead7<u32, 0>); break;
|
||||
case 16: CALL((void*)&SlowRead7<u16, 0>); break;
|
||||
|
@ -422,16 +423,16 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
|||
s32 offset = (regsCount * 4) * (decrement ? -1 : 1);
|
||||
|
||||
int expectedTarget = Num == 0
|
||||
? JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||
: JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||
? NDS.JIT.Memory.ClassifyAddress9(CurInstr.DataRegion)
|
||||
: NDS.JIT.Memory.ClassifyAddress7(CurInstr.DataRegion);
|
||||
|
||||
if (!store)
|
||||
Comp_AddCycles_CDI();
|
||||
else
|
||||
Comp_AddCycles_CD();
|
||||
|
||||
bool compileFastPath = JIT.FastMemory
|
||||
&& !usermode && (CurInstr.Cond() < 0xE || JIT.Memory.IsFastmemCompatible(expectedTarget));
|
||||
bool compileFastPath = NDS.JIT.FastMemory
|
||||
&& !usermode && (CurInstr.Cond() < 0xE || NDS.JIT.Memory.IsFastmemCompatible(expectedTarget));
|
||||
|
||||
// we need to make sure that the stack stays aligned to 16 bytes
|
||||
#ifdef _WIN32
|
||||
|
@ -454,7 +455,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
|||
u8* fastPathStart = GetWritableCodePtr();
|
||||
u8* loadStoreAddr[16];
|
||||
|
||||
MOV(64, R(RSCRATCH2), ImmPtr(Num == 0 ? JIT.Memory.FastMem9Start : JIT.Memory.FastMem7Start));
|
||||
MOV(64, R(RSCRATCH2), ImmPtr(Num == 0 ? NDS.JIT.Memory.FastMem9Start : NDS.JIT.Memory.FastMem7Start));
|
||||
ADD(64, R(RSCRATCH2), R(RSCRATCH4));
|
||||
|
||||
u32 offset = 0;
|
||||
|
@ -523,7 +524,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
|||
if (Num == 0)
|
||||
MOV(64, R(ABI_PARAM4), R(RCPU));
|
||||
|
||||
switch (Num * 2 | NDS::ConsoleType)
|
||||
switch (Num * 2 | NDS.ConsoleType)
|
||||
{
|
||||
case 0: CALL((void*)&SlowBlockTransfer9<false, 0>); break;
|
||||
case 1: CALL((void*)&SlowBlockTransfer9<false, 1>); break;
|
||||
|
@ -627,7 +628,7 @@ s32 Compiler::Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc
|
|||
if (Num == 0)
|
||||
MOV(64, R(ABI_PARAM4), R(RCPU));
|
||||
|
||||
switch (Num * 2 | NDS::ConsoleType)
|
||||
switch (Num * 2 | NDS.ConsoleType)
|
||||
{
|
||||
case 0: CALL((void*)&SlowBlockTransfer9<true, 0>); break;
|
||||
case 1: CALL((void*)&SlowBlockTransfer9<true, 1>); break;
|
||||
|
@ -808,7 +809,7 @@ void Compiler::T_Comp_LoadPCRel()
|
|||
{
|
||||
u32 offset = (CurInstr.Instr & 0xFF) << 2;
|
||||
u32 addr = (R15 & ~0x2) + offset;
|
||||
if (!JIT.LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
|
||||
if (!NDS.JIT.LiteralOptimizations || !Comp_MemLoadLiteral(32, false, CurInstr.T_Reg(8), addr))
|
||||
Comp_MemAccess(CurInstr.T_Reg(8), 15, Op2(offset), 32, 0);
|
||||
}
|
||||
|
||||
|
|
28
src/CP15.cpp
28
src/CP15.cpp
|
@ -124,7 +124,7 @@ void ARMv5::UpdateDTCMSetting()
|
|||
|
||||
if (newDTCMBase != DTCMBase || newDTCMMask != DTCMMask)
|
||||
{
|
||||
JIT.Memory.RemapDTCM(newDTCMBase, newDTCMSize);
|
||||
NDS.JIT.Memory.RemapDTCM(newDTCMBase, newDTCMSize);
|
||||
DTCMBase = newDTCMBase;
|
||||
DTCMMask = newDTCMMask;
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
|
|||
for (u32 i = addrstart; i < addrend; i++)
|
||||
{
|
||||
u8 pu = PU_Map[i];
|
||||
u8* bustimings = NDS::ARM9MemTimings[i >> 2];
|
||||
u8* bustimings = NDS.ARM9MemTimings[i >> 2];
|
||||
|
||||
if (pu & 0x40)
|
||||
{
|
||||
|
@ -303,7 +303,7 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
|
|||
}
|
||||
else
|
||||
{
|
||||
MemTimings[i][0] = bustimings[2] << NDS::ARM9ClockShift;
|
||||
MemTimings[i][0] = bustimings[2] << NDS.ARM9ClockShift;
|
||||
}
|
||||
|
||||
if (pu & 0x10)
|
||||
|
@ -314,9 +314,9 @@ void ARMv5::UpdateRegionTimings(u32 addrstart, u32 addrend)
|
|||
}
|
||||
else
|
||||
{
|
||||
MemTimings[i][1] = bustimings[0] << NDS::ARM9ClockShift;
|
||||
MemTimings[i][2] = bustimings[2] << NDS::ARM9ClockShift;
|
||||
MemTimings[i][3] = bustimings[3] << NDS::ARM9ClockShift;
|
||||
MemTimings[i][1] = bustimings[0] << NDS.ARM9ClockShift;
|
||||
MemTimings[i][2] = bustimings[2] << NDS.ARM9ClockShift;
|
||||
MemTimings[i][3] = bustimings[3] << NDS.ARM9ClockShift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -388,14 +388,14 @@ void ARMv5::ICacheLookup(u32 addr)
|
|||
else
|
||||
{
|
||||
for (int i = 0; i < 32; i+=4)
|
||||
*(u32*)&ptr[i] = NDS::ARM9Read32(addr+i);
|
||||
*(u32*)&ptr[i] = NDS.ARM9Read32(addr+i);
|
||||
}
|
||||
|
||||
ICacheTags[line] = tag;
|
||||
|
||||
// ouch :/
|
||||
//printf("cache miss %08X: %d/%d\n", addr, NDS::ARM9MemTimings[addr >> 14][2], NDS::ARM9MemTimings[addr >> 14][3]);
|
||||
CodeCycles = (NDS::ARM9MemTimings[addr >> 14][2] + (NDS::ARM9MemTimings[addr >> 14][3] * 7)) << NDS::ARM9ClockShift;
|
||||
CodeCycles = (NDS.ARM9MemTimings[addr >> 14][2] + (NDS.ARM9MemTimings[addr >> 14][3] * 7)) << NDS.ARM9ClockShift;
|
||||
CurICacheLine = ptr;
|
||||
}
|
||||
|
||||
|
@ -923,7 +923,7 @@ void ARMv5::DataWrite8(u32 addr, u8 val)
|
|||
{
|
||||
DataCycles = 1;
|
||||
*(u8*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
||||
JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
return;
|
||||
}
|
||||
if ((addr & DTCMMask) == DTCMBase)
|
||||
|
@ -953,7 +953,7 @@ void ARMv5::DataWrite16(u32 addr, u16 val)
|
|||
{
|
||||
DataCycles = 1;
|
||||
*(u16*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
||||
JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
return;
|
||||
}
|
||||
if ((addr & DTCMMask) == DTCMBase)
|
||||
|
@ -983,7 +983,7 @@ void ARMv5::DataWrite32(u32 addr, u32 val)
|
|||
{
|
||||
DataCycles = 1;
|
||||
*(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
||||
JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
return;
|
||||
}
|
||||
if ((addr & DTCMMask) == DTCMBase)
|
||||
|
@ -1006,7 +1006,7 @@ void ARMv5::DataWrite32S(u32 addr, u32 val)
|
|||
DataCycles += 1;
|
||||
*(u32*)&ITCM[addr & (ITCMPhysicalSize - 1)] = val;
|
||||
#ifdef JIT_ENABLED
|
||||
JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
NDS.JIT.CheckAndInvalidate<0, ARMJIT_Memory::memregion_ITCM>(addr);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -1021,7 +1021,7 @@ void ARMv5::DataWrite32S(u32 addr, u32 val)
|
|||
DataCycles += MemTimings[addr >> 12][3];
|
||||
}
|
||||
|
||||
void ARMv5::GetCodeMemRegion(u32 addr, NDS::MemRegion* region)
|
||||
void ARMv5::GetCodeMemRegion(u32 addr, MemRegion* region)
|
||||
{
|
||||
/*if (addr < ITCMSize)
|
||||
{
|
||||
|
@ -1030,7 +1030,7 @@ void ARMv5::GetCodeMemRegion(u32 addr, NDS::MemRegion* region)
|
|||
return;
|
||||
}*/
|
||||
|
||||
GetMemRegion(addr, false, &CodeMem);
|
||||
NDS.ARM9GetMemRegion(addr, false, &CodeMem);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
160
src/DMA.cpp
160
src/DMA.cpp
|
@ -49,10 +49,10 @@ using Platform::LogLevel;
|
|||
// TODO: timings are nonseq when address is fixed/decrementing
|
||||
|
||||
|
||||
DMA::DMA(u32 cpu, u32 num, melonDS::GPU& gpu) :
|
||||
DMA::DMA(u32 cpu, u32 num, melonDS::NDS& nds) :
|
||||
CPU(cpu),
|
||||
Num(num),
|
||||
GPU(gpu)
|
||||
NDS(nds)
|
||||
{
|
||||
if (cpu == 0)
|
||||
CountMask = 0x001FFFFF;
|
||||
|
@ -145,7 +145,7 @@ void DMA::WriteCnt(u32 val)
|
|||
if ((StartMode & 0x7) == 0)
|
||||
Start();
|
||||
else if (StartMode == 0x07)
|
||||
GPU.GPU3D.CheckFIFODMA();
|
||||
NDS.GPU.GPU3D.CheckFIFODMA();
|
||||
|
||||
if (StartMode==0x06 || StartMode==0x13)
|
||||
Log(LogLevel::Warn, "UNIMPLEMENTED ARM%d DMA%d START MODE %02X, %08X->%08X\n", CPU?7:9, Num, StartMode, SrcAddr, DstAddr);
|
||||
|
@ -192,7 +192,7 @@ void DMA::Start()
|
|||
MRAMBurstTable = DMATiming::MRAMDummy;
|
||||
|
||||
InProgress = true;
|
||||
NDS::StopCPU(CPU, 1<<Num);
|
||||
NDS.StopCPU(CPU, 1<<Num);
|
||||
}
|
||||
|
||||
u32 DMA::UnitTimings9_16(bool burststart)
|
||||
|
@ -200,18 +200,18 @@ u32 DMA::UnitTimings9_16(bool burststart)
|
|||
u32 src_id = CurSrcAddr >> 14;
|
||||
u32 dst_id = CurDstAddr >> 14;
|
||||
|
||||
u32 src_rgn = NDS::ARM9Regions[src_id];
|
||||
u32 dst_rgn = NDS::ARM9Regions[dst_id];
|
||||
u32 src_rgn = NDS.ARM9Regions[src_id];
|
||||
u32 dst_rgn = NDS.ARM9Regions[dst_id];
|
||||
|
||||
u32 src_n, src_s, dst_n, dst_s;
|
||||
src_n = NDS::ARM9MemTimings[src_id][4];
|
||||
src_s = NDS::ARM9MemTimings[src_id][5];
|
||||
dst_n = NDS::ARM9MemTimings[dst_id][4];
|
||||
dst_s = NDS::ARM9MemTimings[dst_id][5];
|
||||
src_n = NDS.ARM9MemTimings[src_id][4];
|
||||
src_s = NDS.ARM9MemTimings[src_id][5];
|
||||
dst_n = NDS.ARM9MemTimings[dst_id][4];
|
||||
dst_s = NDS.ARM9MemTimings[dst_id][5];
|
||||
|
||||
if (src_rgn == NDS::Mem9_MainRAM)
|
||||
if (src_rgn == Mem9_MainRAM)
|
||||
{
|
||||
if (dst_rgn == NDS::Mem9_MainRAM)
|
||||
if (dst_rgn == Mem9_MainRAM)
|
||||
return 16;
|
||||
|
||||
if (SrcAddrInc > 0)
|
||||
|
@ -220,7 +220,7 @@ u32 DMA::UnitTimings9_16(bool burststart)
|
|||
{
|
||||
MRAMBurstCount = 0;
|
||||
|
||||
if (dst_rgn == NDS::Mem9_GBAROM)
|
||||
if (dst_rgn == Mem9_GBAROM)
|
||||
{
|
||||
if (dst_s == 4)
|
||||
MRAMBurstTable = DMATiming::MRAMRead16Bursts[1];
|
||||
|
@ -241,7 +241,7 @@ u32 DMA::UnitTimings9_16(bool burststart)
|
|||
(burststart ? dst_n : dst_s);
|
||||
}
|
||||
}
|
||||
else if (dst_rgn == NDS::Mem9_MainRAM)
|
||||
else if (dst_rgn == Mem9_MainRAM)
|
||||
{
|
||||
if (DstAddrInc > 0)
|
||||
{
|
||||
|
@ -249,7 +249,7 @@ u32 DMA::UnitTimings9_16(bool burststart)
|
|||
{
|
||||
MRAMBurstCount = 0;
|
||||
|
||||
if (src_rgn == NDS::Mem9_GBAROM)
|
||||
if (src_rgn == Mem9_GBAROM)
|
||||
{
|
||||
if (src_s == 4)
|
||||
MRAMBurstTable = DMATiming::MRAMWrite16Bursts[1];
|
||||
|
@ -286,18 +286,18 @@ u32 DMA::UnitTimings9_32(bool burststart)
|
|||
u32 src_id = CurSrcAddr >> 14;
|
||||
u32 dst_id = CurDstAddr >> 14;
|
||||
|
||||
u32 src_rgn = NDS::ARM9Regions[src_id];
|
||||
u32 dst_rgn = NDS::ARM9Regions[dst_id];
|
||||
u32 src_rgn = NDS.ARM9Regions[src_id];
|
||||
u32 dst_rgn = NDS.ARM9Regions[dst_id];
|
||||
|
||||
u32 src_n, src_s, dst_n, dst_s;
|
||||
src_n = NDS::ARM9MemTimings[src_id][6];
|
||||
src_s = NDS::ARM9MemTimings[src_id][7];
|
||||
dst_n = NDS::ARM9MemTimings[dst_id][6];
|
||||
dst_s = NDS::ARM9MemTimings[dst_id][7];
|
||||
src_n = NDS.ARM9MemTimings[src_id][6];
|
||||
src_s = NDS.ARM9MemTimings[src_id][7];
|
||||
dst_n = NDS.ARM9MemTimings[dst_id][6];
|
||||
dst_s = NDS.ARM9MemTimings[dst_id][7];
|
||||
|
||||
if (src_rgn == NDS::Mem9_MainRAM)
|
||||
if (src_rgn == Mem9_MainRAM)
|
||||
{
|
||||
if (dst_rgn == NDS::Mem9_MainRAM)
|
||||
if (dst_rgn == Mem9_MainRAM)
|
||||
return 18;
|
||||
|
||||
if (SrcAddrInc > 0)
|
||||
|
@ -306,7 +306,7 @@ u32 DMA::UnitTimings9_32(bool burststart)
|
|||
{
|
||||
MRAMBurstCount = 0;
|
||||
|
||||
if (dst_rgn == NDS::Mem9_GBAROM)
|
||||
if (dst_rgn == Mem9_GBAROM)
|
||||
{
|
||||
if (dst_s == 8)
|
||||
MRAMBurstTable = DMATiming::MRAMRead32Bursts[2];
|
||||
|
@ -329,7 +329,7 @@ u32 DMA::UnitTimings9_32(bool burststart)
|
|||
(burststart ? dst_n : dst_s);
|
||||
}
|
||||
}
|
||||
else if (dst_rgn == NDS::Mem9_MainRAM)
|
||||
else if (dst_rgn == Mem9_MainRAM)
|
||||
{
|
||||
if (DstAddrInc > 0)
|
||||
{
|
||||
|
@ -337,7 +337,7 @@ u32 DMA::UnitTimings9_32(bool burststart)
|
|||
{
|
||||
MRAMBurstCount = 0;
|
||||
|
||||
if (src_rgn == NDS::Mem9_GBAROM)
|
||||
if (src_rgn == Mem9_GBAROM)
|
||||
{
|
||||
if (src_s == 8)
|
||||
MRAMBurstTable = DMATiming::MRAMWrite32Bursts[2];
|
||||
|
@ -378,18 +378,18 @@ u32 DMA::UnitTimings7_16(bool burststart)
|
|||
u32 src_id = CurSrcAddr >> 15;
|
||||
u32 dst_id = CurDstAddr >> 15;
|
||||
|
||||
u32 src_rgn = NDS::ARM7Regions[src_id];
|
||||
u32 dst_rgn = NDS::ARM7Regions[dst_id];
|
||||
u32 src_rgn = NDS.ARM7Regions[src_id];
|
||||
u32 dst_rgn = NDS.ARM7Regions[dst_id];
|
||||
|
||||
u32 src_n, src_s, dst_n, dst_s;
|
||||
src_n = NDS::ARM7MemTimings[src_id][0];
|
||||
src_s = NDS::ARM7MemTimings[src_id][1];
|
||||
dst_n = NDS::ARM7MemTimings[dst_id][0];
|
||||
dst_s = NDS::ARM7MemTimings[dst_id][1];
|
||||
src_n = NDS.ARM7MemTimings[src_id][0];
|
||||
src_s = NDS.ARM7MemTimings[src_id][1];
|
||||
dst_n = NDS.ARM7MemTimings[dst_id][0];
|
||||
dst_s = NDS.ARM7MemTimings[dst_id][1];
|
||||
|
||||
if (src_rgn == NDS::Mem7_MainRAM)
|
||||
if (src_rgn == Mem7_MainRAM)
|
||||
{
|
||||
if (dst_rgn == NDS::Mem7_MainRAM)
|
||||
if (dst_rgn == Mem7_MainRAM)
|
||||
return 16;
|
||||
|
||||
if (SrcAddrInc > 0)
|
||||
|
@ -398,7 +398,7 @@ u32 DMA::UnitTimings7_16(bool burststart)
|
|||
{
|
||||
MRAMBurstCount = 0;
|
||||
|
||||
if (dst_rgn == NDS::Mem7_GBAROM || dst_rgn == NDS::Mem7_Wifi0 || dst_rgn == NDS::Mem7_Wifi1)
|
||||
if (dst_rgn == Mem7_GBAROM || dst_rgn == Mem7_Wifi0 || dst_rgn == Mem7_Wifi1)
|
||||
{
|
||||
if (dst_s == 4)
|
||||
MRAMBurstTable = DMATiming::MRAMRead16Bursts[1];
|
||||
|
@ -419,7 +419,7 @@ u32 DMA::UnitTimings7_16(bool burststart)
|
|||
(burststart ? dst_n : dst_s);
|
||||
}
|
||||
}
|
||||
else if (dst_rgn == NDS::Mem7_MainRAM)
|
||||
else if (dst_rgn == Mem7_MainRAM)
|
||||
{
|
||||
if (DstAddrInc > 0)
|
||||
{
|
||||
|
@ -427,7 +427,7 @@ u32 DMA::UnitTimings7_16(bool burststart)
|
|||
{
|
||||
MRAMBurstCount = 0;
|
||||
|
||||
if (src_rgn == NDS::Mem7_GBAROM || src_rgn == NDS::Mem7_Wifi0 || src_rgn == NDS::Mem7_Wifi1)
|
||||
if (src_rgn == Mem7_GBAROM || src_rgn == Mem7_Wifi0 || src_rgn == Mem7_Wifi1)
|
||||
{
|
||||
if (src_s == 4)
|
||||
MRAMBurstTable = DMATiming::MRAMWrite16Bursts[1];
|
||||
|
@ -464,18 +464,18 @@ u32 DMA::UnitTimings7_32(bool burststart)
|
|||
u32 src_id = CurSrcAddr >> 15;
|
||||
u32 dst_id = CurDstAddr >> 15;
|
||||
|
||||
u32 src_rgn = NDS::ARM7Regions[src_id];
|
||||
u32 dst_rgn = NDS::ARM7Regions[dst_id];
|
||||
u32 src_rgn = NDS.ARM7Regions[src_id];
|
||||
u32 dst_rgn = NDS.ARM7Regions[dst_id];
|
||||
|
||||
u32 src_n, src_s, dst_n, dst_s;
|
||||
src_n = NDS::ARM7MemTimings[src_id][2];
|
||||
src_s = NDS::ARM7MemTimings[src_id][3];
|
||||
dst_n = NDS::ARM7MemTimings[dst_id][2];
|
||||
dst_s = NDS::ARM7MemTimings[dst_id][3];
|
||||
src_n = NDS.ARM7MemTimings[src_id][2];
|
||||
src_s = NDS.ARM7MemTimings[src_id][3];
|
||||
dst_n = NDS.ARM7MemTimings[dst_id][2];
|
||||
dst_s = NDS.ARM7MemTimings[dst_id][3];
|
||||
|
||||
if (src_rgn == NDS::Mem7_MainRAM)
|
||||
if (src_rgn == Mem7_MainRAM)
|
||||
{
|
||||
if (dst_rgn == NDS::Mem7_MainRAM)
|
||||
if (dst_rgn == Mem7_MainRAM)
|
||||
return 18;
|
||||
|
||||
if (SrcAddrInc > 0)
|
||||
|
@ -484,7 +484,7 @@ u32 DMA::UnitTimings7_32(bool burststart)
|
|||
{
|
||||
MRAMBurstCount = 0;
|
||||
|
||||
if (dst_rgn == NDS::Mem7_GBAROM || dst_rgn == NDS::Mem7_Wifi0 || dst_rgn == NDS::Mem7_Wifi1)
|
||||
if (dst_rgn == Mem7_GBAROM || dst_rgn == Mem7_Wifi0 || dst_rgn == Mem7_Wifi1)
|
||||
{
|
||||
if (dst_s == 8)
|
||||
MRAMBurstTable = DMATiming::MRAMRead32Bursts[2];
|
||||
|
@ -507,7 +507,7 @@ u32 DMA::UnitTimings7_32(bool burststart)
|
|||
(burststart ? dst_n : dst_s);
|
||||
}
|
||||
}
|
||||
else if (dst_rgn == NDS::Mem7_MainRAM)
|
||||
else if (dst_rgn == Mem7_MainRAM)
|
||||
{
|
||||
if (DstAddrInc > 0)
|
||||
{
|
||||
|
@ -515,7 +515,7 @@ u32 DMA::UnitTimings7_32(bool burststart)
|
|||
{
|
||||
MRAMBurstCount = 0;
|
||||
|
||||
if (src_rgn == NDS::Mem7_GBAROM || src_rgn == NDS::Mem7_Wifi0 || src_rgn == NDS::Mem7_Wifi1)
|
||||
if (src_rgn == Mem7_GBAROM || src_rgn == Mem7_Wifi0 || src_rgn == Mem7_Wifi1)
|
||||
{
|
||||
if (src_s == 8)
|
||||
MRAMBurstTable = DMATiming::MRAMWrite32Bursts[2];
|
||||
|
@ -549,10 +549,9 @@ u32 DMA::UnitTimings7_32(bool burststart)
|
|||
}
|
||||
}
|
||||
|
||||
template <int ConsoleType>
|
||||
void DMA::Run9()
|
||||
{
|
||||
if (NDS::ARM9Timestamp >= NDS::ARM9Target) return;
|
||||
if (NDS.ARM9Timestamp >= NDS.ARM9Target) return;
|
||||
|
||||
Executing = true;
|
||||
|
||||
|
@ -564,40 +563,34 @@ void DMA::Run9()
|
|||
{
|
||||
while (IterCount > 0 && !Stall)
|
||||
{
|
||||
NDS::ARM9Timestamp += (UnitTimings9_16(burststart) << NDS::ARM9ClockShift);
|
||||
NDS.ARM9Timestamp += (UnitTimings9_16(burststart) << NDS.ARM9ClockShift);
|
||||
burststart = false;
|
||||
|
||||
if (ConsoleType == 1)
|
||||
DSi::ARM9Write16(CurDstAddr, DSi::ARM9Read16(CurSrcAddr));
|
||||
else
|
||||
NDS::ARM9Write16(CurDstAddr, NDS::ARM9Read16(CurSrcAddr));
|
||||
NDS.ARM9Write16(CurDstAddr, NDS.ARM9Read16(CurSrcAddr));
|
||||
|
||||
CurSrcAddr += SrcAddrInc<<1;
|
||||
CurDstAddr += DstAddrInc<<1;
|
||||
IterCount--;
|
||||
RemCount--;
|
||||
|
||||
if (NDS::ARM9Timestamp >= NDS::ARM9Target) break;
|
||||
if (NDS.ARM9Timestamp >= NDS.ARM9Target) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (IterCount > 0 && !Stall)
|
||||
{
|
||||
NDS::ARM9Timestamp += (UnitTimings9_32(burststart) << NDS::ARM9ClockShift);
|
||||
NDS.ARM9Timestamp += (UnitTimings9_32(burststart) << NDS.ARM9ClockShift);
|
||||
burststart = false;
|
||||
|
||||
if (ConsoleType == 1)
|
||||
DSi::ARM9Write32(CurDstAddr, DSi::ARM9Read32(CurSrcAddr));
|
||||
else
|
||||
NDS::ARM9Write32(CurDstAddr, NDS::ARM9Read32(CurSrcAddr));
|
||||
NDS.ARM9Write32(CurDstAddr, NDS.ARM9Read32(CurSrcAddr));
|
||||
|
||||
CurSrcAddr += SrcAddrInc<<2;
|
||||
CurDstAddr += DstAddrInc<<2;
|
||||
IterCount--;
|
||||
RemCount--;
|
||||
|
||||
if (NDS::ARM9Timestamp >= NDS::ARM9Target) break;
|
||||
if (NDS.ARM9Timestamp >= NDS.ARM9Target) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -609,10 +602,10 @@ void DMA::Run9()
|
|||
if (IterCount == 0)
|
||||
{
|
||||
Running = 0;
|
||||
NDS::ResumeCPU(0, 1<<Num);
|
||||
NDS.ResumeCPU(0, 1<<Num);
|
||||
|
||||
if (StartMode == 0x07)
|
||||
GPU.GPU3D.CheckFIFODMA();
|
||||
NDS.GPU.GPU3D.CheckFIFODMA();
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -622,17 +615,16 @@ void DMA::Run9()
|
|||
Cnt &= ~(1<<31);
|
||||
|
||||
if (Cnt & (1<<30))
|
||||
NDS::SetIRQ(0, NDS::IRQ_DMA0 + Num);
|
||||
NDS.SetIRQ(0, IRQ_DMA0 + Num);
|
||||
|
||||
Running = 0;
|
||||
InProgress = false;
|
||||
NDS::ResumeCPU(0, 1<<Num);
|
||||
NDS.ResumeCPU(0, 1<<Num);
|
||||
}
|
||||
|
||||
template <int ConsoleType>
|
||||
void DMA::Run7()
|
||||
{
|
||||
if (NDS::ARM7Timestamp >= NDS::ARM7Target) return;
|
||||
if (NDS.ARM7Timestamp >= NDS.ARM7Target) return;
|
||||
|
||||
Executing = true;
|
||||
|
||||
|
@ -644,40 +636,34 @@ void DMA::Run7()
|
|||
{
|
||||
while (IterCount > 0 && !Stall)
|
||||
{
|
||||
NDS::ARM7Timestamp += UnitTimings7_16(burststart);
|
||||
NDS.ARM7Timestamp += UnitTimings7_16(burststart);
|
||||
burststart = false;
|
||||
|
||||
if (ConsoleType == 1)
|
||||
DSi::ARM7Write16(CurDstAddr, DSi::ARM7Read16(CurSrcAddr));
|
||||
else
|
||||
NDS::ARM7Write16(CurDstAddr, NDS::ARM7Read16(CurSrcAddr));
|
||||
NDS.ARM7Write16(CurDstAddr, NDS.ARM7Read16(CurSrcAddr));
|
||||
|
||||
CurSrcAddr += SrcAddrInc<<1;
|
||||
CurDstAddr += DstAddrInc<<1;
|
||||
IterCount--;
|
||||
RemCount--;
|
||||
|
||||
if (NDS::ARM7Timestamp >= NDS::ARM7Target) break;
|
||||
if (NDS.ARM7Timestamp >= NDS.ARM7Target) break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (IterCount > 0 && !Stall)
|
||||
{
|
||||
NDS::ARM7Timestamp += UnitTimings7_32(burststart);
|
||||
NDS.ARM7Timestamp += UnitTimings7_32(burststart);
|
||||
burststart = false;
|
||||
|
||||
if (ConsoleType == 1)
|
||||
DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr));
|
||||
else
|
||||
NDS::ARM7Write32(CurDstAddr, NDS::ARM7Read32(CurSrcAddr));
|
||||
NDS.ARM7Write32(CurDstAddr, NDS.ARM7Read32(CurSrcAddr));
|
||||
|
||||
CurSrcAddr += SrcAddrInc<<2;
|
||||
CurDstAddr += DstAddrInc<<2;
|
||||
IterCount--;
|
||||
RemCount--;
|
||||
|
||||
if (NDS::ARM7Timestamp >= NDS::ARM7Target) break;
|
||||
if (NDS.ARM7Timestamp >= NDS.ARM7Target) break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -689,7 +675,7 @@ void DMA::Run7()
|
|||
if (IterCount == 0)
|
||||
{
|
||||
Running = 0;
|
||||
NDS::ResumeCPU(1, 1<<Num);
|
||||
NDS.ResumeCPU(1, 1<<Num);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -699,22 +685,18 @@ void DMA::Run7()
|
|||
Cnt &= ~(1<<31);
|
||||
|
||||
if (Cnt & (1<<30))
|
||||
NDS::SetIRQ(1, NDS::IRQ_DMA0 + Num);
|
||||
NDS.SetIRQ(1, IRQ_DMA0 + Num);
|
||||
|
||||
Running = 0;
|
||||
InProgress = false;
|
||||
NDS::ResumeCPU(1, 1<<Num);
|
||||
NDS.ResumeCPU(1, 1<<Num);
|
||||
}
|
||||
|
||||
template <int ConsoleType>
|
||||
void DMA::Run()
|
||||
{
|
||||
if (!Running) return;
|
||||
if (CPU == 0) return Run9<ConsoleType>();
|
||||
else return Run7<ConsoleType>();
|
||||
if (CPU == 0) return Run9();
|
||||
else return Run7();
|
||||
}
|
||||
|
||||
template void DMA::Run<0>();
|
||||
template void DMA::Run<1>();
|
||||
|
||||
}
|
13
src/DMA.h
13
src/DMA.h
|
@ -21,17 +21,16 @@
|
|||
|
||||
#include <array>
|
||||
#include "types.h"
|
||||
#include "Savestate.h"
|
||||
#include "DMA_Timings.h"
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
class GPU;
|
||||
class NDS;
|
||||
class Savestate;
|
||||
|
||||
class DMA
|
||||
{
|
||||
public:
|
||||
DMA(u32 cpu, u32 num, GPU& gpu);
|
||||
DMA(u32 cpu, u32 num, NDS& nds);
|
||||
~DMA() = default;
|
||||
|
||||
void Reset();
|
||||
|
@ -46,12 +45,8 @@ public:
|
|||
u32 UnitTimings7_16(bool burststart);
|
||||
u32 UnitTimings7_32(bool burststart);
|
||||
|
||||
template <int ConsoleType>
|
||||
void Run();
|
||||
|
||||
template <int ConsoleType>
|
||||
void Run9();
|
||||
template <int ConsoleType>
|
||||
void Run7();
|
||||
|
||||
bool IsInMode(u32 mode) const noexcept
|
||||
|
@ -83,7 +78,7 @@ public:
|
|||
u32 Cnt {};
|
||||
|
||||
private:
|
||||
melonDS::GPU& GPU;
|
||||
melonDS::NDS& NDS;
|
||||
u32 CPU {};
|
||||
u32 Num {};
|
||||
|
||||
|
|
1010
src/DSi.cpp
1010
src/DSi.cpp
File diff suppressed because it is too large
Load Diff
183
src/DSi.h
183
src/DSi.h
|
@ -20,7 +20,12 @@
|
|||
#define DSI_H
|
||||
|
||||
#include "NDS.h"
|
||||
#include "DSi_NDMA.h"
|
||||
#include "DSi_SD.h"
|
||||
#include "DSi_DSP.h"
|
||||
#include "DSi_AES.h"
|
||||
#include "DSi_Camera.h"
|
||||
#include "DSi_NAND.h"
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
|
@ -34,99 +39,135 @@ namespace DSi_NAND
|
|||
class NANDImage;
|
||||
}
|
||||
|
||||
namespace DSi
|
||||
class DSi final : public NDS
|
||||
{
|
||||
protected:
|
||||
void DoSavestateExtra(Savestate* file) override;
|
||||
public:
|
||||
u16 SCFG_BIOS;
|
||||
u16 SCFG_Clock9;
|
||||
u32 SCFG_EXT[2];
|
||||
|
||||
extern u16 SCFG_BIOS;
|
||||
extern u16 SCFG_Clock9;
|
||||
extern u32 SCFG_EXT[2];
|
||||
u8 ARM9iBIOS[0x10000];
|
||||
u8 ARM7iBIOS[0x10000];
|
||||
std::unique_ptr<DSi_NAND::NANDImage> NANDImage;
|
||||
DSi_SDHost SDMMC;
|
||||
DSi_SDHost SDIO;
|
||||
|
||||
const u32 NWRAMSize = 0x40000;
|
||||
|
||||
extern u8 ARM9iBIOS[0x10000];
|
||||
extern u8 ARM7iBIOS[0x10000];
|
||||
u8* NWRAM_A;
|
||||
u8* NWRAM_B;
|
||||
u8* NWRAM_C;
|
||||
|
||||
extern std::unique_ptr<DSi_NAND::NANDImage> NANDImage;
|
||||
extern DSi_SDHost* SDMMC;
|
||||
extern DSi_SDHost* SDIO;
|
||||
u8* NWRAMMap_A[2][4];
|
||||
u8* NWRAMMap_B[3][8];
|
||||
u8* NWRAMMap_C[3][8];
|
||||
|
||||
const u32 NWRAMSize = 0x40000;
|
||||
u32 NWRAMStart[2][3];
|
||||
u32 NWRAMEnd[2][3];
|
||||
u32 NWRAMMask[2][3];
|
||||
|
||||
extern u8* NWRAM_A;
|
||||
extern u8* NWRAM_B;
|
||||
extern u8* NWRAM_C;
|
||||
DSi_I2CHost I2C;
|
||||
DSi_CamModule CamModule;
|
||||
DSi_AES AES;
|
||||
DSi_DSP DSP;
|
||||
|
||||
extern u8* NWRAMMap_A[2][4];
|
||||
extern u8* NWRAMMap_B[3][8];
|
||||
extern u8* NWRAMMap_C[3][8];
|
||||
void Reset() override;
|
||||
void Stop(Platform::StopReason reason) override;
|
||||
|
||||
extern u32 NWRAMStart[2][3];
|
||||
extern u32 NWRAMEnd[2][3];
|
||||
extern u32 NWRAMMask[2][3];
|
||||
bool DoSavestate(Savestate* file);
|
||||
|
||||
extern DSi_I2CHost* I2C;
|
||||
extern DSi_CamModule* CamModule;
|
||||
extern DSi_AES* AES;
|
||||
extern DSi_DSP* DSP;
|
||||
void SetCartInserted(bool inserted);
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
void Stop();
|
||||
void SetupDirectBoot() override;
|
||||
void SoftReset();
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
bool LoadNAND();
|
||||
|
||||
void SetCartInserted(bool inserted);
|
||||
void RunNDMAs(u32 cpu);
|
||||
void StallNDMAs();
|
||||
bool NDMAsInMode(u32 cpu, u32 mode);
|
||||
bool NDMAsRunning(u32 cpu);
|
||||
void CheckNDMAs(u32 cpu, u32 mode);
|
||||
void StopNDMAs(u32 cpu, u32 mode);
|
||||
|
||||
void SetupDirectBoot();
|
||||
void SoftReset();
|
||||
void MapNWRAM_A(u32 num, u8 val);
|
||||
void MapNWRAM_B(u32 num, u8 val);
|
||||
void MapNWRAM_C(u32 num, u8 val);
|
||||
void MapNWRAMRange(u32 cpu, u32 num, u32 val);
|
||||
|
||||
bool LoadNAND();
|
||||
u8 ARM9Read8(u32 addr) override;
|
||||
u16 ARM9Read16(u32 addr) override;
|
||||
u32 ARM9Read32(u32 addr) override;
|
||||
void ARM9Write8(u32 addr, u8 val) override;
|
||||
void ARM9Write16(u32 addr, u16 val) override;
|
||||
void ARM9Write32(u32 addr, u32 val) override;
|
||||
|
||||
void RunNDMAs(u32 cpu);
|
||||
void StallNDMAs();
|
||||
bool NDMAsInMode(u32 cpu, u32 mode);
|
||||
bool NDMAsRunning(u32 cpu);
|
||||
void CheckNDMAs(u32 cpu, u32 mode);
|
||||
void StopNDMAs(u32 cpu, u32 mode);
|
||||
bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region) override;
|
||||
|
||||
void MapNWRAM_A(u32 num, u8 val);
|
||||
void MapNWRAM_B(u32 num, u8 val);
|
||||
void MapNWRAM_C(u32 num, u8 val);
|
||||
void MapNWRAMRange(u32 cpu, u32 num, u32 val);
|
||||
u8 ARM7Read8(u32 addr) override;
|
||||
u16 ARM7Read16(u32 addr) override;
|
||||
u32 ARM7Read32(u32 addr) override;
|
||||
void ARM7Write8(u32 addr, u8 val) override;
|
||||
void ARM7Write16(u32 addr, u16 val) override;
|
||||
void ARM7Write32(u32 addr, u32 val) override;
|
||||
|
||||
u8 ARM9Read8(u32 addr);
|
||||
u16 ARM9Read16(u32 addr);
|
||||
u32 ARM9Read32(u32 addr);
|
||||
void ARM9Write8(u32 addr, u8 val);
|
||||
void ARM9Write16(u32 addr, u16 val);
|
||||
void ARM9Write32(u32 addr, u32 val);
|
||||
bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region) override;
|
||||
|
||||
bool ARM9GetMemRegion(u32 addr, bool write, NDS::MemRegion* region);
|
||||
u8 ARM9IORead8(u32 addr) override;
|
||||
u16 ARM9IORead16(u32 addr) override;
|
||||
u32 ARM9IORead32(u32 addr) override;
|
||||
void ARM9IOWrite8(u32 addr, u8 val) override;
|
||||
void ARM9IOWrite16(u32 addr, u16 val) override;
|
||||
void ARM9IOWrite32(u32 addr, u32 val) override;
|
||||
|
||||
u8 ARM7Read8(u32 addr);
|
||||
u16 ARM7Read16(u32 addr);
|
||||
u32 ARM7Read32(u32 addr);
|
||||
void ARM7Write8(u32 addr, u8 val);
|
||||
void ARM7Write16(u32 addr, u16 val);
|
||||
void ARM7Write32(u32 addr, u32 val);
|
||||
u8 ARM7IORead8(u32 addr) override;
|
||||
u16 ARM7IORead16(u32 addr) override;
|
||||
u32 ARM7IORead32(u32 addr) override;
|
||||
void ARM7IOWrite8(u32 addr, u8 val) override;
|
||||
void ARM7IOWrite16(u32 addr, u16 val) override;
|
||||
void ARM7IOWrite32(u32 addr, u32 val) override;
|
||||
|
||||
bool ARM7GetMemRegion(u32 addr, bool write, NDS::MemRegion* region);
|
||||
public:
|
||||
DSi() noexcept;
|
||||
~DSi() noexcept override;
|
||||
DSi(const DSi&) = delete;
|
||||
DSi& operator=(const DSi&) = delete;
|
||||
DSi(DSi&&) = delete;
|
||||
DSi& operator=(DSi&&) = delete;
|
||||
bool LoadCart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen) override;
|
||||
void EjectCart() override;
|
||||
bool NeedsDirectBoot() override
|
||||
{
|
||||
// for now, DSi mode requires original BIOS/NAND
|
||||
return false;
|
||||
}
|
||||
void CamInputFrame(int cam, u32* data, int width, int height, bool rgb) override;
|
||||
bool DMAsInMode(u32 cpu, u32 mode) override;
|
||||
bool DMAsRunning(u32 cpu) override;
|
||||
void StopDMAs(u32 cpu, u32 mode) override;
|
||||
void CheckDMAs(u32 cpu, u32 mode) override;
|
||||
u16 SCFG_Clock7;
|
||||
u32 SCFG_MC;
|
||||
u16 SCFG_RST;
|
||||
u32 MBK[2][9];
|
||||
u32 NDMACnt[2];
|
||||
std::array<DSi_NDMA, 8> NDMAs;
|
||||
// FIXME: these currently have no effect (and aren't stored in a savestate)
|
||||
// ... not that they matter all that much
|
||||
u8 GPIO_Data;
|
||||
u8 GPIO_Dir;
|
||||
u8 GPIO_IEdgeSel;
|
||||
u8 GPIO_IE;
|
||||
u8 GPIO_WiFi;
|
||||
|
||||
u8 ARM9IORead8(u32 addr);
|
||||
u16 ARM9IORead16(u32 addr);
|
||||
u32 ARM9IORead32(u32 addr);
|
||||
void ARM9IOWrite8(u32 addr, u8 val);
|
||||
void ARM9IOWrite16(u32 addr, u16 val);
|
||||
void ARM9IOWrite32(u32 addr, u32 val);
|
||||
|
||||
u8 ARM7IORead8(u32 addr);
|
||||
u16 ARM7IORead16(u32 addr);
|
||||
u32 ARM7IORead32(u32 addr);
|
||||
void ARM7IOWrite8(u32 addr, u8 val);
|
||||
void ARM7IOWrite16(u32 addr, u16 val);
|
||||
void ARM7IOWrite32(u32 addr, u32 val);
|
||||
|
||||
}
|
||||
private:
|
||||
void Set_SCFG_Clock9(u16 val);
|
||||
void Set_SCFG_MC(u32 val);
|
||||
void DecryptModcryptArea(u32 offset, u32 size, u8* iv);
|
||||
void ApplyNewRAMSize(u32 size);
|
||||
};
|
||||
|
||||
}
|
||||
#endif // DSI_H
|
||||
|
|
|
@ -36,7 +36,7 @@ using Platform::LogLevel;
|
|||
#define _printhex2R(str, size) { for (int z = 0; z < (size); z++) printf("%02X", (str)[((size)-1)-z]); }
|
||||
|
||||
|
||||
DSi_AES::DSi_AES()
|
||||
DSi_AES::DSi_AES(melonDS::DSi& dsi) : DSi(dsi)
|
||||
{
|
||||
const u8 zero[16] = {0};
|
||||
AES_init_ctx_iv(&Ctx, zero, zero);
|
||||
|
@ -78,7 +78,7 @@ void DSi_AES::Reset()
|
|||
OutputMACDue = false;
|
||||
|
||||
// initialize keys
|
||||
u64 consoleid = DSi::NANDImage->GetConsoleID();
|
||||
u64 consoleid = DSi.NANDImage->GetConsoleID();
|
||||
|
||||
// slot 0: modcrypt
|
||||
*(u32*)&KeyX[0][0] = 0x746E694E;
|
||||
|
@ -313,7 +313,7 @@ void DSi_AES::WriteCnt(u32 val)
|
|||
AES_init_ctx_iv(&Ctx, key, iv);
|
||||
}
|
||||
|
||||
DSi::CheckNDMAs(1, 0x2A);
|
||||
DSi.CheckNDMAs(1, 0x2A);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -347,9 +347,9 @@ u32 DSi_AES::ReadOutputFIFO()
|
|||
else
|
||||
{
|
||||
if (OutputFIFO.Level() > 0)
|
||||
DSi::CheckNDMAs(1, 0x2B);
|
||||
DSi.CheckNDMAs(1, 0x2B);
|
||||
else
|
||||
DSi::StopNDMAs(1, 0x2B);
|
||||
DSi.StopNDMAs(1, 0x2B);
|
||||
|
||||
if (OutputMACDue && OutputFIFO.Level() <= 12)
|
||||
{
|
||||
|
@ -384,7 +384,7 @@ void DSi_AES::CheckInputDMA()
|
|||
if (InputFIFO.Level() <= InputDMASize)
|
||||
{
|
||||
// trigger input DMA
|
||||
DSi::CheckNDMAs(1, 0x2A);
|
||||
DSi.CheckNDMAs(1, 0x2A);
|
||||
}
|
||||
|
||||
Update();
|
||||
|
@ -395,7 +395,7 @@ void DSi_AES::CheckOutputDMA()
|
|||
if (OutputFIFO.Level() >= OutputDMASize)
|
||||
{
|
||||
// trigger output DMA
|
||||
DSi::CheckNDMAs(1, 0x2B);
|
||||
DSi.CheckNDMAs(1, 0x2B);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -475,13 +475,13 @@ void DSi_AES::Update()
|
|||
}
|
||||
|
||||
Cnt &= ~(1<<31);
|
||||
if (Cnt & (1<<30)) NDS::SetIRQ2(NDS::IRQ2_DSi_AES);
|
||||
DSi::StopNDMAs(1, 0x2A);
|
||||
if (Cnt & (1<<30)) DSi.SetIRQ2(IRQ2_DSi_AES);
|
||||
DSi.StopNDMAs(1, 0x2A);
|
||||
|
||||
if (!OutputFIFO.IsEmpty())
|
||||
DSi::CheckNDMAs(1, 0x2B);
|
||||
DSi.CheckNDMAs(1, 0x2B);
|
||||
else
|
||||
DSi::StopNDMAs(1, 0x2B);
|
||||
DSi.StopNDMAs(1, 0x2B);
|
||||
OutputFlush = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,10 +45,11 @@ __attribute((always_inline)) static void Bswap128(void* Dst, const void* Src)
|
|||
#endif
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
class DSi;
|
||||
class DSi_AES
|
||||
{
|
||||
public:
|
||||
DSi_AES();
|
||||
DSi_AES(melonDS::DSi& dsi);
|
||||
~DSi_AES();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
@ -73,6 +74,7 @@ public:
|
|||
static void DeriveNormalKey(u8* keyX, u8* keyY, u8* normalkey);
|
||||
|
||||
private:
|
||||
melonDS::DSi& DSi;
|
||||
u32 Cnt;
|
||||
|
||||
u32 BlkCnt;
|
||||
|
|
|
@ -38,13 +38,13 @@ const u32 DSi_CamModule::kIRQInterval = 1120000; // ~30 FPS
|
|||
const u32 DSi_CamModule::kTransferStart = 60000;
|
||||
|
||||
|
||||
DSi_CamModule::DSi_CamModule()
|
||||
DSi_CamModule::DSi_CamModule(melonDS::DSi& dsi) : DSi(dsi)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_DSi_CamIRQ, 0, MemberEventFunc(DSi_CamModule, IRQ));
|
||||
NDS::RegisterEventFunc(NDS::Event_DSi_CamTransfer, 0, MemberEventFunc(DSi_CamModule, TransferScanline));
|
||||
DSi.RegisterEventFunc(Event_DSi_CamIRQ, 0, MemberEventFunc(DSi_CamModule, IRQ));
|
||||
DSi.RegisterEventFunc(Event_DSi_CamTransfer, 0, MemberEventFunc(DSi_CamModule, TransferScanline));
|
||||
|
||||
Camera0 = DSi::I2C->GetOuterCamera();
|
||||
Camera1 = DSi::I2C->GetInnerCamera();
|
||||
Camera0 = DSi.I2C.GetOuterCamera();
|
||||
Camera1 = DSi.I2C.GetInnerCamera();
|
||||
}
|
||||
|
||||
DSi_CamModule::~DSi_CamModule()
|
||||
|
@ -52,8 +52,8 @@ DSi_CamModule::~DSi_CamModule()
|
|||
Camera0 = nullptr;
|
||||
Camera1 = nullptr;
|
||||
|
||||
NDS::UnregisterEventFunc(NDS::Event_DSi_CamIRQ, 0);
|
||||
NDS::UnregisterEventFunc(NDS::Event_DSi_CamTransfer, 0);
|
||||
DSi.UnregisterEventFunc(Event_DSi_CamIRQ, 0);
|
||||
DSi.UnregisterEventFunc(Event_DSi_CamTransfer, 0);
|
||||
}
|
||||
|
||||
void DSi_CamModule::Reset()
|
||||
|
@ -70,7 +70,7 @@ void DSi_CamModule::Reset()
|
|||
BufferNumLines = 0;
|
||||
CurCamera = nullptr;
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, false, kIRQInterval, 0, 0);
|
||||
DSi.ScheduleEvent(Event_DSi_CamIRQ, false, kIRQInterval, 0, 0);
|
||||
}
|
||||
|
||||
void DSi_CamModule::Stop()
|
||||
|
@ -106,7 +106,7 @@ void DSi_CamModule::IRQ(u32 param)
|
|||
activecam->StartTransfer();
|
||||
|
||||
if (Cnt & (1<<11))
|
||||
NDS::SetIRQ(0, NDS::IRQ_DSi_Camera);
|
||||
DSi.SetIRQ(0, IRQ_DSi_Camera);
|
||||
|
||||
if (Cnt & (1<<15))
|
||||
{
|
||||
|
@ -114,11 +114,11 @@ void DSi_CamModule::IRQ(u32 param)
|
|||
BufferWritePos = 0;
|
||||
BufferNumLines = 0;
|
||||
CurCamera = activecam;
|
||||
NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, kTransferStart, 0, 0);
|
||||
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, kTransferStart, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_DSi_CamIRQ, true, kIRQInterval, 0, 0);
|
||||
DSi.ScheduleEvent(Event_DSi_CamIRQ, true, kIRQInterval, 0, 0);
|
||||
}
|
||||
|
||||
void DSi_CamModule::TransferScanline(u32 line)
|
||||
|
@ -144,7 +144,7 @@ void DSi_CamModule::TransferScanline(u32 line)
|
|||
if (line < ystart || line > yend)
|
||||
{
|
||||
if (!CurCamera->TransferDone())
|
||||
NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, 0, line+1);
|
||||
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, delay, 0, line+1);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ void DSi_CamModule::TransferScanline(u32 line)
|
|||
BufferReadPos = 0; // checkme
|
||||
BufferWritePos = 0;
|
||||
BufferNumLines = 0;
|
||||
DSi::CheckNDMAs(0, 0x0B);
|
||||
DSi.CheckNDMAs(0, 0x0B);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -224,7 +224,7 @@ void DSi_CamModule::TransferScanline(u32 line)
|
|||
if (CurCamera->TransferDone())
|
||||
return;
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_DSi_CamTransfer, false, delay, 0, line+1);
|
||||
DSi.ScheduleEvent(Event_DSi_CamTransfer, false, delay, 0, line+1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -379,7 +379,7 @@ void DSi_CamModule::Write32(u32 addr, u32 val)
|
|||
|
||||
|
||||
|
||||
DSi_Camera::DSi_Camera(DSi_I2CHost* host, u32 num) : DSi_I2CDevice(host), Num(num)
|
||||
DSi_Camera::DSi_Camera(melonDS::DSi& dsi, DSi_I2CHost* host, u32 num) : DSi_I2CDevice(dsi, host), Num(num)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -25,17 +25,18 @@
|
|||
|
||||
namespace melonDS
|
||||
{
|
||||
class DSi;
|
||||
class DSi_CamModule;
|
||||
|
||||
class DSi_Camera : public DSi_I2CDevice
|
||||
{
|
||||
public:
|
||||
DSi_Camera(DSi_I2CHost* host, u32 num);
|
||||
DSi_Camera(melonDS::DSi& dsi, DSi_I2CHost* host, u32 num);
|
||||
~DSi_Camera();
|
||||
|
||||
void DoSavestate(Savestate* file);
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
void Reset();
|
||||
void Reset() override;
|
||||
void Stop();
|
||||
bool IsActivated();
|
||||
|
||||
|
@ -45,9 +46,9 @@ public:
|
|||
// lengths in words
|
||||
int TransferScanline(u32* buffer, int maxlen);
|
||||
|
||||
void Acquire();
|
||||
u8 Read(bool last);
|
||||
void Write(u8 val, bool last);
|
||||
void Acquire() override;
|
||||
u8 Read(bool last) override;
|
||||
void Write(u8 val, bool last) override;
|
||||
|
||||
void InputFrame(u32* data, int width, int height, bool rgb);
|
||||
|
||||
|
@ -84,7 +85,7 @@ private:
|
|||
class DSi_CamModule
|
||||
{
|
||||
public:
|
||||
DSi_CamModule();
|
||||
DSi_CamModule(melonDS::DSi& dsi);
|
||||
~DSi_CamModule();
|
||||
void Reset();
|
||||
void Stop();
|
||||
|
@ -105,6 +106,7 @@ public:
|
|||
void Write32(u32 addr, u32 val);
|
||||
|
||||
private:
|
||||
melonDS::DSi& DSi;
|
||||
DSi_Camera* Camera0; // 78 / facing outside
|
||||
DSi_Camera* Camera1; // 7A / selfie cam
|
||||
|
||||
|
|
|
@ -55,33 +55,33 @@ u16 DSi_DSP::GetPSTS()
|
|||
|
||||
void DSi_DSP::IrqRep0()
|
||||
{
|
||||
if (DSP_PCFG & (1<< 9)) NDS::SetIRQ(0, NDS::IRQ_DSi_DSP);
|
||||
if (DSP_PCFG & (1<< 9)) DSi.SetIRQ(0, IRQ_DSi_DSP);
|
||||
}
|
||||
void DSi_DSP::IrqRep1()
|
||||
{
|
||||
if (DSP_PCFG & (1<<10)) NDS::SetIRQ(0, NDS::IRQ_DSi_DSP);
|
||||
if (DSP_PCFG & (1<<10)) DSi.SetIRQ(0, IRQ_DSi_DSP);
|
||||
}
|
||||
void DSi_DSP::IrqRep2()
|
||||
{
|
||||
if (DSP_PCFG & (1<<11)) NDS::SetIRQ(0, NDS::IRQ_DSi_DSP);
|
||||
if (DSP_PCFG & (1<<11)) DSi.SetIRQ(0, IRQ_DSi_DSP);
|
||||
}
|
||||
void DSi_DSP::IrqSem()
|
||||
{
|
||||
DSP_PSTS |= 1<<9;
|
||||
// apparently these are always fired?
|
||||
NDS::SetIRQ(0, NDS::IRQ_DSi_DSP);
|
||||
DSi.SetIRQ(0, IRQ_DSi_DSP);
|
||||
}
|
||||
|
||||
u16 DSi_DSP::DSPRead16(u32 addr)
|
||||
{
|
||||
if (!(addr & 0x40000))
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_B[2][(addr >> 15) & 0x7];
|
||||
u8* ptr = DSi.NWRAMMap_B[2][(addr >> 15) & 0x7];
|
||||
return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_C[2][(addr >> 15) & 0x7];
|
||||
u8* ptr = DSi.NWRAMMap_C[2][(addr >> 15) & 0x7];
|
||||
return ptr ? *(u16*)&ptr[addr & 0x7FFF] : 0;
|
||||
}
|
||||
}
|
||||
|
@ -92,12 +92,12 @@ void DSi_DSP::DSPWrite16(u32 addr, u16 val)
|
|||
|
||||
if (!(addr & 0x40000))
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_B[2][(addr >> 15) & 0x7];
|
||||
u8* ptr = DSi.NWRAMMap_B[2][(addr >> 15) & 0x7];
|
||||
if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8* ptr = DSi::NWRAMMap_C[2][(addr >> 15) & 0x7];
|
||||
u8* ptr = DSi.NWRAMMap_C[2][(addr >> 15) & 0x7];
|
||||
if (ptr) *(u16*)&ptr[addr & 0x7FFF] = val;
|
||||
}
|
||||
}
|
||||
|
@ -107,9 +107,9 @@ void DSi_DSP::AudioCb(std::array<s16, 2> frame)
|
|||
// TODO
|
||||
}
|
||||
|
||||
DSi_DSP::DSi_DSP()
|
||||
DSi_DSP::DSi_DSP(melonDS::DSi& dsi) : DSi(dsi)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_DSi_DSP, 0, MemberEventFunc(DSi_DSP, DSPCatchUpU32));
|
||||
DSi.RegisterEventFunc(Event_DSi_DSP, 0, MemberEventFunc(DSi_DSP, DSPCatchUpU32));
|
||||
|
||||
TeakraCore = new Teakra::Teakra();
|
||||
SCFG_RST = false;
|
||||
|
@ -133,12 +133,12 @@ DSi_DSP::DSi_DSP()
|
|||
// these happen instantaneously and without too much regard for bus aribtration
|
||||
// rules, so, this might have to be changed later on
|
||||
Teakra::AHBMCallback cb;
|
||||
cb.read8 = DSi::ARM9Read8;
|
||||
cb.write8 = DSi::ARM9Write8;
|
||||
cb.read16 = DSi::ARM9Read16;
|
||||
cb.write16 = DSi::ARM9Write16;
|
||||
cb.read32 = DSi::ARM9Read32;
|
||||
cb.write32 = DSi::ARM9Write32;
|
||||
cb.read8 = [this](auto addr) { return DSi.ARM9Read8(addr); };
|
||||
cb.write8 = [this](auto addr, auto val) { DSi.ARM9Write8(addr, val); };
|
||||
cb.read16 = [this](auto addr) { return DSi.ARM9Read16(addr); };
|
||||
cb.write16 = [this](auto addr, auto val) { DSi.ARM9Write16(addr, val); };
|
||||
cb.read32 = [this](auto addr) { return DSi.ARM9Read32(addr); };
|
||||
cb.write32 = [this](auto addr, auto val) { DSi.ARM9Write32(addr, val); };
|
||||
TeakraCore->SetAHBMCallback(cb);
|
||||
|
||||
TeakraCore->SetAudioCallback(std::bind(&DSi_DSP::AudioCb, this, _1));
|
||||
|
@ -156,7 +156,7 @@ DSi_DSP::~DSi_DSP()
|
|||
//PDATAWriteFifo = NULL;
|
||||
TeakraCore = NULL;
|
||||
|
||||
NDS::UnregisterEventFunc(NDS::Event_DSi_DSP, 0);
|
||||
DSi.UnregisterEventFunc(Event_DSi_DSP, 0);
|
||||
}
|
||||
|
||||
void DSi_DSP::Reset()
|
||||
|
@ -177,7 +177,7 @@ void DSi_DSP::Reset()
|
|||
//PDATAWriteFifo->Clear();
|
||||
TeakraCore->Reset();
|
||||
|
||||
NDS::CancelEvent(NDS::Event_DSi_DSP);
|
||||
DSi.CancelEvent(Event_DSi_DSP);
|
||||
|
||||
SNDExCnt = 0;
|
||||
}
|
||||
|
@ -190,17 +190,17 @@ void DSi_DSP::SetRstLine(bool release)
|
|||
{
|
||||
SCFG_RST = release;
|
||||
Reset();
|
||||
DSPTimestamp = NDS::ARM9Timestamp; // only start now!
|
||||
DSPTimestamp = DSi.ARM9Timestamp; // only start now!
|
||||
}
|
||||
|
||||
inline bool DSi_DSP::IsDSPCoreEnabled()
|
||||
{
|
||||
return (DSi::SCFG_Clock9 & (1<<1)) && SCFG_RST && (!(DSP_PCFG & (1<<0)));
|
||||
return (DSi.SCFG_Clock9 & (1<<1)) && SCFG_RST && (!(DSP_PCFG & (1<<0)));
|
||||
}
|
||||
|
||||
inline bool DSi_DSP::IsDSPIOEnabled()
|
||||
{
|
||||
return (DSi::SCFG_Clock9 & (1<<1)) && SCFG_RST;
|
||||
return (DSi.SCFG_Clock9 & (1<<1)) && SCFG_RST;
|
||||
}
|
||||
|
||||
bool DSi_DSP::DSPCatchUp()
|
||||
|
@ -210,13 +210,13 @@ bool DSi_DSP::DSPCatchUp()
|
|||
{
|
||||
// nothing to do, but advance the current time so that we don't do an
|
||||
// unreasonable amount of cycles when rst is released
|
||||
if (DSPTimestamp < NDS::ARM9Timestamp)
|
||||
DSPTimestamp = NDS::ARM9Timestamp;
|
||||
if (DSPTimestamp < DSi.ARM9Timestamp)
|
||||
DSPTimestamp = DSi.ARM9Timestamp;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 curtime = NDS::ARM9Timestamp;
|
||||
u64 curtime = DSi.ARM9Timestamp;
|
||||
|
||||
if (DSPTimestamp >= curtime) return true; // ummmm?!
|
||||
|
||||
|
@ -257,7 +257,7 @@ void DSi_DSP::PDataDMAWrite(u16 wrval)
|
|||
{
|
||||
switch (TeakraCore->AHBMGetUnitSize(0))
|
||||
{
|
||||
case 0: /* 8bit */ DSi::ARM9Write8 (addr, (u8)wrval); break;
|
||||
case 0: /* 8bit */ DSi.ARM9Write8 (addr, (u8)wrval); break;
|
||||
case 1: /* 16 b */ TeakraCore->AHBMWrite16(addr, wrval); break;
|
||||
// does it work like this, or should it first buffer two u16's
|
||||
// until it has enough data to write to the actual destination?
|
||||
|
@ -272,7 +272,7 @@ void DSi_DSP::PDataDMAWrite(u16 wrval)
|
|||
if (DSP_PCFG & (1<<1)) // auto-increment
|
||||
++DSP_PADR; // overflows and stays within a 64k 'page' // TODO: is this +1 or +2?
|
||||
|
||||
NDS::SetIRQ(0, NDS::IRQ_DSi_DSP); // wrfifo empty
|
||||
DSi.SetIRQ(0, IRQ_DSi_DSP); // wrfifo empty
|
||||
}
|
||||
// TODO: FIFO interrupts! (rd full, nonempty)
|
||||
u16 DSi_DSP::PDataDMARead()
|
||||
|
@ -299,7 +299,7 @@ u16 DSi_DSP::PDataDMARead()
|
|||
{
|
||||
switch (TeakraCore->AHBMGetUnitSize(0))
|
||||
{
|
||||
case 0: /* 8bit */ r = DSi::ARM9Read8 (addr); break;
|
||||
case 0: /* 8bit */ r = DSi.ARM9Read8 (addr); break;
|
||||
case 1: /* 16 b */ r = TeakraCore->AHBMRead16(addr); break;
|
||||
case 2: /* 32 b */ r = (u16)TeakraCore->AHBMRead32(addr); break;
|
||||
}
|
||||
|
@ -337,7 +337,7 @@ void DSi_DSP::PDataDMAStart()
|
|||
for (int i = 0; i < amt; ++i)
|
||||
PDataDMAFetch();
|
||||
|
||||
NDS::SetIRQ(0, NDS::IRQ_DSi_DSP);
|
||||
DSi.SetIRQ(0, IRQ_DSi_DSP);
|
||||
|
||||
}
|
||||
void DSi_DSP::PDataDMACancel()
|
||||
|
@ -372,7 +372,7 @@ u16 DSi_DSP::PDataDMAReadMMIO()
|
|||
}
|
||||
|
||||
if (!PDATAReadFifo.IsEmpty() || PDATAReadFifo.IsFull())
|
||||
NDS::SetIRQ(0, NDS::IRQ_DSi_DSP);
|
||||
DSi.SetIRQ(0, IRQ_DSi_DSP);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -477,7 +477,7 @@ void DSi_DSP::Write8(u32 addr, u8 val)
|
|||
}
|
||||
void DSi_DSP::Write16(u32 addr, u16 val)
|
||||
{
|
||||
Log(LogLevel::Debug,"DSP WRITE16 %d %08X %08X %08X\n", IsDSPCoreEnabled(), addr, val, NDS::GetPC(0));
|
||||
Log(LogLevel::Debug,"DSP WRITE16 %d %08X %08X %08X\n", IsDSPCoreEnabled(), addr, val, DSi.GetPC(0));
|
||||
//if (!IsDSPIOEnabled()) return;
|
||||
DSPCatchUp();
|
||||
|
||||
|
@ -565,8 +565,8 @@ void DSi_DSP::Run(u32 cycles)
|
|||
|
||||
DSPTimestamp += cycles;
|
||||
|
||||
NDS::CancelEvent(NDS::Event_DSi_DSP);
|
||||
NDS::ScheduleEvent(NDS::Event_DSi_DSP, false,
|
||||
DSi.CancelEvent(Event_DSi_DSP);
|
||||
DSi.ScheduleEvent(Event_DSi_DSP, false,
|
||||
16384/*from citra (TeakraSlice)*/, 0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,11 @@ namespace Teakra { class Teakra; }
|
|||
|
||||
namespace melonDS
|
||||
{
|
||||
class DSi;
|
||||
class DSi_DSP
|
||||
{
|
||||
public:
|
||||
DSi_DSP();
|
||||
DSi_DSP(melonDS::DSi& dsi);
|
||||
~DSi_DSP();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
@ -68,6 +69,7 @@ public:
|
|||
void AudioCb(std::array<s16, 2> frame);
|
||||
|
||||
private:
|
||||
melonDS::DSi& DSi;
|
||||
// not sure whether to not rather put it somewhere else
|
||||
u16 SNDExCnt;
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ const u8 DSi_BPTWL::VolumeUpTable[32] =
|
|||
};
|
||||
|
||||
|
||||
DSi_BPTWL::DSi_BPTWL(DSi_I2CHost* host) : DSi_I2CDevice(host)
|
||||
DSi_BPTWL::DSi_BPTWL(melonDS::DSi& dsi, DSi_I2CHost* host) : DSi_I2CDevice(dsi, host)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -177,19 +177,19 @@ void DSi_BPTWL::DoHardwareReset(bool direct)
|
|||
if (direct)
|
||||
{
|
||||
// TODO: This doesn't seem to stop the SPU
|
||||
DSi::SoftReset();
|
||||
DSi.SoftReset();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: soft-reset might need to be scheduled later!
|
||||
// TODO: this has been moved for the JIT to work, nothing is confirmed here
|
||||
NDS::ARM7->Halt(4);
|
||||
DSi.ARM7.Halt(4);
|
||||
}
|
||||
|
||||
void DSi_BPTWL::DoShutdown()
|
||||
{
|
||||
ResetButtonState();
|
||||
NDS::Stop(Platform::StopReason::PowerOff);
|
||||
DSi.Stop(Platform::StopReason::PowerOff);
|
||||
}
|
||||
|
||||
|
||||
|
@ -369,7 +369,7 @@ void DSi_BPTWL::SetIRQ(u8 irqFlag)
|
|||
|
||||
if (GetIRQMode())
|
||||
{
|
||||
NDS::SetIRQ2(NDS::IRQ2_DSi_BPTWL);
|
||||
DSi.SetIRQ2(IRQ2_DSi_BPTWL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -451,11 +451,11 @@ void DSi_BPTWL::Write(u8 val, bool last)
|
|||
}
|
||||
|
||||
|
||||
DSi_I2CHost::DSi_I2CHost()
|
||||
DSi_I2CHost::DSi_I2CHost(melonDS::DSi& dsi) : DSi(dsi)
|
||||
{
|
||||
BPTWL = new DSi_BPTWL(this);
|
||||
Camera0 = new DSi_Camera(this, 0);
|
||||
Camera1 = new DSi_Camera(this, 1);
|
||||
BPTWL = new DSi_BPTWL(dsi, this);
|
||||
Camera0 = new DSi_Camera(dsi, this, 0);
|
||||
Camera1 = new DSi_Camera(dsi, this, 1);
|
||||
}
|
||||
|
||||
DSi_I2CHost::~DSi_I2CHost()
|
||||
|
|
|
@ -26,11 +26,11 @@ namespace melonDS
|
|||
{
|
||||
class DSi_I2CHost;
|
||||
class DSi_Camera;
|
||||
|
||||
class DSi;
|
||||
class DSi_I2CDevice
|
||||
{
|
||||
public:
|
||||
DSi_I2CDevice(DSi_I2CHost* host) : Host(host) {}
|
||||
DSi_I2CDevice(melonDS::DSi& dsi, DSi_I2CHost* host) : DSi(dsi), Host(host) {}
|
||||
virtual ~DSi_I2CDevice() {}
|
||||
virtual void Reset() = 0;
|
||||
virtual void DoSavestate(Savestate* file) = 0;
|
||||
|
@ -40,6 +40,7 @@ public:
|
|||
virtual void Write(u8 val, bool last) = 0;
|
||||
|
||||
protected:
|
||||
melonDS::DSi& DSi;
|
||||
DSi_I2CHost* Host;
|
||||
};
|
||||
|
||||
|
@ -80,7 +81,7 @@ public:
|
|||
IRQ_ValidMask = 0x7B,
|
||||
};
|
||||
|
||||
DSi_BPTWL(DSi_I2CHost* host);
|
||||
DSi_BPTWL(melonDS::DSi& dsi, DSi_I2CHost* host);
|
||||
~DSi_BPTWL() override;
|
||||
void Reset() override;
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
@ -153,7 +154,7 @@ private:
|
|||
class DSi_I2CHost
|
||||
{
|
||||
public:
|
||||
DSi_I2CHost();
|
||||
DSi_I2CHost(melonDS::DSi& dsi);
|
||||
~DSi_I2CHost();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
@ -169,6 +170,7 @@ public:
|
|||
void WriteData(u8 val);
|
||||
|
||||
private:
|
||||
melonDS::DSi& DSi;
|
||||
u8 Cnt;
|
||||
u8 Data;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace melonDS
|
|||
using Platform::Log;
|
||||
using Platform::LogLevel;
|
||||
|
||||
DSi_NDMA::DSi_NDMA(u32 cpu, u32 num, melonDS::GPU& gpu) : GPU(gpu)
|
||||
DSi_NDMA::DSi_NDMA(u32 cpu, u32 num, melonDS::DSi& dsi) : DSi(dsi), CPU(cpu), Num(num)
|
||||
{
|
||||
CPU = cpu;
|
||||
Num = num;
|
||||
|
@ -127,7 +127,7 @@ void DSi_NDMA::WriteCnt(u32 val)
|
|||
if ((StartMode & 0x1F) == 0x10)
|
||||
Start();
|
||||
else if (StartMode == 0x0A)
|
||||
GPU.GPU3D.CheckFIFODMA();
|
||||
DSi.GPU.GPU3D.CheckFIFODMA();
|
||||
|
||||
// TODO: unsupported start modes:
|
||||
// * timers (00-03)
|
||||
|
@ -181,13 +181,13 @@ void DSi_NDMA::Start()
|
|||
//if (SubblockTimer & 0xFFFF)
|
||||
// printf("TODO! NDMA SUBBLOCK TIMER: %08X\n", SubblockTimer);
|
||||
|
||||
if (NDS::DMAsRunning(CPU))
|
||||
if (DSi.DMAsRunning(CPU))
|
||||
Running = 1;
|
||||
else
|
||||
Running = 2;
|
||||
|
||||
InProgress = true;
|
||||
NDS::StopCPU(CPU, 1<<(Num+4));
|
||||
DSi.StopCPU(CPU, 1<<(Num+4));
|
||||
}
|
||||
|
||||
void DSi_NDMA::Run()
|
||||
|
@ -199,7 +199,7 @@ void DSi_NDMA::Run()
|
|||
|
||||
void DSi_NDMA::Run9()
|
||||
{
|
||||
if (NDS::ARM9Timestamp >= NDS::ARM9Target) return;
|
||||
if (DSi.ARM9Timestamp >= DSi.ARM9Target) return;
|
||||
|
||||
Executing = true;
|
||||
|
||||
|
@ -214,11 +214,11 @@ void DSi_NDMA::Run9()
|
|||
|
||||
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
||||
{
|
||||
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][2] + NDS::ARM9MemTimings[CurDstAddr >> 14][2];
|
||||
unitcycles = DSi.ARM9MemTimings[CurSrcAddr >> 14][2] + DSi.ARM9MemTimings[CurDstAddr >> 14][2];
|
||||
}
|
||||
else
|
||||
{
|
||||
unitcycles = NDS::ARM9MemTimings[CurSrcAddr >> 14][3] + NDS::ARM9MemTimings[CurDstAddr >> 14][3];
|
||||
unitcycles = DSi.ARM9MemTimings[CurSrcAddr >> 14][3] + DSi.ARM9MemTimings[CurDstAddr >> 14][3];
|
||||
if ((CurSrcAddr >> 24) == (CurDstAddr >> 24))
|
||||
unitcycles++;
|
||||
else if ((CurSrcAddr >> 24) == 0x02)
|
||||
|
@ -234,12 +234,12 @@ void DSi_NDMA::Run9()
|
|||
|
||||
while (IterCount > 0 && !Stall)
|
||||
{
|
||||
NDS::ARM9Timestamp += (unitcycles << NDS::ARM9ClockShift);
|
||||
DSi.ARM9Timestamp += (unitcycles << DSi.ARM9ClockShift);
|
||||
|
||||
if (dofill)
|
||||
DSi::ARM9Write32(CurDstAddr, FillData);
|
||||
DSi.ARM9Write32(CurDstAddr, FillData);
|
||||
else
|
||||
DSi::ARM9Write32(CurDstAddr, DSi::ARM9Read32(CurSrcAddr));
|
||||
DSi.ARM9Write32(CurDstAddr, DSi.ARM9Read32(CurSrcAddr));
|
||||
|
||||
CurSrcAddr += SrcAddrInc<<2;
|
||||
CurDstAddr += DstAddrInc<<2;
|
||||
|
@ -247,7 +247,7 @@ void DSi_NDMA::Run9()
|
|||
RemCount--;
|
||||
TotalRemCount--;
|
||||
|
||||
if (NDS::ARM9Timestamp >= NDS::ARM9Target) break;
|
||||
if (DSi.ARM9Timestamp >= DSi.ARM9Target) break;
|
||||
}
|
||||
|
||||
Executing = false;
|
||||
|
@ -258,10 +258,10 @@ void DSi_NDMA::Run9()
|
|||
if (IterCount == 0)
|
||||
{
|
||||
Running = 0;
|
||||
NDS::ResumeCPU(0, 1<<(Num+4));
|
||||
DSi.ResumeCPU(0, 1<<(Num+4));
|
||||
|
||||
if (StartMode == 0x0A)
|
||||
GPU.GPU3D.CheckFIFODMA();
|
||||
DSi.GPU.GPU3D.CheckFIFODMA();
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -270,25 +270,25 @@ void DSi_NDMA::Run9()
|
|||
if ((StartMode & 0x1F) == 0x10) // CHECKME
|
||||
{
|
||||
Cnt &= ~(1<<31);
|
||||
if (Cnt & (1<<30)) NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num);
|
||||
if (Cnt & (1<<30)) DSi.SetIRQ(0, IRQ_DSi_NDMA0 + Num);
|
||||
}
|
||||
else if (!(Cnt & (1<<29)))
|
||||
{
|
||||
if (TotalRemCount == 0)
|
||||
{
|
||||
Cnt &= ~(1<<31);
|
||||
if (Cnt & (1<<30)) NDS::SetIRQ(0, NDS::IRQ_DSi_NDMA0 + Num);
|
||||
if (Cnt & (1<<30)) DSi.SetIRQ(0, IRQ_DSi_NDMA0 + Num);
|
||||
}
|
||||
}
|
||||
|
||||
Running = 0;
|
||||
InProgress = false;
|
||||
NDS::ResumeCPU(0, 1<<(Num+4));
|
||||
DSi.ResumeCPU(0, 1<<(Num+4));
|
||||
}
|
||||
|
||||
void DSi_NDMA::Run7()
|
||||
{
|
||||
if (NDS::ARM7Timestamp >= NDS::ARM7Target) return;
|
||||
if (DSi.ARM7Timestamp >= DSi.ARM7Target) return;
|
||||
|
||||
Executing = true;
|
||||
|
||||
|
@ -303,11 +303,11 @@ void DSi_NDMA::Run7()
|
|||
|
||||
if ((CurSrcAddr >> 24) == 0x02 && (CurDstAddr >> 24) == 0x02)
|
||||
{
|
||||
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][2] + NDS::ARM7MemTimings[CurDstAddr >> 15][2];
|
||||
unitcycles = DSi.ARM7MemTimings[CurSrcAddr >> 15][2] + DSi.ARM7MemTimings[CurDstAddr >> 15][2];
|
||||
}
|
||||
else
|
||||
{
|
||||
unitcycles = NDS::ARM7MemTimings[CurSrcAddr >> 15][3] + NDS::ARM7MemTimings[CurDstAddr >> 15][3];
|
||||
unitcycles = DSi.ARM7MemTimings[CurSrcAddr >> 15][3] + DSi.ARM7MemTimings[CurDstAddr >> 15][3];
|
||||
if ((CurSrcAddr >> 23) == (CurDstAddr >> 23))
|
||||
unitcycles++;
|
||||
else if ((CurSrcAddr >> 24) == 0x02)
|
||||
|
@ -323,12 +323,12 @@ void DSi_NDMA::Run7()
|
|||
|
||||
while (IterCount > 0 && !Stall)
|
||||
{
|
||||
NDS::ARM7Timestamp += unitcycles;
|
||||
DSi.ARM7Timestamp += unitcycles;
|
||||
|
||||
if (dofill)
|
||||
DSi::ARM7Write32(CurDstAddr, FillData);
|
||||
DSi.ARM7Write32(CurDstAddr, FillData);
|
||||
else
|
||||
DSi::ARM7Write32(CurDstAddr, DSi::ARM7Read32(CurSrcAddr));
|
||||
DSi.ARM7Write32(CurDstAddr, DSi.ARM7Read32(CurSrcAddr));
|
||||
|
||||
CurSrcAddr += SrcAddrInc<<2;
|
||||
CurDstAddr += DstAddrInc<<2;
|
||||
|
@ -336,7 +336,7 @@ void DSi_NDMA::Run7()
|
|||
RemCount--;
|
||||
TotalRemCount--;
|
||||
|
||||
if (NDS::ARM7Timestamp >= NDS::ARM7Target) break;
|
||||
if (DSi.ARM7Timestamp >= DSi.ARM7Target) break;
|
||||
}
|
||||
|
||||
Executing = false;
|
||||
|
@ -347,10 +347,10 @@ void DSi_NDMA::Run7()
|
|||
if (IterCount == 0)
|
||||
{
|
||||
Running = 0;
|
||||
NDS::ResumeCPU(1, 1<<(Num+4));
|
||||
DSi.ResumeCPU(1, 1<<(Num+4));
|
||||
|
||||
DSi::AES->CheckInputDMA();
|
||||
DSi::AES->CheckOutputDMA();
|
||||
DSi.AES.CheckInputDMA();
|
||||
DSi.AES.CheckOutputDMA();
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -359,23 +359,23 @@ void DSi_NDMA::Run7()
|
|||
if ((StartMode & 0x1F) == 0x10) // CHECKME
|
||||
{
|
||||
Cnt &= ~(1<<31);
|
||||
if (Cnt & (1<<30)) NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num);
|
||||
if (Cnt & (1<<30)) DSi.SetIRQ(1, IRQ_DSi_NDMA0 + Num);
|
||||
}
|
||||
else if (!(Cnt & (1<<29)))
|
||||
{
|
||||
if (TotalRemCount == 0)
|
||||
{
|
||||
Cnt &= ~(1<<31);
|
||||
if (Cnt & (1<<30)) NDS::SetIRQ(1, NDS::IRQ_DSi_NDMA0 + Num);
|
||||
if (Cnt & (1<<30)) DSi.SetIRQ(1, IRQ_DSi_NDMA0 + Num);
|
||||
}
|
||||
}
|
||||
|
||||
Running = 0;
|
||||
InProgress = false;
|
||||
NDS::ResumeCPU(1, 1<<(Num+4));
|
||||
DSi.ResumeCPU(1, 1<<(Num+4));
|
||||
|
||||
DSi::AES->CheckInputDMA();
|
||||
DSi::AES->CheckOutputDMA();
|
||||
DSi.AES.CheckInputDMA();
|
||||
DSi.AES.CheckOutputDMA();
|
||||
}
|
||||
|
||||
}
|
|
@ -24,12 +24,12 @@
|
|||
|
||||
namespace melonDS
|
||||
{
|
||||
class GPU;
|
||||
class DSi;
|
||||
|
||||
class DSi_NDMA
|
||||
{
|
||||
public:
|
||||
DSi_NDMA(u32 cpu, u32 num, GPU& gpu);
|
||||
DSi_NDMA(u32 cpu, u32 num, melonDS::DSi& dsi);
|
||||
~DSi_NDMA();
|
||||
|
||||
void Reset();
|
||||
|
@ -77,7 +77,7 @@ public:
|
|||
u32 Cnt;
|
||||
|
||||
private:
|
||||
melonDS::GPU& GPU;
|
||||
melonDS::DSi& DSi;
|
||||
u32 CPU, Num;
|
||||
|
||||
u32 StartMode;
|
||||
|
|
|
@ -119,21 +119,22 @@ const u8 CIS1[256] =
|
|||
};
|
||||
|
||||
|
||||
DSi_NWifi::DSi_NWifi(DSi_SDHost* host)
|
||||
: DSi_SDDevice(host),
|
||||
Mailbox
|
||||
{
|
||||
// HACK
|
||||
// the mailboxes are supposed to be 0x80 bytes
|
||||
// however, as we do things instantly, emulating this is meaningless
|
||||
// and only adds complication
|
||||
DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600),
|
||||
DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600),
|
||||
// mailbox 8: extra mailbox acting as a bigger RX buffer
|
||||
DynamicFIFO<u8>(0x8000)
|
||||
}
|
||||
DSi_NWifi::DSi_NWifi(melonDS::DSi& dsi, DSi_SDHost* host) :
|
||||
DSi_SDDevice(host),
|
||||
Mailbox
|
||||
{
|
||||
// HACK
|
||||
// the mailboxes are supposed to be 0x80 bytes
|
||||
// however, as we do things instantly, emulating this is meaningless
|
||||
// and only adds complication
|
||||
DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600),
|
||||
DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600), DynamicFIFO<u8>(0x600),
|
||||
// mailbox 8: extra mailbox acting as a bigger RX buffer
|
||||
DynamicFIFO<u8>(0x8000)
|
||||
},
|
||||
DSi(dsi)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_DSi_NWifi, 0, MemberEventFunc(DSi_NWifi, MSTimer));
|
||||
DSi.RegisterEventFunc(Event_DSi_NWifi, 0, MemberEventFunc(DSi_NWifi, MSTimer));
|
||||
|
||||
// this seems to control whether the firmware upload is done
|
||||
EEPROMReady = 0;
|
||||
|
@ -141,9 +142,9 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host)
|
|||
|
||||
DSi_NWifi::~DSi_NWifi()
|
||||
{
|
||||
NDS::CancelEvent(NDS::Event_DSi_NWifi);
|
||||
DSi.CancelEvent(Event_DSi_NWifi);
|
||||
|
||||
NDS::UnregisterEventFunc(NDS::Event_DSi_NWifi, 0);
|
||||
DSi.UnregisterEventFunc(Event_DSi_NWifi, 0);
|
||||
}
|
||||
|
||||
void DSi_NWifi::Reset()
|
||||
|
@ -164,7 +165,7 @@ void DSi_NWifi::Reset()
|
|||
for (int i = 0; i < 9; i++)
|
||||
Mailbox[i].Clear();
|
||||
|
||||
const Firmware* fw = NDS::SPI->GetFirmware();
|
||||
const Firmware* fw = DSi.SPI.GetFirmware();
|
||||
|
||||
MacAddress mac = fw->GetHeader().MacAddr;
|
||||
Log(LogLevel::Info, "NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
|
||||
|
@ -226,7 +227,7 @@ void DSi_NWifi::Reset()
|
|||
BeaconTimer = 0x10A2220ULL;
|
||||
ConnectionStatus = 0;
|
||||
|
||||
NDS::CancelEvent(NDS::Event_DSi_NWifi);
|
||||
DSi.CancelEvent(Event_DSi_NWifi);
|
||||
}
|
||||
|
||||
void DSi_NWifi::DoSavestate(Savestate* file)
|
||||
|
@ -909,7 +910,7 @@ void DSi_NWifi::HTC_Command()
|
|||
SendWMIEvent(1, 0x1006, regdomain_evt, 4);
|
||||
|
||||
BootPhase = 2;
|
||||
NDS::ScheduleEvent(NDS::Event_DSi_NWifi, false, 33611, 0, 0);
|
||||
DSi.ScheduleEvent(Event_DSi_NWifi, false, 33611, 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1608,7 +1609,7 @@ void DSi_NWifi::MSTimer(u32 param)
|
|||
CheckRX();
|
||||
}
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, 0, 0);
|
||||
DSi.ScheduleEvent(Event_DSi_NWifi, true, 33611, 0, 0);
|
||||
}
|
||||
|
||||
}
|
|
@ -28,7 +28,7 @@ namespace melonDS
|
|||
class DSi_NWifi : public DSi_SDDevice
|
||||
{
|
||||
public:
|
||||
DSi_NWifi(DSi_SDHost* host);
|
||||
DSi_NWifi(melonDS::DSi& dsi, DSi_SDHost* host);
|
||||
~DSi_NWifi();
|
||||
|
||||
void Reset();
|
||||
|
@ -45,6 +45,7 @@ public:
|
|||
void MSTimer(u32 param);
|
||||
|
||||
private:
|
||||
melonDS::DSi& DSi;
|
||||
u32 TransferCmd;
|
||||
u32 TransferAddr;
|
||||
u32 RemSize;
|
||||
|
|
|
@ -57,13 +57,13 @@ enum
|
|||
};
|
||||
|
||||
|
||||
DSi_SDHost::DSi_SDHost(u32 num)
|
||||
DSi_SDHost::DSi_SDHost(melonDS::DSi& dsi, u32 num) : DSi(dsi)
|
||||
{
|
||||
Num = num;
|
||||
|
||||
NDS::RegisterEventFunc(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
|
||||
DSi.RegisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
Transfer_TX, MemberEventFunc(DSi_SDHost, FinishTX));
|
||||
NDS::RegisterEventFunc(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
|
||||
DSi.RegisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
Transfer_RX, MemberEventFunc(DSi_SDHost, FinishRX));
|
||||
|
||||
Ports[0] = nullptr;
|
||||
|
@ -75,9 +75,9 @@ DSi_SDHost::~DSi_SDHost()
|
|||
if (Ports[0]) delete Ports[0];
|
||||
if (Ports[1]) delete Ports[1];
|
||||
|
||||
NDS::UnregisterEventFunc(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
|
||||
DSi.UnregisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
Transfer_TX);
|
||||
NDS::UnregisterEventFunc(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
|
||||
DSi.UnregisterEventFunc(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
Transfer_RX);
|
||||
}
|
||||
|
||||
|
@ -156,15 +156,15 @@ void DSi_SDHost::Reset()
|
|||
else
|
||||
sd = nullptr;
|
||||
|
||||
mmc = new DSi_MMCStorage(this, *DSi::NANDImage);
|
||||
mmc->SetCID(DSi::NANDImage->GetEMMCID().data());
|
||||
mmc = new DSi_MMCStorage(this, *DSi.NANDImage);
|
||||
mmc->SetCID(DSi.NANDImage->GetEMMCID().data());
|
||||
|
||||
Ports[0] = sd;
|
||||
Ports[1] = mmc;
|
||||
}
|
||||
else
|
||||
{
|
||||
DSi_NWifi* nwifi = new DSi_NWifi(this);
|
||||
DSi_NWifi* nwifi = new DSi_NWifi(DSi, this);
|
||||
|
||||
Ports[0] = nwifi;
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ void DSi_SDHost::UpdateData32IRQ()
|
|||
newflags &= (Data32IRQ >> 11);
|
||||
|
||||
if ((oldflags == 0) && (newflags != 0))
|
||||
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC);
|
||||
DSi.SetIRQ2(Num ? IRQ2_DSi_SDIO : IRQ2_DSi_SDMMC);
|
||||
}
|
||||
|
||||
void DSi_SDHost::ClearIRQ(u32 irq)
|
||||
|
@ -244,7 +244,7 @@ void DSi_SDHost::SetIRQ(u32 irq)
|
|||
u32 newflags = IRQStatus & ~IRQMask;
|
||||
|
||||
if ((oldflags == 0) && (newflags != 0))
|
||||
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC);
|
||||
DSi.SetIRQ2(Num ? IRQ2_DSi_SDIO : IRQ2_DSi_SDMMC);
|
||||
}
|
||||
|
||||
void DSi_SDHost::UpdateIRQ(u32 oldmask)
|
||||
|
@ -253,7 +253,7 @@ void DSi_SDHost::UpdateIRQ(u32 oldmask)
|
|||
u32 newflags = IRQStatus & ~IRQMask;
|
||||
|
||||
if ((oldflags == 0) && (newflags != 0))
|
||||
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC);
|
||||
DSi.SetIRQ2(Num ? IRQ2_DSi_SDIO : IRQ2_DSi_SDMMC);
|
||||
}
|
||||
|
||||
void DSi_SDHost::SetCardIRQ()
|
||||
|
@ -270,8 +270,8 @@ void DSi_SDHost::SetCardIRQ()
|
|||
|
||||
if ((oldflags == 0) && (newflags != 0)) // checkme
|
||||
{
|
||||
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC);
|
||||
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO_Data1 : NDS::IRQ2_DSi_SD_Data1);
|
||||
DSi.SetIRQ2(Num ? IRQ2_DSi_SDIO : IRQ2_DSi_SDMMC);
|
||||
DSi.SetIRQ2(Num ? IRQ2_DSi_SDIO_Data1 : IRQ2_DSi_SD_Data1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,8 +282,8 @@ void DSi_SDHost::UpdateCardIRQ(u16 oldmask)
|
|||
|
||||
if ((oldflags == 0) && (newflags != 0)) // checkme
|
||||
{
|
||||
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC);
|
||||
NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO_Data1 : NDS::IRQ2_DSi_SD_Data1);
|
||||
DSi.SetIRQ2(Num ? IRQ2_DSi_SDIO : IRQ2_DSi_SDMMC);
|
||||
DSi.SetIRQ2(Num ? IRQ2_DSi_SDIO_Data1 : IRQ2_DSi_SD_Data1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,7 +324,7 @@ u32 DSi_SDHost::DataRX(u8* data, u32 len)
|
|||
// we need a delay because DSi boot2 will send a command and then wait for IRQ0
|
||||
// but if IRQ24 is thrown instantly, the handler clears IRQ0 before the
|
||||
// send-command function starts polling IRQ status
|
||||
NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
|
||||
DSi.ScheduleEvent(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
false, 512, Transfer_RX, 0);
|
||||
|
||||
return len;
|
||||
|
@ -366,7 +366,7 @@ u32 DSi_SDHost::DataTX(u8* data, u32 len)
|
|||
if (DataFIFO32.IsEmpty())
|
||||
{
|
||||
SetIRQ(25);
|
||||
DSi::CheckNDMAs(1, Num ? 0x29 : 0x28);
|
||||
DSi.CheckNDMAs(1, Num ? 0x29 : 0x28);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ u32 DSi_SDHost::DataTX(u8* data, u32 len)
|
|||
CurFIFO ^= 1;
|
||||
BlockCountInternal--;
|
||||
|
||||
NDS::ScheduleEvent(Num ? NDS::Event_DSi_SDIOTransfer : NDS::Event_DSi_SDMMCTransfer,
|
||||
DSi.ScheduleEvent(Num ? Event_DSi_SDIOTransfer : Event_DSi_SDMMCTransfer,
|
||||
false, 512, Transfer_TX, 0);
|
||||
|
||||
return len;
|
||||
|
@ -536,7 +536,7 @@ u16 DSi_SDHost::Read(u32 addr)
|
|||
case 0x10A: return 0;
|
||||
}
|
||||
|
||||
Log(LogLevel::Warn, "unknown %s read %08X @ %08X\n", SD_DESC, addr, NDS::GetPC(1));
|
||||
Log(LogLevel::Warn, "unknown %s read %08X @ %08X\n", SD_DESC, addr, DSi.GetPC(1));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -761,7 +761,7 @@ void DSi_SDHost::UpdateFIFO32()
|
|||
|
||||
if ((DataFIFO32.Level() << 2) >= BlockLen32)
|
||||
{
|
||||
DSi::CheckNDMAs(1, Num ? 0x29 : 0x28);
|
||||
DSi.CheckNDMAs(1, Num ? 0x29 : 0x28);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,12 +32,13 @@ namespace DSi_NAND
|
|||
}
|
||||
|
||||
class DSi_SDDevice;
|
||||
class DSi;
|
||||
|
||||
|
||||
class DSi_SDHost
|
||||
{
|
||||
public:
|
||||
DSi_SDHost(u32 num);
|
||||
DSi_SDHost(melonDS::DSi& dsi, u32 num);
|
||||
~DSi_SDHost();
|
||||
|
||||
void CloseHandles();
|
||||
|
@ -69,6 +70,7 @@ public:
|
|||
void CheckSwapFIFO();
|
||||
|
||||
private:
|
||||
melonDS::DSi& DSi;
|
||||
u32 Num;
|
||||
|
||||
u16 PortSelect;
|
||||
|
|
|
@ -28,7 +28,7 @@ using Platform::Log;
|
|||
using Platform::LogLevel;
|
||||
|
||||
|
||||
DSi_TSC::DSi_TSC(SPIHost* host) : TSC(host)
|
||||
DSi_TSC::DSi_TSC(melonDS::DSi& dsi) : TSC(dsi)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -198,7 +198,7 @@ void DSi_TSC::Write(u8 val)
|
|||
{
|
||||
Log(LogLevel::Debug, "DSi_SPI_TSC: DS-compatibility mode\n");
|
||||
DataPos = 0;
|
||||
NDS::KeyInput |= (1 << (16+6));
|
||||
NDS.KeyInput |= (1 << (16+6));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,11 @@
|
|||
|
||||
namespace melonDS
|
||||
{
|
||||
class DSi;
|
||||
class DSi_TSC : public TSC
|
||||
{
|
||||
public:
|
||||
DSi_TSC(SPIHost* host);
|
||||
DSi_TSC(melonDS::DSi& dsi);
|
||||
~DSi_TSC() override;
|
||||
|
||||
void Reset() override;
|
||||
|
|
|
@ -850,7 +850,7 @@ void GBACartSlot::LoadAddon(int type) noexcept
|
|||
{
|
||||
switch (type)
|
||||
{
|
||||
case NDS::GBAAddon_RAMExpansion:
|
||||
case GBAAddon_RAMExpansion:
|
||||
Cart = std::make_unique<CartRAMExpansion>();
|
||||
break;
|
||||
|
||||
|
|
60
src/GPU.cpp
60
src/GPU.cpp
|
@ -64,12 +64,12 @@ enum
|
|||
VRAMDirty need to be reset for the respective VRAM bank.
|
||||
*/
|
||||
|
||||
GPU::GPU(ARMJIT& jit) noexcept : GPU2D_A(0, *this), GPU2D_B(1, *this), JIT(jit)
|
||||
GPU::GPU(melonDS::NDS& nds) noexcept : NDS(nds), GPU2D_A(0, *this), GPU2D_B(1, *this), GPU3D(nds)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartHBlank, MemberEventFunc(GPU, StartHBlank));
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_StartScanline, MemberEventFunc(GPU, StartScanline));
|
||||
NDS::RegisterEventFunc(NDS::Event_LCD, LCD_FinishFrame, MemberEventFunc(GPU, FinishFrame));
|
||||
NDS::RegisterEventFunc(NDS::Event_DisplayFIFO, 0, MemberEventFunc(GPU, DisplayFIFO));
|
||||
NDS.RegisterEventFunc(Event_LCD, LCD_StartHBlank, MemberEventFunc(GPU, StartHBlank));
|
||||
NDS.RegisterEventFunc(Event_LCD, LCD_StartScanline, MemberEventFunc(GPU, StartScanline));
|
||||
NDS.RegisterEventFunc(Event_LCD, LCD_FinishFrame, MemberEventFunc(GPU, FinishFrame));
|
||||
NDS.RegisterEventFunc(Event_DisplayFIFO, 0, MemberEventFunc(GPU, DisplayFIFO));
|
||||
|
||||
GPU2D_Renderer = std::make_unique<GPU2D::SoftRenderer>(*this);
|
||||
|
||||
|
@ -92,10 +92,10 @@ GPU::~GPU() noexcept
|
|||
Framebuffer[1][0] = nullptr;
|
||||
Framebuffer[1][1] = nullptr;
|
||||
|
||||
NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_StartHBlank);
|
||||
NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_StartScanline);
|
||||
NDS::UnregisterEventFunc(NDS::Event_LCD, LCD_FinishFrame);
|
||||
NDS::UnregisterEventFunc(NDS::Event_DisplayFIFO, 0);
|
||||
NDS.UnregisterEventFunc(Event_LCD, LCD_StartHBlank);
|
||||
NDS.UnregisterEventFunc(Event_LCD, LCD_StartScanline);
|
||||
NDS.UnregisterEventFunc(Event_LCD, LCD_FinishFrame);
|
||||
NDS.UnregisterEventFunc(Event_DisplayFIFO, 0);
|
||||
}
|
||||
|
||||
void GPU::ResetVRAMCache() noexcept
|
||||
|
@ -298,7 +298,7 @@ void GPU::DoSavestate(Savestate* file) noexcept
|
|||
void GPU::AssignFramebuffers() noexcept
|
||||
{
|
||||
int backbuf = FrontBuffer ? 0 : 1;
|
||||
if (NDS::PowerControl9 & (1<<15))
|
||||
if (NDS.PowerControl9 & (1<<15))
|
||||
{
|
||||
GPU2D_Renderer->SetFramebuffer(Framebuffer[backbuf][0], Framebuffer[backbuf][1]);
|
||||
}
|
||||
|
@ -588,7 +588,7 @@ void GPU::MapVRAM_CD(u32 bank, u8 cnt) noexcept
|
|||
VRAMMap_ARM7[ofs] |= bankmask;
|
||||
memset(VRAMDirty[bank].Data, 0xFF, sizeof(VRAMDirty[bank].Data));
|
||||
VRAMSTAT |= (1 << (bank-2));
|
||||
JIT.CheckAndInvalidateWVRAM(ofs);
|
||||
NDS.JIT.CheckAndInvalidateWVRAM(ofs);
|
||||
break;
|
||||
|
||||
case 3: // texture
|
||||
|
@ -942,8 +942,8 @@ void GPU::DisplayFIFO(u32 x) noexcept
|
|||
if (x < 256)
|
||||
{
|
||||
// transfer the next 8 pixels
|
||||
NDS::CheckDMAs(0, 0x04);
|
||||
NDS::ScheduleEvent(NDS::Event_DisplayFIFO, true, 6*8, 0, x+8);
|
||||
NDS.CheckDMAs(0, 0x04);
|
||||
NDS.ScheduleEvent(Event_DisplayFIFO, true, 6*8, 0, x+8);
|
||||
}
|
||||
else
|
||||
GPU2D_A.SampleFIFO(253, 3); // sample the remaining pixels
|
||||
|
@ -954,7 +954,7 @@ void GPU::StartFrame() noexcept
|
|||
// only run the display FIFO if needed:
|
||||
// * if it is used for display or capture
|
||||
// * if we have display FIFO DMA
|
||||
RunFIFO = GPU2D_A.UsesFIFO() || NDS::DMAsInMode(0, 0x04);
|
||||
RunFIFO = GPU2D_A.UsesFIFO() || NDS.DMAsInMode(0, 0x04);
|
||||
|
||||
TotalScanlines = 0;
|
||||
StartScanline(0);
|
||||
|
@ -982,7 +982,7 @@ void GPU::StartHBlank(u32 line) noexcept
|
|||
GPU2D_Renderer->DrawSprites(line+1, &GPU2D_B);
|
||||
}
|
||||
|
||||
NDS::CheckDMAs(0, 0x02);
|
||||
NDS.CheckDMAs(0, 0x02);
|
||||
}
|
||||
else if (VCount == 215)
|
||||
{
|
||||
|
@ -994,13 +994,13 @@ void GPU::StartHBlank(u32 line) noexcept
|
|||
GPU2D_Renderer->DrawSprites(0, &GPU2D_B);
|
||||
}
|
||||
|
||||
if (DispStat[0] & (1<<4)) NDS::SetIRQ(0, NDS::IRQ_HBlank);
|
||||
if (DispStat[1] & (1<<4)) NDS::SetIRQ(1, NDS::IRQ_HBlank);
|
||||
if (DispStat[0] & (1<<4)) NDS.SetIRQ(0, IRQ_HBlank);
|
||||
if (DispStat[1] & (1<<4)) NDS.SetIRQ(1, IRQ_HBlank);
|
||||
|
||||
if (VCount < 262)
|
||||
NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), LCD_StartScanline, line+1);
|
||||
NDS.ScheduleEvent(Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), LCD_StartScanline, line+1);
|
||||
else
|
||||
NDS::ScheduleEvent(NDS::Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), LCD_FinishFrame, line+1);
|
||||
NDS.ScheduleEvent(Event_LCD, true, (LINE_CYCLES - HBLANK_CYCLES), LCD_FinishFrame, line+1);
|
||||
}
|
||||
|
||||
void GPU::FinishFrame(u32 lines) noexcept
|
||||
|
@ -1053,7 +1053,7 @@ void GPU::StartScanline(u32 line) noexcept
|
|||
{
|
||||
DispStat[0] |= (1<<2);
|
||||
|
||||
if (DispStat[0] & (1<<5)) NDS::SetIRQ(0, NDS::IRQ_VCount);
|
||||
if (DispStat[0] & (1<<5)) NDS.SetIRQ(0, IRQ_VCount);
|
||||
}
|
||||
else
|
||||
DispStat[0] &= ~(1<<2);
|
||||
|
@ -1062,7 +1062,7 @@ void GPU::StartScanline(u32 line) noexcept
|
|||
{
|
||||
DispStat[1] |= (1<<2);
|
||||
|
||||
if (DispStat[1] & (1<<5)) NDS::SetIRQ(1, NDS::IRQ_VCount);
|
||||
if (DispStat[1] & (1<<5)) NDS.SetIRQ(1, IRQ_VCount);
|
||||
}
|
||||
else
|
||||
DispStat[1] &= ~(1<<2);
|
||||
|
@ -1071,9 +1071,9 @@ void GPU::StartScanline(u32 line) noexcept
|
|||
GPU2D_B.CheckWindows(VCount);
|
||||
|
||||
if (VCount >= 2 && VCount < 194)
|
||||
NDS::CheckDMAs(0, 0x03);
|
||||
NDS.CheckDMAs(0, 0x03);
|
||||
else if (VCount == 194)
|
||||
NDS::StopDMAs(0, 0x03);
|
||||
NDS.StopDMAs(0, 0x03);
|
||||
|
||||
if (line < 192)
|
||||
{
|
||||
|
@ -1085,7 +1085,7 @@ void GPU::StartScanline(u32 line) noexcept
|
|||
}
|
||||
|
||||
if (RunFIFO)
|
||||
NDS::ScheduleEvent(NDS::Event_DisplayFIFO, false, 32, 0, 0);
|
||||
NDS.ScheduleEvent(Event_DisplayFIFO, false, 32, 0, 0);
|
||||
}
|
||||
|
||||
if (VCount == 262)
|
||||
|
@ -1111,13 +1111,13 @@ void GPU::StartScanline(u32 line) noexcept
|
|||
DispStat[0] |= (1<<0);
|
||||
DispStat[1] |= (1<<0);
|
||||
|
||||
NDS::StopDMAs(0, 0x04);
|
||||
NDS.StopDMAs(0, 0x04);
|
||||
|
||||
NDS::CheckDMAs(0, 0x01);
|
||||
NDS::CheckDMAs(1, 0x11);
|
||||
NDS.CheckDMAs(0, 0x01);
|
||||
NDS.CheckDMAs(1, 0x11);
|
||||
|
||||
if (DispStat[0] & (1<<3)) NDS::SetIRQ(0, NDS::IRQ_VBlank);
|
||||
if (DispStat[1] & (1<<3)) NDS::SetIRQ(1, NDS::IRQ_VBlank);
|
||||
if (DispStat[0] & (1<<3)) NDS.SetIRQ(0, IRQ_VBlank);
|
||||
if (DispStat[1] & (1<<3)) NDS.SetIRQ(1, IRQ_VBlank);
|
||||
|
||||
GPU2D_A.VBlank();
|
||||
GPU2D_B.VBlank();
|
||||
|
@ -1131,7 +1131,7 @@ void GPU::StartScanline(u32 line) noexcept
|
|||
}
|
||||
}
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_LCD, true, HBLANK_CYCLES, LCD_StartHBlank, line);
|
||||
NDS.ScheduleEvent(Event_LCD, true, HBLANK_CYCLES, LCD_StartHBlank, line);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ struct RenderSettings
|
|||
class GPU
|
||||
{
|
||||
public:
|
||||
GPU(ARMJIT& jit) noexcept;
|
||||
GPU(melonDS::NDS& nds) noexcept;
|
||||
~GPU() noexcept;
|
||||
void Reset() noexcept;
|
||||
void Stop() noexcept;
|
||||
|
@ -536,7 +536,7 @@ public:
|
|||
|
||||
void SyncDirtyFlags() noexcept;
|
||||
|
||||
ARMJIT& JIT;
|
||||
melonDS::NDS& NDS;
|
||||
u16 VCount = 0;
|
||||
u16 TotalScanlines = 0;
|
||||
u16 DispStat[2] {};
|
||||
|
@ -582,7 +582,7 @@ public:
|
|||
|
||||
GPU2D::Unit GPU2D_A;
|
||||
GPU2D::Unit GPU2D_B;
|
||||
melonDS::GPU3D GPU3D {};
|
||||
melonDS::GPU3D GPU3D;
|
||||
|
||||
NonStupidBitField<128*1024/VRAMDirtyGranularity> VRAMDirty[9] {};
|
||||
VRAMTrackingSet<512*1024, 16*1024> VRAMDirty_ABG {};
|
||||
|
|
|
@ -139,6 +139,10 @@ const u8 CmdNumParams[256] =
|
|||
|
||||
void MatrixLoadIdentity(s32* m);
|
||||
|
||||
GPU3D::GPU3D(melonDS::NDS& nds) noexcept : NDS(nds)
|
||||
{
|
||||
}
|
||||
|
||||
void GPU3D::ResetRenderingState() noexcept
|
||||
{
|
||||
RenderNumPolygons = 0;
|
||||
|
@ -1596,7 +1600,7 @@ void GPU3D::CmdFIFOWrite(CmdFIFOEntry& entry) noexcept
|
|||
// has 64 entries. this is less complicated than trying to make STMxx stall-able.
|
||||
|
||||
CmdStallQueue.Write(entry);
|
||||
NDS::GXFIFOStall();
|
||||
NDS.GXFIFOStall();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1640,7 +1644,7 @@ GPU3D::CmdFIFOEntry GPU3D::CmdFIFORead() noexcept
|
|||
}
|
||||
|
||||
if (CmdStallQueue.IsEmpty())
|
||||
NDS::GXFIFOUnstall();
|
||||
NDS.GXFIFOUnstall();
|
||||
}
|
||||
|
||||
CheckFIFODMA();
|
||||
|
@ -2273,13 +2277,13 @@ void GPU3D::Run() noexcept
|
|||
if (!GeometryEnabled || FlushRequest ||
|
||||
(CmdPIPE.IsEmpty() && !(GXStat & (1<<27))))
|
||||
{
|
||||
Timestamp = NDS::ARM9Timestamp >> NDS::ARM9ClockShift;
|
||||
Timestamp = NDS.ARM9Timestamp >> NDS.ARM9ClockShift;
|
||||
return;
|
||||
}
|
||||
|
||||
s32 cycles = (NDS::ARM9Timestamp >> NDS::ARM9ClockShift) - Timestamp;
|
||||
s32 cycles = (NDS.ARM9Timestamp >> NDS.ARM9ClockShift) - Timestamp;
|
||||
CycleCount -= cycles;
|
||||
Timestamp = NDS::ARM9Timestamp >> NDS::ARM9ClockShift;
|
||||
Timestamp = NDS.ARM9Timestamp >> NDS.ARM9ClockShift;
|
||||
|
||||
if (CycleCount <= 0)
|
||||
{
|
||||
|
@ -2312,14 +2316,14 @@ void GPU3D::CheckFIFOIRQ() noexcept
|
|||
case 2: irq = CmdFIFO.IsEmpty(); break;
|
||||
}
|
||||
|
||||
if (irq) NDS::SetIRQ(0, NDS::IRQ_GXFIFO);
|
||||
else NDS::ClearIRQ(0, NDS::IRQ_GXFIFO);
|
||||
if (irq) NDS.SetIRQ(0, IRQ_GXFIFO);
|
||||
else NDS.ClearIRQ(0, IRQ_GXFIFO);
|
||||
}
|
||||
|
||||
void GPU3D::CheckFIFODMA() noexcept
|
||||
{
|
||||
if (CmdFIFO.Level() < 128)
|
||||
NDS::CheckDMAs(0, 0x07);
|
||||
NDS.CheckDMAs(0, 0x07);
|
||||
}
|
||||
|
||||
void GPU3D::VCount144() noexcept
|
||||
|
|
|
@ -81,11 +81,12 @@ struct Polygon
|
|||
};
|
||||
|
||||
class Renderer3D;
|
||||
class NDS;
|
||||
|
||||
class GPU3D
|
||||
{
|
||||
public:
|
||||
GPU3D() noexcept = default;
|
||||
GPU3D(melonDS::NDS& nds) noexcept;
|
||||
~GPU3D() noexcept = default;
|
||||
void Reset() noexcept;
|
||||
|
||||
|
@ -124,6 +125,7 @@ public:
|
|||
void Write16(u32 addr, u16 val) noexcept;
|
||||
void Write32(u32 addr, u32 val) noexcept;
|
||||
private:
|
||||
melonDS::NDS& NDS;
|
||||
typedef union
|
||||
{
|
||||
u64 _contents;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
Copyright 2016-2023 melonDS team
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef MELONDS_MEMCONSTANTS_H
|
||||
#define MELONDS_MEMCONSTANTS_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
constexpr u32 MainRAMMaxSize = 0x1000000;
|
||||
constexpr u32 SharedWRAMSize = 0x8000;
|
||||
constexpr u32 ARM7WRAMSize = 0x10000;
|
||||
constexpr u32 NWRAMSize = 0x40000;
|
||||
constexpr u32 ARM9BIOSSize = 0x1000;
|
||||
constexpr u32 ARM7BIOSSize = 0x4000;
|
||||
constexpr u32 DSiBIOSSize = 0x10000;
|
||||
}
|
||||
|
||||
#endif // MELONDS_MEMCONSTANTS_H
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
Copyright 2016-2023 melonDS team
|
||||
|
||||
This file is part of melonDS.
|
||||
|
||||
melonDS is free software: you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation, either version 3 of the License, or (at your option)
|
||||
any later version.
|
||||
|
||||
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with melonDS. If not, see http://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
#ifndef MELONDS_MEMREGION_H
|
||||
#define MELONDS_MEMREGION_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
// this file exists to break #include cycle loops
|
||||
namespace melonDS
|
||||
{
|
||||
struct MemRegion
|
||||
{
|
||||
u8* Mem;
|
||||
u32 Mask;
|
||||
};
|
||||
}
|
||||
#endif //MELONDS_MEMREGION_H
|
1989
src/NDS.cpp
1989
src/NDS.cpp
File diff suppressed because it is too large
Load Diff
379
src/NDS.h
379
src/NDS.h
|
@ -29,6 +29,14 @@
|
|||
#include "types.h"
|
||||
#include "NDSCart.h"
|
||||
#include "GBACart.h"
|
||||
#include "SPU.h"
|
||||
#include "SPI.h"
|
||||
#include "RTC.h"
|
||||
#include "Wifi.h"
|
||||
#include "AREngine.h"
|
||||
#include "GPU.h"
|
||||
#include "ARMJIT.h"
|
||||
#include "DMA.h"
|
||||
|
||||
// when touching the main loop/timing code, pls test a lot of shit
|
||||
// with this enabled, to make sure it doesn't desync
|
||||
|
@ -36,17 +44,6 @@
|
|||
|
||||
namespace melonDS
|
||||
{
|
||||
class SPU;
|
||||
class SPIHost;
|
||||
class RTC;
|
||||
class Wifi;
|
||||
|
||||
class AREngine;
|
||||
class GPU;
|
||||
class ARMJIT;
|
||||
|
||||
namespace NDS
|
||||
{
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -75,7 +72,13 @@ enum
|
|||
|
||||
typedef std::function<void(u32)> EventFunc;
|
||||
#define MemberEventFunc(cls,func) std::bind(&cls::func,this,std::placeholders::_1)
|
||||
|
||||
struct SchedEvent
|
||||
{
|
||||
std::map<u32, EventFunc> Funcs;
|
||||
u64 Timestamp;
|
||||
u32 FuncID;
|
||||
u32 Param;
|
||||
};
|
||||
enum
|
||||
{
|
||||
IRQ_VBlank = 0,
|
||||
|
@ -197,196 +200,274 @@ enum
|
|||
// TODO: add DSi regions!
|
||||
};
|
||||
|
||||
struct MemRegion
|
||||
{
|
||||
u8* Mem;
|
||||
u32 Mask;
|
||||
};
|
||||
|
||||
// supported GBA slot addon types
|
||||
enum
|
||||
{
|
||||
GBAAddon_RAMExpansion = 1,
|
||||
};
|
||||
|
||||
class SPU;
|
||||
class SPIHost;
|
||||
class RTC;
|
||||
class Wifi;
|
||||
|
||||
class AREngine;
|
||||
class GPU;
|
||||
class ARMJIT;
|
||||
|
||||
class NDS
|
||||
{
|
||||
public:
|
||||
|
||||
#ifdef JIT_ENABLED
|
||||
extern bool EnableJIT;
|
||||
bool EnableJIT;
|
||||
#endif
|
||||
extern int ConsoleType;
|
||||
extern int CurCPU;
|
||||
int ConsoleType;
|
||||
int CurCPU;
|
||||
|
||||
extern u8 ARM9MemTimings[0x40000][8];
|
||||
extern u32 ARM9Regions[0x40000];
|
||||
extern u8 ARM7MemTimings[0x20000][4];
|
||||
extern u32 ARM7Regions[0x20000];
|
||||
SchedEvent SchedList[Event_MAX] {};
|
||||
u8 ARM9MemTimings[0x40000][8];
|
||||
u32 ARM9Regions[0x40000];
|
||||
u8 ARM7MemTimings[0x20000][4];
|
||||
u32 ARM7Regions[0x20000];
|
||||
|
||||
extern u32 NumFrames;
|
||||
extern u32 NumLagFrames;
|
||||
extern bool LagFrameFlag;
|
||||
u32 NumFrames;
|
||||
u32 NumLagFrames;
|
||||
bool LagFrameFlag;
|
||||
|
||||
extern u64 ARM9Timestamp, ARM9Target;
|
||||
extern u64 ARM7Timestamp, ARM7Target;
|
||||
extern u32 ARM9ClockShift;
|
||||
// no need to worry about those overflowing, they can keep going for atleast 4350 years
|
||||
u64 ARM9Timestamp, ARM9Target;
|
||||
u64 ARM7Timestamp, ARM7Target;
|
||||
u32 ARM9ClockShift;
|
||||
|
||||
extern u32 IME[2];
|
||||
extern u32 IE[2];
|
||||
extern u32 IF[2];
|
||||
extern u32 IE2;
|
||||
extern u32 IF2;
|
||||
extern Timer Timers[8];
|
||||
u32 IME[2];
|
||||
u32 IE[2];
|
||||
u32 IF[2];
|
||||
u32 IE2;
|
||||
u32 IF2;
|
||||
Timer Timers[8];
|
||||
|
||||
extern u32 CPUStop;
|
||||
u32 CPUStop;
|
||||
|
||||
extern u16 PowerControl9;
|
||||
u16 PowerControl9;
|
||||
|
||||
extern u16 ExMemCnt[2];
|
||||
extern u8 ROMSeed0[2*8];
|
||||
extern u8 ROMSeed1[2*8];
|
||||
u16 ExMemCnt[2];
|
||||
u8 ROMSeed0[2*8];
|
||||
u8 ROMSeed1[2*8];
|
||||
|
||||
extern u8 ARM9BIOS[0x1000];
|
||||
extern u8 ARM7BIOS[0x4000];
|
||||
extern u16 ARM7BIOSProt;
|
||||
u8 ARM9BIOS[0x1000];
|
||||
u8 ARM7BIOS[0x4000];
|
||||
u16 ARM7BIOSProt;
|
||||
|
||||
extern u8* MainRAM;
|
||||
extern u32 MainRAMMask;
|
||||
u8* MainRAM;
|
||||
u32 MainRAMMask;
|
||||
|
||||
const u32 MainRAMMaxSize = 0x1000000;
|
||||
const u32 MainRAMMaxSize = 0x1000000;
|
||||
|
||||
const u32 SharedWRAMSize = 0x8000;
|
||||
extern u8* SharedWRAM;
|
||||
const u32 SharedWRAMSize = 0x8000;
|
||||
u8* SharedWRAM;
|
||||
|
||||
extern MemRegion SWRAM_ARM9;
|
||||
extern MemRegion SWRAM_ARM7;
|
||||
MemRegion SWRAM_ARM9;
|
||||
MemRegion SWRAM_ARM7;
|
||||
|
||||
extern u32 KeyInput;
|
||||
extern u16 RCnt;
|
||||
u32 KeyInput;
|
||||
u16 RCnt;
|
||||
|
||||
extern class SPU* SPU;
|
||||
extern class SPIHost* SPI;
|
||||
extern class RTC* RTC;
|
||||
extern class Wifi* Wifi;
|
||||
extern std::unique_ptr<NDSCart::NDSCartSlot> NDSCartSlot;
|
||||
extern std::unique_ptr<GBACart::GBACartSlot> GBACartSlot;
|
||||
extern std::unique_ptr<GPU> GPU;
|
||||
extern std::unique_ptr<ARMJIT> JIT;
|
||||
extern class AREngine* AREngine;
|
||||
// JIT MUST be declared before all other component objects,
|
||||
// as they'll need the memory that it allocates in its constructor!
|
||||
// (Reminder: C++ fields are initialized in the order they're declared,
|
||||
// regardless of what the constructor's initializer list says.)
|
||||
melonDS::ARMJIT JIT;
|
||||
ARMv5 ARM9;
|
||||
ARMv4 ARM7;
|
||||
melonDS::SPU SPU;
|
||||
SPIHost SPI;
|
||||
melonDS::RTC RTC;
|
||||
melonDS::Wifi Wifi;
|
||||
NDSCart::NDSCartSlot NDSCartSlot;
|
||||
GBACart::GBACartSlot GBACartSlot;
|
||||
melonDS::GPU GPU;
|
||||
melonDS::AREngine AREngine;
|
||||
|
||||
const u32 ARM7WRAMSize = 0x10000;
|
||||
extern u8* ARM7WRAM;
|
||||
const u32 ARM7WRAMSize = 0x10000;
|
||||
u8* ARM7WRAM;
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
void Reset();
|
||||
void Start();
|
||||
virtual void Reset();
|
||||
void Start();
|
||||
|
||||
/// Stop the emulator.
|
||||
void Stop(Platform::StopReason reason = Platform::StopReason::External);
|
||||
/// Stop the emulator.
|
||||
virtual void Stop(Platform::StopReason reason = Platform::StopReason::External);
|
||||
|
||||
bool DoSavestate(Savestate* file);
|
||||
bool DoSavestate(Savestate* file);
|
||||
|
||||
void SetARM9RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq);
|
||||
void SetARM7RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq);
|
||||
void SetARM9RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq);
|
||||
void SetARM7RegionTimings(u32 addrstart, u32 addrend, u32 region, int buswidth, int nonseq, int seq);
|
||||
|
||||
// 0=DS 1=DSi
|
||||
void SetConsoleType(int type);
|
||||
// 0=DS 1=DSi
|
||||
void SetConsoleType(int type);
|
||||
|
||||
void LoadBIOS();
|
||||
bool IsLoadedARM9BIOSBuiltIn();
|
||||
bool IsLoadedARM7BIOSBuiltIn();
|
||||
void LoadBIOS();
|
||||
bool IsLoadedARM9BIOSBuiltIn();
|
||||
bool IsLoadedARM7BIOSBuiltIn();
|
||||
|
||||
bool LoadCart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen);
|
||||
void LoadSave(const u8* savedata, u32 savelen);
|
||||
void EjectCart();
|
||||
bool CartInserted();
|
||||
virtual bool LoadCart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen);
|
||||
void LoadSave(const u8* savedata, u32 savelen);
|
||||
virtual void EjectCart();
|
||||
bool CartInserted();
|
||||
|
||||
bool NeedsDirectBoot();
|
||||
void SetupDirectBoot(const std::string& romname);
|
||||
virtual bool NeedsDirectBoot();
|
||||
void SetupDirectBoot(const std::string& romname);
|
||||
virtual void SetupDirectBoot();
|
||||
|
||||
bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen);
|
||||
void LoadGBAAddon(int type);
|
||||
void EjectGBACart();
|
||||
bool LoadGBACart(const u8* romdata, u32 romlen, const u8* savedata, u32 savelen);
|
||||
void LoadGBAAddon(int type);
|
||||
void EjectGBACart();
|
||||
|
||||
u32 RunFrame();
|
||||
u32 RunFrame();
|
||||
|
||||
void TouchScreen(u16 x, u16 y);
|
||||
void ReleaseScreen();
|
||||
bool IsRunning() const noexcept { return Running; }
|
||||
|
||||
void SetKeyMask(u32 mask);
|
||||
void TouchScreen(u16 x, u16 y);
|
||||
void ReleaseScreen();
|
||||
|
||||
bool IsLidClosed();
|
||||
void SetLidClosed(bool closed);
|
||||
void SetKeyMask(u32 mask);
|
||||
|
||||
void CamInputFrame(int cam, u32* data, int width, int height, bool rgb);
|
||||
void MicInputFrame(s16* data, int samples);
|
||||
bool IsLidClosed();
|
||||
void SetLidClosed(bool closed);
|
||||
|
||||
void RegisterEventFunc(u32 id, u32 funcid, EventFunc func);
|
||||
void UnregisterEventFunc(u32 id, u32 funcid);
|
||||
void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param);
|
||||
void CancelEvent(u32 id);
|
||||
virtual void CamInputFrame(int cam, u32* data, int width, int height, bool rgb) {}
|
||||
void MicInputFrame(s16* data, int samples);
|
||||
|
||||
void debug(u32 p);
|
||||
void RegisterEventFunc(u32 id, u32 funcid, EventFunc func);
|
||||
void UnregisterEventFunc(u32 id, u32 funcid);
|
||||
void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param);
|
||||
void CancelEvent(u32 id);
|
||||
|
||||
void Halt();
|
||||
void debug(u32 p);
|
||||
|
||||
void MapSharedWRAM(u8 val);
|
||||
void Halt();
|
||||
|
||||
void UpdateIRQ(u32 cpu);
|
||||
void SetIRQ(u32 cpu, u32 irq);
|
||||
void ClearIRQ(u32 cpu, u32 irq);
|
||||
void SetIRQ2(u32 irq);
|
||||
void ClearIRQ2(u32 irq);
|
||||
bool HaltInterrupted(u32 cpu);
|
||||
void StopCPU(u32 cpu, u32 mask);
|
||||
void ResumeCPU(u32 cpu, u32 mask);
|
||||
void GXFIFOStall();
|
||||
void GXFIFOUnstall();
|
||||
void MapSharedWRAM(u8 val);
|
||||
|
||||
u32 GetPC(u32 cpu);
|
||||
u64 GetSysClockCycles(int num);
|
||||
void NocashPrint(u32 cpu, u32 addr);
|
||||
void UpdateIRQ(u32 cpu);
|
||||
void SetIRQ(u32 cpu, u32 irq);
|
||||
void ClearIRQ(u32 cpu, u32 irq);
|
||||
void SetIRQ2(u32 irq);
|
||||
void ClearIRQ2(u32 irq);
|
||||
bool HaltInterrupted(u32 cpu);
|
||||
void StopCPU(u32 cpu, u32 mask);
|
||||
void ResumeCPU(u32 cpu, u32 mask);
|
||||
void GXFIFOStall();
|
||||
void GXFIFOUnstall();
|
||||
|
||||
void MonitorARM9Jump(u32 addr);
|
||||
u32 GetPC(u32 cpu);
|
||||
u64 GetSysClockCycles(int num);
|
||||
void NocashPrint(u32 cpu, u32 addr);
|
||||
|
||||
bool DMAsInMode(u32 cpu, u32 mode);
|
||||
bool DMAsRunning(u32 cpu);
|
||||
void CheckDMAs(u32 cpu, u32 mode);
|
||||
void StopDMAs(u32 cpu, u32 mode);
|
||||
void MonitorARM9Jump(u32 addr);
|
||||
|
||||
void RunTimers(u32 cpu);
|
||||
virtual bool DMAsInMode(u32 cpu, u32 mode);
|
||||
virtual bool DMAsRunning(u32 cpu);
|
||||
virtual void CheckDMAs(u32 cpu, u32 mode);
|
||||
virtual void StopDMAs(u32 cpu, u32 mode);
|
||||
|
||||
u8 ARM9Read8(u32 addr);
|
||||
u16 ARM9Read16(u32 addr);
|
||||
u32 ARM9Read32(u32 addr);
|
||||
void ARM9Write8(u32 addr, u8 val);
|
||||
void ARM9Write16(u32 addr, u16 val);
|
||||
void ARM9Write32(u32 addr, u32 val);
|
||||
void RunTimers(u32 cpu);
|
||||
|
||||
bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region);
|
||||
virtual u8 ARM9Read8(u32 addr);
|
||||
virtual u16 ARM9Read16(u32 addr);
|
||||
virtual u32 ARM9Read32(u32 addr);
|
||||
virtual void ARM9Write8(u32 addr, u8 val);
|
||||
virtual void ARM9Write16(u32 addr, u16 val);
|
||||
virtual void ARM9Write32(u32 addr, u32 val);
|
||||
|
||||
u8 ARM7Read8(u32 addr);
|
||||
u16 ARM7Read16(u32 addr);
|
||||
u32 ARM7Read32(u32 addr);
|
||||
void ARM7Write8(u32 addr, u8 val);
|
||||
void ARM7Write16(u32 addr, u16 val);
|
||||
void ARM7Write32(u32 addr, u32 val);
|
||||
virtual bool ARM9GetMemRegion(u32 addr, bool write, MemRegion* region);
|
||||
|
||||
bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region);
|
||||
virtual u8 ARM7Read8(u32 addr);
|
||||
virtual u16 ARM7Read16(u32 addr);
|
||||
virtual u32 ARM7Read32(u32 addr);
|
||||
virtual void ARM7Write8(u32 addr, u8 val);
|
||||
virtual void ARM7Write16(u32 addr, u16 val);
|
||||
virtual void ARM7Write32(u32 addr, u32 val);
|
||||
|
||||
u8 ARM9IORead8(u32 addr);
|
||||
u16 ARM9IORead16(u32 addr);
|
||||
u32 ARM9IORead32(u32 addr);
|
||||
void ARM9IOWrite8(u32 addr, u8 val);
|
||||
void ARM9IOWrite16(u32 addr, u16 val);
|
||||
void ARM9IOWrite32(u32 addr, u32 val);
|
||||
virtual bool ARM7GetMemRegion(u32 addr, bool write, MemRegion* region);
|
||||
|
||||
u8 ARM7IORead8(u32 addr);
|
||||
u16 ARM7IORead16(u32 addr);
|
||||
u32 ARM7IORead32(u32 addr);
|
||||
void ARM7IOWrite8(u32 addr, u8 val);
|
||||
void ARM7IOWrite16(u32 addr, u16 val);
|
||||
void ARM7IOWrite32(u32 addr, u32 val);
|
||||
virtual u8 ARM9IORead8(u32 addr);
|
||||
virtual u16 ARM9IORead16(u32 addr);
|
||||
virtual u32 ARM9IORead32(u32 addr);
|
||||
virtual void ARM9IOWrite8(u32 addr, u8 val);
|
||||
virtual void ARM9IOWrite16(u32 addr, u16 val);
|
||||
virtual void ARM9IOWrite32(u32 addr, u32 val);
|
||||
|
||||
}
|
||||
virtual u8 ARM7IORead8(u32 addr);
|
||||
virtual u16 ARM7IORead16(u32 addr);
|
||||
virtual u32 ARM7IORead32(u32 addr);
|
||||
virtual void ARM7IOWrite8(u32 addr, u8 val);
|
||||
virtual void ARM7IOWrite16(u32 addr, u16 val);
|
||||
virtual void ARM7IOWrite32(u32 addr, u32 val);
|
||||
|
||||
private:
|
||||
void InitTimings();
|
||||
u32 SchedListMask;
|
||||
u64 SysTimestamp;
|
||||
u8 WRAMCnt;
|
||||
u8 PostFlag9;
|
||||
u8 PostFlag7;
|
||||
u16 PowerControl7;
|
||||
u16 WifiWaitCnt;
|
||||
u8 TimerCheckMask[2];
|
||||
u64 TimerTimestamp[2];
|
||||
DMA DMAs[8];
|
||||
u32 DMA9Fill[4];
|
||||
u16 IPCSync9, IPCSync7;
|
||||
u16 IPCFIFOCnt9, IPCFIFOCnt7;
|
||||
FIFO<u32, 16> IPCFIFO9; // FIFO in which the ARM9 writes
|
||||
FIFO<u32, 16> IPCFIFO7;
|
||||
u16 DivCnt;
|
||||
u32 DivNumerator[2];
|
||||
u32 DivDenominator[2];
|
||||
u32 DivQuotient[2];
|
||||
u32 DivRemainder[2];
|
||||
u16 SqrtCnt;
|
||||
u32 SqrtVal[2];
|
||||
u32 SqrtRes;
|
||||
u16 KeyCnt[2];
|
||||
bool Running;
|
||||
bool RunningGame;
|
||||
u64 LastSysClockCycles;
|
||||
u64 FrameStartTimestamp;
|
||||
u64 NextTarget();
|
||||
u64 NextTargetSleep();
|
||||
void CheckKeyIRQ(u32 cpu, u32 oldkey, u32 newkey);
|
||||
void Reschedule(u64 target);
|
||||
void RunSystemSleep(u64 timestamp);
|
||||
void RunSystem(u64 timestamp);
|
||||
void HandleTimerOverflow(u32 tid);
|
||||
u16 TimerGetCounter(u32 timer);
|
||||
void TimerStart(u32 id, u16 cnt);
|
||||
void StartDiv();
|
||||
void DivDone(u32 param);
|
||||
void SqrtDone(u32 param);
|
||||
void StartSqrt();
|
||||
void RunTimer(u32 tid, s32 cycles);
|
||||
void UpdateWifiTimings();
|
||||
void SetWifiWaitCnt(u16 val);
|
||||
void SetGBASlotTimings();
|
||||
void EnterSleepMode();
|
||||
template <bool EnableJIT>
|
||||
u32 RunFrame();
|
||||
public:
|
||||
NDS() noexcept : NDS(0) {}
|
||||
virtual ~NDS() noexcept;
|
||||
NDS(const NDS&) = delete;
|
||||
NDS& operator=(const NDS&) = delete;
|
||||
NDS(NDS&&) = delete;
|
||||
NDS& operator=(NDS&&) = delete;
|
||||
// The frontend should set and unset this manually after creating and destroying the NDS object.
|
||||
[[deprecated("Temporary workaround until JIT code generation is revised to accommodate multiple NDS objects.")]] static NDS* Current;
|
||||
protected:
|
||||
explicit NDS(int type) noexcept;
|
||||
virtual void DoSavestateExtra(Savestate* file) {}
|
||||
};
|
||||
|
||||
}
|
||||
#endif // NDS_H
|
||||
|
|
107
src/NDSCart.cpp
107
src/NDSCart.cpp
|
@ -214,11 +214,11 @@ void CartCommon::Reset()
|
|||
DSiMode = false;
|
||||
}
|
||||
|
||||
void CartCommon::SetupDirectBoot(const std::string& romname)
|
||||
void CartCommon::SetupDirectBoot(const std::string& romname, NDS& nds)
|
||||
{
|
||||
CmdEncMode = 2;
|
||||
DataEncMode = 2;
|
||||
DSiMode = IsDSi && (NDS::ConsoleType==1);
|
||||
DSiMode = IsDSi && (nds.ConsoleType==1);
|
||||
}
|
||||
|
||||
void CartCommon::DoSavestate(Savestate* file)
|
||||
|
@ -238,7 +238,7 @@ void CartCommon::LoadSave(const u8* savedata, u32 savelen)
|
|||
{
|
||||
}
|
||||
|
||||
int CartCommon::ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len)
|
||||
int CartCommon::ROMCommandStart(NDS& nds, NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len)
|
||||
{
|
||||
if (CmdEncMode == 0)
|
||||
{
|
||||
|
@ -267,15 +267,16 @@ int CartCommon::ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* dat
|
|||
|
||||
case 0x3C:
|
||||
CmdEncMode = 1;
|
||||
cartslot.Key1_InitKeycode(false, *(u32*)&ROM[0xC], 2, 2, NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
cartslot.Key1_InitKeycode(false, *(u32*)&ROM[0xC], 2, 2, nds.ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
DSiMode = false;
|
||||
return 0;
|
||||
|
||||
case 0x3D:
|
||||
if (IsDSi)
|
||||
{
|
||||
auto& dsi = static_cast<DSi&>(nds);
|
||||
CmdEncMode = 1;
|
||||
cartslot.Key1_InitKeycode(true, *(u32*)&ROM[0xC], 1, 2, DSi::ARM7iBIOS, sizeof(DSi::ARM7iBIOS));
|
||||
cartslot.Key1_InitKeycode(true, *(u32*)&ROM[0xC], 1, 2, dsi.ARM7iBIOS, sizeof(DSi::ARM7iBIOS));
|
||||
DSiMode = true;
|
||||
}
|
||||
return 0;
|
||||
|
@ -359,12 +360,6 @@ u8 CartCommon::SPIWrite(u8 val, u32 pos, bool last)
|
|||
return 0xFF;
|
||||
}
|
||||
|
||||
void CartCommon::SetIRQ()
|
||||
{
|
||||
NDS::SetIRQ(0, NDS::IRQ_CartIREQMC);
|
||||
NDS::SetIRQ(1, NDS::IRQ_CartIREQMC);
|
||||
}
|
||||
|
||||
u8 *CartCommon::GetSaveMemory() const
|
||||
{
|
||||
return nullptr;
|
||||
|
@ -496,9 +491,9 @@ void CartRetail::LoadSave(const u8* savedata, u32 savelen)
|
|||
Platform::WriteNDSSave(savedata, len, 0, len);
|
||||
}
|
||||
|
||||
int CartRetail::ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len)
|
||||
int CartRetail::ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len)
|
||||
{
|
||||
if (CmdEncMode != 2) return CartCommon::ROMCommandStart(cartslot, cmd, data, len);
|
||||
if (CmdEncMode != 2) return CartCommon::ROMCommandStart(nds, cartslot, cmd, data, len);
|
||||
|
||||
switch (cmd[0])
|
||||
{
|
||||
|
@ -519,7 +514,7 @@ int CartRetail::ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* dat
|
|||
return 0;
|
||||
|
||||
default:
|
||||
return CartCommon::ROMCommandStart(cartslot, cmd, data, len);
|
||||
return CartCommon::ROMCommandStart(nds, cartslot, cmd, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -900,9 +895,9 @@ void CartRetailNAND::LoadSave(const u8* savedata, u32 savelen)
|
|||
BuildSRAMID();
|
||||
}
|
||||
|
||||
int CartRetailNAND::ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len)
|
||||
int CartRetailNAND::ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len)
|
||||
{
|
||||
if (CmdEncMode != 2) return CartCommon::ROMCommandStart(cartslot, cmd, data, len);
|
||||
if (CmdEncMode != 2) return CartCommon::ROMCommandStart(nds, cartslot, cmd, data, len);
|
||||
|
||||
switch (cmd[0])
|
||||
{
|
||||
|
@ -1032,7 +1027,7 @@ int CartRetailNAND::ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8*
|
|||
return 0;
|
||||
|
||||
default:
|
||||
return CartRetail::ROMCommandStart(cartslot, cmd, data, len);
|
||||
return CartRetail::ROMCommandStart(nds, cartslot, cmd, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1152,7 +1147,7 @@ void CartRetailBT::DoSavestate(Savestate* file)
|
|||
|
||||
u8 CartRetailBT::SPIWrite(u8 val, u32 pos, bool last)
|
||||
{
|
||||
Log(LogLevel::Debug,"POKETYPE SPI: %02X %d %d - %08X\n", val, pos, last, NDS::GetPC(0));
|
||||
//Log(LogLevel::Debug,"POKETYPE SPI: %02X %d %d - %08X\n", val, pos, last, NDS::GetPC(0));
|
||||
|
||||
/*if (pos == 0)
|
||||
{
|
||||
|
@ -1210,9 +1205,9 @@ void CartHomebrew::Reset()
|
|||
SD = nullptr;
|
||||
}
|
||||
|
||||
void CartHomebrew::SetupDirectBoot(const std::string& romname)
|
||||
void CartHomebrew::SetupDirectBoot(const std::string& romname, NDS& nds)
|
||||
{
|
||||
CartCommon::SetupDirectBoot(romname);
|
||||
CartCommon::SetupDirectBoot(romname, nds);
|
||||
|
||||
if (SD)
|
||||
{
|
||||
|
@ -1231,17 +1226,17 @@ void CartHomebrew::SetupDirectBoot(const std::string& romname)
|
|||
argvlen = strlen(argv);
|
||||
|
||||
const NDSHeader& header = GetHeader();
|
||||
void (*writefn)(u32,u32) = (NDS::ConsoleType==1) ? DSi::ARM9Write32 : NDS::ARM9Write32;
|
||||
|
||||
u32 argvbase = header.ARM9RAMAddress + header.ARM9Size;
|
||||
argvbase = (argvbase + 0xF) & ~0xF;
|
||||
|
||||
for (u32 i = 0; i <= argvlen; i+=4)
|
||||
writefn(argvbase+i, *(u32*)&argv[i]);
|
||||
nds.ARM9Write32(argvbase+i, *(u32*)&argv[i]);
|
||||
|
||||
writefn(0x02FFFE70, 0x5F617267);
|
||||
writefn(0x02FFFE74, argvbase);
|
||||
writefn(0x02FFFE78, argvlen+1);
|
||||
nds.ARM9Write32(0x02FFFE70, 0x5F617267);
|
||||
nds.ARM9Write32(0x02FFFE74, argvbase);
|
||||
nds.ARM9Write32(0x02FFFE78, argvlen+1);
|
||||
// The DSi version of ARM9Write32 will be called if nds is really a DSi
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1250,9 +1245,9 @@ void CartHomebrew::DoSavestate(Savestate* file)
|
|||
CartCommon::DoSavestate(file);
|
||||
}
|
||||
|
||||
int CartHomebrew::ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len)
|
||||
int CartHomebrew::ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len)
|
||||
{
|
||||
if (CmdEncMode != 2) return CartCommon::ROMCommandStart(cartslot, cmd, data, len);
|
||||
if (CmdEncMode != 2) return CartCommon::ROMCommandStart(nds, cartslot, cmd, data, len);
|
||||
|
||||
switch (cmd[0])
|
||||
{
|
||||
|
@ -1283,7 +1278,7 @@ int CartHomebrew::ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* d
|
|||
return 1;
|
||||
|
||||
default:
|
||||
return CartCommon::ROMCommandStart(cartslot, cmd, data, len);
|
||||
return CartCommon::ROMCommandStart(nds, cartslot, cmd, data, len);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1449,19 +1444,19 @@ void CartHomebrew::ReadROM_B7(u32 addr, u32 len, u8* data, u32 offset)
|
|||
|
||||
|
||||
|
||||
NDSCartSlot::NDSCartSlot() noexcept
|
||||
NDSCartSlot::NDSCartSlot(melonDS::NDS& nds) noexcept : NDS(nds)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_ROMTransfer, ROMTransfer_PrepareData, MemberEventFunc(NDSCartSlot, ROMPrepareData));
|
||||
NDS::RegisterEventFunc(NDS::Event_ROMTransfer, ROMTransfer_End, MemberEventFunc(NDSCartSlot, ROMEndTransfer));
|
||||
NDS::RegisterEventFunc(NDS::Event_ROMSPITransfer, 0, MemberEventFunc(NDSCartSlot, SPITransferDone));
|
||||
NDS.RegisterEventFunc(Event_ROMTransfer, ROMTransfer_PrepareData, MemberEventFunc(NDSCartSlot, ROMPrepareData));
|
||||
NDS.RegisterEventFunc(Event_ROMTransfer, ROMTransfer_End, MemberEventFunc(NDSCartSlot, ROMEndTransfer));
|
||||
NDS.RegisterEventFunc(Event_ROMSPITransfer, 0, MemberEventFunc(NDSCartSlot, SPITransferDone));
|
||||
// All fields are default-constructed because they're listed as such in the class declaration
|
||||
}
|
||||
|
||||
NDSCartSlot::~NDSCartSlot() noexcept
|
||||
{
|
||||
NDS::UnregisterEventFunc(NDS::Event_ROMTransfer, ROMTransfer_PrepareData);
|
||||
NDS::UnregisterEventFunc(NDS::Event_ROMTransfer, ROMTransfer_End);
|
||||
NDS::UnregisterEventFunc(NDS::Event_ROMSPITransfer, 0);
|
||||
NDS.UnregisterEventFunc(Event_ROMTransfer, ROMTransfer_PrepareData);
|
||||
NDS.UnregisterEventFunc(Event_ROMTransfer, ROMTransfer_End);
|
||||
NDS.UnregisterEventFunc(Event_ROMSPITransfer, 0);
|
||||
|
||||
// Cart is cleaned up automatically because it's a unique_ptr
|
||||
}
|
||||
|
@ -1574,10 +1569,10 @@ void NDSCartSlot::DecryptSecureArea(u8* out) noexcept
|
|||
|
||||
memcpy(out, &cartrom[arm9base], 0x800);
|
||||
|
||||
Key1_InitKeycode(false, gamecode, 2, 2, NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
Key1_InitKeycode(false, gamecode, 2, 2, NDS.ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
Key1_Decrypt((u32*)&out[0]);
|
||||
|
||||
Key1_InitKeycode(false, gamecode, 3, 2, NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
Key1_InitKeycode(false, gamecode, 3, 2, NDS.ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
for (u32 i = 0; i < 0x800; i += 8)
|
||||
Key1_Decrypt((u32*)&out[i]);
|
||||
|
||||
|
@ -1744,11 +1739,11 @@ bool NDSCartSlot::InsertROM(std::unique_ptr<CartCommon>&& cart) noexcept
|
|||
|
||||
strncpy((char*)&cartrom[header.ARM9ROMOffset], "encryObj", 8);
|
||||
|
||||
Key1_InitKeycode(false, romparams.GameCode, 3, 2, NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
Key1_InitKeycode(false, romparams.GameCode, 3, 2, NDS.ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
for (u32 i = 0; i < 0x800; i += 8)
|
||||
Key1_Encrypt((u32*)&cartrom[header.ARM9ROMOffset + i]);
|
||||
|
||||
Key1_InitKeycode(false, romparams.GameCode, 2, 2, NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
Key1_InitKeycode(false, romparams.GameCode, 2, 2, NDS.ARM7BIOS, sizeof(NDS::ARM7BIOS));
|
||||
Key1_Encrypt((u32*)&cartrom[header.ARM9ROMOffset]);
|
||||
|
||||
Log(LogLevel::Debug, "Re-encrypted cart secure area\n");
|
||||
|
@ -1763,8 +1758,6 @@ bool NDSCartSlot::InsertROM(std::unique_ptr<CartCommon>&& cart) noexcept
|
|||
Log(LogLevel::Info, "Inserted cart with ID: %08X\n", Cart->ID());
|
||||
Log(LogLevel::Info, "ROM entry: %08X %08X\n", romparams.ROMSize, romparams.SaveMemType);
|
||||
|
||||
DSi::SetCartInserted(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1784,7 +1777,7 @@ void NDSCartSlot::LoadSave(const u8* savedata, u32 savelen) noexcept
|
|||
void NDSCartSlot::SetupDirectBoot(const std::string& romname) noexcept
|
||||
{
|
||||
if (Cart)
|
||||
Cart->SetupDirectBoot(romname);
|
||||
Cart->SetupDirectBoot(romname, NDS);
|
||||
}
|
||||
|
||||
void NDSCartSlot::EjectCart() noexcept
|
||||
|
@ -1792,13 +1785,11 @@ void NDSCartSlot::EjectCart() noexcept
|
|||
if (!Cart) return;
|
||||
|
||||
// ejecting the cart triggers the gamecard IRQ
|
||||
NDS::SetIRQ(0, NDS::IRQ_CartIREQMC);
|
||||
NDS::SetIRQ(1, NDS::IRQ_CartIREQMC);
|
||||
NDS.SetIRQ(0, IRQ_CartIREQMC);
|
||||
NDS.SetIRQ(1, IRQ_CartIREQMC);
|
||||
|
||||
Cart = nullptr;
|
||||
|
||||
DSi::SetCartInserted(false);
|
||||
|
||||
// CHECKME: does an eject imply anything for the ROM/SPI transfer registers?
|
||||
}
|
||||
|
||||
|
@ -1835,7 +1826,7 @@ void NDSCartSlot::ROMEndTransfer(u32 param) noexcept
|
|||
ROMCnt &= ~(1<<31);
|
||||
|
||||
if (SPICnt & (1<<14))
|
||||
NDS::SetIRQ((NDS::ExMemCnt[0]>>11)&0x1, NDS::IRQ_CartXferDone);
|
||||
NDS.SetIRQ((NDS.ExMemCnt[0]>>11)&0x1, IRQ_CartXferDone);
|
||||
|
||||
if (Cart)
|
||||
Cart->ROMCommandFinish(TransferCmd.data(), TransferData.data(), TransferLen);
|
||||
|
@ -1855,10 +1846,10 @@ void NDSCartSlot::ROMPrepareData(u32 param) noexcept
|
|||
|
||||
ROMCnt |= (1<<23);
|
||||
|
||||
if (NDS::ExMemCnt[0] & (1<<11))
|
||||
NDS::CheckDMAs(1, 0x12);
|
||||
if (NDS.ExMemCnt[0] & (1<<11))
|
||||
NDS.CheckDMAs(1, 0x12);
|
||||
else
|
||||
NDS::CheckDMAs(0, 0x05);
|
||||
NDS.CheckDMAs(0, 0x05);
|
||||
}
|
||||
|
||||
void NDSCartSlot::WriteROMCnt(u32 val) noexcept
|
||||
|
@ -1870,9 +1861,9 @@ void NDSCartSlot::WriteROMCnt(u32 val) noexcept
|
|||
// a DS cart reader
|
||||
if (val & (1<<15))
|
||||
{
|
||||
u32 snum = (NDS::ExMemCnt[0]>>8)&0x8;
|
||||
u64 seed0 = *(u32*)&NDS::ROMSeed0[snum] | ((u64)NDS::ROMSeed0[snum+4] << 32);
|
||||
u64 seed1 = *(u32*)&NDS::ROMSeed1[snum] | ((u64)NDS::ROMSeed1[snum+4] << 32);
|
||||
u32 snum = (NDS.ExMemCnt[0]>>8)&0x8;
|
||||
u64 seed0 = *(u32*)&NDS.ROMSeed0[snum] | ((u64)NDS.ROMSeed0[snum+4] << 32);
|
||||
u64 seed1 = *(u32*)&NDS.ROMSeed1[snum] | ((u64)NDS.ROMSeed1[snum+4] << 32);
|
||||
|
||||
Key2_X = 0;
|
||||
Key2_Y = 0;
|
||||
|
@ -1919,7 +1910,7 @@ void NDSCartSlot::WriteROMCnt(u32 val) noexcept
|
|||
TransferDir = 0;
|
||||
|
||||
if (Cart)
|
||||
TransferDir = Cart->ROMCommandStart(*this, TransferCmd.data(), TransferData.data(), TransferLen);
|
||||
TransferDir = Cart->ROMCommandStart(NDS, *this, TransferCmd.data(), TransferData.data(), TransferLen);
|
||||
|
||||
if ((datasize > 0) && (((ROMCnt >> 30) & 0x1) != TransferDir))
|
||||
Log(LogLevel::Debug, "NDSCART: !! BAD TRANSFER DIRECTION FOR CMD %02X, DIR=%d, ROMCNT=%08X\n", ROMCommand[0], TransferDir, ROMCnt);
|
||||
|
@ -1945,9 +1936,9 @@ void NDSCartSlot::WriteROMCnt(u32 val) noexcept
|
|||
}
|
||||
|
||||
if (datasize == 0)
|
||||
NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*cmddelay, ROMTransfer_End, 0);
|
||||
NDS.ScheduleEvent(Event_ROMTransfer, false, xfercycle*cmddelay, ROMTransfer_End, 0);
|
||||
else
|
||||
NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*(cmddelay+4), ROMTransfer_PrepareData, 0);
|
||||
NDS.ScheduleEvent(Event_ROMTransfer, false, xfercycle*(cmddelay+4), ROMTransfer_PrepareData, 0);
|
||||
}
|
||||
|
||||
void NDSCartSlot::AdvanceROMTransfer() noexcept
|
||||
|
@ -1964,7 +1955,7 @@ void NDSCartSlot::AdvanceROMTransfer() noexcept
|
|||
delay += ((ROMCnt >> 16) & 0x3F);
|
||||
}
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_ROMTransfer, false, xfercycle*delay, ROMTransfer_PrepareData, 0);
|
||||
NDS.ScheduleEvent(Event_ROMTransfer, false, xfercycle*delay, ROMTransfer_PrepareData, 0);
|
||||
}
|
||||
else
|
||||
ROMEndTransfer(0);
|
||||
|
@ -2066,7 +2057,7 @@ void NDSCartSlot::WriteSPIData(u8 val) noexcept
|
|||
|
||||
// SPI transfers one bit per cycle -> 8 cycles per byte
|
||||
u32 delay = 8 * (8 << (SPICnt & 0x3));
|
||||
NDS::ScheduleEvent(NDS::Event_ROMSPITransfer, false, delay, 0, 0);
|
||||
NDS.ScheduleEvent(Event_ROMSPITransfer, false, delay, 0, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,6 +30,10 @@
|
|||
#include "FATStorage.h"
|
||||
#include "ROMList.h"
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
class NDS;
|
||||
}
|
||||
namespace melonDS::NDSCart
|
||||
{
|
||||
|
||||
|
@ -56,14 +60,14 @@ public:
|
|||
[[nodiscard]] u32 Checksum() const;
|
||||
|
||||
virtual void Reset();
|
||||
virtual void SetupDirectBoot(const std::string& romname);
|
||||
virtual void SetupDirectBoot(const std::string& romname, NDS& nds);
|
||||
|
||||
virtual void DoSavestate(Savestate* file);
|
||||
|
||||
virtual void SetupSave(u32 type);
|
||||
virtual void LoadSave(const u8* savedata, u32 savelen);
|
||||
|
||||
virtual int ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len);
|
||||
virtual int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len);
|
||||
virtual void ROMCommandFinish(u8* cmd, u8* data, u32 len);
|
||||
|
||||
virtual u8 SPIWrite(u8 val, u32 pos, bool last);
|
||||
|
@ -83,8 +87,6 @@ public:
|
|||
protected:
|
||||
void ReadROM(u32 addr, u32 len, u8* data, u32 offset);
|
||||
|
||||
void SetIRQ();
|
||||
|
||||
u8* ROM;
|
||||
u32 ROMLength;
|
||||
u32 ChipID;
|
||||
|
@ -116,7 +118,7 @@ public:
|
|||
virtual void SetupSave(u32 type) override;
|
||||
virtual void LoadSave(const u8* savedata, u32 savelen) override;
|
||||
|
||||
virtual int ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
virtual int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
|
||||
virtual u8 SPIWrite(u8 val, u32 pos, bool last) override;
|
||||
|
||||
|
@ -155,7 +157,7 @@ public:
|
|||
|
||||
void LoadSave(const u8* savedata, u32 savelen) override;
|
||||
|
||||
int ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
void ROMCommandFinish(u8* cmd, u8* data, u32 len) override;
|
||||
|
||||
u8 SPIWrite(u8 val, u32 pos, bool last) override;
|
||||
|
@ -216,11 +218,11 @@ public:
|
|||
virtual u32 Type() const override { return CartType::Homebrew; }
|
||||
|
||||
void Reset() override;
|
||||
void SetupDirectBoot(const std::string& romname) override;
|
||||
void SetupDirectBoot(const std::string& romname, NDS& nds) override;
|
||||
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
int ROMCommandStart(NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
int ROMCommandStart(NDS& nds, NDSCart::NDSCartSlot& cartslot, u8* cmd, u8* data, u32 len) override;
|
||||
void ROMCommandFinish(u8* cmd, u8* data, u32 len) override;
|
||||
|
||||
private:
|
||||
|
@ -235,7 +237,7 @@ private:
|
|||
class NDSCartSlot
|
||||
{
|
||||
public:
|
||||
NDSCartSlot() noexcept;
|
||||
NDSCartSlot(melonDS::NDS& nds) noexcept;
|
||||
~NDSCartSlot() noexcept;
|
||||
void Reset() noexcept;
|
||||
void ResetCart() noexcept;
|
||||
|
@ -303,6 +305,7 @@ public:
|
|||
void SetSPICnt(u16 val) noexcept { SPICnt = val; }
|
||||
private:
|
||||
friend class CartCommon;
|
||||
melonDS::NDS& NDS;
|
||||
u16 SPICnt {};
|
||||
u32 ROMCnt {};
|
||||
std::array<u8, 8> ROMCommand {};
|
||||
|
|
22
src/RTC.cpp
22
src/RTC.cpp
|
@ -32,9 +32,9 @@ using Platform::LogLevel;
|
|||
void WriteDateTime(int num, u8 val);
|
||||
|
||||
|
||||
RTC::RTC()
|
||||
RTC::RTC(melonDS::NDS& nds) : NDS(nds)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_RTC, 0, MemberEventFunc(RTC, ClockTimer));
|
||||
NDS.RegisterEventFunc(Event_RTC, 0, MemberEventFunc(RTC, ClockTimer));
|
||||
|
||||
ResetState();
|
||||
|
||||
|
@ -45,7 +45,7 @@ RTC::RTC()
|
|||
|
||||
RTC::~RTC()
|
||||
{
|
||||
NDS::UnregisterEventFunc(NDS::Event_RTC, 0);
|
||||
NDS.UnregisterEventFunc(Event_RTC, 0);
|
||||
}
|
||||
|
||||
void RTC::Reset()
|
||||
|
@ -221,10 +221,10 @@ void RTC::SetIRQ(u8 irq)
|
|||
|
||||
if ((!(oldstat & 0x30)) && (State.IRQFlag & 0x30))
|
||||
{
|
||||
if ((NDS::RCnt & 0xC100) == 0x8100)
|
||||
if ((NDS.RCnt & 0xC100) == 0x8100)
|
||||
{
|
||||
// CHECKME: is the IRQ status readable in RCNT?
|
||||
NDS::SetIRQ(1, NDS::IRQ_RTC);
|
||||
NDS.SetIRQ(1, IRQ_RTC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -306,7 +306,7 @@ void RTC::ProcessIRQ(int type) // 0=minute carry 1=periodic 2=status reg write
|
|||
if (State.Alarm1[2] & (1<<7))
|
||||
cond = cond && ((State.Alarm1[2] & 0x7F) == State.DateTime[5]);
|
||||
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (NDS.ConsoleType == 1)
|
||||
{
|
||||
if (State.AlarmDate1[1] & (1<<6))
|
||||
cond = cond && (State.AlarmDate1[0] == State.DateTime[0]);
|
||||
|
@ -348,7 +348,7 @@ void RTC::ProcessIRQ(int type) // 0=minute carry 1=periodic 2=status reg write
|
|||
if (State.Alarm2[2] & (1<<7))
|
||||
cond = cond && ((State.Alarm2[2] & 0x7F) == State.DateTime[5]);
|
||||
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (NDS.ConsoleType == 1)
|
||||
{
|
||||
if (State.AlarmDate2[1] & (1<<6))
|
||||
cond = cond && (State.AlarmDate2[0] == State.DateTime[0]);
|
||||
|
@ -520,7 +520,7 @@ void RTC::ScheduleTimer(bool first)
|
|||
s32 delay = sysclock >> 15;
|
||||
TimerError = sysclock & 0x7FFF;
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_RTC, !first, delay, 0, 0);
|
||||
NDS.ScheduleEvent(Event_RTC, !first, delay, 0, 0);
|
||||
}
|
||||
|
||||
void RTC::ClockTimer(u32 param)
|
||||
|
@ -647,7 +647,7 @@ void RTC::CmdRead()
|
|||
}
|
||||
else if ((CurCmd & 0x0F) == 0x0E)
|
||||
{
|
||||
if (NDS::ConsoleType != 1)
|
||||
if (NDS.ConsoleType != 1)
|
||||
{
|
||||
Log(LogLevel::Debug, "RTC: unknown read command %02X\n", CurCmd);
|
||||
return;
|
||||
|
@ -797,7 +797,7 @@ void RTC::CmdWrite(u8 val)
|
|||
}
|
||||
else if ((CurCmd & 0x0F) == 0x0E)
|
||||
{
|
||||
if (NDS::ConsoleType != 1)
|
||||
if (NDS.ConsoleType != 1)
|
||||
{
|
||||
Log(LogLevel::Debug, "RTC: unknown write command %02X\n", CurCmd);
|
||||
return;
|
||||
|
@ -852,7 +852,7 @@ void RTC::ByteIn(u8 val)
|
|||
else
|
||||
CurCmd = val;
|
||||
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (NDS.ConsoleType == 1)
|
||||
{
|
||||
// for DSi: handle extra commands
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public:
|
|||
u8 AlarmDate2[3];
|
||||
};
|
||||
|
||||
RTC();
|
||||
RTC(melonDS::NDS& nds);
|
||||
~RTC();
|
||||
|
||||
void Reset();
|
||||
|
@ -66,9 +66,7 @@ public:
|
|||
void Write(u16 val, bool byte);
|
||||
|
||||
private:
|
||||
/// This value represents the Nintendo DS IO register,
|
||||
/// \em not the value of the system's clock.
|
||||
/// The actual system time is taken directly from the host.
|
||||
melonDS::NDS& NDS;
|
||||
u16 IO;
|
||||
|
||||
u8 Input;
|
||||
|
|
57
src/SPI.cpp
57
src/SPI.cpp
|
@ -65,7 +65,7 @@ bool FirmwareMem::VerifyCRC16(u32 start, u32 offset, u32 len, u32 crcoffset)
|
|||
}
|
||||
|
||||
|
||||
FirmwareMem::FirmwareMem(SPIHost* host) : SPIDevice(host)
|
||||
FirmwareMem::FirmwareMem(melonDS::NDS& nds) : SPIDevice(nds)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ void FirmwareMem::Reset()
|
|||
if (!Firmware)
|
||||
{
|
||||
Log(LogLevel::Warn, "SPI firmware: no firmware loaded! Using default\n");
|
||||
Firmware = std::make_unique<class Firmware>(NDS::ConsoleType);
|
||||
Firmware = std::make_unique<class Firmware>(NDS.ConsoleType);
|
||||
}
|
||||
|
||||
// fix touchscreen coords
|
||||
|
@ -134,31 +134,32 @@ void FirmwareMem::DoSavestate(Savestate* file)
|
|||
file->Var32(&Addr);
|
||||
}
|
||||
|
||||
void FirmwareMem::SetupDirectBoot(bool dsi)
|
||||
void FirmwareMem::SetupDirectBoot()
|
||||
{
|
||||
const auto& header = Firmware->GetHeader();
|
||||
const auto& userdata = Firmware->GetEffectiveUserData();
|
||||
if (dsi)
|
||||
if (NDS.ConsoleType == 1)
|
||||
{
|
||||
// The ARMWrite methods are virtual, they'll delegate to DSi if necessary
|
||||
for (u32 i = 0; i < 6; i += 2)
|
||||
DSi::ARM9Write16(0x02FFFCF4, *(u16*)&header.MacAddr[i]); // MAC address
|
||||
NDS.ARM9Write16(0x02FFFCF4, *(u16*)&header.MacAddr[i]); // MAC address
|
||||
|
||||
// checkme
|
||||
DSi::ARM9Write16(0x02FFFCFA, header.EnabledChannels); // enabled channels
|
||||
NDS.ARM9Write16(0x02FFFCFA, header.EnabledChannels); // enabled channels
|
||||
|
||||
for (u32 i = 0; i < 0x70; i += 4)
|
||||
DSi::ARM9Write32(0x02FFFC80+i, *(u32*)&userdata.Bytes[i]);
|
||||
NDS.ARM9Write32(0x02FFFC80+i, *(u32*)&userdata.Bytes[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::ARM9Write32(0x027FF864, 0);
|
||||
NDS::ARM9Write32(0x027FF868, header.UserSettingsOffset << 3); // user settings offset
|
||||
NDS.ARM9Write32(0x027FF864, 0);
|
||||
NDS.ARM9Write32(0x027FF868, header.UserSettingsOffset << 3); // user settings offset
|
||||
|
||||
NDS::ARM9Write16(0x027FF874, header.DataGfxChecksum); // CRC16 for data/gfx
|
||||
NDS::ARM9Write16(0x027FF876, header.GUIWifiCodeChecksum); // CRC16 for GUI/wifi code
|
||||
NDS.ARM9Write16(0x027FF874, header.DataGfxChecksum); // CRC16 for data/gfx
|
||||
NDS.ARM9Write16(0x027FF876, header.GUIWifiCodeChecksum); // CRC16 for GUI/wifi code
|
||||
|
||||
for (u32 i = 0; i < 0x70; i += 4)
|
||||
NDS::ARM9Write32(0x027FFC80+i, *(u32*)&userdata.Bytes[i]);
|
||||
NDS.ARM9Write32(0x027FFC80+i, *(u32*)&userdata.Bytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,7 +327,7 @@ void FirmwareMem::Release()
|
|||
|
||||
|
||||
|
||||
PowerMan::PowerMan(SPIHost* host) : SPIDevice(host)
|
||||
PowerMan::PowerMan(melonDS::NDS& nds) : SPIDevice(nds)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -395,7 +396,7 @@ void PowerMan::Write(u8 val)
|
|||
switch (regid)
|
||||
{
|
||||
case 0:
|
||||
if (val & 0x40) NDS::Stop(StopReason::PowerOff); // shutdown
|
||||
if (val & 0x40) NDS.Stop(StopReason::PowerOff); // shutdown
|
||||
//printf("power %02X\n", val);
|
||||
break;
|
||||
case 4:
|
||||
|
@ -410,7 +411,7 @@ void PowerMan::Write(u8 val)
|
|||
|
||||
|
||||
|
||||
TSC::TSC(SPIHost* host) : SPIDevice(host)
|
||||
TSC::TSC(melonDS::NDS& nds) : SPIDevice(nds)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -452,13 +453,13 @@ void TSC::SetTouchCoords(u16 x, u16 y)
|
|||
if (y == 0xFFF)
|
||||
{
|
||||
// released
|
||||
NDS::KeyInput |= (1 << (16+6));
|
||||
NDS.KeyInput |= (1 << (16+6));
|
||||
return;
|
||||
}
|
||||
|
||||
TouchX <<= 4;
|
||||
TouchY <<= 4;
|
||||
NDS::KeyInput &= ~(1 << (16+6));
|
||||
NDS.KeyInput &= ~(1 << (16+6));
|
||||
}
|
||||
|
||||
void TSC::MicInputFrame(s16* data, int samples)
|
||||
|
@ -500,7 +501,7 @@ void TSC::Write(u8 val)
|
|||
else
|
||||
{
|
||||
// 560190 cycles per frame
|
||||
u32 cyclepos = (u32)NDS::GetSysClockCycles(2);
|
||||
u32 cyclepos = (u32)NDS.GetSysClockCycles(2);
|
||||
u32 samplepos = (cyclepos * MicBufferLen) / 560190;
|
||||
if (samplepos >= MicBufferLen) samplepos = MicBufferLen-1;
|
||||
s16 sample = MicBuffer[samplepos];
|
||||
|
@ -529,17 +530,17 @@ void TSC::Write(u8 val)
|
|||
|
||||
|
||||
|
||||
SPIHost::SPIHost()
|
||||
SPIHost::SPIHost(melonDS::NDS& nds) : NDS(nds)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_SPITransfer, 0, MemberEventFunc(SPIHost, TransferDone));
|
||||
NDS.RegisterEventFunc(Event_SPITransfer, 0, MemberEventFunc(SPIHost, TransferDone));
|
||||
|
||||
Devices[SPIDevice_FirmwareMem] = new FirmwareMem(this);
|
||||
Devices[SPIDevice_PowerMan] = new PowerMan(this);
|
||||
Devices[SPIDevice_FirmwareMem] = new FirmwareMem(NDS);
|
||||
Devices[SPIDevice_PowerMan] = new PowerMan(NDS);
|
||||
|
||||
if (NDS::ConsoleType == 1)
|
||||
Devices[SPIDevice_TSC] = new DSi_TSC(this);
|
||||
if (NDS.ConsoleType == 1)
|
||||
Devices[SPIDevice_TSC] = new DSi_TSC(static_cast<DSi&>(NDS));
|
||||
else
|
||||
Devices[SPIDevice_TSC] = new TSC(this);
|
||||
Devices[SPIDevice_TSC] = new TSC(NDS);
|
||||
}
|
||||
|
||||
SPIHost::~SPIHost()
|
||||
|
@ -552,7 +553,7 @@ SPIHost::~SPIHost()
|
|||
Devices[i] = nullptr;
|
||||
}
|
||||
|
||||
NDS::UnregisterEventFunc(NDS::Event_SPITransfer, 0);
|
||||
NDS.UnregisterEventFunc(Event_SPITransfer, 0);
|
||||
}
|
||||
|
||||
void SPIHost::Reset()
|
||||
|
@ -603,7 +604,7 @@ void SPIHost::TransferDone(u32 param)
|
|||
Cnt &= ~(1<<7);
|
||||
|
||||
if (Cnt & (1<<14))
|
||||
NDS::SetIRQ(1, NDS::IRQ_SPI);
|
||||
NDS.SetIRQ(1, IRQ_SPI);
|
||||
}
|
||||
|
||||
u8 SPIHost::ReadData()
|
||||
|
@ -641,7 +642,7 @@ void SPIHost::WriteData(u8 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);
|
||||
NDS.ScheduleEvent(Event_SPITransfer, false, delay, 0, 0);
|
||||
}
|
||||
|
||||
}
|
17
src/SPI.h
17
src/SPI.h
|
@ -42,11 +42,11 @@ enum
|
|||
u16 CRC16(const u8* data, u32 len, u32 start);
|
||||
|
||||
class SPIHost;
|
||||
|
||||
class NDS;
|
||||
class SPIDevice
|
||||
{
|
||||
public:
|
||||
SPIDevice(SPIHost* host) : Host(host), Hold(false), DataPos(0) {}
|
||||
SPIDevice(melonDS::NDS& nds) : NDS(nds), Hold(false), DataPos(0) {}
|
||||
virtual ~SPIDevice() {}
|
||||
virtual void Reset() = 0;
|
||||
virtual void DoSavestate(Savestate* file) = 0;
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
virtual void Release() { Hold = false; DataPos = 0; }
|
||||
|
||||
protected:
|
||||
SPIHost* Host;
|
||||
melonDS::NDS& NDS;
|
||||
|
||||
bool Hold;
|
||||
u32 DataPos;
|
||||
|
@ -66,12 +66,12 @@ protected:
|
|||
class FirmwareMem : public SPIDevice
|
||||
{
|
||||
public:
|
||||
FirmwareMem(SPIHost* host);
|
||||
FirmwareMem(melonDS::NDS& nds);
|
||||
~FirmwareMem() override;
|
||||
void Reset() override;
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
||||
void SetupDirectBoot(bool dsi);
|
||||
void SetupDirectBoot();
|
||||
|
||||
const class Firmware* GetFirmware();
|
||||
bool IsLoadedFirmwareBuiltIn();
|
||||
|
@ -96,7 +96,7 @@ private:
|
|||
class PowerMan : public SPIDevice
|
||||
{
|
||||
public:
|
||||
PowerMan(SPIHost* host);
|
||||
PowerMan(melonDS::NDS& nds);
|
||||
~PowerMan() override;
|
||||
void Reset() override;
|
||||
void DoSavestate(Savestate* file) override;
|
||||
|
@ -116,7 +116,7 @@ private:
|
|||
class TSC : public SPIDevice
|
||||
{
|
||||
public:
|
||||
TSC(SPIHost* host);
|
||||
TSC(melonDS::NDS& nds);
|
||||
virtual ~TSC() override;
|
||||
virtual void Reset() override;
|
||||
virtual void DoSavestate(Savestate* file) override;
|
||||
|
@ -141,7 +141,7 @@ protected:
|
|||
class SPIHost
|
||||
{
|
||||
public:
|
||||
SPIHost();
|
||||
SPIHost(melonDS::NDS& nds);
|
||||
~SPIHost();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
@ -161,6 +161,7 @@ public:
|
|||
void TransferDone(u32 param);
|
||||
|
||||
private:
|
||||
melonDS::NDS& NDS;
|
||||
u16 Cnt;
|
||||
|
||||
SPIDevice* Devices[3];
|
||||
|
|
35
src/SPU.cpp
35
src/SPU.cpp
|
@ -70,15 +70,15 @@ s16 SPUChannel::InterpCubic[0x100][4];
|
|||
bool SPUChannel::InterpInited = false;
|
||||
|
||||
|
||||
SPU::SPU()
|
||||
SPU::SPU(melonDS::NDS& nds) : NDS(nds)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_SPU, 0, MemberEventFunc(SPU, Mix));
|
||||
NDS.RegisterEventFunc(Event_SPU, 0, MemberEventFunc(SPU, Mix));
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
Channels[i] = new SPUChannel(i);
|
||||
Channels[i] = new SPUChannel(i, NDS);
|
||||
|
||||
Capture[0] = new SPUCaptureUnit(0);
|
||||
Capture[1] = new SPUCaptureUnit(1);
|
||||
Capture[0] = new SPUCaptureUnit(0, NDS);
|
||||
Capture[1] = new SPUCaptureUnit(1, NDS);
|
||||
|
||||
AudioLock = Platform::Mutex_Create();
|
||||
|
||||
|
@ -137,7 +137,7 @@ SPU::~SPU()
|
|||
Platform::Mutex_Free(AudioLock);
|
||||
AudioLock = nullptr;
|
||||
|
||||
NDS::UnregisterEventFunc(NDS::Event_SPU, 0);
|
||||
NDS.UnregisterEventFunc(Event_SPU, 0);
|
||||
}
|
||||
|
||||
void SPU::Reset()
|
||||
|
@ -154,7 +154,7 @@ void SPU::Reset()
|
|||
Capture[0]->Reset();
|
||||
Capture[1]->Reset();
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_SPU, false, 1024, 0, 0);
|
||||
NDS.ScheduleEvent(Event_SPU, false, 1024, 0, 0);
|
||||
}
|
||||
|
||||
void SPU::Stop()
|
||||
|
@ -212,7 +212,7 @@ void SPU::SetDegrade10Bit(bool enable)
|
|||
}
|
||||
|
||||
|
||||
SPUChannel::SPUChannel(u32 num)
|
||||
SPUChannel::SPUChannel(u32 num, melonDS::NDS& nds) : NDS(nds)
|
||||
{
|
||||
Num = num;
|
||||
|
||||
|
@ -225,11 +225,6 @@ SPUChannel::~SPUChannel()
|
|||
|
||||
void SPUChannel::Reset()
|
||||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
BusRead32 = DSi::ARM7Read32;
|
||||
else
|
||||
BusRead32 = NDS::ARM7Read32;
|
||||
|
||||
KeyOn = false;
|
||||
|
||||
SetCnt(0);
|
||||
|
@ -299,7 +294,7 @@ void SPUChannel::FIFO_BufferData()
|
|||
{
|
||||
for (u32 i = 0; i < burstlen; i += 4)
|
||||
{
|
||||
FIFO[FIFOWritePos] = BusRead32(SrcAddr + FIFOReadOffset);
|
||||
FIFO[FIFOWritePos] = NDS.ARM7Read32(SrcAddr + FIFOReadOffset);
|
||||
FIFOReadOffset += 4;
|
||||
FIFOWritePos++;
|
||||
FIFOWritePos &= 0x7;
|
||||
|
@ -583,7 +578,7 @@ void SPUChannel::PanOutput(s32 in, s32& left, s32& right)
|
|||
}
|
||||
|
||||
|
||||
SPUCaptureUnit::SPUCaptureUnit(u32 num)
|
||||
SPUCaptureUnit::SPUCaptureUnit(u32 num, melonDS::NDS& nds) : NDS(nds), Num(num)
|
||||
{
|
||||
Num = num;
|
||||
}
|
||||
|
@ -594,11 +589,6 @@ SPUCaptureUnit::~SPUCaptureUnit()
|
|||
|
||||
void SPUCaptureUnit::Reset()
|
||||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
BusWrite32 = DSi::ARM7Write32;
|
||||
else
|
||||
BusWrite32 = NDS::ARM7Write32;
|
||||
|
||||
SetCnt(0);
|
||||
DstAddr = 0;
|
||||
TimerReload = 0;
|
||||
|
@ -634,7 +624,8 @@ void SPUCaptureUnit::FIFO_FlushData()
|
|||
{
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
BusWrite32(DstAddr + FIFOWriteOffset, FIFO[FIFOReadPos]);
|
||||
NDS.ARM7Write32(DstAddr + FIFOWriteOffset, FIFO[FIFOReadPos]);
|
||||
// Calls the NDS or DSi version, depending on the class
|
||||
|
||||
FIFOReadPos++;
|
||||
FIFOReadPos &= 0x3;
|
||||
|
@ -858,7 +849,7 @@ void SPU::Mix(u32 dummy)
|
|||
OutputBackbufferWritePosition += 2;
|
||||
}
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_SPU, true, 1024, 0, 0);
|
||||
NDS.ScheduleEvent(Event_SPU, true, 1024, 0, 0);
|
||||
}
|
||||
|
||||
void SPU::TransferOutput()
|
||||
|
|
12
src/SPU.h
12
src/SPU.h
|
@ -24,12 +24,13 @@
|
|||
|
||||
namespace melonDS
|
||||
{
|
||||
class NDS;
|
||||
class SPU;
|
||||
|
||||
class SPUChannel
|
||||
{
|
||||
public:
|
||||
SPUChannel(u32 num);
|
||||
SPUChannel(u32 num, melonDS::NDS& nds);
|
||||
~SPUChannel();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
@ -142,13 +143,13 @@ public:
|
|||
void PanOutput(s32 in, s32& left, s32& right);
|
||||
|
||||
private:
|
||||
u32 (*BusRead32)(u32 addr);
|
||||
melonDS::NDS& NDS;
|
||||
};
|
||||
|
||||
class SPUCaptureUnit
|
||||
{
|
||||
public:
|
||||
SPUCaptureUnit(u32 num);
|
||||
SPUCaptureUnit(u32 num, melonDS::NDS&);
|
||||
~SPUCaptureUnit();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
@ -199,13 +200,13 @@ public:
|
|||
void Run(s32 sample);
|
||||
|
||||
private:
|
||||
void (*BusWrite32)(u32 addr, u32 val);
|
||||
melonDS::NDS& NDS;
|
||||
};
|
||||
|
||||
class SPU
|
||||
{
|
||||
public:
|
||||
SPU();
|
||||
SPU(melonDS::NDS& nds);
|
||||
~SPU();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
@ -240,6 +241,7 @@ public:
|
|||
|
||||
private:
|
||||
static const u32 OutputBufferSize = 2*2048;
|
||||
melonDS::NDS& NDS;
|
||||
s16 OutputBackbuffer[2 * OutputBufferSize];
|
||||
u32 OutputBackbufferWritePosition;
|
||||
|
||||
|
|
18
src/Wifi.cpp
18
src/Wifi.cpp
|
@ -89,9 +89,9 @@ bool MACIsBroadcast(u8* a)
|
|||
}
|
||||
|
||||
|
||||
Wifi::Wifi()
|
||||
Wifi::Wifi(melonDS::NDS& nds) : NDS(nds)
|
||||
{
|
||||
NDS::RegisterEventFunc(NDS::Event_Wifi, 0, MemberEventFunc(Wifi, USTimer));
|
||||
NDS.RegisterEventFunc(Event_Wifi, 0, MemberEventFunc(Wifi, USTimer));
|
||||
|
||||
//MPInited = false;
|
||||
//LANInited = false;
|
||||
|
@ -114,7 +114,7 @@ Wifi::~Wifi()
|
|||
|
||||
delete WifiAP; WifiAP = nullptr;
|
||||
|
||||
NDS::UnregisterEventFunc(NDS::Event_Wifi, 0);
|
||||
NDS.UnregisterEventFunc(Event_Wifi, 0);
|
||||
}
|
||||
|
||||
void Wifi::Reset()
|
||||
|
@ -158,7 +158,7 @@ void Wifi::Reset()
|
|||
}
|
||||
#undef BBREG_FIXED
|
||||
|
||||
const Firmware* fw = NDS::SPI->GetFirmware();
|
||||
const Firmware* fw = NDS.SPI.GetFirmware();
|
||||
|
||||
RFVersion = fw->GetHeader().RFChipType;
|
||||
memset(RFRegs, 0, 4*0x40);
|
||||
|
@ -168,7 +168,7 @@ void Wifi::Reset()
|
|||
IOPORT(0x000) = 0x1440;
|
||||
else if (console == Firmware::FirmwareConsoleType::DSLite)
|
||||
IOPORT(0x000) = 0xC340;
|
||||
else if (NDS::ConsoleType == 1 && console == Firmware::FirmwareConsoleType::DSi)
|
||||
else if (NDS.ConsoleType == 1 && console == Firmware::FirmwareConsoleType::DSi)
|
||||
IOPORT(0x000) = 0xC340; // DSi has the modern DS-wifi variant
|
||||
else
|
||||
{
|
||||
|
@ -303,14 +303,14 @@ void Wifi::ScheduleTimer(bool first)
|
|||
s32 delay = (cycles + 999999) / 1000000;
|
||||
TimerError = (delay * 1000000) - cycles;
|
||||
|
||||
NDS::ScheduleEvent(NDS::Event_Wifi, !first, delay, 0, 0);
|
||||
NDS.ScheduleEvent(Event_Wifi, !first, delay, 0, 0);
|
||||
}
|
||||
|
||||
void Wifi::UpdatePowerOn()
|
||||
{
|
||||
bool on = Enabled;
|
||||
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (NDS.ConsoleType == 1)
|
||||
{
|
||||
// TODO for DSi:
|
||||
// * W_POWER_US doesn't work (atleast on DWM-W024)
|
||||
|
@ -338,7 +338,7 @@ void Wifi::UpdatePowerOn()
|
|||
{
|
||||
Log(LogLevel::Debug, "WIFI: OFF\n");
|
||||
|
||||
NDS::CancelEvent(NDS::Event_Wifi);
|
||||
NDS.CancelEvent(Event_Wifi);
|
||||
|
||||
Platform::MP_End();
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ void Wifi::SetIRQ(u32 irq)
|
|||
u32 newflags = IOPORT(W_IF) & IOPORT(W_IE);
|
||||
|
||||
if ((oldflags == 0) && (newflags != 0))
|
||||
NDS::SetIRQ(1, NDS::IRQ_Wifi);
|
||||
NDS.SetIRQ(1, IRQ_Wifi);
|
||||
}
|
||||
|
||||
void Wifi::SetIRQ13()
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
namespace melonDS
|
||||
{
|
||||
class WifiAP;
|
||||
|
||||
class NDS;
|
||||
class Wifi
|
||||
{
|
||||
public:
|
||||
|
@ -157,7 +157,7 @@ public:
|
|||
W_RXTXAddr = 0x268,
|
||||
};
|
||||
|
||||
Wifi();
|
||||
Wifi(melonDS::NDS& nds);
|
||||
~Wifi();
|
||||
void Reset();
|
||||
void DoSavestate(Savestate* file);
|
||||
|
@ -173,6 +173,7 @@ public:
|
|||
u8* GetBSSID();
|
||||
|
||||
private:
|
||||
melonDS::NDS& NDS;
|
||||
u8 RAM[0x2000];
|
||||
u16 IO[0x1000>>1];
|
||||
|
||||
|
|
|
@ -24,6 +24,10 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
class NDS;
|
||||
}
|
||||
namespace Frontend
|
||||
{
|
||||
using namespace melonDS;
|
||||
|
@ -105,14 +109,14 @@ int AudioOut_GetNumSamples(int outlen);
|
|||
void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volume);
|
||||
|
||||
// feed silence to the microphone input
|
||||
void Mic_FeedSilence();
|
||||
void Mic_FeedSilence(NDS& nds);
|
||||
|
||||
// feed random noise to the microphone input
|
||||
void Mic_FeedNoise();
|
||||
void Mic_FeedNoise(NDS& nds);
|
||||
|
||||
// feed an external buffer to the microphone input
|
||||
// buffer should be mono
|
||||
void Mic_FeedExternalBuffer();
|
||||
void Mic_FeedExternalBuffer(NDS& nds);
|
||||
void Mic_SetExternalBuffer(s16* buffer, u32 len);
|
||||
|
||||
}
|
||||
|
|
|
@ -82,13 +82,13 @@ void AudioOut_Resample(s16* inbuf, int inlen, s16* outbuf, int outlen, int volum
|
|||
}
|
||||
|
||||
|
||||
void Mic_FeedSilence()
|
||||
void Mic_FeedSilence(NDS& nds)
|
||||
{
|
||||
MicBufferReadPos = 0;
|
||||
NDS::MicInputFrame(NULL, 0);
|
||||
nds.MicInputFrame(NULL, 0);
|
||||
}
|
||||
|
||||
void Mic_FeedNoise()
|
||||
void Mic_FeedNoise(NDS& nds)
|
||||
{
|
||||
int sample_len = sizeof(mic_blow) / sizeof(u16);
|
||||
static int sample_pos = 0;
|
||||
|
@ -102,12 +102,12 @@ void Mic_FeedNoise()
|
|||
if (sample_pos >= sample_len) sample_pos = 0;
|
||||
}
|
||||
|
||||
NDS::MicInputFrame(tmp, 735);
|
||||
nds.MicInputFrame(tmp, 735);
|
||||
}
|
||||
|
||||
void Mic_FeedExternalBuffer()
|
||||
void Mic_FeedExternalBuffer(NDS& nds)
|
||||
{
|
||||
if (!MicBuffer) return Mic_FeedSilence();
|
||||
if (!MicBuffer) return Mic_FeedSilence(nds);
|
||||
|
||||
if ((MicBufferReadPos + 735) > MicBufferLength)
|
||||
{
|
||||
|
@ -116,12 +116,12 @@ void Mic_FeedExternalBuffer()
|
|||
memcpy(&tmp[0], &MicBuffer[MicBufferReadPos], len1*sizeof(s16));
|
||||
memcpy(&tmp[len1], &MicBuffer[0], (735 - len1)*sizeof(s16));
|
||||
|
||||
NDS::MicInputFrame(tmp, 735);
|
||||
nds.MicInputFrame(tmp, 735);
|
||||
MicBufferReadPos = 735 - len1;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::MicInputFrame(&MicBuffer[MicBufferReadPos], 735);
|
||||
nds.MicInputFrame(&MicBuffer[MicBufferReadPos], 735);
|
||||
MicBufferReadPos += 735;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,8 +55,9 @@ void AudioCallback(void* data, Uint8* stream, int len)
|
|||
s16 buf_in[1024*2];
|
||||
int num_in;
|
||||
|
||||
EmuThread* emuThread = (EmuThread*)data;
|
||||
SDL_LockMutex(audioSyncLock);
|
||||
num_in = NDS::SPU->ReadOutput(buf_in, len_in);
|
||||
num_in = emuThread->NDS->SPU.ReadOutput(buf_in, len_in);
|
||||
SDL_CondSignal(audioSync);
|
||||
SDL_UnlockMutex(audioSyncLock);
|
||||
|
||||
|
@ -244,7 +245,7 @@ void MicLoadWav(const std::string& name)
|
|||
SDL_FreeWAV(buf);
|
||||
}
|
||||
|
||||
void MicProcess()
|
||||
void MicProcess(melonDS::NDS& nds)
|
||||
{
|
||||
int type = Config::MicInputType;
|
||||
bool cmd = Input::HotkeyDown(HK_Mic);
|
||||
|
@ -257,16 +258,16 @@ void MicProcess()
|
|||
switch (type)
|
||||
{
|
||||
case micInputType_Silence: // no mic
|
||||
Frontend::Mic_FeedSilence();
|
||||
Frontend::Mic_FeedSilence(nds);
|
||||
break;
|
||||
|
||||
case micInputType_External: // host mic
|
||||
case micInputType_Wav: // WAV
|
||||
Frontend::Mic_FeedExternalBuffer();
|
||||
Frontend::Mic_FeedExternalBuffer(nds);
|
||||
break;
|
||||
|
||||
case micInputType_Noise: // blowing noise
|
||||
Frontend::Mic_FeedNoise();
|
||||
Frontend::Mic_FeedNoise(nds);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -296,7 +297,7 @@ void SetupMicInputData()
|
|||
}
|
||||
}
|
||||
|
||||
void Init()
|
||||
void Init(EmuThread* thread)
|
||||
{
|
||||
audioMuted = false;
|
||||
audioSync = SDL_CreateCond();
|
||||
|
@ -310,6 +311,7 @@ void Init()
|
|||
whatIwant.channels = 2;
|
||||
whatIwant.samples = 1024;
|
||||
whatIwant.callback = AudioCallback;
|
||||
whatIwant.userdata = thread;
|
||||
audioDevice = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE);
|
||||
if (!audioDevice)
|
||||
{
|
||||
|
@ -349,12 +351,12 @@ void DeInit()
|
|||
micWavBuffer = nullptr;
|
||||
}
|
||||
|
||||
void AudioSync()
|
||||
void AudioSync(NDS& nds)
|
||||
{
|
||||
if (audioDevice)
|
||||
{
|
||||
SDL_LockMutex(audioSyncLock);
|
||||
while (NDS::SPU->GetOutputSize() > 1024)
|
||||
while (nds.SPU.GetOutputSize() > 1024)
|
||||
{
|
||||
int ret = SDL_CondWaitTimeout(audioSync, audioSyncLock, 500);
|
||||
if (ret == SDL_MUTEX_TIMEDOUT) break;
|
||||
|
@ -363,11 +365,11 @@ void AudioSync()
|
|||
}
|
||||
}
|
||||
|
||||
void UpdateSettings()
|
||||
void UpdateSettings(NDS& nds)
|
||||
{
|
||||
MicClose();
|
||||
|
||||
NDS::SPU->SetInterpolation(Config::AudioInterp);
|
||||
nds.SPU.SetInterpolation(Config::AudioInterp);
|
||||
SetupMicInputData();
|
||||
|
||||
MicOpen();
|
||||
|
|
|
@ -23,18 +23,23 @@
|
|||
|
||||
#include <QMainWindow>
|
||||
|
||||
class EmuThread;
|
||||
namespace melonDS
|
||||
{
|
||||
class NDS;
|
||||
}
|
||||
namespace AudioInOut
|
||||
{
|
||||
|
||||
void Init();
|
||||
void Init(EmuThread* thread);
|
||||
void DeInit();
|
||||
|
||||
void MicProcess();
|
||||
void MicProcess(melonDS::NDS& nds);
|
||||
void AudioMute(QMainWindow* mainWindow);
|
||||
|
||||
void AudioSync();
|
||||
void AudioSync(melonDS::NDS& nds);
|
||||
|
||||
void UpdateSettings();
|
||||
void UpdateSettings(melonDS::NDS& nds);
|
||||
|
||||
void Enable();
|
||||
void Disable();
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
|
||||
#include "AudioSettingsDialog.h"
|
||||
#include "ui_AudioSettingsDialog.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
using namespace melonDS;
|
||||
AudioSettingsDialog* AudioSettingsDialog::currentDlg = nullptr;
|
||||
|
@ -37,7 +37,7 @@ AudioSettingsDialog* AudioSettingsDialog::currentDlg = nullptr;
|
|||
extern std::string EmuDirectory;
|
||||
|
||||
|
||||
AudioSettingsDialog::AudioSettingsDialog(QWidget* parent, bool emuActive) : QDialog(parent), ui(new Ui::AudioSettingsDialog)
|
||||
AudioSettingsDialog::AudioSettingsDialog(QWidget* parent, bool emuActive, EmuThread* emuThread) : QDialog(parent), ui(new Ui::AudioSettingsDialog), emuThread(emuThread)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
@ -65,7 +65,7 @@ AudioSettingsDialog::AudioSettingsDialog(QWidget* parent, bool emuActive) : QDia
|
|||
ui->chkSyncDSiVolume->setChecked(Config::DSiVolumeSync);
|
||||
|
||||
// Setup volume slider accordingly
|
||||
if (emuActive && NDS::ConsoleType == 1)
|
||||
if (emuActive && emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
on_chkSyncDSiVolume_clicked(Config::DSiVolumeSync);
|
||||
}
|
||||
|
@ -125,10 +125,11 @@ AudioSettingsDialog::~AudioSettingsDialog()
|
|||
|
||||
void AudioSettingsDialog::onSyncVolumeLevel()
|
||||
{
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
if (Config::DSiVolumeSync && emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
bool state = ui->slVolume->blockSignals(true);
|
||||
ui->slVolume->setValue(DSi::I2C->GetBPTWL()->GetVolumeLevel());
|
||||
ui->slVolume->setValue(dsi.I2C.GetBPTWL()->GetVolumeLevel());
|
||||
ui->slVolume->blockSignals(state);
|
||||
}
|
||||
}
|
||||
|
@ -136,7 +137,7 @@ void AudioSettingsDialog::onSyncVolumeLevel()
|
|||
void AudioSettingsDialog::onConsoleReset()
|
||||
{
|
||||
on_chkSyncDSiVolume_clicked(Config::DSiVolumeSync);
|
||||
ui->chkSyncDSiVolume->setEnabled(NDS::ConsoleType == 1);
|
||||
ui->chkSyncDSiVolume->setEnabled(emuThread->NDS->ConsoleType == 1);
|
||||
}
|
||||
|
||||
void AudioSettingsDialog::on_AudioSettingsDialog_accepted()
|
||||
|
@ -181,9 +182,10 @@ void AudioSettingsDialog::on_cbInterpolation_currentIndexChanged(int idx)
|
|||
|
||||
void AudioSettingsDialog::on_slVolume_valueChanged(int val)
|
||||
{
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
if (Config::DSiVolumeSync && emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetVolumeLevel(val);
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
dsi.I2C.GetBPTWL()->SetVolumeLevel(val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -195,10 +197,11 @@ void AudioSettingsDialog::on_chkSyncDSiVolume_clicked(bool checked)
|
|||
Config::DSiVolumeSync = checked;
|
||||
|
||||
bool state = ui->slVolume->blockSignals(true);
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
if (Config::DSiVolumeSync && emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
ui->slVolume->setMaximum(31);
|
||||
ui->slVolume->setValue(DSi::I2C->GetBPTWL()->GetVolumeLevel());
|
||||
ui->slVolume->setValue(dsi.I2C.GetBPTWL()->GetVolumeLevel());
|
||||
ui->slVolume->setPageStep(4);
|
||||
ui->slVolume->setTickPosition(QSlider::TicksBelow);
|
||||
}
|
||||
|
|
|
@ -24,17 +24,18 @@
|
|||
|
||||
namespace Ui { class AudioSettingsDialog; }
|
||||
class AudioSettingsDialog;
|
||||
class EmuThread;
|
||||
|
||||
class AudioSettingsDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AudioSettingsDialog(QWidget* parent, bool emuActive);
|
||||
explicit AudioSettingsDialog(QWidget* parent, bool emuActive, EmuThread* emuThread);
|
||||
~AudioSettingsDialog();
|
||||
|
||||
static AudioSettingsDialog* currentDlg;
|
||||
static AudioSettingsDialog* openDlg(QWidget* parent, bool emuActive)
|
||||
static AudioSettingsDialog* openDlg(QWidget* parent, bool emuActive, EmuThread* emuThread)
|
||||
{
|
||||
if (currentDlg)
|
||||
{
|
||||
|
@ -42,7 +43,7 @@ public:
|
|||
return currentDlg;
|
||||
}
|
||||
|
||||
currentDlg = new AudioSettingsDialog(parent, emuActive);
|
||||
currentDlg = new AudioSettingsDialog(parent, emuActive, emuThread);
|
||||
currentDlg->show();
|
||||
return currentDlg;
|
||||
}
|
||||
|
@ -69,6 +70,7 @@ private slots:
|
|||
void on_btnMicWavBrowse_clicked();
|
||||
|
||||
private:
|
||||
EmuThread* emuThread;
|
||||
Ui::AudioSettingsDialog* ui;
|
||||
|
||||
int oldInterp;
|
||||
|
|
|
@ -29,45 +29,59 @@
|
|||
#include "types.h"
|
||||
|
||||
#include <QtDebug>
|
||||
#include "main.h"
|
||||
|
||||
using namespace melonDS;
|
||||
|
||||
PowerManagementDialog* PowerManagementDialog::currentDlg = nullptr;
|
||||
|
||||
PowerManagementDialog::PowerManagementDialog(QWidget* parent) : QDialog(parent), ui(new Ui::PowerManagementDialog)
|
||||
PowerManagementDialog::PowerManagementDialog(QWidget* parent, EmuThread* emuThread) : QDialog(parent), emuThread(emuThread), ui(new Ui::PowerManagementDialog)
|
||||
{
|
||||
inited = false;
|
||||
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
ui->grpDSBattery->setEnabled(false);
|
||||
|
||||
oldDSiBatteryLevel = DSi::I2C->GetBPTWL()->GetBatteryLevel();
|
||||
oldDSiBatteryCharging = DSi::I2C->GetBPTWL()->GetBatteryCharging();
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
oldDSiBatteryLevel = dsi.I2C.GetBPTWL()->GetBatteryLevel();
|
||||
oldDSiBatteryCharging = dsi.I2C.GetBPTWL()->GetBatteryCharging();
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->grpDSiBattery->setEnabled(false);
|
||||
|
||||
oldDSBatteryLevel = NDS::SPI->GetPowerMan()->GetBatteryLevelOkay();
|
||||
oldDSBatteryLevel = emuThread->NDS->SPI.GetPowerMan()->GetBatteryLevelOkay();
|
||||
}
|
||||
|
||||
updateDSBatteryLevelControls();
|
||||
|
||||
ui->cbDSiBatteryCharging->setChecked(DSi::I2C->GetBPTWL()->GetBatteryCharging());
|
||||
int dsiBatterySliderPos;
|
||||
switch (DSi::I2C->GetBPTWL()->GetBatteryLevel())
|
||||
bool defaultDSiBatteryCharging = (emuThread->NDS->ConsoleType == 1) ? Config::DSiBatteryCharging : false;
|
||||
|
||||
if (emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
ui->cbDSiBatteryCharging->setChecked(dsi.I2C.GetBPTWL()->GetBatteryCharging());
|
||||
int dsiBatterySliderPos = 4;
|
||||
switch (dsi.I2C.GetBPTWL()->GetBatteryLevel())
|
||||
{
|
||||
case DSi_BPTWL::batteryLevel_AlmostEmpty: dsiBatterySliderPos = 0; break;
|
||||
case DSi_BPTWL::batteryLevel_Low: dsiBatterySliderPos = 1; break;
|
||||
case DSi_BPTWL::batteryLevel_Half: dsiBatterySliderPos = 2; break;
|
||||
case DSi_BPTWL::batteryLevel_ThreeQuarters: dsiBatterySliderPos = 3; break;
|
||||
case DSi_BPTWL::batteryLevel_Full: dsiBatterySliderPos = 4; break;
|
||||
}
|
||||
ui->sliderDSiBatteryLevel->setValue(dsiBatterySliderPos);
|
||||
}
|
||||
ui->sliderDSiBatteryLevel->setValue(dsiBatterySliderPos);
|
||||
else
|
||||
{
|
||||
ui->cbDSiBatteryCharging->setChecked(Config::DSiBatteryCharging);
|
||||
ui->sliderDSiBatteryLevel->setValue(Config::DSiBatteryLevel);
|
||||
}
|
||||
|
||||
|
||||
int inst = Platform::InstanceID();
|
||||
if (inst > 0)
|
||||
|
@ -87,26 +101,28 @@ void PowerManagementDialog::done(int r)
|
|||
{
|
||||
if (r == QDialog::Accepted)
|
||||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
Config::DSiBatteryLevel = DSi::I2C->GetBPTWL()->GetBatteryLevel();
|
||||
Config::DSiBatteryCharging = DSi::I2C->GetBPTWL()->GetBatteryCharging();
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
Config::DSiBatteryLevel = dsi.I2C.GetBPTWL()->GetBatteryLevel();
|
||||
Config::DSiBatteryCharging = dsi.I2C.GetBPTWL()->GetBatteryCharging();
|
||||
}
|
||||
else
|
||||
{
|
||||
Config::DSBatteryLevelOkay = NDS::SPI->GetPowerMan()->GetBatteryLevelOkay();
|
||||
Config::DSBatteryLevelOkay = emuThread->NDS->SPI.GetPowerMan()->GetBatteryLevelOkay();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetBatteryLevel(oldDSiBatteryLevel);
|
||||
DSi::I2C->GetBPTWL()->SetBatteryCharging(oldDSiBatteryCharging);
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
dsi.I2C.GetBPTWL()->SetBatteryLevel(oldDSiBatteryLevel);
|
||||
dsi.I2C.GetBPTWL()->SetBatteryCharging(oldDSiBatteryCharging);
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::SPI->GetPowerMan()->SetBatteryLevelOkay(oldDSBatteryLevel);
|
||||
emuThread->NDS->SPI.GetPowerMan()->SetBatteryLevelOkay(oldDSBatteryLevel);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,17 +133,17 @@ void PowerManagementDialog::done(int r)
|
|||
|
||||
void PowerManagementDialog::on_rbDSBatteryLow_clicked()
|
||||
{
|
||||
NDS::SPI->GetPowerMan()->SetBatteryLevelOkay(false);
|
||||
emuThread->NDS->SPI.GetPowerMan()->SetBatteryLevelOkay(false);
|
||||
}
|
||||
|
||||
void PowerManagementDialog::on_rbDSBatteryOkay_clicked()
|
||||
{
|
||||
NDS::SPI->GetPowerMan()->SetBatteryLevelOkay(true);
|
||||
emuThread->NDS->SPI.GetPowerMan()->SetBatteryLevelOkay(true);
|
||||
}
|
||||
|
||||
void PowerManagementDialog::updateDSBatteryLevelControls()
|
||||
{
|
||||
if (NDS::SPI->GetPowerMan()->GetBatteryLevelOkay())
|
||||
if (emuThread->NDS->SPI.GetPowerMan()->GetBatteryLevelOkay())
|
||||
ui->rbDSBatteryOkay->setChecked(true);
|
||||
else
|
||||
ui->rbDSBatteryLow->setChecked(true);
|
||||
|
@ -135,23 +151,32 @@ void PowerManagementDialog::updateDSBatteryLevelControls()
|
|||
|
||||
void PowerManagementDialog::on_cbDSiBatteryCharging_toggled()
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetBatteryCharging(ui->cbDSiBatteryCharging->isChecked());
|
||||
if (emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
dsi.I2C.GetBPTWL()->SetBatteryCharging(ui->cbDSiBatteryCharging->isChecked());
|
||||
}
|
||||
}
|
||||
|
||||
void PowerManagementDialog::on_sliderDSiBatteryLevel_valueChanged(int value)
|
||||
{
|
||||
if (!inited) return;
|
||||
|
||||
u8 newBatteryLevel;
|
||||
switch (value)
|
||||
if (emuThread->NDS->ConsoleType == 1)
|
||||
{
|
||||
case 0: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_AlmostEmpty; break;
|
||||
case 1: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Low; break;
|
||||
case 2: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Half; break;
|
||||
case 3: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_ThreeQuarters; break;
|
||||
case 4: newBatteryLevel = DSi::I2C->GetBPTWL()->batteryLevel_Full; break;
|
||||
auto& dsi = static_cast<DSi&>(*emuThread->NDS);
|
||||
u8 newBatteryLevel = DSi_BPTWL::batteryLevel_Full;
|
||||
switch (value)
|
||||
{
|
||||
case 0: newBatteryLevel = DSi_BPTWL::batteryLevel_AlmostEmpty; break;
|
||||
case 1: newBatteryLevel = DSi_BPTWL::batteryLevel_Low; break;
|
||||
case 2: newBatteryLevel = DSi_BPTWL::batteryLevel_Half; break;
|
||||
case 3: newBatteryLevel = DSi_BPTWL::batteryLevel_ThreeQuarters; break;
|
||||
case 4: newBatteryLevel = DSi_BPTWL::batteryLevel_Full; break;
|
||||
}
|
||||
dsi.I2C.GetBPTWL()->SetBatteryLevel(newBatteryLevel);
|
||||
}
|
||||
DSi::I2C->GetBPTWL()->SetBatteryLevel(newBatteryLevel);
|
||||
|
||||
updateDSBatteryLevelControls();
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "types.h"
|
||||
|
||||
namespace Ui { class PowerManagementDialog; }
|
||||
class EmuThread;
|
||||
class PowerManagementDialog;
|
||||
|
||||
class PowerManagementDialog : public QDialog
|
||||
|
@ -32,11 +33,11 @@ class PowerManagementDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit PowerManagementDialog(QWidget* parent);
|
||||
explicit PowerManagementDialog(QWidget* parent, EmuThread* emu_thread);
|
||||
~PowerManagementDialog();
|
||||
|
||||
static PowerManagementDialog* currentDlg;
|
||||
static PowerManagementDialog* openDlg(QWidget* parent)
|
||||
static PowerManagementDialog* openDlg(QWidget* parent, EmuThread* emu_thread)
|
||||
{
|
||||
if (currentDlg)
|
||||
{
|
||||
|
@ -44,7 +45,7 @@ public:
|
|||
return currentDlg;
|
||||
}
|
||||
|
||||
currentDlg = new PowerManagementDialog(parent);
|
||||
currentDlg = new PowerManagementDialog(parent, emu_thread);
|
||||
currentDlg->open();
|
||||
return currentDlg;
|
||||
}
|
||||
|
@ -64,6 +65,7 @@ private slots:
|
|||
|
||||
private:
|
||||
Ui::PowerManagementDialog* ui;
|
||||
EmuThread* emuThread;
|
||||
|
||||
bool inited;
|
||||
bool oldDSBatteryLevel;
|
||||
|
|
|
@ -24,16 +24,16 @@
|
|||
using namespace melonDS;
|
||||
extern EmuThread* emuThread;
|
||||
|
||||
s32 GetMainRAMValue(const u32& addr, const ramInfo_ByteType& byteType)
|
||||
s32 GetMainRAMValue(NDS& nds, const u32& addr, const ramInfo_ByteType& byteType)
|
||||
{
|
||||
switch (byteType)
|
||||
{
|
||||
case ramInfo_OneByte:
|
||||
return *(s8*)(NDS::MainRAM + (addr&NDS::MainRAMMask));
|
||||
return *(s8*)(nds.MainRAM + (addr&nds.MainRAMMask));
|
||||
case ramInfo_TwoBytes:
|
||||
return *(s16*)(NDS::MainRAM + (addr&NDS::MainRAMMask));
|
||||
return *(s16*)(nds.MainRAM + (addr&nds.MainRAMMask));
|
||||
case ramInfo_FourBytes:
|
||||
return *(s32*)(NDS::MainRAM + (addr&NDS::MainRAMMask));
|
||||
return *(s32*)(nds.MainRAM + (addr&nds.MainRAMMask));
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ s32 GetMainRAMValue(const u32& addr, const ramInfo_ByteType& byteType)
|
|||
|
||||
RAMInfoDialog* RAMInfoDialog::currentDlg = nullptr;
|
||||
|
||||
RAMInfoDialog::RAMInfoDialog(QWidget* parent) : QDialog(parent), ui(new Ui::RAMInfoDialog)
|
||||
RAMInfoDialog::RAMInfoDialog(QWidget* parent, EmuThread* emuThread) : QDialog(parent), emuThread(emuThread), ui(new Ui::RAMInfoDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
@ -91,7 +91,7 @@ void RAMInfoDialog::ShowRowsInTable()
|
|||
for (u32 row = scrollValue; row < std::min<u32>(scrollValue+25, RowDataVector->size()); row++)
|
||||
{
|
||||
ramInfo_RowData& rowData = RowDataVector->at(row);
|
||||
rowData.Update(SearchThread->GetSearchByteType());
|
||||
rowData.Update(*emuThread->NDS, SearchThread->GetSearchByteType());
|
||||
|
||||
if (ui->ramTable->item(row, ramInfo_Address) == nullptr)
|
||||
{
|
||||
|
@ -186,7 +186,7 @@ void RAMInfoDialog::on_ramTable_itemChanged(QTableWidgetItem *item)
|
|||
s32 itemValue = item->text().toInt();
|
||||
|
||||
if (rowData.Value != itemValue)
|
||||
rowData.SetValue(itemValue);
|
||||
rowData.SetValue(*emuThread->NDS, itemValue);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,14 +241,14 @@ void RAMSearchThread::run()
|
|||
if (SearchMode == ramInfoSTh_SearchAll || RowDataVector->size() == 0)
|
||||
{
|
||||
// First search mode
|
||||
for (u32 addr = 0x02000000; SearchRunning && addr < 0x02000000+NDS::MainRAMMaxSize; addr += SearchByteType)
|
||||
for (u32 addr = 0x02000000; SearchRunning && addr < 0x02000000+MainRAMMaxSize; addr += SearchByteType)
|
||||
{
|
||||
const s32& value = GetMainRAMValue(addr, SearchByteType);
|
||||
const s32& value = GetMainRAMValue(*emuThread->NDS, addr, SearchByteType);
|
||||
|
||||
RowDataVector->push_back({ addr, value, value });
|
||||
|
||||
// A solution to prevent to call too many slot.
|
||||
u32 newProgress = (int)((addr-0x02000000) / (NDS::MainRAMMaxSize-1.0f) * 100);
|
||||
u32 newProgress = (int)((addr-0x02000000) / (MainRAMMaxSize-1.0f) * 100);
|
||||
if (progress < newProgress)
|
||||
{
|
||||
progress = newProgress;
|
||||
|
@ -264,7 +264,7 @@ void RAMSearchThread::run()
|
|||
for (u32 row = 0; SearchRunning && row < RowDataVector->size(); row++)
|
||||
{
|
||||
const u32& addr = RowDataVector->at(row).Address;
|
||||
const s32& value = GetMainRAMValue(addr, SearchByteType);
|
||||
const s32& value = GetMainRAMValue(*emuThread->NDS, addr, SearchByteType);
|
||||
|
||||
if (SearchValue == value)
|
||||
newRowDataVector->push_back({ addr, value, value });
|
||||
|
|
|
@ -32,6 +32,7 @@ namespace Ui { class RAMInfoDialog; }
|
|||
class RAMInfoDialog;
|
||||
class RAMSearchThread;
|
||||
class RAMUpdateThread;
|
||||
class EmuThread;
|
||||
|
||||
enum ramInfo_ByteType
|
||||
{
|
||||
|
@ -53,7 +54,7 @@ enum
|
|||
ramInfo_Previous
|
||||
};
|
||||
|
||||
melonDS::s32 GetMainRAMValue(const melonDS::u32& addr, const ramInfo_ByteType& byteType);
|
||||
melonDS::s32 GetMainRAMValue(melonDS::NDS& nds, const melonDS::u32& addr, const ramInfo_ByteType& byteType);
|
||||
|
||||
struct ramInfo_RowData
|
||||
{
|
||||
|
@ -61,14 +62,14 @@ struct ramInfo_RowData
|
|||
melonDS::s32 Value;
|
||||
melonDS::s32 Previous;
|
||||
|
||||
void Update(const ramInfo_ByteType& byteType)
|
||||
void Update(melonDS::NDS& nds, const ramInfo_ByteType& byteType)
|
||||
{
|
||||
Value = GetMainRAMValue(Address, byteType);
|
||||
Value = GetMainRAMValue(nds, Address, byteType);
|
||||
}
|
||||
|
||||
void SetValue(const melonDS::s32& value)
|
||||
void SetValue(melonDS::NDS& nds, const melonDS::s32& value)
|
||||
{
|
||||
melonDS::NDS::MainRAM[Address&melonDS::NDS::MainRAMMask] = (melonDS::u32)value;
|
||||
nds.MainRAM[Address&nds.MainRAMMask] = (melonDS::u32)value;
|
||||
Value = value;
|
||||
}
|
||||
};
|
||||
|
@ -78,11 +79,11 @@ class RAMInfoDialog : public QDialog
|
|||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RAMInfoDialog(QWidget* parent);
|
||||
explicit RAMInfoDialog(QWidget* parent, EmuThread* emuThread);
|
||||
~RAMInfoDialog();
|
||||
|
||||
static RAMInfoDialog* currentDlg;
|
||||
static RAMInfoDialog* openDlg(QWidget* parent)
|
||||
static RAMInfoDialog* openDlg(QWidget* parent, EmuThread* emuThread)
|
||||
{
|
||||
if (currentDlg)
|
||||
{
|
||||
|
@ -90,7 +91,7 @@ public:
|
|||
return currentDlg;
|
||||
}
|
||||
|
||||
currentDlg = new RAMInfoDialog(parent);
|
||||
currentDlg = new RAMInfoDialog(parent, emuThread);
|
||||
currentDlg->show();
|
||||
return currentDlg;
|
||||
}
|
||||
|
@ -118,6 +119,7 @@ private slots:
|
|||
void SetProgressbarValue(const melonDS::u32& value);
|
||||
|
||||
private:
|
||||
EmuThread* emuThread;
|
||||
Ui::RAMInfoDialog* ui;
|
||||
|
||||
RAMSearchThread* SearchThread;
|
||||
|
|
|
@ -42,14 +42,13 @@ QString QStringBytes(u64 num)
|
|||
|
||||
ROMInfoDialog* ROMInfoDialog::currentDlg = nullptr;
|
||||
|
||||
ROMInfoDialog::ROMInfoDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ROMInfoDialog)
|
||||
ROMInfoDialog::ROMInfoDialog(QWidget* parent, const melonDS::NDSCart::CartCommon& rom) : QDialog(parent), ui(new Ui::ROMInfoDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
const NDSBanner* banner = NDS::NDSCartSlot->GetCart()->Banner();
|
||||
const NDSHeader& header = NDS::NDSCartSlot->GetCart()->GetHeader();
|
||||
|
||||
const NDSBanner* banner = rom.Banner();
|
||||
const NDSHeader& header = rom.GetHeader();
|
||||
u32 iconData[32 * 32];
|
||||
ROMManager::ROMIcon(banner->Icon, banner->Palette, iconData);
|
||||
iconImage = QImage(reinterpret_cast<u8*>(iconData), 32, 32, QImage::Format_RGBA8888).copy();
|
||||
|
|
|
@ -29,17 +29,17 @@
|
|||
|
||||
namespace Ui { class ROMInfoDialog; }
|
||||
class ROMInfoDialog;
|
||||
|
||||
namespace melonDS::NDSCart { class CartCommon; }
|
||||
class ROMInfoDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ROMInfoDialog(QWidget* parent);
|
||||
explicit ROMInfoDialog(QWidget* parent, const melonDS::NDSCart::CartCommon& rom);
|
||||
~ROMInfoDialog();
|
||||
|
||||
static ROMInfoDialog* currentDlg;
|
||||
static ROMInfoDialog* openDlg(QWidget* parent)
|
||||
static ROMInfoDialog* openDlg(QWidget* parent, const melonDS::NDSCart::CartCommon& rom)
|
||||
{
|
||||
if (currentDlg)
|
||||
{
|
||||
|
@ -47,7 +47,7 @@ public:
|
|||
return currentDlg;
|
||||
}
|
||||
|
||||
currentDlg = new ROMInfoDialog(parent);
|
||||
currentDlg = new ROMInfoDialog(parent, rom);
|
||||
currentDlg->open();
|
||||
return currentDlg;
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include "RTC.h"
|
||||
#include "DSi_I2C.h"
|
||||
#include "FreeBIOS.h"
|
||||
#include "main.h"
|
||||
|
||||
using std::make_unique;
|
||||
using std::pair;
|
||||
|
@ -316,7 +317,7 @@ bool SavestateExists(int slot)
|
|||
return Platform::FileExists(ssfile);
|
||||
}
|
||||
|
||||
bool LoadState(const std::string& filename)
|
||||
bool LoadState(NDS& nds, const std::string& filename)
|
||||
{
|
||||
FILE* file = fopen(filename.c_str(), "rb");
|
||||
if (file == nullptr)
|
||||
|
@ -333,7 +334,7 @@ bool LoadState(const std::string& filename)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!NDS::DoSavestate(backup.get()) || backup->Error)
|
||||
if (!nds.DoSavestate(backup.get()) || backup->Error)
|
||||
{ // Back up the emulator's state. If that failed...
|
||||
Platform::Log(Platform::LogLevel::Error, "Failed to back up state, aborting load (from \"%s\")\n", filename.c_str());
|
||||
fclose(file);
|
||||
|
@ -365,7 +366,7 @@ bool LoadState(const std::string& filename)
|
|||
// Get ready to load the state from the buffer into the emulator
|
||||
std::unique_ptr<Savestate> state = std::make_unique<Savestate>(buffer.data(), size, false);
|
||||
|
||||
if (!NDS::DoSavestate(state.get()) || state->Error)
|
||||
if (!nds.DoSavestate(state.get()) || state->Error)
|
||||
{ // If we couldn't load the savestate from the buffer...
|
||||
Platform::Log(Platform::LogLevel::Error, "Failed to load state file \"%s\" into emulator\n", filename.c_str());
|
||||
return false;
|
||||
|
@ -390,7 +391,7 @@ bool LoadState(const std::string& filename)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool SaveState(const std::string& filename)
|
||||
bool SaveState(NDS& nds, const std::string& filename)
|
||||
{
|
||||
FILE* file = fopen(filename.c_str(), "wb");
|
||||
|
||||
|
@ -407,7 +408,7 @@ bool SaveState(const std::string& filename)
|
|||
}
|
||||
|
||||
// Write the savestate to the in-memory buffer
|
||||
NDS::DoSavestate(&state);
|
||||
nds.DoSavestate(&state);
|
||||
|
||||
if (state.Error)
|
||||
{
|
||||
|
@ -439,7 +440,7 @@ bool SaveState(const std::string& filename)
|
|||
return true;
|
||||
}
|
||||
|
||||
void UndoStateLoad()
|
||||
void UndoStateLoad(NDS& nds)
|
||||
{
|
||||
if (!SavestateLoaded || !BackupState) return;
|
||||
|
||||
|
@ -448,7 +449,7 @@ void UndoStateLoad()
|
|||
// pray that this works
|
||||
// what do we do if it doesn't???
|
||||
// but it should work.
|
||||
NDS::DoSavestate(BackupState.get());
|
||||
nds.DoSavestate(BackupState.get());
|
||||
|
||||
if (NDSSave && (!PreviousSaveFile.empty()))
|
||||
{
|
||||
|
@ -457,36 +458,264 @@ void UndoStateLoad()
|
|||
}
|
||||
|
||||
|
||||
void UnloadCheats()
|
||||
void UnloadCheats(NDS& nds)
|
||||
{
|
||||
if (CheatFile)
|
||||
{
|
||||
delete CheatFile;
|
||||
CheatFile = nullptr;
|
||||
NDS::AREngine->SetCodeFile(nullptr);
|
||||
nds.AREngine.SetCodeFile(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadCheats()
|
||||
void LoadCheats(NDS& nds)
|
||||
{
|
||||
UnloadCheats();
|
||||
UnloadCheats(nds);
|
||||
|
||||
std::string filename = GetAssetPath(false, Config::CheatFilePath, ".mch");
|
||||
|
||||
// TODO: check for error (malformed cheat file, ...)
|
||||
CheatFile = new ARCodeFile(filename);
|
||||
|
||||
NDS::AREngine->SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
||||
nds.AREngine.SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
||||
}
|
||||
|
||||
void LoadBIOSFiles()
|
||||
std::optional<std::array<u8, ARM9BIOSSize>> LoadARM9BIOS() noexcept
|
||||
{
|
||||
if (FileHandle* f = OpenLocalFile(Config::BIOS9Path, Read))
|
||||
{
|
||||
std::array<u8, ARM9BIOSSize> bios {};
|
||||
FileRewind(f);
|
||||
FileRead(bios.data(), sizeof(bios), 1, f);
|
||||
CloseFile(f);
|
||||
Log(Info, "ARM9 BIOS loaded from %s\n", Config::BIOS9Path.c_str());
|
||||
return bios;
|
||||
}
|
||||
|
||||
Log(Warn, "ARM9 BIOS not found\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::array<u8, ARM7BIOSSize>> LoadARM7BIOS() noexcept
|
||||
{
|
||||
if (FileHandle* f = OpenLocalFile(Config::BIOS7Path, Read))
|
||||
{
|
||||
std::array<u8, ARM7BIOSSize> bios {};
|
||||
FileRead(bios.data(), sizeof(bios), 1, f);
|
||||
CloseFile(f);
|
||||
Log(Info, "ARM7 BIOS loaded from %s\n", Config::BIOS7Path.c_str());
|
||||
return bios;
|
||||
}
|
||||
|
||||
Log(Warn, "ARM7 BIOS not found\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM9BIOS() noexcept
|
||||
{
|
||||
if (FileHandle* f = OpenLocalFile(Config::DSiBIOS9Path, Read))
|
||||
{
|
||||
std::array<u8, DSiBIOSSize> bios {};
|
||||
FileRead(bios.data(), sizeof(bios), 1, f);
|
||||
CloseFile(f);
|
||||
Log(Info, "ARM9i BIOS loaded from %s\n", Config::DSiBIOS9Path.c_str());
|
||||
return bios;
|
||||
}
|
||||
|
||||
Log(Warn, "ARM9i BIOS not found\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM7BIOS() noexcept
|
||||
{
|
||||
if (FileHandle* f = OpenLocalFile(Config::DSiBIOS7Path, Read))
|
||||
{
|
||||
std::array<u8, DSiBIOSSize> bios {};
|
||||
FileRead(bios.data(), sizeof(bios), 1, f);
|
||||
CloseFile(f);
|
||||
Log(Info, "ARM7i BIOS loaded from %s\n", Config::DSiBIOS7Path.c_str());
|
||||
return bios;
|
||||
}
|
||||
|
||||
Log(Warn, "ARM7i BIOS not found\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
Firmware GenerateFirmware(int type) noexcept
|
||||
{
|
||||
// Construct the default firmware...
|
||||
string settingspath;
|
||||
Firmware firmware = Firmware(type);
|
||||
assert(firmware.Buffer() != nullptr);
|
||||
|
||||
// If using generated firmware, we keep the wi-fi settings on the host disk separately.
|
||||
// Wi-fi access point data includes Nintendo WFC settings,
|
||||
// and if we didn't keep them then the player would have to reset them in each session.
|
||||
// We don't need to save the whole firmware, just the part that may actually change.
|
||||
if (FileHandle* f = OpenLocalFile(Config::WifiSettingsPath, Read))
|
||||
{// If we have Wi-fi settings to load...
|
||||
constexpr unsigned TOTAL_WFC_SETTINGS_SIZE = 3 * (sizeof(Firmware::WifiAccessPoint) + sizeof(Firmware::ExtendedWifiAccessPoint));
|
||||
|
||||
if (!FileRead(firmware.GetExtendedAccessPointPosition(), TOTAL_WFC_SETTINGS_SIZE, 1, f))
|
||||
{ // If we couldn't read the Wi-fi settings from this file...
|
||||
Log(Warn, "Failed to read Wi-fi settings from \"%s\"; using defaults instead\n", Config::WifiSettingsPath.c_str());
|
||||
|
||||
// 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.)
|
||||
firmware.GetAccessPoints() = {
|
||||
Firmware::WifiAccessPoint(type),
|
||||
Firmware::WifiAccessPoint(),
|
||||
Firmware::WifiAccessPoint(),
|
||||
};
|
||||
|
||||
firmware.GetExtendedAccessPoints() = {
|
||||
Firmware::ExtendedWifiAccessPoint(),
|
||||
Firmware::ExtendedWifiAccessPoint(),
|
||||
Firmware::ExtendedWifiAccessPoint(),
|
||||
};
|
||||
firmware.UpdateChecksums();
|
||||
CloseFile(f);
|
||||
}
|
||||
}
|
||||
|
||||
CustomizeFirmware(firmware);
|
||||
|
||||
// If we don't have Wi-fi settings to load,
|
||||
// then the defaults will have already been populated by the constructor.
|
||||
return firmware;
|
||||
}
|
||||
|
||||
std::optional<Firmware> LoadFirmware(int type) noexcept
|
||||
{
|
||||
const string& firmwarepath = type == 1 ? Config::DSiFirmwarePath : Config::FirmwarePath;
|
||||
|
||||
Log(Debug, "SPI firmware: loading from file %s\n", firmwarepath.c_str());
|
||||
|
||||
FileHandle* file = OpenLocalFile(firmwarepath, Read);
|
||||
|
||||
if (!file)
|
||||
{
|
||||
Log(Error, "SPI firmware: couldn't open firmware file!\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
Firmware firmware(file);
|
||||
CloseFile(file);
|
||||
|
||||
if (!firmware.Buffer())
|
||||
{
|
||||
Log(Error, "SPI firmware: couldn't read firmware file!\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
CustomizeFirmware(firmware);
|
||||
|
||||
return firmware;
|
||||
}
|
||||
|
||||
|
||||
std::optional<DSi_NAND::NANDImage> LoadNAND(const std::array<u8, DSiBIOSSize>& arm7ibios) noexcept
|
||||
{
|
||||
FileHandle* nandfile = OpenLocalFile(Config::DSiNANDPath, ReadWriteExisting);
|
||||
if (!nandfile)
|
||||
return std::nullopt;
|
||||
|
||||
DSi_NAND::NANDImage nandImage(nandfile, &arm7ibios[0x8308]);
|
||||
if (!nandImage)
|
||||
{
|
||||
Log(Error, "Failed to parse DSi NAND\n");
|
||||
return std::nullopt;
|
||||
// the NANDImage takes ownership of the FileHandle, no need to clean it up here
|
||||
}
|
||||
|
||||
// scoped so that mount isn't alive when we move the NAND image to DSi::NANDImage
|
||||
{
|
||||
auto mount = DSi_NAND::NANDMount(nandImage);
|
||||
if (!mount)
|
||||
{
|
||||
Log(Error, "Failed to mount DSi NAND\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
DSi_NAND::DSiFirmwareSystemSettings settings {};
|
||||
if (!mount.ReadUserData(settings))
|
||||
{
|
||||
Log(Error, "Failed to read DSi NAND user data\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// override user settings, if needed
|
||||
if (Config::FirmwareOverrideSettings)
|
||||
{
|
||||
// we store relevant strings as UTF-8, so we need to convert them to UTF-16
|
||||
auto converter = wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t>{};
|
||||
|
||||
// setting up username
|
||||
std::u16string username = converter.from_bytes(Config::FirmwareUsername);
|
||||
size_t usernameLength = std::min(username.length(), (size_t) 10);
|
||||
memset(&settings.Nickname, 0, sizeof(settings.Nickname));
|
||||
memcpy(&settings.Nickname, username.data(), usernameLength * sizeof(char16_t));
|
||||
|
||||
// setting language
|
||||
settings.Language = static_cast<Firmware::Language>(Config::FirmwareLanguage);
|
||||
|
||||
// setting up color
|
||||
settings.FavoriteColor = Config::FirmwareFavouriteColour;
|
||||
|
||||
// setting up birthday
|
||||
settings.BirthdayMonth = Config::FirmwareBirthdayMonth;
|
||||
settings.BirthdayDay = Config::FirmwareBirthdayDay;
|
||||
|
||||
// setup message
|
||||
std::u16string message = converter.from_bytes(Config::FirmwareMessage);
|
||||
size_t messageLength = std::min(message.length(), (size_t) 26);
|
||||
memset(&settings.Message, 0, sizeof(settings.Message));
|
||||
memcpy(&settings.Message, message.data(), messageLength * sizeof(char16_t));
|
||||
|
||||
// TODO: make other items configurable?
|
||||
}
|
||||
|
||||
// fix touchscreen coords
|
||||
settings.TouchCalibrationADC1 = {0, 0};
|
||||
settings.TouchCalibrationPixel1 = {0, 0};
|
||||
settings.TouchCalibrationADC2 = {255 << 4, 191 << 4};
|
||||
settings.TouchCalibrationPixel2 = {255, 191};
|
||||
|
||||
settings.UpdateHash();
|
||||
|
||||
if (!mount.ApplyUserData(settings))
|
||||
{
|
||||
Log(LogLevel::Error, "Failed to write patched DSi NAND user data\n");
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
|
||||
return nandImage;
|
||||
}
|
||||
|
||||
constexpr int imgsizes[] = {0, 256, 512, 1024, 2048, 4096};
|
||||
std::optional<FATStorage> LoadDSiSDCard() noexcept
|
||||
{
|
||||
if (!Config::DSiSDEnable)
|
||||
return std::nullopt;
|
||||
|
||||
return FATStorage(
|
||||
Config::DSiSDPath,
|
||||
imgsizes[Config::DSiSDSize],
|
||||
Config::DSiSDReadOnly,
|
||||
Config::DSiSDFolderSync ? Config::DSiSDFolderPath : ""
|
||||
);
|
||||
}
|
||||
|
||||
void LoadBIOSFiles(NDS& nds)
|
||||
{
|
||||
if (Config::ExternalBIOSEnable)
|
||||
{
|
||||
if (FileHandle* f = Platform::OpenLocalFile(Config::BIOS9Path, FileMode::Read))
|
||||
{
|
||||
FileRewind(f);
|
||||
FileRead(NDS::ARM9BIOS, sizeof(NDS::ARM9BIOS), 1, f);
|
||||
FileRead(nds.ARM9BIOS, sizeof(NDS::ARM9BIOS), 1, f);
|
||||
|
||||
Log(LogLevel::Info, "ARM9 BIOS loaded from %s\n", Config::BIOS9Path.c_str());
|
||||
Platform::CloseFile(f);
|
||||
|
@ -496,12 +725,12 @@ void LoadBIOSFiles()
|
|||
Log(LogLevel::Warn, "ARM9 BIOS not found\n");
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
((u32*)NDS::ARM9BIOS)[i] = 0xE7FFDEFF;
|
||||
((u32*)nds.ARM9BIOS)[i] = 0xE7FFDEFF;
|
||||
}
|
||||
|
||||
if (FileHandle* f = Platform::OpenLocalFile(Config::BIOS7Path, FileMode::Read))
|
||||
{
|
||||
FileRead(NDS::ARM7BIOS, sizeof(NDS::ARM7BIOS), 1, f);
|
||||
FileRead(nds.ARM7BIOS, sizeof(NDS::ARM7BIOS), 1, f);
|
||||
|
||||
Log(LogLevel::Info, "ARM7 BIOS loaded from\n", Config::BIOS7Path.c_str());
|
||||
Platform::CloseFile(f);
|
||||
|
@ -511,21 +740,22 @@ void LoadBIOSFiles()
|
|||
Log(LogLevel::Warn, "ARM7 BIOS not found\n");
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
((u32*)NDS::ARM7BIOS)[i] = 0xE7FFDEFF;
|
||||
((u32*)nds.ARM7BIOS)[i] = 0xE7FFDEFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log(LogLevel::Info, "Using built-in ARM7 and ARM9 BIOSes\n");
|
||||
memcpy(NDS::ARM9BIOS, bios_arm9_bin, sizeof(bios_arm9_bin));
|
||||
memcpy(NDS::ARM7BIOS, bios_arm7_bin, sizeof(bios_arm7_bin));
|
||||
memcpy(nds.ARM9BIOS, bios_arm9_bin, sizeof(bios_arm9_bin));
|
||||
memcpy(nds.ARM7BIOS, bios_arm7_bin, sizeof(bios_arm7_bin));
|
||||
}
|
||||
|
||||
if (Config::ConsoleType == 1)
|
||||
{
|
||||
DSi& dsi = static_cast<DSi&>(nds);
|
||||
if (FileHandle* f = Platform::OpenLocalFile(Config::DSiBIOS9Path, FileMode::Read))
|
||||
{
|
||||
FileRead(DSi::ARM9iBIOS, sizeof(DSi::ARM9iBIOS), 1, f);
|
||||
FileRead(dsi.ARM9iBIOS, sizeof(DSi::ARM9iBIOS), 1, f);
|
||||
|
||||
Log(LogLevel::Info, "ARM9i BIOS loaded from %s\n", Config::DSiBIOS9Path.c_str());
|
||||
Platform::CloseFile(f);
|
||||
|
@ -535,13 +765,13 @@ void LoadBIOSFiles()
|
|||
Log(LogLevel::Warn, "ARM9i BIOS not found\n");
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
((u32*)DSi::ARM9iBIOS)[i] = 0xE7FFDEFF;
|
||||
((u32*)dsi.ARM9iBIOS)[i] = 0xE7FFDEFF;
|
||||
}
|
||||
|
||||
if (FileHandle* f = Platform::OpenLocalFile(Config::DSiBIOS7Path, FileMode::Read))
|
||||
{
|
||||
// TODO: check if the first 32 bytes are crapoed
|
||||
FileRead(DSi::ARM7iBIOS, sizeof(DSi::ARM7iBIOS), 1, f);
|
||||
FileRead(dsi.ARM7iBIOS, sizeof(DSi::ARM7iBIOS), 1, f);
|
||||
|
||||
Log(LogLevel::Info, "ARM7i BIOS loaded from %s\n", Config::DSiBIOS7Path.c_str());
|
||||
CloseFile(f);
|
||||
|
@ -551,14 +781,14 @@ void LoadBIOSFiles()
|
|||
Log(LogLevel::Warn, "ARM7i BIOS not found\n");
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
((u32*)DSi::ARM7iBIOS)[i] = 0xE7FFDEFF;
|
||||
((u32*)dsi.ARM7iBIOS)[i] = 0xE7FFDEFF;
|
||||
}
|
||||
|
||||
if (!Config::DSiFullBIOSBoot)
|
||||
{
|
||||
// herp
|
||||
*(u32*)&DSi::ARM9iBIOS[0] = 0xEAFFFFFE;
|
||||
*(u32*)&DSi::ARM7iBIOS[0] = 0xEAFFFFFE;
|
||||
*(u32*)&dsi.ARM9iBIOS[0] = 0xEAFFFFFE;
|
||||
*(u32*)&dsi.ARM7iBIOS[0] = 0xEAFFFFFE;
|
||||
|
||||
// TODO!!!!
|
||||
// hax the upper 32K out of the goddamn DSi
|
||||
|
@ -567,11 +797,11 @@ void LoadBIOSFiles()
|
|||
}
|
||||
}
|
||||
|
||||
void EnableCheats(bool enable)
|
||||
void EnableCheats(NDS& nds, bool enable)
|
||||
{
|
||||
CheatsOn = enable;
|
||||
if (CheatFile)
|
||||
NDS::AREngine->SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
||||
nds.AREngine.SetCodeFile(CheatsOn ? CheatFile : nullptr);
|
||||
}
|
||||
|
||||
ARCodeFile* GetCheatFile()
|
||||
|
@ -580,42 +810,44 @@ ARCodeFile* GetCheatFile()
|
|||
}
|
||||
|
||||
|
||||
void SetBatteryLevels()
|
||||
void SetBatteryLevels(NDS& nds)
|
||||
{
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (nds.ConsoleType == 1)
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetBatteryLevel(Config::DSiBatteryLevel);
|
||||
DSi::I2C->GetBPTWL()->SetBatteryCharging(Config::DSiBatteryCharging);
|
||||
auto& dsi = static_cast<DSi&>(nds);
|
||||
dsi.I2C.GetBPTWL()->SetBatteryLevel(Config::DSiBatteryLevel);
|
||||
dsi.I2C.GetBPTWL()->SetBatteryCharging(Config::DSiBatteryCharging);
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS::SPI->GetPowerMan()->SetBatteryLevelOkay(Config::DSBatteryLevelOkay);
|
||||
nds.SPI.GetPowerMan()->SetBatteryLevelOkay(Config::DSBatteryLevelOkay);
|
||||
}
|
||||
}
|
||||
|
||||
void SetDateTime()
|
||||
void SetDateTime(NDS& nds)
|
||||
{
|
||||
QDateTime hosttime = QDateTime::currentDateTime();
|
||||
QDateTime time = hosttime.addSecs(Config::RTCOffset);
|
||||
|
||||
NDS::RTC->SetDateTime(time.date().year(), time.date().month(), time.date().day(),
|
||||
nds.RTC.SetDateTime(time.date().year(), time.date().month(), time.date().day(),
|
||||
time.time().hour(), time.time().minute(), time.time().second());
|
||||
}
|
||||
|
||||
void Reset()
|
||||
void Reset(EmuThread* thread)
|
||||
{
|
||||
NDS::SetConsoleType(Config::ConsoleType);
|
||||
if (Config::ConsoleType == 1) EjectGBACart();
|
||||
LoadBIOSFiles();
|
||||
thread->RecreateConsole();
|
||||
|
||||
InstallFirmware();
|
||||
if (Config::ConsoleType == 1) EjectGBACart(*thread->NDS);
|
||||
LoadBIOSFiles(*thread->NDS);
|
||||
|
||||
InstallFirmware(*thread->NDS);
|
||||
if (Config::ConsoleType == 1)
|
||||
{
|
||||
InstallNAND(&DSi::ARM7iBIOS[0x8308]);
|
||||
InstallNAND(static_cast<DSi&>(*thread->NDS));
|
||||
}
|
||||
NDS::Reset();
|
||||
SetBatteryLevels();
|
||||
SetDateTime();
|
||||
thread->NDS->Reset();
|
||||
SetBatteryLevels(*thread->NDS);
|
||||
SetDateTime(*thread->NDS);
|
||||
|
||||
if ((CartType != -1) && NDSSave)
|
||||
{
|
||||
|
@ -659,27 +891,27 @@ void Reset()
|
|||
|
||||
if (!BaseROMName.empty())
|
||||
{
|
||||
if (Config::DirectBoot || NDS::NeedsDirectBoot())
|
||||
if (Config::DirectBoot || thread->NDS->NeedsDirectBoot())
|
||||
{
|
||||
NDS::SetupDirectBoot(BaseROMName);
|
||||
thread->NDS->SetupDirectBoot(BaseROMName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LoadBIOS()
|
||||
bool LoadBIOS(EmuThread* thread)
|
||||
{
|
||||
NDS::SetConsoleType(Config::ConsoleType);
|
||||
thread->RecreateConsole();
|
||||
|
||||
LoadBIOSFiles();
|
||||
LoadBIOSFiles(*thread->NDS);
|
||||
|
||||
if (!InstallFirmware())
|
||||
if (!InstallFirmware(*thread->NDS))
|
||||
return false;
|
||||
|
||||
if (Config::ConsoleType == 1 && !InstallNAND(&DSi::ARM7iBIOS[0x8308]))
|
||||
if (Config::ConsoleType == 1 && !InstallNAND(static_cast<DSi&>(*thread->NDS)))
|
||||
return false;
|
||||
|
||||
if (NDS::NeedsDirectBoot())
|
||||
if (thread->NDS->NeedsDirectBoot())
|
||||
return false;
|
||||
|
||||
/*if (NDSSave) delete NDSSave;
|
||||
|
@ -690,9 +922,9 @@ bool LoadBIOS()
|
|||
BaseROMName = "";
|
||||
BaseAssetName = "";*/
|
||||
|
||||
NDS::Reset();
|
||||
SetBatteryLevels();
|
||||
SetDateTime();
|
||||
thread->NDS->Reset();
|
||||
SetBatteryLevels(*thread->NDS);
|
||||
SetDateTime(*thread->NDS);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -884,7 +1116,7 @@ pair<unique_ptr<Firmware>, string> GenerateDefaultFirmware()
|
|||
return std::make_pair(std::move(firmware), std::move(wfcsettingspath));
|
||||
}
|
||||
|
||||
void LoadUserSettingsFromConfig(Firmware& firmware)
|
||||
void CustomizeFirmware(Firmware& firmware) noexcept
|
||||
{
|
||||
auto& currentData = firmware.GetEffectiveUserData();
|
||||
|
||||
|
@ -992,13 +1224,13 @@ static Platform::FileHandle* OpenNANDFile() noexcept
|
|||
return nandfile;
|
||||
}
|
||||
|
||||
bool InstallNAND(const u8* es_keyY)
|
||||
bool InstallNAND(DSi& dsi)
|
||||
{
|
||||
Platform::FileHandle* nandfile = OpenNANDFile();
|
||||
if (!nandfile)
|
||||
return false;
|
||||
|
||||
DSi_NAND::NANDImage nandImage(nandfile, es_keyY);
|
||||
DSi_NAND::NANDImage nandImage(nandfile, &dsi.ARM7iBIOS[0x8308]);
|
||||
if (!nandImage)
|
||||
{
|
||||
Log(LogLevel::Error, "Failed to parse DSi NAND\n");
|
||||
|
@ -1067,11 +1299,11 @@ bool InstallNAND(const u8* es_keyY)
|
|||
}
|
||||
}
|
||||
|
||||
DSi::NANDImage = std::make_unique<DSi_NAND::NANDImage>(std::move(nandImage));
|
||||
dsi.NANDImage = std::make_unique<DSi_NAND::NANDImage>(std::move(nandImage));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool InstallFirmware()
|
||||
bool InstallFirmware(NDS& nds)
|
||||
{
|
||||
FirmwareSave.reset();
|
||||
unique_ptr<Firmware> firmware;
|
||||
|
@ -1098,15 +1330,15 @@ bool InstallFirmware()
|
|||
|
||||
if (Config::FirmwareOverrideSettings)
|
||||
{
|
||||
LoadUserSettingsFromConfig(*firmware);
|
||||
CustomizeFirmware(*firmware);
|
||||
}
|
||||
|
||||
FirmwareSave = std::make_unique<SaveManager>(firmwarepath);
|
||||
|
||||
return NDS::SPI->GetFirmwareMem()->InstallFirmware(std::move(firmware));
|
||||
return nds.SPI.GetFirmwareMem()->InstallFirmware(std::move(firmware));
|
||||
}
|
||||
|
||||
bool LoadROM(QStringList filepath, bool reset)
|
||||
bool LoadROM(EmuThread* emuthread, QStringList filepath, bool reset)
|
||||
{
|
||||
if (filepath.empty()) return false;
|
||||
|
||||
|
@ -1201,22 +1433,22 @@ bool LoadROM(QStringList filepath, bool reset)
|
|||
BaseROMName = romname;
|
||||
BaseAssetName = romname.substr(0, romname.rfind('.'));
|
||||
|
||||
if (!InstallFirmware())
|
||||
emuthread->RecreateConsole();
|
||||
if (!InstallFirmware(*emuthread->NDS))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reset)
|
||||
{
|
||||
NDS::SetConsoleType(Config::ConsoleType);
|
||||
NDS::EjectCart();
|
||||
LoadBIOSFiles();
|
||||
emuthread->NDS->EjectCart();
|
||||
LoadBIOSFiles(*emuthread->NDS);
|
||||
if (Config::ConsoleType == 1)
|
||||
InstallNAND(&DSi::ARM7iBIOS[0x8308]);
|
||||
InstallNAND(static_cast<DSi&>(*emuthread->NDS));
|
||||
|
||||
NDS::Reset();
|
||||
SetBatteryLevels();
|
||||
SetDateTime();
|
||||
emuthread->NDS->Reset();
|
||||
SetBatteryLevels(*emuthread->NDS);
|
||||
SetDateTime(*emuthread->NDS);
|
||||
}
|
||||
|
||||
u32 savelen = 0;
|
||||
|
@ -1238,12 +1470,12 @@ bool LoadROM(QStringList filepath, bool reset)
|
|||
CloseFile(sav);
|
||||
}
|
||||
|
||||
bool res = NDS::LoadCart(filedata, filelen, savedata, savelen);
|
||||
bool res = emuthread->NDS->LoadCart(filedata, filelen, savedata, savelen);
|
||||
if (res && reset)
|
||||
{
|
||||
if (Config::DirectBoot || NDS::NeedsDirectBoot())
|
||||
if (Config::DirectBoot || emuthread->NDS->NeedsDirectBoot())
|
||||
{
|
||||
NDS::SetupDirectBoot(romname);
|
||||
emuthread->NDS->SetupDirectBoot(romname);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1252,7 +1484,7 @@ bool LoadROM(QStringList filepath, bool reset)
|
|||
CartType = 0;
|
||||
NDSSave = new SaveManager(savname);
|
||||
|
||||
LoadCheats();
|
||||
LoadCheats(*emuthread->NDS);
|
||||
}
|
||||
|
||||
if (savedata) delete[] savedata;
|
||||
|
@ -1260,14 +1492,14 @@ bool LoadROM(QStringList filepath, bool reset)
|
|||
return res;
|
||||
}
|
||||
|
||||
void EjectCart()
|
||||
void EjectCart(NDS& nds)
|
||||
{
|
||||
if (NDSSave) delete NDSSave;
|
||||
NDSSave = nullptr;
|
||||
|
||||
UnloadCheats();
|
||||
UnloadCheats(nds);
|
||||
|
||||
NDS::EjectCart();
|
||||
nds.EjectCart();
|
||||
|
||||
CartType = -1;
|
||||
BaseROMDir = "";
|
||||
|
@ -1295,7 +1527,7 @@ QString CartLabel()
|
|||
}
|
||||
|
||||
|
||||
bool LoadGBAROM(QStringList filepath)
|
||||
bool LoadGBAROM(NDS& nds, QStringList filepath)
|
||||
{
|
||||
if (Config::ConsoleType == 1) return false;
|
||||
if (filepath.empty()) return false;
|
||||
|
@ -1408,7 +1640,7 @@ bool LoadGBAROM(QStringList filepath)
|
|||
CloseFile(sav);
|
||||
}
|
||||
|
||||
bool res = NDS::LoadGBACart(filedata, filelen, savedata, savelen);
|
||||
bool res = nds.LoadGBACart(filedata, filelen, savedata, savelen);
|
||||
|
||||
if (res)
|
||||
{
|
||||
|
@ -1421,14 +1653,14 @@ bool LoadGBAROM(QStringList filepath)
|
|||
return res;
|
||||
}
|
||||
|
||||
void LoadGBAAddon(int type)
|
||||
void LoadGBAAddon(NDS& nds, int type)
|
||||
{
|
||||
if (Config::ConsoleType == 1) return;
|
||||
|
||||
if (GBASave) delete GBASave;
|
||||
GBASave = nullptr;
|
||||
|
||||
NDS::LoadGBAAddon(type);
|
||||
nds.LoadGBAAddon(type);
|
||||
|
||||
GBACartType = type;
|
||||
BaseGBAROMDir = "";
|
||||
|
@ -1436,12 +1668,12 @@ void LoadGBAAddon(int type)
|
|||
BaseGBAAssetName = "";
|
||||
}
|
||||
|
||||
void EjectGBACart()
|
||||
void EjectGBACart(NDS& nds)
|
||||
{
|
||||
if (GBASave) delete GBASave;
|
||||
GBASave = nullptr;
|
||||
|
||||
NDS::EjectGBACart();
|
||||
nds.EjectGBACart();
|
||||
|
||||
GBACartType = -1;
|
||||
BaseGBAROMDir = "";
|
||||
|
@ -1471,7 +1703,7 @@ QString GBACartLabel()
|
|||
return ret;
|
||||
}
|
||||
|
||||
case NDS::GBAAddon_RAMExpansion:
|
||||
case GBAAddon_RAMExpansion:
|
||||
return "Memory expansion";
|
||||
}
|
||||
|
||||
|
|
|
@ -24,10 +24,19 @@
|
|||
#include "AREngine.h"
|
||||
#include "DSi_NAND.h"
|
||||
|
||||
#include "MemConstants.h"
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
class NDS;
|
||||
class DSi;
|
||||
class FATStorage;
|
||||
}
|
||||
class EmuThread;
|
||||
namespace ROMManager
|
||||
{
|
||||
|
||||
|
@ -37,30 +46,41 @@ extern SaveManager* GBASave;
|
|||
extern std::unique_ptr<SaveManager> FirmwareSave;
|
||||
|
||||
QString VerifySetup();
|
||||
void Reset();
|
||||
bool LoadBIOS();
|
||||
void Reset(EmuThread* thread);
|
||||
bool LoadBIOS(EmuThread* thread);
|
||||
void ClearBackupState();
|
||||
|
||||
bool InstallFirmware();
|
||||
bool InstallNAND(const u8* es_keyY);
|
||||
bool LoadROM(QStringList filepath, bool reset);
|
||||
void EjectCart();
|
||||
std::optional<std::array<u8, ARM9BIOSSize>> LoadARM9BIOS() noexcept;
|
||||
std::optional<std::array<u8, ARM7BIOSSize>> LoadARM7BIOS() noexcept;
|
||||
std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM9BIOS() noexcept;
|
||||
std::optional<std::array<u8, DSiBIOSSize>> LoadDSiARM7BIOS() noexcept;
|
||||
std::optional<FATStorage> LoadDSiSDCard() noexcept;
|
||||
void CustomizeFirmware(Firmware& firmware) noexcept;
|
||||
Firmware GenerateFirmware(int type) noexcept;
|
||||
/// Loads and customizes a firmware image based on the values in Config
|
||||
std::optional<Firmware> LoadFirmware(int type) noexcept;
|
||||
/// Loads and customizes a NAND image based on the values in Config
|
||||
std::optional<DSi_NAND::NANDImage> LoadNAND(const std::array<u8, DSiBIOSSize>& arm7ibios) noexcept;
|
||||
bool InstallFirmware(NDS& nds);
|
||||
bool InstallNAND(DSi& dsi);
|
||||
bool LoadROM(EmuThread*, QStringList filepath, bool reset);
|
||||
void EjectCart(NDS& nds);
|
||||
bool CartInserted();
|
||||
QString CartLabel();
|
||||
|
||||
bool LoadGBAROM(QStringList filepath);
|
||||
void LoadGBAAddon(int type);
|
||||
void EjectGBACart();
|
||||
bool LoadGBAROM(NDS& nds, QStringList filepath);
|
||||
void LoadGBAAddon(NDS& nds, int type);
|
||||
void EjectGBACart(NDS& nds);
|
||||
bool GBACartInserted();
|
||||
QString GBACartLabel();
|
||||
|
||||
std::string GetSavestateName(int slot);
|
||||
bool SavestateExists(int slot);
|
||||
bool LoadState(const std::string& filename);
|
||||
bool SaveState(const std::string& filename);
|
||||
void UndoStateLoad();
|
||||
bool LoadState(NDS& nds, const std::string& filename);
|
||||
bool SaveState(NDS& nds, const std::string& filename);
|
||||
void UndoStateLoad(NDS& nds);
|
||||
|
||||
void EnableCheats(bool enable);
|
||||
void EnableCheats(NDS& nds, bool enable);
|
||||
ARCodeFile* GetCheatFile();
|
||||
|
||||
void ROMIcon(const u8 (&data)[512], const u16 (&palette)[16], u32 (&iconRef)[32*32]);
|
||||
|
|
|
@ -203,6 +203,30 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
|
|||
static_cast<ScreenPanelGL*>(mainWindow->panel)->transferLayout(this);
|
||||
}
|
||||
|
||||
std::unique_ptr<NDS> EmuThread::CreateConsole()
|
||||
{
|
||||
if (Config::ConsoleType == 1)
|
||||
{
|
||||
return std::make_unique<melonDS::DSi>();
|
||||
}
|
||||
|
||||
return std::make_unique<melonDS::NDS>();
|
||||
}
|
||||
|
||||
void EmuThread::RecreateConsole()
|
||||
{
|
||||
if (!NDS || NDS->ConsoleType != Config::ConsoleType)
|
||||
{
|
||||
NDS = nullptr; // To ensure the destructor is called before a new one is created
|
||||
NDS::Current = nullptr;
|
||||
|
||||
NDS = CreateConsole();
|
||||
// TODO: Insert ROMs
|
||||
NDS::Current = NDS.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void EmuThread::updateScreenSettings(bool filter, const WindowInfo& windowInfo, int numScreens, int* screenKind, float* screenMatrix)
|
||||
{
|
||||
screenSettingsLock.lock();
|
||||
|
@ -318,7 +342,7 @@ void EmuThread::run()
|
|||
u32 mainScreenPos[3];
|
||||
Platform::FileHandle* file;
|
||||
|
||||
NDS::Init();
|
||||
RecreateConsole();
|
||||
|
||||
mainScreenPos[0] = 0;
|
||||
mainScreenPos[1] = 0;
|
||||
|
@ -340,10 +364,10 @@ void EmuThread::run()
|
|||
videoRenderer = 0;
|
||||
}
|
||||
|
||||
NDS::GPU->InitRenderer(videoRenderer);
|
||||
NDS::GPU->SetRenderSettings(videoRenderer, videoSettings);
|
||||
NDS->GPU.InitRenderer(videoRenderer);
|
||||
NDS->GPU.SetRenderSettings(videoRenderer, videoSettings);
|
||||
|
||||
NDS::SPU->SetInterpolation(Config::AudioInterp);
|
||||
NDS->SPU.SetInterpolation(Config::AudioInterp);
|
||||
|
||||
Input::Init();
|
||||
|
||||
|
@ -362,7 +386,7 @@ void EmuThread::run()
|
|||
RTC::StateData state;
|
||||
Platform::FileRead(&state, sizeof(state), 1, file);
|
||||
Platform::CloseFile(file);
|
||||
NDS::RTC->SetState(state);
|
||||
NDS->RTC.SetState(state);
|
||||
}
|
||||
|
||||
char melontitle[100];
|
||||
|
@ -384,8 +408,7 @@ void EmuThread::run()
|
|||
|
||||
if (Input::HotkeyPressed(HK_SolarSensorDecrease))
|
||||
{
|
||||
assert(NDS::GBACartSlot != nullptr);
|
||||
int level = NDS::GBACartSlot->SetInput(GBACart::Input_SolarSensorDown, true);
|
||||
int level = NDS->GBACartSlot.SetInput(GBACart::Input_SolarSensorDown, true);
|
||||
if (level != -1)
|
||||
{
|
||||
char msg[64];
|
||||
|
@ -395,8 +418,7 @@ void EmuThread::run()
|
|||
}
|
||||
if (Input::HotkeyPressed(HK_SolarSensorIncrease))
|
||||
{
|
||||
assert(NDS::GBACartSlot != nullptr);
|
||||
int level = NDS::GBACartSlot->SetInput(GBACart::Input_SolarSensorUp, true);
|
||||
int level = NDS->GBACartSlot.SetInput(GBACart::Input_SolarSensorUp, true);
|
||||
if (level != -1)
|
||||
{
|
||||
char msg[64];
|
||||
|
@ -405,40 +427,41 @@ void EmuThread::run()
|
|||
}
|
||||
}
|
||||
|
||||
if (NDS::ConsoleType == 1)
|
||||
if (NDS->ConsoleType == 1)
|
||||
{
|
||||
DSi& dsi = static_cast<DSi&>(*NDS);
|
||||
double currentTime = SDL_GetPerformanceCounter() * perfCountsSec;
|
||||
|
||||
// Handle power button
|
||||
if (Input::HotkeyDown(HK_PowerButton))
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetPowerButtonHeld(currentTime);
|
||||
dsi.I2C.GetBPTWL()->SetPowerButtonHeld(currentTime);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_PowerButton))
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetPowerButtonReleased(currentTime);
|
||||
dsi.I2C.GetBPTWL()->SetPowerButtonReleased(currentTime);
|
||||
}
|
||||
|
||||
// Handle volume buttons
|
||||
if (Input::HotkeyDown(HK_VolumeUp))
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetVolumeSwitchHeld(DSi::I2C->GetBPTWL()->volumeKey_Up);
|
||||
dsi.I2C.GetBPTWL()->SetVolumeSwitchHeld(DSi_BPTWL::volumeKey_Up);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_VolumeUp))
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetVolumeSwitchReleased(DSi::I2C->GetBPTWL()->volumeKey_Up);
|
||||
dsi.I2C.GetBPTWL()->SetVolumeSwitchReleased(DSi_BPTWL::volumeKey_Up);
|
||||
}
|
||||
|
||||
if (Input::HotkeyDown(HK_VolumeDown))
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetVolumeSwitchHeld(DSi::I2C->GetBPTWL()->volumeKey_Down);
|
||||
dsi.I2C.GetBPTWL()->SetVolumeSwitchHeld(DSi_BPTWL::volumeKey_Down);
|
||||
}
|
||||
else if (Input::HotkeyReleased(HK_VolumeDown))
|
||||
{
|
||||
DSi::I2C->GetBPTWL()->SetVolumeSwitchReleased(DSi::I2C->GetBPTWL()->volumeKey_Down);
|
||||
dsi.I2C.GetBPTWL()->SetVolumeSwitchReleased(DSi_BPTWL::volumeKey_Down);
|
||||
}
|
||||
|
||||
DSi::I2C->GetBPTWL()->ProcessVolumeSwitchInput(currentTime);
|
||||
dsi.I2C.GetBPTWL()->ProcessVolumeSwitchInput(currentTime);
|
||||
}
|
||||
|
||||
if (EmuRunning == emuStatus_Running || EmuRunning == emuStatus_FrameStep)
|
||||
|
@ -472,28 +495,28 @@ void EmuThread::run()
|
|||
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
|
||||
videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons;
|
||||
|
||||
NDS::GPU->SetRenderSettings(videoRenderer, videoSettings);
|
||||
NDS->GPU.SetRenderSettings(videoRenderer, videoSettings);
|
||||
}
|
||||
|
||||
// process input and hotkeys
|
||||
NDS::SetKeyMask(Input::InputMask);
|
||||
NDS->SetKeyMask(Input::InputMask);
|
||||
|
||||
if (Input::HotkeyPressed(HK_Lid))
|
||||
{
|
||||
bool lid = !NDS::IsLidClosed();
|
||||
NDS::SetLidClosed(lid);
|
||||
bool lid = !NDS->IsLidClosed();
|
||||
NDS->SetLidClosed(lid);
|
||||
OSD::AddMessage(0, lid ? "Lid closed" : "Lid opened");
|
||||
}
|
||||
|
||||
// microphone input
|
||||
AudioInOut::MicProcess();
|
||||
AudioInOut::MicProcess(*NDS);
|
||||
|
||||
// auto screen layout
|
||||
if (Config::ScreenSizing == Frontend::screenSizing_Auto)
|
||||
{
|
||||
mainScreenPos[2] = mainScreenPos[1];
|
||||
mainScreenPos[1] = mainScreenPos[0];
|
||||
mainScreenPos[0] = NDS::PowerControl9 >> 15;
|
||||
mainScreenPos[0] = NDS->PowerControl9 >> 15;
|
||||
|
||||
int guess;
|
||||
if (mainScreenPos[0] == mainScreenPos[2] &&
|
||||
|
@ -520,7 +543,7 @@ void EmuThread::run()
|
|||
|
||||
|
||||
// emulate
|
||||
u32 nlines = NDS::RunFrame();
|
||||
u32 nlines = NDS->RunFrame();
|
||||
|
||||
if (ROMManager::NDSSave)
|
||||
ROMManager::NDSSave->CheckFlush();
|
||||
|
@ -534,12 +557,12 @@ void EmuThread::run()
|
|||
if (!oglContext)
|
||||
{
|
||||
FrontBufferLock.lock();
|
||||
FrontBuffer = NDS::GPU->FrontBuffer;
|
||||
FrontBuffer = NDS->GPU.FrontBuffer;
|
||||
FrontBufferLock.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
FrontBuffer = NDS::GPU->FrontBuffer;
|
||||
FrontBuffer = NDS->GPU.FrontBuffer;
|
||||
drawScreenGL();
|
||||
}
|
||||
|
||||
|
@ -563,9 +586,10 @@ void EmuThread::run()
|
|||
oglContext->SetSwapInterval(0);
|
||||
}
|
||||
|
||||
if (Config::DSiVolumeSync && NDS::ConsoleType == 1)
|
||||
if (Config::DSiVolumeSync && NDS->ConsoleType == 1)
|
||||
{
|
||||
u8 volumeLevel = DSi::I2C->GetBPTWL()->GetVolumeLevel();
|
||||
DSi& dsi = static_cast<DSi&>(*NDS);
|
||||
u8 volumeLevel = dsi.I2C.GetBPTWL()->GetVolumeLevel();
|
||||
if (volumeLevel != dsiVolumeLevel)
|
||||
{
|
||||
dsiVolumeLevel = volumeLevel;
|
||||
|
@ -576,7 +600,7 @@ void EmuThread::run()
|
|||
}
|
||||
|
||||
if (Config::AudioSync && !fastforward)
|
||||
AudioInOut::AudioSync();
|
||||
AudioInOut::AudioSync(*emuThread->NDS);
|
||||
|
||||
double frametimeStep = nlines / (60.0 * 263.0);
|
||||
|
||||
|
@ -669,16 +693,15 @@ void EmuThread::run()
|
|||
if (file)
|
||||
{
|
||||
RTC::StateData state;
|
||||
NDS::RTC->GetState(state);
|
||||
NDS->RTC.GetState(state);
|
||||
Platform::FileWrite(&state, sizeof(state), 1, file);
|
||||
Platform::CloseFile(file);
|
||||
}
|
||||
|
||||
EmuStatus = emuStatus_Exit;
|
||||
|
||||
NDS::GPU->DeInitRenderer();
|
||||
NDS::DeInit();
|
||||
//Platform::LAN_DeInit();
|
||||
NDS::Current = nullptr;
|
||||
// nds is out of scope, so unique_ptr cleans it up for us
|
||||
}
|
||||
|
||||
void EmuThread::changeWindowTitle(char* title)
|
||||
|
@ -759,6 +782,7 @@ bool EmuThread::emuIsActive()
|
|||
|
||||
void EmuThread::drawScreenGL()
|
||||
{
|
||||
if (!NDS) return;
|
||||
int w = windowInfo.surface_width;
|
||||
int h = windowInfo.surface_height;
|
||||
float factor = windowInfo.surface_scale;
|
||||
|
@ -780,10 +804,10 @@ void EmuThread::drawScreenGL()
|
|||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
if (NDS::GPU->Renderer != 0)
|
||||
if (NDS->GPU.Renderer != 0)
|
||||
{
|
||||
// hardware-accelerated render
|
||||
NDS::GPU->CurGLCompositor->BindOutputTexture(frontbuf);
|
||||
NDS->GPU.CurGLCompositor->BindOutputTexture(frontbuf);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -791,12 +815,12 @@ void EmuThread::drawScreenGL()
|
|||
// regular render
|
||||
glBindTexture(GL_TEXTURE_2D, screenTexture);
|
||||
|
||||
if (NDS::GPU->Framebuffer[frontbuf][0] && NDS::GPU->Framebuffer[frontbuf][1])
|
||||
if (NDS->GPU.Framebuffer[frontbuf][0] && NDS->GPU.Framebuffer[frontbuf][1])
|
||||
{
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 256, 192, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, NDS::GPU->Framebuffer[frontbuf][0]);
|
||||
GL_UNSIGNED_BYTE, NDS->GPU.Framebuffer[frontbuf][0]);
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 192+2, 256, 192, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, NDS::GPU->Framebuffer[frontbuf][1]);
|
||||
GL_UNSIGNED_BYTE, NDS->GPU.Framebuffer[frontbuf][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -927,7 +951,8 @@ void ScreenHandler::screenOnMousePress(QMouseEvent* event)
|
|||
if (Frontend::GetTouchCoords(x, y, false))
|
||||
{
|
||||
touching = true;
|
||||
NDS::TouchScreen(x, y);
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->TouchScreen(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -939,7 +964,8 @@ void ScreenHandler::screenOnMouseRelease(QMouseEvent* event)
|
|||
if (touching)
|
||||
{
|
||||
touching = false;
|
||||
NDS::ReleaseScreen();
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->ReleaseScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -956,7 +982,10 @@ void ScreenHandler::screenOnMouseMove(QMouseEvent* event)
|
|||
int y = event->pos().y();
|
||||
|
||||
if (Frontend::GetTouchCoords(x, y, true))
|
||||
NDS::TouchScreen(x, y);
|
||||
{
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->TouchScreen(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenHandler::screenHandleTablet(QTabletEvent* event)
|
||||
|
@ -974,14 +1003,16 @@ void ScreenHandler::screenHandleTablet(QTabletEvent* event)
|
|||
if (Frontend::GetTouchCoords(x, y, event->type()==QEvent::TabletMove))
|
||||
{
|
||||
touching = true;
|
||||
NDS::TouchScreen(x, y);
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->TouchScreen(x, y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QEvent::TabletRelease:
|
||||
if (touching)
|
||||
{
|
||||
NDS::ReleaseScreen();
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->ReleaseScreen();
|
||||
touching = false;
|
||||
}
|
||||
break;
|
||||
|
@ -1007,14 +1038,16 @@ void ScreenHandler::screenHandleTouch(QTouchEvent* event)
|
|||
if (Frontend::GetTouchCoords(x, y, event->type()==QEvent::TouchUpdate))
|
||||
{
|
||||
touching = true;
|
||||
NDS::TouchScreen(x, y);
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->TouchScreen(x, y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case QEvent::TouchEnd:
|
||||
if (touching)
|
||||
{
|
||||
NDS::ReleaseScreen();
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->ReleaseScreen();
|
||||
touching = false;
|
||||
}
|
||||
break;
|
||||
|
@ -1080,16 +1113,17 @@ void ScreenPanelNative::paintEvent(QPaintEvent* event)
|
|||
|
||||
if (emuThread->emuIsActive())
|
||||
{
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->FrontBufferLock.lock();
|
||||
int frontbuf = emuThread->FrontBuffer;
|
||||
if (!NDS::GPU->Framebuffer[frontbuf][0] || !NDS::GPU->Framebuffer[frontbuf][1])
|
||||
if (!emuThread->NDS->GPU.Framebuffer[frontbuf][0] || !emuThread->NDS->GPU.Framebuffer[frontbuf][1])
|
||||
{
|
||||
emuThread->FrontBufferLock.unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(screen[0].scanLine(0), NDS::GPU->Framebuffer[frontbuf][0], 256 * 192 * 4);
|
||||
memcpy(screen[1].scanLine(0), NDS::GPU->Framebuffer[frontbuf][1], 256 * 192 * 4);
|
||||
memcpy(screen[0].scanLine(0), emuThread->NDS->GPU.Framebuffer[frontbuf][0], 256 * 192 * 4);
|
||||
memcpy(screen[1].scanLine(0), emuThread->NDS->GPU.Framebuffer[frontbuf][1], 256 * 192 * 4);
|
||||
emuThread->FrontBufferLock.unlock();
|
||||
|
||||
QRect screenrc(0, 0, 256, 192);
|
||||
|
@ -1472,7 +1506,7 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
|||
QMenu* submenu = menu->addMenu("Insert add-on cart");
|
||||
|
||||
actInsertGBAAddon[0] = submenu->addAction("Memory expansion");
|
||||
actInsertGBAAddon[0]->setData(QVariant(NDS::GBAAddon_RAMExpansion));
|
||||
actInsertGBAAddon[0]->setData(QVariant(GBAAddon_RAMExpansion));
|
||||
connect(actInsertGBAAddon[0], &QAction::triggered, this, &MainWindow::onInsertGBAAddon);
|
||||
}
|
||||
|
||||
|
@ -2025,7 +2059,7 @@ void MainWindow::dropEvent(QDropEvent* event)
|
|||
|
||||
if (isNdsRom)
|
||||
{
|
||||
if (!ROMManager::LoadROM(file, true))
|
||||
if (!ROMManager::LoadROM(emuThread, file, true))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "Failed to load the DS ROM.");
|
||||
|
@ -2038,14 +2072,15 @@ void MainWindow::dropEvent(QDropEvent* event)
|
|||
recentFileList.prepend(barredFilename);
|
||||
updateRecentFilesMenu();
|
||||
|
||||
NDS::Start();
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->Start();
|
||||
emuThread->emuRun();
|
||||
|
||||
updateCartInserted(false);
|
||||
}
|
||||
else if (isGbaRom)
|
||||
{
|
||||
if (!ROMManager::LoadGBAROM(file))
|
||||
if (!ROMManager::LoadGBAROM(*emuThread->NDS, file))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "Failed to load the GBA ROM.");
|
||||
|
@ -2111,7 +2146,7 @@ bool MainWindow::preloadROMs(QStringList file, QStringList gbafile, bool boot)
|
|||
bool gbaloaded = false;
|
||||
if (!gbafile.isEmpty())
|
||||
{
|
||||
if (!ROMManager::LoadGBAROM(gbafile))
|
||||
if (!ROMManager::LoadGBAROM(*emuThread->NDS, gbafile))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "Failed to load the GBA ROM.");
|
||||
|
@ -2124,7 +2159,7 @@ bool MainWindow::preloadROMs(QStringList file, QStringList gbafile, bool boot)
|
|||
bool ndsloaded = false;
|
||||
if (!file.isEmpty())
|
||||
{
|
||||
if (!ROMManager::LoadROM(file, true))
|
||||
if (!ROMManager::LoadROM(emuThread, file, true))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
||||
|
@ -2140,7 +2175,7 @@ bool MainWindow::preloadROMs(QStringList file, QStringList gbafile, bool boot)
|
|||
{
|
||||
if (ndsloaded)
|
||||
{
|
||||
NDS::Start();
|
||||
emuThread->NDS->Start();
|
||||
emuThread->emuRun();
|
||||
}
|
||||
else
|
||||
|
@ -2333,7 +2368,7 @@ void MainWindow::onOpenFile()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!ROMManager::LoadROM(file, true))
|
||||
if (!ROMManager::LoadROM(emuThread, file, true))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
||||
|
@ -2346,7 +2381,8 @@ void MainWindow::onOpenFile()
|
|||
recentFileList.prepend(filename);
|
||||
updateRecentFilesMenu();
|
||||
|
||||
NDS::Start();
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->Start();
|
||||
emuThread->emuRun();
|
||||
|
||||
updateCartInserted(false);
|
||||
|
@ -2431,7 +2467,7 @@ void MainWindow::onClickRecentFile()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!ROMManager::LoadROM(file, true))
|
||||
if (!ROMManager::LoadROM(emuThread, file, true))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
||||
|
@ -2443,7 +2479,8 @@ void MainWindow::onClickRecentFile()
|
|||
recentFileList.prepend(filename);
|
||||
updateRecentFilesMenu();
|
||||
|
||||
NDS::Start();
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->Start();
|
||||
emuThread->emuRun();
|
||||
|
||||
updateCartInserted(false);
|
||||
|
@ -2459,7 +2496,7 @@ void MainWindow::onBootFirmware()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!ROMManager::LoadBIOS())
|
||||
if (!ROMManager::LoadBIOS(emuThread))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "This firmware is not bootable.");
|
||||
|
@ -2467,7 +2504,8 @@ void MainWindow::onBootFirmware()
|
|||
return;
|
||||
}
|
||||
|
||||
NDS::Start();
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->Start();
|
||||
emuThread->emuRun();
|
||||
}
|
||||
|
||||
|
@ -2482,7 +2520,7 @@ void MainWindow::onInsertCart()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!ROMManager::LoadROM(file, false))
|
||||
if (!ROMManager::LoadROM(emuThread, file, false))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
||||
|
@ -2499,7 +2537,7 @@ void MainWindow::onEjectCart()
|
|||
{
|
||||
emuThread->emuPause();
|
||||
|
||||
ROMManager::EjectCart();
|
||||
ROMManager::EjectCart(*emuThread->NDS);
|
||||
|
||||
emuThread->emuUnpause();
|
||||
|
||||
|
@ -2517,7 +2555,7 @@ void MainWindow::onInsertGBACart()
|
|||
return;
|
||||
}
|
||||
|
||||
if (!ROMManager::LoadGBAROM(file))
|
||||
if (!ROMManager::LoadGBAROM(*emuThread->NDS, file))
|
||||
{
|
||||
// TODO: better error reporting?
|
||||
QMessageBox::critical(this, "melonDS", "Failed to load the ROM.");
|
||||
|
@ -2537,7 +2575,7 @@ void MainWindow::onInsertGBAAddon()
|
|||
|
||||
emuThread->emuPause();
|
||||
|
||||
ROMManager::LoadGBAAddon(type);
|
||||
ROMManager::LoadGBAAddon(*emuThread->NDS, type);
|
||||
|
||||
emuThread->emuUnpause();
|
||||
|
||||
|
@ -2548,7 +2586,7 @@ void MainWindow::onEjectGBACart()
|
|||
{
|
||||
emuThread->emuPause();
|
||||
|
||||
ROMManager::EjectGBACart();
|
||||
ROMManager::EjectGBACart(*emuThread->NDS);
|
||||
|
||||
emuThread->emuUnpause();
|
||||
|
||||
|
@ -2582,7 +2620,7 @@ void MainWindow::onSaveState()
|
|||
filename = qfilename.toStdString();
|
||||
}
|
||||
|
||||
if (ROMManager::SaveState(filename))
|
||||
if (ROMManager::SaveState(*emuThread->NDS, filename))
|
||||
{
|
||||
char msg[64];
|
||||
if (slot > 0) sprintf(msg, "State saved to slot %d", slot);
|
||||
|
@ -2637,7 +2675,7 @@ void MainWindow::onLoadState()
|
|||
return;
|
||||
}
|
||||
|
||||
if (ROMManager::LoadState(filename))
|
||||
if (ROMManager::LoadState(*emuThread->NDS, filename))
|
||||
{
|
||||
char msg[64];
|
||||
if (slot > 0) sprintf(msg, "State loaded from slot %d", slot);
|
||||
|
@ -2657,7 +2695,7 @@ void MainWindow::onLoadState()
|
|||
void MainWindow::onUndoStateLoad()
|
||||
{
|
||||
emuThread->emuPause();
|
||||
ROMManager::UndoStateLoad();
|
||||
ROMManager::UndoStateLoad(*emuThread->NDS);
|
||||
emuThread->emuUnpause();
|
||||
|
||||
OSD::AddMessage(0, "State load undone");
|
||||
|
@ -2696,7 +2734,7 @@ void MainWindow::onImportSavefile()
|
|||
return;
|
||||
}
|
||||
|
||||
ROMManager::Reset();
|
||||
ROMManager::Reset(emuThread);
|
||||
}
|
||||
|
||||
u32 len = FileLength(f);
|
||||
|
@ -2705,7 +2743,8 @@ void MainWindow::onImportSavefile()
|
|||
Platform::FileRewind(f);
|
||||
Platform::FileRead(data, len, 1, f);
|
||||
|
||||
NDS::LoadSave(data, len);
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->LoadSave(data, len);
|
||||
delete[] data;
|
||||
|
||||
CloseFile(f);
|
||||
|
@ -2747,7 +2786,7 @@ void MainWindow::onReset()
|
|||
|
||||
actUndoStateLoad->setEnabled(false);
|
||||
|
||||
ROMManager::Reset();
|
||||
ROMManager::Reset(emuThread);
|
||||
|
||||
OSD::AddMessage(0, "Reset");
|
||||
emuThread->emuRun();
|
||||
|
@ -2758,7 +2797,7 @@ void MainWindow::onStop()
|
|||
if (!RunningSomething) return;
|
||||
|
||||
emuThread->emuPause();
|
||||
NDS::Stop();
|
||||
emuThread->NDS->Stop();
|
||||
}
|
||||
|
||||
void MainWindow::onFrameStep()
|
||||
|
@ -2775,13 +2814,13 @@ void MainWindow::onOpenDateTime()
|
|||
|
||||
void MainWindow::onOpenPowerManagement()
|
||||
{
|
||||
PowerManagementDialog* dlg = PowerManagementDialog::openDlg(this);
|
||||
PowerManagementDialog* dlg = PowerManagementDialog::openDlg(this, emuThread);
|
||||
}
|
||||
|
||||
void MainWindow::onEnableCheats(bool checked)
|
||||
{
|
||||
Config::EnableCheats = checked?1:0;
|
||||
ROMManager::EnableCheats(Config::EnableCheats != 0);
|
||||
ROMManager::EnableCheats(*emuThread->NDS, Config::EnableCheats != 0);
|
||||
}
|
||||
|
||||
void MainWindow::onSetupCheats()
|
||||
|
@ -2799,12 +2838,14 @@ void MainWindow::onCheatsDialogFinished(int res)
|
|||
|
||||
void MainWindow::onROMInfo()
|
||||
{
|
||||
ROMInfoDialog* dlg = ROMInfoDialog::openDlg(this);
|
||||
auto cart = emuThread->NDS->NDSCartSlot.GetCart();
|
||||
if (cart)
|
||||
ROMInfoDialog* dlg = ROMInfoDialog::openDlg(this, *cart);
|
||||
}
|
||||
|
||||
void MainWindow::onRAMInfo()
|
||||
{
|
||||
RAMInfoDialog* dlg = RAMInfoDialog::openDlg(this);
|
||||
RAMInfoDialog* dlg = RAMInfoDialog::openDlg(this, emuThread);
|
||||
}
|
||||
|
||||
void MainWindow::onOpenTitleManager()
|
||||
|
@ -2907,7 +2948,7 @@ void MainWindow::onCameraSettingsFinished(int res)
|
|||
|
||||
void MainWindow::onOpenAudioSettings()
|
||||
{
|
||||
AudioSettingsDialog* dlg = AudioSettingsDialog::openDlg(this, emuThread->emuIsActive());
|
||||
AudioSettingsDialog* dlg = AudioSettingsDialog::openDlg(this, emuThread->emuIsActive(), emuThread);
|
||||
connect(emuThread, &EmuThread::syncVolumeLevel, dlg, &AudioSettingsDialog::onSyncVolumeLevel);
|
||||
connect(emuThread, &EmuThread::windowEmuStart, dlg, &AudioSettingsDialog::onConsoleReset);
|
||||
connect(dlg, &AudioSettingsDialog::updateAudioSettings, this, &MainWindow::onUpdateAudioSettings);
|
||||
|
@ -2948,17 +2989,18 @@ void MainWindow::onPathSettingsFinished(int res)
|
|||
|
||||
void MainWindow::onUpdateAudioSettings()
|
||||
{
|
||||
NDS::SPU->SetInterpolation(Config::AudioInterp);
|
||||
assert(emuThread->NDS != nullptr);
|
||||
emuThread->NDS->SPU.SetInterpolation(Config::AudioInterp);
|
||||
|
||||
if (Config::AudioBitDepth == 0)
|
||||
NDS::SPU->SetDegrade10Bit(NDS::ConsoleType == 0);
|
||||
emuThread->NDS->SPU.SetDegrade10Bit(emuThread->NDS->ConsoleType == 0);
|
||||
else
|
||||
NDS::SPU->SetDegrade10Bit(Config::AudioBitDepth == 1);
|
||||
emuThread->NDS->SPU.SetDegrade10Bit(Config::AudioBitDepth == 1);
|
||||
}
|
||||
|
||||
void MainWindow::onAudioSettingsFinished(int res)
|
||||
{
|
||||
AudioInOut::UpdateSettings();
|
||||
AudioInOut::UpdateSettings(*emuThread->NDS);
|
||||
}
|
||||
|
||||
void MainWindow::onOpenMPSettings()
|
||||
|
@ -3313,13 +3355,11 @@ int main(int argc, char** argv)
|
|||
|
||||
#define SANITIZE(var, min, max) { var = std::clamp(var, min, max); }
|
||||
SANITIZE(Config::ConsoleType, 0, 1);
|
||||
SANITIZE(Config::_3DRenderer,
|
||||
0,
|
||||
0 // Minimum, Software renderer
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
+ 1 // OpenGL Renderer
|
||||
#endif
|
||||
);
|
||||
#ifdef OGLRENDERER_ENABLED
|
||||
SANITIZE(Config::_3DRenderer, 0, 1); // 0 is the software renderer, 1 is the OpenGL renderer
|
||||
#else
|
||||
SANITIZE(Config::_3DRenderer, 0, 0);
|
||||
#endif
|
||||
SANITIZE(Config::ScreenVSyncInterval, 1, 20);
|
||||
SANITIZE(Config::GL_ScaleFactor, 1, 16);
|
||||
SANITIZE(Config::AudioInterp, 0, 3);
|
||||
|
@ -3333,7 +3373,6 @@ int main(int argc, char** argv)
|
|||
SANITIZE(Config::ScreenAspectBot, 0, AspectRatiosNum);
|
||||
#undef SANITIZE
|
||||
|
||||
AudioInOut::Init();
|
||||
camStarted[0] = false;
|
||||
camStarted[1] = false;
|
||||
camManager[0] = new CameraManager(0, 640, 480, true);
|
||||
|
@ -3341,7 +3380,6 @@ int main(int argc, char** argv)
|
|||
camManager[0]->setXFlip(Config::Camera[0].XFlip);
|
||||
camManager[1]->setXFlip(Config::Camera[1].XFlip);
|
||||
|
||||
ROMManager::EnableCheats(Config::EnableCheats != 0);
|
||||
|
||||
Input::JoystickID = Config::JoystickID;
|
||||
Input::OpenJoystick();
|
||||
|
@ -3354,6 +3392,8 @@ int main(int argc, char** argv)
|
|||
emuThread->start();
|
||||
emuThread->emuPause();
|
||||
|
||||
AudioInOut::Init(emuThread);
|
||||
ROMManager::EnableCheats(*emuThread->NDS, Config::EnableCheats != 0);
|
||||
AudioInOut::AudioMute(mainWindow);
|
||||
|
||||
QObject::connect(&melon, &QApplication::applicationStateChanged, mainWindow, &MainWindow::onAppStateChanged);
|
||||
|
|
|
@ -40,6 +40,11 @@
|
|||
#include "FrontendUtil.h"
|
||||
#include "duckstation/gl/context.h"
|
||||
|
||||
namespace melonDS
|
||||
{
|
||||
class NDS;
|
||||
}
|
||||
|
||||
class EmuThread : public QThread
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -67,7 +72,8 @@ public:
|
|||
QMutex FrontBufferLock;
|
||||
|
||||
void updateScreenSettings(bool filter, const WindowInfo& windowInfo, int numScreens, int* screenKind, float* screenMatrix);
|
||||
|
||||
void RecreateConsole();
|
||||
std::unique_ptr<melonDS::NDS> NDS; // TODO: Proper encapsulation and synchronization
|
||||
signals:
|
||||
void windowUpdate();
|
||||
void windowTitleChange(QString title);
|
||||
|
@ -90,6 +96,7 @@ signals:
|
|||
void syncVolumeLevel();
|
||||
|
||||
private:
|
||||
std::unique_ptr<melonDS::NDS> CreateConsole();
|
||||
void drawScreenGL();
|
||||
void initOpenGL();
|
||||
void deinitOpenGL();
|
||||
|
|
Loading…
Reference in New Issue