2011-02-20 08:40:22 +00:00
using System ;
2013-07-16 01:59:59 +00:00
using System.Collections.Generic ;
2011-01-11 02:55:51 +00:00
using System.Drawing ;
using System.Drawing.Imaging ;
using System.IO ;
2013-07-16 01:59:59 +00:00
using System.Linq ;
using System.Text ;
using System.Threading ;
2011-01-11 02:55:51 +00:00
using System.Windows.Forms ;
2013-11-03 23:45:44 +00:00
using BizHawk.Common ;
using BizHawk.Client.Common ;
2013-07-16 01:59:59 +00:00
using BizHawk.Emulation ;
2013-11-04 01:06:36 +00:00
using BizHawk.Emulation.Common ;
2013-11-13 23:36:21 +00:00
using BizHawk.Emulation.DiscSystem ;
2013-11-12 19:22:09 +00:00
using BizHawk.Emulation.Cores.Computers.Commodore64 ;
2013-11-13 03:32:25 +00:00
using BizHawk.Emulation.Cores.Calculators ;
using BizHawk.Emulation.Cores.Atari.Atari2600 ;
using BizHawk.Emulation.Cores.Atari.Atari7800 ;
using BizHawk.Emulation.Cores.ColecoVision ;
using BizHawk.Emulation.Cores.Intellivision ;
2013-11-13 23:36:21 +00:00
using BizHawk.Emulation.Cores.PCEngine ;
2013-11-14 13:15:41 +00:00
using BizHawk.Emulation.Cores.Nintendo.NES ;
2013-11-13 23:36:21 +00:00
using BizHawk.Emulation.Cores.Nintendo.SNES ;
2013-11-13 03:32:25 +00:00
using BizHawk.Emulation.Cores.Nintendo.N64 ;
2013-11-13 23:36:21 +00:00
using BizHawk.Emulation.Cores.Nintendo.Gameboy ;
using BizHawk.Emulation.Cores.Nintendo.GBA ;
using BizHawk.Emulation.Cores.Sega.MasterSystem ;
using BizHawk.Emulation.Cores.Sega.Genesis ;
using BizHawk.Emulation.Cores.Sega.Saturn ;
using BizHawk.Emulation.Cores.Sony.PSX ;
using BizHawk.Emulation.Cores.Sony.PSP ;
2013-10-25 00:57:23 +00:00
2013-11-03 03:54:37 +00:00
namespace BizHawk.Client.EmuHawk
2011-01-11 02:55:51 +00:00
{
2011-02-20 08:40:22 +00:00
public partial class MainForm : Form
{
2013-11-03 02:51:21 +00:00
#region Constructors and Initialization , and Tear down
2013-10-25 00:57:23 +00:00
2013-11-03 02:51:21 +00:00
private void MainForm_Load ( object sender , EventArgs e )
2013-10-25 00:57:23 +00:00
{
2013-11-10 02:32:47 +00:00
Text = "BizHawk" + ( VersionInfo . INTERIM ? " (interim) " : "" ) ;
2013-10-25 00:57:23 +00:00
2013-11-03 02:51:21 +00:00
//Hide Status bar icons
PlayRecordStatusButton . Visible = false ;
AVIStatusLabel . Visible = false ;
SetPauseStatusbarIcon ( ) ;
UpdateCheatStatus ( ) ;
RebootStatusBarIcon . Visible = false ;
2013-10-06 16:40:51 +00:00
}
2013-08-25 04:23:27 +00:00
2013-01-02 18:52:11 +00:00
static MainForm ( )
{
//if this isnt here, then our assemblyresolving hacks wont work due to the check for MainForm.INTERIM
//its.. weird. dont ask.
}
2012-07-23 00:33:30 +00:00
2011-02-20 08:40:22 +00:00
public MainForm ( string [ ] args )
{
2013-11-03 16:07:58 +00:00
GlobalWin . MainForm = this ;
2013-11-01 23:17:30 +00:00
Global . FirmwareManager = new FirmwareManager ( ) ;
2013-11-01 18:52:26 +00:00
Global . MovieSession = new MovieSession
{
2013-11-10 02:55:11 +00:00
Movie = new Movie ( ) ,
2013-11-03 16:07:58 +00:00
MessageCallback = GlobalWin . OSD . AddMessage ,
2013-11-01 18:52:26 +00:00
AskYesNoCallback = StateErrorAskUser
} ;
2013-11-27 23:35:32 +00:00
_mainWait = new AutoResetEvent ( false ) ;
2013-04-16 00:19:31 +00:00
Icon = Properties . Resources . logo ;
2011-03-21 00:54:30 +00:00
InitializeComponent ( ) ;
2011-09-11 00:11:46 +00:00
Global . Game = GameInfo . GetNullGame ( ) ;
2011-07-10 20:01:27 +00:00
if ( Global . Config . ShowLogWindow )
{
2012-03-09 21:36:55 +00:00
ShowConsole ( ) ;
2013-10-27 07:54:00 +00:00
DisplayLogWindowMenuItem . Checked = true ;
2011-07-10 20:01:27 +00:00
}
2011-09-24 16:19:38 +00:00
2013-11-27 23:35:32 +00:00
_throttle = new Throttle ( ) ;
2011-08-27 18:09:54 +00:00
2013-04-16 00:19:31 +00:00
FFMpeg . FFMpegPath = PathManager . MakeProgramRelativePath ( Global . Config . FFMpegPath ) ;
2011-07-09 19:54:24 +00:00
2013-11-16 16:30:20 +00:00
Global . CheatList = new CheatCollection ( ) ;
2013-11-04 15:52:59 +00:00
Global . CheatList . Changed + = ToolHelpers . UpdateCheatRelatedTools ;
2011-07-22 01:14:13 +00:00
UpdateStatusSlots ( ) ;
2012-12-02 16:17:42 +00:00
UpdateKeyPriorityIcon ( ) ;
2011-08-09 00:51:46 +00:00
2011-03-07 10:41:46 +00:00
//in order to allow late construction of this database, we hook up a delegate here to dearchive the data and provide it on demand
//we could background thread this later instead if we wanted to be real clever
2011-06-11 12:54:26 +00:00
NES . BootGodDB . GetDatabaseBytes = ( ) = >
{
2013-11-27 23:35:32 +00:00
using ( var NesCartFile = new HawkFile ( Path . Combine ( PathManager . GetExeDirectoryAbsolute ( ) , "gamedb" , "NesCarts.7z" ) ) . BindFirst ( ) )
2011-06-11 12:54:26 +00:00
return Util . ReadAllBytes ( NesCartFile . GetStream ( ) ) ;
2011-03-07 10:41:46 +00:00
} ;
2013-10-25 00:57:23 +00:00
2012-10-09 01:54:15 +00:00
Database . LoadDatabase ( Path . Combine ( PathManager . GetExeDirectoryAbsolute ( ) , "gamedb" , "gamedb.txt" ) ) ;
2011-01-11 02:55:51 +00:00
2011-03-21 00:54:30 +00:00
SyncPresentationMode ( ) ;
2011-01-11 02:55:51 +00:00
2011-02-20 08:40:22 +00:00
Load + = ( o , e ) = >
2011-02-21 16:35:42 +00:00
{
AllowDrop = true ;
DragEnter + = FormDragEnter ;
DragDrop + = FormDragDrop ;
} ;
2011-02-20 08:40:22 +00:00
2011-06-11 12:54:26 +00:00
Closing + = ( o , e ) = >
{
2013-11-05 16:37:05 +00:00
if ( GlobalWin . Tools . AskSave ( ) )
{
Global . CheatList . SaveOnClose ( ) ;
CloseGame ( ) ;
Global . MovieSession . Movie . Stop ( ) ;
GlobalWin . Tools . Close ( ) ;
SaveConfig ( ) ;
}
else
{
e . Cancel = true ;
}
2011-06-11 12:54:26 +00:00
} ;
2011-02-20 08:40:22 +00:00
ResizeBegin + = ( o , e ) = >
{
2013-11-03 16:07:58 +00:00
if ( GlobalWin . Sound ! = null ) GlobalWin . Sound . StopSound ( ) ;
2011-02-20 08:40:22 +00:00
} ;
ResizeEnd + = ( o , e ) = >
{
2013-11-03 16:07:58 +00:00
if ( GlobalWin . RenderPanel ! = null ) GlobalWin . RenderPanel . Resized = true ;
if ( GlobalWin . Sound ! = null ) GlobalWin . Sound . StartSound ( ) ;
2011-02-20 08:40:22 +00:00
} ;
2011-07-13 01:29:13 +00:00
Input . Initialize ( ) ;
InitControls ( ) ;
2013-12-10 17:58:12 +00:00
Global . CoreComm = new CoreComm ( ShowMessageCoreComm ) ;
2013-11-01 23:17:30 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
2013-10-27 16:26:37 +00:00
Global . Emulator = new NullEmulator ( Global . CoreComm ) ;
Global . ActiveController = Global . NullControls ;
Global . AutoFireController = Global . AutofireNullControls ;
2013-11-03 16:47:21 +00:00
Global . AutofireStickyXORAdapter . SetOnOffPatternFromConfig ( ) ;
2012-03-12 04:44:34 +00:00
#if WINDOWS
2013-11-03 16:07:58 +00:00
GlobalWin . Sound = new Sound ( Handle , GlobalWin . DSound ) ;
2012-03-12 04:44:34 +00:00
#else
Global . Sound = new Sound ( ) ;
#endif
2013-11-03 16:07:58 +00:00
GlobalWin . Sound . StartSound ( ) ;
2011-06-28 23:43:13 +00:00
RewireInputChain ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . Tools = new ToolManager ( ) ;
2011-02-05 21:00:59 +00:00
//TODO - replace this with some kind of standard dictionary-yielding parser in a separate component
string cmdRom = null ;
string cmdLoadState = null ;
2011-06-11 12:54:26 +00:00
string cmdMovie = null ;
2012-07-23 00:33:30 +00:00
string cmdDumpType = null ;
string cmdDumpName = null ;
2013-12-12 21:05:09 +00:00
if ( Global . Config . MainWndx > = 0 & & Global . Config . MainWndy > = 0 & & Global . Config . SaveWindowPosition )
{
Location = new Point ( Global . Config . MainWndx , Global . Config . MainWndy ) ;
}
2011-02-05 21:00:59 +00:00
for ( int i = 0 ; i < args . Length ; i + + )
2011-06-11 12:54:26 +00:00
{
2011-06-06 21:08:38 +00:00
//for some reason sometimes visual studio will pass this to us on the commandline. it makes no sense.
if ( args [ i ] = = ">" )
{
i + + ;
string stdout = args [ i ] ;
Console . SetOut ( new StreamWriter ( stdout ) ) ;
continue ;
}
2011-02-05 21:00:59 +00:00
string arg = args [ i ] . ToLower ( ) ;
2013-09-07 01:38:24 +00:00
if ( arg . StartsWith ( "--load-slot=" ) )
2013-12-12 21:05:09 +00:00
{
2013-09-07 01:38:24 +00:00
cmdLoadState = arg . Substring ( arg . IndexOf ( '=' ) + 1 ) ;
2013-12-12 21:05:09 +00:00
}
2013-09-07 01:38:24 +00:00
else if ( arg . StartsWith ( "--movie=" ) )
2013-12-12 21:05:09 +00:00
{
2013-09-07 01:38:24 +00:00
cmdMovie = arg . Substring ( arg . IndexOf ( '=' ) + 1 ) ;
2013-12-12 21:05:09 +00:00
}
2013-09-07 01:38:24 +00:00
else if ( arg . StartsWith ( "--dump-type=" ) )
2013-12-12 21:05:09 +00:00
{
2013-09-07 01:38:24 +00:00
cmdDumpType = arg . Substring ( arg . IndexOf ( '=' ) + 1 ) ;
2013-12-12 21:05:09 +00:00
}
2013-09-07 01:38:24 +00:00
else if ( arg . StartsWith ( "--dump-name=" ) )
2013-12-12 21:05:09 +00:00
{
2013-09-07 01:38:24 +00:00
cmdDumpName = arg . Substring ( arg . IndexOf ( '=' ) + 1 ) ;
2013-12-12 21:05:09 +00:00
}
2013-09-07 01:38:24 +00:00
else if ( arg . StartsWith ( "--dump-length=" ) )
2013-12-12 21:05:09 +00:00
{
2013-11-27 23:35:32 +00:00
int . TryParse ( arg . Substring ( arg . IndexOf ( '=' ) + 1 ) , out _autoDumpLength ) ;
2013-12-12 21:05:09 +00:00
}
2013-09-29 14:15:26 +00:00
else if ( arg . StartsWith ( "--dump-close" ) )
2013-12-12 21:05:09 +00:00
{
2013-09-07 01:38:24 +00:00
autoCloseOnDump = true ;
2013-12-12 21:05:09 +00:00
}
else if ( arg . StartsWith ( "--fullscreen" ) )
{
ToggleFullscreen ( ) ;
}
2013-09-07 01:38:24 +00:00
else
2013-12-12 21:05:09 +00:00
{
2013-09-07 01:38:24 +00:00
cmdRom = arg ;
2013-12-12 21:05:09 +00:00
}
2011-02-05 21:00:59 +00:00
}
2011-03-19 09:12:56 +00:00
if ( cmdRom ! = null )
{
//Commandline should always override auto-load
2011-02-05 21:00:59 +00:00
LoadRom ( cmdRom ) ;
2011-03-19 09:12:56 +00:00
if ( Global . Game = = null )
{
2011-05-22 00:13:12 +00:00
MessageBox . Show ( "Failed to load " + cmdRom + " specified on commandline" ) ;
2011-03-19 09:12:56 +00:00
}
}
2013-09-07 03:15:29 +00:00
else if ( Global . Config . RecentRoms . AutoLoad & & ! Global . Config . RecentRoms . Empty )
{
2013-09-06 21:23:59 +00:00
LoadRomFromRecent ( Global . Config . RecentRoms [ 0 ] ) ;
2013-09-07 03:15:29 +00:00
}
2011-01-19 04:18:33 +00:00
2011-06-11 12:54:26 +00:00
if ( cmdMovie ! = null )
{
2011-06-30 02:30:06 +00:00
if ( Global . Game = = null )
2012-09-03 19:42:53 +00:00
{
2013-11-27 23:35:32 +00:00
OpenRom ( ) ;
2012-09-03 19:42:53 +00:00
}
else
2011-06-30 02:30:06 +00:00
{
2013-11-27 23:35:32 +00:00
var movie = new Movie ( cmdMovie ) ;
2013-12-03 18:08:45 +00:00
Global . MovieSession . ReadOnly = true ;
2012-07-23 00:33:30 +00:00
// if user is dumping and didnt supply dump length, make it as long as the loaded movie
2013-11-27 23:35:32 +00:00
if ( _autoDumpLength = = 0 )
2012-09-03 19:42:53 +00:00
{
2013-11-30 03:10:05 +00:00
_autoDumpLength = movie . InputLogLength ;
2012-09-03 19:42:53 +00:00
}
2013-11-10 02:55:11 +00:00
StartNewMovie ( movie , false ) ;
2011-06-30 02:30:06 +00:00
Global . Config . RecentMovies . Add ( cmdMovie ) ;
}
2011-06-11 12:54:26 +00:00
}
2013-09-07 03:15:29 +00:00
else if ( Global . Config . RecentMovies . AutoLoad & & ! Global . Config . RecentMovies . Empty )
2011-06-11 12:54:26 +00:00
{
2011-06-30 02:30:06 +00:00
if ( Global . Game = = null )
2012-09-03 19:42:53 +00:00
{
2013-11-27 23:35:32 +00:00
OpenRom ( ) ;
2012-09-03 19:42:53 +00:00
}
else
2011-06-30 02:30:06 +00:00
{
2013-11-10 02:55:11 +00:00
StartNewMovie ( new Movie ( Global . Config . RecentMovies [ 0 ] ) , false ) ;
2011-06-30 02:30:06 +00:00
}
2011-06-11 12:54:26 +00:00
}
2011-05-21 22:37:15 +00:00
2011-03-19 09:12:56 +00:00
if ( cmdLoadState ! = null & & Global . Game ! = null )
2012-09-03 19:42:53 +00:00
{
2011-02-05 21:00:59 +00:00
LoadState ( "QuickSave" + cmdLoadState ) ;
2012-09-03 19:42:53 +00:00
}
2011-09-17 00:25:34 +00:00
else if ( Global . Config . AutoLoadLastSaveSlot & & Global . Game ! = null )
2012-09-03 19:42:53 +00:00
{
2013-11-27 23:35:32 +00:00
LoadState ( "QuickSave" + Global . Config . SaveSlot ) ;
2012-09-03 19:42:53 +00:00
}
2011-02-05 21:00:59 +00:00
2013-09-07 01:38:24 +00:00
if ( Global . Config . RecentWatches . AutoLoad )
2012-08-15 01:03:27 +00:00
{
2013-11-28 20:02:32 +00:00
GlobalWin . Tools . LoadRamWatch ( ! Global . Config . DisplayRamWatch ) ;
2012-08-15 01:03:27 +00:00
}
2013-12-12 21:05:09 +00:00
2013-09-07 03:15:29 +00:00
if ( Global . Config . RecentSearches . AutoLoad )
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < RamSearch > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2011-06-11 12:54:26 +00:00
if ( Global . Config . AutoLoadHexEditor )
2013-09-07 03:15:29 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < HexEditor > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2013-09-07 03:15:29 +00:00
if ( Global . Config . RecentCheats . AutoLoad )
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < Cheats > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2013-10-20 18:02:43 +00:00
if ( Global . Config . AutoLoadNESPPU & & Global . Emulator is NES )
2013-09-07 03:15:29 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < NESPPU > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2013-10-20 18:02:43 +00:00
if ( Global . Config . AutoLoadNESNameTable & & Global . Emulator is NES )
2013-09-07 03:15:29 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < NESNameTableViewer > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2013-10-20 18:02:43 +00:00
if ( Global . Config . AutoLoadNESDebugger & & Global . Emulator is NES )
2013-09-07 03:15:29 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < NESDebugger > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2013-10-20 18:02:43 +00:00
if ( Global . Config . NESGGAutoload & & Global . Emulator is NES )
2013-09-07 03:15:29 +00:00
{
2013-11-27 23:35:32 +00:00
LoadGameGenieEc ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2013-10-20 18:02:43 +00:00
if ( Global . Config . AutoLoadGBGPUView & & Global . Emulator is Gameboy )
2013-09-07 03:15:29 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < GBGPUView > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2011-06-11 22:32:12 +00:00
if ( Global . Config . AutoloadTAStudio )
2012-10-29 22:57:15 +00:00
{
2011-06-11 22:32:12 +00:00
LoadTAStudio ( ) ;
2012-10-29 22:57:15 +00:00
}
2013-12-12 21:05:09 +00:00
2012-10-29 22:57:15 +00:00
if ( Global . Config . AutoloadVirtualPad )
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < VirtualPadForm > ( ) ;
2012-10-29 22:57:15 +00:00
}
2013-12-12 21:05:09 +00:00
2012-01-10 01:30:17 +00:00
if ( Global . Config . AutoLoadLuaConsole )
2013-09-07 03:15:29 +00:00
{
2012-01-10 01:30:17 +00:00
OpenLuaConsole ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2013-10-20 18:02:43 +00:00
if ( Global . Config . PCEBGViewerAutoload & & Global . Emulator is PCEngine )
2013-09-07 03:15:29 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < PCEBGViewer > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2013-10-20 18:02:43 +00:00
if ( Global . Config . AutoLoadSNESGraphicsDebugger & & Global . Emulator is LibsnesCore )
2013-09-07 03:15:29 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < SNESGraphicsDebugger > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2012-09-30 03:09:41 +00:00
if ( Global . Config . TraceLoggerAutoLoad )
2012-09-30 13:38:37 +00:00
{
2013-10-27 16:26:37 +00:00
if ( Global . CoreComm . CpuTraceAvailable )
2012-09-30 13:38:37 +00:00
{
LoadTraceLogger ( ) ;
}
}
2011-02-20 08:40:22 +00:00
2011-06-11 12:54:26 +00:00
if ( Global . Config . DisplayStatusBar = = false )
2013-09-07 03:15:29 +00:00
{
2013-10-27 15:53:37 +00:00
MainStatusBar . Visible = false ;
2013-09-07 03:15:29 +00:00
}
2011-06-11 12:54:26 +00:00
else
2013-09-07 03:15:29 +00:00
{
2013-10-27 07:54:00 +00:00
DisplayStatusBarMenuItem . Checked = true ;
2013-09-07 03:15:29 +00:00
}
2011-06-10 04:41:33 +00:00
2011-02-20 08:40:22 +00:00
if ( Global . Config . StartPaused )
2013-09-07 03:15:29 +00:00
{
2011-02-20 08:40:22 +00:00
PauseEmulator ( ) ;
2013-09-07 03:15:29 +00:00
}
2011-09-11 00:11:46 +00:00
2013-11-10 02:32:47 +00:00
if ( ! VersionInfo . INTERIM )
2011-09-11 00:11:46 +00:00
{
2013-10-27 13:53:28 +00:00
NESDebuggerMenuItem . Enabled = false ;
2011-09-11 00:11:46 +00:00
}
2012-07-23 00:33:30 +00:00
// start dumping, if appropriate
if ( cmdDumpType ! = null & & cmdDumpName ! = null )
{
RecordAVI ( cmdDumpType , cmdDumpName ) ;
}
2012-10-10 22:52:11 +00:00
UpdateStatusSlots ( ) ;
2013-10-12 15:40:20 +00:00
2013-11-27 23:35:32 +00:00
_renderTarget . Paint + = ( o , e ) = >
2013-10-12 15:40:20 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-10-14 03:22:33 +00:00
} ;
2011-02-21 09:48:53 +00:00
}
2011-02-20 08:40:22 +00:00
public void ProgramRunLoop ( )
{
2012-02-24 20:38:35 +00:00
CheckMessages ( ) ;
LogConsole . PositionConsole ( ) ;
2011-02-20 08:40:22 +00:00
for ( ; ; )
{
2011-07-09 22:09:39 +00:00
Input . Instance . Update ( ) ;
2011-07-10 07:39:40 +00:00
//handle events and dispatch as a hotkey action, or a hotkey button, or an input button
ProcessInput ( ) ;
2013-11-03 16:47:21 +00:00
Global . ClientControls . LatchFromPhysical ( GlobalWin . HotkeyCoalescer ) ;
2013-11-03 16:07:58 +00:00
Global . ActiveController . LatchFromPhysical ( GlobalWin . ControllerInputCoalescer ) ;
2012-09-15 13:11:29 +00:00
2013-11-01 22:56:55 +00:00
Global . ActiveController . OR_FromLogical ( Global . ClickyVirtualPadController ) ;
2013-11-03 16:07:58 +00:00
Global . AutoFireController . LatchFromPhysical ( GlobalWin . ControllerInputCoalescer ) ;
2012-09-15 13:11:29 +00:00
2013-11-03 16:47:21 +00:00
if ( Global . ClientControls [ "Autohold" ] )
2012-09-15 13:11:29 +00:00
{
2013-11-01 22:56:55 +00:00
Global . StickyXORAdapter . MassToggleStickyState ( Global . ActiveController . PressedButtons ) ;
2013-11-03 16:47:21 +00:00
Global . AutofireStickyXORAdapter . MassToggleStickyState ( Global . AutoFireController . PressedButtons ) ;
2012-09-15 13:11:29 +00:00
}
2013-11-03 16:47:21 +00:00
else if ( Global . ClientControls [ "Autofire" ] )
2013-03-09 20:10:04 +00:00
{
2013-11-03 16:47:21 +00:00
Global . AutofireStickyXORAdapter . MassToggleStickyState ( Global . ActiveController . PressedButtons ) ;
2013-03-09 20:10:04 +00:00
}
2012-09-15 13:11:29 +00:00
2013-11-03 16:07:58 +00:00
if ( GlobalWin . Tools . Has < LuaConsole > ( ) )
2013-11-03 01:02:17 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . LuaConsole . ResumeScripts ( false ) ;
2013-11-03 01:02:17 +00:00
}
2012-01-28 21:43:55 +00:00
2012-03-23 23:03:39 +00:00
2011-02-21 09:48:53 +00:00
StepRunLoop_Core ( ) ;
2011-09-24 16:19:38 +00:00
StepRunLoop_Throttle ( ) ;
2011-06-11 12:54:26 +00:00
2013-11-03 16:07:58 +00:00
if ( GlobalWin . DisplayManager . NeedsToPaint ) { Render ( ) ; }
2012-01-28 21:43:55 +00:00
2011-02-20 08:40:22 +00:00
CheckMessages ( ) ;
2013-11-27 23:35:32 +00:00
if ( _exit )
{
2011-02-20 18:28:01 +00:00
break ;
2013-11-27 23:35:32 +00:00
}
2011-02-20 08:40:22 +00:00
Thread . Sleep ( 0 ) ;
}
2011-07-11 07:35:14 +00:00
Shutdown ( ) ;
}
2013-11-03 02:51:21 +00:00
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose ( bool disposing )
2011-07-11 07:35:14 +00:00
{
2013-11-03 16:07:58 +00:00
if ( GlobalWin . DisplayManager ! = null ) GlobalWin . DisplayManager . Dispose ( ) ;
GlobalWin . DisplayManager = null ;
2013-11-03 02:51:21 +00:00
if ( disposing & & ( components ! = null ) )
2011-07-11 07:35:14 +00:00
{
2013-11-03 02:51:21 +00:00
components . Dispose ( ) ;
2012-02-24 07:48:06 +00:00
}
2013-11-03 02:51:21 +00:00
base . Dispose ( disposing ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-08 15:34:47 +00:00
#endregion `
2013-11-03 02:51:21 +00:00
#region Properties
2011-02-20 08:40:22 +00:00
2013-11-03 02:51:21 +00:00
public string CurrentlyOpenRom ;
public bool PauseAVI = false ;
public bool PressFrameAdvance = false ;
public bool PressRewind = false ;
public bool FastForward = false ;
public bool TurboFastForward = false ;
public bool RestoreReadWriteOnStop = false ;
public bool UpdateFrame = false ;
public bool RewindActive = true ;
public bool EmulatorPaused { get ; private set ; }
2011-02-20 08:40:22 +00:00
2013-11-03 02:51:21 +00:00
#endregion
#region Public Methods
2013-11-27 23:35:32 +00:00
public void FlagNeedsReboot ( )
{
RebootStatusBarIcon . Visible = true ;
GlobalWin . OSD . AddMessage ( "Core reboot needed for this setting" ) ;
}
2013-11-03 02:51:21 +00:00
/// <summary>
/// Controls whether the app generates input events. should be turned off for most modal dialogs
/// </summary>
public bool AllowInput
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
get
2012-09-03 20:17:57 +00:00
{
2013-11-03 02:51:21 +00:00
//the main form gets input
if ( ActiveForm = = this ) return true ;
//modals that need to capture input for binding purposes get input, of course
if ( ActiveForm is HotkeyConfig ) return true ;
if ( ActiveForm is ControllerConfig ) return true ;
if ( ActiveForm is TAStudio ) return true ;
if ( ActiveForm is VirtualPadForm ) return true ;
//if no form is active on this process, then the background input setting applies
if ( ActiveForm = = null & & Global . Config . AcceptBackgroundInput ) return true ;
return false ;
2012-09-03 20:17:57 +00:00
}
2012-09-29 22:37:34 +00:00
}
2011-06-19 20:50:46 +00:00
2013-11-03 02:51:21 +00:00
public void ProcessInput ( )
2012-09-29 22:37:34 +00:00
{
2013-11-03 02:51:21 +00:00
for ( ; ; )
{
//loop through all available events
var ie = Input . Instance . DequeueEvent ( ) ;
if ( ie = = null ) { break ; }
//useful debugging:
//Console.WriteLine(ie);
//TODO - wonder what happens if we pop up something interactive as a response to one of these hotkeys? may need to purge further processing
//look for hotkey bindings for this key
2013-11-03 16:47:21 +00:00
var triggers = Global . ClientControls . SearchBindings ( ie . LogicalButton . ToString ( ) ) ;
2013-11-03 02:51:21 +00:00
if ( triggers . Count = = 0 )
{
//bool sys_hotkey = false;
//maybe it is a system alt-key which hasnt been overridden
if ( ie . EventType = = Input . InputEventType . Press )
{
if ( ie . LogicalButton . Alt & & ie . LogicalButton . Button . Length = = 1 )
{
2013-11-27 23:35:32 +00:00
var c = ie . LogicalButton . Button . ToLower ( ) [ 0 ] ;
2013-11-03 02:51:21 +00:00
if ( c > = 'a' & & c < = 'z' | | c = = ' ' )
{
SendAltKeyChar ( c ) ;
//sys_hotkey = true;
}
}
if ( ie . LogicalButton . Alt & & ie . LogicalButton . Button = = "Space" )
{
SendPlainAltKey ( 32 ) ;
//sys_hotkey = true;
}
}
//ordinarily, an alt release with nothing else would move focus to the menubar. but that is sort of useless, and hard to implement exactly right.
//????????????
//no hotkeys or system keys bound this, so mutate it to an unmodified key and assign it for use as a game controller input
//(we have a rule that says: modified events may be used for game controller inputs but not hotkeys)
//if (!sys_hotkey)
//{
// var mutated_ie = new Input.InputEvent();
// mutated_ie.EventType = ie.EventType;
// mutated_ie.LogicalButton = ie.LogicalButton;
// mutated_ie.LogicalButton.Modifiers = Input.ModifierKey.None;
// Global.ControllerInputCoalescer.Receive(ie);
//}
}
//zero 09-sep-2012 - all input is eligible for controller input. not sure why the above was done.
//maybe because it doesnt make sense to me to bind hotkeys and controller inputs to the same keystrokes
//adelikat 02-dec-2012 - implemented options for how to handle controller vs hotkey conflicts. This is primarily motivated by computer emulation and thus controller being nearly the entire keyboard
bool handled ;
switch ( Global . Config . Input_Hotkey_OverrideOptions )
{
default :
case 0 : //Both allowed
2013-11-03 16:07:58 +00:00
GlobalWin . ControllerInputCoalescer . Receive ( ie ) ;
2013-11-03 02:51:21 +00:00
handled = false ;
if ( ie . EventType = = Input . InputEventType . Press )
{
handled = triggers . Aggregate ( handled , ( current , trigger ) = > current | CheckHotkey ( trigger ) ) ;
}
//hotkeys which arent handled as actions get coalesced as pollable virtual client buttons
if ( ! handled )
{
2013-11-03 16:07:58 +00:00
GlobalWin . HotkeyCoalescer . Receive ( ie ) ;
2013-11-03 02:51:21 +00:00
}
break ;
case 1 : //Input overrides Hokeys
2013-11-03 16:07:58 +00:00
GlobalWin . ControllerInputCoalescer . Receive ( ie ) ;
2013-11-03 02:51:21 +00:00
bool inputisbound = Global . ActiveController . HasBinding ( ie . LogicalButton . ToString ( ) ) ;
if ( ! inputisbound )
{
handled = false ;
if ( ie . EventType = = Input . InputEventType . Press )
{
handled = triggers . Aggregate ( handled , ( current , trigger ) = > current | CheckHotkey ( trigger ) ) ;
}
//hotkeys which arent handled as actions get coalesced as pollable virtual client buttons
if ( ! handled )
{
2013-11-03 16:07:58 +00:00
GlobalWin . HotkeyCoalescer . Receive ( ie ) ;
2013-11-03 02:51:21 +00:00
}
}
break ;
case 2 : //Hotkeys override Input
handled = false ;
if ( ie . EventType = = Input . InputEventType . Press )
{
handled = triggers . Aggregate ( handled , ( current , trigger ) = > current | CheckHotkey ( trigger ) ) ;
}
//hotkeys which arent handled as actions get coalesced as pollable virtual client buttons
if ( ! handled )
{
2013-11-03 16:07:58 +00:00
GlobalWin . HotkeyCoalescer . Receive ( ie ) ;
GlobalWin . ControllerInputCoalescer . Receive ( ie ) ;
2013-11-03 02:51:21 +00:00
}
break ;
}
} //foreach event
// also handle floats
2013-11-03 16:07:58 +00:00
GlobalWin . ControllerInputCoalescer . AcceptNewFloats ( Input . Instance . GetFloats ( ) ) ;
2011-06-11 12:54:26 +00:00
}
2011-05-22 18:38:44 +00:00
2013-11-03 02:51:21 +00:00
public void RebootCore ( )
2011-02-20 08:40:22 +00:00
{
2013-11-03 02:51:21 +00:00
LoadRom ( CurrentlyOpenRom ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-03 02:51:21 +00:00
public void PauseEmulator ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
EmulatorPaused = true ;
SetPauseStatusbarIcon ( ) ;
}
2011-07-13 01:29:13 +00:00
2013-11-03 02:51:21 +00:00
public void UnpauseEmulator ( )
{
EmulatorPaused = false ;
SetPauseStatusbarIcon ( ) ;
2011-06-11 12:54:26 +00:00
}
2011-05-19 18:50:09 +00:00
2013-11-03 02:51:21 +00:00
public void TogglePause ( )
2011-02-20 08:40:22 +00:00
{
2013-11-03 02:51:21 +00:00
EmulatorPaused ^ = true ;
SetPauseStatusbarIcon ( ) ;
}
2011-04-11 01:30:11 +00:00
2013-11-03 02:51:21 +00:00
public string GenerateDefaultCheatFilename ( )
{
2013-12-11 02:05:24 +00:00
PathEntry pathEntry = Global . Config . PathEntries [ Global . Game . System , "Cheats" ] ;
2013-11-03 02:51:21 +00:00
if ( pathEntry = = null )
2013-08-04 16:47:54 +00:00
{
2013-12-11 02:05:24 +00:00
pathEntry = Global . Config . PathEntries [ Global . Game . System , "Base" ] ;
2013-08-04 16:47:54 +00:00
}
2013-12-11 02:05:24 +00:00
string path = PathManager . MakeAbsolutePath ( pathEntry . Path , Global . Game . System ) ;
2011-02-20 08:40:22 +00:00
2013-11-03 02:51:21 +00:00
var f = new FileInfo ( path ) ;
if ( f . Directory ! = null & & f . Directory . Exists = = false )
{
f . Directory . Create ( ) ;
}
2011-07-13 02:11:20 +00:00
2013-11-03 02:51:21 +00:00
return Path . Combine ( path , PathManager . FilesystemSafeName ( Global . Game ) + ".cht" ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-03 02:51:21 +00:00
public void TakeScreenshotToClipboard ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
using ( var img = Global . Config . Screenshot_CaptureOSD ? CaptureOSD ( ) : MakeScreenshotImage ( ) )
{
Clipboard . SetImage ( img ) ;
}
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Screenshot saved to clipboard." ) ;
2011-06-11 12:54:26 +00:00
}
2011-05-13 17:03:05 +00:00
2013-11-03 02:51:21 +00:00
public void TakeScreenshot ( )
2011-02-20 08:40:22 +00:00
{
2013-11-03 02:51:21 +00:00
string path = String . Format ( PathManager . ScreenshotPrefix ( Global . Game ) + ".{0:yyyy-MM-dd HH.mm.ss}.png" , DateTime . Now ) ;
TakeScreenshot ( path ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-03 02:51:21 +00:00
public void TakeScreenshot ( string path )
2011-02-20 08:40:22 +00:00
{
2013-11-03 02:51:21 +00:00
var fi = new FileInfo ( path ) ;
if ( fi . Directory ! = null & & fi . Directory . Exists = = false )
fi . Directory . Create ( ) ;
using ( var img = Global . Config . Screenshot_CaptureOSD ? CaptureOSD ( ) : MakeScreenshotImage ( ) )
2011-02-20 08:40:22 +00:00
{
2013-11-03 02:51:21 +00:00
img . Save ( fi . FullName , ImageFormat . Png ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( fi . Name + " saved." ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-27 23:35:32 +00:00
public void LoadGameGenieEc ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Global . Emulator is NES )
2012-10-06 12:27:56 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < NESGameGenie > ( ) ;
2012-10-06 12:27:56 +00:00
}
2013-11-03 02:51:21 +00:00
else if ( Global . Emulator is LibsnesCore )
2011-06-11 12:54:26 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < SNESGameGenie > ( ) ;
2011-06-11 12:54:26 +00:00
}
2013-11-03 02:51:21 +00:00
else if ( ( Global . Emulator . SystemId = = "GB" ) | | ( Global . Game . System = = "GG" ) )
2013-08-04 16:47:54 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < GBGameGenie > ( ) ;
2013-11-03 02:51:21 +00:00
}
else if ( Global . Emulator is Genesis )
2012-10-28 15:22:15 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < GenGameGenie > ( ) ;
2012-10-28 15:22:15 +00:00
}
}
2013-11-03 02:51:21 +00:00
public void LoadTraceLogger ( )
2013-05-14 03:06:37 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Global . Emulator . CoreComm . CpuTraceAvailable )
2013-05-14 03:06:37 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < TraceLogger > ( ) ;
2013-05-14 03:06:37 +00:00
}
}
2013-11-03 02:51:21 +00:00
public void FrameBufferResized ( )
2013-07-14 01:48:05 +00:00
{
2013-11-03 02:51:21 +00:00
// run this entire thing exactly twice, since the first resize may adjust the menu stacking
for ( int i = 0 ; i < 2 ; i + + )
2013-07-14 01:48:05 +00:00
{
2013-11-03 02:51:21 +00:00
var video = Global . Emulator . VideoProvider ;
int zoom = Global . Config . TargetZoomFactor ;
var area = Screen . FromControl ( this ) . WorkingArea ;
2013-11-27 23:35:32 +00:00
int borderWidth = Size . Width - _renderTarget . Size . Width ;
int borderHeight = Size . Height - _renderTarget . Size . Height ;
2013-11-03 02:51:21 +00:00
// start at target zoom and work way down until we find acceptable zoom
for ( ; zoom > = 1 ; zoom - - )
2013-07-14 01:48:05 +00:00
{
2013-11-03 02:51:21 +00:00
if ( ( ( ( video . BufferWidth * zoom ) + borderWidth ) < area . Width ) & & ( ( ( video . BufferHeight * zoom ) + borderHeight ) < area . Height ) )
break ;
2013-07-14 01:48:05 +00:00
}
2013-11-03 02:51:21 +00:00
// Change size
Size = new Size ( ( video . BufferWidth * zoom ) + borderWidth , ( video . BufferHeight * zoom + borderHeight ) ) ;
PerformLayout ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . RenderPanel . Resized = true ;
2013-11-03 02:51:21 +00:00
// Is window off the screen at this size?
if ( area . Contains ( Bounds ) = = false )
2013-07-24 02:14:25 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Bounds . Right > area . Right ) // Window is off the right edge
Location = new Point ( area . Right - Size . Width , Location . Y ) ;
if ( Bounds . Bottom > area . Bottom ) // Window is off the bottom edge
Location = new Point ( Location . X , area . Bottom - Size . Height ) ;
2013-07-24 02:14:25 +00:00
}
}
2013-07-14 01:48:05 +00:00
}
2013-07-24 02:14:25 +00:00
2013-11-03 02:51:21 +00:00
public void ToggleFullscreen ( )
2013-07-14 01:48:05 +00:00
{
2013-11-27 23:35:32 +00:00
if ( _inFullscreen = = false )
2013-07-14 01:48:05 +00:00
{
2013-11-03 02:51:21 +00:00
_windowed_location = Location ;
FormBorderStyle = FormBorderStyle . None ;
WindowState = FormWindowState . Maximized ;
if ( Global . Config . ShowMenuInFullscreen )
MainMenuStrip . Visible = true ;
else
MainMenuStrip . Visible = false ;
MainStatusBar . Visible = false ;
PerformLayout ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . RenderPanel . Resized = true ;
2013-11-27 23:35:32 +00:00
_inFullscreen = true ;
2013-11-03 02:51:21 +00:00
}
else
{
FormBorderStyle = FormBorderStyle . Sizable ;
WindowState = FormWindowState . Normal ;
MainMenuStrip . Visible = true ;
MainStatusBar . Visible = Global . Config . DisplayStatusBar ;
Location = _windowed_location ;
PerformLayout ( ) ;
FrameBufferResized ( ) ;
2013-11-27 23:35:32 +00:00
_inFullscreen = false ;
2013-07-14 01:48:05 +00:00
}
}
2013-11-03 02:51:21 +00:00
public void LoadTAStudio ( )
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < TAStudio > ( ) ;
2013-11-03 02:51:21 +00:00
}
2013-07-14 01:48:05 +00:00
2013-11-03 02:51:21 +00:00
public void OpenLuaConsole ( )
2011-04-06 05:43:59 +00:00
{
2013-11-03 02:51:21 +00:00
#if WINDOWS
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < LuaConsole > ( ) ;
2013-11-03 02:51:21 +00:00
#else
MessageBox . Show ( "Sorry, Lua is not supported on this platform." , "Lua not supported" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
#endif
}
2013-07-14 01:48:05 +00:00
2013-11-03 02:51:21 +00:00
public void NotifyLogWindowClosing ( )
{
DisplayLogWindowMenuItem . Checked = false ;
LogWindowAsConsoleMenuItem . Enabled = true ;
}
2013-07-14 01:48:05 +00:00
2013-11-27 23:35:32 +00:00
public void SetNesSoundChannels ( )
2013-11-03 02:51:21 +00:00
{
NES nes = Global . Emulator as NES ;
nes . SetSquare1 ( Global . Config . NESSquare1 ) ;
nes . SetSquare2 ( Global . Config . NESSquare2 ) ;
nes . SetTriangle ( Global . Config . NESTriangle ) ;
nes . SetNoise ( Global . Config . NESNoise ) ;
nes . SetDMC ( Global . Config . NESDMC ) ;
2011-06-27 05:31:46 +00:00
}
2013-11-03 02:51:21 +00:00
public void ClickSpeedItem ( int num )
{
if ( ( ModifierKeys & Keys . Control ) ! = 0 ) SetSpeedPercentAlternate ( num ) ;
else SetSpeedPercent ( num ) ;
}
2011-08-08 23:35:13 +00:00
2013-11-03 02:51:21 +00:00
public void FrameSkipMessage ( )
{
2013-11-27 23:35:32 +00:00
GlobalWin . OSD . AddMessage ( "Frameskipping set to " + Global . Config . FrameSkip ) ;
2013-11-03 02:51:21 +00:00
}
2011-07-24 23:14:16 +00:00
2013-11-03 02:51:21 +00:00
public void UpdateCheatStatus ( )
{
if ( Global . CheatList . ActiveCount > 0 )
{
CheatStatusButton . ToolTipText = "Cheats are currently active" ;
CheatStatusButton . Image = Properties . Resources . Freeze ;
CheatStatusButton . Visible = true ;
}
2011-07-24 23:14:16 +00:00
else
2013-11-03 02:51:21 +00:00
{
CheatStatusButton . ToolTipText = String . Empty ;
CheatStatusButton . Image = Properties . Resources . Blank ;
CheatStatusButton . Visible = false ;
}
2011-04-06 05:43:59 +00:00
}
2013-11-03 02:51:21 +00:00
public void SNES_ToggleBG1 ( bool? setto = null )
2011-02-20 08:40:22 +00:00
{
2013-11-27 23:35:32 +00:00
if ( ! ( Global . Emulator is LibsnesCore ) ) return ;
if ( setto . HasValue )
2011-01-20 06:24:31 +00:00
{
2013-11-27 23:35:32 +00:00
Global . Config . SNES_ShowBG1_1 = Global . Config . SNES_ShowBG1_0 = setto . Value ;
}
else
{
Global . Config . SNES_ShowBG1_1 = Global . Config . SNES_ShowBG1_0 ^ = true ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
GlobalWin . OSD . AddMessage ( Global . Config . SNES_ShowBG1_1 ? "BG 1 Layer On" : "BG 1 Layer Off" ) ;
2013-11-03 02:51:21 +00:00
}
2011-03-07 01:07:49 +00:00
2013-11-03 02:51:21 +00:00
public void SNES_ToggleBG2 ( bool? setto = null )
{
2013-11-27 23:35:32 +00:00
if ( ! ( Global . Emulator is LibsnesCore ) ) return ;
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
Global . Config . SNES_ShowBG2_1 = Global . Config . SNES_ShowBG2_0 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
Global . Config . SNES_ShowBG2_1 = Global . Config . SNES_ShowBG2_0 ^ = true ;
}
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
GlobalWin . OSD . AddMessage ( Global . Config . SNES_ShowBG2_1 ? "BG 2 Layer On" : "BG 2 Layer Off" ) ;
2013-11-03 02:51:21 +00:00
}
2011-03-07 02:04:42 +00:00
2013-11-03 02:51:21 +00:00
public void SNES_ToggleBG3 ( bool? setto = null )
{
2013-11-27 23:35:32 +00:00
if ( ! ( Global . Emulator is LibsnesCore ) ) return ;
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
Global . Config . SNES_ShowBG3_1 = Global . Config . SNES_ShowBG3_0 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
Global . Config . SNES_ShowBG3_1 = Global . Config . SNES_ShowBG3_0 ^ = true ;
}
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
GlobalWin . OSD . AddMessage ( Global . Config . SNES_ShowBG3_1 ? "BG 3 Layer On" : "BG 3 Layer Off" ) ;
2013-11-03 02:51:21 +00:00
}
2011-03-07 02:04:42 +00:00
2013-11-03 02:51:21 +00:00
public void SNES_ToggleBG4 ( bool? setto = null )
{
2013-11-27 23:35:32 +00:00
if ( ! ( Global . Emulator is LibsnesCore ) ) return ;
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
Global . Config . SNES_ShowBG4_1 = Global . Config . SNES_ShowBG4_0 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
Global . Config . SNES_ShowBG4_1 = Global . Config . SNES_ShowBG4_0 ^ = true ;
}
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
GlobalWin . OSD . AddMessage ( Global . Config . SNES_ShowBG4_1 ? "BG 4 Layer On" : "BG 4 Layer Off" ) ;
2013-11-03 02:51:21 +00:00
}
2011-03-07 01:07:49 +00:00
2013-11-03 02:51:21 +00:00
public void SNES_ToggleOBJ1 ( bool? setto = null )
{
2013-11-27 23:35:32 +00:00
if ( ! ( Global . Emulator is LibsnesCore ) ) return ;
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
Global . Config . SNES_ShowOBJ1 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
Global . Config . SNES_ShowOBJ1 ^ = true ;
}
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
GlobalWin . OSD . AddMessage ( Global . Config . SNES_ShowOBJ1 ? "OBJ 1 Layer On" : "OBJ 1 Layer Off" ) ;
2013-11-03 02:51:21 +00:00
}
2011-08-09 00:51:46 +00:00
2013-11-03 02:51:21 +00:00
public void SNES_ToggleOBJ2 ( bool? setto = null )
{
2013-11-27 23:35:32 +00:00
if ( ! ( Global . Emulator is LibsnesCore ) ) return ;
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
Global . Config . SNES_ShowOBJ2 = setto . Value ;
}
else
{
Global . Config . SNES_ShowOBJ2 ^ = true ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
GlobalWin . OSD . AddMessage ( Global . Config . SNES_ShowOBJ2 ? "OBJ 2 Layer On" : "OBJ 2 Layer Off" ) ;
2013-11-03 02:51:21 +00:00
}
2013-09-07 01:38:24 +00:00
2013-11-03 02:51:21 +00:00
public void SNES_ToggleOBJ3 ( bool? setto = null )
{
2013-11-27 23:35:32 +00:00
if ( ! ( Global . Emulator is LibsnesCore ) ) return ;
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
Global . Config . SNES_ShowOBJ3 = setto . Value ;
}
else
{
Global . Config . SNES_ShowOBJ3 ^ = true ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
GlobalWin . OSD . AddMessage ( Global . Config . SNES_ShowOBJ3 ? "OBJ 3 Layer On" : "OBJ 3 Layer Off" ) ;
2013-11-03 02:51:21 +00:00
}
2011-08-09 00:51:46 +00:00
2013-11-03 02:51:21 +00:00
public void SNES_ToggleOBJ4 ( bool? setto = null )
{
2013-11-27 23:35:32 +00:00
if ( ! ( Global . Emulator is LibsnesCore ) ) return ;
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
Global . Config . SNES_ShowOBJ4 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
Global . Config . SNES_ShowOBJ4 ^ = true ;
}
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
GlobalWin . OSD . AddMessage ( Global . Config . SNES_ShowOBJ4 ? "OBJ 4 Layer On" : "OBJ 4 Layer Off" ) ;
2013-11-03 02:51:21 +00:00
}
2012-03-03 21:51:20 +00:00
2013-11-03 02:51:21 +00:00
#endregion
2011-08-30 04:02:52 +00:00
2013-11-03 02:51:21 +00:00
#region Private variables
2011-08-30 04:02:52 +00:00
2013-11-27 23:35:32 +00:00
private int _lastWidth = - 1 ;
private int _lastHeight = - 1 ;
private Control _renderTarget ;
private RetainedViewportPanel _retainedPanel ;
private readonly SaveSlotManager _stateSlots = new SaveSlotManager ( ) ;
private readonly Dictionary < string , string > _snesPrepared = new Dictionary < string , string > ( ) ;
2011-08-30 04:02:52 +00:00
2013-11-03 02:51:21 +00:00
//avi/wav state
2013-11-27 23:35:32 +00:00
private IVideoWriter _currAviWriter ;
private ISoundProvider _aviSoundInput ;
private MetaspuSoundProvider _dumpProxy ; //an audio proxy used for dumping
private long _soundRemainder ; //audio timekeeping for video dumping
private int _avwriterResizew ;
private int _avwriterResizeh ;
private EventWaitHandle _mainWait ;
private bool _exit ;
private bool _runloopFrameProgress ;
2013-11-03 02:51:21 +00:00
private DateTime FrameAdvanceTimestamp = DateTime . MinValue ;
2013-11-27 23:35:32 +00:00
private int _runloopFps ;
private int _runloopLastFps ;
private bool _runloopFrameadvance ;
private DateTime _runloopSecond ;
private bool _runloopLastFf ;
2011-08-30 04:02:52 +00:00
2013-11-27 23:35:32 +00:00
private readonly Throttle _throttle ;
private bool _unthrottled ;
2011-09-24 16:09:40 +00:00
2013-11-03 02:51:21 +00:00
//For handling automatic pausing when entering the menu
2013-11-27 23:35:32 +00:00
private bool _wasPaused ;
private bool _didMenuPause ;
2011-09-19 00:39:28 +00:00
2013-11-27 23:35:32 +00:00
private bool _inFullscreen ;
2013-11-03 02:51:21 +00:00
private Point _windowed_location ;
2012-10-05 21:04:46 +00:00
2013-11-27 23:35:32 +00:00
private int _autoDumpLength ;
private readonly bool autoCloseOnDump ;
private int _lastOpenRomFilter ;
2013-04-27 02:02:37 +00:00
2013-11-03 02:51:21 +00:00
// workaround for possible memory leak in SysdrawingRenderPanel
private RetainedViewportPanel captureosd_rvp ;
private SysdrawingRenderPanel captureosd_srp ;
2013-04-27 02:02:37 +00:00
2013-11-03 02:51:21 +00:00
#endregion
2013-04-27 02:02:37 +00:00
2013-11-03 02:51:21 +00:00
#region Private methods
2013-11-27 23:35:32 +00:00
private static void UpdateToolsLoadstate ( )
2013-11-03 02:51:21 +00:00
{
2013-11-03 16:07:58 +00:00
if ( GlobalWin . Tools . Has < SNESGraphicsDebugger > ( ) )
2013-11-03 02:51:21 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . SNESGraphicsDebugger . UpdateToolsLoadstate ( ) ;
2013-11-03 02:51:21 +00:00
}
}
2011-08-09 00:51:46 +00:00
2013-11-03 02:51:21 +00:00
private void UpdateToolsAfter ( bool fromLua = false )
{
2013-11-27 23:35:32 +00:00
GlobalWin . Tools . UpdateToolsAfter ( fromLua ) ;
2013-11-03 02:51:21 +00:00
HandleToggleLight ( ) ;
}
2013-04-24 22:09:11 +00:00
2013-11-27 23:35:32 +00:00
private static void ClearAutohold ( )
2013-11-03 02:51:21 +00:00
{
Global . StickyXORAdapter . ClearStickies ( ) ;
2013-11-03 16:47:21 +00:00
Global . AutofireStickyXORAdapter . ClearStickies ( ) ;
2013-04-24 22:09:11 +00:00
2013-11-03 16:07:58 +00:00
if ( GlobalWin . Tools . Has < VirtualPadForm > ( ) )
2013-11-03 02:51:21 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . VirtualPad . ClearVirtualPadHolds ( ) ;
2013-11-03 02:51:21 +00:00
}
2013-04-24 22:09:11 +00:00
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Autohold keys cleared" ) ;
2013-11-03 02:51:21 +00:00
}
2012-10-21 15:58:24 +00:00
2013-11-03 02:51:21 +00:00
private bool CheckHotkey ( string trigger )
{
//todo - could have these in a table somehow ?
switch ( trigger )
{
default :
2011-08-04 03:20:54 +00:00
return false ;
2013-11-03 02:51:21 +00:00
case "Pause" : TogglePause ( ) ; break ;
case "Toggle Throttle" :
2013-11-27 23:35:32 +00:00
_unthrottled ^ = true ;
GlobalWin . OSD . AddMessage ( "Unthrottled: " + _unthrottled ) ;
2013-11-03 02:51:21 +00:00
break ;
case "Soft Reset" : SoftReset ( ) ; break ;
case "Hard Reset" : HardReset ( ) ; break ;
case "Quick Load" : LoadState ( "QuickSave" + Global . Config . SaveSlot ) ; break ;
case "Quick Save" : SaveState ( "QuickSave" + Global . Config . SaveSlot ) ; break ;
case "Clear Autohold" : ClearAutohold ( ) ; break ;
case "Screenshot" : TakeScreenshot ( ) ; break ;
case "Full Screen" : ToggleFullscreen ( ) ; break ;
2013-11-27 23:35:32 +00:00
case "Open ROM" : OpenRom ( ) ; break ;
case "Close ROM" : CloseRom ( ) ; break ;
2013-11-03 02:51:21 +00:00
case "Display FPS" : ToggleFPS ( ) ; break ;
case "Frame Counter" : ToggleFrameCounter ( ) ; break ;
case "Lag Counter" : ToggleLagCounter ( ) ; break ;
case "Input Display" : ToggleInputDisplay ( ) ; break ;
case "Toggle BG Input" : ToggleBackgroundInput ( ) ; break ;
case "Toggle Menu" : MainMenuStrip . Visible ^ = true ; break ;
case "Volume Up" : VolumeUp ( ) ; break ;
case "Volume Down" : VolumeDown ( ) ; break ;
case "Record A/V" : RecordAVI ( ) ; break ;
case "Stop A/V" : StopAVI ( ) ; break ;
case "Larger Window" : IncreaseWindowSize ( ) ; break ;
case "Smaller Window" : DecreaseWIndowSize ( ) ; break ;
case "Increase Speed" : IncreaseSpeed ( ) ; break ;
case "Decrease Speed" : DecreaseSpeed ( ) ; break ;
case "Reboot Core" :
bool autoSaveState = Global . Config . AutoSavestates ;
Global . Config . AutoSavestates = false ;
LoadRom ( CurrentlyOpenRom ) ;
Global . Config . AutoSavestates = autoSaveState ;
break ;
2012-04-16 08:18:41 +00:00
2013-11-03 02:51:21 +00:00
case "Save State 0" : SaveState ( "QuickSave0" ) ; break ;
case "Save State 1" : SaveState ( "QuickSave1" ) ; break ;
case "Save State 2" : SaveState ( "QuickSave2" ) ; break ;
case "Save State 3" : SaveState ( "QuickSave3" ) ; break ;
case "Save State 4" : SaveState ( "QuickSave4" ) ; break ;
case "Save State 5" : SaveState ( "QuickSave5" ) ; break ;
case "Save State 6" : SaveState ( "QuickSave6" ) ; break ;
case "Save State 7" : SaveState ( "QuickSave7" ) ; break ;
case "Save State 8" : SaveState ( "QuickSave8" ) ; break ;
case "Save State 9" : SaveState ( "QuickSave9" ) ; break ;
case "Load State 0" : LoadState ( "QuickSave0" ) ; break ;
case "Load State 1" : LoadState ( "QuickSave1" ) ; break ;
case "Load State 2" : LoadState ( "QuickSave2" ) ; break ;
case "Load State 3" : LoadState ( "QuickSave3" ) ; break ;
case "Load State 4" : LoadState ( "QuickSave4" ) ; break ;
case "Load State 5" : LoadState ( "QuickSave5" ) ; break ;
case "Load State 6" : LoadState ( "QuickSave6" ) ; break ;
case "Load State 7" : LoadState ( "QuickSave7" ) ; break ;
case "Load State 8" : LoadState ( "QuickSave8" ) ; break ;
case "Load State 9" : LoadState ( "QuickSave9" ) ; break ;
case "Select State 0" : SelectSlot ( 0 ) ; break ;
case "Select State 1" : SelectSlot ( 1 ) ; break ;
case "Select State 2" : SelectSlot ( 2 ) ; break ;
case "Select State 3" : SelectSlot ( 3 ) ; break ;
case "Select State 4" : SelectSlot ( 4 ) ; break ;
case "Select State 5" : SelectSlot ( 5 ) ; break ;
case "Select State 6" : SelectSlot ( 6 ) ; break ;
case "Select State 7" : SelectSlot ( 7 ) ; break ;
case "Select State 8" : SelectSlot ( 8 ) ; break ;
case "Select State 9" : SelectSlot ( 9 ) ; break ;
case "Save Named State" : SaveStateAs ( ) ; break ;
case "Load Named State" : LoadStateAs ( ) ; break ;
case "Previous Slot" : PreviousSlot ( ) ; break ;
case "Next Slot" : NextSlot ( ) ; break ;
2013-11-02 19:28:45 +00:00
2013-11-03 02:51:21 +00:00
case "Toggle read-only" : ToggleReadOnly ( ) ; break ;
case "Play Movie" : LoadPlayMovieDialog ( ) ; break ;
case "Record Movie" : LoadRecordMovieDialog ( ) ; break ;
case "Stop Movie" : StopMovie ( ) ; break ;
case "Play from beginning" : RestartMovie ( ) ; break ;
case "Save Movie" : SaveMovie ( ) ; break ;
case "Toggle MultiTrack" :
if ( Global . MovieSession . Movie . IsActive )
2012-09-01 17:44:55 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Global . Config . VBAStyleMovieLoadState )
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Multi-track can not be used in Full Movie Loadstates mode" ) ;
2013-11-03 02:51:21 +00:00
}
else
{
Global . MovieSession . MultiTrack . IsActive = ! Global . MovieSession . MultiTrack . IsActive ;
if ( Global . MovieSession . MultiTrack . IsActive )
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "MultiTrack Enabled" ) ;
GlobalWin . OSD . MT = "Recording None" ;
2013-11-03 02:51:21 +00:00
}
else
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "MultiTrack Disabled" ) ;
2013-11-03 02:51:21 +00:00
}
Global . MovieSession . MultiTrack . RecordAll = false ;
Global . MovieSession . MultiTrack . CurrentPlayer = 0 ;
}
2012-09-01 17:44:55 +00:00
}
2013-11-03 02:51:21 +00:00
else
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "MultiTrack cannot be enabled while not recording." ) ;
2013-11-03 02:51:21 +00:00
}
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
break ;
case "MT Select All" :
Global . MovieSession . MultiTrack . CurrentPlayer = 0 ;
Global . MovieSession . MultiTrack . RecordAll = true ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . MT = "Recording All" ;
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
break ;
case "MT Select None" :
Global . MovieSession . MultiTrack . CurrentPlayer = 0 ;
Global . MovieSession . MultiTrack . RecordAll = false ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . MT = "Recording None" ;
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
break ;
case "MT Increment Player" :
Global . MovieSession . MultiTrack . CurrentPlayer + + ;
Global . MovieSession . MultiTrack . RecordAll = false ;
if ( Global . MovieSession . MultiTrack . CurrentPlayer > 5 ) //TODO: Replace with console's maximum or current maximum players??!
{
Global . MovieSession . MultiTrack . CurrentPlayer = 1 ;
}
2013-11-27 23:35:32 +00:00
GlobalWin . OSD . MT = "Recording Player " + Global . MovieSession . MultiTrack . CurrentPlayer ;
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
break ;
case "MT Decrement Player" :
Global . MovieSession . MultiTrack . CurrentPlayer - - ;
Global . MovieSession . MultiTrack . RecordAll = false ;
if ( Global . MovieSession . MultiTrack . CurrentPlayer < 1 )
{
Global . MovieSession . MultiTrack . CurrentPlayer = 5 ; //TODO: Replace with console's maximum or current maximum players??!
}
2013-11-27 23:35:32 +00:00
GlobalWin . OSD . MT = "Recording Player " + Global . MovieSession . MultiTrack . CurrentPlayer ;
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
break ;
case "Movie Poke" : ToggleModePokeMode ( ) ; break ;
2013-08-25 04:23:27 +00:00
2013-11-28 20:02:32 +00:00
case "Ram Watch" : GlobalWin . Tools . LoadRamWatch ( true ) ; break ;
2013-11-03 16:07:58 +00:00
case "Ram Search" : GlobalWin . Tools . Load < RamSearch > ( ) ; break ;
case "Hex Editor" : GlobalWin . Tools . Load < HexEditor > ( ) ; break ;
2013-11-03 02:51:21 +00:00
case "Trace Logger" : LoadTraceLogger ( ) ; break ;
case "Lua Console" : OpenLuaConsole ( ) ; break ;
2013-11-03 16:07:58 +00:00
case "Cheats" : GlobalWin . Tools . Load < Cheats > ( ) ; break ;
2013-11-03 02:51:21 +00:00
case "TAStudio" : LoadTAStudio ( ) ; break ;
2013-11-03 16:07:58 +00:00
case "ToolBox" : GlobalWin . Tools . Load < ToolBox > ( ) ; break ;
case "Virtual Pad" : GlobalWin . Tools . Load < VirtualPadForm > ( ) ; break ;
2012-05-28 04:59:22 +00:00
2013-11-03 16:07:58 +00:00
case "Do Search" : GlobalWin . Tools . RamSearch . DoSearch ( ) ; break ;
case "New Search" : GlobalWin . Tools . RamSearch . NewSearch ( ) ; break ;
case "Previous Compare To" : GlobalWin . Tools . RamSearch . NextCompareTo ( reverse : true ) ; break ;
case "Next Compare To" : GlobalWin . Tools . RamSearch . NextCompareTo ( ) ; break ;
case "Previous Operator" : GlobalWin . Tools . RamSearch . NextOperator ( reverse : true ) ; break ;
case "Next Operator" : GlobalWin . Tools . RamSearch . NextOperator ( ) ; break ;
2012-05-28 04:59:22 +00:00
2013-11-03 02:51:21 +00:00
case "Toggle BG 1" : SNES_ToggleBG1 ( ) ; break ;
case "Toggle BG 2" : SNES_ToggleBG2 ( ) ; break ;
case "Toggle BG 3" : SNES_ToggleBG3 ( ) ; break ;
case "Toggle BG 4" : SNES_ToggleBG4 ( ) ; break ;
case "Toggle OBJ 1" : SNES_ToggleOBJ1 ( ) ; break ;
case "Toggle OBJ 2" : SNES_ToggleOBJ2 ( ) ; break ;
case "Toggle OBJ 3" : SNES_ToggleOBJ3 ( ) ; break ;
case "Toggle OBJ 4" : SNES_ToggleOBJ4 ( ) ; break ;
2012-09-15 13:11:29 +00:00
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
2013-11-03 16:07:58 +00:00
case "Y Up Small" : GlobalWin . Tools . VirtualPad . BumpAnalogValue ( null , Global . Config . Analog_SmallChange ) ; break ;
case "Y Up Large" : GlobalWin . Tools . VirtualPad . BumpAnalogValue ( null , Global . Config . Analog_LargeChange ) ; break ;
case "Y Down Small" : GlobalWin . Tools . VirtualPad . BumpAnalogValue ( null , - ( Global . Config . Analog_SmallChange ) ) ; break ;
case "Y Down Large" : GlobalWin . Tools . VirtualPad . BumpAnalogValue ( null , - ( Global . Config . Analog_LargeChange ) ) ; break ;
2011-02-20 08:40:22 +00:00
2013-11-03 16:07:58 +00:00
case "X Up Small" : GlobalWin . Tools . VirtualPad . BumpAnalogValue ( Global . Config . Analog_SmallChange , null ) ; break ;
case "X Up Large" : GlobalWin . Tools . VirtualPad . BumpAnalogValue ( Global . Config . Analog_LargeChange , null ) ; break ;
case "X Down Small" : GlobalWin . Tools . VirtualPad . BumpAnalogValue ( - ( Global . Config . Analog_SmallChange ) , null ) ; break ;
case "X Down Large" : GlobalWin . Tools . VirtualPad . BumpAnalogValue ( - ( Global . Config . Analog_LargeChange ) , null ) ; break ;
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
}
2013-11-03 02:51:21 +00:00
return true ;
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
}
2011-07-10 15:36:41 +00:00
private void UpdateDumpIcon ( )
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . Blank ;
DumpStatusButton . ToolTipText = "" ;
2011-07-10 21:00:28 +00:00
2013-10-20 18:02:43 +00:00
if ( Global . Emulator = = null ) return ;
2011-07-22 01:34:21 +00:00
if ( Global . Game = = null ) return ;
2011-07-10 21:00:28 +00:00
2011-08-04 03:20:54 +00:00
var status = Global . Game . Status ;
2013-04-16 00:19:31 +00:00
string annotation ;
2011-07-10 21:00:28 +00:00
if ( status = = RomStatus . BadDump )
2011-07-10 15:36:41 +00:00
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . ExclamationRed ;
2011-07-10 21:00:28 +00:00
annotation = "Warning: Bad ROM Dump" ;
}
else if ( status = = RomStatus . Overdump )
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . ExclamationRed ;
2011-07-10 21:00:28 +00:00
annotation = "Warning: Overdump" ;
}
else if ( status = = RomStatus . NotInDatabase )
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . RetroQuestion ;
2011-07-10 21:00:28 +00:00
annotation = "Warning: Unknown ROM" ;
}
else if ( status = = RomStatus . TranslatedRom )
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . Translation ;
2011-07-10 21:00:28 +00:00
annotation = "Translated ROM" ;
}
else if ( status = = RomStatus . Homebrew )
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . HomeBrew ;
2011-07-10 21:00:28 +00:00
annotation = "Homebrew ROM" ;
}
else if ( Global . Game . Status = = RomStatus . Hack )
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . Hack ;
2011-07-10 21:00:28 +00:00
annotation = "Hacked ROM" ;
2011-07-10 15:36:41 +00:00
}
2012-04-16 08:18:41 +00:00
else if ( Global . Game . Status = = RomStatus . Unknown )
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . Hack ;
2012-04-16 08:18:41 +00:00
annotation = "Warning: ROM of Unknown Character" ;
}
2011-07-10 15:36:41 +00:00
else
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . GreenCheck ;
2011-07-10 21:00:28 +00:00
annotation = "Verified good dump" ;
2011-07-10 15:36:41 +00:00
}
2013-10-20 18:02:43 +00:00
if ( ! string . IsNullOrEmpty ( Global . Emulator . CoreComm . RomStatusAnnotation ) )
annotation = Global . Emulator . CoreComm . RomStatusAnnotation ;
2011-07-10 21:00:28 +00:00
2013-10-27 15:53:37 +00:00
DumpStatusButton . ToolTipText = annotation ;
2011-07-10 15:36:41 +00:00
}
2013-11-27 23:35:32 +00:00
private static void LoadSaveRam ( )
2011-02-20 08:40:22 +00:00
{
2013-11-03 02:51:21 +00:00
try //zero says: this is sort of sketchy... but this is no time for rearchitecting
2011-08-09 00:51:46 +00:00
{
2012-11-24 02:25:47 +00:00
byte [ ] sram ;
// GBA core might not know how big the saveram ought to be, so just send it the whole file
2013-10-20 18:02:43 +00:00
if ( Global . Emulator is GBA )
2012-11-24 02:25:47 +00:00
{
sram = File . ReadAllBytes ( PathManager . SaveRamPath ( Global . Game ) ) ;
}
2012-09-10 23:40:53 +00:00
else
2012-11-24 02:25:47 +00:00
{
2013-10-20 18:02:43 +00:00
sram = new byte [ Global . Emulator . ReadSaveRam ( ) . Length ] ;
2012-11-24 02:25:47 +00:00
using ( var reader = new BinaryReader ( new FileStream ( PathManager . SaveRamPath ( Global . Game ) , FileMode . Open , FileAccess . Read ) ) )
2013-09-07 01:38:24 +00:00
reader . Read ( sram , 0 , sram . Length ) ;
2012-11-24 02:25:47 +00:00
}
2013-10-20 18:02:43 +00:00
Global . Emulator . StoreSaveRam ( sram ) ;
2011-08-09 00:51:46 +00:00
}
2012-10-27 13:57:26 +00:00
catch ( IOException ) { }
2011-02-20 08:40:22 +00:00
}
2011-08-09 00:51:46 +00:00
private static void SaveRam ( )
{
2013-11-27 23:35:32 +00:00
var path = PathManager . SaveRamPath ( Global . Game ) ;
2011-08-09 00:51:46 +00:00
var f = new FileInfo ( path ) ;
2013-04-16 00:19:31 +00:00
if ( f . Directory ! = null & & f . Directory . Exists = = false )
2013-11-27 23:35:32 +00:00
{
2011-08-09 00:51:46 +00:00
f . Directory . Create ( ) ;
2013-11-27 23:35:32 +00:00
}
2011-08-04 03:20:54 +00:00
2012-09-29 15:32:44 +00:00
//Make backup first
2013-04-16 00:19:31 +00:00
if ( Global . Config . BackupSaveram & & f . Exists )
2012-09-29 15:32:44 +00:00
{
2013-11-27 23:35:32 +00:00
var backup = path + ".bak" ;
2012-09-29 15:32:44 +00:00
var backupFile = new FileInfo ( backup ) ;
2013-04-16 00:19:31 +00:00
if ( backupFile . Exists )
2013-11-27 23:35:32 +00:00
{
2012-09-29 15:32:44 +00:00
backupFile . Delete ( ) ;
2013-11-27 23:35:32 +00:00
}
2012-09-29 15:32:44 +00:00
f . CopyTo ( backup ) ;
}
2011-08-09 00:51:46 +00:00
var writer = new BinaryWriter ( new FileStream ( path , FileMode . Create , FileAccess . Write ) ) ;
2012-09-14 22:28:38 +00:00
2013-10-20 18:02:43 +00:00
var saveram = Global . Emulator . ReadSaveRam ( ) ;
2012-09-14 22:28:38 +00:00
// this assumes that the default state of the core's sram is 0-filled, so don't do
// int len = Util.SaveRamBytesUsed(saveram);
int len = saveram . Length ;
writer . Write ( saveram , 0 , len ) ;
2011-08-09 00:51:46 +00:00
writer . Close ( ) ;
}
2011-08-04 03:20:54 +00:00
2013-11-03 02:51:21 +00:00
private void SelectSlot ( int num )
2011-07-09 22:09:39 +00:00
{
2011-09-17 00:04:50 +00:00
Global . Config . SaveSlot = num ;
2011-07-09 22:09:39 +00:00
SaveSlotSelectedMessage ( ) ;
2011-08-09 00:51:46 +00:00
UpdateStatusSlots ( ) ;
2011-07-09 22:09:39 +00:00
}
2013-11-03 02:51:21 +00:00
private void RewireSound ( )
2011-07-24 23:14:16 +00:00
{
2013-11-27 23:35:32 +00:00
if ( _dumpProxy ! = null )
2011-07-24 23:14:16 +00:00
{
2013-11-03 02:51:21 +00:00
// we're video dumping, so async mode only and use the DumpProxy.
// note that the avi dumper has already rewired the emulator itself in this case.
2013-11-27 23:35:32 +00:00
GlobalWin . Sound . SetAsyncInputPin ( _dumpProxy ) ;
2013-11-03 02:51:21 +00:00
}
else if ( Global . Config . SoundThrottle )
{
// for sound throttle, use sync mode
Global . Emulator . EndAsyncSound ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . Sound . SetSyncInputPin ( Global . Emulator . SyncSoundProvider ) ;
2013-11-03 02:51:21 +00:00
}
else
{
// for vsync\clock throttle modes, use async
if ( ! Global . Emulator . StartAsyncSound ( ) )
{
// if the core doesn't support async mode, use a standard vecna wrapper
2013-11-14 19:33:13 +00:00
GlobalWin . Sound . SetAsyncInputPin ( new MetaspuAsync ( Global . Emulator . SyncSoundProvider , ESynchMethod . ESynchMethod_V ) ) ;
2013-11-03 02:51:21 +00:00
}
else
{
2013-11-03 16:07:58 +00:00
GlobalWin . Sound . SetAsyncInputPin ( Global . Emulator . SoundProvider ) ;
2013-11-03 02:51:21 +00:00
}
2011-07-24 23:14:16 +00:00
}
}
2013-11-27 23:35:32 +00:00
private static Controller BindToDefinition ( ControllerDefinition def , IDictionary < string , Dictionary < string , string > > allbinds , IDictionary < string , Dictionary < string , Config . AnalogBind > > analogbinds )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
var ret = new Controller ( def ) ;
Dictionary < string , string > binds ;
if ( allbinds . TryGetValue ( def . Name , out binds ) )
2011-06-11 12:54:26 +00:00
{
2013-11-27 23:35:32 +00:00
foreach ( var cbutton in def . BoolButtons )
2011-07-10 02:14:58 +00:00
{
2013-11-03 02:51:21 +00:00
string bind ;
if ( binds . TryGetValue ( cbutton , out bind ) )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
ret . BindMulti ( cbutton , bind ) ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
}
}
Dictionary < string , Config . AnalogBind > abinds ;
if ( analogbinds . TryGetValue ( def . Name , out abinds ) )
{
2013-11-27 23:35:32 +00:00
foreach ( var cbutton in def . FloatControls )
2013-11-03 02:51:21 +00:00
{
Config . AnalogBind bind ;
if ( abinds . TryGetValue ( cbutton , out bind ) )
2011-07-10 19:50:59 +00:00
{
2013-11-03 02:51:21 +00:00
ret . BindFloat ( cbutton , bind ) ;
}
2011-07-10 02:14:58 +00:00
}
2013-11-03 02:51:21 +00:00
}
return ret ;
}
2011-07-10 07:39:40 +00:00
2013-11-27 23:35:32 +00:00
private static AutofireController BindToDefinitionAF ( ControllerDefinition def , IDictionary < string , Dictionary < string , string > > allbinds )
2013-11-03 02:51:21 +00:00
{
var ret = new AutofireController ( def ) ;
Dictionary < string , string > binds ;
if ( allbinds . TryGetValue ( def . Name , out binds ) )
{
2013-11-27 23:35:32 +00:00
foreach ( var cbutton in def . BoolButtons )
2011-07-09 22:09:39 +00:00
{
2013-11-03 02:51:21 +00:00
string bind ;
if ( binds . TryGetValue ( cbutton , out bind ) )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
ret . BindMulti ( cbutton , bind ) ;
2013-11-27 23:35:32 +00:00
}
2011-07-10 07:39:40 +00:00
}
2013-11-03 02:51:21 +00:00
}
return ret ;
}
2011-08-09 00:51:46 +00:00
2013-11-13 23:36:21 +00:00
private void SaturnSetPrefs ( Yabause e = null )
2013-11-03 02:51:21 +00:00
{
if ( e = = null )
2013-11-13 23:36:21 +00:00
e = Global . Emulator as Yabause ;
2013-07-18 16:18:17 +00:00
2013-11-03 02:51:21 +00:00
if ( Global . Config . SaturnUseGL ! = e . GLMode )
{
// theoretically possible; not coded. meh.
FlagNeedsReboot ( ) ;
return ;
}
if ( e . GLMode & & Global . Config . SaturnUseGL )
{
if ( Global . Config . SaturnDispFree )
e . SetGLRes ( 0 , Global . Config . SaturnGLW , Global . Config . SaturnGLH ) ;
else
e . SetGLRes ( Global . Config . SaturnDispFactor , 0 , 0 ) ;
}
2011-07-10 07:39:40 +00:00
}
2013-11-03 02:51:21 +00:00
private void HandlePlatformMenus ( )
2012-09-15 13:11:29 +00:00
{
2013-11-27 23:35:32 +00:00
var system = String . Empty ;
2013-11-02 21:31:04 +00:00
2013-11-03 02:51:21 +00:00
if ( Global . Game ! = null )
2013-11-02 21:31:04 +00:00
{
2013-11-03 02:51:21 +00:00
system = Global . Game . System ;
2013-11-02 21:31:04 +00:00
}
2013-11-03 02:51:21 +00:00
TI83SubMenu . Visible = false ;
NESSubMenu . Visible = false ;
PCESubMenu . Visible = false ;
SMSSubMenu . Visible = false ;
GBSubMenu . Visible = false ;
GBASubMenu . Visible = false ;
AtariSubMenu . Visible = false ;
SNESSubMenu . Visible = false ;
ColecoSubMenu . Visible = false ;
N64SubMenu . Visible = false ;
SaturnSubMenu . Visible = false ;
2012-09-15 13:11:29 +00:00
2013-11-03 02:51:21 +00:00
switch ( system )
2011-07-10 07:39:40 +00:00
{
2013-08-04 18:15:11 +00:00
default :
2013-11-03 02:51:21 +00:00
case "GEN" :
2011-07-10 07:39:40 +00:00
break ;
2013-11-03 02:51:21 +00:00
case "NULL" :
N64SubMenu . Visible = true ;
2011-07-10 07:39:40 +00:00
break ;
2013-11-03 02:51:21 +00:00
case "TI83" :
TI83SubMenu . Visible = true ;
2011-07-10 07:39:40 +00:00
break ;
2013-11-03 02:51:21 +00:00
case "NES" :
NESSubMenu . Visible = true ;
2013-11-27 23:35:32 +00:00
NesSpecialMenuControls ( ) ;
2011-07-10 07:39:40 +00:00
break ;
2013-11-03 02:51:21 +00:00
case "PCE" :
case "PCECD" :
case "SGX" :
PCESubMenu . Visible = true ;
2013-08-04 16:47:54 +00:00
break ;
2013-11-03 02:51:21 +00:00
case "SMS" :
SMSSubMenu . Text = "SMS" ;
SMSSubMenu . Visible = true ;
break ;
case "SG" :
SMSSubMenu . Text = "SG" ;
SMSSubMenu . Visible = true ;
break ;
case "GG" :
SMSSubMenu . Text = "GG" ;
SMSSubMenu . Visible = true ;
break ;
case "GB" :
case "GBC" :
GBSubMenu . Visible = true ;
break ;
case "GBA" :
GBASubMenu . Visible = true ;
break ;
case "A26" :
AtariSubMenu . Visible = true ;
break ;
case "SNES" :
case "SGB" :
if ( ( Global . Emulator as LibsnesCore ) . IsSGB )
SNESSubMenu . Text = "&SGB" ;
else
SNESSubMenu . Text = "&SNES" ;
SNESSubMenu . Visible = true ;
2013-08-04 16:47:54 +00:00
break ;
2013-11-03 02:51:21 +00:00
case "Coleco" :
ColecoSubMenu . Visible = true ;
2013-08-04 16:47:54 +00:00
break ;
2013-11-03 02:51:21 +00:00
case "N64" :
N64SubMenu . Visible = true ;
2013-08-04 16:47:54 +00:00
break ;
2013-11-03 02:51:21 +00:00
case "SAT" :
SaturnSubMenu . Visible = true ;
2013-03-09 23:11:00 +00:00
break ;
2013-11-03 02:51:21 +00:00
}
}
2013-10-09 20:43:13 +00:00
2013-11-27 23:35:32 +00:00
private static string DisplayNameForSystem ( string system )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
var str = String . Empty ;
2013-11-03 02:51:21 +00:00
switch ( system )
{
case "INTV" : str = "Intellivision" ; break ;
case "SG" : str = "SG-1000" ; break ;
case "SMS" : str = "Sega Master System" ; break ;
case "GG" : str = "Game Gear" ; break ;
case "PCECD" : str = "TurboGrafx-16 (CD)" ; break ;
case "PCE" : str = "TurboGrafx-16" ; break ;
case "SGX" : str = "SuperGrafx" ; break ;
case "GEN" : str = "Genesis" ; break ;
case "TI83" : str = "TI-83" ; break ;
case "NES" : str = "NES" ; break ;
case "SNES" : str = "SNES" ; break ;
case "GB" : str = "Game Boy" ; break ;
case "GBC" : str = "Game Boy Color" ; break ;
case "A26" : str = "Atari 2600" ; break ;
case "A78" : str = "Atari 7800" ; break ;
case "C64" : str = "Commodore 64" ; break ;
case "Coleco" : str = "ColecoVision" ; break ;
case "GBA" : str = "Game Boy Advance" ; break ;
case "N64" : str = "Nintendo 64" ; break ;
case "SAT" : str = "Saturn" ; break ;
case "DGB" : str = "Game Boy Link" ; break ;
}
2013-08-04 16:47:54 +00:00
2013-11-27 23:35:32 +00:00
if ( VersionInfo . INTERIM )
{
str + = " (interim)" ;
}
2013-11-03 02:51:21 +00:00
return str ;
}
2013-08-04 18:36:33 +00:00
2013-11-27 23:35:32 +00:00
private static void InitControls ( )
2013-11-03 02:51:21 +00:00
{
var controls = new Controller (
new ControllerDefinition
{
Name = "Emulator Frontend Controls" ,
BoolButtons = Global . Config . HotkeyBindings . Select ( x = > x . DisplayName ) . ToList ( )
} ) ;
2013-08-04 20:32:50 +00:00
2013-11-03 02:51:21 +00:00
foreach ( var b in Global . Config . HotkeyBindings )
{
controls . BindMulti ( b . DisplayName , b . Bindings ) ;
2013-08-04 16:47:54 +00:00
}
2011-07-10 07:39:40 +00:00
2013-11-03 16:47:21 +00:00
Global . ClientControls = controls ;
2013-11-03 02:51:21 +00:00
Global . NullControls = new Controller ( NullEmulator . NullController ) ;
Global . AutofireNullControls = new AutofireController ( NullEmulator . NullController ) ;
2011-06-11 12:54:26 +00:00
}
2013-11-27 23:35:32 +00:00
private static bool IsValidMovieExtension ( string ext )
2011-02-21 09:48:53 +00:00
{
2013-11-03 02:51:21 +00:00
if ( ext . ToUpper ( ) = = "." + Global . Config . MovieExtension )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
return true ;
2013-11-27 23:35:32 +00:00
}
else if ( ext . ToUpper ( ) = = ".TAS" | | ext . ToUpper ( ) = = ".BKM" )
{
2013-11-03 02:51:21 +00:00
return true ;
2013-11-27 23:35:32 +00:00
}
2011-02-21 09:48:53 +00:00
2013-11-03 02:51:21 +00:00
return false ;
2011-02-21 09:48:53 +00:00
}
2011-02-20 08:40:22 +00:00
2013-11-03 02:51:21 +00:00
private void LoadMoviesFromRecent ( string path )
2011-02-20 08:40:22 +00:00
{
2013-11-27 23:35:32 +00:00
var movie = new Movie ( path ) ;
2011-02-20 08:40:22 +00:00
2013-11-10 02:55:11 +00:00
if ( ! movie . Loaded )
2012-03-16 15:27:45 +00:00
{
2013-11-03 02:51:21 +00:00
ToolHelpers . HandleLoadError ( Global . Config . RecentMovies , path ) ;
2012-03-16 15:27:45 +00:00
}
2013-11-03 02:51:21 +00:00
else
2011-02-20 08:40:22 +00:00
{
2013-12-03 18:08:45 +00:00
Global . MovieSession . ReadOnly = true ;
2013-11-10 02:55:11 +00:00
StartNewMovie ( movie , false ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-03 02:51:21 +00:00
}
private void LoadRomFromRecent ( string rom )
{
if ( ! LoadRom ( rom ) )
2011-02-20 08:40:22 +00:00
{
2013-11-03 02:51:21 +00:00
ToolHelpers . HandleLoadError ( Global . Config . RecentRoms , rom ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-03 02:51:21 +00:00
}
2012-03-16 15:27:45 +00:00
2013-11-03 02:51:21 +00:00
private void SetPauseStatusbarIcon ( )
{
if ( EmulatorPaused )
2012-03-16 15:27:45 +00:00
{
2013-11-03 02:51:21 +00:00
PauseStatusButton . Image = Properties . Resources . Pause ;
PauseStatusButton . Visible = true ;
PauseStatusButton . ToolTipText = "Emulator Paused" ;
}
else
{
PauseStatusButton . Image = Properties . Resources . Blank ;
PauseStatusButton . Visible = false ;
PauseStatusButton . ToolTipText = String . Empty ;
2012-03-16 15:27:45 +00:00
}
2013-11-03 02:51:21 +00:00
}
2011-02-20 08:40:22 +00:00
2013-11-03 02:51:21 +00:00
private void Cheats_Restart ( )
{
2013-11-05 15:36:18 +00:00
if ( ! GlobalWin . Tools . Has < Cheats > ( ) )
2012-06-01 05:49:26 +00:00
{
2013-11-03 02:51:21 +00:00
Global . CheatList . NewList ( GenerateDefaultCheatFilename ( ) ) ;
2012-06-01 05:49:26 +00:00
}
2013-11-05 15:36:18 +00:00
//If Cheat tool is loaded, restarting will restart the list too anyway
2013-11-03 02:51:21 +00:00
}
2011-02-20 08:40:22 +00:00
2013-11-03 02:51:21 +00:00
//contains a mapping: profilename->exepath ; or null if the exe wasnt available
private string SNES_Prepare ( string profile )
{
SNES_Check ( profile ) ;
2013-11-27 23:35:32 +00:00
if ( _snesPrepared [ profile ] = = null )
2011-02-20 08:40:22 +00:00
{
2013-11-03 02:51:21 +00:00
throw new InvalidOperationException ( "Couldn't locate the executable for SNES emulation for profile: " + profile + ". Please make sure you're using a fresh dearchive of a BizHawk distribution." ) ;
}
2013-11-27 23:35:32 +00:00
return _snesPrepared [ profile ] ;
2013-11-03 02:51:21 +00:00
}
2012-10-11 22:37:44 +00:00
2013-11-03 02:51:21 +00:00
private void SNES_Check ( string profile )
{
2013-11-27 23:35:32 +00:00
if ( _snesPrepared . ContainsKey ( profile ) ) return ;
2012-10-11 22:37:44 +00:00
2013-11-03 02:51:21 +00:00
const string bits = "32" ;
2012-11-18 15:25:55 +00:00
2013-11-03 02:51:21 +00:00
//disabled til it works
//if (Win32.Is64BitOperatingSystem)
// bits = "64";
2011-06-11 12:54:26 +00:00
2013-11-27 23:35:32 +00:00
var exename = "libsneshawk-" + bits + "-" + profile . ToLower ( ) + ".exe" ;
var thisDir = PathManager . GetExeDirectoryAbsolute ( ) ;
var exePath = Path . Combine ( thisDir , exename ) ;
2011-06-10 07:12:57 +00:00
2013-11-03 02:51:21 +00:00
if ( ! File . Exists ( exePath ) )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
exePath = Path . Combine ( Path . Combine ( thisDir , "dll" ) , exename ) ;
2013-11-27 23:35:32 +00:00
}
2011-03-16 06:30:25 +00:00
2013-11-03 02:51:21 +00:00
if ( ! File . Exists ( exePath ) )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
exePath = null ;
2013-11-27 23:35:32 +00:00
}
2012-06-03 01:18:13 +00:00
2013-11-27 23:35:32 +00:00
_snesPrepared [ profile ] = exePath ;
2013-11-03 02:51:21 +00:00
}
2011-06-11 12:54:26 +00:00
2013-11-03 02:51:21 +00:00
private void SyncPresentationMode ( )
{
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . Suspend ( ) ;
2011-06-27 05:31:46 +00:00
2013-11-03 02:51:21 +00:00
#if WINDOWS
2013-11-03 16:07:58 +00:00
bool gdi = Global . Config . DisplayGDI | | GlobalWin . Direct3D = = null ;
2013-11-03 02:51:21 +00:00
#endif
2013-11-27 23:35:32 +00:00
if ( _renderTarget ! = null )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
_renderTarget . Dispose ( ) ;
Controls . Remove ( _renderTarget ) ;
2013-11-03 02:51:21 +00:00
}
2011-07-11 07:35:14 +00:00
2013-11-27 23:35:32 +00:00
if ( _retainedPanel ! = null ) _retainedPanel . Dispose ( ) ;
2013-11-03 16:07:58 +00:00
if ( GlobalWin . RenderPanel ! = null ) GlobalWin . RenderPanel . Dispose ( ) ;
2013-09-07 01:38:24 +00:00
2013-11-03 02:51:21 +00:00
#if WINDOWS
if ( gdi )
#endif
2013-11-27 23:35:32 +00:00
_renderTarget = _retainedPanel = new RetainedViewportPanel ( ) ;
2013-11-03 02:51:21 +00:00
#if WINDOWS
2013-11-27 23:35:32 +00:00
else _renderTarget = new ViewportPanel ( ) ;
2013-11-03 02:51:21 +00:00
#endif
2013-11-27 23:35:32 +00:00
Controls . Add ( _renderTarget ) ;
Controls . SetChildIndex ( _renderTarget , 0 ) ;
2011-08-29 03:28:34 +00:00
2013-11-27 23:35:32 +00:00
_renderTarget . Dock = DockStyle . Fill ;
_renderTarget . BackColor = Color . Black ;
2012-05-28 01:29:43 +00:00
2013-11-03 02:51:21 +00:00
#if WINDOWS
if ( gdi )
2012-05-28 01:29:43 +00:00
{
2013-11-03 02:51:21 +00:00
#endif
2013-11-27 23:35:32 +00:00
GlobalWin . RenderPanel = new SysdrawingRenderPanel ( _retainedPanel ) ;
_retainedPanel . ActivateThreaded ( ) ;
2013-11-03 02:51:21 +00:00
#if WINDOWS
2012-05-28 01:29:43 +00:00
}
2013-11-03 02:51:21 +00:00
else
2012-06-01 05:49:26 +00:00
{
2013-11-03 02:51:21 +00:00
try
2012-08-02 21:30:30 +00:00
{
2013-11-27 23:35:32 +00:00
var d3dPanel = new Direct3DRenderPanel ( GlobalWin . Direct3D , _renderTarget ) ;
2013-11-03 02:51:21 +00:00
d3dPanel . CreateDevice ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . RenderPanel = d3dPanel ;
2013-11-03 02:51:21 +00:00
}
catch
{
Program . DisplayDirect3DError ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . Direct3D . Dispose ( ) ;
GlobalWin . Direct3D = null ;
2013-11-03 02:51:21 +00:00
SyncPresentationMode ( ) ;
2012-08-02 21:30:30 +00:00
}
2012-06-01 05:49:26 +00:00
}
2013-11-03 02:51:21 +00:00
#endif
2012-05-28 01:29:43 +00:00
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . Resume ( ) ;
2013-11-03 02:51:21 +00:00
}
private void SyncThrottle ( )
{
2013-11-03 16:47:21 +00:00
bool fastforward = Global . ClientControls [ "Fast Forward" ] | | FastForward ;
bool superfastforward = Global . ClientControls [ "Turbo" ] ;
2013-11-27 23:35:32 +00:00
Global . ForceNoThrottle = _unthrottled | | fastforward ;
2013-11-03 02:51:21 +00:00
// realtime throttle is never going to be so exact that using a double here is wrong
2013-11-27 23:35:32 +00:00
_throttle . SetCoreFps ( Global . Emulator . CoreComm . VsyncRate ) ;
2013-11-03 02:51:21 +00:00
2013-11-27 23:35:32 +00:00
_throttle . signal_paused = EmulatorPaused | | Global . Emulator is NullEmulator ;
_throttle . signal_unthrottle = _unthrottled | | superfastforward ;
2013-11-03 02:51:21 +00:00
if ( fastforward )
2012-05-28 01:29:43 +00:00
{
2013-11-27 23:35:32 +00:00
_throttle . SetSpeedPercent ( Global . Config . SpeedPercentAlternate ) ;
2012-05-28 01:29:43 +00:00
}
else
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
_throttle . SetSpeedPercent ( Global . Config . SpeedPercent ) ;
2013-11-03 02:51:21 +00:00
}
2011-02-20 08:40:22 +00:00
}
2013-11-03 02:51:21 +00:00
private void SetSpeedPercentAlternate ( int value )
2011-07-09 00:26:23 +00:00
{
2013-11-03 02:51:21 +00:00
Global . Config . SpeedPercentAlternate = value ;
SyncThrottle ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Alternate Speed: " + value + "%" ) ;
2012-09-22 05:03:52 +00:00
}
2013-11-03 02:51:21 +00:00
private void SetSpeedPercent ( int value )
2012-09-22 05:03:52 +00:00
{
2013-11-03 02:51:21 +00:00
Global . Config . SpeedPercent = value ;
SyncThrottle ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Speed: " + value + "%" ) ;
2011-07-09 00:26:23 +00:00
}
2013-11-03 02:51:21 +00:00
private void Shutdown ( )
2012-05-28 01:29:43 +00:00
{
2013-11-27 23:35:32 +00:00
if ( _currAviWriter ! = null )
2013-09-07 01:38:24 +00:00
{
2013-11-27 23:35:32 +00:00
_currAviWriter . CloseFile ( ) ;
_currAviWriter = null ;
2013-09-07 01:38:24 +00:00
}
2013-11-03 02:51:21 +00:00
}
2012-10-13 12:44:52 +00:00
2013-11-27 23:35:32 +00:00
private static void CheckMessages ( )
2013-11-03 02:51:21 +00:00
{
Application . DoEvents ( ) ;
if ( ActiveForm ! = null )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
ScreenSaver . ResetTimerPeriodically ( ) ;
2013-11-27 23:35:32 +00:00
}
2012-05-28 01:29:43 +00:00
}
2012-05-28 00:44:27 +00:00
2013-11-27 23:35:32 +00:00
private static unsafe Image MakeScreenshotImage ( )
2011-06-11 12:54:26 +00:00
{
2013-10-20 18:02:43 +00:00
var video = Global . Emulator . VideoProvider ;
2011-06-11 12:54:26 +00:00
var image = new Bitmap ( video . BufferWidth , video . BufferHeight , PixelFormat . Format32bppArgb ) ;
2011-02-20 08:40:22 +00:00
2012-03-04 01:30:30 +00:00
//TODO - replace with BitmapBuffer
2011-06-11 12:54:26 +00:00
var framebuf = video . GetVideoBuffer ( ) ;
2012-03-30 12:26:36 +00:00
var bmpdata = image . LockBits ( new Rectangle ( 0 , 0 , image . Width , image . Height ) , ImageLockMode . WriteOnly , PixelFormat . Format32bppArgb ) ;
2012-03-04 01:30:30 +00:00
int * ptr = ( int * ) bmpdata . Scan0 . ToPointer ( ) ;
2012-03-30 12:26:36 +00:00
int stride = bmpdata . Stride / 4 ;
2011-06-11 12:54:26 +00:00
for ( int y = 0 ; y < video . BufferHeight ; y + + )
for ( int x = 0 ; x < video . BufferWidth ; x + + )
2011-07-10 01:55:37 +00:00
{
int col = framebuf [ ( y * video . BufferWidth ) + x ] ;
2013-10-20 18:02:43 +00:00
if ( Global . Emulator is TI83 )
2011-07-10 01:55:37 +00:00
{
if ( col = = 0 )
col = Color . Black . ToArgb ( ) ;
else
col = Color . White . ToArgb ( ) ;
}
2013-08-23 17:49:15 +00:00
// make opaque
2013-08-23 17:54:33 +00:00
col | = unchecked ( ( int ) 0xff000000 ) ;
2013-08-23 17:49:15 +00:00
2012-03-04 01:30:30 +00:00
ptr [ y * stride + x ] = col ;
2011-07-10 01:55:37 +00:00
}
2013-11-03 02:51:21 +00:00
image . UnlockBits ( bmpdata ) ;
return image ;
2011-06-11 12:54:26 +00:00
}
2011-05-22 19:52:49 +00:00
2013-11-03 02:51:21 +00:00
private void SaveStateAs ( )
2011-05-16 15:38:48 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Global . Emulator is NullEmulator )
2013-08-04 16:47:54 +00:00
{
return ;
}
2013-11-03 02:51:21 +00:00
var sfd = new SaveFileDialog ( ) ;
2013-11-27 23:35:32 +00:00
var path = PathManager . GetSaveStatePath ( Global . Game ) ;
2013-11-03 02:51:21 +00:00
sfd . InitialDirectory = path ;
sfd . FileName = PathManager . SaveStatePrefix ( Global . Game ) + "." + "QuickSave0.State" ;
var file = new FileInfo ( path ) ;
if ( file . Directory ! = null & & file . Directory . Exists = = false )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
file . Directory . Create ( ) ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
2013-11-28 22:39:00 +00:00
var result = sfd . ShowHawkDialog ( ) ;
2013-11-27 23:35:32 +00:00
if ( result = = DialogResult . OK )
{
SaveStateFile ( sfd . FileName , sfd . FileName , false ) ;
}
2011-02-20 08:40:22 +00:00
}
2011-06-11 12:54:26 +00:00
private void LoadStateAs ( )
{
2013-11-03 02:51:21 +00:00
if ( Global . Emulator is NullEmulator )
{
return ;
}
2013-04-16 00:19:31 +00:00
var ofd = new OpenFileDialog
2013-11-03 02:51:21 +00:00
{
InitialDirectory = PathManager . GetSaveStatePath ( Global . Game ) ,
Filter = "Save States (*.State)|*.State|All Files|*.*" ,
RestoreDirectory = true
} ;
2011-04-11 00:22:17 +00:00
2013-11-28 22:39:00 +00:00
var result = ofd . ShowHawkDialog ( ) ;
2011-06-11 12:54:26 +00:00
if ( result ! = DialogResult . OK )
return ;
2011-04-11 00:22:17 +00:00
2011-06-11 12:54:26 +00:00
if ( File . Exists ( ofd . FileName ) = = false )
2013-11-27 23:35:32 +00:00
{
2011-06-11 12:54:26 +00:00
return ;
2013-11-27 23:35:32 +00:00
}
2011-06-11 12:54:26 +00:00
LoadStateFile ( ofd . FileName , Path . GetFileName ( ofd . FileName ) ) ;
}
2011-04-11 00:22:17 +00:00
2013-11-27 23:35:32 +00:00
private static void SaveSlotSelectedMessage ( )
2011-02-20 08:40:22 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Slot " + Global . Config . SaveSlot + " selected." ) ;
2011-02-20 08:40:22 +00:00
}
2013-11-27 23:35:32 +00:00
private static VideoPluginSettings N64GenerateVideoSettings ( GameInfo game , bool hasmovie )
2013-05-14 23:06:47 +00:00
{
2013-11-27 23:35:32 +00:00
var PluginToUse = String . Empty ;
2013-06-08 20:13:11 +00:00
2013-11-30 02:20:34 +00:00
if ( hasmovie & & Global . MovieSession . Movie . Header [ HeaderKeys . PLATFORM ] = = "N64" & & Global . MovieSession . Movie . Header . ContainsKey ( HeaderKeys . VIDEOPLUGIN ) )
2013-05-27 20:25:06 +00:00
{
2013-11-30 02:20:34 +00:00
PluginToUse = Global . MovieSession . Movie . Header [ HeaderKeys . VIDEOPLUGIN ] ;
2013-05-27 20:25:06 +00:00
}
2013-06-08 20:13:11 +00:00
2013-09-07 01:38:24 +00:00
if ( PluginToUse = = "" | | ( PluginToUse ! = "Rice" & & PluginToUse ! = "Glide64" ) )
2013-05-27 20:25:06 +00:00
{
PluginToUse = Global . Config . N64VidPlugin ;
}
2013-11-27 23:35:32 +00:00
var video_settings = new VideoPluginSettings ( PluginToUse , Global . Config . N64VideoSizeX , Global . Config . N64VideoSizeY ) ;
2013-06-08 20:13:11 +00:00
2013-05-27 20:25:06 +00:00
if ( PluginToUse = = "Rice" )
2013-05-14 23:06:47 +00:00
{
2013-05-23 00:16:04 +00:00
Global . Config . RicePlugin . FillPerGameHacks ( game ) ;
video_settings . Parameters = Global . Config . RicePlugin . GetPluginSettings ( ) ;
2013-05-14 23:06:47 +00:00
}
2013-05-27 20:25:06 +00:00
else if ( PluginToUse = = "Glide64" )
2013-05-27 02:14:43 +00:00
{
Global . Config . GlidePlugin . FillPerGameHacks ( game ) ;
video_settings . Parameters = Global . Config . GlidePlugin . GetPluginSettings ( ) ;
}
2013-08-09 02:32:49 +00:00
else if ( PluginToUse = = "Glide64mk2" )
{
Global . Config . Glide64mk2Plugin . FillPerGameHacks ( game ) ;
video_settings . Parameters = Global . Config . Glide64mk2Plugin . GetPluginSettings ( ) ;
}
2013-09-07 01:38:24 +00:00
2013-11-30 02:20:34 +00:00
if ( hasmovie & & Global . MovieSession . Movie . Header [ HeaderKeys . PLATFORM ] = = "N64" & & Global . MovieSession . Movie . Header . ContainsKey ( HeaderKeys . VIDEOPLUGIN ) )
2013-05-27 20:25:06 +00:00
{
2013-11-27 23:35:32 +00:00
var settings = new List < string > ( video_settings . Parameters . Keys ) ;
foreach ( var setting in settings )
2013-05-27 20:25:06 +00:00
{
2013-11-30 02:20:34 +00:00
if ( Global . MovieSession . Movie . Header . ContainsKey ( setting ) )
2013-05-27 20:25:06 +00:00
{
2013-11-30 02:20:34 +00:00
var Value = Global . MovieSession . Movie . Header [ setting ] ;
2013-07-16 01:59:59 +00:00
if ( video_settings . Parameters [ setting ] is bool )
2013-06-08 20:13:11 +00:00
{
try
{
video_settings . Parameters [ setting ] = bool . Parse ( Value ) ;
}
catch { }
}
2013-07-16 01:59:59 +00:00
else if ( video_settings . Parameters [ setting ] is int )
2013-06-08 20:13:11 +00:00
{
try
{
video_settings . Parameters [ setting ] = int . Parse ( Value ) ;
}
catch { }
}
2013-05-27 20:25:06 +00:00
}
}
}
2013-09-07 01:38:24 +00:00
2013-05-14 23:06:47 +00:00
return video_settings ;
}
2011-02-20 08:40:22 +00:00
private void Render ( )
{
2013-10-20 18:02:43 +00:00
var video = Global . Emulator . VideoProvider ;
2013-11-27 23:35:32 +00:00
if ( video . BufferHeight ! = _lastHeight | | video . BufferWidth ! = _lastWidth )
2011-02-20 08:40:22 +00:00
{
2013-11-27 23:35:32 +00:00
_lastWidth = video . BufferWidth ;
_lastHeight = video . BufferHeight ;
2011-02-20 08:40:22 +00:00
FrameBufferResized ( ) ;
}
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . UpdateSource ( Global . Emulator . VideoProvider ) ;
2011-02-20 08:40:22 +00:00
}
2011-07-10 19:50:59 +00:00
//sends a simulation of a plain alt key keystroke
2013-11-03 02:51:21 +00:00
private void SendPlainAltKey ( int lparam )
2011-07-10 19:50:59 +00:00
{
2013-11-27 23:35:32 +00:00
var m = new Message { WParam = new IntPtr ( 0xF100 ) , LParam = new IntPtr ( lparam ) , Msg = 0x0112 , HWnd = Handle } ;
2011-07-10 19:50:59 +00:00
base . WndProc ( ref m ) ;
}
//sends an alt+mnemonic combination
2013-11-03 02:51:21 +00:00
private void SendAltKeyChar ( char c )
2011-07-10 19:50:59 +00:00
{
2013-10-27 07:54:00 +00:00
typeof ( ToolStrip ) . InvokeMember ( "ProcessMnemonicInternal" , System . Reflection . BindingFlags . NonPublic | System . Reflection . BindingFlags . InvokeMethod | System . Reflection . BindingFlags . Instance , null , MainformMenu , new object [ ] { c } ) ;
2011-07-10 19:50:59 +00:00
}
2013-11-27 23:35:32 +00:00
private static string FormatFilter ( params string [ ] args )
2011-07-24 06:45:05 +00:00
{
var sb = new StringBuilder ( ) ;
if ( args . Length % 2 ! = 0 ) throw new ArgumentException ( ) ;
2013-11-27 23:35:32 +00:00
var num = args . Length / 2 ;
2011-07-24 06:45:05 +00:00
for ( int i = 0 ; i < num ; i + + )
{
sb . AppendFormat ( "{0} ({1})|{1}" , args [ i * 2 ] , args [ i * 2 + 1 ] ) ;
if ( i ! = num - 1 ) sb . Append ( '|' ) ;
}
2013-11-27 23:35:32 +00:00
var str = sb . ToString ( ) . Replace ( "%ARCH%" , "*.zip;*.rar;*.7z" ) ;
2011-07-24 06:45:05 +00:00
str = str . Replace ( ";" , "; " ) ;
return str ;
}
2013-11-27 23:35:32 +00:00
private void OpenRom ( )
2011-06-11 12:54:26 +00:00
{
2013-10-20 18:02:43 +00:00
var ofd = new OpenFileDialog { InitialDirectory = PathManager . GetRomsPath ( Global . Emulator . SystemId ) } ;
2011-07-24 06:45:05 +00:00
2012-03-18 00:00:47 +00:00
//adelikat: ugly design for this, I know
2013-11-10 02:32:47 +00:00
if ( VersionInfo . INTERIM )
2012-03-18 00:00:47 +00:00
{
ofd . Filter = FormatFilter (
2013-04-29 01:57:41 +00:00
"Rom Files" , "*.nes;*.fds;*.sms;*.gg;*.sg;*.pce;*.sgx;*.bin;*.smd;*.rom;*.a26;*.a78;*.cue;*.exe;*.gb;*.gbc;*.gen;*.md;*.col;.int;*.smc;*.sfc;*.prg;*.d64;*.g64;*.crt;*.sgb;*.xml;*.z64;*.v64;*.n64;%ARCH%" ,
2012-11-13 20:10:06 +00:00
"Music Files" , "*.psf;*.sid" ,
2012-03-18 00:00:47 +00:00
"Disc Images" , "*.cue" ,
2012-11-18 02:51:39 +00:00
"NES" , "*.nes;*.fds;%ARCH%" ,
2013-04-24 22:09:11 +00:00
"Super NES" , "*.smc;*.sfc;*.xml;%ARCH%" ,
2012-03-18 00:00:47 +00:00
"Master System" , "*.sms;*.gg;*.sg;%ARCH%" ,
"PC Engine" , "*.pce;*.sgx;*.cue;%ARCH%" ,
"TI-83" , "*.rom;%ARCH%" ,
"Archive Files" , "%ARCH%" ,
"Savestate" , "*.state" ,
2012-10-20 13:40:58 +00:00
"Atari 2600" , "*.a26;*.bin;%ARCH%" ,
2012-10-23 19:13:57 +00:00
"Atari 7800" , "*.a78;*.bin;%ARCH%" ,
2012-09-23 02:44:04 +00:00
"Genesis (experimental)" , "*.gen;*.smd;*.bin;*.md;*.cue;%ARCH%" ,
2013-03-09 18:41:23 +00:00
"Gameboy" , "*.gb;*.gbc;*.sgb;%ARCH%" ,
2012-11-18 02:51:39 +00:00
"Colecovision" , "*.col;%ARCH%" ,
2012-09-26 01:20:11 +00:00
"Intellivision (very experimental)" , "*.int;*.bin;*.rom;%ARCH%" ,
2012-09-10 21:26:22 +00:00
"PSX Executables (very experimental)" , "*.exe" ,
2012-11-13 20:10:06 +00:00
"PSF Playstation Sound File (very experimental)" , "*.psf" ,
2012-11-18 02:51:39 +00:00
"Commodore 64 (experimental)" , "*.prg; *.d64, *.g64; *.crt;%ARCH%" ,
2012-11-13 20:10:06 +00:00
"SID Commodore 64 Music File" , "*.sid;%ARCH%" ,
2013-04-29 01:57:41 +00:00
"Nintendo 64" , "*.z64;*.v64;*.n64" ,
2012-03-18 00:00:47 +00:00
"All Files" , "*.*" ) ;
}
else
{
ofd . Filter = FormatFilter (
2013-07-28 22:45:19 +00:00
"Rom Files" , "*.nes;*.fds;*.sms;*.gg;*.sg;*.gb;*.gbc;*.pce;*.sgx;*.bin;*.smd;*.gen;*.md;*.smc;*.sfc;*.a26;*.a78;*.col;*.rom;*.cue;*.sgb;*.z64;*.v64;*.n64;*.xml;%ARCH%" ,
2012-03-18 00:00:47 +00:00
"Disc Images" , "*.cue" ,
2012-11-18 02:51:39 +00:00
"NES" , "*.nes;*.fds;%ARCH%" ,
2013-04-24 22:09:11 +00:00
"Super NES" , "*.smc;*.sfc;*.xml;%ARCH%" ,
2013-07-28 22:45:19 +00:00
"Nintendo 64" , "*.z64;*.v64;*.n64" ,
2013-03-09 18:41:23 +00:00
"Gameboy" , "*.gb;*.gbc;*.sgb;%ARCH%" ,
2012-03-18 00:00:47 +00:00
"Master System" , "*.sms;*.gg;*.sg;%ARCH%" ,
"PC Engine" , "*.pce;*.sgx;*.cue;%ARCH%" ,
2012-10-20 13:40:58 +00:00
"Atari 2600" , "*.a26;%ARCH%" ,
2012-12-23 18:55:05 +00:00
"Atari 7800" , "*.a78;%ARCH%" ,
2012-11-18 02:51:39 +00:00
"Colecovision" , "*.col;%ARCH%" ,
2012-03-18 00:00:47 +00:00
"TI-83" , "*.rom;%ARCH%" ,
"Archive Files" , "%ARCH%" ,
"Savestate" , "*.state" ,
2012-09-23 02:44:04 +00:00
"Genesis (experimental)" , "*.gen;*.md;*.smd;*.bin;*.cue;%ARCH%" ,
2013-09-07 01:38:24 +00:00
2012-03-18 00:00:47 +00:00
"All Files" , "*.*" ) ;
}
2013-09-07 01:38:24 +00:00
2011-06-11 12:54:26 +00:00
ofd . RestoreDirectory = false ;
2013-11-27 23:35:32 +00:00
ofd . FilterIndex = _lastOpenRomFilter ;
2013-09-07 01:38:24 +00:00
2013-11-28 22:39:00 +00:00
var result = ofd . ShowHawkDialog ( ) ;
2011-06-11 12:54:26 +00:00
if ( result ! = DialogResult . OK )
2013-11-28 22:39:00 +00:00
{
2011-06-11 12:54:26 +00:00
return ;
2013-11-28 22:39:00 +00:00
}
2011-06-11 12:54:26 +00:00
var file = new FileInfo ( ofd . FileName ) ;
Global . Config . LastRomPath = file . DirectoryName ;
2013-11-27 23:35:32 +00:00
_lastOpenRomFilter = ofd . FilterIndex ;
2011-06-11 12:54:26 +00:00
LoadRom ( file . FullName ) ;
}
2013-11-03 02:51:21 +00:00
private void SaveConfig ( )
{
if ( Global . Config . SaveWindowPosition )
{
Global . Config . MainWndx = Location . X ;
Global . Config . MainWndy = Location . Y ;
}
else
{
Global . Config . MainWndx = - 1 ;
Global . Config . MainWndy = - 1 ;
}
if ( Global . Config . ShowLogWindow ) LogConsole . SaveConfigSettings ( ) ;
ConfigService . Save ( PathManager . DefaultIniPath , Global . Config ) ;
}
private void PreviousSlot ( )
{
if ( Global . Config . SaveSlot = = 0 )
2013-11-27 23:35:32 +00:00
{
Global . Config . SaveSlot = 9 ; //Wrap to end of slot list
}
2013-11-03 02:51:21 +00:00
else if ( Global . Config . SaveSlot > 9 )
2013-11-27 23:35:32 +00:00
{
Global . Config . SaveSlot = 9 ; //Meh, just in case
}
else
{
Global . Config . SaveSlot - - ;
}
2013-11-03 02:51:21 +00:00
SaveSlotSelectedMessage ( ) ;
UpdateStatusSlots ( ) ;
}
private void NextSlot ( )
{
if ( Global . Config . SaveSlot > = 9 )
2013-11-27 23:35:32 +00:00
{
Global . Config . SaveSlot = 0 ; //Wrap to beginning of slot list
}
2013-11-03 02:51:21 +00:00
else if ( Global . Config . SaveSlot < 0 )
2013-11-27 23:35:32 +00:00
{
Global . Config . SaveSlot = 0 ; //Meh, just in case
}
else
{
Global . Config . SaveSlot + + ;
}
2013-11-03 02:51:21 +00:00
SaveSlotSelectedMessage ( ) ;
UpdateStatusSlots ( ) ;
}
2013-11-27 23:35:32 +00:00
private static void ToggleFPS ( )
2013-11-03 02:51:21 +00:00
{
Global . Config . DisplayFPS ^ = true ;
}
2013-11-27 23:35:32 +00:00
private static void ToggleFrameCounter ( )
2013-11-03 02:51:21 +00:00
{
Global . Config . DisplayFrameCounter ^ = true ;
}
2013-11-27 23:35:32 +00:00
private static void ToggleLagCounter ( )
2013-11-03 02:51:21 +00:00
{
Global . Config . DisplayLagCounter ^ = true ;
}
2013-11-27 23:35:32 +00:00
private static void ToggleInputDisplay ( )
2013-11-03 02:51:21 +00:00
{
Global . Config . DisplayInput ^ = true ;
}
2013-11-27 23:35:32 +00:00
private static void ToggleReadOnly ( )
2013-11-03 02:51:21 +00:00
{
if ( Global . MovieSession . Movie . IsActive )
{
2013-12-03 18:08:45 +00:00
Global . MovieSession . ReadOnly ^ = true ;
if ( Global . MovieSession . ReadOnly )
2013-11-03 02:51:21 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Movie read-only mode" ) ;
2013-11-03 02:51:21 +00:00
}
else
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Movie read+write mode" ) ;
2013-11-03 02:51:21 +00:00
}
}
else
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "No movie active" ) ;
2013-11-03 02:51:21 +00:00
}
}
2013-11-27 23:35:32 +00:00
private static void VolumeUp ( )
2013-11-03 02:51:21 +00:00
{
Global . Config . SoundVolume + = 10 ;
if ( Global . Config . SoundVolume > 100 )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
Global . Config . SoundVolume = 100 ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 16:07:58 +00:00
GlobalWin . Sound . ChangeVolume ( Global . Config . SoundVolume ) ;
2013-11-27 23:35:32 +00:00
GlobalWin . OSD . AddMessage ( "Volume " + Global . Config . SoundVolume ) ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
private static void VolumeDown ( )
2013-11-03 02:51:21 +00:00
{
Global . Config . SoundVolume - = 10 ;
if ( Global . Config . SoundVolume < 0 )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
Global . Config . SoundVolume = 0 ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 16:07:58 +00:00
GlobalWin . Sound . ChangeVolume ( Global . Config . SoundVolume ) ;
2013-11-27 23:35:32 +00:00
GlobalWin . OSD . AddMessage ( "Volume " + Global . Config . SoundVolume ) ;
2013-11-03 02:51:21 +00:00
}
2012-12-10 00:43:43 +00:00
2013-11-27 23:35:32 +00:00
private static void SoftReset ( )
2012-12-10 00:43:43 +00:00
{
2013-11-03 02:51:21 +00:00
//is it enough to run this for one frame? maybe..
if ( Global . Emulator . ControllerDefinition . BoolButtons . Contains ( "Reset" ) )
2013-10-11 16:32:36 +00:00
{
2013-11-03 02:51:21 +00:00
if ( ! Global . MovieSession . Movie . IsPlaying | | Global . MovieSession . Movie . IsFinished )
{
Global . ClickyVirtualPadController . Click ( "Reset" ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Reset button pressed." ) ;
2013-11-03 02:51:21 +00:00
}
2013-10-11 16:32:36 +00:00
}
2013-11-03 02:51:21 +00:00
}
2013-10-11 16:32:36 +00:00
2013-11-27 23:35:32 +00:00
private static void HardReset ( )
2013-11-03 02:51:21 +00:00
{
//is it enough to run this for one frame? maybe..
if ( Global . Emulator . ControllerDefinition . BoolButtons . Contains ( "Power" ) )
2013-10-11 16:32:36 +00:00
{
2013-11-03 02:51:21 +00:00
if ( ! Global . MovieSession . Movie . IsPlaying | | Global . MovieSession . Movie . IsFinished )
2013-10-11 16:32:36 +00:00
{
2013-11-03 02:51:21 +00:00
Global . ClickyVirtualPadController . Click ( "Power" ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Power button pressed." ) ;
2013-10-11 16:32:36 +00:00
}
}
2013-11-03 02:51:21 +00:00
}
private void UpdateStatusSlots ( )
{
2013-11-27 23:35:32 +00:00
_stateSlots . Update ( ) ;
2013-11-03 02:51:21 +00:00
2013-11-27 23:35:32 +00:00
Slot1StatusButton . ForeColor = _stateSlots . HasSlot ( 1 ) ? Color . Black : Color . Black ;
Slot2StatusButton . ForeColor = _stateSlots . HasSlot ( 2 ) ? Color . Black : Color . Black ;
Slot3StatusButton . ForeColor = _stateSlots . HasSlot ( 3 ) ? Color . Black : Color . Black ;
Slot4StatusButton . ForeColor = _stateSlots . HasSlot ( 4 ) ? Color . Black : Color . Black ;
Slot5StatusButton . ForeColor = _stateSlots . HasSlot ( 5 ) ? Color . Black : Color . Black ;
Slot6StatusButton . ForeColor = _stateSlots . HasSlot ( 6 ) ? Color . Black : Color . Black ;
Slot7StatusButton . ForeColor = _stateSlots . HasSlot ( 7 ) ? Color . Black : Color . Black ;
Slot8StatusButton . ForeColor = _stateSlots . HasSlot ( 8 ) ? Color . Black : Color . Black ;
Slot9StatusButton . ForeColor = _stateSlots . HasSlot ( 9 ) ? Color . Black : Color . Black ;
Slot0StatusButton . ForeColor = _stateSlots . HasSlot ( 0 ) ? Color . Black : Color . Black ;
2013-11-03 02:51:21 +00:00
Slot1StatusButton . BackColor = SystemColors . Control ;
Slot2StatusButton . BackColor = SystemColors . Control ;
Slot3StatusButton . BackColor = SystemColors . Control ;
Slot4StatusButton . BackColor = SystemColors . Control ;
Slot5StatusButton . BackColor = SystemColors . Control ;
Slot6StatusButton . BackColor = SystemColors . Control ;
Slot7StatusButton . BackColor = SystemColors . Control ;
Slot8StatusButton . BackColor = SystemColors . Control ;
Slot9StatusButton . BackColor = SystemColors . Control ;
Slot0StatusButton . BackColor = SystemColors . Control ;
if ( Global . Config . SaveSlot = = 0 ) Slot0StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 1 ) Slot1StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 2 ) Slot2StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 3 ) Slot3StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 4 ) Slot4StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 5 ) Slot5StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 6 ) Slot6StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 7 ) Slot7StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 8 ) Slot8StatusButton . BackColor = SystemColors . ControlDark ;
if ( Global . Config . SaveSlot = = 9 ) Slot9StatusButton . BackColor = SystemColors . ControlDark ;
}
private Bitmap CaptureOSD ( ) //sort of like MakeScreenShot(), but with OSD and LUA captured as well. slow and bad.
{
// this code captures the emu display with OSD and lua composited onto it.
// it's slow and a bit hackish; a better solution is to create a new
// "dummy render" class that implements IRenderer, IBlitter, and possibly
// IVideoProvider, and pass that to DisplayManager.UpdateSourceEx()
if ( captureosd_rvp = = null )
2013-10-11 16:32:36 +00:00
{
2013-11-03 02:51:21 +00:00
captureosd_rvp = new RetainedViewportPanel ( ) ;
captureosd_srp = new SysdrawingRenderPanel ( captureosd_rvp ) ;
2013-10-11 16:32:36 +00:00
}
2013-11-03 02:51:21 +00:00
// this size can be different for showing off stretching or filters
captureosd_rvp . Width = Global . Emulator . VideoProvider . BufferWidth ;
captureosd_rvp . Height = Global . Emulator . VideoProvider . BufferHeight ;
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . UpdateSourceEx ( Global . Emulator . VideoProvider , captureosd_srp ) ;
2013-11-03 02:51:21 +00:00
return ( Bitmap ) captureosd_rvp . GetBitmap ( ) . Clone ( ) ;
2012-12-10 00:43:43 +00:00
}
2013-11-03 02:51:21 +00:00
private void ShowConsole ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
LogConsole . ShowConsole ( ) ;
LogWindowAsConsoleMenuItem . Enabled = false ;
}
2013-11-02 19:28:45 +00:00
2013-11-03 02:51:21 +00:00
private void HideConsole ( )
{
LogConsole . HideConsole ( ) ;
LogWindowAsConsoleMenuItem . Enabled = true ;
2011-06-11 12:54:26 +00:00
}
2011-04-16 19:35:37 +00:00
2013-11-03 02:51:21 +00:00
private void IncreaseWindowSize ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
switch ( Global . Config . TargetZoomFactor )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
case 1 :
Global . Config . TargetZoomFactor = 2 ;
break ;
case 2 :
Global . Config . TargetZoomFactor = 3 ;
break ;
case 3 :
Global . Config . TargetZoomFactor = 4 ;
break ;
case 4 :
Global . Config . TargetZoomFactor = 5 ;
break ;
case 5 :
Global . Config . TargetZoomFactor = 10 ;
break ;
case 10 :
return ;
2011-06-11 12:54:26 +00:00
}
2013-11-03 02:51:21 +00:00
FrameBufferResized ( ) ;
}
private void DecreaseWIndowSize ( )
{
switch ( Global . Config . TargetZoomFactor )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
case 1 :
return ;
case 2 :
Global . Config . TargetZoomFactor = 1 ;
break ;
case 3 :
Global . Config . TargetZoomFactor = 2 ;
break ;
case 4 :
Global . Config . TargetZoomFactor = 3 ;
break ;
case 5 :
Global . Config . TargetZoomFactor = 4 ;
break ;
case 10 :
Global . Config . TargetZoomFactor = 5 ;
return ;
2011-06-11 12:54:26 +00:00
}
2013-11-03 02:51:21 +00:00
FrameBufferResized ( ) ;
}
2012-05-28 01:29:43 +00:00
2013-11-03 02:51:21 +00:00
private void IncreaseSpeed ( )
{
int oldp = Global . Config . SpeedPercent ;
int newp ;
if ( oldp < 3 ) newp = 3 ;
else if ( oldp < 6 ) newp = 6 ;
else if ( oldp < 12 ) newp = 12 ;
else if ( oldp < 25 ) newp = 25 ;
else if ( oldp < 50 ) newp = 50 ;
else if ( oldp < 75 ) newp = 75 ;
else if ( oldp < 100 ) newp = 100 ;
else if ( oldp < 150 ) newp = 150 ;
else if ( oldp < 200 ) newp = 200 ;
else if ( oldp < 400 ) newp = 400 ;
else if ( oldp < 800 ) newp = 800 ;
else newp = 1600 ;
SetSpeedPercent ( newp ) ;
2012-04-21 22:46:48 +00:00
}
2013-11-03 02:51:21 +00:00
private void DecreaseSpeed ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
int oldp = Global . Config . SpeedPercent ;
int newp ;
if ( oldp > 800 ) newp = 800 ;
else if ( oldp > 400 ) newp = 400 ;
else if ( oldp > 200 ) newp = 200 ;
else if ( oldp > 150 ) newp = 150 ;
else if ( oldp > 100 ) newp = 100 ;
else if ( oldp > 75 ) newp = 75 ;
else if ( oldp > 50 ) newp = 50 ;
else if ( oldp > 25 ) newp = 25 ;
else if ( oldp > 12 ) newp = 12 ;
else if ( oldp > 6 ) newp = 6 ;
else if ( oldp > 3 ) newp = 3 ;
else newp = 1 ;
SetSpeedPercent ( newp ) ;
2011-06-11 12:54:26 +00:00
}
2013-11-27 23:35:32 +00:00
private static void SaveMovie ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Global . MovieSession . Movie . IsActive )
{
2013-11-23 18:18:58 +00:00
Global . MovieSession . Movie . Save ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( Global . MovieSession . Movie . Filename + " saved." ) ;
2013-11-03 02:51:21 +00:00
}
2011-06-11 12:54:26 +00:00
}
2013-11-03 02:51:21 +00:00
private void HandleToggleLight ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
if ( MainStatusBar . Visible )
{
if ( Global . Emulator . CoreComm . UsesDriveLed )
{
if ( ! LedLightStatusLabel . Visible )
{
LedLightStatusLabel . Visible = true ;
}
if ( Global . Emulator . CoreComm . DriveLED )
{
LedLightStatusLabel . Image = Properties . Resources . LightOn ;
}
else
{
LedLightStatusLabel . Image = Properties . Resources . LightOff ;
}
}
else
{
if ( LedLightStatusLabel . Visible )
{
LedLightStatusLabel . Visible = false ;
}
}
}
2011-06-11 12:54:26 +00:00
}
2013-11-03 02:51:21 +00:00
private void UpdateKeyPriorityIcon ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
switch ( Global . Config . Input_Hotkey_OverrideOptions )
{
default :
case 0 :
KeyPriorityStatusLabel . Image = Properties . Resources . Both ;
KeyPriorityStatusLabel . ToolTipText = "Key priority: Allow both hotkeys and controller buttons" ;
break ;
case 1 :
KeyPriorityStatusLabel . Image = Properties . Resources . GameController ;
KeyPriorityStatusLabel . ToolTipText = "Key priority: Controller buttons will override hotkeys" ;
break ;
case 2 :
KeyPriorityStatusLabel . Image = Properties . Resources . HotKeys ;
KeyPriorityStatusLabel . ToolTipText = "Key priority: Hotkeys will override controller buttons" ;
break ;
}
2011-06-11 12:54:26 +00:00
}
2013-11-27 23:35:32 +00:00
private static void ToggleModePokeMode ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
Global . Config . MoviePlaybackPokeMode ^ = true ;
2013-11-27 23:35:32 +00:00
GlobalWin . OSD . AddMessage ( Global . Config . MoviePlaybackPokeMode ? "Movie Poke mode enabled" : "Movie Poke mode disabled" ) ;
2011-06-11 12:54:26 +00:00
}
2013-11-27 23:35:32 +00:00
private static void ToggleBackgroundInput ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
Global . Config . AcceptBackgroundInput ^ = true ;
2013-11-27 23:35:32 +00:00
GlobalWin . OSD . AddMessage ( Global . Config . AcceptBackgroundInput
? "Background Input enabled"
: "Background Input disabled" ) ;
2011-06-11 12:54:26 +00:00
}
2013-11-27 23:35:32 +00:00
private static void LimitFrameRateMessage ( )
2011-06-11 12:54:26 +00:00
{
2013-11-27 23:35:32 +00:00
GlobalWin . OSD . AddMessage ( Global . Config . ClockThrottle ? "Framerate limiting on" : "Framerate limiting off" ) ;
2011-06-11 23:54:35 +00:00
}
2013-11-27 23:35:32 +00:00
private static void VsyncMessage ( )
2011-06-11 12:54:26 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage (
2013-11-03 02:51:21 +00:00
"Display Vsync set to " + ( Global . Config . VSyncThrottle ? "on" : "off" )
) ;
2011-06-11 12:54:26 +00:00
}
2013-11-27 23:35:32 +00:00
private static bool StateErrorAskUser ( string title , string message )
2011-06-11 12:54:26 +00:00
{
2013-11-03 02:51:21 +00:00
var result = MessageBox . Show ( message ,
title ,
MessageBoxButtons . YesNo ,
MessageBoxIcon . Question
) ;
return result = = DialogResult . Yes ;
2011-06-18 18:27:51 +00:00
}
2011-06-26 21:11:12 +00:00
2013-11-03 02:51:21 +00:00
//--alt key hacks
protected override void WndProc ( ref Message m )
2011-06-30 02:22:12 +00:00
{
2013-11-03 02:51:21 +00:00
//this is necessary to trap plain alt keypresses so that only our hotkey system gets them
if ( m . Msg = = 0x0112 ) //WM_SYSCOMMAND
if ( m . WParam . ToInt32 ( ) = = 0xF100 ) //SC_KEYMENU
return ;
base . WndProc ( ref m ) ;
2011-06-30 02:22:12 +00:00
}
2011-07-01 01:28:25 +00:00
2013-11-03 02:51:21 +00:00
protected override bool ProcessDialogChar ( char charCode )
2012-09-16 16:52:30 +00:00
{
2013-11-03 02:51:21 +00:00
//this is necessary to trap alt+char combinations so that only our hotkey system gets them
2013-11-27 23:35:32 +00:00
return ( ModifierKeys & Keys . Alt ) ! = 0 | | base . ProcessDialogChar ( charCode ) ;
2012-09-16 16:52:30 +00:00
}
2013-11-03 02:51:21 +00:00
#endregion
#region Frame Loop
private void StepRunLoop_Throttle ( )
2011-07-01 01:28:25 +00:00
{
2013-11-03 02:51:21 +00:00
SyncThrottle ( ) ;
2013-11-27 23:35:32 +00:00
_throttle . signal_frameAdvance = _runloopFrameadvance ;
_throttle . signal_continuousframeAdvancing = _runloopFrameProgress ;
2011-07-01 01:28:25 +00:00
2013-11-27 23:35:32 +00:00
_throttle . Step ( true , - 1 ) ;
2013-11-03 02:51:21 +00:00
}
2012-10-07 19:52:09 +00:00
2013-11-03 02:51:21 +00:00
private void StepRunLoop_Core ( )
{
bool runFrame = false ;
2013-11-27 23:35:32 +00:00
_runloopFrameadvance = false ;
2013-11-03 02:51:21 +00:00
DateTime now = DateTime . Now ;
bool suppressCaptureRewind = false ;
2012-10-07 19:52:09 +00:00
2013-11-03 02:51:21 +00:00
double frameAdvanceTimestampDelta = ( now - FrameAdvanceTimestamp ) . TotalMilliseconds ;
bool frameProgressTimeElapsed = Global . Config . FrameProgressDelayMs < frameAdvanceTimestampDelta ;
2012-10-07 19:52:09 +00:00
2013-11-03 02:51:21 +00:00
if ( Global . Config . SkipLagFrame & & Global . Emulator . IsLagFrame & & frameProgressTimeElapsed )
2012-10-07 19:52:09 +00:00
{
2013-11-03 02:51:21 +00:00
runFrame = true ;
2012-10-07 19:52:09 +00:00
}
2013-11-03 16:47:21 +00:00
if ( Global . ClientControls [ "Frame Advance" ] | | PressFrameAdvance )
2012-10-07 19:52:09 +00:00
{
2013-11-03 02:51:21 +00:00
//handle the initial trigger of a frame advance
if ( FrameAdvanceTimestamp = = DateTime . MinValue )
{
PauseEmulator ( ) ;
runFrame = true ;
2013-11-27 23:35:32 +00:00
_runloopFrameadvance = true ;
2013-11-03 02:51:21 +00:00
FrameAdvanceTimestamp = now ;
}
else
{
//handle the timed transition from countdown to FrameProgress
if ( frameProgressTimeElapsed )
{
runFrame = true ;
2013-11-27 23:35:32 +00:00
_runloopFrameProgress = true ;
2013-11-03 02:51:21 +00:00
UnpauseEmulator ( ) ;
}
}
2012-10-07 19:52:09 +00:00
}
else
{
2013-11-03 02:51:21 +00:00
//handle release of frame advance: do we need to deactivate FrameProgress?
2013-11-27 23:35:32 +00:00
if ( _runloopFrameProgress )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
_runloopFrameProgress = false ;
2013-11-03 02:51:21 +00:00
PauseEmulator ( ) ;
}
FrameAdvanceTimestamp = DateTime . MinValue ;
2012-10-07 19:52:09 +00:00
}
2013-11-03 02:51:21 +00:00
if ( ! EmulatorPaused )
2012-10-07 19:52:09 +00:00
{
2013-11-03 02:51:21 +00:00
runFrame = true ;
2012-10-07 19:52:09 +00:00
}
2013-11-03 02:51:21 +00:00
bool ReturnToRecording = Global . MovieSession . Movie . IsRecording ;
2013-11-03 16:47:21 +00:00
if ( RewindActive & & ( Global . ClientControls [ "Rewind" ] | | PressRewind ) )
2012-10-07 19:52:09 +00:00
{
2013-11-03 02:51:21 +00:00
Rewind ( 1 ) ;
suppressCaptureRewind = true ;
if ( 0 = = RewindBuf . Count )
{
runFrame = false ;
}
else
{
runFrame = true ;
}
//we don't want to capture input when rewinding, even in record mode
if ( Global . MovieSession . Movie . IsRecording )
{
Global . MovieSession . Movie . SwitchToPlay ( ) ;
}
2012-10-07 19:52:09 +00:00
}
2013-11-03 02:51:21 +00:00
if ( UpdateFrame )
2012-10-07 19:52:09 +00:00
{
2013-11-03 02:51:21 +00:00
runFrame = true ;
if ( Global . MovieSession . Movie . IsRecording )
{
Global . MovieSession . Movie . SwitchToPlay ( ) ;
}
2012-10-07 19:52:09 +00:00
}
2013-11-03 02:51:21 +00:00
bool genSound = false ;
bool coreskipaudio = false ;
if ( runFrame )
2012-10-07 19:52:09 +00:00
{
2013-11-03 16:47:21 +00:00
bool ff = Global . ClientControls [ "Fast Forward" ] | | Global . ClientControls [ "Turbo" ] ;
bool fff = Global . ClientControls [ "Turbo" ] ;
2013-11-27 23:35:32 +00:00
bool updateFpsString = ( _runloopLastFf ! = ff ) ;
_runloopLastFf = ff ;
2013-11-03 02:51:21 +00:00
2013-11-20 02:14:29 +00:00
//client input-related duties
GlobalWin . OSD . ClearGUIText ( ) ;
2013-11-03 02:51:21 +00:00
if ( ! fff )
{
2013-11-27 23:35:32 +00:00
GlobalWin . Tools . UpdateToolsBefore ( ) ;
2013-11-03 02:51:21 +00:00
}
Global . ClickyVirtualPadController . FrameTick ( ) ;
2013-11-27 23:35:32 +00:00
_runloopFps + + ;
2013-11-03 02:51:21 +00:00
2013-11-27 23:35:32 +00:00
if ( ( DateTime . Now - _runloopSecond ) . TotalSeconds > 1 )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
_runloopLastFps = _runloopFps ;
_runloopSecond = DateTime . Now ;
_runloopFps = 0 ;
2013-11-03 02:51:21 +00:00
updateFpsString = true ;
}
if ( updateFpsString )
{
2013-11-27 23:35:32 +00:00
string fps_string = _runloopLastFps + " fps" ;
2013-11-03 02:51:21 +00:00
if ( fff )
{
fps_string + = " >>>>" ;
}
else if ( ff )
{
fps_string + = " >>" ;
}
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . FPS = fps_string ;
2013-11-03 02:51:21 +00:00
}
if ( ! suppressCaptureRewind & & RewindActive ) CaptureRewindState ( ) ;
2013-11-27 23:35:32 +00:00
if ( ! _runloopFrameadvance ) genSound = true ;
2013-11-03 02:51:21 +00:00
else if ( ! Global . Config . MuteFrameAdvance )
genSound = true ;
2013-11-03 16:53:05 +00:00
Global . MovieSession . HandleMovieOnFrameLoop ( ) ;
2013-11-03 02:51:21 +00:00
2013-11-27 23:35:32 +00:00
coreskipaudio = Global . ClientControls [ "Turbo" ] & & _currAviWriter = = null ;
2013-11-03 02:51:21 +00:00
//=======================================
Global . CheatList . Pulse ( ) ;
2013-11-27 23:35:32 +00:00
Global . Emulator . FrameAdvance ( ! _throttle . skipnextframe | | _currAviWriter ! = null , ! coreskipaudio ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
Global . CheatList . Pulse ( ) ;
//=======================================
if ( ! PauseAVI )
{
AVIFrameAdvance ( ) ;
}
if ( Global . Emulator . IsLagFrame & & Global . Config . AutofireLagFrames )
{
Global . AutoFireController . IncrementStarts ( ) ;
}
2012-10-07 19:52:09 +00:00
2013-11-03 02:51:21 +00:00
PressFrameAdvance = false ;
if ( ! fff )
{
UpdateToolsAfter ( ) ;
}
2012-10-07 19:52:09 +00:00
}
2013-11-03 16:47:21 +00:00
if ( Global . ClientControls [ "Rewind" ] | | PressRewind )
2012-10-07 19:52:09 +00:00
{
2013-11-03 02:51:21 +00:00
UpdateToolsAfter ( ) ;
if ( ReturnToRecording )
{
Global . MovieSession . Movie . SwitchToRecord ( ) ;
}
PressRewind = false ;
2012-10-07 19:52:09 +00:00
}
2013-11-03 02:51:21 +00:00
if ( UpdateFrame )
2012-10-07 19:52:09 +00:00
{
2013-11-03 02:51:21 +00:00
if ( ReturnToRecording )
{
Global . MovieSession . Movie . SwitchToRecord ( ) ;
}
UpdateFrame = false ;
2012-10-07 19:52:09 +00:00
}
2013-11-03 02:51:21 +00:00
if ( genSound & & ! coreskipaudio )
2012-10-07 19:52:09 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Sound . UpdateSound ( ) ;
2012-10-07 19:52:09 +00:00
}
else
2013-11-03 16:07:58 +00:00
GlobalWin . Sound . UpdateSilence ( ) ;
2011-07-01 01:28:25 +00:00
}
2013-11-03 02:51:21 +00:00
#endregion
2012-11-26 21:08:08 +00:00
#region AVI Stuff
2012-07-23 00:33:30 +00:00
/// <summary>
/// start avi recording, unattended
/// </summary>
/// <param name="videowritername">match the short name of an ivideowriter</param>
/// <param name="filename">filename to save to</param>
2013-11-03 02:51:21 +00:00
private void RecordAVI ( string videowritername , string filename )
2012-07-23 00:33:30 +00:00
{
_RecordAVI ( videowritername , filename , true ) ;
}
/// <summary>
/// start avi recording, asking user for filename and options
/// </summary>
2013-11-03 02:51:21 +00:00
private void RecordAVI ( )
2012-07-23 00:33:30 +00:00
{
_RecordAVI ( null , null , false ) ;
}
/// <summary>
/// start avi recording
/// </summary>
/// <param name="videowritername"></param>
/// <param name="filename"></param>
/// <param name="unattended"></param>
private void _RecordAVI ( string videowritername , string filename , bool unattended )
2011-07-09 21:13:18 +00:00
{
2013-11-27 23:35:32 +00:00
if ( _currAviWriter ! = null ) return ;
2012-06-13 19:50:50 +00:00
// select IVideoWriter to use
2012-07-23 00:33:30 +00:00
IVideoWriter aw = null ;
var writers = VideoWriterInventory . GetAllVideoWriters ( ) ;
2013-04-16 00:19:31 +00:00
var video_writers = writers as IVideoWriter [ ] ? ? writers . ToArray ( ) ;
2012-07-23 00:33:30 +00:00
if ( unattended )
{
2013-04-16 00:19:31 +00:00
foreach ( var w in video_writers )
2012-07-23 00:33:30 +00:00
{
if ( w . ShortName ( ) = = videowritername )
{
aw = w ;
break ;
}
}
}
else
{
2013-11-27 23:35:32 +00:00
aw = VideoWriterChooserForm . DoVideoWriterChoserDlg ( video_writers , GlobalWin . MainForm , out _avwriterResizew , out _avwriterResizeh ) ;
2012-07-23 00:33:30 +00:00
}
2012-06-13 19:50:50 +00:00
2013-04-16 00:19:31 +00:00
foreach ( var w in video_writers )
2011-07-11 23:26:20 +00:00
{
2012-06-13 19:50:50 +00:00
if ( w ! = aw )
w . Dispose ( ) ;
2011-07-11 23:26:20 +00:00
}
2012-07-23 00:33:30 +00:00
2012-06-13 19:50:50 +00:00
if ( aw = = null )
2011-07-11 23:26:20 +00:00
{
2012-07-23 00:33:30 +00:00
if ( unattended )
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( string . Format ( "Couldn't start video writer \"{0}\"" , videowritername ) ) ;
2012-07-23 00:33:30 +00:00
else
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "A/V capture canceled." ) ;
2011-07-11 23:26:20 +00:00
return ;
2012-06-13 19:50:50 +00:00
}
2011-08-09 00:51:46 +00:00
2011-07-11 23:26:20 +00:00
try
{
2013-10-20 18:02:43 +00:00
aw . SetMovieParameters ( Global . Emulator . CoreComm . VsyncNum , Global . Emulator . CoreComm . VsyncDen ) ;
2013-11-27 23:35:32 +00:00
if ( _avwriterResizew > 0 & & _avwriterResizeh > 0 )
aw . SetVideoParameters ( _avwriterResizew , _avwriterResizeh ) ;
2012-11-26 02:25:23 +00:00
else
2013-10-20 18:02:43 +00:00
aw . SetVideoParameters ( Global . Emulator . VideoProvider . BufferWidth , Global . Emulator . VideoProvider . BufferHeight ) ;
2011-07-11 23:26:20 +00:00
aw . SetAudioParameters ( 44100 , 2 , 16 ) ;
2012-06-13 19:50:50 +00:00
// select codec token
// do this before save dialog because ffmpeg won't know what extension it wants until it's been configured
2012-07-23 00:33:30 +00:00
if ( unattended )
2012-05-28 01:29:43 +00:00
{
2012-07-23 00:33:30 +00:00
aw . SetDefaultVideoCodecToken ( ) ;
}
else
{
2013-11-03 16:07:58 +00:00
var token = aw . AcquireVideoCodecToken ( GlobalWin . MainForm ) ;
2012-07-23 00:33:30 +00:00
if ( token = = null )
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "A/V capture canceled." ) ;
2012-07-23 00:33:30 +00:00
aw . Dispose ( ) ;
return ;
}
aw . SetVideoCodecToken ( token ) ;
2012-05-28 01:29:43 +00:00
}
2012-06-13 19:50:50 +00:00
// select file to save to
2012-07-23 00:33:30 +00:00
if ( unattended )
2012-06-13 19:50:50 +00:00
{
2012-07-23 00:33:30 +00:00
aw . OpenFile ( filename ) ;
2012-06-13 19:50:50 +00:00
}
else
{
2012-07-23 00:33:30 +00:00
var sfd = new SaveFileDialog ( ) ;
2013-10-20 18:02:43 +00:00
if ( ! ( Global . Emulator is NullEmulator ) )
2012-07-23 00:33:30 +00:00
{
sfd . FileName = PathManager . FilesystemSafeName ( Global . Game ) ;
2013-12-13 05:20:50 +00:00
sfd . InitialDirectory = PathManager . MakeAbsolutePath ( Global . Config . PathEntries . AvPathFragment , null ) ;
2012-07-23 00:33:30 +00:00
}
else
{
sfd . FileName = "NULL" ;
2013-12-13 05:20:50 +00:00
sfd . InitialDirectory = PathManager . MakeAbsolutePath ( Global . Config . PathEntries . AvPathFragment , null ) ;
2012-07-23 00:33:30 +00:00
}
sfd . Filter = String . Format ( "{0} (*.{0})|*.{0}|All Files|*.*" , aw . DesiredExtension ( ) ) ;
2012-06-13 19:50:50 +00:00
2013-11-28 22:39:00 +00:00
var result = sfd . ShowHawkDialog ( ) ;
2012-07-23 00:33:30 +00:00
if ( result = = DialogResult . Cancel )
{
aw . Dispose ( ) ;
return ;
}
aw . OpenFile ( sfd . FileName ) ;
2012-06-13 19:50:50 +00:00
}
2011-07-11 23:26:20 +00:00
//commit the avi writing last, in case there were any errors earlier
2013-11-27 23:35:32 +00:00
_currAviWriter = aw ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "A/V capture started" ) ;
2013-04-16 00:19:31 +00:00
AVIStatusLabel . Image = Properties . Resources . AVI ;
2012-06-13 19:50:50 +00:00
AVIStatusLabel . ToolTipText = "A/V capture in progress" ;
2012-09-29 22:37:34 +00:00
AVIStatusLabel . Visible = true ;
2012-10-13 21:10:20 +00:00
2011-07-11 23:26:20 +00:00
}
catch
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "A/V capture failed!" ) ;
2011-07-11 23:26:20 +00:00
aw . Dispose ( ) ;
throw ;
}
2012-06-13 19:50:50 +00:00
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
// do sound rewire. the plan is to eventually have AVI writing support syncsound input, but it doesn't for the moment
2013-10-20 18:02:43 +00:00
if ( ! Global . Emulator . StartAsyncSound ( ) )
2013-11-27 23:35:32 +00:00
_aviSoundInput = new MetaspuAsync ( Global . Emulator . SyncSoundProvider , ESynchMethod . ESynchMethod_V ) ;
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
else
2013-11-27 23:35:32 +00:00
_aviSoundInput = Global . Emulator . SoundProvider ;
_dumpProxy = new MetaspuSoundProvider ( ESynchMethod . ESynchMethod_V ) ;
_soundRemainder = 0 ;
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
RewireSound ( ) ;
2011-07-09 21:13:18 +00:00
}
2011-07-10 00:04:33 +00:00
2013-11-03 02:51:21 +00:00
private void AbortAVI ( )
2012-10-18 20:57:53 +00:00
{
2013-11-27 23:35:32 +00:00
if ( _currAviWriter = = null )
2012-10-18 20:57:53 +00:00
{
2013-11-27 23:35:32 +00:00
_dumpProxy = null ;
2012-10-18 20:57:53 +00:00
RewireSound ( ) ;
return ;
}
2013-11-27 23:35:32 +00:00
_currAviWriter . Dispose ( ) ;
_currAviWriter = null ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "A/V capture aborted" ) ;
2013-04-16 00:19:31 +00:00
AVIStatusLabel . Image = Properties . Resources . Blank ;
2012-10-18 20:57:53 +00:00
AVIStatusLabel . ToolTipText = "" ;
AVIStatusLabel . Visible = false ;
2013-11-27 23:35:32 +00:00
_aviSoundInput = null ;
_dumpProxy = null ; // return to normal sound output
_soundRemainder = 0 ;
2012-10-18 20:57:53 +00:00
RewireSound ( ) ;
}
2013-11-03 02:51:21 +00:00
private void StopAVI ( )
2011-07-10 00:04:33 +00:00
{
2013-11-27 23:35:32 +00:00
if ( _currAviWriter = = null )
2012-05-28 01:29:43 +00:00
{
2013-11-27 23:35:32 +00:00
_dumpProxy = null ;
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
RewireSound ( ) ;
2012-05-28 01:29:43 +00:00
return ;
}
2013-11-27 23:35:32 +00:00
_currAviWriter . CloseFile ( ) ;
_currAviWriter . Dispose ( ) ;
_currAviWriter = null ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "A/V capture stopped" ) ;
2013-04-16 00:19:31 +00:00
AVIStatusLabel . Image = Properties . Resources . Blank ;
2011-07-12 00:37:24 +00:00
AVIStatusLabel . ToolTipText = "" ;
2012-09-29 22:37:34 +00:00
AVIStatusLabel . Visible = false ;
2013-11-27 23:35:32 +00:00
_aviSoundInput = null ;
_dumpProxy = null ; // return to normal sound output
_soundRemainder = 0 ;
sound api changes. added a new ISyncSoundProvider, which works similarly to ISoundProvider except the source (not the sink) determines the number of samples to process. Added facilities to metaspu, dcfilter, speexresampler to work with ISyncSoundProvider. Add ISyncSoundProvider to IEmulator. All IEmulators must provide sync sound, but they need not provide async sound. When async is needed and an IEmulator doesn't provide it, the frontend will wrap it in a vecna metaspu. SNES, GB changed to provide sync sound only. All other emulator cores mostly unchanged; they just provide stub fakesync alongside async, for now. For the moment, the only use of the sync sound is for realtime audio throttling, where it works and sounds quite nice. In the future, sync sound will be supported for AV dumping as well.
2012-10-11 00:44:59 +00:00
RewireSound ( ) ;
2011-07-10 00:04:33 +00:00
}
2011-07-31 22:29:56 +00:00
2013-11-03 02:51:21 +00:00
private void AVIFrameAdvance ( )
2012-11-26 21:08:08 +00:00
{
2013-11-23 00:51:31 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-27 23:35:32 +00:00
if ( _currAviWriter ! = null )
2012-11-26 21:08:08 +00:00
{
2013-11-27 23:35:32 +00:00
long nsampnum = 44100 * ( long ) Global . Emulator . CoreComm . VsyncDen + _soundRemainder ;
2013-10-20 18:02:43 +00:00
long nsamp = nsampnum / Global . Emulator . CoreComm . VsyncNum ;
2012-11-26 21:08:08 +00:00
// exactly remember fractional parts of an audio sample
2013-11-27 23:35:32 +00:00
_soundRemainder = nsampnum % Global . Emulator . CoreComm . VsyncNum ;
2012-11-26 21:08:08 +00:00
short [ ] temp = new short [ nsamp * 2 ] ;
2013-11-27 23:35:32 +00:00
_aviSoundInput . GetSamples ( temp ) ;
_dumpProxy . buffer . enqueue_samples ( temp , ( int ) nsamp ) ;
2012-11-26 21:08:08 +00:00
try
{
IVideoProvider output ;
2013-11-27 23:35:32 +00:00
if ( _avwriterResizew > 0 & & _avwriterResizeh > 0 )
2012-11-26 21:08:08 +00:00
{
Bitmap bmpin ;
if ( Global . Config . AVI_CaptureOSD )
bmpin = CaptureOSD ( ) ;
else
{
2013-10-20 18:02:43 +00:00
bmpin = new Bitmap ( Global . Emulator . VideoProvider . BufferWidth , Global . Emulator . VideoProvider . BufferHeight , PixelFormat . Format32bppArgb ) ;
2012-11-26 21:08:08 +00:00
var lockdata = bmpin . LockBits ( new Rectangle ( 0 , 0 , bmpin . Width , bmpin . Height ) , ImageLockMode . WriteOnly , PixelFormat . Format32bppArgb ) ;
2013-10-20 18:02:43 +00:00
System . Runtime . InteropServices . Marshal . Copy ( Global . Emulator . VideoProvider . GetVideoBuffer ( ) , 0 , lockdata . Scan0 , bmpin . Width * bmpin . Height ) ;
2012-11-26 21:08:08 +00:00
bmpin . UnlockBits ( lockdata ) ;
}
2013-11-27 23:35:32 +00:00
Bitmap bmpout = new Bitmap ( _avwriterResizew , _avwriterResizeh , PixelFormat . Format32bppArgb ) ;
2012-11-26 21:08:08 +00:00
using ( Graphics g = Graphics . FromImage ( bmpout ) )
g . DrawImage ( bmpin , new Rectangle ( 0 , 0 , bmpout . Width , bmpout . Height ) ) ;
bmpin . Dispose ( ) ;
2013-11-03 03:54:37 +00:00
output = new BmpVideoProvder ( bmpout ) ;
2012-11-26 21:08:08 +00:00
}
else
{
if ( Global . Config . AVI_CaptureOSD )
2013-11-03 03:54:37 +00:00
output = new BmpVideoProvder ( CaptureOSD ( ) ) ;
2012-11-26 21:08:08 +00:00
else
2013-10-20 18:02:43 +00:00
output = Global . Emulator . VideoProvider ;
2012-11-26 21:08:08 +00:00
}
2013-11-27 23:35:32 +00:00
_currAviWriter . AddFrame ( output ) ;
2013-11-03 03:54:37 +00:00
if ( output is BmpVideoProvder )
( output as BmpVideoProvder ) . Dispose ( ) ;
2012-11-26 21:08:08 +00:00
2013-11-27 23:35:32 +00:00
_currAviWriter . AddSamples ( temp ) ;
2012-11-26 21:08:08 +00:00
}
catch ( Exception e )
{
2013-04-16 00:19:31 +00:00
MessageBox . Show ( "Video dumping died:\n\n" + e ) ;
2012-11-26 21:08:08 +00:00
AbortAVI ( ) ;
}
2013-11-27 23:35:32 +00:00
if ( _autoDumpLength > 0 )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
_autoDumpLength - - ;
if ( _autoDumpLength = = 0 ) // finish
2013-11-03 02:51:21 +00:00
{
StopAVI ( ) ;
if ( autoCloseOnDump )
{
2013-11-27 23:35:32 +00:00
_exit = true ;
2013-11-03 02:51:21 +00:00
}
}
}
2013-11-23 00:51:31 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
}
}
#endregion
#region Scheduled for refactor
2013-12-10 17:58:12 +00:00
void ShowMessageCoreComm ( string message )
{
MessageBox . Show ( this , message , "Warning" , MessageBoxButtons . OK , MessageBoxIcon . Warning ) ;
}
2013-11-27 23:35:32 +00:00
private void NesSpeicalMenuAdd ( string name , string button , string msg ) //TODO: don't do this, put these into the menu but hide them in the dropdownopened event as needed
2013-11-03 02:51:21 +00:00
{
NESSpecialControlsMenuItem . Visible = true ;
NESSpecialControlsMenuItem . DropDownItems . Add ( name , null , delegate
{
if ( Global . Emulator . ControllerDefinition . BoolButtons . Contains ( button ) )
{
if ( ! Global . MovieSession . Movie . IsPlaying | | Global . MovieSession . Movie . IsFinished )
{
Global . ClickyVirtualPadController . Click ( button ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( msg ) ;
2013-11-03 02:51:21 +00:00
}
}
} ) ;
}
2013-11-27 23:35:32 +00:00
private void NesSpecialMenuControls ( ) //Ditto
2013-11-03 02:51:21 +00:00
{
// ugly and hacky
NESSpecialControlsMenuItem . Visible = false ;
NESSpecialControlsMenuItem . DropDownItems . Clear ( ) ;
var ss = Global . Emulator . ControllerDefinition . BoolButtons ;
if ( ss . Contains ( "FDS Eject" ) )
2013-11-27 23:35:32 +00:00
{
NesSpeicalMenuAdd ( "Eject Disk" , "FDS Eject" , "FDS Disk Ejected." ) ;
}
2013-11-03 02:51:21 +00:00
for ( int i = 0 ; i < 16 ; i + + )
{
2013-11-27 23:35:32 +00:00
var s = "FDS Insert " + i ;
2013-11-03 02:51:21 +00:00
if ( ss . Contains ( s ) )
2013-11-27 23:35:32 +00:00
{
NesSpeicalMenuAdd ( "Insert Disk " + i , s , "FDS Disk " + i + " inserted." ) ;
}
2013-11-03 02:51:21 +00:00
}
if ( ss . Contains ( "VS Coin 1" ) )
2013-11-27 23:35:32 +00:00
{
NesSpeicalMenuAdd ( "Insert Coin 1" , "VS Coin 1" , "Coin 1 inserted." ) ;
}
2013-11-03 02:51:21 +00:00
if ( ss . Contains ( "VS Coin 2" ) )
2013-11-27 23:35:32 +00:00
{
NesSpeicalMenuAdd ( "Insert Coin 2" , "VS Coin 2" , "Coin 2 inserted." ) ;
}
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
private static void RewireInputChain ( ) //Move to Client.Common
2013-11-03 02:51:21 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . ControllerInputCoalescer = new ControllerInputCoalescer { Type = Global . ActiveController . Type } ;
2013-11-03 02:51:21 +00:00
2013-11-03 16:47:21 +00:00
Global . OrControllerAdapter . Source = Global . ActiveController ;
Global . OrControllerAdapter . SourceOr = Global . AutoFireController ;
Global . UD_LR_ControllerAdapter . Source = Global . OrControllerAdapter ;
2013-11-03 02:51:21 +00:00
2013-11-03 16:47:21 +00:00
Global . StickyXORAdapter . Source = Global . UD_LR_ControllerAdapter ;
Global . AutofireStickyXORAdapter . Source = Global . StickyXORAdapter ;
2013-11-03 02:51:21 +00:00
2013-11-03 16:47:21 +00:00
Global . MultitrackRewiringControllerAdapter . Source = Global . AutofireStickyXORAdapter ;
2013-11-03 02:51:21 +00:00
Global . ForceOffAdaptor . Source = Global . MultitrackRewiringControllerAdapter ;
Global . MovieInputSourceAdapter . Source = Global . ForceOffAdaptor ;
Global . ControllerOutput . Source = Global . MovieOutputHardpoint ;
Global . Emulator . Controller = Global . ControllerOutput ;
Global . MovieSession . MovieControllerAdapter . Type = Global . MovieInputSourceAdapter . Type ;
//connect the movie session before MovieOutputHardpoint if it is doing anything
//otherwise connect the MovieInputSourceAdapter to it, effectively bypassing the movie session
if ( Global . MovieSession . Movie ! = null )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
Global . MovieOutputHardpoint . Source = Global . MovieSession . MovieControllerAdapter ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
else
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
Global . MovieOutputHardpoint . Source = Global . MovieInputSourceAdapter ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
private static void SyncControls ( ) //Move to client.comon
2013-11-03 02:51:21 +00:00
{
var def = Global . Emulator . ControllerDefinition ;
Global . ActiveController = BindToDefinition ( def , Global . Config . AllTrollers , Global . Config . AllTrollersAnalog ) ;
Global . AutoFireController = BindToDefinitionAF ( def , Global . Config . AllTrollersAutoFire ) ;
// allow propogating controls that are in the current controller definition but not in the prebaked one
// these two lines shouldn't be required anymore under the new system?
Global . ActiveController . ForceType ( new ControllerDefinition ( Global . Emulator . ControllerDefinition ) ) ;
Global . ClickyVirtualPadController . Type = new ControllerDefinition ( Global . Emulator . ControllerDefinition ) ;
RewireInputChain ( ) ;
}
public bool LoadRom ( string path , bool deterministicemulation = false , bool hasmovie = false ) //Move to client.common
{
if ( path = = null ) return false ;
using ( var file = new HawkFile ( ) )
{
2013-11-27 23:35:32 +00:00
var romExtensions = new [ ] { "SMS" , "SMC" , "SFC" , "PCE" , "SGX" , "GG" , "SG" , "BIN" , "GEN" , "MD" , "SMD" , "GB" , "NES" , "FDS" , "ROM" , "INT" , "GBC" , "UNF" , "A78" , "CRT" , "COL" , "XML" , "Z64" , "V64" , "N64" } ;
2013-11-03 02:51:21 +00:00
//lets not use this unless we need to
//file.NonArchiveExtensions = romExtensions;
file . Open ( path ) ;
//if the provided file doesnt even exist, give up!
if ( ! file . Exists ) return false ;
//try binding normal rom extensions first
if ( ! file . IsBound )
file . BindSoleItemOf ( romExtensions ) ;
//if we have an archive and need to bind something, then pop the dialog
if ( file . IsArchive & & ! file . IsBound )
{
var ac = new ArchiveChooser ( file ) ;
if ( ac . ShowDialog ( this ) = = DialogResult . OK )
{
file . BindArchiveMember ( ac . SelectedMemberIndex ) ;
}
else return false ;
}
IEmulator nextEmulator = null ;
RomGame rom = null ;
GameInfo game = null ;
2013-12-10 17:58:12 +00:00
var nextComm = new CoreComm ( ShowMessageCoreComm ) ;
2013-11-03 02:51:21 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( nextComm ) ;
try
{
string ext = file . Extension . ToLower ( ) ;
if ( ext = = ".iso" | | ext = = ".cue" )
{
2013-11-27 23:35:32 +00:00
Disc disc = ext = = ".iso" ? Disc . FromIsoPath ( path ) : Disc . FromCuePath ( path , new CueBinPrefs ( ) ) ;
2013-11-03 02:51:21 +00:00
var hash = disc . GetHash ( ) ;
game = Database . CheckDatabase ( hash ) ;
if ( game = = null )
{
// try to use our wizard methods
game = new GameInfo { Name = Path . GetFileNameWithoutExtension ( file . Name ) , Hash = hash } ;
switch ( disc . DetectDiscType ( ) )
{
case DiscType . SegaSaturn :
game . System = "SAT" ;
break ;
case DiscType . SonyPSP :
game . System = "PSP" ;
break ;
case DiscType . SonyPSX :
game . System = "PSX" ;
break ;
2013-12-16 19:00:05 +00:00
case DiscType . MegaCD :
game . System = "GEN" ;
break ;
2013-11-03 02:51:21 +00:00
case DiscType . TurboCD :
case DiscType . UnknownCDFS :
case DiscType . UnknownFormat :
2013-12-16 19:00:05 +00:00
default : // PCECD was bizhawk's first CD core,
// and during that time, all CDs were blindly sent to it
// so this prevents regressions
2013-11-03 02:51:21 +00:00
game . System = "PCECD" ;
break ;
}
}
switch ( game . System )
{
2013-12-16 19:00:05 +00:00
case "GEN" :
{
var genesis = new BizHawk . Emulation . Cores . Consoles . Sega . gpgx . GPGX (
nextComm , null , disc , "GEN" , true , Emulation . Cores . Consoles . Sega . gpgx . GPGX . ControlType . Normal ) ;
nextEmulator = genesis ;
}
break ;
2013-11-03 02:51:21 +00:00
case "SAT" :
{
2013-12-10 17:58:12 +00:00
var saturn = new Yabause ( nextComm , disc , Global . Config . SaturnUseGL ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = saturn ;
SaturnSetPrefs ( saturn ) ;
}
break ;
case "PSP" :
{
2013-11-13 23:36:21 +00:00
var psp = new PSP ( nextComm , file . Name ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = psp ;
}
break ;
case "PSX" :
{
2013-11-13 23:36:21 +00:00
var psx = new Octoshock ( nextComm ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = psx ;
psx . LoadCuePath ( file . CanonicalFullPath ) ;
nextEmulator . CoreComm . RomStatusDetails = "PSX etc." ;
}
break ;
case "PCE" :
case "PCECD" :
{
2013-11-27 23:35:32 +00:00
var biosPath = Global . FirmwareManager . Request ( "PCECD" , "Bios" ) ;
2013-11-03 02:51:21 +00:00
if ( File . Exists ( biosPath ) = = false )
{
MessageBox . Show ( "PCE-CD System Card not found. Please check the BIOS path in Config->Paths->PC Engine." ) ;
return false ;
}
rom = new RomGame ( new HawkFile ( biosPath ) ) ;
2012-11-26 21:08:08 +00:00
2013-11-03 02:51:21 +00:00
if ( rom . GameInfo . Status = = RomStatus . BadDump )
MessageBox . Show ( "The PCE-CD System Card you have selected is known to be a bad dump. This may cause problems playing PCE-CD games.\n\n" +
"It is recommended that you find a good dump of the system card. Sorry to be the bearer of bad news!" ) ;
2012-11-26 21:08:08 +00:00
2013-11-03 02:51:21 +00:00
else if ( rom . GameInfo . NotInDatabase )
MessageBox . Show ( "The PCE-CD System Card you have selected is not recognized in our database. That might mean it's a bad dump, or isn't the correct rom." ) ;
2011-07-31 22:29:56 +00:00
2013-11-03 02:51:21 +00:00
else if ( rom . GameInfo [ "BIOS" ] = = false )
MessageBox . Show ( "The PCE-CD System Card you have selected is not a BIOS image. You may have selected the wrong rom." ) ;
2011-07-31 22:29:56 +00:00
2013-11-03 02:51:21 +00:00
if ( rom . GameInfo [ "SuperSysCard" ] )
game . AddOption ( "SuperSysCard" ) ;
if ( ( game [ "NeedSuperSysCard" ] ) & & game [ "SuperSysCard" ] = = false )
MessageBox . Show ( "This game requires a version 3.0 System card and won't run with the system card you've selected. Try selecting a 3.0 System Card in Config->Paths->PC Engine." ) ;
2011-07-31 23:25:00 +00:00
2013-11-03 02:51:21 +00:00
if ( Global . Config . PceSpriteLimit ) game . AddOption ( "ForceSpriteLimit" ) ;
if ( Global . Config . PceEqualizeVolume ) game . AddOption ( "EqualizeVolumes" ) ;
if ( Global . Config . PceArcadeCardRewindHack ) game . AddOption ( "ArcadeRewindHack" ) ;
2011-09-24 23:12:43 +00:00
2013-11-03 02:51:21 +00:00
game . FirmwareHash = Util . BytesToHexString ( System . Security . Cryptography . SHA1 . Create ( ) . ComputeHash ( rom . RomData ) ) ;
2012-01-10 01:30:17 +00:00
2013-11-03 02:51:21 +00:00
nextEmulator = new PCEngine ( nextComm , game , disc , rom . RomData ) ;
break ;
}
}
}
else if ( file . Extension . ToLower ( ) = = ".xml" )
{
try
{
var XMLG = XmlGame . Create ( file ) ; // if load fails, are we supposed to retry as a bsnes XML????????
game = XMLG . GI ;
2012-01-22 22:42:40 +00:00
2013-11-03 02:51:21 +00:00
switch ( game . System )
{
case "DGB" :
2012-10-02 21:28:14 +00:00
2013-11-03 02:51:21 +00:00
var L = Database . GetGameInfo ( XMLG . Assets [ "LeftRom" ] , "left.gb" ) ;
var R = Database . GetGameInfo ( XMLG . Assets [ "RightRom" ] , "right.gb" ) ;
2012-10-02 21:28:14 +00:00
2013-11-03 02:51:21 +00:00
if ( Global . Config . GB_ForceDMG ) L . AddOption ( "ForceDMG" ) ;
if ( Global . Config . GB_GBACGB ) L . AddOption ( "GBACGB" ) ;
if ( Global . Config . GB_MulticartCompat ) L . AddOption ( "MulitcartCompat" ) ;
if ( Global . Config . GB_ForceDMG ) R . AddOption ( "ForceDMG" ) ;
if ( Global . Config . GB_GBACGB ) R . AddOption ( "GBACGB" ) ;
if ( Global . Config . GB_MulticartCompat ) R . AddOption ( "MulitcartCompat" ) ;
2012-10-02 21:28:14 +00:00
2013-11-27 23:35:32 +00:00
var gbl = new GambatteLink ( nextComm , L , XMLG . Assets [ "LeftRom" ] , R , XMLG . Assets [ "RightRom" ] ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = gbl ;
// other stuff todo
break ;
2012-09-22 01:06:18 +00:00
2013-11-03 02:51:21 +00:00
default :
return false ;
}
}
catch ( Exception ex )
{
2013-11-27 23:35:32 +00:00
MessageBox . Show ( ex . ToString ( ) , "XMLGame Load Error" ) ;
2013-11-03 02:51:21 +00:00
}
}
else // most extensions
{
rom = new RomGame ( file ) ;
game = rom . GameInfo ;
2012-10-02 21:28:14 +00:00
2013-11-03 02:51:21 +00:00
bool isXml = false ;
2012-09-22 01:06:18 +00:00
2013-11-03 02:51:21 +00:00
// other xml has already been handled
if ( file . Extension . ToLower ( ) = = ".xml" )
{
game . System = "SNES" ;
isXml = true ;
}
2012-09-22 01:06:18 +00:00
2013-11-03 02:51:21 +00:00
switch ( game . System )
{
case "SNES" :
{
game . System = "SNES" ;
nextComm . SNES_ExePath = SNES_Prepare ( Global . Config . SNESProfile ) ;
2012-09-27 17:53:00 +00:00
2013-12-10 18:16:39 +00:00
// need to get rid of this hack at some point
2013-11-03 02:51:21 +00:00
( ( CoreFileProvider ) nextComm . CoreFileProvider ) . SubfileDirectory = Path . GetDirectoryName ( path . Replace ( "|" , "" ) ) ; //Dirty hack to get around archive filenames (since we are just getting the directory path, it is safe to mangle the filename
2012-09-22 01:06:18 +00:00
2013-12-10 17:58:12 +00:00
var snes = new LibsnesCore ( nextComm ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = snes ;
byte [ ] romData = isXml ? null : rom . FileData ;
byte [ ] xmlData = isXml ? rom . FileData : null ;
2013-12-10 17:58:12 +00:00
snes . Load ( game , romData , deterministicemulation , xmlData ) ;
2013-11-03 02:51:21 +00:00
}
break ;
case "SMS" :
case "SG" :
if ( Global . Config . SmsEnableFM ) game . AddOption ( "UseFM" ) ;
if ( Global . Config . SmsAllowOverlock ) game . AddOption ( "AllowOverclock" ) ;
if ( Global . Config . SmsForceStereoSeparation ) game . AddOption ( "ForceStereo" ) ;
if ( Global . Config . SmsSpriteLimit ) game . AddOption ( "SpriteLimit" ) ;
nextEmulator = new SMS ( nextComm , game , rom . RomData ) ;
break ;
case "GG" :
if ( Global . Config . SmsAllowOverlock ) game . AddOption ( "AllowOverclock" ) ;
if ( Global . Config . SmsSpriteLimit ) game . AddOption ( "SpriteLimit" ) ;
nextEmulator = new SMS ( nextComm , game , rom . RomData ) ;
break ;
case "A26" :
nextEmulator = new Atari2600 ( nextComm , game , rom . FileData ) ;
( ( Atari2600 ) nextEmulator ) . SetBw ( Global . Config . Atari2600_BW ) ;
( ( Atari2600 ) nextEmulator ) . SetP0Diff ( Global . Config . Atari2600_LeftDifficulty ) ;
( ( Atari2600 ) nextEmulator ) . SetP1Diff ( Global . Config . Atari2600_RightDifficulty ) ;
break ;
case "PCE" :
case "PCECD" :
case "SGX" :
if ( Global . Config . PceSpriteLimit ) game . AddOption ( "ForceSpriteLimit" ) ;
nextEmulator = new PCEngine ( nextComm , game , rom . RomData ) ;
break ;
case "GEN" :
2013-12-15 20:51:57 +00:00
{
//nextEmulator = new Genesis(nextComm, game, rom.RomData);
2013-12-16 18:04:45 +00:00
nextEmulator = new BizHawk . Emulation . Cores . Consoles . Sega . gpgx . GPGX ( nextComm , rom . RomData , null , "GEN" , true , Emulation . Cores . Consoles . Sega . gpgx . GPGX . ControlType . Normal ) ;
2013-12-15 20:51:57 +00:00
break ;
}
2013-11-03 02:51:21 +00:00
case "TI83" :
nextEmulator = new TI83 ( nextComm , game , rom . RomData ) ;
if ( Global . Config . TI83autoloadKeyPad )
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Load < TI83KeyPad > ( ) ;
2013-11-03 02:51:21 +00:00
}
break ;
case "NES" :
{
2013-12-10 17:58:12 +00:00
var nes = new NES ( nextComm , game , rom . FileData , Global . MovieSession . Movie . Header . BoardProperties )
2013-11-03 02:51:21 +00:00
{
NTSC_FirstDrawLine = Global . Config . NTSC_NESTopLine ,
NTSC_LastDrawLine = Global . Config . NTSC_NESBottomLine ,
PAL_FirstDrawLine = Global . Config . PAL_NESTopLine
} ;
nes . NTSC_LastDrawLine = Global . Config . PAL_NESBottomLine ;
nes . SetClipLeftAndRight ( Global . Config . NESClipLeftAndRight ) ;
nextEmulator = nes ;
if ( Global . Config . NESAutoLoadPalette & & Global . Config . NESPaletteFile . Length > 0 & &
HawkFile . ExistsAt ( Global . Config . NESPaletteFile ) )
{
nes . SetPalette (
NES . Palettes . Load_FCEUX_Palette ( HawkFile . ReadAllBytes ( Global . Config . NESPaletteFile ) ) ) ;
}
}
break ;
case "GB" :
case "GBC" :
if ( ! Global . Config . GB_AsSGB )
{
if ( Global . Config . GB_ForceDMG ) game . AddOption ( "ForceDMG" ) ;
if ( Global . Config . GB_GBACGB ) game . AddOption ( "GBACGB" ) ;
if ( Global . Config . GB_MulticartCompat ) game . AddOption ( "MulitcartCompat" ) ;
2013-11-27 23:35:32 +00:00
var gb = new Gameboy ( nextComm , game , rom . FileData ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = gb ;
if ( gb . IsCGBMode ( ) )
{
gb . SetCGBColors ( Global . Config . CGBColors ) ;
}
else
{
try
{
2013-11-27 23:35:32 +00:00
using ( var f = new StreamReader ( Global . Config . GB_PaletteFile ) )
2013-11-03 02:51:21 +00:00
{
2013-11-09 00:27:07 +00:00
int [ ] colors = ColorChooserForm . LoadPalFile ( f ) ;
2013-11-03 02:51:21 +00:00
if ( colors ! = null )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
gb . ChangeDMGColors ( colors ) ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
}
}
catch { }
}
}
else
{
try
{
game . System = "SNES" ;
game . AddOption ( "SGB" ) ;
nextComm . SNES_ExePath = SNES_Prepare ( Global . Config . SNESProfile ) ;
2013-12-10 17:58:12 +00:00
var snes = new LibsnesCore ( nextComm ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = snes ;
2013-12-10 17:58:12 +00:00
snes . Load ( game , rom . FileData , deterministicemulation , null ) ;
2013-12-09 20:36:24 +00:00
}
catch
{
// failed to load SGB bios. to avoid catch-22, disable SGB mode
2013-12-10 17:58:12 +00:00
ShowMessageCoreComm ( "Failed to load a GB rom in SGB mode. Disabling SGB Mode." ) ;
2013-12-09 20:36:24 +00:00
Global . Config . GB_AsSGB = false ;
throw ;
2013-11-03 02:51:21 +00:00
}
}
break ;
case "Coleco" :
{
2013-12-10 18:16:39 +00:00
var c = new ColecoVision ( nextComm , game , rom . RomData , Global . Config . ColecoSkipBiosIntro ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = c ;
}
break ;
case "INTV" :
{
2013-11-27 23:35:32 +00:00
var intv = new Intellivision ( nextComm , game , rom . RomData ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = intv ;
}
break ;
case "A78" :
2013-11-27 23:35:32 +00:00
var gamedbpath = Path . Combine ( PathManager . GetExeDirectoryAbsolute ( ) , "gamedb" , "EMU7800.csv" ) ;
2013-12-10 17:58:12 +00:00
var a78 = new Atari7800 ( nextComm , game , rom . RomData , gamedbpath ) ;
2013-12-09 20:36:24 +00:00
nextEmulator = a78 ;
2013-11-03 02:51:21 +00:00
break ;
case "C64" :
C64 c64 = new C64 ( nextComm , game , rom . RomData , rom . Extension ) ;
c64 . HardReset ( ) ;
nextEmulator = c64 ;
break ;
case "GBA" :
2013-11-10 02:32:47 +00:00
if ( VersionInfo . INTERIM )
2013-11-03 02:51:21 +00:00
{
GBA gba = new GBA ( nextComm ) ;
//var gba = new GarboDev.GbaManager(nextComm);
2013-12-10 17:58:12 +00:00
gba . Load ( rom . RomData ) ;
2013-11-03 02:51:21 +00:00
nextEmulator = gba ;
}
break ;
case "N64" :
Global . Game = game ;
2013-11-27 23:35:32 +00:00
var video_settings = N64GenerateVideoSettings ( game , hasmovie ) ;
2013-11-03 02:51:21 +00:00
int SaveType = 0 ;
if ( game . OptionValue ( "SaveType" ) = = "EEPROM_16K" )
{
SaveType = 1 ;
}
nextEmulator = new N64 ( nextComm , game , rom . RomData , video_settings , SaveType ) ;
break ;
2013-12-10 23:12:09 +00:00
case "DEBUG" :
if ( VersionInfo . INTERIM )
{
nextEmulator = LibRetroEmulator . CreateDebug ( nextComm , rom . RomData ) ;
}
break ;
2013-11-03 02:51:21 +00:00
}
}
2012-06-10 02:19:36 +00:00
2013-11-03 02:51:21 +00:00
if ( nextEmulator = = null )
throw new Exception ( "No core could load the rom." ) ;
}
catch ( Exception ex )
{
MessageBox . Show ( "Exception during loadgame:\n\n" + ex ) ;
return false ;
}
2012-07-12 21:39:11 +00:00
2013-11-03 02:51:21 +00:00
CloseGame ( ) ;
Global . Emulator . Dispose ( ) ;
Global . Emulator = nextEmulator ;
Global . CoreComm = nextComm ;
Global . Game = game ;
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
SyncControls ( ) ;
2012-07-12 23:13:22 +00:00
2013-11-03 02:51:21 +00:00
if ( nextEmulator is LibsnesCore )
{
var snes = nextEmulator as LibsnesCore ;
snes . SetPalette ( ( SnesColors . ColorType ) Enum . Parse ( typeof ( SnesColors . ColorType ) , Global . Config . SNESPalette , false ) ) ;
}
2012-09-12 22:18:51 +00:00
2013-11-03 02:51:21 +00:00
if ( game . System = = "NES" )
{
NES nes = Global . Emulator as NES ;
if ( nes . GameName ! = null )
Global . Game . Name = nes . GameName ;
Global . Game . Status = nes . RomStatus ;
2013-11-27 23:35:32 +00:00
SetNesSoundChannels ( ) ;
2013-11-03 02:51:21 +00:00
}
2012-09-29 23:03:51 +00:00
2013-11-03 02:51:21 +00:00
Text = DisplayNameForSystem ( game . System ) + " - " + game . Name ;
ResetRewindBuffer ( ) ;
2012-09-30 00:53:08 +00:00
2013-12-16 19:00:05 +00:00
if ( Global . Emulator . CoreComm . RomStatusDetails = = null & & rom ! = null )
2013-11-03 02:51:21 +00:00
{
Global . Emulator . CoreComm . RomStatusDetails =
string . Format ( "{0}\r\nSHA1:{1}\r\nMD5:{2}\r\n" ,
game . Name ,
Util . BytesToHexString ( System . Security . Cryptography . SHA1 . Create ( ) . ComputeHash ( rom . RomData ) ) ,
Util . BytesToHexString ( System . Security . Cryptography . MD5 . Create ( ) . ComputeHash ( rom . RomData ) ) ) ;
}
2012-10-28 23:38:41 +00:00
2013-11-03 02:51:21 +00:00
if ( Global . Emulator . BoardName ! = null )
2012-11-26 01:28:14 +00:00
{
2013-11-03 02:51:21 +00:00
Console . WriteLine ( "Core reported BoardID: \"{0}\"" , Global . Emulator . BoardName ) ;
2012-11-26 01:28:14 +00:00
}
2013-11-03 02:51:21 +00:00
//restarts the lua console if a different rom is loaded.
//im not really a fan of how this is done..
if ( Global . Config . RecentRoms . Empty | | Global . Config . RecentRoms [ 0 ] ! = file . CanonicalFullPath )
2012-11-26 01:28:14 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Restart < LuaConsole > ( ) ;
2012-11-26 01:28:14 +00:00
}
2012-11-26 23:16:31 +00:00
2013-11-03 02:51:21 +00:00
Global . Config . RecentRoms . Add ( file . CanonicalFullPath ) ;
2013-12-13 04:57:14 +00:00
JumpLists . AddRecentItem ( file . CanonicalFullPath ) ;
2013-11-03 02:51:21 +00:00
if ( File . Exists ( PathManager . SaveRamPath ( game ) ) )
{
LoadSaveRam ( ) ;
}
if ( Global . Config . AutoSavestates )
{
LoadState ( "Auto" ) ;
}
2012-12-25 20:36:04 +00:00
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . Restart ( ) ;
2013-11-03 02:51:21 +00:00
Cheats_Restart ( ) ;
2013-03-10 23:03:52 +00:00
2013-11-03 02:51:21 +00:00
if ( Global . Config . LoadCheatFileByGame )
{
if ( Global . CheatList . AttemptToLoadCheatFile ( ) )
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Cheats file loaded" ) ;
2013-11-03 02:51:21 +00:00
}
}
2013-07-27 01:03:15 +00:00
2013-11-03 02:51:21 +00:00
CurrentlyOpenRom = file . CanonicalFullPath ;
HandlePlatformMenus ( ) ;
2013-11-27 23:35:32 +00:00
_stateSlots . Clear ( ) ;
2013-11-03 02:51:21 +00:00
UpdateStatusSlots ( ) ;
UpdateDumpIcon ( ) ;
2013-10-11 16:32:36 +00:00
2013-11-03 02:51:21 +00:00
CaptureRewindState ( ) ;
2013-10-27 07:54:00 +00:00
2013-11-03 02:51:21 +00:00
Global . StickyXORAdapter . ClearStickies ( ) ;
Global . StickyXORAdapter . ClearStickyFloats ( ) ;
2013-11-03 16:47:21 +00:00
Global . AutofireStickyXORAdapter . ClearStickies ( ) ;
2013-10-27 07:54:00 +00:00
2013-11-03 02:51:21 +00:00
RewireSound ( ) ;
2013-10-27 07:54:00 +00:00
2013-11-03 02:51:21 +00:00
return true ;
2013-10-27 07:54:00 +00:00
}
}
2013-11-03 02:51:21 +00:00
public void SaveState ( string name ) //Move to client.common
2013-10-27 07:54:00 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Global . Emulator is NullEmulator )
2013-10-27 07:54:00 +00:00
{
2013-11-03 02:51:21 +00:00
return ;
2013-10-27 07:54:00 +00:00
}
2013-11-27 23:35:32 +00:00
var path = PathManager . SaveStatePrefix ( Global . Game ) + "." + name + ".State" ;
2013-10-27 15:23:41 +00:00
2013-11-03 02:51:21 +00:00
var file = new FileInfo ( path ) ;
if ( file . Directory ! = null & & file . Directory . Exists = = false )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
file . Directory . Create ( ) ;
2013-11-27 23:35:32 +00:00
}
2013-10-27 15:23:41 +00:00
2013-11-03 02:51:21 +00:00
//Make backup first
if ( Global . Config . BackupSavestates & & file . Exists )
2013-10-27 15:23:41 +00:00
{
2013-11-27 23:35:32 +00:00
var backup = path + ".bak" ;
2013-11-03 02:51:21 +00:00
var backupFile = new FileInfo ( backup ) ;
if ( backupFile . Exists )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
backupFile . Delete ( ) ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
file . CopyTo ( backup ) ;
2013-10-27 15:23:41 +00:00
}
2013-11-03 02:51:21 +00:00
SaveStateFile ( path , name , false ) ;
2013-11-03 16:07:58 +00:00
if ( GlobalWin . Tools . Has < LuaConsole > ( ) )
2013-10-27 15:23:41 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . LuaConsole . LuaImp . CallSaveStateEvent ( name ) ;
2013-10-27 15:23:41 +00:00
}
}
2013-11-03 02:51:21 +00:00
public void SaveStateFile ( string filename , string name , bool fromLua ) //Move to client.common
2013-10-27 15:23:41 +00:00
{
2013-11-03 02:51:21 +00:00
SavestateManager . SaveStateFile ( filename , name ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Saved state: " + name ) ;
2013-11-03 02:51:21 +00:00
if ( ! fromLua )
2013-10-27 15:23:41 +00:00
{
2013-11-03 02:51:21 +00:00
UpdateStatusSlots ( ) ;
2013-10-27 15:23:41 +00:00
}
}
2013-11-03 02:51:21 +00:00
public void LoadStateFile ( string path , string name , bool fromLua = false ) //Move to client.commo
2013-10-27 15:23:41 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
if ( SavestateManager . LoadStateFile ( path , name ) )
2013-10-27 15:23:41 +00:00
{
2013-11-03 02:51:21 +00:00
SetMainformMovieInfo ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . ClearGUIText ( ) ;
2013-11-27 23:35:32 +00:00
GlobalWin . Tools . UpdateToolsBefore ( fromLua ) ;
2013-11-03 02:51:21 +00:00
UpdateToolsAfter ( fromLua ) ;
UpdateToolsLoadstate ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Loaded state: " + name ) ;
2013-11-03 02:51:21 +00:00
2013-11-03 16:07:58 +00:00
if ( GlobalWin . Tools . Has < LuaConsole > ( ) )
2013-10-27 15:23:41 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . LuaConsole . LuaImp . CallLoadStateEvent ( name ) ;
2013-10-27 15:23:41 +00:00
}
}
2013-11-03 02:51:21 +00:00
else
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Loadstate error!" ) ;
2013-11-03 02:51:21 +00:00
}
2013-10-27 15:23:41 +00:00
}
2013-11-03 02:51:21 +00:00
public void LoadState ( string name , bool fromLua = false ) //Move to client.commo
2013-10-27 15:23:41 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Global . Emulator is NullEmulator )
2013-10-27 15:23:41 +00:00
{
2013-11-03 02:51:21 +00:00
return ;
2013-10-27 15:23:41 +00:00
}
2013-11-03 02:51:21 +00:00
string path = PathManager . SaveStatePrefix ( Global . Game ) + "." + name + ".State" ;
if ( File . Exists ( path ) = = false )
2013-10-27 15:23:41 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "Unable to load " + name + ".State" ) ;
2013-11-03 02:51:21 +00:00
return ;
2013-10-27 15:23:41 +00:00
}
2013-11-03 02:51:21 +00:00
LoadStateFile ( path , name , fromLua ) ;
2013-10-27 15:23:41 +00:00
}
2013-11-03 02:51:21 +00:00
//whats the difference between these two methods??
//its very tricky. rename to be more clear or combine them.
2013-11-27 23:35:32 +00:00
private void CloseGame ( bool clearSram = false )
2013-10-27 15:23:41 +00:00
{
2013-11-03 02:51:21 +00:00
if ( Global . Config . AutoSavestates & & Global . Emulator is NullEmulator = = false )
2013-10-27 15:23:41 +00:00
{
2013-11-03 02:51:21 +00:00
SaveState ( "Auto" ) ;
2013-10-27 15:23:41 +00:00
}
2013-11-27 23:35:32 +00:00
if ( clearSram )
2013-10-27 15:23:41 +00:00
{
2013-11-27 23:35:32 +00:00
var path = PathManager . SaveRamPath ( Global . Game ) ;
2013-11-03 02:51:21 +00:00
if ( File . Exists ( path ) )
2013-10-27 15:23:41 +00:00
{
2013-11-03 02:51:21 +00:00
File . Delete ( path ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( "SRAM cleared." ) ;
2013-10-27 15:23:41 +00:00
}
}
2013-11-03 02:51:21 +00:00
else if ( Global . Emulator . SaveRamModified )
{
SaveRam ( ) ;
}
StopAVI ( ) ;
Global . Emulator . Dispose ( ) ;
2013-12-10 17:58:12 +00:00
Global . CoreComm = new CoreComm ( ShowMessageCoreComm ) ;
2013-11-03 02:51:21 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
Global . Emulator = new NullEmulator ( Global . CoreComm ) ;
Global . ActiveController = Global . NullControls ;
Global . AutoFireController = Global . AutofireNullControls ;
2013-12-14 06:58:09 +00:00
// adelikat: TODO: Ugly hack! But I don't know a way around this yet.
if ( ! ( Global . MovieSession . Movie is TasMovie ) )
{
Global . MovieSession . Movie . Stop ( ) ;
}
2013-11-03 02:51:21 +00:00
RebootStatusBarIcon . Visible = false ;
2013-10-27 15:23:41 +00:00
}
2013-11-27 23:35:32 +00:00
public void CloseRom ( bool clearSram = false )
2013-10-27 15:23:41 +00:00
{
2013-11-05 16:37:05 +00:00
if ( GlobalWin . Tools . AskSave ( ) )
{
2013-11-27 23:35:32 +00:00
CloseGame ( clearSram ) ;
2013-12-10 17:58:12 +00:00
Global . CoreComm = new CoreComm ( ShowMessageCoreComm ) ;
2013-11-05 16:37:05 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
Global . Emulator = new NullEmulator ( Global . CoreComm ) ;
Global . Game = GameInfo . GetNullGame ( ) ;
2013-11-03 02:51:21 +00:00
2013-11-05 16:37:05 +00:00
GlobalWin . Tools . Restart ( ) ;
2013-11-03 02:51:21 +00:00
2013-11-05 16:37:05 +00:00
RewireSound ( ) ;
ResetRewindBuffer ( ) ;
Cheats_Restart ( ) ;
2013-11-10 02:32:47 +00:00
Text = "BizHawk" + ( VersionInfo . INTERIM ? " (interim) " : String . Empty ) ;
2013-11-05 16:37:05 +00:00
HandlePlatformMenus ( ) ;
2013-11-27 23:35:32 +00:00
_stateSlots . Clear ( ) ;
2013-11-05 16:37:05 +00:00
UpdateDumpIcon ( ) ;
}
2013-10-27 15:23:41 +00:00
}
2013-11-01 15:47:37 +00:00
2013-11-03 02:51:21 +00:00
private void SwapBackupSavestate ( string path ) //Move inside Saveslot Manager
2013-11-01 15:47:37 +00:00
{
2013-11-03 02:51:21 +00:00
//Takes the .state and .bak files and swaps them
var state = new FileInfo ( path ) ;
var backup = new FileInfo ( path + ".bak" ) ;
var temp = new FileInfo ( path + ".bak.tmp" ) ;
if ( state . Exists = = false ) return ;
if ( backup . Exists = = false ) return ;
if ( temp . Exists ) temp . Delete ( ) ;
backup . CopyTo ( path + ".bak.tmp" ) ;
backup . Delete ( ) ;
state . CopyTo ( path + ".bak" ) ;
state . Delete ( ) ;
temp . CopyTo ( path ) ;
temp . Delete ( ) ;
2013-11-27 23:35:32 +00:00
_stateSlots . ToggleRedo ( Global . Config . SaveSlot ) ;
2013-11-01 15:47:37 +00:00
}
2013-11-01 18:52:26 +00:00
2013-11-27 23:35:32 +00:00
private static void ProcessMovieImport ( string fn ) //Nothing Winform Specific here, move to Movie import
2013-11-01 18:52:26 +00:00
{
2013-12-13 05:20:50 +00:00
var d = PathManager . MakeAbsolutePath ( Global . Config . PathEntries . MoviesPathFragment , null ) ;
2013-11-03 02:51:21 +00:00
string errorMsg ;
string warningMsg ;
2013-11-27 23:35:32 +00:00
var m = MovieImport . ImportFile ( fn , out errorMsg , out warningMsg ) ;
if ( ! String . IsNullOrWhiteSpace ( errorMsg ) )
{
2013-11-03 02:51:21 +00:00
MessageBox . Show ( errorMsg , "Conversion error" , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
2013-11-27 23:35:32 +00:00
}
if ( ! String . IsNullOrWhiteSpace ( warningMsg ) )
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( warningMsg ) ;
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
else
2013-11-27 23:35:32 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . AddMessage ( Path . GetFileName ( fn ) + " imported as " + "Movies\\" +
2013-11-27 23:35:32 +00:00
Path . GetFileName ( fn ) + "." + Global . Config . MovieExtension ) ;
}
2013-11-03 02:51:21 +00:00
if ( ! Directory . Exists ( d ) )
2013-11-27 23:35:32 +00:00
{
2013-11-03 02:51:21 +00:00
Directory . CreateDirectory ( d ) ;
2013-11-27 23:35:32 +00:00
}
2013-11-01 18:52:26 +00:00
2013-11-27 23:35:32 +00:00
var outPath = Path . Combine ( d , ( Path . GetFileName ( fn ) + "." + Global . Config . MovieExtension ) ) ;
2013-11-23 18:18:58 +00:00
m . SaveAs ( outPath ) ;
2013-11-03 02:51:21 +00:00
}
#endregion
2013-12-02 18:35:15 +00:00
2011-02-20 08:40:22 +00:00
}
2012-03-09 12:10:41 +00:00
}