////////////////////////////////////////////////////////////////////////// // // // NES Emulation core // // Norix // // written 2001/02/22 // // last modify ----/--/-- // ////////////////////////////////////////////////////////////////////////// #ifndef __NES_INCLUDED__ #define __NES_INCLUDED__ #define WIN32_LEAN_AND_MEAN #include #include #include #include "typedef.h" #include "macro.h" #include "state.h" #include "cheat.h" #include "VsUnisystem.h" #include using namespace std; #define NES_PROFILER 0 // コンフィグ #define FETCH_CYCLES 8 typedef struct tagNESCONFIG { FLOAT BaseClock; // NTSC:21477270.0 PAL:21281364.0 FLOAT CpuClock; // NTSC: 1789772.5 PAL: 1773447.0 INT TotalScanlines; // NTSC: 262 PAL: 312 INT ScanlineCycles; // NTSC:1364 PAL:1362 INT HDrawCycles; // NTSC:1024 PAL:1024 INT HBlankCycles; // NTSC: 340 PAL: 338 INT ScanlineEndCycles; // NTSC: 4 PAL: 2 INT FrameCycles; // NTSC:29829.52 PAL:35468.94 INT FrameIrqCycles; // NTSC:29829.52 PAL:35468.94 INT FrameRate; // NTSC:60(59.94) PAL:50 FLOAT FramePeriod; // NTSC:16.683 PAL:20.0 } NESCONFIG, *LPNESCONFIG; extern NESCONFIG NESCONFIG_NTSC; extern NESCONFIG NESCONFIG_PAL; // class prototypes class CPU; class PPU; class APU; class ROM; class PAD; class Mapper; // // NES クラス // class NES { public: // メンバ変数 CPU* cpu; PPU* ppu; APU* apu; ROM* rom; PAD* pad; Mapper* mapper; NESCONFIG* nescfg; public: NES( const char* fname ); virtual ~NES(); // メンバ関数 // エミュレーション void Reset(); void SoftReset(); void Clock( INT cycles ); BYTE Read ( WORD addr ); void Write( WORD addr, BYTE data ); void EmulationCPU( INT basecycles ); void EmulationCPU_BeforeNMI( INT cycles ); void EmulateFrame( BOOL bDraw ); // For NSF void EmulateNSF(); void SetNsfPlay( INT songno, INT songmode ); void SetNsfStop(); BOOL IsNsfPlaying() { return m_bNsfPlaying; }; // IRQ type contorol enum IRQMETHOD { IRQ_HSYNC = 0, IRQ_CLOCK = 1 }; void SetIrqType( INT nType ) { nIRQtype = nType; }; INT GetIrqType() { return (INT)nIRQtype; }; // Frame-IRQ control (for Paris-Dakar Rally Special) void SetFrameIRQmode( BOOL bMode ) { bFrameIRQ = bMode; } BOOL GetFrameIRQmode() { return bFrameIRQ; } // NTSC/PAL void SetVideoMode( BOOL bMode ); BOOL GetVideoMode() { return bVideoMode; } // INT GetDiskNo(); void SoundSetup(); INT GetScanline() { return NES_scanline; } BOOL GetZapperHit() { return bZapper; } void GetZapperPos( LONG&x, LONG&y ) { x = ZapperX; y = ZapperY; } void SetZapperPos( LONG x, LONG y ) { ZapperX = x; ZapperY = y; } // ステートファイル // 0:ERROR 1:CRC OK -1:CRC ERR static INT IsStateFile( const char* fname, ROM* rom ); BOOL LoadState( const char* fname ); BOOL SaveState( const char* fname ); INT GetSAVERAM_SIZE() { return SAVERAM_SIZE; } void SetSAVERAM_SIZE( INT size ) { SAVERAM_SIZE = size; } // VS-Unisystem BYTE GetVSDipSwitch() { return m_VSDipValue; } void SetVSDipSwitch( BYTE v ) { m_VSDipValue = v; } VSDIPSWITCH* GetVSDipSwitchTable() { return m_VSDipTable; } // スナップショット BOOL Snapshot(); // For Movie // 0:ERROR 1:CRC OK -1:CRC ERR static INT IsMovieFile( const char* fname, ROM* rom ); BOOL IsMoviePlay() { return m_bMoviePlay; } BOOL IsMovieRec() { return m_bMovieRec; } BOOL MoviePlay( const char* fname ); BOOL MovieRec( const char* fname ); BOOL MovieRecAppend( const char* fname ); BOOL MovieStop(); // その他コントロール BOOL IsDiskThrottle() { return m_bDiskThrottle; } // BOOL IsBraking() { return m_bBrake; } // Debugger // 描画方式 enum RENDERMETHOD { POST_ALL_RENDER = 0, // スキャンライン分の命令実行後,レンダリング PRE_ALL_RENDER = 1, // レンダリングの実行後,スキャンライン分の命令実行 POST_RENDER = 2, // 表示期間分の命令実行後,レンダリング PRE_RENDER = 3, // レンダリング実行後,表示期間分の命令実行 TILE_RENDER = 4 // タイルベースレンダリング }; void SetRenderMethod( RENDERMETHOD type ) { RenderMethod = type; } RENDERMETHOD GetRenderMethod() { return RenderMethod; } // コマンド enum NESCOMMAND { NESCMD_NONE = 0, NESCMD_HWRESET, NESCMD_SWRESET, NESCMD_EXCONTROLLER, // Commandparam NESCMD_DISK_THROTTLE_ON, NESCMD_DISK_THROTTLE_OFF, NESCMD_DISK_EJECT, NESCMD_DISK_0A, NESCMD_DISK_0B, NESCMD_DISK_1A, NESCMD_DISK_1B, NESCMD_DISK_2A, NESCMD_DISK_2B, NESCMD_DISK_3A, NESCMD_DISK_3B, NESCMD_SOUND_MUTE, // CommandParam }; void Command( NESCOMMAND cmd ); BOOL CommandParam( NESCOMMAND cmd, INT param ); // For Movie void Movie(); void GetMovieInfo( WORD& wRecVersion, WORD& wVersion, DWORD& dwRecordFrames, DWORD& dwRecordTimes ); // For Cheat void CheatInitial(); BOOL IsCheatCodeAdd(); INT GetCheatCodeNum(); BOOL GetCheatCode( INT no, CHEATCODE& code ); void SetCheatCodeFlag( INT no, BOOL bEnable ); void SetCheatCodeAllFlag( BOOL bEnable, BOOL bKey ); void ReplaceCheatCode( INT no, CHEATCODE code ); void AddCheatCode( CHEATCODE code ); void DelCheatCode( INT no ); DWORD CheatRead( INT length, WORD addr ); void CheatWrite( INT length, WORD addr, DWORD data ); void CheatCodeProcess(); // For Genie void GenieInitial(); void GenieLoad( char* fname ); void GenieCodeProcess(); // TapeDevice BOOL IsTapePlay() { return m_bTapePlay; } BOOL IsTapeRec() { return m_bTapeRec; } BOOL TapePlay( const char* fname ); BOOL TapeRec( const char* fname ); void TapeStop(); void Tape( INT cycles ); // Barcode battler(Bandai) void SetBarcodeData( LPBYTE code, INT len ); void Barcode( INT cycles ); BOOL IsBarcodeEnable() { return m_bBarcode; }; BYTE GetBarcodeStatus() { return m_BarcodeOut; }; // Barcode world(Sunsoft/EPOCH) void SetBarcode2Data( LPBYTE code, INT len ); BYTE Barcode2( void ); BOOL IsBarcode2Enable() { return m_bBarcode2; }; // TurboFile void SetTurboFileBank( INT bank ) { m_TurboFileBank = bank; } INT GetTurboFileBank() { return m_TurboFileBank; } #if NES_PROFILER // TEST DWORD GetFrameTotalCycles() { return m_dwTotalCycle; } DWORD GetProfileTotalCycles() { return m_dwProfileTotalCycle; } DWORD GetProfileTotalCount() { return m_dwProfileTotalCount; } DWORD GetProfileCycles() { return m_dwProfileCycle; } #endif protected: // メンバ関数 // エミュレーション BYTE ReadReg ( WORD addr ); void WriteReg( WORD addr, BYTE data ); // ステートサブ BOOL ReadState( FILE* fp ); void WriteState( FILE* fp ); void LoadSRAM(); void SaveSRAM(); void LoadDISK(); void SaveDISK(); void LoadTurboFile(); void SaveTurboFile(); protected: // メンバ変数 INT nIRQtype; BOOL bVideoMode; BOOL bFrameIRQ; BOOL bZapper; LONG ZapperX, ZapperY; BOOL m_bPadStrobe; RENDERMETHOD RenderMethod; BOOL m_bDiskThrottle; SQWORD base_cycles; SQWORD emul_cycles; INT NES_scanline; INT SAVERAM_SIZE; // For VS-Unisystem BYTE m_VSDipValue; VSDIPSWITCH* m_VSDipTable; // Snapshot number INT m_nSnapNo; // For NSF BOOL m_bNsfPlaying; BOOL m_bNsfInit; INT m_nNsfSongNo; INT m_nNsfSongMode; // For Movie BOOL m_bMoviePlay; BOOL m_bMovieRec; WORD m_MovieVersion; FILE* m_fpMovie; MOVIEFILEHDR m_hedMovie; DWORD m_MovieControl; LONG m_MovieStepTotal; LONG m_MovieStep; INT m_CommandRequest; // For Tape BOOL m_bTapePlay; BOOL m_bTapeRec; FILE* m_fpTape; double m_TapeCycles; BYTE m_TapeIn; BYTE m_TapeOut; // For Barcode BOOL m_bBarcode; BYTE m_BarcodeOut; BYTE m_BarcodePtr; INT m_BarcodeCycles; BYTE m_BarcodeData[256]; // For Barcode BOOL m_bBarcode2; INT m_Barcode2seq; INT m_Barcode2ptr; INT m_Barcode2cnt; BYTE m_Barcode2bit; BYTE m_Barcode2data[32]; // For TurboFile INT m_TurboFileBank; // gameoption backup INT m_saveRenderMethod; INT m_saveIrqType; BOOL m_saveFrameIRQ; BOOL m_saveVideoMode; // For Cheat BOOL m_bCheatCodeAdd; vector m_CheatCode; // For Genie vector m_GenieCode; // For Movie pad display void DrawPad(); void DrawBitmap( INT x, INT y, LPBYTE lpBitmap ); static BYTE m_PadImg[]; static BYTE m_KeyImg0[]; static BYTE m_KeyImg1[]; static BYTE m_KeyImg2[]; #if NES_PROFILER // TEST BYTE m_ProfileEnable; DWORD m_dwTotalCycle; DWORD m_dwTotalTempCycle; DWORD m_dwProfileTotalCycle; DWORD m_dwProfileTotalCount; DWORD m_dwProfileCycle; DWORD m_dwProfileTempCycle; DWORD m_dwProfileAveCycle; DWORD m_dwProfileMaxCycle; // static BYTE Font6x8[]; // void DrawFont( INT x, INT y, BYTE chr, BYTE col ); // void DrawString( INT x, INT y, LPSTR str, BYTE col ); #endif static BYTE Font6x8[]; void DrawFont( INT x, INT y, BYTE chr, BYTE col ); void DrawString( INT x, INT y, LPSTR str, BYTE col ); private: }; #endif // !__NES_INCLUDED__