annotate 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
rev   line source
rlm@0 1 /* Loads "test.spc", skips 5 seconds, saves exact emulator state to "state.bin",
rlm@0 2 hen records 5 seconds to "first.wav". When run again, loads this state back into
rlm@0 3 emulator and records 5 seconds to "second.wav". These two wave files should
rlm@0 4 be identical.
rlm@0 5
rlm@0 6 Usage: save_state [test.spc]
rlm@0 7 */
rlm@0 8
rlm@0 9 #include "snes_spc/spc.h"
rlm@0 10
rlm@0 11 #include "wave_writer.h"
rlm@0 12 #include "demo_util.h" /* error(), load_file() */
rlm@0 13
rlm@0 14 static SNES_SPC* snes_spc;
rlm@0 15
rlm@0 16 void record_wav( const char* path, int secs )
rlm@0 17 {
rlm@0 18 /* Start writing wave file */
rlm@0 19 wave_open( spc_sample_rate, path );
rlm@0 20 wave_enable_stereo();
rlm@0 21 while ( wave_sample_count() < secs * spc_sample_rate * 2 )
rlm@0 22 {
rlm@0 23 /* Play into buffer */
rlm@0 24 #define BUF_SIZE 2048
rlm@0 25 short buf [BUF_SIZE];
rlm@0 26 error( spc_play( snes_spc, BUF_SIZE, buf ) );
rlm@0 27
rlm@0 28 wave_write( buf, BUF_SIZE );
rlm@0 29 }
rlm@0 30 wave_close();
rlm@0 31 }
rlm@0 32
rlm@0 33 void state_save( unsigned char** out, void* in, size_t size )
rlm@0 34 {
rlm@0 35 memcpy( *out, in, size );
rlm@0 36 *out += size;
rlm@0 37 }
rlm@0 38
rlm@0 39 void make_save_state( const char* path )
rlm@0 40 {
rlm@0 41 /* Load SPC */
rlm@0 42 long spc_size;
rlm@0 43 void* spc = load_file( path, &spc_size );
rlm@0 44 error( spc_load_spc( snes_spc, spc, spc_size ) );
rlm@0 45 free( spc );
rlm@0 46 spc_clear_echo( snes_spc );
rlm@0 47
rlm@0 48 /* Skip several seconds */
rlm@0 49 error( spc_play( snes_spc, 5 * spc_sample_rate * 2, 0 ) );
rlm@0 50
rlm@0 51 /* Save state to file */
rlm@0 52 {
rlm@0 53 static unsigned char state [spc_state_size]; /* buffer large enough for data */
rlm@0 54 unsigned char* out = state;
rlm@0 55 spc_copy_state( snes_spc, &out, state_save );
rlm@0 56 write_file( "state.bin", state, out - state );
rlm@0 57 }
rlm@0 58
rlm@0 59 record_wav( "first.wav", 5 );
rlm@0 60 }
rlm@0 61
rlm@0 62 void state_load( unsigned char** in, void* out, size_t size )
rlm@0 63 {
rlm@0 64 memcpy( out, *in, size );
rlm@0 65 *in += size;
rlm@0 66 }
rlm@0 67
rlm@0 68 void use_save_state()
rlm@0 69 {
rlm@0 70 /* Load state into memory */
rlm@0 71 long state_size;
rlm@0 72 unsigned char* state = load_file( "state.bin", &state_size );
rlm@0 73
rlm@0 74 /* Load into emulator */
rlm@0 75 unsigned char* in = state;
rlm@0 76 spc_copy_state( snes_spc, &in, state_load );
rlm@0 77 assert( in - state <= state_size ); /* be sure it didn't read past end */
rlm@0 78
rlm@0 79 record_wav( "second.wav", 5 );
rlm@0 80 }
rlm@0 81
rlm@0 82 int file_exists( const char* path )
rlm@0 83 {
rlm@0 84 FILE* file = fopen( path, "rb" );
rlm@0 85 if ( !file )
rlm@0 86 return 0;
rlm@0 87
rlm@0 88 fclose( file );
rlm@0 89 return 1;
rlm@0 90 }
rlm@0 91
rlm@0 92 int main( int argc, char** argv )
rlm@0 93 {
rlm@0 94 snes_spc = spc_new();
rlm@0 95 if ( !snes_spc ) error( "Out of memory" );
rlm@0 96
rlm@0 97 /* Make new state if it doesn't exist, otherwise load it and
rlm@0 98 record to wave file */
rlm@0 99 if ( !file_exists( "state.bin" ) )
rlm@0 100 make_save_state( (argc > 1) ? argv [1] : "test.spc" );
rlm@0 101 else
rlm@0 102 use_save_state();
rlm@0 103
rlm@0 104 spc_delete( snes_spc );
rlm@0 105
rlm@0 106 return 0;
rlm@0 107 }