AxibugEmuOnline/References/VirtuaNESex_src_191105/NES/Nes.cpp
2024-08-05 17:58:53 +08:00

4269 lines
104 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//////////////////////////////////////////////////////////////////////////
// //
// 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 );
}
/*
<09>`<60><><EFBFBD>V<EFBFBD>[<5B>P<EFBFBD><50><EFBFBD>X
0 <09>_<EFBFBD>~<7E>[<5B>X<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><43>(<28>`<60><EFBFBD>Ȃ<EFBFBD>)
1 - 239 <09>`<60><>
240 <09>_<EFBFBD>~<7E>[<5B>X<EFBFBD>L<EFBFBD><4C><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>C<EFBFBD><43>,VBLANK<4E>t<EFBFBD><74><EFBFBD>OON
241 VINT<4E><54><EFBFBD><EFBFBD>,NMI<4D><49><EFBFBD><EFBFBD>
242-261 VINT<4E><54><EFBFBD><EFBFBD>
261 VINT<4E><54><EFBFBD><EFBFBD>,VBLANK<4E>t<EFBFBD><74><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 );
// // <20>B<EFBFBD><EFBFBD><E892BC><EFBFBD>֎~<7E>̏ꍇ<CC8F>͒NjL<C78B>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
}
}
}
//----------------------------------------------------------------------------------------