mirror of
https://github.com/davidgiven/fluxengine.git
synced 2025-10-31 11:17:01 -07:00
Small bugfixes and added a check on the sectorskew
This commit is contained in:
@@ -16,7 +16,6 @@ static unsigned int getModulationandSpeed(uint8_t flags, bool *mfm)
|
||||
switch (flags)
|
||||
{
|
||||
case 0: /* 500 kbps FM */
|
||||
//clockRateKhz.setDefaultValue(250);
|
||||
*mfm = false;
|
||||
return 500;
|
||||
break;
|
||||
@@ -73,10 +72,9 @@ static unsigned int getSectorSize(uint8_t flags)
|
||||
case 5: return 4096;
|
||||
case 6: return 8192;
|
||||
}
|
||||
Error() << "not reachable";
|
||||
Error() << fmt::format("Sector size {} not in standard range (0-6).", flags);
|
||||
}
|
||||
|
||||
|
||||
#define SEC_CYL_MAP_FLAG 0x80
|
||||
#define SEC_HEAD_MAP_FLAG 0x40
|
||||
#define HEAD_MASK 0x3F
|
||||
@@ -92,22 +90,22 @@ public:
|
||||
|
||||
SectorSet readImage()
|
||||
/*
|
||||
IMAGE FILE FORMAT
|
||||
The overall layout of an ImageDisk .IMD image file is:
|
||||
IMD v.vv: dd/mm/yyyy hh:mm:ss
|
||||
Comment (ASCII only - unlimited size)
|
||||
1A byte - ASCII EOF character
|
||||
- For each track on the disk:
|
||||
1 byte Mode value see getModulationspeed for definition
|
||||
1 byte Cylinder
|
||||
1 byte Head
|
||||
1 byte number of sectors in track
|
||||
1 byte sector size see getsectorsize for definition
|
||||
sector numbering map
|
||||
sector cylinder map (optional) definied in high byte of head (since head is 0 or 1)
|
||||
sector head map (optional) definied in high byte of head (since head is 0 or 1)
|
||||
sector data records
|
||||
<End of file>
|
||||
*IMAGE FILE FORMAT
|
||||
*The overall layout of an ImageDisk .IMD image file is:
|
||||
*IMD v.vv: dd/mm/yyyy hh:mm:ss
|
||||
*Comment (ASCII only - unlimited size)
|
||||
*1A byte - ASCII EOF character
|
||||
*- For each track on the disk:
|
||||
*1 byte Mode value see getModulationspeed for definition
|
||||
*1 byte Cylinder
|
||||
*1 byte Head
|
||||
*1 byte number of sectors in track
|
||||
*1 byte sector size see getsectorsize for definition
|
||||
*sector numbering map
|
||||
*sector cylinder map (optional) definied in high byte of head (since head is 0 or 1)
|
||||
*sector head map (optional) definied in high byte of head (since head is 0 or 1)
|
||||
*sector data records
|
||||
*<End of file>
|
||||
*/
|
||||
{
|
||||
//Read File
|
||||
@@ -116,7 +114,7 @@ public:
|
||||
Error() << "cannot open input file";
|
||||
//define some variables
|
||||
int startSectorId = 0;
|
||||
bool mfm = false; //define coding just to show in comment for setting the right write parameters
|
||||
bool mfm = false;
|
||||
inputFile.seekg(0, inputFile.end);
|
||||
int inputFileSize = inputFile.tellg(); // determine filesize
|
||||
inputFile.seekg(0, inputFile.beg);
|
||||
@@ -125,14 +123,22 @@ public:
|
||||
ByteReader br(data);
|
||||
SectorSet sectors;
|
||||
TrackHeader header = {0, 0, 0, 0, 0};
|
||||
TrackHeader previousheader = {0, 0, 0, 0, 0};
|
||||
|
||||
unsigned n = 0;
|
||||
unsigned headerPtr = 0;
|
||||
unsigned int n = 0;
|
||||
unsigned int headerPtr = 0;
|
||||
unsigned int Modulation_Speed = 0;
|
||||
unsigned int sectorSize = 0;
|
||||
unsigned int previoussectorSize = 0;
|
||||
std::string sector_skew;
|
||||
std::string previous_sector_skew;
|
||||
previous_sector_skew.clear(); //added because fluxengine cannot handle different sector_skew in an image
|
||||
sector_skew.clear();
|
||||
uint8_t b;
|
||||
std::string comment;
|
||||
bool blnOptionalCylinderMap = false;
|
||||
bool blnOptionalHeadMap = false;
|
||||
|
||||
// Read comment
|
||||
comment.clear();
|
||||
while ((b = br.read_8()) != EOF && b != END_OF_FILE)
|
||||
@@ -143,7 +149,7 @@ public:
|
||||
headerPtr = n; //set pointer to after comment
|
||||
//write comment to screen
|
||||
std::cout << "Comment in IMD image:\n"
|
||||
<< fmt::format("{}\n",
|
||||
<< fmt::format("{}\n\n",
|
||||
comment);
|
||||
|
||||
//first read header
|
||||
@@ -176,7 +182,10 @@ public:
|
||||
for (b = 0; b < header.numSectors; b++)
|
||||
{
|
||||
optionalsector_map[b] = br.read_8();
|
||||
}
|
||||
headerPtr++;
|
||||
}
|
||||
blnOptionalCylinderMap = true; //set bool so we know there is an optional cylinder map
|
||||
header.Head = header.Head^SEC_CYL_MAP_FLAG; //remove flag 10000001 ^ 10000000 = 00000001 and 10000000 ^ 10000000 = 00000000
|
||||
}
|
||||
//Read optional sector head map
|
||||
//The Sector Head Map has one entry for each sector, and contains the logical Head ID for the corresponding sector in the Sector Numbering Map.
|
||||
@@ -187,18 +196,22 @@ public:
|
||||
for (b = 0; b < header.numSectors; b++)
|
||||
{
|
||||
optionalhead_map[b] = br.read_8();
|
||||
}
|
||||
headerPtr++;
|
||||
}
|
||||
blnOptionalHeadMap = true; //set bool so we know there is an optional head map
|
||||
header.Head = header.Head^SEC_HEAD_MAP_FLAG; //remove flag 01000001 ^ 01000001 = 00000001 and 01000000 ^ 0100000 = 00000000 for writing sector head later
|
||||
}
|
||||
|
||||
//read sector numbering map
|
||||
unsigned int sector_map[header.numSectors];
|
||||
sector_skew.clear();
|
||||
for (b = 0; b < header.numSectors; b++)
|
||||
{
|
||||
sector_map[b] = br.read_8();
|
||||
headerPtr++;
|
||||
if (b == 0) //first sector see if base is 0 or 1 Fluxengine wants 0
|
||||
{
|
||||
startSectorId = sector_map[b];
|
||||
// startSectorId = sector_map[b]; //the start sectorID is for IBM disks always 1. so while we can only write IBM disks with IMD set this default to 1
|
||||
startSectorId = 1; //the start sectorID is for IBM disks is always 1. so while we can only write IBM disks with IMD set this default to 1
|
||||
if (sector_map[b]==1)
|
||||
{
|
||||
blnBaseOne = true;
|
||||
@@ -209,108 +222,146 @@ public:
|
||||
sector_map[b] = (sector_map[b]-1);
|
||||
}
|
||||
sector_skew.push_back(sector_map[b] + '0');
|
||||
headerPtr++;
|
||||
}
|
||||
//read the sectors
|
||||
for (int s = 0; s < header.numSectors; s++)
|
||||
if ((header.Head == 0) and (header.track == 0)) //first read set previous sector skew
|
||||
{
|
||||
Bytes sectordata;
|
||||
std::unique_ptr<Sector>& sector = sectors.get(header.track, header.Head, sector_map[s]);
|
||||
sector.reset(new Sector);
|
||||
//read the status of the sector
|
||||
unsigned int Status_Sector = br.read_8();
|
||||
headerPtr++;
|
||||
|
||||
switch (Status_Sector)
|
||||
{
|
||||
case 0: /* Sector data unavailable - could not be read */
|
||||
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
break;
|
||||
|
||||
case 1: /* Normal data: (Sector Size) bytes follow */
|
||||
sectordata = br.read(sectorSize);
|
||||
headerPtr += sectorSize;
|
||||
sector->data.writer().append(sectordata);
|
||||
sector->status = Sector::OK;
|
||||
break;
|
||||
|
||||
case 2: /* Compressed: All bytes in sector have same value (xx) */
|
||||
sectordata = br.read(1);
|
||||
headerPtr++;
|
||||
sector->data.writer().append(sectordata);
|
||||
sector->status = Sector::OK;
|
||||
for (int k = 1; k < sectorSize; k++)
|
||||
{
|
||||
//fill data till sector is full
|
||||
sector->data.writer().append(sectordata);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 3: /* Normal data with "Deleted-Data address mark" */
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 4: /* Compressed with "Deleted-Data address mark"*/
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 5: /* Normal data read with data error - could not be read*/
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 6: /* Compressed read with data error - could not be read */
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 7: /* Deleted data read with data error - could not be read */
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 8: /* Compressed, Deleted read with data error - could not be read */
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
Error() << fmt::format("don't understand IMD disks with sector status {}", Status_Sector);
|
||||
}
|
||||
if (header.Head & SEC_CYL_MAP_FLAG)
|
||||
//The Sector Cylinder Map has one entry for each sector, and contains the logical Cylinder ID for the corresponding sector in the Sector Numbering Map.
|
||||
{
|
||||
sector->physicalTrack = header.track;
|
||||
sector->logicalTrack = optionalsector_map[s];
|
||||
}
|
||||
else {
|
||||
|
||||
sector->logicalTrack = sector->physicalTrack = header.track;
|
||||
}
|
||||
if (header.Head & SEC_HEAD_MAP_FLAG)
|
||||
//The Sector Head Map has one entry for each sector, and contains the logical Head ID for the corresponding sector in the Sector Numbering Map.
|
||||
{
|
||||
sector->physicalSide = header.Head;
|
||||
sector->logicalSide = optionalhead_map[s];
|
||||
}
|
||||
else {
|
||||
sector->logicalSide = sector->physicalSide = header.Head;
|
||||
}
|
||||
sector->logicalSector = (sector_map[s]);
|
||||
previous_sector_skew = sector_skew;
|
||||
previousheader = header;
|
||||
previoussectorSize = sectorSize;
|
||||
}
|
||||
if (!sector_skew.compare(previous_sector_skew) == 0)
|
||||
{
|
||||
/* Get the previous information and give a warning
|
||||
* I had a problem with DD disks written in HP-LIF format and consisting of only 76 tracks. When i read them, the default is 79 tracks so there are 3 tracks in the normal IBM DD format.
|
||||
* to make it easier for the user (not having to specify all the tracks he/she wants) i wrote this.
|
||||
* the IMD image generated is capable of storing different sector skews per track but fluxengine specifies the sector_skew for IBM disks for the whole image at once
|
||||
*/
|
||||
std::cout << fmt::format("\nWarning as of track {} there is a different sectorskew. New sectorskew {}, old sectorskew {}.\nFluxengine can't write IMD images back to disk with a different sectorskew.\nIgnoring rest of image as of track {}. \n\n",
|
||||
header.track, sector_skew, previous_sector_skew, header.track);
|
||||
|
||||
header = previousheader;
|
||||
sector_skew = previous_sector_skew;
|
||||
sectorSize = previoussectorSize;
|
||||
break;
|
||||
} else
|
||||
{
|
||||
//read the sectors
|
||||
for (int s = 0; s < header.numSectors; s++)
|
||||
{
|
||||
Bytes sectordata;
|
||||
Bytes compressed(sectorSize);
|
||||
std::unique_ptr<Sector>& sector = sectors.get(header.track, header.Head, sector_map[s]);
|
||||
sector.reset(new Sector);
|
||||
//read the status of the sector
|
||||
unsigned int Status_Sector = br.read_8();
|
||||
headerPtr++;
|
||||
|
||||
switch (Status_Sector)
|
||||
{
|
||||
/*fluxengine knows of a few sector statussen but not all of the statussen in IMD.
|
||||
* // the statussen are in sector.h. Translation to fluxengine is as follows:
|
||||
* Statussen fluxengine | Status IMD
|
||||
*--------------------------------------------------------------------------------------------------------------------
|
||||
* OK, | 1, 2 (Normal data: (Sector Size) of (compressed) bytes follow)
|
||||
* BAD_CHECKSUM, |
|
||||
* MISSING, sector not found | 0 (Sector data unavailable - could not be read)
|
||||
* DATA_MISSING, sector present but no data found | 3, 4, 5, 6, 7, 8
|
||||
* CONFLICT, |
|
||||
* INTERNAL_ERROR |
|
||||
*/
|
||||
case 0: /* Sector data unavailable - could not be read */
|
||||
|
||||
sector->status = Sector::MISSING;
|
||||
break;
|
||||
|
||||
case 1: /* Normal data: (Sector Size) bytes follow */
|
||||
sectordata = br.read(sectorSize);
|
||||
headerPtr += sectorSize;
|
||||
sector->data = sectordata;
|
||||
sector->status = Sector::OK;
|
||||
break;
|
||||
|
||||
case 2: /* Compressed: All bytes in sector have same value (xx) */
|
||||
compressed[0] = br.read_8();
|
||||
headerPtr++;
|
||||
for (int k = 1; k < sectorSize; k++)
|
||||
{
|
||||
//fill data till sector is full
|
||||
br.seek(headerPtr);
|
||||
compressed[k] = br.read_8();
|
||||
}
|
||||
sector->data = compressed;
|
||||
sector->status = Sector::OK;
|
||||
break;
|
||||
|
||||
case 3: /* Normal data with "Deleted-Data address mark" */
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 4: /* Compressed with "Deleted-Data address mark"*/
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 5: /* Normal data read with data error - could not be read*/
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 6: /* Compressed read with data error - could not be read */
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 7: /* Deleted data read with data error - could not be read */
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
case 8: /* Compressed, Deleted read with data error - could not be read */
|
||||
sector->status = Sector::DATA_MISSING;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
Error() << fmt::format("Don't understand IMD disks with sector status {}", Status_Sector);
|
||||
}
|
||||
if (blnOptionalCylinderMap) //there was een optional cylinder map. write is to the sector
|
||||
//The Sector Cylinder Map has one entry for each sector, and contains the logical Cylinder ID for the corresponding sector in the Sector Numbering Map.
|
||||
{
|
||||
sector->physicalTrack = header.track;
|
||||
sector->logicalTrack = optionalsector_map[s];
|
||||
blnOptionalCylinderMap = false;
|
||||
}
|
||||
else {
|
||||
|
||||
sector->logicalTrack = sector->physicalTrack = header.track;
|
||||
}
|
||||
if (blnOptionalHeadMap) //there was een optional head map. write is to the sector
|
||||
//The Sector Head Map has one entry for each sector, and contains the logical Head ID for the corresponding sector in the Sector Numbering Map.
|
||||
{
|
||||
sector->physicalSide = header.Head;
|
||||
sector->logicalSide = optionalhead_map[s];
|
||||
blnOptionalHeadMap = false;
|
||||
}
|
||||
else {
|
||||
sector->logicalSide = sector->physicalSide = header.Head;
|
||||
}
|
||||
sector->logicalSector = (sector_map[s]);
|
||||
previous_sector_skew = sector_skew;
|
||||
previousheader = header;
|
||||
sectorSize = previoussectorSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
//Write format detected in IMD image to screen to help user set the right write parameters in case of failures
|
||||
size_t headSize = header.numSectors * sectorSize;
|
||||
size_t trackSize = headSize * (header.Head + 1);
|
||||
size_t headSize = ((header.numSectors) * (sectorSize));
|
||||
size_t trackSize = (headSize * (header.Head + 1));
|
||||
|
||||
std::cout << "reading IMD image\n"
|
||||
std::cout << "Reading IMD image\n"
|
||||
<< fmt::format("{} tracks, {} heads; {}; {} kbps; {} sectoren; sectorsize {}; sectormap {}; {} kB total \n",
|
||||
header.track, header.Head + 1,
|
||||
header.track + 1, header.Head + 1,
|
||||
mfm ? "MFM" : "FM",
|
||||
Modulation_Speed, header.numSectors, sectorSize, sector_skew, (header.track+1) * trackSize / 1024);
|
||||
|
||||
@@ -329,23 +380,17 @@ public:
|
||||
IbmEncoder::setclockRateKhz(Modulation_Speed);
|
||||
IbmEncoder::setsectorSkew(fmt::format(sector_skew));
|
||||
|
||||
//set the rest with the deault (IBM) parameters (because no option was set all these are not filled)
|
||||
//set the rest with the default (IBM) parameters (because no option was set all these are not filled)
|
||||
//First check if these settings have been set bij een flag from the user or we will overwrite them
|
||||
//if gap3 ==0 then not initialised so initialise the rest
|
||||
|
||||
if (IbmEncoder::getgap3() == 0)
|
||||
{
|
||||
IbmEncoder::settrackLengthMs(200);
|
||||
IbmEncoder::setemitIam(true);
|
||||
IbmEncoder::setidamByte(0x5554);
|
||||
IbmEncoder::setdamByte(0x5545);
|
||||
IbmEncoder::setgap0(80);
|
||||
IbmEncoder::setgap1(50);
|
||||
IbmEncoder::setgap2(22);
|
||||
IbmEncoder::setgap3(80);
|
||||
IbmEncoder::setswapSides(false);
|
||||
}
|
||||
|
||||
if (IbmEncoder::gettrackLengthMs() == 0) IbmEncoder::settrackLengthMs(200);
|
||||
if (IbmEncoder::getemitIam() == false) IbmEncoder::setemitIam(true);
|
||||
if (IbmEncoder::getidamByte() == 0) IbmEncoder::setidamByte(0x5554);
|
||||
if (IbmEncoder::getdamByte() == 0) IbmEncoder::setdamByte(0x5545);
|
||||
if (IbmEncoder::getgap0() == 0) IbmEncoder::setgap0(80);
|
||||
if (IbmEncoder::getgap1() == 0) IbmEncoder::setgap1(50);
|
||||
if (IbmEncoder::getgap2() == 0) IbmEncoder::setgap2(22);
|
||||
if (IbmEncoder::getgap3() == 0) IbmEncoder::setgap3(80);
|
||||
if (IbmEncoder::getswapSides() == false) IbmEncoder::setswapSides(false);
|
||||
return sectors;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user