- fix FIFO;
This commit is contained in:
mtabachenko 2008-09-24 16:16:11 +00:00
parent 1755ca4178
commit d5502611e3
6 changed files with 162 additions and 120 deletions

View File

@ -23,37 +23,44 @@
#include "FIFO.h" #include "FIFO.h"
#include <string.h> #include <string.h>
#include "debug.h"
void FIFOInit(FIFO * fifo) void FIFOclear(FIFO * fifo)
{ {
memset(fifo,0,sizeof(FIFO)); memset(fifo,0,sizeof(FIFO));
fifo->empty = TRUE; fifo->empty = true;
} }
void FIFOAdd(FIFO * fifo, u32 v) void FIFOadd(FIFO *fifo, u32 val)
{ {
if(fifo->full) if (fifo->full)
{ {
fifo->error = TRUE; //printlog("!!!!! FIFOadd full\n");
fifo->error = true;
return; return;
} }
fifo->data[fifo->end] = v;
fifo->end = (fifo->end + 1)& 0x7FFF; fifo->buf[fifo->sendPos] = val;
fifo->full = (fifo->end == fifo->begin); fifo->sendPos = (fifo->sendPos+1) & 0x7FFF;
fifo->empty = FALSE; fifo->half = (fifo->sendPos < (sizeof(fifo->buf)>>1));
fifo->full = (fifo->sendPos == fifo->recvPos);
fifo->empty = false;
//printlog("-------------- FIFO add size=%i, val=%X\n",fifo->sendPos, val);
} }
u32 FIFOValue(FIFO * fifo) u32 FIFOget(FIFO * fifo)
{ {
u32 v; if (fifo->empty)
if(fifo->empty)
{ {
fifo->error = TRUE; //printlog("!!!!! FIFOget empty\n");
fifo->error = true;
return 0; return 0;
} }
v = fifo->data[fifo->begin];
fifo->begin = (fifo->begin + 1)& 0x7FFF; u32 val;
fifo->empty = (fifo->begin == fifo->end); val = fifo->buf[fifo->recvPos];
return v; fifo->recvPos = (fifo->recvPos+1) & 0x7FFF;
fifo->empty = (fifo->recvPos == fifo->sendPos);
//printlog("-------------- FIFO get size=%i, val=%X\n",fifo->recvPos, val);
return val;
} }

View File

@ -28,28 +28,22 @@
typedef struct typedef struct
{ {
u32 data[0x8000]; bool error;
u32 begin; bool enable;
u32 end;
BOOL full; bool empty;
BOOL empty; bool half;
BOOL error; bool full;
u8 irq;
u8 sendPos;
u8 recvPos;
u32 buf[0x8000];
} FIFO; } FIFO;
void FIFOInit(FIFO * fifo); extern void FIFOclear(FIFO * fifo);
void FIFOAdd(FIFO * fifo, u32 v); extern void FIFOadd(FIFO * fifo, u32 val);
u32 FIFOValue(FIFO * fifo); extern u32 FIFOget(FIFO * fifo);
//================== 3D GFX FIFO
typedef struct{
u32 hits[640];
u32 hits_count;
u32 empty;
u32 half;
u32 full;
u32 begin;
u32 end;
u32 irq;
} GFXFIFO;
#endif #endif

View File

@ -2072,11 +2072,15 @@ void GPU_ligne(NDS_Screen * screen, u16 l)
// Read from FIFO MAIN_MEMORY_DISP_FIFO, two pixels at once format is x555, bit15 unused // Read from FIFO MAIN_MEMORY_DISP_FIFO, two pixels at once format is x555, bit15 unused
// Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode // Reference: http://nocash.emubase.de/gbatek.htm#dsvideocaptureandmainmemorydisplaymode
// (under DISP_MMEM_FIFO) // (under DISP_MMEM_FIFO)
#ifdef 0
for (i=0; i<256;) { for (i=0; i<256;) {
c = FIFOValue(MMU.fifos + MAIN_MEMORY_DISP_FIFO); c = FIFOValue(MMU.fifos + MAIN_MEMORY_DISP_FIFO);
T2WriteWord(dst, i << 1, c&0xFFFF); i++; T2WriteWord(dst, i << 1, c&0xFFFF); i++;
T2WriteWord(dst, i << 1, c>>16); i++; T2WriteWord(dst, i << 1, c>>16); i++;
} }
else
printlog("FIFO MAIN_MEMORY_DISP_FIFO\n");
#endif
return; return;
} }

View File

@ -201,10 +201,8 @@ void MMU_Init(void) {
MMU.MMU_WAIT32[0] = MMU_ARM9_WAIT32; MMU.MMU_WAIT32[0] = MMU_ARM9_WAIT32;
MMU.MMU_WAIT32[1] = MMU_ARM7_WAIT32; MMU.MMU_WAIT32[1] = MMU_ARM7_WAIT32;
for(i = 0;i < 16;i++) FIFOclear(MMU.fifos);
FIFOInit(MMU.fifos + i); FIFOclear(MMU.fifos+1);
memset(&MMU.gfxfifo, 0, sizeof(GFXFIFO));
MMU.gfxfifo.empty=MMU.gfxfifo.half=TRUE;
mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */ mc_init(&MMU.fw, MC_TYPE_FLASH); /* init fw device */
mc_alloc(&MMU.fw, NDS_FW_SIZE_V1); mc_alloc(&MMU.fw, NDS_FW_SIZE_V1);
@ -260,10 +258,8 @@ void MMU_clearMem()
memset(MMU.ARM7_ERAM, 0, 0x010000); memset(MMU.ARM7_ERAM, 0, 0x010000);
memset(MMU.ARM7_REG, 0, 0x010000); memset(MMU.ARM7_REG, 0, 0x010000);
for(i = 0;i < 16;i++) FIFOclear(MMU.fifos);
FIFOInit(MMU.fifos + i); FIFOclear(MMU.fifos+1);
memset(&MMU.gfxfifo, 0, sizeof(GFXFIFO));
MMU.gfxfifo.empty=MMU.gfxfifo.half=TRUE;
MMU.DTCMRegion = 0x027C0000; MMU.DTCMRegion = 0x027C0000;
MMU.ITCMRegion = 0x00000000; MMU.ITCMRegion = 0x00000000;
@ -660,6 +656,7 @@ u16 FASTCALL _MMU_read16(u32 adr)
return (gfx3d_GetNumVertex()&8191); return (gfx3d_GetNumVertex()&8191);
case REG_IPCFIFORECV : /* TODO (clear): ??? */ case REG_IPCFIFORECV : /* TODO (clear): ??? */
printlog("read16: IPCFIFORECV\n");
//printlog("Stopped IPCFIFORECV\n"); //printlog("Stopped IPCFIFORECV\n");
execute = FALSE; execute = FALSE;
return 1; return 1;
@ -673,8 +670,10 @@ u16 FASTCALL _MMU_read16(u32 adr)
return (u16)(MMU.reg_IE[proc]>>16); return (u16)(MMU.reg_IE[proc]>>16);
case REG_IF : case REG_IF :
//printlog("read16 (low): REG_IF\n");
return (u16)MMU.reg_IF[proc]; return (u16)MMU.reg_IF[proc];
case REG_IF + 2 : case REG_IF + 2 :
//printlog("read16 (high): REG_IF\n");
return (u16)(MMU.reg_IF[proc]>>16); return (u16)(MMU.reg_IF[proc]>>16);
case REG_TM0CNTL : case REG_TM0CNTL :
@ -726,13 +725,14 @@ u32 FASTCALL _MMU_read32(u32 adr)
switch(adr) switch(adr)
{ {
// This is hacked due to the only current 3D core // This is hacked due to the only current 3D core
case 0x04000600: case 0x04000600: // Geometry Engine Status Register (R and R/W)
{ {
u32 gxstat =(2|(MMU.gfxfifo.hits_count<<16)| u32 gxstat = ( 2 |
(MMU.gfxfifo.full<<24)| (MMU.fifos[proc].full<<24)|
(MMU.gfxfifo.empty<<25)| (MMU.fifos[proc].half<<25)|
(MMU.gfxfifo.half<<26)| (MMU.fifos[proc].empty<<26)|
(MMU.gfxfifo.irq<<30)); (MMU.fifos[proc].irq<<30)
);
return gxstat; return gxstat;
} }
@ -781,25 +781,27 @@ u32 FASTCALL _MMU_read32(u32 adr)
case REG_IE : case REG_IE :
return MMU.reg_IE[proc]; return MMU.reg_IE[proc];
case REG_IF : case REG_IF :
//printlog("read32: REG_IF\n");
return MMU.reg_IF[proc]; return MMU.reg_IF[proc];
case REG_IPCFIFORECV : case REG_IPCFIFORECV :
{ {
u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
if(IPCFIFO_CNT&0x8000) //printlog("read32: REG_IPCFIFORECV (%X)\n", cnt_l);
{ if (!(cnt_l & 0x8000)) return 0; // FIFO disabled
//execute = FALSE; u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184);
u32 fifonum = IPCFIFO+proc; u32 val = FIFOget(MMU.fifos + proc);
u32 val = FIFOValue(MMU.fifos + fifonum);
u32 remote = (proc+1) & 1; cnt_l |= (MMU.fifos[proc].empty<<8) | (MMU.fifos[proc].full<<9) | (MMU.fifos[proc].error<<14);
u16 IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184); cnt_r |= (MMU.fifos[proc].empty) | (MMU.fifos[proc].full<<1);
IPCFIFO_CNT |= (MMU.fifos[fifonum].empty<<8) | (MMU.fifos[fifonum].full<<9) | (MMU.fifos[fifonum].error<<14);
IPCFIFO_CNT_remote |= (MMU.fifos[fifonum].empty) | (MMU.fifos[fifonum].full<<1); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT); T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r);
T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote);
if ((MMU.fifos[fifonum].empty) && (IPCFIFO_CNT & BIT(2))) if ((MMU.fifos[proc].empty) && (cnt_l & BIT(2)))
NDS_makeInt(remote,17) ; /* remote: SEND FIFO EMPTY */ NDS_makeInt(proc^1,17) ; /* remote: SEND FIFO EMPTY */
return val; return val;
} #endif
} }
return 0; return 0;
case REG_TM0CNTL : case REG_TM0CNTL :
@ -1684,15 +1686,18 @@ void FASTCALL _MMU_write16(u32 adr, u16 val)
case REG_IF : case REG_IF :
//execute = FALSE; //execute = FALSE;
//printlog("write16 (low): REG_IF (%X)\n", val);
MMU.reg_IF[proc] &= (~((u32)val)); MMU.reg_IF[proc] &= (~((u32)val));
return; return;
case REG_IF + 2 : case REG_IF + 2 :
//printlog("write16 (high): REG_IF (%X)\n", val);
//execute = FALSE; //execute = FALSE;
MMU.reg_IF[proc] &= (~(((u32)val)<<16)); MMU.reg_IF[proc] &= (~(((u32)val)<<16));
return; return;
case REG_IPCSYNC : case REG_IPCSYNC :
{ {
//printlog("IPCSYNC\n");
u32 remote = (proc+1)&1; u32 remote = (proc+1)&1;
u16 IPCSYNC_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x180); u16 IPCSYNC_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x180);
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF)); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x180, (val&0xFFF0)|((IPCSYNC_remote>>8)&0xF));
@ -1701,28 +1706,34 @@ void FASTCALL _MMU_write16(u32 adr, u16 val)
//execute = FALSE; //execute = FALSE;
} }
return; return;
case REG_IPCFIFOCNT : case REG_IPCFIFOCNT :
{ {
u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ; u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ;
u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ; u32 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184) ;
//printlog("write16 (%s): REG_IPCFIFOCNT 0x(%08X)\n", proc?"ARM9":"ARM7",REG_IPCFIFOCNT);
//printlog(" --- val=%X\n",val);
if ((val & 0x8000) && !(cnt_l & 0x8000)) if ((val & 0x8000) && !(cnt_l & 0x8000))
{ {
/* this is the first init, the other side didnt init yet */ /* this is the first init, the other side didnt init yet */
/* so do a complete init */ /* so do a complete init */
FIFOInit(MMU.fifos + (IPCFIFO+proc)); FIFOclear(MMU.fifos + proc);
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ; T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184,0x8101) ;
/* and then handle it as usual */ /* and then handle it as usual */
} }
if(val & 0x4008) if (val & 0x4008) // clear FIFO
{ {
FIFOInit(MMU.fifos + (IPCFIFO+((proc+1)&1))); FIFOclear(&MMU.fifos[proc]);
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, (cnt_l & 0x0301) | (val & 0x8404) | 1);
T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100); T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, (cnt_r & 0xC507) | 0x100);
MMU.reg_IF[proc] |= ((val & 4)<<15);// & (MMU.reg_IME[proc]<<17);// & (MMU.reg_IE[proc]&0x20000);// MMU.reg_IF[proc] |= ((val & 4)<<15);
//T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val);
return; return;
} }
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) | (val & 0xBFF4)); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l | (val & 0xBFF4));
} }
return; return;
case REG_TM0CNTL : case REG_TM0CNTL :
@ -2364,9 +2375,12 @@ void FASTCALL _MMU_write32(u32 adr, u32 val)
return; return;
} }
case 0x04000600: case 0x04000600: // Geometry Engine Status Register (R and R/W)
{ {
MMU.gfxfifo.irq=(val>>30)&3; //printlog("write32: Geometry Engine Status Register (R and R/W)");
//printlog("------- val=%X\n\n************\n\n", val);
MMU.fifos[proc].irq = (val>>30) & 0x03;
return; return;
} }
case REG_DISPA_WININ: case REG_DISPA_WININ:
@ -2509,6 +2523,7 @@ void FASTCALL _MMU_write32(u32 adr, u32 val)
return; return;
case REG_IF : case REG_IF :
//printlog("write32: REG_IF (%X)\n", val);
MMU.reg_IF[proc] &= (~val); MMU.reg_IF[proc] &= (~val);
return; return;
@ -2713,6 +2728,7 @@ void FASTCALL _MMU_write32(u32 adr, u32 val)
return; return;
case REG_IPCFIFOCNT : case REG_IPCFIFOCNT :
{ {
#ifdef 0
u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ; u32 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184) ;
u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ; u32 cnt_r = T1ReadWord(MMU.MMU_MEM[(proc+1) & 1][0x40], 0x184) ;
if ((val & 0x8000) && !(cnt_l & 0x8000)) if ((val & 0x8000) && !(cnt_l & 0x8000))
@ -2732,27 +2748,25 @@ void FASTCALL _MMU_write32(u32 adr, u32 val)
return; return;
} }
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val & 0xBFF4); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, val & 0xBFF4);
#else
printlog("write32: REG_IPCFIFOCNT\n");
#endif
//execute = FALSE; //execute = FALSE;
return; return;
} }
case REG_IPCFIFOSEND : case REG_IPCFIFOSEND :
{ {
u16 IPCFIFO_CNT = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184); u16 cnt_l = T1ReadWord(MMU.MMU_MEM[proc][0x40], 0x184);
if(IPCFIFO_CNT&0x8000) if (!(cnt_l & 0x8000)) return; //FIFO disabled
{ u16 cnt_r = T1ReadWord(MMU.MMU_MEM[proc^1][0x40], 0x184);
//if(val==43) execute = FALSE; //printlog("write32 (%s): REG_IPCFIFOSEND (%X-%X) val=%X\n", proc?"ARM9":"ARM7",cnt_l,cnt_r,val);
u32 remote = (proc+1)&1; //FIFOadd(MMU.fifos+(proc^1), val);
u32 fifonum = IPCFIFO+remote; FIFOadd(MMU.fifos+(proc^1), val);
u16 IPCFIFO_CNT_remote; cnt_l = (cnt_l & 0xFFFC) | (MMU.fifos[proc^1].full<<1);
FIFOAdd(MMU.fifos + fifonum, val); cnt_r = (cnt_r & 0xFCFF) | (MMU.fifos[proc^1].full<<9);
IPCFIFO_CNT = (IPCFIFO_CNT & 0xFFFC) | (MMU.fifos[fifonum].full<<1); T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, cnt_l);
IPCFIFO_CNT_remote = T1ReadWord(MMU.MMU_MEM[remote][0x40], 0x184); T1WriteWord(MMU.MMU_MEM[proc^1][0x40], 0x184, cnt_r);
IPCFIFO_CNT_remote = (IPCFIFO_CNT_remote & 0xFCFF) | (MMU.fifos[fifonum].full<<10); MMU.reg_IF[proc^1] |= ((cnt_r & (1<<10))<<8);
T1WriteWord(MMU.MMU_MEM[proc][0x40], 0x184, IPCFIFO_CNT);
T1WriteWord(MMU.MMU_MEM[remote][0x40], 0x184, IPCFIFO_CNT_remote);
MMU.reg_IF[remote] |= ((IPCFIFO_CNT_remote & (1<<10))<<8);// & (MMU.reg_IME[remote] << 18);// & (MMU.reg_IE[remote] & 0x40000);//
//execute = FALSE;
}
} }
return; return;
case REG_DMA0CNTL : case REG_DMA0CNTL :
@ -2929,8 +2943,21 @@ void FASTCALL _MMU_write32(u32 adr, u32 val)
{ {
// NOTE: right now, the capture unit is not taken into account, // NOTE: right now, the capture unit is not taken into account,
// I don't know is it should be handled here or // I don't know is it should be handled here or
#ifdef 0
FIFOAdd(MMU.fifos + MAIN_MEMORY_DISP_FIFO, val); FIFOAdd(MMU.fifos + MAIN_MEMORY_DISP_FIFO, val);
#else
//4000068h - NDS9 - DISP_MMEM_FIFO - 32bit - Main Memory Display FIFO (R?/W)
//Intended to send 256x192 pixel 32K color bitmaps by DMA directly
//- to Screen A (set DISPCNT to Main Memory Display mode), or
//- to Display Capture unit (set DISPCAPCNT to Main Memory Source).
//The FIFO can receive 4 words (8 pixels) at a time, each pixel is a 15bit RGB value (the upper bit, bit15, is unused).
//Set DMA to Main Memory mode, 32bit transfer width, word count set to 4, destination address to DISP_MMEM_FIFO, source address must be in Main Memory.
//Transfer starts at next frame.
//Main Memory Display/Capture is supported for Display Engine A only.
printlog("write32: REG_DISPA_DISPMMEMFIFO\n");
#endif
break; break;
} }
//case 0x21FDFF0 : if(val==0) execute = FALSE; //case 0x21FDFF0 : if(val==0) execute = FALSE;

View File

@ -39,8 +39,8 @@ extern char szRomBaseName[512];
/* theses ones for reading in rom data */ /* theses ones for reading in rom data */
#define ROM_8(m, a) (((u8*)(m))[(a)]) #define ROM_8(m, a) (((u8*)(m))[(a)])
#define IPCFIFO 0 //#define IPCFIFO 0
#define MAIN_MEMORY_DISP_FIFO 2 //#define MAIN_MEMORY_DISP_FIFO 2
typedef struct { typedef struct {
//ARM7 mem //ARM7 mem
@ -67,8 +67,8 @@ typedef struct {
u8 ARM9_RW_MODE; u8 ARM9_RW_MODE;
FIFO fifos[16]; FIFO fifos[2]; // 0 - ARM9 FIFO
GFXFIFO gfxfifo; // 1 - ARM7 FIFO
u32 * MMU_WAIT16[2]; u32 * MMU_WAIT16[2];
u32 * MMU_WAIT32[2]; u32 * MMU_WAIT32[2];

View File

@ -1526,12 +1526,22 @@ NDS_exec(s32 nb, BOOL force)
} }
} }
if(MMU.reg_IE[0]&(1<<21)) /*for (int tt=0; tt<24; tt++)
{ {
if(MMU.gfxfifo.irq==0) return nds.cycles; if (tt == 0) continue; //VBlank
if(MMU.gfxfifo.irq==3) return nds.cycles; if (tt == 1) continue; //HBlank
if(MMU.gfxfifo.irq==1 && MMU.gfxfifo.half) NDS_makeARM9Int(21); if (tt == 3) continue;
if(MMU.gfxfifo.irq==2 && MMU.gfxfifo.empty) NDS_makeARM9Int(21); if (tt == 12) continue;
if (tt == 18) continue;
if (MMU.reg_IE[0]&(1<<tt)) printlog("wait IRQ%i\n", tt);
}*/
//if(MMU.reg_IE[0]&(1<<0)) gfx3d_VBlankSignal();
if(MMU.reg_IE[0]&(1<<21)) // IRQ21
{
if (MMU.fifos[0].irq==1) NDS_makeARM9Int(21);
if (MMU.fifos[0].irq==2) NDS_makeARM9Int(21);
} }
if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0])) if((MMU.reg_IF[0]&MMU.reg_IE[0]) && (MMU.reg_IME[0]))