mirror of
https://github.com/aaru-dps/Aaru.git
synced 2025-12-16 19:24:25 +00:00
Implement writing support for DiskCopy 4.2 format, fixes #129
This commit is contained in:
@@ -31,6 +31,9 @@
|
|||||||
<ConsolePause>false</ConsolePause>
|
<ConsolePause>false</ConsolePause>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Claunia.Encoding, Version=1.4.6570.38892, Culture=neutral, PublicKeyToken=null">
|
||||||
|
<HintPath>..\packages\Claunia.Encoding.1.4.0\lib\portable40-net40+sl5+win8+wp8\Claunia.Encoding.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="SharpCompress, Version=0.19.2.0, Culture=neutral, PublicKeyToken=afb0a02973931d96">
|
<Reference Include="SharpCompress, Version=0.19.2.0, Culture=neutral, PublicKeyToken=afb0a02973931d96">
|
||||||
<HintPath>..\packages\SharpCompress.0.19.2\lib\net35\SharpCompress.dll</HintPath>
|
<HintPath>..\packages\SharpCompress.0.19.2\lib\net35\SharpCompress.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
|||||||
@@ -34,19 +34,20 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using Claunia.Encoding;
|
||||||
using Claunia.RsrcFork;
|
using Claunia.RsrcFork;
|
||||||
using DiscImageChef.CommonTypes;
|
using DiscImageChef.CommonTypes;
|
||||||
using DiscImageChef.Console;
|
using DiscImageChef.Console;
|
||||||
using DiscImageChef.Filters;
|
using DiscImageChef.Filters;
|
||||||
|
using Encoding = System.Text.Encoding;
|
||||||
using Version = Resources.Version;
|
using Version = Resources.Version;
|
||||||
|
|
||||||
namespace DiscImageChef.DiscImages
|
namespace DiscImageChef.DiscImages
|
||||||
{
|
{
|
||||||
// Checked using several images and strings inside Apple's DiskImages.framework
|
// Checked using several images and strings inside Apple's DiskImages.framework
|
||||||
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
||||||
public class DiskCopy42 : IMediaImage
|
public class DiskCopy42 : IWritableImage
|
||||||
{
|
{
|
||||||
// format byte
|
// format byte
|
||||||
/// <summary>3.5", single side, double density, GCR</summary>
|
/// <summary>3.5", single side, double density, GCR</summary>
|
||||||
@@ -91,6 +92,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
const byte kFmtNotStandard = 0x93;
|
const byte kFmtNotStandard = 0x93;
|
||||||
/// <summary>Used incorrectly by Mac OS X with certaing disk images</summary>
|
/// <summary>Used incorrectly by Mac OS X with certaing disk images</summary>
|
||||||
const byte kMacOSXFmtByte = 0x00;
|
const byte kMacOSXFmtByte = 0x00;
|
||||||
|
const string REGEX_DCPY = @"(?<application>\S+)\s(?<version>\S+)\rData checksum=\$(?<checksum>\S+)$";
|
||||||
/// <summary>Bytes per tag, should be 12</summary>
|
/// <summary>Bytes per tag, should be 12</summary>
|
||||||
uint bptag;
|
uint bptag;
|
||||||
|
|
||||||
@@ -100,16 +102,17 @@ namespace DiscImageChef.DiscImages
|
|||||||
IFilter dc42ImageFilter;
|
IFilter dc42ImageFilter;
|
||||||
/// <summary>Header of opened image</summary>
|
/// <summary>Header of opened image</summary>
|
||||||
Dc42Header header;
|
Dc42Header header;
|
||||||
|
ImageInfo imageInfo;
|
||||||
|
ulong sectorsToWrite;
|
||||||
/// <summary>Start of tags in disk image, after data sectors</summary>
|
/// <summary>Start of tags in disk image, after data sectors</summary>
|
||||||
uint tagOffset;
|
uint tagOffset;
|
||||||
bool twiggy;
|
bool twiggy;
|
||||||
byte[] twiggyCache;
|
byte[] twiggyCache;
|
||||||
byte[] twiggyCacheTags;
|
byte[] twiggyCacheTags;
|
||||||
ImageInfo imageInfo;
|
MemoryStream twiggyDataCache;
|
||||||
public ImageInfo Info => imageInfo;
|
MemoryStream twiggyTagCache;
|
||||||
|
|
||||||
public string Name => "Apple DiskCopy 4.2";
|
FileStream writingStream;
|
||||||
public Guid Id => new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
|
|
||||||
|
|
||||||
public DiskCopy42()
|
public DiskCopy42()
|
||||||
{
|
{
|
||||||
@@ -138,6 +141,10 @@ namespace DiscImageChef.DiscImages
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ImageInfo Info => imageInfo;
|
||||||
|
public string Name => "Apple DiskCopy 4.2";
|
||||||
|
public Guid Id => new Guid("0240B7B1-E959-4CDC-B0BD-386D6E467B88");
|
||||||
|
|
||||||
public bool Identify(IFilter imageFilter)
|
public bool Identify(IFilter imageFilter)
|
||||||
{
|
{
|
||||||
Stream stream = imageFilter.GetDataForkStream();
|
Stream stream = imageFilter.GetDataForkStream();
|
||||||
@@ -226,6 +233,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
byte[] buffer = new byte[0x58];
|
byte[] buffer = new byte[0x58];
|
||||||
byte[] pString = new byte[64];
|
byte[] pString = new byte[64];
|
||||||
stream.Read(buffer, 0, 0x58);
|
stream.Read(buffer, 0, 0x58);
|
||||||
|
IsWriting = false;
|
||||||
|
|
||||||
// Incorrect pascal string length, not DC42
|
// Incorrect pascal string length, not DC42
|
||||||
if(buffer[0] > 63) return false;
|
if(buffer[0] > 63) return false;
|
||||||
@@ -419,9 +427,12 @@ namespace DiscImageChef.DiscImages
|
|||||||
if(i >= 42 && i <= 45) sectorsToCopy = 15;
|
if(i >= 42 && i <= 45) sectorsToCopy = 15;
|
||||||
|
|
||||||
Array.Copy(data, header.DataSize / 2 + copiedSectors * 512, twiggyCache,
|
Array.Copy(data, header.DataSize / 2 + copiedSectors * 512, twiggyCache,
|
||||||
twiggyCache.Length - copiedSectors * 512 - sectorsToCopy * 512, sectorsToCopy * 512);
|
twiggyCache.Length - copiedSectors * 512 - sectorsToCopy * 512,
|
||||||
Array.Copy(tags, header.TagSize / 2 + copiedSectors * bptag, twiggyCacheTags,
|
sectorsToCopy * 512);
|
||||||
twiggyCacheTags.Length - copiedSectors * bptag - sectorsToCopy * bptag,
|
Array.Copy(tags, header.TagSize / 2 + copiedSectors * bptag,
|
||||||
|
twiggyCacheTags,
|
||||||
|
twiggyCacheTags.Length - copiedSectors * bptag -
|
||||||
|
sectorsToCopy * bptag,
|
||||||
sectorsToCopy * bptag);
|
sectorsToCopy * bptag);
|
||||||
|
|
||||||
copiedSectors += sectorsToCopy;
|
copiedSectors += sectorsToCopy;
|
||||||
@@ -481,18 +492,13 @@ namespace DiscImageChef.DiscImages
|
|||||||
{
|
{
|
||||||
string dCpy = StringHandlers.PascalToString(dCpyRsrc.GetResource(dCpyRsrc.GetIds()[0]),
|
string dCpy = StringHandlers.PascalToString(dCpyRsrc.GetResource(dCpyRsrc.GetIds()[0]),
|
||||||
Encoding.GetEncoding("macintosh"));
|
Encoding.GetEncoding("macintosh"));
|
||||||
string dCpyRegEx =
|
Regex dCpyEx = new Regex(REGEX_DCPY);
|
||||||
@"(?<application>\S+)\s(?<version>\S+)\rData checksum=\$(?<checksum>\S+)$";
|
|
||||||
Regex dCpyEx = new Regex(dCpyRegEx);
|
|
||||||
Match dCpyMatch = dCpyEx.Match(dCpy);
|
Match dCpyMatch = dCpyEx.Match(dCpy);
|
||||||
|
|
||||||
if(dCpyMatch.Success)
|
if(dCpyMatch.Success)
|
||||||
{
|
{
|
||||||
imageInfo.Application = dCpyMatch.Groups["application"].Value;
|
imageInfo.Application = dCpyMatch.Groups["application"].Value;
|
||||||
imageInfo.ApplicationVersion = dCpyMatch.Groups["version"].Value;
|
imageInfo.ApplicationVersion = dCpyMatch.Groups["version"].Value;
|
||||||
|
|
||||||
// Until MacRoman is implemented
|
|
||||||
if(imageInfo.Application == "ShrinkWrap?") imageInfo.Application = "ShrinkWrap™";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -603,7 +609,6 @@ namespace DiscImageChef.DiscImages
|
|||||||
{
|
{
|
||||||
byte[] data = new byte[header.DataSize];
|
byte[] data = new byte[header.DataSize];
|
||||||
byte[] tags = new byte[header.TagSize];
|
byte[] tags = new byte[header.TagSize];
|
||||||
uint dataChk;
|
|
||||||
uint tagsChk = 0;
|
uint tagsChk = 0;
|
||||||
|
|
||||||
DicConsole.DebugWriteLine("DC42 plugin", "Reading data");
|
DicConsole.DebugWriteLine("DC42 plugin", "Reading data");
|
||||||
@@ -612,7 +617,7 @@ namespace DiscImageChef.DiscImages
|
|||||||
datastream.Read(data, 0, (int)header.DataSize);
|
datastream.Read(data, 0, (int)header.DataSize);
|
||||||
|
|
||||||
DicConsole.DebugWriteLine("DC42 plugin", "Calculating data checksum");
|
DicConsole.DebugWriteLine("DC42 plugin", "Calculating data checksum");
|
||||||
dataChk = DC42CheckSum(data);
|
uint dataChk = DC42CheckSum(data);
|
||||||
DicConsole.DebugWriteLine("DC42 plugin", "Calculated data checksum = 0x{0:X8}", dataChk);
|
DicConsole.DebugWriteLine("DC42 plugin", "Calculated data checksum = 0x{0:X8}", dataChk);
|
||||||
DicConsole.DebugWriteLine("DC42 plugin", "Stored data checksum = 0x{0:X8}", header.DataChecksum);
|
DicConsole.DebugWriteLine("DC42 plugin", "Stored data checksum = 0x{0:X8}", header.DataChecksum);
|
||||||
|
|
||||||
@@ -773,6 +778,333 @@ namespace DiscImageChef.DiscImages
|
|||||||
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
throw new FeatureUnsupportedImageException("Feature not supported by image format");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerable<MediaTagType> SupportedMediaTags => new MediaTagType[] { };
|
||||||
|
public IEnumerable<SectorTagType> SupportedSectorTags => new[] {SectorTagType.AppleSectorTag};
|
||||||
|
public IEnumerable<MediaType> SupportedMediaTypes =>
|
||||||
|
new[]
|
||||||
|
{
|
||||||
|
MediaType.AppleFileWare, MediaType.AppleHD20, MediaType.AppleProfile, MediaType.AppleSonyDS,
|
||||||
|
MediaType.AppleSonySS, MediaType.AppleWidget, MediaType.DOS_35_DS_DD_9, MediaType.DOS_35_HD,
|
||||||
|
MediaType.DMF
|
||||||
|
};
|
||||||
|
public IEnumerable<(string name, Type type, string description)> SupportedOptions =>
|
||||||
|
new[] {("macosx", typeof(bool), "Use Mac OS X format byte")};
|
||||||
|
public IEnumerable<string> KnownExtensions => new[] {".dc42", ".diskcopy42", ".image"};
|
||||||
|
public bool IsWriting { get; private set; }
|
||||||
|
public string ErrorMessage { get; private set; }
|
||||||
|
|
||||||
|
public bool Create(string path, MediaType mediaType, Dictionary<string, string> options, ulong sectors)
|
||||||
|
{
|
||||||
|
header = new Dc42Header();
|
||||||
|
bool tags = false;
|
||||||
|
bool macosx;
|
||||||
|
|
||||||
|
if(options != null && options.TryGetValue("macosx", out string tmpOption))
|
||||||
|
bool.TryParse(tmpOption, out macosx);
|
||||||
|
|
||||||
|
switch(mediaType)
|
||||||
|
{
|
||||||
|
case MediaType.AppleFileWare:
|
||||||
|
header.FmtByte = kSigmaFmtByteTwiggy;
|
||||||
|
header.Format = kSigmaFormatTwiggy;
|
||||||
|
twiggy = true;
|
||||||
|
tags = true;
|
||||||
|
twiggyDataCache = new MemoryStream();
|
||||||
|
twiggyTagCache = new MemoryStream();
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
ErrorMessage = "Twiggy write support not yet implemented";
|
||||||
|
return false;
|
||||||
|
case MediaType.AppleHD20:
|
||||||
|
if(sectors != 39040)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect number of sectors for Apple HD20 image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.FmtByte = kFmtNotStandard;
|
||||||
|
header.Format = kNotStandardFormat;
|
||||||
|
tags = true;
|
||||||
|
break;
|
||||||
|
case MediaType.AppleProfile:
|
||||||
|
if(sectors != 9728 && sectors != 19456)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect number of sectors for Apple Profile image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.FmtByte = kFmtNotStandard;
|
||||||
|
header.Format = kNotStandardFormat;
|
||||||
|
tags = true;
|
||||||
|
break;
|
||||||
|
case MediaType.AppleSonyDS:
|
||||||
|
if(sectors != 1600)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect number of sectors for Apple MF2DD image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.FmtByte = macosx ? kMacOSXFmtByte : kSonyFmtByte800K;
|
||||||
|
header.Format = kSonyFormat800K;
|
||||||
|
tags = true;
|
||||||
|
break;
|
||||||
|
case MediaType.AppleSonySS:
|
||||||
|
if(sectors != 800)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect number of sectors for Apple MF1DD image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.FmtByte = macosx ? kMacOSXFmtByte : kSonyFmtByte400K;
|
||||||
|
header.Format = kSonyFormat400K;
|
||||||
|
tags = true;
|
||||||
|
break;
|
||||||
|
case MediaType.AppleWidget:
|
||||||
|
if(sectors != 39040)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect number of sectors for Apple Widget image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.FmtByte = kFmtNotStandard;
|
||||||
|
header.Format = kNotStandardFormat;
|
||||||
|
tags = true;
|
||||||
|
break;
|
||||||
|
case MediaType.DOS_35_DS_DD_9:
|
||||||
|
if(sectors != 1440)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect number of sectors for MF2DD image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.FmtByte = macosx ? kMacOSXFmtByte : kSonyFmtByte720K;
|
||||||
|
header.Format = kSonyFormat720K;
|
||||||
|
break;
|
||||||
|
case MediaType.DOS_35_HD:
|
||||||
|
if(sectors != 2880)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect number of sectors for MF2HD image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.Format = kSonyFmtByte1440K;
|
||||||
|
header.FmtByte = macosx ? kMacOSXFmtByte : kSonyFmtByte1440K;
|
||||||
|
break;
|
||||||
|
case MediaType.DMF:
|
||||||
|
if(sectors != 3360)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect number of sectors for DMF image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header.FmtByte = macosx ? kMacOSXFmtByte : kSonyFmtByte1680K;
|
||||||
|
header.Format = kSonyFormat1680K;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ErrorMessage = $"Unsupport media format {mediaType}";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
dataOffset = 0x54;
|
||||||
|
tagOffset = header.TagSize != 0 ? 0x54 + header.DataSize : 0;
|
||||||
|
header.DiskName = "-DiscImageChef converted image-";
|
||||||
|
header.Valid = 1;
|
||||||
|
header.DataSize = (uint)(sectors * 512);
|
||||||
|
if(tags) header.TagSize = (uint)(sectors * 12);
|
||||||
|
sectorsToWrite = sectors;
|
||||||
|
|
||||||
|
try { writingStream = new FileStream(path, FileMode.CreateNew, FileAccess.ReadWrite, FileShare.None); }
|
||||||
|
catch(IOException e)
|
||||||
|
{
|
||||||
|
ErrorMessage = $"Could not create new image file, exception {e.Message}";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorMessage = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool WriteMediaTag(byte[] data, MediaTagType tag)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Unsupported feature";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool WriteSector(byte[] data, ulong sectorAddress)
|
||||||
|
{
|
||||||
|
if(!IsWriting)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Tried to write on a non-writable image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sectorAddress >= sectorsToWrite)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Tried to write past image size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writingStream.Seek((long)(dataOffset + sectorAddress * 512), SeekOrigin.Begin);
|
||||||
|
writingStream.Write(data, 0, data.Length);
|
||||||
|
|
||||||
|
ErrorMessage = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool WriteSectors(byte[] data, ulong sectorAddress, uint length)
|
||||||
|
{
|
||||||
|
if(!IsWriting)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Tried to write on a non-writable image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data.Length != 512)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect data size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data.Length % 512 != 0)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect data size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sectorAddress + length >= sectorsToWrite)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Tried to write past image size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writingStream.Seek((long)(dataOffset + sectorAddress * 512), SeekOrigin.Begin);
|
||||||
|
writingStream.Write(data, 0, data.Length);
|
||||||
|
|
||||||
|
ErrorMessage = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool WriteSectorLong(byte[] data, ulong sectorAddress)
|
||||||
|
{
|
||||||
|
if(!IsWriting)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Tried to write on a non-writable image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(header.TagSize == 0)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Image does not support tags";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data.Length != 524)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect data size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sectorAddress >= sectorsToWrite)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Tried to write past image size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writingStream.Seek((long)(dataOffset + sectorAddress * 512), SeekOrigin.Begin);
|
||||||
|
writingStream.Write(data, 0, 512);
|
||||||
|
writingStream.Seek((long)(tagOffset + sectorAddress * 12), SeekOrigin.Begin);
|
||||||
|
writingStream.Write(data, 512, 12);
|
||||||
|
|
||||||
|
ErrorMessage = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length)
|
||||||
|
{
|
||||||
|
if(!IsWriting)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Tried to write on a non-writable image";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(header.TagSize == 0)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Image does not support tags";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data.Length % 524 != 0)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Incorrect data size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(sectorAddress + length >= sectorsToWrite)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Tried to write past image size";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
writingStream.Seek((long)(dataOffset + (sectorAddress + i) * 512), SeekOrigin.Begin);
|
||||||
|
writingStream.Write(data, (int)(i * 524 + 0), 512);
|
||||||
|
writingStream.Seek((long)(tagOffset + (sectorAddress + i) * 12),
|
||||||
|
SeekOrigin.Begin);
|
||||||
|
writingStream.Write(data, (int)(i * 524 + 512),
|
||||||
|
12);
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorMessage = "";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetTracks(List<Track> tracks)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Unsupported feature";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Close()
|
||||||
|
{
|
||||||
|
if(!IsWriting)
|
||||||
|
{
|
||||||
|
ErrorMessage = "Image is not opened for writing";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
writingStream.Seek(0x54, SeekOrigin.Begin);
|
||||||
|
byte[] data = new byte[header.DataSize];
|
||||||
|
writingStream.Read(data, 0, (int)header.DataSize);
|
||||||
|
header.DataChecksum = DC42CheckSum(data);
|
||||||
|
writingStream.Seek(0x54 + header.DataSize, SeekOrigin.Begin);
|
||||||
|
data = new byte[header.TagSize];
|
||||||
|
writingStream.Read(data, 0, (int)header.TagSize);
|
||||||
|
header.TagChecksum = DC42CheckSum(data);
|
||||||
|
|
||||||
|
writingStream.Seek(0, SeekOrigin.Begin);
|
||||||
|
if(header.DiskName.Length > 63) header.DiskName = header.DiskName.Substring(0, 63);
|
||||||
|
writingStream.WriteByte((byte)header.DiskName.Length);
|
||||||
|
Encoding macRoman = new MacRoman();
|
||||||
|
writingStream.Write(macRoman.GetBytes(header.DiskName), 0, header.DiskName.Length);
|
||||||
|
|
||||||
|
writingStream.Seek(64, SeekOrigin.Begin);
|
||||||
|
writingStream.Write(BigEndianBitConverter.GetBytes(header.DataSize), 0, 4);
|
||||||
|
writingStream.Write(BigEndianBitConverter.GetBytes(header.TagSize), 0, 4);
|
||||||
|
writingStream.Write(BigEndianBitConverter.GetBytes(header.DataChecksum), 0, 4);
|
||||||
|
writingStream.Write(BigEndianBitConverter.GetBytes(header.TagChecksum), 0, 4);
|
||||||
|
writingStream.WriteByte(header.Format);
|
||||||
|
writingStream.WriteByte(header.FmtByte);
|
||||||
|
writingStream.WriteByte(1);
|
||||||
|
writingStream.WriteByte(0);
|
||||||
|
|
||||||
|
writingStream.Flush();
|
||||||
|
writingStream.Close();
|
||||||
|
IsWriting = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static uint DC42CheckSum(byte[] buffer)
|
static uint DC42CheckSum(byte[] buffer)
|
||||||
{
|
{
|
||||||
uint dc42Chk = 0;
|
uint dc42Chk = 0;
|
||||||
@@ -788,6 +1120,11 @@ namespace DiscImageChef.DiscImages
|
|||||||
return dc42Chk;
|
return dc42Chk;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~DiskCopy42()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
// DiskCopy 4.2 header, big-endian, data-fork, start of file, 84 bytes
|
// DiskCopy 4.2 header, big-endian, data-fork, start of file, 84 bytes
|
||||||
struct Dc42Header
|
struct Dc42Header
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,15 +45,15 @@ namespace DiscImageChef.DiscImages
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of <see cref="MediaTagType" /> that are supported by the media image format
|
/// Gets a list of <see cref="MediaTagType" /> that are supported by the media image format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<MediaTagType> SupportedMediaTags { get; }
|
IEnumerable<MediaTagType> SupportedMediaTags { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of <see cref="SectorTagType" /> that are supported by the media image format
|
/// Gets a list of <see cref="SectorTagType" /> that are supported by the media image format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<SectorTagType> SupportedSectorTags { get; }
|
IEnumerable<SectorTagType> SupportedSectorTags { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of <see cref="MediaType" /> that are supported by the media image format
|
/// Gets a list of <see cref="MediaType" /> that are supported by the media image format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<MediaType> SupportedMediaTypes { get; }
|
IEnumerable<MediaType> SupportedMediaTypes { get; }
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Retrieves a list of options supported by the filesystem, with name, type and description
|
/// Retrieves a list of options supported by the filesystem, with name, type and description
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -61,7 +61,10 @@ namespace DiscImageChef.DiscImages
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of known extensions for format auto-chosing
|
/// Gets a list of known extensions for format auto-chosing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
List<string> KnownExtensions { get; }
|
IEnumerable<string> KnownExtensions { get; }
|
||||||
|
|
||||||
|
bool IsWriting { get; }
|
||||||
|
string ErrorMessage { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new image in the specified path, for the specified <see cref="MediaType" />, with the
|
/// Creates a new image in the specified path, for the specified <see cref="MediaType" />, with the
|
||||||
|
|||||||
Reference in New Issue
Block a user