AxibugEmuOnline/AxibugEmuOnline.Client/Assets/MyNes.Core/Mapper105.cs
2024-07-03 18:22:22 +08:00

201 lines
4.7 KiB
C#

using System.IO;
namespace MyNes.Core
{
[BoardInfo("NES-EVENT", 105)]
[HassIssues]
internal class Mapper105 : Board
{
private int DipSwitchNumber;
private byte[] reg = new byte[4];
private byte shift;
private byte buffer;
private bool flag_p;
private bool flag_s;
private bool flag_o;
private int reg_a;
private int reg_b;
private bool irq_control;
private bool initialized;
private int irq_counter;
private int dipswitches;
internal override string Issues => MNInterfaceLanguage.IssueMapper105;
internal override void HardReset()
{
base.HardReset();
TogglePRGRAMEnable(enable: true);
reg = new byte[4];
reg[0] = 12;
flag_s = (flag_p = true);
reg[1] = (reg[2] = (reg[3] = 0));
buffer = 0;
shift = 0;
initialized = false;
DipSwitchNumber = 0;
dipswitches = 0x20000000 | (DipSwitchNumber << 22);
}
internal override void SoftReset()
{
DipSwitchNumber = (DipSwitchNumber + 1) & 0xF;
dipswitches = 0x20000000 | (DipSwitchNumber << 22);
}
internal override void WritePRG(ref ushort address, ref byte value)
{
if ((value & 0x80) == 128)
{
reg[0] |= 12;
flag_s = (flag_p = true);
shift = (buffer = 0);
return;
}
if ((value & 1) == 1)
{
buffer |= (byte)(1 << (int)shift);
}
if (++shift < 5)
{
return;
}
address = (ushort)((address & 0x7FFF) >> 13);
reg[address] = buffer;
shift = (buffer = 0);
switch (address)
{
case 0:
flag_p = (reg[0] & 8) != 0;
flag_s = (reg[0] & 4) != 0;
UpdatePRG();
switch (reg[0] & 3)
{
case 0:
Switch01KNMTFromMirroring(Mirroring.OneScA);
break;
case 1:
Switch01KNMTFromMirroring(Mirroring.OneScB);
break;
case 2:
Switch01KNMTFromMirroring(Mirroring.Vert);
break;
case 3:
Switch01KNMTFromMirroring(Mirroring.Horz);
break;
}
break;
case 1:
irq_control = (reg[1] & 0x10) == 16;
if (irq_control)
{
initialized = true;
irq_counter = 0;
NesEmu.IRQFlags &= -9;
}
else
{
Switch32KPRG(0, PRGArea.Area8000);
}
flag_o = (reg[1] & 8) == 8;
reg_a = (reg[1] >> 1) & 3;
UpdatePRG();
break;
case 3:
TogglePRGRAMEnable((reg[3] & 0x10) == 0);
reg_b = reg[3] & 0xF;
UpdatePRG();
break;
case 2:
break;
}
}
private void UpdatePRG()
{
if (initialized)
{
if (!flag_o)
{
Switch32KPRG(reg_a, PRGArea.Area8000);
}
else if (!flag_p)
{
Switch32KPRG((reg_b >> 1) + 4, PRGArea.Area8000);
}
else if (!flag_s)
{
Switch16KPRG(8, PRGArea.Area8000);
Switch16KPRG(reg_b + 8, PRGArea.AreaC000);
}
else
{
Switch16KPRG(reg_b + 8, PRGArea.Area8000);
Switch16KPRG(15, PRGArea.AreaC000);
}
}
}
internal override void OnCPUClock()
{
if (!irq_control)
{
irq_counter++;
if (irq_counter == dipswitches)
{
irq_counter = 0;
NesEmu.IRQFlags |= 8;
}
}
}
internal override void WriteStateData(ref BinaryWriter stream)
{
base.WriteStateData(ref stream);
stream.Write(DipSwitchNumber);
stream.Write(reg);
stream.Write(shift);
stream.Write(buffer);
stream.Write(flag_p);
stream.Write(flag_s);
stream.Write(flag_o);
stream.Write(reg_a);
stream.Write(reg_b);
stream.Write(irq_control);
stream.Write(initialized);
stream.Write(irq_counter);
stream.Write(dipswitches);
}
internal override void ReadStateData(ref BinaryReader stream)
{
base.ReadStateData(ref stream);
DipSwitchNumber = stream.ReadInt32();
stream.Read(reg, 0, reg.Length);
shift = stream.ReadByte();
buffer = stream.ReadByte();
flag_p = stream.ReadBoolean();
flag_s = stream.ReadBoolean();
flag_o = stream.ReadBoolean();
reg_a = stream.ReadInt32();
reg_b = stream.ReadInt32();
irq_control = stream.ReadBoolean();
initialized = stream.ReadBoolean();
irq_counter = stream.ReadInt32();
dipswitches = stream.ReadInt32();
}
}
}