|
|
1.1 root 1: /*
2: * UAE - The U*nix Amiga Emulator
3: *
4: * Picasso96 Support Module
5: *
6: * Copyright 1997 Brian King <[email protected], [email protected]>
7: *
8: * Theory of operation:
9: * On the Amiga side, a Picasso card consists mainly of a memory area that
10: * contains the frame buffer. On the UAE side, we allocate a block of memory
11: * that will hold the frame buffer. This block is in normal memory, it is
12: * never directly on the graphics card. All graphics operations, which are
13: * mainly reads and writes into this block and a few basic operations like
14: * filling a rectangle, operate on this block of memory.
15: * Since the memory is not on the graphics card, some work must be done to
16: * synchronize the display with the data in the Picasso frame buffer. There
17: * are various ways to do this. One possibility is to allocate a second
18: * buffer of the same size, and perform all write operations twice. Since
19: * we never read from the second buffer, it can actually be placed in video
20: * memory. The X11 driver could be made to use the Picasso frame buffer as
21: * the data buffer of an XImage, which could then be XPutImage()d from time
22: * to time. Another possibility is to translate all Picasso accesses into
23: * Xlib (or GDI, or whatever your graphics system is) calls. This possibility
24: * is a bit tricky, since there is a risk of generating very many single pixel
25: * accesses which may be rather slow.
26: *
27: * TODO:
28: * - add panning capability
29: */
30:
31: #include "sysconfig.h"
32: #include "sysdeps.h"
33:
34: #include "config.h"
35: #include "options.h"
36: #include "threaddep/penguin.h"
37: #include "uae.h"
38: #include "memory.h"
39: #include "custom.h"
40: #include "readcpu.h"
41: #include "newcpu.h"
42: #include "xwin.h"
43: #include "picasso96.h"
44:
45: #ifdef PICASSO96
46:
47: static uae_u32 gfxmem_lget (uaecptr) REGPARAM;
48: static uae_u32 gfxmem_wget (uaecptr) REGPARAM;
49: static uae_u32 gfxmem_bget (uaecptr) REGPARAM;
50: static void gfxmem_lput (uaecptr, uae_u32) REGPARAM;
51: static void gfxmem_wput (uaecptr, uae_u32) REGPARAM;
52: static void gfxmem_bput (uaecptr, uae_u32) REGPARAM;
53: static int gfxmem_check (uaecptr addr, uae_u32 size) REGPARAM;
54: static uae_u8 *gfxmem_xlate (uaecptr addr) REGPARAM;
55:
56: static void write_gfx_long (uaecptr addr, uae_u32 value);
57: static void write_gfx_word (uaecptr addr, uae_u16 value);
58: static void write_gfx_byte (uaecptr addr, uae_u8 value);
59:
60: static uae_u8 all_ones_bitmap, all_zeros_bitmap; /* yuk */
61:
62: struct picasso96_state_struct picasso96_state;
63: struct picasso_vidbuf_description picasso_vidinfo;
64:
65: /* These are the maximum resolutions... They are filled in by GetSupportedResolutions() */
66: /* have to fill this in, otherwise problems occur
67: * @@@ ??? what problems?
68: */
69: struct ScreenResolution planar = { 320, 240 };
70: struct ScreenResolution chunky = { 640, 480 };
71: struct ScreenResolution hicolour = { 640, 480 };
72: struct ScreenResolution truecolour = { 640, 480 };
73: struct ScreenResolution alphacolour = { 460, 480 };
74:
75: uae_u16 picasso96_pixel_format = RGBFF_CHUNKY;
76:
77: struct PicassoResolution DisplayModes[MAX_PICASSO_MODES];
78:
79: static int mode_count = 0;
80:
81: static uae_u32 p2ctab[256][2];
82:
83: /*
84: * Debugging dumps
85: */
86:
87: static void DumpModeInfoStructure (uaecptr amigamodeinfoptr)
88: {
1.1.1.2 ! root 89: write_log ("ModeInfo Structure Dump:\n");
! 90: write_log (" Node.ln_Succ = 0x%x\n", get_long (amigamodeinfoptr));
! 91: write_log (" Node.ln_Pred = 0x%x\n", get_long (amigamodeinfoptr + 4));
! 92: write_log (" Node.ln_Type = 0x%x\n", get_byte (amigamodeinfoptr + 8));
! 93: write_log (" Node.ln_Pri = %d\n", get_byte (amigamodeinfoptr + 9));
! 94: /*write_log (" Node.ln_Name = %s\n", uaememptr->Node.ln_Name); */
! 95: write_log (" OpenCount = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_OpenCount));
! 96: write_log (" Active = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Active));
! 97: write_log (" Width = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Width));
! 98: write_log (" Height = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_Height));
! 99: write_log (" Depth = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Depth));
! 100: write_log (" Flags = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_Flags));
! 101: write_log (" HorTotal = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorTotal));
! 102: write_log (" HorBlankSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorBlankSize));
! 103: write_log (" HorSyncStart = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncStart));
! 104: write_log (" HorSyncSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSize));
! 105: write_log (" HorSyncSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorSyncSkew));
! 106: write_log (" HorEnableSkew = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_HorEnableSkew));
! 107: write_log (" VerTotal = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerTotal));
! 108: write_log (" VerBlankSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerBlankSize));
! 109: write_log (" VerSyncStart = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncStart));
! 110: write_log (" VerSyncSize = %d\n", get_word (amigamodeinfoptr + PSSO_ModeInfo_VerSyncSize));
! 111: write_log (" Clock = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_first_union));
! 112: write_log (" ClockDivide = %d\n", get_byte (amigamodeinfoptr + PSSO_ModeInfo_second_union));
! 113: write_log (" PixelClock = %d\n", get_long (amigamodeinfoptr + PSSO_ModeInfo_PixelClock));
1.1 root 114: }
115:
116: static void DumpLibResolutionStructure (uaecptr amigalibresptr)
117: {
118: int i;
119: uaecptr amigamodeinfoptr;
120: struct LibResolution *uaememptr = (struct LibResolution *)get_mem_bank(amigalibresptr).xlateaddr(amigalibresptr);
121:
122: return;
123:
1.1.1.2 ! root 124: write_log ("LibResolution Structure Dump:\n");
1.1 root 125:
126: if (get_long (amigalibresptr + PSSO_LibResolution_DisplayID) == 0xFFFFFFFF) {
1.1.1.2 ! root 127: write_log (" Finished With LibResolutions...\n");
1.1 root 128: } else {
1.1.1.2 ! root 129: write_log (" Name = %s\n", uaememptr->P96ID);
! 130: write_log (" DisplayID = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_DisplayID));
! 131: write_log (" Width = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Width));
! 132: write_log (" Height = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Height));
! 133: write_log (" Flags = %d\n", get_word (amigalibresptr + PSSO_LibResolution_Flags));
1.1 root 134: for (i = 0; i < MAXMODES; i++) {
135: amigamodeinfoptr = get_long (amigalibresptr + PSSO_LibResolution_Modes + i*4);
1.1.1.2 ! root 136: write_log (" ModeInfo[%d] = 0x%x\n", i, amigamodeinfoptr);
1.1 root 137: if (amigamodeinfoptr)
1.1.1.2 ! root 138: DumpModeInfoStructure (amigamodeinfoptr);
1.1 root 139: }
1.1.1.2 ! root 140: write_log (" BoardInfo = 0x%x\n", get_long (amigalibresptr + PSSO_LibResolution_BoardInfo));
1.1 root 141: }
142: }
143:
144: static char binary_byte[8];
145:
146: static char *BuildBinaryString (uae_u8 value)
147: {
148: int i;
149: for (i = 0; i < 8; i++) {
150: binary_byte[i] = (value & (1 << (7 - i))) ? '#' : '.';
151: }
152: return binary_byte;
153: }
154:
155: static void DumpPattern (struct Pattern *patt)
156: {
157: uae_u8 *mem;
158: int row, col;
159: for (row = 0; row < (1 << patt->Size); row++) {
160: mem = patt->Memory + row * 2;
161: for (col = 0; col < 2; col++) {
1.1.1.2 ! root 162: write_log ("%s", BuildBinaryString (*mem++));
1.1 root 163: }
1.1.1.2 ! root 164: write_log ("\n");
1.1 root 165: }
166: }
167:
168: static void DumpTemplate (struct Template *tmp, uae_u16 w, uae_u16 h)
169: {
170: uae_u8 *mem = tmp->Memory;
171: int row, col, width;
172: width = (w + 7) >> 3;
1.1.1.2 ! root 173: write_log ("xoffset = %d, bpr = %d\n", tmp->XOffset, tmp->BytesPerRow);
1.1 root 174: for (row = 0; row < h; row++) {
175: mem = tmp->Memory + row * tmp->BytesPerRow;
176: for (col = 0; col < width; col++) {
1.1.1.2 ! root 177: write_log ("%s", BuildBinaryString (*mem++));
1.1 root 178: }
1.1.1.2 ! root 179: write_log ("\n");
1.1 root 180: }
181: }
182:
183: static void ShowSupportedResolutions (void)
184: {
185: int i;
186:
187: return;
188:
189: for (i = 0; i < mode_count; i++)
1.1.1.2 ! root 190: write_log ("%s\n", DisplayModes[i].name);
! 191: }
! 192:
! 193: static uae_u8 GetBytesPerPixel (uae_u32 RGBfmt)
! 194: {
! 195: switch (RGBfmt) {
! 196: case RGBFB_CLUT:
! 197: return 1;
! 198:
! 199: case RGBFB_A8R8G8B8:
! 200: case RGBFB_A8B8G8R8:
! 201: case RGBFB_R8G8B8A8:
! 202: case RGBFB_B8G8R8A8:
! 203: return 4;
! 204:
! 205: case RGBFB_B8G8R8:
! 206: case RGBFB_R8G8B8:
! 207: return 3;
! 208:
! 209: case RGBFB_R5G5B5:
! 210: case RGBFB_R5G6B5:
! 211: case RGBFB_R5G6B5PC:
! 212: case RGBFB_R5G5B5PC:
! 213: case RGBFB_B5G6R5PC:
! 214: case RGBFB_B5G5R5PC:
! 215: return 2;
! 216: default:
! 217: write_log ("ERROR - GetBytesPerPixel() was unsuccessful with 0x%x?!\n", RGBfmt);
! 218: return 0;
! 219: }
1.1 root 220: }
221:
222: /*
223: * Amiga <-> native structure conversion functions
224: */
225:
226: static int CopyRenderInfoStructureA2U (uaecptr amigamemptr, struct RenderInfo *ri)
227: {
228: uaecptr memp = get_long (amigamemptr + PSSO_RenderInfo_Memory);
229:
230: if (valid_address (memp, 1 /* FIXME */)) {
231: ri->Memory = get_real_address (memp);
232: ri->BytesPerRow = get_word (amigamemptr + PSSO_RenderInfo_BytesPerRow);
233: ri->RGBFormat = get_long (amigamemptr + PSSO_RenderInfo_RGBFormat);
234: return 1;
235: }
1.1.1.2 ! root 236: write_log ("ERROR - Invalid RenderInfo memory area...\n");
1.1 root 237: return 0;
238: }
239:
240: static int CopyPatternStructureA2U (uaecptr amigamemptr, struct Pattern *pattern)
241: {
242: uaecptr memp = get_long (amigamemptr + PSSO_Pattern_Memory);
243: if (valid_address (memp, 1 /* FIXME */)) {
244: pattern->Memory = get_real_address (memp);
245: pattern->XOffset = get_word (amigamemptr + PSSO_Pattern_XOffset);
246: pattern->YOffset = get_word (amigamemptr + PSSO_Pattern_YOffset);
247: pattern->FgPen = get_long (amigamemptr + PSSO_Pattern_FgPen);
248: pattern->BgPen = get_long (amigamemptr + PSSO_Pattern_BgPen);
249: pattern->Size = get_byte (amigamemptr + PSSO_Pattern_Size);
250: pattern->DrawMode = get_byte (amigamemptr + PSSO_Pattern_DrawMode);
251: return 1;
252: }
1.1.1.2 ! root 253: write_log ("ERROR - Invalid Pattern memory area...\n");
1.1 root 254: return 0;
255: }
256:
257: static void CopyColorIndexMappingA2U (uaecptr amigamemptr, struct ColorIndexMapping *cim)
258: {
259: int i;
260: cim->ColorMask = get_long (amigamemptr);
261: for (i = 0; i < 256; i++, amigamemptr += 4)
262: cim->Colors[i] = get_long (amigamemptr + 4);
263: }
264:
265: static int CopyBitMapStructureA2U (uaecptr amigamemptr, struct BitMap *bm)
266: {
267: int i;
268:
269: bm->BytesPerRow = get_word (amigamemptr + PSSO_BitMap_BytesPerRow);
270: bm->Rows = get_word (amigamemptr + PSSO_BitMap_Rows);
271: bm->Flags = get_byte (amigamemptr + PSSO_BitMap_Flags);
272: bm->Depth = get_byte (amigamemptr + PSSO_BitMap_Depth);
273:
274: for (i = 0; i < bm->Depth; i++) {
275: uaecptr plane = get_long (amigamemptr + PSSO_BitMap_Planes + i*4);
276: switch (plane) {
277: case 0:
278: bm->Planes[i] = &all_zeros_bitmap;
279: break;
280: case 0xFFFFFFFF:
281: bm->Planes[i] = &all_ones_bitmap;
282: break;
283: default:
284: if (valid_address (plane, bm->BytesPerRow * bm->Rows))
285: bm->Planes[i] = get_real_address (plane);
286: else
287: return 0;
288: break;
289: }
290: }
291: return 1;
292: }
293:
294: static int CopyTemplateStructureA2U (uaecptr amigamemptr, struct Template *tmpl)
295: {
296: uaecptr memp = get_long (amigamemptr + PSSO_Template_Memory);
297:
298: if (valid_address (memp, 1 /* FIXME */)) {
299: tmpl->Memory = get_real_address (memp);
300: tmpl->BytesPerRow = get_word (amigamemptr + PSSO_Template_BytesPerRow);
301: tmpl->XOffset = get_byte (amigamemptr + PSSO_Template_XOffset);
302: tmpl->DrawMode = get_byte (amigamemptr + PSSO_Template_DrawMode);
303: tmpl->FgPen = get_long (amigamemptr + PSSO_Template_FgPen);
304: tmpl->BgPen = get_long (amigamemptr + PSSO_Template_BgPen);
305: return 1;
306: }
1.1.1.2 ! root 307: write_log ("ERROR - Invalid Template memory area...\n");
1.1 root 308: return 0;
309: }
310:
311: static void CopyLibResolutionStructureU2A (struct LibResolution *libres, uaecptr amigamemptr)
312: {
313: char *uaememptr = 0;
314: int i;
315:
316: uaememptr = gfxmem_xlate(amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
317: memset(uaememptr, 0, PSSO_LibResolution_sizeof); /* zero out our LibResolution structure */
318: strcpy(uaememptr + PSSO_LibResolution_P96ID, libres->P96ID);
1.1.1.2 ! root 319: put_long (amigamemptr + PSSO_LibResolution_DisplayID, libres->DisplayID);
! 320: put_word (amigamemptr + PSSO_LibResolution_Width, libres->Width);
! 321: put_word (amigamemptr + PSSO_LibResolution_Height, libres->Height);
! 322: put_word (amigamemptr + PSSO_LibResolution_Flags, libres->Flags);
1.1 root 323: for (i = 0; i < MAXMODES; i++)
1.1.1.2 ! root 324: put_long (amigamemptr + PSSO_LibResolution_Modes + i*4, libres->Modes[i]);
1.1 root 325: #if 0
1.1.1.2 ! root 326: put_long (amigamemptr, libres->Node.ln_Succ);
! 327: put_long (amigamemptr + 4, libres->Node.ln_Pred);
! 328: put_byte (amigamemptr + 8, libres->Node.ln_Type);
! 329: put_byte (amigamemptr + 9, libres->Node.ln_Pri);
1.1 root 330: #endif
1.1.1.2 ! root 331: put_long (amigamemptr + 10, amigamemptr + PSSO_LibResolution_P96ID);
! 332: put_long (amigamemptr + PSSO_LibResolution_BoardInfo, libres->BoardInfo);
1.1 root 333: }
334:
335: /* list is Amiga address of list, in correct endian format for UAE
336: * node is Amiga address of node, in correct endian format for UAE */
337: static void AmigaListAddTail (uaecptr list, uaecptr node)
338: {
339: uaecptr amigamemptr = 0;
340:
341: if (get_long (list + 8) == list) {
342: /* Empty list - set it up */
1.1.1.2 ! root 343: put_long (list, node); /* point the lh_Head to our new node */
! 344: put_long (list + 4, 0); /* set the lh_Tail to NULL */
! 345: put_long (list + 8, node); /* point the lh_TailPred to our new node */
1.1 root 346:
347: /* Adjust the new node - don't rely on it being zeroed out */
1.1.1.2 ! root 348: put_long (node, 0); /* ln_Succ */
! 349: put_long (node + 4, 0); /* ln_Pred */
1.1 root 350: } else {
351: amigamemptr = get_long (list + 8); /* get the lh_TailPred contents */
352:
1.1.1.2 ! root 353: put_long (list + 8, node); /* point the lh_TailPred to our new node */
1.1 root 354:
355: /* Adjust the previous lh_TailPred node */
1.1.1.2 ! root 356: put_long (amigamemptr, node); /* point the ln_Succ to our new node */
1.1 root 357:
358: /* Adjust the new node - don't rely on it being zeroed out */
1.1.1.2 ! root 359: put_long (node, 0); /* ln_Succ */
! 360: put_long (node + 4, amigamemptr); /* ln_Pred */
1.1 root 361: }
362: }
363:
364: /*
365: * Functions to perform an action on the real screen
366: */
367:
368: /*
369: * Fill a rectangle on the screen. src points to the start of a line of the
370: * filled rectangle in the frame buffer; it can be used as a memcpy source if
371: * there is no OS specific function to fill the rectangle.
372: */
373:
374: static void do_fillrect (uae_u8 *src, int x, int y, int width, int height)
375: {
376: uae_u8 *dst;
377: /* Try OS specific fillrect function here; and return if successful. */
378:
379: DX_Invalidate (y, y + height - 1);
380: if (! picasso_vidinfo.extra_mem)
381: return;
382:
383: width *= picasso96_state.BytesPerPixel;
1.1.1.2 ! root 384: dst = gfx_lock_picasso ();
1.1 root 385: if (!dst)
1.1.1.2 ! root 386: goto out;
1.1 root 387:
1.1.1.2 ! root 388: dst += y*picasso_vidinfo.rowbytes + x*picasso_vidinfo.pixbytes;
! 389: if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
! 390: while (height-- > 0) {
! 391: memcpy (dst, src, width);
! 392: dst += picasso_vidinfo.rowbytes;
! 393: }
! 394: } else {
! 395: int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
! 396: if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
! 397: abort ();
! 398:
! 399: while (height-- > 0) {
! 400: int i;
! 401: switch (psiz) {
! 402: case 2:
! 403: for (i = 0; i < width; i++)
! 404: *((uae_u16 *)dst + i) = picasso_vidinfo.clut[src[i]];
! 405: break;
! 406: case 4:
! 407: for (i = 0; i < width; i++)
! 408: *((uae_u32 *)dst + i) = picasso_vidinfo.clut[src[i]];
! 409: break;
! 410: default:
! 411: abort ();
! 412: }
! 413: dst += picasso_vidinfo.rowbytes;
! 414: }
1.1 root 415: }
1.1.1.2 ! root 416: out:
! 417: gfx_unlock_picasso ();
1.1 root 418: }
419:
420: /*
421: * This routine modifies the real screen buffer after a blit has been
422: * performed in the save area. If can_do_blit is nonzero, the blit can
423: * be performed within the real screen buffer; otherwise, this routine
424: * must do it by hand using the data in the save area, pointed to by
425: * srcp.
426: */
427:
428: static void do_blit (uae_u8 *srcp, unsigned long src_rowbytes,
429: int srcx, int srcy, int dstx, int dsty,
430: int width, int height, int can_do_blit)
431: {
432: uae_u8 *dstp;
433: /* If this RenderInfo points at something else than the currently visible
434: * screen, we must ignore the blit. */
435: if (can_do_blit) {
436: /*
437: * Call OS blitting function that can do it in video memory.
438: * Should return if it was successful
439: */
440: }
441:
442: DX_Invalidate (dsty, dsty + height - 1);
443: if (! picasso_vidinfo.extra_mem)
444: return;
445:
1.1.1.2 ! root 446: dstp = gfx_lock_picasso ();
1.1 root 447: if (dstp == 0)
1.1.1.2 ! root 448: goto out;
1.1 root 449:
450: /* The areas can't overlap: the source is always in the Picasso frame buffer,
451: * and the destination is a different buffer owned by the graphics code. */
452:
1.1.1.2 ! root 453: dstp += dsty * picasso_vidinfo.rowbytes + dstx * picasso_vidinfo.pixbytes;
! 454: if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
! 455: width *= picasso96_state.BytesPerPixel;
! 456: while (height-- > 0) {
! 457: memcpy (dstp, srcp, width);
! 458: srcp += src_rowbytes;
! 459: dstp += picasso_vidinfo.rowbytes;
! 460: }
! 461: } else {
! 462: int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
! 463: if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
! 464: abort ();
! 465:
! 466: while (height-- > 0) {
! 467: int i;
! 468: switch (psiz) {
! 469: case 2:
! 470: for (i = 0; i < width; i++)
! 471: *((uae_u16 *)dstp + i) = picasso_vidinfo.clut[srcp[i]];
! 472: break;
! 473: case 4:
! 474: for (i = 0; i < width; i++)
! 475: *((uae_u32 *)dstp + i) = picasso_vidinfo.clut[srcp[i]];
! 476: break;
! 477: default:
! 478: abort ();
! 479: }
! 480: srcp += src_rowbytes;
! 481: dstp += picasso_vidinfo.rowbytes;
! 482: }
1.1 root 483: }
1.1.1.2 ! root 484: out:
! 485: gfx_unlock_picasso ();
1.1 root 486: }
487:
488: /*
489: * Invert a rectangle on the screen. src and src_rowbytes describe the
490: * inverted rectangle in the frame buffer, so that do_blit can be used if
491: * there is no OS specific function to fill the rectangle.
492: */
493:
494: static void do_invertrect (uae_u8 *src, unsigned long src_rowbytes,
495: int x, int y, int width, int height)
496: {
1.1.1.2 ! root 497: /* TODO: Try OS specific invertrect function here; and return if successful. */
1.1 root 498:
499: do_blit (src, src_rowbytes, 0, 0, x, y, width, height, 0);
500: }
501:
502: static uaecptr wgfx_linestart;
503: static uaecptr wgfx_lineend;
504: static uaecptr wgfx_min, wgfx_max;
505: static unsigned long wgfx_y;
506:
507: static void wgfx_do_flushline (void)
508: {
509: uae_u8 *src, *dstp;
510:
511: DX_Invalidate (wgfx_y, wgfx_y);
512: if (! picasso_vidinfo.extra_mem)
513: goto out;
514:
1.1.1.2 ! root 515: dstp = gfx_lock_picasso ();
1.1 root 516: if (dstp == 0)
517: goto out;
518: /*printf("flushing %d (%x %x %x)\n", wgfx_y, wgfx_linestart, wgfx_min, wgfx_max); */
1.1.1.2 ! root 519: src = gfxmemory + wgfx_min;
1.1 root 520:
1.1.1.2 ! root 521: if (picasso_vidinfo.rgbformat == picasso96_state.RGBFormat) {
! 522: dstp += wgfx_y * picasso_vidinfo.rowbytes + wgfx_min - wgfx_linestart;
! 523: memcpy (dstp, src, wgfx_max - wgfx_min);
! 524: } else {
! 525: int width = wgfx_max - wgfx_min;
! 526: int i;
! 527: int psiz = GetBytesPerPixel (picasso_vidinfo.rgbformat);
! 528:
! 529: if (picasso96_state.RGBFormat != RGBFB_CHUNKY)
! 530: abort ();
! 531:
! 532: dstp += wgfx_y * picasso_vidinfo.rowbytes + (wgfx_min - wgfx_linestart) * psiz;
! 533: switch (psiz) {
! 534: case 2:
! 535: for (i = 0; i < width; i++)
! 536: *((uae_u16 *)dstp + i) = picasso_vidinfo.clut[src[i]];
! 537: break;
! 538: case 4:
! 539: for (i = 0; i < width; i++)
! 540: *((uae_u32 *)dstp + i) = picasso_vidinfo.clut[src[i]];
! 541: break;
! 542: default:
! 543: abort ();
! 544: }
! 545: }
1.1 root 546:
547: out:
1.1.1.2 ! root 548: gfx_unlock_picasso ();
1.1 root 549: wgfx_linestart = 0xFFFFFFFF;
550: }
551:
552: static __inline__ void wgfx_flushline (void)
553: {
1.1.1.2 ! root 554: if (wgfx_linestart == 0xFFFFFFFF || ! picasso_on)
1.1 root 555: return;
556: wgfx_do_flushline ();
557: }
558:
559: static int renderinfo_is_current_screen (struct RenderInfo *ri)
560: {
561: if (! picasso_on)
562: return 0;
563: if (ri->Memory != gfxmemory + (picasso96_state.Address - gfxmem_start)) {
564: return 0;
565: }
566: return 1;
567: }
568:
569: /* Clear our screen, since we've got a new Picasso screen-mode, and refresh with the proper contents
1.1.1.2 ! root 570: * This is called on several occasions:
! 571: * 1. Amiga-->Picasso transition, via SetSwitch()
! 572: * 2. Picasso-->Picasso transition, via SetPanning().
! 573: * 3. whenever the graphics code notifies us that the screen contents have been lost.
! 574: */
! 575: void picasso_refresh (void)
1.1 root 576: {
577: struct RenderInfo ri;
578:
579: if (! picasso_on)
580: return;
581:
582: /* Make sure that the first time we show a Picasso video mode, we don't blit any crap.
583: * We can do this by checking if we have an Address yet. */
584: if (picasso96_state.Address) {
585: /* blit the stuff from our static frame-buffer to the gfx-card */
586: uae_u8 *ptr = gfxmemory + (picasso96_state.Address - gfxmem_start);
587: ri.BytesPerRow = picasso96_state.BytesPerRow;
588: ri.RGBFormat = picasso96_state.RGBFormat;
589: do_blit (ptr, picasso96_state.BytesPerRow, 0, 0, 0, 0,
590: picasso96_state.Width, picasso96_state.Height, 0);
1.1.1.2 ! root 591: write_log ("picasso_refresh() successful.\n");
1.1 root 592: } else
1.1.1.2 ! root 593: write_log ("ERROR - picasso_refresh() can't refresh!\n");
1.1 root 594: }
595:
596: /*
597: * BOOL FindCard(struct BoardInfo *bi); and
598: *
599: * FindCard is called in the first stage of the board initialisation and
600: * configuration and is used to look if there is a free and unconfigured
601: * board of the type the driver is capable of managing. If it finds one,
602: * it immediately reserves it for use by Picasso96, usually by clearing
603: * the CDB_CONFIGME bit in the flags field of the ConfigDev struct of
604: * this expansion card. But this is only a common example, a driver can
605: * do whatever it wants to mark this card as used by the driver. This
606: * mechanism is intended to ensure that a board is only configured and
607: * used by one driver. FindBoard also usually fills some fields of the
608: * BoardInfo struct supplied by the caller, the rtg.library, for example
609: * the MemoryBase, MemorySize and RegisterBase fields.
610: */
611: uae_u32 picasso_FindCard (void)
612: {
1.1.1.2 ! root 613: uaecptr AmigaBoardInfo = m68k_areg (regs, 0);
1.1 root 614: /* NOTES: See BoardInfo struct definition in Picasso96 dev info */
615:
1.1.1.2 ! root 616: if (allocated_gfxmem && !picasso96_state.CardFound) {
1.1 root 617: /* Fill in MemoryBase, MemorySize */
1.1.1.2 ! root 618: put_long (AmigaBoardInfo + PSSO_BoardInfo_MemoryBase, gfxmem_start);
1.1 root 619: /* size of memory, minus a 32K chunk: 16K for pattern bitmaps, 16K for resolution list */
1.1.1.2 ! root 620: put_long (AmigaBoardInfo + PSSO_BoardInfo_MemorySize, allocated_gfxmem - 32768);
1.1 root 621:
622: picasso96_state.CardFound = 1; /* mark our "card" as being found */
623: return -1;
624: } else
625: return 0;
626: }
627:
628: static void FillBoardInfo (uaecptr amigamemptr, struct LibResolution *res, struct PicassoResolution *dm)
629: {
630: char *uaememptr;
631: switch (dm->depth) {
632: case 1:
633: res->Modes[CHUNKY] = amigamemptr;
634: break;
635: case 2:
636: res->Modes[HICOLOR] = amigamemptr;
637: break;
638: case 3:
639: res->Modes[TRUECOLOR] = amigamemptr;
640: break;
641: default:
642: res->Modes[TRUEALPHA] = amigamemptr;
643: break;
644: }
645: uaememptr = gfxmem_xlate(amigamemptr); /* I know that amigamemptr is inside my gfxmem chunk, so I can just do the xlate() */
646: memset(uaememptr, 0, PSSO_ModeInfo_sizeof); /* zero out our ModeInfo struct */
647:
1.1.1.2 ! root 648: put_word (amigamemptr + PSSO_ModeInfo_Width, dm->res.width);
! 649: put_word (amigamemptr + PSSO_ModeInfo_Height, dm->res.height);
! 650: put_byte (amigamemptr + PSSO_ModeInfo_Depth, dm->depth * 8);
! 651: put_byte (amigamemptr + PSSO_ModeInfo_Flags, 0);
! 652: put_word (amigamemptr + PSSO_ModeInfo_HorTotal, dm->res.width);
! 653: put_word (amigamemptr + PSSO_ModeInfo_HorBlankSize, 0);
! 654: put_word (amigamemptr + PSSO_ModeInfo_HorSyncStart, 0);
! 655: put_word (amigamemptr + PSSO_ModeInfo_HorSyncSize, 0);
! 656: put_byte (amigamemptr + PSSO_ModeInfo_HorSyncSkew, 0);
! 657: put_byte (amigamemptr + PSSO_ModeInfo_HorEnableSkew, 0);
! 658:
! 659: put_word (amigamemptr + PSSO_ModeInfo_VerTotal, dm->res.height);
! 660: put_word (amigamemptr + PSSO_ModeInfo_VerBlankSize, 0);
! 661: put_word (amigamemptr + PSSO_ModeInfo_VerSyncStart, 0);
! 662: put_word (amigamemptr + PSSO_ModeInfo_VerSyncSize, 0);
1.1 root 663:
1.1.1.2 ! root 664: put_byte (amigamemptr + PSSO_ModeInfo_first_union, 98);
! 665: put_byte (amigamemptr + PSSO_ModeInfo_second_union, 14);
1.1 root 666:
1.1.1.2 ! root 667: put_long (amigamemptr + PSSO_ModeInfo_PixelClock, dm->res.width * dm->res.height * dm->refresh);
1.1 root 668: }
669:
670: /****************************************
671: * InitCard()
672: *
673: * a2: BoardInfo structure ptr - Amiga-based address in Intel endian-format
674: *
675: * Job - fill in the following structure members:
676: * gbi_RGBFormats: the pixel formats that the host-OS of UAE supports
677: * If UAE is running in a window, it should ONLY report the pixel format of the host-OS desktop
678: * If UAE is running full-screen, it should report ALL pixel formats that the host-OS can handle in full-screen
679: * NOTE: If full-screen, and the user toggles to windowed-mode, all hell will break loose visually. Must inform
680: * user that they're doing something stupid (unless their desktop and full-screen colour modes match).
681: * gbi_SoftSpriteFlags: should be the same as above for now, until actual cursor support is added
682: * gbi_BitsPerCannon: could be 6 or 8 or ???, depending on the host-OS gfx-card
683: * gbi_MaxHorResolution: fill this in for all modes (even if you don't support them)
684: * gbi_MaxVerResolution: fill this in for all modes (even if you don't support them)
685: */
686: uae_u32 picasso_InitCard (void)
687: {
688: struct LibResolution res;
689: int i;
690: int ModeInfoStructureCount = 1, LibResolutionStructureCount = 0;
691: uaecptr amigamemptr = 0;
1.1.1.2 ! root 692: uaecptr AmigaBoardInfo = m68k_areg (regs, 2);
! 693: put_word (AmigaBoardInfo + PSSO_BoardInfo_BitsPerCannon, DX_BitsPerCannon());
! 694: put_word (AmigaBoardInfo + PSSO_BoardInfo_RGBFormats, picasso96_pixel_format);
! 695: put_word (AmigaBoardInfo + PSSO_BoardInfo_SoftSpriteFlags, picasso96_pixel_format);
! 696: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 0, planar.width);
! 697: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 2, chunky.width);
! 698: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 4, hicolour.width);
! 699: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 6, truecolour.width);
! 700: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxHorResolution + 8, alphacolour.width);
! 701: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 0, planar.height);
! 702: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 2, chunky.height);
! 703: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 4, hicolour.height);
! 704: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 6, truecolour.height);
! 705: put_word (AmigaBoardInfo + PSSO_BoardInfo_MaxVerResolution + 8, alphacolour.height);
1.1 root 706:
707: for (i = 0; i < mode_count;) {
708: int j = i;
709: /* Add a LibResolution structure to the ResolutionsList MinList in our BoardInfo */
710: res.DisplayID = 0x50001000 + LibResolutionStructureCount * 0x10000;
711: res.BoardInfo = AmigaBoardInfo;
712: res.Width = DisplayModes[i].res.width;
713: res.Height = DisplayModes[i].res.height;
714: res.Flags = P96F_PUBLIC;
715: res.P96ID[0] = 'P';
716: res.P96ID[1] = '9';
717: res.P96ID[2] = '6';
718: res.P96ID[3] = '-';
719: res.P96ID[4] = '0';
720: res.P96ID[5] = ':';
721: strcpy (res.Name, "uaegfx:");
722: strncat (res.Name, DisplayModes[i].name, strchr(DisplayModes[i].name, ',') - DisplayModes[i].name);
723: res.Modes[PLANAR] = 0;
724: res.Modes[CHUNKY] = 0;
725: res.Modes[HICOLOR] = 0;
726: res.Modes[TRUECOLOR] = 0;
727: res.Modes[TRUEALPHA] = 0;
728:
729: do {
730: /* Handle this display mode's depth */
1.1.1.2 ! root 731: amigamemptr = gfxmem_start + allocated_gfxmem - (PSSO_ModeInfo_sizeof * ModeInfoStructureCount++);
1.1 root 732: FillBoardInfo(amigamemptr, &res, &DisplayModes[i]);
733: i++;
734: } while (i < mode_count
735: && DisplayModes[i].res.width == DisplayModes[j].res.width
736: && DisplayModes[i].res.height == DisplayModes[j].res.height);
737:
1.1.1.2 ! root 738: amigamemptr = gfxmem_start + allocated_gfxmem - 16384 + (PSSO_LibResolution_sizeof * LibResolutionStructureCount++);
1.1 root 739: CopyLibResolutionStructureU2A (&res, amigamemptr);
740: DumpLibResolutionStructure( amigamemptr);
741: AmigaListAddTail (AmigaBoardInfo + PSSO_BoardInfo_ResolutionsList, amigamemptr);
742: }
743:
744: return 0;
745: }
746:
747: extern int x_size, y_size;
748:
749: /*
750: * SetSwitch:
751: * a0: struct BoardInfo
752: * d0.w: BOOL state
753: * this function should set a board switch to let the Amiga signal pass
754: * through when supplied with a 0 in d0 and to show the board signal if
755: * a 1 is passed in d0. You should remember the current state of the
756: * switch to avoid unneeded switching. If your board has no switch, then
757: * simply supply a function that does nothing except a RTS.
758: *
759: * NOTE: Return the opposite of the switch-state. BDK
760: */
761: uae_u32 picasso_SetSwitch (void)
762: {
1.1.1.2 ! root 763: uae_u16 flag = m68k_dreg (regs, 0) & 0xFFFF;
1.1 root 764:
765: /* Do not switch immediately. Tell the custom chip emulation about the
766: * desired state, and wait for custom.c to call picasso_enablescreen
767: * whenever it is ready to change the screen state. */
768: picasso_requested_on = !!flag;
1.1.1.2 ! root 769: write_log ("SetSwitch() - trying to show %s screen\n", flag ? "picasso96":"amiga");
1.1 root 770:
771: /* Put old switch-state in D0 */
772: return !flag;
773: }
774:
775: void picasso_enablescreen (int on)
776: {
777: wgfx_linestart = 0xFFFFFFFF;
778: picasso_refresh ();
1.1.1.2 ! root 779: write_log ("SetSwitch() - showing %s screen\n", on ? "picasso96": "amiga");
1.1 root 780: }
781:
782: /*
783: * SetColorArray:
784: * a0: struct BoardInfo
785: * d0.w: startindex
786: * d1.w: count
787: * when this function is called, your driver has to fetch "count" color
788: * values starting at "startindex" from the CLUT field of the BoardInfo
789: * structure and write them to the hardware. The color values are always
790: * between 0 and 255 for each component regardless of the number of bits
791: * per cannon your board has. So you might have to shift the colors
792: * before writing them to the hardware.
793: */
794: uae_u32 picasso_SetColorArray (void)
795: {
796: /* Fill in some static UAE related structure about this new CLUT setting
797: * We need this for CLUT-based displays, and for mapping CLUT to hi/true colour */
1.1.1.2 ! root 798: uae_u16 start = m68k_dreg (regs, 0);
! 799: uae_u16 count = m68k_dreg (regs, 1);
1.1 root 800: int i;
1.1.1.2 ! root 801: uaecptr boardinfo = m68k_areg (regs, 0);
1.1 root 802: uaecptr clut = boardinfo + PSSO_BoardInfo_CLUT + start * 3;
1.1.1.2 ! root 803: int changed = 0;
1.1 root 804:
805: for (i = start; i < start + count; i++) {
1.1.1.2 ! root 806: int r = get_byte (clut);
! 807: int g = get_byte (clut + 1);
! 808: int b = get_byte (clut + 2);
! 809:
! 810: changed |= (picasso96_state.CLUT[i].Red != r
! 811: || picasso96_state.CLUT[i].Green != g
! 812: || picasso96_state.CLUT[i].Blue != b);
! 813:
! 814: picasso96_state.CLUT[i].Red = r;
! 815: picasso96_state.CLUT[i].Green = g;
! 816: picasso96_state.CLUT[i].Blue = b;
1.1 root 817: clut += 3;
818: }
1.1.1.2 ! root 819: if (changed) {
! 820: DX_SetPalette (start, count);
1.1 root 821: }
1.1.1.2 ! root 822: /*write_log ("SetColorArray(%d,%d)\n", start, count); */
! 823: return m68k_dreg (regs, 0);
1.1 root 824: }
825:
826: /*
827: * SetDAC:
828: * a0: struct BoardInfo
829: * d7: RGBFTYPE RGBFormat
830: * This function is called whenever the RGB format of the display changes,
831: * e.g. from chunky to TrueColor. Usually, all you have to do is to set
832: * the RAMDAC of your board accordingly.
833: */
834: uae_u32 picasso_SetDAC (void)
835: {
836: /* Fill in some static UAE related structure about this new DAC setting
837: * Lets us keep track of what pixel format the Amiga is thinking about in our frame-buffer */
838:
1.1.1.2 ! root 839: write_log ("SetDAC()\n");
! 840: return m68k_dreg (regs, 0);
1.1 root 841: }
842:
843: /*
844: * SetGC:
845: * a0: struct BoardInfo
846: * a1: struct ModeInfo
847: * d0: BOOL Border
848: * This function is called whenever another ModeInfo has to be set. This
849: * function simply sets up the CRTC and TS registers to generate the
850: * timing used for that screen mode. You should not set the DAC, clocks
851: * or linear start adress. They will be set when appropriate by their
852: * own functions.
853: */
854: uae_u32 picasso_SetGC (void)
855: {
856: /* Fill in some static UAE related structure about this new ModeInfo setting */
1.1.1.2 ! root 857: uaecptr modeinfo = m68k_areg (regs, 1);
1.1 root 858:
859: picasso96_state.Width = get_word (modeinfo + PSSO_ModeInfo_Width);
860: picasso96_state.VirtualWidth = picasso96_state.Width; /* in case SetPanning doesn't get called */
861:
862: picasso96_state.Height = get_word (modeinfo + PSSO_ModeInfo_Height);
863: picasso96_state.VirtualHeight = picasso96_state.Height;
864:
865: picasso96_state.GC_Depth = get_byte (modeinfo + PSSO_ModeInfo_Depth);
866: picasso96_state.GC_Flags = get_byte (modeinfo + PSSO_ModeInfo_Flags);
867:
1.1.1.2 ! root 868: write_log ("SetGC(%d,%d,%d)\n", picasso96_state.Width, picasso96_state.Height, picasso96_state.GC_Depth);
1.1 root 869:
870: gfx_set_picasso_modeinfo (picasso96_state.Width, picasso96_state.Height,
1.1.1.2 ! root 871: picasso96_state.GC_Depth, picasso96_state.RGBFormat);
1.1 root 872: wgfx_linestart = 0xFFFFFFFF;
873: picasso_refresh ();
874:
1.1.1.2 ! root 875: return m68k_dreg (regs, 0);
1.1 root 876: }
877:
878: /*
879: * SetPanning:
880: * a0: struct BoardInfo
881: * a1: UBYTE *Memory
882: * d0: uae_u16 Width
883: * d1: WORD XOffset
884: * d2: WORD YOffset
885: * d7: RGBFTYPE RGBFormat
886: * This function sets the view origin of a display which might also be
887: * overscanned. In register a1 you get the start address of the screen
888: * bitmap on the Amiga side. You will have to subtract the starting
889: * address of the board memory from that value to get the memory start
890: * offset within the board. Then you get the offset in pixels of the
891: * left upper edge of the visible part of an overscanned display. From
892: * these values you will have to calculate the LinearStartingAddress
893: * fields of the CRTC registers.
894:
895: * NOTE: SetPanning() can be used to know when a Picasso96 screen is
896: * being opened. Better to do the appropriate clearing of the
897: * background here than in SetSwitch() derived functions,
898: * because SetSwitch() is not called for subsequent Picasso screens.
899: */
900: uae_u32 picasso_SetPanning (void)
901: {
1.1.1.2 ! root 902: uae_u16 Width = m68k_dreg (regs, 0);
! 903: uaecptr start_of_screen = m68k_areg (regs, 1);
1.1 root 904:
905: picasso96_state.Address = start_of_screen; /* Amiga-side address */
1.1.1.2 ! root 906: picasso96_state.XOffset = (uae_s16)m68k_dreg (regs, 1);
! 907: picasso96_state.YOffset = (uae_s16)m68k_dreg (regs, 2);
1.1 root 908: picasso96_state.VirtualWidth = Width;
1.1.1.2 ! root 909: picasso96_state.RGBFormat = m68k_dreg (regs, 7);
! 910: picasso96_state.BytesPerPixel = GetBytesPerPixel (picasso96_state.RGBFormat);
1.1 root 911: picasso96_state.BytesPerRow = Width * picasso96_state.BytesPerPixel;
912:
913: /* I assume SetGC() has been called, so I can calculate the Extent */
914: picasso96_state.Extent = picasso96_state.Address + (picasso96_state.BytesPerRow * picasso96_state.Height);
915:
1.1.1.2 ! root 916: write_log ("SetPanning(%d, %d, %d) Start 0x%x, BPR %d\n",
! 917: Width, picasso96_state.XOffset, picasso96_state.YOffset,
1.1 root 918: start_of_screen, picasso96_state.BytesPerRow);
1.1.1.2 ! root 919: gfx_set_picasso_modeinfo (picasso96_state.Width, picasso96_state.Height,
! 920: picasso96_state.GC_Depth, picasso96_state.RGBFormat);
! 921: DX_SetPalette (0, 256);
1.1 root 922:
923: wgfx_linestart = 0xFFFFFFFF;
924: picasso_refresh ();
925:
1.1.1.2 ! root 926: return m68k_dreg (regs, 0);
1.1 root 927: }
928:
929: static void do_xor8 (uae_u8 *ptr, long len, uae_u32 val)
930: {
931: int i;
932: #if 0 && defined ALIGN_POINTER_TO32
933: int align_adjust = ALIGN_POINTER_TO32(ptr);
934: int len2;
935:
936: len -= align_adjust;
937: while (align_adjust) {
938: *ptr ^= val;
939: ptr++;
940: align_adjust--;
941: }
942: len2 = len >> 2;
943: len -= len2 << 2;
944: for (i = 0; i < len2; i++, ptr += 4) {
945: *(uae_u32 *)ptr ^= val;
946: }
947: while (len) {
948: *ptr ^= val;
949: ptr++;
950: len--;
951: }
952: return;
953: #endif
954: for (i = 0; i < len; i++, ptr++) {
955: do_put_mem_byte (ptr, do_get_mem_byte (ptr) ^ val);
956: }
957: }
958:
959: /*
960: * InvertRect:
961: *
962: * Inputs:
963: * a0:struct BoardInfo *bi
964: * a1:struct RenderInfo *ri
965: * d0.w:X
966: * d1.w:Y
967: * d2.w:Width
968: * d3.w:Height
969: * d4.l:Mask
970: * d7.l:RGBFormat
971: *
972: * This function is used to invert a rectangular area on the board. It is called by BltBitMap,
973: * BltPattern and BltTemplate.
974: */
975: uae_u32 picasso_InvertRect (void)
976: {
1.1.1.2 ! root 977: uaecptr renderinfo = m68k_areg (regs, 1);
! 978: long X = (uae_u16)m68k_dreg (regs, 0);
! 979: long Y = (uae_u16)m68k_dreg (regs, 1);
! 980: long Width = (uae_u16)m68k_dreg (regs, 2);
! 981: long Height = (uae_u16)m68k_dreg (regs, 3);
! 982: uae_u32 mask = m68k_dreg (regs, 4);
! 983: int Bpp = GetBytesPerPixel (m68k_dreg (regs, 7));
1.1 root 984: uae_u32 xorval;
985: int lines;
986: struct RenderInfo ri;
987: uae_u8 *uae_mem, *rectstart;
988: long width_in_bytes;
989:
990: wgfx_flushline ();
991:
1.1.1.2 ! root 992: if (! CopyRenderInfoStructureA2U (renderinfo, &ri))
1.1 root 993: return 0;
994:
1.1.1.2 ! root 995: /*write_log ("InvertRect %d %lx\n", Bpp, (long)mask);*/
1.1 root 996:
997: /* ??? Brian? mask used to be 32 bit, but it appears that only 8 bit
998: * values are passed to this function. This code here seems to work
999: * much better... */
1000: if (mask != 0xFF && Bpp > 8) {
1.1.1.2 ! root 1001: write_log ("InvertRect: not obeying mask 0x%x properly with Bpp %d.\n", mask, Bpp);
1.1 root 1002: mask = 0xFF;
1003: }
1004: if ((mask & ~0xFF) != 0) {
1.1.1.2 ! root 1005: write_log ("InvertRect: mask has high bits set!\n");
1.1 root 1006: }
1007: xorval = 0x01010101 * (mask & 0xFF);
1008: width_in_bytes = Bpp * Width;
1009: rectstart = uae_mem = ri.Memory + Y*ri.BytesPerRow + X*Bpp;
1010:
1.1.1.2 ! root 1011: for (lines = 0; lines < Height; lines++, uae_mem += ri.BytesPerRow)
1.1 root 1012: do_xor8 (uae_mem, width_in_bytes, xorval);
1.1.1.2 ! root 1013:
1.1 root 1014: if (renderinfo_is_current_screen (&ri)) {
1015: if (mask == 0xFF)
1016: do_invertrect (rectstart, ri.BytesPerRow, X, Y, Width, Height);
1017: else
1018: do_blit (rectstart, ri.BytesPerRow, 0, 0, X, Y, Width, Height, 0);
1019: }
1020:
1021: return 1; /* 1 if supported, 0 otherwise */
1022: }
1023:
1024: /***********************************************************
1025: FillRect:
1026: ***********************************************************
1027: * a0: struct BoardInfo *
1028: * a1: struct RenderInfo *
1029: * d0: WORD X
1030: * d1: WORD Y
1031: * d2: WORD Width
1032: * d3: WORD Height
1033: * d4: uae_u32 Pen
1034: * d5: UBYTE Mask
1035: * d7: uae_u32 RGBFormat
1036: ***********************************************************/
1037: uae_u32 picasso_FillRect (void)
1038: {
1.1.1.2 ! root 1039: uaecptr renderinfo = m68k_areg (regs, 1);
! 1040: unsigned long X = (uae_u16)m68k_dreg (regs, 0);
! 1041: unsigned long Y = (uae_u16)m68k_dreg (regs, 1);
! 1042: unsigned long Width = (uae_u16)m68k_dreg (regs, 2);
! 1043: unsigned long Height = (uae_u16)m68k_dreg (regs, 3);
! 1044: uae_u32 Pen = m68k_dreg (regs, 4);
! 1045: uae_u8 Mask = (uae_u8)m68k_dreg (regs, 5);
! 1046: uae_u32 RGBFormat = m68k_dreg (regs, 7);
1.1 root 1047:
1048: uae_u8 *src, *dst;
1049: uae_u8 *start, *oldstart;
1050: unsigned long lines, cols;
1051: int Bpp;
1052: struct RenderInfo ri;
1053:
1054: wgfx_flushline ();
1055:
1.1.1.2 ! root 1056: if (! CopyRenderInfoStructureA2U (renderinfo, &ri) || Y == 0xFFFF)
1.1 root 1057: return 0;
1058:
1059: if (ri.RGBFormat != RGBFormat)
1.1.1.2 ! root 1060: write_log ("Weird Stuff!\n");
1.1 root 1061:
1.1.1.2 ! root 1062: Bpp = GetBytesPerPixel (RGBFormat);
1.1 root 1063:
1.1.1.2 ! root 1064: /*write_log ("FillRect(%d, %d, %d, %d) Pen 0x%x BPP %d BPR %d Mask 0x%x\n",
1.1 root 1065: X, Y, Width, Height, Pen, Bpp, ri.BytesPerRow, Mask); */
1066:
1067: if (Mask == 0xFF) {
1068: /* Do our virtual frame-buffer memory. First, we do a single line fill by hand */
1069: oldstart = start = ri.Memory + Y*ri.BytesPerRow + X*Bpp;
1070: switch (Bpp) {
1071: case 1:
1072: memset (start, Pen, Width);
1073: break;
1074: case 2:
1075: for (cols = 0; cols < Width; cols++) {
1076: do_put_mem_word ((uae_u16 *)start, Pen);
1077: start += 2;
1078: }
1079: break;
1080: case 3:
1081: for (cols = 0; cols < Width; cols++) {
1082: do_put_mem_byte (start, Pen & 0x000000FF);
1083: start++;
1084: *(uae_u16 *)(start) = (Pen & 0x00FFFF00) >> 8;
1085: start+=2;
1086: }
1087: break;
1088: case 4:
1089: for (cols = 0; cols < Width; cols++) {
1090: /**start = Pen; */
1091: do_put_mem_long ((uae_u32 *)start, Pen);
1092: start += 4;
1093: }
1094: break;
1095: }
1096: src = oldstart;
1097: dst = src + ri.BytesPerRow;
1098: /* next, we do the remaining line fills via memcpy() */
1099: for (lines = 0; lines < (Height - 1); lines++, dst += ri.BytesPerRow)
1.1.1.2 ! root 1100: memcpy (dst, src, Width * Bpp);
1.1 root 1101:
1.1.1.2 ! root 1102: if (renderinfo_is_current_screen (&ri))
1.1 root 1103: do_fillrect (src, X, Y, Width, Height);
1.1.1.2 ! root 1104:
1.1 root 1105: return 1;
1106: }
1107:
1108: /* We get here only if Mask != 0xFF */
1109: if (Bpp != 1) {
1110: write_log ("Picasso: mask != 0xFF in truecolor mode!\n");
1111: return 0;
1112: }
1113: Pen &= Mask;
1114: Mask = ~Mask;
1115:
1116: oldstart = start = ri.Memory + Y*ri.BytesPerRow + X*Bpp;
1117: for (lines = 0; lines < Height; lines++, start += ri.BytesPerRow) {
1118: uae_u8 *p = start;
1119: for (cols = 0; cols < Width; cols++) {
1120: uae_u32 tmpval = do_get_mem_byte (p) & Mask;
1121: do_put_mem_byte (p, Pen | tmpval);
1122: p++;
1123: }
1124: }
1125: if (renderinfo_is_current_screen (&ri))
1126: do_blit (oldstart, ri.BytesPerRow, 0, 0, X, Y, Width, Height, 0);
1127:
1128: return 1;
1129: }
1130:
1131: /*
1132: * BlitRect() is a generic (any chunky pixel format) rectangle copier
1133: * NOTE: If dstri is NULL, then we're only dealing with one RenderInfo area, and called from picasso_BlitRect()
1134: */
1135: static void BlitRect (struct RenderInfo *ri, struct RenderInfo *dstri,
1136: uae_u16 srcx, uae_u16 srcy, uae_u16 dstx, uae_u16 dsty,
1137: uae_u16 width, uae_u16 height, uae_u8 mask)
1138: {
1139: uae_u8 *src, *dst, *tmp, *tmp2, *tmp3;
1140: int lines;
1141: uae_u8 Bpp = GetBytesPerPixel(ri->RGBFormat);
1142: uae_u8 *blitsrc;
1143: unsigned long total_width = width * Bpp;
1144: unsigned long linewidth = (total_width + 15) & ~15;
1145: int cant_blit = 1;
1146:
1147: /*
1148: * If we have no destination RenderInfo, then we're dealing with a single-buffer action, called
1149: * from picasso_BlitRect(). The code up to the DX_xxxxx() functions deals with the frame-buffer,
1150: * while the DX_ functions actually deal with the visible screen.
1151: *
1152: * If we have a destination RenderInfo, then we've been called from picasso_BlitRectNoMaskComplete()
1153: * and we need to put the results on the screen from the frame-buffer.
1154: */
1155: if (dstri == NULL) {
1156: dstri = ri;
1157: cant_blit = 0;
1158: }
1159:
1160: /* Do our virtual frame-buffer memory first */
1161: src = ri->Memory + srcx*Bpp + srcy*ri->BytesPerRow;
1162: dst = dstri->Memory + dstx*Bpp + dsty*dstri->BytesPerRow;
1163: blitsrc = dst;
1164: if (mask != 0xFF && Bpp > 1)
1.1.1.2 ! root 1165: write_log ("ERROR - not obeying BlitRect() mask 0x%x properly with Bpp %d.\n", mask, Bpp);
1.1 root 1166:
1167: if (mask == 0xFF || Bpp > 1) {
1168: /* handle normal case efficiently */
1169: if (ri->Memory == dstri->Memory && dsty == srcy) {
1170: int i;
1171: for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
1172: memmove (dst, src, total_width);
1173: } else if (dsty < srcy) {
1174: int i;
1175: for (i = 0; i < height; i++, src += ri->BytesPerRow, dst += dstri->BytesPerRow)
1176: memcpy (dst, src, total_width);
1177: } else {
1178: int i;
1179: src += (height-1) * ri->BytesPerRow;
1180: dst += (height-1) * dstri->BytesPerRow;
1181: for (i = 0; i < height; i++, src -= ri->BytesPerRow, dst -= dstri->BytesPerRow)
1182: memcpy (dst, src, total_width);
1183: }
1184: if (renderinfo_is_current_screen (dstri))
1185: do_blit (blitsrc, dstri->BytesPerRow, srcx, srcy, dstx, dsty,
1186: width, height, ! cant_blit);
1187: return;
1188: }
1189:
1190: tmp3 = tmp2 = tmp = xmalloc (linewidth * height); /* allocate enough memory for the src-rect */
1191: if (!tmp)
1192: return;
1193:
1194: /* copy the src-rect into our temporary buffer space */
1195: for (lines = 0; lines < height; lines++, src += ri->BytesPerRow, tmp2 += linewidth) {
1196: memcpy (tmp2, src, total_width);
1197: }
1198:
1199: /* copy the temporary buffer to the destination */
1200: for (lines = 0; lines < height; lines++, dst += dstri->BytesPerRow, tmp += linewidth) {
1201: int cols;
1202: for (cols = 0; cols < width; cols++) {
1203: dst[cols] &= ~mask;
1204: dst[cols] |= tmp[cols] & mask;
1205: }
1206: }
1207: if (renderinfo_is_current_screen (dstri))
1208: do_blit (blitsrc, dstri->BytesPerRow, srcx, srcy, dstx, dsty,
1209: width, height, 0);
1210: /* free the temp-buf */
1211: free (tmp3);
1212:
1213: }
1214:
1215: /***********************************************************
1216: BlitRect:
1217: ***********************************************************
1218: * a0: struct BoardInfo
1219: * a1: struct RenderInfo
1220: * d0: WORD SrcX
1221: * d1: WORD SrcY
1222: * d2: WORD DstX
1223: * d3: WORD DstY
1224: * d4: WORD Width
1225: * d5: WORD Height
1226: * d6: UBYTE Mask
1227: * d7: uae_u32 RGBFormat
1228: ***********************************************************/
1229: uae_u32 picasso_BlitRect (void)
1230: {
1.1.1.2 ! root 1231: uaecptr renderinfo = m68k_areg (regs, 1);
! 1232: uae_u16 srcx = (uae_u16)m68k_dreg (regs, 0);
! 1233: uae_u16 srcy = (uae_u16)m68k_dreg (regs, 1);
! 1234: uae_u16 dstx = (uae_u16)m68k_dreg (regs, 2);
! 1235: uae_u16 dsty = (uae_u16)m68k_dreg (regs, 3);
! 1236: uae_u16 width = (uae_u16)m68k_dreg (regs, 4);
! 1237: uae_u16 height = (uae_u16)m68k_dreg (regs, 5);
! 1238: uae_u8 Mask = (uae_u8)m68k_dreg (regs, 6);
1.1 root 1239:
1240: struct RenderInfo ri;
1241:
1242: wgfx_flushline ();
1243:
1.1.1.2 ! root 1244: if (! CopyRenderInfoStructureA2U (renderinfo, &ri))
1.1 root 1245: return 0;
1246:
1247: BlitRect(&ri, NULL, srcx, srcy, dstx, dsty, width, height, Mask);
1.1.1.2 ! root 1248: /*write_log ("BlitRect(%d, %d, %d, %d, %d, %d, 0x%x)\n", srcx, srcy, dstx, dsty, width, height, Mask); */
1.1 root 1249:
1250: return 1;
1251: }
1252:
1253: /***********************************************************
1254: BlitRectNoMaskComplete:
1255: ***********************************************************
1256: * a0: struct BoardInfo
1257: * a1: struct RenderInfo (src)
1258: * a2: struct RenderInfo (dst)
1259: * d0: WORD SrcX
1260: * d1: WORD SrcY
1261: * d2: WORD DstX
1262: * d3: WORD DstY
1263: * d4: WORD Width
1264: * d5: WORD Height
1265: * d6: UBYTE OpCode
1266: * d7: uae_u32 RGBFormat
1267: * NOTE: MUST return 0 in D0 if we're not handling this operation
1268: * because the RGBFormat or opcode aren't supported.
1269: * OTHERWISE return 1
1270: ***********************************************************/
1271: uae_u32 picasso_BlitRectNoMaskComplete (void)
1272: {
1.1.1.2 ! root 1273: uaecptr srcri = m68k_areg (regs, 1);
! 1274: uaecptr dstri = m68k_areg (regs, 2);
! 1275: uae_u16 srcx = m68k_dreg (regs, 0);
! 1276: uae_u16 srcy = m68k_dreg (regs, 1);
! 1277: uae_u16 dstx = m68k_dreg (regs, 2);
! 1278: uae_u16 dsty = m68k_dreg (regs, 3);
! 1279: uae_u16 width = m68k_dreg (regs, 4);
! 1280: uae_u16 height = m68k_dreg (regs, 5);
! 1281: uae_u8 OpCode = m68k_dreg (regs, 6);
! 1282: uae_u32 RGBFmt = m68k_dreg (regs, 7);
1.1 root 1283: struct RenderInfo src_ri, dst_ri;
1284:
1285: wgfx_flushline ();
1286:
1.1.1.2 ! root 1287: if (! CopyRenderInfoStructureA2U (srcri, &src_ri)
! 1288: || ! CopyRenderInfoStructureA2U (dstri, &dst_ri))
1.1 root 1289: return 0;
1290:
1.1.1.2 ! root 1291: /*write_log ("BlitRectNoMaskComplete() op 0x%2x, Bpp %d, xy(%4d,%4d) --> xy(%4d,%4d), wh(%4d,%4d)\n",
1.1 root 1292: OpCode, Bpp, srcx, srcy, dstx, dsty, width, height); */
1.1.1.2 ! root 1293: /*write_log ("-- src mem 0x%x BPR %d, dst mem 0x%x BPR %d, screen-mem 0x%x - 0x%x\n",
1.1 root 1294: src_ri.Memory, src_ri.BytesPerRow, dst_ri.Memory, dst_ri.BytesPerRow, picasso96_state.Address, picasso96_state.Extent); */
1295:
1296: switch (OpCode) {
1297: case 0x0C:
1.1.1.2 ! root 1298: BlitRect (&src_ri, &dst_ri, srcx, srcy, dstx, dsty, width, height, 0xFF);
1.1 root 1299: return 1;
1300:
1301: default:
1302: /* FOR NOW! */
1303: return 0;
1304: }
1305: }
1306:
1307: /* This utility function is used both by BlitTemplate() and BlitPattern() */
1308: static __inline__ void PixelWrite1(uae_u8 *mem, int bits, uae_u32 fgpen, uae_u32 mask)
1309: {
1310: if (mask != 0xFF)
1311: fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
1312: do_put_mem_byte (mem + bits, fgpen);
1313: }
1314:
1315: static __inline__ void PixelWrite2(uae_u8 *mem, int bits, uae_u32 fgpen)
1316: {
1317: do_put_mem_word (((uae_u16 *)mem) + bits, fgpen);
1318: }
1319:
1320: static __inline__ void PixelWrite3(uae_u8 *mem, int bits, uae_u32 fgpen)
1321: {
1322: do_put_mem_byte (mem + bits*3, fgpen & 0x000000FF);
1323: *(uae_u16 *)(mem + bits*3+1) = (fgpen & 0x00FFFF00) >> 8;
1324: }
1325:
1326: static __inline__ void PixelWrite4(uae_u8 *mem, int bits, uae_u32 fgpen)
1327: {
1328: do_put_mem_long (((uae_u32 *)mem) + bits, fgpen);
1329: }
1330:
1331: static __inline__ void PixelWrite(uae_u8 *mem, int bits, uae_u32 fgpen, uae_u8 Bpp, uae_u32 mask)
1332: {
1333: switch (Bpp) {
1334: case 1:
1335: if (mask != 0xFF)
1336: fgpen = (fgpen & mask) | (do_get_mem_byte (mem + bits) & ~mask);
1337: do_put_mem_byte (mem + bits, fgpen);
1338: break;
1339: case 2:
1340: do_put_mem_word (((uae_u16 *)mem) + bits, fgpen);
1341: break;
1342: case 3:
1343: do_put_mem_byte (mem + bits*3, fgpen & 0x000000FF);
1344: *(uae_u16 *)(mem + bits*3+1) = (fgpen & 0x00FFFF00) >> 8;
1345: break;
1346: case 4:
1347: do_put_mem_long (((uae_u32 *)mem) + bits, fgpen);
1348: break;
1349: }
1350: }
1351:
1352: /*
1353: * BlitPattern:
1354: *
1355: * Synopsis:BlitPattern(bi, ri, pattern, X, Y, Width, Height, Mask, RGBFormat);
1356: * Inputs:
1357: * a0:struct BoardInfo *bi
1358: * a1:struct RenderInfo *ri
1359: * a2:struct Pattern *pattern
1360: * d0.w:X
1361: * d1.w:Y
1362: * d2.w:Width
1363: * d3.w:Height
1364: * d4.w:Mask
1365: * d7.l:RGBFormat
1366: *
1367: * This function is used to paint a pattern on the board memory using the blitter. It is called by
1368: * BltPattern, if a AreaPtrn is used with positive AreaPtSz. The pattern consists of a b/w image
1369: * using a single plane of image data which will be expanded repeatedly to the destination RGBFormat
1370: * using ForeGround and BackGround pens as well as draw modes. The width of the pattern data is
1371: * always 16 pixels (one word) and the height is calculated as 2^Size. The data must be shifted up
1372: * and to the left by XOffset and YOffset pixels at the beginning.
1373: */
1374: uae_u32 picasso_BlitPattern (void)
1375: {
1.1.1.2 ! root 1376: uaecptr rinf = m68k_areg (regs, 1);
! 1377: uaecptr pinf = m68k_areg (regs, 2);
! 1378: long X = (uae_u16)m68k_dreg (regs, 0);
! 1379: long Y = (uae_u16)m68k_dreg (regs, 1);
! 1380: long W = (uae_u16)m68k_dreg (regs, 2);
! 1381: long H = (uae_u16)m68k_dreg (regs, 3);
! 1382: uae_u8 Mask = (uae_u8)m68k_dreg (regs, 4);
! 1383: uae_u32 RGBFmt = m68k_dreg (regs, 7);
1.1 root 1384:
1385: uae_u8 Bpp = GetBytesPerPixel(RGBFmt);
1386: int inversion = 0;
1387: struct RenderInfo ri;
1388: struct Pattern pattern;
1389: uae_u16 rows;
1.1.1.2 ! root 1390: uae_u32 fgpen;
1.1 root 1391: uae_u8 *uae_mem, *frame_buffer_UAM;
1392: int xshift;
1.1.1.2 ! root 1393: unsigned long ysize_mask;
1.1 root 1394:
1395: wgfx_flushline ();
1396:
1.1.1.2 ! root 1397: if (! CopyRenderInfoStructureA2U (rinf, &ri)
! 1398: || ! CopyPatternStructureA2U (pinf, &pattern))
1.1 root 1399: return 0;
1400:
1401: Bpp = GetBytesPerPixel(ri.RGBFormat);
1402: uae_mem = ri.Memory + Y*ri.BytesPerRow + X*Bpp; /* offset with address */
1403:
1404: if (pattern.DrawMode & INVERS)
1405: inversion = 1;
1406:
1407: pattern.DrawMode &= 0x03;
1408: if (Mask != 0xFF) {
1409: if (Bpp > 1)
1.1.1.2 ! root 1410: write_log ("ERROR - not obeying BlitPattern() mask 0x%x properly with Bpp %d.\n", Mask, Bpp);
1.1 root 1411: else if (pattern.DrawMode == COMP) {
1.1.1.2 ! root 1412: write_log ("ERROR - Unsupported Mask value 0x%x with COMP Draw in BlitPattern(), using fallback method.\n", Mask);
1.1 root 1413: return 0;
1414: }
1415: }
1416:
1.1.1.2 ! root 1417: /* write_log ("BlitPattern() xy(%d,%d), wh(%d,%d) draw 0x%x, off(%d,%d), ph %d\n",
! 1418: X, Y, W, H, pattern.DrawMode, pattern.XOffset, pattern.YOffset, 1 << pattern.Size); */
1.1 root 1419: #ifdef _DEBUG
1420: DumpPattern(&pattern);
1421: #endif
1422: ysize_mask = (1 << pattern.Size) - 1;
1423: xshift = pattern.XOffset & 15;
1424:
1425: for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow) {
1426: int prow = (rows + pattern.YOffset) & ysize_mask;
1427: unsigned int d = do_get_mem_word (((uae_u16 *)pattern.Memory) + prow);
1428: uae_u8 *uae_mem2 = uae_mem;
1429: long cols;
1430:
1431: if (xshift != 0)
1432: d = (d << xshift) | (d >> (16 - xshift));
1433:
1434: for (cols = 0; cols < W; cols += 16, uae_mem2 += Bpp << 4) {
1435: long bits;
1436: long max = W - cols;
1437: unsigned int data = d;
1438:
1439: if (max > 16)
1440: max = 16;
1441:
1442: for (bits = 0; bits < max; bits++) {
1443: int bit_set = data & 0x8000;
1444: data <<= 1;
1445: switch (pattern.DrawMode) {
1446: case JAM1:
1447: if (inversion)
1448: bit_set = !bit_set;
1449: if (bit_set)
1.1.1.2 ! root 1450: PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
1.1 root 1451: break;
1452: case JAM2:
1453: if (inversion)
1454: bit_set = !bit_set;
1455: if (bit_set)
1.1.1.2 ! root 1456: PixelWrite (uae_mem2, bits, pattern.FgPen, Bpp, Mask);
1.1 root 1457: else
1.1.1.2 ! root 1458: PixelWrite (uae_mem2, bits, pattern.BgPen, Bpp, Mask);
1.1 root 1459: break;
1460: case COMP:
1461: if (bit_set) {
1462: fgpen = pattern.FgPen;
1463:
1464: switch (Bpp) {
1465: case 1:
1466: {
1467: uae_u8 *addr = uae_mem2 + bits;
1468: do_put_mem_byte (addr, do_get_mem_byte (addr) ^ fgpen);
1469: }
1470: break;
1471: case 2:
1472: {
1473: uae_u16 *addr = ((uae_u16 *)uae_mem2) + bits;
1474: do_put_mem_word (addr, do_get_mem_word (addr) ^ fgpen);
1475: }
1476: break;
1477: case 3:
1478: {
1479: uae_u32 *addr = (uae_u32 *)(uae_mem2 + bits * 3);
1480: do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
1481: }
1482: break;
1483: case 4:
1484: {
1485: uae_u32 *addr = ((uae_u32 *)uae_mem2) + bits;
1486: do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
1487: }
1488: break;
1489: }
1490: }
1491: break;
1492: }
1493: }
1494: }
1495: }
1496:
1497: frame_buffer_UAM = ri.Memory + X*picasso96_state.BytesPerPixel + Y*ri.BytesPerRow;
1498: if (renderinfo_is_current_screen (&ri))
1499: do_blit (frame_buffer_UAM, ri.BytesPerRow, 0, 0, X, Y, W, H, 0);
1500:
1501: return 1;
1502: }
1503:
1504: /*************************************************
1505: BlitTemplate:
1506: **************************************************
1507: * Synopsis: BlitTemplate(bi, ri, template, X, Y, Width, Height, Mask, RGBFormat);
1508: * a0: struct BoardInfo *bi
1509: * a1: struct RenderInfo *ri
1510: * a2: struct Template *template
1511: * d0.w: X
1512: * d1.w: Y
1513: * d2.w: Width
1514: * d3.w: Height
1515: * d4.w: Mask
1516: * d7.l: RGBFormat
1517: *
1518: * This function is used to paint a template on the board memory using the blitter.
1519: * It is called by BltPattern and BltTemplate. The template consists of a b/w image
1520: * using a single plane of image data which will be expanded to the destination RGBFormat
1521: * using ForeGround and BackGround pens as well as draw modes.
1522: ***********************************************************************************/
1523: uae_u32 picasso_BlitTemplate (void)
1524: {
1525: uae_u8 inversion = 0;
1.1.1.2 ! root 1526: uaecptr rinf = m68k_areg (regs, 1);
! 1527: uaecptr tmpl = m68k_areg (regs, 2);
! 1528: uae_u16 X = m68k_dreg (regs, 0);
! 1529: uae_u16 Y = m68k_dreg (regs, 1);
! 1530: uae_u16 W = m68k_dreg (regs, 2);
! 1531: uae_u16 H = m68k_dreg (regs, 3);
! 1532: uae_u16 Mask = m68k_dreg (regs, 4);
1.1 root 1533: struct Template tmp;
1534: struct RenderInfo ri;
1535: long rows;
1536: int bitoffset;
1.1.1.2 ! root 1537: uae_u32 fgpen;
! 1538: uae_u8 *uae_mem, Bpp, *frame_buffer_UAM;
1.1 root 1539: uae_u8 *tmpl_base;
1540:
1541: wgfx_flushline ();
1542:
1.1.1.2 ! root 1543: if (! CopyRenderInfoStructureA2U (rinf, &ri)
! 1544: || ! CopyTemplateStructureA2U (tmpl, &tmp))
1.1 root 1545: return 0;
1546:
1547: Bpp = GetBytesPerPixel(ri.RGBFormat);
1548: uae_mem = ri.Memory + Y*ri.BytesPerRow + X*Bpp; /* offset into address */
1549:
1550: if (tmp.DrawMode & INVERS)
1551: inversion = 1;
1552:
1553: tmp.DrawMode &= 0x03;
1554: if (Mask != 0xFF) {
1555: if (Bpp > 1)
1.1.1.2 ! root 1556: write_log ("ERROR - not obeying BlitTemplate() mask 0x%x properly with Bpp %d.\n", Mask, Bpp);
1.1 root 1557: else if (tmp.DrawMode == COMP) {
1.1.1.2 ! root 1558: write_log ("ERROR - Unsupported Mask value 0x%x with COMP Draw in BlitTemplate(), using fallback method.\n", Mask);
1.1 root 1559: return 0;
1560: }
1561: }
1562:
1.1.1.2 ! root 1563: /*write_log ("BlitTemplate() xy(%d,%d), wh(%d,%d) draw 0x%x fg 0x%x bg 0x%x \n",
1.1 root 1564: X, Y, W, H, tmp.DrawMode, tmp.FgPen, tmp.BgPen); */
1565:
1566: bitoffset = tmp.XOffset % 8;
1567:
1568: #ifdef _DEBUG
1569: DumpTemplate(&tmp, W, H);
1570: #endif
1571:
1572: tmpl_base = tmp.Memory + tmp.XOffset/8;
1573:
1574: for (rows = 0; rows < H; rows++, uae_mem += ri.BytesPerRow, tmpl_base += tmp.BytesPerRow) {
1575: long cols;
1576: uae_u8 *tmpl_mem = tmpl_base;
1577: uae_u8 *uae_mem2 = uae_mem;
1578: unsigned int data = *tmpl_mem;
1579:
1580: for (cols = 0; cols < W; cols += 8, uae_mem2 += Bpp << 3) {
1581: unsigned int byte;
1582: long bits;
1583: long max = W - cols;
1584:
1585: if (max > 8)
1586: max = 8;
1587:
1588: data <<= 8;
1589: data |= *++tmpl_mem;
1590:
1591: byte = data >> (8 - bitoffset);
1592:
1593: for (bits = 0; bits < max; bits++) {
1594: int bit_set = (byte & 0x80);
1595: byte <<= 1;
1596: switch (tmp.DrawMode) {
1597: case JAM1:
1598: if (inversion)
1599: bit_set = !bit_set;
1600: if (bit_set) {
1601: fgpen = tmp.FgPen;
1602: PixelWrite(uae_mem2, bits, fgpen, Bpp, Mask);
1603: }
1604: break;
1605: case JAM2:
1606: if (inversion)
1607: bit_set = !bit_set;
1608: fgpen = tmp.BgPen;
1609: if (bit_set)
1610: fgpen = tmp.FgPen;
1611:
1612: PixelWrite(uae_mem2, bits, fgpen, Bpp, Mask);
1613: break;
1614: case COMP:
1615: if (bit_set) {
1616: fgpen = tmp.FgPen;
1617:
1618: switch (Bpp) {
1619: case 1:
1620: {
1621: uae_u8 *addr = uae_mem2 + bits;
1622: do_put_mem_byte (addr, do_get_mem_byte (addr) ^ fgpen);
1623: }
1624: break;
1625: case 2:
1626: {
1627: uae_u16 *addr = ((uae_u16 *)uae_mem2) + bits;
1628: do_put_mem_word (addr, do_get_mem_word (addr) ^ fgpen);
1629: }
1630: break;
1631: case 3:
1632: {
1633: uae_u32 *addr = (uae_u32 *)(uae_mem2 + bits * 3);
1634: do_put_mem_long (addr, do_get_mem_long (addr) ^ (fgpen & 0x00FFFFFF));
1635: }
1636: break;
1637: case 4:
1638: {
1639: uae_u32 *addr = ((uae_u32 *)uae_mem2) + bits;
1640: do_put_mem_long (addr, do_get_mem_long (addr) ^ fgpen);
1641: }
1642: break;
1643: }
1644: }
1645: break;
1646: }
1647: }
1648: }
1649: }
1650:
1651: frame_buffer_UAM = ri.Memory + X*picasso96_state.BytesPerPixel + Y*ri.BytesPerRow;
1652: if (renderinfo_is_current_screen (&ri))
1653: do_blit (frame_buffer_UAM, ri.BytesPerRow, 0, 0, X, Y, W, H, 0);
1654:
1655: return 1;
1656: }
1657:
1658: /*
1659: * CalculateBytesPerRow:
1660: * a0: struct BoardInfo
1661: * d0: uae_u16 Width
1662: * d7: RGBFTYPE RGBFormat
1663: * This function calculates the amount of bytes needed for a line of
1664: * "Width" pixels in the given RGBFormat.
1665: */
1666: uae_u32 picasso_CalculateBytesPerRow (void)
1667: {
1.1.1.2 ! root 1668: uae_u16 width = m68k_dreg (regs, 0);
! 1669: uae_u32 type = m68k_dreg (regs, 7);
1.1 root 1670:
1671: width = GetBytesPerPixel(type)*width;
1.1.1.2 ! root 1672: /*write_log ("CalculateBytesPerRow() = %d\n",width); */
1.1 root 1673:
1674: return width;
1675: }
1676:
1677: /*
1678: * SetDisplay:
1679: * a0: struct BoardInfo
1680: * d0: BOOL state
1681: * This function enables and disables the video display.
1682: *
1683: * NOTE: return the opposite of the state
1684: */
1685: uae_u32 picasso_SetDisplay (void)
1686: {
1.1.1.2 ! root 1687: uae_u32 state = m68k_dreg (regs, 0);
! 1688: write_log ("SetDisplay(%d)\n", state);
1.1 root 1689: return !state;
1690: }
1691:
1692: /*
1693: * WaitVerticalSync:
1694: * a0: struct BoardInfo
1695: * This function waits for the next horizontal retrace.
1696: */
1697: uae_u32 picasso_WaitVerticalSync (void)
1698: {
1.1.1.2 ! root 1699: /*write_log ("WaitVerticalSync()\n");*/
1.1 root 1700: return 1;
1701: }
1702:
1703: /* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
1704: static void PlanarToChunky(struct RenderInfo *ri, struct BitMap *bm, long srcx, long srcy,
1705: long dstx, long dsty, long width, long height, uae_u8 mask)
1706: {
1.1.1.2 ! root 1707: int j;
1.1 root 1708:
1709: uae_u8 *PLANAR[8], *image = ri->Memory + dstx * GetBytesPerPixel (ri->RGBFormat) + dsty*ri->BytesPerRow;
1710: int Depth = bm->Depth;
1.1.1.2 ! root 1711: uae_u16 rows, bitoffset = srcx & 7;
1.1 root 1712: long eol_offset;
1713:
1714: /* if (mask != 0xFF)
1.1.1.2 ! root 1715: write_log ("P2C - pixel-width = %d, bit-offset = %d\n", width, bitoffset); */
1.1 root 1716:
1717: /* Set up our bm->Planes[] pointers to the right horizontal offset */
1718: for (j = 0; j < Depth; j++) {
1719: uae_u8 *p = bm->Planes[j];
1720: if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
1721: p += srcx/8 + srcy*bm->BytesPerRow;
1722: PLANAR[j] = p;
1723: if ((mask & (1 << j)) == 0)
1724: PLANAR[j] = &all_zeros_bitmap;
1725: }
1726: eol_offset = (long)bm->BytesPerRow - ((width + 7) >> 3);
1727: for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
1728: long cols;
1729:
1730: for (cols = 0; cols < width; cols += 8) {
1731: int k;
1732: uae_u32 a = 0, b = 0;
1733: unsigned int msk = 0xFF;
1734: long tmp = cols + 8 - width;
1735: if (tmp > 0) {
1736: msk <<= tmp;
1737: b = do_get_mem_long ((uae_u32 *)(image + cols + 4));
1738: if (tmp < 4)
1739: b &= 0xFFFFFFFF >> (32 - tmp * 8);
1740: else if (tmp > 4) {
1741: a = do_get_mem_long ((uae_u32 *)(image + cols));
1742: a &= 0xFFFFFFFF >> (64 - tmp * 8);
1743: }
1744: }
1745: for (k = 0; k < Depth; k++) {
1746: unsigned int data;
1747: if (PLANAR[k] == &all_zeros_bitmap)
1748: data = 0;
1749: else if (PLANAR[k] == &all_ones_bitmap)
1750: data = 0xFF;
1751: else {
1752: data = (uae_u8)(do_get_mem_word ((uae_u16 *)PLANAR[k]) >> (8 - bitoffset));
1753: PLANAR[k]++;
1754: }
1755: data &= msk;
1756: a |= p2ctab[data][0] << k;
1757: b |= p2ctab[data][1] << k;
1758: }
1759: do_put_mem_long ((uae_u32 *)(image + cols), a);
1760: do_put_mem_long ((uae_u32 *)(image + cols + 4), b);
1761: }
1762: for (j = 0; j < Depth; j++) {
1763: if (PLANAR[j] != &all_zeros_bitmap && PLANAR[j] != &all_ones_bitmap) {
1764: PLANAR[j] += eol_offset;
1765: }
1766: }
1767: }
1768: }
1769:
1770: /*
1771: * BlitPlanar2Chunky:
1772: * a0: struct BoardInfo *bi
1773: * a1: struct BitMap *bm - source containing planar information and assorted details
1774: * a2: struct RenderInfo *ri - dest area and its details
1775: * d0.w: SrcX
1776: * d1.w: SrcY
1777: * d2.w: DstX
1778: * d3.w: DstY
1779: * d4.w: SizeX
1780: * d5.w: SizeY
1781: * d6.b: MinTerm - uh oh!
1782: * d7.b: Mask - uh oh!
1783: *
1784: * This function is currently used to blit from planar bitmaps within system memory to chunky bitmaps
1785: * on the board. Watch out for plane pointers that are 0x00000000 (represents a plane with all bits "0")
1786: * or 0xffffffff (represents a plane with all bits "1").
1787: */
1788: uae_u32 picasso_BlitPlanar2Chunky (void)
1789: {
1.1.1.2 ! root 1790: uaecptr bm = m68k_areg (regs, 1);
! 1791: uaecptr ri = m68k_areg (regs, 2);
! 1792: uae_u16 srcx = m68k_dreg (regs, 0) & 0xFFFF;
! 1793: uae_u16 srcy = m68k_dreg (regs, 1) & 0xFFFF;
! 1794: uae_u16 dstx = m68k_dreg (regs, 2) & 0xFFFF;
! 1795: uae_u16 dsty = m68k_dreg (regs, 3) & 0xFFFF;
! 1796: uae_u16 width = m68k_dreg (regs, 4) & 0xFFFF;
! 1797: uae_u16 height = m68k_dreg (regs, 5) & 0xFFFF;
! 1798: uae_u8 minterm = m68k_dreg (regs, 6) & 0xFF;
! 1799: uae_u8 mask = m68k_dreg (regs, 7) & 0xFF;
1.1 root 1800: struct RenderInfo local_ri;
1801: struct BitMap local_bm;
1802:
1803: wgfx_flushline ();
1804:
1805: if (minterm != 0x0C) {
1.1.1.2 ! root 1806: write_log ("ERROR - BlitPlanar2Chunky() has minterm 0x%x, which I don't handle. Using fall-back routine.\n",
1.1 root 1807: minterm);
1808: return 0;
1809: }
1.1.1.2 ! root 1810: if (! CopyRenderInfoStructureA2U (ri, &local_ri)
! 1811: || ! CopyBitMapStructureA2U (bm, &local_bm))
1.1 root 1812: return 0;
1813:
1.1.1.2 ! root 1814: /*write_log ("BlitPlanar2Chunky(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
1.1 root 1815: srcx, srcy, dstx, dsty, width, height, minterm, mask, local_bm.Depth);
1.1.1.2 ! root 1816: write_log ("P2C - BitMap has %d BPR, %d rows\n", local_bm.BytesPerRow, local_bm.Rows); */
! 1817: PlanarToChunky (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, mask);
1.1 root 1818: if (renderinfo_is_current_screen (&local_ri))
1819: do_blit (local_ri.Memory + dstx * GetBytesPerPixel (local_ri.RGBFormat) + dsty * local_ri.BytesPerRow,
1820: local_ri.BytesPerRow,
1821: 0, 0, dstx, dsty, width, height, 0);
1822:
1.1.1.2 ! root 1823: return m68k_dreg (regs, 0);
1.1 root 1824: }
1825:
1826: /* NOTE: Watch for those planeptrs of 0x00000000 and 0xFFFFFFFF for all zero / all one bitmaps !!!! */
1827: static void PlanarToDirect(struct RenderInfo *ri, struct BitMap *bm,
1828: long srcx, long srcy, long dstx, long dsty,
1829: long width, long height, uae_u8 mask,
1830: struct ColorIndexMapping *cim)
1831: {
1832: int j;
1833: int bpp = GetBytesPerPixel(ri->RGBFormat);
1834: uae_u8 *PLANAR[8];
1835: uae_u8 *image = ri->Memory + dstx * bpp + dsty * ri->BytesPerRow;
1836: int Depth = bm->Depth;
1837: long rows;
1838: long eol_offset;
1839:
1840: /* Set up our bm->Planes[] pointers to the right horizontal offset */
1841: for (j = 0; j < Depth; j++) {
1842: uae_u8 *p = bm->Planes[j];
1843: if (p != &all_zeros_bitmap && p != &all_ones_bitmap)
1844: p += srcx/8 + srcy*bm->BytesPerRow;
1845: PLANAR[j] = p;
1846: if ((mask & (1 << j)) == 0)
1847: PLANAR[j] = &all_zeros_bitmap;
1848: }
1849:
1850: eol_offset = (long)bm->BytesPerRow - ((width + (srcx & 7)) >> 3);
1851: for (rows = 0; rows < height; rows++, image += ri->BytesPerRow) {
1852: long cols;
1853: uae_u8 *image2 = image;
1854: unsigned int bitoffs = 7 - (srcx & 7);
1855: int i;
1856:
1857: for (cols = 0; cols < width; cols ++) {
1858: int v = 0, k;
1859: for (k = 0; k < Depth; k++) {
1860: if (PLANAR[k] == &all_ones_bitmap)
1861: v |= 1 << k;
1862: else if (PLANAR[k] != &all_zeros_bitmap) {
1863: v |= ((*PLANAR[k] >> bitoffs) & 1) << k;
1864: }
1865: }
1866:
1867: switch (bpp) {
1868: case 2:
1869: do_put_mem_word ((uae_u16 *)image2, cim->Colors[v]);
1870: image2 += 2;
1871: break;
1872: case 3:
1873: do_put_mem_byte (image2++, cim->Colors[v] & 0x000000FF);
1874: do_put_mem_word ((uae_u16 *)image2, (cim->Colors[v] & 0x00FFFF00) >> 8);
1875: image2 += 2;
1876: break;
1877: case 4:
1878: do_put_mem_long ((uae_u32 *)image2, cim->Colors[v]);
1879: image2 += 4;
1880: break;
1881: }
1882: bitoffs--;
1883: bitoffs &= 7;
1884: if (bitoffs == 7) {
1885: int k;
1886: for (k = 0; k < Depth; k++) {
1887: if (PLANAR[k] != &all_zeros_bitmap && PLANAR[k] != &all_ones_bitmap) {
1888: PLANAR[k]++;
1889: }
1890: }
1891: }
1892: }
1893:
1894: for (i = 0; i < Depth; i++) {
1895: if (PLANAR[i] != &all_zeros_bitmap && PLANAR[i] != &all_ones_bitmap) {
1896: PLANAR[i] += eol_offset;
1897: }
1898: }
1899: }
1900: }
1901:
1902: /*
1903: * BlitPlanar2Direct:
1904: *
1905: * Synopsis:
1906: * BlitPlanar2Direct(bi, bm, ri, cim, SrcX, SrcY, DstX, DstY, SizeX, SizeY, MinTerm, Mask);
1907: * Inputs:
1908: * a0:struct BoardInfo *bi
1909: * a1:struct BitMap *bm
1910: * a2:struct RenderInfo *ri
1911: * a3:struct ColorIndexMapping *cmi
1912: * d0.w:SrcX
1913: * d1.w:SrcY
1914: * d2.w:DstX
1915: * d3.w:DstY
1916: * d4.w:SizeX
1917: * d5.w:SizeY
1918: * d6.b:MinTerm
1919: * d7.b:Mask
1920: *
1921: * This function is currently used to blit from planar bitmaps within system memory to direct color
1922: * bitmaps (15, 16, 24 or 32 bit) on the board. Watch out for plane pointers that are 0x00000000 (represents
1923: * a plane with all bits "0") or 0xffffffff (represents a plane with all bits "1"). The ColorIndexMapping is
1924: * used to map the color index of each pixel formed by the bits in the bitmap's planes to a direct color value
1925: * which is written to the destination RenderInfo. The color mask and all colors within the mapping are words,
1926: * triple bytes or longwords respectively similar to the color values used in FillRect(), BlitPattern() or
1927: * BlitTemplate().
1928: */
1929: uae_u32 picasso_BlitPlanar2Direct (void)
1930: {
1.1.1.2 ! root 1931: uaecptr bm = m68k_areg (regs, 1);
! 1932: uaecptr ri = m68k_areg (regs, 2);
! 1933: uaecptr cim = m68k_areg (regs, 3);
! 1934: uae_u16 srcx = m68k_dreg (regs, 0);
! 1935: uae_u16 srcy = m68k_dreg (regs, 1);
! 1936: uae_u16 dstx = m68k_dreg (regs, 2);
! 1937: uae_u16 dsty = m68k_dreg (regs, 3);
! 1938: uae_u16 width = m68k_dreg (regs, 4);
! 1939: uae_u16 height = m68k_dreg (regs, 5);
! 1940: uae_u8 minterm = m68k_dreg (regs, 6);
! 1941: uae_u8 Mask = m68k_dreg (regs, 7);
1.1 root 1942: struct RenderInfo local_ri;
1943: struct BitMap local_bm;
1944: struct ColorIndexMapping local_cim;
1945:
1946: wgfx_flushline ();
1947:
1948: if (minterm != 0x0C) {
1.1.1.2 ! root 1949: write_log ("ERROR - BlitPlanar2Direct() has op-code 0x%x, which I don't handle. Using fall-back routine.\n",
! 1950: minterm);
1.1 root 1951: return 0;
1952: }
1953: if (Mask != 0xFF) {
1.1.1.2 ! root 1954: write_log ("ERROR - Unsupported Mask value 0x%x in BlitPlanar2Direct(), using fallback method.\n", Mask);
1.1 root 1955: return 0;
1956: }
1.1.1.2 ! root 1957: if (! CopyRenderInfoStructureA2U (ri, &local_ri)
! 1958: || ! CopyBitMapStructureA2U (bm, &local_bm))
1.1 root 1959: return 0;
1960:
1961: CopyColorIndexMappingA2U (cim, &local_cim);
1.1.1.2 ! root 1962: /* write_log ("BlitPlanar2Direct(%d, %d, %d, %d, %d, %d) Minterm 0x%x, Mask 0x%x, Depth %d\n",
! 1963: srcx, srcy, dstx, dsty, width, height, minterm, Mask, local_bm.Depth); */
! 1964: PlanarToDirect (&local_ri, &local_bm, srcx, srcy, dstx, dsty, width, height, Mask, &local_cim);
1.1 root 1965: if (renderinfo_is_current_screen (&local_ri))
1966: do_blit (local_ri.Memory + dstx * GetBytesPerPixel (local_ri.RGBFormat) + dsty * local_ri.BytesPerRow,
1967: local_ri.BytesPerRow,
1968: 0, 0, dstx, dsty, width, height, 0);
1969: return 1;
1970: }
1971:
1972: /* @@@ - Work to be done here!
1973: *
1974: * The address is the offset into our Picasso96 frame-buffer (pointed to by gfxmem_start)
1975: * where the value was put.
1976: *
1977: * Porting work: on some machines you may not need these functions, ie. if the memory for the
1978: * Picasso96 frame-buffer is directly viewable or directly blittable. On Win32 with DirectX,
1979: * this is not the case. So I provide some write-through functions (as per Mathias' orders!)
1980: */
1981: static void write_gfx_long (uaecptr addr, uae_u32 value)
1982: {
1983: uaecptr oldaddr = addr;
1984: int x, xbytes, y;
1985: uae_u8 *dst;
1986:
1987: if (!picasso_on)
1988: return;
1989:
1990: /*
1991: * Several writes to successive memory locations are a common access pattern.
1992: * Try to optimize it.
1993: */
1994: if (addr >= wgfx_linestart && addr + 4 <= wgfx_lineend) {
1995: if (addr < wgfx_min)
1996: wgfx_min = addr;
1997: if (addr + 4 > wgfx_max)
1998: wgfx_max = addr + 4;
1999: return;
2000: } else
2001: wgfx_flushline ();
2002:
2003: addr += gfxmem_start;
2004: /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
2005: if (addr < picasso96_state.Address || addr + 4 > picasso96_state.Extent)
2006: return;
2007:
2008: addr -= picasso96_state.Address;
2009: y = addr / picasso96_state.BytesPerRow;
2010:
2011: #if 0
2012: DX_Invalidate (y, y);
2013: if (! picasso_vidinfo.extra_mem)
2014: return;
2015:
2016: xbytes = addr - y * picasso96_state.BytesPerRow;
2017: x = xbytes / picasso96_state.BytesPerPixel;
2018:
2019: if (x < picasso96_state.Width && y < picasso96_state.Height) {
1.1.1.2 ! root 2020: dst = gfx_lock_picasso ();
1.1 root 2021: if (dst) {
2022: do_put_mem_long ((uae_u32 *)(dst + y * picasso_vidinfo.rowbytes + xbytes), value);
1.1.1.2 ! root 2023: gfx_unlock_picasso ();
1.1 root 2024: }
2025: }
2026: #else
2027: if (y >= picasso96_state.Height)
2028: return;
2029: wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
2030: wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
2031: wgfx_y = y;
2032: wgfx_min = oldaddr;
2033: wgfx_max = oldaddr + 4;
2034: #endif
2035: }
2036:
2037: static void write_gfx_word (uaecptr addr, uae_u16 value)
2038: {
2039: uaecptr oldaddr = addr;
2040: int x, xbytes, y;
2041: uae_u8 *dst;
2042:
2043: if (!picasso_on)
2044: return;
2045:
2046: /*
2047: * Several writes to successive memory locations are a common access pattern.
2048: * Try to optimize it.
2049: */
2050: if (addr >= wgfx_linestart && addr + 2 <= wgfx_lineend) {
2051: if (addr < wgfx_min)
2052: wgfx_min = addr;
2053: if (addr + 2 > wgfx_max)
2054: wgfx_max = addr + 2;
2055: return;
2056: } else
2057: wgfx_flushline ();
2058:
2059: addr += gfxmem_start;
2060: /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
2061: if (addr < picasso96_state.Address || addr + 2 > picasso96_state.Extent)
2062: return;
2063:
2064: addr -= picasso96_state.Address;
2065: y = addr / picasso96_state.BytesPerRow;
2066:
2067: #if 0
2068: DX_Invalidate (y, y);
2069: if (! picasso_vidinfo.extra_mem)
2070: return;
2071:
2072: xbytes = addr - y * picasso96_state.BytesPerRow;
2073: x = xbytes / picasso96_state.BytesPerPixel;
2074:
2075: if (x < picasso96_state.Width && y < picasso96_state.Height) {
1.1.1.2 ! root 2076: dst = gfx_lock_picasso ();
1.1 root 2077: if (dst) {
2078: do_put_mem_word ((uae_u16 *)(dst + y * picasso_vidinfo.rowbytes + xbytes), value);
1.1.1.2 ! root 2079: gfx_unlock_picasso ();
1.1 root 2080: }
2081: }
2082: #else
2083: if (y >= picasso96_state.Height)
2084: return;
2085: wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
2086: wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
2087: wgfx_y = y;
2088: wgfx_min = oldaddr;
2089: wgfx_max = oldaddr + 2;
2090: #endif
2091: }
2092:
2093: static void write_gfx_byte (uaecptr addr, uae_u8 value)
2094: {
2095: uaecptr oldaddr = addr;
2096: int x, xbytes, y;
2097: uae_u8 *dst;
2098:
2099: if (!picasso_on)
2100: return;
2101:
2102: /*
2103: * Several writes to successive memory locations are a common access pattern.
2104: * Try to optimize it.
2105: */
2106: if (addr >= wgfx_linestart && addr + 4 <= wgfx_lineend) {
2107: if (addr < wgfx_min)
2108: wgfx_min = addr;
2109: if (addr + 1 > wgfx_max)
2110: wgfx_max = addr + 1;
2111: return;
2112: } else
2113: wgfx_flushline ();
2114:
2115: addr += gfxmem_start;
2116: /* Check to see if this needs to be written through to the display, or was it an "offscreen" area? */
2117: if (addr < picasso96_state.Address || addr + 1 > picasso96_state.Extent)
2118: return;
2119:
2120: addr -= picasso96_state.Address;
2121: y = addr / picasso96_state.BytesPerRow;
2122:
2123: #if 0
2124: DX_Invalidate (y, y);
2125: if (! picasso_vidinfo.extra_mem)
2126: return;
2127:
2128: xbytes = addr - y * picasso96_state.BytesPerRow;
2129: x = xbytes / picasso96_state.BytesPerPixel;
2130:
2131: if (x < picasso96_state.Width && y < picasso96_state.Height) {
1.1.1.2 ! root 2132: dst = gfx_lock_picasso ();
1.1 root 2133: if (dst) {
2134: *(uae_u8 *)(dst + y * picasso_vidinfo.rowbytes + xbytes) = value;
1.1.1.2 ! root 2135: gfx_unlock_picasso ();
1.1 root 2136: }
2137: }
2138: #else
2139: if (y >= picasso96_state.Height)
2140: return;
2141: wgfx_linestart = picasso96_state.Address - gfxmem_start + y * picasso96_state.BytesPerRow;
2142: wgfx_lineend = wgfx_linestart + picasso96_state.BytesPerRow;
2143: wgfx_y = y;
2144: wgfx_min = oldaddr;
2145: wgfx_max = oldaddr + 1;
2146: #endif
2147: }
2148:
2149: static uae_u32 REGPARAM2 gfxmem_lget (uaecptr addr)
2150: {
2151: uae_u32 *m;
2152: addr -= gfxmem_start & gfxmem_mask;
2153: addr &= gfxmem_mask;
2154: m = (uae_u32 *)(gfxmemory + addr);
2155: return do_get_mem_long(m);
2156: }
2157:
2158: static uae_u32 REGPARAM2 gfxmem_wget (uaecptr addr)
2159: {
2160: uae_u16 *m;
2161: addr -= gfxmem_start & gfxmem_mask;
2162: addr &= gfxmem_mask;
2163: m = (uae_u16 *)(gfxmemory + addr);
2164: return do_get_mem_word(m);
2165: }
2166:
2167: static uae_u32 REGPARAM2 gfxmem_bget (uaecptr addr)
2168: {
2169: addr -= gfxmem_start & gfxmem_mask;
2170: addr &= gfxmem_mask;
2171: return gfxmemory[addr];
2172: }
2173:
2174: static void REGPARAM2 gfxmem_lput (uaecptr addr, uae_u32 l)
2175: {
2176: uae_u32 *m;
2177: addr -= gfxmem_start & gfxmem_mask;
2178: addr &= gfxmem_mask;
2179: m = (uae_u32 *)(gfxmemory + addr);
2180: do_put_mem_long(m, l);
2181:
2182: /* write the long-word to our displayable memory */
2183: write_gfx_long(addr, l);
2184: }
2185:
2186: static void REGPARAM2 gfxmem_wput (uaecptr addr, uae_u32 w)
2187: {
2188: uae_u16 *m;
2189: addr -= gfxmem_start & gfxmem_mask;
2190: addr &= gfxmem_mask;
2191: m = (uae_u16 *)(gfxmemory + addr);
2192: do_put_mem_word(m, (uae_u16)w);
2193:
2194: /* write the word to our displayable memory */
2195: write_gfx_word(addr, (uae_u16)w);
2196: }
2197:
2198: static void REGPARAM2 gfxmem_bput (uaecptr addr, uae_u32 b)
2199: {
2200: addr -= gfxmem_start & gfxmem_mask;
2201: addr &= gfxmem_mask;
2202: gfxmemory[addr] = b;
2203:
2204: /* write the byte to our displayable memory */
2205: write_gfx_byte(addr, (uae_u8)b);
2206: }
2207:
2208: static int REGPARAM2 gfxmem_check (uaecptr addr, uae_u32 size)
2209: {
2210: addr -= gfxmem_start & gfxmem_mask;
2211: addr &= gfxmem_mask;
1.1.1.2 ! root 2212: return (addr + size) < allocated_gfxmem;
1.1 root 2213: }
2214:
2215: static uae_u8 REGPARAM2 *gfxmem_xlate (uaecptr addr)
2216: {
2217: addr -= gfxmem_start & gfxmem_mask;
2218: addr &= gfxmem_mask;
2219: return gfxmemory + addr;
2220: }
2221:
2222: addrbank gfxmem_bank = {
2223: gfxmem_lget, gfxmem_wget, gfxmem_bget,
2224: gfxmem_lput, gfxmem_wput, gfxmem_bput,
2225: gfxmem_xlate, gfxmem_check
2226: };
2227:
2228: static int resolution_compare (const void *a, const void *b)
2229: {
2230: struct PicassoResolution *ma = (struct PicassoResolution *)a;
2231: struct PicassoResolution *mb = (struct PicassoResolution *)b;
2232: if (ma->res.width > mb->res.width)
2233: return -1;
2234: if (ma->res.width < mb->res.width)
2235: return 1;
2236: if (ma->res.height > mb->res.height)
2237: return -1;
2238: if (ma->res.height < mb->res.height)
2239: return 1;
2240: return ma->depth - mb->depth;
2241: }
2242: /* Call this function first, near the beginning of code flow
2243: * NOTE: Don't stuff it in InitGraphics() which seems reasonable...
2244: * Instead, put it in customreset() for safe-keeping. */
2245: void InitPicasso96 (void)
2246: {
2247: static int first_time = 1;
2248:
1.1.1.2 ! root 2249: memset (&picasso96_state, 0, sizeof(struct picasso96_state_struct));
! 2250:
1.1 root 2251: if (first_time) {
2252: int i;
2253:
2254: for (i = 0; i < 256; i++) {
2255: p2ctab[i][0] = (((i & 128) ? 0x01000000 : 0)
2256: | ((i & 64) ? 0x010000 : 0)
2257: | ((i & 32) ? 0x0100 : 0)
2258: | ((i & 16) ? 0x01 : 0));
2259: p2ctab[i][1] = (((i & 8) ? 0x01000000 : 0)
2260: | ((i & 4) ? 0x010000 : 0)
2261: | ((i & 2) ? 0x0100 : 0)
2262: | ((i & 1) ? 0x01 : 0));
2263: }
2264: mode_count = DX_FillResolutions (&picasso96_pixel_format);
2265: qsort (DisplayModes, mode_count, sizeof (struct PicassoResolution),
2266: resolution_compare);
2267:
2268: for (i = 0; i < mode_count; i++) {
2269: sprintf(DisplayModes[i].name, "%dx%d, %d-bit, %d Hz",
2270: DisplayModes[i].res.width, DisplayModes[i].res.height,
2271: DisplayModes[i].depth * 8, DisplayModes[i].refresh);
2272: switch (DisplayModes[i].depth) {
2273: case 1:
2274: if (DisplayModes[i].res.width > chunky.width)
2275: chunky.width = DisplayModes[i].res.width;
2276: if (DisplayModes[i].res.height > chunky.height)
2277: chunky.height = DisplayModes[i].res.height;
2278: break;
2279: case 2:
2280: if (DisplayModes[i].res.width > hicolour.width)
2281: hicolour.width = DisplayModes[i].res.width;
2282: if (DisplayModes[i].res.height > hicolour.height)
2283: hicolour.height = DisplayModes[i].res.height;
2284: break;
2285: case 3:
2286: if (DisplayModes[i].res.width > truecolour.width)
2287: truecolour.width = DisplayModes[i].res.width;
2288: if (DisplayModes[i].res.height > truecolour.height)
2289: truecolour.height = DisplayModes[i].res.height;
2290: break;
2291: case 4:
2292: if (DisplayModes[i].res.width > alphacolour.width)
2293: alphacolour.width = DisplayModes[i].res.width;
2294: if (DisplayModes[i].res.height > alphacolour.height)
2295: alphacolour.height = DisplayModes[i].res.height;
2296: break;
2297: }
2298: }
1.1.1.2 ! root 2299: ShowSupportedResolutions ();
1.1 root 2300:
2301: first_time = 0;
2302: }
2303: }
2304:
2305: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.