diff --git a/desmume/src/FIFO.c b/desmume/src/FIFO.c index b49de3c87..b1cbdc2b0 100644 --- a/desmume/src/FIFO.c +++ b/desmume/src/FIFO.c @@ -27,7 +27,7 @@ void FIFOInit(FIFO * fifo) fifo->begin = 0; fifo->end = 0; - for(i = 0; i<0x2000; ++i) + for(i = 0; i<0x8000; ++i) fifo->data[i] = 0; fifo->full = FALSE; fifo->empty = TRUE; @@ -42,7 +42,7 @@ void FIFOAdd(FIFO * fifo, u32 v) return; } fifo->data[fifo->end] = v; - fifo->end = (fifo->end + 1)& 0x1FFF; + fifo->end = (fifo->end + 1)& 0x7FFF; fifo->full = (fifo->end == fifo->begin); fifo->empty = FALSE; } @@ -57,7 +57,7 @@ u32 FIFOValue(FIFO * fifo) return 0; } v = fifo->data[fifo->begin]; - fifo->begin = (fifo->begin + 1)& 0x1FFF; + fifo->begin = (fifo->begin + 1)& 0x7FFF; fifo->empty = (fifo->begin == fifo->end); return v; } diff --git a/desmume/src/FIFO.h b/desmume/src/FIFO.h index 0bc6eb095..5010819ee 100644 --- a/desmume/src/FIFO.h +++ b/desmume/src/FIFO.h @@ -30,7 +30,7 @@ extern "C" { typedef struct { - u32 data[0x2000]; + u32 data[0x8000]; u32 begin; u32 end; BOOL full; diff --git a/desmume/src/GPU.c b/desmume/src/GPU.c index 1fca45e5f..ed21e1117 100644 --- a/desmume/src/GPU.c +++ b/desmume/src/GPU.c @@ -24,6 +24,7 @@ #include #include +#include "MMU.h" #include "GPU.h" #include "debug.h" diff --git a/desmume/src/GPU.h b/desmume/src/GPU.h index 97a497e0a..e75c22c3a 100644 --- a/desmume/src/GPU.h +++ b/desmume/src/GPU.h @@ -270,6 +270,8 @@ void Screen_Init(void); void Screen_Reset(void); void Screen_DeInit(void); +extern MMU_struct MMU; + static INLINE void GPU_ligne(Screen * screen, u16 l) { GPU * gpu = screen->gpu; @@ -307,11 +309,13 @@ static INLINE void GPU_ligne(Screen * screen, u16 l) } return; } - case 3: - // it is just a wild wild guess (WWG) - // I dont need a game using this mode ... + case 3: + // Read from FIFO MAIN_MEMORY_DISP_FIFO, two pixels + // at once format is 5bit per component, bit15 unused + // Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode + // (under DISP_MMEM_FIFO) for (i=0; i<256;) { - c = FIFOValue(REG_DISPA_DISPMMEMFIFO); + c = FIFOValue(MMU.fifos + MAIN_MEMORY_DISP_FIFO); T2WriteWord(dst, i << 1, c&0xFFFF); i++; T2WriteWord(dst, i << 1, c>>16); i++; } diff --git a/desmume/src/MMU.c b/desmume/src/MMU.c index 191a8f4b3..608961a81 100644 --- a/desmume/src/MMU.c +++ b/desmume/src/MMU.c @@ -1944,7 +1944,7 @@ void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) MMU.DMAStartTime[proc][0] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); MMU.DMACrt[proc][0] = val; T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xB8, val); - if(MMU.DMAStartTime[proc][0] == 0) + if( MMU.DMAStartTime[proc][0] == 0) // Start Immediately MMU_doDMA(proc, 0); #ifdef LOG_DMA2 else @@ -1961,7 +1961,7 @@ void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) MMU.DMAStartTime[proc][1] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); MMU.DMACrt[proc][1] = val; T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xC4, val); - if(MMU.DMAStartTime[proc][1] == 0) + if(MMU.DMAStartTime[proc][1] == 0) // Start Immediately MMU_doDMA(proc, 1); #ifdef LOG_DMA2 else @@ -1977,7 +1977,7 @@ void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) MMU.DMAStartTime[proc][2] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); MMU.DMACrt[proc][2] = val; T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xD0, val); - if(MMU.DMAStartTime[proc][2] == 0) + if(MMU.DMAStartTime[proc][2] == 0) // Start Immediately MMU_doDMA(proc, 2); #ifdef LOG_DMA2 else @@ -1993,7 +1993,7 @@ void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) MMU.DMAStartTime[proc][3] = (proc ? (val>>28) & 0x3 : (val>>27) & 0x7); MMU.DMACrt[proc][3] = val; T1WriteLong(MMU.MMU_MEM[proc][0x40], 0xDC, val); - if(MMU.DMAStartTime[proc][3] == 0) + if( MMU.DMAStartTime[proc][3] == 0) // Start Immediately MMU_doDMA(proc, 3); #ifdef LOG_DMA2 else @@ -2091,6 +2091,15 @@ void FASTCALL MMU_write32(u32 proc, u32 adr, u32 val) GPU_setBLDCNT (SubScreen.gpu,val&0xffff); GPU_setBLDALPHA (SubScreen.gpu,val>>16); break; + + case REG_DISPA_DISPMMEMFIFO: + { + // NOTE: right now, the capture unit is not taken into account, + // I don't know is it should be handled here or + + FIFOAdd(MMU.fifos + MAIN_MEMORY_DISP_FIFO, val); + break; + } //case 0x21FDFF0 : if(val==0) execute = FALSE; //case 0x21FDFB0 : if(val==0) execute = FALSE; default : @@ -2122,8 +2131,18 @@ void FASTCALL MMU_doDMA(u32 proc, u32 num) return; } - /* word count */ - taille = (MMU.DMACrt[proc][num]&0xFFFF); + + /* word count */ + taille = (MMU.DMACrt[proc][num]&0xFFFF); + + // 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[proc][num]==4) && // Must be in main memory display mode + (taille==4) && // Word must be 4 + (((MMU.DMACrt[proc][num]>>26)&1) == 1)) // Transfer mode must be 32bit wide + taille = 256*192/2; if(MMU.DMAStartTime[proc][num] == 5) taille *= 0x80; diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index f6a022a82..0d1e3c730 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -42,6 +42,7 @@ extern char szRomBaseName[512]; #define ROM_8(m, a) (((u8*)(m))[(a)]) #define IPCFIFO 0 +#define MAIN_MEMORY_DISP_FIFO 2 typedef struct { //ARM7 mem diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index d698ce5db..94db14615 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -265,6 +265,49 @@ int NDS_LoadFirmware(const char *filename); MMU_doDMA(0, 2); if(MMU.DMAStartTime[0][3] == 3) MMU_doDMA(0, 3); + + // Main memory display + if(MMU.DMAStartTime[0][0] == 4) + { + MMU_doDMA(0, 0); + MMU.DMAStartTime[0][0] = 0; + } + if(MMU.DMAStartTime[0][1] == 4) + { + MMU_doDMA(0, 1); + MMU.DMAStartTime[0][1] = 0; + } + if(MMU.DMAStartTime[0][2] == 4) + { + MMU_doDMA(0, 2); + MMU.DMAStartTime[0][2] = 0; + } + if(MMU.DMAStartTime[0][3] == 4) + { + MMU_doDMA(0, 3); + MMU.DMAStartTime[0][3] = 0; + } + + if(MMU.DMAStartTime[1][0] == 4) + { + MMU_doDMA(1, 0); + MMU.DMAStartTime[1][0] = 0; + } + if(MMU.DMAStartTime[1][1] == 4) + { + MMU_doDMA(1, 1); + MMU.DMAStartTime[0][1] = 0; + } + if(MMU.DMAStartTime[1][2] == 4) + { + MMU_doDMA(1, 2); + MMU.DMAStartTime[1][2] = 0; + } + if(MMU.DMAStartTime[1][3] == 4) + { + MMU_doDMA(1, 3); + MMU.DMAStartTime[1][3] = 0; + } nds.lignerendu = FALSE; if(nds.VCount==193)