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