Browse Source

sms renderer, fix unaligned bg-filled tiles
core+gp2x+psp, fix handling mid-frame palette changes
platform, fix vertical scaling, aspect ratio handling (gp2x, psp)
libretro, various fixes (input handling, aspect ratio)
platform, include current dir in bios search path

root 2 years ago
parent
commit
84d01c5bba

+ 2 - 2
pico/draw.c

@@ -1894,10 +1894,10 @@ PICO_INTERNAL void PicoFrameStart(void)
 
 
   if (FinalizeLine == FinalizeLine8bit) {
   if (FinalizeLine == FinalizeLine8bit) {
     // make a backup of the current palette in case Sonic mode is detected later
     // make a backup of the current palette in case Sonic mode is detected later
-    Pico.est.SonicPalCount = 0;
-    Pico.m.dirtyPal = (Pico.m.dirtyPal ? 2 : 0); // mark as dirty but copied
+    Pico.m.dirtyPal = (Pico.m.dirtyPal || Pico.est.SonicPalCount ? 2 : 0);
     blockcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);
     blockcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);
   }
   }
+  Pico.est.SonicPalCount = 0;
 }
 }
 
 
 static void DrawBlankedLine(int line, int offs, int sh, int bgc)
 static void DrawBlankedLine(int line, int offs, int sh, int bgc)

+ 21 - 16
pico/mode4.c

@@ -60,8 +60,14 @@ static int CollisionDetect(u8 *mb, u16 sx, unsigned int pack, int zoomed)
 
 
 static void TileBGM4(u16 sx, int pal)
 static void TileBGM4(u16 sx, int pal)
 {
 {
-  u32 *pd = (u32 *)(Pico.est.HighCol + sx);
-  pd[0] = pd[1] = pal * 0x01010101;
+  if (sx & 3) {
+    u8 *pd = (u8 *)(Pico.est.HighCol + sx);
+    pd[0] = pd[1] = pd[2] = pd[3] = pal;
+    pd[4] = pd[5] = pd[6] = pd[7] = pal;
+  } else {
+    u32 *pd = (u32 *)(Pico.est.HighCol + sx);
+    pd[0] = pd[1] = pal * 0x01010101;
+  }
 }
 }
 
 
 // 8 pixels are arranged in 4 bitplane bytes in a 32 bit word. To pull the
 // 8 pixels are arranged in 4 bitplane bytes in a 32 bit word. To pull the
@@ -650,10 +656,10 @@ void PicoFrameStartSMS(void)
   Pico.est.DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement;
   Pico.est.DrawLineDest = (char *)DrawLineDestBase + screen_offset * DrawLineDestIncrement;
 
 
   if (FinalizeLineSMS == FinalizeLine8bitSMS) {
   if (FinalizeLineSMS == FinalizeLine8bitSMS) {
-    Pico.est.SonicPalCount = 0;
-    Pico.m.dirtyPal = (Pico.m.dirtyPal ? 2 : 0);
-    memcpy(Pico.est.SonicPal, PicoMem.cram, 0x20*2);
+    Pico.m.dirtyPal = (Pico.m.dirtyPal || Pico.est.SonicPalCount ? 2 : 0);
+    memcpy(Pico.est.SonicPal, PicoMem.cram, 0x40*2);
   }
   }
+  Pico.est.SonicPalCount = 0;
 }
 }
 
 
 void PicoParseSATSMS(int line)
 void PicoParseSATSMS(int line)
@@ -701,13 +707,12 @@ norender:
 
 
 /* Fixed palette for TMS9918 modes */
 /* Fixed palette for TMS9918 modes */
 static u16 tmspal[32] = {
 static u16 tmspal[32] = {
-#if 1  // SMS palette
+  // SMS palette
   0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
   0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
   0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
   0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
-#else  // TMS palette
+  // TMS palette
   0x0000, 0x0000, 0x04c2, 0x07d5, 0x0e55, 0x0f77, 0x045d, 0x0fe4,
   0x0000, 0x0000, 0x04c2, 0x07d5, 0x0e55, 0x0f77, 0x045d, 0x0fe4,
   0x055f, 0x077f, 0x05cd, 0x08ce, 0x03b2, 0x0b5c, 0x0ccc, 0x0fff,
   0x055f, 0x077f, 0x05cd, 0x08ce, 0x03b2, 0x0b5c, 0x0ccc, 0x0fff,
-#endif
 };
 };
 
 
 void PicoDoHighPal555SMS(void)
 void PicoDoHighPal555SMS(void)
@@ -731,18 +736,18 @@ void PicoDoHighPal555SMS(void)
     if (!(Pico.video.reg[0] & 0x4))
     if (!(Pico.video.reg[0] & 0x4))
       spal = (u32 *)tmspal; // fixed palette in TMS modes
       spal = (u32 *)tmspal; // fixed palette in TMS modes
     for (i = 0x20/2; i > 0; i--, spal++, dpal++) { 
     for (i = 0x20/2; i > 0; i--, spal++, dpal++) { 
-     t = *spal;
+      t = *spal;
 #if defined(USE_BGR555)
 #if defined(USE_BGR555)
-     t = ((t & 0x000f000f)<< 1) | ((t & 0x00f000f0)<<2) | ((t & 0x0f000f00)<<3);
-     t |= (t >> 4) & 0x04210421;
+      t = ((t & 0x000f000f)<<1) | ((t & 0x00f000f0)<<2) | ((t & 0x0f000f00)<<3);
+      t |= (t >> 4) & 0x04210421;
 #elif defined(USE_BGR565)
 #elif defined(USE_BGR565)
-     t = ((t & 0x000f000f)<< 1) | ((t & 0x00f000f0)<<3) | ((t & 0x0f000f00)<<4);
-     t |= (t >> 4) & 0x08610861;
+      t = ((t & 0x000f000f)<<1) | ((t & 0x00f000f0)<<3) | ((t & 0x0f000f00)<<4);
+      t |= (t >> 4) & 0x08610861;
 #else
 #else
-     t = ((t & 0x000f000f)<<12) | ((t & 0x00f000f0)<<3) | ((t & 0x0f000f00)>>7);
-     t |= (t >> 4) & 0x08610861;
+      t = ((t & 0x000f000f)<<12)| ((t & 0x00f000f0)<<3) | ((t & 0x0f000f00)>>7);
+      t |= (t >> 4) & 0x08610861;
 #endif
 #endif
-     *dpal = t;
+      *dpal = t;
     }
     }
     memcpy(dpal, dpal-0x20/2, 0x20*2); // for prio bit
     memcpy(dpal, dpal-0x20/2, 0x20*2); // for prio bit
     spal += 0x20/2, dpal += 0x20/2;
     spal += 0x20/2, dpal += 0x20/2;

+ 3 - 2
pico/sms.c

@@ -56,18 +56,19 @@ static void vdp_data_write(unsigned char d)
   struct PicoVideo *pv = &Pico.video;
   struct PicoVideo *pv = &Pico.video;
 
 
   if (pv->type == 3) {
   if (pv->type == 3) {
+    // cram. 32 on SMS, but 64 on MD. Fill 2nd half of cram for prio bit mirror
     if (Pico.m.hardware & 0x1) { // GG, same layout as MD
     if (Pico.m.hardware & 0x1) { // GG, same layout as MD
       unsigned a = pv->addr & 0x3f;
       unsigned a = pv->addr & 0x3f;
       if (a & 0x1) { // write complete color on high byte write
       if (a & 0x1) { // write complete color on high byte write
         u16 c = ((d&0x0f) << 8) | Pico.ms.vdp_buffer;
         u16 c = ((d&0x0f) << 8) | Pico.ms.vdp_buffer;
         if (PicoMem.cram[a >> 1] != c) Pico.m.dirtyPal = 1;
         if (PicoMem.cram[a >> 1] != c) Pico.m.dirtyPal = 1;
-        PicoMem.cram[a >> 1] = c;
+        PicoMem.cram[a >> 1] = PicoMem.cram[(a >> 1)+0x20] = c;
       }
       }
     } else { // SMS, convert to MD layout (00BbGgRr to 0000BbBbGgGgRrRr)
     } else { // SMS, convert to MD layout (00BbGgRr to 0000BbBbGgGgRrRr)
       unsigned a = pv->addr & 0x1f;
       unsigned a = pv->addr & 0x1f;
       u16 c = ((d&0x30)<<6) + ((d&0x0c)<<4) + ((d&0x03)<<2);
       u16 c = ((d&0x30)<<6) + ((d&0x0c)<<4) + ((d&0x03)<<2);
       if (PicoMem.cram[a] != (c | (c>>2))) Pico.m.dirtyPal = 1;
       if (PicoMem.cram[a] != (c | (c>>2))) Pico.m.dirtyPal = 1;
-      PicoMem.cram[a] = c | (c>>2);
+      PicoMem.cram[a] = PicoMem.cram[a+0x20] = c | (c>>2);
     }
     }
   } else {
   } else {
     PicoMem.vramb[MEM_LE2(pv->addr)] = d;
     PicoMem.vramb[MEM_LE2(pv->addr)] = d;

+ 1 - 1
platform/common/arm_utils.h

@@ -1,5 +1,5 @@
 
 
-void bgr444_to_rgb32(void *to, void *from);
+void bgr444_to_rgb32(void *to, void *from, unsigned entries);
 void bgr444_to_rgb32_sh(void *to, void *from);
 void bgr444_to_rgb32_sh(void *to, void *from);
 
 
 void vidcpy_m2(void *dest, void *src, int m32col, int with_32c_border);
 void vidcpy_m2(void *dest, void *src, int m32col, int with_32c_border);

+ 2 - 2
platform/common/arm_utils.s

@@ -62,12 +62,12 @@
 .endm
 .endm
 
 
 
 
-.global bgr444_to_rgb32 @ void *to, void *from
+.global bgr444_to_rgb32 @ void *to, void *from, unsigned entries
 
 
 bgr444_to_rgb32:
 bgr444_to_rgb32:
     stmfd   sp!, {r4-r7,lr}
     stmfd   sp!, {r4-r7,lr}
 
 
-    mov     r12, #0x40>>3 @ repeats
+    mov     r12, r2, lsr #3 @ repeats
     mov     lr, #0x00f00000
     mov     lr, #0x00f00000
     orr     lr, lr, #0x00f0
     orr     lr, lr, #0x00f0
 
 

+ 10 - 0
platform/common/emu.c

@@ -219,6 +219,16 @@ static const char *find_bios(int *region, const char *cd_fname)
 		strcat(static_buff, ".zip");
 		strcat(static_buff, ".zip");
 		f = fopen(static_buff, "rb");
 		f = fopen(static_buff, "rb");
 		if (f) break;
 		if (f) break;
+
+		strcpy(static_buff, files[i]);
+		strcat(static_buff, ".bin");
+		f = fopen(static_buff, "rb");
+		if (f) break;
+
+		static_buff[strlen(static_buff) - 4] = 0;
+		strcat(static_buff, ".zip");
+		f = fopen(static_buff, "rb");
+		if (f) break;
 	}
 	}
 
 
 	/** Check Bios files in <rom path>/bios */
 	/** Check Bios files in <rom path>/bios */

+ 39 - 12
platform/gp2x/emu.c

@@ -256,8 +256,11 @@ static int ld_left, ld_lines; // numbers in Q1 format
 
 
 static int EmuScanBegin16_ld(unsigned int num)
 static int EmuScanBegin16_ld(unsigned int num)
 {
 {
-	if ((signed int)(ld_counter - num) > 100)
-		ld_counter = 0;
+	if ((signed int)(ld_counter - num) > 100) {
+		// vsync, offset so that the upscaled image is centered
+		ld_counter = 120 - (120-num) * (ld_lines+2)/ld_lines;
+		ld_left = ld_lines;
+	}
 
 
 	if (emu_scan_begin)
 	if (emu_scan_begin)
 		return emu_scan_begin(ld_counter);
 		return emu_scan_begin(ld_counter);
@@ -301,26 +304,26 @@ static int make_local_pal_md(int fast_mode)
 	int pallen = 0x100;
 	int pallen = 0x100;
 
 
 	if (fast_mode) {
 	if (fast_mode) {
-		bgr444_to_rgb32(localPal, PicoMem.cram);
+		bgr444_to_rgb32(localPal, PicoMem.cram, 64);
 		pallen = 0x40;
 		pallen = 0x40;
 		Pico.m.dirtyPal = 0;
 		Pico.m.dirtyPal = 0;
 	}
 	}
 	else if (Pico.est.rendstatus & PDRAW_SONIC_MODE) { // mid-frame palette changes
 	else if (Pico.est.rendstatus & PDRAW_SONIC_MODE) { // mid-frame palette changes
 		switch (Pico.est.SonicPalCount) {
 		switch (Pico.est.SonicPalCount) {
-		case 3: bgr444_to_rgb32(localPal+0xc0, Pico.est.SonicPal+0xc0);
-		case 2: bgr444_to_rgb32(localPal+0x80, Pico.est.SonicPal+0x80);
-		case 1: bgr444_to_rgb32(localPal+0x40, Pico.est.SonicPal+0x40);
-		default:bgr444_to_rgb32(localPal, Pico.est.SonicPal);
+		case 3: bgr444_to_rgb32(localPal+0xc0, Pico.est.SonicPal+0xc0, 64);
+		case 2: bgr444_to_rgb32(localPal+0x80, Pico.est.SonicPal+0x80, 64);
+		case 1: bgr444_to_rgb32(localPal+0x40, Pico.est.SonicPal+0x40, 64);
+		default:bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);
 		}
 		}
 		pallen = (Pico.est.SonicPalCount+1)*0x40;
 		pallen = (Pico.est.SonicPalCount+1)*0x40;
 	}
 	}
 	else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode
 	else if (Pico.video.reg[0xC] & 8) { // shadow/hilight mode
-		bgr444_to_rgb32(localPal, Pico.est.SonicPal);
+		bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);
 		bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal);
 		bgr444_to_rgb32_sh(localPal, Pico.est.SonicPal);
 		memcpy(localPal+0xc0, localPal, 0x40*4); // for spr prio mess
 		memcpy(localPal+0xc0, localPal, 0x40*4); // for spr prio mess
 	}
 	}
 	else {
 	else {
-		bgr444_to_rgb32(localPal, Pico.est.SonicPal);
+		bgr444_to_rgb32(localPal, Pico.est.SonicPal, 64);
 		memcpy(localPal+0x40, localPal, 0x40*4); // for spr prio mess
 		memcpy(localPal+0x40, localPal, 0x40*4); // for spr prio mess
 		memcpy(localPal+0x80, localPal, 0x80*4); // for spr prio mess
 		memcpy(localPal+0x80, localPal, 0x80*4); // for spr prio mess
 	}
 	}
@@ -336,9 +339,27 @@ static int make_local_pal_md(int fast_mode)
 
 
 static int make_local_pal_sms(int fast_mode)
 static int make_local_pal_sms(int fast_mode)
 {
 {
-	bgr444_to_rgb32(localPal, PicoMem.cram);
-	Pico.m.dirtyPal = 0;
-	return 0x40;
+	static u16 tmspal[32] = {
+		// SMS palette for TMS modes
+		0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
+		0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
+	};
+	int i;
+	
+	if (!(Pico.video.reg[0] & 0x4)) {
+		for (i = Pico.est.SonicPalCount; i >= 0; i--) {
+			bgr444_to_rgb32(localPal+i*0x40, tmspal, 32);
+			memcpy(localPal+i*0x40+0x20, localPal+i*0x40, 0x20*4);
+		}
+	} else {
+		for (i = Pico.est.SonicPalCount; i >= 0; i--) {
+			bgr444_to_rgb32(localPal+i*0x40, Pico.est.SonicPal+i*0x40, 32);
+			memcpy(localPal+i*0x40+0x20, localPal+i*0x40, 0x20*4);
+		}
+	}
+	if (Pico.m.dirtyPal == 2)
+		Pico.m.dirtyPal = 0;
+	return (Pico.est.SonicPalCount+1)*0x40;
 }
 }
 
 
 void pemu_finalize_frame(const char *fps, const char *notice)
 void pemu_finalize_frame(const char *fps, const char *notice)
@@ -568,6 +589,12 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
 	int scalex = 320, scaley = 240;
 	int scalex = 320, scaley = 240;
 	int ln_offs = 0;
 	int ln_offs = 0;
 
 
+	/* NTSC always has 224 visible lines, anything smaller has bars */
+	if (line_count < 224 && line_count > 144) {
+		start_line -= (224-line_count) /2;
+		line_count = 224;
+	}
+
 	/* line doubling for swscaling, also needed for bg frames */
 	/* line doubling for swscaling, also needed for bg frames */
 	if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {
 	if (currentConfig.vscaling == EOPT_SCALE_SW && line_count < 240) {
 		ld_lines = ld_left = 2*line_count / (240 - line_count);
 		ld_lines = ld_left = 2*line_count / (240 - line_count);

+ 29 - 46
platform/libretro/libretro.c

@@ -94,9 +94,7 @@ static const float VOUT_PAR = 0.0;
 static const float VOUT_4_3 = (4.0f / 3.0f);
 static const float VOUT_4_3 = (4.0f / 3.0f);
 static const float VOUT_CRT = (1.29911f);
 static const float VOUT_CRT = (1.29911f);
 
 
-static bool show_overscan = false;
-
-/* Required to allow on the fly changes to 'show overscan' */
+/* Required to allow on the fly changes to 'renderer' */
 static int vm_current_start_line = -1;
 static int vm_current_start_line = -1;
 static int vm_current_line_count = -1;
 static int vm_current_line_count = -1;
 static int vm_current_start_col = -1;
 static int vm_current_start_col = -1;
@@ -657,17 +655,9 @@ void emu_video_mode_change(int start_line, int line_count, int start_col, int co
    if (vout_16bit)
    if (vout_16bit)
       PicoDrawSetOutBuf(vout_buf, vout_width * 2);
       PicoDrawSetOutBuf(vout_buf, vout_width * 2);
 
 
-   if (show_overscan)
-   {
-      vout_height = line_count + (start_line * 2);
-      vout_offset = 0;
-   }
-   else
-   {
-      vout_height = line_count;
-      /* Note: We multiply by 2 here to account for pitch */
-      vout_offset = vout_width * start_line * 2;
-   }
+   vout_height = line_count;
+   /* Note: We multiply by 2 here to account for pitch */
+   vout_offset = vout_width * start_line * 2;
 
 
    /* Redundant sanity check... */
    /* Redundant sanity check... */
    vout_height = (vout_height > VOUT_MAX_HEIGHT) ?
    vout_height = (vout_height > VOUT_MAX_HEIGHT) ?
@@ -764,7 +754,7 @@ void retro_get_system_info(struct retro_system_info *info)
 
 
 void retro_get_system_av_info(struct retro_system_av_info *info)
 void retro_get_system_av_info(struct retro_system_av_info *info)
 {
 {
-   int common_height;
+   float tv_height = (vout_height > 144 ? Pico.m.pal ? 240 : 224 : 144);
    float common_width;
    float common_width;
 
 
    memset(info, 0, sizeof(*info));
    memset(info, 0, sizeof(*info));
@@ -776,11 +766,10 @@ void retro_get_system_av_info(struct retro_system_av_info *info)
    info->geometry.max_height   = vout_height;
    info->geometry.max_height   = vout_height;
 
 
    common_width = vout_width;
    common_width = vout_width;
-   common_height = vout_height >= 192 && vout_height <= 224 ? 224 : vout_height;
    if (vout_aspect != 0)
    if (vout_aspect != 0)
-      common_width = vout_aspect * common_height;
+      common_width = vout_aspect * tv_height;
 
 
-   info->geometry.aspect_ratio = common_width / common_height;
+   info->geometry.aspect_ratio = common_width / vout_height;
 }
 }
 
 
 /* savestates */
 /* savestates */
@@ -1312,6 +1301,8 @@ bool retro_load_game(const struct retro_game_info *info)
    PsndRerate(0);
    PsndRerate(0);
 
 
    PicoDrawSetOutFormat(vout_format, 0);
    PicoDrawSetOutFormat(vout_format, 0);
+   if (vout_format == PDF_8BIT)
+      PicoDrawSetOutBuf(Pico.est.Draw2FB, 328);
 
 
    /* Setup retro memory maps */
    /* Setup retro memory maps */
    set_memory_maps();
    set_memory_maps();
@@ -1407,18 +1398,18 @@ void retro_reset(void)
 }
 }
 
 
 static const unsigned short retro_pico_map[] = {
 static const unsigned short retro_pico_map[] = {
-   1 << GBTN_B,
-   1 << GBTN_A,
-   1 << GBTN_MODE,
-   1 << GBTN_START,
-   1 << GBTN_UP,
-   1 << GBTN_DOWN,
-   1 << GBTN_LEFT,
-   1 << GBTN_RIGHT,
-   1 << GBTN_C,
-   1 << GBTN_Y,
-   1 << GBTN_X,
-   1 << GBTN_Z,
+   [RETRO_DEVICE_ID_JOYPAD_B]      = 1 << GBTN_B,
+   [RETRO_DEVICE_ID_JOYPAD_Y]      = 1 << GBTN_A,
+   [RETRO_DEVICE_ID_JOYPAD_SELECT] = 1 << GBTN_MODE,
+   [RETRO_DEVICE_ID_JOYPAD_START]  = 1 << GBTN_START,
+   [RETRO_DEVICE_ID_JOYPAD_UP]     = 1 << GBTN_UP,
+   [RETRO_DEVICE_ID_JOYPAD_DOWN]   = 1 << GBTN_DOWN,
+   [RETRO_DEVICE_ID_JOYPAD_LEFT]   = 1 << GBTN_LEFT,
+   [RETRO_DEVICE_ID_JOYPAD_RIGHT]  = 1 << GBTN_RIGHT,
+   [RETRO_DEVICE_ID_JOYPAD_A]      = 1 << GBTN_C,
+   [RETRO_DEVICE_ID_JOYPAD_X]      = 1 << GBTN_Y,
+   [RETRO_DEVICE_ID_JOYPAD_L]      = 1 << GBTN_X,
+   [RETRO_DEVICE_ID_JOYPAD_R]      = 1 << GBTN_Z,
 };
 };
 #define RETRO_PICO_MAP_LEN (sizeof(retro_pico_map) / sizeof(retro_pico_map[0]))
 #define RETRO_PICO_MAP_LEN (sizeof(retro_pico_map) / sizeof(retro_pico_map[0]))
 
 
@@ -1451,7 +1442,6 @@ static void update_variables(bool first_run)
    double new_sound_rate;
    double new_sound_rate;
    unsigned short old_snd_filter;
    unsigned short old_snd_filter;
    int32_t old_snd_filter_range;
    int32_t old_snd_filter_range;
-   bool old_show_overscan;
 
 
    var.value = NULL;
    var.value = NULL;
    var.key = "picodrive_input1";
    var.key = "picodrive_input1";
@@ -1579,15 +1569,6 @@ static void update_variables(bool first_run)
          PicoIn.opt &= ~POPT_DIS_SPRITE_LIM;
          PicoIn.opt &= ~POPT_DIS_SPRITE_LIM;
    }
    }
 
 
-   old_show_overscan = show_overscan;
-   var.value = NULL;
-   var.key = "picodrive_overscan";
-   show_overscan = false;
-   if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
-      if (strcmp(var.value, "enabled") == 0)
-         show_overscan = true;
-   }
-
    var.value = NULL;
    var.value = NULL;
    var.key = "picodrive_overclk68k";
    var.key = "picodrive_overclk68k";
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
@@ -1664,6 +1645,8 @@ static void update_variables(bool first_run)
       if (vout_format == PDF_NONE)
       if (vout_format == PDF_NONE)
          PicoIn.opt |= POPT_ALT_RENDERER;
          PicoIn.opt |= POPT_ALT_RENDERER;
       PicoDrawSetOutFormat(vout_format, 0);
       PicoDrawSetOutFormat(vout_format, 0);
+      if (vout_format == PDF_8BIT)
+         PicoDrawSetOutBuf(Pico.est.Draw2FB, 328);
    }
    }
 
 
    var.value = NULL;
    var.value = NULL;
@@ -1681,7 +1664,7 @@ static void update_variables(bool first_run)
    }
    }
 
 
    /* setup video if required */
    /* setup video if required */
-   if (show_overscan != old_show_overscan || vout_format != old_vout_format)
+   if (vout_format != old_vout_format)
    {
    {
       if ((vm_current_start_line != -1) &&
       if ((vm_current_start_line != -1) &&
           (vm_current_line_count != -1) &&
           (vm_current_line_count != -1) &&
@@ -1819,15 +1802,15 @@ void retro_run(void)
        * with the fast renderer this is improving performance, at the expense of accuracy.
        * with the fast renderer this is improving performance, at the expense of accuracy.
        */
        */
       /* This section is mostly copied from pemu_finalize_frame in platform/linux/emu.c */
       /* This section is mostly copied from pemu_finalize_frame in platform/linux/emu.c */
-      unsigned short *pd = (unsigned short *)vout_buf;
+      unsigned short *pd = (unsigned short *)((char *)vout_buf + vout_offset);
       /* Skip the leftmost 8 columns (it is used as an overlap area for rendering) */
       /* Skip the leftmost 8 columns (it is used as an overlap area for rendering) */
-      unsigned char *ps = Pico.est.Draw2FB + 8;
+      unsigned char *ps = Pico.est.Draw2FB + vm_current_start_line * 328 + 8;
       unsigned short *pal = Pico.est.HighPal;
       unsigned short *pal = Pico.est.HighPal;
       int x;
       int x;
       if (Pico.m.dirtyPal)
       if (Pico.m.dirtyPal)
          PicoDrawUpdateHighPal();
          PicoDrawUpdateHighPal();
-      /* Copy up to the max height to include the overscan area, and skip the leftmost 8 columns again */
-      for (i = 0; i < VOUT_MAX_HEIGHT; i++, ps += 8) {
+      /* Copy, and skip the leftmost 8 columns again */
+      for (i = 0; i < vout_height; i++, ps += 8) {
          for (x = 0; x < vout_width; x+=4) {
          for (x = 0; x < vout_width; x+=4) {
             *pd++ = pal[*ps++];
             *pd++ = pal[*ps++];
             *pd++ = pal[*ps++];
             *pd++ = pal[*ps++];
@@ -1842,7 +1825,7 @@ void retro_run(void)
       unsigned short *pd = (unsigned short *)vout_buf;
       unsigned short *pd = (unsigned short *)vout_buf;
       unsigned short *ps = (unsigned short *)vout_ghosting_buf;
       unsigned short *ps = (unsigned short *)vout_ghosting_buf;
       int y;
       int y;
-      for (y = 0; y < VOUT_MAX_HEIGHT; y++) {
+      for (y = 0; y < vout_height; y++) {
          if (vout_ghosting == 1)
          if (vout_ghosting == 1)
             v_blend(pd, ps, vout_width, p_075_round);
             v_blend(pd, ps, vout_width, p_075_round);
          else
          else

+ 0 - 11
platform/libretro/libretro_core_options.h

@@ -174,17 +174,6 @@ struct retro_core_option_definition option_defs_us[] = {
       },
       },
       "disabled"
       "disabled"
    },
    },
-   {
-      "picodrive_overscan",
-      "Show Overscan",
-      "Crop out the potentially random glitchy video output that would have been hidden by the bezel around the edge of a standard-definition television screen.",
-      {
-         { "disabled", NULL },
-         { "enabled",  NULL },
-         { NULL, NULL },
-      },
-      "disabled"
-   },
    {
    {
       "picodrive_overclk68k",
       "picodrive_overclk68k",
       "68K Overclock",
       "68K Overclock",

+ 0 - 9
platform/libretro/libretro_core_options_intl.h

@@ -139,15 +139,6 @@ struct retro_core_option_definition option_defs_tr[] = {
       },
       },
       "PAR"
       "PAR"
    },
    },
-   {
-      "picodrive_overscan",
-      "Tarama Taşmasını Göster",
-      "Standart tanımlı bir televizyon ekranının kenar çevresinde, çerçeve tarafından gizlenmiş olabilecek rastgele video çıkışını kesin.",
-      {
-         { NULL, NULL },
-      },
-      "disabled"
-   },
    {
    {
       "picodrive_overclk68k",
       "picodrive_overclk68k",
       "68K Hızaşırtma",
       "68K Hızaşırtma",

+ 2 - 2
platform/linux/blit.c

@@ -10,13 +10,13 @@
 // to      00000000 rrr00000 ggg00000 bbb00000 ...
 // to      00000000 rrr00000 ggg00000 bbb00000 ...
 // TODO: rm when gp2x/emu.c is no longer used
 // TODO: rm when gp2x/emu.c is no longer used
 
 
-void bgr444_to_rgb32(void *to, void *from)
+void bgr444_to_rgb32(void *to, void *from, unsigned entries)
 {
 {
 	unsigned short *ps = from;
 	unsigned short *ps = from;
 	unsigned int   *pd = to;
 	unsigned int   *pd = to;
 	int pixels;
 	int pixels;
 
 
-	for (pixels = 0x40; pixels; pixels--, ps++, pd++)
+	for (pixels = entries; pixels; pixels--, ps++, pd++)
 	{
 	{
 		*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
 		*pd = ((*ps<<20)&0xe00000) | ((*ps<<8)&0xe000) | ((*ps>>4)&0xe0);
 		*pd |= *pd >> 3;
 		*pd |= *pd >> 3;

+ 37 - 18
platform/psp/emu.c

@@ -204,32 +204,42 @@ static void set_scaling_params(void)
 	*/
 	*/
 }
 }
 
 
+static void do_pal_update_sms(void)
+{
+	static u16 tmspal[32] = {
+		// SMS palette
+		0x0000, 0x0000, 0x00a0, 0x00f0, 0x0500, 0x0f00, 0x0005, 0x0ff0,
+		0x000a, 0x000f, 0x0055, 0x00ff, 0x0050, 0x0f0f, 0x0555, 0x0fff,
+	};
+	int i;
+	
+	if (!(Pico.video.reg[0] & 0x4)) {
+		for (i = Pico.est.SonicPalCount; i >= 0; i--)
+			do_pal_convert(localPal+i*0x40, tmspal, currentConfig.gamma, currentConfig.gamma2);
+	} else {
+		for (i = Pico.est.SonicPalCount; i >= 0; i--)
+			do_pal_convert(localPal+i*0x40, Pico.est.SonicPal+i*0x40, currentConfig.gamma, currentConfig.gamma2);
+	}
+	if (Pico.m.dirtyPal == 2)
+		Pico.m.dirtyPal = 0;
+	need_pal_upload = 1;
+}
+
 static void do_pal_update(void)
 static void do_pal_update(void)
 {
 {
 	u32 *dpal=(void *)localPal;
 	u32 *dpal=(void *)localPal;
 	int i;
 	int i;
 
 
-	//for (i = 0x3f/2; i >= 0; i--)
-	//	dpal[i] = ((spal[i]&0x000f000f)<< 1)|((spal[i]&0x00f000f0)<<3)|((spal[i]&0x0f000f00)<<4);
-	if (PicoIn.AHW & PAHW_SMS) {
-		u32 *spal = (void *)PicoMem.cram; 
-		for (i = 0; i < 0x20 / 2; i++) {
-			u32 t = spal[i];
-			t = ((t & 0x00030003)<< 3) | ((t & 0x000c000c)<<7) | ((t & 0x00300030)<<10);
-			t |= (t >> 2) | ((t >> 4) & 0x08610861);
-			dpal[i] = t;
-		}
-		Pico.m.dirtyPal = 0;
-	} else if (PicoIn.opt & POPT_ALT_RENDERER) {
+	if (PicoIn.opt & POPT_ALT_RENDERER) {
 		do_pal_convert(localPal, PicoMem.cram, currentConfig.gamma, currentConfig.gamma2);
 		do_pal_convert(localPal, PicoMem.cram, currentConfig.gamma, currentConfig.gamma2);
 		Pico.m.dirtyPal = 0;
 		Pico.m.dirtyPal = 0;
 	}
 	}
 	else if (Pico.est.rendstatus & PDRAW_SONIC_MODE)
 	else if (Pico.est.rendstatus & PDRAW_SONIC_MODE)
 	{
 	{
 		switch (Pico.est.SonicPalCount) {
 		switch (Pico.est.SonicPalCount) {
-		case 3: do_pal_convert(localPal+0xc0/2, Pico.est.SonicPal+0xc0, currentConfig.gamma, currentConfig.gamma2);
-		case 2: do_pal_convert(localPal+0x80/2, Pico.est.SonicPal+0x80, currentConfig.gamma, currentConfig.gamma2);
-		case 1:	do_pal_convert(localPal+0x40/2, Pico.est.SonicPal+0x40, currentConfig.gamma, currentConfig.gamma2);
+		case 3: do_pal_convert(localPal+0xc0, Pico.est.SonicPal+0xc0, currentConfig.gamma, currentConfig.gamma2);
+		case 2: do_pal_convert(localPal+0x80, Pico.est.SonicPal+0x80, currentConfig.gamma, currentConfig.gamma2);
+		case 1:	do_pal_convert(localPal+0x40, Pico.est.SonicPal+0x40, currentConfig.gamma, currentConfig.gamma2);
 		default:do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2);
 		default:do_pal_convert(localPal, Pico.est.SonicPal, currentConfig.gamma, currentConfig.gamma2);
 		}
 		}
 	}
 	}
@@ -267,9 +277,12 @@ static void blitscreen_clut(void)
 	sceGuTexMode(is_16bit_mode() ? GU_PSM_5650:GU_PSM_T8,0,0,0);
 	sceGuTexMode(is_16bit_mode() ? GU_PSM_5650:GU_PSM_T8,0,0,0);
 	sceGuTexImage(0,512,512,512,g_screen_ptr);
 	sceGuTexImage(0,512,512,512,g_screen_ptr);
 
 
-	if (!is_16bit_mode() && Pico.m.dirtyPal)
-		do_pal_update();
-
+	if (!is_16bit_mode() && Pico.m.dirtyPal) {
+		if (PicoIn.AHW & PAHW_SMS)
+			do_pal_update_sms();
+		else
+			do_pal_update();
+	}
 
 
 	if (need_pal_upload) {
 	if (need_pal_upload) {
 		need_pal_upload = 0;
 		need_pal_upload = 0;
@@ -666,6 +679,12 @@ void plat_update_volume(int has_changed, int is_up)
 /* prepare for MD screen mode change */
 /* prepare for MD screen mode change */
 void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)
 void emu_video_mode_change(int start_line, int line_count, int start_col, int col_count)
 {
 {
+	/* NTSC always has 224 visible lines, anything smaller has bars */
+	if (line_count < 224 && line_count > 144) {
+		start_line -= (224-line_count) /2;
+		line_count = 224;
+	}
+
 	out_y = start_line; out_x = start_col;
 	out_y = start_line; out_x = start_col;
 	out_h = line_count; out_w = col_count;
 	out_h = line_count; out_w = col_count;