diff demo/save_state.c @ 0:e38dacceb958

initial import
author Robert McIntyre <rlm@mit.edu>
date Fri, 21 Oct 2011 05:53:11 -0700
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/demo/save_state.c	Fri Oct 21 05:53:11 2011 -0700
     1.3 @@ -0,0 +1,107 @@
     1.4 +/* Loads "test.spc", skips 5 seconds, saves exact emulator state to "state.bin",
     1.5 +hen records 5 seconds to "first.wav". When run again, loads this state back into
     1.6 +emulator and records 5 seconds to "second.wav". These two wave files should
     1.7 +be identical.
     1.8 +
     1.9 +Usage: save_state [test.spc]
    1.10 +*/
    1.11 +
    1.12 +#include "snes_spc/spc.h"
    1.13 +
    1.14 +#include "wave_writer.h"
    1.15 +#include "demo_util.h" /* error(), load_file() */
    1.16 +
    1.17 +static SNES_SPC* snes_spc;
    1.18 +
    1.19 +void record_wav( const char* path, int secs )
    1.20 +{
    1.21 +	/* Start writing wave file */
    1.22 +	wave_open( spc_sample_rate, path );
    1.23 +	wave_enable_stereo();
    1.24 +	while ( wave_sample_count() < secs * spc_sample_rate * 2 )
    1.25 +	{
    1.26 +		/* Play into buffer */
    1.27 +		#define BUF_SIZE 2048
    1.28 +		short buf [BUF_SIZE];
    1.29 +		error( spc_play( snes_spc, BUF_SIZE, buf ) );
    1.30 +		
    1.31 +		wave_write( buf, BUF_SIZE );
    1.32 +	}
    1.33 +	wave_close();
    1.34 +}
    1.35 +
    1.36 +void state_save( unsigned char** out, void* in, size_t size )
    1.37 +{
    1.38 +	memcpy( *out, in, size );
    1.39 +	*out += size;
    1.40 +}
    1.41 +
    1.42 +void make_save_state( const char* path )
    1.43 +{
    1.44 +	/* Load SPC */
    1.45 +	long spc_size;
    1.46 +	void* spc = load_file( path, &spc_size );
    1.47 +	error( spc_load_spc( snes_spc, spc, spc_size ) );
    1.48 +	free( spc );
    1.49 +	spc_clear_echo( snes_spc );
    1.50 +	
    1.51 +	/* Skip several seconds */
    1.52 +	error( spc_play( snes_spc, 5 * spc_sample_rate * 2, 0 ) );
    1.53 +	
    1.54 +	/* Save state to file */
    1.55 +	{
    1.56 +		static unsigned char state [spc_state_size]; /* buffer large enough for data */
    1.57 +		unsigned char* out = state;
    1.58 +		spc_copy_state( snes_spc, &out, state_save );
    1.59 +		write_file( "state.bin", state, out - state );
    1.60 +	}
    1.61 +	
    1.62 +	record_wav( "first.wav", 5 );
    1.63 +}
    1.64 +
    1.65 +void state_load( unsigned char** in, void* out, size_t size )
    1.66 +{
    1.67 +	memcpy( out, *in, size );
    1.68 +	*in += size;
    1.69 +}
    1.70 +
    1.71 +void use_save_state()
    1.72 +{
    1.73 +	/* Load state into memory */
    1.74 +	long state_size;
    1.75 +	unsigned char* state = load_file( "state.bin", &state_size );
    1.76 +	
    1.77 +	/* Load into emulator */
    1.78 +	unsigned char* in = state;
    1.79 +	spc_copy_state( snes_spc, &in, state_load );
    1.80 +	assert( in  - state <= state_size ); /* be sure it didn't read past end */
    1.81 +	
    1.82 +	record_wav( "second.wav", 5 );
    1.83 +}
    1.84 +
    1.85 +int file_exists( const char* path )
    1.86 +{
    1.87 +	FILE* file = fopen( path, "rb" );
    1.88 +	if ( !file )
    1.89 +		return 0;
    1.90 +	
    1.91 +	fclose( file );
    1.92 +	return 1;
    1.93 +}
    1.94 +
    1.95 +int main( int argc, char** argv )
    1.96 +{
    1.97 +	snes_spc = spc_new();
    1.98 +	if ( !snes_spc ) error( "Out of memory" );
    1.99 +	
   1.100 +	/* Make new state if it doesn't exist, otherwise load it and
   1.101 +	record to wave file */
   1.102 +	if ( !file_exists( "state.bin" ) )
   1.103 +		make_save_state( (argc > 1) ? argv [1] : "test.spc" );
   1.104 +	else
   1.105 +		use_save_state();
   1.106 +	
   1.107 +	spc_delete( snes_spc );
   1.108 +	
   1.109 +	return 0;
   1.110 +}