AxibugEmuOnline/References/VirtuaNESex_src_191105/NES/Mapper/Mapper121 - 副本.cpp
2024-08-05 17:58:53 +08:00

240 lines
5.8 KiB
C++

//////////////////////////////////////////////////////////////////////////
// Mapper121 //
//////////////////////////////////////////////////////////////////////////
void Mapper121::Reset()
{
EXPREGS[3] = 0x80;
EXPREGS[5] = 0;
IRQReload = IRQCount = IRQLatch = IRQa = 0;
MMC3cmd = A000B = A001B = 0;
DRegBuf[0] = 0;
DRegBuf[1] = 2;
DRegBuf[2] = 4;
DRegBuf[3] = 5;
DRegBuf[4] = 6;
DRegBuf[5] = 7;
DRegBuf[6] = 0;
DRegBuf[7] = 1;
Fix121MMC3PRG(MMC3cmd);
Fix121MMC3CHR(MMC3cmd);
}
BYTE Mapper121::ReadLow( WORD addr )
{
DEBUGOUT( "MPRWR A=%04X L=%3d CYC=%d\n", addr&0xFFFF, nes->GetScanline(), nes->cpu->GetTotalCycles() );
if((addr>=0x5000)&&(addr<=0x5FFF)) return EXPREGS[4];
if(addr>=0x6000) return CPU_MEM_BANK[addr>>13][addr&0x1FFF];
return Mapper::ReadLow( addr );
}
void Mapper121::WriteLow( WORD addr, BYTE data )
{
DEBUGOUT( "MPRWR A=%04X D=%02X L=%3d CYC=%d\n", addr&0xFFFF, data&0xFF, nes->GetScanline(), nes->cpu->GetTotalCycles() );
if((addr>=0x5000)&&(addr<=0x5FFF)){
const uint8 prot_array[4] = { 0x83, 0x83, 0x42, 0x00 };
EXPREGS[4] = prot_array[data & 3];
if ((addr & 0x5180) == 0x5180) {
EXPREGS[3] = data;
Fix121MMC3PRG(MMC3cmd);
Fix121MMC3CHR(MMC3cmd);
}
}
if(addr>=0x6000) CPU_MEM_BANK[addr>>13][addr&0x1FFF] = data;
}
void Mapper121::Write( WORD addr, BYTE data )
{
DEBUGOUT( "MPRWR A=%04X D=%02X L=%3d CYC=%d\n", addr&0xFFFF, data&0xFF, nes->GetScanline(), nes->cpu->GetTotalCycles() );
if(addr<0xA000){
switch (addr & 0xE003) {
case 0x8000:
MMC3CMDWrite(addr, data);
Fix121MMC3PRG(MMC3cmd);
break;
case 0x8001:
EXPREGS[6] = ((data&1)<<5)|((data&2)<<3)|((data&4)<<1)|((data&8)>>1)|((data&0x10)>>3)|((data&0x20)>>5);
if (!EXPREGS[7]) SetDATA();
MMC3CMDWrite(addr, data);
Fix121MMC3PRG(MMC3cmd);
break;
case 0x8003:
EXPREGS[5] = data;
SetDATA();
MMC3CMDWrite(0x8000, data);
Fix121MMC3PRG(MMC3cmd);
break;
}
}else{
MMC3MIRWrite(addr, data);
MMC3IRQWrite(addr, data);
}
}
void Mapper121::MMC3CMDWrite(WORD A, BYTE V)
{
switch (A & 0xE001) {
case 0x8000:
if ((V & 0x40) != (MMC3cmd & 0x40))
Fix121MMC3PRG(V);
if ((V & 0x80) != (MMC3cmd & 0x80))
Fix121MMC3CHR(V);
MMC3cmd = V;
break;
case 0x8001:
{
int cbase = (MMC3cmd & 0x80) << 5;
DRegBuf[MMC3cmd & 0x7] = V;
switch (MMC3cmd & 0x07) {
case 0:
PPUSW((cbase ^ 0x000), V & (~1));
PPUSW((cbase ^ 0x400), V | 1);
break;
case 1:
PPUSW((cbase ^ 0x800), V & (~1));
PPUSW((cbase ^ 0xC00), V | 1);
break;
case 2:
PPUSW(cbase ^ 0x1000, V);
break;
case 3:
PPUSW(cbase ^ 0x1400, V);
break;
case 4:
PPUSW(cbase ^ 0x1800, V);
break;
case 5:
PPUSW(cbase ^ 0x1C00, V);
break;
case 6:
if (MMC3cmd&0x40) CPUSW(0xC000, V);
else CPUSW(0x8000, V);
break;
case 7:
CPUSW(0xA000, V);
break;
}
break;
}
}
}
void Mapper121::MMC3MIRWrite(WORD A, BYTE V)
{
switch (A & 0xE001) {
case 0xA000:
A000B = V;
if (A000B & 0x01) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
break;
case 0xA001:
A001B = V;
break;
}
}
void Mapper121::MMC3IRQWrite(WORD A, BYTE V)
{
switch (A & 0xE001) {
case 0xC000: IRQReload = 0;IRQCount = V; break;
case 0xC001: IRQReload = 0;IRQLatch = V; break;
case 0xE000: IRQReload = 0;IRQa = 0;nes->cpu->ClrIRQ(IRQ_MAPPER); break;
case 0xE001: IRQReload = 0;IRQa = 1; break;
}
}
void Mapper121::SetDATA()
{
switch (EXPREGS[5] & 0x3F) {
case 0x20: EXPREGS[7] = 1; EXPREGS[0] = EXPREGS[6]; break;
case 0x29: EXPREGS[7] = 1; EXPREGS[0] = EXPREGS[6]; break;
case 0x26: EXPREGS[7] = 0; EXPREGS[0] = EXPREGS[6]; break;
case 0x2B: EXPREGS[7] = 1; EXPREGS[0] = EXPREGS[6]; break;
case 0x2C: EXPREGS[7] = 1; if (EXPREGS[6]) EXPREGS[0] = EXPREGS[6]; break;
case 0x3C:
case 0x3F: EXPREGS[7] = 1; EXPREGS[0] = EXPREGS[6]; break;
case 0x28: EXPREGS[7] = 0; EXPREGS[1] = EXPREGS[6]; break;
case 0x2A: EXPREGS[7] = 0; EXPREGS[2] = EXPREGS[6]; break;
case 0x2F: break;
default: EXPREGS[5] = 0; break;
}
}
void Mapper121::PPUSW( WORD addr, BYTE data )
{
if ((nes->rom->GetPROM_SIZE()*2)==nes->rom->GetVROM_SIZE()) {
SetVROM_1K_Bank(addr>>10, data | ((EXPREGS[3] & 0x80) << 1));
} else {
if ((addr & 0x1000) == ((MMC3cmd & 0x80) << 5))
SetVROM_1K_Bank(addr>>10, data | 0x100);
else
SetVROM_1K_Bank(addr>>10, data);
}
}
void Mapper121::CPUSW( WORD addr, BYTE data )
{
if (EXPREGS[5] & 0x3F) {
SetPROM_8K_Bank(addr>>13, (data & 0x1F) | ((EXPREGS[3] & 0x80) >> 2));
SetPROM_8K_Bank(7, (EXPREGS[0]) | ((EXPREGS[3] & 0x80) >> 2));
SetPROM_8K_Bank(6, (EXPREGS[1]) | ((EXPREGS[3] & 0x80) >> 2));
SetPROM_8K_Bank(5, (EXPREGS[2]) | ((EXPREGS[3] & 0x80) >> 2));
} else {
SetPROM_8K_Bank(addr>>13, (data & 0x1F) | ((EXPREGS[3] & 0x80) >> 2));
}
}
void Mapper121::Fix121MMC3PRG(BYTE data)
{
if (data & 0x40) {
CPUSW(0xC000, DRegBuf[6]);
CPUSW(0x8000, PROM_8K_SIZE-2);
} else {
CPUSW(0x8000, DRegBuf[6]);
CPUSW(0xC000, PROM_8K_SIZE-2);
}
CPUSW(0xA000, DRegBuf[7]);
CPUSW(0xE000, PROM_8K_SIZE-1);
}
void Mapper121::Fix121MMC3CHR(BYTE data)
{
int cbase = (data & 0x80) << 5;
PPUSW((cbase ^ 0x0000), DRegBuf[0] & (~1));
PPUSW((cbase ^ 0x0400), DRegBuf[0] | 1);
PPUSW((cbase ^ 0x0800), DRegBuf[1] & (~1));
PPUSW((cbase ^ 0x0C00), DRegBuf[1] | 1);
PPUSW((cbase ^ 0x1000), DRegBuf[2]);
PPUSW((cbase ^ 0x1400), DRegBuf[3]);
PPUSW((cbase ^ 0x1800), DRegBuf[4]);
PPUSW((cbase ^ 0x1c00), DRegBuf[5]);
if (A000B & 0x01) SetVRAM_Mirror(VRAM_HMIRROR);
else SetVRAM_Mirror(VRAM_VMIRROR);
}
void Mapper121::HSync(INT scanline)
{
if ((scanline >= 0 && scanline <= 239)) {
if (nes->ppu->IsDispON())
{
if (IRQa && !IRQReload) {
if (scanline == 0) {
if (IRQCount) {
IRQCount -= 1;
}
}
if (!(IRQCount)){
IRQReload = 0xFF;
IRQCount = IRQLatch;
nes->cpu->SetIRQ(IRQ_MAPPER);
}
IRQCount--;
}
}
}
}