]> Shamusworld >> Repos - apple2/blobdiff - src/floppy.cpp
Added Prodos detection for .dsk images, fixes to 80STORE switch.
[apple2] / src / floppy.cpp
index 193e5cb5bd734cae90cb9a4d00ec20158fe1c49e..61230aef1b18d462de5dbd975baa3761dabd0d2a 100755 (executable)
@@ -1,10 +1,10 @@
 //
 // Apple 2 floppy disk support
 //
-// by James L. Hammons
+// by James Hammons
 // (c) 2005 Underground Software
 //
-// JLH = James L. Hammons <jlhamm@acm.org>
+// JLH = James Hammons <jlhamm@acm.org>
 //
 // WHO  WHEN        WHAT
 // ---  ----------  ------------------------------------------------------------
@@ -39,6 +39,7 @@ 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)
@@ -51,6 +52,7 @@ FloppyDrive::FloppyDrive(): motorOn(0), activeDrive(0), ioMode(IO_MODE_READ), ph
        imageName[0][0] = imageName[1][0] = 0;                  // Zero out filenames
 }
 
+
 FloppyDrive::~FloppyDrive()
 {
        if (disk[0])
@@ -60,6 +62,7 @@ FloppyDrive::~FloppyDrive()
                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);
@@ -112,6 +115,7 @@ bool FloppyDrive::LoadImage(const char * filename, uint8_t driveNum/*= 0*/)
        return true;
 }
 
+
 bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/)
 {
        if (driveNum > 1)
@@ -153,6 +157,7 @@ bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/)
        return true;
 }
 
+
 bool FloppyDrive::SaveImageAs(const char * filename, uint8_t driveNum/*= 0*/)
 {
 //WARNING: Buffer overflow possibility
@@ -161,6 +166,7 @@ bool FloppyDrive::SaveImageAs(const char * filename, uint8_t driveNum/*= 0*/)
        return SaveImage(driveNum);
 }
 
+
 void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/)
 {
        if (disk[driveNum] != NULL)
@@ -176,6 +182,7 @@ void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/)
 SpawnMessage("New blank image inserted in drive %u...", driveNum);
 }
 
+
 void FloppyDrive::SwapImages(void)
 {
        uint8_t nybblizedImageTmp[232960];
@@ -211,6 +218,7 @@ void FloppyDrive::SwapImages(void)
 SpawnMessage("Drive 0: %s...", imageName[0]);
 }
 
+
 void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum)
 {
        diskType[driveNum] = DT_UNKNOWN;
@@ -229,35 +237,46 @@ void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum)
 WriteLog("FLOPPY: Found extension [%s]...\n", ext);
 
 //Apparently .dsk can house either DOS order OR PRODOS order... !!! FIX !!!
-//[DONE, see below why we don't need it]
                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;
-//WriteLog("Detected DOS 3.3 disk!\n");
-/*
-This doesn't seem to be accurate... Maybe it's just a ProDOS disk in a DOS33 order...
-That would seem to be the case--just because it's a ProDOS disk doesn't mean anything
-WRT to the disk image itself.
-                       // This could really be a ProDOS order disk with a .dsk extension, so let's see...
-                       char fingerprint[3][4] = {
-                               { 0x04, 0x00, 0x00, 0x00 },             // @ $500
-                               { 0x03, 0x00, 0x05, 0x00 },             // @ $700
-                               { 0x02, 0x00, 0x04, 0x00 } };   // @ $900
-
-                       if ((strcmp((char *)(disk[driveNum] + 0x500), fingerprint[0]) == 0)
-                               && (strcmp((char *)(disk[driveNum] + 0x700), fingerprint[1]) == 0)
-                               && (strcmp((char *)(disk[driveNum] + 0x900), fingerprint[2]) == 0))
+
+                       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
-// Here, we check for BT3
-//Nope, no change...
-//diskType[driveNum] = DT_PRODOS;
-
+// (and, it does... :-P)
+               NybblizeImage(driveNum);
+       }
+       else if (diskSize[driveNum] == 143488)
+       {
+               diskType[driveNum] = DT_DOS33_HDR;
                NybblizeImage(driveNum);
        }
 
@@ -265,9 +284,11 @@ WRT to the disk image itself.
 
 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"))));
+       "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
@@ -319,6 +340,8 @@ void FloppyDrive::NybblizeImage(uint8_t 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
@@ -371,6 +394,7 @@ WriteLog("FL: i = %u, img[i] = %02X, diskbyte = %02X\n", i, img[i], diskbyte[img
        }
 }
 
+
 void FloppyDrive::DenybblizeImage(uint8_t driveNum)
 {
        uint8_t decodeNybble[0x80] = {
@@ -462,6 +486,8 @@ void FloppyDrive::DenybblizeImage(uint8_t 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
@@ -472,6 +498,7 @@ void FloppyDrive::DenybblizeImage(uint8_t driveNum)
        }
 }
 
+
 const char * FloppyDrive::GetImageName(uint8_t driveNum/*= 0*/)
 {
        // Set up a zero-length string for return value
@@ -508,6 +535,7 @@ const char * FloppyDrive::GetImageName(uint8_t driveNum/*= 0*/)
        return nameBuf;
 }
 
+
 void FloppyDrive::EjectImage(uint8_t driveNum/*= 0*/)
 {
        // Probably want to save a dirty image... ;-)
@@ -527,6 +555,7 @@ void FloppyDrive::EjectImage(uint8_t driveNum/*= 0*/)
        memset(nybblizedImage[driveNum], 0xFF, 232960); // Doesn't matter if 00s or FFs...
 }
 
+
 bool FloppyDrive::DriveIsEmpty(uint8_t driveNum/*= 0*/)
 {
        if (driveNum > 1)
@@ -539,6 +568,7 @@ bool FloppyDrive::DriveIsEmpty(uint8_t driveNum/*= 0*/)
        return (imageName[driveNum][0] == 0 ? true : false);
 }
 
+
 bool FloppyDrive::DiskIsWriteProtected(uint8_t driveNum/*= 0*/)
 {
        if (driveNum > 1)
@@ -550,6 +580,7 @@ bool FloppyDrive::DiskIsWriteProtected(uint8_t driveNum/*= 0*/)
        return writeProtected[driveNum];
 }
 
+
 void FloppyDrive::SetWriteProtect(bool state, uint8_t driveNum/*= 0*/)
 {
        if (driveNum > 1)
@@ -606,18 +637,21 @@ 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,
@@ -651,24 +685,28 @@ Which we now do. :-)
        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