32x and sms savestates. Core-independent z80 state. SS bugfixing/refactoring.
authornotaz <notasas@gmail.com>
Wed, 27 Jan 2010 16:30:41 +0000 (16:30 +0000)
committernotaz <notasas@gmail.com>
Wed, 27 Jan 2010 16:30:41 +0000 (16:30 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@868 be3aeb3a-fb24-0410-a615-afba39da0efa

19 files changed:
cpu/DrZ80/drz80.s
cpu/cz80/cz80.c
cpu/sh2/sh2.c
cpu/sh2/sh2.h
pico/32x/memory.c
pico/32x/pwm.c
pico/area.c [deleted file]
pico/cart.c
pico/cd/area.c [deleted file]
pico/memory.c
pico/memory_arm.s
pico/pico.h
pico/pico_int.h
pico/sek.c
pico/sms.c
pico/state.c [new file with mode: 0644]
pico/z80if.c
platform/common/common.mak
platform/common/menu.c

index 499c856..edb29df 100644 (file)
@@ -19,7 +19,6 @@
 \r
 .if DRZ80_XMAP\r
       .equ Z80_MEM_SHIFT, 13\r
-      ;@ note: stack is locked in single bank that z80sp_base points to\r
 .endif\r
 \r
 .if INTERRUPT_MODE\r
@@ -206,12 +205,30 @@ z80_xmap_rebase_pc:
     bxcc lr\r
 \r
 z80_bad_jump:\r
-    ldr r0,[cpucontext,#z80_read8]\r
-    ldr r0,[r0]\r
-    str r0,[cpucontext,#z80pc_base]\r
+    stmfd sp!,{r3,r12,lr}\r
+    mov lr,pc\r
+    ldr pc,[cpucontext,#z80_rebasePC]\r
     mov z80pc,r0\r
-    bx lr\r
-.endif\r
+    ldmfd sp!,{r3,r12,pc}\r
+\r
+z80_xmap_rebase_sp:\r
+    ldr r1,[cpucontext,#z80_read8]\r
+    sub r2,r0,#1\r
+    mov r2,r2,lsl #16\r
+    mov r2,r2,lsr #(Z80_MEM_SHIFT+16)\r
+    ldr r1,[r1,r2,lsl #2]\r
+    movs r1,r1,lsl #1\r
+    strcc r1,[cpucontext,#z80sp_base]\r
+    addcc z80sp,r1,r0\r
+    bxcc lr\r
+\r
+    stmfd sp!,{r3,r12,lr}\r
+    mov lr,pc\r
+    ldr pc,[cpucontext,#z80_rebaseSP]\r
+    mov z80sp,r0\r
+    ldmfd sp!,{r3,r12,pc}\r
\r
+.endif @ DRZ80_XMAP\r
 \r
 \r
 .macro fetch cycs\r
@@ -367,15 +384,13 @@ z80_bad_jump:
      str z80pc,[cpucontext,#z80pc_pointer]\r
 .endif\r
 .if DRZ80_XMAP\r
-    ;@ XXX: SP is locked to single back z80sp_base points to.\r
-    ldr r1,[cpucontext,#z80sp_base]\r
-    bic r0,r0,#0x7f<<Z80_MEM_SHIFT\r
-    add r0,r1,r0\r
+    bl z80_xmap_rebase_sp\r
 .else\r
        stmfd sp!,{r3,r12}\r
        mov lr,pc\r
        ldr pc,[cpucontext,#z80_rebaseSP]               ;@ external function must rebase sp\r
        ldmfd sp!,{r3,r12}\r
+       mov z80sp,r0\r
 .endif\r
 .endm\r
 ;@----------------------------------------------------------------------------\r
@@ -4492,7 +4507,6 @@ opcode_3_1:
 .if FAST_Z80SP\r
        orr r0,r0,r1, lsl #8\r
        rebasesp\r
-       mov z80sp,r0\r
 .else\r
        orr z80sp,r0,r1, lsl #8\r
 .endif\r
@@ -5567,7 +5581,6 @@ opcode_F_9:
 .if FAST_Z80SP\r
        mov r0,z80hl, lsr #16\r
        rebasesp\r
-       mov z80sp,r0\r
 .else\r
        mov z80sp,z80hl, lsr #16\r
 .endif\r
@@ -7433,7 +7446,6 @@ opcode_DD_F9:
 .if FAST_Z80SP\r
        ldrh r0,[z80xx,#2]\r
        rebasesp\r
-       mov z80sp,r0\r
 .else\r
        ldrh z80sp,[z80xx,#2]\r
 .endif\r
@@ -7771,8 +7783,9 @@ opcode_ED_7B:
        readmem16\r
 .if FAST_Z80SP\r
        rebasesp\r
-.endif\r
+.else\r
        mov z80sp,r0\r
+.endif\r
        fetch 20\r
 ;@LDI\r
 opcode_ED_A0:\r
index 1f3cae2..61ca5f8 100644 (file)
@@ -394,8 +394,8 @@ void Cz80_Set_Reg(cz80_struc *CPU, INT32 regnum, UINT32 val)
        case CZ80_R:    zR = val; break;\r
        case CZ80_I:    zI = val; break;\r
        case CZ80_IM:   zIM = val; break;\r
-       case CZ80_IFF1: zIFF1 = val; break;\r
-       case CZ80_IFF2: zIFF2 = val; break;\r
+       case CZ80_IFF1: zIFF1 = val ? (1 << 2) : 0; break;\r
+       case CZ80_IFF2: zIFF2 = val ? (1 << 2) : 0; break;\r
        case CZ80_HALT: CPU->HaltState = val; break;\r
        case CZ80_IRQ:  CPU->IRQState = val; break;\r
        default: break;\r
index 80c458f..0e6be67 100644 (file)
@@ -1,4 +1,6 @@
 #include <string.h>
+#include <stddef.h>
+
 #include "sh2.h"
 #include "../debug.h"
 #include "compiler.h"
@@ -85,3 +87,31 @@ void sh2_internal_irq(SH2 *sh2, int level, int vector)
        sh2->test_irq = 1;
 }
 
+#define SH2_REG_SIZE (offsetof(SH2, macl) + sizeof(sh2->macl))
+
+void sh2_pack(const SH2 *sh2, unsigned char *buff)
+{
+       unsigned int *p;
+
+       memcpy(buff, sh2, SH2_REG_SIZE);
+       p = (void *)(buff + SH2_REG_SIZE);
+
+       p[0] = sh2->pending_int_irq;
+       p[1] = sh2->pending_int_vector;
+       p[2] = sh2->cycles_aim;
+       p[3] = sh2->cycles_done;
+}
+
+void sh2_unpack(SH2 *sh2, const unsigned char *buff)
+{
+       unsigned int *p;
+
+       memcpy(sh2, buff, SH2_REG_SIZE);
+       p = (void *)(buff + SH2_REG_SIZE);
+
+       sh2->pending_int_irq = p[0];
+       sh2->pending_int_vector = p[1];
+       sh2->cycles_aim = p[2];
+       sh2->cycles_done = p[3];
+}
+
index a69a159..e15259d 100644 (file)
@@ -64,9 +64,14 @@ void sh2_reset(SH2 *sh2);
 void sh2_irl_irq(SH2 *sh2, int level, int nested_call);\r
 void sh2_internal_irq(SH2 *sh2, int level, int vector);\r
 void sh2_do_irq(SH2 *sh2, int level, int vector);\r
+void sh2_pack(const SH2 *sh2, unsigned char *buff);\r
+void sh2_unpack(SH2 *sh2, const unsigned char *buff);\r
 \r
 void sh2_execute(SH2 *sh2, int cycles);\r
 \r
+// regs, pending_int*, cycles, reserved\r
+#define SH2_STATE_SIZE ((24 + 2 + 2 + 12) * 4)\r
+\r
 // pico memhandlers\r
 // XXX: move somewhere else\r
 unsigned int REGPARM(2) p32x_sh2_read8(unsigned int a, SH2 *sh2);\r
index ee33caa..c720547 100644 (file)
@@ -352,7 +352,7 @@ static void p32x_vdp_write8(u32 a, u32 d)
       Pico32x.pending_fb = d;
       // if we are blanking and FS bit is changing
       if (((r[0x0a/2] & P32XV_VBLK) || (r[0] & P32XV_Mx) == 0) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
-        r[0x0a/2] ^= 1;
+        r[0x0a/2] ^= P32XV_FS;
        Pico32xSwapDRAM(d ^ 1);
         elprintf(EL_32X, "VDP FS: %d", r[0x0a/2] & P32XV_FS);
       }
@@ -1329,7 +1329,7 @@ static void get_bios(void)
   // M68K ROM
   if (p32x_bios_g != NULL) {
     elprintf(EL_STATUS|EL_32X, "32x: using supplied 68k BIOS");
-    Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, 0x100);
+    Byteswap(Pico32xMem->m68k_rom, p32x_bios_g, sizeof(Pico32xMem->m68k_rom));
   }
   else {
     // generate 68k ROM
@@ -1351,7 +1351,9 @@ static void get_bios(void)
 #endif
   }
   // fill remaining m68k_rom page with game ROM
-  memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
+  memcpy(Pico32xMem->m68k_rom_bank + sizeof(Pico32xMem->m68k_rom),
+    Pico.rom + sizeof(Pico32xMem->m68k_rom),
+    sizeof(Pico32xMem->m68k_rom_bank) - sizeof(Pico32xMem->m68k_rom));
 
   // MSH2
   if (p32x_bios_m != NULL) {
@@ -1439,9 +1441,9 @@ void PicoMemSetup32x(void)
   // m68k_map_unmap(0x000000, 0x3fffff);
 
   // MD ROM area
-  rs = sizeof(Pico32xMem->m68k_rom);
-  cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
-  cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
+  rs = sizeof(Pico32xMem->m68k_rom_bank);
+  cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
+  cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom_bank, 0);
   cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
   cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
 
@@ -1538,4 +1540,16 @@ void PicoMemSetup32x(void)
 #endif
 }
 
+void Pico32xStateLoaded(void)
+{
+  bank_switch(Pico32x.regs[4 / 2]);
+  Pico32xSwapDRAM((Pico32x.vdp_regs[0x0a / 2] & P32XV_FS) ^ P32XV_FS);
+  p32x_poll_event(3, 0);
+  Pico32x.dirty_pal = 1;
+  memset(Pico32xMem->pwm, 0, sizeof(Pico32xMem->pwm));
+#ifdef DRC_SH2
+  sh2_drc_flush_all();
+#endif
+}
+
 // vim:shiftwidth=2:expandtab
index 8e36589..defbf0d 100644 (file)
@@ -145,7 +145,6 @@ void p32x_pwm_write16(unsigned int a, unsigned int d)
 
 void p32x_pwm_update(int *buf32, int length, int stereo)
 {
-  extern int pwm_ptr;
   short *pwmb;
   int step;
   int p = 0;
diff --git a/pico/area.c b/pico/area.c
deleted file mode 100644 (file)
index 23e00da..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-// This is part of Pico Library\r
-\r
-// (c) Copyright 2004 Dave, All rights reserved.\r
-// (c) Copyright 2006 notaz, All rights reserved.\r
-// Free for non-commercial use.\r
-\r
-// For commercial use, separate licencing terms must be obtained.\r
-\r
-\r
-#include "pico_int.h"\r
-#include <zlib/zlib.h>\r
-\r
-// ym2612\r
-#include "sound/ym2612.h"\r
-\r
-// sn76496\r
-extern int *sn76496_regs;\r
-\r
-struct PicoArea { void *data; int len; char *name; };\r
-\r
-// strange observation on Symbian OS 9.1, m600 organizer fw r3a06:\r
-// taking an address of fread or fwrite causes "application could't be started" error\r
-// on startup randomly depending on binary layout of executable file.\r
-\r
-arearw    *areaRead  = (arearw *) 0; // fread;  // read and write function pointers for\r
-arearw    *areaWrite = (arearw *) 0; // fwrite; // gzip save state ability\r
-areaeof   *areaEof   = (areaeof *) 0;\r
-areaseek  *areaSeek  = (areaseek *) 0;\r
-areaclose *areaClose = (areaclose *) 0;\r
-\r
-void (*PicoLoadStateHook)(void) = NULL;\r
-\r
-\r
-// Scan one variable and callback\r
-static int ScanVar(void *data,int len,char *name,void *PmovFile,int is_write)\r
-{\r
-  int ret = 0;\r
-  if (is_write)\r
-    ret = areaWrite(data,1,len,PmovFile);\r
-  else\r
-    ret = areaRead (data,1,len,PmovFile);\r
-  return (ret != len);\r
-}\r
-\r
-#define SCAN_VAR(x,y) ScanVar(&x,sizeof(x),y,PmovFile,is_write);\r
-#define SCANP(x)      ScanVar(&Pico.x,sizeof(Pico.x),#x,PmovFile,is_write);\r
-\r
-// Pack the cpu into a common format:\r
-PICO_INTERNAL void PicoAreaPackCpu(unsigned char *cpu, int is_sub)\r
-{\r
-  unsigned int pc=0;\r
-\r
-#if defined(EMU_C68K)\r
-  struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k;\r
-  memcpy(cpu,context->d,0x40);\r
-  pc=context->pc-context->membase;\r
-  *(unsigned int *)(cpu+0x44)=CycloneGetSr(context);\r
-  *(unsigned int *)(cpu+0x48)=context->osp;\r
-  cpu[0x4c] = context->irq;\r
-  cpu[0x4d] = context->state_flags & 1;\r
-#elif defined(EMU_M68K)\r
-  void *oldcontext = m68ki_cpu_p;\r
-  m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k);\r
-  memcpy(cpu,m68ki_cpu_p->dar,0x40);\r
-  pc=m68ki_cpu_p->pc;\r
-  *(unsigned int  *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR);\r
-  *(unsigned int  *)(cpu+0x48)=m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET];\r
-  cpu[0x4c] = CPU_INT_LEVEL>>8;\r
-  cpu[0x4d] = CPU_STOPPED;\r
-  m68k_set_context(oldcontext);\r
-#elif defined(EMU_F68K)\r
-  M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k;\r
-  memcpy(cpu,context->dreg,0x40);\r
-  pc=context->pc;\r
-  *(unsigned int  *)(cpu+0x44)=context->sr;\r
-  *(unsigned int  *)(cpu+0x48)=context->asp;\r
-  cpu[0x4c] = context->interrupts[0];\r
-  cpu[0x4d] = (context->execinfo & FM68K_HALTED) ? 1 : 0;\r
-#endif\r
-\r
-  *(unsigned int *)(cpu+0x40)=pc;\r
-}\r
-\r
-PICO_INTERNAL void PicoAreaUnpackCpu(unsigned char *cpu, int is_sub)\r
-{\r
-#if defined(EMU_C68K)\r
-  struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k;\r
-  CycloneSetSr(context, *(unsigned int *)(cpu+0x44));\r
-  context->osp=*(unsigned int *)(cpu+0x48);\r
-  memcpy(context->d,cpu,0x40);\r
-  context->membase = 0;\r
-  context->pc = *(unsigned int *)(cpu+0x40);\r
-  CycloneUnpack(context, NULL); // rebase PC\r
-  context->irq = cpu[0x4c];\r
-  context->state_flags = 0;\r
-  if (cpu[0x4d])\r
-    context->state_flags |= 1;\r
-#elif defined(EMU_M68K)\r
-  void *oldcontext = m68ki_cpu_p;\r
-  m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k);\r
-  m68k_set_reg(M68K_REG_SR, *(unsigned int *)(cpu+0x44));\r
-  memcpy(m68ki_cpu_p->dar,cpu,0x40);\r
-  m68ki_cpu_p->pc=*(unsigned int *)(cpu+0x40);\r
-  m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]=*(unsigned int *)(cpu+0x48);\r
-  CPU_INT_LEVEL = cpu[0x4c] << 8;\r
-  CPU_STOPPED = cpu[0x4d];\r
-  m68k_set_context(oldcontext);\r
-#elif defined(EMU_F68K)\r
-  M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k;\r
-  memcpy(context->dreg,cpu,0x40);\r
-  context->pc =*(unsigned int *)(cpu+0x40);\r
-  context->sr =*(unsigned int *)(cpu+0x44);\r
-  context->asp=*(unsigned int *)(cpu+0x48);\r
-  context->interrupts[0] = cpu[0x4c];\r
-  context->execinfo &= ~FM68K_HALTED;\r
-  if (cpu[0x4d]&1) context->execinfo |= FM68K_HALTED;\r
-#endif\r
-}\r
-\r
-// Scan the contents of the virtual machine's memory for saving or loading\r
-static int PicoAreaScan(int is_write, unsigned int ver, void *PmovFile)\r
-{\r
-  void *ym2612_regs;\r
-  unsigned char cpu[0x60];\r
-  unsigned char cpu_z80[0x60];\r
-  int ret;\r
-\r
-  memset(&cpu,0,sizeof(cpu));\r
-  memset(&cpu_z80,0,sizeof(cpu_z80));\r
-  Pico.m.scanline=0;\r
-\r
-  ym2612_regs = YM2612GetRegs();\r
-\r
-  // Scan all the memory areas:\r
-  SCANP(ram) SCANP(vram) SCANP(zram) SCANP(cram) SCANP(vsram)\r
-\r
-  // Pack, scan and unpack the cpu data:\r
-  if (is_write)\r
-    PicoAreaPackCpu(cpu, 0);\r
-  SCAN_VAR(cpu,"cpu")\r
-  if (!is_write)\r
-    PicoAreaUnpackCpu(cpu, 0);\r
-\r
-  SCAN_VAR(Pico.m    ,"misc")\r
-  SCAN_VAR(Pico.video,"video")\r
-\r
-  // no longer keeping eeprom data in sram_reg\r
-  if (!is_write && (Pico.m.sram_reg & 4))\r
-    Pico.m.sram_reg = SRR_MAPPED;\r
-\r
-  if (is_write)\r
-    z80_pack(cpu_z80);\r
-  ret = SCAN_VAR(cpu_z80,"cpu_z80")\r
-  // do not unpack if we fail to load z80 state\r
-  if (!is_write) {\r
-    if (ret) z80_reset();\r
-    else     z80_unpack(cpu_z80);\r
-  }\r
-\r
-  ScanVar(sn76496_regs, 28*4, "SN76496state", PmovFile, is_write);\r
-  if (is_write)\r
-    ym2612_pack_state();\r
-  ret = ScanVar(ym2612_regs, 0x200+4, "YM2612state", PmovFile, is_write); // regs + addr line\r
-  if (!is_write && !ret)\r
-    ym2612_unpack_state();\r
-\r
-  return 0;\r
-}\r
-\r
-// ---------------------------------------------------------------------------\r
-// Helper code to save/load to a file handle\r
-\r
-// XXX: error checking\r
-// Save or load the state from PmovFile:\r
-static int PmovState(int is_write, void *PmovFile)\r
-{\r
-  unsigned char head[32];\r
-\r
-  if ((PicoAHW & PAHW_MCD) || carthw_chunks != NULL)\r
-  {\r
-    if (is_write)\r
-      return PicoCdSaveState(PmovFile);\r
-    else {\r
-      int ret = PicoCdLoadState(PmovFile);\r
-      if (PicoLoadStateHook) PicoLoadStateHook();\r
-      return ret;\r
-    }\r
-  }\r
-\r
-  memset(head,0,sizeof(head));\r
-\r
-  // not really used..\r
-  memcpy(head,"Pico",4);\r
-  *(unsigned int *)(head+0x8)=0x0133;\r
-  *(unsigned int *)(head+0xc)=0x0021;\r
-\r
-  // Scan header:\r
-  if (is_write)\r
-    areaWrite(head,1,sizeof(head),PmovFile);\r
-  else\r
-    areaRead (head,1,sizeof(head),PmovFile);\r
-\r
-  // Scan memory areas:\r
-  PicoAreaScan(is_write, *(unsigned int *)(head+0x8), PmovFile);\r
-\r
-  if (!is_write && PicoLoadStateHook)\r
-    PicoLoadStateHook();\r
-\r
-  return 0;\r
-}\r
-\r
-static size_t gzRead2(void *p, size_t _size, size_t _n, void *file)\r
-{\r
-  return gzread(file, p, _n);\r
-}\r
-\r
-static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file)\r
-{\r
-  return gzwrite(file, p, _n);\r
-}\r
-\r
-static void set_cbs(int gz)\r
-{\r
-  if (gz) {\r
-    areaRead  = gzRead2;\r
-    areaWrite = gzWrite2;\r
-    areaEof   = (areaeof *) gzeof;\r
-    areaSeek  = (areaseek *) gzseek;\r
-    areaClose = (areaclose *) gzclose;\r
-  } else {\r
-    areaRead  = (arearw *) fread;\r
-    areaWrite = (arearw *) fwrite;\r
-    areaEof   = (areaeof *) feof;\r
-    areaSeek  = (areaseek *) fseek;\r
-    areaClose = (areaclose *) fclose;\r
-  }\r
-}\r
-\r
-int PicoState(const char *fname, int is_save)\r
-{\r
-  void *afile = NULL;\r
-  int ret;\r
-\r
-  if (strcmp(fname + strlen(fname) - 3, ".gz") == 0)\r
-  {\r
-    if ( (afile = gzopen(fname, is_save ? "wb" : "rb")) ) {\r
-      set_cbs(1);\r
-      if (is_save)\r
-        gzsetparams(afile, 9, Z_DEFAULT_STRATEGY);\r
-    }\r
-  }\r
-  else\r
-  {\r
-    if ( (afile = fopen(fname, is_save ? "wb" : "rb")) ) {\r
-      set_cbs(0);\r
-    }\r
-  }\r
-\r
-  if (afile == NULL)\r
-    return -1;\r
-\r
-  ret = PmovState(is_save, afile);\r
-  areaClose(afile);\r
-  if (!is_save)\r
-    Pico.m.dirtyPal=1;\r
-\r
-  return ret;\r
-}\r
-\r
-int PicoStateLoadVDP(const char *fname)\r
-{\r
-  void *afile = NULL;\r
-  if (strcmp(fname + strlen(fname) - 3, ".gz") == 0)\r
-  {\r
-    if ( (afile = gzopen(fname, "rb")) )\r
-      set_cbs(1);\r
-  }\r
-  else\r
-  {\r
-    if ( (afile = fopen(fname, "rb")) )\r
-      set_cbs(0);\r
-  }\r
-  if (afile == NULL)\r
-    return -1;\r
-\r
-  if ((PicoAHW & PAHW_MCD) || carthw_chunks != NULL) {\r
-    PicoCdLoadStateGfx(afile);\r
-  } else {\r
-    areaSeek(afile, 0x10020, SEEK_SET);  // skip header and RAM in state file\r
-    areaRead(Pico.vram, 1, sizeof(Pico.vram), afile);\r
-    areaSeek(afile, 0x2000, SEEK_CUR);\r
-    areaRead(Pico.cram, 1, sizeof(Pico.cram), afile);\r
-    areaRead(Pico.vsram, 1, sizeof(Pico.vsram), afile);\r
-    areaSeek(afile, 0x221a0, SEEK_SET);\r
-    areaRead(&Pico.video, 1, sizeof(Pico.video), afile);\r
-  }\r
-  areaClose(afile);\r
-  return 0;\r
-}\r
-\r
index fa283c8..8ac330a 100644 (file)
@@ -439,6 +439,9 @@ static unsigned char *PicoCartAlloc(int filesize, int is_sms)
     if (filesize > (1 << s))\r
       s++;\r
     rom_alloc_size = 1 << s;\r
+    // be sure we can cover all address space\r
+    if (rom_alloc_size < 0x10000)\r
+      rom_alloc_size = 0x10000;\r
   }\r
   else {\r
     // make alloc size at least sizeof(mcd_state),\r
diff --git a/pico/cd/area.c b/pico/cd/area.c
deleted file mode 100644 (file)
index 645993b..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-// Savestate handling for emulated Sega/Mega CD machine.
-// (c) Copyright 2007, Grazvydas "notaz" Ignotas
-
-
-#include "../pico_int.h"
-
-// ym2612
-#include "../sound/ym2612.h"
-
-// sn76496
-extern int *sn76496_regs;
-
-carthw_state_chunk *carthw_chunks;
-void (*PicoStateProgressCB)(const char *str) = 0;
-
-
-typedef enum {
-       CHUNK_M68K = 1,
-       CHUNK_RAM,
-       CHUNK_VRAM,
-       CHUNK_ZRAM,
-       CHUNK_CRAM,     // 5
-       CHUNK_VSRAM,
-       CHUNK_MISC,
-       CHUNK_VIDEO,
-       CHUNK_Z80,
-       CHUNK_PSG,      // 10
-       CHUNK_FM,
-       // CD stuff
-       CHUNK_S68K,
-       CHUNK_PRG_RAM,
-       CHUNK_WORD_RAM,
-       CHUNK_PCM_RAM,  // 15
-       CHUNK_BRAM,
-       CHUNK_GA_REGS,
-       CHUNK_PCM,
-       CHUNK_CDC,
-       CHUNK_CDD,      // 20
-       CHUNK_SCD,
-       CHUNK_RC,
-       CHUNK_MISC_CD,
-       CHUNK_DEFAULT_COUNT
-       // CHUNK_CARTHW = 64,   // defined in PicoInt
-} chunk_name_e;
-
-
-static char *chunk_names[] = {
-       "INVALID!",
-       "Saving.. M68K state",
-       "Saving.. RAM",
-       "Saving.. VRAM",
-       "Saving.. ZRAM",
-       "Saving.. CRAM",        // 5
-       "Saving.. VSRAM",
-       "Saving.. emu state",
-       "Saving.. VIDEO",
-       "Saving.. Z80 state",
-       "Saving.. PSG",         // 10
-       "Saving.. FM",
-       // CD stuff
-       "Saving.. S68K state",
-       "Saving.. PRG_RAM",
-       "Saving.. WORD_RAM",
-       "Saving.. PCM_RAM",     // 15
-       "Saving.. BRAM",
-       "Saving.. GATE ARRAY regs",
-       "Saving.. PCM state",
-       "Saving.. CDC",
-       "Saving.. CDD",         // 20
-       "Saving.. SCD",
-       "Saving.. GFX chip",
-       "Saving.. MCD state",
-};
-
-
-static int write_chunk(chunk_name_e name, int len, void *data, void *file)
-{
-       size_t bwritten = 0;
-       bwritten += areaWrite(&name, 1, 1, file);
-       bwritten += areaWrite(&len, 1, 4, file);
-       bwritten += areaWrite(data, 1, len, file);
-
-       return (bwritten == len + 4 + 1);
-}
-
-
-#define CHECKED_WRITE(name,len,data) { \
-       if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT) \
-               PicoStateProgressCB(chunk_names[name]); \
-       if (!write_chunk(name, len, data, file)) return 1; \
-}
-
-#define CHECKED_WRITE_BUFF(name,buff) { \
-       if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT) \
-               PicoStateProgressCB(chunk_names[name]); \
-       if (!write_chunk(name, sizeof(buff), &buff, file)) return 1; \
-}
-
-PICO_INTERNAL int PicoCdSaveState(void *file)
-{
-       unsigned char buff[0x60];
-       void *ym2612_regs = YM2612GetRegs();
-       int ver = 0x0133; // not really used..
-
-       areaWrite("PicoSEXT", 1, 8, file);
-       areaWrite(&ver, 1, 4, file);
-
-       memset(buff, 0, sizeof(buff));
-       PicoAreaPackCpu(buff, 0);
-       CHECKED_WRITE_BUFF(CHUNK_M68K,  buff);
-       CHECKED_WRITE_BUFF(CHUNK_RAM,   Pico.ram);
-       CHECKED_WRITE_BUFF(CHUNK_VRAM,  Pico.vram);
-       CHECKED_WRITE_BUFF(CHUNK_ZRAM,  Pico.zram);
-       CHECKED_WRITE_BUFF(CHUNK_CRAM,  Pico.cram);
-       CHECKED_WRITE_BUFF(CHUNK_VSRAM, Pico.vsram);
-       CHECKED_WRITE_BUFF(CHUNK_MISC,  Pico.m);
-       CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);
-
-       memset(buff, 0, sizeof(buff));
-       z80_pack(buff);
-       CHECKED_WRITE_BUFF(CHUNK_Z80, buff);
-       CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs);
-       ym2612_pack_state();
-       CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs);
-
-       if (PicoAHW & PAHW_MCD)
-       {
-               memset(buff, 0, sizeof(buff));
-               PicoAreaPackCpu(buff, 1);
-               if (Pico_mcd->s68k_regs[3]&4) // 1M mode?
-                       wram_1M_to_2M(Pico_mcd->word_ram2M);
-               Pico_mcd->m.hint_vector = *(unsigned short *)(Pico_mcd->bios + 0x72);
-
-               CHECKED_WRITE_BUFF(CHUNK_S68K,     buff);
-               CHECKED_WRITE_BUFF(CHUNK_PRG_RAM,  Pico_mcd->prg_ram);
-               CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram2M); // in 2M format
-               CHECKED_WRITE_BUFF(CHUNK_PCM_RAM,  Pico_mcd->pcm_ram);
-               CHECKED_WRITE_BUFF(CHUNK_BRAM,     Pico_mcd->bram);
-               CHECKED_WRITE_BUFF(CHUNK_GA_REGS,  Pico_mcd->s68k_regs); // GA regs, not CPU regs
-               CHECKED_WRITE_BUFF(CHUNK_PCM,      Pico_mcd->pcm);
-               CHECKED_WRITE_BUFF(CHUNK_CDD,      Pico_mcd->cdd);
-               CHECKED_WRITE_BUFF(CHUNK_CDC,      Pico_mcd->cdc);
-               CHECKED_WRITE_BUFF(CHUNK_SCD,      Pico_mcd->scd);
-               CHECKED_WRITE_BUFF(CHUNK_RC,       Pico_mcd->rot_comp);
-               CHECKED_WRITE_BUFF(CHUNK_MISC_CD,  Pico_mcd->m);
-
-               if (Pico_mcd->s68k_regs[3]&4) // convert back
-                       wram_2M_to_1M(Pico_mcd->word_ram2M);
-       }
-
-       if (carthw_chunks != NULL)
-       {
-               carthw_state_chunk *chwc;
-               if (PicoStateProgressCB)
-                       PicoStateProgressCB("Saving.. cart hw state");
-               for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++)
-                       CHECKED_WRITE(chwc->chunk, chwc->size, chwc->ptr);
-       }
-
-       return 0;
-}
-
-static int g_read_offs = 0;
-
-#define R_ERROR_RETURN(error) \
-{ \
-       elprintf(EL_STATUS, "PicoCdLoadState @ %x: " error, g_read_offs); \
-       return 1; \
-}
-
-// when is eof really set?
-#define CHECKED_READ(len,data) \
-       if (areaRead(data, 1, len, file) != len) { \
-               if (len == 1 && areaEof(file)) goto readend; \
-               R_ERROR_RETURN("areaRead: premature EOF\n"); \
-               return 1; \
-       } \
-       g_read_offs += len;
-
-#define CHECKED_READ2(len2,data) \
-       if (len2 != len) { \
-               elprintf(EL_STATUS, "unexpected len %i, wanted %i (%s)", len, len2, #len2); \
-               if (len > len2) R_ERROR_RETURN("failed."); \
-               /* else read anyway and hope for the best.. */ \
-       } \
-       CHECKED_READ(len, data)
-
-#define CHECKED_READ_BUFF(buff) CHECKED_READ2(sizeof(buff), &buff);
-
-PICO_INTERNAL int PicoCdLoadState(void *file)
-{
-       unsigned char buff[0x60], buff_m68k[0x60], buff_s68k[0x60];
-       int ver, len;
-       void *ym2612_regs = YM2612GetRegs();
-
-       g_read_offs = 0;
-       CHECKED_READ(8, buff);
-       if (strncmp((char *)buff, "PicoSMCD", 8) && strncmp((char *)buff, "PicoSEXT", 8))
-               R_ERROR_RETURN("bad header");
-       CHECKED_READ(4, &ver);
-
-       while (!areaEof(file))
-       {
-               CHECKED_READ(1, buff);
-               CHECKED_READ(4, &len);
-               if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
-               if (buff[0] > CHUNK_FM && buff[0] <= CHUNK_MISC_CD && !(PicoAHW & PAHW_MCD))
-                       R_ERROR_RETURN("cd chunk in non CD state?");
-
-               switch (buff[0])
-               {
-                       case CHUNK_M68K:
-                               CHECKED_READ_BUFF(buff_m68k);
-                               break;
-
-                       case CHUNK_Z80:
-                               CHECKED_READ_BUFF(buff);
-                               z80_unpack(buff);
-                               break;
-
-                       case CHUNK_RAM:   CHECKED_READ_BUFF(Pico.ram); break;
-                       case CHUNK_VRAM:  CHECKED_READ_BUFF(Pico.vram); break;
-                       case CHUNK_ZRAM:  CHECKED_READ_BUFF(Pico.zram); break;
-                       case CHUNK_CRAM:  CHECKED_READ_BUFF(Pico.cram); break;
-                       case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); break;
-                       case CHUNK_MISC:  CHECKED_READ_BUFF(Pico.m); break;
-                       case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); break;
-                       case CHUNK_PSG:   CHECKED_READ2(28*4, sn76496_regs); break;
-                       case CHUNK_FM:
-                               CHECKED_READ2(0x200+4, ym2612_regs);
-                               ym2612_unpack_state();
-                               break;
-
-                       // cd stuff
-                       case CHUNK_S68K:
-                               CHECKED_READ_BUFF(buff_s68k);
-                               break;
-
-                       case CHUNK_PRG_RAM:     CHECKED_READ_BUFF(Pico_mcd->prg_ram); break;
-                       case CHUNK_WORD_RAM:    CHECKED_READ_BUFF(Pico_mcd->word_ram2M); break;
-                       case CHUNK_PCM_RAM:     CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break;
-                       case CHUNK_BRAM:        CHECKED_READ_BUFF(Pico_mcd->bram); break;
-                       case CHUNK_GA_REGS:     CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;
-                       case CHUNK_PCM:         CHECKED_READ_BUFF(Pico_mcd->pcm); break;
-                       case CHUNK_CDD:         CHECKED_READ_BUFF(Pico_mcd->cdd); break;
-                       case CHUNK_CDC:         CHECKED_READ_BUFF(Pico_mcd->cdc); break;
-                       case CHUNK_SCD:         CHECKED_READ_BUFF(Pico_mcd->scd); break;
-                       case CHUNK_RC:          CHECKED_READ_BUFF(Pico_mcd->rot_comp); break;
-                       case CHUNK_MISC_CD:     CHECKED_READ_BUFF(Pico_mcd->m); break;
-
-                       default:
-                               if (carthw_chunks != NULL)
-                               {
-                                       carthw_state_chunk *chwc;
-                                       for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++) {
-                                               if (chwc->chunk == buff[0]) {
-                                                       CHECKED_READ2(chwc->size, chwc->ptr);
-                                                       goto breakswitch;
-                                               }
-                                       }
-                               }
-                               elprintf(EL_STATUS, "PicoCdLoadState: skipping unknown chunk %i of size %i", buff[0], len);
-                               areaSeek(file, len, SEEK_CUR);
-                               break;
-               }
-               breakswitch:;
-       }
-
-readend:
-       if (PicoAHW & PAHW_MCD)
-       {
-               PicoMemStateLoaded();
-
-               if (!(Pico_mcd->s68k_regs[0x36] & 1) && (Pico_mcd->scd.Status_CDC & 1))
-                       cdda_start_play();
-
-               // must unpack after other CD stuff is loaded
-               PicoAreaUnpackCpu(buff_s68k, 1);
-       }
-       PicoAreaUnpackCpu(buff_m68k, 0);
-
-       return 0;
-}
-
-
-int PicoCdLoadStateGfx(void *file)
-{
-       int ver, len, found = 0;
-       char buff[8];
-
-       g_read_offs = 0;
-       CHECKED_READ(8, buff);
-       if (strncmp((char *)buff, "PicoSMCD", 8) && strncmp((char *)buff, "PicoSEXT", 8))
-               R_ERROR_RETURN("bad header");
-       CHECKED_READ(4, &ver);
-
-       while (!areaEof(file) && found < 4)
-       {
-               CHECKED_READ(1, buff);
-               CHECKED_READ(4, &len);
-               if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");
-               if (buff[0] > CHUNK_FM && buff[0] <= CHUNK_MISC_CD && !(PicoAHW & PAHW_MCD))
-                       R_ERROR_RETURN("cd chunk in non CD state?");
-
-               switch (buff[0])
-               {
-                       case CHUNK_VRAM:  CHECKED_READ_BUFF(Pico.vram);  found++; break;
-                       case CHUNK_CRAM:  CHECKED_READ_BUFF(Pico.cram);  found++; break;
-                       case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); found++; break;
-                       case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break;
-                       default:
-                               areaSeek(file, len, SEEK_CUR);
-                               break;
-               }
-       }
-
-readend:
-       return 0;
-}
-
-
index d0b1697..00e5016 100644 (file)
@@ -322,7 +322,7 @@ static u32 PicoRead8_sram(u32 a)
 static u32 PicoRead16_sram(u32 a)\r
 {\r
   u32 d;\r
-  if (SRam.end >= a && a >= SRam.start && (Pico.m.sram_reg & SRR_MAPPED))\r
+  if (SRam.start <= a && a <= SRam.end && (Pico.m.sram_reg & SRR_MAPPED))\r
   {\r
     if (SRam.flags & SRF_EEPROM)\r
       d = EEPROM_read();\r
index dde8342..972b918 100644 (file)
@@ -27,7 +27,7 @@ PicoRead8_sram: @ u32 a, u32 d
     ldr     r3, =(Pico+0x22200)\r
     ldr     r1, [r2, #8]    @ SRam.end\r
     cmp     r0, r1\r
-    bge     m_read8_nosram\r
+    bgt     m_read8_nosram\r
     ldr     r1, [r2, #4]    @ SRam.start\r
     cmp     r0, r1\r
     blt     m_read8_nosram\r
@@ -58,8 +58,8 @@ m_read8_nosram:
 m_read8_eeprom:\r
     stmfd   sp!,{r0,lr}\r
     bl      EEPROM_read\r
-    ldmfd   sp!,{r0,lr}\r
-    tst     r0, #1\r
+    ldmfd   sp!,{r1,lr}\r
+    tst     r1, #1\r
     moveq   r0, r0, lsr #8\r
     bx      lr\r
 \r
@@ -126,7 +126,7 @@ PicoRead16_sram: @ u32 a, u32 d
     ldr     r3, =(Pico+0x22200)\r
     ldr     r1, [r2, #8]    @ SRam.end\r
     cmp     r0, r1\r
-    bge     m_read16_nosram\r
+    bgt     m_read16_nosram\r
     ldr     r1, [r2, #4]    @ SRam.start\r
     cmp     r0, r1\r
     blt     m_read16_nosram\r
index c614aa9..870444a 100644 (file)
@@ -34,6 +34,7 @@ extern void cache_flush_d_inval_i(const void *start_addr, const void *end_addr);
 // attempt to alloc mem at specified address.\r
 // alloc anywhere else if that fails (callers should handle that)\r
 extern void *plat_mmap(unsigned long addr, size_t size);\r
+extern void *plat_mremap(void *ptr, size_t oldsize, size_t newsize);\r
 extern void  plat_munmap(void *ptr, size_t size);\r
 \r
 // this one should handle display mode changes\r
@@ -119,12 +120,11 @@ extern picohw_state PicoPicohw;
 \r
 // area.c\r
 int PicoState(const char *fname, int is_save);\r
-int PicoStateLoadVDP(const char *fname);\r
+int PicoStateLoadGfx(const char *fname);\r
+void *PicoTmpStateSave(void);\r
+void  PicoTmpStateRestore(void *data);\r
 extern void (*PicoStateProgressCB)(const char *str);\r
 \r
-// cd/area.c\r
-int  PicoCdLoadStateGfx(void *file);\r
-\r
 // cd/buffering.c\r
 void PicoCDBufferInit(void);\r
 void PicoCDBufferFree(void);\r
index 3ee4ea1..74d1da2 100644 (file)
@@ -178,14 +178,7 @@ extern int dbg_irq_level;
 \r
 // ----------------------- Z80 CPU -----------------------\r
 \r
-#if defined(_USE_MZ80)\r
-#include "../cpu/mz80/mz80.h"\r
-\r
-#define z80_run(cycles)    { mz80GetElapsedTicks(1); mz80_run(cycles) }\r
-#define z80_run_nr(cycles) mz80_run(cycles)\r
-#define z80_int()          mz80int(0)\r
-\r
-#elif defined(_USE_DRZ80)\r
+#if defined(_USE_DRZ80)\r
 #include "../cpu/DrZ80/drz80.h"\r
 \r
 extern struct DrZ80 drZ80;\r
@@ -215,6 +208,8 @@ extern struct DrZ80 drZ80;
 \r
 #endif\r
 \r
+#define Z80_STATE_SIZE 0x60\r
+\r
 extern int z80stopCycle;         /* in 68k cycles */\r
 extern int z80_cycle_cnt;        /* 'done' z80 cycles before z80_run() */\r
 extern int z80_cycle_aim;\r
@@ -305,6 +300,13 @@ struct PicoMisc
   unsigned int  frame_count;   // 1c for movies and idle det\r
 };\r
 \r
+struct PicoMS\r
+{\r
+  unsigned char carthw[0x10];\r
+  unsigned char io_ctl;\r
+  unsigned char pad[0x4f];\r
+};\r
+\r
 // some assembly stuff depend on these, do not touch!\r
 struct Pico\r
 {\r
@@ -314,9 +316,8 @@ struct Pico
     unsigned char  vramb[0x4000]; // VRAM in SMS mode\r
   };\r
   unsigned char zram[0x2000];  // 0x20000 Z80 ram\r
-  unsigned char ioports[0x10];\r
-  unsigned char sms_io_ctl;\r
-  unsigned char pad[0xef];     // unused\r
+  unsigned char ioports[0x10]; // XXX: fix asm and mv\r
+  unsigned char pad[0xf0];     // unused\r
   unsigned short cram[0x40];   // 0x22100\r
   unsigned short vsram[0x40];  // 0x22180\r
 \r
@@ -325,6 +326,7 @@ struct Pico
 \r
   struct PicoMisc m;\r
   struct PicoVideo video;\r
+  struct PicoMS ms;\r
 };\r
 \r
 // sram\r
@@ -487,6 +489,7 @@ struct Pico32x
   unsigned short dmac_fifo[DMAC_FIFO_LEN];\r
   unsigned int dmac_ptr;\r
   unsigned int pwm_irq_sample_cnt;\r
+  unsigned int reserved[9];\r
 };\r
 \r
 struct Pico32xMem\r
@@ -496,7 +499,10 @@ struct Pico32xMem
   unsigned short drcblk_ram[1 << (18 - SH2_DRCBLK_RAM_SHIFT)];\r
 #endif\r
   unsigned short dram[2][0x20000/2];    // AKA fb\r
-  unsigned char  m68k_rom[0x10000];     // 0x100; using M68K_BANK_SIZE\r
+  union {\r
+    unsigned char  m68k_rom[0x100];\r
+    unsigned char  m68k_rom_bank[0x10000]; // M68K_BANK_SIZE\r
+  };\r
   unsigned char  data_array[2][0x1000]; // cache in SH2s (can be used as RAM)\r
 #ifdef DRC_SH2\r
   unsigned short drcblk_da[2][1 << (12 - SH2_DRCBLK_DA_SHIFT)];\r
@@ -510,14 +516,8 @@ struct Pico32xMem
 };\r
 \r
 // area.c\r
-PICO_INTERNAL void PicoAreaPackCpu(unsigned char *cpu, int is_sub);\r
-PICO_INTERNAL void PicoAreaUnpackCpu(unsigned char *cpu, int is_sub);\r
 extern void (*PicoLoadStateHook)(void);\r
 \r
-// cd/area.c\r
-PICO_INTERNAL int PicoCdSaveState(void *file);\r
-PICO_INTERNAL int PicoCdLoadState(void *file);\r
-\r
 typedef struct {\r
        int chunk;\r
        int size;\r
@@ -526,19 +526,9 @@ typedef struct {
 extern carthw_state_chunk *carthw_chunks;\r
 #define CHUNK_CARTHW 64\r
 \r
-// area.c\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
-extern arearw  *areaRead;  // external read and write function pointers for\r
-extern arearw  *areaWrite; // gzip save state ability\r
-extern areaeof *areaEof;\r
-extern areaseek *areaSeek;\r
-extern areaclose *areaClose;\r
-\r
 // cart.c\r
-void Byteswap(void *dst, const void *src, int len);\r
+extern int PicoCartResize(int newsize);\r
+extern void Byteswap(void *dst, const void *src, int len);\r
 extern void (*PicoCartMemSetup)(void);\r
 extern void (*PicoCartUnloadHook)(void);\r
 \r
@@ -612,6 +602,8 @@ PICO_INTERNAL void SekInit(void);
 PICO_INTERNAL int  SekReset(void);\r
 PICO_INTERNAL void SekState(int *data);\r
 PICO_INTERNAL void SekSetRealTAS(int use_real);\r
+PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub);\r
+PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub);\r
 void SekStepM68k(void);\r
 void SekInitIdleDet(void);\r
 void SekFinishIdleDet(void);\r
@@ -671,8 +663,8 @@ unsigned int EEPROM_read(void);
 \r
 // z80 functionality wrappers\r
 PICO_INTERNAL void z80_init(void);\r
-PICO_INTERNAL void z80_pack(unsigned char *data);\r
-PICO_INTERNAL void z80_unpack(unsigned char *data);\r
+PICO_INTERNAL void z80_pack(void *data);\r
+PICO_INTERNAL int  z80_unpack(const void *data);\r
 PICO_INTERNAL void z80_reset(void);\r
 PICO_INTERNAL void z80_exit(void);\r
 \r
@@ -695,6 +687,7 @@ extern int PsndDacLine;
 void PicoPowerMS(void);\r
 void PicoResetMS(void);\r
 void PicoMemSetupMS(void);\r
+void PicoStateLoadedMS(void);\r
 void PicoFrameMS(void);\r
 void PicoFrameDrawOnlyMS(void);\r
 \r
@@ -717,6 +710,7 @@ void PicoWrite8_32x(unsigned int a, unsigned int d);
 void PicoWrite16_32x(unsigned int a, unsigned int d);\r
 void PicoMemSetup32x(void);\r
 void Pico32xSwapDRAM(int b);\r
+void Pico32xStateLoaded(void);\r
 void p32x_poll_event(int cpu_mask, int is_vdp);\r
 \r
 // 32x/draw.c\r
index fe381f2..bc44c47 100644 (file)
@@ -50,12 +50,13 @@ static void SekResetAck(void)
 \r
 static int SekUnrecognizedOpcode()\r
 {\r
-  unsigned int pc, op;\r
+  unsigned int pc;\r
   pc = SekPc;\r
-  op = PicoCpuCM68k.read16(pc);\r
-  elprintf(EL_ANOMALY, "Unrecognized Opcode %04x @ %06x", op, pc);\r
-  // see if we are not executing trash\r
-  if (pc < 0x200 || (pc > Pico.romsize+4 && (pc&0xe00000)!=0xe00000)) {\r
+  elprintf(EL_ANOMALY, "Unrecognized Opcode @ %06x", pc);\r
+  // see if we are still in a mapped region\r
+  pc &= 0x00ffffff;\r
+  if (map_flag_set(m68k_read16_map[pc >> M68K_MEM_SHIFT])) {\r
+    elprintf(EL_STATUS|EL_ANOMALY, "m68k crash @%06x", pc);\r
     PicoCpuCM68k.cycles = 0;\r
     PicoCpuCM68k.state_flags |= 1;\r
     return 1;\r
@@ -184,6 +185,79 @@ PICO_INTERNAL void SekSetRealTAS(int use_real)
 #endif\r
 }\r
 \r
+// Pack the cpu into a common format:\r
+// XXX: rename\r
+PICO_INTERNAL void SekPackCpu(unsigned char *cpu, int is_sub)\r
+{\r
+  unsigned int pc=0;\r
+\r
+#if defined(EMU_C68K)\r
+  struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k;\r
+  memcpy(cpu,context->d,0x40);\r
+  pc=context->pc-context->membase;\r
+  *(unsigned int *)(cpu+0x44)=CycloneGetSr(context);\r
+  *(unsigned int *)(cpu+0x48)=context->osp;\r
+  cpu[0x4c] = context->irq;\r
+  cpu[0x4d] = context->state_flags & 1;\r
+#elif defined(EMU_M68K)\r
+  void *oldcontext = m68ki_cpu_p;\r
+  m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k);\r
+  memcpy(cpu,m68ki_cpu_p->dar,0x40);\r
+  pc=m68ki_cpu_p->pc;\r
+  *(unsigned int  *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR);\r
+  *(unsigned int  *)(cpu+0x48)=m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET];\r
+  cpu[0x4c] = CPU_INT_LEVEL>>8;\r
+  cpu[0x4d] = CPU_STOPPED;\r
+  m68k_set_context(oldcontext);\r
+#elif defined(EMU_F68K)\r
+  M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k;\r
+  memcpy(cpu,context->dreg,0x40);\r
+  pc=context->pc;\r
+  *(unsigned int  *)(cpu+0x44)=context->sr;\r
+  *(unsigned int  *)(cpu+0x48)=context->asp;\r
+  cpu[0x4c] = context->interrupts[0];\r
+  cpu[0x4d] = (context->execinfo & FM68K_HALTED) ? 1 : 0;\r
+#endif\r
+\r
+  *(unsigned int *)(cpu+0x40)=pc;\r
+}\r
+\r
+PICO_INTERNAL void SekUnpackCpu(const unsigned char *cpu, int is_sub)\r
+{\r
+#if defined(EMU_C68K)\r
+  struct Cyclone *context = is_sub ? &PicoCpuCS68k : &PicoCpuCM68k;\r
+  CycloneSetSr(context, *(unsigned int *)(cpu+0x44));\r
+  context->osp=*(unsigned int *)(cpu+0x48);\r
+  memcpy(context->d,cpu,0x40);\r
+  context->membase = 0;\r
+  context->pc = *(unsigned int *)(cpu+0x40);\r
+  CycloneUnpack(context, NULL); // rebase PC\r
+  context->irq = cpu[0x4c];\r
+  context->state_flags = 0;\r
+  if (cpu[0x4d])\r
+    context->state_flags |= 1;\r
+#elif defined(EMU_M68K)\r
+  void *oldcontext = m68ki_cpu_p;\r
+  m68k_set_context(is_sub ? &PicoCpuMS68k : &PicoCpuMM68k);\r
+  m68k_set_reg(M68K_REG_SR, *(unsigned int *)(cpu+0x44));\r
+  memcpy(m68ki_cpu_p->dar,cpu,0x40);\r
+  m68ki_cpu_p->pc=*(unsigned int *)(cpu+0x40);\r
+  m68ki_cpu_p->sp[m68ki_cpu_p->s_flag^SFLAG_SET]=*(unsigned int *)(cpu+0x48);\r
+  CPU_INT_LEVEL = cpu[0x4c] << 8;\r
+  CPU_STOPPED = cpu[0x4d];\r
+  m68k_set_context(oldcontext);\r
+#elif defined(EMU_F68K)\r
+  M68K_CONTEXT *context = is_sub ? &PicoCpuFS68k : &PicoCpuFM68k;\r
+  memcpy(context->dreg,cpu,0x40);\r
+  context->pc =*(unsigned int *)(cpu+0x40);\r
+  context->sr =*(unsigned int *)(cpu+0x44);\r
+  context->asp=*(unsigned int *)(cpu+0x48);\r
+  context->interrupts[0] = cpu[0x4c];\r
+  context->execinfo &= ~FM68K_HALTED;\r
+  if (cpu[0x4d]&1) context->execinfo |= FM68K_HALTED;\r
+#endif\r
+}\r
+\r
 \r
 /* idle loop detection, not to be used in CD mode */\r
 #ifdef EMU_C68K\r
index e94e731..cc75bff 100644 (file)
@@ -103,7 +103,7 @@ static unsigned char z80_sms_in(unsigned short a)
       break;
 
     case 0xc1: /* I/O port B and miscellaneous */
-      d = (Pico.sms_io_ctl & 0x80) | ((Pico.sms_io_ctl << 1) & 0x40) | 0x30;
+      d = (Pico.ms.io_ctl & 0x80) | ((Pico.ms.io_ctl << 1) & 0x40) | 0x30;
       d |= ~(PicoPad[1] >> 2) & 0x0f;
       break;
   }
@@ -119,7 +119,7 @@ static void z80_sms_out(unsigned short a, unsigned char d)
   switch (a)
   {
     case 0x01:
-      Pico.sms_io_ctl = d;
+      Pico.ms.io_ctl = d;
       break;
 
     case 0x40:
@@ -167,6 +167,7 @@ static void write_bank(unsigned short a, unsigned char d)
 #endif
       break;
   }
+  Pico.ms.carthw[a & 0x0f] = d;
 }
 
 static void xwrite(unsigned int a, unsigned char d)
@@ -174,7 +175,7 @@ static void xwrite(unsigned int a, unsigned char d)
   elprintf(EL_IO, "z80 write [%04x] %02x", a, d);
   if (a >= 0xc000)
     Pico.zram[a & 0x1fff] = d;
-  if (a >= 0xfff0)
+  if (a >= 0xfff8)
     write_bank(a, d);
 }
 
@@ -203,6 +204,9 @@ void PicoPowerMS(void)
   tmp = 1 << s;
   bank_mask = (tmp - 1) >> 14;
 
+  Pico.ms.carthw[0x0e] = 1;
+  Pico.ms.carthw[0x0f] = 2;
+
   PicoReset();
 }
 
@@ -229,6 +233,12 @@ void PicoMemSetupMS(void)
 #endif
 }
 
+void PicoStateLoadedMS(void)
+{
+  write_bank(0xfffe, Pico.ms.carthw[0x0e]);
+  write_bank(0xffff, Pico.ms.carthw[0x0f]);
+}
+
 void PicoFrameMS(void)
 {
   struct PicoVideo *pv = &Pico.video;
diff --git a/pico/state.c b/pico/state.c
new file mode 100644 (file)
index 0000000..60a6f72
--- /dev/null
@@ -0,0 +1,679 @@
+// (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
+#include "pico_int.h"\r
+#include <zlib/zlib.h>\r
+\r
+#include "../cpu/sh2/sh2.h"\r
+#include "sound/ym2612.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
+static areaseek  *areaSeek;\r
+static areaclose *areaClose;\r
+\r
+carthw_state_chunk *carthw_chunks;\r
+void (*PicoStateProgressCB)(const char *str);\r
+void (*PicoLoadStateHook)(void);\r
+\r
+\r
+/* I/O functions */\r
+static size_t gzRead2(void *p, size_t _size, size_t _n, void *file)\r
+{\r
+  return gzread(file, p, _size * _n);\r
+}\r
+\r
+static size_t gzWrite2(void *p, size_t _size, size_t _n, void *file)\r
+{\r
+  return gzwrite(file, p, _size * _n);\r
+}\r
+\r
+static void set_cbs(int gz)\r
+{\r
+  if (gz) {\r
+    areaRead  = gzRead2;\r
+    areaWrite = gzWrite2;\r
+    areaEof   = (areaeof *) gzeof;\r
+    areaSeek  = (areaseek *) gzseek;\r
+    areaClose = (areaclose *) gzclose;\r
+  } else {\r
+    areaRead  = (arearw *) fread;\r
+    areaWrite = (arearw *) fwrite;\r
+    areaEof   = (areaeof *) feof;\r
+    areaSeek  = (areaseek *) fseek;\r
+    areaClose = (areaclose *) fclose;\r
+  }\r
+}\r
+\r
+static void *open_save_file(const char *fname, int is_save)\r
+{\r
+  int len = strlen(fname);\r
+  void *afile = NULL;\r
+\r
+  if (len > 3 && strcmp(fname + len - 3, ".gz") == 0)\r
+  {\r
+    if ( (afile = gzopen(fname, is_save ? "wb" : "rb")) ) {\r
+      set_cbs(1);\r
+      if (is_save)\r
+        gzsetparams(afile, 9, Z_DEFAULT_STRATEGY);\r
+    }\r
+  }\r
+  else\r
+  {\r
+    if ( (afile = fopen(fname, is_save ? "wb" : "rb")) ) {\r
+      set_cbs(0);\r
+    }\r
+  }\r
+\r
+  return afile;\r
+}\r
+\r
+// legacy savestate loading\r
+#define SCANP(f, x) areaRead(&Pico.x, sizeof(Pico.x), 1, f)\r
+\r
+static int state_load_legacy(void *file)\r
+{\r
+  unsigned char head[32];\r
+  unsigned char cpu[0x60];\r
+  unsigned char cpu_z80[Z80_STATE_SIZE];\r
+  void *ym2612_regs;\r
+  int ok;\r
+\r
+  memset(&cpu,0,sizeof(cpu));\r
+  memset(&cpu_z80,0,sizeof(cpu_z80));\r
+\r
+  memset(head, 0, sizeof(head));\r
+  areaRead(head, sizeof(head), 1, file);\r
+  if (strcmp((char *)head, "Pico") != 0)\r
+    return -1;\r
+\r
+  elprintf(EL_STATUS, "legacy savestate");\r
+\r
+  // Scan all the memory areas:\r
+  SCANP(file, ram);\r
+  SCANP(file, vram);\r
+  SCANP(file, zram);\r
+  SCANP(file, cram);\r
+  SCANP(file, vsram);\r
+\r
+  // Pack, scan and unpack the cpu data:\r
+  areaRead(cpu, sizeof(cpu), 1, file);\r
+  SekUnpackCpu(cpu, 0);\r
+\r
+  SCANP(file, m);\r
+  SCANP(file, video);\r
+\r
+  ok = areaRead(cpu_z80, sizeof(cpu_z80), 1, file) == sizeof(cpu_z80);\r
+  // do not unpack if we fail to load z80 state\r
+  if (!ok) z80_reset();\r
+  else     z80_unpack(cpu_z80);\r
+\r
+  ym2612_regs = YM2612GetRegs();\r
+  areaRead(sn76496_regs, 28*4, 1, file);\r
+  areaRead(ym2612_regs, 0x200+4, 1, file);\r
+  ym2612_unpack_state();\r
+\r
+  return 0;\r
+}\r
+\r
+// ---------------------------------------------------------------------------\r
+\r
+typedef enum {\r
+  CHUNK_M68K = 1,\r
+  CHUNK_RAM,\r
+  CHUNK_VRAM,\r
+  CHUNK_ZRAM,\r
+  CHUNK_CRAM,    // 5\r
+  CHUNK_VSRAM,\r
+  CHUNK_MISC,\r
+  CHUNK_VIDEO,\r
+  CHUNK_Z80,\r
+  CHUNK_PSG,     // 10\r
+  CHUNK_FM,\r
+  // CD stuff\r
+  CHUNK_S68K,\r
+  CHUNK_PRG_RAM,\r
+  CHUNK_WORD_RAM,\r
+  CHUNK_PCM_RAM, // 15\r
+  CHUNK_BRAM,\r
+  CHUNK_GA_REGS,\r
+  CHUNK_PCM,\r
+  CHUNK_CDC,\r
+  CHUNK_CDD,     // 20\r
+  CHUNK_SCD,\r
+  CHUNK_RC,\r
+  CHUNK_MISC_CD,\r
+  //\r
+  CHUNK_IOPORTS, // versions < 1.70 did not save that..\r
+  CHUNK_SMS,     // 25\r
+  // 32x\r
+  CHUNK_MSH2,\r
+  CHUNK_MSH2_DATA,\r
+  CHUNK_MSH2_PERI,\r
+  CHUNK_SSH2,\r
+  CHUNK_SSH2_DATA, // 30\r
+  CHUNK_SSH2_PERI,\r
+  CHUNK_32XSYS,\r
+  CHUNK_M68K_BIOS,\r
+  CHUNK_MSH2_BIOS,\r
+  CHUNK_SSH2_BIOS, // 35\r
+  CHUNK_SDRAM,\r
+  CHUNK_DRAM,\r
+  CHUNK_32XPAL,\r
+  //\r
+  CHUNK_DEFAULT_COUNT,\r
+  CHUNK_CARTHW_ = CHUNK_CARTHW,  // defined in PicoInt\r
+} chunk_name_e;\r
+\r
+static const char * const chunk_names[] = {\r
+  "INVALID!",\r
+  "M68K state",\r
+  "RAM",\r
+  "VRAM",\r
+  "ZRAM",\r
+  "CRAM",      // 5\r
+  "VSRAM",\r
+  "emu state",\r
+  "VIDEO",\r
+  "Z80 state",\r
+  "PSG",       // 10\r
+  "FM",\r
+  // CD stuff\r
+  "S68K state",\r
+  "PRG_RAM",\r
+  "WORD_RAM",\r
+  "PCM_RAM",   // 15\r
+  "BRAM",\r
+  "GATE ARRAY regs",\r
+  "PCM state",\r
+  "CDC",\r
+  "CDD",       // 20\r
+  "SCD",\r
+  "GFX chip",\r
+  "MCD state",\r
+  //\r
+  "IO",\r
+  "SMS state", // 25\r
+  // 32x\r
+  "MSH2",\r
+  "MSH2 data",\r
+  "MSH2 peri",\r
+  "SSH2",\r
+  "SSH2 data", // 30\r
+  "SSH2 peri",\r
+  "32X system regs",\r
+  "M68K BIOS",\r
+  "MSH2 BIOS",\r
+  "SSH2 BIOS", // 35\r
+  "SDRAM",\r
+  "DRAM",\r
+  "PAL",\r
+};\r
+\r
+static int write_chunk(chunk_name_e name, int len, void *data, void *file)\r
+{\r
+  size_t bwritten = 0;\r
+  bwritten += areaWrite(&name, 1, 1, file);\r
+  bwritten += areaWrite(&len, 1, 4, file);\r
+  bwritten += areaWrite(data, 1, len, file);\r
+\r
+  return (bwritten == len + 4 + 1);\r
+}\r
+\r
+#define CHECKED_WRITE(name,len,data) { \\r
+  if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT) { \\r
+    strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \\r
+    PicoStateProgressCB(sbuff); \\r
+  } \\r
+  if (!write_chunk(name, len, data, file)) return 1; \\r
+}\r
+\r
+#define CHECKED_WRITE_BUFF(name,buff) { \\r
+  if (PicoStateProgressCB && name < CHUNK_DEFAULT_COUNT) { \\r
+    strncpy(sbuff + 9, chunk_names[name], sizeof(sbuff) - 9); \\r
+    PicoStateProgressCB(sbuff); \\r
+  } \\r
+  if (!write_chunk(name, sizeof(buff), &buff, file)) return 1; \\r
+}\r
+\r
+static int state_save(void *file)\r
+{\r
+  char sbuff[32] = "Saving.. ";\r
+  unsigned char buff[0x60], buff_z80[Z80_STATE_SIZE];\r
+  void *ym2612_regs = YM2612GetRegs();\r
+  int ver = 0x0170; // not really used..\r
+\r
+  areaWrite("PicoSEXT", 1, 8, file);\r
+  areaWrite(&ver, 1, 4, file);\r
+\r
+  if (!(PicoAHW & PAHW_SMS)) {\r
+    memset(buff, 0, sizeof(buff));\r
+    SekPackCpu(buff, 0);\r
+    CHECKED_WRITE_BUFF(CHUNK_M68K,  buff);\r
+    CHECKED_WRITE_BUFF(CHUNK_RAM,   Pico.ram);\r
+    CHECKED_WRITE_BUFF(CHUNK_VSRAM, Pico.vsram);\r
+    CHECKED_WRITE_BUFF(CHUNK_IOPORTS, Pico.ioports);\r
+    ym2612_pack_state();\r
+    CHECKED_WRITE(CHUNK_FM, 0x200+4, ym2612_regs);\r
+  }\r
+  else {\r
+    CHECKED_WRITE_BUFF(CHUNK_SMS, Pico.ms);\r
+  }\r
+\r
+  CHECKED_WRITE_BUFF(CHUNK_VRAM,  Pico.vram);\r
+  CHECKED_WRITE_BUFF(CHUNK_ZRAM,  Pico.zram);\r
+  CHECKED_WRITE_BUFF(CHUNK_CRAM,  Pico.cram);\r
+  CHECKED_WRITE_BUFF(CHUNK_MISC,  Pico.m);\r
+  CHECKED_WRITE_BUFF(CHUNK_VIDEO, Pico.video);\r
+\r
+  z80_pack(buff_z80);\r
+  CHECKED_WRITE_BUFF(CHUNK_Z80, buff_z80);\r
+  CHECKED_WRITE(CHUNK_PSG, 28*4, sn76496_regs);\r
+\r
+  if (PicoAHW & PAHW_MCD)\r
+  {\r
+    memset(buff, 0, sizeof(buff));\r
+    SekPackCpu(buff, 1);\r
+    if (Pico_mcd->s68k_regs[3] & 4) // 1M mode?\r
+      wram_1M_to_2M(Pico_mcd->word_ram2M);\r
+    Pico_mcd->m.hint_vector = *(unsigned short *)(Pico_mcd->bios + 0x72);\r
+\r
+    CHECKED_WRITE_BUFF(CHUNK_S68K,     buff);\r
+    CHECKED_WRITE_BUFF(CHUNK_PRG_RAM,  Pico_mcd->prg_ram);\r
+    CHECKED_WRITE_BUFF(CHUNK_WORD_RAM, Pico_mcd->word_ram2M); // in 2M format\r
+    CHECKED_WRITE_BUFF(CHUNK_PCM_RAM,  Pico_mcd->pcm_ram);\r
+    CHECKED_WRITE_BUFF(CHUNK_BRAM,     Pico_mcd->bram);\r
+    CHECKED_WRITE_BUFF(CHUNK_GA_REGS,  Pico_mcd->s68k_regs); // GA regs, not CPU regs\r
+    CHECKED_WRITE_BUFF(CHUNK_PCM,      Pico_mcd->pcm);\r
+    CHECKED_WRITE_BUFF(CHUNK_CDD,      Pico_mcd->cdd);\r
+    CHECKED_WRITE_BUFF(CHUNK_CDC,      Pico_mcd->cdc);\r
+    CHECKED_WRITE_BUFF(CHUNK_SCD,      Pico_mcd->scd);\r
+    CHECKED_WRITE_BUFF(CHUNK_RC,       Pico_mcd->rot_comp);\r
+    CHECKED_WRITE_BUFF(CHUNK_MISC_CD,  Pico_mcd->m);\r
+\r
+    if (Pico_mcd->s68k_regs[3] & 4) // convert back\r
+      wram_2M_to_1M(Pico_mcd->word_ram2M);\r
+  }\r
+\r
+  if (PicoAHW & PAHW_32X)\r
+  {\r
+    unsigned char cpubuff[SH2_STATE_SIZE];\r
+\r
+    memset(cpubuff, 0, sizeof(cpubuff));\r
+\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
+\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
+\r
+    CHECKED_WRITE_BUFF(CHUNK_32XSYS,    Pico32x);\r
+    CHECKED_WRITE_BUFF(CHUNK_M68K_BIOS, Pico32xMem->m68k_rom);\r
+    CHECKED_WRITE_BUFF(CHUNK_MSH2_BIOS, Pico32xMem->sh2_rom_m);\r
+    CHECKED_WRITE_BUFF(CHUNK_SSH2_BIOS, Pico32xMem->sh2_rom_s);\r
+    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
+\r
+  if (carthw_chunks != NULL)\r
+  {\r
+    carthw_state_chunk *chwc;\r
+    if (PicoStateProgressCB)\r
+      PicoStateProgressCB("Saving.. cart hw state");\r
+    for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++)\r
+      CHECKED_WRITE(chwc->chunk, chwc->size, chwc->ptr);\r
+  }\r
+\r
+  return 0;\r
+}\r
+\r
+static int g_read_offs = 0;\r
+\r
+#define R_ERROR_RETURN(error) \\r
+{ \\r
+  elprintf(EL_STATUS, "load_state @ %x: " error, g_read_offs); \\r
+  return 1; \\r
+}\r
+\r
+// when is eof really set?\r
+#define CHECKED_READ(len,data) { \\r
+  if (areaRead(data, 1, len, file) != len) { \\r
+    if (len == 1 && areaEof(file)) goto readend; \\r
+    R_ERROR_RETURN("areaRead: premature EOF\n"); \\r
+    return 1; \\r
+  } \\r
+  g_read_offs += len; \\r
+}\r
+\r
+#define CHECKED_READ2(len2,data) { \\r
+  if (len2 != len) { \\r
+    elprintf(EL_STATUS, "unexpected len %i, wanted %i (%s)", len, len2, #len2); \\r
+    if (len > len2) R_ERROR_RETURN("failed."); \\r
+    /* else read anyway and hope for the best.. */ \\r
+  } \\r
+  CHECKED_READ(len, data); \\r
+}\r
+\r
+#define CHECKED_READ_BUFF(buff) CHECKED_READ2(sizeof(buff), &buff);\r
+\r
+static int state_load(void *file)\r
+{\r
+  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 chunk;\r
+  void *ym2612_regs;\r
+  char header[8];\r
+  int ver, len;\r
+\r
+  g_read_offs = 0;\r
+  CHECKED_READ(8, header);\r
+  if (strncmp(header, "PicoSMCD", 8) && strncmp(header, "PicoSEXT", 8))\r
+    R_ERROR_RETURN("bad header");\r
+  CHECKED_READ(4, &ver);\r
+\r
+  while (!areaEof(file))\r
+  {\r
+    CHECKED_READ(1, &chunk);\r
+    CHECKED_READ(4, &len);\r
+    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
+\r
+    switch (chunk)\r
+    {\r
+      case CHUNK_M68K:\r
+        CHECKED_READ_BUFF(buff_m68k);\r
+        break;\r
+\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
+      case CHUNK_VRAM:    CHECKED_READ_BUFF(Pico.vram); break;\r
+      case CHUNK_ZRAM:    CHECKED_READ_BUFF(Pico.zram); break;\r
+      case CHUNK_CRAM:    CHECKED_READ_BUFF(Pico.cram); break;\r
+      case CHUNK_VSRAM:   CHECKED_READ_BUFF(Pico.vsram); break;\r
+      case CHUNK_MISC:    CHECKED_READ_BUFF(Pico.m); break;\r
+      case CHUNK_VIDEO:   CHECKED_READ_BUFF(Pico.video); break;\r
+      case CHUNK_IOPORTS: CHECKED_READ_BUFF(Pico.ioports); break;\r
+      case CHUNK_PSG:     CHECKED_READ2(28*4, sn76496_regs); break;\r
+      case CHUNK_FM:\r
+        ym2612_regs = YM2612GetRegs();\r
+        CHECKED_READ2(0x200+4, ym2612_regs);\r
+        ym2612_unpack_state();\r
+        break;\r
+\r
+      case CHUNK_SMS:\r
+        CHECKED_READ_BUFF(Pico.ms);\r
+        break;\r
+\r
+      // cd stuff\r
+      case CHUNK_S68K:\r
+        CHECKED_READ_BUFF(buff_s68k);\r
+        break;\r
+\r
+      case CHUNK_PRG_RAM:  CHECKED_READ_BUFF(Pico_mcd->prg_ram); break;\r
+      case CHUNK_WORD_RAM: CHECKED_READ_BUFF(Pico_mcd->word_ram2M); break;\r
+      case CHUNK_PCM_RAM:  CHECKED_READ_BUFF(Pico_mcd->pcm_ram); break;\r
+      case CHUNK_BRAM:     CHECKED_READ_BUFF(Pico_mcd->bram); break;\r
+      case CHUNK_GA_REGS:  CHECKED_READ_BUFF(Pico_mcd->s68k_regs); break;\r
+      case CHUNK_PCM:      CHECKED_READ_BUFF(Pico_mcd->pcm); break;\r
+      case CHUNK_CDD:      CHECKED_READ_BUFF(Pico_mcd->cdd); break;\r
+      case CHUNK_CDC:      CHECKED_READ_BUFF(Pico_mcd->cdc); break;\r
+      case CHUNK_SCD:      CHECKED_READ_BUFF(Pico_mcd->scd); break;\r
+      case CHUNK_RC:       CHECKED_READ_BUFF(Pico_mcd->rot_comp); break;\r
+      case CHUNK_MISC_CD:  CHECKED_READ_BUFF(Pico_mcd->m); break;\r
+\r
+      // 32x stuff\r
+      case CHUNK_MSH2:\r
+        CHECKED_READ_BUFF(buff_sh2);\r
+        sh2_unpack(&sh2s[0], buff_sh2);\r
+        break;\r
+\r
+      case CHUNK_SSH2:\r
+        CHECKED_READ_BUFF(buff_sh2);\r
+        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_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
+      case CHUNK_SSH2_BIOS:   CHECKED_READ_BUFF(Pico32xMem->sh2_rom_s); break;\r
+      case CHUNK_SDRAM:       CHECKED_READ_BUFF(Pico32xMem->sdram); break;\r
+      case CHUNK_DRAM:        CHECKED_READ_BUFF(Pico32xMem->dram); break;\r
+      case CHUNK_32XPAL:      CHECKED_READ_BUFF(Pico32xMem->pal); break;\r
+\r
+      default:\r
+        if (carthw_chunks != NULL)\r
+        {\r
+          carthw_state_chunk *chwc;\r
+          for (chwc = carthw_chunks; chwc->ptr != NULL; chwc++) {\r
+            if (chwc->chunk == chunk) {\r
+              CHECKED_READ2(chwc->size, chwc->ptr);\r
+              goto breakswitch;\r
+            }\r
+          }\r
+        }\r
+        elprintf(EL_STATUS, "load_state: skipping unknown chunk %i of size %i", chunk, len);\r
+        areaSeek(file, len, SEEK_CUR);\r
+        break;\r
+    }\r
+breakswitch:;\r
+  }\r
+\r
+readend:\r
+  if (PicoAHW & PAHW_SMS)\r
+    PicoStateLoadedMS();\r
+\r
+  if (PicoAHW & PAHW_MCD)\r
+  {\r
+    PicoMemStateLoaded();\r
+\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_SMS))\r
+    SekUnpackCpu(buff_m68k, 0);\r
+\r
+  if (PicoAHW & PAHW_32X)\r
+    Pico32xStateLoaded();\r
+\r
+  return 0;\r
+}\r
+\r
+static int state_load_gfx(void *file)\r
+{\r
+  int ver, len, found = 0, to_find = 4;\r
+  char buff[8];\r
+\r
+  if (PicoAHW & PAHW_32X)\r
+    to_find += 2;\r
+\r
+  g_read_offs = 0;\r
+  CHECKED_READ(8, buff);\r
+  if (strncmp((char *)buff, "PicoSMCD", 8) && strncmp((char *)buff, "PicoSEXT", 8))\r
+    R_ERROR_RETURN("bad header");\r
+  CHECKED_READ(4, &ver);\r
+\r
+  while (!areaEof(file) && found < to_find)\r
+  {\r
+    CHECKED_READ(1, buff);\r
+    CHECKED_READ(4, &len);\r
+    if (len < 0 || len > 1024*512) R_ERROR_RETURN("bad length");\r
+    if (buff[0] > CHUNK_FM && buff[0] <= CHUNK_MISC_CD && !(PicoAHW & PAHW_MCD))\r
+      R_ERROR_RETURN("cd chunk in non CD state?");\r
+\r
+    switch (buff[0])\r
+    {\r
+      case CHUNK_VRAM:  CHECKED_READ_BUFF(Pico.vram);  found++; break;\r
+      case CHUNK_CRAM:  CHECKED_READ_BUFF(Pico.cram);  found++; break;\r
+      case CHUNK_VSRAM: CHECKED_READ_BUFF(Pico.vsram); found++; break;\r
+      case CHUNK_VIDEO: CHECKED_READ_BUFF(Pico.video); found++; break;\r
+\r
+      case CHUNK_DRAM:\r
+        if (Pico32xMem != NULL)\r
+          CHECKED_READ_BUFF(Pico32xMem->dram);\r
+        break;\r
+\r
+      case CHUNK_32XPAL:\r
+        if (Pico32xMem != NULL)\r
+          CHECKED_READ_BUFF(Pico32xMem->pal);\r
+        Pico32x.dirty_pal = 1;\r
+        break;\r
+\r
+      case CHUNK_32XSYS:\r
+        CHECKED_READ_BUFF(Pico32x);\r
+        break;\r
+\r
+      default:\r
+        areaSeek(file, len, SEEK_CUR);\r
+        break;\r
+    }\r
+  }\r
+\r
+readend:\r
+  return 0;\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
+  if (is_save)\r
+    ret = state_save(afile);\r
+  else {\r
+    ret = state_load(afile);\r
+    if (ret != 0) {\r
+      areaSeek(afile, 0, SEEK_SET);\r
+      ret = state_load_legacy(afile);\r
+    }\r
+\r
+    if (PicoLoadStateHook != NULL)\r
+      PicoLoadStateHook();\r
+    Pico.m.dirtyPal = 1;\r
+  }\r
+\r
+  areaClose(afile);\r
+  return ret;\r
+}\r
+\r
+int PicoStateLoadGfx(const char *fname)\r
+{\r
+  void *afile;\r
+  int ret;\r
+\r
+  afile = open_save_file(fname, 0);\r
+  if (afile == NULL)\r
+    return -1;\r
+\r
+  ret = state_load_gfx(afile);\r
+  if (ret != 0) {\r
+    // assume legacy\r
+    areaSeek(afile, 0x10020, SEEK_SET);  // skip header and RAM\r
+    areaRead(Pico.vram, 1, sizeof(Pico.vram), afile);\r
+    areaSeek(afile, 0x2000, SEEK_CUR);\r
+    areaRead(Pico.cram, 1, sizeof(Pico.cram), afile);\r
+    areaRead(Pico.vsram, 1, sizeof(Pico.vsram), afile);\r
+    areaSeek(afile, 0x221a0, SEEK_SET);\r
+    areaRead(&Pico.video, 1, sizeof(Pico.video), afile);\r
+  }\r
+  areaClose(afile);\r
+  return 0;\r
+}\r
+\r
+// tmp state\r
+struct PicoTmp\r
+{\r
+  unsigned short vram[0x8000];\r
+  unsigned short cram[0x40];\r
+  unsigned short vsram[0x40];\r
+\r
+  //struct PicoMisc m;\r
+  struct PicoVideo video;\r
+\r
+  struct {\r
+    struct Pico32x p32x;\r
+    unsigned short dram[2][0x20000/2];\r
+    unsigned short pal[0x100];\r
+  } t32x;\r
+};\r
+\r
+// returns data ptr to free() or PicoTmpStateRestore()\r
+void *PicoTmpStateSave(void)\r
+{\r
+  // gfx only for now\r
+  struct PicoTmp *t = malloc(sizeof(*t));\r
+  if (t == NULL)\r
+    return NULL;\r
+\r
+  memcpy(t->vram, Pico.vram, sizeof(Pico.vram));\r
+  memcpy(t->cram, Pico.cram, sizeof(Pico.cram));\r
+  memcpy(t->vsram, Pico.vsram, sizeof(Pico.vsram));\r
+  memcpy(&t->video, &Pico.video, sizeof(Pico.video));\r
+\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
+\r
+  return t;\r
+}\r
+\r
+void PicoTmpStateRestore(void *data)\r
+{\r
+  struct PicoTmp *t = data;\r
+  if (t == NULL)\r
+    return;\r
+\r
+  memcpy(Pico.vram, t->vram, sizeof(Pico.vram));\r
+  memcpy(Pico.cram, t->cram, sizeof(Pico.cram));\r
+  memcpy(Pico.vsram, t->vsram, sizeof(Pico.vsram));\r
+  memcpy(&Pico.video, &t->video, sizeof(Pico.video));\r
+  Pico.m.dirtyPal = 1;\r
+\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
+}\r
+\r
+// vim:shiftwidth=2:expandtab\r
index 454938b..10c438a 100644 (file)
@@ -5,72 +5,60 @@
 uptr z80_read_map [0x10000 >> Z80_MEM_SHIFT];
 uptr z80_write_map[0x10000 >> Z80_MEM_SHIFT];
 
-#ifdef _USE_MZ80
+#ifdef _USE_DRZ80
+struct DrZ80 drZ80;
 
-// memhandlers for mz80 core
-unsigned char mz80_read(UINT32 a,  struct MemoryReadByte *w)  { return z80_read(a); }
-void mz80_write(UINT32 a, UINT8 d, struct MemoryWriteByte *w) { z80_write(d, a); }
+static u32 drz80_sp_base;
 
-// structures for mz80 core
-static struct MemoryReadByte mz80_mem_read[]=
-{
-  {0x0000,0xffff,mz80_read},
-  {(UINT32) -1,(UINT32) -1,NULL}
-};
-static struct MemoryWriteByte mz80_mem_write[]=
+static void drz80_load_pcsp(u32 pc, u32 sp)
 {
-  {0x0000,0xffff,mz80_write},
-  {(UINT32) -1,(UINT32) -1,NULL}
-};
-static struct z80PortRead mz80_io_read[] ={
-  {(UINT16) -1,(UINT16) -1,NULL}
-};
-static struct z80PortWrite mz80_io_write[]={
-  {(UINT16) -1,(UINT16) -1,NULL}
-};
+  drZ80.Z80PC_BASE = z80_read_map[pc >> Z80_MEM_SHIFT];
+  if (drZ80.Z80PC_BASE & (1<<31)) {
+    elprintf(EL_STATUS|EL_ANOMALY, "load_pcsp: bad PC: %04x", pc);
+    drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0];
+  } else {
+    drZ80.Z80PC_BASE <<= 1;
+    drZ80.Z80PC = drZ80.Z80PC_BASE + pc;
+  }
+  drZ80.Z80SP_BASE = z80_read_map[sp >> Z80_MEM_SHIFT];
+  if (drZ80.Z80SP_BASE & (1<<31)) {
+    elprintf(EL_STATUS|EL_ANOMALY, "load_pcsp: bad SP: %04x", sp);
+    drZ80.Z80SP_BASE = z80_read_map[0];
+    drZ80.Z80SP = drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT);
+  } else {
+    drZ80.Z80SP_BASE <<= 1;
+    drZ80.Z80SP = drZ80.Z80SP_BASE + sp;
+  }
+}
 
-int mz80_run(int cycles)
+// called only if internal xmap rebase fails
+static unsigned int dz80_rebase_pc(unsigned short pc)
 {
-  int ticks_pre = mz80GetElapsedTicks(0);
-  mz80exec(cycles);
-  return mz80GetElapsedTicks(0) - ticks_pre;
+  elprintf(EL_STATUS|EL_ANOMALY, "dz80_rebase_pc: fail on %04x", pc);
+  drZ80.Z80PC_BASE = z80_read_map[0] << 1;
+  return drZ80.Z80PC_BASE;
 }
 
-#endif
-
-#ifdef _USE_DRZ80
-struct DrZ80 drZ80;
+static unsigned int dz80_rebase_sp(unsigned short sp)
+{
+  elprintf(EL_STATUS|EL_ANOMALY, "dz80_rebase_sp: fail on %04x", sp);
+  drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1;
+  return drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT) - 0x100;
+}
 #endif
 
 
-PICO_INTERNAL void z80_init(void)
+void z80_init(void)
 {
-#ifdef _USE_MZ80
-  struct mz80context z80;
-
-  // z80
-  mz80init();
-  // Modify the default context
-  mz80GetContext(&z80);
-
-  // point mz80 stuff
-  z80.z80Base=Pico.zram;
-  z80.z80MemRead=mz80_mem_read;
-  z80.z80MemWrite=mz80_mem_write;
-  z80.z80IoRead=mz80_io_read;
-  z80.z80IoWrite=mz80_io_write;
-
-  mz80SetContext(&z80);
-#endif
 #ifdef _USE_DRZ80
   memset(&drZ80, 0, sizeof(drZ80));
-  drZ80.z80_rebasePC=NULL; // unused, handled by xmap
-  drZ80.z80_rebaseSP=NULL;
-  drZ80.z80_read8   =(void *)z80_read_map;
-  drZ80.z80_read16  =NULL;
-  drZ80.z80_write8  =(void *)z80_write_map;
-  drZ80.z80_write16 =NULL;
-  drZ80.z80_irq_callback=NULL;
+  drZ80.z80_rebasePC = dz80_rebase_pc;
+  drZ80.z80_rebaseSP = dz80_rebase_sp;
+  drZ80.z80_read8    = (void *)z80_read_map;
+  drZ80.z80_read16   = NULL;
+  drZ80.z80_write8   = (void *)z80_write_map;
+  drZ80.z80_write16  = NULL;
+  drZ80.z80_irq_callback = NULL;
 #endif
 #ifdef _USE_CZ80
   memset(&CZ80, 0, sizeof(CZ80));
@@ -80,113 +68,206 @@ PICO_INTERNAL void z80_init(void)
 #endif
 }
 
-PICO_INTERNAL void z80_reset(void)
+void z80_reset(void)
 {
-#ifdef _USE_MZ80
-  mz80reset();
-#endif
 #ifdef _USE_DRZ80
   memset(&drZ80, 0, 0x54);
   drZ80.Z80F  = (1<<2);  // set ZFlag
   drZ80.Z80F2 = (1<<2);  // set ZFlag
   drZ80.Z80IX = 0xFFFF << 16;
   drZ80.Z80IY = 0xFFFF << 16;
+  drZ80.Z80I = 0;
   drZ80.Z80IM = 0; // 1?
   drZ80.z80irqvector = 0xff0000; // RST 38h
   drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0] << 1;
   // drZ80 is locked in single bank
-  drZ80.Z80SP_BASE = ((PicoAHW & PAHW_SMS) ?
-    z80_read_map[0xc000 >> Z80_MEM_SHIFT] : z80_read_map[0]) << 1;
-//  drZ80.Z80SP = drZ80.z80_rebaseSP(0x2000); // 0xf000 ?
+  drz80_sp_base = (PicoAHW & PAHW_SMS) ? 0xc000 : 0x0000;
+  drZ80.Z80SP_BASE = z80_read_map[drz80_sp_base >> Z80_MEM_SHIFT] << 1;
+  if (PicoAHW & PAHW_SMS)
+    drZ80.Z80SP = drZ80.Z80SP_BASE + 0xdff0; // simulate BIOS
 #endif
 #ifdef _USE_CZ80
   Cz80_Reset(&CZ80);
   Cz80_Set_Reg(&CZ80, CZ80_IX, 0xffff);
   Cz80_Set_Reg(&CZ80, CZ80_IY, 0xffff);
-  Cz80_Set_Reg(&CZ80, CZ80_SP, 0x2000);
-#endif
-}
-
-// XXX TODO: should better use universal z80 save format
-PICO_INTERNAL void z80_pack(unsigned char *data)
-{
-#if defined(_USE_MZ80)
-  struct mz80context mz80;
-  *(int *)data = 0x00005A6D; // "mZ"
-  mz80GetContext(&mz80);
-  memcpy(data+4, &mz80.z80clockticks, sizeof(mz80)-5*4); // don't save base&memhandlers
-#elif defined(_USE_DRZ80)
-  *(int *)data = 0x015A7244; // "DrZ" v1
-//  drZ80.Z80PC = drZ80.z80_rebasePC(drZ80.Z80PC-drZ80.Z80PC_BASE);
-//  drZ80.Z80SP = drZ80.z80_rebaseSP(drZ80.Z80SP-drZ80.Z80SP_BASE);
-  memcpy(data+4, &drZ80, 0x54);
-#elif defined(_USE_CZ80)
-  *(int *)data = 0x00007a43; // "Cz"
-  *(int *)(data+4) = Cz80_Get_Reg(&CZ80, CZ80_PC);
-  memcpy(data+8, &CZ80, offsetof(cz80_struc, BasePC));
+  if (PicoAHW & PAHW_SMS)
+    Cz80_Set_Reg(&CZ80, CZ80_SP, 0xdff0);
 #endif
 }
 
-PICO_INTERNAL void z80_unpack(unsigned char *data)
+/* save state stuff */
+static int z80_unpack_legacy(const void *data)
 {
-#if defined(_USE_MZ80)
-  if (*(int *)data == 0x00005A6D) { // "mZ" save?
-    struct mz80context mz80;
-    mz80GetContext(&mz80);
-    memcpy(&mz80.z80clockticks, data+4, sizeof(mz80)-5*4);
-    mz80SetContext(&mz80);
-  } else {
-    z80_reset();
-    z80_int();
-  }
-#elif defined(_USE_DRZ80)
+#if defined(_USE_DRZ80)
   if (*(int *)data == 0x015A7244) { // "DrZ" v1 save?
-    int pc, sp;
+    u32 pc, sp;
     memcpy(&drZ80, data+4, 0x54);
     pc = (drZ80.Z80PC - drZ80.Z80PC_BASE) & 0xffff;
     sp = (drZ80.Z80SP - drZ80.Z80SP_BASE) & 0xffff;
     // update bases
-    drZ80.Z80PC_BASE = z80_read_map[pc >> Z80_MEM_SHIFT];
-    if (drZ80.Z80PC & (1<<31)) {
-      elprintf(EL_STATUS|EL_ANOMALY, "bad PC in z80 save: %04x", pc);
-      drZ80.Z80PC_BASE = drZ80.Z80PC = z80_read_map[0];
-    } else {
-      drZ80.Z80PC_BASE <<= 1;
-      drZ80.Z80PC = drZ80.Z80PC_BASE + pc;
-    }
-    drZ80.Z80SP_BASE = z80_read_map[sp >> Z80_MEM_SHIFT];
-    if (drZ80.Z80SP & (1<<31)) {
-      elprintf(EL_STATUS|EL_ANOMALY, "bad SP in z80 save: %04x", sp);
-      drZ80.Z80SP_BASE = z80_read_map[0];
-      drZ80.Z80SP = drZ80.Z80SP_BASE + (1 << Z80_MEM_SHIFT);
-    } else {
-      drZ80.Z80SP_BASE <<= 1;
-      drZ80.Z80SP = drZ80.Z80SP_BASE + sp;
-    }
-  } else {
-    z80_reset();
-    drZ80.Z80IM = 1;
-    z80_int(); // try to goto int handler, maybe we won't execute trash there?
+    drz80_load_pcsp(pc, sp);
+    return 0;
   }
 #elif defined(_USE_CZ80)
   if (*(int *)data == 0x00007a43) { // "Cz" save?
     memcpy(&CZ80, data+8, offsetof(cz80_struc, BasePC));
     Cz80_Set_Reg(&CZ80, CZ80_PC, *(int *)(data+4));
-  } else {
-    z80_reset();
-    z80_int();
+    return 0;
   }
 #endif
+  return -1;
 }
 
-PICO_INTERNAL void z80_exit(void)
+struct z80sr_main {
+  u8 a, f;
+  u8 b, c;
+  u8 d, e;
+  u8 h, l;
+};
+
+struct z80_state {
+  char magic[4];
+  // regs
+  struct z80sr_main m; // main regs
+  struct z80sr_main a; // alt (') regs
+  u8  i, r;
+  u16 ix, iy;
+  u16 sp;
+  u16 pc;
+  // other
+  u8 halted;
+  u8 iff1, iff2;
+  u8 im;            // irq mode
+  u8 irq_pending;   // irq line level, 1 if active
+  u8 irq_vector[3]; // up to 3 byte vector for irq mode0 handling
+  u8 reserved[8];
+};
+
+void z80_pack(void *data)
 {
-#if defined(_USE_MZ80)
-  mz80shutdown();
+  struct z80_state *s = data;
+  memset(data, 0, Z80_STATE_SIZE);
+  strcpy(s->magic, "Z80");
+#if defined(_USE_DRZ80)
+  #define DRR8(n)   (drZ80.Z80##n >> 24)
+  #define DRR16(n)  (drZ80.Z80##n >> 16)
+  #define DRR16H(n) (drZ80.Z80##n >> 24)
+  #define DRR16L(n) ((drZ80.Z80##n >> 16) & 0xff)
+  s->m.a = DRR8(A);     s->m.f = DRR8(F);
+  s->m.b = DRR16H(BC);  s->m.c = DRR16L(BC);
+  s->m.d = DRR16H(DE);  s->m.e = DRR16L(DE);
+  s->m.h = DRR16H(HL);  s->m.l = DRR16L(HL);
+  s->a.a = DRR8(A2);    s->a.f = DRR8(F2);
+  s->a.b = DRR16H(BC2); s->a.c = DRR16L(BC2);
+  s->a.d = DRR16H(DE2); s->a.e = DRR16L(DE2);
+  s->a.h = DRR16H(HL2); s->a.l = DRR16L(HL2);
+  s->i = DRR8(I);       s->r = drZ80.spare;
+  s->ix = DRR16(IX);    s->iy = DRR16(IY);
+  s->sp = drZ80.Z80SP - drZ80.Z80SP_BASE;
+  s->pc = drZ80.Z80PC - drZ80.Z80PC_BASE;
+  s->halted = !!(drZ80.Z80IF & 4);
+  s->iff1 = !!(drZ80.Z80IF & 1);
+  s->iff2 = !!(drZ80.Z80IF & 2);
+  s->im = drZ80.Z80IM;
+  s->irq_pending = !!drZ80.Z80_IRQ;
+  s->irq_vector[0] = drZ80.z80irqvector >> 16;
+  s->irq_vector[1] = drZ80.z80irqvector >> 8;
+  s->irq_vector[2] = drZ80.z80irqvector;
+#elif defined(_USE_CZ80)
+  {
+    const cz80_struc *CPU = &CZ80;
+    s->m.a = zA;  s->m.f = zF;
+    s->m.b = zB;  s->m.c = zC;
+    s->m.d = zD;  s->m.e = zE;
+    s->m.h = zH;  s->m.l = zL;
+    s->a.a = zA2; s->a.f = zF2;
+    s->a.b = CZ80.BC2.B.H; s->a.c = CZ80.BC2.B.L;
+    s->a.d = CZ80.DE2.B.H; s->a.e = CZ80.DE2.B.L;
+    s->a.h = CZ80.HL2.B.H; s->a.l = CZ80.HL2.B.L;
+    s->i  = zI;   s->r  = zR;
+    s->ix = zIX;  s->iy = zIY;
+    s->sp = Cz80_Get_Reg(&CZ80, CZ80_SP);
+    s->pc = Cz80_Get_Reg(&CZ80, CZ80_PC);
+    s->halted = !!Cz80_Get_Reg(&CZ80, CZ80_HALT);
+    s->iff1 = !!zIFF1;
+    s->iff2 = !!zIFF2;
+    s->im = zIM;
+    s->irq_pending = (Cz80_Get_Reg(&CZ80, CZ80_IRQ) == HOLD_LINE);
+    s->irq_vector[0] = 0xff;
+  }
 #endif
 }
 
-PICO_INTERNAL void z80_debug(char *dstr)
+int z80_unpack(const void *data)
+{
+  const struct z80_state *s = data;
+  if (strcmp(s->magic, "Z80") != 0) {
+    if (z80_unpack_legacy(data) != 0)
+      goto fail;
+    elprintf(EL_STATUS, "legacy z80 state");
+    return 0;
+  }
+
+#if defined(_USE_DRZ80)
+  #define DRW8(n, v)       drZ80.Z80##n = (u32)(v) << 24
+  #define DRW16(n, v)      drZ80.Z80##n = (u32)(v) << 16
+  #define DRW16HL(n, h, l) drZ80.Z80##n = ((u32)(h) << 24) | ((u32)(l) << 16)
+  DRW8(A, s->m.a);  DRW8(F, s->m.f);
+  DRW16HL(BC, s->m.b, s->m.c);
+  DRW16HL(DE, s->m.d, s->m.e);
+  DRW16HL(HL, s->m.h, s->m.l);
+  DRW8(A2, s->a.a); DRW8(F2, s->a.f);
+  DRW16HL(BC2, s->a.b, s->a.c);
+  DRW16HL(DE2, s->a.d, s->a.e);
+  DRW16HL(HL2, s->a.h, s->a.l);
+  DRW8(I, s->i);    drZ80.spare = s->r;
+  DRW16(IX, s->ix); DRW16(IY, s->iy);
+  drz80_load_pcsp(s->pc, s->sp);
+  drZ80.Z80IF = 0;
+  if (s->halted) drZ80.Z80IF |= 4;
+  if (s->iff1)   drZ80.Z80IF |= 1;
+  if (s->iff2)   drZ80.Z80IF |= 2;
+  drZ80.Z80IM = s->im;
+  drZ80.Z80_IRQ = s->irq_pending;
+  drZ80.z80irqvector = ((u32)s->irq_vector[0] << 16) |
+    ((u32)s->irq_vector[1] << 8) | s->irq_vector[2];
+  return 0;
+#elif defined(_USE_CZ80)
+  {
+    cz80_struc *CPU = &CZ80;
+    zA  = s->m.a; zF  = s->m.f;
+    zB  = s->m.b; zC  = s->m.c;
+    zD  = s->m.d; zE  = s->m.e;
+    zH  = s->m.h; zL  = s->m.l;
+    zA2 = s->a.a; zF2 = s->a.f;
+    CZ80.BC2.B.H = s->a.b; CZ80.BC2.B.L = s->a.c;
+    CZ80.DE2.B.H = s->a.d; CZ80.DE2.B.L = s->a.e;
+    CZ80.HL2.B.H = s->a.h; CZ80.HL2.B.L = s->a.l;
+    zI  = s->i;   zR  = s->r;
+    zIX = s->ix;  zIY = s->iy;
+    Cz80_Set_Reg(&CZ80, CZ80_SP, s->sp);
+    Cz80_Set_Reg(&CZ80, CZ80_PC, s->pc);
+    Cz80_Set_Reg(&CZ80, CZ80_HALT, s->halted);
+    Cz80_Set_Reg(&CZ80, CZ80_IFF1, s->iff1);
+    Cz80_Set_Reg(&CZ80, CZ80_IFF2, s->iff2);
+    zIM = s->im;
+    Cz80_Set_Reg(&CZ80, CZ80_IRQ, s->irq_pending ? HOLD_LINE : CLEAR_LINE);
+    return 0;
+  }
+#endif
+
+fail:
+  elprintf(EL_STATUS|EL_ANOMALY, "z80_unpack failed");
+  z80_reset();
+  z80_int();
+  return -1;
+}
+
+void z80_exit(void)
+{
+}
+
+void z80_debug(char *dstr)
 {
 #if defined(_USE_DRZ80)
   sprintf(dstr, "Z80 state: PC: %04x SP: %04x\n", drZ80.Z80PC-drZ80.Z80PC_BASE, drZ80.Z80SP-drZ80.Z80SP_BASE);
index 061771e..2a240b0 100644 (file)
@@ -25,13 +25,13 @@ endif
 
 # === Pico core ===
 # Pico
-OBJS += pico/area.o pico/cart.o pico/memory.o pico/pico.o pico/sek.o pico/z80if.o \
+OBJS += pico/state.o pico/cart.o pico/memory.o pico/pico.o pico/sek.o pico/z80if.o \
        pico/videoport.o pico/draw2.o pico/draw.o pico/mode4.o pico/sms.o \
        pico/misc.o pico/eeprom.o pico/patch.o pico/debug.o
 # CD
 OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \
        pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \
-       pico/cd/area.o pico/cd/misc.o pico/cd/pcm.o pico/cd/buffering.o
+       pico/cd/misc.o pico/cd/pcm.o pico/cd/buffering.o
 # 32X
 OBJS += pico/32x/32x.o pico/32x/memory.o pico/32x/draw.o pico/32x/pwm.o
 # Pico
@@ -62,11 +62,6 @@ OBJS += cpu/fame/famec.o
 endif
 
 # --- Z80 ---
-ifeq "$(use_mz80)" "1"
-DEFINES += _USE_MZ80
-OBJS += cpu/mz80/mz80.o
-endif
-#
 ifeq "$(use_drz80)" "1"
 DEFINES += _USE_DRZ80
 OBJS += cpu/DrZ80/drz80.o
index 34d5b49..5b0474a 100644 (file)
@@ -19,7 +19,7 @@
 #include <version.h>\r
 #include <revision.h>\r
 \r
-#include <pico/pico_int.h>\r
+#include <pico/pico.h>\r
 #include <pico/patch.h>\r
 \r
 static char static_buff[64];\r
@@ -1039,34 +1039,22 @@ static void state_check_slots(void)
 \r
 static void draw_savestate_bg(int slot)\r
 {\r
-       struct PicoVideo tmp_pv;\r
-       unsigned short tmp_cram[0x40];\r
-       unsigned short tmp_vsram[0x40];\r
-       void *tmp_vram;\r
        const char *fname;\r
+       void *tmp_state;\r
 \r
        fname = emu_get_save_fname(1, 0, slot);\r
-       if (!fname) return;\r
-\r
-       tmp_vram = malloc(sizeof(Pico.vram));\r
-       if (tmp_vram == NULL) return;\r
+       if (!fname)\r
+               return;\r
 \r
-       memcpy(tmp_vram, Pico.vram, sizeof(Pico.vram));\r
-       memcpy(tmp_cram, Pico.cram, sizeof(Pico.cram));\r
-       memcpy(tmp_vsram, Pico.vsram, sizeof(Pico.vsram));\r
-       memcpy(&tmp_pv, &Pico.video, sizeof(Pico.video));\r
+       tmp_state = PicoTmpStateSave();\r
 \r
-       PicoStateLoadVDP(fname);\r
+       PicoStateLoadGfx(fname);\r
 \r
        /* do a frame and fetch menu bg */\r
        pemu_forced_frame(POPT_EN_SOFTSCALE);\r
        menu_enter(1);\r
 \r
-       memcpy(Pico.vram, tmp_vram, sizeof(Pico.vram));\r
-       memcpy(Pico.cram, tmp_cram, sizeof(Pico.cram));\r
-       memcpy(Pico.vsram, tmp_vsram, sizeof(Pico.vsram));\r
-       memcpy(&Pico.video, &tmp_pv,  sizeof(Pico.video));\r
-       free(tmp_vram);\r
+       PicoTmpStateRestore(tmp_state);\r
 }\r
 \r
 static void draw_savestate_menu(int menu_sel, int is_loading)\r
@@ -1105,6 +1093,7 @@ static int menu_loop_savestate(int is_loading)
        static int menu_sel = 10;\r
        int menu_sel_max = 10;\r
        unsigned long inp = 0;\r
+       int ret = 0;\r
 \r
        state_check_slots();\r
 \r
@@ -1134,15 +1123,18 @@ static int menu_loop_savestate(int is_loading)
                                state_slot = menu_sel;\r
                                if (emu_save_load_game(is_loading, 0)) {\r
                                        me_update_msg(is_loading ? "Load failed" : "Save failed");\r
-                                       return 0;\r
+                                       break;\r
                                }\r
-                               return 1;\r
+                               ret = 1;\r
+                               break;\r
                        }\r
-                       return 0;\r
+                       break;\r
                }\r
                if (inp & PBTN_MBACK)\r
-                       return 0;\r
+                       break;\r
        }\r
+\r
+       return ret;\r
 }\r
 \r
 // -------------- key config --------------\r