Annotation of uae/src/gfxlib.c, revision 1.1.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.