diff --git a/desmume/src/FIFO.cpp b/desmume/src/FIFO.cpp index ff781aec7..830017fbf 100644 --- a/desmume/src/FIFO.cpp +++ b/desmume/src/FIFO.cpp @@ -1,7 +1,7 @@ /* Copyright 2006 yopyop Copyright 2007 shash - Copyright 2007-2012 DeSmuME team + Copyright 2007-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -164,6 +164,8 @@ void IPC_FIFOcnt(u8 proc, u16 val) GFX_PIPE gxPIPE; GFX_FIFO gxFIFO; +int GFX_FIFOsize() { return gxFIFO.size; } + void GFX_PIPEclear() { gxPIPE.head = 0; @@ -202,8 +204,19 @@ static bool IsMatrixStackCommand(u8 cmd) return cmd == 0x11 || cmd == 0x12; } +extern BOOL isSwapBuffers; void GFX_FIFOsend(u8 cmd, u32 param) { + if(isSwapBuffers) + { + //when trying to process a 3d command while a flush is pending, freeze. + //NOTE: this is probably not a correct implementation. it should freeze at the moment the command is beginning to go in the fifo + //however, this is kind of hard with our current architecture. + //instead, we freeze just after the command goes into the fifo + //test case: https://sourceforge.net/p/desmume/bugs/1134/ + nds.freezeBus |= FREEZEBUS_FLAG_GXFLUSH_JAMMED; + } + //INFO("gxFIFO: send 0x%02X = 0x%08X (size %03i/0x%02X) gxstat 0x%08X\n", cmd, param, gxFIFO.size, gxFIFO.size, gxstat); //printf("fifo recv: %02X: %08X upto:%d\n",cmd,param,gxFIFO.size+1); diff --git a/desmume/src/FIFO.h b/desmume/src/FIFO.h index f96c4fa47..9718e28d4 100644 --- a/desmume/src/FIFO.h +++ b/desmume/src/FIFO.h @@ -1,7 +1,7 @@ /* Copyright 2006 yopyop Copyright 2007 shash - Copyright 2007-2011 DeSmuME team + Copyright 2007-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -74,6 +74,7 @@ extern void GFX_FIFOclear(); extern void GFX_FIFOsend(u8 cmd, u32 param); extern BOOL GFX_PIPErecv(u8 *cmd, u32 *param); extern void GFX_FIFOcnt(u32 val); +extern int GFX_FIFOsize(); //=================================================== Display memory FIFO typedef struct diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index 9c258c757..1704cccaa 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -1,7 +1,7 @@ /* Copyright (C) 2006 yopyop Copyright (C) 2007 shash - Copyright (C) 2007-2013 DeSmuME team + Copyright (C) 2007-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -2181,7 +2181,7 @@ void DmaController::exec() //printf("ARM%c DMA%d execute, count %08X, mode %d%s\n", procnum?'7':'9', chan, wordcount, startmode, running?" - RUNNING":""); //we'll need to unfreeze the arm9 bus now - if(procnum==ARMCPU_ARM9) nds.freezeBus &= ~(1<<(chan+1)); + if(procnum==ARMCPU_ARM9) nds.freezeBus &= ~(FREEZEBUS_FLAG_ARM9_DMA0< 254) - nds.freezeBus |= 1; + nds.freezeBus |= FREEZEBUS_FLAG_GXFIFO_JAMMED; ((u32 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]))[(adr & 0xFFF) >> 2] = val; gfx3d_sendCommand(adr, val); diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index e0e84d847..0ae486bf7 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2006 yopyop - Copyright (C) 2008-2013 DeSmuME team + Copyright (C) 2008-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1740,7 +1740,7 @@ static /*donotinline*/ std::pair armInnerLoop( s32 temp = arm9; arm9 = min(s32next, arm9 + kIrqWait); nds.idleCycles[0] += arm9-temp; - if (gxFIFO.size < 255) nds.freezeBus &= ~1; + if (gxFIFO.size < 255) nds.freezeBus &= ~FREEZEBUS_FLAG_GXFIFO_JAMMED; } } if(doarm7 && (!doarm9 || arm7 <= timer)) diff --git a/desmume/src/NDSSystem.h b/desmume/src/NDSSystem.h index 48b01d207..e117e0c99 100644 --- a/desmume/src/NDSSystem.h +++ b/desmume/src/NDSSystem.h @@ -1,6 +1,6 @@ /* Copyright (C) 2006 yopyop - Copyright (C) 2008-2013 DeSmuME team + Copyright (C) 2008-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -177,6 +177,13 @@ enum NDS_CONSOLE_TYPE NDS_CONSOLE_TYPE_DSI = 0xFE }; +#define FREEZEBUS_FLAG_GXFIFO_JAMMED (1<<0) +#define FREEZEBUS_FLAG_ARM9_DMA0 (1<<1) +#define FREEZEBUS_FLAG_ARM9_DMA1 (1<<2) +#define FREEZEBUS_FLAG_ARM9_DMA2 (1<<3) +#define FREEZEBUS_FLAG_ARM9_DMA3 (1<<4) +#define FREEZEBUS_FLAG_GXFLUSH_JAMMED (1<<5) + struct NDSSystem { s32 wifiCycle; diff --git a/desmume/src/gfx3d.cpp b/desmume/src/gfx3d.cpp index 99dc4b233..fefe5fd95 100644 --- a/desmume/src/gfx3d.cpp +++ b/desmume/src/gfx3d.cpp @@ -1,6 +1,6 @@ /* Copyright (C) 2006 yopyop - Copyright (C) 2008-2013 DeSmuME team + Copyright (C) 2008-2014 DeSmuME team This file is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -112,6 +112,7 @@ public: void receive(u32 val) { + //so, it seems as if the dummy values and restrictions on the highest-order command in the packed command set //is solely about some unknown internal timing quirk, and not about the logical behaviour of the state machine. //it's possible that writing some values too quickly can result in the gxfifo not being ready. @@ -1973,16 +1974,19 @@ void gfx3d_execute3D() u8 cmd = 0; u32 param = 0; -#ifndef FLUSHMODE_HACK - if (isSwapBuffers) return; -#endif + if(nds.freezeBus & FREEZEBUS_FLAG_GXFLUSH_JAMMED) + { + //sanity check: in case a command went into the fifo but the cpu should be frozen, do nothing + return; + } //this is a SPEED HACK //fifo is currently emulated more accurately than it probably needs to be. //without this batch size the emuloop will escape way too often to run fast. const int HACK_FIFO_BATCH_SIZE = 64; - for(int i=0;i