32x: packed pixel mode (works over 68k)
authornotaz <notasas@gmail.com>
Sat, 12 Sep 2009 21:54:46 +0000 (21:54 +0000)
committernotaz <notasas@gmail.com>
Sat, 12 Sep 2009 21:54:46 +0000 (21:54 +0000)
git-svn-id: file:///home/notaz/opt/svn/PicoDrive@773 be3aeb3a-fb24-0410-a615-afba39da0efa

15 files changed:
pico/32x/32x.c
pico/32x/draw.c [new file with mode: 0644]
pico/32x/memory.c
pico/draw.c
pico/memory.c
pico/pico.c
pico/pico.h
pico/pico_cmn.c
pico/pico_int.h
platform/common/emu.c
platform/common/menu.c
platform/common/plat.h
platform/gp2x/Makefile
platform/gp2x/emu.c
platform/linux/Makefile

index dc881a9..7a122cb 100644 (file)
@@ -1,4 +1,5 @@
 #include "../pico_int.h"
+#include "../sound/ym2612.h"
 
 struct Pico32x Pico32x;
 
@@ -9,23 +10,68 @@ void Pico32xStartup(void)
   PicoAHW |= PAHW_32X;
   PicoMemSetup32x();
 
-  // probably should only done on power
-//  memset(&Pico32x, 0, sizeof(Pico32x));
-
   if (!Pico.m.pal)
-    Pico32x.vdp_regs[0] |= 0x8000;
+    Pico32x.vdp_regs[0] |= P32XV_nPAL;
 
-  // prefill checksum
-  Pico32x.regs[0x28/2] = *(unsigned short *)(Pico.rom + 0x18e);
+  emu_32x_startup();
 }
 
 void Pico32xInit(void)
 {
-  // XXX: mv
-  Pico32x.regs[0] = 0x0082;
+}
+
+void PicoPower32x(void)
+{
+  memset(&Pico32x, 0, sizeof(Pico32x));
+  Pico32x.regs[0] = 0x0082; // SH2 reset?
+  Pico32x.vdp_regs[0x0a/2] = P32XV_VBLK|P32XV_HBLK|P32XV_PEN;
 }
 
 void PicoReset32x(void)
 {
 }
 
+static void p32x_start_blank(void)
+{
+  // enter vblank
+  Pico32x.vdp_regs[0x0a/2] |= P32XV_VBLK|P32XV_PEN;
+
+  // swap waits until vblank
+  if ((Pico32x.vdp_regs[0x0a/2] ^ Pico32x.pending_fb) & P32XV_FS) {
+    Pico32x.vdp_regs[0x0a/2] &= ~P32XV_FS;
+    Pico32x.vdp_regs[0x0a/2] |= Pico32x.pending_fb;
+    Pico32xSwapDRAM(Pico32x.pending_fb ^ 1);
+  }
+}
+
+// FIXME..
+static __inline void SekRunM68k(int cyc)
+{
+  int cyc_do;
+  SekCycleAim+=cyc;
+  if ((cyc_do=SekCycleAim-SekCycleCnt) <= 0) return;
+#if defined(EMU_CORE_DEBUG)
+  // this means we do run-compare
+  SekCycleCnt+=CM_compareRun(cyc_do, 0);
+#elif defined(EMU_C68K)
+  PicoCpuCM68k.cycles=cyc_do;
+  CycloneRun(&PicoCpuCM68k);
+  SekCycleCnt+=cyc_do-PicoCpuCM68k.cycles;
+#elif defined(EMU_M68K)
+  SekCycleCnt+=m68k_execute(cyc_do);
+#elif defined(EMU_F68K)
+  SekCycleCnt+=fm68k_emulate(cyc_do+1, 0, 0);
+#endif
+}
+
+#define PICO_32X
+#include "../pico_cmn.c"
+
+void PicoFrame32x(void)
+{
+  if ((Pico32x.vdp_regs[0] & 3 ) != 0) // no forced blanking
+    Pico32x.vdp_regs[0x0a/2] &= ~(P32XV_VBLK|P32XV_PEN); // get out of vblank
+
+  PicoFrameStart();
+  PicoFrameHints();
+}
diff --git a/pico/32x/draw.c b/pico/32x/draw.c
new file mode 100644 (file)
index 0000000..794e2d4
--- /dev/null
@@ -0,0 +1,58 @@
+#include "../pico_int.h"
+
+static void convert_pal555(void)
+{
+  unsigned int *ps = (void *)Pico32xMem->pal;
+  unsigned int *pd = (void *)Pico32xMem->pal_native;
+  unsigned int m1 = 0x001f001f;
+  unsigned int m2 = 0x03e003e0;
+  unsigned int m3 = 0xfc00fc00;
+  int i;
+
+  // place prio to LS green bit
+  for (i = 0x100/2; i > 0; i--, ps++, pd++) {
+    unsigned int t = *ps;
+    *pd = ((t & m1) << 11) | ((t & m2) << 1) | ((t & m3) >> 10);
+  }
+
+  Pico32x.dirty_pal = 0;
+}
+
+void FinalizeLine32xRGB555(int sh, int line)
+{
+  unsigned short *pd = DrawLineDest;
+  unsigned short *pal = Pico32xMem->pal_native;
+  unsigned char *pb = HighCol + 8;
+  unsigned short cram0;
+
+  // this is a bit hackish:
+  // we swap cram color 0 with color that is used for background,
+  // as bg is forced to 0 when we do 32X
+  cram0 = Pico.cram[0];
+  Pico.cram[0] = Pico.cram[Pico.video.reg[7] & 0x3f];
+
+  FinalizeLineRGB555(sh, line);
+  Pico.cram[0] = cram0;
+
+  if ((Pico32x.vdp_regs[0] & 3) == 0)
+    return; // blanking
+
+  if (Pico32x.dirty_pal)
+    convert_pal555();
+
+  if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 1) {
+    unsigned short *dram = (void *)Pico32xMem->dram[Pico32x.vdp_regs[0x0a/2] & P32XV_FS];
+    unsigned short *ps = dram + dram[line];
+    unsigned short t;
+    int i;
+    for (i = 320/2; i > 0; i--, ps++, pd += 2, pb += 2) {
+      t = pal[*ps >> 8];
+      if (pb[0] == 0 || (t & 0x20))
+        pd[0] = t;
+      t = pal[*ps & 0xff];
+      if (pb[1] == 0 || (t & 0x20))
+        pd[1] = t;
+    }
+  }
+}
+
index 324c789..f1a109e 100644 (file)
@@ -3,18 +3,33 @@
 
 static const char str_mars[] = "MARS";
 
-struct Pico32xMem {
-  u8 sdram[0x40000];
-  u8 dram[0x40000]; // AKA fb
-  u8 m68k_rom[M68K_BANK_SIZE]; // 0x100
+struct Pico32xMem *Pico32xMem;
+
+// SH2 faking
+static const u16 comm_fakevals[] = {
+  0x4d5f, 0x4f4b, // M_OK
+  0x535f, 0x4f4b, // S_OK
+  0x0002, // Mortal Kombat
+  0, // pad
 };
 
-static struct Pico32xMem *Pico32xMem;
-
 static u32 p32x_reg_read16(u32 a)
 {
   a &= 0x3e;
 
+  // SH2 faker
+  if ((a & 0x30) == 0x20)
+  {
+    static int f = 0, csum_faked = 0;
+    if (a == 0x28 && !csum_faked) {
+      csum_faked = 1;
+      return *(unsigned short *)(Pico.rom + 0x18e);
+    }
+    if (f >= sizeof(comm_fakevals) / sizeof(comm_fakevals[0]))
+      f = 0;
+    return comm_fakevals[f++];
+  }
+
   return Pico32x.regs[a / 2];
 }
 
@@ -48,36 +63,39 @@ static u32 p32x_vdp_read16(u32 a)
   return Pico32x.vdp_regs[a / 2];
 }
 
-static void p32x_vdp_write16(u32 a, u32 d)
-{
-  a &= 0x0e;
-
-  switch (a) {
-    case 0x0a:
-      Pico32x.pending_fb = d & 1;
-      if (Pico.video.status & 8) {
-        Pico32x.vdp_regs[0x0a/2] &= ~1;
-        Pico32x.vdp_regs[0x0a/2] |= d & 1;
-      }
-      break;
-  }
-}
-
 static void p32x_vdp_write8(u32 a, u32 d)
 {
+  u16 *r = Pico32x.vdp_regs;
   a &= 0x0f;
 
+  // TODO: verify what's writeable
   switch (a) {
+    case 0x01:
+      if (((r[0] & 3) == 0) != ((d & 3) == 0)) { // forced blanking changed
+        if (Pico.video.status & 8)
+          r[0x0a/2] |=  P32XV_VBLK;
+        else
+          r[0x0a/2] &= ~P32XV_VBLK;
+      }
+      r[0] = (r[0] & P32XV_nPAL) | (d & 0xff);
+      break;
     case 0x0b:
-      Pico32x.pending_fb = d & 1;
-      if (Pico.video.status & 8) {
-        Pico32x.vdp_regs[0x0a/2] &= ~1;
-        Pico32x.vdp_regs[0x0a/2] |= d & 1;
+      d &= 1;
+      Pico32x.pending_fb = d;
+      // if we are blanking and FS bit is changing
+      if ((r[0x0a/2] & P32XV_VBLK) && ((r[0x0a/2] ^ d) & P32XV_FS)) {
+        r[0x0a/2] ^= 1;
+       Pico32xSwapDRAM(d ^ 1);
       }
       break;
   }
 }
 
+static void p32x_vdp_write16(u32 a, u32 d)
+{
+  p32x_vdp_write8(a | 1, d);
+}
+
 // default 32x handlers
 u32 PicoRead8_32x(u32 a)
 {
@@ -87,11 +105,20 @@ u32 PicoRead8_32x(u32 a)
     goto out_16to8;
   }
 
-  if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) {
+  if (!(Pico32x.regs[0] & 1))
+    goto no_vdp;
+
+  if ((a & 0xfff0) == 0x5180) { // a15180
     d = p32x_vdp_read16(a);
     goto out_16to8;
   }
 
+  if ((a & 0xfe00) == 0x5200) { // a15200
+    d = Pico32xMem->pal[(a & 0x1ff) / 2];
+    goto out_16to8;
+  }
+
+no_vdp:
   if ((a & 0xfffc) == 0x30ec) { // a130ec
     d = str_mars[a & 3];
     goto out;
@@ -119,11 +146,20 @@ u32 PicoRead16_32x(u32 a)
     goto out;
   }
 
-  if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
+  if (!(Pico32x.regs[0] & 1))
+    goto no_vdp;
+
+  if ((a & 0xfff0) == 0x5180) { // a15180
     d = p32x_vdp_read16(a);
     goto out;
   }
 
+  if ((a & 0xfe00) == 0x5200) { // a15200
+    d = Pico32xMem->pal[(a & 0x1ff) / 2];
+    goto out;
+  }
+
+no_vdp:
   if ((a & 0xfffc) == 0x30ec) { // a130ec
     d = !(a & 2) ? ('M'<<8)|'A' : ('R'<<8)|'S';
     goto out;
@@ -147,11 +183,23 @@ void PicoWrite8_32x(u32 a, u32 d)
     return;
   }
 
-  if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
+  if (!(Pico32x.regs[0] & 1))
+    goto no_vdp;
+
+  if ((a & 0xfff0) == 0x5180) { // a15180
     p32x_vdp_write8(a, d);
     return;
   }
 
+  // TODO: verify
+  if ((a & 0xfe00) == 0x5200) { // a15200
+    elprintf(EL_32X|EL_ANOMALY, "m68k 32x PAL w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
+    ((u8 *)Pico32xMem->pal)[(a & 0x1ff) ^ 1] = d;
+    Pico32x.dirty_pal = 1;
+    return;
+  }
+
+no_vdp:
   elprintf(EL_UIO, "m68k unmapped w8  [%06x]   %02x @%06x", a, d & 0xff, SekPc);
 }
 
@@ -165,11 +213,21 @@ void PicoWrite16_32x(u32 a, u32 d)
     return;
   }
 
-  if ((a & 0xfff0) == 0x5180 && (Pico32x.regs[0] & 1)) { // a15180
+  if (!(Pico32x.regs[0] & 1))
+    goto no_vdp;
+
+  if ((a & 0xfff0) == 0x5180) { // a15180
     p32x_vdp_write16(a, d);
     return;
   }
 
+  if ((a & 0xfe00) == 0x5200) { // a15200
+    Pico32xMem->pal[(a & 0x1ff) / 2] = d;
+    Pico32x.dirty_pal = 1;
+    return;
+  }
+
+no_vdp:
   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
 }
 
@@ -194,6 +252,14 @@ static void PicoWrite16_hint(u32 a, u32 d)
   elprintf(EL_UIO, "m68k unmapped w16 [%06x] %04x @%06x", a, d & 0xffff, SekPc);
 }
 
+void Pico32xSwapDRAM(int b)
+{
+  cpu68k_map_set(m68k_read8_map,   0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
+  cpu68k_map_set(m68k_read16_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
+  cpu68k_map_set(m68k_write8_map,  0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
+  cpu68k_map_set(m68k_write16_map, 0x840000, 0x85ffff, Pico32xMem->dram[b], 0);
+}
+
 #define HWSWAP(x) (((x) << 16) | ((x) >> 16))
 void PicoMemSetup32x(void)
 {
@@ -212,7 +278,7 @@ void PicoMemSetup32x(void)
   ps = (unsigned short *)Pico32xMem->m68k_rom;
   pl = (unsigned int *)Pico32xMem->m68k_rom;
   for (i = 1; i < 0xc0/4; i++)
-    pl[i] = HWSWAP(0x880200 + i * 6);
+    pl[i] = HWSWAP(0x880200 + (i - 1) * 6);
 
   // fill with nops
   for (i = 0xc0/2; i < 0x100/2; i++)
@@ -223,7 +289,7 @@ void PicoMemSetup32x(void)
   ps[0xfe/2] = 0x60fe; // jump to self
 
   // fill remaining mem with ROM
-  memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, M68K_BANK_SIZE - 0x100);
+  memcpy(Pico32xMem->m68k_rom + 0x100, Pico.rom + 0x100, sizeof(Pico32xMem->m68k_rom) - 0x100);
 
   // cartridge area becomes unmapped
   // XXX: we take the easy way and don't unmap ROM,
@@ -231,10 +297,14 @@ void PicoMemSetup32x(void)
   // m68k_map_unmap(0x000000, 0x3fffff);
 
   // MD ROM area
-  cpu68k_map_set(m68k_read8_map,   0x000000, M68K_BANK_SIZE - 1, Pico32xMem->m68k_rom, 0);
-  cpu68k_map_set(m68k_read16_map,  0x000000, M68K_BANK_SIZE - 1, Pico32xMem->m68k_rom, 0);
-  cpu68k_map_set(m68k_write8_map,  0x000000, M68K_BANK_SIZE - 1, PicoWrite8_hint, 1); // TODO verify
-  cpu68k_map_set(m68k_write16_map, 0x000000, M68K_BANK_SIZE - 1, PicoWrite16_hint, 1);
+  rs = sizeof(Pico32xMem->m68k_rom);
+  cpu68k_map_set(m68k_read8_map,   0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
+  cpu68k_map_set(m68k_read16_map,  0x000000, rs - 1, Pico32xMem->m68k_rom, 0);
+  cpu68k_map_set(m68k_write8_map,  0x000000, rs - 1, PicoWrite8_hint, 1); // TODO verify
+  cpu68k_map_set(m68k_write16_map, 0x000000, rs - 1, PicoWrite16_hint, 1);
+
+  // DRAM area
+  Pico32xSwapDRAM(1);
 
   // 32X ROM (unbanked, XXX: consider mirroring?)
   rs1 = rs = (Pico.romsize + M68K_BANK_MASK) & ~M68K_BANK_MASK;
index 8647a36..180045d 100644 (file)
@@ -78,7 +78,7 @@ void DrawAllSprites(unsigned char *sprited, int prio, int sh);
 void DrawTilesFromCache(int *hc, int sh, int rlim);\r
 void DrawSpritesSHi(unsigned char *sprited);\r
 void DrawLayer(int plane_sh, int *hcache, int cellskip, int maxcells);\r
-void FinalizeLineBGR444(int sh);\r
+void FinalizeLineBGR444(int sh, int line);\r
 void *blockcpy(void *dst, const void *src, size_t n);\r
 void blockcpy_or(void *dst, void *src, size_t n, int pat);\r
 #else\r
@@ -1192,7 +1192,7 @@ void PicoDoHighPal555(int sh)
   }\r
 }\r
 \r
-static void FinalizeLineBGR444(int sh)\r
+static void FinalizeLineBGR444(int sh, int line)\r
 {\r
   unsigned short *pd=DrawLineDest;\r
   unsigned char  *ps=HighCol+8;\r
@@ -1230,7 +1230,7 @@ static void FinalizeLineBGR444(int sh)
 }\r
 \r
 \r
-void FinalizeLineRGB555(int sh)\r
+void FinalizeLineRGB555(int sh, int line)\r
 {\r
   unsigned short *pd=DrawLineDest;\r
   unsigned char  *ps=HighCol+8;\r
@@ -1266,7 +1266,7 @@ void FinalizeLineRGB555(int sh)
 }\r
 #endif\r
 \r
-static void FinalizeLine8bit(int sh)\r
+static void FinalizeLine8bit(int sh, int line)\r
 {\r
   unsigned char *pd = DrawLineDest;\r
   int len, rs = rendstatus;\r
@@ -1306,7 +1306,7 @@ static void FinalizeLine8bit(int sh)
   }\r
 }\r
 \r
-static void (*FinalizeLine)(int sh);\r
+static void (*FinalizeLine)(int sh, int line);\r
 \r
 // --------------------------------------------\r
 \r
@@ -1429,43 +1429,38 @@ PICO_INTERNAL void PicoFrameStart(void)
   PrepareSprites(1);\r
 }\r
 \r
-static void DrawBlankedLine(int line, int offs)\r
+static void DrawBlankedLine(int line, int offs, int sh, int bgc)\r
 {\r
-  int sh = (Pico.video.reg[0xC]&8)>>3; // shadow/hilight?\r
-\r
   if (PicoScanBegin != NULL)\r
     PicoScanBegin(line + offs);\r
 \r
-  BackFill(Pico.video.reg[7], sh);\r
+  BackFill(bgc, sh);\r
 \r
   if (FinalizeLine != NULL)\r
-    FinalizeLine(sh);\r
+    FinalizeLine(sh, line);\r
 \r
   if (PicoScanEnd != NULL)\r
     PicoScanEnd(line + offs);\r
 }\r
 \r
-static void PicoLine(int line, int offs)\r
+static void PicoLine(int line, int offs, int sh, int bgc)\r
 {\r
-  int sh;\r
   if (skip_next_line > 0) {\r
     skip_next_line--;\r
     return;\r
   }\r
 \r
-  sh=(Pico.video.reg[0xC]&8)>>3; // shadow/hilight?\r
-\r
   DrawScanline = line;\r
   if (PicoScanBegin != NULL)\r
     skip_next_line = PicoScanBegin(line + offs);\r
 \r
   // Draw screen:\r
-  BackFill(Pico.video.reg[7], sh);\r
+  BackFill(bgc, sh);\r
   if (Pico.video.reg[1]&0x40)\r
     DrawDisplay(sh);\r
 \r
   if (FinalizeLine != NULL)\r
-    FinalizeLine(sh);\r
+    FinalizeLine(sh, line);\r
 \r
   if (PicoScanEnd != NULL)\r
     skip_next_line = PicoScanEnd(line + offs);\r
@@ -1474,16 +1469,22 @@ static void PicoLine(int line, int offs)
 void PicoDrawSync(int to, int blank_last_line)\r
 {\r
   int line, offs = 0;\r
+  int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight?\r
+  int bgc = Pico.video.reg[7];\r
 \r
   if (!(rendstatus & PDRAW_240LINES))\r
     offs = 8;\r
 \r
+  // need to know which pixels are bg for 32x\r
+  if (PicoAHW & PAHW_32X)\r
+    bgc = 0;\r
+\r
   for (line = DrawScanline; line < to; line++)\r
   {\r
 #if !CAN_HANDLE_240_LINES\r
     if (line >= 224) break;\r
 #endif\r
-    PicoLine(line, offs);\r
+    PicoLine(line, offs, sh, bgc);\r
   }\r
 \r
 #if !CAN_HANDLE_240_LINES\r
@@ -1497,8 +1498,8 @@ void PicoDrawSync(int to, int blank_last_line)
   if (line <= to)\r
   {\r
     if (blank_last_line)\r
-         DrawBlankedLine(line, offs);\r
-    else PicoLine(line, offs);\r
+         DrawBlankedLine(line, offs, sh, bgc);\r
+    else PicoLine(line, offs, sh, bgc);\r
     line++;\r
   }\r
   DrawScanline = line;\r
@@ -1509,7 +1510,7 @@ void PicoDrawSetColorFormat(int which)
   switch (which)\r
   {\r
     case 2: FinalizeLine = FinalizeLine8bit;   break;\r
-    case 1: FinalizeLine = FinalizeLineRGB555; break;\r
+    case 1: FinalizeLine = (PicoAHW & PAHW_32X) ? FinalizeLine32xRGB555 : FinalizeLineRGB555; break;\r
     case 0: FinalizeLine = FinalizeLineBGR444; break;\r
     default:FinalizeLine = NULL; break;\r
   }\r
index d2dced3..5160df1 100644 (file)
@@ -1082,7 +1082,6 @@ static unsigned char MEMH_FUNC z80_md_vdp_read(unsigned short a)
 \r
 static unsigned char MEMH_FUNC z80_md_bank_read(unsigned short a)\r
 {\r
-  extern unsigned int PicoReadM68k8(unsigned int a);\r
   unsigned int addr68k;\r
   unsigned char ret;\r
 \r
@@ -1124,7 +1123,6 @@ static void MEMH_FUNC z80_md_vdp_br_write(unsigned int a, unsigned char data)
 \r
 static void MEMH_FUNC z80_md_bank_write(unsigned int a, unsigned char data)\r
 {\r
-  extern void PicoWriteM68k8(unsigned int a, unsigned char d);\r
   unsigned int addr68k;\r
 \r
   addr68k = Pico.m.z80_bank68k << 15;\r
index aa2be38..302cc69 100644 (file)
@@ -76,6 +76,9 @@ void PicoPower(void)
   if (PicoAHW & PAHW_MCD)\r
     PicoPowerMCD();\r
 \r
+  if (!(PicoOpt & POPT_DIS_32X))\r
+    PicoPower32x();\r
+\r
   PicoReset();\r
 }\r
 \r
@@ -302,11 +305,17 @@ void PicoFrame(void)
     return;\r
   }\r
 \r
+  // TODO: MCD+32X\r
   if (PicoAHW & PAHW_MCD) {\r
     PicoFrameMCD();\r
     return;\r
   }\r
 \r
+  if (PicoAHW & PAHW_32X) {\r
+    PicoFrame32x();\r
+    return;\r
+  }\r
+\r
   //if(Pico.video.reg[12]&0x2) Pico.video.status ^= 0x10; // change odd bit in interlace mode\r
 \r
   PicoFrameStart();\r
index 8b7d032..e20820c 100644 (file)
@@ -34,6 +34,9 @@ extern void cache_flush_d_inval_i(const void *start_addr, const void *end_addr);
 // this one should handle display mode changes\r
 extern void emu_video_mode_change(int start_line, int line_count, int is_32cols);\r
 \r
+// this must switch to 32bpp mode\r
+extern void emu_32x_startup(void);\r
+\r
 // Pico.c\r
 #define POPT_EN_FM          (1<< 0) // 00 000x\r
 #define POPT_EN_PSG         (1<< 1)\r
index 368b4c8..407309a 100644 (file)
@@ -31,7 +31,6 @@
 }
 #endif
 
-// Accurate but slower frame which does hints
 static int PicoFrameHints(void)
 {
   struct PicoVideo *pv=&Pico.video;
@@ -176,6 +175,10 @@ static int PicoFrameHints(void)
   pv->status|=0x08; // go into vblank
   pv->pending_ints|=0x20;
 
+#ifdef PICO_32X
+  p32x_start_blank();
+#endif
+
   // the following SekRun is there for several reasons:
   // there must be a delay after vblank bit is set and irq is asserted (Mazin Saga)
   // also delay between F bit (bit 7) is set in SR and IRQ happens (Ex-Mutants)
index 85f2506..431c9a6 100644 (file)
@@ -389,12 +389,32 @@ typedef struct
 #define Pico_mcd ((mcd_state *)Pico.rom)\r
 \r
 // 32X\r
+#define P32XV_nPAL (1<<15)\r
+#define P32XV_PRI  (1<< 7)\r
+#define P32XV_Mx   (3<< 0)\r
+\r
+#define P32XV_VBLK (1<<15)\r
+#define P32XV_HBLK (1<<14)\r
+#define P32XV_PEN  (1<<13)\r
+#define P32XV_nFEN (1<< 1)\r
+#define P32XV_FS   (1<< 0)\r
+\r
 struct Pico32x\r
 {\r
   unsigned short regs[0x20];\r
   unsigned short vdp_regs[0x10];\r
   unsigned char pending_fb;\r
-  unsigned char pad[3];\r
+  unsigned char dirty_pal;\r
+  unsigned char pad[2];\r
+};\r
+\r
+struct Pico32xMem\r
+{\r
+  unsigned char  sdram[0x40000];\r
+  unsigned short dram[2][0x20000/2]; // AKA fb\r
+  unsigned char  m68k_rom[0x10000]; // 0x100; using M68K_BANK_SIZE\r
+  unsigned short pal[0x100];\r
+  unsigned short pal_native[0x100]; // converted to native (for renderer)\r
 };\r
 \r
 // area.c\r
@@ -436,7 +456,7 @@ int CM_compareRun(int cyc, int is_sub);
 PICO_INTERNAL void PicoFrameStart(void);\r
 void PicoDrawSync(int to, int blank_last_line);\r
 void BackFill(int reg7, int sh);\r
-void FinalizeLineRGB555(int sh);\r
+void FinalizeLineRGB555(int sh, int line);\r
 extern int DrawScanline;\r
 #define MAX_LINE_SPRITES 29\r
 extern unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES];\r
@@ -588,15 +608,22 @@ void PicoFrameDrawOnlyMS(void);
 // 32x/32x.c\r
 extern struct Pico32x Pico32x;\r
 void Pico32xInit(void);\r
-void Pico32xStartup(void);\r
+void PicoPower32x(void);\r
 void PicoReset32x(void);\r
+void Pico32xStartup(void);\r
+void PicoFrame32x(void);\r
 \r
 // 32x/memory.c\r
+struct Pico32xMem *Pico32xMem;\r
 unsigned int PicoRead8_32x(unsigned int a);\r
 unsigned int PicoRead16_32x(unsigned int a);\r
 void PicoWrite8_32x(unsigned int a, unsigned int d);\r
 void PicoWrite16_32x(unsigned int a, unsigned int d);\r
 void PicoMemSetup32x(void);\r
+void Pico32xSwapDRAM(int b);\r
+\r
+// 32x/draw.c\r
+void FinalizeLine32xRGB555(int sh, int line);\r
 \r
 /* avoid dependency on newer glibc */\r
 static __inline int isspace_(int c)\r
index 6fc25b4..627c3be 100644 (file)
@@ -409,6 +409,32 @@ static void shutdown_MCD(void)
        PicoAHW &= ~PAHW_MCD;\r
 }\r
 \r
+static void system_announce(void)\r
+{\r
+       const char *sys_name, *tv_standard;\r
+       int fps;\r
+\r
+       if (PicoAHW & PAHW_SMS) {\r
+               sys_name = "Master System";\r
+       } else if (PicoAHW & PAHW_PICO) {\r
+               sys_name = "Pico";\r
+       } else if (PicoAHW & PAHW_MCD) {\r
+               sys_name = "Mega CD";\r
+               if ((Pico.m.hardware & 0xc0) == 0x80)\r
+                       sys_name = "Sega CD";\r
+       } else if (PicoAHW & PAHW_32X) {\r
+               sys_name = "32X";\r
+       } else {\r
+               sys_name = "MegaDrive";\r
+               if ((Pico.m.hardware & 0xc0) == 0x80)\r
+                       sys_name = "Genesis";\r
+       }\r
+       tv_standard = Pico.m.pal ? "PAL" : "NTSC";\r
+       fps = Pico.m.pal ? 50 : 60;\r
+\r
+       emu_status_msg("%s %s / %dFPS", tv_standard, sys_name, fps);\r
+}\r
+\r
 // note: this function might mangle rom_fname\r
 // XXX: portions of this code should move to pico/\r
 int emu_reload_rom(char *rom_fname)\r
@@ -612,21 +638,7 @@ int emu_reload_rom(char *rom_fname)
        }\r
        else\r
        {\r
-               const char *sys_name, *tv_standard;\r
-               int fps;\r
-\r
-               if (PicoAHW & PAHW_SMS) {\r
-                       sys_name = "Master System";\r
-               } else {\r
-                       sys_name = "MegaDrive";\r
-                       if ((Pico.m.hardware&0xc0) == 0x80)\r
-                               sys_name = "Genesis";\r
-               }\r
-               tv_standard = Pico.m.pal ? "PAL" : "NTSC";\r
-               fps = Pico.m.pal ? 50 : 60;\r
-\r
-               emu_status_msg("%s %s / %dFPS", tv_standard, sys_name, fps);\r
-\r
+               system_announce();\r
                PicoOpt &= ~POPT_DIS_VDP_FIFO;\r
        }\r
 \r
@@ -1073,6 +1085,12 @@ static void emu_tray_close(void)
        emu_status_msg("CD tray closed.");\r
 }\r
 \r
+void emu_32x_startup(void)\r
+{\r
+       plat_video_toggle_renderer(0, 1, 0);\r
+       system_announce();\r
+}\r
+\r
 void emu_reset_game(void)\r
 {\r
        PicoReset();\r
@@ -1200,9 +1218,9 @@ static void run_events_ui(unsigned int which)
                        PicoStateProgressCB = NULL;\r
                }\r
        }\r
-       if (which & PEV_SWITCH_RND)\r
+       if ((which & PEV_SWITCH_RND) && !(PicoAHW & PAHW_32X))\r
        {\r
-               plat_video_toggle_renderer(1, 0);\r
+               plat_video_toggle_renderer(1, 0, 0);\r
        }\r
        if (which & (PEV_SSLOT_PREV|PEV_SSLOT_NEXT))\r
        {\r
index e651694..adfacef 100644 (file)
@@ -1452,7 +1452,7 @@ static int menu_loop_adv_options(menu_id id, int keys)
 \r
 static int mh_opt_render(menu_id id, int keys)\r
 {\r
-       plat_video_toggle_renderer((keys & PBTN_RIGHT) ? 1 : 0, 1);\r
+       plat_video_toggle_renderer((keys & PBTN_RIGHT) ? 1 : 0, 0, 1);\r
        return 0;\r
 }\r
 \r
index ca847c6..e1fc29b 100644 (file)
@@ -36,7 +36,7 @@ void plat_video_menu_begin(void);
 void plat_video_menu_end(void);
 
 void plat_video_wait_vsync(void);
-void plat_video_toggle_renderer(int is_next, int is_menu);
+void plat_video_toggle_renderer(int is_next, int force_16bpp, int is_menu);
 void plat_validate_config(void);
 void plat_update_volume(int has_changed, int is_up);
 
index 817237a..8ccea30 100644 (file)
@@ -72,6 +72,8 @@ OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \
                pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \\r
                pico/cd/area.o pico/cd/misc.o pico/cd/pcm.o pico/cd/buffering.o\r
 endif\r
+# Pico - 32X\r
+OBJS += pico/32x/32x.o pico/32x/memory.o pico/32x/draw.o\r
 # Pico - Pico\r
 OBJS += pico/pico/pico.o pico/pico/memory.o pico/pico/xpcm.o\r
 # Pico - carthw\r
index 97b28b6..757bea6 100644 (file)
@@ -498,10 +498,14 @@ static void vidResetMode(void)
        make_local_pal = (PicoAHW & PAHW_SMS) ? make_local_pal_sms : make_local_pal_md;\r
 }\r
 \r
-void plat_video_toggle_renderer(int is_next, int is_menu)\r
+void plat_video_toggle_renderer(int is_next, int force_16bpp, int is_menu)\r
 {\r
+       if (force_16bpp) {\r
+               PicoOpt &= ~POPT_ALT_RENDERER;\r
+               currentConfig.EmuOpt |= EOPT_16BPP;\r
+       }\r
        /* alt, 16bpp, 8bpp */\r
-       if (PicoOpt & POPT_ALT_RENDERER) {\r
+       else if (PicoOpt & POPT_ALT_RENDERER) {\r
                PicoOpt &= ~POPT_ALT_RENDERER;\r
                if (is_next)\r
                        currentConfig.EmuOpt |= EOPT_16BPP;\r
index e6a94a2..32fa3c5 100644 (file)
@@ -40,7 +40,7 @@ OBJS += pico/cd/pico.o pico/cd/memory.o pico/cd/sek.o pico/cd/LC89510.o \
        pico/cd/cd_sys.o pico/cd/cd_file.o pico/cd/cue.o pico/cd/gfx_cd.o \
        pico/cd/area.o pico/cd/misc.o pico/cd/pcm.o pico/cd/buffering.o
 # Pico - 32X
-OBJS += pico/32x/32x.o pico/32x/memory.o
+OBJS += pico/32x/32x.o pico/32x/memory.o pico/32x/draw.o
 # Pico - Pico
 OBJS += pico/pico/pico.o pico/pico/memory.o pico/pico/xpcm.o
 # Pico - sound