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