Annotation of uae/custom.c, revision 1.1.1.2

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

unix.superglobalmegacorp.com

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