BizHawk/BizHawk.Emulation/Consoles/Nintendo/NES/Boards/NES-EVENT.cs

192 lines
4.2 KiB
C#

using System;
using System.IO;
using System.Diagnostics;
namespace BizHawk.Emulation.Consoles.Nintendo
{
//AKA mapper 105
public class NES_EVENT : NES.NESBoardBase
{
//configuration
int prg_bank_mask_16k;
//regenerable state
IntBuffer prg_banks_16k = new IntBuffer(2);
//state
MMC1.MMC1_SerialController scnt;
bool slot_mode, prg_mode;
bool irq_control;
int prg_a,prg_b;
int init_sequence;
bool chip_select;
bool wram_disable;
public override void Dispose()
{
base.Dispose();
prg_banks_16k.Dispose();
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
scnt.SyncState(ser);
ser.Sync("slot_mode", ref slot_mode);
ser.Sync("prg_mode", ref prg_mode);
ser.Sync("irq_control", ref irq_control);
ser.Sync("prg_a", ref prg_a);
ser.Sync("prg_b", ref prg_b);
ser.Sync("init_sequence", ref init_sequence);
ser.Sync("chip_select", ref chip_select);
ser.Sync("wram_disable", ref wram_disable);
if (ser.IsReader) Sync();
}
public override bool Configure(NES.EDetectionOrigin origin)
{
switch (Cart.board_type)
{
case "MAPPER105":
break;
case "NES-EVENT":
AssertPrg(256); AssertChr(0); AssertVram(8); AssertWram(8);
break;
default:
return false;
}
prg_bank_mask_16k = Cart.prg_size / 16 - 1;
SetMirrorType(EMirrorType.Vertical);
scnt = new MMC1.MMC1_SerialController();
scnt.WriteRegister = SerialWriteRegister;
scnt.Reset = SerialReset;
Sync();
return true;
}
void SerialReset()
{
prg_mode = true;
slot_mode = true;
}
void Sync()
{
if (init_sequence != 2)
{
//"use first 128k"
prg_banks_16k[0] = 0;
prg_banks_16k[1] = 1;
}
else
{
if (chip_select == false)
{
//"use first 128k"
prg_banks_16k[0] = prg_a*2;
prg_banks_16k[1] = prg_a*2 + 1;
}
else
{
if (prg_mode == false)
{
//"use second 128k"
prg_banks_16k[0] = (prg_b>>1) + 8;
prg_banks_16k[1] = (prg_b>>1) + 8;
}
else
{
//((these arent tested, i think...))
if (slot_mode == false)
{
//"use second 128k"
prg_banks_16k[0] = 8;
prg_banks_16k[1] = prg_b + 8;
}
else
{
//"use second 128k"
prg_banks_16k[0] = prg_b + 8;
prg_banks_16k[1] = 8 + 7;
}
}
}
}
prg_banks_16k[0] &= prg_bank_mask_16k;
prg_banks_16k[1] &= prg_bank_mask_16k;
}
public override void WritePPU(int addr, byte value)
{
base.WritePPU(addr, value);
}
void SerialWriteRegister(int addr, int value)
{
switch (addr)
{
case 0: //8000-9FFF
switch (value & 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;
}
slot_mode = value.Bit(2);
prg_mode = value.Bit(3);
Sync();
break;
case 1: //A000-BFFF
{
bool last_irq_control = irq_control;
irq_control = value.Bit(4);
if (init_sequence == 0)
if (irq_control == false) init_sequence = 1; else { }
else if (init_sequence == 1)
if (irq_control == true) init_sequence = 2;
chip_select = value.Bit(3);
prg_a = (value >> 1) & 3;
Sync();
break;
}
case 2: //C000-DFFF
//unused
break;
case 3: //E000-FFFF
prg_b = value & 0xF;
wram_disable = value.Bit(4);
Sync();
break;
}
//board.NES.LogLine("mapping.. chr_mode={0}, chr={1},{2}", chr_mode, chr_0, chr_1);
//board.NES.LogLine("mapping.. prg_mode={0}, prg_slot{1}, prg={2}", prg_mode, prg_slot, prg);
}
public override void WritePRG(int addr, byte value)
{
scnt.Write(addr, value);
}
public override byte ReadPRG(int addr)
{
int bank_16k = addr >> 14;
int ofs = addr & ((1 << 14) - 1);
bank_16k = prg_banks_16k[bank_16k];
addr = (bank_16k << 14) | ofs;
return ROM[addr];
}
}
}