165 lines
4.9 KiB
C#
165 lines
4.9 KiB
C#
|
//////////////////////////////////////////////////////////////////////////
|
|||
|
// Mapper168 Subor (PPUExtLatch) //
|
|||
|
//////////////////////////////////////////////////////////////////////////
|
|||
|
using static VirtualNes.MMU;
|
|||
|
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];
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|