Added 0.030 of PicoDrive and moved license files into root
[cyclone68000.git] / Pico / Pico.cpp
diff --git a/Pico/Pico.cpp b/Pico/Pico.cpp
new file mode 100644 (file)
index 0000000..7acc937
--- /dev/null
@@ -0,0 +1,215 @@
+\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