Fixed #201 with regards to Maverick's single drive copy.

This commit is contained in:
Stephen White 2021-01-06 18:44:40 +11:00
parent e1f59e7262
commit 0ae620842f
6 changed files with 122 additions and 86 deletions

View file

@ -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);
unsigned char* dest = tracksD81[halfTrackIndex][headIndex];
#if defined(EXPERIMENTALZERO)
unsigned char* dest = &tracks[halfTrackIndex << 13];
#else
unsigned char* dest = tracks[halfTrackIndex];
#endif
trackLengths[halfTrackIndex] = SectorsPerTrack[track] * GCR_SECTOR_LENGTH;
trackLengths[halfTrackIndex] = trackSize[GetSpeedZoneIndexD64(track)];
if ((halfTrackIndex & 1) == 0)
{
if (offset < size) // This will allow for >35 tracks.
if (offset < size)
{
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)
{
convert_sector_to_GCR(diskImage + offset, dest, track + 1, sectorNo, diskImage + 0x165A2, 0);
dest += 361;
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;
//DEBUG_LOG("Track %d not used\r\n", halfTrackIndex);
}
}
}
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))
{

View file

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

View file

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

View file

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

View file

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

View file

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