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