File coercemodes.patch of Package fs-uae

diff --git a/od-win32/picasso96_win.cpp b/od-win32/picasso96_win.cpp
index 307c9ff93..373b68397 100644
--- a/src/od-win32/picasso96_win.cpp
+++ b/src/od-win32/picasso96_win.cpp
@@ -129,7 +129,8 @@ struct picasso96_state_struct picasso96_state;
 struct picasso_vidbuf_description picasso_vidinfo;
 static struct PicassoResolution *newmodes;
 
-static int picasso_convert, host_mode;
+static int picasso_convert[2], host_mode;
+static uae_u32 dacrgbformat[2];
 
 /* These are the maximum resolutions... They are filled in by GetSupportedResolutions() */
 /* have to fill this in, otherwise problems occur on the Amiga side P96 s/w which expects
@@ -1030,7 +1031,12 @@ static void setconvert(int monid)
 {
 	static int ohost_mode, orgbformat;
 
-	picasso_convert = getconvert (picasso96_state.RGBFormat, picasso_vidinfo.pixbytes);
+	if (picasso96_state.advDragging) {
+		picasso_convert[0] = getconvert(dacrgbformat[0], picasso_vidinfo.pixbytes);
+		picasso_convert[1] = getconvert(dacrgbformat[1], picasso_vidinfo.pixbytes);
+	} else {
+		picasso_convert[0] = picasso_convert[1] = getconvert(picasso96_state.RGBFormat, picasso_vidinfo.pixbytes);
+	}
 #ifdef FSUAE
 	if (g_amiga_video_format == AMIGA_VIDEO_FORMAT_RGBA) {
 		host_mode = RGBFB_R8G8B8A8;
@@ -1063,8 +1069,8 @@ static void setconvert (void)
 	gfx_set_picasso_colors (picasso96_state.RGBFormat);
 	picasso_palette ();
 	if (host_mode != ohost_mode || picasso96_state.RGBFormat != orgbformat) {
-		write_log (_T("RTG conversion: Depth=%d HostRGBF=%d P96RGBF=%d Mode=%d\n"),
-			picasso_vidinfo.pixbytes, host_mode, picasso96_state.RGBFormat, picasso_convert);
+		write_log (_T("RTG conversion: Depth=%d HostRGBF=%d P96RGBF=%d Mode=%d/%d\n"),
+			picasso_vidinfo.pixbytes, host_mode, picasso96_state.RGBFormat, picasso_convert[0], picasso_convert[1]);
 		ohost_mode = host_mode;
 		orgbformat = picasso96_state.RGBFormat;
 	}
@@ -2618,6 +2624,7 @@ static void inituaegfx(TrapContext *ctx, uaecptr ABI)
 	}
 	flags |= BIF_VGASCREENSPLIT;
 	flags |= BIF_PALETTESWITCH;
+	flags |= (1 << 28);
 	put_long (ABI + PSSO_BoardInfo_Flags, flags);
 	if (debug_rtg_blitter != 3)
 		write_log (_T("P96: Blitter mode = %x!\n"), debug_rtg_blitter);
@@ -2862,14 +2869,55 @@ static uae_u32 REGPARAM2 picasso_SetColorArray (TrapContext *ctx)
 */
 static uae_u32 REGPARAM2 picasso_SetDAC (TrapContext *ctx)
 {
+	uae_u16 idx = m68k_dreg (regs, 0);
+	uae_u32 mode = m68k_dreg (regs, 7);
 	/* Fill in some static UAE related structure about this new DAC setting
 	* Lets us keep track of what pixel format the Amiga is thinking about in our frame-buffer */
 
+	if (picasso96_state.advDragging) {
+		dacrgbformat[idx ? 1 : 0] = mode;
+		picasso_convert[0] = getconvert(dacrgbformat[0], picasso_vidinfo.pixbytes);
+		picasso_convert[1] = getconvert(dacrgbformat[1], picasso_vidinfo.pixbytes);
+	} else {
+		dacrgbformat[0] = mode;
+		dacrgbformat[1] = mode;
+	}
 	P96TRACE((_T("SetDAC()\n")));
 	rtg_clear ();
 	return 1;
 }
 
+static uae_u32 REGPARAM2 picasso_CoerceMode(struct TrapContext *ctx)
+{
+	uae_u16 bw = m68k_dreg (regs, 2);
+	uae_u16 fw = m68k_dreg (regs, 3);
+	return bw > fw ? bw : fw;
+}
+
+static uae_u32 REGPARAM2 picasso_GetCompatibleDACFormats(struct TrapContext *ctx)
+{
+	RGBFTYPE type = (RGBFTYPE)m68k_dreg (regs, 7);
+	switch (type)
+	{
+	case RGBFB_CLUT:
+	case RGBFB_R8G8B8:
+	case RGBFB_B8G8R8:
+	case RGBFB_R5G6B5PC:
+	case RGBFB_R5G5B5PC:
+	case RGBFB_A8R8G8B8:
+	case RGBFB_A8B8G8R8:
+	case RGBFB_R8G8B8A8:
+	case RGBFB_B8G8R8A8:
+	case RGBFB_R5G6B5:
+	case RGBFB_R5G5B5:
+	case RGBFB_B5G6R5PC:
+	case RGBFB_B5G5R5PC:
+		picasso96_state.advDragging = true;
+		return RGBMASK_8BIT | RGBMASK_15BIT | RGBMASK_16BIT | RGBMASK_24BIT | RGBMASK_32BIT;
+	}
+	return 0;
+}
+
 static void init_picasso_screen (void)
 {
 	if(set_panning_called) {
@@ -4095,12 +4041,13 @@ void picasso_statusline(int monid, uae_u8 *dst)
 	}
 }
 
-static void copyrow (uae_u8 *src, uae_u8 *dst, int x, int y, int width, int srcbytesperrow, int srcpixbytes, int dstbytesperrow, int dstpixbytes, bool direct, int convert_mode)
+static void copyrow(uae_u8 *src, uae_u8 *dst, int x, int y, int width, int srcbytesperrow, int srcpixbytes, int dstbytesperrow, int dstpixbytes, int *convert_modep)
 {
 	int endx = x + width, endx4;
 	int dstpix = dstpixbytes;
 	int srcpix = srcpixbytes;
 	uae_u32 *clut = picasso_vidinfo.clut;
+	int convert_mode = convert_modep[0];
 	int dy = y;
 
 	if (y >= picasso_vidinfo.splitypos && picasso_vidinfo.splitypos >= 0) {
@@ -4108,15 +4155,17 @@ static void copyrow (int monid, uae_u8 *src, uae_u8 *dst, int x, int y, int widt
 			clut += 256;
 		}
 		y -= picasso_vidinfo.splitypos;
+		if (convert_mode != convert_modep[1]) {
+			int bpp1 = GetBytesPerPixel(dacrgbformat[0]);
+			int bpp2 = GetBytesPerPixel(dacrgbformat[1]);
+			srcbytesperrow = srcbytesperrow * bpp2 / bpp1;
+			convert_mode = convert_modep[1];
+		}
 	}
 
 	uae_u8 *src2 = src + y * srcbytesperrow;
 	uae_u8 *dst2 = dst + dy * dstbytesperrow;
 
-	if (direct) {
-		memcpy (dst2 + x * dstpix, src2 + x * srcpix, width * dstpix);
-		return;
-	}
 	// native match?
 	if (currprefs.gfx_api) {
 		switch (convert_mode)
@@ -4346,53 +4395,26 @@ void fb_copyrow(int monid, uae_u8 *src, uae_u8 *dst, int x, int y, int width, in
 	}
 }
 
-static void copyallinvert (uae_u8 *src, uae_u8 *dst, int pwidth, int pheight, int srcbytesperrow, int srcpixbytes, int dstbytesperrow, int dstpixbytes, bool direct, int mode_convert)
+static void copyallinvert(uae_u8 *src, uae_u8 *dst, int pwidth, int pheight, int srcbytesperrow, int srcpixbytes, int dstbytesperrow, int dstpixbytes, int *mode_convert)
 {
-	int x, y, w;
-
-	w = pwidth * dstpixbytes;
-	if (direct) {
-		for (y = 0; y < pheight; y++) {
-			if (y == picasso_vidinfo.splitypos) {
-				src = gfxmem_bank.start + natmem_offset;
-			}
-			for (x = 0; x < w; x++) {
-				dst[x] = src[x] ^ 0xff;
-			}
-			dst += dstbytesperrow;
-			src += srcbytesperrow;
-		}
-	} else {
-		uae_u8 *src2 = src;
-		for (y = 0; y < pheight; y++) {
-			for (x = 0; x < w; x++)
-				src2[x] ^= 0xff;
-			copyrow (src, dst, 0, y, pwidth, srcbytesperrow, srcpixbytes, dstbytesperrow, dstpixbytes, direct, mode_convert);
-			for (x = 0; x < w; x++)
-				src2[x] ^= 0xff;
-			src2 += srcbytesperrow;
-		}
+	
+	int w = pwidth * dstpixbytes;
+	uae_u8 *src2 = src;
+	for (int y = 0; y < pheight; y++) {
+		for (int x = 0; x < w; x++)
+			src2[x] ^= 0xff;
+		copyrow(src, dst, 0, y, pwidth, srcbytesperrow, srcpixbytes, dstbytesperrow, dstpixbytes, mode_convert);
+		for (int x = 0; x < w; x++)
+			src2[x] ^= 0xff;
+		src2 += srcbytesperrow;
 	}
 }
 
-static void copyall (uae_u8 *src, uae_u8 *dst, int pwidth, int pheight, int srcbytesperrow, int srcpixbytes, int dstbytesperrow, int dstpixbytes, bool direct, int mode_convert)
+static void copyall(uae_u8 *src, uae_u8 *dst, int pwidth, int pheight, int srcbytesperrow, int srcpixbytes, int dstbytesperrow, int dstpixbytes, int *mode_convert)
 {
-	int y;
 
-	if (direct) {
-		int w = pwidth * picasso_vidinfo.pixbytes;
-		for (y = 0; y < pheight; y++) {
-			if (y == picasso_vidinfo.splitypos) {
-				src = gfxmem_bank.start + natmem_offset;
-			}
-			memcpy (dst, src, w);
-			dst += dstbytesperrow;
-			src += srcbytesperrow;
-		}
-	} else {
-		for (y = 0; y < pheight; y++) {
-			copyrow(src, dst, 0, y, pwidth, srcbytesperrow, srcpixbytes, dstbytesperrow, dstpixbytes, direct, mode_convert);
-		}
+	for (int y = 0; y < pheight; y++) {
+		copyrow(src, dst, 0, y, pwidth, srcbytesperrow, srcpixbytes, dstbytesperrow, dstpixbytes, mode_convert);
 	}
 }
 
@@ -4402,8 +4424,7 @@ uae_u8 *uaegfx_getrtgbuffer(int monid, int *widthp, int *heightp, int *pitch, in
 	int off = picasso96_state.XYOffset - gfxmem_bank.start;
 	int width, height, pixbytes;
 	uae_u8 *dst;
-	int convert;
-	int hmode;
+	int convert[2];
 
 	if (!picasso_vidinfo.extra_mem)
 		return NULL;
@@ -4415,21 +4394,11 @@ uae_u8 *uaegfx_getrtgbuffer(int monid, int *widthp, int *heightp, int *pitch, in
 	dst = xmalloc (uae_u8, width * height * pixbytes);
 	if (!dst)
 		return NULL;
-	hmode = pixbytes == 1 ? RGBFB_CLUT : RGBFB_B8G8R8A8;
-	convert = getconvert (picasso96_state.RGBFormat, pixbytes);
+	convert[0] = getconvert (picasso96_state.RGBFormat, pixbytes);
+	convert[1] = convert[0];
 	alloc_colors_picasso(8, 8, 8, 16, 8, 0, picasso96_state.RGBFormat);
 
-	if (pixbytes > 1 && hmode != convert) {
-		copyall (src + off, dst, width, height, picasso96_state.BytesPerRow, picasso96_state.BytesPerPixel, width * pixbytes, pixbytes, false, convert);
-	} else {
-		uae_u8 *dstp = dst;
-		uae_u8 *srcp = src;
-		for (int y = 0; y < height; y++) {
-			memcpy (dstp, srcp, width * pixbytes);
-			dstp += width * pixbytes;
-			srcp += picasso96_state.BytesPerRow;
-		}
-	}
+	copyall (src + off, dst, width, height, picasso96_state.BytesPerRow, picasso96_state.BytesPerPixel, width * pixbytes, pixbytes, convert);
 	if (pixbytes == 1) {
 		for (int i = 0; i < 256; i++) {
 			palette[i * 3 + 0] = picasso96_state.CLUT[i].Red;
@@ -4571,12 +4582,12 @@ static void picasso_flushpixels(int index, uae_u8 *src, int off, bool render)
 					copyallinvert(src + off, dst, pwidth, pheight,
 						picasso96_state.BytesPerRow, picasso96_state.BytesPerPixel,
 						picasso_vidinfo.rowbytes, picasso_vidinfo.pixbytes,
-						picasso96_state.RGBFormat == host_mode, picasso_convert);
+						picasso_convert);
 				} else {
 					copyall(src + off, dst, pwidth, pheight,
 						picasso96_state.BytesPerRow, picasso96_state.BytesPerPixel,
 						picasso_vidinfo.rowbytes, picasso_vidinfo.pixbytes,
-						picasso96_state.RGBFormat == host_mode, picasso_convert);
+						picasso_convert);
 				}
 				miny = 0;
 				maxy = pheight;
@@ -4611,7 +4622,7 @@ static void picasso_flushpixels(int index, uae_u8 *src, int off, bool render)
 							copyrow(src + off, dst, x, y, pwidth - x,
 								picasso96_state.BytesPerRow, picasso96_state.BytesPerPixel,
 								picasso_vidinfo.rowbytes, picasso_vidinfo.pixbytes,
-								picasso96_state.RGBFormat == host_mode, picasso_convert);
+								picasso_convert);
 							flushlines++;
 						}
 						w = (gwwpagesize - (picasso96_state.BytesPerRow - x * picasso96_state.BytesPerPixel) + picasso96_state.BytesPerPixel - 1) / picasso96_state.BytesPerPixel;
@@ -4624,7 +4635,7 @@ static void picasso_flushpixels(int index, uae_u8 *src, int off, bool render)
 							copyrow(src + off, dst, 0, y, maxw,
 								picasso96_state.BytesPerRow, picasso96_state.BytesPerPixel,
 								picasso_vidinfo.rowbytes, picasso_vidinfo.pixbytes,
-								picasso96_state.RGBFormat == host_mode, picasso_convert);
+								picasso_convert);
 							w -= maxw;
 							y++;
 							flushlines++;
@@ -4971,6 +4982,8 @@ static void inituaegfxfuncs(TrapContext *ctx, uaecptr start, uaecptr ABI)
 	RTGCALLDEFAULT(PSSO_BoardInfo_DrawLine, PSSO_BoardInfo_DrawLineDefault);
 
 	RTGCALL2(PSSO_SetSplitPosition, picasso_SetSplitPosition);
+	RTGCALL2(PSSO_BoardInfo_GetCompatibleDACFormats, picasso_GetCompatibleDACFormats);
+	RTGCALL2(PSSO_BoardInfo_CoerceMode, picasso_CoerceMode);
 
 	if (currprefs.rtg_hardwareinterrupt)
 		RTGCALL2(PSSO_BoardInfo_SetInterrupt, picasso_SetInterrupt);
@@ -4991,6 +5004,7 @@ static void picasso_reset (void)
 		reserved_gfxmem = 0;
 		resetpalette ();
 		picasso96_state.dualclut = false;
+		picasso96_state.advDragging = false;
 		InitPicasso96 ();
 	}
 }
diff --git a/od-win32/picasso96_win.h b/od-win32/picasso96_win.h
index 4221af5c6..6b81a57a2 100644
--- a/src/od-win32/picasso96_win.h
+++ b/src/od-win32/picasso96_win.h
@@ -396,10 +396,10 @@ enum {
 #define PSSO_BoardInfo_Reserved0Default		    PSSO_BoardInfo_Reserved0 + 4
 #define PSSO_BoardInfo_Reserved1		    PSSO_BoardInfo_Reserved0Default + 4
 #define PSSO_SetSplitPosition		    PSSO_BoardInfo_Reserved1 + 4
-#define PSSO_BoardInfo_Reserved2		    PSSO_SetSplitPosition + 4
-#define PSSO_BoardInfo_Reserved2Default		    PSSO_BoardInfo_Reserved2 + 4
-#define PSSO_BoardInfo_Reserved3		    PSSO_BoardInfo_Reserved2Default + 4
-#define PSSO_BoardInfo_Reserved3Default		    PSSO_BoardInfo_Reserved3 + 4
+#define PSSO_ReInitMemory		    PSSO_SetSplitPosition + 4
+#define PSSO_BoardInfo_GetCompatibleDACFormats		    PSSO_ReInitMemory + 4
+#define PSSO_BoardInfo_CoerceMode		    PSSO_BoardInfo_GetCompatibleDACFormats + 4
+#define PSSO_BoardInfo_Reserved3Default		    PSSO_BoardInfo_CoerceMode + 4
 #define PSSO_BoardInfo_Reserved4		    PSSO_BoardInfo_Reserved3Default + 4
 #define PSSO_BoardInfo_Reserved4Default		    PSSO_BoardInfo_Reserved4 + 4
 #define PSSO_BoardInfo_Reserved5		    PSSO_BoardInfo_Reserved4Default + 4
@@ -559,7 +559,7 @@ struct picasso96_state_struct
     // everytime windows can remove your surface from card so the mainrender place
     // must be in memory
     long		XYOffset;
-    bool        dualclut;
+    bool        dualclut, advDragging;
 };
 
 extern void InitPicasso96 (void);
openSUSE Build Service is sponsored by