diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj index b8961e5eb6..cdbc943f47 100644 --- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj +++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj @@ -209,6 +209,7 @@ + @@ -217,6 +218,7 @@ + diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs index 071e3f2dff..641692ffda 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.Motherboard.cs @@ -196,7 +196,9 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 } public void Init() - { + { + CartPort.ReadOpenBus = ReadOpenBus; + Cassette.ReadDataOutput = CassPort_ReadDataOutput; Cassette.ReadMotor = CassPort_ReadMotor; diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.MotherboardInterface.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.MotherboardInterface.cs index 95f99362c2..14375eceb6 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/C64.MotherboardInterface.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/C64.MotherboardInterface.cs @@ -172,5 +172,10 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64 _lastReadVicData = Pla.VicRead(_lastReadVicAddress); return _lastReadVicData; } + + private int ReadOpenBus() + { + return _lastReadVicData; + } } } diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs index 7fed92029f..3636f28b85 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs @@ -9,6 +9,8 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge { public abstract partial class CartridgeDevice : IDriveLight { + public Func ReadOpenBus; + public static CartridgeDevice Load(byte[] crtFile) { using (var mem = new MemoryStream(crtFile)) @@ -70,33 +72,39 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge CartridgeDevice result; switch (mapper) { - case 0x0000: + case 0x0000: // Standard Cartridge result = new Mapper0000(chipAddress, chipData, game, exrom); break; - case 0x0005: + case 0x0001: // Action Replay (4.2 and up) + result = new Mapper0001(chipAddress, chipBank, chipData); + break; + case 0x0005: // Ocean result = new Mapper0005(chipAddress, chipBank, chipData); break; - case 0x000A: - result = new Mapper000A(chipAddress, chipBank, chipData); + case 0x000A: // Epyx FastLoad + result = new Mapper000A(chipData); break; - case 0x000B: + case 0x000B: // Westermann Learning result = new Mapper000B(chipAddress, chipData); break; - case 0x000F: + case 0x000F: // C64 Game System / System 3 result = new Mapper000F(chipAddress, chipBank, chipData); break; - case 0x0011: + case 0x0011: // Dinamic result = new Mapper0011(chipAddress, chipBank, chipData); break; - case 0x0012: + case 0x0012: // Zaxxon / Super Zaxxon result = new Mapper0012(chipAddress, chipBank, chipData); break; - case 0x0013: + case 0x0013: // Domark result = new Mapper0013(chipAddress, chipBank, chipData); break; - case 0x0020: + case 0x0020: // EasyFlash result = new Mapper0020(chipAddress, chipBank, chipData); break; + case 0x002B: // Prophet 64 + result = new Mapper002B(chipAddress, chipBank, chipData); + break; default: throw new Exception("This cartridge file uses an unrecognized mapper: " + mapper); } @@ -182,22 +190,22 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge public virtual int Peek8000(int addr) { - return 0xFF; + return ReadOpenBus(); } public virtual int PeekA000(int addr) { - return 0xFF; + return ReadOpenBus(); } public virtual int PeekDE00(int addr) { - return 0xFF; + return ReadOpenBus(); } public virtual int PeekDF00(int addr) { - return 0xFF; + return ReadOpenBus(); } public virtual void Poke8000(int addr, int val) @@ -218,22 +226,22 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge public virtual int Read8000(int addr) { - return 0xFF; + return ReadOpenBus(); } public virtual int ReadA000(int addr) { - return 0xFF; + return ReadOpenBus(); } public virtual int ReadDE00(int addr) { - return 0xFF; + return ReadOpenBus(); } public virtual int ReadDF00(int addr) { - return 0xFF; + return ReadOpenBus(); } [SaveState.DoNotSave] diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs index 9ca7f2112b..88c65a1a47 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgePort.cs @@ -1,10 +1,13 @@ -using BizHawk.Common; +using System; +using BizHawk.Common; using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge { public sealed class CartridgePort : IDriveLight { + public Func ReadOpenBus; + private CartridgeDevice _cartridgeDevice; private bool _connected; @@ -82,6 +85,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge { _connected = true; _cartridgeDevice = newCartridgeDevice; + newCartridgeDevice.ReadOpenBus = ReadOpenBus; } public void Disconnect() diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0001.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0001.cs new file mode 100644 index 0000000000..d2dd29fbec --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0001.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge +{ + public abstract partial class CartridgeDevice + { + private sealed class Mapper0001 : CartridgeDevice + { + [SaveState.SaveWithName("RAM")] private readonly int[] _ram = new int[0x2000]; + [SaveState.SaveWithName("RAMEnabled")] private bool _ramEnabled; + [SaveState.DoNotSave] private readonly int[] _rom = new int[0x8000]; + [SaveState.SaveWithName("ROMOffset")] private int _romOffset; + [SaveState.SaveWithName("CartEnabled")] private bool _cartEnabled; + + public Mapper0001(IList newAddresses, IList newBanks, IList newData) + { + pinExRom = false; + pinGame = false; + for (var i = 0; i < newData.Count; i++) + { + if (newAddresses[i] == 0x8000) + Array.Copy(newData[i], 0, _rom, 0x2000 * newBanks[i], 0x2000); + } + _romOffset = 0; + _cartEnabled = true; + } + + public override void HardReset() + { + base.HardReset(); + pinExRom = false; + pinGame = false; + for (var i = 0; i < 0x2000; i++) + _ram[i] = 0x00; + _romOffset = 0; + _cartEnabled = true; + } + + public override int Peek8000(int addr) + { + return GetLoRom(addr); + } + + public override int PeekA000(int addr) + { + return Peek8000(addr); + } + + public override int PeekDF00(int addr) + { + return GetIo2(addr); + } + + public override void Poke8000(int addr, int val) + { + SetLoRom(addr, val); + } + + public override void PokeA000(int addr, int val) + { + Poke8000(addr, val); + } + + public override void PokeDE00(int addr, int val) + { + SetState(val); + } + + public override void PokeDF00(int addr, int val) + { + SetIo2(addr, val); + } + + public override int Read8000(int addr) + { + return GetLoRom(addr); + } + + public override int ReadA000(int addr) + { + return GetHiRom(addr); + } + + public override int ReadDF00(int addr) + { + return GetIo2(addr); + } + + public override void Write8000(int addr, int val) + { + SetLoRom(addr, val); + } + + public override void WriteA000(int addr, int val) + { + SetLoRom(addr, val); + } + + public override void WriteDE00(int addr, int val) + { + SetState(val); + } + + public override void WriteDF00(int addr, int val) + { + SetIo2(addr, val); + } + + private void SetState(int val) + { + pinGame = (val & 0x01) == 0; + pinExRom = (val & 0x02) != 0; + _cartEnabled = (val & 0x04) == 0; + _romOffset = (val & 0x18) << 10; + _ramEnabled = (val & 0x20) == 0; + } + + private int GetLoRom(int addr) + { + return _ramEnabled + ? _ram[addr & 0x1FFF] + : _rom[(addr & 0x1FFF) | _romOffset]; + } + + private int GetHiRom(int addr) + { + return _rom[(addr & 0x1FFF) | _romOffset]; + } + + private void SetLoRom(int addr, int val) + { + _ram[addr & 0x1FFF] = val; + } + + private int GetIo2(int addr) + { + if (!_cartEnabled) + return ReadOpenBus(); + + return _ramEnabled + ? _ram[(addr & 0xFF) | 0x1F00] + : _rom[(addr & 0xFF) | _romOffset | 0x1F00]; + } + + private void SetIo2(int addr, int val) + { + _ram[addr & 0x1FFF] = val & 0xFF; + } + } + } +} diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs index 47b904d97f..e3e1250e91 100644 --- a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper000A.cs @@ -5,11 +5,11 @@ 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. + // They use a capacitor that is discharged by accesses to DExx + // to pull down EXROM. Also, accesses to LOROM while it is active + // discharge the capacitor. + // Thanks to VICE team for the info: http://vice-emu.sourceforge.net/vice_15.html public abstract partial class CartridgeDevice { @@ -24,7 +24,7 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge [SaveState.DoNotSave] private readonly int[] _rom; - public Mapper000A(IList newAddresses, IList newBanks, IList newData) + public Mapper000A(IList newData) { _rom = new int[0x2000]; Array.Copy(newData.First(), _rom, 0x2000); diff --git a/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper002B.cs b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper002B.cs new file mode 100644 index 0000000000..8e14566357 --- /dev/null +++ b/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper002B.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge +{ + // Prophet 64 cartridge. Because we can. + // 32 banks of 8KB. + // DFxx = status register, xxABBBBB. A=enable cart, B=bank + // Thanks to VICE team for the info: http://vice-emu.sourceforge.net/vice_15.html + + public abstract partial class CartridgeDevice + { + private class Mapper002B : CartridgeDevice + { + [SaveState.DoNotSave] + private readonly int[] _rom; + [SaveState.SaveWithName("RomOffset")] + private int _romOffset; + [SaveState.SaveWithName("RomEnabled")] + private bool _romEnabled; + + public Mapper002B(IList newAddresses, IList newBanks, IList newData) + { + pinExRom = false; + pinGame = true; + _rom = new int[0x40000]; + Array.Copy(newData.First(), _rom, 0x2000); + pinGame = true; + for (var i = 0; i < newData.Count; i++) + { + if (newAddresses[i] == 0x8000) + { + Array.Copy(newData[i], 0, _rom, newBanks[i] * 0x2000, 0x2000); + } + } + } + + public override void HardReset() + { + _romEnabled = true; + _romOffset = 0; + } + + public override int Peek8000(int addr) + { + return _romOffset | (addr & 0x1FFF); + } + + public override int PeekDF00(int addr) + { + // For debugging only. The processor does not see this. + return ((_romOffset >> 13) & 0x1F) | (_romEnabled ? 0x20 : 0x00); + } + + public override void PokeDF00(int addr, int val) + { + _romOffset = (val & 0x1F) << 13; + _romEnabled = (val & 0x20) != 0; + } + + public override int Read8000(int addr) + { + return _romOffset | (addr & 0x1FFF); + } + + public override int ReadDF00(int addr) + { + return 0x00; + } + + public override void WriteDF00(int addr, int val) + { + _romOffset = (val & 0x1F) << 13; + _romEnabled = (val & 0x20) != 0; + } + } + } +}