Annotation of uae/custom.c, revision 1.1

1.1     ! root        1:  /* 
        !             2:   * UAE - The Un*x Amiga Emulator
        !             3:   * 
        !             4:   * Custom chip emulation
        !             5:   * 
        !             6:   * (c) 1995 Bernd Schmidt, Alessandro Bissacco
        !             7:   */
        !             8: 
        !             9: #include <ctype.h>
        !            10: #ifdef __unix
        !            11: #include <sys/time.h>
        !            12: #include <unistd.h>
        !            13: #endif
        !            14: #include <stdio.h>
        !            15: #include <string.h>
        !            16: #include <stdlib.h>
        !            17: #include <assert.h>
        !            18: 
        !            19: #include "config.h"
        !            20: #include "amiga.h"
        !            21: #include "options.h"
        !            22: #include "events.h"
        !            23: #include "memory.h"
        !            24: #include "custom.h"
        !            25: #include "cia.h"
        !            26: #include "disk.h"
        !            27: #include "blit.h"
        !            28: #include "xwin.h"
        !            29: #include "os.h"
        !            30: 
        !            31: #define DMA_AUD0      0x0001
        !            32: #define DMA_AUD1      0x0002
        !            33: #define DMA_AUD2      0x0004
        !            34: #define DMA_AUD3      0x0008
        !            35: #define DMA_DISK      0x0010
        !            36: #define DMA_SPRITE    0x0020
        !            37: #define DMA_BLITTER   0x0040
        !            38: #define DMA_COPPER    0x0080
        !            39: #define DMA_BITPLANE  0x0100
        !            40: #define DMA_BLITPRI   0x0400
        !            41: 
        !            42: /* These are default values for mouse emulation.
        !            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: #ifndef __mac__
        !            51: #define defxoffs 0
        !            52: #define defyoffs 0
        !            53: #else
        !            54: #define defxoffs 210
        !            55: #define defyoffs 85
        !            56: #endif
        !            57: 
        !            58: /* Values below define mouse auto calibration process.
        !            59:  * They are not critical, change them if you want.
        !            60:  * The most important is calweight, which sets mouse adjustement rate */ 
        !            61: 
        !            62: static const int docal = 60, xcaloff = 40, ycaloff = 20;
        !            63: static const int calweight = 3;
        !            64: 
        !            65: static int lastsampledmx, lastsampledmy;
        !            66: 
        !            67:  /*
        !            68:   * Events
        !            69:   */
        !            70: 
        !            71: unsigned long int cycles, nextevent, nextev_count, specialflags;
        !            72: int vpos;
        !            73: UWORD lof;
        !            74: 
        !            75: struct ev eventtab[ev_max];
        !            76: 
        !            77: bool copper_active;
        !            78: 
        !            79: static const int maxhpos = 227,maxvpos = 312;
        !            80: static const int dskdelay = 2; /* FIXME: ??? */
        !            81: static const int minfirstline = 29;
        !            82: 
        !            83:  /* 
        !            84:   * hardware register values that are visible/can be written to by someone
        !            85:   */
        !            86: 
        !            87: static UWORD cregs[256];
        !            88: 
        !            89: static UWORD dmacon,intena,intreq,adkcon;
        !            90: 
        !            91: static ULONG cop1lc,cop2lc,copcon;
        !            92: 
        !            93: static CPTR  bpl1pt,bpl2pt,bpl3pt,bpl4pt,bpl5pt,bpl6pt;
        !            94: static ULONG bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat;
        !            95: static UWORD bplcon0,bplcon1,bplcon2,bplcon3;
        !            96: static UWORD diwstrt,diwstop,ddfstrt,ddfstop;
        !            97: static WORD  bpl1mod,bpl2mod;
        !            98: 
        !            99: static UWORD sprdata[8], sprdatb[8], sprctl[8], sprpos[8];
        !           100: static ULONG sprpt[8];
        !           101: static bool sprarmed[8], sprptset[8];
        !           102: /* Kludge. FIXME: How does sprite restart after vsync work? */
        !           103: static int spron[8]; 
        !           104: 
        !           105: static UWORD bltadat,bltbdat,bltcdat,bltddat,bltafwm,bltalwm,bltsize;
        !           106: static WORD  bltamod,bltbmod,bltcmod,bltdmod;
        !           107: static UWORD bltcon0,bltcon1;
        !           108: static ULONG bltapt,bltbpt,bltcpt,bltdpt,bltcnxlpt,bltdnxlpt;
        !           109: 
        !           110: static ULONG dskpt;
        !           111: static UWORD dsklen,dsksync;
        !           112: 
        !           113: static int joy0x, joy1x, joy0y, joy1y;
        !           114: static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl;
        !           115: static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs;
        !           116: static int sprvbfl;
        !           117: 
        !           118: static enum { normal_mouse, dont_care_mouse, follow_mouse} mousestate;
        !           119: 
        !           120: xcolnr acolors[64];
        !           121: UWORD color_regs[32];
        !           122: 
        !           123:  /*
        !           124:   * "hidden" hardware registers
        !           125:   */
        !           126: 
        !           127: static int dblpf_ind1[64], dblpf_ind2[64];
        !           128: 
        !           129: static ULONG coplc;
        !           130: static UWORD copi1,copi2;
        !           131: 
        !           132: static enum {
        !           133:     COP_stop, COP_read, COP_wait, COP_move, COP_skip
        !           134: } copstate;
        !           135: 
        !           136: static UWORD vblitsize,hblitsize,blitpreva,blitprevb;
        !           137: static UWORD blitlpos,blitashift,blitbshift,blinea,blineb;
        !           138: static bool blitline,blitfc,blitzero,blitfill,blitife,blitdesc,blitsing;
        !           139: static bool blitonedot,blitsign;
        !           140: static long int bltwait;
        !           141: 
        !           142: static int dsklength;
        !           143: 
        !           144: static enum {
        !           145:     BLT_done, BLT_init, BLT_read, BLT_work, BLT_write, BLT_next
        !           146: } bltstate;
        !           147: 
        !           148: static int plffirstline,plflastline,plfstrt,plfstop,plflinelen;
        !           149: static int diwfirstword,diwlastword;
        !           150: static int plf1pri, plf2pri;
        !           151: 
        !           152: int dskdmaen; /* used in cia.c */
        !           153: static UWORD dskmfm,dskbyte,dsktime;
        !           154: static bool dsksynced;
        !           155: 
        !           156: static int bpldelay1;
        !           157: static int bpldelay2;
        !           158: static bool bplhires;
        !           159: static int bplplanecnt;
        !           160: 
        !           161: static bool pfield_fullline,pfield_linedone;
        !           162: static bool pfield_linedmaon;
        !           163: static int pfield_lastpart_hpos;
        !           164: 
        !           165: unsigned char apixels[1000]; /* includes a lot of safety padding */
        !           166: char spixels[1000]; /* for sprites */
        !           167: char spixstate[1000]; /* more sprites */
        !           168: 
        !           169:  /*
        !           170:   * Statistics
        !           171:   */
        !           172: 
        !           173: static unsigned long int msecs = 0, frametime = 0, timeframes = 0;
        !           174: static unsigned long int seconds_base;
        !           175: bool bogusframe;
        !           176: 
        !           177:  /*
        !           178:   * helper functions
        !           179:   */
        !           180: 
        !           181: static void pfield_doline_slow(int);
        !           182: static void pfield_doline(void);
        !           183: static void pfield_hsync(int);
        !           184: 
        !           185: bool inhibit_frame;
        !           186: static int framecnt = 0;
        !           187: 
        !           188: static __inline__ void count_frame(void)
        !           189: {
        !           190:     if (inhibit_frame) 
        !           191:        framecnt = 1;
        !           192:     else {     
        !           193:        framecnt++;
        !           194:        if (framecnt == framerate)
        !           195:            framecnt = 0;
        !           196:     }
        !           197: }
        !           198: 
        !           199: static __inline__ void setclr(UWORD *p, UWORD val)
        !           200: {
        !           201:     if (val & 0x8000) {
        !           202:        *p |= val & 0x7FFF;
        !           203:     } else {
        !           204:        *p &= ~val;
        !           205:     }
        !           206: }
        !           207: 
        !           208: bool dmaen(UWORD dmamask)
        !           209: {
        !           210:     return (dmamask & dmacon) && (dmacon & 0x200);
        !           211: }
        !           212: 
        !           213: static __inline__ int current_hpos(void)
        !           214: {
        !           215:     return cycles - eventtab[ev_hsync].oldcycles;
        !           216: }
        !           217: 
        !           218: static void calcdiw(void)
        !           219: {
        !           220:     diwfirstword = (diwstrt & 0xFF) * 2 - 0x60;
        !           221:     diwlastword  = (diwstop & 0xFF) * 2 + 0x200 - 0x60;
        !           222:     if (diwfirstword < 0) diwfirstword = 0;
        !           223: 
        !           224:     plffirstline = diwstrt >> 8;
        !           225:     plflastline = diwstop >> 8;
        !           226: #if 0
        !           227:     /* This happens far too often. */
        !           228:     if (plffirstline < minfirstline) {
        !           229:        fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline);
        !           230:        plffirstline = minfirstline;
        !           231:     }
        !           232: #endif
        !           233:     if ((plflastline & 0x80) == 0) plflastline |= 0x100;
        !           234: #if 0 /* Turrican does this */
        !           235:     if (plflastline > 313) {
        !           236:        fprintf(stderr, "Warning: Playfield out of range!\n");
        !           237:        plflastline = 313;
        !           238:     }
        !           239: #endif
        !           240:     plfstrt = ddfstrt;
        !           241:     plfstop = ddfstop;
        !           242:     if (plfstrt < 0x18) plfstrt = 0x18;
        !           243:     if (plfstop > 0xD8) plfstop = 0xD8;
        !           244:     if (plfstrt > plfstop) plfstrt = plfstop;
        !           245:     
        !           246:     /* 
        !           247:      * Prize question: What are the next lines supposed to be?
        !           248:      * I can't seem to get it right.
        !           249:      */
        !           250: #if 0
        !           251:     /* Pretty good guess, but wrong. */
        !           252:     plflinelen = (plfstop-plfstrt+15) & ~7;
        !           253:     plfstrt &= ~(bplhires ? 3 : 7);
        !           254:     plfstop &= ~(bplhires ? 3 : 7);
        !           255: #endif
        !           256:     plfstrt &= ~(bplhires ? 3 : 3);
        !           257:     plfstop &= ~(bplhires ? 3 : 3);
        !           258:     plflinelen = (plfstop-plfstrt+15) & ~7;
        !           259: }
        !           260: 
        !           261: static void pfield_may_need_update(bool colreg)
        !           262: {
        !           263:     int i;
        !           264:     
        !           265:     /* Ignore, if this happened before or after the DDF window */
        !           266:     if (framecnt != 0 || !pfield_linedmaon || current_hpos() <= plfstrt
        !           267:        || vpos < plffirstline || vpos >= plflastline)
        !           268:     {  
        !           269:        return;
        !           270:     }
        !           271:     /* 
        !           272:      * If a color reg was modified, it is only important if we are within
        !           273:      * the DIW.
        !           274:      */
        !           275:     if (current_hpos() <= (diwfirstword+0x60)/4 && colreg)
        !           276:        return;
        !           277: 
        !           278:     /*
        !           279:      * If we are past the DDF window, me might as well draw the complete
        !           280:      * line now.
        !           281:      */
        !           282:     if (current_hpos() > plfstrt + plflinelen && pfield_fullline) {
        !           283:        if (!pfield_linedone)
        !           284:            pfield_doline();
        !           285:        pfield_linedone = true;
        !           286:        return;
        !           287:     }
        !           288:        
        !           289:     if (pfield_fullline) {
        !           290:        pfield_lastpart_hpos = 0;
        !           291:        memset(apixels, 0, sizeof(apixels));
        !           292:        pfield_fullline = false;
        !           293:     } else {   
        !           294:        assert(pfield_lastpart_hpos <= current_hpos());
        !           295:     }
        !           296:     for (i = pfield_lastpart_hpos; i < current_hpos(); i++) {
        !           297:        pfield_doline_slow(i);
        !           298:     }
        !           299:     pfield_lastpart_hpos = current_hpos();
        !           300: }
        !           301: 
        !           302: /* Apparently, the DMA bit is tested by the hardware at some point,
        !           303:  * presumably at the ddfstart position, to determine whether it
        !           304:  * ought to draw the line.
        !           305:  * This is probably not completely correct, but should not matter
        !           306:  * very much.
        !           307:  */
        !           308: static void pfield_calclinedma(void)
        !           309: {
        !           310:     if (current_hpos() >= plfstrt)
        !           311:        return;
        !           312:     
        !           313:     pfield_linedmaon = dmaen(DMA_BITPLANE);
        !           314: }
        !           315: 
        !           316:  /* 
        !           317:   * register functions
        !           318:   */
        !           319: 
        !           320: static UWORD DMACONR(void)
        !           321: {
        !           322:     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
        !           323:            | (blitzero ? 0x2000 : 0));
        !           324: }
        !           325: static UWORD INTENAR(void) { return intena; }
        !           326: static UWORD INTREQR(void) { return intreq; }
        !           327: static UWORD ADKCONR(void) { return adkcon; }
        !           328: static UWORD VPOSR(void) { return (vpos >> 8) | lof; }
        !           329: static void  VPOSW(UWORD v)  { lof = v & 0x8000; }
        !           330: static UWORD VHPOSR(void) { return (vpos << 8) | current_hpos(); } 
        !           331: 
        !           332: static void  COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); }
        !           333: static void  COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; }
        !           334: static void  COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); }
        !           335: static void  COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; }
        !           336: 
        !           337: static void  COPJMP1(UWORD a)
        !           338: {
        !           339:     coplc = cop1lc; copstate = COP_read; 
        !           340:     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
        !           341:     eventtab[ev_copper].evtime = 4; events_schedule();
        !           342:     copper_active = true;
        !           343: }
        !           344: static void  COPJMP2(UWORD a)
        !           345: {
        !           346:     coplc = cop2lc; copstate = COP_read; 
        !           347:     eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles;
        !           348:     eventtab[ev_copper].evtime = 4; events_schedule();
        !           349:     copper_active = true;
        !           350: }
        !           351: 
        !           352: static void  DMACON(UWORD v) 
        !           353: {
        !           354:     UWORD oldcon = dmacon;
        !           355:     setclr(&dmacon,v); dmacon &= 0x1FFF;
        !           356:     pfield_calclinedma();
        !           357:     
        !           358:     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { 
        !           359:        COPJMP1(0); /* @@@ not sure how this works */
        !           360:     }
        !           361:     if (copper_active && !eventtab[ev_copper].active) {
        !           362:        eventtab[ev_copper].active = true;
        !           363:        eventtab[ev_copper].oldcycles = cycles;
        !           364:        eventtab[ev_copper].evtime = 1;
        !           365:        events_schedule();
        !           366:     }
        !           367: }
        !           368: static void  INTENA(UWORD v) { setclr(&intena,v); specialflags |= SPCFLAG_INT; }
        !           369: static void  INTREQ(UWORD v) { setclr(&intreq,v); specialflags |= SPCFLAG_INT; }
        !           370: static void  ADKCON(UWORD v) { setclr(&adkcon,v); }
        !           371: 
        !           372: static void  BPL1PTH(UWORD v) { bpl1pt= (bpl1pt & 0xffff) | ((ULONG)v << 16); }
        !           373: static void  BPL1PTL(UWORD v) { bpl1pt= (bpl1pt & ~0xffff) | v; }
        !           374: static void  BPL2PTH(UWORD v) { bpl2pt= (bpl2pt & 0xffff) | ((ULONG)v << 16); }
        !           375: static void  BPL2PTL(UWORD v) { bpl2pt= (bpl2pt & ~0xffff) | v; }
        !           376: static void  BPL3PTH(UWORD v) { bpl3pt= (bpl3pt & 0xffff) | ((ULONG)v << 16); }
        !           377: static void  BPL3PTL(UWORD v) { bpl3pt= (bpl3pt & ~0xffff) | v; }
        !           378: static void  BPL4PTH(UWORD v) { bpl4pt= (bpl4pt & 0xffff) | ((ULONG)v << 16); }
        !           379: static void  BPL4PTL(UWORD v) { bpl4pt= (bpl4pt & ~0xffff) | v; }
        !           380: static void  BPL5PTH(UWORD v) { bpl5pt= (bpl5pt & 0xffff) | ((ULONG)v << 16); }
        !           381: static void  BPL5PTL(UWORD v) { bpl5pt= (bpl5pt & ~0xffff) | v; }
        !           382: static void  BPL6PTH(UWORD v) { bpl6pt= (bpl6pt & 0xffff) | ((ULONG)v << 16); }
        !           383: static void  BPL6PTL(UWORD v) { bpl6pt= (bpl6pt & ~0xffff) | v; }
        !           384: 
        !           385: /*
        !           386:  * I've seen the listing of an example program that changes 
        !           387:  * from lo- to hires while a line is being drawn. That's
        !           388:  * awful, but we want to emulate it.
        !           389:  */
        !           390: static void  BPLCON0(UWORD v) 
        !           391: {
        !           392:     pfield_may_need_update(false);
        !           393:     bplcon0 = v;
        !           394:     bplhires = (bplcon0 & 0x8000) == 0x8000; 
        !           395:     bplplanecnt = (bplcon0 & 0x7000) >> 12; 
        !           396:     calcdiw(); /* This should go away. */
        !           397: }
        !           398: static void  BPLCON1(UWORD v) 
        !           399: {
        !           400:     pfield_may_need_update(false);
        !           401:     bplcon1 = v; 
        !           402:     bpldelay1 = bplcon1 & 0xF; 
        !           403:     bpldelay2 = (bplcon1 >> 4) & 0xF; 
        !           404: }
        !           405: static void  BPLCON2(UWORD v) 
        !           406: {
        !           407:     pfield_may_need_update(false); 
        !           408:     bplcon2 = v;
        !           409:     plf1pri = 1 << 2*(v & 7);
        !           410:     plf2pri = 1 << 2*((v>>3) & 7);
        !           411: }
        !           412: static void  BPLCON3(UWORD v) { pfield_may_need_update(false); bplcon3 = v; }
        !           413: 
        !           414: static void  BPL1MOD(UWORD v) { pfield_may_need_update(false); bpl1mod = v; }
        !           415: static void  BPL2MOD(UWORD v) { pfield_may_need_update(false); bpl2mod = v; }
        !           416: 
        !           417: static void  BPL1DAT(UWORD v) { bpl1dat = v; }
        !           418: static void  BPL2DAT(UWORD v) { bpl2dat = v; }
        !           419: static void  BPL3DAT(UWORD v) { bpl3dat = v; }
        !           420: static void  BPL4DAT(UWORD v) { bpl4dat = v; }
        !           421: static void  BPL5DAT(UWORD v) { bpl5dat = v; }
        !           422: static void  BPL6DAT(UWORD v) { bpl6dat = v; }
        !           423: 
        !           424: /* We call pfield_may_need_update() from here. Actually, 
        !           425:  * I have no idea what happens if someone changes ddf or
        !           426:  * diw mid-line, and I don't really want to know. I doubt
        !           427:  * that this sort of thing was ever used to create a
        !           428:  * useful effect.
        !           429:  */
        !           430: static void  DIWSTRT(UWORD v) { pfield_may_need_update(false); diwstrt = v; calcdiw(); }
        !           431: static void  DIWSTOP(UWORD v) { pfield_may_need_update(false); diwstop = v; calcdiw(); }
        !           432: static void  DDFSTRT(UWORD v) { pfield_may_need_update(false); ddfstrt = v; calcdiw(); }
        !           433: static void  DDFSTOP(UWORD v) { pfield_may_need_update(false); ddfstop = v; calcdiw(); }
        !           434: 
        !           435: static void  BLTADAT(UWORD v) { bltadat = v; }
        !           436: static void  BLTBDAT(UWORD v) { bltbdat = v; }
        !           437: static void  BLTCDAT(UWORD v) { bltcdat = v; }
        !           438: 
        !           439: static void  BLTAMOD(UWORD v) { bltamod = v; }
        !           440: static void  BLTBMOD(UWORD v) { bltbmod = v; }
        !           441: static void  BLTCMOD(UWORD v) { bltcmod = v; }
        !           442: static void  BLTDMOD(UWORD v) { bltdmod = v; }
        !           443: 
        !           444: static void  BLTCON0(UWORD v) { bltcon0 = v; }
        !           445: static void  BLTCON1(UWORD v) { bltcon1 = v; }
        !           446: 
        !           447: static void  BLTAFWM(UWORD v) { bltafwm = v; }
        !           448: static void  BLTALWM(UWORD v) { bltalwm = v; }
        !           449: 
        !           450: static void  BLTAPTH(UWORD v) { bltapt= (bltapt & 0xffff) | ((ULONG)v << 16); }
        !           451: static void  BLTAPTL(UWORD v) { bltapt= (bltapt & ~0xffff) | (v); }
        !           452: static void  BLTBPTH(UWORD v) { bltbpt= (bltbpt & 0xffff) | ((ULONG)v << 16); }
        !           453: static void  BLTBPTL(UWORD v) { bltbpt= (bltbpt & ~0xffff) | (v); }
        !           454: static void  BLTCPTH(UWORD v) { bltcpt= (bltcpt & 0xffff) | ((ULONG)v << 16); }
        !           455: static void  BLTCPTL(UWORD v) { bltcpt= (bltcpt & ~0xffff) | (v); }
        !           456: static void  BLTDPTH(UWORD v) { bltdpt= (bltdpt & 0xffff) | ((ULONG)v << 16); }
        !           457: static void  BLTDPTL(UWORD v) { bltdpt= (bltdpt & ~0xffff) | (v); }
        !           458: static void  BLTSIZE(UWORD v) { bltsize = v; bltstate = BLT_init; specialflags |= SPCFLAG_BLIT; }
        !           459: 
        !           460: static void  SPRxCTL(UWORD v, int num) { pfield_may_need_update(false); sprctl[num] = v; sprarmed[num] = false; spron[num] |= 2; }
        !           461: static void  SPRxPOS(UWORD v, int num) { pfield_may_need_update(false); sprpos[num] = v; }
        !           462: static void  SPRxDATA(UWORD v, int num) { pfield_may_need_update(false); sprdata[num] = v; sprarmed[num] = true; }
        !           463: static void  SPRxDATB(UWORD v, int num) { pfield_may_need_update(false); sprdatb[num] = v; }
        !           464: static void  SPRxPTH(UWORD v, int num) { sprpt[num] &= 0xffff; sprpt[num] |= (ULONG)v << 16; spron[num] |= 1; }
        !           465: static void  SPRxPTL(UWORD v, int num) { sprpt[num] &= ~0xffff; sprpt[num] |= v; spron[num] |= 1; }
        !           466: 
        !           467: static void  COLOR(UWORD v, int num)
        !           468: {
        !           469:     pfield_may_need_update(true);
        !           470:     color_regs[num] = v;
        !           471:     acolors[num] = xcolors[v];
        !           472:     acolors[num+32] = xcolors[(v >> 1) & 0x777];
        !           473: }
        !           474: 
        !           475: static void  DSKSYNC(UWORD v) { dsksync = v; }
        !           476: static void  DSKDAT(UWORD v) { dskmfm = v; }
        !           477: static void  DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); }
        !           478: static void  DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); }
        !           479: 
        !           480: static void  DSKLEN(UWORD v) 
        !           481: {
        !           482:     if (v & 0x8000) { dskdmaen++; } else { dskdmaen = 0; }
        !           483:     dsktime = dskdelay; dsksynced = false;
        !           484:     dsklen = dsklength = v; dsklength &= 0x3fff;
        !           485:     if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) {
        !           486:        printf("Non-standard sync: %04x len: %x\n", dsksync, dsklength);
        !           487:     }
        !           488:     if (dsklen & 0x4000) DISK_InitWrite();
        !           489:     if (dskdmaen) specialflags |= SPCFLAG_DISK;
        !           490: }
        !           491: 
        !           492: static UWORD DSKBYTR(void)
        !           493: {
        !           494:     UWORD v = (dsklen >> 1) & 0x6000;
        !           495:     v |= dskbyte;
        !           496:     dskbyte &= ~0x8000;
        !           497:     if (dsksync == dskmfm) v |= 0x1000;
        !           498:     return v;
        !           499: }
        !           500: 
        !           501: static UWORD DSKDATR(void) { return dskmfm; }
        !           502: static UWORD POTGOR(void)
        !           503: {
        !           504:     if (!buttonstate[2]) {     
        !           505:        return 0xffff;
        !           506:     } else {
        !           507:        return 0xbbff;
        !           508:     }
        !           509: }
        !           510: 
        !           511: static UWORD JOY0DAT(void) { return joy0x + (joy0y << 8); }
        !           512: static UWORD JOY1DAT(void)
        !           513: {
        !           514: #ifdef HAVE_JOYSTICK
        !           515:     UWORD dir;
        !           516:     bool button;
        !           517:     read_joystick(&dir, &button);
        !           518:     buttonstate[1] = button;
        !           519:     return dir;
        !           520: #else
        !           521:     return joy1x + (joy1y << 8);
        !           522: #endif
        !           523: }
        !           524: static void JOYTEST(UWORD v)
        !           525: {
        !           526:     joy0x = joy1x = v & 0xFC;
        !           527:     joy0y = joy1y = (v >> 8) & 0xFC;    
        !           528: }
        !           529: static void AUD0LCH(UWORD v) { audlc[0] = (audlc[0] & 0xffff) | ((ULONG)v << 16); }
        !           530: static void AUD0LCL(UWORD v) { audlc[0] = (audlc[0] & ~0xffff) | v; }
        !           531: static void AUD1LCH(UWORD v) { audlc[1] = (audlc[1] & 0xffff) | ((ULONG)v << 16); }
        !           532: static void AUD1LCL(UWORD v) { audlc[1] = (audlc[1] & ~0xffff) | v; }
        !           533: static void AUD2LCH(UWORD v) { audlc[2] = (audlc[2] & 0xffff) | ((ULONG)v << 16); }
        !           534: static void AUD2LCL(UWORD v) { audlc[2] = (audlc[2] & ~0xffff) | v; }
        !           535: static void AUD3LCH(UWORD v) { audlc[3] = (audlc[3] & 0xffff) | ((ULONG)v << 16); }
        !           536: static void AUD3LCL(UWORD v) { audlc[3] = (audlc[3] & ~0xffff) | v; }
        !           537: static void AUD0PER(UWORD v) { audper[0] = v; }
        !           538: static void AUD1PER(UWORD v) { audper[1] = v; }
        !           539: static void AUD2PER(UWORD v) { audper[2] = v; }
        !           540: static void AUD3PER(UWORD v) { audper[3] = v; }
        !           541: static void AUD0VOL(UWORD v) { audvol[0] = v; }
        !           542: static void AUD1VOL(UWORD v) { audvol[1] = v; }
        !           543: static void AUD2VOL(UWORD v) { audvol[2] = v; }
        !           544: static void AUD3VOL(UWORD v) { audvol[3] = v; }
        !           545: static void AUD0LEN(UWORD v) { audlen[0] = v; }
        !           546: static void AUD1LEN(UWORD v) { audlen[1] = v; }
        !           547: static void AUD2LEN(UWORD v) { audlen[2] = v; }
        !           548: static void AUD3LEN(UWORD v) { audlen[3] = v; }
        !           549: 
        !           550: /* Custom chip memory bank */
        !           551: 
        !           552: static ULONG custom_lget(CPTR) REGPARAM;
        !           553: static UWORD custom_wget(CPTR) REGPARAM;
        !           554: static UBYTE custom_bget(CPTR) REGPARAM;
        !           555: static void  custom_lput(CPTR, ULONG) REGPARAM;
        !           556: static void  custom_wput(CPTR, UWORD) REGPARAM;
        !           557: static void  custom_bput(CPTR, UBYTE) REGPARAM;
        !           558: 
        !           559: addrbank custom_bank = {
        !           560:     custom_lget, custom_wget, custom_bget,
        !           561:     custom_lput, custom_wput, custom_bput,
        !           562:     default_xlate, default_check
        !           563: };
        !           564: 
        !           565: UWORD custom_wget(CPTR addr)
        !           566: {
        !           567: #ifdef DUALCPU
        !           568:     customacc = true;
        !           569: #endif
        !           570:     switch(addr & 0x1FE) {
        !           571:      case 0x002: return DMACONR();
        !           572:      case 0x004: return VPOSR();
        !           573:      case 0x006: return VHPOSR();
        !           574:        
        !           575:      case 0x008: return DSKDATR();
        !           576:      case 0x016: return POTGOR();
        !           577:      case 0x01A: return DSKBYTR();
        !           578:      case 0x01C: return INTENAR();
        !           579:      case 0x01E: return INTREQR();
        !           580:      case 0x010: return ADKCONR();
        !           581:      case 0x00A: return JOY0DAT();
        !           582:      case 0x00C: return JOY1DAT();
        !           583:      default:
        !           584:        custom_wput(addr,0);
        !           585:        return 0xffff;
        !           586:     }
        !           587: }
        !           588: 
        !           589: UBYTE custom_bget(CPTR addr)
        !           590: {
        !           591:     return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
        !           592: }
        !           593: 
        !           594: ULONG custom_lget(CPTR addr)
        !           595: {
        !           596:     return ((ULONG)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe);
        !           597: }
        !           598: 
        !           599: void custom_wput(CPTR addr, UWORD value)
        !           600: {
        !           601: #ifdef DUALCPU
        !           602:     customacc = true;
        !           603: #endif
        !           604:     addr &= 0x1FE;
        !           605:     cregs[addr>>1] = value;
        !           606:     switch(addr) {     
        !           607:      case 0x020: DSKPTH(value); break;
        !           608:      case 0x022: DSKPTL(value); break;
        !           609:      case 0x024: DSKLEN(value); break;
        !           610:      case 0x026: DSKDAT(value); break;
        !           611:        
        !           612:      case 0x02A: VPOSW(value); break;
        !           613:        
        !           614:      case 0x040: BLTCON0(value); break;
        !           615:      case 0x042: BLTCON1(value); break;
        !           616:        
        !           617:      case 0x044: BLTAFWM(value); break;
        !           618:      case 0x046: BLTALWM(value); break;
        !           619:        
        !           620:      case 0x050: BLTAPTH(value); break;
        !           621:      case 0x052: BLTAPTL(value); break;
        !           622:      case 0x04C: BLTBPTH(value); break;
        !           623:      case 0x04E: BLTBPTL(value); break;
        !           624:      case 0x048: BLTCPTH(value); break;
        !           625:      case 0x04A: BLTCPTL(value); break;
        !           626:      case 0x054: BLTDPTH(value); break;
        !           627:      case 0x056: BLTDPTL(value); break;
        !           628:        
        !           629:      case 0x058: BLTSIZE(value); break;
        !           630:        
        !           631:      case 0x064: BLTAMOD(value); break;
        !           632:      case 0x062: BLTBMOD(value); break;
        !           633:      case 0x060: BLTCMOD(value); break;
        !           634:      case 0x066: BLTDMOD(value); break;
        !           635:        
        !           636:      case 0x070: BLTCDAT(value); break;
        !           637:      case 0x072: BLTBDAT(value); break;
        !           638:      case 0x074: BLTADAT(value); break;
        !           639:                        
        !           640:      case 0x07E: DSKSYNC(value); break;
        !           641: 
        !           642:      case 0x080: COP1LCH(value); break;
        !           643:      case 0x082: COP1LCL(value); break;
        !           644:      case 0x084: COP2LCH(value); break;
        !           645:      case 0x086: COP2LCL(value); break;
        !           646:        
        !           647:      case 0x088: COPJMP1(value); break;
        !           648:      case 0x08A: COPJMP2(value); break;
        !           649:        
        !           650:      case 0x08E: DIWSTRT(value); break;
        !           651:      case 0x090: DIWSTOP(value); break;
        !           652:      case 0x092: DDFSTRT(value); break;
        !           653:      case 0x094: DDFSTOP(value); break;
        !           654:        
        !           655:      case 0x096: DMACON(value); break;
        !           656:      case 0x09A: INTENA(value); break;
        !           657:      case 0x09C: INTREQ(value); break;
        !           658:      case 0x09E: ADKCON(value); break;
        !           659:        
        !           660:      case 0x0A0: AUD0LCH(value); break;
        !           661:      case 0x0A2: AUD0LCL(value); break;
        !           662:      case 0x0A4: AUD0LEN(value); break;
        !           663:      case 0x0A6: AUD0PER(value); break;
        !           664:      case 0x0A8: AUD0VOL(value); break;
        !           665:        
        !           666:      case 0x0B0: AUD1LCH(value); break;
        !           667:      case 0x0B2: AUD1LCL(value); break;
        !           668:      case 0x0B4: AUD1LEN(value); break;
        !           669:      case 0x0B6: AUD1PER(value); break;
        !           670:      case 0x0B8: AUD1VOL(value); break;
        !           671:        
        !           672:      case 0x0C0: AUD2LCH(value); break;
        !           673:      case 0x0C2: AUD2LCL(value); break;
        !           674:      case 0x0C4: AUD2LEN(value); break;
        !           675:      case 0x0C6: AUD2PER(value); break;
        !           676:      case 0x0C8: AUD2VOL(value); break;
        !           677:        
        !           678:      case 0x0D0: AUD3LCH(value); break;
        !           679:      case 0x0D2: AUD3LCL(value); break;
        !           680:      case 0x0D4: AUD3LEN(value); break;
        !           681:      case 0x0D6: AUD3PER(value); break;
        !           682:      case 0x0D8: AUD3VOL(value); break;
        !           683:        
        !           684:      case 0x0E0: BPL1PTH(value); break;
        !           685:      case 0x0E2: BPL1PTL(value); break;
        !           686:      case 0x0E4: BPL2PTH(value); break;
        !           687:      case 0x0E6: BPL2PTL(value); break;
        !           688:      case 0x0E8: BPL3PTH(value); break;
        !           689:      case 0x0EA: BPL3PTL(value); break;
        !           690:      case 0x0EC: BPL4PTH(value); break;
        !           691:      case 0x0EE: BPL4PTL(value); break;
        !           692:      case 0x0F0: BPL5PTH(value); break;
        !           693:      case 0x0F2: BPL5PTL(value); break;
        !           694:      case 0x0F4: BPL6PTH(value); break;
        !           695:      case 0x0F6: BPL6PTL(value); break;
        !           696:        
        !           697:      case 0x100: BPLCON0(value); break;
        !           698:      case 0x102: BPLCON1(value); break;
        !           699:      case 0x104: BPLCON2(value); break;
        !           700:      case 0x106: BPLCON3(value); break;
        !           701:        
        !           702:      case 0x108: BPL1MOD(value); break;
        !           703:      case 0x10A: BPL2MOD(value); break;
        !           704: 
        !           705:      case 0x110: BPL1DAT(value); break;
        !           706:      case 0x112: BPL2DAT(value); break;
        !           707:      case 0x114: BPL3DAT(value); break;
        !           708:      case 0x116: BPL4DAT(value); break;
        !           709:      case 0x118: BPL5DAT(value); break;
        !           710:      case 0x11A: BPL6DAT(value); break;
        !           711:        
        !           712:      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
        !           713:      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
        !           714:      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
        !           715:      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
        !           716:      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
        !           717:      case 0x1BC: case 0x1BE: 
        !           718:        COLOR(value & 0xFFF, (addr & 0x3E) / 2);
        !           719:        break;  
        !           720:      case 0x120: case 0x124: case 0x128: case 0x12C: 
        !           721:      case 0x130: case 0x134: case 0x138: case 0x13C:
        !           722:        SPRxPTH(value, (addr - 0x120) / 4);
        !           723:        break;
        !           724:      case 0x122: case 0x126: case 0x12A: case 0x12E: 
        !           725:      case 0x132: case 0x136: case 0x13A: case 0x13E:
        !           726:        SPRxPTL(value, (addr - 0x122) / 4);
        !           727:        break;
        !           728:      case 0x140: case 0x148: case 0x150: case 0x158: 
        !           729:      case 0x160: case 0x168: case 0x170: case 0x178:
        !           730:        SPRxPOS(value, (addr - 0x140) / 8);
        !           731:        break;
        !           732:      case 0x142: case 0x14A: case 0x152: case 0x15A: 
        !           733:      case 0x162: case 0x16A: case 0x172: case 0x17A:
        !           734:        SPRxCTL(value, (addr - 0x142) / 8);
        !           735:        break;
        !           736:      case 0x144: case 0x14C: case 0x154: case 0x15C:
        !           737:      case 0x164: case 0x16C: case 0x174: case 0x17C:
        !           738:        SPRxDATA(value, (addr - 0x144) / 8);
        !           739:        break;
        !           740:      case 0x146: case 0x14E: case 0x156: case 0x15E: 
        !           741:      case 0x166: case 0x16E: case 0x176: case 0x17E:
        !           742:        SPRxDATB(value, (addr - 0x146) / 8);
        !           743:        break;
        !           744:        
        !           745:      case 0x36: JOYTEST(value); break; 
        !           746:     }
        !           747: }
        !           748: 
        !           749: void custom_bput(CPTR addr, UBYTE value)
        !           750: {
        !           751:     /* Yes, there are programs that do this. The programmers should be shot.
        !           752:      * This might actually work sometimes. */
        !           753:     UWORD rval = value;
        !           754:     CPTR raddr = addr & 0x1FE;
        !           755:     if (addr & 1) {
        !           756:        rval |= cregs[raddr >> 1] & 0xFF00;
        !           757:     } else {
        !           758:        rval <<= 8;
        !           759:        rval |= cregs[raddr >> 1] & 0xFF;
        !           760:     }
        !           761:     custom_wput(raddr, rval);
        !           762: }
        !           763: 
        !           764: void custom_lput(CPTR addr, ULONG value)
        !           765: {
        !           766:     custom_wput(addr & 0xfffe, value >> 16);
        !           767:     custom_wput((addr+2) & 0xfffe, (UWORD)value);
        !           768: }
        !           769: 
        !           770: static bool copcomp(void)
        !           771: {
        !           772:     UWORD vp = vpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !           773:     UWORD hp = current_hpos() & (copi2 & 0xFE);
        !           774:     UWORD vcmp = copi1 >> 8;
        !           775:     UWORD hcmp = copi1 & 0xFE;
        !           776:     return (vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000));
        !           777: }
        !           778: 
        !           779: /*
        !           780:  * Calculate the minimum number of cycles after which the
        !           781:  * copper comparison becomes true. This is quite tricky. I hope it works.
        !           782:  */
        !           783: static int calc_copcomp_true(int currvpos, int currhpos)
        !           784: {    
        !           785:     UWORD vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !           786:     UWORD hp = currhpos & (copi2 & 0xFE);
        !           787:     UWORD vcmp = copi1 >> 8;
        !           788:     UWORD hcmp = copi1 & 0xFE;
        !           789: 
        !           790:     int cycleadd = maxhpos - currhpos;
        !           791:     int coptime = 0;
        !           792: 
        !           793:     if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)))
        !           794:        return 0;    
        !           795:     
        !           796:     try_again:
        !           797:     
        !           798:     while (vp < vcmp) {
        !           799:        currvpos++;
        !           800:        if (currvpos > maxvpos + 1)
        !           801:            return -1;
        !           802:        currhpos = 0;
        !           803:        coptime += cycleadd;
        !           804:        cycleadd = maxhpos;
        !           805:        vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !           806:     }
        !           807:     hp = currhpos & (copi2 & 0xFE);
        !           808:     if (!(vp > vcmp)) {        
        !           809:        while (hp < hcmp) {
        !           810:            currhpos++;
        !           811:            if (currhpos > maxhpos) {
        !           812:                /* Now, what? There might be a good position on the
        !           813:                 * next line. But it can also be the FFFF FFFE
        !           814:                 * case.
        !           815:                 */
        !           816:                currhpos = 0;
        !           817:                currvpos++;
        !           818:                vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80);
        !           819:                goto try_again;
        !           820:            }
        !           821:            coptime++;
        !           822:            hp = currhpos & (copi2 & 0xFE);
        !           823:        }
        !           824:     }
        !           825:     if (coptime == 0) /* waiting for the blitter */
        !           826:        return 1;
        !           827:     
        !           828:     return coptime;
        !           829: }
        !           830: 
        !           831: static void copper_read(void)
        !           832: {
        !           833:     if (dmaen(DMA_COPPER)){
        !           834:        copi1 = chipmem_bank.wget(coplc); 
        !           835:        copi2 = chipmem_bank.wget(coplc+2);
        !           836:        coplc += 4;
        !           837:        eventtab[ev_copper].oldcycles = cycles;
        !           838:        eventtab[ev_copper].evtime = (copi1 & 1) ? (copi2 & 1) ? 4 : 6 : 4;
        !           839:        copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move;
        !           840:     } else {
        !           841:        copstate = COP_read;
        !           842:        eventtab[ev_copper].active = false;
        !           843:     }
        !           844: }
        !           845: 
        !           846: static void do_copper(void)
        !           847: {    
        !           848:     switch(copstate){
        !           849:      case COP_read:
        !           850:        copper_read();
        !           851:        break;
        !           852:      case COP_move:
        !           853:        if (copi1 >= (copcon & 2 ? 0x40 : 0x80))
        !           854:            custom_bank.wput(copi1,copi2);
        !           855:        copper_read();
        !           856:        break;
        !           857:      case COP_skip:
        !           858:        if (copcomp())
        !           859:            coplc += 4;
        !           860:        copper_read();
        !           861:        break;
        !           862:      case COP_wait: {      
        !           863:         int coptime = calc_copcomp_true(vpos, current_hpos());
        !           864:         if (coptime < 0) {
        !           865:             copstate = COP_stop;
        !           866:             eventtab[ev_copper].active = false;
        !           867:             copper_active = false;
        !           868:         } else {            
        !           869:             if (!coptime)
        !           870:                 copper_read();
        !           871:             else {
        !           872:                 eventtab[ev_copper].evtime = coptime;
        !           873:                 eventtab[ev_copper].oldcycles = cycles;
        !           874:             }
        !           875:         }
        !           876:         break;
        !           877:      }
        !           878:      case COP_stop:
        !           879:        eventtab[ev_copper].active = false;
        !           880:        copper_active = false;
        !           881:        break;
        !           882:     }
        !           883: }
        !           884: 
        !           885: static __inline__ bool blitter_read(void)
        !           886: {
        !           887:     if (bltcon0 & 0xe00){
        !           888:        if (!dmaen(DMA_BLITTER)) return true; /* blitter stopped */
        !           889:        if (!blitline){
        !           890:            if (bltcon0 & 0x800) bltadat = chipmem_bank.wget(bltapt);
        !           891:            if (bltcon0 & 0x400) bltbdat = chipmem_bank.wget(bltbpt);
        !           892:        }
        !           893:        if (bltcon0 & 0x200) bltcdat = chipmem_bank.wget(bltcpt);
        !           894:     }
        !           895:     bltstate = BLT_work;
        !           896:     return (bltcon0 & 0xE00) != 0;
        !           897: }
        !           898: 
        !           899: static __inline__ bool blitter_write(void)
        !           900: {
        !           901:     if (bltddat) blitzero = false;
        !           902:     if ((bltcon0 & 0x100) || blitline){
        !           903:        if (!dmaen(DMA_BLITTER)) return true;
        !           904:        chipmem_bank.wput(bltdpt,bltddat);
        !           905:     }
        !           906:     bltstate = BLT_next;
        !           907:     return (bltcon0 & 0x100) != 0;
        !           908: }
        !           909: 
        !           910: static void blitter_blit(void)
        !           911: {
        !           912:     UWORD blitahold,blitbhold,blitchold;
        !           913:     UWORD bltaold;
        !           914:     
        !           915:     if (blitdesc) {
        !           916:        UWORD bltamask = 0xffff;
        !           917:        
        !           918:        if (!blitlpos) { bltamask &= bltafwm; }
        !           919:        if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
        !           920:        bltaold = bltadat & bltamask;
        !           921: 
        !           922:        blitahold = (((ULONG)bltaold << 16) | blitpreva) >> (16-blitashift);
        !           923:        blitbhold = (((ULONG)bltbdat << 16) | blitprevb) >> (16-blitbshift);
        !           924:        blitchold = bltcdat;
        !           925:     } else {
        !           926:        UWORD bltamask = 0xffff;
        !           927:        
        !           928:        if (!blitlpos) { bltamask &= bltafwm; }
        !           929:        if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
        !           930:        bltaold = bltadat & bltamask;
        !           931: 
        !           932:        blitahold = (((ULONG)blitpreva << 16) | bltaold) >> blitashift;
        !           933:        blitbhold = (((ULONG)blitprevb << 16) | bltbdat) >> blitbshift;
        !           934:        blitchold = bltcdat;
        !           935:     }
        !           936:     bltddat = 0;
        !           937:     bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
        !           938:     if (blitfill){
        !           939:        UWORD fillmask;
        !           940:        for (fillmask = 1; fillmask; fillmask <<= 1){
        !           941:            UWORD tmp = bltddat;
        !           942:            if (blitfc) {
        !           943:                if (blitife)
        !           944:                    bltddat |= fillmask;
        !           945:                else
        !           946:                    bltddat ^= fillmask;
        !           947:            }
        !           948:            if (tmp & fillmask) blitfc = !blitfc;
        !           949:        }
        !           950:     }
        !           951:     bltstate = BLT_write;
        !           952:     blitpreva = bltaold; blitprevb = bltbdat;
        !           953: }
        !           954: 
        !           955: static void blitter_nxblit(void)
        !           956: {
        !           957:     bltstate = BLT_read;
        !           958:     if (blitdesc){
        !           959:        if (++blitlpos == hblitsize) {
        !           960:            if (--vblitsize == 0) {
        !           961:                bltstate = BLT_done;
        !           962: #ifdef NO_FAST_BLITTER
        !           963:                custom_bank.wput(0xDFF09C,0x8040);
        !           964: #endif
        !           965:            }
        !           966:            blitfc = bltcon1 & 0x4;
        !           967: 
        !           968:            blitlpos = 0;
        !           969:            if (bltcon0 & 0x800) bltapt -= 2+bltamod; 
        !           970:            if (bltcon0 & 0x400) bltbpt -= 2+bltbmod; 
        !           971:            if (bltcon0 & 0x200) bltcpt -= 2+bltcmod; 
        !           972:            if (bltcon0 & 0x100) bltdpt -= 2+bltdmod;
        !           973:        } else {
        !           974:            if (bltcon0 & 0x800) bltapt -= 2; 
        !           975:            if (bltcon0 & 0x400) bltbpt -= 2; 
        !           976:            if (bltcon0 & 0x200) bltcpt -= 2; 
        !           977:            if (bltcon0 & 0x100) bltdpt -= 2;       
        !           978:        }
        !           979:     } else {
        !           980:        if (++blitlpos == hblitsize) {
        !           981:            if (--vblitsize == 0) { 
        !           982:                bltstate = BLT_done;
        !           983: #ifdef NO_FAST_BLITTER
        !           984:                custom_bank.wput(0xDFF09C,0x8040);
        !           985: #endif
        !           986:            }
        !           987:            blitlpos = 0;
        !           988:            if (bltcon0 & 0x800) bltapt += 2+bltamod; 
        !           989:            if (bltcon0 & 0x400) bltbpt += 2+bltbmod; 
        !           990:            if (bltcon0 & 0x200) bltcpt += 2+bltcmod; 
        !           991:            if (bltcon0 & 0x100) bltdpt += 2+bltdmod;
        !           992:        } else {
        !           993:            if (bltcon0 & 0x800) bltapt += 2; 
        !           994:            if (bltcon0 & 0x400) bltbpt += 2; 
        !           995:            if (bltcon0 & 0x200) bltcpt += 2; 
        !           996:            if (bltcon0 & 0x100) bltdpt += 2;
        !           997:        }
        !           998:     }
        !           999: }
        !          1000: 
        !          1001: static __inline__ void blitter_line_incx(int a)
        !          1002: {
        !          1003:     blinea >>= 1;
        !          1004:     if (!blinea) {
        !          1005:        blinea = 0x8000;
        !          1006:        bltcnxlpt += 2;
        !          1007:        bltdnxlpt += 2;
        !          1008:     }
        !          1009: }
        !          1010: 
        !          1011: static __inline__ void blitter_line_decx(int shm)
        !          1012: {
        !          1013:     if (shm) blineb = (blineb << 2) | (blineb >> 14);
        !          1014:     blinea <<= 1;
        !          1015:     if (!blinea) {
        !          1016:        blinea = 1;
        !          1017:        bltcnxlpt -= 2;
        !          1018:        bltdnxlpt -= 2;
        !          1019:     }
        !          1020: }
        !          1021: 
        !          1022: static __inline__ void blitter_line_decy(int shm)
        !          1023: {
        !          1024:     if (shm) blineb = (blineb >> 1) | (blineb << 15);
        !          1025:     bltcnxlpt -= bltcmod;
        !          1026:     bltdnxlpt -= bltcmod; /* ??? am I wrong or doesn't KS1.3 set bltdmod? */
        !          1027:     blitonedot = 0;
        !          1028: }
        !          1029: 
        !          1030: static __inline__ void blitter_line_incy(int shm)
        !          1031: {
        !          1032:     if (shm) blineb = (blineb >> 1) | (blineb << 15);
        !          1033:     bltcnxlpt += bltcmod;
        !          1034:     bltdnxlpt += bltcmod; /* ??? */
        !          1035:     blitonedot = 0;
        !          1036: }
        !          1037: 
        !          1038: static void blitter_line(void)
        !          1039: {
        !          1040:     UWORD blitahold = blinea, blitbhold = blineb, blitchold = bltcdat;
        !          1041:     bltddat = 0;
        !          1042:     
        !          1043:     if (blitsing && blitonedot) blitahold = 0;
        !          1044:     blitonedot = 1;
        !          1045:     bltddat = blit_func(blitahold, blitbhold, blitchold, bltcon0 & 0xFF);
        !          1046:     if (!blitsign){
        !          1047:        bltapt += (WORD)bltamod;
        !          1048:        if (bltcon1 & 0x10){
        !          1049:            if (bltcon1 & 0x8)
        !          1050:                blitter_line_decy(0);
        !          1051:            else
        !          1052:                blitter_line_incy(0);
        !          1053:        } else {
        !          1054:            if (bltcon1 & 0x8)
        !          1055:                blitter_line_decx(0);
        !          1056:            else 
        !          1057:                blitter_line_incx(0);
        !          1058:        }
        !          1059:     } else {
        !          1060:        bltapt += (WORD)bltbmod;
        !          1061:     }
        !          1062:     if (bltcon1 & 0x10){
        !          1063:        if (bltcon1 & 0x4)
        !          1064:            blitter_line_decx(1);
        !          1065:        else
        !          1066:            blitter_line_incx(1);
        !          1067:     } else {
        !          1068:        if (bltcon1 & 0x4)
        !          1069:            blitter_line_decy(1);
        !          1070:        else
        !          1071:            blitter_line_incy(1);
        !          1072:     }
        !          1073:     blitsign = 0 > (WORD)bltapt;
        !          1074:     bltstate = BLT_write;
        !          1075: }
        !          1076: 
        !          1077: static __inline__ void blitter_nxline(void)
        !          1078: {
        !          1079:     if (--vblitsize == 0) {
        !          1080:        bltstate = BLT_done;
        !          1081: #ifdef NO_FAST_BLITTER
        !          1082:        custom_bank.wput(0xDFF09C,0x8040);
        !          1083: #endif
        !          1084:     } else {
        !          1085:        bltstate = BLT_read;
        !          1086:        bltcpt = bltcnxlpt;
        !          1087:        bltdpt = bltdnxlpt;
        !          1088:     }
        !          1089: }
        !          1090: 
        !          1091: static void blit_init(void)
        !          1092: {
        !          1093:     vblitsize = bltsize >> 6;
        !          1094:     hblitsize = bltsize & 0x3F;
        !          1095:     if (!vblitsize) vblitsize = 1024;
        !          1096:     if (!hblitsize) hblitsize = 64;
        !          1097:     blitlpos = 0;
        !          1098:     blitzero = true; blitpreva = blitprevb = 0;
        !          1099:     blitline = bltcon1 & 1;
        !          1100:     blitashift = bltcon0 >> 12; blitbshift = bltcon1 >> 12;
        !          1101:     
        !          1102:     if (blitline) {
        !          1103:        bltcnxlpt = bltcpt;
        !          1104:        bltdnxlpt = bltdpt;
        !          1105:        blitsing = bltcon1 & 0x2;
        !          1106:        blinea = bltadat >> blitashift;
        !          1107:        blineb = (bltbdat >> blitbshift) | (bltbdat << (16-blitbshift));
        !          1108:        blitsign = bltcon1 & 0x40; 
        !          1109:        blitonedot = false;
        !          1110:        bltamod &= 0xfffe; bltbmod &= 0xfffe; bltapt &= 0xfffe;
        !          1111:     } else {
        !          1112:        blitfc = bltcon1 & 0x4;
        !          1113:        blitife = bltcon1 & 0x8;
        !          1114:        blitfill = bltcon1 & 0x18;
        !          1115: 
        !          1116:        if ((bltcon1 & 0x18) == 0x18) {
        !          1117:            /* Digital "Trash" demo does this; others too. Apparently, no
        !          1118:             * negative effects. */
        !          1119:            static bool warn = true;
        !          1120:            if (warn)
        !          1121:                fprintf(stderr, "warning: weird fill mode (further messages suppressed)\n");
        !          1122:            warn = false;
        !          1123:        }
        !          1124:        blitdesc = bltcon1 & 0x2;
        !          1125:        if (blitfill && !blitdesc)
        !          1126:            fprintf(stderr, "warning: blitter fill without desc\n");
        !          1127:     }
        !          1128: }
        !          1129: 
        !          1130: #ifdef DEFERRED_INT
        !          1131: 
        !          1132: static UWORD deferred_bits;
        !          1133: 
        !          1134: static void defer_int_handler(void)
        !          1135: {
        !          1136:     INTREQ(0x8000 | deferred_bits);
        !          1137:     deferred_bits = 0;
        !          1138:     eventtab[ev_deferint].active = false;
        !          1139: }
        !          1140: #endif
        !          1141: 
        !          1142: void do_blitter(void)
        !          1143: {
        !          1144: #ifdef NO_FAST_BLITTER
        !          1145:     /* I'm not sure all this bltstate stuff is really necessary.
        !          1146:      * Most programs should be OK if the blit is done as soon as BLTSIZE is
        !          1147:      * written to, and the BLTFINISH bit is set some time after that.
        !          1148:      * This code here is nowhere near exact.
        !          1149:      */
        !          1150:     do {       
        !          1151:        switch(bltstate) {
        !          1152:         case BLT_init:
        !          1153:            blit_init();
        !          1154:            bltstate = BLT_read;
        !          1155:            /* fall through */
        !          1156:         case BLT_read:
        !          1157:            if (blitter_read())
        !          1158:                break;
        !          1159:            /* fall through */
        !          1160:         case BLT_work:
        !          1161:            if (blitline)
        !          1162:                blitter_line(); 
        !          1163:            else 
        !          1164:                blitter_blit();
        !          1165:            /* fall through */
        !          1166:         case BLT_write:
        !          1167:            if (blitter_write())
        !          1168:                break;
        !          1169:            /* fall through */
        !          1170:         case BLT_next:
        !          1171:            if (blitline)
        !          1172:                blitter_nxline();
        !          1173:            else 
        !          1174:                blitter_nxblit();
        !          1175:            break;
        !          1176:         case BLT_done:
        !          1177:            specialflags &= ~SPCFLAG_BLIT;
        !          1178:            break;
        !          1179:        }
        !          1180:     } while(bltstate != BLT_done && dmaen(DMA_BLITTER)
        !          1181:            && dmaen(DMA_BLITPRI));  /* blitter nasty -> no time for CPU */
        !          1182: #else
        !          1183:     if (bltstate == BLT_init) {
        !          1184:        blit_init();
        !          1185:        bltstate =  BLT_read;
        !          1186:     }
        !          1187:     if (!dmaen(DMA_BLITTER))
        !          1188:        return; /* gotta come back later. */
        !          1189: 
        !          1190:     if (blitline) {
        !          1191:        do {
        !          1192:            blitter_read();
        !          1193:            blitter_line();
        !          1194:            blitter_write();
        !          1195:            blitter_nxline();
        !          1196:        } while (bltstate != BLT_done);
        !          1197:     } else {
        !          1198:        do {    
        !          1199:            blitter_read();
        !          1200:            blitter_blit();
        !          1201:            blitter_write();
        !          1202:            blitter_nxblit();
        !          1203:        } while (bltstate != BLT_done);
        !          1204:     }
        !          1205:     eventtab[ev_deferint].active = true;
        !          1206:     eventtab[ev_deferint].oldcycles = cycles;
        !          1207:     eventtab[ev_deferint].evtime = 10; /* whatever */
        !          1208:     deferred_bits |= 0x40;
        !          1209:     events_schedule();
        !          1210: 
        !          1211:     specialflags &= ~SPCFLAG_BLIT;
        !          1212: #endif
        !          1213: }
        !          1214: 
        !          1215: void do_disk(void)
        !          1216: {
        !          1217: #ifdef NO_FAST_FLOPPY
        !          1218:     if (dskdmaen > 1 && dmaen(0x10)){
        !          1219:        if (--dsktime == 0) {
        !          1220:            dsktime = dskdelay;
        !          1221:            if (dsklen & 0x4000){
        !          1222:                UWORD dsksync_check;
        !          1223:                DISK_GetData(&dsksync_check, &dskbyte);
        !          1224:                dskbyte |= 0x8000;
        !          1225:                if (dsksynced || !(adkcon & 0x400)) {
        !          1226:                    *mfmwrite++ = chipmem_bank.wget(dskpt); dskpt += 2;
        !          1227:                    if (--dsklength == 0) {
        !          1228:                        DISK_WriteData();
        !          1229:                        custom_bank.wput(0xDFF09C, 0x8002); /*INTREQ->DSKBLK */
        !          1230:                        dskdmaen = 0;
        !          1231:                        specialflags &= ~SPCFLAG_DISK;
        !          1232:                    }
        !          1233:                }
        !          1234:                if (dsksync_check == dsksync) {
        !          1235:                    custom_bank.wput(0xDFF09C, 0x9000);
        !          1236:                    dsksynced = true;
        !          1237:                }
        !          1238:            } else {
        !          1239:                DISK_GetData(&dskmfm, &dskbyte);
        !          1240:                dskbyte |= 0x8000;
        !          1241:                if (dsksynced || !(adkcon & 0x400)){
        !          1242:                    chipmem_bank.wput(dskpt, dskmfm); dskpt += 2;
        !          1243:                    if (--dsklength == 0) {
        !          1244:                        custom_bank.wput(0xDFF09C, 0x8002);
        !          1245:                        dskdmaen = 0;
        !          1246:                        specialflags &= ~SPCFLAG_DISK;
        !          1247:                    }
        !          1248:                }
        !          1249:                if (dskmfm == dsksync) {
        !          1250:                    custom_bank.wput(0xDFF09C,0x9000);
        !          1251:                    dsksynced = true;
        !          1252:                }
        !          1253:            }
        !          1254:        }
        !          1255:     }
        !          1256: #else
        !          1257:     if (dskdmaen > 1 && dmaen(0x10)){
        !          1258:        /* Just don't get into an infinite loop if the code below screws up */
        !          1259:        int ntries = 100000; 
        !          1260:        
        !          1261:        while (--ntries > 0 && (specialflags & SPCFLAG_DISK)) {
        !          1262:            if (dsklen & 0x4000){
        !          1263:                UWORD dsksync_check;
        !          1264:                DISK_GetData(&dsksync_check, &dskbyte);
        !          1265:                dskbyte |= 0x8000;
        !          1266:                if (dsksynced || !(adkcon & 0x400)) {
        !          1267:                    *mfmwrite++ = chipmem_bank.wget(dskpt); dskpt += 2;
        !          1268:                    if (--dsklength == 0) {
        !          1269:                        DISK_WriteData();
        !          1270:                        dskdmaen = 0;
        !          1271:                        specialflags &= ~SPCFLAG_DISK;
        !          1272:                        eventtab[ev_deferint].active = true;
        !          1273:                        eventtab[ev_deferint].oldcycles = cycles;
        !          1274:                        eventtab[ev_deferint].evtime = 10; /* whatever */
        !          1275:                        events_schedule ();
        !          1276:                        deferred_bits |= 0x0002;
        !          1277:                    }
        !          1278:                }
        !          1279:                if (dsksync_check == dsksync) {
        !          1280:                    /* This is pretty pointless... */
        !          1281:                    custom_bank.wput(0xDFF09C, 0x9000);
        !          1282:                    dsksynced = true;
        !          1283:                }
        !          1284:            } else {
        !          1285:                DISK_GetData(&dskmfm, &dskbyte);
        !          1286:                dskbyte |= 0x8000;
        !          1287:                if (dsksynced || !(adkcon & 0x400)){
        !          1288:                    chipmem_bank.wput(dskpt, dskmfm); dskpt += 2;
        !          1289:                    if (--dsklength == 0) {
        !          1290:                        eventtab[ev_deferint].active = true;
        !          1291:                        eventtab[ev_deferint].oldcycles = cycles;
        !          1292:                        eventtab[ev_deferint].evtime = 10; /* whatever */
        !          1293:                        events_schedule ();
        !          1294:                        deferred_bits |= 0x0002;
        !          1295:                        dskdmaen = 0;
        !          1296:                        specialflags &= ~SPCFLAG_DISK;
        !          1297:                    }
        !          1298:                }
        !          1299:                if (dskmfm == dsksync) {
        !          1300:                    /* This is pretty pointless... */
        !          1301:                    custom_bank.wput(0xDFF09C,0x9000);
        !          1302:                    dsksynced = true;
        !          1303:                }
        !          1304:            }
        !          1305:        }
        !          1306:     }
        !          1307: #endif
        !          1308: }
        !          1309: 
        !          1310: static __inline__ void pfield_fetchdata(void)
        !          1311: {
        !          1312:     if (dmaen(0x100) && pfield_linedmaon) {
        !          1313:        switch(bplplanecnt){
        !          1314:         case 6:
        !          1315:            bpl6dat = chipmem_bank.wget(bpl6pt); bpl6pt += 2; bpl6dat <<= 5;
        !          1316:         case 5:
        !          1317:            bpl5dat = chipmem_bank.wget(bpl5pt); bpl5pt += 2; bpl5dat <<= 4;
        !          1318:         case 4:
        !          1319:            bpl4dat = chipmem_bank.wget(bpl4pt); bpl4pt += 2; bpl4dat <<= 3;
        !          1320:         case 3:
        !          1321:            bpl3dat = chipmem_bank.wget(bpl3pt); bpl3pt += 2; bpl3dat <<= 2;
        !          1322:         case 2:
        !          1323:            bpl2dat = chipmem_bank.wget(bpl2pt); bpl2pt += 2; bpl2dat <<= 1;
        !          1324:         case 1:
        !          1325:            bpl1dat = chipmem_bank.wget(bpl1pt); bpl1pt += 2;
        !          1326:        }
        !          1327:     }
        !          1328: }
        !          1329: 
        !          1330: static void pfield_hsync(int plfline)
        !          1331: {
        !          1332: }
        !          1333: 
        !          1334: static void do_sprites(int currvp)
        !          1335: {   
        !          1336:     int spr;
        !          1337:     for(spr = 0; spr < 8; spr++) {
        !          1338:        int vstart = (sprpos[spr] >> 8) | ((sprctl[spr] << 6) & 0x100);
        !          1339:        int vstop = (sprctl[spr] >> 8) | ((sprctl[spr] << 7) & 0x100);
        !          1340:        if ((vstart <= currvp && vstop >= currvp) || spron[spr] == 1) {
        !          1341:            if (dmaen(0x20)) {
        !          1342:                UWORD data1 = chipmem_bank.wget(sprpt[spr]);
        !          1343:                UWORD data2 = chipmem_bank.wget(sprpt[spr]+2);
        !          1344:                sprpt[spr] += 4;
        !          1345:                
        !          1346:                if (vstop != currvp && spron[spr] != 1) {
        !          1347:                    SPRxDATB(data2, spr);
        !          1348:                    SPRxDATA(data1, spr);
        !          1349:                    if (!spr && !sprvbfl && ((sprpos[0]&0xff)<<2)>0x60) {
        !          1350:                        sprvbfl=2; 
        !          1351:                        spr0ctl=sprctl[0]; 
        !          1352:                        spr0pos=sprpos[0]; 
        !          1353:                    }
        !          1354:                } else {
        !          1355:                    SPRxPOS(data1, spr);
        !          1356:                    SPRxCTL(data2, spr);
        !          1357:                }
        !          1358: 
        !          1359: #if 0
        !          1360:                if (vstop != currvp && !sprptset[spr]) {
        !          1361:                    SPRxDATB(data2, spr);
        !          1362:                    SPRxDATA(data1, spr);
        !          1363:                    if (!spr && !sprvbfl && ((sprpos[0]&0xff)<<2)>0x60) {
        !          1364:                        sprvbfl=2; 
        !          1365:                        spr0ctl=sprctl[0]; 
        !          1366:                        spr0pos=sprpos[0]; 
        !          1367:                    }
        !          1368:                } else {
        !          1369:                    SPRxPOS(data1, spr);
        !          1370:                    SPRxCTL(data2, spr);
        !          1371:                    sprptset[spr] = false;
        !          1372:                }
        !          1373: #endif
        !          1374:            }
        !          1375:        }
        !          1376:     }
        !          1377: }
        !          1378: 
        !          1379: static void pfield_modulos(void)
        !          1380: {
        !          1381:     switch(bplplanecnt){
        !          1382:      case 6:
        !          1383:        bpl6pt += bpl2mod;
        !          1384:      case 5:
        !          1385:        bpl5pt += bpl1mod;
        !          1386:      case 4:
        !          1387:        bpl4pt += bpl2mod;
        !          1388:      case 3:
        !          1389:        bpl3pt += bpl1mod;
        !          1390:      case 2:
        !          1391:        bpl2pt += bpl2mod;
        !          1392:      case 1:
        !          1393:        bpl1pt += bpl1mod;
        !          1394:     }   
        !          1395: }
        !          1396: 
        !          1397: static void pfield_linetoscr(int pix, int stoppos)
        !          1398: {
        !          1399:     if (bplcon0 & 0x800 && bplplanecnt == 6) {
        !          1400:        /* HAM */
        !          1401:        static UWORD lastcolor;
        !          1402:        while (pix < diwfirstword && pix < stoppos) {
        !          1403:            DrawPixel((pix++)-16, acolors[0]);
        !          1404:            lastcolor = color_regs[0];
        !          1405:        }
        !          1406:        while (pix < diwlastword && pix < stoppos) {
        !          1407:            int pv = apixels[pix];
        !          1408:            switch(pv & 0x30) {
        !          1409:             case 0x00: lastcolor = color_regs[pv]; break;
        !          1410:             case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break;
        !          1411:             case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break;
        !          1412:             case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break;
        !          1413:            }
        !          1414:            
        !          1415:            if (spixstate[pix]) {
        !          1416:                DrawPixel(pix-16, acolors[spixels[pix]+16]);
        !          1417:                spixels[pix] = spixstate[pix] = 0;
        !          1418:            } else {
        !          1419:                DrawPixel(pix-16, xcolors[lastcolor]);
        !          1420:            }
        !          1421:            pix++;
        !          1422:        }
        !          1423:        while (pix < stoppos) {
        !          1424:            DrawPixel((pix++)-16, acolors[0]);
        !          1425:        }
        !          1426:     } else {       
        !          1427:        if (bplcon0 & 0x400) {
        !          1428:            int *lookup = (bplcon2 & 0x40) ? dblpf_ind2 : dblpf_ind1;
        !          1429:            /* Dual playfield */
        !          1430:            while (pix < diwfirstword && pix < stoppos) {
        !          1431:                DrawPixel((pix++)-16, acolors[0]);
        !          1432:            }
        !          1433:            while (pix < diwlastword && pix < stoppos) {
        !          1434:                if (spixstate[pix]) {
        !          1435:                    DrawPixel(pix-16, acolors[spixels[pix]+16]);
        !          1436:                    spixels[pix] = spixstate[pix] = 0;
        !          1437:                } else {
        !          1438:                    DrawPixel(pix-16, acolors[lookup[apixels[pix]]]);
        !          1439:                }
        !          1440:                pix++;
        !          1441:            }
        !          1442:            while (pix < stoppos) {
        !          1443:                DrawPixel((pix++)-16, acolors[0]);
        !          1444:            }
        !          1445:        } else {        
        !          1446:            while (pix < diwfirstword && pix < stoppos) {
        !          1447:                DrawPixel((pix++)-16, acolors[0]);
        !          1448:            }
        !          1449:            while (pix < diwlastword && pix < stoppos) {
        !          1450:                if (spixstate[pix]) {
        !          1451:                    if (apixels[pix] == 0 || spixstate[pix] < plf2pri)
        !          1452:                        DrawPixel(pix-16, acolors[spixels[pix]+16]);
        !          1453:                    else
        !          1454:                        DrawPixel(pix-16, acolors[apixels[pix]]);
        !          1455:                    spixels[pix] = spixstate[pix] = 0;
        !          1456:                } else {                    
        !          1457:                    DrawPixel(pix-16, acolors[apixels[pix]]);
        !          1458:                }
        !          1459:                pix++;
        !          1460:            }
        !          1461:            while (pix < stoppos) {
        !          1462:                DrawPixel((pix++)-16, acolors[0]);
        !          1463:            }
        !          1464:        }
        !          1465:     }
        !          1466: }
        !          1467: 
        !          1468: static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb)
        !          1469: {
        !          1470:     int i;
        !          1471:     for(i = 15; i >= 0; i--) {
        !          1472:        int sprxpos = sprxp + i*2;
        !          1473:        if ((sprctl[num] & 0x80) && (num & 1)) {
        !          1474:            /* Attached sprite */
        !          1475:            int col = ((data << 2) & 4) + ((datb << 3) & 8);
        !          1476:            if (col) {
        !          1477:                spixels[sprxpos] = col;
        !          1478:                spixels[sprxpos+1] = col;
        !          1479:                spixstate[sprxpos] = 1 << num;
        !          1480:                spixstate[sprxpos+1] = 1 << num;
        !          1481:            }
        !          1482:            spixstate[sprxpos] |= 1 << (num-1);
        !          1483:            spixstate[sprxpos+1] |= 1 << (num-1);
        !          1484:        } else {                        
        !          1485:            int col = (data & 1) | ((datb << 1) & 2);
        !          1486:            if (spixstate[sprxpos] & (1 << num)) {
        !          1487:                /* finish attached sprite */
        !          1488:                /* Did the upper half of the sprite have any bits set? */
        !          1489:                if (spixstate[sprxpos] & (1 << (num+1)))
        !          1490:                    col += spixels[sprxpos];
        !          1491:                if (!col) {
        !          1492:                    spixstate[sprxpos] = spixstate[sprxpos+1] &= ~(3 << num);
        !          1493:                }
        !          1494:            } else {
        !          1495:                if (col) {
        !          1496:                    col |= (num & 6) << 1;
        !          1497:                }
        !          1498:            }
        !          1499:            if (col) {
        !          1500:                spixels[sprxpos] = col;
        !          1501:                spixels[sprxpos+1] = col;
        !          1502:                spixstate[sprxpos] = 1<<num;
        !          1503:                spixstate[sprxpos+1] = 1<<num;
        !          1504:            }
        !          1505:        }
        !          1506:        data >>= 1;
        !          1507:        datb >>= 1;
        !          1508:     }   
        !          1509: }
        !          1510: 
        !          1511: void pfield_doline_slow(int currhpos)
        !          1512: {
        !          1513:     int xpos = currhpos * 4 - 0x60;
        !          1514:     static int nextpos = -1;
        !          1515:     static int linepos;
        !          1516:     static bool paststop = false;
        !          1517:     
        !          1518:     if (vpos < plffirstline || vpos >= plflastline) 
        !          1519:        return;
        !          1520:     
        !          1521:     if (currhpos == plfstrt) { 
        !          1522:        nextpos = currhpos;
        !          1523:        linepos = 0;
        !          1524:        paststop = false;
        !          1525:     }
        !          1526:     if (currhpos == nextpos) {    
        !          1527:        if (linepos >= plflinelen) {
        !          1528:            nextpos = -1;
        !          1529:            pfield_modulos();
        !          1530:        } else {            
        !          1531:            nextpos += bplhires ? 4 : 8;
        !          1532:            linepos += bplhires ? 4 : 8;
        !          1533:            
        !          1534:            pfield_fetchdata();
        !          1535:            
        !          1536:            if (bplhires) {
        !          1537:                int offs1 = 2 + xpos + 16 + bpldelay1*2; /* Never trust compilers, kids! */
        !          1538:                int offs2 = 2 + xpos + 16 + bpldelay2*2;
        !          1539:                
        !          1540:                int pix;
        !          1541:                for(pix = 15; pix >= 0; pix--) {
        !          1542:                    switch(bplplanecnt) {
        !          1543:                     case 4:
        !          1544:                        apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1;
        !          1545:                     case 3:
        !          1546:                        apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1;
        !          1547:                     case 2:
        !          1548:                        apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1;
        !          1549:                     case 1:
        !          1550:                        apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1;
        !          1551:                    }
        !          1552:                }
        !          1553:            } else {
        !          1554:                int offs1 = 2 + xpos + 32 + bpldelay1*2;
        !          1555:                int offs2 = 2 + xpos + 32 + bpldelay2*2;
        !          1556:                
        !          1557:                int pix;
        !          1558:                for(pix = 30; pix >= 0; pix -= 2) {
        !          1559:                    switch(bplplanecnt) {
        !          1560:                     case 6:
        !          1561:                        apixels[pix + offs2] |= bpl6dat & 0x20;
        !          1562:                        apixels[pix + offs2 + 1] |= bpl6dat & 0x20; bpl6dat >>= 1;
        !          1563:                     case 5:
        !          1564:                        apixels[pix + offs1] |= bpl5dat & 0x10;
        !          1565:                        apixels[pix + offs1 + 1] |= bpl5dat & 0x10; bpl5dat >>= 1;
        !          1566:                     case 4:
        !          1567:                        apixels[pix + offs2] |= bpl4dat & 0x8;
        !          1568:                        apixels[pix + offs2 + 1] |= bpl4dat & 0x8; bpl4dat >>= 1;
        !          1569:                     case 3:
        !          1570:                        apixels[pix + offs1] |= bpl3dat & 0x4; 
        !          1571:                        apixels[pix + offs1 + 1] |= bpl3dat & 0x4; bpl3dat >>= 1;
        !          1572:                     case 2:
        !          1573:                        apixels[pix + offs2] |= bpl2dat & 0x2; 
        !          1574:                        apixels[pix + offs2 + 1] |= bpl2dat & 0x2; bpl2dat >>= 1;
        !          1575:                     case 1:
        !          1576:                        apixels[pix + offs1] |= bpl1dat & 0x1; 
        !          1577:                        apixels[pix + offs1 + 1] |= bpl1dat & 0x1; bpl1dat >>= 1;
        !          1578:                    }
        !          1579:                }
        !          1580:            }   
        !          1581:        }
        !          1582:     }
        !          1583:     if (xpos > 0x60) { /* sprites can't appear that far to the left */
        !          1584:        int spr;
        !          1585:        for(spr = 7; spr >= 0; spr--) {
        !          1586:            if (sprarmed[spr] && xpos == ((sprpos[spr] & 0xFF) * 4) - 0x60) {
        !          1587:                int sprxp = xpos + 2 + (sprctl[spr] & 1)*2;
        !          1588:                pfield_sprite (spr, sprxp, sprdata[spr], sprdatb[spr]);
        !          1589:            }
        !          1590:        }
        !          1591:     }
        !          1592:     
        !          1593:     if (xpos >= 16 && xpos <= 812) {
        !          1594:        pfield_linetoscr (xpos, xpos+4);
        !          1595:     }
        !          1596: }
        !          1597: 
        !          1598: static __inline__ UWORD *pfield_xlateptr(CPTR plpt, int bytecount)
        !          1599: {
        !          1600:     if (!chipmem_bank.check(plpt,bytecount)) {
        !          1601:        fprintf(stderr, "Warning: Bad playfield pointer\n");
        !          1602:        return NULL;
        !          1603:     }
        !          1604:     return chipmem_bank.xlateaddr(plpt);
        !          1605: }
        !          1606: 
        !          1607: /*
        !          1608:  * A few hand-unrolled loops...
        !          1609:  */
        !          1610: static __inline__ void pfield_orword_hires(UWORD **plfptr, 
        !          1611:                                           unsigned char **dataptr, int bit)
        !          1612: {
        !          1613:     UWORD data = *(*plfptr)++;
        !          1614:     unsigned char *pixptr = *dataptr;
        !          1615:     
        !          1616:     if (data & 0x8000) *pixptr |= bit;
        !          1617:     pixptr++;
        !          1618:     if (data & 0x4000) *pixptr |= bit;
        !          1619:     pixptr++;
        !          1620:     if (data & 0x2000) *pixptr |= bit;
        !          1621:     pixptr++;
        !          1622:     if (data & 0x1000) *pixptr |= bit;
        !          1623:     pixptr++;
        !          1624:     if (data & 0x800) *pixptr |= bit;
        !          1625:     pixptr++;
        !          1626:     if (data & 0x400) *pixptr |= bit;
        !          1627:     pixptr++;
        !          1628:     if (data & 0x200) *pixptr |= bit;
        !          1629:     pixptr++;
        !          1630:     if (data & 0x100) *pixptr |= bit;
        !          1631:     pixptr++;
        !          1632:     if (data & 0x80) *pixptr |= bit;
        !          1633:     pixptr++;
        !          1634:     if (data & 0x40) *pixptr |= bit;
        !          1635:     pixptr++;
        !          1636:     if (data & 0x20) *pixptr |= bit;
        !          1637:     pixptr++;
        !          1638:     if (data & 0x10) *pixptr |= bit;
        !          1639:     pixptr++;
        !          1640:     if (data & 0x8) *pixptr |= bit;
        !          1641:     pixptr++;
        !          1642:     if (data & 0x4) *pixptr |= bit;
        !          1643:     pixptr++;
        !          1644:     if (data & 0x2) *pixptr |= bit;
        !          1645:     pixptr++;
        !          1646:     if (data & 0x1) *pixptr |= bit;
        !          1647:     pixptr++;
        !          1648:     *dataptr = pixptr;
        !          1649: }
        !          1650: 
        !          1651: static __inline__ void pfield_orword_lores(UWORD **plfptr,
        !          1652:                                           unsigned char **dataptr, int bit)
        !          1653: {
        !          1654:     UWORD data = *(*plfptr)++;
        !          1655:     unsigned char *pixptr = *dataptr;
        !          1656:     if (data & 0x8000) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1657:     pixptr+=2;
        !          1658:     if (data & 0x4000) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1659:     pixptr+=2;
        !          1660:     if (data & 0x2000) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1661:     pixptr+=2;
        !          1662:     if (data & 0x1000) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1663:     pixptr+=2;
        !          1664:     if (data & 0x800) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1665:     pixptr+=2;
        !          1666:     if (data & 0x400) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1667:     pixptr+=2;
        !          1668:     if (data & 0x200) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1669:     pixptr+=2;
        !          1670:     if (data & 0x100) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1671:     pixptr+=2;
        !          1672:     if (data & 0x80) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1673:     pixptr+=2;
        !          1674:     if (data & 0x40) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1675:     pixptr+=2;
        !          1676:     if (data & 0x20) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1677:     pixptr+=2;
        !          1678:     if (data & 0x10) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1679:     pixptr+=2;
        !          1680:     if (data & 0x8) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1681:     pixptr+=2;
        !          1682:     if (data & 0x4) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1683:     pixptr+=2;
        !          1684:     if (data & 0x2) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1685:     pixptr+=2;
        !          1686:     if (data & 0x1) { *pixptr |= bit; *(pixptr+1) |= bit; }
        !          1687:     pixptr+=2;
        !          1688:     *dataptr = pixptr;
        !          1689: }
        !          1690: 
        !          1691: static __inline__ void pfield_setword_hires(UWORD **plfptr, 
        !          1692:                                            unsigned char **dataptr, int bit)
        !          1693: {
        !          1694:     UWORD data = *(*plfptr)++;
        !          1695:     unsigned char *pixptr = *dataptr; 
        !          1696:     if (data & 0x8000) *pixptr++ = bit;
        !          1697:     else *pixptr++ = 0;
        !          1698:     if (data & 0x4000) *pixptr++ = bit;
        !          1699:     else *pixptr++ = 0;
        !          1700:     if (data & 0x2000) *pixptr++ = bit;
        !          1701:     else *pixptr++ = 0;
        !          1702:     if (data & 0x1000) *pixptr++ = bit;
        !          1703:     else *pixptr++ = 0;
        !          1704:     if (data & 0x800) *pixptr++ = bit;
        !          1705:     else *pixptr++ = 0;
        !          1706:     if (data & 0x400) *pixptr++ = bit;
        !          1707:     else *pixptr++ = 0;
        !          1708:     if (data & 0x200) *pixptr++ = bit;
        !          1709:     else *pixptr++ = 0;
        !          1710:     if (data & 0x100) *pixptr++ = bit;
        !          1711:     else *pixptr++ = 0;
        !          1712:     if (data & 0x80) *pixptr++ = bit;
        !          1713:     else *pixptr++ = 0;
        !          1714:     if (data & 0x40) *pixptr++ = bit;
        !          1715:     else *pixptr++ = 0;
        !          1716:     if (data & 0x20) *pixptr++ = bit;
        !          1717:     else *pixptr++ = 0;
        !          1718:     if (data & 0x10) *pixptr++ = bit;
        !          1719:     else *pixptr++ = 0;
        !          1720:     if (data & 0x8) *pixptr++ = bit;
        !          1721:     else *pixptr++ = 0;
        !          1722:     if (data & 0x4) *pixptr++ = bit;
        !          1723:     else *pixptr++ = 0;
        !          1724:     if (data & 0x2) *pixptr++ = bit;
        !          1725:     else *pixptr++ = 0;
        !          1726:     if (data & 0x1) *pixptr++ = bit;
        !          1727:     else *pixptr++ = 0;
        !          1728:     *dataptr = pixptr;
        !          1729: }
        !          1730:        
        !          1731: static __inline__ void pfield_setword_lores(UWORD **plfptr,
        !          1732:                                            unsigned char **dataptr, int bit)
        !          1733: {
        !          1734:     UWORD data = *(*plfptr)++;
        !          1735:     unsigned char *pixptr = *dataptr;
        !          1736:     
        !          1737:     if (data & 0x8000) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1738:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1739:     if (data & 0x4000) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1740:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1741:     if (data & 0x2000) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1742:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1743:     if (data & 0x1000) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1744:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1745:     if (data & 0x800) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1746:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1747:     if (data & 0x400) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1748:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1749:     if (data & 0x200) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1750:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1751:     if (data & 0x100) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1752:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1753:     if (data & 0x80) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1754:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1755:     if (data & 0x40) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1756:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1757:     if (data & 0x20) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1758:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1759:     if (data & 0x10) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1760:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1761:     if (data & 0x8) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1762:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1763:     if (data & 0x4) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1764:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1765:     if (data & 0x2) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1766:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1767:     if (data & 0x1) { *pixptr++ = bit; *pixptr++ = bit; }
        !          1768:     else { *pixptr++ = 0; *pixptr++ = 0; }
        !          1769:     
        !          1770:     *dataptr = pixptr;
        !          1771: }
        !          1772: 
        !          1773: static void pfield_doline(void)
        !          1774: {
        !          1775:     int xpos = plfstrt * 4 - 0x60;
        !          1776:     int spr;
        !          1777:     int linelen;
        !          1778: 
        !          1779:     if (vpos < plffirstline || vpos >= plflastline) 
        !          1780:        return;
        !          1781: 
        !          1782:     if (dmaen(0x100) && pfield_linedmaon) {    
        !          1783:        /*
        !          1784:         * We want to use real pointers, but we don't want to get segfaults
        !          1785:          * because of them.
        !          1786:          */
        !          1787:        UWORD *r_bpl1pt,*r_bpl2pt,*r_bpl3pt,*r_bpl4pt,*r_bpl5pt,*r_bpl6pt;
        !          1788:        int bytecount = plflinelen / (bplhires ? 4 : 8) * 2;
        !          1789:        switch (bplplanecnt) {      
        !          1790:         case 6:
        !          1791:            r_bpl6pt = pfield_xlateptr(bpl6pt, bytecount);
        !          1792:            if (r_bpl6pt == NULL)
        !          1793:                return;
        !          1794:         case 5: 
        !          1795:            r_bpl5pt = pfield_xlateptr(bpl5pt, bytecount);
        !          1796:            if (r_bpl5pt == NULL)
        !          1797:                return;
        !          1798:         case 4:
        !          1799:            r_bpl4pt = pfield_xlateptr(bpl4pt, bytecount);
        !          1800:            if (r_bpl4pt == NULL)
        !          1801:                return;
        !          1802:         case 3:
        !          1803:            r_bpl3pt = pfield_xlateptr(bpl3pt, bytecount);
        !          1804:            if (r_bpl3pt == NULL)
        !          1805:                return;
        !          1806:         case 2: 
        !          1807:            r_bpl2pt = pfield_xlateptr(bpl2pt, bytecount);
        !          1808:            if (r_bpl2pt == NULL)
        !          1809:                return;
        !          1810:         case 1:
        !          1811:            r_bpl1pt = pfield_xlateptr(bpl1pt, bytecount);
        !          1812:            if (r_bpl1pt == NULL)
        !          1813:                return;
        !          1814:        } 
        !          1815:        switch (bplplanecnt) {      
        !          1816:         case 6: bpl6pt += bytecount + bpl2mod;
        !          1817:         case 5: bpl5pt += bytecount + bpl1mod;
        !          1818:         case 4: bpl4pt += bytecount + bpl2mod;
        !          1819:         case 3: bpl3pt += bytecount + bpl1mod;
        !          1820:         case 2: bpl2pt += bytecount + bpl2mod;
        !          1821:         case 1: bpl1pt += bytecount + bpl1mod;
        !          1822:        }
        !          1823:  
        !          1824:        if (bplhires) { 
        !          1825:            int xpos1 = 2 + xpos + 16 + bpldelay1*2;
        !          1826:            int xpos2 = 2 + xpos + 16 + bpldelay2*2;
        !          1827:            unsigned char *xp1ptr = apixels+xpos1;
        !          1828:            unsigned char *xp2ptr = apixels+xpos2;
        !          1829: 
        !          1830:            if (bplplanecnt > 0) {
        !          1831:                unsigned char *app = xp1ptr;
        !          1832:                for (linelen = plflinelen; linelen > 0; linelen-=4) {
        !          1833:                    pfield_setword_hires(&r_bpl1pt, &app, 1);
        !          1834:                }
        !          1835:                if (bplplanecnt > 2) {
        !          1836:                    unsigned char *app = xp1ptr;
        !          1837:                    for (linelen = plflinelen; linelen > 0; linelen-=4) {
        !          1838:                        pfield_orword_hires(&r_bpl3pt, &app, 4);
        !          1839:                    }
        !          1840:                }
        !          1841:                if (bplplanecnt > 1) {
        !          1842:                    unsigned char *app = xp2ptr;
        !          1843:                    for (linelen = plflinelen; linelen > 0; linelen-=4) {
        !          1844:                        pfield_orword_hires(&r_bpl2pt, &app, 2);
        !          1845:                    }
        !          1846:                }
        !          1847:                if (bplplanecnt > 3) {
        !          1848:                    unsigned char *app = xp2ptr;
        !          1849:                    for (linelen = plflinelen; linelen > 0; linelen-=4) {
        !          1850:                        pfield_orword_hires(&r_bpl4pt, &app, 8);
        !          1851:                    }
        !          1852:                }
        !          1853:            } else {
        !          1854:                memset(apixels, 0, sizeof(apixels));
        !          1855:            }
        !          1856:        } else {
        !          1857:            int xpos1 = 2 + xpos + 32 + bpldelay1*2;
        !          1858:            int xpos2 = 2 + xpos + 32 + bpldelay2*2;
        !          1859:            unsigned char *xp1ptr = apixels+xpos1;
        !          1860:            unsigned char *xp2ptr = apixels+xpos2;
        !          1861:            if (bplplanecnt > 0) {
        !          1862:                unsigned char *app = xp1ptr;
        !          1863:                for (linelen = plflinelen; linelen > 0; linelen-=8) {
        !          1864:                    pfield_setword_lores(&r_bpl1pt, &app, 1);
        !          1865:                }
        !          1866:                if (bplplanecnt > 2) {
        !          1867:                    unsigned char *app = xp1ptr;
        !          1868:                    for (linelen = plflinelen; linelen > 0; linelen-=8) {
        !          1869:                        pfield_orword_lores(&r_bpl3pt, &app, 4);
        !          1870:                    }
        !          1871:                }
        !          1872:                if (bplplanecnt > 4) {
        !          1873:                    unsigned char *app = xp1ptr;
        !          1874:                    for (linelen = plflinelen; linelen > 0; linelen-=8) {
        !          1875:                        pfield_orword_lores(&r_bpl5pt, &app, 16);
        !          1876:                    }
        !          1877:                }
        !          1878:                if (bplplanecnt > 1) {
        !          1879:                    unsigned char *app = xp2ptr;
        !          1880:                    for (linelen = plflinelen; linelen > 0; linelen-=8) {
        !          1881:                        pfield_orword_lores(&r_bpl2pt, &app, 2);
        !          1882:                    }
        !          1883:                }
        !          1884:                if (bplplanecnt > 3) {
        !          1885:                    unsigned char *app = xp2ptr;
        !          1886:                    for (linelen = plflinelen; linelen > 0; linelen-=8) {
        !          1887:                        pfield_orword_lores(&r_bpl4pt, &app, 8);
        !          1888:                    }
        !          1889:                }
        !          1890:                if (bplplanecnt > 5) {
        !          1891:                    unsigned char *app = xp2ptr;
        !          1892:                    for (linelen = plflinelen; linelen > 0; linelen-=8) {
        !          1893:                        pfield_orword_lores(&r_bpl6pt, &app, 32);
        !          1894:                    }
        !          1895:                }
        !          1896:            } else {
        !          1897:                memset(apixels, 0, sizeof(apixels));
        !          1898:            }
        !          1899:        }
        !          1900:     }
        !          1901:     for(spr = 7; spr >= 0; spr--) {
        !          1902:        if (sprarmed[spr]) {
        !          1903:            int sprxp = ((sprpos[spr] & 0xFF) * 4) - 0x60 + 2 + (sprctl[spr] & 1)*2;
        !          1904:            int i;
        !          1905:            /* Ugh. Nasty bug. Let's rather lose some sprites than trash
        !          1906:             * memory. */
        !          1907:            if (sprxp < 0)
        !          1908:                continue;
        !          1909:            pfield_sprite (spr, sprxp, sprdata[spr], sprdatb[spr]);
        !          1910:        }
        !          1911:     }
        !          1912:     
        !          1913:     pfield_linetoscr (16, 812);
        !          1914: }
        !          1915: 
        !          1916: static void setdontcare(void)
        !          1917: {
        !          1918:     printf("Don't care mouse mode set\n");
        !          1919:     mousestate=dont_care_mouse;
        !          1920:     lastspr0x=lastmx; lastspr0y=lastmy;
        !          1921:     mstepx=defstepx; mstepy=defstepy;
        !          1922: }
        !          1923: 
        !          1924: static void setfollow(void)
        !          1925: {
        !          1926:     printf("Follow sprite mode set\n");
        !          1927:     mousestate=follow_mouse;
        !          1928:     lastdiffx=lastdiffy=0;
        !          1929:     sprvbfl=0;
        !          1930:     spr0ctl=spr0pos=0;
        !          1931:     mstepx=defstepx; mstepy=defstepy;
        !          1932: }
        !          1933: 
        !          1934: void togglemouse(void)
        !          1935: {
        !          1936:     switch(mousestate) {
        !          1937:      case dont_care_mouse: setfollow(); break;
        !          1938:      case follow_mouse: setdontcare(); break;
        !          1939:     }
        !          1940: }          
        !          1941: 
        !          1942: #if 0 /* Mouse calibrations works well enough without this. */
        !          1943: void mousesetup(void)
        !          1944: {
        !          1945:     if (mousestate != follow_mouse) return;
        !          1946:     char buf[80];
        !          1947:     printf("\nMouse pointer centering.\n\n");
        !          1948:     printf("Current values: xoffs=0x%x yoffs=0x%x\n", xoffs, yoffs);
        !          1949:     printf("New values (y/n)?";
        !          1950:     cin.get(buf,80,'\n');
        !          1951:     if (toupper(buf[0]) != 'Y') return;
        !          1952:     cout << "\nxoffs= "; cin>>xoffs;
        !          1953:     cout << "yoffs= "; cin>>yoffs;
        !          1954:     cout << "\n";
        !          1955: }
        !          1956: #endif
        !          1957: 
        !          1958: static __inline__ int adjust(int val)
        !          1959: {
        !          1960:     if (val>127)
        !          1961:        return 127; 
        !          1962:     else if (val<-127)
        !          1963:        return -127;
        !          1964:     return val;
        !          1965: }
        !          1966: 
        !          1967: static void vsync_handler(void)
        !          1968: {
        !          1969:     int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1);
        !          1970:     int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1;
        !          1971:     int diffx, diffy;
        !          1972:     int i;
        !          1973:     
        !          1974:     handle_events();
        !          1975: #ifdef HAVE_JOYSTICK
        !          1976:     {
        !          1977:        UWORD dir;
        !          1978:        bool button;
        !          1979:        read_joystick(&dir, &button);
        !          1980:        buttonstate[1] = button;
        !          1981:     }
        !          1982: #endif
        !          1983: 
        !          1984:     if (produce_sound)
        !          1985:        flush_sound ();
        !          1986:     
        !          1987:     switch (mousestate) {
        !          1988:      case normal_mouse:
        !          1989:        diffx = lastmx - lastsampledmx;
        !          1990:        diffy = lastmy - lastsampledmy;
        !          1991:        if (!newmousecounters) {        
        !          1992:            if (diffx > 127) diffx = 127;
        !          1993:            if (diffx < -127) diffx = -127;
        !          1994:            joy0x += diffx;
        !          1995:            if (diffy > 127) diffy = 127;
        !          1996:            if (diffy < -127) diffy = -127;
        !          1997:            joy0y += diffy;
        !          1998:        }
        !          1999:        lastsampledmx += diffx; lastsampledmy += diffy;
        !          2000:        break;
        !          2001: 
        !          2002:      case dont_care_mouse:
        !          2003:        diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16);
        !          2004:        diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16);
        !          2005:        lastspr0x=lastmx; lastspr0y=lastmy;
        !          2006:        joy0x+=diffx; joy0y+=diffy;
        !          2007:        break;
        !          2008:        
        !          2009:      case follow_mouse:
        !          2010:        if (sprvbfl && sprvbfl-- >1) {
        !          2011:            int mouseypos;
        !          2012:            
        !          2013:            if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x 
        !          2014:                && spr0x > plfstrt*4+34+xcaloff && spr0x < plfstop*4-xcaloff)
        !          2015:            {  
        !          2016:                int val = (lastdiffx << 16) / (spr0x - lastspr0x);
        !          2017:                if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight;
        !          2018:            }
        !          2019:            if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y
        !          2020:                && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff) 
        !          2021:            { 
        !          2022:                int val = (lastdiffy<<16) / (spr0y-lastspr0y);
        !          2023:                if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight;
        !          2024:            }
        !          2025:            mouseypos = lastmy;
        !          2026: 
        !          2027:            /* Calculations might be incorrect */
        !          2028:            if(dont_want_aspect)
        !          2029:                mouseypos *= 2;
        !          2030: 
        !          2031:            /* cout<<" mstepx= "<<mstepx<<" mstepy= "<<mstepy<<"\n";*/
        !          2032:            diffx = adjust ((((lastmx + 0x70 + xoffs - spr0x) & ~1) * mstepx) >> 16);
        !          2033:            diffy = adjust ((((mouseypos + yoffs - spr0y+minfirstline*2) & ~1) * mstepy) >> 16);
        !          2034:            lastspr0x=spr0x; lastspr0y=spr0y;
        !          2035:            lastdiffx=diffx; lastdiffy=diffy;
        !          2036:            joy0x+=diffx; joy0y+=diffy; 
        !          2037:        }
        !          2038:        break;
        !          2039:     }
        !          2040:  
        !          2041:     INTREQ(0x8020);
        !          2042:     if (bplcon0 & 4) lof ^= 0x8000;
        !          2043:     COPJMP1(0);
        !          2044:     
        !          2045:     for (i = 0; i < 8; i++)
        !          2046:        spron[i] = 0;
        !          2047: 
        !          2048:     if (framecnt == 0)
        !          2049:        flush_screen ();
        !          2050:     count_frame();    
        !          2051: #ifdef __unix
        !          2052:     {
        !          2053:        struct timeval tv;
        !          2054:        unsigned long int newtime;
        !          2055:        
        !          2056:        gettimeofday(&tv,NULL); 
        !          2057:        newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
        !          2058:        
        !          2059:        if (!bogusframe) {      
        !          2060:            frametime += newtime - msecs;
        !          2061:            timeframes++;
        !          2062:        }
        !          2063:        msecs = newtime;
        !          2064:        bogusframe = false;
        !          2065:     }
        !          2066: #endif
        !          2067:     CIA_vsync_handler();
        !          2068: }
        !          2069: 
        !          2070: static void hsync_handler(void)
        !          2071: {
        !          2072:     eventtab[ev_hsync].oldcycles = cycles;
        !          2073:     CIA_hsync_handler();
        !          2074:     
        !          2075:     if(produce_sound)
        !          2076:        do_sound ();
        !          2077: 
        !          2078:     if (framecnt == 0 && vpos >= plffirstline && vpos < plflastline 
        !          2079:        && vpos >= minfirstline) 
        !          2080:     {
        !          2081:        /* Finish the line, if we started doing it with the slow update.
        !          2082:         * Otherwise, draw it entirely. */
        !          2083:        if (pfield_fullline) {      
        !          2084:            if (!pfield_linedone) {             
        !          2085:                pfield_doline();
        !          2086:            }
        !          2087:        } else {
        !          2088:            int i;
        !          2089:            for(i = pfield_lastpart_hpos; i < maxhpos; i++)
        !          2090:                pfield_doline_slow(i);
        !          2091:        }
        !          2092:        flush_line ();
        !          2093:     }
        !          2094:     pfield_calclinedma();
        !          2095:     pfield_fullline = true;
        !          2096:     pfield_linedone = false;
        !          2097:     pfield_lastpart_hpos = 0;
        !          2098: 
        !          2099:     if (++vpos == (maxvpos + (lof != 0))) {
        !          2100:        vpos = 0;
        !          2101:        vsync_handler();
        !          2102:     }
        !          2103:     
        !          2104:     /* Tell the graphics code about the next line. */
        !          2105:     if (framecnt == 0 && vpos >= plffirstline && vpos < plflastline
        !          2106:        && vpos >= minfirstline) 
        !          2107:     {
        !          2108:        if (dont_want_aspect) {
        !          2109:            prepare_line(vpos - minfirstline, false);
        !          2110:        } else {
        !          2111:            if (bplcon0 & 4) {
        !          2112:                if(lof) {
        !          2113:                    prepare_line((vpos-minfirstline)*2, false);
        !          2114:                } else {
        !          2115:                    prepare_line((vpos-minfirstline)*2+1, false);
        !          2116:                }
        !          2117:            } else {
        !          2118:                prepare_line((vpos-minfirstline)*2, true);
        !          2119:            }
        !          2120:        }
        !          2121:     }
        !          2122: 
        !          2123:     /* do_sprites must be called after pfield_lastpart_hpos
        !          2124:      * is set to 0. */
        !          2125:     if (vpos > 0) do_sprites(vpos);
        !          2126: }
        !          2127: 
        !          2128: void customreset(void)
        !          2129: {
        !          2130:     int i;
        !          2131: #ifdef __unix
        !          2132:     struct timeval tv;
        !          2133: #endif
        !          2134:     inhibit_frame = 0;
        !          2135:     CIA_reset();
        !          2136:     cycles = 0; specialflags = 0;
        !          2137:     
        !          2138:     vpos = 0; lof = 0;
        !          2139:     
        !          2140:     if (needmousehack()) {
        !          2141:        if (mousestate != follow_mouse) setfollow();
        !          2142:     } else {
        !          2143:        mousestate = normal_mouse;
        !          2144:     }
        !          2145: 
        !          2146:     memset(spixels, 0, sizeof(spixels));
        !          2147:     memset(spixstate, 0, sizeof(spixstate));
        !          2148:     
        !          2149:     prepare_line(0, false); /* Get the graphics stuff in a sane state */
        !          2150:     
        !          2151:     dmacon = intena = 0;
        !          2152:     bltstate = BLT_done;
        !          2153:     copstate = COP_stop;
        !          2154:     copcon = 0;
        !          2155:     dskdmaen = 0;
        !          2156:     cycles = 0;
        !          2157:     for(i = ev_copper; i < ev_max; i++) {
        !          2158:        eventtab[i].active = false;
        !          2159:        eventtab[i].oldcycles = 0;
        !          2160:     }
        !          2161:     copper_active = false;
        !          2162:     eventtab[ev_cia].handler = CIA_handler;
        !          2163:     eventtab[ev_copper].handler = do_copper;
        !          2164:     eventtab[ev_hsync].handler = hsync_handler;
        !          2165:     eventtab[ev_hsync].evtime = maxhpos;
        !          2166:     eventtab[ev_hsync].active = true;
        !          2167: #ifdef DEFERRED_INT
        !          2168:     eventtab[ev_deferint].handler = defer_int_handler;
        !          2169:     eventtab[ev_deferint].active = false;
        !          2170:     deferred_bits = 0;
        !          2171: #endif
        !          2172:     events_schedule();
        !          2173:     
        !          2174: #ifdef __unix
        !          2175:     gettimeofday(&tv,NULL);
        !          2176:     seconds_base = tv.tv_sec;
        !          2177:     bogusframe = true;
        !          2178: #endif
        !          2179: }
        !          2180: 
        !          2181: void dumpcustom(void)
        !          2182: {
        !          2183: 
        !          2184:     printf("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
        !          2185:           intena, intreq, vpos, current_hpos());
        !          2186:     if (timeframes) { 
        !          2187:        printf("Average frame time: %d ms [frames: %d time: %d]\n", 
        !          2188:               frametime/timeframes, timeframes, frametime);
        !          2189:     }
        !          2190: }
        !          2191: 
        !          2192: int intlev(void)
        !          2193: {
        !          2194:     UWORD imask = intreq & intena;
        !          2195:     if (imask && (intena & 0x4000)){
        !          2196:        if (imask & 0x2000) return 6;
        !          2197:        if (imask & 0x1800) return 5;
        !          2198:        if (imask & 0x0780) return 4;
        !          2199:        if (imask & 0x0070) return 3;
        !          2200:        if (imask & 0x0008) return 2;
        !          2201:        if (imask & 0x0007) return 1;
        !          2202:     }
        !          2203:     return -1;
        !          2204: }
        !          2205: 
        !          2206: void custom_init(void)
        !          2207: {
        !          2208:     int num;
        !          2209:     setfollow();
        !          2210:     customreset();
        !          2211:     for (num = 0; num < 64; num++) {   
        !          2212:        int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4);
        !          2213:        int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4);
        !          2214:        if (plane2 > 0) plane2 += 8;
        !          2215:        dblpf_ind1[num] = plane1 == 0 ? plane2 : plane1;
        !          2216:        dblpf_ind2[num] = plane2 == 0 ? plane1 : plane2;
        !          2217:     }
        !          2218: }

unix.superglobalmegacorp.com

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