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