rlm@0: /* Loads "test.spc", skips 5 seconds, saves exact emulator state to "state.bin", rlm@0: hen records 5 seconds to "first.wav". When run again, loads this state back into rlm@0: emulator and records 5 seconds to "second.wav". These two wave files should rlm@0: be identical. rlm@0: rlm@0: Usage: save_state [test.spc] rlm@0: */ rlm@0: rlm@0: #include "snes_spc/spc.h" rlm@0: rlm@0: #include "wave_writer.h" rlm@0: #include "demo_util.h" /* error(), load_file() */ rlm@0: rlm@0: static SNES_SPC* snes_spc; rlm@0: rlm@0: void record_wav( const char* path, int secs ) rlm@0: { rlm@0: /* Start writing wave file */ rlm@0: wave_open( spc_sample_rate, path ); rlm@0: wave_enable_stereo(); rlm@0: while ( wave_sample_count() < secs * spc_sample_rate * 2 ) rlm@0: { rlm@0: /* Play into buffer */ rlm@0: #define BUF_SIZE 2048 rlm@0: short buf [BUF_SIZE]; rlm@0: error( spc_play( snes_spc, BUF_SIZE, buf ) ); rlm@0: rlm@0: wave_write( buf, BUF_SIZE ); rlm@0: } rlm@0: wave_close(); rlm@0: } rlm@0: rlm@0: void state_save( unsigned char** out, void* in, size_t size ) rlm@0: { rlm@0: memcpy( *out, in, size ); rlm@0: *out += size; rlm@0: } rlm@0: rlm@0: void make_save_state( const char* path ) rlm@0: { rlm@0: /* Load SPC */ rlm@0: long spc_size; rlm@0: void* spc = load_file( path, &spc_size ); rlm@0: error( spc_load_spc( snes_spc, spc, spc_size ) ); rlm@0: free( spc ); rlm@0: spc_clear_echo( snes_spc ); rlm@0: rlm@0: /* Skip several seconds */ rlm@0: error( spc_play( snes_spc, 5 * spc_sample_rate * 2, 0 ) ); rlm@0: rlm@0: /* Save state to file */ rlm@0: { rlm@0: static unsigned char state [spc_state_size]; /* buffer large enough for data */ rlm@0: unsigned char* out = state; rlm@0: spc_copy_state( snes_spc, &out, state_save ); rlm@0: write_file( "state.bin", state, out - state ); rlm@0: } rlm@0: rlm@0: record_wav( "first.wav", 5 ); rlm@0: } rlm@0: rlm@0: void state_load( unsigned char** in, void* out, size_t size ) rlm@0: { rlm@0: memcpy( out, *in, size ); rlm@0: *in += size; rlm@0: } rlm@0: rlm@0: void use_save_state() rlm@0: { rlm@0: /* Load state into memory */ rlm@0: long state_size; rlm@0: unsigned char* state = load_file( "state.bin", &state_size ); rlm@0: rlm@0: /* Load into emulator */ rlm@0: unsigned char* in = state; rlm@0: spc_copy_state( snes_spc, &in, state_load ); rlm@0: assert( in - state <= state_size ); /* be sure it didn't read past end */ rlm@0: rlm@0: record_wav( "second.wav", 5 ); rlm@0: } rlm@0: rlm@0: int file_exists( const char* path ) rlm@0: { rlm@0: FILE* file = fopen( path, "rb" ); rlm@0: if ( !file ) rlm@0: return 0; rlm@0: rlm@0: fclose( file ); rlm@0: return 1; rlm@0: } rlm@0: rlm@0: int main( int argc, char** argv ) rlm@0: { rlm@0: snes_spc = spc_new(); rlm@0: if ( !snes_spc ) error( "Out of memory" ); rlm@0: rlm@0: /* Make new state if it doesn't exist, otherwise load it and rlm@0: record to wave file */ rlm@0: if ( !file_exists( "state.bin" ) ) rlm@0: make_save_state( (argc > 1) ? argv [1] : "test.spc" ); rlm@0: else rlm@0: use_save_state(); rlm@0: rlm@0: spc_delete( snes_spc ); rlm@0: rlm@0: return 0; rlm@0: }