8c0c6d223a11affb11c32bfd00d09a7c6b7e29d3
[cyclone68000.git] / Pico / Area.cpp
1 \r
2 // This file is part of the PicoDrive Megadrive Emulator\r
3 \r
4 // This code is licensed under the GNU General Public License version 2.0 and the MAME License.\r
5 // You can choose the license that has the most advantages for you.\r
6 \r
7 // SVN repository can be found at http://code.google.com/p/cyclone68000/\r
8 \r
9 #include "PicoInt.h"\r
10 \r
11 int (*PicoAcb)(struct PicoArea *)=NULL; // Area callback for each block of memory\r
12 FILE *PmovFile=NULL;\r
13 int PmovAction=0;\r
14 \r
15 // Scan one variable and callback\r
16 static void ScanVar(void *data,int len,char *name)\r
17 {\r
18   struct PicoArea pa={NULL,0,NULL};\r
19   pa.data=data; pa.len=len; pa.name=name;\r
20   if (PicoAcb) PicoAcb(&pa);\r
21 }\r
22 \r
23 #define SCAN_VAR(x,y) ScanVar(&x,sizeof(x),y);\r
24 #define SCANP(x)      ScanVar(&Pico.x,sizeof(Pico.x),#x);\r
25 \r
26 // Pack the cpu into a common format:\r
27 static int PackCpu(unsigned char *cpu)\r
28 {\r
29   unsigned int pc=0;\r
30 \r
31 #ifdef EMU_A68K\r
32   memcpy(cpu,M68000_regs.d,0x40);\r
33   pc=M68000_regs.pc;\r
34   *(unsigned char *)(cpu+0x44)=(unsigned char)M68000_regs.ccr;\r
35   *(unsigned char *)(cpu+0x45)=(unsigned char)M68000_regs.srh;\r
36   *(unsigned int  *)(cpu+0x48)=M68000_regs.isp;\r
37 #endif\r
38 \r
39 #ifdef EMU_C68K\r
40   memcpy(cpu,PicoCpu.d,0x40);\r
41   pc=PicoCpu.pc-PicoCpu.membase;\r
42   *(unsigned char *)(cpu+0x44)=PicoCpu.ccr;\r
43   *(unsigned char *)(cpu+0x45)=PicoCpu.srh;\r
44   *(unsigned int  *)(cpu+0x48)=PicoCpu.osp;\r
45 #endif\r
46 \r
47   *(unsigned int *)(cpu+0x40)=pc;\r
48   return 0;\r
49 }\r
50 \r
51 static int UnpackCpu(unsigned char *cpu)\r
52 {\r
53   unsigned int pc=0;\r
54 \r
55   pc=*(unsigned int *)(cpu+0x40);\r
56 \r
57 #ifdef EMU_A68K\r
58   memcpy(M68000_regs.d,cpu,0x40);\r
59   M68000_regs.pc=pc;\r
60   M68000_regs.ccr=*(unsigned char *)(cpu+0x44);\r
61   M68000_regs.srh=*(unsigned char *)(cpu+0x45);\r
62   M68000_regs.isp=*(unsigned int  *)(cpu+0x48);\r
63 #endif\r
64 \r
65 #ifdef EMU_C68K\r
66   memcpy(PicoCpu.d,cpu,0x40);\r
67   PicoCpu.membase=0;\r
68   PicoCpu.pc =PicoCpu.checkpc(pc); // Base pc\r
69   PicoCpu.ccr=*(unsigned char *)(cpu+0x44);\r
70   PicoCpu.srh=*(unsigned char *)(cpu+0x45);\r
71   PicoCpu.osp=*(unsigned int  *)(cpu+0x48);\r
72 #endif\r
73   return 0;\r
74 }\r
75 \r
76 // Scan the contents of the virtual machine's memory for saving or loading\r
77 int PicoAreaScan(int action,int *pmin)\r
78 {\r
79   unsigned char cpu[0x60];\r
80 \r
81   memset(&cpu,0,sizeof(cpu));\r
82 \r
83   if (action&4)\r
84   {\r
85     // Scan all the memory areas:\r
86     SCANP(ram) SCANP(vram) SCANP(zram) SCANP(cram) SCANP(vsram)\r
87 \r
88     // Pack, scan and unpack the cpu data:\r
89     PackCpu(cpu);\r
90     SekInit();\r
91     PicoMemInit();\r
92     SCAN_VAR(cpu,"cpu")\r
93     UnpackCpu(cpu);\r
94 \r
95     SCAN_VAR(Pico.m    ,"misc")\r
96     SCAN_VAR(Pico.video,"video")\r
97     SCAN_VAR(Pico.s    ,"sound")\r
98 \r
99     Pico.m.scanline=0;\r
100     if (action&2)\r
101     {\r
102       memset(Pico.highpal,0,sizeof(Pico.highpal));\r
103       Pico.m.dirtyPal=1; // Recalculate palette\r
104     }\r
105   }\r
106 \r
107   if (pmin) *pmin=0x0021;\r
108 \r
109   return 0;\r
110 }\r
111 \r
112 // ---------------------------------------------------------------------------\r
113 // Helper code to save/load to a file handle\r
114 \r
115 // Area callback for each piece of Megadrive memory, read or write to the file:\r
116 static int StateAcb(struct PicoArea *pa)\r
117 {\r
118   if (PmovFile==NULL) return 1;\r
119 \r
120   if ((PmovAction&3)==1) fwrite(pa->data,1,pa->len,PmovFile);\r
121   if ((PmovAction&3)==2) fread (pa->data,1,pa->len,PmovFile);\r
122   return 0;\r
123 }\r
124 \r
125 // Save or load the state from PmovFile:\r
126 int PmovState()\r
127 {\r
128   int minimum=0;\r
129   unsigned char head[32];\r
130 \r
131   memset(head,0,sizeof(head));\r
132 \r
133   // Find out minial compatible version:\r
134   PicoAreaScan(PmovAction&0xc,&minimum);  \r
135 \r
136   memcpy(head,"Pico",4);\r
137   *(unsigned int *)(head+0x8)=PicoVer;\r
138   *(unsigned int *)(head+0xc)=minimum;\r
139 \r
140   // Scan header:\r
141   if (PmovAction&1) fwrite(head,1,sizeof(head),PmovFile);\r
142   if (PmovAction&2) fread (head,1,sizeof(head),PmovFile);\r
143 \r
144   // Scan memory areas:\r
145   PicoAcb=StateAcb;\r
146   PicoAreaScan(PmovAction,NULL);\r
147   PicoAcb=NULL;\r
148   return 0;\r
149 }\r
150 \r
151 int PmovUpdate()\r
152 {\r
153   int ret=0;\r
154   if (PmovFile==NULL) return 1;\r
155   \r
156   if ((PmovAction&3)==0) return 0;\r
157 \r
158   PicoPad[1]=0; // Make sure pad #2 is blank\r
159   if (PmovAction&1) ret=fwrite(PicoPad,1,2,PmovFile);\r
160   if (PmovAction&2) ret=fread (PicoPad,1,2,PmovFile);\r
161 \r
162   if (ret!=2)\r
163   {\r
164     // End of file\r
165     fclose(PmovFile); PmovFile=NULL;\r
166     PmovAction=0;\r
167   }\r
168 \r
169   return 0;\r
170 }\r