4269 lines
104 KiB
C++
4269 lines
104 KiB
C++
|
//////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// NES Emulation core //
|
|||
|
// Norix //
|
|||
|
// written 2001/02/22 //
|
|||
|
// last modify ----/--/-- //
|
|||
|
//////////////////////////////////////////////////////////////////////////
|
|||
|
#define WIN32_LEAN_AND_MEAN
|
|||
|
#include <windows.h>
|
|||
|
#include <stdio.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <math.h>
|
|||
|
#include <time.h>
|
|||
|
#include <mbstring.h>
|
|||
|
|
|||
|
#include "typedef.h"
|
|||
|
#include "macro.h"
|
|||
|
|
|||
|
#include "VirtuaNESres.h"
|
|||
|
|
|||
|
#include "DebugOut.h"
|
|||
|
#include "App.h"
|
|||
|
#include "Pathlib.h"
|
|||
|
#include "Config.h"
|
|||
|
#include "Crclib.h"
|
|||
|
|
|||
|
#include "nes.h"
|
|||
|
#include "mmu.h"
|
|||
|
#include "cpu.h"
|
|||
|
#include "ppu.h"
|
|||
|
#include "apu.h"
|
|||
|
#include "pad.h"
|
|||
|
#include "rom.h"
|
|||
|
#include "mapper.h"
|
|||
|
|
|||
|
#include "DirectDraw.h"
|
|||
|
#include "DirectSound.h"
|
|||
|
#include "DirectInput.h"
|
|||
|
|
|||
|
#include "pngwrite.h"
|
|||
|
|
|||
|
NESCONFIG NESCONFIG_NTSC = {
|
|||
|
21477270.0f, // Base clock
|
|||
|
1789772.5f, // Cpu clock
|
|||
|
|
|||
|
262, // Total scanlines
|
|||
|
241, // VBlank start line
|
|||
|
|
|||
|
1364, // Scanline total cycles(15.75KHz)
|
|||
|
|
|||
|
1024, // H-Draw cycles
|
|||
|
340, // H-Blank cycles
|
|||
|
4, // End cycles
|
|||
|
|
|||
|
1364*262, // Frame cycles
|
|||
|
29830, // FrameIRQ cycles
|
|||
|
|
|||
|
60, // Frame rate(Be originally 59.94Hz)
|
|||
|
1000.0f/60.0f // Frame period(ms)
|
|||
|
};
|
|||
|
|
|||
|
NESCONFIG NESCONFIG_PAL = {
|
|||
|
21281364.0f, // Base clock
|
|||
|
1773447.0f, // Cpu clock
|
|||
|
|
|||
|
312, // Total scanlines
|
|||
|
241, // VBlank start line
|
|||
|
|
|||
|
1362, // Scanline total cycles(15.625KHz)
|
|||
|
|
|||
|
1024, // H-Draw cycles
|
|||
|
338, // H-Blank cycles
|
|||
|
4, // End cycles
|
|||
|
|
|||
|
1362*312, // Frame cycles
|
|||
|
35469, // FrameIRQ cycles
|
|||
|
|
|||
|
50, // Frame rate(Hz)
|
|||
|
1000.0f/50.0f // Frame period(ms)
|
|||
|
};
|
|||
|
|
|||
|
NESCONFIG NESCONFIG_PALCHINA = {
|
|||
|
21281364.0f, // Base clock
|
|||
|
1773447.0f, // Cpu clock
|
|||
|
|
|||
|
313, // Total scanlines
|
|||
|
291, // VBlank start line
|
|||
|
|
|||
|
1362, // Scanline total cycles(15.625KHz)
|
|||
|
|
|||
|
1024, // H-Draw cycles
|
|||
|
338, // H-Blank cycles
|
|||
|
2, // End cycles
|
|||
|
|
|||
|
1362*313, // Frame cycles
|
|||
|
35469, // FrameIRQ cycles
|
|||
|
|
|||
|
50, // Frame rate(Hz)
|
|||
|
1000.0f/50.0f // Frame period(ms)
|
|||
|
};
|
|||
|
|
|||
|
// Pad disp
|
|||
|
BYTE NES::m_PadImg[] = {
|
|||
|
28, 8,
|
|||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
|
|||
|
0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x0F,
|
|||
|
0x0F, 0x0F, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x0F,
|
|||
|
0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|||
|
};
|
|||
|
BYTE NES::m_KeyImg0[] = {
|
|||
|
2, 2,
|
|||
|
0x2A, 0x2A,
|
|||
|
0x2A, 0x2A,
|
|||
|
};
|
|||
|
BYTE NES::m_KeyImg1[] = {
|
|||
|
3, 3,
|
|||
|
0x2A, 0x2A, 0x2A,
|
|||
|
0x2A, 0x2A, 0x2A,
|
|||
|
};
|
|||
|
BYTE NES::m_KeyImg2[] = {
|
|||
|
4, 4,
|
|||
|
0xFF, 0x2A, 0x2A, 0xFF,
|
|||
|
0x2A, 0x2A, 0x2A, 0x2A,
|
|||
|
0x2A, 0x2A, 0x2A, 0x2A,
|
|||
|
0xFF, 0x2A, 0x2A, 0xFF,
|
|||
|
};
|
|||
|
|
|||
|
//
|
|||
|
//
|
|||
|
//
|
|||
|
NES::NES( const char* fname )
|
|||
|
{
|
|||
|
DEBUGOUT( "VirtuaNES - NES Emulator for Win32 by Norix (C)2001\n" );
|
|||
|
|
|||
|
m_bDiskThrottle = FALSE;
|
|||
|
m_CommandRequest = 0;
|
|||
|
|
|||
|
m_nSnapNo = 0;
|
|||
|
|
|||
|
m_bNsfPlaying = FALSE;
|
|||
|
|
|||
|
m_bMoviePlay = m_bMovieRec = FALSE;
|
|||
|
m_fpMovie = NULL;
|
|||
|
|
|||
|
m_bTapePlay = m_bTapeRec = FALSE;
|
|||
|
m_fpTape = NULL;
|
|||
|
m_TapeCycles = 0.0;
|
|||
|
m_TapeIn = m_TapeOut = 0;
|
|||
|
|
|||
|
m_bBarcode = FALSE;
|
|||
|
m_BarcodeOut = 0;
|
|||
|
m_BarcodePtr = 0;
|
|||
|
m_BarcodeCycles = 0;
|
|||
|
|
|||
|
m_bBarcode2 = FALSE;
|
|||
|
|
|||
|
m_TurboFileBank = 0;
|
|||
|
|
|||
|
cpu = NULL;
|
|||
|
ppu = NULL;
|
|||
|
apu = NULL;
|
|||
|
rom = NULL;
|
|||
|
pad = NULL;
|
|||
|
mapper = NULL;
|
|||
|
|
|||
|
SAVERAM_SIZE = 8*1024; // 8K byte
|
|||
|
|
|||
|
// IRQ type
|
|||
|
nIRQtype = 0;
|
|||
|
|
|||
|
// FrameIRQ mode
|
|||
|
bFrameIRQ = TRUE;
|
|||
|
|
|||
|
// NTSC/PAL VideoMode
|
|||
|
bVideoMode = FALSE;
|
|||
|
|
|||
|
// Default config
|
|||
|
nescfg = &NESCONFIG_NTSC;
|
|||
|
|
|||
|
// Cheat
|
|||
|
CheatInitial();
|
|||
|
|
|||
|
// TEST
|
|||
|
m_dwTotalCycle = 0;
|
|||
|
m_dwTotalTempCycle = 0;
|
|||
|
m_dwProfileTotalCycle = 0;
|
|||
|
m_dwProfileTotalCount = 0;
|
|||
|
m_dwProfileCycle = 0;
|
|||
|
m_dwProfileTempCycle = 0;
|
|||
|
|
|||
|
try {
|
|||
|
DEBUGOUT( "Allocating CPU..." );
|
|||
|
if( !(cpu = new CPU(this)) )
|
|||
|
throw "Allocating CPU failed.";
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
|
|||
|
DEBUGOUT( "Allocating PPU..." );
|
|||
|
if( !(ppu = new PPU(this)) )
|
|||
|
throw "Allocating PPU failed.";
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
|
|||
|
DEBUGOUT( "Allocating APU..." );
|
|||
|
if( !(apu = new APU(this)) )
|
|||
|
throw "Allocating APU failed.";
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
|
|||
|
DEBUGOUT( "Allocating PAD..." );
|
|||
|
if( !(pad = new PAD(this)) )
|
|||
|
throw "Allocating PAD failed.";
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
|
|||
|
DEBUGOUT( "Loading ROM Image...\n" );
|
|||
|
|
|||
|
if( !(rom = new ROM(fname)) )
|
|||
|
throw "Allocating ROM failed.";
|
|||
|
/*
|
|||
|
if( !(mapper = CreateMapper(this, rom->GetMapperNo())) ) {
|
|||
|
// <20><><EFBFBD>T<EFBFBD>|<7C>[<5B>g<EFBFBD>̃}<7D>b<EFBFBD>p<EFBFBD>[<5B>ł<EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_UNSUPPORTMAPPER );
|
|||
|
sprintf( szErrorString, szErrStr, rom->GetMapperNo() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
*/
|
|||
|
if( !(mapper = CreateMapper(this, rom->IsUnifMapper()?rom->GetUnifBoard():rom->GetMapperNo(), rom->IsUnifMapper())) ){
|
|||
|
// <20><><EFBFBD>T<EFBFBD>|<7C>[<5B>g<EFBFBD>̃}<7D>b<EFBFBD>p<EFBFBD>[<5B>ł<EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_UNSUPPORTMAPPER );
|
|||
|
if(rom->IsUnifMapper()){
|
|||
|
sprintf( szErrorString, "<EFBFBD>ݲ<EFBFBD>֧<EFBFBD><EFBFBD>UNIF Board - [ %s ] <20><>", rom->GetBoardName() );
|
|||
|
}else{
|
|||
|
sprintf( szErrorString, szErrStr, rom->GetMapperNo() );
|
|||
|
}
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
|
|||
|
DEBUGOUT( "ROM status\n" );
|
|||
|
DEBUGOUT( " %s\n", rom->GetRomName() );
|
|||
|
DEBUGOUT( " Mapper : %03d\n", rom->GetMapperNo() );
|
|||
|
DEBUGOUT( " PRG SIZE : %4dK\n", 16*(INT)rom->GetPROM_SIZE() );
|
|||
|
DEBUGOUT( " CHR SIZE : %4dK\n", 8*(INT)rom->GetVROM_SIZE() );
|
|||
|
|
|||
|
DEBUGOUT( " V MIRROR : " );
|
|||
|
if( rom->IsVMIRROR() ) DEBUGOUT( "Yes\n" );
|
|||
|
else DEBUGOUT( "No\n" );
|
|||
|
DEBUGOUT( " 4 SCREEN : " );
|
|||
|
if( rom->Is4SCREEN() ) DEBUGOUT( "Yes\n" );
|
|||
|
else DEBUGOUT( "No\n" );
|
|||
|
DEBUGOUT( " SAVE RAM : " );
|
|||
|
if( rom->IsSAVERAM() ) DEBUGOUT( "Yes\n" );
|
|||
|
else DEBUGOUT( "No\n" );
|
|||
|
DEBUGOUT( " TRAINER : " );
|
|||
|
if( rom->IsTRAINER() ) DEBUGOUT( "Yes\n" );
|
|||
|
else DEBUGOUT( "No\n" );
|
|||
|
DEBUGOUT( " VS-Unisystem : " );
|
|||
|
if( rom->IsVSUNISYSTEM() ) DEBUGOUT( "Yes\n" );
|
|||
|
else DEBUGOUT( "No\n" );
|
|||
|
|
|||
|
NesSub_MemoryInitial();
|
|||
|
LoadSRAM();
|
|||
|
LoadDISK();
|
|||
|
|
|||
|
{
|
|||
|
// Pad<61>N<EFBFBD><4E><EFBFBD>X<EFBFBD><58><EFBFBD><EFBFBD><EFBFBD>Ə<EFBFBD><C68F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>^<5E>C<EFBFBD>~<7E><><EFBFBD>O<EFBFBD><4F><EFBFBD>x<EFBFBD><78><EFBFBD>̂ł<CC82><C582><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
DWORD crc = rom->GetPROM_CRC();
|
|||
|
if( crc == 0xe792de94 // Best Play - Pro Yakyuu (New) (J)
|
|||
|
|| crc == 0xf79d684a // Best Play - Pro Yakyuu (Old) (J)
|
|||
|
|| crc == 0xc2ef3422 // Best Play - Pro Yakyuu 2 (J)
|
|||
|
|| crc == 0x974e8840 // Best Play - Pro Yakyuu '90 (J)
|
|||
|
|| crc == 0xb8747abf // Best Play - Pro Yakyuu Special (J)
|
|||
|
|| crc == 0x9fa1c11f // Castle Excellent (J)
|
|||
|
|| crc == 0x0b0d4d1b // Derby Stallion - Zenkoku Ban (J)
|
|||
|
|| crc == 0x728c3d98 // Downtown - Nekketsu Monogatari (J)
|
|||
|
|| crc == 0xd68a6f33 // Dungeon Kid (J)
|
|||
|
|| crc == 0x3a51eb04 // Fleet Commander (J)
|
|||
|
|| crc == 0x7c46998b // Haja no Fuuin (J)
|
|||
|
|| crc == 0x7e5d2f1a // Itadaki Street - Watashi no Mise ni Yottette (J)
|
|||
|
|| crc == 0xcee5857b // Ninjara Hoi! (J)
|
|||
|
|| crc == 0x50ec5e8b // Wizardry - Legacy of Llylgamyn (J)
|
|||
|
|| crc == 0x343e9146 // Wizardry - Proving Grounds of the Mad Overlord (J)
|
|||
|
|| crc == 0x33d07e45 ) { // Wizardry - The Knight of Diamonds (J)
|
|||
|
pad->SetExController( PAD::EXCONTROLLER_TURBOFILE );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LoadTurboFile();
|
|||
|
|
|||
|
// VS-Unisystem<65>̃f<CC83>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD>ݒ<EFBFBD>
|
|||
|
if( rom->IsVSUNISYSTEM() ) {
|
|||
|
DWORD crc = rom->GetPROM_CRC();
|
|||
|
|
|||
|
m_VSDipValue = GetVSDefaultDipSwitchValue( crc );
|
|||
|
m_VSDipTable = FindVSDipSwitchTable( crc );
|
|||
|
|
|||
|
#include "VS_Setting.h"
|
|||
|
} else {
|
|||
|
m_VSDipValue = 0;
|
|||
|
m_VSDipTable = vsdip_default;
|
|||
|
}
|
|||
|
|
|||
|
Reset();
|
|||
|
|
|||
|
// <20>Q<EFBFBD>[<5B><><EFBFBD>ŗL<C597>̃f<CC83>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD>I<EFBFBD>v<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ݒ<EFBFBD>(<28>ݒ<EFBFBD><DD92>߂<EFBFBD><DF82><EFBFBD><EFBFBD>Ɏg<C98E><67><EFBFBD><EFBFBD>)
|
|||
|
GameOption.defRenderMethod = (INT)GetRenderMethod();
|
|||
|
GameOption.defIRQtype = (INT)GetIrqType();
|
|||
|
GameOption.defFrameIRQ = GetFrameIRQmode();
|
|||
|
GameOption.defVideoMode = GetVideoMode();
|
|||
|
|
|||
|
// <20>ݒ<EFBFBD><DD92><EFBFBD><EFBFBD><EFBFBD><EFBFBD>[<5B>h<EFBFBD><68><EFBFBD>Đݒ肷<DD92><E882B7>(<28>G<EFBFBD><47><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>f<CE83>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
|||
|
if( rom->GetMapperNo() != 20 ) {
|
|||
|
GameOption.Load( rom->GetPROM_CRC() );
|
|||
|
} else {
|
|||
|
GameOption.Load( rom->GetGameID(), rom->GetMakerID() );
|
|||
|
}
|
|||
|
SetRenderMethod( (RENDERMETHOD)GameOption.nRenderMethod );
|
|||
|
SetIrqType ( GameOption.nIRQtype );
|
|||
|
SetFrameIRQmode( GameOption.bFrameIRQ );
|
|||
|
SetVideoMode ( GameOption.bVideoMode );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DELETEPTR( cpu );
|
|||
|
DELETEPTR( ppu );
|
|||
|
DELETEPTR( apu );
|
|||
|
DELETEPTR( pad );
|
|||
|
DELETEPTR( rom );
|
|||
|
DELETEPTR( mapper );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch( ... ) {
|
|||
|
DELETEPTR( cpu );
|
|||
|
DELETEPTR( ppu );
|
|||
|
DELETEPTR( apu );
|
|||
|
DELETEPTR( pad );
|
|||
|
DELETEPTR( rom );
|
|||
|
DELETEPTR( mapper );
|
|||
|
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "Starting emulation!\n" );
|
|||
|
}
|
|||
|
|
|||
|
NES::~NES()
|
|||
|
{
|
|||
|
MovieStop();
|
|||
|
|
|||
|
SaveSRAM();
|
|||
|
SaveDISK();
|
|||
|
SaveTurboFile();
|
|||
|
|
|||
|
DEBUGOUT( "Free NES..." );
|
|||
|
|
|||
|
DELETEPTR( cpu );
|
|||
|
DELETEPTR( ppu );
|
|||
|
DELETEPTR( apu );
|
|||
|
DELETEPTR( pad );
|
|||
|
DELETEPTR( rom );
|
|||
|
DELETEPTR( mapper );
|
|||
|
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
}
|
|||
|
|
|||
|
void NES::SetVideoMode( BOOL bMode )
|
|||
|
{
|
|||
|
bVideoMode = bMode;
|
|||
|
if( bVideoMode==0 ) {
|
|||
|
nescfg = &NESCONFIG_NTSC;
|
|||
|
}else if(bVideoMode==1){
|
|||
|
nescfg = &NESCONFIG_PAL;
|
|||
|
}else if(bVideoMode==2){
|
|||
|
nescfg = &NESCONFIG_PALCHINA;
|
|||
|
}
|
|||
|
apu->SoundSetup();
|
|||
|
}
|
|||
|
|
|||
|
void NES::Reset()
|
|||
|
{
|
|||
|
SaveSRAM();
|
|||
|
SaveDISK();
|
|||
|
SaveTurboFile();
|
|||
|
|
|||
|
// RAM Clear
|
|||
|
ZEROMEMORY( RAM, sizeof(RAM) );
|
|||
|
|
|||
|
// RAM set
|
|||
|
if( !rom->IsSAVERAM() && rom->GetMapperNo() != 20 ) {
|
|||
|
::memset( WRAM, 0xFF, sizeof(WRAM) );
|
|||
|
}
|
|||
|
|
|||
|
ZEROMEMORY( CRAM, sizeof(CRAM) );
|
|||
|
ZEROMEMORY( YCRAM, sizeof(YCRAM) );
|
|||
|
ZEROMEMORY( VRAM, sizeof(VRAM) );
|
|||
|
|
|||
|
ZEROMEMORY( SPRAM, sizeof(SPRAM) );
|
|||
|
ZEROMEMORY( BGPAL, sizeof(BGPAL) );
|
|||
|
ZEROMEMORY( SPPAL, sizeof(SPPAL) );
|
|||
|
|
|||
|
ZEROMEMORY( CPUREG, sizeof(CPUREG) );
|
|||
|
ZEROMEMORY( PPUREG, sizeof(PPUREG) );
|
|||
|
|
|||
|
m_bDiskThrottle = FALSE;
|
|||
|
|
|||
|
SetRenderMethod( PRE_RENDER );
|
|||
|
|
|||
|
if( rom->IsPAL() ) {
|
|||
|
SetVideoMode(1);
|
|||
|
}
|
|||
|
|
|||
|
PROM = rom->GetPROM();
|
|||
|
VROM = rom->GetVROM();
|
|||
|
|
|||
|
PROM_8K_SIZE = rom->GetPROM_SIZE()*2;
|
|||
|
PROM_16K_SIZE = rom->GetPROM_SIZE();
|
|||
|
PROM_32K_SIZE = rom->GetPROM_SIZE()/2;
|
|||
|
|
|||
|
//for Game Star - Smart Genius (Unl)
|
|||
|
if(PROM_16K_SIZE==0xff){
|
|||
|
PROM_8K_SIZE = (rom->GetPROM_SIZE()+1)*2;
|
|||
|
PROM_16K_SIZE = rom->GetPROM_SIZE()+1;
|
|||
|
PROM_32K_SIZE = (rom->GetPROM_SIZE()+1)/2;
|
|||
|
}
|
|||
|
|
|||
|
VROM_1K_SIZE = rom->GetVROM_SIZE()*8;
|
|||
|
VROM_2K_SIZE = rom->GetVROM_SIZE()*4;
|
|||
|
VROM_4K_SIZE = rom->GetVROM_SIZE()*2;
|
|||
|
VROM_8K_SIZE = rom->GetVROM_SIZE();
|
|||
|
|
|||
|
// <20>f<EFBFBD>t<EFBFBD>H<EFBFBD><48><EFBFBD>g<EFBFBD>o<EFBFBD><6F><EFBFBD>N
|
|||
|
if( VROM_8K_SIZE ) {
|
|||
|
SetVROM_8K_Bank( 0 );
|
|||
|
} else {
|
|||
|
SetCRAM_8K_Bank( 0 );
|
|||
|
}
|
|||
|
|
|||
|
// <20>~<7E><><EFBFBD>[
|
|||
|
if( rom->Is4SCREEN() ) {
|
|||
|
SetVRAM_Mirror( VRAM_MIRROR4 );
|
|||
|
} else if( rom->IsVMIRROR() ) {
|
|||
|
SetVRAM_Mirror( VRAM_VMIRROR );
|
|||
|
} else {
|
|||
|
SetVRAM_Mirror( VRAM_HMIRROR );
|
|||
|
}
|
|||
|
|
|||
|
apu->SelectExSound( 0 );
|
|||
|
|
|||
|
ppu->Reset();
|
|||
|
mapper->Reset();
|
|||
|
|
|||
|
// Trainer
|
|||
|
if( rom->IsTRAINER() ) {
|
|||
|
::memcpy( WRAM+0x1000, rom->GetTRAINER(), 512 );
|
|||
|
}
|
|||
|
|
|||
|
pad->Reset();
|
|||
|
cpu->Reset();
|
|||
|
apu->Reset();
|
|||
|
|
|||
|
if( rom->IsNSF() ) {
|
|||
|
mapper->Reset();
|
|||
|
}
|
|||
|
|
|||
|
// mapper->Reset();
|
|||
|
base_cycles = emul_cycles = 0;
|
|||
|
}
|
|||
|
|
|||
|
void NES::SoftReset()
|
|||
|
{
|
|||
|
pad->Reset();
|
|||
|
cpu->Reset();
|
|||
|
apu->Reset();
|
|||
|
|
|||
|
if( rom->IsNSF() ) {
|
|||
|
mapper->Reset();
|
|||
|
}
|
|||
|
|
|||
|
// mapper->Reset();
|
|||
|
m_bDiskThrottle = FALSE;
|
|||
|
|
|||
|
base_cycles = emul_cycles = 0;
|
|||
|
}
|
|||
|
|
|||
|
void NES::EmulationCPU( INT basecycles )
|
|||
|
{
|
|||
|
INT cycles;
|
|||
|
|
|||
|
base_cycles += basecycles;
|
|||
|
cycles = (INT)((base_cycles/12)-emul_cycles);
|
|||
|
if( cycles > 0 ) {
|
|||
|
emul_cycles += cpu->EXEC( cycles );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::EmulationCPU_BeforeNMI( INT cycles )
|
|||
|
{
|
|||
|
base_cycles += cycles;
|
|||
|
emul_cycles += cpu->EXEC( cycles/12 );
|
|||
|
}
|
|||
|
|
|||
|
/*
|
|||
|
<EFBFBD>`<EFBFBD><EFBFBD><EFBFBD>V<EFBFBD>[<EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>X
|
|||
|
0 <EFBFBD>_<EFBFBD>~<EFBFBD>[<EFBFBD>X<EFBFBD>L<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD>(<EFBFBD>`<EFBFBD>悵<EFBFBD>Ȃ<EFBFBD>)
|
|||
|
1 - 239 <EFBFBD>`<EFBFBD><EFBFBD>
|
|||
|
240 <EFBFBD>_<EFBFBD>~<EFBFBD>[<EFBFBD>X<EFBFBD>L<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><EFBFBD>,VBLANK<EFBFBD>t<EFBFBD><EFBFBD><EFBFBD>OON
|
|||
|
241 VINT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,NMI<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
242-261 VINT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
261 VINT<EFBFBD><EFBFBD><EFBFBD><EFBFBD>,VBLANK<EFBFBD>t<EFBFBD><EFBFBD><EFBFBD>OOFF
|
|||
|
*/
|
|||
|
void NES::EmulateFrame( BOOL bDraw )
|
|||
|
{
|
|||
|
INT scanline = 0;
|
|||
|
|
|||
|
// NSF<53>v<EFBFBD><76><EFBFBD>C<EFBFBD><43><EFBFBD>̎<EFBFBD>
|
|||
|
if( rom->IsNSF() ) {
|
|||
|
EmulateNSF();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// Cheat
|
|||
|
CheatCodeProcess();
|
|||
|
//
|
|||
|
NES_scanline = scanline;
|
|||
|
|
|||
|
if( RenderMethod != TILE_RENDER ) {
|
|||
|
bZapper = FALSE;
|
|||
|
while( TRUE ) {
|
|||
|
ppu->SetRenderScanline( scanline );
|
|||
|
|
|||
|
if( scanline == 0 ) {
|
|||
|
// <20>_<EFBFBD>~<7E>[<5B>X<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><43>
|
|||
|
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 );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if( RenderMethod == PRE_ALL_RENDER )
|
|||
|
EmulationCPU( nescfg->ScanlineCycles );
|
|||
|
ppu->ScanlineNext(); // <20><><EFBFBD><EFBFBD><EFBFBD>̈ʒu<CA92>Ń<EFBFBD><C583>X<EFBFBD>^<5E>[<5B>n<EFBFBD>͉<EFBFBD><CD89>ʂ<EFBFBD><CA82>Ⴄ
|
|||
|
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 ) {
|
|||
|
pad->VSync();
|
|||
|
|
|||
|
// VBLANK<4E><4B><EFBFBD><EFBFBD>
|
|||
|
if( scanline == nescfg->TotalScanlines-1 ) {
|
|||
|
ppu->VBlankEnd();
|
|||
|
}
|
|||
|
if( RenderMethod < POST_RENDER ) {
|
|||
|
if( scanline == nescfg->VBlankLine ) {
|
|||
|
ppu->VBlankStart();
|
|||
|
if( PPUREG[0] & PPU_VBLANK_BIT ) {
|
|||
|
cpu->NMI();
|
|||
|
}
|
|||
|
}
|
|||
|
EmulationCPU( nescfg->ScanlineCycles );
|
|||
|
mapper->HSync( scanline );
|
|||
|
} else {
|
|||
|
if( scanline == nescfg->VBlankLine ) {
|
|||
|
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 ) {
|
|||
|
// <20>_<EFBFBD>~<7E>[<5B>X<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><43>
|
|||
|
// H-Draw (4fetches*32)
|
|||
|
EmulationCPU( FETCH_CYCLES*128 );
|
|||
|
ppu->FrameStart();
|
|||
|
ppu->ScanlineNext();
|
|||
|
EmulationCPU( FETCH_CYCLES*10 );
|
|||
|
mapper->HSync( scanline );
|
|||
|
EmulationCPU( FETCH_CYCLES*22 );
|
|||
|
ppu->ScanlineStart();
|
|||
|
EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
|
|||
|
} else if( scanline < 240 ) {
|
|||
|
// <20>X<EFBFBD>N<EFBFBD><4E><EFBFBD>[<5B><><EFBFBD>`<60><>(Scanline 1<>`239)
|
|||
|
if( bDraw ) {
|
|||
|
ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
|
|||
|
ppu->ScanlineNext();
|
|||
|
EmulationCPU( FETCH_CYCLES*10 );
|
|||
|
mapper->HSync( scanline );
|
|||
|
EmulationCPU( FETCH_CYCLES*22 );
|
|||
|
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();
|
|||
|
EmulationCPU( FETCH_CYCLES*10 );
|
|||
|
mapper->HSync( scanline );
|
|||
|
EmulationCPU( FETCH_CYCLES*22 );
|
|||
|
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();
|
|||
|
EmulationCPU( FETCH_CYCLES*10 );
|
|||
|
mapper->HSync( scanline );
|
|||
|
EmulationCPU( FETCH_CYCLES*22 );
|
|||
|
ppu->ScanlineStart();
|
|||
|
EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
|
|||
|
} else {
|
|||
|
///////--- EmulationCPU( nescfg->HDrawCycles );
|
|||
|
ppu->Scanline( scanline, Config.graphics.bAllSprite, Config.graphics.bLeftClip );
|
|||
|
ppu->ScanlineNext();
|
|||
|
EmulationCPU( FETCH_CYCLES*10 );
|
|||
|
mapper->HSync( scanline );
|
|||
|
EmulationCPU( FETCH_CYCLES*22 );
|
|||
|
ppu->ScanlineStart();
|
|||
|
EmulationCPU( FETCH_CYCLES*10+nescfg->ScanlineEndCycles );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else if( scanline == 240 ) {
|
|||
|
// <20>_<EFBFBD>~<7E>[<5B>X<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><43> (Scanline 240)
|
|||
|
mapper->VSync();
|
|||
|
|
|||
|
EmulationCPU( nescfg->HDrawCycles );
|
|||
|
// H-Sync
|
|||
|
mapper->HSync( scanline );
|
|||
|
|
|||
|
EmulationCPU( nescfg->HBlankCycles );
|
|||
|
} else if( scanline <= nescfg->TotalScanlines-1 ) {
|
|||
|
pad->VSync();
|
|||
|
|
|||
|
// VBLANK<4E><4B><EFBFBD><EFBFBD>
|
|||
|
if( scanline == nescfg->TotalScanlines-1 ) {
|
|||
|
ppu->VBlankEnd();
|
|||
|
}
|
|||
|
if( scanline == nescfg->VBlankLine ) {
|
|||
|
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 );
|
|||
|
|
|||
|
// <20><><EFBFBD>S<EFBFBD><EFBFBD><CE8D><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˂Ă<CB82><C482><EFBFBD><EFBFBD>ă<EFBFBD><C483>[<5B>v<EFBFBD><76>(1<>b<EFBFBD><62>)
|
|||
|
for( INT i = 0; i < nescfg->TotalScanlines*60; i++ ) {
|
|||
|
EmulationCPU( nescfg->ScanlineCycles );
|
|||
|
cpu->GetContext( reg );
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>[<5B>v<EFBFBD>ɓ<EFBFBD><C993><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƃ<EFBFBD><C682>m<EFBFBD>F<EFBFBD><46><EFBFBD><EFBFBD><EFBFBD>甲<EFBFBD><E794B2><EFBFBD><EFBFBD>
|
|||
|
if( reg.PC == 0x4700 ) {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
m_bNsfInit = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
cpu->GetContext( reg );
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>[<5B>v<EFBFBD>ɓ<EFBFBD><C993><EFBFBD><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Đݒ肷<DD92><E882B7>
|
|||
|
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; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>[<5B>v
|
|||
|
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 mapper->Read( addr );
|
|||
|
}
|
|||
|
|
|||
|
return 0x00; // Warning<6E>\<5C>h
|
|||
|
}
|
|||
|
|
|||
|
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&0xE01F, 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:
|
|||
|
if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
return mapper->ReadExAPU(addr);
|
|||
|
return apu->Read( addr );
|
|||
|
break;
|
|||
|
case 0x15:
|
|||
|
if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
return mapper->ReadExAPU(addr);
|
|||
|
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(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
return mapper->ReadExAPU(addr);
|
|||
|
if( rom->IsVSUNISYSTEM() ) {
|
|||
|
return pad->Read( addr );
|
|||
|
} else {
|
|||
|
return pad->Read( addr ) | apu->Read( addr );
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
if((NES_ROM_get_unifBoardID(rom->GetBoardName())==643)&&(addr<0x4040))
|
|||
|
return mapper->ReadExAPU(addr);
|
|||
|
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;
|
|||
|
if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
mapper->WriteExAPU(addr,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;
|
|||
|
case 0x17:
|
|||
|
CPUREG[addr & 0xFF] = data;
|
|||
|
pad->Write( addr, data );
|
|||
|
apu->Write( addr, data );
|
|||
|
if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
mapper->WriteExAPU(addr,data);
|
|||
|
break;
|
|||
|
// VirtuaNES<45>ŗL<C597>|<7C>[<5B>g
|
|||
|
case 0x18:
|
|||
|
apu->Write( addr, data );
|
|||
|
// if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
// mapper->WriteExAPU(addr,data);
|
|||
|
break;
|
|||
|
#if 0
|
|||
|
case 0x1C:
|
|||
|
m_dwProfileTempCycle = cpu->GetTotalCycles();
|
|||
|
if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
mapper->WriteExAPU(addr,data);
|
|||
|
break;
|
|||
|
case 0x1D:
|
|||
|
m_dwProfileCycle = cpu->GetTotalCycles()-m_dwProfileTempCycle-4;
|
|||
|
m_dwProfileTotalCycle += m_dwProfileCycle;
|
|||
|
m_dwProfileTotalCount++;
|
|||
|
if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
mapper->WriteExAPU(addr,data);
|
|||
|
break;
|
|||
|
case 0x1E:
|
|||
|
m_dwProfileTotalCount = 0;
|
|||
|
m_dwProfileTotalCycle = 0;
|
|||
|
m_dwTotalTempCycle = cpu->GetTotalCycles();
|
|||
|
if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
mapper->WriteExAPU(addr,data);
|
|||
|
break;
|
|||
|
case 0x1F:
|
|||
|
m_dwTotalCycle = cpu->GetTotalCycles()-m_dwTotalTempCycle-4;
|
|||
|
if(NES_ROM_get_unifBoardID(rom->GetBoardName())==643)
|
|||
|
mapper->WriteExAPU(addr,data);
|
|||
|
break;
|
|||
|
#endif
|
|||
|
default:
|
|||
|
mapper->ExWrite( addr, data );
|
|||
|
if((NES_ROM_get_unifBoardID(rom->GetBoardName())==643)&&(addr<0x4040))
|
|||
|
mapper->WriteExAPU(addr,data);
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::LoadSRAM()
|
|||
|
{
|
|||
|
if( rom->IsNSF() )
|
|||
|
return;
|
|||
|
|
|||
|
ZEROMEMORY( WRAM, sizeof(WRAM) );
|
|||
|
|
|||
|
if( !rom->IsSAVERAM() )
|
|||
|
return;
|
|||
|
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.bSavePath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szSavePath );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "sav" );
|
|||
|
DEBUGOUT( "Path: %s\n", tempstr.c_str() );
|
|||
|
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "rb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "Loading SAVERAM..." );
|
|||
|
|
|||
|
LONG size;
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>T<EFBFBD>C<EFBFBD>Y<EFBFBD>擾
|
|||
|
::fseek( fp, 0, SEEK_END );
|
|||
|
size = ftell( fp );
|
|||
|
::fseek( fp, 0, SEEK_SET );
|
|||
|
if( size <= 128*1024 ) {
|
|||
|
if( ::fread( WRAM, size, 1, fp ) != 1 )
|
|||
|
throw "File Read error.";
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
DEBUGOUT( "Loading SAVERAM Error.\n" );
|
|||
|
DEBUGOUT( "%s\n", str );
|
|||
|
// throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
DEBUGOUT( "Loading SAVERAM Error.\n" );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::SaveSRAM()
|
|||
|
{
|
|||
|
INT i;
|
|||
|
|
|||
|
if( rom->IsNSF() )
|
|||
|
return;
|
|||
|
|
|||
|
if( !rom->IsSAVERAM() )
|
|||
|
return;
|
|||
|
|
|||
|
for( i = 0; i < SAVERAM_SIZE; i++ ) {
|
|||
|
if( WRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if( i < SAVERAM_SIZE ) {
|
|||
|
DEBUGOUT( "Saving SAVERAM...\n" );
|
|||
|
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.bSavePath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szSavePath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "sav" );
|
|||
|
DEBUGOUT( "Path: %s\n", tempstr.c_str() );
|
|||
|
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
if( ::fwrite( WRAM, SAVERAM_SIZE, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DEBUGOUT( "Writing SAVERAM Error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
DEBUGOUT( "Writing SAVERAM Error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::LoadDISK()
|
|||
|
{
|
|||
|
if( rom->GetMapperNo() != 20 )
|
|||
|
return;
|
|||
|
|
|||
|
BOOL bExit = FALSE;
|
|||
|
|
|||
|
INT i, j, diskno;
|
|||
|
FILE* fp = NULL;
|
|||
|
DISKIMGFILEHDR ifh;
|
|||
|
DISKIMGHDR hdr;
|
|||
|
LPBYTE disk;
|
|||
|
|
|||
|
WORD Version;
|
|||
|
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.bSavePath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szSavePath );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "dsv" );
|
|||
|
DEBUGOUT( "Path: %s\n", tempstr.c_str() );
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "rb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
if( ::fread( &ifh, sizeof(DISKIMGFILEHDR), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
if( ::memcmp( ifh.ID, "VirtuaNES DI", sizeof(ifh.ID) ) == 0 ) {
|
|||
|
if( ifh.BlockVersion < 0x0100 && ifh.BlockVersion > 0x200 ) {
|
|||
|
// <20><><EFBFBD>Ή<EFBFBD><CE89>`<60><><EFBFBD>ł<EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNSUPPORTFORMAT );
|
|||
|
}
|
|||
|
Version = ifh.BlockVersion;
|
|||
|
} else {
|
|||
|
// <20><><EFBFBD>Ή<EFBFBD><CE89>`<60><><EFBFBD>ł<EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNSUPPORTFORMAT );
|
|||
|
}
|
|||
|
|
|||
|
if( Version == 0x0100 ) {
|
|||
|
// Ver0.24<EFBFBD>ȑO
|
|||
|
if( ifh.DiskNumber > 4 ) {
|
|||
|
// <20><><EFBFBD>Ή<EFBFBD><CE89>`<60><><EFBFBD>ł<EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNSUPPORTFORMAT );
|
|||
|
}
|
|||
|
|
|||
|
for( i = 0; i < (INT)ifh.DiskNumber; i++ ) {
|
|||
|
if( ::fread( &hdr, sizeof(DISKIMGHDR), 1, fp ) != 1 ) {
|
|||
|
if( i == 0 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
} else {
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if( ::memcmp( hdr.ID, "SIDE0A", sizeof(hdr.ID) ) == 0 ) {
|
|||
|
diskno = 0;
|
|||
|
} else if( ::memcmp( hdr.ID, "SIDE0B", sizeof(hdr.ID) ) == 0 ) {
|
|||
|
diskno = 1;
|
|||
|
} else if( ::memcmp( hdr.ID, "SIDE1A", sizeof(hdr.ID) ) == 0 ) {
|
|||
|
diskno = 2;
|
|||
|
} else if( ::memcmp( hdr.ID, "SIDE1B", sizeof(hdr.ID) ) == 0 ) {
|
|||
|
diskno = 3;
|
|||
|
} else {
|
|||
|
// <20><><EFBFBD>Ή<EFBFBD><CE89>`<60><><EFBFBD>ł<EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNSUPPORTFORMAT );
|
|||
|
}
|
|||
|
|
|||
|
for( j = 0; j < 16; j++ ) {
|
|||
|
if( hdr.DiskTouch[j] ) {
|
|||
|
disk = rom->GetPROM()+16+65500*diskno+(4*1024)*j;
|
|||
|
if( j < 15 ) {
|
|||
|
if( ::fread( disk, 4*1024, 1, fp ) != 1 ) {
|
|||
|
bExit = TRUE;
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
} else {
|
|||
|
if( ::fread( disk, 4*1024-36, 1, fp ) != 1 ) {
|
|||
|
bExit = TRUE;
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else
|
|||
|
if( Version == 0x0200 || Version == 0x0210 ) {
|
|||
|
// Ver0.30<EFBFBD>ȍ~
|
|||
|
DISKFILEHDR dfh;
|
|||
|
LPBYTE lpDisk = rom->GetPROM();
|
|||
|
LPBYTE lpWrite = rom->GetDISK();
|
|||
|
LONG DiskSize = 16+65500*rom->GetDiskNo();
|
|||
|
DWORD pos;
|
|||
|
BYTE data;
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FLAG<41><47><EFBFBD><EFBFBD>
|
|||
|
::ZeroMemory( lpWrite, 16+65500*rom->GetDiskNo() );
|
|||
|
|
|||
|
// <20>w<EFBFBD>b<EFBFBD>_<EFBFBD>ǂݒ<C782><DD92><EFBFBD>
|
|||
|
if( ::fseek( fp, 0, SEEK_SET ) ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
if( ::fread( &dfh, sizeof(DISKFILEHDR), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
if( Config.emulator.bCrcCheck ) {
|
|||
|
// <20><><EFBFBD>݃<EFBFBD><DD83>[<5B>h<EFBFBD><68><EFBFBD>̃^<5E>C<EFBFBD>g<EFBFBD><67><EFBFBD>ƈႤ<C688><E182A4><EFBFBD><EFBFBD><EFBFBD>`<60>F<EFBFBD>b<EFBFBD>N
|
|||
|
if( dfh.ProgID != rom->GetGameID()
|
|||
|
|| dfh.MakerID != (WORD)rom->GetMakerID()
|
|||
|
|| dfh.DiskNo != (WORD)rom->GetDiskNo() ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for( i = 0; i < dfh.DifferentSize; i++ ) {
|
|||
|
if( ::fread( &pos, sizeof(DWORD), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
bExit = TRUE;
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
data = (BYTE)(pos>>24);
|
|||
|
pos &= 0x00FFFFFF;
|
|||
|
if( pos >= 16 && pos < DiskSize ) {
|
|||
|
lpDisk[pos] = data;
|
|||
|
lpWrite[pos] = 0xFF;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
DEBUGOUT( "%s\n", str );
|
|||
|
if( bExit )
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
DEBUGOUT( "Loading DISKIMAGE Error.\n" );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::SaveDISK()
|
|||
|
{
|
|||
|
if( rom->GetMapperNo() != 20 )
|
|||
|
return;
|
|||
|
|
|||
|
INT i;
|
|||
|
FILE* fp = NULL;
|
|||
|
DISKFILEHDR ifh;
|
|||
|
LPBYTE lpDisk = rom->GetPROM();
|
|||
|
LPBYTE lpWrite = rom->GetDISK();
|
|||
|
LONG DiskSize = 16+65500*rom->GetDiskNo();
|
|||
|
DWORD data;
|
|||
|
|
|||
|
try
|
|||
|
{
|
|||
|
::ZeroMemory( &ifh, sizeof(ifh) );
|
|||
|
|
|||
|
::memcpy( ifh.ID, "VirtuaNES DI", sizeof(ifh.ID) );
|
|||
|
ifh.BlockVersion = 0x0210;
|
|||
|
ifh.ProgID = rom->GetGameID();
|
|||
|
ifh.MakerID = (WORD)rom->GetMakerID();
|
|||
|
ifh.DiskNo = (WORD)rom->GetDiskNo();
|
|||
|
|
|||
|
// <20><><EFBFBD>ᐔ<EFBFBD><E19094><EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g
|
|||
|
for( i = 16; i < DiskSize; i++ ) {
|
|||
|
if( lpWrite[i] )
|
|||
|
ifh.DifferentSize++;
|
|||
|
}
|
|||
|
|
|||
|
if( !ifh.DifferentSize )
|
|||
|
return;
|
|||
|
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.bSavePath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szSavePath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "dsv" );
|
|||
|
DEBUGOUT( "Path: %s\n", tempstr.c_str() );
|
|||
|
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
::wsprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
if( ::fwrite( &ifh, sizeof(DISKFILEHDR), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
DEBUGOUT( "%s\n", str );
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
DEBUGOUT( "Saving DISKIMAGE Error.\n" );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::LoadTurboFile()
|
|||
|
{
|
|||
|
ZEROMEMORY( ERAM, sizeof(ERAM) );
|
|||
|
|
|||
|
if( pad->GetExController() != PAD::EXCONTROLLER_TURBOFILE )
|
|||
|
return;
|
|||
|
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.bSavePath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szSavePath );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), "TurboFile", "vtf" );
|
|||
|
DEBUGOUT( "Path: %s\n", tempstr.c_str() );
|
|||
|
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "rb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "Loading TURBOFILE..." );
|
|||
|
|
|||
|
LONG size;
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>T<EFBFBD>C<EFBFBD>Y<EFBFBD>擾
|
|||
|
::fseek( fp, 0, SEEK_END );
|
|||
|
size = ftell( fp );
|
|||
|
::fseek( fp, 0, SEEK_SET );
|
|||
|
if( size > 32*1024 ) {
|
|||
|
size = 32*1024;
|
|||
|
}
|
|||
|
if( ::fread( ERAM, size, 1, fp ) != 1 )
|
|||
|
throw "File Read error.";
|
|||
|
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
DEBUGOUT( "Loading TurboFile Error.\n" );
|
|||
|
DEBUGOUT( "%s\n", str );
|
|||
|
// throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
DEBUGOUT( "Loading TurboFile Error.\n" );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::SaveTurboFile()
|
|||
|
{
|
|||
|
INT i;
|
|||
|
|
|||
|
if( pad->GetExController() != PAD::EXCONTROLLER_TURBOFILE )
|
|||
|
return;
|
|||
|
|
|||
|
for( i = 0; i < sizeof(ERAM); i++ ) {
|
|||
|
if( ERAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
if( i < sizeof(ERAM) ) {
|
|||
|
DEBUGOUT( "Saving TURBOFILE...\n" );
|
|||
|
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.bSavePath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szSavePath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), "TurboFile", "vtf" );
|
|||
|
DEBUGOUT( "Path: %s\n", tempstr.c_str() );
|
|||
|
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
if( ::fwrite( ERAM, sizeof(ERAM), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "Ok.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DEBUGOUT( "Writing TurboFile Error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
DEBUGOUT( "Writing TurboFile Error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
INT NES::IsStateFile( const char* fname, ROM* rom )
|
|||
|
{
|
|||
|
FILE* fp = NULL;
|
|||
|
FILEHDR2 header;
|
|||
|
|
|||
|
if( !(fp = ::fopen( fname, "rb" )) )
|
|||
|
return -1;
|
|||
|
|
|||
|
if( ::fread( &header, sizeof(header), 1, fp ) != 1 ) {
|
|||
|
FCLOSE( fp );
|
|||
|
return -1;
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
|
|||
|
if( ::memcmp( header.ID, "VirtuaNES ST", sizeof(header.ID) ) == 0 ) {
|
|||
|
if( header.BlockVersion < 0x0100 )
|
|||
|
return 0;
|
|||
|
|
|||
|
if( Config.emulator.bCrcCheck ) {
|
|||
|
if( header.BlockVersion >= 0x200 ) {
|
|||
|
if( rom->GetMapperNo() != 20 ) {
|
|||
|
// FDS<44>ȊO
|
|||
|
if( header.Ext0 != rom->GetPROM_CRC() ) {
|
|||
|
return IDS_ERROR_ILLEGALSTATECRC; // <20>Ⴄ<EFBFBD><E182A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
} else {
|
|||
|
// FDS
|
|||
|
if( header.Ext0 != rom->GetGameID() ||
|
|||
|
header.Ext1 != (WORD)rom->GetMakerID() ||
|
|||
|
header.Ext2 != (WORD)rom->GetDiskNo() )
|
|||
|
return IDS_ERROR_ILLEGALSTATECRC; // <20>Ⴄ<EFBFBD><E182A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
return 0;
|
|||
|
}
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::LoadState( const char* fname )
|
|||
|
{
|
|||
|
FILE* fp = NULL;
|
|||
|
BOOL bRet = FALSE;
|
|||
|
|
|||
|
if( rom->IsNSF() )
|
|||
|
return TRUE;
|
|||
|
|
|||
|
try {
|
|||
|
if( !(fp = ::fopen( fname, "rb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, fname );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
bRet = ReadState( fp );
|
|||
|
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DEBUGOUT( "State load error.\n" );
|
|||
|
DEBUGOUT( "%s\n", str );
|
|||
|
FCLOSE( fp );
|
|||
|
return FALSE;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
DEBUGOUT( "State load error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
return bRet;
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::SaveState( const char* fname )
|
|||
|
{
|
|||
|
FILE* fp = NULL;
|
|||
|
|
|||
|
if( rom->IsNSF() )
|
|||
|
return TRUE;
|
|||
|
|
|||
|
try {
|
|||
|
if( !(fp = ::fopen( fname, "wb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, fname );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
WriteState( fp );
|
|||
|
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DEBUGOUT( "State save error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
DEBUGOUT( "State save error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::ReadState( FILE* fp )
|
|||
|
{
|
|||
|
INT i;
|
|||
|
BOOL bHeader = FALSE;
|
|||
|
WORD Version = 0;
|
|||
|
|
|||
|
BLOCKHDR hdr;
|
|||
|
INT type;
|
|||
|
|
|||
|
while( TRUE ) {
|
|||
|
// Read File
|
|||
|
if( ::fread( &hdr, sizeof(BLOCKHDR), 1, fp ) != 1 )
|
|||
|
break;
|
|||
|
|
|||
|
// File Header check
|
|||
|
if( !bHeader ) {
|
|||
|
LPFILEHDR fh = (LPFILEHDR)&hdr;
|
|||
|
if( ::memcmp( fh->ID, "VirtuaNES ST", sizeof(fh->ID) ) == 0 ) {
|
|||
|
Version = fh->BlockVersion;
|
|||
|
if( Version == 0x0100 ) {
|
|||
|
// Ver0.24<EFBFBD>܂<EFBFBD>
|
|||
|
bHeader = TRUE;
|
|||
|
// <20>Â<EFBFBD><C382>z<EFBFBD>̓<EFBFBD><CD83>[<5B>r<EFBFBD>[<5B><><EFBFBD>̓<EFBFBD><CD83>[<5B>h<EFBFBD>o<EFBFBD><6F><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
if( m_bMoviePlay ) {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
// <20>Â<EFBFBD><C382>z<EFBFBD><7A>FDS<44>̓<EFBFBD><CD83>[<5B>h<EFBFBD>o<EFBFBD><6F><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
if( rom->GetMapperNo() == 20 ) {
|
|||
|
// <20><><EFBFBD>Ή<EFBFBD><CE89>`<60><><EFBFBD>ł<EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNSUPPORTFORMAT );
|
|||
|
}
|
|||
|
} else
|
|||
|
if( Version == 0x0200 || Version == 0x0210 ) {
|
|||
|
// Ver0.30<EFBFBD>ȍ~ Ver0.60<EFBFBD>ȍ~
|
|||
|
FILEHDR2 hdr2;
|
|||
|
// <20>w<EFBFBD>b<EFBFBD>_<EFBFBD><5F><EFBFBD>ǂݒ<C782><DD92><EFBFBD>
|
|||
|
if( ::fseek( fp, -sizeof(BLOCKHDR), SEEK_CUR ) ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
// Read File
|
|||
|
if( ::fread( &hdr2, sizeof(FILEHDR2), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
#if 0
|
|||
|
if( Config.emulator.bCrcCheck ) {
|
|||
|
// <20><><EFBFBD>݃<EFBFBD><DD83>[<5B>h<EFBFBD><68><EFBFBD>̃^<5E>C<EFBFBD>g<EFBFBD><67><EFBFBD>ƈႤ<C688><E182A4><EFBFBD><EFBFBD><EFBFBD>`<60>F<EFBFBD>b<EFBFBD>N
|
|||
|
if( rom->GetMapperNo() != 20 ) {
|
|||
|
// FDS<44>ȊO
|
|||
|
if( hdr2.Ext0 != rom->GetPROM_CRC() ) {
|
|||
|
return FALSE; // <20>Ⴄ<EFBFBD><E182A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
} else {
|
|||
|
// FDS
|
|||
|
if( hdr2.Ext0 != rom->GetGameID() ||
|
|||
|
hdr2.Ext1 != (WORD)rom->GetMakerID() ||
|
|||
|
hdr2.Ext2 != (WORD)rom->GetDiskNo() )
|
|||
|
return FALSE; // <20>Ⴄ<EFBFBD><E182A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
// <20><><EFBFBD>[<5B>r<EFBFBD>[<5B><><EFBFBD>̓t<CD83>@<40>C<EFBFBD><43><EFBFBD>|<7C>C<EFBFBD><43><EFBFBD>^<5E>ƃX<C683>e<EFBFBD>b<EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD>
|
|||
|
// <20>ύX<CF8D><58><EFBFBD>āC<C481><43><EFBFBD>[<5B>r<EFBFBD>[<5B><><EFBFBD>L<EFBFBD>^<5E><><EFBFBD>[<5B>h<EFBFBD>ɕύX
|
|||
|
if( m_bMoviePlay || m_bMovieRec ) {
|
|||
|
// <20>B<EFBFBD>蒼<EFBFBD><E892BC><EFBFBD>\<5C>H
|
|||
|
if( m_hedMovie.Control & 0x80 ) {
|
|||
|
if( hdr2.MovieOffset && hdr2.MovieStep ) {
|
|||
|
if( m_bMoviePlay ) {
|
|||
|
// <20>Đ<EFBFBD><C490><EFBFBD>
|
|||
|
// <20>X<EFBFBD>e<EFBFBD>[<5B>g<EFBFBD>̃X<CC83>e<EFBFBD>b<EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD>L<EFBFBD>^<5E><><EFBFBD><EFBFBD><EFBFBD>i<EFBFBD><69><EFBFBD>ł<EFBFBD><C582><EFBFBD><EFBFBD>_<EFBFBD><5F>
|
|||
|
if( hdr2.MovieStep > m_hedMovie.MovieStep )
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
// <20>L<EFBFBD>^<5E><>
|
|||
|
// <20>X<EFBFBD>e<EFBFBD>[<5B>g<EFBFBD>̃X<CC83>e<EFBFBD>b<EFBFBD>v<EFBFBD><76><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂<EFBFBD><DD82><EFBFBD><EFBFBD>i<EFBFBD><69><EFBFBD>ł<EFBFBD><C582><EFBFBD><EFBFBD>_<EFBFBD><5F>
|
|||
|
if( hdr2.MovieStep > m_MovieStep )
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
//DEBUGOUT( "LD STEP=%d POS=%d\n", hdr2.MovieStep, hdr2.MovieOffset );
|
|||
|
|
|||
|
m_bMoviePlay = FALSE;
|
|||
|
m_bMovieRec = TRUE;
|
|||
|
m_MovieStep = hdr2.MovieStep;
|
|||
|
m_hedMovie.RecordTimes++; // <20>B<EFBFBD>蒼<EFBFBD><E892BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>+1
|
|||
|
if( ::fseek( m_fpMovie, hdr2.MovieOffset, SEEK_SET ) ) {
|
|||
|
//DEBUGOUT( "MOVIE:STATE LOAD SEEK <20><><EFBFBD>s\n" );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
} else {
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
bHeader = TRUE;
|
|||
|
continue;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if( !bHeader ) {
|
|||
|
// <20><><EFBFBD>Ή<EFBFBD><CE89>`<60><><EFBFBD>ł<EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNSUPPORTFORMAT );
|
|||
|
}
|
|||
|
|
|||
|
//DEBUGOUT( "HEADER ID=%8s\n", hdr.ID );
|
|||
|
|
|||
|
type = -1;
|
|||
|
if( ::memcmp( hdr.ID, "REG DATA", sizeof(hdr.ID) ) == 0 )
|
|||
|
type = 0;
|
|||
|
if( ::memcmp( hdr.ID, "RAM DATA", sizeof(hdr.ID) ) == 0 )
|
|||
|
type = 1;
|
|||
|
if( ::memcmp( hdr.ID, "MMU DATA", sizeof(hdr.ID) ) == 0 )
|
|||
|
type = 2;
|
|||
|
if( ::memcmp( hdr.ID, "MMC DATA", sizeof(hdr.ID) ) == 0 )
|
|||
|
type = 3;
|
|||
|
if( ::memcmp( hdr.ID, "CTR DATA", sizeof(hdr.ID) ) == 0 )
|
|||
|
type = 4;
|
|||
|
if( ::memcmp( hdr.ID, "SND DATA", sizeof(hdr.ID) ) == 0 )
|
|||
|
type = 5;
|
|||
|
|
|||
|
if( rom->GetMapperNo() == 20 ) {
|
|||
|
if( ::memcmp( hdr.ID, "DISKDATA", sizeof(hdr.ID) ) == 0 )
|
|||
|
type = 6;
|
|||
|
}
|
|||
|
|
|||
|
if( type == -1 ) {
|
|||
|
//DEBUGOUT( "UNKNOWN HEADER ID=%8s\n", hdr.ID );
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
switch( type ) {
|
|||
|
case 0:
|
|||
|
// REGISTER STATE
|
|||
|
{
|
|||
|
if( hdr.BlockVersion < 0x0200 ) {
|
|||
|
REGSTAT_O reg;
|
|||
|
if( ::fread( ®, sizeof(REGSTAT_O), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
// LOAD CPU STATE
|
|||
|
R6502 R;
|
|||
|
R.PC = reg.cpureg.cpu.PC;
|
|||
|
R.A = reg.cpureg.cpu.A;
|
|||
|
R.X = reg.cpureg.cpu.X;
|
|||
|
R.Y = reg.cpureg.cpu.Y;
|
|||
|
R.S = reg.cpureg.cpu.S;
|
|||
|
R.P = reg.cpureg.cpu.P;
|
|||
|
R.INT_pending = reg.cpureg.cpu.I;
|
|||
|
cpu->SetContext( R );
|
|||
|
// FrameIRQ = reg.cpureg.cpu.FrameIRQ;
|
|||
|
|
|||
|
if( hdr.BlockVersion < 0x0110 ) {
|
|||
|
emul_cycles = 0;
|
|||
|
base_cycles = reg.cpureg.cpu.mod_cycles;
|
|||
|
} else if( hdr.BlockVersion == 0x0110 ) {
|
|||
|
// FrameIRQ_cycles = reg.cpureg.cpu.mod_cycles;
|
|||
|
emul_cycles = reg.cpureg.cpu.emul_cycles;
|
|||
|
base_cycles = reg.cpureg.cpu.base_cycles;
|
|||
|
}
|
|||
|
|
|||
|
// LOAD PPU STATE
|
|||
|
PPUREG[0] = reg.ppureg.ppu.reg0;
|
|||
|
PPUREG[1] = reg.ppureg.ppu.reg1;
|
|||
|
PPUREG[2] = reg.ppureg.ppu.reg2;
|
|||
|
PPUREG[3] = reg.ppureg.ppu.reg3;
|
|||
|
PPU7_Temp = reg.ppureg.ppu.reg7;
|
|||
|
loopy_t = reg.ppureg.ppu.loopy_t;
|
|||
|
loopy_v = reg.ppureg.ppu.loopy_v;
|
|||
|
loopy_x = reg.ppureg.ppu.loopy_x;
|
|||
|
PPU56Toggle = reg.ppureg.ppu.toggle56;
|
|||
|
} else {
|
|||
|
REGSTAT reg;
|
|||
|
if( ::fread( ®, sizeof(REGSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
// LOAD CPU STATE
|
|||
|
R6502 R;
|
|||
|
R.PC = reg.cpureg.cpu.PC;
|
|||
|
R.A = reg.cpureg.cpu.A;
|
|||
|
R.X = reg.cpureg.cpu.X;
|
|||
|
R.Y = reg.cpureg.cpu.Y;
|
|||
|
R.S = reg.cpureg.cpu.S;
|
|||
|
R.P = reg.cpureg.cpu.P;
|
|||
|
R.INT_pending = reg.cpureg.cpu.I;
|
|||
|
cpu->SetContext( R );
|
|||
|
|
|||
|
if( hdr.BlockVersion == 0x0200 ) {
|
|||
|
// FrameIRQ = reg.cpureg.cpu.FrameIRQ;
|
|||
|
// bFrameIRQ_occur = (reg.cpureg.cpu.FrameIRQ_occur!=0)?TRUE:FALSE;
|
|||
|
// FrameIRQ_cycles = reg.cpureg.cpu.FrameIRQ_cycles;
|
|||
|
} else {
|
|||
|
apu->SetFrameIRQ( reg.cpureg.cpu.FrameIRQ_cycles,
|
|||
|
reg.cpureg.cpu.FrameIRQ_count,
|
|||
|
reg.cpureg.cpu.FrameIRQ_type,
|
|||
|
reg.cpureg.cpu.FrameIRQ,
|
|||
|
reg.cpureg.cpu.FrameIRQ_occur );
|
|||
|
}
|
|||
|
|
|||
|
emul_cycles = reg.cpureg.cpu.emul_cycles;
|
|||
|
base_cycles = reg.cpureg.cpu.base_cycles;
|
|||
|
|
|||
|
cpu->SetDmaCycles( (INT)reg.cpureg.cpu.DMA_cycles );
|
|||
|
|
|||
|
// LOAD PPU STATE
|
|||
|
PPUREG[0] = reg.ppureg.ppu.reg0;
|
|||
|
PPUREG[1] = reg.ppureg.ppu.reg1;
|
|||
|
PPUREG[2] = reg.ppureg.ppu.reg2;
|
|||
|
PPUREG[3] = reg.ppureg.ppu.reg3;
|
|||
|
PPU7_Temp = reg.ppureg.ppu.reg7;
|
|||
|
loopy_t = reg.ppureg.ppu.loopy_t;
|
|||
|
loopy_v = reg.ppureg.ppu.loopy_v;
|
|||
|
loopy_x = reg.ppureg.ppu.loopy_x;
|
|||
|
PPU56Toggle = reg.ppureg.ppu.toggle56;
|
|||
|
}
|
|||
|
|
|||
|
// APU STATE
|
|||
|
// <20>L<EFBFBD><4C><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
apu->QueueClear();
|
|||
|
|
|||
|
// APU<50>X<EFBFBD>e<EFBFBD>[<5B>g<EFBFBD><67><EFBFBD>ۑ<EFBFBD><DB91><EFBFBD><EFBFBD><EFBFBD><EFBFBD>悤<EFBFBD>ɂ<EFBFBD><C982><EFBFBD><EFBFBD>̂Ń<CC82><C583><EFBFBD>
|
|||
|
// // DMC<4D>͎~<7E>߂Ȃ<DF82><C882>Ƃ܂<C682><DC82><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>N<EFBFBD><4E><EFBFBD><EFBFBD>
|
|||
|
// for( i = 0x4010; i <= 0x4013; i++ ) {
|
|||
|
// apu->Write( i, 0 );
|
|||
|
// }
|
|||
|
}
|
|||
|
break;
|
|||
|
case 1:
|
|||
|
// RAM STATE
|
|||
|
{
|
|||
|
RAMSTAT ram;
|
|||
|
if( ::fread( &ram, sizeof(RAMSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
::memcpy( RAM, ram.RAM, sizeof(ram.RAM) );
|
|||
|
::memcpy( BGPAL, ram.BGPAL, sizeof(ram.BGPAL) );
|
|||
|
::memcpy( SPPAL, ram.SPPAL, sizeof(ram.SPPAL) );
|
|||
|
::memcpy( SPRAM, ram.SPRAM, sizeof(ram.SPRAM) );
|
|||
|
if( rom->IsSAVERAM() ) {
|
|||
|
if( ::fread( WRAM, SAVERAM_SIZE, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case 2:
|
|||
|
// BANK STATE
|
|||
|
{
|
|||
|
MMUSTAT mmu;
|
|||
|
if( ::fread( &mmu, sizeof(MMUSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
if( hdr.BlockVersion == 0x100 ) {
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƑO<C691>̃o<CC83>[<5B>W<EFBFBD><57><EFBFBD><EFBFBD>
|
|||
|
if( mmu.CPU_MEM_TYPE[3] == BANKTYPE_RAM
|
|||
|
|| mmu.CPU_MEM_TYPE[3] == BANKTYPE_DRAM ) {
|
|||
|
if( ::fread( CPU_MEM_BANK[3], 8*1024, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
} else if( !rom->IsSAVERAM() ) {
|
|||
|
SetPROM_8K_Bank( 3, mmu.CPU_MEM_PAGE[3] );
|
|||
|
}
|
|||
|
// <20>o<EFBFBD><6F><EFBFBD>N0<4E>`3<>ȊO<C88A><4F><EFBFBD>[<5B>h
|
|||
|
for( i = 4; i < 8; i++ ) {
|
|||
|
CPU_MEM_TYPE[i] = mmu.CPU_MEM_TYPE[i];
|
|||
|
CPU_MEM_PAGE[i] = mmu.CPU_MEM_PAGE[i];
|
|||
|
if( CPU_MEM_TYPE[i] == BANKTYPE_ROM ) {
|
|||
|
SetPROM_8K_Bank( i, CPU_MEM_PAGE[i] );
|
|||
|
} else {
|
|||
|
if( ::fread( CPU_MEM_BANK[i], 8*1024, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
} else if( hdr.BlockVersion == 0x200 ) {
|
|||
|
// <20>ŐV<C590>o<EFBFBD>[<5B>W<EFBFBD><57><EFBFBD><EFBFBD>
|
|||
|
// SRAM<41><4D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>S<EFBFBD><53><EFBFBD><EFBFBD><EFBFBD>[<5B>h<EFBFBD><68><EFBFBD>Ȃ<EFBFBD><C882><EFBFBD>
|
|||
|
for( i = 3; i < 8; i++ ) {
|
|||
|
CPU_MEM_TYPE[i] = mmu.CPU_MEM_TYPE[i];
|
|||
|
CPU_MEM_PAGE[i] = mmu.CPU_MEM_PAGE[i];
|
|||
|
if( CPU_MEM_TYPE[i] == BANKTYPE_ROM ) {
|
|||
|
SetPROM_8K_Bank( i, CPU_MEM_PAGE[i] );
|
|||
|
} else {
|
|||
|
if( ::fread( CPU_MEM_BANK[i], 8*1024, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// VRAM
|
|||
|
if( ::fread( VRAM, 4*1024, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
// CRAM
|
|||
|
for( i = 0; i < 8; i++ ) {
|
|||
|
if( mmu.CRAM_USED[i] != 0 ) {
|
|||
|
if( ::fread( &CRAM[0x1000*i], 4*1024, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// BANK
|
|||
|
for( i = 0; i < 12; i++ ) {
|
|||
|
if( mmu.PPU_MEM_TYPE[i] == BANKTYPE_VROM ) {
|
|||
|
//SetCRAM_1K_Bank( i, mmu.PPU_MEM_PAGE[i] );
|
|||
|
SetVROM_1K_Bank( i, mmu.PPU_MEM_PAGE[i] );
|
|||
|
} else if( mmu.PPU_MEM_TYPE[i] == BANKTYPE_CRAM ) {
|
|||
|
SetCRAM_1K_Bank( i, mmu.PPU_MEM_PAGE[i] );
|
|||
|
} else if( mmu.PPU_MEM_TYPE[i] == BANKTYPE_VRAM ) {
|
|||
|
SetVRAM_1K_Bank( i, mmu.PPU_MEM_PAGE[i] );
|
|||
|
} else {
|
|||
|
throw "Unknown bank types.";
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// for mapper 74
|
|||
|
if(ppu->IsVromWrite()){
|
|||
|
int cb = 0;
|
|||
|
for(i=0; i<256; i++){
|
|||
|
if(VROM_WRITED[i]){
|
|||
|
memcpy(VROM+0x400*i, CRAM+0x0400*cb, 0x0400);
|
|||
|
cb++;
|
|||
|
if(cb>27){
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
break;
|
|||
|
case 3:
|
|||
|
// MMC STATE
|
|||
|
{
|
|||
|
MMCSTAT mmc;
|
|||
|
if( ::fread( &mmc, sizeof(MMCSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
mapper->LoadState( mmc.mmcdata );
|
|||
|
}
|
|||
|
break;
|
|||
|
case 4:
|
|||
|
// CTR STATE
|
|||
|
{
|
|||
|
CTRSTAT ctr;
|
|||
|
if( ::fread( &ctr, sizeof(CTRSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
pad->pad1bit = ctr.ctrreg.ctr.pad1bit;
|
|||
|
pad->pad2bit = ctr.ctrreg.ctr.pad2bit;
|
|||
|
pad->pad3bit = ctr.ctrreg.ctr.pad3bit;
|
|||
|
pad->pad4bit = ctr.ctrreg.ctr.pad4bit;
|
|||
|
pad->SetStrobe( (ctr.ctrreg.ctr.strobe!=0)?TRUE:FALSE );
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
case 5:
|
|||
|
// SND STATE
|
|||
|
{
|
|||
|
SNDSTAT snd;
|
|||
|
if( ::fread( &snd, sizeof(SNDSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
apu->LoadState( snd.snddata );
|
|||
|
}
|
|||
|
break;
|
|||
|
|
|||
|
// Disk Images
|
|||
|
// Ver0.30<EFBFBD>ȍ~
|
|||
|
case 6:
|
|||
|
{
|
|||
|
DISKDATA ddata;
|
|||
|
DWORD pos;
|
|||
|
BYTE data;
|
|||
|
LONG DiskSize = 16+65500*rom->GetDiskNo();
|
|||
|
LPBYTE lpDisk = rom->GetPROM();
|
|||
|
LPBYTE lpWrite = rom->GetDISK();
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>FLAG<41><47><EFBFBD><EFBFBD>
|
|||
|
::ZeroMemory( lpWrite, 16+65500*rom->GetDiskNo() );
|
|||
|
|
|||
|
if( ::fread( &ddata, sizeof(DISKDATA), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
for( i = 0; i < ddata.DifferentSize; i++ ) {
|
|||
|
if( ::fread( &pos, sizeof(DWORD), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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();
|
|||
|
}
|
|||
|
|
|||
|
// <20><><EFBFBD>[<5B>r<EFBFBD>[<5B>Đ<EFBFBD><C490><EFBFBD><EFBFBD>L<EFBFBD>^<5E><><EFBFBD>ł<EFBFBD><C582><EFBFBD><EFBFBD><EFBFBD><CE82>̈ʒu<CA92><75><EFBFBD>L<EFBFBD>^<5E><><EFBFBD><EFBFBD>
|
|||
|
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 )
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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; // <20>Q<EFBFBD>Ƃ<EFBFBD>INT<4E>Ȉׁi<D781><69>
|
|||
|
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
if( ::fwrite( ®, sizeof(REGSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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(<28>g<EFBFBD>p/<2F><><EFBFBD>g<EFBFBD>p<EFBFBD>Ɋւ<C98A><D682>炸<EFBFBD><E782B8><EFBFBD>݂<EFBFBD><DD82><EFBFBD><EFBFBD>Z<CE83>[<5B>u<EFBFBD><75><EFBFBD><EFBFBD>)
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
if( ::fwrite( &ram, sizeof(RAMSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
if( rom->IsSAVERAM() ) {
|
|||
|
if( ::fwrite( WRAM, SAVERAM_SIZE, 1, fp ) != 1 )
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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<>̓o<CD83><6F><EFBFBD>N<EFBFBD>Z<EFBFBD>[<5B>u<EFBFBD>ɊW<D68C>Ȃ<EFBFBD>
|
|||
|
// VirtuaNES0.30<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
// <20>o<EFBFBD><6F><EFBFBD>N<EFBFBD>R<EFBFBD><52>SRAM<41>g<EFBFBD>p<EFBFBD>Ɋւ<C98A><D682>炸<EFBFBD>Z<EFBFBD>[<5B>u
|
|||
|
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 mapper 74
|
|||
|
if(ppu->IsVromWrite()){
|
|||
|
int cb = 0;
|
|||
|
for(i=0; i<256; i++){
|
|||
|
if(VROM_WRITED[i]){
|
|||
|
memcpy(CRAM+0x0400*cb, VROM+0x400*i, 0x0400);
|
|||
|
CRAM_USED[cb>>2] = 1;
|
|||
|
size += 1024;
|
|||
|
cb++;
|
|||
|
if(cb>27){
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
CRAM_USED[7] = 1;
|
|||
|
size += 4*1024;
|
|||
|
}
|
|||
|
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
if( ::fwrite( &mmu, sizeof(MMUSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// WRITE VRAM MEMORY(<28><><EFBFBD><EFBFBD>4K<34><4B><EFBFBD><EFBFBD><EFBFBD>ׂď<D782><C48F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
|
|||
|
if( ::fwrite( VRAM, 4*1024, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
if( ::fwrite( &mmc, sizeof(MMCSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
if( ::fwrite( &ctr, sizeof(CTRSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
if( ::fwrite( &snd, sizeof(SNDSTAT), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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) );
|
|||
|
|
|||
|
// <20><><EFBFBD>ᐔ<EFBFBD><E19094><EFBFBD>J<EFBFBD>E<EFBFBD><45><EFBFBD>g
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
// Write File
|
|||
|
if( ::fwrite( &dsk, sizeof(DISKDATA), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
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 ); // <20><><EFBFBD>^<5E>[<5B><><EFBFBD>l<EFBFBD>͕ύX<CF8D><58><EFBFBD>̃~<7E><><EFBFBD>[<5B>g<EFBFBD><67><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
|
|||
|
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 <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
LPBYTE lpScn = ppu->GetScreenPtr();
|
|||
|
|
|||
|
BITMAPFILEHEADER bfh;
|
|||
|
BITMAPINFOHEADER bih;
|
|||
|
RGBQUAD rgb[256];
|
|||
|
|
|||
|
ZEROMEMORY( &bfh, sizeof(bfh) );
|
|||
|
ZEROMEMORY( &bih, sizeof(bih) );
|
|||
|
ZEROMEMORY( rgb, sizeof(rgb) );
|
|||
|
|
|||
|
bfh.bfType = 0x4D42; // 'BM'
|
|||
|
bfh.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;
|
|||
|
bfh.bfSize = bfh.bfOffBits+256*240;
|
|||
|
|
|||
|
bih.biSize = sizeof(bih);
|
|||
|
bih.biWidth = 256;
|
|||
|
bih.biHeight = 240;
|
|||
|
bih.biPlanes = 1;
|
|||
|
bih.biBitCount = 8;
|
|||
|
bih.biCompression = BI_RGB;
|
|||
|
bih.biSizeImage = 0;
|
|||
|
bih.biXPelsPerMeter = 0;
|
|||
|
bih.biYPelsPerMeter = 0;
|
|||
|
bih.biClrUsed = 256;
|
|||
|
bih.biClrImportant = 0;
|
|||
|
|
|||
|
DirectDraw.GetPaletteData( rgb );
|
|||
|
|
|||
|
if( ::fwrite( &bfh, sizeof(bfh), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
if( ::fwrite( &bih, sizeof(bih), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
if( ::fwrite( &rgb, sizeof(rgb), 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
lpScn += 8;
|
|||
|
for( INT i = 239; i >= 0; i-- ) {
|
|||
|
if( ::fwrite( &lpScn[(256+16)*i], 256, 1, fp ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
FCLOSE( fp );
|
|||
|
} else {
|
|||
|
LPBYTE lpScn = ppu->GetScreenPtr();
|
|||
|
RGBQUAD rgb[256];
|
|||
|
ZEROMEMORY( rgb, sizeof(rgb) );
|
|||
|
DirectDraw.GetPaletteData( rgb );
|
|||
|
|
|||
|
PNGWRITE png;
|
|||
|
|
|||
|
png.Write( tempstr.c_str(), 256, 240, rgb, lpScn+8, CDirectDraw::RENDER_WIDTH );
|
|||
|
}
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DEBUGOUT( "Snapshot error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
DEBUGOUT( "Snapshot error.\n" );
|
|||
|
FCLOSE( fp );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
INT NES::IsMovieFile( const char* fname, ROM* rom )
|
|||
|
{
|
|||
|
FILE* fp = NULL;
|
|||
|
MOVIEFILEHDR header;
|
|||
|
|
|||
|
if( !(fp = ::fopen( fname, "rb" )) )
|
|||
|
return -1;
|
|||
|
|
|||
|
if( ::fread( &header, sizeof(header), 1, fp ) != 1 ) {
|
|||
|
FCLOSE( fp );
|
|||
|
return -1;
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
|
|||
|
if( ::memcmp( header.ID, "VirtuaNES MV", sizeof(header.ID) ) == 0 ) {
|
|||
|
if( header.BlockVersion < 0x0300 ) {
|
|||
|
return IDS_ERROR_ILLEGALMOVIEOLD;
|
|||
|
} else
|
|||
|
if( header.BlockVersion >= 0x0300 ) {
|
|||
|
if( rom->GetMapperNo() != 20 ) {
|
|||
|
// FDS<44>ȊO
|
|||
|
if( header.Ext0 != rom->GetPROM_CRC() ) {
|
|||
|
return IDS_ERROR_ILLEGALMOVIECRC; // <20>Ⴄ<EFBFBD><E182A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
} else {
|
|||
|
// FDS
|
|||
|
if( header.Ext0 != rom->GetGameID() ||
|
|||
|
header.Ext1 != (WORD)rom->GetMakerID() ||
|
|||
|
header.Ext2 != (WORD)rom->GetDiskNo() )
|
|||
|
return IDS_ERROR_ILLEGALMOVIECRC; // <20>Ⴄ<EFBFBD><E182A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
|
|||
|
if( header.RecordVersion != VIRTUANES_VERSION ) {
|
|||
|
return IDS_ERROR_ILLEGALMOVIEVER;
|
|||
|
}
|
|||
|
|
|||
|
return 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return -1;
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::MoviePlay( const char* fname )
|
|||
|
{
|
|||
|
if( rom->IsNSF() )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if( IsMoviePlay() || IsMovieRec() ) {
|
|||
|
MovieStop();
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "NES::MoviePlay\n" );
|
|||
|
|
|||
|
try {
|
|||
|
if( !(m_fpMovie = ::fopen( fname, "rb+" )) ) {
|
|||
|
DEBUGOUT( "Movie play error. File not found.\n" );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD>
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// <20>ǂݍ<C782><DD8D><EFBFBD>
|
|||
|
if( ::fread( &m_hedMovie, sizeof(m_hedMovie), 1, m_fpMovie ) != 1 ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
if( ::memcmp( m_hedMovie.ID, "VirtuaNES MV", sizeof(m_hedMovie.ID) ) == 0 ) {
|
|||
|
m_MovieVersion = m_hedMovie.BlockVersion;
|
|||
|
|
|||
|
if( m_hedMovie.BlockVersion == 0x0300 ) {
|
|||
|
if( m_hedMovie.CRC != 0 ) {
|
|||
|
if( CRC::Crc( sizeof(m_hedMovie)-sizeof(DWORD), (LPBYTE)&m_hedMovie ) != m_hedMovie.CRC ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
return FALSE; // <20>Ⴄ<EFBFBD><E182A4><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
}
|
|||
|
}
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>`
|
|||
|
} else {
|
|||
|
// <20>搶<EFBFBD>I<EFBFBD>Â<EFBFBD><C382>̂Ń_<C583><5F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>B
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// <20>Q<EFBFBD>[<5B><><EFBFBD>ŗL<C597>I<EFBFBD>v<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD>
|
|||
|
m_saveRenderMethod = (INT)GetRenderMethod();
|
|||
|
m_saveIrqType = GetIrqType();
|
|||
|
m_saveFrameIRQ = GetFrameIRQmode();
|
|||
|
m_saveVideoMode = GetVideoMode();
|
|||
|
SetRenderMethod( (RENDERMETHOD)m_hedMovie.RenderMethod );
|
|||
|
SetIrqType( (INT)m_hedMovie.IRQtype );
|
|||
|
SetFrameIRQmode( (m_hedMovie.FrameIRQ!=0)?TRUE:FALSE );
|
|||
|
SetVideoMode( m_hedMovie.VideoMode);
|
|||
|
|
|||
|
LONG MovieOffset;
|
|||
|
m_MovieControl = m_hedMovie.Control;
|
|||
|
m_MovieStepTotal = m_hedMovie.MovieStep;
|
|||
|
MovieOffset = m_hedMovie.MovieOffset;
|
|||
|
|
|||
|
// <20>X<EFBFBD>e<EFBFBD>[<5B>g<EFBFBD>ǂݍ<C782><DD8D><EFBFBD>
|
|||
|
ReadState( m_fpMovie );
|
|||
|
|
|||
|
if( ::fseek( m_fpMovie, MovieOffset, SEEK_SET ) ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
// <20><><EFBFBD>[<5B>r<EFBFBD>[<5B><><EFBFBD>L<EFBFBD>^<5E><><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>Ȃ<EFBFBD><C882>H
|
|||
|
if( m_MovieStepTotal == 0 ) {
|
|||
|
MovieStop();
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
m_bMoviePlay = TRUE;
|
|||
|
m_MovieStep = 0;
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DEBUGOUT( "Movie play error. %s\n", str );
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
DEBUGOUT( "Movie play error.\n" );
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::MovieRec( const char* fname )
|
|||
|
{
|
|||
|
if( rom->IsNSF() )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if( IsMoviePlay() || IsMovieRec() ) {
|
|||
|
MovieStop();
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "NES::MovieRec\n" );
|
|||
|
|
|||
|
try {
|
|||
|
if( !(m_fpMovie = ::fopen( fname, "wb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, fname );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
::ZeroMemory( &m_hedMovie, sizeof(m_hedMovie) );
|
|||
|
::memcpy( m_hedMovie.ID, "VirtuaNES MV", sizeof(m_hedMovie.ID) );
|
|||
|
m_hedMovie.BlockVersion = 0x0300;
|
|||
|
m_hedMovie.RecordVersion = VIRTUANES_VERSION;
|
|||
|
|
|||
|
m_hedMovie.StateStOffset = sizeof(m_hedMovie);
|
|||
|
|
|||
|
m_hedMovie.Control |= Config.movie.bUsePlayer[0]?0x01:0x00;
|
|||
|
m_hedMovie.Control |= Config.movie.bUsePlayer[1]?0x02:0x00;
|
|||
|
m_hedMovie.Control |= Config.movie.bUsePlayer[2]?0x04:0x00;
|
|||
|
m_hedMovie.Control |= Config.movie.bUsePlayer[3]?0x08:0x00;
|
|||
|
m_hedMovie.Control |= Config.movie.bRerecord?0x80:0x00;
|
|||
|
m_MovieControl = m_hedMovie.Control;
|
|||
|
|
|||
|
// <20>Q<EFBFBD>[<5B><><EFBFBD>ŗL<C597>I<EFBFBD>v<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD>
|
|||
|
m_hedMovie.RenderMethod = (BYTE)GetRenderMethod();
|
|||
|
m_hedMovie.IRQtype = (BYTE)GetIrqType();
|
|||
|
m_hedMovie.FrameIRQ = GetFrameIRQmode()?0xFF:0;
|
|||
|
m_hedMovie.VideoMode = GetVideoMode();
|
|||
|
|
|||
|
// CRC,ID<49>l<EFBFBD><6C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>(<28>듮<EFBFBD><EB93AE><EFBFBD>h<EFBFBD>~<7E>p)
|
|||
|
if( rom->GetMapperNo() != 20 ) {
|
|||
|
// FDS<44>ȊO
|
|||
|
m_hedMovie.Ext0 = rom->GetPROM_CRC();
|
|||
|
} else {
|
|||
|
// FDS
|
|||
|
m_hedMovie.Ext0 = rom->GetGameID();
|
|||
|
m_hedMovie.Ext1 = (WORD)rom->GetMakerID();
|
|||
|
m_hedMovie.Ext2 = (WORD)rom->GetDiskNo();
|
|||
|
}
|
|||
|
|
|||
|
// <20>_<EFBFBD>~<7E>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &m_hedMovie, sizeof(m_hedMovie), 1, m_fpMovie ) != 1 ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
if( Config.movie.bResetRec ) {
|
|||
|
Reset(); // <20>n<EFBFBD>[<5B>h<EFBFBD>E<EFBFBD>F<EFBFBD>A<EFBFBD><41><EFBFBD>Z<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>̋L<CC8B>^<5E>J<EFBFBD>n
|
|||
|
}
|
|||
|
|
|||
|
// <20>X<EFBFBD>e<EFBFBD>[<5B>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
WriteState( m_fpMovie );
|
|||
|
|
|||
|
m_hedMovie.MovieOffset = ::ftell( m_fpMovie );
|
|||
|
m_bMovieRec = TRUE;
|
|||
|
m_MovieStep = m_MovieStepTotal = 0;
|
|||
|
m_MovieVersion = 0x0300;
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DEBUGOUT( "Movie record error. %s\n", str );
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
DEBUGOUT( "Movie record error.\n" );
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::MovieRecAppend( const char* fname )
|
|||
|
{
|
|||
|
if( rom->IsNSF() )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
// <20>L<EFBFBD>^<5E><><EFBFBD>͈Ӗ<CD88><D396><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( IsMovieRec() )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if( IsMoviePlay() ) {
|
|||
|
MovieStop();
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "NES::MovieAppendRec\n" );
|
|||
|
|
|||
|
try {
|
|||
|
if( !(m_fpMovie = ::fopen( fname, "rb" )) ) {
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƃ<EFBFBD>
|
|||
|
if( !(m_fpMovie = ::fopen( fname, "wb" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, fname );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
|
|||
|
::ZeroMemory( &m_hedMovie, sizeof(m_hedMovie) );
|
|||
|
::memcpy( m_hedMovie.ID, "VirtuaNES MV", sizeof(m_hedMovie.ID) );
|
|||
|
m_hedMovie.BlockVersion = 0x0300;
|
|||
|
m_hedMovie.RecordVersion = VIRTUANES_VERSION;
|
|||
|
m_hedMovie.StateStOffset = sizeof(m_hedMovie);
|
|||
|
|
|||
|
m_hedMovie.Control |= Config.movie.bUsePlayer[0]?0x01:0x00;
|
|||
|
m_hedMovie.Control |= Config.movie.bUsePlayer[1]?0x02:0x00;
|
|||
|
m_hedMovie.Control |= Config.movie.bUsePlayer[2]?0x04:0x00;
|
|||
|
m_hedMovie.Control |= Config.movie.bUsePlayer[3]?0x08:0x00;
|
|||
|
m_hedMovie.Control |= Config.movie.bRerecord?0x80:0x00;
|
|||
|
// m_hedMovie.Control |= Config.movie.bResetRec?0x40:0x00;
|
|||
|
m_MovieControl = m_hedMovie.Control;
|
|||
|
|
|||
|
// <20>Q<EFBFBD>[<5B><><EFBFBD>ŗL<C597>I<EFBFBD>v<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD>
|
|||
|
m_hedMovie.RenderMethod = (BYTE)GetRenderMethod();
|
|||
|
m_hedMovie.IRQtype = (BYTE)GetIrqType();
|
|||
|
m_hedMovie.FrameIRQ = GetFrameIRQmode()?0xFF:0;
|
|||
|
m_hedMovie.VideoMode = GetVideoMode();
|
|||
|
|
|||
|
// <20>_<EFBFBD>~<7E>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &m_hedMovie, sizeof(m_hedMovie), 1, m_fpMovie ) != 1 ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
if( Config.movie.bResetRec ) {
|
|||
|
Reset(); // <20>n<EFBFBD>[<5B>h<EFBFBD>E<EFBFBD>F<EFBFBD>A<EFBFBD><41><EFBFBD>Z<EFBFBD>b<EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>̋L<CC8B>^<5E>J<EFBFBD>n
|
|||
|
}
|
|||
|
// <20>X<EFBFBD>e<EFBFBD>[<5B>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
WriteState( m_fpMovie );
|
|||
|
|
|||
|
m_hedMovie.MovieOffset = ::ftell( m_fpMovie );
|
|||
|
m_MovieStep = m_MovieStepTotal = 0;
|
|||
|
m_MovieVersion = 0x0300;
|
|||
|
} else {
|
|||
|
if( !(m_fpMovie = ::fopen( fname, "rb+" )) ) {
|
|||
|
// xxx <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD>J<EFBFBD><4A><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, fname );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
// <20>ǂݍ<C782><DD8D><EFBFBD>
|
|||
|
if( ::fseek( m_fpMovie, 0, SEEK_SET ) ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
if( ::fread( &m_hedMovie, sizeof(m_hedMovie), 1, m_fpMovie ) != 1 ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
|
|||
|
if( ::memcmp( m_hedMovie.ID, "VirtuaNES MV", sizeof(m_hedMovie.ID) ) != 0 ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
// <20>Â<EFBFBD><C382>o<EFBFBD>[<5B>W<EFBFBD><57><EFBFBD><EFBFBD><EFBFBD>͎̂<CD8E>
|
|||
|
if( m_hedMovie.BlockVersion < 0x0300 ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
m_MovieControl = m_hedMovie.Control;
|
|||
|
m_MovieStep = m_MovieStepTotal = m_hedMovie.MovieStep;
|
|||
|
m_MovieVersion = 0x0300;
|
|||
|
|
|||
|
if( ::fseek( m_fpMovie, m_hedMovie.StateEdOffset, SEEK_SET ) ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
if( !ReadState( m_fpMovie ) ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
if( ::fseek( m_fpMovie, m_hedMovie.StateEdOffset, SEEK_SET ) ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̓ǂݍ<C782><DD8D>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_READ );
|
|||
|
}
|
|||
|
}
|
|||
|
m_bMovieRec = TRUE;
|
|||
|
} catch( CHAR* str ) {
|
|||
|
DEBUGOUT( "Movie record error. %s\n", str );
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
DEBUGOUT( "Movie record error.\n" );
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>s<EFBFBD><73><EFBFBD>ȃG<C883><47><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::MovieStop()
|
|||
|
{
|
|||
|
if( !m_fpMovie && !(m_bMoviePlay||m_bMovieRec) )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
DEBUGOUT( "NES::MovieStop\n" );
|
|||
|
|
|||
|
DirectDraw.SetMessageString( "Movie stop." );
|
|||
|
|
|||
|
if( m_bMovieRec ) {
|
|||
|
m_hedMovie.MovieStep = m_MovieStep;
|
|||
|
m_hedMovie.StateEdOffset = ::ftell( m_fpMovie );
|
|||
|
WriteState( m_fpMovie );
|
|||
|
|
|||
|
// // <EFBFBD>B<EFBFBD>蒼<EFBFBD><EFBFBD><EFBFBD>֎~<EFBFBD>̏ꍇ<EFBFBD>͒NjL<EFBFBD>s<EFBFBD>\
|
|||
|
// if( m_MovieControl & 0x80 ) {
|
|||
|
// } else {
|
|||
|
// m_hedMovie.StateEdOffset = 0;
|
|||
|
// }
|
|||
|
if( ::fseek( m_fpMovie, 0, SEEK_SET ) ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
// CRC <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
m_hedMovie.CRC = CRC::Crc( sizeof(m_hedMovie)-sizeof(DWORD), (LPBYTE)&m_hedMovie );
|
|||
|
|
|||
|
// <20>ŏI<C58F>I<EFBFBD>ȃw<C883>b<EFBFBD>_<EFBFBD><5F><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &m_hedMovie, sizeof(m_hedMovie), 1, m_fpMovie ) != 1 ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
m_bMovieRec = FALSE;
|
|||
|
}
|
|||
|
|
|||
|
if( m_bMoviePlay ) {
|
|||
|
FCLOSE( m_fpMovie );
|
|||
|
m_bMoviePlay = FALSE;
|
|||
|
|
|||
|
// <20>Q<EFBFBD>[<5B><><EFBFBD>ŗL<C597>I<EFBFBD>v<EFBFBD>V<EFBFBD><56><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ɖ߂<C996>
|
|||
|
SetRenderMethod( (RENDERMETHOD)m_saveRenderMethod );
|
|||
|
SetIrqType ( m_saveIrqType );
|
|||
|
SetFrameIRQmode( m_saveFrameIRQ );
|
|||
|
SetVideoMode ( m_saveVideoMode );
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
void NES::GetMovieInfo( WORD& wRecVersion, WORD& wVersion, DWORD& dwRecordFrames, DWORD& dwRecordTimes )
|
|||
|
{
|
|||
|
wRecVersion = m_hedMovie.RecordVersion;
|
|||
|
wVersion = m_hedMovie.BlockVersion;
|
|||
|
dwRecordFrames = m_hedMovie.MovieStep;
|
|||
|
dwRecordTimes = m_hedMovie.RecordTimes;
|
|||
|
}
|
|||
|
|
|||
|
// <20><><EFBFBD>t<EFBFBD><74><EFBFBD>[<5B><><EFBFBD>Ăяo<D18F><6F>
|
|||
|
void NES::Movie()
|
|||
|
{
|
|||
|
if( !m_fpMovie && !(m_bMoviePlay||m_bMovieRec) ) {
|
|||
|
m_CommandRequest = 0; // <20>R<EFBFBD><52><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882>Ǝ<EFBFBD><C68E><EFBFBD>
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
INT exctr = pad->GetExController();
|
|||
|
|
|||
|
BYTE Data;
|
|||
|
WORD wData;
|
|||
|
DWORD dwData;
|
|||
|
|
|||
|
if( m_bMovieRec ) {
|
|||
|
// <20>ŏ<EFBFBD><C58F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>۰ׂ<DBB0><D782>ݒ肳<DD92><E882B3><EFBFBD>Ă<EFBFBD><C482><EFBFBD><EFBFBD>ꍇ
|
|||
|
if( m_MovieStep == 0 ) {
|
|||
|
if( exctr == PAD::EXCONTROLLER_ZAPPER
|
|||
|
|| exctr == PAD::EXCONTROLLER_PADDLE
|
|||
|
|| exctr == PAD::EXCONTROLLER_CRAZYCLIMBER
|
|||
|
|| exctr == PAD::EXCONTROLLER_TOPRIDER
|
|||
|
|| exctr == PAD::EXCONTROLLER_SPACESHADOWGUN
|
|||
|
|| exctr == PAD::EXCONTROLLER_FAMILYTRAINER_A
|
|||
|
|| exctr == PAD::EXCONTROLLER_FAMILYTRAINER_B
|
|||
|
|| exctr == PAD::EXCONTROLLER_MAHJANG
|
|||
|
|| exctr == PAD::EXCONTROLLER_EXCITINGBOXING
|
|||
|
|| exctr == PAD::EXCONTROLLER_CHINA_EDUCATIONAL_MOUSE
|
|||
|
|| exctr == PAD::EXCONTROLLER_OEKAKIDS_TABLET ) {
|
|||
|
// <20>R<EFBFBD>}<7D><><EFBFBD>hID
|
|||
|
Data = 0xF0;
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &Data, sizeof(Data), 1, m_fpMovie ) != 1 ) {
|
|||
|
MovieStop();
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
// <20><><EFBFBD><EFBFBD>
|
|||
|
wData = (WORD)(0x0100|(pad->GetExController()&0x0FF));
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &wData, sizeof(wData), 1, m_fpMovie ) != 1 ) {
|
|||
|
MovieStop();
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if( m_CommandRequest ) {
|
|||
|
// <20>R<EFBFBD>}<7D><><EFBFBD>hID
|
|||
|
Data = 0xF0;
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &Data, sizeof(Data), 1, m_fpMovie ) != 1 ) {
|
|||
|
MovieStop();
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
// <20>R<EFBFBD>}<7D><><EFBFBD>h
|
|||
|
wData = (WORD)m_CommandRequest;
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &wData, sizeof(wData), 1, m_fpMovie ) != 1 ) {
|
|||
|
MovieStop();
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
}
|
|||
|
m_CommandRequest = 0;
|
|||
|
|
|||
|
// <20>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>۰<EFBFBD>
|
|||
|
if( exctr == PAD::EXCONTROLLER_ZAPPER
|
|||
|
|| exctr == PAD::EXCONTROLLER_PADDLE
|
|||
|
|| exctr == PAD::EXCONTROLLER_CRAZYCLIMBER
|
|||
|
|| exctr == PAD::EXCONTROLLER_TOPRIDER
|
|||
|
|| exctr == PAD::EXCONTROLLER_SPACESHADOWGUN
|
|||
|
|| exctr == PAD::EXCONTROLLER_FAMILYTRAINER_A
|
|||
|
|| exctr == PAD::EXCONTROLLER_FAMILYTRAINER_B
|
|||
|
|| exctr == PAD::EXCONTROLLER_MAHJANG
|
|||
|
|| exctr == PAD::EXCONTROLLER_EXCITINGBOXING
|
|||
|
|| exctr == PAD::EXCONTROLLER_CHINA_EDUCATIONAL_MOUSE
|
|||
|
|| exctr == PAD::EXCONTROLLER_OEKAKIDS_TABLET ) {
|
|||
|
// <20>g<EFBFBD><67><EFBFBD>R<EFBFBD><52><EFBFBD>g<EFBFBD><67><EFBFBD>[<5B><><EFBFBD>f<EFBFBD>[<5B>^ID
|
|||
|
Data = 0xF3;
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &Data, sizeof(Data), 1, m_fpMovie ) != 1 ) {
|
|||
|
MovieStop();
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
// <20>f<EFBFBD>[<5B>^
|
|||
|
dwData = pad->GetSyncExData();
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &dwData, sizeof(dwData), 1, m_fpMovie ) != 1 ) {
|
|||
|
MovieStop();
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
dwData = pad->GetSyncData();
|
|||
|
for( INT i = 0; i < 4; i++ ) {
|
|||
|
Data = (BYTE)(dwData>>(i*8));
|
|||
|
if( m_MovieControl & (1<<i) ) {
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
if( ::fwrite( &Data, sizeof(Data), 1, m_fpMovie ) != 1 ) {
|
|||
|
MovieStop();
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD>̏<EFBFBD><CC8F><EFBFBD><EFBFBD><EFBFBD><EFBFBD>݂Ɏ<DD82><C98E>s<EFBFBD><73><EFBFBD>܂<EFBFBD><DC82><EFBFBD>
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
m_MovieStep++;
|
|||
|
}
|
|||
|
|
|||
|
if( m_bMoviePlay ) {
|
|||
|
DWORD dwPadData = 0;
|
|||
|
INT num = 0;
|
|||
|
BYTE PadBuf[4];
|
|||
|
|
|||
|
PadBuf[0] = PadBuf[1] = PadBuf[2] = PadBuf[3] = 0;
|
|||
|
|
|||
|
// <20><><EFBFBD>[<5B>r<EFBFBD>[<5B>Đ<EFBFBD><C490>I<EFBFBD><49><EFBFBD>H
|
|||
|
if( m_MovieStep >= m_MovieStepTotal ) {
|
|||
|
if( !Config.movie.bLoopPlay ) {
|
|||
|
MovieStop();
|
|||
|
return;
|
|||
|
} else {
|
|||
|
// <20><><EFBFBD>U<EFBFBD>Đ<EFBFBD><C490><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ȃ<EFBFBD><C882><EFBFBD><EFBFBD>Ď<EFBFBD><C48E>ɂ<EFBFBD><C982><EFBFBD>
|
|||
|
m_bMoviePlay = FALSE;
|
|||
|
m_MovieStep = 0;
|
|||
|
::fseek( m_fpMovie, m_hedMovie.StateStOffset, SEEK_SET );
|
|||
|
// <20>X<EFBFBD>e<EFBFBD>[<5B>g<EFBFBD>ǂݍ<C782><DD8D><EFBFBD>
|
|||
|
ReadState( m_fpMovie );
|
|||
|
::fseek( m_fpMovie, m_hedMovie.MovieOffset, SEEK_SET );
|
|||
|
// <20>Đ<EFBFBD><C490><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ď<EFBFBD><C48E>ɂ<EFBFBD><C982><EFBFBD>
|
|||
|
m_bMoviePlay = TRUE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
do {
|
|||
|
// <20>ǂݍ<C782><DD8D><EFBFBD>
|
|||
|
if( ::fread( &Data, sizeof(Data), 1, m_fpMovie ) != 1 ) {
|
|||
|
// <20>I<EFBFBD><49><EFBFBD>H
|
|||
|
MovieStop();
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// <20>R<EFBFBD>}<7D><><EFBFBD>h<EFBFBD>H
|
|||
|
if( (Data & 0xF0) == 0xF0 ) {
|
|||
|
if( Data == 0xF0 ) {
|
|||
|
// <20>ǂݍ<C782><DD8D><EFBFBD>
|
|||
|
if( ::fread( &wData, sizeof(wData), 1, m_fpMovie ) != 1 ) {
|
|||
|
// <20>I<EFBFBD><49><EFBFBD>H
|
|||
|
MovieStop();
|
|||
|
return;
|
|||
|
}
|
|||
|
if( wData < 0x0100 ) {
|
|||
|
Command( (NESCOMMAND)((INT)wData) );
|
|||
|
} else {
|
|||
|
// <20>g<EFBFBD><67><EFBFBD><EFBFBD><EFBFBD>۰<EFBFBD>
|
|||
|
CommandParam( NESCMD_EXCONTROLLER, ((INT)wData) & 0x00FF );
|
|||
|
}
|
|||
|
} else
|
|||
|
if( Data == 0xF3 ) {
|
|||
|
// <20>ǂݍ<C782><DD8D><EFBFBD>
|
|||
|
if( ::fread( &dwData, sizeof(dwData), 1, m_fpMovie ) != 1 ) {
|
|||
|
// <20>I<EFBFBD><49><EFBFBD>H
|
|||
|
MovieStop();
|
|||
|
return;
|
|||
|
}
|
|||
|
pad->SetSyncExData( dwData );
|
|||
|
} else {
|
|||
|
// <20>f<EFBFBD>[<5B>^<5E>Ԃ<EFBFBD><D482><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ă<EFBFBD><C482>H<EFBFBD>I<EFBFBD><49><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
MovieStop();
|
|||
|
return;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// <20><><EFBFBD>g<EFBFBD>p<EFBFBD>v<EFBFBD><76><EFBFBD>C<EFBFBD><43><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
while( !(m_MovieControl & (1<<num)) && (num < 4) ) {
|
|||
|
PadBuf[num] = 0;
|
|||
|
num++;
|
|||
|
}
|
|||
|
PadBuf[num] = Data;
|
|||
|
num++;
|
|||
|
// <20><><EFBFBD>g<EFBFBD>p<EFBFBD>v<EFBFBD><76><EFBFBD>C<EFBFBD><43><EFBFBD>[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
while( !(m_MovieControl & (1<<num)) && (num < 4) ) {
|
|||
|
PadBuf[num] = 0;
|
|||
|
num++;
|
|||
|
}
|
|||
|
}
|
|||
|
} while( num < 4 );
|
|||
|
|
|||
|
dwData = (((DWORD)PadBuf[3])<<24)|(((DWORD)PadBuf[2])<<16)|(((DWORD)PadBuf[1])<<8)|((DWORD)PadBuf[0]);
|
|||
|
pad->SetSyncData( dwData );
|
|||
|
|
|||
|
// <20>J<EFBFBD>E<EFBFBD><45><EFBFBD>^<5E><><EFBFBD>₷
|
|||
|
m_MovieStep++;
|
|||
|
}
|
|||
|
|
|||
|
m_CommandRequest = 0;
|
|||
|
}
|
|||
|
|
|||
|
// For Cheat
|
|||
|
void NES::CheatInitial()
|
|||
|
{
|
|||
|
m_CheatCode.clear();
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::IsCheatCodeAdd()
|
|||
|
{
|
|||
|
BOOL bRet = m_bCheatCodeAdd;
|
|||
|
m_bCheatCodeAdd = FALSE;
|
|||
|
|
|||
|
return bRet;
|
|||
|
}
|
|||
|
|
|||
|
INT NES::GetCheatCodeNum()
|
|||
|
{
|
|||
|
return m_CheatCode.size();
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::GetCheatCode( INT no, CHEATCODE& code )
|
|||
|
{
|
|||
|
if( m_CheatCode.size()-1 < no )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
code = m_CheatCode[no];
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
void NES::SetCheatCodeFlag( INT no, BOOL bEnable )
|
|||
|
{
|
|||
|
if( m_CheatCode.size()-1 < no )
|
|||
|
return;
|
|||
|
|
|||
|
if( bEnable ) {
|
|||
|
m_CheatCode[no].enable |= CHEAT_ENABLE;
|
|||
|
} else {
|
|||
|
m_CheatCode[no].enable &= ~CHEAT_ENABLE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::SetCheatCodeAllFlag( BOOL bEnable, BOOL bKey )
|
|||
|
{
|
|||
|
for( INT i = 0; i < m_CheatCode.size(); i++ ) {
|
|||
|
if( !bKey ) {
|
|||
|
if( bEnable ) {
|
|||
|
m_CheatCode[i].enable |= CHEAT_ENABLE;
|
|||
|
} else {
|
|||
|
m_CheatCode[i].enable &= ~CHEAT_ENABLE;
|
|||
|
}
|
|||
|
} else if( !(m_CheatCode[i].enable&CHEAT_KEYDISABLE) ) {
|
|||
|
if( bEnable ) {
|
|||
|
m_CheatCode[i].enable |= CHEAT_ENABLE;
|
|||
|
} else {
|
|||
|
m_CheatCode[i].enable &= ~CHEAT_ENABLE;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::ReplaceCheatCode( INT no, CHEATCODE code )
|
|||
|
{
|
|||
|
if( m_CheatCode.size()-1 < no )
|
|||
|
return;
|
|||
|
|
|||
|
m_CheatCode[no] = code;
|
|||
|
}
|
|||
|
|
|||
|
void NES::AddCheatCode( CHEATCODE code )
|
|||
|
{
|
|||
|
m_CheatCode.push_back( code );
|
|||
|
m_bCheatCodeAdd = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
void NES::DelCheatCode( INT no )
|
|||
|
{
|
|||
|
if( m_CheatCode.size()-1 < no )
|
|||
|
return;
|
|||
|
|
|||
|
m_CheatCode.erase( &m_CheatCode[no] );
|
|||
|
}
|
|||
|
|
|||
|
DWORD NES::CheatRead( INT length, WORD addr )
|
|||
|
{
|
|||
|
DWORD data = 0;
|
|||
|
for( INT i = 0; i <= length; i++ ) {
|
|||
|
data |= (DWORD)Read( addr+i )*(1<<(i*8));
|
|||
|
}
|
|||
|
|
|||
|
return data;
|
|||
|
}
|
|||
|
|
|||
|
void NES::CheatWrite( INT length, WORD addr, DWORD data )
|
|||
|
{
|
|||
|
for( INT i = 0; i <= length; i++ ) {
|
|||
|
Write( (WORD)(addr+i), data&0xFF );
|
|||
|
data >>= 8;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::CheatCodeProcess()
|
|||
|
{
|
|||
|
for( vector<CHEATCODE>::iterator it = m_CheatCode.begin(); it != m_CheatCode.end(); it++ ) {
|
|||
|
if( !(it->enable & CHEAT_ENABLE) )
|
|||
|
continue;
|
|||
|
|
|||
|
switch( it->type ) {
|
|||
|
case CHEAT_TYPE_ALWAYS:
|
|||
|
CheatWrite( it->length, it->address, it->data );
|
|||
|
break;
|
|||
|
case CHEAT_TYPE_ONCE:
|
|||
|
CheatWrite( it->length, it->address, it->data );
|
|||
|
it->enable = 0;
|
|||
|
break;
|
|||
|
case CHEAT_TYPE_GREATER:
|
|||
|
if( CheatRead( it->length, it->address ) > it->data ) {
|
|||
|
CheatWrite( it->length, it->address, it->data );
|
|||
|
}
|
|||
|
break;
|
|||
|
case CHEAT_TYPE_LESS:
|
|||
|
if( CheatRead( it->length, it->address ) < it->data ) {
|
|||
|
CheatWrite( it->length, it->address, it->data );
|
|||
|
}
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::GenieInitial()
|
|||
|
{
|
|||
|
m_bCheatCodeAdd = FALSE;
|
|||
|
m_GenieCode.clear();
|
|||
|
}
|
|||
|
|
|||
|
void NES::GenieLoad( char* fname )
|
|||
|
{
|
|||
|
FILE* fp = NULL;
|
|||
|
|
|||
|
CHAR buf[256];
|
|||
|
GENIECODE code;
|
|||
|
BYTE codetmp[9];
|
|||
|
INT no;
|
|||
|
|
|||
|
if( (fp = ::fopen( fname, "r" )) ) {
|
|||
|
m_GenieCode.clear();
|
|||
|
|
|||
|
while( ::fgets( buf, sizeof(buf), fp ) ) {
|
|||
|
if( buf[0] == ';' )
|
|||
|
continue;
|
|||
|
if( buf[0] == 0x0D || buf[0] == 0x0A )
|
|||
|
continue;
|
|||
|
|
|||
|
if( ::strlen( buf ) < 6 )
|
|||
|
continue;
|
|||
|
|
|||
|
code.address = 0;
|
|||
|
code.data = 0;
|
|||
|
code.cmp = 0;
|
|||
|
|
|||
|
for( no = 0; isalpha(buf[no]) && no < 8; no++ ) {
|
|||
|
switch( buf[no] ) {
|
|||
|
case 'A': codetmp[no] = 0x00; break;
|
|||
|
case 'P': codetmp[no] = 0x01; break;
|
|||
|
case 'Z': codetmp[no] = 0x02; break;
|
|||
|
case 'L': codetmp[no] = 0x03; break;
|
|||
|
case 'G': codetmp[no] = 0x04; break;
|
|||
|
case 'I': codetmp[no] = 0x05; break;
|
|||
|
case 'T': codetmp[no] = 0x06; break;
|
|||
|
case 'Y': codetmp[no] = 0x07; break;
|
|||
|
case 'E': codetmp[no] = 0x08; break;
|
|||
|
case 'O': codetmp[no] = 0x09; break;
|
|||
|
case 'X': codetmp[no] = 0x0A; break;
|
|||
|
case 'U': codetmp[no] = 0x0B; break;
|
|||
|
case 'K': codetmp[no] = 0x0C; break;
|
|||
|
case 'S': codetmp[no] = 0x0D; break;
|
|||
|
case 'V': codetmp[no] = 0x0E; break;
|
|||
|
case 'N': codetmp[no] = 0x0F; break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if( no == 6 ) {
|
|||
|
// Address
|
|||
|
code.address |= (WORD)(codetmp[3] & 0x07)<<12;
|
|||
|
code.address |= (WORD)(codetmp[4] & 0x08)<< 8;
|
|||
|
code.address |= (WORD)(codetmp[5] & 0x07)<< 8;
|
|||
|
code.address |= (WORD)(codetmp[1] & 0x08)<< 4;
|
|||
|
code.address |= (WORD)(codetmp[2] & 0x07)<< 4;
|
|||
|
code.address |= (WORD)(codetmp[3] & 0x08);
|
|||
|
code.address |= (WORD)(codetmp[4] & 0x07);
|
|||
|
// Data
|
|||
|
code.data |= (codetmp[0] & 0x08)<<4;
|
|||
|
code.data |= (codetmp[1] & 0x07)<<4;
|
|||
|
code.data |= (codetmp[5] & 0x08);
|
|||
|
code.data |= (codetmp[0] & 0x07);
|
|||
|
|
|||
|
m_GenieCode.push_back( code );
|
|||
|
} else
|
|||
|
if( no == 8 ) {
|
|||
|
// Address
|
|||
|
code.address |= 0x8000;
|
|||
|
code.address |= (WORD)(codetmp[3] & 0x07)<<12;
|
|||
|
code.address |= (WORD)(codetmp[4] & 0x08)<< 8;
|
|||
|
code.address |= (WORD)(codetmp[5] & 0x07)<< 8;
|
|||
|
code.address |= (WORD)(codetmp[1] & 0x08)<< 4;
|
|||
|
code.address |= (WORD)(codetmp[2] & 0x07)<< 4;
|
|||
|
code.address |= (WORD)(codetmp[3] & 0x08);
|
|||
|
code.address |= (WORD)(codetmp[4] & 0x07);
|
|||
|
// Data
|
|||
|
code.data |= (codetmp[0] & 0x08)<<4;
|
|||
|
code.data |= (codetmp[1] & 0x07)<<4;
|
|||
|
code.data |= (codetmp[7] & 0x08);
|
|||
|
code.data |= (codetmp[0] & 0x07);
|
|||
|
// Data
|
|||
|
code.cmp |= (codetmp[6] & 0x08)<<4;
|
|||
|
code.cmp |= (codetmp[7] & 0x07)<<4;
|
|||
|
code.cmp |= (codetmp[5] & 0x08);
|
|||
|
code.cmp |= (codetmp[6] & 0x07);
|
|||
|
|
|||
|
m_GenieCode.push_back( code );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
GenieCodeProcess();
|
|||
|
}
|
|||
|
|
|||
|
FCLOSE( fp );
|
|||
|
}
|
|||
|
|
|||
|
void NES::GenieCodeProcess()
|
|||
|
{
|
|||
|
WORD addr;
|
|||
|
|
|||
|
for( INT i = 0; i < m_GenieCode.size(); i++ ) {
|
|||
|
addr = m_GenieCode[i].address;
|
|||
|
if( addr & 0x8000 ) {
|
|||
|
// 8character codes
|
|||
|
if( CPU_MEM_BANK[addr>>13][addr&0x1FFF] == m_GenieCode[i].cmp ) {
|
|||
|
CPU_MEM_BANK[addr>>13][addr&0x1FFF] = m_GenieCode[i].data;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// 6character codes
|
|||
|
addr |= 0x8000;
|
|||
|
CPU_MEM_BANK[addr>>13][addr&0x1FFF] = m_GenieCode[i].data;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::DrawPad()
|
|||
|
{
|
|||
|
if( m_bMoviePlay ) {
|
|||
|
INT offset_h = 12;
|
|||
|
INT offset_v = Config.graphics.bAllLine?(240-18):(240-22);
|
|||
|
|
|||
|
DWORD dwData = pad->GetSyncData();
|
|||
|
for( INT i = 0; i < 4; i++ ) {
|
|||
|
BYTE Data = (BYTE)(dwData>>(i*8));
|
|||
|
if( m_MovieControl & (1<<i) ) {
|
|||
|
DrawBitmap( offset_h, offset_v, m_PadImg );
|
|||
|
|
|||
|
// KEY
|
|||
|
if( Data&(1<<4) ) DrawBitmap( offset_h+3, offset_v+1, m_KeyImg0 ); // U
|
|||
|
if( Data&(1<<5) ) DrawBitmap( offset_h+3, offset_v+5, m_KeyImg0 ); // D
|
|||
|
if( Data&(1<<6) ) DrawBitmap( offset_h+1, offset_v+3, m_KeyImg0 ); // L
|
|||
|
if( Data&(1<<7) ) DrawBitmap( offset_h+5, offset_v+3, m_KeyImg0 ); // R
|
|||
|
|
|||
|
// START,SELECT
|
|||
|
if( Data&(1<<2) ) DrawBitmap( offset_h+ 9, offset_v+5, m_KeyImg1 ); // SELECT
|
|||
|
if( Data&(1<<3) ) DrawBitmap( offset_h+13, offset_v+5, m_KeyImg1 ); // START
|
|||
|
|
|||
|
// A,B
|
|||
|
if( Data&(1<<0) ) DrawBitmap( offset_h+23, offset_v+3, m_KeyImg2 ); // A
|
|||
|
if( Data&(1<<1) ) DrawBitmap( offset_h+18, offset_v+3, m_KeyImg2 ); // B
|
|||
|
|
|||
|
offset_h += 30;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::DrawBitmap( INT x, INT y, LPBYTE lpBitmap )
|
|||
|
{
|
|||
|
INT i, j;
|
|||
|
INT h, v;
|
|||
|
LPBYTE pScn = ppu->GetScreenPtr()+8+(256+16)*y+x;
|
|||
|
LPBYTE pPtr;
|
|||
|
|
|||
|
h = (INT)*lpBitmap++;
|
|||
|
v = (INT)*lpBitmap++;
|
|||
|
|
|||
|
for( j = 0; j < v; j++ ) {
|
|||
|
pPtr = pScn;
|
|||
|
for( i = 0; i < h; i++ ) {
|
|||
|
if( *lpBitmap != 0xFF ) {
|
|||
|
*pPtr = *lpBitmap;
|
|||
|
}
|
|||
|
lpBitmap++;
|
|||
|
pPtr++;
|
|||
|
}
|
|||
|
pScn += 256+16;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// TapeDevice
|
|||
|
BOOL NES::TapePlay( const char* fname )
|
|||
|
{
|
|||
|
if( rom->IsNSF() )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if( IsTapePlay() || IsTapeRec() ) {
|
|||
|
TapeStop();
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "NES::TapePlay\n" );
|
|||
|
|
|||
|
if( !(m_fpTape = ::fopen( fname, "rb" )) ) {
|
|||
|
DEBUGOUT( "Tape play error. File not found.\n" );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD>
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
m_bTapePlay = TRUE;
|
|||
|
m_TapeCycles = 0;
|
|||
|
m_TapeOut = 0;
|
|||
|
|
|||
|
cpu->SetClockProcess( TRUE );
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
BOOL NES::TapeRec( const char* fname )
|
|||
|
{
|
|||
|
if( rom->IsNSF() )
|
|||
|
return FALSE;
|
|||
|
|
|||
|
if( IsTapePlay() || IsTapeRec() ) {
|
|||
|
TapeStop();
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "NES::TapeRec\n" );
|
|||
|
|
|||
|
if( !(m_fpTape = ::fopen( fname, "wb" )) ) {
|
|||
|
DEBUGOUT( "Tape rec error. File not found.\n" );
|
|||
|
// <20>t<EFBFBD>@<40>C<EFBFBD><43><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ł<EFBFBD>
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
m_bTapeRec = TRUE;
|
|||
|
m_TapeCycles = 0;
|
|||
|
m_TapeIn = 0;
|
|||
|
|
|||
|
cpu->SetClockProcess( TRUE );
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
void NES::TapeStop()
|
|||
|
{
|
|||
|
DirectDraw.SetMessageString( "Tape stop." );
|
|||
|
|
|||
|
if( !m_bBarcode ) {
|
|||
|
cpu->SetClockProcess( FALSE );
|
|||
|
}
|
|||
|
|
|||
|
m_bTapePlay = m_bTapeRec = FALSE;
|
|||
|
FCLOSE( m_fpTape );
|
|||
|
}
|
|||
|
|
|||
|
void NES::Tape( INT cycles )
|
|||
|
{
|
|||
|
if( !(IsTapePlay() || IsTapeRec()) ) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
if( (m_TapeCycles-=(double)cycles) > 0 )
|
|||
|
return;
|
|||
|
|
|||
|
m_TapeCycles += (nescfg->CpuClock / 32000.0);
|
|||
|
// m_TapeCycles += (nescfg->CpuClock / 22050.0); // <20>x<EFBFBD><78><EFBFBD><EFBFBD><EFBFBD>ă_<C483><5F><EFBFBD><EFBFBD><EFBFBD>ۂ<EFBFBD>
|
|||
|
|
|||
|
if( m_bTapePlay ) {
|
|||
|
INT data = ::fgetc( m_fpTape );
|
|||
|
if( data != EOF ) {
|
|||
|
if( (data&0xFF) >= 0x8C ) {
|
|||
|
m_TapeOut = 0x02;
|
|||
|
} else
|
|||
|
if( (data&0xFF) <= 0x74 ) {
|
|||
|
m_TapeOut = 0x00;
|
|||
|
}
|
|||
|
} else {
|
|||
|
TapeStop();
|
|||
|
}
|
|||
|
}
|
|||
|
if( m_bTapeRec ) {
|
|||
|
::fputc( (int)((m_TapeIn&7)==7)?0x90:0x70, m_fpTape );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::Barcode( INT cycles )
|
|||
|
{
|
|||
|
if( m_bBarcode ) {
|
|||
|
if( (m_BarcodeCycles+=cycles) > 1000 ) {
|
|||
|
m_BarcodeCycles = 0;
|
|||
|
// <20><><EFBFBD>~<7E>H
|
|||
|
if( m_BarcodeData[m_BarcodePtr] != 0xFF ) {
|
|||
|
m_BarcodeOut = m_BarcodeData[m_BarcodePtr++];
|
|||
|
} else {
|
|||
|
m_bBarcode = FALSE;
|
|||
|
m_BarcodeOut = 0;
|
|||
|
DEBUGOUT( "Barcode data trasnfer complete!!\n" );
|
|||
|
|
|||
|
if( !(IsTapePlay() || IsTapeRec()) ) {
|
|||
|
cpu->SetClockProcess( FALSE );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::SetBarcodeData( LPBYTE code, INT len )
|
|||
|
{
|
|||
|
if( rom->GetPROM_CRC() == 0x67898319 ) { // Barcode World (J)
|
|||
|
SetBarcode2Data( code, len );
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
DEBUGOUT( "NES::SetBarcodeData code=%s len=%d\n", code, len );
|
|||
|
|
|||
|
bool prefix_parity_type[10][6] = {
|
|||
|
{0,0,0,0,0,0}, {0,0,1,0,1,1}, {0,0,1,1,0,1}, {0,0,1,1,1,0},
|
|||
|
{0,1,0,0,1,1}, {0,1,1,0,0,1}, {0,1,1,1,0,0}, {0,1,0,1,0,1},
|
|||
|
{0,1,0,1,1,0}, {0,1,1,0,1,0}
|
|||
|
};
|
|||
|
bool data_left_odd[10][7] = {
|
|||
|
{0,0,0,1,1,0,1}, {0,0,1,1,0,0,1}, {0,0,1,0,0,1,1}, {0,1,1,1,1,0,1},
|
|||
|
{0,1,0,0,0,1,1}, {0,1,1,0,0,0,1}, {0,1,0,1,1,1,1}, {0,1,1,1,0,1,1},
|
|||
|
{0,1,1,0,1,1,1}, {0,0,0,1,0,1,1}
|
|||
|
};
|
|||
|
bool data_left_even[10][7] = {
|
|||
|
{0,1,0,0,1,1,1}, {0,1,1,0,0,1,1}, {0,0,1,1,0,1,1}, {0,1,0,0,0,0,1},
|
|||
|
{0,0,1,1,1,0,1}, {0,1,1,1,0,0,1}, {0,0,0,0,1,0,1}, {0,0,1,0,0,0,1},
|
|||
|
{0,0,0,1,0,0,1}, {0,0,1,0,1,1,1}
|
|||
|
};
|
|||
|
bool data_right[10][7] = {
|
|||
|
{1,1,1,0,0,1,0}, {1,1,0,0,1,1,0}, {1,1,0,1,1,0,0}, {1,0,0,0,0,1,0},
|
|||
|
{1,0,1,1,1,0,0}, {1,0,0,1,1,1,0}, {1,0,1,0,0,0,0}, {1,0,0,0,1,0,0},
|
|||
|
{1,0,0,1,0,0,0}, {1,1,1,0,1,0,0}
|
|||
|
};
|
|||
|
|
|||
|
INT i, j, count = 0;;
|
|||
|
|
|||
|
// <20><><EFBFBD>l<EFBFBD>ɕϊ<C995>
|
|||
|
for( i = 0; i < len; i++ ) {
|
|||
|
code[i] = code[i]-'0';
|
|||
|
}
|
|||
|
|
|||
|
// <20><><EFBFBD>t<EFBFBD>g<EFBFBD>}<7D>[<5B>W<EFBFBD><57>
|
|||
|
for( i = 0; i < 32; i++ ) {
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
}
|
|||
|
// <20><><EFBFBD>t<EFBFBD>g<EFBFBD>K<EFBFBD>[<5B>h<EFBFBD>o<EFBFBD>[
|
|||
|
m_BarcodeData[count++] = 0x00;
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
m_BarcodeData[count++] = 0x00;
|
|||
|
|
|||
|
if( len == 13 ) {
|
|||
|
#if 0
|
|||
|
// <20>`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD>f<EFBFBD>B<EFBFBD>W<EFBFBD>b<EFBFBD>g<EFBFBD>̍Čv<C48C>Z
|
|||
|
INT sum = 0;
|
|||
|
for( i = 0; i < 12; i++ ) {
|
|||
|
sum += (i&1)?(code[i]*3):code[i];
|
|||
|
}
|
|||
|
code[12] = (10-(sum%10))%10;
|
|||
|
// test start
|
|||
|
// INT cs = (10-(sum%10))%10;
|
|||
|
// if( cs == 0 ) {
|
|||
|
// cs = 9;
|
|||
|
// } else {
|
|||
|
// cs--;
|
|||
|
// }
|
|||
|
// code[12] = cs;
|
|||
|
// test end
|
|||
|
#endif
|
|||
|
// <20><><EFBFBD><EFBFBD>6<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD>N<EFBFBD>^
|
|||
|
for( i = 0; i < 6; i++ ) {
|
|||
|
if( prefix_parity_type[code[0]][i] ) {
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD>p<EFBFBD><70><EFBFBD>e<EFBFBD>B
|
|||
|
for( j = 0; j < 7; j++ ) {
|
|||
|
m_BarcodeData[count++] = data_left_even[code[i+1]][j]?0x00:0x08;
|
|||
|
}
|
|||
|
} else {
|
|||
|
// <20><EFBFBD>p<EFBFBD><70><EFBFBD>e<EFBFBD>B
|
|||
|
for( j = 0; j < 7; j++ ) {
|
|||
|
m_BarcodeData[count++] = data_left_odd[code[i+1]][j]?0x00:0x08;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// <20>Z<EFBFBD><5A><EFBFBD>^<5E>[<5B>o<EFBFBD>[
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
m_BarcodeData[count++] = 0x00;
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
m_BarcodeData[count++] = 0x00;
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
|
|||
|
// <20>E<EFBFBD><45>5<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD>N<EFBFBD>^<5E>ƃ`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD>f<EFBFBD>B<EFBFBD>W<EFBFBD>b<EFBFBD>g
|
|||
|
for( i = 7; i < 13; i++ ) {
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD>p<EFBFBD><70><EFBFBD>e<EFBFBD>B
|
|||
|
for( j = 0; j < 7; j++ ) {
|
|||
|
m_BarcodeData[count++] = data_right[code[i]][j]?0x00:0x08;
|
|||
|
}
|
|||
|
}
|
|||
|
} else
|
|||
|
if( len == 8 ) {
|
|||
|
// <20>`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD>f<EFBFBD>B<EFBFBD>W<EFBFBD>b<EFBFBD>g<EFBFBD>̍Čv<C48C>Z
|
|||
|
INT sum = 0;
|
|||
|
for( i = 0; i < 7; i++ ) {
|
|||
|
sum += (i&1)?code[i]:(code[i]*3);
|
|||
|
}
|
|||
|
code[7] = (10-(sum%10))%10;
|
|||
|
|
|||
|
// <20><><EFBFBD><EFBFBD>4<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD>N<EFBFBD>^
|
|||
|
for( i = 0; i < 4; i++ ) {
|
|||
|
// <20><EFBFBD>p<EFBFBD><70><EFBFBD>e<EFBFBD>B
|
|||
|
for( j = 0; j < 7; j++ ) {
|
|||
|
m_BarcodeData[count++] = data_left_odd[code[i]][j]?0x00:0x08;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// <20>Z<EFBFBD><5A><EFBFBD>^<5E>[<5B>o<EFBFBD>[
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
m_BarcodeData[count++] = 0x00;
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
m_BarcodeData[count++] = 0x00;
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
|
|||
|
// <20>E<EFBFBD><45>3<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD>N<EFBFBD>^<5E>ƃ`<60>F<EFBFBD>b<EFBFBD>N<EFBFBD>f<EFBFBD>B<EFBFBD>W<EFBFBD>b<EFBFBD>g
|
|||
|
for( i = 4; i < 8; i++ ) {
|
|||
|
// <20><><EFBFBD><EFBFBD><EFBFBD>p<EFBFBD><70><EFBFBD>e<EFBFBD>B
|
|||
|
for( j = 0; j < 7; j++ ) {
|
|||
|
m_BarcodeData[count++] = data_right[code[i]][j]?0x00:0x08;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// <20><><EFBFBD>C<EFBFBD>g<EFBFBD>K<EFBFBD>[<5B>h<EFBFBD>o<EFBFBD>[
|
|||
|
m_BarcodeData[count++] = 0x00;
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
m_BarcodeData[count++] = 0x00;
|
|||
|
// <20><><EFBFBD>C<EFBFBD>g<EFBFBD>}<7D>[<5B>W<EFBFBD><57>
|
|||
|
for( i = 0; i < 32; i++ ) {
|
|||
|
m_BarcodeData[count++] = 0x08;
|
|||
|
}
|
|||
|
// <20>I<EFBFBD><49><EFBFBD>}<7D>[<5B>N
|
|||
|
m_BarcodeData[count++] = 0xFF;
|
|||
|
|
|||
|
// <20>]<5D><><EFBFBD>J<EFBFBD>n
|
|||
|
m_bBarcode = TRUE;
|
|||
|
m_BarcodeCycles = 0;
|
|||
|
m_BarcodePtr = 0;
|
|||
|
m_BarcodeOut = 0x08;
|
|||
|
|
|||
|
cpu->SetClockProcess( TRUE );
|
|||
|
|
|||
|
DEBUGOUT( "BARCODE DATA MAX:%d\n", count );
|
|||
|
}
|
|||
|
|
|||
|
BYTE NES::Barcode2( void )
|
|||
|
{
|
|||
|
BYTE ret = 0x00;
|
|||
|
|
|||
|
if( !m_bBarcode2 || m_Barcode2seq < 0 )
|
|||
|
return ret;
|
|||
|
|
|||
|
switch( m_Barcode2seq ) {
|
|||
|
case 0:
|
|||
|
m_Barcode2seq++;
|
|||
|
m_Barcode2ptr = 0;
|
|||
|
ret = 0x04; // d3
|
|||
|
break;
|
|||
|
|
|||
|
case 1:
|
|||
|
m_Barcode2seq++;
|
|||
|
m_Barcode2bit = m_Barcode2data[m_Barcode2ptr];
|
|||
|
m_Barcode2cnt = 0;
|
|||
|
ret = 0x04; // d3
|
|||
|
break;
|
|||
|
|
|||
|
case 2:
|
|||
|
ret = (m_Barcode2bit&0x01)?0x00:0x04; // Bit rev.
|
|||
|
m_Barcode2bit >>= 1;
|
|||
|
if( ++m_Barcode2cnt > 7 ) {
|
|||
|
m_Barcode2seq++;
|
|||
|
}
|
|||
|
break;
|
|||
|
case 3:
|
|||
|
if( ++m_Barcode2ptr > 19 ) {
|
|||
|
m_bBarcode2 = FALSE;
|
|||
|
m_Barcode2seq = -1;
|
|||
|
} else {
|
|||
|
m_Barcode2seq = 1;
|
|||
|
}
|
|||
|
break;
|
|||
|
default:
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
return ret;
|
|||
|
}
|
|||
|
|
|||
|
void NES::SetBarcode2Data( LPBYTE code, INT len )
|
|||
|
{
|
|||
|
DEBUGOUT( "NES::SetBarcodeData2 code=%s len=%d\n", code, len );
|
|||
|
|
|||
|
if( len < 13 )
|
|||
|
return;
|
|||
|
|
|||
|
m_bBarcode2 = TRUE;
|
|||
|
m_Barcode2seq = 0;
|
|||
|
m_Barcode2ptr = 0;
|
|||
|
|
|||
|
::strcpy( (char*)m_Barcode2data, (char*)code );
|
|||
|
|
|||
|
m_Barcode2data[13] = 'S';
|
|||
|
m_Barcode2data[14] = 'U';
|
|||
|
m_Barcode2data[15] = 'N';
|
|||
|
m_Barcode2data[16] = 'S';
|
|||
|
m_Barcode2data[17] = 'O';
|
|||
|
m_Barcode2data[18] = 'F';
|
|||
|
m_Barcode2data[19] = 'T';
|
|||
|
}
|
|||
|
|
|||
|
//----------Dump RAM----------------------------------------------------------------------
|
|||
|
void NES::Dump_RAM0()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(RAM); i++ ) {
|
|||
|
if( RAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(RAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "ram0" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( RAM, sizeof(RAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void NES::Dump_VRAM()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(VRAM); i++ ) {
|
|||
|
if( VRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(VRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "vram" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( VRAM, sizeof(VRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void NES::Dump_CRAM()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(CRAM); i++ ) {
|
|||
|
if( CRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(CRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "cram" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( CRAM, sizeof(CRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void NES::Dump_YCRAM()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(YCRAM); i++ ) {
|
|||
|
if( YCRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(YCRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "YCRAM" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( YCRAM, sizeof(YCRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void NES::Dump_YSRAM()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(YSRAM); i++ ) {
|
|||
|
if( YSRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(YSRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "YSRAM" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( YSRAM, sizeof(YSRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void NES::Dump_YWRAM()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(YWRAM); i++ ) {
|
|||
|
if( YWRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(YWRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "YWRAM" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( YWRAM, sizeof(YWRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void NES::Dump_CPUHMEM()
|
|||
|
{
|
|||
|
BYTE CPUHRAM[32*1024];
|
|||
|
memcpy( CPUHRAM+0x0000, CPU_MEM_BANK[4], 0x2000 );
|
|||
|
memcpy( CPUHRAM+0x2000, CPU_MEM_BANK[5], 0x2000 );
|
|||
|
memcpy( CPUHRAM+0x4000, CPU_MEM_BANK[6], 0x2000 );
|
|||
|
memcpy( CPUHRAM+0x6000, CPU_MEM_BANK[7], 0x2000 );
|
|||
|
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(CPUHRAM); i++ ) {
|
|||
|
if( CPUHRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(CPUHRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "CPUHRAM" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( CPUHRAM, sizeof(CPUHRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
void NES::Dump_CPULMEM()
|
|||
|
{
|
|||
|
BYTE CPULRAM[16*1024];
|
|||
|
memcpy( CPULRAM+0x0000, CPU_MEM_BANK[2], 0x2000 );
|
|||
|
memcpy( CPULRAM+0x2000, CPU_MEM_BANK[3], 0x2000 );
|
|||
|
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(CPULRAM); i++ ) {
|
|||
|
if( CPULRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(CPULRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "CPULRAM" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( CPULRAM, sizeof(CPULRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::Dump_BDRAM()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(BDRAM); i++ ) {
|
|||
|
if( BDRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(BDRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "BDRAM" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( BDRAM, sizeof(BDRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void NES::Dump_JDRAM()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(JDRAM); i++ ) {
|
|||
|
if( JDRAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(JDRAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "JDRAM" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( JDRAM, sizeof(JDRAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//----------------------------------------------------------------------------------------
|
|||
|
void NES::Dump_ERAM()
|
|||
|
{
|
|||
|
int i;
|
|||
|
for( i = 0; i < sizeof(ERAM); i++ ) {
|
|||
|
if( ERAM[i] != 0x00 )
|
|||
|
break;
|
|||
|
}
|
|||
|
if( i < sizeof(ERAM) ) {
|
|||
|
string pathstr, tempstr;
|
|||
|
if( Config.path.szRamPath ) {
|
|||
|
pathstr = CPathlib::CreatePath( CApp::GetModulePath(), Config.path.szRamPath );
|
|||
|
::CreateDirectory( pathstr.c_str(), NULL );
|
|||
|
} else {
|
|||
|
pathstr = rom->GetRomPath();
|
|||
|
}
|
|||
|
tempstr = CPathlib::MakePathExt( pathstr.c_str(), rom->GetRomName(), "ERAM" );
|
|||
|
FILE* fp = NULL;
|
|||
|
try
|
|||
|
{
|
|||
|
if( !(fp = ::fopen( tempstr.c_str(), "wb" )) ) {
|
|||
|
LPCSTR szErrStr = CApp::GetErrorString( IDS_ERROR_OPEN );
|
|||
|
sprintf( szErrorString, szErrStr, tempstr.c_str() );
|
|||
|
throw szErrorString;
|
|||
|
}
|
|||
|
if( ::fwrite( ERAM, sizeof(ERAM), 1, fp ) != 1 ) {
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_WRITE );
|
|||
|
}
|
|||
|
FCLOSE( fp );
|
|||
|
} catch( CHAR* str ) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw str;
|
|||
|
#ifndef _DEBUG
|
|||
|
} catch(...) {
|
|||
|
FCLOSE( fp );
|
|||
|
throw CApp::GetErrorString( IDS_ERROR_UNKNOWN );
|
|||
|
#endif
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
//----------------------------------------------------------------------------------------
|