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