From a6cbe6df74de317e5d44d46badee0d1a92a127ed Mon Sep 17 00:00:00 2001 From: sin365 <353374337@qq.com> Date: Mon, 5 Aug 2024 01:44:13 +0800 Subject: [PATCH] transfer 016-018 --- .../VirtualNes.Core/Mapper/Mapper016.cs | 430 ++++++++++++++++++ .../VirtualNes.Core/Mapper/Mapper016.cs.meta | 11 + .../VirtualNes.Core/Mapper/Mapper017.cs | 127 ++++++ .../VirtualNes.Core/Mapper/Mapper017.cs.meta | 11 + .../VirtualNes.Core/Mapper/Mapper018.cs | 255 +++++++++++ 5 files changed, 834 insertions(+) create mode 100644 AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper016.cs create mode 100644 AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper016.cs.meta create mode 100644 AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper017.cs create mode 100644 AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper017.cs.meta diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper016.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper016.cs new file mode 100644 index 0000000..2bf76bb --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper016.cs @@ -0,0 +1,430 @@ +////////////////////////////////////////////////////////////////////////// +// Mapper016 Bandai Standard // +////////////////////////////////////////////////////////////////////////// +using static VirtualNes.MMU; +using static VirtualNes.Core.CPU; +using INT = System.Int32; +using BYTE = System.Byte; +using Codice.CM.Client.Differences; + +namespace VirtualNes.Core +{ + public class Mapper016 : Mapper + { + BYTE patch; // For Famicom Jump 2 + BYTE eeprom_type; // EEPROM type + + BYTE[] reg = new byte[3]; + + BYTE irq_enable; + INT irq_counter; + INT irq_latch; + BYTE irq_type; + + X24C01 x24c01; + X24C02 x24c02; + public Mapper016(NES parent) : base(parent) + { + } + + + public override void Reset() + { + patch = 0; + + reg[0] = reg[1] = reg[2] = 0; + irq_enable = 0; + irq_counter = 0; + irq_latch = 0; + + irq_type = 0; + nes.SetIrqType( NES.IRQMETHOD.IRQ_CLOCK); + + eeprom_type = 0; + + SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1); + + uint crc = nes.rom.GetPROM_CRC(); + + if (crc == 0x3f15d20d // Famicom Jump 2(J) + || crc == 0xf76aa523) + { // Famicom Jump 2(J)(alt) + patch = 1; + eeprom_type = 0xFF; + + WRAM[0x0BBC] = 0xFF; // SRAM対策 + } + + if (crc == 0x1d6f27f7) + { // Dragon Ball Z 2(Korean Hack) + nes.SetIrqType( NES.IRQMETHOD.IRQ_HSYNC); + eeprom_type = 1; + } + if (crc == 0x6f7247c8) + { // Dragon Ball Z 3(Korean Hack) + nes.SetIrqType( NES.IRQMETHOD.IRQ_CLOCK); + eeprom_type = 1; + } + + if (crc == 0x7fb799fd) + { // Dragon Ball 2 - Dai Maou Fukkatsu(J) + } + if (crc == 0x6c6c2feb // Dragon Ball 3 - Gokuu Den(J) + || crc == 0x8edeb257) + { // Dragon Ball 3 - Gokuu Den(J)(Alt) + } + if (crc == 0x31cd9903) + { // Dragon Ball Z - Kyoushuu! Saiya Jin(J) + nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC); + } + if (crc == 0xe49fc53e // Dragon Ball Z 2 - Gekishin Freeza!!(J) + || crc == 0x1582fee0) + { // Dragon Ball Z 2 - Gekishin Freeza!!(J) [alt] + nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC); + eeprom_type = 1; + } + if (crc == 0x09499f4d) + { // Dragon Ball Z 3 - Ressen Jinzou Ningen(J) + nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC); + eeprom_type = 1; + } + if (crc == 0x2e991109) + { // Dragon Ball Z Gaiden - Saiya Jin Zetsumetsu Keikaku (J) + nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC); + eeprom_type = 1; + } + if (crc == 0x146fb9c3) + { // SD Gundam Gaiden - Knight Gundam Monogatari(J) + } + + if (crc == 0x73ac76db // SD Gundam Gaiden - Knight Gundam Monogatari 2 - Hikari no Kishi(J) + || crc == 0x81a15eb8) + { // SD Gundam Gaiden - Knight Gundam Monogatari 3 - Densetsu no Kishi Dan(J) + eeprom_type = 1; + } + if (crc == 0x170250de) + { // Rokudenashi Blues(J) + nes.SetRenderMethod( EnumRenderMethod.POST_ALL_RENDER); + eeprom_type = 1; + } + + // DATACH系 + if (crc == 0x0be0a328 // Datach - SD Gundam - Gundam Wars(J) + || crc == 0x19e81461 // Datach - Dragon Ball Z - Gekitou Tenkaichi Budou Kai(J) + || crc == 0x5b457641 // Datach - Ultraman Club - Supokon Fight!(J) + || crc == 0x894efdbc // Datach - Crayon Shin Chan - Ora to Poi Poi(J) + || crc == 0x983d8175 // Datach - Battle Rush - Build Up Robot Tournament(J) + || crc == 0xbe06853f) + { // Datach - J League Super Top Players(J) + eeprom_type = 2; + } + if (crc == 0xf51a7f46) + { // Datach - Yuu Yuu Hakusho - Bakutou Ankoku Bujutsu Kai(J) + nes.SetIrqType(NES.IRQMETHOD.IRQ_HSYNC); + eeprom_type = 2; + } + + if (eeprom_type == 0) + { + nes.SetSAVERAM_SIZE(128); + x24c01.Reset(WRAM); + } + else + if (eeprom_type == 1) + { + nes.SetSAVERAM_SIZE(256); + x24c02.Reset(WRAM); + } + else + if (eeprom_type == 2) + { + nes.SetSAVERAM_SIZE(384); + x24c02.Reset(WRAM); + x24c01.Reset(WRAM + 256); + } + } + + //BYTE Mapper016::ReadLow(WORD addr) + public override byte ReadLow(ushort addr) + { + if (patch!=0) + { + return base.ReadLow(addr); + } + else + { + if ((addr & 0x00FF) == 0x0000) + { + BYTE ret = 0; + if (eeprom_type == 0) + { + ret = x24c01.Read(); + } + else + if (eeprom_type == 1) + { + ret = x24c02.Read(); + } + else + if (eeprom_type == 2) + { + ret = x24c02.Read() & x24c01.Read(); + } + return (ret ? 0x10 : 0) | (nes.GetBarcodeStatus()); + } + } + return 0x00; + } + + //void Mapper016::WriteLow(WORD addr, BYTE data) + public override void WriteLow(ushort addr, byte data) + { + if (patch == 0) + { + WriteSubA(addr, data); + } + else + { + Mapper::WriteLow(addr, data); + } + } + + void Mapper016::Write(WORD addr, BYTE data) + { + if (!patch) + { + WriteSubA(addr, data); + } + else + { + WriteSubB(addr, data); + } + } + + static BYTE eeprom_addinc; + + // Normal mapper #16 + void Mapper016::WriteSubA(WORD addr, BYTE data) + { + switch (addr & 0x000F) + { + case 0x0000: + case 0x0001: + case 0x0002: + case 0x0003: + case 0x0004: + case 0x0005: + case 0x0006: + case 0x0007: + if (VROM_1K_SIZE) + { + SetVROM_1K_Bank(addr & 0x0007, data); + } + if (eeprom_type == 2) + { + reg[0] = data; + x24c01.Write((data & 0x08) ? 0xFF : 0, (reg[1] & 0x40) ? 0xFF : 0); + } + break; + + case 0x0008: + SetPROM_16K_Bank(4, data); + break; + + case 0x0009: + 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 0x000A: + irq_enable = data & 0x01; + irq_counter = irq_latch; + nes.cpu.ClrIRQ(IRQ_MAPPER); + break; + case 0x000B: + irq_latch = (irq_latch & 0xFF00) | data; + irq_counter = (irq_counter & 0xFF00) | data; + break; + case 0x000C: + irq_latch = ((INT)data << 8) | (irq_latch & 0x00FF); + irq_counter = ((INT)data << 8) | (irq_counter & 0x00FF); + break; + + case 0x000D: + // EEPTYPE0(DragonBallZ) + if (eeprom_type == 0) + { + x24c01.Write((data & 0x20) ? 0xFF : 0, (data & 0x40) ? 0xFF : 0); + } + // EEPTYPE1(DragonBallZ2,Z3,Z Gaiden) + if (eeprom_type == 1) + { + x24c02.Write((data & 0x20) ? 0xFF : 0, (data & 0x40) ? 0xFF : 0); + } + // EEPTYPE2(DATACH) + if (eeprom_type == 2) + { + reg[1] = data; + x24c02.Write((data & 0x20) ? 0xFF : 0, (data & 0x40) ? 0xFF : 0); + x24c01.Write((reg[0] & 0x08) ? 0xFF : 0, (data & 0x40) ? 0xFF : 0); + } + break; + } + } + + // Famicom Jump 2 + void Mapper016::WriteSubB(WORD addr, BYTE data) + { + switch (addr) + { + case 0x8000: + case 0x8001: + case 0x8002: + case 0x8003: + reg[0] = data & 0x01; + SetPROM_8K_Bank(4, reg[0] * 0x20 + reg[2] * 2 + 0); + SetPROM_8K_Bank(5, reg[0] * 0x20 + reg[2] * 2 + 1); + break; + case 0x8004: + case 0x8005: + case 0x8006: + case 0x8007: + reg[1] = data & 0x01; + SetPROM_8K_Bank(6, reg[1] * 0x20 + 0x1E); + SetPROM_8K_Bank(7, reg[1] * 0x20 + 0x1F); + break; + case 0x8008: + reg[2] = data; + SetPROM_8K_Bank(4, reg[0] * 0x20 + reg[2] * 2 + 0); + SetPROM_8K_Bank(5, reg[0] * 0x20 + reg[2] * 2 + 1); + SetPROM_8K_Bank(6, reg[1] * 0x20 + 0x1E); + SetPROM_8K_Bank(7, reg[1] * 0x20 + 0x1F); + break; + + case 0x8009: + 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 0x800A: + irq_enable = data & 0x01; + irq_counter = irq_latch; + + // if( !irq_enable ) { + // nes.cpu.ClrIRQ( IRQ_MAPPER ); + // } + nes.cpu.ClrIRQ(IRQ_MAPPER); + break; + case 0x800B: + irq_latch = (irq_latch & 0xFF00) | data; + break; + case 0x800C: + irq_latch = ((INT)data << 8) | (irq_latch & 0x00FF); + break; + + case 0x800D: + break; + } + } + + void Mapper016::HSync(INT scanline) + { + if (irq_enable && (nes.GetIrqType() == NES.IRQMETHOD.IRQ_HSYNC)) + { + if (irq_counter <= 113) + { + nes.cpu.SetIRQ(IRQ_MAPPER); + // nes.cpu.IRQ(); + //// nes.cpu.IRQ_NotPending(); + // irq_enable = 0; + // irq_counter = 0; + irq_counter &= 0xFFFF; + } + else + { + irq_counter -= 113; + } + } + } + + void Mapper016::Clock(INT cycles) + { + if (irq_enable && (nes.GetIrqType() == NES::IRQ_CLOCK)) + { + if ((irq_counter -= cycles) <= 0) + { + nes.cpu.SetIRQ(IRQ_MAPPER); + // nes.cpu.IRQ(); + //// nes.cpu.IRQ_NotPending(); + // irq_enable = 0; + // irq_counter = 0; + irq_counter &= 0xFFFF; + } + } + } + + void Mapper016::SaveState(LPBYTE p) + { + p[0] = reg[0]; + p[1] = reg[1]; + p[2] = reg[2]; + p[3] = irq_enable; + *(INT*)&p[4] = irq_counter; + *(INT*)&p[8] = irq_latch; + + if (eeprom_type == 0) + { + x24c01.Save(&p[16]); + } + else + if (eeprom_type == 1) + { + x24c02.Save(&p[16]); + } + else + if (eeprom_type == 2) + { + x24c02.Save(&p[16]); + x24c01.Save(&p[48]); + } + } + + void Mapper016::LoadState(LPBYTE p) + { + reg[0] = p[0]; + reg[1] = p[1]; + reg[2] = p[2]; + irq_enable = p[3]; + irq_counter = *(INT*)&p[4]; + irq_latch = *(INT*)&p[8]; + if (eeprom_type == 0) + { + x24c01.Load(&p[16]); + } + else + if (eeprom_type == 1) + { + x24c02.Load(&p[16]); + } + else + if (eeprom_type == 2) + { + x24c02.Load(&p[16]); + x24c01.Load(&p[48]); + } + } + + + public override bool IsStateSave() + { + return true; + } + + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper016.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper016.cs.meta new file mode 100644 index 0000000..cace94d --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper016.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 6dc87b177aa092e4e98c49eb5b9e0bfb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper017.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper017.cs new file mode 100644 index 0000000..d1344c1 --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper017.cs @@ -0,0 +1,127 @@ +using static VirtualNes.MMU; +using static VirtualNes.Core.CPU; +using INT = System.Int32; +using BYTE = System.Byte; +using Codice.CM.Client.Differences; + +namespace VirtualNes.Core +{ + public class Mapper017 : Mapper + { + BYTE irq_enable; + INT irq_counter; + INT irq_latch; + public Mapper017(NES parent) : base(parent) + { + } + + + public override void Reset() + { + SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1); + + if (VROM_1K_SIZE != 0) + { + SetVROM_8K_Bank(0); + } + + irq_enable = 0; + irq_counter = 0; + irq_latch = 0; + } + + //void Mapper017::WriteLow(WORD addr, BYTE data) + public override void WriteLow(ushort addr, byte data) + { + switch (addr) + { + case 0x42FE: + if ((data & 0x10) != 0) SetVRAM_Mirror(VRAM_MIRROR4H); + else SetVRAM_Mirror(VRAM_MIRROR4L); + break; + case 0x42FF: + if ((data & 0x10) != 0) SetVRAM_Mirror(VRAM_HMIRROR); + else SetVRAM_Mirror(VRAM_VMIRROR); + break; + + case 0x4501: + irq_enable = 0; + nes.cpu.ClrIRQ(IRQ_MAPPER); + break; + case 0x4502: + irq_latch = (irq_latch & 0xFF00) | data; + break; + case 0x4503: + irq_latch = (irq_latch & 0x00FF) | ((INT)data << 8); + irq_counter = irq_latch; + irq_enable = 0xFF; + break; + + case 0x4504: + case 0x4505: + case 0x4506: + case 0x4507: + SetPROM_8K_Bank((byte)(addr & 0x07), data); + break; + + case 0x4510: + case 0x4511: + case 0x4512: + case 0x4513: + case 0x4514: + case 0x4515: + case 0x4516: + case 0x4517: + SetVROM_1K_Bank((byte)(addr & 0x07), data); + break; + + default: + base.WriteLow(addr, data); + break; + } + } + + //void Mapper017::HSync(INT scanline) + public override void HSync(int scanline) + { + if (irq_enable != 0) + { + if (irq_counter >= 0xFFFF - 113) + { + nes.cpu.SetIRQ(IRQ_MAPPER); + // nes.cpu.IRQ(); + // irq_counter = 0; + // irq_enable = 0; + irq_counter &= 0xFFFF; + } + else + { + irq_counter += 113; + } + } + } + + //void Mapper017::SaveState(LPBYTE p) + public override void SaveState(byte[] p) + { + //p[0] = irq_enable; + //*(INT*)&p[1] = irq_counter; + //*(INT*)&p[5] = irq_latch; + } + + //void Mapper017::LoadState(LPBYTE p) + public override void LoadState(byte[] p) + { + //irq_enable = p[0]; + //irq_counter = *(INT*)&p[1]; + //irq_latch = *(INT*)&p[5]; + } + + + public override bool IsStateSave() + { + return true; + } + + } +} diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper017.cs.meta b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper017.cs.meta new file mode 100644 index 0000000..6b34a7d --- /dev/null +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper017.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 776d527e770087845a767df931da9af6 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper018.cs b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper018.cs index b416798..c476644 100644 --- a/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper018.cs +++ b/AxibugEmuOnline.Client/Assets/VirtualNes.Core/Mapper/Mapper018.cs @@ -5,11 +5,18 @@ using static VirtualNes.MMU; using static VirtualNes.Core.CPU; using INT = System.Int32; using BYTE = System.Byte; +using Codice.CM.Client.Differences; namespace VirtualNes.Core { public class Mapper018 : Mapper { + BYTE[] reg = new byte[11]; + + BYTE irq_enable; + BYTE irq_mode; + INT irq_latch; + INT irq_counter; public Mapper018(NES parent) : base(parent) { } @@ -17,6 +24,254 @@ namespace VirtualNes.Core public override void Reset() { + for (INT i = 0; i < 11; i++) + { + reg[i] = 0; + } + reg[2] = (byte)(PROM_8K_SIZE - 2); + reg[3] = (byte)(PROM_8K_SIZE - 1); + + SetPROM_32K_Bank(0, 1, PROM_8K_SIZE - 2, PROM_8K_SIZE - 1); + + irq_enable = 0; + irq_mode = 0; + irq_counter = 0xFFFF; + irq_latch = 0xFFFF; + + uint crc = nes.rom.GetPROM_CRC(); + + if (crc == 0xefb1df9e) + { // The Lord of King(J) + nes.SetRenderMethod(EnumRenderMethod.PRE_ALL_RENDER); + } + if (crc == 0x3746f951) + { // Pizza Pop!(J) + nes.SetRenderMethod(EnumRenderMethod.PRE_ALL_RENDER); + } + + // nes.SetRenderMethod( NES::PRE_ALL_RENDER ); + // nes.SetRenderMethod( NES::POST_ALL_RENDER ); + } + + //void Mapper018::Write(WORD addr, BYTE data) + public override void Write(ushort addr, byte data) + { + switch (addr) + { + case 0x8000: + reg[0] = (byte)((reg[0] & 0xF0) | (data & 0x0F)); + SetPROM_8K_Bank(4, reg[0]); + break; + case 0x8001: + reg[0] = (byte)((reg[0] & 0x0F) | ((data & 0x0F) << 4)); + SetPROM_8K_Bank(4, reg[0]); + break; + case 0x8002: + reg[1] = (byte)((reg[1] & 0xF0) | (data & 0x0F)); + SetPROM_8K_Bank(5, reg[1]); + break; + case 0x8003: + reg[1] = (byte)((reg[1] & 0x0F) | ((data & 0x0F) << 4)); + SetPROM_8K_Bank(5, reg[1]); + break; + case 0x9000: + reg[2] = (byte)((reg[2] & 0xF0) | (data & 0x0F)); + SetPROM_8K_Bank(6, reg[2]); + break; + case 0x9001: + reg[2] = (byte)((reg[2] & 0x0F) | ((data & 0x0F) << 4)); + SetPROM_8K_Bank(6, reg[2]); + break; + + case 0xA000: + reg[3] = (byte)((reg[3] & 0xF0) | (data & 0x0F)); + SetVROM_1K_Bank(0, reg[3]); + break; + case 0xA001: + reg[3] = (byte)((reg[3] & 0x0F) | ((data & 0x0F) << 4)); + SetVROM_1K_Bank(0, reg[3]); + break; + case 0xA002: + reg[4] = (byte)((reg[4] & 0xF0) | (data & 0x0F)); + SetVROM_1K_Bank(1, reg[4]); + break; + case 0xA003: + reg[4] = (byte)((reg[4] & 0x0F) | ((data & 0x0F) << 4)); + SetVROM_1K_Bank(1, reg[4]); + break; + + case 0xB000: + reg[5] = (byte)((reg[5] & 0xF0) | (data & 0x0F)); + SetVROM_1K_Bank(2, reg[5]); + break; + case 0xB001: + reg[5] = (byte)((reg[5] & 0x0F) | ((data & 0x0F) << 4)); + SetVROM_1K_Bank(2, reg[5]); + break; + case 0xB002: + reg[6] = (byte)((reg[6] & 0xF0) | (data & 0x0F)); + SetVROM_1K_Bank(3, reg[6]); + break; + case 0xB003: + reg[6] = (byte)((reg[6] & 0x0F) | ((data & 0x0F) << 4)); + SetVROM_1K_Bank(3, reg[6]); + break; + + case 0xC000: + reg[7] = (byte)((reg[7] & 0xF0) | (data & 0x0F)); + SetVROM_1K_Bank(4, reg[7]); + break; + case 0xC001: + reg[7] = (byte)((reg[7] & 0x0F) | ((data & 0x0F) << 4)); + SetVROM_1K_Bank(4, reg[7]); + break; + case 0xC002: + reg[8] = (byte)((reg[8] & 0xF0) | (data & 0x0F)); + SetVROM_1K_Bank(5, reg[8]); + break; + case 0xC003: + reg[8] = (byte)((reg[8] & 0x0F) | ((data & 0x0F) << 4)); + SetVROM_1K_Bank(5, reg[8]); + break; + + case 0xD000: + reg[9] = (byte)((reg[9] & 0xF0) | (data & 0x0F)); + SetVROM_1K_Bank(6, reg[9]); + break; + case 0xD001: + reg[9] = (byte)((reg[9] & 0x0F) | ((data & 0x0F) << 4)); + SetVROM_1K_Bank(6, reg[9]); + break; + case 0xD002: + reg[10] = (byte)((reg[10] & 0xF0) | (data & 0x0F)); + SetVROM_1K_Bank(7, reg[10]); + break; + case 0xD003: + reg[10] = (byte)((reg[10] & 0x0F) | ((data & 0x0F) << 4)); + SetVROM_1K_Bank(7, reg[10]); + break; + + case 0xE000: + irq_latch = (irq_latch & 0xFFF0) | (data & 0x0F); + break; + case 0xE001: + irq_latch = (irq_latch & 0xFF0F) | ((data & 0x0F) << 4); + break; + case 0xE002: + irq_latch = (irq_latch & 0xF0FF) | ((data & 0x0F) << 8); + break; + case 0xE003: + irq_latch = (irq_latch & 0x0FFF) | ((data & 0x0F) << 12); + break; + + case 0xF000: + // if( data & 0x01 ) { + irq_counter = irq_latch; + // } else { + // irq_counter = 0; + // } + break; + case 0xF001: + irq_mode = (byte)((data >> 1) & 0x07); + irq_enable = ((byte)(data & 0x01)); + // if( !irq_enable ) { + nes.cpu.ClrIRQ(IRQ_MAPPER); + // } + break; + + case 0xF002: + data &= 0x03; + if (data == 0) SetVRAM_Mirror(VRAM_HMIRROR); + else if (data == 1) SetVRAM_Mirror(VRAM_VMIRROR); + else SetVRAM_Mirror(VRAM_MIRROR4L); + break; + } + } + + //void Mapper018::Clock(INT cycles) + public override void Clock(int cycles) + { + bool bIRQ = false; + INT irq_counter_old = irq_counter; + + if (irq_enable != 0 && irq_counter != 0) + { + irq_counter -= cycles; + + switch (irq_mode) + { + case 0: + if (irq_counter <= 0) + { + bIRQ = true; + } + break; + case 1: + if ((irq_counter & 0xF000) != (irq_counter_old & 0xF000)) + { + bIRQ = true; + } + break; + case 2: + case 3: + if ((irq_counter & 0xFF00) != (irq_counter_old & 0xFF00)) + { + bIRQ = true; + } + break; + case 4: + case 5: + case 6: + case 7: + if ((irq_counter & 0xFFF0) != (irq_counter_old & 0xFFF0)) + { + bIRQ = true; + } + break; + } + + if (bIRQ) + { + //// irq_enable = 0; + // irq_counter = irq_latch; + irq_counter = 0; + irq_enable = 0; + // nes.cpu.IRQ_NotPending(); + nes.cpu.SetIRQ(IRQ_MAPPER); + } + } + } + + //void Mapper018::SaveState(LPBYTE p) + public override void SaveState(byte[] p) + { + //for (INT i = 0; i < 11; i++) + //{ + // p[i] = reg[i]; + //} + //p[11] = irq_enable; + //p[12] = irq_mode; + //*(INT*)&p[13] = irq_counter; + //*(INT*)&p[17] = irq_latch; + } + + //void Mapper018::LoadState(LPBYTE p) + public override void LoadState(byte[] p) + { + //for (INT i = 0; i < 11; i++) + //{ + // p[i] = reg[i]; + //} + //irq_enable = p[11]; + //irq_mode = p[12]; + //irq_counter = *(INT*)&p[13]; + //irq_latch = *(INT*)&p[17]; + } + + + public override bool IsStateSave() + { + return true; } }