\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
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
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
.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
.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
.if FAST_Z80SP\r
ldrh r0,[z80xx,#2]\r
rebasesp\r
- mov z80sp,r0\r
.else\r
ldrh z80sp,[z80xx,#2]\r
.endif\r
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
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
#include <string.h>
+#include <stddef.h>
+
#include "sh2.h"
#include "../debug.h"
#include "compiler.h"
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];
+}
+
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
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);
}
// 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
#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) {
// 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);
#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
void p32x_pwm_update(int *buf32, int length, int stereo)
{
- extern int pwm_ptr;
short *pwmb;
int step;
int p = 0;
+++ /dev/null
-// 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
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
+++ /dev/null
-// 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;
-}
-
-
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
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
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
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
// 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
\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
\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
\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
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
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
\r
struct PicoMisc m;\r
struct PicoVideo video;\r
+ struct PicoMS ms;\r
};\r
\r
// sram\r
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
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
};\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
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
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
\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
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
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
\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
#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
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;
}
switch (a)
{
case 0x01:
- Pico.sms_io_ctl = d;
+ Pico.ms.io_ctl = d;
break;
case 0x40:
#endif
break;
}
+ Pico.ms.carthw[a & 0x0f] = d;
}
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);
}
tmp = 1 << s;
bank_mask = (tmp - 1) >> 14;
+ Pico.ms.carthw[0x0e] = 1;
+ Pico.ms.carthw[0x0f] = 2;
+
PicoReset();
}
#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;
--- /dev/null
+// (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
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));
#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);
# === 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
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
#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
\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
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
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