Skip to content

Instantly share code, notes, and snippets.

@andres-asm
Created January 29, 2017 20:12
Show Gist options
  • Select an option

  • Save andres-asm/c16a5f1a7e191706fd13bbd2f55ac8d3 to your computer and use it in GitHub Desktop.

Select an option

Save andres-asm/c16a5f1a7e191706fd13bbd2f55ac8d3 to your computer and use it in GitHub Desktop.
diff --git a/libretro/libretro.c b/libretro/libretro.c
index c4b515a..b2d36e7 100644
--- a/libretro/libretro.c
+++ b/libretro/libretro.c
@@ -934,13 +934,14 @@ bool retro_serialize(void *data, size_t size)
if (initializing)
return false;
- const char* filename = ConfigGetSharedDataFilepath("savestate.temp");
- int success = savestates_save_m64p((char*)filename);
- FILE *read_ptr;
- read_ptr = fopen(filename, "rb");
- int read_size = fread(data, size, 1, read_ptr);
- fclose(read_ptr);
- remove(filename);
+ int success = savestates_save_libretro(data, size);
+
+ for (int i = 0; i < 46; i++)
+ {
+ printf ("%d\n", *((char*)data + i));
+ fflush (stdout);
+ }
+
if (success)
return true;
@@ -951,14 +952,8 @@ bool retro_unserialize(const void * data, size_t size)
{
if (initializing)
return false;
-
- FILE *write_ptr;
- const char* filename = ConfigGetSharedDataFilepath("savestate.temp");
- write_ptr = fopen(filename,"wb");
- fwrite(data, size, 1, write_ptr);
- fclose(write_ptr);
- int success = savestates_load_m64p((char*)filename);
- remove(filename);
+ log_cb(RETRO_LOG_ERROR, "data: %d\n", data);
+ int success = savestates_load_libretro(data, size);
if (success)
return true;
diff --git a/mupen64plus-core/src/main/savestates.c b/mupen64plus-core/src/main/savestates.c
index 23cf508..e7071d2 100644
--- a/mupen64plus-core/src/main/savestates.c
+++ b/mupen64plus-core/src/main/savestates.c
@@ -515,6 +515,303 @@ int savestates_load_m64p(char *filepath)
return 1;
}
+int savestates_load_libretro(const void *data, size_t size)
+{
+ unsigned char header[44];
+ unsigned int version;
+ int i;
+ uint32_t FCR31;
+
+ size_t savestateSize = size;
+ unsigned char *savestateData, *curr;
+ char queue[1024];
+ unsigned char additionalData[4];
+ char filepath[10] = "libretro";
+
+ curr = (unsigned char *)malloc(savestateSize);
+ memcpy (curr, data, savestateSize);
+
+
+ uint32_t* cp0_regs = r4300_cp0_regs();
+
+ for (int i = 0; i < 200; i++)
+ {
+ printf ("%d: %d %c\n", i ,*(curr + i),*(curr + i));
+ fflush (stdout);
+ }
+ /* Read and check Mupen64Plus magic number. */
+
+ for (i = 0; i < 45; i++)
+ {
+ printf ("%d: %d %c\n", i ,*(curr + i),*(curr + i));
+ fflush (stdout);
+ }
+
+ if(strncmp((char *)curr, savestate_magic, 8)!=0)
+ {
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State file: %s is not a valid Mupen64plus savestate.", filepath);
+ return 0;
+ }
+ else
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State file valid");
+ curr += 8;
+
+ version = *curr++;
+ version = (version << 8) | *curr++;
+ version = (version << 8) | *curr++;
+ version = (version << 8) | *curr++;
+ if((version >> 16) != (savestate_latest_version >> 16))
+ {
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State version (%08x) isn't compatible. Please update Mupen64Plus.", version);
+ return 0;
+ }
+ else
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State file valid %08x", version);
+
+ if(memcmp((char *)curr, ROM_SETTINGS.MD5, 32))
+ {
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State ROM MD5 does not match current ROM.");
+
+ return 0;
+ }
+ else
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State file valid");
+ curr += 32;
+
+ /* Read the rest of the savestate */
+ savestateSize = 16788244;
+ savestateData = curr = (unsigned char *)malloc(savestateSize);
+ if (savestateData == NULL)
+ {
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Insufficient memory to load state.");
+
+ return 0;
+ }
+ if (version == 0x00010000) /* original savestate version */
+ {
+ if (*(savestateData + savestateSize) != savestateSize ||
+ (*(queue + sizeof(queue)) % 4) != 0)
+ {
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Could not read Mupen64Plus savestate 1.0 data from %s", filepath);
+ free(savestateData);
+
+
+ return 0;
+ }
+ }
+ else // version >= 0x00010100 saves entire eventqueue plus 4-byte using_tlb flage
+ {
+ /*if (gzread(f, savestateData, savestateSize) != savestateSize ||
+ gzread(f, queue, sizeof(queue)) != sizeof(queue) ||
+ gzread(f, additionalData, sizeof(additionalData)) != sizeof(additionalData))
+ {
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "Could not read Mupen64Plus savestate 1.1 data from %s", filepath);
+ free(savestateData);
+ gzclose(f);
+
+ return 0;
+ }*/
+ memcpy(savestateData, data, savestateSize);
+ memcpy(queue, data, sizeof(queue));
+ memcpy(additionalData, data, sizeof(additionalData));
+
+ }
+
+ // Parse savestate
+ g_dev.ri.rdram.regs[RDRAM_CONFIG_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_DEVICE_ID_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_DELAY_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_MODE_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_REF_INTERVAL_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_REF_ROW_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_RAS_INTERVAL_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_MIN_INTERVAL_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_ADDR_SELECT_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.rdram.regs[RDRAM_DEVICE_MANUF_REG] = GETDATA(curr, uint32_t);
+
+ curr += 4; /* Padding from old implementation */
+ g_dev.r4300.mi.regs[MI_INIT_MODE_REG] = GETDATA(curr, uint32_t);
+ curr += 4; // Duplicate MI init mode flags from old implementation
+ g_dev.r4300.mi.regs[MI_VERSION_REG] = GETDATA(curr, uint32_t);
+ g_dev.r4300.mi.regs[MI_INTR_REG] = GETDATA(curr, uint32_t);
+ g_dev.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
+
+ g_dev.pi.regs[PI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_CART_ADDR_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_RD_LEN_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_WR_LEN_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_STATUS_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_BSD_DOM1_LAT_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_BSD_DOM1_PWD_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_BSD_DOM1_PGS_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_BSD_DOM1_RLS_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_BSD_DOM2_LAT_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_BSD_DOM2_PWD_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_BSD_DOM2_PGS_REG] = GETDATA(curr, uint32_t);
+ g_dev.pi.regs[PI_BSD_DOM2_RLS_REG] = GETDATA(curr, uint32_t);
+
+ g_dev.sp.regs[SP_MEM_ADDR_REG] = GETDATA(curr, uint32_t);
+ g_dev.sp.regs[SP_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
+ g_dev.sp.regs[SP_RD_LEN_REG] = GETDATA(curr, uint32_t);
+ g_dev.sp.regs[SP_WR_LEN_REG] = GETDATA(curr, uint32_t);
+ curr += 4; /* Padding from old implementation */
+ g_dev.sp.regs[SP_STATUS_REG] = GETDATA(curr, uint32_t);
+ curr += 16; // Duplicated SP flags and padding from old implementation
+ g_dev.sp.regs[SP_DMA_FULL_REG] = GETDATA(curr, uint32_t);
+ g_dev.sp.regs[SP_DMA_BUSY_REG] = GETDATA(curr, uint32_t);
+ g_dev.sp.regs[SP_SEMAPHORE_REG] = GETDATA(curr, uint32_t);
+
+ g_dev.sp.regs2[SP_PC_REG] = GETDATA(curr, uint32_t);
+ g_dev.sp.regs2[SP_IBIST_REG] = GETDATA(curr, uint32_t);
+
+ g_dev.si.regs[SI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
+ g_dev.si.regs[SI_PIF_ADDR_RD64B_REG] = GETDATA(curr, uint32_t);
+ g_dev.si.regs[SI_PIF_ADDR_WR64B_REG] = GETDATA(curr, uint32_t);
+ g_dev.si.regs[SI_STATUS_REG] = GETDATA(curr, uint32_t);
+
+ g_dev.vi.regs[VI_STATUS_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_ORIGIN_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_WIDTH_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_V_INTR_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_CURRENT_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_BURST_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_V_SYNC_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_H_SYNC_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_LEAP_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_H_START_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_V_START_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_V_BURST_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_X_SCALE_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.regs[VI_Y_SCALE_REG] = GETDATA(curr, uint32_t);
+ g_dev.vi.delay = GETDATA(curr, unsigned int);
+ gfx.viStatusChanged();
+ gfx.viWidthChanged();
+
+ g_dev.ri.regs[RI_MODE_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.regs[RI_CONFIG_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.regs[RI_CURRENT_LOAD_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.regs[RI_SELECT_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.regs[RI_REFRESH_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.regs[RI_LATENCY_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.regs[RI_ERROR_REG] = GETDATA(curr, uint32_t);
+ g_dev.ri.regs[RI_WERROR_REG] = GETDATA(curr, uint32_t);
+
+ g_dev.ai.regs[AI_DRAM_ADDR_REG] = GETDATA(curr, uint32_t);
+ g_dev.ai.regs[AI_LEN_REG] = GETDATA(curr, uint32_t);
+ g_dev.ai.regs[AI_CONTROL_REG] = GETDATA(curr, uint32_t);
+ g_dev.ai.regs[AI_STATUS_REG] = GETDATA(curr, uint32_t);
+ g_dev.ai.regs[AI_DACRATE_REG] = GETDATA(curr, uint32_t);
+ g_dev.ai.regs[AI_BITRATE_REG] = GETDATA(curr, uint32_t);
+ g_dev.ai.fifo[1].duration = GETDATA(curr, unsigned int);
+ g_dev.ai.fifo[1].length = GETDATA(curr, uint32_t);
+ g_dev.ai.fifo[0].duration = GETDATA(curr, unsigned int);
+ g_dev.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
+ */
+ g_dev.ai.fifo[0].address = g_dev.ai.regs[AI_DRAM_ADDR_REG];
+ g_dev.ai.fifo[1].address = g_dev.ai.regs[AI_DRAM_ADDR_REG];
+ g_dev.ai.samples_format_changed = 1;
+
+ g_dev.dp.dpc_regs[DPC_START_REG] = GETDATA(curr, uint32_t);
+ g_dev.dp.dpc_regs[DPC_END_REG] = GETDATA(curr, uint32_t);
+ g_dev.dp.dpc_regs[DPC_CURRENT_REG] = GETDATA(curr, uint32_t);
+ curr += 4; // Padding from old implementation
+ g_dev.dp.dpc_regs[DPC_STATUS_REG] = GETDATA(curr, uint32_t);
+ curr += 12; // Duplicated DPC flags and padding from old implementation
+ g_dev.dp.dpc_regs[DPC_CLOCK_REG] = GETDATA(curr, uint32_t);
+ g_dev.dp.dpc_regs[DPC_BUFBUSY_REG] = GETDATA(curr, uint32_t);
+ g_dev.dp.dpc_regs[DPC_PIPEBUSY_REG] = GETDATA(curr, uint32_t);
+ g_dev.dp.dpc_regs[DPC_TMEM_REG] = GETDATA(curr, uint32_t);
+
+ g_dev.dp.dps_regs[DPS_TBIST_REG] = GETDATA(curr, uint32_t);
+ g_dev.dp.dps_regs[DPS_TEST_MODE_REG] = GETDATA(curr, uint32_t);
+ g_dev.dp.dps_regs[DPS_BUFTEST_ADDR_REG] = GETDATA(curr, uint32_t);
+ g_dev.dp.dps_regs[DPS_BUFTEST_DATA_REG] = GETDATA(curr, uint32_t);
+
+ COPYARRAY(g_dev.ri.rdram.dram, curr, uint32_t, RDRAM_MAX_SIZE/4);
+ COPYARRAY(g_dev.sp.mem, curr, uint32_t, SP_MEM_SIZE/4);
+ COPYARRAY(g_dev.si.pif.ram, curr, uint8_t, PIF_RAM_SIZE);
+
+ g_dev.pi.use_flashram = GETDATA(curr, int);
+ g_dev.pi.flashram.mode = GETDATA(curr, int);
+ g_dev.pi.flashram.status = GETDATA(curr, unsigned long long);
+ g_dev.pi.flashram.erase_offset = GETDATA(curr, unsigned int);
+ g_dev.pi.flashram.write_pointer = GETDATA(curr, unsigned int);
+
+ COPYARRAY(tlb_LUT_r, curr, unsigned int, 0x100000);
+ COPYARRAY(tlb_LUT_w, curr, unsigned int, 0x100000);
+
+ *r4300_llbit() = GETDATA(curr, unsigned int);
+ COPYARRAY(r4300_regs(), curr, int64_t, 32);
+ COPYARRAY(cp0_regs, curr, uint32_t, CP0_REGS_COUNT);
+ set_fpr_pointers(cp0_regs[CP0_STATUS_REG]);
+ *r4300_mult_lo() = GETDATA(curr, int64_t);
+ *r4300_mult_hi() = GETDATA(curr, int64_t);
+ COPYARRAY(r4300_cp1_regs(), curr, int64_t, 32);
+ if ((cp0_regs[CP0_STATUS_REG] & UINT32_C(0x04000000)) == 0) // 32-bit FPR mode requires data shuffling because 64-bit layout is always stored in savestate file
+ shuffle_fpr_data(UINT32_C(0x04000000), 0);
+ *r4300_cp1_fcr0() = GETDATA(curr, uint32_t);
+ FCR31 = GETDATA(curr, uint32_t);
+ *r4300_cp1_fcr31() = FCR31;
+ update_x86_rounding_mode(FCR31);
+
+ for (i = 0; i < 32; i++)
+ {
+ tlb_e[i].mask = GETDATA(curr, short);
+ curr += 2;
+ tlb_e[i].vpn2 = GETDATA(curr, int);
+ tlb_e[i].g = GETDATA(curr, char);
+ tlb_e[i].asid = GETDATA(curr, unsigned char);
+ curr += 2;
+ tlb_e[i].pfn_even = GETDATA(curr, int);
+ tlb_e[i].c_even = GETDATA(curr, char);
+ tlb_e[i].d_even = GETDATA(curr, char);
+ tlb_e[i].v_even = GETDATA(curr, char);
+ curr++;
+ tlb_e[i].pfn_odd = GETDATA(curr, int);
+ tlb_e[i].c_odd = GETDATA(curr, char);
+ tlb_e[i].d_odd = GETDATA(curr, char);
+ tlb_e[i].v_odd = GETDATA(curr, char);
+ tlb_e[i].r = GETDATA(curr, char);
+
+ tlb_e[i].start_even = GETDATA(curr, unsigned int);
+ tlb_e[i].end_even = GETDATA(curr, unsigned int);
+ tlb_e[i].phys_even = GETDATA(curr, unsigned int);
+ tlb_e[i].start_odd = GETDATA(curr, unsigned int);
+ tlb_e[i].end_odd = GETDATA(curr, unsigned int);
+ tlb_e[i].phys_odd = GETDATA(curr, unsigned int);
+ }
+
+ savestates_load_set_pc(GETDATA(curr, uint32_t));
+
+ *r4300_next_interrupt() = GETDATA(curr, unsigned int);
+ g_dev.vi.next_vi = GETDATA(curr, unsigned int);
+ g_dev.vi.field = GETDATA(curr, unsigned int);
+
+ // assert(savestateData+savestateSize == curr)
+
+ to_little_endian_buffer(queue, 4, 256);
+ load_eventqueue_infos(queue);
+
+
+#ifdef NEW_DYNAREC
+ if (version >= 0x00010100)
+ {
+ curr = additionalData;
+ using_tlb = GETDATA(curr, unsigned int);
+ }
+#endif
+
+ *r4300_last_addr() = *r4300_pc();
+ free(savestateData);
+ main_message(M64MSG_STATUS, OSD_BOTTOM_LEFT, "State loaded from: %s", namefrompath(filepath));
+ return 1;
+}
+
static int savestates_load_pj64(char *filepath, void *handle,
int (*read_func)(void *, void *, size_t))
{
@@ -1263,6 +1560,263 @@ int savestates_save_m64p(char *filepath)
return 1;
}
+int savestates_save_libretro(void *out, size_t size)
+{
+ unsigned char outbuf[4];
+ int i;
+
+ char queue[1024];
+
+ struct savestate_work *save;
+ char *curr;
+
+ uint32_t* cp0_regs = r4300_cp0_regs();
+
+ save = malloc(sizeof(*save));
+ if (!save) {
+ return 0;
+ }
+
+ save_eventqueue_infos(queue);
+
+ // Allocate memory for the save state data
+ save->size = 16788288 + sizeof(queue) + 4;
+ save->data = curr = malloc(save->size);
+ if (save->data == NULL)
+ {
+ free(save);
+ return 0;
+ }
+
+ memset(save->data, 0, save->size);
+
+ // Write the save state data to memory
+ PUTARRAY(savestate_magic, curr, unsigned char, 8);
+
+ outbuf[0] = (savestate_latest_version >> 24) & 0xff;
+ outbuf[1] = (savestate_latest_version >> 16) & 0xff;
+ outbuf[2] = (savestate_latest_version >> 8) & 0xff;
+ outbuf[3] = (savestate_latest_version >> 0) & 0xff;
+ PUTARRAY(outbuf, curr, unsigned char, 4);
+
+ PUTARRAY(ROM_SETTINGS.MD5, curr, char, 32);
+
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_CONFIG_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_DEVICE_ID_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_DELAY_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_MODE_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_REF_INTERVAL_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_REF_ROW_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_RAS_INTERVAL_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_MIN_INTERVAL_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_ADDR_SELECT_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.rdram.regs[RDRAM_DEVICE_MANUF_REG]);
+
+ PUTDATA(curr, uint32_t, 0); // Padding from old implementation
+ PUTDATA(curr, uint32_t, g_dev.r4300.mi.regs[MI_INIT_MODE_REG]);
+ PUTDATA(curr, uint8_t, g_dev.r4300.mi.regs[MI_INIT_MODE_REG] & 0x7F);
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INIT_MODE_REG] & 0x80) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INIT_MODE_REG] & 0x100) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INIT_MODE_REG] & 0x200) != 0);
+ PUTDATA(curr, uint32_t, g_dev.r4300.mi.regs[MI_VERSION_REG]);
+ PUTDATA(curr, uint32_t, g_dev.r4300.mi.regs[MI_INTR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.r4300.mi.regs[MI_INTR_MASK_REG]);
+ PUTDATA(curr, uint32_t, 0); //Padding from old implementation
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INTR_MASK_REG] & 0x1) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INTR_MASK_REG] & 0x2) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INTR_MASK_REG] & 0x4) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INTR_MASK_REG] & 0x8) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INTR_MASK_REG] & 0x10) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.r4300.mi.regs[MI_INTR_MASK_REG] & 0x20) != 0);
+ PUTDATA(curr, uint16_t, 0); // Padding from old implementation
+
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_DRAM_ADDR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_CART_ADDR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_RD_LEN_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_WR_LEN_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_STATUS_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_BSD_DOM1_LAT_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_BSD_DOM1_PWD_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_BSD_DOM1_PGS_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_BSD_DOM1_RLS_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_BSD_DOM2_LAT_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_BSD_DOM2_PWD_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_BSD_DOM2_PGS_REG]);
+ PUTDATA(curr, uint32_t, g_dev.pi.regs[PI_BSD_DOM2_RLS_REG]);
+
+ PUTDATA(curr, uint32_t, g_dev.sp.regs[SP_MEM_ADDR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.sp.regs[SP_DRAM_ADDR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.sp.regs[SP_RD_LEN_REG]);
+ PUTDATA(curr, uint32_t, g_dev.sp.regs[SP_WR_LEN_REG]);
+ PUTDATA(curr, uint32_t, 0); /* Padding from old implementation */
+ PUTDATA(curr, uint32_t, g_dev.sp.regs[SP_STATUS_REG]);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x1) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x2) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x4) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x8) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x10) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x20) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x40) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x80) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x100) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x200) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x400) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x800) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x1000) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x2000) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.sp.regs[SP_STATUS_REG] & 0x4000) != 0);
+ PUTDATA(curr, uint8_t, 0);
+ PUTDATA(curr, uint32_t, g_dev.sp.regs[SP_DMA_FULL_REG]);
+ PUTDATA(curr, uint32_t, g_dev.sp.regs[SP_DMA_BUSY_REG]);
+ PUTDATA(curr, uint32_t, g_dev.sp.regs[SP_SEMAPHORE_REG]);
+
+ PUTDATA(curr, uint32_t, g_dev.sp.regs2[SP_PC_REG]);
+ PUTDATA(curr, uint32_t, g_dev.sp.regs2[SP_IBIST_REG]);
+
+ PUTDATA(curr, uint32_t, g_dev.si.regs[SI_DRAM_ADDR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.si.regs[SI_PIF_ADDR_RD64B_REG]);
+ PUTDATA(curr, uint32_t, g_dev.si.regs[SI_PIF_ADDR_WR64B_REG]);
+ PUTDATA(curr, uint32_t, g_dev.si.regs[SI_STATUS_REG]);
+
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_STATUS_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_ORIGIN_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_WIDTH_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_V_INTR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_CURRENT_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_BURST_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_V_SYNC_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_H_SYNC_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_LEAP_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_H_START_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_V_START_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_V_BURST_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_X_SCALE_REG]);
+ PUTDATA(curr, uint32_t, g_dev.vi.regs[VI_Y_SCALE_REG]);
+ PUTDATA(curr, unsigned int, g_dev.vi.delay);
+
+ PUTDATA(curr, uint32_t, g_dev.ri.regs[RI_MODE_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.regs[RI_CONFIG_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.regs[RI_CURRENT_LOAD_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.regs[RI_SELECT_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.regs[RI_REFRESH_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.regs[RI_LATENCY_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.regs[RI_ERROR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ri.regs[RI_WERROR_REG]);
+
+ PUTDATA(curr, uint32_t, g_dev.ai.regs[AI_DRAM_ADDR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ai.regs[AI_LEN_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ai.regs[AI_CONTROL_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ai.regs[AI_STATUS_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ai.regs[AI_DACRATE_REG]);
+ PUTDATA(curr, uint32_t, g_dev.ai.regs[AI_BITRATE_REG]);
+ PUTDATA(curr, unsigned int, g_dev.ai.fifo[1].duration);
+ PUTDATA(curr, uint32_t , g_dev.ai.fifo[1].length);
+ PUTDATA(curr, unsigned int, g_dev.ai.fifo[0].duration);
+ PUTDATA(curr, uint32_t , g_dev.ai.fifo[0].length);
+
+ PUTDATA(curr, uint32_t, g_dev.dp.dpc_regs[DPC_START_REG]);
+ PUTDATA(curr, uint32_t, g_dev.dp.dpc_regs[DPC_END_REG]);
+ PUTDATA(curr, uint32_t, g_dev.dp.dpc_regs[DPC_CURRENT_REG]);
+ PUTDATA(curr, uint32_t, 0); /* Padding from old implementation */
+ PUTDATA(curr, uint32_t, g_dev.dp.dpc_regs[DPC_STATUS_REG]);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x1) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x2) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x4) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x8) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x10) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x20) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x40) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x80) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x100) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x200) != 0);
+ PUTDATA(curr, uint8_t, (g_dev.dp.dpc_regs[DPC_STATUS_REG] & 0x400) != 0);
+ PUTDATA(curr, uint8_t, 0);
+ PUTDATA(curr, uint32_t, g_dev.dp.dpc_regs[DPC_CLOCK_REG]);
+ PUTDATA(curr, uint32_t, g_dev.dp.dpc_regs[DPC_BUFBUSY_REG]);
+ PUTDATA(curr, uint32_t, g_dev.dp.dpc_regs[DPC_PIPEBUSY_REG]);
+ PUTDATA(curr, uint32_t, g_dev.dp.dpc_regs[DPC_TMEM_REG]);
+
+ PUTDATA(curr, uint32_t, g_dev.dp.dps_regs[DPS_TBIST_REG]);
+ PUTDATA(curr, uint32_t, g_dev.dp.dps_regs[DPS_TEST_MODE_REG]);
+ PUTDATA(curr, uint32_t, g_dev.dp.dps_regs[DPS_BUFTEST_ADDR_REG]);
+ PUTDATA(curr, uint32_t, g_dev.dp.dps_regs[DPS_BUFTEST_DATA_REG]);
+
+ PUTARRAY(g_dev.ri.rdram.dram, curr, uint32_t, RDRAM_MAX_SIZE/4);
+ PUTARRAY(g_dev.sp.mem, curr, uint32_t, SP_MEM_SIZE/4);
+ PUTARRAY(g_dev.si.pif.ram, curr, uint8_t, PIF_RAM_SIZE);
+
+ PUTDATA(curr, int, g_dev.pi.use_flashram);
+ PUTDATA(curr, int, g_dev.pi.flashram.mode);
+ PUTDATA(curr, unsigned long long, g_dev.pi.flashram.status);
+ PUTDATA(curr, unsigned int, g_dev.pi.flashram.erase_offset);
+ PUTDATA(curr, unsigned int, g_dev.pi.flashram.write_pointer);
+
+ PUTARRAY(tlb_LUT_r, curr, unsigned int, 0x100000);
+ PUTARRAY(tlb_LUT_w, curr, unsigned int, 0x100000);
+
+ PUTDATA(curr, unsigned int, *r4300_llbit());
+ PUTARRAY(r4300_regs(), curr, int64_t, 32);
+ PUTARRAY(cp0_regs, curr, uint32_t, CP0_REGS_COUNT);
+ PUTDATA(curr, int64_t, *r4300_mult_lo());
+ PUTDATA(curr, int64_t, *r4300_mult_hi());
+
+ if ((cp0_regs[CP0_STATUS_REG] & UINT32_C(0x04000000)) == 0) // FR bit == 0 means 32-bit (MIPS I) FGR mode
+ shuffle_fpr_data(0, UINT32_C(0x04000000)); // shuffle data into 64-bit register format for storage
+ PUTARRAY(r4300_cp1_regs(), curr, int64_t, 32);
+ if ((cp0_regs[CP0_STATUS_REG] & UINT32_C(0x04000000)) == 0)
+ shuffle_fpr_data(UINT32_C(0x04000000), 0); // put it back in 32-bit mode
+
+ PUTDATA(curr, uint32_t, *r4300_cp1_fcr0());
+ PUTDATA(curr, uint32_t, *r4300_cp1_fcr31());
+ for (i = 0; i < 32; i++)
+ {
+ PUTDATA(curr, short, tlb_e[i].mask);
+ PUTDATA(curr, short, 0);
+ PUTDATA(curr, int, tlb_e[i].vpn2);
+ PUTDATA(curr, char, tlb_e[i].g);
+ PUTDATA(curr, unsigned char, tlb_e[i].asid);
+ PUTDATA(curr, short, 0);
+ PUTDATA(curr, int, tlb_e[i].pfn_even);
+ PUTDATA(curr, char, tlb_e[i].c_even);
+ PUTDATA(curr, char, tlb_e[i].d_even);
+ PUTDATA(curr, char, tlb_e[i].v_even);
+ PUTDATA(curr, char, 0);
+ PUTDATA(curr, int, tlb_e[i].pfn_odd);
+ PUTDATA(curr, char, tlb_e[i].c_odd);
+ PUTDATA(curr, char, tlb_e[i].d_odd);
+ PUTDATA(curr, char, tlb_e[i].v_odd);
+ PUTDATA(curr, char, tlb_e[i].r);
+
+ PUTDATA(curr, unsigned int, tlb_e[i].start_even);
+ PUTDATA(curr, unsigned int, tlb_e[i].end_even);
+ PUTDATA(curr, unsigned int, tlb_e[i].phys_even);
+ PUTDATA(curr, unsigned int, tlb_e[i].start_odd);
+ PUTDATA(curr, unsigned int, tlb_e[i].end_odd);
+ PUTDATA(curr, unsigned int, tlb_e[i].phys_odd);
+ }
+ PUTDATA(curr, uint32_t, *r4300_pc());
+
+ PUTDATA(curr, unsigned int, *r4300_next_interrupt());
+ PUTDATA(curr, unsigned int, g_dev.vi.next_vi);
+ PUTDATA(curr, unsigned int, g_dev.vi.field);
+
+ to_little_endian_buffer(queue, 4, sizeof(queue)/4);
+ PUTARRAY(queue, curr, char, sizeof(queue));
+
+#ifdef NEW_DYNAREC
+ PUTDATA(curr, unsigned int, using_tlb);
+#else
+ PUTDATA(curr, unsigned int, 0);
+#endif
+ memcpy (out, save->data, size);
+ for (int i = 0; i < 100; i++)
+ {
+ printf ("%d %d\n", *(save->data + i),*((char*)out + i));
+ fflush (stdout);
+ }
+ return 1;
+}
+
static int savestates_save_pj64(char *filepath, void *handle,
int (*write_func)(void *, const void *, size_t))
{
diff --git a/mupen64plus-core/src/main/savestates.h b/mupen64plus-core/src/main/savestates.h
index 17f97bc..caf5aa5 100644
--- a/mupen64plus-core/src/main/savestates.h
+++ b/mupen64plus-core/src/main/savestates.h
@@ -51,6 +51,9 @@ int savestates_save(void);
int savestates_save_m64p(char *filepath);
int savestates_load_m64p(char *filepath);
+int savestates_save_libretro(void *out, size_t size);
+int savestates_load_libretro(const void *data, size_t size);
+
void savestates_select_slot(unsigned int s);
unsigned int savestates_get_slot(void);
void savestates_set_autoinc_slot(int b);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment