DiskII: Support partial nibble reads for very close disk latch reads (#586)

Support partial reads for sequential accesses of 6 or less cycles.
- And 31 or less cycles when in "Disk Access Speed" = "Authentic Speed"
Save-state support for partial read cycle (Disk][ unit v3)
Added boot-time logging for Phasor1.dsk (ProDOS 1.1.1)
This commit is contained in:
TomCh 2018-10-02 22:08:54 +01:00 committed by GitHub
parent a2d05ca386
commit 53d1d04988
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 3 deletions

View File

@ -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;

View File

@ -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++)
{