File dualpalettesupport.patch of Package fs-uae

From 5413a3000a7e5dde59290f98d28f358a19b12e71 Mon Sep 17 00:00:00 2001
From: Toni Wilen <twilen@winuae.net>
Date: Thu, 10 Jun 2021 19:38:39 +0300
Subject: [PATCH] Screen dragging fix and dual palette support, fix bad VRAM
 pointer check.

---
 od-win32/picasso96_win.cpp | 265 ++++++++++++++++++++++---------------
 od-win32/picasso96_win.h   |  36 +++--
 2 files changed, 183 insertions(+), 118 deletions(-)

diff --git a/od-win32/picasso96_win.cpp b/od-win32/picasso96_win.cpp
index 0fd0cad56..aa2e4e54c 100644
--- a/src/od-win32/picasso96_win.cpp
+++ b/src/od-win32/picasso96_win.cpp
@@ -416,12 +416,13 @@ static int CopyRenderInfoStructureA2U(TrapContext *ctx, uaecptr amigamemptr, str
 	if (valid_address (amigamemptr, PSSO_RenderInfo_sizeof)) {
 		uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
 		ri->AMemory = memp;
-		ri->Memory = get_real_address (memp);
 		ri->BytesPerRow = get_word (amigamemptr + PSSO_RenderInfo_BytesPerRow);
 		ri->RGBFormat = (RGBFTYPE)get_long (amigamemptr + PSSO_RenderInfo_RGBFormat);
 		// Can't really validate this better at this point, no height.
-		if (valid_address (memp, ri->BytesPerRow))
+		if (valid_address (memp, ri->BytesPerRow)) {
+			ri->Memory = get_real_address(memp);
 			return 1;
+		}
 	}
 	write_log (_T("ERROR - Invalid RenderInfo memory area...\n"));
 	return 0;
@@ -431,7 +432,6 @@ static int CopyPatternStructureA2U(TrapContext *ctx, uaecptr amigamemptr, struct
 {
 	if (valid_address (amigamemptr, PSSO_Pattern_sizeof)) {
 		uaecptr memp = get_long (amigamemptr + PSSO_Pattern_Memory);
-		pattern->Memory = get_real_address (memp);
 		pattern->XOffset = get_word (amigamemptr + PSSO_Pattern_XOffset);
 		pattern->YOffset = get_word (amigamemptr + PSSO_Pattern_YOffset);
 		pattern->FgPen = get_long (amigamemptr + PSSO_Pattern_FgPen);
@@ -438,8 +438,10 @@ static int CopyPatternStructureA2U(TrapContext *ctx, uaecptr amigamemptr, struct
 		pattern->BgPen = get_long (amigamemptr + PSSO_Pattern_BgPen);
 		pattern->Size = get_byte (amigamemptr + PSSO_Pattern_Size);
 		pattern->DrawMode = get_byte (amigamemptr + PSSO_Pattern_DrawMode);
-		if (valid_address (memp, 2))
+		if (valid_address (memp, 2)) {
+			pattern->Memory = get_real_address(memp);
			return 1;
+		}
	}
	write_log (_T("ERROR - Invalid Pattern memory area...\n"));
	return 0;
@@ -494,6 +496,10 @@ static int CopyTemplateStructureA2U(TrapContext *ctx, uaecptr amigamemptr, struc
 	uaecptr memp = get_long (amigamemptr + PSSO_Template_Memory);
 
 	if (valid_address (memp, sizeof(struct Template))) {
+		if (!valid_address(memp, 1)) {
+			write_log(_T("ERROR - Invalid Template memory region %08x...\n"), memp);
+			return 0;
+		}
 		tmpl->Memory = get_real_address (memp);
 		tmpl->BytesPerRow = get_word (amigamemptr + PSSO_Template_BytesPerRow);
 		tmpl->XOffset = get_byte (amigamemptr + PSSO_Template_XOffset);
@@ -1643,6 +1651,9 @@ int createwindowscursor(int monid, uaecptr src, int w, int h, int hiressprite, i
 		ct = cursorrgbn;
 	}
 	datasize = h * ((w + 15) / 16) * 4;
+	if (!valid_address(src, datasize)) {
+		goto exit;
+	}
 	realsrc = get_real_address (src);
 
 	if (w > 64 || h > 64)
@@ -2606,6 +2617,7 @@ static void inituaegfx(TrapContext *ctx, uaecptr ABI)
 		flags |= BIF_INDISPLAYCHAIN;
 	}
 	flags |= BIF_VGASCREENSPLIT;
+	flags |= BIF_PALETTESWITCH;
 	put_long (ABI + PSSO_BoardInfo_Flags, flags);
 	if (debug_rtg_blitter != 3)
 		write_log (_T("P96: Blitter mode = %x!\n"), debug_rtg_blitter);
@@ -2770,8 +2780,9 @@ void picasso_enablescreen(int monid, int on)
 
 static void resetpalette(void)
 {
-	for (int i = 0; i < 256 * 2; i++)
+	for (int i = 0; i < 256 * 2; i++) {
 		picasso96_state.CLUT[i].Pad = 0xff;
+	}
 }
 
 /*
@@ -2789,31 +2800,32 @@ static void resetpalette(struct picasso96_state_struct *state)
 * per cannon your board has. So you might have to shift the colors
 * before writing them to the hardware.
 */
-static int updateclut (uaecptr clut, int start, int count)
+static int updateclut (uaecptr clut, int start, int count, int offset)
 {
 	int i, changed = 0;
 	clut += start * 3;
 	for (i = start; i < start + count; i++) {
+		int coffset = i + offset;
 		int r = get_byte (clut);
 		int g = get_byte (clut + 1);
 		int b = get_byte (clut + 2);
 
 		//write_log(_T("%d: %02x%02x%02x\n"), i, r, g, b);
-		changed |= picasso96_state.CLUT[i].Red != r
-			|| picasso96_state.CLUT[i].Green != g
-			|| picasso96_state.CLUT[i].Blue != b;
-		if (picasso96_state.CLUT[i].Pad) {
+		changed |= picasso96_state.CLUT[coffset].Red != r
+			|| picasso96_state.CLUT[coffset].Green != g
+			|| picasso96_state.CLUT[coffset].Blue != b;
+		if (picasso96_state.CLUT[coffset].Pad) {
 			changed = 1;
-			picasso96_state.CLUT[i].Pad = 0;
+			picasso96_state.CLUT[coffset].Pad = 0;
 		}
-		picasso96_state.CLUT[i].Red = r;
-		picasso96_state.CLUT[i].Green = g;
-		picasso96_state.CLUT[i].Blue = b;
-		picasso96_state.CLUT[i + 256].Red = r;
-		picasso96_state.CLUT[i + 256].Green = g;
-		picasso96_state.CLUT[i + 256].Blue = b;
+		picasso96_state.CLUT[coffset].Red = r;
+		picasso96_state.CLUT[coffset].Green = g;
+		picasso96_state.CLUT[coffset].Blue = b;
 		clut += 3;
+	}
+	if (offset) {
+		picasso96_state.dualclut = true;
 	}
 	changed |= picasso_palette ();
 	return changed;
 }
@@ -2818,9 +2830,15 @@ static uae_u32 REGPARAM2 picasso_SetColorArray (TrapContext *ctx)
 	uae_u16 count = m68k_dreg (regs, 1);
 	uaecptr boardinfo = m68k_areg (regs, 0);
 	uaecptr clut = boardinfo + PSSO_BoardInfo_CLUT;
-	if (start > 256 || start + count > 256)
+	int offset = 0;
+	if (start > 512 || count > 512 || start + count > 512)
 		return 0;
-	if (updateclut (clut, start, count))
+	if (start >= 256) {
+		clut = boardinfo + PSSO_BoardInfo_SecondaryCLUT;
+		start -= 256;
+		offset = 256;
+	}
+	if (updateclut(clut, start, count, offset))
 		full_refresh = 1;
 	P96TRACE((_T("SetColorArray(%d,%d)\n"), start, count));
 	return 1;
@@ -3002,8 +3019,11 @@ static uae_u32 picasso_SetSplitPosition(TrapContext *ctx)
 	//lockrtg();
 	//int monid = currprefs.rtgboards[0].monitor_id;
 	//struct picasso_vidbuf_description *vidinfo = &picasso_vidinfo[monid];
+	uaecptr bi = m68k_areg(regs, 0);

-	uae_s16 pos = m68k_dreg (regs, 0) - 1;
+	uae_s16 pos = m68k_dreg (regs, 0);
+	put_word(bi + PSSO_BoardInfo_YSplit, pos);
+	pos--;
 	if (pos != picasso_vidinfo.splitypos) {
 		picasso_vidinfo.splitypos = pos;
 		full_refresh = 1;
@@ -4030,7 +4064,7 @@ void picasso_statusline(int monid, uae_u8 *dst)
 #include "statusline.h"
 void picasso_statusline (uae_u8 *dst)
 {
-	int y, yy, slx, sly;
+	int y, yy, slx, sly; //was: int y, slx, sly;
 	int dst_height, dst_width, pitch;
 
 	dst_height = picasso96_state.Height;
@@ -4080,7 +4100,9 @@ static void copyrow (int monid, uae_u8 *src, uae_u8 *dst, int x, int y, int widt
 
 	if (y >= picasso_vidinfo.splitypos && picasso_vidinfo.splitypos >= 0) {
 		src = gfxmem_bank.start + natmem_offset;
-		clut += 256;
+		if (picasso96_state.dualclut) {
+			clut += 256;
+		}
 		y -= picasso_vidinfo.splitypos;
 	}
 
@@ -4402,8 +4422,8 @@ static void picasso_flushpixels(int index, uae_u8 *src, int off, bool render)
 bool picasso_flushpixels (uae_u8 *src, int off)
 {
 	int i;
-	uae_u8 *src_start;
-	uae_u8 *src_end;
+	uae_u8 *src_start[2];
+	uae_u8 *src_end[2];
 	int lock = 0;
 	uae_u8 *dst = NULL;
 #ifdef FSUAE
@@ -4421,15 +4441,22 @@ static void picasso_flushpixels(int index, uae_u8 *src, int off, bool render)
 	picasso_vidinfo.extra_mem = 1;
 #endif
 
-	src_start = src + (off & ~gwwpagemask);
-	src_end = src + ((off + picasso96_state.BytesPerRow * pheight + gwwpagesize - 1) & ~gwwpagemask);
+	src_start[0] = src + (off & ~gwwpagemask);
+	src_end[0] = src + ((off + picasso96_state.BytesPerRow * pheight + gwwpagesize - 1) & ~gwwpagemask);
+	if (picasso_vidinfo.splitypos >= 0) {
+		src_end[0] = src + ((off + picasso96_state.BytesPerRow * picasso_vidinfo.splitypos + gwwpagesize - 1) & ~gwwpagemask);
+		src_start[1] = src;
+		src_end[1] = src + ((picasso96_state.BytesPerRow * (pheight - picasso_vidinfo.splitypos) + gwwpagesize - 1) & ~gwwpagemask);
+	} else {
+		src_start[1] = src_end[1] = 0;
+	}
 #if 0
 	write_log (_T("%dx%d %dx%d %dx%d (%dx%d)\n"), picasso96_state.Width, picasso96_state.Width,
 		picasso96_state.VirtualWidth, picasso96_state.VirtualHeight,
 		picasso_vidinfo.width, picasso_vidinfo.height,
 		pwidth, pheight);
 #endif
-	if (!picasso_vidinfo.extra_mem || !gwwbuf || src_start >= src_end) {
+	if (!picasso_vidinfo.extra_mem || !gwwbuf || (src_start[0] >= src_end[0] && src_start[1] >= src_end[1])) {
 #ifdef FSUAE
 		printf("%d %p %d returning\n", picasso_vidinfo.extra_mem, gwwbuf, src_start >= src_end);
 #endif
@@ -4454,103 +4481,123@@ static void picasso_flushpixels(int index, uae_u8 *src, int off, bool render)
 			break;
 		}
 
-		if (full_refresh < 0) {
-			gwwcnt = (src_end - src_start) / gwwpagesize + 1;
-			full_refresh = 1;
-			for (i = 0; i < gwwcnt; i++)
-				gwwbuf[i] = src_start + i * gwwpagesize;
-		} else {
-			ULONG ps;
-			gwwcnt = gwwbufsize;
-#ifdef FSUAE
-#else
-			if (mman_GetWriteWatch (src_start, src_end - src_start, gwwbuf, &gwwcnt, &ps))
-				break;
-#endif
-		}
-
-		matchcount += gwwcnt;
 
-		if (gwwcnt == 0)
-			break;
+		for (int split = 0; split < 2; split++) {
+			uae_u32 regionsize = src_end[split] - src_start[split];
+			if (src_start[split] == 0 && src_end[split] == 0) {
+				break;
+			}
 
-		dofull = gwwcnt >= ((src_end - src_start) / gwwpagesize) * 80 / 100;
+			if (full_refresh < 0) {
+				gwwcnt = regionsize / gwwpagesize + 1;
+				full_refresh = 1;
+				for (i = 0; i < gwwcnt; i++)
+					gwwbuf[i] = src_start[split] + i * gwwpagesize;
+			} else {
+				ULONG ps;
+				gwwcnt = gwwbufsize;
+#ifdef FSUAE
+#else
+				if (mman_GetWriteWatch(src_start[split], regionsize, gwwbuf, &gwwcnt, &ps))
+					continue;
+#endif
+			}
 
-		dst = gfx_lock_picasso (dofull, rtg_clear_flag != 0);
-		if (rtg_clear_flag)
-			rtg_clear_flag--;
-		if (dst == NULL)
-			break;
-		lock = 1;
-		dst += picasso_vidinfo.offset;
+			matchcount += gwwcnt;
 
-		if (doskip () && p96skipmode == 2) {
-#ifdef FSUAE
-			printf("breaking (2)\n");
-#endif
-			break;
-		}
+			if (gwwcnt == 0) {
+				continue;
+			}
 
-		if (dofull) {
-			if (flashscreen != 0)
-				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);
-			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);
-
-			miny = 0;
-			maxy = pheight;
-			flushlines = -1;
-			break;
-		}
+			dofull = gwwcnt >= (regionsize / gwwpagesize) * 80 / 100;
 
-		for (i = 0; i < gwwcnt; i++) {
-			uae_u8 *p = (uae_u8*)gwwbuf[i];
+			dst = gfx_lock_picasso(dofull, rtg_clear_flag != 0);
+			if (rtg_clear_flag)
+				rtg_clear_flag--;
+			if (dst == NULL) {
+				continue;
+			}
+			lock = 1;
+			dst += picasso_vidinfo.offset;
 
-			if (p >= src_start && p < src_end) {
-				int y, x, realoffset;
+			if (doskip() && p96skipmode == 2) {
+#ifdef FSUAE
+			printf("breaking (2)\n");
+#endif
+				continue;
+			}
 
-				if (p >= src + off) {
-					realoffset = p - (src + off);
+			if (dofull) {
+				if (flashscreen != 0) {
+					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);
 				} else {
-					realoffset = 0;
+					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);
 				}
+				miny = 0;
+				maxy = pheight;
+				flushlines = -1;
+				break;
+			}
+
+			if (split) {
+				off = 0;
+			}
+
+			for (i = 0; i < gwwcnt; i++) {
+				uae_u8 *p = (uae_u8 *)gwwbuf[i];
 
-				y = realoffset / picasso96_state.BytesPerRow;
-				if (y < pheight) {
-					int w = gwwpagesize / picasso96_state.BytesPerPixel;
-					x = (realoffset % picasso96_state.BytesPerRow) / picasso96_state.BytesPerPixel;
-					if (x < pwidth)
-						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);
-						flushlines++;
+				if (p >= src_start[split] && p < src_end[split]) {
+					int y, x, realoffset;
+
+					if (p >= src + off) {
+						realoffset = p - (src + off);
+					} else {
+						realoffset = 0;
+					}
-					w = (gwwpagesize - (picasso96_state.BytesPerRow - x * picasso96_state.BytesPerPixel)) / picasso96_state.BytesPerPixel;
-					if (y < miny)
-						miny = y;
-					y++;
-					while (y < pheight && w > 0) {
-						int maxw = w > pwidth ? pwidth : w;
-						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);
-						w -= maxw;
+
+					y = realoffset / picasso96_state.BytesPerRow;
+					if (split) {
+						y += picasso_vidinfo.splitypos;
+					}
+					if (y < pheight) {
+						int w = (gwwpagesize + picasso96_state.BytesPerPixel - 1) / picasso96_state.BytesPerPixel;
+						x = (realoffset % picasso96_state.BytesPerRow) / picasso96_state.BytesPerPixel;
+						if (x < pwidth) {
+							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);
+							flushlines++;
+						}
+						w = (gwwpagesize - (picasso96_state.BytesPerRow - x * picasso96_state.BytesPerPixel) + picasso96_state.BytesPerPixel - 1) / picasso96_state.BytesPerPixel;
+						if (y < miny) {
+							miny = y;
+						}
 						y++;
-						flushlines++;
+						while (y < pheight && w > 0) {
+							int maxw = w > pwidth ? pwidth : w;
+							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);
+							w -= maxw;
+							y++;
+							flushlines++;
+						}
+						if (y > maxy) {
+							maxy = y;
+						}
 					}
-					if (y > maxy)
-						maxy = y;
+
 				}
 
 			}
-
 		}
 		break;
 	}
@@ -4902,6 +4963,7 @@ static void picasso_reset2(int monid)
 		interrupt_enabled = 0;
 		reserved_gfxmem = 0;
 		resetpalette ();
+		picasso96_state.dualclut = false;
 		InitPicasso96 ();
 	}
 }
diff --git a/od-win32/picasso96_win.h b/od-win32/picasso96_win.h
index 74b86a742..c9866c4b1 100644
--- a/src/od-win32/picasso96_win.h
+++ b/src/od-win32/picasso96_win.h
@@ -459,7 +459,18 @@ enum {
 #define PSSO_BoardInfo_SyncTime			    PSSO_BoardInfo_DoubleBufferList + 4
 #define PSSO_BoardInfo_SyncPeriod		    PSSO_BoardInfo_SyncTime + 4
 #define PSSO_BoardInfo_SoftVBlankPort		    PSSO_BoardInfo_SyncPeriod + 8
-#define PSSO_BoardInfo_SizeOf			    PSSO_BoardInfo_SoftVBlankPort + 34
+#define PSSO_BoardInfo_WaitQ                PSSO_BoardInfo_SoftVBlankPort + 34
+#define PSSO_BoardInfo_EssentialFormats     PSSO_BoardInfo_WaitQ + 3 * 4
+#define PSSO_BoardInfo_MouseImageBuffer     PSSO_BoardInfo_EssentialFormats + 4
+#define PSSO_BoardInfo_BackViewPort         PSSO_BoardInfo_MouseImageBuffer + 4
+#define PSSO_BoardInfo_BackBitMap           PSSO_BoardInfo_BackViewPort + 4
+#define PSSO_BoardInfo_BackBitMapExtra      PSSO_BoardInfo_BackBitMap + 4
+#define PSSO_BoardInfo_YSplit               PSSO_BoardInfo_BackBitMapExtra + 4
+#define PSSO_BoardInfo_MaxPlanarMemory      PSSO_BoardInfo_YSplit + 2
+#define PSSO_BoardInfo_MaxBMWidth           PSSO_BoardInfo_MaxPlanarMemory + 4
+#define PSSO_BoardInfo_MaxBMHeight          PSSO_BoardInfo_MaxBMWidth + 4
+#define PSSO_BoardInfo_SecondaryCLUT        PSSO_BoardInfo_MaxBMHeight + 4
+#define PSSO_BoardInfo_SizeOf			    PSSO_BoardInfo_SecondaryCLUT + 3 * 256
 
 /* BoardInfo flags */
 /*  0-15: hardware flags */
@@ -487,6 +498,7 @@ enum {
 #define BIB_NOMASKBLITS		22	/* perform blits without taking care of mask */
 #define BIB_NOC2PBLITS		23	/* use CPU for planar to chunky conversions */
 #define BIB_NOBLITTER		24	/* disable all blitter functions */
+#define BIB_PALETTESWITCH		27
 #define BIB_OVERCLOCK		31	/* enable overclocking for some boards */
 
 #define BIB_IGNOREMASK	BIB_NOMASKBLITS
@@ -514,6 +526,7 @@ enum {
 #define BIF_NOMASKBLITS		(1 << BIB_NOMASKBLITS)
 #define BIF_NOC2PBLITS		(1 << BIB_NOC2PBLITS)
 #define BIF_NOBLITTER		(1 << BIB_NOBLITTER)
+#define BIF_PALETTESWITCH		(1 << BIB_PALETTESWITCH)
 #define BIF_OVERCLOCK		(1 << BIB_OVERCLOCK)
 
 #define BIF_IGNOREMASK 	BIF_NOMASKBLITS
@@ -546,6 +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;
 };
 
 extern void InitPicasso96 (void);
openSUSE Build Service is sponsored by