Compare commits
5 Commits
98d0a6b371
...
93dd0f47bd
Author | SHA1 | Date |
---|---|---|
Jaklyy | 93dd0f47bd | |
Jaklyy | 4940f940c7 | |
Jaklyy | caa009ca03 | |
Jaklyy | 65e2f64695 | |
Jaklyy | 22f1b4d90c |
16
src/ARM.cpp
16
src/ARM.cpp
|
@ -1447,6 +1447,22 @@ void ARMv5::ForceInterlock_2()
|
|||
NDS.ARM9Timestamp = TimestampMemory + ILForceDelay;
|
||||
}
|
||||
|
||||
void ARMv5::QueueFunction(void (ARMv5::*QueueEntry)(void))
|
||||
{
|
||||
if ((NDS.ARM9Timestamp >= NDS.ARM9Target) || (MRTrack.Type != MainRAMType::Null))
|
||||
FuncQueue[FuncQueueFill++] = QueueEntry;
|
||||
else
|
||||
(this->*QueueEntry)();
|
||||
}
|
||||
|
||||
void ARMv4::QueueFunction(void (ARMv4::*QueueEntry)(void))
|
||||
{
|
||||
if ((NDS.ARM7Timestamp >= NDS.ARM7Target) || (MRTrack.Type != MainRAMType::Null))
|
||||
FuncQueue[FuncQueueFill++] = QueueEntry;
|
||||
else
|
||||
(this->*QueueEntry)();
|
||||
}
|
||||
|
||||
void ARMv4::CodeRead16(u32 addr)
|
||||
{
|
||||
if ((addr >> 24) == 0x02)
|
||||
|
|
38
src/ARM.h
38
src/ARM.h
|
@ -723,14 +723,8 @@ public:
|
|||
* @return Value of the cp15 register
|
||||
*/
|
||||
u32 CP15Read(const u32 id) const;
|
||||
|
||||
inline void QueueFunction(void (ARMv5::*QueueEntry)(void))
|
||||
{
|
||||
if (MRTrack.Type != MainRAMType::Null)
|
||||
FuncQueue[FuncQueueFill++] = QueueEntry;
|
||||
else
|
||||
(this->*QueueEntry)();
|
||||
}
|
||||
|
||||
void QueueFunction(void (ARMv5::*QueueEntry)(void));
|
||||
|
||||
// Queue Functions
|
||||
void StartExecARM();
|
||||
|
@ -744,27 +738,47 @@ public:
|
|||
void JumpTo_3C();
|
||||
void JumpTo_4();
|
||||
void CodeRead32_2();
|
||||
void CodeRead32_3();
|
||||
void CodeRead32_4();
|
||||
void ICacheLookup_2();
|
||||
void DAbortHandle();
|
||||
void DCacheFin8();
|
||||
void DRead8_2();
|
||||
void DRead8_3();
|
||||
void DRead8_4();
|
||||
void DRead8_5();
|
||||
void DCacheFin16();
|
||||
void DRead16_2();
|
||||
void DRead16_3();
|
||||
void DRead16_4();
|
||||
void DRead16_5();
|
||||
void DCacheFin32();
|
||||
void DRead32_2();
|
||||
void DRead32_3();
|
||||
void DRead32_4();
|
||||
void DRead32_5();
|
||||
void DRead32S_2();
|
||||
void DRead32S_3();
|
||||
void DRead32S_4();
|
||||
void DRead32S_5A();
|
||||
void DRead32S_5B();
|
||||
void DWrite8_2();
|
||||
void DWrite8_3();
|
||||
void DWrite8_4();
|
||||
void DWrite8_5();
|
||||
void DWrite16_2();
|
||||
void DWrite16_3();
|
||||
void DWrite16_4();
|
||||
void DWrite16_5();
|
||||
void DWrite32_2();
|
||||
void DWrite32_3();
|
||||
void DWrite32_4();
|
||||
void DWrite32_5();
|
||||
void DWrite32S_2();
|
||||
void DWrite32S_3();
|
||||
void DWrite32S_4();
|
||||
void DWrite32S_5A();
|
||||
void DWrite32S_5B();
|
||||
void WBCheck_2();
|
||||
void ICachePrefetch_2();
|
||||
void DCacheLookup_2();
|
||||
|
@ -933,13 +947,7 @@ public:
|
|||
void AddCycles_CDI() override;
|
||||
void AddCycles_CD() override;
|
||||
|
||||
inline void QueueFunction(void (ARMv4::*QueueEntry)(void))
|
||||
{
|
||||
if (MRTrack.Type != MainRAMType::Null)
|
||||
FuncQueue[FuncQueueFill++] = QueueEntry;
|
||||
else
|
||||
(this->*QueueEntry)();
|
||||
}
|
||||
void QueueFunction(void (ARMv4::*QueueEntry)(void));
|
||||
|
||||
void StartExecARM();
|
||||
void StartExecTHUMB();
|
||||
|
|
468
src/CP15.cpp
468
src/CP15.cpp
|
@ -2213,7 +2213,13 @@ void ARMv5::CodeRead32(u32 addr)
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
FetchAddr[16] = addr;
|
||||
QueueFunction(&ARMv5::CodeRead32_2);
|
||||
}
|
||||
|
||||
void ARMv5::CodeRead32_2()
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with dcache streaming by 6 cycles
|
||||
if (DCacheStreamPtr < 7)
|
||||
|
@ -2222,47 +2228,56 @@ void ARMv5::CodeRead32(u32 addr)
|
|||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
|
||||
if (PU_Map[addr>>12] & 0x30)
|
||||
if (PU_Map[FetchAddr[16]>>12] & 0x30)
|
||||
WriteBufferDrain();
|
||||
else
|
||||
WriteBufferCheck<3>();
|
||||
|
||||
FetchAddr[16] = addr;
|
||||
QueueFunction(&ARMv5::CodeRead32_2);
|
||||
QueueFunction(&ARMv5::CodeRead32_3);
|
||||
}
|
||||
|
||||
void ARMv5::CodeRead32_2()
|
||||
void ARMv5::CodeRead32_3()
|
||||
{
|
||||
u32 addr = FetchAddr[16];
|
||||
|
||||
NDS.ARM9Timestamp = NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
u8 cycles = MemTimings[addr >> 14][1];
|
||||
|
||||
if ((addr >> 24) == 0x02)
|
||||
{
|
||||
FetchAddr[16] = addr;
|
||||
MRTrack.Type = MainRAMType::Fetch;
|
||||
MRTrack.Var = MRCodeFetch | MR32;
|
||||
|
||||
QueueFunction(DelayedQueue);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((NDS.ARM9Timestamp <= WBReleaseTS) && (NDS.ARM9Regions[addr>>14] == WBLastRegion)) // check write buffer
|
||||
|| (Store && (NDS.ARM9Regions[addr>>14] == DataRegion))) //check the actual store
|
||||
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
|
||||
|
||||
NDS.ARM9Timestamp += cycles;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
RetVal = BusRead32(addr);
|
||||
|
||||
QueueFunction(&ARMv5::CodeRead32_4);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::CodeRead32_4()
|
||||
{
|
||||
u32 addr = FetchAddr[16];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
u8 cycles = MemTimings[addr >> 14][1];
|
||||
|
||||
NDS.ARM9Timestamp += cycles;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
Store = false;
|
||||
DataRegion = Mem9_Null;
|
||||
|
||||
RetVal = BusRead32(addr);
|
||||
QueueFunction(DelayedQueue);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2346,6 +2361,15 @@ void ARMv5::DRead8_2()
|
|||
}
|
||||
#endif
|
||||
|
||||
QueueFunction(&ARMv5::DRead8_3);
|
||||
}
|
||||
|
||||
void ARMv5::DRead8_3()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: does dcache trigger this?
|
||||
|
@ -2360,10 +2384,10 @@ void ARMv5::DRead8_2()
|
|||
else
|
||||
WriteBufferCheck<1>();
|
||||
|
||||
QueueFunction(&ARMv5::DRead8_3);
|
||||
QueueFunction(&ARMv5::DRead8_4);
|
||||
}
|
||||
|
||||
void ARMv5::DRead8_3()
|
||||
void ARMv5::DRead8_4()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
|
@ -2379,18 +2403,31 @@ void ARMv5::DRead8_3()
|
|||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
|
||||
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
*val = BusRead8(addr);
|
||||
|
||||
QueueFunction(&ARMv5::DRead8_5);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DRead8_5()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
*val = BusRead8(addr);
|
||||
}
|
||||
|
||||
void ARMv5::DCacheFin16()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
|
@ -2461,6 +2498,15 @@ void ARMv5::DRead16_2()
|
|||
}
|
||||
#endif
|
||||
|
||||
QueueFunction(&ARMv5::DRead16_3);
|
||||
}
|
||||
|
||||
void ARMv5::DRead16_3()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: does cache trigger this?
|
||||
|
@ -2475,10 +2521,10 @@ void ARMv5::DRead16_2()
|
|||
else
|
||||
WriteBufferCheck<1>();
|
||||
|
||||
QueueFunction(&ARMv5::DRead16_3);
|
||||
QueueFunction(&ARMv5::DRead16_4);
|
||||
}
|
||||
|
||||
void ARMv5::DRead16_3()
|
||||
void ARMv5::DRead16_4()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
|
@ -2494,18 +2540,31 @@ void ARMv5::DRead16_3()
|
|||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
|
||||
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
*val = BusRead16(addr);
|
||||
|
||||
QueueFunction(&ARMv5::DRead16_5);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DRead16_5()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
*val = BusRead16(addr);
|
||||
}
|
||||
|
||||
void ARMv5::DCacheFin32()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
|
@ -2576,7 +2635,16 @@ void ARMv5::DRead32_2()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
QueueFunction(&ARMv5::DRead32_3);
|
||||
}
|
||||
|
||||
void ARMv5::DRead32_3()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: does cache trigger this?
|
||||
|
@ -2591,10 +2659,10 @@ void ARMv5::DRead32_2()
|
|||
else
|
||||
WriteBufferCheck<1>();
|
||||
|
||||
QueueFunction(&ARMv5::DRead32_3);
|
||||
QueueFunction(&ARMv5::DRead32_4);
|
||||
}
|
||||
|
||||
void ARMv5::DRead32_3()
|
||||
void ARMv5::DRead32_4()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
|
@ -2607,19 +2675,34 @@ void ARMv5::DRead32_3()
|
|||
MRTrack.Type = MainRAMType::Fetch;
|
||||
MRTrack.Var = MR32;
|
||||
MRTrack.Progress = reg;
|
||||
|
||||
LDRRegs &= ~1<<reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][1];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
|
||||
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
*val = BusRead32(addr);
|
||||
|
||||
QueueFunction(&ARMv5::DRead32_5);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DRead32_5()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][1];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
*val = BusRead32(addr);
|
||||
LDRRegs &= ~1<<reg;
|
||||
}
|
||||
|
||||
|
@ -2678,7 +2761,16 @@ void ARMv5::DRead32S_2()
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
QueueFunction(&ARMv5::DRead32S_3);
|
||||
}
|
||||
|
||||
void ARMv5::DRead32S_3()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: does cache trigger this?
|
||||
|
@ -2692,11 +2784,11 @@ void ARMv5::DRead32S_2()
|
|||
WriteBufferDrain();
|
||||
else
|
||||
WriteBufferCheck<1>();
|
||||
|
||||
QueueFunction(&ARMv5::DRead32S_3);
|
||||
|
||||
QueueFunction(&ARMv5::DRead32S_4);
|
||||
}
|
||||
|
||||
void ARMv5::DRead32S_3()
|
||||
void ARMv5::DRead32S_4()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
|
@ -2710,18 +2802,16 @@ void ARMv5::DRead32S_3()
|
|||
MRTrack.Type = MainRAMType::Fetch;
|
||||
MRTrack.Var = MR32 | MRSequential;
|
||||
MRTrack.Progress = reg;
|
||||
|
||||
LDRRegs &= ~1<<reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr>>14][2];
|
||||
DataCycles = MemTimings[addr>>14][2];
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
|
||||
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
*val = BusRead32(addr);
|
||||
|
||||
QueueFunction(&ARMv5::DRead32S_5A);
|
||||
}
|
||||
}
|
||||
else // ns
|
||||
|
@ -2733,20 +2823,53 @@ void ARMv5::DRead32S_3()
|
|||
MRTrack.Type = MainRAMType::Fetch;
|
||||
MRTrack.Var = MR32;
|
||||
MRTrack.Progress = reg;
|
||||
|
||||
LDRRegs &= ~1<<reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr>>14][1];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
if ((NDS.ARM9Timestamp <= WBReleaseTS) && (DataRegion == WBLastRegion)) // check write buffer
|
||||
NDS.ARM9Timestamp += 1<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
*val = BusRead32(addr);
|
||||
|
||||
QueueFunction(&ARMv5::DRead32S_5B);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DRead32S_5A()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr>>14][2];
|
||||
DataCycles = MemTimings[addr>>14][2];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
*val = BusRead32(addr);
|
||||
LDRRegs &= ~1<<reg;
|
||||
}
|
||||
|
||||
void ARMv5::DRead32S_5B()
|
||||
{
|
||||
u8 reg = __builtin_ctz(LDRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 dummy; u32* val = (LDRFailedRegs & (1<<reg)) ? &dummy : &R[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr>>14][1];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp - (3<<NDS.ARM9ClockShift) + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
*val = BusRead32(addr);
|
||||
LDRRegs &= ~1<<reg;
|
||||
}
|
||||
|
||||
|
@ -2815,16 +2938,6 @@ void ARMv5::DWrite8_2()
|
|||
|
||||
if (!(PU_Map[addr>>12] & (0x30)))
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: do buffered writes trigger this?
|
||||
if (ICacheStreamPtr < 7)
|
||||
{
|
||||
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
|
||||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
|
||||
WriteBufferCheck<2>();
|
||||
QueueFunction(&ARMv5::DWrite8_3);
|
||||
}
|
||||
else
|
||||
|
@ -2837,6 +2950,21 @@ void ARMv5::DWrite8_2()
|
|||
}
|
||||
|
||||
void ARMv5::DWrite8_3()
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: do buffered writes trigger this?
|
||||
if (ICacheStreamPtr < 7)
|
||||
{
|
||||
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
|
||||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
|
||||
WriteBufferCheck<2>();
|
||||
QueueFunction(&ARMv5::DWrite8_4);
|
||||
}
|
||||
|
||||
void ARMv5::DWrite8_4()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
|
@ -2852,16 +2980,28 @@ void ARMv5::DWrite8_3()
|
|||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
BusWrite8(addr, val);
|
||||
QueueFunction(&ARMv5::DWrite8_5);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DWrite8_5()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u8 val = STRVal[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
BusWrite8(addr, val);
|
||||
}
|
||||
|
||||
bool ARMv5::DataWrite16(u32 addr, u16 val, u8 reg)
|
||||
{
|
||||
// Data Aborts
|
||||
|
@ -2929,16 +3069,6 @@ void ARMv5::DWrite16_2()
|
|||
|
||||
if (!(PU_Map[addr>>12] & 0x30))
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: do buffered writes trigger this?
|
||||
if (ICacheStreamPtr < 7)
|
||||
{
|
||||
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
|
||||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
|
||||
WriteBufferCheck<2>();
|
||||
QueueFunction(&ARMv5::DWrite16_3);
|
||||
}
|
||||
else
|
||||
|
@ -2951,6 +3081,21 @@ void ARMv5::DWrite16_2()
|
|||
}
|
||||
|
||||
void ARMv5::DWrite16_3()
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: do buffered writes trigger this?
|
||||
if (ICacheStreamPtr < 7)
|
||||
{
|
||||
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
|
||||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
|
||||
WriteBufferCheck<2>();
|
||||
QueueFunction(&ARMv5::DWrite16_4);
|
||||
}
|
||||
|
||||
void ARMv5::DWrite16_4()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
|
@ -2966,16 +3111,28 @@ void ARMv5::DWrite16_3()
|
|||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
BusWrite16(addr, val);
|
||||
QueueFunction(&ARMv5::DWrite16_5);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DWrite16_5()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u16 val = STRVal[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][0];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
BusWrite16(addr, val);
|
||||
}
|
||||
|
||||
bool ARMv5::DataWrite32(u32 addr, u32 val, u8 reg)
|
||||
{
|
||||
// Data Aborts
|
||||
|
@ -3048,16 +3205,6 @@ void ARMv5::DWrite32_2()
|
|||
|
||||
if (!(PU_Map[addr>>12] & 0x30))
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: do buffered writes trigger this?
|
||||
if (ICacheStreamPtr < 7)
|
||||
{
|
||||
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
|
||||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
|
||||
WriteBufferCheck<2>();
|
||||
QueueFunction(&ARMv5::DWrite32_3);
|
||||
}
|
||||
else
|
||||
|
@ -3071,6 +3218,21 @@ void ARMv5::DWrite32_2()
|
|||
}
|
||||
|
||||
void ARMv5::DWrite32_3()
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: do buffered writes trigger this?
|
||||
if (ICacheStreamPtr < 7)
|
||||
{
|
||||
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
|
||||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
|
||||
WriteBufferCheck<2>();
|
||||
QueueFunction(&ARMv5::DWrite32_4);
|
||||
}
|
||||
|
||||
void ARMv5::DWrite32_4()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
|
@ -3083,17 +3245,31 @@ void ARMv5::DWrite32_3()
|
|||
MRTrack.Type = MainRAMType::Fetch;
|
||||
MRTrack.Var = MRWrite | MR32;
|
||||
MRTrack.Progress = reg;
|
||||
|
||||
STRRegs &= ~1<<reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][1];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
BusWrite32(addr, val);
|
||||
QueueFunction(&ARMv5::DWrite32_5);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DWrite32_5()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 val = STRVal[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr >> 14][1];
|
||||
DataCycles = 3<<NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
BusWrite32(addr, val);
|
||||
STRRegs &= ~1<<reg;
|
||||
}
|
||||
|
||||
|
@ -3162,15 +3338,6 @@ void ARMv5::DWrite32S_2()
|
|||
|
||||
if (!(PU_Map[addr>>12] & 0x30)) // non-bufferable
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: do buffered writes trigger this?
|
||||
if (ICacheStreamPtr < 7)
|
||||
{
|
||||
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
|
||||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
WriteBufferCheck<2>();
|
||||
QueueFunction(&ARMv5::DWrite32S_3);
|
||||
}
|
||||
else
|
||||
|
@ -3181,6 +3348,20 @@ void ARMv5::DWrite32S_2()
|
|||
}
|
||||
|
||||
void ARMv5::DWrite32S_3()
|
||||
{
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
// bus reads can only overlap with icache streaming by 6 cycles
|
||||
// checkme: do buffered writes trigger this?
|
||||
if (ICacheStreamPtr < 7)
|
||||
{
|
||||
u64 time = ICacheStreamTimes[6] - 6; // checkme: minus 6?
|
||||
if (NDS.ARM9Timestamp < time) NDS.ARM9Timestamp = time;
|
||||
}
|
||||
WriteBufferCheck<2>();
|
||||
QueueFunction(&ARMv5::DWrite32S_4);
|
||||
}
|
||||
|
||||
void ARMv5::DWrite32S_4()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
|
@ -3194,15 +3375,12 @@ void ARMv5::DWrite32S_3()
|
|||
MRTrack.Type = MainRAMType::Fetch;
|
||||
MRTrack.Var = MRWrite | MR32 | MRSequential;
|
||||
MRTrack.Progress = reg;
|
||||
|
||||
STRRegs &= ~1<<reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr>>14][2];
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
BusWrite32(addr, val);
|
||||
QueueFunction(&ARMv5::DWrite32S_5A);
|
||||
}
|
||||
}
|
||||
else // ns
|
||||
|
@ -3214,18 +3392,50 @@ void ARMv5::DWrite32S_3()
|
|||
MRTrack.Type = MainRAMType::Fetch;
|
||||
MRTrack.Var = MRWrite | MR32;
|
||||
MRTrack.Progress = reg;
|
||||
|
||||
STRRegs &= ~1<<reg;
|
||||
}
|
||||
else
|
||||
{
|
||||
NDS.ARM9Timestamp += MemTimings[addr>>14][1];
|
||||
DataCycles = 3 << NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
BusWrite32(addr, val);
|
||||
QueueFunction(&ARMv5::DWrite32S_5B);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv5::DWrite32S_5A()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 val = STRVal[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr>>14][2];
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
BusWrite32(addr, val);
|
||||
STRRegs &= ~1<<reg;
|
||||
}
|
||||
|
||||
void ARMv5::DWrite32S_5B()
|
||||
{
|
||||
u8 reg = __builtin_ctz(STRRegs);
|
||||
u32 addr = FetchAddr[reg];
|
||||
u32 val = STRVal[reg];
|
||||
|
||||
if (NDS.ARM9Timestamp < NDS.DMA9Timestamp) NDS.ARM9Timestamp = NDS.DMA9Timestamp;
|
||||
|
||||
NDS.ARM9Timestamp += MemTimings[addr>>14][1];
|
||||
DataCycles = 3 << NDS.ARM9ClockShift;
|
||||
DataRegion = NDS.ARM9Regions[addr>>14];
|
||||
|
||||
if (WBTimestamp < ((NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1)))
|
||||
WBTimestamp = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
BusWrite32(addr, val);
|
||||
STRRegs &= ~1<<reg;
|
||||
}
|
||||
|
||||
|
|
21
src/DMA.cpp
21
src/DMA.cpp
|
@ -146,7 +146,10 @@ void DMA::WriteCnt(u32 val)
|
|||
StartMode = ((Cnt >> 28) & 0x3) | 0x10;
|
||||
|
||||
if ((StartMode & 0x7) == 0)
|
||||
Start();
|
||||
{
|
||||
NDS.DMAsQueued[NDS.DMAQueuePtr++] = (CPU*4)+Num;
|
||||
if (!(NDS.SchedListMask & (1<<Event_DMA))) NDS.ScheduleEvent(Event_DMA, false, 1, 0, 0);
|
||||
}
|
||||
else if (StartMode == 0x07)
|
||||
NDS.GPU.GPU3D.CheckFIFODMA();
|
||||
|
||||
|
@ -212,6 +215,18 @@ void DMA::Start()
|
|||
InProgress = true;
|
||||
NDS.StopCPU(CPU, 1<<Num);
|
||||
|
||||
if (CPU == 0)
|
||||
{
|
||||
u64 ts;
|
||||
/*if (StartMode == 0x00)
|
||||
{
|
||||
ts = (NDS.ARM9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
}
|
||||
else*/ ts = NDS.SysTimestamp << NDS.ARM9ClockShift;
|
||||
|
||||
if (NDS.DMA9Timestamp < ts) NDS.DMA9Timestamp = ts;
|
||||
}
|
||||
|
||||
if (Num == 0) NDS.DMAs[(CPU*4)+1].ResetBurst();
|
||||
if (Num <= 1) NDS.DMAs[(CPU*4)+2].ResetBurst();
|
||||
if (Num <= 2) NDS.DMAs[(CPU*4)+3].ResetBurst();
|
||||
|
@ -587,8 +602,8 @@ u32 DMA::UnitTimings7_32(int burststart)
|
|||
|
||||
void DMA::Run9()
|
||||
{
|
||||
NDS.DMA9Timestamp = std::max(NDS.DMA9Timestamp, NDS.ARM9Timestamp);
|
||||
NDS.DMA9Timestamp = (NDS.DMA9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
//NDS.DMA9Timestamp = std::max(NDS.DMA9Timestamp, NDS.SysTimestamp << NDS.ARM9ClockShift);
|
||||
//NDS.DMA9Timestamp = (NDS.DMA9Timestamp + ((1<<NDS.ARM9ClockShift)-1)) & ~((1<<NDS.ARM9ClockShift)-1);
|
||||
|
||||
if (NDS.DMA9Timestamp-1 >= NDS.ARM9Target) return;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ public:
|
|||
|
||||
void ResetBurst()
|
||||
{
|
||||
if (Running > 0) Running = (CPU ? 2 : 3);
|
||||
if (Running > 0) Running = 3;
|
||||
}
|
||||
|
||||
u32 SrcAddr {};
|
||||
|
|
147
src/NDS.cpp
147
src/NDS.cpp
|
@ -124,6 +124,7 @@ NDS::NDS(NDSArgs&& args, int type, void* userdata) noexcept :
|
|||
{
|
||||
RegisterEventFuncs(Event_Div, this, {MakeEventThunk(NDS, DivDone)});
|
||||
RegisterEventFuncs(Event_Sqrt, this, {MakeEventThunk(NDS, SqrtDone)});
|
||||
RegisterEventFuncs(Event_DMA, this, {MakeEventThunk(NDS, QueueDMAs)});
|
||||
|
||||
MainRAM = JIT.Memory.GetMainRAM();
|
||||
SharedWRAM = JIT.Memory.GetSharedWRAM();
|
||||
|
@ -134,6 +135,7 @@ NDS::~NDS() noexcept
|
|||
{
|
||||
UnregisterEventFuncs(Event_Div);
|
||||
UnregisterEventFuncs(Event_Sqrt);
|
||||
UnregisterEventFuncs(Event_DMA);
|
||||
// The destructor for each component is automatically called by the compiler
|
||||
}
|
||||
|
||||
|
@ -548,6 +550,9 @@ void NDS::Reset()
|
|||
KeyCnt[1] = 0;
|
||||
RCnt = 0;
|
||||
|
||||
memset(DMAsQueued, 0, sizeof(DMAsQueued));
|
||||
DMAQueuePtr = 0;
|
||||
|
||||
GPU.Reset();
|
||||
NDSCartSlot.Reset();
|
||||
GBACartSlot.Reset();
|
||||
|
@ -840,6 +845,21 @@ void NDS::RunSystem(u64 timestamp)
|
|||
}
|
||||
}
|
||||
|
||||
void NDS::RunEventManual(u32 id)
|
||||
{
|
||||
if (SchedListMask & (1<<id))
|
||||
{
|
||||
u64 curts = CurCPU ? ARM7Timestamp : (std::max(ARM9Timestamp, DMA9Timestamp) >> ARM9ClockShift);
|
||||
SchedEvent& evt = SchedList[id];
|
||||
|
||||
if (evt.Timestamp <= curts)
|
||||
{
|
||||
evt.Funcs[evt.FuncID](evt.That, evt.Param);
|
||||
SchedListMask &= ~(1<<id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u64 NDS::NextTargetSleep()
|
||||
{
|
||||
u64 minEvent = UINT64_MAX;
|
||||
|
@ -1645,13 +1665,19 @@ bool NDS::MainRAMHandle()
|
|||
{
|
||||
if (A9ContentionTS < ARM7Timestamp)
|
||||
{
|
||||
if (ARM9.MRTrack.Type == MainRAMType::Null || (CPUStop & CPUStop_GXStall)) return 0;
|
||||
MainRAMHandleARM9();
|
||||
if (ARM9.MRTrack.Type == MainRAMType::Null) return 0;
|
||||
else if (CPUStop & CPUStop_GXStall)
|
||||
{
|
||||
// gx stalls can occur during this, and if not handled properly will cause issues
|
||||
s32 cycles = GPU.GPU3D.CyclesToRunFor();
|
||||
A9ContentionTS = std::min(ARM9Target, A9ContentionTS+cycles);
|
||||
}
|
||||
else MainRAMHandleARM9();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ARM7.MRTrack.Type == MainRAMType::Null) return 1;
|
||||
MainRAMHandleARM7();
|
||||
else MainRAMHandleARM7();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1661,13 +1687,19 @@ bool NDS::MainRAMHandle()
|
|||
{
|
||||
if (A9ContentionTS <= ARM7Timestamp)
|
||||
{
|
||||
if (ARM9.MRTrack.Type == MainRAMType::Null || (CPUStop & CPUStop_GXStall)) return 0;
|
||||
MainRAMHandleARM9();
|
||||
if (ARM9.MRTrack.Type == MainRAMType::Null) return 0;
|
||||
else if (CPUStop & CPUStop_GXStall)
|
||||
{
|
||||
// gx stalls can occur during this, and if not handled properly will cause issues
|
||||
s32 cycles = GPU.GPU3D.CyclesToRunFor();
|
||||
A9ContentionTS = std::min(ARM9Target, A9ContentionTS+cycles);
|
||||
}
|
||||
else MainRAMHandleARM9();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ARM7.MRTrack.Type == MainRAMType::Null) return 1;
|
||||
MainRAMHandleARM7();
|
||||
else MainRAMHandleARM7();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1740,57 +1772,55 @@ u32 NDS::RunFrame()
|
|||
u64 target = NextTarget();
|
||||
|
||||
ARM9Target = target << ARM9ClockShift;
|
||||
//ARM7Target = target;
|
||||
ARM7Target = target;
|
||||
|
||||
while (std::max(std::max(ARM9Timestamp, DMA9Timestamp), A9ContentionTS << ARM9ClockShift) < ARM9Target)
|
||||
while (((std::max(std::max(ARM9Timestamp, DMA9Timestamp), A9ContentionTS << ARM9ClockShift) < ARM9Target) && (ARM9.MRTrack.Type == MainRAMType::Null))
|
||||
|| (ARM7Timestamp < ARM7Target) && (ARM7.MRTrack.Type == MainRAMType::Null))
|
||||
{
|
||||
CurCPU = 0;
|
||||
RunTimers(0);
|
||||
GPU.GPU3D.Run();
|
||||
while (std::max(std::max(ARM9Timestamp, DMA9Timestamp), A9ContentionTS << ARM9ClockShift) < ARM9Target)
|
||||
{
|
||||
CurCPU = 0;
|
||||
RunTimers(0);
|
||||
GPU.GPU3D.Run();
|
||||
|
||||
if (CPUStop & CPUStop_GXStall)
|
||||
{
|
||||
// GXFIFO stall
|
||||
s32 cycles = GPU.GPU3D.CyclesToRunFor();
|
||||
DMA9Timestamp = std::min(ARM9Target, std::max(ARM9Timestamp, DMA9Timestamp)+(cycles<<ARM9ClockShift));
|
||||
}
|
||||
else if (ARM9.MRTrack.Type == MainRAMType::Null)
|
||||
{
|
||||
if (CPUStop & CPUStop_DMA9)
|
||||
if (CPUStop & CPUStop_GXStall)
|
||||
{
|
||||
DMAs[0].Run();
|
||||
if (!(CPUStop & CPUStop_GXStall) && (ARM9.MRTrack.Type == MainRAMType::Null)) DMAs[1].Run();
|
||||
if (!(CPUStop & CPUStop_GXStall) && (ARM9.MRTrack.Type == MainRAMType::Null)) DMAs[2].Run();
|
||||
if (!(CPUStop & CPUStop_GXStall) && (ARM9.MRTrack.Type == MainRAMType::Null)) DMAs[3].Run();
|
||||
if (ConsoleType == 1)
|
||||
// GXFIFO stall
|
||||
s32 cycles = GPU.GPU3D.CyclesToRunFor();
|
||||
DMA9Timestamp = std::min(ARM9Target, std::max(ARM9Timestamp, DMA9Timestamp)+(cycles<<ARM9ClockShift));
|
||||
}
|
||||
else if (ARM9.MRTrack.Type == MainRAMType::Null)
|
||||
{
|
||||
if (CPUStop & CPUStop_DMA9)
|
||||
{
|
||||
auto& dsi = dynamic_cast<melonDS::DSi&>(*this);
|
||||
dsi.RunNDMAs(0);
|
||||
DMAs[0].Run();
|
||||
if (!(CPUStop & CPUStop_GXStall) && (ARM9.MRTrack.Type == MainRAMType::Null)) DMAs[1].Run();
|
||||
if (!(CPUStop & CPUStop_GXStall) && (ARM9.MRTrack.Type == MainRAMType::Null)) DMAs[2].Run();
|
||||
if (!(CPUStop & CPUStop_GXStall) && (ARM9.MRTrack.Type == MainRAMType::Null)) DMAs[3].Run();
|
||||
if (ConsoleType == 1)
|
||||
{
|
||||
auto& dsi = dynamic_cast<melonDS::DSi&>(*this);
|
||||
dsi.RunNDMAs(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (ARM9.abt) ARM9Timestamp = ARM9Target;
|
||||
ARM9.Execute<cpuMode>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (ARM9.abt) ARM9Timestamp = ARM9Target;
|
||||
ARM9.Execute<cpuMode>();
|
||||
}
|
||||
|
||||
//printf("MAIN LOOP: 9 %lli %lli %08X %08llX %i 7 %lli %lli %08X %08llX %i\n", ARM9Timestamp, ARM9Target, ARM9.PC, ARM9.CurInstr, (u8)ARM9.MRTrack.Type, ARM7Timestamp, ARM7Target, ARM7.R[15], ARM7.CurInstr, (u8)ARM7.MRTrack.Type);
|
||||
|
||||
RunTimers(0);
|
||||
GPU.GPU3D.Run();
|
||||
|
||||
if (MainRAMHandle()) break;
|
||||
}
|
||||
|
||||
//printf("MAIN LOOP: 9 %lli %08X %08llX %i 7 %lli %08X %08llX %i %i %08X\n", ARM9Timestamp>>ARM9ClockShift, ARM9.PC, ARM9.CurInstr, (u8)ARM9.MRTrack.Type, ARM7Timestamp, ARM7.R[15], ARM7.CurInstr, (u8)ARM7.MRTrack.Type, IME[1], IE[1]);
|
||||
|
||||
NDSCartSlot.ROMPrepareData();
|
||||
RunTimers(0);
|
||||
GPU.GPU3D.Run();
|
||||
|
||||
//if (MainRAMHandle()) break;
|
||||
MainRAMHandle();
|
||||
|
||||
target = std::max(std::max(ARM9Timestamp, DMA9Timestamp) >> ARM9ClockShift, A9ContentionTS);
|
||||
if (target == ARM7Timestamp) target++;
|
||||
|
||||
while (ARM7Timestamp < target)
|
||||
while (ARM7Timestamp < ARM7Target)
|
||||
{
|
||||
ARM7Target = target;
|
||||
//printf("A7 LOOP: %lli %lli\n", ARM9Timestamp>>ARM9ClockShift, ARM7Timestamp);
|
||||
//printf("A7 LOOP: 9 %lli %lli %08X %08llX %i 7 %lli %lli %08X %08llX %i\n", ARM9Timestamp, ARM9Target, ARM9.PC, ARM9.CurInstr, (u8)ARM9.MRTrack.Type, ARM7Timestamp, ARM7Target, ARM7.R[15], ARM7.CurInstr, (u8)ARM7.MRTrack.Type);
|
||||
CurCPU = 1;
|
||||
RunTimers(1);
|
||||
|
||||
|
@ -1816,13 +1846,12 @@ u32 NDS::RunFrame()
|
|||
}
|
||||
|
||||
RunTimers(1);
|
||||
NDSCartSlot.ROMPrepareData();
|
||||
|
||||
if (!MainRAMHandle()) break;
|
||||
}
|
||||
}
|
||||
|
||||
RunSystem(target);
|
||||
|
||||
RunSystem(ARM7Target);
|
||||
|
||||
if (CPUStop & CPUStop_Sleep)
|
||||
{
|
||||
|
@ -1844,7 +1873,6 @@ u32 NDS::RunFrame()
|
|||
SPU.TransferOutput();
|
||||
break;
|
||||
}
|
||||
//printf("MAIN LOOP: 9 %lli %08X %08llX %i 7 %lli %08X %08llX %i %i %08X\n", ARM9Timestamp>>ARM9ClockShift, ARM9.PC, ARM9.CurInstr, (u8)ARM9.MRTrack.Type, ARM7Timestamp, ARM7.R[15], ARM7.CurInstr, (u8)ARM7.MRTrack.Type, IME[1], IE[1]);
|
||||
|
||||
// In the context of TASes, frame count is traditionally the primary measure of emulated time,
|
||||
// so it needs to be tracked even if NDS is powered off.
|
||||
|
@ -1878,13 +1906,11 @@ u32 NDS::RunFrame()
|
|||
|
||||
void NDS::Reschedule(u64 target)
|
||||
{
|
||||
if (CurCPU == 0)
|
||||
if (target < ARM7Target)
|
||||
{
|
||||
if (target < (ARM9Target >> ARM9ClockShift))
|
||||
ARM9Target = (target << ARM9ClockShift);
|
||||
}
|
||||
else if (target < ARM7Target)
|
||||
ARM7Target = target;
|
||||
ARM9Target = (target << ARM9ClockShift);
|
||||
}
|
||||
}
|
||||
|
||||
void NDS::RegisterEventFuncs(u32 id, void* that, const std::initializer_list<EventFunc>& funcs)
|
||||
|
@ -2529,6 +2555,15 @@ void NDS::StopDMAs(u32 cpu, u32 mode)
|
|||
DMAs[cpu+3].StopIfNeeded(mode);
|
||||
}
|
||||
|
||||
void NDS::QueueDMAs(u32 param)
|
||||
{
|
||||
DMAs[DMAsQueued[0]].Start();
|
||||
for(int i = 0; i < 7; i++) DMAsQueued[i] = DMAsQueued[i+1];
|
||||
DMAQueuePtr--;
|
||||
|
||||
if (DMAQueuePtr != 0) ScheduleEvent(Event_DMA, false, 1, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void NDS::DivDone(u32 param)
|
||||
|
|
11
src/NDS.h
11
src/NDS.h
|
@ -64,6 +64,7 @@ enum
|
|||
Event_SPITransfer,
|
||||
Event_Div,
|
||||
Event_Sqrt,
|
||||
Event_DMA,
|
||||
|
||||
// DSi
|
||||
Event_DSi_SDMMCTransfer,
|
||||
|
@ -243,7 +244,8 @@ public: // TODO: Encapsulate the rest of these members
|
|||
|
||||
int ConsoleType;
|
||||
int CurCPU;
|
||||
|
||||
|
||||
u32 SchedListMask;
|
||||
SchedEvent SchedList[Event_MAX] {};
|
||||
u8 ARM9MemTimings[0x40000][8];
|
||||
u32 ARM9Regions[0x40000];
|
||||
|
@ -259,6 +261,7 @@ public: // TODO: Encapsulate the rest of these members
|
|||
u64 ARM7Timestamp, ARM7Target;
|
||||
u64 MainRAMTimestamp, MainRAMBurstStart;
|
||||
u64 A9ContentionTS; bool ConTSLock;
|
||||
u64 SysTimestamp;
|
||||
u32 ARM9ClockShift;
|
||||
|
||||
u32 IME[2];
|
||||
|
@ -277,6 +280,8 @@ public: // TODO: Encapsulate the rest of these members
|
|||
alignas(u32) u8 ROMSeed1[2*8];
|
||||
|
||||
u32 DMAReadHold[2];
|
||||
u8 DMAsQueued[8];
|
||||
u8 DMAQueuePtr;
|
||||
bool MainRAMBork; // if a main ram read burst starts in the last 6 bytes of a 32 byte block, and then crosses the 32 byte boundary, the burst forcibly restarts
|
||||
bool MainRAMLastAccess; // 0 == ARM9 | 1 == ARM7
|
||||
bool DMALastWasMainRAM;
|
||||
|
@ -427,6 +432,7 @@ public: // TODO: Encapsulate the rest of these members
|
|||
void UnregisterEventFuncs(u32 id);
|
||||
void ScheduleEvent(u32 id, bool periodic, s32 delay, u32 funcid, u32 param);
|
||||
void CancelEvent(u32 id);
|
||||
void RunEventManual(u32 id);
|
||||
|
||||
void debug(u32 p);
|
||||
|
||||
|
@ -506,8 +512,6 @@ public: // TODO: Encapsulate the rest of these members
|
|||
|
||||
private:
|
||||
void InitTimings();
|
||||
u32 SchedListMask;
|
||||
u64 SysTimestamp;
|
||||
u8 WRAMCnt;
|
||||
u8 PostFlag9;
|
||||
u8 PostFlag7;
|
||||
|
@ -542,6 +546,7 @@ private:
|
|||
void HandleTimerOverflow(u32 tid);
|
||||
u16 TimerGetCounter(u32 timer);
|
||||
void TimerStart(u32 id, u16 cnt);
|
||||
void QueueDMAs(u32 param);
|
||||
void StartDiv();
|
||||
void DivDone(u32 param);
|
||||
void SqrtDone(u32 param);
|
||||
|
|
|
@ -37,7 +37,8 @@ namespace NDSCart
|
|||
|
||||
enum
|
||||
{
|
||||
ROMTransfer_End = 0
|
||||
ROMTransfer_PrepareData = 0,
|
||||
ROMTransfer_End
|
||||
};
|
||||
|
||||
// SRAM TODO: emulate write delays???
|
||||
|
@ -1442,6 +1443,7 @@ NDSCartSlot::NDSCartSlot(melonDS::NDS& nds, std::unique_ptr<CartCommon>&& rom) n
|
|||
{
|
||||
NDS.RegisterEventFuncs(Event_ROMTransfer, this,
|
||||
{
|
||||
MakeEventThunk(NDSCartSlot, ROMPrepareData),
|
||||
MakeEventThunk(NDSCartSlot, ROMEndTransfer)
|
||||
});
|
||||
NDS.RegisterEventFuncs(Event_ROMSPITransfer, this, {MakeEventThunk(NDSCartSlot, SPITransferDone)});
|
||||
|
@ -1797,8 +1799,7 @@ void NDSCartSlot::ResetCart() noexcept
|
|||
TransferDir = 0;
|
||||
memset(TransferCmd.data(), 0, sizeof(TransferCmd));
|
||||
TransferCmd[0] = 0xFF;
|
||||
ROMTransferTime[0] = -1;
|
||||
ROMTransferTime[1] = -1;
|
||||
ROMTransferTime = -1;
|
||||
|
||||
if (Cart) Cart->Reset();
|
||||
}
|
||||
|
@ -1815,14 +1816,8 @@ void NDSCartSlot::ROMEndTransfer(u32 param) noexcept
|
|||
Cart->ROMCommandFinish(TransferCmd.data(), TransferData.data(), TransferLen);
|
||||
}
|
||||
|
||||
void NDSCartSlot::ROMPrepareData() noexcept
|
||||
void NDSCartSlot::ROMPrepareData(u32 param) noexcept
|
||||
{
|
||||
u64 curts;
|
||||
if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
|
||||
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
|
||||
|
||||
if (curts < ROMTransferTime[0]) return;
|
||||
|
||||
if (TransferDir == 0)
|
||||
{
|
||||
if (TransferPos >= TransferLen)
|
||||
|
@ -1833,8 +1828,6 @@ void NDSCartSlot::ROMPrepareData() noexcept
|
|||
TransferPos += 4;
|
||||
}
|
||||
|
||||
ROMTransferTime[0] = -1;
|
||||
|
||||
ROMCnt |= (1<<23);
|
||||
|
||||
if (NDS.ExMemCnt[0] & (1<<11))
|
||||
|
@ -1845,7 +1838,7 @@ void NDSCartSlot::ROMPrepareData() noexcept
|
|||
|
||||
u32 NDSCartSlot::GetROMCnt() noexcept
|
||||
{
|
||||
ROMPrepareData();
|
||||
NDS.RunEventManual(Event_ROMTransfer);
|
||||
return ROMCnt;
|
||||
}
|
||||
|
||||
|
@ -1936,16 +1929,13 @@ void NDSCartSlot::WriteROMCnt(u32 val) noexcept
|
|||
NDS.ScheduleEvent(Event_ROMTransfer, false, xfercycle*cmddelay, ROMTransfer_End, 0);
|
||||
else
|
||||
{
|
||||
NDS.ScheduleEvent(Event_ROMTransfer, false, xfercycle*(cmddelay+4), ROMTransfer_PrepareData, 0);
|
||||
|
||||
u64 curts;
|
||||
if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
|
||||
else curts = ((std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift);
|
||||
if (NDS.ExMemCnt[0] & (1<<11)) curts = NDS.ARM7Timestamp;
|
||||
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
|
||||
|
||||
ROMTransferTime[0] = (xfercycle*(cmddelay+4)) + curts;
|
||||
|
||||
if ((TransferPos + 4) < TransferLen)
|
||||
ROMTransferTime[1] = (xfercycle*(cmddelay+8)) + curts;
|
||||
else
|
||||
ROMTransferTime[1] = -1;
|
||||
ROMTransferTime = (xfercycle*(cmddelay+8)) + curts;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1962,18 +1952,14 @@ void NDSCartSlot::AdvanceROMTransfer() noexcept
|
|||
if (!((TransferPos+4) & 0x1FF))
|
||||
delay += ((ROMCnt >> 16) & 0x3F);
|
||||
}
|
||||
|
||||
|
||||
u64 curts;
|
||||
if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
|
||||
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
|
||||
|
||||
ROMTransferTime[0] = ROMTransferTime[1];
|
||||
|
||||
if ((TransferPos + 4) < TransferLen)
|
||||
ROMTransferTime[1] = (xfercycle*delay) + std::max(curts, ROMTransferTime[0]);
|
||||
else
|
||||
ROMTransferTime[1] = -1;
|
||||
if (NDS.ExMemCnt[0] & (1<<11)) curts = NDS.ARM7Timestamp;
|
||||
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
|
||||
|
||||
NDS.ScheduleEvent(Event_ROMTransfer, false, ROMTransferTime-curts, ROMTransfer_PrepareData, 0);
|
||||
|
||||
ROMTransferTime = (xfercycle*delay) + std::max(curts, ROMTransferTime);
|
||||
}
|
||||
else
|
||||
ROMEndTransfer(0);
|
||||
|
@ -1983,11 +1969,7 @@ u32 NDSCartSlot::ReadROMData() noexcept
|
|||
{
|
||||
if (ROMCnt & (1<<30)) return 0;
|
||||
|
||||
u64 curts;
|
||||
if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
|
||||
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
|
||||
|
||||
ROMPrepareData();
|
||||
NDS.RunEventManual(Event_ROMTransfer);
|
||||
|
||||
if (ROMCnt & (1<<23))
|
||||
{
|
||||
|
@ -2000,12 +1982,8 @@ u32 NDSCartSlot::ReadROMData() noexcept
|
|||
void NDSCartSlot::WriteROMData(u32 val) noexcept
|
||||
{
|
||||
if (!(ROMCnt & (1<<30))) return;
|
||||
|
||||
u64 curts;
|
||||
if (NDS.CurCPU) curts = NDS.ARM7Timestamp;
|
||||
else curts = (std::max(NDS.ARM9Timestamp, NDS.DMA9Timestamp) + ((1<<NDS.ARM9ClockShift)-1)) >> NDS.ARM9ClockShift;
|
||||
|
||||
ROMPrepareData();
|
||||
NDS.RunEventManual(Event_ROMTransfer);
|
||||
|
||||
ROMData = val;
|
||||
|
||||
|
|
|
@ -410,7 +410,6 @@ public:
|
|||
void WriteROMCnt(u32 val) noexcept;
|
||||
[[nodiscard]] u8 ReadSPIData() const noexcept;
|
||||
void WriteSPIData(u8 val) noexcept;
|
||||
void ROMPrepareData() noexcept;
|
||||
|
||||
[[nodiscard]] u8 GetROMCommand(u8 index) const noexcept { return ROMCommand[index]; }
|
||||
void SetROMCommand(u8 index, u8 val) noexcept { ROMCommand[index] = val; }
|
||||
|
@ -444,8 +443,7 @@ private:
|
|||
|
||||
u64 Key2_X = 0;
|
||||
u64 Key2_Y = 0;
|
||||
|
||||
u64 ROMTransferTime[2];
|
||||
u64 ROMTransferTime;
|
||||
|
||||
void Key1_Encrypt(u32* data) const noexcept;
|
||||
void Key1_Decrypt(u32* data) const noexcept;
|
||||
|
@ -454,6 +452,7 @@ private:
|
|||
void Key1_InitKeycode(bool dsi, u32 idcode, u32 level, u32 mod) noexcept;
|
||||
void Key2_Encrypt(const u8* data, u32 len) noexcept;
|
||||
void ROMEndTransfer(u32 param) noexcept;
|
||||
void ROMPrepareData(u32 param) noexcept;
|
||||
void AdvanceROMTransfer() noexcept;
|
||||
void SPITransferDone(u32 param) noexcept;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue