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