implement caitsith6502's mapper 30 support patch (with a few minor cleanups). fixes issue 153
This commit is contained in:
parent
c4b6d8656f
commit
5f66376f82
|
@ -284,6 +284,7 @@
|
|||
<Compile Include="Consoles\Nintendo\NES\Boards\JALECO_SS8806.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper015.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper029.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper030.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper036.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper038.cs" />
|
||||
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper040.cs" />
|
||||
|
|
|
@ -0,0 +1,235 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using BizHawk.Common;
|
||||
|
||||
namespace BizHawk.Emulation.Cores.Nintendo.NES
|
||||
{
|
||||
public class Mapper030 : NES.NESBoardBase
|
||||
{
|
||||
|
||||
enum flashmode { fm_default, fm_erase, fm_write, fm_id }
|
||||
|
||||
// config
|
||||
int prg_bank_mask_16k;
|
||||
int vram_bank_mask_8k;
|
||||
|
||||
// state
|
||||
int prg;
|
||||
int chr;
|
||||
int flash_state = 0;
|
||||
flashmode flash_mode = flashmode.fm_default;
|
||||
byte[] flash_rom = null;
|
||||
|
||||
int get_flash_write_count(int addr)
|
||||
{
|
||||
if (flash_rom == null)
|
||||
return 0;
|
||||
int[] value = new int[1];
|
||||
int bank = (addr >= 0x4000) ? prg_bank_mask_16k : prg;
|
||||
Buffer.BlockCopy(flash_rom, (bank << 2 | (addr >> 12) & 3) << 2, value, 0, 4);
|
||||
return value[0];
|
||||
}
|
||||
|
||||
void increment_flash_write_count(int addr, bool direct = false)
|
||||
{
|
||||
if (flash_rom == null)
|
||||
return;
|
||||
int[] value = new int[1];
|
||||
int bank = (addr >= 0x4000) ? prg_bank_mask_16k : prg;
|
||||
if (!direct)
|
||||
{
|
||||
Buffer.BlockCopy(flash_rom, (bank << 2 | (addr >> 12) & 3) << 2, value, 0, 4);
|
||||
value[0]++;
|
||||
Buffer.BlockCopy(value, 0, flash_rom, (bank << 2 | (addr >> 12) & 3) << 2, 4);
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer.BlockCopy(flash_rom, addr << 2, value, 0, 4);
|
||||
value[0]++;
|
||||
Buffer.BlockCopy(value, 0, flash_rom, addr << 2, 4);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SyncState(Serializer ser)
|
||||
{
|
||||
base.SyncState(ser);
|
||||
ser.Sync("prg", ref prg);
|
||||
ser.Sync("chr", ref chr);
|
||||
ser.Sync("flash_state", ref flash_state);
|
||||
int tmp = (int)flash_mode;
|
||||
ser.Sync("flash_mode", ref tmp);
|
||||
flash_mode = (flashmode)tmp;
|
||||
ser.Sync("flash_rom", ref flash_rom, true);
|
||||
}
|
||||
|
||||
public override bool Configure(NES.EDetectionOrigin origin)
|
||||
{
|
||||
switch (Cart.board_type)
|
||||
{
|
||||
case "MAPPER030":
|
||||
Cart.vram_size = 32;
|
||||
break;
|
||||
case "MAPPER0030-00":
|
||||
AssertVram(8, 16, 32);
|
||||
break;
|
||||
case "UNIF_UNROM-512-8":
|
||||
Cart.vram_size = 8;
|
||||
break;
|
||||
case "UNIF_UNROM-512-16":
|
||||
Cart.vram_size = 16;
|
||||
break;
|
||||
case "UNIF_UNROM-512-32":
|
||||
Cart.vram_size = 32;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Cart.wram_battery)
|
||||
{
|
||||
flash_state = 0;
|
||||
flash_mode = flashmode.fm_default;
|
||||
if (flash_rom == null)
|
||||
{
|
||||
// extra space is used to hold information about what sectors have been flashed
|
||||
flash_rom = new byte[Cart.prg_size * 1024 + Cart.prg_size];
|
||||
}
|
||||
}
|
||||
SetMirrorType(CalculateMirrorType(Cart.pad_h, Cart.pad_v));
|
||||
AssertChr(0);
|
||||
AssertPrg(128, 256, 512); //Flash chip sizes that fits sealie unrom-512 are 39SF010, 39SF020, 39SF040.
|
||||
Cart.wram_size = 0;
|
||||
prg_bank_mask_16k = Cart.prg_size / 16 - 1;
|
||||
vram_bank_mask_8k = Cart.vram_size / 8 - 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
static readonly int[] addr_state = new int[5] { 0x1555, 0x2AAA, 0x1555, 0x1555, 0x2AAA };
|
||||
static readonly int[] addr_bank = new int[5] { 1, 0, 1, 1, 0 };
|
||||
static readonly byte[] addr_data = new byte[5] { 0xAA, 0x55, 0x80, 0xAA, 0x55 };
|
||||
|
||||
public override void WritePRG(int addr, byte value)
|
||||
{
|
||||
if ((!Cart.wram_battery) || (addr >= 0x4000))
|
||||
{
|
||||
byte value2 = value;
|
||||
|
||||
if (!Cart.wram_battery)
|
||||
value2 = HandleNormalPRGConflict(addr, value);
|
||||
chr = value2 >> 5 & 3 & vram_bank_mask_8k;
|
||||
prg = value2 & prg_bank_mask_16k;
|
||||
if ((Cart.pad_h == 0) && (Cart.pad_v == 0))
|
||||
{
|
||||
int mirror = (value2 & 0x80) >> 7;
|
||||
SetMirrorType(CalculateMirrorType(mirror, mirror));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (flash_mode == flashmode.fm_default)
|
||||
{
|
||||
if (addr_state[flash_state] == addr && addr_bank[flash_state] == prg && addr_data[flash_state] == value)
|
||||
{
|
||||
flash_state++;
|
||||
if (flash_state == 5)
|
||||
flash_mode = flashmode.fm_erase;
|
||||
}
|
||||
else if (flash_state == 2 && addr == 0x1555 && prg == 1 && value == 0x90)
|
||||
{
|
||||
flash_mode = flashmode.fm_id;
|
||||
}
|
||||
else if (flash_state == 2 && addr == 0x1555 && prg == 1 && value == 0xA0)
|
||||
{
|
||||
flash_state++;
|
||||
flash_mode = flashmode.fm_write;
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_state = 0;
|
||||
flash_mode = flashmode.fm_default;
|
||||
}
|
||||
}
|
||||
else if (flash_mode == flashmode.fm_erase)
|
||||
{
|
||||
if (value == 0x10) //You probably don't want to do this, as this is erase entire flash chip. :)
|
||||
{ //Of course, we gotta emulate the behaviour.
|
||||
for (int i = 0; i < (Cart.prg_size / 4); i++)
|
||||
increment_flash_write_count(i, true);
|
||||
for (int i = 0; i < flash_rom.Count(); i++)
|
||||
flash_rom[Cart.prg_size + i] = 0xFF;
|
||||
}
|
||||
else if (value == 0x30)
|
||||
{
|
||||
increment_flash_write_count(addr);
|
||||
for (int i = 0; i < 0x1000; i++)
|
||||
flash_rom[(prg << 14 | addr & 0x3000) + i + Cart.prg_size] = 0xFF;
|
||||
}
|
||||
flash_mode = 0;
|
||||
flash_state = 0;
|
||||
}
|
||||
else if (flash_mode == flashmode.fm_write)
|
||||
{
|
||||
if (get_flash_write_count(addr) == 0)
|
||||
{
|
||||
increment_flash_write_count(addr);
|
||||
for (int i = 0; i < 0x1000; i++)
|
||||
flash_rom[(prg << 14 | addr & 0x3000) + i + Cart.prg_size] = ROM[(prg << 14 | addr & 0x3000) + i];
|
||||
}
|
||||
flash_rom[Cart.prg_size + (prg << 14 | addr & 0x3fff)] &= value;
|
||||
flash_state = 0;
|
||||
flash_mode = 0;
|
||||
}
|
||||
if (flash_mode == flashmode.fm_id && value == 0xF0)
|
||||
{
|
||||
flash_state = 0;
|
||||
flash_mode = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override byte ReadPRG(int addr)
|
||||
{
|
||||
int bank = addr >= 0x4000 ? prg_bank_mask_16k : prg;
|
||||
if (Cart.wram_battery)
|
||||
{
|
||||
if (flash_mode == flashmode.fm_id)
|
||||
{
|
||||
if ((addr & 1) == 0)
|
||||
return 0xBF;
|
||||
else
|
||||
switch (Cart.prg_size)
|
||||
{
|
||||
case 128:
|
||||
return 0xB5;
|
||||
case 256:
|
||||
return 0xB6;
|
||||
case 512:
|
||||
return 0xB7;
|
||||
}
|
||||
}
|
||||
if (get_flash_write_count(addr) > 0)
|
||||
return flash_rom[Cart.prg_size + (bank << 14 | addr & 0x3fff)];
|
||||
}
|
||||
return ROM[bank << 14 | addr & 0x3fff];
|
||||
}
|
||||
|
||||
public override byte[] SaveRam { get { return flash_rom; } }
|
||||
|
||||
public override byte ReadPPU(int addr)
|
||||
{
|
||||
if (addr < 0x2000)
|
||||
return VRAM[addr | chr << 13];
|
||||
else
|
||||
return base.ReadPPU(addr);
|
||||
}
|
||||
public override void WritePPU(int addr, byte value)
|
||||
{
|
||||
if (addr < 0x2000)
|
||||
VRAM[addr | chr << 13] = value;
|
||||
else
|
||||
base.WritePPU(addr, value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -36,9 +36,11 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
|
|||
CartV2.prg_size *= 16;
|
||||
CartV2.chr_size *= 8;
|
||||
|
||||
CartV2.wram_battery = (data[6] & 2) != 0; // should this be respected in v2 mode??
|
||||
|
||||
int wrambat = iNES2Wram(data[10] >> 4);
|
||||
int wramnon = iNES2Wram(data[10] & 15);
|
||||
CartV2.wram_battery = wrambat > 0;
|
||||
CartV2.wram_battery |= wrambat > 0;
|
||||
// fixme - doesn't handle sizes not divisible by 1024
|
||||
CartV2.wram_size = (short)((wrambat + wramnon) / 1024);
|
||||
|
||||
|
|
Loading…
Reference in New Issue