2014-06-12 23:57:23 +00:00
using System ;
using System.IO ;
using System.Text ;
using BizHawk.Common ;
namespace BizHawk.Client.Common
{
2014-06-29 03:03:27 +00:00
public partial class BkmMovie
2014-06-12 23:57:23 +00:00
{
private int _preloadFramecount ; // Not a a reliable number, used for preloading (when no log has yet been loaded), this is only for quick stat compilation for dialogs such as play movie
public void SaveAs ( string path )
{
Filename = path ;
if ( ! Loaded )
{
return ;
}
2017-05-17 18:18:26 +00:00
var directoryInfo = new FileInfo ( Filename ) . Directory ;
if ( directoryInfo ! = null )
2014-06-12 23:57:23 +00:00
{
2017-05-17 18:18:26 +00:00
Directory . CreateDirectory ( directoryInfo . FullName ) ;
2014-06-12 23:57:23 +00:00
}
Write ( Filename ) ;
}
public void Save ( )
{
if ( ! Loaded | | string . IsNullOrWhiteSpace ( Filename ) )
{
return ;
}
SaveAs ( Filename ) ;
_changes = false ;
}
public void SaveBackup ( )
{
if ( ! Loaded | | string . IsNullOrWhiteSpace ( Filename ) )
{
return ;
}
var backupName = Filename ;
2017-04-14 19:59:01 +00:00
backupName = backupName . Insert ( Filename . LastIndexOf ( "." ) , $".{DateTime.Now:yyyy-MM-dd HH.mm.ss}" ) ;
2014-06-12 23:57:23 +00:00
backupName = Path . Combine ( Global . Config . PathEntries [ "Global" , "Movie backups" ] . Path , Path . GetFileName ( backupName ) ) ;
2017-05-17 18:18:26 +00:00
var directoryInfo = new FileInfo ( backupName ) . Directory ;
if ( directoryInfo ! = null )
2014-06-12 23:57:23 +00:00
{
2017-05-17 18:18:26 +00:00
Directory . CreateDirectory ( directoryInfo . FullName ) ;
2014-06-12 23:57:23 +00:00
}
Write ( backupName ) ;
}
2015-08-05 22:00:39 +00:00
public bool Load ( bool preload )
2014-06-12 23:57:23 +00:00
{
var file = new FileInfo ( Filename ) ;
if ( file . Exists = = false )
{
Loaded = false ;
return false ;
}
Header . Clear ( ) ;
_log . Clear ( ) ;
using ( var sr = file . OpenText ( ) )
{
string line ;
while ( ( line = sr . ReadLine ( ) ) ! = null )
{
2017-05-10 11:45:23 +00:00
if ( line = = "" )
2014-06-12 23:57:23 +00:00
{
continue ;
}
if ( line . Contains ( "LoopOffset" ) )
{
try
{
_loopOffset = int . Parse ( line . Split ( new [ ] { ' ' } , 2 ) [ 1 ] ) ;
}
catch ( Exception )
{
continue ;
}
}
else if ( Header . ParseLineFromFile ( line ) )
{
continue ;
}
else if ( line . StartsWith ( "|" ) )
{
2014-06-14 21:37:51 +00:00
_log . Add ( line ) ;
2014-06-12 23:57:23 +00:00
}
else
{
Header . Comments . Add ( line ) ;
}
}
}
2017-04-14 19:59:01 +00:00
2014-06-20 00:39:46 +00:00
if ( Header . SavestateBinaryBase64Blob ! = null )
2017-04-14 19:59:01 +00:00
{
2014-06-20 00:39:46 +00:00
BinarySavestate = Convert . FromBase64String ( Header . SavestateBinaryBase64Blob ) ;
2017-04-14 19:59:01 +00:00
}
2014-06-12 23:57:23 +00:00
Loaded = true ;
2014-07-11 18:06:18 +00:00
_changes = false ;
2014-06-12 23:57:23 +00:00
return true ;
}
/// <summary>
/// Load Header information only for displaying file information in dialogs such as play movie
/// TODO - consider not loading the SavestateBinaryBase64Blob key?
/// </summary>
2014-06-14 19:13:21 +00:00
public bool PreLoadHeaderAndLength ( HawkFile hawkFile )
2014-06-12 23:57:23 +00:00
{
Loaded = false ;
var file = new FileInfo ( hawkFile . CanonicalFullPath ) ;
if ( file . Exists = = false )
{
return false ;
}
Header . Clear ( ) ;
_log . Clear ( ) ;
var origStreamPosn = hawkFile . GetStream ( ) . Position ;
hawkFile . GetStream ( ) . Position = 0 ; // Reset to start
// No using block because we're sharing the stream and need to give it back undisposed.
var sr = new StreamReader ( hawkFile . GetStream ( ) ) ;
2017-04-14 19:59:01 +00:00
for ( ; ; )
2014-06-12 23:57:23 +00:00
{
2017-04-14 19:59:01 +00:00
// read to first space (key/value delimeter), or pipe, or EOF
2014-06-12 23:57:23 +00:00
int first = sr . Read ( ) ;
2014-06-29 03:03:27 +00:00
if ( first = = - 1 )
{
break ;
} // EOF
2017-04-14 19:59:01 +00:00
if ( first = = '|' ) // pipe: begin input log
2014-06-12 23:57:23 +00:00
{
2017-04-14 19:59:01 +00:00
// NOTE - this code is a bit convoluted due to its predating the basic outline of the parser which was upgraded in may 2014
2014-06-29 03:03:27 +00:00
var line = '|' + sr . ReadLine ( ) ;
2014-06-12 23:57:23 +00:00
2017-04-14 19:59:01 +00:00
// how many bytes are left, total?
2014-06-12 23:57:23 +00:00
long remain = sr . BaseStream . Length - sr . BaseStream . Position ;
2017-04-14 19:59:01 +00:00
// try to find out whether we use \r\n or \n
// but only look for 1K characters.
2014-06-12 23:57:23 +00:00
bool usesR = false ;
for ( int i = 0 ; i < 1024 ; i + + )
{
int c = sr . Read ( ) ;
if ( c = = - 1 )
2017-05-17 18:18:26 +00:00
{
2014-06-12 23:57:23 +00:00
break ;
2017-05-17 18:18:26 +00:00
}
2014-06-12 23:57:23 +00:00
if ( c = = '\r' )
{
usesR = true ;
break ;
}
2017-05-17 18:18:26 +00:00
2014-06-12 23:57:23 +00:00
if ( c = = '\n' )
2017-05-17 18:18:26 +00:00
{
2014-06-12 23:57:23 +00:00
break ;
2017-05-17 18:18:26 +00:00
}
2014-06-12 23:57:23 +00:00
}
2017-04-14 19:59:01 +00:00
int lineLen = line . Length + 1 ; // account for \n
if ( usesR )
{
lineLen + + ; // account for \r
}
2014-06-12 23:57:23 +00:00
2017-04-14 19:59:01 +00:00
_preloadFramecount = ( int ) ( remain / lineLen ) ; // length is remaining bytes / length per line
_preloadFramecount + + ; // account for the current line
2014-06-12 23:57:23 +00:00
break ;
}
else
{
2017-04-14 19:59:01 +00:00
// a header line. finish reading key token, to make sure it isn't one of the FORBIDDEN keys
2014-06-29 03:03:27 +00:00
var sbLine = new StringBuilder ( ) ;
2014-06-12 23:57:23 +00:00
sbLine . Append ( ( char ) first ) ;
2017-04-14 19:59:01 +00:00
for ( ; ; )
2014-06-12 23:57:23 +00:00
{
int c = sr . Read ( ) ;
2017-05-17 18:18:26 +00:00
if ( c = = - 1 | | c = = '\n' | | c = = ' ' )
{
break ;
}
2014-06-12 23:57:23 +00:00
sbLine . Append ( ( char ) c ) ;
}
var line = sbLine . ToString ( ) ;
2017-04-14 19:59:01 +00:00
// ignore these suckers, theyre way too big for preloading. seriously, we will get out of memory errors.
2014-06-12 23:57:23 +00:00
var skip = line = = HeaderKeys . SAVESTATEBINARYBASE64BLOB ;
if ( skip )
{
2017-04-14 19:59:01 +00:00
// skip remainder of the line
2014-06-12 23:57:23 +00:00
sr . DiscardBufferedData ( ) ;
var stream = sr . BaseStream ;
2017-04-14 19:59:01 +00:00
for ( ; ; )
2014-06-12 23:57:23 +00:00
{
int c = stream . ReadByte ( ) ;
2017-05-17 18:18:26 +00:00
if ( c = = - 1 | | c = = '\n' )
{
break ;
}
2014-06-12 23:57:23 +00:00
}
2017-04-14 19:59:01 +00:00
// proceed to next line
2014-06-12 23:57:23 +00:00
continue ;
}
2014-06-29 03:03:27 +00:00
var remainder = sr . ReadLine ( ) ;
2014-06-12 23:57:23 +00:00
sbLine . Append ( ' ' ) ;
sbLine . Append ( remainder ) ;
line = sbLine . ToString ( ) ;
if ( string . IsNullOrWhiteSpace ( line ) | | Header . ParseLineFromFile ( line ) )
{
continue ;
}
Header . Comments . Add ( line ) ;
}
}
hawkFile . GetStream ( ) . Position = origStreamPosn ;
return true ;
}
private void Write ( string fn )
{
2017-04-14 19:59:01 +00:00
Header . SavestateBinaryBase64Blob = BinarySavestate ! = null
? Convert . ToBase64String ( BinarySavestate )
: null ;
2014-06-20 00:39:46 +00:00
2014-06-12 23:57:23 +00:00
using ( var fs = new FileStream ( fn , FileMode . Create , FileAccess . Write , FileShare . Read ) )
{
using ( var sw = new StreamWriter ( fs ) )
{
sw . Write ( Header . ToString ( ) ) ;
// TODO: clean this up
if ( _loopOffset . HasValue )
{
sw . WriteLine ( "LoopOffset " + _loopOffset ) ;
}
foreach ( var input in _log )
{
sw . WriteLine ( input ) ;
}
}
}
2014-07-11 18:06:18 +00:00
_changes = false ;
2014-06-12 23:57:23 +00:00
}
}
}