From 776a48fc0176c0c503cd8acaaa49f0a57f4f88c8 Mon Sep 17 00:00:00 2001 From: tomcw Date: Wed, 10 Feb 2021 20:51:11 +0000 Subject: [PATCH 1/5] MB/6522: support for T1 latch in one-shot mode --- source/Mockingboard.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index 131fbb6a..b4e98fe1 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -275,6 +275,8 @@ static void StopTimer2(SY6522_AY8910* pMB) static void ResetSY6522(SY6522_AY8910* pMB) { memset(&pMB->sy6522,0,sizeof(SY6522)); + pMB->sy6522.TIMER1_LATCH.w = 0xffff; // Some random value (but pick $ffff so it's deterministic) + // . NB. if it's too small (< ~$0007) then MB detection routines will fail! StopTimer1(pMB); StopTimer2(pMB); @@ -2007,7 +2009,7 @@ static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, UL // . RESET -> Mockingboard mode (b#000) // . $C0C1, then $C0C4 (or $C0C4, then $C0C1) -> Phasor mode (b#101) // . $C0C2 -> Echo+ mode (b#111) -// . $C0C5 -> remaing in Echo+ mode (b#111) +// . $C0C5 -> remaining in Echo+ mode (b#111) // So $C0C5 seemingly results in 2 different modes. // @@ -2216,9 +2218,7 @@ void MB_UpdateCycles(ULONG uExecutedCycles) SY6522_AY8910* pMB = &g_MB[i]; const bool bTimer1Underflow = CheckTimerUnderflow(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks); - const bool bTimer2Underflow = CheckTimerUnderflow(pMB->sy6522.TIMER2_COUNTER.w, pMB->sy6522.timer2IrqDelay, nClocks); - - if (pMB->bTimer1Active && bTimer1Underflow) + if (bTimer1Underflow) { pMB->sy6522.TIMER1_COUNTER.w += pMB->sy6522.TIMER1_LATCH.w; // GH#651: account for underflowed cycles too pMB->sy6522.TIMER1_COUNTER.w += kExtraTimerCycles; // GH#652: account for extra 2 cycles @@ -2233,6 +2233,9 @@ void MB_UpdateCycles(ULONG uExecutedCycles) pMB->sy6522.TIMER1_COUNTER.w = 0; } } + + // No TIMER2 latch so "after timing out, the counter will continue to decrement" + CheckTimerUnderflow(pMB->sy6522.TIMER2_COUNTER.w, pMB->sy6522.timer2IrqDelay, nClocks); } } @@ -2249,6 +2252,8 @@ static int MB_SyncEventCallback(int id, int /*cycles*/, ULONG uExecutedCycles) UpdateIFR(pMB, 0, IxR_TIMER1); + MB_UpdateCycles(uExecutedCycles); + if ((pMB->sy6522.ACR & RUNMODE) == RM_ONESHOT) { // One-shot mode @@ -2257,8 +2262,6 @@ static int MB_SyncEventCallback(int id, int /*cycles*/, ULONG uExecutedCycles) return 0; // Don't repeat event } - MB_UpdateCycles(uExecutedCycles); - StartTimer1(pMB); return pMB->sy6522.TIMER1_COUNTER.w + kExtraTimerCycles; } From 466207f5d3699586fc40d6270de187f262341089 Mon Sep 17 00:00:00 2001 From: Andrea Date: Wed, 10 Feb 2021 20:55:58 +0000 Subject: [PATCH 2/5] Save-state: load/save dialog: Remove ; to concatenate string and avoid unused code. (PR #924) --- source/Configuration/PropertySheetHelper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/Configuration/PropertySheetHelper.cpp b/source/Configuration/PropertySheetHelper.cpp index e9c9dfd3..7ce645bc 100644 --- a/source/Configuration/PropertySheetHelper.cpp +++ b/source/Configuration/PropertySheetHelper.cpp @@ -209,7 +209,7 @@ int CPropertySheetHelper::SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bo ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = hWindow; ofn.hInstance = GetFrame().g_hInstance; - ofn.lpstrFilter = TEXT("Save State files (*.aws.yaml)\0*.aws.yaml\0"); + ofn.lpstrFilter = TEXT("Save State files (*.aws.yaml)\0*.aws.yaml\0") TEXT("All Files\0*.*\0"); ofn.lpstrFile = szFilename; // Dialog strips the last .EXT from this string (eg. file.aws.yaml is displayed as: file.aws ofn.nMaxFile = sizeof(szFilename); From 8c2b38d19dc674ac5beab8daf257f501c27323b9 Mon Sep 17 00:00:00 2001 From: Andrea Date: Wed, 10 Feb 2021 21:05:00 +0000 Subject: [PATCH 3/5] Enable ConformanceMode in VS2019. (PR #923) This reduces the chances of incompatibility between gcc and vs. 99% is "const char *" literals. 1 case of a goto jumping over a variable declaration (but it is not needed). --- AppleWinExpress2019.vcxproj | 6 +++++ source/Configuration/PropertySheetHelper.cpp | 4 +-- source/Configuration/PropertySheetHelper.h | 4 +-- source/Debugger/Debug.cpp | 26 +++++++++---------- source/Debugger/Debug.h | 2 +- source/Debugger/Debugger_Assembler.h | 2 +- source/Debugger/Debugger_DisassemblerData.cpp | 8 +++--- source/Debugger/Debugger_Display.cpp | 12 ++++----- source/Debugger/Debugger_Help.cpp | 4 +-- source/Debugger/Debugger_Symbols.cpp | 6 ++--- source/Debugger/Debugger_Types.h | 2 +- source/SoundCore.cpp | 2 +- 12 files changed, 42 insertions(+), 36 deletions(-) diff --git a/AppleWinExpress2019.vcxproj b/AppleWinExpress2019.vcxproj index bc27be23..9ee9b430 100644 --- a/AppleWinExpress2019.vcxproj +++ b/AppleWinExpress2019.vcxproj @@ -441,6 +441,7 @@ MultiThreadedDebug /utf-8 %(AdditionalOptions) Default + true Windows @@ -469,6 +470,7 @@ /utf-8 %(AdditionalOptions) Default 4995 + true Windows @@ -495,6 +497,7 @@ source;source\cpu;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories) MultiThreadedDebug /utf-8 %(AdditionalOptions) + true Windows @@ -524,6 +527,7 @@ MultiThreaded Speed /utf-8 %(AdditionalOptions) + true Windows @@ -557,6 +561,7 @@ Speed /utf-8 %(AdditionalOptions) 4995 + true Windows @@ -589,6 +594,7 @@ MultiThreaded Speed /utf-8 %(AdditionalOptions) + true Windows diff --git a/source/Configuration/PropertySheetHelper.cpp b/source/Configuration/PropertySheetHelper.cpp index 7ce645bc..51b2dec3 100644 --- a/source/Configuration/PropertySheetHelper.cpp +++ b/source/Configuration/PropertySheetHelper.cpp @@ -150,7 +150,7 @@ void CPropertySheetHelper::SetSlot(UINT slot, SS_CARDTYPE newCardType) // Used by: // . CPageDisk: IDC_CIDERPRESS_BROWSE // . CPageAdvanced: IDC_PRINTER_DUMP_FILENAME_BROWSE -std::string CPropertySheetHelper::BrowseToFile(HWND hWindow, TCHAR* pszTitle, TCHAR* REGVALUE, TCHAR* FILEMASKS) +std::string CPropertySheetHelper::BrowseToFile(HWND hWindow, const TCHAR* pszTitle, const TCHAR* REGVALUE, const TCHAR* FILEMASKS) { TCHAR szFilename[MAX_PATH]; RegLoadString(REG_CONFIG, REGVALUE, 1, szFilename, MAX_PATH, TEXT("")); @@ -189,7 +189,7 @@ void CPropertySheetHelper::SaveStateUpdate() } // NB. OK'ing this property sheet will call SaveStateUpdate()->Snapshot_SetFilename() with this new path & filename -int CPropertySheetHelper::SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bool bSave) +int CPropertySheetHelper::SaveStateSelectImage(HWND hWindow, const TCHAR* pszTitle, bool bSave) { // Whenever harddisks/disks are inserted (or removed) and *if path has changed* then: // . Snapshot's path & Snapshot's filename will be updated to reflect the new defaults. diff --git a/source/Configuration/PropertySheetHelper.h b/source/Configuration/PropertySheetHelper.h index fe405f67..1c4feb10 100644 --- a/source/Configuration/PropertySheetHelper.h +++ b/source/Configuration/PropertySheetHelper.h @@ -15,9 +15,9 @@ public: void FillComboBox(HWND window, int controlid, LPCTSTR choices, int currentchoice); void SetSlot(UINT slot, SS_CARDTYPE newCardType); - std::string BrowseToFile(HWND hWindow, TCHAR* pszTitle, TCHAR* REGVALUE,TCHAR* FILEMASKS); + std::string BrowseToFile(HWND hWindow, const TCHAR* pszTitle, const TCHAR* REGVALUE, const TCHAR* FILEMASKS); void SaveStateUpdate(); - int SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bool bSave); + int SaveStateSelectImage(HWND hWindow, const TCHAR* pszTitle, bool bSave); void PostMsgAfterClose(HWND hWnd, PAGETYPE page); void ResetPageMask(void) { m_bmPages = 0; } // Req'd because cancelling doesn't clear the page-mask diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp index 2affeccc..47188308 100644 --- a/source/Debugger/Debug.cpp +++ b/source/Debugger/Debug.cpp @@ -4368,7 +4368,7 @@ Update_t CmdMemoryLoad (int nArgs) struct KnownFileType_t { - char *pExtension; + const char *pExtension; int nAddress; int nLength; }; @@ -5005,7 +5005,7 @@ Update_t CmdNTSC (int nArgs) struct KnownFileType_t { - char *pExtension; + const char *pExtension; }; enum KnownFileType_e @@ -5032,9 +5032,9 @@ Update_t CmdNTSC (int nArgs) assert( (nFileType == NUM_FILE_TYPES) ); #endif - char *pFileName = (nArgs > 1) ? g_aArgs[ 2 ].sArg : ""; + const char *pFileName = (nArgs > 1) ? g_aArgs[ 2 ].sArg : ""; int nLen = strlen( pFileName ); - char *pEnd = pFileName + nLen - 1; + const char *pEnd = pFileName + nLen - 1; while( pEnd > pFileName ) { if( *pEnd == '.' ) @@ -5558,7 +5558,7 @@ Update_t CmdNTSC (int nArgs) } - size_t nRead = fread( pSwizzled, g_nChromaSize, 1, pFile ); + fread( pSwizzled, g_nChromaSize, 1, pFile ); if( iFileType == TYPE_BMP ) { @@ -8296,12 +8296,12 @@ void ProfileFormat( bool bExport, ProfileFormat_e eFormatMode ) bOpcodeGood = false; } - char *pColorOperator = ""; - char *pColorNumber = ""; - char *pColorOpcode = ""; - char *pColorMnemonic = ""; - char *pColorOpmode = ""; - char *pColorTotal = ""; + const char *pColorOperator = ""; + const char *pColorNumber = ""; + const char *pColorOpcode = ""; + const char *pColorMnemonic = ""; + const char *pColorOpmode = ""; + const char *pColorTotal = ""; if (! bExport) { pColorOperator = CHC_ARG_SEP; // grey @@ -8700,7 +8700,7 @@ void DebugContinueStepping(const bool bCallerWillUpdateDisplay/*=false*/) { TCHAR sText[ CONSOLE_WIDTH ]; char szStopMessage[CONSOLE_WIDTH]; - char* pszStopReason = szStopMessage; + const char* pszStopReason = szStopMessage; if (regs.pc == g_nDebugStepUntil) pszStopReason = TEXT("PC matches 'Go until' address"); @@ -8966,7 +8966,7 @@ void DebugInitialize () // Check all summary help to see if it fits within the console for (int iCmd = 0; iCmd < NUM_COMMANDS; iCmd++ ) { - char *pHelp = g_aCommands[ iCmd ].pHelpSummary; + const char *pHelp = g_aCommands[ iCmd ].pHelpSummary; if (pHelp) { int nLen = _tcslen( pHelp ) + 2; diff --git a/source/Debugger/Debug.h b/source/Debugger/Debug.h index 91ac7d5c..29e963bd 100644 --- a/source/Debugger/Debug.h +++ b/source/Debugger/Debug.h @@ -150,7 +150,7 @@ // Symbol Table / Memory bool FindAddressFromSymbol( const char* pSymbol, WORD * pAddress_ = NULL, int * iTable_ = NULL ); WORD GetAddressFromSymbol( const char* symbol); // HACK: returns 0 if symbol not found - void SymbolUpdate( SymbolTable_Index_e eSymbolTable, char *pSymbolName, WORD nAddrss, bool bRemoveSymbol, bool bUpdateSymbol ); + void SymbolUpdate( SymbolTable_Index_e eSymbolTable, const char *pSymbolName, WORD nAddrss, bool bRemoveSymbol, bool bUpdateSymbol ); const char* FindSymbolFromAddress( WORD nAdress, int * iTable_ = NULL ); const char* GetSymbol( WORD nAddress, int nBytes); diff --git a/source/Debugger/Debugger_Assembler.h b/source/Debugger/Debugger_Assembler.h index 30ed3f58..56dddcb4 100644 --- a/source/Debugger/Debugger_Assembler.h +++ b/source/Debugger/Debugger_Assembler.h @@ -172,7 +172,7 @@ extern int g_aAssemblerFirstDirective[ NUM_ASSEMBLERS ]; struct AssemblerDirective_t { - char *m_pMnemonic; + const char *m_pMnemonic; Hash_t m_nHash; }; diff --git a/source/Debugger/Debugger_DisassemblerData.cpp b/source/Debugger/Debugger_DisassemblerData.cpp index 2c4dbee3..24cec475 100644 --- a/source/Debugger/Debugger_DisassemblerData.cpp +++ b/source/Debugger/Debugger_DisassemblerData.cpp @@ -80,7 +80,7 @@ WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_) tData_.nEndAddress = nAddress + nLen; // tData_.nArraySize = 0; - char *pSymbolName = ""; + const char *pSymbolName = ""; char aSymbolName[ MAX_SYMBOLS_LEN+1 ]; SymbolTable_Index_e eSymbolTable = SYMBOLS_ASSEMBLY; bool bAutoDefineName = false; // 2.7.0.34 @@ -93,8 +93,8 @@ WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_) } else { - pSymbolName = g_aArgs[ 1 ].sArg; - pSymbolName[MAX_SYMBOLS_LEN] = 0; // truncate to max symbol length + g_aArgs[ 1 ].sArg[MAX_SYMBOLS_LEN] = 0; // truncate to max symbol length + pSymbolName = g_aArgs[1].sArg; } } else @@ -167,7 +167,7 @@ Update_t CmdDisasmDataDefCode (int nArgs) return UPDATE_DISASM | ConsoleUpdate(); } -char* g_aNopcodeTypes[ NUM_NOPCODE_TYPES ] = +const char* g_aNopcodeTypes[ NUM_NOPCODE_TYPES ] = { "-n/a-" ,"byte1" diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp index 79a0b7fe..336891cd 100644 --- a/source/Debugger/Debugger_Display.cpp +++ b/source/Debugger/Debugger_Display.cpp @@ -140,12 +140,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \x19 Down */ #if USE_APPLE_FONT - char * g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "^", "\x8B" }; // "`K" 0x4B - char * g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "=", "\x88" }; // "`H" 0x48 - char * g_sConfigBranchIndicatorDown [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "v", "\x8A" }; // "`J" 0x4A + const char * g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "^", "\x8B" }; // "`K" 0x4B + const char * g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "=", "\x88" }; // "`H" 0x48 + const char * g_sConfigBranchIndicatorDown [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "v", "\x8A" }; // "`J" 0x4A #else - char * g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "^", "\x35" }; - char * g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "=", "\x33" }; + const char * g_sConfigBranchIndicatorUp [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "^", "\x35" }; + const char * g_sConfigBranchIndicatorEqual[ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "=", "\x33" }; char * g_sConfigBranchIndicatorDown [ NUM_DISASM_BRANCH_TYPES+1 ] = { " ", "v", "\x36" }; #endif @@ -2832,7 +2832,7 @@ void _DrawSoftSwitchAddress( RECT & rect, int nAddress, int bg_default = BG_INFO // 2.7.0.7 Cleaned up display of soft-switches to show address. //=========================================================================== -void _DrawSoftSwitch( RECT & rect, int nAddress, bool bSet, char *sPrefix, char *sOn, char *sOff, const char *sSuffix = NULL, int bg_default = BG_INFO ) +void _DrawSoftSwitch( RECT & rect, int nAddress, bool bSet, const char *sPrefix, const char *sOn, const char *sOff, const char *sSuffix = NULL, int bg_default = BG_INFO ) { RECT temp = rect; diff --git a/source/Debugger/Debugger_Help.cpp b/source/Debugger/Debugger_Help.cpp index c1d281ea..433fe931 100644 --- a/source/Debugger/Debugger_Help.cpp +++ b/source/Debugger/Debugger_Help.cpp @@ -335,7 +335,7 @@ void _ColorizeString( // pOperator is one of CHC_* void _ColorizeOperator( char * & pDst, const char * & pSrc, - char * pOperator ) + const char * pOperator ) { int nLen; @@ -828,7 +828,7 @@ Update_t CmdHelpSpecific (int nArgs) if (pCommand) { - char *pHelp = pCommand->pHelpSummary; + const char *pHelp = pCommand->pHelpSummary; if (pHelp) { if (bCategory) diff --git a/source/Debugger/Debugger_Symbols.cpp b/source/Debugger/Debugger_Symbols.cpp index a168d6cd..636a5e61 100644 --- a/source/Debugger/Debugger_Symbols.cpp +++ b/source/Debugger/Debugger_Symbols.cpp @@ -42,7 +42,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // Symbols ________________________________________________________________________________________ - char* g_sFileNameSymbols[ NUM_SYMBOL_TABLES ] = { + const char* g_sFileNameSymbols[ NUM_SYMBOL_TABLES ] = { "APPLE2E.SYM" ,"A2_BASIC.SYM" ,"A2_ASM.SYM" @@ -55,7 +55,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA }; std::string g_sFileNameSymbolsUser; - char * g_aSymbolTableNames[ NUM_SYMBOL_TABLES ] = + const char * g_aSymbolTableNames[ NUM_SYMBOL_TABLES ] = { "Main" ,"Basic" @@ -833,7 +833,7 @@ Update_t _CmdSymbolsClear( SymbolTable_Index_e eSymbolTable ) //=========================================================================== -void SymbolUpdate( SymbolTable_Index_e eSymbolTable, char *pSymbolName, WORD nAddress, bool bRemoveSymbol, bool bUpdateSymbol ) +void SymbolUpdate( SymbolTable_Index_e eSymbolTable, const char *pSymbolName, WORD nAddress, bool bRemoveSymbol, bool bUpdateSymbol ) { if (bRemoveSymbol) pSymbolName = g_aArgs[2].sArg; diff --git a/source/Debugger/Debugger_Types.h b/source/Debugger/Debugger_Types.h index 2cbdf57d..02722cb5 100644 --- a/source/Debugger/Debugger_Types.h +++ b/source/Debugger/Debugger_Types.h @@ -270,7 +270,7 @@ char m_sName[ MAX_COMMAND_LEN ]; CmdFuncPtr_t pFunction; int iCommand; // offset (enum) for direct command name lookup - char *pHelpSummary; // 1 line help summary + const char *pHelpSummary; // 1 line help summary // Hash_t m_nHash; // TODO }; diff --git a/source/SoundCore.cpp b/source/SoundCore.cpp index 68a2336a..50190811 100644 --- a/source/SoundCore.cpp +++ b/source/SoundCore.cpp @@ -80,7 +80,7 @@ static BOOL CALLBACK DSEnumProc(LPGUID lpGUID, LPCTSTR lpszDesc, LPCTSTR lpszDrv //----------------------------------------------------------------------------- #ifdef _DEBUG -static char *DirectSound_ErrorText (HRESULT error) +static const char *DirectSound_ErrorText (HRESULT error) { switch( error ) { From ff29b055ce789ff09d0861fed9f4a66ebdc8cf76 Mon Sep 17 00:00:00 2001 From: tomcw Date: Thu, 11 Feb 2021 22:44:40 +0000 Subject: [PATCH 4/5] MB/6522: fix timer1 underflow for very small values --- source/Mockingboard.cpp | 57 +++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 31 deletions(-) diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index b4e98fe1..898c31da 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -696,6 +696,21 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) //----------------------------------------------------------------------------- +static USHORT GetTimer1Counter(BYTE reg, USHORT counter, USHORT latch) +{ + const UINT opcodeCycleAdjust = GetOpcodeCyclesForRead(reg) - 1; // to compensate for the 4/5/6 cycle read opcode + int timer = (short)counter - opcodeCycleAdjust; + while (timer < -1) + timer += (latch + kExtraTimerCycles); + return (USHORT)timer; +} + +static USHORT GetTimer2Counter(BYTE reg, USHORT counter) +{ + const UINT opcodeCycleAdjust = GetOpcodeCyclesForRead(reg) - 1; // to compensate for the 4/5/6 cycle read opcode + return counter - opcodeCycleAdjust; +} + static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) { g_bMB_Active = true; @@ -718,18 +733,12 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) nValue = pMB->sy6522.DDRA; break; case 0x04: // TIMER1L_COUNTER - { - // NB. GH#701 (T1C:=0xFFFF, LDA T1C_L, A==0xFC) - const UINT opcodeCycleAdjust = GetOpcodeCyclesForRead(nReg) - 1; // to compensate for the 4/5/6 cycle read opcode - nValue = (pMB->sy6522.TIMER1_COUNTER.w - opcodeCycleAdjust) & 0xff; - UpdateIFR(pMB, IxR_TIMER1); - } + // NB. GH#701 (T1C:=0xFFFF, LDA T1C_L[4cy], A==0xFC) + nValue = GetTimer1Counter(nReg, pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.TIMER1_LATCH.w) & 0xff; + UpdateIFR(pMB, IxR_TIMER1); break; case 0x05: // TIMER1H_COUNTER - { - const UINT opcodeCycleAdjust = GetOpcodeCyclesForRead(nReg) - 1; // to compensate for the 4/5/6 cycle read opcode - nValue = (pMB->sy6522.TIMER1_COUNTER.w - opcodeCycleAdjust) >> 8; - } + nValue = GetTimer1Counter(nReg, pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.TIMER1_LATCH.w) >> 8; break; case 0x06: // TIMER1L_LATCH nValue = pMB->sy6522.TIMER1_LATCH.l; @@ -738,17 +747,11 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) nValue = pMB->sy6522.TIMER1_LATCH.h; break; case 0x08: // TIMER2L - { - const UINT opcodeCycleAdjust = GetOpcodeCyclesForRead(nReg) - 1; // to compensate for the 4/5/6 cycle read opcode - nValue = (pMB->sy6522.TIMER2_COUNTER.w - opcodeCycleAdjust) & 0xff; - UpdateIFR(pMB, IxR_TIMER2); - } + nValue = GetTimer2Counter(nReg, pMB->sy6522.TIMER2_COUNTER.w) & 0xff; + UpdateIFR(pMB, IxR_TIMER2); break; case 0x09: // TIMER2H - { - const UINT opcodeCycleAdjust = GetOpcodeCyclesForRead(nReg) - 1; // to compensate for the 4/5/6 cycle read opcode - nValue = (pMB->sy6522.TIMER2_COUNTER.w - opcodeCycleAdjust) >> 8; - } + nValue = GetTimer2Counter(nReg, pMB->sy6522.TIMER2_COUNTER.w) >> 8; break; case 0x0a: // SERIAL_SHIFT break; @@ -2220,18 +2223,10 @@ void MB_UpdateCycles(ULONG uExecutedCycles) const bool bTimer1Underflow = CheckTimerUnderflow(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks); if (bTimer1Underflow) { - pMB->sy6522.TIMER1_COUNTER.w += pMB->sy6522.TIMER1_LATCH.w; // GH#651: account for underflowed cycles too - pMB->sy6522.TIMER1_COUNTER.w += kExtraTimerCycles; // GH#652: account for extra 2 cycles - // EG. T1C=0xFFFE, T1L=0x0001 - // . T1C += T1L = 0xFFFF - // . T1C += 2 = 0x0001 - if (pMB->sy6522.TIMER1_COUNTER.w > pMB->sy6522.TIMER1_LATCH.w) - { - if (pMB->sy6522.TIMER1_LATCH.w) - pMB->sy6522.TIMER1_COUNTER.w %= pMB->sy6522.TIMER1_LATCH.w; // Only occurs if LATCH.w<0x0007 (# cycles for longest opcode) - else - pMB->sy6522.TIMER1_COUNTER.w = 0; - } + int timer = (int) (short) (pMB->sy6522.TIMER1_COUNTER.w); + while (timer < -1) + timer += (pMB->sy6522.TIMER1_LATCH.w + kExtraTimerCycles); // GH#651: account for underflowed cycles / GH#652: account for extra 2 cycles + pMB->sy6522.TIMER1_COUNTER.w = (USHORT)timer; } // No TIMER2 latch so "after timing out, the counter will continue to decrement" From 84a705d20d19d6147bf44f257f75c4662cc1b56b Mon Sep 17 00:00:00 2001 From: tomcw Date: Fri, 12 Feb 2021 19:16:14 +0000 Subject: [PATCH 5/5] MB/6522: improve T1 underflow with latch --- source/Mockingboard.cpp | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index 898c31da..b71ae4ba 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -696,13 +696,15 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) //----------------------------------------------------------------------------- -static USHORT GetTimer1Counter(BYTE reg, USHORT counter, USHORT latch) +static bool CheckTimerUnderflow(USHORT& counter, int& timerIrqDelay, const USHORT nClocks); +static int OnTimer1Underflow(USHORT& counter, USHORT latch); + +static USHORT GetTimer1Counter(BYTE reg, USHORT counter, USHORT latch, int timerIrqDelay) { const UINT opcodeCycleAdjust = GetOpcodeCyclesForRead(reg) - 1; // to compensate for the 4/5/6 cycle read opcode - int timer = (short)counter - opcodeCycleAdjust; - while (timer < -1) - timer += (latch + kExtraTimerCycles); - return (USHORT)timer; + if (CheckTimerUnderflow(counter, timerIrqDelay, opcodeCycleAdjust)) + OnTimer1Underflow(counter, latch); + return counter; } static USHORT GetTimer2Counter(BYTE reg, USHORT counter) @@ -734,11 +736,11 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) break; case 0x04: // TIMER1L_COUNTER // NB. GH#701 (T1C:=0xFFFF, LDA T1C_L[4cy], A==0xFC) - nValue = GetTimer1Counter(nReg, pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.TIMER1_LATCH.w) & 0xff; + nValue = GetTimer1Counter(nReg, pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.TIMER1_LATCH.w, pMB->sy6522.timer1IrqDelay) & 0xff; UpdateIFR(pMB, IxR_TIMER1); break; case 0x05: // TIMER1H_COUNTER - nValue = GetTimer1Counter(nReg, pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.TIMER1_LATCH.w) >> 8; + nValue = GetTimer1Counter(nReg, pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.TIMER1_LATCH.w, pMB->sy6522.timer1IrqDelay) >> 8; break; case 0x06: // TIMER1L_LATCH nValue = pMB->sy6522.TIMER1_LATCH.l; @@ -2166,15 +2168,15 @@ void MB_PeriodicUpdate(UINT executedCycles) //----------------------------------------------------------------------------- -static bool CheckTimerUnderflow(USHORT& timerCounter, int& timerIrqDelay, const USHORT nClocks) +static bool CheckTimerUnderflow(USHORT& counter, int& timerIrqDelay, const USHORT nClocks) { if (nClocks == 0) return false; - int oldTimer = timerCounter; - int timer = timerCounter; + int oldTimer = counter; + int timer = counter; timer -= nClocks; - timerCounter = (USHORT)timer; + counter = (USHORT)timer; bool timerIrq = false; @@ -2197,6 +2199,15 @@ static bool CheckTimerUnderflow(USHORT& timerCounter, int& timerIrqDelay, const return timerIrq; } +static int OnTimer1Underflow(USHORT& counter, USHORT latch) +{ + int timer = (int)(short)(counter); + while (timer < -1) + timer += (latch + kExtraTimerCycles); // GH#651: account for underflowed cycles / GH#652: account for extra 2 cycles + counter = (USHORT)timer; + return (timer == -1) ? 1 : 0; // timer1IrqDelay +} + // Called by: // . CpuExecute() every ~1000 cycles @ 1MHz // . MB_SyncEventCallback() on a TIMER1/2 underflow @@ -2222,12 +2233,7 @@ void MB_UpdateCycles(ULONG uExecutedCycles) const bool bTimer1Underflow = CheckTimerUnderflow(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks); if (bTimer1Underflow) - { - int timer = (int) (short) (pMB->sy6522.TIMER1_COUNTER.w); - while (timer < -1) - timer += (pMB->sy6522.TIMER1_LATCH.w + kExtraTimerCycles); // GH#651: account for underflowed cycles / GH#652: account for extra 2 cycles - pMB->sy6522.TIMER1_COUNTER.w = (USHORT)timer; - } + pMB->sy6522.timer1IrqDelay = OnTimer1Underflow(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.TIMER1_LATCH.w); // No TIMER2 latch so "after timing out, the counter will continue to decrement" CheckTimerUnderflow(pMB->sy6522.TIMER2_COUNTER.w, pMB->sy6522.timer2IrqDelay, nClocks);