nes: implement mapper028, a hypothetical multicart. untested

This commit is contained in:
goyuken 2012-11-03 23:56:35 +00:00
parent 50f65452b5
commit a7b2be48e2
2 changed files with 197 additions and 0 deletions

View File

@ -204,6 +204,7 @@
<Compile Include="Consoles\Nintendo\NES\Boards\BANDAI_74_161_161_32.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\BxROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\Camerica.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\Mapper028.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\CNROM.cs" />
<Compile Include="Consoles\Nintendo\NES\Boards\CPROM.cs">
<SubType>Code</SubType>

View File

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BizHawk.Emulation.Consoles.Nintendo
{
// http://wiki.nesdev.com/w/index.php/User:Tepples/Multi-discrete_mapper
public class Mapper028 : NES.NESBoardBase
{
// config
int chr_mask_8k;
int prg_mask_16k;
// state
int reg;
int chr;
int prg;
int mode;
int outer;
// regennable state
int prglo;
int prghi;
public override bool Configure(NES.EDetectionOrigin origin)
{
switch (Cart.board_type)
{
case "MAPPER028":
break;
default:
return false;
}
AssertPrg(32, 64, 128, 256, 512, 1024, 2048);
AssertChr(0);
chr_mask_8k = Cart.chr_size / 8 - 1;
prg_mask_16k = Cart.prg_size / 16 - 1;
Cart.wram_size = 0;
Cart.vram_size = 32;
return true;
}
void Sync()
{
int outb = outer << 1;
// this can probably be rolled up, but i have no motivation to do so
// until it's been tested
switch (mode & 0x3c)
{
// 32K modes
case 0x00:
case 0x04:
prglo = outb;
prghi = outb | 1;
break;
case 0x10:
case 0x14:
prglo = outb & ~2 | prg & 2;
prghi = outb & ~2 | prg & 2 | 1;
break;
case 0x20:
case 0x24:
prglo = outb & ~6 | prg & 6;
prghi = outb & ~6 | prg & 6 | 1;
break;
case 0x30:
case 0x34:
prglo = outb & ~14 | prg & 14;
prghi = outb & ~14 | prg & 14 | 1;
break;
// bottom fixed modes
case 0x08:
prglo = outb;
prghi = outb | prg & 1;
break;
case 0x18:
prglo = outb;
prghi = outb & ~2 | prg & 3;
break;
case 0x28:
prglo = outb;
prghi = outb & ~6 | prg & 7;
break;
case 0x38:
prglo = outb;
prghi = outb & ~14 | prg & 15;
break;
// top fixed modes
case 0x0c:
prglo = outb | prg & 1;
prghi = outb | 1;
break;
case 0x1c:
prglo = outb & ~2 | prg & 3;
prghi = outb | 1;
break;
case 0x2c:
prglo = outb & ~6 | prg & 7;
prghi = outb | 1;
break;
case 0x3c:
prglo = outb & ~14 | prg & 15;
prghi = outb | 1;
break;
}
prglo &= prg_mask_16k;
prghi &= prg_mask_16k;
}
void Mirror(byte value)
{
if ((mode & 2) == 0)
{
mode &= 0xfe;
mode |= value >> 4 & 1;
}
SyncMirror();
}
void SyncMirror()
{
switch (mode & 3)
{
case 0: SetMirrorType(EMirrorType.OneScreenA); break;
case 1: SetMirrorType(EMirrorType.OneScreenB); break;
case 2: SetMirrorType(EMirrorType.Vertical); break;
case 3: SetMirrorType(EMirrorType.Horizontal); break;
}
}
public override void WriteEXP(int addr, byte value)
{
if (addr >= 0x1000)
reg = value & 0x81;
}
public override void WritePRG(int addr, byte value)
{
switch (reg)
{
case 0x00:
chr = value & 3;
Mirror(value);
break;
case 0x01:
prg = value & 15;
Mirror(value);
Sync();
break;
case 0x80:
mode = value & 63;
SyncMirror();
Sync();
break;
case 0x81:
outer = value & 63;
Sync();
break;
}
}
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);
}
public override byte ReadPRG(int addr)
{
return ROM[(addr & 0x3fff) | (addr < 0x4000 ? prglo : prghi) << 14];
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("reg", ref reg);
ser.Sync("chr", ref chr);
ser.Sync("prg", ref prg);
ser.Sync("mode", ref mode);
ser.Sync("outer", ref outer);
if (!ser.IsWriter)
Sync();
}
}
}