AxibugEmuOnline/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper168.cs

167 lines
5.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//////////////////////////////////////////////////////////////////////////
// Mapper168 Subor (PPUExtLatch) //
//////////////////////////////////////////////////////////////////////////
using VirtualNes.Core.Debug;
using static VirtualNes.MMU;
using BYTE = System.Byte;
using INT = System.Int32;
namespace VirtualNes.Core
{
public class Mapper168 : Mapper
{
byte reg5000, reg5200, reg5300;
byte PPU_SW, NT_data;
byte Rom_Type;
public Mapper168(NES parent) : base(parent) { }
public override bool IsStateSave()
{
return true;
}
public override void Reset()
{
reg5000 = 0;
reg5200 = 0;
reg5300 = 0;
PPU_SW = 0;
NT_data = 0;
nes.ppu.SetExtLatchMode(true);
SetPROM_16K_Bank(4, 0);
SetPROM_16K_Bank(6, 0);
Rom_Type = 0;
uint crc = nes.rom.GetPROM_CRC();
if (crc == 0x0A9808AE) //[Subor] Karaoke (C)
{
Rom_Type = 1;
SetPROM_32K_Bank(0);
nes.SetVideoMode(2 != 0);
}
if (crc == 0x12D61CE8) //[Subor] Subor V11.0 (C)
{
Rom_Type = 2;
}
}
public override byte ReadLow(ushort addr)
{
if (addr == 0x5300) return 0x8F; //返回0x8F跳过真人语音发声有关的程序段
return base.ReadLow(addr);
}
public override void WriteLow(ushort addr, byte data)
{
if (addr == 0x5000)
{
reg5000 = data;
SetBank_CPU();
}
else if (addr == 0x5200)
{
reg5200 = (byte)(data & 0x7);
SetBank_CPU();
}
else if (addr == 0x5300)
{
reg5300 = data;
}
else if (addr >= 0x6000)
{
CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] = data;
}
}
public override void Write(ushort addr, byte data)
{
if (Rom_Type == 1)
{ //[Subor] Karaoke (C)
SetPROM_32K_Bank(data & 0x1F);
if ((data & 0x40) != 0) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
if ((data & 0xC0) != 0) PPU_SW = 1;
else PPU_SW = 0;
}
}
void SetBank_CPU()
{
if (reg5200 < 4) SetPROM_16K_Bank(4, reg5000);
else SetPROM_32K_Bank(reg5000);
switch (reg5200)
{
case 0:
SetVRAM_Mirror(VRAM_VMIRROR);
PPU_SW = 0;
break;
case 2:
SetVRAM_Mirror(VRAM_VMIRROR);
PPU_SW = 1;
break;
case 1:
case 3:
SetVRAM_Mirror(VRAM_HMIRROR);
PPU_SW = 0;
break;
case 5:
if (reg5000 == 4 && Rom_Type == 2)
{ //Special for [Subor] Subor V11.0 (C) - Tank (坦克大战)
nes.ppu.SetExtLatchMode(false);
SetVRAM_Mirror(VRAM_HMIRROR);
}
break;
}
}
public override void PPU_Latch(ushort addr)
{
if ((addr & 0xF000) == 0x2000)
{
NT_data = (byte)((addr >> 8) & 0x03);
}
}
public override void PPU_ExtLatch(ushort ntbladr, ref byte chr_l, ref byte chr_h, ref byte attr)
{
INT loopy_v = nes.ppu.GetPPUADDR();
INT loopy_y = nes.ppu.GetTILEY();
INT tileofs = (PPUREG[0] & PPU.PPU_BGTBL_BIT) << 8;
INT attradr = 0x23C0 + (loopy_v & 0x0C00) + ((loopy_v & 0x0380) >> 4);
INT attrsft = (ntbladr & 0x0040) >> 4;
ArrayRef<byte> pNTBL = PPU_MEM_BANK[ntbladr >> 10];
INT ntbl_x = ntbladr & 0x001F;
INT tileadr, ntb;
ntb = (ntbladr >> 10) & 3;
if (ntb == 2)
tileofs |= 0x1000;
else if (ntb != 0 && PPU_SW != 0)
tileofs |= 0x1000;
else
tileofs |= 0x0000;
attradr &= 0x3FF;
attr = (byte)(((pNTBL[attradr + (ntbl_x >> 2)] >> ((ntbl_x & 2) + attrsft)) & 3) << 2);
tileadr = tileofs + pNTBL[ntbladr & 0x03FF] * 0x10 + loopy_y;
chr_l = PPU_MEM_BANK[tileadr >> 10][tileadr & 0x03FF];
chr_h = PPU_MEM_BANK[tileadr >> 10][(tileadr & 0x03FF) + 8];
}
public override void SaveState(byte[] p)
{
p[0] = reg5000;
p[1] = reg5200;
}
public override void LoadState(byte[] p)
{
reg5000 = p[0];
reg5200 = p[1];
}
}
}