cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

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