补充Mapper from VirtuaNESex
This commit is contained in:
parent
2510b2b7e3
commit
a66835c091
@ -1,4 +1,5 @@
|
|||||||
using VirtualNes.Core;
|
using Codice.CM.Client.Differences;
|
||||||
|
using VirtualNes.Core;
|
||||||
|
|
||||||
namespace VirtualNes
|
namespace VirtualNes
|
||||||
{
|
{
|
||||||
@ -84,6 +85,20 @@ namespace VirtualNes
|
|||||||
CPU_MEM_PAGE[page] = 0;
|
CPU_MEM_PAGE[page] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal static void SetPROM_4K_Bank(ushort addr, int bank)
|
||||||
|
{
|
||||||
|
throw new System.NotImplementedException();
|
||||||
|
|
||||||
|
bank %= (PROM_8K_SIZE * 2);
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
//memcpy(&CPU_MEM_BANK[addr >> 13][addr & 0x1FFF], PROM + 0x1000 * bank, 0x1000);
|
||||||
|
//// memcpy( &CPU_MEM_BANK[addr>>13][addr&0x1FFF], YSRAM+0x1000*bank, 0x1000);
|
||||||
|
CPU_MEM_TYPE[addr >> 13] = BANKTYPE_ROM;
|
||||||
|
CPU_MEM_PAGE[addr >> 13] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal static void SetPROM_8K_Bank(byte page, int bank)
|
internal static void SetPROM_8K_Bank(byte page, int bank)
|
||||||
{
|
{
|
||||||
bank %= PROM_8K_SIZE;
|
bank %= PROM_8K_SIZE;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
namespace VirtualNes.Core
|
using System;
|
||||||
|
|
||||||
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
public class Mapper004 : Mapper
|
public class Mapper004 : Mapper
|
||||||
{
|
{
|
||||||
@ -569,5 +571,49 @@
|
|||||||
MMU.SetPROM_32K_Bank(prg0, prg1, MMU.PROM_8K_SIZE - 2, MMU.PROM_8K_SIZE - 1);
|
MMU.SetPROM_32K_Bank(prg0, prg1, MMU.PROM_8K_SIZE - 2, MMU.PROM_8K_SIZE - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void SaveState(byte[] p)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
p[i] = reg[i];
|
||||||
|
}
|
||||||
|
p[8] = prg0;
|
||||||
|
p[9] = prg1;
|
||||||
|
p[10] = chr01;
|
||||||
|
p[11] = chr23;
|
||||||
|
p[12] = chr4;
|
||||||
|
p[13] = chr5;
|
||||||
|
p[14] = chr6;
|
||||||
|
p[15] = chr7;
|
||||||
|
p[16] = irq_enable;
|
||||||
|
p[17] = (byte)irq_counter;
|
||||||
|
p[18] = irq_latch;
|
||||||
|
p[19] = irq_request;
|
||||||
|
p[20] = irq_preset;
|
||||||
|
p[21] = irq_preset_vbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadState(byte[] p)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
reg[i] = p[i];
|
||||||
|
}
|
||||||
|
prg0 = p[8];
|
||||||
|
prg1 = p[9];
|
||||||
|
chr01 = p[10];
|
||||||
|
chr23 = p[11];
|
||||||
|
chr4 = p[12];
|
||||||
|
chr5 = p[13];
|
||||||
|
chr6 = p[14];
|
||||||
|
chr7 = p[15];
|
||||||
|
irq_enable = p[16];
|
||||||
|
irq_counter = (Byte)p[17];
|
||||||
|
irq_latch = p[18];
|
||||||
|
irq_request = p[19];
|
||||||
|
irq_preset = p[20];
|
||||||
|
irq_preset_vbl = p[21];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,198 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Mapper052 Konami VRC2 type B //
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
using VirtualNes.Core.Debug;
|
||||||
|
using static VirtualNes.MMU;
|
||||||
|
using BYTE = System.Byte;
|
||||||
|
using INT = System.Int32;
|
||||||
|
|
||||||
|
namespace VirtualNes.Core
|
||||||
|
{
|
||||||
|
public class Mapper052 : Mapper
|
||||||
|
{
|
||||||
|
|
||||||
|
BYTE[] reg = new byte[9];
|
||||||
|
BYTE irq_enable;
|
||||||
|
BYTE irq_counter;
|
||||||
|
BYTE irq_latch;
|
||||||
|
INT irq_clock;
|
||||||
|
public Mapper052(NES parent) : base(parent) { }
|
||||||
|
|
||||||
|
public override void Reset()
|
||||||
|
{
|
||||||
|
for (byte i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
reg[i] = i;
|
||||||
|
}
|
||||||
|
reg[8] = 0;
|
||||||
|
|
||||||
|
irq_enable = 0;
|
||||||
|
irq_counter = 0;
|
||||||
|
irq_latch = 0;
|
||||||
|
irq_clock = 0;
|
||||||
|
|
||||||
|
SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1);
|
||||||
|
SetVROM_8K_Bank(0);
|
||||||
|
|
||||||
|
nes.SetRenderMethod(EnumRenderMethod.PRE_ALL_RENDER);
|
||||||
|
// nes->SetRenderMethod( NES::POST_RENDER );
|
||||||
|
// nes->SetRenderMethod( NES::POST_ALL_RENDER );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(ushort addr, byte data)
|
||||||
|
{
|
||||||
|
if (addr >= 0xf000) Debuger.Log($"MPRWR A={addr & 0xFFFF} D={data & 0xFF} L={nes.GetScanline()} CYC={nes.cpu.GetTotalCycles()}\n");
|
||||||
|
if (addr >= 0xf000) Debuger.Log($"MPRWR A={addr & 0xFFFF} RAM={RAM[0x1c0] & 0xFF} L={nes.GetScanline()} CYC={nes.cpu.GetTotalCycles()}\n");
|
||||||
|
switch (addr & 0xFFFF)
|
||||||
|
{
|
||||||
|
case 0x8000:
|
||||||
|
if (reg[8] != 0) SetPROM_8K_Bank(6, data);
|
||||||
|
else SetPROM_8K_Bank(4, data);
|
||||||
|
break;
|
||||||
|
case 0x9002:
|
||||||
|
reg[8] = (byte)(data & 0x02);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x9004:
|
||||||
|
data &= 0x03;
|
||||||
|
if (data == 0) SetVRAM_Mirror(VRAM_VMIRROR);
|
||||||
|
else if (data == 1) SetVRAM_Mirror(VRAM_HMIRROR);
|
||||||
|
else if (data == 2) SetVRAM_Mirror(VRAM_MIRROR4L);
|
||||||
|
else SetVRAM_Mirror(VRAM_MIRROR4H);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xA000:
|
||||||
|
SetPROM_8K_Bank(5, data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xB000:
|
||||||
|
reg[0] = (byte)((reg[0] & 0xF0) | (data & 0x0F));
|
||||||
|
SetVROM_1K_Bank(0, reg[0]);
|
||||||
|
break;
|
||||||
|
case 0xB001:
|
||||||
|
reg[0] = (byte)((reg[0] & 0x0F) | ((data & 0x0F) << 4));
|
||||||
|
SetVROM_1K_Bank(0, reg[0]);
|
||||||
|
break;
|
||||||
|
case 0xB002:
|
||||||
|
reg[1] = (byte)((reg[1] & 0xF0) | (data & 0x0F));
|
||||||
|
SetVROM_1K_Bank(1, reg[1]);
|
||||||
|
break;
|
||||||
|
case 0xB003:
|
||||||
|
reg[1] = (byte)((reg[1] & 0x0F) | ((data & 0x0F) << 4));
|
||||||
|
SetVROM_1K_Bank(1, reg[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xC000:
|
||||||
|
reg[2] = (byte)((reg[2] & 0xF0) | (data & 0x0F));
|
||||||
|
SetVROM_1K_Bank(2, reg[2]);
|
||||||
|
break;
|
||||||
|
case 0xC001:
|
||||||
|
reg[2] = (byte)((reg[2] & 0x0F) | ((data & 0x0F) << 4));
|
||||||
|
SetVROM_1K_Bank(2, reg[2]);
|
||||||
|
break;
|
||||||
|
case 0xC002:
|
||||||
|
reg[3] = (byte)((reg[3] & 0xF0) | (data & 0x0F));
|
||||||
|
SetVROM_1K_Bank(3, reg[3]);
|
||||||
|
break;
|
||||||
|
case 0xC003:
|
||||||
|
reg[3] = (byte)((reg[3] & 0x0F) | ((data & 0x0F) << 4));
|
||||||
|
SetVROM_1K_Bank(3, reg[3]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xD000:
|
||||||
|
reg[4] = (byte)((reg[4] & 0xF0) | (data & 0x0F));
|
||||||
|
SetVROM_1K_Bank(4, reg[4]);
|
||||||
|
break;
|
||||||
|
case 0xD001:
|
||||||
|
reg[4] = (byte)((reg[4] & 0x0F) | ((data & 0x0F) << 4));
|
||||||
|
SetVROM_1K_Bank(4, reg[4]);
|
||||||
|
break;
|
||||||
|
case 0xD002:
|
||||||
|
reg[5] = (byte)((reg[5] & 0xF0) | (data & 0x0F));
|
||||||
|
SetVROM_1K_Bank(5, reg[5]);
|
||||||
|
break;
|
||||||
|
case 0xD003:
|
||||||
|
reg[5] = (byte)((reg[5] & 0x0F) | ((data & 0x0F) << 4));
|
||||||
|
SetVROM_1K_Bank(5, reg[5]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xE000:
|
||||||
|
reg[6] = (byte)((reg[6] & 0xF0) | (data & 0x0F));
|
||||||
|
SetVROM_1K_Bank(6, reg[6]);
|
||||||
|
break;
|
||||||
|
case 0xE001:
|
||||||
|
reg[6] = (byte)((reg[6] & 0x0F) | ((data & 0x0F) << 4));
|
||||||
|
SetVROM_1K_Bank(6, reg[6]);
|
||||||
|
break;
|
||||||
|
case 0xE002:
|
||||||
|
reg[7] = (byte)((reg[7] & 0xF0) | (data & 0x0F));
|
||||||
|
SetVROM_1K_Bank(7, reg[7]);
|
||||||
|
break;
|
||||||
|
case 0xE003:
|
||||||
|
reg[7] = (byte)((reg[7] & 0x0F) | ((data & 0x0F) << 4));
|
||||||
|
SetVROM_1K_Bank(7, reg[7]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0xF000:
|
||||||
|
break;
|
||||||
|
case 0xF004:
|
||||||
|
case 0xFF04:
|
||||||
|
RAM[0x7f8] = 1;
|
||||||
|
break;
|
||||||
|
case 0xF008:
|
||||||
|
case 0xFF08:
|
||||||
|
irq_enable = 1;
|
||||||
|
// irq_latch = ((RAM[0x7f8]*2)+0x11)^0xFF; //Akumajou Special - Boku Dracula-kun
|
||||||
|
irq_latch = (byte)(((RAM[0x1c0] * 2) + 0x11) ^ 0xFF); //Teenage Mutant Ninja Turtles
|
||||||
|
irq_counter = irq_latch;
|
||||||
|
irq_clock = 0;
|
||||||
|
nes.cpu.ClrIRQ(CPU.IRQ_MAPPER);
|
||||||
|
break;
|
||||||
|
case 0xF00C:
|
||||||
|
irq_enable = 0;
|
||||||
|
nes.cpu.ClrIRQ(CPU.IRQ_MAPPER);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void HSync(int scanline)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Clock(int cycles)
|
||||||
|
{
|
||||||
|
if (irq_enable != null)
|
||||||
|
{
|
||||||
|
irq_clock += cycles * 3;
|
||||||
|
while (irq_clock >= 341)
|
||||||
|
{
|
||||||
|
irq_clock -= 341;
|
||||||
|
irq_counter++;
|
||||||
|
if (irq_counter == 0)
|
||||||
|
{
|
||||||
|
irq_counter = irq_latch;
|
||||||
|
nes.cpu.SetIRQ(CPU.IRQ_MAPPER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SaveState(byte[] p)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadState(byte[] p)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override bool IsStateSave()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bbcd8b5589ac667448a1be830aac1d4a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,166 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: f468229e616f1cd41aba98252208fbf7
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -0,0 +1,244 @@
|
|||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
// Mapper173 Subor //
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
using Codice.CM.Client.Differences;
|
||||||
|
using VirtualNes.Core.Debug;
|
||||||
|
using static VirtualNes.MMU;
|
||||||
|
using BYTE = System.Byte;
|
||||||
|
using INT = System.Int32;
|
||||||
|
namespace VirtualNes.Core
|
||||||
|
{
|
||||||
|
public class Mapper173 : Mapper
|
||||||
|
{
|
||||||
|
|
||||||
|
BYTE[] reg = new BYTE[10];
|
||||||
|
|
||||||
|
INT irq_counter, irq_latch;
|
||||||
|
BYTE irq_enable, irq_repeat;
|
||||||
|
BYTE irq_occur;
|
||||||
|
public Mapper173(NES parent) : base(parent) { }
|
||||||
|
|
||||||
|
public override bool IsStateSave()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public override void Reset()
|
||||||
|
{
|
||||||
|
// nes.ppu.SetExtLatchMode( TRUE );
|
||||||
|
for (INT i = 0; i < 11; i++) reg[i] = 0x00;
|
||||||
|
|
||||||
|
irq_enable = irq_repeat = 0;
|
||||||
|
irq_counter = irq_latch = 0;
|
||||||
|
irq_occur = 0;
|
||||||
|
|
||||||
|
SetPROM_32K_Bank(0);
|
||||||
|
nes.SetVideoMode(2 != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte ExRead(ushort addr)
|
||||||
|
{
|
||||||
|
Debuger.Log($"ExRead - addr= {addr}\n");
|
||||||
|
|
||||||
|
return 0x00;
|
||||||
|
|
||||||
|
switch (addr)
|
||||||
|
{
|
||||||
|
case 0x4026:
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
case 0x4033:
|
||||||
|
//D7:
|
||||||
|
//D6:
|
||||||
|
//D5:
|
||||||
|
//D4:
|
||||||
|
//D3:
|
||||||
|
//D2:
|
||||||
|
//D1:
|
||||||
|
//D0:
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
case 0x4204: //FDC主状态寄存器(STATUS)
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
case 0x4205: //FDC数据寄存器(DATA)(读???)
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ExWrite(ushort addr, byte data)
|
||||||
|
{
|
||||||
|
Debuger.Log($"ExWrite - addr= {addr} ; dat= {data}\n");
|
||||||
|
switch (addr)
|
||||||
|
{
|
||||||
|
case 0x4020:
|
||||||
|
reg[0] = data;
|
||||||
|
break;
|
||||||
|
case 0x4022:
|
||||||
|
reg[1] = data;
|
||||||
|
break;
|
||||||
|
case 0x4023:
|
||||||
|
reg[2] = data;
|
||||||
|
break;
|
||||||
|
case 0x4026:
|
||||||
|
reg[3] = data;
|
||||||
|
break;
|
||||||
|
case 0x4031:
|
||||||
|
reg[4] = data;
|
||||||
|
break;
|
||||||
|
case 0x4032:
|
||||||
|
reg[5] = data;
|
||||||
|
|
||||||
|
irq_repeat = (byte)(data & 0x01);
|
||||||
|
irq_enable = (byte)(data & 0x02);
|
||||||
|
irq_occur = 0;
|
||||||
|
if (irq_enable!= null)
|
||||||
|
{
|
||||||
|
irq_counter = irq_latch;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nes.cpu.ClrIRQ(CPU.IRQ_MAPPER);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x4034:
|
||||||
|
reg[6] = data;
|
||||||
|
|
||||||
|
irq_latch = (irq_latch & 0xFF00) | data;
|
||||||
|
break;
|
||||||
|
case 0x4035:
|
||||||
|
reg[7] = data;
|
||||||
|
|
||||||
|
irq_latch = (irq_latch & 0x00FF) | ((ushort)data << 8);
|
||||||
|
break;
|
||||||
|
case 0x4040:
|
||||||
|
SetPROM_4K_Bank(0x8000, data & 0x7F);
|
||||||
|
break;
|
||||||
|
case 0x4041:
|
||||||
|
SetPROM_4K_Bank(0x9000, data & 0x7F);
|
||||||
|
break;
|
||||||
|
case 0x4042:
|
||||||
|
SetPROM_4K_Bank(0xa000, data & 0x7F);
|
||||||
|
break;
|
||||||
|
case 0x4043:
|
||||||
|
SetPROM_4K_Bank(0xb000, data & 0x7F);
|
||||||
|
break;
|
||||||
|
case 0x4044:
|
||||||
|
SetPROM_4K_Bank(0xc000, data & 0x7F);
|
||||||
|
break;
|
||||||
|
case 0x4045:
|
||||||
|
SetPROM_4K_Bank(0xd000, data & 0x7F);
|
||||||
|
break;
|
||||||
|
case 0x4046:
|
||||||
|
SetPROM_4K_Bank(0xe000, data & 0x7F);
|
||||||
|
break;
|
||||||
|
case 0x4047:
|
||||||
|
SetPROM_4K_Bank(0xf000, data & 0x7F);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x4205: //FDC数据寄存器(DATA)(写???)
|
||||||
|
//
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override byte ReadLow(ushort addr)
|
||||||
|
{
|
||||||
|
// DEBUGOUT( "ReadLow - addr= %04x\n", addr );
|
||||||
|
|
||||||
|
return CPU_MEM_BANK[addr >> 13][addr & 0x1FFF];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void WriteLow(ushort addr, byte data)
|
||||||
|
{
|
||||||
|
// DEBUGOUT( "WriteLow - addr= %04x ; dat= %03x\n", addr, data );
|
||||||
|
|
||||||
|
CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(ushort addr, byte data)
|
||||||
|
{
|
||||||
|
// DEBUGOUT( "Write - addr= %04x ; dat= %03x\n", addr, data );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override void HSync(int scanline)
|
||||||
|
{
|
||||||
|
// if( (scanline >= 0 && scanline <= 239) ) {
|
||||||
|
// if( nes.ppu.IsDispON() ) {
|
||||||
|
// if( irq_enable ) {
|
||||||
|
// irq_enable = 0;
|
||||||
|
/// nes.cpu.SetIRQ( IRQ_MAPPER );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Clock(int cycles)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (irq_enable!= 0)
|
||||||
|
{
|
||||||
|
irq_counter -= cycles;
|
||||||
|
if (irq_counter <= 0)
|
||||||
|
{
|
||||||
|
//// irq_counter &= 0xFFFF;
|
||||||
|
irq_counter += irq_latch;
|
||||||
|
|
||||||
|
if (irq_occur == 0)
|
||||||
|
{
|
||||||
|
irq_occur = 0xFF;
|
||||||
|
if (irq_repeat == 0)
|
||||||
|
{
|
||||||
|
irq_enable = 0;
|
||||||
|
}
|
||||||
|
nes.cpu.SetIRQ(CPU.IRQ_MAPPER);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PPU_Latch(ushort addr)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
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 && PPU_SW)
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void LoadState(byte[] p)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c98a3c4204201144eb348e0d2f1f7076
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -60,6 +60,16 @@ namespace VirtualNes.Core
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void LoadState(byte[] p)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SaveState(byte[] p)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
namespace VirtualNes.Core
|
using VirtualNes.Core.Debug;
|
||||||
|
using static VirtualNes.MMU;
|
||||||
|
using BYTE = System.Byte;
|
||||||
|
using INT = System.Int32;
|
||||||
|
namespace VirtualNes.Core
|
||||||
{
|
{
|
||||||
public class _Mapper : Mapper
|
public class _Mapper : Mapper
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user