Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
RishiRecon
GitHub Repository: RishiRecon/exploits
Path: blob/main/misc/emulator/xnes/snes9x/apu/SNES_SPC_state.cpp
28798 views
1
// SPC emulation state save/load: copy_state(), save_spc()
2
// Separate file to avoid linking in unless needed
3
4
// snes_spc 0.9.0. http://www.slack.net/‾ant/
5
6
#include "SNES_SPC.h"
7
8
#if !SPC_NO_COPY_STATE_FUNCS
9
10
#include <string.h>
11
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 */
22
23
#include <stdio.h>
24
#include "blargg_source.h"
25
26
#define RAM (m.ram.ram)
27
#define REGS (m.smp_regs [0])
28
#define REGS_IN (m.smp_regs [1])
29
30
void SNES_SPC::save_regs( uint8_t out [reg_count] )
31
{
32
// Use current timer counter values
33
for ( int i = 0; i < timer_count; i++ )
34
out [r_t0out + i] = m.timers [i].counter;
35
36
// Last written values
37
memcpy( out, REGS, r_t0out );
38
}
39
40
void SNES_SPC::init_header( void* spc_out )
41
{
42
spc_file_t* const spc = (spc_file_t*) spc_out;
43
44
spc->has_id666 = 26; // has none
45
spc->version = 30;
46
memcpy( spc, signature, sizeof spc->signature );
47
memset( spc->text, 0, sizeof spc->text );
48
}
49
50
void SNES_SPC::save_spc( void* spc_out )
51
{
52
spc_file_t* const spc = (spc_file_t*) spc_out;
53
54
// CPU
55
spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0);
56
spc->pch = (uint8_t) (m.cpu_regs.pc >> 8);
57
spc->a = m.cpu_regs.a;
58
spc->x = m.cpu_regs.x;
59
spc->y = m.cpu_regs.y;
60
spc->psw = m.cpu_regs.psw;
61
spc->sp = m.cpu_regs.sp;
62
63
// RAM, ROM
64
memcpy( spc->ram, RAM, sizeof spc->ram );
65
if ( m.rom_enabled )
66
memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram );
67
memset( spc->unused, 0, sizeof spc->unused );
68
memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom );
69
70
// SMP registers
71
save_regs( &spc->ram [0xF0] );
72
int i;
73
for ( i = 0; i < port_count; i++ )
74
spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i];
75
76
// DSP registers
77
for ( i = 0; i < SPC_DSP::register_count; i++ )
78
spc->dsp [i] = dsp.read( i );
79
}
80
81
#undef IF_0_THEN_256
82
#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)
83
void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy )
84
{
85
SPC_State_Copier copier( io, copy );
86
87
// Make state data more readable by putting 64K RAM, 16 SMP registers,
88
// then DSP (with its 128 registers) first
89
90
// RAM
91
enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below
92
copier.copy( RAM, 0x10000 );
93
94
{
95
// SMP registers
96
uint8_t regs [reg_count];
97
uint8_t regs_in [reg_count];
98
99
memcpy( regs, REGS, reg_count );
100
memcpy( regs_in, REGS_IN, reg_count );
101
102
copier.copy( regs, sizeof regs );
103
copier.copy( regs_in, sizeof regs_in );
104
105
memcpy( REGS, regs, reg_count);
106
memcpy( REGS_IN, regs_in, reg_count );
107
108
enable_rom( REGS [r_control] & 0x80 );
109
}
110
111
// CPU registers
112
SPC_COPY( uint16_t, m.cpu_regs.pc );
113
SPC_COPY( uint8_t, m.cpu_regs.a );
114
SPC_COPY( uint8_t, m.cpu_regs.x );
115
SPC_COPY( uint8_t, m.cpu_regs.y );
116
SPC_COPY( uint8_t, m.cpu_regs.psw );
117
SPC_COPY( uint8_t, m.cpu_regs.sp );
118
copier.extra();
119
120
SPC_COPY( int16_t, m.spc_time );
121
SPC_COPY( int16_t, m.dsp_time );
122
123
// DSP
124
dsp.copy_state( io, copy );
125
126
// Timers
127
for ( int i = 0; i < timer_count; i++ )
128
{
129
Timer* t = &m.timers [i];
130
t->period = IF_0_THEN_256( REGS [r_t0target + i] );
131
t->enabled = REGS [r_control] >> i & 1;
132
SPC_COPY( int16_t, t->next_time );
133
SPC_COPY( uint8_t, t->divider );
134
SPC_COPY( uint8_t, t->counter );
135
copier.extra();
136
}
137
138
set_tempo( m.tempo );
139
140
copier.extra();
141
}
142
#endif
143
144