2011-02-20 08:40:22 +00:00
using System ;
2014-04-14 16:48:45 +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 ;
2014-05-31 14:29:27 +00:00
2013-11-03 23:45:44 +00:00
using BizHawk.Client.Common ;
2013-12-20 22:05:56 +00:00
using BizHawk.Common ;
2013-11-04 01:06:36 +00:00
using BizHawk.Emulation.Common ;
2014-05-31 14:29:27 +00:00
using BizHawk.Emulation.Common.IEmulatorExtensions ;
2014-04-20 16:19:08 +00:00
using BizHawk.Emulation.Cores.Atari.Atari2600 ;
2014-04-25 21:55:56 +00:00
using BizHawk.Emulation.Cores.Atari.Atari7800 ;
2013-12-20 22:05:56 +00:00
using BizHawk.Emulation.Cores.Calculators ;
2014-04-25 01:19:57 +00:00
using BizHawk.Emulation.Cores.Consoles.Nintendo.QuickNES ;
2014-04-13 22:08:46 +00:00
using BizHawk.Emulation.Cores.Consoles.Sega.gpgx ;
2013-11-13 23:36:21 +00:00
using BizHawk.Emulation.Cores.Nintendo.Gameboy ;
using BizHawk.Emulation.Cores.Nintendo.GBA ;
2013-12-20 22:05:56 +00:00
using BizHawk.Emulation.Cores.Nintendo.NES ;
using BizHawk.Emulation.Cores.Nintendo.SNES ;
using BizHawk.Emulation.Cores.PCEngine ;
2014-04-13 19:44:08 +00:00
using BizHawk.Emulation.Cores.Sega.MasterSystem ;
2014-04-25 21:41:34 +00:00
using BizHawk.Emulation.Cores.Sega.Saturn ;
2014-04-25 22:50:28 +00:00
using BizHawk.Emulation.Cores.Sony.PSP ;
2013-12-20 22:05:56 +00:00
using BizHawk.Emulation.DiscSystem ;
2014-05-17 20:02:10 +00:00
using BizHawk.Emulation.Cores.Nintendo.N64 ;
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
{
2014-05-12 20:51:09 +00:00
Text = "BizHawk" + ( VersionInfo . INTERIM ? " (interim) " : string . Empty ) ;
2013-10-25 00:57:23 +00:00
2014-02-17 09:20:08 +00:00
Global . CheatList . Changed + = ToolHelpers . UpdateCheatRelatedTools ;
// Hide Status bar icons and general statusbar prep
2013-11-03 02:51:21 +00:00
PlayRecordStatusButton . Visible = false ;
AVIStatusLabel . Visible = false ;
SetPauseStatusbarIcon ( ) ;
2013-12-21 16:42:36 +00:00
ToolHelpers . UpdateCheatRelatedTools ( null , null ) ;
2013-11-03 02:51:21 +00:00
RebootStatusBarIcon . Visible = false ;
2014-02-17 09:20:08 +00:00
StatusBarDiskLightOnImage = Properties . Resources . LightOn ;
StatusBarDiskLightOffImage = Properties . Resources . LightOff ;
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 ( )
{
2013-12-20 22:05:56 +00:00
// If this isnt here, then our assemblyresolving hacks wont work due to the check for MainForm.INTERIM
// its.. weird. dont ask.
2013-01-02 18:52:11 +00:00
}
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 ;
2014-05-04 14:10:28 +00:00
Global . Rewinder = new Rewinder
2013-12-27 01:14:17 +00:00
{
MessageCallback = GlobalWin . OSD . AddMessage
} ;
2013-12-24 21:37:51 +00:00
Global . ControllerInputCoalescer = new ControllerInputCoalescer ( ) ;
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-12-27 16:23:12 +00:00
2013-12-29 23:35:42 +00:00
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 )
{
2014-05-06 01:27:56 +00:00
LogConsole . 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 ;
2014-01-01 03:03:10 +00:00
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
2013-12-20 22:05:56 +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-12-20 22:05:56 +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 ( ) ) ;
2013-12-20 22:05:56 +00:00
}
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
2014-01-27 00:02:21 +00:00
//TODO GL - a lot of disorganized wiring-up here
2014-01-27 06:03:18 +00:00
GlobalWin . PresentationPanel = new PresentationPanel ( ) ;
2014-01-28 04:39:27 +00:00
GlobalWin . DisplayManager = new DisplayManager ( GlobalWin . PresentationPanel ) ;
2014-01-27 06:03:18 +00:00
Controls . Add ( GlobalWin . PresentationPanel ) ;
Controls . SetChildIndex ( GlobalWin . PresentationPanel , 0 ) ;
2011-01-11 02:55:51 +00:00
2014-01-27 00:02:21 +00:00
//TODO GL - move these event handlers somewhere less obnoxious line in the On* overrides
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-12-20 22:05:56 +00:00
if ( GlobalWin . Sound ! = null )
{
GlobalWin . Sound . StopSound ( ) ;
}
2011-02-20 08:40:22 +00:00
} ;
ResizeEnd + = ( o , e ) = >
{
2014-01-27 06:03:18 +00:00
if ( GlobalWin . PresentationPanel ! = null )
2013-12-20 22:05:56 +00:00
{
2014-01-27 06:03:18 +00:00
GlobalWin . PresentationPanel . Resized = true ;
2013-12-20 22:05:56 +00:00
}
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 ( ) ;
2014-03-18 03:03:53 +00:00
Global . CoreComm = new CoreComm ( ShowMessageCoreComm , NotifyCoreComm ) ;
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 ( ) ;
2013-12-24 21:59:41 +00:00
InputManager . RewireInputChain ( ) ;
2013-11-03 16:07:58 +00:00
GlobalWin . Tools = new ToolManager ( ) ;
2013-12-18 19:36:17 +00:00
RewireSound ( ) ;
2013-12-20 22:05:56 +00:00
// TODO - replace this with some kind of standard dictionary-yielding parser in a separate component
2011-02-05 21:00:59 +00:00
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
{
2013-12-20 22:05:56 +00:00
// For some reason sometimes visual studio will pass this to us on the commandline. it makes no sense.
2011-06-06 21:08:38 +00:00
if ( args [ i ] = = ">" )
{
i + + ;
2013-12-20 22:05:56 +00:00
var stdout = args [ i ] ;
2011-06-06 21:08:38 +00:00
Console . SetOut ( new StreamWriter ( stdout ) ) ;
continue ;
}
2013-12-20 22:05:56 +00:00
var 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
{
2014-01-10 16:54:53 +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 )
{
2013-12-20 22:05:56 +00:00
// 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 )
{
2014-04-06 20:46:23 +00:00
LoadRomFromRecent ( Global . Config . RecentRoms . MostRecent ) ;
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 ;
2013-12-20 22:05:56 +00:00
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-12-20 22:05:56 +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
{
2014-04-06 20:46:23 +00:00
StartNewMovie ( new Movie ( Global . Config . RecentMovies . MostRecent ) , 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
{
2013-12-30 16:49:13 +00:00
LoadQuickSave ( "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-12-30 16:49:13 +00:00
LoadQuickSave ( "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
{
2014-01-31 22:58:41 +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
2014-01-07 00:56:50 +00:00
if ( Global . Config . NESGGAutoload & & Global . Emulator . SystemId = = "NES" )
2013-09-07 03:15:29 +00:00
{
2013-12-22 23:34:22 +00:00
GlobalWin . Tools . 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
{
2013-12-29 23:35:42 +00:00
GlobalWin . Tools . Load < TAStudio > ( ) ;
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
2014-04-13 19:44:08 +00:00
if ( Global . Config . SmsVdpAutoLoad & & Global . Emulator is SMS )
{
GlobalWin . Tools . Load < SmsVDPViewer > ( ) ;
}
2013-10-20 18:02:43 +00:00
if ( Global . Config . PCEBGViewerAutoload & & Global . Emulator is PCEngine )
2013-09-07 03:15:29 +00:00
{
2014-01-31 23:42:06 +00:00
GlobalWin . Tools . Load < PceBgViewer > ( ) ;
2013-09-07 03:15:29 +00:00
}
2013-12-12 21:05:09 +00:00
2014-04-13 20:33:01 +00:00
if ( Global . Config . PceVdpAutoLoad & & Global . Emulator is PCEngine )
{
GlobalWin . Tools . Load < PCETileViewer > ( ) ;
}
2014-04-13 01:05:23 +00:00
if ( Global . Config . RecentPceCdlFiles . AutoLoad & & Global . Emulator is PCEngine )
{
GlobalWin . Tools . Load < PCECDL > ( ) ;
}
2014-04-13 22:08:46 +00:00
if ( Global . Config . GenVdpAutoLoad & & Global . Emulator is GPGX )
{
GlobalWin . Tools . Load < GenVDPViewer > ( ) ;
}
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-12-22 23:34:22 +00:00
GlobalWin . Tools . LoadTraceLogger ( ) ;
2012-09-30 13:38:37 +00:00
}
2011-02-20 08:40:22 +00:00
2014-04-20 16:19:08 +00:00
if ( Global . Config . Atari2600DebuggerAutoload & & Global . Emulator is Atari2600 )
{
GlobalWin . Tools . Load < Atari2600Debugger > ( ) ;
}
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
2012-07-23 00:33:30 +00:00
// start dumping, if appropriate
if ( cmdDumpType ! = null & & cmdDumpName ! = null )
{
2014-01-10 16:54:53 +00:00
RecordAv ( cmdDumpType , cmdDumpName ) ;
2012-07-23 00:33:30 +00:00
}
2012-10-10 22:52:11 +00:00
UpdateStatusSlots ( ) ;
2013-10-12 15:40:20 +00:00
2014-01-27 06:03:18 +00:00
//TODO POOP
GlobalWin . PresentationPanel . Control . 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 ( ) ;
2014-01-01 03:03:10 +00:00
for ( ; ; )
2011-02-20 08:40:22 +00:00
{
2011-07-09 22:09:39 +00:00
Input . Instance . Update ( ) ;
2013-12-20 22:05:56 +00:00
// handle events and dispatch as a hotkey action, or a hotkey button, or an input button
2011-07-10 07:39:40 +00:00
ProcessInput ( ) ;
2013-11-03 16:47:21 +00:00
Global . ClientControls . LatchFromPhysical ( GlobalWin . HotkeyCoalescer ) ;
2014-05-17 19:35:47 +00:00
2013-12-24 21:37:51 +00:00
Global . ActiveController . LatchFromPhysical ( Global . ControllerInputCoalescer ) ;
2012-09-15 13:11:29 +00:00
2014-05-17 20:02:10 +00:00
Global . ActiveController . ApplyAxisConstraints (
( Global . Emulator is N64 & & Global . Config . N64UseCircularAnalogConstraint ) ? "Natural Circle" : null ) ;
2014-05-17 19:35:47 +00:00
2013-11-01 22:56:55 +00:00
Global . ActiveController . OR_FromLogical ( Global . ClickyVirtualPadController ) ;
2014-03-29 21:12:04 +00:00
Global . ActiveController . Overrides ( Global . LuaAndAdaptor ) ;
2013-12-24 21:37:51 +00:00
Global . AutoFireController . LatchFromPhysical ( Global . 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
2014-04-28 00:39:40 +00:00
if ( Global . Config . DisplayInput ) // Input display wants to update even while paused
{
GlobalWin . DisplayManager . NeedsToPaint = true ;
}
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-12-20 22:05:56 +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
}
2013-12-20 22:05:56 +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
{
2014-04-26 21:55:04 +00:00
//NOTE: this gets called twice sometimes. once by using() in Program.cs and once from winforms internals when the form is closed...
2013-12-20 22:05:56 +00:00
if ( GlobalWin . DisplayManager ! = null )
{
GlobalWin . DisplayManager . Dispose ( ) ;
2014-04-26 21:55:04 +00:00
GlobalWin . DisplayManager = null ;
2013-12-20 22:05:56 +00:00
}
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-12-20 22:05:56 +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 `
2014-01-01 03:03:10 +00:00
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 EmulatorPaused { get ; private set ; }
2011-02-20 08:40:22 +00:00
2014-06-01 02:11:02 +00:00
// TODO: SystemInfo should be able to do this
2014-04-14 16:48:45 +00:00
// Because we don't have enough places where we list SystemID's
public Dictionary < string , string > SupportedPlatforms
{
get
{
var released = new Dictionary < string , string >
{
{ "A26" , "Atari 2600" } ,
{ "A78" , "Atari 7800" } ,
{ "NES" , "Nintendo Entertainment System/Famicom" } ,
{ "SNES" , "Super Nintendo" } ,
{ "N64" , "Nintendo 64" } ,
{ "GB" , "Game Boy" } ,
{ "GBC" , "Game Boy Color" } ,
{ "SMS" , "Sega Master System" } ,
{ "GG" , "Sega Game Gear" } ,
{ "SG" , "SG-1000" } ,
{ "GEN" , "Sega Genesis/Megadrive" } ,
{ "SAT" , "Sega Saturn" } ,
{ "PCE" , "PC Engine/TurboGrafx 16" } ,
{ "Coleco" , "Colecovision" } ,
2014-06-01 02:11:02 +00:00
{ "TI83" , "TI-83 Calculator" } ,
{ "WSWAN" , "WonderSwan" }
2014-04-14 16:48:45 +00:00
} ;
if ( VersionInfo . INTERIM )
{
released . Add ( "GBA" , "Gameboy Advance" ) ;
released . Add ( "C64" , "Commodore 64" ) ;
}
return released ;
}
}
2013-11-03 02:51:21 +00:00
#endregion
#region Public Methods
2014-01-21 00:36:22 +00:00
public void ClearHolds ( )
{
Global . StickyXORAdapter . ClearStickies ( ) ;
Global . AutofireStickyXORAdapter . ClearStickies ( ) ;
if ( GlobalWin . Tools . Has < VirtualPadForm > ( ) )
{
GlobalWin . Tools . VirtualPad . ClearVirtualPadHolds ( ) ;
}
}
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-12-20 22:05:56 +00:00
// the main form gets input
if ( ActiveForm = = this )
{
return true ;
}
2013-11-03 02:51:21 +00:00
2013-12-20 22:05:56 +00:00
// modals that need to capture input for binding purposes get input, of course
if ( ActiveForm is HotkeyConfig | |
ActiveForm is ControllerConfig | |
ActiveForm is TAStudio | |
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 ;
}
2013-11-03 02:51:21 +00:00
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-12-24 21:37:51 +00:00
ControllerInputCoalescer conInput = Global . ControllerInputCoalescer as ControllerInputCoalescer ;
2013-11-03 02:51:21 +00:00
for ( ; ; )
{
2014-01-01 03:03:10 +00:00
2013-12-20 22:05:56 +00:00
// loop through all available events
2013-11-03 02:51:21 +00:00
var ie = Input . Instance . DequeueEvent ( ) ;
if ( ie = = null ) { break ; }
2013-12-20 22:05:56 +00:00
// useful debugging:
// Console.WriteLine(ie);
2013-11-03 02:51:21 +00:00
2013-12-20 22:05:56 +00:00
// TODO - wonder what happens if we pop up something interactive as a response to one of these hotkeys? may need to purge further processing
2013-11-03 02:51:21 +00:00
2013-12-20 22:05:56 +00:00
// 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 )
{
2013-12-20 22:05:56 +00:00
// Maybe it is a system alt-key which hasnt been overridden
2013-11-03 02:51:21 +00:00
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-12-20 22:05:56 +00:00
if ( ( c > = 'a' & & c < = 'z' ) | | c = = ' ' )
2013-11-03 02:51:21 +00:00
{
SendAltKeyChar ( c ) ;
}
}
if ( ie . LogicalButton . Alt & & ie . LogicalButton . Button = = "Space" )
{
SendPlainAltKey ( 32 ) ;
}
}
2013-12-20 22:05:56 +00:00
// 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.
2013-11-03 02:51:21 +00:00
}
2013-12-20 22:05:56 +00:00
// 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
2013-11-03 02:51:21 +00:00
2013-12-20 22:05:56 +00:00
// 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
2013-11-03 02:51:21 +00:00
bool handled ;
switch ( Global . Config . Input_Hotkey_OverrideOptions )
{
default :
2013-12-20 22:05:56 +00:00
case 0 : // Both allowed
2013-12-24 21:37:51 +00:00
conInput . 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 ) ) ;
}
2013-12-20 22:05:56 +00:00
// hotkeys which arent handled as actions get coalesced as pollable virtual client buttons
2013-11-03 02:51:21 +00:00
if ( ! handled )
{
2013-11-03 16:07:58 +00:00
GlobalWin . HotkeyCoalescer . Receive ( ie ) ;
2013-11-03 02:51:21 +00:00
}
2013-12-20 22:05:56 +00:00
2013-11-03 02:51:21 +00:00
break ;
2013-12-20 22:05:56 +00:00
case 1 : // Input overrides Hokeys
2013-12-24 21:37:51 +00:00
conInput . Receive ( ie ) ;
2013-12-20 22:05:56 +00:00
if ( ! Global . ActiveController . HasBinding ( ie . LogicalButton . ToString ( ) ) )
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 ) ) ;
}
2013-12-20 22:05:56 +00:00
// hotkeys which arent handled as actions get coalesced as pollable virtual client buttons
2013-11-03 02:51:21 +00:00
if ( ! handled )
{
2013-11-03 16:07:58 +00:00
GlobalWin . HotkeyCoalescer . Receive ( ie ) ;
2013-11-03 02:51:21 +00:00
}
}
break ;
2013-12-20 22:05:56 +00:00
case 2 : // Hotkeys override Input
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 ) ) ;
}
2013-12-20 22:05:56 +00:00
// hotkeys which arent handled as actions get coalesced as pollable virtual client buttons
2013-11-03 02:51:21 +00:00
if ( ! handled )
{
2013-11-03 16:07:58 +00:00
GlobalWin . HotkeyCoalescer . Receive ( ie ) ;
2013-12-24 21:37:51 +00:00
conInput . Receive ( ie ) ;
2013-11-03 02:51:21 +00:00
}
2013-12-20 22:05:56 +00:00
2013-11-03 02:51:21 +00:00
break ;
}
2013-12-20 22:05:56 +00:00
} // foreach event
2013-11-03 02:51:21 +00:00
// also handle floats
2014-04-16 01:47:37 +00:00
conInput . AcceptNewFloats ( Input . Instance . GetFloats ( ) . Select ( o = >
2014-05-04 14:10:28 +00:00
{
// hackish
if ( o . Item1 = = "WMouse X" )
2014-04-16 01:47:37 +00:00
{
2014-05-04 14:10:28 +00:00
var P = GlobalWin . DisplayManager . UntransformPoint ( new System . Drawing . Point ( ( int ) o . Item2 , 0 ) ) ;
float x = P . X / ( float ) Global . Emulator . VideoProvider . BufferWidth ;
return new Tuple < string , float > ( "WMouse X" , x * 20000 - 10000 ) ;
}
if ( o . Item1 = = "WMouse Y" )
{
var P = GlobalWin . DisplayManager . UntransformPoint ( new System . Drawing . Point ( 0 , ( int ) o . Item2 ) ) ;
float y = P . Y / ( float ) Global . Emulator . VideoProvider . BufferHeight ;
return new Tuple < string , float > ( "WMouse Y" , y * 20000 - 10000 ) ;
}
return o ;
} ) ) ;
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 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-12-20 22:05:56 +00:00
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-12-20 22:05:56 +00:00
TakeScreenshot (
String . Format ( PathManager . ScreenshotPrefix ( Global . Game ) + ".{0:yyyy-MM-dd HH.mm.ss}.png" , DateTime . Now )
) ;
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 )
2013-12-20 22:05:56 +00:00
{
2013-11-03 02:51:21 +00:00
fi . Directory . Create ( ) ;
2013-12-20 22:05:56 +00:00
}
2013-11-03 02:51:21 +00:00
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-12-20 22:05:56 +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-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 ;
2014-01-27 06:03:18 +00:00
int borderWidth = Size . Width - GlobalWin . PresentationPanel . Control . Size . Width ;
int borderHeight = Size . Height - GlobalWin . PresentationPanel . Control . Size . Height ;
2013-11-03 02:51:21 +00:00
// start at target zoom and work way down until we find acceptable zoom
2014-05-17 03:50:19 +00:00
Size lastComputedSize = new Size ( 1 , 1 ) ;
2013-11-03 02:51:21 +00:00
for ( ; zoom > = 1 ; zoom - - )
2013-07-14 01:48:05 +00:00
{
2014-05-17 03:50:19 +00:00
lastComputedSize = GlobalWin . DisplayManager . CalculateClientSize ( video , zoom ) ;
if ( ( ( ( lastComputedSize . Width ) + borderWidth ) < area . Width )
& & ( ( ( lastComputedSize . Height ) + borderHeight ) < area . Height ) )
2013-12-20 22:05:56 +00:00
{
2013-11-03 02:51:21 +00:00
break ;
2013-12-20 22:05:56 +00:00
}
2013-07-14 01:48:05 +00:00
}
2013-11-03 02:51:21 +00:00
// Change size
2014-05-17 03:50:19 +00:00
Size = new Size ( ( lastComputedSize . Width ) + borderWidth , ( ( lastComputedSize . Height ) + borderHeight ) ) ;
2013-11-03 02:51:21 +00:00
PerformLayout ( ) ;
2014-01-27 06:03:18 +00:00
GlobalWin . PresentationPanel . 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
2013-12-20 22:05:56 +00:00
{
2013-11-03 02:51:21 +00:00
Location = new Point ( area . Right - Size . Width , Location . Y ) ;
2013-12-20 22:05:56 +00:00
}
2013-11-03 02:51:21 +00:00
if ( Bounds . Bottom > area . Bottom ) // Window is off the bottom edge
2013-12-20 22:05:56 +00:00
{
2013-11-03 02:51:21 +00:00
Location = new Point ( Location . X , area . Bottom - Size . Height ) ;
2013-12-20 22:05:56 +00:00
}
2013-07-24 02:14:25 +00:00
}
}
2013-07-14 01:48:05 +00:00
}
2013-07-24 02:14:25 +00:00
2014-05-06 01:27:56 +00:00
public bool IsInFullscreen
{
get { return _inFullscreen ; }
}
2014-05-17 02:55:58 +00:00
public void ToggleFullscreen ( bool allowSuppress = false )
2013-07-14 01:48:05 +00:00
{
2014-05-17 02:55:58 +00:00
//prohibit this operation if the current controls include LMouse
if ( allowSuppress )
{
if ( Global . ActiveController . HasBinding ( "WMouse L" ) )
return ;
}
2013-11-27 23:35:32 +00:00
if ( _inFullscreen = = false )
2013-07-14 01:48:05 +00:00
{
2014-02-04 21:06:00 +00:00
SuspendLayout ( ) ;
2014-02-04 00:41:24 +00:00
#if WINDOWS
//Work around an AMD driver bug in >= vista:
//It seems windows will activate opengl fullscreen mode when a GL control is occupying the exact space of a screen (0,0 and dimensions=screensize)
//AMD cards manifest a problem under these circumstances, flickering other monitors.
//It isnt clear whether nvidia cards are failing to employ this optimization, or just not flickering.
//(this could be determined with more work; other side affects of the fullscreen mode include: corrupted taskbar, no modal boxes on top of GL control, no screenshots)
2014-02-04 21:06:00 +00:00
//At any rate, we can solve this by adding a 1px black border around the GL control
2014-02-04 00:41:24 +00:00
//Please note: It is important to do this before resizing things, otherwise momentarily a GL control without WS_BORDER will be at the magic dimensions and cause the flakeout
2014-02-04 21:06:00 +00:00
Padding = new System . Windows . Forms . Padding ( 1 ) ;
BackColor = Color . Black ;
2014-02-04 00:41:24 +00:00
#endif
2014-01-10 16:54:53 +00:00
_windowedLocation = Location ;
2013-11-03 02:51:21 +00:00
FormBorderStyle = FormBorderStyle . None ;
WindowState = FormWindowState . Maximized ;
2013-12-20 22:05:56 +00:00
MainMenuStrip . Visible = Global . Config . ShowMenuInFullscreen ;
2013-11-03 02:51:21 +00:00
MainStatusBar . Visible = false ;
2014-02-04 21:06:00 +00:00
ResumeLayout ( ) ;
2014-02-04 00:41:24 +00:00
2014-01-27 06:03:18 +00:00
GlobalWin . PresentationPanel . Resized = true ;
2013-11-27 23:35:32 +00:00
_inFullscreen = true ;
2013-11-03 02:51:21 +00:00
}
else
{
2014-02-04 21:06:00 +00:00
SuspendLayout ( ) ;
2013-11-03 02:51:21 +00:00
FormBorderStyle = FormBorderStyle . Sizable ;
WindowState = FormWindowState . Normal ;
2014-02-04 01:37:43 +00:00
#if WINDOWS
2014-02-04 21:06:00 +00:00
Padding = new System . Windows . Forms . Padding ( 0 ) ;
2014-02-22 21:54:42 +00:00
//it's important that we set the form color back to this, because the statusbar icons blend onto the mainform, not onto the statusbar--
//so we need the statusbar and mainform backdrop color to match
BackColor = SystemColors . Control ;
2014-02-04 01:37:43 +00:00
#endif
2013-11-03 02:51:21 +00:00
MainMenuStrip . Visible = true ;
MainStatusBar . Visible = Global . Config . DisplayStatusBar ;
2014-01-10 16:54:53 +00:00
Location = _windowedLocation ;
2014-02-04 21:06:00 +00:00
ResumeLayout ( ) ;
2014-02-04 00:41:24 +00:00
2013-11-03 02:51:21 +00:00
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 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 ;
}
2013-07-14 01:48:05 +00:00
2013-11-03 02:51:21 +00:00
public void ClickSpeedItem ( int num )
{
2013-12-20 22:05:56 +00:00
if ( ( ModifierKeys & Keys . Control ) ! = 0 )
{
SetSpeedPercentAlternate ( num ) ;
}
else
{
SetSpeedPercent ( num ) ;
}
2013-11-03 02:51:21 +00:00
}
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
{
2014-05-12 20:51:09 +00:00
CheatStatusButton . ToolTipText = string . Empty ;
2013-11-03 02:51:21 +00:00
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-12-27 17:59:19 +00:00
var s = ( LibsnesCore . SnesSettings ) Global . Emulator . GetSettings ( ) ;
2013-11-27 23:35:32 +00:00
if ( setto . HasValue )
2011-01-20 06:24:31 +00:00
{
2013-12-27 17:59:19 +00:00
s . ShowBG1_1 = s . ShowBG1_0 = setto . Value ;
2013-11-27 23:35:32 +00:00
}
else
{
2013-12-27 17:59:19 +00:00
s . ShowBG1_1 = s . ShowBG1_0 ^ = true ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
2013-12-27 17:59:19 +00:00
Global . Emulator . PutSettings ( s ) ;
GlobalWin . OSD . AddMessage ( s . 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-12-27 17:59:19 +00:00
var s = ( LibsnesCore . SnesSettings ) Global . Emulator . GetSettings ( ) ;
2013-11-27 23:35:32 +00:00
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
s . ShowBG2_1 = s . ShowBG2_0 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
2013-12-27 17:59:19 +00:00
s . ShowBG2_1 = s . ShowBG2_0 ^ = true ;
2013-11-27 23:35:32 +00:00
}
2013-12-20 22:05:56 +00:00
2013-12-27 17:59:19 +00:00
Global . Emulator . PutSettings ( s ) ;
GlobalWin . OSD . AddMessage ( s . 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-12-27 17:59:19 +00:00
var s = ( LibsnesCore . SnesSettings ) Global . Emulator . GetSettings ( ) ;
2013-11-27 23:35:32 +00:00
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
s . ShowBG3_1 = s . ShowBG3_0 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
2013-12-27 17:59:19 +00:00
s . ShowBG3_1 = s . ShowBG3_0 ^ = true ;
2013-11-27 23:35:32 +00:00
}
2013-12-20 22:05:56 +00:00
2013-12-27 17:59:19 +00:00
Global . Emulator . PutSettings ( s ) ;
GlobalWin . OSD . AddMessage ( s . 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-12-27 17:59:19 +00:00
var s = ( LibsnesCore . SnesSettings ) Global . Emulator . GetSettings ( ) ;
2013-11-27 23:35:32 +00:00
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
s . ShowBG4_1 = s . ShowBG4_0 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
2013-12-27 17:59:19 +00:00
s . ShowBG4_1 = s . ShowBG4_0 ^ = true ;
2013-11-27 23:35:32 +00:00
}
2013-12-20 22:05:56 +00:00
2013-12-27 17:59:19 +00:00
Global . Emulator . PutSettings ( s ) ;
GlobalWin . OSD . AddMessage ( s . 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-12-29 23:35:42 +00:00
public void SNES_ToggleObj1 ( bool? setto = null )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
var s = ( LibsnesCore . SnesSettings ) Global . Emulator . GetSettings ( ) ;
2013-11-27 23:35:32 +00:00
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
s . ShowOBJ_0 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
2013-12-27 17:59:19 +00:00
s . ShowOBJ_0 ^ = true ;
2013-11-27 23:35:32 +00:00
}
2013-12-20 22:05:56 +00:00
2013-12-27 17:59:19 +00:00
Global . Emulator . PutSettings ( s ) ;
GlobalWin . OSD . AddMessage ( s . ShowOBJ_0 ? "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-12-29 23:35:42 +00:00
public void SNES_ToggleObj2 ( bool? setto = null )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
var s = ( LibsnesCore . SnesSettings ) Global . Emulator . GetSettings ( ) ;
2013-11-27 23:35:32 +00:00
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
s . ShowOBJ_1 = setto . Value ;
2013-11-27 23:35:32 +00:00
}
else
{
2013-12-27 17:59:19 +00:00
s . ShowOBJ_1 ^ = true ;
2013-11-03 02:51:21 +00:00
}
2013-12-27 17:59:19 +00:00
Global . Emulator . PutSettings ( s ) ;
GlobalWin . OSD . AddMessage ( s . ShowOBJ_1 ? "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-12-27 17:59:19 +00:00
var s = ( LibsnesCore . SnesSettings ) Global . Emulator . GetSettings ( ) ;
2013-11-27 23:35:32 +00:00
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
s . ShowOBJ_2 = setto . Value ;
2013-11-27 23:35:32 +00:00
}
else
{
2013-12-27 17:59:19 +00:00
s . ShowOBJ_2 ^ = true ;
2013-11-03 02:51:21 +00:00
}
2013-12-20 22:05:56 +00:00
2013-12-27 17:59:19 +00:00
Global . Emulator . PutSettings ( s ) ;
GlobalWin . OSD . AddMessage ( s . ShowOBJ_2 ? "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-12-27 17:59:19 +00:00
var s = ( LibsnesCore . SnesSettings ) Global . Emulator . GetSettings ( ) ;
2013-11-27 23:35:32 +00:00
if ( setto . HasValue )
2013-11-03 02:51:21 +00:00
{
2013-12-27 17:59:19 +00:00
s . ShowOBJ_3 = setto . Value ;
2013-11-03 02:51:21 +00:00
}
2013-11-27 23:35:32 +00:00
else
{
2013-12-27 17:59:19 +00:00
s . ShowOBJ_3 ^ = true ;
2013-11-27 23:35:32 +00:00
}
2013-12-20 22:05:56 +00:00
2013-12-27 17:59:19 +00:00
Global . Emulator . PutSettings ( s ) ;
GlobalWin . OSD . AddMessage ( s . ShowOBJ_3 ? "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
2014-05-18 02:11:17 +00:00
private Size _lastVideoSize = new Size ( - 1 , - 1 ) , _lastVirtualSize = new Size ( - 1 , - 1 ) ;
2013-11-27 23:35:32 +00:00
private readonly SaveSlotManager _stateSlots = new SaveSlotManager ( ) ;
2011-08-30 04:02:52 +00:00
2013-12-20 22:05:56 +00:00
// AVI/WAV state
2013-11-27 23:35:32 +00:00
private IVideoWriter _currAviWriter ;
private ISoundProvider _aviSoundInput ;
2013-12-20 22:05:56 +00:00
private MetaspuSoundProvider _dumpProxy ; // an audio proxy used for dumping
private long _soundRemainder ; // audio timekeeping for video dumping
2013-11-27 23:35:32 +00:00
private int _avwriterResizew ;
private int _avwriterResizeh ;
2014-02-07 02:28:07 +00:00
private bool _avwriterpad ;
2013-12-29 23:35:42 +00:00
2013-11-27 23:35:32 +00:00
private bool _exit ;
private bool _runloopFrameProgress ;
2013-12-20 22:05:56 +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-12-20 22:05:56 +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-12-29 23:35:42 +00:00
private Point _windowedLocation ;
2012-10-05 21:04:46 +00:00
2013-11-27 23:35:32 +00:00
private int _autoDumpLength ;
2013-12-29 23:35:42 +00:00
private readonly bool _autoCloseOnDump ;
2013-11-27 23:35:32 +00:00
private int _lastOpenRomFilter ;
2013-04-27 02:02:37 +00:00
2014-02-17 09:20:08 +00:00
// Resources
Bitmap StatusBarDiskLightOnImage , StatusBarDiskLightOffImage ;
2013-04-27 02:02:37 +00:00
2013-12-29 23:35:42 +00:00
private object _syncSettingsHack ;
2013-12-27 16:23:12 +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-12-20 22:05:56 +00:00
2014-01-21 00:36:22 +00:00
private void ClearAutohold ( )
{
ClearHolds ( ) ;
GlobalWin . OSD . AddMessage ( "Autohold keys cleared" ) ;
}
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
2014-04-15 22:10:39 +00:00
public void UpdateDumpIcon ( )
2011-07-10 15:36:41 +00:00
{
2013-10-27 15:53:37 +00:00
DumpStatusButton . Image = Properties . Resources . Blank ;
2013-12-20 22:05:56 +00:00
DumpStatusButton . ToolTipText = string . Empty ;
2011-07-10 21:00:28 +00:00
2013-12-20 22:05:56 +00:00
if ( Global . Emulator = = null )
{
return ;
}
else 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-12-20 22:05:56 +00:00
2013-10-20 18:02:43 +00:00
if ( ! string . IsNullOrEmpty ( Global . Emulator . CoreComm . RomStatusAnnotation ) )
2013-12-20 22:05:56 +00:00
{
2013-10-20 18:02:43 +00:00
annotation = Global . Emulator . CoreComm . RomStatusAnnotation ;
2013-12-20 22:05:56 +00:00
}
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-12-20 22:05:56 +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 ;
2013-12-20 22:05:56 +00:00
2012-11-24 02:25:47 +00:00
// 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
{
2014-02-06 22:08:01 +00:00
var oldram = Global . Emulator . ReadSaveRam ( ) ;
if ( oldram = = null )
{
2014-05-18 17:18:26 +00:00
// we're eating this one now. the possible negative consequence is that a user could lose
// their saveram and not know why
// MessageBox.Show("Error: tried to load saveram, but core would not accept it?");
2014-02-06 22:08:01 +00:00
return ;
}
sram = new byte [ oldram . Length ] ;
2013-12-20 22:05:56 +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 ) ;
2013-12-20 22:05:56 +00:00
}
2012-11-24 02:25:47 +00:00
}
2013-12-20 22:05:56 +00:00
2013-10-20 18:02:43 +00:00
Global . Emulator . StoreSaveRam ( sram ) ;
2011-08-09 00:51:46 +00:00
}
2013-12-20 22:05:56 +00:00
catch ( IOException )
{
2013-12-29 23:35:42 +00:00
GlobalWin . OSD . AddMessage ( "An error occurred while loading Sram" ) ;
2013-12-20 22:05:56 +00:00
}
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
2013-12-20 22:05:56 +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
}
2013-12-20 22:05:56 +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 ) ) ;
2013-10-20 18:02:43 +00:00
var saveram = Global . Emulator . ReadSaveRam ( ) ;
2012-09-14 22:28:38 +00:00
2013-12-20 22:05:56 +00:00
writer . Write ( saveram , 0 , saveram . Length ) ;
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
2013-12-29 23:35:42 +00:00
GlobalWin . Sound . SetAsyncInputPin (
! Global . Emulator . StartAsyncSound ( )
? new MetaspuAsync ( Global . Emulator . SyncSoundProvider , ESynchMethod . ESynchMethod_V )
: Global . Emulator . SoundProvider ) ;
2011-07-24 23:14:16 +00:00
}
}
2013-11-03 02:51:21 +00:00
private void HandlePlatformMenus ( )
2012-09-15 13:11:29 +00:00
{
2014-05-04 13:57:58 +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 ;
2013-12-23 16:58:20 +00:00
DGBSubMenu . Visible = false ;
2013-12-24 01:06:17 +00:00
GenesisSubMenu . Visible = false ;
2014-05-30 22:31:16 +00:00
wonderSwanToolStripMenuItem . 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-11-03 02:51:21 +00:00
case "GEN" :
2013-12-24 01:06:17 +00:00
GenesisSubMenu . 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 ;
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" :
2013-12-24 01:06:17 +00:00
SMSSubMenu . Text = "&SMS" ;
2013-11-03 02:51:21 +00:00
SMSSubMenu . Visible = true ;
break ;
case "SG" :
2013-12-24 01:06:17 +00:00
SMSSubMenu . Text = "&SG" ;
2013-11-03 02:51:21 +00:00
SMSSubMenu . Visible = true ;
break ;
case "GG" :
2013-12-24 01:06:17 +00:00
SMSSubMenu . Text = "&GG" ;
2013-11-03 02:51:21 +00:00
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 )
2013-12-20 22:05:56 +00:00
{
2013-11-03 02:51:21 +00:00
SNESSubMenu . Text = "&SGB" ;
2013-12-20 22:05:56 +00:00
}
2013-11-03 02:51:21 +00:00
else
2013-12-20 22:05:56 +00:00
{
2013-11-03 02:51:21 +00:00
SNESSubMenu . Text = "&SNES" ;
2013-12-20 22:05:56 +00:00
}
2013-11-03 02:51:21 +00:00
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-12-23 16:58:20 +00:00
case "DGB" :
DGBSubMenu . Visible = true ;
break ;
2014-05-30 22:31:16 +00:00
case "WSWAN" :
wonderSwanToolStripMenuItem . Visible = true ;
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
{
2014-05-30 22:00:16 +00:00
var str = Global . SystemInfo . DisplayName ;
2014-05-31 23:05:02 +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-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 ;
2014-05-12 20:51:09 +00:00
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 SyncThrottle ( )
{
2013-12-29 23:35:42 +00:00
var fastforward = Global . ClientControls [ "Fast Forward" ] | | FastForward ;
var 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 ) ;
_throttle . signal_paused = EmulatorPaused | | Global . Emulator is NullEmulator ;
_throttle . signal_unthrottle = _unthrottled | | superfastforward ;
2013-12-20 22:05:56 +00:00
_throttle . SetSpeedPercent ( fastforward ? Global . Config . SpeedPercentAlternate : Global . Config . SpeedPercent ) ;
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
2013-12-20 22:05:56 +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 + + )
2013-12-20 22:05:56 +00:00
{
2011-06-11 12:54:26 +00:00
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 )
2013-12-20 22:05:56 +00:00
{
2011-07-10 01:55:37 +00:00
col = Color . Black . ToArgb ( ) ;
2013-12-20 22:05:56 +00:00
}
2011-07-10 01:55:37 +00:00
else
2013-12-20 22:05:56 +00:00
{
2011-07-10 01:55:37 +00:00
col = Color . White . ToArgb ( ) ;
2013-12-20 22:05:56 +00:00
}
2011-07-10 01:55:37 +00:00
}
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
2013-12-20 22:05:56 +00:00
ptr [ ( y * stride ) + x ] = col ;
2011-07-10 01:55:37 +00:00
}
2013-12-20 22:05:56 +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 )
{
2013-12-30 16:49:13 +00:00
SaveState ( sfd . FileName , sfd . FileName , false ) ;
2013-11-27 23:35:32 +00:00
}
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 )
2013-12-20 22:05:56 +00:00
{
2011-06-11 12:54:26 +00:00
return ;
2013-12-20 22:05:56 +00:00
}
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
2013-12-30 16:49:13 +00:00
LoadState ( ofd . FileName , Path . GetFileName ( ofd . FileName ) ) ;
2011-06-11 12:54:26 +00:00
}
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
}
private void Render ( )
{
2014-05-18 02:11:17 +00:00
//private Size _lastVideoSize = new Size(-1, -1), _lastVirtualSize = new Size(-1, -1);
2013-10-20 18:02:43 +00:00
var video = Global . Emulator . VideoProvider ;
2014-05-19 12:57:02 +00:00
//bool change = false;
2014-05-18 02:11:17 +00:00
Size currVideoSize = new Size ( video . BufferWidth , video . BufferHeight ) ;
Size currVirtualSize = new Size ( video . VirtualWidth , video . VirtualWidth ) ;
if ( currVideoSize ! = _lastVideoSize | | currVirtualSize ! = _lastVirtualSize )
2011-02-20 08:40:22 +00:00
{
2014-05-18 02:11:17 +00:00
_lastVideoSize = currVideoSize ;
_lastVirtualSize = currVirtualSize ;
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
}
2013-12-20 22:05:56 +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 ) ;
}
2013-12-20 22:05:56 +00:00
// 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 ( ) ;
2013-12-20 22:05:56 +00:00
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 ] ) ;
2013-12-20 22:05:56 +00:00
if ( i ! = num - 1 )
{
sb . Append ( '|' ) ;
}
2011-07-24 06:45:05 +00:00
}
2013-12-20 22:05:56 +00:00
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
2013-12-20 22:05:56 +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 (
2014-06-01 04:40:20 +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;*.ws;*.wsc;%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%" ,
2014-05-18 01:27:24 +00:00
"Genesis" , "*.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" ,
2014-06-01 04:40:20 +00:00
"WonderSawn" , "*.ws;*.wsc;%ARCH%" ,
2012-03-18 00:00:47 +00:00
"All Files" , "*.*" ) ;
}
else
{
ofd . Filter = FormatFilter (
2014-06-01 02:06:23 +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;*.wsc;*.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" ,
2014-05-18 01:27:24 +00:00
"Genesis" , "*.gen;*.md;*.smd;*.bin;*.cue;%ARCH%" ,
2014-06-01 02:06:23 +00:00
"WonderSawn" , "*.wsc;%ARCH%" ,
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-12-29 23:35:42 +00:00
private void CoreSyncSettings ( object sender , RomLoader . SettingsLoadArgs e )
2013-12-24 23:32:43 +00:00
{
// if movie 2.0 was finished, this is where you'd decide whether to get a settings object
// from a config file or from the movie file
// since all we have right now is movie 1.0, we get silly hacks instead
2013-12-29 23:35:42 +00:00
e . Settings = _syncSettingsHack ? ? Global . Config . GetCoreSyncSettings ( e . Core ) ;
2013-12-26 20:19:28 +00:00
}
2013-12-29 23:35:42 +00:00
private static void CoreSettings ( object sender , RomLoader . SettingsLoadArgs e )
2013-12-26 20:19:28 +00:00
{
e . Settings = Global . Config . GetCoreSettings ( e . Core ) ;
2013-12-24 23:32:43 +00:00
}
2013-12-22 20:41:21 +00:00
/// <summary>
/// send core settings to emu, setting reboot flag if needed
/// </summary>
2013-12-24 01:06:17 +00:00
public void PutCoreSettings ( object o )
2013-12-22 20:41:21 +00:00
{
if ( Global . Emulator . PutSettings ( o ) )
2013-12-29 23:35:42 +00:00
{
2013-12-22 20:41:21 +00:00
FlagNeedsReboot ( ) ;
2013-12-29 23:35:42 +00:00
}
2013-12-22 20:41:21 +00:00
}
2013-12-23 02:51:41 +00:00
/// <summary>
/// send core sync settings to emu, setting reboot flag if needed
/// </summary>
2013-12-23 23:03:12 +00:00
public void PutCoreSyncSettings ( object o )
2013-12-23 02:51:41 +00:00
{
if ( Global . MovieSession . Movie . IsActive )
{
GlobalWin . OSD . AddMessage ( "Attempt to change sync-relevant setings while recording BLOCKED." ) ;
}
2013-12-29 23:35:42 +00:00
else if ( Global . Emulator . PutSyncSettings ( o ) )
2013-12-23 02:51:41 +00:00
{
2013-12-29 23:35:42 +00:00
FlagNeedsReboot ( ) ;
2013-12-23 02:51:41 +00:00
}
}
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 ;
}
2013-12-20 22:05:56 +00:00
if ( Global . Config . ShowLogWindow )
{
LogConsole . SaveConfigSettings ( ) ;
}
2013-11-03 02:51:21 +00:00
ConfigService . Save ( PathManager . DefaultIniPath , Global . Config ) ;
}
private void PreviousSlot ( )
{
if ( Global . Config . SaveSlot = = 0 )
2013-11-27 23:35:32 +00:00
{
2013-12-20 22:05:56 +00:00
Global . Config . SaveSlot = 9 ; // Wrap to end of slot list
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
else if ( Global . Config . SaveSlot > 9 )
2013-11-27 23:35:32 +00:00
{
2013-12-20 22:05:56 +00:00
Global . Config . SaveSlot = 9 ; // Meh, just in case
2013-11-27 23:35:32 +00:00
}
else
{
Global . Config . SaveSlot - - ;
}
2013-12-20 22:05:56 +00:00
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
{
2013-12-20 22:05:56 +00:00
Global . Config . SaveSlot = 0 ; // Wrap to beginning of slot list
2013-11-27 23:35:32 +00:00
}
2013-11-03 02:51:21 +00:00
else if ( Global . Config . SaveSlot < 0 )
2013-11-27 23:35:32 +00:00
{
2013-12-20 22:05:56 +00:00
Global . Config . SaveSlot = 0 ; // Meh, just in case
2013-11-27 23:35:32 +00:00
}
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 ;
2013-12-20 22:05:56 +00:00
GlobalWin . OSD . AddMessage ( Global . MovieSession . ReadOnly ? "Movie read-only mode" : "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-12-20 22:05:56 +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
}
2014-05-15 00:00:02 +00:00
public static void ToggleSound ( )
{
Global . Config . SoundEnabled ^ = true ;
GlobalWin . Sound . UpdateSoundSettings ( ) ;
GlobalWin . Sound . StartSound ( ) ;
}
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-12-20 22:05:56 +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
2014-01-16 16:32:34 +00:00
private static void SoftReset ( )
2012-12-10 00:43:43 +00:00
{
2013-12-20 22:05:56 +00:00
// is it enough to run this for one frame? maybe..
2013-11-03 02:51:21 +00:00
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
2014-01-16 16:32:34 +00:00
private static void HardReset ( )
2013-11-03 02:51:21 +00:00
{
2013-12-20 22:05:56 +00:00
// is it enough to run this for one frame? maybe..
2013-11-03 02:51:21 +00:00
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
2014-02-22 21:59:46 +00:00
Slot0StatusButton . ForeColor = _stateSlots . HasSlot ( 0 ) ? Global . Config . SaveSlot = = 0 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot1StatusButton . ForeColor = _stateSlots . HasSlot ( 1 ) ? Global . Config . SaveSlot = = 1 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot2StatusButton . ForeColor = _stateSlots . HasSlot ( 2 ) ? Global . Config . SaveSlot = = 2 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot3StatusButton . ForeColor = _stateSlots . HasSlot ( 3 ) ? Global . Config . SaveSlot = = 3 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot4StatusButton . ForeColor = _stateSlots . HasSlot ( 4 ) ? Global . Config . SaveSlot = = 4 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot5StatusButton . ForeColor = _stateSlots . HasSlot ( 5 ) ? Global . Config . SaveSlot = = 5 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot6StatusButton . ForeColor = _stateSlots . HasSlot ( 6 ) ? Global . Config . SaveSlot = = 6 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot7StatusButton . ForeColor = _stateSlots . HasSlot ( 7 ) ? Global . Config . SaveSlot = = 7 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot8StatusButton . ForeColor = _stateSlots . HasSlot ( 8 ) ? Global . Config . SaveSlot = = 8 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot9StatusButton . ForeColor = _stateSlots . HasSlot ( 9 ) ? Global . Config . SaveSlot = = 9 ? SystemColors . HighlightText : SystemColors . WindowText : SystemColors . GrayText ;
Slot0StatusButton . BackColor = Global . Config . SaveSlot = = 0 ? SystemColors . Highlight : SystemColors . Control ;
Slot1StatusButton . BackColor = Global . Config . SaveSlot = = 1 ? SystemColors . Highlight : SystemColors . Control ;
Slot2StatusButton . BackColor = Global . Config . SaveSlot = = 2 ? SystemColors . Highlight : SystemColors . Control ;
Slot3StatusButton . BackColor = Global . Config . SaveSlot = = 3 ? SystemColors . Highlight : SystemColors . Control ;
Slot4StatusButton . BackColor = Global . Config . SaveSlot = = 4 ? SystemColors . Highlight : SystemColors . Control ;
Slot5StatusButton . BackColor = Global . Config . SaveSlot = = 5 ? SystemColors . Highlight : SystemColors . Control ;
Slot6StatusButton . BackColor = Global . Config . SaveSlot = = 6 ? SystemColors . Highlight : SystemColors . Control ;
Slot7StatusButton . BackColor = Global . Config . SaveSlot = = 7 ? SystemColors . Highlight : SystemColors . Control ;
Slot8StatusButton . BackColor = Global . Config . SaveSlot = = 8 ? SystemColors . Highlight : SystemColors . Control ;
Slot9StatusButton . BackColor = Global . Config . SaveSlot = = 9 ? SystemColors . Highlight : SystemColors . Control ;
2013-11-03 02:51:21 +00:00
}
2014-01-27 00:02:21 +00:00
//TODO GL - this whole feature will have to be re-added
2013-12-20 22:05:56 +00:00
private Bitmap CaptureOSD ( ) // sort of like MakeScreenShot(), but with OSD and LUA captured as well. slow and bad.
2013-11-03 02:51:21 +00:00
{
2014-01-27 00:02:21 +00:00
// // 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 (_captureOsdRvp == null)
// {
// _captureOsdRvp = new RetainedViewportPanel();
// _captureOsdSrp = new SysdrawingRenderPanel(_captureOsdRvp);
// }
// // this size can be different for showing off stretching or filters
// _captureOsdRvp.Width = Global.Emulator.VideoProvider.BufferWidth;
// _captureOsdRvp.Height = Global.Emulator.VideoProvider.BufferHeight;
// GlobalWin.DisplayManager.UpdateSourceEx(Global.Emulator.VideoProvider, _captureOsdSrp);
// return (Bitmap)_captureOsdRvp.GetBitmap().Clone();
return null ;
2012-12-10 00:43:43 +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-12-20 22:05:56 +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-12-20 22:05:56 +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 ( )
{
2013-12-29 23:35:42 +00:00
var oldp = Global . Config . SpeedPercent ;
2013-11-03 02:51:21 +00:00
int newp ;
2014-01-01 03:03:10 +00:00
2013-12-29 23:35:42 +00:00
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 ;
}
2014-01-10 16:49:17 +00:00
else if ( oldp < 1600 )
2013-12-29 23:35:42 +00:00
{
newp = 1600 ;
}
2014-01-10 16:49:17 +00:00
else
{
newp = 3200 ;
}
2013-12-29 23:35:42 +00:00
2013-11-03 02:51:21 +00:00
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-12-29 23:35:42 +00:00
var oldp = Global . Config . SpeedPercent ;
2013-11-03 02:51:21 +00:00
int newp ;
2014-01-01 03:03:10 +00:00
2014-01-10 16:49:17 +00:00
if ( oldp > 1600 )
{
newp = 1600 ;
}
else if ( oldp > 800 )
2013-12-29 23:35:42 +00:00
{
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 ;
}
2013-11-03 02:51:21 +00:00
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 ;
}
2013-12-20 22:05:56 +00:00
2014-01-01 03:03:10 +00:00
LedLightStatusLabel . Image = Global . Emulator . CoreComm . DriveLED
2014-02-17 09:20:08 +00:00
? StatusBarDiskLightOnImage
: StatusBarDiskLightOffImage ;
2013-11-03 02:51:21 +00:00
}
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
2014-01-01 03:03:10 +00:00
? "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-12-20 22:05:56 +00:00
"Display Vsync set to " + ( Global . Config . VSyncThrottle ? "on" : "off" )
2013-11-03 02:51:21 +00:00
) ;
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-12-20 22:05:56 +00:00
var result = MessageBox . Show (
message ,
2013-11-03 02:51:21 +00:00
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-12-20 22:49:35 +00:00
private void FdsInsertDiskMenuAdd ( string name , string button , string msg )
{
FDSControlsMenuItem . 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 ) ;
GlobalWin . OSD . AddMessage ( msg ) ;
}
}
} ) ;
}
2013-12-30 16:49:13 +00:00
public void LoadState ( string path , string userFriendlyStateName , bool fromLua = false ) // Move to client.common
{
GlobalWin . DisplayManager . NeedsToPaint = true ;
if ( SavestateManager . LoadStateFile ( path , userFriendlyStateName ) )
{
SetMainformMovieInfo ( ) ;
GlobalWin . OSD . ClearGUIText ( ) ;
GlobalWin . Tools . UpdateToolsBefore ( fromLua ) ;
UpdateToolsAfter ( fromLua ) ;
UpdateToolsLoadstate ( ) ;
GlobalWin . OSD . AddMessage ( "Loaded state: " + userFriendlyStateName ) ;
if ( GlobalWin . Tools . Has < LuaConsole > ( ) )
{
GlobalWin . Tools . LuaConsole . LuaImp . CallLoadStateEvent ( userFriendlyStateName ) ;
}
}
else
{
GlobalWin . OSD . AddMessage ( "Loadstate error!" ) ;
}
}
public void LoadQuickSave ( string quickSlotName , bool fromLua = false )
{
if ( Global . Emulator is NullEmulator )
{
return ;
}
var path = PathManager . SaveStatePrefix ( Global . Game ) + "." + quickSlotName + ".State" ;
if ( File . Exists ( path ) = = false )
{
GlobalWin . OSD . AddMessage ( "Unable to load " + quickSlotName + ".State" ) ;
return ;
}
LoadState ( path , quickSlotName , fromLua ) ;
}
public void SaveState ( string path , string userFriendlyStateName , bool fromLua )
{
SavestateManager . SaveStateFile ( path , userFriendlyStateName ) ;
GlobalWin . OSD . AddMessage ( "Saved state: " + userFriendlyStateName ) ;
if ( ! fromLua )
{
UpdateStatusSlots ( ) ;
}
}
2013-12-20 22:05:56 +00:00
// Alt key hacks
2013-11-03 02:51:21 +00:00
protected override void WndProc ( ref Message m )
2011-06-30 02:22:12 +00:00
{
2013-12-20 22:05:56 +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
{
2013-11-03 02:51:21 +00:00
return ;
2013-12-20 22:05:56 +00:00
}
}
2013-11-03 02:51:21 +00:00
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-12-20 22:05:56 +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
}
2014-04-25 01:19:57 +00:00
private void UpdateCoreStatusBarButton ( )
{
if ( Global . Emulator is NullEmulator )
{
CoreNameStatusBarButton . Visible = false ;
return ;
}
CoreNameStatusBarButton . Visible = true ;
CoreAttributes attributes = Global . Emulator . Attributes ( ) ;
CoreNameStatusBarButton . Text =
( ! attributes . Released ? "(Experimental) " : string . Empty ) +
attributes . CoreName ;
2014-04-25 21:55:56 +00:00
CoreNameStatusBarButton . ToolTipText = attributes . Ported ? "(ported) " : string . Empty ;
2014-04-25 01:19:57 +00:00
if ( ! attributes . Ported )
{
2014-05-04 14:10:28 +00:00
CoreNameStatusBarButton . Image = Properties . Resources . CorpHawkSmall ;
2014-04-25 01:19:57 +00:00
}
else
{
if ( Global . Emulator is QuickNES )
{
2014-05-04 14:10:28 +00:00
CoreNameStatusBarButton . Image = Properties . Resources . QuickNes ;
2014-04-25 01:19:57 +00:00
}
2014-04-25 21:41:34 +00:00
else if ( Global . Emulator is LibsnesCore )
{
2014-05-04 14:10:28 +00:00
CoreNameStatusBarButton . Image = Properties . Resources . bsnes ;
2014-05-04 13:47:01 +00:00
CoreNameStatusBarButton . Text + = " (" + ( ( LibsnesCore . SnesSyncSettings ) Global . Emulator . GetSyncSettings ( ) ) . Profile + ")" ;
2014-04-25 21:41:34 +00:00
}
else if ( Global . Emulator is Yabause )
{
2014-05-04 14:10:28 +00:00
CoreNameStatusBarButton . Image = Properties . Resources . yabause ;
2014-04-25 21:41:34 +00:00
}
2014-04-25 21:55:56 +00:00
else if ( Global . Emulator is Atari7800 )
{
2014-05-04 14:10:28 +00:00
CoreNameStatusBarButton . Image = Properties . Resources . emu7800 ;
2014-04-25 21:55:56 +00:00
}
2014-04-25 22:50:28 +00:00
else if ( Global . Emulator is GBA )
{
2014-05-04 14:10:28 +00:00
CoreNameStatusBarButton . Image = Properties . Resources . meteor ;
2014-04-25 22:50:28 +00:00
}
else if ( Global . Emulator is GPGX )
{
2014-05-04 14:10:28 +00:00
CoreNameStatusBarButton . Image = Properties . Resources . genplus ;
2014-04-25 22:50:28 +00:00
}
else if ( Global . Emulator is PSP )
{
2014-05-04 14:10:28 +00:00
CoreNameStatusBarButton . Image = Properties . Resources . ppsspp ;
2014-04-25 22:50:28 +00:00
}
2014-04-25 23:17:10 +00:00
else if ( Global . Emulator is Gameboy )
{
CoreNameStatusBarButton . Image = BizHawk . Client . EmuHawk . Properties . Resources . gambatte ;
}
else
{
CoreNameStatusBarButton . Image = null ;
}
2014-04-25 01:19:57 +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 ( )
{
2013-12-29 23:35:42 +00:00
var runFrame = false ;
2013-11-27 23:35:32 +00:00
_runloopFrameadvance = false ;
2013-12-29 23:35:42 +00:00
var now = DateTime . Now ;
var suppressCaptureRewind = false ;
2012-10-07 19:52:09 +00:00
2013-12-29 23:35:42 +00:00
double frameAdvanceTimestampDelta = ( now - _frameAdvanceTimestamp ) . TotalMilliseconds ;
2013-11-03 02:51:21 +00:00
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-12-29 23:35:42 +00:00
// handle the initial trigger of a frame advance
2014-01-10 16:54:53 +00:00
if ( _frameAdvanceTimestamp = = DateTime . MinValue )
2013-11-03 02:51:21 +00:00
{
PauseEmulator ( ) ;
runFrame = true ;
2013-11-27 23:35:32 +00:00
_runloopFrameadvance = true ;
2013-12-29 23:35:42 +00:00
_frameAdvanceTimestamp = now ;
2013-11-03 02:51:21 +00:00
}
else
{
2013-12-29 23:35:42 +00:00
// handle the timed transition from countdown to FrameProgress
2013-11-03 02:51:21 +00:00
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-12-29 23:35:42 +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 ( ) ;
}
2013-12-29 23:35:42 +00:00
_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-12-26 23:12:41 +00:00
// TODO: mostly likely this will need to be whacked, if not then refactor
2013-12-29 23:35:42 +00:00
var returnToRecording = Global . MovieSession . Movie . IsRecording ;
2013-12-27 01:19:38 +00:00
if ( Global . Rewinder . RewindActive & & ( Global . ClientControls [ "Rewind" ] | | PressRewind ) )
2012-10-07 19:52:09 +00:00
{
2013-12-27 01:19:38 +00:00
Global . Rewinder . Rewind ( 1 ) ;
2013-11-03 02:51:21 +00:00
suppressCaptureRewind = true ;
2013-12-27 00:47:52 +00:00
2013-12-29 23:35:42 +00:00
runFrame = Global . Rewinder . Count ! = 0 ;
2013-12-27 00:47:52 +00:00
2013-12-29 23:35:42 +00:00
// we don't want to capture input when rewinding, even in record mode
2013-11-03 02:51:21 +00:00
if ( Global . MovieSession . Movie . IsRecording )
{
Global . MovieSession . Movie . SwitchToPlay ( ) ;
}
2012-10-07 19:52:09 +00:00
}
2013-12-27 00:47:52 +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-12-29 23:35:42 +00:00
var genSound = false ;
var coreskipaudio = false ;
2013-11-03 02:51:21 +00:00
if ( runFrame )
2012-10-07 19:52:09 +00:00
{
2013-12-29 23:35:42 +00:00
var isFastForwarding = Global . ClientControls [ "Fast Forward" ] | | Global . ClientControls [ "Turbo" ] ;
var isTurboing = Global . ClientControls [ "Turbo" ] ;
var updateFpsString = _runloopLastFf ! = isFastForwarding ;
_runloopLastFf = isFastForwarding ;
2013-11-03 02:51:21 +00:00
2013-12-29 23:35:42 +00:00
// client input-related duties
2013-11-20 02:14:29 +00:00
GlobalWin . OSD . ClearGUIText ( ) ;
2014-01-01 03:19:08 +00:00
Global . CheatList . Pulse ( ) ;
2014-05-03 09:02:17 +00:00
//zero 03-may-2014 - moved this before call to UpdateToolsBefore(), since it seems to clear the state which a lua event.framestart is going to want to alter
Global . ClickyVirtualPadController . FrameTick ( ) ;
Global . LuaAndAdaptor . FrameTick ( ) ;
2014-05-03 11:59:11 +00:00
if ( GlobalWin . Tools . Has < LuaConsole > ( ) )
{
GlobalWin . Tools . LuaConsole . LuaImp . CallFrameBeforeEvent ( ) ;
}
2013-12-29 23:35:42 +00:00
if ( ! isTurboing )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
GlobalWin . Tools . UpdateToolsBefore ( ) ;
2013-11-03 02:51:21 +00:00
}
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-12-29 23:35:42 +00:00
var fps_string = _runloopLastFps + " fps" ;
if ( isTurboing )
2013-11-03 02:51:21 +00:00
{
fps_string + = " >>>>" ;
}
2013-12-29 23:35:42 +00:00
else if ( isFastForwarding )
2013-11-03 02:51:21 +00:00
{
fps_string + = " >>" ;
}
2013-12-29 23:35:42 +00:00
2013-11-03 16:07:58 +00:00
GlobalWin . OSD . FPS = fps_string ;
2013-11-03 02:51:21 +00:00
}
2013-12-29 23:35:42 +00:00
if ( ! suppressCaptureRewind & & Global . Rewinder . RewindActive )
{
Global . Rewinder . CaptureRewindState ( ) ;
}
2013-11-03 02:51:21 +00:00
2013-12-29 23:35:42 +00:00
if ( ! _runloopFrameadvance )
{
genSound = true ;
}
2013-11-03 02:51:21 +00:00
else if ( ! Global . Config . MuteFrameAdvance )
2013-12-29 23:35:42 +00:00
{
2013-11-03 02:51:21 +00:00
genSound = true ;
2013-12-29 23:35:42 +00:00
}
2013-11-03 02:51:21 +00:00
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-12-29 23:35:42 +00:00
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 )
{
2014-01-10 16:54:53 +00:00
AvFrameAdvance ( ) ;
2013-11-03 02:51:21 +00:00
}
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 ;
2014-05-03 11:59:11 +00:00
if ( GlobalWin . Tools . Has < LuaConsole > ( ) )
{
GlobalWin . Tools . LuaConsole . LuaImp . CallFrameAfterEvent ( ) ;
}
2013-12-29 23:35:42 +00:00
if ( ! isTurboing )
2013-11-03 02:51:21 +00:00
{
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 ( ) ;
2013-12-29 23:35:42 +00:00
if ( returnToRecording )
2013-11-03 02:51:21 +00:00
{
Global . MovieSession . Movie . SwitchToRecord ( ) ;
}
2013-12-29 23:35:42 +00:00
2013-11-03 02:51:21 +00:00
PressRewind = false ;
2012-10-07 19:52:09 +00:00
}
2013-12-29 23:35:42 +00:00
2013-11-03 02:51:21 +00:00
if ( UpdateFrame )
2012-10-07 19:52:09 +00:00
{
2013-12-29 23:35:42 +00:00
if ( returnToRecording )
2013-11-03 02:51:21 +00:00
{
Global . MovieSession . Movie . SwitchToRecord ( ) ;
}
2013-12-29 23:35:42 +00:00
2013-11-03 02:51:21 +00:00
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-12-29 23:35:42 +00:00
{
2013-11-03 16:07:58 +00:00
GlobalWin . Sound . UpdateSilence ( ) ;
2013-12-29 23:35:42 +00:00
}
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-12-29 23:35:42 +00:00
private void RecordAv ( string videowritername , string filename )
2012-07-23 00:33:30 +00:00
{
2013-12-29 23:35:42 +00:00
_RecordAv ( videowritername , filename , true ) ;
2012-07-23 00:33:30 +00:00
}
/// <summary>
/// start avi recording, asking user for filename and options
/// </summary>
2013-12-29 23:35:42 +00:00
private void RecordAv ( )
2012-07-23 00:33:30 +00:00
{
2013-12-29 23:35:42 +00:00
_RecordAv ( null , null , false ) ;
2012-07-23 00:33:30 +00:00
}
/// <summary>
2013-12-29 23:35:42 +00:00
/// start AV recording
2012-07-23 00:33:30 +00:00
/// </summary>
2013-12-29 23:35:42 +00:00
private void _RecordAv ( string videowritername , string filename , bool unattended )
2011-07-09 21:13:18 +00:00
{
2013-12-29 23:35:42 +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-12-29 23:35:42 +00:00
foreach ( var w in video_writers . Where ( w = > w . ShortName ( ) = = videowritername ) )
2012-07-23 00:33:30 +00:00
{
2013-12-29 23:35:42 +00:00
aw = w ;
break ;
2012-07-23 00:33:30 +00:00
}
}
else
{
2014-02-07 02:28:07 +00:00
aw = VideoWriterChooserForm . DoVideoWriterChoserDlg ( video_writers , GlobalWin . MainForm , out _avwriterResizew , out _avwriterResizeh , out _avwriterpad ) ;
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 )
2013-12-29 23:35:42 +00:00
{
2012-06-13 19:50:50 +00:00
w . Dispose ( ) ;
2013-12-29 23:35:42 +00:00
}
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
{
2013-12-29 23:35:42 +00:00
GlobalWin . OSD . AddMessage (
unattended ? string . Format ( "Couldn't start video writer \"{0}\"" , videowritername ) : "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 )
2013-12-29 23:35:42 +00:00
{
2013-11-27 23:35:32 +00:00
aw . SetVideoParameters ( _avwriterResizew , _avwriterResizeh ) ;
2013-12-29 23:35:42 +00:00
}
2012-11-26 02:25:23 +00:00
else
2013-12-29 23:35:42 +00:00
{
2013-10-20 18:02:43 +00:00
aw . SetVideoParameters ( Global . Emulator . VideoProvider . BufferWidth , Global . Emulator . VideoProvider . BufferHeight ) ;
2013-12-29 23:35:42 +00:00
}
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 ;
}
2013-12-29 23:35:42 +00:00
2012-07-23 00:33:30 +00:00
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
}
2013-12-29 23:35:42 +00:00
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 ;
}
2013-12-29 23:35:42 +00:00
2012-07-23 00:33:30 +00:00
aw . OpenFile ( sfd . FileName ) ;
2012-06-13 19:50:50 +00:00
}
2013-12-29 23:35:42 +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 ;
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
2014-01-01 03:03:10 +00:00
_aviSoundInput = ! Global . Emulator . StartAsyncSound ( )
? new MetaspuAsync ( Global . Emulator . SyncSoundProvider , ESynchMethod . ESynchMethod_V )
2013-12-29 23:35:42 +00:00
: Global . Emulator . SoundProvider ;
2013-11-27 23:35:32 +00:00
_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-12-29 23:35:42 +00:00
private void AbortAv ( )
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-12-29 23:35:42 +00:00
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 ;
2013-12-20 22:05:56 +00:00
AVIStatusLabel . ToolTipText = string . Empty ;
2012-10-18 20:57:53 +00:00
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-12-29 23:35:42 +00:00
private void StopAv ( )
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-12-29 23:35:42 +00:00
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 ;
2013-12-20 22:05:56 +00:00
AVIStatusLabel . ToolTipText = string . Empty ;
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-12-29 23:35:42 +00:00
private void AvFrameAdvance ( )
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
{
2014-01-12 19:11:11 +00:00
var nsampnum = 44100 * ( long ) Global . Emulator . CoreComm . VsyncDen + _soundRemainder ;
2013-12-29 23:35:42 +00:00
var 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
2013-12-29 23:35:42 +00:00
var 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 )
2013-12-29 23:35:42 +00:00
{
2012-11-26 21:08:08 +00:00
bmpin = CaptureOSD ( ) ;
2013-12-29 23:35:42 +00:00
}
2012-11-26 21:08:08 +00:00
else
{
2013-12-29 23:35:42 +00:00
bmpin = new Bitmap (
Global . Emulator . VideoProvider . BufferWidth ,
Global . Emulator . VideoProvider . BufferHeight ,
PixelFormat . Format32bppArgb ) ;
var lockdata = bmpin . LockBits (
new Rectangle ( 0 , 0 , bmpin . Width , bmpin . Height ) , ImageLockMode . WriteOnly , PixelFormat . Format32bppArgb ) ;
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-12-29 23:35:42 +00:00
var bmpout = new Bitmap ( _avwriterResizew , _avwriterResizeh , PixelFormat . Format32bppArgb ) ;
using ( var g = Graphics . FromImage ( bmpout ) )
{
2014-02-07 02:28:07 +00:00
if ( _avwriterpad )
{
g . Clear ( Color . FromArgb ( Global . Emulator . VideoProvider . BackgroundColor ) ) ;
g . DrawImageUnscaled ( bmpin , ( bmpout . Width - bmpin . Width ) / 2 , ( bmpout . Height - bmpin . Height ) / 2 ) ;
}
else
{
g . DrawImage ( bmpin , new Rectangle ( 0 , 0 , bmpout . Width , bmpout . Height ) ) ;
}
2013-12-29 23:35:42 +00:00
}
2012-11-26 21:08:08 +00:00
bmpin . Dispose ( ) ;
2013-11-03 03:54:37 +00:00
output = new BmpVideoProvder ( bmpout ) ;
2012-11-26 21:08:08 +00:00
}
else
{
2014-01-01 03:03:10 +00:00
output = Global . Config . AVI_CaptureOSD
? new BmpVideoProvder ( CaptureOSD ( ) )
2013-12-29 23:35:42 +00:00
: 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 )
2013-12-29 23:35:42 +00:00
{
2013-11-03 03:54:37 +00:00
( output as BmpVideoProvder ) . Dispose ( ) ;
2013-12-29 23:35:42 +00:00
}
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 ) ;
2014-01-10 16:54:53 +00:00
AbortAv ( ) ;
2012-11-26 21:08:08 +00:00
}
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
{
2014-01-10 16:54:53 +00:00
StopAv ( ) ;
if ( _autoCloseOnDump )
2013-11-03 02:51:21 +00:00
{
2013-11-27 23:35:32 +00:00
_exit = true ;
2013-11-03 02:51:21 +00:00
}
}
}
2013-12-29 23:35:42 +00:00
2013-11-23 00:51:31 +00:00
GlobalWin . DisplayManager . NeedsToPaint = true ;
2013-11-03 02:51:21 +00:00
}
}
2014-01-10 16:54:53 +00:00
private int? LoadArhiveChooser ( HawkFile file )
{
var ac = new ArchiveChooser ( file ) ;
if ( ac . ShowDialog ( this ) = = DialogResult . OK )
{
return ac . SelectedMemberIndex ;
}
else
{
return null ;
}
}
2013-11-03 02:51:21 +00:00
#endregion
#region Scheduled for refactor
2013-12-20 22:05:56 +00:00
private void ShowMessageCoreComm ( string message )
2013-12-10 17:58:12 +00:00
{
MessageBox . Show ( this , message , "Warning" , MessageBoxButtons . OK , MessageBoxIcon . Warning ) ;
}
2013-12-25 19:09:53 +00:00
private void ShowLoadError ( object sender , RomLoader . RomErrorArgs e )
2013-11-03 02:51:21 +00:00
{
2014-05-08 03:18:00 +00:00
string title = "load error" ;
if ( e . AttemptedCoreLoad ! = null )
title = e . AttemptedCoreLoad + " load error" ;
MessageBox . Show ( this , e . Message , title , MessageBoxButtons . OK , MessageBoxIcon . Error ) ;
2013-12-25 19:09:53 +00:00
}
2013-11-03 02:51:21 +00:00
2014-03-18 03:03:53 +00:00
private void NotifyCoreComm ( string message )
{
GlobalWin . OSD . AddMessage ( message ) ;
}
2014-04-14 01:59:57 +00:00
private string ChoosePlatformForRom ( RomGame rom )
{
2014-04-14 12:25:57 +00:00
var platformChooser = new PlatformChooser
2014-04-14 01:59:57 +00:00
{
RomGame = rom
} ;
platformChooser . ShowDialog ( ) ;
return platformChooser . PlatformChoice ;
}
2013-12-25 19:09:53 +00:00
// Still needs a good bit of refactoring
2014-05-24 22:06:08 +00:00
public bool LoadRom ( string path , bool? deterministicemulation = null )
2013-12-25 19:09:53 +00:00
{
2014-05-24 22:06:08 +00:00
// If deterministic emulation is passed in, respect that value regardless, else determine a good value (currently that simply means movies require detemrinistic emulaton)
bool deterministic = deterministicemulation . HasValue ?
deterministicemulation . Value :
Global . MovieSession . Movie . IsActive ;
2014-01-01 19:07:23 +00:00
if ( ! GlobalWin . Tools . AskSave ( ) )
{
return false ;
}
2014-01-01 03:03:10 +00:00
var loader = new RomLoader
2013-12-26 01:00:44 +00:00
{
ChooseArchive = LoadArhiveChooser ,
2014-05-24 22:06:08 +00:00
ChoosePlatform = ChoosePlatformForRom ,
Deterministic = deterministic
2013-12-26 01:00:44 +00:00
} ;
2013-12-25 19:09:53 +00:00
loader . OnLoadError + = ShowLoadError ;
2013-12-26 01:00:44 +00:00
2013-12-26 20:19:28 +00:00
loader . OnLoadSettings + = CoreSettings ;
loader . OnLoadSyncSettings + = CoreSyncSettings ;
2014-01-01 21:24:58 +00:00
// this also happens in CloseGame(). but it needs to happen here since if we're restarting with the same core,
// any settings changes that we made need to make it back to config before we try to instantiate that core with
// the new settings objects
CommitCoreSettingsToConfig ( ) ;
2014-03-18 03:03:53 +00:00
var nextComm = new CoreComm ( ShowMessageCoreComm , NotifyCoreComm ) ;
2014-01-01 21:24:58 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( nextComm ) ;
var result = loader . LoadRom ( path , nextComm ) ;
2013-11-03 02:51:21 +00:00
2013-12-25 19:09:53 +00:00
if ( result )
{
2013-12-27 03:02:28 +00:00
if ( loader . LoadedEmulator is TI83 )
2013-11-03 02:51:21 +00:00
{
2013-12-25 19:09:53 +00:00
if ( Global . Config . TI83autoloadKeyPad )
2013-12-20 22:05:56 +00:00
{
2013-12-25 19:09:53 +00:00
GlobalWin . Tools . Load < TI83KeyPad > ( ) ;
2013-12-20 22:05:56 +00:00
}
2013-11-03 02:51:21 +00:00
}
2012-07-12 21:39:11 +00:00
2013-11-03 02:51:21 +00:00
CloseGame ( ) ;
Global . Emulator . Dispose ( ) ;
2013-12-26 01:00:44 +00:00
Global . Emulator = loader . LoadedEmulator ;
2014-01-01 21:24:58 +00:00
Global . CoreComm = nextComm ;
2013-12-26 01:00:44 +00:00
Global . Game = loader . Game ;
2013-11-03 02:51:21 +00:00
CoreFileProvider . SyncCoreCommInputSignals ( ) ;
2013-12-24 21:59:41 +00:00
InputManager . SyncControls ( ) ;
2012-07-12 23:13:22 +00:00
2013-12-29 23:35:42 +00:00
if ( loader . LoadedEmulator is NES )
2013-11-03 02:51:21 +00:00
{
2013-12-29 23:35:42 +00:00
var nes = loader . LoadedEmulator as NES ;
2014-05-23 15:10:14 +00:00
if ( ! string . IsNullOrWhiteSpace ( nes . GameName ) )
2013-12-20 22:05:56 +00:00
{
2013-11-03 02:51:21 +00:00
Global . Game . Name = nes . GameName ;
2013-12-20 22:05:56 +00:00
}
2013-11-03 02:51:21 +00:00
Global . Game . Status = nes . RomStatus ;
}
2012-09-29 23:03:51 +00:00
2014-05-23 16:22:24 +00:00
Text = DisplayNameForSystem ( loader . Game . System ) + " - " + Global . Game . Name ;
2014-05-12 20:51:09 +00:00
2013-12-27 01:19:38 +00:00
Global . Rewinder . ResetRewindBuffer ( ) ;
2012-09-30 00:53:08 +00:00
2013-12-26 01:00:44 +00:00
if ( Global . Emulator . CoreComm . RomStatusDetails = = null & & loader . Rom ! = null )
2013-11-03 02:51:21 +00:00
{
2013-12-29 23:35:42 +00:00
Global . Emulator . CoreComm . RomStatusDetails = string . Format (
"{0}\r\nSHA1:{1}\r\nMD5:{2}\r\n" ,
2013-12-26 01:00:44 +00:00
loader . Game . Name ,
2013-12-27 04:41:50 +00:00
Util . Hash_SHA1 ( loader . Rom . RomData ) ,
Util . Hash_MD5 ( loader . Rom . RomData ) ) ;
2013-11-03 02:51:21 +00:00
}
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
2013-12-20 22:05:56 +00:00
// restarts the lua console if a different rom is loaded.
// im not really a fan of how this is done..
2014-04-06 20:46:23 +00:00
if ( Global . Config . RecentRoms . Empty | | Global . Config . RecentRoms . MostRecent ! = loader . 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-12-26 01:00:44 +00:00
Global . Config . RecentRoms . Add ( loader . CanonicalFullPath ) ;
JumpLists . AddRecentItem ( loader . CanonicalFullPath ) ;
if ( File . Exists ( PathManager . SaveRamPath ( loader . Game ) ) )
2013-11-03 02:51:21 +00:00
{
LoadSaveRam ( ) ;
}
2013-12-20 22:05:56 +00:00
2013-11-03 16:07:58 +00:00
GlobalWin . Tools . 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-12-26 01:00:44 +00:00
CurrentlyOpenRom = loader . CanonicalFullPath ;
2013-11-03 02:51:21 +00:00
HandlePlatformMenus ( ) ;
2013-11-27 23:35:32 +00:00
_stateSlots . Clear ( ) ;
2013-11-03 02:51:21 +00:00
UpdateStatusSlots ( ) ;
2014-04-25 01:19:57 +00:00
UpdateCoreStatusBarButton ( ) ;
2013-11-03 02:51:21 +00:00
UpdateDumpIcon ( ) ;
2013-10-11 16:32:36 +00:00
2013-12-27 01:19:38 +00:00
Global . Rewinder . 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-12-21 16:42:36 +00:00
ToolHelpers . UpdateCheatRelatedTools ( null , null ) ;
2013-11-03 02:51:21 +00:00
return true ;
2013-10-27 07:54:00 +00:00
}
2013-12-25 19:09:53 +00:00
else
{
return false ;
}
}
2013-12-30 16:49:13 +00:00
// TODO: should backup logic be stuffed in into Client.Common.SaveStateManager?
public void SaveQuickSave ( string quickSlotName )
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-12-30 16:49:13 +00:00
var path = PathManager . SaveStatePrefix ( Global . Game ) + "." + quickSlotName + ".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
2014-01-01 03:03:10 +00:00
2013-12-20 22:05:56 +00:00
// Make backup first
2013-11-03 02:51:21 +00:00
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-12-29 23:35:42 +00:00
2013-11-03 02:51:21 +00:00
file . CopyTo ( backup ) ;
2013-10-27 15:23:41 +00:00
}
2013-12-30 16:49:13 +00:00
SaveState ( path , quickSlotName , false ) ;
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-12-30 16:49:13 +00:00
GlobalWin . Tools . LuaConsole . LuaImp . CallSaveStateEvent ( quickSlotName ) ;
2013-10-27 15:23:41 +00:00
}
}
2013-12-29 23:35:42 +00:00
private static void CommitCoreSettingsToConfig ( )
2013-12-23 23:03:12 +00:00
{
// save settings object
2013-12-29 23:35:42 +00:00
var t = Global . Emulator . GetType ( ) ;
2013-12-23 23:03:12 +00:00
Global . Config . PutCoreSettings ( Global . Emulator . GetSettings ( ) , t ) ;
2014-01-01 03:03:10 +00:00
2013-12-23 23:03:12 +00:00
// don't trample config with loaded-from-movie settings
if ( ! Global . MovieSession . Movie . IsActive )
2013-12-29 23:35:42 +00:00
{
2013-12-23 23:03:12 +00:00
Global . Config . PutCoreSyncSettings ( Global . Emulator . GetSyncSettings ( ) , t ) ;
2013-12-29 23:35:42 +00:00
}
2013-12-23 23:03:12 +00:00
}
2013-12-20 22:05:56 +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-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 ( ) ;
}
2013-12-29 23:35:42 +00:00
StopAv ( ) ;
2013-12-22 00:44:39 +00:00
2013-12-23 23:03:12 +00:00
CommitCoreSettingsToConfig ( ) ;
2013-12-22 00:44:39 +00:00
2013-11-03 02:51:21 +00:00
Global . Emulator . Dispose ( ) ;
2014-03-18 03:03:53 +00:00
Global . CoreComm = new CoreComm ( ShowMessageCoreComm , NotifyCoreComm ) ;
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-12-20 22:05:56 +00:00
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 ) ;
2014-03-18 03:03:53 +00:00
Global . CoreComm = new CoreComm ( ShowMessageCoreComm , NotifyCoreComm ) ;
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 ( ) ;
2013-12-27 01:19:38 +00:00
Global . Rewinder . ResetRewindBuffer ( ) ;
2014-04-25 01:19:57 +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 ( ) ;
2014-04-25 01:19:57 +00:00
UpdateCoreStatusBarButton ( ) ;
2013-12-21 19:34:01 +00:00
ToolHelpers . UpdateCheatRelatedTools ( null , null ) ;
2013-11-05 16:37:05 +00:00
}
2013-10-27 15:23:41 +00:00
}
2013-11-01 15:47:37 +00:00
2013-12-20 22:05:56 +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 ) ;
2014-01-01 03:03:10 +00:00
2013-11-27 23:35:32 +00:00
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\\" +
2014-01-01 03:03:10 +00:00
Path . GetFileName ( fn ) + "." + Global . Config . MovieExtension ) ;
2013-11-27 23:35:32 +00:00
}
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-12-20 22:05:56 +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
2014-05-12 17:24:43 +00:00
private void GBcoreSettingsToolStripMenuItem_Click ( object sender , EventArgs e )
{
BizHawk . Client . EmuHawk . config . GB . GBPrefs . DoGBPrefsDialog ( this ) ;
}
2014-05-30 22:31:16 +00:00
private void settingsToolStripMenuItem_Click ( object sender , EventArgs e )
{
GenericCoreConfig . DoDialog ( this , "WonderSwan Settings" ) ;
}
2011-02-20 08:40:22 +00:00
}
2012-03-09 12:10:41 +00:00
}