From 4ad09233998869169ce7e0886702a804aabf86cf Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 3 Nov 2019 15:05:28 +0000 Subject: [PATCH] Fix video tearing by only updating during the Apple II VBL (#711) --- source/Applewin.cpp | 2 +- source/NTSC.cpp | 8 ++++++-- source/Video.cpp | 6 ++++++ source/Video.h | 1 + 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/source/Applewin.cpp b/source/Applewin.cpp index b6cd6409..01579acd 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -356,7 +356,7 @@ static void ContinueExecution(void) // const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame(); - if (g_dwCyclesThisFrame >= dwClksPerFrame) + if (g_dwCyclesThisFrame >= dwClksPerFrame && !VideoGetVblBar()) { g_dwCyclesThisFrame -= dwClksPerFrame; diff --git a/source/NTSC.cpp b/source/NTSC.cpp index 87e8853f..38691c63 100644 --- a/source/NTSC.cpp +++ b/source/NTSC.cpp @@ -2003,8 +2003,12 @@ void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit //=========================================================================== void NTSC_VideoReinitialize( DWORD cyclesThisFrame, bool bInitVideoScannerAddress ) { - _ASSERT(cyclesThisFrame < g_videoScanner6502Cycles); - if (cyclesThisFrame >= g_videoScanner6502Cycles) cyclesThisFrame = 0; // error + if (cyclesThisFrame >= g_videoScanner6502Cycles) + { + // Possible, since ContinueExecution() loop waits until: cycles > g_videoScanner6502Cycles && VBL + cyclesThisFrame %= g_videoScanner6502Cycles; + } + g_nVideoClockVert = (uint16_t) (cyclesThisFrame / VIDEO_SCANNER_MAX_HORZ); g_nVideoClockHorz = cyclesThisFrame % VIDEO_SCANNER_MAX_HORZ; diff --git a/source/Video.cpp b/source/Video.cpp index a29c6e49..4440ec30 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -874,6 +874,7 @@ WORD VideoGetScannerAddress(DWORD nCycles, VideoScanner_e videoScannerAddr /*= V //=========================================================================== // TODO: Consider replacing simply with: return g_nVideoClockVert < kVDisplayableScanLines +// - will this work in full-speed mode? bool VideoGetVblBar(const DWORD uExecutedCycles) { // get video scanner position @@ -888,6 +889,11 @@ bool VideoGetVblBar(const DWORD uExecutedCycles) return nCycles < kVDisplayableScanLines * kHClocks; } +bool VideoGetVblBar(void) +{ + return g_nVideoClockVert < kVDisplayableScanLines; +} + //=========================================================================== #define MAX_DRAW_DEVICES 10 diff --git a/source/Video.h b/source/Video.h index fe566322..0bb88578 100644 --- a/source/Video.h +++ b/source/Video.h @@ -189,6 +189,7 @@ void VideoResetState (); enum VideoScanner_e {VS_FullAddr, VS_PartialAddrV, VS_PartialAddrH}; WORD VideoGetScannerAddress(DWORD nCycles, VideoScanner_e videoScannerAddr = VS_FullAddr); bool VideoGetVblBar(DWORD uExecutedCycles); +bool VideoGetVblBar(void); bool VideoGetSW80COL(void); bool VideoGetSWDHIRES(void);