AxibugEmuOnline/References/VirtuaNESex_src_191105/NES/Mapper/Mapper116b.cpp

446 lines
8.8 KiB
C++
Raw Normal View History

2024-08-05 17:58:53 +08:00
//////////////////////////////////////////////////////////////////////////
// Mapper116 CartSaint : <20>H<EFBFBD>VAV<41><56><EFBFBD><EFBFBD><EFBFBD>` //
//////////////////////////////////////////////////////////////////////////
void Mapper116::Reset()
{
int i;
mode = 0;
vrc2_prg[0] = 0x0;
vrc2_prg[1] = 0x1;
vrc2_nmt = 0;
for (i=0; i < 8; ++i)
vrc2_chr[i] = i;
mmc3_ctrl = 0;
mmc3_nmt = 0;
mmc3_banks[0] = 0x0;
mmc3_banks[1] = 0x1;
mmc3_banks[2] = 0x4;
mmc3_banks[3] = 0x5;
mmc3_banks[4] = 0x6;
mmc3_banks[5] = 0x7;
mmc3_banks[6] = 0x3C;
mmc3_banks[7] = 0x3D;
mmc3_banks[8] = 0xFE;
mmc3_banks[9] = 0xFF;
mmc1_buffer = 0;
mmc1_shifter = 0;
mmc1_regs[0] = 0x4U|0x8U;
mmc1_regs[1] = 0;
mmc1_regs[2] = 0;
mmc1_regs[3] = 0;
irq_enable = 0; // Disable
irq_counter = 0;
irq_latch = 0;
NES_mapper116_MMC3_set_CPU_banks();
NES_mapper116_MMC3_set_Nmt();
NES_mapper116_MMC3_set_PPU_banks();
}
void Mapper116::NES_mapper116_MMC3_set_CPU_banks()
{
switch (mode & 0x3)
{
case 0x0:
SetPROM_32K_Bank(vrc2_prg[0], vrc2_prg[1], 0x1E, 0x1F);
break;
case 0x1:
{
const uint32 i = mmc3_ctrl >> 5 & 0x2U;
SetPROM_32K_Bank(mmc3_banks[6+i],mmc3_banks[6+1],mmc3_banks[6+(i^2)],mmc3_banks[6+3] );
break;
}
case 0x2:
{
const uint32 bank = mmc1_regs[3] & 0xFU;
if (mmc1_regs[0] & 0x8U)
{
SetPROM_16K_Bank(4,(mmc1_regs[0] & 0x4U) ? bank : 0x0);
SetPROM_16K_Bank(6,(mmc1_regs[0] & 0x4U) ? 0xF : bank );
}
else{
SetPROM_32K_Bank( bank >> 1 );
}
break;
}
}
}
void Mapper116::NES_mapper116_MMC3_set_PPU_banks()
{
const uint32 base = (mode & 0x4) << 6;
switch (mode & 0x3)
{
case 0x0:
SetVROM_8K_Bank(
base|vrc2_chr[0],
base|vrc2_chr[1],
base|vrc2_chr[2],
base|vrc2_chr[3],
base|vrc2_chr[4],
base|vrc2_chr[5],
base|vrc2_chr[6],
base|vrc2_chr[7] );
break;
case 0x1:
{
const uint32 swap = (mmc3_ctrl & 0x80U) << 5;
SetVROM_2K_Bank( (0x0000 ^ swap)/0x400+0,base >> 1 | mmc3_banks[0]);
SetVROM_2K_Bank( (0x0000 ^ swap)/0x400+2,base >> 1 | mmc3_banks[1]);
SetVROM_1K_Bank((0x1000 ^ swap)/0x400+0,base|mmc3_banks[2]);
SetVROM_1K_Bank((0x1000 ^ swap)/0x400+1,base|mmc3_banks[3]);
SetVROM_1K_Bank((0x1000 ^ swap)/0x400+2,base|mmc3_banks[4]);
SetVROM_1K_Bank((0x1000 ^ swap)/0x400+3,base|mmc3_banks[5]);
break;
}
case 0x2:
SetVROM_4K_Bank(0,(mmc1_regs[0] & 0x10U) ? mmc1_regs[1] : mmc1_regs[1] & 0x1EU );
SetVROM_4K_Bank(4,(mmc1_regs[0] & 0x10U) ? mmc1_regs[2] : mmc1_regs[1] | 0x01U );
break;
}
}
void Mapper116::NES_mapper116_MMC3_set_Nmt()
{
uint8 nmtCtrl = 0XFF;
switch (mode & 0x3)
{
case 0x0:
nmtCtrl = (vrc2_nmt & 0x1U) ? VRAM_HMIRROR : VRAM_VMIRROR ;
break;
case 0x1:
nmtCtrl = (mmc3_nmt & 0x1U) ? VRAM_HMIRROR : VRAM_VMIRROR ;
break;
case 0x2:
switch (mmc1_regs[0] & 0x3U)
{
case 0x0: SetVRAM_Mirror(VRAM_MIRROR4L); break;
case 0x1: SetVRAM_Mirror(VRAM_MIRROR4H); break;
case 0x2: nmtCtrl =VRAM_VMIRROR; break;
default: nmtCtrl = VRAM_HMIRROR ; break;
}
break;
default: return;
}
if(nmtCtrl!=0xff)
SetVRAM_Mirror(nmtCtrl);
}
void Mapper116::WriteLow( WORD addr, BYTE data )
{
if( (addr & 0x4100) == 0x4100 )
{
if (mode != data)
{
mode = data;
if ((data & 0x3) != 1)
{
//nes6502_ClrIRQ( IRQ_MAPPER );//irq.unit.Disable( cpu );
irq_counter = irq_latch;
irq_enable = 0;
nes->cpu->ClrIRQ( IRQ_MAPPER );
}
NES_mapper116_MMC3_set_CPU_banks();
NES_mapper116_MMC3_set_Nmt();
NES_mapper116_MMC3_set_PPU_banks();
}
}
}
void Mapper116::Mapper116_Poke_Vrc2_8000(uint32 address,uint32 data)
{
//NST_ASSERT( (mode & 0x3) == 0 );
data &= 0x1F;
address = address >> 13 & 0x1;
if (vrc2_prg[address] != data)
{
vrc2_prg[address] = data;
NES_mapper116_MMC3_set_CPU_banks();
}
}
void Mapper116::Mapper116_Poke_Vrc2_9000(uint32 address,uint32 data)
{
//NST_ASSERT( (mode & 0x3) == 0 );
data &= 0x1;
if (vrc2_nmt != data)
{
vrc2_nmt = data;
NES_mapper116_MMC3_set_Nmt();
}
}
void Mapper116::Mapper116_Poke_Vrc2_B000(uint32 address,uint32 data)
{
//NST_ASSERT( (mode & 0x3) == 0 );
data = (data & 0xF) << (address << 1 & 0x4);
address = ((address - 0xB000) >> 11 & 0x6) | (address & 0x1);
if (vrc2_chr[address] != data)
{
vrc2_chr[address] = data;
;//ppu.Update();
NES_mapper116_MMC3_set_PPU_banks();
}
}
void Mapper116::Mapper116_Poke_Mmc3_8000(uint32 address,uint32 data)
{
//NST_ASSERT( (mode & 0x3) == 1 );
if (address & 0x1)
{
address = mmc3_ctrl & 0x7U;
if (address < 2)
data >>= 1;
if (mmc3_banks[address] != data)
{
mmc3_banks[address] = data;
if (address < 6)
{
;//ppu.Update();
NES_mapper116_MMC3_set_PPU_banks();
}
else
{
NES_mapper116_MMC3_set_CPU_banks();
}
}
}
else
{
address = mmc3_ctrl ^ data;
mmc3_ctrl = data;
if (address & 0x40)
NES_mapper116_MMC3_set_CPU_banks();
if (address & (0x80U|0x07U))
{
//ppu.Update();
NES_mapper116_MMC3_set_PPU_banks();
}
}
}
void Mapper116::Mapper116_Poke_Mmc3_A000(uint32 address,uint32 data)
{
//NST_ASSERT( (mode & 0x3) == 1 );
if (!(address & 0x1))
{
if (mmc3_nmt != data)
{
mmc3_nmt = data;
NES_mapper116_MMC3_set_Nmt();
}
}
}
void Mapper116::Mapper116_Poke_Mmc3_C000(uint32 address,uint32 data)
{
//NST_ASSERT( (mode & 0x3) == 1 );
;//irq.Update();
if (address & 0x1)
irq_latch = data;//irq.unit.Reload();
else
irq_counter = data;//irq.unit.SetLatch( data );
}
void Mapper116::Mapper116_Poke_Mmc3_E000(uint32 address,uint32 data)
{
//NST_ASSERT( (mode & 0x3) == 1 );
;//irq.Update();
if (address & 0x1)
irq_enable = 0xFF;//Enable
else
{
irq_counter = irq_latch;
irq_enable = 0;
nes->cpu->ClrIRQ( IRQ_MAPPER );
}
}
void Mapper116::Mapper116_Poke_Mmc1_8000(uint32 address,uint32 data)
{
//NST_ASSERT( (mode & 0x3) == 2 );
if (!(data & 0x80))
{
mmc1_buffer |=
(data & 0x1) << mmc1_shifter++;
if (mmc1_shifter != 5)
return;
mmc1_shifter = 0;
data = mmc1_buffer;
mmc1_buffer = 0;
address = address >> 13 & 0x3;
if (mmc1_regs[address] != data)
{
mmc1_regs[address] = data;
NES_mapper116_MMC3_set_CPU_banks();
NES_mapper116_MMC3_set_Nmt();
NES_mapper116_MMC3_set_PPU_banks();
}
}
else
{
mmc1_buffer = 0;
mmc1_shifter = 0;
if ((mmc1_regs[0] & (0x4U|0x8U)) != (0x4U|0x8U))
{
mmc1_regs[0] |= (0x4U|0x8U);
NES_mapper116_MMC3_set_CPU_banks();
NES_mapper116_MMC3_set_Nmt();
NES_mapper116_MMC3_set_PPU_banks();
}
}
}
void Mapper116::Write( WORD address, BYTE data )
{
switch( address & 0xF000 ) {
case 0x8000:
switch (mode & 0x3)
{
case 0x0: Mapper116_Poke_Vrc2_8000( address, data ); break;
case 0x1: Mapper116_Poke_Mmc3_8000( address, data ); break;
case 0x2: Mapper116_Poke_Mmc1_8000( address, data ); break;
}
break;
case 0x9000:
switch (mode & 0x3)
{
case 0x0: Mapper116_Poke_Vrc2_9000( address, data ); break;
case 0x1: Mapper116_Poke_Mmc3_8000( address, data ); break;
case 0x2: Mapper116_Poke_Mmc1_8000( address, data ); break;
}
break;
case 0xA000:
switch (mode & 0x3)
{
case 0x0: Mapper116_Poke_Vrc2_8000( address, data ); break;
case 0x1: Mapper116_Poke_Mmc3_A000( address, data ); break;
case 0x2: Mapper116_Poke_Mmc1_8000( address, data ); break;
}
break;
case 0xB000:
switch (mode & 0x3)
{
case 0x0: Mapper116_Poke_Vrc2_B000( address, data ); break;
case 0x1: Mapper116_Poke_Mmc3_A000( address, data ); break;
case 0x2: Mapper116_Poke_Mmc1_8000( address, data ); break;
}
break;
case 0xC000:
switch (mode & 0x3)
{
case 0x0: Mapper116_Poke_Vrc2_B000( address, data ); break;
case 0x1: Mapper116_Poke_Mmc3_C000( address, data ); break;
case 0x2: Mapper116_Poke_Mmc1_8000( address, data ); break;
}
break;
case 0xD000:
switch (mode & 0x3)
{
case 0x0: Mapper116_Poke_Vrc2_B000( address, data ); break;
case 0x1: Mapper116_Poke_Mmc3_C000( address, data ); break;
case 0x2: Mapper116_Poke_Mmc1_8000( address, data ); break;
}
break;
case 0xE000:
switch (mode & 0x3)
{
case 0x0: Mapper116_Poke_Vrc2_B000( address, data ); break;
case 0x1: Mapper116_Poke_Mmc3_E000( address, data ); break;
case 0x2: Mapper116_Poke_Mmc1_8000( address, data ); break;
}
break;
case 0xF000:
switch (mode & 0x3)
{
case 0x0: break;
case 0x1: Mapper116_Poke_Mmc3_E000( address, data ); break;
case 0x2: Mapper116_Poke_Mmc1_8000( address, data ); break;
}
break;
}
}
void Mapper116::HSync( INT scanline )
{
if( (scanline >= 0 && scanline <= 239) ) {
if( irq_counter <= 0 ) {
if( irq_enable ) {
nes->cpu->SetIRQ( IRQ_MAPPER );
return;
}
}
if(nes->ppu->IsDispON() ) {
irq_counter--;
}
}
}
void Mapper116::SaveState( LPBYTE p )
{
}
void Mapper116::LoadState( LPBYTE p )
{
}