X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Ffloppy.cpp;fp=src%2Ffloppy.cpp;h=0000000000000000000000000000000000000000;hb=66a747c7d92af86ebdfaf136cf5506a7ab714fd0;hp=859db6d7faf954d64e961ca62622b7bef993fec7;hpb=6bdd378e27a9bbf3a074e9c33c61195c8fcfef1c;p=apple2 diff --git a/src/floppy.cpp b/src/floppy.cpp deleted file mode 100644 index 859db6d..0000000 --- a/src/floppy.cpp +++ /dev/null @@ -1,872 +0,0 @@ -// -// Apple 2 floppy disk support -// -// by James Hammons -// (c) 2005 Underground Software -// -// JLH = James Hammons -// -// WHO WHEN WHAT -// --- ---------- ----------------------------------------------------------- -// JLH 12/03/2005 Created this file -// JLH 12/15/2005 Fixed nybblization functions to work properly -// JLH 12/27/2005 Added blank disk creation, fixed saving to work properly -// - -#include "floppy.h" - -#include -#include -#include "apple2.h" -#include "log.h" -#include "video.h" // For message spawning... Though there's probably a - // better approach than this! - -// Useful enums - -enum { IO_MODE_READ, IO_MODE_WRITE }; - -// FloppyDrive class variable initialization - -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_t FloppyDrive::doSector[16] = { - 0x0, 0x7, 0xE, 0x6, 0xD, 0x5, 0xC, 0x4, 0xB, 0x3, 0xA, 0x2, 0x9, 0x1, 0x8, 0xF }; -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... - -FloppyDrive::FloppyDrive(): motorOn(0), activeDrive(0), ioMode(IO_MODE_READ), phase(0), track(0), ioHappened(false) -{ - disk[0] = disk[1] = NULL; - diskSize[0] = diskSize[1] = 0; - diskType[0] = diskType[1] = DFT_UNKNOWN; - imageDirty[0] = imageDirty[1] = false; - writeProtected[0] = writeProtected[1] = false; - imageName[0][0] = imageName[1][0] = 0; // Zero out filenames -} - - -FloppyDrive::~FloppyDrive() -{ - if (disk[0]) - delete[] disk[0]; - - if (disk[1]) - delete[] disk[1]; -} - - -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); - return false; - } - - imageName[driveNum][0] = 0; // Zero out filename, in case it doesn't load - - FILE * fp = fopen(filename, "rb"); - - if (fp == NULL) - { - WriteLog("FLOPPY: Failed to open image file '%s' for reading...\n", filename); - return false; - } - - if (disk[driveNum]) - delete[] disk[driveNum]; - - fseek(fp, 0, SEEK_END); - diskSize[driveNum] = ftell(fp); - fseek(fp, 0, SEEK_SET); - disk[driveNum] = new uint8_t[diskSize[driveNum]]; - fread(disk[driveNum], 1, diskSize[driveNum], fp); - - fclose(fp); -//printf("Read disk image: %u bytes.\n", diskSize); - 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_t driveNum/*= 0*/) -{ - // Various sanity checks... - if (driveNum > 1) - { - WriteLog("FLOPPY: Attempted to save image to drive #%u!\n", driveNum); - return false; - } - - if (!imageDirty[driveNum]) - { - WriteLog("FLOPPY: No need to save unchanged image...\n"); - return false; - } - - if (imageName[driveNum][0] == 0) - { - WriteLog("FLOPPY: Attempted to save non-existant image!\n"); - return false; - } - - // Handle nybbylization, if necessary - if (diskType[driveNum] == DT_NYBBLE) - memcpy(disk[driveNum], nybblizedImage[driveNum], 232960); - else - DenybblizeImage(driveNum); - - // Finally, write the damn image - FILE * fp = fopen(imageName[driveNum], "wb"); - - if (fp == NULL) - { - WriteLog("FLOPPY: Failed to open image file '%s' for writing...\n", imageName[driveNum]); - return false; - } - - 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_t driveNum/*= 0*/) -{ -//WARNING: Buffer overflow possibility -#warning "Buffer overflow possible--!!! FIX !!!" - strcpy(imageName[driveNum], filename); - return SaveImage(driveNum); -} - - -void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/) -{ - if (disk[driveNum] != NULL) - delete disk[driveNum]; - - 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_t nybblizedImageTmp[232960]; - char imageNameTmp[MAX_PATH]; - - memcpy(nybblizedImageTmp, nybblizedImage[0], 232960); - memcpy(nybblizedImage[0], nybblizedImage[1], 232960); - memcpy(nybblizedImage[1], nybblizedImageTmp, 232960); - - memcpy(imageNameTmp, imageName[0], MAX_PATH); - memcpy(imageName[0], imageName[1], MAX_PATH); - memcpy(imageName[1], imageNameTmp, MAX_PATH); - - uint8_t * diskTmp = disk[0]; - disk[0] = disk[1]; - disk[1] = diskTmp; - - uint32_t diskSizeTmp = diskSize[0]; - diskSize[0] = diskSize[1]; - diskSize[1] = diskSizeTmp; - - uint8_t diskTypeTmp = diskType[0]; - diskType[0] = diskType[1]; - diskType[1] = diskTypeTmp; - - 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_t driveNum) -{ - diskType[driveNum] = DFT_UNKNOWN; - - if (diskSize[driveNum] == 232960) - { - diskType[driveNum] = DT_NYBBLE; - memcpy(nybblizedImage[driveNum], disk[driveNum], 232960); - } - else if (diskSize[driveNum] == 143360) - { - const char * ext = strrchr(filename, '.'); - - if (ext == NULL) - return; -WriteLog("FLOPPY: Found extension [%s]...\n", ext); - -//Apparently .dsk can house either DOS order OR PRODOS order... !!! FIX !!! - if (strcasecmp(ext, ".po") == 0) - diskType[driveNum] = DT_PRODOS; - else if ((strcasecmp(ext, ".do") == 0) || (strcasecmp(ext, ".dsk") == 0)) - { - // We assume this, but check for a PRODOS fingerprint. Trust, but - // verify. ;-) - diskType[driveNum] = DT_DOS33; - - uint8_t fingerprint[4][4] = { - { 0x00, 0x00, 0x03, 0x00 }, // @ $400 - { 0x02, 0x00, 0x04, 0x00 }, // @ $600 - { 0x03, 0x00, 0x05, 0x00 }, // @ $800 - { 0x04, 0x00, 0x00, 0x00 } // @ $A00 - }; - - bool foundProdos = true; - - for(uint32_t i=0; i<4; i++) - { - for(uint32_t j=0; j<4; j++) - { - if (disk[driveNum][0x400 + (i * 0x200) + j] != fingerprint[i][j]) - { - foundProdos = false; - break; - } - } - } - - if (foundProdos) - diskType[driveNum] = DT_PRODOS; - } - -// Actually, it just might matter WRT to nybblyzing/denybblyzing -// (and, it does... :-P) - NybblizeImage(driveNum); - } - else if (diskSize[driveNum] == 143488) - { - diskType[driveNum] = DT_DOS33_HDR; - 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_DOS33_HDR ? - "DOS 3.3 image (headered)" : (diskType[driveNum] == DT_PRODOS ? "ProDOS image" : "unknown"))))); -} - - -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]) -// Hmph. Who'da thunk that AppleWin's nybblization routines would be wrong? -// This is now correct, BTW - // hdr (21) + nybbles (343) + footer (48) = 412 bytes per sector - // (not incl. 64 byte track marker) - - 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, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - - 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, - 0xBD, 0xBE, 0xBF, 0xCB, 0xCD, 0xCE, 0xCF, 0xD3, - 0xD6, 0xD7, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, - 0xDF, 0xE5, 0xE6, 0xE7, 0xE9, 0xEA, 0xEB, 0xEC, - 0xED, 0xEE, 0xEF, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, - 0xF7, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF }; - - uint8_t * img = nybblizedImage[driveNum]; - memset(img, 0xFF, 232960); // Doesn't matter if 00s or FFs... - - for(uint8_t trk=0; trk<35; trk++) - { - memset(img, 0xFF, 64); // Write gap 1, 64 bytes (self-sync) - img += 64; - - for(uint8_t sector=0; sector<16; sector++) - { - memcpy(img, header, 21); // Set up the sector header - - img[5] = ((trk >> 1) & 0x55) | 0xAA; - img[6] = (trk & 0x55) | 0xAA; - img[7] = ((sector >> 1) & 0x55) | 0xAA; - img[8] = (sector & 0x55) | 0xAA; - img[9] = (((trk ^ sector ^ 0xFE) >> 1) & 0x55) | 0xAA; - img[10] = ((trk ^ sector ^ 0xFE) & 0x55) | 0xAA; - - img += 21; - uint8_t * bytes = disk[driveNum]; - - if (diskType[driveNum] == DT_DOS33) - bytes += (doSector[sector] * 256) + (trk * 256 * 16); - else if (diskType[driveNum] == DT_DOS33_HDR) - bytes += (doSector[sector] * 256) + (trk * 256 * 16) + 128; - else if (diskType[driveNum] == DT_PRODOS) - bytes += (poSector[sector] * 256) + (trk * 256 * 16); - else - bytes += (sector * 256) + (trk * 256 * 16); - - // Convert the 256 8-bit bytes into 342 6-bit bytes. - - for(uint16_t i=0; i<0x56; i++) - { - img[i] = ((bytes[(i + 0xAC) & 0xFF] & 0x01) << 7) - | ((bytes[(i + 0xAC) & 0xFF] & 0x02) << 5) - | ((bytes[(i + 0x56) & 0xFF] & 0x01) << 5) - | ((bytes[(i + 0x56) & 0xFF] & 0x02) << 3) - | ((bytes[(i + 0x00) & 0xFF] & 0x01) << 3) - | ((bytes[(i + 0x00) & 0xFF] & 0x02) << 1); - } - - img[0x54] &= 0x3F; - img[0x55] &= 0x3F; - memcpy(img + 0x56, bytes, 256); - - // XOR the data block with itself, offset by one byte, - // creating a 343rd byte which is used as a cheksum. - - img[342] = 0x00; - - 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_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... - - memcpy(img, footer, 48); - img += 48; - } - } -} - - -void FloppyDrive::DenybblizeImage(uint8_t driveNum) -{ - 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, - 0x00, 0x00, 0x08, 0x0C, 0x00, 0x10, 0x14, 0x18, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x20, - 0x00, 0x00, 0x00, 0x24, 0x28, 0x2C, 0x30, 0x34, - 0x00, 0x00, 0x38, 0x3C, 0x40, 0x44, 0x48, 0x4C, - 0x00, 0x50, 0x54, 0x58, 0x5C, 0x60, 0x64, 0x68, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x6C, 0x00, 0x70, 0x74, 0x78, - 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x80, 0x84, - 0x00, 0x88, 0x8C, 0x90, 0x94, 0x98, 0x9C, 0xA0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0xA4, 0xA8, 0xAC, - 0x00, 0xB0, 0xB4, 0xB8, 0xBC, 0xC0, 0xC4, 0xC8, - 0x00, 0x00, 0xCC, 0xD0, 0xD4, 0xD8, 0xDC, 0xE0, - 0x00, 0xE4, 0xE8, 0xEC, 0xF0, 0xF4, 0xF8, 0xFC }; - - // Sanity checks... - if (disk[driveNum] == NULL || diskSize[driveNum] < 143360) - { - WriteLog("FLOPPY: Source disk image invalid! [drive=%u, disk=%08X, diskSize=%u]\n", - driveNum, disk[driveNum], diskSize[driveNum]); - return; - } - - uint8_t * srcImg = nybblizedImage[driveNum]; - uint8_t * dstImg = disk[driveNum]; - uint8_t buffer[345]; // 2 extra bytes for the unpack routine below... - - for(uint8_t trk=0; trk<35; trk++) - { - uint8_t * trackBase = srcImg + (trk * 6656); - - for(uint8_t sector=0; sector<16; sector++) - { - uint16_t sectorStart = (uint16_t)-1; - - for(uint16_t i=0; i<6656; i++) - { - if (trackBase[i] == header[0] - && trackBase[(i + 1) % 6656] == header[1] - && trackBase[(i + 2) % 6656] == header[2] - && trackBase[(i + 3) % 6656] == header[3] - && trackBase[(i + 4) % 6656] == header[4]) - { -//Could also check the track # at +5,6... - uint8_t foundSector = ((trackBase[(i + 7) % 6656] & 0x55) << 1) - | (trackBase[(i + 8) % 6656] & 0x55); - - if (foundSector == sector) - { - sectorStart = (i + 21) % 6656; - break; - } - } - } - - // Sanity check... - if (sectorStart == (uint16_t)-1) - { - WriteLog("FLOPPY: Failed to find sector %u (track %u) in nybble image!\n", - sector, trk); - return; - } - - // Using a lookup table, convert the disk bytes into 6-bit bytes. - - 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_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_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_t * bytes = dstImg; - - if (diskType[driveNum] == DT_DOS33) - bytes += (doSector[sector] * 256) + (trk * 256 * 16); - else if (diskType[driveNum] == DT_DOS33_HDR) - bytes += (doSector[sector] * 256) + (trk * 256 * 16) + 128; - else if (diskType[driveNum] == DT_PRODOS) - bytes += (poSector[sector] * 256) + (trk * 256 * 16); - else - bytes += (sector * 256) + (trk * 256 * 16);//*/ - - memcpy(bytes, buffer + 0x56, 256); - } - } -} - - -const char * FloppyDrive::ImageName(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::IsWriteProtected(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; -} - - -int FloppyDrive::DriveLightStatus(uint8_t driveNum/*= 0*/) -{ - int retval = DLS_OFF; - - if (activeDrive != driveNum) - return DLS_OFF; - - if (ioHappened) - retval = (ioMode == IO_MODE_READ ? DLS_READ : DLS_WRITE); - - ioHappened = false; - return retval; -} - - -void FloppyDrive::SaveState(FILE * file) -{ - // Internal state vars - fputc(motorOn, file); - fputc(activeDrive, file); - fputc(ioMode, file); - fputc(latchValue, file); - fputc(phase, file); - fputc(track, file); - fputc((ioHappened ? 1 : 0), file); - WriteLong(file, currentPos); - - // Disk #1 - if (disk[0] != NULL) - { - WriteLong(file, diskSize[0]); - WriteLong(file, diskType[0]); - fputc((imageDirty[0] ? 1 : 0), file); - fputc((writeProtected[0] ? 1 : 0), file); - fwrite(nybblizedImage[0], 1, 232960, file); - fwrite(imageName[0], 1, MAX_PATH, file); - } - else - WriteLong(file, 0); - - // Disk #2 - if (disk[1] != NULL) - { - WriteLong(file, diskSize[1]); - WriteLong(file, diskType[1]); - fputc((imageDirty[1] ? 1 : 0), file); - fputc((writeProtected[1] ? 1 : 0), file); - fwrite(nybblizedImage[1], 1, 232960, file); - fwrite(imageName[1], 1, MAX_PATH, file); - } - else - WriteLong(file, 0); -} - - -void FloppyDrive::LoadState(FILE * file) -{ - // Eject images if they're loaded - EjectImage(0); - EjectImage(1); - - // Read internal state variables - motorOn = fgetc(file); - activeDrive = fgetc(file); - ioMode = fgetc(file); - latchValue = fgetc(file); - phase = fgetc(file); - track = fgetc(file); - ioHappened = (fgetc(file) == 1 ? true : false); - currentPos = ReadLong(file); - - diskSize[0] = ReadLong(file); - - if (diskSize[0]) - { - disk[0] = new uint8_t[diskSize[0]]; - diskType[0] = (uint8_t)ReadLong(file); - imageDirty[0] = (fgetc(file) == 1 ? true : false); - writeProtected[0] = (fgetc(file) == 1 ? true : false); - fread(nybblizedImage[0], 1, 232960, file); - fread(imageName[0], 1, MAX_PATH, file); - } - - diskSize[1] = ReadLong(file); - - if (diskSize[1]) - { - disk[1] = new uint8_t[diskSize[1]]; - diskType[1] = (uint8_t)ReadLong(file); - imageDirty[1] = (fgetc(file) == 1 ? true : false); - writeProtected[1] = (fgetc(file) == 1 ? true : false); - fread(nybblizedImage[1], 1, 232960, file); - fread(imageName[1], 1, MAX_PATH, file); - } -} - - -uint32_t FloppyDrive::ReadLong(FILE * file) -{ - uint32_t r = 0; - - for(int i=0; i<4; i++) - r = (r << 8) | fgetc(file); - - return r; -} - - -void FloppyDrive::WriteLong(FILE * file, uint32_t l) -{ - for(int i=0; i<4; i++) - { - fputc((l >> 24) & 0xFF, file); - l = l << 8; - } -} - - -// Memory mapped I/O functions - -/* -The DSK format is a byte-for-byte image of a 16-sector Apple II floppy disk: 35 -tracks of 16 sectors of 256 bytes each, making 143,360 bytes in total. The PO -format is exactly the same size as DSK and is also organized as 35 sequential -tracks, but the sectors within each track are in a different sequence. The NIB -format is a nybblized format: a more direct representation of the disk's data -as encoded by the Apple II floppy drive hardware. NIB contains 35 tracks of -6656 bytes each, for a total size of 232,960 bytes. Although this format is -much larger, it is also more versatile and can represent the older 13-sector -disks, many copy-protected disks, and other unusual encodings. -*/ - -void FloppyDrive::ControlStepper(uint8_t addr) -{ - // $C0E0 - 7 -/* -What I can gather here: -bits 1-2 are the "phase" of the track (which is 1/4 of a full track (?)) -bit 0 is the "do something" bit. -*/ - if (addr & 0x01) - { - 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) - phase += (phase < 79 ? 1 : 0); - - if (((phase - 1) & 0x03) == newPhase) - phase -= (phase > 0 ? 1 : 0); - - if (!(phase & 0x01)) - { - track = ((phase >> 1) < 35 ? phase >> 1 : 34); - currentPos = 0; - } -//WriteLog(" track = %u, phase = %u, newPhase = %u\n", track, phase, newPhase); -SpawnMessage("Stepping to track %u...", track); - } - -// return something if read mode... -} - - -void FloppyDrive::ControlMotor(uint8_t addr) -{ - // $C0E8 - 9 - motorOn = addr; -} - - -void FloppyDrive::DriveEnable(uint8_t addr) -{ - // $C0EA - B - activeDrive = addr; -} - - -uint8_t FloppyDrive::ReadWrite(void) -{ -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 - ioHappened = true; -/* -I think what happens here is that once a track is read its nybblized form -is fed through here, one byte at a time--which means for DO disks, we have -to convert the actual 256 byte sector to a 416 byte nybblized data "sector". -Which we now do. :-) -*/ - if (ioMode == IO_MODE_WRITE && (latchValue & 0x80)) - { - // Does it behave like this? -#warning "Write protection kludged in--investigate real behavior!" - if (writeProtected[activeDrive]) -//doesn't seem to do anything - return 0;//is this more like it? - - nybblizedImage[activeDrive][(track * 6656) + currentPos] = latchValue; - imageDirty[activeDrive] = true; - } - - uint8_t diskByte = nybblizedImage[activeDrive][(track * 6656) + currentPos]; - currentPos = (currentPos + 1) % 6656; - -//WriteLog("FL: diskByte=%02X, currentPos=%u\n", diskByte, currentPos); - return diskByte; -} - - -uint8_t FloppyDrive::GetLatchValue(void) -{ - // $C0ED - return latchValue; -} - - -void FloppyDrive::SetLatchValue(uint8_t value) -{ - // $C0ED - latchValue = value; -} - - -void FloppyDrive::SetReadMode(void) -{ - // $C0EE - ioMode = IO_MODE_READ; -} - - -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 -*/