X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffloppy.cpp;h=193e5cb5bd734cae90cb9a4d00ec20158fe1c49e;hb=c0001155bc0909da61f6c849c0be9b16e9b7f4b6;hp=e811bb0f53d67d58ef17aa7b222e6ce4ef7361e2;hpb=ce9f31494277a11aa9cfcbdb5fe5c303627e626e;p=apple2 diff --git a/src/floppy.cpp b/src/floppy.cpp index e811bb0..193e5cb 100755 --- a/src/floppy.cpp +++ b/src/floppy.cpp @@ -16,12 +16,12 @@ #include "floppy.h" #include -#include +#include #include "apple2.h" #include "log.h" #include "applevideo.h" // For message spawning... Though there's probably a better approach than this! -using namespace std; +//using namespace std; // Useful enums @@ -29,14 +29,15 @@ enum { IO_MODE_READ, IO_MODE_WRITE }; // FloppyDrive class variable initialization -uint8 FloppyDrive::header[21] = { +uint8_t FloppyDrive::header[21] = { 0xD5, 0xAA, 0x96, 0xFF, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xDE, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD5, 0xAA, 0xAD }; -uint8 FloppyDrive::doSector[16] = { +uint8_t FloppyDrive::doSector[16] = { 0x0, 0x7, 0xE, 0x6, 0xD, 0x5, 0xC, 0x4, 0xB, 0x3, 0xA, 0x2, 0x9, 0x1, 0x8, 0xF }; -uint8 FloppyDrive::poSector[16] = { +uint8_t FloppyDrive::poSector[16] = { 0x0, 0x8, 0x1, 0x9, 0x2, 0xA, 0x3, 0xB, 0x4, 0xC, 0x5, 0xD, 0x6, 0xE, 0x7, 0xF }; +char FloppyDrive::nameBuf[MAX_PATH]; // FloppyDrive class implementation... @@ -46,6 +47,7 @@ FloppyDrive::FloppyDrive(): motorOn(0), activeDrive(0), ioMode(IO_MODE_READ), ph diskSize[0] = diskSize[1] = 0; diskType[0] = diskType[1] = DT_UNKNOWN; imageDirty[0] = imageDirty[1] = false; + writeProtected[0] = writeProtected[1] = false; imageName[0][0] = imageName[1][0] = 0; // Zero out filenames } @@ -58,8 +60,10 @@ FloppyDrive::~FloppyDrive() delete[] disk[1]; } -bool FloppyDrive::LoadImage(const char * filename, uint8 driveNum/*= 0*/) +bool FloppyDrive::LoadImage(const char * filename, uint8_t driveNum/*= 0*/) { + WriteLog("FLOPPY: Attempting to load image '%s' in drive #%u.\n", filename, driveNum); + if (driveNum > 1) { WriteLog("FLOPPY: Attempted to load image to drive #%u!\n", driveNum); @@ -82,7 +86,7 @@ bool FloppyDrive::LoadImage(const char * filename, uint8 driveNum/*= 0*/) fseek(fp, 0, SEEK_END); diskSize[driveNum] = ftell(fp); fseek(fp, 0, SEEK_SET); - disk[driveNum] = new uint8[diskSize[driveNum]]; + disk[driveNum] = new uint8_t[diskSize[driveNum]]; fread(disk[driveNum], 1, diskSize[driveNum], fp); fclose(fp); @@ -90,10 +94,25 @@ bool FloppyDrive::LoadImage(const char * filename, uint8 driveNum/*= 0*/) DetectImageType(filename, driveNum); strcpy(imageName[driveNum], filename); +#if 0 + WriteLog("FLOPPY: Opening image for drive #%u.\n", driveNum); + FILE * fp2 = fopen("bt-nybblized.nyb", "wb"); + + if (fp2 == NULL) + WriteLog("FLOPPY: Failed to open image file 'bt-nybblized.nyb' for writing...\n"); + else + { + fwrite(nybblizedImage[driveNum], 1, 232960, fp2); + fclose(fp2); + } +#endif +//writeProtected[driveNum] = true; + WriteLog("FLOPPY: Loaded image '%s' for drive #%u.\n", filename, driveNum); + return true; } -bool FloppyDrive::SaveImage(uint8 driveNum/*= 0*/) +bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/) { if (driveNum > 1) { @@ -129,33 +148,37 @@ bool FloppyDrive::SaveImage(uint8 driveNum/*= 0*/) fwrite(disk[driveNum], 1, diskSize[driveNum], fp); fclose(fp); + WriteLog("FLOPPY: Successfully wrote image file '%s'...\n", imageName[driveNum]); + return true; } -bool FloppyDrive::SaveImageAs(const char * filename, uint8 driveNum/*= 0*/) +bool FloppyDrive::SaveImageAs(const char * filename, uint8_t driveNum/*= 0*/) { //WARNING: Buffer overflow possibility +#warning "Buffer overflow possible--!!! FIX !!!" strcpy(imageName[driveNum], filename); return SaveImage(driveNum); } -void FloppyDrive::CreateBlankImage(uint8 driveNum/*= 0*/) +void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/) { if (disk[driveNum] != NULL) delete disk[driveNum]; - disk[driveNum] = new uint8[143360]; + disk[driveNum] = new uint8_t[143360]; diskSize[driveNum] = 143360; memset(disk[driveNum], 0x00, 143360); memset(nybblizedImage[driveNum], 0x00, 232960); // Set it to 0 instead of $FF for proper formatting... diskType[driveNum] = DT_DOS33; strcpy(imageName[driveNum], "newblank.dsk"); + writeProtected[driveNum] = false; SpawnMessage("New blank image inserted in drive %u...", driveNum); } void FloppyDrive::SwapImages(void) { - uint8 nybblizedImageTmp[232960]; + uint8_t nybblizedImageTmp[232960]; char imageNameTmp[MAX_PATH]; memcpy(nybblizedImageTmp, nybblizedImage[0], 232960); @@ -166,25 +189,29 @@ void FloppyDrive::SwapImages(void) memcpy(imageName[0], imageName[1], MAX_PATH); memcpy(imageName[1], imageNameTmp, MAX_PATH); - uint8 * diskTmp = disk[0]; + uint8_t * diskTmp = disk[0]; disk[0] = disk[1]; disk[1] = diskTmp; - uint32 diskSizeTmp = diskSize[0]; + uint32_t diskSizeTmp = diskSize[0]; diskSize[0] = diskSize[1]; diskSize[1] = diskSizeTmp; - uint8 diskTypeTmp = diskType[0]; + uint8_t diskTypeTmp = diskType[0]; diskType[0] = diskType[1]; diskType[1] = diskTypeTmp; - uint8 imageDirtyTmp = imageDirty[0]; + uint8_t imageDirtyTmp = imageDirty[0]; imageDirty[0] = imageDirty[1]; imageDirty[1] = imageDirtyTmp; + + uint8_t writeProtectedTmp = writeProtected[0]; + writeProtected[0] = writeProtected[1]; + writeProtected[1] = writeProtectedTmp; SpawnMessage("Drive 0: %s...", imageName[0]); } -void FloppyDrive::DetectImageType(const char * filename, uint8 driveNum) +void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum) { diskType[driveNum] = DT_UNKNOWN; @@ -226,14 +253,22 @@ WRT to the disk image itself. //*/ } +// Actually, it just might matter WRT to nybblyzing/denybblyzing +// Here, we check for BT3 +//Nope, no change... +//diskType[driveNum] = DT_PRODOS; + NybblizeImage(driveNum); } + +#warning "Should we attempt to nybblize unknown images here? Definitely SHOULD issue a warning!" + WriteLog("FLOPPY: Detected image type %s...\n", (diskType[driveNum] == DT_NYBBLE ? "Nybble image" : (diskType[driveNum] == DT_DOS33 ? "DOS 3.3 image" : (diskType[driveNum] == DT_PRODOS ? "ProDOS image" : "unknown")))); } -void FloppyDrive::NybblizeImage(uint8 driveNum) +void FloppyDrive::NybblizeImage(uint8_t driveNum) { // Format of a sector is header (23) + nybbles (343) + footer (30) = 396 // (short by 20 bytes of 416 [413 if 48 byte header is one time only]) @@ -242,7 +277,7 @@ void FloppyDrive::NybblizeImage(uint8 driveNum) // hdr (21) + nybbles (343) + footer (48) = 412 bytes per sector // (not incl. 64 byte track marker) - uint8 footer[48] = { + uint8_t footer[48] = { 0xDE, 0xAA, 0xEB, 0xFF, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, @@ -250,7 +285,7 @@ void FloppyDrive::NybblizeImage(uint8 driveNum) 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - uint8 diskbyte[0x40] = { + uint8_t diskbyte[0x40] = { 0x96, 0x97, 0x9A, 0x9B, 0x9D, 0x9E, 0x9F, 0xA6, 0xA7, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6, 0xB7, 0xB9, 0xBA, 0xBB, 0xBC, @@ -260,15 +295,15 @@ void FloppyDrive::NybblizeImage(uint8 driveNum) 0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; - uint8 * img = nybblizedImage[driveNum]; + uint8_t * img = nybblizedImage[driveNum]; memset(img, 0xFF, 232960); // Doesn't matter if 00s or FFs... - for(uint8 trk=0; trk<35; trk++) + for(uint8_t trk=0; trk<35; trk++) { memset(img, 0xFF, 64); // Write gap 1, 64 bytes (self-sync) img += 64; - for(uint8 sector=0; sector<16; sector++) + for(uint8_t sector=0; sector<16; sector++) { memcpy(img, header, 21); // Set up the sector header @@ -280,7 +315,7 @@ void FloppyDrive::NybblizeImage(uint8 driveNum) img[10] = ((trk ^ sector ^ 0xFE) & 0x55) | 0xAA; img += 21; - uint8 * bytes = disk[driveNum]; + uint8_t * bytes = disk[driveNum]; if (diskType[driveNum] == DT_DOS33) bytes += (doSector[sector] * 256) + (trk * 256 * 16); @@ -291,7 +326,7 @@ void FloppyDrive::NybblizeImage(uint8 driveNum) // Convert the 256 8-bit bytes into 342 6-bit bytes. - for(uint16 i=0; i<0x56; i++) + for(uint16_t i=0; i<0x56; i++) { img[i] = ((bytes[(i + 0xAC) & 0xFF] & 0x01) << 7) | ((bytes[(i + 0xAC) & 0xFF] & 0x02) << 5) @@ -310,14 +345,22 @@ void FloppyDrive::NybblizeImage(uint8 driveNum) img[342] = 0x00; - for(uint16 i=342; i>0; i--) + for(uint16_t i=342; i>0; i--) img[i] = img[i] ^ img[i - 1]; // Using a lookup table, convert the 6-bit bytes into disk bytes. - for(uint16 i=0; i<343; i++) + for(uint16_t i=0; i<343; i++) +//#define TEST_NYBBLIZATION +#ifdef TEST_NYBBLIZATION +{ +WriteLog("FL: i = %u, img[i] = %02X, diskbyte = %02X\n", i, img[i], diskbyte[img[i] >> 2]); +#endif img[i] = diskbyte[img[i] >> 2]; - +#ifdef TEST_NYBBLIZATION +//WriteLog(" img[i] = %02X\n", img[i]); +} +#endif img += 343; // Done with the nybblization, now for the epilogue... @@ -328,9 +371,9 @@ void FloppyDrive::NybblizeImage(uint8 driveNum) } } -void FloppyDrive::DenybblizeImage(uint8 driveNum) +void FloppyDrive::DenybblizeImage(uint8_t driveNum) { - uint8 decodeNybble[0x80] = { + uint8_t decodeNybble[0x80] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, @@ -356,19 +399,19 @@ void FloppyDrive::DenybblizeImage(uint8 driveNum) return; } - uint8 * srcImg = nybblizedImage[driveNum]; - uint8 * dstImg = disk[driveNum]; - uint8 buffer[345]; // 2 extra bytes for the unpack routine below... + uint8_t * srcImg = nybblizedImage[driveNum]; + uint8_t * dstImg = disk[driveNum]; + uint8_t buffer[345]; // 2 extra bytes for the unpack routine below... - for(uint8 trk=0; trk<35; trk++) + for(uint8_t trk=0; trk<35; trk++) { - uint8 * trackBase = srcImg + (trk * 6656); + uint8_t * trackBase = srcImg + (trk * 6656); - for(uint8 sector=0; sector<16; sector++) + for(uint8_t sector=0; sector<16; sector++) { - uint16 sectorStart = (uint16)-1; + uint16_t sectorStart = (uint16_t)-1; - for(uint16 i=0; i<6656; i++) + for(uint16_t i=0; i<6656; i++) { if (trackBase[i] == header[0] && trackBase[(i + 1) % 6656] == header[1] @@ -377,7 +420,7 @@ void FloppyDrive::DenybblizeImage(uint8 driveNum) && trackBase[(i + 4) % 6656] == header[4]) { //Could also check the track # at +5,6... - uint8 foundSector = ((trackBase[(i + 7) % 6656] & 0x55) << 1) + uint8_t foundSector = ((trackBase[(i + 7) % 6656] & 0x55) << 1) | (trackBase[(i + 8) % 6656] & 0x55); if (foundSector == sector) @@ -389,7 +432,7 @@ void FloppyDrive::DenybblizeImage(uint8 driveNum) } // Sanity check... - if (sectorStart == (uint16)-1) + if (sectorStart == (uint16_t)-1) { WriteLog("FLOPPY: Failed to find sector %u (track %u) in nybble image!\n", sector, trk); @@ -398,24 +441,24 @@ void FloppyDrive::DenybblizeImage(uint8 driveNum) // Using a lookup table, convert the disk bytes into 6-bit bytes. - for(uint16 i=0; i<343; i++) + for(uint16_t i=0; i<343; i++) buffer[i] = decodeNybble[trackBase[(sectorStart + i) % 6656] & 0x7F]; // XOR the data block with itself, offset by one byte. - for(uint16 i=1; i<342; i++) + for(uint16_t i=1; i<342; i++) buffer[i] = buffer[i] ^ buffer[i - 1]; // Convert the 342 6-bit bytes into 256 8-bit bytes (at buffer + $56). - for(uint16 i=0; i<0x56; i++) + for(uint16_t i=0; i<0x56; i++) { buffer[0x056 + i] |= ((buffer[i] >> 3) & 0x01) | ((buffer[i] >> 1) & 0x02); buffer[0x0AC + i] |= ((buffer[i] >> 5) & 0x01) | ((buffer[i] >> 3) & 0x02); buffer[0x102 + i] |= ((buffer[i] >> 7) & 0x01) | ((buffer[i] >> 5) & 0x02); } - uint8 * bytes = dstImg; + uint8_t * bytes = dstImg; if (diskType[driveNum] == DT_DOS33) bytes += (doSector[sector] * 256) + (trk * 256 * 16); @@ -429,6 +472,96 @@ void FloppyDrive::DenybblizeImage(uint8 driveNum) } } +const char * FloppyDrive::GetImageName(uint8_t driveNum/*= 0*/) +{ + // Set up a zero-length string for return value + nameBuf[0] = 0; + + if (driveNum > 1) + { + WriteLog("FLOPPY: Attempted to get image name for drive #%u!\n", driveNum); + return nameBuf; + } + + // Now we attempt to strip out extraneous paths/extensions to get just the filename + const char * startOfFile = strrchr(imageName[driveNum], '/'); + const char * startOfExt = strrchr(imageName[driveNum], '.'); + + // If there isn't a path, assume we're starting at the beginning + if (startOfFile == NULL) + startOfFile = &imageName[driveNum][0]; + else + startOfFile++; + + // If there isn't an extension, assume it's at the terminating NULL + if (startOfExt == NULL) + startOfExt = &imageName[driveNum][0] + strlen(imageName[driveNum]); + + // Now copy the filename (may copy nothing!) + int j = 0; + + for(const char * i=startOfFile; i 1) + { + WriteLog("FLOPPY: Attempted DriveIsEmtpy() for drive #%u!\n", driveNum); + return true; + } + + // This is kinda gay, but it works + return (imageName[driveNum][0] == 0 ? true : false); +} + +bool FloppyDrive::DiskIsWriteProtected(uint8_t driveNum/*= 0*/) +{ + if (driveNum > 1) + { + WriteLog("FLOPPY: Attempted DiskIsWriteProtected() for drive #%u!\n", driveNum); + return true; + } + + return writeProtected[driveNum]; +} + +void FloppyDrive::SetWriteProtect(bool state, uint8_t driveNum/*= 0*/) +{ + if (driveNum > 1) + { + WriteLog("FLOPPY: Attempted set write protect for drive #%u!\n", driveNum); + return; + } + + writeProtected[driveNum] = state; +} + + // Memory mapped I/O functions /* @@ -442,7 +575,7 @@ also more versatile and can represent the older 13-sector disks, many copy-prote other unusual encodings. */ -void FloppyDrive::ControlStepper(uint8 addr) +void FloppyDrive::ControlStepper(uint8_t addr) { // $C0E0 - 7 /* @@ -452,7 +585,7 @@ bit 0 is the "do something" bit. */ if (addr & 0x01) { - uint8 newPhase = (addr >> 1) & 0x03; + uint8_t newPhase = (addr >> 1) & 0x03; //WriteLog("*** Stepper change [%u]: track = %u, phase = %u, newPhase = %u\n", addr, track, phase, newPhase); if (((phase + 1) & 0x03) == newPhase) @@ -470,24 +603,25 @@ bit 0 is the "do something" bit. SpawnMessage("Stepping to track %u...", track); } -// return something if read mode... +// return something if read mode... } -void FloppyDrive::ControlMotor(uint8 addr) +void FloppyDrive::ControlMotor(uint8_t addr) { // $C0E8 - 9 motorOn = addr; } -void FloppyDrive::DriveEnable(uint8 addr) +void FloppyDrive::DriveEnable(uint8_t addr) { // $C0EA - B activeDrive = addr; } -uint8 FloppyDrive::ReadWrite(void) +uint8_t FloppyDrive::ReadWrite(void) { -SpawnMessage("%sing %s track %u, sector %u...", (ioMode == IO_MODE_READ ? "Read" : "Write"), +SpawnMessage("%u:%sing %s track %u, sector %u...", activeDrive, + (ioMode == IO_MODE_READ ? "Read" : "Write"), (ioMode == IO_MODE_READ ? "from" : "to"), track, currentPos / 396); // $C0EC /* @@ -498,23 +632,32 @@ Which we now do. :-) */ if (ioMode == IO_MODE_WRITE && (latchValue & 0x80)) { - nybblizedImage[activeDrive][(track * 6656) + currentPos] = latchValue; - imageDirty[activeDrive] = true; + // Does it behave like this? +#warning "Write protection kludged in--investigate real behavior!" + if (!writeProtected[activeDrive]) + { + nybblizedImage[activeDrive][(track * 6656) + currentPos] = latchValue; + imageDirty[activeDrive] = true; + } + else +//doesn't seem to do anything + return 0;//is this more like it? } - uint8 diskByte = nybblizedImage[activeDrive][(track * 6656) + currentPos]; + uint8_t diskByte = nybblizedImage[activeDrive][(track * 6656) + currentPos]; currentPos = (currentPos + 1) % 6656; +//WriteLog("FL: diskByte=%02X, currentPos=%u\n", diskByte, currentPos); return diskByte; } -uint8 FloppyDrive::GetLatchValue(void) +uint8_t FloppyDrive::GetLatchValue(void) { // $C0ED return latchValue; } -void FloppyDrive::SetLatchValue(uint8 value) +void FloppyDrive::SetLatchValue(uint8_t value) { // $C0ED latchValue = value; @@ -531,3 +674,38 @@ void FloppyDrive::SetWriteMode(void) // $C0EF ioMode = IO_MODE_WRITE; } + +/* +PRODOS 8 MLI ERROR CODES + +$00: No error +$01: Bad system call number +$04: Bad system call parameter count +$25: Interrupt table full +$27: I/O error +$28: No device connected +$2B: Disk write protected +$2E: Disk switched +$40: Invalid pathname +$42: Maximum number of files open +$43: Invalid reference number +$44: Directory not found +$45: Volume not found +$46: File not found +$47: Duplicate filename +$48: Volume full +$49: Volume directory full +$4A: Incompatible file format, also a ProDOS directory +$4B: Unsupported storage_type +$4C: End of file encountered +$4D: Position out of range +$4E: File access error, also file locked +$50: File is open +$51: Directory structure damaged +$52: Not a ProDOS volume +$53: Invalid system call parameter +$55: Volume Control Block table full +$56: Bad buffer address +$57: Duplicate volume +$5A: File structure damaged +*/