⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mapper005.cpp

📁 著名的任天堂FC游戏机模拟器VirtuaNes 085版的源码!
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////////
// Mapper005  Nintendo MMC5                                             //
//////////////////////////////////////////////////////////////////////////
#define	MMC5_IRQ_METAL		(1<<0)

void	Mapper005::Reset()
{
INT	i;

	prg_size = 3;
	chr_size = 3;

	sram_we_a = 0x00;
	sram_we_b = 0x00;

	graphic_mode = 0;
	nametable_mode = 0;

	for( i = 0; i < 4; i++ ) {
		nametable_type[i] = 0;
	}

	fill_chr = fill_pal = 0;
	split_control = split_scroll = split_page = 0;

	irq_enable = 0;
	irq_status = 0;
	irq_scanline = 0;
	irq_line = 0;
	irq_clear = 0;

	irq_type = 0;

	mult_a = mult_b = 0;

	chr_type = 0;
	chr_mode = 0;
	for( i = 0; i < 8; i++ ) {
		chr_page[0][i] = i;
		chr_page[1][i] = 4+(i&0x03);
	}

	SetPROM_32K_Bank( PROM_8K_SIZE-1, PROM_8K_SIZE-1, PROM_8K_SIZE-1, PROM_8K_SIZE-1 );
	SetVROM_8K_Bank( 0 );

	for( i = 0; i < 8; i++ ) {
		BG_MEM_BANK[i] = VROM+0x0400*i;
		BG_MEM_PAGE[i] = i;
	}

	// SRAM愝掕
	SetBank_SRAM( 3, 0 );

	sram_size = 0;
	nes->SetSAVERAM_SIZE( 16*1024 );

	DWORD	crc = nes->rom->GetPROM_CRC();

	if( crc == 0x2b548d75	// Bandit Kings of Ancient China(U)
	 || crc == 0xf4cd4998	// Dai Koukai Jidai(J)
	 || crc == 0x8fa95456	// Ishin no Arashi(J)
	 || crc == 0x98c8e090	// Nobunaga no Yabou - Sengoku Gunyuu Den(J)
	 || crc == 0x8e9a5e2f	// L'Empereur(Alt)(U)
	 || crc == 0x57e3218b	// L'Empereur(U)
	 || crc == 0x2f50bd38	// L'Empereur(J)
	 || crc == 0xb56958d1	// Nobunaga's Ambition 2(U)
	 || crc == 0xe6c28c5f	// Suikoden - Tenmei no Chikai(J)
	 || crc == 0xcd35e2e9 ) {	// Uncharted Waters(U)
		sram_size = 1;
		nes->SetSAVERAM_SIZE( 32*1024 );
	} else
	if( crc == 0xf4120e58	// Aoki Ookami to Shiroki Mejika - Genchou Hishi(J)
	 || crc == 0x286613d8	// Nobunaga no Yabou - Bushou Fuuun Roku(J)
	 || crc == 0x11eaad26	// Romance of the Three Kingdoms 2(U)
	 || crc == 0x95ba5733 ) {	// Sangokushi 2(J)
		sram_size = 2;
		nes->SetSAVERAM_SIZE( 64*1024 );
	}

	if( crc == 0x95ca9ec7 ) { // Castlevania 3 - Dracula's Curse(U)
		nes->SetRenderMethod( NES::TILE_RENDER );
	}

	if( crc == 0xcd9acf43 ) { // Metal Slader Glory(J)
		irq_type = MMC5_IRQ_METAL;
	}

	if( crc == 0xe91548d8 ) { // Shin 4 Nin Uchi Mahjong - Yakuman Tengoku(J)
		chr_type = 1;
	}

	nes->ppu->SetExtLatchMode( TRUE );
	nes->apu->SelectExSound( 8 );
}

BYTE	Mapper005::ReadLow( WORD addr )
{
BYTE	data = (BYTE)(addr>>8);

	switch( addr ) {
		case	0x5015:
			data = nes->apu->ExRead( addr );
			break;

		case	0x5204:
			data = irq_status;
//			irq_status = 0;
			irq_status &= ~0x80;

			nes->cpu->ClrIRQ( IRQ_MAPPER );
			break;
		case	0x5205:
			data = mult_a*mult_b;
			break;
		case	0x5206:
			data = (BYTE)(((WORD)mult_a*(WORD)mult_b)>>8);
			break;
	}

	if( addr >= 0x5C00 && addr <= 0x5FFF ) {
		if( graphic_mode >= 2 ) { // ExRAM mode
			data = VRAM[0x0800+(addr&0x3FF)];
		}
	} else if( addr >= 0x6000 && addr <= 0x7FFF ) {
		data = Mapper::ReadLow( addr );
	}

	return	data;
}

void	Mapper005::WriteLow( WORD addr, BYTE data )
{
INT	i;

#if	0
if( addr >= 0x5000 && addr <=0x5100 ) {
DEBUGOUT( "$%04X=%02X C:%10d\n", addr, data, nes->cpu->GetTotalCycles() );
}
#endif

	switch( addr ) {
		case	0x5100:
			prg_size = data & 0x03;
			break;
		case	0x5101:
			chr_size = data & 0x03;
			break;

		case	0x5102:
			sram_we_a = data & 0x03;
			break;
		case	0x5103:
			sram_we_b = data & 0x03;
			break;

		case	0x5104:
			graphic_mode = data & 0x03;
			break;
		case	0x5105:
			nametable_mode = data;
			for( i = 0; i < 4; i++ ) {
				nametable_type[i] = data&0x03;
				SetVRAM_1K_Bank( 8+i, nametable_type[i] );
				data >>= 2;
			}
			break;

		case	0x5106:
			fill_chr = data;
			break;
		case	0x5107:
			fill_pal = data & 0x03;
			break;

		case	0x5113:
			SetBank_SRAM( 3, data&0x07 );
			break;

		case	0x5114:
		case	0x5115:
		case	0x5116:
		case	0x5117:
			SetBank_CPU( addr, data );
			break;

		case	0x5120:
		case	0x5121:
		case	0x5122:
		case	0x5123:
		case	0x5124:
		case	0x5125:
		case	0x5126:
		case	0x5127:
			chr_mode = 0;
			chr_page[0][addr&0x07] = data;
			SetBank_PPU();
			break;

		case	0x5128:
		case	0x5129:
		case	0x512A:
		case	0x512B:
			chr_mode = 1;
			chr_page[1][(addr&0x03)+0] = data;
			chr_page[1][(addr&0x03)+4] = data;
			SetBank_PPU();
			break;

		case	0x5200:
			split_control = data;
			break;
		case	0x5201:
			split_scroll = data;
			break;
		case	0x5202:
			split_page = data&0x3F;
			break;

		case	0x5203:
			irq_line = data;

			nes->cpu->ClrIRQ( IRQ_MAPPER );
			break;
		case	0x5204:
			irq_enable = data;

			nes->cpu->ClrIRQ( IRQ_MAPPER );
			break;

		case	0x5205:
			mult_a = data;
			break;
		case	0x5206:
			mult_b = data;
			break;

		default:
			if( addr >= 0x5000 && addr <= 0x5015 ) {
				nes->apu->ExWrite( addr, data );
			} else if( addr >= 0x5C00 && addr <= 0x5FFF ) {
				if( graphic_mode == 2 ) {		// ExRAM
					VRAM[0x0800+(addr&0x3FF)] = data;
				} else if( graphic_mode != 3 ) {	// Split,ExGraphic
					if( irq_status&0x40 ) {
						VRAM[0x0800+(addr&0x3FF)] = data;
					} else {
						VRAM[0x0800+(addr&0x3FF)] = 0;
					}
				}
			} else if( addr >= 0x6000 && addr <= 0x7FFF ) {
				if( sram_we_a == 0x02 && sram_we_b == 0x01 ) {
					if( CPU_MEM_TYPE[3] == BANKTYPE_RAM ) {
						CPU_MEM_BANK[3][addr&0x1FFF] = data;
					}
				}
			}
			break;
	}
}

void	Mapper005::Write( WORD addr, BYTE data )
{
	if( sram_we_a == 0x02 && sram_we_b == 0x01 ) {
		if( addr >= 0x8000 && addr < 0xE000 ) {
			if( CPU_MEM_TYPE[addr>>13] == BANKTYPE_RAM ) {
				CPU_MEM_BANK[addr>>13][addr&0x1FFF] = data;
			}
		}
	}
}

void	Mapper005::SetBank_CPU( WORD addr, BYTE data )
{
	if( data & 0x80 ) {
	// PROM Bank
		switch( addr & 7 ) {
			case	4:
				if( prg_size == 3 ) {
					SetPROM_8K_Bank( 4, data&0x7F );
				}
				break;
			case	5:
				if( prg_size == 1 || prg_size == 2 ) {
					SetPROM_16K_Bank( 4, (data&0x7F)>>1 );
				} else if( prg_size == 3 ) {
					SetPROM_8K_Bank( 5, (data&0x7F) );
				}
				break;
			case	6:
				if( prg_size == 2 || prg_size == 3 ) {
					SetPROM_8K_Bank( 6, (data&0x7F) );
				}
				break;
			case	7:
				if( prg_size == 0 ) {
					SetPROM_32K_Bank( (data&0x7F)>>2 );
				} else if( prg_size == 1 ) {
					SetPROM_16K_Bank( 6, (data&0x7F)>>1 );
				} else if( prg_size == 2 || prg_size == 3 ) {
					SetPROM_8K_Bank( 7, (data&0x7F) );
				}
				break;
		}
	} else {
	// WRAM Bank
		switch( addr & 7 ) {
			case	4:
				if( prg_size == 3 ) {
					SetBank_SRAM( 4, data&0x07 );
				}
				break;
			case	5:
				if( prg_size == 1 || prg_size == 2 ) {
					SetBank_SRAM( 4, (data&0x06)+0 );
					SetBank_SRAM( 5, (data&0x06)+1 );
				} else if( prg_size == 3 ) {
					SetBank_SRAM( 5, data&0x07 );
				}
				break;
			case	6:
				if( prg_size == 2 || prg_size == 3 ) {
					SetBank_SRAM( 6, data&0x07 );
				}
				break;
		}
	}
}

void	Mapper005::SetBank_SRAM( BYTE page, BYTE data )
{
	if( sram_size == 0 ) data = (data > 3) ? 8 : 0;
	if( sram_size == 1 ) data = (data > 3) ? 1 : 0;
	if( sram_size == 2 ) data = (data > 3) ? 8 : data;
	if( sram_size == 3 ) data = (data > 3) ? 4 : data;

	if( data != 8 ) {
		SetPROM_Bank( page, &WRAM[0x2000*data], BANKTYPE_RAM );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -