1.10 release
[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
25arearw *areaRead = (arearw *) 0; // fread; // read and write function pointers for\r
26arearw *areaWrite = (arearw *) 0; // fwrite; // gzip save state ability\r
27\r
28\r
29// Scan one variable and callback\r
30static int ScanVar(void *data,int len,char *name,void *PmovFile,int PmovAction)\r
31{\r
32 int ret = 0;\r
33 if ((PmovAction&3)==1) ret = areaWrite(data,1,len,PmovFile);\r
34 if ((PmovAction&3)==2) ret = areaRead (data,1,len,PmovFile);\r
35 return (ret != len);\r
36}\r
37\r
38#define SCAN_VAR(x,y) ScanVar(&x,sizeof(x),y,PmovFile,PmovAction);\r
39#define SCANP(x) ScanVar(&Pico.x,sizeof(Pico.x),#x,PmovFile,PmovAction);\r
40\r
41// Pack the cpu into a common format:\r
42static int PackCpu(unsigned char *cpu)\r
43{\r
44 unsigned int pc=0;\r
45\r
46#ifdef EMU_A68K\r
47 memcpy(cpu,M68000_regs.d,0x40);\r
48 pc=M68000_regs.pc;\r
49 *(unsigned char *)(cpu+0x44)=(unsigned char)M68000_regs.ccr;\r
50 *(unsigned char *)(cpu+0x45)=(unsigned char)M68000_regs.srh;\r
51 *(unsigned int *)(cpu+0x48)=M68000_regs.isp;\r
52#endif\r
53\r
54#ifdef EMU_C68K\r
55 memcpy(cpu,PicoCpu.d,0x40);\r
56 pc=PicoCpu.pc-PicoCpu.membase;\r
57 *(unsigned int *)(cpu+0x44)=CycloneGetSr(&PicoCpu);\r
58 *(unsigned int *)(cpu+0x48)=PicoCpu.osp;\r
59#endif\r
60\r
61#ifdef EMU_M68K\r
62 memcpy(cpu,m68ki_cpu.dar,0x40);\r
63 pc=m68ki_cpu.pc;\r
64 *(unsigned int *)(cpu+0x44)=m68k_get_reg(NULL, M68K_REG_SR);\r
65 *(unsigned int *)(cpu+0x48)=m68ki_cpu.sp[0];\r
66#endif\r
67\r
68 *(unsigned int *)(cpu+0x40)=pc;\r
69 return 0;\r
70}\r
71\r
72static int UnpackCpu(unsigned char *cpu)\r
73{\r
74 unsigned int pc=0;\r
75\r
76 pc=*(unsigned int *)(cpu+0x40);\r
77\r
78#ifdef EMU_A68K\r
79 memcpy(M68000_regs.d,cpu,0x40);\r
80 M68000_regs.pc=pc;\r
81 M68000_regs.ccr=*(unsigned char *)(cpu+0x44);\r
82 M68000_regs.srh=*(unsigned char *)(cpu+0x45);\r
83 M68000_regs.isp=*(unsigned int *)(cpu+0x48);\r
84#endif\r
85\r
86#ifdef EMU_C68K\r
87 CycloneSetSr(&PicoCpu, *(unsigned int *)(cpu+0x44));\r
88 PicoCpu.osp=*(unsigned int *)(cpu+0x48);\r
89 memcpy(PicoCpu.d,cpu,0x40);\r
90 PicoCpu.membase=0;\r
91 PicoCpu.pc =PicoCpu.checkpc(pc); // Base pc\r
92#endif\r
93\r
94#ifdef EMU_M68K\r
95 memcpy(m68ki_cpu.dar,cpu,0x40);\r
96 m68ki_cpu.pc=pc;\r
97 m68k_set_reg(M68K_REG_SR, *(unsigned int *)(cpu+0x44));\r
98 m68ki_cpu.sp[0]=*(unsigned int *)(cpu+0x48);\r
99#endif\r
100 return 0;\r
101}\r
102\r
103// Scan the contents of the virtual machine's memory for saving or loading\r
104static int PicoAreaScan(int PmovAction,unsigned int ver, void *PmovFile)\r
105{\r
106 void *ym2612_regs;\r
107 unsigned char cpu[0x60];\r
108 unsigned char cpu_z80[0x60];\r
109 int ret;\r
110\r
111 memset(&cpu,0,sizeof(cpu));\r
112 memset(&cpu_z80,0,sizeof(cpu_z80));\r
113\r
114 ym2612_regs = YM2612GetRegs();\r
115\r
116 if (PmovAction&4)\r
117 {\r
118 Pico.m.scanline=0;\r
119\r
120 // Scan all the memory areas:\r
121 SCANP(ram) SCANP(vram) SCANP(zram) SCANP(cram) SCANP(vsram)\r
122\r
123 // Pack, scan and unpack the cpu data:\r
124 if((PmovAction&3)==1) PackCpu(cpu);\r
125 //SekInit(); // notaz: do we really have to do this here?\r
126 //PicoMemInit();\r
127 SCAN_VAR(cpu,"cpu")\r
128 if((PmovAction&3)==2) UnpackCpu(cpu);\r
129\r
130 SCAN_VAR(Pico.m ,"misc")\r
131 SCAN_VAR(Pico.video,"video")\r
132\r
133\r
134 if(ver == 0x0030) { // zram was being saved incorrectly in 0x0030 (byteswaped?)\r
135 Byteswap(Pico.zram, 0x2000);\r
136 return 0; // do not try to load sound stuff\r
137 }\r
138\r
139 //SCAN_VAR(Pico.s ,"sound")\r
140 // notaz: save/load z80, YM2612, sn76496 states instead of Pico.s (which is unused anyway)\r
141 if(PicoOpt&7) {\r
142 if((PmovAction&3)==1) z80_pack(cpu_z80);\r
143 ret = SCAN_VAR(cpu_z80,"cpu_z80")\r
144 // do not unpack if we fail to load z80 state\r
145 if((PmovAction&3)==2) {\r
146 if(ret) z80_reset();\r
147 else z80_unpack(cpu_z80);\r
148 }\r
149 }\r
150 if(PicoOpt&3)\r
151 ScanVar(sn76496_regs,28*4,"SN76496state", PmovFile, PmovAction); // regs and other stuff\r
152 if(PicoOpt&1) {\r
153 ScanVar(ym2612_regs, 0x200+4, "YM2612state", PmovFile, PmovAction); // regs + addr line\r
154 if((PmovAction&3)==2) YM2612PicoStateLoad(); // reload YM2612 state from it's regs\r
155 }\r
156 }\r
157\r
158 return 0;\r
159}\r
160\r
161// ---------------------------------------------------------------------------\r
162// Helper code to save/load to a file handle\r
163\r
164// Save or load the state from PmovFile:\r
165int PmovState(int PmovAction, void *PmovFile)\r
166{\r
167 int minimum=0;\r
168 unsigned char head[32];\r
169\r
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