2013-04-14 20:39:19 +00:00
|
|
|
|
using System.Collections.Generic;
|
2013-11-04 00:36:15 +00:00
|
|
|
|
using BizHawk.Common;
|
2012-11-29 17:58:35 +00:00
|
|
|
|
|
2013-11-12 19:22:09 +00:00
|
|
|
|
namespace BizHawk.Emulation.Cores.Computers.Commodore64
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
|
|
|
|
// EasyFlash cartridge
|
|
|
|
|
// No official games came on one of these but there
|
|
|
|
|
// are a few dumps from GameBase64 that use this mapper
|
|
|
|
|
|
|
|
|
|
// There are 64 banks total, DE00 is bank select.
|
|
|
|
|
// Selecing a bank will select both Lo and Hi ROM.
|
|
|
|
|
// DE02 will switch exrom/game bits: bit 0=game,
|
|
|
|
|
// bit 1=exrom, bit 2=for our cases, always set true.
|
|
|
|
|
// These two registers are write only.
|
|
|
|
|
|
|
|
|
|
// This cartridge always starts up in Ultimax mode,
|
|
|
|
|
// with Game set high and ExRom set low.
|
|
|
|
|
|
|
|
|
|
// There is also 256 bytes RAM at DF00-DFFF.
|
2012-12-06 06:25:30 +00:00
|
|
|
|
|
|
|
|
|
public class Mapper0020 : Cart
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
|
|
|
|
private byte[][] banksA = new byte[64][]; //8000
|
|
|
|
|
private byte[][] banksB = new byte[64][]; //A000
|
2013-08-14 05:05:17 +00:00
|
|
|
|
private int bankNumber;
|
2012-11-29 17:58:35 +00:00
|
|
|
|
private bool boardLed;
|
|
|
|
|
private byte[] currentBankA;
|
|
|
|
|
private byte[] currentBankB;
|
|
|
|
|
private byte[] dummyBank;
|
2013-08-19 08:30:37 +00:00
|
|
|
|
private bool jumper = false;
|
|
|
|
|
private int stateBits;
|
2012-11-29 17:58:35 +00:00
|
|
|
|
private byte[] ram = new byte[256];
|
|
|
|
|
|
2013-08-14 05:05:17 +00:00
|
|
|
|
public Mapper0020(List<int> newAddresses, List<int> newBanks, List<byte[]> newData)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
2013-08-14 05:05:17 +00:00
|
|
|
|
int count = newAddresses.Count;
|
2012-11-29 17:58:35 +00:00
|
|
|
|
|
|
|
|
|
// build dummy bank
|
|
|
|
|
dummyBank = new byte[0x2000];
|
2013-08-14 05:05:17 +00:00
|
|
|
|
for (int i = 0; i < 0x2000; i++)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
dummyBank[i] = 0xFF; // todo: determine if this is correct
|
|
|
|
|
|
|
|
|
|
// force ultimax mode (the cart SHOULD set this
|
|
|
|
|
// otherwise on load, according to the docs)
|
|
|
|
|
pinGame = false;
|
|
|
|
|
pinExRom = true;
|
|
|
|
|
|
|
|
|
|
// for safety, initialize all banks to dummy
|
2013-08-14 05:05:17 +00:00
|
|
|
|
for (int i = 0; i < 64; i++)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
banksA[i] = dummyBank;
|
2013-08-14 05:05:17 +00:00
|
|
|
|
for (int i = 0; i < 64; i++)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
banksB[i] = dummyBank;
|
|
|
|
|
|
|
|
|
|
// load in all banks
|
|
|
|
|
for (int i = 0; i < count; i++)
|
|
|
|
|
{
|
|
|
|
|
if (newAddresses[i] == 0x8000)
|
|
|
|
|
{
|
|
|
|
|
banksA[newBanks[i]] = newData[i];
|
|
|
|
|
}
|
|
|
|
|
else if (newAddresses[i] == 0xA000 || newAddresses[i] == 0xE000)
|
|
|
|
|
{
|
|
|
|
|
banksB[newBanks[i]] = newData[i];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// default to bank 0
|
|
|
|
|
BankSet(0);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-14 05:05:17 +00:00
|
|
|
|
private void BankSet(int index)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
|
|
|
|
bankNumber = index & 0x3F;
|
|
|
|
|
UpdateState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override byte Peek8000(int addr)
|
|
|
|
|
{
|
|
|
|
|
return currentBankA[addr];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override byte PeekA000(int addr)
|
|
|
|
|
{
|
|
|
|
|
return currentBankB[addr];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override byte PeekDE00(int addr)
|
|
|
|
|
{
|
|
|
|
|
// normally you can't read these regs
|
|
|
|
|
// but Peek is provided here for debug reasons
|
|
|
|
|
// and may not stay around
|
2013-08-19 08:30:37 +00:00
|
|
|
|
addr &= 0x02;
|
|
|
|
|
if (addr == 0x00)
|
|
|
|
|
return (byte)bankNumber;
|
|
|
|
|
else
|
|
|
|
|
return (byte)stateBits;
|
2012-11-29 17:58:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override byte PeekDF00(int addr)
|
|
|
|
|
{
|
|
|
|
|
return ram[addr];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PokeDE00(int addr, byte val)
|
|
|
|
|
{
|
2013-08-19 08:30:37 +00:00
|
|
|
|
addr &= 0x02;
|
2012-11-29 17:58:35 +00:00
|
|
|
|
if (addr == 0x00)
|
|
|
|
|
BankSet(val);
|
2013-08-19 08:30:37 +00:00
|
|
|
|
else
|
2012-11-29 17:58:35 +00:00
|
|
|
|
StateSet(val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public override void PokeDF00(int addr, byte val)
|
|
|
|
|
{
|
|
|
|
|
ram[addr] = val;
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-14 05:05:17 +00:00
|
|
|
|
public override byte Read8000(int addr)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
|
|
|
|
return currentBankA[addr];
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-14 05:05:17 +00:00
|
|
|
|
public override byte ReadA000(int addr)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
|
|
|
|
return currentBankB[addr];
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-14 05:05:17 +00:00
|
|
|
|
public override byte ReadDF00(int addr)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
|
|
|
|
return ram[addr];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void StateSet(byte val)
|
|
|
|
|
{
|
2013-08-19 08:30:37 +00:00
|
|
|
|
stateBits = val &= 0x87;
|
|
|
|
|
if ((val & 0x04) != 0)
|
|
|
|
|
pinGame = ((val & 0x01) == 0);
|
|
|
|
|
else
|
|
|
|
|
pinGame = jumper;
|
2012-11-29 17:58:35 +00:00
|
|
|
|
pinExRom = ((val & 0x02) == 0);
|
2013-08-19 08:30:37 +00:00
|
|
|
|
boardLed = ((val & 0x80) != 0);
|
2012-11-29 17:58:35 +00:00
|
|
|
|
UpdateState();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateState()
|
|
|
|
|
{
|
|
|
|
|
currentBankA = banksA[bankNumber];
|
|
|
|
|
currentBankB = banksB[bankNumber];
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-14 05:05:17 +00:00
|
|
|
|
public override void WriteDE00(int addr, byte val)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
2013-08-19 08:30:37 +00:00
|
|
|
|
addr &= 0x02;
|
2012-11-29 17:58:35 +00:00
|
|
|
|
if (addr == 0x00)
|
|
|
|
|
BankSet(val);
|
2013-08-19 08:30:37 +00:00
|
|
|
|
else
|
2012-11-29 17:58:35 +00:00
|
|
|
|
StateSet(val);
|
|
|
|
|
}
|
|
|
|
|
|
2013-08-14 05:05:17 +00:00
|
|
|
|
public override void WriteDF00(int addr, byte val)
|
2012-11-29 17:58:35 +00:00
|
|
|
|
{
|
|
|
|
|
ram[addr] = val;
|
|
|
|
|
}
|
2012-12-03 08:38:12 +00:00
|
|
|
|
|
|
|
|
|
public override void SyncState(Serializer ser)
|
|
|
|
|
{
|
|
|
|
|
base.SyncState(ser);
|
|
|
|
|
ser.Sync("bankNumber", ref bankNumber);
|
|
|
|
|
ser.Sync("boardLed", ref boardLed);
|
|
|
|
|
ser.Sync("ram", ref ram, false);
|
|
|
|
|
if (ser.IsReader)
|
|
|
|
|
UpdateState();
|
|
|
|
|
}
|
2012-11-29 17:58:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|