Annotation of uae/src/gfxlib.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.