📄 004.cpp
字号:
/////////////////////////////////////////////////////////////////////
// Mapper 4
// much of this is based on the DarcNES source. thanks, nyef :)
void NES_mapper4::Reset()
{
patch = 0;
if(parent_NES->crc32() == 0xdebea5a6 || // Ninja Ryukenden 2 - Ankoku no Jashin Ken
parent_NES->crc32() == 0xc5fea9f2) // Dai2Ji - Super Robot Taisen
{
patch = 1;
}
if(parent_NES->crc32() == 0xd7a97b38) // Chou Jinrou Senki - Warwolf
{
patch = 2;
}
if(parent_NES->crc32() == 0xeb2dba63) // VS TKO Boxing
{
patch = 3;
vs_index = 0;
}
if(parent_NES->crc32() == 0x135adf7c) // VS Atari RBI Baseball
{
patch = 4;
vs_index = 0;
}
// clear registers FIRST!!!
for(int i = 0; i < 8; i++) regs[i] = 0x00;
// set CPU bank pointers
prg0 = 0;
prg1 = 1;
MMC3_set_CPU_banks();
// For Tun Shi Tian Di 2(Chinese hack of "Destiny of an Emperor 2(j)")
// This game will copy some codes to the wram and jmp to there
// Rick
parent_NES->cpu->Set_CPU_bank(2, wram);
// set VROM banks
if(num_1k_VROM_banks)
{
chr01 = 0;
chr23 = 2;
chr4 = 4;
chr5 = 5;
chr6 = 6;
chr7 = 7;
MMC3_set_PPU_banks();
}
else
{
chr01 = chr23 = chr4 = chr5 = chr6 = chr7 = 0;
}
irq_enabled = 0;
irq_counter = 0;
irq_latch = 0;
}
// For Tun Shi Tian Di 2(Chinese hack of "Destiny of an Emperor 2(j)")
// Rick
void NES_mapper4::MemoryWriteLow(uint32 addr, uint8 data)
{
if (addr < 0x6000) {
wram[addr - 0x4000] = data;
}
}
uint8 NES_mapper4::MemoryReadLow(uint32 addr)
{
if(patch == 3)
{
// VS TKO Boxing security
if(addr == 0x5E00)
{
vs_index = 0;
return 0x00;
}
else if(addr == 0x5E01)
{
uint8 security_data[32] =
{
0xff, 0xbf, 0xb7, 0x97, 0x97, 0x17, 0x57, 0x4f,
0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90, 0x94, 0x14,
0x56, 0x4e, 0x6f, 0x6b, 0xeb, 0xa9, 0xb1, 0x90,
0xd4, 0x5c, 0x3e, 0x26, 0x87, 0x83, 0x13, 0x00
};
return security_data[(vs_index++) & 0x1F];
}
}
else if(patch == 4)
{
// VS Atari RBI Baseball security
if(addr == 0x5E00)
{
vs_index = 0;
return 0xFF;
}
else if(addr == 0x5E01)
{
switch(vs_index++)
{
case 0x09:
return 0x6F;
default:
return 0xB4;
}
}
} else {
// For Tun Shi Tian Di 2(Chinese hack of "Destiny of an Emperor 2(j)")
// Rick
if (addr < 0x6000) {
return wram[addr - 0x4000];
}
}
return (uint8)(addr >> 8);
}
void NES_mapper4::MemoryWrite(uint32 addr, uint8 data)
{
switch(addr & 0xE001)
{
case 0x8000:
{
/*
regs[0] = data;
MMC3_set_PPU_banks();
MMC3_set_CPU_banks();
*/
uint8 old = regs[0];
regs[0] = data;
if ((old & 0x40) != (data & 0x40)) {
MMC3_set_CPU_banks();
}
if ((old & 0x80) != (data & 0x80)) {
MMC3_set_PPU_banks();
}
}
break;
case 0x8001:
{
uint32 bank_num;
regs[1] = data;
bank_num = regs[1];
switch(regs[0] & 0x07)
{
case 0x00:
{
//if(num_1k_VROM_banks)
{
bank_num &= 0xfe;
if (chr01 != bank_num) {
chr01 = bank_num;
MMC3_set_PPU_banks();
}
}
}
break;
case 0x01:
{
//if(num_1k_VROM_banks)
{
bank_num &= 0xfe;
if (chr23 != bank_num) {
chr23 = bank_num;
MMC3_set_PPU_banks();
}
}
}
break;
case 0x02:
{
//if(num_1k_VROM_banks)
{
if (chr4 != bank_num) {
chr4 = bank_num;
MMC3_set_PPU_banks();
}
}
}
break;
case 0x03:
{
//if(num_1k_VROM_banks)
{
if (chr5 != bank_num) {
chr5 = bank_num;
MMC3_set_PPU_banks();
}
}
}
break;
case 0x04:
{
//if(num_1k_VROM_banks)
{
if (chr6 != bank_num) {
chr6 = bank_num;
MMC3_set_PPU_banks();
}
}
}
break;
case 0x05:
{
//if(num_1k_VROM_banks)
{
if (chr7 != bank_num) {
chr7 = bank_num;
MMC3_set_PPU_banks();
}
}
}
break;
case 0x06:
{
if (prg0 != bank_num) {
// For Tun Shi Tian Di 2(Chinese hack of "Destiny of an Emperor 2(j)")
// Rick
if (bank_num > 0x4f)
bank_num &= 0x4f;
prg0 = bank_num;
MMC3_set_CPU_banks();
}
}
break;
case 0x07:
{
if (prg1 != bank_num) {
prg1 = bank_num;
MMC3_set_CPU_banks();
}
}
break;
}
}
break;
case 0xA000:
{
regs[2] = data;
if(data & 0x40)
{
LOG("MAP4 MIRRORING: 0x40 ???" << endl);
}
if(parent_NES->ROM->get_mirroring() != NES_PPU::MIRROR_FOUR_SCREEN)
{
if(data & 0x01)
{
set_mirroring(NES_PPU::MIRROR_HORIZ);
}
else
{
set_mirroring(NES_PPU::MIRROR_VERT);
}
}
}
break;
case 0xA001:
{
regs[3] = data;
if(data & 0x80)
{
// enable save RAM $6000-$7FFF
}
else
{
// disable save RAM $6000-$7FFF
}
}
break;
case 0xC000:
regs[4] = data;
irq_counter = regs[4];
break;
case 0xC001:
regs[5] = data;
irq_latch = regs[5];
break;
case 0xE000:
regs[6] = data;
irq_enabled = 0;
break;
case 0xE001:
regs[7] = data;
irq_enabled = 1;
break;
default:
LOG("MAP4: UNKNOWN: " << HEX(addr,4) << " = " << HEX(data) << endl);
break;
}
}
void NES_mapper4::HSync(uint32 scanline)
{
if(irq_enabled)
{
if((scanline >= 0) && (scanline <= 239))
{
if(parent_NES->ppu->spr_enabled() || parent_NES->ppu->bg_enabled())
{
if(patch == 1)
{
if(!(--irq_counter))
{
irq_counter = irq_latch;
parent_NES->cpu->DoIRQ();
}
}
else if(patch == 2)
{
if(--irq_counter == 0x01)
{
irq_counter = irq_latch;
parent_NES->cpu->DoIRQ();
}
}
else
{
if(!(irq_counter--))
{
irq_counter = irq_latch;
parent_NES->cpu->DoIRQ();
}
}
}
}
}
}
void NES_mapper4::MMC3_set_CPU_banks()
{
if(prg_swap())
{
set_CPU_banks(num_8k_ROM_banks-2,prg1,prg0,num_8k_ROM_banks-1);
}
else
{
set_CPU_banks(prg0,prg1,num_8k_ROM_banks-2,num_8k_ROM_banks-1);
}
}
void NES_mapper4::MMC3_set_PPU_banks()
{
if(num_1k_VROM_banks)
{
if(chr_swap())
{
set_PPU_banks(chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1);
}
else
{
set_PPU_banks(chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7);
}
}
else
{
if(chr_swap())
{
set_VRAM_bank(0, chr4);
set_VRAM_bank(1, chr5);
set_VRAM_bank(2, chr6);
set_VRAM_bank(3, chr7);
set_VRAM_bank(4, chr01+0);
set_VRAM_bank(5, chr01+1);
set_VRAM_bank(6, chr23+0);
set_VRAM_bank(7, chr23+1);
}
else
{
set_VRAM_bank(0, chr01+0);
set_VRAM_bank(1, chr01+1);
set_VRAM_bank(2, chr23+0);
set_VRAM_bank(3, chr23+1);
set_VRAM_bank(4, chr4);
set_VRAM_bank(5, chr5);
set_VRAM_bank(6, chr6);
set_VRAM_bank(7, chr7);
}
}
}
#define MAP4_ROM(ptr) (((ptr)-parent_NES->ROM->get_ROM_banks()) >> 13)
#define MAP4_VROM(ptr) (((ptr)-parent_NES->ROM->get_VROM_banks()) >> 10)
#define MAP4_VRAM(ptr) (((ptr)-parent_NES->ppu->get_patt()) >> 10)
void NES_mapper4::SNSS_fixup() // HACK HACK HACK HACK
{
NES_6502::Context context;
parent_NES->cpu->GetContext(&context);
prg0 = MAP4_ROM(context.mem_page[prg_swap() ? 6 : 4]);
prg1 = MAP4_ROM(context.mem_page[5]);
if(num_1k_VROM_banks)
{
if(chr_swap())
{
chr01 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[4]);
chr23 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[6]);
chr4 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[0]);
chr5 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[1]);
chr6 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[2]);
chr7 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[3]);
}
else
{
chr01 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[0]);
chr23 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[2]);
chr4 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[4]);
chr5 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[5]);
chr6 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[6]);
chr7 = MAP4_VROM(parent_NES->ppu->PPU_VRAM_banks[7]);
}
}
else
{
if(chr_swap())
{
chr01 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[4]);
chr23 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[6]);
chr4 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[0]);
chr5 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[1]);
chr6 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[2]);
chr7 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[3]);
}
else
{
chr01 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[0]);
chr23 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[2]);
chr4 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[4]);
chr5 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[5]);
chr6 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[6]);
chr7 = MAP4_VRAM(parent_NES->ppu->PPU_VRAM_banks[7]);
}
}
}
/////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -