diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeChip.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeChip.cs index e370bce84b..1fa912ecdb 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeChip.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeChip.cs @@ -5,4 +5,16 @@ public class CartridgeChip public int Address; public int Bank; public int[] Data; + + /// + /// This exists to bridge the gap between the old int[] representation + /// and the new byte[] representation of . + /// + public byte[] ConvertDataToBytes() + { + var result = new byte[Data.Length]; + for (var i = 0; i < Data.Length; i++) + result[i] = unchecked((byte) Data[i]); + return result; + } } \ No newline at end of file diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs index e61507d16a..17e601d98c 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/CartridgeDevice.cs @@ -103,7 +103,7 @@ public static CartridgeDevice Load(byte[] crtFile) result = new Mapper0012(chipAddress, chipBank, chipData); break; case 0x0013: // Domark - result = new Mapper0013(chipAddress, chipBank, chipData); + result = new Mapper0013(BuildChipList(chipAddress, chipBank, chipData)); break; case 0x0020: // EasyFlash result = new Mapper0020(BuildChipList(chipAddress, chipBank, chipData)); diff --git a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0013.cs b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0013.cs index 946cc45448..50f9324d20 100644 --- a/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0013.cs +++ b/src/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0013.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; - using BizHawk.Common; +using BizHawk.Emulation.Common; namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge { @@ -11,71 +11,87 @@ namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge // // Bank select is DE00, bit 7 enabled means to disable // ROM in 8000-9FFF. + internal sealed class Mapper0013 : CartridgeDevice { - private readonly int[][] _banks; // 8000 + private const int BankSize = 0x2000; + private const byte DummyData = 0xFF; - private int _bankMask; - private int _bankNumber; - - private int[] _currentBank; + private readonly byte[][] _banks = new byte[128][]; + private readonly byte _bankMask; + private readonly int _bankCount; + private byte _bankNumber; + private byte[] _currentBank; private bool _romEnable; - public Mapper0013(IList newAddresses, IList newBanks, IList newData) + public Mapper0013(IEnumerable chips) { - var count = newAddresses.Count; - pinGame = true; pinExRom = false; _romEnable = true; - // build dummy bank - var dummyBank = new int[0x2000]; - for (var i = 0; i < 0x2000; i++) - { - dummyBank[i] = 0xFF; // todo: determine if this is correct - } + // This bank will be chosen if uninitialized. + var dummyBank = new byte[BankSize]; + dummyBank.AsSpan().Fill(DummyData); + _banks.AsSpan().Fill(dummyBank); + _bankMask = 0x00; - switch (count) + // Load in each bank. + var maxBank = 0; + foreach (var chip in chips) { - case 16: - _bankMask = 0x0F; - _banks = new int[16][]; - break; - case 8: - _bankMask = 0x07; - _banks = new int[8][]; - break; - case 4: - _bankMask = 0x03; - _banks = new int[4][]; - break; - default: - throw new Exception("This looks like a Domark/HES cartridge but cannot be loaded..."); - } + // Maximum 128 banks. + if (chip.Bank is > 0x7F or < 0x00) + { + throw new Exception("Cartridge image has an invalid bank"); + } + + // Addresses other than 0x8000 are not supported. + if (chip.Address != 0x8000) + { + continue; + } - // for safety, initialize all banks to dummy - for (var i = 0; i < _banks.Length; i++) - { - _banks[i] = dummyBank; - } + // Bank wrap-around is based on powers of 2. + while (chip.Bank > _bankMask) + { + _bankMask = unchecked((byte) ((_bankMask << 1) | 1)); + } + + var bank = new byte[BankSize]; - // now load in the banks - for (var i = 0; i < count; i++) - { - if (newAddresses[i] == 0x8000) + bank.AsSpan().Fill(DummyData); + chip.ConvertDataToBytes().CopyTo(bank.AsSpan()); + + _banks[chip.Bank] = bank; + + if (chip.Bank > maxBank) { - _banks[newBanks[i] & _bankMask] = newData[i]; + maxBank = chip.Bank; } } + _bankCount = maxBank + 1; + + // Start with bank 0. BankSet(0); } + public override IEnumerable CreateMemoryDomains() + { + yield return new MemoryDomainDelegate( + name: "ROM", + size: _bankCount * BankSize, + endian: MemoryDomain.Endian.Little, + peek: a => _banks[a >> 13][a & 0x1FFF], + poke: (a, d) => _banks[a >> 13][a & 0x1FFF] = d, + wordSize: 1 + ); + } + protected override void SyncStateInternal(Serializer ser) { - ser.Sync("BankMask", ref _bankMask); ser.Sync("BankNumber", ref _bankNumber); ser.Sync("ROMEnable", ref _romEnable); @@ -87,15 +103,13 @@ protected override void SyncStateInternal(Serializer ser) private void BankSet(int index) { - _bankNumber = index & _bankMask; + _bankNumber = unchecked((byte) (index & _bankMask)); _romEnable = (index & 0x80) == 0; UpdateState(); } - public override int Peek8000(int addr) - { - return _currentBank[addr]; - } + public override int Peek8000(int addr) => + _currentBank[addr]; public override void PokeDE00(int addr, int val) { @@ -105,24 +119,16 @@ public override void PokeDE00(int addr, int val) } } - public override int Read8000(int addr) - { - return _currentBank[addr]; - } + public override int Read8000(int addr) => + _currentBank[addr]; private void UpdateState() { _currentBank = _banks[_bankNumber]; - if (_romEnable) - { - pinExRom = false; - pinGame = true; - } - else - { - pinExRom = true; - pinGame = true; - } + + (pinExRom, pinGame) = _romEnable + ? (false, true) + : (true, true); } public override void WriteDE00(int addr, int val)