|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.