From bc45812f4ea6c06700e185ea79ebe2ab4135bcda Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 13 Sep 2014 22:22:27 +0100 Subject: [PATCH 1/5] Simplified and moved main-loop video update logic into Video.cpp. Removed complex case below for: . VideoHasRefreshed(), 'anyupdates' . VideoCheckPage() Detailed notes below. --- Video updates in ContinueExecution() loop: 'anyupdates' gets set if there were any page-flip(s) in last ~17030 cycles: anyupdates |= VideoHasRefreshed(); ie. VideoRefreshScreen() was called outside of this loop. If there's been a call to VideoRefreshScreen() outside of this loop, and then the video framebuffer gets written to, ie. VideoApparentlyDirty() returns TRUE, then don't call VideoRefreshScreen() from this loop for 3 frames. (If a VideoRefreshScreen() is called outside of this loop then restart the 3 frame count.) So.. if the game is flipping, the VideoApparentlyDirty() will return FALSE (since game writes to other framebuffer). if the game is not flipping, then VideoHasRefreshed() will return FALSE (since no flips occur). Therefore this complex case above probably only arises at a boundary eg. when the game is transitioning between these 2 modes, and so if the emulator does the very occasional screen update in this main loop, it is of no consequence. (I guess this extra logic was to throttle video updates on very old slow machines) --- VideoCheckPage(BOOL bForce) was called twice in main-loop: UnexpectedPage if g_bVideoDisplayPage2 != SW_PAGE2 Once each time through the loop (ie. every 1ms), with bForce=0 if UnexpectedPage && >500ms since last flip then VideoRefreshScreen() Once each video frame (ie. ~17030 cycles) when not flipping, with bForce=1 if UnexpectedPage then VideoRefreshScreen() Basically this was all about supporting FullSpeed mode, and limiting the calls to VideoRefreshScreen(). --- source/Applewin.cpp | 30 +---- source/Debugger/Debug.cpp | 14 +-- source/Debugger/Debugger_Display.cpp | 30 ++--- source/Video.cpp | 169 ++++++++++++++++----------- source/Video.h | 36 +++--- 5 files changed, 134 insertions(+), 145 deletions(-) diff --git a/source/Applewin.cpp b/source/Applewin.cpp index dd210225..d34aa828 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -254,41 +254,13 @@ void ContinueExecution(void) emulmsec_frac %= CLKS_PER_MS; } - // DETERMINE WHETHER THE SCREEN WAS UPDATED THIS CLOCKTICK - static BOOL anyupdates = 0; - VideoCheckPage(0); // force=0 - anyupdates |= VideoHasRefreshed(); // Only called from here. Returns & clears 'hasrefreshed' flag - - // - if (g_dwCyclesThisFrame >= dwClksPerFrame) { g_dwCyclesThisFrame -= dwClksPerFrame; - VideoUpdateFlash(); - - static BOOL lastupdates[2] = {0,0}; - if (!anyupdates && !lastupdates[0] && !lastupdates[1] && VideoApparentlyDirty()) - { - VideoCheckPage(1); // force=1 - static DWORD lasttime = 0; - DWORD currtime = GetTickCount(); - if ((!g_bFullSpeed) || - (currtime-lasttime >= (DWORD)(g_bGraphicsMode ? 100 : 25))) - { - VideoRefreshScreen(); - lasttime = currtime; - } - } - - lastupdates[1] = lastupdates[0]; - lastupdates[0] = anyupdates; - anyupdates = 0; - + VideoEndOfVideoFrame(); MB_EndOfVideoFrame(); } - // - if (!g_bFullSpeed) { SysClk_WaitTimer(); diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp index 92b7e7f9..40b8d8a4 100644 --- a/source/Debugger/Debug.cpp +++ b/source/Debugger/Debug.cpp @@ -4711,9 +4711,9 @@ size_t Util_GetTextScreen ( char* &pText_ ) g_nTextScreen = 0; memset( pBeg, 0, sizeof( g_aTextScreen ) ); - int bBank2 = g_bVideoDisplayPage2; - LPBYTE g_pTextBank1 = MemGetAuxPtr (0x400 << (int)bBank2); - LPBYTE g_pTextBank0 = MemGetMainPtr(0x400 << (int)bBank2); + unsigned int uBank2 = VideoGetSWPAGE2() ? 1 : 0; + LPBYTE g_pTextBank1 = MemGetAuxPtr (0x400 << uBank2); + LPBYTE g_pTextBank0 = MemGetMainPtr(0x400 << uBank2); for( int y = 0; y < 24; y++ ) { @@ -4724,7 +4724,7 @@ size_t Util_GetTextScreen ( char* &pText_ ) { char c; // TODO: FormatCharTxtCtrl() ? - if ( g_bVideoMode & VF_80COL ) + if ( VideoGetSW80COL() ) { // AUX c = g_pTextBank1[ nAddressStart ] & 0x7F; c = RemapChar(c); @@ -4792,7 +4792,7 @@ int CmdTextSave (int nArgs) _tcscpy( g_sMemoryLoadSaveFileName, g_aArgs[ 1 ].sArg ); else { - if( g_bVideoMode & VF_80COL ) + if( VideoGetSW80COL() ) sprintf( g_sMemoryLoadSaveFileName, "AppleWin_Text80.txt" ); else sprintf( g_sMemoryLoadSaveFileName, "AppleWin_Text40.txt" ); @@ -5997,11 +5997,11 @@ Update_t _ViewOutput( ViewVideoPage_t iPage, VideoUpdateFuncPtr_t pfUpdate ); Update_t _ViewOutput( ViewVideoPage_t iPage, VideoUpdateFuncPtr_t pfUpdate ) { - g_VideoForceFullRedraw = true; + VideoSetForceFullRedraw(); _Video_Dirty(); switch( iPage ) { - case VIEW_PAGE_X: _Video_SetupBanks( g_bVideoDisplayPage2 ); break; // Page Current + case VIEW_PAGE_X: _Video_SetupBanks( VideoGetSWPAGE2() ); break; // Page Current case VIEW_PAGE_1: _Video_SetupBanks( false ); break; // Page 1 case VIEW_PAGE_2: _Video_SetupBanks( true ); break; // Page 2 ! default: diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp index e0b88ed1..7fd183bd 100644 --- a/source/Debugger/Debugger_Display.cpp +++ b/source/Debugger/Debugger_Display.cpp @@ -2735,38 +2735,38 @@ void DrawSoftSwitches( int iSoftSwitch ) // GR / TEXT // GRAPH/TEXT // TEXT ON/OFF - sprintf( sText, !(g_bVideoMode & VF_TEXT) ? "GR / ----" : "-- / TEXT" ); + sprintf( sText, !VideoGetSWTEXT() ? "GR / ----" : "-- / TEXT" ); PrintTextCursorY( sText, rect ); // $C052 / $C053 = MIXEDOFF/MIXEDON = SW.MIXCLR/SW.MIXSET // FULL/MIXED // MIX OFF/ON - sprintf( sText, !(g_bVideoMode & VF_MIXED) ? "FULL/-----" : "----/MIXED" ); + sprintf( sText, !VideoGetSWMIXED() ? "FULL/-----" : "----/MIXED" ); PrintTextCursorY( sText, rect ); // $C054 / $C055 = PAGE1/PAGE2 = PAGE2OFF/PAGE2ON = SW.LOWSCR/SW.HISCR // PAGE 1 / 2 - sprintf( sText, !(g_bVideoMode & VF_PAGE2) ? "PAGE 1 / -" : "PAGE - / 2" ); + sprintf( sText, !VideoGetSWPAGE2() ? "PAGE 1 / -" : "PAGE - / 2" ); PrintTextCursorY( sText, rect ); // $C056 / $C057 LORES/HIRES = HIRESOFF/HIRESON = SW.LORES/SW.HIRES // LO / HIRES // LO / ----- // -- / HIRES - sprintf( sText, !(g_bVideoMode & VF_HIRES) ? "LO /-- RES" : "---/HI RES" ); + sprintf( sText, !VideoGetSWHIRES() ? "LO /-- RES" : "---/HI RES" ); PrintTextCursorY( sText, rect ); PrintTextCursorY( "", rect ); // Extended soft switches - sprintf( sText, !(g_bVideoMode & VF_80COL) ? "40 / -- COL" : "-- / 80 COL" ); + sprintf( sText, !VideoGetSW80COL() ? "40 / -- COL" : "-- / 80 COL" ); PrintTextCursorY( sText, rect ); - sprintf(sText, (g_nAltCharSetOffset == 0) ? "ASCII/-----" : "-----/MOUSE" ); + sprintf(sText, VideoGetSWAltCharSet() ? "ASCII/-----" : "-----/MOUSE" ); PrintTextCursorY( sText, rect ); // 280/560 HGR - sprintf(sText, !(g_bVideoMode & VF_DHIRES) ? "HGR / ----" : "--- / DHGR" ); + sprintf(sText, !VideoGetSWDHIRES() ? "HGR / ----" : "--- / DHGR" ); PrintTextCursorY( sText, rect ); #else //SOFTSWITCH_OLD // See: VideoSetMode() @@ -2778,25 +2778,25 @@ void DrawSoftSwitches( int iSoftSwitch ) bool bSet; // $C050 / $C051 = TEXTOFF/TEXTON = SW.TXTCLR/SW.TXTSET - bSet = !(g_bVideoMode & VF_TEXT); + bSet = !VideoGetSWTEXT(); _DrawSoftSwitch( rect, 0xC050, bSet, NULL, "GR.", "TEXT" ); // $C052 / $C053 = MIXEDOFF/MIXEDON = SW.MIXCLR/SW.MIXSET // FULL/MIXED // MIX OFF/ON - bSet = !(g_bVideoMode & VF_MIXED); + bSet = !VideoGetSWMIXED(); _DrawSoftSwitch( rect, 0xC052, bSet, NULL, "FULL", "MIX" ); // $C054 / $C055 = PAGE1/PAGE2 = PAGE2OFF/PAGE2ON = SW.LOWSCR/SW.HISCR // PAGE 1 / 2 - bSet = !(g_bVideoMode & VF_PAGE2); + bSet = !VideoGetSWPAGE2(); _DrawSoftSwitch( rect, 0xC054, bSet, "PAGE ", "1", "2" ); // $C056 / $C057 LORES/HIRES = HIRESOFF/HIRESON = SW.LORES/SW.HIRES // LO / HIRES // LO / ----- // -- / HIRES - bSet = !(g_bVideoMode & VF_HIRES); + bSet = !VideoGetSWHIRES(); _DrawSoftSwitch( rect, 0xC056, bSet, NULL, "LO", "HI", "RES" ); DebuggerSetColorBG( DebuggerGetColor( BG_INFO )); @@ -2805,20 +2805,20 @@ void DrawSoftSwitches( int iSoftSwitch ) // 280/560 HGR // C05E = ON, C05F = OFF - bSet = (g_bVideoMode & VF_DHIRES) ? true : false; + bSet = VideoGetSWDHIRES(); _DrawSoftSwitch( rect, 0xC05E, bSet, NULL, "DHGR", "HGR" ); // Extended soft switches // C00C = off, C00D = on - bSet = !(g_bVideoMode & VF_80COL); + bSet = !VideoGetSW80COL(); _DrawSoftSwitch( rect, 0xC00C, bSet, "Col", "40", "80" ); // C00E = off, C00F = on - bSet = (g_nAltCharSetOffset == 0); + bSet = VideoGetSWAltCharSet(); _DrawSoftSwitch( rect, 0xC00E, bSet, NULL, "ASC", "MOUS" ); // ASCII/MouseText // C000 = 80STOREOFF, C001 = 80STOREON - bSet = !(g_bVideoMode & VF_MASK2); + bSet = !VideoGetSW80STORE(); _DrawSoftSwitch( rect, 0xC000, bSet, "80Sto", "0", "1" ); #endif // SOFTSWITCH_OLD } diff --git a/source/Video.cpp b/source/Video.cpp index 9060d26e..58dbfc27 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -197,10 +197,21 @@ const BYTE DoubleHiresPalIndex[16] = { const int SRCOFFS_DHIRES = (SRCOFFS_HIRES + 512); // 1168 const int SRCOFFS_TOTAL = (SRCOFFS_DHIRES + 2560); // 3278 + enum VideoFlag_e + { + VF_80COL = 0x00000001, + VF_DHIRES = 0x00000002, + VF_HIRES = 0x00000004, + VF_80STORE= 0x00000008, + VF_MIXED = 0x00000010, + VF_PAGE2 = 0x00000020, + VF_TEXT = 0x00000040 + }; + #define SW_80COL (g_bVideoMode & VF_80COL) #define SW_DHIRES (g_bVideoMode & VF_DHIRES) #define SW_HIRES (g_bVideoMode & VF_HIRES) - #define SW_MASK2 (g_bVideoMode & VF_MASK2) + #define SW_80STORE (g_bVideoMode & VF_80STORE) #define SW_MIXED (g_bVideoMode & VF_MIXED) #define SW_PAGE2 (g_bVideoMode & VF_PAGE2) #define SW_TEXT (g_bVideoMode & VF_TEXT) @@ -261,24 +272,21 @@ static BYTE colormixbuffer[6]; static WORD colormixmap[6][6][6]; // - int g_nAltCharSetOffset = 0; // alternate character set +static int g_nAltCharSetOffset = 0; // alternate character set - bool g_bVideoDisplayPage2 = 0; - /*bool*/ UINT g_VideoForceFullRedraw = 1; +static /*bool*/ UINT g_VideoForceFullRedraw = 1; static LPBYTE framebufferaddr = (LPBYTE)0; static LONG g_nFrameBufferPitch = 0; -BOOL g_bGraphicsMode = 0; -static BOOL hasrefreshed = 0; static DWORD lastpageflip = 0; COLORREF monochrome = RGB(0xC0,0xC0,0xC0); static BOOL rebuiltsource = 0; static LPBYTE vidlastmem = NULL; - int g_bVideoMode = VF_TEXT; +static int g_bVideoMode = VF_TEXT; DWORD g_eVideoType = VT_COLOR_TVEMU; - DWORD g_uHalfScanLines = true; // drop 50% scan lines for a more authentic look + DWORD g_uHalfScanLines = 1; // drop 50% scan lines for a more authentic look static bool g_bTextFlashState = false; @@ -1924,8 +1932,8 @@ BOOL VideoApparentlyDirty () return 1; DWORD address = (SW_HIRES && !SW_TEXT) - ? (0x20 << (int)g_bVideoDisplayPage2) - : (0x04 << (int)g_bVideoDisplayPage2); + ? (0x20 << (SW_PAGE2 ? 1 : 0)) + : (0x04 << (SW_PAGE2 ? 1 : 0)); DWORD length = (SW_HIRES && !SW_TEXT) ? 0x20 : 0x4; while (length--) if (*(memdirty+(address++)) & 2) @@ -1938,7 +1946,7 @@ BOOL VideoApparentlyDirty () // Scan visible text page for any flashing chars if((SW_TEXT || SW_MIXED) && (g_nAltCharSetOffset == 0)) { - BYTE* pnMemText = MemGetMainPtr(0x400 << (int)g_bVideoDisplayPage2); + BYTE* pnMemText = MemGetMainPtr(0x400 << (SW_PAGE2 ? 1 : 0)); // Scan 8 long-lines of 120 chars (at 128 char offsets): // . Skip 8-char holes in TEXT @@ -2154,25 +2162,6 @@ BYTE VideoCheckMode (WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles) //=========================================================================== -// Check if we should call VideoRefreshScreen() based on unexpected page -// - Only called from 2 places in main ContinueExecution() loop -void VideoCheckPage(BOOL force) -{ - const bool bUnexpectedPage = (g_bVideoDisplayPage2 != (SW_PAGE2 != 0)); - //_ASSERT(!bUnexpectedPage); // [TC] Q: When does this happen? A: EG. When page-flipping && Scroll-Lock is pressed - - if (bUnexpectedPage && // Unexpected page && - (force || (emulmsec-lastpageflip > 500))) // force || >500ms since last flip - { - g_bVideoDisplayPage2 = (SW_PAGE2 != 0); - VideoRefreshScreen(); - hasrefreshed = 1; - lastpageflip = emulmsec; - } -} - -//=========================================================================== - /* // Drol expects = 80 68DE A5 02 LDX #02 @@ -2384,13 +2373,6 @@ void VideoDisplayLogo () DeleteObject(font); } -//=========================================================================== -BOOL VideoHasRefreshed () { - BOOL result = hasrefreshed; - hasrefreshed = 0; - return result; -} - //=========================================================================== void VideoRealizePalette(HDC dc) { @@ -2505,7 +2487,7 @@ VideoUpdateFuncPtr_t VideoRefreshScreen () // IN THE FRAME BUFFER. MARK CELLS IN WHICH REDRAWING HAS TAKEN PLACE AS // DIRTY. _Video_Dirty(); - _Video_SetupBanks( g_bVideoDisplayPage2 ); + _Video_SetupBanks( SW_PAGE2 != 0 ); VideoUpdateFuncPtr_t pfUpdate = SW_TEXT ? SW_80COL @@ -2694,15 +2676,8 @@ void VideoReinitialize () void VideoResetState () { g_nAltCharSetOffset = 0; - g_bVideoDisplayPage2 = 0; g_bVideoMode = VF_TEXT; g_VideoForceFullRedraw = 1; - -#if 0 // Debug HGR2 without having to exec 6502 code - g_bVideoDisplayPage2 = 1; - g_bVideoMode = VF_TEXT | VF_HIRES; -#endif - } @@ -2711,10 +2686,12 @@ BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles) { address &= 0xFF; DWORD oldpage2 = SW_PAGE2; - int oldvalue = g_nAltCharSetOffset+(int)(g_bVideoMode & ~(VF_MASK2 | VF_PAGE2)); - switch (address) { - case 0x00: g_bVideoMode &= ~VF_MASK2; break; - case 0x01: g_bVideoMode |= VF_MASK2; break; + int oldvalue = g_nAltCharSetOffset+(int)(g_bVideoMode & ~(VF_80STORE | VF_PAGE2)); + + switch (address) + { + case 0x00: g_bVideoMode &= ~VF_80STORE; break; + case 0x01: g_bVideoMode |= VF_80STORE; break; case 0x0C: if (!IS_APPLE2) g_bVideoMode &= ~VF_80COL; break; case 0x0D: if (!IS_APPLE2) g_bVideoMode |= VF_80COL; break; case 0x0E: if (!IS_APPLE2) g_nAltCharSetOffset = 0; break; // Alternate char set off @@ -2730,29 +2707,21 @@ BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles) case 0x5E: if (!IS_APPLE2) g_bVideoMode |= VF_DHIRES; break; case 0x5F: if (!IS_APPLE2) g_bVideoMode &= ~VF_DHIRES; break; } - if (SW_MASK2) + + if (SW_80STORE) g_bVideoMode &= ~VF_PAGE2; - if (oldvalue != g_nAltCharSetOffset+(int)(g_bVideoMode & ~(VF_MASK2 | VF_PAGE2))) { - g_bGraphicsMode = !SW_TEXT; - g_VideoForceFullRedraw = 1; - } - if (g_bFullSpeed && oldpage2 && !SW_PAGE2) { - static DWORD lasttime = 0; - DWORD currtime = GetTickCount(); - if (currtime-lasttime >= 20) - lasttime = currtime; - else - oldpage2 = SW_PAGE2; + + if (oldvalue != g_nAltCharSetOffset+(int)(g_bVideoMode & ~(VF_80STORE | VF_PAGE2))) + { + g_VideoForceFullRedraw = 1; } if (oldpage2 != SW_PAGE2) { - g_bVideoDisplayPage2 = (SW_PAGE2 != 0); if (!g_VideoForceFullRedraw) { #if 1 VideoRefreshScreen(); - hasrefreshed = 1; #else g_VideoForceFullRedraw = 1; // GH#129,GH204: Defer the redraw until the main ContinueExecution() loop (TODO: What effect does this have on other games?) #endif @@ -2766,7 +2735,7 @@ BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles) //=========================================================================== // Called at 60Hz (every 16.666ms) -void VideoUpdateFlash() +static void VideoUpdateFlash() { static UINT nTextFlashCnt = 0; @@ -2788,11 +2757,75 @@ void VideoUpdateFlash() //=========================================================================== -bool VideoGetSW80COL() +// Called from main-loop every 17030 cycles (ie. 60Hz when CPU = 1MHz) +void VideoEndOfVideoFrame(void) +{ + VideoUpdateFlash(); // TODO: Flash rate should be constant (regardless of CPU speed) + + if (!VideoApparentlyDirty()) + return; + + // Apple II is not page flipping... + + static DWORD dwLastTime = 0; + DWORD dwCurrTime = GetTickCount(); + if (!g_bFullSpeed || + (dwCurrTime-dwLastTime >= 100)) // FullSpeed: update every 100ms + { + VideoRefreshScreen(); + dwLastTime = dwCurrTime; + } +} + +//=========================================================================== + +bool VideoGetSW80COL(void) { return SW_80COL ? true : false; } +bool VideoGetSWDHIRES(void) +{ + return SW_DHIRES ? true : false; +} + +bool VideoGetSWHIRES(void) +{ + return SW_HIRES ? true : false; +} + +bool VideoGetSW80STORE(void) +{ + return SW_80STORE ? true : false; +} + +bool VideoGetSWMIXED(void) +{ + return SW_MIXED ? true : false; +} + +bool VideoGetSWPAGE2(void) +{ + return SW_PAGE2 ? true : false; +} + +bool VideoGetSWTEXT(void) +{ + return SW_TEXT ? true : false; +} + +bool VideoGetSWAltCharSet(void) +{ + return g_nAltCharSetOffset == 0; +} + +//=========================================================================== + +void VideoSetForceFullRedraw(void) +{ + g_VideoForceFullRedraw = 1; +} + //=========================================================================== DWORD VideoGetSnapshot(SS_IO_Video* pSS) @@ -2808,12 +2841,6 @@ DWORD VideoSetSnapshot(SS_IO_Video* pSS) { g_nAltCharSetOffset = !pSS->bAltCharSet ? 0 : 256; g_bVideoMode = pSS->dwVidMode; - - // - - g_bGraphicsMode = !SW_TEXT; - g_bVideoDisplayPage2 = (SW_PAGE2 != 0); - return 0; } diff --git a/source/Video.h b/source/Video.h index afee07c5..9aa270b9 100644 --- a/source/Video.h +++ b/source/Video.h @@ -19,17 +19,6 @@ extern TCHAR g_aVideoChoices[]; extern char *g_apVideoModeDesc[ NUM_VIDEO_MODES ]; - enum VideoFlag_e - { - VF_80COL = 0x00000001, - VF_DHIRES = 0x00000002, - VF_HIRES = 0x00000004, - VF_MASK2 = 0x00000008, - VF_MIXED = 0x00000010, - VF_PAGE2 = 0x00000020, - VF_TEXT = 0x00000040 - }; - enum AppleFont_e { // 40-Column mode is 1x Zoom (default) @@ -57,15 +46,11 @@ enum AppleFont_e extern HBITMAP g_hLogoBitmap; -extern BOOL g_bGraphicsMode; extern COLORREF monochrome; // saved extern DWORD g_eVideoType; // saved extern DWORD g_uHalfScanLines; // saved extern LPBYTE g_pFramebufferbits; -extern int g_nAltCharSetOffset; -extern int g_bVideoMode; // g_bVideoMode - typedef bool (*VideoUpdateFuncPtr_t)(int,int,int,int,int); // Prototypes _______________________________________________________ @@ -74,12 +59,10 @@ void CreateColorMixMap(); BOOL VideoApparentlyDirty (); void VideoBenchmark (); -void VideoCheckPage (BOOL); void VideoChooseColor (); void VideoDestroy (); void VideoDrawLogoBitmap(HDC hDstDC, int xoff, int yoff, int srcw, int srch, int scale); void VideoDisplayLogo (); -BOOL VideoHasRefreshed (); void VideoInitialize (); void VideoRealizePalette (HDC); VideoUpdateFuncPtr_t VideoRedrawScreen (UINT); @@ -89,15 +72,22 @@ void VideoReinitialize (); void VideoResetState (); WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles); bool VideoGetVbl(DWORD uExecutedCycles); -void VideoUpdateFlash(); -bool VideoGetSW80COL(); +void VideoEndOfVideoFrame(void); + +bool VideoGetSW80COL(void); +bool VideoGetSWDHIRES(void); +bool VideoGetSWHIRES(void); +bool VideoGetSW80STORE(void); +bool VideoGetSWMIXED(void); +bool VideoGetSWPAGE2(void); +bool VideoGetSWTEXT(void); +bool VideoGetSWAltCharSet(void); + +void VideoSetForceFullRedraw(void); + DWORD VideoGetSnapshot(SS_IO_Video* pSS); DWORD VideoSetSnapshot(SS_IO_Video* pSS); - -extern bool g_bVideoDisplayPage2; -extern /*bool*/ UINT g_VideoForceFullRedraw; - void _Video_Dirty(); void _Video_RedrawScreen( VideoUpdateFuncPtr_t update, bool bMixed = false ); void _Video_SetupBanks( bool bBank2 ); From 1f892a27d41416d6c0f6faef667ffc9fe1dc5d46 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 14 Sep 2014 16:12:55 +0100 Subject: [PATCH 2/5] Simplified main-loop a bit more, and removed more globals from AppleWin.cpp --- source/Applewin.cpp | 21 +++------------------ source/Applewin.h | 1 - source/CPU.cpp | 24 ++++++++++++++++++++++++ source/CPU.h | 2 ++ source/Memory.cpp | 9 +-------- source/Memory.h | 1 - source/Video.cpp | 13 ++++++------- 7 files changed, 36 insertions(+), 35 deletions(-) diff --git a/source/Applewin.cpp b/source/Applewin.cpp index d34aa828..da398bff 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -63,8 +63,6 @@ eApple2Type g_Apple2Type = A2TYPE_APPLE2EENHANCED; DWORD cumulativecycles = 0; // Wraps after ~1hr 9mins DWORD cyclenum = 0; // Used by SpkrToggle() for non-wave sound -DWORD emulmsec = 0; -static DWORD emulmsec_frac = 0; bool g_bFullSpeed = false; //Pravets 8A/C variables @@ -229,14 +227,10 @@ void ContinueExecution(void) if (nCyclesToExecute < 0) nCyclesToExecute = 0; - DWORD dwExecutedCycles = CpuExecute(nCyclesToExecute); - g_dwCyclesThisFrame += dwExecutedCycles; + cyclenum = CpuExecute(nCyclesToExecute); + g_dwCyclesThisFrame += cyclenum; - // - - cyclenum = dwExecutedCycles; - - DiskUpdatePosition(dwExecutedCycles); + DiskUpdatePosition(cyclenum); JoyUpdatePosition(); SpkrUpdate(cyclenum); @@ -245,15 +239,6 @@ void ContinueExecution(void) // - const DWORD CLKS_PER_MS = (DWORD)g_fCurrentCLK6502 / 1000; - - emulmsec_frac += dwExecutedCycles; - if (emulmsec_frac > CLKS_PER_MS) - { - emulmsec += emulmsec_frac / CLKS_PER_MS; - emulmsec_frac %= CLKS_PER_MS; - } - if (g_dwCyclesThisFrame >= dwClksPerFrame) { g_dwCyclesThisFrame -= dwClksPerFrame; diff --git a/source/Applewin.h b/source/Applewin.h index 85ceae66..365948e4 100644 --- a/source/Applewin.h +++ b/source/Applewin.h @@ -15,7 +15,6 @@ extern eApple2Type g_Apple2Type; extern DWORD cumulativecycles; extern DWORD cyclenum; -extern DWORD emulmsec; extern bool g_bFullSpeed; //Pravets 8A/C only variables diff --git a/source/CPU.cpp b/source/CPU.cpp index f54cdb45..fc8829d5 100644 --- a/source/CPU.cpp +++ b/source/CPU.cpp @@ -465,6 +465,29 @@ ULONG CpuGetCyclesThisVideoFrame(const ULONG nExecutedCycles) } #endif +//--------------------------------------------------------------------------- + +static DWORD g_dwEmulationTime_ms = 0; + +static void UpdateEmulationTime(const DWORD dwExecutedCycles) +{ + static DWORD dwEmulationTimeFrac_clks = 0; + + const DWORD CLKS_PER_MS = (DWORD)g_fCurrentCLK6502 / 1000; + + dwEmulationTimeFrac_clks += dwExecutedCycles; + if (dwEmulationTimeFrac_clks > CLKS_PER_MS) + { + g_dwEmulationTime_ms += dwEmulationTimeFrac_clks / CLKS_PER_MS; + dwEmulationTimeFrac_clks %= CLKS_PER_MS; + } +} + +DWORD CpuGetEmulationTime_ms(void) +{ + return g_dwEmulationTime_ms; +} + //=========================================================================== DWORD CpuExecute(const DWORD uCycles) @@ -479,6 +502,7 @@ DWORD CpuExecute(const DWORD uCycles) const DWORD uExecutedCycles = InternalCpuExecute(uCycles); MB_UpdateCycles(uExecutedCycles); // Update 6522s (NB. Do this before updating g_nCumulativeCycles below) + UpdateEmulationTime(uExecutedCycles); // diff --git a/source/CPU.h b/source/CPU.h index 2e21591b..58c5d886 100644 --- a/source/CPU.h +++ b/source/CPU.h @@ -31,3 +31,5 @@ DWORD CpuSetSnapshot(SS_CPU6502* pSS); BYTE CpuRead(USHORT addr, ULONG uExecutedCycles); void CpuWrite(USHORT addr, BYTE a, ULONG uExecutedCycles); + +DWORD CpuGetEmulationTime_ms(void); diff --git a/source/Memory.cpp b/source/Memory.cpp index 25f00c92..f1a19fd9 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -88,7 +88,7 @@ MEMORY MANAGEMENT SOFT SWITCHES $C005 W RAMWRTON Write enable aux memory from $0200-$BFFF $C006 W INTCXROMOFF Enable slot ROM from $C100-$CFFF $C007 W INTCXROMON Enable main ROM from $C100-$CFFF - $C008 W ALZTPOFF Enable main memory from $0000-$01FF & avl BSR + $C008 W ALTZPOFF Enable main memory from $0000-$01FF & avl BSR $C009 W ALTZPON Enable aux memory from $0000-$01FF & avl BSR $C00A W SLOTC3ROMOFF Enable main ROM from $C300-$C3FF $C00B W SLOTC3ROMON Enable slot ROM from $C300-$C3FF @@ -1074,13 +1074,6 @@ void MemDestroy () //=========================================================================== -bool MemGet80Store() -{ - return SW_80STORE != 0; -} - -//=========================================================================== - bool MemCheckSLOTCXROM() { return SW_SLOTCXROM ? true : false; diff --git a/source/Memory.h b/source/Memory.h index 55ff2065..c418422c 100644 --- a/source/Memory.h +++ b/source/Memory.h @@ -38,7 +38,6 @@ extern UINT g_uMaxExPages; // user requested ram pages (from cmd line) void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, iofunction IOReadCx, iofunction IOWriteCx, LPVOID lpSlotParameter, BYTE* pExpansionRom); void MemDestroy (); -bool MemGet80Store(); bool MemCheckSLOTCXROM(); LPBYTE MemGetAuxPtr(const WORD); LPBYTE MemGetMainPtr(const WORD); diff --git a/source/Video.cpp b/source/Video.cpp index 58dbfc27..eeb64f0d 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -278,12 +278,11 @@ static /*bool*/ UINT g_VideoForceFullRedraw = 1; static LPBYTE framebufferaddr = (LPBYTE)0; static LONG g_nFrameBufferPitch = 0; -static DWORD lastpageflip = 0; COLORREF monochrome = RGB(0xC0,0xC0,0xC0); static BOOL rebuiltsource = 0; static LPBYTE vidlastmem = NULL; -static int g_bVideoMode = VF_TEXT; +static UINT g_bVideoMode = VF_TEXT; DWORD g_eVideoType = VT_COLOR_TVEMU; DWORD g_uHalfScanLines = 1; // drop 50% scan lines for a more authentic look @@ -2465,8 +2464,9 @@ static void DebugRefresh(char uDebugFlag) { static DWORD uLastRefreshTime = 0; - const DWORD uTimeBetweenRefreshes = uLastRefreshTime ? emulmsec - uLastRefreshTime : 0; - uLastRefreshTime = emulmsec; + const DWORD dwEmuTime_ms = CpuGetEmulationTime_ms(); + const DWORD uTimeBetweenRefreshes = uLastRefreshTime ? dwEmuTime_ms - uLastRefreshTime : 0; + uLastRefreshTime = dwEmuTime_ms; if (!uTimeBetweenRefreshes) return; // 1st time in func @@ -2726,7 +2726,6 @@ BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles) g_VideoForceFullRedraw = 1; // GH#129,GH204: Defer the redraw until the main ContinueExecution() loop (TODO: What effect does this have on other games?) #endif } - lastpageflip = emulmsec; } return MemReadFloatingBus(uExecutedCycles); @@ -2858,8 +2857,8 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles) // machine state switches // int nHires = (SW_HIRES && !SW_TEXT) ? 1 : 0; - int nPage2 = (SW_PAGE2) ? 1 : 0; - int n80Store = (MemGet80Store()) ? 1 : 0; + int nPage2 = SW_PAGE2 ? 1 : 0; + int n80Store = SW_80STORE ? 1 : 0; // calculate video parameters according to display standard // From 0db62489f975eb80d55af6824d54fd5fbb44bedc Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 14 Sep 2014 16:15:14 +0100 Subject: [PATCH 3/5] Refactor: g_bVideoMode -> g_uVideoMode --- source/Video.cpp | 60 ++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/source/Video.cpp b/source/Video.cpp index eeb64f0d..0bb423fc 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -208,13 +208,13 @@ const BYTE DoubleHiresPalIndex[16] = { VF_TEXT = 0x00000040 }; - #define SW_80COL (g_bVideoMode & VF_80COL) - #define SW_DHIRES (g_bVideoMode & VF_DHIRES) - #define SW_HIRES (g_bVideoMode & VF_HIRES) - #define SW_80STORE (g_bVideoMode & VF_80STORE) - #define SW_MIXED (g_bVideoMode & VF_MIXED) - #define SW_PAGE2 (g_bVideoMode & VF_PAGE2) - #define SW_TEXT (g_bVideoMode & VF_TEXT) + #define SW_80COL (g_uVideoMode & VF_80COL) + #define SW_DHIRES (g_uVideoMode & VF_DHIRES) + #define SW_HIRES (g_uVideoMode & VF_HIRES) + #define SW_80STORE (g_uVideoMode & VF_80STORE) + #define SW_MIXED (g_uVideoMode & VF_MIXED) + #define SW_PAGE2 (g_uVideoMode & VF_PAGE2) + #define SW_TEXT (g_uVideoMode & VF_TEXT) #define SETSOURCEPIXEL(x,y,c) g_aSourceStartofLine[(y)][(x)] = (c) @@ -282,7 +282,7 @@ COLORREF monochrome = RGB(0xC0,0xC0,0xC0); static BOOL rebuiltsource = 0; static LPBYTE vidlastmem = NULL; -static UINT g_bVideoMode = VF_TEXT; +static UINT g_uVideoMode = VF_TEXT; DWORD g_eVideoType = VT_COLOR_TVEMU; DWORD g_uHalfScanLines = 1; // drop 50% scan lines for a more authentic look @@ -1988,7 +1988,7 @@ void VideoBenchmark () { // GOING ON, CHANGING HALF OF THE BYTES IN THE VIDEO BUFFER EACH FRAME TO // SIMULATE THE ACTIVITY OF AN AVERAGE GAME DWORD totaltextfps = 0; - g_bVideoMode = VF_TEXT; + g_uVideoMode = VF_TEXT; FillMemory(mem+0x400,0x400,0x14); VideoRedrawScreen(); DWORD milliseconds = GetTickCount(); @@ -2010,7 +2010,7 @@ void VideoBenchmark () { // GOING ON, CHANGING HALF OF THE BYTES IN THE VIDEO BUFFER EACH FRAME TO // SIMULATE THE ACTIVITY OF AN AVERAGE GAME DWORD totalhiresfps = 0; - g_bVideoMode = VF_HIRES; + g_uVideoMode = VF_HIRES; FillMemory(mem+0x2000,0x2000,0x14); VideoRedrawScreen(); milliseconds = GetTickCount(); @@ -2676,7 +2676,7 @@ void VideoReinitialize () void VideoResetState () { g_nAltCharSetOffset = 0; - g_bVideoMode = VF_TEXT; + g_uVideoMode = VF_TEXT; g_VideoForceFullRedraw = 1; } @@ -2686,32 +2686,32 @@ BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles) { address &= 0xFF; DWORD oldpage2 = SW_PAGE2; - int oldvalue = g_nAltCharSetOffset+(int)(g_bVideoMode & ~(VF_80STORE | VF_PAGE2)); + int oldvalue = g_nAltCharSetOffset+(int)(g_uVideoMode & ~(VF_80STORE | VF_PAGE2)); switch (address) { - case 0x00: g_bVideoMode &= ~VF_80STORE; break; - case 0x01: g_bVideoMode |= VF_80STORE; break; - case 0x0C: if (!IS_APPLE2) g_bVideoMode &= ~VF_80COL; break; - case 0x0D: if (!IS_APPLE2) g_bVideoMode |= VF_80COL; break; + case 0x00: g_uVideoMode &= ~VF_80STORE; break; + case 0x01: g_uVideoMode |= VF_80STORE; break; + case 0x0C: if (!IS_APPLE2) g_uVideoMode &= ~VF_80COL; break; + case 0x0D: if (!IS_APPLE2) g_uVideoMode |= VF_80COL; break; case 0x0E: if (!IS_APPLE2) g_nAltCharSetOffset = 0; break; // Alternate char set off case 0x0F: if (!IS_APPLE2) g_nAltCharSetOffset = 256; break; // Alternate char set on - case 0x50: g_bVideoMode &= ~VF_TEXT; break; - case 0x51: g_bVideoMode |= VF_TEXT; break; - case 0x52: g_bVideoMode &= ~VF_MIXED; break; - case 0x53: g_bVideoMode |= VF_MIXED; break; - case 0x54: g_bVideoMode &= ~VF_PAGE2; break; - case 0x55: g_bVideoMode |= VF_PAGE2; break; - case 0x56: g_bVideoMode &= ~VF_HIRES; break; - case 0x57: g_bVideoMode |= VF_HIRES; break; - case 0x5E: if (!IS_APPLE2) g_bVideoMode |= VF_DHIRES; break; - case 0x5F: if (!IS_APPLE2) g_bVideoMode &= ~VF_DHIRES; break; + case 0x50: g_uVideoMode &= ~VF_TEXT; break; + case 0x51: g_uVideoMode |= VF_TEXT; break; + case 0x52: g_uVideoMode &= ~VF_MIXED; break; + case 0x53: g_uVideoMode |= VF_MIXED; break; + case 0x54: g_uVideoMode &= ~VF_PAGE2; break; + case 0x55: g_uVideoMode |= VF_PAGE2; break; + case 0x56: g_uVideoMode &= ~VF_HIRES; break; + case 0x57: g_uVideoMode |= VF_HIRES; break; + case 0x5E: if (!IS_APPLE2) g_uVideoMode |= VF_DHIRES; break; + case 0x5F: if (!IS_APPLE2) g_uVideoMode &= ~VF_DHIRES; break; } if (SW_80STORE) - g_bVideoMode &= ~VF_PAGE2; + g_uVideoMode &= ~VF_PAGE2; - if (oldvalue != g_nAltCharSetOffset+(int)(g_bVideoMode & ~(VF_80STORE | VF_PAGE2))) + if (oldvalue != g_nAltCharSetOffset+(int)(g_uVideoMode & ~(VF_80STORE | VF_PAGE2))) { g_VideoForceFullRedraw = 1; } @@ -2830,7 +2830,7 @@ void VideoSetForceFullRedraw(void) DWORD VideoGetSnapshot(SS_IO_Video* pSS) { pSS->bAltCharSet = !(g_nAltCharSetOffset == 0); - pSS->dwVidMode = g_bVideoMode; + pSS->dwVidMode = g_uVideoMode; return 0; } @@ -2839,7 +2839,7 @@ DWORD VideoGetSnapshot(SS_IO_Video* pSS) DWORD VideoSetSnapshot(SS_IO_Video* pSS) { g_nAltCharSetOffset = !pSS->bAltCharSet ? 0 : 256; - g_bVideoMode = pSS->dwVidMode; + g_uVideoMode = pSS->dwVidMode; return 0; } From 8c019bcd357dd3fc370aac6db5f1addd67188eb1 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 14 Sep 2014 21:23:54 +0100 Subject: [PATCH 4/5] More main-loop reduction & removal of redundant globals. Fixed JoyUpdateButtonLatch() to debounce in 5mecs instead of 5secs! SpkrToggle() was using redundant global ('cyclenum') when using the PC speaker. . I reworked the code (as it looked out-of-date), but probably better to just remove all the PC speaker support. --- source/Applewin.cpp | 51 +++++++-------------------------------------- source/Applewin.h | 2 -- source/CPU.cpp | 24 +++++++++++++-------- source/Joystick.cpp | 20 ++++++++++++------ source/Joystick.h | 2 +- source/Speaker.cpp | 9 +++++--- source/Video.cpp | 2 +- 7 files changed, 45 insertions(+), 65 deletions(-) diff --git a/source/Applewin.cpp b/source/Applewin.cpp index da398bff..a4d5ee05 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "DiskImage.h" #include "Frame.h" #include "Harddisk.h" +#include "Joystick.h" #include "Log.h" #include "Memory.h" #include "Mockingboard.h" @@ -61,8 +62,6 @@ TCHAR *g_pAppTitle = TITLE_APPLE_2E_ENHANCED; eApple2Type g_Apple2Type = A2TYPE_APPLE2EENHANCED; -DWORD cumulativecycles = 0; // Wraps after ~1hr 9mins -DWORD cyclenum = 0; // Used by SpkrToggle() for non-wave sound bool g_bFullSpeed = false; //Pravets 8A/C variables @@ -76,7 +75,6 @@ HINSTANCE g_hInstance = (HINSTANCE)0; AppMode_e g_nAppMode = MODE_LOGO; static bool g_bLoadedSaveState = false; -static int lastmode = MODE_LOGO; TCHAR g_sProgramDir[MAX_PATH] = TEXT(""); // Directory of where AppleWin executable resides TCHAR g_sDebugDir [MAX_PATH] = TEXT(""); // TODO: Not currently used TCHAR g_sScreenShotDir[MAX_PATH] = TEXT(""); // TODO: Not currently used @@ -115,17 +113,6 @@ CSpeech g_Speech; //=========================================================================== -#define DBG_CALC_FREQ 0 -#if DBG_CALC_FREQ -const UINT MAX_CNT = 256; -double g_fDbg[MAX_CNT]; -UINT g_nIdx = 0; -double g_fMeanPeriod,g_fMeanFreq; -ULONGLONG g_nPerfFreq = 0; -#endif - -//--------------------------------------------------------------------------- - bool GetLoadedSaveStateFlag(void) { return g_bLoadedSaveState; @@ -227,15 +214,15 @@ void ContinueExecution(void) if (nCyclesToExecute < 0) nCyclesToExecute = 0; - cyclenum = CpuExecute(nCyclesToExecute); - g_dwCyclesThisFrame += cyclenum; + const DWORD uActualCyclesExecuted = CpuExecute(nCyclesToExecute); + g_dwCyclesThisFrame += uActualCyclesExecuted; - DiskUpdatePosition(cyclenum); - JoyUpdatePosition(); + DiskUpdatePosition(uActualCyclesExecuted); + JoyUpdateButtonLatch(nExecutionPeriodUsec); // Button latch time is independent of CPU clock frequency - SpkrUpdate(cyclenum); - sg_SSC.CommUpdate(cyclenum); - PrintUpdate(cyclenum); + SpkrUpdate(uActualCyclesExecuted); + sg_SSC.CommUpdate(uActualCyclesExecuted); + PrintUpdate(uActualCyclesExecuted); // @@ -249,23 +236,6 @@ void ContinueExecution(void) if (!g_bFullSpeed) { SysClk_WaitTimer(); - -#if DBG_CALC_FREQ - if (g_nPerfFreq) - { - QueryPerformanceCounter((LARGE_INTEGER*)&nTime1); - LONGLONG nTimeDiff = nTime1 - nTime0; - double fTime = (double)nTimeDiff / (double)(LONGLONG)g_nPerfFreq; - - g_fDbg[g_nIdx] = fTime; - g_nIdx = (g_nIdx+1) & (MAX_CNT-1); - g_fMeanPeriod = 0.0; - for(UINT n=0; n> 8) PUSH(regs.pc & 0xFF) EF_TO_AF @@ -369,7 +373,9 @@ static __forceinline void IRQ(ULONG& uExecutedCycles, UINT& uExtraCycles, BOOL& if(g_bmIRQ && !(regs.ps & AF_INTERRUPT)) { // IRQ signals are deasserted when a specific r/w operation is done on device +#ifdef _DEBUG g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles; +#endif PUSH(regs.pc >> 8) PUSH(regs.pc & 0xFF) EF_TO_AF diff --git a/source/Joystick.cpp b/source/Joystick.cpp index 3b232378..00141aa5 100644 --- a/source/Joystick.cpp +++ b/source/Joystick.cpp @@ -45,7 +45,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "Configuration\PropertySheet.h" -#define BUTTONTIME 5000 // TODO: Describe this magic number +#define BUTTONTIME 5000 // This is the latch (debounce) time in usecs for the joystick buttons enum {DEVICE_NONE=0, DEVICE_JOYSTICK, DEVICE_KEYBOARD, DEVICE_MOUSE}; @@ -82,7 +82,7 @@ static POINT keyvalue[9] = {{PDL_MIN,PDL_MAX}, {PDL_CENTRAL,PDL_MAX}, {PDL {PDL_MIN,PDL_CENTRAL},{PDL_CENTRAL,PDL_CENTRAL},{PDL_MAX,PDL_CENTRAL}, {PDL_MIN,PDL_MIN}, {PDL_CENTRAL,PDL_MIN}, {PDL_MAX,PDL_MIN}}; -static DWORD buttonlatch[3] = {0,0,0}; +static int buttonlatch[3] = {0,0,0}; static BOOL joybutton[3] = {0,0,0}; static int joyshrx[2] = {8,8}; @@ -703,11 +703,19 @@ void JoySetPosition(int xvalue, int xrange, int yvalue, int yrange) } //=========================================================================== -void JoyUpdatePosition() + +// Update the latch (debounce) time for each button +void JoyUpdateButtonLatch(const UINT nExecutionPeriodUsec) { - if (buttonlatch[0]) --buttonlatch[0]; - if (buttonlatch[1]) --buttonlatch[1]; - if (buttonlatch[2]) --buttonlatch[2]; + for (UINT i=0; i<3; i++) + { + if (buttonlatch[i]) + { + buttonlatch[i] -= nExecutionPeriodUsec; + if (buttonlatch[i] < 0) + buttonlatch[i] = 0; + } + } } //=========================================================================== diff --git a/source/Joystick.h b/source/Joystick.h index 32cfeb72..9889c2c9 100644 --- a/source/Joystick.h +++ b/source/Joystick.h @@ -15,7 +15,7 @@ void JoyReset(); void JoySetButton(eBUTTON,eBUTTONSTATE); BOOL JoySetEmulationType(HWND,DWORD,int, const bool bMousecardActive); void JoySetPosition(int,int,int,int); -void JoyUpdatePosition(); +void JoyUpdateButtonLatch(const UINT nExecutionPeriodUsec); BOOL JoyUsingMouse(); BOOL JoyUsingKeyboard(); BOOL JoyUsingKeyboardCursors(); diff --git a/source/Speaker.cpp b/source/Speaker.cpp index 288c9c60..3608ecd6 100644 --- a/source/Speaker.cpp +++ b/source/Speaker.cpp @@ -479,7 +479,9 @@ BYTE __stdcall SpkrToggle (WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft) if (lastcyclenum) { toggles++; - DWORD delta = cyclenum-lastcyclenum; + //DWORD delta = cyclenum-lastcyclenum; // [TC: 14/09/2014] Looks broken, since 'cyclenum' is cycles executed in previous call to CpuExecute() + CpuCalcCycles(nCyclesLeft); + DWORD delta = (DWORD)g_nCumulativeCycles - lastcyclenum; // DETERMINE WHETHER WE ARE PLAYING A SOUND EFFECT if (directio && @@ -493,7 +495,8 @@ BYTE __stdcall SpkrToggle (WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft) lastdelta[0] = delta; totaldelta += delta; } - lastcyclenum = cyclenum; + //lastcyclenum = cyclenum; + lastcyclenum = (DWORD)g_nCumulativeCycles; } @@ -610,7 +613,7 @@ void SpkrUpdate_Timer() nSamplesUsed = Spkr_SubmitWaveBuffer_FullSpeed(g_pSpeakerBuffer, g_nBufferIdx); _ASSERT(nSamplesUsed <= g_nBufferIdx); - memmove(g_pSpeakerBuffer, &g_pSpeakerBuffer[nSamplesUsed], g_nBufferIdx-nSamplesUsed); // FIXME-TC: _Size * 2 + memmove(g_pSpeakerBuffer, &g_pSpeakerBuffer[nSamplesUsed], g_nBufferIdx-nSamplesUsed); // FIXME-TC: _Size * 2 (GH#213?) g_nBufferIdx -= nSamplesUsed; } } diff --git a/source/Video.cpp b/source/Video.cpp index 0bb423fc..c983ee0a 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -2106,7 +2106,7 @@ void VideoBenchmark () { DWORD executedcycles = CpuExecute(103); cycles -= executedcycles; DiskUpdatePosition(executedcycles); - JoyUpdatePosition(); + JoyUpdateButtonLatch(executedcycles); } } if (cycle & 1) From efd2e4405a9af3998ab4d59934b061f575b1f102 Mon Sep 17 00:00:00 2001 From: tomcw Date: Mon, 15 Sep 2014 22:47:50 +0100 Subject: [PATCH 5/5] Fix: 80-column video mode wasn't being detected as needing an update, when FLASH chars only existed in AUX text pages. --- source/Video.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/source/Video.cpp b/source/Video.cpp index c983ee0a..404d0d94 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -1940,12 +1940,12 @@ BOOL VideoApparentlyDirty () // - bool bCharFlashing = false; - // Scan visible text page for any flashing chars if((SW_TEXT || SW_MIXED) && (g_nAltCharSetOffset == 0)) { - BYTE* pnMemText = MemGetMainPtr(0x400 << (SW_PAGE2 ? 1 : 0)); + BYTE* pTextBank0 = MemGetMainPtr(0x400 << (SW_PAGE2 ? 1 : 0)); + BYTE* pTextBank1 = MemGetAuxPtr (0x400 << (SW_PAGE2 ? 1 : 0)); + const bool b80Col = SW_80COL; // Scan 8 long-lines of 120 chars (at 128 char offsets): // . Skip 8-char holes in TEXT @@ -1953,19 +1953,20 @@ BOOL VideoApparentlyDirty () { for(UINT x=0; x<40*3; x++) { - BYTE ch = pnMemText[y*128+x]; + BYTE ch = pTextBank0[y*128+x]; if((ch >= 0x40) && (ch <= 0x7F)) + return 1; + + if (b80Col) { - bCharFlashing = true; - break; + ch = pTextBank1[y*128+x]; + if((ch >= 0x40) && (ch <= 0x7F)) + return 1; } } } } - if(bCharFlashing) - return 1; - return 0; }