From 8fd552274ea421b36137aef11d098ce5425ce6c7 Mon Sep 17 00:00:00 2001 From: Anthony Konzel Date: Sat, 5 Mar 2016 15:23:22 -0600 Subject: [PATCH] C64: Discover file formats heuristically instead of by filename. --- BizHawk.Client.Common/RomLoader.cs | 2 +- .../BizHawk.Emulation.Cores.csproj | 2 + .../Computers/Commodore64/C64.ISettable.cs | 2 +- .../Computers/Commodore64/C64.cs | 51 +++++++++++-------- .../Computers/Commodore64/C64Format.cs | 24 +++++++++ .../Computers/Commodore64/C64FormatFinder.cs | 47 +++++++++++++++++ .../Computers/Commodore64/Media/D64.cs | 2 +- .../Computers/Commodore64/Media/Disk.cs | 2 +- .../Computers/Commodore64/Media/G64.cs | 2 +- .../Computers/Commodore64/Serial/Drive1541.cs | 2 +- 10 files changed, 108 insertions(+), 28 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Computers/Commodore64/C64Format.cs create mode 100644 BizHawk.Emulation.Cores/Computers/Commodore64/C64FormatFinder.cs diff --git a/BizHawk.Client.Common/RomLoader.cs b/BizHawk.Client.Common/RomLoader.cs index 677f153f25..b8e00b5874 100644 --- a/BizHawk.Client.Common/RomLoader.cs +++ b/BizHawk.Client.Common/RomLoader.cs @@ -776,7 +776,7 @@ namespace BizHawk.Client.Common nextEmulator = new Atari7800(nextComm, game, rom.RomData, gamedbpath); break; case "C64": - var c64 = new C64(nextComm, game, rom.RomData, rom.Extension, GetCoreSettings(), GetCoreSyncSettings()); + var c64 = new C64(nextComm, game, rom.RomData, GetCoreSettings(), GetCoreSyncSettings()); nextEmulator = c64; break; case "GBA": diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 728146771b..b8961e5eb6 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -205,6 +205,7 @@ + @@ -218,6 +219,7 @@ + diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs index b0cf805828..a34ff6f602 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.ISettable.cs @@ -115,7 +115,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 public enum DiskDriveType { - None, Commodore1541, Commodore1541II + None, Commodore1541, Commodore1541II, Commodore1571 } } } \ No newline at end of file diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs index 5b80726e40..632e72073d 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs @@ -22,7 +22,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 public sealed partial class C64 : IEmulator, IRegionable { // framework - public C64(CoreComm comm, GameInfo game, byte[] rom, string extension, object settings, object syncSettings) + public C64(CoreComm comm, GameInfo game, byte[] rom, object settings, object syncSettings) { PutSyncSettings((C64SyncSettings)syncSettings ?? new C64SyncSettings()); PutSettings((C64Settings)settings ?? new C64Settings()); @@ -31,7 +31,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 InputCallbacks = new InputCallbackSystem(); CoreComm = comm; - Roms = new Dictionary { { "rom" + extension.ToUpper(), rom } }; + Roms = new List { rom }; Init(SyncSettings.VicType, Settings.BorderType, SyncSettings.SidType, SyncSettings.TapeDriveType, SyncSettings.DiskDriveType); _cyclesPerFrame = _board.Vic.CyclesPerFrame; SetupMemoryDomains(_board.DiskDrive != null); @@ -88,7 +88,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 // controller [SaveState.DoNotSave] public ControllerDefinition ControllerDefinition { get { return C64ControllerDefinition; } } [SaveState.DoNotSave] public IController Controller { get { return _board.Controller; } set { _board.Controller = value; } } - [SaveState.DoNotSave] public IDictionary Roms { get; private set; } + [SaveState.DoNotSave] public IEnumerable Roms { get; private set; } [SaveState.DoNotSave] private static readonly ControllerDefinition C64ControllerDefinition = new ControllerDefinition @@ -204,16 +204,20 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 // Force certain drive types to be available depending on ROM type foreach (var rom in Roms) { - switch (Path.GetExtension(rom.Key).ToUpper()) + switch (C64FormatFinder.GetFormat(rom)) { - case @".D64": - case @".G64": + case C64Format.D64: + case C64Format.G64: + case C64Format.X64: if (diskDriveType == DiskDriveType.None) - { diskDriveType = DiskDriveType.Commodore1541; - } break; - case @".TAP": + case C64Format.D71: + if (diskDriveType == DiskDriveType.None) + diskDriveType = DiskDriveType.Commodore1571; + break; + case C64Format.T64: + case C64Format.TAP: if (tapeDriveType == TapeDriveType.None) { tapeDriveType = TapeDriveType.Commodore1530; @@ -235,41 +239,41 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 { foreach (var rom in Roms) { - switch (Path.GetExtension(rom.Key).ToUpper()) + switch (C64FormatFinder.GetFormat(rom)) { - case @".D64": - var d64 = D64.Read(rom.Value); + case C64Format.D64: + var d64 = D64.Read(rom); if (d64 != null) { _board.DiskDrive.InsertMedia(d64); } break; - case @".G64": - var g64 = G64.Read(rom.Value); + case C64Format.G64: + var g64 = G64.Read(rom); if (g64 != null) { _board.DiskDrive.InsertMedia(g64); } break; - case @".CRT": - var cart = CartridgeDevice.Load(rom.Value); + case C64Format.CRT: + var cart = CartridgeDevice.Load(rom); if (cart != null) { _board.CartPort.Connect(cart); } break; - case @".TAP": - var tape = Tape.Load(rom.Value); + case C64Format.TAP: + var tape = Tape.Load(rom); if (tape != null) { _board.TapeDrive.Insert(tape); } break; - case @".PRG": - if (rom.Value.Length > 2) + default: + if (rom.Length > 2) { _loadPrg = true; - _prgFile = rom.Value; + _prgFile = rom; } break; } @@ -290,8 +294,11 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 case DiskDriveType.Commodore1541II: _board.DiskDrive.DriveRom.Flash(GetFirmware(0x4000, "Drive1541II")); break; + case DiskDriveType.Commodore1571: + _board.DiskDrive.DriveRom.Flash(GetFirmware(0x8000, "Drive1571")); + break; } - } + } // ------------------------------------ diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64Format.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64Format.cs new file mode 100644 index 0000000000..b730b49d05 --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64Format.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Cores.Computers.Commodore64 +{ + public enum C64Format + { + Unknown, + D64, + D71, + D81, + X64, + G64, + T64, + TAP, + CRT, + P64, + P00, + D82, + D80, + } +} diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64FormatFinder.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64FormatFinder.cs new file mode 100644 index 0000000000..36126f7c5d --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64FormatFinder.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Cores.Computers.Commodore64 +{ + public static class C64FormatFinder + { + public static C64Format GetFormat(byte[] data) + { + if (data == null || data.Length < 0x10) + return C64Format.Unknown; + using (var mem = new MemoryStream(data)) + { + var reader = new BinaryReader(mem); + var header = Encoding.GetEncoding(437).GetString(reader.ReadBytes(0x10)); + if (header.StartsWith("C64 CARTRIDGE ")) + return C64Format.CRT; + if (header.StartsWith("GCR-1541")) + return C64Format.G64; + if (header.StartsWith("C64S tape image ")) + return C64Format.T64; + if (header.StartsWith("C64-TAPE-RAW")) + return C64Format.TAP; + if (header.StartsWith("C64File")) + return C64Format.P00; + if (header.StartsWith("P64-1541")) + return C64Format.P64; + if (data[0] == 0x43 && data[1] == 0x15 && data[2] == 0x41 && data[3] == 0x64) + return C64Format.X64; + if (data.Length == 174848 || data.Length == 175531 || data.Length == 196608 || data.Length == 197376) + return C64Format.D64; + if (data.Length == 349696 || data.Length == 351062) + return C64Format.D71; + if (data.Length == 533248) + return C64Format.D80; + if (data.Length == 819200 || data.Length == 822400) + return C64Format.D81; + if (data.Length == 1066496) + return C64Format.D82; + } + return C64Format.Unknown; + } + } +} diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs index 188f69acf8..e1f27c3ed0 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/D64.cs @@ -202,7 +202,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media } } - return new Disk(trackDatas, trackNumbers, trackDensities, trackLengths, 84); + return new Disk(trackDatas, trackNumbers, trackDensities, 84); } } } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs index 189066f5ee..e9874d481e 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs @@ -35,7 +35,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media /// Density zones for the raw bit data. /// Length, in bits, of each raw bit data. /// Total number of tracks on the media. - public Disk(IList trackData, IList trackNumbers, IList trackDensities, IList trackLengths, int trackCapacity) + public Disk(IList trackData, IList trackNumbers, IList trackDensities, int trackCapacity) { WriteProtected = true; _tracks = new int[trackCapacity][]; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs index 2ddac42728..26b24523b3 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/G64.cs @@ -54,7 +54,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media throw new Exception("Byte-level speeds are not yet supported in the G64 loader."); } - return new Disk(trackDatas, trackNumbers, trackDensities, trackLengths, 84); + return new Disk(trackDatas, trackNumbers, trackDensities, 84); } return new Disk(84); diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs index c31635e03c..e7afd30f56 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs @@ -119,7 +119,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial if (_ledEnabled) { - _driveLightOffTime = 1000000; + _driveLightOffTime = 25000; } else if (_driveLightOffTime > 0) {