aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ARM.cpp77
-rw-r--r--src/ARM.h15
-rw-r--r--src/ARMInterpreter.cpp16
-rw-r--r--src/CP15.cpp333
-rw-r--r--src/DMA.cpp4
-rw-r--r--src/GPU.cpp5
-rw-r--r--src/NDS.cpp11
7 files changed, 390 insertions, 71 deletions
diff --git a/src/ARM.cpp b/src/ARM.cpp
index 64196f6..10e2e04 100644
--- a/src/ARM.cpp
+++ b/src/ARM.cpp
@@ -100,8 +100,8 @@ void ARM::Reset()
void ARMv5::Reset()
{
- ARM::Reset();
CP15Reset();
+ ARM::Reset();
}
@@ -158,7 +158,7 @@ void ARM::SetupCodeMem(u32 addr)
NDS::ARM7GetMemRegion(addr, false, &CodeMem);
}
}
-
+namespace GPU{extern u16 VCount;}
void ARMv5::JumpTo(u32 addr, bool restorecpsr)
{
if (restorecpsr)
@@ -173,10 +173,19 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
//if (addr == 0x0201764C) printf("capture test %d: R1=%08X\n", R[6], R[1]);
//if (addr == 0x020175D8) printf("capture test %d: res=%08X\n", R[6], R[0]);
// R0=DMA# R1=src R2=size
+ if (addr==0x1FFD9E0) printf("[%03d] FMVdec\n", GPU::VCount);
+ if (R[15]==0x1FFDF40) printf("[%03d] FMVdec FINISHED\n", GPU::VCount);
+ if (addr==0x202585C)
+ {
+ //u32 dorp; NDS::ARM9Read32(0x20630DC, &dorp);
+ //printf("[%03d] IRQ handler thing. wait=%08X\n", GPU::VCount, dorp);
+ }
u32 oldregion = R[15] >> 23;
u32 newregion = addr >> 23;
+ s32 cycles;
+
if (addr & 0x1)
{
addr &= ~0x1;
@@ -190,13 +199,13 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
{
NextInstr[0] = CodeRead32(addr-2) >> 16;
NextInstr[1] = CodeRead32(addr+2);
- Cycles += NDS::ARM9MemTimings[CodeRegion][2] * 2;
+ cycles = NDS::ARM9MemTimings[CodeRegion][2] * 2;
}
else
{
NextInstr[0] = CodeRead32(addr);
NextInstr[1] = NextInstr[0] >> 16;
- Cycles += NDS::ARM9MemTimings[CodeRegion][2];
+ cycles = NDS::ARM9MemTimings[CodeRegion][2];
}
CPSR |= 0x20;
@@ -210,10 +219,22 @@ void ARMv5::JumpTo(u32 addr, bool restorecpsr)
NextInstr[0] = CodeRead32(addr);
NextInstr[1] = CodeRead32(addr+4);
- Cycles += NDS::ARM9MemTimings[CodeRegion][2] * 2;
+ cycles = NDS::ARM9MemTimings[CodeRegion][2] * 2;
CPSR &= ~0x20;
}
+
+ // TODO: investigate this
+ // firmware jumps to region 01FFxxxx, but region 5 (01000000-02000000) is set to non-executable
+ // is melonDS fucked up somewhere, or is the DS PU just incomplete/crapoed?
+ /*if (!(PU_Map[addr>>12] & 0x04))
+ {
+ printf("jumped to %08X. very bad\n", addr);
+ PrefetchAbort();
+ return;
+ }*/
+
+ Cycles += cycles;
}
void ARMv4::JumpTo(u32 addr, bool restorecpsr)
@@ -365,6 +386,15 @@ void ARM::UpdateMode(u32 oldmode, u32 newmode)
}
#undef SWAP
+
+ if (Num == 0)
+ {
+ /*if ((newmode & 0x1F) == 0x16)
+ ((ARMv5*)this)->PU_Map = ((ARMv5*)this)->PU_UserMap;
+ else
+ ((ARMv5*)this)->PU_Map = ((ARMv5*)this)->PU_PrivMap;*/
+ //if ((newmode & 0x1F) == 0x10) printf("!! USER MODE\n");
+ }
}
void ARM::TriggerIRQ()
@@ -382,6 +412,43 @@ void ARM::TriggerIRQ()
JumpTo(ExceptionBase + 0x18);
}
+void ARMv5::PrefetchAbort()
+{
+ printf("prefetch abort\n");
+
+ u32 oldcpsr = CPSR;
+ CPSR &= ~0xBF;
+ CPSR |= 0x97;
+ UpdateMode(oldcpsr, CPSR);
+
+ // this shouldn't happen, but if it does, we're stuck in some nasty endless loop
+ // so better take care of it
+ if (!(PU_Map[ExceptionBase>>12] & 0x04))
+ {
+ printf("!!!!! EXCEPTION REGION NOT READABLE. THIS IS VERY BAD!!\n");
+ NDS::Stop();
+ return;
+ }
+
+ R_IRQ[2] = oldcpsr;
+ R[14] = R[15] + (oldcpsr & 0x20 ? 2 : 0);
+ JumpTo(ExceptionBase + 0x0C);
+}
+
+void ARMv5::DataAbort()
+{
+ printf("data abort\n");
+
+ u32 oldcpsr = CPSR;
+ CPSR &= ~0xBF;
+ CPSR |= 0x97;
+ UpdateMode(oldcpsr, CPSR);
+
+ R_IRQ[2] = oldcpsr;
+ R[14] = R[15] + (oldcpsr & 0x20 ? 6 : 4);
+ JumpTo(ExceptionBase + 0x10);
+}
+
s32 ARMv5::Execute()
{
if (Halted)
diff --git a/src/ARM.h b/src/ARM.h
index a516dbe..ac8001e 100644
--- a/src/ARM.h
+++ b/src/ARM.h
@@ -166,6 +166,9 @@ public:
void JumpTo(u32 addr, bool restorecpsr = false);
+ void PrefetchAbort();
+ void DataAbort();
+
s32 Execute();
// all code accesses are forced nonseq 32bit
@@ -223,6 +226,8 @@ public:
void UpdateDTCMSetting();
void UpdateITCMSetting();
+ void UpdatePURegions();
+
void CP15Write(u32 id, u32 val);
u32 CP15Read(u32 id);
@@ -243,6 +248,16 @@ public:
u32 PU_DataRW;
u32 PU_Region[8];
+
+ // 0=dataR 1=dataW 2=codeR 4=datacache 5=datawrite 6=codecache
+ // seems the DS operates entirely under privileged mode? it never sets user regions to be read/writable
+ // TODO: investigate
+ u8 PU_UserMap[0x100000];
+ u8 PU_PrivMap[0x100000];
+ //u8* PU_Map;
+ #define PU_Map PU_PrivMap
+
+ bool CodeCached;
};
class ARMv4 : public ARM
diff --git a/src/ARMInterpreter.cpp b/src/ARMInterpreter.cpp
index b29f558..1312771 100644
--- a/src/ARMInterpreter.cpp
+++ b/src/ARMInterpreter.cpp
@@ -34,8 +34,8 @@ void A_UNK(ARM* cpu)
//for (int i = 0; i < 16; i++) printf("R%d: %08X\n", i, cpu->R[i]);
//NDS::Halt();
u32 oldcpsr = cpu->CPSR;
- cpu->CPSR &= ~0xFF;
- cpu->CPSR |= 0xDB;
+ cpu->CPSR &= ~0xBF;
+ cpu->CPSR |= 0x9B;
cpu->UpdateMode(oldcpsr, cpu->CPSR);
cpu->R_UND[2] = oldcpsr;
@@ -48,8 +48,8 @@ void T_UNK(ARM* cpu)
printf("undefined THUMB%d instruction %04X @ %08X\n", cpu->Num?7:9, cpu->CurInstr, cpu->R[15]-4);
//NDS::Halt();
u32 oldcpsr = cpu->CPSR;
- cpu->CPSR &= ~0xFF;
- cpu->CPSR |= 0xDB;
+ cpu->CPSR &= ~0xBF;
+ cpu->CPSR |= 0x9B;
cpu->UpdateMode(oldcpsr, cpu->CPSR);
cpu->R_UND[2] = oldcpsr;
@@ -221,8 +221,8 @@ void A_MRC(ARM* cpu)
void A_SVC(ARM* cpu)
{
u32 oldcpsr = cpu->CPSR;
- cpu->CPSR &= ~0xFF;
- cpu->CPSR |= 0xD3;
+ cpu->CPSR &= ~0xBF;
+ cpu->CPSR |= 0x93;
cpu->UpdateMode(oldcpsr, cpu->CPSR);
cpu->R_SVC[2] = oldcpsr;
@@ -233,8 +233,8 @@ void A_SVC(ARM* cpu)
void T_SVC(ARM* cpu)
{
u32 oldcpsr = cpu->CPSR;
- cpu->CPSR &= ~0xFF;
- cpu->CPSR |= 0xD3;
+ cpu->CPSR &= ~0xBF;
+ cpu->CPSR |= 0x93;
cpu->UpdateMode(oldcpsr, cpu->CPSR);
cpu->R_SVC[2] = oldcpsr;
diff --git a/src/CP15.cpp b/src/CP15.cpp
index 3507b57..0665137 100644
--- a/src/CP15.cpp
+++ b/src/CP15.cpp
@@ -25,7 +25,7 @@
void ARMv5::CP15Reset()
{
- CP15Control = 0x78; // dunno
+ CP15Control = 0x2078; // dunno
DTCMSetting = 0;
ITCMSetting = 0;
@@ -36,6 +36,16 @@ void ARMv5::CP15Reset()
ITCMSize = 0;
DTCMBase = 0xFFFFFFFF;
DTCMSize = 0;
+
+ PU_CodeCacheable = 0;
+ PU_DataCacheable = 0;
+ PU_DataCacheWrite = 0;
+
+ PU_CodeRW = 0;
+ PU_DataRW = 0;
+
+ memset(PU_Region, 0, 8*sizeof(u32));
+ UpdatePURegions();
}
void ARMv5::CP15DoSavestate(Savestate* file)
@@ -64,13 +74,13 @@ void ARMv5::UpdateDTCMSetting()
{
DTCMBase = DTCMSetting & 0xFFFFF000;
DTCMSize = 0x200 << ((DTCMSetting >> 1) & 0x1F);
- //printf("DTCM [%08X] enabled at %08X, size %X\n", DTCMSetting, DTCMBase, DTCMSize);
+ printf("DTCM [%08X] enabled at %08X, size %X\n", DTCMSetting, DTCMBase, DTCMSize);
}
else
{
DTCMBase = 0xFFFFFFFF;
DTCMSize = 0;
- //printf("DTCM disabled\n");
+ printf("DTCM disabled\n");
}
}
@@ -79,12 +89,128 @@ void ARMv5::UpdateITCMSetting()
if (CP15Control & (1<<18))
{
ITCMSize = 0x200 << ((ITCMSetting >> 1) & 0x1F);
- //printf("ITCM [%08X] enabled at %08X, size %X\n", ITCMSetting, 0, ITCMSize);
+ printf("ITCM [%08X] enabled at %08X, size %X\n", ITCMSetting, 0, ITCMSize);
}
else
{
ITCMSize = 0;
- //printf("ITCM disabled\n");
+ printf("ITCM disabled\n");
+ }
+}
+
+
+void ARMv5::UpdatePURegions()
+{
+ if (!(CP15Control & (1<<0)))
+ {
+ // PU disabled
+
+ u8 mask = 0x07;
+ if (CP15Control & (1<<2)) mask |= 0x30;
+ if (CP15Control & (1<<12)) mask |= 0x40;
+
+ memset(PU_UserMap, mask, 0x100000);
+ memset(PU_PrivMap, mask, 0x100000);
+
+ return;
+ }
+
+ memset(PU_UserMap, 0, 0x100000);
+ memset(PU_PrivMap, 0, 0x100000);
+
+ u32 coderw = PU_CodeRW;
+ u32 datarw = PU_DataRW;
+
+ u32 codecache, datacache, datawrite;
+
+ // datacache/datawrite
+ // 0/0: goes to memory
+ // 0/1: goes to memory
+ // 1/0: goes to memory and cache
+ // 1/1: goes to cache
+
+ if (CP15Control & (1<<12))
+ codecache = PU_CodeCacheable;
+ else
+ codecache = 0;
+
+ if (CP15Control & (1<<2))
+ {
+ datacache = PU_DataCacheable;
+ datawrite = PU_DataCacheWrite;
+ }
+ else
+ {
+ datacache = 0;
+ datawrite = 0;
+ }
+
+ for (int n = 0; n < 8; n++)
+ {
+ u32 rgn = PU_Region[n];
+ if (!(rgn & (1<<0))) continue;
+
+ u32 start = rgn >> 12;
+ u32 sz = 2 << ((rgn >> 1) & 0x1F);
+ u32 end = start + (sz >> 12);
+ // TODO: check alignment of start
+
+ u8 usermask = 0;
+ u8 privmask = 0;
+
+ switch (datarw & 0xF)
+ {
+ case 0: break;
+ case 1: privmask |= 0x03; break;
+ case 2: privmask |= 0x03; usermask |= 0x01; break;
+ case 3: privmask |= 0x03; usermask |= 0x03; break;
+ case 5: privmask |= 0x01; break;
+ case 6: privmask |= 0x01; usermask |= 0x01; break;
+ default: printf("!! BAD DATARW VALUE %d\n", datarw&0xF);
+ }
+
+ switch (coderw & 0xF)
+ {
+ case 0: break;
+ case 1: privmask |= 0x04; break;
+ case 2: privmask |= 0x04; usermask |= 0x04; break;
+ case 3: privmask |= 0x04; usermask |= 0x04; break;
+ case 5: privmask |= 0x04; break;
+ case 6: privmask |= 0x04; usermask |= 0x04; break;
+ default: printf("!! BAD CODERW VALUE %d\n", datarw&0xF);
+ }
+
+ if (datacache & 0x1)
+ {
+ privmask |= 0x10;
+ usermask |= 0x10;
+
+ if (datawrite & 0x1)
+ {
+ privmask |= 0x20;
+ usermask |= 0x20;
+ }
+ }
+
+ if (codecache & 0x1)
+ {
+ privmask |= 0x40;
+ usermask |= 0x40;
+ }
+
+ printf("PU region %d: %08X-%08X, user=%02X priv=%02X\n", n, start<<12, end<<12, usermask, privmask);
+
+ for (u32 i = start; i < end; i++)
+ {
+ PU_UserMap[i] = usermask;
+ PU_PrivMap[i] = privmask;
+ }
+
+ coderw >>= 4;
+ datarw >>= 4;
+ codecache >>= 1;
+ datacache >>= 1;
+ datawrite >>= 1;
}
}
@@ -96,28 +222,39 @@ void ARMv5::CP15Write(u32 id, u32 val)
switch (id)
{
case 0x100:
- val &= 0x000FF085;
- CP15Control &= ~0x000FF085;
- CP15Control |= val;
- UpdateDTCMSetting();
- UpdateITCMSetting();
+ {
+ u32 old = CP15Control;
+ val &= 0x000FF085;
+ CP15Control &= ~0x000FF085;
+ CP15Control |= val;
+ printf("CP15Control = %08X (%08X->%08X)\n", CP15Control, old, val);
+ UpdateDTCMSetting();
+ UpdateITCMSetting();
+ if ((old & 0x1005) != (val & 0x1005)) UpdatePURegions();
+ if (val & (1<<7)) printf("!!!! ARM9 BIG ENDIAN MODE. VERY BAD. SHIT GONNA ASPLODE NOW\n");
+ if (val & (1<<13)) ExceptionBase = 0xFFFF0000;
+ else ExceptionBase = 0x00000000;
+ }
return;
case 0x200: // data cacheable
PU_DataCacheable = val;
printf("PU: DataCacheable=%08X\n", val);
+ UpdatePURegions();
return;
case 0x201: // code cacheable
PU_CodeCacheable = val;
printf("PU: CodeCacheable=%08X\n", val);
+ UpdatePURegions();
return;
case 0x300: // data cache write-buffer
PU_DataCacheWrite = val;
printf("PU: DataCacheWrite=%08X\n", val);
+ UpdatePURegions();
return;
@@ -132,6 +269,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
PU_DataRW |= ((val & 0x3000) << 12);
PU_DataRW |= ((val & 0xC000) << 14);
printf("PU: DataRW=%08X (legacy %08X)\n", PU_DataRW, val);
+ UpdatePURegions();
return;
case 0x501: // legacy code permissions
@@ -145,16 +283,19 @@ void ARMv5::CP15Write(u32 id, u32 val)
PU_CodeRW |= ((val & 0x3000) << 12);
PU_CodeRW |= ((val & 0xC000) << 14);
printf("PU: CodeRW=%08X (legacy %08X)\n", PU_CodeRW, val);
+ UpdatePURegions();
return;
case 0x502: // data permissions
PU_DataRW = val;
printf("PU: DataRW=%08X\n", PU_DataRW);
+ UpdatePURegions();
return;
case 0x503: // code permissions
PU_CodeRW = val;
printf("PU: CodeRW=%08X\n", PU_CodeRW);
+ UpdatePURegions();
return;
@@ -179,6 +320,7 @@ void ARMv5::CP15Write(u32 id, u32 val)
printf("%s, ", val&1 ? "enabled":"disabled");
printf("%08X-", val&0xFFFFF000);
printf("%08X\n", (val&0xFFFFF000)+(2<<((val&0x3E)>>1)));
+ UpdatePURegions();
return;
@@ -318,7 +460,7 @@ u32 ARMv5::CP15Read(u32 id)
u32 ARMv5::CodeRead32(u32 addr)
{
- // PU/cache check here
+ u8 pu = PU_Map[addr>>12];
if (addr < ITCMSize)
{
@@ -328,34 +470,49 @@ u32 ARMv5::CodeRead32(u32 addr)
u32 ret;
CodeRegion = NDS::ARM9Read32(addr, &ret);
+ if (pu & 0x40) CodeRegion = NDS::Region9_ICache;
return ret;
}
bool ARMv5::DataRead8(u32 addr, u32* val, u32 flags)
{
- // PU/cache check here
+ u8 pu = PU_Map[addr>>12];
+ /*if (!(pu & 0x01))
+ {
+ DataAbort();
+ return false;
+ }*/
if (addr < ITCMSize)
{
DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*val = *(u8*)&ITCM[addr & 0x7FFF];
return true;
}
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
{
- DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ DataRegion = NDS::Region9_DTCM;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*val = *(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF];
return true;
}
DataRegion = NDS::ARM9Read8(addr, val);
- if (flags & RWFlags_Nonseq)
- DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ if (pu & 0x10)
+ {
+ DataRegion = NDS::Region9_DCache;
+ if (flags & RWFlags_Nonseq) DataCycles = 2;
+ else DataCycles += 2;
+ }
else
- DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ {
+ if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ }
return true;
}
@@ -363,28 +520,42 @@ bool ARMv5::DataRead16(u32 addr, u32* val, u32 flags)
{
addr &= ~1;
- // PU/cache check here
+ u8 pu = PU_Map[addr>>12];
+ /*if (!(pu & 0x01))
+ {
+ DataAbort();
+ return false;
+ }*/
if (addr < ITCMSize)
{
DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*val = *(u16*)&ITCM[addr & 0x7FFF];
return true;
}
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
{
- DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ DataRegion = NDS::Region9_DTCM;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*val = *(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF];
return true;
}
DataRegion = NDS::ARM9Read16(addr, val);
- if (flags & RWFlags_Nonseq)
- DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ if (pu & 0x10)
+ {
+ DataRegion = NDS::Region9_DCache;
+ if (flags & RWFlags_Nonseq) DataCycles = 2;
+ else DataCycles += 2;
+ }
else
- DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ {
+ if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ }
return true;
}
@@ -392,55 +563,83 @@ bool ARMv5::DataRead32(u32 addr, u32* val, u32 flags)
{
addr &= ~3;
- // PU/cache check here
+ u8 pu = PU_Map[addr>>12];
+ /*if (!(pu & 0x01))
+ {
+ DataAbort();
+ return false;
+ }*/
if (addr < ITCMSize)
{
DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*val = *(u32*)&ITCM[addr & 0x7FFF];
return true;
}
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
{
- DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ DataRegion = NDS::Region9_DTCM;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*val = *(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF];
return true;
}
DataRegion = NDS::ARM9Read32(addr, val);
- if (flags & RWFlags_Nonseq)
- DataCycles = NDS::ARM9MemTimings[DataRegion][2];
+ if (pu & 0x10)
+ {
+ DataRegion = NDS::Region9_DCache;
+ if (flags & RWFlags_Nonseq) DataCycles = 2;
+ else DataCycles += 2;
+ }
else
- DataCycles += NDS::ARM9MemTimings[DataRegion][3];
+ {
+ if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ }
return true;
}
bool ARMv5::DataWrite8(u32 addr, u8 val, u32 flags)
{
- // PU/cache check here
+ u8 pu = PU_Map[addr>>12];
+ /*if (!(pu & 0x02))
+ {
+ DataAbort();
+ return false;
+ }*/
if (addr < ITCMSize)
{
DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*(u8*)&ITCM[addr & 0x7FFF] = val;
return true;
}
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
{
- DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ DataRegion = NDS::Region9_DTCM;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*(u8*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
return true;
}
DataRegion = NDS::ARM9Write8(addr, val);
- if (flags & RWFlags_Nonseq)
- DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ if (pu & 0x20)
+ {
+ DataRegion = NDS::Region9_DCache;
+ if (flags & RWFlags_Nonseq) DataCycles = 2;
+ else DataCycles += 2;
+ }
else
- DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ {
+ if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ }
return true;
}
@@ -448,28 +647,42 @@ bool ARMv5::DataWrite16(u32 addr, u16 val, u32 flags)
{
addr &= ~1;
- // PU/cache check here
+ u8 pu = PU_Map[addr>>12];
+ /*if (!(pu & 0x02))
+ {
+ DataAbort();
+ return false;
+ }*/
if (addr < ITCMSize)
{
DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*(u16*)&ITCM[addr & 0x7FFF] = val;
return true;
}
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
{
- DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ DataRegion = NDS::Region9_DTCM;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*(u16*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
return true;
}
DataRegion = NDS::ARM9Write16(addr, val);
- if (flags & RWFlags_Nonseq)
- DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ if (pu & 0x20)
+ {
+ DataRegion = NDS::Region9_DCache;
+ if (flags & RWFlags_Nonseq) DataCycles = 2;
+ else DataCycles += 2;
+ }
else
- DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ {
+ if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ }
return true;
}
@@ -477,28 +690,42 @@ bool ARMv5::DataWrite32(u32 addr, u32 val, u32 flags)
{
addr &= ~3;
- // PU/cache check here
+ u8 pu = PU_Map[addr>>12];
+ /*if (!(pu & 0x02))
+ {
+ DataAbort();
+ return false;
+ }*/
if (addr < ITCMSize)
{
DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*(u32*)&ITCM[addr & 0x7FFF] = val;
return true;
}
if (addr >= DTCMBase && addr < (DTCMBase + DTCMSize))
{
- DataRegion = NDS::Region9_ITCM;
- DataCycles += 1;
+ DataRegion = NDS::Region9_DTCM;
+ if (flags & RWFlags_Nonseq) DataCycles = 1;
+ else DataCycles += 1;
*(u32*)&DTCM[(addr - DTCMBase) & 0x3FFF] = val;
return true;
}
DataRegion = NDS::ARM9Write32(addr, val);
- if (flags & RWFlags_Nonseq)
- DataCycles = NDS::ARM9MemTimings[DataRegion][2];
+ if (pu & 0x20)
+ {
+ DataRegion = NDS::Region9_DCache;
+ if (flags & RWFlags_Nonseq) DataCycles = 2;
+ else DataCycles += 2;
+ }
else
- DataCycles += NDS::ARM9MemTimings[DataRegion][3];
+ {
+ if (flags & RWFlags_Nonseq) DataCycles = NDS::ARM9MemTimings[DataRegion][0];
+ else DataCycles += NDS::ARM9MemTimings[DataRegion][1];
+ }
return true;
}
diff --git a/src/DMA.cpp b/src/DMA.cpp
index 95aa9e6..2f7d9bb 100644
--- a/src/DMA.cpp
+++ b/src/DMA.cpp
@@ -255,7 +255,7 @@ s32 DMA::Run(s32 cycles)
readfn(CurSrcAddr, &val);
writefn(CurDstAddr, val);
- s32 c = (Waitstates[0][(CurSrcAddr >> 24) & 0xF] + Waitstates[0][(CurDstAddr >> 24) & 0xF]);
+ s32 c = 1;//(Waitstates[0][(CurSrcAddr >> 24) & 0xF] + Waitstates[0][(CurDstAddr >> 24) & 0xF]);
cycles -= c;
NDS::RunTimingCriticalDevices(CPU, c);
@@ -294,7 +294,7 @@ s32 DMA::Run(s32 cycles)
readfn(CurSrcAddr, &val);
writefn(CurDstAddr, val);
- s32 c = (Waitstates[1][(CurSrcAddr >> 24) & 0xF] + Waitstates[1][(CurDstAddr >> 24) & 0xF]);
+ s32 c = 1;//(Waitstates[1][(CurSrcAddr >> 24) & 0xF] + Waitstates[1][(CurDstAddr >> 24) & 0xF]);
cycles -= c;
NDS::RunTimingCriticalDevices(CPU, c);
diff --git a/src/GPU.cpp b/src/GPU.cpp
index aba97a5..9d79848 100644
--- a/src/GPU.cpp
+++ b/src/GPU.cpp
@@ -653,12 +653,12 @@ void MapVRAM_I(u32 bank, u8 cnt)
void DisplaySwap(u32 val)
{
if (val)
- {
+ {printf("main GPU on top screen\n");
GPU2D_A->SetFramebuffer(&Framebuffer[256*0]);
GPU2D_B->SetFramebuffer(&Framebuffer[256*192]);
}
else
- {
+ {printf("main GPU on bottom screen\n");
GPU2D_A->SetFramebuffer(&Framebuffer[256*192]);
GPU2D_B->SetFramebuffer(&Framebuffer[256*0]);
}
@@ -813,6 +813,7 @@ void StartScanline(u32 line)
GPU2D_A->VBlank();
GPU2D_B->VBlank();
GPU3D::VBlank();
+ printf("VBlank. PC=%08X\n", NDS::GetPC(0));
}
else if (VCount == 144)
{
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 38cc611..2c3f5cd 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -226,6 +226,15 @@ void CalculateTimings(int arm9shift)
{
RegionTimings t = ARM9MemTimingInfo[i];
+ /*if (i==2||i==3) // ARM9 internal
+ {
+ ARM9MemTimings[i][0] = 5; // 16-bit N
+ ARM9MemTimings[i][1] = 5; // 16-bit S
+ ARM9MemTimings[i][2] = 5; // 32-bit N
+ ARM9MemTimings[i][3] = 5; // 32-bit S
+ continue;
+ }*/
+
if (t.BusType == 3) // ARM9 internal
{
ARM9MemTimings[i][0] = 1; // 16-bit N
@@ -1030,7 +1039,7 @@ void HandleTimerOverflow(u32 tid)
timer->Counter += timer->Reload << 16;
if (timer->Cnt & (1<<6))
SetIRQ(tid >> 2, IRQ_Timer0 + (tid & 0x3));
-
+//if (tid<4) printf("[%03d] timer%d IRQ\n", GPU::VCount, tid);
if ((tid & 0x3) == 3)
return;