diff --git a/source/Applewin.cpp b/source/Applewin.cpp index 5fa5dce3..6ec6a619 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -129,13 +129,16 @@ void LogFileTimeUntilFirstKeyReadReset(void) } // Log the time from emulation restart/reboot until the first key read: BIT $C000 -// . NB. AZTEC.DSK does prior LDY $C000 reads, but the BIT $C000 is at the "Press any key" message +// . AZTEC.DSK (DOS 3.3) does prior LDY $C000 reads, but the BIT $C000 is at the "Press any key" message +// . Phasor1.dsk / ProDOS 1.1.1: PC=E797: B1 50: LDA ($50),Y / "Select an Option:" message void LogFileTimeUntilFirstKeyRead(void) { if (!g_fh || bLogKeyReadDone) return; - if (mem[regs.pc-3] != 0x2C) // bit $c000 + if ( (mem[regs.pc-3] != 0x2C) // AZTEC: bit $c000 + && !((regs.pc-2) == 0xE797 && mem[regs.pc-2] == 0xB1 && mem[regs.pc-1] == 0x50) // Phasor1: lda ($50),y + ) return; DWORD dwTime = GetTickCount() - dwLogKeyReadTickStart; diff --git a/source/Disk.cpp b/source/Disk.cpp index f81002a9..d3998ae7 100644 --- a/source/Disk.cpp +++ b/source/Disk.cpp @@ -86,6 +86,7 @@ static WORD phases = 0; // state bits for stepper magnet phases 0 - 3 static bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry static UINT g_uSlot = 0; static unsigned __int64 g_uDiskLastCycle = 0; +static unsigned __int64 g_uDiskLastReadLatchCycle = 0; static FormatTrack g_formatTrack; static bool IsDriveValid( const int iDrive ); @@ -895,7 +896,23 @@ static void __stdcall DiskReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULO // but Sherwood Forest sets shift mode and reads with the drive off, so don't check for now if (!floppywritemode) { + const ULONG nReadCycleDiff = (ULONG) (g_nCumulativeCycles - g_uDiskLastReadLatchCycle); + + // Support partial nibble read if disk reads are very close: (GH#582) + // . 6 cycles (1st->2nd read) for DOS 3.3 / $BD34: "read with delays to see if disk is spinning." (Beneath Apple DOS) + // . 6 cycles (1st->2nd read) for Curse of the Azure Bonds (loop to see if disk is spinning) + // . 31 cycles is the max for a partial 8-bit nibble + const ULONG kReadAccessThreshold = enhancedisk ? 6 : 31; + + if (nReadCycleDiff <= kReadAccessThreshold) + { + UINT invalidBits = 8 - (nReadCycleDiff / 4); // 4 cycles per bit-cell + floppylatch = *(pFloppy->trackimage + pFloppy->byte) >> invalidBits; + return; // Early return so don't update: g_uDiskLastReadLatchCycle & pFloppy->byte + } + floppylatch = *(pFloppy->trackimage + pFloppy->byte); + g_uDiskLastReadLatchCycle = g_nCumulativeCycles; #if LOG_DISK_NIBBLES_READ #if LOG_DISK_NIBBLES_USE_RUNTIME_VAR @@ -959,6 +976,10 @@ void DiskReset(const bool bIsPowerCycle/*=false*/) if (bIsPowerCycle) // GH#460 { + // NB. This doesn't affect the drive head (ie. drive's track position) + // . The initial machine start-up state is track=0, but after a power-cycle the track could be any value. + // . (For DiskII firmware, this results in a subtle extra latch read in this latter case, for the track!=0 case) + g_aFloppyDrive[DRIVE_1].spinning = 0; g_aFloppyDrive[DRIVE_1].writelight = 0; g_aFloppyDrive[DRIVE_2].spinning = 0; @@ -1363,7 +1384,8 @@ int DiskSetSnapshot_v1(const SS_CARD_DISK2* const pSS) // Unit version history: // 2: Added: Format Track state & DiskLastCycle -static const UINT kUNIT_VERSION = 2; +// 3: Added: DiskLastReadLatchCycle +static const UINT kUNIT_VERSION = 3; #define SS_YAML_VALUE_CARD_DISK2 "Disk][" @@ -1375,6 +1397,7 @@ static const UINT kUNIT_VERSION = 2; #define SS_YAML_KEY_FLOPPY_MOTOR_ON "Floppy Motor On" #define SS_YAML_KEY_FLOPPY_WRITE_MODE "Floppy Write Mode" #define SS_YAML_KEY_LAST_CYCLE "Last Cycle" +#define SS_YAML_KEY_LAST_READ_LATCH_CYCLE "Last Read Latch Cycle" #define SS_YAML_KEY_DISK2UNIT "Unit" #define SS_YAML_KEY_FILENAME "Filename" @@ -1429,6 +1452,7 @@ void DiskSaveSnapshot(class YamlSaveHelper& yamlSaveHelper) yamlSaveHelper.SaveBool(SS_YAML_KEY_FLOPPY_MOTOR_ON, floppymotoron == TRUE); yamlSaveHelper.SaveBool(SS_YAML_KEY_FLOPPY_WRITE_MODE, floppywritemode == TRUE); yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_LAST_CYCLE, g_uDiskLastCycle); // v2 + yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_LAST_READ_LATCH_CYCLE, g_uDiskLastReadLatchCycle); // v3 g_formatTrack.SaveSnapshot(yamlSaveHelper); // v2 DiskSaveSnapshotDisk2Unit(yamlSaveHelper, DRIVE_1); @@ -1534,6 +1558,11 @@ bool DiskLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT vers g_formatTrack.LoadSnapshot(yamlLoadHelper); } + if (version >= 3) + { + g_uDiskLastReadLatchCycle = yamlLoadHelper.LoadUint64(SS_YAML_KEY_LAST_READ_LATCH_CYCLE); + } + // Eject all disks first in case Drive-2 contains disk to be inserted into Drive-1 for(UINT i=0; i<NUM_DRIVES; i++) {