//
// 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
// --- ---------- ------------------------------------------------------------
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)
imageName[0][0] = imageName[1][0] = 0; // Zero out filenames
}
+
FloppyDrive::~FloppyDrive()
{
if (disk[0])
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);
return true;
}
+
bool FloppyDrive::SaveImage(uint8_t driveNum/*= 0*/)
{
if (driveNum > 1)
return true;
}
+
bool FloppyDrive::SaveImageAs(const char * filename, uint8_t driveNum/*= 0*/)
{
//WARNING: Buffer overflow possibility
return SaveImage(driveNum);
}
+
void FloppyDrive::CreateBlankImage(uint8_t driveNum/*= 0*/)
{
if (disk[driveNum] != NULL)
SpawnMessage("New blank image inserted in drive %u...", driveNum);
}
+
void FloppyDrive::SwapImages(void)
{
uint8_t nybblizedImageTmp[232960];
SpawnMessage("Drive 0: %s...", imageName[0]);
}
+
void FloppyDrive::DetectImageType(const char * filename, uint8_t driveNum)
{
diskType[driveNum] = DT_UNKNOWN;
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);
}
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
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
}
}
+
void FloppyDrive::DenybblizeImage(uint8_t driveNum)
{
uint8_t decodeNybble[0x80] = {
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
}
}
+
const char * FloppyDrive::GetImageName(uint8_t driveNum/*= 0*/)
{
// Set up a zero-length string for return value
return nameBuf;
}
+
void FloppyDrive::EjectImage(uint8_t driveNum/*= 0*/)
{
// Probably want to save a dirty image... ;-)
memset(nybblizedImage[driveNum], 0xFF, 232960); // Doesn't matter if 00s or FFs...
}
+
bool FloppyDrive::DriveIsEmpty(uint8_t driveNum/*= 0*/)
{
if (driveNum > 1)
return (imageName[driveNum][0] == 0 ? true : false);
}
+
bool FloppyDrive::DiskIsWriteProtected(uint8_t driveNum/*= 0*/)
{
if (driveNum > 1)
return writeProtected[driveNum];
}
+
void FloppyDrive::SetWriteProtect(bool state, uint8_t driveNum/*= 0*/)
{
if (driveNum > 1)
// 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,
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