143 lines
4.6 KiB
C#
143 lines
4.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
|
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media
|
|
{
|
|
public static class G64
|
|
{
|
|
public static Disk Read(byte[] source)
|
|
{
|
|
using (var mem = new MemoryStream(source))
|
|
{
|
|
var reader = new BinaryReader(mem);
|
|
var id = new string(reader.ReadChars(8));
|
|
var trackDatas = new List<byte[]>();
|
|
var trackLengths = new List<int>();
|
|
var trackNumbers = new List<int>();
|
|
var trackDensities = new List<int>();
|
|
|
|
if (id == @"GCR-1541")
|
|
{
|
|
reader.ReadByte(); // version
|
|
int trackCount = reader.ReadByte();
|
|
reader.ReadInt16(); // max track size in bytes
|
|
|
|
var trackOffsetTable = new int[trackCount];
|
|
var trackSpeedTable = new int[trackCount];
|
|
|
|
for (var i = 0; i < trackCount; i++)
|
|
{
|
|
trackOffsetTable[i] = reader.ReadInt32();
|
|
}
|
|
|
|
for (var i = 0; i < trackCount; i++)
|
|
{
|
|
trackSpeedTable[i] = reader.ReadInt32();
|
|
}
|
|
|
|
for (var i = 0; i < trackCount; i++)
|
|
{
|
|
if (trackOffsetTable[i] > 0)
|
|
{
|
|
mem.Position = trackOffsetTable[i];
|
|
int trackLength = reader.ReadInt16();
|
|
var trackData = reader.ReadBytes(trackLength);
|
|
|
|
trackDatas.Add(trackData);
|
|
trackLengths.Add(trackLength * 8);
|
|
trackDensities.Add(trackSpeedTable[i]);
|
|
trackNumbers.Add(i);
|
|
}
|
|
}
|
|
|
|
if (trackSpeedTable.Any(ts => ts > 3 || ts < 0))
|
|
{
|
|
throw new Exception("Byte-level speeds are not yet supported in the G64 loader.");
|
|
}
|
|
|
|
return new Disk(trackDatas, trackNumbers, trackDensities, 84) {WriteProtected = true};
|
|
}
|
|
|
|
return new Disk(84) {WriteProtected = false};
|
|
}
|
|
}
|
|
|
|
public static byte[] Write(IList<byte[]> trackData, IList<int> trackNumbers, IList<int> trackDensities)
|
|
{
|
|
const byte version = 0;
|
|
const byte trackCount = 84;
|
|
const int headerLength = 0xC;
|
|
const byte dataFillerValue = 0xFF;
|
|
|
|
var trackMaxLength = (ushort)Math.Max(7928, trackData.Max(d => d.Length));
|
|
|
|
using (var mem = new MemoryStream())
|
|
{
|
|
var writer = new BinaryWriter(mem);
|
|
|
|
// header ID
|
|
writer.Write("GCR-1541".ToCharArray());
|
|
|
|
// version #
|
|
writer.Write(version);
|
|
|
|
// tracks in the image
|
|
writer.Write(trackCount);
|
|
|
|
// maximum track size in bytes
|
|
writer.Write(trackMaxLength);
|
|
|
|
// combine track data
|
|
var offsets = new List<int>();
|
|
var densities = new List<int>();
|
|
using (var trackMem = new MemoryStream())
|
|
{
|
|
var trackMemWriter = new BinaryWriter(trackMem);
|
|
for (var i = 0; i < trackCount; i++)
|
|
{
|
|
if (trackNumbers.Contains(i))
|
|
{
|
|
var trackIndex = trackNumbers.IndexOf(i);
|
|
offsets.Add((int)trackMem.Length);
|
|
densities.Add(trackDensities[trackIndex]);
|
|
|
|
var data = trackData[trackIndex];
|
|
var buffer = Enumerable.Repeat(dataFillerValue, trackMaxLength).ToArray();
|
|
var dataBytes = data.Select(d => unchecked((byte)d)).ToArray();
|
|
Array.Copy(dataBytes, buffer, dataBytes.Length);
|
|
trackMemWriter.Write((ushort)dataBytes.Length);
|
|
trackMemWriter.Write(buffer);
|
|
}
|
|
else
|
|
{
|
|
offsets.Add(-1);
|
|
densities.Add(0);
|
|
}
|
|
}
|
|
trackMemWriter.Flush();
|
|
|
|
// offset table
|
|
foreach (var offset in offsets.Select(o => o >= 0 ? o + headerLength + trackCount * 8 : 0))
|
|
{
|
|
writer.Write(offset);
|
|
}
|
|
|
|
// speed zone data
|
|
foreach (var density in densities)
|
|
{
|
|
writer.Write(density);
|
|
}
|
|
|
|
// track data
|
|
writer.Write(trackMem.ToArray());
|
|
}
|
|
|
|
writer.Flush();
|
|
return mem.ToArray();
|
|
}
|
|
}
|
|
}
|
|
}
|