fix #1134 - american girl games (need system jamming when sending 3d commands with pending flush)

TODO - check #1428 (reportedly it affects PMD somehow)
This commit is contained in:
zeromus 2014-06-17 05:46:49 +00:00
parent fca4afd7ce
commit 0c54127f59
6 changed files with 42 additions and 15 deletions

View File

@ -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);

View File

@ -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

View File

@ -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<<chan);
dmaCheck = FALSE;
@ -2330,7 +2330,7 @@ void DmaController::doCopy()
//freeze the ARM9 bus for the duration of this DMA
//thats not entirely accurate
if(procnum==ARMCPU_ARM9)
nds.freezeBus |= (1<<(chan+1));
nds.freezeBus |= (FREEZEBUS_FLAG_ARM9_DMA0<<chan);
//write back the addresses
saddr = src;
@ -4009,7 +4009,7 @@ void FASTCALL _MMU_ARM9_write32(u32 adr, u32 val)
case 0x40005B:
case 0x40005C: // Individual Commands
if (gxFIFO.size > 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);

View File

@ -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<s32,s32> 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))

View File

@ -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;

View File

@ -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<HACK_FIFO_BATCH_SIZE;i++) {
for(int i=0;i<HACK_FIFO_BATCH_SIZE;i++)
{
if(GFX_PIPErecv(&cmd, &param))
{
//if (isSwapBuffers) printf("Executing while swapbuffers is pending: %d:%08X\n",cmd,param);
@ -2022,7 +2026,7 @@ void gfx3d_glFlush(u32 v)
#endif
isSwapBuffers = TRUE;
//printf("%05d:%03d:%12lld: FLUSH\n",currFrameCounter, nds.VCount, nds_timer);
//well, the game wanted us to flush.
@ -2179,6 +2183,8 @@ void gfx3d_VBlankSignal()
#endif
GFX_DELAY(392);
isSwapBuffers = FALSE;
//GX processing can proceed once more. I think it was important that the GFX_DELAY above ran, to reschedule 3d
nds.freezeBus &= ~FREEZEBUS_FLAG_GXFLUSH_JAMMED;
}
}