|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * graphics.library emulation
5: *
1.1.1.3 root 6: * Copyright 1996, 1997 Bernd Schmidt
7: *
1.1.1.2 root 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
1.1.1.3 root 16: * rewritten as well.
1.1.1.2 root 17: * Once that's done, add support for non-planar bitmaps. Conveniently, the
18: * struct Bitmap has an unused pad field which we could abuse as some sort of
19: * type field. Need to add chunky<->planar conversion routines to get it
20: * going, plus variants of all the drawing functions for speed reasons.
1.1.1.3 root 21: *
1.1.1.2 root 22: * When it becomes necessary to convert a structure from Amiga memory, make
23: * a function with a name ending in ..FA, which takes a pointer to the
1.1.1.3 root 24: * native structure and a uaecptr and returns the native pointer.
1.1 root 25: */
26:
27: #include "sysconfig.h"
28: #include "sysdeps.h"
29:
30: #include <assert.h>
31:
32: #include "options.h"
1.1.1.7 root 33: #include "threaddep/thread.h"
1.1 root 34: #include "memory.h"
35: #include "custom.h"
36: #include "newcpu.h"
37: #include "xwin.h"
38: #include "autoconf.h"
1.1.1.9 ! root 39: #include "traps.h"
1.1 root 40: #include "osemu.h"
1.1.1.3 root 41: #include "osdep/exectasks.h"
1.1 root 42:
1.1.1.3 root 43: #ifdef USE_EXECLIB
44:
45: /* Uniq list management. Should be in a separate file. */
46: struct uniq_head {
47: struct uniq_head *next;
48: uae_u32 uniq;
49: };
50:
51: typedef struct {
52: struct uniq_head *head;
53: uae_u32 uniq;
54: } uniq_list;
55:
56: #define UNIQ_INIT { NULL, 1 }
57:
58: static void init_uniq(uniq_list *list)
59: {
60: list->head = NULL;
61: list->uniq = 1;
62: }
63:
64: static struct uniq_head *find_uniq (uniq_list *a, uae_u32 uniq)
65: {
66: struct uniq_head *b = a->head;
67: while (b && b->uniq != uniq)
68: b = b->next;
69: if (!b)
70: write_log("Couldn't find structure. Bad\n");
71: return b;
72: }
73:
74: static struct uniq_head *find_and_rem_uniq (uniq_list *a, uae_u32 uniq)
75: {
76: struct uniq_head **b = &a->head, *c;
77: while (*b && (*b)->uniq != uniq)
78: b = &(*b)->next;
79: c = *b;
80: if (!c)
81: write_log("Couldn't find structure. Bad\n");
82: else
83: *b = c->next;
84: return c;
85: }
86:
87: static void add_uniq (uniq_list *a, struct uniq_head *item, uaecptr amem)
88: {
89: item->uniq = a->uniq++;
90: put_long(amem, item->uniq);
91: if (a->uniq == 0)
92: a->uniq++;
93: item->next = a->head;
94: a->head = item;
95: }
96:
97: /* Graphics stuff begins here */
98: #define CLIPRECT_SIZE 40
99: #define LAYER_SIZE 160
100: #define LINFO_SIZE 102
101:
102: static uaecptr gfxbase, layersbase;
103:
104: static void do_LockLayer(uaecptr layer)
105: {
106: #if 0 /* Later.. */
107: uaecptr sigsem = layer + 72;
108: m68k_areg(regs, 0) = sigsem;
109: CallLib(get_long(4), -564);
110: #else
111: m68k_areg(regs, 1) = layer;
112: CallLib(layersbase, -96);
113: #endif
114: }
115:
116: static void do_UnlockLayer(uaecptr layer)
117: {
118: m68k_areg(regs, 0) = layer;
119: CallLib(layersbase, -102);
120: }
121:
122: static uae_u32 gfxlibname, layerslibname;
1.1.1.2 root 123:
124: struct Rectangle {
125: int MinX, MinY, MaxX, MaxY;
126: };
1.1 root 127:
1.1.1.3 root 128: static int GFX_PointInRectangle(uaecptr rect, int x, int y)
1.1 root 129: {
1.1.1.3 root 130: uae_s16 minx = get_word(rect);
131: uae_s16 miny = get_word(rect+2);
132: uae_s16 maxx = get_word(rect+4);
133: uae_s16 maxy = get_word(rect+6);
134:
1.1 root 135: if (x < minx || x > maxx || y < miny || y > maxy)
136: return 0;
137: return 1;
138: }
139:
1.1.1.2 root 140: static int GFX_RectContainsRect(struct Rectangle *r1, struct Rectangle *r2)
141: {
142: return (r2->MinX >= r1->MinX && r2->MaxX <= r1->MaxX
143: && r2->MinY >= r1->MinY && r2->MaxY <= r1->MaxY);
144: }
145:
1.1.1.3 root 146: static struct Rectangle *GFX_RectFA(struct Rectangle *rp, uaecptr rect)
1.1.1.2 root 147: {
1.1.1.3 root 148: rp->MinX = (uae_s16)get_word(rect);
149: rp->MinY = (uae_s16)get_word(rect+2);
150: rp->MaxX = (uae_s16)get_word(rect+4);
151: rp->MaxY = (uae_s16)get_word(rect+6);
1.1.1.2 root 152: return rp;
153: }
154:
1.1.1.3 root 155: static int GFX_Bitmap_WritePixel(uaecptr bitmap, int x, int y, uaecptr rp)
1.1 root 156: {
157: int i, offs;
158: unsigned int bpr = get_word (bitmap);
159: unsigned int rows = get_word (bitmap + 2);
1.1.1.3 root 160: uae_u16 mask;
1.1 root 161:
1.1.1.3 root 162: uae_u8 planemask = get_byte(rp + 24);
163: uae_u8 fgpen = get_byte(rp + 25);
164: uae_u8 bgpen = get_byte(rp + 26);
165: uae_u8 drmd = get_byte(rp + 28);
166: uae_u8 pen = drmd & 4 ? bgpen : fgpen;
1.1 root 167:
168: if (x < 0 || y < 0 || x >= 8*bpr || y >= rows)
169: return -1;
1.1.1.3 root 170:
1.1 root 171: offs = y*bpr + (x & ~15)/8;
172:
173: for (i = 0; i < get_byte (bitmap + 5); i++) {
1.1.1.3 root 174: uaecptr planeptr;
175: uae_u16 data;
1.1 root 176:
177: if ((planemask & (1 << i)) == 0)
178: continue;
179:
180: planeptr = get_long(bitmap + 8 + i*4);
181: data = get_word(planeptr + offs);
1.1.1.3 root 182:
1.1 root 183: mask = 0x8000 >> (x & 15);
1.1.1.3 root 184:
1.1 root 185: if (drmd & 2) {
186: if ((pen & (1 << i)) != 0)
187: data ^=mask;
188: } else {
189: data &= ~mask;
190: if ((pen & (1 << i)) != 0)
191: data |= mask;
1.1.1.3 root 192: }
1.1 root 193: put_word(planeptr + offs, data);
194: }
195: return 0;
196: }
197:
1.1.1.3 root 198: int GFX_WritePixel(uaecptr rp, int x, int y)
1.1 root 199: {
1.1.1.3 root 200: int v;
201: uaecptr layer = get_long(rp);
202: uaecptr bitmap = get_long(rp + 4);
203: uaecptr cliprect;
1.1 root 204: int x2, y2;
205:
206: if (bitmap == 0) {
1.1.1.8 root 207: write_log ("bogus RastPort in WritePixel\n");
1.1 root 208: return -1;
209: }
210:
211: /* Easy case first */
212: if (layer == 0) {
213: return GFX_Bitmap_WritePixel(bitmap, x, y, rp);
214: }
1.1.1.3 root 215: do_LockLayer(layer);
1.1 root 216: /*
217: * Now, in theory we ought to obtain the semaphore.
218: * Since we don't, the programs will happily write into the raster
219: * even though we are currently moving the window around.
220: * Not good.
221: */
1.1.1.3 root 222:
223: x2 = x + (uae_s16)get_word(layer + 16);
224: y2 = y + (uae_s16)get_word(layer + 18);
225:
226: if (!GFX_PointInRectangle (layer + 16, x2, y2)) {
227: do_UnlockLayer(layer);
1.1 root 228: return -1;
1.1.1.3 root 229: }
1.1 root 230: /* Find the right ClipRect */
231: cliprect = get_long(layer + 8);
232: while (cliprect != 0 && !GFX_PointInRectangle (cliprect + 16, x2, y2))
233: cliprect = get_long(cliprect);
234: if (cliprect == 0) {
235: /* Don't complain: The "Dots" demo does this all the time. I
236: * suppose if we can't find a ClipRect, we aren't supposed to draw
237: * the dot.
238: */
1.1.1.8 root 239: /*write_log ("Weirdness in WritePixel\n");*/
1.1.1.3 root 240: v = -1;
241: } else if (get_long(cliprect + 8) == 0) {
242: v = GFX_Bitmap_WritePixel(bitmap, x2, y2, rp);
243: } else if (get_long(cliprect + 12) == 0) {
244: /* I don't really know what to do here... */
245: v = 0;
246: } else {
247: /* This appears to be normal for smart refresh layers which are obscured */
248: v = GFX_Bitmap_WritePixel (get_long(cliprect + 12), x2 - (uae_s16)get_word(cliprect + 16),
249: y2 - (uae_s16)get_word(cliprect + 18), rp);
1.1 root 250: }
1.1.1.3 root 251: do_UnlockLayer(layer);
252: return v;
1.1 root 253: }
254:
255:
1.1.1.3 root 256: static uae_u32 gfxl_WritePixel(void) { return GFX_WritePixel(m68k_areg(regs, 1), (uae_s16)m68k_dreg(regs, 0), (uae_s16)m68k_dreg(regs, 1)); }
1.1 root 257:
1.1.1.3 root 258: static uae_u32 gfxl_BltClear(void)
1.1 root 259: {
1.1.1.3 root 260: uaecptr mem=m68k_areg(regs, 1);
261: uae_u8 *mptr = chipmem_bank.xlateaddr(m68k_areg(regs, 1));
262: uae_u32 count=m68k_dreg(regs, 0);
263: uae_u32 flags=m68k_dreg(regs, 1);
1.1 root 264: unsigned int i;
1.1.1.3 root 265: uae_u32 pattern;
1.1 root 266:
267: if ((flags & 2) == 2){
268: /* count is given in Rows / Bytes per row */
269: count=(count & 0xFFFF) * (count >> 16);
270: }
271:
272: if ((mem & 1) != 0 || (count & 1) != 0)
1.1.1.8 root 273: write_log ("gfx: BltClear called with odd parameters\n");
1.1.1.3 root 274:
1.1 root 275: /* Bit 2 set means use pattern (V36+ only, but we might as well emulate
276: * it always) */
277: if ((flags & 4) == 0)
278: pattern = 0;
279: else
1.1.1.2 root 280: pattern= ((flags >> 16) & 0xFFFF) | (flags & 0xFFFF0000ul);
1.1 root 281:
282: if ((pattern & 0xFF) == ((pattern >> 8) & 0xFF)) {
283: memset(mptr, pattern, count);
284: return 0;
285: }
286:
1.1.1.3 root 287: for(i = 0; i < count; i += 4)
1.1 root 288: chipmem_bank.lput(mem+i, pattern);
1.1.1.3 root 289:
1.1 root 290: if ((count & 3) != 0)
291: chipmem_bank.wput(mem + i - 4, pattern);
292:
293: return 0;
1.1.1.3 root 294: }
1.1 root 295:
1.1.1.3 root 296: static uae_u32 gfxl_BltBitmap(void)
1.1 root 297: {
1.1.1.3 root 298: uaecptr srcbitmap = m68k_areg(regs, 0), dstbitmap = m68k_areg(regs, 1);
299: int srcx = (uae_s16)m68k_dreg(regs, 0), srcy = (uae_s16)m68k_dreg(regs, 1);
300: int dstx = (uae_s16)m68k_dreg(regs, 2), dsty = (uae_s16)m68k_dreg(regs, 3);
301: int sizex = (uae_s16)m68k_dreg(regs, 4), sizey = (uae_s16)m68k_dreg(regs, 5);
302: uae_u8 minterm = (uae_u8)m68k_dreg(regs, 6), mask = m68k_dreg(regs, 7);
303: return 0; /* sam: a return was missing here ! */
1.1 root 304: }
305:
1.1.1.3 root 306: static uaecptr amiga_malloc(int len)
1.1 root 307: {
1.1.1.2 root 308: m68k_dreg(regs, 0) = len;
309: m68k_dreg(regs, 1) = 1; /* MEMF_PUBLIC */
1.1 root 310: return CallLib(get_long(4), -198); /* AllocMem */
311: }
312:
1.1.1.3 root 313: static void amiga_free(uaecptr addr, int len)
1.1 root 314: {
1.1.1.2 root 315: m68k_areg(regs, 1) = addr;
316: m68k_dreg(regs, 0) = len;
1.1 root 317: CallLib(get_long(4), -210); /* FreeMem */
318: }
319:
320: /*
321: * Region handling code
1.1.1.3 root 322: *
1.1.1.2 root 323: * General ideas stolen from xc/verylongpath/miregion.c
1.1 root 324: *
325: * The Clear code is untested. And and Or seem to work, Xor is only used
326: * by the 1.3 Prefs program and seems to work, too.
327: */
328:
329: struct RegionRectangle {
330: struct RegionRectangle *Next,*Prev;
331: struct Rectangle bounds;
332: };
333:
334: struct Region {
335: struct Rectangle bounds;
336: struct RegionRectangle *RegionRectangle;
337: };
338:
339: struct RectList {
340: int count;
341: int space;
342: struct Rectangle bounds;
343: struct Rectangle *rects;
344: };
345:
346: struct BandList {
347: int count;
348: int space;
349: int *miny, *maxy;
350: };
351:
352: static void init_bandlist(struct BandList *bl)
353: {
354: bl->count = 0;
355: bl->space = 20;
356: bl->miny = (int *)malloc(20*sizeof(int));
357: bl->maxy = (int *)malloc(20*sizeof(int));
358: }
359:
1.1.1.3 root 360: static void dup_bandlist(struct BandList *to, struct BandList *from)
361: {
362: to->count = from->count;
363: to->space = to->count+4;
364: to->miny = (int *)malloc (to->space*sizeof(int));
365: to->maxy = (int *)malloc (to->space*sizeof(int));
366: memcpy(to->miny, from->miny, to->count*sizeof(int));
367: memcpy(to->maxy, from->maxy, to->count*sizeof(int));
368: }
369:
1.1.1.5 root 370: STATIC_INLINE void add_band(struct BandList *bl, int miny, int maxy, int pos)
1.1 root 371: {
372: if (bl->count == bl->space) {
373: bl->space += 20;
1.1.1.3 root 374: bl->miny = (int *)realloc(bl->miny, bl->space*sizeof(int));
375: bl->maxy = (int *)realloc(bl->maxy, bl->space*sizeof(int));
1.1 root 376: }
377: memmove(bl->miny + pos + 1, bl->miny + pos, (bl->count - pos) * sizeof(int));
378: memmove(bl->maxy + pos + 1, bl->maxy + pos, (bl->count - pos) * sizeof(int));
379: bl->count++;
380: bl->miny[pos] = miny;
381: bl->maxy[pos] = maxy;
382: }
383:
384: static void init_rectlist(struct RectList *rl)
385: {
386: rl->count = 0;
387: rl->space = 100;
388: rl->bounds.MinX = rl->bounds.MinY = rl->bounds.MaxX = rl->bounds.MaxY = 0;
389: rl->rects = (struct Rectangle *)malloc(100*sizeof(struct Rectangle));
390: }
391:
1.1.1.3 root 392: static void dup_rectlist(struct RectList *to, struct RectList *from)
393: {
394: to->count = from->count;
395: to->space = to->count+4;
396: to->bounds = from->bounds;
397: to->rects = (struct Rectangle *)malloc (to->space*sizeof(struct Rectangle));
398: memcpy(to->rects, from->rects, to->count*sizeof(struct Rectangle));
399: }
400:
1.1.1.5 root 401: STATIC_INLINE void add_rect(struct RectList *rl, struct Rectangle r)
1.1 root 402: {
403: if (rl->count == 0)
404: rl->bounds = r;
405: else {
406: if (r.MinX < rl->bounds.MinX)
407: rl->bounds.MinX = r.MinX;
408: if (r.MinY < rl->bounds.MinY)
409: rl->bounds.MinY = r.MinY;
410: if (r.MaxX > rl->bounds.MaxX)
411: rl->bounds.MaxX = r.MaxX;
412: if (r.MaxY > rl->bounds.MaxY)
413: rl->bounds.MaxY = r.MaxY;
414: }
415: if (rl->count == rl->space) {
416: rl->space += 100;
1.1.1.3 root 417: rl->rects = (struct Rectangle *)realloc(rl->rects, rl->space*sizeof(struct Rectangle));
1.1 root 418: }
419: rl->rects[rl->count++] = r;
420: }
421:
1.1.1.5 root 422: STATIC_INLINE void rem_rect(struct RectList *rl, int num)
1.1 root 423: {
424: rl->count--;
425: if (num == rl->count)
426: return;
427: rl->rects[num] = rl->rects[rl->count];
428: }
429:
430: static void free_rectlist(struct RectList *rl)
431: {
432: free(rl->rects);
433: }
434:
435: static void free_bandlist(struct BandList *bl)
436: {
437: free(bl->miny);
438: free(bl->maxy);
439: }
440:
441: static int regionrect_cmpfn(const void *a, const void *b)
442: {
443: struct Rectangle *ra = (struct Rectangle *)a;
444: struct Rectangle *rb = (struct Rectangle *)b;
1.1.1.3 root 445:
1.1 root 446: if (ra->MinY < rb->MinY)
447: return -1;
448: if (ra->MinY > rb->MinY)
449: return 1;
450: if (ra->MinX < rb->MinX)
451: return -1;
452: if (ra->MinX > rb->MinX)
453: return 1;
454: if (ra->MaxX < rb->MaxX)
455: return -1;
456: return 1;
457: }
458:
1.1.1.5 root 459: STATIC_INLINE int min(int x, int y)
1.1 root 460: {
461: return x < y ? x : y;
462: }
463:
1.1.1.5 root 464: STATIC_INLINE int max(int x, int y)
1.1 root 465: {
466: return x > y ? x : y;
467: }
468:
1.1.1.3 root 469: static void add_rect_to_bands(struct BandList *bl, struct Rectangle *rect)
1.1 root 470: {
1.1.1.3 root 471: int j;
472: struct Rectangle tmpr = *rect;
1.1 root 473:
1.1.1.3 root 474: for (j = 0; j < bl->count; j++) {
475: /* Is the current band before the rectangle? */
476: if (bl->maxy[j] < tmpr.MinY)
477: continue;
478: /* Band already present? */
479: if (bl->miny[j] == tmpr.MinY && bl->maxy[j] == tmpr.MaxY)
480: break;
481: /* Completely new band? Add it */
482: if (bl->miny[j] > tmpr.MaxY) {
483: add_band(bl, tmpr.MinY, tmpr.MaxY, j);
484: break;
485: }
486: /* Now we know that the bands are overlapping.
487: * See whether they match in one point */
488: if (bl->miny[j] == tmpr.MinY) {
489: int t;
490: if (bl->maxy[j] < tmpr.MaxY) {
491: /* Rectangle exceeds band */
492: tmpr.MinY = bl->maxy[j]+1;
1.1 root 493: continue;
494: }
1.1.1.3 root 495: /* Rectangle splits band */
496: t = bl->maxy[j];
497: bl->maxy[j] = tmpr.MaxY;
498: tmpr.MinY = bl->maxy[j] + 1;
499: tmpr.MaxY = t;
500: continue;
501: } else if (bl->maxy[j] == tmpr.MaxY) {
502: int t;
1.1 root 503: if (bl->miny[j] > tmpr.MinY) {
1.1.1.3 root 504: /* Rectangle exceeds band */
505: t = bl->miny[j];
506: bl->miny[j] = tmpr.MinY;
507: bl->maxy[j] = t-1;
508: tmpr.MinY = t;
509: continue;
1.1 root 510: }
1.1.1.3 root 511: /* Rectangle splits band */
512: bl->maxy[j] = tmpr.MinY - 1;
1.1 root 513: continue;
514: }
1.1.1.3 root 515: /* Bands overlap and match in no points. Get a new band and align */
516: if (bl->miny[j] > tmpr.MinY) {
517: /* Rectangle begins before band, so make a new band before
518: * and adjust rectangle */
519: add_band(bl, tmpr.MinY, bl->miny[j] - 1, j);
520: tmpr.MinY = bl->miny[j+1];
521: } else {
522: /* Rectangle begins in band */
523: add_band(bl, bl->miny[j], tmpr.MinY - 1, j);
524: bl->miny[j+1] = tmpr.MinY;
525: }
526: continue;
527: }
528: if (j == bl->count)
529: add_band(bl, tmpr.MinY, tmpr.MaxY, j);
530: }
531:
532: static void region_addbands(struct RectList *rl, struct BandList *bl)
533: {
534: int i,j;
535:
536: for (i = 0; i < rl->count; i++) {
537: add_rect_to_bands(bl, rl->rects + i);
538: }
539: }
540:
541: static void merge_bands(struct BandList *dest, struct BandList *src)
542: {
543: int i;
544: for (i = 0; i < src->count; i++) {
545: struct Rectangle tmp;
546: tmp.MinY = src->miny[i];
547: tmp.MaxY = src->maxy[i];
548: add_rect_to_bands(dest, &tmp);
1.1 root 549: }
550: }
551:
552: static void region_splitrects_band(struct RectList *rl, struct BandList *bl)
553: {
554: int i,j;
555: for (i = 0; i < rl->count; i++) {
556: for (j = 0; j < bl->count; j++) {
557: if (bl->miny[j] == rl->rects[i].MinY && bl->maxy[j] == rl->rects[i].MaxY)
558: break;
559: if (rl->rects[i].MinY > bl->maxy[j])
560: continue;
561: if (bl->miny[j] == rl->rects[i].MinY) {
562: struct Rectangle tmpr;
563: tmpr.MinX = rl->rects[i].MinX;
564: tmpr.MaxX = rl->rects[i].MaxX;
565: tmpr.MinY = bl->maxy[j] + 1;
566: tmpr.MaxY = rl->rects[i].MaxY;
567: add_rect(rl, tmpr); /* will be processed later */
568: rl->rects[i].MaxY = bl->maxy[j];
569: break;
570: }
1.1.1.8 root 571: write_log ("Foo..\n");
1.1 root 572: }
573: }
574: qsort(rl->rects, rl->count, sizeof (struct Rectangle), regionrect_cmpfn);
575: }
576:
577: static void region_coalesce_rects(struct RectList *rl, int do_2nd_pass)
578: {
579: int i,j;
580:
581: /* First pass: Coalesce horizontally */
582: for (i = j = 0; i < rl->count;) {
583: int offs = 1;
584: while (i + offs < rl->count) {
585: if (rl->rects[i].MinY != rl->rects[i+offs].MinY
586: || rl->rects[i].MaxY != rl->rects[i+offs].MaxY
587: || rl->rects[i].MaxX+1 < rl->rects[i+offs].MinX)
588: break;
589: rl->rects[i].MaxX = rl->rects[i+offs].MaxX;
590: offs++;
591: }
592: rl->rects[j++] = rl->rects[i];
593: i += offs;
594: }
595: rl->count = j;
1.1.1.3 root 596:
1.1 root 597: if (!do_2nd_pass)
598: return;
1.1.1.3 root 599:
1.1 root 600: /* Second pass: Coalesce bands */
601: for (i = 0; i < rl->count;) {
602: int match = 0;
603: for (j = i + 1; j < rl->count; j++)
604: if (rl->rects[i].MinY != rl->rects[j].MinY)
605: break;
606: if (j < rl->count && rl->rects[i].MaxY + 1 == rl->rects[j].MinY) {
607: int k;
608: match = 1;
609: for (k = 0; i+k < j; k++) {
610: if (j+k >= rl->count
611: || rl->rects[j+k].MinY != rl->rects[j].MinY)
612: {
613: match = 0; break;
614: }
615: if (rl->rects[i+k].MinX != rl->rects[j+k].MinX
616: || rl->rects[i+k].MaxX != rl->rects[j+k].MaxX)
617: {
618: match = 0;
619: break;
620: }
621: }
622: if (j+k < rl->count && rl->rects[j+k].MinY == rl->rects[j].MinY)
623: match = 0;
624: if (match) {
625: for (k = 0; i+k < j; k++)
626: rl->rects[i+k].MaxY = rl->rects[j].MaxY;
627: memmove(rl->rects + j, rl->rects + j + k, (rl->count - j - k)*sizeof(struct Rectangle));
628: rl->count -= k;
629: }
630: }
631: if (!match)
632: i = j;
633: }
634: }
635:
1.1.1.3 root 636: static int copy_rects (uaecptr region, struct RectList *rl)
1.1 root 637: {
1.1.1.3 root 638: uaecptr regionrect;
1.1 root 639: int numrects = 0;
640: struct Rectangle b;
641: regionrect = get_long(region+8);
642: b.MinX = get_word(region);
643: b.MinY = get_word(region+2);
644: b.MaxX = get_word(region+4);
645: b.MaxY = get_word(region+6);
1.1.1.3 root 646:
1.1 root 647: while (regionrect != 0) {
648: struct Rectangle tmpr;
1.1.1.3 root 649:
650: tmpr.MinX = (uae_s16)get_word(regionrect+8) + b.MinX;
651: tmpr.MinY = (uae_s16)get_word(regionrect+10) + b.MinY;
652: tmpr.MaxX = (uae_s16)get_word(regionrect+12) + b.MinX;
653: tmpr.MaxY = (uae_s16)get_word(regionrect+14) + b.MinY;
1.1 root 654: add_rect(rl, tmpr);
655: regionrect = get_long(regionrect);
656: numrects++;
657: }
658: return numrects;
659: }
660:
1.1.1.3 root 661: static int rect_in_region(struct RectList *rl, struct Rectangle *r)
662: {
663: int i;
664: int miny = r->MinY;
665:
666: for (i = 0; i < rl->count; i++) {
667: int j;
668: if (rl->rects[i].MaxY < miny)
669: continue;
670: if (rl->rects[i].MinY > miny)
671: break;
672: if (rl->rects[i].MaxX < r->MinX)
673: continue;
674: if (rl->rects[i].MinX > r->MaxX)
675: break;
676: /* Overlap! */
677: j = i;
678: for (;;) {
679: if (rl->rects[j].MaxX > r->MaxX) {
680: miny = rl->rects[i].MaxY + 1;
681: break;
682: }
683: j++;
684: if (j == rl->count)
685: break;
686: if (rl->rects[j].MinX != rl->rects[j-1].MaxX+1)
687: break;
688: if (rl->rects[i].MinY != rl->rects[j].MinY)
689: break;
690: }
691: if (miny <= rl->rects[i].MaxY)
692: break;
693: }
694: return 0;
695: }
696:
1.1 root 697: typedef void (*regionop)(struct RectList *,struct RectList *,struct RectList *);
698:
699: static void region_do_ClearRegionRegion(struct RectList *rl1,struct RectList *rl2,
700: struct RectList *rl3)
701: {
702: int i,j;
703:
704: for (i = j = 0; i < rl2->count && j < rl1->count;) {
705: struct Rectangle tmpr;
706:
707: while ((rl1->rects[j].MinY < rl2->rects[i].MinY
708: || (rl1->rects[j].MinY == rl2->rects[i].MinY
709: && rl1->rects[j].MaxX < rl2->rects[i].MinX))
710: && j < rl1->count)
711: j++;
712: if (j >= rl1->count)
713: break;
714: while ((rl1->rects[j].MinY > rl2->rects[i].MinY
715: || (rl1->rects[j].MinY == rl2->rects[i].MinY
716: && rl1->rects[j].MinX > rl2->rects[i].MaxX))
717: && i < rl2->count)
718: {
719: add_rect(rl3, rl2->rects[i]);
720: i++;
721: }
722: if (i >= rl2->count)
723: break;
1.1.1.3 root 724:
1.1 root 725: tmpr = rl2->rects[i];
1.1.1.3 root 726:
1.1 root 727: while (i < rl2->count && j < rl1->count
728: && rl1->rects[j].MinY == tmpr.MinY
729: && rl2->rects[i].MinY == tmpr.MinY
730: && rl1->rects[j].MinX <= rl2->rects[i].MaxX
731: && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
732: {
733: int oldmin = tmpr.MinX;
734: int oldmax = tmpr.MaxX;
735: if (tmpr.MinX < rl1->rects[j].MinX) {
736: tmpr.MaxX = rl1->rects[j].MinX - 1;
737: add_rect(rl3, tmpr);
738: }
739: if (oldmax <= rl1->rects[j].MaxX) {
740: i++;
741: if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY)
742: tmpr = rl2->rects[i];
743: } else {
744: tmpr.MinX = rl1->rects[j].MaxX + 1;
745: tmpr.MaxX = oldmax;
746: j++;
747: }
748: }
749: }
750: for(; i < rl2->count; i++)
751: add_rect(rl3, rl2->rects[i]);
752: }
753:
754: static void region_do_AndRegionRegion(struct RectList *rl1,struct RectList *rl2,
755: struct RectList *rl3)
756: {
757: int i,j;
758:
759: for (i = j = 0; i < rl2->count && j < rl1->count;) {
760: while ((rl1->rects[j].MinY < rl2->rects[i].MinY
761: || (rl1->rects[j].MinY == rl2->rects[i].MinY
762: && rl1->rects[j].MaxX < rl2->rects[i].MinX))
763: && j < rl1->count)
764: j++;
765: if (j >= rl1->count)
766: break;
767: while ((rl1->rects[j].MinY > rl2->rects[i].MinY
768: || (rl1->rects[j].MinY == rl2->rects[i].MinY
769: && rl1->rects[j].MinX > rl2->rects[i].MaxX))
770: && i < rl2->count)
771: i++;
772: if (i >= rl2->count)
773: break;
774: if (rl1->rects[j].MinY == rl2->rects[i].MinY
775: && rl1->rects[j].MinX <= rl2->rects[i].MaxX
776: && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
777: {
778: /* We have an intersection! */
779: struct Rectangle tmpr;
780: tmpr = rl2->rects[i];
781: if (tmpr.MinX < rl1->rects[j].MinX)
782: tmpr.MinX = rl1->rects[j].MinX;
783: if (tmpr.MaxX > rl1->rects[j].MaxX)
784: tmpr.MaxX = rl1->rects[j].MaxX;
785: add_rect(rl3, tmpr);
786: if (rl1->rects[j].MaxX == rl2->rects[i].MaxX)
787: i++, j++;
788: else if (rl1->rects[j].MaxX > rl2->rects[i].MaxX)
789: i++;
790: else
791: j++;
792: }
793: }
794: }
795:
796: static void region_do_OrRegionRegion(struct RectList *rl1,struct RectList *rl2,
797: struct RectList *rl3)
798: {
799: int i,j;
800:
801: for (i = j = 0; i < rl2->count && j < rl1->count;) {
802: while ((rl1->rects[j].MinY < rl2->rects[i].MinY
803: || (rl1->rects[j].MinY == rl2->rects[i].MinY
804: && rl1->rects[j].MaxX < rl2->rects[i].MinX))
805: && j < rl1->count)
806: {
807: add_rect(rl3, rl1->rects[j]);
808: j++;
809: }
810: if (j >= rl1->count)
811: break;
812: while ((rl1->rects[j].MinY > rl2->rects[i].MinY
813: || (rl1->rects[j].MinY == rl2->rects[i].MinY
814: && rl1->rects[j].MinX > rl2->rects[i].MaxX))
815: && i < rl2->count)
816: {
817: add_rect(rl3, rl2->rects[i]);
818: i++;
819: }
820: if (i >= rl2->count)
821: break;
822: if (rl1->rects[j].MinY == rl2->rects[i].MinY
823: && rl1->rects[j].MinX <= rl2->rects[i].MaxX
824: && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
825: {
826: /* We have an intersection! */
827: struct Rectangle tmpr;
828: tmpr = rl2->rects[i];
829: if (tmpr.MinX > rl1->rects[j].MinX)
830: tmpr.MinX = rl1->rects[j].MinX;
831: if (tmpr.MaxX < rl1->rects[j].MaxX)
832: tmpr.MaxX = rl1->rects[j].MaxX;
833: i++; j++;
834: for (;;) {
835: int cont = 0;
836: if (j < rl1->count && rl1->rects[j].MinY == tmpr.MinY
837: && tmpr.MaxX+1 >= rl1->rects[j].MinX) {
838: if (tmpr.MaxX < rl1->rects[j].MaxX)
839: tmpr.MaxX = rl1->rects[j].MaxX;
840: j++; cont = 1;
841: }
842: if (i < rl2->count && rl2->rects[i].MinY == tmpr.MinY
843: && tmpr.MaxX+1 >= rl2->rects[i].MinX) {
844: if (tmpr.MaxX < rl2->rects[i].MaxX)
845: tmpr.MaxX = rl2->rects[i].MaxX;
846: i++; cont = 1;
847: }
848: if (!cont)
849: break;
850: }
851: add_rect(rl3, tmpr);
852: }
853: }
854: for(; i < rl2->count; i++)
855: add_rect(rl3, rl2->rects[i]);
856: for(; j < rl1->count; j++)
857: add_rect(rl3, rl1->rects[j]);
858: }
859:
860: static void region_do_XorRegionRegion(struct RectList *rl1,struct RectList *rl2,
861: struct RectList *rl3)
862: {
863: int i,j;
864:
865: for (i = j = 0; i < rl2->count && j < rl1->count;) {
866: struct Rectangle tmpr1, tmpr2;
867:
868: while ((rl1->rects[j].MinY < rl2->rects[i].MinY
869: || (rl1->rects[j].MinY == rl2->rects[i].MinY
870: && rl1->rects[j].MaxX < rl2->rects[i].MinX))
871: && j < rl1->count)
872: {
873: add_rect(rl3, rl1->rects[j]);
874: j++;
875: }
876: if (j >= rl1->count)
877: break;
878: while ((rl1->rects[j].MinY > rl2->rects[i].MinY
879: || (rl1->rects[j].MinY == rl2->rects[i].MinY
880: && rl1->rects[j].MinX > rl2->rects[i].MaxX))
881: && i < rl2->count)
882: {
883: add_rect(rl3, rl2->rects[i]);
884: i++;
885: }
886: if (i >= rl2->count)
887: break;
888:
889: tmpr2 = rl2->rects[i];
890: tmpr1 = rl1->rects[j];
1.1.1.3 root 891:
1.1 root 892: while (i < rl2->count && j < rl1->count
893: && rl1->rects[j].MinY == tmpr1.MinY
894: && rl2->rects[i].MinY == tmpr1.MinY
895: && rl1->rects[j].MinX <= rl2->rects[i].MaxX
896: && rl1->rects[j].MaxX >= rl2->rects[i].MinX)
897: {
898: int oldmin2 = tmpr2.MinX;
899: int oldmax2 = tmpr2.MaxX;
900: int oldmin1 = tmpr1.MinX;
901: int oldmax1 = tmpr1.MaxX;
902: int need_1 = 0, need_2 = 0;
903:
1.1.1.3 root 904: if (tmpr2.MinX > tmpr1.MinX && tmpr2.MaxX < tmpr1.MaxX)
1.1 root 905: {
906: /*
907: * ###########
908: * ****
909: */
910: tmpr1.MaxX = tmpr2.MinX - 1;
911: add_rect(rl3, tmpr1);
912: tmpr1.MaxX = oldmax1;
913: tmpr1.MinX = tmpr2.MaxX + 1;
914: add_rect(rl3, tmpr1);
915: need_2 = 1;
916: } else if (tmpr2.MinX > tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) {
917: /*
918: * ##########
919: * *********
920: */
921: tmpr1.MaxX = tmpr2.MinX - 1;
922: add_rect(rl3, tmpr1);
923: tmpr2.MinX = oldmax1 + 1;
924: add_rect(rl3, tmpr2);
925: need_1 = 1;
926: } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX < tmpr1.MaxX) {
927: /*
928: * ##########
929: * *********
930: */
931: tmpr2.MaxX = tmpr1.MinX - 1;
932: add_rect(rl3, tmpr2);
933: tmpr1.MinX = oldmax2 + 1;
934: add_rect(rl3, tmpr1);
935: need_2 = 1;
936: } else if (tmpr2.MinX < tmpr1.MinX && tmpr2.MaxX > tmpr1.MaxX) {
937: /*
938: * ###
939: * *********
940: */
941: tmpr2.MaxX = tmpr1.MinX - 1;
942: add_rect(rl3, tmpr2);
943: tmpr2.MaxX = oldmax2;
944: tmpr2.MinX = tmpr1.MaxX + 1;
945: add_rect(rl3, tmpr2);
946: need_1 = 1;
947: } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX < tmpr1.MaxX) {
948: /*
949: * #############
950: * *********
951: */
952: tmpr1.MinX = tmpr2.MaxX + 1;
953: need_2 = 1;
954: } else if (tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX > tmpr1.MaxX) {
955: /*
956: * #########
957: * *************
958: */
959: tmpr2.MinX = tmpr1.MaxX + 1;
960: need_1 = 1;
961: } else if (tmpr1.MinX < tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) {
962: /*
963: * #############
964: * *********
965: */
966: tmpr1.MaxX = tmpr2.MinX - 1;
967: add_rect(rl3, tmpr1);
968: need_2 = need_1 = 1;
969: } else if (tmpr1.MinX > tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX) {
970: /*
971: * #########
972: * *************
973: */
974: tmpr2.MaxX = tmpr1.MinX - 1;
975: add_rect(rl3, tmpr2);
976: need_2 = need_1 = 1;
977: } else {
978: assert(tmpr1.MinX == tmpr2.MinX && tmpr2.MaxX == tmpr1.MaxX);
979: need_1 = need_2 = 1;
980: }
981: if (need_1) {
982: j++;
983: if (j < rl1->count && rl1->rects[j].MinY == tmpr1.MinY)
984: tmpr1 = rl1->rects[j];
985: }
986: if (need_2) {
987: i++;
988: if (i < rl2->count && rl2->rects[i].MinY == tmpr2.MinY)
989: tmpr2 = rl2->rects[i];
990: }
991: }
992: }
993: for(; i < rl2->count; i++)
994: add_rect(rl3, rl2->rects[i]);
995: for(; j < rl1->count; j++)
996: add_rect(rl3, rl1->rects[j]);
997: }
998:
1.1.1.3 root 999: static uae_u32 gfxl_perform_regionop(regionop op, int with_rect)
1.1 root 1000: {
1001: int i,j,k;
1.1.1.3 root 1002: uaecptr reg1;
1003: uaecptr reg2;
1004: uaecptr tmp, rpp;
1.1 root 1005: struct RectList rl1, rl2, rl3;
1006: struct BandList bl;
1007:
1008: int retval = 0;
1009: int numrects2;
1.1.1.3 root 1010:
1.1 root 1011: init_rectlist(&rl1); init_rectlist(&rl2); init_rectlist(&rl3);
1012:
1013: if (with_rect) {
1014: struct Rectangle tmpr;
1.1.1.2 root 1015: reg2 = m68k_areg(regs, 0);
1.1 root 1016: numrects2 = copy_rects(reg2, &rl2);
1.1.1.2 root 1017: tmpr.MinX = get_word(m68k_areg(regs, 1));
1018: tmpr.MinY = get_word(m68k_areg(regs, 1) + 2);
1019: tmpr.MaxX = get_word(m68k_areg(regs, 1) + 4);
1020: tmpr.MaxY = get_word(m68k_areg(regs, 1) + 6);
1.1 root 1021: add_rect(&rl1, tmpr);
1022: } else {
1.1.1.2 root 1023: reg1 = m68k_areg(regs, 0);
1024: reg2 = m68k_areg(regs, 1);
1.1 root 1025:
1026: copy_rects(reg1, &rl1);
1027: numrects2 = copy_rects(reg2, &rl2);
1028: }
1029:
1030: init_bandlist(&bl);
1031: region_addbands(&rl1, &bl);
1032: region_addbands(&rl2, &bl);
1033: region_splitrects_band(&rl1, &bl);
1034: region_splitrects_band(&rl2, &bl);
1035: region_coalesce_rects(&rl1, 0);
1036: region_coalesce_rects(&rl2, 0);
1037:
1038: (*op)(&rl1, &rl2, &rl3);
1039: region_coalesce_rects(&rl3, 1);
1040:
1041: rpp = reg2 + 8;
1042: if (rl3.count < numrects2) {
1043: while (numrects2-- != rl3.count) {
1044: tmp = get_long(rpp);
1045: put_long(rpp, get_long(tmp));
1046: amiga_free(tmp, 16);
1047: }
1048: if (rl3.count > 0)
1049: put_long(get_long(rpp) + 4, rpp);
1050: } else if (rl3.count > numrects2) {
1051: while(numrects2++ != rl3.count) {
1.1.1.3 root 1052: uaecptr prev = get_long(rpp);
1.1 root 1053: tmp = amiga_malloc(16);
1054: if (tmp == 0)
1055: goto done;
1056: put_long(tmp, prev);
1057: put_long(tmp + 4, rpp);
1058: if (prev != 0)
1059: put_long(prev + 4, tmp);
1.1.1.3 root 1060: put_long(rpp, tmp);
1.1 root 1061: }
1062: }
1.1.1.3 root 1063:
1.1 root 1064: if (rl3.count > 0) {
1065: rpp = reg2 + 8;
1066: for (i = 0; i < rl3.count; i++) {
1.1.1.3 root 1067: uaecptr rr = get_long(rpp);
1.1 root 1068: put_word(rr+8, rl3.rects[i].MinX - rl3.bounds.MinX);
1069: put_word(rr+10, rl3.rects[i].MinY - rl3.bounds.MinY);
1070: put_word(rr+12, rl3.rects[i].MaxX - rl3.bounds.MinX);
1071: put_word(rr+14, rl3.rects[i].MaxY - rl3.bounds.MinY);
1072: rpp = rr;
1073: }
1074: if (get_long(rpp) != 0)
1.1.1.8 root 1075: write_log ("BUG\n");
1.1.1.3 root 1076: }
1.1 root 1077: put_word(reg2+0, rl3.bounds.MinX);
1078: put_word(reg2+2, rl3.bounds.MinY);
1079: put_word(reg2+4, rl3.bounds.MaxX);
1080: put_word(reg2+6, rl3.bounds.MaxY);
1081: retval = 1;
1082:
1083: done:
1084: free_rectlist(&rl1); free_rectlist(&rl2); free_rectlist(&rl3);
1.1.1.3 root 1085: free_bandlist(&bl);
1.1 root 1086:
1087: return retval;
1088: }
1089:
1.1.1.3 root 1090: static uae_u32 gfxl_AndRegionRegion(void)
1.1 root 1091: {
1092: return gfxl_perform_regionop(region_do_AndRegionRegion, 0);
1093: }
1.1.1.3 root 1094: static uae_u32 gfxl_XorRegionRegion(void)
1.1 root 1095: {
1096: return gfxl_perform_regionop(region_do_XorRegionRegion, 0);
1097: }
1.1.1.3 root 1098: static uae_u32 gfxl_OrRegionRegion(void)
1.1 root 1099: {
1100: return gfxl_perform_regionop(region_do_OrRegionRegion, 0);
1101: }
1102:
1.1.1.3 root 1103: static uae_u32 gfxl_ClearRectRegion(void)
1.1 root 1104: {
1105: return gfxl_perform_regionop(region_do_ClearRegionRegion, 1);
1106: }
1.1.1.3 root 1107: static uae_u32 gfxl_OrRectRegion(void)
1.1 root 1108: {
1109: return gfxl_perform_regionop(region_do_OrRegionRegion, 1);
1110: }
1111:
1.1.1.3 root 1112: static uae_u32 gfxl_AndRectRegion(void)
1.1 root 1113: {
1114: return gfxl_perform_regionop(region_do_AndRegionRegion, 1);
1115: }
1116:
1.1.1.3 root 1117: static uae_u32 gfxl_XorRectRegion(void)
1.1 root 1118: {
1119: return gfxl_perform_regionop(region_do_XorRegionRegion, 1);
1120: }
1121:
1122:
1.1.1.3 root 1123: /* Layers code */
1124:
1125: static uae_u32 LY_TryLockLayer(uaecptr layer)
1126: {
1127: uaecptr sigsem = layer + 72;
1128:
1129: m68k_areg(regs, 0) = sigsem;
1130: return CallLib(get_long(4), -576);
1131: }
1132:
1133: static void LY_LockLayer(uaecptr layer)
1134: {
1135: uaecptr sigsem = layer + 72;
1136:
1137: m68k_areg(regs, 0) = sigsem;
1138: CallLib(get_long(4), -564);
1139: }
1140:
1141: static void LY_UnlockLayer(uaecptr layer)
1142: {
1143: uaecptr sigsem = layer + 72;
1144:
1145: m68k_areg(regs, 0) = sigsem;
1146: CallLib(get_long(4), -570);
1147: }
1148:
1149: static void LY_LockLayerInfo(uaecptr li)
1150: {
1151: uaecptr sigsem = li + 24;
1152:
1153: m68k_areg(regs, 0) = sigsem;
1154: CallLib(get_long(4), -564);
1155: put_byte(li+91, get_byte(li+91)+1);
1156: }
1157:
1158: static void LY_UnlockLayerInfo(uaecptr li)
1159: {
1160: uaecptr sigsem = li + 24;
1161:
1162: put_byte(li+91, get_byte(li+91)-1);
1163: m68k_areg(regs, 0) = sigsem;
1164: CallLib(get_long(4), -570);
1165: }
1166:
1167: static void LY_LockLayers(uaecptr li)
1168: {
1169: uaecptr l = get_long (li);
1170: LY_LockLayerInfo(li);
1171: while (l != 0) {
1172: LY_LockLayer(l);
1173: l = get_long(l);
1174: }
1175: LY_UnlockLayerInfo(li);
1176: }
1177:
1178: static void LY_UnlockLayers(uaecptr li)
1179: {
1180: uaecptr l = get_long (li);
1181: LY_LockLayerInfo(li);
1182: while (l != 0) {
1183: LY_UnlockLayer(l);
1184: l = get_long(l);
1185: }
1186: LY_UnlockLayerInfo(li);
1187: }
1188:
1189: #define LAYER_CLUELESS 0x8000 /* Indicates we know nothing about the layer's regions. */
1190: #define LAYER_CR_CHANGED 0x4000 /* Indicates that the cliprects in Amiga memory need to be re-done */
1191: #define LAYER_REDO 0x2000 /* Indicates that we have regions, but they are bogus. */
1192:
1193: static uae_u32 layer_uniq = 1;
1194:
1195: struct MyLayerInfo {
1196: struct uniq_head head;
1197: uaecptr amigaos_linfo;
1198: uniq_list layer_list;
1199: };
1200:
1201: struct MyLayer {
1202: struct uniq_head head;
1203: uaecptr amigaos_layer, rastport;
1204: struct Rectangle bounds;
1205: struct RectList clipregion;
1206: struct RectList obscured;
1207: struct RectList visible;
1208: struct BandList big_bands; /* created by obscuring layers */
1209: struct BandList small_bands; /* big_bands + those from clipregion */
1210: struct RectList damage;
1211: struct BandList damage_bands;
1212: struct MyLayerInfo *mli;
1213: };
1214:
1215: static uniq_list MyLayerInfo_list = UNIQ_INIT;
1216:
1217: static void LY_InitLayers(uaecptr li)
1218: {
1219: memset (get_real_address(li), 0, 92);
1220: put_long(li + 0, 0); /* top layer */
1221: put_long(li+84, 0); /* uniq: */
1222: m68k_areg(regs, 0) = li + 24; CallLib(get_long(4), -558); /* InitSemaphore() */
1223: put_word(li+88, 0); /* flags (???) */
1224: put_byte(li+89, 0); /* fatten_count */
1225: /* @@@ How big can I assume the structure? What's all this 1.0/1.1 cruft? */
1226: }
1227:
1228: static void LY_FattenLayerInfo(uaecptr li)
1229: {
1230: struct MyLayerInfo *mli;
1231: int fatten_count = get_byte (li + 89);
1232: if (fatten_count == 0) {
1233: mli = (struct MyLayerInfo *)malloc(sizeof(struct MyLayerInfo));
1234: add_uniq(&MyLayerInfo_list, &mli->head, li + 84);
1235: init_uniq(&mli->layer_list);
1236: mli->amigaos_linfo = li;
1237: }
1238: put_byte (li + 89, fatten_count + 1);
1239: }
1240:
1241: static void LY_ThinLayerInfo(uaecptr li)
1242: {
1243: int fatten_count = get_byte (li + 89)-1;
1244: put_byte (li + 89, fatten_count);
1245: if (fatten_count == 0) {
1246: struct MyLayerInfo *mli = (struct MyLayerInfo *)find_and_rem_uniq(&MyLayerInfo_list, get_long(li+84));
1247: if (mli)
1248: free(mli);
1249: }
1250: }
1251:
1252: static void build_cliprect (struct MyLayer *l, struct Rectangle *bounds,
1253: int obscured, uaecptr *crp, uaecptr *prev)
1254: {
1255: uaecptr cr = get_long (*crp);
1256: if (cr == 0) {
1257: put_long (*crp, cr = amiga_malloc(CLIPRECT_SIZE));
1258: put_long (cr, 0);
1259: }
1260: *prev = cr;
1261: *crp = cr;
1262: put_word (cr + 16, bounds->MinX);
1263: put_word (cr + 18, bounds->MinY);
1264: put_word (cr + 20, bounds->MaxX);
1265: put_word (cr + 22, bounds->MaxY);
1266: put_long (cr + 8, obscured ? l->amigaos_layer : 0); /* cheat */
1267: put_long (cr + 12, 0); /* no smart refresh yet */
1268: }
1269:
1270: static void build_cliprects (struct MyLayer *l)
1271: {
1272: uaecptr layer = l->amigaos_layer;
1273: uaecptr cr = layer + 8;
1274: uaecptr prev = 0;
1275: uae_u16 flags = get_word(layer + 30);
1276: int i;
1277:
1278: if ((flags & LAYER_CR_CHANGED) == 0)
1279: return;
1280: put_word (layer + 30, flags & ~LAYER_CR_CHANGED);
1281: for (i = 0; i < l->obscured.count; i++) {
1282: build_cliprect (l, l->obscured.rects + i, 1, &cr, &prev);
1283: }
1284: for (i = 0; i < l->visible.count; i++) {
1285: build_cliprect (l, l->visible.rects + i, 1, &cr, &prev);
1286: }
1287: while ((prev = get_long (cr))) {
1288: put_long (cr, get_long (prev));
1289: amiga_free (prev, CLIPRECT_SIZE);
1290: }
1291: }
1292:
1293: static void propagate_clueless_redo (struct MyLayerInfo *mli)
1294: {
1295: /* For all CLUELESS layers, set the REDO bit for all layers below it that overlap it
1296: * and delete the data associated with them. */
1297: uaecptr current_l = get_long(mli->amigaos_linfo);
1298: while (current_l) {
1299: struct MyLayer *l = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(current_l + 24));
1300: if ((get_word(l->amigaos_layer + 32) & LAYER_CLUELESS) != 0) {
1301: uaecptr next_l = get_long(current_l);
1302: put_word(l->amigaos_layer + 32, get_word(l->amigaos_layer + 32) | LAYER_REDO);
1303: while (next_l) {
1304: struct MyLayer *l2 = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(next_l + 24));
1305: uae_u16 flags = get_word(l2->amigaos_layer + 32);
1306: if (l2->bounds.MinX <= l->bounds.MaxX && l->bounds.MinX <= l2->bounds.MaxX
1307: && l2->bounds.MinY <= l->bounds.MaxY && l->bounds.MinY <= l2->bounds.MaxY)
1308: put_word(l2->amigaos_layer + 32, flags | LAYER_REDO);
1309: if ((flags & (LAYER_REDO|LAYER_CLUELESS)) == 0) {
1310: free_rectlist(&l->obscured);
1311: free_rectlist(&l->visible);
1312: free_bandlist(&l->big_bands);
1313: free_bandlist(&l->small_bands);
1314: }
1315: next_l = get_long(next_l);
1316: }
1317: }
1318: current_l = get_long(current_l);
1319: }
1320: }
1321:
1322: static void redo_layers(struct MyLayerInfo *mli, uaecptr bm)
1323: {
1324: uaecptr current_l;
1325: struct RectList tmp_rl;
1326:
1327: propagate_clueless_redo(mli);
1328: current_l = get_long(mli->amigaos_linfo);
1329:
1330: while (current_l) {
1331: struct MyLayer *l = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(current_l + 24));
1332: uae_u16 flags = get_word(l->amigaos_layer + 32);
1333: if ((flags & LAYER_REDO) != 0) {
1334: uaecptr next_l = get_long(current_l+4);
1335: int have_rects = 0;
1336:
1337: init_rectlist(&l->obscured);
1338: init_bandlist(&l->big_bands);
1339: add_rect_to_bands(&l->big_bands, &l->bounds);
1340:
1341: while (next_l) {
1342: struct MyLayer *l2 = (struct MyLayer *)find_uniq(&mli->layer_list, get_long(next_l + 24));
1343: if (l2->visible.bounds.MinX <= l->bounds.MaxX && l->bounds.MinX <= l2->visible.bounds.MaxX
1344: && l2->visible.bounds.MinY <= l->bounds.MaxY && l->bounds.MinY <= l2->visible.bounds.MaxY
1345: && !rect_in_region (&l->obscured, &l2->visible.bounds))
1346: {
1347: add_rect_to_bands(&l->big_bands, &l2->visible.bounds);
1348: add_rect(&l->obscured, l2->visible.bounds);
1349: have_rects++;
1350: }
1351: next_l = get_long(next_l+4);
1352: }
1353: init_rectlist(&l->visible);
1354: init_rectlist(&tmp_rl);
1355: add_rect (&tmp_rl, l->bounds);
1356:
1357: region_splitrects_band(&l->obscured, &l->big_bands);
1358: region_splitrects_band(&tmp_rl, &l->big_bands);
1359: region_do_ClearRegionRegion(&l->obscured, &tmp_rl, &l->visible);
1360: flags |= LAYER_CR_CHANGED;
1361: }
1362: put_word (l->amigaos_layer + 32, flags & ~(LAYER_CLUELESS|LAYER_REDO));
1363: current_l = get_long(current_l);
1364: }
1365: }
1366:
1367: static struct MyLayer *LY_NewLayer(struct MyLayerInfo *mli, int x0, int x1, int y0, int y1,
1368: uae_u16 flags, uaecptr bm, uaecptr sbm)
1369: {
1370: struct MyLayer *l = (struct MyLayer *)malloc(sizeof (struct MyLayer));
1371: uaecptr layer = amiga_malloc(LAYER_SIZE);
1372: memset (get_real_address(layer), 0, LAYER_SIZE);
1373: l->amigaos_layer = layer;
1374:
1375: put_word(layer + 16, x0); /* bounds */
1376: put_word(layer + 18, y0);
1377: put_word(layer + 20, x1);
1378: put_word(layer + 22, y1);
1379: put_word(layer + 30, flags | LAYER_CLUELESS);
1380: put_long(layer + 32, flags & 4 ? sbm : 0); /* ClipRect */
1381: put_long(layer + 68, mli->amigaos_linfo);
1382: m68k_areg(regs, 0) = layer + 72; CallLib(get_long(4), -558); /* InitSemaphore() */
1383: add_uniq(&mli->layer_list, &l->head, layer + 24);
1384: l->mli = mli;
1385:
1386: l->bounds.MinX = x0;
1387: l->bounds.MaxX = x1;
1388: l->bounds.MinY = y0;
1389: l->bounds.MaxY = y1;
1390: return l;
1391: }
1392:
1393: static void LY_DeleteLayer(uaecptr layer)
1394: {
1395: uaecptr cr;
1396: struct MyLayer *l = (struct MyLayer *)find_and_rem_uniq(&l->mli->layer_list, get_long (layer + 24));
1397: /* Free ClipRects */
1398: while ((cr = get_long (l->amigaos_layer + 8))) {
1399: put_long (l->amigaos_layer + 8, get_long(cr));
1400: amiga_free(cr, CLIPRECT_SIZE);
1401: }
1402: amiga_free (l->amigaos_layer, LAYER_SIZE);
1403: free(l);
1404: }
1405:
1406: static uaecptr find_behindlayer_position(uaecptr li, uae_u16 flags)
1407: {
1408: uaecptr where = li;
1409: for (;;) {
1410: uaecptr other = get_long (where);
1411: /* End of list? */
1412: if (other == 0)
1413: break;
1414: /* Backdrop? */
1415: if ((get_word(other + 30) & 0x40) > (flags & 0x40))
1416: break;
1417: where = other;
1418: }
1419: return where;
1420: }
1421:
1422: static uaecptr LY_CreateLayer(uaecptr li, int x0, int x1, int y0, int y1,
1423: uae_u16 flags, uaecptr bm, uaecptr sbm, uaecptr where)
1424: {
1425: struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq(&MyLayerInfo_list, get_long (li + 84));
1426: struct MyLayer *l;
1427:
1428: LY_LockLayerInfo(li);
1429:
1430: l = LY_NewLayer(mli, x0, x1, y0, y1, flags, bm, sbm);
1431: /* Chain into list */
1432: put_long(l->amigaos_layer, get_long (where));
1433: put_long(l->amigaos_layer + 4, where == li ? 0 : where);
1434: if (get_long (where) != 0)
1435: put_long(get_long (where) + 4, l->amigaos_layer);
1436: put_long(where, l->amigaos_layer);
1437: redo_layers(mli, bm);
1438: build_cliprects(l);
1439: LY_UnlockLayerInfo(li);
1440: return l->amigaos_layer;
1441: }
1442:
1443: static void LY_DisposeLayerInfo(uaecptr li)
1444: {
1445: LY_ThinLayerInfo(li);
1446: amiga_free(li, LINFO_SIZE);
1447: }
1448:
1449: static uae_u32 layers_NewLayerInfo(void)
1450: {
1451: uaecptr li = amiga_malloc(LINFO_SIZE);
1452: LY_InitLayers(li);
1453: LY_FattenLayerInfo(li);
1454: return li;
1455: }
1456: static uae_u32 layers_InitLayers(void) { LY_InitLayers (m68k_areg (regs, 0)); return 0; }
1457: static uae_u32 layers_DisposeLayerInfo(void) { LY_DisposeLayerInfo (m68k_areg (regs, 0)); return 0; }
1458:
1459: static uae_u32 layers_FattenLayerInfo(void) { LY_FattenLayerInfo(m68k_areg(regs, 0)); return 0; }
1460: static uae_u32 layers_ThinLayerInfo(void) { LY_ThinLayerInfo(m68k_areg(regs, 0)); return 0; }
1461:
1462: static uae_u32 layers_CreateUpfrontLayer(void)
1463: {
1464: return LY_CreateLayer(m68k_areg(regs, 0), (uae_s32)m68k_dreg(regs, 0),
1465: (uae_s32)m68k_dreg(regs, 1), (uae_s32)m68k_dreg(regs, 2),
1466: (uae_s32)m68k_dreg(regs, 3),
1467: m68k_dreg(regs, 4),
1468: m68k_areg(regs, 1), m68k_areg(regs, 2), m68k_areg(regs, 0));
1469: }
1470: static uae_u32 layers_CreateBehindLayer(void)
1471: {
1472: return LY_CreateLayer(m68k_areg(regs, 0), (uae_s32)m68k_dreg(regs, 0),
1473: (uae_s32)m68k_dreg(regs, 1), (uae_s32)m68k_dreg(regs, 2),
1474: (uae_s32)m68k_dreg(regs, 3),
1475: m68k_dreg(regs, 4),
1476: m68k_areg(regs, 1), m68k_areg(regs, 2),
1477: find_behindlayer_position (m68k_areg(regs, 0), m68k_dreg(regs, 4)));
1478: }
1479: static uae_u32 layers_DeleteLayer(void) { LY_DeleteLayer (m68k_areg (regs, 1)); return 0; }
1480:
1481: static void LY_LockLayer1(uaecptr layer)
1482: {
1483: uaecptr li = get_long (layer + 68);
1484: struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq (&MyLayerInfo_list, get_long (li + 84));
1485: struct MyLayer *l = (struct MyLayer *)find_uniq (&mli->layer_list, get_long (layer + 24));
1486:
1487: LY_LockLayer(layer);
1488: build_cliprects (l);
1489: }
1490: static uae_u32 LY_TryLockLayer1(uaecptr layer)
1491: {
1492: uaecptr li = get_long (layer + 68);
1493: struct MyLayerInfo *mli = (struct MyLayerInfo *)find_uniq (&MyLayerInfo_list, get_long (li + 84));
1494: struct MyLayer *l = (struct MyLayer *)find_uniq (&mli->layer_list, get_long (layer + 24));
1495:
1496: if (!LY_TryLockLayer(layer))
1497: return 0;
1498: build_cliprects (l);
1499: return 1;
1500: }
1501: static uae_u32 gfx_TryLockLayer(void) { return LY_TryLockLayer1 (m68k_areg(regs, 5)); }
1502: static uae_u32 gfx_LockLayer(void) { LY_LockLayer1 (m68k_areg(regs, 5)); return 0; }
1503: static uae_u32 gfx_UnlockLayer(void) { LY_UnlockLayer(m68k_areg(regs, 5)); return 0; }
1504: static uae_u32 layers_LockLayer(void) { LY_LockLayer1 (m68k_areg(regs, 1)); return 0; }
1505: static uae_u32 layers_LockLayers(void) { LY_LockLayers(m68k_areg(regs, 0)); return 0; }
1506: static uae_u32 layers_LockLayerInfo(void) { LY_LockLayerInfo(m68k_areg(regs, 0)); return 0; }
1507: static uae_u32 layers_UnlockLayer(void) { LY_UnlockLayer(m68k_areg(regs, 0)); return 0; }
1508: static uae_u32 layers_UnlockLayers(void) { LY_UnlockLayers(m68k_areg(regs, 0)); return 0; }
1509: static uae_u32 layers_UnlockLayerInfo(void) { LY_UnlockLayerInfo(m68k_areg(regs, 0)); return 0; }
1510:
1511: static uae_u32 layers_ScrollLayer(void)
1512: {
1513: abort();
1514: }
1515:
1516: static uae_u32 layers_SizeLayer(void)
1517: {
1518: abort();
1519: }
1520:
1521: static uae_u32 layers_MoveLayer(void)
1522: {
1523: abort();
1524: }
1525:
1526: static uae_u32 layers_UpfrontLayer(void)
1527: {
1528: abort();
1529: }
1530:
1531: static uae_u32 layers_BehindLayer(void)
1532: {
1533: abort();
1534: }
1535:
1536: static uae_u32 layers_MoveLayerInFrontOf(void)
1537: {
1538: abort();
1539: }
1540:
1541: static uae_u32 layers_BeginUpdate(void)
1542: {
1543: return 1;
1544: }
1545:
1546: static uae_u32 layers_EndUpdate(void)
1547: {
1548: return 0;
1549: }
1550:
1551: static uae_u32 layers_WhichLayer(void)
1552: {
1553: abort();
1554: }
1555:
1556: static uae_u32 layers_InstallClipRegion(void)
1557: {
1558: return 0;
1559: }
1560:
1561: static uae_u32 layers_SwapBitsRastPortClipRect(void)
1562: {
1563: abort();
1564: }
1565:
1.1 root 1566: /*
1567: * Initialization
1568: */
1.1.1.3 root 1569: static uae_u32 gfxlib_init(void)
1.1 root 1570: {
1.1.1.3 root 1571: uae_u32 old_arr;
1572: uaecptr sysbase=m68k_areg(regs, 6);
1.1 root 1573: int i=0;
1574:
1575: /* Install new routines */
1.1.1.2 root 1576: m68k_dreg(regs, 0)=0;
1577: m68k_areg(regs, 1)=gfxlibname;
1.1 root 1578: gfxbase=CallLib(sysbase, -408); /* OpenLibrary */
1.1.1.2 root 1579: m68k_dreg(regs, 0)=0;
1580: m68k_areg(regs, 1)=layerslibname;
1581: layersbase=CallLib(sysbase, -408); /* OpenLibrary */
1582:
1.1.1.3 root 1583: libemu_InstallFunctionFlags(gfxl_WritePixel, gfxbase, -324, TRAPFLAG_EXTRA_STACK, "");
1584: libemu_InstallFunctionFlags(gfxl_BltClear, gfxbase, -300, 0, "");
1585: libemu_InstallFunctionFlags(gfxl_AndRegionRegion, gfxbase, -624, TRAPFLAG_EXTRA_STACK, "");
1586: libemu_InstallFunctionFlags(gfxl_OrRegionRegion, gfxbase, -612, TRAPFLAG_EXTRA_STACK, "");
1587: libemu_InstallFunctionFlags(gfxl_XorRegionRegion, gfxbase, -618, TRAPFLAG_EXTRA_STACK, "");
1588: libemu_InstallFunctionFlags(gfxl_AndRectRegion, gfxbase, -504, TRAPFLAG_EXTRA_STACK, "");
1589: libemu_InstallFunctionFlags(gfxl_OrRectRegion, gfxbase, -510, TRAPFLAG_EXTRA_STACK, "");
1590: libemu_InstallFunctionFlags(gfxl_XorRectRegion, gfxbase, -558, TRAPFLAG_EXTRA_STACK, "");
1591: libemu_InstallFunctionFlags(gfxl_ClearRectRegion, gfxbase, -522, TRAPFLAG_EXTRA_STACK, "");
1592:
1593: #if 0
1594: #define MAYBE_FUNCTION(a) NULL
1595: #else
1596: #define MAYBE_FUNCTION(a) (a)
1597: #endif
1598: #if 0
1599: libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_TryLockLayer), gfxbase, -654, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "AttemptLockLayerRom");
1600: libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_LockLayer), gfxbase, -432, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "LockLayerRom");
1601: libemu_InstallFunctionFlags(MAYBE_FUNCTION(gfx_UnlockLayer), gfxbase, -438, TRAPFLAG_EXTRA_STACK|TRAPFLAG_NO_RETVAL, "UnlockLayerRom");
1602:
1603: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_InitLayers), layersbase, -30, TRAPFLAG_EXTRA_STACK, "InitLayers");
1604: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_CreateUpfrontLayer), layersbase, -36, TRAPFLAG_EXTRA_STACK, "CreateUpfrontLayer");
1605: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_CreateBehindLayer), layersbase, -42, TRAPFLAG_EXTRA_STACK, "CreateBehindLayer");
1606: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UpfrontLayer), layersbase, -48, TRAPFLAG_EXTRA_STACK, "UpfrontLayer");
1607: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_BehindLayer), layersbase, -54, TRAPFLAG_EXTRA_STACK, "BehindLayer");
1608: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_MoveLayer), layersbase, -60, TRAPFLAG_EXTRA_STACK, "MoveLayer");
1609: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_SizeLayer), layersbase, -66, TRAPFLAG_EXTRA_STACK, "SizeLayer");
1610: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_ScrollLayer), layersbase, -72, TRAPFLAG_EXTRA_STACK, "ScrollLayer");
1611: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_BeginUpdate), layersbase, -78, TRAPFLAG_EXTRA_STACK, "BeginUpdate");
1612: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_EndUpdate), layersbase, -84, TRAPFLAG_EXTRA_STACK, "EndUpdate");
1613: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_DeleteLayer), layersbase, -90, TRAPFLAG_EXTRA_STACK, "DeleteLayer");
1614: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayer), layersbase, -96, TRAPFLAG_EXTRA_STACK, "LockLayer");
1615: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayer), layersbase, -102, TRAPFLAG_EXTRA_STACK, "UnlockLayer");
1616: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayers), layersbase, -108, TRAPFLAG_EXTRA_STACK, "LockLayers");
1617: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayers), layersbase, -114, TRAPFLAG_EXTRA_STACK, "UnlockLayers");
1618: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_LockLayerInfo), layersbase, -120, TRAPFLAG_EXTRA_STACK, "LockLayerInfo");
1619: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_SwapBitsRastPortClipRect), layersbase, -126, TRAPFLAG_EXTRA_STACK, "SwapBitsRastPortClipRect");
1620: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_WhichLayer), layersbase, -132, TRAPFLAG_EXTRA_STACK, "WhichLayer");
1621: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_UnlockLayerInfo), layersbase, -138, TRAPFLAG_EXTRA_STACK, "UnlockLayerInfo");
1622: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_NewLayerInfo), layersbase, -144, TRAPFLAG_EXTRA_STACK, "NewLayerInfo");
1623: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_DisposeLayerInfo), layersbase, -150, TRAPFLAG_EXTRA_STACK, "DisposeLayerInfo");
1624: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_FattenLayerInfo), layersbase, -156, TRAPFLAG_EXTRA_STACK, "FattenLayerInfo");
1625: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_ThinLayerInfo), layersbase, -162, TRAPFLAG_EXTRA_STACK, "ThinLayerInfo");
1626: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_MoveLayerInFrontOf), layersbase, -168, TRAPFLAG_EXTRA_STACK, "MoveLayerInFrontOf");
1627: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_InstallClipRegion), layersbase, -174, TRAPFLAG_EXTRA_STACK, "InstallClipRegion");
1628: #if 0
1629: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -180, TRAPFLAG_EXTRA_STACK, "MoveSizeLayer");
1630: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -186, TRAPFLAG_EXTRA_STACK, "CreateUpfrontHookLayer");
1631: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -192, TRAPFLAG_EXTRA_STACK, "CreateBehindHookLayer");
1632: libemu_InstallFunctionFlags(MAYBE_FUNCTION(layers_), layersbase, -198, TRAPFLAG_EXTRA_STACK, "InstallLayerHook");
1633: #endif
1634: #endif
1.1 root 1635: return 0;
1636: }
1637:
1.1.1.3 root 1638: /*
1639: * Install the gfx-library-replacement
1.1 root 1640: */
1641: void gfxlib_install(void)
1642: {
1.1.1.3 root 1643: uae_u32 begin, end, resname, resid;
1.1 root 1644: int i;
1.1.1.3 root 1645:
1.1.1.4 root 1646: if (! currprefs.use_gfxlib)
1647: return;
1.1.1.3 root 1648:
1.1.1.8 root 1649: write_log ("Warning: you enabled the graphics.library replacement with -g\n"
1.1.1.4 root 1650: "This may be buggy right now, and will not speed things up much.\n");
1.1 root 1651:
1.1.1.4 root 1652: resname = ds ("UAEgfxlib.resource");
1653: resid = ds ("UAE gfxlib 0.1");
1.1 root 1654:
1.1.1.4 root 1655: gfxlibname = ds ("graphics.library");
1656: layerslibname = ds ("layers.library");
1.1 root 1657:
1658: begin = here();
1.1.1.3 root 1659: dw(0x4AFC); /* RTC_MATCHuae_s16 */
1.1 root 1660: dl(begin); /* our start address */
1661: dl(0); /* Continue scan here */
1662: dw(0x0101); /* RTF_COLDSTART; Version 1 */
1663: dw(0x0805); /* NT_RESOURCE; pri 5 */
1664: dl(resname); /* name */
1665: dl(resid); /* ID */
1666: dl(here() + 4); /* Init area: directly after this */
1667:
1.1.1.3 root 1668: calltrap(deftrap2(gfxlib_init, TRAPFLAG_EXTRA_STACK, "")); dw(RTS);
1.1 root 1669:
1670: end = here();
1671: org(begin + 6);
1672: dl(end);
1673:
1674: org(end);
1675: }
1.1.1.3 root 1676: #else
1677:
1678: void gfxlib_install (void)
1679: {
1680: }
1681:
1682: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.