2014-07-07 18:00:25 +00:00
using System ;
2014-11-01 13:37:18 +00:00
using System.Collections.Generic ;
2014-07-07 18:00:25 +00:00
using System.IO ;
2014-07-07 19:32:37 +00:00
using System.Linq ;
2014-11-01 13:37:18 +00:00
using System.Text ;
2014-07-07 18:00:25 +00:00
using BizHawk.Common ;
2014-07-07 19:32:37 +00:00
using BizHawk.Common.CollectionExtensions ;
using BizHawk.Common.IOExtensions ;
2015-01-03 02:29:55 +00:00
using System.Diagnostics ;
using System.ComponentModel ;
2014-07-07 18:00:25 +00:00
namespace BizHawk.Client.Common
{
public partial class TasMovie
{
2014-10-14 18:09:30 +00:00
public Func < string > ClientSettingsForSave { get ; set ; }
public Action < string > GetClientSettingsOnLoad { get ; set ; }
2015-01-03 02:29:55 +00:00
2015-02-24 20:15:43 +00:00
private const double PROGRESS_STEP = 100 / 12 ; // TODO hardcoded for now, there might be a better way of doing this
2015-01-03 02:29:55 +00:00
2015-02-24 20:15:43 +00:00
private double _totalProgress = 0 ;
2014-10-14 18:09:30 +00:00
2015-02-24 20:15:43 +00:00
private void ReportProgress ( double percent )
2014-07-07 18:00:25 +00:00
{
2015-02-24 20:15:43 +00:00
if ( _progressReportWorker ! = null )
{
_totalProgress + = percent ;
_progressReportWorker . ReportProgress ( ( int ) _totalProgress ) ;
}
}
2015-01-03 02:29:55 +00:00
2015-02-24 20:15:43 +00:00
protected override void Write ( string fn )
{
_totalProgress = 0 ;
2015-01-03 02:29:55 +00:00
2014-07-07 18:00:25 +00:00
var file = new FileInfo ( fn ) ;
if ( ! file . Directory . Exists )
{
Directory . CreateDirectory ( file . Directory . ToString ( ) ) ;
}
2014-10-12 04:24:31 +00:00
using ( var bs = new BinaryStateSaver ( fn , false ) )
2014-07-07 18:00:25 +00:00
{
bs . PutLump ( BinaryStateLump . Movieheader , tw = > tw . WriteLine ( Header . ToString ( ) ) ) ;
2015-02-24 20:15:43 +00:00
ReportProgress ( PROGRESS_STEP ) ;
bs . PutLump ( BinaryStateLump . Comments , tw = > tw . WriteLine ( CommentsString ( ) ) ) ;
ReportProgress ( PROGRESS_STEP ) ;
bs . PutLump ( BinaryStateLump . Subtitles , tw = > tw . WriteLine ( Subtitles . ToString ( ) ) ) ;
ReportProgress ( PROGRESS_STEP ) ;
bs . PutLump ( BinaryStateLump . SyncSettings , tw = > tw . WriteLine ( SyncSettingsJson ) ) ;
ReportProgress ( PROGRESS_STEP ) ;
bs . PutLump ( BinaryStateLump . Input , tw = > tw . WriteLine ( RawInputLog ( ) ) ) ;
ReportProgress ( PROGRESS_STEP ) ;
2014-07-07 18:00:25 +00:00
2014-11-01 13:37:18 +00:00
// TasProj extras
2015-03-03 06:56:45 +00:00
bs . PutLump ( BinaryStateLump . StateHistorySettings , tw = > tw . WriteLine ( StateManager . Settings . ToString ( ) ) ) ;
2015-02-24 20:15:43 +00:00
ReportProgress ( PROGRESS_STEP ) ;
2015-03-02 23:43:52 +00:00
if ( StateManager . Settings . SaveStateHistory )
2014-07-10 22:44:44 +00:00
{
2015-03-03 06:56:45 +00:00
bs . PutLump ( BinaryStateLump . StateHistory , ( BinaryWriter bw ) = > StateManager . Save ( bw ) ) ;
2015-02-24 20:15:43 +00:00
}
ReportProgress ( PROGRESS_STEP ) ;
2014-07-10 22:44:44 +00:00
2015-02-24 20:15:43 +00:00
bs . PutLump ( BinaryStateLump . LagLog , ( BinaryWriter bw ) = > LagLog . Save ( bw ) ) ;
ReportProgress ( PROGRESS_STEP ) ;
bs . PutLump ( BinaryStateLump . Markers , tw = > tw . WriteLine ( Markers . ToString ( ) ) ) ;
ReportProgress ( PROGRESS_STEP ) ;
2014-07-07 19:32:37 +00:00
2014-07-07 18:00:25 +00:00
if ( StartsFromSavestate )
{
if ( TextSavestate ! = null )
{
bs . PutLump ( BinaryStateLump . CorestateText , ( TextWriter tw ) = > tw . Write ( TextSavestate ) ) ;
}
else
{
bs . PutLump ( BinaryStateLump . Corestate , ( BinaryWriter bw ) = > bw . Write ( BinarySavestate ) ) ;
}
2015-02-24 20:15:43 +00:00
}
2015-07-26 19:48:12 +00:00
else if ( StartsFromSaveRam )
{
bs . PutLump ( BinaryStateLump . MovieSaveRam , ( BinaryWriter bw ) = > bw . Write ( SaveRam ) ) ;
}
2015-02-24 20:15:43 +00:00
ReportProgress ( PROGRESS_STEP ) ;
2014-10-14 18:09:30 +00:00
if ( ClientSettingsForSave ! = null )
{
var clientSettingsJson = ClientSettingsForSave ( ) ;
bs . PutLump ( BinaryStateLump . ClientSettings , ( TextWriter tw ) = > tw . Write ( clientSettingsJson ) ) ;
2015-02-24 20:15:43 +00:00
}
ReportProgress ( PROGRESS_STEP ) ;
2014-11-01 13:37:18 +00:00
if ( VerificationLog . Any ( ) )
{
bs . PutLump ( BinaryStateLump . VerificationLog , tw = > tw . WriteLine ( InputLogToString ( VerificationLog ) ) ) ;
2015-02-24 20:15:43 +00:00
}
2015-07-19 02:20:38 +00:00
if ( Branches . Any ( ) )
{
2015-07-19 19:57:40 +00:00
Branches . Save ( bs ) ;
2015-07-19 02:20:38 +00:00
}
2015-02-24 20:15:43 +00:00
ReportProgress ( PROGRESS_STEP ) ;
2014-07-07 18:00:25 +00:00
}
Changes = false ;
}
2015-08-05 22:00:39 +00:00
public override bool Load ( bool preload )
2014-07-07 18:00:25 +00:00
{
var file = new FileInfo ( Filename ) ;
if ( ! file . Exists )
{
return false ;
}
using ( var bl = BinaryStateLoader . LoadAndDetect ( Filename , true ) )
{
if ( bl = = null )
{
return false ;
}
ClearBeforeLoad ( ) ;
2014-11-01 12:50:36 +00:00
ClearTasprojExtras ( ) ;
2014-07-07 18:00:25 +00:00
bl . GetLump ( BinaryStateLump . Movieheader , true , delegate ( TextReader tr )
{
string line ;
while ( ( line = tr . ReadLine ( ) ) ! = null )
{
if ( ! string . IsNullOrWhiteSpace ( line ) )
{
var pair = line . Split ( new [ ] { ' ' } , 2 , StringSplitOptions . RemoveEmptyEntries ) ;
if ( pair . Length > 1 )
{
Header . Add ( pair [ 0 ] , pair [ 1 ] ) ;
}
}
}
} ) ;
bl . GetLump ( BinaryStateLump . Comments , true , delegate ( TextReader tr )
{
string line ;
while ( ( line = tr . ReadLine ( ) ) ! = null )
{
if ( ! string . IsNullOrWhiteSpace ( line ) )
{
Comments . Add ( line ) ;
}
}
} ) ;
bl . GetLump ( BinaryStateLump . Subtitles , true , delegate ( TextReader tr )
{
string line ;
while ( ( line = tr . ReadLine ( ) ) ! = null )
{
if ( ! string . IsNullOrWhiteSpace ( line ) )
{
Subtitles . AddFromString ( line ) ;
}
}
} ) ;
bl . GetLump ( BinaryStateLump . SyncSettings , true , delegate ( TextReader tr )
{
string line ;
while ( ( line = tr . ReadLine ( ) ) ! = null )
{
if ( ! string . IsNullOrWhiteSpace ( line ) )
{
SyncSettingsJson = line ;
}
}
} ) ;
2014-11-15 21:49:58 +00:00
bl . GetLump ( BinaryStateLump . Input , true , delegate ( TextReader tr ) // Note: ExtractInputLog will clear Lag and State data potentially, this must come before loading those
2014-07-07 18:00:25 +00:00
{
var errorMessage = string . Empty ;
2014-11-13 23:49:58 +00:00
IsCountingRerecords = false ;
2014-07-07 18:00:25 +00:00
ExtractInputLog ( tr , out errorMessage ) ;
2014-11-13 23:49:58 +00:00
IsCountingRerecords = true ;
2014-07-07 18:00:25 +00:00
} ) ;
2014-07-10 22:07:50 +00:00
if ( StartsFromSavestate )
{
bl . GetCoreState (
2014-07-25 16:51:27 +00:00
delegate ( BinaryReader br , long length )
2014-07-10 22:07:50 +00:00
{
2014-07-25 16:51:27 +00:00
BinarySavestate = br . ReadBytes ( ( int ) length ) ;
2014-07-10 22:07:50 +00:00
} ,
delegate ( TextReader tr )
{
TextSavestate = tr . ReadToEnd ( ) ;
} ) ;
}
2015-07-26 19:48:12 +00:00
else if ( StartsFromSaveRam )
{
bl . GetLump ( BinaryStateLump . MovieSaveRam , false ,
delegate ( BinaryReader br , long length )
{
SaveRam = br . ReadBytes ( ( int ) length ) ;
} ) ;
}
2014-07-10 22:07:50 +00:00
// TasMovie enhanced information
2014-11-15 14:31:18 +00:00
if ( bl . HasLump ( BinaryStateLump . LagLog ) )
2014-07-07 19:32:37 +00:00
{
2014-11-15 14:31:18 +00:00
bl . GetLump ( BinaryStateLump . LagLog , false , delegate ( BinaryReader br , long length )
{
LagLog . Load ( br ) ;
} ) ;
}
2014-07-07 19:32:37 +00:00
2015-03-03 06:56:45 +00:00
bl . GetLump ( BinaryStateLump . StateHistorySettings , false , delegate ( TextReader tr )
2014-07-10 22:07:50 +00:00
{
2014-07-10 22:44:44 +00:00
StateManager . Settings . PopulateFromString ( tr . ReadToEnd ( ) ) ;
2014-07-10 22:07:50 +00:00
} ) ;
2015-08-05 22:00:39 +00:00
if ( ! preload )
2014-07-10 22:44:44 +00:00
{
2015-08-05 22:00:39 +00:00
if ( StateManager . Settings . SaveStateHistory )
2014-07-10 22:44:44 +00:00
{
2015-08-05 22:00:39 +00:00
bl . GetLump ( BinaryStateLump . StateHistory , false , delegate ( BinaryReader br , long length )
{
StateManager . Load ( br ) ;
} ) ;
}
// Movie should always have a state at frame 0.
if ( ! this . StartsFromSavestate )
StateManager . Capture ( ) ;
2014-07-10 22:44:44 +00:00
}
2014-07-10 22:07:50 +00:00
bl . GetLump ( BinaryStateLump . Markers , false , delegate ( TextReader tr )
2014-07-09 16:35:39 +00:00
{
string line ;
while ( ( line = tr . ReadLine ( ) ) ! = null )
{
if ( ! string . IsNullOrWhiteSpace ( line ) )
{
Markers . Add ( new TasMovieMarker ( line ) ) ;
}
}
} ) ;
2014-10-14 18:09:30 +00:00
2014-10-15 15:55:41 +00:00
if ( GetClientSettingsOnLoad ! = null & & bl . HasLump ( BinaryStateLump . ClientSettings ) )
2014-10-14 18:09:30 +00:00
{
string clientSettings = string . Empty ;
bl . GetLump ( BinaryStateLump . ClientSettings , true , delegate ( TextReader tr )
{
string line ;
while ( ( line = tr . ReadLine ( ) ) ! = null )
{
if ( ! string . IsNullOrWhiteSpace ( line ) )
{
clientSettings = line ;
}
}
} ) ;
GetClientSettingsOnLoad ( clientSettings ) ;
}
2014-11-01 13:37:18 +00:00
if ( bl . HasLump ( BinaryStateLump . VerificationLog ) )
{
bl . GetLump ( BinaryStateLump . VerificationLog , true , delegate ( TextReader tr )
{
VerificationLog . Clear ( ) ;
while ( true )
{
var line = tr . ReadLine ( ) ;
if ( string . IsNullOrEmpty ( line ) )
{
break ;
}
if ( line . StartsWith ( "|" ) )
{
VerificationLog . Add ( line ) ;
}
}
} ) ;
}
2015-07-19 02:20:38 +00:00
2015-07-19 19:57:40 +00:00
Branches . Load ( bl ) ;
2014-07-07 18:00:25 +00:00
}
2014-07-11 18:06:18 +00:00
Changes = false ;
2014-07-07 18:00:25 +00:00
return true ;
}
2014-11-01 12:50:36 +00:00
private void ClearTasprojExtras ( )
2014-07-07 18:00:25 +00:00
{
2014-07-07 19:32:37 +00:00
LagLog . Clear ( ) ;
StateManager . Clear ( ) ;
2014-11-01 12:50:36 +00:00
Markers . Clear ( ) ;
2015-03-03 18:22:54 +00:00
ChangeLog . ClearLog ( ) ;
2014-07-07 19:32:37 +00:00
}
2014-11-01 13:37:18 +00:00
private static string InputLogToString ( List < string > log )
{
var sb = new StringBuilder ( ) ;
foreach ( var record in log )
{
sb . AppendLine ( record ) ;
}
return sb . ToString ( ) ;
}
2014-07-07 18:00:25 +00:00
}
}