AxibugEmuOnline/References/VirtuaNESex_src_191105/NES/Nes.cpp

4269 lines
104 KiB
C++
Raw Normal View History

2024-08-05 17:58:53 +08:00
//////////////////////////////////////////////////////////////////////////
// //
// 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( &reg, 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( &reg, 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( &reg, sizeof(REGSTAT) );
// Create Header
::memcpy( hdr.ID, "REG DATA", sizeof(hdr.ID) );
hdr.BlockVersion = 0x0210;
hdr.BlockSize = sizeof(REGSTAT);
// SAVE CPU STATE
R6502 R;
cpu->GetContext( R );
reg.cpureg.cpu.PC = R.PC;
reg.cpureg.cpu.A = R.A;
reg.cpureg.cpu.X = R.X;
reg.cpureg.cpu.Y = R.Y;
reg.cpureg.cpu.S = R.S;
reg.cpureg.cpu.P = R.P;
reg.cpureg.cpu.I = R.INT_pending;
INT cycles;
apu->GetFrameIRQ( cycles,
reg.cpureg.cpu.FrameIRQ_count,
reg.cpureg.cpu.FrameIRQ_type,
reg.cpureg.cpu.FrameIRQ,
reg.cpureg.cpu.FrameIRQ_occur );
reg.cpureg.cpu.FrameIRQ_cycles = (LONG)cycles; // <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( &reg, 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
}
}
}
//----------------------------------------------------------------------------------------