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)