void Disk2InterfaceCard::WriteTrack(const int drive) { FloppyDrive* pDrive = &m_floppyDrive[ drive ]; FloppyDisk* pFloppy = &pDrive->m_disk; if (pDrive->m_track >= ImageGetNumTracks(pFloppy->m_imagehandle)) return; if (pFloppy->m_bWriteProtected) return; if (pFloppy->m_trackimage && pFloppy->m_imagehandle) { #if LOG_DISK_TRACKS LOG_DISK("track $%02X%s write\r\n", pDrive->m_track, (pDrive->m_phase & 0) ? ".5" : " "); // TODO: hard-coded to whole tracks - see below (nickw) #endif ImageWriteTrack( pFloppy->m_imagehandle, pDrive->m_track, pDrive->m_phase, // TODO: this should never be used; it's the current phase (half-track), not that of the track to be written (nickw) pFloppy->m_trackimage, pFloppy->m_nibbles); } pFloppy->m_trackimagedirty = false; }
static void ReadTrack(const int iDrive) { if (! IsDriveValid( iDrive )) return; Disk_t *pFloppy = &g_aFloppyDisk[ iDrive ]; if (pFloppy->track >= ImageGetNumTracks(pFloppy->imagehandle)) { pFloppy->trackimagedata = 0; return; } if (! pFloppy->trackimage) AllocTrack( iDrive ); if (pFloppy->trackimage && pFloppy->imagehandle) { LOG_DISK("read track %2X%s\r", pFloppy->track, (pFloppy->phase & 1) ? ".5" : ""); ImageReadTrack( pFloppy->imagehandle, pFloppy->track, pFloppy->phase, pFloppy->trackimage, &pFloppy->nibbles); pFloppy->byte = 0; pFloppy->trackimagedata = (pFloppy->nibbles != 0); } }
void Disk2InterfaceCard::ReadTrack(const int drive) { if (! IsDriveValid( drive )) return; FloppyDrive* pDrive = &m_floppyDrive[ drive ]; FloppyDisk* pFloppy = &pDrive->m_disk; if (pDrive->m_track >= ImageGetNumTracks(pFloppy->m_imagehandle)) { pFloppy->m_trackimagedata = false; return; } if (!pFloppy->m_trackimage) AllocTrack( drive ); if (pFloppy->m_trackimage && pFloppy->m_imagehandle) { #if LOG_DISK_TRACKS LOG_DISK("track $%02X%s read\r\n", pDrive->m_track, (pDrive->m_phase & 1) ? ".5" : " "); #endif ImageReadTrack( pFloppy->m_imagehandle, pDrive->m_track, pDrive->m_phase, pFloppy->m_trackimage, &pFloppy->m_nibbles, m_enhanceDisk); pFloppy->m_byte = 0; pFloppy->m_trackimagedata = (pFloppy->m_nibbles != 0); } }
void __stdcall Disk2InterfaceCard::Enable(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles) { m_currDrive = address & 1; #if LOG_DISK_ENABLE_DRIVE LOG_DISK("enable drive: %d\r\n", m_currDrive); #endif m_floppyDrive[!m_currDrive].m_spinning = 0; m_floppyDrive[!m_currDrive].m_writelight = 0; CheckSpinning(uExecutedCycles); }
void __stdcall Disk2InterfaceCard::ControlMotor(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles) { BOOL newState = address & 1; if (newState != m_floppyMotorOn) // motor changed state m_formatTrack.DriveNotWritingTrack(); m_floppyMotorOn = newState; // NB. Motor off doesn't reset the Command Decoder like reset. (UTAIIe figures 9.7 & 9.8 chip C2) // - so it doesn't reset this state: m_floppyLoadMode, m_floppyWriteMode, m_phases #if LOG_DISK_MOTOR LOG_DISK("motor %s\r\n", (m_floppyMotorOn) ? "on" : "off"); #endif CheckSpinning(uExecutedCycles); }
void __stdcall Disk2InterfaceCard::ReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) { /* m_floppyLoadMode = 0; */ FloppyDrive* pDrive = &m_floppyDrive[m_currDrive]; FloppyDisk* pFloppy = &pDrive->m_disk; if (!pFloppy->m_trackimagedata && pFloppy->m_imagehandle) ReadTrack(m_currDrive); if (!pFloppy->m_trackimagedata) { m_floppyLatch = 0xFF; return; } // Improve precision of "authentic" drive mode - GH#125 UINT uSpinNibbleCount = 0; CpuCalcCycles(nExecutedCycles); // g_nCumulativeCycles required for uSpinNibbleCount & LogWriteCheckSyncFF() if (!m_enhanceDisk && pDrive->m_spinning) { const ULONG nCycleDiff = (ULONG) (g_nCumulativeCycles - m_diskLastCycle); m_diskLastCycle = g_nCumulativeCycles; if (nCycleDiff > 40) { // 40 cycles for a write of a 10-bit 0xFF sync byte uSpinNibbleCount = nCycleDiff >> 5; // ...but divide by 32 (not 40) ULONG uWrapOffset = uSpinNibbleCount % pFloppy->m_nibbles; pFloppy->m_byte += uWrapOffset; if (pFloppy->m_byte >= pFloppy->m_nibbles) pFloppy->m_byte -= pFloppy->m_nibbles; #if LOG_DISK_NIBBLES_SPIN UINT uCompleteRevolutions = uSpinNibbleCount / pFloppy->m_nibbles; LOG_DISK("spin: revs=%d, nibbles=%d\r\n", uCompleteRevolutions, uWrapOffset); #endif } }
static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG) { Disk_t * fptr = &g_aFloppyDisk[currdrive]; #if 1 int phase = (address >> 1) & 3; int phase_bit = (1 << phase); // update the magnet states if (address & 1) { // phase on phases |= phase_bit; LOG_DISK("track %02X phases %X phase %d on address $C0E%X\r", fptr->phase, phases, phase, address & 0xF); } else { // phase off phases &= ~phase_bit; LOG_DISK("track %02X phases %X phase %d off address $C0E%X\r", fptr->phase, phases, phase, address & 0xF); } // check for any stepping effect from a magnet // - move only when the magnet opposite the cog is off // - move in the direction of an adjacent magnet if one is on // - do not move if both adjacent magnets are on // momentum and timing are not accounted for ... maybe one day! int direction = 0; if (phases & (1 << ((fptr->phase + 1) & 3))) direction += 1; if (phases & (1 << ((fptr->phase + 3) & 3))) direction -= 1; // apply magnet step, if any if (direction) { fptr->phase = MAX(0, MIN(79, fptr->phase + direction)); const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle); const int newtrack = (nNumTracksInImage == 0) ? 0 : MIN(nNumTracksInImage-1, fptr->phase >> 1); // (round half tracks down) LOG_DISK("newtrack %2X%s\r", newtrack, (fptr->phase & 1) ? ".5" : ""); if (newtrack != fptr->track) { if (fptr->trackimage && fptr->trackimagedirty) { WriteTrack(currdrive); } fptr->track = newtrack; fptr->trackimagedata = 0; } // Feature Request #201 Show track status // https://github.com/AppleWin/AppleWin/issues/201 FrameDrawDiskStatus( (HDC)0 ); } #else // Old 1.13.1 code for Chessmaster 2000 to work! (see bug#18109) const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle); if (address & 1) { int phase = (address >> 1) & 3; int direction = 0; if (phase == ((fptr->phase+1) & 3)) direction = 1; if (phase == ((fptr->phase+3) & 3)) direction = -1; if (direction) { fptr->phase = MAX(0,MIN(79,fptr->phase+direction)); if (!(fptr->phase & 1)) { int newtrack = MIN(nNumTracksInImage-1,fptr->phase >> 1); if (newtrack != fptr->track) { if (fptr->trackimage && fptr->trackimagedirty) WriteTrack(currdrive); fptr->track = newtrack; fptr->trackimagedata = 0; } } }
void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles) { FloppyDrive* pDrive = &m_floppyDrive[m_currDrive]; FloppyDisk* pFloppy = &pDrive->m_disk; if (!m_floppyMotorOn) // GH#525 { if (!pDrive->m_spinning) { #if LOG_DISK_PHASES LOG_DISK("stepper accessed whilst motor is off and not spinning\r\n"); #endif return; } #if LOG_DISK_PHASES LOG_DISK("stepper accessed whilst motor is off, but still spinning\r\n"); #endif } int phase = (address >> 1) & 3; int phase_bit = (1 << phase); #if 1 // update the magnet states if (address & 1) { // phase on m_phases |= phase_bit; } else { // phase off m_phases &= ~phase_bit; } // check for any stepping effect from a magnet // - move only when the magnet opposite the cog is off // - move in the direction of an adjacent magnet if one is on // - do not move if both adjacent magnets are on // momentum and timing are not accounted for ... maybe one day! int direction = 0; if (m_phases & (1 << ((pDrive->m_phase + 1) & 3))) direction += 1; if (m_phases & (1 << ((pDrive->m_phase + 3) & 3))) direction -= 1; // apply magnet step, if any if (direction) { pDrive->m_phase = MAX(0, MIN(79, pDrive->m_phase + direction)); const int nNumTracksInImage = ImageGetNumTracks(pFloppy->m_imagehandle); const int newtrack = (nNumTracksInImage == 0) ? 0 : MIN(nNumTracksInImage-1, pDrive->m_phase >> 1); // (round half tracks down) if (newtrack != pDrive->m_track) { FlushCurrentTrack(m_currDrive); pDrive->m_track = newtrack; pFloppy->m_trackimagedata = false; m_formatTrack.DriveNotWritingTrack(); } // Feature Request #201 Show track status // https://github.com/AppleWin/AppleWin/issues/201 FrameDrawDiskStatus( (HDC)0 ); } #else // substitute alternate stepping code here to test #endif #if LOG_DISK_PHASES LOG_DISK("track $%02X%s phases %d%d%d%d phase %d %s address $%4X\r\n", pDrive->m_phase >> 1, (pDrive->m_phase & 1) ? ".5" : " ", (m_phases >> 3) & 1, (m_phases >> 2) & 1, (m_phases >> 1) & 1, (m_phases >> 0) & 1, phase, (address & 1) ? "on " : "off", address); #endif }