BizHawk/BizHawk.Emulation.Cores/Computers/Commodore64/Cartridge/Mapper0005.cs

173 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Cartridge
{
internal sealed class Mapper0005 : CartridgeDevice
{
private readonly int[][] _banksA; // 8000
private readonly int[][] _banksB = new int[0][]; // A000
private int _bankMask;
private int _bankNumber;
private int[] _currentBankA;
private int[] _currentBankB;
private readonly int[] _dummyBank;
public Mapper0005(IList<int> newAddresses, IList<int> newBanks, IList<int[]> newData)
{
var count = newAddresses.Count;
// build dummy bank
_dummyBank = new int[0x2000];
for (var i = 0; i < 0x2000; i++)
{
_dummyBank[i] = 0xFF; // todo: determine if this is correct
}
switch (count)
{
case 64:
pinGame = true;
pinExRom = false;
_bankMask = 0x3F;
_banksA = new int[64][];
break;
case 32:
// this specific config is a weird exception
pinGame = false;
pinExRom = false;
_bankMask = 0x0F;
_banksA = new int[16][];
_banksB = new int[16][];
break;
case 16:
pinGame = true;
pinExRom = false;
_bankMask = 0x0F;
_banksA = new int[16][];
break;
case 8:
pinGame = true;
pinExRom = false;
_bankMask = 0x07;
_banksA = new int[8][];
break;
case 4:
pinGame = true;
pinExRom = false;
_bankMask = 0x03;
_banksA = new int[4][];
break;
case 2:
pinGame = true;
pinExRom = false;
_bankMask = 0x01;
_banksA = new int[2][];
break;
case 1:
pinGame = true;
pinExRom = false;
_bankMask = 0x00;
_banksA = new int[1][];
break;
default:
throw new Exception("This looks like an Ocean cartridge but cannot be loaded...");
}
// for safety, initialize all banks to dummy
for (var i = 0; i < _banksA.Length; i++)
{
_banksA[i] = _dummyBank;
}
for (var i = 0; i < _banksB.Length; i++)
{
_banksB[i] = _dummyBank;
}
// now load in the banks
for (var i = 0; i < count; i++)
{
switch (newAddresses[i])
{
case 0x8000:
_banksA[newBanks[i] & _bankMask] = newData[i];
break;
case 0xA000:
case 0xE000:
_banksB[newBanks[i] & _bankMask] = newData[i];
break;
}
}
BankSet(0);
}
protected override void SyncStateInternal(Serializer ser)
{
ser.Sync("BankMask", ref _bankMask);
ser.Sync("BankNumber", ref _bankNumber);
}
private void BankSet(int index)
{
_bankNumber = index & _bankMask;
_currentBankA = !pinExRom ? _banksA[_bankNumber] : _dummyBank;
_currentBankB = !pinGame ? _banksB[_bankNumber] : _dummyBank;
}
public override int Peek8000(int addr)
{
return _currentBankA[addr];
}
public override int PeekA000(int addr)
{
return _currentBankB[addr];
}
public override void PokeDE00(int addr, int val)
{
if (addr == 0x00)
{
BankSet(val);
}
}
public override int Read8000(int addr)
{
return _currentBankA[addr];
}
public override int ReadA000(int addr)
{
return _currentBankB[addr];
}
public override void WriteDE00(int addr, int val)
{
if (addr == 0x00)
{
BankSet(val);
}
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
if (ser.IsReader)
{
BankSet(_bankNumber);
}
}
}
}