Path: blob/main/misc/emulator/xnes/snes9x/apu/SNES_SPC_state.cpp
28798 views
// SPC emulation state save/load: copy_state(), save_spc()1// Separate file to avoid linking in unless needed23// snes_spc 0.9.0. http://www.slack.net/‾ant/45#include "SNES_SPC.h"67#if !SPC_NO_COPY_STATE_FUNCS89#include <string.h>1011/* Copyright (C) 2004-2007 Shay Green. This module is free software; you12can redistribute it and/or modify it under the terms of the GNU Lesser13General Public License as published by the Free Software Foundation; either14version 2.1 of the License, or (at your option) any later version. This15module is distributed in the hope that it will be useful, but WITHOUT ANY16WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more18details. You should have received a copy of the GNU Lesser General Public19License along with this module; if not, write to the Free Software Foundation,20Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */2122#include <stdio.h>23#include "blargg_source.h"2425#define RAM (m.ram.ram)26#define REGS (m.smp_regs [0])27#define REGS_IN (m.smp_regs [1])2829void SNES_SPC::save_regs( uint8_t out [reg_count] )30{31// Use current timer counter values32for ( int i = 0; i < timer_count; i++ )33out [r_t0out + i] = m.timers [i].counter;3435// Last written values36memcpy( out, REGS, r_t0out );37}3839void SNES_SPC::init_header( void* spc_out )40{41spc_file_t* const spc = (spc_file_t*) spc_out;4243spc->has_id666 = 26; // has none44spc->version = 30;45memcpy( spc, signature, sizeof spc->signature );46memset( spc->text, 0, sizeof spc->text );47}4849void SNES_SPC::save_spc( void* spc_out )50{51spc_file_t* const spc = (spc_file_t*) spc_out;5253// CPU54spc->pcl = (uint8_t) (m.cpu_regs.pc >> 0);55spc->pch = (uint8_t) (m.cpu_regs.pc >> 8);56spc->a = m.cpu_regs.a;57spc->x = m.cpu_regs.x;58spc->y = m.cpu_regs.y;59spc->psw = m.cpu_regs.psw;60spc->sp = m.cpu_regs.sp;6162// RAM, ROM63memcpy( spc->ram, RAM, sizeof spc->ram );64if ( m.rom_enabled )65memcpy( spc->ram + rom_addr, m.hi_ram, sizeof m.hi_ram );66memset( spc->unused, 0, sizeof spc->unused );67memcpy( spc->ipl_rom, m.rom, sizeof spc->ipl_rom );6869// SMP registers70save_regs( &spc->ram [0xF0] );71int i;72for ( i = 0; i < port_count; i++ )73spc->ram [0xF0 + r_cpuio0 + i] = REGS_IN [r_cpuio0 + i];7475// DSP registers76for ( i = 0; i < SPC_DSP::register_count; i++ )77spc->dsp [i] = dsp.read( i );78}7980#undef IF_0_THEN_25681#define IF_0_THEN_256( n ) ((uint8_t) ((n) - 1) + 1)82void SNES_SPC::copy_state( unsigned char** io, copy_func_t copy )83{84SPC_State_Copier copier( io, copy );8586// Make state data more readable by putting 64K RAM, 16 SMP registers,87// then DSP (with its 128 registers) first8889// RAM90enable_rom( 0 ); // will get re-enabled if necessary in regs_loaded() below91copier.copy( RAM, 0x10000 );9293{94// SMP registers95uint8_t regs [reg_count];96uint8_t regs_in [reg_count];9798memcpy( regs, REGS, reg_count );99memcpy( regs_in, REGS_IN, reg_count );100101copier.copy( regs, sizeof regs );102copier.copy( regs_in, sizeof regs_in );103104memcpy( REGS, regs, reg_count);105memcpy( REGS_IN, regs_in, reg_count );106107enable_rom( REGS [r_control] & 0x80 );108}109110// CPU registers111SPC_COPY( uint16_t, m.cpu_regs.pc );112SPC_COPY( uint8_t, m.cpu_regs.a );113SPC_COPY( uint8_t, m.cpu_regs.x );114SPC_COPY( uint8_t, m.cpu_regs.y );115SPC_COPY( uint8_t, m.cpu_regs.psw );116SPC_COPY( uint8_t, m.cpu_regs.sp );117copier.extra();118119SPC_COPY( int16_t, m.spc_time );120SPC_COPY( int16_t, m.dsp_time );121122// DSP123dsp.copy_state( io, copy );124125// Timers126for ( int i = 0; i < timer_count; i++ )127{128Timer* t = &m.timers [i];129t->period = IF_0_THEN_256( REGS [r_t0target + i] );130t->enabled = REGS [r_control] >> i & 1;131SPC_COPY( int16_t, t->next_time );132SPC_COPY( uint8_t, t->divider );133SPC_COPY( uint8_t, t->counter );134copier.extra();135}136137set_tempo( m.tempo );138139copier.extra();140}141#endif142143144