📄 nes.cpp
字号:
// 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( ®, 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( ®, 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 + -