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

1.1     ! root        1:  /*
        !             2:   * UAE - The Un*x Amiga Emulator
        !             3:   * 
        !             4:   * Custom chip emulation
        !             5:   * 
        !             6:   * (c) 1995 Bernd Schmidt, Alessandro Bissacco
        !             7:   */
        !             8: 
        !             9: #include "sysconfig.h"
        !            10: #include "sysdeps.h"
        !            11: 
        !            12: #include <ctype.h>
        !            13: #include <assert.h>
        !            14: 
        !            15: #include "config.h"
        !            16: #include "options.h"
        !            17: #include "events.h"
        !            18: #include "memory.h"
        !            19: #include "custom.h"
        !            20: #include "newcpu.h"
        !            21: #include "cia.h"
        !            22: #include "disk.h"
        !            23: #include "blitter.h"
        !            24: #include "xwin.h"
        !            25: #include "os.h"
        !            26: #include "keybuf.h"
        !            27: #include "serial.h"
        !            28: 
        !            29: /* #define EMULATE_AGA */
        !            30: 
        !            31: #ifndef EMULATE_AGA
        !            32: #define AGA_CHIPSET 0
        !            33: #else
        !            34: #define AGA_CHIPSET 1
        !            35: #endif
        !            36: 
        !            37: #define SMART_UPDATE 1
        !            38: 
        !            39: #define MAX_PLANES 8
        !            40: 
        !            41: #define PIXEL_XPOS(HPOS) (((HPOS)*2 - 0x30)*(use_lores ? 1 : 2))
        !            42: 
        !            43: /* These are default values for mouse calibration.
        !            44:  * The first two are default values for mstepx and mstepy.
        !            45:  * The second line set the orizontal and vertical offset for amiga and X 
        !            46:  * pointer matching
        !            47:  */
        !            48:    
        !            49: #define defstepx (1<<16)
        !            50: #define defstepy (1<<16)
        !            51: #define defxoffs 0
        !            52: #define defyoffs 0
        !            53:     
        !            54: /* Values below define mouse auto calibration process.
        !            55:  * They are not critical, change them if you want.
        !            56:  * The most important is calweight, which sets mouse adjustement rate */ 
        !            57: 
        !            58: static const int docal = 60, xcaloff = 40, ycaloff = 20;
        !            59: static const int calweight = 3;
        !            60: static int lastsampledmx, lastsampledmy;
        !            61: 
        !            62:  /*
        !            63:   * Events
        !            64:   */
        !            65: 
        !            66: unsigned long int cycles, nextevent;
        !            67: int vpos;
        !            68: UWORD lof;
        !            69: 
        !            70: struct ev eventtab[ev_max];
        !            71: 
        !            72: int copper_active;
        !            73: 
        !            74: static const int dskdelay = 2; /* FIXME: ??? */
        !            75: 
        !            76:  /* 
        !            77:   * hardware register values that are visible/can be written to by someone
        !            78:   */
        !            79: 
        !            80: static int fmode;
        !            81: 
        !            82: static UWORD cregs[256];
        !            83: 
        !            84: UWORD intena,intreq;
        !            85: UWORD dmacon;
        !            86: UWORD adkcon; /* used by audio code */
        !            87: 
        !            88: static ULONG cop1lc,cop2lc,copcon;
        !            89: 
        !            90: /* Kludge. FIXME: How does sprite restart after vsync work? */
        !            91: static int spron[8];
        !            92: static CPTR sprpt[8];
        !            93: 
        !            94: static ULONG bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat;
        !            95: static WORD  bpl1mod,bpl2mod;
        !            96: 
        !            97: xcolnr acolors[64];
        !            98: 
        !            99: UBYTE *r_bplpt[MAX_PLANES];
        !           100: static CPTR bplpt[MAX_PLANES];
        !           101: 
        !           102: /*static int blitcount[256];  blitter debug */
        !           103: 
        !           104: struct bplinfo {
        !           105: #if AGA_CHIPSET == 0
        !           106:     /* X86.S will break if this isn't at the beginning of the structure. */
        !           107:     UWORD color_regs[32];
        !           108: #else
        !           109:     ULONG color_regs[256];
        !           110: #endif
        !           111:     UWORD bplcon0,bplcon1,bplcon2,bplcon3,bplcon4;
        !           112:     UWORD diwstrt,diwstop,ddfstrt,ddfstop;
        !           113: 
        !           114:     UWORD sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
        !           115:     int sprarmed[8];
        !           116: } bpl_info;
        !           117: 
        !           118: struct line_description
        !           119: {
        !           120:     int inborder;
        !           121:     xcolnr bordercol;
        !           122:     struct bplinfo bpl_info;
        !           123:     struct mem_notify_node *mnn;
        !           124:     CPTR bplpt[MAX_PLANES];
        !           125:     int linedata_valid;
        !           126: };
        !           127: 
        !           128: static int frame_redraw_necessary;
        !           129: 
        !           130: /* 50 words give you 800 horizontal pixels. An A500 can't do that, so it ought
        !           131:  * to be enough. */
        !           132: #define MAX_WORDS_PER_LINE 50
        !           133: static UBYTE line_data[numscrlines * 2][MAX_PLANES][MAX_WORDS_PER_LINE*2];
        !           134: static struct line_description linedescr[numscrlines * 2];
        !           135: 
        !           136: static ULONG dskpt;
        !           137: static UWORD dsklen,dsksync;
        !           138: 
        !           139: static int joy0x, joy1x, joy0y, joy1y;
        !           140: int joy0button;
        !           141: UWORD joy0dir;
        !           142: static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
        !           143: static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
        !           144: static int sprvbfl;
        !           145: 
        !           146: static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate;
        !           147: 
        !           148:  /*
        !           149:   * "hidden" hardware registers
        !           150:   */
        !           151: 
        !           152: int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256];
        !           153: int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256];
        !           154: 
        !           155: int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
        !           156: 
        !           157: static ULONG coplc;
        !           158: static UWORD copi1,copi2;
        !           159: 
        !           160: static enum {
        !           161:     COP_stop, COP_read, COP_wait, COP_move, COP_skip
        !           162: } copstate;
        !           163: 
        !           164: static int dsklength;
        !           165: 
        !           166: int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
        !           167: int diwfirstword,diwlastword;
        !           168: int plfpri[3];
        !           169: 
        !           170: int max_diwstop, prev_max_diwstop;
        !           171: 
        !           172: int dskdmaen; /* used in cia.c */
        !           173: 
        !           174: int bpldelay1, bpldelay2;
        !           175: int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
        !           176: 
        !           177: static int pfield_fullline,pfield_linedone;
        !           178: static int pfield_linedmaon;
        !           179: static int pfield_lastpart_hpos,last_sprite;
        !           180: static int slowline_nextpos, slowline_linepos, slowline_lasttoscr;
        !           181: 
        !           182: union {
        !           183:     /* Let's try to align this thing. */
        !           184:     double uupzuq;
        !           185:     long int cruxmedo;
        !           186:     unsigned char apixels[1000];
        !           187: } pixdata;
        !           188: 
        !           189: char spixels[1000]; /* for sprites */
        !           190: char spixstate[1000]; /* more sprites */
        !           191: 
        !           192: ULONG ham_linebuf[1000];
        !           193: ULONG aga_linebuf[1000], *aga_lbufptr;
        !           194: 
        !           195: char *xlinebuffer;
        !           196: int next_lineno, linetoscreen, line_in_border;
        !           197: 
        !           198: /*
        !           199:  * Statistics
        !           200:  */
        !           201: 
        !           202: static unsigned long int msecs = 0, frametime = 0, timeframes = 0;
        !           203: static unsigned long int seconds_base;
        !           204: int bogusframe;
        !           205: 
        !           206: /*
        !           207:  * helper functions
        !           208:  */
        !           209: 
        !           210: static void pfield_doline_slow(int);
        !           211: static void pfield_doline(void);
        !           212: static void do_sprites(int, int);
        !           213: 
        !           214: int inhibit_frame;
        !           215: static int framecnt = 0;
        !           216: 
        !           217: static __inline__ void count_frame(void)
        !           218: {
        !           219:     if (inhibit_frame) 
        !           220:        framecnt = 1;
        !           221:     else {
        !           222:        framecnt++;
        !           223:        if (framecnt >= framerate)
        !           224:            framecnt = 0;
        !           225:     }
        !           226: }
        !           227: 
        !           228: static __inline__ void setclr(UWORD *p, UWORD val)
        !           229: {
        !           230:     if (val & 0x8000) {
        !           231:        *p |= val & 0x7FFF;
        !           232:     } else {
        !           233:        *p &= ~val;
        !           234:     }
        !           235: }
        !           236: 
        !           237: static __inline__ int current_hpos(void)
        !           238: {
        !           239:     return cycles - eventtab[ev_hsync].oldcycles;
        !           240: }
        !           241: 
        !           242: static void calcdiw(void)
        !           243: {
        !           244:     if (use_lores) {
        !           245:        diwfirstword = (bpl_info.diwstrt & 0xFF) - 0x30 - 1;
        !           246:        diwlastword  = (bpl_info.diwstop & 0xFF) + 0x100 - 0x30 - 1;
        !           247:     } else {
        !           248:        diwfirstword = (bpl_info.diwstrt & 0xFF) * 2 - 0x60 - 2;
        !           249:        diwlastword  = (bpl_info.diwstop & 0xFF) * 2 + 0x200 - 0x60 - 2;
        !           250:     }
        !           251:     if (diwfirstword < 0) diwfirstword = 0;
        !           252:     if (diwlastword > max_diwstop) max_diwstop = diwlastword;
        !           253:     
        !           254:     plffirstline = bpl_info.diwstrt >> 8;
        !           255:     plflastline = bpl_info.diwstop >> 8;
        !           256: #if 0
        !           257:     /* This happens far too often. */
        !           258:     if (plffirstline < minfirstline) {
        !           259:        fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
        !           260:        plffirstline = minfirstline;
        !           261:     }
        !           262: #endif
        !           263:     if ((plflastline & 0x80) == 0) plflastline |= 0x100;
        !           264: #if 0 /* Turrican does this */
        !           265:     if (plflastline > 313) {
        !           266:        fprintf(stderr, "Warning: Playfield out of range!\n");
        !           267:        plflastline = 313;
        !           268:     }
        !           269: #endif
        !           270:     plfstrt = bpl_info.ddfstrt;
        !           271:     plfstop = bpl_info.ddfstop;
        !           272:     if (plfstrt < 0x18) plfstrt = 0x18;
        !           273:     if (plfstop > 0xD8) plfstop = 0xD8;
        !           274:     if (plfstrt > plfstop) plfstrt = plfstop;
        !           275: 
        !           276:     /* ! If the masking operation is changed, the pfield_doline code could break
        !           277:      * on some systems (alignment) */
        !           278:     /* This actually seems to be correct now, at least the non-AGA stuff... */
        !           279:     plfstrt &= ~3;
        !           280:     plfstop &= ~3;
        !           281:     if ((fmode & 3) == 0)
        !           282:        plflinelen = (plfstop-plfstrt+15) & ~7;
        !           283:     else if ((fmode & 3) == 3)
        !           284:        plflinelen = (plfstop-plfstrt+63) & ~31;
        !           285:     else
        !           286:        plflinelen = (plfstop-plfstrt+31) & ~15;
        !           287:        
        !           288: }
        !           289: 
        !           290: /*
        !           291:  * Screen update macros/functions
        !           292:  */
        !           293: 
        !           294: static void decode_ham6 (int pix, int stoppos)
        !           295: {
        !           296:     static UWORD lastcolor;
        !           297:     ULONG *buf = ham_linebuf; 
        !           298: 
        !           299:     if (!bplham || bplplanecnt != 6)
        !           300:        return;
        !           301:     
        !           302:     if (pix <= diwfirstword) {
        !           303:        pix = diwfirstword;
        !           304:        lastcolor = bpl_info.color_regs[0];
        !           305:     }
        !           306: 
        !           307:     while (pix < diwlastword && pix < stoppos) {
        !           308:        int pv = pixdata.apixels[pix];
        !           309:        switch(pv & 0x30) {
        !           310:         case 0x00: lastcolor = bpl_info.color_regs[pv]; break;
        !           311:         case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break;
        !           312:         case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break;
        !           313:         case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break;
        !           314:        }
        !           315: 
        !           316:        buf[pix++] = lastcolor;
        !           317:     }    
        !           318: }
        !           319: 
        !           320: static void decode_ham_aga (int pix, int stoppos)
        !           321: {
        !           322:     static ULONG lastcolor;
        !           323:     ULONG *buf = ham_linebuf; 
        !           324: 
        !           325:     if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
        !           326:        return;
        !           327:     
        !           328:     if (pix <= diwfirstword) {
        !           329:        pix = diwfirstword;
        !           330:        lastcolor = bpl_info.color_regs[0];
        !           331:     }
        !           332: 
        !           333:     if (bplplanecnt == 6) {
        !           334:        /* HAM 6 */
        !           335:        while (pix < diwlastword && pix < stoppos) {
        !           336:            int pv = pixdata.apixels[pix];
        !           337:            switch(pv & 0x30) {
        !           338:             case 0x00: lastcolor = bpl_info.color_regs[pv]; break;
        !           339:             case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break;
        !           340:             case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break;
        !           341:             case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break;
        !           342:            }       
        !           343:            buf[pix++] = lastcolor;
        !           344:        }
        !           345:     } else if (bplplanecnt == 8) {
        !           346:        /* HAM 8 */
        !           347:        while (pix < diwlastword && pix < stoppos) {
        !           348:            int pv = pixdata.apixels[pix];
        !           349:            switch(pv & 0x3) {
        !           350:             case 0x0: lastcolor = bpl_info.color_regs[pv >> 2]; break;
        !           351:             case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
        !           352:             case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
        !           353:             case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
        !           354:            }
        !           355:            buf[pix++] = lastcolor;
        !           356:        }
        !           357:     }
        !           358: }
        !           359: 
        !           360: #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE) \
        !           361: static void NAME(int pix, int stoppos, int offset) \
        !           362: { \
        !           363:     TYPE *buf = (TYPE *)xlinebuffer; \
        !           364:     int oldpix = pix; \
        !           365:     buf -= pix; \
        !           366:     if (DO_DOUBLE) offset /= sizeof(TYPE); \
        !           367:     while (pix < diwfirstword && pix < stoppos) { \
        !           368:         TYPE d = acolors[0]; \
        !           369:        buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
        !           370:        pix++; \
        !           371:     } \
        !           372:     if (bplham && bplplanecnt == 6) { \
        !           373:        /* HAM 6 */ \
        !           374:        while (pix < diwlastword && pix < stoppos) { \
        !           375:            TYPE d = xcolors[ham_linebuf[pix]]; \
        !           376:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
        !           377:            pix++; \
        !           378:        } \
        !           379:     } else if (bpldualpf) { \
        !           380:        /* Dual playfield */ \
        !           381:        int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
        !           382:        while (pix < diwlastword && pix < stoppos) { \
        !           383:            int pixcol = pixdata.apixels[pix]; \
        !           384:            TYPE d; \
        !           385:            if (spixstate[pix]) { \
        !           386:                d = acolors[pixcol]; \
        !           387:            } else { \
        !           388:                d = acolors[lookup[pixcol]]; \
        !           389:            } \
        !           390:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
        !           391:            pix++; \
        !           392:        } \
        !           393:     } else { \
        !           394:        while (pix < diwlastword && pix < stoppos) { \
        !           395:            TYPE d = acolors[pixdata.apixels[pix]]; \
        !           396:            buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
        !           397:            pix++; \
        !           398:        } \
        !           399:     } \
        !           400:     while (pix < stoppos) { \
        !           401:         TYPE d = acolors[0]; \
        !           402:        buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
        !           403:        pix++; \
        !           404:     } \
        !           405:     xlinebuffer = (char *)(((TYPE *)xlinebuffer) + pix - oldpix); \
        !           406: }
        !           407: 
        !           408: /* WARNING: Not too much of this will work correctly yet. */
        !           409: 
        !           410: static void pfield_linetoscr_aga(int pix, int stoppos)
        !           411: {
        !           412:     ULONG *buf = aga_lbufptr;
        !           413:     int i;
        !           414:     int xor = (UBYTE)(bpl_info.bplcon4 >> 8);
        !           415:     int oldpix = pix; \
        !           416: 
        !           417:     buf -= pix; \
        !           418: 
        !           419:     for (i = 0; i < stoppos; i++)
        !           420:        pixdata.apixels[i] ^= xor;
        !           421:     
        !           422:     while (pix < diwfirstword && pix < stoppos) {
        !           423:        buf[pix++] = bpl_info.color_regs[0];
        !           424:     }
        !           425:     if (bplham) {
        !           426:        while (pix < diwlastword && pix < stoppos) {
        !           427:            ULONG d = ham_linebuf[pix];
        !           428:            buf[pix] = d;
        !           429:            pix++;
        !           430:        }
        !           431:     } else if (bpldualpf) {
        !           432:        /* Dual playfield */
        !           433:        int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
        !           434:        int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
        !           435:        while (pix < diwlastword && pix < stoppos) {
        !           436:            int pixcol = pixdata.apixels[pix];
        !           437:            int pfno = lookup_no[pixcol];
        !           438:            
        !           439:            if (spixstate[pix]) {
        !           440:                buf[pix] = bpl_info.color_regs[pixcol];
        !           441:            } else {
        !           442:                int val = lookup[pixdata.apixels[pix]];
        !           443:                if (pfno == 2) 
        !           444:                    val += dblpfofs[(bpl_info.bplcon2 >> 10) & 7];
        !           445:                buf[pix] = bpl_info.color_regs[val];
        !           446:            }
        !           447:            pix++;
        !           448:        }
        !           449:     } else if (bplehb) {
        !           450:        while (pix < diwlastword && pix < stoppos) {
        !           451:             int pixcol = pixdata.apixels[pix];
        !           452:            ULONG d = bpl_info.color_regs[pixcol];
        !           453:            /* What about sprites? */
        !           454:            if (pixcol & 0x20)
        !           455:                d = (d & 0x777777) >> 1;
        !           456:            buf[pix] = d;
        !           457:            pix++;
        !           458:        }
        !           459:     } else {
        !           460:        while (pix < diwlastword && pix < stoppos) {
        !           461:            int pixcol = pixdata.apixels[pix];
        !           462:            buf[pix] = bpl_info.color_regs[pixcol];
        !           463:            pix++;
        !           464:        }
        !           465:     }
        !           466:     while (pix < stoppos) {
        !           467:        buf[pix++] = bpl_info.color_regs[0];
        !           468:     }
        !           469:     aga_lbufptr += pix - oldpix;
        !           470: }
        !           471: 
        !           472: static void aga_translate32(int start, int stop)
        !           473: {
        !           474:     memcpy (((ULONG *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start));
        !           475: }
        !           476: 
        !           477: static void aga_translate16(int start, int stop)
        !           478: {
        !           479:     int i;
        !           480:     for (i = start; i < stop; i++) {
        !           481:        ULONG d = aga_linebuf[i];
        !           482:        UWORD v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
        !           483:        ((UWORD *)xlinebuffer)[i] = xcolors[v];
        !           484:     }
        !           485: }
        !           486: 
        !           487: static void aga_translate8(int start, int stop)
        !           488: {
        !           489:     int i;
        !           490:     for (i = start; i < stop; i++) {
        !           491:        ULONG d = aga_linebuf[i];
        !           492:        UWORD v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
        !           493:        ((UBYTE *)xlinebuffer)[i] = xcolors[v];
        !           494:     }
        !           495: }
        !           496: 
        !           497: 
        !           498: 
        !           499: #define FILL_LINE(NAME, TYPE) \
        !           500: static void NAME(char *buf) \
        !           501: { \
        !           502:     TYPE *b = (TYPE *)buf; \
        !           503:     int i;\
        !           504:     int maxpos = gfxvidinfo.maxlinetoscr; \
        !           505:     xcolnr col = acolors[0]; \
        !           506:     if (!maxpos) maxpos = 796; \
        !           507:     for (i = 0; i < maxpos; i++) \
        !           508:         *b++ = col; \
        !           509: }
        !           510: 
        !           511: LINE_TO_SCR(pfield_linetoscr_8, UBYTE, 0)
        !           512: LINE_TO_SCR(pfield_linetoscr_16, UWORD, 0)
        !           513: LINE_TO_SCR(pfield_linetoscr_32, ULONG, 0)
        !           514: LINE_TO_SCR(pfield_linetoscr_8_double_slow, UBYTE, 1)
        !           515: LINE_TO_SCR(pfield_linetoscr_16_double_slow, UWORD, 1)
        !           516: LINE_TO_SCR(pfield_linetoscr_32_double_slow, ULONG, 1)
        !           517: 
        !           518: FILL_LINE(fill_line_8, UBYTE)
        !           519: FILL_LINE(fill_line_16, UWORD)
        !           520: FILL_LINE(fill_line_32, ULONG)
        !           521: 
        !           522: #define pfield_linetoscr_full8 pfield_linetoscr_8
        !           523: #define pfield_linetoscr_full16 pfield_linetoscr_16
        !           524: #define pfield_linetoscr_full32 pfield_linetoscr_32
        !           525: 
        !           526: #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow
        !           527: #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow
        !           528: #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow
        !           529: 
        !           530: #if 1 && defined(X86_ASSEMBLY)
        !           531: #undef pfield_linetoscr_full8
        !           532: #undef pfield_linetoscr_full16
        !           533: extern void pfield_linetoscr_full8(int, int, int) __asm__("pfield_linetoscr_full8");
        !           534: extern void pfield_linetoscr_full16(int, int, int) __asm__("pfield_linetoscr_full16");
        !           535: #undef pfield_linetoscr_full8_double
        !           536: #undef pfield_linetoscr_full16_double
        !           537: 
        !           538: static void pfield_linetoscr_full8_double(int start, int stop, int offset)
        !           539: {
        !           540:     char *oldxlb = (char *)xlinebuffer;
        !           541:     pfield_linetoscr_full8(start,stop,offset);
        !           542:     xlinebuffer = oldxlb + offset;
        !           543:     pfield_linetoscr_full8(start,stop,offset);
        !           544: }
        !           545: static void pfield_linetoscr_full16_double(int start, int stop, int offset)
        !           546: {
        !           547:     char *oldxlb = (char *)xlinebuffer;
        !           548:     pfield_linetoscr_full16(start,stop,offset);
        !           549:     xlinebuffer = oldxlb + offset;
        !           550:     pfield_linetoscr_full16(start,stop,offset);
        !           551: }
        !           552: #endif
        !           553: 
        !           554: static __inline__ void fill_line(int y)
        !           555: {
        !           556:     switch (gfxvidinfo.pixbytes) {
        !           557:      case 1: fill_line_8(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break;
        !           558:      case 2: fill_line_16(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break;
        !           559:      case 4: fill_line_32(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break;
        !           560:     }
        !           561: }
        !           562: 
        !           563: static void pfield_do_linetoscr(int start, int stop)
        !           564: {
        !           565:     int factor = use_lores ? 1 : 2;
        !           566:     int oldstop = stop;
        !           567:     int real_start, real_stop;
        !           568:     
        !           569:     start = PIXEL_XPOS(start);
        !           570:     if (start < 8*factor)
        !           571:        start = 8*factor;
        !           572:     stop = PIXEL_XPOS(stop);
        !           573:     if (stop > 406*factor)
        !           574:        stop = 406*factor;
        !           575:     
        !           576:     if (start >= stop)
        !           577:        return;
        !           578:     if (stop <= gfxvidinfo.x_adjust)
        !           579:        return;
        !           580:     
        !           581:     slowline_lasttoscr = oldstop;
        !           582: 
        !           583:     if (start < gfxvidinfo.x_adjust)
        !           584:        real_start = gfxvidinfo.x_adjust;
        !           585:     else
        !           586:        real_start = start;
        !           587:     
        !           588:     if (gfxvidinfo.maxlinetoscr) {
        !           589:        real_stop = gfxvidinfo.x_adjust + gfxvidinfo.maxlinetoscr;
        !           590:        if (real_stop > stop)
        !           591:            real_stop = stop;
        !           592:     } else
        !           593:        real_stop = stop;
        !           594: 
        !           595: #if AGA_CHIPSET == 0
        !           596:     if (start == 8*factor && stop == 406*factor) {
        !           597:        switch (gfxvidinfo.pixbytes) {
        !           598:         case 1: pfield_linetoscr_full8 (real_start, real_stop, 0); break;
        !           599:         case 2: pfield_linetoscr_full16 (real_start, real_stop, 0); break;
        !           600:         case 4: pfield_linetoscr_full32 (real_start, real_stop, 0); break;
        !           601:        }
        !           602:     } else {
        !           603:        if (real_start >= real_stop)
        !           604:            return;
        !           605:        switch (gfxvidinfo.pixbytes) {
        !           606:         case 1: pfield_linetoscr_8 (real_start, real_stop, 0); break;
        !           607:         case 2: pfield_linetoscr_16 (real_start, real_stop, 0); break;
        !           608:         case 4: pfield_linetoscr_32 (real_start, real_stop, 0); break;
        !           609:        }
        !           610:     }
        !           611: #else
        !           612:     pfield_linetoscr_aga(real_start, real_stop);
        !           613: #endif
        !           614: }
        !           615: 
        !           616: static void pfield_do_linetoscr_full(int double_line)
        !           617: {
        !           618:     int factor = use_lores ? 1 : 2;
        !           619:     int stop, start;
        !           620:     
        !           621:     start = 8*factor;
        !           622:     stop = 406*factor;
        !           623:     
        !           624:     if (start < gfxvidinfo.x_adjust)
        !           625:        start = gfxvidinfo.x_adjust;
        !           626:     
        !           627:     if (gfxvidinfo.maxlinetoscr) {
        !           628:        int tmp = gfxvidinfo.x_adjust + gfxvidinfo.maxlinetoscr;
        !           629:        if (tmp < stop)
        !           630:            stop = tmp;
        !           631:     }
        !           632: 
        !           633: #if AGA_CHIPSET == 0
        !           634:     if (double_line) {
        !           635:        switch (gfxvidinfo.pixbytes) {
        !           636:         case 1: pfield_linetoscr_full8_double (start, stop, gfxvidinfo.rowbytes); break;
        !           637:         case 2: pfield_linetoscr_full16_double (start, stop, gfxvidinfo.rowbytes); break;
        !           638:         case 4: pfield_linetoscr_full32_double (start, stop, gfxvidinfo.rowbytes); break;
        !           639:        }
        !           640:     } else 
        !           641:        switch (gfxvidinfo.pixbytes) {
        !           642:         case 1: pfield_linetoscr_full8 (start, stop, 0); break;
        !           643:         case 2: pfield_linetoscr_full16 (start, stop, 0); break;
        !           644:         case 4: pfield_linetoscr_full32 (start, stop, 0); break;
        !           645:        }
        !           646: #else
        !           647:     pfield_linetoscr_aga(start, stop);
        !           648: #endif
        !           649: }
        !           650: 
        !           651: /*
        !           652:  * This function is called whenever a hardware register that controls the
        !           653:  * screen display is modified. Usually, this routine does nothing. But in
        !           654:  * some cases, e.g., when a color changes in mid-screen, as in copper-plasma
        !           655:  * effects, this function switches the update method from the fast full-line
        !           656:  * update to the much slower single-color-clock update.
        !           657:  */
        !           658: static void pfield_may_need_update(int colreg)
        !           659: {
        !           660:     int i;
        !           661:     
        !           662:     /* Ignore, if this happened before or after the DDF window */
        !           663:     /* @@@ This breaks some copper plasmas. Not good... maybe a config
        !           664:      * option is needed. */
        !           665:     if (framecnt != 0 || !pfield_linedmaon || current_hpos() <= plfstrt
        !           666:        || vpos < plffirstline || vpos < minfirstline || vpos >= plflastline
        !           667:        || next_lineno >= gfxvidinfo.maxline)
        !           668:     {
        !           669:        return;
        !           670:     }
        !           671:     /* 
        !           672:      * If a color reg was modified, it is only important if we are within
        !           673:      * the DIW.
        !           674:      */
        !           675:     if (PIXEL_XPOS(current_hpos()) <= diwfirstword && colreg)
        !           676:        return;
        !           677: 
        !           678:     /*
        !           679:      * If we are past the DDF window, me might as well draw the complete
        !           680:      * line now.
        !           681:      */
        !           682:     if (current_hpos() > plfstrt + plflinelen && pfield_fullline) {
        !           683:        if (!pfield_linedone)
        !           684:            pfield_doline();
        !           685:        pfield_linedone = 1;
        !           686:        return;
        !           687:     }
        !           688:        
        !           689:     do_sprites(vpos, current_hpos());
        !           690:     if (pfield_fullline) {
        !           691:        pfield_lastpart_hpos = 0;
        !           692:        memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
        !           693:        memset(spixstate,0,sizeof spixstate);
        !           694:        pfield_fullline = 0;
        !           695:        slowline_nextpos = -1;
        !           696:        slowline_linepos = 0;
        !           697:        slowline_lasttoscr = 0;
        !           698:     } else {   
        !           699:        assert(pfield_lastpart_hpos <= current_hpos());
        !           700:     }
        !           701:     for (i = pfield_lastpart_hpos; i < current_hpos(); i++) {
        !           702:        pfield_doline_slow(i);
        !           703:     }
        !           704:     if (colreg) {
        !           705:        pfield_do_linetoscr(slowline_lasttoscr, current_hpos());
        !           706:     }
        !           707:     pfield_lastpart_hpos = current_hpos();
        !           708: }
        !           709: 
        !           710: /* Apparently, the DMA bit is tested by the hardware at some point,
        !           711:  * presumably at the ddfstart position, to determine whether it
        !           712:  * ought to draw the line.
        !           713:  * This is probably not completely correct, but should not matter
        !           714:  * very much.
        !           715:  */
        !           716: static void pfield_calclinedma(void)
        !           717: {
        !           718:     if (current_hpos() >= plfstrt)
        !           719:        return;
        !           720:     
        !           721:     pfield_linedmaon = dmaen(DMA_BITPLANE);
        !           722: }
        !           723: 
        !           724:  /* 
        !           725:   * register functions
        !           726:   */
        !           727: 
        !           728: static UWORD DMACONR(void)
        !           729: {
        !           730:     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
        !           731:            | (blt_info.blitzero ? 0x2000 : 0));
        !           732: }
        !           733: static UWORD INTENAR(void) { return intena; }
        !           734: UWORD INTREQR(void)
        !           735: {
        !           736:     return intreq | (use_serial ? 0x0001 : 0);
        !           737: }
        !           738: static UWORD ADKCONR(void) { return adkcon; }
        !           739: static UWORD VPOSR(void) 
        !           740: {
        !           741: #if AGA_CHIPSET == 1
        !           742:     return (vpos >> 8) | lof | 0x2300;
        !           743: #elif defined (ECS_AGNUS)
        !           744:     return (vpos >> 8) | lof | 0x2000;
        !           745: #else
        !           746:     return (vpos >> 8) | lof;
        !           747: #endif
        !           748: }
        !           749: static void  VPOSW(UWORD v)  { lof = v & 0x8000; }
        !           750: static UWORD VHPOSR(void) { return (vpos << 8) | current_hpos(); } 
        !           751: 
        !           752: static void  COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); }
        !           753: static void  COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; }
        !           754: static void  COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); }
        !           755: static void  COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; }
        !           756: 
        !           757: static void  COPJMP1(UWORD a)
        !           758: {
        !           759:     coplc = cop1lc; copstate = COP_read; 
        !           760:     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
        !           761:     eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
        !           762:     copper_active = 1;
        !           763: }
        !           764: static void  COPJMP2(UWORD a)
        !           765: {
        !           766:     coplc = cop2lc; copstate = COP_read; 
        !           767:     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
        !           768:     eventtab[ev_copper].evtime = 4 + cycles; events_schedule();
        !           769:     copper_active = 1;
        !           770: }
        !           771: 
        !           772: static void  DMACON(UWORD v) 
        !           773: {
        !           774:     int i, need_resched = 0;
        !           775: 
        !           776:     UWORD oldcon = dmacon;
        !           777:     setclr(&dmacon,v); dmacon &= 0x1FFF;
        !           778:     pfield_calclinedma();
        !           779:     
        !           780:     /* FIXME? Maybe we need to think a bit more about the master DMA enable 
        !           781:      * bit in these cases. */
        !           782:     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { 
        !           783:        COPJMP1(0);
        !           784:     }
        !           785:     if ((dmacon & DMA_SPRITE) > (oldcon & DMA_SPRITE)) {
        !           786:        int i;
        !           787:        for (i = 0; i < 8; i++)
        !           788:            spron[i] = 1;
        !           789:     }
        !           790:     if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
        !           791:        static int count = 0;
        !           792:        if (!count) {
        !           793:            count = 1;
        !           794:            fprintf(stderr, "warning: program is doing blitpri hacks.\n");
        !           795:        }
        !           796:        regs.spcflags |= SPCFLAG_BLTNASTY;
        !           797:     }
        !           798: #ifndef DONT_WANT_SOUND
        !           799:     for (i = 0; i < 4; i++) {
        !           800:        struct audio_channel_data *cdp = audio_channel + i;
        !           801:        
        !           802:        cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<<i));
        !           803:        if (cdp->dmaen) {
        !           804:            if (cdp->state == 0) {
        !           805:                cdp->state = 1;
        !           806:                cdp->pt = cdp->lc;
        !           807:                cdp->wper = cdp->per;
        !           808:                cdp->wlen = cdp->len;
        !           809:                cdp->data_written = 2;
        !           810:                eventtab[ev_aud0 + i].oldcycles = eventtab[ev_hsync].oldcycles;
        !           811:                eventtab[ev_aud0 + i].evtime = eventtab[ev_hsync].evtime;
        !           812:                eventtab[ev_aud0 + i].active = 1;
        !           813:                need_resched = 1; /* not _really_ necessary here, but... */
        !           814:            }
        !           815:        } else {
        !           816:            if (cdp->state == 1 || cdp->state == 5) {
        !           817:                cdp->state = 0;
        !           818:                cdp->current_sample = 0;
        !           819:                eventtab[ev_aud0 + i].active = 0;
        !           820:                need_resched = 1;
        !           821:            }
        !           822:        }
        !           823:     }
        !           824: #endif
        !           825:     if (copper_active && !eventtab[ev_copper].active) {
        !           826:        eventtab[ev_copper].active = 1;
        !           827:        eventtab[ev_copper].oldcycles = cycles;
        !           828:        eventtab[ev_copper].evtime = 1 + cycles;
        !           829:        need_resched = 1;
        !           830:     }
        !           831:     if (need_resched)
        !           832:        events_schedule();
        !           833: }
        !           834: static void  INTENA(UWORD v) { setclr(&intena,v); regs.spcflags |= SPCFLAG_INT; }
        !           835: void  INTREQ(UWORD v)
        !           836: {
        !           837:   setclr(&intreq,v);
        !           838:   regs.spcflags |= SPCFLAG_INT;
        !           839:   if ((v&0x8800)==0x0800) serdat&=0xbfff;
        !           840:  }
        !           841: 
        !           842: static void  ADKCON(UWORD v) { setclr(&adkcon,v); }
        !           843: 
        !           844: static void  BPLPTH(UWORD v, int num) { bplpt[num] = (bplpt[num] & 0xffff) | ((ULONG)v << 16); }
        !           845: static void  BPLPTL(UWORD v, int num) { bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xFFFE); }
        !           846: 
        !           847: /*
        !           848:  * I've seen the listing of an example program that changes 
        !           849:  * from lo- to hires while a line is being drawn. That's
        !           850:  * awful, but we want to emulate it.
        !           851:  */
        !           852: static void  BPLCON0(UWORD v) 
        !           853: {
        !           854:     if (bpl_info.bplcon0 == v)
        !           855:        return;
        !           856:     pfield_may_need_update(0);
        !           857:     bpl_info.bplcon0 = v;
        !           858:     bplhires = (v & 0x8000) == 0x8000;
        !           859:     bplplanecnt = (v & 0x7000) >> 12;
        !           860:     bplham = (v & 0x800) == 0x800;
        !           861:     bpldualpf = (v & 0x400) == 0x400;
        !           862:     bplehb = (v & 0xFDC0) == 0x6000 && !(bpl_info.bplcon2 & 0x200); /* see below */
        !           863:     calcdiw(); /* This should go away. */
        !           864: }
        !           865: static void  BPLCON1(UWORD v) 
        !           866: {
        !           867:     if (bpl_info.bplcon1 == v)
        !           868:        return;
        !           869:     pfield_may_need_update(0);
        !           870:     bpl_info.bplcon1 = v; 
        !           871:     bpldelay1 = v & 0xF; 
        !           872:     bpldelay2 = (v >> 4) & 0xF; 
        !           873: }
        !           874: static void  BPLCON2(UWORD v) 
        !           875: {
        !           876:     if (bpl_info.bplcon2 == v)
        !           877:        return;
        !           878:     pfield_may_need_update(0)        !           879:     bpl_info.bplcon2 = v;
        !           880:     bpldualpfpri = (v & 0x40) == 0x40;
        !           881:     plfpri[1] = 1 << 2*(v & 7);
        !           882:     plfpri[2] = 1 << 2*((v>>3) & 7);
        !           883:     bplehb = (bpl_info.bplcon0 & 0xFDC0) == 0x6000 && !(v & 0x200); /* see above */
        !           884: }
        !           885: static void  BPLCON3(UWORD v) 
        !           886: {
        !           887:     if (bpl_info.bplcon3 == v)
        !           888:        return;
        !           889:     pfield_may_need_update(0)        !           890:     bpl_info.bplcon3 = v; 
        !           891: }
        !           892: static void  BPLCON4(UWORD v) 
        !           893: {
        !           894:     if (bpl_info.bplcon4 == v)
        !           895:        return;
        !           896:     pfield_may_need_update(0)        !           897:     bpl_info.bplcon4 = v; 
        !           898: }
        !           899: 
        !           900: static void  BPL1MOD(UWORD v)
        !           901: {
        !           902:     v &= ~1;
        !           903:     if (bpl1mod == v)
        !           904:        return;
        !           905:     pfield_may_need_update(0)        !           906:     bpl1mod = v;
        !           907: }
        !           908: static void  BPL2MOD(UWORD v)
        !           909: { 
        !           910:     v &= ~1;
        !           911:     if (bpl2mod == v)
        !           912:        return;
        !           913:     pfield_may_need_update(0)        !           914:     bpl2mod = v;
        !           915: }
        !           916: 
        !           917: static void  BPL1DAT(UWORD v) { bpl1dat = v; }
        !           918: static void  BPL2DAT(UWORD v) { bpl2dat = v; }
        !           919: static void  BPL3DAT(UWORD v) { bpl3dat = v; }
        !           920: static void  BPL4DAT(UWORD v) { bpl4dat = v; }
        !           921: static void  BPL5DAT(UWORD v) { bpl5dat = v; }
        !           922: static void  BPL6DAT(UWORD v) { bpl6dat = v; }
        !           923: 
        !           924: /* We call pfield_may_need_update() from here. Actually, 
        !           925:  * I have no idea what happens if someone changes ddf or
        !           926:  * diw mid-line, and I don't really want to know. I doubt
        !           927:  * that this sort of thing was ever used to create a
        !           928:  * useful effect.
        !           929:  */
        !           930: static void  DIWSTRT(UWORD v) 
        !           931: {
        !           932:     if (bpl_info.diwstrt == v)
        !           933:        return;
        !           934:     pfield_may_need_update(0);
        !           935:     bpl_info.diwstrt = v; 
        !           936:     calcdiw();
        !           937: }
        !           938: static void  DIWSTOP(UWORD v)
        !           939: {
        !           940:     if (bpl_info.diwstop == v)
        !           941:        return;
        !           942:     pfield_may_need_update(0);
        !           943:     bpl_info.diwstop = v; 
        !           944:     calcdiw();
        !           945: }
        !           946: static void  DDFSTRT(UWORD v)
        !           947: { 
        !           948:     if (bpl_info.ddfstrt == v)
        !           949:        return;
        !           950:     pfield_may_need_update(0);
        !           951:     bpl_info.ddfstrt = v; 
        !           952:     calcdiw();
        !           953: }
        !           954: static void  DDFSTOP(UWORD v) 
        !           955: { 
        !           956:     if (bpl_info.ddfstop == v)
        !           957:        return;
        !           958:     pfield_may_need_update(0)        !           959:     bpl_info.ddfstop = v;
        !           960:     calcdiw();
        !           961: }
        !           962: 
        !           963: static void  BLTADAT(UWORD v) 
        !           964: {
        !           965:     maybe_blit(); 
        !           966:     blt_info.bltadat = v; 
        !           967: }
        !           968: static void  BLTBDAT(UWORD v)
        !           969: {
        !           970:     maybe_blit(); 
        !           971:     blt_info.bltbdat = v; 
        !           972: }
        !           973: static void  BLTCDAT(UWORD v) { maybe_blit(); blt_info.bltcdat = v; }
        !           974: 
        !           975: static void  BLTAMOD(UWORD v) { maybe_blit(); blt_info.bltamod = v & 0xFFFE; }
        !           976: static void  BLTBMOD(UWORD v) { maybe_blit(); blt_info.bltbmod = v & 0xFFFE; }
        !           977: static void  BLTCMOD(UWORD v) { maybe_blit(); blt_info.bltcmod = v & 0xFFFE; }
        !           978: static void  BLTDMOD(UWORD v) { maybe_blit(); blt_info.bltdmod = v & 0xFFFE; }
        !           979: 
        !           980: static void  BLTCON0(UWORD v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; }
        !           981: /* The next category is "Most useless hardware register". 
        !           982:  * And the winner is... */
        !           983: static void  BLTCON0L(UWORD v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); }
        !           984: static void  BLTCON1(UWORD v) { maybe_blit(); bltcon1 = v; }
        !           985: 
        !           986: static void  BLTAFWM(UWORD v) { maybe_blit(); blt_info.bltafwm = v; }
        !           987: static void  BLTALWM(UWORD v) { maybe_blit(); blt_info.bltalwm = v; }
        !           988: 
        !           989: static void  BLTAPTH(UWORD v) { maybe_blit(); bltapt= (bltapt & 0xffff) | ((ULONG)(v & 0x1F) << 16); }
        !           990: static void  BLTAPTL(UWORD v) { maybe_blit(); bltapt= (bltapt & ~0xffff) | (v & 0xFFFE); }
        !           991: static void  BLTBPTH(UWORD v) { maybe_blit(); bltbpt= (bltbpt & 0xffff) | ((ULONG)(v & 0x1F) << 16); }
        !           992: static void  BLTBPTL(UWORD v) { maybe_blit(); bltbpt= (bltbpt & ~0xffff) | (v & 0xFFFE); }
        !           993: static void  BLTCPTH(UWORD v) { maybe_blit(); bltcpt= (bltcpt & 0xffff) | ((ULONG)(v & 0x1F) << 16); }
        !           994: static void  BLTCPTL(UWORD v) { maybe_blit(); bltcpt= (bltcpt & ~0xffff) | (v & 0xFFFE); }
        !           995: static void  BLTDPTH(UWORD v) { maybe_blit(); bltdpt= (bltdpt & 0xffff) | ((ULONG)(v & 0x1F) << 16); }
        !           996: static void  BLTDPTL(UWORD v) { maybe_blit(); bltdpt= (bltdpt & ~0xffff) | (v & 0xFFFE); }
        !           997: static void  BLTSIZE(UWORD v) 
        !           998: {
        !           999:     bltsize = v;
        !          1000:     
        !          1001:     maybe_blit(); 
        !          1002: 
        !          1003:     blt_info.vblitsize = bltsize >> 6;
        !          1004:     blt_info.hblitsize = bltsize & 0x3F;
        !          1005:     if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
        !          1006:     if (!blt_info.hblitsize) blt_info.hblitsize = 64;
        !          1007:     
        !          1008:     bltstate = BLT_init; 
        !          1009:     regs.spcflags |= SPCFLAG_BLIT; 
        !          1010: }
        !          1011: static void BLTSIZV(UWORD v) 
        !          1012: {
        !          1013:     maybe_blit(); 
        !          1014:     oldvblts = v & 0x7FFF;
        !          1015: }
        !          1016: static void BLTSIZH(UWORD v) 
        !          1017: {
        !          1018:     maybe_blit(); 
        !          1019:     blt_info.hblitsize = v & 0x7FF;
        !          1020:     blt_info.vblitsize = oldvblts;
        !          1021:     if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
        !          1022:     if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
        !          1023:     bltstate = BLT_init; 
        !          1024:     regs.spcflags |= SPCFLAG_BLIT;
        !          1025: }
        !          1026: static void  SPRxCTL_1(UWORD v, int num)
        !          1027: {
        !          1028:     bpl_info.sprctl[num] = v;
        !          1029:     bpl_info.sprarmed[num] = 0;
        !          1030:     if (bpl_info.sprpos[num] == 0 && v == 0)
        !          1031:        spron[num] = 0;
        !          1032:     else
        !          1033:        spron[num] |= 2;
        !          1034: }
        !          1035: static void  SPRxPOS_1(UWORD v, int num) 
        !          1036: {
        !          1037:     bpl_info.sprpos[num] = v; 
        !          1038: }
        !          1039: static void  SPRxDATA_1(UWORD v, int num)
        !          1040: {
        !          1041:     bpl_info.sprdata[num] = v;
        !          1042:     bpl_info.sprarmed[num] = 1; 
        !          1043: }
        !          1044: static void  SPRxDATB_1(UWORD v, int num) 
        !          1045: {
        !          1046:     bpl_info.sprdatb[num] = v;
        !          1047: }
        !          1048: static void  SPRxCTL(UWORD v, int num) { pfield_may_need_update(0); SPRxCTL_1(v, num); }
        !          1049: static void  SPRxPOS(UWORD v, int num) { pfield_may_need_update(0); SPRxPOS_1(v, num); }
        !          1050: static void  SPRxDATA(UWORD v, int num){ pfield_may_need_update(0); SPRxDATA_1(v, num); }
        !          1051: static void  SPRxDATB(UWORD v, int num){ pfield_may_need_update(0); SPRxDATB_1(v, num); }
        !          1052: static void  SPRxPTH(UWORD v, int num)
        !          1053: {
        !          1054:     sprpt[num] &= 0xffff; 
        !          1055:     sprpt[num] |= (ULONG)v << 16; 
        !          1056:     if (!spron[num]) spron[num] = 1; 
        !          1057: }
        !          1058: static void  SPRxPTL(UWORD v, int num)
        !          1059: {
        !          1060:     sprpt[num] &= ~0xffff; 
        !          1061:     sprpt[num] |= v; 
        !          1062:     if (!spron[num]) spron[num] = 1; 
        !          1063: }
        !          1064: 
        !          1065: static void  COLOR(UWORD v, int num)
        !          1066: {
        !          1067:     int r,g,b;
        !          1068:     int cr,cg,cb;
        !          1069:     int colreg;
        !          1070:     
        !          1071:     v &= 0xFFF;
        !          1072: #if AGA_CHIPSET == 1
        !          1073:     {
        !          1074:        ULONG cval;
        !          1075:        colreg = ((bpl_info.bplcon3 >> 13) & 7) * 32 + num;
        !          1076:        r = (v & 0xF00) >> 8;
        !          1077:        g = (v & 0xF0) >> 4;
        !          1078:        b = (v & 0xF) >> 0;
        !          1079:        cr = bpl_info.color_regs[colreg] >> 16;
        !          1080:        cg = (bpl_info.color_regs[colreg] >> 8) & 0xFF;
        !          1081:        cb = bpl_info.color_regs[colreg] & 0xFF;
        !          1082: 
        !          1083:        if (bpl_info.bplcon3 & 0x200) {
        !          1084:            cr &= 0xF0; cr |= r;
        !          1085:            cg &= 0xF0; cg |= g;
        !          1086:            cb &= 0xF0; cb |= b;
        !          1087:        } else {
        !          1088:            cr = r + (r << 4);
        !          1089:            cg = g + (g << 4);
        !          1090:            cb = b + (b << 4);
        !          1091:        }
        !          1092:        cval = (cr << 16) | (cg << 8) | cb;
        !          1093:        if (cval == bpl_info.color_regs[colreg])
        !          1094:            return;
        !          1095:        bpl_info.color_regs[colreg] = cval;
        !          1096:        pfield_may_need_update(1);
        !          1097:     }
        !          1098: #else 
        !          1099:     {
        !          1100:        if (bpl_info.color_regs[num] == v)
        !          1101:            return;
        !          1102:        pfield_may_need_update(1);
        !          1103:        bpl_info.color_regs[num] = v;
        !          1104:        acolors[num] = xcolors[v];
        !          1105:        acolors[num+32] = xcolors[(v >> 1) & 0x777];
        !          1106:     }
        !          1107: #endif
        !          1108: }
        !          1109: 
        !          1110: static void  DSKSYNC(UWORD v) { dsksync = v; }
        !          1111: static void  DSKDAT(UWORD v) { fprintf(stderr, "DSKDAT written. Not good.\n"); }
        !          1112: static void  DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); }
        !          1113: static void  DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); }
        !          1114: 
        !          1115: static void  DSKLEN(UWORD v) 
        !          1116: {
        !          1117:     if (v & 0x8000) {
        !          1118:        dskdmaen = dskdmaen == 1 ? 2 : 1;
        !          1119:     } else { 
        !          1120:        dskdmaen = 0;
        !          1121:        if (eventtab[ev_diskblk].active)
        !          1122:            fprintf(stderr, "warning: Disk DMA aborted!\n");
        !          1123:        eventtab[ev_diskblk].active = 0;
        !          1124:        events_schedule();
        !          1125:        
        !          1126:     }
        !          1127:     dsklen = dsklength = v; dsklength &= 0x3fff;
        !          1128:     if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
        !          1129:        fprintf(stderr, "Non-standard sync: %04x len: %x\n", dsksync, dsklength);
        !          1130:     }
        !          1131:     if (dskdmaen > 1) {
        !          1132:        if (dsklen & 0x4000) {
        !          1133:            eventtab[ev_diskblk].active = 1;
        !          1134:            eventtab[ev_diskblk].oldcycles = cycles;
        !          1135:            eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */
        !          1136:            events_schedule();
        !          1137:        } else {
        !          1138:            int result = DISK_PrepareReadMFM(dsklength, dsksync, adkcon & 0x400);
        !          1139:            if (result) {
        !          1140:                eventtab[ev_diskblk].active = 1;
        !          1141:                eventtab[ev_diskblk].oldcycles = cycles;
        !          1142:                eventtab[ev_diskblk].evtime = result + cycles;
        !          1143:                events_schedule();
        !          1144:            }
        !          1145:        }
        !          1146:     }
        !          1147: }
        !          1148: 
        !          1149: static UWORD DSKBYTR(void)
        !          1150: {
        !          1151:     UWORD v = (dsklen >> 1) & 0x6000;
        !          1152:     UWORD mfm, byte;
        !          1153:     if (DISK_GetData(&mfm, &byte))
        !          1154:        v |= 0x8000;
        !          1155:     v |= byte;
        !          1156:     if (dsksync == mfm) v |= 0x1000;
        !          1157:     return v;
        !          1158: }
        !          1159: 
        !          1160: static UWORD DSKDATR(void) 
        !          1161: {
        !          1162:     UWORD mfm, byte;
        !          1163:     DISK_GetData(&mfm, &byte);
        !          1164:     return mfm; 
        !          1165: }
        !          1166: static UWORD POTGOR(void)
        !          1167: {
        !          1168:     UWORD v = 0xFF00;
        !          1169:     if (buttonstate[2])
        !          1170:        v &= 0xFBFF;
        !          1171: 
        !          1172:     if (buttonstate[1])
        !          1173:        v &= 0xFEFF;
        !          1174:     
        !          1175:     return v;
        !          1176: }
        !          1177: static UWORD POT0DAT(void)
        !          1178: {
        !          1179:     static UWORD cnt = 0;
        !          1180:     if (buttonstate[2])
        !          1181:        cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00);
        !          1182:     if (buttonstate[1])
        !          1183:        cnt += 0x100;
        !          1184:     
        !          1185:     return cnt;
        !          1186: }
        !          1187: static UWORD JOY0DAT(void) { return joy0x + (joy0y << 8); }
        !          1188: static UWORD JOY1DAT(void)
        !          1189: {
        !          1190:     return joy0dir;
        !          1191: }
        !          1192: static void JOYTEST(UWORD v)
        !          1193: {
        !          1194:     joy0x = joy1x = v & 0xFC;
        !          1195:     joy0y = joy1y = (v >> 8) & 0xFC;    
        !          1196: }
        !          1197: static void AUDxLCH(int nr, UWORD v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((ULONG)v << 16); }
        !          1198: static void AUDxLCL(int nr, UWORD v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); }
        !          1199: static void AUDxPER(int nr, UWORD v)
        !          1200: {
        !          1201:     static int warned = 0;
        !          1202:     if (v <= 0) {
        !          1203:        if (!warned)
        !          1204:            fprintf(stderr, "Broken program accessing the sound hardware\n"), warned++;
        !          1205:        v = 65535;
        !          1206:     }
        !          1207: 
        !          1208:     if (v < maxhpos/2 && produce_sound < 3)
        !          1209:        v = maxhpos/2;
        !          1210: 
        !          1211:     audio_channel[nr].per = v;
        !          1212: }
        !          1213: 
        !          1214: static void AUDxVOL(int nr, UWORD v) { audio_channel[nr].vol = v & 64 ? 63 : v & 63; }
        !          1215: static void AUDxLEN(int nr, UWORD v) { audio_channel[nr].len = v; }
        !          1216: 
        !          1217: static int copcomp(void)
        !          1218: {
        !          1219:     UWORD vp = vpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !          1220:     UWORD hp = current_hpos() & (copi2 & 0xFE);
        !          1221:     UWORD vcmp = copi1 >> 8;
        !          1222:     UWORD hcmp = copi1 & 0xFE;
        !          1223:     return (vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000));
        !          1224: }
        !          1225: 
        !          1226: /*
        !          1227:  * Calculate the minimum number of cycles after which the
        !          1228:  * copper comparison becomes true. This is quite tricky. I hope it works.
        !          1229:  */
        !          1230: static int calc_copcomp_true(int currvpos, int currhpos)
        !          1231: {    
        !          1232:     UWORD vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !          1233:     UWORD hp = currhpos & (copi2 & 0xFE);
        !          1234:     UWORD vcmp = copi1 >> 8;
        !          1235:     UWORD hcmp = copi1 & 0xFE;
        !          1236:     int copper_time_hpos;
        !          1237:     int cycleadd = maxhpos - currhpos;
        !          1238:     int coptime = 0;
        !          1239: 
        !          1240:     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
        !          1241:        return 0;    
        !          1242: 
        !          1243:     try_again:
        !          1244: 
        !          1245:     while (vp < vcmp) {
        !          1246:        currvpos++;
        !          1247:        if (currvpos > maxvpos + 1)
        !          1248:            return -1;
        !          1249:        currhpos = 0;
        !          1250:        coptime += cycleadd;
        !          1251:        cycleadd = maxhpos;
        !          1252:        vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !          1253:     }
        !          1254:     if (coptime > 0 && bplhires && bplplanecnt == 4)
        !          1255:        return coptime;
        !          1256:     copper_time_hpos = currhpos;
        !          1257:     hp = copper_time_hpos & (copi2 & 0xFE);
        !          1258:     if (!(vp > vcmp)) {        
        !          1259:        while (hp < hcmp-2) {
        !          1260:            currhpos++;
        !          1261:            /* Copper DMA is turned off in Hires 4 bitplane mode */
        !          1262:            if (!bplhires || bplplanecnt < 4 || !dmaen(DMA_BITPLANE)
        !          1263:                || currhpos < plfstrt-2 || currhpos > (plfstop+4))
        !          1264:                copper_time_hpos++;
        !          1265:            
        !          1266:            if (currhpos > maxhpos-4) {
        !          1267:                /* Now, what? There might be a good position on the
        !          1268:                 * next line. But it can also be the FFFF FFFE
        !          1269:                 * case.
        !          1270:                 */
        !          1271:                currhpos = 0;
        !          1272:                currvpos++;
        !          1273:                vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !          1274:                goto try_again;
        !          1275:            }
        !          1276:            coptime++;
        !          1277:            hp = copper_time_hpos & (copi2 & 0xFE);
        !          1278:        }
        !          1279:     }
        !          1280:     if (coptime == 0) /* waiting for the blitter */
        !          1281:        return 1;
        !          1282: 
        !          1283:     return coptime;
        !          1284: }
        !          1285: 
        !          1286: static void copper_read(void)
        !          1287: {
        !          1288:     if (dmaen(DMA_COPPER)){
        !          1289:        copi1 = chipmem_bank.wget(coplc); 
        !          1290:        copi2 = chipmem_bank.wget(coplc+2);
        !          1291:        coplc += 4;
        !          1292:        eventtab[ev_copper].oldcycles = cycles;
        !          1293:        eventtab[ev_copper].evtime = ((copi1 & 1) ? (copi2 & 1) ? 10 : 8 : 4) + cycles;
        !          1294:        copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move;
        !          1295:     } else {
        !          1296:        copstate = COP_read;
        !          1297:        eventtab[ev_copper].active = 0;
        !          1298:     }
        !          1299: }
        !          1300: 
        !          1301: static void do_copper(void)
        !          1302: {    
        !          1303:     switch(copstate){
        !          1304:      case COP_read:
        !          1305:        copper_read();
        !          1306:        break;
        !          1307:      case COP_move:
        !          1308:        if (copi1 >= (copcon & 2 ? 0x40 : 0x80)) {
        !          1309:            custom_bank.wput(copi1,copi2);
        !          1310:            copper_read();
        !          1311:        } else {
        !          1312:            copstate = COP_stop;
        !          1313:            eventtab[ev_copper].active = 0;
        !          1314:            copper_active = 0;
        !          1315:        }
        !          1316:        break;
        !          1317:      case COP_skip:
        !          1318:        if (calc_copcomp_true(vpos, current_hpos()) == 0)
        !          1319:            coplc += 4;
        !          1320:        copper_read();
        !          1321:        break;
        !          1322:      case COP_wait: {      
        !          1323:         int coptime = calc_copcomp_true(vpos, current_hpos());
        !          1324:         if (coptime < 0) {
        !          1325:             copstate = COP_stop;
        !          1326:             eventtab[ev_copper].active = 0;
        !          1327:             copper_active = 0;
        !          1328:         } else {            
        !          1329:             if (!coptime)
        !          1330:                 copper_read();
        !          1331:             else {
        !          1332:                 eventtab[ev_copper].evtime = coptime + cycles;
        !          1333:                 eventtab[ev_copper].oldcycles = cycles;
        !          1334:             }
        !          1335:         }
        !          1336:         break;
        !          1337:      }
        !          1338:      case COP_stop:
        !          1339:        eventtab[ev_copper].active = 0;
        !          1340:        copper_active = 0;
        !          1341:        break;
        !          1342:     }
        !          1343: }
        !          1344: 
        !          1345: static void diskblk_handler(void)
        !          1346: {
        !          1347:     regs.spcflags |= SPCFLAG_DISK;
        !          1348:     eventtab[ev_diskblk].active = 0;
        !          1349: }
        !          1350: 
        !          1351: void do_disk(void)
        !          1352: {
        !          1353:     if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) {
        !          1354:        fprintf(stderr, "BUG!\n");
        !          1355:        return;
        !          1356:     }
        !          1357:     if (dmaen(0x10)){
        !          1358:        if (dsklen & 0x4000) {
        !          1359:            if (!chipmem_bank.check (dskpt, 2*dsklength)) {
        !          1360:                fprintf(stderr, "warning: Bad disk write DMA pointer\n");
        !          1361:            } else {
        !          1362:                UBYTE *mfmp = get_real_address (dskpt);
        !          1363:                int i;
        !          1364:                DISK_InitWrite();
        !          1365: 
        !          1366:                for (i = 0; i < dsklength; i++) {
        !          1367:                    UWORD d = (*mfmp << 8) + *(mfmp+1);
        !          1368:                    mfmwrite[i] = d;
        !          1369:                    mfmp += 2;
        !          1370:                }
        !          1371:                DISK_WriteData(dsklength);
        !          1372:            }
        !          1373:        } else {
        !          1374:            int result = DISK_ReadMFM (dskpt);
        !          1375:        }
        !          1376:        regs.spcflags &= ~SPCFLAG_DISK;
        !          1377:        INTREQ(0x9002);
        !          1378:        dskdmaen = -1;
        !          1379:     }
        !          1380: }
        !          1381: 
        !          1382: static __inline__ void pfield_fetchdata(void)
        !          1383: {
        !          1384:     if (dmaen(0x100) && pfield_linedmaon) {
        !          1385:        switch(bplplanecnt){
        !          1386:         case 8:
        !          1387:            bpl8dat = chipmem_bank.wget(bplpt[7]); bplpt[7] += 2; bpl8dat <<= 7;
        !          1388:         case 7:
        !          1389:            bpl7dat = chipmem_bank.wget(bplpt[6]); bplpt[6] += 2; bpl7dat <<= 6;
        !          1390:         case 6:
        !          1391:            bpl6dat = chipmem_bank.wget(bplpt[5]); bplpt[5] += 2; bpl6dat <<= 5;
        !          1392:         case 5:
        !          1393:            bpl5dat = chipmem_bank.wget(bplpt[4]); bplpt[4] += 2; bpl5dat <<= 4;
        !          1394:         case 4:
        !          1395:            bpl4dat = chipmem_bank.wget(bplpt[3]); bplpt[3] += 2; bpl4dat <<= 3;
        !          1396:         case 3:
        !          1397:            bpl3dat = chipmem_bank.wget(bplpt[2]); bplpt[2] += 2; bpl3dat <<= 2;
        !          1398:         case 2:
        !          1399:            bpl2dat = chipmem_bank.wget(bplpt[1]); bplpt[1] += 2; bpl2dat <<= 1;
        !          1400:         case 1:
        !          1401:            bpl1dat = chipmem_bank.wget(bplpt[0]); bplpt[0] += 2;
        !          1402:        }
        !          1403:     }
        !          1404: }
        !          1405: 
        !          1406: static void do_sprites(int currvp, int currhp)
        !          1407: {   
        !          1408:     int i;
        !          1409:     int maxspr = currhp/4 - 0x18/4;
        !          1410:     
        !          1411:     if (currvp == 0)
        !          1412:        return;
        !          1413:     if (maxspr < 0)
        !          1414:        return;
        !          1415:     if (maxspr > 7)
        !          1416:        maxspr = 7;
        !          1417:     
        !          1418:     for(i = last_sprite; i <= maxspr; i++) {
        !          1419:        int vstart = (bpl_info.sprpos[i] >> 8) | ((bpl_info.sprctl[i] << 6) & 0x100);
        !          1420:        int vstop = (bpl_info.sprctl[i] >> 8) | ((bpl_info.sprctl[i] << 7) & 0x100);
        !          1421:        if ((vstart <= currvp && vstop >= currvp) || spron[i] == 1) {
        !          1422:            if (dmaen(0x20)) {
        !          1423:                UWORD data1 = chipmem_bank.wget(sprpt[i]);
        !          1424:                UWORD data2 = chipmem_bank.wget(sprpt[i]+2);
        !          1425:                sprpt[i] += 4;
        !          1426:                
        !          1427:                if (vstop != currvp && spron[i] != 1) {
        !          1428:                    /* Hack for X mouse auto-calibration */
        !          1429:                    if (i == 0 && !sprvbfl && ((bpl_info.sprpos[0]&0xff)<<2)>0x60) {
        !          1430:                        spr0ctl=bpl_info.sprctl[0];
        !          1431:                        spr0pos=bpl_info.sprpos[0];
        !          1432:                        sprvbfl=2;
        !          1433:                    }
        !          1434:                    SPRxDATB_1(data2, i);
        !          1435:                    SPRxDATA_1(data1, i);
        !          1436:                } else {
        !          1437:                    SPRxPOS_1(data1, i);
        !          1438:                    SPRxCTL_1(data2, i);
        !          1439:                }
        !          1440:            }
        !          1441:        }
        !          1442:     }
        !          1443:     last_sprite = maxspr + 1;
        !          1444: }
        !          1445: 
        !          1446: static __inline__ void pfield_modulos(int add)
        !          1447: {
        !          1448:     switch(bplplanecnt){
        !          1449:      case 8:
        !          1450:        bplpt[7] += add + bpl2mod;
        !          1451:      case 7:
        !          1452:        bplpt[6] += add + bpl1mod;
        !          1453:      case 6:
        !          1454:        bplpt[5] += add + bpl2mod;
        !          1455:      case 5:
        !          1456:        bplpt[4] += add + bpl1mod;
        !          1457:      case 4:
        !          1458:        bplpt[3] += add + bpl2mod;
        !          1459:      case 3:
        !          1460:        bplpt[2] += add + bpl1mod;
        !          1461:      case 2:
        !          1462:        bplpt[1] += add + bpl2mod;
        !          1463:      case 1:
        !          1464:        bplpt[0] += add + bpl1mod;
        !          1465:     }
        !          1466: }
        !          1467: 
        !          1468: #if AGA_CHIPSET == 0
        !          1469: static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb, int lores)
        !          1470: {
        !          1471:     int i;
        !          1472: 
        !          1473:     int *lookup = bpldualpf ? (bpldualpfpri ? dblpf_ind2 : dblpf_ind1) : linear_map_256;
        !          1474:     int *lookup_no = bpldualpf ? (bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1) : lots_of_twos;
        !          1475: 
        !          1476:     for(i = 15; i >= 0; i--, data >>= 1, datb >>= 1) {
        !          1477:        int sprxpos = sprxp + i*(lores ? 1 : 2);
        !          1478:        int plno;
        !          1479:        int col;
        !          1480: 
        !          1481:        /* When doing the slow line update, the following condition can
        !          1482:         * happen. Lower-numbered sprites get the higher priority. */
        !          1483:        if (spixstate[sprxpos] & ((1 << num)-1))
        !          1484:            continue;
        !          1485: 
        !          1486:        /* Check the priority, but only if we did not already put a sprite
        !          1487:         * pixel at this position. If there's already a sprite pixel here, 
        !          1488:         * the priority was previously tested. */
        !          1489:        if (!spixstate[sprxpos]) {
        !          1490:            /* ??? What about hires mode when one hires pixel is 0, enabling the
        !          1491:             * sprite, and the other is != 0, blocking it? */
        !          1492:            plno = lookup_no[pixdata.apixels[sprxpos]];
        !          1493:            if (plno != 0 && (1 << num) >= plfpri[plno])
        !          1494:                continue;
        !          1495:        }
        !          1496: 
        !          1497:        if ((bpl_info.sprctl[num] & 0x80) && (num & 1)) {
        !          1498:            /* Attached sprite */
        !          1499:            col = ((data << 2) & 4) + ((datb << 3) & 8);
        !          1500:            spixstate[sprxpos] |= 1 << (num-1);
        !          1501:            spixels[sprxpos] = col;
        !          1502:        } else {                        
        !          1503:            col = (data & 1) | ((datb << 1) & 2);
        !          1504:            if (spixstate[sprxpos] & (1 << num)) {
        !          1505:                /* Finish attached sprite */
        !          1506:                /* Did the upper half of the sprite have any bits set? */
        !          1507:                if (spixstate[sprxpos] & (1 << (num+1)))
        !          1508:                    col += spixels[sprxpos];
        !          1509:                /* Is there any sprite pixel at this position at all? */
        !          1510:                if (!col) {
        !          1511:                    spixstate[sprxpos] &= ~(3 << num);
        !          1512:                } else
        !          1513:                    col += 16;
        !          1514:            } else {
        !          1515:                if (col) {
        !          1516:                    col |= 16 | ((num & 6) << 1);
        !          1517:                }
        !          1518:            }
        !          1519:        }
        !          1520:        if (col) {
        !          1521:            pixdata.apixels[sprxpos] = col;
        !          1522:            spixstate[sprxpos] |= 1<<num;
        !          1523:            if (!lores) {
        !          1524:                pixdata.apixels[sprxpos+1] = col;
        !          1525:                spixstate[sprxpos+1] |= 1<<num;
        !          1526:            }
        !          1527:            if (bplham && bplplanecnt == 6) {
        !          1528:                ham_linebuf[sprxpos] = bpl_info.color_regs[col];
        !          1529:                if (!lores)
        !          1530:                    ham_linebuf[sprxpos+1] = bpl_info.color_regs[col];
        !          1531:            }
        !          1532:        }
        !          1533:     }
        !          1534: }
        !          1535: #else /* AGA version */
        !          1536: static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb, int lores)
        !          1537: {
        !          1538:     int i;
        !          1539: 
        !          1540:     int *lookup = bpldualpf ? (bpldualpfpri ? dblpf_ind2 : dblpf_ind1) : linear_map_256;
        !          1541:     int *lookup_no = bpldualpf ? (bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1) : lots_of_twos;
        !          1542: 
        !          1543:     for(i = 15; i >= 0; i--, data >>= 1, datb >>= 1) {
        !          1544:        int sprxpos = sprxp + i*(lores ? 1 : 2);
        !          1545:        int plno;
        !          1546:        int col;
        !          1547: 
        !          1548:        /* When doing the slow line update, the following condition can
        !          1549:         * happen. Lower-numbered sprites get the higher priority. */
        !          1550:        if (spixstate[sprxpos] & ((1 << num)-1))
        !          1551:            continue;
        !          1552: 
        !          1553:        /* Check the priority, but only if we did not already put a sprite
        !          1554:         * pixel at this position. If there's already a sprite pixel here, 
        !          1555:         * the priority was previously tested. */
        !          1556:        if (!spixstate[sprxpos]) {
        !          1557:            /* ??? What about hires mode when one hires pixel is 0, enabling the
        !          1558:             * sprite, and the other is != 0, blocking it? */
        !          1559:            plno = lookup_no[pixdata.apixels[sprxpos]];
        !          1560:            if (plno != 0 && (1 << num) >= plfpri[plno])
        !          1561:                continue;
        !          1562:        }
        !          1563: 
        !          1564:        if ((bpl_info.sprctl[num] & 0x80) && (num & 1)) {
        !          1565:            /* Attached sprite */
        !          1566:            col = ((data << 2) & 4) + ((datb << 3) & 8);
        !          1567:            spixstate[sprxpos] |= 1 << (num-1);
        !          1568:            spixels[sprxpos] = col;
        !          1569:        } else {                        
        !          1570:            col = (data & 1) | ((datb << 1) & 2);
        !          1571:            if (spixstate[sprxpos] & (1 << num)) {
        !          1572:                /* Finish attached sprite */
        !          1573:                /* Did the upper half of the sprite have any bits set? */
        !          1574:                if (spixstate[sprxpos] & (1 << (num+1)))
        !          1575:                    col += spixels[sprxpos];
        !          1576:                /* Is there any sprite pixel at this position at all? */
        !          1577:                if (!col) {
        !          1578:                    spixstate[sprxpos] &= ~(3 << num);
        !          1579:                } else
        !          1580:                    col += ((bpl_info.bplcon4 << (num & 1 ? 4 : 0)) & 240);
        !          1581:            } else {
        !          1582:                if (col) {
        !          1583:                    col |= ((bpl_info.bplcon4 << (num & 1 ? 4 : 0)) & 240) | ((num & 6) << 1);
        !          1584:                }
        !          1585:            }
        !          1586:        }
        !          1587:        if (col) {
        !          1588:            pixdata.apixels[sprxpos] = col;
        !          1589:            spixstate[sprxpos] |= 1<<num;
        !          1590:            if (!lores) {
        !          1591:                pixdata.apixels[sprxpos+1] = col;
        !          1592:                spixstate[sprxpos+1] |= 1<<num;
        !          1593:            }
        !          1594:            if (bplham && bplplanecnt == 6) {
        !          1595:                ham_linebuf[sprxpos] = bpl_info.color_regs[col];
        !          1596:                if (!lores)
        !          1597:                    ham_linebuf[sprxpos+1] = bpl_info.color_regs[col];
        !          1598:            }
        !          1599:        }
        !          1600:     }
        !          1601: }
        !          1602: #endif
        !          1603: 
        !          1604: static __inline__ UBYTE *pfield_xlateptr(CPTR plpt, int bytecount)
        !          1605: {
        !          1606:     if (!chipmem_bank.check(plpt,bytecount)) {
        !          1607:        static int count = 0;
        !          1608:        if (count < 5) {
        !          1609:            count++;
        !          1610:            fprintf(stderr, "Warning: Bad playfield pointer");
        !          1611:            if (count == 5) fprintf(stderr, " (no further warnings)");
        !          1612:            fprintf(stderr, "\n");
        !          1613:        }
        !          1614:        return NULL;
        !          1615:     }
        !          1616:     return chipmem_bank.xlateaddr(plpt);
        !          1617: }
        !          1618: 
        !          1619: static void pfield_doline_slow_h(int currhpos)
        !          1620: {
        !          1621:     int xpos = currhpos * 4 - 0x60;
        !          1622:            
        !          1623:     if (bplhires) {
        !          1624:        int offs1 = xpos + 16 + bpldelay1*2;
        !          1625:        int offs2 = xpos + 16 + bpldelay2*2;
        !          1626:        
        !          1627:        int pix;
        !          1628:        for(pix = 15; pix >= 0; pix--) {
        !          1629:            switch(bplplanecnt) {
        !          1630:             case 8:
        !          1631:                pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 1;
        !          1632:             case 7:
        !          1633:                pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 1;
        !          1634:             case 6:
        !          1635:                pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 1;
        !          1636:             case 5:
        !          1637:                pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 1;
        !          1638:             case 4:
        !          1639:                pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1;
        !          1640:             case 3:
        !          1641:                pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1;
        !          1642:             case 2:
        !          1643:                pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1;
        !          1644:             case 1:
        !          1645:                pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1;
        !          1646:            }
        !          1647:        }
        !          1648:     } else {
        !          1649:        int offs1 = xpos + 32 + bpldelay1*2;
        !          1650:        int offs2 = xpos + 32 + bpldelay2*2;
        !          1651:        
        !          1652:        int pix;
        !          1653:        for(pix = 30; pix >= 0; pix -= 2) {
        !          1654:            switch(bplplanecnt) {
        !          1655:             case 8:
        !          1656:                pixdata.apixels[pix + offs2] |= bpl8dat & 0x80;
        !          1657:                pixdata.apixels[pix + offs2 + 1] |= bpl8dat & 0x80; bpl8dat >>= 1;
        !          1658:             case 7:
        !          1659:                pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; 
        !          1660:                pixdata.apixels[pix + offs1 + 1] |= bpl7dat & 0x40; bpl7dat >>= 1;
        !          1661:             case 6:
        !          1662:                pixdata.apixels[pix + offs2] |= bpl6dat & 0x20;
        !          1663:                pixdata.apixels[pix + offs2 + 1] |= bpl6dat & 0x20; bpl6dat >>= 1;
        !          1664:             case 5:
        !          1665:                pixdata.apixels[pix + offs1] |= bpl5dat & 0x10;
        !          1666:                pixdata.apixels[pix + offs1 + 1] |= bpl5dat & 0x10; bpl5dat >>= 1;
        !          1667:             case 4:
        !          1668:                pixdata.apixels[pix + offs2] |= bpl4dat & 0x8;
        !          1669:                pixdata.apixels[pix + offs2 + 1] |= bpl4dat & 0x8; bpl4dat >>= 1;
        !          1670:             case 3:
        !          1671:                pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; 
        !          1672:                pixdata.apixels[pix + offs1 + 1] |= bpl3dat & 0x4; bpl3dat >>= 1;
        !          1673:             case 2:
        !          1674:                pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; 
        !          1675:                pixdata.apixels[pix + offs2 + 1] |= bpl2dat & 0x2; bpl2dat >>= 1;
        !          1676:             case 1:
        !          1677:                pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; 
        !          1678:                pixdata.apixels[pix + offs1 + 1] |= bpl1dat & 0x1; bpl1dat >>= 1;
        !          1679:            }
        !          1680:        }
        !          1681:     }  
        !          1682: }
        !          1683: 
        !          1684: static void pfield_doline_slow_l(int currhpos)
        !          1685: {
        !          1686:     int xpos = currhpos * 2 - 0x30;
        !          1687:     
        !          1688:     if (bplhires) {
        !          1689:        int offs1 = xpos + 8 + bpldelay1;
        !          1690:        int offs2 = xpos + 8 + bpldelay2;
        !          1691:        
        !          1692:        int pix;
        !          1693:        for(pix = 7; pix >= 0; pix--) {
        !          1694:            switch(bplplanecnt) {
        !          1695:             case 8:
        !          1696:                pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 2;
        !          1697:             case 7:
        !          1698:                pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 2;
        !          1699:             case 6:
        !          1700:                pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 2;
        !          1701:             case 5:
        !          1702:                pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 2;
        !          1703:             case 4:
        !          1704:                pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 2;
        !          1705:             case 3:
        !          1706:                pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 2;
        !          1707:             case 2:
        !          1708:                pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 2;
        !          1709:             case 1:
        !          1710:                pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 2;
        !          1711:            }
        !          1712:        }
        !          1713:     } else {
        !          1714:        int offs1 = xpos + 16 + bpldelay1;
        !          1715:        int offs2 = xpos + 16 + bpldelay2;
        !          1716:        
        !          1717:        int pix;
        !          1718:        for(pix = 15; pix >= 0; pix --) {
        !          1719:            switch(bplplanecnt) {
        !          1720:             case 8:
        !          1721:                pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 1;
        !          1722:             case 7:
        !          1723:                pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 1;
        !          1724:             case 6:
        !          1725:                pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 1;
        !          1726:             case 5:
        !          1727:                pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 1;
        !          1728:             case 4:
        !          1729:                pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1;
        !          1730:             case 3:
        !          1731:                pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1;
        !          1732:             case 2:
        !          1733:                pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1;
        !          1734:             case 1:
        !          1735:                pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1;
        !          1736:            }
        !          1737:        }
        !          1738:     }  
        !          1739: }
        !          1740: 
        !          1741: ULONG hirestab_h[256][2];
        !          1742: ULONG lorestab_h[256][4];
        !          1743: 
        !          1744: ULONG hirestab_l[256][1];
        !          1745: ULONG lorestab_l[256][2];
        !          1746: 
        !          1747: static void gen_pfield_tables(void)
        !          1748: {
        !          1749:     int i;
        !          1750:     union {
        !          1751:        struct {
        !          1752:            UBYTE a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
        !          1753:        } foo;
        !          1754:        struct {
        !          1755:            ULONG a, b, c, d;
        !          1756:        } bar;
        !          1757:     } baz;
        !          1758:     
        !          1759:     for (i = 0; i < 256; i++) {
        !          1760:        /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
        !          1761:        baz.foo.a = i & 64 ? 1 : 0;
        !          1762:        baz.foo.b = i & 16 ? 1 : 0;
        !          1763:        baz.foo.c = i & 4 ? 1 : 0;
        !          1764:        baz.foo.d = i & 1 ? 1 : 0;
        !          1765:        hirestab_l[i][0] = baz.bar.a;
        !          1766:        
        !          1767:        baz.foo.a = i & 128 ? 1 : 0;
        !          1768:        baz.foo.b = i & 64 ? 1 : 0;
        !          1769:        baz.foo.c = i & 32 ? 1 : 0;
        !          1770:        baz.foo.d = i & 16 ? 1 : 0;
        !          1771:        baz.foo.e = i & 8 ? 1 : 0;
        !          1772:        baz.foo.f = i & 4 ? 1 : 0;
        !          1773:        baz.foo.g = i & 2 ? 1 : 0;
        !          1774:        baz.foo.h = i & 1 ? 1 : 0;
        !          1775:        lorestab_l[i][0] = baz.bar.a;
        !          1776:        lorestab_l[i][1] = baz.bar.b;
        !          1777:     }
        !          1778:     
        !          1779:     for (i = 0; i < 256; i++) {
        !          1780:        baz.foo.a = i & 128 ? 1 : 0;
        !          1781:        baz.foo.b = i & 64 ? 1 : 0;
        !          1782:        baz.foo.c = i & 32 ? 1 : 0;
        !          1783:        baz.foo.d = i & 16 ? 1 : 0;
        !          1784:        baz.foo.e = i & 8 ? 1 : 0;
        !          1785:        baz.foo.f = i & 4 ? 1 : 0;
        !          1786:        baz.foo.g = i & 2 ? 1 : 0;
        !          1787:        baz.foo.h = i & 1 ? 1 : 0;
        !          1788:        hirestab_h[i][0] = baz.bar.a;
        !          1789:        hirestab_h[i][1] = baz.bar.b;
        !          1790:        
        !          1791:        baz.foo.a = i & 128 ? 1 : 0;
        !          1792:        baz.foo.b = i & 128 ? 1 : 0;
        !          1793:        baz.foo.c = i & 64 ? 1 : 0;
        !          1794:        baz.foo.d = i & 64 ? 1 : 0;
        !          1795:        baz.foo.e = i & 32 ? 1 : 0;
        !          1796:        baz.foo.f = i & 32 ? 1 : 0;
        !          1797:        baz.foo.g = i & 16 ? 1 : 0;
        !          1798:        baz.foo.h = i & 16 ? 1 : 0;
        !          1799:        baz.foo.i = i & 8 ? 1 : 0;
        !          1800:        baz.foo.j = i & 8 ? 1 : 0;
        !          1801:        baz.foo.k = i & 4 ? 1 : 0;
        !          1802:        baz.foo.l = i & 4 ? 1 : 0;
        !          1803:        baz.foo.m = i & 2 ? 1 : 0;
        !          1804:        baz.foo.n = i & 2 ? 1 : 0;
        !          1805:        baz.foo.o = i & 1 ? 1 : 0;
        !          1806:        baz.foo.p = i & 1 ? 1 : 0;
        !          1807:        lorestab_h[i][0] = baz.bar.a;
        !          1808:        lorestab_h[i][1] = baz.bar.b;
        !          1809:        lorestab_h[i][2] = baz.bar.c;
        !          1810:        lorestab_h[i][3] = baz.bar.d;
        !          1811:     }
        !          1812: }
        !          1813: 
        !          1814: static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
        !          1815: {
        !          1816:     ULONG *pixptr = (ULONG *)dp;
        !          1817: 
        !          1818:     *pixptr |= hirestab_h[data >> 8][0] << bit;
        !          1819:     *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
        !          1820:     *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
        !          1821:     *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
        !          1822: }
        !          1823: 
        !          1824: static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
        !          1825: {
        !          1826:     ULONG *pixptr = (ULONG *)dp;
        !          1827:     
        !          1828:     *pixptr |= lorestab_h[data >> 8][0] << bit;
        !          1829:     *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
        !          1830:     *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
        !          1831:     *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
        !          1832:     *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
        !          1833:     *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
        !          1834:     *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
        !          1835:     *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
        !          1836: }
        !          1837: 
        !          1838: static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
        !          1839: {
        !          1840:     ULONG *pixptr = (ULONG *)dp;
        !          1841: 
        !          1842:     *pixptr = hirestab_h[data >> 8][0] << bit;
        !          1843:     *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
        !          1844:     *(pixptr+2) = hirestab_h[data & 255][0] << bit;
        !          1845:     *(pixptr+3) = hirestab_h[data & 255][1] << bit;
        !          1846: }
        !          1847: 
        !          1848: static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
        !          1849: {
        !          1850:     ULONG *pixptr = (ULONG *)dp;
        !          1851:     
        !          1852:     *pixptr = lorestab_h[data >> 8][0] << bit;
        !          1853:     *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
        !          1854:     *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
        !          1855:     *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
        !          1856:     *(pixptr+4) = lorestab_h[data & 255][0] << bit;
        !          1857:     *(pixptr+5) = lorestab_h[data & 255][1] << bit;
        !          1858:     *(pixptr+6) = lorestab_h[data & 255][2] << bit;
        !          1859:     *(pixptr+7) = lorestab_h[data & 255][3] << bit;
        !          1860: }
        !          1861: 
        !          1862: static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
        !          1863: {
        !          1864:     ULONG *pixptr = (ULONG *)dp;
        !          1865: 
        !          1866:     *pixptr |= hirestab_l[data >> 8][0] << bit;
        !          1867:     *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
        !          1868: }
        !          1869: 
        !          1870: static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
        !          1871: {
        !          1872:     ULONG *pixptr = (ULONG *)dp;
        !          1873:     
        !          1874:     *pixptr |= lorestab_l[data >> 8][0] << bit;
        !          1875:     *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
        !          1876:     *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
        !          1877:     *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
        !          1878: }
        !          1879: 
        !          1880: static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
        !          1881: {
        !          1882:     ULONG *pixptr = (ULONG *)dp;
        !          1883: 
        !          1884:     *pixptr = hirestab_l[data >> 8][0] << bit;
        !          1885:     *(pixptr+1) = hirestab_l[data & 255][0] << bit;
        !          1886: }
        !          1887: 
        !          1888: static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
        !          1889: {
        !          1890:     ULONG *pixptr = (ULONG *)dp;
        !          1891:     
        !          1892:     *pixptr = lorestab_l[data >> 8][0] << bit;
        !          1893:     *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
        !          1894:     *(pixptr+2) = lorestab_l[data & 255][0] << bit;
        !          1895:     *(pixptr+3) = lorestab_l[data & 255][1] << bit;
        !          1896: }
        !          1897: 
        !          1898: #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
        !          1899:     int i; \
        !          1900:     unsigned int bpldat1; \
        !          1901:     UWORD data; \
        !          1902:     unsigned int bpldat2 = 0; \
        !          1903:     for (i = plflinelen; i > 0; i -= LL_SUB) { \
        !          1904:         bpldat1 = bpldat2; \
        !          1905:        bpldat2 = (*POINTER << 8) | *(POINTER+1); \
        !          1906:         POINTER+=2; \
        !          1907:        data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
        !          1908:        FUNC(data, app, MULT); \
        !          1909:        app += P_ADD; \
        !          1910:     } \
        !          1911:     data = bpldat2 << (16 - DELAY); \
        !          1912:     FUNC(data, app, MULT); \
        !          1913: }
        !          1914: 
        !          1915: #if 1
        !          1916: static void pfield_doline_h(void)
        !          1917: {
        !          1918:     int xpos = plfstrt * 4 - 0x60;
        !          1919:     int spr, sprites_seen;
        !          1920: 
        !          1921:     if (bplhires) {
        !          1922:        if (bplplanecnt > 0) {
        !          1923:            int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
        !          1924:            int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
        !          1925:            int delay1 = 2*(bpldelay1 & 7);
        !          1926:            int delay2 = 2*(bpldelay2 & 7);
        !          1927:            unsigned char *app = pixdata.apixels + xpos1;
        !          1928: 
        !          1929:            DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_hires_h, delay1, 4, 16);
        !          1930:            if (bplplanecnt > 2) {
        !          1931:                app = pixdata.apixels + xpos1;
        !          1932:                DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_hires_h, delay1, 4, 16);
        !          1933:            }
        !          1934: #if AGA_CHIPSET == 1
        !          1935:            if (bplplanecnt > 4) {
        !          1936:                app = pixdata.apixels + xpos1;
        !          1937:                DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_hires_h, delay1, 4, 16);
        !          1938:            }
        !          1939:            if (bplplanecnt > 6) {
        !          1940:                app = pixdata.apixels + xpos1;
        !          1941:                DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_hires_h, delay1, 4, 16);
        !          1942:            }
        !          1943: #endif
        !          1944:            if (bplplanecnt > 1) {
        !          1945:                app = pixdata.apixels + xpos2;
        !          1946:                DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_hires_h, delay2, 4, 16);
        !          1947:            }
        !          1948:            if (bplplanecnt > 3) {
        !          1949:                app = pixdata.apixels + xpos2;
        !          1950:                DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_hires_h, delay2, 4, 16);
        !          1951:            }
        !          1952: #if AGA_CHIPSET == 1
        !          1953:            if (bplplanecnt > 5) {
        !          1954:                app = pixdata.apixels + xpos2;
        !          1955:                DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_hires_h, delay2, 4, 16);
        !          1956:            }
        !          1957:            if (bplplanecnt > 7) {
        !          1958:                app = pixdata.apixels + xpos2;
        !          1959:                DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_hires_h, delay2, 4, 16);
        !          1960:            }
        !          1961: #endif
        !          1962:        } else {
        !          1963:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
        !          1964:        }
        !          1965:     } else {
        !          1966:        if (bplplanecnt > 0) {
        !          1967:            int x = xpos + 32;
        !          1968:            unsigned char *app = pixdata.apixels + x;
        !          1969:            
        !          1970:            DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_lores_h, bpldelay1, 8, 32);
        !          1971:            if (bplplanecnt > 2) {
        !          1972:                app = pixdata.apixels + x;
        !          1973:                DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_lores_h, bpldelay1, 8, 32);
        !          1974:            }
        !          1975:            if (bplplanecnt > 4) {
        !          1976:                app = pixdata.apixels + x;
        !          1977:                DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_lores_h, bpldelay1, 8, 32);
        !          1978:            }
        !          1979: #if AGA_CHIPSET == 1
        !          1980:            if (bplplanecnt > 6) {
        !          1981:                app = pixdata.apixels + x;
        !          1982:                DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_lores_h, bpldelay1, 8, 32);
        !          1983:            }
        !          1984: #endif
        !          1985:            if (bplplanecnt > 1) {
        !          1986:                app = pixdata.apixels + x;
        !          1987:                DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_lores_h, bpldelay2, 8, 32);
        !          1988:            }
        !          1989:            if (bplplanecnt > 3) {
        !          1990:                app = pixdata.apixels + x;
        !          1991:                DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_lores_h, bpldelay2, 8, 32);
        !          1992:            }
        !          1993:            if (bplplanecnt > 5) {
        !          1994:                app = pixdata.apixels + x;
        !          1995:                DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_lores_h, bpldelay2, 8, 32);
        !          1996:            }
        !          1997: #if AGA_CHIPSET == 1
        !          1998:            if (bplplanecnt > 7) {
        !          1999:                app = pixdata.apixels + x;
        !          2000:                DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_lores_h, bpldelay2, 8, 32);
        !          2001:            }
        !          2002: #endif
        !          2003:        } else {
        !          2004:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
        !          2005:        }
        !          2006:     }
        !          2007:     
        !          2008:     decode_ham6 (16,812);
        !          2009:                
        !          2010:     linetoscreen = 1;
        !          2011:     sprites_seen = 0;
        !          2012:     
        !          2013:     for(spr = 7; spr >= 0; spr--) {
        !          2014:        if (bpl_info.sprarmed[spr]) {
        !          2015:            int sprxp = ((bpl_info.sprpos[spr] & 0xFF) * 4) - 0x60 + (bpl_info.sprctl[spr] & 1)*2;
        !          2016:            int i;
        !          2017:            /* Ugh. Nasty bug. Let's rather lose some sprites than trash
        !          2018:             * memory. */
        !          2019:            if (sprxp >= 0) {
        !          2020:                if (!sprites_seen) {
        !          2021:                    sprites_seen = 1;
        !          2022:                    memset(spixstate,0,sizeof spixstate);
        !          2023:                }
        !          2024:                pfield_sprite (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr], 0);
        !          2025:            }
        !          2026:        }
        !          2027:     }
        !          2028: }
        !          2029: #endif
        !          2030: static void pfield_doline_l(void)
        !          2031: {
        !          2032:     int xpos = plfstrt * 2 - 0x30;
        !          2033:     int spr;
        !          2034:     int sprites_seen;
        !          2035:         
        !          2036:     if (bplhires) {
        !          2037:        if (bplplanecnt > 0) {
        !          2038:            int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
        !          2039:            int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
        !          2040:            int delay1 = (bpldelay1 & 7) * 2;
        !          2041:            int delay2 = (bpldelay2 & 7) * 2;
        !          2042:            unsigned char *app = pixdata.apixels + xpos1;
        !          2043:            
        !          2044:            DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_hires_l, delay1, 4, 8);
        !          2045:            if (bplplanecnt > 2) {
        !          2046:                app = pixdata.apixels + xpos1;
        !          2047:                DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_hires_l, delay1, 4, 8);
        !          2048:            }
        !          2049: #if AGA_CHIPSET == 1
        !          2050:            if (bplplanecnt > 4) {
        !          2051:                app = pixdata.apixels + xpos1;
        !          2052:                DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_hires_l, delay1, 4, 8);
        !          2053:            }
        !          2054:            if (bplplanecnt > 6) {
        !          2055:                app = pixdata.apixels + xpos1;
        !          2056:                DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_hires_l, delay1, 4, 8);
        !          2057:            }
        !          2058: #endif
        !          2059:            if (bplplanecnt > 1) {
        !          2060:                app = pixdata.apixels + xpos2;
        !          2061:                DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_hires_l, delay2, 4, 8);
        !          2062:            }
        !          2063:            if (bplplanecnt > 3) {
        !          2064:                app = pixdata.apixels + xpos2;
        !          2065:                DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_hires_l, delay2, 4, 8);
        !          2066:            }
        !          2067: #if AGA_CHIPSET == 1
        !          2068:            if (bplplanecnt > 5) {
        !          2069:                app = pixdata.apixels + xpos2;
        !          2070:                DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_hires_l, delay2, 4, 8);
        !          2071:            }
        !          2072:            if (bplplanecnt > 7) {
        !          2073:                app = pixdata.apixels + xpos2;
        !          2074:                DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_hires_l, delay2, 4, 8);
        !          2075:            }
        !          2076: #endif
        !          2077:        } else {
        !          2078:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
        !          2079:        }
        !          2080:     } else {
        !          2081:        if (bplplanecnt > 0) {
        !          2082:            int x = xpos + 16;
        !          2083:            int delay1 = bpldelay1;
        !          2084:            int delay2 = bpldelay2;
        !          2085:            unsigned char *app = pixdata.apixels + x;
        !          2086:            DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_lores_l, delay1, 8, 16);
        !          2087:            if (bplplanecnt > 2) {
        !          2088:                app = pixdata.apixels + x;
        !          2089:                DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_lores_l, delay1, 8, 16);
        !          2090:            }
        !          2091:            if (bplplanecnt > 4) {
        !          2092:                app = pixdata.apixels + x;
        !          2093:                DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_lores_l, delay1, 8, 16);
        !          2094:            }
        !          2095: #if AGA_CHIPSET == 1
        !          2096:            if (bplplanecnt > 6) {
        !          2097:                app = pixdata.apixels + x;
        !          2098:                DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_lores_l, delay1, 8, 16);
        !          2099:            }
        !          2100: #endif
        !          2101:            if (bplplanecnt > 1) {
        !          2102:                app = pixdata.apixels + x;
        !          2103:                DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_lores_l, delay2, 8, 16);
        !          2104:            }
        !          2105:            if (bplplanecnt > 3) {
        !          2106:                app = pixdata.apixels + x;
        !          2107:                DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_lores_l, delay2, 8, 16);
        !          2108:            }
        !          2109:            if (bplplanecnt > 5) {
        !          2110:                app = pixdata.apixels + x;
        !          2111:                DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_lores_l, delay2, 8, 16);
        !          2112:            }
        !          2113: #if AGA_CHIPSET == 1
        !          2114:            if (bplplanecnt > 7) {
        !          2115:                app = pixdata.apixels + x;
        !          2116:                DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_lores_l, delay2, 8, 16);
        !          2117:            }
        !          2118: #endif
        !          2119:        } else {
        !          2120:            memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
        !          2121:        }
        !          2122:     }
        !          2123: 
        !          2124:     decode_ham6 (8,406);
        !          2125: 
        !          2126:     linetoscreen = 1;
        !          2127:     sprites_seen = 0;
        !          2128: 
        !          2129:     for(spr = 7; spr >= 0; spr--) {
        !          2130:        if (bpl_info.sprarmed[spr]) {
        !          2131:            int sprxp = ((bpl_info.sprpos[spr] & 0xFF) * 2) - 0x30 + (bpl_info.sprctl[spr] & 1);
        !          2132:            int i;
        !          2133:            /* Ugh. Nasty bug. Let's rather lose some sprites than trash
        !          2134:             * memory. */
        !          2135:            if (sprxp >= 0) {
        !          2136:                if (!sprites_seen) {
        !          2137:                    sprites_seen = 1;
        !          2138:                    memset(spixstate,0,sizeof spixstate);
        !          2139:                }
        !          2140:                pfield_sprite (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr], 1);
        !          2141:            }
        !          2142:        }
        !          2143:     }
        !          2144: }
        !          2145: 
        !          2146: static int bpl_data_differs(UBYTE *data, UBYTE *r_addr, int nbytes)
        !          2147: {
        !          2148:     return memcmpy(data, r_addr, nbytes);
        !          2149: }
        !          2150: 
        !          2151: static __inline__ int bplinfo_differs(struct bplinfo *a, struct bplinfo *b)
        !          2152: {
        !          2153:     int ncolors;
        !          2154:     int i;
        !          2155:     if (a->bplcon0 != b->bplcon0
        !          2156:        || a->bplcon1 != b->bplcon1
        !          2157:        || a->bplcon2 != b->bplcon2
        !          2158:        || a->bplcon3 != b->bplcon3
        !          2159:        || a->bplcon4 != b->bplcon4
        !          2160:        || a->diwstrt != b->diwstrt
        !          2161:        || a->diwstop != b->diwstop
        !          2162:        || a->ddfstrt != b->ddfstrt
        !          2163:        || a->ddfstop != b->ddfstop)
        !          2164:        return 1;
        !          2165: 
        !          2166: #if 1
        !          2167:     /* This sometimes loses for sprite colors */
        !          2168:     ncolors = 1 << ((a->bplcon0 & 0x7000) >> 12);
        !          2169:     if (ncolors == 64)
        !          2170:        ncolors = (a->bplcon0 & 0x800) ? 16 : 32;
        !          2171:     for (i = 0; i < ncolors; i++)
        !          2172:        if (a->color_regs[i] != b->color_regs[i])
        !          2173:            return 1;
        !          2174: #else
        !          2175:     /* ... and this will lose badly on few-color screens when we implement 
        !          2176:      * AGA.
        !          2177:      */
        !          2178:     if (memcmp(a->color_regs, b->color_regs, sizeof a->color_regs) != 0)
        !          2179:        return 1;
        !          2180: #endif
        !          2181:     for (i = 0; i < 8; i++) {
        !          2182:        if (a->sprarmed[i] != b->sprarmed[i])
        !          2183:            return 1;
        !          2184:        if (a->sprarmed[i]
        !          2185:            && (a->sprctl[i] != b->sprctl[i]
        !          2186:                || a->sprpos[i] != b->sprpos[i]
        !          2187:                || a->sprdata[i] != b->sprdata[i]
        !          2188:                || a->sprdatb[i] != b->sprdatb[i]))
        !          2189:            return 1;
        !          2190:     }
        !          2191:     return 0;
        !          2192: }
        !          2193: 
        !          2194: static void pfield_doline(void)
        !          2195: {
        !          2196:     int bytecount = plflinelen / (bplhires ? 4 : 8) * 2;
        !          2197:     int drawit = 0;
        !          2198:     int i;
        !          2199:     
        !          2200:     if (vpos < plffirstline || vpos >= plflastline) 
        !          2201:        return;
        !          2202: 
        !          2203:     if (!dmaen(0x100) || !pfield_linedmaon) {
        !          2204:        line_in_border = 1;
        !          2205:        return;
        !          2206:     }
        !          2207:     
        !          2208:     for (i = 0; i < bplplanecnt; i++) {
        !          2209:        r_bplpt[i] = pfield_xlateptr(bplpt[i], bytecount);
        !          2210:        if (r_bplpt[i] == NULL)
        !          2211:            return;
        !          2212:     }
        !          2213:     
        !          2214: #if SMART_UPDATE == 1
        !          2215:     drawit = bplinfo_differs(&bpl_info, &linedescr[next_lineno].bpl_info);
        !          2216:     if (drawit) {
        !          2217:        linedescr[next_lineno].bpl_info = bpl_info;
        !          2218:     }
        !          2219:     drawit |= !linedescr[next_lineno].linedata_valid | frame_redraw_necessary;
        !          2220:        
        !          2221:     if (bytecount <= MAX_WORDS_PER_LINE * 2) {
        !          2222:        linedescr[next_lineno].linedata_valid = 1;
        !          2223:        for (i = 0; i < bplplanecnt; i++)
        !          2224:            drawit |= bpl_data_differs(line_data[next_lineno][i],r_bplpt[i],
        !          2225:                                       bytecount);
        !          2226:        
        !          2227:     } else {
        !          2228:        linedescr[next_lineno].linedata_valid = 0;
        !          2229:     }
        !          2230: #endif
        !          2231: 
        !          2232:     pfield_modulos(bytecount);
        !          2233: 
        !          2234: #if SMART_UPDATE != 0
        !          2235:     if (!drawit)
        !          2236:        return;
        !          2237: #endif    
        !          2238: 
        !          2239:     if (use_lores)
        !          2240:        pfield_doline_l();
        !          2241:     else
        !          2242:        pfield_doline_h();
        !          2243: }
        !          2244: 
        !          2245: static void pfield_doline_slow(int currhp)
        !          2246: {
        !          2247:     int xpos = PIXEL_XPOS(currhp);
        !          2248: 
        !          2249:     if (vpos < plffirstline || vpos >= plflastline) 
        !          2250:        return;
        !          2251:     
        !          2252:     if (currhp == plfstrt)
        !          2253:        slowline_nextpos = currhp;
        !          2254: 
        !          2255:     if (currhp == slowline_nextpos) {    
        !          2256:        if (slowline_linepos >= plflinelen) {
        !          2257:            /* The modulos must get added at exactly this point. */
        !          2258:            pfield_modulos(0);
        !          2259:            slowline_nextpos = -1;
        !          2260:        } else {
        !          2261:            slowline_nextpos += bplhires ? 4 : 8;
        !          2262:            slowline_linepos += bplhires ? 4 : 8;
        !          2263: 
        !          2264:            /* Hmmmm.....
        !          2265:             * In theory, we could use the fast pfield_doline functions even
        !          2266:             * in this case. We only need to do sprites, ham decoding and
        !          2267:             * the line_to_scr stuff cycle-per-cycle. However, we would no
        !          2268:             * longer be able to emulate tricks that switch lores/hires in
        !          2269:             * the middle of a line, but I'm not sure whether this sort of
        !          2270:             * thing actually works currently and whether it's worthwhile.
        !          2271:             */
        !          2272:                                     
        !          2273:            pfield_fetchdata();
        !          2274: 
        !          2275:            if (use_lores)
        !          2276:                pfield_doline_slow_l (currhp);
        !          2277:            else
        !          2278:                pfield_doline_slow_h (currhp);
        !          2279:            /* @@@ need to test this */
        !          2280:            decode_ham6 (xpos, PIXEL_XPOS(slowline_nextpos));
        !          2281:        }
        !          2282:     }
        !          2283:     if (currhp > 48) {
        !          2284:        int spr;
        !          2285:        for(spr = 7; spr >= 0; spr--) {
        !          2286:            if (bpl_info.sprarmed[spr] && currhp == (bpl_info.sprpos[spr] & 0xFF)) {
        !          2287:                int sprxp = xpos + (bpl_info.sprctl[spr] & 1) * (use_lores ? 1 : 2);
        !          2288:                pfield_sprite (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr], use_lores);
        !          2289:            }
        !          2290:        }
        !          2291:     }    
        !          2292: }
        !          2293: 
        !          2294: static int first_drawn_line, last_drawn_line;
        !          2295: static int first_block_line, last_block_line;
        !          2296: 
        !          2297: static void init_frame (void)
        !          2298: {
        !          2299:     int i;
        !          2300:     int maxpos = use_lores ? 400 : 800;
        !          2301:     int old_pmds = prev_max_diwstop;
        !          2302:     
        !          2303:     if (max_diwstop == 0)
        !          2304:        max_diwstop = diwlastword;
        !          2305:     
        !          2306:     if (max_diwstop < (use_lores ? 320 : 640) || max_diwstop > maxpos)
        !          2307:        prev_max_diwstop = maxpos;
        !          2308:     else
        !          2309:        prev_max_diwstop = max_diwstop;
        !          2310: 
        !          2311:     max_diwstop = 0;
        !          2312: 
        !          2313:     memset(spron, 0, sizeof spron);
        !          2314:     memset(bpl_info.sprpos, 0, sizeof bpl_info.sprpos);
        !          2315:     memset(bpl_info.sprctl, 0, sizeof bpl_info.sprctl);
        !          2316:     last_drawn_line = 0;
        !          2317:     first_drawn_line = 32767;
        !          2318: 
        !          2319:     first_block_line = last_block_line = -2;
        !          2320:     calc_adjustment();
        !          2321:     if (frame_redraw_necessary)
        !          2322:        frame_redraw_necessary--;
        !          2323:     
        !          2324:     if (old_pmds != prev_max_diwstop) {
        !          2325:        frame_redraw_necessary |= (bpl_info.bplcon0 & 4 ? 2 : 1);
        !          2326:     }
        !          2327: }
        !          2328: 
        !          2329: /*
        !          2330:  * A raster line has been built in the graphics buffer. Tell the graphics code
        !          2331:  * to do anything necessary to display it.
        !          2332:  */
        !          2333: 
        !          2334: static void do_flush_line (int lineno)
        !          2335: {
        !          2336:     if (lineno < first_drawn_line)
        !          2337:        first_drawn_line = lineno;
        !          2338:     if (lineno > last_drawn_line)
        !          2339:        last_drawn_line = lineno;
        !          2340: 
        !          2341:     if (gfxvidinfo.maxblocklines == 0)
        !          2342:        flush_line(lineno);
        !          2343:     else {
        !          2344:        if ((last_block_line+1) != lineno) {
        !          2345:            if (first_block_line != -2)
        !          2346:                flush_block (first_block_line, last_block_line);
        !          2347:            first_block_line = lineno;
        !          2348:        }
        !          2349:        last_block_line = lineno;
        !          2350:        if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
        !          2351:            flush_block (first_block_line, last_block_line);
        !          2352:            first_block_line = last_block_line = -2;
        !          2353:        }
        !          2354:     }
        !          2355: }
        !          2356: 
        !          2357: /*
        !          2358:  * One Amiga frame has been finished. Tell the graphics code about it.
        !          2359:  * Note that the actual flush_scren() call is a no-op for all reasonable
        !          2360:  * systems.
        !          2361:  */
        !          2362: 
        !          2363: static void do_flush_screen (int start, int stop)
        !          2364: {
        !          2365:     if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
        !          2366:        flush_block (first_block_line, last_block_line);
        !          2367:     }
        !          2368:     if (start <= stop)
        !          2369:        flush_screen (start, stop);
        !          2370: }
        !          2371: 
        !          2372: static void setdontcare(void)
        !          2373: {
        !          2374:     fprintf(stderr, "Don't care mouse mode set\n");
        !          2375:     mousestate = dont_care_mouse;
        !          2376:     lastspr0x = lastmx; lastspr0y = lastmy;
        !          2377:     mstepx = defstepx; mstepy = defstepy;
        !          2378: }
        !          2379: 
        !          2380: static void setfollow(void)
        !          2381: {
        !          2382:     fprintf(stderr, "Follow sprite mode set\n");
        !          2383:     mousestate = follow_mouse;
        !          2384:     lastdiffx = lastdiffy = 0;
        !          2385:     sprvbfl = 0;
        !          2386:     spr0ctl=spr0pos = 0;
        !          2387:     mstepx = defstepx; mstepy = defstepy;
        !          2388: }
        !          2389: 
        !          2390: void togglemouse(void)
        !          2391: {
        !          2392:     switch(mousestate) {
        !          2393:      case dont_care_mouse: setfollow(); break;
        !          2394:      case follow_mouse: setdontcare(); break;
        !          2395:      default: break; /* Nnnnnghh! */
        !          2396:     }
        !          2397: }          
        !          2398: 
        !          2399: static __inline__ int adjust(int val)
        !          2400: {
        !          2401:     if (val>127)
        !          2402:        return 127; 
        !          2403:     else if (val<-127)
        !          2404:        return -127;
        !          2405:     return val;
        !          2406: }
        !          2407: 
        !          2408: static void do_mouse_hack(void)
        !          2409: {
        !          2410:     int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
        !          2411:     int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
        !          2412:     int diffx, diffy;
        !          2413:     
        !          2414:     switch (mousestate) {
        !          2415:      case normal_mouse:
        !          2416:        diffx = lastmx - lastsampledmx;
        !          2417:        diffy = lastmy - lastsampledmy;
        !          2418:        if (!newmousecounters) {        
        !          2419:            if (diffx > 127) diffx = 127;
        !          2420:            if (diffx < -127) diffx = -127;
        !          2421:            joy0x += diffx;
        !          2422:            if (diffy > 127) diffy = 127;
        !          2423:            if (diffy < -127) diffy = -127;
        !          2424:            joy0y += diffy;
        !          2425:        }
        !          2426:        lastsampledmx += diffx; lastsampledmy += diffy;
        !          2427:        break;
        !          2428: 
        !          2429:      case dont_care_mouse:
        !          2430:        diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
        !          2431:        diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
        !          2432:        lastspr0x=lastmx; lastspr0y=lastmy;
        !          2433:        joy0x+=diffx; joy0y+=diffy;
        !          2434:        break;
        !          2435:        
        !          2436:      case follow_mouse:
        !          2437:        if (sprvbfl && sprvbfl-- >1) {
        !          2438:            int mousexpos, mouseypos;
        !          2439:            
        !          2440:            if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x 
        !          2441:                && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff)
        !          2442:            {  
        !          2443:                int val = (lastdiffx << 16) / (spr0x - lastspr0x);
        !          2444:                if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
        !          2445:            }
        !          2446:            if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
        !          2447:                && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff) 
        !          2448:            { 
        !          2449:                int val = (lastdiffy<<16) / (spr0y-lastspr0y);
        !          2450:                if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
        !          2451:            }
        !          2452:            mousexpos = lastmx;
        !          2453:            if (gfxvidinfo.x_adjust)
        !          2454:                mousexpos += gfxvidinfo.x_adjust;
        !          2455:            mouseypos = lastmy;
        !          2456:            
        !          2457:            if(!correct_aspect)
        !          2458:                mouseypos *= 2;
        !          2459:            if(use_lores)
        !          2460:                mousexpos *= 2;
        !          2461:            if (gfxvidinfo.x_adjust)
        !          2462:                mousexpos -= 16;
        !          2463: 
        !          2464:            diffx = adjust ((((mousexpos + 0x70 + xoffs - spr0x) & ~1) * mstepx) >> 16);
        !          2465:            diffy = adjust ((((mouseypos + yoffs - spr0y+minfirstline*2) & ~1) * mstepy) >> 16);
        !          2466:            lastspr0x=spr0x; lastspr0y=spr0y;
        !          2467:            lastdiffx=diffx; lastdiffy=diffy;
        !          2468:            joy0x+=diffx; joy0y+=diffy; 
        !          2469:        }
        !          2470:        break;
        !          2471:     }
        !          2472: }
        !          2473: 
        !          2474: static void vsync_handler(void)
        !          2475: {
        !          2476:     UWORD dir;
        !          2477:     int button;
        !          2478: 
        !          2479:     handle_events();
        !          2480:     getjoystate(&joy0dir, &joy0button);
        !          2481: 
        !          2482:     do_mouse_hack();
        !          2483:     
        !          2484:     INTREQ(0x8020);
        !          2485:     if (bpl_info.bplcon0 & 4) lof ^= 0x8000;
        !          2486:     COPJMP1(0);
        !          2487:     
        !          2488:     if (framecnt == 0)
        !          2489:        do_flush_screen (first_drawn_line, last_drawn_line);
        !          2490: 
        !          2491:     count_frame();
        !          2492:     init_frame();
        !          2493: #ifdef HAVE_GETTIMEOFDAY
        !          2494:     {
        !          2495:        struct timeval tv;
        !          2496:        unsigned long int newtime;
        !          2497:        
        !          2498:        gettimeofday(&tv,NULL); 
        !          2499:        newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
        !          2500:        
        !          2501:        if (!bogusframe) {      
        !          2502:            frametime += newtime - msecs;
        !          2503:            timeframes++;
        !          2504:        }
        !          2505:        msecs = newtime;
        !          2506:        bogusframe = 0;
        !          2507:     }
        !          2508: #endif
        !          2509:     CIA_vsync_handler();
        !          2510: }
        !          2511: 
        !          2512: static void hsync_handler(void)
        !          2513: {
        !          2514:     int lineno = vpos - minfirstline;
        !          2515:     int lineisdouble = 0;
        !          2516:     int line_was_doubled = 0;
        !          2517:     
        !          2518:     do_sprites(vpos, maxhpos);
        !          2519:     last_sprite = 0;
        !          2520:     
        !          2521:     if (correct_aspect) {
        !          2522:        lineno *= 2;
        !          2523:        if (bpl_info.bplcon0 & 4) {
        !          2524:            if(!lof) {
        !          2525:                lineno++;
        !          2526:            }
        !          2527:        } else {
        !          2528:            lineisdouble = 1;
        !          2529:        }
        !          2530:     }
        !          2531: 
        !          2532:     eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles;
        !          2533:     eventtab[ev_hsync].oldcycles = cycles;
        !          2534:     CIA_hsync_handler();
        !          2535:     
        !          2536:     if (produce_sound > 0) {
        !          2537:        int nr;
        !          2538:        /* Sound data is fetched at the beginning of each line */
        !          2539:        for (nr = 0; nr < 4; nr++) {
        !          2540:            struct audio_channel_data *cdp = audio_channel + nr;
        !          2541:            
        !          2542:            if (cdp->data_written == 2) {
        !          2543:                cdp->data_written = 0;
        !          2544:                cdp->nextdat = chipmem_bank.wget(cdp->pt);
        !          2545:                cdp->pt += 2;
        !          2546:                if (cdp->state == 2 || cdp->state == 3) {
        !          2547:                    if (cdp->wlen == 1) {
        !          2548:                        cdp->pt = cdp->lc;
        !          2549:                        cdp->wlen = cdp->len;
        !          2550:                        cdp->intreq2 = 1;
        !          2551:                    } else
        !          2552:                        cdp->wlen--;
        !          2553:                }
        !          2554:            }
        !          2555:        }
        !          2556:     }
        !          2557: 
        !          2558:     if (framecnt == 0 && vpos >= minfirstline && lineno < gfxvidinfo.maxline) {
        !          2559:        if (vpos >= plffirstline && vpos < plflastline)
        !          2560:        {
        !          2561:            /* Finish the line, if we started doing it with the slow update.
        !          2562:             * Otherwise, draw it entirely. */
        !          2563:            if (pfield_fullline) {          
        !          2564:                if (!pfield_linedone) {
        !          2565:                    /* This can turn on line_in_border if DMA is off */
        !          2566:                    pfield_doline();
        !          2567:                }
        !          2568:                if (linetoscreen)
        !          2569:                    pfield_do_linetoscr_full (line_was_doubled = lineisdouble);
        !          2570:            } else {
        !          2571:                int i;
        !          2572:                for(i = pfield_lastpart_hpos; i < maxhpos; i++)
        !          2573:                    pfield_doline_slow(i);
        !          2574:                pfield_do_linetoscr(slowline_lasttoscr, maxhpos);
        !          2575:                /* The COLOR routine masks off the high nibble. This means
        !          2576:                 * that there will never be 0xFFFF in color_regs[0], and this
        !          2577:                 * means that the line will be drawn completely the next time
        !          2578:                 * we get into pfield_doline()
        !          2579:                 */
        !          2580:                linedescr[lineno].bpl_info.color_regs[0] = 0xFFFF;
        !          2581:                linetoscreen = 1;
        !          2582:            }
        !          2583:        } else
        !          2584:            line_in_border = 1;
        !          2585:        
        !          2586:        if (line_in_border && 
        !          2587:            (!linedescr[lineno].inborder 
        !          2588:             || linedescr[lineno].bordercol != acolors[0]))
        !          2589:        {
        !          2590:            linedescr[lineno].bordercol = acolors[0];
        !          2591:            linedescr[lineno].linedata_valid = 0;
        !          2592:            
        !          2593:            fill_line (lineno);
        !          2594:            linetoscreen = 1;
        !          2595:        }
        !          2596:            
        !          2597:        linedescr[lineno].inborder = line_in_border;
        !          2598:        
        !          2599:        if (linetoscreen) {
        !          2600: #if AGA_CHIPSET == 1
        !          2601:            switch (gfxvidinfo.pixbytes) {
        !          2602:             case 1: aga_translate8 (0, aga_lbufptr-aga_linebuf); break;
        !          2603:             case 2: aga_translate16 (0, aga_lbufptr-aga_linebuf); break;
        !          2604:             case 4: aga_translate32 (0, aga_lbufptr-aga_linebuf); break;
        !          2605:            }
        !          2606: #endif
        !          2607:            do_flush_line (lineno);
        !          2608:        }
        !          2609:        if (lineisdouble) {
        !          2610:            int drawit = 0;
        !          2611:            
        !          2612:            if (linedescr[lineno].inborder != linedescr[lineno+1].inborder
        !          2613:                || (linedescr[lineno].inborder == 1
        !          2614:                    && linedescr[lineno].bordercol != linedescr[lineno+1].bordercol)) {
        !          2615:                drawit = 1;
        !          2616:                
        !          2617:            } else if (linedescr[lineno].inborder == 0 
        !          2618:                       && (linetoscreen 
        !          2619:                           || (bplinfo_differs(&linedescr[lineno].bpl_info, 
        !          2620:                                               &linedescr[lineno+1].bpl_info)))) {
        !          2621:                drawit = 1;
        !          2622:            }
        !          2623:            
        !          2624:            if (drawit) {
        !          2625:                linedescr[lineno+1].inborder = linedescr[lineno].inborder;
        !          2626:                linedescr[lineno+1].bordercol = linedescr[lineno].bordercol;
        !          2627: #if SMART_UPDATE != 0
        !          2628:                linedescr[lineno+1].bpl_info = linedescr[lineno].bpl_info;
        !          2629: #endif
        !          2630:                if (!line_was_doubled) {
        !          2631:                    if (line_in_border)
        !          2632:                        fill_line (lineno+1);
        !          2633:                    else
        !          2634:                        memcpy (gfxvidinfo.bufmem + (lineno+1)*gfxvidinfo.rowbytes,
        !          2635:                                gfxvidinfo.bufmem + lineno*gfxvidinfo.rowbytes,
        !          2636:                                gfxvidinfo.rowbytes);
        !          2637:                }
        !          2638:                do_flush_line (lineno+1);
        !          2639:            }
        !          2640:        }
        !          2641:     }
        !          2642: 
        !          2643:     pfield_calclinedma();
        !          2644: 
        !          2645:     if (++vpos == (maxvpos + (lof != 0))) {
        !          2646:        vpos = 0;
        !          2647:        vsync_handler();
        !          2648:     }
        !          2649:     
        !          2650:     if (framecnt == 0) 
        !          2651:     {
        !          2652:        lineno = vpos - minfirstline;
        !          2653:        
        !          2654:        if (correct_aspect) {
        !          2655:            lineno *= 2;
        !          2656:            if ((bpl_info.bplcon0 & 4) && !lof) {
        !          2657:                lineno++;
        !          2658:            }
        !          2659:        }
        !          2660:        xlinebuffer = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * lineno;
        !          2661:        aga_lbufptr = aga_linebuf;
        !          2662:        next_lineno = lineno;
        !          2663:        linetoscreen = 0;
        !          2664:        line_in_border = 0;
        !          2665:        pfield_fullline = 1;
        !          2666:        pfield_linedone = 0;
        !          2667:        pfield_lastpart_hpos = 0;
        !          2668:     }
        !          2669: 
        !          2670: }
        !          2671: 
        !          2672: void customreset(void)
        !          2673: {
        !          2674:     int i;
        !          2675: #ifdef HAVE_GETTIMEOFDAY
        !          2676:     struct timeval tv;
        !          2677: #endif
        !          2678:     inhibit_frame = 0;
        !          2679:     expamem_reset();
        !          2680:     CIA_reset();
        !          2681:     cycles = 0; 
        !          2682:     regs.spcflags &= SPCFLAG_BRK;
        !          2683:     
        !          2684:     last_sprite = 0;
        !          2685:     vpos = 0; 
        !          2686:     lof = 0;
        !          2687:     next_lineno = 0;
        !          2688:     max_diwstop = 0;
        !          2689:     
        !          2690:     if (needmousehack()) {
        !          2691:        if (mousestate != follow_mouse) setfollow();
        !          2692:     } else {
        !          2693:        mousestate = normal_mouse;
        !          2694:     }
        !          2695: 
        !          2696:     memset(spixstate, 0, sizeof(spixstate));
        !          2697:     
        !          2698:     /*memset(blitcount, 0, sizeof(blitcount));  blitter debug */
        !          2699:     
        !          2700:     for (i = 0; i < numscrlines*2; i++) {
        !          2701:        linedescr[i].mnn = NULL;
        !          2702:        linedescr[i].linedata_valid = 0;
        !          2703:        linedescr[i].bpl_info.color_regs[0] = 0xFFFF;
        !          2704:        linedescr[i].bplpt[0] = (CPTR)-1;
        !          2705:     }
        !          2706:     
        !          2707:     xlinebuffer = gfxvidinfo.bufmem;
        !          2708: 
        !          2709:     dmacon = intena = 0;
        !          2710:     bltstate = BLT_done;
        !          2711:     copstate = COP_stop;
        !          2712:     copcon = 0;
        !          2713:     dskdmaen = 0;
        !          2714:     cycles = 0;
        !          2715:     
        !          2716:     memset(audio_channel, 0, sizeof audio_channel);
        !          2717: 
        !          2718:     bpl_info.bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
        !          2719:     bpl_info.bplcon3 = 0xC00;
        !          2720:     for(i = 0; i < ev_max; i++) {
        !          2721:        eventtab[i].active = 0;
        !          2722:        eventtab[i].oldcycles = 0;
        !          2723:     }
        !          2724:     copper_active = 0;
        !          2725:     eventtab[ev_cia].handler = CIA_handler;
        !          2726:     eventtab[ev_copper].handler = do_copper;
        !          2727:     eventtab[ev_hsync].handler = hsync_handler;
        !          2728:     eventtab[ev_hsync].evtime = maxhpos + cycles;
        !          2729:     eventtab[ev_hsync].active = 1;
        !          2730: 
        !          2731:     eventtab[ev_blitter].handler = blitter_handler;
        !          2732:     eventtab[ev_blitter].active = 0;
        !          2733:     eventtab[ev_diskblk].handler = diskblk_handler;
        !          2734:     eventtab[ev_diskblk].active = 0;
        !          2735:     eventtab[ev_diskindex].handler = diskindex_handler;
        !          2736:     eventtab[ev_diskindex].active = 0;
        !          2737: #ifndef DONT_WANT_SOUND
        !          2738:     eventtab[ev_aud0].handler = aud0_handler;
        !          2739:     eventtab[ev_aud0].active = 0;
        !          2740:     eventtab[ev_aud1].handler = aud1_handler;
        !          2741:     eventtab[ev_aud1].active = 0;
        !          2742:     eventtab[ev_aud2].handler = aud2_handler;
        !          2743:     eventtab[ev_aud2].active = 0;
        !          2744:     eventtab[ev_aud3].handler = aud3_handler;
        !          2745:     eventtab[ev_aud3].active = 0;
        !          2746:     if (sound_available) {
        !          2747:        eventtab[ev_sample].active = 1;
        !          2748:        eventtab[ev_sample].evtime += cycles;
        !          2749:        eventtab[ev_sample].oldcycles = cycles;
        !          2750:     } else {
        !          2751:        eventtab[ev_sample].active = 0;
        !          2752:     }
        !          2753: #endif
        !          2754:     events_schedule();
        !          2755:     
        !          2756:     init_frame();
        !          2757: #ifdef HAVE_GETTIMEOFDAY
        !          2758:     gettimeofday(&tv,NULL);
        !          2759:     seconds_base = tv.tv_sec;
        !          2760:     bogusframe = 1;
        !          2761: #endif
        !          2762: }
        !          2763: 
        !          2764: void dumpcustom(void)
        !          2765: {
        !          2766:     int i;
        !          2767:     fprintf(stderr, "DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
        !          2768:           intena, intreq, vpos, current_hpos());
        !          2769:     if (timeframes) { 
        !          2770:        fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n", 
        !          2771:               frametime/timeframes, timeframes, frametime);
        !          2772:     }
        !          2773:     /*for (i=0; i<256; i++) if (blitcount[i]) fprintf(stderr, "minterm %x = %d\n",i,blitcount[i]);  blitter debug */
        !          2774: }
        !          2775: 
        !          2776: int intlev(void)
        !          2777: {
        !          2778:     UWORD imask = intreq & intena;
        !          2779:     if (imask && (intena & 0x4000)){
        !          2780:        if (imask & 0x2000) return 6;
        !          2781:        if (imask & 0x1800) return 5;
        !          2782:        if (imask & 0x0780) return 4;
        !          2783:        if (imask & 0x0070) return 3;
        !          2784:        if (imask & 0x0008) return 2;
        !          2785:        if (imask & 0x0007) return 1;
        !          2786:     }
        !          2787:     return -1;
        !          2788: }
        !          2789: 
        !          2790: void custom_init(void)
        !          2791: {
        !          2792:     int num;
        !          2793:     if (needmousehack())
        !          2794:        setfollow();
        !          2795:     customreset();
        !          2796:     for (num = 0; num < 256; num++) {  
        !          2797:        int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8);
        !          2798:        int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8);
        !          2799:        dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
        !          2800:        dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
        !          2801:        dblpf_aga1[num] = plane1 == 0 ? plane2 : plane1;
        !          2802:        dblpf_aga2[num] = plane2 == 0 ? plane1 : plane2;
        !          2803:        if (plane2 > 0) plane2 += 8;
        !          2804:        dblpf_ind1[num] = plane1 == 0 ? plane2 : plane1;
        !          2805:        dblpf_ind2[num] = plane2 == 0 ? plane1 : plane2;
        !          2806:        
        !          2807:        lots_of_twos[num] = num == 0 ? 0 : 2;
        !          2808:        linear_map_256[num] = num;
        !          2809:     }
        !          2810:     build_blitfilltable();
        !          2811:     gen_pfield_tables();
        !          2812: }
        !          2813: 
        !          2814: /* Custom chip memory bank */
        !          2815: 
        !          2816: static ULONG custom_lget(CPTR) REGPARAM;
        !          2817: static UWORD custom_wget(CPTR) REGPARAM;
        !          2818: static UBYTE custom_bget(CPTR) REGPARAM;
        !          2819: static void  custom_lput(CPTR, ULONG) REGPARAM;
        !          2820: static void  custom_wput(CPTR, UWORD) REGPARAM;
        !          2821: static void  custom_bput(CPTR, UBYTE) REGPARAM;
        !          2822: 
        !          2823: addrbank custom_bank = {
        !          2824:     default_alget, default_awget,
        !          2825:     custom_lget, custom_wget, custom_bget,
        !          2826:     custom_lput, custom_wput, custom_bput,
        !          2827:     default_xlate, default_check
        !          2828: };
        !          2829: 
        !          2830: UWORD custom_wget(CPTR addr)
        !          2831: {
        !          2832:     switch(addr & 0x1FE) {
        !          2833:      case 0x002: return DMACONR();
        !          2834:      case 0x004: return VPOSR();
        !          2835:      case 0x006: return VHPOSR();
        !          2836:        
        !          2837:      case 0x008: return DSKDATR();
        !          2838: 
        !          2839:      case 0x00A: return JOY0DAT();
        !          2840:      case 0x00C: return JOY1DAT();
        !          2841:      case 0x010: return ADKCONR();
        !          2842: 
        !          2843:      case 0x012: return POT0DAT();
        !          2844:      case 0x016: return POTGOR();
        !          2845:      case 0x018: return SERDATR();
        !          2846:      case 0x01A: return DSKBYTR();
        !          2847:      case 0x01C: return INTENAR();
        !          2848:      case 0x01E: return INTREQR();
        !          2849: 
        !          2850: #if AGA_CHIPSET == 1
        !          2851:      case 0x07C: return 0xF8;
        !          2852: #elif defined ECS_DENISE
        !          2853:      case 0x07C: return 0xFC;
        !          2854: #endif
        !          2855:      default:
        !          2856:        custom_wput(addr,0);
        !          2857:        return 0xffff;
        !          2858:     }
        !          2859: }
        !          2860: 
        !          2861: UBYTE custom_bget(CPTR addr)
        !          2862: {
        !          2863:     return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
        !          2864: }
        !          2865: 
        !          2866: ULONG custom_lget(CPTR addr)
        !          2867: {
        !          2868:     return ((ULONG)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
        !          2869: }
        !          2870: 
        !          2871: void custom_wput(CPTR addr, UWORD value)
        !          2872: {
        !          2873:     addr &= 0x1FE;
        !          2874:     cregs[addr>>1] = value;
        !          2875:     switch(addr) {     
        !          2876:      case 0x020: DSKPTH(value); break;
        !          2877:      case 0x022: DSKPTL(value); break;
        !          2878:      case 0x024: DSKLEN(value); break;
        !          2879:      case 0x026: DSKDAT(value); break;
        !          2880:        
        !          2881:      case 0x02A: VPOSW(value); break;
        !          2882: 
        !          2883:      case 0x030: SERDAT(value); break;
        !          2884:      case 0x032: SERPER(value); break;
        !          2885:  
        !          2886:      case 0x040: BLTCON0(value); break;
        !          2887:      case 0x042: BLTCON1(value); break;
        !          2888:        
        !          2889:      case 0x044: BLTAFWM(value); break;
        !          2890:      case 0x046: BLTALWM(value); break;
        !          2891:        
        !          2892:      case 0x050: BLTAPTH(value); break;
        !          2893:      case 0x052: BLTAPTL(value); break;
        !          2894:      case 0x04C: BLTBPTH(value); break;
        !          2895:      case 0x04E: BLTBPTL(value); break;
        !          2896:      case 0x048: BLTCPTH(value); break;
        !          2897:      case 0x04A: BLTCPTL(value); break;
        !          2898:      case 0x054: BLTDPTH(value); break;
        !          2899:      case 0x056: BLTDPTL(value); break;
        !          2900:        
        !          2901:      case 0x058: BLTSIZE(value); break;
        !          2902:        
        !          2903:      case 0x064: BLTAMOD(value); break;
        !          2904:      case 0x062: BLTBMOD(value); break;
        !          2905:      case 0x060: BLTCMOD(value); break;
        !          2906:      case 0x066: BLTDMOD(value); break;
        !          2907:        
        !          2908:      case 0x070: BLTCDAT(value); break;
        !          2909:      case 0x072: BLTBDAT(value); break;
        !          2910:      case 0x074: BLTADAT(value); break;
        !          2911:                        
        !          2912:      case 0x07E: DSKSYNC(value); break;
        !          2913: 
        !          2914:      case 0x080: COP1LCH(value); break;
        !          2915:      case 0x082: COP1LCL(value); break;
        !          2916:      case 0x084: COP2LCH(value); break;
        !          2917:      case 0x086: COP2LCL(value); break;
        !          2918:        
        !          2919:      case 0x088: COPJMP1(value); break;
        !          2920:      case 0x08A: COPJMP2(value); break;
        !          2921:        
        !          2922:      case 0x08E: DIWSTRT(value); break;
        !          2923:      case 0x090: DIWSTOP(value); break;
        !          2924:      case 0x092: DDFSTRT(value); break;
        !          2925:      case 0x094: DDFSTOP(value); break;
        !          2926:        
        !          2927:      case 0x096: DMACON(value); break;
        !          2928:      case 0x09A: INTENA(value); break;
        !          2929:      case 0x09C: INTREQ(value); break;
        !          2930:      case 0x09E: ADKCON(value); break;
        !          2931:        
        !          2932:      case 0x0A0: AUDxLCH(0, value); break;
        !          2933:      case 0x0A2: AUDxLCL(0, value); break;
        !          2934:      case 0x0A4: AUDxLEN(0, value); break;
        !          2935:      case 0x0A6: AUDxPER(0, value); break;
        !          2936:      case 0x0A8: AUDxVOL(0, value); break;
        !          2937:      case 0x0AA: AUDxDAT(0, value); break;
        !          2938:        
        !          2939:      case 0x0B0: AUDxLCH(1, value); break;
        !          2940:      case 0x0B2: AUDxLCL(1, value); break;
        !          2941:      case 0x0B4: AUDxLEN(1, value); break;
        !          2942:      case 0x0B6: AUDxPER(1, value); break;
        !          2943:      case 0x0B8: AUDxVOL(1, value); break;
        !          2944:      case 0x0BA: AUDxDAT(1, value); break;
        !          2945:        
        !          2946:      case 0x0C0: AUDxLCH(2, value); break;
        !          2947:      case 0x0C2: AUDxLCL(2, value); break;
        !          2948:      case 0x0C4: AUDxLEN(2, value); break;
        !          2949:      case 0x0C6: AUDxPER(2, value); break;
        !          2950:      case 0x0C8: AUDxVOL(2, value); break;
        !          2951:      case 0x0CA: AUDxDAT(2, value); break;
        !          2952:        
        !          2953:      case 0x0D0: AUDxLCH(3, value); break;
        !          2954:      case 0x0D2: AUDxLCL(3, value); break;
        !          2955:      case 0x0D4: AUDxLEN(3, value); break;
        !          2956:      case 0x0D6: AUDxPER(3, value); break;
        !          2957:      case 0x0D8: AUDxVOL(3, value); break;
        !          2958:      case 0x0DA: AUDxDAT(3, value); break;
        !          2959:        
        !          2960:      case 0x0E0: BPLPTH(value, 0); break;
        !          2961:      case 0x0E2: BPLPTL(value, 0); break;
        !          2962:      case 0x0E4: BPLPTH(value, 1); break;
        !          2963:      case 0x0E6: BPLPTL(value, 1); break;
        !          2964:      case 0x0E8: BPLPTH(value, 2); break;
        !          2965:      case 0x0EA: BPLPTL(value, 2); break;
        !          2966:      case 0x0EC: BPLPTH(value, 3); break;
        !          2967:      case 0x0EE: BPLPTL(value, 3); break;
        !          2968:      case 0x0F0: BPLPTH(value, 4); break;
        !          2969:      case 0x0F2: BPLPTL(value, 4); break;
        !          2970:      case 0x0F4: BPLPTH(value, 5); break;
        !          2971:      case 0x0F6: BPLPTL(value, 5); break;
        !          2972:        
        !          2973:      case 0x100: BPLCON0(value); break;
        !          2974:      case 0x102: BPLCON1(value); break;
        !          2975:      case 0x104: BPLCON2(value); break;
        !          2976:      case 0x106: BPLCON3(value); break;
        !          2977:        
        !          2978:      case 0x108: BPL1MOD(value); break;
        !          2979:      case 0x10A: BPL2MOD(value); break;
        !          2980: 
        !          2981:      case 0x110: BPL1DAT(value); break;
        !          2982:      case 0x112: BPL2DAT(value); break;
        !          2983:      case 0x114: BPL3DAT(value); break;
        !          2984:      case 0x116: BPL4DAT(value); break;
        !          2985:      case 0x118: BPL5DAT(value); break;
        !          2986:      case 0x11A: BPL6DAT(value); break;
        !          2987:        
        !          2988:      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
        !          2989:      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
        !          2990:      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
        !          2991:      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
        !          2992:      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
        !          2993:      case 0x1BC: case 0x1BE: 
        !          2994:        COLOR(value & 0xFFF, (addr & 0x3E) / 2);
        !          2995:        break;  
        !          2996:      case 0x120: case 0x124: case 0x128: case 0x12C: 
        !          2997:      case 0x130: case 0x134: case 0x138: case 0x13C:
        !          2998:        SPRxPTH(value, (addr - 0x120) / 4);
        !          2999:        break;
        !          3000:      case 0x122: case 0x126: case 0x12A: case 0x12E: 
        !          3001:      case 0x132: case 0x136: case 0x13A: case 0x13E:
        !          3002:        SPRxPTL(value, (addr - 0x122) / 4);
        !          3003:        break;
        !          3004:      case 0x140: case 0x148: case 0x150: case 0x158: 
        !          3005:      case 0x160: case 0x168: case 0x170: case 0x178:
        !          3006:        SPRxPOS(value, (addr - 0x140) / 8);
        !          3007:        break;
        !          3008:      case 0x142: case 0x14A: case 0x152: case 0x15A: 
        !          3009:      case 0x162: case 0x16A: case 0x172: case 0x17A:
        !          3010:        SPRxCTL(value, (addr - 0x142) / 8);
        !          3011:        break;
        !          3012:      case 0x144: case 0x14C: case 0x154: case 0x15C:
        !          3013:      case 0x164: case 0x16C: case 0x174: case 0x17C:
        !          3014:        SPRxDATA(value, (addr - 0x144) / 8);
        !          3015:        break;
        !          3016:      case 0x146: case 0x14E: case 0x156: case 0x15E: 
        !          3017:      case 0x166: case 0x16E: case 0x176: case 0x17E:
        !          3018:        SPRxDATB(value, (addr - 0x146) / 8);
        !          3019:        break;
        !          3020:        
        !          3021:      case 0x36: JOYTEST(value); break;
        !          3022: #if defined(ECS_AGNUS) || (AGA_CHIPSET == 1)
        !          3023:      case 0x5A: BLTCON0L(value); break;
        !          3024:      case 0x5C: BLTSIZV(value); break;
        !          3025:      case 0x5E: BLTSIZH(value); break;
        !          3026: #endif
        !          3027: #if AGA_CHIPSET == 1
        !          3028:      case 0x10C: BPLCON4(value); break;
        !          3029:      case 0x1FC: fmode = value; break;
        !          3030: #endif
        !          3031:     }
        !          3032: }
        !          3033: 
        !          3034: void custom_bput(CPTR addr, UBYTE value)
        !          3035: {
        !          3036:     /* Yes, there are programs that do this. The programmers should be shot.
        !          3037:      * This might actually work sometimes. */
        !          3038:     UWORD rval = value;
        !          3039:     CPTR raddr = addr & 0x1FE;
        !          3040:     if (addr & 1) {
        !          3041:        rval |= cregs[raddr >> 1] & 0xFF00;
        !          3042:     } else {
        !          3043:        rval <<= 8;
        !          3044:        rval |= cregs[raddr >> 1] & 0xFF;
        !          3045:     }
        !          3046:     custom_wput(raddr, rval);
        !          3047: }
        !          3048: 
        !          3049: void custom_lput(CPTR addr, ULONG value)
        !          3050: {
        !          3051:     custom_wput(addr & 0xfffe, value >> 16);
        !          3052:     custom_wput((addr+2) & 0xfffe, (UWORD)value);
        !          3053: }
        !          3054: 

unix.superglobalmegacorp.com

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