////////////////////////////////////////////////////////////////////////// // Mapper163 NanJing Games // ////////////////////////////////////////////////////////////////////////// using static VirtualNes.MMU; using static VirtualNes.Core.CPU; using INT = System.Int32; using BYTE = System.Byte; using System; using Codice.CM.Client.Differences; namespace VirtualNes.Core { public class Mapper163 : Mapper { //BYTE strobe; //BYTE security; //BYTE trigger; //BYTE rom_type; //BYTE reg[2]; BYTE[] reg = new byte[3]; BYTE strobe, trigger; ushort security; BYTE rom_type; INT www, index; public Mapper163(NES parent) : base(parent) { } static Int32[] index_adjust = new Int32[]{ -1, -1, -1, -1, 2, 4, 6, 8 }; static Int16[] step_table = new Int16[] { 7,8,9,10,11,12,13,14,16,17,19,21,23,25,28,31,34,37,41,45,50,55, 60,66,73,80,88,97,107,118,130,143,157,173,190,209,230,253,279, 307,337,371,408,449,494,544,598,658,724,796,876,963,1060, 1166,1282,1411,1552,1707,1878,2066,2272,2499,2749,3024,3327, 3660,4026,4428,4871,5358,5894,6484,7132,7845,8630,9493,10442, 11487,12635,13899,15289,16818,18500,20350,22385,24623,27086,29794,32767 }; BYTE adpcm_decoder(BYTE data) { int sb, delta; int cur_sample = 0; if ((data & 8) != 0) sb = 1; else sb = 0; data &= 7; delta = (step_table[index] * data) / 4 + step_table[index] / 8; if (sb == 1) delta = -delta; cur_sample += delta; if (cur_sample > 32767) cur_sample = 32767; else if (cur_sample < -32768) cur_sample = -32768; else cur_sample = cur_sample; index += index_adjust[data]; if (index < 0) index = 0; if (index > 88) index = 88; return (byte)(cur_sample & 0xff); } //void Mapper163::Reset() public override void Reset() { index = 0; reg[1] = 0xFF; strobe = 1; security = trigger = reg[0] = 0x00; rom_type = 0; SetPROM_32K_Bank(15); // jedi_table_init(); uint crc = nes.rom.GetPROM_CRC(); if (crc == 0xb6a10d5d) { // Hu Lu Jin Gang (NJ039) (Ch) [dump] SetPROM_32K_Bank(0); } if (crc == 0xf52468e7 // San Guo Wu Shuang - Meng Jiang Zhuan (NJ047) (Ch) [dump] || crc == 0x696D98E3) { // San Guo Zhi Lv Bu Zhuan (NJ040) (Ch) [dump] rom_type = 1; } if (crc == 0xEFF96E8A) { // Mo Shou Shi Jie E Mo Lie Ren (NJ097) (Ch) [dump] rom_type = 2; } www = 0; } ///BYTE Mapper163::ReadLow(WORD addr) public override byte ReadLow(ushort addr) { // DEBUGOUT( "ReadLow - addr= %04x\n", addr ); if ((addr >= 0x5000 && addr < 0x6000)) { switch (addr & 0x7700) { case 0x5100: return (byte)security; break; case 0x5500: if (trigger!=0) return (byte)security; else return 0; break; } return 4; } else if (addr >= 0x6000) { return CPU_MEM_BANK[addr >> 13][addr & 0x1FFF]; } return base.ReadLow(addr); } //void Mapper163::WriteLow(WORD addr, BYTE data) public override void WriteLow(ushort addr, byte data) { // if(addr==0x5200) DEBUGOUT( "WriteLow - addr= %04x ; dat= %03x\n", addr, data ); if ((addr >= 0x4020 && addr < 0x6000)) { if (addr == 0x5101) { if (strobe !=0 && data == 0) { trigger ^= 1; // trigger ^= 0xFF; } strobe = data; } else if (addr == 0x5100 && data == 6) { SetPROM_32K_Bank(3); } else { switch (addr & 0x7300) { case 0x5000: reg[1] = data; SetPROM_32K_Bank((reg[1] & 0xF) | (reg[0] << 4)); if ((reg[1] & 0x80) == 0 && (nes.ppu.GetScanlineNo() < 128)) SetCRAM_8K_Bank(0); if (rom_type == 1) SetCRAM_8K_Bank(0); break; case 0x5100: reg[2] = data; // nes.apu.Write(0x4011,(decode(reg[0]&0xf)<<3)); break; case 0x5200: reg[0] = data; SetPROM_32K_Bank((reg[1] & 0xF) | (reg[0] << 4)); break; case 0x5300: security = data; break; } } } else if (addr >= 0x6000) { CPU_MEM_BANK[addr >> 13][addr & 0x1FFF] = data; if ((addr >= 0x7900 && addr <= 0x79FF)) { // WAVRAM[addr&0xFF] = data; // if(addr==0x79FF){ // memcpy( YWRAM+(www*256), WAVRAM, 256); // www++; // } // nes.apu.Write(0x4011,(adpcm_decoder(data))); nes.apu.Write(0x4011, data); } } } //void Mapper163::Write(WORD addr, BYTE data) public override void Write(ushort addr, byte data) { // DEBUGOUT( "Write - addr= %04x ; dat= %03x\n", addr, data ); } //void Mapper163::HSync(int scanline) public override void HSync(int scanline) { if ((reg[1] & 0x80) !=0 && nes.ppu.IsDispON()) { if (scanline == 127) { SetCRAM_4K_Bank(0, 1); SetCRAM_4K_Bank(4, 1); } if (rom_type == 1) { if (scanline < 127) { SetCRAM_4K_Bank(0, 0); SetCRAM_4K_Bank(4, 0); } } else { if (scanline == 239) { SetCRAM_4K_Bank(0, 0); SetCRAM_4K_Bank(4, 0); if (rom_type == 2) SetCRAM_4K_Bank(4, 1); } } } } ///void Mapper163::PPU_Latch(WORD addr) //{ // if (DirectInput.m_Sw[DIK_PAUSE]) // { // nes.Dump_YWRAM(); // } //} //void Mapper163::SaveState(LPBYTE p) public override void SaveState(byte[] p) { p[0] = reg[0]; p[1] = reg[1]; } //void Mapper163::LoadState(LPBYTE p) public override void LoadState(byte[] p) { reg[0] = p[0]; reg[1] = p[1]; } } }