diff snes_spc/SNES_SPC_state.cpp @ 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/snes_spc/SNES_SPC_state.cpp	Fri Oct 21 05:53:11 2011 -0700
     1.3 @@ -0,0 +1,129 @@
     1.4 +// SPC emulation state save/load: copy_state(), save_spc()
     1.5 +// Separate file to avoid linking in unless needed
     1.6 +
     1.7 +// snes_spc 0.9.0. http://www.slack.net/~ant/
     1.8 +
     1.9 +#include "SNES_SPC.h"
    1.10 +
    1.11 +#if !SPC_NO_COPY_STATE_FUNCS
    1.12 +
    1.13 +#include <string.h>
    1.14 +
    1.15 +/* Copyright (C) 2004-2007 Shay Green. This module is free software; you
    1.16 +can redistribute it and/or modify it under the terms of the GNU Lesser
    1.17 +General Public License as published by the Free Software Foundation; either
    1.18 +version 2.1 of the License, or (at your option) any later version. This
    1.19 +module is distributed in the hope that it will be useful, but WITHOUT ANY
    1.20 +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    1.21 +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
    1.22 +details. You should have received a copy of the GNU Lesser General Public
    1.23 +License along with this module; if not, write to the Free Software Foundation,
    1.24 +Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
    1.25 +
    1.26 +#include "blargg_source.h"
    1.27 +
    1.28 +#define RAM         (m.ram.ram)
    1.29 +#define REGS        (m.smp_regs [0])
    1.30 +#define REGS_IN     (m.smp_regs [1])
    1.31 +
    1.32 +void SNES_SPC::save_regs( uint8_t out [reg_count] )
    1.33 +{
    1.34 +	// Use current timer counter values
    1.35 +	for ( int i = 0; i < timer_count; i++ )
    1.36 +		out [r_t0out + i] = m.timers [i].counter;
    1.37 +	
    1.38 +	// Last written values
    1.39 +	memcpy( out, REGS, r_t0out );
    1.40 +}
    1.41 +
    1.42 +void SNES_SPC::init_header( void* spc_out )
    1.43 +{
    1.44 +	spc_file_t* const spc = (spc_file_t*) spc_out;
    1.45 +	
    1.46 +	spc->has_id666 = 26; // has none
    1.47 +	spc->version   = 30;
    1.48 +	memcpy( spc, signature, sizeof spc->signature );
    1.49 +	memset( spc->text, 0, sizeof spc->text );
    1.50 +}
    1.51 +
    1.52 +void SNES_SPC::save_spc( void* spc_out )
    1.53 +{
    1.54 +	spc_file_t* const spc = (spc_file_t*) spc_out;
    1.55 +	
    1.56 +	// CPU
    1.57 +	spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0);
    1.58 +	spc->pch = (uint8_t) (m.cpu_regs.pc >> 8);
    1.59 +	spc->a   = m.cpu_regs.a;
    1.60 +	spc->x   = m.cpu_regs.x;
    1.61 +	spc->y   = m.cpu_regs.y;
    1.62 +	spc->psw = m.cpu_regs.psw;
    1.63 +	spc->sp  = m.cpu_regs.sp;
    1.64 +	
    1.65 +	// RAM, ROM
    1.66 +	memcpy( spc->ram, RAM, sizeof spc->ram );
    1.67 +	if ( m.rom_enabled )
    1.68 +		memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram );
    1.69 +	memset( spc->unused, 0, sizeof spc->unused );
    1.70 +	memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom );
    1.71 +	
    1.72 +	// SMP registers
    1.73 +	save_regs( &spc->ram [0xF0] );
    1.74 +	int i;
    1.75 +	for ( i = 0; i < port_count; i++ )
    1.76 +		spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i];
    1.77 +	
    1.78 +	// DSP registers
    1.79 +	for ( i = 0; i < SPC_DSP::register_count; i++ )
    1.80 +		spc->dsp [i] = dsp.read( i );
    1.81 +}
    1.82 +
    1.83 +void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy )
    1.84 +{
    1.85 +	SPC_State_Copier copier( io, copy );
    1.86 +	
    1.87 +	// Make state data more readable by putting 64K RAM, 16 SMP registers,
    1.88 +	// then DSP (with its 128 registers) first
    1.89 +	
    1.90 +	// RAM
    1.91 +	enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below
    1.92 +	copier.copy( RAM, 0x10000 );
    1.93 +	
    1.94 +	{
    1.95 +		// SMP registers
    1.96 +		uint8_t out_ports [port_count];
    1.97 +		uint8_t regs [reg_count];
    1.98 +		memcpy( out_ports, &REGS [r_cpuio0], sizeof out_ports );
    1.99 +		save_regs( regs );
   1.100 +		copier.copy( regs, sizeof regs );
   1.101 +		copier.copy( out_ports, sizeof out_ports );
   1.102 +		load_regs( regs );
   1.103 +		regs_loaded();
   1.104 +		memcpy( &REGS [r_cpuio0], out_ports, sizeof out_ports );
   1.105 +	}
   1.106 +	
   1.107 +	// CPU registers
   1.108 +	SPC_COPY( uint16_t, m.cpu_regs.pc );
   1.109 +	SPC_COPY(  uint8_t, m.cpu_regs.a );
   1.110 +	SPC_COPY(  uint8_t, m.cpu_regs.x );
   1.111 +	SPC_COPY(  uint8_t, m.cpu_regs.y );
   1.112 +	SPC_COPY(  uint8_t, m.cpu_regs.psw );
   1.113 +	SPC_COPY(  uint8_t, m.cpu_regs.sp );
   1.114 +	copier.extra();
   1.115 +	
   1.116 +	SPC_COPY( int16_t, m.spc_time );
   1.117 +	SPC_COPY( int16_t, m.dsp_time );
   1.118 +	
   1.119 +	// DSP
   1.120 +	dsp.copy_state( io, copy );
   1.121 +	
   1.122 +	// Timers
   1.123 +	for ( int i = 0; i < timer_count; i++ )
   1.124 +	{
   1.125 +		Timer* t = &m.timers [i];
   1.126 +		SPC_COPY( int16_t, t->next_time );
   1.127 +		SPC_COPY( uint8_t, t->divider );
   1.128 +		copier.extra();
   1.129 +	}
   1.130 +	copier.extra();
   1.131 +}
   1.132 +#endif