From 297cea7d2aec892b13522f74e271c6a965409e96 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 21 Oct 2017 18:47:22 +0100 Subject: [PATCH 1/9] Support polling of Mockingboard's & Phasor's 6522 IFR.Timer1 (#496) . Extended save-state (Mockingboard & Phasor: version 2) to support 6522 timer being active --- source/AY8910.cpp | 1 - source/CPU.cpp | 1 + source/Mockingboard.cpp | 130 ++++++++++++++++++++++++++-------------- source/Mockingboard.h | 5 -- 4 files changed, 85 insertions(+), 52 deletions(-) diff --git a/source/AY8910.cpp b/source/AY8910.cpp index e7f21f7d..701a958a 100644 --- a/source/AY8910.cpp +++ b/source/AY8910.cpp @@ -32,7 +32,6 @@ #include "AY8910.h" #include "Applewin.h" // For g_fh -#include "Mockingboard.h" // For g_uTimer1IrqCount #include "YamlHelper.h" /* The AY white noise RNG algorithm is based on info from MAME's ay8910.c - diff --git a/source/CPU.cpp b/source/CPU.cpp index 402ca743..f6bdc0fd 100644 --- a/source/CPU.cpp +++ b/source/CPU.cpp @@ -539,6 +539,7 @@ DWORD CpuExecute(const DWORD uCycles, const bool bVideoUpdate) const DWORD uExecutedCycles = InternalCpuExecute(uCycles, bVideoUpdate); MB_UpdateCycles(uExecutedCycles); // Update 6522s (NB. Do this before updating g_nCumulativeCycles below) + // NB. Ensures that 6522 regs are up-to-date for any potential save-state UpdateEmulationTime(uExecutedCycles); // diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index 4571f6cf..928b593d 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -122,7 +122,8 @@ struct SY6522_AY8910 SY6522 sy6522; BYTE nAY8910Number; BYTE nAYCurrentRegister; - BYTE nTimerStatus; + bool bTimer1Active; + bool bTimer2Active; SSI263A SpeechChip; }; @@ -203,13 +204,7 @@ static DWORD g_dwMaxPhonemeLen = 0; // When 6522 IRQ is *not* active use 60Hz update freq for MB voices static const double g_f6522TimerPeriod_NoIRQ = CLK_6502 / 60.0; // Constant whatever the CLK is set to -//--------------------------------------------------------------------------- - -// External global vars: -bool g_bMBTimerIrqActive = false; -#ifdef _DEBUG -UINT32 g_uTimer1IrqCount = 0; // DEBUG -#endif +static bool g_bMBTimerIrqActive = false; //--------------------------------------------------------------------------- @@ -219,33 +214,41 @@ static void Votrax_Write(BYTE nDevice, BYTE nValue); //--------------------------------------------------------------------------- -static void StartTimer(SY6522_AY8910* pMB) +static void StartTimer1(SY6522_AY8910* pMB) { -// if((pMB->nAY8910Number & 1) != SY6522_DEVICE_A) -// return; - - if((pMB->sy6522.IER & IxR_TIMER1) == 0x00) - return; - - USHORT nPeriod = pMB->sy6522.TIMER1_LATCH.w; - -// if(nPeriod <= 0xff) // Timer1L value has been written (but TIMER1H hasn't) -// return; - - pMB->nTimerStatus = 1; + pMB->bTimer1Active = true; // 6522 CLK runs at same speed as 6502 CLK - g_n6522TimerPeriod = nPeriod; + g_n6522TimerPeriod = pMB->sy6522.TIMER1_LATCH.w; + + if (pMB->sy6522.IER & IxR_TIMER1) + g_bMBTimerIrqActive = true; + + g_nMBTimerDevice = pMB->nAY8910Number; +} + +// The assumption was that timer1 was only active if IER.TIMER1=1 +// . Not true, since IFR can be polled (with IER.TIMER1=0) +static void StartTimer1_LoadStateV1(SY6522_AY8910* pMB) +{ + if ((pMB->sy6522.IER & IxR_TIMER1) == 0x00) + return; + + pMB->bTimer1Active = true; + + // 6522 CLK runs at same speed as 6502 CLK + g_n6522TimerPeriod = pMB->sy6522.TIMER1_LATCH.w; g_bMBTimerIrqActive = true; + g_nMBTimerDevice = pMB->nAY8910Number; } //----------------------------------------------------------------------------- -static void StopTimer(SY6522_AY8910* pMB) +static void StopTimer1(SY6522_AY8910* pMB) { - pMB->nTimerStatus = 0; + pMB->bTimer1Active = false; g_bMBTimerIrqActive = false; g_nMBTimerDevice = TIMERDEVICE_INVALID; } @@ -256,8 +259,8 @@ static void ResetSY6522(SY6522_AY8910* pMB) { memset(&pMB->sy6522,0,sizeof(SY6522)); - if(pMB->nTimerStatus) - StopTimer(pMB); + if (pMB->bTimer1Active) + StopTimer1(pMB); pMB->nAYCurrentRegister = 0; } @@ -398,7 +401,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) pMB->sy6522.TIMER1_LATCH.h = nValue; pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w; - StartTimer(pMB); + StartTimer1(pMB); break; case 0x07: // TIMER1H_LATCH // Clear Timer1 Interrupt Flag. @@ -445,11 +448,11 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) if(pMB->sy6522.IER & IxR_TIMER1) break; - if(pMB->nTimerStatus == 0) + if (pMB->bTimer1Active == false) break; // Stop timer - StopTimer(pMB); + StopTimer1(pMB); } else { @@ -457,7 +460,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) nValue &= 0x7F; pMB->sy6522.IER |= nValue; UpdateIFR(pMB); - StartTimer(pMB); + StartTimer1(pMB); } break; case 0x0f: // ORA_NO_HS @@ -1656,7 +1659,10 @@ void MB_EndOfVideoFrame() //----------------------------------------------------------------------------- -// Called by CpuExecute() after every N opcodes (N = ~1000 @ 1MHz) +// Called by: +// . CpuExecute() every ~1000 @ 1MHz +// . CheckInterruptSources() every 128 cycles +// . MB_Read() / MB_Write() void MB_UpdateCycles(ULONG uExecutedCycles) { if(g_SoundcardType == CT_Empty) @@ -1682,12 +1688,8 @@ void MB_UpdateCycles(ULONG uExecutedCycles) bool bTimer1Underflow = (!(OldTimer1 & 0x8000) && (pMB->sy6522.TIMER1_COUNTER.w & 0x8000)); bool bTimer2Underflow = (!(OldTimer2 & 0x8000) && (pMB->sy6522.TIMER2_COUNTER.w & 0x8000)); - if( bTimer1Underflow && (g_nMBTimerDevice == i) && g_bMBTimerIrqActive ) + if ( bTimer1Underflow && (g_nMBTimerDevice == i) ) { -#ifdef _DEBUG - g_uTimer1IrqCount++; // DEBUG -#endif - pMB->sy6522.IFR |= IxR_TIMER1; UpdateIFR(pMB); @@ -1696,20 +1698,20 @@ void MB_UpdateCycles(ULONG uExecutedCycles) // One-shot mode // - Phasor's playback code uses one-shot mode // - Willy Byte sets to one-shot to stop the timer IRQ - StopTimer(pMB); + StopTimer1(pMB); } else { // Free-running mode // - Ultima4/5 change ACCESS_TIMER1 after a couple of IRQs into tune pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w; - StartTimer(pMB); + StartTimer1(pMB); } MB_Update(); } else if ( bTimer1Underflow - && !g_bMBTimerIrqActive // StopTimer() has been called + && !g_bMBTimerIrqActive // StopTimer1() has been called && (pMB->sy6522.IFR & IxR_TIMER1) // IRQ && ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) ) // One-shot mode { @@ -1826,7 +1828,7 @@ int MB_SetSnapshot_v1(const SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD /*dw memcpy(&pMB->SpeechChip, &pSS->Unit[i].RegsSSI263, sizeof(SSI263A)); pMB->nAYCurrentRegister = pSS->Unit[i].nAYCurrentRegister; - StartTimer(pMB); // Attempt to start timer + StartTimer1_LoadStateV1(pMB); // Attempt to start timer // @@ -1919,6 +1921,8 @@ const UINT NUM_PHASOR_UNITS = 2; #define SS_YAML_KEY_TIMER1_IRQ "Timer1 IRQ Pending" #define SS_YAML_KEY_TIMER2_IRQ "Timer2 IRQ Pending" #define SS_YAML_KEY_SPEECH_IRQ "Speech IRQ Pending" +#define SS_YAML_KEY_TIMER1_ACTIVE "Timer1 Active" +#define SS_YAML_KEY_TIMER2_ACTIVE "Timer2 Active" #define SS_YAML_KEY_PHASOR_UNIT "Unit" #define SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR "Clock Scale Factor" @@ -1974,7 +1978,8 @@ void MB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot) UINT nDeviceNum = nMbCardNum*2; SY6522_AY8910* pMB = &g_MB[nDeviceNum]; - YamlSaveHelper::Slot slot(yamlSaveHelper, MB_GetSnapshotCardName(), uSlot, 1); // fixme: object should be just 1 Mockingboard card & it will know its slot + const UINT version = 2; + YamlSaveHelper::Slot slot(yamlSaveHelper, MB_GetSnapshotCardName(), uSlot, version); // fixme: object should be just 1 Mockingboard card & it will know its slot YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); @@ -1990,6 +1995,8 @@ void MB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot) yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER1_IRQ, "false"); yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER2_IRQ, "false"); yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_SPEECH_IRQ, "false"); + yamlSaveHelper.SaveBool(SS_YAML_KEY_TIMER1_ACTIVE, pMB->bTimer1Active); + yamlSaveHelper.SaveBool(SS_YAML_KEY_TIMER2_ACTIVE, pMB->bTimer2Active); nDeviceNum++; pMB++; @@ -2039,7 +2046,7 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version) if (slot != 4 && slot != 5) // fixme throw std::string("Card: wrong slot"); - if (version != 1) + if (version < 1 || version > 2) throw std::string("Card: wrong version"); AY8910UpdateSetCycles(); @@ -2067,11 +2074,25 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version) yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER2_IRQ); // Consume yamlLoadHelper.LoadBool(SS_YAML_KEY_SPEECH_IRQ); // Consume + if (version >= 2) + { + pMB->bTimer1Active = yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER1_ACTIVE); + pMB->bTimer2Active = yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER2_ACTIVE); + } + yamlLoadHelper.PopMap(); // - StartTimer(pMB); // Attempt to start timer + if (version == 1) + { + StartTimer1_LoadStateV1(pMB); // Attempt to start timer + } + else // version >= 2 + { + if (pMB->bTimer1Active) + StartTimer1(pMB); // Attempt to start timer + } // Crude - currently only support a single speech chip // FIX THIS: @@ -2110,7 +2131,8 @@ void Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot) UINT nDeviceNum = 0; SY6522_AY8910* pMB = &g_MB[0]; // fixme: Phasor uses MB's slot4(2x6522), slot4(2xSSI263), but slot4+5(4xAY8910) - YamlSaveHelper::Slot slot(yamlSaveHelper, Phasor_GetSnapshotCardName(), uSlot, 1); // fixme: object should be just 1 Mockingboard card & it will know its slot + const UINT version = 2; + YamlSaveHelper::Slot slot(yamlSaveHelper, Phasor_GetSnapshotCardName(), uSlot, version); // fixme: object should be just 1 Mockingboard card & it will know its slot YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); @@ -2130,6 +2152,8 @@ void Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot) yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER1_IRQ, "false"); yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER2_IRQ, "false"); yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_SPEECH_IRQ, "false"); + yamlSaveHelper.SaveBool(SS_YAML_KEY_TIMER1_ACTIVE, pMB->bTimer1Active); + yamlSaveHelper.SaveBool(SS_YAML_KEY_TIMER2_ACTIVE, pMB->bTimer2Active); nDeviceNum += 2; pMB++; @@ -2141,7 +2165,7 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version if (slot != 4) // fixme throw std::string("Card: wrong slot"); - if (version != 1) + if (version < 1 || version > 2) throw std::string("Card: wrong version"); g_PhasorClockScaleFactor = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR); @@ -2172,11 +2196,25 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER2_IRQ); // Consume yamlLoadHelper.LoadBool(SS_YAML_KEY_SPEECH_IRQ); // Consume + if (version >= 2) + { + pMB->bTimer1Active = yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER1_ACTIVE); + pMB->bTimer2Active = yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER2_ACTIVE); + } + yamlLoadHelper.PopMap(); // - StartTimer(pMB); // Attempt to start timer + if (version == 1) + { + StartTimer1_LoadStateV1(pMB); // Attempt to start timer + } + else // version >= 2 + { + if (pMB->bTimer1Active) + StartTimer1(pMB); // Attempt to start timer + } // Crude - currently only support a single speech chip // FIX THIS: diff --git a/source/Mockingboard.h b/source/Mockingboard.h index 901a9e41..0c33bc8b 100644 --- a/source/Mockingboard.h +++ b/source/Mockingboard.h @@ -1,10 +1,5 @@ #pragma once -extern bool g_bMBTimerIrqActive; -#ifdef _DEBUG -extern UINT32 g_uTimer1IrqCount; // DEBUG -#endif - void MB_Initialize(); void MB_Reinitialize(); void MB_Destroy(); From 86f56a9a49d72587ade14eec5d44e4c5f4440333 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 21 Oct 2017 21:02:38 +0100 Subject: [PATCH 2/9] Bump to 1.26.3.2 and update History.txt --- bin/History.txt | 8 ++++++-- resource/Applewin.rc | 8 ++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/bin/History.txt b/bin/History.txt index ce0af9c5..6d6a53d9 100644 --- a/bin/History.txt +++ b/bin/History.txt @@ -9,8 +9,8 @@ https://github.com/AppleWin/AppleWin/issues/new Tom Charlesworth -1.26.3.1 (Experimental) - 29 Sep 2017 ------------------------------------- +1.26.3.2 (Experimental) - 21 Oct 2017 +------------------------------------- Changes: . [Bug #469] New -no-printscreen-key switch to prevent the PrintScreen key from being registered. . [Bug #488] New -fs-height= switch. @@ -24,7 +24,11 @@ Changes: . [PR #441] Update zlib to latest version 1.2.11 Fixes: +. [Bug #499] Flush current track (if dirty) before 'Send to CiderPress' +. [Bug #496] Support polling of Mockingboard's & Phasor's 6522 IFR.Timer1 +. [Bug #492] UI fixes for full-screen & 2x windowed-mode . [Bug #486] Peripheral card's expansion ROM ($C800-CFFF, eg. SSC) wasn't being correctly restored from a save-state +. [Bug #464] Fix for full-screen: bottom line missing when vertical resolution is 768 . [Bug #460] Debugger: F2 whilst debugger active will immediately stop the drive spinning (allowing disk swap) . [Bug #456] Fix strange speaker clicks when changing configuration - DirectSound wasn't being uninitialised on a restart . [Bug #452] Fix for unmounted HD now gives "NO DEVICE CONNECTED" (before gave "I/O ERROR") diff --git a/resource/Applewin.rc b/resource/Applewin.rc index a06bb3a0..721e4b94 100644 --- a/resource/Applewin.rc +++ b/resource/Applewin.rc @@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,26,3,1 - PRODUCTVERSION 1,26,3,1 + FILEVERSION 1,26,3,2 + PRODUCTVERSION 1,26,3,2 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -271,12 +271,12 @@ BEGIN VALUE "Comments", "https://github.com/AppleWin" VALUE "CompanyName", "AppleWin" VALUE "FileDescription", "Apple //e Emulator for Windows" - VALUE "FileVersion", "1, 26, 3, 1" + VALUE "FileVersion", "1, 26, 3, 2" VALUE "InternalName", "APPLEWIN" VALUE "LegalCopyright", " 1994-2017 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis" VALUE "OriginalFilename", "APPLEWIN.EXE" VALUE "ProductName", "Apple //e Emulator" - VALUE "ProductVersion", "1, 26, 3, 1" + VALUE "ProductVersion", "1, 26, 3, 2" END END BLOCK "VarFileInfo" From 49465d018228406aff51c6c04f1dd86f3e3ae562 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 21 Oct 2017 21:59:21 +0100 Subject: [PATCH 3/9] Fix position of disk status in 2x Windowed-mode --- source/Frame.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/Frame.cpp b/source/Frame.cpp index 74e60576..b41bcebc 100644 --- a/source/Frame.cpp +++ b/source/Frame.cpp @@ -795,7 +795,7 @@ void FrameDrawDiskStatus( HDC passdc ) HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow)); int x = buttonx; - int y = buttony+BUTTONS*BUTTONCY+1; + int y = buttony+BUTTONS*BUTTONCY+4; SelectObject(dc,smallfont); SetBkMode(dc,OPAQUE); @@ -841,12 +841,12 @@ void FrameDrawDiskStatus( HDC passdc ) SetBkMode(dc,TRANSPARENT); sprintf( text, "T%s", g_sTrackDrive1 ); - TextOut(dc,x+6 ,y+32,text, strlen(text) ); + TextOut(dc,x+6, y+32, text, strlen(text) ); sprintf( text, "S%s", g_sSectorDrive1 ); - TextOut(dc,x+ 6,y+42, text, strlen(text) ); + TextOut(dc,x+6, y+42, text, strlen(text) ); sprintf( text, "T%s", g_sTrackDrive2 ); - TextOut(dc,x+26,y+32,text, strlen(text) ); + TextOut(dc,x+26,y+32, text, strlen(text) ); sprintf( text, "S%s", g_sSectorDrive2 ); TextOut(dc,x+26,y+42, text, strlen(text) ); } From 66321febbaea46625defb974fd2aa3689484bde6 Mon Sep 17 00:00:00 2001 From: TomCh Date: Tue, 24 Oct 2017 22:28:22 +0100 Subject: [PATCH 4/9] Support Mockingboard/Phasor when polling IFR.Timer1 (#496) * Support precise AY8910 sound-buffer filling when polling 6522 IFR.Timer1 (ACR=Free Running mode) - same as if using 6522 IER.Timer1 interrupt * Support 6522's Timer2 and some code refactoring * Bump version: 1.26.3.4 --- resource/Applewin.rc | 8 +-- source/Mockingboard.cpp | 150 +++++++++++++++++++++++++++------------- source/Mockingboard.h | 1 - 3 files changed, 106 insertions(+), 53 deletions(-) diff --git a/resource/Applewin.rc b/resource/Applewin.rc index 721e4b94..bb9da64c 100644 --- a/resource/Applewin.rc +++ b/resource/Applewin.rc @@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,26,3,2 - PRODUCTVERSION 1,26,3,2 + FILEVERSION 1,26,3,4 + PRODUCTVERSION 1,26,3,4 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -271,12 +271,12 @@ BEGIN VALUE "Comments", "https://github.com/AppleWin" VALUE "CompanyName", "AppleWin" VALUE "FileDescription", "Apple //e Emulator for Windows" - VALUE "FileVersion", "1, 26, 3, 2" + VALUE "FileVersion", "1, 26, 3, 4" VALUE "InternalName", "APPLEWIN" VALUE "LegalCopyright", " 1994-2017 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis" VALUE "OriginalFilename", "APPLEWIN.EXE" VALUE "ProductName", "Apple //e Emulator" - VALUE "ProductVersion", "1, 26, 3, 2" + VALUE "ProductVersion", "1, 26, 3, 4" END END BLOCK "VarFileInfo" diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index 928b593d..92fd4502 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -153,8 +153,8 @@ static SY6522_AY8910 g_MB[NUM_AY8910]; // Timer vars static ULONG g_n6522TimerPeriod = 0; -static const UINT TIMERDEVICE_INVALID = -1; -static UINT g_nMBTimerDevice = TIMERDEVICE_INVALID; // SY6522 device# which is generating timer IRQ +static const UINT kTIMERDEVICE_INVALID = -1; +static UINT g_nMBTimerDevice = kTIMERDEVICE_INVALID; // SY6522 device# which is generating timer IRQ static UINT64 g_uLastCumulativeCycles = 0; // SSI263 vars: @@ -204,13 +204,12 @@ static DWORD g_dwMaxPhonemeLen = 0; // When 6522 IRQ is *not* active use 60Hz update freq for MB voices static const double g_f6522TimerPeriod_NoIRQ = CLK_6502 / 60.0; // Constant whatever the CLK is set to -static bool g_bMBTimerIrqActive = false; - //--------------------------------------------------------------------------- // Forward refs: static DWORD WINAPI SSI263Thread(LPVOID); static void Votrax_Write(BYTE nDevice, BYTE nValue); +static double MB_GetFramePeriod(void); //--------------------------------------------------------------------------- @@ -221,10 +220,10 @@ static void StartTimer1(SY6522_AY8910* pMB) // 6522 CLK runs at same speed as 6502 CLK g_n6522TimerPeriod = pMB->sy6522.TIMER1_LATCH.w; - if (pMB->sy6522.IER & IxR_TIMER1) - g_bMBTimerIrqActive = true; - - g_nMBTimerDevice = pMB->nAY8910Number; + if (pMB->sy6522.IER & IxR_TIMER1) // Using 6522 interrupt + g_nMBTimerDevice = pMB->nAY8910Number; + else if (pMB->sy6522.ACR & RM_FREERUNNING) // Polling 6522 IFR + g_nMBTimerDevice = pMB->nAY8910Number; } // The assumption was that timer1 was only active if IER.TIMER1=1 @@ -239,18 +238,28 @@ static void StartTimer1_LoadStateV1(SY6522_AY8910* pMB) // 6522 CLK runs at same speed as 6502 CLK g_n6522TimerPeriod = pMB->sy6522.TIMER1_LATCH.w; - g_bMBTimerIrqActive = true; - g_nMBTimerDevice = pMB->nAY8910Number; } -//----------------------------------------------------------------------------- - static void StopTimer1(SY6522_AY8910* pMB) { pMB->bTimer1Active = false; - g_bMBTimerIrqActive = false; - g_nMBTimerDevice = TIMERDEVICE_INVALID; + g_nMBTimerDevice = kTIMERDEVICE_INVALID; +} + +//----------------------------------------------------------------------------- + +static void StartTimer2(SY6522_AY8910* pMB) +{ + pMB->bTimer2Active = true; + + // NB. Can't mimic StartTimer1() as that would stomp on global state + // TODO: Switch to per-device state +} + +static void StopTimer2(SY6522_AY8910* pMB) +{ + pMB->bTimer2Active = false; } //----------------------------------------------------------------------------- @@ -259,8 +268,8 @@ static void ResetSY6522(SY6522_AY8910* pMB) { memset(&pMB->sy6522,0,sizeof(SY6522)); - if (pMB->bTimer1Active) - StopTimer1(pMB); + StopTimer1(pMB); + StopTimer2(pMB); pMB->nAYCurrentRegister = 0; } @@ -272,7 +281,7 @@ static void AY8910_Write(BYTE nDevice, BYTE nReg, BYTE nValue, BYTE nAYDevice) g_bMB_RegAccessedFlag = true; SY6522_AY8910* pMB = &g_MB[nDevice]; - if((nValue & 4) == 0) + if ((nValue & 4) == 0) { // RESET: Reset AY8910 only AY8910_reset(nDevice+2*nAYDevice); @@ -287,7 +296,7 @@ static void AY8910_Write(BYTE nDevice, BYTE nReg, BYTE nValue, BYTE nAYDevice) int nAYFunc = (nBDIR<<2) | (nBC2<<1) | nBC1; enum {AY_NOP0, AY_NOP1, AY_INACTIVE, AY_READ, AY_NOP4, AY_NOP5, AY_WRITE, AY_LATCH}; - switch(nAYFunc) + switch (nAYFunc) { case AY_INACTIVE: // 4: INACTIVE break; @@ -312,17 +321,20 @@ static void AY8910_Write(BYTE nDevice, BYTE nReg, BYTE nValue, BYTE nAYDevice) } } +// TODO: Fix data-race: main thread & SSI263Thread accessing IFR +// . extend this func to take an or_mask & and_mask +// . then do the mods inside a critical section static void UpdateIFR(SY6522_AY8910* pMB) { pMB->sy6522.IFR &= 0x7F; - if(pMB->sy6522.IFR & pMB->sy6522.IER & 0x7F) + if (pMB->sy6522.IFR & pMB->sy6522.IER & 0x7F) pMB->sy6522.IFR |= 0x80; // Now update the IRQ signal from all 6522s // . OR-sum of all active TIMER1, TIMER2 & SPEECH sources (from all 6522s) UINT bIRQ = 0; - for(UINT i=0; isy6522.TIMER2_LATCH.h = nValue; pMB->sy6522.TIMER2_COUNTER.w = pMB->sy6522.TIMER2_LATCH.w; + + StartTimer2(pMB); break; case 0x0a: // SERIAL_SHIFT break; @@ -444,15 +458,12 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) pMB->sy6522.IER &= nValue; UpdateIFR(pMB); - // Check if timer has been disabled. - if(pMB->sy6522.IER & IxR_TIMER1) - break; + // Check if active timer has been disabled: + if (((pMB->sy6522.IER & IxR_TIMER1) == 0) && pMB->bTimer1Active) + StopTimer1(pMB); - if (pMB->bTimer1Active == false) - break; - - // Stop timer - StopTimer1(pMB); + if (((pMB->sy6522.IER & IxR_TIMER2) == 0) && pMB->bTimer2Active) + StopTimer2(pMB); } else { @@ -460,7 +471,13 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) nValue &= 0x7F; pMB->sy6522.IER |= nValue; UpdateIFR(pMB); - StartTimer1(pMB); + + // Check if active timer changed from non-interrupt (polling IFR) to interrupt: + if ((pMB->sy6522.IER & IxR_TIMER1) && pMB->bTimer1Active) + StartTimer1(pMB); + + if ((pMB->sy6522.IER & IxR_TIMER2) && pMB->bTimer2Active) + StartTimer2(pMB); } break; case 0x0f: // ORA_NO_HS @@ -742,6 +759,9 @@ static void Votrax_Write(BYTE nDevice, BYTE nValue) //=========================================================================== +// Called by: +// . MB_UpdateCycles() - when g_nMBTimerDevice == {0,1,2,3} +// . MB_EndOfVideoFrame() - when g_nMBTimerDevice == kTIMERDEVICE_INVALID static void MB_Update() { //char szDbg[200]; @@ -1408,7 +1428,7 @@ void MB_Destroy() static void ResetState() { g_n6522TimerPeriod = 0; - g_nMBTimerDevice = TIMERDEVICE_INVALID; + g_nMBTimerDevice = kTIMERDEVICE_INVALID; g_uLastCumulativeCycles = 0; g_nSSI263Device = 0; @@ -1650,10 +1670,10 @@ void MB_StartOfCpuExecute() // Called by ContinueExecution() at the end of every video frame void MB_EndOfVideoFrame() { - if(g_SoundcardType == CT_Empty) + if (g_SoundcardType == CT_Empty) return; - if(!g_bMBTimerIrqActive) + if (g_nMBTimerDevice == kTIMERDEVICE_INVALID) MB_Update(); } @@ -1688,11 +1708,28 @@ void MB_UpdateCycles(ULONG uExecutedCycles) bool bTimer1Underflow = (!(OldTimer1 & 0x8000) && (pMB->sy6522.TIMER1_COUNTER.w & 0x8000)); bool bTimer2Underflow = (!(OldTimer2 & 0x8000) && (pMB->sy6522.TIMER2_COUNTER.w & 0x8000)); - if ( bTimer1Underflow && (g_nMBTimerDevice == i) ) + if (!pMB->bTimer1Active && bTimer1Underflow) + { + if ( (g_nMBTimerDevice == kTIMERDEVICE_INVALID) // StopTimer1() has been called + && (pMB->sy6522.IFR & IxR_TIMER1) // Counter underflowed + && ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) ) // One-shot mode + { + // Fix for Willy Byte - need to confirm that 6522 really does this! + // . It never accesses IER/IFR/TIMER1 regs to clear IRQ + pMB->sy6522.IFR &= ~IxR_TIMER1; // Deassert the TIMER IRQ + UpdateIFR(pMB); + } + } + + if (pMB->bTimer1Active && bTimer1Underflow) { pMB->sy6522.IFR |= IxR_TIMER1; UpdateIFR(pMB); + // Do MB_Update() before StopTimer1() + if (g_nMBTimerDevice == i) + MB_Update(); + if((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) { // One-shot mode @@ -1707,18 +1744,21 @@ void MB_UpdateCycles(ULONG uExecutedCycles) pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w; StartTimer1(pMB); } - - MB_Update(); } - else if ( bTimer1Underflow - && !g_bMBTimerIrqActive // StopTimer1() has been called - && (pMB->sy6522.IFR & IxR_TIMER1) // IRQ - && ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) ) // One-shot mode + else if (pMB->bTimer2Active && bTimer2Underflow) { - // Fix for Willy Byte - need to confirm that 6522 really does this! - // . It never accesses IER/IFR/TIMER1 regs to clear IRQ - pMB->sy6522.IFR &= ~IxR_TIMER1; // Deassert the TIMER IRQ + pMB->sy6522.IFR |= IxR_TIMER2; UpdateIFR(pMB); + + if((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) + { + StopTimer2(pMB); + } + else + { + pMB->sy6522.TIMER2_COUNTER.w = pMB->sy6522.TIMER2_LATCH.w; + StartTimer2(pMB); + } } } } @@ -1732,7 +1772,6 @@ SS_CARDTYPE MB_GetSoundcardType() void MB_SetSoundcardType(SS_CARDTYPE NewSoundcardType) { -// if ((NewSoundcardType == SC_UNINIT) || (g_SoundcardType == NewSoundcardType)) if (g_SoundcardType == NewSoundcardType) return; @@ -1746,18 +1785,33 @@ void MB_SetSoundcardType(SS_CARDTYPE NewSoundcardType) //----------------------------------------------------------------------------- -double MB_GetFramePeriod() +static double MB_GetFramePeriod(void) { - return (g_bMBTimerIrqActive||(g_MB[0].sy6522.IFR & IxR_TIMER1)) ? (double)g_n6522TimerPeriod : g_f6522TimerPeriod_NoIRQ; + // TODO: Ideally remove this (slot-4) Phasor-IFR check: [*1] + // . It's for Phasor music player, which runs in one-shot mode: + // . MB_UpdateCycles() + // -> Timer1 underflows & StopTimer1() is called, which sets g_nMBTimerDevice == kTIMERDEVICE_INVALID + // . MB_EndOfVideoFrame(), and g_nMBTimerDevice == kTIMERDEVICE_INVALID + // -> MB_Update() + // -> MB_GetFramePeriod() + // NB. Removing this Phasor-IFR check means the occasional 'g_f6522TimerPeriod_NoIRQ' gets returned. + + if ((g_nMBTimerDevice != kTIMERDEVICE_INVALID) || + (g_bPhasorEnable && (g_MB[0].sy6522.IFR & IxR_TIMER1))) // [*1] + { + return (double)g_n6522TimerPeriod; + } + else + { + return g_f6522TimerPeriod_NoIRQ; + } } bool MB_IsActive() { - if(!MockingboardVoice.bActive) + if (!MockingboardVoice.bActive) return false; - // Ignore /g_bMBTimerIrqActive/ as timer's irq handler will access 6522 regs affecting /g_bMB_Active/ - return g_bMB_Active; } diff --git a/source/Mockingboard.h b/source/Mockingboard.h index 0c33bc8b..96e1bcf5 100644 --- a/source/Mockingboard.h +++ b/source/Mockingboard.h @@ -13,7 +13,6 @@ void MB_CheckIRQ(); void MB_UpdateCycles(ULONG uExecutedCycles); SS_CARDTYPE MB_GetSoundcardType(); void MB_SetSoundcardType(SS_CARDTYPE NewSoundcardType); -double MB_GetFramePeriod(); bool MB_IsActive(); DWORD MB_GetVolume(); void MB_SetVolume(DWORD dwVolume, DWORD dwVolumeMax); From 74ac2a4f2265e4d75f5a7abd5d6139c87448bd08 Mon Sep 17 00:00:00 2001 From: tomcw Date: Fri, 27 Oct 2017 11:10:15 +0100 Subject: [PATCH 5/9] Mockingboard/Phasor unit functions only work from an inactive state (#320) - Extended save-state (MB/Phasor v3) to support 'Unit state' --- source/Mockingboard.cpp | 73 +++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index 92fd4502..3db4cfb6 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -117,6 +117,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define Phasor_SY6522A_Offset (1<nAYCurrentRegister = 0; + pMB->state = AY_INACTIVE; } //----------------------------------------------------------------------------- @@ -293,31 +297,35 @@ static void AY8910_Write(BYTE nDevice, BYTE nReg, BYTE nValue, BYTE nAYDevice) const int nBC2 = 1; // Hardwired to +5V int nBC1 = nValue & 1; - int nAYFunc = (nBDIR<<2) | (nBC2<<1) | nBC1; - enum {AY_NOP0, AY_NOP1, AY_INACTIVE, AY_READ, AY_NOP4, AY_NOP5, AY_WRITE, AY_LATCH}; + MockingboardUnitState_e nAYFunc = (MockingboardUnitState_e) ((nBDIR<<2) | (nBC2<<1) | nBC1); - switch (nAYFunc) + if (pMB->state == AY_INACTIVE) // GH#320: functions only work from inactive state { - case AY_INACTIVE: // 4: INACTIVE - break; + switch (nAYFunc) + { + case AY_INACTIVE: // 4: INACTIVE + break; - case AY_READ: // 5: READ FROM PSG (need to set DDRA to input) - break; + case AY_READ: // 5: READ FROM PSG (need to set DDRA to input) + break; - case AY_WRITE: // 6: WRITE TO PSG - _AYWriteReg(nDevice+2*nAYDevice, pMB->nAYCurrentRegister, pMB->sy6522.ORA); - break; + case AY_WRITE: // 6: WRITE TO PSG + _AYWriteReg(nDevice+2*nAYDevice, pMB->nAYCurrentRegister, pMB->sy6522.ORA); + break; - case AY_LATCH: // 7: LATCH ADDRESS - // http://www.worldofspectrum.org/forums/showthread.php?t=23327 - // Selecting an unused register number above 0x0f puts the AY into a state where - // any values written to the data/address bus are ignored, but can be read back - // within a few tens of thousands of cycles before they decay to zero. - if(pMB->sy6522.ORA <= 0x0F) - pMB->nAYCurrentRegister = pMB->sy6522.ORA & 0x0F; - // else Pro-Mockingboard (clone from HK) - break; + case AY_LATCH: // 7: LATCH ADDRESS + // http://www.worldofspectrum.org/forums/showthread.php?t=23327 + // Selecting an unused register number above 0x0f puts the AY into a state where + // any values written to the data/address bus are ignored, but can be read back + // within a few tens of thousands of cycles before they decay to zero. + if(pMB->sy6522.ORA <= 0x0F) + pMB->nAYCurrentRegister = pMB->sy6522.ORA & 0x0F; + // else Pro-Mockingboard (clone from HK) + break; + } } + + pMB->state = nAYFunc; } } @@ -1881,6 +1889,7 @@ int MB_SetSnapshot_v1(const SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD /*dw memcpy(AY8910_GetRegsPtr(nDeviceNum), &pSS->Unit[i].RegsAY8910, 16); memcpy(&pMB->SpeechChip, &pSS->Unit[i].RegsSSI263, sizeof(SSI263A)); pMB->nAYCurrentRegister = pSS->Unit[i].nAYCurrentRegister; + pMB->state = AY_INACTIVE; StartTimer1_LoadStateV1(pMB); // Attempt to start timer @@ -1946,6 +1955,11 @@ static UINT DoReadFile(const HANDLE hFile, void* const pData, const UINT Length) //=========================================================================== +// Unit version history: +// 2: Added: Timer1 & Timer2 active +// 3: Added: Unit state +const UINT kUNIT_VERSION = 3; + const UINT NUM_MB_UNITS = 2; const UINT NUM_PHASOR_UNITS = 2; @@ -1972,6 +1986,7 @@ const UINT NUM_PHASOR_UNITS = 2; #define SS_YAML_KEY_SSI263_REG_FILTER_FREQ "Filter Frequency" #define SS_YAML_KEY_SSI263_REG_CURRENT_MODE "Current Mode" #define SS_YAML_KEY_AY_CURR_REG "AY Current Register" +#define SS_YAML_KEY_MB_UNIT_STATE "Unit State" #define SS_YAML_KEY_TIMER1_IRQ "Timer1 IRQ Pending" #define SS_YAML_KEY_TIMER2_IRQ "Timer2 IRQ Pending" #define SS_YAML_KEY_SPEECH_IRQ "Speech IRQ Pending" @@ -2032,8 +2047,7 @@ void MB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot) UINT nDeviceNum = nMbCardNum*2; SY6522_AY8910* pMB = &g_MB[nDeviceNum]; - const UINT version = 2; - YamlSaveHelper::Slot slot(yamlSaveHelper, MB_GetSnapshotCardName(), uSlot, version); // fixme: object should be just 1 Mockingboard card & it will know its slot + YamlSaveHelper::Slot slot(yamlSaveHelper, MB_GetSnapshotCardName(), uSlot, kUNIT_VERSION); // fixme: object should be just 1 Mockingboard card & it will know its slot YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); @@ -2045,6 +2059,7 @@ void MB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot) AY8910_SaveSnapshot(yamlSaveHelper, nDeviceNum, std::string("")); SaveSnapshotSSI263(yamlSaveHelper, pMB->SpeechChip); + yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_MB_UNIT_STATE, pMB->state); yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_AY_CURR_REG, pMB->nAYCurrentRegister); yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER1_IRQ, "false"); yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER2_IRQ, "false"); @@ -2100,7 +2115,7 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version) if (slot != 4 && slot != 5) // fixme throw std::string("Card: wrong slot"); - if (version < 1 || version > 2) + if (version < 1 || version > kUNIT_VERSION) throw std::string("Card: wrong version"); AY8910UpdateSetCycles(); @@ -2134,6 +2149,10 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version) pMB->bTimer2Active = yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER2_ACTIVE); } + pMB->state = AY_INACTIVE; + if (version >= 3) + pMB->state = (MockingboardUnitState_e) (yamlLoadHelper.LoadUint(SS_YAML_KEY_MB_UNIT_STATE) & 7); + yamlLoadHelper.PopMap(); // @@ -2185,8 +2204,7 @@ void Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot) UINT nDeviceNum = 0; SY6522_AY8910* pMB = &g_MB[0]; // fixme: Phasor uses MB's slot4(2x6522), slot4(2xSSI263), but slot4+5(4xAY8910) - const UINT version = 2; - YamlSaveHelper::Slot slot(yamlSaveHelper, Phasor_GetSnapshotCardName(), uSlot, version); // fixme: object should be just 1 Mockingboard card & it will know its slot + YamlSaveHelper::Slot slot(yamlSaveHelper, Phasor_GetSnapshotCardName(), uSlot, kUNIT_VERSION); // fixme: object should be just 1 Mockingboard card & it will know its slot YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); @@ -2202,6 +2220,7 @@ void Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot) AY8910_SaveSnapshot(yamlSaveHelper, nDeviceNum+1, std::string("-B")); SaveSnapshotSSI263(yamlSaveHelper, pMB->SpeechChip); + yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_MB_UNIT_STATE, pMB->state); yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_AY_CURR_REG, pMB->nAYCurrentRegister); yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER1_IRQ, "false"); yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER2_IRQ, "false"); @@ -2219,7 +2238,7 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version if (slot != 4) // fixme throw std::string("Card: wrong slot"); - if (version < 1 || version > 2) + if (version < 1 || version > kUNIT_VERSION) throw std::string("Card: wrong version"); g_PhasorClockScaleFactor = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR); @@ -2256,6 +2275,10 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version pMB->bTimer2Active = yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER2_ACTIVE); } + pMB->state = AY_INACTIVE; + if (version >= 3) + pMB->state = (MockingboardUnitState_e) (yamlLoadHelper.LoadUint(SS_YAML_KEY_MB_UNIT_STATE) & 7); + yamlLoadHelper.PopMap(); // From e2b515de3300683617bc98ee1c1fe99329735854 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 28 Oct 2017 18:39:45 +0100 Subject: [PATCH 6/9] MB/Phasor: Wrap 6522.IFR changes inside a critical section to avoid a potential 2 thread data-race --- source/Mockingboard.cpp | 128 ++++++++++++++-------------------------- 1 file changed, 45 insertions(+), 83 deletions(-) diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index 3db4cfb6..13217884 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -207,6 +207,9 @@ static DWORD g_dwMaxPhonemeLen = 0; // When 6522 IRQ is *not* active use 60Hz update freq for MB voices static const double g_f6522TimerPeriod_NoIRQ = CLK_6502 / 60.0; // Constant whatever the CLK is set to +static bool g_bCritSectionValid = false; // Deleting CritialSection when not valid causes crash on Win98 +static CRITICAL_SECTION g_CriticalSection; // To guard 6522's IFR + //--------------------------------------------------------------------------- // Forward refs: @@ -329,15 +332,22 @@ static void AY8910_Write(BYTE nDevice, BYTE nReg, BYTE nValue, BYTE nAYDevice) } } -// TODO: Fix data-race: main thread & SSI263Thread accessing IFR -// . extend this func to take an or_mask & and_mask -// . then do the mods inside a critical section -static void UpdateIFR(SY6522_AY8910* pMB) +static void UpdateIFR(SY6522_AY8910* pMB, BYTE clr_ifr, BYTE set_ifr=0) { - pMB->sy6522.IFR &= 0x7F; + // Need critical section to avoid data-race: main thread & SSI263Thread can both access IFR + // . NB. Loading a save-state just directly writes into 6522.IFR (which is fine) + _ASSERT(g_bCritSectionValid); + if (g_bCritSectionValid) EnterCriticalSection(&g_CriticalSection); + { + pMB->sy6522.IFR &= ~clr_ifr; + pMB->sy6522.IFR |= set_ifr; - if (pMB->sy6522.IFR & pMB->sy6522.IER & 0x7F) - pMB->sy6522.IFR |= 0x80; + if (pMB->sy6522.IFR & pMB->sy6522.IER & 0x7F) + pMB->sy6522.IFR |= 0x80; + else + pMB->sy6522.IFR &= 0x7F; + } + if (g_bCritSectionValid) LeaveCriticalSection(&g_CriticalSection); // Now update the IRQ signal from all 6522s // . OR-sum of all active TIMER1, TIMER2 & SPEECH sources (from all 6522s) @@ -352,13 +362,9 @@ static void UpdateIFR(SY6522_AY8910* pMB) // . I assume Phasor's 6522s just generate 6502 IRQs (not NMIs) if (bIRQ) - { CpuIrqAssert(IS_6522); - } else - { CpuIrqDeassert(IS_6522); - } } static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) @@ -415,8 +421,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) /* Initiates timer1 & clears time-out of timer1 */ // Clear Timer Interrupt Flag. - pMB->sy6522.IFR &= ~IxR_TIMER1; - UpdateIFR(pMB); + UpdateIFR(pMB, IxR_TIMER1); pMB->sy6522.TIMER1_LATCH.h = nValue; pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w; @@ -425,17 +430,15 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) break; case 0x07: // TIMER1H_LATCH // Clear Timer1 Interrupt Flag. + UpdateIFR(pMB, IxR_TIMER1); pMB->sy6522.TIMER1_LATCH.h = nValue; - pMB->sy6522.IFR &= ~IxR_TIMER1; - UpdateIFR(pMB); break; case 0x08: // TIMER2L pMB->sy6522.TIMER2_LATCH.l = nValue; break; case 0x09: // TIMER2H // Clear Timer2 Interrupt Flag. - pMB->sy6522.IFR &= ~IxR_TIMER2; - UpdateIFR(pMB); + UpdateIFR(pMB, IxR_TIMER2); pMB->sy6522.TIMER2_LATCH.h = nValue; pMB->sy6522.TIMER2_COUNTER.w = pMB->sy6522.TIMER2_LATCH.w; @@ -453,10 +456,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) case 0x0d: // IFR // - Clear those bits which are set in the lower 7 bits. // - Can't clear bit 7 directly. - nValue |= 0x80; // Set high bit - nValue ^= 0x7F; // Make mask - pMB->sy6522.IFR &= nValue; - UpdateIFR(pMB); + UpdateIFR(pMB, nValue); break; case 0x0e: // IER if(!(nValue & 0x80)) @@ -464,7 +464,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) // Clear those bits which are set in the lower 7 bits. nValue ^= 0x7F; pMB->sy6522.IER &= nValue; - UpdateIFR(pMB); + UpdateIFR(pMB, 0); // Check if active timer has been disabled: if (((pMB->sy6522.IER & IxR_TIMER1) == 0) && pMB->bTimer1Active) @@ -478,7 +478,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) // Set those bits which are set in the lower 7 bits. nValue &= 0x7F; pMB->sy6522.IER |= nValue; - UpdateIFR(pMB); + UpdateIFR(pMB, 0); // Check if active timer changed from non-interrupt (polling IFR) to interrupt: if ((pMB->sy6522.IER & IxR_TIMER1) && pMB->bTimer1Active) @@ -519,8 +519,7 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) break; case 0x04: // TIMER1L_COUNTER nValue = pMB->sy6522.TIMER1_COUNTER.l; - pMB->sy6522.IFR &= ~IxR_TIMER1; // Also clears Timer1 Interrupt Flag - UpdateIFR(pMB); + UpdateIFR(pMB, IxR_TIMER1); break; case 0x05: // TIMER1H_COUNTER nValue = pMB->sy6522.TIMER1_COUNTER.h; @@ -533,8 +532,7 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) break; case 0x08: // TIMER2L nValue = pMB->sy6522.TIMER2_COUNTER.l; - pMB->sy6522.IFR &= ~IxR_TIMER2; // Also clears Timer2 Interrupt Flag - UpdateIFR(pMB); + UpdateIFR(pMB, IxR_TIMER2); break; case 0x09: // TIMER2H nValue = pMB->sy6522.TIMER2_COUNTER.h; @@ -627,8 +625,7 @@ static void SSI263_Write(BYTE nDevice, BYTE nReg, BYTE nValue) } else { - pMB->sy6522.IFR &= ~IxR_PERIPHERAL; - UpdateIFR(pMB); + UpdateIFR(pMB, IxR_PERIPHERAL); } pMB->SpeechChip.CurrentMode &= ~1; // Clear SSI263's D7 pin @@ -757,8 +754,7 @@ static void Votrax_Write(BYTE nDevice, BYTE nValue) // !A/R: Acknowledge receipt of phoneme data (signal goes from high to low) SY6522_AY8910* pMB = &g_MB[nDevice]; - pMB->sy6522.IFR &= ~IxR_VOTRAX; - UpdateIFR(pMB); + UpdateIFR(pMB, IxR_VOTRAX); g_nSSI263Device = nDevice; @@ -1008,8 +1004,7 @@ static DWORD WINAPI SSI263Thread(LPVOID lpParameter) { if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C)) { - pMB->sy6522.IFR |= IxR_PERIPHERAL; - UpdateIFR(pMB); + UpdateIFR(pMB, 0, IxR_PERIPHERAL); pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin } } @@ -1020,8 +1015,7 @@ static DWORD WINAPI SSI263Thread(LPVOID lpParameter) { // !A/R: Time-out of old phoneme (signal goes from low to high) - pMB->sy6522.IFR |= IxR_VOTRAX; - UpdateIFR(pMB); + UpdateIFR(pMB, 0, IxR_VOTRAX); g_bVotraxPhoneme = false; } @@ -1410,6 +1404,9 @@ void MB_Initialize() MB_Reset(); LogFileOutput("MB_Initialize: MB_Reset()\n"); } + + InitializeCriticalSection(&g_CriticalSection); + g_bCritSectionValid = true; } //----------------------------------------------------------------------------- @@ -1427,8 +1424,14 @@ void MB_Destroy() { MB_DSUninit(); - for(int i=0; isy6522.IFR &= ~IxR_TIMER1; // Deassert the TIMER IRQ - UpdateIFR(pMB); + UpdateIFR(pMB, IxR_TIMER1); // Deassert the TIMER IRQ } } if (pMB->bTimer1Active && bTimer1Underflow) { - pMB->sy6522.IFR |= IxR_TIMER1; - UpdateIFR(pMB); + UpdateIFR(pMB, 0, IxR_TIMER1); // Do MB_Update() before StopTimer1() if (g_nMBTimerDevice == i) @@ -1755,8 +1756,7 @@ void MB_UpdateCycles(ULONG uExecutedCycles) } else if (pMB->bTimer2Active && bTimer2Underflow) { - pMB->sy6522.IFR |= IxR_TIMER2; - UpdateIFR(pMB); + UpdateIFR(pMB, 0, IxR_TIMER2); if((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) { @@ -1905,8 +1905,7 @@ int MB_SetSnapshot_v1(const SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD /*dw if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL)) { - pMB->sy6522.IFR |= IxR_PERIPHERAL; - UpdateIFR(pMB); + UpdateIFR(pMB, 0, IxR_PERIPHERAL); pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin } } @@ -1920,41 +1919,6 @@ int MB_SetSnapshot_v1(const SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD /*dw //=========================================================================== -static UINT DoWriteFile(const HANDLE hFile, const void* const pData, const UINT Length) -{ - DWORD dwBytesWritten; - BOOL bRes = WriteFile( hFile, - pData, - Length, - &dwBytesWritten, - NULL); - - if(!bRes || (dwBytesWritten != Length)) - { - //dwError = GetLastError(); - throw std::string("Card: save error"); - } - - return dwBytesWritten; -} - -static UINT DoReadFile(const HANDLE hFile, void* const pData, const UINT Length) -{ - DWORD dwBytesRead; - BOOL bRes = ReadFile( hFile, - pData, - Length, - &dwBytesRead, - NULL); - - if (dwBytesRead != Length) - throw std::string("Card: file corrupt"); - - return dwBytesRead; -} - -//=========================================================================== - // Unit version history: // 2: Added: Timer1 & Timer2 active // 3: Added: Unit state @@ -2177,8 +2141,7 @@ bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version) if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL)) { - pMB->sy6522.IFR |= IxR_PERIPHERAL; - UpdateIFR(pMB); + UpdateIFR(pMB, 0, IxR_PERIPHERAL); pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin } } @@ -2303,8 +2266,7 @@ bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL)) { - pMB->sy6522.IFR |= IxR_PERIPHERAL; - UpdateIFR(pMB); + UpdateIFR(pMB, 0, IxR_PERIPHERAL); pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin } } From e5dbdb169649331f00bae59dfeb2f087b0f70411 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 28 Oct 2017 21:59:48 +0100 Subject: [PATCH 7/9] Full-screen: Hide mouse cursor after 2s of inactivity (#504) --- source/Common.h | 2 + source/Frame.cpp | 101 +++++++++++++++++++++++++++++--------- source/MouseInterface.cpp | 1 + source/MouseInterface.h | 2 - 4 files changed, 82 insertions(+), 24 deletions(-) diff --git a/source/Common.h b/source/Common.h index b439caac..c78af713 100644 --- a/source/Common.h +++ b/source/Common.h @@ -212,3 +212,5 @@ inline bool IsOriginal2E(void) enum eBUTTON {BUTTON0=0, BUTTON1}; enum eBUTTONSTATE {BUTTON_UP=0, BUTTON_DOWN}; + +enum {IDEVENT_TIMER_MOUSE=1, IDEVENT_TIMER_100MSEC}; diff --git a/source/Frame.cpp b/source/Frame.cpp index b41bcebc..6f70315e 100644 --- a/source/Frame.cpp +++ b/source/Frame.cpp @@ -117,7 +117,6 @@ static int buttondown = -1; static int buttonover = -1; static int buttonx = BUTTONX; static int buttony = BUTTONY; -static HRGN clipregion = (HRGN)0; static HDC g_hFrameDC = (HDC)0; static RECT framerect = {0,0,0,0}; @@ -130,10 +129,13 @@ static BOOL helpquit = 0; static BOOL g_bPaintingWindow = 0; static HFONT smallfont = (HFONT)0; static HWND tooltipwindow = (HWND)0; -static BOOL g_bUsingCursor = 0; // 1=AppleWin is using (hiding) the mouse-cursor +static BOOL g_bUsingCursor = FALSE; // TRUE = AppleWin is using (hiding) the mouse-cursor && restricting cursor to window - see SetUsingCursor() static int viewportx = VIEWPORTX; // Default to Normal (non-FullScreen) mode static int viewporty = VIEWPORTY; // Default to Normal (non-FullScreen) mode +static UINT_PTR g_TimerIDEvent_100msec = 0; +static UINT g_uCount100msec = 0; + static bool g_bShowingCursor = true; static bool g_bLastCursorInAppleViewport = false; @@ -144,7 +146,7 @@ void RelayEvent (UINT message, WPARAM wparam, LPARAM lparam); void ResetMachineState (); void SetFullScreenMode (); void SetNormalMode (); -void SetUsingCursor (BOOL); +static void SetUsingCursor(BOOL); static bool FileExists(std::string strFilename); bool g_bScrollLock_FullSpeed = false; @@ -164,11 +166,13 @@ static FULLSCREEN_SCALE_TYPE g_win_fullscreen_scale = 1; static int g_win_fullscreen_offsetx = 0; static int g_win_fullscreen_offsety = 0; +static bool g_bShowingConfigDlg = false; + // __ Prototypes __________________________________________________________________________________ - static void DrawCrosshairs (int x, int y); - static void UpdateMouseInAppleViewport(int iOutOfBoundsX, int iOutOfBoundsY, int x=0, int y=0); - static void ScreenWindowResize(const bool bCtrlKey); - static void FrameResizeWindow(int nNewScale); +void DrawCrosshairs (int x, int y); +void UpdateMouseInAppleViewport(int iOutOfBoundsX, int iOutOfBoundsY, int x=0, int y=0); +void ScreenWindowResize(const bool bCtrlKey); +void FrameResizeWindow(int nNewScale); // ========================================================================== @@ -326,6 +330,25 @@ static void RevealCursor() g_bLastCursorInAppleViewport = false; } +// Called when: +// . WM_MOUSEMOVE event +// . Switch from full-screen to normal (windowed) mode +// . AppleWin's main window is deactivated +static void FullScreenRevealCursor(void) +{ + if (!g_bIsFullScreen) + return; + + if (sg_Mouse.IsActive()) + return; + + if (!g_bUsingCursor && !g_bShowingCursor) + { + FrameShowCursor(TRUE); + g_uCount100msec = 0; + } +} + //=========================================================================== #define LOADBUTTONBITMAP(bitmapname) LoadImage(g_hInstance,bitmapname, \ @@ -1025,8 +1048,9 @@ LRESULT CALLBACK FrameWndProc ( case WM_ACTIVATE: // Sent when window is activated/deactivated. wParam indicates WA_ACTIVE, WA_INACTIVE, etc // Eg. Deactivate when Config dialog is active, AppleWin app loses focus, etc JoyReset(); - SetUsingCursor(0); + SetUsingCursor(FALSE); RevealCursor(); + FullScreenRevealCursor(); break; case WM_ACTIVATEAPP: // Sent when different app's window is activated/deactivated. @@ -1045,11 +1069,17 @@ LRESULT CALLBACK FrameWndProc ( RegSaveValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_X_POS), 1, framerect.left); RegSaveValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_Y_POS), 1, framerect.top); FrameReleaseDC(); - SetUsingCursor(0); + SetUsingCursor(FALSE); if (helpquit) { helpquit = 0; HtmlHelp(NULL,NULL,HH_CLOSE_ALL,0); } + if (g_TimerIDEvent_100msec) + { + BOOL bRes = KillTimer(g_hFrameWindow, g_TimerIDEvent_100msec); + LogFileOutput("KillTimer(g_TimerIDEvent_100msec), res=%d\n", bRes ? 1 : 0); + g_TimerIDEvent_100msec = 0; + } LogFileOutput("WM_CLOSE (done)\n"); break; @@ -1233,7 +1263,7 @@ LRESULT CALLBACK FrameWndProc ( // Process is done in WM_KEYUP: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8 if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == -1)) { - SetUsingCursor(0); + SetUsingCursor(FALSE); buttondown = wparam-VK_F1; if (g_bIsFullScreen && (buttonover != -1)) { if (buttonover != buttondown) @@ -1312,7 +1342,7 @@ LRESULT CALLBACK FrameWndProc ( } else if (wparam == VK_PAUSE) { - SetUsingCursor(0); + SetUsingCursor(FALSE); switch (g_nAppMode) { case MODE_RUNNING: @@ -1362,8 +1392,7 @@ LRESULT CALLBACK FrameWndProc ( } else { - SetUsingCursor(0); - return 0; // TC: Why return early? + SetUsingCursor(FALSE); } } break; @@ -1407,7 +1436,7 @@ LRESULT CALLBACK FrameWndProc ( { if (wparam & (MK_CONTROL | MK_SHIFT)) { - SetUsingCursor(0); + SetUsingCursor(FALSE); } else { @@ -1416,7 +1445,7 @@ LRESULT CALLBACK FrameWndProc ( } else if ( ((x < buttonx) && JoyUsingMouse() && ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING))) ) { - SetUsingCursor(1); + SetUsingCursor(TRUE); } else if (sg_Mouse.IsActive()) { @@ -1525,6 +1554,8 @@ LRESULT CALLBACK FrameWndProc ( UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY, x, y); } + FullScreenRevealCursor(); + RelayEvent(WM_MOUSEMOVE,wparam,lparam); break; } @@ -1549,6 +1580,21 @@ LRESULT CALLBACK FrameWndProc ( UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY); } } + else if (wparam == IDEVENT_TIMER_100MSEC) // GH#504 + { + if (g_bIsFullScreen + && !sg_Mouse.IsActive() // Don't interfere if there's a mousecard present! + && !g_bUsingCursor // Using mouse for joystick emulation (or mousecard restricted to window) + && g_bShowingCursor + && !g_bShowingConfigDlg) + { + g_uCount100msec++; + if (g_uCount100msec > 20) // Hide every 2sec of mouse inactivity + { + FrameShowCursor(FALSE); + } + } + } break; // VSCROLL @@ -1644,13 +1690,12 @@ LRESULT CALLBACK FrameWndProc ( } } } - if (g_bUsingCursor) - { - if (sg_Mouse.IsActive()) - sg_Mouse.SetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP); - else - JoySetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP); - } + + if (g_bUsingCursor && !sg_Mouse.IsActive()) + JoySetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP); + else if (sg_Mouse.IsActive()) + sg_Mouse.SetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP); + RelayEvent(message,wparam,lparam); break; @@ -1952,7 +1997,9 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/) case BTN_SETUP: { + g_bShowingConfigDlg = true; sg_PropertySheet.Init(); + g_bShowingConfigDlg = false; } break; @@ -2215,6 +2262,8 @@ void SetFullScreenMode () //=========================================================================== void SetNormalMode () { + FullScreenRevealCursor(); // Do before clearing g_bIsFullScreen flag + buttonover = -1; buttonx = BUTTONX; buttony = BUTTONY; @@ -2242,8 +2291,12 @@ void SetUsingCursor (BOOL bNewValue) return; g_bUsingCursor = bNewValue; + if (g_bUsingCursor) { + // Set TRUE when: + // . Using mouse for joystick emulation + // . Using mousecard and mouse is restricted to window SetCapture(g_hFrameWindow); RECT rect = { viewportx+2, // left viewporty+2, // top @@ -2454,6 +2507,10 @@ void FrameCreateWindow(void) g_hInstance,NULL ); SetupTooltipControls(); + + _ASSERT(g_TimerIDEvent_100msec == 0); + g_TimerIDEvent_100msec = SetTimer(g_hFrameWindow, IDEVENT_TIMER_100MSEC, 100, NULL); + LogFileOutput("FrameCreateWindow: SetTimer(), id=0x%08X\n", g_TimerIDEvent_100msec); } //=========================================================================== diff --git a/source/MouseInterface.cpp b/source/MouseInterface.cpp index 9be5d279..2c4be60f 100644 --- a/source/MouseInterface.cpp +++ b/source/MouseInterface.cpp @@ -889,6 +889,7 @@ namespace DIMouse return hr; // Setup timer to read mouse position + _ASSERT(g_TimerIDEvent == 0); g_TimerIDEvent = SetTimer(hDlg, IDEVENT_TIMER_MOUSE, 8, NULL); // 120Hz timer LogFileOutput("DirectInputInit: SetTimer(), id=0x%08X\n", g_TimerIDEvent); if (g_TimerIDEvent == 0) diff --git a/source/MouseInterface.h b/source/MouseInterface.h index 2b48f0f0..4d63b81b 100644 --- a/source/MouseInterface.h +++ b/source/MouseInterface.h @@ -101,8 +101,6 @@ protected: UINT m_uSlot; }; -#define IDEVENT_TIMER_MOUSE 1 - namespace DIMouse { HRESULT DirectInputInit( HWND hDlg ); From 146b6ebad3ac3f11cb146a0917bbacd3b9366ba6 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 28 Oct 2017 22:13:05 +0100 Subject: [PATCH 8/9] Opening any dialog will deactivate the main frame - so don't hide the mouse cursor --- source/Frame.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/source/Frame.cpp b/source/Frame.cpp index 6f70315e..062c7ab7 100644 --- a/source/Frame.cpp +++ b/source/Frame.cpp @@ -166,7 +166,7 @@ static FULLSCREEN_SCALE_TYPE g_win_fullscreen_scale = 1; static int g_win_fullscreen_offsetx = 0; static int g_win_fullscreen_offsety = 0; -static bool g_bShowingConfigDlg = false; +static bool g_bFrameActive = false; // __ Prototypes __________________________________________________________________________________ void DrawCrosshairs (int x, int y); @@ -311,7 +311,7 @@ static void FrameShowCursor(BOOL bShow) // Called when: // . Ctrl-Left mouse button // . PAUSE pressed (when MODE_RUNNING) -// . AppleWin's main window is deactivated +// . AppleWin's main window is activated/deactivated static void RevealCursor() { if (!sg_Mouse.IsActiveAndEnabled()) @@ -333,7 +333,7 @@ static void RevealCursor() // Called when: // . WM_MOUSEMOVE event // . Switch from full-screen to normal (windowed) mode -// . AppleWin's main window is deactivated +// . AppleWin's main window is activated/deactivated static void FullScreenRevealCursor(void) { if (!g_bIsFullScreen) @@ -1051,6 +1051,7 @@ LRESULT CALLBACK FrameWndProc ( SetUsingCursor(FALSE); RevealCursor(); FullScreenRevealCursor(); + g_bFrameActive = (wparam != WA_INACTIVE); break; case WM_ACTIVATEAPP: // Sent when different app's window is activated/deactivated. @@ -1586,7 +1587,7 @@ LRESULT CALLBACK FrameWndProc ( && !sg_Mouse.IsActive() // Don't interfere if there's a mousecard present! && !g_bUsingCursor // Using mouse for joystick emulation (or mousecard restricted to window) && g_bShowingCursor - && !g_bShowingConfigDlg) + && g_bFrameActive) // Frame inactive when eg. Config or 'Select Disk Image' dialogs are opened { g_uCount100msec++; if (g_uCount100msec > 20) // Hide every 2sec of mouse inactivity @@ -1997,9 +1998,7 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/) case BTN_SETUP: { - g_bShowingConfigDlg = true; sg_PropertySheet.Init(); - g_bShowingConfigDlg = false; } break; From 77cbfbec99eb4383aebaafb9b45205c74ba545f7 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 29 Oct 2017 10:50:08 +0000 Subject: [PATCH 9/9] Remove stale/unused key buffering code --- source/Keyboard.cpp | 94 +-------------------------------------------- 1 file changed, 2 insertions(+), 92 deletions(-) diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp index 47f1687d..d403dbe6 100644 --- a/source/Keyboard.cpp +++ b/source/Keyboard.cpp @@ -36,10 +36,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "YamlHelper.h" #include "Video.h" // Needed by TK3000 //e, to refresh the frame at each |Mode| change -static bool g_bKeybBufferEnable = false; - -#define KEY_OLD - static BYTE asciicode[2][10] = { {0x08,0x0D,0x15,0x2F,0x00,0x00,0x00,0x00,0x00,0x00}, {0x08,0x0B,0x15,0x0A,0x00,0x00,0x00,0x00,0x00,0x7F} @@ -56,26 +52,7 @@ static bool g_bP8CapsLock = true; //Caps lock key of Pravets 8A/C static int lastvirtkey = 0; // Current PC keycode static BYTE keycode = 0; // Current Apple keycode -#ifdef KEY_OLD -// Original static BOOL keywaiting = 0; -#else -// Buffered key input: -// - Needed on faster PCs where aliasing occurs during short/fast bursts of 6502 code. -// - Keyboard only sampled during 6502 execution, so if it's run too fast then key presses will be missed. -const int KEY_BUFFER_MIN_SIZE = 1; -const int KEY_BUFFER_MAX_SIZE = 2; -static int g_nKeyBufferSize = KEY_BUFFER_MAX_SIZE; // Circ key buffer size -static int g_nNextInIdx = 0; -static int g_nNextOutIdx = 0; -static int g_nKeyBufferCnt = 0; - -static struct -{ - int nVirtKey; - BYTE nAppleKey; -} g_nKeyBuffer[KEY_BUFFER_MAX_SIZE]; -#endif static BYTE g_nLastKey = 0x00; @@ -87,34 +64,9 @@ static BYTE g_nLastKey = 0x00; void KeybReset() { -#ifdef KEY_OLD keywaiting = 0; -#else - g_nNextInIdx = 0; - g_nNextOutIdx = 0; - g_nKeyBufferCnt = 0; - g_nLastKey = 0x00; - - g_nKeyBufferSize = g_bKeybBufferEnable ? KEY_BUFFER_MAX_SIZE : KEY_BUFFER_MIN_SIZE; -#endif } -//=========================================================================== - -//void KeybSetBufferMode(bool bNewKeybBufferEnable) -//{ -// if(g_bKeybBufferEnable == bNewKeybBufferEnable) -// return; -// -// g_bKeybBufferEnable = bNewKeybBufferEnable; -// KeybReset(); -//} -// -//bool KeybGetBufferMode() -//{ -// return g_bKeybBufferEnable; -//} - //=========================================================================== bool KeybGetAltStatus () { @@ -329,9 +281,6 @@ void KeybQueueKeypress (int key, BOOL bASCII) // Note: VK_CANCEL is Control-Break if ((key == VK_CANCEL) && (GetKeyState(VK_CONTROL) < 0)) { -#ifndef KEY_OLD - g_nNextInIdx = g_nNextOutIdx = g_nKeyBufferCnt = 0; -#endif g_bFreshReset = true; CtrlReset(); return; @@ -360,23 +309,8 @@ void KeybQueueKeypress (int key, BOOL bASCII) keycode = asciicode[IS_APPLE2 ? 0 : 1][key - VK_LEFT]; // Convert to Apple arrow keycode lastvirtkey = key; } -#ifdef KEY_OLD + keywaiting = 1; -#else - bool bOverflow = false; - - if(g_nKeyBufferCnt < g_nKeyBufferSize) - g_nKeyBufferCnt++; - else - bOverflow = true; - - g_nKeyBuffer[g_nNextInIdx].nVirtKey = lastvirtkey; - g_nKeyBuffer[g_nNextInIdx].nAppleKey = keycode; - g_nNextInIdx = (g_nNextInIdx + 1) % g_nKeyBufferSize; - - if(bOverflow) - g_nNextOutIdx = (g_nNextOutIdx + 1) % g_nKeyBufferSize; -#endif } //=========================================================================== @@ -472,21 +406,7 @@ BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG) // -#ifdef KEY_OLD return keycode | (keywaiting ? 0x80 : 0); -#else - BYTE nKey = g_nKeyBufferCnt ? 0x80 : 0; - if(g_nKeyBufferCnt) - { - nKey |= g_nKeyBuffer[g_nNextOutIdx].nAppleKey; - g_nLastKey = g_nKeyBuffer[g_nNextOutIdx].nAppleKey; - } - else - { - nKey |= g_nLastKey; - } - return nKey; -#endif } //=========================================================================== @@ -506,19 +426,9 @@ BYTE __stdcall KeybReadFlag (WORD, WORD, BYTE, BYTE, ULONG) // -#ifdef KEY_OLD keywaiting = 0; + return keycode | ((GetKeyState(lastvirtkey) < 0) ? 0x80 : 0); -#else - BYTE nKey = (GetKeyState(g_nKeyBuffer[g_nNextOutIdx].nVirtKey) < 0) ? 0x80 : 0; - nKey |= g_nKeyBuffer[g_nNextOutIdx].nAppleKey; - if(g_nKeyBufferCnt) - { - g_nKeyBufferCnt--; - g_nNextOutIdx = (g_nNextOutIdx + 1) % g_nKeyBufferSize; - } - return nKey; -#endif } //===========================================================================