bool SoftSectoredDisk::readIMD(const char* name) { std::ifstream file; unsigned long int fileSize; unsigned long int pos = 0; BYTE* buf; debugss(ssFloppyDisk, INFO, "file: %s\n", name); file.open(name, std::ios::binary); file.seekg(0, std::ios::end); fileSize = file.tellg(); file.seekg(0, std::ios::beg); buf = new BYTE[fileSize]; file.read((char*) buf, fileSize); file.close(); while (buf[pos] != 0x1a) { if (pos == fileSize) { delete [] buf; return (false); } } // get past the EOF character. pos++; BYTE sectorOrder[256]; BYTE sectorCylMapping[256]; BYTE sectorHeadMapping[256]; unsigned char mode, cyl, head, numSec, sectorSizeKey; int sectorSize; bool sectorCylMap, sectorHeadMap; Track::Density density; Track::DataRate dataRate; do { // mode mode = buf[pos++]; switch (mode) { case 0: density = Track::singleDensity; dataRate = Track::dr_500kbps; debugss(ssFloppyDisk, INFO, "FM/500 kbps\n"); break; case 1: density = Track::singleDensity; dataRate = Track::dr_300kbps; debugss(ssFloppyDisk, INFO, "FM/300 kbps\n"); break; case 2: density = Track::singleDensity; dataRate = Track::dr_250kbps; debugss(ssFloppyDisk, INFO, "FM/250 kbps\n"); break; case 3: density = Track::doubleDensity; dataRate = Track::dr_500kbps; debugss(ssFloppyDisk, INFO, "MFM/500 kbps\n"); break; case 4: density = Track::doubleDensity; dataRate = Track::dr_300kbps; debugss(ssFloppyDisk, INFO, "MFM/300 kbps\n"); break; case 5: density = Track::doubleDensity; dataRate = Track::dr_250kbps; debugss(ssFloppyDisk, INFO, "MFM/250 kbps\n"); break; default: density = Track::density_Unknown; dataRate = Track::dr_Unknown; debugss(ssFloppyDisk, WARNING, "Unknown density/data rate: %d\n", mode); break; } cyl = buf[pos++]; debugss(ssFloppyDisk, ALL, "Cylinder: %d\n", cyl); head = buf[pos++]; // Check flags. sectorCylMap = ((head & 0x80) != 0); sectorHeadMap = ((head & 0x40) != 0); // mask off any flags head &= 1; debugss(ssFloppyDisk, ALL, "Head: %d\n", head); Track* trk = new Track(head, cyl); numSec = buf[pos++]; debugss(ssFloppyDisk, ALL, "Num Sectors: %d\n", numSec); sectorSizeKey = buf[pos++]; if (sectorSizeKey < 7) { sectorSize = 1 << (sectorSizeKey + 7); } else { debugss(ssFloppyDisk, ERROR, "Sector Size unknown: %d\n", sectorSizeKey); delete [] buf; delete trk; return (false); } debugss(ssFloppyDisk, ALL, "Sector Size: %d (%d)\n", sectorSize, sectorSizeKey); for (int i = 0; i < numSec; i++) { sectorOrder[i] = buf[pos++]; } if (sectorCylMap) { debugss(ssFloppyDisk, INFO, "Sector Cylinder Map Present\n"); for (int i = 0; i < numSec; i++) { sectorCylMapping[i] = buf[pos++]; } } if (sectorHeadMap) { debugss(ssFloppyDisk, INFO, "Sector Head Map Present\n"); for (int i = 0; i < numSec; i++) { sectorHeadMapping[i] = buf[pos++]; } } for (int i = 0; i < numSec; i++) { unsigned char sectorType = buf[pos++]; debugss(ssFloppyDisk, INFO, "Sector: %d(%d) Type: %d\n", sectorOrder[i], i, sectorType); if (sectorType == 0x00) { // Sector Data Unavailable debugss(ssFloppyDisk, INFO, "Sector Size unknown: %d\n", sectorSizeKey); } else if (sectorType > 0x08) { // Out of Range. debugss(ssFloppyDisk, ERROR, "Out of Range: %d\n", sectorType); delete [] buf; return false; } else { BYTE type = sectorType - 1; bool compressed = ((type & 0x01) != 0); bool deleteData = ((type & 0x02) != 0); bool dataError = ((type & 0x04) != 0); BYTE sectorData[sectorSize]; if (compressed) { BYTE val = buf[pos++]; for (int i = 0; i < sectorSize; i++) { sectorData[i] = val; } } else { for (int i = 0; i < sectorSize; i++) { sectorData[i] = buf[pos++]; } } // create sector Sector* sect = new Sector(head, cyl, sectorOrder[i], sectorSize, sectorData); // set flags sect->setReadError(dataError); sect->setDeletedDataAddressMark(deleteData); // add sector to track trk->addSector(sect); } } // add track to disk tracks_m[head].push_back(trk); } while (pos < fileSize); delete [] buf; debugss(ssFloppyDisk, INFO, "Read successful.\n"); return true; }