Gb_Apu_State.cpp (3467B)
1// Gb_Snd_Emu $vers. http://www.slack.net/~ant/ 2 3#include "Gb_Apu.h" 4 5#include <string.h> 6 7/* Copyright (C) 2007 Shay Green. This module is free software; you 8can redistribute it and/or modify it under the terms of the GNU Lesser 9General Public License as published by the Free Software Foundation; either 10version 2.1 of the License, or (at your option) any later version. This 11module is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 14details. You should have received a copy of the GNU Lesser General Public 15License along with this module; if not, write to the Free Software Foundation, 16Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ 17 18#include "blargg_source.h" 19 20#if GB_APU_CUSTOM_STATE 21 #define REFLECT( x, y ) (save ? (io->y) = (x) : (x) = (io->y) ) 22#else 23 #define REFLECT( x, y ) (save ? set_val( io->y, x ) : (void) ((x) = get_val( io->y ))) 24 25 static blargg_ulong get_val( byte const* p ) 26 { 27 return p [3] * 0x1000000 + p [2] * 0x10000 + p [1] * 0x100 + p [0]; 28 } 29 30 static void set_val( byte* p, blargg_ulong n ) 31 { 32 p [0] = (byte) (n ); 33 p [1] = (byte) (n >> 8); 34 p [2] = (byte) (n >> 16); 35 p [3] = (byte) (n >> 24); 36 } 37#endif 38 39inline const char* Gb_Apu::save_load( gb_apu_state_t* io, bool save ) 40{ 41 #if !GB_APU_CUSTOM_STATE 42 assert( sizeof (gb_apu_state_t) == 256 ); 43 #endif 44 45 int format = io->format0; 46 REFLECT( format, format ); 47 if ( format != io->format0 ) 48 return "Unsupported sound save state format"; 49 50 int version = 0; 51 REFLECT( version, version ); 52 53 // Registers and wave RAM 54 assert( regs_size == sizeof io->regs ); 55 if ( save ) 56 memcpy( io->regs, regs, sizeof io->regs ); 57 else 58 memcpy( regs, io->regs, sizeof regs ); 59 60 // Frame sequencer 61 REFLECT( frame_time, frame_time ); 62 REFLECT( frame_phase, frame_phase ); 63 64 REFLECT( square1.sweep_freq, sweep_freq ); 65 REFLECT( square1.sweep_delay, sweep_delay ); 66 REFLECT( square1.sweep_enabled, sweep_enabled ); 67 REFLECT( square1.sweep_neg, sweep_neg ); 68 69 REFLECT( noise.divider, noise_divider ); 70 REFLECT( wave.sample_buf, wave_buf ); 71 72 return 0; 73} 74 75// second function to avoid inline limits of some compilers 76inline void Gb_Apu::save_load2( gb_apu_state_t* io, bool save ) 77{ 78 for ( int i = osc_count; --i >= 0; ) 79 { 80 Gb_Osc& osc = *oscs [i]; 81 REFLECT( osc.delay, delay [i] ); 82 REFLECT( osc.length_ctr, length_ctr [i] ); 83 REFLECT( osc.phase, phase [i] ); 84 REFLECT( osc.enabled, enabled [i] ); 85 86 if ( i != 2 ) 87 { 88 int j = min( i, 2 ); 89 Gb_Env& env = STATIC_CAST(Gb_Env&,osc); 90 REFLECT( env.env_delay, env_delay [j] ); 91 REFLECT( env.volume, env_volume [j] ); 92 REFLECT( env.env_enabled, env_enabled [j] ); 93 } 94 } 95} 96 97void Gb_Apu::save_state( gb_apu_state_t* out ) 98{ 99 (void) save_load( out, true ); 100 save_load2( out, true ); 101 102 #if !GB_APU_CUSTOM_STATE 103 memset( out->unused, 0, sizeof out->unused ); 104 #endif 105} 106 107blargg_err_t Gb_Apu::load_state( gb_apu_state_t const& in ) 108{ 109 RETURN_ERR( save_load( CONST_CAST(gb_apu_state_t*,&in), false ) ); 110 save_load2( CONST_CAST(gb_apu_state_t*,&in), false ); 111 112 apply_stereo(); 113 synth_volume( 0 ); // suppress output for the moment 114 run_until_( last_time ); // get last_amp updated 115 apply_volume(); // now use correct volume 116 117 return 0; 118} 119