diff --git a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
index 7700b36452..ddf0709624 100644
--- a/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
+++ b/BizHawk.Emulation.Cores/BizHawk.Emulation.Cores.csproj
@@ -641,6 +641,7 @@
+
@@ -685,11 +686,11 @@
-
- PPU.cs
+
+ PPU.cs
- PPU.cs
+ PPU.cs
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs
index 3b48926029..6becfb67af 100644
--- a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/GBHawk.cs
@@ -367,6 +367,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
mapper = new MapperMBC1Multi();
}
+ // special case for bootlegs
+ if ((_rom.HashMD5(0, _rom.Length) == "CAE0998A899DF2EE6ABA8E7695C2A096"))
+ {
+ Console.WriteLine("Using RockMan 8 (Unlicensed) Mapper");
+ mapper = new MapperRM8();
+ }
+
Console.Write("Mapper: ");
Console.WriteLine(mppr);
@@ -413,7 +420,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
if (cart_RAM != null)
{
-
Console.Write("RAM: "); Console.WriteLine(cart_RAM.Length);
for (int i = 0; i < cart_RAM.Length; i++)
@@ -422,7 +428,6 @@ namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
}
}
-
// Extra RTC initialization for mbc3
if (mppr == "MBC3")
{
diff --git a/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_RockMan8.cs b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_RockMan8.cs
new file mode 100644
index 0000000000..a45175f84e
--- /dev/null
+++ b/BizHawk.Emulation.Cores/Consoles/Nintendo/GBHawk/Mappers/Mapper_RockMan8.cs
@@ -0,0 +1,69 @@
+using BizHawk.Common;
+using BizHawk.Common.NumberExtensions;
+using System;
+
+namespace BizHawk.Emulation.Cores.Nintendo.GBHawk
+{
+ // RockMan 8, just some simple bankswitching
+ public class MapperRM8 : MapperBase
+ {
+ public int ROM_bank;
+ public int ROM_mask;
+
+ public override void Initialize()
+ {
+ ROM_bank = 1;
+ ROM_mask = Core._rom.Length / 0x4000 - 1;
+
+ // some games have sizes that result in a degenerate ROM, account for it here
+ if (ROM_mask > 4) { ROM_mask |= 3; }
+ }
+
+ public override byte ReadMemory(ushort addr)
+ {
+ if (addr < 0x4000)
+ {
+ // lowest bank is fixed
+ return Core._rom[addr];
+
+ }
+ else if (addr < 0x8000)
+ {
+ return Core._rom[(addr - 0x4000) + ROM_bank * 0x4000];
+ }
+ else
+ {
+ return 0xFF;
+ }
+ }
+
+ public override byte PeekMemory(ushort addr)
+ {
+ return ReadMemory(addr);
+ }
+
+ public override void WriteMemory(ushort addr, byte value)
+ {
+ if ((addr >= 0x2000) && (addr < 0x4000))
+ {
+ value &= 0x1F;
+
+ if (value == 0) { value = 1; }
+
+ // in hhugboy they just subtract 8, but to me looks like bits 4 and 5 are just swapped (and bit 4 is unused?)
+ ROM_bank = ((value & 0xF) | ((value & 0x10) >> 1)) & ROM_mask;
+ }
+ }
+
+ public override void PokeMemory(ushort addr, byte value)
+ {
+ WriteMemory(addr, value);
+ }
+
+ public override void SyncState(Serializer ser)
+ {
+ ser.Sync("ROM_Bank", ref ROM_bank);
+ ser.Sync("ROM_Mask", ref ROM_mask);
+ }
+ }
+}