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

📄 nes.cpp

📁 著名的任天堂FC游戏机模拟器VirtuaNes 085版的源码!
💻 CPP
📖 第 1 页 / 共 5 页
字号:
			// Ver0.30埲崀
			case	6:
				{
				DISKDATA ddata;
				DWORD	pos;
				BYTE	data;
				LONG	DiskSize = 16+65500*rom->GetDiskNo();
				LPBYTE	lpDisk  = rom->GetPROM();
				LPBYTE	lpWrite = rom->GetDISK();

				// 彂偒姺偊FLAG徚嫀
				::ZeroMemory( lpWrite, 16+65500*rom->GetDiskNo() );

				if( ::fread( &ddata, sizeof(DISKDATA), 1, fp ) != 1 ) {
					// 僼傽僀儖偺撉傒崬傒偵幐攕偟傑偟偨
					throw	CApp::GetErrorString( IDS_ERROR_READ );
				}

				for( i = 0; i < ddata.DifferentSize; i++ ) {
					if( ::fread( &pos, sizeof(DWORD), 1, fp ) != 1 ) {
						// 僼傽僀儖偺撉傒崬傒偵幐攕偟傑偟偨
						throw	CApp::GetErrorString( IDS_ERROR_READ );
					}
					data = (BYTE)(pos>>24);
					pos &= 0x00FFFFFF;
					if( pos >= 16 && pos < DiskSize ) {
						lpDisk[pos] = data;
						lpWrite[pos] = 0xFF;
					}
				}

				}
				break;
		}
	}

	return	TRUE;
}

void	NES::WriteState( FILE* fp )
{
	INT	i;

	// HEADER
	{
	FILEHDR2 hdr;

	ZEROMEMORY( &hdr, sizeof(FILEHDR2) );
	::memcpy( hdr.ID, "VirtuaNES ST", sizeof(hdr.ID) );
	hdr.BlockVersion = 0x0200;

	if( rom->GetMapperNo() != 20 ) {
		hdr.Ext0 = rom->GetPROM_CRC();
	} else {
		hdr.Ext0 = rom->GetGameID();
		hdr.Ext1 = (WORD)rom->GetMakerID();
		hdr.Ext2 = (WORD)rom->GetDiskNo();
	}

	// 儉乕價乕嵞惗傗婰榐拞偱偁傟偽偦偺埵抲傪婰榐偡傞
	if( m_bMoviePlay || m_bMovieRec ) {
		hdr.MovieStep   = m_MovieStep;
		hdr.MovieOffset = ::ftell( m_fpMovie );
//DEBUGOUT( "\nSV STEP=%d POS=%d\n", m_MovieStep, hdr.MovieOffset );
	}

	// Write File
	if( ::fwrite( &hdr, sizeof(FILEHDR2), 1, fp ) != 1 )
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}

	BLOCKHDR hdr;

	// REGISTER STATE
	{
	REGSTAT	reg;

	ZEROMEMORY( &hdr, sizeof(BLOCKHDR) );
	ZEROMEMORY( &reg, sizeof(REGSTAT) );

	// Create Header
	::memcpy( hdr.ID, "REG DATA", sizeof(hdr.ID) );
	hdr.BlockVersion = 0x0210;
	hdr.BlockSize    = sizeof(REGSTAT);

	// SAVE CPU STATE
	R6502	R;
	cpu->GetContext( R );

	reg.cpureg.cpu.PC = R.PC;
	reg.cpureg.cpu.A  = R.A;
	reg.cpureg.cpu.X  = R.X;
	reg.cpureg.cpu.Y  = R.Y;
	reg.cpureg.cpu.S  = R.S;
	reg.cpureg.cpu.P  = R.P;
	reg.cpureg.cpu.I  = R.INT_pending;

	INT	cycles;
	apu->GetFrameIRQ( cycles,
			  reg.cpureg.cpu.FrameIRQ_count,
			  reg.cpureg.cpu.FrameIRQ_type,
			  reg.cpureg.cpu.FrameIRQ,
			  reg.cpureg.cpu.FrameIRQ_occur );
	reg.cpureg.cpu.FrameIRQ_cycles = (LONG)cycles;	// 嶲徠偑INT側堊乮偋

	reg.cpureg.cpu.DMA_cycles = (LONG)cpu->GetDmaCycles();
	reg.cpureg.cpu.emul_cycles = emul_cycles;
	reg.cpureg.cpu.base_cycles = base_cycles;

	// SAVE PPU STATE
	reg.ppureg.ppu.reg0 = PPUREG[0];
	reg.ppureg.ppu.reg1 = PPUREG[1];
	reg.ppureg.ppu.reg2 = PPUREG[2];
	reg.ppureg.ppu.reg3 = PPUREG[3];
	reg.ppureg.ppu.reg7 = PPU7_Temp;
	reg.ppureg.ppu.loopy_t  = loopy_t;
	reg.ppureg.ppu.loopy_v  = loopy_v;
	reg.ppureg.ppu.loopy_x  = loopy_x;
	reg.ppureg.ppu.toggle56 = PPU56Toggle;

	// Write File
	if( ::fwrite( &hdr, sizeof(BLOCKHDR), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}
	if( ::fwrite( &reg, sizeof(REGSTAT), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}
	}

	// RAM STATE
	{
	RAMSTAT	ram;
	DWORD	size = 0;

	::ZeroMemory( &hdr, sizeof(BLOCKHDR) );
	::ZeroMemory( &ram, sizeof(RAMSTAT) );

	// SAVE RAM STATE
	::memcpy( ram.RAM, RAM, sizeof(ram.RAM) );
	::memcpy( ram.BGPAL, BGPAL, sizeof(ram.BGPAL) );
	::memcpy( ram.SPPAL, SPPAL, sizeof(ram.SPPAL) );
	::memcpy( ram.SPRAM, SPRAM, sizeof(ram.SPRAM) );

	// S-RAM STATE(巊梡/枹巊梡偵娭傢傜偢懚嵼偡傟偽僙乕僽偡傞)
	if( rom->IsSAVERAM() ) {
		size = SAVERAM_SIZE;
	}

	// Create Header
	::memcpy( hdr.ID, "RAM DATA", sizeof(hdr.ID) );
	hdr.BlockVersion = 0x0100;
	hdr.BlockSize    = size+sizeof(RAMSTAT);

	// Write File
	if( ::fwrite( &hdr, sizeof(BLOCKHDR), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}
	if( ::fwrite( &ram, sizeof(RAMSTAT), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}
	if( rom->IsSAVERAM() ) {
		if( ::fwrite( WRAM, SAVERAM_SIZE, 1, fp ) != 1 )
			// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
			throw	CApp::GetErrorString( IDS_ERROR_WRITE );
		}
	}

	// BANK STATE
	{
	MMUSTAT mmu;
	DWORD	size;

	::ZeroMemory( &hdr, sizeof(BLOCKHDR) );
	::ZeroMemory( &mmu, sizeof(MMUSTAT) );

	size = 0;
	// SAVE CPU MEMORY BANK DATA
	// BANK0,1,2偼僶儞僋僙乕僽偵娭學側偟
	// VirtuaNES0.30偐傜
	// 僶儞僋俁偼SRAM巊梡偵娭傢傜偢僙乕僽
	for( i = 3; i < 8; i++ ) {
		mmu.CPU_MEM_TYPE[i] = CPU_MEM_TYPE[i];
		mmu.CPU_MEM_PAGE[i] = CPU_MEM_PAGE[i];

		if( CPU_MEM_TYPE[i] == BANKTYPE_RAM
		 || CPU_MEM_TYPE[i] == BANKTYPE_DRAM ) {
			size += 8*1024;	// 8K BANK
		}
	}

	// SAVE VRAM MEMORY DATA
	for( i = 0; i < 12; i++ ) {
		mmu.PPU_MEM_TYPE[i] = PPU_MEM_TYPE[i];
		mmu.PPU_MEM_PAGE[i] = PPU_MEM_PAGE[i];
	}
	size += 4*1024;	// 1K BANK x 4 (VRAM)

	for( i = 0; i < 8; i++ ) {
		mmu.CRAM_USED[i] = CRAM_USED[i];
		if( CRAM_USED[i] != 0 ) {
			size += 4*1024;	// 4K BANK
		}
	}

	// Create Header
	::memcpy( hdr.ID, "MMU DATA", sizeof(hdr.ID) );
	hdr.BlockVersion = 0x0200;
	hdr.BlockSize    = size+sizeof(MMUSTAT);

	// Write File
	if( ::fwrite( &hdr, sizeof(BLOCKHDR), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}
	if( ::fwrite( &mmu, sizeof(MMUSTAT), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}

	// WRITE CPU RAM MEMORY BANK
	for( i = 3; i < 8; i++ ) {
		if( mmu.CPU_MEM_TYPE[i] != BANKTYPE_ROM ) {
			if( ::fwrite( CPU_MEM_BANK[i], 8*1024, 1, fp ) != 1 ) {
				// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
				throw	CApp::GetErrorString( IDS_ERROR_WRITE );
			}
		}
	}
	// WRITE VRAM MEMORY(忢偵4K暘偡傋偰彂偒崬傓)
	if( ::fwrite( VRAM, 4*1024, 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}

	// WRITE CRAM MEMORY
	for( i = 0; i < 8; i++ ) {
		if( CRAM_USED[i] != 0 ) {
			if( ::fwrite( &CRAM[0x1000*i], 4*1024, 1, fp ) != 1 ) {
				// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
				throw	CApp::GetErrorString( IDS_ERROR_WRITE );
			}
		}
	}
	}

	// MMC STATE
	{
	MMCSTAT	mmc;

	::ZeroMemory( &hdr, sizeof(BLOCKHDR) );
	::ZeroMemory( &mmc, sizeof(MMCSTAT) );

	// Create Header
	::memcpy( hdr.ID, "MMC DATA", sizeof(hdr.ID) );
	hdr.BlockVersion = 0x0100;
	hdr.BlockSize    = sizeof(MMCSTAT);

	if( mapper->IsStateSave() ) {
		mapper->SaveState( mmc.mmcdata );
		// Write File
		if( ::fwrite( &hdr, sizeof(BLOCKHDR), 1, fp ) != 1 ) {
			// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
			throw	CApp::GetErrorString( IDS_ERROR_WRITE );
		}
		if( ::fwrite( &mmc, sizeof(MMCSTAT), 1, fp ) != 1 ) {
			// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
			throw	CApp::GetErrorString( IDS_ERROR_WRITE );
		}
	}
	}

	// CONTROLLER STATE
	{
	CTRSTAT	ctr;

	::ZeroMemory( &hdr, sizeof(BLOCKHDR) );
	::ZeroMemory( &ctr, sizeof(CTRSTAT) );

	// Create Header
	::memcpy( hdr.ID, "CTR DATA", sizeof(hdr.ID) );
	hdr.BlockVersion = 0x0100;
	hdr.BlockSize    = sizeof(CTRSTAT);

	ctr.ctrreg.ctr.pad1bit = pad->pad1bit;
	ctr.ctrreg.ctr.pad2bit = pad->pad2bit;
	ctr.ctrreg.ctr.pad3bit = pad->pad3bit;
	ctr.ctrreg.ctr.pad4bit = pad->pad4bit;
	ctr.ctrreg.ctr.strobe  = pad->GetStrobe()?0xFF:0;
//DEBUGOUT( "SV pad1bit=%08X Strobe=%d\n", pad->pad1bit, pad->GetStrobe()?1:0 );

	if( ::fwrite( &hdr, sizeof(BLOCKHDR), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}

	if( ::fwrite( &ctr, sizeof(CTRSTAT), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}
	}

	// SND STATE
	{
	SNDSTAT	snd;

	::ZeroMemory( &hdr, sizeof(BLOCKHDR) );
	::ZeroMemory( &snd, sizeof(SNDSTAT) );

	// Create Header
	::memcpy( hdr.ID, "SND DATA", sizeof(hdr.ID) );
	hdr.BlockVersion = 0x0100;
	hdr.BlockSize    = sizeof(SNDSTAT);

	apu->SaveState( snd.snddata );

	if( ::fwrite( &hdr, sizeof(BLOCKHDR), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}

	if( ::fwrite( &snd, sizeof(SNDSTAT), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}
	}

	// DISKIMAGE STATE
	if( rom->GetMapperNo() == 20 )
	{
	DISKDATA dsk;
	LPBYTE	lpDisk  = rom->GetPROM();
	LPBYTE	lpWrite = rom->GetDISK();
	LONG	DiskSize = 16+65500*rom->GetDiskNo();
	DWORD	data;

	::ZeroMemory( &hdr, sizeof(BLOCKHDR) );
	::ZeroMemory( &dsk, sizeof(DISKDATA) );

	// 憡堘悢傪僇僂儞僩
	for( i = 16; i < DiskSize; i++ ) {
		if( lpWrite[i] )
			dsk.DifferentSize++;
	}

	::memcpy( hdr.ID, "DISKDATA", sizeof(hdr.ID) );
	hdr.BlockVersion = 0x0210;
	hdr.BlockSize    = 0;

	// Write File
	if( ::fwrite( &hdr, sizeof(BLOCKHDR), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}
	// Write File
	if( ::fwrite( &dsk, sizeof(DISKDATA), 1, fp ) != 1 ) {
		// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
		throw	CApp::GetErrorString( IDS_ERROR_WRITE );
	}

	for( i = 16; i < DiskSize; i++ ) {
		if( lpWrite[i] ) {
			data = i & 0x00FFFFFF;
			data |= ((DWORD)lpDisk[i]&0xFF)<<24;

			// Write File
			if( ::fwrite( &data, sizeof(DWORD), 1, fp ) != 1 ) {
				// 僼傽僀儖偺彂偒崬傒偵幐攕偟傑偟偨
				throw	CApp::GetErrorString( IDS_ERROR_WRITE );
			}
		}
	}
	}
}

INT	NES::GetDiskNo()
{
	return	rom->GetDiskNo();
}

void	NES::SoundSetup()
{
	apu->SoundSetup();
}

void	NES::Command( NESCOMMAND cmd )
{
	CommandParam( cmd, 0 );
}

BOOL	NES::CommandParam( NESCOMMAND cmd, INT param )
{
	switch( cmd ) {
		case	NESCMD_NONE:
			break;
		case	NESCMD_DISK_THROTTLE_ON:
			if( Config.emulator.bDiskThrottle ) {
				m_bDiskThrottle = TRUE;
			}
			break;
		case	NESCMD_DISK_THROTTLE_OFF:
			m_bDiskThrottle = FALSE;
			break;
		case	NESCMD_DISK_EJECT:
			mapper->ExCmdWrite( Mapper::EXCMDWR_DISKEJECT, 0 );
			m_CommandRequest = (INT)cmd;
			break;
		case	NESCMD_DISK_0A:
			if( rom->GetDiskNo() > 0 ) {
				mapper->ExCmdWrite( Mapper::EXCMDWR_DISKINSERT, 0 );
				m_CommandRequest = (INT)cmd;
			}
			break;
		case	NESCMD_DISK_0B:
			if( rom->GetDiskNo() > 1 ) {
				mapper->ExCmdWrite( Mapper::EXCMDWR_DISKINSERT, 1 );
				m_CommandRequest = (INT)cmd;
			}
			break;
		case	NESCMD_DISK_1A:
			if( rom->GetDiskNo() > 2 ) {
				mapper->ExCmdWrite( Mapper::EXCMDWR_DISKINSERT, 2 );
				m_CommandRequest = (INT)cmd;
			}
			break;
		case	NESCMD_DISK_1B:
			if( rom->GetDiskNo() > 3 ) {
				mapper->ExCmdWrite( Mapper::EXCMDWR_DISKINSERT, 3 );
				m_CommandRequest = (INT)cmd;
			}
			break;

		case	NESCMD_HWRESET:
			Reset();
			m_CommandRequest = (INT)cmd;
			break;
		case	NESCMD_SWRESET:
			SoftReset();
			m_CommandRequest = (INT)cmd;
			break;

		case	NESCMD_EXCONTROLLER:
			pad->SetExController( param&0xFF );
			m_CommandRequest = 0x0100|(param&0xFF);
			break;

		case	NESCMD_SOUND_MUTE:
			return	apu->SetChannelMute( (BOOL)param ); // 儕僞乕儞抣偼曄峏屻偺儈儏乕僩忬懺
	}

	return	TRUE;
}

BOOL	NES::Snapshot()
{
FILE*	fp = NULL;

	try {
		SYSTEMTIME	now;
		::GetLocalTime( &now );

		CHAR	name[_MAX_PATH];

		if( !Config.emulator.bPNGsnapshot ) {
			sprintf( name, "%s %04d%02d%02d%02d%02d%02d%01d.bmp", rom->GetRomName(),
				now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond, now.wMilliseconds/100 );
		} else {
			sprintf( name, "%s %04d%02d%02d%02d%02d%02d%01d.png", rom->GetRomName(),
				now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond, now.wMilliseconds/100 );
		}

		string	pathstr, tempstr;
		if( Config.path.bSnapshotPath ) {
			pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szSnapshotPath );
			::CreateDirectory( pathstr.c_str(), NULL );
		} else {
			pathstr = rom->GetRomPath();
		}
		tempstr = CPathlib::MakePath( pathstr.c_str(), name );
		DEBUGOUT( "Snapshot: %s\n", tempstr.c_str() );

		if( !Config.emulator.bPNGsnapshot ) {
			if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
				// xxx 僼傽僀儖傪奐偗傑偣傫
				LPCSTR	szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
				sprintf( szErrorString, sz

⌨️ 快捷键说明

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