150 lines
3.8 KiB
C#
150 lines
3.8 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Diagnostics;
|
|
|
|
namespace BizHawk.Emulation.Consoles.Nintendo
|
|
{
|
|
//AKA mapper 068 (and TENGEN-800042)
|
|
|
|
//After Burner & After Burner 2
|
|
//Maharaja
|
|
|
|
class Sunsoft4 : NES.NESBoardBase
|
|
{
|
|
//configuration
|
|
int prg_bank_mask, chr_bank_mask, nt_bank_mask;
|
|
|
|
//state
|
|
ByteBuffer chr_regs_2k = new ByteBuffer(4);
|
|
ByteBuffer nt_regs = new ByteBuffer(2);
|
|
ByteBuffer prg_regs_16k = new ByteBuffer(2);
|
|
bool flag_m, flag_r;
|
|
|
|
public override void Dispose()
|
|
{
|
|
base.Dispose();
|
|
chr_regs_2k.Dispose();
|
|
nt_regs.Dispose();
|
|
prg_regs_16k.Dispose();
|
|
}
|
|
|
|
public override void SyncState(Serializer ser)
|
|
{
|
|
base.SyncState(ser);
|
|
ser.Sync("chr_regs_2k", ref chr_regs_2k);
|
|
ser.Sync("nt_regs", ref nt_regs);
|
|
ser.Sync("prg_regs_16k", ref prg_regs_16k);
|
|
ser.Sync("flag_m", ref flag_m);
|
|
ser.Sync("flag_r", ref flag_r);
|
|
}
|
|
|
|
public override bool Configure(NES.EDetectionOrigin origin)
|
|
{
|
|
//configure
|
|
switch (Cart.board_type)
|
|
{
|
|
case "MAPPER068":
|
|
break;
|
|
case "TENGEN-800042":
|
|
AssertPrg(128); AssertChr(256); AssertVram(0); AssertWram(0);
|
|
break;
|
|
case "SUNSOFT-4":
|
|
AssertPrg(128); AssertChr(128,256); AssertVram(0); AssertWram(0,8);
|
|
break;
|
|
case "UNIF_NES-NTBROM":
|
|
AssertPrg(128 + 16); AssertChr(128); Cart.wram_size = 8; Cart.vram_size = 0;
|
|
/* The actual cart had 128k prg, with a small slot on the top that can load an optional daughterboard.
|
|
* The UNIF dump has this as an extra 16k prg lump. I don't know how this lump is actually used,
|
|
* though.
|
|
*/
|
|
break;
|
|
default:
|
|
return false;
|
|
}
|
|
|
|
SetMirrorType(EMirrorType.Vertical);
|
|
prg_regs_16k[1] = 0xFF;
|
|
prg_bank_mask = Cart.prg_size / 16 - 1;
|
|
if (Cart.prg_size == 128 + 16)
|
|
prg_bank_mask = 7; // ignore extra prg lump
|
|
chr_bank_mask = Cart.chr_size / 2 - 1;
|
|
nt_bank_mask = Cart.chr_size - 1;
|
|
return true;
|
|
}
|
|
|
|
public override byte ReadPRG(int addr)
|
|
{
|
|
int bank_16k = addr >> 14;
|
|
int ofs = addr & ((1 << 14) - 1);
|
|
bank_16k = prg_regs_16k[bank_16k];
|
|
bank_16k &= prg_bank_mask;
|
|
addr = (bank_16k << 14) | ofs;
|
|
return ROM[addr];
|
|
}
|
|
|
|
public override byte ReadPPU(int addr)
|
|
{
|
|
if (addr < 0x2000)
|
|
{
|
|
//chr comes from normal chr mapping
|
|
int bank_2k = addr >> 11;
|
|
int ofs = addr & ((1 << 11) - 1);
|
|
bank_2k = chr_regs_2k[bank_2k];
|
|
bank_2k &= chr_bank_mask;
|
|
addr = (bank_2k << 11) | ofs;
|
|
return VROM[addr];
|
|
}
|
|
else
|
|
{
|
|
//nametable may come from "NT-ROM"
|
|
//which means from extra CHR data starting at bank 0x80
|
|
if (flag_r)
|
|
{
|
|
addr = ApplyMirroring(addr);
|
|
int bank_1k = (addr >> 10) & 3;
|
|
int ofs = addr & ((1 << 10) - 1);
|
|
bank_1k = nt_regs[bank_1k] + 0x80;
|
|
bank_1k &= nt_bank_mask;
|
|
addr = (bank_1k << 10) | ofs;
|
|
return VROM[addr];
|
|
}
|
|
else return base.ReadPPU(addr);
|
|
}
|
|
}
|
|
|
|
public override void WritePRG(int addr, byte value)
|
|
{
|
|
//Console.WriteLine("W{0:x4} {1:x2}", addr + 0x8000, value);
|
|
switch (addr & 0xF000)
|
|
{
|
|
case 0x0000: //$8000
|
|
chr_regs_2k[0] = value;
|
|
break;
|
|
case 0x1000: //$9000
|
|
chr_regs_2k[1] = value;
|
|
break;
|
|
case 0x2000: //$A000
|
|
chr_regs_2k[2] = value;
|
|
break;
|
|
case 0x3000: //$B000
|
|
chr_regs_2k[3] = value;
|
|
break;
|
|
case 0x4000: //$C000
|
|
nt_regs[0] = (byte)(value & 0x7F);
|
|
break;
|
|
case 0x5000: //$D000
|
|
nt_regs[1] = (byte)(value & 0x7F);
|
|
break;
|
|
case 0x6000: //$E000
|
|
flag_m = (value & 1) != 0;
|
|
flag_r = ((value >> 4) & 1) != 0;
|
|
if (flag_m) SetMirrorType(EMirrorType.Horizontal);
|
|
else SetMirrorType(EMirrorType.Vertical);
|
|
break;
|
|
case 0x7000: //$F000
|
|
prg_regs_16k[0] = value;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} |