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

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

unix.superglobalmegacorp.com

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