////////////////////////////////////////////////////////////////////////// // BoardOneBus // ////////////////////////////////////////////////////////////////////////// //code by CaH4e3 from fceumm void BoardOneBus::Reset() { inv_hack = 0; pcm_enable = pcm_irq = 0; pcm_clock = 0xE1; IRQReload = IRQCount = IRQa = 0; memset(cpu410x, 0x00, sizeof(cpu410x)); memset(ppu201x, 0x00, sizeof(ppu201x)); memset(apu40xx, 0x00, sizeof(apu40xx)); SetBank(); count = 0; } void BoardOneBus::WriteExPPU( WORD addr, BYTE data ) //Write $2010-$201F { ppu201x[addr&0x0F] = data; SetBank(); } BYTE BoardOneBus::ReadExAPU ( WORD addr ) //Read $4000-$403F { uint8 result = nes->apu->Read(addr); switch (addr & 0x3f) { case 0x15: if (apu40xx[0x30] & 0x10) { result = (result & 0x7f) | pcm_irq; } break; } return result; } void BoardOneBus::WriteExAPU( WORD addr, BYTE data ) //Write $4000-$403F { apu40xx[addr & 0x3f] = data; switch (addr & 0x3f) { case 0x12: if (apu40xx[0x30] & 0x10) { pcm_addr = data << 6; } break; case 0x13: if (apu40xx[0x30] & 0x10) { pcm_size = (data << 4) + 1; } break; case 0x15: if (apu40xx[0x30] & 0x10) { pcm_enable = data & 0x10; if (pcm_irq) { nes->cpu->ClrIRQ(IRQ_MAPPER); pcm_irq = 0; } if (pcm_enable) pcm_latch = pcm_clock; data &= 0xef; } break; } nes->apu->Write(addr,data); } void BoardOneBus::WriteLow( WORD addr, BYTE data ) { if((addr>=0x4100)&&(addr<=0x410F)) //Write $4100-$410F { switch (addr & 0xf) { case 0x1: IRQLatch = data & 0xfe; break; case 0x2: IRQReload = 1; break; case 0x3: nes->cpu->ClrIRQ(IRQ_MAPPER); IRQa = 0; break; case 0x4: IRQa = 1; break; default: cpu410x[addr & 0xf] = data; SetBank(); } } } void BoardOneBus::Write( WORD addr, BYTE data ) { switch (addr & 0xe001) { case 0x8000: mmc3cmd = (mmc3cmd & 0x38) | (data & 0xc7); SetBank(); break; case 0x8001: { switch (mmc3cmd & 7) { case 0: ppu201x[0x6] = data; SetBankPPU(); break; case 1: ppu201x[0x7] = data; SetBankPPU(); break; case 2: ppu201x[0x2] = data; SetBankPPU(); break; case 3: ppu201x[0x3] = data; SetBankPPU(); break; case 4: ppu201x[0x4] = data; SetBankPPU(); break; case 5: ppu201x[0x5] = data; SetBankPPU(); break; case 6: cpu410x[0x7] = data; SetBankCPU(); break; case 7: cpu410x[0x8] = data; SetBankCPU(); break; } break; } case 0xa000: mirror = data; SetBankPPU(); break; case 0xc000: IRQLatch = data & 0xfe; break; case 0xc001: IRQReload = 1; break; case 0xe000: nes->cpu->ClrIRQ(IRQ_MAPPER); IRQa = 0; break; case 0xe001: IRQa = 1; break; } } void BoardOneBus::SetBank() { SetBankCPU(); SetBankPPU(); } void BoardOneBus::SetBankCPU() { uint8 bankmode = cpu410x[0xb] & 7; uint8 mask = (bankmode == 0x7) ? (0xff) : (0x3f >> bankmode); uint32 block = ((cpu410x[0x0] & 0xf0) << 4) + (cpu410x[0xa] & (~mask)); uint32 pswap = (mmc3cmd & 0x40) << 8; uint8 bank0 = cpu410x[0x7 ^ inv_hack]; uint8 bank1 = cpu410x[0x8 ^ inv_hack]; uint8 bank2 = (cpu410x[0xb] & 0x40) ? (cpu410x[0x9]) : (~1); uint8 bank3 = ~0; SetPROM_8K_Bank((0x8000^pswap)>>13, block | (bank0 & mask)); SetPROM_8K_Bank(5, block | (bank1 & mask)); SetPROM_8K_Bank((0xc000^pswap)>>13, block | (bank2 & mask)); SetPROM_8K_Bank(7, block | (bank3 & mask)); } void BoardOneBus::SetBankPPU() { static const uint8 midx[8] = { 0, 1, 2, 0, 3, 4, 5, 0 }; uint8 mask = 0xff >> midx[ppu201x[0xa] & 7]; uint32 block = ((cpu410x[0x0] & 0x0f) << 11) + ((ppu201x[0x8] & 0x70) << 4) + (ppu201x[0xa] & (~mask)); uint32 cswap = (mmc3cmd & 0x80) << 5; uint8 bank0 = ppu201x[0x6] & (~1); uint8 bank1 = ppu201x[0x6] | 1; uint8 bank2 = ppu201x[0x7] & (~1); uint8 bank3 = ppu201x[0x7] | 1; uint8 bank4 = ppu201x[0x2]; uint8 bank5 = ppu201x[0x3]; uint8 bank6 = ppu201x[0x4]; uint8 bank7 = ppu201x[0x5]; SetOBCRAM_1K_Bank((0x0000^cswap)>>10, block | (bank0 & mask)); SetOBCRAM_1K_Bank((0x0400^cswap)>>10, block | (bank1 & mask)); SetOBCRAM_1K_Bank((0x0800^cswap)>>10, block | (bank2 & mask)); SetOBCRAM_1K_Bank((0x0c00^cswap)>>10, block | (bank3 & mask)); SetOBCRAM_1K_Bank((0x1000^cswap)>>10, block | (bank4 & mask)); SetOBCRAM_1K_Bank((0x1400^cswap)>>10, block | (bank5 & mask)); SetOBCRAM_1K_Bank((0x1800^cswap)>>10, block | (bank6 & mask)); SetOBCRAM_1K_Bank((0x1c00^cswap)>>10, block | (bank7 & mask)); if(mirror&0x01) SetVRAM_Mirror(VRAM_HMIRROR); else SetVRAM_Mirror(VRAM_VMIRROR); } void BoardOneBus::HSync( INT scanline ) { if ((scanline >= 0 && scanline <= 239)) { if (nes->ppu->IsDispON()) { uint32 count = IRQCount; if (!count || IRQReload) { IRQCount = IRQLatch; IRQReload = 0; } else IRQCount--; if (count && !IRQCount) { if (IRQa) nes->cpu->SetIRQ(IRQ_MAPPER); } } } } void BoardOneBus::Clock( INT cycles ) { if (pcm_enable) { pcm_latch -= cycles; if (pcm_latch <= 0) { pcm_latch += pcm_clock; pcm_size--; if (pcm_size < 0) { pcm_irq = 0x80; pcm_enable = 0; nes->cpu->SetIRQ(IRQ_MAPPER); } else { uint16 addr = pcm_addr | ((apu40xx[0x30]^3) << 14); uint8 raw_pcm = CPU_MEM_BANK[addr>>13][addr&0x1FFF] >> 1; // YWRAM[count] = CPU_MEM_BANK[addr>>13][addr&0x1FFF]; // count++; nes->apu->Write(0x4011, raw_pcm); pcm_addr++; pcm_addr &= 0x7FFF; } } } } void BoardOneBus::PPU_Latch( WORD addr ) { if(DirectInput.m_Sw[DIK_PAUSE]){ // nes->Dump_YWRAM(); } } void BoardOneBus::SaveState( LPBYTE p ) { // } void BoardOneBus::LoadState( LPBYTE p ) { // }