107 lines
3.8 KiB
C#
107 lines
3.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
using Essgee.Exceptions;
|
|
|
|
namespace Essgee.Emulation.Cartridges.Nintendo
|
|
{
|
|
public static class SpecializedLoader
|
|
{
|
|
public static IGameBoyCartridge CreateCartridgeInstance(byte[] romData, byte[] ramData, Type mapperType)
|
|
{
|
|
var romSize = -1;
|
|
switch (romData[0x0148])
|
|
{
|
|
case 0x00: romSize = 32 * 1024; break;
|
|
case 0x01: romSize = 64 * 1024; break;
|
|
case 0x02: romSize = 128 * 1024; break;
|
|
case 0x03: romSize = 256 * 1024; break;
|
|
case 0x04: romSize = 512 * 1024; break;
|
|
case 0x05: romSize = 1024 * 1024; break;
|
|
case 0x06: romSize = 2048 * 1024; break;
|
|
case 0x07: romSize = 4096 * 1024; break;
|
|
case 0x08: romSize = 8192 * 1024; break;
|
|
case 0x52: romSize = 1152 * 1024; break;
|
|
case 0x53: romSize = 1280 * 1024; break;
|
|
case 0x54: romSize = 1536 * 1024; break;
|
|
|
|
default: romSize = romData.Length; break;
|
|
}
|
|
|
|
var ramSize = -1;
|
|
switch (romData[0x0149])
|
|
{
|
|
case 0x00: ramSize = 0 * 1024; break;
|
|
case 0x01: ramSize = 2 * 1024; break;
|
|
case 0x02: ramSize = 8 * 1024; break;
|
|
case 0x03: ramSize = 32 * 1024; break;
|
|
case 0x04: ramSize = 128 * 1024; break;
|
|
case 0x05: ramSize = 64 * 1024; break;
|
|
|
|
default: ramSize = 0; break;
|
|
}
|
|
|
|
/* NOTES:
|
|
* MBC2 internal RAM is not given in header, 512*4b == 256 bytes
|
|
* GB Camera internal RAM ~seems~ to not be given in header? 128 kbytes
|
|
*/
|
|
|
|
var mapperTypeFromHeader = typeof(NoMapperCartridge);
|
|
var hasBattery = false;
|
|
var hasRtc = false;
|
|
var hasRumble = false;
|
|
switch (romData[0x0147])
|
|
{
|
|
case 0x00: mapperType = typeof(NoMapperCartridge); break;
|
|
case 0x01: mapperType = typeof(MBC1Cartridge); break;
|
|
case 0x02: mapperType = typeof(MBC1Cartridge); break;
|
|
case 0x03: mapperType = typeof(MBC1Cartridge); hasBattery = true; break;
|
|
case 0x05: mapperType = typeof(MBC2Cartridge); ramSize = 0x100; break;
|
|
case 0x06: mapperType = typeof(MBC2Cartridge); ramSize = 0x100; hasBattery = true; break;
|
|
case 0x08: mapperType = typeof(NoMapperCartridge); break;
|
|
case 0x09: mapperType = typeof(NoMapperCartridge); hasBattery = true; break;
|
|
// 0B-0D, MMM01
|
|
case 0x0F: mapperType = typeof(MBC3Cartridge); hasBattery = true; hasRtc = true; break;
|
|
case 0x10: mapperType = typeof(MBC3Cartridge); hasBattery = true; hasRtc = true; break;
|
|
case 0x11: mapperType = typeof(MBC3Cartridge); break;
|
|
case 0x12: mapperType = typeof(MBC3Cartridge); break;
|
|
case 0x13: mapperType = typeof(MBC3Cartridge); hasBattery = true; break;
|
|
case 0x19: mapperType = typeof(MBC5Cartridge); break;
|
|
case 0x1A: mapperType = typeof(MBC5Cartridge); break;
|
|
case 0x1B: mapperType = typeof(MBC5Cartridge); hasBattery = true; break;
|
|
case 0x1C: mapperType = typeof(MBC5Cartridge); hasRumble = true; break;
|
|
case 0x1D: mapperType = typeof(MBC5Cartridge); hasRumble = true; break;
|
|
case 0x1E: mapperType = typeof(MBC5Cartridge); hasBattery = true; hasRumble = true; break;
|
|
// 20, MBC6
|
|
// 22, MBC7
|
|
case 0xFC: mapperType = typeof(GBCameraCartridge); ramSize = 128 * 1024; break;
|
|
// FD, BANDAI TAMA5
|
|
// FE, HuC3
|
|
// FF, HuC1
|
|
|
|
default: throw new EmulationException($"Unimplemented cartridge type 0x{romData[0x0147]:X2}");
|
|
}
|
|
|
|
if (mapperType == null)
|
|
mapperType = mapperTypeFromHeader;
|
|
|
|
if (romSize != romData.Length)
|
|
{
|
|
var romSizePadded = 1;
|
|
while (romSizePadded < romData.Length) romSizePadded <<= 1;
|
|
romSize = Math.Max(romSizePadded, romData.Length);
|
|
}
|
|
|
|
var cartridge = (IGameBoyCartridge)Activator.CreateInstance(mapperType, new object[] { romSize, ramSize });
|
|
cartridge.LoadRom(romData);
|
|
cartridge.LoadRam(ramData);
|
|
cartridge.SetCartridgeConfig(hasBattery, hasRtc, hasRumble);
|
|
|
|
return cartridge;
|
|
}
|
|
}
|
|
}
|