From 87200593b6e682d7434e4a5da983749c3e1ff017 Mon Sep 17 00:00:00 2001 From: Anthony Konzel Date: Thu, 3 Mar 2016 21:14:19 -0600 Subject: [PATCH] C64: Internal support for multiple files and Epyx Fastload support. --- .../BizHawk.Emulation.Cores.csproj | 2 +- .../Computers/Commodore64/C64.Motherboard.cs | 2 + .../Computers/Commodore64/C64.cs | 135 +++++++++--------- .../Commodore64/Cartridge/CartridgeDevice.cs | 11 +- .../Commodore64/Cartridge/CartridgePort.cs | 6 + .../Commodore64/Cartridge/Mapper000A.cs | 83 +++++++++++ .../Computers/Commodore64/InputFileInfo.cs | 8 -- .../Computers/Commodore64/Media/Disk.cs | 1 - .../Serial/Drive1541.FluxTransitions.cs | 20 ++- .../Computers/Commodore64/Serial/Drive1541.cs | 2 +- 10 files changed, 181 insertions(+), 89 deletions(-) create mode 100644 BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs delete mode 100644 BizHawk.Emulation.Cores/Computers/Commodore64/InputFileInfo.cs diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index 6c21f9741d..50f0b3a832 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -209,6 +209,7 @@ + @@ -218,7 +219,6 @@ - diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs index d288c463de..217b5aadff 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs @@ -159,6 +159,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 _vicBank = (0x3 - ((Cia1.PrA | ~Cia1.DdrA) & 0x3)) << 14; Vic.ExecutePhase(); + CartPort.ExecutePhase(); Cassette.ExecutePhase(); Serial.ExecutePhase(); Sid.ExecutePhase(); @@ -190,6 +191,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 Cassette.HardReset(); Serial.HardReset(); Cpu.HardReset(); + CartPort.HardReset(); } public void Init() diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.cs index 33778c5e99..b14a3787e0 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 romextension, object settings, object syncSettings) + public C64(CoreComm comm, GameInfo game, byte[] rom, string extension, object settings, object syncSettings) { PutSyncSettings((C64SyncSettings)syncSettings ?? new C64SyncSettings()); PutSettings((C64Settings)settings ?? new C64Settings()); @@ -30,14 +30,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 ServiceProvider = new BasicServiceProvider(this); InputCallbacks = new InputCallbackSystem(); - _inputFileInfo = new InputFileInfo - { - Data = rom, - Extension = romextension - }; - CoreComm = comm; - Init(SyncSettings.VicType, Settings.BorderType, SyncSettings.SidType, SyncSettings.TapeDriveType, SyncSettings.DiskDriveType); + Roms = new Dictionary { { "rom" + extension.ToUpper(), rom } }; + Init(SyncSettings.VicType, Settings.BorderType, SyncSettings.SidType, SyncSettings.TapeDriveType, SyncSettings.DiskDriveType); _cyclesPerFrame = _board.Vic.CyclesPerFrame; SetupMemoryDomains(_board.DiskDrive != null); _memoryCallbacks = new MemoryCallbackSystem(); @@ -62,7 +57,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 // internal variables private int _frame; [SaveState.DoNotSave] private readonly int _cyclesPerFrame; - [SaveState.DoNotSave] private InputFileInfo _inputFileInfo; private bool _driveLed; // bizhawk I/O @@ -94,6 +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] private static readonly ControllerDefinition C64ControllerDefinition = new ControllerDefinition @@ -155,7 +150,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 // check to see if cpu PC is at the BASIC warm start vector if (_board.Cpu.Pc != 0 && _board.Cpu.Pc == ((_board.Ram.Peek(0x0303) << 8) | _board.Ram.Peek(0x0302))) { - Prg.Load(_board.Pla, _inputFileInfo.Data); + Prg.Load(_board.Pla, _prgFile); _loadPrg = false; } } @@ -182,6 +177,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 private Motherboard _board; private bool _loadPrg; + [SaveState.DoNotSave] private byte[] _prgFile; private byte[] GetFirmware(int length, params string[] names) { @@ -194,29 +190,29 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 private void Init(VicType initRegion, BorderType borderType, SidType sidType, TapeDriveType tapeDriveType, DiskDriveType diskDriveType) { // Force certain drive types to be available depending on ROM type - switch (_inputFileInfo.Extension.ToUpper()) + foreach (var rom in Roms) { - case @".D64": - case @".G64": - if (diskDriveType == DiskDriveType.None) - { - diskDriveType = DiskDriveType.Commodore1541; - } - break; - case @".TAP": - if (tapeDriveType == TapeDriveType.None) - { - tapeDriveType = TapeDriveType.Commodore1530; - } - break; - } + switch (Path.GetExtension(rom.Key).ToUpper()) + { + case @".D64": + case @".G64": + if (diskDriveType == DiskDriveType.None) + { + diskDriveType = DiskDriveType.Commodore1541; + } + break; + case @".TAP": + if (tapeDriveType == TapeDriveType.None) + { + tapeDriveType = TapeDriveType.Commodore1530; + } + break; + } + } _board = new Motherboard(this, initRegion, borderType, sidType, tapeDriveType, diskDriveType); InitRoms(diskDriveType); _board.Init(); - InitMedia(); - - // configure video CoreComm.VsyncDen = _board.Vic.CyclesPerFrame; @@ -225,42 +221,48 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 private void InitMedia() { - switch (_inputFileInfo.Extension.ToUpper()) - { - case @".D64": - var d64 = D64.Read(_inputFileInfo.Data); - if (d64 != null) - { - _board.DiskDrive.InsertMedia(d64); - } - break; - case @".G64": - var g64 = G64.Read(_inputFileInfo.Data); - if (g64 != null) - { - _board.DiskDrive.InsertMedia(g64); - } - break; - case @".CRT": - var cart = CartridgeDevice.Load(_inputFileInfo.Data); - if (cart != null) - { - _board.CartPort.Connect(cart); - } - break; - case @".TAP": - var tape = Tape.Load(_inputFileInfo.Data); - if (tape != null) - { - _board.TapeDrive.Insert(tape); - } - break; - case @".PRG": - if (_inputFileInfo.Data.Length > 2) - _loadPrg = true; - break; - } - } + foreach (var rom in Roms) + { + switch (Path.GetExtension(rom.Key).ToUpper()) + { + case @".D64": + var d64 = D64.Read(rom.Value); + if (d64 != null) + { + _board.DiskDrive.InsertMedia(d64); + } + break; + case @".G64": + var g64 = G64.Read(rom.Value); + if (g64 != null) + { + _board.DiskDrive.InsertMedia(g64); + } + break; + case @".CRT": + var cart = CartridgeDevice.Load(rom.Value); + if (cart != null) + { + _board.CartPort.Connect(cart); + } + break; + case @".TAP": + var tape = Tape.Load(rom.Value); + if (tape != null) + { + _board.TapeDrive.Insert(tape); + } + break; + case @".PRG": + if (rom.Value.Length > 2) + { + _loadPrg = true; + _prgFile = rom.Value; + } + break; + } + } + } private void InitRoms(DiskDriveType diskDriveType) { @@ -274,7 +276,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 if (diskDriveType == DiskDriveType.Commodore1541) { - var diskRom = GetFirmware(0x4000, "Drive1541II", "Drive1541"); + var diskRom = GetFirmware(0x4000, "Drive1541", "Drive1541II"); _board.DiskDrive.DriveRom.Flash(diskRom); } } @@ -283,7 +285,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 public void HardReset() { - _board.HardReset(); + InitMedia(); + _board.HardReset(); } } } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs index 40dd410c29..13c9d3dda6 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs @@ -74,7 +74,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge case 0x0005: result = new Mapper0005(chipAddress, chipBank, chipData); break; - case 0x000B: + case 0x000A: + result = new Mapper000A(chipAddress, chipBank, chipData); + break; + case 0x000B: result = new Mapper000B(chipAddress, chipData); break; case 0x000F: @@ -127,11 +130,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge [SaveState.DoNotSave] protected bool validCartridge; - public virtual void ExecutePhase1() - { - } - - public virtual void ExecutePhase2() + public virtual void ExecutePhase() { } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs index 8ea04893cb..c980d8ae85 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs @@ -89,6 +89,12 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge _connected = false; } + public void ExecutePhase() + { + if (_connected) + _cartridgeDevice.ExecutePhase(); + } + public void HardReset() { // note: this will not disconnect any attached media diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs new file mode 100644 index 0000000000..47b904d97f --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge +{ + //792 + + // Epyx Fastload. Uppermost page is always visible at DFxx. + // They use a capacitor that is recharged by accesses to DExx + // to pull down EXROM. + + public abstract partial class CartridgeDevice + { + private class Mapper000A : CartridgeDevice + { + // This constant differs depending on whose research you reference. TODO: Verify. + [SaveState.DoNotSave] + private const int RESET_CAPACITOR_CYCLES = 512; + + [SaveState.SaveWithName("CapacitorCycles")] + private int _capacitorCycles; + [SaveState.DoNotSave] + private readonly int[] _rom; + + public Mapper000A(IList newAddresses, IList newBanks, IList newData) + { + _rom = new int[0x2000]; + Array.Copy(newData.First(), _rom, 0x2000); + pinGame = true; + } + + public override void ExecutePhase() + { + pinExRom = !(_capacitorCycles > 0); + if (!pinExRom) + { + _capacitorCycles--; + } + } + + public override void HardReset() + { + _capacitorCycles = RESET_CAPACITOR_CYCLES; + base.HardReset(); + } + + public override int Peek8000(int addr) + { + return _rom[addr & 0x1FFF]; + } + + public override int PeekDE00(int addr) + { + return 0x00; + } + + public override int PeekDF00(int addr) + { + return _rom[(addr & 0xFF) | 0x1F00]; + } + + public override int Read8000(int addr) + { + _capacitorCycles = RESET_CAPACITOR_CYCLES; + return _rom[addr & 0x1FFF]; + } + + public override int ReadDE00(int addr) + { + _capacitorCycles = RESET_CAPACITOR_CYCLES; + return 0x00; + } + + public override int ReadDF00(int addr) + { + return _rom[(addr & 0xFF) | 0x1F00]; + } + } + } + +} diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/InputFileInfo.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/InputFileInfo.cs deleted file mode 100644 index 464d647d6e..0000000000 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/InputFileInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace BizHawk.Emulation.Cores.Computers.Commodore64 -{ - public struct InputFileInfo - { - public byte[] Data; - public string Extension; - } -} diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs index a8a43e6f6b..339d7b215e 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Media/Disk.cs @@ -72,7 +72,6 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Media paddedBytes[i] = 0xAA; } var result = new int[FluxEntriesPerTrack]; - var length = paddedLength; var lengthBits = (paddedLength * 8) - 7; var offsets = new List(); var remainingBits = lengthBits; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs index 6a393af42d..ae2b18361e 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs @@ -48,15 +48,23 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial // rotate disk if (_motorEnabled) { - if (_diskBitsLeft <= 0) + if (_disk == null) { - _diskByteOffset++; - if (_diskByteOffset == Disk.FluxEntriesPerTrack) + _diskBitsLeft = 1; + _diskBits = 0; + } + else + { + if (_diskBitsLeft <= 0) { - _diskByteOffset = 0; + _diskByteOffset++; + if (_diskByteOffset == Disk.FluxEntriesPerTrack) + { + _diskByteOffset = 0; + } + _diskBits = _trackImageData[_diskByteOffset]; + _diskBitsLeft = Disk.FluxBitsPerEntry; } - _diskBits = _trackImageData[_diskByteOffset]; - _diskBitsLeft = Disk.FluxBitsPerEntry; } if ((_diskBits & 1) != 0) { diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs index 82bba29bf1..306352c90d 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.cs @@ -218,7 +218,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial public void RemoveMedia() { - _trackImageData = new int[1]; + _disk = null; } public int Peek(int addr)