--- /dev/null
+\r
+#include "PicoInt.h"\r
+\r
+int PicoVer=0x0030;\r
+struct Pico Pico;\r
+int PicoOpt=0;\r
+\r
+int PicoPad[2]; // Joypads, format is SACB RLDU\r
+\r
+int PicoInit()\r
+{\r
+ // Blank space for state:\r
+ memset(&Pico,0,sizeof(Pico));\r
+ memset(&PicoPad,0,sizeof(PicoPad));\r
+ Pico.m.dirtyPal=1;\r
+\r
+ // Init CPU:\r
+ SekInit();\r
+\r
+ // Setup memory callbacks:\r
+ PicoMemInit();\r
+ PsndReset();\r
+\r
+#ifdef MSOUND\r
+ YM2612Init(1,7670443,PsndRate,NULL,NULL);\r
+#endif\r
+ return 0;\r
+}\r
+\r
+void PicoExit()\r
+{\r
+#ifdef MSOUND\r
+ YM2612Shutdown();\r
+#endif\r
+\r
+ memset(&Pico,0,sizeof(Pico));\r
+}\r
+\r
+int PicoReset()\r
+{\r
+ unsigned int region=0;\r
+ int support=0,hw=0,i=0;\r
+ unsigned char pal=0;\r
+\r
+ if (Pico.romsize<=0) return 1;\r
+\r
+ SekReset();\r
+ PsndReset();\r
+#ifdef MSOUND\r
+ YM2612ResetChip(0);\r
+#endif\r
+\r
+ // Read cartridge region data:\r
+ region=PicoRead32(0x1f0);\r
+\r
+ for (i=0;i<4;i++)\r
+ {\r
+ int c=0;\r
+ \r
+ c=region>>(i<<3); c&=0xff;\r
+ if (c<=' ') continue;\r
+\r
+ if (c=='J') support|=1;\r
+ else if (c=='U') support|=4;\r
+ else if (c=='E') support|=8;\r
+ else\r
+ {\r
+ // New style code:\r
+ char s[2]={0,0};\r
+ s[0]=(char)c;\r
+ support|=strtol(s,NULL,16);\r
+ }\r
+\r
+ }\r
+\r
+ // Try to pick the best hardware value for English/60hz:\r
+ if (support&4) hw=0x80; // USA\r
+ else if (support&8) { hw=0xc0; pal=1; } // Europe\r
+ else if (support&1) hw=0x00; // Japan NTSC\r
+ else if (support&2) { hw=0x40; pal=1; } // Japan PAL\r
+ else hw=0x80; // USA\r
+\r
+ Pico.m.hardware=(unsigned char)(hw|0x20); // No disk attached\r
+ Pico.m.pal=pal;\r
+\r
+ return 0;\r
+}\r
+\r
+static int CheckIdle()\r
+{\r
+ unsigned char state[0x88];\r
+\r
+ memset(state,0,sizeof(state));\r
+\r
+ // See if the state is the same after 2 steps:\r
+ SekState(state); SekRun(0); SekRun(0); SekState(state+0x44);\r
+ if (memcmp(state,state+0x44,0x44)==0) return 1;\r
+\r
+ return 0;\r
+}\r
+\r
+// Accurate but slower frame which does hints\r
+static int PicoFrameHints()\r
+{\r
+ struct PicoVideo *pv=&Pico.video;\r
+ int total=0,aim=0;\r
+ int y=0;\r
+ int hint=0x400; // Hint counter\r
+\r
+ pv->status|=0x08; // Go into vblank\r
+\r
+ for (y=-38;y<224;y++)\r
+ {\r
+ if (y==0)\r
+ {\r
+ hint=pv->reg[10]; // Load H-Int counter\r
+ if (pv->reg[1]&0x40) pv->status&=~8; // Come out of vblank if display enabled\r
+ }\r
+\r
+ // H-Interrupts:\r
+ if (hint<0)\r
+ {\r
+ hint=pv->reg[10]; // Reload H-Int counter\r
+ if (pv->reg[0]&0x10) SekInterrupt(4);\r
+ }\r
+\r
+ // V-Interrupt:\r
+ if (y==-37)\r
+ {\r
+ pv->status|=0x80; // V-Int happened\r
+ if (pv->reg[1]&0x20) SekInterrupt(6);\r
+ }\r
+\r
+ Pico.m.scanline=(short)y;\r
+\r
+ // Run scanline:\r
+ aim+=489; total+=SekRun(aim-total);\r
+\r
+ hint--;\r
+\r
+ if (PicoScan && y>=0) PicoLine(y);\r
+ }\r
+\r
+ SekInterrupt(0); // Cancel interrupt\r
+\r
+ return 0;\r
+}\r
+\r
+// Simple frame without H-Ints\r
+static int PicoFrameSimple()\r
+{\r
+ int total=0,y=0,aim=0;\r
+ \r
+ Pico.m.scanline=-64;\r
+\r
+ // V-Blanking period:\r
+ if (Pico.video.reg[1]&0x20) SekInterrupt(6); // Set IRQ\r
+ Pico.video.status|=0x88; // V-Int happened / go into vblank\r
+ total+=SekRun(18560);\r
+\r
+ // Active Scan:\r
+ if (Pico.video.reg[1]&0x40) Pico.video.status&=~8; // Come out of vblank if display is enabled\r
+ SekInterrupt(0); // Clear IRQ\r
+\r
+ // Run in sections:\r
+ for (aim=18560+6839; aim<=18560+6839*16; aim+=6839)\r
+ {\r
+ int add=0;\r
+ if (CheckIdle()) break;\r
+ add=SekRun(aim-total);\r
+ total+=add;\r
+ }\r
+\r
+ if (PicoMask&0x100)\r
+ if (PicoScan)\r
+ {\r
+ // Draw the screen\r
+ for (y=0;y<224;y++) PicoLine(y);\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+int PicoFrame()\r
+{\r
+ int hints=0;\r
+\r
+ if (Pico.rom==NULL) return 1; // No Rom plugged in\r
+\r
+\r
+ PmovUpdate();\r
+\r
+ hints=Pico.video.reg[0]&0x10;\r
+\r
+ if (hints) PicoFrameHints();\r
+ else PicoFrameSimple();\r
+\r
+ PsndRender();\r
+\r
+ return 0;\r
+}\r
+\r
+static int DefaultCram(int cram)\r
+{\r
+ int high=0x0841;\r
+ // Convert 0000bbbb ggggrrrr\r
+ // to rrrr1ggg g10bbbb1\r
+ high|=(cram&0x00f)<<12; // Red\r
+ high|=(cram&0x0f0)<< 3; // Green\r
+ high|=(cram&0xf00)>> 7; // Blue\r
+ return high;\r
+}\r
+\r
+// Function to convert Megadrive Cram into a native colour:\r
+int (*PicoCram)(int cram)=DefaultCram;\r