new gxFIFO:

- fix for work with new emuloop;
- add early implementation of pipeline;
This commit is contained in:
mtabachenko 2009-07-15 22:46:33 +00:00
parent 6275b5d746
commit aa84f1529e
4 changed files with 126 additions and 46 deletions

View File

@ -137,8 +137,14 @@ void IPC_FIFOcnt(u8 proc, u16 val)
}
// ========================================================= GFX FIFO
GFX_PIPE gxPIPE;
GFX_FIFO gxFIFO;
void GFX_PIPEclear()
{
gxPIPE.tail = 0;
}
void GFX_FIFOclear()
{
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
@ -151,9 +157,30 @@ void GFX_FIFOclear()
void GFX_FIFOsend(u8 cmd, u32 param)
{
//INFO("GFX FIFO: Send GFX 3D cmd 0x%02X to FIFO - 0x%08X (%03i/%02X)\n", cmd, param, gxFIFO.tail, gxFIFO.tail);
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
if (gxstat & 0x01000000) return; // full
if (gxFIFO.tail == 0) // FIFO empty
{
if (gxPIPE.tail < 4) // pipe not full
{
gxPIPE.cmd[gxPIPE.tail] = cmd;
gxPIPE.param[gxPIPE.tail] = param;
gxPIPE.tail++;
#ifdef USE_GEOMETRY_FIFO_EMULATION
gxstat |= 0x08000000; // set busy flag
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
#endif
NDS_RescheduleGXFIFO();
return;
}
}
//INFO("GFX FIFO: Send GFX 3D cmd 0x%02X to FIFO - 0x%08X (%03i/%02X)\n", cmd, param, gxFIFO.tail, gxFIFO.tail);
if (gxstat & 0x01000000)
{
//INFO("ERROR: gxFIFO is full\n");
return; // full
}
gxstat &= 0xF000FFFF;
@ -175,45 +202,29 @@ 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)
{
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
#if 0
if (gxstat & 0xC0000000)
{
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}
#endif
if (gxFIFO.tail == 0) // empty
if (gxFIFO.tail == 0) // empty
{
gxstat &= 0xF000FFFF;
gxstat |= 0x06000000;
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
if ((gxstat & 0x80000000)) // empty
if ((gxstat & 0x80000000)) // IRQ: empty
{
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}
return FALSE;
}
if (gxstat & 0x40000000) // IRQ: less half
{
if (gxstat & 0x02000000)
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}
if ((gxstat & 0x80000000)) // IRQ: empty
{
if (gxstat & 0x04000000)
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
if (gxstat & 0x02000000) setIF(0, (1<<21));
}
gxstat &= 0xF000FFFF;
@ -226,28 +237,81 @@ BOOL GFX_FIFOrecv(u8 *cmd, u32 *param)
gxFIFO.param[i] = gxFIFO.param[i+1];
}
#ifdef USE_GEOMETRY_FIFO_EMULATION
gxstat |= 0x08000000; // set busy flag
#endif
gxstat |= (gxFIFO.tail << 16);
if (gxFIFO.tail < 128)
gxstat |= 0x02000000;
if (gxFIFO.tail == 0) // empty
gxstat |= 0x04000000;
else
gxstat |= 0x08000000; // set busy flag
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
NDS_RescheduleGXFIFO();
return TRUE;
}
BOOL GFX_PIPErecv(u8 *cmd, u32 *param)
{
u8 tmp_cmd = 0;
u32 tmp_param = 0;
u32 gxstat = 0;
if (gxPIPE.tail > 0)
{
*cmd = gxPIPE.cmd[0];
*param = gxPIPE.param[0];
gxPIPE.tail--;
for (int i=0; i < gxPIPE.tail; i++)
{
gxPIPE.cmd[i] = gxPIPE.cmd[i+1];
gxPIPE.param[i] = gxPIPE.param[i+1];
}
if (gxPIPE.tail < 2)
{
if (GFX_FIFOrecv(&tmp_cmd, &tmp_param))
{
gxPIPE.cmd[gxPIPE.tail] = tmp_cmd;
gxPIPE.param[gxPIPE.tail] = tmp_param;
gxPIPE.tail++;
if (GFX_FIFOrecv(&tmp_cmd, &tmp_param))
{
gxPIPE.cmd[gxPIPE.tail] = tmp_cmd;
gxPIPE.param[gxPIPE.tail] = tmp_param;
gxPIPE.tail++;
}
}
}
if (gxPIPE.tail == 0)
{
gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
gxstat &= 0xF7FFFFFF; // clear busy flag
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
}
return (TRUE);
}
gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
gxstat &= 0xF7FFFFFF; // clear busy flag
if ((gxstat & 0x80000000)) // IRQ: empty
{
if (gxFIFO.tail == 0) setIF(0, (1<<21));
}
T1WriteLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600, gxstat);
return FALSE;
}
void GFX_FIFOcnt(u32 val)
{
u32 gxstat = T1ReadLong(MMU.MMU_MEM[ARMCPU_ARM9][0x40], 0x600);
//INFO("GFX FIFO: write context 0x%08X (prev 0x%08X) tail %i\n", val, gxstat, gxFIFO.tail);
if (val & (1<<29)) // clear? (homebrew)
{
GFX_PIPEclear();
GFX_FIFOclear();
return;
}
@ -258,7 +322,6 @@ void GFX_FIFOcnt(u32 val)
/*if (gxstat & 0xC0000000)
{
setIF(0, (1<<21));
//NDS_makeARM9Int(21);
}*/
}

View File

@ -26,7 +26,7 @@
#ifndef FIFO_H
#define FIFO_H
//#define USE_GEOMETRY_FIFO_EMULATION //enables new experimental gxFIFO
//#define USE_GEOMETRY_FIFO_EMULATION //enable gxFIFO emulation
#include "types.h"
@ -47,16 +47,26 @@ extern void IPC_FIFOcnt(u8 proc, u16 val);
//=================================================== GFX FIFO
typedef struct
{
u8 cmd[261];
u32 param[261];
u8 cmd[257];
u32 param[257];
u16 tail; // tail
} GFX_FIFO;
typedef struct
{
u8 cmd[5];
u32 param[5];
u8 tail;
} GFX_PIPE;
extern GFX_PIPE gxPIPE;
extern GFX_FIFO gxFIFO;
extern void GFX_PIPEclear();
extern void GFX_FIFOclear();
extern void GFX_FIFOsend(u8 cmd, u32 param);
extern BOOL GFX_FIFOrecv(u8 *cmd, u32 *param);
extern BOOL GFX_PIPErecv(u8 *cmd, u32 *param);
extern void GFX_FIFOcnt(u32 val);
//=================================================== Display memory FIFO

View File

@ -894,6 +894,7 @@ void MMU_Init(void) {
IPC_FIFOinit(ARMCPU_ARM9);
IPC_FIFOinit(ARMCPU_ARM7);
GFX_PIPEclear();
GFX_FIFOclear();
DISP_FIFOinit();
@ -951,6 +952,7 @@ void MMU_clearMem()
IPC_FIFOinit(ARMCPU_ARM9);
IPC_FIFOinit(ARMCPU_ARM7);
GFX_PIPEclear();
GFX_FIFOclear();
DISP_FIFOinit();

View File

@ -61,10 +61,8 @@ in this function: */
static void gfx3d_doFlush();
#ifdef USE_GEOMETRY_FIFO_EMULATION
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(); }
#define GFX_DELAY(x) MMU.gfx3dCycles = nds_timer + (1*x);
#define GFX_DELAY_M2(x) MMU.gfx3dCycles += (1*x);
#else
#define GFX_DELAY(x)
#define GFX_DELAY_M2(x)
@ -366,6 +364,7 @@ void gfx3d_reset()
gfx3d.clearDepth = gfx3d_extendDepth_15_to_24(0x7FFF);
GFX_PIPEclear();
GFX_FIFOclear();
#ifdef USE_GEOMETRY_FIFO_EMULATION
@ -1528,8 +1527,9 @@ void gfx3d_execute(u8 cmd, u32 param)
break;
default:
INFO("Unknown execute FIFO 3D command 0x%02X with param 0x%08X\n", cmd, param);
break;
return;
}
NDS_RescheduleGXFIFO();
}
void gfx3d_execute3D()
@ -1539,7 +1539,7 @@ void gfx3d_execute3D()
if (isSwapBuffers) return;
if (GFX_FIFOrecv(&cmd, &param))
if (GFX_PIPErecv(&cmd, &param))
{
gfx3d_execute(cmd, param);
#if 0
@ -1631,6 +1631,7 @@ static void gfx3d_doFlush()
gfx3d.frameCtr++;
#ifndef USE_GEOMETRY_FIFO_EMULATION
GFX_PIPEclear();
GFX_FIFOclear();
// reset
clInd = 0;
@ -1718,12 +1719,14 @@ void gfx3d_VBlankSignal()
gfx3d_doFlush();
isSwapBuffers = false;
GFX_DELAY(392);
NDS_RescheduleGXFIFO();
}
#else
//the 3d buffers are swapped when a vblank begins.
//so, if we have a redraw pending, now is a safe time to do it
if(!flushPending)
{
GFX_PIPEclear();
GFX_FIFOclear();
return;
}
@ -1748,11 +1751,10 @@ void gfx3d_VBlankEndSignal(bool skipFrame)
{
memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedScreen));
memset(gfx3d_convertedScreen,0,sizeof(gfx3d_convertedAlpha));
return;
}
else
{
gpu3D->NDS_3D_Render();
}
gpu3D->NDS_3D_Render();
#else
//if we are skipping 3d frames then the 3d rendering will get held up here.
//but, as soon as we quit skipping frames, the held-up 3d frame will render
@ -2432,8 +2434,11 @@ SFORMAT SF_GFX3D[]={
{ "GLPT", 4, 1, &PTind},
{ "GLPC", 4, 4, PTcoords},
{ "GLF9", 4, 1, &gxFIFO.tail},
{ "GLF9", 1, 261, &gxFIFO.cmd[0]},
{ "GLF9", 4, 261, &gxFIFO.param[0]},
{ "GLF9", 1, 257, &gxFIFO.cmd[0]},
{ "GLF9", 4, 257, &gxFIFO.param[0]},
{ "GLP9", 4, 1, &gxPIPE.tail},
{ "GLP9", 1, 5, &gxPIPE.cmd[0]},
{ "GLP9", 4, 5, &gxPIPE.param[0]},
{ "GCOL", 1, 4, colorRGB},
{ "GLCO", 4, 4, lightColor},
{ "GLDI", 4, 4, lightDirection},