|
|
1.1 ! root 1: /* ! 2: * UAE - The Un*x Amiga Emulator ! 3: * ! 4: * graphics.library emulation ! 5: * ! 6: * Copyright 1996 Bernd Schmidt ! 7: */ ! 8: ! 9: #include "sysconfig.h" ! 10: #include "sysdeps.h" ! 11: ! 12: #include <assert.h> ! 13: ! 14: #include "config.h" ! 15: #include "options.h" ! 16: #include "memory.h" ! 17: #include "custom.h" ! 18: #include "newcpu.h" ! 19: #include "xwin.h" ! 20: #include "autoconf.h" ! 21: #include "osemu.h" ! 22: ! 23: /* Global variables etc. */ ! 24: static ULONG gfxlibname; ! 25: ! 26: static int GFX_PointInRectangle(CPTR rect, int x, int y) ! 27: { ! 28: WORD minx = get_word(rect); ! 29: WORD miny = get_word(rect+2); ! 30: WORD maxx = get_word(rect+4); ! 31: WORD maxy = get_word(rect+6); ! 32: ! 33: if (x < minx || x > maxx || y < miny || y > maxy) ! 34: return 0; ! 35: return 1; ! 36: } ! 37: ! 38: static int GFX_Bitmap_WritePixel(CPTR bitmap, int x, int y, CPTR rp) ! 39: { ! 40: int i, offs; ! 41: unsigned int bpr = get_word (bitmap); ! 42: unsigned int rows = get_word (bitmap + 2); ! 43: UWORD mask; ! 44: ! 45: UBYTE planemask = get_byte(rp + 24); ! 46: UBYTE fgpen = get_byte(rp + 25); ! 47: UBYTE bgpen = get_byte(rp + 26); ! 48: UBYTE drmd = get_byte(rp + 28); ! 49: UBYTE pen = drmd & 4 ? bgpen : fgpen; ! 50: ! 51: if (x < 0 || y < 0 || x >= 8*bpr || y >= rows) ! 52: return -1; ! 53: ! 54: offs = y*bpr + (x & ~15)/8; ! 55: ! 56: for (i = 0; i < get_byte (bitmap + 5); i++) { ! 57: CPTR planeptr; ! 58: UWORD data; ! 59: ! 60: if ((planemask & (1 << i)) == 0) ! 61: continue; ! 62: ! 63: planeptr = get_long(bitmap + 8 + i*4); ! 64: data = get_word(planeptr + offs); ! 65: ! 66: mask = 0x8000 >> (x & 15); ! 67: ! 68: if (drmd & 2) { ! 69: if ((pen & (1 << i)) != 0) ! 70: data ^=mask; ! 71: } else { ! 72: data &= ~mask; ! 73: if ((pen & (1 << i)) != 0) ! 74: data |= mask; ! 75: } ! 76: put_word(planeptr + offs, data); ! 77: } ! 78: return 0; ! 79: } ! 80: ! 81: int GFX_WritePixel(CPTR rp, int x, int y) ! 82: { ! 83: CPTR layer = get_long(rp); ! 84: CPTR bitmap = get_long(rp + 4); ! 85: CPTR cliprect; ! 86: int x2, y2; ! 87: ! 88: if (bitmap == 0) { ! 89: fprintf(stderr, "bogus RastPort in WritePixel\n"); ! 90: return -1; ! 91: } ! 92: ! 93: /* Easy case first */ ! 94: if (layer == 0) { ! 95: return GFX_Bitmap_WritePixel(bitmap, x, y, rp); ! 96: } ! 97: ! 98: /* ! 99: * Now, in theory we ought to obtain the semaphore. ! 100: * Since we don't, the programs will happily write into the raster ! 101: * even though we are currently moving the window around. ! 102: * Not good. ! 103: */ ! 104: ! 105: x2 = x + (WORD)get_word(layer + 16); ! 106: y2 = y + (WORD)get_word(layer + 18); ! 107: ! 108: if (!GFX_PointInRectangle (layer + 16, x2, y2)) ! 109: return -1; ! 110: /* Find the right ClipRect */ ! 111: cliprect = get_long(layer + 8); ! 112: while (cliprect != 0 && !GFX_PointInRectangle (cliprect + 16, x2, y2)) ! 113: cliprect = get_long(cliprect); ! 114: if (cliprect == 0) { ! 115: /* Don't complain: The "Dots" demo does this all the time. I ! 116: * suppose if we can't find a ClipRect, we aren't supposed to draw ! 117: * the dot. ! 118: */ ! 119: /*fprintf(stderr, "Weirdness in WritePixel\n");*/ ! 120: return -1; ! 121: } ! 122: if (get_long(cliprect + 8) == 0) ! 123: return GFX_Bitmap_WritePixel(bitmap, x2, y2, rp); ! 124: ! 125: /* Now come the cases where I don't really know what to do... */ ! 126: if (get_long(cliprect + 12) == 0) ! 127: return 0; ! 128: ! 129: return GFX_Bitmap_WritePixel (get_long(cliprect + 12), x2 - (WORD)get_word(cliprect + 16), ! 130: y2 - (WORD)get_word(cliprect + 18), rp); ! 131: } ! 132: ! 133: ! 134: static ULONG gfxl_WritePixel(void) { return GFX_WritePixel(regs.a[1], (WORD)regs.d[0], (WORD)regs.d[1]); } ! 135: ! 136: static ULONG gfxl_BltClear(void) ! 137: { ! 138: CPTR mem=regs.a[1]; ! 139: UBYTE *mptr = chipmem_bank.xlateaddr(regs.a[1]); ! 140: ULONG count=regs.d[0]; ! 141: ULONG flags=regs.d[1]; ! 142: unsigned int i; ! 143: ULONG pattern; ! 144: ! 145: if ((flags & 2) == 2){ ! 146: /* count is given in Rows / Bytes per row */ ! 147: count=(count & 0xFFFF) * (count >> 16); ! 148: } ! 149: ! 150: if ((mem & 1) != 0 || (count & 1) != 0) ! 151: fprintf(stderr, "gfx: BltClear called with odd parameters\n"); ! 152: ! 153: /* Bit 2 set means use pattern (V36+ only, but we might as well emulate ! 154: * it always) */ ! 155: if ((flags & 4) == 0) ! 156: pattern = 0; ! 157: else ! 158: pattern= ((flags >> 16) & 0xFFFF) | (flags & 0xFFFF0000); ! 159: ! 160: if ((pattern & 0xFF) == ((pattern >> 8) & 0xFF)) { ! 161: memset(mptr, pattern, count); ! 162: return 0; ! 163: } ! 164: ! 165: for(i = 0; i < count; i += 4) ! 166: chipmem_bank.lput(mem+i, pattern); ! 167: ! 168: if ((count & 3) != 0) ! 169: chipmem_bank.wput(mem + i - 4, pattern); ! 170: ! 171: return 0; ! 172: } ! 173: ! 174: static ULONG gfxl_BltBitmap(void) ! 175: { ! 176: CPTR srcbitmap = regs.a[0], dstbitmap = regs.a[1]; ! 177: int srcx = (WORD)regs.d[0], srcy = (WORD)regs.d[1]; ! 178: int dstx = (WORD)regs.d[2], dsty = (WORD)regs.d[3]; ! 179: int sizex = (WORD)regs.d[4], sizey = (WORD)regs.d[5]; ! 180: UBYTE minterm = (UBYTE)regs.d[6], mask = regs.d[7]; ! 181: ! 182: } ! 183: ! 184: static CPTR amiga_malloc(int len) ! 185: { ! 186: regs.d[0] = len; ! 187: regs.d[1] = 1; /* MEMF_PUBLIC */ ! 188: return CallLib(get_long(4), -198); /* AllocMem */ ! 189: } ! 190: ! 191: static void amiga_free(CPTR addr, int len) ! 192: { ! 193: regs.a[1] = addr; ! 194: regs.d[0] = len; ! 195: CallLib(get_long(4), -210); /* FreeMem */ ! 196: } ! 197: ! 198: /* ! 199: * Region handling code ! 200: * ! 201: * The Clear code is untested. And and Or seem to work, Xor is only used ! 202: * by the 1.3 Prefs program and seems to work, too. ! 203: */ ! 204: ! 205: struct Rectangle { ! 206: WORD MinX, MinY, MaxX, MaxY; ! 207: }; ! 208: ! 209: struct RegionRectangle { ! 210: struct RegionRectangle *Next,*Prev; ! 211: struct Rectangle bounds; ! 212: }; ! 213: ! 214: struct Region { ! 215: struct Rectangle bounds; ! 216: struct RegionRectangle *RegionRectangle; ! 217: }; ! 218: ! 219: struct RectList { ! 220: int count; ! 221: int space; ! 222: struct Rectangle bounds; ! 223: struct Rectangle *rects; ! 224: }; ! 225: ! 226: struct BandList { ! 227: int count; ! 228: int space; ! 229: int *miny, *maxy; ! 230: }; ! 231: ! 232: static void init_bandlist(struct BandList *bl) ! 233: { ! 234: bl->count = 0; ! 235: bl->space = 20; ! 236: bl->miny = (int *)malloc(20*sizeof(int)); ! 237: bl->maxy = (int *)malloc(20*sizeof(int)); ! 238: } ! 239: ! 240: static __inline__ void add_band(struct BandList *bl, int miny, int maxy, int pos) ! 241: { ! 242: if (bl->count == bl->space) { ! 243: bl->space += 20; ! 244: bl->miny = (int *)realloc(bl->miny, bl->space*sizeof(int)); ! 245: bl->maxy = (int *)realloc(bl->maxy, bl->space*sizeof(int)); ! 246: } ! 247: memmove(bl->miny + pos + 1, bl->miny + pos, (bl->count - pos) * sizeof(int)); ! 248: memmove(bl->maxy + pos + 1, bl->maxy + pos, (bl->count - pos) * sizeof(int)); ! 249: bl->count++; ! 250: bl->miny[pos] = miny; ! 251: bl->maxy[pos] = maxy; ! 252: } ! 253: ! 254: static void init_rectlist(struct RectList *rl) ! 255: { ! 256: rl->count = 0; ! 257: rl->space = 100; ! 258: rl->bounds.MinX = rl->bounds.MinY = rl->bounds.MaxX = rl->bounds.MaxY = 0; ! 259: rl->rects = (struct Rectangle *)malloc(100*sizeof(struct Rectangle)); ! 260: } ! 261: ! 262: static __inline__ void add_rect(struct RectList *rl, struct Rectangle r) ! 263: { ! 264: if (rl->count == 0) ! 265: rl->bounds = r; ! 266: else { ! 267: if (r.MinX < rl->bounds.MinX) ! 268: rl->bounds.MinX = r.MinX; ! 269: if (r.MinY < rl->bounds.MinY) ! 270: rl->bounds.MinY = r.MinY; ! 271: if (r.MaxX > rl->bounds.MaxX) ! 272: rl->bounds.MaxX = r.MaxX; ! 273: if (r.MaxY > rl->bounds.MaxY) ! 274: rl->bounds.MaxY = r.MaxY; ! 275: } ! 276: if (rl->count == rl->space) { ! 277: rl->space += 100; ! 278: rl->rects = (struct Rectangle *)realloc(rl->rects, rl->space*sizeof(struct Rectangle)); ! 279: } ! 280: rl->rects[rl->count++] = r; ! 281: } ! 282: ! 283: static __inline__ void rem_rect(struct RectList *rl, int num) ! 284: { ! 285: rl->count--; ! 286: if (num == rl->count) ! 287: return; ! 288: rl->rects[num] = rl->rects[rl->count]; ! 289: } ! 290: ! 291: static void free_rectlist(struct RectList *rl) ! 292: { ! 293: free(rl->rects); ! 294: } ! 295: ! 296: static void free_bandlist(struct BandList *bl) ! 297: { ! 298: free(bl->miny); ! 299: free(bl->maxy); ! 300: } ! 301: ! 302: static int regionrect_cmpfn(const void *a, const void *b) ! 303: { ! 304: struct Rectangle *ra = (struct Rectangle *)a; ! 305: struct Rectangle *rb = (struct Rectangle *)b; ! 306: ! 307: if (ra->MinY < rb->MinY) ! 308: return -1; ! 309: if (ra->MinY > rb->MinY) ! 310: return 1; ! 311: if (ra->MinX < rb->MinX) ! 312: return -1; ! 313: if (ra->MinX > rb->MinX) ! 314: return 1; ! 315: if (ra->MaxX < rb->MaxX) ! 316: return -1; ! 317: return 1; ! 318: } ! 319: ! 320: static __inline__ int min(int x, int y) ! 321: { ! 322: return x < y ? x : y; ! 323: } ! 324: ! 325: static __inline__ int max(int x, int y) ! 326: { ! 327: return x > y ? x : y; ! 328: } ! 329: ! 330: static void region_addbands(struct RectList *rl, struct BandList *bl) ! 331: { ! 332: int i,j; ! 333: ! 334: for (i = 0; i < rl->count; i++) { ! 335: struct Rectangle tmpr = rl->rects[i]; ! 336: ! 337: for (j = 0; j < bl->count; j++) { ! 338: /* Is the current band before the rectangle? */ ! 339: if (bl->maxy[j] < tmpr.MinY) ! 340: continue; ! 341: /* Band already present? */ ! 342: if (bl->miny[j] == tmpr.MinY && bl->maxy[j] == tmpr.MaxY) ! 343: break; ! 344: /* Completely new band? Add it */ ! 345: if (bl->miny[j] > tmpr.MaxY) { ! 346: add_band(bl, tmpr.MinY, tmpr.MaxY, j); ! 347: break; ! 348: } ! 349: /* Now we know that the bands are overlapping. ! 350: * See whether they match in one point */ ! 351: if (bl->miny[j] == tmpr.MinY) { ! 352: int t; ! 353: if (bl->maxy[j] < tmpr.MaxY) { ! 354: /* Rectangle exceeds band */ ! 355: tmpr.MinY = bl->maxy[j]+1; ! 356: continue; ! 357: } ! 358: /* Rectangle splits band */ ! 359: t = bl->maxy[j]; ! 360: bl->maxy[j] = tmpr.MaxY; ! 361: tmpr.MinY = bl->maxy[j] + 1; ! 362: tmpr.MaxY = t; ! 363: continue; ! 364: } else if (bl->maxy[j] == tmpr.MaxY) { ! 365: int t; ! 366: if (bl->miny[j] > tmpr.MinY) { ! 367: /* Rectangle exceeds band */ ! 368: t = bl->miny[j]; ! 369: bl->miny[j] = tmpr.MinY; ! 370: bl->maxy[j] = t-1; ! 371: tmpr.MinY = t; ! 372: continue; ! 373: } ! 374: /* Rectangle splits band */ ! 375: bl->maxy[j] = tmpr.MinY - 1; ! 376: continue; ! 377: } ! 378: /* Bands overlap and match in no points. Get a new band and align */ ! 379: if (bl->miny[j] > tmpr.MinY) { ! 380: /* Rectangle begins before band, so make a new band before ! 381: * and adjust rectangle */ ! 382: add_band(bl, tmpr.MinY, bl->miny[j] - 1, j); ! 383: tmpr.MinY = bl->miny[j+1]; ! 384: } else { ! 385: /* Rectangle begins in band */ ! 386: add_band(bl, bl->miny[j], tmpr.MinY - 1, j); ! 387: bl->miny[j+1] = tmpr.MinY; ! 388: } ! 389: continue; ! 390: } ! 391: if (j == bl->count) ! 392: add_band(bl, tmpr.MinY, tmpr.MaxY, j); ! 393: } ! 394: } ! 395: ! 396: static void region_splitrects_band(struct RectList *rl, struct BandList *bl) ! 397: { ! 398: int i,j; ! 399: for (i = 0; i < rl->count; i++) { ! 400: for (j = 0; j < bl->count; j++) { ! 401: if (bl->miny[j] == rl->rects[i].MinY && bl->maxy[j] == rl->rects[i].MaxY) ! 402: break; ! 403: if (rl->rects[i].MinY > bl->maxy[j]) ! 404: continue; ! 405: if (bl->miny[j] == rl->rects[i].MinY) { ! 406: struct Rectangle tmpr; ! 407: tmpr.MinX = rl->rects[i].MinX; ! 408: tmpr.MaxX = rl->rects[i].MaxX; ! 409: tmpr.MinY = bl->maxy[j] + 1; ! 410: tmpr.MaxY = rl->rects[i].MaxY; ! 411: add_rect(rl, tmpr); /* will be processed later */ ! 412: rl->rects[i].MaxY = bl->maxy[j]; ! 413: break; ! 414: } ! 415: fprintf(stderr, "Foo..\n"); ! 416: } ! 417: } ! 418: qsort(rl->rects, rl->count, sizeof (struct Rectangle), regionrect_cmpfn); ! 419: } ! 420: ! 421: static void region_coalesce_rects(struct RectList *rl, int do_2nd_pass) ! 422: { ! 423: int i,j; ! 424: ! 425: /* First pass: Coalesce horizontally */ ! 426: for (i = j = 0; i < rl->count;) { ! 427: int offs = 1; ! 428: while (i + offs < rl->count) { ! 429: if (rl->rects[i].MinY != rl->rects[i+offs].MinY ! 430: || rl->rects[i].MaxY != rl->rects[i+offs].MaxY ! 431: || rl->rects[i].MaxX+1 < rl->rects[i+offs].MinX) ! 432: break; ! 433: rl->rects[i].MaxX = rl->rects[i+offs].MaxX; ! 434: offs++; ! 435: } ! 436: rl->rects[j++] = rl->rects[i]; ! 437: i += offs; ! 438: } ! 439: rl->count = j; ! 440: ! 441: if (!do_2nd_pass) ! 442: return; ! 443: ! 444: /* Second pass: Coalesce bands */ ! 445: for (i = 0; i < rl->count;) { ! 446: int match = 0; ! 447: for (j = i + 1; j < rl->count; j++) ! 448: if (rl->rects[i].MinY != rl->rects[j].MinY) ! 449: break; ! 450: if (j < rl->count && rl->rects[i].MaxY + 1 == rl->rects[j].MinY) { ! 451: int k; ! 452: match = 1; ! 453: for (k = 0; i+k < j; k++) { ! 454: if (j+k >= rl->count ! 455: || rl->rects[j+k].MinY != rl->rects[j].MinY) ! 456: { ! 457: match = 0; break; ! 458: } ! 459: if (rl->rects[i+k].MinX != rl->rects[j+k].MinX ! 460: || rl->rects[i+k].MaxX != rl->rects[j+k].MaxX) ! 461: { ! 462: match = 0; ! 463: break; ! 464: } ! 465: } ! 466: if (j+k < rl->count && rl->rects[j+k].MinY == rl->rects[j].MinY) ! 467: match = 0; ! 468: if (match) { ! 469: for (k = 0; i+k < j; k++) ! 470: rl->rects[i+k].MaxY = rl->rects[j].MaxY; ! 471: memmove(rl->rects + j, rl->rects + j + k, (rl->count - j - k)*sizeof(struct Rectangle)); ! 472: rl->count -= k; ! 473: } ! 474: } ! 475: if (!match) ! 476: i = j; ! 477: } ! 478: } ! 479: ! 480: static int copy_rects (CPTR region, struct RectList *rl) ! 481: { ! 482: CPTR regionrect; ! 483: int numrects = 0; ! 484: struct Rectangle b; ! 485: regionrect = get_long(region+8); ! 486: b.MinX = get_word(region); ! 487: b.MinY = get_word(region+2); ! 488: b.MaxX = get_word(region+4); ! 489: b.MaxY = get_word(region+6); ! 490: ! 491: while (regionrect != 0) { ! 492: struct Rectangle tmpr; ! 493: ! 494: tmpr.MinX = (WORD)get_word(regionrect+8) + b.MinX; ! 495: tmpr.MinY = (WORD)get_word(regionrect+10) + b.MinY; ! 496: tmpr.MaxX = (WORD)get_word(regionrect+12) + b.MinX; ! 497: tmpr.MaxY = (WORD)get_word(regionrect+14) + b.MinY; ! 498: add_rect(rl, tmpr); ! 499: regionrect = get_long(regionrect); ! 500: numrects++; ! 501: } ! 502: return numrects; ! 503: } ! 504: ! 505: typedef void (*regionop)(struct RectList *,struct RectList *,struct RectList *); ! 506: ! 507: static void region_do_ClearRegionRegion(struct RectList *rl1,struct RectList *rl2, ! 508: struct RectList *rl3) ! 509: { ! 510: int i,j; ! 511: ! 512: for (i = j = 0; i < rl2->count && j < rl1->count;) { ! 513: struct Rectangle tmpr; ! 514: ! 515: while ((rl1->rects[j].MinY < rl2->rects[i].MinY ! 516: || (rl1->rects[j].MinY == rl2->rects[i].MinY ! 517: && rl1->rects[j].MaxX < rl2->rects[i].MinX)) ! 518: && j < rl1->count) ! 519: j++; ! 520: if (j >= rl1->count) ! 521: break; ! 522: while ((rl1->rects[j].MinY > rl2->rects[i].MinY ! 523: || (rl1->rects[j].MinY == rl2->rects[i].MinY ! 524: && rl1->rects[j].MinX > rl2->rects[i].MaxX)) ! 525: && i < rl2->count) ! 526: { ! 527: add_rect(rl3, rl2->rects[i]); ! 528: i++; ! 529: } ! 530: if (i >= rl2->count) ! 531: break; ! 532: ! 533: tmpr = rl2->rects[i]; ! 534: ! 535: while (i < rl2->count && j < rl1->count ! 536: && rl1->rects[j].MinY == tmpr.MinY ! 537: && rl2->rects[i].MinY == tmpr.MinY ! 538: && rl1->rects[j].MinX <= rl2->rects[i].MaxX ! 539: && rl1->rects[j].MaxX >= rl2->rects[i].MinX) ! 540: { ! 541: int oldmin = tmpr.MinX; ! 542: int oldmax = tmpr.MaxX; ! 543: if (tmpr.MinX < rl1->rects[j].MinX) { ! 544: tmpr.MaxX = rl1->rects[j].MinX - 1; ! 545: add_rect(rl3, tmpr); ! 546: } ! 547: if (oldmax <= rl1->rects[j].MaxX) { ! 548: i++; ! 549: if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY) ! 550: tmpr = rl2->rects[i]; ! 551: } else { ! 552: tmpr.MinX = rl1->rects[j].MaxX + 1; ! 553: tmpr.MaxX = oldmax; ! 554: j++; ! 555: } ! 556: } ! 557: } ! 558: for(; i < rl2->count; i++) ! 559: add_rect(rl3, rl2->rects[i]); ! 560: } ! 561: ! 562: static void region_do_AndRegionRegion(struct RectList *rl1,struct RectList *rl2, ! 563: struct RectList *rl3) ! 564: { ! 565: int i,j; ! 566: ! 567: for (i = j = 0; i < rl2->count && j < rl1->count;) { ! 568: while ((rl1->rects[j].MinY < rl2->rects[i].MinY ! 569: || (rl1->rects[j].MinY == rl2->rects[i].MinY ! 570: && rl1->rects[j].MaxX < rl2->rects[i].MinX)) ! 571: && j < rl1->count) ! 572: j++; ! 573: if (j >= rl1->count) ! 574: break; ! 575: while ((rl1->rects[j].MinY > rl2->rects[i].MinY ! 576: || (rl1->rects[j].MinY == rl2->rects[i].MinY ! 577: && rl1->rects[j].MinX > rl2->rects[i].MaxX)) ! 578: && i < rl2->count) ! 579: i++; ! 580: if (i >= rl2->count) ! 581: break; ! 582: if (rl1->rects[j].MinY == rl2->rects[i].MinY ! 583: && rl1->rects[j].MinX <= rl2->rects[i].MaxX ! 584: && rl1->rects[j].MaxX >= rl2->rects[i].MinX) ! 585: { ! 586: /* We have an intersection! */ ! 587: struct Rectangle tmpr; ! 588: tmpr = rl2->rects[i]; ! 589: if (tmpr.MinX < rl1->rects[j].MinX) ! 590: tmpr.MinX = rl1->rects[j].MinX; ! 591: if (tmpr.MaxX > rl1->rects[j].MaxX) ! 592: tmpr.MaxX = rl1->rects[j].MaxX; ! 593: add_rect(rl3, tmpr); ! 594: if (rl1->rects[j].MaxX == rl2->rects[i].MaxX) ! 595: i++, j++; ! 596: else if (rl1->rects[j].MaxX > rl2->rects[i].MaxX) ! 597: i++; ! 598: else ! 599: j++; ! 600: } ! 601: } ! 602: } ! 603: ! 604: static void region_do_OrRegionRegion(struct RectList *rl1,struct RectList *rl2, ! 605: struct RectList *rl3) ! 606: { ! 607: int i,j; ! 608: ! 609: for (i = j = 0; i < rl2->count && j < rl1->count;) { ! 610: while ((rl1->rects[j].MinY < rl2->rects[i].MinY ! 611: || (rl1->rects[j].MinY == rl2->rects[i].MinY ! 612: && rl1->rects[j].MaxX < rl2->rects[i].MinX)) ! 613: && j < rl1->count) ! 614: { ! 615: add_rect(rl3, rl1->rects[j]); ! 616: j++; ! 617: } ! 618: if (j >= rl1->count) ! 619: break; ! 620: while ((rl1->rects[j].MinY > rl2->rects[i].MinY ! 621: || (rl1->rects[j].MinY == rl2->rects[i].MinY ! 622: && rl1->rects[j].MinX > rl2->rects[i].MaxX)) ! 623: && i < rl2->count) ! 624: { ! 625: add_rect(rl3, rl2->rects[i]); ! 626: i++; ! 627: } ! 628: if (i >= rl2->count) ! 629: break; ! 630: if (rl1->rects[j].MinY == rl2->rects[i].MinY ! 631: && rl1->rects[j].MinX <= rl2->rects[i].MaxX ! 632: && rl1->rects[j].MaxX >= rl2->rects[i].MinX) ! 633: { ! 634: /* We have an intersection! */ ! 635: struct Rectangle tmpr; ! 636: tmpr = rl2->rects[i]; ! 637: if (tmpr.MinX > rl1->rects[j].MinX) ! 638: tmpr.MinX = rl1->rects[j].MinX; ! 639: if (tmpr.MaxX < rl1->rects[j].MaxX) ! 640: tmpr.MaxX = rl1->rects[j].MaxX; ! 641: i++; j++; ! 642: for (;;) { ! 643: int cont = 0; ! 644: if (j < rl1->count && rl1->rects[j].MinY == tmpr.MinY ! 645: && tmpr.MaxX+1 >= rl1->rects[j].MinX) { ! 646: if (tmpr.MaxX < rl1->rects[j].MaxX) ! 647: tmpr.MaxX = rl1->rects[j].MaxX; ! 648: j++; cont = 1; ! 649: } ! 650: if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY ! 651: && tmpr.MaxX+1 >= rl2->rects[i].MinX) { ! 652: if (tmpr.MaxX < rl2->rects[i].MaxX) ! 653: tmpr.MaxX = rl2->rects[i].MaxX; ! 654: i++; cont = 1; ! 655: } ! 656: if (!cont) ! 657: break; ! 658: } ! 659: add_rect(rl3, tmpr); ! 660: } ! 661: } ! 662: for(; i < rl2->count; i++) ! 663: add_rect(rl3, rl2->rects[i]); ! 664: for(; j < rl1->count; j++) ! 665: add_rect(rl3, rl1->rects[j]); ! 666: } ! 667: ! 668: static void region_do_XorRegionRegion(struct RectList *rl1,struct RectList *rl2, ! 669: struct RectList *rl3) ! 670: { ! 671: int i,j; ! 672: ! 673: for (i = j = 0; i < rl2->count && j < rl1->count;) { ! 674: struct Rectangle tmpr1, tmpr2; ! 675: ! 676: while ((rl1->rects[j].MinY < rl2->rects[i].MinY ! 677: || (rl1->rects[j].MinY == rl2->rects[i].MinY ! 678: && rl1->rects[j].MaxX < rl2->rects[i].MinX)) ! 679: && j < rl1->count) ! 680: { ! 681: add_rect(rl3, rl1->rects[j]); ! 682: j++; ! 683: } ! 684: if (j >= rl1->count) ! 685: break; ! 686: while ((rl1->rects[j].MinY > rl2->rects[i].MinY ! 687: || (rl1->rects[j].MinY == rl2->rects[i].MinY ! 688: && rl1->rects[j].MinX > rl2->rects[i].MaxX)) ! 689: && i < rl2->count) ! 690: { ! 691: add_rect(rl3, rl2->rects[i]); ! 692: i++; ! 693: } ! 694: if (i >= rl2->count) ! 695: break; ! 696: ! 697: tmpr2 = rl2->rects[i]; ! 698: tmpr1 = rl1->rects[j]; ! 699: ! 700: while (i < rl2->count && j < rl1->count ! 701: && rl1->rects[j].MinY == tmpr1.MinY ! 702: && rl2->rects[i].MinY == tmpr1.MinY ! 703: && rl1->rects[j].MinX <= rl2->rects[i].MaxX ! 704: && rl1->rects[j].MaxX >= rl2->rects[i].MinX) ! 705: { ! 706: int oldmin2 = tmpr2.MinX; ! 707: int oldmax2 = tmpr2.MaxX; ! 708: int oldmin1 = tmpr1.MinX; ! 709: int oldmax1 = tmpr1.MaxX; ! 710: int need_1 = 0, need_2 = 0; ! 711: ! 712: if (tmpr2.MinX > tmpr1.MinX && tmpr2.MaxX < tmpr1.MaxX) ! 713: { ! 714: /* ! 715: * ########### ! 716: * **** ! 717: */ ! 718: tmpr1.MaxX = tmpr2.MinX - 1; ! 719: add_rect(rl3, tmpr1); ! 720: tmpr1.MaxX = oldmax1; ! 721: tmpr1.MinX = tmpr2.MaxX + 1; ! 722: add_rect(rl3, tmpr1); ! 723: need_2 = 1; ! 724: } else if (tmpr2.MinX > tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) { ! 725: /* ! 726: * ########## ! 727: * ********* ! 728: */ ! 729: tmpr1.MaxX = tmpr2.MinX - 1; ! 730: add_rect(rl3, tmpr1); ! 731: tmpr2.MinX = oldmax1 + 1; ! 732: add_rect(rl3, tmpr2); ! 733: need_1 = 1; ! 734: } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX < tmpr1.MaxX) { ! 735: /* ! 736: * ########## ! 737: * ********* ! 738: */ ! 739: tmpr2.MaxX = tmpr1.MinX - 1; ! 740: add_rect(rl3, tmpr2); ! 741: tmpr1.MinX = oldmax2 + 1; ! 742: add_rect(rl3, tmpr1); ! 743: need_2 = 1; ! 744: } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) { ! 745: /* ! 746: * ### ! 747: * ********* ! 748: */ ! 749: tmpr2.MaxX = tmpr1.MinX - 1; ! 750: add_rect(rl3, tmpr2); ! 751: tmpr2.MaxX = oldmax2; ! 752: tmpr2.MinX = tmpr1.MaxX + 1; ! 753: add_rect(rl3, tmpr2); ! 754: need_1 = 1; ! 755: } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX < tmpr1.MaxX) { ! 756: /* ! 757: * ############# ! 758: * ********* ! 759: */ ! 760: tmpr1.MinX = tmpr2.MaxX + 1; ! 761: need_2 = 1; ! 762: } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX > tmpr1.MaxX) { ! 763: /* ! 764: * ######### ! 765: * ************* ! 766: */ ! 767: tmpr2.MinX = tmpr1.MaxX + 1; ! 768: need_1 = 1; ! 769: } else if (tmpr1.MinX < tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) { ! 770: /* ! 771: * ############# ! 772: * ********* ! 773: */ ! 774: tmpr1.MaxX = tmpr2.MinX - 1; ! 775: add_rect(rl3, tmpr1); ! 776: need_2 = need_1 = 1; ! 777: } else if (tmpr1.MinX > tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) { ! 778: /* ! 779: * ######### ! 780: * ************* ! 781: */ ! 782: tmpr2.MaxX = tmpr1.MinX - 1; ! 783: add_rect(rl3, tmpr2); ! 784: need_2 = need_1 = 1; ! 785: } else { ! 786: assert(tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX); ! 787: need_1 = need_2 = 1; ! 788: } ! 789: if (need_1) { ! 790: j++; ! 791: if (j < rl1->count && rl1->rects[j].MinY == tmpr1.MinY) ! 792: tmpr1 = rl1->rects[j]; ! 793: } ! 794: if (need_2) { ! 795: i++; ! 796: if (i < rl2->count && rl2->rects[i].MinY == tmpr2.MinY) ! 797: tmpr2 = rl2->rects[i]; ! 798: } ! 799: } ! 800: } ! 801: for(; i < rl2->count; i++) ! 802: add_rect(rl3, rl2->rects[i]); ! 803: for(; j < rl1->count; j++) ! 804: add_rect(rl3, rl1->rects[j]); ! 805: } ! 806: ! 807: static ULONG gfxl_perform_regionop(regionop op, int with_rect) ! 808: { ! 809: int i,j,k; ! 810: CPTR reg1; ! 811: CPTR reg2; ! 812: CPTR tmp, rpp; ! 813: struct RectList rl1, rl2, rl3; ! 814: struct BandList bl; ! 815: ! 816: int retval = 0; ! 817: int numrects2; ! 818: ! 819: init_rectlist(&rl1); init_rectlist(&rl2); init_rectlist(&rl3); ! 820: ! 821: if (with_rect) { ! 822: struct Rectangle tmpr; ! 823: reg2 = regs.a[0]; ! 824: numrects2 = copy_rects(reg2, &rl2); ! 825: tmpr.MinX = get_word(regs.a[1]); ! 826: tmpr.MinY = get_word(regs.a[1] + 2); ! 827: tmpr.MaxX = get_word(regs.a[1] + 4); ! 828: tmpr.MaxY = get_word(regs.a[1] + 6); ! 829: add_rect(&rl1, tmpr); ! 830: } else { ! 831: reg1 = regs.a[0]; ! 832: reg2 = regs.a[1]; ! 833: ! 834: copy_rects(reg1, &rl1); ! 835: numrects2 = copy_rects(reg2, &rl2); ! 836: } ! 837: ! 838: init_bandlist(&bl); ! 839: region_addbands(&rl1, &bl); ! 840: region_addbands(&rl2, &bl); ! 841: region_splitrects_band(&rl1, &bl); ! 842: region_splitrects_band(&rl2, &bl); ! 843: region_coalesce_rects(&rl1, 0); ! 844: region_coalesce_rects(&rl2, 0); ! 845: ! 846: (*op)(&rl1, &rl2, &rl3); ! 847: region_coalesce_rects(&rl3, 1); ! 848: ! 849: rpp = reg2 + 8; ! 850: if (rl3.count < numrects2) { ! 851: while (numrects2-- != rl3.count) { ! 852: tmp = get_long(rpp); ! 853: put_long(rpp, get_long(tmp)); ! 854: amiga_free(tmp, 16); ! 855: } ! 856: if (rl3.count > 0) ! 857: put_long(get_long(rpp) + 4, rpp); ! 858: } else if (rl3.count > numrects2) { ! 859: while(numrects2++ != rl3.count) { ! 860: CPTR prev = get_long(rpp); ! 861: tmp = amiga_malloc(16); ! 862: if (tmp == 0) ! 863: goto done; ! 864: put_long(tmp, prev); ! 865: put_long(tmp + 4, rpp); ! 866: if (prev != 0) ! 867: put_long(prev + 4, tmp); ! 868: put_long(rpp, tmp); ! 869: } ! 870: } ! 871: ! 872: if (rl3.count > 0) { ! 873: rpp = reg2 + 8; ! 874: for (i = 0; i < rl3.count; i++) { ! 875: CPTR rr = get_long(rpp); ! 876: put_word(rr+8, rl3.rects[i].MinX - rl3.bounds.MinX); ! 877: put_word(rr+10, rl3.rects[i].MinY - rl3.bounds.MinY); ! 878: put_word(rr+12, rl3.rects[i].MaxX - rl3.bounds.MinX); ! 879: put_word(rr+14, rl3.rects[i].MaxY - rl3.bounds.MinY); ! 880: rpp = rr; ! 881: } ! 882: if (get_long(rpp) != 0) ! 883: fprintf(stderr, "BUG\n"); ! 884: } ! 885: put_word(reg2+0, rl3.bounds.MinX); ! 886: put_word(reg2+2, rl3.bounds.MinY); ! 887: put_word(reg2+4, rl3.bounds.MaxX); ! 888: put_word(reg2+6, rl3.bounds.MaxY); ! 889: retval = 1; ! 890: ! 891: done: ! 892: free_rectlist(&rl1); free_rectlist(&rl2); free_rectlist(&rl3); ! 893: free_bandlist(&bl); ! 894: ! 895: return retval; ! 896: } ! 897: ! 898: static ULONG gfxl_AndRegionRegion(void) ! 899: { ! 900: /* printf("AndRegionRegion\n");*/ ! 901: return gfxl_perform_regionop(region_do_AndRegionRegion, 0); ! 902: } ! 903: static ULONG gfxl_XorRegionRegion(void) ! 904: { ! 905: printf("XorRegionRegion\n"); ! 906: return gfxl_perform_regionop(region_do_XorRegionRegion, 0); ! 907: } ! 908: static ULONG gfxl_OrRegionRegion(void) ! 909: { ! 910: /* printf("OrRegionRegion\n");*/ ! 911: return gfxl_perform_regionop(region_do_OrRegionRegion, 0); ! 912: } ! 913: ! 914: static ULONG gfxl_ClearRectRegion(void) ! 915: { ! 916: printf("ClearRectRegion\n"); ! 917: return gfxl_perform_regionop(region_do_ClearRegionRegion, 1); ! 918: } ! 919: static ULONG gfxl_OrRectRegion(void) ! 920: { ! 921: /* printf("OrRectRegion\n");*/ ! 922: return gfxl_perform_regionop(region_do_OrRegionRegion, 1); ! 923: } ! 924: ! 925: static ULONG gfxl_AndRectRegion(void) ! 926: { ! 927: printf("AndRectRegion\n"); ! 928: return gfxl_perform_regionop(region_do_AndRegionRegion, 1); ! 929: } ! 930: ! 931: static ULONG gfxl_XorRectRegion(void) ! 932: { ! 933: printf("XorRectRegion\n"); ! 934: return gfxl_perform_regionop(region_do_XorRegionRegion, 1); ! 935: } ! 936: ! 937: ! 938: /* ! 939: * Initialization ! 940: */ ! 941: static ULONG gfxlib_init(void) ! 942: { ! 943: ULONG old_arr; ! 944: CPTR gfxbase; ! 945: CPTR sysbase=regs.a[6]; ! 946: int i=0; ! 947: ! 948: /* Install new routines */ ! 949: /* We have to call SetFunction here instead of writing direktly into the GfxBase, ! 950: * because of the library checksum ! */ ! 951: ! 952: regs.d[0]=0; ! 953: regs.a[1]=gfxlibname; ! 954: gfxbase=CallLib(sysbase, -408); /* OpenLibrary */ ! 955: ! 956: libemu_InstallFunction(gfxl_WritePixel, gfxbase, -324); ! 957: libemu_InstallFunction(gfxl_BltClear, gfxbase, -300); ! 958: libemu_InstallFunction(gfxl_AndRegionRegion, gfxbase, -624); ! 959: libemu_InstallFunction(gfxl_OrRegionRegion, gfxbase, -612); ! 960: libemu_InstallFunction(gfxl_XorRegionRegion, gfxbase, -618); ! 961: libemu_InstallFunction(gfxl_AndRectRegion, gfxbase, -504); ! 962: libemu_InstallFunction(gfxl_OrRectRegion, gfxbase, -510); ! 963: libemu_InstallFunction(gfxl_XorRectRegion, gfxbase, -558); ! 964: libemu_InstallFunction(gfxl_ClearRectRegion, gfxbase, -522); ! 965: ! 966: return 0; ! 967: } ! 968: ! 969: /* ! 970: * Install the gfx-library-replacement ! 971: */ ! 972: void gfxlib_install(void) ! 973: { ! 974: ULONG begin, end, resname, resid; ! 975: int i; ! 976: ! 977: if(!use_gfxlib) return; ! 978: ! 979: fprintf(stderr, "Warning: you enabled the graphics.library replacement with -g\n" ! 980: "This may be buggy right now, and will not speed things up much.\n"); ! 981: ! 982: resname = ds("UAEgfxlib.resource"); ! 983: resid = ds("UAE gfxlib 0.1"); ! 984: ! 985: gfxlibname = ds("graphics.library"); ! 986: ! 987: begin = here(); ! 988: dw(0x4AFC); /* RTC_MATCHWORD */ ! 989: dl(begin); /* our start address */ ! 990: dl(0); /* Continue scan here */ ! 991: dw(0x0101); /* RTF_COLDSTART; Version 1 */ ! 992: dw(0x0805); /* NT_RESOURCE; pri 5 */ ! 993: dl(resname); /* name */ ! 994: dl(resid); /* ID */ ! 995: dl(here() + 4); /* Init area: directly after this */ ! 996: ! 997: calltrap(deftrap(gfxlib_init)); dw(RTS); ! 998: ! 999: end = here(); ! 1000: org(begin + 6); ! 1001: dl(end); ! 1002: ! 1003: org(end); ! 1004: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.