302 lines
14 KiB
C++
302 lines
14 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
||
// Mapper001 Nintendo MMC1 //
|
||
//////////////////////////////////////////////////////////////////////////
|
||
void Mapper001::Reset()
|
||
{
|
||
reg[0] = 0x0C; // D3=1,D2=1
|
||
reg[1] = reg[2] = reg[3] = 0;
|
||
shift = regbuf = 0;
|
||
|
||
patch = 0;
|
||
wram_patch = 0;
|
||
|
||
if( PROM_16K_SIZE < 32 ) {
|
||
SetPROM_32K_Bank( 0, 1, PROM_8K_SIZE-2, PROM_8K_SIZE-1 );
|
||
} else {
|
||
// For 512K/1M byte Cartridge
|
||
SetPROM_16K_Bank( 4, 0 );
|
||
SetPROM_16K_Bank( 6, 16-1 );
|
||
|
||
patch = 1;
|
||
}
|
||
|
||
if( VROM_8K_SIZE ) {
|
||
// SetVROM_8K_Bank( 0 );
|
||
}
|
||
|
||
DWORD crc = nes->rom->GetPROM_CRC();
|
||
|
||
if( crc == 0xb8e16bd0 ) { // Snow Bros.(J)
|
||
patch = 2;
|
||
}
|
||
// if( crc == 0x9b565541 ) { // Triathron, The(J)
|
||
// nes->SetFrameIRQmode( FALSE );
|
||
// }
|
||
if( crc == 0xc96c6f04 ) { // Venus Senki(J)
|
||
nes->SetRenderMethod( NES::POST_ALL_RENDER );
|
||
}
|
||
// if( crc == 0x5e3f7004 ) { // Softball Tengoku(J)
|
||
// }
|
||
|
||
if( crc == 0x4d2edf70 ) { // Night Rider(J)
|
||
nes->SetRenderMethod( NES::TILE_RENDER );
|
||
}
|
||
if( crc == 0xcd2a73f0 ) { // Pirates!(U)
|
||
nes->SetRenderMethod( NES::TILE_RENDER );
|
||
patch = 2;
|
||
}
|
||
|
||
// if( crc == 0x09efe54b ) { // Majaventure - Mahjong Senki(J)
|
||
// nes->SetFrameIRQmode( FALSE );
|
||
// }
|
||
|
||
if( crc == 0x11469ce3 ) { // Viva! Las Vegas(J)
|
||
}
|
||
if( crc == 0xd878ebf5 ) { // Ninja Ryukenden(J)
|
||
nes->SetRenderMethod( NES::POST_ALL_RENDER );
|
||
}
|
||
|
||
// if( crc == 0x7bd7b849 ) { // Nekketsu Koukou - Dodgeball Bu(J)
|
||
// }
|
||
|
||
if( crc == 0x466efdc2 ) { // Final Fantasy(J)
|
||
nes->SetRenderMethod( NES::TILE_RENDER );
|
||
nes->ppu->SetExtMonoMode( TRUE );
|
||
}
|
||
if( crc == 0xc9556b36 ) { // Final Fantasy I&II(J)
|
||
nes->SetRenderMethod( NES::TILE_RENDER );
|
||
nes->ppu->SetExtMonoMode( TRUE );
|
||
nes->SetSAVERAM_SIZE( 16*1024 );
|
||
wram_patch = 2;
|
||
}
|
||
|
||
if( crc == 0x717e1169 ) { // Cosmic Wars(J)
|
||
nes->SetRenderMethod( NES::PRE_ALL_RENDER );
|
||
}
|
||
|
||
if( crc == 0xC05D2034 ) { // Snake's Revenge(U)
|
||
nes->SetRenderMethod( NES::PRE_ALL_RENDER );
|
||
}
|
||
|
||
if( crc == 0xb8747abf // Best Play - Pro Yakyuu Special(J)
|
||
|| crc == 0x29449ba9 // Nobunaga no Yabou - Zenkoku Ban(J)
|
||
|| crc == 0x2b11e0b0 // Nobunaga no Yabou - Zenkoku Ban(J)(alt)
|
||
|| crc == 0x4642dda6 // Nobunaga's Ambition(U)
|
||
|| crc == 0xfb69743a // Aoki Ookami to Shiroki Mejika - Genghis Khan(J)
|
||
|| crc == 0x2225c20f // Genghis Khan(U)
|
||
|| crc == 0xabbf7217 // Sangokushi(J)
|
||
) {
|
||
|
||
nes->SetSAVERAM_SIZE( 16*1024 );
|
||
wram_patch = 1;
|
||
wram_bank = 0;
|
||
wram_count = 0;
|
||
}
|
||
}
|
||
|
||
void Mapper001::Write( WORD addr, BYTE data )
|
||
{
|
||
// DEBUGOUT( "MMC1 %04X=%02X\n", addr&0xFFFF,data&0xFF );
|
||
|
||
if( wram_patch == 1 && addr == 0xBFFF ) {
|
||
wram_count++;
|
||
wram_bank += data&0x01;
|
||
if( wram_count == 5 ) {
|
||
if( wram_bank ) {
|
||
SetPROM_Bank( 3, &WRAM[0x2000], BANKTYPE_RAM );
|
||
} else {
|
||
SetPROM_Bank( 3, &WRAM[0x0000], BANKTYPE_RAM );
|
||
}
|
||
wram_bank = wram_count = 0;
|
||
}
|
||
}
|
||
|
||
if( patch != 1 ) {
|
||
if((addr & 0x6000) != (last_addr & 0x6000)) {
|
||
shift = regbuf = 0;
|
||
}
|
||
last_addr = addr;
|
||
}
|
||
|
||
if( data & 0x80 ) {
|
||
shift = regbuf = 0;
|
||
// reg[0] = 0x0C; // D3=1,D2=1
|
||
reg[0] |= 0x0C; // D3=1,D2=1 残りはリセットされない
|
||
return;
|
||
}
|
||
|
||
if( data&0x01 ) regbuf |= 1<<shift;
|
||
if( ++shift < 5 )
|
||
return;
|
||
addr = (addr&0x7FFF)>>13;
|
||
reg[addr] = regbuf;
|
||
|
||
// DEBUGOUT( "MMC1 %d=%02X\n", addr&0xFFFF,regbuf&0xFF );
|
||
|
||
regbuf = 0;
|
||
shift = 0;
|
||
|
||
if( patch != 1 ) {
|
||
// For Normal Cartridge
|
||
switch( addr ) {
|
||
case 0:
|
||
if( reg[0] & 0x02 ) {
|
||
if( reg[0] & 0x01 ) SetVRAM_Mirror( VRAM_HMIRROR );
|
||
else SetVRAM_Mirror( VRAM_VMIRROR );
|
||
} else {
|
||
if( reg[0] & 0x01 ) SetVRAM_Mirror( VRAM_MIRROR4H );
|
||
else SetVRAM_Mirror( VRAM_MIRROR4L );
|
||
}
|
||
break;
|
||
case 1:
|
||
// Register #1
|
||
if( VROM_1K_SIZE ) {
|
||
if( reg[0] & 0x10 ) {
|
||
// CHR 4K bank lower($0000-$0FFF)
|
||
SetVROM_4K_Bank( 0, reg[1] );
|
||
// CHR 4K bank higher($1000-$1FFF)
|
||
SetVROM_4K_Bank( 4, reg[2] );
|
||
} else {
|
||
// CHR 8K bank($0000-$1FFF)
|
||
SetVROM_8K_Bank( reg[1]>>1 );
|
||
}
|
||
} else {
|
||
// For Romancia
|
||
if( reg[0] & 0x10 ) {
|
||
SetCRAM_4K_Bank( 0, reg[1] );
|
||
}
|
||
}
|
||
break;
|
||
case 2:
|
||
// Register #2
|
||
if( VROM_1K_SIZE ) {
|
||
if( reg[0] & 0x10 ) {
|
||
// CHR 4K bank lower($0000-$0FFF)
|
||
SetVROM_4K_Bank( 0, reg[1] );
|
||
// CHR 4K bank higher($1000-$1FFF)
|
||
SetVROM_4K_Bank( 4, reg[2] );
|
||
} else {
|
||
// CHR 8K bank($0000-$1FFF)
|
||
SetVROM_8K_Bank( reg[1]>>1 );
|
||
}
|
||
} else {
|
||
// For Romancia
|
||
if( reg[0] & 0x10 ) {
|
||
SetCRAM_4K_Bank( 4, reg[2] );
|
||
}
|
||
}
|
||
break;
|
||
case 3:
|
||
if( !(reg[0] & 0x08) ) {
|
||
// PRG 32K bank ($8000-$FFFF)
|
||
SetPROM_32K_Bank( reg[3]>>1 );
|
||
} else {
|
||
if( reg[0] & 0x04 ) {
|
||
// PRG 16K bank ($8000-$BFFF)
|
||
SetPROM_16K_Bank( 4, reg[3] );
|
||
SetPROM_16K_Bank( 6, PROM_16K_SIZE-1 );
|
||
} else {
|
||
// PRG 16K bank ($C000-$FFFF)
|
||
SetPROM_16K_Bank( 6, reg[3] );
|
||
SetPROM_16K_Bank( 4, 0 );
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
} else {
|
||
// For 512K/1M byte Cartridge
|
||
INT PROM_BASE = 0;
|
||
if( PROM_16K_SIZE >= 32 ) {
|
||
PROM_BASE = reg[1] & 0x10;
|
||
}
|
||
|
||
// For FinalFantasy I&II
|
||
if( wram_patch == 2 ) {
|
||
if( !(reg[1] & 0x18) ) {
|
||
SetPROM_Bank( 3, &WRAM[0x0000], BANKTYPE_RAM );
|
||
} else {
|
||
SetPROM_Bank( 3, &WRAM[0x2000], BANKTYPE_RAM );
|
||
}
|
||
}
|
||
|
||
// Register #0
|
||
if( addr == 0 ) {
|
||
if( reg[0] & 0x02 ) {
|
||
if( reg[0] & 0x01 ) SetVRAM_Mirror( VRAM_HMIRROR );
|
||
else SetVRAM_Mirror( VRAM_VMIRROR );
|
||
} else {
|
||
if( reg[0] & 0x01 ) SetVRAM_Mirror( VRAM_MIRROR4H );
|
||
else SetVRAM_Mirror( VRAM_MIRROR4L );
|
||
}
|
||
}
|
||
// Register #1
|
||
if( VROM_1K_SIZE ) {
|
||
if( reg[0] & 0x10 ) {
|
||
// CHR 4K bank lower($0000-$0FFF)
|
||
SetVROM_4K_Bank( 0, reg[1] );
|
||
} else {
|
||
// CHR 8K bank($0000-$1FFF)
|
||
SetVROM_8K_Bank( reg[1]>>1 );
|
||
}
|
||
} else {
|
||
// For Romancia
|
||
if( reg[0] & 0x10 ) {
|
||
SetCRAM_4K_Bank( 0, reg[1] );
|
||
}
|
||
}
|
||
// Register #2
|
||
if( VROM_1K_SIZE ) {
|
||
if( reg[0] & 0x10 ) {
|
||
// CHR 4K bank higher($1000-$1FFF)
|
||
SetVROM_4K_Bank( 4, reg[2] );
|
||
}
|
||
} else {
|
||
// For Romancia
|
||
if( reg[0] & 0x10 ) {
|
||
SetCRAM_4K_Bank( 4, reg[2] );
|
||
}
|
||
}
|
||
// Register #3
|
||
if( !(reg[0] & 0x08) ) {
|
||
// PRG 32K bank ($8000-$FFFF)
|
||
SetPROM_32K_Bank( (reg[3]&(0xF+PROM_BASE))>>1 );
|
||
} else {
|
||
if( reg[0] & 0x04 ) {
|
||
// PRG 16K bank ($8000-$BFFF)
|
||
SetPROM_16K_Bank( 4, PROM_BASE+(reg[3]&0x0F) );
|
||
if( PROM_16K_SIZE >= 32 ) SetPROM_16K_Bank( 6, PROM_BASE+16-1 );
|
||
} else {
|
||
// PRG 16K bank ($C000-$FFFF)
|
||
SetPROM_16K_Bank( 6, PROM_BASE+(reg[3]&0x0F) );
|
||
if( PROM_16K_SIZE >= 32 ) SetPROM_16K_Bank( 4, PROM_BASE );
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
void Mapper001::SaveState( LPBYTE p )
|
||
{
|
||
p[0] = reg[0];
|
||
p[1] = reg[1];
|
||
p[2] = reg[2];
|
||
p[3] = reg[3];
|
||
p[4] = shift;
|
||
p[5] = regbuf;
|
||
|
||
p[6] = wram_bank;
|
||
p[7] = wram_count;
|
||
}
|
||
|
||
void Mapper001::LoadState( LPBYTE p )
|
||
{
|
||
reg[0] = p[0];
|
||
reg[1] = p[1];
|
||
reg[2] = p[2];
|
||
reg[3] = p[3];
|
||
shift = p[4];
|
||
regbuf = p[5];
|
||
|
||
wram_bank = p[6];
|
||
wram_count = p[7];
|
||
}
|