added copyright line to top of source files next to license information
[cyclone68000.git] / Pico / Pico.cpp
CommitLineData
15eb0001 1\r
4abeeb4b 2// This file is part of the PicoDrive Megadrive Emulator\r
3\r
c41b9b97 4// Copyright (c) 2011 FinalDave (emudave (at) gmail.com)\r
5\r
4abeeb4b 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
15eb0001 11#include "PicoInt.h"\r
12\r
13int PicoVer=0x0030;\r
14struct Pico Pico;\r
15int PicoOpt=0;\r
16\r
17int PicoPad[2]; // Joypads, format is SACB RLDU\r
18\r
19int PicoInit()\r
20{\r
21 // Blank space for state:\r
22 memset(&Pico,0,sizeof(Pico));\r
23 memset(&PicoPad,0,sizeof(PicoPad));\r
24 Pico.m.dirtyPal=1;\r
25\r
26 // Init CPU:\r
27 SekInit();\r
28\r
29 // Setup memory callbacks:\r
30 PicoMemInit();\r
31 PsndReset();\r
32\r
33#ifdef MSOUND\r
34 YM2612Init(1,7670443,PsndRate,NULL,NULL);\r
35#endif\r
36 return 0;\r
37}\r
38\r
39void PicoExit()\r
40{\r
41#ifdef MSOUND\r
42 YM2612Shutdown();\r
43#endif\r
44\r
45 memset(&Pico,0,sizeof(Pico));\r
46}\r
47\r
48int PicoReset()\r
49{\r
50 unsigned int region=0;\r
51 int support=0,hw=0,i=0;\r
52 unsigned char pal=0;\r
53\r
54 if (Pico.romsize<=0) return 1;\r
55\r
56 SekReset();\r
57 PsndReset();\r
58#ifdef MSOUND\r
59 YM2612ResetChip(0);\r
60#endif\r
61\r
62 // Read cartridge region data:\r
63 region=PicoRead32(0x1f0);\r
64\r
65 for (i=0;i<4;i++)\r
66 {\r
67 int c=0;\r
68 \r
69 c=region>>(i<<3); c&=0xff;\r
70 if (c<=' ') continue;\r
71\r
72 if (c=='J') support|=1;\r
73 else if (c=='U') support|=4;\r
74 else if (c=='E') support|=8;\r
75 else\r
76 {\r
77 // New style code:\r
78 char s[2]={0,0};\r
79 s[0]=(char)c;\r
80 support|=strtol(s,NULL,16);\r
81 }\r
82\r
83 }\r
84\r
85 // Try to pick the best hardware value for English/60hz:\r
86 if (support&4) hw=0x80; // USA\r
87 else if (support&8) { hw=0xc0; pal=1; } // Europe\r
88 else if (support&1) hw=0x00; // Japan NTSC\r
89 else if (support&2) { hw=0x40; pal=1; } // Japan PAL\r
90 else hw=0x80; // USA\r
91\r
92 Pico.m.hardware=(unsigned char)(hw|0x20); // No disk attached\r
93 Pico.m.pal=pal;\r
94\r
95 return 0;\r
96}\r
97\r
98static int CheckIdle()\r
99{\r
100 unsigned char state[0x88];\r
101\r
102 memset(state,0,sizeof(state));\r
103\r
104 // See if the state is the same after 2 steps:\r
105 SekState(state); SekRun(0); SekRun(0); SekState(state+0x44);\r
106 if (memcmp(state,state+0x44,0x44)==0) return 1;\r
107\r
108 return 0;\r
109}\r
110\r
111// Accurate but slower frame which does hints\r
112static int PicoFrameHints()\r
113{\r
114 struct PicoVideo *pv=&Pico.video;\r
115 int total=0,aim=0;\r
116 int y=0;\r
117 int hint=0x400; // Hint counter\r
118\r
119 pv->status|=0x08; // Go into vblank\r
120\r
121 for (y=-38;y<224;y++)\r
122 {\r
123 if (y==0)\r
124 {\r
125 hint=pv->reg[10]; // Load H-Int counter\r
126 if (pv->reg[1]&0x40) pv->status&=~8; // Come out of vblank if display enabled\r
127 }\r
128\r
129 // H-Interrupts:\r
130 if (hint<0)\r
131 {\r
132 hint=pv->reg[10]; // Reload H-Int counter\r
133 if (pv->reg[0]&0x10) SekInterrupt(4);\r
134 }\r
135\r
136 // V-Interrupt:\r
137 if (y==-37)\r
138 {\r
139 pv->status|=0x80; // V-Int happened\r
140 if (pv->reg[1]&0x20) SekInterrupt(6);\r
141 }\r
142\r
143 Pico.m.scanline=(short)y;\r
144\r
145 // Run scanline:\r
146 aim+=489; total+=SekRun(aim-total);\r
147\r
148 hint--;\r
149\r
150 if (PicoScan && y>=0) PicoLine(y);\r
151 }\r
152\r
153 SekInterrupt(0); // Cancel interrupt\r
154\r
155 return 0;\r
156}\r
157\r
158// Simple frame without H-Ints\r
159static int PicoFrameSimple()\r
160{\r
161 int total=0,y=0,aim=0;\r
162 \r
163 Pico.m.scanline=-64;\r
164\r
165 // V-Blanking period:\r
166 if (Pico.video.reg[1]&0x20) SekInterrupt(6); // Set IRQ\r
167 Pico.video.status|=0x88; // V-Int happened / go into vblank\r
168 total+=SekRun(18560);\r
169\r
170 // Active Scan:\r
171 if (Pico.video.reg[1]&0x40) Pico.video.status&=~8; // Come out of vblank if display is enabled\r
172 SekInterrupt(0); // Clear IRQ\r
173\r
174 // Run in sections:\r
175 for (aim=18560+6839; aim<=18560+6839*16; aim+=6839)\r
176 {\r
177 int add=0;\r
178 if (CheckIdle()) break;\r
179 add=SekRun(aim-total);\r
180 total+=add;\r
181 }\r
182\r
183 if (PicoMask&0x100)\r
184 if (PicoScan)\r
185 {\r
186 // Draw the screen\r
187 for (y=0;y<224;y++) PicoLine(y);\r
188 }\r
189\r
190 return 0;\r
191}\r
192\r
193int PicoFrame()\r
194{\r
195 int hints=0;\r
196\r
197 if (Pico.rom==NULL) return 1; // No Rom plugged in\r
198\r
199\r
200 PmovUpdate();\r
201\r
202 hints=Pico.video.reg[0]&0x10;\r
203\r
204 if (hints) PicoFrameHints();\r
205 else PicoFrameSimple();\r
206\r
207 PsndRender();\r
208\r
209 return 0;\r
210}\r
211\r
212static int DefaultCram(int cram)\r
213{\r
214 int high=0x0841;\r
215 // Convert 0000bbbb ggggrrrr\r
216 // to rrrr1ggg g10bbbb1\r
217 high|=(cram&0x00f)<<12; // Red\r
218 high|=(cram&0x0f0)<< 3; // Green\r
219 high|=(cram&0xf00)>> 7; // Blue\r
220 return high;\r
221}\r
222\r
223// Function to convert Megadrive Cram into a native colour:\r
224int (*PicoCram)(int cram)=DefaultCram;\r