commodore64: Implemented conversion of D64 into GCR bitcode (both major disk formats can be loaded now)
This commit is contained in:
parent
9d070deb16
commit
a3db998a0d
|
@ -86,6 +86,7 @@
|
|||
<Compile Include="Computers\Commodore64\Cartridge.cs" />
|
||||
<Compile Include="Computers\Commodore64\CartridgeMappers.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cia.cs" />
|
||||
<Compile Include="Computers\Commodore64\D64.cs" />
|
||||
<Compile Include="Computers\Commodore64\DataPort.cs" />
|
||||
<Compile Include="Computers\Commodore64\Disk.cs" />
|
||||
<Compile Include="Computers\Commodore64\G64.cs" />
|
||||
|
|
|
@ -76,11 +76,12 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
switch (extension.ToUpper())
|
||||
{
|
||||
case @".G64":
|
||||
diskDrive = new Drive1541(File.ReadAllBytes(Path.Combine(romPath, @"1541dos")), Region.NTSC);
|
||||
diskDrive = new Drive1541(File.ReadAllBytes(Path.Combine(romPath, @"dos1541")), Region.NTSC);
|
||||
diskDrive.Insert(G64.Read(inputFile));
|
||||
break;
|
||||
case @".D64":
|
||||
diskDrive = new Drive1541(File.ReadAllBytes(Path.Combine(romPath, @"1541dos")), Region.NTSC);
|
||||
diskDrive = new Drive1541(File.ReadAllBytes(Path.Combine(romPath, @"dos1541")), Region.NTSC);
|
||||
diskDrive.Insert(D64.Read(inputFile));
|
||||
break;
|
||||
case @".PRG":
|
||||
if (inputFile.Length > 2)
|
||||
|
|
|
@ -0,0 +1,241 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public static class D64
|
||||
{
|
||||
private static int[] densityTable =
|
||||
{
|
||||
3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3,
|
||||
3, 3, 3, 3, 3,
|
||||
3, 3, 2, 2, 2,
|
||||
2, 2, 2, 2, 1,
|
||||
1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
private static int[] gcrDecodeTable =
|
||||
{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, //00xxx
|
||||
0xFF, 0x08, 0x00, 0x01, 0xFF, 0x0C, 0x04, 0x05, //01xxx
|
||||
0xFF, 0xFF, 0x02, 0x03, 0xFF, 0x0F, 0x06, 0x07, //10xxx
|
||||
0xFF, 0x09, 0x0A, 0x0B, 0xFF, 0x0D, 0x0E, 0xFF //11xxx
|
||||
};
|
||||
|
||||
private static int[] gcrEncodeTable =
|
||||
{
|
||||
Convert.ToByte("01010", 2), // 0
|
||||
Convert.ToByte("01011", 2), // 1
|
||||
Convert.ToByte("10010", 2), // 2
|
||||
Convert.ToByte("10011", 2), // 3
|
||||
Convert.ToByte("01110", 2), // 4
|
||||
Convert.ToByte("01111", 2), // 5
|
||||
Convert.ToByte("10110", 2), // 6
|
||||
Convert.ToByte("10111", 2), // 7
|
||||
Convert.ToByte("01001", 2), // 8
|
||||
Convert.ToByte("11001", 2), // 9
|
||||
Convert.ToByte("11010", 2), // A
|
||||
Convert.ToByte("11011", 2), // B
|
||||
Convert.ToByte("01101", 2), // C
|
||||
Convert.ToByte("11101", 2), // D
|
||||
Convert.ToByte("11110", 2), // E
|
||||
Convert.ToByte("10101", 2) // F
|
||||
};
|
||||
|
||||
private static int[] sectorsPerTrack =
|
||||
{
|
||||
21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21,
|
||||
21, 21, 21, 21, 21,
|
||||
21, 21, 19, 19, 19,
|
||||
19, 19, 19, 19, 18,
|
||||
18, 18, 18, 18, 18,
|
||||
17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17
|
||||
};
|
||||
|
||||
private static byte Checksum(byte[] source)
|
||||
{
|
||||
int count = source.Length;
|
||||
byte result = 0;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
result ^= source[i];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte[] ConvertSectorFromGCR(byte[] source, out int bitsWritten)
|
||||
{
|
||||
bitsWritten = 0;
|
||||
return new byte[] { };
|
||||
}
|
||||
|
||||
private static byte[] ConvertSectorToGCR(byte[] source, byte sectorNo, byte trackNo, byte formatA, byte formatB, out int bitsWritten)
|
||||
{
|
||||
MemoryStream mem = new MemoryStream();
|
||||
BinaryWriter writer = new BinaryWriter(mem);
|
||||
byte[] writtenData;
|
||||
byte headerChecksum = (byte)(sectorNo ^ trackNo ^ formatA ^ formatB);
|
||||
|
||||
// assemble written data for GCR encoding
|
||||
writtenData = new byte[260];
|
||||
Array.Copy(source, 0, writtenData, 1, 256);
|
||||
writtenData[0] = 0x07;
|
||||
writtenData[0x101] = Checksum(source);
|
||||
writtenData[0x102] = 0x00;
|
||||
writtenData[0x103] = 0x00;
|
||||
|
||||
bitsWritten = 0;
|
||||
writer.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); // sync
|
||||
writer.Write(EncodeGCR(new byte[] { 0x08, headerChecksum, sectorNo, trackNo, formatA, formatB, 0x0F, 0x0F })); // header
|
||||
writer.Write(new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }); // gap
|
||||
writer.Write(new byte[] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }); // sync
|
||||
writer.Write(EncodeGCR(writtenData)); // data
|
||||
writer.Write(new byte[] { 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55 }); // gap
|
||||
|
||||
bitsWritten = (int)mem.Length * 8;
|
||||
|
||||
writer.Flush();
|
||||
return mem.ToArray();
|
||||
}
|
||||
|
||||
private static byte[] DecodeGCR(byte[] source)
|
||||
{
|
||||
// 5 GCR encoded bytes -> 4 bytes
|
||||
int[] gcr = new int[8];
|
||||
byte[] data = new byte[4];
|
||||
int count = source.Length;
|
||||
int outputValue;
|
||||
MemoryStream mem = new MemoryStream();
|
||||
BinaryWriter writer = new BinaryWriter(mem);
|
||||
|
||||
for (int i = 0; i < count; i += 5)
|
||||
{
|
||||
Array.Copy(source, i, data, 0, 5);
|
||||
|
||||
// -------- -------- -------- -------- --------
|
||||
// 11100000 32222211 44443333 66555554 77777666
|
||||
|
||||
gcr[0] = ((data[0])) & 0x1F;
|
||||
gcr[1] = ((data[0] >> 5) | data[1] << 3) & 0x1F;
|
||||
gcr[2] = ((data[1] >> 2)) & 0x1F;
|
||||
gcr[3] = ((data[1] >> 7) | data[2] << 1) & 0x1F;
|
||||
gcr[4] = ((data[2] >> 4) | data[3] << 4) & 0x1F;
|
||||
gcr[5] = ((data[3] >> 1)) & 0x1F;
|
||||
gcr[6] = ((data[3] >> 6) | data[4] << 2) & 0x1F;
|
||||
gcr[7] = ((data[4] >> 3)) & 0x1F;
|
||||
|
||||
outputValue = gcrDecodeTable[gcr[0]] | (gcrDecodeTable[gcr[1]] << 4);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
outputValue = gcrDecodeTable[gcr[2]] | (gcrDecodeTable[gcr[3]] << 4);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
outputValue = gcrDecodeTable[gcr[4]] | (gcrDecodeTable[gcr[5]] << 4);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
outputValue = gcrDecodeTable[gcr[6]] | (gcrDecodeTable[gcr[7]] << 4);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
}
|
||||
writer.Flush();
|
||||
return mem.ToArray();
|
||||
}
|
||||
|
||||
private static byte[] EncodeGCR(byte[] source)
|
||||
{
|
||||
// 4 bytes -> 5 GCR encoded bytes
|
||||
int[] gcr = new int[8];
|
||||
byte[] data = new byte[4];
|
||||
int count = source.Length;
|
||||
int outputValue;
|
||||
MemoryStream mem = new MemoryStream();
|
||||
BinaryWriter writer = new BinaryWriter(mem);
|
||||
|
||||
for (int i = 0; i < count; i += 4)
|
||||
{
|
||||
Array.Copy(source, i, data, 0, 4);
|
||||
gcr[0] = gcrEncodeTable[data[0] & 0xF];
|
||||
gcr[1] = gcrEncodeTable[data[0] >> 4];
|
||||
gcr[2] = gcrEncodeTable[data[1] & 0xF];
|
||||
gcr[3] = gcrEncodeTable[data[1] >> 4];
|
||||
gcr[4] = gcrEncodeTable[data[2] & 0xF];
|
||||
gcr[5] = gcrEncodeTable[data[2] >> 4];
|
||||
gcr[6] = gcrEncodeTable[data[3] & 0xF];
|
||||
gcr[7] = gcrEncodeTable[data[3] >> 4];
|
||||
|
||||
// -------- -------- -------- -------- --------
|
||||
// 11100000 32222211 44443333 66555554 77777666
|
||||
|
||||
outputValue = (gcr[0]) | (gcr[1] << 5);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
outputValue = (gcr[1] >> 3) | (gcr[2] << 2) | (gcr[3] << 7);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
outputValue = (gcr[3] >> 1) | (gcr[4] << 4);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
outputValue = (gcr[4] >> 4) | (gcr[5] << 1) | (gcr[6] << 6);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
outputValue = (gcr[6] >> 2) | (gcr[7] << 3);
|
||||
writer.Write((byte)(outputValue & 0xFF));
|
||||
}
|
||||
writer.Flush();
|
||||
return mem.ToArray();
|
||||
}
|
||||
|
||||
public static Disk Read(byte[] source)
|
||||
{
|
||||
MemoryStream mem = new MemoryStream(source);
|
||||
BinaryReader reader = new BinaryReader(mem);
|
||||
Disk result = new Disk();
|
||||
int trackCount = 0;
|
||||
|
||||
switch (source.Length)
|
||||
{
|
||||
case 174848: // 35 tracks no errors
|
||||
trackCount = 35;
|
||||
break;
|
||||
case 175531: // 35 tracks with errors
|
||||
trackCount = 35;
|
||||
break;
|
||||
case 196608: // 40 tracks no errors
|
||||
trackCount = 40;
|
||||
break;
|
||||
case 197376: // 40 tracks with errors
|
||||
trackCount = 40;
|
||||
break;
|
||||
}
|
||||
|
||||
for (int i = 0; i < trackCount; i++)
|
||||
{
|
||||
Track track = new Track();
|
||||
int sectors = sectorsPerTrack[i];
|
||||
MemoryStream trackMem = new MemoryStream();
|
||||
|
||||
for (int j = 0; j < sectors; j++)
|
||||
{
|
||||
int bitsWritten;
|
||||
byte[] sectorData = reader.ReadBytes(256);
|
||||
byte[] diskData = ConvertSectorToGCR(sectorData, (byte)j, (byte)i, (byte)0x00, (byte)0x00, out bitsWritten);
|
||||
trackMem.Write(diskData, 0, diskData.Length);
|
||||
}
|
||||
track.data = trackMem.ToArray();
|
||||
track.bits = (int)trackMem.Length;
|
||||
track.density = densityTable[i];
|
||||
track.index = i;
|
||||
result.tracks.Add(track);
|
||||
trackMem.Dispose();
|
||||
}
|
||||
|
||||
result.valid = (result.tracks.Count > 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] Write(Disk source)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,15 +5,16 @@ using System.Text;
|
|||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64
|
||||
{
|
||||
public class Track
|
||||
{
|
||||
public int bits;
|
||||
public byte[] data;
|
||||
public int density;
|
||||
public int index;
|
||||
}
|
||||
|
||||
public class Disk
|
||||
{
|
||||
public class Track
|
||||
{
|
||||
public int bits;
|
||||
public byte[] data;
|
||||
public int density;
|
||||
public int index;
|
||||
}
|
||||
|
||||
public List<Track> tracks = new List<Track>();
|
||||
public bool valid;
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
{
|
||||
int trackLength;
|
||||
byte[] trackData;
|
||||
Disk.Track track = new Disk.Track();
|
||||
Track track = new Track();
|
||||
|
||||
mem.Position = trackOffsetTable[i];
|
||||
trackLength = reader.ReadInt16();
|
||||
|
@ -55,8 +55,9 @@ namespace BizHawk.Emulation.Computers.Commodore64
|
|||
return result;
|
||||
}
|
||||
|
||||
public static void Write(Disk source)
|
||||
public static byte[] Write(Disk source)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue