rlm@0: // SPC emulation state save/load: copy_state(), save_spc() rlm@0: // Separate file to avoid linking in unless needed rlm@0: rlm@0: // snes_spc 0.9.0. http://www.slack.net/~ant/ rlm@0: rlm@0: #include "SNES_SPC.h" rlm@0: rlm@0: #if !SPC_NO_COPY_STATE_FUNCS rlm@0: rlm@0: #include rlm@0: rlm@0: /* Copyright (C) 2004-2007 Shay Green. This module is free software; you rlm@0: can redistribute it and/or modify it under the terms of the GNU Lesser rlm@0: General Public License as published by the Free Software Foundation; either rlm@0: version 2.1 of the License, or (at your option) any later version. This rlm@0: module is distributed in the hope that it will be useful, but WITHOUT ANY rlm@0: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS rlm@0: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more rlm@0: details. You should have received a copy of the GNU Lesser General Public rlm@0: License along with this module; if not, write to the Free Software Foundation, rlm@0: Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ rlm@0: rlm@0: #include "blargg_source.h" rlm@0: rlm@0: #define RAM (m.ram.ram) rlm@0: #define REGS (m.smp_regs [0]) rlm@0: #define REGS_IN (m.smp_regs [1]) rlm@0: rlm@0: void SNES_SPC::save_regs( uint8_t out [reg_count] ) rlm@0: { rlm@0: // Use current timer counter values rlm@0: for ( int i = 0; i < timer_count; i++ ) rlm@0: out [r_t0out + i] = m.timers [i].counter; rlm@0: rlm@0: // Last written values rlm@0: memcpy( out, REGS, r_t0out ); rlm@0: } rlm@0: rlm@0: void SNES_SPC::init_header( void* spc_out ) rlm@0: { rlm@0: spc_file_t* const spc = (spc_file_t*) spc_out; rlm@0: rlm@0: spc->has_id666 = 26; // has none rlm@0: spc->version = 30; rlm@0: memcpy( spc, signature, sizeof spc->signature ); rlm@0: memset( spc->text, 0, sizeof spc->text ); rlm@0: } rlm@0: rlm@0: void SNES_SPC::save_spc( void* spc_out ) rlm@0: { rlm@0: spc_file_t* const spc = (spc_file_t*) spc_out; rlm@0: rlm@0: // CPU rlm@0: spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0); rlm@0: spc->pch = (uint8_t) (m.cpu_regs.pc >> 8); rlm@0: spc->a = m.cpu_regs.a; rlm@0: spc->x = m.cpu_regs.x; rlm@0: spc->y = m.cpu_regs.y; rlm@0: spc->psw = m.cpu_regs.psw; rlm@0: spc->sp = m.cpu_regs.sp; rlm@0: rlm@0: // RAM, ROM rlm@0: memcpy( spc->ram, RAM, sizeof spc->ram ); rlm@0: if ( m.rom_enabled ) rlm@0: memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram ); rlm@0: memset( spc->unused, 0, sizeof spc->unused ); rlm@0: memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom ); rlm@0: rlm@0: // SMP registers rlm@0: save_regs( &spc->ram [0xF0] ); rlm@0: int i; rlm@0: for ( i = 0; i < port_count; i++ ) rlm@0: spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i]; rlm@0: rlm@0: // DSP registers rlm@0: for ( i = 0; i < SPC_DSP::register_count; i++ ) rlm@0: spc->dsp [i] = dsp.read( i ); rlm@0: } rlm@0: rlm@0: void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy ) rlm@0: { rlm@0: SPC_State_Copier copier( io, copy ); rlm@0: rlm@0: // Make state data more readable by putting 64K RAM, 16 SMP registers, rlm@0: // then DSP (with its 128 registers) first rlm@0: rlm@0: // RAM rlm@0: enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below rlm@0: copier.copy( RAM, 0x10000 ); rlm@0: rlm@0: { rlm@0: // SMP registers rlm@0: uint8_t out_ports [port_count]; rlm@0: uint8_t regs [reg_count]; rlm@0: memcpy( out_ports, ®S [r_cpuio0], sizeof out_ports ); rlm@0: save_regs( regs ); rlm@0: copier.copy( regs, sizeof regs ); rlm@0: copier.copy( out_ports, sizeof out_ports ); rlm@0: load_regs( regs ); rlm@0: regs_loaded(); rlm@0: memcpy( ®S [r_cpuio0], out_ports, sizeof out_ports ); rlm@0: } rlm@0: rlm@0: // CPU registers rlm@0: SPC_COPY( uint16_t, m.cpu_regs.pc ); rlm@0: SPC_COPY( uint8_t, m.cpu_regs.a ); rlm@0: SPC_COPY( uint8_t, m.cpu_regs.x ); rlm@0: SPC_COPY( uint8_t, m.cpu_regs.y ); rlm@0: SPC_COPY( uint8_t, m.cpu_regs.psw ); rlm@0: SPC_COPY( uint8_t, m.cpu_regs.sp ); rlm@0: copier.extra(); rlm@0: rlm@0: SPC_COPY( int16_t, m.spc_time ); rlm@0: SPC_COPY( int16_t, m.dsp_time ); rlm@0: rlm@0: // DSP rlm@0: dsp.copy_state( io, copy ); rlm@0: rlm@0: // Timers rlm@0: for ( int i = 0; i < timer_count; i++ ) rlm@0: { rlm@0: Timer* t = &m.timers [i]; rlm@0: SPC_COPY( int16_t, t->next_time ); rlm@0: SPC_COPY( uint8_t, t->divider ); rlm@0: copier.extra(); rlm@0: } rlm@0: copier.extra(); rlm@0: } rlm@0: #endif