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