329 lines
6.6 KiB
C++
329 lines
6.6 KiB
C++
|
#include "nes_mapper.h"
|
|||
|
|
|||
|
uint32 chr_swap() { return MAPx->regs[0] & 0x80; }
|
|||
|
uint32 prg_swap() { return MAPx->regs[0] & 0x40; }
|
|||
|
void MAP4_MMC3_set_CPU_banks(void);
|
|||
|
void MAP4_MMC3_set_PPU_banks(void);
|
|||
|
|
|||
|
// Mapper 4
|
|||
|
// much of this is based on the DarcNES source. thanks, nyef :)
|
|||
|
void MAP4_Reset()
|
|||
|
{
|
|||
|
int i;
|
|||
|
// clear registers FIRST!!!
|
|||
|
for( i = 0; i < 8; i++) MAPx->regs[i] = 0x00;
|
|||
|
// set CPU bank pointers
|
|||
|
MAPx->prg0 = 0;
|
|||
|
MAPx->prg1 = 1;
|
|||
|
// MAP4_MMC3_set_CPU_banks();
|
|||
|
|
|||
|
// set VROM banks
|
|||
|
if(num_1k_VROM_banks)
|
|||
|
{
|
|||
|
MAPx->chr01 = 0;
|
|||
|
MAPx->chr23 = 2;
|
|||
|
MAPx->chr4 = 4;
|
|||
|
MAPx->chr5 = 5;
|
|||
|
MAPx->chr6 = 6;
|
|||
|
MAPx->chr7 = 7;
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
MAPx->chr01 = MAPx->chr23 = MAPx->chr4 = MAPx->chr5 = MAPx->chr6 = MAPx->chr7 = 0;
|
|||
|
}
|
|||
|
MAPx->irq_enabled = 0;
|
|||
|
MAPx->irq_counter = 0;
|
|||
|
MAPx->irq_latch = 0;
|
|||
|
}
|
|||
|
|
|||
|
void MAP4_MemoryWrite(uint16 addr, uint8 data)
|
|||
|
{
|
|||
|
switch(addr & 0xE001)
|
|||
|
{
|
|||
|
case 0x8000:
|
|||
|
{
|
|||
|
/*
|
|||
|
MAPx->regs[0] = data;
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
MAP4_MMC3_set_CPU_banks();
|
|||
|
*/
|
|||
|
uint8 old = MAPx->regs[0];
|
|||
|
MAPx->regs[0] = data;
|
|||
|
|
|||
|
if ((old & 0x40) != (data & 0x40)) {
|
|||
|
MAP4_MMC3_set_CPU_banks();
|
|||
|
}
|
|||
|
if ((old & 0x80) != (data & 0x80)) {
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x8001:
|
|||
|
{
|
|||
|
uint32 bank_num;
|
|||
|
|
|||
|
MAPx->regs[1] = data;
|
|||
|
bank_num = MAPx->regs[1];
|
|||
|
|
|||
|
switch(MAPx->regs[0] & 0x07)
|
|||
|
{
|
|||
|
case 0x00:
|
|||
|
{
|
|||
|
if(num_1k_VROM_banks)
|
|||
|
{
|
|||
|
bank_num &= 0xfe;
|
|||
|
if (MAPx->chr01 != bank_num) {
|
|||
|
MAPx->chr01 = bank_num;
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x01:
|
|||
|
{
|
|||
|
if(num_1k_VROM_banks)
|
|||
|
{
|
|||
|
bank_num &= 0xfe;
|
|||
|
if (MAPx->chr23 != bank_num) {
|
|||
|
MAPx->chr23 = bank_num;
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x02:
|
|||
|
{
|
|||
|
if(num_1k_VROM_banks)
|
|||
|
{
|
|||
|
if (MAPx->chr4 != bank_num) {
|
|||
|
MAPx->chr4 = bank_num;
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x03:
|
|||
|
{
|
|||
|
if(num_1k_VROM_banks)
|
|||
|
{
|
|||
|
if (MAPx->chr5 != bank_num) {
|
|||
|
MAPx->chr5 = bank_num;
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x04:
|
|||
|
{
|
|||
|
if(num_1k_VROM_banks)
|
|||
|
{
|
|||
|
if (MAPx->chr6 != bank_num) {
|
|||
|
MAPx->chr6 = bank_num;
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x05:
|
|||
|
{
|
|||
|
if(num_1k_VROM_banks)
|
|||
|
{
|
|||
|
if (MAPx->chr7 != bank_num) {
|
|||
|
MAPx->chr7 = bank_num;
|
|||
|
MAP4_MMC3_set_PPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x06:
|
|||
|
{
|
|||
|
if (MAPx->prg0 != bank_num) {
|
|||
|
MAPx->prg0 = bank_num;
|
|||
|
MAP4_MMC3_set_CPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0x07:
|
|||
|
{
|
|||
|
if (MAPx->prg1 != bank_num) {
|
|||
|
MAPx->prg1 = bank_num;
|
|||
|
MAP4_MMC3_set_CPU_banks();
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0xA000:
|
|||
|
{
|
|||
|
MAPx->regs[2] = data;
|
|||
|
|
|||
|
if(data & 0x40)
|
|||
|
{
|
|||
|
//LOG("MAPx MIRRORING: 0x40 ???" << endl);
|
|||
|
}
|
|||
|
|
|||
|
//if(parent_NES->ROM->get_mirroring() != NES_PPU::MIRROR_FOUR_SCREEN)
|
|||
|
if ( !(RomHeader->flags_1&0x8 ))
|
|||
|
{
|
|||
|
if(data & 0x01)
|
|||
|
{
|
|||
|
set_mirroring(0,0,1,1);//ˮƽ<CBAE><C6BD><EFBFBD><EFBFBD>
|
|||
|
//set_mirroring(NES_PPU::MIRROR_HORIZ);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
set_mirroring(0,1,0,1);//<2F><>ֱ<EFBFBD><D6B1><EFBFBD><EFBFBD>
|
|||
|
//set_mirroring(NES_PPU::MIRROR_VERT);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0xA001:
|
|||
|
{
|
|||
|
MAPx->regs[3] = data;
|
|||
|
|
|||
|
if(data & 0x80)
|
|||
|
{
|
|||
|
// enable save RAM $6000-$7FFF
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// disable save RAM $6000-$7FFF
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 0xC000:
|
|||
|
MAPx->regs[4] = data;
|
|||
|
MAPx->irq_counter = MAPx->regs[4];
|
|||
|
break;
|
|||
|
|
|||
|
case 0xC001:
|
|||
|
MAPx->regs[5] = data;
|
|||
|
MAPx->irq_latch = MAPx->regs[5];
|
|||
|
break;
|
|||
|
|
|||
|
case 0xE000:
|
|||
|
MAPx->regs[6] = data;
|
|||
|
MAPx->irq_enabled = 0;
|
|||
|
break;
|
|||
|
|
|||
|
case 0xE001:
|
|||
|
MAPx->regs[7] = data;
|
|||
|
MAPx->irq_enabled = 1;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
//LOG("MAPx: UNKNOWN: " << HEX(addr,4) << " = " << HEX(data) << endl);
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void MAP4_HSync(int scanline)
|
|||
|
{
|
|||
|
if(MAPx->irq_enabled)
|
|||
|
{
|
|||
|
if((scanline >= 0) && (scanline <= 239)&&( spr_enabled() || bg_enabled()))
|
|||
|
{
|
|||
|
//if(parent_NES->ppu->spr_enabled() || parent_NES->ppu->bg_enabled())
|
|||
|
{
|
|||
|
// if(patch == 1)
|
|||
|
// {
|
|||
|
// if(!(--MAPx->irq_counter))
|
|||
|
// {
|
|||
|
// MAPx->irq_counter = MAPx->irq_latch;
|
|||
|
// parent_NES->cpu->DoIRQ();
|
|||
|
// }
|
|||
|
// }
|
|||
|
// else if(patch == 2)
|
|||
|
// {
|
|||
|
// if(--MAPx->irq_counter == 0x01)
|
|||
|
// {
|
|||
|
// MAPx->irq_counter = MAPx->irq_latch;
|
|||
|
// parent_NES->cpu->DoIRQ();
|
|||
|
// }
|
|||
|
// }
|
|||
|
// else
|
|||
|
{
|
|||
|
if(!(MAPx->irq_counter--))
|
|||
|
{
|
|||
|
MAPx->irq_counter = MAPx->irq_latch;
|
|||
|
CPU_IRQ;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void MAP4_MMC3_set_CPU_banks()
|
|||
|
{
|
|||
|
if(prg_swap())
|
|||
|
{
|
|||
|
set_CPU_banks(-2,MAPx->prg1,MAPx->prg0,-1);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
set_CPU_banks(MAPx->prg0,MAPx->prg1,-2,-1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void MAP4_MMC3_set_PPU_banks()
|
|||
|
{
|
|||
|
if(num_1k_VROM_banks)
|
|||
|
{
|
|||
|
if(chr_swap())
|
|||
|
{
|
|||
|
set_PPU_banks(MAPx->chr4,MAPx->chr5,MAPx->chr6,MAPx->chr7,MAPx->chr01,MAPx->chr01+1,MAPx->chr23,MAPx->chr23+1);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
set_PPU_banks(MAPx->chr01,MAPx->chr01+1,MAPx->chr23,MAPx->chr23+1,MAPx->chr4,MAPx->chr5,MAPx->chr6,MAPx->chr7);
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
if(chr_swap())
|
|||
|
{
|
|||
|
set_VRAM_bank(0, MAPx->chr4);
|
|||
|
set_VRAM_bank(1, MAPx->chr5);
|
|||
|
set_VRAM_bank(2, MAPx->chr6);
|
|||
|
set_VRAM_bank(3, MAPx->chr7);
|
|||
|
set_VRAM_bank(4, MAPx->chr01+0);
|
|||
|
set_VRAM_bank(5, MAPx->chr01+1);
|
|||
|
set_VRAM_bank(6, MAPx->chr23+0);
|
|||
|
set_VRAM_bank(7, MAPx->chr23+1);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
set_VRAM_bank(0, MAPx->chr01+0);
|
|||
|
set_VRAM_bank(1, MAPx->chr01+1);
|
|||
|
set_VRAM_bank(2, MAPx->chr23+0);
|
|||
|
set_VRAM_bank(3, MAPx->chr23+1);
|
|||
|
set_VRAM_bank(4, MAPx->chr4);
|
|||
|
set_VRAM_bank(5, MAPx->chr5);
|
|||
|
set_VRAM_bank(6, MAPx->chr6);
|
|||
|
set_VRAM_bank(7, MAPx->chr7);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void MAP4_Init()
|
|||
|
{
|
|||
|
NES_Mapper->Reset = MAP4_Reset;
|
|||
|
NES_Mapper->Write = MAP4_MemoryWrite;
|
|||
|
NES_Mapper->HSync = MAP4_HSync;
|
|||
|
}
|