--- uae/src/picasso96.c 2018/04/24 16:56:42 1.1.1.9 +++ uae/src/picasso96.c 2018/04/24 17:18:27 1.1.1.18 @@ -33,9 +33,8 @@ #include "sysconfig.h" #include "sysdeps.h" -#include "config.h" #include "options.h" -#include "threaddep/penguin.h" +#include "threaddep/thread.h" #include "uae.h" #include "memory.h" #include "custom.h" @@ -45,8 +44,8 @@ #ifdef PICASSO96 -/*#define P96TRACING_ENABLED */ -#ifdef P96TRACING_ENABLED +#define P96TRACING_ENABLED 0 +#if P96TRACING_ENABLED #define P96TRACE(x) do { write_log x; } while(0) #else #define P96TRACE(x) @@ -86,9 +85,72 @@ struct PicassoResolution DisplayModes[MA static int mode_count = 0; +static int set_gc_called = 0; +static int set_panning_called = 0; +/* Address of the screen in the Amiga frame buffer at the time of the last + SetPanning call. */ +static uaecptr oldscr; + +int screen_is_picasso; + static uae_u32 p2ctab[256][2]; /* + * Screen handling. + */ + +static void set_window_for_picasso (void) +{ + P96TRACE (("Function: set_window_for_picasso\n")); +#if 0 + if (current_width == picasso_vidinfo.width && current_height == picasso_vidinfo.height) + return; +#endif + + graphics_subshutdown (0); + graphics_subinit (); + + DX_SetPalette (0, 256); +} + +void gfx_set_picasso_modeinfo (int w, int h, int depth, int rgbfmt) +{ + P96TRACE (("Function: gfx_set_picasso_modeinfo w: %i h: %i depth: %i rgbfmt: %i\n", w, h, depth, rgbfmt)); + + if (screen_is_picasso + && picasso_vidinfo.width == w + && picasso_vidinfo.height == h) + return; + + picasso_vidinfo.width = w; + picasso_vidinfo.height = h; + picasso_vidinfo.depth = depth; + if (screen_is_picasso) + set_window_for_picasso (); +} + +void gfx_set_picasso_baseaddr (uaecptr a) +{ +} + +void gfx_set_picasso_state (int on) +{ + P96TRACE (("Function: gfx_set_picasso_state: %d\n", on)); + + if (on == screen_is_picasso) + return; + + graphics_subshutdown (0); + screen_is_picasso = on; + graphics_subinit (); + + if (on) + DX_SetPalette (0, 256); + else + reset_drawing (); +} + +/* * Debugging dumps */ @@ -189,6 +251,11 @@ static void DumpTemplate (struct Templat } } +int picasso_nr_resolutions (void) +{ + return mode_count; +} + static void ShowSupportedResolutions (void) { int i; @@ -322,8 +389,13 @@ static void CopyLibResolutionStructureU2 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 */ + /* I know that amigamemptr is inside my gfxmem chunk, so I can just + * do the xlate() */ + uaememptr = gfxmem_xlate (amigamemptr); + + /* zero out our LibResolution structure */ + memset (uaememptr, 0, PSSO_LibResolution_sizeof); + strcpy (uaememptr + PSSO_LibResolution_P96ID, libres->P96ID); put_long (amigamemptr + PSSO_LibResolution_DisplayID, libres->DisplayID); put_word (amigamemptr + PSSO_LibResolution_Width, libres->Width); @@ -379,10 +451,30 @@ static void AmigaListAddTail (uaecptr li * 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, int x, int y, int width, int height) +static void do_fillrect (uae_u8 * src, int x, int y, int width, int height, + uae_u32 pen, int Bpp, RGBFTYPE rgbtype) { uae_u8 *dst; + + /* Clipping. */ + x -= picasso96_state.XOffset; + y -= picasso96_state.YOffset; + if (x < 0) { + width += x; + x = 0; + } + if (y < 0) { + height += y; + y = 0; + } + if (x + width > picasso96_state.Width) + width = picasso96_state.Width - x; + if (y + height > picasso96_state.Height) + height = picasso96_state.Height - y; + + if (width <= 0 || height <= 0) + return; + /* Try OS specific fillrect function here; and return if successful. */ DX_Invalidate (y, y + height - 1); @@ -396,9 +488,16 @@ static void do_fillrect (uae_u8 * src, i dst += y * picasso_vidinfo.rowbytes + x * picasso_vidinfo.pixbytes; if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) { - while (height-- > 0) { - memcpy (dst, src, width); - dst += picasso_vidinfo.rowbytes; + 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); @@ -434,10 +533,40 @@ static void do_fillrect (uae_u8 * src, i * srcp. */ -static void do_blit (uae_u8 * srcp, unsigned long src_rowbytes, - int srcx, int srcy, int dstx, int dsty, int width, int height, int can_do_blit) -{ - uae_u8 *dstp; +static void do_blit (struct RenderInfo *ri, int Bpp, int srcx, int srcy, + int dstx, int dsty, int width, int height, + BLIT_OPCODE opcode, int can_do_blit) +{ + int xoff = picasso96_state.XOffset; + int yoff = picasso96_state.YOffset; + uae_u8 *srcp, *dstp; + + /* Clipping. */ + dstx -= xoff; + dsty -= yoff; + if (srcy < yoff || srcx < xoff + || srcx - xoff + width > picasso96_state.Width + || srcy - yoff + height > picasso96_state.Height) + { + can_do_blit = 0; + } + if (dstx < 0) { + srcx -= dstx; + width += dstx; + dstx = 0; + } + if (dsty < 0) { + srcy -= dsty; + height += dsty; + dsty = 0; + } + if (dstx + width > picasso96_state.Width) + width = picasso96_state.Width - dstx; + if (dsty + height > picasso96_state.Height) + height = picasso96_state.Height - dsty; + if (width <= 0 || height <= 0) + return; + /* If this RenderInfo points at something else than the currently visible * screen, we must ignore the blit. */ if (can_do_blit) { @@ -447,6 +576,8 @@ static void do_blit (uae_u8 * srcp, unsi */ } + /* If no OS blit available, we do a copy from the P96 framebuffer in Amiga + memory to the host's frame buffer. */ DX_Invalidate (dsty, dsty + height - 1); if (!picasso_vidinfo.extra_mem) return; @@ -454,16 +585,17 @@ static void do_blit (uae_u8 * srcp, unsi dstp = gfx_lock_picasso (); if (dstp == 0) 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 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 0x%x\n",gfxmemory)); + + srcp = ri->Memory + srcx * Bpp + srcy * ri->BytesPerRow; if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) { - width *= picasso96_state.BytesPerPixel; + width *= Bpp; while (height-- > 0) { memcpy (dstp, srcp, width); - srcp += src_rowbytes; + srcp += ri->BytesPerRow; dstp += picasso_vidinfo.rowbytes; } } else { @@ -485,7 +617,7 @@ static void do_blit (uae_u8 * srcp, unsi default: abort (); } - srcp += src_rowbytes; + srcp += ri->BytesPerRow; dstp += picasso_vidinfo.rowbytes; } } @@ -494,50 +626,87 @@ static void do_blit (uae_u8 * srcp, unsi } /* - * Invert a rectangle on the screen. src and src_rowbytes describe the - * inverted rectangle in the frame buffer, so that do_blit can be used if - * there is no OS specific function to fill the rectangle. + * Invert a rectangle on the screen. */ -static void do_invertrect (uae_u8 * src, unsigned long src_rowbytes, 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 0 + /* Clipping. */ + x -= picasso96_state.XOffset; + y -= picasso96_state.YOffset; + if (x < 0) { + width += x; + x = 0; + } + if (y < 0) { + height += y; + y = 0; + } + if (x + width > picasso96_state.Width) + width = picasso96_state.Width - x; + if (y + height > picasso96_state.Height) + height = picasso96_state.Height - y; + + if (width <= 0 || height <= 0) + return; + +#endif /* TODO: Try OS specific invertrect function here; and return if successful. */ - do_blit (src, src_rowbytes, 0, 0, x, y, width, height, 0); + do_blit (ri, Bpp, x, y, x, y, width, height, BLIT_SRC, 0); } static uaecptr wgfx_linestart; static uaecptr wgfx_lineend; static uaecptr wgfx_min, wgfx_max; -static unsigned long wgfx_y; +static long wgfx_y; static void wgfx_do_flushline (void) { + int src_y = wgfx_y; + long x0, x1, width; uae_u8 *src, *dstp; + int Bpp = GetBytesPerPixel (picasso_vidinfo.rgbformat); + int fb_bpp = picasso96_state.BytesPerPixel; + + wgfx_y -= picasso96_state.YOffset; + if (wgfx_y < 0 || wgfx_y >= picasso96_state.Height) + goto out1; DX_Invalidate (wgfx_y, wgfx_y); if (!picasso_vidinfo.extra_mem) - goto out; + goto out1; + + x0 = wgfx_min - wgfx_linestart; + width = wgfx_max - wgfx_min; + x0 -= picasso96_state.XOffset * fb_bpp; + if (x0 < 0) { + width += x0; + wgfx_min += x0; + x0 = 0; + } + if (x0 + width > picasso96_state.Width * fb_bpp) + width = picasso96_state.Width * fb_bpp - x0; dstp = gfx_lock_picasso (); if (dstp == 0) goto out; - /*printf("flushing %d (%x %x %x)\n", wgfx_y, wgfx_linestart, wgfx_min, wgfx_max); */ + + // P96TRACE(("flushing %d\n", wgfx_y)); src = gfxmemory + wgfx_min; if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) { - dstp += wgfx_y * picasso_vidinfo.rowbytes + wgfx_min - wgfx_linestart; - memcpy (dstp, src, wgfx_max - wgfx_min); + dstp += wgfx_y * picasso_vidinfo.rowbytes + x0; + memcpy (dstp, src, width); } else { - int width = wgfx_max - wgfx_min; int i; - int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat); if (picasso96_state.RGBFormat != RGBFB_CHUNKY) abort (); - dstp += wgfx_y * picasso_vidinfo.rowbytes + (wgfx_min - wgfx_linestart) * psiz; - switch (psiz) { + dstp += wgfx_y * picasso_vidinfo.rowbytes + x0 * Bpp; + switch (Bpp) { case 2: for (i = 0; i < width; i++) *((uae_u16 *) dstp + i) = picasso_vidinfo.clut[src[i]]; @@ -553,6 +722,7 @@ static void wgfx_do_flushline (void) out: gfx_unlock_picasso (); + out1: wgfx_linestart = 0xFFFFFFFF; } @@ -589,12 +759,21 @@ void picasso_refresh (void) /* 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 */ - uae_u8 *ptr = gfxmemory + (picasso96_state.Address - gfxmem_start); + ri.Memory = gfxmemory + (picasso96_state.Address - gfxmem_start); ri.BytesPerRow = picasso96_state.BytesPerRow; ri.RGBFormat = picasso96_state.RGBFormat; - do_blit (ptr, picasso96_state.BytesPerRow, 0, 0, 0, 0, picasso96_state.Width, picasso96_state.Height, 0); - write_log ("picasso_refresh() successful.\n"); + + if (set_panning_called) { + width = picasso96_state.VirtualWidth; + height = picasso96_state.VirtualHeight; + } 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"); } @@ -723,6 +902,7 @@ uae_u32 picasso_InitCard (void) put_word (AmigaBoardInfo + PSSO_BoardInfo_BitsPerCannon, DX_BitsPerCannon ()); put_word (AmigaBoardInfo + PSSO_BoardInfo_RGBFormats, picasso96_pixel_format); put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, picasso96_pixel_format); + put_long (AmigaBoardInfo + PSSO_BoardInfo_BoardType, BT_uaegfx); 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); @@ -758,8 +938,12 @@ uae_u32 picasso_InitCard (void) do { /* Handle this display mode's depth */ - amigamemptr = gfxmem_start + allocated_gfxmem - (PSSO_ModeInfo_sizeof * ModeInfoStructureCount++); - FillBoardInfo (amigamemptr, &res, &DisplayModes[i]); + /* Only add the modes when there is enough P96 RTG memory to hold the bitmap */ + long required = DisplayModes[i].res.width * DisplayModes[i].res.height * DisplayModes[i].depth; + if (allocated_gfxmem - 32768 > required) { + amigamemptr = gfxmem_start + allocated_gfxmem - (PSSO_ModeInfo_sizeof * ModeInfoStructureCount++); + FillBoardInfo (amigamemptr, &res, &DisplayModes[i]); + } i++; } while (i < mode_count && DisplayModes[i].res.width == DisplayModes[j].res.width @@ -796,8 +980,9 @@ uae_u32 picasso_SetSwitch (void) * desired state, and wait for custom.c to call picasso_enablescreen * whenever it is ready to change the screen state. */ picasso_requested_on = !!flag; +#if 1 write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96" : "amiga"); - +#endif /* Put old switch-state in D0 */ return !flag; } @@ -806,7 +991,39 @@ void picasso_enablescreen (int on) { wgfx_linestart = 0xFFFFFFFF; picasso_refresh (); +#if 1 write_log ("SetSwitch() - showing %s screen\n", on ? "picasso96" : "amiga"); +#endif +} + +static int first_color_changed = 256; +static int last_color_changed = -1; + +void picasso_handle_vsync (void) +{ + if (first_color_changed < last_color_changed) { + DX_SetPalette (first_color_changed, last_color_changed - first_color_changed); + /* If we're emulating a CLUT mode, we need to redraw the entire screen. */ + if (picasso_vidinfo.rgbformat != picasso96_state.RGBFormat) + picasso_refresh (); + } + + first_color_changed = 256; + last_color_changed = -1; +} + +void picasso_clip_mouse (int *px, int *py) +{ + int xoff = picasso96_state.XOffset; + int yoff = picasso96_state.YOffset; + if (*px < -xoff) + *px = -xoff; + if (*px + xoff > picasso_vidinfo.width) + *px = picasso_vidinfo.width - xoff; + if (*py < -yoff) + *py = -yoff; + if (*py + yoff > picasso_vidinfo.height) + *py = picasso_vidinfo.height - yoff; } /* @@ -845,7 +1062,10 @@ uae_u32 picasso_SetColorArray (void) clut += 3; } if (changed) { - DX_SetPalette (start, count); + if (start < first_color_changed) + first_color_changed = start; + if (start + count > last_color_changed) + last_color_changed = start + count; } /*write_log ("SetColorArray(%d,%d)\n", start, count); */ return 1; @@ -868,18 +1088,25 @@ uae_u32 picasso_SetDAC (void) return 1; } -static int set_gc_called = 0; -static int set_panning_called = 0; - static void init_picasso_screen (void) { + int width = picasso96_state.Width; + int height = picasso96_state.Height; + int vwidth = picasso96_state.VirtualWidth; + int vheight = picasso96_state.VirtualHeight; + int xoff = 0; + int yoff = 0; + if (!set_gc_called) return; - if (set_panning_called) - picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * picasso96_state.Height); + if (set_panning_called) { + picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * vheight); + xoff = picasso96_state.XOffset; + yoff = picasso96_state.YOffset; + } - gfx_set_picasso_modeinfo (picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth, picasso96_state.RGBFormat); + gfx_set_picasso_modeinfo (width, height, picasso96_state.GC_Depth, picasso96_state.RGBFormat); DX_SetPalette (0, 256); wgfx_linestart = 0xFFFFFFFF; @@ -911,7 +1138,7 @@ uae_u32 picasso_SetGC (void) picasso96_state.GC_Depth = get_byte (modeinfo + PSSO_ModeInfo_Depth); picasso96_state.GC_Flags = get_byte (modeinfo + PSSO_ModeInfo_Flags); - write_log ("SetGC(%d,%d,%d)\n", picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth); + P96TRACE (("SetGC(%d,%d,%d)\n", picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth)); set_gc_called = 1; /* @@@ when do we need to reset this? */ init_picasso_screen (); @@ -944,18 +1171,33 @@ uae_u32 picasso_SetPanning (void) { 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 */ + int oldxoff = picasso96_state.XOffset; + int oldyoff = picasso96_state.YOffset; +#if 0 + /* @@@ This is in WinUAE, but it breaks things. */ + if (oldscr == 0) { + oldscr = start_of_screen; + } + if ((oldscr != start_of_screen)) { + set_gc_called = 0; + oldscr = start_of_screen; + } +#endif picasso96_state.Address = start_of_screen; /* Amiga-side address */ picasso96_state.XOffset = (uae_s16) m68k_dreg (regs, 1); picasso96_state.YOffset = (uae_s16) m68k_dreg (regs, 2); - picasso96_state.VirtualWidth = Width; + picasso96_state.VirtualWidth = get_word (bmeptr + PSSO_BitMapExtra_Width); + picasso96_state.VirtualHeight = get_word (bmeptr + PSSO_BitMapExtra_Height); picasso96_state.RGBFormat = m68k_dreg (regs, 7); picasso96_state.BytesPerPixel = GetBytesPerPixel (picasso96_state.RGBFormat); picasso96_state.BytesPerRow = Width * picasso96_state.BytesPerPixel; set_panning_called = 1; - write_log ("SetPanning(%d, %d, %d) Start 0x%x, BPR %d\n", - Width, picasso96_state.XOffset, picasso96_state.YOffset, start_of_screen, picasso96_state.BytesPerRow); + P96TRACE (("SetPanning(%d, %d, %d) Start 0x%x, BPR %d\n", + Width, picasso96_state.XOffset, picasso96_state.YOffset, start_of_screen, picasso96_state.BytesPerRow)); init_picasso_screen (); @@ -994,7 +1236,7 @@ static void do_xor8 (uae_u8 * ptr, long /* * InvertRect: - * + * * Inputs: * a0:struct BoardInfo *bi * a1:struct RenderInfo *ri @@ -1004,7 +1246,7 @@ static void do_xor8 (uae_u8 * ptr, long * 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. */ @@ -1020,7 +1262,7 @@ uae_u32 picasso_InvertRect (void) uae_u32 xorval; unsigned int lines; struct RenderInfo ri; - uae_u8 *uae_mem, *rectstart; + uae_u8 *uae_mem; unsigned long width_in_bytes; wgfx_flushline (); @@ -1028,12 +1270,13 @@ uae_u32 picasso_InvertRect (void) if (!CopyRenderInfoStructureA2U (renderinfo, &ri)) return 0; + P96TRACE (("InvertRect: X %d Y %d Width %d Height %d\n", X, Y, Width, Height)); /*write_log ("InvertRect %d %lx\n", Bpp, (long)mask); */ /* ??? Brian? mask used to be 32 bit, but it appears that only 8 bit * values are passed to this function. This code here seems to work * much better... */ - if (mask != 0xFF && Bpp > 8) { + if (mask != 0xFF && Bpp > 1) { write_log ("InvertRect: not obeying mask 0x%x properly with Bpp %d.\n", mask, Bpp); mask = 0xFF; } @@ -1042,21 +1285,71 @@ uae_u32 picasso_InvertRect (void) } xorval = 0x01010101 * (mask & 0xFF); width_in_bytes = Bpp * Width; - rectstart = uae_mem = ri.Memory + Y * ri.BytesPerRow + X * Bpp; + 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 (renderinfo_is_current_screen (&ri)) { if (mask == 0xFF) - do_invertrect (rectstart, ri.BytesPerRow, X, Y, Width, Height); + do_invertrect (&ri, Bpp, X, Y, Width, Height); else - do_blit (rectstart, ri.BytesPerRow, 0, 0, X, Y, Width, Height, 0); + do_blit (&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0); } return 1; /* 1 if supported, 0 otherwise */ } +/* Fill a rectangle in the Amiga-memory frame buffer. */ + +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) +{ + uae_u8 *start, *oldstart, *dst; + long lines, cols; + + /* Do our virtual frame-buffer memory. First, we do a single line fill by hand */ + oldstart = start = ri->Memory + Y * ri->BytesPerRow + X * Bpp; + switch (Bpp) { + case 1: + memset (start, Pen, Width); + break; + case 2: + for (cols = 0; cols < Width; cols++) { + do_put_mem_word ((uae_u16 *) start, Pen); + start += 2; + } + break; + case 3: + for (cols = 0; cols < Width; cols++) { + do_put_mem_byte (start, Pen & 0x000000FF); + 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; + } + + dst = oldstart + 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, oldstart, Width * Bpp); + } else { + for (lines = 0; lines < (Height - 1); lines++, dst += ri->BytesPerRow) + memset (dst, Pen, Width); + } +} + + /*********************************************************** FillRect: *********************************************************** @@ -1081,9 +1374,6 @@ uae_u32 picasso_FillRect (void) uae_u8 Mask = (uae_u8) m68k_dreg (regs, 5); uae_u32 RGBFormat = m68k_dreg (regs, 7); - uae_u8 *src, *dst; - uae_u8 *start, *oldstart; - unsigned long lines, cols; int Bpp; struct RenderInfo ri; @@ -1092,51 +1382,23 @@ uae_u32 picasso_FillRect (void) if (!CopyRenderInfoStructureA2U (renderinfo, &ri) || Y == 0xFFFF) return 0; + 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 (ri.RGBFormat != RGBFormat) write_log ("Weird Stuff!\n"); Bpp = GetBytesPerPixel (RGBFormat); - /*write_log ("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n", + /* write_log ("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 (Mask == 0xFF) { - /* Do our virtual frame-buffer memory. First, we do a single line fill by hand */ - oldstart = start = ri.Memory + Y * ri.BytesPerRow + X * Bpp; - switch (Bpp) { - case 1: - memset (start, Pen, Width); - break; - case 2: - for (cols = 0; cols < Width; cols++) { - do_put_mem_word ((uae_u16 *) start, Pen); - start += 2; - } - break; - case 3: - for (cols = 0; cols < Width; cols++) { - do_put_mem_byte (start, Pen & 0x000000FF); - 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 (lines = 0; lines < (Height - 1); lines++, dst += ri.BytesPerRow) - memcpy (dst, src, Width * Bpp); + do_fillrect_frame_buffer (&ri, X, Y, Width, Height, Pen, Bpp, RGBFormat); if (renderinfo_is_current_screen (&ri)) - do_fillrect (src, X, Y, Width, Height); + do_fillrect (ri.Memory + Y * ri.BytesPerRow + X * Bpp, X, Y, + Width, Height, Pen, Bpp, RGBFormat); return 1; } @@ -1149,9 +1411,8 @@ uae_u32 picasso_FillRect (void) Pen &= Mask; Mask = ~Mask; - oldstart = ri.Memory + Y * ri.BytesPerRow + X * Bpp; { - uae_u8 *start = oldstart; + uae_u8 *start = ri.Memory + Y * ri.BytesPerRow + X * Bpp; uae_u8 *end = start + Height * ri.BytesPerRow; for (; start != end; start += ri.BytesPerRow) { uae_u8 *p = start; @@ -1162,8 +1423,9 @@ uae_u32 picasso_FillRect (void) } } } + if (renderinfo_is_current_screen (&ri)) - do_blit (oldstart, ri.BytesPerRow, 0, 0, X, Y, Width, Height, 0); + do_blit (&ri, Bpp, X, Y, X, Y, Width, Height, BLIT_SRC, 0); return 1; } @@ -1174,7 +1436,7 @@ uae_u32 picasso_FillRect (void) */ static void BlitRect (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) + unsigned long width, unsigned long height, uae_u8 mask, BLIT_OPCODE opcode) { uae_u8 *src, *dst, *tmp, *tmp2, *tmp3; unsigned long lines; @@ -1221,8 +1483,10 @@ static void BlitRect (struct RenderInfo for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow) memcpy (dst, src, total_width); } + if (cant_blit) + srcx = dstx, srcy = dsty; if (renderinfo_is_current_screen (dstri)) - do_blit (blitsrc, dstri->BytesPerRow, srcx, srcy, dstx, dsty, width, height, !cant_blit); + do_blit (dstri, Bpp, srcx, srcy, dstx, dsty, width, height, opcode, !cant_blit); return; } @@ -1244,7 +1508,8 @@ static void BlitRect (struct RenderInfo } } if (renderinfo_is_current_screen (dstri)) - do_blit (blitsrc, dstri->BytesPerRow, srcx, srcy, dstx, dsty, width, height, 0); + do_blit (dstri, Bpp, dstx, dsty, dstx, dsty, width, height, opcode, 0); + /* free the temp-buf */ free (tmp3); @@ -1282,7 +1547,8 @@ uae_u32 picasso_BlitRect (void) if (!CopyRenderInfoStructureA2U (renderinfo, &ri)) return 0; - BlitRect (&ri, NULL, srcx, srcy, dstx, dsty, width, height, Mask); + P96TRACE(("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask)); + BlitRect (&ri, NULL, srcx, srcy, dstx, dsty, width, height, Mask, BLIT_SRC); /*write_log ("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask); */ return 1; @@ -1326,14 +1592,12 @@ uae_u32 picasso_BlitRectNoMaskComplete ( || !CopyRenderInfoStructureA2U (dstri, &dst_ri)) return 0; - /*write_log ("BlitRectNoMaskComplete() op 0x%2x, Bpp %d, xy(%4d,%4d) --> xy(%4d,%4d), wh(%4d,%4d)\n", - OpCode, Bpp, srcx, srcy, dstx, dsty, width, height); */ - /*write_log ("-- src mem 0x%x BPR %d, dst mem 0x%x BPR %d, screen-mem 0x%x - 0x%x\n", - src_ri.Memory, src_ri.BytesPerRow, dst_ri.Memory, dst_ri.BytesPerRow, picasso96_state.Address, picasso96_state.Extent); */ + P96TRACE(("BlitRectNoMaskComplete() op 0x%2x, xy(%4d,%4d) --> xy(%4d,%4d), wh(%4d,%4d)\n", + OpCode, srcx, srcy, dstx, dsty, width, height)); switch (OpCode) { case 0x0C: - BlitRect (&src_ri, &dst_ri, srcx, srcy, dstx, dsty, width, height, 0xFF); + BlitRect (&src_ri, &dst_ri, srcx, srcy, dstx, dsty, width, height, 0xFF, OpCode); return 1; default: @@ -1389,7 +1653,7 @@ STATIC_INLINE void PixelWrite (uae_u8 * /* * BlitPattern: - * + * * Synopsis:BlitPattern(bi, ri, pattern, X, Y, Width, Height, Mask, RGBFormat); * Inputs: * a0:struct BoardInfo *bi @@ -1401,7 +1665,7 @@ STATIC_INLINE void PixelWrite (uae_u8 * * 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 @@ -1426,13 +1690,13 @@ uae_u32 picasso_BlitPattern (void) struct Pattern pattern; unsigned long rows; uae_u32 fgpen; - uae_u8 *uae_mem, *frame_buffer_UAM; + uae_u8 *uae_mem; int xshift; unsigned long ysize_mask; wgfx_flushline (); - if (!CopyRenderInfoStructureA2U (rinf, &ri) + if (! CopyRenderInfoStructureA2U (rinf, &ri) || !CopyPatternStructureA2U (pinf, &pattern)) return 0; @@ -1452,8 +1716,8 @@ uae_u32 picasso_BlitPattern (void) } } - /* 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); */ + P96TRACE (("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 _DEBUG DumpPattern (&pattern); #endif @@ -1532,9 +1796,8 @@ uae_u32 picasso_BlitPattern (void) } } - frame_buffer_UAM = ri.Memory + X * picasso96_state.BytesPerPixel + Y * ri.BytesPerRow; if (renderinfo_is_current_screen (&ri)) - do_blit (frame_buffer_UAM, ri.BytesPerRow, 0, 0, X, Y, W, H, 0); + do_blit (&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0); return 1; } @@ -1573,7 +1836,7 @@ uae_u32 picasso_BlitTemplate (void) unsigned long rows; int bitoffset; uae_u32 fgpen; - uae_u8 *uae_mem, Bpp, *frame_buffer_UAM; + uae_u8 *uae_mem, Bpp; uae_u8 *tmpl_base; wgfx_flushline (); @@ -1598,8 +1861,8 @@ uae_u32 picasso_BlitTemplate (void) } } - /*write_log ("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); */ + 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; @@ -1686,9 +1949,8 @@ uae_u32 picasso_BlitTemplate (void) } } - frame_buffer_UAM = ri.Memory + X * picasso96_state.BytesPerPixel + Y * ri.BytesPerRow; if (renderinfo_is_current_screen (&ri)) - do_blit (frame_buffer_UAM, ri.BytesPerRow, 0, 0, X, Y, W, H, 0); + do_blit (&ri, Bpp, X, Y, X, Y, W, H, BLIT_SRC, 0); return 1; } @@ -1707,7 +1969,7 @@ uae_u32 picasso_CalculateBytesPerRow (vo uae_u32 type = m68k_dreg (regs, 7); width = GetBytesPerPixel (type) * width; - /*write_log ("CalculateBytesPerRow() = %d\n",width); */ + P96TRACE (("CalculateBytesPerRow() = %d\n", width)); return width; } @@ -1717,13 +1979,13 @@ uae_u32 picasso_CalculateBytesPerRow (vo * a0: struct BoardInfo * d0: BOOL state * This function enables and disables the video display. - * + * * NOTE: return the opposite of the state */ uae_u32 picasso_SetDisplay (void) { uae_u32 state = m68k_dreg (regs, 0); - write_log ("SetDisplay(%d)\n", state); + P96TRACE (("SetDisplay(%d)\n", state)); return !state; } @@ -1750,7 +2012,7 @@ static void PlanarToChunky (struct Rende unsigned long rows, bitoffset = srcx & 7; long eol_offset; - /* if (mask != 0xFF) + /* 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 */ @@ -1849,18 +2111,16 @@ uae_u32 picasso_BlitPlanar2Chunky (void) || !CopyBitMapStructureA2U (bm, &local_bm)) return 0; - /*write_log ("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); - write_log ("P2C - BitMap has %d BPR, %d rows\n", local_bm.BytesPerRow, local_bm.Rows); */ + 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)) - do_blit (local_ri.Memory + dstx * GetBytesPerPixel (local_ri.RGBFormat) + dsty * local_ri.BytesPerRow, - local_ri.BytesPerRow, 0, 0, dstx, dsty, width, height, 0); + do_blit (&local_ri, GetBytesPerPixel (local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0); return 1; } -/* 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, @@ -1937,8 +2197,8 @@ static void PlanarToDirect (struct Rende } /* - * BlitPlanar2Direct: - * + * BlitPlanar2Direct: + * * Synopsis: * BlitPlanar2Direct(bi, bm, ri, cim, SrcX, SrcY, DstX, DstY, SizeX, SizeY, MinTerm, Mask); * Inputs: @@ -1954,14 +2214,14 @@ static void PlanarToDirect (struct Rende * 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(). + * BlitTemplate(). */ uae_u32 picasso_BlitPlanar2Direct (void) { @@ -1995,12 +2255,11 @@ uae_u32 picasso_BlitPlanar2Direct (void) return 0; CopyColorIndexMappingA2U (cim, &local_cim); - /* write_log ("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); */ + 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); if (renderinfo_is_current_screen (&local_ri)) - do_blit (local_ri.Memory + dstx * GetBytesPerPixel (local_ri.RGBFormat) + dsty * local_ri.BytesPerRow, - local_ri.BytesPerRow, 0, 0, dstx, dsty, width, height, 0); + do_blit (&local_ri, GetBytesPerPixel (local_ri.RGBFormat), dstx, dsty, dstx, dsty, width, height, BLIT_SRC, 0); return 1; } @@ -2043,30 +2302,13 @@ static void write_gfx_long (uaecptr addr addr -= picasso96_state.Address; y = addr / picasso96_state.BytesPerRow; -#if 0 - DX_Invalidate (y, y); - if (!picasso_vidinfo.extra_mem) - return; - - xbytes = addr - y * picasso96_state.BytesPerRow; - x = xbytes / picasso96_state.BytesPerPixel; - - if (x < picasso96_state.Width && y < picasso96_state.Height) { - dst = gfx_lock_picasso (); - if (dst) { - do_put_mem_long ((uae_u32 *) (dst + y * picasso_vidinfo.rowbytes + xbytes), value); - gfx_unlock_picasso (); - } - } -#else - if (y >= picasso96_state.Height) + if (y >= picasso96_state.VirtualHeight) 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 + 4; -#endif } static void write_gfx_word (uaecptr addr, uae_u16 value) @@ -2099,30 +2341,13 @@ static void write_gfx_word (uaecptr addr addr -= picasso96_state.Address; y = addr / picasso96_state.BytesPerRow; -#if 0 - DX_Invalidate (y, y); - if (!picasso_vidinfo.extra_mem) - return; - - xbytes = addr - y * picasso96_state.BytesPerRow; - x = xbytes / picasso96_state.BytesPerPixel; - - if (x < picasso96_state.Width && y < picasso96_state.Height) { - dst = gfx_lock_picasso (); - if (dst) { - do_put_mem_word ((uae_u16 *) (dst + y * picasso_vidinfo.rowbytes + xbytes), value); - gfx_unlock_picasso (); - } - } -#else - if (y >= picasso96_state.Height) + if (y >= picasso96_state.VirtualHeight) 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 + 2; -#endif } static void write_gfx_byte (uaecptr addr, uae_u8 value) @@ -2155,36 +2380,19 @@ static void write_gfx_byte (uaecptr addr addr -= picasso96_state.Address; y = addr / picasso96_state.BytesPerRow; -#if 0 - DX_Invalidate (y, y); - if (!picasso_vidinfo.extra_mem) - return; - - xbytes = addr - y * picasso96_state.BytesPerRow; - x = xbytes / picasso96_state.BytesPerPixel; - - if (x < picasso96_state.Width && y < picasso96_state.Height) { - dst = gfx_lock_picasso (); - if (dst) { - *(uae_u8 *) (dst + y * picasso_vidinfo.rowbytes + xbytes) = value; - gfx_unlock_picasso (); - } - } -#else - if (y >= picasso96_state.Height) + if (y >= picasso96_state.VirtualHeight) 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 + 1; -#endif } static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr) { uae_u32 *m; - addr -= gfxmem_start & gfxmem_mask; + addr -= gfxmem_start; addr &= gfxmem_mask; m = (uae_u32 *) (gfxmemory + addr); return do_get_mem_long (m); @@ -2193,7 +2401,7 @@ static uae_u32 REGPARAM2 gfxmem_lget (ua static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr) { uae_u16 *m; - addr -= gfxmem_start & gfxmem_mask; + addr -= gfxmem_start; addr &= gfxmem_mask; m = (uae_u16 *) (gfxmemory + addr); return do_get_mem_word (m); @@ -2201,7 +2409,7 @@ static uae_u32 REGPARAM2 gfxmem_wget (ua static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr) { - addr -= gfxmem_start & gfxmem_mask; + addr -= gfxmem_start; addr &= gfxmem_mask; return gfxmemory[addr]; } @@ -2209,7 +2417,7 @@ static uae_u32 REGPARAM2 gfxmem_bget (ua static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l) { uae_u32 *m; - addr -= gfxmem_start & gfxmem_mask; + addr -= gfxmem_start; addr &= gfxmem_mask; m = (uae_u32 *) (gfxmemory + addr); do_put_mem_long (m, l); @@ -2221,7 +2429,7 @@ static void REGPARAM2 gfxmem_lput (uaecp static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w) { uae_u16 *m; - addr -= gfxmem_start & gfxmem_mask; + addr -= gfxmem_start; addr &= gfxmem_mask; m = (uae_u16 *) (gfxmemory + addr); do_put_mem_word (m, (uae_u16) w); @@ -2232,7 +2440,7 @@ static void REGPARAM2 gfxmem_wput (uaecp static void REGPARAM2 gfxmem_bput (uaecptr addr, uae_u32 b) { - addr -= gfxmem_start & gfxmem_mask; + addr -= gfxmem_start; addr &= gfxmem_mask; gfxmemory[addr] = b; @@ -2242,14 +2450,14 @@ static void REGPARAM2 gfxmem_bput (uaecp static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size) { - addr -= gfxmem_start & gfxmem_mask; + addr -= gfxmem_start; addr &= gfxmem_mask; return (addr + size) < allocated_gfxmem; } static uae_u8 REGPARAM2 *gfxmem_xlate (uaecptr addr) { - addr -= gfxmem_start & gfxmem_mask; + addr -= gfxmem_start; addr &= gfxmem_mask; return gfxmemory + addr; } @@ -2257,9 +2465,23 @@ static uae_u8 REGPARAM2 *gfxmem_xlate (u addrbank gfxmem_bank = { gfxmem_lget, gfxmem_wget, gfxmem_bget, gfxmem_lput, gfxmem_wput, gfxmem_bput, - gfxmem_xlate, gfxmem_check + gfxmem_xlate, gfxmem_check, NULL }; +int picasso_display_mode_index (uae_u32 x, uae_u32 y, uae_u32 d) +{ + int i; + for (i = 0; i < mode_count; i++) { + if (DisplayModes[i].res.width == x + && DisplayModes[i].res.height == y + && DisplayModes[i].depth == d) + break; + } + if (i == mode_count) + i = -1; + return i; +} + static int resolution_compare (const void *a, const void *b) { struct PicassoResolution *ma = (struct PicassoResolution *) a;