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

📄 nes.cpp

📁 著名的任天堂FC游戏机模拟器VirtuaNes 085版的源码!
💻 CPP
📖 第 1 页 / 共 5 页
字号:
void	NES::EmulationCPU_BeforeNMI( INT cycles )
{
	base_cycles += cycles;
	emul_cycles += cpu->EXEC( cycles/12 );
}

/*
	昤夋僔乕働儞僗
	0		僟儈乕僗僉儍儞儔僀儞(昤夋偟側偄)
	1 - 239		昤夋
	240		僟儈乕僗僉儍儞儔僀儞,VBLANK僼儔僌ON
	241		VINT婜娫,NMI敪惗
	242-261		VINT婜娫
	261		VINT婜娫,VBLANK僼儔僌OFF
*/
void	NES::EmulateFrame( BOOL bDraw )
{
INT	scanline = 0;

	// NSF僾儗僀儎偺帪
	if( rom->IsNSF() ) {
		EmulateNSF();
		return;
	}

	// Cheat
	CheatCodeProcess();
	//
	NES_scanline = scanline;

	if( RenderMethod != TILE_RENDER ) {
		bZapper = FALSE;
		while( TRUE ) {
			ppu->SetRenderScanline( scanline );

			if( scanline == 0 ) {
			// 僟儈乕僗僉儍儞儔僀儞
				if( RenderMethod < POST_RENDER ) {
					EmulationCPU( nescfg->ScanlineCycles );
					ppu->FrameStart();
					ppu->ScanlineNext();
					mapper->HSync( scanline );
					ppu->ScanlineStart();
				} else {
					EmulationCPU( nescfg->HDrawCycles );
					ppu->FrameStart();
					ppu->ScanlineNext();
					mapper->HSync( scanline );
					EmulationCPU( FETCH_CYCLES*32 );
					ppu->ScanlineStart();
					EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
				}
			} else if( scanline < 240 ) {
				if( RenderMethod < POST_RENDER ) {
					if( RenderMethod == POST_ALL_RENDER )
						EmulationCPU( nescfg->ScanlineCycles );
					if( bDraw ) {
						ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
					} else {
						if( pad->IsZapperMode() && scanline == ZapperY ) {
							ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
						} else {
							if( !ppu->IsSprite0( scanline ) ) {
								ppu->DummyScanline( scanline );
							} else {
								ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
							}
						}
					}
					ppu->ScanlineNext();				// 偙傟偺埵抲偱儔僗僞乕宯偼夋柺偑堘偆
					if( RenderMethod == PRE_ALL_RENDER )
						EmulationCPU( nescfg->ScanlineCycles );
//					ppu->ScanlineNext();				// 偙傟偺埵抲偱儔僗僞乕宯偼夋柺偑堘偆
					mapper->HSync( scanline );
					ppu->ScanlineStart();
				} else {
					if( RenderMethod == POST_RENDER )
						EmulationCPU( nescfg->HDrawCycles );
					if( bDraw ) {
						ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
					} else {
						if( pad->IsZapperMode() && scanline == ZapperY ) {
							ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
						} else {
							if( !ppu->IsSprite0( scanline ) ) {
								ppu->DummyScanline( scanline );
							} else {
								ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
							}
						}
					}
					if( RenderMethod == PRE_RENDER )
						EmulationCPU( nescfg->HDrawCycles );
					ppu->ScanlineNext();
					mapper->HSync( scanline );
					EmulationCPU( FETCH_CYCLES*32 );
					ppu->ScanlineStart();
					EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
				}
			} else if( scanline == 240 ) {
				mapper->VSync();
				if( RenderMethod < POST_RENDER ) {
					EmulationCPU( nescfg->ScanlineCycles );
					mapper->HSync( scanline );
				} else {
					EmulationCPU( nescfg->HDrawCycles );
					mapper->HSync( scanline );
					EmulationCPU( nescfg->HBlankCycles );
				}
			} else if( scanline <= nescfg->TotalScanlines-1 ) {
				// VBLANK婜娫
				if( scanline == nescfg->TotalScanlines-1 ) {
					ppu->VBlankEnd();
				}
				if( RenderMethod < POST_RENDER ) {
					if( scanline == 241 ) {
						ppu->VBlankStart();
						if( PPUREG[0] & PPU_VBLANK_BIT ) {
							cpu->NMI();
						}
					}
					EmulationCPU( nescfg->ScanlineCycles );
					mapper->HSync( scanline );
				} else {
					if( scanline == 241 ) {
						ppu->VBlankStart();
						if( PPUREG[0] & PPU_VBLANK_BIT ) {
							cpu->NMI();
						}
					}
					EmulationCPU( nescfg->HDrawCycles );
					mapper->HSync( scanline );
					EmulationCPU( nescfg->HBlankCycles );
				}

				if( scanline == nescfg->TotalScanlines-1 ) {
					break;
				}
			}
			if( pad->IsZapperMode() ) {
				if( scanline == ZapperY )
					bZapper = TRUE;
				else
					bZapper = FALSE;
			}

			scanline++;
			NES_scanline = scanline;
		}
	} else {
		bZapper = FALSE;
		while( TRUE ) {
			ppu->SetRenderScanline( scanline );

			if( scanline == 0 ) {
			// 僟儈乕僗僉儍儞儔僀儞
				// H-Draw (4fetches*32)
				EmulationCPU( FETCH_CYCLES*128 );
				ppu->FrameStart();
				ppu->ScanlineNext();
#if	0
				EmulationCPU( FETCH_CYCLES*16 );
				mapper->HSync( scanline );
				EmulationCPU( FETCH_CYCLES*16 );
#else
				EmulationCPU( FETCH_CYCLES*10 );
				mapper->HSync( scanline );
				EmulationCPU( FETCH_CYCLES*22 );
#endif
				ppu->ScanlineStart();
				EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
			} else if( scanline < 240 ) {
			// 僗僋儕乕儞昤夋(Scanline 1乣239)
				if( bDraw ) {
					ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
					ppu->ScanlineNext();
#if	0
					EmulationCPU( FETCH_CYCLES*16 );
					mapper->HSync( scanline );
					EmulationCPU( FETCH_CYCLES*16 );
#else
					EmulationCPU( FETCH_CYCLES*10 );
					mapper->HSync( scanline );
					EmulationCPU( FETCH_CYCLES*22 );
#endif
					ppu->ScanlineStart();
					EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
				} else {
					if( pad->IsZapperMode() && scanline == ZapperY ) {
						ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
						ppu->ScanlineNext();
#if	0
						EmulationCPU( FETCH_CYCLES*16 );
						mapper->HSync( scanline );
						EmulationCPU( FETCH_CYCLES*16 );
#else
						EmulationCPU( FETCH_CYCLES*10 );
						mapper->HSync( scanline );
						EmulationCPU( FETCH_CYCLES*22 );
#endif
						ppu->ScanlineStart();
						EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
					} else {
						if( !ppu->IsSprite0( scanline ) ) {
							// H-Draw (4fetches*32)
							EmulationCPU( FETCH_CYCLES*128 );
							ppu->DummyScanline( scanline );
							ppu->ScanlineNext();
#if	0
							EmulationCPU( FETCH_CYCLES*16 );
							mapper->HSync( scanline );
							EmulationCPU( FETCH_CYCLES*16 );
#else
							EmulationCPU( FETCH_CYCLES*10 );
							mapper->HSync( scanline );
							EmulationCPU( FETCH_CYCLES*22 );
#endif
							ppu->ScanlineStart();
							EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
						} else {
///////---						EmulationCPU( nescfg->HDrawCycles );
							ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
							ppu->ScanlineNext();
#if	0
							EmulationCPU( FETCH_CYCLES*16 );
							mapper->HSync( scanline );
							EmulationCPU( FETCH_CYCLES*16 );
#else
							EmulationCPU( FETCH_CYCLES*10 );
							mapper->HSync( scanline );
							EmulationCPU( FETCH_CYCLES*22 );
#endif
							ppu->ScanlineStart();
							EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
						}
					}
				}
			} else if( scanline == 240 ) {
			// 僟儈乕僗僉儍儞儔僀儞 (Scanline 240)
				mapper->VSync();

				EmulationCPU( nescfg->HDrawCycles );
				// H-Sync
				mapper->HSync( scanline );

				EmulationCPU( nescfg->HBlankCycles );
			} else if( scanline <= nescfg->TotalScanlines-1 ) {
			// VBLANK婜娫
				if( scanline == nescfg->TotalScanlines-1 ) {
					ppu->VBlankEnd();
				}
				if( scanline == 241 ) {
					ppu->VBlankStart();
					if( PPUREG[0]&PPU_VBLANK_BIT ) {
						cpu->NMI();
					}
				}
				EmulationCPU( nescfg->HDrawCycles );

				// H-Sync
				mapper->HSync( scanline );

				EmulationCPU( nescfg->HBlankCycles );

				if( scanline == nescfg->TotalScanlines-1 ) {
					break;
				}
			}
			if( pad->IsZapperMode() ) {
				if( scanline == ZapperY )
					bZapper = TRUE;
				else
					bZapper = FALSE;
			}

			scanline++;
			NES_scanline = scanline;
		}
	}

	// Movie pad
	if( Config.movie.bPadDisplay && bDraw ) {
		DrawPad();
	}
}

void	NES::EmulateNSF()
{
R6502	reg;

	ppu->Reset();
	mapper->VSync();

//DEBUGOUT( "Frame\n" );

	if( m_bNsfPlaying ) {
		if( m_bNsfInit ) {
			ZEROMEMORY( RAM, sizeof(RAM) );
			if( !(rom->GetNsfHeader()->ExtraChipSelect&0x04) ) {
				ZEROMEMORY( WRAM, 0x2000 );
			}

			apu->Reset();
			apu->Write( 0x4015, 0x1F );
			apu->Write( 0x4017, 0xC0 );
			apu->ExWrite( 0x4080, 0x80 );	// FDS Volume 0
			apu->ExWrite( 0x408A, 0xE8 );	// FDS Envelope Speed

			cpu->GetContext( reg );
			reg.PC = 0x4710;	// Init Address
			reg.A  = (BYTE)m_nNsfSongNo;
			reg.X  = (BYTE)m_nNsfSongMode;
			reg.Y  = 0;
			reg.S  = 0xFF;
			reg.P  = Z_FLAG|R_FLAG|I_FLAG;
			cpu->SetContext( reg );

			// 埨慡懳嶔傪寭偹偰偁偊偰儖乕僾偵(1昩暘)
			for( INT i = 0; i < nescfg->TotalScanlines*60; i++ ) {
				EmulationCPU( nescfg->ScanlineCycles );
				cpu->GetContext( reg );

				// 柍尷儖乕僾偵擖偭偨偙偲傪妋擣偟偨傜敳偗傞
				if( reg.PC == 0x4700 ) {
					break;
				}
			}

			m_bNsfInit = FALSE;
		}

		cpu->GetContext( reg );
		// 柍尷儖乕僾偵擖偭偰偄偨傜嵞愝掕偡傞
		if( reg.PC == 0x4700 ) {
			reg.PC = 0x4720;	// Play Address
			reg.A  = 0;
			reg.S  = 0xFF;
			cpu->SetContext( reg );
		}

		for( INT i = 0; i < nescfg->TotalScanlines; i++ ) {
			EmulationCPU( nescfg->ScanlineCycles );
		}
	} else {
		cpu->GetContext( reg );
		reg.PC = 0x4700;	// 柍尷儖乕僾
		reg.S  = 0xFF;
		cpu->SetContext( reg );

		EmulationCPU( nescfg->ScanlineCycles*nescfg->TotalScanlines );
	}
}

void	NES::SetNsfPlay( INT songno, INT songmode )
{
	m_bNsfPlaying  = TRUE;
	m_bNsfInit     = TRUE;
	m_nNsfSongNo   = songno;
	m_nNsfSongMode = songmode;
}

void	NES::SetNsfStop()
{
	m_bNsfPlaying = FALSE;
	apu->Reset();
}

void	NES::Clock( INT cycles )
{
	Tape( cycles );
	Barcode( cycles );
}

BYTE	NES::Read( WORD addr )
{
	switch( addr>>13 ) {
		case	0x00:	// $0000-$1FFF
			return	RAM[addr&0x07FF];
		case	0x01:	// $2000-$3FFF
			return	ppu->Read( addr&0xE007 );
		case	0x02:	// $4000-$5FFF
			if( addr < 0x4100 ) {
				return	ReadReg( addr );
			} else {
				return	mapper->ReadLow( addr );
			}
			break;
		case	0x03:	// $6000-$7FFF
			return	mapper->ReadLow( addr );
		case	0x04:	// $8000-$9FFF
		case	0x05:	// $A000-$BFFF
		case	0x06:	// $C000-$DFFF
		case	0x07:	// $E000-$FFFF
			return	CPU_MEM_BANK[addr>>13][addr&0x1FFF];
	}

	return	0x00;	// Warning梊杊
}

void	NES::Write( WORD addr, BYTE data )
{
	switch( addr>>13 ) {
		case	0x00:	// $0000-$1FFF
			RAM[addr&0x07FF] = data;
			break;
		case	0x01:	// $2000-$3FFF
			if( !rom->IsNSF() ) {
				ppu->Write( addr&0xE007, data );
			}
			break;
		case	0x02:	// $4000-$5FFF
			if( addr < 0x4100 ) {
				WriteReg( addr, data );
			} else {
				mapper->WriteLow( addr, data );
			}
			break;
		case	0x03:	// $6000-$7FFF
			mapper->WriteLow( addr, data );
			break;
		case	0x04:	// $8000-$9FFF
		case	0x05:	// $A000-$BFFF
		case	0x06:	// $C000-$DFFF
		case	0x07:	// $E000-$FFFF
			mapper->Write( addr, data );

			GenieCodeProcess();
			break;
	}
}

BYTE	NES::ReadReg( WORD addr )
{
	switch( addr & 0xFF ) {
		case 0x00: case 0x01: case 0x02: case 0x03:
		case 0x04: case 0x05: case 0x06: case 0x07:
		case 0x08: case 0x09: case 0x0A: case 0x0B:
		case 0x0C: case 0x0D: case 0x0E: case 0x0F:
		case 0x10: case 0x11: case 0x12: case 0x13:
			return	apu->Read( addr );
			break;
		case	0x15:
			return	apu->Read( addr );
			break;

		case	0x14:
			return	addr&0xFF;
			break;

		case	0x16:
			if( rom->IsVSUNISYSTEM() ) {
				return	pad->Read( addr );
			} else {
				return	pad->Read( addr ) | 0x40 | m_TapeOut;
			}
			break;
		case	0x17:
			if( rom->IsVSUNISYSTEM() ) {
				return	pad->Read( addr );
			} else {
				return	pad->Read( addr ) | apu->Read( addr );
			}
			break;
		default:
			return	mapper->ExRead( addr );
			break;
	}
}

void	NES::WriteReg( WORD addr, BYTE data )
{
	switch( addr & 0xFF ) {
		case 0x00: case 0x01: case 0x02: case 0x03:
		case 0x04: case 0x05: case 0x06: case 0x07:
		case 0x08: case 0x09: case 0x0A: case 0x0B:
		case 0x0C: case 0x0D: case 0x0E: case 0x0F:
		case 0x10: case 0x11: case 0x12: case 0x13:
		case 0x15:
			apu->Write( addr, data );
			CPUREG[addr & 0xFF] = data;
			break;

		case	0x14:
			ppu->DMA( data );
			cpu->DMA( 514 ); // DMA Pending cycle
			CPUREG[addr & 0xFF] = data;
			break;

		case	0x16:
			mapper->ExWrite( addr, data );	// For VS-Unisystem
			pad->Write( addr, data );
			CPUREG[addr & 0xFF] = data;
			m_TapeIn = data;
			break;

⌨️ 快捷键说明

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