From 93ea5b3e60e840a396bdead6e98ccd190a4f4020 Mon Sep 17 00:00:00 2001 From: tomcw Date: Sat, 23 Apr 2022 18:13:15 +0100 Subject: [PATCH] WOZ: Improve reading write-protect (#1078) and remove 'm_resetSequencer' var --- source/Disk.cpp | 71 ++++++++++++++++++++++++++----------------------- source/Disk.h | 3 +-- 2 files changed, 38 insertions(+), 36 deletions(-) diff --git a/source/Disk.cpp b/source/Disk.cpp index 4319e89a..5ac09cba 100644 --- a/source/Disk.cpp +++ b/source/Disk.cpp @@ -1028,7 +1028,6 @@ void Disk2InterfaceCard::ResetLogicStateSequencer(void) { m_shiftReg = 0; m_latchDelay = 0; - m_resetSequencer = true; m_writeStarted = false; m_dbgLatchDelayedCnt = 0; @@ -1080,8 +1079,6 @@ void Disk2InterfaceCard::UpdateBitStreamPosition(FloppyDisk& floppy, const ULONG floppy.m_bitOffset %= floppy.m_bitCount; UpdateBitStreamOffsets(floppy); - - m_resetSequencer = false; } void Disk2InterfaceCard::UpdateBitStreamOffsets(FloppyDisk& floppy) @@ -1253,14 +1250,6 @@ void Disk2InterfaceCard::DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemain IncBitStream(floppy); - if (m_resetSequencer) - { - m_resetSequencer = false; // LSS takes some cycles to reset (ref?) - continue; - } - - // - m_shiftReg <<= 1; m_shiftReg |= outputBit; @@ -1580,10 +1569,6 @@ bool Disk2InterfaceCard::UserSelectNewDiskImage(const int drive, LPCSTR pszFilen void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG uExecutedCycles) { - // NB. Only reads in LOAD mode can issue the SR (shift write-protect) operation - UTAIIe page 9-20, fig 9.11 - // But STA $C08D,X (no PX) does a read from $C08D+X, followed by the write to $C08D+X - // So just want to ignore: STA $C0ED or eg. STA $BFFF,X (PX, X=$EE) - // Don't change latch if drive off after 1 second drive-off delay (UTAIIe page 9-13) // "DRIVES OFF forces the data register to hold its present state." (UTAIIe page 9-12) // Note: Gemstone Warrior sets load mode with the drive off. @@ -1591,6 +1576,7 @@ void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE return; // Notes: + // . Only READ-LOAD mode ($C08E,X & $C08D,X) can issue the SR (shift write-protect) operation - UTAIIe page 9-20, fig 9.11 // . Phase 1 on also forces write protect in the Disk II drive (UTAIIe page 9-7) but we don't implement that. // . write mode doesn't prevent reading write protect (GH#537): // "If for some reason the above write protect check were entered with the READ/WRITE switch in WRITE, @@ -1616,11 +1602,7 @@ void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE const UINT bitCellDelta = GetBitCellDelta(uExecutedCycles); UpdateBitStreamPosition(floppy, bitCellDelta); // Fix E7-copy protection - // UpdateBitStreamPosition() must be done before ResetLSS, as the former clears m_resetSequencer (and the latter sets it). - // . Commando.woz is sensitive to this. EG. It can crash after pressing 'J' (1 failure in 20 reboot repeats) - ResetLogicStateSequencer(); // reset sequencer (UTAIIe page 9-21) - - m_shiftReg = m_floppyLatch; + ResetLogicStateSequencer(); // "Set the sequencer to State 0" (UTAIIe page 9-21) } } @@ -1791,21 +1773,35 @@ void Disk2InterfaceCard::InitializeIO(LPBYTE pCxRomPeripheral) //=========================================================================== -void Disk2InterfaceCard::SetSequencerFunction(WORD addr) +void Disk2InterfaceCard::SetSequencerFunction(WORD addr, ULONG executedCycles) { if ((addr & 0xf) < 0xc) return; + const SEQFUNC oldSeqFunc = m_seqFunc.function; + switch ((addr & 3) ^ 2) { - case 0: m_seqFunc.writeMode = 0; break; // $C08E,X (sequence addr A2 input) - case 1: m_seqFunc.writeMode = 1; break; // $C08F,X (sequence addr A2 input) - case 2: m_seqFunc.loadMode = 0; break; // $C08C,X (sequence addr A3 input) - case 3: m_seqFunc.loadMode = 1; break; // $C08D,X (sequence addr A3 input) + case 0: m_seqFunc.writeMode = 0; break; // $C08E,X (sequence addr A3 input) + case 1: m_seqFunc.writeMode = 1; break; // $C08F,X (sequence addr A3 input) + case 2: m_seqFunc.loadMode = 0; break; // $C08C,X (sequence addr A2 input) + case 3: m_seqFunc.loadMode = 1; break; // $C08D,X (sequence addr A2 input) } if (!m_seqFunc.writeMode) m_writeStarted = false; + + if (oldSeqFunc == checkWriteProtAndInitWrite && m_seqFunc.function != checkWriteProtAndInitWrite) + { + // Use up remaining cycles before switching out of "checkWriteProtAndInitWrite" mode + // Done when checking write-protect, but also for bit-slip (eg. E7) copy-protections + FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk; + if (ImageIsWOZ(floppy.m_imagehandle)) + { + const UINT bitCellDelta = GetBitCellDelta(executedCycles); + UpdateBitStreamPosition(floppy, bitCellDelta); + } + } } BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) @@ -1821,7 +1817,7 @@ BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE if (isWOZ && pCard->m_seqFunc.function == dataShiftWrite) // Occurs at end of sector write ($C0EE) pCard->DataShiftWriteWOZ(pc, addr, nExecutedCycles); // Finish any previous write - pCard->SetSequencerFunction(addr); + pCard->SetSequencerFunction(addr, nExecutedCycles); switch (addr & 0xF) { @@ -1868,7 +1864,7 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE if (isWOZ && pCard->m_seqFunc.function == dataShiftWrite) pCard->DataShiftWriteWOZ(pc, addr, nExecutedCycles); // Finish any previous write - pCard->SetSequencerFunction(addr); + pCard->SetSequencerFunction(addr, nExecutedCycles); switch (addr & 0xF) { @@ -1911,13 +1907,14 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE // Split up 'Unit' putting some state into a new 'Floppy' // 5: Added: Sequencer Function // 6: Added: Drive Connected & Motor On Cycle -static const UINT kUNIT_VERSION = 6; +// 7: Deprecated SS_YAML_KEY_LSS_RESET_SEQUENCER, SS_YAML_KEY_DISK_ACCESSED +static const UINT kUNIT_VERSION = 7; #define SS_YAML_VALUE_CARD_DISK2 "Disk][" #define SS_YAML_KEY_PHASES "Phases" #define SS_YAML_KEY_CURRENT_DRIVE "Current Drive" -#define SS_YAML_KEY_DISK_ACCESSED "Disk Accessed" +#define SS_YAML_KEY_DISK_ACCESSED "Disk Accessed" // deprecated at v7 #define SS_YAML_KEY_ENHANCE_DISK "Enhance Disk" #define SS_YAML_KEY_FLOPPY_LATCH "Floppy Latch" #define SS_YAML_KEY_FLOPPY_MOTOR_ON "Floppy Motor On" @@ -1926,7 +1923,7 @@ static const UINT kUNIT_VERSION = 6; #define SS_YAML_KEY_LAST_READ_LATCH_CYCLE "Last Read Latch Cycle" #define SS_YAML_KEY_LSS_SHIFT_REG "LSS Shift Reg" #define SS_YAML_KEY_LSS_LATCH_DELAY "LSS Latch Delay" -#define SS_YAML_KEY_LSS_RESET_SEQUENCER "LSS Reset Sequencer" +#define SS_YAML_KEY_LSS_RESET_SEQUENCER "LSS Reset Sequencer" // deprecated at v7 #define SS_YAML_KEY_LSS_SEQUENCER_FUNCTION "LSS Sequencer Function" #define SS_YAML_KEY_DISK2UNIT "Unit" @@ -2000,7 +1997,6 @@ void Disk2InterfaceCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper) YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); yamlSaveHelper.SaveUint(SS_YAML_KEY_CURRENT_DRIVE, m_currDrive); yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_PHASES, m_magnetStates); - yamlSaveHelper.SaveBool(SS_YAML_KEY_DISK_ACCESSED, false); // deprecated yamlSaveHelper.SaveBool(SS_YAML_KEY_ENHANCE_DISK, m_enhanceDisk); yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_FLOPPY_LATCH, m_floppyLatch); yamlSaveHelper.SaveBool(SS_YAML_KEY_FLOPPY_MOTOR_ON, m_floppyMotorOn == TRUE); @@ -2008,7 +2004,6 @@ void Disk2InterfaceCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper) yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_LAST_READ_LATCH_CYCLE, m_diskLastReadLatchCycle); // v3 yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_LSS_SHIFT_REG, m_shiftReg); // v4 yamlSaveHelper.SaveInt(SS_YAML_KEY_LSS_LATCH_DELAY, m_latchDelay); // v4 - yamlSaveHelper.SaveBool(SS_YAML_KEY_LSS_RESET_SEQUENCER, m_resetSequencer); // v4 yamlSaveHelper.SaveInt(SS_YAML_KEY_LSS_SEQUENCER_FUNCTION, m_seqFunc.function); // v5 m_formatTrack.SaveSnapshot(yamlSaveHelper); // v2 @@ -2166,7 +2161,6 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi m_currDrive = yamlLoadHelper.LoadUint(SS_YAML_KEY_CURRENT_DRIVE); m_magnetStates = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASES); - (void) yamlLoadHelper.LoadBool(SS_YAML_KEY_DISK_ACCESSED); // deprecated - but retrieve the value to avoid the "State: Unknown key (Disk Accessed)" warning m_enhanceDisk = yamlLoadHelper.LoadBool(SS_YAML_KEY_ENHANCE_DISK); m_floppyLatch = yamlLoadHelper.LoadUint(SS_YAML_KEY_FLOPPY_LATCH); m_floppyMotorOn = yamlLoadHelper.LoadBool(SS_YAML_KEY_FLOPPY_MOTOR_ON); @@ -2186,7 +2180,11 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi { m_shiftReg = yamlLoadHelper.LoadUint(SS_YAML_KEY_LSS_SHIFT_REG) & 0xff; m_latchDelay = yamlLoadHelper.LoadInt(SS_YAML_KEY_LSS_LATCH_DELAY); - m_resetSequencer = yamlLoadHelper.LoadBool(SS_YAML_KEY_LSS_RESET_SEQUENCER); + } + + if (version >= 4 && version <= 6) + { + (void) yamlLoadHelper.LoadBool(SS_YAML_KEY_LSS_RESET_SEQUENCER); // deprecated } if (version >= 5) @@ -2199,6 +2197,11 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi m_seqFunc.loadMode = 0; // Wasn't saved until v5 } + if (version <= 6) + { + (void) yamlLoadHelper.LoadBool(SS_YAML_KEY_DISK_ACCESSED); // deprecated - but retrieve the value to avoid the "State: Unknown key (Disk Accessed)" warning + } + // Eject all disks first in case Drive-2 contains disk to be inserted into Drive-1 for (UINT i=0; i