diff --git a/apple/diskii.cpp b/apple/diskii.cpp index 6b665d3..8a53740 100644 --- a/apple/diskii.cpp +++ b/apple/diskii.cpp @@ -26,6 +26,7 @@ DiskII::DiskII(AppleMMU *mmu) curTrack = 0; trackDirty = false; trackToRead = -1; + trackToFlush = -1; writeMode = false; writeProt = false; // FIXME: expose an interface to this @@ -56,6 +57,15 @@ void DiskII::Reset() ejectDisk(1); } +void DiskII::checkFlush(int8_t track) +{ + if (trackDirty && trackToFlush == -1) { + diskToFlush = selectedDisk; + trackToFlush = track; + trackDirty = false; // just so we don't overwrite disk/track to flush before continuing... + } +} + uint8_t DiskII::readSwitches(uint8_t s) { switch (s) { @@ -73,7 +83,7 @@ uint8_t DiskII::readSwitches(uint8_t s) case 0x08: // drive off indicatorIsOn[selectedDisk] = 99; g_display->setDriveIndicator(selectedDisk, false); // FIXME: after a spell... - flushTrack(); + checkFlush(curTrack); break; case 0x09: // drive on indicatorIsOn[selectedDisk] = 100; @@ -104,11 +114,11 @@ uint8_t DiskII::readSwitches(uint8_t s) case 0x0E: // set read mode setWriteMode(false); - + // FIXME: with this shortcut here, disk access speeds up ridiculously. // Is this breaking anything? return ( (readOrWriteByte() & 0x7F) | - (isWriteProtected() ? 0x80 : 0x00) ); + (isWriteProtected() ? 0x80 : 0x00) ); break; case 0x0F: // set write mode @@ -226,13 +236,12 @@ void DiskII::step(uint8_t phase) curTrack = (trackPos + 1) / 2; if (curTrack != prevTrack) { // We're about to change tracks - be sure to flush the track if we've written to it - if (trackDirty) { - flushTrack(); - } + checkFlush(prevTrack); + // step to the appropriate track - trackDirty = false; prevTrack = curTrack; - trackBuffer->clear(); + // mark it to be read + trackToRead = curTrack; } } @@ -308,8 +317,7 @@ void DiskII::select(int8_t which) indicatorIsOn[selectedDisk] = 0; g_display->setDriveIndicator(selectedDisk, false); - flushTrack(); // in case it's dirty: flush before changing drives - trackBuffer->clear(); + checkFlush(curTrack); } // set the selected disk drive @@ -319,7 +327,6 @@ void DiskII::select(int8_t which) uint8_t DiskII::readOrWriteByte() { if (disk[selectedDisk] == -1) { - // printf("NO DISK\n"); return GAP; } @@ -371,10 +378,15 @@ uint8_t DiskII::readOrWriteByte() // // Don't fill it right here, b/c we don't want to bog down the CPU // thread/ISR. + if (trackToRead == curTrack) {// waiting for a read to complete + return GAP; + } + if ((trackToRead != -1) || !trackBuffer->hasData()) { + checkFlush(curTrack); + // Need to read in a track of data and nibblize it. We'll return 0xFF // until that completes. - trackDirty = false; // effectively flush; forget that we had any data :) // This might update trackToRead with a different track than the // one we're reading. When we finish the read, we'll need to check @@ -392,10 +404,20 @@ uint8_t DiskII::readOrWriteByte() void DiskII::fillDiskBuffer() { + if (trackToFlush != -1) { + flushTrack(trackToFlush, diskToFlush); // in case it's dirty: flush before changing drives + trackBuffer->clear(); + + trackToFlush = -1; + } + // No work to do if trackToRead is -1 if (trackToRead == -1) return; + trackDirty = false; + trackBuffer->clear(); + int8_t trackWeAreReading = trackToRead; int8_t diskWeAreUsing = selectedDisk; @@ -462,12 +484,8 @@ void DiskII::loadROM(uint8_t *toWhere) #endif } -void DiskII::flushTrack() +void DiskII::flushTrack(int8_t track, int8_t sel) { - if (!trackDirty) { - return; - } - // safety check: if we're write-protected, then how did we get here? if (writeProt) { g_display->debugMsg("Write Protected"); @@ -479,14 +497,14 @@ void DiskII::flushTrack() return; } - if (diskType[selectedDisk] == nibDisk) { + if (diskType[sel] == nibDisk) { // Write the whole track out exactly as we've got it. Hopefully // someone has re-calcuated appropriate checksums on it... g_display->debugMsg("Not writing Nib image"); return; } - nibErr e = denibblizeTrack(trackBuffer, rawTrackBuffer, diskType[selectedDisk], curTrack); + nibErr e = denibblizeTrack(trackBuffer, rawTrackBuffer, diskType[sel], curTrack); switch (e) { case errorShortTrack: g_display->debugMsg("DII: short track"); @@ -503,9 +521,7 @@ void DiskII::flushTrack() } // ok, write the track! - g_filemanager->seekBlock(disk[selectedDisk], curTrack * 16); - g_filemanager->writeTrack(disk[selectedDisk], rawTrackBuffer); - - trackDirty = false; + g_filemanager->seekBlock(disk[sel], track * 16); + g_filemanager->writeTrack(disk[sel], rawTrackBuffer); } diff --git a/apple/diskii.h b/apple/diskii.h index b931bcd..faaae31 100644 --- a/apple/diskii.h +++ b/apple/diskii.h @@ -29,7 +29,7 @@ class DiskII : public Slot { void ejectDisk(int8_t driveNum); const char *DiskName(int8_t num); - void flushTrack(); + void flushTrack(int8_t track, int8_t sel); void fillDiskBuffer(); // called from main loop @@ -41,13 +41,15 @@ class DiskII : public Slot { void select(int8_t which); // 0 or 1 for drives 1 and 2, respectively uint8_t readOrWriteByte(); + void checkFlush(int8_t track); + #ifndef TEENSYDUINO void convertDskToNib(const char *outFN); #endif private: - uint8_t curTrack; - bool trackDirty; // does this track need flushing to disk? + volatile uint8_t curTrack; + volatile bool trackDirty; // does this track need flushing to disk? uint8_t readWriteLatch; RingBuffer *trackBuffer; // nibblized data uint8_t *rawTrackBuffer; // not nibblized data @@ -60,8 +62,10 @@ class DiskII : public Slot { volatile uint8_t indicatorIsOn[2]; uint8_t diskType[2]; - volatile int8_t selectedDisk; volatile int8_t trackToRead; // -1 when we're idle; not -1 when we need to read a track. + volatile int8_t selectedDisk; + volatile int8_t trackToFlush; // -1 when there's none + volatile int8_t diskToFlush; // which selected disk are we writing to? }; #endif