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);