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