totally rewrite main emulation loop! YOUR SAVESTATES ARE INVALIDATED. your timing is all different. but, your timing is more precise, a few hidden old bugs surfaced and were smashed, and some games work that didn't used to. INSTRUCTIONS_PER_BATCH is a thing of the past. crazymax and luigi, I may have broken your parts, but hopefully only a little bit. your new hookups into the emulation loop are more complicated but potentially faster and definitely more precise.

This commit is contained in:
zeromus 2009-07-15 19:42:32 +00:00
parent b54420e5a7
commit 28435d9334
16 changed files with 1272 additions and 1633 deletions

View File

@ -1,21 +1,31 @@
0.9.4 -> ??? (r2437-r???)
??? introduces an entirely rewritten main emulation loop.
This totally changes the timing, and totally breaks old savestates.
Highlights:
* win32: lua engine, path configuration, 7z dearchiving support
* rewritten main emulation loop
General/Core:
bug: fix cflash directory support for non-windows
bug: fix freeze in cart irq
bug: correctly emulate dma to/from tcm
enh: add guitar grip emulation
enh: add more powerful antigrain-based drawing library and rewrite OSD system
enh: ideas-style debugging prints
Graphics:
bug: fixing of obj blending and bmp obj rendering
bug: fix backdrop blending with garbage
bug: fix 256B granularity sprite addressing for sub gpu
bug: swrast: add clear image emulation
bug: swrast: add edge marking
Windows:
bug: improve map view tool
bug: improve map view tool to support more modes
enh: added 2x resizing filters (hq2x, 2xsai, supereagle, scanlines)
enh: soundview can now mute channels
Linux:
enh: alsa microphone support

View File

@ -28,6 +28,7 @@
#include "debug.h"
#include "mem.h"
#include "MMU.h"
#include "NDSSystem.h"
// ========================================================= IPC FIFO
IPC_FIFO ipc_fifo[2]; // 0 - ARM9
@ -174,6 +175,8 @@ void GFX_FIFOsend(u8 cmd, u32 param)
#endif
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
NDS_RescheduleGXFIFO();
}
BOOL GFX_FIFOrecv(u8 *cmd, u32 *param)
@ -183,6 +186,7 @@ BOOL GFX_FIFOrecv(u8 *cmd, u32 *param)
if (gxstat & 0xC0000000)
{
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}
#endif
if (gxFIFO.tail == 0) // empty
@ -193,18 +197,23 @@ BOOL GFX_FIFOrecv(u8 *cmd, u32 *param)
if ((gxstat & 0x80000000)) // empty
{
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}
return FALSE;
}
if (gxstat & 0x40000000) // IRQ: less half
{
if (gxstat & 0x02000000) setIF(0, (1<<21));
if (gxstat & 0x02000000)
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}
if ((gxstat & 0x80000000)) // IRQ: empty
{
if (gxstat & 0x04000000) setIF(0, (1<<21));
if (gxstat & 0x04000000)
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}
gxstat &= 0xF000FFFF;
@ -228,6 +237,8 @@ BOOL GFX_FIFOrecv(u8 *cmd, u32 *param)
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
NDS_RescheduleGXFIFO();
return TRUE;
}
@ -241,10 +252,13 @@ void GFX_FIFOcnt(u32 val)
return;
}
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
NDS_RescheduleGXFIFO();
/*if (gxstat & 0xC0000000)
{
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}*/
}

View File

@ -410,23 +410,8 @@ u8 *MMU_RenderMapToLCD(u32 vram_addr)
}
template<u8 DMA_CHANNEL>
void DMAtoVRAMmapping()
{
//THIS IS ALSO DANGEROUS!!!!!!
//but i dont think it needs to be done
/*u32 dst = DMADst[ARMCPU_ARM9][DMA_CHANNEL];
bool unmapped;
dst = MMU_LCDmap(dst,unmapped);
DMADst[ARMCPU_ARM9][DMA_CHANNEL] = dst;*/
}
#define LOG_VRAM_ERROR() LOG("No data for block %i MST %i\n", block, VRAMBankCnt & 0x07);
struct VramConfiguration {
enum Purpose {
@ -983,7 +968,7 @@ void MMU_clearMem()
memset(MMU.reg_IF, 0, sizeof(u32) * 2);
memset(MMU.DMAStartTime, 0, sizeof(u32) * 2 * 4);
memset(MMU.DMACycle, 0, sizeof(s32) * 2 * 4);
memset(MMU.DMACycle, 0, sizeof(MMU.DMACycle));
memset(MMU.DMACrt, 0, sizeof(u32) * 2 * 4);
memset(MMU.DMAing, 0, sizeof(BOOL) * 2 * 4);
@ -1011,9 +996,7 @@ void MMU_clearMem()
partie = 1;
addonsReset();
Mic_Reset();
#ifdef USE_GEOMETRY_FIFO_EMULATION
MMU.gfx3dCycles = 0;
#endif
}
void MMU_setRom(u8 * rom, u32 mask)
@ -1062,10 +1045,11 @@ static void execsqrt() {
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B4, 0);
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x2B0, cnt | 0x8000);
MMU.sqrtCycles = (nds.cycles + 26);
MMU.sqrtCycles = nds_timer + 26;
MMU.sqrtResult = ret;
MMU.sqrtCnt = (cnt & 0x7FFF);
MMU.sqrtRunning = TRUE;
NDS_Reschedule();
}
static void execdiv() {
@ -1078,19 +1062,19 @@ static void execdiv() {
case 0:
num = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290);
den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298);
MMU.divCycles = (nds.cycles + 36);
MMU.divCycles = nds_timer + 36;
break;
case 1:
case 3: //gbatek says this is same as mode 1
num = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290);
den = (s64) (s32) T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298);
MMU.divCycles = (nds.cycles + 68);
MMU.divCycles = nds_timer + 68;
break;
case 2:
default:
num = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x290);
den = (s64) T1ReadQuad(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x298);
MMU.divCycles = (nds.cycles + 68);
MMU.divCycles = nds_timer + 68;
break;
}
@ -1122,6 +1106,7 @@ static void execdiv() {
MMU.divMod = mod;
MMU.divCnt = (cnt & 0x7FFF);
MMU.divRunning = TRUE;
NDS_Reschedule();
}
template<int PROCNUM>
@ -1150,19 +1135,21 @@ void FASTCALL MMU_doDMA(u32 num)
taille = (MMU.DMACrt[PROCNUM][num]&0x1FFFFF);
if(taille == 0) taille = 0x200000; //according to gbatek..
//THIS IS A BIG HACK
// If we are in "Main memory display" mode just copy an entire
// screen (256x192 pixels).
// Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
// (under DISP_MMEM_FIFO)
if ((MMU.DMAStartTime[PROCNUM][num]==4) && // Must be in main memory display mode
if ((MMU.DMAStartTime[PROCNUM][num]==EDMAMode_MemDisplay) && // Must be in main memory display mode
(taille==4) && // Word must be 4
(((MMU.DMACrt[PROCNUM][num]>>26)&1) == 1)) // Transfer mode must be 32bit wide
taille = 24576; //256*192/2;
if(MMU.DMAStartTime[PROCNUM][num] == 5)
if(MMU.DMAStartTime[PROCNUM][num] == EDMAMode_Card)
taille *= 0x80;
MMU.DMACycle[PROCNUM][num] = taille + nds.cycles;
MMU.DMACycle[PROCNUM][num] = taille + nds_timer; //TODO - surely this is a gross simplification
MMU.DMAing[PROCNUM][num] = TRUE;
MMU.CheckDMAs |= (1<<(num+(PROCNUM<<2)));
@ -1172,6 +1159,8 @@ void FASTCALL MMU_doDMA(u32 num)
if(!(MMU.DMACrt[PROCNUM][num]&(1<<25)))
MMU.DMAStartTime[PROCNUM][num] = 0;
NDS_RescheduleDMA();
// transfer
{
@ -1315,6 +1304,97 @@ static INLINE void MMU_IPCSync(u8 proc, u32 val)
setIF(proc^1, ( 1 << 16 ));
}
static INLINE u16 read_timer(int proc, int timerIndex)
{
//chained timers are always up to date
if(MMU.timerMODE[proc][timerIndex] == 0xFFFF)
return MMU.timer[proc][timerIndex];
//for unchained timers, we do not keep the timer up to date. its value will need to be calculated here
s32 diff = (s32)(nds.timerCycle[proc][timerIndex] - nds_timer);
assert(diff>=0);
if(diff<0)
printf("NEW EMULOOP BAD NEWS PLEASE REPORT: TIME READ DIFF < 0 (%d) (%d) (%d)\n",diff,timerIndex,MMU.timerMODE[proc][timerIndex]);
s32 units = diff / (1<<MMU.timerMODE[proc][timerIndex]);
s32 ret = 65535 - units;
assert(ret>=0);
if(ret<0) printf("NEW EMULOOP BAD NEWS PLEASE REPORT: TIME READ RETURN < 0\n");
return ret;
}
static INLINE void write_timer(int proc, int timerIndex, u16 val)
{
int mask = ((val&0x80)>>7) << timerIndex;
//MMU.CheckTimers = (MMU.CheckTimers & (~mask)) | mask;
if(val&0x80)
MMU.timer[proc][timerIndex] = MMU.timerReload[proc][timerIndex];
MMU.timerON[proc][timerIndex] = val & 0x80;
switch(val&7)
{
case 0 :
MMU.timerMODE[proc][timerIndex] = 0+1;
break;
case 1 :
MMU.timerMODE[proc][timerIndex] = 6+1;
break;
case 2 :
MMU.timerMODE[proc][timerIndex] = 8+1;
break;
case 3 :
MMU.timerMODE[proc][timerIndex] = 10+1;
break;
default :
MMU.timerMODE[proc][timerIndex] = 0xFFFF;
break;
}
int remain = 65536 - MMU.timerReload[proc][timerIndex];
nds.timerCycle[proc][timerIndex] = nds_timer + (remain<<MMU.timerMODE[proc][timerIndex]);
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x102+timerIndex*4, val);
NDS_RescheduleTimers();
}
template<int proc> static INLINE void write_dma_hictrl(const int dmanum, const u16 val)
{
u32 baseAddr = 0xB0 + dmanum*12;
//write this control value
T1WriteWord(MMU.MMU_MEM[proc][0x40], baseAddr+10, val);
//read back the src and dst addr
DMASrc[proc][dmanum] = T1ReadLong(MMU.MMU_MEM[proc][0x40], baseAddr);
DMADst[proc][dmanum] = T1ReadLong(MMU.MMU_MEM[proc][0x40], baseAddr+4);
//analyze the control value
u32 v = T1ReadLong(MMU.MMU_MEM[proc][0x40], baseAddr+8);
if(proc==ARMCPU_ARM9) MMU.DMAStartTime[proc][dmanum] = (v>>27) & 0x7;
else {
static const EDMAMode lookup[] = {EDMAMode_Immediate,EDMAMode_VBlank,EDMAMode_Card,EDMAMode7_Wifi};
MMU.DMAStartTime[proc][dmanum] = lookup[(v>>28) & 0x3];
if(MMU.DMAStartTime[proc][dmanum] == EDMAMode7_Wifi && (dmanum==1 || dmanum==3))
MMU.DMAStartTime[proc][dmanum] = EDMAMode7_GBASlot;
}
MMU.DMACrt[proc][dmanum] = v;
if(MMU.DMAStartTime[proc][dmanum] == EDMAMode_Immediate
//TODO HACK: I think this is a gxfifo hack:
|| MMU.DMAStartTime[proc][dmanum] == EDMAMode_GXFifo)
{
MMU_doDMA<proc>(dmanum);
}
//printf("dma ctrl %d %d\n",proc,dmanum);
//LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM9, 0, DMASrc[ARMCPU_ARM9][0], DMADst[ARMCPU_ARM9][0], (val&(1<<25))?"ON":"OFF");
NDS_RescheduleDMA();
}
static INLINE void write_auxspicnt(const int proc, const int size, const int adr, const int val)
{
//why val==0 to reset? is it a particular bit? its not bit 6...
@ -1869,6 +1949,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
case REG_IME:
{
NDS_Reschedule();
u32 old_val = MMU.reg_IME[ARMCPU_ARM9];
u32 new_val = val & 0x01;
MMU.reg_IME[ARMCPU_ARM9] = new_val;
@ -1887,6 +1968,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
return;
}
case REG_IE :
NDS_Reschedule();
MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF0000) | val;
#ifndef NEW_IRQ
if ( MMU.reg_IME[ARMCPU_ARM9])
@ -1901,6 +1983,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
#endif
return;
case REG_IE + 2 :
NDS_Reschedule();
MMU.reg_IE[ARMCPU_ARM9] = (MMU.reg_IE[ARMCPU_ARM9]&0xFFFF) | (((u32)val)<<16);
#ifndef NEW_IRQ
if ( MMU.reg_IME[ARMCPU_ARM9])
@ -1916,9 +1999,11 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
return;
case REG_IF :
NDS_Reschedule();
MMU.reg_IF[ARMCPU_ARM9] &= (~((u32)val));
return;
case REG_IF + 2 :
NDS_Reschedule();
MMU.reg_IF[ARMCPU_ARM9] &= (~(((u32)val)<<16));
return;
@ -1941,37 +2026,7 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
case REG_TM3CNTH :
{
int timerIndex = ((adr-2)>>2)&0x3;
int mask = ((val&0x80)>>7) << timerIndex;
MMU.CheckTimers = (MMU.CheckTimers & (~mask)) | mask;
if(val&0x80)
MMU.timer[ARMCPU_ARM9][timerIndex] = MMU.timerReload[ARMCPU_ARM9][((adr-2)>>2)&0x3];
MMU.timerON[ARMCPU_ARM9][((adr-2)>>2)&0x3] = val & 0x80;
switch(val&7)
{
case 0 :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 0+1;//ARMCPU_ARM9;
break;
case 1 :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 6+1;//ARMCPU_ARM9;
break;
case 2 :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 8+1;//ARMCPU_ARM9;
break;
case 3 :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 10+1;//ARMCPU_ARM9;
break;
default :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 0xFFFF;
break;
}
if(!(val & 0x80))
MMU.timerRUN[ARMCPU_ARM9][timerIndex] = FALSE;
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], adr & 0xFFF, val);
write_timer(ARMCPU_ARM9, timerIndex, val);
return;
}
@ -2021,95 +2076,17 @@ void FASTCALL _MMU_ARM9_write16(u32 adr, u16 val)
}
case REG_DMA0CNTH :
{
u32 v;
//if(val&0x8000) emu_halt();
//LOG("16 bit dma0 %04X\r\n", val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xBA, val);
DMASrc[ARMCPU_ARM9][0] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xB0);
DMADst[ARMCPU_ARM9][0] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xB4);
DMAtoVRAMmapping<0>();
v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xB8);
MMU.DMAStartTime[ARMCPU_ARM9][0] = (v>>27) & 0x7;
MMU.DMACrt[ARMCPU_ARM9][0] = v;
if(MMU.DMAStartTime[ARMCPU_ARM9][0] == 0)
MMU_doDMA<ARMCPU_ARM9>(0);
#ifdef LOG_DMA2
//else
{
LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM9, 0, DMASrc[ARMCPU_ARM9][0], DMADst[ARMCPU_ARM9][0], (val&(1<<25))?"ON":"OFF");
}
#endif
}
write_dma_hictrl<ARMCPU_ARM9>(0,val);
return;
case REG_DMA1CNTH :
{
u32 v;
//if(val&0x8000) emu_halt();
//LOG("16 bit dma1 %04X\r\n", val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC6, val);
DMASrc[ARMCPU_ARM9][1] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xBC);
DMADst[ARMCPU_ARM9][1] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC0);
DMAtoVRAMmapping<1>();
v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC4);
MMU.DMAStartTime[ARMCPU_ARM9][1] = (v>>27) & 0x7;
MMU.DMACrt[ARMCPU_ARM9][1] = v;
if(MMU.DMAStartTime[ARMCPU_ARM9][1] == 0)
MMU_doDMA<ARMCPU_ARM9>(1);
#ifdef LOG_DMA2
//else
{
LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM9, 1, DMASrc[ARMCPU_ARM9][1], DMADst[ARMCPU_ARM9][1], (val&(1<<25))?"ON":"OFF");
}
#endif
}
write_dma_hictrl<ARMCPU_ARM9>(1,val);
return;
case REG_DMA2CNTH :
{
u32 v;
//if(val&0x8000) emu_halt();
//LOG("16 bit dma2 %04X\r\n", val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xD2, val);
DMASrc[ARMCPU_ARM9][2] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC8);
DMADst[ARMCPU_ARM9][2] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xCC);
DMAtoVRAMmapping<2>();
v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xD0);
MMU.DMAStartTime[ARMCPU_ARM9][2] = (v>>27) & 0x7;
MMU.DMACrt[ARMCPU_ARM9][2] = v;
if(MMU.DMAStartTime[ARMCPU_ARM9][2] == 0)
MMU_doDMA<ARMCPU_ARM9>(2);
#ifdef LOG_DMA2
//else
{
LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM9, 2, DMASrc[ARMCPU_ARM9][2], DMADst[ARMCPU_ARM9][2], (val&(1<<25))?"ON":"OFF");
}
#endif
}
write_dma_hictrl<ARMCPU_ARM9>(2,val);
return;
case REG_DMA3CNTH :
{
u32 v;
//if(val&0x8000) emu_halt();
//LOG("16 bit dma3 %04X\r\n", val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xDE, val);
DMASrc[ARMCPU_ARM9][3] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xD4);
DMADst[ARMCPU_ARM9][3] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xD8);
DMAtoVRAMmapping<3>();
v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xDC);
MMU.DMAStartTime[ARMCPU_ARM9][3] = (v>>27) & 0x7;
MMU.DMACrt[ARMCPU_ARM9][3] = v;
if(MMU.DMAStartTime[ARMCPU_ARM9][3] == 0)
MMU_doDMA<ARMCPU_ARM9>(3);
#ifdef LOG_DMA2
//else
{
LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM9, 3, DMASrc[ARMCPU_ARM9][3], DMADst[ARMCPU_ARM9][3], (val&(1<<25))?"ON":"OFF");
}
#endif
}
write_dma_hictrl<ARMCPU_ARM9>(3,val);
return;
//case REG_AUXSPICNT : emu_halt();
case REG_DISPA_DISPMMEMFIFO:
{
DISP_FIFOsend(val);
@ -2382,6 +2359,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
case REG_IME :
{
NDS_Reschedule();
u32 old_val = MMU.reg_IME[ARMCPU_ARM9];
u32 new_val = val & 0x01;
MMU.reg_IME[ARMCPU_ARM9] = new_val;
@ -2401,6 +2379,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
return;
case REG_IE :
NDS_Reschedule();
MMU.reg_IE[ARMCPU_ARM9] = val;
#ifndef NEW_IRQ
if ( MMU.reg_IME[ARMCPU_ARM9])
@ -2416,6 +2395,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
return;
case REG_IF :
NDS_Reschedule();
MMU.reg_IF[ARMCPU_ARM9] &= (~val);
return;
@ -2425,36 +2405,9 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
case REG_TM3CNTL:
{
int timerIndex = (adr>>2)&0x3;
int mask = ((val & 0x800000)>>(16+7)) << timerIndex;
MMU.CheckTimers = (MMU.CheckTimers & (~mask)) | mask;
MMU.timerReload[ARMCPU_ARM9][timerIndex] = (u16)val;
if(val&0x800000)
MMU.timer[ARMCPU_ARM9][timerIndex] = MMU.timerReload[ARMCPU_ARM9][(adr>>2)&0x3];
MMU.timerON[ARMCPU_ARM9][timerIndex] = val & 0x800000;
switch((val>>16)&7)
{
case 0 :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 0+1;//ARMCPU_ARM9;
break;
case 1 :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 6+1;//ARMCPU_ARM9;
break;
case 2 :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 8+1;//ARMCPU_ARM9;
break;
case 3 :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 10+1;//ARMCPU_ARM9;
break;
default :
MMU.timerMODE[ARMCPU_ARM9][timerIndex] = 0xFFFF;
break;
}
if(!(val & 0x800000))
MMU.timerRUN[ARMCPU_ARM9][timerIndex] = FALSE;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], adr & 0xFFF, val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], adr & 0xFFF, val);
write_timer(ARMCPU_ARM9, timerIndex, val>>16);
return;
}
@ -2492,77 +2445,20 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
return;
case REG_DMA0CNTL :
//LOG("32 bit dma0 %04X\r\n", val);
DMASrc[ARMCPU_ARM9][0] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xB0);
DMADst[ARMCPU_ARM9][0] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xB4);
DMAtoVRAMmapping<0>();
MMU.DMAStartTime[ARMCPU_ARM9][0] = (val>>27) & 0x7;
MMU.DMACrt[ARMCPU_ARM9][0] = val;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xB8, val);
if( MMU.DMAStartTime[ARMCPU_ARM9][0] == 0 ||
MMU.DMAStartTime[ARMCPU_ARM9][0] == 7) // Start Immediately
MMU_doDMA<ARMCPU_ARM9>(0);
#ifdef LOG_DMA2
else
{
LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X start taille %d %d\r\n", ARMCPU_ARM9, 0, DMASrc[ARMCPU_ARM9][0], DMADst[ARMCPU_ARM9][0], 0, ((MMU.DMACrt[ARMCPU_ARM9][0]>>27)&7));
}
#endif
//emu_halt();
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xB8, val); //write the low word
write_dma_hictrl<ARMCPU_ARM9>(0,val>>16);
return;
case REG_DMA1CNTL:
//LOG("32 bit dma1 %04X\r\n", val);
DMASrc[ARMCPU_ARM9][1] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xBC);
DMADst[ARMCPU_ARM9][1] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC0);
DMAtoVRAMmapping<1>();
MMU.DMAStartTime[ARMCPU_ARM9][1] = (val>>27) & 0x7;
MMU.DMACrt[ARMCPU_ARM9][1] = val;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC4, val);
if(MMU.DMAStartTime[ARMCPU_ARM9][1] == 0 ||
MMU.DMAStartTime[ARMCPU_ARM9][1] == 7) // Start Immediately
MMU_doDMA<ARMCPU_ARM9>(1);
#ifdef LOG_DMA2
else
{
LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X start taille %d %d\r\n", ARMCPU_ARM9, 1, DMASrc[ARMCPU_ARM9][1], DMADst[ARMCPU_ARM9][1], 0, ((MMU.DMACrt[ARMCPU_ARM9][1]>>27)&7));
}
#endif
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC4, val); //write the low word
write_dma_hictrl<ARMCPU_ARM9>(1,val>>16);
return;
case REG_DMA2CNTL :
//LOG("32 bit dma2 %04X\r\n", val);
DMASrc[ARMCPU_ARM9][2] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xC8);
DMADst[ARMCPU_ARM9][2] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xCC);
DMAtoVRAMmapping<2>();
MMU.DMAStartTime[ARMCPU_ARM9][2] = (val>>27) & 0x7;
MMU.DMACrt[ARMCPU_ARM9][2] = val;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xD0, val);
if(MMU.DMAStartTime[ARMCPU_ARM9][2] == 0 ||
MMU.DMAStartTime[ARMCPU_ARM9][2] == 7) // Start Immediately
MMU_doDMA<ARMCPU_ARM9>(2);
#ifdef LOG_DMA2
else
{
LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X start taille %d %d\r\n", ARMCPU_ARM9, 2, DMASrc[ARMCPU_ARM9][2], DMADst[ARMCPU_ARM9][2], 0, ((MMU.DMACrt[ARMCPU_ARM9][2]>>27)&7));
}
#endif
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xD0, val); //write the low word
write_dma_hictrl<ARMCPU_ARM9>(2,val>>16);
return;
case REG_DMA3CNTL :
//LOG("32 bit dma3 %04X\r\n", val);
DMASrc[ARMCPU_ARM9][3] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xD4);
DMADst[ARMCPU_ARM9][3] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xD8);
DMAtoVRAMmapping<3>();
MMU.DMAStartTime[ARMCPU_ARM9][3] = (val>>27) & 0x7;
MMU.DMACrt[ARMCPU_ARM9][3] = val;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xDC, val);
if( MMU.DMAStartTime[ARMCPU_ARM9][3] == 0 ||
MMU.DMAStartTime[ARMCPU_ARM9][3] == 7) // Start Immediately
MMU_doDMA<ARMCPU_ARM9>(3);
#ifdef LOG_DMA2
else
{
LOG("ARMCPU_ARM9 %d, dma %d src %08X dst %08X start taille %d %d\r\n", ARMCPU_ARM9, 3, DMASrc[ARMCPU_ARM9][3], DMADst[ARMCPU_ARM9][3], 0, ((MMU.DMACrt[ARMCPU_ARM9][3]>>27)&7));
}
#endif
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0xDC, val); //write the low word
write_dma_hictrl<ARMCPU_ARM9>(3,val>>16);
return;
case REG_GCROMCTRL :
{
@ -2640,23 +2536,11 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
val |= 0x00800000;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x1A4, val);
/* launch DMA if start flag was set to "DS Cart" */
if(MMU.DMAStartTime[ARMCPU_ARM9][0] == 5)
{
MMU_doDMA<ARMCPU_ARM9>(0);
}
if(MMU.DMAStartTime[ARMCPU_ARM9][1] == 5)
{
MMU_doDMA<ARMCPU_ARM9>(1);
}
if(MMU.DMAStartTime[ARMCPU_ARM9][2] == 5)
{
MMU_doDMA<ARMCPU_ARM9>(2);
}
if(MMU.DMAStartTime[ARMCPU_ARM9][3] == 5)
{
MMU_doDMA<ARMCPU_ARM9>(3);
}
//launch DMA if start flag was set to "DS Cart"
if(MMU.DMAStartTime[ARMCPU_ARM9][0] == EDMAMode_Card) MMU_doDMA<ARMCPU_ARM9>(0);
if(MMU.DMAStartTime[ARMCPU_ARM9][1] == EDMAMode_Card) MMU_doDMA<ARMCPU_ARM9>(1);
if(MMU.DMAStartTime[ARMCPU_ARM9][2] == EDMAMode_Card) MMU_doDMA<ARMCPU_ARM9>(2);
if(MMU.DMAStartTime[ARMCPU_ARM9][3] == EDMAMode_Card) MMU_doDMA<ARMCPU_ARM9>(3);
}
return;
case REG_DISPA_DISPCAPCNT :
@ -2768,7 +2652,7 @@ u16 FASTCALL _MMU_ARM9_read16(u32 adr)
case REG_TM1CNTL :
case REG_TM2CNTL :
case REG_TM3CNTL :
return MMU.timer[ARMCPU_ARM9][(adr&0xF)>>2];
return read_timer(ARMCPU_ARM9,(adr&0xF)>>2);
case REG_AUXSPICNT:
return MMU.AUX_SPI_CNT;
@ -3246,6 +3130,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
case REG_IME :
{
NDS_Reschedule();
u32 old_val = MMU.reg_IME[ARMCPU_ARM7];
u32 new_val = val & 1;
MMU.reg_IME[ARMCPU_ARM7] = new_val;
@ -3264,6 +3149,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
return;
}
case REG_IE :
NDS_Reschedule();
MMU.reg_IE[ARMCPU_ARM7] = (MMU.reg_IE[ARMCPU_ARM7]&0xFFFF0000) | val;
#ifndef NEW_IRQ
if ( MMU.reg_IME[ARMCPU_ARM7])
@ -3278,6 +3164,7 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
#endif
return;
case REG_IE + 2 :
NDS_Reschedule();
//emu_halt();
MMU.reg_IE[ARMCPU_ARM7] = (MMU.reg_IE[ARMCPU_ARM7]&0xFFFF) | (((u32)val)<<16);
#ifndef NEW_IRQ
@ -3294,10 +3181,12 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
return;
case REG_IF :
NDS_Reschedule();
//emu_halt();
MMU.reg_IF[ARMCPU_ARM7] &= (~((u32)val));
return;
case REG_IF + 2 :
NDS_Reschedule();
//emu_halt();
MMU.reg_IF[ARMCPU_ARM7] &= (~(((u32)val)<<16));
return;
@ -3321,127 +3210,22 @@ void FASTCALL _MMU_ARM7_write16(u32 adr, u16 val)
case REG_TM3CNTH :
{
int timerIndex = ((adr-2)>>2)&0x3;
int mask = ((val&0x80)>>7) << (timerIndex+(ARMCPU_ARM7<<2));
MMU.CheckTimers = (MMU.CheckTimers & (~mask)) | mask;
if(val&0x80)
MMU.timer[ARMCPU_ARM7][timerIndex] = MMU.timerReload[ARMCPU_ARM7][((adr-2)>>2)&0x3];
MMU.timerON[ARMCPU_ARM7][((adr-2)>>2)&0x3] = val & 0x80;
switch(val&7)
{
case 0 :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 0+1;//ARMCPU_ARM7;
break;
case 1 :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 6+1;//ARMCPU_ARM7;
break;
case 2 :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 8+1;//ARMCPU_ARM7;
break;
case 3 :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 10+1;//ARMCPU_ARM7;
break;
default :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 0xFFFF;
break;
}
if(!(val & 0x80))
MMU.timerRUN[ARMCPU_ARM7][timerIndex] = FALSE;
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], adr & 0xFFF, val);
write_timer(ARMCPU_ARM7, timerIndex, val);
return;
}
case REG_DMA0CNTH :
{
u32 v;
//if(val&0x8000) emu_halt();
//LOG("16 bit dma0 %04X\r\n", val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xBA, val);
DMASrc[ARMCPU_ARM7][0] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xB0);
DMADst[ARMCPU_ARM7][0] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xB4);
v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xB8);
MMU.DMAStartTime[ARMCPU_ARM7][0] = (v>>28) & 0x3;
MMU.DMACrt[ARMCPU_ARM7][0] = v;
if(MMU.DMAStartTime[ARMCPU_ARM7][0] == 0)
MMU_doDMA<ARMCPU_ARM7>(0);
#ifdef LOG_DMA2
//else
{
LOG("ARMCPU_ARM7 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM7, 0, DMASrc[ARMCPU_ARM7][0], DMADst[ARMCPU_ARM7][0], (val&(1<<25))?"ON":"OFF");
}
#endif
}
write_dma_hictrl<ARMCPU_ARM7>(0,val);
return;
case REG_DMA1CNTH :
{
u32 v;
//if(val&0x8000) emu_halt();
//LOG("16 bit dma1 %04X\r\n", val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xC6, val);
DMASrc[ARMCPU_ARM7][1] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xBC);
DMADst[ARMCPU_ARM7][1] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xC0);
v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xC4);
MMU.DMAStartTime[ARMCPU_ARM7][1] = (v>>28) & 0x3;
MMU.DMACrt[ARMCPU_ARM7][1] = v;
if(MMU.DMAStartTime[ARMCPU_ARM7][1] == 0)
MMU_doDMA<ARMCPU_ARM7>(1);
#ifdef LOG_DMA2
//else
{
LOG("ARMCPU_ARM7 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM7, 1, DMASrc[ARMCPU_ARM7][1], DMADst[ARMCPU_ARM7][1], (val&(1<<25))?"ON":"OFF");
}
#endif
}
write_dma_hictrl<ARMCPU_ARM7>(1,val);
return;
case REG_DMA2CNTH :
{
u32 v;
//if(val&0x8000) emu_halt();
//LOG("16 bit dma2 %04X\r\n", val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xD2, val);
DMASrc[ARMCPU_ARM7][2] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xC8);
DMADst[ARMCPU_ARM7][2] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xCC);
v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xD0);
MMU.DMAStartTime[ARMCPU_ARM7][2] = (v>>28) & 0x3;
MMU.DMACrt[ARMCPU_ARM7][2] = v;
if(MMU.DMAStartTime[ARMCPU_ARM7][2] == 0)
MMU_doDMA<ARMCPU_ARM7>(2);
#ifdef LOG_DMA2
//else
{
LOG("ARMCPU_ARM7 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM7, 2, DMASrc[ARMCPU_ARM7][2], DMADst[ARMCPU_ARM7][2], (val&(1<<25))?"ON":"OFF");
}
#endif
}
write_dma_hictrl<ARMCPU_ARM7>(2,val);
return;
case REG_DMA3CNTH :
{
u32 v;
//if(val&0x8000) emu_halt();
//LOG("16 bit dma3 %04X\r\n", val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xDE, val);
DMASrc[ARMCPU_ARM7][3] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xD4);
DMADst[ARMCPU_ARM7][3] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xD8);
v = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xDC);
MMU.DMAStartTime[ARMCPU_ARM7][3] = (v>>28) & 0x3;
MMU.DMACrt[ARMCPU_ARM7][3] = v;
if(MMU.DMAStartTime[ARMCPU_ARM7][3] == 0)
MMU_doDMA<ARMCPU_ARM7>(3);
#ifdef LOG_DMA2
//else
{
LOG("ARMCPU_ARM7 %d, dma %d src %08X dst %08X %s\r\n", ARMCPU_ARM7, 3, DMASrc[ARMCPU_ARM7][3], DMADst[ARMCPU_ARM7][3], (val&(1<<25))?"ON":"OFF");
}
#endif
}
write_dma_hictrl<ARMCPU_ARM7>(3,val);
return;
//case REG_AUXSPICNT : emu_halt();
}
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], adr&MMU.MMU_MASK[ARMCPU_ARM7][adr>>20], val);
@ -3497,6 +3281,7 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
case REG_IME :
{
NDS_Reschedule();
u32 old_val = MMU.reg_IME[ARMCPU_ARM7];
u32 new_val = val & 1;
MMU.reg_IME[ARMCPU_ARM7] = new_val;
@ -3516,6 +3301,7 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
}
case REG_IE :
NDS_Reschedule();
MMU.reg_IE[ARMCPU_ARM7] = val;
#ifndef NEW_IRQ
if ( MMU.reg_IME[ARMCPU_ARM7])
@ -3531,6 +3317,7 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
return;
case REG_IF :
NDS_Reschedule();
MMU.reg_IF[ARMCPU_ARM7] &= (~val);
return;
@ -3540,38 +3327,13 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
case REG_TM3CNTL:
{
int timerIndex = (adr>>2)&0x3;
int mask = ((val & 0x800000)>>(16+7)) << (timerIndex+(ARMCPU_ARM7<<2));
MMU.CheckTimers = (MMU.CheckTimers & (~mask)) | mask;
MMU.timerReload[ARMCPU_ARM7][timerIndex] = (u16)val;
if(val&0x800000)
MMU.timer[ARMCPU_ARM7][timerIndex] = MMU.timerReload[ARMCPU_ARM7][(adr>>2)&0x3];
MMU.timerON[ARMCPU_ARM7][timerIndex] = val & 0x800000;
switch((val>>16)&7)
{
case 0 :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 0+1;//ARMCPU_ARM7;
break;
case 1 :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 6+1;//ARMCPU_ARM7;
break;
case 2 :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 8+1;//ARMCPU_ARM7;
break;
case 3 :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 10+1;//ARMCPU_ARM7;
break;
default :
MMU.timerMODE[ARMCPU_ARM7][timerIndex] = 0xFFFF;
break;
}
if(!(val & 0x800000))
MMU.timerRUN[ARMCPU_ARM7][timerIndex] = FALSE;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], adr & 0xFFF, val);
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], adr & 0xFFF, val);
write_timer(ARMCPU_ARM7, timerIndex, val>>16);
return;
}
case REG_IPCSYNC :
MMU_IPCSync(ARMCPU_ARM7, val);
return;
@ -3579,75 +3341,24 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
case REG_IPCFIFOSEND :
IPC_FIFOsend(ARMCPU_ARM7, val);
return;
case REG_DMA0CNTL :
//LOG("32 bit dma0 %04X\r\n", val);
DMASrc[ARMCPU_ARM7][0] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xB0);
DMADst[ARMCPU_ARM7][0] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xB4);
MMU.DMAStartTime[ARMCPU_ARM7][0] = (val>>28) & 0x3;
MMU.DMACrt[ARMCPU_ARM7][0] = val;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xB8, val);
if( MMU.DMAStartTime[ARMCPU_ARM7][0] == 0 ||
MMU.DMAStartTime[ARMCPU_ARM7][0] == 7) // Start Immediately
MMU_doDMA<ARMCPU_ARM7>(0);
#ifdef LOG_DMA2
else
{
LOG("ARMCPU_ARM7 %d, dma %d src %08X dst %08X start taille %d %d\r\n", ARMCPU_ARM7, 0, DMASrc[ARMCPU_ARM7][0], DMADst[ARMCPU_ARM7][0], 0, ((MMU.DMACrt[ARMCPU_ARM7][0]>>27)&7));
}
#endif
//emu_halt();
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xB8, val); //write the low word
write_dma_hictrl<ARMCPU_ARM7>(0,val>>16);
return;
case REG_DMA1CNTL:
//LOG("32 bit dma1 %04X\r\n", val);
DMASrc[ARMCPU_ARM7][1] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xBC);
DMADst[ARMCPU_ARM7][1] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xC0);
MMU.DMAStartTime[ARMCPU_ARM7][1] = (val>>28) & 0x3;
MMU.DMACrt[ARMCPU_ARM7][1] = val;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xC4, val);
if(MMU.DMAStartTime[ARMCPU_ARM7][1] == 0 ||
MMU.DMAStartTime[ARMCPU_ARM7][1] == 7) // Start Immediately
MMU_doDMA<ARMCPU_ARM7>(1);
#ifdef LOG_DMA2
else
{
LOG("ARMCPU_ARM7 %d, dma %d src %08X dst %08X start taille %d %d\r\n", ARMCPU_ARM7, 1, DMASrc[ARMCPU_ARM7][1], DMADst[ARMCPU_ARM7][1], 0, ((MMU.DMACrt[ARMCPU_ARM7][1]>>27)&7));
}
#endif
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xC4, val); //write the low word
write_dma_hictrl<ARMCPU_ARM7>(1,val>>16);
return;
case REG_DMA2CNTL :
//LOG("32 bit dma2 %04X\r\n", val);
DMASrc[ARMCPU_ARM7][2] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xC8);
DMADst[ARMCPU_ARM7][2] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xCC);
MMU.DMAStartTime[ARMCPU_ARM7][2] = (val>>28) & 0x3;
MMU.DMACrt[ARMCPU_ARM7][2] = val;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xD0, val);
if(MMU.DMAStartTime[ARMCPU_ARM7][2] == 0 ||
MMU.DMAStartTime[ARMCPU_ARM7][2] == 7) // Start Immediately
MMU_doDMA<ARMCPU_ARM7>(2);
#ifdef LOG_DMA2
else
{
LOG("ARMCPU_ARM7 %d, dma %d src %08X dst %08X start taille %d %d\r\n", ARMCPU_ARM7, 2, DMASrc[ARMCPU_ARM7][2], DMADst[ARMCPU_ARM7][2], 0, ((MMU.DMACrt[ARMCPU_ARM7][2]>>27)&7));
}
#endif
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xD0, val); //write the low word
write_dma_hictrl<ARMCPU_ARM7>(2,val>>16);
return;
case REG_DMA3CNTL :
//LOG("32 bit dma3 %04X\r\n", val);
DMASrc[ARMCPU_ARM7][3] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xD4);
DMADst[ARMCPU_ARM7][3] = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xD8);
MMU.DMAStartTime[ARMCPU_ARM7][3] = (val>>28) & 0x3;
MMU.DMACrt[ARMCPU_ARM7][3] = val;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xDC, val);
if( MMU.DMAStartTime[ARMCPU_ARM7][3] == 0 ||
MMU.DMAStartTime[ARMCPU_ARM7][3] == 7) // Start Immediately
MMU_doDMA<ARMCPU_ARM7>(3);
#ifdef LOG_DMA2
else
{
LOG("ARMCPU_ARM7 %d, dma %d src %08X dst %08X start taille %d %d\r\n", ARMCPU_ARM7, 3, DMASrc[ARMCPU_ARM7][3], DMADst[ARMCPU_ARM7][3], 0, ((MMU.DMACrt[ARMCPU_ARM7][3]>>27)&7));
}
#endif
T1WriteWord(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0xDC, val); //write the low word
write_dma_hictrl<ARMCPU_ARM7>(3,val>>16);
return;
case REG_GCROMCTRL :
{
if(!(val & 0x80000000))
@ -3707,16 +3418,11 @@ void FASTCALL _MMU_ARM7_write32(u32 adr, u32 val)
val |= 0x00800000;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM7][0x40], 0x1A4, val);
/* launch DMA if start flag was set to "DS Cart" */
if(MMU.DMAStartTime[ARMCPU_ARM7][2] == 2)
{
MMU_doDMA<ARMCPU_ARM7>(2);
}
if(MMU.DMAStartTime[ARMCPU_ARM7][3] == 2)
{
MMU_doDMA<ARMCPU_ARM7>(3);
}
//launch DMA if start flag was set to "DS Cart"
if(MMU.DMAStartTime[ARMCPU_ARM7][0] == EDMAMode_Card) MMU_doDMA<ARMCPU_ARM7>(0);
if(MMU.DMAStartTime[ARMCPU_ARM7][1] == EDMAMode_Card) MMU_doDMA<ARMCPU_ARM7>(1);
if(MMU.DMAStartTime[ARMCPU_ARM7][2] == EDMAMode_Card) MMU_doDMA<ARMCPU_ARM7>(2);
if(MMU.DMAStartTime[ARMCPU_ARM7][3] == EDMAMode_Card) MMU_doDMA<ARMCPU_ARM7>(3);
return;
@ -3803,7 +3509,7 @@ u16 FASTCALL _MMU_ARM7_read16(u32 adr)
case REG_TM1CNTL :
case REG_TM2CNTL :
case REG_TM3CNTL :
return MMU.timer[ARMCPU_ARM7][(adr&0xF)>>2];
return read_timer(ARMCPU_ARM7,(adr&0xF)>>2);
case REG_AUXSPICNT:
return MMU.AUX_SPI_CNT;

View File

@ -97,7 +97,7 @@ struct MMU_struct {
u32 reg_IF[2];
u32 DMAStartTime[2][4];
s32 DMACycle[2][4];
u64 DMACycle[2][4];
u32 DMACrt[2][4];
BOOL DMAing[2][4];
@ -105,21 +105,19 @@ struct MMU_struct {
s64 divResult;
s64 divMod;
u32 divCnt;
s32 divCycles;
u64 divCycles;
BOOL sqrtRunning;
u32 sqrtResult;
u32 sqrtCnt;
s32 sqrtCycles;
u64 sqrtCycles;
u16 SPI_CNT;
u16 SPI_CMD;
u16 AUX_SPI_CNT;
u16 AUX_SPI_CMD;
#ifdef USE_GEOMETRY_FIFO_EMULATION
s32 gfx3dCycles;
#endif
u64 gfx3dCycles;
u8 powerMan_CntReg;
BOOL powerMan_CntRegWritten;
@ -265,6 +263,20 @@ inline void SetupMMU(bool debugConsole) {
//T1ReadWord(MMU.MMU_MEM[ARMCPU_ARM7][(adr >> 20) & 0xFF],
// adr & MMU.MMU_MASK[ARMCPU_ARM7][(adr >> 20) & 0xFF]);
enum EDMAMode
{
EDMAMode_Immediate = 0,
EDMAMode_VBlank = 1,
EDMAMode_HBlank = 2,
EDMAMode_HStart = 3,
EDMAMode_MemDisplay = 4,
EDMAMode_Card = 5,
EDMAMode_GBASlot = 6,
EDMAMode_GXFifo = 7,
EDMAMode7_Wifi = 8,
EDMAMode7_GBASlot = 9,
};
FORCEINLINE u8 _MMU_read08(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr)
{
//special handling for DMA: read 0 from TCM
@ -427,6 +439,10 @@ FORCEINLINE void _MMU_write16(const int PROCNUM, const MMU_ACCESS_TYPE AT, const
FORCEINLINE void _MMU_write32(const int PROCNUM, const MMU_ACCESS_TYPE AT, const u32 addr, u32 val)
{
if(addr == 0x022D7900)
{
int zzz=9;
}
//special handling for DMA: discard writes to TCM
if(PROCNUM==ARMCPU_ARM9 && AT == MMU_AT_DMA)
{

File diff suppressed because it is too large Load Diff

View File

@ -173,19 +173,19 @@ struct NDS_header
extern void debug();
void emu_halt();
extern u64 nds_timer;
void NDS_Reschedule();
void NDS_RescheduleGXFIFO();
void NDS_RescheduleDMA();
void NDS_RescheduleTimers();
typedef struct
{
s32 ARM9Cycle;
s32 ARM7Cycle;
s32 wifiCycle;
s32 cycles;
s32 timerCycle[2][4];
BOOL timerOver[2][4];
s32 nextHBlank;
u64 timerCycle[2][4];
u32 VCount;
u32 old;
s32 diff;
BOOL lignerendu;
u16 touchX;
u16 touchY;

View File

@ -318,7 +318,7 @@ u32 armcpu_switchMode(armcpu_t *armcpu, u8 mode)
case FIQ :
{
u32 tmp;
u32 tmp;
SWAP(armcpu->R[8], armcpu->R8_fiq, tmp);
SWAP(armcpu->R[9], armcpu->R9_fiq, tmp);
SWAP(armcpu->R[10], armcpu->R10_fiq, tmp);

View File

@ -234,6 +234,8 @@ static INLINE void setIF(int PROCNUM, u32 flag)
if(ARMPROC.waitIRQ)
ARMPROC.newIrqFlags |= flag;
extern void NDS_Reschedule();
NDS_Reschedule();
}
static INLINE void NDS_makeARM9Int(u32 num)

View File

@ -161,4 +161,4 @@ std::string GetRomNameWithoutExtension()
if (x > 0)
return RomName.substr(0,x);
else return RomName;
}
}

View File

@ -61,8 +61,10 @@ in this function: */
static void gfx3d_doFlush();
#ifdef USE_GEOMETRY_FIFO_EMULATION
#define GFX_DELAY(x) MMU.gfx3dCycles = nds.cycles + (2*x)
#define GFX_DELAY_M2(x) MMU.gfx3dCycles += (2*x)
inline void GFX_DELAY(int x) {
MMU.gfx3dCycles = nds_timer + (2*x); NDS_RescheduleGXFIFO(); }
inline void GFX_DELAY_M2(int x) {
MMU.gfx3dCycles += (2*x); NDS_RescheduleGXFIFO(); }
#else
#define GFX_DELAY(x)
#define GFX_DELAY_M2(x)

View File

@ -85,6 +85,8 @@ int write32le(u32 b, std::ostream* os)
return 4;
}
void writebool(bool b, std::ostream* os) { write32le(b?1:0,os); }
int write64le(u64 b, std::ostream* os)
{
u8 s[8];
@ -155,6 +157,14 @@ int read32le(u32 *Bufo, std::istream *is)
return 1;
}
int readbool(bool *b, std::istream* is)
{
u32 temp;
int ret = read32le(&temp,is);
*b = (bool)temp;
return ret;
}
int readbuffer(std::vector<u8> &vec, std::istream* is)
{
u32 size;

View File

@ -21,6 +21,8 @@ int read32le(u32 *Bufo, FILE *fp);
int read16le(u16 *Bufo, std::istream *is);
inline int read16le(s16 *Bufo, std::istream* is) { return read16le((u16*)Bufo,is); }
int read8le(u8 *Bufo, std::istream *is);
int readbool(bool *b, std::istream* is);
void writebool(bool b, std::ostream* os);
int readbuffer(std::vector<u8> &vec, std::istream* is);
int writebuffer(std::vector<u8>& vec, std::ostream* os);

View File

@ -52,7 +52,7 @@ int lastSaveState = 0; //Keeps track of last savestate used for quick save/load
savestates_t savestates[NB_STATES];
#define SAVESTATE_VERSION 11
#define SAVESTATE_VERSION 12
static const char* magic = "DeSmuME SState\0";
//a savestate chunk loader can set this if it wants to permit a silent failure (for compatibility)
@ -161,17 +161,10 @@ SFORMAT SF_MEM[]={
};
SFORMAT SF_NDS[]={
{ "_9CY", 4, 1, &nds.ARM9Cycle},
{ "_7CY", 4, 1, &nds.ARM7Cycle},
{ "_CYC", 4, 1, &nds.cycles},
{ "_WCY", 4, 1, &nds.wifiCycle},
{ "_TCY", 4, 8, nds.timerCycle},
{ "_TOV", 4, 8, nds.timerOver},
{ "_NHB", 4, 1, &nds.nextHBlank},
{ "_TCY", 8, 8, nds.timerCycle},
{ "_VCT", 4, 1, &nds.VCount},
{ "_OLD", 4, 1, &nds.old},
{ "_DIF", 4, 1, &nds.diff},
{ "_LIG", 4, 1, &nds.lignerendu},
{ "_TPX", 2, 1, &nds.touchX},
{ "_TPY", 2, 1, &nds.touchY},
{ "_TPB", 4, 1, &nds.isTouch},
@ -200,6 +193,8 @@ SFORMAT SF_MMU[]={
{ "MIME", 4, 2, MMU.reg_IME},
{ "MIE_", 4, 2, MMU.reg_IE},
{ "MIF_", 4, 2, MMU.reg_IF},
{ "MGXC", 8, 1, &MMU.gfx3dCycles},
{ "M_SX", 1, 2, &MMU.SPI_CNT},
{ "M_SC", 1, 2, &MMU.SPI_CMD},
@ -207,7 +202,7 @@ SFORMAT SF_MMU[]={
{ "MASC", 1, 2, &MMU.AUX_SPI_CMD},
{ "MDST", 4, 8, MMU.DMAStartTime},
{ "MDCY", 4, 8, MMU.DMACycle},
{ "MDCY", 8, 8, MMU.DMACycle},
{ "MDCR", 4, 8, MMU.DMACrt},
{ "MDMA", 4, 8, MMU.DMAing},
{ "MDSR", 4, 8, DMASrc},
@ -217,12 +212,12 @@ SFORMAT SF_MMU[]={
{ "MDV2", 8, 1, &MMU.divResult},
{ "MDV3", 8, 1, &MMU.divMod},
{ "MDV4", 4, 1, &MMU.divCnt},
{ "MDV5", 4, 1, &MMU.divCycles},
{ "MDV5", 8, 1, &MMU.divCycles},
{ "MSQ1", 4, 1, &MMU.sqrtRunning},
{ "MSQ2", 4, 1, &MMU.sqrtResult},
{ "MSQ3", 4, 1, &MMU.sqrtCnt},
{ "MSQ4", 4, 1, &MMU.sqrtCycles},
{ "MSQ4", 8, 1, &MMU.sqrtCycles},
//begin memory chips
//we are skipping the firmware, because we really don't want to save the firmware to the savestate
@ -262,6 +257,9 @@ SFORMAT SF_MOVIE[]={
{ 0 }
};
void nds_savestate(std::ostream* os);
bool nds_loadstate(std::istream* is, int size);
static void mmu_savestate(std::ostream* os)
{
//version
@ -824,6 +822,7 @@ static void writechunks(std::ostream* os) {
savestate_WriteChunk(os,3,cp15_savestate);
savestate_WriteChunk(os,4,SF_MEM);
savestate_WriteChunk(os,5,SF_NDS);
savestate_WriteChunk(os,51,nds_savestate);
savestate_WriteChunk(os,60,SF_MMU);
savestate_WriteChunk(os,61,mmu_savestate);
savestate_WriteChunk(os,7,gpu_savestate);
@ -852,6 +851,7 @@ static bool ReadStateChunks(std::istream* is, s32 totalsize)
case 3: if(!cp15_loadstate(is,size)) ret=false; break;
case 4: if(!ReadStateChunk(is,SF_MEM,size)) ret=false; break;
case 5: if(!ReadStateChunk(is,SF_NDS,size)) ret=false; break;
case 51: if(!nds_loadstate(is,size)) ret=false; break;
case 60: if(!ReadStateChunk(is,SF_MMU,size)) ret=false; break;
case 61: if(!mmu_loadstate(is,size)) ret=false; break;
case 7: if(!gpu_loadstate(is,size)) ret=false; break;

View File

@ -105,7 +105,7 @@
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long u64;
typedef unsigned long long u64;
typedef signed char s8;
typedef signed short s16;

View File

@ -594,6 +594,22 @@
>
</File>
</Filter>
<Filter
Name="filter"
>
<File
RelativePath=".\filter\2xsai.cpp"
>
</File>
<File
RelativePath=".\filter\hq2x.cpp"
>
</File>
<File
RelativePath=".\filter\scanline.cpp"
>
</File>
</Filter>
</Filter>
<Filter
Name="utils"
@ -750,10 +766,6 @@
>
</File>
</Filter>
<File
RelativePath=".\filter\2xsai.cpp"
>
</File>
<File
RelativePath="..\addons.cpp"
>
@ -958,10 +970,6 @@
RelativePath="..\GPU_osd.h"
>
</File>
<File
RelativePath=".\filter\hq2x.cpp"
>
</File>
<File
RelativePath="..\lua-engine.cpp"
>
@ -1090,10 +1098,6 @@
RelativePath="..\saves.h"
>
</File>
<File
RelativePath=".\filter\scanline.cpp"
>
</File>
<File
RelativePath="..\shaders.h"
>

View File

@ -924,8 +924,8 @@ DWORD WINAPI run()
for(int i=0;i<16;i++)
load = load/8 + nds.runCycleCollector[(i+nds.idleFrameCounter)&15]*7/8;
load = std::min(100,std::max(0,(int)(load*100/1120380)));
sprintf(txt,"(%02d%%) %s", load, DESMUME_NAME_AND_VERSION);
SetWindowText(hwnd, txt);
//sprintf(txt,"(%02d%%) %s", load, DESMUME_NAME_AND_VERSION);
SetWindowText(hwnd, DESMUME_NAME_AND_VERSION);
}
if(!skipnextframe)