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