diff --git a/DiscImageChef.DiscImages/Apple2MG.cs b/DiscImageChef.DiscImages/Apple2MG.cs
index 7411d86a..8ce6a4b6 100644
--- a/DiscImageChef.DiscImages/Apple2MG.cs
+++ b/DiscImageChef.DiscImages/Apple2MG.cs
@@ -34,6 +34,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
+using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using DiscImageChef.CommonTypes;
@@ -42,7 +43,7 @@ using DiscImageChef.Filters;
namespace DiscImageChef.DiscImages
{
- public class Apple2Mg : IMediaImage
+ public class Apple2Mg : IWritableImage
{
///
/// Magic number, "2IMG"
@@ -76,6 +77,10 @@ namespace DiscImageChef.DiscImages
/// Disk image created by CiderPress, "CdrP"
///
const uint CREATOR_CIDER = 0x50726443;
+ ///
+ /// Disk image created by DiscImageChef, "dic "
+ ///
+ const uint CREATOR_DIC = 0x20636964;
const uint LOCKED_DISK = 0x80000000;
const uint VALID_VOLUME_NUMBER = 0x00000100;
@@ -88,6 +93,7 @@ namespace DiscImageChef.DiscImages
byte[] decodedImage;
A2ImgHeader imageHeader;
ImageInfo imageInfo;
+ FileStream writingStream;
public Apple2Mg()
{
@@ -314,6 +320,9 @@ namespace DiscImageChef.DiscImages
case CREATOR_CIDER:
imageInfo.Application = "CiderPress";
break;
+ case CREATOR_DIC:
+ imageInfo.Application = "DiscImageChef";
+ break;
default:
imageInfo.Application = $"Unknown creator code \"{Encoding.ASCII.GetString(creator)}\"";
break;
@@ -378,8 +387,8 @@ namespace DiscImageChef.DiscImages
imageInfo.SectorsPerTrack = 10;
break;
case MediaType.DOS_35_HD:
- imageInfo.Cylinders = 80;
- imageInfo.Heads = 2;
+ imageInfo.Cylinders = 80;
+ imageInfo.Heads = 2;
imageInfo.SectorsPerTrack = 18;
break;
}
@@ -511,6 +520,218 @@ namespace DiscImageChef.DiscImages
return null;
}
+ public IEnumerable SupportedMediaTags => new MediaTagType[] { };
+ public IEnumerable SupportedSectorTags => new SectorTagType[] { };
+ public IEnumerable SupportedMediaTypes =>
+ new[]
+ {
+ MediaType.Apple32SS, MediaType.Apple33SS, MediaType.AppleSonySS, MediaType.AppleSonyDS,
+ MediaType.DOS_35_HD, MediaType.Unknown, MediaType.GENERIC_HDD
+ };
+ public IEnumerable<(string name, Type type, string description)> SupportedOptions =>
+ new (string name, Type type, string description)[] { };
+ public IEnumerable KnownExtensions => new[] {".2mg"};
+ public bool IsWriting { get; private set; }
+ public string ErrorMessage { get; private set; }
+
+ public bool Create(string path, MediaType mediaType, Dictionary options, ulong sectors,
+ uint sectorSize)
+ {
+ if(sectorSize != 512)
+ if(sectorSize != 256 || mediaType != MediaType.Apple32SS && mediaType != MediaType.Apple33SS)
+ {
+ ErrorMessage = "Unsupported sector size";
+ return false;
+ }
+
+ if(!SupportedMediaTypes.Contains(mediaType))
+ {
+ ErrorMessage = $"Unsupport media format {mediaType}";
+ return false;
+ }
+
+ if(sectors > uint.MaxValue)
+ {
+ ErrorMessage = "Too many sectors";
+ return false;
+ }
+
+ imageInfo = new ImageInfo {MediaType = mediaType, SectorSize = sectorSize, Sectors = 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;
+ }
+
+ IsWriting = true;
+ 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(data.Length != imageInfo.SectorSize)
+ {
+ ErrorMessage = "Incorrect data size";
+ return false;
+ }
+
+ if(sectorAddress >= imageInfo.Sectors)
+ {
+ ErrorMessage = "Tried to write past image size";
+ return false;
+ }
+
+ writingStream.Seek((long)(0x40 + sectorAddress * imageInfo.SectorSize), 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 % imageInfo.SectorSize != 0)
+ {
+ ErrorMessage = "Incorrect data size";
+ return false;
+ }
+
+ if(sectorAddress + length > imageInfo.Sectors)
+ {
+ ErrorMessage = "Tried to write past image size";
+ return false;
+ }
+
+ writingStream.Seek((long)(0x40 + sectorAddress * imageInfo.SectorSize), SeekOrigin.Begin);
+ writingStream.Write(data, 0, data.Length);
+
+ ErrorMessage = "";
+ return true;
+ }
+
+ public bool WriteSectorLong(byte[] data, ulong sectorAddress)
+ {
+ ErrorMessage = "Writing sectors with tags is not supported.";
+ return false;
+ }
+
+ public bool WriteSectorsLong(byte[] data, ulong sectorAddress, uint length)
+ {
+ ErrorMessage = "Writing sectors with tags is not supported.";
+ return false;
+ }
+
+ public bool SetTracks(List