Annotation of uae/custom.cc, revision 1.1

1.1     ! root        1:  /* 
        !             2:   * UAE - The Unusable Amiga Emulator
        !             3:   * 
        !             4:   * custom chip support v0.6
        !             5:   *
        !             6:   * v0.0: 950228
        !             7:   *       provide DMACON/INTENA/INTREQ dummys so that KS gets the memory check
        !             8:   *       right
        !             9:   * v0.1: 950304
        !            10:   *       more registers (partially) implemented
        !            11:   *       copper and beam position should work, so should interrupts
        !            12:   * v0.2: 950305
        !            13:   *       Blitter implemented. Doesn't work.
        !            14:   *       some b/w playfield support
        !            15:   * v0.3: 950306
        !            16:   *       many bug fixes
        !            17:   * v0.4: 950309
        !            18:   *       lots more bug fixes. A hand holding a disk appears in the X window!
        !            19:   *       But it sure looks messed up.
        !            20:   * v0.5: 950311
        !            21:   *       hopefully fixed all remaining blitter bugs. The hand and the disk 
        !            22:   *       look PERFECT!
        !            23:   * v0.6: 950312
        !            24:   *       interface to disk code
        !            25:   *
        !            26:   * (c) 1995 Bernd Schmidt
        !            27:   */
        !            28: 
        !            29: #include <iostream.h>
        !            30: #include <iomanip.h>
        !            31: 
        !            32: #include "amiga.h"
        !            33: #include "memory.h"
        !            34: #include "custom.h"
        !            35: #include "cia.h"
        !            36: #include "disk.h"
        !            37: #include "xwin.h"
        !            38: 
        !            39: static const int maxhpos = 227,maxvpos = 312;
        !            40: static const int dskdelay = 80; // FIXME: ???
        !            41: 
        !            42: UWORD custom64k::wget(UWORD addr)
        !            43: {
        !            44:   UWORD (*f)() = cchiptable[(addr >> 1) & 0xFF].get;
        !            45:   if (f != 0) return (*f)();
        !            46:   else {
        !            47:     cout << "Custom read at " << hex << addr << "\n";
        !            48:     return 0;
        !            49:   }
        !            50: }
        !            51: 
        !            52: UBYTE custom64k::bget(UWORD addr)
        !            53: {
        !            54:   return wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8);
        !            55: }
        !            56: 
        !            57: void custom64k::wput(UWORD addr,UWORD value)
        !            58: {
        !            59:   void (*f)(UWORD) = cchiptable[(addr >> 1) & 0xFF].put;
        !            60:   if (f != 0) (*f)(value);
        !            61:   else {
        !            62:     cout << "Custom write " << hex << value << " at " << addr << "\n";
        !            63:   }
        !            64: }
        !            65: 
        !            66: void custom64k::bput(UWORD addr,UBYTE value)
        !            67: {
        !            68:   wput(addr & 0xfffe,value << (addr & 1 ? 0 : 8)); // ??
        !            69: }
        !            70: 
        !            71: static void setclr(UWORD &p, UWORD val)
        !            72: {
        !            73: //  cout << "setclr, new val ";
        !            74:   if (val & 0x8000) {
        !            75:     p |= val & 0x7FFF;
        !            76:   } else {
        !            77:     p &= ~val;
        !            78:   }
        !            79:  // cout << hex << p << "\n";
        !            80: }
        !            81: 
        !            82:  /* 
        !            83:   * hardware register values that are visible/can be written to by someone
        !            84:   */
        !            85: 
        !            86: static UWORD dmacon,intena,intreq,adkcon;
        !            87: static UWORD vpos, hpos, lof;
        !            88: 
        !            89: static ULONG cop1lc,cop2lc,copcon;
        !            90: 
        !            91: static ULONG bpl1pt,bpl2pt,bpl3pt,bpl4pt,bpl5pt,bpl6pt;
        !            92: static UWORD bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat;
        !            93: static UWORD bplcon0,bplcon1,bplcon2,bplcon3;
        !            94: static UWORD diwstrt,diwstop,ddfstrt,ddfstop;
        !            95: static WORD  bpl1mod,bpl2mod;
        !            96: 
        !            97: static UWORD bltadat,bltbdat,bltcdat,bltddat,bltafwm,bltalwm,bltsize;
        !            98: static WORD  bltamod,bltbmod,bltcmod,bltdmod;
        !            99: static UWORD bltcon0,bltcon1;
        !           100: static ULONG bltapt,bltbpt,bltcpt,bltdpt,bltcnxlpt,bltdnxlpt;
        !           101: 
        !           102: static ULONG dskpt;
        !           103: static UWORD dsklen,dsksync;
        !           104: 
        !           105:  /*
        !           106:   * "hidden" hardware registers
        !           107:   */
        !           108: 
        !           109: static ULONG coplc;
        !           110: static UWORD copi1,copi2;
        !           111: 
        !           112: static enum {
        !           113:   COP_stop, COP_read, COP_wait, COP_move, COP_skip  
        !           114: } copstate;
        !           115: 
        !           116: static UWORD vblitsize,hblitsize,blitpreva,blitprevb;
        !           117: static UWORD blitlpos,blitashift,blitbshift,blinea,blineb;
        !           118: static bool blitline,blitfc,blitzero,blitfill,blitife,blitdesc,blitsing;
        !           119: static bool blitonedot,blitsign;
        !           120: static long int bltwait;
        !           121: 
        !           122: static enum {
        !           123:   BLT_done, BLT_init, BLT_read, BLT_work, BLT_write, BLT_next,BLT_wait
        !           124: } bltstate;
        !           125: 
        !           126: static UWORD plffirstline,plflastline,plffirstword,plflastword;
        !           127: 
        !           128: static enum {
        !           129:   PF_above, PF_left, PF_within, PF_right, PF_below
        !           130: } pfieldstate;
        !           131: 
        !           132: static UWORD dskmfm,dskbyte,dskdmaen,dsktime;
        !           133: static bool dsksynced;
        !           134: 
        !           135:  /*
        !           136:   * helper functions
        !           137:   */
        !           138: 
        !           139: static void calcdiw()
        !           140: {
        !           141:   plffirstline = diwstrt >> 8;
        !           142:   plflastline = diwstop >> 8;
        !           143:   if ((plflastline & 0x80) == 0) plflastline |= 0x100;
        !           144:   plffirstword = (ddfstrt & 0x1FC) * 4;
        !           145:   plflastword = ((ddfstop & 0x1FC)+8) *4;
        !           146: }
        !           147: 
        !           148:  /* 
        !           149:   * register functions
        !           150:   */
        !           151: 
        !           152: static UWORD DMACONR() 
        !           153: {
        !           154:   return dmacon | (bltstate==BLT_done ? 0 : 0x4000)
        !           155:     | (blitzero ? 0x2000 : 0); 
        !           156: }
        !           157: static UWORD INTENAR() { return intena; }
        !           158: static UWORD INTREQR() { return intreq; }
        !           159: static UWORD ADKCONR() { return adkcon; }
        !           160: static UWORD VPOSR() { return (vpos >> 8) | lof; }
        !           161: static UWORD VHPOSR() { return (vpos << 8) | hpos; } 
        !           162: 
        !           163: static void  DMACON(UWORD v) { setclr(dmacon,v); dmacon &= 0x1FFF; }
        !           164: static void  INTENA(UWORD v) { setclr(intena,v); }
        !           165: static void  INTREQ(UWORD v) { setclr(intreq,v); }
        !           166: static void  ADKCON(UWORD v) { setclr(adkcon,v); }
        !           167: 
        !           168: static void  BPL1PTH(UWORD v) { bpl1pt= (bpl1pt & 0xffff) | ((ULONG)v << 16); }
        !           169: static void  BPL1PTL(UWORD v) { bpl1pt= (bpl1pt & ~0xffff) | v; }
        !           170: static void  BPL2PTH(UWORD v) { bpl2pt= (bpl2pt & 0xffff) | ((ULONG)v << 16); }
        !           171: static void  BPL2PTL(UWORD v) { bpl2pt= (bpl2pt & ~0xffff) | v; }
        !           172: static void  BPL3PTH(UWORD v) { bpl3pt= (bpl3pt & 0xffff) | ((ULONG)v << 16); }
        !           173: static void  BPL3PTL(UWORD v) { bpl3pt= (bpl3pt & ~0xffff) | v; }
        !           174: static void  BPL4PTH(UWORD v) { bpl4pt= (bpl4pt & 0xffff) | ((ULONG)v << 16); }
        !           175: static void  BPL4PTL(UWORD v) { bpl4pt= (bpl4pt & ~0xffff) | v; }
        !           176: static void  BPL5PTH(UWORD v) { bpl5pt= (bpl5pt & 0xffff) | ((ULONG)v << 16); }
        !           177: static void  BPL5PTL(UWORD v) { bpl5pt= (bpl5pt & ~0xffff) | v; }
        !           178: static void  BPL6PTH(UWORD v) { bpl6pt= (bpl6pt & 0xffff) | ((ULONG)v << 16); }
        !           179: static void  BPL6PTL(UWORD v) { bpl6pt= (bpl6pt & ~0xffff) | v; }
        !           180: 
        !           181: static void  BPLCON0(UWORD v) { bplcon0 = v; }
        !           182: static void  BPLCON1(UWORD v) { bplcon1 = v; }
        !           183: static void  BPLCON2(UWORD v) { bplcon2 = v; }
        !           184: static void  BPLCON3(UWORD v) { bplcon3 = v; }
        !           185: 
        !           186: static void  BPL1MOD(UWORD v) { bpl1mod = v; }
        !           187: static void  BPL2MOD(UWORD v) { bpl2mod = v; }
        !           188: 
        !           189: static void  BPL1DAT(UWORD v) { bpl1dat = v; }
        !           190: static void  BPL2DAT(UWORD v) { bpl2dat = v; }
        !           191: static void  BPL3DAT(UWORD v) { bpl3dat = v; }
        !           192: static void  BPL4DAT(UWORD v) { bpl4dat = v; }
        !           193: static void  BPL5DAT(UWORD v) { bpl5dat = v; }
        !           194: static void  BPL6DAT(UWORD v) { bpl6dat = v; }
        !           195: 
        !           196: static void  DIWSTRT(UWORD v) { diwstrt = v; calcdiw(); }
        !           197: static void  DIWSTOP(UWORD v) { diwstop = v; calcdiw(); }
        !           198: static void  DDFSTRT(UWORD v) { ddfstrt = v; calcdiw(); }
        !           199: static void  DDFSTOP(UWORD v) { ddfstop = v; calcdiw(); }
        !           200: 
        !           201: static void  COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); }
        !           202: static void  COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; }
        !           203: static void  COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); }
        !           204: static void  COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; }
        !           205: 
        !           206: static UWORD COPJMPR1() { coplc = cop1lc; copstate = COP_read; cout << "CJMP1\n"; return 0; }
        !           207: static UWORD COPJMPR2() { coplc = cop2lc; copstate = COP_read; cout << "CJMP2\n"; return 0; }
        !           208: static void  COPJMP1(UWORD) { coplc = cop1lc; copstate = COP_read; cout << "CJMP1\n"; }
        !           209: static void  COPJMP2(UWORD) { coplc = cop2lc; copstate = COP_read; cout << "CJMP2\n"; }
        !           210: 
        !           211: static void  BLTADAT(UWORD v) { bltadat = v; }
        !           212: static void  BLTBDAT(UWORD v) { bltbdat = v; }
        !           213: static void  BLTCDAT(UWORD v) { bltcdat = v; }
        !           214: 
        !           215: static void  BLTAMOD(UWORD v) { bltamod = v; }
        !           216: static void  BLTBMOD(UWORD v) { bltbmod = v; }
        !           217: static void  BLTCMOD(UWORD v) { bltcmod = v; }
        !           218: static void  BLTDMOD(UWORD v) { bltdmod = v; }
        !           219: 
        !           220: static void  BLTCON0(UWORD v) { bltcon0 = v; }
        !           221: static void  BLTCON1(UWORD v) { bltcon1 = v; }
        !           222: 
        !           223: static void  BLTAFWM(UWORD v) { bltafwm = v; }
        !           224: static void  BLTALWM(UWORD v) { bltalwm = v; }
        !           225: 
        !           226: static void  BLTAPTH(UWORD v) { bltapt= (bltapt & 0xffff) | ((ULONG)v << 16); }
        !           227: static void  BLTAPTL(UWORD v) { bltapt= (bltapt & ~0xffff) | (v); }
        !           228: static void  BLTBPTH(UWORD v) { bltbpt= (bltbpt & 0xffff) | ((ULONG)v << 16); }
        !           229: static void  BLTBPTL(UWORD v) { bltbpt= (bltbpt & ~0xffff) | (v); }
        !           230: static void  BLTCPTH(UWORD v) { bltcpt= (bltcpt & 0xffff) | ((ULONG)v << 16); }
        !           231: static void  BLTCPTL(UWORD v) { bltcpt= (bltcpt & ~0xffff) | (v); }
        !           232: static void  BLTDPTH(UWORD v) { bltdpt= (bltdpt & 0xffff) | ((ULONG)v << 16); }
        !           233: static void  BLTDPTL(UWORD v) { bltdpt= (bltdpt & ~0xffff) | (v); }
        !           234: static void  BLTSIZE(UWORD v) { bltsize = v; bltstate = BLT_init; }
        !           235: 
        !           236: static void  DSKSYNC(UWORD v) { dsksync = v; }
        !           237: static void  DSKDAT(UWORD v) { dskmfm = v; }
        !           238: static void  DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); }
        !           239: static void  DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); }
        !           240: 
        !           241: static void  DSKLEN(UWORD v) 
        !           242: {
        !           243:   if (v & 0x8000) { dskdmaen++; } else { dskdmaen = 0; }
        !           244:   dsktime = dskdelay; dsksynced = false;
        !           245:   dsklen = v;
        !           246: }
        !           247: 
        !           248: static UWORD DSKBYTR() 
        !           249: {
        !           250:   UWORD v = dsklen >> 1 & 0x6000;
        !           251:   v |= dskbyte;
        !           252:   dskbyte &= ~0x8000;
        !           253:   if (dsksync == dskmfm) v |= 0x1000;
        !           254:   return v;
        !           255: }
        !           256: 
        !           257: static UWORD DSKDATR() { return dskmfm; }
        !           258: 
        !           259: custom64k::custom_func custom64k::functable[] = {
        !           260:   { 0x002,  { &DMACONR, 0 }},
        !           261:   { 0x096,  { 0, DMACON  }},
        !           262:   { 0x01C,  { &INTENAR, 0 }},
        !           263:   { 0x09A,  { 0, INTENA  }},
        !           264:   { 0x01E,  { &INTREQR, 0 }},
        !           265:   { 0x09C,  { 0, INTREQ  }},
        !           266:   { 0x010,  { &ADKCONR, 0 }},
        !           267:   { 0x09E,  { 0, ADKCON  }},
        !           268: 
        !           269:   { 0x006,  { &VHPOSR, 0 }},
        !           270:   { 0x004,  { &VPOSR, 0 }},
        !           271: 
        !           272:   { 0x080,  { 0, &COP1LCH }},
        !           273:   { 0x082,  { 0, &COP1LCL }},
        !           274:   { 0x084,  { 0, &COP2LCH }},
        !           275:   { 0x086,  { 0, &COP2LCL }},
        !           276: 
        !           277:   { 0x088,  { &COPJMPR1, &COPJMP1 }},
        !           278:   { 0x08A,  { &COPJMPR2, &COPJMP2 }},
        !           279: 
        !           280:   { 0x08E,  { 0, &DIWSTRT }},
        !           281:   { 0x090,  { 0, &DIWSTOP }},
        !           282:   { 0x092,  { 0, &DDFSTRT }},
        !           283:   { 0x094,  { 0, &DDFSTOP }},
        !           284: 
        !           285:   { 0x0E0,  { 0, &BPL1PTH }},
        !           286:   { 0x0E2,  { 0, &BPL1PTL }},
        !           287:   { 0x0E4,  { 0, &BPL2PTH }},
        !           288:   { 0x0E6,  { 0, &BPL2PTL }},
        !           289:   { 0x0E8,  { 0, &BPL3PTH }},
        !           290:   { 0x0EA,  { 0, &BPL3PTL }},
        !           291:   { 0x0EC,  { 0, &BPL4PTH }},
        !           292:   { 0x0EE,  { 0, &BPL4PTL }},
        !           293:   { 0x0F0,  { 0, &BPL5PTH }},
        !           294:   { 0x0F2,  { 0, &BPL5PTL }},
        !           295:   { 0x0F4,  { 0, &BPL6PTH }},
        !           296:   { 0x0F6,  { 0, &BPL6PTL }},
        !           297: 
        !           298:   { 0x100,  { 0, &BPLCON0 }},
        !           299:   { 0x102,  { 0, &BPLCON1 }},
        !           300:   { 0x104,  { 0, &BPLCON2 }},
        !           301:   { 0x106,  { 0, &BPLCON3 }},
        !           302: 
        !           303:   { 0x108,  { 0, &BPL1MOD }},
        !           304:   { 0x10A,  { 0, &BPL2MOD }},
        !           305: 
        !           306:   { 0x110,  { 0, &BPL1DAT }},
        !           307:   { 0x112,  { 0, &BPL2DAT }},
        !           308:   { 0x114,  { 0, &BPL3DAT }},
        !           309:   { 0x116,  { 0, &BPL4DAT }},
        !           310:   { 0x118,  { 0, &BPL5DAT }},
        !           311:   { 0x11A,  { 0, &BPL6DAT }},
        !           312: 
        !           313:   { 0x040,  { 0, &BLTCON0 }},
        !           314:   { 0x042,  { 0, &BLTCON1 }},
        !           315: 
        !           316:   { 0x044,  { 0, &BLTAFWM }},
        !           317:   { 0x046,  { 0, &BLTALWM }},
        !           318: 
        !           319:   { 0x064,  { 0, &BLTAMOD }},
        !           320:   { 0x062,  { 0, &BLTBMOD }},
        !           321:   { 0x060,  { 0, &BLTCMOD }},
        !           322:   { 0x066,  { 0, &BLTDMOD }},
        !           323: 
        !           324:   { 0x050,  { 0, &BLTAPTH }},
        !           325:   { 0x052,  { 0, &BLTAPTL }},
        !           326:   { 0x04C,  { 0, &BLTBPTH }},
        !           327:   { 0x04E,  { 0, &BLTBPTL }},
        !           328:   { 0x048,  { 0, &BLTCPTH }},
        !           329:   { 0x04A,  { 0, &BLTCPTL }},
        !           330:   { 0x054,  { 0, &BLTDPTH }},
        !           331:   { 0x056,  { 0, &BLTDPTL }},
        !           332: 
        !           333:   { 0x070,  { 0, &BLTCDAT }},
        !           334:   { 0x072,  { 0, &BLTBDAT }},
        !           335:   { 0x074,  { 0, &BLTADAT }},
        !           336: 
        !           337:   { 0x058,  { 0, &BLTSIZE }},
        !           338: 
        !           339:   { 0x008,  { &DSKDATR, 0 }},
        !           340:   { 0x01A,  { &DSKBYTR, 0 }},
        !           341:   { 0x026,  { 0, &DSKDAT }},
        !           342:   { 0x024,  { 0, &DSKLEN }},
        !           343:   { 0x020,  { 0, &DSKPTH }},
        !           344:   { 0x022,  { 0, &DSKPTL }},
        !           345:   { 0x07E,  { 0, &DSKSYNC }},
        !           346: 
        !           347:   { 0xFFFF, { 0, 0 }}
        !           348: };
        !           349: 
        !           350: custom64k::cchipaddr *custom64k::cchiptable = 0;
        !           351: 
        !           352: custom64k::custom64k()
        !           353: {
        !           354:   if (!cchiptable){
        !           355:     // CUSTOM CHIP INITIALIZATION
        !           356:     // build function pointer table
        !           357:     cchiptable = new cchipaddr[256];
        !           358:     for (int i=0;i<256;i++) {
        !           359:       cchiptable[i].get = 0;
        !           360:       cchiptable[i].put = 0;
        !           361:     }
        !           362:     for(custom_func *f = functable; f->addr != 0xffff; f++){
        !           363:       cchiptable[f->addr >> 1] = f->fptrs;
        !           364:     }
        !           365:     customreset();
        !           366:   }
        !           367: }
        !           368: 
        !           369: void customreset()
        !           370: {
        !           371:   // reset some values
        !           372:   vpos = hpos = lof = 0;
        !           373:   dmacon = intena = 0;
        !           374:   bltstate = BLT_done;
        !           375:   copstate = COP_stop;
        !           376:   copcon = 0;
        !           377:   dskdmaen = 0;
        !           378: }
        !           379: 
        !           380: static bool dmaen(UWORD dmamask)
        !           381: {
        !           382:   return (dmamask & dmacon) && (dmacon & 0x200);
        !           383: }
        !           384: 
        !           385: static bool copcomp()
        !           386: {
        !           387:   UWORD vp = vpos & ((copi2 >> 8) & 0x7F);
        !           388:   UWORD hp = hpos & (copi2 & 0xFE);
        !           389:   UWORD vcmp = copi1 >> 8;
        !           390:   UWORD hcmp = copi1 & 0xFE;
        !           391:   return (vp >= vcmp) && (hp >= hcmp) && ((copi2 & 0x8000) /*|| bfd FIXME*/);  
        !           392: }
        !           393: 
        !           394: static void do_copper()
        !           395: {
        !           396:   switch(copstate){
        !           397:   case COP_read:
        !           398:     if (dmaen(0x80)){
        !           399:  //     cout << "copper read at " << hex << coplc << "\n";
        !           400:       copi1 = mem.get_word(coplc); 
        !           401:       copi2 = mem.get_word(coplc+2);
        !           402:       coplc += 4;
        !           403:       copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move;
        !           404:     } 
        !           405:     break;
        !           406:   case COP_move:
        !           407:  //   cout << "copper move " << hex << copi1 << " " << copi2 << "\n";
        !           408:     if (copi1 >= (copcon & 2 ? 0x40 : 0x80))
        !           409:       mem.put_word(0xDFF000+copi1,copi2);
        !           410:     copstate = COP_read; // FIXME: copdang
        !           411:     break;
        !           412:   case COP_skip:
        !           413:     if (copcomp()) coplc += 4;
        !           414:     copstate = COP_read;
        !           415:     break;
        !           416:   case COP_wait:
        !           417:     if (copcomp()) copstate = COP_read;
        !           418:     break;
        !           419:   case COP_stop:
        !           420:     break;
        !           421:   }
        !           422: }
        !           423: 
        !           424: static void blitter_read()
        !           425: {
        !           426:   if (bltcon0 & 0xe00){
        !           427:     if (!dmaen(0x40)) return; // blitter stopped
        !           428:     if (!blitline){
        !           429:       if (bltcon0 & 0x800) bltadat = mem.get_word(bltapt);
        !           430:       if (bltcon0 & 0x400) bltbdat = mem.get_word(bltbpt);
        !           431:     }
        !           432:     if (bltcon0 & 0x200) bltcdat = mem.get_word(bltcpt);
        !           433:   }
        !           434:   bltstate = BLT_work;
        !           435: }
        !           436: 
        !           437: static void blitter_write()
        !           438: {
        !           439:   if (bltddat) blitzero = false;
        !           440:   if (bltcon0 & 0x100){
        !           441:     if (!dmaen(0x40)) return;
        !           442:     mem.put_word(bltdpt,bltddat);
        !           443:   }
        !           444:   bltstate = BLT_next;
        !           445: }
        !           446: 
        !           447: static void blitter_blit()
        !           448: {
        !           449:   UWORD blitahold,blitbhold,blitchold;
        !           450: 
        !           451:   if (blitdesc) { // aaarggh!
        !           452:     UWORD bltamask = 0xffff;
        !           453: 
        !           454:     if (!blitlpos) { bltamask &= bltafwm; }
        !           455:     if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
        !           456: 
        !           457:     // FIXME? The following two lines are probably not 100% exact
        !           458:     blitahold = ((ULONG)((bltadat & bltamask) << 16) | blitpreva) 
        !           459:       >> (16-blitashift);
        !           460:     blitbhold = ((ULONG)(bltbdat << 16) | blitprevb) >> (16-blitbshift);
        !           461:     blitchold = bltcdat;
        !           462:   } else {
        !           463:     UWORD bltamask = 0xffff;
        !           464: 
        !           465:     if (!blitlpos) { bltamask &= bltafwm; }
        !           466:     if (blitlpos == (hblitsize - 1)) { bltamask &= bltalwm; }
        !           467:     // FIXME? The following two lines are probably not 100% exact
        !           468:     blitahold = ((ULONG)(blitpreva << 16) | (bltadat&bltamask)) >> blitashift;
        !           469:     blitbhold = ((ULONG)(blitprevb << 16) | bltbdat) >> blitbshift;
        !           470:     blitchold = bltcdat;
        !           471:   }
        !           472:   bltddat = 0;
        !           473:   for(int i=0; i<16; i++) {
        !           474:     // oh dear, this is SLOW!
        !           475:     int minterm = ((blitahold >> 13) & 4) | ((blitbhold >> 14) & 2)
        !           476:       | ((blitchold >> 15) & 1);
        !           477:     blitahold <<= 1; blitbhold <<= 1; blitchold <<= 1;
        !           478:     if (bltcon0 & (1 << minterm)) 
        !           479:       bltddat |= (1 << (15-i));
        !           480:   }
        !           481:   if (blitfill){
        !           482:     UWORD fillmask = 1;
        !           483:     for (;fillmask;fillmask <<= 1){
        !           484:       UWORD tmp = bltddat;
        !           485:       if (blitfc) {
        !           486:        if (blitife) bltddat |= fillmask; else bltddat ^= fillmask;
        !           487:       }
        !           488:       if (tmp & fillmask) blitfc = !blitfc;
        !           489:     } 
        !           490:   }
        !           491:   bltstate = BLT_write;
        !           492:   blitpreva = bltadat; blitprevb = bltbdat;
        !           493: }
        !           494: 
        !           495: static void blitter_nxblit()
        !           496: {
        !           497:   bltstate = BLT_read;
        !           498:   if (blitdesc){
        !           499:     if (++blitlpos == hblitsize) {
        !           500:       if (--vblitsize == 0) {
        !           501:        bltstate = BLT_done; mem.put_word(0xDFF09C,0x8040);
        !           502:       }
        !           503:       blitlpos = 0;
        !           504:       if (bltcon0 & 0x800) bltapt -= 2+bltamod; 
        !           505:       if (bltcon0 & 0x400) bltbpt -= 2+bltbmod; 
        !           506:       if (bltcon0 & 0x200) bltcpt -= 2+bltcmod; 
        !           507:       if (bltcon0 & 0x100) bltdpt -= 2+bltdmod;
        !           508:     } else {
        !           509:       if (bltcon0 & 0x800) bltapt -= 2; 
        !           510:       if (bltcon0 & 0x400) bltbpt -= 2; 
        !           511:       if (bltcon0 & 0x200) bltcpt -= 2; 
        !           512:       if (bltcon0 & 0x100) bltdpt -= 2;
        !           513: 
        !           514:     }
        !           515:   } else {
        !           516:     if (++blitlpos == hblitsize) {
        !           517:       if (--vblitsize == 0) { 
        !           518:        bltstate = BLT_done; mem.put_word(0xDFF09C,0x8040);
        !           519:       }
        !           520:       blitlpos = 0;
        !           521:       if (bltcon0 & 0x800) bltapt += 2+bltamod; 
        !           522:       if (bltcon0 & 0x400) bltbpt += 2+bltbmod; 
        !           523:       if (bltcon0 & 0x200) bltcpt += 2+bltcmod; 
        !           524:       if (bltcon0 & 0x100) bltdpt += 2+bltdmod;
        !           525:     } else {
        !           526:       if (bltcon0 & 0x800) bltapt += 2; 
        !           527:       if (bltcon0 & 0x400) bltbpt += 2; 
        !           528:       if (bltcon0 & 0x200) bltcpt += 2; 
        !           529:       if (bltcon0 & 0x100) bltdpt += 2;
        !           530:     }
        !           531:   }
        !           532: }
        !           533: 
        !           534: static void blitter_line_incx(int =1)
        !           535: {
        !           536:   blinea >>= 1;
        !           537:   if (!blinea) {
        !           538:     blinea = 0x8000;
        !           539:     bltcnxlpt += 2;
        !           540:     bltdnxlpt += 2;
        !           541:   }
        !           542: }
        !           543: 
        !           544: static void blitter_line_decx(int shm=1)
        !           545: {
        !           546:   if (shm) blineb = (blineb << 2) | (blineb >> 14);
        !           547:   blinea <<= 1;
        !           548:   if (!blinea) {
        !           549:     blinea = 1;
        !           550:     bltcnxlpt -= 2;
        !           551:     bltdnxlpt -= 2;
        !           552:   }
        !           553: }
        !           554: 
        !           555: static void blitter_line_decy(int shm=1)
        !           556: {
        !           557:   if (shm) blineb = (blineb >> 1) | (blineb << 15);
        !           558:   bltcnxlpt -= bltcmod;
        !           559:   bltdnxlpt -= bltcmod; // ??? ??? ??? am I wrong or doesn't KS1.3 set bltdmod?
        !           560:   blitonedot = 0;
        !           561: }
        !           562: 
        !           563: static void blitter_line_incy(int shm=1)
        !           564: {
        !           565:   if (shm) blineb = (blineb >> 1) | (blineb << 15);
        !           566:   bltcnxlpt += bltcmod;
        !           567:   bltdnxlpt += bltcmod; // ??? ??? ???
        !           568:   blitonedot = 0;
        !           569: }
        !           570: 
        !           571: static void blitter_line()
        !           572: {
        !           573:   bltddat = 0;
        !           574:   UWORD blitahold = blinea, blitbhold = blineb, blitchold = bltcdat;
        !           575:   if (blitsing && blitonedot) blitahold = 0;
        !           576:   blitonedot = 1;
        !           577:   for(int i=0; i<16; i++) {
        !           578:     int minterm = ((blitahold >> 13) & 4) | ((blitbhold >> 14) & 2)
        !           579:       | ((blitchold >> 15) & 1);
        !           580:     blitahold <<= 1; blitbhold <<= 1; blitchold <<= 1;
        !           581:     if (bltcon0 & (1 << minterm)) bltddat |= (1 << (15-i));
        !           582:   }
        !           583:   if (!blitsign){
        !           584:     bltapt += (WORD)bltamod;
        !           585:     if (bltcon1 & 0x10){
        !           586:       if (bltcon1 & 0x8) blitter_line_decy(0); else blitter_line_incy(0);
        !           587:     } else {
        !           588:       if (bltcon1 & 0x8) blitter_line_decx(0); else blitter_line_incx(0);
        !           589:     }
        !           590:   } else {
        !           591:     bltapt += (WORD)bltbmod;
        !           592:   }
        !           593:   if (bltcon1 & 0x10){
        !           594:     if (bltcon1 & 0x4) blitter_line_decx(); else blitter_line_incx();
        !           595:   } else {
        !           596:     if (bltcon1 & 0x4) blitter_line_decy(); else blitter_line_incy();
        !           597:   }
        !           598:   blitsign = 0 > (WORD)bltapt;
        !           599:   bltstate = BLT_write;
        !           600: }
        !           601: 
        !           602: static void blitter_nxline()
        !           603: {
        !           604:   if (--vblitsize == 0) {
        !           605:     bltstate = BLT_wait; bltwait = /*0xE2*31*/2; mem.put_word(0xDFF09C,0x8040);
        !           606:   } else {
        !           607:     bltstate = BLT_read;
        !           608:     bltcpt = bltcnxlpt;
        !           609:     bltdpt = bltdnxlpt;
        !           610:   }
        !           611: }
        !           612: 
        !           613: static void do_blitter()
        !           614: {
        !           615:   switch(bltstate) {
        !           616:   case BLT_init:
        !           617:     cout << "Blit started!";
        !           618:     vblitsize = bltsize >> 6;
        !           619:     hblitsize = bltsize & 0x3F;
        !           620:     if (!vblitsize) vblitsize = 1024;
        !           621:     if (!hblitsize) hblitsize = 64;
        !           622:     blitlpos = 0;
        !           623:     blitzero = true; blitpreva = blitprevb = 0;
        !           624:     blitline = bltcon1 & 1;
        !           625:     blitashift = bltcon0 >> 12; blitbshift = bltcon1 >> 12;
        !           626:     
        !           627:     if (blitline) {
        !           628:       cout << " line\n";
        !           629:       bltcnxlpt = bltcpt;
        !           630:       bltdnxlpt = bltdpt;
        !           631:       blitsing = bltcon1 & 0x2;
        !           632:       blinea = bltadat >> blitashift;
        !           633:       blineb = (bltbdat >> blitbshift) | (bltbdat << (16-blitbshift));
        !           634:       blitsign = bltcon1 & 0x40; 
        !           635:       blitonedot = false;
        !           636:       bltamod &= 0xfffe; bltbmod &= 0xfffe; bltapt &= 0xfffe;
        !           637:     } else {
        !           638:       blitfc = bltcon1 & 0x4;
        !           639:       blitife = bltcon1 & 0x8;
        !           640:       blitfill = bltcon1 & 0x18;
        !           641:       if (blitfill) cout << " fill";
        !           642:       if ((bltcon1 & 0x18) == 0x18) cout << "STRANGE FILL MODE ALERT!!\n";
        !           643:       blitdesc = bltcon1 & 0x2;
        !           644:       if(blitdesc) cout << " desc";
        !           645:       cout << "\n";
        !           646:     }
        !           647:     bltstate = BLT_read;
        !           648:     break;
        !           649:   case BLT_read:
        !           650:     blitter_read();
        !           651:     break;
        !           652:   case BLT_write:
        !           653:     blitter_write();
        !           654:     break;
        !           655:   case BLT_work:
        !           656:     if (blitline) blitter_line(); else blitter_blit();
        !           657:     break;
        !           658:   case BLT_next:
        !           659:     if (blitline) blitter_nxline(); else blitter_nxblit();
        !           660:     break;
        !           661:   case BLT_wait:
        !           662:     if (!--bltwait) bltstate = BLT_done;
        !           663:     break;
        !           664:   case BLT_done:
        !           665:     break;
        !           666:   }
        !           667: }
        !           668: 
        !           669:   // note: fall-throughs in all playfield functions
        !           670: 
        !           671: static void pfield_fetchdata()
        !           672: {
        !           673:   if (/*dmaen(0x100)*/ 1) {
        !           674:     switch(bplcon0 & 0x7000){
        !           675:     case 0x6000:
        !           676:       bpl6dat = mem.get_word(bpl6pt); bpl6pt += 2;
        !           677:     case 0x5000:
        !           678:       bpl5dat = mem.get_word(bpl5pt); bpl5pt += 2;
        !           679:     case 0x4000:
        !           680:       bpl4dat = mem.get_word(bpl4pt); bpl4pt += 2;
        !           681:     case 0x3000:
        !           682:       bpl3dat = mem.get_word(bpl3pt); bpl3pt += 2;
        !           683:     case 0x2000:
        !           684:       bpl2dat = mem.get_word(bpl2pt); bpl2pt += 2;
        !           685:     case 0x1000:
        !           686:       bpl1dat = mem.get_word(bpl1pt); bpl1pt += 2;
        !           687:     }
        !           688:   }
        !           689: }
        !           690: 
        !           691: static void pfield_hsync()
        !           692: {
        !           693:   if (/*dmaen(0x100)*/ 1) {
        !           694:     switch(bplcon0 & 0x7000){
        !           695:     case 0x6000:
        !           696:       bpl6pt += bpl2mod;
        !           697:     case 0x5000:
        !           698:       bpl5pt += bpl1mod;
        !           699:     case 0x4000:
        !           700:       bpl4pt += bpl2mod;
        !           701:     case 0x3000:
        !           702:       bpl3pt += bpl1mod;
        !           703:     case 0x2000:
        !           704:       bpl2pt += bpl2mod;
        !           705:     case 0x1000:
        !           706:       bpl1pt += bpl1mod;
        !           707:     }
        !           708:   }
        !           709: }
        !           710: 
        !           711: static UWORD pfield_nextpixel()
        !           712: {
        !           713:   UWORD tmp = 0;
        !           714:   switch(bplcon0 & 0x7000){
        !           715:   case 0x6000: 
        !           716:     tmp = (bpl6dat >> 15); bpl6dat <<= 1;
        !           717:   case 0x5000: 
        !           718:     tmp = (tmp << 1) | (bpl5dat >> 15); bpl5dat <<= 1;
        !           719:   case 0x4000: 
        !           720:     tmp = (tmp << 1) | (bpl4dat >> 15); bpl4dat <<= 1;
        !           721:   case 0x3000: 
        !           722:     tmp = (tmp << 1) | (bpl3dat >> 15); bpl3dat <<= 1;
        !           723:   case 0x2000: 
        !           724:     tmp = (tmp << 1) | (bpl2dat >> 15); bpl2dat <<= 1;
        !           725:   case 0x1000: 
        !           726:     tmp = (tmp << 1) | (bpl1dat >> 15); bpl1dat <<= 1;
        !           727:   } 
        !           728:   return tmp;
        !           729: }
        !           730: 
        !           731: static void do_playfield()
        !           732: {
        !           733:   int xpos = hpos * 4;
        !           734:   if (vpos >= plffirstline && vpos < plflastline){
        !           735:     if (xpos >= plffirstword && xpos < plflastword){
        !           736:       if (bplcon0 & 0x8000){
        !           737:        if ((xpos & 0xF) == 0){
        !           738:          pfield_fetchdata();
        !           739:          for(int i=0;i<16;i++){
        !           740:            UWORD pixel = pfield_nextpixel() & 3;
        !           741:            int col;
        !           742:            if (pixel == 3) col = 1;
        !           743:            else if (pixel == 0) col = 0;
        !           744:            else col = (pixel & 1) == ((xpos ^ vpos) & 1);
        !           745:            DrawPixel(xpos+i,vpos,col);
        !           746:          }
        !           747:        }
        !           748:       } else {
        !           749:        if ((xpos & 0x1F) == 0){
        !           750:          pfield_fetchdata();
        !           751:          for(int i=0;i<16;i++){
        !           752:            UWORD pixel = pfield_nextpixel() & 3;
        !           753:            int col;
        !           754:            if (pixel == 3) col = 1;
        !           755:            else if (pixel == 0) col = 0;
        !           756:            else col = (pixel & 1) == ((xpos ^ vpos) & 1);
        !           757:            DrawPixel(xpos+i*2,vpos,col);
        !           758:            DrawPixel(xpos+i*2+1,vpos,col);
        !           759:          }
        !           760:        }
        !           761:       }
        !           762:     }
        !           763:   }
        !           764: }
        !           765: 
        !           766: static void do_disk()
        !           767: {
        !           768:   if (dskdmaen > 1 && dmaen(0x10)){
        !           769:     if (--dsktime == 0) {
        !           770:       dsktime = dskdelay;
        !           771:       if (dsklen & 0x4000){
        !           772:        // write
        !           773:       } else {
        !           774:        DISK_GetData(dskmfm,dskbyte);
        !           775:        dskbyte |= 0x8000;
        !           776:        if (dskmfm == dsksync) {
        !           777:          mem.put_word(0xDFF09C,0x9000);
        !           778:          dsksynced = true;
        !           779:        }
        !           780:        if (dsksynced || !(adkcon & 0x400)){
        !           781:          mem.put_word(dskpt,dskmfm); dskpt+=2;
        !           782:        }
        !           783:       }
        !           784:     }
        !           785:   }
        !           786: }
        !           787: 
        !           788: static void do_vsync()
        !           789: {
        !           790: //  intreq |= 1 << i_vertb;
        !           791:   mem.put_word(0xDFF09C,0x8020);
        !           792:   lof ^= 1;
        !           793: //  if (copstate != COP_stop)
        !           794:     mem.put_word(0xDFF088,0); // restart copper
        !           795:   CIA_vsync();
        !           796: }
        !           797: 
        !           798: void clockcycle()
        !           799: {
        !           800:   if (++hpos == maxhpos){
        !           801:     hpos = 0; CIA_hsync();
        !           802:     pfield_hsync();
        !           803:     if (++vpos == maxvpos) {
        !           804:       vpos = 0;
        !           805:       do_vsync();
        !           806:     }
        !           807:   }
        !           808:   do_copper();
        !           809:   do_playfield();
        !           810:   do_blitter();
        !           811:   do_disk();
        !           812:   CIA_cycle();
        !           813: }
        !           814: 
        !           815: void dumpcustom()
        !           816: {
        !           817:   cout << "DMACON: " << DMACONR() << " INTENA: " << intena << " INTREQ: "
        !           818:     << intreq << " VPOS: " << vpos << " HPOS: " << hpos << "\n";
        !           819: }
        !           820: 
        !           821: int intlev()
        !           822: {
        !           823:   UWORD imask = intreq & intena;
        !           824:   if (imask && (intena & 0x4000)){
        !           825:  //   cout << hex << "intreq " << intreq << " intena " << intena <<"\n";
        !           826:     if (imask & 0x2000) return 6;
        !           827:     if (imask & 0x1800) return 5;
        !           828:     if (imask & 0x0780) return 4;
        !           829:     if (imask & 0x0070) return 3;
        !           830:     if (imask & 0x0008) return 2;
        !           831:     if (imask & 0x0007) return 1;
        !           832:   }
        !           833:   return -1;
        !           834: }

unix.superglobalmegacorp.com

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