32x: memhandler improvements
[picodrive.git] / pico / state.c
index 60a6f72..de2d8ab 100644 (file)
@@ -1,24 +1,21 @@
-// (c) Copyright 2004 Dave, All rights reserved.\r
-// (c) Copyright 2006-2010 notaz, All rights reserved.\r
-// Free for non-commercial use.\r
-\r
-// For commercial use, separate licencing terms must be obtained.\r
-\r
+/*\r
+ * PicoDrive\r
+ * (C) notaz, 2010\r
+ *\r
+ * This work is licensed under the terms of MAME license.\r
+ * See COPYING file in the top-level directory.\r
+ */\r
 \r
 #include "pico_int.h"\r
 #include <zlib/zlib.h>\r
 \r
 #include "../cpu/sh2/sh2.h"\r
 #include "sound/ym2612.h"\r
+#include "state.h"\r
 \r
 // sn76496\r
 extern int *sn76496_regs;\r
 \r
-typedef size_t (arearw)(void *p, size_t _size, size_t _n, void *file);\r
-typedef size_t (areaeof)(void *file);\r
-typedef int    (areaseek)(void *file, long offset, int whence);\r
-typedef int    (areaclose)(void *file);\r
-\r
 static arearw    *areaRead;\r
 static arearw    *areaWrite;\r
 static areaeof   *areaEof;\r
@@ -173,6 +170,9 @@ typedef enum {
   CHUNK_SDRAM,\r
   CHUNK_DRAM,\r
   CHUNK_32XPAL,\r
+  CHUNK_32X_EVT,\r
+  CHUNK_32X_FIRST = CHUNK_MSH2,\r
+  CHUNK_32X_LAST = CHUNK_32X_EVT,\r
   //\r
   CHUNK_DEFAULT_COUNT,\r
   CHUNK_CARTHW_ = CHUNK_CARTHW,  // defined in PicoInt\r
@@ -221,6 +221,7 @@ static const char * const chunk_names[] = {
   "SDRAM",\r
   "DRAM",\r
   "PAL",\r
+  "events",\r
 };\r
 \r
 static int write_chunk(chunk_name_e name, int len, void *data, void *file)\r
@@ -308,6 +309,7 @@ static int state_save(void *file)
       wram_2M_to_1M(Pico_mcd->word_ram2M);\r
   }\r
 \r
+#ifndef NO_32X\r
   if (PicoAHW & PAHW_32X)\r
   {\r
     unsigned char cpubuff[SH2_STATE_SIZE];\r
@@ -316,13 +318,13 @@ static int state_save(void *file)
 \r
     sh2_pack(&sh2s[0], cpubuff);\r
     CHECKED_WRITE_BUFF(CHUNK_MSH2,      cpubuff);\r
-    CHECKED_WRITE_BUFF(CHUNK_MSH2_DATA, Pico32xMem->data_array[0]);\r
-    CHECKED_WRITE_BUFF(CHUNK_MSH2_PERI, Pico32xMem->sh2_peri_regs[0]);\r
+    CHECKED_WRITE_BUFF(CHUNK_MSH2_DATA, sh2s[0].data_array);\r
+    CHECKED_WRITE_BUFF(CHUNK_MSH2_PERI, sh2s[0].peri_regs);\r
 \r
     sh2_pack(&sh2s[1], cpubuff);\r
     CHECKED_WRITE_BUFF(CHUNK_SSH2,      cpubuff);\r
-    CHECKED_WRITE_BUFF(CHUNK_SSH2_DATA, Pico32xMem->data_array[1]);\r
-    CHECKED_WRITE_BUFF(CHUNK_SSH2_PERI, Pico32xMem->sh2_peri_regs[1]);\r
+    CHECKED_WRITE_BUFF(CHUNK_SSH2_DATA, sh2s[1].data_array);\r
+    CHECKED_WRITE_BUFF(CHUNK_SSH2_PERI, sh2s[1].peri_regs);\r
 \r
     CHECKED_WRITE_BUFF(CHUNK_32XSYS,    Pico32x);\r
     CHECKED_WRITE_BUFF(CHUNK_M68K_BIOS, Pico32xMem->m68k_rom);\r
@@ -331,7 +333,12 @@ static int state_save(void *file)
     CHECKED_WRITE_BUFF(CHUNK_SDRAM,     Pico32xMem->sdram);\r
     CHECKED_WRITE_BUFF(CHUNK_DRAM,      Pico32xMem->dram);\r
     CHECKED_WRITE_BUFF(CHUNK_32XPAL,    Pico32xMem->pal);\r
+\r
+    memset(buff, 0, 0x40);\r
+    memcpy(buff, event_times, sizeof(event_times));\r
+    CHECKED_WRITE(CHUNK_32X_EVT, 0x40, buff);\r
   }\r
+#endif\r
 \r
   if (carthw_chunks != NULL)\r
   {\r
@@ -379,11 +386,16 @@ static int state_load(void *file)
   unsigned char buff_m68k[0x60], buff_s68k[0x60];\r
   unsigned char buff_z80[Z80_STATE_SIZE];\r
   unsigned char buff_sh2[SH2_STATE_SIZE];\r
+  unsigned char buff[0x40];\r
   unsigned char chunk;\r
   void *ym2612_regs;\r
   char header[8];\r
   int ver, len;\r
 \r
+  memset(buff_m68k, 0, sizeof(buff_m68k));\r
+  memset(buff_s68k, 0, sizeof(buff_s68k));\r
+  memset(buff_z80, 0, sizeof(buff_z80));\r
+\r
   g_read_offs = 0;\r
   CHECKED_READ(8, header);\r
   if (strncmp(header, "PicoSMCD", 8) && strncmp(header, "PicoSEXT", 8))\r
@@ -397,8 +409,8 @@ static int state_load(void *file)
     if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");\r
     if (CHUNK_S68K <= chunk && chunk <= CHUNK_MISC_CD && !(PicoAHW & PAHW_MCD))\r
       R_ERROR_RETURN("cd chunk in non CD state?");\r
-    if (CHUNK_MSH2 <= chunk && chunk <= CHUNK_32XPAL && !(PicoAHW & PAHW_32X))\r
-      R_ERROR_RETURN("32x chunk in non 32x state?");\r
+    if (CHUNK_32X_FIRST <= chunk && chunk <= CHUNK_32X_LAST && !(PicoAHW & PAHW_32X))\r
+      Pico32xStartup();\r
 \r
     switch (chunk)\r
     {\r
@@ -408,7 +420,6 @@ static int state_load(void *file)
 \r
       case CHUNK_Z80:\r
         CHECKED_READ_BUFF(buff_z80);\r
-        z80_unpack(buff_z80);\r
         break;\r
 \r
       case CHUNK_RAM:     CHECKED_READ_BUFF(Pico.ram); break;\r
@@ -448,6 +459,7 @@ static int state_load(void *file)
       case CHUNK_MISC_CD:  CHECKED_READ_BUFF(Pico_mcd->m); break;\r
 \r
       // 32x stuff\r
+#ifndef NO_32X\r
       case CHUNK_MSH2:\r
         CHECKED_READ_BUFF(buff_sh2);\r
         sh2_unpack(&sh2s[0], buff_sh2);\r
@@ -458,10 +470,10 @@ static int state_load(void *file)
         sh2_unpack(&sh2s[1], buff_sh2);\r
         break;\r
 \r
-      case CHUNK_MSH2_DATA:   CHECKED_READ_BUFF(Pico32xMem->data_array[0]); break;\r
-      case CHUNK_MSH2_PERI:   CHECKED_READ_BUFF(Pico32xMem->sh2_peri_regs[0]); break;\r
-      case CHUNK_SSH2_DATA:   CHECKED_READ_BUFF(Pico32xMem->data_array[1]); break;\r
-      case CHUNK_SSH2_PERI:   CHECKED_READ_BUFF(Pico32xMem->sh2_peri_regs[1]); break;\r
+      case CHUNK_MSH2_DATA:   CHECKED_READ_BUFF(sh2s[0].data_array); break;\r
+      case CHUNK_MSH2_PERI:   CHECKED_READ_BUFF(sh2s[0].peri_regs); break;\r
+      case CHUNK_SSH2_DATA:   CHECKED_READ_BUFF(sh2s[1].data_array); break;\r
+      case CHUNK_SSH2_PERI:   CHECKED_READ_BUFF(sh2s[1].peri_regs); break;\r
       case CHUNK_32XSYS:      CHECKED_READ_BUFF(Pico32x); break;\r
       case CHUNK_M68K_BIOS:   CHECKED_READ_BUFF(Pico32xMem->m68k_rom); break;\r
       case CHUNK_MSH2_BIOS:   CHECKED_READ_BUFF(Pico32xMem->sh2_rom_m); break;\r
@@ -470,6 +482,11 @@ static int state_load(void *file)
       case CHUNK_DRAM:        CHECKED_READ_BUFF(Pico32xMem->dram); break;\r
       case CHUNK_32XPAL:      CHECKED_READ_BUFF(Pico32xMem->pal); break;\r
 \r
+      case CHUNK_32X_EVT:\r
+        CHECKED_READ_BUFF(buff);\r
+        memcpy(event_times, buff, sizeof(event_times));\r
+        break;\r
+#endif\r
       default:\r
         if (carthw_chunks != NULL)\r
         {\r
@@ -498,16 +515,22 @@ readend:
 \r
     if (!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1))\r
       cdda_start_play();\r
-\r
-    // must unpack after mem is set up\r
-    SekUnpackCpu(buff_s68k, 1);\r
   }\r
 \r
+  if (PicoAHW & PAHW_32X)\r
+    Pico32xStateLoaded(1);\r
+\r
+  // must unpack 68k and z80 after banks are set up\r
   if (!(PicoAHW & PAHW_SMS))\r
     SekUnpackCpu(buff_m68k, 0);\r
+  if (PicoAHW & PAHW_MCD)\r
+    SekUnpackCpu(buff_s68k, 1);\r
 \r
+  z80_unpack(buff_z80);\r
+\r
+  // due to dep from 68k cycles..\r
   if (PicoAHW & PAHW_32X)\r
-    Pico32xStateLoaded();\r
+    Pico32xStateLoaded(0);\r
 \r
   return 0;\r
 }\r
@@ -541,6 +564,7 @@ static int state_load_gfx(void *file)
       case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); found++; break;\r
       case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break;\r
 \r
+#ifndef NO_32X\r
       case CHUNK_DRAM:\r
         if (Pico32xMem != NULL)\r
           CHECKED_READ_BUFF(Pico32xMem->dram);\r
@@ -555,7 +579,7 @@ static int state_load_gfx(void *file)
       case CHUNK_32XSYS:\r
         CHECKED_READ_BUFF(Pico32x);\r
         break;\r
-\r
+#endif\r
       default:\r
         areaSeek(file, len, SEEK_CUR);\r
         break;\r
@@ -566,15 +590,10 @@ readend:
   return 0;\r
 }\r
 \r
-int PicoState(const char *fname, int is_save)\r
+static int pico_state_internal(void *afile, int is_save)\r
 {\r
-  void *afile = NULL;\r
   int ret;\r
 \r
-  afile = open_save_file(fname, is_save);\r
-  if (afile == NULL)\r
-    return -1;\r
-\r
   if (is_save)\r
     ret = state_save(afile);\r
   else {\r
@@ -589,10 +608,35 @@ int PicoState(const char *fname, int is_save)
     Pico.m.dirtyPal = 1;\r
   }\r
 \r
+  return ret;\r
+}\r
+\r
+int PicoState(const char *fname, int is_save)\r
+{\r
+  void *afile = NULL;\r
+  int ret;\r
+\r
+  afile = open_save_file(fname, is_save);\r
+  if (afile == NULL)\r
+    return -1;\r
+\r
+  ret = pico_state_internal(afile, is_save);\r
   areaClose(afile);\r
   return ret;\r
 }\r
 \r
+int PicoStateFP(void *afile, int is_save,\r
+  arearw *read, arearw *write, areaeof *eof, areaseek *seek)\r
+{\r
+  areaRead  = read;\r
+  areaWrite = write;\r
+  areaEof   = eof;\r
+  areaSeek  = seek;\r
+  areaClose = NULL;\r
+\r
+  return pico_state_internal(afile, is_save);\r
+}\r
+\r
 int PicoStateLoadGfx(const char *fname)\r
 {\r
   void *afile;\r
@@ -647,11 +691,13 @@ void *PicoTmpStateSave(void)
   memcpy(t->vsram, Pico.vsram, sizeof(Pico.vsram));\r
   memcpy(&t->video, &Pico.video, sizeof(Pico.video));\r
 \r
+#ifndef NO_32X\r
   if (PicoAHW & PAHW_32X) {\r
     memcpy(&t->t32x.p32x, &Pico32x, sizeof(Pico32x));\r
     memcpy(t->t32x.dram, Pico32xMem->dram, sizeof(Pico32xMem->dram));\r
     memcpy(t->t32x.pal, Pico32xMem->pal, sizeof(Pico32xMem->pal));\r
   }\r
+#endif\r
 \r
   return t;\r
 }\r
@@ -668,12 +714,14 @@ void PicoTmpStateRestore(void *data)
   memcpy(&Pico.video, &t->video, sizeof(Pico.video));\r
   Pico.m.dirtyPal = 1;\r
 \r
+#ifndef NO_32X\r
   if (PicoAHW & PAHW_32X) {\r
     memcpy(&Pico32x, &t->t32x.p32x, sizeof(Pico32x));\r
     memcpy(Pico32xMem->dram, t->t32x.dram, sizeof(Pico32xMem->dram));\r
     memcpy(Pico32xMem->pal, t->t32x.pal, sizeof(Pico32xMem->pal));\r
     Pico32x.dirty_pal = 1;\r
   }\r
+#endif\r
 }\r
 \r
-// vim:shiftwidth=2:expandtab\r
+// vim:shiftwidth=2:ts=2:expandtab\r