2011-07-22 01:14:13 +00:00
using System ;
using System.Collections.Generic ;
using System.Linq ;
using System.Text ;
using System.Drawing ;
using System.IO ;
using System.Windows.Forms ;
namespace BizHawk.MultiClient
{
partial class MainForm
{
public bool ReadOnly = true ; //Global Movie Read only setting
2013-03-09 23:37:37 +00:00
public void ClearFrame ( )
{
if ( Global . MovieSession . Movie . IsPlaying )
{
Global . MovieSession . Movie . ClearFrame ( Global . Emulator . Frame ) ;
Global . OSD . AddMessage ( "Scrubbed input at frame " + Global . Emulator . Frame . ToString ( ) ) ;
}
}
2011-07-22 01:14:13 +00:00
public void StartNewMovie ( Movie m , bool record )
{
2012-09-22 20:04:37 +00:00
//If a movie is already loaded, save it before starting a new movie
if ( Global . MovieSession . Movie . IsActive )
{
Global . MovieSession . Movie . WriteMovie ( ) ;
}
2012-10-13 21:30:19 +00:00
2011-07-24 23:14:16 +00:00
Global . MovieSession = new MovieSession ( ) ;
Global . MovieSession . Movie = m ;
RewireInputChain ( ) ;
2011-07-22 01:14:13 +00:00
2011-09-04 19:04:00 +00:00
if ( ! record )
2012-09-03 19:42:53 +00:00
{
2011-09-04 19:04:00 +00:00
Global . MovieSession . Movie . LoadMovie ( ) ;
2012-11-22 03:47:18 +00:00
SetSyncDependentSettings ( ) ;
2012-09-03 19:42:53 +00:00
}
2012-11-22 03:47:18 +00:00
LoadRom ( Global . MainForm . CurrentlyOpenRom , true ) ;
2011-07-22 01:14:13 +00:00
Global . Config . RecentMovies . Add ( m . Filename ) ;
2011-09-03 18:07:30 +00:00
if ( Global . MovieSession . Movie . StartsFromSavestate )
2011-07-30 20:49:36 +00:00
{
2011-09-04 19:04:00 +00:00
LoadStateFile ( Global . MovieSession . Movie . Filename , Path . GetFileName ( Global . MovieSession . Movie . Filename ) ) ;
2011-07-30 20:49:36 +00:00
Global . Emulator . ResetFrameCounter ( ) ;
}
2011-07-22 01:14:13 +00:00
if ( record )
{
2012-09-03 20:17:57 +00:00
Global . MovieSession . Movie . StartRecording ( ) ;
2011-07-22 01:14:13 +00:00
ReadOnly = false ;
}
else
{
2011-09-03 18:07:30 +00:00
Global . MovieSession . Movie . StartPlayback ( ) ;
2011-07-22 01:14:13 +00:00
}
SetMainformMovieInfo ( ) ;
2011-08-30 00:26:14 +00:00
TAStudio1 . Restart ( ) ;
2012-10-29 22:57:15 +00:00
VirtualPadForm1 . Restart ( ) ;
2011-07-22 01:14:13 +00:00
}
public void SetMainformMovieInfo ( )
{
2012-09-03 19:42:53 +00:00
if ( Global . MovieSession . Movie . IsPlaying )
2011-07-22 01:14:13 +00:00
{
2011-09-03 18:07:30 +00:00
Text = DisplayNameForSystem ( Global . Game . System ) + " - " + Global . Game . Name + " - " + Path . GetFileName ( Global . MovieSession . Movie . Filename ) ;
2011-07-22 01:14:13 +00:00
PlayRecordStatus . Image = BizHawk . MultiClient . Properties . Resources . Play ;
PlayRecordStatus . ToolTipText = "Movie is in playback mode" ;
2012-09-29 22:37:34 +00:00
PlayRecordStatus . Visible = true ;
2011-07-22 01:14:13 +00:00
}
2012-09-03 19:42:53 +00:00
else if ( Global . MovieSession . Movie . IsRecording )
2011-07-22 01:14:13 +00:00
{
2011-09-03 18:07:30 +00:00
Text = DisplayNameForSystem ( Global . Game . System ) + " - " + Global . Game . Name + " - " + Path . GetFileName ( Global . MovieSession . Movie . Filename ) ;
2011-07-22 01:14:13 +00:00
PlayRecordStatus . Image = BizHawk . MultiClient . Properties . Resources . RecordHS ;
PlayRecordStatus . ToolTipText = "Movie is in record mode" ;
2012-09-29 22:37:34 +00:00
PlayRecordStatus . Visible = true ;
2011-07-22 01:14:13 +00:00
}
2012-09-27 02:19:07 +00:00
else if ( ! Global . MovieSession . Movie . IsActive )
2011-07-22 01:14:13 +00:00
{
Text = DisplayNameForSystem ( Global . Game . System ) + " - " + Global . Game . Name ;
PlayRecordStatus . Image = BizHawk . MultiClient . Properties . Resources . Blank ;
2012-09-27 02:19:07 +00:00
PlayRecordStatus . ToolTipText = "No movie is active" ;
2012-09-29 22:37:34 +00:00
PlayRecordStatus . Visible = false ;
2011-07-22 01:14:13 +00:00
}
}
2012-05-28 00:44:27 +00:00
public void PlayMovie ( )
2011-07-22 01:14:13 +00:00
{
PlayMovie p = new PlayMovie ( ) ;
DialogResult d = p . ShowDialog ( ) ;
}
2012-05-28 00:44:27 +00:00
public void RecordMovie ( )
2011-07-22 01:14:13 +00:00
{
2012-11-24 22:14:05 +00:00
// put any BEETA quality cores here
2012-12-15 20:35:37 +00:00
if ( Global . Emulator is Emulation . Consoles . Nintendo . GBA . GBA | |
2012-12-28 03:40:08 +00:00
Global . Emulator is Emulation . Consoles . Sega . Genesis )
2012-11-24 22:14:05 +00:00
{
var result = MessageBox . Show
( this , "Thanks for using Bizhawk! The emulation core you have selected " +
"is currently BETA-status. We appreciate your help in testing Bizhawk. " +
"You can record a movie on this core if you'd like to, but expect to " +
"encounter bugs and sync problems. Continue?" , "BizHawk" , MessageBoxButtons . YesNo ) ;
if ( result ! = System . Windows . Forms . DialogResult . Yes )
return ;
}
2011-07-22 01:14:13 +00:00
RecordMovie r = new RecordMovie ( ) ;
r . ShowDialog ( ) ;
}
public void PlayMovieFromBeginning ( )
{
2012-09-03 19:42:53 +00:00
if ( Global . MovieSession . Movie . IsActive )
2011-07-22 01:14:13 +00:00
{
2012-10-01 14:39:52 +00:00
LoadRom ( CurrentlyOpenRom , true ) ;
2011-09-04 19:06:18 +00:00
if ( Global . MovieSession . Movie . StartsFromSavestate )
{
LoadStateFile ( Global . MovieSession . Movie . Filename , Path . GetFileName ( Global . MovieSession . Movie . Filename ) ) ;
Global . Emulator . ResetFrameCounter ( ) ;
}
2011-09-03 18:07:30 +00:00
Global . MovieSession . Movie . StartPlayback ( ) ;
2011-07-22 01:14:13 +00:00
SetMainformMovieInfo ( ) ;
2012-04-16 08:18:41 +00:00
Global . OSD . AddMessage ( "Replaying movie file in read-only mode" ) ;
2011-09-05 17:38:54 +00:00
Global . MainForm . ReadOnly = true ;
2011-07-22 01:14:13 +00:00
}
}
2011-07-22 01:34:21 +00:00
public void StopMovie ( )
{
string message = "Movie " ;
2012-09-03 19:42:53 +00:00
if ( Global . MovieSession . Movie . IsRecording )
{
2011-07-22 01:34:21 +00:00
message + = "recording " ;
2012-09-03 19:42:53 +00:00
}
else if ( Global . MovieSession . Movie . IsPlaying )
{
2011-07-22 01:34:21 +00:00
message + = "playback " ;
2012-09-03 19:42:53 +00:00
}
2011-07-22 01:34:21 +00:00
message + = "stopped." ;
2012-09-03 19:42:53 +00:00
if ( Global . MovieSession . Movie . IsActive )
2011-07-22 01:34:21 +00:00
{
2012-09-03 19:42:53 +00:00
Global . MovieSession . Movie . Stop ( ) ;
2012-04-16 08:18:41 +00:00
Global . OSD . AddMessage ( message ) ;
2011-08-17 23:53:05 +00:00
Global . MainForm . ReadOnly = true ;
2012-09-27 02:19:07 +00:00
SetMainformMovieInfo ( ) ;
2011-07-22 01:34:21 +00:00
}
}
2011-07-31 01:15:14 +00:00
2011-08-20 19:27:00 +00:00
private bool HandleMovieLoadState ( string path )
2011-07-31 01:15:14 +00:00
{
//Note, some of the situations in these IF's may be identical and could be combined but I intentionally separated it out for clarity
2012-09-03 19:42:53 +00:00
if ( ! Global . MovieSession . Movie . IsActive )
2012-08-25 22:18:54 +00:00
{
2011-07-31 16:41:27 +00:00
return true ;
2012-08-25 22:18:54 +00:00
}
2012-10-13 21:30:19 +00:00
2012-09-03 19:42:53 +00:00
else if ( Global . MovieSession . Movie . IsRecording )
2011-07-31 01:15:14 +00:00
{
2012-10-13 21:30:19 +00:00
2011-07-31 01:15:14 +00:00
if ( ReadOnly )
{
2011-09-03 18:07:30 +00:00
if ( ! Global . MovieSession . Movie . CheckTimeLines ( path , false ) )
2012-08-25 22:18:54 +00:00
{
2011-07-31 16:41:27 +00:00
return false ; //Timeline/GUID error
2012-08-25 22:18:54 +00:00
}
2011-07-31 16:41:27 +00:00
else
2011-07-31 01:15:14 +00:00
{
2011-09-03 18:07:30 +00:00
Global . MovieSession . Movie . WriteMovie ( ) ;
2012-10-29 00:40:26 +00:00
Global . MovieSession . Movie . SwitchToPlay ( ) ;
2011-07-31 01:15:14 +00:00
SetMainformMovieInfo ( ) ;
}
}
else
{
2011-09-03 18:07:30 +00:00
if ( ! Global . MovieSession . Movie . CheckTimeLines ( path , true ) )
2012-08-25 22:18:54 +00:00
{
2011-07-31 17:35:02 +00:00
return false ; //GUID Error
2012-08-25 22:18:54 +00:00
}
2011-09-03 18:07:30 +00:00
Global . MovieSession . Movie . LoadLogFromSavestateText ( path ) ;
2011-07-31 01:15:14 +00:00
}
}
2012-08-25 22:18:54 +00:00
2012-09-03 19:42:53 +00:00
else if ( Global . MovieSession . Movie . IsPlaying & & ! Global . MovieSession . Movie . IsFinished )
2011-07-31 01:15:14 +00:00
{
if ( ReadOnly )
{
2011-09-03 18:07:30 +00:00
if ( ! Global . MovieSession . Movie . CheckTimeLines ( path , false ) )
2012-08-25 22:18:54 +00:00
{
2011-07-31 16:41:27 +00:00
return false ; //Timeline/GUID error
2012-08-25 22:18:54 +00:00
}
2011-07-31 16:41:27 +00:00
//Frame loop automatically handles the rewinding effect based on Global.Emulator.Frame so nothing else is needed here
2011-07-31 01:15:14 +00:00
}
else
{
2011-09-03 18:07:30 +00:00
if ( ! Global . MovieSession . Movie . CheckTimeLines ( path , true ) )
2012-08-25 22:18:54 +00:00
{
2011-07-31 17:35:02 +00:00
return false ; //GUID Error
2012-08-25 22:18:54 +00:00
}
2012-09-03 20:17:57 +00:00
Global . MovieSession . Movie . SwitchToRecord ( ) ;
2011-07-31 01:15:14 +00:00
SetMainformMovieInfo ( ) ;
2011-09-03 18:07:30 +00:00
Global . MovieSession . Movie . LoadLogFromSavestateText ( path ) ;
2011-07-31 01:15:14 +00:00
}
}
2012-09-03 19:42:53 +00:00
else if ( Global . MovieSession . Movie . IsFinished )
2011-07-31 01:15:14 +00:00
{
if ( ReadOnly )
{
{
2011-09-03 18:07:30 +00:00
if ( ! Global . MovieSession . Movie . CheckTimeLines ( path , false ) )
2012-08-25 22:18:54 +00:00
{
2011-07-31 16:41:27 +00:00
return false ; //Timeline/GUID error
2012-08-25 22:18:54 +00:00
}
2012-09-03 19:42:53 +00:00
else if ( Global . MovieSession . Movie . IsFinished ) //TimeLine check can change a movie to finished, hence the check here (not a good design)
2012-08-25 22:18:54 +00:00
{
2011-09-29 01:46:35 +00:00
Global . MovieSession . LatchInputFromPlayer ( Global . MovieInputSourceAdapter ) ;
2012-08-25 22:18:54 +00:00
}
2011-09-29 01:46:35 +00:00
else
{
2012-10-29 00:40:26 +00:00
Global . MovieSession . Movie . SwitchToPlay ( ) ;
2011-09-29 01:46:35 +00:00
SetMainformMovieInfo ( ) ;
}
2011-07-31 01:15:14 +00:00
}
}
else
{
{
2011-09-03 18:07:30 +00:00
if ( ! Global . MovieSession . Movie . CheckTimeLines ( path , true ) )
2012-08-25 22:18:54 +00:00
{
2011-07-31 17:35:02 +00:00
return false ; //GUID Error
2012-08-25 22:18:54 +00:00
}
2011-09-29 01:46:35 +00:00
else
{
2012-09-03 20:17:57 +00:00
Global . MovieSession . Movie . StartRecording ( ) ;
2011-09-29 01:46:35 +00:00
SetMainformMovieInfo ( ) ;
Global . MovieSession . Movie . LoadLogFromSavestateText ( path ) ;
}
2011-07-31 01:15:14 +00:00
}
}
}
2011-07-31 16:41:27 +00:00
return true ;
2011-07-31 01:15:14 +00:00
}
private void HandleMovieSaveState ( StreamWriter writer )
{
2012-09-03 19:42:53 +00:00
if ( Global . MovieSession . Movie . IsActive )
2011-07-31 01:15:14 +00:00
{
2011-09-03 18:07:30 +00:00
Global . MovieSession . Movie . DumpLogIntoSavestateText ( writer ) ;
2011-07-31 01:15:14 +00:00
}
}
2012-08-25 23:31:54 +00:00
private void HandleMovieOnFrameLoop ( )
{
2012-09-03 19:42:53 +00:00
if ( ! Global . MovieSession . Movie . IsActive )
2012-08-25 23:31:54 +00:00
{
2012-09-03 19:42:53 +00:00
Global . MovieSession . LatchInputFromPlayer ( Global . MovieInputSourceAdapter ) ;
}
2012-10-13 21:30:19 +00:00
2012-09-03 19:42:53 +00:00
else if ( Global . MovieSession . Movie . IsFinished )
{
if ( Global . Emulator . Frame < Global . MovieSession . Movie . Frames ) //This scenario can happen from rewinding (suddenly we are back in the movie, so hook back up to the movie
{
2012-10-29 00:40:26 +00:00
Global . MovieSession . Movie . SwitchToPlay ( ) ;
2012-09-03 19:42:53 +00:00
Global . MovieSession . LatchInputFromLog ( ) ;
}
else
{
Global . MovieSession . LatchInputFromPlayer ( Global . MovieInputSourceAdapter ) ;
}
}
else if ( Global . MovieSession . Movie . IsPlaying )
{
if ( Global . Emulator . Frame > = Global . MovieSession . Movie . Frames )
{
2012-11-01 03:53:12 +00:00
if ( TAStudio1 . IsHandleCreated & & ! TAStudio1 . IsDisposed )
{
Global . MovieSession . Movie . CaptureState ( ) ;
Global . MovieSession . LatchInputFromLog ( ) ;
Global . MovieSession . Movie . CommitFrame ( Global . Emulator . Frame , Global . MovieOutputHardpoint ) ;
}
else
{
Global . MovieSession . Movie . Finish ( ) ;
}
2012-09-03 19:42:53 +00:00
}
else
{
2012-08-25 23:31:54 +00:00
Global . MovieSession . Movie . CaptureState ( ) ;
2012-09-03 19:42:53 +00:00
Global . MovieSession . LatchInputFromLog ( ) ;
2013-03-09 23:37:37 +00:00
if ( Global . ClientControls [ "ClearFrame" ] )
{
Global . MovieSession . LatchInputFromPlayer ( Global . MovieInputSourceAdapter ) ;
ClearFrame ( ) ;
}
else if ( TAStudio1 . IsHandleCreated & & ! TAStudio1 . IsDisposed | | Global . Config . MoviePlaybackPokeMode )
2012-11-01 03:53:12 +00:00
{
2013-03-09 23:11:00 +00:00
Global . MovieSession . LatchInputFromPlayer ( Global . MovieInputSourceAdapter ) ;
2013-03-10 00:06:40 +00:00
MnemonicsGenerator mg = new MnemonicsGenerator ( ) ;
mg . SetSource ( Global . MovieOutputHardpoint ) ;
if ( ! mg . IsEmpty )
{
Global . MovieSession . LatchInputFromPlayer ( Global . MovieInputSourceAdapter ) ;
Global . MovieSession . Movie . PokeFrame ( Global . Emulator . Frame , mg . GetControllersAsMnemonic ( ) ) ;
}
else
{
Global . MovieSession . LatchInputFromLog ( ) ;
}
2012-11-01 03:53:12 +00:00
}
2012-09-03 19:42:53 +00:00
}
}
else if ( Global . MovieSession . Movie . IsRecording )
{
Global . MovieSession . Movie . CaptureState ( ) ;
if ( Global . MovieSession . MultiTrack . IsActive )
{
Global . MovieSession . LatchMultitrackPlayerInput ( Global . MovieInputSourceAdapter , Global . MultitrackRewiringControllerAdapter ) ;
}
else
{
2012-08-25 23:31:54 +00:00
Global . MovieSession . LatchInputFromPlayer ( Global . MovieInputSourceAdapter ) ;
2012-09-03 19:42:53 +00:00
}
//the movie session makes sure that the correct input has been read and merged to its MovieControllerAdapter;
//this has been wired to Global.MovieOutputHardpoint in RewireInputChain
Global . MovieSession . Movie . CommitFrame ( Global . Emulator . Frame , Global . MovieOutputHardpoint ) ;
2012-08-25 23:31:54 +00:00
}
}
2012-11-22 03:47:18 +00:00
//On movie load, these need to be set based on the contents of the movie file
private void SetSyncDependentSettings ( )
{
string str = "" ;
switch ( Global . Emulator . SystemId )
{
case "Coleco" :
str = Global . MovieSession . Movie . Header . GetHeaderLine ( MovieHeader . SKIPBIOS ) ;
if ( ! String . IsNullOrWhiteSpace ( str ) )
{
if ( str . ToLower ( ) = = "true" )
{
Global . Config . ColecoSkipBiosIntro = true ;
}
else
{
Global . Config . ColecoSkipBiosIntro = false ;
}
}
break ;
}
}
2011-07-22 01:14:13 +00:00
}
}