region detection, cd states wip, fixes, stuff
[picodrive.git] / Pico / Area.c
CommitLineData
cc68a136 1// This is part of Pico Library\r
2\r
3// (c) Copyright 2004 Dave, All rights reserved.\r
4// (c) Copyright 2006 notaz, All rights reserved.\r
5// Free for non-commercial use.\r
6\r
7// For commercial use, separate licencing terms must be obtained.\r
8\r
9\r
10#include "PicoInt.h"\r
11\r
12// ym2612\r
13#include "sound/ym2612.h"\r
14\r
15// sn76496\r
16extern int *sn76496_regs;\r
17\r
18\r
19struct PicoArea { void *data; int len; char *name; };\r
20\r
21// strange observation on Symbian OS 9.1, m600 organizer fw r3a06:\r
22// taking an address of fread or fwrite causes "application could't be started" error\r
23// on startup randomly depending on binary layout of executable file.\r
24\r
51a902ae 25arearw *areaRead = (arearw *) 0; // fread; // read and write function pointers for\r
26arearw *areaWrite = (arearw *) 0; // fwrite; // gzip save state ability\r
27areaeof *areaEof = (areaeof *) 0;\r
cc68a136 28\r
29\r
30// Scan one variable and callback\r
31static int ScanVar(void *data,int len,char *name,void *PmovFile,int PmovAction)\r
32{\r
33 int ret = 0;\r
34 if ((PmovAction&3)==1) ret = areaWrite(data,1,len,PmovFile);\r
35 if ((PmovAction&3)==2) ret = areaRead (data,1,len,PmovFile);\r
36 return (ret != len);\r
37}\r
38\r
39#define SCAN_VAR(x,y) ScanVar(&x,sizeof(x),y,PmovFile,PmovAction);\r
40#define SCANP(x) ScanVar(&Pico.x,sizeof(Pico.x),#x,PmovFile,PmovAction);\r
41\r
42// Pack the cpu into a common format:\r
51a902ae 43int PicoAreaPackCpu(unsigned char *cpu, int is_sub)\r
cc68a136 44{\r
45 unsigned int pc=0;\r
46\r
47#ifdef EMU_A68K\r
48 memcpy(cpu,M68000_regs.d,0x40);\r
49 pc=M68000_regs.pc;\r
50 *(unsigned char *)(cpu+0x44)=(unsigned char)M68000_regs.ccr;\r
51 *(unsigned char *)(cpu+0x45)=(unsigned char)M68000_regs.srh;\r
52 *(unsigned int *)(cpu+0x48)=M68000_regs.isp;\r
53#endif\r
54\r
55#ifdef EMU_C68K\r
51a902ae 56 struct Cyclone *context = is_sub ? &PicoCpuS68k : &PicoCpu;\r
57 memcpy(cpu,context->d,0x40);\r
58 pc=context->pc-context->membase;\r
59 *(unsigned int *)(cpu+0x44)=CycloneGetSr(context);\r
60 *(unsigned int *)(cpu+0x48)=context->osp;\r
cc68a136 61#endif\r
62\r
63#ifdef EMU_M68K\r
51a902ae 64 m68ki_cpu_core *context = is_sub ? &PicoS68kCPU : &PicoM68kCPU;\r
65 memcpy(cpu,context->dar,0x40);\r
66 pc=context->pc;\r
cc68a136 67 *(unsigned int *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR);\r
51a902ae 68 *(unsigned int *)(cpu+0x48)=context->sp[0];\r
cc68a136 69#endif\r
70\r
71 *(unsigned int *)(cpu+0x40)=pc;\r
72 return 0;\r
73}\r
74\r
51a902ae 75int PicoAreaUnpackCpu(unsigned char *cpu, int is_sub)\r
cc68a136 76{\r
cc68a136 77#ifdef EMU_A68K\r
78 memcpy(M68000_regs.d,cpu,0x40);\r
79 M68000_regs.pc=pc;\r
80 M68000_regs.ccr=*(unsigned char *)(cpu+0x44);\r
81 M68000_regs.srh=*(unsigned char *)(cpu+0x45);\r
82 M68000_regs.isp=*(unsigned int *)(cpu+0x48);\r
83#endif\r
84\r
85#ifdef EMU_C68K\r
51a902ae 86 struct Cyclone *context = is_sub ? &PicoCpuS68k : &PicoCpu;\r
87 CycloneSetSr(context, *(unsigned int *)(cpu+0x44));\r
88 context->osp=*(unsigned int *)(cpu+0x48);\r
89 memcpy(context->d,cpu,0x40);\r
90 context->membase=0;\r
91 context->pc = context->checkpc(*(unsigned int *)(cpu+0x40)); // Base pc\r
cc68a136 92#endif\r
93\r
94#ifdef EMU_M68K\r
51a902ae 95 m68ki_cpu_core *context = is_sub ? &PicoS68kCPU : &PicoM68kCPU;\r
96 memcpy(context->dar,cpu,0x40);\r
97 context->pc=*(unsigned int *)(cpu+0x40);\r
cc68a136 98 m68k_set_reg(M68K_REG_SR, *(unsigned int *)(cpu+0x44));\r
51a902ae 99 context->sp[0]=*(unsigned int *)(cpu+0x48);\r
cc68a136 100#endif\r
101 return 0;\r
102}\r
103\r
104// Scan the contents of the virtual machine's memory for saving or loading\r
105static int PicoAreaScan(int PmovAction,unsigned int ver, void *PmovFile)\r
106{\r
107 void *ym2612_regs;\r
108 unsigned char cpu[0x60];\r
109 unsigned char cpu_z80[0x60];\r
110 int ret;\r
111\r
112 memset(&cpu,0,sizeof(cpu));\r
113 memset(&cpu_z80,0,sizeof(cpu_z80));\r
114\r
115 ym2612_regs = YM2612GetRegs();\r
116\r
117 if (PmovAction&4)\r
118 {\r
119 Pico.m.scanline=0;\r
120\r
51a902ae 121 // Scan all the memory areas:\r
cc68a136 122 SCANP(ram) SCANP(vram) SCANP(zram) SCANP(cram) SCANP(vsram)\r
123\r
124 // Pack, scan and unpack the cpu data:\r
51a902ae 125 if((PmovAction&3)==1) PicoAreaPackCpu(cpu, 0);\r
cc68a136 126 //SekInit(); // notaz: do we really have to do this here?\r
127 //PicoMemInit();\r
128 SCAN_VAR(cpu,"cpu")\r
51a902ae 129 if((PmovAction&3)==2) PicoAreaUnpackCpu(cpu, 0);\r
cc68a136 130\r
131 SCAN_VAR(Pico.m ,"misc")\r
132 SCAN_VAR(Pico.video,"video")\r
133\r
51a902ae 134 // notaz: save/load z80, YM2612, sn76496 states instead of Pico.s (which is unused anyway)\r
135 if(PicoOpt&7) {\r
136 if((PmovAction&3)==1) z80_pack(cpu_z80);\r
cc68a136 137 ret = SCAN_VAR(cpu_z80,"cpu_z80")\r
51a902ae 138 // do not unpack if we fail to load z80 state\r
139 if((PmovAction&3)==2) {\r
cc68a136 140 if(ret) z80_reset();\r
141 else z80_unpack(cpu_z80);\r
142 }\r
51a902ae 143 }\r
144 if(PicoOpt&3)\r
cc68a136 145 ScanVar(sn76496_regs,28*4,"SN76496state", PmovFile, PmovAction); // regs and other stuff\r
51a902ae 146 if(PicoOpt&1) {\r
cc68a136 147 ScanVar(ym2612_regs, 0x200+4, "YM2612state", PmovFile, PmovAction); // regs + addr line\r
51a902ae 148 if((PmovAction&3)==2) YM2612PicoStateLoad(); // reload YM2612 state from it's regs\r
149 }\r
cc68a136 150 }\r
151\r
152 return 0;\r
153}\r
154\r
155// ---------------------------------------------------------------------------\r
156// Helper code to save/load to a file handle\r
157\r
158// Save or load the state from PmovFile:\r
159int PmovState(int PmovAction, void *PmovFile)\r
160{\r
161 int minimum=0;\r
162 unsigned char head[32];\r
163\r
51a902ae 164 // testing\r
165 {\r
166 if (PmovAction&1) return PicoCdSaveState(PmovFile);\r
167 if (PmovAction&2) return PicoCdLoadState(PmovFile);\r
168 }\r
169\r
cc68a136 170 memset(head,0,sizeof(head));\r
171\r
172 // Find out minimal compatible version:\r
173 //PicoAreaScan(PmovAction&0xc,&minimum);\r
174 minimum = 0x0021;\r
175\r
176 memcpy(head,"Pico",4);\r
177 *(unsigned int *)(head+0x8)=PicoVer;\r
178 *(unsigned int *)(head+0xc)=minimum;\r
179\r
180 // Scan header:\r
181 if (PmovAction&1) areaWrite(head,1,sizeof(head),PmovFile);\r
182 if (PmovAction&2) areaRead (head,1,sizeof(head),PmovFile);\r
183\r
184 // Scan memory areas:\r
185 PicoAreaScan(PmovAction, *(unsigned int *)(head+0x8), PmovFile);\r
186\r
187 return 0;\r
188}\r
189\r