|
|
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.