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