From d1b595f7bd83918be6a75bf672c8fc9a9f94a215 Mon Sep 17 00:00:00 2001 From: TomCh Date: Sat, 16 Nov 2019 23:49:21 +0000 Subject: [PATCH 1/5] Fix for "Mad Effect 1&2" demos (PR #725) . 6502 interrupt delays 1 opcode when interrupt occurs on last cycle of opcode (#724). . Only 1-cycle delay for VF_TEXT & VF_MIXED mode changes (#656). NB. Mad Effect 1 still has a bit of flicker on Space Invader (left edge) --- source/CPU.cpp | 22 +++++++++++++--- source/Mockingboard.cpp | 56 +++++++++++++++++++++++++++++++++++------ source/Mockingboard.h | 2 +- source/Video.cpp | 7 +++--- 4 files changed, 72 insertions(+), 15 deletions(-) diff --git a/source/CPU.cpp b/source/CPU.cpp index d4e7e7d0..61bf5c68 100644 --- a/source/CPU.cpp +++ b/source/CPU.cpp @@ -403,10 +403,23 @@ static __forceinline void NMI(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn, #endif } +static bool g_irqOnLastOpcodeCycle = false; +static bool g_irqDefer1Opcode = false; + static __forceinline void IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn, BOOL& flagv, BOOL& flagz) { if(g_bmIRQ && !(regs.ps & AF_INTERRUPT)) { + // if 6522 interrupt occurs on opcode's last cycle, then defer IRQ by 1 opcode + if (g_irqOnLastOpcodeCycle && !g_irqDefer1Opcode) + { + g_irqOnLastOpcodeCycle = false; + g_irqDefer1Opcode = true; // if INT occurs again on next opcode, then do NOT defer + return; + } + + g_irqDefer1Opcode = false; + // IRQ signals are deasserted when a specific r/w operation is done on device #ifdef _DEBUG g_nCycleIrqStart = g_nCumulativeCycles + uExecutedCycles; @@ -420,6 +433,8 @@ static __forceinline void IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn, UINT uExtraCycles = 0; // Needed for CYC(a) macro CYC(7) } + + g_irqOnLastOpcodeCycle = false; } const int IRQ_CHECK_OPCODE_FULL_SPEED = 40; // ~128 cycles (assume 3 cycles per opcode) @@ -435,7 +450,9 @@ static __forceinline void CheckInterruptSources(ULONG uExecutedCycles, const boo g_fullSpeedOpcodeCount = IRQ_CHECK_OPCODE_FULL_SPEED; } - MB_UpdateCycles(uExecutedCycles); + if (MB_UpdateCycles(uExecutedCycles)) + g_irqOnLastOpcodeCycle = true; + if (sg_Mouse.IsActive()) sg_Mouse.SetVBlank( !VideoGetVblBar(uExecutedCycles) ); } @@ -536,11 +553,10 @@ DWORD CpuExecute(const DWORD uCycles, const bool bVideoUpdate) // >0 : Do multi-opcode emulation const DWORD uExecutedCycles = InternalCpuExecute(uCycles, bVideoUpdate); + // NB. Required for normal-speed (even though 6522 is updated after every opcode), as may've finished on IRQ() 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 - // - const UINT nRemainingCycles = uExecutedCycles - g_nCyclesExecuted; g_nCumulativeCycles += nRemainingCycles; diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index 8c4c6a8c..a8cc13b2 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -129,6 +129,8 @@ struct SY6522_AY8910 SSI263A SpeechChip; MockingboardUnitState_e state; // Where a unit is a 6522+AY8910 pair MockingboardUnitState_e stateB; // Phasor: 6522 & 2nd AY8910 + bool bLoadT1C; + bool bLoadT2C; }; @@ -376,6 +378,8 @@ static void UpdateIFR(SY6522_AY8910* pMB, BYTE clr_ifr, BYTE set_ifr=0) CpuIrqDeassert(IS_6522); } +#define DEFER_T1C_LOAD + static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) { g_bMB_Active = true; @@ -433,7 +437,7 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) UpdateIFR(pMB, IxR_TIMER1); pMB->sy6522.TIMER1_LATCH.h = nValue; - pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w; + pMB->bLoadT1C = true; StartTimer1(pMB); CpuAdjustIrqCheck(pMB->sy6522.TIMER1_LATCH.w); // Sync IRQ check timeout with 6522 counter underflow - GH#608 @@ -529,7 +533,8 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg) nValue = pMB->sy6522.DDRA; break; case 0x04: // TIMER1L_COUNTER - nValue = pMB->sy6522.TIMER1_COUNTER.l; + // NB. GH#701 (T1C:=0xFFFF, LDA T1C_L, A==0xFC) + nValue = (pMB->sy6522.TIMER1_COUNTER.w - 3) & 0xff; // -3 to compensate for the (assumed) 4-cycle STA 6522.T1C_H UpdateIFR(pMB, IxR_TIMER1); break; case 0x05: // TIMER1H_COUNTER @@ -1541,7 +1546,8 @@ void MB_Reset() // CTRL+RESET or power-cycle static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nExecutedCycles) { - MB_UpdateCycles(nExecutedCycles); + if (g_bFullSpeed) + MB_UpdateCycles(nExecutedCycles); #ifdef _DEBUG if(!IS_APPLE2 && MemCheckINTCXROM()) @@ -1604,7 +1610,8 @@ static BYTE __stdcall MB_Read(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULO static BYTE __stdcall MB_Write(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, ULONG nExecutedCycles) { - MB_UpdateCycles(nExecutedCycles); + if (g_bFullSpeed) + MB_UpdateCycles(nExecutedCycles); #ifdef _DEBUG if(!IS_APPLE2 && MemCheckINTCXROM()) @@ -1828,24 +1835,45 @@ static bool CheckTimerUnderflowAndIrq(USHORT& timerCounter, int& timerIrqDelay, // Called by: // . CpuExecute() every ~1000 @ 1MHz // . CheckInterruptSources() every opcode (or every 40 opcodes at full-speed) -// . MB_Read() / MB_Write() -void MB_UpdateCycles(ULONG uExecutedCycles) +// . MB_Read() / MB_Write() (only for full-speed) +bool MB_UpdateCycles(ULONG uExecutedCycles) { if (g_SoundcardType == CT_Empty) - return; + return false; CpuCalcCycles(uExecutedCycles); UINT64 uCycles = g_nCumulativeCycles - g_uLastCumulativeCycles; + if (uCycles == 0) + return false; // Likely when called from CpuExecute() + _ASSERT(uCycles > 1); + + const bool isOpcode = (uCycles > 1 && uCycles <= 7); // todo: better to pass in a flag? + g_uLastCumulativeCycles = g_nCumulativeCycles; _ASSERT(uCycles < 0x10000); USHORT nClocks = (USHORT) uCycles; + bool bIrqOnLastOpcodeCycle = false; + for (int i=0; isy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks, &bTimer1Underflow); + bool bTimer1Irq = false; + bool bTimer1IrqOnLastCycle = false; + + if (isOpcode) + { + bTimer1Irq = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks-1, &bTimer1Underflow); + bTimer1IrqOnLastCycle = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, 1, &bTimer1Underflow); + bTimer1Irq = bTimer1Irq || bTimer1IrqOnLastCycle; + } + else + { + bTimer1Irq = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER1_COUNTER.w, pMB->sy6522.timer1IrqDelay, nClocks, &bTimer1Underflow); + } + const bool bTimer2Irq = CheckTimerUnderflowAndIrq(pMB->sy6522.TIMER2_COUNTER.w, pMB->sy6522.timer2IrqDelay, nClocks); if (!pMB->bTimer1Active && bTimer1Underflow) @@ -1864,6 +1892,7 @@ void MB_UpdateCycles(ULONG uExecutedCycles) if (pMB->bTimer1Active && bTimer1Irq) { UpdateIFR(pMB, 0, IxR_TIMER1); + bIrqOnLastOpcodeCycle = true; MB_Update(); @@ -1880,6 +1909,9 @@ void MB_UpdateCycles(ULONG uExecutedCycles) // - Ultima4/5 change ACCESS_TIMER1 after a couple of IRQs into tune pMB->sy6522.TIMER1_COUNTER.w += pMB->sy6522.TIMER1_LATCH.w; // GH#651: account for underflowed cycles too pMB->sy6522.TIMER1_COUNTER.w += 2; // GH#652: account for extra 2 cycles (Rockwell, Fig.16: period=N+2cycles) + // 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) @@ -1891,6 +1923,12 @@ void MB_UpdateCycles(ULONG uExecutedCycles) } } + if (pMB->bLoadT1C) + { + pMB->bLoadT1C = false; + pMB->sy6522.TIMER1_COUNTER.w = pMB->sy6522.TIMER1_LATCH.w; + } + if (pMB->bTimer2Active && bTimer2Irq) { UpdateIFR(pMB, 0, IxR_TIMER2); @@ -1913,6 +1951,8 @@ void MB_UpdateCycles(ULONG uExecutedCycles) } } } + + return bIrqOnLastOpcodeCycle; } //----------------------------------------------------------------------------- diff --git a/source/Mockingboard.h b/source/Mockingboard.h index 40da37ef..89526938 100644 --- a/source/Mockingboard.h +++ b/source/Mockingboard.h @@ -11,7 +11,7 @@ void MB_Demute(); void MB_StartOfCpuExecute(); void MB_PeriodicUpdate(UINT executedCycles); void MB_CheckIRQ(); -void MB_UpdateCycles(ULONG uExecutedCycles); +bool MB_UpdateCycles(ULONG uExecutedCycles); SS_CARDTYPE MB_GetSoundcardType(); bool MB_IsActive(); DWORD MB_GetVolume(); diff --git a/source/Video.cpp b/source/Video.cpp index 431b7351..806d0558 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -660,9 +660,10 @@ BYTE VideoSetMode(WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles) if (!IS_APPLE2) RGB_SetVideoMode(address); - bool delay = true; - if ((oldVideoMode ^ g_uVideoMode) & VF_PAGE2) - delay = false; // PAGE2 flag changed state, so no 1 cycle delay (GH#656) + // Only 1-cycle delay for VF_TEXT & VF_MIXED mode changes (GH#656) + bool delay = false; + if ((oldVideoMode ^ g_uVideoMode) & (VF_TEXT|VF_MIXED)) + delay = true; NTSC_SetVideoMode( g_uVideoMode, delay ); From b82de931a1f5d976ee00e88f0903f98b284205f6 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sun, 17 Nov 2019 12:26:14 +0000 Subject: [PATCH 2/5] Fixed 6522 timer interrupt which was occurring 1 cycle late (#711) --- source/Mockingboard.cpp | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index a8cc13b2..b911d267 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -378,8 +378,6 @@ static void UpdateIFR(SY6522_AY8910* pMB, BYTE clr_ifr, BYTE set_ifr=0) CpuIrqDeassert(IS_6522); } -#define DEFER_T1C_LOAD - static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue) { g_bMB_Active = true; @@ -1801,6 +1799,9 @@ void MB_PeriodicUpdate(UINT executedCycles) static bool CheckTimerUnderflowAndIrq(USHORT& timerCounter, int& timerIrqDelay, const USHORT nClocks, bool* pTimerUnderflow=NULL) { + if (nClocks == 0) + return false; + int oldTimer = timerCounter; int timer = timerCounter; timer -= nClocks; @@ -1810,23 +1811,20 @@ static bool CheckTimerUnderflowAndIrq(USHORT& timerCounter, int& timerIrqDelay, if (timerIrqDelay) // Deal with any previous counter underflow which didn't yet result in an IRQ { - timerIrqDelay -= nClocks; - if (timerIrqDelay <= 0) - { - timerIrqDelay = 0; - timerIrq = true; - } - // don't re-underflow if TIMER = 0xFFFF or 0xFFFE (so just return) + _ASSERT(timerIrqDelay == 1); + timerIrqDelay = 0; + timerIrq = true; + // don't re-underflow if TIMER = 0x0000 (so just return) } else if (oldTimer >= 0 && timer < 0) // Underflow occurs for 0x0000 -> 0xFFFF { if (pTimerUnderflow) *pTimerUnderflow = true; // Just for Willy Byte! - if (timer < -2) + if (timer <= -2) // TIMER = 0xFFFE (or less) timerIrq = true; - else // TIMER = 0xFFFF or 0xFFFE - timerIrqDelay = 3 + timer; // ...so 2 or 1 cycles until IRQ + else // TIMER = 0xFFFF + timerIrqDelay = 1; // ...so 1 cycle until IRQ } return timerIrq; From 7d38b1ba38da8c9c010f548f0987e122aba22cf9 Mon Sep 17 00:00:00 2001 From: tomcw Date: Mon, 18 Nov 2019 15:08:59 +0000 Subject: [PATCH 3/5] CPU save-state: added 'Defer IRQ By 1 Opcode' (v5) and comments for why the other state doesn't need saving --- source/CPU.cpp | 19 ++++++++++++++----- source/CPU.h | 2 +- source/Mockingboard.cpp | 11 +++++++---- source/NTSC.cpp | 2 +- source/SaveState.cpp | 7 ++++--- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/source/CPU.cpp b/source/CPU.cpp index 61bf5c68..b9e02e4e 100644 --- a/source/CPU.cpp +++ b/source/CPU.cpp @@ -143,6 +143,8 @@ static volatile UINT32 g_bmIRQ = 0; static volatile UINT32 g_bmNMI = 0; static volatile BOOL g_bNmiFlank = FALSE; // Positive going flank on NMI line +static bool g_irqDefer1Opcode = false; + // static eCpuType g_MainCPU = CPU_65C02; @@ -403,8 +405,8 @@ static __forceinline void NMI(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn, #endif } +// NB. No need to save to save-state, as IRQ() follows CheckInterruptSources(), and IRQ() always sets it to false. static bool g_irqOnLastOpcodeCycle = false; -static bool g_irqDefer1Opcode = false; static __forceinline void IRQ(ULONG& uExecutedCycles, BOOL& flagc, BOOL& flagn, BOOL& flagv, BOOL& flagz) { @@ -681,6 +683,8 @@ void CpuReset() regs.bJammed = 0; + g_irqDefer1Opcode = false; + SetActiveCpu( GetMainCpu() ); z80_reset(); } @@ -694,7 +698,8 @@ void CpuReset() #define SS_YAML_KEY_REGP "P" #define SS_YAML_KEY_REGS "S" #define SS_YAML_KEY_REGPC "PC" -#define SS_YAML_KEY_CUMULATIVECYCLES "Cumulative Cycles" +#define SS_YAML_KEY_CUMULATIVE_CYCLES "Cumulative Cycles" +#define SS_YAML_KEY_IRQ_DEFER_1_OPCODE "Defer IRQ By 1 Opcode" #define SS_YAML_VALUE_6502 "6502" #define SS_YAML_VALUE_65C02 "65C02" @@ -717,10 +722,11 @@ void CpuSaveSnapshot(YamlSaveHelper& yamlSaveHelper) yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGP, regs.ps); yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGS, (BYTE) regs.sp); yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_REGPC, regs.pc); - yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_CUMULATIVECYCLES, g_nCumulativeCycles); + yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_CUMULATIVE_CYCLES, g_nCumulativeCycles); + yamlSaveHelper.SaveBool(SS_YAML_KEY_IRQ_DEFER_1_OPCODE, g_irqDefer1Opcode); } -void CpuLoadSnapshot(YamlLoadHelper& yamlLoadHelper) +void CpuLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version) { if (!yamlLoadHelper.GetSubMap(CpuGetSnapshotStructName())) return; @@ -741,7 +747,10 @@ void CpuLoadSnapshot(YamlLoadHelper& yamlLoadHelper) CpuIrqReset(); CpuNmiReset(); - g_nCumulativeCycles = yamlLoadHelper.LoadUint64(SS_YAML_KEY_CUMULATIVECYCLES); + g_nCumulativeCycles = yamlLoadHelper.LoadUint64(SS_YAML_KEY_CUMULATIVE_CYCLES); + + if (version >= 5) + g_irqDefer1Opcode = yamlLoadHelper.LoadBool(SS_YAML_KEY_IRQ_DEFER_1_OPCODE); yamlLoadHelper.PopMap(); } diff --git a/source/CPU.h b/source/CPU.h index 78eb9a64..20d481e4 100644 --- a/source/CPU.h +++ b/source/CPU.h @@ -29,7 +29,7 @@ void CpuNmiAssert(eIRQSRC Device); void CpuNmiDeassert(eIRQSRC Device); void CpuReset (); void CpuSaveSnapshot(class YamlSaveHelper& yamlSaveHelper); -void CpuLoadSnapshot(class YamlLoadHelper& yamlLoadHelper); +void CpuLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version); BYTE CpuRead(USHORT addr, ULONG uExecutedCycles); void CpuWrite(USHORT addr, BYTE a, ULONG uExecutedCycles); diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp index b911d267..3f830ea5 100644 --- a/source/Mockingboard.cpp +++ b/source/Mockingboard.cpp @@ -129,8 +129,10 @@ struct SY6522_AY8910 SSI263A SpeechChip; MockingboardUnitState_e state; // Where a unit is a 6522+AY8910 pair MockingboardUnitState_e stateB; // Phasor: 6522 & 2nd AY8910 - bool bLoadT1C; - bool bLoadT2C; + + // NB. No need to save to save-state, as it will be done immediately after opcode completes in MB_UpdateCycles() + bool bLoadT1C; // Load T1C with T1L after opcode completes + bool bLoadT2C; // Load T2C with T2L after opcode completes }; @@ -1814,9 +1816,10 @@ static bool CheckTimerUnderflowAndIrq(USHORT& timerCounter, int& timerIrqDelay, _ASSERT(timerIrqDelay == 1); timerIrqDelay = 0; timerIrq = true; - // don't re-underflow if TIMER = 0x0000 (so just return) + // if LATCH is very small then could underflow for every opcode... } - else if (oldTimer >= 0 && timer < 0) // Underflow occurs for 0x0000 -> 0xFFFF + + if (oldTimer >= 0 && timer < 0) // Underflow occurs for 0x0000 -> 0xFFFF { if (pTimerUnderflow) *pTimerUnderflow = true; // Just for Willy Byte! diff --git a/source/NTSC.cpp b/source/NTSC.cpp index 38691c63..4c49426d 100644 --- a/source/NTSC.cpp +++ b/source/NTSC.cpp @@ -116,7 +116,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA static int g_nHiresPage = 1; static int g_nTextPage = 1; - static bool g_bDelayVideoMode = false; + static bool g_bDelayVideoMode = false; // NB. No need to save to save-state, as it will be done immediately after opcode completes in NTSC_VideoUpdateCycles() static uint32_t g_uNewVideoModeFlags = 0; // Understanding the Apple II, Timing Generation and the Video Scanner, Pg 3-11 diff --git a/source/SaveState.cpp b/source/SaveState.cpp index 9cf8f9be..17ea43db 100644 --- a/source/SaveState.cpp +++ b/source/SaveState.cpp @@ -68,7 +68,8 @@ static YamlHelper yamlHelper; // v2: Extended: keyboard (added 'Key Waiting'), memory (LC mem type for II/II+, inverted MF_INTCXROM bit) // v3: Extended: memory (added 'AnnunciatorN') // v4: Extended: video (added 'Video Refresh Rate') -#define UNIT_APPLE2_VER 4 +// v5: Extended: cpu (added 'Defer IRQ By 1 Opcode') +#define UNIT_APPLE2_VER 5 #define UNIT_SLOTS_VER 1 @@ -214,7 +215,7 @@ static void ParseUnitApple2(YamlLoadHelper& yamlLoadHelper, UINT version) SetApple2Type( ParseApple2Type(model) ); // NB. Sets default main CPU type m_ConfigNew.m_Apple2Type = GetApple2Type(); - CpuLoadSnapshot(yamlLoadHelper); // NB. Overrides default main CPU type + CpuLoadSnapshot(yamlLoadHelper, version); // NB. Overrides default main CPU type m_ConfigNew.m_CpuType = GetMainCpu(); JoyLoadSnapshot(yamlLoadHelper); @@ -390,7 +391,7 @@ static void Snapshot_LoadState_v2(void) m_ConfigNew.m_bEnableHDD = false; //m_ConfigNew.m_bEnableTheFreezesF8Rom = ?; // todo: when support saving config - MemReset(); + MemReset(); // Also calls CpuInitialize() PravetsReset(); sg_Disk2Card.Reset(); HD_Reset(); From 91f12942206f317eff7e4aebc895722bae7be5c6 Mon Sep 17 00:00:00 2001 From: tomcw Date: Mon, 18 Nov 2019 15:11:55 +0000 Subject: [PATCH 4/5] 1.29.6.0: Updated version and History.txt --- bin/History.txt | 9 ++++++++- resource/version.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/bin/History.txt b/bin/History.txt index 8e9266dc..78d21d90 100644 --- a/bin/History.txt +++ b/bin/History.txt @@ -9,12 +9,18 @@ https://github.com/AppleWin/AppleWin/issues/new Tom Charlesworth -1.29.5.0 - 11 Nov 2019 +1.29.6.0 - 18 Nov 2019 ---------------------- +. [Bug #724] Fixed so that 6502 interrupt is delayed by 1 opcode when interrupt occurs on last cycle of opcode. + - fixes French Touch's "Mad Effect" & "Mad Effect #2" demos. . [Bug #711] Fixed Mockingboard initial "stretched" music playback (regression introduced at 1.28.7.0). . [Bug #707] Fixed ADTPro (running under AppleWin) not working with real COM ports. +. [Bug #701] Fixed 6522's TIMER being out-of-sync with 6502. +. [Bug #699] Fixed French Touch's "Mad Effect". See #656, #701, #724. . [Bug #680] Fixed video tearing (eg. for FT's "Scroll Scroll Scroll" & "Mad Effect #2"). . [Bug #659] Fix for Applied Engineering's Phasor song player (noisy playback) (regression introduced at 1.26.3.4). +. [Bug #656] Changed so only TEXT ($C050/1) and MIXED ($C052/3) have a 1 cycle delay (extension to 1.28.8.0). + - fixes French Touch's "Mad Effect" demo. . [Bug #652] Fixed 6522's TIMER to underflow at 0x0000 -> 0xFFFF - and T1C=0x0000 now correctly underflows on next cycle. . [Bug #435] COM ports above COM9 weren't available from the UI. @@ -23,6 +29,7 @@ Tom Charlesworth . [PR #694] Debugger: Symbol loading: Fix random crash upon start up. . Fixed crash with debug command line switches: -m and -no-mb. +(1.29.5.0 - skipped) 1.29.4.0 - 24 Oct 2019 ---------------------- diff --git a/resource/version.h b/resource/version.h index 8601add5..6a4218b6 100644 --- a/resource/version.h +++ b/resource/version.h @@ -1,4 +1,4 @@ -#define APPLEWIN_VERSION 1,29,5,0 +#define APPLEWIN_VERSION 1,29,6,0 #define xstr(a) str(a) #define str(a) #a From 37db160bd5536091a7ded72f3ed4c6ad0b84668a Mon Sep 17 00:00:00 2001 From: tomcw Date: Mon, 18 Nov 2019 16:45:35 +0000 Subject: [PATCH 5/5] Addition to History.txt --- bin/History.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/bin/History.txt b/bin/History.txt index 78d21d90..f352bc73 100644 --- a/bin/History.txt +++ b/bin/History.txt @@ -21,6 +21,7 @@ Tom Charlesworth . [Bug #659] Fix for Applied Engineering's Phasor song player (noisy playback) (regression introduced at 1.26.3.4). . [Bug #656] Changed so only TEXT ($C050/1) and MIXED ($C052/3) have a 1 cycle delay (extension to 1.28.8.0). - fixes French Touch's "Mad Effect" demo. + - fixed Deater's "Cycle-count Megademo" (vertical GR grey line shouldn't be visible between GR & HGR video). . [Bug #652] Fixed 6522's TIMER to underflow at 0x0000 -> 0xFFFF - and T1C=0x0000 now correctly underflows on next cycle. . [Bug #435] COM ports above COM9 weren't available from the UI.