Browse Source

new 32x renderers, auto fskip change, massive refactoring

git-svn-id: file:///home/notaz/opt/svn/PicoDrive@855 be3aeb3a-fb24-0410-a615-afba39da0efa
notaz 14 years ago
parent
commit
5a68108691

+ 20 - 0
pico/32x/32x.c

@@ -148,6 +148,26 @@ void PicoReset32x(void)
 
 static void p32x_start_blank(void)
 {
+  if (Pico32xDrawMode != 0) {
+    if ((Pico32x.vdp_regs[0] & P32XV_Mx) != 0 && // 32x not blanking
+        (Pico.video.reg[12] & 1) && // 40col mode
+        (PicoDrawMask & PDRAW_32X_ON))
+    {
+      int md_bg = Pico.video.reg[7] & 0x3f;
+      int offs = 8, lines = 224;
+      if (Pico.video.reg[1] & 8) {
+        offs = 0;
+        lines = 240;
+      }
+
+      // we draw full layer (not line-by-line)
+      PicoDraw32xLayer(offs, lines, md_bg);
+    }
+    else {
+      // TODO: MD layer only?
+    }
+  }
+
   // enter vblank
   Pico32x.vdp_regs[0x0a/2] |= P32XV_VBLK|P32XV_PEN;
 

+ 229 - 48
pico/32x/draw.c

@@ -1,5 +1,9 @@
 #include "../pico_int.h"
 
+int (*PicoScan32xBegin)(unsigned int num);
+int (*PicoScan32xEnd)(unsigned int num);
+int Pico32xDrawMode;
+
 static void convert_pal555(int invert_prio)
 {
   unsigned int *ps = (void *)Pico32xMem->pal;
@@ -22,49 +26,87 @@ static void convert_pal555(int invert_prio)
   Pico32x.dirty_pal = 0;
 }
 
+// direct color mode
+#define do_line_dc(pd, p32x, pmd, inv, pmd_draw_code)             \
+{                                                                 \
+  const unsigned int m1 = 0x001f;                                 \
+  const unsigned int m2 = 0x03e0;                                 \
+  const unsigned int m3 = 0x7c00;                                 \
+  int i;                                                          \
+                                                                  \
+  for (i = 320; i > 0; i--, pd++, p32x++, pmd++) {                \
+    unsigned short t = *p32x;                                     \
+    if (*pmd != mdbg && !((t ^ inv) & 0x8000)) {                  \
+      pmd_draw_code;                                              \
+      continue;                                                   \
+    }                                                             \
+                                                                  \
+    *pd = ((t & m1) << 11) | ((t & m2) << 1) | ((t & m3) >> 10);  \
+  }                                                               \
+}
+
+// packed pixel mode
+#define do_line_pp(pd, p32x, pmd, pmd_draw_code)                  \
+{                                                                 \
+  unsigned short t;                                               \
+  int i;                                                          \
+  for (i = 320/2; i > 0; i--, p32x++) {                           \
+    t = pal[*p32x >> 8];                                          \
+    if (*pmd == mdbg || (t & 0x20))                               \
+      *pd = t;                                                    \
+    else                                                          \
+      pmd_draw_code;                                              \
+    pd++; pmd++;                                                  \
+    t = pal[*p32x & 0xff];                                        \
+    if (*pmd == mdbg || (t & 0x20))                               \
+      *pd = t;                                                    \
+    else                                                          \
+      pmd_draw_code;                                              \
+    pd++; pmd++;                                                  \
+  }                                                               \
+} 
+
+// run length mode
+#define do_line_rl(pd, p32x, pmd, pmd_draw_code)                  \
+{                                                                 \
+  unsigned short len, t;                                          \
+  int i;                                                          \
+  for (i = 320; i > 0; p32x++) {                                  \
+    t = pal[*p32x & 0xff];                                        \
+    for (len = (*p32x >> 8) + 1; len > 0 && i > 0; len--, i--, pd++, pmd++) { \
+      if (*pmd == mdbg || (t & 0x20))                             \
+        *pd = t;                                                  \
+      else                                                        \
+        pmd_draw_code;                                            \
+    }                                                             \
+  }                                                               \
+}
+
 void FinalizeLine32xRGB555(int sh, int line)
 {
   unsigned short *pd = DrawLineDest;
   unsigned short *pal = Pico32xMem->pal_native;
-  unsigned char *pb = HighCol + 8;
-  unsigned short *dram, *ps, cram0;
-  int i;
-
-  // 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;
+  unsigned char  *pmd = HighCol + 8;
+  unsigned short *dram, *p32x;
+  unsigned char   mdbg;
 
-  if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 0)
-    return; // blanking
-
-  // XXX: how is 32col mode hadled by real hardware?
-  if (!(Pico.video.reg[12] & 1))
-    return;
+  FinalizeLine555(sh, line);
 
-  if (!(PicoDrawMask & PDRAW_32X_ON))
+  if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 0 || // 32x blanking
+      // XXX: how is 32col mode hadled by real hardware?
+      !(Pico.video.reg[12] & 1) || // 32col mode
+      !(PicoDrawMask & PDRAW_32X_ON))
+  {
     return;
+  }
 
   dram = (void *)Pico32xMem->dram[Pico32x.vdp_regs[0x0a/2] & P32XV_FS];
-  ps = dram + dram[line];
+  p32x = dram + dram[line];
+  mdbg = Pico.video.reg[7] & 0x3f;
 
   if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 2) { // Direct Color Mode
-    int inv = (Pico32x.vdp_regs[0] & P32XV_PRI) ? 0x8000 : 0;
-    unsigned int m1 = 0x001f001f;
-    unsigned int m2 = 0x03e003e0;
-    unsigned int m3 = 0xfc00fc00;
-
-    for (i = 320; i > 0; i--, ps++, pd++, pb++) {
-      unsigned short t = *ps;
-      if (*pb != 0 && !((t ^ inv) & 0x8000))
-        continue;
-
-      *pd = ((t & m1) << 11) | ((t & m2) << 1) | ((t & m3) >> 10);
-    }
+    int inv_bit = (Pico32x.vdp_regs[0] & P32XV_PRI) ? 0x8000 : 0;
+    do_line_dc(pd, p32x, pmd, inv_bit,);
     return;
   }
 
@@ -72,24 +114,163 @@ void FinalizeLine32xRGB555(int sh, int line)
     convert_pal555(Pico32x.vdp_regs[0] & P32XV_PRI);
 
   if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 1) { // Packed Pixel Mode
-    unsigned short t;
-    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;
-    }
+    do_line_pp(pd, p32x, pmd,);
   }
   else { // Run Length Mode
-    unsigned short len, t;
-    for (i = 320; i > 0; ps++) {
-      t = pal[*ps & 0xff];
-      for (len = (*ps >> 8) + 1; len > 0 && i > 0; len--, i--, pd++, pb++)
-        if (*pb == 0 || (t & 0x20))
-          *pd = t;
-    }
+    do_line_rl(pd, p32x, pmd,);
+  }
+}
+
+#define MD_LAYER_CODE \
+  *dst = palmd[*pmd]
+
+#define PICOSCAN_PRE \
+  PicoScan32xBegin(l + (lines_offs & 0xff)); \
+  dst = DrawLineDest; \
+
+#define PICOSCAN_POST \
+  PicoScan32xEnd(l + (lines_offs & 0xff)); \
+
+#define make_do_loop(name, pre_code, post_code, md_code)        \
+/* Direct Color Mode */                                         \
+static void do_loop_dc##name(unsigned short *dst,               \
+    unsigned short *dram, int lines_offs, int mdbg)             \
+{                                                               \
+  int inv_bit = (Pico32x.vdp_regs[0] & P32XV_PRI) ? 0x8000 : 0; \
+  unsigned char  *pmd = PicoDraw2FB + 328 * 8 + 8;              \
+  unsigned short *palmd = HighPal;                              \
+  unsigned short *p32x;                                         \
+  int lines = lines_offs >> 16;                                 \
+  int l;                                                        \
+  (void)palmd;                                                  \
+  for (l = 0; l < lines; l++, pmd += 8) {                       \
+    pre_code;                                                   \
+    p32x = dram + dram[l];                                      \
+    do_line_dc(dst, p32x, pmd, inv_bit, md_code);               \
+    post_code;                                                  \
+  }                                                             \
+}                                                               \
+                                                                \
+/* Packed Pixel Mode */                                         \
+static void do_loop_pp##name(unsigned short *dst,               \
+    unsigned short *dram, int lines_offs, int mdbg)             \
+{                                                               \
+  unsigned short *pal = Pico32xMem->pal_native;                 \
+  unsigned char  *pmd = PicoDraw2FB + 328 * 8 + 8;              \
+  unsigned short *palmd = HighPal;                              \
+  unsigned short *p32x;                                         \
+  int lines = lines_offs >> 16;                                 \
+  int l;                                                        \
+  (void)palmd;                                                  \
+  for (l = 0; l < lines; l++, pmd += 8) {                       \
+    pre_code;                                                   \
+    p32x = dram + dram[l];                                      \
+    do_line_pp(dst, p32x, pmd, md_code);                        \
+    post_code;                                                  \
+  }                                                             \
+}                                                               \
+                                                                \
+/* Run Length Mode */                                           \
+static void do_loop_rl##name(unsigned short *dst,               \
+    unsigned short *dram, int lines_offs, int mdbg)             \
+{                                                               \
+  unsigned short *pal = Pico32xMem->pal_native;                 \
+  unsigned char  *pmd = PicoDraw2FB + 328 * 8 + 8;              \
+  unsigned short *palmd = HighPal;                              \
+  unsigned short *p32x;                                         \
+  int lines = lines_offs >> 16;                                 \
+  int l;                                                        \
+  (void)palmd;                                                  \
+  for (l = 0; l < lines; l++, pmd += 8) {                       \
+    pre_code;                                                   \
+    p32x = dram + dram[l];                                      \
+    do_line_rl(dst, p32x, pmd, md_code);                        \
+    post_code;                                                  \
+  }                                                             \
+}
+
+#ifdef _ASM_32X_DRAW
+#undef make_do_loop
+#define make_do_loop(name, pre_code, post_code, md_code) \
+extern void do_loop_dc##name(unsigned short *dst,        \
+    unsigned short *dram, int lines_offs, int mdbg);     \
+extern void do_loop_pp##name(unsigned short *dst,        \
+    unsigned short *dram, int lines_offs, int mdbg);     \
+extern void do_loop_rl##name(unsigned short *dst,        \
+    unsigned short *dram, int lines_offs, int mdbg);
+#endif
+
+make_do_loop(,,,)
+make_do_loop(_md, , , MD_LAYER_CODE)
+make_do_loop(_scan, PICOSCAN_PRE, PICOSCAN_POST, )
+make_do_loop(_scan_md, PICOSCAN_PRE, PICOSCAN_POST, MD_LAYER_CODE)
+
+typedef void (*do_loop_func)(unsigned short *dst, unsigned short *dram, int lines, int mdbg);
+enum { DO_LOOP, DO_LOOP_MD, DO_LOOP_SCAN, DO_LOOP_MD_SCAN };
+
+static const do_loop_func do_loop_dc_f[] = { do_loop_dc, do_loop_dc_md, do_loop_dc_scan, do_loop_dc_scan_md };
+static const do_loop_func do_loop_pp_f[] = { do_loop_pp, do_loop_pp_md, do_loop_pp_scan, do_loop_pp_scan_md };
+static const do_loop_func do_loop_rl_f[] = { do_loop_rl, do_loop_rl_md, do_loop_rl_scan, do_loop_rl_scan_md };
+
+void PicoDraw32xLayer(int offs, int lines, int md_bg)
+{
+  int have_scan = PicoScan32xBegin != NULL && PicoScan32xEnd != NULL;
+  const do_loop_func *do_loop;
+  unsigned short *dram;
+  int which_func;
+
+  DrawLineDest = DrawLineDestBase + offs * DrawLineDestIncrement;
+  dram = Pico32xMem->dram[Pico32x.vdp_regs[0x0a/2] & P32XV_FS];
+
+  if (Pico32xDrawMode == 2) {
+    if (Pico.m.dirtyPal)
+      PicoDrawUpdateHighPal();
+  }
+
+  if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 2)
+  {
+    // Direct Color Mode
+    do_loop = do_loop_dc_f;
+    goto do_it;
+  }
+
+  if (Pico32x.dirty_pal)
+    convert_pal555(Pico32x.vdp_regs[0] & P32XV_PRI);
+
+  if ((Pico32x.vdp_regs[0] & P32XV_Mx) == 1)
+  {
+    // Packed Pixel Mode
+    do_loop = do_loop_pp_f;
+  }
+  else
+  {
+    // Run Length Mode
+    do_loop = do_loop_rl_f;
+  }
+
+do_it:
+  if (Pico32xDrawMode == 2)
+    which_func = have_scan ? DO_LOOP_MD_SCAN : DO_LOOP_MD;
+  else
+    which_func = have_scan ? DO_LOOP_SCAN : DO_LOOP;
+
+  do_loop[which_func](DrawLineDest, dram, (lines << 16) | offs, md_bg);
+}
+
+void PicoDraw32xSetFrameMode(int is_on, int only_32x)
+{
+#ifdef _ASM_32X_DRAW
+  extern void *Pico32xNativePal;
+  Pico32xNativePal = Pico32xMem->pal_native;
+#endif
+
+  if (is_on) {
+    // use the same layout as alt renderer
+    PicoDrawSetInternalBuf(PicoDraw2FB + 328*8, 328);
+    Pico32xDrawMode = only_32x ? 1 : 2;
+  } else {
+    PicoDrawSetInternalBuf(NULL, 0);
+    Pico32xDrawMode = 0;
   }
 }
 

+ 263 - 0
pico/32x/draw_arm.s

@@ -0,0 +1,263 @@
+@ vim:filetype=armasm
+
+.extern Pico32x
+.extern PicoDraw2FB
+.extern HighPal
+
+.equiv P32XV_PRI,  (1<< 7)
+
+.bss
+.align 2
+.global Pico32xNativePal
+Pico32xNativePal:
+    .word 0
+
+.text
+.align 2
+
+
+.macro call_scan_prep cond
+.if \cond
+    ldr     r4, =PicoScan32xBegin
+    ldr     r5, =PicoScan32xEnd
+    ldr     r6, =DrawLineDest
+    ldr     r4, [r4]
+    ldr     r5, [r5]
+    stmfd   sp!, {r4,r5,r6}
+.endif
+.endm
+
+.macro call_scan_fin_ge cond
+.if \cond
+    addge   sp, sp, #4*3
+.endif
+.endm
+
+.macro call_scan_begin cond
+.if \cond
+    stmfd   sp!, {r1-r3}
+    and     r0, r2, #0xff
+    add     r0, r0, r4
+    mov     lr, pc
+    ldr     pc, [sp, #(3+0)*4]
+    ldr     r0, [sp, #(3+2)*4] @ &DrawLineDest
+    ldmfd   sp!, {r1-r3}
+    ldr     r0, [r0]
+.endif
+.endm
+
+.macro call_scan_end cond
+.if \cond
+    stmfd   sp!, {r0-r3}
+    and     r0, r2, #0xff
+    add     r0, r0, r4
+    mov     lr, pc
+    ldr     pc, [sp, #(4+1)*4]
+    ldmfd   sp!, {r0-r3}
+.endif
+.endm
+
+@ direct color
+@ unsigned short *dst, unsigned short *dram, int lines_offs, int mdbg
+.macro make_do_loop_dc name call_scan do_md
+.global \name
+\name:
+    stmfd   sp!, {r4-r11,lr}
+
+    ldr     r10,=Pico32x
+    ldr     r11,=PicoDraw2FB
+    ldr     r10,[r10, #0x40] @ Pico32x.vdp_regs[0]
+    ldr     r11,[r11]
+    ldr     r9, =HighPal     @ palmd
+    add     r11,r11,#(328*8) @ r11 = pmd: md data
+    tst     r10,#P32XV_PRI
+    moveq   r10,#0
+    movne   r10,#0x8000      @ r10 = inv_bit
+    call_scan_prep \call_scan
+
+    mov     r4, #0           @ line
+    b       1f @ loop_outer_entry
+
+0: @ loop_outer:
+    call_scan_end \call_scan
+    add     r4, r4, #1
+    sub     r11,r11,#1       @ adjust for prev read
+    cmp     r4, r2, lsr #16
+    call_scan_fin_ge \call_scan
+    ldmgefd sp!, {r4-r11,pc}
+
+1: @ loop_outer_entry:
+    call_scan_begin \call_scan
+    mov     r12,r4, lsl #1
+    ldrh    r12,[r1, r12]
+    add     r11,r11,#8
+    mov     r6, #320
+    add     r5, r1, r12, lsl #1 @ p32x = dram + dram[l]
+
+2: @ loop_inner:
+    ldrb    r7, [r11], #1    @ MD pixel
+    subs    r6, r6, #1
+    blt     0b @ loop_outer
+    ldrh    r8, [r5], #2     @ 32x pixel
+    cmp     r7, r3           @ MD has bg pixel?
+    beq     3f @ draw32x
+    eor     r12,r8, r10
+    ands    r12,r12,#0x8000  @ !((t ^ inv) & 0x8000)
+.if \do_md
+    mov     r7, r7, lsl #1
+    ldreqh  r12,[r9, r7]
+    streqh  r12,[r0], #2     @ *dst++ = palmd[*pmd]
+.endif
+    beq     2b @ loop_inner
+
+3: @ draw32x:
+    and     r12,r8, #0x03e0
+    mov     r8, r8, lsl #11
+    orr     r8, r8, r8, lsr #(10+11)
+    orr     r8, r8, r12,lsl #1
+    bic     r8, r8, #0x0020  @ kill prio bit
+    strh    r8, [r0], #2     @ *dst++ = bgr2rgb(*p32x++)
+    b       2b @ loop_inner
+.endm
+
+
+@ packed pixel
+.macro do_pixel_pp do_md
+    ldrb    r7, [r11], #1    @ MD pixel
+    eor     r12,r5, #1
+    ldrb    r8, [r12]        @ palette index
+    cmp     r7, r3           @ MD has bg pixel?
+    mov     r12,r8,lsl #1
+    ldrh    r8, [r10,r12]    @ t = 32x pixel
+    mov     r7, r7, lsl #1
+    add     r5, r5, #1
+    eorne   r12,r8, #0x20
+    tstne   r12, #0x20
+.if \do_md
+    ldrneh  r8, [r9, r7]     @ t = palmd[*pmd]
+    subs    r6, r6, #1
+    strh    r8, [r0], #2     @ *dst++ = t
+.else
+    streqh  r8, [r0], #2
+    addne   r0, r0, #2
+    subs    r6, r6, #1
+.endif
+.endm
+
+@ unsigned short *dst, unsigned short *dram, int lines_offs, int mdbg
+.macro make_do_loop_pp name call_scan do_md
+.global \name
+\name:
+    stmfd   sp!, {r4-r11,lr}
+
+    ldr     r11,=PicoDraw2FB
+    ldr     r10,=Pico32xNativePal
+    ldr     r11,[r11]
+    ldr     r10,[r10]
+    ldr     r9, =HighPal     @ palmd
+    add     r11,r11,#(328*8) @ r11 = pmd: md data
+    call_scan_prep \call_scan
+
+    mov     r4, #0           @ line
+    b       1f @ loop_outer_entry
+
+0: @ loop_outer:
+    call_scan_end \call_scan
+    add     r4, r4, #1
+    cmp     r4, r2, lsr #16
+    call_scan_fin_ge \call_scan
+    ldmgefd sp!, {r4-r11,pc}
+
+1: @ loop_outer_entry:
+    call_scan_begin \call_scan
+    mov     r12,r4, lsl #1
+    ldrh    r12,[r1, r12]
+    add     r11,r11,#8
+    mov     r6, #320
+    add     r5, r1, r12, lsl #1 @ p32x = dram + dram[l]
+
+2: @ loop_inner:
+    do_pixel_pp \do_md
+    do_pixel_pp \do_md
+    bgt     2b @ loop_inner
+    b       0b @ loop_outer
+.endm
+
+
+@ run length
+@ unsigned short *dst, unsigned short *dram, int lines_offs, int mdbg
+.macro make_do_loop_rl name call_scan do_md
+.global \name
+\name:
+    stmfd   sp!, {r4-r11,lr}
+
+    ldr     r11,=PicoDraw2FB
+    ldr     r10,=Pico32xNativePal
+    ldr     r11,[r11]
+    ldr     r10,[r10]
+    ldr     r9, =HighPal     @ palmd
+    add     r11,r11,#(328*8) @ r11 = pmd: md data
+    call_scan_prep \call_scan
+
+    mov     r4, #0           @ line
+    b       1f @ loop_outer_entry
+
+0: @ loop_outer:
+    call_scan_end \call_scan
+    add     r4, r4, #1
+    sub     r11,r11,#1       @ adjust for prev read
+    cmp     r4, r2, lsr #16
+    call_scan_fin_ge \call_scan
+    ldmgefd sp!, {r4-r11,pc}
+
+1: @ loop_outer_entry:
+    call_scan_begin \call_scan
+    mov     r12,r4, lsl #1
+    ldrh    r12,[r1, r12]
+    add     r11,r11,#8
+    mov     r6, #320
+    add     r5, r1, r12, lsl #1 @ p32x = dram + dram[l]
+
+2: @ loop_inner:
+    ldrh    r8, [r5], #2     @ control word
+    and     r12,r8, #0xff
+    mov     r12,r12,lsl #1
+    ldrh    lr, [r10,r12]    @ t = 32x pixel
+    eor     lr, lr, #0x20
+
+3: @ loop_innermost:
+    ldrb    r7, [r11], #1    @ MD pixel
+    subs    r6, r6, #1
+    blt     0b @ loop_outer
+    cmp     r7, r3           @ MD has bg pixel?
+    mov     r7, r7, lsl #1
+    tstne   lr, #0x20
+.if \do_md
+    ldrneh  r12,[r9, r7]     @ t = palmd[*pmd]
+    streqh  lr, [r0], #2
+    strneh  r12,[r0], #2     @ *dst++ = t
+.else
+    streqh  lr, [r0]
+    add     r0, r0, #2
+.endif
+    subs    r8, r8, #0x100
+    bge     3b @ loop_innermost
+    b       2b @ loop_inner
+.endm
+
+
+make_do_loop_dc do_loop_dc,         0, 0
+make_do_loop_dc do_loop_dc_md,      0, 1
+make_do_loop_dc do_loop_dc_scan,    1, 0
+make_do_loop_dc do_loop_dc_scan_md, 1, 1
+
+make_do_loop_pp do_loop_pp,         0, 0
+make_do_loop_pp do_loop_pp_md,      0, 1
+make_do_loop_pp do_loop_pp_scan,    1, 0
+make_do_loop_pp do_loop_pp_scan_md, 1, 1
+
+make_do_loop_rl do_loop_rl,         0, 0
+make_do_loop_rl do_loop_rl_md,      0, 1
+make_do_loop_rl do_loop_rl_scan,    1, 0
+make_do_loop_rl do_loop_rl_scan_md, 1, 1
+

+ 68 - 23
pico/draw.c

@@ -34,14 +34,15 @@
 int (*PicoScanBegin)(unsigned int num) = NULL;
 int (*PicoScanEnd)  (unsigned int num) = NULL;
 
-#if OVERRIDE_HIGHCOL
 static unsigned char DefHighCol[8+320+8];
-unsigned char *HighCol=DefHighCol;
-#else
-unsigned char  HighCol[8+320+8];
-#endif
+unsigned char *HighCol = DefHighCol;
+static unsigned char *HighColBase = DefHighCol;
+static int HighColIncrement;
+
 static unsigned int DefOutBuff[320*2/2];
-void *DrawLineDest=DefOutBuff; // pointer to dest buffer where to draw this line to
+void *DrawLineDest = DefOutBuff; // pointer to dest buffer where to draw this line to
+void *DrawLineDestBase = DefOutBuff;
+int DrawLineDestIncrement;
 
 static int  HighCacheA[41+1];   // caches for high layers
 static int  HighCacheB[41+1];
@@ -1193,6 +1194,7 @@ void PicoDoHighPal555(int sh)
   }
 }
 
+#if 0
 static void FinalizeLineBGR444(int sh, int line)
 {
   unsigned short *pd=DrawLineDest;
@@ -1229,9 +1231,10 @@ static void FinalizeLineBGR444(int sh, int line)
   for(i = 0; i < len; i++)
     pd[i] = pal[ps[i] & mask];
 }
+#endif
 
 
-void FinalizeLineRGB555(int sh, int line)
+void FinalizeLine555(int sh, int line)
 {
   unsigned short *pd=DrawLineDest;
   unsigned char  *ps=HighCol+8;
@@ -1405,7 +1408,7 @@ static int DrawDisplay(int sh)
 // MUST be called every frame
 PICO_INTERNAL void PicoFrameStart(void)
 {
-  int lines = 224;
+  int offs = 8, lines = 224;
 
   // prepare to do this frame
   rendstatus = 0;
@@ -1413,9 +1416,13 @@ PICO_INTERNAL void PicoFrameStart(void)
     rendstatus |= PDRAW_INTERLACE; // interlace mode
   if (!(Pico.video.reg[12] & 1))
     rendstatus |= PDRAW_32_COLS;
-  if (Pico.video.reg[1] & 8)
+  if (Pico.video.reg[1] & 8) {
+    offs = 0;
     lines = 240;
+  }
 
+  HighCol = HighColBase;
+  DrawLineDest = (char *)DrawLineDestBase + offs * DrawLineDestIncrement;
   DrawScanline = 0;
   skip_next_line = 0;
 
@@ -1477,6 +1484,9 @@ static void PicoLine(int line, int offs, int sh, int bgc)
 
   if (PicoScanEnd != NULL)
     skip_next_line = PicoScanEnd(line + offs);
+
+  HighCol += HighColIncrement;
+  DrawLineDest = (char *)DrawLineDest + DrawLineDestIncrement;
 }
 
 void PicoDrawSync(int to, int blank_last_line)
@@ -1490,10 +1500,6 @@ void PicoDrawSync(int to, int blank_last_line)
   if (rendlines != 240)
     offs = 8;
 
-  // need to know which pixels are bg for 32x
-  if (PicoAHW & PAHW_32X)
-    bgc = 0;
-
   for (line = DrawScanline; line < to; line++)
   {
 #if !CAN_HANDLE_240_LINES
@@ -1522,20 +1528,59 @@ void PicoDrawSync(int to, int blank_last_line)
   pprof_end(draw);
 }
 
-void PicoDrawSetColorFormat(int which)
+// also works for fast renderer
+void PicoDrawUpdateHighPal(void)
+{
+  int sh = (Pico.video.reg[0xC] & 8) >> 3; // shadow/hilight?
+  if (PicoOpt & POPT_ALT_RENDERER)
+    sh = 0; // no s/h support
+
+  PicoDoHighPal555(sh);
+  if (rendstatus & PDRAW_SONIC_MODE) {
+    // FIXME?
+    memcpy(HighPal + 0x40, HighPal, 0x40*2);
+    memcpy(HighPal + 0x80, HighPal, 0x40*2);
+  }
+}
+
+void PicoDrawSetOutFormat(pdso_t which, int allow_32x)
 {
   switch (which)
   {
-    case 2: FinalizeLine = FinalizeLine8bit;   break;
-    case 1: FinalizeLine = (PicoAHW & PAHW_32X) ? FinalizeLine32xRGB555 : FinalizeLineRGB555; break;
-    case 0: FinalizeLine = FinalizeLineBGR444; break;
-    default:FinalizeLine = NULL; break;
+    case PDF_8BIT:
+      FinalizeLine = FinalizeLine8bit;
+      break;
+
+    case PDF_RGB555:
+      if ((PicoAHW & PAHW_32X) && allow_32x)
+        FinalizeLine = FinalizeLine32xRGB555;
+      else
+        FinalizeLine = FinalizeLine555;
+      break;
+
+    default:
+      FinalizeLine = NULL;
+      break;
   }
-  PicoDrawSetColorFormatMode4(which);
+  PicoDrawSetOutputMode4(which);
   rendstatus_old = -1;
-#if OVERRIDE_HIGHCOL
-  if (which)
-    HighCol=DefHighCol;
-#endif
+}
+
+void PicoDrawSetOutBuf(void *dest, int increment)
+{
+  DrawLineDestBase = dest;
+  DrawLineDestIncrement = increment;
+}
+
+void PicoDrawSetInternalBuf(void *dest, int increment)
+{
+  if (dest != NULL) {
+    HighColBase = dest;
+    HighColIncrement = increment;
+  }
+  else {
+    HighColBase = DefHighCol;
+    HighColIncrement = 0;
+  }
 }
 

+ 5 - 3
pico/draw_arm.s

@@ -19,6 +19,8 @@
 .extern DrawStripInterlace
 .extern HighCacheS_ptr
 
+.equiv OVERRIDE_HIGHCOL,  1
+
 .equ PDRAW_SPRITES_MOVED, (1<<0)
 .equ PDRAW_WND_DIFF_PRIO, (1<<1)
 .equ PDRAW_ACC_SPRITES,   (1<<2)
@@ -1674,7 +1676,7 @@ PicoDoHighPal555:
     ldr     r8, =(Pico+0x22228)  @ Pico.video
 
 PicoDoHighPal555_nopush:
-    str     r1, [sp, #-8]        @ is called from FinalizeLineRGB555?
+    str     r1, [sp, #-8]        @ is called from FinalizeLine555?
 
     str     r0, [sp, #-4]
     ldr     r0, =HighPal
@@ -1728,9 +1730,9 @@ PicoDoHighPal555_end:
     b       FinalizeLineRGB555_pal_done
 
 
-.global FinalizeLineRGB555 @ int sh
+.global FinalizeLine555 @ int sh
 
-FinalizeLineRGB555:
+FinalizeLine555:
     stmfd   sp!, {r4-r9,lr}
     ldr     r8, =(Pico+0x22228)  @ Pico.video
 

+ 9 - 5
pico/mode4.c

@@ -211,6 +211,8 @@ void PicoFrameStartMode4(void)
     rendlines = lines;
     emu_video_mode_change(screen_offset, lines, 1);
   }
+
+  DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement;
 }
 
 void PicoLineMode4(int line)
@@ -233,6 +235,8 @@ void PicoLineMode4(int line)
 
   if (PicoScanEnd != NULL)
     skip_next_line = PicoScanEnd(line + screen_offset);
+
+  DrawLineDest = (char *)DrawLineDest + DrawLineDestIncrement;
 }
 
 void PicoDoHighPal555M4(void)
@@ -265,7 +269,7 @@ static void FinalizeLineRGB555M4(int line)
 
   // standard FinalizeLine can finish it for us,
   // with features like scaling and such
-  FinalizeLineRGB555(0, line);
+  FinalizeLine555(0, line);
 }
 
 static void FinalizeLine8bitM4(int line)
@@ -278,13 +282,13 @@ static void FinalizeLine8bitM4(int line)
   memcpy32((int *)pd, (int *)(HighCol+8), 256/4);
 }
 
-void PicoDrawSetColorFormatMode4(int which)
+void PicoDrawSetOutputMode4(pdso_t which)
 {
   switch (which)
   {
-    case 2: FinalizeLineM4 = FinalizeLine8bitM4; break;
-    case 1: FinalizeLineM4 = FinalizeLineRGB555M4; break;
-    default:FinalizeLineM4 = NULL; break;
+    case PDF_8BIT:   FinalizeLineM4 = FinalizeLine8bitM4; break;
+    case PDF_RGB555: FinalizeLineM4 = FinalizeLineRGB555M4; break;
+    default:         FinalizeLineM4 = NULL; break;
   }
 }
 

+ 20 - 6
pico/pico.h

@@ -160,13 +160,18 @@ extern void (*PicoCartLoadProgressCB)(int percent);
 extern void (*PicoCDLoadProgressCB)(const char *fname, int percent);
 
 // Draw.c
-void PicoDrawSetColorFormat(int which); // 0=BGR444, 1=RGB555, 2=8bit(HighPal pal)
+// for line-based renderer, set conversion
+// from internal 8 bit representation in 'HighCol' to:
+typedef enum
+{
+	PDF_NONE = 0,    // no conversion
+	PDF_RGB555,      // RGB/BGR output, depends on compile options
+	PDF_8BIT,        // 8-bit out (handles shadow/hilight mode, sonic water)
+} pdso_t;
+void PicoDrawSetOutFormat(pdso_t which, int allow_32x);
+void PicoDrawSetOutBuf(void *dest, int increment);
 extern void *DrawLineDest;
-#if OVERRIDE_HIGHCOL
 extern unsigned char *HighCol;
-#else
-extern unsigned char  HighCol[8+320+8];
-#endif
 extern int (*PicoScanBegin)(unsigned int num);
 extern int (*PicoScanEnd)(unsigned int num);
 // utility
@@ -194,12 +199,21 @@ extern int rendstatus, rendstatus_old;
 extern int rendlines;
 extern unsigned short HighPal[0x100];
 
-// Draw2.c
+// draw.c
+void PicoDrawUpdateHighPal(void);
+void PicoDrawSetInternalBuf(void *dest, int line_increment);
+
+// draw2.c
 // stuff below is optional
 extern unsigned char  *PicoDraw2FB;  // buffer for fast renderer in format (8+320)x(8+224+8) (eights for borders)
 extern unsigned short *PicoCramHigh; // pointer to CRAM buff (0x40 shorts), converted to native device color (works only with 16bit for now)
 extern void (*PicoPrepareCram)();    // prepares PicoCramHigh for renderer to use
 
+// 32x/draw.c
+void PicoDraw32xSetFrameMode(int is_on, int only_32x);
+extern int (*PicoScan32xBegin)(unsigned int num);
+extern int (*PicoScan32xEnd)(unsigned int num);
+
 // sound.c
 extern int PsndRate,PsndLen;
 extern short *PsndOut;

+ 8 - 4
pico/pico_int.h

@@ -474,8 +474,8 @@ typedef struct
 struct Pico32x
 {
   unsigned short regs[0x20];
-  unsigned short vdp_regs[0x10];
-  unsigned short sh2_regs[3];
+  unsigned short vdp_regs[0x10]; // 0x40
+  unsigned short sh2_regs[3];    // 0x60
   unsigned char pending_fb;
   unsigned char dirty_pal;
   unsigned int emu_flags;
@@ -547,10 +547,12 @@ int CM_compareRun(int cyc, int is_sub);
 PICO_INTERNAL void PicoFrameStart(void);
 void PicoDrawSync(int to, int blank_last_line);
 void BackFill(int reg7, int sh);
-void FinalizeLineRGB555(int sh, int line);
+void FinalizeLine555(int sh, int line);
 extern int DrawScanline;
 #define MAX_LINE_SPRITES 29
 extern unsigned char HighLnSpr[240][3 + MAX_LINE_SPRITES];
+extern void *DrawLineDestBase;
+extern int DrawLineDestIncrement;
 
 // draw2.c
 PICO_INTERNAL void PicoFrameFull();
@@ -559,7 +561,7 @@ PICO_INTERNAL void PicoFrameFull();
 void PicoFrameStartMode4(void);
 void PicoLineMode4(int line);
 void PicoDoHighPal555M4(void);
-void PicoDrawSetColorFormatMode4(int which);
+void PicoDrawSetOutputMode4(pdso_t which);
 
 // memory.c
 PICO_INTERNAL void PicoMemSetup(void);
@@ -717,6 +719,8 @@ void p32x_poll_event(int cpu_mask, int is_vdp);
 
 // 32x/draw.c
 void FinalizeLine32xRGB555(int sh, int line);
+void PicoDraw32xLayer(int offs, int lines, int mdbg);
+extern int Pico32xDrawMode;
 
 // 32x/pwm.c
 unsigned int p32x_pwm_read16(unsigned int a);

+ 4 - 0
platform/common/common_arm.mak

@@ -24,6 +24,10 @@ ifeq "$(asm_cdmemory)" "1"
 DEFINES += _ASM_CD_MEMORY_C
 OBJS += pico/cd/memory_arm.o
 endif
+ifeq "$(asm_32xdraw)" "1"
+DEFINES += _ASM_32X_DRAW
+OBJS += pico/32x/draw_arm.o
+endif
 
 
 DIRS += cpu/Cyclone cpu/Cyclone/proj cpu/Cyclone/tools cpu/DrZ80

+ 15 - 21
platform/common/config.c

@@ -10,6 +10,7 @@
 #include <unistd.h>
 #endif
 #include "config.h"
+#include "plat.h"
 #include "input.h"
 #include "lprintf.h"
 
@@ -197,6 +198,7 @@ static int default_var(const menu_entry *me)
 		case MA_OPT2_GAMMA:      return defaultConfig.gamma;
 		case MA_OPT_FRAMESKIP:   return defaultConfig.Frameskip;
 		case MA_OPT_CPU_CLOCKS:  return defaultConfig.CPUclock;
+		case MA_OPT_RENDERER:    return defaultConfig.renderer;
 
 		case MA_OPT_SAVE_SLOT:
 		default:
@@ -217,9 +219,6 @@ static int is_cust_val_default(const menu_entry *me)
 		case MA_OPT_CONFIRM_STATES:
 			return !((defaultConfig.EmuOpt ^ currentConfig.EmuOpt) &
 				(EOPT_CONFIRM_LOAD|EOPT_CONFIRM_SAVE)) == 0;
-		case MA_OPT_RENDERER:
-			return ((defaultConfig.s_PicoOpt ^ PicoOpt) & POPT_ALT_RENDERER) == 0 &&
-				((defaultConfig.EmuOpt ^ currentConfig.EmuOpt) & EOPT_16BPP) == 0;
 		case MA_CDOPT_READAHEAD:
 			return defaultConfig.s_PicoCDBuffers == PicoCDBuffers;
 		default:break;
@@ -468,26 +467,21 @@ int config_readlrom(const char *fname)
 static int custom_read(menu_entry *me, const char *var, const char *val)
 {
 	char *tmp;
-	int tmpi;
+	int i;
 
 	switch (me->id)
 	{
 		case MA_OPT_RENDERER:
-			if (strcasecmp(var, "Renderer") != 0) return 0;
-			if      (strcasecmp(val, "8bit fast") == 0 || strcasecmp(val, "fast") == 0) {
-				PicoOpt |=  POPT_ALT_RENDERER;
-			}
-			else if (strcasecmp(val, "16bit accurate") == 0 || strcasecmp(val, "accurate") == 0) {
-				PicoOpt &= ~POPT_ALT_RENDERER;
-				currentConfig.EmuOpt |=  0x80;
-			}
-			else if (strcasecmp(val, "8bit accurate") == 0) {
-				PicoOpt &= ~POPT_ALT_RENDERER;
-				currentConfig.EmuOpt &= ~0x80;
-			}
-			else
+			if (strcasecmp(var, "Renderer") != 0 || renderer_names == NULL)
 				return 0;
-			return 1;
+
+			for (i = 0; renderer_names[i] != NULL; i++) {
+				if (strcasecmp(val, renderer_names[i]) == 0) {
+					currentConfig.renderer = i;
+					return 1;
+				}
+			}
+			return 0;
 
 		case MA_OPT_SCALING:
 #ifdef __GP2X__
@@ -589,9 +583,9 @@ static int custom_read(menu_entry *me, const char *var, const char *val)
 
 		case MA_OPT2_SQUIDGEHACK:
 			if (strcasecmp(var, "Squidgehack") != 0) return 0;
-			tmpi = atoi(val);
-			if (tmpi) *(int *)me->var |=  me->mask;
-			else      *(int *)me->var &= ~me->mask;
+			i = atoi(val);
+			if (i) *(int *)me->var |=  me->mask;
+			else   *(int *)me->var &= ~me->mask;
 			return 1;
 
 		case MA_CDOPT_READAHEAD:

+ 15 - 19
platform/common/emu.c

@@ -1116,7 +1116,7 @@ static void emu_tray_close(void)
 
 void emu_32x_startup(void)
 {
-	plat_video_toggle_renderer(0, 1, 0);
+	plat_video_toggle_renderer(0, 0);
 	system_announce();
 }
 
@@ -1247,9 +1247,9 @@ static void run_events_ui(unsigned int which)
 			PicoStateProgressCB = NULL;
 		}
 	}
-	if ((which & PEV_SWITCH_RND) && !(PicoAHW & PAHW_32X))
+	if (which & PEV_SWITCH_RND)
 	{
-		plat_video_toggle_renderer(1, 0, 0);
+		plat_video_toggle_renderer(1, 0);
 	}
 	if (which & (PEV_SSLOT_PREV|PEV_SSLOT_NEXT))
 	{
@@ -1493,17 +1493,15 @@ void emu_loop(void)
 		{
 			if ((currentConfig.EmuOpt & EOPT_NO_FRMLIMIT) && currentConfig.Frameskip >= 0)
 				pframes_done = 0;
-			else {
+			else
 				pframes_done -= target_fps;
-				/* don't allow it to drift during heavy slowdowns */
-				if (pframes_done < -5) {
-					reset_timing = 1;
-					continue;
-				}
-				if (pframes_done < -2)
-					pframes_done = -2;
+			if (pframes_done < -2) {
+				/* don't drag more than 2 frames behind */
+				pframes_done = -2;
+				timestamp_base = timestamp - 2 * target_frametime;
 			}
-			timestamp_base += ms_to_ticks(1000);
+			else
+				timestamp_base += ms_to_ticks(1000);
 		}
 
 		diff = timestamp - timestamp_base;
@@ -1528,15 +1526,13 @@ void emu_loop(void)
 		else if (diff > diff_lim)
 		{
 			/* no time left for this frame - skip */
-			if (diff - diff_lim >= ms_to_ticks(200)) {
-				/* if too much behind, reset instead */
-				reset_timing = 1;
+			/* limit auto frameskip to 8 */
+			if (frames_done / 8 <= frames_shown) {
+				emu_update_input();
+				skip_frame(diff < diff_lim + target_frametime * 16);
+				pframes_done++; frames_done++;
 				continue;
 			}
-			emu_update_input();
-			skip_frame(diff < diff_lim + target_frametime * 2);
-			pframes_done++; frames_done++;
-			continue;
 		}
 
 		emu_update_input();

+ 3 - 1
platform/common/emu.h

@@ -28,7 +28,7 @@ extern int g_screen_height;
 #define EOPT_GZIP_SAVES   (1<<3)
 #define EOPT_MMUHACK      (1<<4)
 #define EOPT_NO_AUTOSVCFG (1<<5)
-#define EOPT_16BPP        (1<<7)
+#define EOPT_16BPP        (1<<7)  // depreceted for .renderer
 #define EOPT_RAM_TIMINGS  (1<<8)
 #define EOPT_CONFIRM_SAVE (1<<9)
 #define EOPT_EN_CD_LEDS   (1<<10)
@@ -67,6 +67,8 @@ typedef struct _currentConfig_t {
 	float hscale32, hscale40; // psp: horizontal scale
 	int gamma2;  // psp: black level
 	int turbo_rate;
+	int renderer;
+	int renderer32x;
 } currentConfig_t;
 
 extern currentConfig_t currentConfig, defaultConfig;

+ 44 - 7
platform/common/menu.c

@@ -603,7 +603,6 @@ static void me_loop(menu_entry *menu, int *menu_sel, void (*draw_more)(void))
 #else
 #define MENU_OPTIONS_GFX
 #define MENU_OPTIONS_ADV
-#define mgn_opt_renderer NULL /* TODO */
 #define menu_main_plat_draw NULL
 #endif
 
@@ -1494,16 +1493,47 @@ static int menu_loop_cd_options(menu_id id, int keys)
 
 // ------------ 32X options menu ------------
 
+static const char *get_rname(const char **rn, int val, int *offs)
+{
+	int i, len, found = -1, maxlen = 0;
+
+	for (i = 0; rn[i] != NULL; i++) {
+		len = strlen(rn[i]);
+		if (len > maxlen)
+			maxlen = len;
+		if (i == val)
+			found = i;
+	}
+
+	*offs = 3 - maxlen;
+	if (found >= 0)
+		return rn[found];
+	return "???";
+}
+
+static const char *mgn_opt_renderer32x(menu_id id, int *offs)
+{
+	return get_rname(renderer_names32x, currentConfig.renderer32x, offs);
+}
+
 static menu_entry e_menu_32x_options[] =
 {
-	mee_onoff("32X enabled",          MA_32XOPT_ENABLE_32X,   PicoOpt, POPT_EN_32X),
-	mee_onoff("PWM sound",            MA_32XOPT_PWM,          PicoOpt, POPT_EN_PWM),
+	mee_onoff     ("32X enabled",  MA_32XOPT_ENABLE_32X, PicoOpt, POPT_EN_32X),
+	mee_range_cust("32X renderer", MA_32XOPT_RENDERER,   currentConfig.renderer32x, 0, 0, mgn_opt_renderer32x),
+	mee_onoff     ("PWM sound",    MA_32XOPT_PWM,        PicoOpt, POPT_EN_PWM),
 	mee_end,
 };
 
 static int menu_loop_32x_options(menu_id id, int keys)
 {
 	static int sel = 0;
+	int i, c;
+
+	for (c = 0; renderer_names32x != NULL && renderer_names32x[c] != NULL; )
+		c++;
+	i = me_id2offset(e_menu_32x_options, MA_32XOPT_RENDERER);
+	e_menu_32x_options[i].max = c > 0 ? (c - 1) : 0;
+
 	me_loop(e_menu_32x_options, &sel, NULL);
 	return 0;
 }
@@ -1534,15 +1564,14 @@ static int menu_loop_adv_options(menu_id id, int keys)
 
 // ------------ gfx options menu ------------
 
-static int mh_opt_render(menu_id id, int keys)
+static const char *mgn_opt_renderer(menu_id id, int *offs)
 {
-	plat_video_toggle_renderer((keys & PBTN_RIGHT) ? 1 : 0, 0, 1);
-	return 0;
+	return get_rname(renderer_names, currentConfig.renderer, offs);
 }
 
 static menu_entry e_menu_gfx_options[] =
 {
-	mee_cust      ("Renderer",                 MA_OPT_RENDERER,       mh_opt_render, mgn_opt_renderer),
+	mee_range_cust("Renderer", MA_OPT_RENDERER,   currentConfig.renderer, 0, 0, mgn_opt_renderer),
 	MENU_OPTIONS_GFX
 	mee_end,
 };
@@ -1550,6 +1579,14 @@ static menu_entry e_menu_gfx_options[] =
 static int menu_loop_gfx_options(menu_id id, int keys)
 {
 	static int sel = 0;
+	int i, c;
+
+	for (c = 0; renderer_names != NULL && renderer_names[c] != NULL; )
+		c++;
+	i = me_id2offset(e_menu_gfx_options, MA_OPT_RENDERER);
+	e_menu_gfx_options[i].max = c > 0 ? (c - 1) : 0;
+	me_enable(e_menu_gfx_options, MA_OPT_RENDERER, renderer_names != NULL);
+
 	me_loop(e_menu_gfx_options, &sel, NULL);
 	return 0;
 }

+ 1 - 0
platform/common/menu.h

@@ -86,6 +86,7 @@ typedef enum
 	MA_CDOPT_BETTER_SYNC,
 	MA_CDOPT_DONE,
 	MA_32XOPT_ENABLE_32X,
+	MA_32XOPT_RENDERER,
 	MA_32XOPT_PWM,
 	MA_CTRL_PLAYER1,
 	MA_CTRL_PLAYER2,

+ 3 - 1
platform/common/plat.h

@@ -4,6 +4,8 @@ extern "C" {
 
 /* stuff to be implemented by platform code */
 extern char cpu_clk_name[];
+extern const char **renderer_names;
+extern const char **renderer_names32x;
 
 void pemu_prep_defconfig(void);
 void pemu_validate_config(void);
@@ -35,7 +37,7 @@ void plat_video_menu_end(void);
 
 void plat_video_flip(void);
 void plat_video_wait_vsync(void);
-void plat_video_toggle_renderer(int is_next, int force_16bpp, int is_menu);
+void plat_video_toggle_renderer(int change, int menu_call);
 
 void plat_update_volume(int has_changed, int is_up);
 

+ 3 - 3
platform/gizmondo/emu.c

@@ -230,10 +230,10 @@ static void vidResetMode(void)
 
 	if (PicoOpt&0x10) {
 	} else if (currentConfig.EmuOpt&0x80) {
-		PicoDrawSetColorFormat(1);
+		PicoDrawSetOutFormat(PDF_RGB555, 0);
 		PicoScanBegin = EmuScanBegin16;
 	} else {
-		PicoDrawSetColorFormat(-1);
+		PicoDrawSetOutFormat(PDF_NONE, 0);
 		PicoScanBegin = EmuScanBegin8;
 	}
 	if ((PicoOpt&0x10) || !(currentConfig.EmuOpt&0x80)) {
@@ -306,7 +306,7 @@ void pemu_forced_frame(int opts)
 	if (giz_screen == NULL)
 		giz_screen = fb_lock(1);
 
-	PicoDrawSetColorFormat(1);
+	PicoDrawSetOutFormat(PDF_RGB555, 0);
 	PicoScanBegin = EmuScanBegin16;
 	Pico.m.dirtyPal = 1;
 	PicoFrameDrawOnly();

+ 0 - 3
platform/gizmondo/port_config.h

@@ -12,9 +12,6 @@
 #define SCREEN_WIDTH  321
 #define SCREEN_HEIGHT 240
 
-// draw.c
-#define OVERRIDE_HIGHCOL 1
-
 // draw2.c
 #define START_ROW  0 // which row of tiles to start rendering at?
 #define END_ROW   28 // ..end

+ 0 - 1
platform/gizmondo/port_config.s

@@ -6,7 +6,6 @@
 .equiv START_ROW,               0
 .equiv END_ROW,                28
 
-.equiv OVERRIDE_HIGHCOL,        1
 .equiv UNALIGNED_DRAWLINEDEST,  1
 
 @ this should be set to one only for GP2X port

+ 1 - 0
platform/gp2x/Makefile

@@ -13,6 +13,7 @@ asm_ym2612 = 1
 asm_misc = 1
 asm_cdpico = 1
 asm_cdmemory = 1
+asm_32xdraw = 1
 #profile = 1
 #drc_debug = 3
 

+ 131 - 89
platform/gp2x/emu.c

@@ -1,7 +1,15 @@
-// (c) Copyright 2006-2009 notaz, All rights reserved.
-// Free for non-commercial use.
-
-// For commercial use, separate licencing terms must be obtained.
+/*
+ * (c) Copyright 2006-2010 notaz, All rights reserved.
+ *
+ * For performance reasons 3 renderers are exported for both MD and 32x modes:
+ * - 16bpp line renderer
+ * - 8bpp line renderer (slightly faster)
+ * - 8bpp tile renderer
+ * In 32x mode:
+ * - 32x layer is overlayed on top of 16bpp one
+ * - line internal one done on PicoDraw2FB, then mixed with 32x
+ * - tile internal one done on PicoDraw2FB, then mixed with 32x
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -37,6 +45,11 @@ static short __attribute__((aligned(4))) sndBuffer[2*(44100+100)/50];
 static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)];
 unsigned char *PicoDraw2FB = PicoDraw2FB_;
 static int osd_fps_x, osd_y;
+const char *renderer_names_[] = { "16bit accurate", " 8bit accurate", "     8bit fast", NULL };
+const char *renderer_names32x_[] = { "accurate", "faster  ", "fastest ", NULL };
+const char **renderer_names = renderer_names_;
+const char **renderer_names32x = renderer_names32x_;
+enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT };
 
 extern void *gp2x_screens[4];
 
@@ -62,6 +75,7 @@ void pemu_prep_defconfig(void)
 	gp2x_soc_t soc;
 
 	defaultConfig.CPUclock = default_cpu_clock;
+	defaultConfig.renderer32x = RT_8BIT_FAST;
 
 	soc = soc_detect();
 	if (soc == SOCID_MMSP2)
@@ -87,6 +101,31 @@ void pemu_validate_config(void)
 		currentConfig.CPUclock = default_cpu_clock;
 }
 
+static int get_renderer(void)
+{
+	if (PicoAHW & PAHW_32X)
+		return currentConfig.renderer32x;
+	else
+		return currentConfig.renderer;
+}
+
+static void change_renderer(int diff)
+{
+	int *r;
+	if (PicoAHW & PAHW_32X)
+		r = &currentConfig.renderer32x;
+	else
+		r = &currentConfig.renderer;
+	*r += diff;
+	if      (*r >= RT_COUNT)
+		*r = 0;
+	else if (*r < 0)
+		*r = RT_COUNT - 1;
+}
+
+#define is_16bit_mode() \
+	(get_renderer() == RT_16BIT || (PicoAHW & PAHW_32X))
+
 static void (*osd_text)(int x, int y, const char *text);
 
 static void osd_text8(int x, int y, const char *text)
@@ -160,7 +199,7 @@ static void draw_cd_leds(void)
 		scr_offs = pitch * 2 + 4;
 	}
 
-	if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP)) {
+	if (!is_16bit_mode()) {
 	#define p(x) px[(x) >> 2]
 		// 8-bit modes
 		unsigned int *px = (unsigned int *)((char *)g_screen_ptr + scr_offs);
@@ -187,7 +226,7 @@ static void draw_pico_ptr(void)
 	int x, y, pitch = 320;
 
 	// only if pen enabled and for 16bit modes
-	if (pico_inp_mode == 0 || (PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP))
+	if (pico_inp_mode == 0 || currentConfig.EmuOpt != RT_16BIT)
 		return;
 
 	x = pico_pen_x + PICO_PEN_ADJUST_X;
@@ -208,20 +247,6 @@ static void draw_pico_ptr(void)
 	p[pitch*2] ^= 0xffff;
 }
 
-static int EmuScanBegin16(unsigned int num)
-{
-	DrawLineDest = (unsigned short *) g_screen_ptr + g_screen_width * num;
-
-	return 0;
-}
-
-static int EmuScanBegin8(unsigned int num)
-{
-	DrawLineDest = (unsigned char *)  g_screen_ptr + g_screen_width * num;
-
-	return 0;
-}
-
 /* rot thing for Wiz */
 static unsigned char __attribute__((aligned(4))) rot_buff[320*4*2];
 
@@ -307,7 +332,9 @@ void pemu_finalize_frame(const char *fps, const char *notice)
 	int emu_opt = currentConfig.EmuOpt;
 	int ret;
 
-	if (PicoOpt & POPT_ALT_RENDERER)
+	if (PicoAHW & PAHW_32X)
+		; // nothing to do
+	else if (get_renderer() == RT_8BIT_FAST)
 	{
 		// 8bit fast renderer
 		if (Pico.m.dirtyPal) {
@@ -323,7 +350,7 @@ void pemu_finalize_frame(const char *fps, const char *notice)
 		vidcpyM2(g_screen_ptr, PicoDraw2FB+328*8,
 			!(Pico.video.reg[12] & 1), !(PicoOpt & POPT_DIS_32C_BORDER));
 	}
-	else if (!(emu_opt & EOPT_16BPP))
+	else if (get_renderer() == RT_8BIT_ACC)
 	{
 		// 8bit accurate renderer
 		if (Pico.m.dirtyPal)
@@ -348,7 +375,12 @@ void pemu_finalize_frame(const char *fps, const char *notice)
 
 void plat_video_flip(void)
 {
+	int stride = g_screen_width;
 	gp2x_video_flip();
+
+	if (is_16bit_mode())
+		stride *= 2;
+	PicoDrawSetOutBuf(g_screen_ptr, stride);
 }
 
 /* XXX */
@@ -385,7 +417,7 @@ void plat_video_wait_vsync(void)
 
 void plat_status_msg_clear(void)
 {
-	int is_8bit = (PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP);
+	int is_8bit = !is_16bit_mode();
 	if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
 		/* ugh.. */
 		int i, u, *p;
@@ -431,47 +463,78 @@ void plat_status_msg_busy_first(const char *msg)
 
 static void vidResetMode(void)
 {
+	int gp2x_mode = 16;
+	int renderer = get_renderer();
+
+	PicoScanBegin = NULL;
 	PicoScanEnd = NULL;
 
-	if (PicoOpt & POPT_ALT_RENDERER) {
-		if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
-			gp2x_video_changemode(-8);
-			vidcpyM2 = vidcpy_m2_rot;
-			osd_text = osd_text8_rot;
-		} else {
-			gp2x_video_changemode(8);
-			vidcpyM2 = vidcpy_m2;
-			osd_text = osd_text8;
-		}
-	}
-	else if (currentConfig.EmuOpt & EOPT_16BPP) {
-		PicoDrawSetColorFormat(1);
+	switch (renderer) {
+	case RT_16BIT:
+		PicoOpt &= ~POPT_ALT_RENDERER;
+		PicoDrawSetOutFormat(PDF_RGB555, 0);
+		PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
 		if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
-			gp2x_video_changemode(-16);
 			PicoScanBegin = EmuScanBegin16_rot;
 			PicoScanEnd = EmuScanEnd16_rot;
-			osd_text = osd_text16_rot;
-		} else {
-			gp2x_video_changemode(16);
-			PicoScanBegin = EmuScanBegin16;
-			osd_text = osd_text16;
 		}
-	}
-	else {
-		PicoDrawSetColorFormat(2);
+		break;
+	case RT_8BIT_ACC:
+		PicoOpt &= ~POPT_ALT_RENDERER;
+		PicoDrawSetOutFormat(PDF_8BIT, 0);
+		PicoDrawSetOutBuf(g_screen_ptr, g_screen_width);
 		if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
-			gp2x_video_changemode(-8);
 			PicoScanBegin = EmuScanBegin8_rot;
 			PicoScanEnd = EmuScanEnd8_rot;
-			osd_text = osd_text8_rot;
-		} else {
-			gp2x_video_changemode(8);
-			PicoScanBegin = EmuScanBegin8;
-			osd_text = osd_text8;
 		}
+		gp2x_mode = 8;
+		break;
+	case RT_8BIT_FAST:
+		PicoOpt |=  POPT_ALT_RENDERER;
+		PicoDrawSetOutFormat(PDF_NONE, 0);
+		if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)
+			vidcpyM2 = vidcpy_m2_rot;
+		else
+			vidcpyM2 = vidcpy_m2;
+		gp2x_mode = 8;
+		break;
 	}
 
-	if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP)) {
+	if (is_16bit_mode())
+		osd_text = (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) ? osd_text16_rot : osd_text16;
+	else
+		osd_text = (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) ? osd_text8_rot : osd_text8;
+
+	if (PicoAHW & PAHW_32X) {
+		// rules change in 32X world
+		if (renderer != RT_16BIT) {
+			PicoDrawSetOutFormat(PDF_NONE, 0);
+			PicoScanBegin = NULL;
+			PicoScanEnd = NULL;
+		}
+		PicoScan32xBegin = NULL;
+		PicoScan32xEnd = NULL;
+		if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX) {
+			PicoScan32xBegin = EmuScanBegin16_rot;
+			PicoScan32xEnd = EmuScanEnd16_rot;
+		}
+		// Wiz 16bit is an exception, uses line rendering due to rotation mess
+		if (renderer == RT_16BIT && (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)) {
+			PicoDrawSetOutFormat(PDF_RGB555, 1);
+			PicoDraw32xSetFrameMode(0, 0);
+		}
+		else {
+			PicoDraw32xSetFrameMode(1, (renderer == RT_16BIT) ? 1 : 0);
+		}
+		PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
+		gp2x_mode = 16;
+	}
+
+	if (currentConfig.EmuOpt & EOPT_WIZ_TEAR_FIX)
+		gp2x_mode = -gp2x_mode;
+	gp2x_video_changemode(gp2x_mode);
+
+	if (!is_16bit_mode()) {
 		// setup pal for 8-bit modes
 		localPal[0xc0] = 0x0000c000; // MCD LEDs
 		localPal[0xd0] = 0x00c00000;
@@ -492,41 +555,20 @@ static void vidResetMode(void)
 	make_local_pal = (PicoAHW & PAHW_SMS) ? make_local_pal_sms : make_local_pal_md;
 }
 
-void plat_video_toggle_renderer(int is_next, int force_16bpp, int is_menu)
+void plat_video_toggle_renderer(int change, int is_menu_call)
 {
-	if (force_16bpp) {
-		PicoOpt &= ~POPT_ALT_RENDERER;
-		currentConfig.EmuOpt |= EOPT_16BPP;
-	}
-	/* alt, 16bpp, 8bpp */
-	else if (PicoOpt & POPT_ALT_RENDERER) {
-		PicoOpt &= ~POPT_ALT_RENDERER;
-		if (is_next)
-			currentConfig.EmuOpt |= EOPT_16BPP;
-	} else if (!(currentConfig.EmuOpt & EOPT_16BPP)) {
-		if (is_next)
-			PicoOpt |= POPT_ALT_RENDERER;
-		else
-			currentConfig.EmuOpt |= EOPT_16BPP;
-	} else {
-		currentConfig.EmuOpt &= ~EOPT_16BPP;
-		if (!is_next)
-			PicoOpt |= POPT_ALT_RENDERER;
-	}
+	change_renderer(change);
 
-	if (is_menu)
+	if (is_menu_call)
 		return;
 
 	vidResetMode();
 	rendstatus_old = -1;
 
-	if (PicoOpt & POPT_ALT_RENDERER) {
-		emu_status_msg(" 8bit fast renderer");
-	} else if (currentConfig.EmuOpt & EOPT_16BPP) {
-		emu_status_msg("16bit accurate renderer");
-	} else {
-		emu_status_msg(" 8bit accurate renderer");
-	}
+	if (PicoAHW & PAHW_32X)
+		emu_status_msg(renderer_names32x[get_renderer()]);
+	else
+		emu_status_msg(renderer_names[get_renderer()]);
 }
 
 #if 0 // TODO
@@ -695,20 +737,19 @@ void pemu_sound_wait(void)
 void pemu_forced_frame(int opts)
 {
 	int po_old = PicoOpt;
-	int eo_old = currentConfig.EmuOpt;
 
 	PicoOpt &= ~POPT_ALT_RENDERER;
 	PicoOpt |= opts|POPT_ACC_SPRITES;
-	currentConfig.EmuOpt |= EOPT_16BPP;
 
-	PicoDrawSetColorFormat(1);
-	PicoScanBegin = EmuScanBegin16;
+	PicoDrawSetOutFormat(PDF_RGB555, 1);
+	PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
+	PicoDraw32xSetFrameMode(0, 0);
+	PicoScanBegin = NULL;
 	PicoScanEnd = NULL;
 	Pico.m.dirtyPal = 1;
 	PicoFrameDrawOnly();
 
 	PicoOpt = po_old;
-	currentConfig.EmuOpt = eo_old;
 }
 
 void plat_debug_cat(char *str)
@@ -733,7 +774,7 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
 		gp2x_video_RGB_setscaling(0, scalex, 240);
 
 	// clear whole screen in all buffers
-	if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP))
+	if (!is_16bit_mode())
 		gp2x_memset_all_buffers(0, 0xe0, 320*240);
 	else
 		gp2x_memset_all_buffers(0, 0, 320*240*2);
@@ -848,11 +889,12 @@ void pemu_loop_end(void)
 	/* do one more frame for menu bg */
 	PicoOpt &= ~POPT_ALT_RENDERER;
 	PicoOpt |= POPT_EN_SOFTSCALE|POPT_ACC_SPRITES;
-	currentConfig.EmuOpt |= EOPT_16BPP;
 
-	PicoScanBegin = EmuScanBegin16;
+	PicoDrawSetOutFormat(PDF_RGB555, 1);
+	PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
+	PicoDraw32xSetFrameMode(0, 0);
+	PicoScanBegin = NULL;
 	PicoScanEnd = NULL;
-	PicoDrawSetColorFormat(1);
 	Pico.m.dirtyPal = 1;
 	PicoFrame();
 

+ 0 - 11
platform/gp2x/menu.c

@@ -53,17 +53,6 @@ static void menu_main_plat_draw(void)
 
 // ------------ gfx options menu ------------
 
-static const char *mgn_opt_renderer(menu_id id, int *offs)
-{
-	*offs = -11;
-	if (PicoOpt & POPT_ALT_RENDERER)
-		return "     8bit fast";
-	else if (currentConfig.EmuOpt & EOPT_16BPP)
-		return "16bit accurate";
-	else
-		return " 8bit accurate";
-}
-
 static const char *mgn_opt_scaling(menu_id id, int *offs)
 {
 	*offs = -13;

+ 0 - 3
platform/gp2x/port_config.h

@@ -12,9 +12,6 @@
 #define SCREEN_WIDTH  320
 #define SCREEN_HEIGHT 240
 
-// draw.c
-#define OVERRIDE_HIGHCOL 0
-
 // draw2.c
 #define START_ROW  0 // which row of tiles to start rendering at?
 #define END_ROW   28 // ..end

+ 0 - 1
platform/gp2x/port_config.s

@@ -6,7 +6,6 @@
 .equiv START_ROW,               0
 .equiv END_ROW,                28
 
-.equiv OVERRIDE_HIGHCOL,        0
 .equiv UNALIGNED_DRAWLINEDEST,  0
 
 @ this should be set to one only for GP2X port

+ 65 - 18
platform/linux/emu.c

@@ -18,6 +18,11 @@
 
 static short __attribute__((aligned(4))) sndBuffer[2*44100/50];
 char cpu_clk_name[] = "unused";
+const char *renderer_names_[] = { "16bit accurate", " 8bit accurate", "     8bit fast", NULL };
+const char *renderer_names32x_[] = { "accurate", "faster  ", "fastest ", NULL };
+const char **renderer_names = renderer_names_;
+const char **renderer_names32x = renderer_names32x_;
+enum renderer_types { RT_16BIT, RT_8BIT_ACC, RT_8BIT_FAST, RT_COUNT };
 
 
 void pemu_prep_defconfig(void)
@@ -75,7 +80,7 @@ static void draw_cd_leds(void)
 	led_offs = 4;
 	scr_offs = pitch * 2 + 4;
 
-	if ((PicoOpt & POPT_ALT_RENDERER) || !(currentConfig.EmuOpt & EOPT_16BPP)) {
+	if (currentConfig.renderer != RT_16BIT) {
 	#define p(x) px[(x) >> 2]
 		// 8-bit modes
 		unsigned int *px = (unsigned int *)((char *)g_screen_ptr + scr_offs);
@@ -96,15 +101,20 @@ static void draw_cd_leds(void)
 	}
 }
 
-static int EmuScanBegin16(unsigned int num)
-{
-	DrawLineDest = (unsigned short *)g_screen_ptr + num * g_screen_width;
-
-	return 0;
-}
-
 void pemu_finalize_frame(const char *fps, const char *notice)
 {
+	if (currentConfig.renderer != RT_16BIT && !(PicoAHW & PAHW_32X)) {
+		unsigned short *pd = (unsigned short *)g_screen_ptr + 8 * g_screen_width;
+		unsigned char *ps = PicoDraw2FB + 328*8 + 8;
+		unsigned short *pal = HighPal;
+		int i, x;
+		if (Pico.m.dirtyPal)
+			PicoDrawUpdateHighPal();
+		for (i = 0; i < 224; i++, ps += 8)
+			for (x = 0; x < 320; x++)
+				*pd++ = pal[*ps++];
+	}
+
 	if (notice || (currentConfig.EmuOpt & EOPT_SHOW_FPS)) {
 		if (notice)
 			osd_text(4, g_screen_height - 8, notice);
@@ -115,10 +125,51 @@ void pemu_finalize_frame(const char *fps, const char *notice)
 		draw_cd_leds();
 }
 
-void plat_video_toggle_renderer(int is_next, int force_16bpp, int is_menu)
+static void apply_renderer(void)
+{
+	PicoScanBegin = NULL;
+	PicoScanEnd = NULL;
+
+	switch (currentConfig.renderer) {
+	case RT_16BIT:
+		PicoOpt &= ~POPT_ALT_RENDERER;
+		PicoDrawSetOutFormat(PDF_RGB555, 0);
+		PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
+		break;
+	case RT_8BIT_ACC:
+		PicoOpt &= ~POPT_ALT_RENDERER;
+		PicoDrawSetOutFormat(PDF_8BIT, 0);
+		PicoDrawSetOutBuf(PicoDraw2FB + 8, 328);
+		break;
+	case RT_8BIT_FAST:
+		PicoOpt |=  POPT_ALT_RENDERER;
+		PicoDrawSetOutFormat(PDF_NONE, 0);
+		break;
+	}
+
+	if (PicoAHW & PAHW_32X) {
+		int only_32x = 0;
+		if (currentConfig.renderer == RT_16BIT)
+			only_32x = 1;
+		else
+			PicoDrawSetOutFormat(PDF_NONE, 0);
+		PicoDraw32xSetFrameMode(1, only_32x);
+		PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
+	}
+}
+
+void plat_video_toggle_renderer(int change, int is_menu)
 {
-	// this will auto-select SMS/32X renderers
-	PicoDrawSetColorFormat(1);
+	currentConfig.renderer += change;
+	if      (currentConfig.renderer >= RT_COUNT)
+		currentConfig.renderer = 0;
+	else if (currentConfig.renderer < 0)
+		currentConfig.renderer = RT_COUNT - 1;
+
+	if (!is_menu)
+		apply_renderer();
+
+	emu_status_msg(renderer_names[currentConfig.renderer]);
 }
 
 void plat_video_menu_enter(int is_rom_loaded)
@@ -168,10 +219,8 @@ void pemu_forced_frame(int opts)
 
 	PicoOpt &= ~POPT_ALT_RENDERER;
 	PicoOpt |= opts|POPT_ACC_SPRITES; // acc_sprites
-	currentConfig.EmuOpt |= EOPT_16BPP;
 
-	PicoDrawSetColorFormat(1);
-	PicoScanBegin = EmuScanBegin16;
+	PicoDrawSetOutFormat(PDF_RGB555, 0);
 
 	Pico.m.dirtyPal = 1;
 	PicoFrameDrawOnly();
@@ -244,8 +293,7 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
 
 void pemu_loop_prep(void)
 {
-	PicoDrawSetColorFormat(1);
-	PicoScanBegin = EmuScanBegin16;
+	apply_renderer();
 	osd_text = osd_text16;
 
 	pemu_sound_start();
@@ -262,9 +310,8 @@ void pemu_loop_end(void)
 	/* do one more frame for menu bg */
 	PicoOpt &= ~POPT_ALT_RENDERER;
 	PicoOpt |= POPT_EN_SOFTSCALE|POPT_ACC_SPRITES;
-	currentConfig.EmuOpt |= EOPT_16BPP;
 
-	PicoDrawSetColorFormat(1);
+	PicoDrawSetOutFormat(PDF_RGB555, 0);
 	Pico.m.dirtyPal = 1;
 	PicoFrame();
 

+ 0 - 3
platform/linux/port_config.h

@@ -13,9 +13,6 @@
 #define SCREEN_WIDTH  320
 #define SCREEN_HEIGHT 240
 
-// draw.c
-#define OVERRIDE_HIGHCOL 0
-
 // draw2.c
 #define START_ROW  0 // which row of tiles to start rendering at?
 #define END_ROW   28 // ..end

+ 10 - 11
platform/pandora/emu.c

@@ -23,6 +23,8 @@
 static short __attribute__((aligned(4))) sndBuffer[2*44100/50];
 static unsigned char temp_frame[g_screen_width * g_screen_height * 2];
 unsigned char *PicoDraw2FB = temp_frame;
+const char **renderer_names = NULL;
+const char **renderer_names32x = NULL;
 char cpu_clk_name[] = "unused";
 
 
@@ -43,7 +45,7 @@ static void osd_text(int x, int y, const char *text)
 {
 	int len = strlen(text)*8;
 
-	if ((PicoOpt&0x10)||!(currentConfig.EmuOpt&0x80)) {
+	if (0) {
 		int *p, i, h;
 		x &= ~3; // align x
 		len = (len+3) >> 2;
@@ -71,7 +73,7 @@ static void draw_cd_leds(void)
 //	if (!((Pico_mcd->s68k_regs[0] ^ old_reg) & 3)) return; // no change // mmu hack problems?
 	old_reg = Pico_mcd->s68k_regs[0];
 
-	if ((PicoOpt&0x10)||!(currentConfig.EmuOpt&0x80)) {
+	if (0) {
 		// 8-bit modes
 		unsigned int col_g = (old_reg & 2) ? 0xc0c0c0c0 : 0xe0e0e0e0;
 		unsigned int col_r = (old_reg & 1) ? 0xd0d0d0d0 : 0xe0e0e0e0;
@@ -183,10 +185,10 @@ void pemu_finalize_frame(const char *fps, const char *notice)
 		draw_cd_leds();
 }
 
-void plat_video_toggle_renderer(int is_next, int force_16bpp, int is_menu)
+void plat_video_toggle_renderer(int change, int is_menu)
 {
 	// this will auto-select SMS/32X renderers
-	PicoDrawSetColorFormat(1);
+	PicoDrawSetOutFormat(PDF_RGB555, 1);
 }
 
 void plat_video_menu_enter(int is_rom_loaded)
@@ -251,17 +253,14 @@ void plat_update_volume(int has_changed, int is_up)
 void pemu_forced_frame(int opts)
 {
 	int po_old = PicoOpt;
-	int eo_old = currentConfig.EmuOpt;
 
 	PicoOpt &= ~0x10;
 	PicoOpt |= opts|POPT_ACC_SPRITES; // acc_sprites
-	currentConfig.EmuOpt |= 0x80;
 
 	Pico.m.dirtyPal = 1;
 	PicoFrameDrawOnly();
 
 	PicoOpt = po_old;
-	currentConfig.EmuOpt = eo_old;
 }
 
 static void updateSound(int len)
@@ -339,16 +338,16 @@ void emu_video_mode_change(int start_line, int line_count, int is_32cols)
 		memset32(fbdev_buffers[i], 0, g_screen_width * g_screen_height * 2 / 4);
 
 #ifdef USE_320_SCREEN
-	PicoDrawSetColorFormat(1);
+	PicoDrawSetOutFormat(PDF_RGB555, 1);
 	PicoScanBegin = EmuScanBegin16;
 #else
 	if (PicoAHW & PAHW_32X) {
 		DrawLineDest = (unsigned short *)temp_frame;
-		PicoDrawSetColorFormat(1);
+		PicoDrawSetOutFormat(PDF_RGB555, 1);
 		PicoScanBegin = NULL;
 		PicoScanEnd = EmuScanEnd16_32x;
 	} else {
-		PicoDrawSetColorFormat(-1);
+		PicoDrawSetOutFormat(PDF_NONE, 0);
 		PicoScanBegin = NULL;
 		PicoScanEnd = EmuScanEnd16;
 	}
@@ -374,7 +373,7 @@ void pemu_loop_end(void)
 	PicoOpt |= POPT_EN_SOFTSCALE|POPT_ACC_SPRITES;
 	currentConfig.EmuOpt |= EOPT_16BPP;
 
-	PicoDrawSetColorFormat(1);
+	PicoDrawSetOutFormat(PDF_RGB555, 1);
 	Pico.m.dirtyPal = 1;
 	PicoFrame();
 

+ 0 - 1
platform/pandora/menu.c

@@ -6,4 +6,3 @@
 	mee_onoff     ("Status line in main menu", MA_OPT2_STATUS_LINE,   currentConfig.EmuOpt, EOPT_SHOW_RTC),
 
 #define menu_main_plat_draw NULL
-#define mgn_opt_renderer NULL

+ 0 - 3
platform/pandora/port_config.h

@@ -11,9 +11,6 @@
 #define SCREEN_WIDTH  800
 #define SCREEN_HEIGHT 480
 
-// draw.c
-#define OVERRIDE_HIGHCOL 0
-
 // draw2.c
 #define START_ROW  0 // which row of tiles to start rendering at?
 #define END_ROW   28 // ..end

+ 0 - 1
platform/pandora/port_config.s

@@ -6,7 +6,6 @@
 .equiv START_ROW,               0
 .equiv END_ROW,                28
 
-.equiv OVERRIDE_HIGHCOL,        0
 .equiv UNALIGNED_DRAWLINEDEST,  0
 
 @ this should be set to one only for GP2X port

+ 2 - 2
platform/psp/emu.c

@@ -465,7 +465,7 @@ static void vidResetMode(void)
 	sceGuTexImage(0,512,512,512,(char *)VRAM_STUFF + 16);
 
 	// slow rend.
-	PicoDrawSetColorFormat(-1);
+	PicoDrawSetOutFormat(PDF_NONE, 0);
 	PicoScanBegin = EmuScanSlowBegin;
 	PicoScanEnd = EmuScanSlowEnd;
 
@@ -682,7 +682,7 @@ void pemu_forced_frame(int opts)
 	memset32((int *)VRAM_CACHED_STUFF + 512*232/4, 0xe0e0e0e0, 512*8/4);
 	memset32_uncached((int *)psp_screen + 512*264*2/4, 0, 512*8*2/4);
 
-	PicoDrawSetColorFormat(-1);
+	PicoDrawSetOutFormat(PDF_NONE, 0);
 	PicoScanBegin = EmuScanSlowBegin;
 	PicoScanEnd = EmuScanSlowEnd;
 	EmuScanPrepare();

+ 0 - 1
platform/psp/port_config.h

@@ -14,7 +14,6 @@
 
 // draw.c
 #define USE_BGR555 1
-#define OVERRIDE_HIGHCOL 1
 
 // draw2.c
 #define START_ROW  0 // which row of tiles to start rendering at?

+ 0 - 3
platform/uiq3/port_config.h

@@ -8,9 +8,6 @@
 #define REDUCE_IO_CALLS 0
 #define SIMPLE_WRITE_SOUND 0
 
-// draw.c
-#define OVERRIDE_HIGHCOL 0
-
 // draw2.c
 #define START_ROW  0 // which row of tiles to start rendering at?
 #define END_ROW   28 // ..end

+ 0 - 1
platform/uiq3/port_config.s

@@ -6,7 +6,6 @@
 .equiv START_ROW,               0
 .equiv END_ROW,                28
 
-.equiv OVERRIDE_HIGHCOL,        0
 .equiv UNALIGNED_DRAWLINEDEST,  0
 
 @ this should be set to one only for GP2X port

+ 6 - 11
platform/win32/plat.c

@@ -13,6 +13,8 @@
 static unsigned short screen_buff[320 * 240];
 static unsigned char PicoDraw2FB_[(8+320) * (8+240+8)];
 unsigned char *PicoDraw2FB = PicoDraw2FB_;
+const char **renderer_names = NULL;
+const char **renderer_names32x = NULL;
 
 char cpu_clk_name[] = "unused";
 
@@ -68,17 +70,10 @@ void pemu_validate_config(void)
 {
 }
 
-static int EmuScanBegin16(unsigned int num)
-{
-	DrawLineDest = (unsigned short *) g_screen_ptr + g_screen_width * num;
-
-	return 0;
-}
-
 void pemu_loop_prep(void)
 {
-	PicoDrawSetColorFormat(1);
-	PicoScanBegin = EmuScanBegin16;
+	PicoDrawSetOutFormat(PDF_RGB555, 1);
+	PicoDrawSetOutBuf(g_screen_ptr, g_screen_width * 2);
 	pemu_sound_start();
 }
 
@@ -105,10 +100,10 @@ void plat_video_wait_vsync(void)
 {
 }
 
-void plat_video_toggle_renderer(int is_next, int force_16bpp, int is_menu)
+void plat_video_toggle_renderer(int change, int is_menu)
 {
 	// this will auto-select SMS/32X renderers
-	PicoDrawSetColorFormat(1);
+	PicoDrawSetOutFormat(PDF_RGB555, 1);
 }
 
 void emu_video_mode_change(int start_line, int line_count, int is_32cols)

+ 0 - 3
platform/win32/port_config.h

@@ -13,9 +13,6 @@
 #define SCREEN_WIDTH  320
 #define SCREEN_HEIGHT 240
 
-// draw.c
-#define OVERRIDE_HIGHCOL 0
-
 // draw2.c
 #define START_ROW  0 // which row of tiles to start rendering at?
 #define END_ROW   28 // ..end