Added 0.030 of PicoDrive and moved license files into root
[cyclone68000.git] / Pico / Pico.cpp
1 \r
2 #include "PicoInt.h"\r
3 \r
4 int PicoVer=0x0030;\r
5 struct Pico Pico;\r
6 int PicoOpt=0;\r
7 \r
8 int PicoPad[2]; // Joypads, format is SACB RLDU\r
9 \r
10 int 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
30 void 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
39 int 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
89 static 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
103 static 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
150 static 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
184 int 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
203 static 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
215 int (*PicoCram)(int cram)=DefaultCram;\r