view 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 source
1 // SPC emulation state save/load: copy_state(), save_spc()
2 // Separate file to avoid linking in unless needed
4 // snes_spc 0.9.0. http://www.slack.net/~ant/
6 #include "SNES_SPC.h"
8 #if !SPC_NO_COPY_STATE_FUNCS
10 #include <string.h>
12 /* Copyright (C) 2004-2007 Shay Green. This module is free software; you
13 can redistribute it and/or modify it under the terms of the GNU Lesser
14 General Public License as published by the Free Software Foundation; either
15 version 2.1 of the License, or (at your option) any later version. This
16 module is distributed in the hope that it will be useful, but WITHOUT ANY
17 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
19 details. You should have received a copy of the GNU Lesser General Public
20 License along with this module; if not, write to the Free Software Foundation,
21 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
23 #include "blargg_source.h"
25 #define RAM (m.ram.ram)
26 #define REGS (m.smp_regs [0])
27 #define REGS_IN (m.smp_regs [1])
29 void SNES_SPC::save_regs( uint8_t out [reg_count] )
30 {
31 // Use current timer counter values
32 for ( int i = 0; i < timer_count; i++ )
33 out [r_t0out + i] = m.timers [i].counter;
35 // Last written values
36 memcpy( out, REGS, r_t0out );
37 }
39 void SNES_SPC::init_header( void* spc_out )
40 {
41 spc_file_t* const spc = (spc_file_t*) spc_out;
43 spc->has_id666 = 26; // has none
44 spc->version = 30;
45 memcpy( spc, signature, sizeof spc->signature );
46 memset( spc->text, 0, sizeof spc->text );
47 }
49 void SNES_SPC::save_spc( void* spc_out )
50 {
51 spc_file_t* const spc = (spc_file_t*) spc_out;
53 // CPU
54 spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0);
55 spc->pch = (uint8_t) (m.cpu_regs.pc >> 8);
56 spc->a = m.cpu_regs.a;
57 spc->x = m.cpu_regs.x;
58 spc->y = m.cpu_regs.y;
59 spc->psw = m.cpu_regs.psw;
60 spc->sp = m.cpu_regs.sp;
62 // RAM, ROM
63 memcpy( spc->ram, RAM, sizeof spc->ram );
64 if ( m.rom_enabled )
65 memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram );
66 memset( spc->unused, 0, sizeof spc->unused );
67 memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom );
69 // SMP registers
70 save_regs( &spc->ram [0xF0] );
71 int i;
72 for ( i = 0; i < port_count; i++ )
73 spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i];
75 // DSP registers
76 for ( i = 0; i < SPC_DSP::register_count; i++ )
77 spc->dsp [i] = dsp.read( i );
78 }
80 void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy )
81 {
82 SPC_State_Copier copier( io, copy );
84 // Make state data more readable by putting 64K RAM, 16 SMP registers,
85 // then DSP (with its 128 registers) first
87 // RAM
88 enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below
89 copier.copy( RAM, 0x10000 );
91 {
92 // SMP registers
93 uint8_t out_ports [port_count];
94 uint8_t regs [reg_count];
95 memcpy( out_ports, &REGS [r_cpuio0], sizeof out_ports );
96 save_regs( regs );
97 copier.copy( regs, sizeof regs );
98 copier.copy( out_ports, sizeof out_ports );
99 load_regs( regs );
100 regs_loaded();
101 memcpy( &REGS [r_cpuio0], out_ports, sizeof out_ports );
102 }
104 // CPU registers
105 SPC_COPY( uint16_t, m.cpu_regs.pc );
106 SPC_COPY( uint8_t, m.cpu_regs.a );
107 SPC_COPY( uint8_t, m.cpu_regs.x );
108 SPC_COPY( uint8_t, m.cpu_regs.y );
109 SPC_COPY( uint8_t, m.cpu_regs.psw );
110 SPC_COPY( uint8_t, m.cpu_regs.sp );
111 copier.extra();
113 SPC_COPY( int16_t, m.spc_time );
114 SPC_COPY( int16_t, m.dsp_time );
116 // DSP
117 dsp.copy_state( io, copy );
119 // Timers
120 for ( int i = 0; i < timer_count; i++ )
121 {
122 Timer* t = &m.timers [i];
123 SPC_COPY( int16_t, t->next_time );
124 SPC_COPY( uint8_t, t->divider );
125 copier.extra();
126 }
127 copier.extra();
128 }
129 #endif