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