92f72cc8bfdf41d68c5c3ad9436f9154e3086714
[cyclone68000.git] / Pico / Memory.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 typedef unsigned char  u8;\r
12 typedef unsigned short u16;\r
13 typedef unsigned int   u32;\r
14 \r
15 static int PicoMemBase(u32 pc)\r
16 {\r
17   int membase=0;\r
18 \r
19   if (pc<Pico.romsize)\r
20   {\r
21     membase=(int)Pico.rom; // Program Counter in Rom\r
22   }\r
23   else if ((pc&0xe00000)==0xe00000)\r
24   {\r
25     membase=(int)Pico.ram-(pc&0xff0000); // Program Counter in Ram\r
26   }\r
27   else\r
28   {\r
29     // Error - Program Counter is invalid\r
30     membase=(int)Pico.rom;\r
31   }\r
32 \r
33   return membase;\r
34 }\r
35 \r
36 #ifdef EMU_A68K\r
37 extern "C" u8 *OP_ROM=NULL,*OP_RAM=NULL;\r
38 \r
39 static void CPU_CALL PicoCheckPc(u32 pc)\r
40 {\r
41   OP_ROM=(u8 *)PicoMemBase(pc);\r
42 \r
43   // don't bother calling us back unless it's outside the 64k segment\r
44   M68000_regs.AsmBank=(pc>>16);\r
45 }\r
46 #endif\r
47 \r
48 #ifdef EMU_C68K\r
49 static u32 PicoCheckPc(u32 pc)\r
50 {\r
51   pc-=PicoCpu.membase; // Get real pc\r
52   pc&=0xffffff;\r
53 \r
54   PicoCpu.membase=PicoMemBase(pc);\r
55 \r
56   return PicoCpu.membase+pc;\r
57 }\r
58 #endif\r
59 \r
60 #ifdef EMU_NULL\r
61 static u32 PicoCheckPc(u32) { return 0; }\r
62 #endif\r
63 \r
64 \r
65 int PicoInitPc(u32 pc)\r
66 {\r
67   PicoCheckPc(pc);\r
68   return 0;\r
69 }\r
70 \r
71 // -----------------------------------------------------------------\r
72 static int PadRead(int i)\r
73 {\r
74   int pad=0,value=0;\r
75   pad=~PicoPad[i]; // Get inverse of pad\r
76 \r
77   if (Pico.m.padSelect[i]) value=0x40|(pad&0x3f); // 01CB RLDU\r
78   else value=((pad&0xc0)>>2)|(pad&3); // 00SA 00DU\r
79 \r
80   return (value<<8)|value; // Mirror bytes\r
81 }\r
82 \r
83 static u32 OtherRead16(u32 a)\r
84 {\r
85   u32 d=0;\r
86 \r
87   if ((a&0xffe000)==0xa00000)\r
88   {\r
89     // Z80 ram\r
90     d=*(u16 *)(Pico.zram+(a&0x1fff));\r
91 \r
92     if (Pico.m.rotate&2) { d=(Pico.m.rotate>>2)&0xff; d|=d<<8; } // Fake z80\r
93     Pico.m.rotate++;\r
94 \r
95     goto end;\r
96   }\r
97 \r
98   if ((a&0xffe000)==0xa00000)\r
99   {\r
100     // Fake Z80 ram\r
101     d=((Pico.m.rotate++)>>2)&0xff; d|=d<<8;\r
102     goto end;\r
103   }\r
104   \r
105   if (a==0xa04000) { d=Pico.m.rotate&3; Pico.m.rotate++; goto end; } // Fudge\r
106   if (a==0xa10000) { d=Pico.m.hardware; goto end; }  // Hardware value\r
107   if (a==0xa10002) { d=PadRead(0); goto end; }\r
108   if (a==0xa10004) { d=PadRead(1); goto end; }\r
109   if (a==0xa11100) { d=((Pico.m.rotate++)&4)<<6; goto end; } // Fudge z80 reset\r
110 \r
111   if ((a&0xffffe0)==0xc00000) { d=PicoVideoRead(a); goto end; }\r
112 \r
113 end:\r
114   return d;\r
115 }\r
116 \r
117 static void OtherWrite8(u32 a,u32 d)\r
118 {\r
119   if ((a&0xffe000)==0xa00000) { Pico.zram[(a^1)&0x1fff]=(u8)d; return; } // Z80 ram\r
120   if ((a&0xfffffc)==0xa04000) { PsndFm(a,d); return; } // FM Sound\r
121 \r
122   if (a==0xa11100) { Pico.m.z80Run=(u8)(d^1); return; }\r
123   if (a==0xa10003) { Pico.m.padSelect[0]=(u8)((d>>6)&1); return; } // Joypad 1 select\r
124   if (a==0xa10005) { Pico.m.padSelect[1]=(u8)((d>>6)&1); return; } // Joypad 2 select\r
125 \r
126   if ((a&0xffffe0)==0xc00000) { PicoVideoWrite(a,d|(d<<8)); return; } // Byte access gets mirrored\r
127 }\r
128 \r
129 static void OtherWrite16(u32 a,u32 d)\r
130 {\r
131   if ((a&0xffffe0)==0xc00000) { PicoVideoWrite(a,d); return; }\r
132   if ((a&0xffe000)==0xa00000) { *(u16 *)(Pico.zram+(a&0x1ffe))=(u16)d; return; } // Z80 ram\r
133 \r
134   OtherWrite8(a,  d>>8);\r
135   OtherWrite8(a+1,d&0xff);\r
136 }\r
137 \r
138 // -----------------------------------------------------------------\r
139 //                     Read Rom and read Ram\r
140 \r
141 static u8 CPU_CALL PicoRead8(u32 a)\r
142 {\r
143   u32 d=0;\r
144   a&=0xffffff;\r
145 \r
146   if (a<Pico.romsize) return *(u8 *)(Pico.rom+(a^1)); // Rom\r
147   if ((a&0xe00000)==0xe00000) return *(u8 *)(Pico.ram+((a^1)&0xffff)); // Ram\r
148 \r
149   d=OtherRead16(a&~1); if ((a&1)==0) d>>=8;\r
150   return (u8)d;\r
151 }\r
152 \r
153 u16 CPU_CALL PicoRead16(u32 a)\r
154 {\r
155   a&=0xfffffe;\r
156 \r
157   if (a<Pico.romsize) { u16 *pm=(u16 *)(Pico.rom+a); return pm[0]; } // Rom\r
158   if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xffff)); return pm[0]; } // Ram\r
159 \r
160   return (u16)OtherRead16(a);\r
161 }\r
162 \r
163 u32 CPU_CALL PicoRead32(u32 a)\r
164 {\r
165   a&=0xfffffe;\r
166 \r
167   if (a<Pico.romsize) { u16 *pm=(u16 *)(Pico.rom+a); return (pm[0]<<16)|pm[1]; } // Rom\r
168   if ((a&0xe00000)==0xe00000) { u16 *pm=(u16 *)(Pico.ram+(a&0xffff)); return (pm[0]<<16)|pm[1]; } // Ram\r
169 \r
170   return (OtherRead16(a)<<16)|OtherRead16(a+2);\r
171 }\r
172 \r
173 // -----------------------------------------------------------------\r
174 //                            Write Ram\r
175 \r
176 static void CPU_CALL PicoWrite8(u32 a,u8 d)\r
177 {\r
178   if ((a&0xe00000)==0xe00000) { u8 *pm=(u8 *)(Pico.ram+((a^1)&0xffff)); pm[0]=d; return; } // Ram\r
179 \r
180   a&=0xffffff;\r
181   OtherWrite8(a,d);\r
182 }\r
183 \r
184 static void CPU_CALL PicoWrite16(u32 a,u16 d)\r
185 {\r
186   if ((a&0xe00000)==0xe00000) { *(u16 *)(Pico.ram+(a&0xfffe))=d; return; } // Ram\r
187 \r
188   a&=0xfffffe;\r
189   OtherWrite16(a,d);\r
190 }\r
191 \r
192 static void CPU_CALL PicoWrite32(u32 a,u32 d)\r
193 {\r
194   if ((a&0xe00000)==0xe00000)\r
195   {\r
196     // Ram:\r
197     u16 *pm=(u16 *)(Pico.ram+(a&0xfffe));\r
198     pm[0]=(u16)(d>>16); pm[1]=(u16)d;\r
199     return;\r
200   }\r
201 \r
202   a&=0xfffffe;\r
203   OtherWrite16(a,  (u16)(d>>16));\r
204   OtherWrite16(a+2,(u16)d);\r
205 }\r
206 \r
207 \r
208 // -----------------------------------------------------------------\r
209 int PicoMemInit()\r
210 {\r
211 #ifdef EMU_C68K\r
212   // Setup memory callbacks:\r
213   PicoCpu.checkpc=PicoCheckPc;\r
214   PicoCpu.fetch8 =PicoCpu.read8 =PicoRead8;\r
215   PicoCpu.fetch16=PicoCpu.read16=PicoRead16;\r
216   PicoCpu.fetch32=PicoCpu.read32=PicoRead32;\r
217   PicoCpu.write8 =PicoWrite8;\r
218   PicoCpu.write16=PicoWrite16;\r
219   PicoCpu.write32=PicoWrite32;\r
220 #endif\r
221   return 0;\r
222 }\r
223 \r
224 #ifdef EMU_A68K\r
225 struct A68KInter\r
226 {\r
227   u32 unknown;\r
228   u8  (__fastcall *Read8) (u32 a);\r
229   u16 (__fastcall *Read16)(u32 a);\r
230   u32 (__fastcall *Read32)(u32 a);\r
231   void (__fastcall *Write8)  (u32 a,u8 d);\r
232   void (__fastcall *Write16) (u32 a,u16 d);\r
233   void (__fastcall *Write32) (u32 a,u32 d);\r
234   void (__fastcall *ChangePc)(u32 a);\r
235   u8  (__fastcall *PcRel8) (u32 a);\r
236   u16 (__fastcall *PcRel16)(u32 a);\r
237   u32 (__fastcall *PcRel32)(u32 a);\r
238   u16 (__fastcall *Dir16)(u32 a);\r
239   u32 (__fastcall *Dir32)(u32 a);\r
240 };\r
241 \r
242 extern "C" struct A68KInter a68k_memory_intf=\r
243 {\r
244   0,\r
245   PicoRead8,\r
246   PicoRead16,\r
247   PicoRead32,\r
248   PicoWrite8,\r
249   PicoWrite16,\r
250   PicoWrite32,\r
251   PicoCheckPc,\r
252   PicoRead8,\r
253   PicoRead16,\r
254   PicoRead32,\r
255   PicoRead16, // unused\r
256   PicoRead32, // unused\r
257 };\r
258 #endif\r