Cog/Frameworks/lazyusf/lazyusf/main/savestates.c
2015-04-19 22:32:04 -07:00

641 lines
27 KiB
C

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Mupen64plus - savestates.c *
* Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ *
* Copyright (C) 2012 CasualJames *
* Copyright (C) 2009 Olejl Tillin9 *
* Copyright (C) 2008 Richard42 Tillin9 *
* Copyright (C) 2002 Hacktarux *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include <stdlib.h>
#include <string.h>
#include "usf/usf.h"
#include "usf/usf_internal.h"
#define M64P_CORE_PROTOTYPES 1
#include "api/m64p_types.h"
#include "api/callbacks.h"
#include "savestates.h"
#include "main.h"
#include "rom.h"
#include "util.h"
#include "ai/ai_controller.h"
#include "memory/memory.h"
#include "r4300/tlb.h"
#include "r4300/cp0.h"
#include "r4300/cp1.h"
#include "r4300/r4300.h"
#include "r4300/r4300_core.h"
#include "r4300/cached_interp.h"
#include "r4300/interupt.h"
#include "pi/pi_controller.h"
#ifdef NEW_DYNAREC
#include "r4300/new_dynarec/new_dynarec.h"
#endif
#include "rdp/rdp_core.h"
#include "ri/ri_controller.h"
#include "rsp/rsp_core.h"
#include "si/si_controller.h"
#include "vi/vi_controller.h"
static const char* savestate_magic = "M64+SAVE";
static const int savestate_latest_version = 0x00010000; /* 1.0 */
static const unsigned char pj64_magic[4] = { 0xC8, 0xA6, 0xD8, 0x23 };
#define GETARRAY(buff, type, count) \
(to_little_endian_buffer(buff, sizeof(type),count), \
buff += count*sizeof(type), \
(type *)(buff-count*sizeof(type)))
#define COPYARRAY(dst, buff, type, count) \
memcpy(dst, GETARRAY(buff, type, count), sizeof(type)*count)
#define GETDATA(buff, type) *GETARRAY(buff, type, 1)
#define PUTARRAY(src, buff, type, count) \
memcpy(buff, src, sizeof(type)*count); \
to_little_endian_buffer(buff, sizeof(type), count); \
buff += count*sizeof(type);
#define PUTDATA(buff, type, value) \
do { type x = value; PUTARRAY(&x, buff, type, 1); } while(0)
#define read_bytes(ptr, size) \
{ \
if ((size) > state_size) \
{ \
if (savestateData) free(savestateData); \
return 0; \
} \
memcpy((ptr), state_ptr, (size)); \
state_ptr += (size); \
state_size -= (size); \
}
static int savestates_load_m64p(usf_state_t * state, unsigned char * ptr, unsigned int size)
{
unsigned char header[44];
int version;
int i;
unsigned char * state_ptr = ptr;
unsigned int state_size = size;
size_t savestateSize;
unsigned char *savestateData = 0, *curr;
char queue[1024];
/* Read and check Mupen64Plus magic number. */
read_bytes(header, 44);
curr = header;
if(strncmp((char *)curr, savestate_magic, 8)!=0)
return 0;
curr += 8;
version = *curr++;
version = (version << 8) | *curr++;
version = (version << 8) | *curr++;
version = (version << 8) | *curr++;
if(version != 0x00010000)
return 0;
/* skip MD5 */
curr += 32;
/* Read the rest of the savestate */
savestateSize = 16788244;
if (state_size < savestateSize + sizeof(queue))
return 0;
savestateData = curr = malloc(savestateSize);
if (!savestateData)
return 0;
read_bytes(savestateData, savestateSize);
read_bytes(queue, sizeof(queue));
// Parse savestate
state->g_ri.rdram.regs[RDRAM_CONFIG_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_DEVICE_ID_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_DELAY_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_MODE_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_REF_INTERVAL_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_REF_ROW_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_RAS_INTERVAL_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_MIN_INTERVAL_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_ADDR_SELECT_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_DEVICE_MANUF_REG] = GETDATA(curr, uint32_t);
curr += 4; /* Padding from old implementation */
state->g_r4300.mi.regs[MI_INIT_MODE_REG] = GETDATA(curr, uint32_t);
curr += 4; // Duplicate MI init mode flags from old implementation
state->g_r4300.mi.regs[MI_VERSION_REG] = GETDATA(curr, uint32_t);
state->g_r4300.mi.regs[MI_INTR_REG] = GETDATA(curr, uint32_t);
state->g_r4300.mi.regs[MI_INTR_MASK_REG] = GETDATA(curr, uint32_t);
curr += 4; /* Padding from old implementation */
curr += 8; // Duplicated MI intr flags and padding from old implementation
state->g_pi.regs[PI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_CART_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_RD_LEN_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_WR_LEN_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM1_LAT_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM1_PWD_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM1_PGS_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM1_RLS_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM2_LAT_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM2_PWD_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM2_PGS_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM2_RLS_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_MEM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_RD_LEN_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_WR_LEN_REG] = GETDATA(curr, uint32_t);
curr += 4; /* Padding from old implementation */
state->g_sp.regs[SP_STATUS_REG] = GETDATA(curr, uint32_t);
curr += 16; // Duplicated SP flags and padding from old implementation
state->g_sp.regs[SP_DMA_FULL_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_DMA_BUSY_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_SEMAPHORE_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs2[SP_PC_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs2[SP_IBIST_REG] = GETDATA(curr, uint32_t);
state->g_si.regs[SI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_si.regs[SI_PIF_ADDR_RD64B_REG] = GETDATA(curr, uint32_t);
state->g_si.regs[SI_PIF_ADDR_WR64B_REG] = GETDATA(curr, uint32_t);
state->g_si.regs[SI_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_ORIGIN_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_WIDTH_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_V_INTR_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_CURRENT_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_BURST_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_V_SYNC_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_H_SYNC_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_LEAP_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_H_START_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_V_START_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_V_BURST_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_X_SCALE_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_Y_SCALE_REG] = GETDATA(curr, uint32_t);
state->g_vi.delay = GETDATA(curr, unsigned int);
state->g_ri.regs[RI_MODE_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_CONFIG_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_CURRENT_LOAD_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_SELECT_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_REFRESH_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_LATENCY_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_ERROR_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_WERROR_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_LEN_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_CONTROL_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_DACRATE_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_BITRATE_REG] = GETDATA(curr, uint32_t);
state->g_ai.fifo[1].duration = GETDATA(curr, unsigned int);
state->g_ai.fifo[1].length = GETDATA(curr, uint32_t);
state->g_ai.fifo[0].duration = GETDATA(curr, unsigned int);
state->g_ai.fifo[0].length = GETDATA(curr, uint32_t);
/* best effort initialization of fifo addresses...
* You might get a small sound "pop" because address might be wrong.
* Proper initialization requires changes to savestate format
*/
state->g_ai.fifo[0].address = state->g_ai.regs[AI_DRAM_ADDR_REG];
state->g_ai.fifo[1].address = state->g_ai.regs[AI_DRAM_ADDR_REG];
state->g_ai.samples_format_changed = 1;
state->g_dp.dpc_regs[DPC_START_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_END_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_CURRENT_REG] = GETDATA(curr, uint32_t);
curr += 4; // Padding from old implementation
state->g_dp.dpc_regs[DPC_STATUS_REG] = GETDATA(curr, uint32_t);
curr += 12; // Duplicated DPC flags and padding from old implementation
state->g_dp.dpc_regs[DPC_CLOCK_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_BUFBUSY_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_PIPEBUSY_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_TMEM_REG] = GETDATA(curr, uint32_t);
state->g_dp.dps_regs[DPS_TBIST_REG] = GETDATA(curr, uint32_t);
state->g_dp.dps_regs[DPS_TEST_MODE_REG] = GETDATA(curr, uint32_t);
state->g_dp.dps_regs[DPS_BUFTEST_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_dp.dps_regs[DPS_BUFTEST_DATA_REG] = GETDATA(curr, uint32_t);
COPYARRAY(state->g_rdram, curr, uint32_t, RDRAM_MAX_SIZE/4);
COPYARRAY(state->g_sp.mem, curr, uint32_t, SP_MEM_SIZE/4);
COPYARRAY(state->g_si.pif.ram, curr, uint8_t, PIF_RAM_SIZE);
/*state->g_pi.use_flashram =*/ (void)GETDATA(curr, int);
/*state->g_pi.flashram.mode =*/ (void)GETDATA(curr, int);
/*state->g_pi.flashram.status =*/ (void)GETDATA(curr, unsigned long long);
/*state->g_pi.flashram.erase_offset =*/ (void)GETDATA(curr, unsigned int);
/*state->g_pi.flashram.write_pointer =*/ (void)GETDATA(curr, unsigned int);
COPYARRAY(state->tlb_LUT_r, curr, unsigned int, 0x100000);
COPYARRAY(state->tlb_LUT_w, curr, unsigned int, 0x100000);
state->llbit = GETDATA(curr, unsigned int);
COPYARRAY(state->reg, curr, long long int, 32);
COPYARRAY(state->g_cp0_regs, curr, unsigned int, CP0_REGS_COUNT);
set_fpr_pointers(state, state->g_cp0_regs[CP0_STATUS_REG]);
state->lo = GETDATA(curr, long long int);
state->hi = GETDATA(curr, long long int);
COPYARRAY(state->reg_cop1_fgr_64, curr, long long int, 32);
if ((state->g_cp0_regs[CP0_STATUS_REG] & 0x04000000) == 0) // 32-bit FPR mode requires data shuffling because 64-bit layout is always stored in savestate file
shuffle_fpr_data(state, 0x04000000, 0);
state->FCR0 = GETDATA(curr, int);
state->FCR31 = GETDATA(curr, int);
for (i = 0; i < 32; i++)
{
state->tlb_e[i].mask = GETDATA(curr, short);
curr += 2;
state->tlb_e[i].vpn2 = GETDATA(curr, int);
state->tlb_e[i].g = GETDATA(curr, char);
state->tlb_e[i].asid = GETDATA(curr, unsigned char);
curr += 2;
state->tlb_e[i].pfn_even = GETDATA(curr, int);
state->tlb_e[i].c_even = GETDATA(curr, char);
state->tlb_e[i].d_even = GETDATA(curr, char);
state->tlb_e[i].v_even = GETDATA(curr, char);
curr++;
state->tlb_e[i].pfn_odd = GETDATA(curr, int);
state->tlb_e[i].c_odd = GETDATA(curr, char);
state->tlb_e[i].d_odd = GETDATA(curr, char);
state->tlb_e[i].v_odd = GETDATA(curr, char);
state->tlb_e[i].r = GETDATA(curr, char);
state->tlb_e[i].start_even = GETDATA(curr, unsigned int);
state->tlb_e[i].end_even = GETDATA(curr, unsigned int);
state->tlb_e[i].phys_even = GETDATA(curr, unsigned int);
state->tlb_e[i].start_odd = GETDATA(curr, unsigned int);
state->tlb_e[i].end_odd = GETDATA(curr, unsigned int);
state->tlb_e[i].phys_odd = GETDATA(curr, unsigned int);
}
#ifdef NEW_DYNAREC
if (state->r4300emu == CORE_DYNAREC) {
state->pcaddr = GETDATA(curr, unsigned int);
state->pending_exception = 1;
invalidate_all_pages(state);
} else {
if(state->r4300emu != CORE_PURE_INTERPRETER)
{
for (i = 0; i < 0x100000; i++)
state->invalid_code[i] = 1;
}
generic_jump_to(state, GETDATA(curr, unsigned int)); // PC
}
#else
if(state->r4300emu != CORE_PURE_INTERPRETER)
{
for (i = 0; i < 0x100000; i++)
state->invalid_code[i] = 1;
}
generic_jump_to(state, GETDATA(curr, unsigned int)); // PC
#endif
state->next_interupt = GETDATA(curr, unsigned int);
state->g_vi.next_vi = GETDATA(curr, unsigned int);
state->g_vi.field = GETDATA(curr, unsigned int);
free(savestateData);
// assert(savestateData+savestateSize == curr)
to_little_endian_buffer(queue, 4, 256);
load_eventqueue_infos(state, queue);
#ifdef NEW_DYNAREC
if (state->r4300emu == CORE_DYNAREC)
state->last_addr = state->pcaddr;
else
state->last_addr = state->PC->addr;
#else
state->last_addr = state->PC->addr;
#endif
return 1;
}
static int savestates_load_pj64(usf_state_t * state, unsigned char * ptr, unsigned int size)
{
char buffer[1024];
unsigned int vi_timer, SaveRDRAMSize;
int i;
#ifdef DYNAREC
unsigned long long dummy;
#endif
unsigned char header[8];
unsigned char * state_ptr = ptr;
unsigned int state_size = size;
size_t savestateSize;
unsigned char *savestateData = 0, *curr;
/* Read and check Project64 magic number. */
read_bytes(header, 8);
curr = header;
if (memcmp(curr, pj64_magic, 4) != 0)
{
return 0;
}
curr += 4;
SaveRDRAMSize = GETDATA(curr, unsigned int);
/* Read the rest of the savestate into memory. */
savestateSize = SaveRDRAMSize + 0x2754;
savestateData = curr = malloc(savestateSize);
if (!savestateData)
return 0;
if (state_size < savestateSize)
{
free(savestateData);
return 0;
}
read_bytes(savestateData, savestateSize);
// skip ROM header
curr += 0x40;
// vi_timer
vi_timer = GETDATA(curr, unsigned int);
// Program Counter
state->last_addr = GETDATA(curr, unsigned int);
// GPR
COPYARRAY(state->reg, curr, long long int, 32);
// FPR
COPYARRAY(state->reg_cop1_fgr_64, curr, long long int, 32);
// CP0
COPYARRAY(state->g_cp0_regs, curr, unsigned int, CP0_REGS_COUNT);
set_fpr_pointers(state, state->g_cp0_regs[CP0_STATUS_REG]);
if ((state->g_cp0_regs[CP0_STATUS_REG] & 0x04000000) == 0) // TODO not sure how pj64 handles this
shuffle_fpr_data(state, 0x04000000, 0);
// Initialze the interupts
vi_timer += state->g_cp0_regs[CP0_COUNT_REG];
state->next_interupt = (state->g_cp0_regs[CP0_COMPARE_REG] < vi_timer)
? state->g_cp0_regs[CP0_COMPARE_REG]
: vi_timer;
state->g_vi.next_vi = vi_timer;
state->g_vi.field = 0;
*((unsigned int*)&buffer[0]) = VI_INT;
*((unsigned int*)&buffer[4]) = vi_timer;
*((unsigned int*)&buffer[8]) = COMPARE_INT;
*((unsigned int*)&buffer[12]) = state->g_cp0_regs[CP0_COMPARE_REG];
*((unsigned int*)&buffer[16]) = 0xFFFFFFFF;
load_eventqueue_infos(state, buffer);
// FPCR
state->FCR0 = GETDATA(curr, int);
curr += 30 * 4; // FCR1...FCR30 not supported
state->FCR31 = GETDATA(curr, int);
// hi / lo
state->hi = GETDATA(curr, long long int);
state->lo = GETDATA(curr, long long int);
// rdram register
state->g_ri.rdram.regs[RDRAM_CONFIG_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_DEVICE_ID_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_DELAY_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_MODE_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_REF_INTERVAL_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_REF_ROW_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_RAS_INTERVAL_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_MIN_INTERVAL_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_ADDR_SELECT_REG] = GETDATA(curr, uint32_t);
state->g_ri.rdram.regs[RDRAM_DEVICE_MANUF_REG] = GETDATA(curr, uint32_t);
// sp_register
state->g_sp.regs[SP_MEM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_RD_LEN_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_WR_LEN_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_DMA_FULL_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_DMA_BUSY_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs[SP_SEMAPHORE_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs2[SP_PC_REG] = GETDATA(curr, uint32_t);
state->g_sp.regs2[SP_IBIST_REG] = GETDATA(curr, uint32_t);
// dpc_register
state->g_dp.dpc_regs[DPC_START_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_END_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_CURRENT_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_CLOCK_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_BUFBUSY_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_PIPEBUSY_REG] = GETDATA(curr, uint32_t);
state->g_dp.dpc_regs[DPC_TMEM_REG] = GETDATA(curr, uint32_t);
(void)GETDATA(curr, unsigned int); // Dummy read
(void)GETDATA(curr, unsigned int); // Dummy read
// mi_register
state->g_r4300.mi.regs[MI_INIT_MODE_REG] = GETDATA(curr, uint32_t);
state->g_r4300.mi.regs[MI_VERSION_REG] = GETDATA(curr, uint32_t);
state->g_r4300.mi.regs[MI_INTR_REG] = GETDATA(curr, uint32_t);
state->g_r4300.mi.regs[MI_INTR_MASK_REG] = GETDATA(curr, uint32_t);
// vi_register
state->g_vi.regs[VI_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_ORIGIN_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_WIDTH_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_V_INTR_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_CURRENT_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_BURST_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_V_SYNC_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_H_SYNC_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_LEAP_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_H_START_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_V_START_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_V_BURST_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_X_SCALE_REG] = GETDATA(curr, uint32_t);
state->g_vi.regs[VI_Y_SCALE_REG] = GETDATA(curr, uint32_t);
state->g_vi.delay = (state->g_vi.regs[VI_V_SYNC_REG] == 0)
? 500000
: (state->g_vi.regs[VI_V_SYNC_REG] + 1)*1500;
// ai_register
state->g_ai.regs[AI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_LEN_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_CONTROL_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_DACRATE_REG] = GETDATA(curr, uint32_t);
state->g_ai.regs[AI_BITRATE_REG] = GETDATA(curr, uint32_t);
state->g_ai.samples_format_changed = 1;
// XXX USF
state->g_ai.regs[AI_STATUS_REG] = 0;
// pi_register
state->g_pi.regs[PI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_CART_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_RD_LEN_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_WR_LEN_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_STATUS_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM1_LAT_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM1_PWD_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM1_PGS_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM1_RLS_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM2_LAT_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM2_PWD_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM2_PGS_REG] = GETDATA(curr, uint32_t);
state->g_pi.regs[PI_BSD_DOM2_RLS_REG] = GETDATA(curr, uint32_t);
// ri_register
state->g_ri.regs[RI_MODE_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_CONFIG_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_CURRENT_LOAD_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_SELECT_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_REFRESH_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_LATENCY_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_ERROR_REG] = GETDATA(curr, uint32_t);
state->g_ri.regs[RI_WERROR_REG] = GETDATA(curr, uint32_t);
// si_register
state->g_si.regs[SI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
state->g_si.regs[SI_PIF_ADDR_RD64B_REG] = GETDATA(curr, uint32_t);
state->g_si.regs[SI_PIF_ADDR_WR64B_REG] = GETDATA(curr, uint32_t);
state->g_si.regs[SI_STATUS_REG] = GETDATA(curr, uint32_t);
// tlb
memset(state->tlb_LUT_r, 0, 0x400000);
memset(state->tlb_LUT_w, 0, 0x400000);
for (i=0; i < 32; i++)
{
unsigned int MyPageMask, MyEntryHi, MyEntryLo0, MyEntryLo1;
(void)GETDATA(curr, unsigned int); // Dummy read - EntryDefined
MyPageMask = GETDATA(curr, unsigned int);
MyEntryHi = GETDATA(curr, unsigned int);
MyEntryLo0 = GETDATA(curr, unsigned int);
MyEntryLo1 = GETDATA(curr, unsigned int);
// This is copied from TLBWI instruction
state->tlb_e[i].g = (MyEntryLo0 & MyEntryLo1 & 1);
state->tlb_e[i].pfn_even = (MyEntryLo0 & 0x3FFFFFC0) >> 6;
state->tlb_e[i].pfn_odd = (MyEntryLo1 & 0x3FFFFFC0) >> 6;
state->tlb_e[i].c_even = (MyEntryLo0 & 0x38) >> 3;
state->tlb_e[i].c_odd = (MyEntryLo1 & 0x38) >> 3;
state->tlb_e[i].d_even = (MyEntryLo0 & 0x4) >> 2;
state->tlb_e[i].d_odd = (MyEntryLo1 & 0x4) >> 2;
state->tlb_e[i].v_even = (MyEntryLo0 & 0x2) >> 1;
state->tlb_e[i].v_odd = (MyEntryLo1 & 0x2) >> 1;
state->tlb_e[i].asid = (MyEntryHi & 0xFF);
state->tlb_e[i].vpn2 = (MyEntryHi & 0xFFFFE000) >> 13;
//state->tlb_e[i].r = (MyEntryHi & 0xC000000000000000LL) >> 62;
state->tlb_e[i].mask = (MyPageMask & 0x1FFE000) >> 13;
state->tlb_e[i].start_even = state->tlb_e[i].vpn2 << 13;
state->tlb_e[i].end_even = state->tlb_e[i].start_even+
(state->tlb_e[i].mask << 12) + 0xFFF;
state->tlb_e[i].phys_even = state->tlb_e[i].pfn_even << 12;
state->tlb_e[i].start_odd = state->tlb_e[i].end_even+1;
state->tlb_e[i].end_odd = state->tlb_e[i].start_odd+
(state->tlb_e[i].mask << 12) + 0xFFF;
state->tlb_e[i].phys_odd = state->tlb_e[i].pfn_odd << 12;
tlb_map(state, &state->tlb_e[i]);
}
// pif ram
COPYARRAY(state->g_si.pif.ram, curr, uint8_t, PIF_RAM_SIZE);
// RDRAM
memset(state->g_rdram, 0, RDRAM_MAX_SIZE);
COPYARRAY(state->g_rdram, curr, uint32_t, SaveRDRAMSize/4);
// DMEM + IMEM
COPYARRAY(state->g_sp.mem, curr, uint32_t, SP_MEM_SIZE/4);
// The following values should not matter because we don't have any AI interrupt
// g_ai.fifo[1].delay = 0; g_ai.fifo[1].length = 0;
// g_ai.fifo[0].delay = 0; g_ai.fifo[0].length = 0;
// The following is not available in PJ64 savestate. Keep the values as is.
// g_dp.dps_regs[DPS_TBIST_REG] = 0; g_dp.dps_regs[DPS_TEST_MODE_REG] = 0;
// g_dp.dps_regs[DPS_BUFTEST_ADDR_REG] = 0; g_dp.dps_regs[DPS_BUFTEST_DATA_REG] = 0; llbit = 0;
// No flashram info in pj64 savestate.
//init_flashram(&state->g_pi.flashram);
open_rom_header(state, savestateData, sizeof(m64p_rom_header));
#ifdef NEW_DYNAREC
if (state->r4300emu == CORE_DYNAREC) {
state->pcaddr = state->last_addr;
state->pending_exception = 1;
invalidate_all_pages(state);
} else {
if(state->r4300emu != CORE_PURE_INTERPRETER)
{
for (i = 0; i < 0x100000; i++)
state->invalid_code[i] = 1;
}
generic_jump_to(state, state->last_addr);
}
#else
if(state->r4300emu != CORE_PURE_INTERPRETER)
{
for (i = 0; i < 0x100000; i++)
state->invalid_code[i] = 1;
}
#ifdef DYNAREC
*(void **)&state->return_address = (void *)&dummy;
#endif
generic_jump_to(state, state->last_addr);
#ifdef DYNAREC
*(void **)&state->return_address = (void *)0;
#endif
#endif
// assert(savestateData+savestateSize == curr)
free(savestateData);
return 1;
}
int savestates_load(usf_state_t * state, unsigned char * ptr, unsigned int size, unsigned int is_m64p)
{
if (is_m64p)
return savestates_load_m64p(state, ptr, size);
else
return savestates_load_pj64(state, ptr, size);
}