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