int have_done_picasso; /* For the JIT compiler */
static int vsyncgfxwrite = 0;
static int p96syncrate, vsyncgfxcount;
-static int p96hsync_counter;
-
+int p96hsync_counter, palette_changed;
+#if defined(X86_MSVC_ASSEMBLY)
+#define SWAPSPEEDUP
+#endif
+#ifdef PICASSO96
#ifdef DEBUG // Change this to _DEBUG for debugging
#define P96TRACING_ENABLED 1
#define P96TRACING_LEVEL 1
#define PIXEL_LOCK //and scrollable screens
#define MAXFLUSHPIXEL 3200 //pixel draw in a lock
static void flushpixels(void);
-static int pixelcount, palette_changed;
-struct pixel32{
- uaecptr addr;
- uae_u32 value;
- int size;
-};
-static struct pixel32 pixelbase[MAXFLUSHPIXEL + 2];
#ifdef P96TRACING_ENABLED
#define P96TRACE(x) do { write_log x; } while(0)
#else
#define P96TRACE(x)
#endif
-#define P96TRACEX(x) do { write_log x; } while(0)
#define GetBytesPerPixel(x) GetBytesPerPixel2(x,__FILE__,__LINE__)
#if defined(JIT)
+#define P96_SM_RW special_mem |= PIC_READ | PIC_WRITE;
#define P96_SM_R special_mem |= PIC_READ;
#define P96_SM_W special_mem |= PIC_WRITE;
#else
+#define P96_SM_RW
#define P96_SM_R
#define P96_SM_W
#endif
//fastscreen
static uaecptr oldscr = 0;
#ifdef _DEBUG
-static void PICASSO96_Unlock2(char *filename, int linenum)
+void PICASSO96_Unlock2(char *filename, int linenum)
#else
-static void PICASSO96_Unlock(void)
+void PICASSO96_Unlock(void)
#endif
{
#ifdef LOCK_UNLOCK_MADNESS
#if defined(P96TRACING_ENABLED) && P96TRACING_LEVEL > 1
// This format of output lets you double-click and jump to file/line
- write_log("%s(%d) : calling P96 UNLOCK with picasso_on=%d\n", filename, linenum, picasso_on);
+ write_log( "%s(%d) : calling P96 UNLOCK with picasso_on=%d\n", filename, linenum, picasso_on);
#endif
- if(picasso_on) {
+ if(picasso_on)
+ {
#ifdef PIXEL_LOCK
flushpixels();
#endif
gfx_unlock_picasso ();
- picasso96_state.HostAddress = NULL;
}
#endif
}
#ifdef _DEBUG
-static void PICASSO96_Lock2(char *filename, int linenum)
+void PICASSO96_Lock2(char *filename, int linenum)
#else
-static void PICASSO96_Lock(void)
+void PICASSO96_Lock(void)
#endif
{
#ifdef LOCK_UNLOCK_MADNESS
#if defined(P96TRACING_ENABLED) && P96TRACING_LEVEL > 1
// This format of output lets you double-click and jump to file/line
- write_log( "%s(%d) : calling P96 LOCK with picasso_on=%d\n", filename, linenum, picasso_on );
+ write_log( "%s(%d) : calling P96 LOCK with picasso_on=%d\n", filename, linenum, picasso_on);
#endif
- if(picasso_on) {
+ if(picasso_on)
+ {
picasso96_state.HostAddress = gfx_lock_picasso ();
}
#endif
write_log("Line->Xorigin = %d\n", line->Xorigin);
write_log("Line->Yorigin = %d\n", line->Yorigin);
}
-}
#endif
static void ShowSupportedResolutions (void)
return 2;
default:
write_log ("ERROR - GetBytesPerPixel() from %s@%d was unsuccessful with 0x%x?!\n", file, line, RGBfmt);
- if(!bFailure) {
+ if(!bFailure)
+ {
bFailure = TRUE;
return GetBytesPerPixel(picasso_vidinfo.rgbformat);
- } else {
+ }
+ else
+ {
abort();
}
}
bm->Depth = 8;
for (i = 0; i < bm->Depth; i++) {
- uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i * 4);
+ uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i*4);
switch (plane) {
case 0:
bm->Planes[i] = &all_zeros_bitmap;
* filled rectangle in the frame buffer; it can be used as a memcpy source if
* there is no OS specific function to fill the rectangle.
*/
-static void do_fillrect(uae_u8 *src, unsigned int x, unsigned int y, unsigned int width, unsigned int height, uae_u32 pen, int Bpp, RGBFTYPE rgbtype)
+static void do_fillrect(uae_u8 *src, unsigned int x, unsigned int y,
+ unsigned int width, unsigned int height,
+ uae_u32 pen, int Bpp, RGBFTYPE rgbtype)
{
uae_u8 *dst;
- int orig_width = width;
- int orig_height = height;
-
+
/* Try OS specific fillrect function here; and return if successful. Make sure we adjust for
- * the pen values if we're doing 8-bit display-emulation on a 16-bit or higher screen. */
+ * the pen values if we're doing 8-bit display-emulation on a 16-bit or higher screen. */
#ifdef PIXEL_LOCK
- flushpixels();
+ flushpixels();
#endif
- if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
+ if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+ {
if(DX_Fill(x, y, width, height, pen, rgbtype))
return;
- } else {
+ }
+ else
+ {
if(DX_Fill(x, y, width, height, picasso_vidinfo.clut[src[0]], rgbtype))
return;
}
-
+
P96TRACE(("P96_WARNING: do_fillrect() using fall-back routine!\n"));
if(y + height > picasso_vidinfo.height)
if(x + width > picasso_vidinfo.width)
width = picasso_vidinfo.width - x;
+ DX_Invalidate (x, y, width, height);
if (! picasso_vidinfo.extra_mem)
return;
-
+
#ifdef LOCK_UNLOCK_MADNESS
PICASSO96_Lock();
dst = picasso96_state.HostAddress;
#ifndef LOCK_UNLOCK_MADNESS
gfx_unlock_picasso ();
#else
- PICASSO96_Unlock();
+ PICASSO96_Unlock();
#endif
- DX_Invalidate (x, y, orig_width, orig_height);
}
/*
* the RenderInfo data and our coordinates.
*/
static void do_blit(struct RenderInfo *ri, int Bpp,
- unsigned int srcx, unsigned int srcy,
- unsigned int dstx, unsigned int dsty,
- unsigned int width, unsigned int height,
- BLIT_OPCODE opcode, int can_do_blit)
+ unsigned int srcx, unsigned int srcy, unsigned int dstx, unsigned int dsty,
+ unsigned int width, unsigned int height, BLIT_OPCODE opcode, int can_do_blit)
{
uae_u8 *dstp, *srcp;
- int orig_width, orig_height;
+ int orig_height = height;
if(picasso96_state.BigAssBitmap && can_do_blit) {
srcx = dstx;
if (picasso96_state.XOffset < 0)
can_do_blit = 0;
- dstx = dstx - picasso96_state.XOffset;
- dsty = dsty - picasso96_state.YOffset;
+ dstx=dstx - picasso96_state.XOffset;
+ dsty=dsty - picasso96_state.YOffset;
if((int)dstx <= 0) {
srcx = srcx - dstx;
dstx = 0;
}
if((int)dsty <= 0) {
- srcy = srcy - dsty;
+ srcy = srcy-dsty;
dsty = 0;
}
if(dstx + width >= picasso_vidinfo.width)
width = picasso_vidinfo.width - dstx;
- orig_height = height;
- orig_width = width;
-
- if (can_do_blit) {
+ if (can_do_blit)
+ {
//
// Call OS blitting function that can do it in video memory.
// Should return if it was successful
//
if(DX_Blit(srcx, srcy, dstx, dsty, width, height, opcode))
return;
- srcx = dstx;
- srcy = dsty;
- }
- if (opcode != BLIT_SRC) {
- write_log("do_blit() opcode = %d!\n", opcode);
- return;
+ srcx = dstx;
+ srcy = dsty;
}
-
#ifdef LOCK_UNLOCK_MADNESS
PICASSO96_Lock();
#endif
srcp = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
+ DX_Invalidate (dstx, dsty, width, height);
if (! picasso_vidinfo.extra_mem)
{
#ifdef LOCK_UNLOCK_MADNESS
#else
dstp = gfx_lock_picasso ();
#endif
- if (dstp == 0) {
+ if (dstp == 0)
+ {
write_log ("WARNING: do_blit() couldn't lock\n");
goto out;
}
/* The areas can't overlap: the source is always in the Picasso frame buffer,
* and the destination is a different buffer owned by the graphics code. */
dstp += dsty * picasso_vidinfo.rowbytes + dstx * picasso_vidinfo.pixbytes;
- P96TRACE(("do_blit with srcp %p, dstp %p, dst_rowbytes %d, srcx %d, srcy %d, dstx %d, dsty %d, w %d, h %d, dst_pixbytes %d\n",
+ P96TRACE(("do_blit with srcp 0x%x, dstp 0x%x, dst_rowbytes %d, srcx %d, srcy %d, dstx %d, dsty %d, w %d, h %d, dst_pixbytes %d\n",
srcp, dstp, picasso_vidinfo.rowbytes, srcx, srcy, dstx, dsty, width, height, picasso_vidinfo.pixbytes));
- P96TRACE(("gfxmem is at %p\n", gfxmemory));
+ P96TRACE(("gfxmem is at 0x%x\n",gfxmemory));
if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
{
dstp += picasso_vidinfo.rowbytes;
}
}
- out:;
+ out:
#ifndef LOCK_UNLOCK_MADNESS
gfx_unlock_picasso ();
#else
PICASSO96_Unlock();
#endif
- DX_Invalidate (dstx, dsty, orig_width, orig_height);
+ ;
}
/*
* so that do_blit can be used if
* there is no OS specific function to invert the rectangle.
*/
-static void do_invertrect(struct RenderInfo *ri, int Bpp, int x, int y, int width, int height)
+static void do_invertrect( struct RenderInfo *ri, int Bpp, int x, int y, int width, int height)
{
/* if(DX_InvertRect(x, y, width, height))
return;*/ //deactivate in 0.8.20
do_blit (ri, Bpp, x, y, x, y, width, height, BLIT_SRC, 0);
}
-#if 0
static uaecptr wgfx_linestart;
static uaecptr wgfx_lineend;
static uaecptr wgfx_min, wgfx_max;
uae_u8 *src, *dstp;
/* Mark these lines as "dirty" */
+ DX_Invalidate (0, wgfx_y, picasso_vidinfo.width, 1);
if (! picasso_vidinfo.extra_mem) /* The "out" will flush the dirty lines directly */
goto out;
#ifdef LOCK_UNLOCK_MADNESS
dstp = picasso96_state.HostAddress;
+
#else
dstp = gfx_lock_picasso ();
#endif
if (dstp == 0)
goto out;
-
#if P96TRACING_LEVEL > 0
P96TRACE(("flushing %d\n", wgfx_y));
#endif
-
src = gfxmemory + wgfx_min;
if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
P96TRACE(("flushing type-a\n"));
#endif
dstp += wgfx_y * picasso_vidinfo.rowbytes + wgfx_min - wgfx_linestart;
- memcpy (dstp, src, wgfx_max - wgfx_min);
+ memcpy (dstp, src, wgfx_max - wgfx_min);
}
else
{
#ifndef LOCK_UNLOCK_MADNESS
gfx_unlock_picasso ();
#endif
- DX_Invalidate (0, wgfx_y, -1, 1);
wgfx_linestart = 0xFFFFFFFF;
}
return;
wgfx_do_flushline ();
}
-#endif
static int renderinfo_is_current_screen (struct RenderInfo *ri)
{
/*
* Fill a rectangle in the screen.
*/
-static void do_fillrect_frame_buffer(struct RenderInfo *ri, int X, int Y, int Width, int Height, uae_u32 Pen, int Bpp, RGBFTYPE RGBFormat)
+STATIC_INLINE void do_fillrect_frame_buffer(struct RenderInfo *ri, int X, int Y,
+ int Width, int Height, uae_u32 Pen, int Bpp,
+ RGBFTYPE RGBFormat)
{
int cols;
uae_u8 *start, *oldstart;
void picasso_handle_vsync (void)
{
- flushpixels();
+ DX_Invalidate(-1, -1, -1, -1); //so a flushpixel is done every vsync if pixel are in buffer
PICASSO96_Unlock();
if (palette_changed) {
DX_SetPalette (0,256);
palette_changed = 0;
}
- if (vsyncgfxwrite == 1) {
+ if (vsyncgfxwrite==1) {
static long blitcount;
vsyncgfxcount++;
- if (vsyncgfxcount > 1) {
+ if (vsyncgfxcount>1) {
if (picasso_on) {
if (picasso96_state.RGBFormat == picasso_vidinfo.rgbformat
|| picasso96_state.RGBFormat == RGBFB_CHUNKY) {
struct RenderInfo ri;
static int beamcon0_before, p96refresh_was;
- if (! picasso_on)
- return;
+ if (! picasso_on)return;
{ //for higher P96 mousedraw rate
/* HACK */
extern uae_u16 vtotal;
if (p96hack_vpos2) {
- vtotal = p96hack_vpos2;
+ vtotal=p96hack_vpos2;
beamcon0_before = new_beamcon0;
new_beamcon0 |= 0x80;
p96refresh_active = 1;
/* HACK until ntsc timing is fixed.. */
} //end for higher P96 mousedraw rate
have_done_picasso = 1;
-
+
/* Make sure that the first time we show a Picasso video mode, we don't blit any crap.
- * We can do this by checking if we have an Address yet. */
+ * We can do this by checking if we have an Address yet. */
if (picasso96_state.Address) {
unsigned int width, height;
/*
* Functions to perform an action on the frame-buffer
*/
-static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *dstri,
- unsigned long srcx, unsigned long srcy,
- unsigned long dstx, unsigned long dsty,
- unsigned long width, unsigned long height,
- uae_u8 mask, BLIT_OPCODE opcode)
+STATIC_INLINE void do_blitrect_frame_buffer(struct RenderInfo *ri, struct
+RenderInfo *dstri, unsigned long srcx, unsigned long srcy,
+ unsigned long dstx, unsigned long dsty, unsigned long width, unsigned
+long height, uae_u8 mask, BLIT_OPCODE opcode)
{
uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
if(opcode == BLIT_SRC)
{
/* handle normal case efficiently */
- if (ri->Memory == dstri->Memory && dsty == srcy)
+ if (ri->Memory == dstri->Memory && dsty == srcy)
{
unsigned long i;
for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
unsigned long i;
for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
memcpy (dst, src, total_width);
- }
+ }
else
{
unsigned long i;
- src += (height - 1) * ri->BytesPerRow;
- dst += (height - 1) * dstri->BytesPerRow;
+ src += (height-1) * ri->BytesPerRow;
+ dst += (height-1) * dstri->BytesPerRow;
for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
memcpy (dst, src, total_width);
}
return;
}
- else
- {
- uae_u8 *src2;
- uae_u8 *dst2;
- unsigned int y;
-
+ else
+ {
+ uae_u8 *src2 = src;
+ uae_u8 *dst2 = dst;
+ uae_u32 *src2_32 = (uae_u32*)src;
+ uae_u32 *dst2_32 = (uae_u32*)dst;
+ unsigned int y;
+
for(y = 0; y < height; y++) /* Vertical lines */
{
- uae_u8 *bound = src + total_width - 4;
- uae_u32 *src2_32;
- uae_u32 *dst2_32;
- //copy now the longs
- for(src2_32 = (uae_u32*)src, dst2_32 = (uae_u32*)dst; src2_32 < (uae_u32*)bound; src2_32++, dst2_32++) /* Horizontal bytes */
+ uae_u8 *bound = src + total_width - 4;
+ //copy now the longs
+ for(src2_32 = (uae_u32*)src, dst2_32 = (uae_u32*)dst; src2_32 < (uae_u32*)bound; src2_32++, dst2_32++) /* Horizontal bytes */
+ {
+ switch(opcode)
{
- switch(opcode)
+ case BLIT_FALSE:
+ *dst2_32 = 0;
+ break;
+ case BLIT_NOR:
+ *dst2_32 = ~(*src2_32 | *dst2_32);
+ break;
+ case BLIT_ONLYDST:
+ *dst2_32 = *dst2_32 & ~(*src2_32);
+ break;
+ case BLIT_NOTSRC:
+ *dst2_32 = ~(*src2_32);
+ break;
+ case BLIT_ONLYSRC:
+ *dst2_32 = *src2_32 & ~(*dst2_32);
+ break;
+ case BLIT_NOTDST:
+ *dst2_32 = ~(*dst2_32);
+ break;
+ case BLIT_EOR:
+ *dst2_32 = *src2_32 ^ *dst2_32;
+ break;
+ case BLIT_NAND:
+ *dst2_32 = ~(*src2_32 & *dst2_32);
+ break;
+ case BLIT_AND:
+ *dst2_32 = *src2_32 & *dst2_32;
+ break;
+ case BLIT_NEOR:
+ *dst2_32 = ~(*src2_32 ^ *dst2_32);
+ break;
+ case BLIT_DST:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
+ break;
+ case BLIT_NOTONLYSRC:
+ *dst2_32 = ~(*src2_32) | *dst2_32;
+ break;
+ case BLIT_SRC:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
+ break;
+ case BLIT_NOTONLYDST:
+ *dst2_32 = ~(*dst2_32) | *src2_32;
+ break;
+ case BLIT_OR:
+ *dst2_32 = *src2_32 | *dst2_32;
+ break;
+ case BLIT_TRUE:
+ *dst2_32 = 0xFFFFFFFF;
+ break;
+ case 30: //code for swap source with dest in byte
+ {
+ uae_u32 temp;
+ temp = *src2_32;
+ *src2_32 = *dst2_32;
+ *dst2_32 = temp;
+ }
+ break;
+ case BLIT_LAST:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
+ break;
+ } /* switch opcode */
+ }// for end
+ //now copy the rest few bytes
+ for(src2 = (uae_u8*)src2_32, dst2 = (uae_u8*)dst2_32; src2 < src + total_width; src2++, dst2++) /* Horizontal bytes */
+ {
+ switch( opcode )
+ {
+ case BLIT_FALSE:
+ *dst2 = 0;
+ break;
+ case BLIT_NOR:
+ *dst2 = ~(*src2 | *dst2);
+ break;
+ case BLIT_ONLYDST:
+ *dst2 = *dst2 & ~(*src2);
+ break;
+ case BLIT_NOTSRC:
+ *dst2 = ~(*src2);
+ break;
+ case BLIT_ONLYSRC:
+ *dst2 = *src2 & ~(*dst2);
+ break;
+ case BLIT_NOTDST:
+ *dst2 = ~(*dst2);
+ break;
+ case BLIT_EOR:
+ *dst2 = *src2 ^ *dst2;
+ break;
+ case BLIT_NAND:
+ *dst2 = ~(*src2 & *dst2);
+ break;
+ case BLIT_AND:
+ *dst2 = *src2 & *dst2;
+ break;
+ case BLIT_NEOR:
+ *dst2 = ~(*src2 ^ *dst2);
+ break;
+ case BLIT_DST:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
+ break;
+ case BLIT_NOTONLYSRC:
+ *dst2 = ~(*src2) | *dst2;
+ break;
+ case BLIT_SRC:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
+ break;
+ case BLIT_NOTONLYDST:
+ *dst2 = ~(*dst2) | *src2;
+ break;
+ case BLIT_OR:
+ *dst2 = *src2 | *dst2;
+ break;
+ case BLIT_TRUE:
+ *dst2 = 0xFF;
+ break;
+ case BLIT_LAST:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
+ break;
+ case 30: //code for swap source with dest in long
{
- case BLIT_FALSE:
- *dst2_32 = 0;
- break;
- case BLIT_NOR:
- *dst2_32 = ~(*src2_32 | *dst2_32);
- break;
- case BLIT_ONLYDST:
- *dst2_32 = *dst2_32 & ~(*src2_32);
- break;
- case BLIT_NOTSRC:
- *dst2_32 = ~(*src2_32);
- break;
- case BLIT_ONLYSRC:
- *dst2_32 = *src2_32 & ~(*dst2_32);
- break;
- case BLIT_NOTDST:
- *dst2_32 = ~(*dst2_32);
- break;
- case BLIT_EOR:
- *dst2_32 = *src2_32 ^ *dst2_32;
- break;
- case BLIT_NAND:
- *dst2_32 = ~(*src2_32 & *dst2_32);
- break;
- case BLIT_AND:
- *dst2_32 = *src2_32 & *dst2_32;
- break;
- case BLIT_NEOR:
- *dst2_32 = ~(*src2_32 ^ *dst2_32);
- break;
- case BLIT_DST:
- write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
- break;
- case BLIT_NOTONLYSRC:
- *dst2_32 = ~(*src2_32) | *dst2_32;
- break;
- case BLIT_SRC:
- write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
- break;
- case BLIT_NOTONLYDST:
- *dst2_32 = ~(*dst2_32) | *src2_32;
- break;
- case BLIT_OR:
- *dst2_32 = *src2_32 | *dst2_32;
- break;
- case BLIT_TRUE:
- *dst2_32 = 0xFFFFFFFF;
- break;
- case 30: //code for swap source with dest in byte
- {
- uae_u32 temp;
- temp = *src2_32;
- *src2_32 = *dst2_32;
- *dst2_32 = temp;
+ uae_u8 temp;
+ temp = *src2;
+ *src2 = *dst2;
+ *dst2 = temp;
}
- break;
- case BLIT_LAST:
- write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
- break;
- } /* switch opcode */
- }// for end
- //now copy the rest few bytes
- for(src2 = (uae_u8*)src2_32, dst2 = (uae_u8*)dst2_32; src2 < src + total_width; src2++, dst2++) /* Horizontal bytes */
+ break;
+ } /* switch opcode */
+ } /* for width */
+ src += ri->BytesPerRow;
+ dst += dstri->BytesPerRow;
+ } /* for height */
+ }
+ return;
+ }
+
+ tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough
+memory for the src-rect */
+ if (!tmp)
+ return;
+
+ /* copy the src-rect into our temporary buffer space */
+ for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth)
+ {
+ memcpy (tmp2, src, total_width);
+ }
+
+ /* copy the temporary buffer to the destination */
+ for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp += linewidth)
+ {
+ unsigned long cols;
+ for (cols = 0; cols < width; cols++)
+ {
+ dst[cols] &= ~mask;
+ dst[cols] |= tmp[cols] & mask;
+ }
+ }
+ /* free the temp-buf */
+ free (tmp3);
+}
+
+#if 0
+/*
+* Functions to perform an action on the frame-buffer
+*/
+STATIC_INLINE void do_blitrect_frame_buffer( struct RenderInfo *ri, struct RenderInfo *dstri, unsigned long srcx, unsigned long srcy,
+ unsigned long dstx, unsigned long dsty, unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode )
+{
+
+ uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
+ uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
+ unsigned long total_width = width * Bpp;
+ unsigned long linewidth = (total_width + 15) & ~15;
+ unsigned long lines;
+ int can_do_visible_blit = 0;
+
+ src = ri->Memory + srcx*Bpp + srcy*ri->BytesPerRow;
+ dst = dstri->Memory + dstx*Bpp + dsty*dstri->BytesPerRow;
+ if (mask != 0xFF && Bpp > 1)
+ {
+ write_log ("WARNING - BlitRect() has mask 0x%x with Bpp %d.\n", mask, Bpp);
+ }
+
+ if (mask == 0xFF || Bpp > 1)
+ {
+ if( opcode == BLIT_SRC )
+ {
+ /* handle normal case efficiently */
+ if (ri->Memory == dstri->Memory && dsty == srcy)
+ {
+ unsigned long i;
+ for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
+ memmove (dst, src, total_width);
+ }
+ else if (dsty < srcy)
+ {
+ unsigned long i;
+ for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
+ memcpy (dst, src, total_width);
+ }
+ else
+ {
+ unsigned long i;
+ src += (height-1) * ri->BytesPerRow;
+ dst += (height-1) * dstri->BytesPerRow;
+ for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
+ memcpy (dst, src, total_width);
+ }
+ return;
+ }
+ else
+ {
+ uae_u8 *src2 = src;
+ uae_u8 *dst2 = dst;
+ unsigned int y;
+
+ for( y = 0; y < height; y++ ) /* Vertical lines */
+ {
+ for( src2 = src, dst2 = dst; src2 < src + total_width; src2++, dst2++ ) /* Horizontal bytes */
{
- switch(opcode)
+ switch( opcode )
{
case BLIT_FALSE:
- *dst2 = 0;
- break;
+ *dst2 = 0;
+ break;
case BLIT_NOR:
- *dst2 = ~(*src2 | *dst2);
- break;
+ *dst2 = ~(*src2 | *dst2);
+ break;
case BLIT_ONLYDST:
- *dst2 = *dst2 & ~(*src2);
- break;
+ *dst2 = *dst2 & ~(*src2);
+ break;
case BLIT_NOTSRC:
- *dst2 = ~(*src2);
- break;
+ *dst2 = ~(*src2);
+ break;
case BLIT_ONLYSRC:
- *dst2 = *src2 & ~(*dst2);
- break;
+ *dst2 = *src2 & ~(*dst2);
+ break;
case BLIT_NOTDST:
- *dst2 = ~(*dst2);
- break;
+ *dst2 = ~(*dst2);
+ break;
case BLIT_EOR:
- *dst2 = *src2 ^ *dst2;
- break;
+ *dst2 = *src2 ^ *dst2;
+ break;
case BLIT_NAND:
- *dst2 = ~(*src2 & *dst2);
- break;
+ *dst2 = ~(*src2 & *dst2);
+ break;
case BLIT_AND:
- *dst2 = *src2 & *dst2;
- break;
+ *dst2 = *src2 & *dst2;
+ break;
case BLIT_NEOR:
- *dst2 = ~(*src2 ^ *dst2);
- break;
+ *dst2 = ~(*src2 ^ *dst2);
+ break;
case BLIT_DST:
- write_log("do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
- break;
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n" );
+ break;
case BLIT_NOTONLYSRC:
- *dst2 = ~(*src2) | *dst2;
- break;
+ *dst2 = ~(*src2) | *dst2;
+ break;
case BLIT_SRC:
- write_log("do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
- break;
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n" );
+ break;
case BLIT_NOTONLYDST:
- *dst2 = ~(*dst2) | *src2;
- break;
+ *dst2 = ~(*dst2) | *src2;
+ break;
case BLIT_OR:
- *dst2 = *src2 | *dst2;
- break;
+ *dst2 = *src2 | *dst2;
+ break;
case BLIT_TRUE:
- *dst2 = 0xFF;
- break;
+ *dst2 = 0xFF;
+ break;
case BLIT_LAST:
- write_log("do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
- break;
- case 30: //code for swap source with dest in long
- {
- uae_u8 temp;
- temp = *src2;
- *src2 = *dst2;
- *dst2 = temp;
- }
- break;
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n" );
+ break;
} /* switch opcode */
} /* for width */
src += ri->BytesPerRow;
} /* for height */
}
return;
- }
+ }
tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough memory for the src-rect */
if (!tmp)
- return;
+ return;
/* copy the src-rect into our temporary buffer space */
for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth)
}
/* copy the temporary buffer to the destination */
- for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp+= linewidth)
+ for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp += linewidth)
{
unsigned long cols;
for (cols = 0; cols < width; cols++)
}
}
/* free the temp-buf */
- xfree (tmp3);
-}
+ free (tmp3);
+}
+#endif
/*
DrawLine:
uae_u32 picasso_SetSpritePosition (void)
{
uae_u32 result = 0;
- uaecptr bi = m68k_areg(regs, 0);
- uae_u16 MouseX = get_word(bi + PSSO_BoardInfo_MouseX) - picasso96_state.XOffset;
- uae_u16 MouseY = get_word(bi + PSSO_BoardInfo_MouseY) - picasso96_state.YOffset;
+ uaecptr bi = m68k_areg( regs, 0 );
+ uae_u16 MouseX = get_word( bi + PSSO_BoardInfo_MouseX ) - picasso96_state.XOffset;
+ uae_u16 MouseY = get_word( bi + PSSO_BoardInfo_MouseY ) - picasso96_state.YOffset;
// Keep these around, because we don't want flickering
static uae_u16 OldMouseX = -1;
static uae_u16 OldMouseY = -1;
// Bounds check MouseX and MouseY here, because sometimes they seem to go negative...
- if((uae_s16)MouseX < 0)
+ if( (uae_s16)MouseX < 0 )
MouseX = 0;
- if((uae_s16)MouseY < 0)
+ if( (uae_s16)MouseY < 0 )
MouseY = 0;
- if((MouseX != OldMouseX) || (MouseY != OldMouseY))
+ if( ( MouseX != OldMouseX ) || ( MouseY != OldMouseY ) )
{
- result = DX_MoveCursor(MouseX, MouseY);
+ result = DX_MoveCursor( MouseX, MouseY );
write_log ("SetSpritePosition() - moving cursor to (%d,%d), result = %d\n", MouseX, MouseY, result);
- if(result)
+ if( result )
{
OldMouseX = MouseX;
OldMouseY = MouseY;
* desired state, and wait for custom.c to call picasso_enablescreen
* whenever it is ready to change the screen state. */
picasso_requested_on = flag;
- write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96" : "amiga");
+ write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96":"amiga");
/* Put old switch-state in D0 */
void picasso_enablescreen (int on)
{
-#if 0
wgfx_linestart = 0xFFFFFFFF;
-#endif
picasso_refresh (1);
write_log ("SetSwitch() from threadid %d - showing %s screen\n", GetCurrentThreadId(), on ? "picasso96": "amiga");
checkrtglibrary();
}
-static void init_picasso_screen(void)
+static void init_picasso_screen( void )
{
- if(set_panning_called) {
- picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * picasso96_state.VirtualHeight);
+ if(set_panning_called)
+ {
+ picasso96_state.Extent = picasso96_state.Address + picasso96_state.BytesPerRow * picasso96_state.VirtualHeight;
}
- if (set_gc_called) {
+ if (set_gc_called)
+ {
gfx_set_picasso_modeinfo (picasso96_state.Width, picasso96_state.Height,
picasso96_state.GC_Depth, picasso96_state.RGBFormat);
}
if((picasso_vidinfo.width == picasso96_state.Width) &&
(picasso_vidinfo.height == picasso96_state.Height) &&
(picasso_vidinfo.depth == (picasso96_state.GC_Depth >> 3)) &&
- (picasso_vidinfo.selected_rgbformat == picasso96_state.RGBFormat))
+ (picasso_vidinfo.selected_rgbformat == picasso96_state.RGBFormat))
{
DX_SetPalette (0, 256);
picasso_refresh (1);
uae_u16 Width = m68k_dreg (regs, 0);
uaecptr start_of_screen = m68k_areg (regs, 1);
uaecptr bi = m68k_areg(regs, 0);
- uaecptr bmeptr = get_long(bi + PSSO_BoardInfo_BitMapExtra); /* Get our BoardInfo ptr's BitMapExtra ptr */
+ uaecptr bmeptr = get_long( bi + PSSO_BoardInfo_BitMapExtra ); /* Get our BoardInfo ptr's BitMapExtra ptr */
uae_u16 bme_width, bme_height;
if(oldscr == 0) {
oldscr = start_of_screen;
}
- bme_width = get_word(bmeptr + PSSO_BitMapExtra_Width);
- bme_height = get_word(bmeptr + PSSO_BitMapExtra_Height);
+ bme_width = get_word( bmeptr + PSSO_BitMapExtra_Width );
+ bme_height = get_word( bmeptr + PSSO_BitMapExtra_Height );
picasso96_state.Address = start_of_screen; /* Amiga-side address */
picasso96_state.XOffset = (uae_s16)(m68k_dreg (regs, 1) & 0xFFFF);
picasso96_state.YOffset = (uae_s16)(m68k_dreg (regs, 2) & 0xFFFF);
+ picasso96_state.XYOffset = picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+ + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
picasso96_state.VirtualWidth = bme_width;
picasso96_state.VirtualHeight = bme_height;
- if((bme_width > Width) || (bme_height > picasso96_state.Height)) // NOTE: These were != instead of > before...
+ if((bme_width > Width) || (bme_height > picasso96_state.Height))
picasso96_state.BigAssBitmap = 1;
else
picasso96_state.BigAssBitmap = 0;
unsigned long width_in_bytes;
uae_u32 result = 0;
-#ifdef PIXEL_LOCK
- flushpixels();
-#endif
+
#ifndef LOCK_UNLOCK_MADNESS
wgfx_flushline ();
#endif
P96TRACE(("InvertRect %dbpp 0x%lx\n", Bpp, (long)mask));
if (mask != 0xFF && Bpp > 1)
+ {
mask = 0xFF;
+ }
xorval = 0x01010101 * (mask & 0xFF);
width_in_bytes = Bpp * Width;
- rectstart = uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
+ rectstart = uae_mem = ri.Memory + Y*ri.BytesPerRow + X*Bpp;
for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
do_xor8 (uae_mem, width_in_bytes, xorval);
struct RenderInfo ri;
uae_u32 result = 0;
-#ifdef PIXEL_LOCK
- flushpixels();
-#endif
+ if (Width * Height <= 2500)
+ return 0;
+ P96_SM_RW;
+
#ifndef LOCK_UNLOCK_MADNESS
wgfx_flushline ();
#endif
P96TRACE(("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n",
X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask));
- if(Bpp > 1)
+ if( Bpp > 1 )
Mask = 0xFF;
if (Mask == 0xFF)
uaecptr addr;
if(renderinfo_is_current_screen(&ri))
{
- uae_u32 diff = gfxmem_start - (uae_u32)gfxmemory; /* xxx this is sooo wrong.. */
+ uae_u32 diff = gfxmem_start - (uae_u32)gfxmemory;
addr = ri.Memory + X * Bpp + Y * ri.BytesPerRow + diff;
- if(Width == 1)
+ if( Width == 1 )
{
for(i = 0; i < Height; i++)
{
{
for(i = 0; i < Width; i++)
{
- if(Bpp == 4)
+ if( Bpp == 4 )
gfxmem_lput(addr + (i * Bpp), Pen);
- else if(Bpp == 2)
+ else if( Bpp == 2 )
gfxmem_wput(addr + (i * Bpp), Pen);
else
gfxmem_bput(addr + (i * Bpp), Pen);
return 1;
}
}
+
/* Do the fill-rect in the frame-buffer */
do_fillrect_frame_buffer(&ri, X, Y, Width, Height, Pen, Bpp, RGBFormat);
/* Now we do the on-screen display, if renderinfo points to it */
src = ri.Memory + X * Bpp + Y * ri.BytesPerRow;
X = X - picasso96_state.XOffset;
Y = Y - picasso96_state.YOffset;
- if((int)X < 0) {
- Width = Width + X;
- X = 0;
- }
- if((int)Width < 1)
- return 1;
- if((int)Y < 0) {
- Height = Height + Y;
- Y = 0;
- }
- if((int)Height < 1)
- return 1;
+ if((int)X < 0){ Width = Width + X; X = 0; }
+ if((int)Width < 1) return 1;
+ if((int)Y < 0) { Height = Height + Y; Y = 0; }
+ if((int)Height < 1) return 1;
/* Argh - why does P96Speed do this to me, with FillRect only?! */
if((X < picasso96_state.Width) &&
(Y < picasso96_state.Height))
/* We get here only if Mask != 0xFF */
if (Bpp != 1)
{
- write_log("WARNING - FillRect() has unhandled mask 0x%x with Bpp %d. Using fall-back routine.\n", Mask, Bpp);
+ write_log( "WARNING - FillRect() has unhandled mask 0x%x with Bpp %d. Using fall-back routine.\n", Mask, Bpp );
}
else
{
BLIT_OPCODE opcode;
} blitrectdata;
-static int BlitRectHelper(void)
+STATIC_INLINE int BlitRectHelper( void )
{
struct RenderInfo *ri = blitrectdata.ri;
struct RenderInfo *dstri = blitrectdata.dstri;
BLIT_OPCODE opcode = blitrectdata.opcode;
uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
+ unsigned long total_width = width * Bpp;
+ unsigned long linewidth = (total_width + 15) & ~15;
int can_do_visible_blit = 0;
-
+
if(opcode == BLIT_DST)
{
- write_log("WARNING: BlitRect() being called with opcode of BLIT_DST\n");
+ write_log( "WARNING: BlitRect() being called with opcode of BLIT_DST\n" );
return 1;
}
* If we have a destination RenderInfo, then we've been called from picasso_BlitRectNoMaskComplete()
* and we need to put the results on the screen from the frame-buffer.
*/
+ //if (dstri->Memory == ri->Memory)
if (dstri == NULL || dstri->Memory == ri->Memory)
{
if(mask != 0xFF && Bpp > 1)
+ {
mask = 0xFF;
+ }
dstri = ri;
can_do_visible_blit = 1;
}
{
P96TRACE(("Did not do_blit 1 in BlitRect()\n"));
}
-
+
return 1;
}
-static int BlitRect (uaecptr ri, uaecptr dstri,
+STATIC_INLINE int BlitRect (uaecptr ri, uaecptr dstri,
unsigned long srcx, unsigned long srcy, unsigned long dstx, unsigned long dsty,
unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode)
{
/* Set up the params */
CopyRenderInfoStructureA2U(ri, &blitrectdata.ri_struct);
blitrectdata.ri = &blitrectdata.ri_struct;
- if(dstri) {
+ if(dstri)
+ {
CopyRenderInfoStructureA2U(dstri, &blitrectdata.dstri_struct);
blitrectdata.dstri = &blitrectdata.dstri_struct;
- } else {
+ }
+ else
+ {
blitrectdata.dstri = NULL;
}
blitrectdata.srcx = srcx;
unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
unsigned long width = (uae_u16)m68k_dreg (regs, 4);
unsigned long height = (uae_u16)m68k_dreg (regs, 5);
- uae_u8 Mask = (uae_u8)m68k_dreg (regs, 6);
+ uae_u8 Mask = (uae_u8)m68k_dreg (regs, 6);
uae_u32 result = 0;
-#ifdef PIXEL_LOCK
- flushpixels();
-#endif
+ P96_SM_RW;
+
#ifndef LOCK_UNLOCK_MADNESS
wgfx_flushline ();
#endif
+
P96TRACE(("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask));
- result = BlitRect(renderinfo, 0, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC);
+ result = BlitRect(renderinfo, (uaecptr)NULL, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC);
return result;
}
uae_u32 RGBFmt = m68k_dreg (regs, 7);
uae_u32 result = 0;
-#ifdef PIXEL_LOCK
- flushpixels();
-#endif
+ P96_SM_RW;
+
#ifndef LOCK_UNLOCK_MADNESS
wgfx_flushline ();
#endif
STATIC_INLINE void PixelWrite3(uae_u8 *mem, int bits, uae_u32 fgpen)
{
- do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
- *(uae_u16 *)(mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
+ do_put_mem_byte (mem + bits*3, fgpen & 0x000000FF);
+ *(uae_u16 *)(mem + bits*3+1) = (fgpen & 0x00FFFF00) >> 8;
}
STATIC_INLINE void PixelWrite4(uae_u8 *mem, int bits, uae_u32 fgpen)
do_put_mem_word (((uae_u16 *)mem) + bits, (uae_u16)fgpen);
break;
case 3:
- do_put_mem_byte (mem + bits * 3, (uae_u8)fgpen);
- *(uae_u16 *)(mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
+ do_put_mem_byte (mem + bits*3, (uae_u8)fgpen);
+ *(uae_u16 *)(mem + bits*3+1) = (fgpen & 0x00FFFF00) >> 8;
break;
case 4:
do_put_mem_long (((uae_u32 *)mem) + bits, fgpen);
unsigned long ysize_mask;
uae_u32 result = 0;
-#ifdef PIXEL_LOCK
- flushpixels();
-#endif
+ P96_SM_RW;
+
#ifndef LOCK_UNLOCK_MADNESS
wgfx_flushline ();
#endif
case 2:
{
uae_u16 *addr = ((uae_u16 *)uae_mem2) + bits;
- do_put_mem_word (addr, (uae_u16)( do_get_mem_word (addr) ^ fgpen));
+ do_put_mem_word (addr, (uae_u16)(do_get_mem_word (addr) ^ fgpen));
}
break;
case 3:
}
}
}
- #ifdef PIXEL_LOCK
- flushpixels();
- #endif
-
+
/* If we need to update a second-buffer (extra_mem is set), then do it only if visible! */
if (picasso_vidinfo.extra_mem && renderinfo_is_current_screen (&ri)) {
- if (vsyncgfxwrite==0)
+ if (vsyncgfxwrite == 0)
do_blit(&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
}
+
result = 1;
}
}
uae_u8 *tmpl_base;
uae_u32 result = 0;
-#ifdef PIXEL_LOCK
- flushpixels();
-#endif
+// if (W * H <= 2500)
+// return 0;
+ P96_SM_RW;
+
#ifndef LOCK_UNLOCK_MADNESS
wgfx_flushline ();
#endif
}
}
- #ifdef PIXEL_LOCK
- flushpixels();
- #endif
/* If we need to update a second-buffer (extra_mem is set), then do it only if visible! */
if(picasso_vidinfo.extra_mem && renderinfo_is_current_screen(&ri)) {
if (vsyncgfxwrite == 0)
do_blit(&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
}
+
result = 1;
}
-}
+ }
+
return 1;
}
for (j = 0; j < Depth; j++) {
uae_u8 *p = bm->Planes[j];
if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
- p += srcx / 8 + srcy * bm->BytesPerRow;
+ p += srcx/8 + srcy*bm->BytesPerRow;
PLANAR[j] = p;
if ((mask & (1 << j)) == 0)
PLANAR[j] = &all_zeros_bitmap;
struct BitMap local_bm;
uae_u32 result = 0;
-#ifdef PIXEL_LOCK
- flushpixels();
-#endif
+ P96_SM_RW;
+
#ifndef LOCK_UNLOCK_MADNESS
wgfx_flushline ();
#endif
for (j = 0; j < Depth; j++) {
uae_u8 *p = bm->Planes[j];
if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
- p += srcx / 8 + srcy * bm->BytesPerRow;
+ p += srcx/8 + srcy*bm->BytesPerRow;
PLANAR[j] = p;
if ((mask & (1 << j)) == 0)
PLANAR[j] = &all_zeros_bitmap;
image2 += 2;
break;
case 3:
- do_put_mem_byte (image2++, (uae_u8)cim->Colors[v]);
+ do_put_mem_byte (image2++, (uae_u8)cim->Colors[v] );
do_put_mem_word ((uae_u16 *)image2, (uae_u16)((cim->Colors[v] & 0x00FFFF00) >> 8));
image2 += 2;
break;
struct ColorIndexMapping local_cim;
uae_u32 result = 0;
-#ifdef PIXEL_LOCK
- flushpixels();
-#endif
+ P96_SM_RW;
+
#ifndef LOCK_UNLOCK_MADNESS
wgfx_flushline ();
#endif
- if (minterm != 0x0C)
- {
+ if (minterm != 0x0C) {
write_log ("WARNING - BlitPlanar2Direct() has unhandled op-code 0x%x. Using fall-back routine.\n",
minterm);
}
P96TRACE(("BlitPlanar2Direct(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
srcx, srcy, dstx, dsty, width, height, minterm, Mask, local_bm.Depth));
PlanarToDirect (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, Mask, &local_cim);
- #ifdef PIXEL_LOCK
- flushpixels();
- #endif
- if (renderinfo_is_current_screen (&local_ri)) {
+ if (renderinfo_is_current_screen (&local_ri))
if (!vsyncgfxwrite)
do_blit(&local_ri, GetBytesPerPixel(local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0);
- }
result = 1;
}
-
return result;
}
*/
#ifdef PIXEL_LOCK
-struct frect
-{
- int top, left, right, bottom;
- int first;
+static int pixelcount;
+
+struct pixel32 {
+ uaecptr addr;
+ uae_u32 value;
+ int size;
};
+static struct pixel32 pixelbase[MAXFLUSHPIXEL + 2];
-STATIC_INLINE init_refresh(struct frect *r)
+static void flushpixels_paletted(uae_u8 *dst)
{
- r->first = 1;
- r->left = picasso96_state.Width * picasso96_state.BytesPerPixel;
- r->top = picasso96_state.Height;
- r->right = -1;
- r->bottom = -1;
-}
+ int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+ int i;
-STATIC_INLINE flush_it(struct frect *r)
-{
- if (r->right >= 0 && r->bottom >= 0) {
- DX_Invalidate (r->left / picasso96_state.BytesPerPixel, r->top,
- (r->right - r->left) / picasso96_state.BytesPerPixel + 1, (r->bottom - r->top) + 1);
+ if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
+ {
+ write_log ("ERROR - flushpixels() has non RGBFB_CHUNKY mode!\n");
+ return;
}
- init_refresh(r);
-}
+ if (!picasso_vidinfo.extra_mem)
+ return;
-#define FLUSH_MIN 30
-STATIC_INLINE void flush_refresh(int x, int y, struct frect *r)
-{
- if (x < r->left) {
- if (!r->first && r->left - x > FLUSH_MIN) {
- flush_it(r);
- flush_refresh(x, y, r);
- return;
+ for (i = 0; i < pixelcount; i++)
+ {
+ uaecptr addr = pixelbase[i].addr;
+ uae_u32 value = pixelbase[i].value;
+ int y = addr / picasso96_state.BytesPerRow;
+ int xbytes = addr % picasso96_state.BytesPerRow;
+
+ if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height)
+ {
+ if(psiz == 4)
+ {
+ uae_u8 *addr = dst + y * picasso_vidinfo.rowbytes + xbytes * 4;
+ switch (pixelbase[i].size)
+ {
+ case 4:
+ {
+ *(uae_u32 *)addr = picasso_vidinfo.clut[value & 0xff];
+ addr += 4;
+ *(uae_u32 *)addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+ addr += 4;
+ *(uae_u32 *)addr = picasso_vidinfo.clut[(value >> 16) & 0xff];
+ addr += 4;
+ *(uae_u32 *)addr = picasso_vidinfo.clut[(value >> 24) & 0xff];
+ break;
+ }
+ case 2:
+ {
+ *(uae_u32 *)addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+ addr += 4;
+ *(uae_u32 *)addr = picasso_vidinfo.clut[value & 0xff];
+ break;
+ }
+ case 1:
+ {
+ *(uae_u32 *)addr = picasso_vidinfo.clut[value & 0xff];
+ break;
+ }
+ }
}
- r->left = x;
- }
- if (y < r->top) {
- if (!r->first && r->top - y > FLUSH_MIN) {
- flush_it(r);
- flush_refresh(x, y, r);
- return;
+ else
+ {
+ uae_u8 *addr = dst + y * picasso_vidinfo.rowbytes + xbytes * 2;
+
+ switch (pixelbase[i].size)
+ {
+ case 4:
+ {
+ *(uae_u16 *)addr = picasso_vidinfo.clut[value & 0xff];
+ addr += 2;
+ *(uae_u16 *)addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+ addr += 2;
+ *(uae_u16 *)addr = picasso_vidinfo.clut[(value >> 16) & 0xff];
+ addr += 2;
+ *(uae_u16 *)addr = picasso_vidinfo.clut[(value >> 24) & 0xff];
+ break;
+ }
+ case 2:
+ {
+ *(uae_u16 *)addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+ addr += 2;
+ *(uae_u16 *)addr = picasso_vidinfo.clut[value & 0xff];
+ break;
+ }
+ case 1:
+ {
+ *(uae_u16 *)addr = picasso_vidinfo.clut[value & 0xff];
+ break;
+ }
+ }
+ }
}
- r->top = y;
}
- if (x > r->right) {
- if (!r->first && x - r->right > FLUSH_MIN) {
- flush_it(r);
- flush_refresh(x, y, r);
- return;
+}
+
+static void **gwwbuf;
+static int gwwbufsize;
+extern uae_u8 *natmem_offset;
+extern int p96mode;
+
+static void flushpixels_rgbx(uae_u8 *dst)
+{
+ int i, j;
+ int rowwidth_src = picasso_vidinfo.width * picasso_vidinfo.pixbytes;
+ int rowwidth_dst = picasso96_state.Width * picasso96_state.BytesPerPixel;
+ ULONG ps;
+ ULONG_PTR gwwcnt;
+
+ if (!picasso_vidinfo.extra_mem)
+ return;
+ if (!gwwbuf) {
+ gwwbufsize = allocated_gfxmem / 4096 + 1;
+ gwwbuf = xmalloc (gwwbufsize * sizeof (void*));
+ }
+ gwwcnt = gwwbufsize;
+ if (GetWriteWatch(WRITE_WATCH_FLAG_RESET, p96ram_start + natmem_offset, allocated_gfxmem, gwwbuf, &gwwcnt, &ps))
+ return;
+ for (i = 0; i < gwwcnt; i++) {
+ uae_u8 *p = gwwbuf[i];
+ uaecptr addr = p - p96ram_start - natmem_offset;
+ for (j = 0; j < ps / 4; j++) {
+ int xbytes, y;
+ uae_u32 *dst2;
+ y = addr / picasso96_state.BytesPerRow;
+ xbytes = addr % picasso96_state.BytesPerRow;
+ dst2 = (uae_u32*)(dst + y * picasso_vidinfo.rowbytes + xbytes);
+ if (xbytes < rowwidth_dst && y < picasso96_state.Height)
+ *dst2 = ((uae_u32*)p)[0];
+ addr += 4;
+ p += 4;
}
- r->right = x;
}
- if (y > r->bottom) {
- if (!r->first && y - r->bottom > FLUSH_MIN) {
- flush_it(r);
- flush_refresh(x, y, r);
- return;
+}
+
+static void flushpixels_rgb(uae_u8 *dst)
+{
+ uaecptr xminaddr = 0, xmaxaddr = 0;
+ uae_u8 *ydestaddr;
+ int i;
+ int rowwidth_src = picasso_vidinfo.width * picasso_vidinfo.pixbytes;
+ int rowwidth_dst = picasso96_state.Width * picasso96_state.BytesPerPixel;
+
+ if (!picasso_vidinfo.extra_mem)
+ return;
+
+ for (i = 0; i < pixelcount; i++)
+ {
+ uaecptr addr = pixelbase[i].addr;
+ uae_u32 value = pixelbase[i].value;
+ if(addr > xminaddr && addr < xmaxaddr)
+ {
+ switch (pixelbase[i].size)
+ {
+ case 4:
+ #ifdef SWAPSPEEDUP
+ *(uae_u32 *)(ydestaddr + addr) = value;
+ #else
+ do_put_mem_long ((uae_u32 *)(ydestaddr + addr), value);
+ #endif
+ break;;
+ case 2:
+ do_put_mem_word ((uae_u16 *)(ydestaddr + addr), value);
+ break;
+ case 1:
+ *(uae_u8 *)(ydestaddr + addr) = value;
+ break;
+ }
}
- r->bottom = y;
+ else
+ {
+ int xbytes, y;
+ y = addr / picasso96_state.BytesPerRow;
+ xbytes = addr % picasso96_state.BytesPerRow;
+ xminaddr = y * picasso96_state.BytesPerRow;
+ xmaxaddr = xminaddr + rowwidth_src;
+ ydestaddr = dst + y * picasso_vidinfo.rowbytes - xminaddr;
+
+ if (xbytes < rowwidth_dst && y < picasso96_state.Height)
+ {
+ switch (pixelbase[i].size)
+ {
+ case 4:
+ #ifdef SWAPSPEEDUP
+ *(uae_u32 *)(ydestaddr + addr) = value;
+ #else
+ do_put_mem_long ((uae_u32 *)(ydestaddr + addr), value);
+ #endif
+ break;;
+ case 2:
+ do_put_mem_word ((uae_u16 *)(ydestaddr + addr), value);
+ break;
+ case 1:
+ *(uae_u8 *)(ydestaddr + addr) = value;
+ break;
+ }
+ }
+ else
+ {
+ xmaxaddr = 0;
+ }
+ }
}
- r->first = 0;
}
static void flushpixels(void)
{
- int i;
uae_u8 *dst;
int lock = 0;
- int needrefresh;
- struct frect r;
- if (pixelcount == 0)
+ if (pixelcount == 0 && p96mode == 0)
return;
if (!picasso_on) {
pixelcount = 0;
return;
}
- needrefresh = DirectDraw_GetLockableType() == secondary_surface;
-
+ DX_Invalidate (-1, -1, -1, -1);
+#ifndef _DEBUG
if(DirectDraw_IsLocked() == FALSE) {
dst = gfx_lock_picasso ();
lock = 1;
- } else {
+ } else
+#endif
dst = picasso96_state.HostAddress;
- }
- if (!dst)
- goto out;
-
- init_refresh(&r);
-
- if(picasso_vidinfo.rgbformat != picasso96_state.RGBFormat) {
-
- int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
- if (picasso96_state.RGBFormat != RGBFB_CHUNKY) {
- write_log ("ERROR - flushpixels() has non RGBFB_CHUNKY mode!\n");
- goto out;
- }
- for (i = 0; i < pixelcount; i++) {
- int i2 = pixelbase[i].size;
- uaecptr addr = pixelbase[i].addr;
- uae_u32 value = pixelbase[i].value;
- int y = addr / picasso96_state.BytesPerRow;
- int xbytes = addr % picasso96_state.BytesPerRow;
-
- if (! picasso_vidinfo.extra_mem)
- break;
-
- if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height) {
- if(psiz == 4) {
- uae_u8 *addr;
-
- addr = dst + y * picasso_vidinfo.rowbytes + (xbytes * 4);
- if (i2 == 4) {
- *(uae_u32 *) addr = picasso_vidinfo.clut[((value)&0xff)];
- addr += 4;
- *(uae_u32 *) addr = picasso_vidinfo.clut[((value>>8)&0xff)];
- addr += 4;
- *(uae_u32 *) addr = picasso_vidinfo.clut[((value>>16)&0xff)];
- addr += 4;
- *(uae_u32 *) addr = picasso_vidinfo.clut[((value>>24)&0xff)];
- break;
- } else if (i2 == 2) {
- *(uae_u32 *) addr = picasso_vidinfo.clut[((value>>8)&0xff)];
- addr += 4;
- *(uae_u32 *) addr = picasso_vidinfo.clut[((value)&0xff)];
- break;
- } else if (i2 == 1) {
- *(uae_u32 *) addr = picasso_vidinfo.clut[(value&0xff)];
- break;
- }
- } else {
- uae_u8 *addr;
-
- addr = dst + y * picasso_vidinfo.rowbytes + (xbytes * 2);
- if (i2 == 4) {
- *(uae_u16 *) addr = picasso_vidinfo.clut[((value)&0xff)];
- addr += 2;
- *(uae_u16 *) addr = picasso_vidinfo.clut[((value>>8)&0xff)];
- addr += 2;
- *(uae_u16 *) addr = picasso_vidinfo.clut[((value>>16)&0xff)];
- addr += 2;
- *(uae_u16 *) addr = picasso_vidinfo.clut[((value>>24)&0xff)];
- break;
- } else if (i2 == 2) {
- *(uae_u16 *) addr = picasso_vidinfo.clut[((value>>8)&0xff)];
- addr+=2;
- *(uae_u16 *) addr = picasso_vidinfo.clut[((value)&0xff)];
- break;
- } else if (i2 == 1) {
- *(uae_u16 *) addr = picasso_vidinfo.clut[(value&0xff)];
- break;
- }
- }
- if (needrefresh)
- flush_refresh(xbytes, y, &r);
- }
- }
-
- } else {
-
- for (i = 0;i < pixelcount; i++) {
- uaecptr addr = pixelbase[i].addr;
- uae_u32 value = pixelbase[i].value;
- int y = addr / picasso96_state.BytesPerRow;
- int xbytes = addr % picasso96_state.BytesPerRow;
- uae_u8 *p = dst + y * picasso_vidinfo.rowbytes + xbytes;
-
- if (! picasso_vidinfo.extra_mem)
- continue;
-
- if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height) {
- switch (pixelbase[i].size)
- {
- case 1:
- *(uae_u8 *)p = value;
- break;
- case 2:
- do_put_mem_word ((uae_u16 *)p, value);
- break;
- case 4:
- #ifdef SWAPSPEEDUP
- *(uae_u32 *)p = value;
- #else
- do_put_mem_long ((uae_u32 *)p, value);
- #endif
- break;
- }
- if (needrefresh)
- flush_refresh(xbytes, y, &r);
- }
+ if (dst) {
+ if (p96mode) {
+ if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+ flushpixels_rgbx(dst);
+ } else {
+ if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+ flushpixels_rgb(dst);
+ else
+ flushpixels_paletted(dst);
}
}
-out:;
if(lock)
- gfx_unlock_picasso();
- pixelcount = 0;
- flush_it(&r);
+ gfx_unlock_picasso();
+ pixelcount=0;
}
#endif
-static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
+STATIC_INLINE void write_gfx_x (uaecptr addr, uae_u32 value, int size)
{
- uaecptr oldaddr = addr;
+#ifndef PIXEL_LOCK
int y;
+ uaecptr oldaddr = addr;
#ifdef LOCK_UNLOCK_MADNESS
int x, xbytes;
uae_u8 *dst;
+#endif
#endif
if (!picasso_on)
addr += gfxmem_start;
/* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
if (addr >= picasso96_state.Address && addr + size < picasso96_state.Extent) {
- addr -= picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
- + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
+ addr -= picasso96_state.XYOffset;
if (pixelcount > MAXFLUSHPIXEL)
flushpixels();
pixelbase[pixelcount].addr = addr;
pixelbase[pixelcount++].size = size;
}
return;
-#endif
+#else
#ifndef LOCK_UNLOCK_MADNESS
/*
* Several writes to successive memory locations are a common access pattern.
addr += gfxmem_start;
/* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
- if (addr < picasso96_state.Address || addr + size > picasso96_state.Extent)
+ if (addr < picasso96_state.Address || addr + size >= picasso96_state.Extent)
return;
addr -= picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+ (picasso96_state.YOffset * picasso96_state.BytesPerRow);
if (x < picasso96_state.Width && y < picasso96_state.Height) {
dst = picasso96_state.HostAddress;
- //dst = gfx_lock_picasso ();
if (dst) {
switch (size)
{
do_put_mem_long ((uae_u32 *)(dst + y * picasso_vidinfo.rowbytes + xbytes), value);
break;
}
- //gfx_unlock_picasso ();
}
}
#else
wgfx_min = oldaddr;
wgfx_max = oldaddr + size;
#endif
+#endif
}
static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr)
{
- uae_u8 *m;
+ uae_u32 *m;
+
+ P96_SM_R;
addr -= gfxmem_start & gfxmem_mask;
addr &= gfxmem_mask;
- m = gfxmemory + addr;
- return do_get_mem_long((uae_u32*)m);
+ m = (uae_u32 *)(gfxmemory + addr);
+ return do_get_mem_long(m);
}
static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr)
{
- uae_u8 *m;
+ uae_u16 *m;
+ P96_SM_R;
addr -= gfxmem_start & gfxmem_mask;
addr &= gfxmem_mask;
- m = gfxmemory + addr;
- return do_get_mem_word((uae_u16*)m);
+ m = (uae_u16 *)(gfxmemory + addr);
+ return do_get_mem_word(m);
}
static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
{
+ P96_SM_R;
addr -= gfxmem_start & gfxmem_mask;
addr &= gfxmem_mask;
return gfxmemory[addr];
static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
{
- uae_u8 *m;
+ uae_u32 *m;
#ifdef SWAPSPEEDUP
__asm { //byteswap now
mov eax,l
P96_SM_W;
addr -= gfxmem_start & gfxmem_mask;
addr &= gfxmem_mask;
-
- m = gfxmemory + addr;
+ m = (uae_u32 *)(gfxmemory + addr);
#ifdef SWAPSPEEDUP
*m = l;
#else
- do_put_mem_long((uae_u32*)m, l);
+ do_put_mem_long(m, l);
#endif
/* write the long-word to our displayable memory */
if (vsyncgfxwrite == 0)
static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w)
{
- uae_u8 *m;
+ uae_u16 *m;
P96_SM_W;
addr -= gfxmem_start & gfxmem_mask;
addr &= gfxmem_mask;
- m = gfxmemory + addr;
- do_put_mem_word((uae_u16*)m, w);
+ m = (uae_u16 *)(gfxmemory + addr);
+ do_put_mem_word(m, (uae_u16)w);
/* write the word to our displayable memory */
if (vsyncgfxwrite == 0)
write_gfx_x(addr, b, 1);
}
+
+static uae_u32 REGPARAM2 gfxmem_lgetx (uaecptr addr)
+{
+ uae_u32 *m;
+
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ m = (uae_u32 *)(gfxmemory + addr);
+ return do_get_mem_long(m);
+}
+
+static uae_u32 REGPARAM2 gfxmem_wgetx (uaecptr addr)
+{
+ uae_u16 *m;
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ m = (uae_u16 *)(gfxmemory + addr);
+ return do_get_mem_word(m);
+}
+
+static uae_u32 REGPARAM2 gfxmem_bgetx (uaecptr addr)
+{
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ return gfxmemory[addr];
+}
+
+static void REGPARAM2 gfxmem_lputx (uaecptr addr, uae_u32 l)
+{
+ uae_u32 *m;
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ m = (uae_u32 *)(gfxmemory + addr);
+ do_put_mem_long(m, l);
+}
+
+static void REGPARAM2 gfxmem_wputx (uaecptr addr, uae_u32 w)
+{
+ uae_u16 *m;
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ m = (uae_u16 *)(gfxmemory + addr);
+ do_put_mem_word(m, (uae_u16)w);
+}
+
+static void REGPARAM2 gfxmem_bputx (uaecptr addr, uae_u32 b)
+{
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ gfxmemory[addr] = b;
+}
+
static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size)
{
addr -= gfxmem_start & gfxmem_mask;
dummy_lgeti, dummy_wgeti, ABFLAG_RAM
};
+addrbank gfxmem_bankx = {
+ gfxmem_lgetx, gfxmem_wgetx, gfxmem_bgetx,
+ gfxmem_lputx, gfxmem_wputx, gfxmem_bputx,
+ gfxmem_xlate, gfxmem_check, NULL, "RTG RAM",
+ dummy_lgeti, dummy_wgeti, ABFLAG_RAM
+};
/* Call this function first, near the beginning of code flow
* Place in InitGraphics() which seems reasonable...
* Also put it in reset_drawing() for safe-keeping. */
pixelcount = 0;
palette_changed = 0;
//fastscreen
- oldscr = 0;
+ oldscr=0;
//fastscreen
memset (&picasso96_state, 0, sizeof(struct picasso96_state_struct));
}
#endif
+
+#endif
--- /dev/null
+/*
+* UAE - The U*nix Amiga Emulator
+*
+* Picasso96 Support Module
+*
+* Copyright 1997-2001 Brian King <Brian_King@CodePoet.com>
+* Copyright 2000-2001 Bernd Roesch <>
+*
+* Theory of operation:
+* On the Amiga side, a Picasso card consists mainly of a memory area that
+* contains the frame buffer. On the UAE side, we allocate a block of memory
+* that will hold the frame buffer. This block is in normal memory, it is
+* never directly on the graphics card. All graphics operations, which are
+* mainly reads and writes into this block and a few basic operations like
+* filling a rectangle, operate on this block of memory.
+* Since the memory is not on the graphics card, some work must be done to
+* synchronize the display with the data in the Picasso frame buffer. There
+* are various ways to do this. One possibility is to allocate a second
+* buffer of the same size, and perform all write operations twice. Since
+* we never read from the second buffer, it can actually be placed in video
+* memory. The X11 driver could be made to use the Picasso frame buffer as
+* the data buffer of an XImage, which could then be XPutImage()d from time
+* to time. Another possibility is to translate all Picasso accesses into
+* Xlib (or GDI, or whatever your graphics system is) calls. This possibility
+* is a bit tricky, since there is a risk of generating very many single pixel
+* accesses which may be rather slow.
+*
+* TODO:
+* - we want to add a manual switch to override SetSwitch for hardware banging
+* programs started from a Picasso workbench.
+*/
+
+#include "sysconfig.h"
+#include "sysdeps.h"
+
+#include "options.h"
+#include "threaddep/thread.h"
+#include "memory.h"
+#include "custom.h"
+#include "events.h"
+#include "newcpu.h"
+#include "xwin.h"
+#include "savestate.h"
+#include "autoconf.h"
+#include "traps.h"
+
+#if defined(PICASSO96)
+
+#include "dxwrap.h"
+#include "picasso96_win.h"
+#include "win32gfx.h"
+
+int p96hack_vpos, p96hack_vpos2, p96refresh_active;
+int have_done_picasso; /* For the JIT compiler */
+static int vsyncgfxwrite = 0;
+static int p96syncrate, vsyncgfxcount;
+static int p96hsync_counter;
+
+#ifdef DEBUG // Change this to _DEBUG for debugging
+#define P96TRACING_ENABLED 1
+#define P96TRACING_LEVEL 1
+#endif
+#define LOCK_UNLOCK_MADNESS //need for 7 times faster linedraw
+#define PIXEL_LOCK //and scrollable screens
+#define MAXFLUSHPIXEL 3200 //pixel draw in a lock
+static void flushpixels(void);
+static int pixelcount, palette_changed;
+struct pixel32{
+ uaecptr addr;
+ uae_u32 value;
+ int size;
+};
+static struct pixel32 pixelbase[MAXFLUSHPIXEL + 2];
+#ifdef P96TRACING_ENABLED
+#define P96TRACE(x) do { write_log x; } while(0)
+#else
+#define P96TRACE(x)
+#endif
+#define P96TRACEX(x) do { write_log x; } while(0)
+
+#define GetBytesPerPixel(x) GetBytesPerPixel2(x,__FILE__,__LINE__)
+
+#if defined(JIT)
+#define P96_SM_R special_mem |= PIC_READ;
+#define P96_SM_W special_mem |= PIC_WRITE;
+#else
+#define P96_SM_R
+#define P96_SM_W
+#endif
+
+static uae_u32 REGPARAM2 gfxmem_lget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM2 gfxmem_wget (uaecptr) REGPARAM;
+static uae_u32 REGPARAM2 gfxmem_bget (uaecptr) REGPARAM;
+static void REGPARAM2 gfxmem_lput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM2 gfxmem_wput (uaecptr, uae_u32) REGPARAM;
+static void REGPARAM2 gfxmem_bput (uaecptr, uae_u32) REGPARAM;
+static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size) REGPARAM;
+static uae_u8 *REGPARAM2 gfxmem_xlate (uaecptr addr) REGPARAM;
+
+static uae_u8 all_ones_bitmap, all_zeros_bitmap; /* yuk */
+
+struct picasso96_state_struct picasso96_state;
+struct picasso_vidbuf_description picasso_vidinfo;
+
+/* 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
+/* data here. */
+static struct ScreenResolution planar = { 320, 240 };
+static struct ScreenResolution chunky = { 640, 480 };
+static struct ScreenResolution hicolour = { 640, 480 };
+static struct ScreenResolution truecolour = { 640, 480 };
+static struct ScreenResolution alphacolour = { 640, 480 };
+
+#include "win32gui.h"
+#include "resource.h"
+#define UAE_RTG_LIBRARY_VERSION 40
+#define UAE_RTG_LIBRARY_REVISION 3993
+static void checkrtglibrary(void)
+{
+ uae_u32 v;
+ static int checked = FALSE;
+
+ if (checked)
+ return;
+ v = get_long (4); // execbase
+ v += 378; // liblist
+ while ((v = get_long(v))) {
+ uae_u32 v2 = get_long(v + 10); // name
+ uae_u8 *p;
+ addrbank *b = &get_mem_bank(v2);
+ if (!b || !b->check (v2, 12))
+ continue;
+ p = b->xlateaddr(v2);
+ if (!memcmp(p, "rtg.library\0", 12)) {
+ uae_u16 ver = get_word(v + 20);
+ uae_u16 rev = get_word(v + 22);
+ if (ver * 10000 + rev < UAE_RTG_LIBRARY_VERSION * 10000 + UAE_RTG_LIBRARY_REVISION) {
+ char msg[2000];
+ WIN32GUI_LoadUIString(IDS_OLDRTGLIBRARY, msg, sizeof(msg));
+ gui_message(msg, ver, rev, UAE_RTG_LIBRARY_VERSION, UAE_RTG_LIBRARY_REVISION);
+ } else {
+ write_log("P96: rtg.library %d.%d detected\n", ver, rev);
+ }
+ checked = TRUE;
+ }
+ }
+}
+
+static uae_u32 p2ctab[256][2];
+static int set_gc_called = 0;
+//fastscreen
+static uaecptr oldscr = 0;
+#ifdef _DEBUG
+static void PICASSO96_Unlock2(char *filename, int linenum)
+#else
+static void PICASSO96_Unlock(void)
+#endif
+{
+#ifdef LOCK_UNLOCK_MADNESS
+#if defined(P96TRACING_ENABLED) && P96TRACING_LEVEL > 1
+ // This format of output lets you double-click and jump to file/line
+ write_log("%s(%d) : calling P96 UNLOCK with picasso_on=%d\n", filename, linenum, picasso_on);
+#endif
+ if(picasso_on) {
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+ gfx_unlock_picasso ();
+ picasso96_state.HostAddress = NULL;
+ }
+#endif
+}
+
+#ifdef _DEBUG
+static void PICASSO96_Lock2(char *filename, int linenum)
+#else
+static void PICASSO96_Lock(void)
+#endif
+{
+#ifdef LOCK_UNLOCK_MADNESS
+#if defined(P96TRACING_ENABLED) && P96TRACING_LEVEL > 1
+ // This format of output lets you double-click and jump to file/line
+ write_log( "%s(%d) : calling P96 LOCK with picasso_on=%d\n", filename, linenum, picasso_on );
+#endif
+ if(picasso_on) {
+ picasso96_state.HostAddress = gfx_lock_picasso ();
+ }
+#endif
+}
+
+#ifdef P96TRACING_ENABLED
+/*
+* Debugging dumps
+*/
+static void DumpModeInfoStructure (uaecptr amigamodeinfoptr)
+{
+ write_log ("ModeInfo Structure Dump:\n");
+ write_log (" Node.ln_Succ = 0x%x\n", get_long (amigamodeinfoptr));
+ write_log (" Node.ln_Pred = 0x%x\n", get_long (amigamodeinfoptr + 4));
+ write_log (" Node.ln_Type = 0x%x\n", get_byte (amigamodeinfoptr + 8));
+ write_log (" Node.ln_Pri = %d\n", get_byte (amigamodeinfoptr + 9));
+ /*write_log (" Node.ln_Name = %s\n", uaememptr->Node.ln_Name); */
+ write_log (" OpenCount = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_OpenCount));
+ write_log (" Active = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Active));
+ write_log (" Width = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Width));
+ write_log (" Height = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Height));
+ write_log (" Depth = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Depth));
+ write_log (" Flags = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Flags));
+ write_log (" HorTotal = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorTotal));
+ write_log (" HorBlankSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorBlankSize));
+ write_log (" HorSyncStart = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncStart));
+ write_log (" HorSyncSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSize));
+ write_log (" HorSyncSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSkew));
+ write_log (" HorEnableSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorEnableSkew));
+ write_log (" VerTotal = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerTotal));
+ write_log (" VerBlankSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerBlankSize));
+ write_log (" VerSyncStart = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncStart));
+ write_log (" VerSyncSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncSize));
+ write_log (" Clock = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_first_union));
+ write_log (" ClockDivide = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_second_union));
+ write_log (" PixelClock = %d\n", get_long (amigamodeinfoptr + PSSO_ModeInfo_PixelClock));
+}
+
+static void DumpLibResolutionStructure (uaecptr amigalibresptr)
+{
+ int i;
+ uaecptr amigamodeinfoptr;
+ struct LibResolution *uaememptr = (struct LibResolution *)get_mem_bank(amigalibresptr).xlateaddr(amigalibresptr);
+
+ write_log ("LibResolution Structure Dump:\n");
+
+ if (get_long (amigalibresptr + PSSO_LibResolution_DisplayID) == 0xFFFFFFFF) {
+ write_log (" Finished With LibResolutions...\n");
+ } else {
+ write_log (" Name = %s\n", uaememptr->P96ID);
+ write_log (" DisplayID = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_DisplayID));
+ write_log (" Width = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Width));
+ write_log (" Height = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Height));
+ write_log (" Flags = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Flags));
+ for (i = 0; i < MAXMODES; i++) {
+ amigamodeinfoptr = get_long (amigalibresptr + PSSO_LibResolution_Modes + i*4);
+ write_log (" ModeInfo[%d] = 0x%x\n", i, amigamodeinfoptr);
+ if (amigamodeinfoptr)
+ DumpModeInfoStructure (amigamodeinfoptr);
+ }
+ write_log (" BoardInfo = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_BoardInfo));
+ }
+}
+
+static char binary_byte[9] = { 0,0,0,0,0,0,0,0,0 };
+
+static char *BuildBinaryString (uae_u8 value)
+{
+ int i;
+ for (i = 0; i < 8; i++) {
+ binary_byte[i] = (value & (1 << (7 - i))) ? '#' : '.';
+ }
+ return binary_byte;
+}
+
+static void DumpPattern (struct Pattern *patt)
+{
+ uae_u8 *mem;
+ int row, col;
+ for (row = 0; row < (1 << patt->Size); row++) {
+ mem = patt->Memory + row * 2;
+ for (col = 0; col < 2; col++) {
+ write_log ("%s ", BuildBinaryString (*mem++));
+ }
+ write_log ("\n");
+ }
+}
+
+static void DumpTemplate (struct Template *tmp, unsigned long w, unsigned long h)
+{
+ uae_u8 *mem = tmp->Memory;
+ unsigned int row, col, width;
+ width = (w + 7) >> 3;
+ write_log ("xoffset = %d, bpr = %d\n", tmp->XOffset, tmp->BytesPerRow);
+ for (row = 0; row < h; row++) {
+ mem = tmp->Memory + row * tmp->BytesPerRow;
+ for (col = 0; col < width; col++) {
+ write_log ("%s ", BuildBinaryString (*mem++));
+ }
+ write_log ("\n");
+ }
+}
+
+static void DumpLine( struct Line *line )
+{
+ if(line) {
+ write_log("Line->X = %d\n", line->X);
+ write_log("Line->Y = %d\n", line->Y);
+ write_log("Line->Length = %d\n", line->Length);
+ write_log("Line->dX = %d\n", line->dX);
+ write_log("Line->dY = %d\n", line->dY);
+ write_log("Line->sDelta = %d\n", line->sDelta);
+ write_log("Line->lDelta = %d\n", line->lDelta);
+ write_log("Line->twoSDminusLD = %d\n", line->twoSDminusLD);
+ write_log("Line->LinePtrn = %d\n", line->LinePtrn);
+ write_log("Line->PatternShift = %d\n", line->PatternShift);
+ write_log("Line->FgPen = 0x%x\n", line->FgPen);
+ write_log("Line->BgPen = 0x%x\n", line->BgPen);
+ write_log("Line->Horizontal = %d\n", line->Horizontal);
+ write_log("Line->DrawMode = %d\n", line->DrawMode);
+ write_log("Line->Xorigin = %d\n", line->Xorigin);
+ write_log("Line->Yorigin = %d\n", line->Yorigin);
+ }
+}
+#endif
+
+static void ShowSupportedResolutions (void)
+{
+ int i = 0;
+
+ write_log ("-----------------\n");
+ while (DisplayModes[i].depth >= 0) {
+ write_log ("%s\n", DisplayModes[i].name);
+ i++;
+ }
+ write_log ("-----------------\n");
+}
+
+static uae_u8 GetBytesPerPixel2(uae_u32 RGBfmt, char *file, int line)
+{
+ static BOOL bFailure = FALSE;
+
+ switch (RGBfmt) {
+ case RGBFB_CLUT:
+ return 1;
+
+ case RGBFB_A8R8G8B8:
+ case RGBFB_A8B8G8R8:
+ case RGBFB_R8G8B8A8:
+ case RGBFB_B8G8R8A8:
+ return 4;
+
+ case RGBFB_B8G8R8:
+ case RGBFB_R8G8B8:
+ return 3;
+
+ case RGBFB_R5G5B5:
+ case RGBFB_R5G6B5:
+ case RGBFB_R5G6B5PC:
+ case RGBFB_R5G5B5PC:
+ case RGBFB_B5G6R5PC:
+ case RGBFB_B5G5R5PC:
+ return 2;
+ default:
+ write_log ("ERROR - GetBytesPerPixel() from %s@%d was unsuccessful with 0x%x?!\n", file, line, RGBfmt);
+ if(!bFailure) {
+ bFailure = TRUE;
+ return GetBytesPerPixel(picasso_vidinfo.rgbformat);
+ } else {
+ abort();
+ }
+ }
+ return 0;
+}
+
+/*
+* Amiga <-> native structure conversion functions
+*/
+
+static int CopyRenderInfoStructureA2U (uaecptr amigamemptr, struct RenderInfo *ri)
+{
+ uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
+
+ if (valid_address (memp, PSSO_RenderInfo_sizeof)) {
+ ri->Memory = get_real_address (memp);
+ ri->BytesPerRow = get_word (amigamemptr + PSSO_RenderInfo_BytesPerRow);
+ ri->RGBFormat = get_long (amigamemptr + PSSO_RenderInfo_RGBFormat);
+ return 1;
+ }
+ write_log ("ERROR - Invalid RenderInfo memory area...\n");
+ return 0;
+}
+
+static int CopyPatternStructureA2U (uaecptr amigamemptr, struct Pattern *pattern)
+{
+ uaecptr memp = get_long (amigamemptr + PSSO_Pattern_Memory);
+ if (valid_address (memp, PSSO_Pattern_sizeof)) {
+ 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);
+ pattern->BgPen = get_long (amigamemptr + PSSO_Pattern_BgPen);
+ pattern->Size = get_byte (amigamemptr + PSSO_Pattern_Size);
+ pattern->DrawMode = get_byte (amigamemptr + PSSO_Pattern_DrawMode);
+ return 1;
+ }
+ write_log ("ERROR - Invalid Pattern memory area...\n");
+ return 0;
+}
+
+static void CopyColorIndexMappingA2U (uaecptr amigamemptr, struct ColorIndexMapping *cim)
+{
+ int i;
+ cim->ColorMask = get_long (amigamemptr);
+ for (i = 0; i < 256; i++, amigamemptr += 4)
+ cim->Colors[i] = get_long (amigamemptr + 4);
+}
+
+static int CopyBitMapStructureA2U (uaecptr amigamemptr, struct BitMap *bm)
+{
+ int i;
+
+ bm->BytesPerRow = get_word (amigamemptr + PSSO_BitMap_BytesPerRow);
+ bm->Rows = get_word (amigamemptr + PSSO_BitMap_Rows);
+ bm->Flags = get_byte (amigamemptr + PSSO_BitMap_Flags);
+ bm->Depth = get_byte (amigamemptr + PSSO_BitMap_Depth);
+
+ /* ARGH - why is THIS happening? */
+ if(bm->Depth > 8)
+ bm->Depth = 8;
+
+ for (i = 0; i < bm->Depth; i++) {
+ uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i * 4);
+ switch (plane) {
+ case 0:
+ bm->Planes[i] = &all_zeros_bitmap;
+ break;
+ case 0xFFFFFFFF:
+ bm->Planes[i] = &all_ones_bitmap;
+ break;
+ default:
+ if (valid_address (plane, bm->BytesPerRow * bm->Rows))
+ bm->Planes[i] = get_real_address (plane);
+ else
+ return 0;
+ break;
+ }
+ }
+ return 1;
+}
+
+static int CopyTemplateStructureA2U (uaecptr amigamemptr, struct Template *tmpl)
+{
+ uaecptr memp = get_long (amigamemptr + PSSO_Template_Memory);
+
+ if (valid_address (memp, sizeof(struct Template))) {
+ tmpl->Memory = get_real_address (memp);
+ tmpl->BytesPerRow = get_word (amigamemptr + PSSO_Template_BytesPerRow);
+ tmpl->XOffset = get_byte (amigamemptr + PSSO_Template_XOffset);
+ tmpl->DrawMode = get_byte (amigamemptr + PSSO_Template_DrawMode);
+ tmpl->FgPen = get_long (amigamemptr + PSSO_Template_FgPen);
+ tmpl->BgPen = get_long (amigamemptr + PSSO_Template_BgPen);
+ return 1;
+ }
+ write_log ("ERROR - Invalid Template memory area...\n");
+ return 0;
+}
+
+static int CopyLineStructureA2U(uaecptr amigamemptr, struct Line *line)
+{
+ if(valid_address(amigamemptr, sizeof(struct Line))) {
+ line->X = get_word(amigamemptr + PSSO_Line_X);
+ line->Y = get_word(amigamemptr + PSSO_Line_Y);
+ line->Length = get_word(amigamemptr + PSSO_Line_Length);
+ line->dX = get_word(amigamemptr + PSSO_Line_dX);
+ line->dY = get_word(amigamemptr + PSSO_Line_dY);
+ line->lDelta = get_word(amigamemptr + PSSO_Line_lDelta);
+ line->sDelta = get_word(amigamemptr + PSSO_Line_sDelta);
+ line->twoSDminusLD = get_word(amigamemptr + PSSO_Line_twoSDminusLD);
+ line->LinePtrn = get_word(amigamemptr + PSSO_Line_LinePtrn);
+ line->PatternShift = get_word(amigamemptr + PSSO_Line_PatternShift);
+ line->FgPen = get_long(amigamemptr + PSSO_Line_FgPen);
+ line->BgPen = get_long(amigamemptr + PSSO_Line_BgPen);
+ line->Horizontal = get_word(amigamemptr + PSSO_Line_Horizontal);
+ line->DrawMode = get_byte(amigamemptr + PSSO_Line_DrawMode);
+ line->Xorigin = get_word(amigamemptr + PSSO_Line_Xorigin);
+ line->Yorigin = get_word(amigamemptr + PSSO_Line_Yorigin);
+ return 1;
+ }
+ write_log("ERROR - Invalid Line structure...\n");
+ return 0;
+}
+
+static void CopyLibResolutionStructureU2A (struct LibResolution *libres, uaecptr amigamemptr)
+{
+ char *uaememptr = 0;
+ int i;
+
+ uaememptr = gfxmem_xlate (amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
+ memset (uaememptr, 0, PSSO_LibResolution_sizeof); /* zero out our LibResolution structure */
+ strcpy (uaememptr + PSSO_LibResolution_P96ID, libres->P96ID);
+ put_long (amigamemptr + PSSO_LibResolution_DisplayID, libres->DisplayID);
+ put_word (amigamemptr + PSSO_LibResolution_Width, libres->Width);
+ put_word (amigamemptr + PSSO_LibResolution_Height, libres->Height);
+ put_word (amigamemptr + PSSO_LibResolution_Flags, libres->Flags);
+ for (i = 0; i < MAXMODES; i++)
+ put_long (amigamemptr + PSSO_LibResolution_Modes + i * 4, libres->Modes[i]);
+#if 0
+ put_long (amigamemptr, libres->Node.ln_Succ);
+ put_long (amigamemptr + 4, libres->Node.ln_Pred);
+ put_byte (amigamemptr + 8, libres->Node.ln_Type);
+ put_byte (amigamemptr + 9, libres->Node.ln_Pri);
+#endif
+ put_long (amigamemptr + 10, amigamemptr + PSSO_LibResolution_P96ID);
+ put_long (amigamemptr + PSSO_LibResolution_BoardInfo, libres->BoardInfo);
+}
+
+/* list is Amiga address of list, in correct endian format for UAE
+* node is Amiga address of node, in correct endian format for UAE */
+static void AmigaListAddTail (uaecptr l, uaecptr n)
+{
+ put_long (n + 0, l + 4); // n->ln_Succ = (struct Node *)&l->lh_Tail;
+ put_long (n + 4, get_long (l + 8)); // n->ln_Pred = l->lh_TailPred;
+ put_long (get_long (l + 8) + 0, n); // l->lh_TailPred->ln_Succ = n;
+ put_long (l + 8, n); // l->lh_TailPred = n;
+}
+
+/*
+* Functions to perform an action on the real screen
+*/
+
+/*
+* Fill a rectangle on the screen. src points to the start of a line of the
+* filled rectangle in the frame buffer; it can be used as a memcpy source if
+* there is no OS specific function to fill the rectangle.
+*/
+static void do_fillrect(uae_u8 *src, unsigned int x, unsigned int y, unsigned int width, unsigned int height, uae_u32 pen, int Bpp, RGBFTYPE rgbtype)
+{
+ uae_u8 *dst;
+ int orig_width = width;
+ int orig_height = height;
+
+ /* Try OS specific fillrect function here; and return if successful. Make sure we adjust for
+ * the pen values if we're doing 8-bit display-emulation on a 16-bit or higher screen. */
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+
+ if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
+ if(DX_Fill(x, y, width, height, pen, rgbtype))
+ return;
+ } else {
+ if(DX_Fill(x, y, width, height, picasso_vidinfo.clut[src[0]], rgbtype))
+ return;
+ }
+
+ P96TRACE(("P96_WARNING: do_fillrect() using fall-back routine!\n"));
+
+ if(y + height > picasso_vidinfo.height)
+ height = picasso_vidinfo.height - y;
+ if(x + width > picasso_vidinfo.width)
+ width = picasso_vidinfo.width - x;
+
+ if (! picasso_vidinfo.extra_mem)
+ return;
+
+#ifdef LOCK_UNLOCK_MADNESS
+ PICASSO96_Lock();
+ dst = picasso96_state.HostAddress;
+#else
+ dst = gfx_lock_picasso ();
+#endif
+ if (!dst)
+ goto out;
+
+ width *= Bpp;
+ dst += y * picasso_vidinfo.rowbytes + x * picasso_vidinfo.pixbytes;
+ if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+ {
+ if(Bpp == 1)
+ {
+ while (height-- > 0)
+ {
+ memset(dst, pen, width);
+ dst += picasso_vidinfo.rowbytes;
+ }
+ }
+ else
+ {
+ while (height-- > 0)
+ {
+ memcpy (dst, src, width);
+ dst += picasso_vidinfo.rowbytes;
+ }
+ }
+ }
+ else
+ {
+ int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+ if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
+ {
+ write_log ("ERROR - do_fillrect() calling abort 1!\n");
+ abort ();
+ }
+
+ while (height-- > 0)
+ {
+ unsigned int i;
+ switch (psiz)
+ {
+ case 2:
+ for (i = 0; i < width; i++)
+ *((uae_u16 *)dst + i) = picasso_vidinfo.clut[src[i]];
+ break;
+ case 4:
+ for (i = 0; i < width; i++)
+ *((uae_u32 *)dst + i) = picasso_vidinfo.clut[src[i]];
+ break;
+ default:
+ write_log ("ERROR - do_fillrect() calling abort 2!\n");
+ abort ();
+ break;
+ }
+ dst += picasso_vidinfo.rowbytes;
+ }
+ }
+out:;
+#ifndef LOCK_UNLOCK_MADNESS
+ gfx_unlock_picasso ();
+#else
+ PICASSO96_Unlock();
+#endif
+ DX_Invalidate (x, y, orig_width, orig_height);
+}
+
+/*
+* This routine modifies the real screen buffer after a blit has been
+* performed in the save area. If can_do_blit is nonzero, the blit can
+* be performed within the real screen buffer; otherwise, this routine
+* must do it by hand using the data in the frame-buffer, calculated using
+* the RenderInfo data and our coordinates.
+*/
+static void do_blit(struct RenderInfo *ri, int Bpp,
+ unsigned int srcx, unsigned int srcy,
+ unsigned int dstx, unsigned int dsty,
+ unsigned int width, unsigned int height,
+ BLIT_OPCODE opcode, int can_do_blit)
+{
+ uae_u8 *dstp, *srcp;
+ int orig_width, orig_height;
+
+ if(picasso96_state.BigAssBitmap && can_do_blit) {
+ srcx = dstx;
+ srcy = dsty;
+ can_do_blit = 0;
+ } //hack to use cpu rotines for scrolling in big Screens
+ if (picasso96_state.XOffset < 0)
+ can_do_blit = 0;
+
+ dstx = dstx - picasso96_state.XOffset;
+ dsty = dsty - picasso96_state.YOffset;
+ if((int)dstx <= 0) {
+ srcx = srcx - dstx;
+ dstx = 0;
+ }
+ if((int)dsty <= 0) {
+ srcy = srcy - dsty;
+ dsty = 0;
+ }
+
+#ifdef LOCK_UNLOCK_MADNESS
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#endif
+ /* Is our x/y origin on-screen? */
+ if(dsty >= picasso_vidinfo.height)
+ return;
+ if(dstx >= picasso_vidinfo.width)
+ return;
+
+ /* Is our area in-range? */
+ if(dsty + height >= picasso_vidinfo.height)
+ height = picasso_vidinfo.height - dsty;
+ if(dstx + width >= picasso_vidinfo.width)
+ width = picasso_vidinfo.width - dstx;
+
+ orig_height = height;
+ orig_width = width;
+
+ if (can_do_blit) {
+ //
+ // Call OS blitting function that can do it in video memory.
+ // Should return if it was successful
+ //
+ if(DX_Blit(srcx, srcy, dstx, dsty, width, height, opcode))
+ return;
+ srcx = dstx;
+ srcy = dsty;
+ }
+ if (opcode != BLIT_SRC) {
+ write_log("do_blit() opcode = %d!\n", opcode);
+ return;
+ }
+
+#ifdef LOCK_UNLOCK_MADNESS
+ PICASSO96_Lock();
+#endif
+
+ srcp = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
+
+ if (! picasso_vidinfo.extra_mem)
+ {
+ #ifdef LOCK_UNLOCK_MADNESS
+ goto out;
+ #else
+ return;
+ #endif
+ }
+
+#ifdef LOCK_UNLOCK_MADNESS
+ dstp = picasso96_state.HostAddress;
+#else
+ dstp = gfx_lock_picasso ();
+#endif
+ if (dstp == 0) {
+ write_log ("WARNING: do_blit() couldn't lock\n");
+ goto out;
+ }
+
+ /* The areas can't overlap: the source is always in the Picasso frame buffer,
+ * and the destination is a different buffer owned by the graphics code. */
+ dstp += dsty * picasso_vidinfo.rowbytes + dstx * picasso_vidinfo.pixbytes;
+ P96TRACE(("do_blit with srcp %p, dstp %p, dst_rowbytes %d, srcx %d, srcy %d, dstx %d, dsty %d, w %d, h %d, dst_pixbytes %d\n",
+ srcp, dstp, picasso_vidinfo.rowbytes, srcx, srcy, dstx, dsty, width, height, picasso_vidinfo.pixbytes));
+ P96TRACE(("gfxmem is at %p\n", gfxmemory));
+
+ if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+ {
+ P96TRACE(("do_blit type-a\n"));
+ width *= Bpp;
+ while (height-- > 0)
+ {
+ memcpy (dstp, srcp, width);
+ srcp += ri->BytesPerRow;
+ dstp += picasso_vidinfo.rowbytes;
+
+ }
+ }
+ else
+ {
+ int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+ P96TRACE(("do_blit type-b\n"));
+ if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
+ {
+ write_log ("ERROR: do_blit() calling abort 1!\n");
+ abort ();
+ }
+ while (height-- > 0)
+ {
+ unsigned int i;
+ switch (psiz)
+ {
+ case 2:
+ for (i = 0; i < width; i++)
+ *((uae_u16 *)dstp + i) = picasso_vidinfo.clut[srcp[i]];
+ break;
+ case 4:
+ for (i = 0; i < width; i++)
+ *((uae_u32 *)dstp + i) = picasso_vidinfo.clut[srcp[i]];
+ break;
+ default:
+ write_log ("ERROR - do_blit() calling abort 2!\n");
+ abort ();
+ break;
+ }
+ srcp += ri->BytesPerRow;
+ dstp += picasso_vidinfo.rowbytes;
+ }
+ }
+ out:;
+#ifndef LOCK_UNLOCK_MADNESS
+ gfx_unlock_picasso ();
+#else
+ PICASSO96_Unlock();
+#endif
+ DX_Invalidate (dstx, dsty, orig_width, orig_height);
+}
+
+/*
+* Invert a rectangle on the screen. a render-info is given,
+* so that do_blit can be used if
+* there is no OS specific function to invert the rectangle.
+*/
+static void do_invertrect(struct RenderInfo *ri, int Bpp, int x, int y, int width, int height)
+{
+ /* if(DX_InvertRect(x, y, width, height))
+ return;*/ //deactivate in 0.8.20
+ P96TRACE(("do_invertrect falling back to do_blit!\n"));
+ do_blit (ri, Bpp, x, y, x, y, width, height, BLIT_SRC, 0);
+}
+
+#if 0
+static uaecptr wgfx_linestart;
+static uaecptr wgfx_lineend;
+static uaecptr wgfx_min, wgfx_max;
+static unsigned long wgfx_y;
+
+static void wgfx_do_flushline (void)
+{
+ uae_u8 *src, *dstp;
+
+ /* Mark these lines as "dirty" */
+
+ if (! picasso_vidinfo.extra_mem) /* The "out" will flush the dirty lines directly */
+ goto out;
+
+#ifdef LOCK_UNLOCK_MADNESS
+ dstp = picasso96_state.HostAddress;
+#else
+ dstp = gfx_lock_picasso ();
+#endif
+ if (dstp == 0)
+ goto out;
+
+#if P96TRACING_LEVEL > 0
+ P96TRACE(("flushing %d\n", wgfx_y));
+#endif
+
+ src = gfxmemory + wgfx_min;
+
+ if(picasso_vidinfo.rgbformat == picasso96_state.RGBFormat)
+ {
+#if P96TRACING_LEVEL > 0
+ P96TRACE(("flushing type-a\n"));
+#endif
+ dstp += wgfx_y * picasso_vidinfo.rowbytes + wgfx_min - wgfx_linestart;
+ memcpy (dstp, src, wgfx_max - wgfx_min);
+ }
+ else
+ {
+ int width = wgfx_max - wgfx_min;
+ int i;
+ int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+ P96TRACE(("flushing type-b\n"));
+ if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
+ {
+ write_log ("ERROR - wgfx_do_flushline() calling abort 1!\n");
+ abort ();
+ }
+
+ dstp += wgfx_y * picasso_vidinfo.rowbytes + (wgfx_min - wgfx_linestart) * psiz;
+ switch (psiz) {
+ case 2:
+ for (i = 0; i < width; i++)
+ *((uae_u16 *)dstp + i) = picasso_vidinfo.clut[src[i]];
+ break;
+ case 4:
+ for (i = 0; i < width; i++)
+ *((uae_u32 *)dstp + i) = picasso_vidinfo.clut[src[i]];
+ break;
+ default:
+ write_log ("ERROR - wgfx_do_flushline() calling abort 2!\n");
+ abort ();
+ break;
+ }
+ }
+
+out:
+#ifndef LOCK_UNLOCK_MADNESS
+ gfx_unlock_picasso ();
+#endif
+ DX_Invalidate (0, wgfx_y, -1, 1);
+
+ wgfx_linestart = 0xFFFFFFFF;
+}
+
+STATIC_INLINE void wgfx_flushline (void)
+{
+ if (wgfx_linestart == 0xFFFFFFFF || ! picasso_on)
+ return;
+ wgfx_do_flushline ();
+}
+#endif
+
+static int renderinfo_is_current_screen (struct RenderInfo *ri)
+{
+ if (! picasso_on)
+ return 0;
+ if (ri->Memory != gfxmemory + (picasso96_state.Address - gfxmem_start))
+ return 0;
+
+ return 1;
+}
+
+/*
+* Fill a rectangle in the screen.
+*/
+static void do_fillrect_frame_buffer(struct RenderInfo *ri, int X, int Y, int Width, int Height, uae_u32 Pen, int Bpp, RGBFTYPE RGBFormat)
+{
+ int cols;
+ uae_u8 *start, *oldstart;
+ uae_u8 *src, *dst;
+ int lines;
+
+ /* Do our virtual frame-buffer memory. First, we do a single line fill by hand */
+ oldstart = start = src = ri->Memory + X * Bpp + Y * ri->BytesPerRow;
+
+ switch (Bpp)
+ {
+ case 1:
+ memset (start, Pen, Width);
+ break;
+ case 2:
+ for (cols = 0; cols < Width; cols++)
+ {
+ do_put_mem_word ((uae_u16 *)start, (uae_u16)Pen);
+ start += 2;
+ }
+ break;
+ case 3:
+ for (cols = 0; cols < Width; cols++)
+ {
+ do_put_mem_byte (start, (uae_u8)Pen);
+ start++;
+ *(uae_u16 *)(start) = (Pen & 0x00FFFF00) >> 8;
+ start+=2;
+ }
+ break;
+ case 4:
+ for (cols = 0; cols < Width; cols++)
+ {
+ /**start = Pen; */
+ do_put_mem_long ((uae_u32 *)start, Pen);
+ start += 4;
+ }
+ break;
+ }
+ src = oldstart;
+ dst = src + ri->BytesPerRow;
+ /* next, we do the remaining line fills via memcpy() for > 1 BPP, otherwise some more memset() calls */
+ if(Bpp > 1)
+ {
+ for (lines = 0; lines < Height - 1; lines++, dst += ri->BytesPerRow)
+ memcpy (dst, src, Width * Bpp);
+ }
+ else
+ {
+ for (lines = 0; lines < Height - 1; lines++, dst += ri->BytesPerRow)
+ memset(dst, Pen, Width);
+ }
+}
+
+void picasso_handle_vsync (void)
+{
+ flushpixels();
+ if (palette_changed) {
+ DX_SetPalette (0,256);
+ palette_changed = 0;
+ }
+
+ if (vsyncgfxwrite == 1) {
+ static long blitcount;
+ vsyncgfxcount++;
+ if (vsyncgfxcount > 1) {
+ if (picasso_on) {
+ if (picasso96_state.RGBFormat == picasso_vidinfo.rgbformat
+ || picasso96_state.RGBFormat == RGBFB_CHUNKY) {
+ static frame_time_t cycles;
+ blitcount++;
+ cycles = read_processor_time();
+ picasso_refresh(1);
+ vsyncgfxcount = 0;
+ write_log("%d Blitnum %.3fms\n", blitcount,
+ (read_processor_time() - cycles) * 1000 / (double)syncbase);
+ }
+ }
+ }
+ }
+ setoverlay(1);
+}
+
+static int set_panning_called = 0;
+
+/* Clear our screen, since we've got a new Picasso screen-mode, and refresh with the proper contents
+* This is called on several occasions:
+* 1. Amiga-->Picasso transition, via SetSwitch()
+* 2. Picasso-->Picasso transition, via SetPanning().
+* 3. whenever the graphics code notifies us that the screen contents have been lost.
+*/
+extern unsigned int new_beamcon0;
+void picasso_refresh (int call_setpalette)
+{
+ struct RenderInfo ri;
+ static int beamcon0_before, p96refresh_was;
+
+ if (! picasso_on)
+ return;
+ { //for higher P96 mousedraw rate
+ /* HACK */
+ extern uae_u16 vtotal;
+ if (p96hack_vpos2) {
+ vtotal = p96hack_vpos2;
+ beamcon0_before = new_beamcon0;
+ new_beamcon0 |= 0x80;
+ p96refresh_active = 1;
+ p96refresh_was = 1;
+ } else {
+ if (p96refresh_was) {
+ new_beamcon0 = beamcon0_before;
+ p96refresh_was = 0;
+ }
+ new_beamcon0 |= 0x20;
+ }
+ /* HACK until ntsc timing is fixed.. */
+ } //end for higher P96 mousedraw rate
+ have_done_picasso = 1;
+
+ /* Make sure that the first time we show a Picasso video mode, we don't blit any crap.
+ * We can do this by checking if we have an Address yet. */
+ if (picasso96_state.Address) {
+ unsigned int width, height;
+
+ /* blit the stuff from our static frame-buffer to the gfx-card */
+ ri.Memory = gfxmemory + (picasso96_state.Address - gfxmem_start);
+ ri.BytesPerRow = picasso96_state.BytesPerRow;
+ ri.RGBFormat = picasso96_state.RGBFormat;
+
+ if(set_panning_called)
+ {
+ width = (picasso96_state.VirtualWidth < picasso96_state.Width) ?
+ picasso96_state.VirtualWidth : picasso96_state.Width;
+ height = (picasso96_state.VirtualHeight < picasso96_state.Height) ?
+ picasso96_state.VirtualHeight : picasso96_state.Height;
+ // Let's put a black-border around the case where we've got a sub-screen...
+ if(!picasso96_state.BigAssBitmap)
+ {
+ if (picasso96_state.XOffset || picasso96_state.YOffset)
+ DX_Fill(0, 0, picasso96_state.Width, picasso96_state.Height, 0,
+ picasso96_state.RGBFormat);
+ }
+ }
+ else
+ {
+ width = picasso96_state.Width;
+ height = picasso96_state.Height;
+ }
+ do_blit(&ri, picasso96_state.BytesPerPixel, 0, 0, 0, 0, width, height, BLIT_SRC, 0);
+ }
+ else
+ {
+ write_log ("ERROR - picasso_refresh() can't refresh!\n");
+ }
+}
+
+
+/*
+* Functions to perform an action on the frame-buffer
+*/
+static void do_blitrect_frame_buffer(struct RenderInfo *ri, struct RenderInfo *dstri,
+ unsigned long srcx, unsigned long srcy,
+ unsigned long dstx, unsigned long dsty,
+ unsigned long width, unsigned long height,
+ uae_u8 mask, BLIT_OPCODE opcode)
+{
+
+ uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
+ uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
+ unsigned long total_width = width * Bpp;
+ unsigned long linewidth = (total_width + 15) & ~15;
+ unsigned long lines;
+ int can_do_visible_blit = 0;
+
+ src = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow;
+ dst = dstri->Memory + dstx * Bpp + dsty * dstri->BytesPerRow;
+ if (mask != 0xFF && Bpp > 1)
+ {
+ write_log ("WARNING - BlitRect() has mask 0x%x with Bpp %d.\n", mask, Bpp);
+ }
+
+ if (mask == 0xFF || Bpp > 1)
+ {
+ if(opcode == BLIT_SRC)
+ {
+ /* handle normal case efficiently */
+ if (ri->Memory == dstri->Memory && dsty == srcy)
+ {
+ unsigned long i;
+ for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
+ memmove (dst, src, total_width);
+ }
+ else if (dsty < srcy)
+ {
+ unsigned long i;
+ for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
+ memcpy (dst, src, total_width);
+ }
+ else
+ {
+ unsigned long i;
+ src += (height - 1) * ri->BytesPerRow;
+ dst += (height - 1) * dstri->BytesPerRow;
+ for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
+ memcpy (dst, src, total_width);
+ }
+ return;
+ }
+ else
+ {
+ uae_u8 *src2;
+ uae_u8 *dst2;
+ unsigned int y;
+
+ for(y = 0; y < height; y++) /* Vertical lines */
+ {
+ uae_u8 *bound = src + total_width - 4;
+ uae_u32 *src2_32;
+ uae_u32 *dst2_32;
+ //copy now the longs
+ for(src2_32 = (uae_u32*)src, dst2_32 = (uae_u32*)dst; src2_32 < (uae_u32*)bound; src2_32++, dst2_32++) /* Horizontal bytes */
+ {
+ switch(opcode)
+ {
+ case BLIT_FALSE:
+ *dst2_32 = 0;
+ break;
+ case BLIT_NOR:
+ *dst2_32 = ~(*src2_32 | *dst2_32);
+ break;
+ case BLIT_ONLYDST:
+ *dst2_32 = *dst2_32 & ~(*src2_32);
+ break;
+ case BLIT_NOTSRC:
+ *dst2_32 = ~(*src2_32);
+ break;
+ case BLIT_ONLYSRC:
+ *dst2_32 = *src2_32 & ~(*dst2_32);
+ break;
+ case BLIT_NOTDST:
+ *dst2_32 = ~(*dst2_32);
+ break;
+ case BLIT_EOR:
+ *dst2_32 = *src2_32 ^ *dst2_32;
+ break;
+ case BLIT_NAND:
+ *dst2_32 = ~(*src2_32 & *dst2_32);
+ break;
+ case BLIT_AND:
+ *dst2_32 = *src2_32 & *dst2_32;
+ break;
+ case BLIT_NEOR:
+ *dst2_32 = ~(*src2_32 ^ *dst2_32);
+ break;
+ case BLIT_DST:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
+ break;
+ case BLIT_NOTONLYSRC:
+ *dst2_32 = ~(*src2_32) | *dst2_32;
+ break;
+ case BLIT_SRC:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
+ break;
+ case BLIT_NOTONLYDST:
+ *dst2_32 = ~(*dst2_32) | *src2_32;
+ break;
+ case BLIT_OR:
+ *dst2_32 = *src2_32 | *dst2_32;
+ break;
+ case BLIT_TRUE:
+ *dst2_32 = 0xFFFFFFFF;
+ break;
+ case 30: //code for swap source with dest in byte
+ {
+ uae_u32 temp;
+ temp = *src2_32;
+ *src2_32 = *dst2_32;
+ *dst2_32 = temp;
+ }
+ break;
+ case BLIT_LAST:
+ write_log( "do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
+ break;
+ } /* switch opcode */
+ }// for end
+ //now copy the rest few bytes
+ for(src2 = (uae_u8*)src2_32, dst2 = (uae_u8*)dst2_32; src2 < src + total_width; src2++, dst2++) /* Horizontal bytes */
+ {
+ switch(opcode)
+ {
+ case BLIT_FALSE:
+ *dst2 = 0;
+ break;
+ case BLIT_NOR:
+ *dst2 = ~(*src2 | *dst2);
+ break;
+ case BLIT_ONLYDST:
+ *dst2 = *dst2 & ~(*src2);
+ break;
+ case BLIT_NOTSRC:
+ *dst2 = ~(*src2);
+ break;
+ case BLIT_ONLYSRC:
+ *dst2 = *src2 & ~(*dst2);
+ break;
+ case BLIT_NOTDST:
+ *dst2 = ~(*dst2);
+ break;
+ case BLIT_EOR:
+ *dst2 = *src2 ^ *dst2;
+ break;
+ case BLIT_NAND:
+ *dst2 = ~(*src2 & *dst2);
+ break;
+ case BLIT_AND:
+ *dst2 = *src2 & *dst2;
+ break;
+ case BLIT_NEOR:
+ *dst2 = ~(*src2 ^ *dst2);
+ break;
+ case BLIT_DST:
+ write_log("do_blitrect_frame_buffer shouldn't get BLIT_DST!\n");
+ break;
+ case BLIT_NOTONLYSRC:
+ *dst2 = ~(*src2) | *dst2;
+ break;
+ case BLIT_SRC:
+ write_log("do_blitrect_frame_buffer shouldn't get BLIT_SRC!\n");
+ break;
+ case BLIT_NOTONLYDST:
+ *dst2 = ~(*dst2) | *src2;
+ break;
+ case BLIT_OR:
+ *dst2 = *src2 | *dst2;
+ break;
+ case BLIT_TRUE:
+ *dst2 = 0xFF;
+ break;
+ case BLIT_LAST:
+ write_log("do_blitrect_frame_buffer shouldn't get BLIT_LAST!\n");
+ break;
+ case 30: //code for swap source with dest in long
+ {
+ uae_u8 temp;
+ temp = *src2;
+ *src2 = *dst2;
+ *dst2 = temp;
+ }
+ break;
+ } /* switch opcode */
+ } /* for width */
+ src += ri->BytesPerRow;
+ dst += dstri->BytesPerRow;
+ } /* for height */
+ }
+ return;
+ }
+
+ tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough memory for the src-rect */
+ if (!tmp)
+ return;
+
+ /* copy the src-rect into our temporary buffer space */
+ for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth)
+ {
+ memcpy (tmp2, src, total_width);
+ }
+
+ /* copy the temporary buffer to the destination */
+ for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp+= linewidth)
+ {
+ unsigned long cols;
+ for (cols = 0; cols < width; cols++)
+ {
+ dst[cols] &= ~mask;
+ dst[cols] |= tmp[cols] & mask;
+ }
+ }
+ /* free the temp-buf */
+ xfree (tmp3);
+}
+
+/*
+DrawLine:
+Synopsis: DrawLine(bi, ri, line, Mask, RGBFormat);
+Inputs: a0: struct BoardInfo *bi
+a1: struct RenderInfo *ri
+a2: struct Line *line
+d0.b: Mask
+d7.l: RGBFormat
+
+This function is used to paint a line on the board memory possibly using the blitter. It is called by Draw
+and obeyes the destination RGBFormat as well as ForeGround and BackGround pens and draw modes.
+*/
+uae_u32 REGPARAM2 picasso_DrawLine (struct regstruct *regs)
+{
+ uae_u32 result = 0;
+#ifdef P96_DRAWLINE
+ struct Line line;
+ struct RenderInfo ri;
+ uae_u8 Mask = m68k_dreg(regs, 0);
+ RGBFTYPE RGBFormat = m68k_dreg(regs, 7);
+
+ CopyRenderInfoStructureA2U(m68k_areg(regs, 1), &ri);
+ CopyLineStructureA2U(m68k_areg(regs, 2), &line);
+#if defined( P96TRACING_ENABLED ) && P96TRACING_LEVEL > 0
+ DumpLine( &line );
+#endif
+#else
+ P96TRACE(("DrawLine() - not implemented!\n" ));
+#endif
+ return result;
+}
+
+#ifdef HARDWARE_SPRITE_EMULATION
+/*
+SetSprite:
+Synopsis: SetSprite(bi, activate, RGBFormat);
+Inputs: a0: struct BoardInfo *bi
+d0: BOOL activate
+d7: RGBFTYPE RGBFormat
+
+This function activates or deactivates the hardware sprite.
+*/
+uae_u32 picasso_SetSprite (void)
+{
+ uae_u32 result = 0;
+ uae_u32 activate = m68k_dreg( regs, 0 );
+ result = DX_ShowCursor( activate );
+ write_log ("SetSprite() - trying to %s cursor, result = %d\n", activate ? "show":"hide", result);
+ return result;
+}
+
+/*
+SetSpritePosition:
+Synopsis: SetSpritePosition(bi, RGBFormat);
+Inputs: a0: struct BoardInfo *bi
+d7: RGBFTYPE RGBFormat
+
+This function sets the hardware mouse sprite position according to the values in the BoardInfo structure.
+MouseX and MouseY are the coordinates relative to the screen bitmap. XOffset and YOffset must be subtracted
+to account for possible screen panning.
+*/
+uae_u32 picasso_SetSpritePosition (void)
+{
+ uae_u32 result = 0;
+ uaecptr bi = m68k_areg(regs, 0);
+ uae_u16 MouseX = get_word(bi + PSSO_BoardInfo_MouseX) - picasso96_state.XOffset;
+ uae_u16 MouseY = get_word(bi + PSSO_BoardInfo_MouseY) - picasso96_state.YOffset;
+
+ // Keep these around, because we don't want flickering
+ static uae_u16 OldMouseX = -1;
+ static uae_u16 OldMouseY = -1;
+
+ // Bounds check MouseX and MouseY here, because sometimes they seem to go negative...
+ if((uae_s16)MouseX < 0)
+ MouseX = 0;
+ if((uae_s16)MouseY < 0)
+ MouseY = 0;
+
+ if((MouseX != OldMouseX) || (MouseY != OldMouseY))
+ {
+ result = DX_MoveCursor(MouseX, MouseY);
+ write_log ("SetSpritePosition() - moving cursor to (%d,%d), result = %d\n", MouseX, MouseY, result);
+ if(result)
+ {
+ OldMouseX = MouseX;
+ OldMouseY = MouseY;
+ }
+ }
+ return result;
+}
+
+/*
+SetSpriteImage:
+Synopsis: SetSpriteImage(bi, RGBFormat);
+Inputs: a0: struct BoardInfo *bi
+d7: RGBFTYPE RGBFormat
+
+This function gets new sprite image data from the MouseImage field of the BoardInfo structure and writes
+it to the board.
+
+There are three possible cases:
+
+BIB_HIRESSPRITE is set:
+skip the first two long words and the following sprite data is arranged as an array of two longwords. Those form the
+two bit planes for one image line respectively.
+
+BIB_HIRESSPRITE and BIB_BIGSPRITE are not set:
+skip the first two words and the following sprite data is arranged as an array of two words. Those form the two
+bit planes for one image line respectively.
+
+BIB_HIRESSPRITE is not set and BIB_BIGSPRITE is set:
+skip the first two words and the following sprite data is arranged as an array of two words. Those form the two bit
+planes for one image line respectively. You have to double each pixel horizontally and vertically. All coordinates
+used in this case already assume a zoomed sprite, only the sprite data is not zoomed yet. You will have to
+compensate for this when accounting for hotspot offsets and sprite dimensions.
+*/
+uae_u32 picasso_SetSpriteImage (void)
+{
+ uae_u32 result = 0;
+
+ return result;
+}
+
+/*
+SetSpriteColor:
+Synopsis: SetSpriteColor(bi, index, red, green, blue, RGBFormat);
+Inputs: a0: struct BoardInfo *bi
+d0.b: index
+d1.b: red
+d2.b: green
+d3.b: blue
+d7: RGBFTYPE RGBFormat
+
+This function changes one of the possible three colors of the hardware sprite.
+*/
+uae_u32 picasso_SetSpriteColor (void)
+{
+ uae_u32 result = 0;
+
+ return result;
+}
+#endif
+
+/*
+* BOOL FindCard(struct BoardInfo *bi); and
+*
+* FindCard is called in the first stage of the board initialisation and
+* configuration and is used to look if there is a free and unconfigured
+* board of the type the driver is capable of managing. If it finds one,
+* it immediately reserves it for use by Picasso96, usually by clearing
+* the CDB_CONFIGME bit in the flags field of the ConfigDev struct of
+* this expansion card. But this is only a common example, a driver can
+* do whatever it wants to mark this card as used by the driver. This
+* mechanism is intended to ensure that a board is only configured and
+* used by one driver. FindBoard also usually fills some fields of the
+* BoardInfo struct supplied by the caller, the rtg.library, for example
+* the MemoryBase, MemorySize and RegisterBase fields.
+*/
+uae_u32 REGPARAM2 picasso_FindCard (struct regstruct *regs)
+{
+ uaecptr AmigaBoardInfo = m68k_areg (regs, 0);
+
+ /* NOTES: See BoardInfo struct definition in Picasso96 dev info */
+
+ if (allocated_gfxmem && !picasso96_state.CardFound) {
+ /* Fill in MemoryBase, MemorySize */
+ put_long (AmigaBoardInfo + PSSO_BoardInfo_MemoryBase, gfxmem_start);
+ /* size of memory, minus a 32K chunk: 16K for pattern bitmaps, 16K for resolution list */
+ put_long (AmigaBoardInfo + PSSO_BoardInfo_MemorySize, allocated_gfxmem - 32768);
+ picasso96_state.CardFound = 1; /* mark our "card" as being found */
+ return -1;
+ } else
+ return 0;
+}
+
+static void FillBoardInfo (uaecptr amigamemptr, struct LibResolution *res, struct PicassoResolution *dm)
+{
+ char *uaememptr;
+ switch (dm->depth) {
+ case 1:
+ res->Modes[CHUNKY] = amigamemptr;
+ break;
+ case 2:
+ res->Modes[HICOLOR] = amigamemptr;
+ break;
+ case 3:
+ res->Modes[TRUECOLOR] = amigamemptr;
+ break;
+ default:
+ res->Modes[TRUEALPHA] = amigamemptr;
+ break;
+ }
+ uaememptr = gfxmem_xlate(amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
+ memset(uaememptr, 0, PSSO_ModeInfo_sizeof); /* zero out our ModeInfo struct */
+
+ put_word (amigamemptr + PSSO_ModeInfo_Width, dm->res.width);
+ put_word (amigamemptr + PSSO_ModeInfo_Height, dm->res.height);
+ put_byte (amigamemptr + PSSO_ModeInfo_Depth, dm->depth * 8);
+ put_byte (amigamemptr + PSSO_ModeInfo_Flags, 0);
+ put_word (amigamemptr + PSSO_ModeInfo_HorTotal, dm->res.width);
+ put_word (amigamemptr + PSSO_ModeInfo_HorBlankSize, 0);
+ put_word (amigamemptr + PSSO_ModeInfo_HorSyncStart, 0);
+ put_word (amigamemptr + PSSO_ModeInfo_HorSyncSize, 0);
+ put_byte (amigamemptr + PSSO_ModeInfo_HorSyncSkew, 0);
+ put_byte (amigamemptr + PSSO_ModeInfo_HorEnableSkew, 0);
+
+ put_word (amigamemptr + PSSO_ModeInfo_VerTotal, dm->res.height);
+ put_word (amigamemptr + PSSO_ModeInfo_VerBlankSize, 0);
+ put_word (amigamemptr + PSSO_ModeInfo_VerSyncStart, 0);
+ put_word (amigamemptr + PSSO_ModeInfo_VerSyncSize, 0);
+
+ put_byte (amigamemptr + PSSO_ModeInfo_first_union, 98);
+ put_byte (amigamemptr + PSSO_ModeInfo_second_union, 14);
+
+ put_long (amigamemptr + PSSO_ModeInfo_PixelClock,
+ dm->res.width * dm->res.height * (currprefs.gfx_refreshrate ? abs (currprefs.gfx_refreshrate) : default_freq));
+}
+
+struct modeids {
+ int width, height;
+ int id;
+};
+static struct modeids mi[] =
+{
+/* "original" modes */
+
+ 320, 200, 0,
+ 320, 240, 1,
+ 640, 400, 2,
+ 640, 480, 3,
+ 800, 600, 4,
+ 1024, 768, 5,
+ 1152, 864, 6,
+ 1280,1024, 7,
+ 1600,1280, 8,
+
+/* new modes */
+
+ 704, 480, 129,
+ 704, 576, 130,
+ 720, 480, 131,
+ 720, 576, 132,
+ 768, 483, 133,
+ 768, 576, 134,
+ 800, 480, 135,
+ 848, 480, 136,
+ 854, 480, 137,
+ 948, 576, 138,
+ 1024, 576, 139,
+ 1152, 768, 140,
+ 1152, 864, 141,
+ 1280, 720, 142,
+ 1280, 768, 143,
+ 1280, 800, 144,
+ 1280, 854, 145,
+ 1280, 960, 146,
+ 1366, 768, 147,
+ 1440, 900, 148,
+ 1440, 960, 149,
+ 1600,1200, 150,
+ 1680,1050, 151,
+ 1920,1080, 152,
+ 1920,1200, 153,
+ 2048,1152, 154,
+ 2048,1536, 155,
+ 2560,1600, 156,
+ 2560,2048, 157,
+ 400, 300, 158,
+ 512, 384, 159,
+ 640, 432, 160,
+ 1360, 768, 161,
+ 1360,1024, 162,
+ 1400,1050, 163,
+ 1792,1344, 164,
+ 1800,1440, 165,
+ 1856,1392, 166,
+ 1920,1440, 167,
+
+ -1,-1,0
+};
+
+static int AssignModeID(int dm, int count, int *unkcnt)
+{
+ int i, w, h;
+
+ w = DisplayModes[dm].res.width;
+ h = DisplayModes[dm].res.height;
+ for (i = 0; mi[i].width > 0; i++) {
+ if (w == mi[i].width && h == mi[i].height)
+ return 0x50001000 | (mi[i].id * 0x10000);
+ }
+ (*unkcnt)++;
+ write_log("P96: Non-unique mode %dx%d\n", w, h);
+ return 0x51000000 - (*unkcnt) * 0x10000;
+#if 0
+ int result;
+ if(DisplayModes[i].res.width == 320 && DisplayModes[i].res.height == 200)
+ result = 0x50001000;
+ else if(DisplayModes[i].res.width == 320 && DisplayModes[i].res.height == 240)
+ result = 0x50011000;
+ else if(DisplayModes[i].res.width == 640 && DisplayModes[i].res.height == 400)
+ result = 0x50021000;
+ else if(DisplayModes[i].res.width == 640 && DisplayModes[i].res.height == 480)
+ result = 0x50031000;
+ else if(DisplayModes[i].res.width == 800 && DisplayModes[i].res.height == 600)
+ result = 0x50041000;
+ else if(DisplayModes[i].res.width == 1024 && DisplayModes[i].res.height == 768)
+ result = 0x50051000;
+ else if(DisplayModes[i].res.width == 1152 && DisplayModes[i].res.height == 864)
+ result = 0x50061000;
+ else if(DisplayModes[i].res.width == 1280 && DisplayModes[i].res.height == 1024)
+ result = 0x50071000;
+ else if(DisplayModes[i].res.width == 1600 && DisplayModes[i].res.height == 1280)
+ result = 0x50081000;
+ else
+ result = 0x50090000 + count * 0x10000;
+ return result;
+#endif
+}
+
+/****************************************
+* InitCard()
+*
+* a2: BoardInfo structure ptr - Amiga-based address in Intel endian-format
+*
+* Job - fill in the following structure members:
+* gbi_RGBFormats: the pixel formats that the host-OS of UAE supports
+* If UAE is running in a window, it should ONLY report the pixel format of the host-OS desktop
+* If UAE is running full-screen, it should report ALL pixel formats that the host-OS can handle in full-screen
+* NOTE: If full-screen, and the user toggles to windowed-mode, all hell will break loose visually. Must inform
+* user that they're doing something stupid (unless their desktop and full-screen colour modes match).
+* gbi_SoftSpriteFlags: should be the same as above for now, until actual cursor support is added
+* gbi_BitsPerCannon: could be 6 or 8 or ???, depending on the host-OS gfx-card
+* gbi_MaxHorResolution: fill this in for all modes (even if you don't support them)
+* gbi_MaxVerResolution: fill this in for all modes (even if you don't support them)
+*/
+uae_u32 REGPARAM2 picasso_InitCard (struct regstruct *regs)
+{
+ struct LibResolution res;
+ int ModeInfoStructureCount = 1, LibResolutionStructureCount = 0;
+ int i, unkcnt;
+
+ uaecptr amigamemptr = 0;
+ uaecptr AmigaBoardInfo = m68k_areg (regs, 2);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_BitsPerCannon, DX_BitsPerCannon());
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_RGBFormats, picasso96_pixel_format);
+ put_long (AmigaBoardInfo + PSSO_BoardInfo_BoardType, BT_uaegfx);
+#ifdef HARDWARE_SPRITE_EMULATION
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, 0);
+#else
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, picasso96_pixel_format);
+#endif
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 0, planar.width);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 2, chunky.width);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 4, hicolour.width);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 6, truecolour.width);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 8, alphacolour.width);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 0, planar.height);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 2, chunky.height);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 4, hicolour.height);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 6, truecolour.height);
+ put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 8, alphacolour.height);
+
+ i = 0;
+ unkcnt = 0;
+ while (DisplayModes[i].depth >= 0) {
+ int j = i;
+ /* Add a LibResolution structure to the ResolutionsList MinList in our BoardInfo */
+ res.DisplayID = AssignModeID(i, LibResolutionStructureCount, &unkcnt);
+ res.BoardInfo = AmigaBoardInfo;
+ res.Width = DisplayModes[i].res.width;
+ res.Height = DisplayModes[i].res.height;
+ res.Flags = P96F_PUBLIC;
+ memcpy (res.P96ID, "P96-0:", 6);
+ sprintf (res.Name, "uaegfx:%dx%d", res.Width, res.Height);
+ res.Modes[PLANAR] = 0;
+ res.Modes[CHUNKY] = 0;
+ res.Modes[HICOLOR] = 0;
+ res.Modes[TRUECOLOR] = 0;
+ res.Modes[TRUEALPHA] = 0;
+
+ do {
+ /* Handle this display mode's depth */
+
+ /* New: Only add the modes when there is enough P96 RTG memory to hold the bitmap */
+ if((allocated_gfxmem - 32768) >
+ (DisplayModes[i].res.width * DisplayModes[i].res.height * DisplayModes[i].depth))
+ {
+ amigamemptr = gfxmem_start + allocated_gfxmem - (PSSO_ModeInfo_sizeof * ModeInfoStructureCount++);
+ FillBoardInfo(amigamemptr, &res, &DisplayModes[i]);
+ }
+ i++;
+ } while (DisplayModes[i].depth >= 0
+ && DisplayModes[i].res.width == DisplayModes[j].res.width
+ && DisplayModes[i].res.height == DisplayModes[j].res.height);
+
+ amigamemptr = gfxmem_start + allocated_gfxmem - 16384 + (PSSO_LibResolution_sizeof * LibResolutionStructureCount++);
+ CopyLibResolutionStructureU2A (&res, amigamemptr);
+#if defined P96TRACING_ENABLED && P96TRACING_LEVEL > 1
+ DumpLibResolutionStructure(amigamemptr);
+#endif
+ AmigaListAddTail (AmigaBoardInfo + PSSO_BoardInfo_ResolutionsList, amigamemptr);
+ }
+
+ return -1;
+}
+
+/*
+* SetSwitch:
+* a0: struct BoardInfo
+* d0.w: BOOL state
+* this function should set a board switch to let the Amiga signal pass
+* through when supplied with a 0 in d0 and to show the board signal if
+* a 1 is passed in d0. You should remember the current state of the
+* switch to avoid unneeded switching. If your board has no switch, then
+* simply supply a function that does nothing except a RTS.
+*
+* NOTE: Return the opposite of the switch-state. BDK
+*/
+uae_u32 REGPARAM2 picasso_SetSwitch (struct regstruct *regs)
+{
+ uae_u16 flag = m68k_dreg (regs, 0) & 0xFFFF;
+
+ /* Do not switch immediately. Tell the custom chip emulation about the
+ * desired state, and wait for custom.c to call picasso_enablescreen
+ * whenever it is ready to change the screen state. */
+ picasso_requested_on = flag;
+ write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96" : "amiga");
+
+ /* Put old switch-state in D0 */
+
+ return !flag;
+}
+
+void picasso_enablescreen (int on)
+{
+#if 0
+ wgfx_linestart = 0xFFFFFFFF;
+#endif
+ picasso_refresh (1);
+ write_log ("SetSwitch() from threadid %d - showing %s screen\n", GetCurrentThreadId(), on ? "picasso96": "amiga");
+ checkrtglibrary();
+}
+
+/*
+* SetColorArray:
+* a0: struct BoardInfo
+* d0.w: startindex
+* d1.w: count
+* when this function is called, your driver has to fetch "count" color
+* values starting at "startindex" from the CLUT field of the BoardInfo
+* structure and write them to the hardware. The color values are always
+* between 0 and 255 for each component regardless of the number of bits
+* per cannon your board has. So you might have to shift the colors
+* before writing them to the hardware.
+*/
+uae_u32 REGPARAM2 picasso_SetColorArray (struct regstruct *regs)
+{
+/* Fill in some static UAE related structure about this new CLUT setting
+ * We need this for CLUT-based displays, and for mapping CLUT to hi/true colour */
+ uae_u16 start = m68k_dreg (regs, 0);
+ uae_u16 count = m68k_dreg (regs, 1);
+ int i;
+ uaecptr boardinfo = m68k_areg (regs, 0);
+ uaecptr clut = boardinfo + PSSO_BoardInfo_CLUT + start * 3;
+
+ for (i = start; i < start + count; i++) {
+ int r = get_byte (clut);
+ int g = get_byte (clut + 1);
+ int b = get_byte (clut + 2);
+
+ palette_changed |= (picasso96_state.CLUT[i].Red != r
+ || picasso96_state.CLUT[i].Green != g
+ || picasso96_state.CLUT[i].Blue != b);
+
+ picasso96_state.CLUT[i].Red = r;
+ picasso96_state.CLUT[i].Green = g;
+ picasso96_state.CLUT[i].Blue = b;
+ clut += 3;
+ }
+ P96TRACE(("SetColorArray(%d,%d)\n", start, count));
+ return 1;
+}
+
+/*
+* SetDAC:
+* a0: struct BoardInfo
+* d7: RGBFTYPE RGBFormat
+* This function is called whenever the RGB format of the display changes,
+* e.g. from chunky to TrueColor. Usually, all you have to do is to set
+* the RAMDAC of your board accordingly.
+*/
+uae_u32 REGPARAM2 picasso_SetDAC (struct regstruct *regs)
+{
+/* 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 */
+
+ P96TRACE(("SetDAC()\n"));
+ return 1;
+}
+
+
+static void init_picasso_screen(void)
+{
+ if(set_panning_called) {
+ picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * picasso96_state.VirtualHeight);
+ }
+ if (set_gc_called) {
+ gfx_set_picasso_modeinfo (picasso96_state.Width, picasso96_state.Height,
+ picasso96_state.GC_Depth, picasso96_state.RGBFormat);
+ }
+ if((picasso_vidinfo.width == picasso96_state.Width) &&
+ (picasso_vidinfo.height == picasso96_state.Height) &&
+ (picasso_vidinfo.depth == (picasso96_state.GC_Depth >> 3)) &&
+ (picasso_vidinfo.selected_rgbformat == picasso96_state.RGBFormat))
+ {
+ DX_SetPalette (0, 256);
+ picasso_refresh (1);
+ }
+}
+
+/*
+* SetGC:
+* a0: struct BoardInfo
+* a1: struct ModeInfo
+* d0: BOOL Border
+* This function is called whenever another ModeInfo has to be set. This
+* function simply sets up the CRTC and TS registers to generate the
+* timing used for that screen mode. You should not set the DAC, clocks
+* or linear start adress. They will be set when appropriate by their
+* own functions.
+*/
+uae_u32 REGPARAM2 picasso_SetGC (struct regstruct *regs)
+{
+ /* Fill in some static UAE related structure about this new ModeInfo setting */
+ uae_u32 border = m68k_dreg (regs, 0);
+ uaecptr modeinfo = m68k_areg (regs, 1);
+
+ picasso96_state.Width = get_word (modeinfo + PSSO_ModeInfo_Width);
+ picasso96_state.VirtualWidth = picasso96_state.Width; /* in case SetPanning doesn't get called */
+
+ picasso96_state.Height = get_word (modeinfo + PSSO_ModeInfo_Height);
+ picasso96_state.VirtualHeight = picasso96_state.Height; /* in case SetPanning doesn't get called */
+
+ picasso96_state.GC_Depth = get_byte (modeinfo + PSSO_ModeInfo_Depth);
+ picasso96_state.GC_Flags = get_byte (modeinfo + PSSO_ModeInfo_Flags);
+
+ P96TRACE(("SetGC(%d,%d,%d,%d)\n", picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth, border));
+ set_gc_called = 1;
+ picasso96_state.HostAddress = NULL;
+ init_picasso_screen ();
+ init_hz_p96 ();
+ return 1;
+}
+
+/*
+* SetPanning:
+* a0: struct BoardInfo
+* a1: UBYTE *Memory
+* d0: uae_u16 Width
+* d1: WORD XOffset
+* d2: WORD YOffset
+* d7: RGBFTYPE RGBFormat
+* This function sets the view origin of a display which might also be
+* overscanned. In register a1 you get the start address of the screen
+* bitmap on the Amiga side. You will have to subtract the starting
+* address of the board memory from that value to get the memory start
+* offset within the board. Then you get the offset in pixels of the
+* left upper edge of the visible part of an overscanned display. From
+* these values you will have to calculate the LinearStartingAddress
+* fields of the CRTC registers.
+
+ * NOTE: SetPanning() can be used to know when a Picasso96 screen is
+ * being opened. Better to do the appropriate clearing of the
+ * background here than in SetSwitch() derived functions,
+ * because SetSwitch() is not called for subsequent Picasso screens.
+*/
+
+uae_u32 REGPARAM2 picasso_SetPanning (struct regstruct *regs)
+{
+ uae_u16 Width = m68k_dreg (regs, 0);
+ uaecptr start_of_screen = m68k_areg (regs, 1);
+ uaecptr bi = m68k_areg(regs, 0);
+ uaecptr bmeptr = get_long(bi + PSSO_BoardInfo_BitMapExtra); /* Get our BoardInfo ptr's BitMapExtra ptr */
+ uae_u16 bme_width, bme_height;
+
+ if(oldscr == 0) {
+ oldscr = start_of_screen;
+ }
+ if (oldscr != start_of_screen) {
+ set_gc_called = 0;
+ oldscr = start_of_screen;
+ }
+
+ bme_width = get_word(bmeptr + PSSO_BitMapExtra_Width);
+ bme_height = get_word(bmeptr + PSSO_BitMapExtra_Height);
+
+ picasso96_state.Address = start_of_screen; /* Amiga-side address */
+ picasso96_state.XOffset = (uae_s16)(m68k_dreg (regs, 1) & 0xFFFF);
+ picasso96_state.YOffset = (uae_s16)(m68k_dreg (regs, 2) & 0xFFFF);
+ picasso96_state.VirtualWidth = bme_width;
+ picasso96_state.VirtualHeight = bme_height;
+ if((bme_width > Width) || (bme_height > picasso96_state.Height)) // NOTE: These were != instead of > before...
+ picasso96_state.BigAssBitmap = 1;
+ else
+ picasso96_state.BigAssBitmap = 0;
+ picasso96_state.RGBFormat = m68k_dreg (regs, 7);
+ picasso96_state.BytesPerPixel = GetBytesPerPixel (picasso96_state.RGBFormat);
+ picasso96_state.BytesPerRow = bme_width * picasso96_state.BytesPerPixel;
+
+ set_panning_called = 1;
+ P96TRACE(("SetPanning(%d, %d, %d) Start 0x%x, BPR %d Bpp %d RGBF %d\n",
+ Width, picasso96_state.XOffset, picasso96_state.YOffset,
+ start_of_screen, picasso96_state.BytesPerRow, picasso96_state.BytesPerPixel, picasso96_state.RGBFormat));
+ init_picasso_screen ();
+ set_panning_called = 0;
+
+ return 1;
+}
+
+static void do_xor8 (uae_u8 *ptr, long len, uae_u32 val)
+{
+ int i;
+#if 0 && defined ALIGN_POINTER_TO32
+ int align_adjust = ALIGN_POINTER_TO32(ptr);
+ int len2;
+
+ len -= align_adjust;
+ while (align_adjust) {
+ *ptr ^= val;
+ ptr++;
+ align_adjust--;
+ }
+ len2 = len >> 2;
+ len -= len2 << 2;
+ for (i = 0; i < len2; i++, ptr += 4) {
+ *(uae_u32 *)ptr ^= val;
+ }
+ while (len) {
+ *ptr ^= val;
+ ptr++;
+ len--;
+ }
+ return;
+#endif
+ for (i = 0; i < len; i++, ptr++) {
+ do_put_mem_byte (ptr, (uae_u8)(do_get_mem_byte (ptr) ^ val));
+ }
+}
+
+/*
+* InvertRect:
+*
+* Inputs:
+* a0:struct BoardInfo *bi
+* a1:struct RenderInfo *ri
+* d0.w:X
+* d1.w:Y
+* d2.w:Width
+* d3.w:Height
+* d4.l:Mask
+* d7.l:RGBFormat
+*
+* This function is used to invert a rectangular area on the board. It is called by BltBitMap,
+* BltPattern and BltTemplate.
+*/
+uae_u32 REGPARAM2 picasso_InvertRect (struct regstruct *regs)
+{
+ uaecptr renderinfo = m68k_areg (regs, 1);
+ unsigned long X = (uae_u16)m68k_dreg (regs, 0);
+ unsigned long Y = (uae_u16)m68k_dreg (regs, 1);
+ unsigned long Width = (uae_u16)m68k_dreg (regs, 2);
+ unsigned long Height = (uae_u16)m68k_dreg (regs, 3);
+ uae_u8 mask = (uae_u8)m68k_dreg (regs, 4);
+ int Bpp = GetBytesPerPixel (m68k_dreg (regs, 7));
+ uae_u32 xorval;
+ unsigned int lines;
+ struct RenderInfo ri;
+ uae_u8 *uae_mem, *rectstart;
+ unsigned long width_in_bytes;
+ uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#ifdef NOBLIT
+ return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ wgfx_flushline ();
+#endif
+
+ if (CopyRenderInfoStructureA2U (renderinfo, &ri))
+ {
+ P96TRACE(("InvertRect %dbpp 0x%lx\n", Bpp, (long)mask));
+
+ if (mask != 0xFF && Bpp > 1)
+ mask = 0xFF;
+
+ xorval = 0x01010101 * (mask & 0xFF);
+ width_in_bytes = Bpp * Width;
+ rectstart = uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
+
+ for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
+ do_xor8 (uae_mem, width_in_bytes, xorval);
+
+ if (vsyncgfxwrite == 0) {
+ if (renderinfo_is_current_screen (&ri)) {
+ if (mask == 0xFF)
+ do_invertrect(&ri, Bpp, X, Y, Width, Height);
+ else
+ do_blit(&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0);
+ }
+ }
+ result = 1;
+ }
+
+ return result; /* 1 if supported, 0 otherwise */
+}
+
+/***********************************************************
+FillRect:
+***********************************************************
+* a0: struct BoardInfo *
+* a1: struct RenderInfo *
+* d0: WORD X
+* d1: WORD Y
+* d2: WORD Width
+* d3: WORD Height
+* d4: uae_u32 Pen
+* d5: UBYTE Mask
+* d7: uae_u32 RGBFormat
+***********************************************************/
+uae_u32 REGPARAM2 picasso_FillRect (struct regstruct *regs)
+{
+ uaecptr renderinfo = m68k_areg (regs, 1);
+ uae_u32 X = (uae_u16)m68k_dreg (regs, 0);
+ uae_u32 Y = (uae_u16)m68k_dreg (regs, 1);
+ uae_u32 Width = (uae_u16)m68k_dreg (regs, 2);
+ uae_u32 Height = (uae_u16)m68k_dreg (regs, 3);
+ uae_u32 Pen = m68k_dreg (regs, 4);
+ uae_u8 Mask = (uae_u8)m68k_dreg (regs, 5);
+ RGBFTYPE RGBFormat = m68k_dreg (regs, 7);
+
+ uae_u8 *src;
+ uae_u8 *oldstart;
+ int Bpp;
+ struct RenderInfo ri;
+ uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#ifdef NOBLIT
+ return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ wgfx_flushline ();
+#endif
+
+ if (CopyRenderInfoStructureA2U (renderinfo, &ri) && Y != 0xFFFF)
+ {
+ if (ri.RGBFormat != RGBFormat)
+ write_log ("Weird Stuff!\n");
+
+ Bpp = GetBytesPerPixel (RGBFormat);
+
+ P96TRACE(("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n",
+ X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask));
+
+ if(Bpp > 1)
+ Mask = 0xFF;
+
+ if (Mask == 0xFF)
+ {
+ if((Width == 1) || (Height == 1))
+ {
+ int i;
+ uaecptr addr;
+ if(renderinfo_is_current_screen(&ri))
+ {
+ uae_u32 diff = gfxmem_start - (uae_u32)gfxmemory; /* xxx this is sooo wrong.. */
+ addr = ri.Memory + X * Bpp + Y * ri.BytesPerRow + diff;
+ if(Width == 1)
+ {
+ for(i = 0; i < Height; i++)
+ {
+ if(Bpp == 4)
+ gfxmem_lput(addr + (i * picasso96_state.BytesPerRow), Pen);
+ else if(Bpp == 2)
+ gfxmem_wput(addr + (i * picasso96_state.BytesPerRow), Pen);
+ else
+ gfxmem_bput(addr + (i * picasso96_state.BytesPerRow), Pen);
+ }
+ }
+ else if(Height == 1)
+ {
+ for(i = 0; i < Width; i++)
+ {
+ if(Bpp == 4)
+ gfxmem_lput(addr + (i * Bpp), Pen);
+ else if(Bpp == 2)
+ gfxmem_wput(addr + (i * Bpp), Pen);
+ else
+ gfxmem_bput(addr + (i * Bpp), Pen);
+ }
+ }
+ return 1;
+ }
+ }
+ /* Do the fill-rect in the frame-buffer */
+ do_fillrect_frame_buffer(&ri, X, Y, Width, Height, Pen, Bpp, RGBFormat);
+ /* Now we do the on-screen display, if renderinfo points to it */
+ if (renderinfo_is_current_screen (&ri))
+ {
+ src = ri.Memory + X * Bpp + Y * ri.BytesPerRow;
+ X = X - picasso96_state.XOffset;
+ Y = Y - picasso96_state.YOffset;
+ if((int)X < 0) {
+ Width = Width + X;
+ X = 0;
+ }
+ if((int)Width < 1)
+ return 1;
+ if((int)Y < 0) {
+ Height = Height + Y;
+ Y = 0;
+ }
+ if((int)Height < 1)
+ return 1;
+ /* Argh - why does P96Speed do this to me, with FillRect only?! */
+ if((X < picasso96_state.Width) &&
+ (Y < picasso96_state.Height))
+ {
+ if(X + Width > picasso96_state.Width)
+ Width = picasso96_state.Width - X;
+ if(Y + Height > picasso96_state.Height)
+ Height = picasso96_state.Height - Y;
+
+ if (vsyncgfxwrite == 0)
+ do_fillrect(src, X, Y, Width, Height, Pen, Bpp, RGBFormat);
+ }
+ }
+ result = 1;
+ }
+ else
+ {
+ /* We get here only if Mask != 0xFF */
+ if (Bpp != 1)
+ {
+ write_log("WARNING - FillRect() has unhandled mask 0x%x with Bpp %d. Using fall-back routine.\n", Mask, Bpp);
+ }
+ else
+ {
+ Pen &= Mask;
+ Mask = ~Mask;
+ oldstart = ri.Memory + Y * ri.BytesPerRow + X * Bpp;
+ {
+ uae_u8 *start = oldstart;
+ uae_u8 *end = start + Height * ri.BytesPerRow;
+ for (; start != end; start += ri.BytesPerRow)
+ {
+ uae_u8 *p = start;
+ unsigned long cols;
+ for (cols = 0; cols < Width; cols++)
+ {
+ uae_u32 tmpval = do_get_mem_byte (p + cols) & Mask;
+ do_put_mem_byte (p + cols, (uae_u8)(Pen | tmpval));
+ }
+ }
+ }
+ if (vsyncgfxwrite == 0) {
+ if (renderinfo_is_current_screen (&ri))
+ do_blit(&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0);
+ }
+ result = 1;
+ }
+ }
+ }
+ return result;
+}
+
+/*
+* BlitRect() is a generic (any chunky pixel format) rectangle copier
+* NOTE: If dstri is NULL, then we're only dealing with one RenderInfo area, and called from picasso_BlitRect()
+*
+* OpCodes:
+* 0 = FALSE: dst = 0
+* 1 = NOR: dst = ~(src | dst)
+* 2 = ONLYDST: dst = dst & ~src
+* 3 = NOTSRC: dst = ~src
+* 4 = ONLYSRC: dst = src & ~dst
+* 5 = NOTDST: dst = ~dst
+* 6 = EOR: dst = src^dst
+* 7 = NAND: dst = ~(src & dst)
+* 8 = AND: dst = (src & dst)
+* 9 = NEOR: dst = ~(src ^ dst)
+*10 = DST: dst = dst
+*11 = NOTONLYSRC: dst = ~src | dst
+*12 = SRC: dst = src
+*13 = NOTONLYDST: dst = ~dst | src
+*14 = OR: dst = src | dst
+*15 = TRUE: dst = 0xFF
+*/
+struct blitdata
+{
+ struct RenderInfo ri_struct;
+ struct RenderInfo dstri_struct;
+ struct RenderInfo *ri; /* Self-referencing pointers */
+ struct RenderInfo *dstri;
+ unsigned long srcx;
+ unsigned long srcy;
+ unsigned long dstx;
+ unsigned long dsty;
+ unsigned long width;
+ unsigned long height;
+ uae_u8 mask;
+ BLIT_OPCODE opcode;
+} blitrectdata;
+
+static int BlitRectHelper(void)
+{
+ struct RenderInfo *ri = blitrectdata.ri;
+ struct RenderInfo *dstri = blitrectdata.dstri;
+ unsigned long srcx = blitrectdata.srcx;
+ unsigned long srcy = blitrectdata.srcy;
+ unsigned long dstx = blitrectdata.dstx;
+ unsigned long dsty = blitrectdata.dsty;
+ unsigned long width = blitrectdata.width;
+ unsigned long height = blitrectdata.height;
+ uae_u8 mask = blitrectdata.mask;
+ BLIT_OPCODE opcode = blitrectdata.opcode;
+
+ uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
+ int can_do_visible_blit = 0;
+
+ if(opcode == BLIT_DST)
+ {
+ write_log("WARNING: BlitRect() being called with opcode of BLIT_DST\n");
+ return 1;
+ }
+
+ /*
+ * If we have no destination RenderInfo, then we're dealing with a single-buffer action, called
+ * from picasso_BlitRect(). The code in do_blitrect_frame_buffer() deals with the frame-buffer,
+ * while the do_blit() code deals with the visible screen.
+ *
+ * If we have a destination RenderInfo, then we've been called from picasso_BlitRectNoMaskComplete()
+ * and we need to put the results on the screen from the frame-buffer.
+ */
+ if (dstri == NULL || dstri->Memory == ri->Memory)
+ {
+ if(mask != 0xFF && Bpp > 1)
+ mask = 0xFF;
+ dstri = ri;
+ can_do_visible_blit = 1;
+ }
+
+ /* Do our virtual frame-buffer memory first */
+ do_blitrect_frame_buffer(ri, dstri, srcx, srcy, dstx, dsty, width, height, mask, opcode);
+ /* Now we do the on-screen display, if renderinfo points to it */
+ if (vsyncgfxwrite == 1)
+ return 1;
+ if (renderinfo_is_current_screen (dstri))
+ {
+ if (mask == 0xFF || Bpp > 1) {
+ if(can_do_visible_blit)
+ do_blit(dstri, Bpp, srcx, srcy, dstx, dsty, width, height, opcode, 1);
+ else
+ do_blit(dstri, Bpp, dstx, dsty, dstx, dsty, width, height, opcode, 0);
+ } else {
+ do_blit(dstri, Bpp, dstx, dsty, dstx, dsty, width, height, opcode, 0);
+ }
+ P96TRACE(("Did do_blit 1 in BlitRect()\n"));
+ }
+ else
+ {
+ P96TRACE(("Did not do_blit 1 in BlitRect()\n"));
+ }
+
+ return 1;
+}
+
+static int BlitRect (uaecptr ri, uaecptr dstri,
+ unsigned long srcx, unsigned long srcy, unsigned long dstx, unsigned long dsty,
+ unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode)
+{
+ /* Set up the params */
+ CopyRenderInfoStructureA2U(ri, &blitrectdata.ri_struct);
+ blitrectdata.ri = &blitrectdata.ri_struct;
+ if(dstri) {
+ CopyRenderInfoStructureA2U(dstri, &blitrectdata.dstri_struct);
+ blitrectdata.dstri = &blitrectdata.dstri_struct;
+ } else {
+ blitrectdata.dstri = NULL;
+ }
+ blitrectdata.srcx = srcx;
+ blitrectdata.srcy = srcy;
+ blitrectdata.dstx = dstx;
+ blitrectdata.dsty = dsty;
+ blitrectdata.width = width;
+ blitrectdata.height = height;
+ blitrectdata.mask = mask;
+ blitrectdata.opcode = opcode;
+
+ return BlitRectHelper();
+}
+
+/***********************************************************
+BlitRect:
+***********************************************************
+* a0: struct BoardInfo
+* a1: struct RenderInfo
+* d0: WORD SrcX
+* d1: WORD SrcY
+* d2: WORD DstX
+* d3: WORD DstY
+* d4: WORD Width
+* d5: WORD Height
+* d6: UBYTE Mask
+* d7: uae_u32 RGBFormat
+***********************************************************/
+uae_u32 REGPARAM2 picasso_BlitRect (struct regstruct *regs)
+{
+ uaecptr renderinfo = m68k_areg (regs, 1);
+ unsigned long srcx = (uae_u16)m68k_dreg (regs, 0);
+ unsigned long srcy = (uae_u16)m68k_dreg (regs, 1);
+ unsigned long dstx = (uae_u16)m68k_dreg (regs, 2);
+ unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
+ unsigned long width = (uae_u16)m68k_dreg (regs, 4);
+ unsigned long height = (uae_u16)m68k_dreg (regs, 5);
+ uae_u8 Mask = (uae_u8)m68k_dreg (regs, 6);
+ uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#ifdef NOBLIT
+ return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ wgfx_flushline ();
+#endif
+ P96TRACE(("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask));
+ result = BlitRect(renderinfo, 0, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC);
+
+ return result;
+}
+
+/***********************************************************
+BlitRectNoMaskComplete:
+***********************************************************
+* a0: struct BoardInfo
+* a1: struct RenderInfo (src)
+* a2: struct RenderInfo (dst)
+* d0: WORD SrcX
+* d1: WORD SrcY
+* d2: WORD DstX
+* d3: WORD DstY
+* d4: WORD Width
+* d5: WORD Height
+* d6: UBYTE OpCode
+* d7: uae_u32 RGBFormat
+* NOTE: MUST return 0 in D0 if we're not handling this operation
+* because the RGBFormat or opcode aren't supported.
+* OTHERWISE return 1
+***********************************************************/
+uae_u32 REGPARAM2 picasso_BlitRectNoMaskComplete (struct regstruct *regs)
+{
+ uaecptr srcri = m68k_areg (regs, 1);
+ uaecptr dstri = m68k_areg (regs, 2);
+ unsigned long srcx = (uae_u16)m68k_dreg (regs, 0);
+ unsigned long srcy = (uae_u16)m68k_dreg (regs, 1);
+ unsigned long dstx = (uae_u16)m68k_dreg (regs, 2);
+ unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
+ unsigned long width = (uae_u16)m68k_dreg (regs, 4);
+ unsigned long height = (uae_u16)m68k_dreg (regs, 5);
+ uae_u8 OpCode = m68k_dreg (regs, 6);
+ uae_u32 RGBFmt = m68k_dreg (regs, 7);
+ uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#ifdef NOBLIT
+ return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ wgfx_flushline ();
+#endif
+
+ P96TRACE(("BlitRectNoMaskComplete() op 0x%2x, xy(%4d,%4d) --> xy(%4d,%4d), wh(%4d,%4d)\n",
+ OpCode, srcx, srcy, dstx, dsty, width, height));
+
+ result = BlitRect(srcri, dstri, srcx, srcy, dstx, dsty, width, height, 0xFF, OpCode);
+
+ return result;
+}
+
+/* This utility function is used both by BlitTemplate() and BlitPattern() */
+STATIC_INLINE void PixelWrite1(uae_u8 *mem, int bits, uae_u32 fgpen, uae_u32 mask)
+{
+ if (mask != 0xFF)
+ fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
+ do_put_mem_byte (mem + bits, fgpen);
+}
+
+STATIC_INLINE void PixelWrite2(uae_u8 *mem, int bits, uae_u32 fgpen)
+{
+ do_put_mem_word (((uae_u16 *)mem) + bits, fgpen);
+}
+
+STATIC_INLINE void PixelWrite3(uae_u8 *mem, int bits, uae_u32 fgpen)
+{
+ do_put_mem_byte (mem + bits * 3, fgpen & 0x000000FF);
+ *(uae_u16 *)(mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
+}
+
+STATIC_INLINE void PixelWrite4(uae_u8 *mem, int bits, uae_u32 fgpen)
+{
+ do_put_mem_long (((uae_u32 *)mem) + bits, fgpen);
+}
+
+STATIC_INLINE void PixelWrite(uae_u8 *mem, int bits, uae_u32 fgpen, uae_u8 Bpp, uae_u32 mask)
+{
+ switch (Bpp) {
+ case 1:
+ if (mask != 0xFF)
+ fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
+ do_put_mem_byte (mem + bits, (uae_u8)fgpen);
+ break;
+ case 2:
+ do_put_mem_word (((uae_u16 *)mem) + bits, (uae_u16)fgpen);
+ break;
+ case 3:
+ do_put_mem_byte (mem + bits * 3, (uae_u8)fgpen);
+ *(uae_u16 *)(mem + bits * 3 + 1) = (fgpen & 0x00FFFF00) >> 8;
+ break;
+ case 4:
+ do_put_mem_long (((uae_u32 *)mem) + bits, fgpen);
+ break;
+ }
+}
+
+/*
+* BlitPattern:
+*
+* Synopsis:BlitPattern(bi, ri, pattern, X, Y, Width, Height, Mask, RGBFormat);
+* Inputs:
+* a0:struct BoardInfo *bi
+* a1:struct RenderInfo *ri
+* a2:struct Pattern *pattern
+* d0.w:X
+* d1.w:Y
+* d2.w:Width
+* d3.w:Height
+* d4.w:Mask
+* d7.l:RGBFormat
+*
+* This function is used to paint a pattern on the board memory using the blitter. It is called by
+* BltPattern, if a AreaPtrn is used with positive AreaPtSz. The pattern consists of a b/w image
+* using a single plane of image data which will be expanded repeatedly to the destination RGBFormat
+* using ForeGround and BackGround pens as well as draw modes. The width of the pattern data is
+* always 16 pixels (one word) and the height is calculated as 2^Size. The data must be shifted up
+* and to the left by XOffset and YOffset pixels at the beginning.
+*/
+uae_u32 REGPARAM2 picasso_BlitPattern (struct regstruct *regs)
+{
+ uaecptr rinf = m68k_areg (regs, 1);
+ uaecptr pinf = m68k_areg (regs, 2);
+ unsigned long X = (uae_u16)m68k_dreg (regs, 0);
+ unsigned long Y = (uae_u16)m68k_dreg (regs, 1);
+ unsigned long W = (uae_u16)m68k_dreg (regs, 2);
+ unsigned long H = (uae_u16)m68k_dreg (regs, 3);
+ uae_u8 Mask = (uae_u8)m68k_dreg (regs, 4);
+ uae_u32 RGBFmt = m68k_dreg (regs, 7);
+ uae_u8 Bpp = GetBytesPerPixel (RGBFmt);
+ int inversion = 0;
+ struct RenderInfo ri;
+ struct Pattern pattern;
+ unsigned long rows;
+ uae_u32 fgpen;
+ uae_u8 *uae_mem;
+ int xshift;
+ unsigned long ysize_mask;
+ uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#ifdef NOBLIT
+ return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ wgfx_flushline ();
+#endif
+
+ if(CopyRenderInfoStructureA2U (rinf, &ri) && CopyPatternStructureA2U (pinf, &pattern))
+ {
+ Bpp = GetBytesPerPixel(ri.RGBFormat);
+ uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; /* offset with address */
+
+ if (pattern.DrawMode & INVERS)
+ inversion = 1;
+
+ pattern.DrawMode &= 0x03;
+ if (Mask != 0xFF)
+ {
+ if(Bpp > 1)
+ Mask = 0xFF;
+
+ if(pattern.DrawMode == COMP)
+ {
+ write_log ("WARNING - BlitPattern() has unhandled mask 0x%x with COMP DrawMode. Using fall-back routine.\n", Mask);
+ }
+ else
+ {
+ result = 1;
+ }
+ }
+ else
+ {
+ result = 1;
+ }
+
+ if(result)
+ {
+ /* write_log ("BlitPattern() xy(%d,%d), wh(%d,%d) draw 0x%x, off(%d,%d), ph %d\n",
+ X, Y, W, H, pattern.DrawMode, pattern.XOffset, pattern.YOffset, 1 << pattern.Size); */
+ #ifdef P96TRACING_ENABLED
+ DumpPattern(&pattern);
+ #endif
+ ysize_mask = (1 << pattern.Size) - 1;
+ xshift = pattern.XOffset & 15;
+
+ for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow) {
+ unsigned long prow = (rows + pattern.YOffset) & ysize_mask;
+ unsigned int d = do_get_mem_word (((uae_u16 *)pattern.Memory) + prow);
+ uae_u8 *uae_mem2 = uae_mem;
+ unsigned long cols;
+
+ if (xshift != 0)
+ d = (d << xshift) | (d >> (16 - xshift));
+
+ for (cols = 0; cols < W; cols += 16, uae_mem2 += Bpp << 4)
+ {
+ long bits;
+ long max = W - cols;
+ unsigned int data = d;
+
+ if (max > 16)
+ max = 16;
+
+ for (bits = 0; bits < max; bits++)
+ {
+ int bit_set = data & 0x8000;
+ data <<= 1;
+ switch (pattern.DrawMode) {
+ case JAM1:
+ if (inversion)
+ bit_set = !bit_set;
+ if (bit_set)
+ PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
+ break;
+ case JAM2:
+ if (inversion)
+ bit_set = !bit_set;
+ if (bit_set)
+ PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
+ else
+ PixelWrite (uae_mem2, bits, pattern.BgPen, Bpp, Mask);
+ break;
+ case COMP:
+ if (bit_set) {
+ fgpen = pattern.FgPen;
+
+ switch (Bpp) {
+ case 1:
+ {
+ uae_u8 *addr = uae_mem2 + bits;
+ do_put_mem_byte (addr, (uae_u8)(do_get_mem_byte (addr) ^ fgpen));
+ }
+ break;
+ case 2:
+ {
+ uae_u16 *addr = ((uae_u16 *)uae_mem2) + bits;
+ do_put_mem_word (addr, (uae_u16)( do_get_mem_word (addr) ^ fgpen));
+ }
+ break;
+ case 3:
+ {
+ uae_u32 *addr = (uae_u32 *)(uae_mem2 + bits * 3);
+ do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
+ }
+ break;
+ case 4:
+ {
+ uae_u32 *addr = ((uae_u32 *)uae_mem2) + bits;
+ do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ #ifdef PIXEL_LOCK
+ flushpixels();
+ #endif
+
+ /* If we need to update a second-buffer (extra_mem is set), then do it only if visible! */
+ if (picasso_vidinfo.extra_mem && renderinfo_is_current_screen (&ri)) {
+ if (vsyncgfxwrite==0)
+ do_blit(&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
+ }
+ result = 1;
+ }
+ }
+
+ return result;
+}
+
+/*************************************************
+BlitTemplate:
+**************************************************
+* Synopsis: BlitTemplate(bi, ri, template, X, Y, Width, Height, Mask, RGBFormat);
+* a0: struct BoardInfo *bi
+* a1: struct RenderInfo *ri
+* a2: struct Template *template
+* d0.w: X
+* d1.w: Y
+* d2.w: Width
+* d3.w: Height
+* d4.w: Mask
+* d7.l: RGBFormat
+*
+* This function is used to paint a template on the board memory using the blitter.
+* It is called by BltPattern and BltTemplate. The template consists of a b/w image
+* using a single plane of image data which will be expanded to the destination RGBFormat
+* using ForeGround and BackGround pens as well as draw modes.
+***********************************************************************************/
+uae_u32 REGPARAM2 picasso_BlitTemplate (struct regstruct *regs)
+{
+ uae_u8 inversion = 0;
+ uaecptr rinf = m68k_areg (regs, 1);
+ uaecptr tmpl = m68k_areg (regs, 2);
+ unsigned long X = (uae_u16)m68k_dreg (regs, 0);
+ unsigned long Y = (uae_u16)m68k_dreg (regs, 1);
+ unsigned long W = (uae_u16)m68k_dreg (regs, 2);
+ unsigned long H = (uae_u16)m68k_dreg (regs, 3);
+ uae_u16 Mask = (uae_u16)m68k_dreg (regs, 4);
+ struct Template tmp;
+ struct RenderInfo ri;
+ unsigned long rows;
+ int bitoffset;
+ uae_u32 fgpen;
+ uae_u8 *uae_mem, Bpp;
+ uae_u8 *tmpl_base;
+ uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#ifdef NOBLIT
+ return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ wgfx_flushline ();
+#endif
+
+ if (CopyRenderInfoStructureA2U (rinf, &ri) && CopyTemplateStructureA2U (tmpl, &tmp))
+ {
+ Bpp = GetBytesPerPixel(ri.RGBFormat);
+ uae_mem = ri.Memory + Y*ri.BytesPerRow + X*Bpp; /* offset into address */
+
+ if (tmp.DrawMode & INVERS)
+ inversion = 1;
+
+ tmp.DrawMode &= 0x03;
+
+ if (Mask != 0xFF)
+ {
+ if(Bpp > 1)
+ Mask = 0xFF;
+
+ if(tmp.DrawMode == COMP)
+ {
+ write_log ("WARNING - BlitTemplate() has unhandled mask 0x%x with COMP DrawMode. Using fall-back routine.\n", Mask);
+ flushpixels(); //only need in the windows Version
+ return 0;
+ }
+ else
+ {
+ result = 1;
+ }
+ }
+ else
+ {
+ result = 1;
+ }
+#if 1
+ if (tmp.DrawMode == COMP) {
+ /* workaround, let native blitter handle COMP mode */
+ flushpixels();
+ return 0;
+ }
+#endif
+ if(result)
+ {
+ P96TRACE(("BlitTemplate() xy(%d,%d), wh(%d,%d) draw 0x%x fg 0x%x bg 0x%x \n",
+ X, Y, W, H, tmp.DrawMode, tmp.FgPen, tmp.BgPen));
+
+ bitoffset = tmp.XOffset % 8;
+
+#if defined(P96TRACING_ENABLED) && (P96TRACING_LEVEL > 0)
+ DumpTemplate(&tmp, W, H);
+#endif
+
+ tmpl_base = tmp.Memory + tmp.XOffset / 8;
+
+ for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow, tmpl_base += tmp.BytesPerRow) {
+ unsigned long cols;
+ uae_u8 *tmpl_mem = tmpl_base;
+ uae_u8 *uae_mem2 = uae_mem;
+ unsigned int data = *tmpl_mem;
+
+ for (cols = 0; cols < W; cols += 8, uae_mem2 += Bpp << 3) {
+ unsigned int byte;
+ long bits;
+ long max = W - cols;
+
+ if (max > 8)
+ max = 8;
+
+ data <<= 8;
+ data |= *++tmpl_mem;
+
+ byte = data >> (8 - bitoffset);
+
+ for (bits = 0; bits < max; bits++) {
+ int bit_set = (byte & 0x80);
+ byte <<= 1;
+ switch (tmp.DrawMode) {
+ case JAM1:
+ if (inversion)
+ bit_set = !bit_set;
+ if (bit_set) {
+ fgpen = tmp.FgPen;
+ PixelWrite(uae_mem2, bits, fgpen, Bpp, Mask);
+ }
+ break;
+ case JAM2:
+ if (inversion)
+ bit_set = !bit_set;
+ fgpen = tmp.BgPen;
+ if (bit_set)
+ fgpen = tmp.FgPen;
+
+ PixelWrite(uae_mem2, bits, fgpen, Bpp, Mask);
+ break;
+ case COMP:
+ if (bit_set) {
+ fgpen = tmp.FgPen;
+
+ switch (Bpp) {
+ case 1:
+ {
+ uae_u8 *addr = uae_mem2 + bits;
+ do_put_mem_byte (addr, (uae_u8)(do_get_mem_byte (addr) ^ fgpen));
+ }
+ break;
+ case 2:
+ {
+ uae_u16 *addr = ((uae_u16 *)uae_mem2) + bits;
+ do_put_mem_word (addr, (uae_u16)(do_get_mem_word (addr) ^ fgpen));
+ }
+ break;
+ case 3:
+ {
+ uae_u32 *addr = (uae_u32 *)(uae_mem2 + bits * 3);
+ do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
+ }
+ break;
+ case 4:
+ {
+ uae_u32 *addr = ((uae_u32 *)uae_mem2) + bits;
+ do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ #ifdef PIXEL_LOCK
+ flushpixels();
+ #endif
+ /* If we need to update a second-buffer (extra_mem is set), then do it only if visible! */
+ if(picasso_vidinfo.extra_mem && renderinfo_is_current_screen(&ri)) {
+ if (vsyncgfxwrite == 0)
+ do_blit(&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0);
+ }
+ result = 1;
+ }
+}
+ return 1;
+}
+
+/*
+* CalculateBytesPerRow:
+* a0: struct BoardInfo
+* d0: uae_u16 Width
+* d7: RGBFTYPE RGBFormat
+* This function calculates the amount of bytes needed for a line of
+* "Width" pixels in the given RGBFormat.
+*/
+uae_u32 REGPARAM2 picasso_CalculateBytesPerRow (struct regstruct *regs)
+{
+ uae_u16 width = m68k_dreg (regs, 0);
+ uae_u32 type = m68k_dreg (regs, 7);
+
+ width = GetBytesPerPixel(type) * width;
+ P96TRACE(("CalculateBytesPerRow() = %d\n",width));
+
+ return width;
+}
+
+/*
+* SetDisplay:
+* a0: struct BoardInfo
+* d0: BOOL state
+* This function enables and disables the video display.
+*
+* NOTE: return the opposite of the state
+*/
+uae_u32 REGPARAM2 picasso_SetDisplay (struct regstruct *regs)
+{
+ uae_u32 state = m68k_dreg (regs, 0);
+ P96TRACE (("SetDisplay(%d)\n", state));
+ return !state;
+}
+
+void picasso_handle_hsync (void)
+{
+ static int p96hsync;
+
+ if (currprefs.gfxmem_size == 0)
+ return;
+ if (WIN32GFX_IsPicassoScreen () && currprefs.gfx_pfullscreen && currprefs.gfx_vsync) {
+ if (DirectDraw_GetVerticalBlankStatus ())
+ p96hsync = 0;
+ } else {
+ p96hsync--;
+ }
+ if (p96hsync <= 0) {
+ rtarea[get_long (RTAREA_BASE + 36) + 12 - 1]++;
+ p96hsync = p96syncrate;
+ }
+}
+
+void init_hz_p96 (void)
+{
+ int rate;
+ p96syncrate = maxvpos * vblank_hz;
+ if (isfullscreen ())
+ rate = DirectDraw_CurrentRefreshRate ();
+ else
+ rate = abs (currprefs.gfx_refreshrate);
+ if (rate <= 0)
+ rate = 60;
+ p96syncrate /= rate;
+}
+
+/* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
+static void PlanarToChunky(struct RenderInfo *ri, struct BitMap *bm,
+ unsigned long srcx, unsigned long srcy,
+ unsigned long dstx, unsigned long dsty,
+ unsigned long width, unsigned long height,
+ uae_u8 mask)
+{
+ int j;
+
+ uae_u8 *PLANAR[8], *image = ri->Memory + dstx * GetBytesPerPixel (ri->RGBFormat) + dsty * ri->BytesPerRow;
+ int Depth = bm->Depth;
+ unsigned long rows, bitoffset = srcx & 7;
+ long eol_offset;
+
+ /* if (mask != 0xFF)
+ write_log ("P2C - pixel-width = %d, bit-offset = %d\n", width, bitoffset); */
+
+ /* Set up our bm->Planes[] pointers to the right horizontal offset */
+ for (j = 0; j < Depth; j++) {
+ uae_u8 *p = bm->Planes[j];
+ if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
+ p += srcx / 8 + srcy * bm->BytesPerRow;
+ PLANAR[j] = p;
+ if ((mask & (1 << j)) == 0)
+ PLANAR[j] = &all_zeros_bitmap;
+ }
+ eol_offset = (long)bm->BytesPerRow - (long)((width + 7) >> 3);
+ for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
+ unsigned long cols;
+
+ for (cols = 0; cols < width; cols += 8) {
+ int k;
+ uae_u32 a = 0, b = 0;
+ unsigned int msk = 0xFF;
+ long tmp = cols + 8 - width;
+ if (tmp > 0) {
+ msk <<= tmp;
+ b = do_get_mem_long ((uae_u32 *)(image + cols + 4));
+ if (tmp < 4)
+ b &= 0xFFFFFFFF >> (32 - tmp * 8);
+ else if (tmp > 4) {
+ a = do_get_mem_long ((uae_u32 *)(image + cols));
+ a &= 0xFFFFFFFF >> (64 - tmp * 8);
+ }
+ }
+ for (k = 0; k < Depth; k++) {
+ unsigned int data;
+ if (PLANAR[k] == &all_zeros_bitmap)
+ data = 0;
+ else if (PLANAR[k] == &all_ones_bitmap)
+ data = 0xFF;
+ else {
+ data = (uae_u8)(do_get_mem_word ((uae_u16 *)PLANAR[k]) >> (8 - bitoffset));
+ PLANAR[k]++;
+ }
+ data &= msk;
+ a |= p2ctab[data][0] << k;
+ b |= p2ctab[data][1] << k;
+ }
+ do_put_mem_long ((uae_u32 *)(image + cols), a);
+ do_put_mem_long ((uae_u32 *)(image + cols + 4), b);
+ }
+ for (j = 0; j < Depth; j++) {
+ if (PLANAR[j] != &all_zeros_bitmap && PLANAR[j] != &all_ones_bitmap) {
+ PLANAR[j] += eol_offset;
+ }
+ }
+ }
+}
+
+/*
+* BlitPlanar2Chunky:
+* a0: struct BoardInfo *bi
+* a1: struct BitMap *bm - source containing planar information and assorted details
+* a2: struct RenderInfo *ri - dest area and its details
+* d0.w: SrcX
+* d1.w: SrcY
+* d2.w: DstX
+* d3.w: DstY
+* d4.w: SizeX
+* d5.w: SizeY
+* d6.b: MinTerm - uh oh!
+* d7.b: Mask - uh oh!
+*
+* This function is currently used to blit from planar bitmaps within system memory to chunky bitmaps
+* on the board. Watch out for plane pointers that are 0x00000000 (represents a plane with all bits "0")
+* or 0xffffffff (represents a plane with all bits "1").
+*/
+uae_u32 REGPARAM2 picasso_BlitPlanar2Chunky (struct regstruct *regs)
+{
+ uaecptr bm = m68k_areg (regs, 1);
+ uaecptr ri = m68k_areg (regs, 2);
+ unsigned long srcx = (uae_u16)m68k_dreg (regs, 0);
+ unsigned long srcy = (uae_u16)m68k_dreg (regs, 1);
+ unsigned long dstx = (uae_u16)m68k_dreg (regs, 2);
+ unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
+ unsigned long width = (uae_u16)m68k_dreg (regs, 4);
+ unsigned long height = (uae_u16)m68k_dreg (regs, 5);
+ uae_u8 minterm = m68k_dreg (regs, 6) & 0xFF;
+ uae_u8 mask = m68k_dreg (regs, 7) & 0xFF;
+ struct RenderInfo local_ri;
+ struct BitMap local_bm;
+ uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#ifdef NOBLIT
+ return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ wgfx_flushline ();
+#endif
+
+ if (minterm != 0x0C) {
+ write_log ("ERROR - BlitPlanar2Chunky() has minterm 0x%x, which I don't handle. Using fall-back routine.\n",
+ minterm);
+ }
+ else if(CopyRenderInfoStructureA2U (ri, &local_ri) &&
+ CopyBitMapStructureA2U (bm, &local_bm))
+ {
+ P96TRACE(("BlitPlanar2Chunky(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
+ srcx, srcy, dstx, dsty, width, height, minterm, mask, local_bm.Depth));
+ P96TRACE(("P2C - BitMap has %d BPR, %d rows\n", local_bm.BytesPerRow, local_bm.Rows));
+ PlanarToChunky (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, mask);
+ if (renderinfo_is_current_screen (&local_ri))
+ {
+ if (!vsyncgfxwrite)
+ do_blit(&local_ri, GetBytesPerPixel(local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0);
+ }
+ result = 1;
+ }
+
+ return result;
+}
+
+/* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
+static void PlanarToDirect(struct RenderInfo *ri, struct BitMap *bm,
+ unsigned long srcx, unsigned long srcy,
+ unsigned long dstx, unsigned long dsty,
+ unsigned long width, unsigned long height, uae_u8 mask,
+ struct ColorIndexMapping *cim)
+{
+ int j;
+ int bpp = GetBytesPerPixel(ri->RGBFormat);
+ uae_u8 *PLANAR[8];
+ uae_u8 *image = ri->Memory + dstx * bpp + dsty * ri->BytesPerRow;
+ int Depth = bm->Depth;
+ unsigned long rows;
+ long eol_offset;
+
+ if(!bpp)
+ return;
+
+ /* Set up our bm->Planes[] pointers to the right horizontal offset */
+ for (j = 0; j < Depth; j++) {
+ uae_u8 *p = bm->Planes[j];
+ if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
+ p += srcx / 8 + srcy * bm->BytesPerRow;
+ PLANAR[j] = p;
+ if ((mask & (1 << j)) == 0)
+ PLANAR[j] = &all_zeros_bitmap;
+ }
+
+ eol_offset = (long)bm->BytesPerRow - (long)((width + (srcx & 7)) >> 3);
+ for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
+ unsigned long cols;
+ uae_u8 *image2 = image;
+ unsigned int bitoffs = 7 - (srcx & 7);
+ int i;
+
+ for (cols = 0; cols < width; cols ++) {
+ int v = 0, k;
+ for (k = 0; k < Depth; k++) {
+ if (PLANAR[k] == &all_ones_bitmap)
+ v |= 1 << k;
+ else if (PLANAR[k] != &all_zeros_bitmap) {
+ v |= ((*PLANAR[k] >> bitoffs) & 1) << k;
+ }
+ }
+
+ switch (bpp) {
+ case 2:
+ do_put_mem_word ((uae_u16 *)image2, (uae_u16)(cim->Colors[v]));
+ image2 += 2;
+ break;
+ case 3:
+ do_put_mem_byte (image2++, (uae_u8)cim->Colors[v]);
+ do_put_mem_word ((uae_u16 *)image2, (uae_u16)((cim->Colors[v] & 0x00FFFF00) >> 8));
+ image2 += 2;
+ break;
+ case 4:
+ do_put_mem_long ((uae_u32 *)image2, cim->Colors[v]);
+ image2 += 4;
+ break;
+ }
+ bitoffs--;
+ bitoffs &= 7;
+ if (bitoffs == 7) {
+ int k;
+ for (k = 0; k < Depth; k++) {
+ if (PLANAR[k] != &all_zeros_bitmap && PLANAR[k] != &all_ones_bitmap) {
+ PLANAR[k]++;
+ }
+ }
+ }
+ }
+
+ for (i = 0; i < Depth; i++) {
+ if (PLANAR[i] != &all_zeros_bitmap && PLANAR[i] != &all_ones_bitmap) {
+ PLANAR[i] += eol_offset;
+ }
+ }
+ }
+}
+
+/*
+* BlitPlanar2Direct:
+*
+* Synopsis:
+* BlitPlanar2Direct(bi, bm, ri, cim, SrcX, SrcY, DstX, DstY, SizeX, SizeY, MinTerm, Mask);
+* Inputs:
+* a0:struct BoardInfo *bi
+* a1:struct BitMap *bm
+* a2:struct RenderInfo *ri
+* a3:struct ColorIndexMapping *cmi
+* d0.w:SrcX
+* d1.w:SrcY
+* d2.w:DstX
+* d3.w:DstY
+* d4.w:SizeX
+* d5.w:SizeY
+* d6.b:MinTerm
+* d7.b:Mask
+*
+* This function is currently used to blit from planar bitmaps within system memory to direct color
+* bitmaps (15, 16, 24 or 32 bit) on the board. Watch out for plane pointers that are 0x00000000 (represents
+* a plane with all bits "0") or 0xffffffff (represents a plane with all bits "1"). The ColorIndexMapping is
+* used to map the color index of each pixel formed by the bits in the bitmap's planes to a direct color value
+* which is written to the destination RenderInfo. The color mask and all colors within the mapping are words,
+* triple bytes or longwords respectively similar to the color values used in FillRect(), BlitPattern() or
+* BlitTemplate().
+*/
+uae_u32 REGPARAM2 picasso_BlitPlanar2Direct (struct regstruct *regs)
+{
+ uaecptr bm = m68k_areg (regs, 1);
+ uaecptr ri = m68k_areg (regs, 2);
+ uaecptr cim = m68k_areg (regs, 3);
+ unsigned long srcx = (uae_u16)m68k_dreg (regs, 0);
+ unsigned long srcy = (uae_u16)m68k_dreg (regs, 1);
+ unsigned long dstx = (uae_u16)m68k_dreg (regs, 2);
+ unsigned long dsty = (uae_u16)m68k_dreg (regs, 3);
+ unsigned long width = (uae_u16)m68k_dreg (regs, 4);
+ unsigned long height = (uae_u16)m68k_dreg (regs, 5);
+ uae_u8 minterm = m68k_dreg (regs, 6);
+ uae_u8 Mask = m68k_dreg (regs, 7);
+ struct RenderInfo local_ri;
+ struct BitMap local_bm;
+ struct ColorIndexMapping local_cim;
+ uae_u32 result = 0;
+
+#ifdef PIXEL_LOCK
+ flushpixels();
+#endif
+#ifdef NOBLIT
+ return 0;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ wgfx_flushline ();
+#endif
+
+ if (minterm != 0x0C)
+ {
+ write_log ("WARNING - BlitPlanar2Direct() has unhandled op-code 0x%x. Using fall-back routine.\n",
+ minterm);
+ }
+ else if(CopyRenderInfoStructureA2U (ri, &local_ri) &&
+ CopyBitMapStructureA2U (bm, &local_bm))
+ {
+ Mask = 0xFF;
+ CopyColorIndexMappingA2U (cim, &local_cim);
+ P96TRACE(("BlitPlanar2Direct(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
+ srcx, srcy, dstx, dsty, width, height, minterm, Mask, local_bm.Depth));
+ PlanarToDirect (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, Mask, &local_cim);
+ #ifdef PIXEL_LOCK
+ flushpixels();
+ #endif
+ if (renderinfo_is_current_screen (&local_ri)) {
+ if (!vsyncgfxwrite)
+ do_blit(&local_ri, GetBytesPerPixel(local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0);
+ }
+ result = 1;
+ }
+
+ return result;
+}
+
+/* @@@ - Work to be done here!
+*
+* The address is the offset into our Picasso96 frame-buffer (pointed to by gfxmem_start)
+* where the value was put.
+*
+* Porting work: on some machines you may not need these functions, ie. if the memory for the
+* Picasso96 frame-buffer is directly viewable or directly blittable. On Win32 with DirectX,
+* this is not the case. So I provide some write-through functions (as per Mathias' orders!)
+*/
+#ifdef PIXEL_LOCK
+
+struct frect
+{
+ int top, left, right, bottom;
+ int first;
+};
+
+STATIC_INLINE init_refresh(struct frect *r)
+{
+ r->first = 1;
+ r->left = picasso96_state.Width * picasso96_state.BytesPerPixel;
+ r->top = picasso96_state.Height;
+ r->right = -1;
+ r->bottom = -1;
+}
+
+STATIC_INLINE flush_it(struct frect *r)
+{
+ if (r->right >= 0 && r->bottom >= 0) {
+ DX_Invalidate (r->left / picasso96_state.BytesPerPixel, r->top,
+ (r->right - r->left) / picasso96_state.BytesPerPixel + 1, (r->bottom - r->top) + 1);
+ }
+ init_refresh(r);
+}
+
+#define FLUSH_MIN 30
+STATIC_INLINE void flush_refresh(int x, int y, struct frect *r)
+{
+ if (x < r->left) {
+ if (!r->first && r->left - x > FLUSH_MIN) {
+ flush_it(r);
+ flush_refresh(x, y, r);
+ return;
+ }
+ r->left = x;
+ }
+ if (y < r->top) {
+ if (!r->first && r->top - y > FLUSH_MIN) {
+ flush_it(r);
+ flush_refresh(x, y, r);
+ return;
+ }
+ r->top = y;
+ }
+ if (x > r->right) {
+ if (!r->first && x - r->right > FLUSH_MIN) {
+ flush_it(r);
+ flush_refresh(x, y, r);
+ return;
+ }
+ r->right = x;
+ }
+ if (y > r->bottom) {
+ if (!r->first && y - r->bottom > FLUSH_MIN) {
+ flush_it(r);
+ flush_refresh(x, y, r);
+ return;
+ }
+ r->bottom = y;
+ }
+ r->first = 0;
+}
+
+static void flushpixels_2(void)
+{
+ int i;
+ uae_u8 *dst;
+ int lock = 0;
+ int needrefresh;
+ struct frect r;
+
+ if (pixelcount == 0)
+ return;
+ if (!picasso_on) {
+ pixelcount = 0;
+ return;
+ }
+ needrefresh = DirectDraw_GetLockableType() == secondary_surface;
+
+ if(DirectDraw_IsLocked() == FALSE) {
+ dst = gfx_lock_picasso ();
+ lock = 1;
+ } else {
+ dst = picasso96_state.HostAddress;
+ }
+ if (!dst)
+ goto out;
+
+ init_refresh(&r);
+
+ if(picasso_vidinfo.rgbformat != picasso96_state.RGBFormat) {
+
+ int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
+ if (picasso96_state.RGBFormat != RGBFB_CHUNKY) {
+ write_log ("ERROR - flushpixels() has non RGBFB_CHUNKY mode!\n");
+ goto out;
+ }
+ for (i = 0; i < pixelcount; i++) {
+ int i2 = pixelbase[i].size;
+ uaecptr addr = pixelbase[i].addr;
+ uae_u32 value = pixelbase[i].value;
+ int y = addr / picasso96_state.BytesPerRow;
+ int xbytes = addr % picasso96_state.BytesPerRow;
+
+ if (! picasso_vidinfo.extra_mem)
+ break;
+
+ if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height) {
+ if(psiz == 4) {
+ uae_u8 *addr;
+
+ addr = dst + y * picasso_vidinfo.rowbytes + xbytes * 4;
+ if (i2 == 4) {
+ *(uae_u32 *) addr = picasso_vidinfo.clut[value & 0xff];
+ addr += 4;
+ *(uae_u32 *) addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+ addr += 4;
+ *(uae_u32 *) addr = picasso_vidinfo.clut[(value >> 16) & 0xff];
+ addr += 4;
+ *(uae_u32 *) addr = picasso_vidinfo.clut[(value >> 24) & 0xff];
+ break;
+ } else if (i2 == 2) {
+ *(uae_u32 *) addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+ addr += 4;
+ *(uae_u32 *) addr = picasso_vidinfo.clut[value & 0xff];
+ break;
+ } else if (i2 == 1) {
+ *(uae_u32 *) addr = picasso_vidinfo.clut[value & 0xff];
+ break;
+ }
+ } else {
+ uae_u8 *addr;
+
+ addr = dst + y * picasso_vidinfo.rowbytes + xbytes * 2;
+ if (i2 == 4) {
+ *(uae_u16 *) addr = picasso_vidinfo.clut[value & 0xff];
+ addr += 2;
+ *(uae_u16 *) addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+ addr += 2;
+ *(uae_u16 *) addr = picasso_vidinfo.clut[(value >> 16) & 0xff];
+ addr += 2;
+ *(uae_u16 *) addr = picasso_vidinfo.clut[(value >> 24) & 0xff];
+ break;
+ } else if (i2 == 2) {
+ *(uae_u16 *) addr = picasso_vidinfo.clut[(value >> 8) & 0xff];
+ addr+=2;
+ *(uae_u16 *) addr = picasso_vidinfo.clut[value & 0xff];
+ break;
+ } else if (i2 == 1) {
+ *(uae_u16 *) addr = picasso_vidinfo.clut[value & 0xff];
+ break;
+ }
+ }
+ if (needrefresh)
+ flush_refresh(xbytes, y, &r);
+ }
+ }
+
+ } else {
+
+ for (i = 0;i < pixelcount; i++) {
+ uaecptr addr = pixelbase[i].addr;
+ uae_u32 value = pixelbase[i].value;
+ int y = addr / picasso96_state.BytesPerRow;
+ int xbytes = addr % picasso96_state.BytesPerRow;
+ uae_u8 *p = dst + y * picasso_vidinfo.rowbytes + xbytes;
+
+ if (! picasso_vidinfo.extra_mem)
+ continue;
+
+ if (xbytes < picasso96_state.Width * picasso96_state.BytesPerPixel && y < picasso96_state.Height) {
+ switch (pixelbase[i].size)
+ {
+ case 1:
+ *(uae_u8 *)p = value;
+ break;
+ case 2:
+ *(uae_u16 *)p = value;
+ break;
+ case 4:
+ *(uae_u32 *)p = value;
+ break;
+ }
+ if (needrefresh)
+ flush_refresh(xbytes, y, &r);
+ }
+ }
+ }
+out:;
+ if(lock)
+ gfx_unlock_picasso();
+ pixelcount = 0;
+ flush_it(&r);
+}
+
+
+static int watchbuffersize;
+static void **watchbuffer;
+static uae_u8 *secondarygfx;
+extern uae_u8 *natmem_offset;
+
+static void dowatch(void)
+{
+ uae_u8 *dst;
+ int lock = 0;
+ int needrefresh;
+ struct frect r;
+ ULONG pagesize;
+ ULONG_PTR cnt;
+ int i, j, total;
+
+ if (!secondarygfx) {
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ secondarygfx = xmalloc (allocated_gfxmem);
+ watchbuffersize = allocated_gfxmem / si.dwPageSize + 1;
+ watchbuffer = xmalloc (sizeof(void*) * watchbuffersize);
+ }
+
+ cnt = watchbuffersize;
+ if (GetWriteWatch(WRITE_WATCH_FLAG_RESET, gfxmemory, allocated_gfxmem, watchbuffer, &cnt, &pagesize)) {
+ write_log("GetWriteWatch failed, err=%d\n", GetLastError());
+ return;
+ }
+ if (cnt == 0)
+ return;
+
+ needrefresh = DirectDraw_GetLockableType() == secondary_surface;
+
+ if(DirectDraw_IsLocked() == FALSE) {
+ dst = gfx_lock_picasso ();
+ lock = 1;
+ } else {
+ dst = picasso96_state.HostAddress;
+ }
+ if (!dst)
+ goto out;
+
+ init_refresh(&r);
+
+ total = 0;
+ for (i = 0; i < cnt; i++) {
+ uae_u8 *p1 = watchbuffer[i];
+ uae_u8 *p2 = secondarygfx + (p1 - gfxmemory);
+ uaecptr addr = (uaecptr)(p1 - (p96ram_start + natmem_offset)); /* bleh.. */
+ int y, xbytes;
+ uae_u8 *p;
+ int tonextrow_p, tonextrow_addr;
+
+ if (addr >= picasso96_state.Extent)
+ continue;
+ addr -= (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+ + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
+ y = addr / picasso96_state.BytesPerRow;
+ if (y >= picasso96_state.Height)
+ continue;
+ xbytes = addr % picasso96_state.BytesPerRow;
+ p = dst + y * picasso_vidinfo.rowbytes + xbytes;
+ tonextrow_p = picasso_vidinfo.rowbytes - xbytes;
+ tonextrow_addr = (picasso96_state.BytesPerRow - xbytes) / 4;
+
+ for (j = 0; j < pagesize / 4; j++) {
+ uae_u32 *pp1 = (uae_u32*)p1;
+ uae_u32 *pp2 = (uae_u32*)p2;
+ if (pp1[j] != pp2[j]) {
+ pp2[j] = pp1[j];
+ *(uae_u32*)p = pp1[j];
+ if (needrefresh)
+ flush_refresh(xbytes, y, &r);
+ total++;
+ }
+ p += 4;
+ xbytes += 4;
+ if (xbytes >= picasso96_state.Width * picasso96_state.BytesPerPixel) {
+ xbytes -= picasso96_state.Width * picasso96_state.BytesPerPixel;
+ y++;
+ if (y >= picasso96_state.Height)
+ break;
+ p += tonextrow_p;
+ j += tonextrow_addr;
+ }
+ }
+ }
+ write_log("%d ", total);
+out:;
+ if(lock)
+ gfx_unlock_picasso();
+ flush_it(&r);
+}
+
+
+static void flushpixels(void)
+{
+ flushpixels_2();
+ dowatch();
+}
+#endif
+
+static void write_gfx_x (uaecptr addr, uae_u32 value, int size)
+{
+ uaecptr oldaddr = addr;
+ int y;
+#ifdef LOCK_UNLOCK_MADNESS
+ int x, xbytes;
+ uae_u8 *dst;
+#endif
+
+ if (!picasso_on)
+ return;
+
+#ifdef PIXEL_LOCK
+ addr += gfxmem_start;
+ /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
+ if (addr >= picasso96_state.Address && addr + size < picasso96_state.Extent) {
+ addr -= picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+ + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
+ if (pixelcount > MAXFLUSHPIXEL)
+ flushpixels_2();
+ pixelbase[pixelcount].addr = addr;
+ pixelbase[pixelcount].value = value;
+ pixelbase[pixelcount++].size = size;
+ }
+ return;
+#endif
+#ifndef LOCK_UNLOCK_MADNESS
+ /*
+ * Several writes to successive memory locations are a common access pattern.
+ * Try to optimize it.
+ */
+ if (addr >= wgfx_linestart && addr + size <= wgfx_lineend) {
+ if (addr < wgfx_min)
+ wgfx_min = addr;
+ if (addr + size > wgfx_max)
+ wgfx_max = addr + size;
+ return;
+ } else
+ wgfx_flushline ();
+#endif
+
+ addr += gfxmem_start;
+ /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
+ if (addr < picasso96_state.Address || addr + size >= picasso96_state.Extent)
+ return;
+ addr -= picasso96_state.Address + (picasso96_state.XOffset * picasso96_state.BytesPerPixel)
+ + (picasso96_state.YOffset * picasso96_state.BytesPerRow);
+
+ y = addr / picasso96_state.BytesPerRow;
+ xbytes = addr % picasso96_state.BytesPerRow;
+ x = xbytes / picasso96_state.BytesPerPixel;
+
+#ifdef LOCK_UNLOCK_MADNESS
+ if (! picasso_vidinfo.extra_mem) {
+ pixelcount = 0;
+ return;
+ }
+
+ if (x < picasso96_state.Width && y < picasso96_state.Height) {
+ dst = picasso96_state.HostAddress;
+ //dst = gfx_lock_picasso ();
+ if (dst) {
+ switch (size)
+ {
+ case 1:
+ *(uae_u8 *)(dst + y * picasso_vidinfo.rowbytes + xbytes) = value;
+ break;
+ case 2:
+ do_put_mem_word ((uae_u16 *)(dst + y * picasso_vidinfo.rowbytes + xbytes), value);
+ break;
+ case 4:
+ do_put_mem_long ((uae_u32 *)(dst + y * picasso_vidinfo.rowbytes + xbytes), value);
+ break;
+ }
+ //gfx_unlock_picasso ();
+ }
+ }
+#else
+ if (y >= picasso96_state.Height)
+ return;
+ wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
+ wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
+ wgfx_y = y;
+ wgfx_min = oldaddr;
+ wgfx_max = oldaddr + size;
+#endif
+}
+
+static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr)
+{
+ uae_u8 *m;
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ m = gfxmemory + addr;
+ return do_get_mem_long((uae_u32*)m);
+}
+
+static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr)
+{
+ uae_u8 *m;
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ m = gfxmemory + addr;
+ return do_get_mem_word((uae_u16*)m);
+}
+
+static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
+{
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ return gfxmemory[addr];
+}
+
+static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
+{
+ uae_u8 *m;
+#ifdef SWAPSPEEDUP
+ __asm { //byteswap now
+ mov eax,l
+ bswap eax
+ mov l,eax
+ }
+#endif
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+
+ m = gfxmemory + addr;
+#ifdef SWAPSPEEDUP
+ *m = l;
+#else
+ do_put_mem_long((uae_u32*)m, l);
+#endif
+}
+
+static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w)
+{
+ uae_u8 *m;
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ m = gfxmemory + addr;
+ do_put_mem_word((uae_u16*)m, w);
+}
+
+static void REGPARAM2 gfxmem_bput (uaecptr addr, uae_u32 b)
+{
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ gfxmemory[addr] = b;
+}
+
+static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size)
+{
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ return (addr + size) < allocated_gfxmem;
+}
+
+static uae_u8 *REGPARAM2 gfxmem_xlate (uaecptr addr)
+{
+ addr -= gfxmem_start & gfxmem_mask;
+ addr &= gfxmem_mask;
+ return gfxmemory + addr;
+}
+
+addrbank gfxmem_bank = {
+ gfxmem_lget, gfxmem_wget, gfxmem_bget,
+ gfxmem_lput, gfxmem_wput, gfxmem_bput,
+ gfxmem_xlate, gfxmem_check, NULL, "RTG RAM",
+ dummy_lgeti, dummy_wgeti, ABFLAG_RAM
+};
+
+/* Call this function first, near the beginning of code flow
+* Place in InitGraphics() which seems reasonable...
+* Also put it in reset_drawing() for safe-keeping. */
+void InitPicasso96 (void)
+{
+ have_done_picasso = 0;
+ pixelcount = 0;
+ palette_changed = 0;
+//fastscreen
+ oldscr = 0;
+//fastscreen
+ memset (&picasso96_state, 0, sizeof(struct picasso96_state_struct));
+
+ if (1) {
+ int i, count;
+
+ for (i = 0; i < 256; i++) {
+ p2ctab[i][0] = (((i & 128) ? 0x01000000 : 0)
+ | ((i & 64) ? 0x010000 : 0)
+ | ((i & 32) ? 0x0100 : 0)
+ | ((i & 16) ? 0x01 : 0));
+ p2ctab[i][1] = (((i & 8) ? 0x01000000 : 0)
+ | ((i & 4) ? 0x010000 : 0)
+ | ((i & 2) ? 0x0100 : 0)
+ | ((i & 1) ? 0x01 : 0));
+ }
+ count = 0;
+ while (DisplayModes[count].depth >= 0)
+ count++;
+ for (i = 0; i < count; i++) {
+ switch (DisplayModes[i].depth) {
+ case 1:
+ if (DisplayModes[i].res.width > chunky.width)
+ chunky.width = DisplayModes[i].res.width;
+ if (DisplayModes[i].res.height > chunky.height)
+ chunky.height = DisplayModes[i].res.height;
+ break;
+ case 2:
+ if (DisplayModes[i].res.width > hicolour.width)
+ hicolour.width = DisplayModes[i].res.width;
+ if (DisplayModes[i].res.height > hicolour.height)
+ hicolour.height = DisplayModes[i].res.height;
+ break;
+ case 3:
+ if (DisplayModes[i].res.width > truecolour.width)
+ truecolour.width = DisplayModes[i].res.width;
+ if (DisplayModes[i].res.height > truecolour.height)
+ truecolour.height = DisplayModes[i].res.height;
+ break;
+ case 4:
+ if (DisplayModes[i].res.width > alphacolour.width)
+ alphacolour.width = DisplayModes[i].res.width;
+ if (DisplayModes[i].res.height > alphacolour.height)
+ alphacolour.height = DisplayModes[i].res.height;
+ break;
+ }
+ }
+ //ShowSupportedResolutions ();
+ }
+}
+
+uae_u8 *restore_p96 (uae_u8 *src)
+{
+ return src;
+}
+
+uae_u8 *save_p96 (int *len, uae_u8 *dstptr)
+{
+ uae_u8 *dstbak,*dst;
+
+ //dstbak = dst = malloc (16 + 12 + 1 + 1);
+ return 0;
+}
+
+#endif