mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Enable reading dicformat that skip storing CD prefixes and suffixes.
This commit is contained in:
@@ -32,6 +32,7 @@
|
|||||||
// ****************************************************************************/
|
// ****************************************************************************/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using DiscImageChef.CommonTypes.Enums;
|
||||||
|
|
||||||
namespace DiscImageChef.DiscImages
|
namespace DiscImageChef.DiscImages
|
||||||
{
|
{
|
||||||
@@ -58,11 +59,11 @@ namespace DiscImageChef.DiscImages
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SuffixIsCorrect(byte[] channel)
|
bool SuffixIsCorrect(byte[] sector)
|
||||||
{
|
{
|
||||||
if(channel[0x814] != 0x00 || // reserved (8 bytes)
|
if(sector[0x814] != 0x00 || // reserved (8 bytes)
|
||||||
channel[0x815] != 0x00 || channel[0x816] != 0x00 || channel[0x817] != 0x00 || channel[0x818] != 0x00 ||
|
sector[0x815] != 0x00 || sector[0x816] != 0x00 || sector[0x817] != 0x00 || sector[0x818] != 0x00 ||
|
||||||
channel[0x819] != 0x00 || channel[0x81A] != 0x00 || channel[0x81B] != 0x00) return false;
|
sector[0x819] != 0x00 || sector[0x81A] != 0x00 || sector[0x81B] != 0x00) return false;
|
||||||
|
|
||||||
byte[] address = new byte[4];
|
byte[] address = new byte[4];
|
||||||
byte[] data = new byte[2060];
|
byte[] data = new byte[2060];
|
||||||
@@ -70,11 +71,11 @@ namespace DiscImageChef.DiscImages
|
|||||||
byte[] eccP = new byte[172];
|
byte[] eccP = new byte[172];
|
||||||
byte[] eccQ = new byte[104];
|
byte[] eccQ = new byte[104];
|
||||||
|
|
||||||
Array.Copy(channel, 0x0C, address, 0, 4);
|
Array.Copy(sector, 0x0C, address, 0, 4);
|
||||||
Array.Copy(channel, 0x10, data, 0, 2060);
|
Array.Copy(sector, 0x10, data, 0, 2060);
|
||||||
Array.Copy(channel, 0x10, data2, 0, 2232);
|
Array.Copy(sector, 0x10, data2, 0, 2232);
|
||||||
Array.Copy(channel, 0x81C, eccP, 0, 172);
|
Array.Copy(sector, 0x81C, eccP, 0, 172);
|
||||||
Array.Copy(channel, 0x8C8, eccQ, 0, 104);
|
Array.Copy(sector, 0x8C8, eccQ, 0, 104);
|
||||||
|
|
||||||
bool correctEccP = CheckEcc(ref address, ref data, 86, 24, 2, 86, ref eccP);
|
bool correctEccP = CheckEcc(ref address, ref data, 86, 24, 2, 86, ref eccP);
|
||||||
if(!correctEccP) return false;
|
if(!correctEccP) return false;
|
||||||
@@ -82,11 +83,11 @@ namespace DiscImageChef.DiscImages
|
|||||||
bool correctEccQ = CheckEcc(ref address, ref data2, 52, 43, 86, 88, ref eccQ);
|
bool correctEccQ = CheckEcc(ref address, ref data2, 52, 43, 86, 88, ref eccQ);
|
||||||
if(!correctEccQ) return false;
|
if(!correctEccQ) return false;
|
||||||
|
|
||||||
uint storedEdc = BitConverter.ToUInt32(channel, 0x810);
|
uint storedEdc = BitConverter.ToUInt32(sector, 0x810);
|
||||||
uint edc = 0;
|
uint edc = 0;
|
||||||
int size = 0x810;
|
int size = 0x810;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
for(; size > 0; size--) edc = (edc >> 8) ^ edcTable[(edc ^ channel[pos++]) & 0xFF];
|
for(; size > 0; size--) edc = (edc >> 8) ^ edcTable[(edc ^ sector[pos++]) & 0xFF];
|
||||||
uint calculatedEdc = edc;
|
uint calculatedEdc = edc;
|
||||||
|
|
||||||
return calculatedEdc == storedEdc;
|
return calculatedEdc == storedEdc;
|
||||||
@@ -119,5 +120,171 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WriteEcc(byte[] address, byte[] data, uint majorCount, uint minorCount, uint majorMult,
|
||||||
|
uint minorInc,
|
||||||
|
ref byte[] ecc, int addressOffset, int dataOffset, int eccOffset)
|
||||||
|
{
|
||||||
|
uint size = majorCount * minorCount;
|
||||||
|
uint major;
|
||||||
|
for(major = 0; major < majorCount; major++)
|
||||||
|
{
|
||||||
|
uint idx = (major >> 1) * majorMult + (major & 1);
|
||||||
|
byte eccA = 0;
|
||||||
|
byte eccB = 0;
|
||||||
|
uint minor;
|
||||||
|
for(minor = 0; minor < minorCount; minor++)
|
||||||
|
{
|
||||||
|
byte temp = idx < 4 ? address[idx + addressOffset] : data[idx + dataOffset - 4];
|
||||||
|
idx += minorInc;
|
||||||
|
if(idx >= size) idx -= size;
|
||||||
|
eccA ^= temp;
|
||||||
|
eccB ^= temp;
|
||||||
|
eccA = eccFTable[eccA];
|
||||||
|
}
|
||||||
|
|
||||||
|
eccA = eccBTable[eccFTable[eccA] ^ eccB];
|
||||||
|
ecc[major + eccOffset] = eccA;
|
||||||
|
ecc[major + majorCount + eccOffset] = (byte)(eccA ^ eccB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EccWriteSector(byte[] address, byte[] data, ref byte[] ecc, int addressOffset, int dataOffset,
|
||||||
|
int eccOffset)
|
||||||
|
{
|
||||||
|
WriteEcc(address, data, 86, 24, 2, 86, ref ecc, addressOffset, dataOffset, eccOffset); // P
|
||||||
|
WriteEcc(address, data, 52, 43, 86, 88, ref ecc, addressOffset, dataOffset, eccOffset + 0xAC); // Q
|
||||||
|
}
|
||||||
|
|
||||||
|
static (byte minute, byte second, byte frame) LbaToMsf(long pos)
|
||||||
|
{
|
||||||
|
return ((byte)((pos + 150) / 75 / 60), (byte)((pos + 150) / 75 % 60), (byte)((pos + 150) % 75));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReconstructPrefix(ref byte[] sector, // must point to a full 2352-byte sector
|
||||||
|
TrackType type, long lba)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Sync
|
||||||
|
//
|
||||||
|
sector[0x000] = 0x00;
|
||||||
|
sector[0x001] = 0xFF;
|
||||||
|
sector[0x002] = 0xFF;
|
||||||
|
sector[0x003] = 0xFF;
|
||||||
|
sector[0x004] = 0xFF;
|
||||||
|
sector[0x005] = 0xFF;
|
||||||
|
sector[0x006] = 0xFF;
|
||||||
|
sector[0x007] = 0xFF;
|
||||||
|
sector[0x008] = 0xFF;
|
||||||
|
sector[0x009] = 0xFF;
|
||||||
|
sector[0x00A] = 0xFF;
|
||||||
|
sector[0x00B] = 0x00;
|
||||||
|
|
||||||
|
(byte minute, byte second, byte frame) msf = LbaToMsf(lba);
|
||||||
|
|
||||||
|
sector[0x00C] = (byte)(((msf.minute / 10) << 4) + msf.minute % 10);
|
||||||
|
sector[0x00D] = (byte)(((msf.second / 10) << 4) + msf.second % 10);
|
||||||
|
sector[0x00E] = (byte)(((msf.frame / 10) << 4) + msf.frame % 10);
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case TrackType.CdMode1:
|
||||||
|
//
|
||||||
|
// Mode
|
||||||
|
//
|
||||||
|
sector[0x00F] = 0x01;
|
||||||
|
break;
|
||||||
|
case TrackType.CdMode2Form1:
|
||||||
|
case TrackType.CdMode2Form2:
|
||||||
|
case TrackType.CdMode2Formless:
|
||||||
|
//
|
||||||
|
// Mode
|
||||||
|
//
|
||||||
|
sector[0x00F] = 0x02;
|
||||||
|
//
|
||||||
|
// Flags
|
||||||
|
//
|
||||||
|
sector[0x010] = sector[0x014];
|
||||||
|
sector[0x011] = sector[0x015];
|
||||||
|
sector[0x012] = sector[0x016];
|
||||||
|
sector[0x013] = sector[0x017];
|
||||||
|
break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReconstructEcc(ref byte[] sector, // must point to a full 2352-byte sector
|
||||||
|
TrackType type)
|
||||||
|
{
|
||||||
|
byte[] computedEdc;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Compute EDC
|
||||||
|
//
|
||||||
|
case TrackType.CdMode1:
|
||||||
|
computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x810));
|
||||||
|
sector[0x810] = computedEdc[0];
|
||||||
|
sector[0x811] = computedEdc[1];
|
||||||
|
sector[0x812] = computedEdc[2];
|
||||||
|
sector[0x813] = computedEdc[3];
|
||||||
|
break;
|
||||||
|
case TrackType.CdMode2Form1:
|
||||||
|
computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x808, 0x10));
|
||||||
|
sector[0x818] = computedEdc[0];
|
||||||
|
sector[0x819] = computedEdc[1];
|
||||||
|
sector[0x81A] = computedEdc[2];
|
||||||
|
sector[0x81B] = computedEdc[3];
|
||||||
|
break;
|
||||||
|
case TrackType.CdMode2Form2:
|
||||||
|
computedEdc = BitConverter.GetBytes(ComputeEdc(0, sector, 0x91C, 0x10));
|
||||||
|
sector[0x92C] = computedEdc[0];
|
||||||
|
sector[0x92D] = computedEdc[1];
|
||||||
|
sector[0x92E] = computedEdc[2];
|
||||||
|
sector[0x92F] = computedEdc[3];
|
||||||
|
break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] zeroaddress = new byte[4];
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Compute ECC
|
||||||
|
//
|
||||||
|
case TrackType.CdMode1:
|
||||||
|
//
|
||||||
|
// Reserved
|
||||||
|
//
|
||||||
|
sector[0x814] = 0x00;
|
||||||
|
sector[0x815] = 0x00;
|
||||||
|
sector[0x816] = 0x00;
|
||||||
|
sector[0x817] = 0x00;
|
||||||
|
sector[0x818] = 0x00;
|
||||||
|
sector[0x819] = 0x00;
|
||||||
|
sector[0x81A] = 0x00;
|
||||||
|
sector[0x81B] = 0x00;
|
||||||
|
EccWriteSector(sector, sector, ref sector, 0xC, 0x10, 0x81C);
|
||||||
|
break;
|
||||||
|
case TrackType.CdMode2Form1:
|
||||||
|
EccWriteSector(zeroaddress, sector, ref sector, 0, 0x10, 0x81C);
|
||||||
|
break;
|
||||||
|
default: return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Done
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
uint ComputeEdc(uint edc, byte[] src, int size, int srcOffset = 0)
|
||||||
|
{
|
||||||
|
int pos = srcOffset;
|
||||||
|
for(; size > 0; size--) edc = (edc >> 8) ^ edcTable[(edc ^ src[pos++]) & 0xFF];
|
||||||
|
|
||||||
|
return edc;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -388,6 +388,9 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
for(ulong i = 0; i < ddtHeader.entries; i++)
|
for(ulong i = 0; i < ddtHeader.entries; i++)
|
||||||
cdDdt[i] = BitConverter.ToUInt32(decompressedDdt, (int)(i * sizeof(uint)));
|
cdDdt[i] = BitConverter.ToUInt32(decompressedDdt, (int)(i * sizeof(uint)));
|
||||||
|
|
||||||
|
if(entry.dataType == DataType.CdSectorPrefixCorrected) sectorPrefixDdt = cdDdt;
|
||||||
|
else if(entry.dataType == DataType.CdSectorSuffixCorrected) sectorSuffixDdt = cdDdt;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -903,7 +906,10 @@ namespace DiscImageChef.DiscImages
|
|||||||
byte[] sector = ReadSector(tracks[i].TrackStartSector);
|
byte[] sector = ReadSector(tracks[i].TrackStartSector);
|
||||||
tracks[i].TrackBytesPerSector = sector.Length;
|
tracks[i].TrackBytesPerSector = sector.Length;
|
||||||
tracks[i].TrackRawBytesPerSector =
|
tracks[i].TrackRawBytesPerSector =
|
||||||
sectorPrefix != null && sectorSuffix != null ? 2352 : sector.Length;
|
sectorPrefix != null && sectorSuffix != null ||
|
||||||
|
sectorPrefixDdt != null && sectorSuffixDdt != null
|
||||||
|
? 2352
|
||||||
|
: sector.Length;
|
||||||
|
|
||||||
if(sectorSubchannel == null) continue;
|
if(sectorSubchannel == null) continue;
|
||||||
|
|
||||||
@@ -923,6 +929,8 @@ namespace DiscImageChef.DiscImages
|
|||||||
|
|
||||||
SetMetadataFromTags();
|
SetMetadataFromTags();
|
||||||
|
|
||||||
|
if(sectorSuffixDdt != null) EccInit();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1310,23 +1318,70 @@ namespace DiscImageChef.DiscImages
|
|||||||
case TrackType.Audio:
|
case TrackType.Audio:
|
||||||
case TrackType.Data: return data;
|
case TrackType.Data: return data;
|
||||||
case TrackType.CdMode1:
|
case TrackType.CdMode1:
|
||||||
|
Array.Copy(data, 0, sector, 16, 2048);
|
||||||
|
|
||||||
if(sectorPrefix != null)
|
if(sectorPrefix != null)
|
||||||
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
|
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
|
||||||
else if(sectorPrefixMs != null) throw new NotImplementedException();
|
else if(sectorPrefixDdt != null)
|
||||||
|
{
|
||||||
|
if((sectorPrefixDdt[sectorAddress] & CD_XFIX_MASK) == (ulong)CdFixFlags.Correct)
|
||||||
|
ReconstructPrefix(ref sector, trk.TrackType, (long)sectorAddress);
|
||||||
|
else if((sectorPrefixDdt[sectorAddress] & CD_XFIX_MASK) == (ulong)CdFixFlags.NotDumped)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sectorPrefixMs.Position =
|
||||||
|
((sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16;
|
||||||
|
sectorPrefixMs.Read(sector, 0, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
else throw new InvalidProgramException("Should not have arrived here");
|
else throw new InvalidProgramException("Should not have arrived here");
|
||||||
|
|
||||||
if(sectorSuffix != null)
|
if(sectorSuffix != null)
|
||||||
Array.Copy(sectorSuffix, (int)sectorAddress * 288, sector, 2064, 288);
|
Array.Copy(sectorSuffix, (int)sectorAddress * 288, sector, 2064, 288);
|
||||||
else if(sectorSuffixMs != null) throw new NotImplementedException();
|
else if(sectorSuffixDdt != null)
|
||||||
|
{
|
||||||
|
if((sectorSuffixDdt[sectorAddress] & CD_XFIX_MASK) == (ulong)CdFixFlags.Correct)
|
||||||
|
ReconstructEcc(ref sector, trk.TrackType);
|
||||||
|
else if((sectorSuffixDdt[sectorAddress] & CD_XFIX_MASK) == (ulong)CdFixFlags.NotDumped)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sectorSuffixMs.Position =
|
||||||
|
((sectorSuffixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 288;
|
||||||
|
sectorSuffixMs.Read(sector, 0, 288);
|
||||||
|
}
|
||||||
|
}
|
||||||
else throw new InvalidProgramException("Should not have arrived here");
|
else throw new InvalidProgramException("Should not have arrived here");
|
||||||
|
|
||||||
Array.Copy(data, 0, sector, 16, 2048);
|
|
||||||
return sector;
|
return sector;
|
||||||
case TrackType.CdMode2Formless:
|
case TrackType.CdMode2Formless:
|
||||||
case TrackType.CdMode2Form1:
|
case TrackType.CdMode2Form1:
|
||||||
case TrackType.CdMode2Form2:
|
case TrackType.CdMode2Form2:
|
||||||
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
|
Array.Copy(data, 0, sector, 16, 2336);
|
||||||
Array.Copy(data, 0, sector, 16, 2336);
|
if(sectorPrefix != null)
|
||||||
|
Array.Copy(sectorPrefix, (int)sectorAddress * 16, sector, 0, 16);
|
||||||
|
else if(sectorPrefixMs != null)
|
||||||
|
{
|
||||||
|
if((sectorPrefixDdt[sectorAddress] & CD_XFIX_MASK) == (ulong)CdFixFlags.Correct)
|
||||||
|
ReconstructPrefix(ref sector, trk.TrackType, (long)sectorAddress);
|
||||||
|
else if((sectorPrefixDdt[sectorAddress] & CD_XFIX_MASK) == (ulong)CdFixFlags.NotDumped)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sectorPrefixMs.Position =
|
||||||
|
((sectorPrefixDdt[sectorAddress] & CD_DFIX_MASK) - 1) * 16;
|
||||||
|
sectorPrefixMs.Read(sector, 0, 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else throw new InvalidProgramException("Should not have arrived here");
|
||||||
|
|
||||||
return sector;
|
return sector;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1385,38 +1440,64 @@ namespace DiscImageChef.DiscImages
|
|||||||
case TrackType.Data: return ReadSectors(sectorAddress, length);
|
case TrackType.Data: return ReadSectors(sectorAddress, length);
|
||||||
// Join prefix (sync, header) with user data with suffix (edc, ecc p, ecc q)
|
// Join prefix (sync, header) with user data with suffix (edc, ecc p, ecc q)
|
||||||
case TrackType.CdMode1:
|
case TrackType.CdMode1:
|
||||||
if(sectorPrefix == null || sectorSuffix == null) return ReadSectors(sectorAddress, length);
|
if(sectorPrefix != null && sectorSuffix != null)
|
||||||
|
|
||||||
sectors = new byte[2352 * length];
|
|
||||||
data = ReadSectors(sectorAddress, length);
|
|
||||||
for(uint i = 0; i < length; i++)
|
|
||||||
{
|
{
|
||||||
Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors, (int)(i * 2352),
|
sectors = new byte[2352 * length];
|
||||||
16);
|
data = ReadSectors(sectorAddress, length);
|
||||||
Array.Copy(data, (int)(i * 2048), sectors,
|
for(uint i = 0; i < length; i++)
|
||||||
(int)(i * 2352) + 16, 2048);
|
{
|
||||||
Array.Copy(sectorSuffix, (int)((sectorAddress + i) * 288), sectors,
|
Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors, (int)(i * 2352),
|
||||||
(int)(i * 2352) + 2064, 288);
|
16);
|
||||||
}
|
Array.Copy(data, (int)(i * 2048), sectors, (int)(i * 2352) + 16, 2048);
|
||||||
|
Array.Copy(sectorSuffix, (int)((sectorAddress + i) * 288), sectors,
|
||||||
|
(int)(i * 2352) + 2064, 288);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors;
|
||||||
|
}
|
||||||
|
else if(sectorPrefixDdt != null && sectorSuffixDdt != null)
|
||||||
|
{
|
||||||
|
sectors = new byte[2352 * length];
|
||||||
|
for(uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
byte[] temp = ReadSectorLong(sectorAddress + i);
|
||||||
|
Array.Copy(temp, 0, sectors, 2352 * i, 2352);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors;
|
||||||
|
}
|
||||||
|
else return ReadSectors(sectorAddress, length);
|
||||||
|
|
||||||
return sectors;
|
|
||||||
// Join prefix (sync, header) with user data
|
// Join prefix (sync, header) with user data
|
||||||
case TrackType.CdMode2Formless:
|
case TrackType.CdMode2Formless:
|
||||||
case TrackType.CdMode2Form1:
|
case TrackType.CdMode2Form1:
|
||||||
case TrackType.CdMode2Form2:
|
case TrackType.CdMode2Form2:
|
||||||
if(sectorPrefix == null || sectorSuffix == null) return ReadSectors(sectorAddress, length);
|
if(sectorPrefix != null && sectorSuffix != null)
|
||||||
|
|
||||||
sectors = new byte[2352 * length];
|
|
||||||
data = ReadSectors(sectorAddress, length);
|
|
||||||
for(uint i = 0; i < length; i++)
|
|
||||||
{
|
{
|
||||||
Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors, (int)(i * 2352),
|
sectors = new byte[2352 * length];
|
||||||
16);
|
data = ReadSectors(sectorAddress, length);
|
||||||
Array.Copy(data, (int)(i * 2336), sectors,
|
for(uint i = 0; i < length; i++)
|
||||||
(int)(i * 2352) + 16, 2336);
|
{
|
||||||
|
Array.Copy(sectorPrefix, (int)((sectorAddress + i) * 16), sectors, (int)(i * 2352),
|
||||||
|
16);
|
||||||
|
Array.Copy(data, (int)(i * 2336), sectors, (int)(i * 2352) + 16, 2336);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors;
|
||||||
|
}
|
||||||
|
else if(sectorPrefixDdt != null && sectorSuffixDdt != null)
|
||||||
|
{
|
||||||
|
sectors = new byte[2352 * length];
|
||||||
|
for(uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
byte[] temp = ReadSectorLong(sectorAddress + i);
|
||||||
|
Array.Copy(temp, 0, sectors, 2352 * i, 2352);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sectors;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sectors;
|
return ReadSectors(sectorAddress, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user