commodore64: fixed Ultimax E000 mapping, updated mapper 0000, added EzFlash mapper 0020 (no official games use this but a lot of disk-to-cart and homebrew do)
This commit is contained in:
parent
1eca7805cf
commit
e4c760be83
|
@ -85,6 +85,7 @@
|
|||
<Compile Include="Computers\Commodore64\C64.Input.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cartridges\Mapper0005.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cartridges\Mapper0012.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cartridges\Mapper0020.cs" />
|
||||
<Compile Include="Computers\Commodore64\Media\PRG.cs" />
|
||||
<Compile Include="Computers\Commodore64\Memory.cs" />
|
||||
<Compile Include="Computers\Commodore64\Cartridges\Cartridge.cs" />
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
|
|||
switch (mapper)
|
||||
{
|
||||
case 0x0000:
|
||||
result = new Mapper0000(chipData[0], exrom, game);
|
||||
result = new Mapper0000(chipAddress, chipBank, chipData, game, exrom);
|
||||
break;
|
||||
case 0x0005:
|
||||
result = new Mapper0005(chipAddress, chipBank, chipData);
|
||||
|
@ -73,6 +73,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
|
|||
case 0x0012:
|
||||
result = new Mapper0012(chipAddress, chipBank, chipData);
|
||||
break;
|
||||
case 0x0020:
|
||||
result = new Mapper0020(chipAddress, chipBank, chipData);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -11,8 +11,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
|
|||
private byte[] romB;
|
||||
|
||||
// standard cartridge mapper (Commodore)
|
||||
// note that this format also covers Ultimax carts
|
||||
|
||||
public Mapper0000(byte[] data, bool exrom, bool game)
|
||||
public Mapper0000(List<uint> newAddresses, List<uint> newBanks, List<byte[]> newData, bool game, bool exrom)
|
||||
{
|
||||
pinGame = game;
|
||||
pinExRom = exrom;
|
||||
|
@ -21,30 +22,37 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
|
|||
romB = new byte[0x2000];
|
||||
validCartridge = true;
|
||||
|
||||
// we can expect three different configurations:
|
||||
// bank of 4k, bank of 8k, or two banks of 8k
|
||||
|
||||
if (data.Length == 0x1000)
|
||||
for (int i = 0; i < newAddresses.Count; i++)
|
||||
{
|
||||
Array.Copy(data, 0x0000, romA, 0x0000, 0x1000);
|
||||
Array.Copy(data, 0x0000, romA, 0x1000, 0x1000);
|
||||
for (int i = 0; i < 0x2000; i++)
|
||||
romB[i] = 0xFF;
|
||||
}
|
||||
else if (data.Length == 0x2000)
|
||||
{
|
||||
Array.Copy(data, 0x0000, romA, 0x0000, 0x2000);
|
||||
for (int i = 0; i < 0x2000; i++)
|
||||
romB[i] = 0xFF;
|
||||
}
|
||||
else if (data.Length == 0x4000)
|
||||
{
|
||||
Array.Copy(data, 0x0000, romA, 0x0000, 0x2000);
|
||||
Array.Copy(data, 0x2000, romB, 0x0000, 0x2000);
|
||||
}
|
||||
else
|
||||
{
|
||||
validCartridge = false;
|
||||
if (newAddresses[i] == 0x8000)
|
||||
{
|
||||
if (newData[i].Length < 0x2000)
|
||||
{
|
||||
Array.Copy(newData[i], 0x0000, romA, 0x0000, 0x1000);
|
||||
Array.Copy(newData[i], 0x0000, romA, 0x1000, 0x1000);
|
||||
}
|
||||
else if (newData[i].Length < 0x4000)
|
||||
{
|
||||
romA = newData[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
Array.Copy(newData[i], 0x0000, romA, 0x0000, 0x2000);
|
||||
Array.Copy(newData[i], 0x2000, romB, 0x0000, 0x2000);
|
||||
}
|
||||
}
|
||||
else if (newAddresses[i] == 0xA000 || newAddresses[i] == 0xE000)
|
||||
{
|
||||
if (newData[i].Length < 0x2000)
|
||||
{
|
||||
Array.Copy(newData[i], 0x0000, romB, 0x0000, 0x1000);
|
||||
Array.Copy(newData[i], 0x0000, romB, 0x1000, 0x1000);
|
||||
}
|
||||
else
|
||||
{
|
||||
romB = newData[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HardReset();
|
||||
|
|
|
@ -70,11 +70,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
|
|||
{
|
||||
if (newAddresses[i] == 0x8000)
|
||||
{
|
||||
banksA[newBanks[i]] = newData[i];
|
||||
banksA[newBanks[i] & bankMask] = newData[i];
|
||||
}
|
||||
else if (newAddresses[i] == 0xA000)
|
||||
else if (newAddresses[i] == 0xA000 || newAddresses[i] == 0xE000)
|
||||
{
|
||||
banksB[newBanks[i]] = newData[i];
|
||||
banksB[newBanks[i] & bankMask] = newData[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
|
|||
{
|
||||
if (newAddresses[i] == 0x8000)
|
||||
Array.Copy(newData[i], bankMain, 0x1000);
|
||||
else if (newAddresses[i] == 0xA000 && newBanks[i] < 2)
|
||||
else if ((newAddresses[i] == 0xA000 || newAddresses[i] == 0xE000) && newBanks[i] < 2)
|
||||
bankHigh[newBanks[i]] = newData[i];
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
|
||||
{
|
||||
// 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.
|
||||
|
||||
public class Mapper0020 : Cartridge
|
||||
{
|
||||
private byte[][] banksA = new byte[64][]; //8000
|
||||
private byte[][] banksB = new byte[64][]; //A000
|
||||
private uint bankNumber;
|
||||
private bool boardLed;
|
||||
private byte[] currentBankA;
|
||||
private byte[] currentBankB;
|
||||
private byte[] dummyBank;
|
||||
private byte[] ram = new byte[256];
|
||||
|
||||
public Mapper0020(List<uint> newAddresses, List<uint> newBanks, List<byte[]> newData)
|
||||
{
|
||||
uint count = (uint)newAddresses.Count;
|
||||
|
||||
// build dummy bank
|
||||
dummyBank = new byte[0x2000];
|
||||
for (uint i = 0; i < 0x2000; i++)
|
||||
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
|
||||
for (uint i = 0; i < 64; i++)
|
||||
banksA[i] = dummyBank;
|
||||
for (uint i = 0; i < 64; i++)
|
||||
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);
|
||||
}
|
||||
|
||||
private void BankSet(uint index)
|
||||
{
|
||||
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
|
||||
if (addr == 0x00)
|
||||
return (byte)bankNumber;
|
||||
else if (addr == 0x02)
|
||||
return (byte)(
|
||||
(pinGame ? 0x00 : 0x01) |
|
||||
(pinExRom ? 0x00 : 0x02) |
|
||||
0x04 |
|
||||
0x08 |
|
||||
0x10 |
|
||||
0x20 |
|
||||
0x40 |
|
||||
(boardLed ? 0x80 : 0x00)
|
||||
);
|
||||
else
|
||||
return (byte)0xFF;
|
||||
}
|
||||
|
||||
public override byte PeekDF00(int addr)
|
||||
{
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
public override void PokeDE00(int addr, byte val)
|
||||
{
|
||||
if (addr == 0x00)
|
||||
BankSet(val);
|
||||
else if (addr == 0x02)
|
||||
StateSet(val);
|
||||
}
|
||||
|
||||
public override void PokeDF00(int addr, byte val)
|
||||
{
|
||||
ram[addr] = val;
|
||||
}
|
||||
|
||||
public override byte Read8000(ushort addr)
|
||||
{
|
||||
return currentBankA[addr];
|
||||
}
|
||||
|
||||
public override byte ReadA000(ushort addr)
|
||||
{
|
||||
return currentBankB[addr];
|
||||
}
|
||||
|
||||
public override byte ReadDF00(ushort addr)
|
||||
{
|
||||
return ram[addr];
|
||||
}
|
||||
|
||||
private void StateSet(byte val)
|
||||
{
|
||||
pinGame = ((val & 0x01) == 0);
|
||||
pinExRom = ((val & 0x02) == 0);
|
||||
boardLed = ((val & 0x80) != 0) ? !boardLed : boardLed;
|
||||
UpdateState();
|
||||
}
|
||||
|
||||
private void UpdateState()
|
||||
{
|
||||
currentBankA = banksA[bankNumber];
|
||||
currentBankB = banksB[bankNumber];
|
||||
}
|
||||
|
||||
public override void WriteDE00(ushort addr, byte val)
|
||||
{
|
||||
if (addr == 0x00)
|
||||
BankSet(val);
|
||||
else if (addr == 0x02)
|
||||
StateSet(val);
|
||||
}
|
||||
|
||||
public override void WriteDF00(ushort addr, byte val)
|
||||
{
|
||||
ram[addr] = val;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -115,9 +115,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
|
||||
private void UpdateMap()
|
||||
{
|
||||
if (ultimax)
|
||||
return;
|
||||
|
||||
ultimax = false;
|
||||
if (pinCharen && pinHiRam && pinLoRam && pinGame && pinExRom)
|
||||
{
|
||||
// 11111
|
||||
|
@ -291,7 +289,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
|
|||
else if (!pinGame && pinExRom)
|
||||
{
|
||||
// XXX01 (ultimax)
|
||||
// once in this mode, it is not supposed to change
|
||||
map.layout1000 = PLABank.None;
|
||||
map.layout8000 = PLABank.CartridgeLo;
|
||||
map.layoutA000 = PLABank.None;
|
||||
|
|
Loading…
Reference in New Issue