| 1070 | } |
| 1071 | |
| 1072 | void __stdcall Disk2InterfaceCard::ReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles) |
| 1073 | { |
| 1074 | FloppyDrive* pDrive = &m_floppyDrive[m_currDrive]; |
| 1075 | FloppyDisk* pFloppy = &pDrive->m_disk; |
| 1076 | |
| 1077 | if (!pFloppy->m_trackimagedata && pFloppy->m_imagehandle) |
| 1078 | ReadTrack(m_currDrive, uExecutedCycles); |
| 1079 | |
| 1080 | if (!pFloppy->m_trackimagedata) |
| 1081 | return UpdateLatchForEmptyDrive(pDrive); |
| 1082 | |
| 1083 | // Improve precision of "authentic" drive mode - GH#125 |
| 1084 | UINT uSpinNibbleCount = 0; |
| 1085 | |
| 1086 | if (!m_enhanceDisk && pDrive->m_spinning) |
| 1087 | { |
| 1088 | const ULONG nCycleDiff = (ULONG) (g_nCumulativeCycles - m_diskLastCycle); |
| 1089 | m_diskLastCycle = g_nCumulativeCycles; |
| 1090 | |
| 1091 | if (nCycleDiff > 40) |
| 1092 | { |
| 1093 | // 40 cycles for a write of a 10-bit 0xFF sync byte |
| 1094 | uSpinNibbleCount = nCycleDiff >> 5; // ...but divide by 32 (not 40) |
| 1095 | |
| 1096 | ULONG uWrapOffset = uSpinNibbleCount % pFloppy->m_nibbles; |
| 1097 | pFloppy->m_byte += uWrapOffset; |
| 1098 | if (pFloppy->m_byte >= pFloppy->m_nibbles) |
| 1099 | pFloppy->m_byte -= pFloppy->m_nibbles; |
| 1100 | |
| 1101 | #if LOG_DISK_NIBBLES_SPIN |
| 1102 | UINT uCompleteRevolutions = uSpinNibbleCount / pFloppy->m_nibbles; |
| 1103 | LOG_DISK("spin: revs=%d, nibbles=%d\r\n", uCompleteRevolutions, uWrapOffset); |
| 1104 | #endif |
| 1105 | } |
| 1106 | } |
| 1107 | |
| 1108 | if (!m_seqFunc.writeMode) |
| 1109 | { |
| 1110 | // Don't change latch if drive off after 1 second drive-off delay (UTAIIe page 9-13) |
| 1111 | // "DRIVES OFF forces the data register to hold its present state." (UTAIIe page 9-12) |
| 1112 | // Note: Sherwood Forest sets shift mode and reads with the drive off. |
| 1113 | if (!pDrive->m_spinning) // GH#599 |
| 1114 | return; |
| 1115 | |
| 1116 | const ULONG nReadCycleDiff = (ULONG) (g_nCumulativeCycles - m_diskLastReadLatchCycle); |
| 1117 | |
| 1118 | // Support partial nibble read if disk reads are very close: (GH#582) |
| 1119 | // . 6 cycles (1st->2nd read) for DOS 3.3 / $BD34: "read with delays to see if disk is spinning." (Beneath Apple DOS) |
| 1120 | // . 6 cycles (1st->2nd read) for Curse of the Azure Bonds (loop to see if disk is spinning) |
| 1121 | // . 25 cycles or higher fails for Legacy of the Ancients (GH#733) |
| 1122 | // . 31 cycles is the max for a partial 8-bit nibble |
| 1123 | const ULONG kReadAccessThreshold = 6; // Same for enhanced/authentic modes |
| 1124 | |
| 1125 | if (nReadCycleDiff <= kReadAccessThreshold) |
| 1126 | { |
| 1127 | UINT invalidBits = 8 - (nReadCycleDiff / 4); // 4 cycles per bit-cell |
| 1128 | m_floppyLatch = *(pFloppy->m_trackimage + pFloppy->m_byte) >> invalidBits; |
| 1129 | return; // Early return so don't update: m_diskLastReadLatchCycle & pFloppy->byte |
no test coverage detected