diff --git a/src/DiskImage.cpp b/src/DiskImage.cpp index cf3fb8d..272c185 100644 --- a/src/DiskImage.cpp +++ b/src/DiskImage.cpp @@ -42,7 +42,7 @@ extern u32 HashBuffer(const void* pBuffer, u32 length); #define DIRECTRY_ENTRY_FILE_TYPE_PRG 0x82 -static u8 blankD64DIRBAM[] = +static const u8 blankD64DIRBAM[] = { 0x12, 0x01, 0x41, 0x00, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, 0x15, 0xff, 0xff, 0x1f, @@ -76,6 +76,11 @@ static const unsigned MAX_D64_SIZE = 0x32200 + 768; static const unsigned MAX_D71_SIZE = 0x55600 + 1366; static const unsigned MAX_D81_SIZE = 822400; +static const unsigned short GCR_SYNC_LENGTH = 5; +static const unsigned short GCR_HEADER_LENGTH = 10; +static const unsigned short GCR_HEADER_GAP_LENGTH = 9; +static const unsigned short GCR_SECTOR_DATA_LENGTH = 325; + // CRC-16-CCITT // CRC(x) = x^16 + x^12 + x^5 + x^0 unsigned short DiskImage::CRC1021[256] = @@ -98,6 +103,11 @@ unsigned short DiskImage::CRC1021[256] = 0xef1f,0xff3e,0xcf5d,0xdf7c,0xaf9b,0xbfba,0x8fd9,0x9ff8,0x6e17,0x7e36,0x4e55,0x5e74,0x2e93,0x3eb2,0x0ed1,0x1ef0 }; +static const unsigned trackSize[4] = { 6250, 6666, 7142, 7692 }; +static const unsigned sectorsPerTrack[4] = { 17, 18, 19, 21 }; +static const unsigned gapSize[4] = { 9, 12, 17, 8 }; + + void DiskImage::CRC(unsigned short& runningCRC, unsigned char data) { runningCRC = CRC1021[(runningCRC >> 8) ^ data] ^ (runningCRC << 8); @@ -119,21 +129,16 @@ void DiskImage::OutputD81DataByte(unsigned char*& src, unsigned char*& dest) CRC(crc, data); } +unsigned DiskImage::SectorsPerTrackD64(unsigned track) +{ + return sectorsPerTrack[GetSpeedZoneIndexD64(track)]; +} + #define NIB_HEADER_SIZE 0xFF int gap_match_length = 7; // Used by gcr.cpp -const unsigned char DiskImage::SectorsPerTrack[42] = -{ - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, // 1 - 17 - 19, 19, 19, 19, 19, 19, 19, // 18 - 24 - 18, 18, 18, 18, 18, 18, // 25 - 30 - 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, // 31 - 40 - 17, 17 // 41 - 42 - // total 683-768 sectors -}; - DiskImage::DiskImage() : readOnly(false) , dirty(false) @@ -208,6 +213,9 @@ bool DiskImage::OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsig unsigned char errorinfo[MAXBLOCKSONDISK]; unsigned last_track; unsigned sector_ref; + unsigned sectors; + unsigned speedZoneIndex; + unsigned sectorSize; unsigned char error; Close(); @@ -254,7 +262,7 @@ bool DiskImage::OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsig unsigned char* dest = tracks[halfTrackIndex]; #endif - trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH; + trackLengths[halfTrackIndex] = trackSize[GetSpeedZoneIndexD64(track)]; if ((halfTrackIndex & 1) == 0) { @@ -262,13 +270,15 @@ bool DiskImage::OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsig { trackUsed[halfTrackIndex] = true; //DEBUG_LOG("Track %d used\r\n", halfTrackIndex); - for (unsigned sectorNo = 0; sectorNo < SectorsPerTrack[track]; ++sectorNo) + speedZoneIndex = GetSpeedZoneIndexD64(track); + sectors = sectorsPerTrack[speedZoneIndex]; + sectorSize = GCR_SYNC_LENGTH + GCR_HEADER_LENGTH + GCR_HEADER_GAP_LENGTH + GCR_SYNC_LENGTH + GCR_SECTOR_DATA_LENGTH + gapSize[speedZoneIndex]; + + for (unsigned sectorNo = 0; sectorNo < sectors; ++sectorNo) { error = errorinfo[sector_ref++]; - - convert_sector_to_GCR(diskImage + offset, dest, track + 1, sectorNo, diskImage + 0x165A2, error); - dest += 361; - + convert_sector_to_GCR(diskImage + offset, dest, track + 1, sectorNo, diskImage + 0x165A2, error, sectorSize); + dest += sectorSize; offset += SECTOR_LENGTH; } } @@ -291,9 +301,17 @@ bool DiskImage::OpenD64(const FILINFO* fileInfo, unsigned char* diskImage, unsig bool DiskImage::WriteD64(char* name) { + BYTE id[3]; + if (readOnly) return true; + if (!GetID(34, id)) + { + DEBUG_LOG("Cannot find directory sector.\r\n"); + return false; + } + FIL fp; FRESULT res = f_open(&fp, fileInfo ? fileInfo->fname : name, FA_CREATE_ALWAYS | FA_WRITE); if (res == FR_OK) @@ -301,8 +319,7 @@ bool DiskImage::WriteD64(char* name) u32 bytesToWrite; u32 bytesWritten; - int track, sector; - BYTE id[3]; + unsigned track, sector, sectors; BYTE d64data[MAXBLOCKSONDISK * 256], *d64ptr; int blocks_to_save = 0; @@ -310,11 +327,6 @@ bool DiskImage::WriteD64(char* name) memset(d64data, 0, sizeof(d64data)); - if (!GetID(34, id)) - { - DEBUG_LOG("Cannot find directory sector.\r\n"); - return false; - } d64ptr = d64data; for (track = 0; track < HALF_TRACK_COUNT; track += 2) { @@ -322,7 +334,8 @@ bool DiskImage::WriteD64(char* name) { //printf("Track %d\r\n", track); - for (sector = 0; sector < SectorsPerTrack[track / 2]; sector++) + sectors = sectorsPerTrack[GetSpeedZoneIndexD64(track >> 1)]; + for (sector = 0; sector < sectors; sector++) { ConvertSector(track, sector, d64ptr); d64ptr += 256; @@ -369,6 +382,14 @@ void DiskImage::CloseD64() bool DiskImage::OpenD71(const FILINFO* fileInfo, unsigned char* diskImage, unsigned size) { + unsigned char errorinfo[MAXBLOCKSONDISK * 2]; + unsigned last_track; + unsigned sector_ref; + unsigned sectors; + unsigned speedZoneIndex; + unsigned sectorSize; + unsigned char error; + Close(); this->fileInfo = fileInfo; @@ -380,43 +401,67 @@ bool DiskImage::OpenD71(const FILINFO* fileInfo, unsigned char* diskImage, unsig attachedImageSize = size; - for (unsigned headIndex = 0; headIndex < 2; ++headIndex) + memset(errorinfo, SECTOR_OK, sizeof(errorinfo)); + + switch (size) { - for (unsigned halfTrackIndex = 0; halfTrackIndex < D71_HALF_TRACK_COUNT; ++halfTrackIndex) + case (BLOCKSONDISK * 2 * 257): // 70 track image with errorinfo + memcpy(errorinfo, diskImage + (BLOCKSONDISK * 2 * 256), BLOCKSONDISK * 2); + /* FALLTHROUGH */ + case (BLOCKSONDISK * 2 * 256): // 70 track image w/o errorinfo + last_track = 70; + break; + + //case (MAXBLOCKSONDISK * 2 * 257): // 80 track image with errorinfo + // memcpy(errorinfo, diskImage + (MAXBLOCKSONDISK * 2 * 256), MAXBLOCKSONDISK * 2); + // /* FALLTHROUGH */ + //case (MAXBLOCKSONDISK * 2 * 256): // 40 track image w/o errorinfo + // last_track = 80; + // break; + + default: // non-standard images, attempt to load anyway + last_track = MAX_TRACK_D64 * 2; + break; + } + + sector_ref = 0; + for (unsigned halfTrackIndex = 0; halfTrackIndex < last_track * 2; ++halfTrackIndex) + { + unsigned char track = (halfTrackIndex >> 1); +#if defined(EXPERIMENTALZERO) + unsigned char* dest = &tracks[halfTrackIndex << 13]; +#else + unsigned char* dest = tracks[halfTrackIndex]; +#endif + + trackLengths[halfTrackIndex] = trackSize[GetSpeedZoneIndexD64(track)]; + + if ((halfTrackIndex & 1) == 0) { - unsigned char track = (halfTrackIndex >> 1); - unsigned char* dest = tracksD81[halfTrackIndex][headIndex]; - - trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH; - - if ((halfTrackIndex & 1) == 0) + if (offset < size) { - if (offset < size) // This will allow for >35 tracks. + trackUsed[halfTrackIndex] = true; + speedZoneIndex = GetSpeedZoneIndexD64(track); + sectors = sectorsPerTrack[speedZoneIndex]; + sectorSize = GCR_SYNC_LENGTH + GCR_HEADER_LENGTH + GCR_HEADER_GAP_LENGTH + GCR_SYNC_LENGTH + GCR_SECTOR_DATA_LENGTH + gapSize[speedZoneIndex]; + for (unsigned sectorNo = 0; sectorNo < sectors; ++sectorNo) { - trackUsed[halfTrackIndex] = true; - //DEBUG_LOG("Track %d used\r\n", halfTrackIndex); - for (unsigned sectorNo = 0; sectorNo < SectorsPerTrack[track]; ++sectorNo) - { - convert_sector_to_GCR(diskImage + offset, dest, track + 1, sectorNo, diskImage + 0x165A2, 0); - dest += 361; - - offset += SECTOR_LENGTH; - } - } - else - { - trackUsed[halfTrackIndex] = false; - //DEBUG_LOG("Track %d not used\r\n", halfTrackIndex); + error = errorinfo[sector_ref++]; + convert_sector_to_GCR(diskImage + offset, dest, track + 1, sectorNo, diskImage + 0x165A2, error, sectorSize); + dest += sectorSize; + offset += SECTOR_LENGTH; } } else { trackUsed[halfTrackIndex] = false; - //DEBUG_LOG("Track %d not used\r\n", halfTrackIndex); } } + else + { + trackUsed[halfTrackIndex] = false; + } } - diskType = D71; return true; } @@ -1659,7 +1704,7 @@ int DiskImage::RAMD64GetSectorOffset(int track, int sector) for (index = 0; index < (track - 1); ++index) { - sectorOffset += SectorsPerTrack[index]; + sectorOffset += sectorsPerTrack[GetSpeedZoneIndexD64(index)]; } sectorOffset += sector; return sectorOffset; @@ -1807,8 +1852,9 @@ bool DiskImage::RAMD64FindFreeSector(bool searchForwards, unsigned char* ramD64, { unsigned char* ptr; int sectorOffset = RAMD64GetSectorOffset(18, 0); - int trackIndex; - int sectorIndex; + unsigned trackIndex; + unsigned sectorIndex; + unsigned sectors; int stripAmount = 10; track = 0; @@ -1822,7 +1868,7 @@ bool DiskImage::RAMD64FindFreeSector(bool searchForwards, unsigned char* ramD64, for (; trackIndex < 35; ++trackIndex) { - if (lastTrackUsed != (trackIndex + 1)) + if ((unsigned)lastTrackUsed != (trackIndex + 1)) { lastSectorUsed = 0; stripAmount = 0; @@ -1835,9 +1881,10 @@ bool DiskImage::RAMD64FindFreeSector(bool searchForwards, unsigned char* ramD64, ptr = 4 + ramD64 + sectorOffset * 256 + 4 * trackIndex; if (*ptr != 0) { - for (sectorIndex = 0; sectorIndex < SectorsPerTrack[trackIndex]; ++sectorIndex) + sectors = sectorsPerTrack[GetSpeedZoneIndexD64(trackIndex)]; + for (sectorIndex = 0; sectorIndex < sectors; ++sectorIndex) { - int sectorStripped = (sectorIndex + lastSectorUsed + stripAmount) % SectorsPerTrack[trackIndex]; + int sectorStripped = (sectorIndex + lastSectorUsed + stripAmount) % sectors; if (RAMD64AllocateSector(ramD64, trackIndex + 1, sectorStripped)) { track = trackIndex + 1; @@ -1856,7 +1903,7 @@ bool DiskImage::RAMD64FindFreeSector(bool searchForwards, unsigned char* ramD64, trackIndex = lastTrackUsed - 1; for (; trackIndex >= 0; --trackIndex) { - if (lastTrackUsed != (trackIndex + 1)) + if ((unsigned)lastTrackUsed != (trackIndex + 1)) { lastSectorUsed = 0; stripAmount = 0; @@ -1870,9 +1917,10 @@ bool DiskImage::RAMD64FindFreeSector(bool searchForwards, unsigned char* ramD64, ptr = 4 + ramD64 + sectorOffset * 256 + 4 * trackIndex; if (*ptr != 0) { - for (sectorIndex = 0; sectorIndex < SectorsPerTrack[trackIndex]; ++sectorIndex) + sectors = sectorsPerTrack[GetSpeedZoneIndexD64(trackIndex)]; + for (sectorIndex = 0; sectorIndex < sectors; ++sectorIndex) { - int sectorStripped = (sectorIndex + lastSectorUsed + stripAmount) % SectorsPerTrack[trackIndex]; + int sectorStripped = (sectorIndex + lastSectorUsed + stripAmount) % sectors; if (RAMD64AllocateSector(ramD64, trackIndex + 1, sectorStripped)) { diff --git a/src/DiskImage.h b/src/DiskImage.h index e9f3409..e74bc2b 100644 --- a/src/DiskImage.h +++ b/src/DiskImage.h @@ -36,14 +36,7 @@ #define DIR_ENTRY_NAME_LENGTH 18-2 static const unsigned char HALF_TRACK_COUNT = 84; -static const unsigned char D71_HALF_TRACK_COUNT = 70; static const unsigned char D81_TRACK_COUNT = 80; -static const unsigned short GCR_SYNC_LENGTH = 5; -static const unsigned short GCR_HEADER_LENGTH = 10; -static const unsigned short GCR_HEADER_GAP_LENGTH = 8; -static const unsigned short GCR_SECTOR_DATA_LENGTH = 325; -static const unsigned short GCR_SECTOR_GAP_LENGTH = 8; -static const unsigned short GCR_SECTOR_LENGTH = GCR_SYNC_LENGTH + GCR_HEADER_LENGTH + GCR_HEADER_GAP_LENGTH + GCR_SYNC_LENGTH + GCR_SECTOR_DATA_LENGTH + GCR_SECTOR_GAP_LENGTH; //361 static const unsigned short G64_MAX_TRACK_LENGTH = 7928; @@ -209,6 +202,13 @@ public: unsigned GetHash() const { return hash; } + inline static unsigned GetSpeedZoneIndexD64(unsigned track) + { + return (track < 30) + (track < 24) + (track < 17); + } + + static unsigned SectorsPerTrackD64(unsigned track); + private: void CloseD64(); void CloseG64(); diff --git a/src/Drive.h b/src/Drive.h index 00646f5..8d00692 100644 --- a/src/Drive.h +++ b/src/Drive.h @@ -125,7 +125,7 @@ private: void DumpTrack(unsigned track); // Used for debugging disk images. #if defined(EXPERIMENTALZERO) - inline u32 AdvanceSectorPositionR(int& byteOffset) + inline u32 AdvanceSectorPosition(int& byteOffset) { if (++headBitOffset == bitsInTrack) headBitOffset = 0; @@ -133,28 +133,20 @@ private: return (~headBitOffset) & 7; } #else - // No reason why I seperate these into individual read and write versions. I was just trying to get the bit stream to line up when rewriting over existing data. - inline u32 AdvanceSectorPositionR(int& byteOffset) + inline u32 AdvanceSectorPosition(int& byteOffset) { ++headBitOffset %= bitsInTrack; byteOffset = headBitOffset >> 3; return (~headBitOffset) & 7; } #endif - inline u32 AdvanceSectorPositionW(int& byteOffset) - { - byteOffset = headBitOffset >> 3; - u32 bit = (~headBitOffset) & 7; - ++headBitOffset %= bitsInTrack; - return bit; - } unsigned cachedheadTrackPos = -1; int cachedbyteOffset = -1; unsigned char cachedByte = 0; inline bool GetNextBit() { int byteOffset; - int bit = AdvanceSectorPositionR(byteOffset); + int bit = AdvanceSectorPosition(byteOffset); //Why is it faster to check both conditions here than to update the cache when moving the head? if (byteOffset != cachedbyteOffset || cachedheadTrackPos != headTrackPos) @@ -171,7 +163,7 @@ private: inline void SetNextBit(bool value) { int byteOffset; - int bit = AdvanceSectorPositionW(byteOffset); + int bit = AdvanceSectorPosition(byteOffset); diskImage->SetBit(headTrackPos, byteOffset, bit, value); } diff --git a/src/FileBrowser.cpp b/src/FileBrowser.cpp index 1cfea43..6bebb74 100644 --- a/src/FileBrowser.cpp +++ b/src/FileBrowser.cpp @@ -1615,7 +1615,7 @@ void FileBrowser::DisplayDiskInfo(DiskImage* diskImage, const char* filenameForI blocksFree += buffer[bamOffset + bamTrack * BAM_ENTRY_SIZE]; y_px = 0; - for (int bit = 0; bit < DiskImage::SectorsPerTrack[bamTrack]; bit++) + for (u32 bit = 0; bit < DiskImage::SectorsPerTrackD64(bamTrack); bit++) { u32 bits = buffer[bamOffset + 1 + (bit >> 3) + bamTrack * BAM_ENTRY_SIZE]; diff --git a/src/gcr.cpp b/src/gcr.cpp index 67f4547..d098767 100644 --- a/src/gcr.cpp +++ b/src/gcr.cpp @@ -398,14 +398,14 @@ convert_GCR_sector(BYTE * gcr_start, BYTE * gcr_cycle, BYTE * d64_sector, void convert_sector_to_GCR(BYTE * buffer, BYTE * ptr, - int track, int sector, BYTE * diskID, int error) + int track, int sector, BYTE * diskID, int error, int sectorSize) { int i; BYTE buf[4], databuf[0x104], chksum; BYTE tempID[3]; memcpy(tempID, diskID, 3); - memset(ptr, 0x55, 361); /* 'unformat' GCR sector */ + memset(ptr, 0x55, sectorSize); /* 'unformat' GCR sector */ if (error == SYNC_NOT_FOUND) return; @@ -472,10 +472,6 @@ convert_sector_to_GCR(BYTE * buffer, BYTE * ptr, convert_4bytes_to_GCR(databuf + (4 * i), ptr); ptr += 5; } - - /* 7 0x55 gap bytes in my reference disk */ - memset(ptr, 0x55, 7); /* Gap before next sector */ - ptr += 7; } size_t diff --git a/src/gcr.h b/src/gcr.h index 646bbc8..6daabda 100644 --- a/src/gcr.h +++ b/src/gcr.h @@ -135,7 +135,7 @@ size_t find_nondos_track_cycle(BYTE ** cycle_start, BYTE ** cycle_stop, BYTE convert_GCR_sector(BYTE * gcr_start, BYTE * gcr_end, BYTE * d64_sector, int track, int sector, BYTE * id); void convert_sector_to_GCR(BYTE * buffer, BYTE * ptr, - int track, int sector, BYTE * diskID, int error); + int track, int sector, BYTE * diskID, int error, int sectorSize); BYTE * find_sector_gap(BYTE * work_buffer, int tracklen, size_t * p_sectorlen); BYTE * find_sector0(BYTE * work_buffer, int tracklen, size_t * p_sectorlen); int extract_GCR_track(BYTE * destination, BYTE * source, int * align,