diff --git a/BizHawk.Emulation/BizHawk.Emulation.csproj b/BizHawk.Emulation/BizHawk.Emulation.csproj
index e528f878c1..899df90f54 100644
--- a/BizHawk.Emulation/BizHawk.Emulation.csproj
+++ b/BizHawk.Emulation/BizHawk.Emulation.csproj
@@ -84,6 +84,7 @@
+
diff --git a/BizHawk.Emulation/Computers/Commodore64/Cartridges/Cartridge.cs b/BizHawk.Emulation/Computers/Commodore64/Cartridges/Cartridge.cs
index 72fdea9256..58993eaf8f 100644
--- a/BizHawk.Emulation/Computers/Commodore64/Cartridges/Cartridge.cs
+++ b/BizHawk.Emulation/Computers/Commodore64/Cartridges/Cartridge.cs
@@ -70,6 +70,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
case 0x0005:
result = new Mapper0005(chipAddress, chipBank, chipData);
break;
+ case 0x0012:
+ result = new Mapper0012(chipAddress, chipBank, chipData);
+ break;
default:
break;
}
diff --git a/BizHawk.Emulation/Computers/Commodore64/Cartridges/Mapper0000.cs b/BizHawk.Emulation/Computers/Commodore64/Cartridges/Mapper0000.cs
index af20981372..febd5d6a79 100644
--- a/BizHawk.Emulation/Computers/Commodore64/Cartridges/Mapper0000.cs
+++ b/BizHawk.Emulation/Computers/Commodore64/Cartridges/Mapper0000.cs
@@ -10,6 +10,8 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
private byte[] romA;
private byte[] romB;
+ // standard cartridge mapper (Commodore)
+
public Mapper0000(byte[] data, bool exrom, bool game)
{
pinGame = game;
@@ -17,17 +19,32 @@ namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
romA = new byte[0x2000];
romB = new byte[0x2000];
+ validCartridge = true;
- Array.Copy(data, 0x0000, romA, 0x0000, 0x2000);
+ // we can expect three different configurations:
+ // bank of 4k, bank of 8k, or two banks of 8k
- if (data.Length == 0x2000)
+ if (data.Length == 0x1000)
{
+ 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
{
- Array.Copy(data, 0x2000, romB, 0x0000, 0x2000);
+ validCartridge = false;
}
HardReset();
diff --git a/BizHawk.Emulation/Computers/Commodore64/Cartridges/Mapper0012.cs b/BizHawk.Emulation/Computers/Commodore64/Cartridges/Mapper0012.cs
new file mode 100644
index 0000000000..d1f8d58241
--- /dev/null
+++ b/BizHawk.Emulation/Computers/Commodore64/Cartridges/Mapper0012.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace BizHawk.Emulation.Computers.Commodore64.Cartridges
+{
+ public class Mapper0012 : Cartridge
+ {
+ private byte[] bankMain;
+ private byte[][] bankHigh;
+ private byte[] bankHighSelected;
+ private byte[] dummyBank;
+
+ // Zaxxon and Super Zaxxon cartridges
+ // - read to 8xxx selects bank 0 in A000-BFFF
+ // - read to 9xxx selects bank 1 in A000-BFFF
+
+ public Mapper0012(List newAddresses, List newBanks, List newData)
+ {
+ bankMain = new byte[0x2000];
+ bankHigh = new byte[2][];
+ dummyBank = new byte[0x2000];
+
+ // create dummy bank just in case
+ for (uint i = 0; i < 0x2000; i++)
+ dummyBank[i] = 0xFF;
+
+ bankHigh[0] = dummyBank;
+ bankHigh[1] = dummyBank;
+
+ // load in the banks
+ for (int i = 0; i < newAddresses.Count; i++)
+ {
+ if (newAddresses[i] == 0x8000)
+ Array.Copy(newData[i], bankMain, 0x1000);
+ else if (newAddresses[i] == 0xA000 && newBanks[i] < 2)
+ bankHigh[newBanks[i]] = newData[i];
+ }
+
+ // mirror the main rom from 8000 to 9000
+ Array.Copy(bankMain, 0x0000, bankMain, 0x1000, 0x1000);
+
+ // set both pins low for 16k rom config
+ pinExRom = false;
+ pinGame = false;
+
+ }
+
+ public override byte Peek8000(int addr)
+ {
+ return bankMain[addr];
+ }
+
+ public override byte PeekA000(int addr)
+ {
+ return bankHighSelected[addr];
+ }
+
+ public override byte Read8000(ushort addr)
+ {
+ uint bank = (addr & (uint)0x1000) >> 12;
+ bankHighSelected = bankHigh[bank];
+ return bankMain[addr];
+ }
+
+ public override byte ReadA000(ushort addr)
+ {
+ return bankHighSelected[addr];
+ }
+ }
+}
diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6569.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6569.cs
index 445aad39b1..ba5d1f2280 100644
--- a/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6569.cs
+++ b/BizHawk.Emulation/Computers/Commodore64/MOS/MOS6569.cs
@@ -168,20 +168,20 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
},
new uint[] // BA
{
- 0x0834, 0x0834,
- 0x0345, 0x0345,
- 0x0845, 0x0845,
- 0x0456, 0x0456,
- 0x0856, 0x0856,
+ 0x0843, 0x0843,
+ 0x0543, 0x0543,
+ 0x0548, 0x0548,
+ 0x0546, 0x0546,
+ 0x0586, 0x0586,
- 0x0567, 0x0567,
- 0x0867, 0x0867,
- 0x0887, 0x0887,
- 0x0887, 0x0887,
- 0x0000, 0x0000,
+ 0x0576, 0x0576,
+ 0x0876, 0x0876,
+ 0x0876, 0x0876,
+ 0x0878, 0x0878,
+ 0x0878, 0x0878,
0x0000, 0x0000,
- 0x1000, 0x1000,
+ 0x1000, 0x1000, // 12: badline
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
@@ -232,17 +232,17 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
0x1000, 0x1000,
0x1000, 0x1000,
0x1000, 0x1000,
- 0x1000, 0x1000,
+ 0x0880, 0x0880, // 55: sprites
0x0880, 0x0880,
- 0x0880, 0x0880,
- 0x0801, 0x0801,
- 0x0012, 0x0012,
- 0x0812, 0x0812,
+ 0x0810, 0x0810,
+ 0x0810, 0x0810,
+ 0x0210, 0x0210,
+ 0x0218, 0x0218,
- 0x0123, 0x0123,
- 0x0823, 0x0823,
- 0x0234, 0x0234
+ 0x0213, 0x0213,
+ 0x0283, 0x0283,
+ 0x0243, 0x0243
},
new uint[] // actions
{
diff --git a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs
index bf67710557..c97b156213 100644
--- a/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs
+++ b/BizHawk.Emulation/Computers/Commodore64/MOS/Vic.cs
@@ -171,7 +171,7 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
backgroundColor1 = 0;
backgroundColor2 = 0;
backgroundColor3 = 0;
- baCount = 4;
+ baCount = baResetCounter;
badline = false;
badlineEnable = false;
bitmapMode = false;
@@ -243,9 +243,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private void UpdateBA()
{
if (pinBA)
- baCount = 4;
+ baCount = baResetCounter;
else if (baCount > 0)
baCount--;
+ pinAEC = (baCount > 0);
}
private void UpdateBorder()
@@ -279,12 +280,17 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
protected const uint pipelineChkSprDisp = 512;
protected const uint pipelineUpdateRc = 1024;
+ protected const uint rasterIrqLine0Cycle = 1;
+ protected const uint rasterIrqLineXCycle = 0;
+
+ protected const uint baResetCounter = 4;
+
// ------------------------------------
public void ExecutePhase1()
{
// raster IRQ compare
- if ((cycle == 0 && rasterLine > 0) || (cycle == 1 && rasterLine == 0))
+ if ((cycle == rasterIrqLineXCycle && rasterLine > 0) || (cycle == rasterIrqLine0Cycle && rasterLine == 0))
{
if (rasterLine != lastRasterLine)
if (rasterLine == rasterInterruptLine)
@@ -327,6 +333,9 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
xOffset = 0;
Render();
+ // if the BA counter is nonzero, allow CPU bus access
+ UpdateBA();
+
// must always come last
UpdatePins();
}
@@ -355,10 +364,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
}
}
- // if the BA counter is nonzero, allow CPU bus access
- UpdateBA();
- pinAEC = (baCount > 0);
-
Render();
// must always come last
@@ -367,7 +372,6 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
private void ParseCycle()
{
- bool baPinThisCycle = true;
ushort addr = 0x3FFF;
uint cycleBAsprite0;
uint cycleBAsprite1;
@@ -477,10 +481,10 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
switch (ba)
{
case 0x0000:
- baPinThisCycle = true;
+ pinBA = true;
break;
case 0x1000:
- baPinThisCycle = !badline;
+ pinBA = !badline;
break;
default:
cycleBAsprite0 = ba & 0x000F;
@@ -489,10 +493,11 @@ namespace BizHawk.Emulation.Computers.Commodore64.MOS
if ((cycleBAsprite0 < 8 && sprites[cycleBAsprite0].dma) ||
(cycleBAsprite1 < 8 && sprites[cycleBAsprite1].dma) ||
(cycleBAsprite2 < 8 && sprites[cycleBAsprite2].dma))
- baPinThisCycle = false;
+ pinBA = false;
+ else
+ pinBA = true;
break;
}
- pinBA = baPinThisCycle;
// perform actions
borderCheckLEnable = true;