reworked frameskipping logic to hopefully fix frameskipping in dual-screen-3d games
This commit is contained in:
parent
b0895ec82f
commit
89e4e948c3
|
@ -1479,15 +1479,99 @@ int NDS_LoadFirmware(const char *filename)
|
||||||
|
|
||||||
void NDS_Sleep() { nds.sleeping = TRUE; }
|
void NDS_Sleep() { nds.sleeping = TRUE; }
|
||||||
|
|
||||||
bool SkipCur2DFrame = false, SkipNext2DFrame = false;
|
|
||||||
bool SkipCur3DFrame = false;
|
class FrameSkipper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void RequestSkip()
|
||||||
|
{
|
||||||
|
nextSkip = true;
|
||||||
|
}
|
||||||
|
void OmitSkip(bool force, bool forceEvenIfCapturing=false)
|
||||||
|
{
|
||||||
|
nextSkip = false;
|
||||||
|
if((force && !lastCapturing) || forceEvenIfCapturing)
|
||||||
|
{
|
||||||
|
SkipCur2DFrame = false;
|
||||||
|
SkipCur3DFrame = false;
|
||||||
|
SkipNext2DFrame = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void Advance()
|
||||||
|
{
|
||||||
|
bool capturing = (MainScreen.gpu->dispCapCnt.enabled || (MainScreen.gpu->dispCapCnt.val & 0x80000000));
|
||||||
|
|
||||||
|
if(capturing && !lastCapturing)
|
||||||
|
{
|
||||||
|
// the worst-looking graphics corruption problems from frameskip
|
||||||
|
// are the result of skipping the capture on first frame it turns on.
|
||||||
|
// so we do this to handle the capture immediately,
|
||||||
|
// despite the risk of 1 frame of 2d/3d mismatch.
|
||||||
|
SkipNext2DFrame = false;
|
||||||
|
nextSkip = false;
|
||||||
|
}
|
||||||
|
else if(lastOffset != MainScreen.offset && lastSkip && !skipped)
|
||||||
|
{
|
||||||
|
// if we're switching from not skipping to skipping
|
||||||
|
// and the screens are also switching around this frame,
|
||||||
|
// go for 1 extra frame without skipping.
|
||||||
|
// this avoids the scenario where we only draw one of the two screens
|
||||||
|
// when a game is switching screens every frame.
|
||||||
|
nextSkip = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastCapturing = capturing;
|
||||||
|
lastLastOffset = lastOffset;
|
||||||
|
lastOffset = MainScreen.offset;
|
||||||
|
lastSkip = skipped;
|
||||||
|
skipped = nextSkip;
|
||||||
|
nextSkip = false;
|
||||||
|
|
||||||
|
SkipCur2DFrame = SkipNext2DFrame;
|
||||||
|
SkipCur3DFrame = skipped;
|
||||||
|
SkipNext2DFrame = skipped;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool ShouldSkip2D()
|
||||||
|
{
|
||||||
|
return SkipCur2DFrame;
|
||||||
|
}
|
||||||
|
FORCEINLINE bool ShouldSkip3D()
|
||||||
|
{
|
||||||
|
return SkipCur3DFrame;
|
||||||
|
}
|
||||||
|
FrameSkipper()
|
||||||
|
{
|
||||||
|
nextSkip = false;
|
||||||
|
skipped = false;
|
||||||
|
lastSkip = false;
|
||||||
|
lastOffset = 0;
|
||||||
|
SkipCur2DFrame = false;
|
||||||
|
SkipCur3DFrame = false;
|
||||||
|
SkipNext2DFrame = false;
|
||||||
|
lastCapturing = false;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool nextSkip;
|
||||||
|
bool skipped;
|
||||||
|
bool lastSkip;
|
||||||
|
int lastOffset;
|
||||||
|
int lastLastOffset;
|
||||||
|
bool lastCapturing;
|
||||||
|
bool SkipCur2DFrame;
|
||||||
|
bool SkipCur3DFrame;
|
||||||
|
bool SkipNext2DFrame;
|
||||||
|
};
|
||||||
|
static FrameSkipper frameSkipper;
|
||||||
|
|
||||||
|
|
||||||
void NDS_SkipNextFrame() {
|
void NDS_SkipNextFrame() {
|
||||||
if (!driver->AVI_IsRecording()) {
|
if (!driver->AVI_IsRecording()) {
|
||||||
SkipNext2DFrame = true;
|
frameSkipper.RequestSkip();
|
||||||
SkipCur3DFrame = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void NDS_OmitFrameSkip(int force) {
|
||||||
|
frameSkipper.OmitSkip(force > 0, force > 1);
|
||||||
|
}
|
||||||
|
|
||||||
#define INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
|
#define INDEX(i) ((((i)>>16)&0xFF0)|(((i)>>4)&0xF))
|
||||||
|
|
||||||
|
@ -1912,8 +1996,8 @@ static void execHardware_hblank()
|
||||||
//this should be safe since games cannot do anything timing dependent until this next
|
//this should be safe since games cannot do anything timing dependent until this next
|
||||||
//scanline begins, anyway (as this scanline was in the middle of drawing)
|
//scanline begins, anyway (as this scanline was in the middle of drawing)
|
||||||
//taskSubGpu.execute(renderSubScreen,NULL);
|
//taskSubGpu.execute(renderSubScreen,NULL);
|
||||||
GPU_RenderLine(&MainScreen, nds.VCount, SkipCur2DFrame);
|
GPU_RenderLine(&MainScreen, nds.VCount, frameSkipper.ShouldSkip2D());
|
||||||
GPU_RenderLine(&SubScreen, nds.VCount, SkipCur2DFrame);
|
GPU_RenderLine(&SubScreen, nds.VCount, frameSkipper.ShouldSkip2D());
|
||||||
//taskSubGpu.finish();
|
//taskSubGpu.finish();
|
||||||
|
|
||||||
//trigger hblank dmas
|
//trigger hblank dmas
|
||||||
|
@ -1932,6 +2016,9 @@ static void execHardware_hstart_vblankEnd()
|
||||||
//turn off vblank status bit
|
//turn off vblank status bit
|
||||||
T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & 0xFFFE);
|
T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & 0xFFFE);
|
||||||
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFE);
|
T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFE);
|
||||||
|
|
||||||
|
//some emulation housekeeping
|
||||||
|
frameSkipper.Advance();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void execHardware_hstart_vblankStart()
|
static void execHardware_hstart_vblankStart()
|
||||||
|
@ -1948,13 +2035,6 @@ static void execHardware_hstart_vblankStart()
|
||||||
|
|
||||||
//some emulation housekeeping
|
//some emulation housekeeping
|
||||||
gfx3d_VBlankSignal();
|
gfx3d_VBlankSignal();
|
||||||
if(SkipNext2DFrame)
|
|
||||||
{
|
|
||||||
SkipCur2DFrame = true;
|
|
||||||
SkipNext2DFrame = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
SkipCur2DFrame = false;
|
|
||||||
|
|
||||||
//trigger vblank dmas
|
//trigger vblank dmas
|
||||||
triggerDma(EDMAMode_VBlank);
|
triggerDma(EDMAMode_VBlank);
|
||||||
|
@ -2035,8 +2115,7 @@ static void execHardware_hstart()
|
||||||
//end of 3d vblank
|
//end of 3d vblank
|
||||||
if(nds.VCount==214)
|
if(nds.VCount==214)
|
||||||
{
|
{
|
||||||
gfx3d_VBlankEndSignal(SkipCur3DFrame);
|
gfx3d_VBlankEndSignal(frameSkipper.ShouldSkip3D());
|
||||||
SkipCur3DFrame = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue