|
|
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 "sysconfig.h" ! 10: #include "sysdeps.h" ! 11: ! 12: #include <ctype.h> ! 13: #include <assert.h> ! 14: ! 15: #include "config.h" ! 16: #include "options.h" ! 17: #include "events.h" ! 18: #include "memory.h" ! 19: #include "custom.h" ! 20: #include "newcpu.h" ! 21: #include "cia.h" ! 22: #include "disk.h" ! 23: #include "blitter.h" ! 24: #include "xwin.h" ! 25: #include "os.h" ! 26: #include "keybuf.h" ! 27: #include "serial.h" ! 28: ! 29: /* #define EMULATE_AGA */ ! 30: ! 31: #ifndef EMULATE_AGA ! 32: #define AGA_CHIPSET 0 ! 33: #else ! 34: #define AGA_CHIPSET 1 ! 35: #endif ! 36: ! 37: #define SMART_UPDATE 1 ! 38: ! 39: #define MAX_PLANES 8 ! 40: ! 41: #define PIXEL_XPOS(HPOS) (((HPOS)*2 - 0x30)*(use_lores ? 1 : 2)) ! 42: ! 43: /* These are default values for mouse calibration. ! 44: * The first two are default values for mstepx and mstepy. ! 45: * The second line set the orizontal and vertical offset for amiga and X ! 46: * pointer matching ! 47: */ ! 48: ! 49: #define defstepx (1<<16) ! 50: #define defstepy (1<<16) ! 51: #define defxoffs 0 ! 52: #define defyoffs 0 ! 53: ! 54: /* Values below define mouse auto calibration process. ! 55: * They are not critical, change them if you want. ! 56: * The most important is calweight, which sets mouse adjustement rate */ ! 57: ! 58: static const int docal = 60, xcaloff = 40, ycaloff = 20; ! 59: static const int calweight = 3; ! 60: static int lastsampledmx, lastsampledmy; ! 61: ! 62: /* ! 63: * Events ! 64: */ ! 65: ! 66: unsigned long int cycles, nextevent; ! 67: int vpos; ! 68: UWORD lof; ! 69: ! 70: struct ev eventtab[ev_max]; ! 71: ! 72: int copper_active; ! 73: ! 74: static const int dskdelay = 2; /* FIXME: ??? */ ! 75: ! 76: /* ! 77: * hardware register values that are visible/can be written to by someone ! 78: */ ! 79: ! 80: static int fmode; ! 81: ! 82: static UWORD cregs[256]; ! 83: ! 84: UWORD intena,intreq; ! 85: UWORD dmacon; ! 86: UWORD adkcon; /* used by audio code */ ! 87: ! 88: static ULONG cop1lc,cop2lc,copcon; ! 89: ! 90: /* Kludge. FIXME: How does sprite restart after vsync work? */ ! 91: static int spron[8]; ! 92: static CPTR sprpt[8]; ! 93: ! 94: static ULONG bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat; ! 95: static WORD bpl1mod,bpl2mod; ! 96: ! 97: xcolnr acolors[64]; ! 98: ! 99: UBYTE *r_bplpt[MAX_PLANES]; ! 100: static CPTR bplpt[MAX_PLANES]; ! 101: ! 102: /*static int blitcount[256]; blitter debug */ ! 103: ! 104: struct bplinfo { ! 105: #if AGA_CHIPSET == 0 ! 106: /* X86.S will break if this isn't at the beginning of the structure. */ ! 107: UWORD color_regs[32]; ! 108: #else ! 109: ULONG color_regs[256]; ! 110: #endif ! 111: UWORD bplcon0,bplcon1,bplcon2,bplcon3,bplcon4; ! 112: UWORD diwstrt,diwstop,ddfstrt,ddfstop; ! 113: ! 114: UWORD sprdata[8], sprdatb[8], sprctl[8], sprpos[8]; ! 115: int sprarmed[8]; ! 116: } bpl_info; ! 117: ! 118: struct line_description ! 119: { ! 120: int inborder; ! 121: xcolnr bordercol; ! 122: struct bplinfo bpl_info; ! 123: struct mem_notify_node *mnn; ! 124: CPTR bplpt[MAX_PLANES]; ! 125: int linedata_valid; ! 126: }; ! 127: ! 128: static int frame_redraw_necessary; ! 129: ! 130: /* 50 words give you 800 horizontal pixels. An A500 can't do that, so it ought ! 131: * to be enough. */ ! 132: #define MAX_WORDS_PER_LINE 50 ! 133: static UBYTE line_data[numscrlines * 2][MAX_PLANES][MAX_WORDS_PER_LINE*2]; ! 134: static struct line_description linedescr[numscrlines * 2]; ! 135: ! 136: static ULONG dskpt; ! 137: static UWORD dsklen,dsksync; ! 138: ! 139: static int joy0x, joy1x, joy0y, joy1y; ! 140: int joy0button; ! 141: UWORD joy0dir; ! 142: static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl; ! 143: static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs; ! 144: static int sprvbfl; ! 145: ! 146: static enum { normal_mouse, dont_care_mouse, follow_mouse } mousestate; ! 147: ! 148: /* ! 149: * "hidden" hardware registers ! 150: */ ! 151: ! 152: int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256]; ! 153: int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256]; ! 154: ! 155: int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; ! 156: ! 157: static ULONG coplc; ! 158: static UWORD copi1,copi2; ! 159: ! 160: static enum { ! 161: COP_stop, COP_read, COP_wait, COP_move, COP_skip ! 162: } copstate; ! 163: ! 164: static int dsklength; ! 165: ! 166: int plffirstline,plflastline,plfstrt,plfstop,plflinelen; ! 167: int diwfirstword,diwlastword; ! 168: int plfpri[3]; ! 169: ! 170: int max_diwstop, prev_max_diwstop; ! 171: ! 172: int dskdmaen; /* used in cia.c */ ! 173: ! 174: int bpldelay1, bpldelay2; ! 175: int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires; ! 176: ! 177: static int pfield_fullline,pfield_linedone; ! 178: static int pfield_linedmaon; ! 179: static int pfield_lastpart_hpos,last_sprite; ! 180: static int slowline_nextpos, slowline_linepos, slowline_lasttoscr; ! 181: ! 182: union { ! 183: /* Let's try to align this thing. */ ! 184: double uupzuq; ! 185: long int cruxmedo; ! 186: unsigned char apixels[1000]; ! 187: } pixdata; ! 188: ! 189: char spixels[1000]; /* for sprites */ ! 190: char spixstate[1000]; /* more sprites */ ! 191: ! 192: ULONG ham_linebuf[1000]; ! 193: ULONG aga_linebuf[1000], *aga_lbufptr; ! 194: ! 195: char *xlinebuffer; ! 196: int next_lineno, linetoscreen, line_in_border; ! 197: ! 198: /* ! 199: * Statistics ! 200: */ ! 201: ! 202: static unsigned long int msecs = 0, frametime = 0, timeframes = 0; ! 203: static unsigned long int seconds_base; ! 204: int bogusframe; ! 205: ! 206: /* ! 207: * helper functions ! 208: */ ! 209: ! 210: static void pfield_doline_slow(int); ! 211: static void pfield_doline(void); ! 212: static void do_sprites(int, int); ! 213: ! 214: int inhibit_frame; ! 215: static int framecnt = 0; ! 216: ! 217: static __inline__ void count_frame(void) ! 218: { ! 219: if (inhibit_frame) ! 220: framecnt = 1; ! 221: else { ! 222: framecnt++; ! 223: if (framecnt >= framerate) ! 224: framecnt = 0; ! 225: } ! 226: } ! 227: ! 228: static __inline__ void setclr(UWORD *p, UWORD val) ! 229: { ! 230: if (val & 0x8000) { ! 231: *p |= val & 0x7FFF; ! 232: } else { ! 233: *p &= ~val; ! 234: } ! 235: } ! 236: ! 237: static __inline__ int current_hpos(void) ! 238: { ! 239: return cycles - eventtab[ev_hsync].oldcycles; ! 240: } ! 241: ! 242: static void calcdiw(void) ! 243: { ! 244: if (use_lores) { ! 245: diwfirstword = (bpl_info.diwstrt & 0xFF) - 0x30 - 1; ! 246: diwlastword = (bpl_info.diwstop & 0xFF) + 0x100 - 0x30 - 1; ! 247: } else { ! 248: diwfirstword = (bpl_info.diwstrt & 0xFF) * 2 - 0x60 - 2; ! 249: diwlastword = (bpl_info.diwstop & 0xFF) * 2 + 0x200 - 0x60 - 2; ! 250: } ! 251: if (diwfirstword < 0) diwfirstword = 0; ! 252: if (diwlastword > max_diwstop) max_diwstop = diwlastword; ! 253: ! 254: plffirstline = bpl_info.diwstrt >> 8; ! 255: plflastline = bpl_info.diwstop >> 8; ! 256: #if 0 ! 257: /* This happens far too often. */ ! 258: if (plffirstline < minfirstline) { ! 259: fprintf(stderr, "Warning: Playfield begins before line %d!\n", minfirstline); ! 260: plffirstline = minfirstline; ! 261: } ! 262: #endif ! 263: if ((plflastline & 0x80) == 0) plflastline |= 0x100; ! 264: #if 0 /* Turrican does this */ ! 265: if (plflastline > 313) { ! 266: fprintf(stderr, "Warning: Playfield out of range!\n"); ! 267: plflastline = 313; ! 268: } ! 269: #endif ! 270: plfstrt = bpl_info.ddfstrt; ! 271: plfstop = bpl_info.ddfstop; ! 272: if (plfstrt < 0x18) plfstrt = 0x18; ! 273: if (plfstop > 0xD8) plfstop = 0xD8; ! 274: if (plfstrt > plfstop) plfstrt = plfstop; ! 275: ! 276: /* ! If the masking operation is changed, the pfield_doline code could break ! 277: * on some systems (alignment) */ ! 278: /* This actually seems to be correct now, at least the non-AGA stuff... */ ! 279: plfstrt &= ~3; ! 280: plfstop &= ~3; ! 281: if ((fmode & 3) == 0) ! 282: plflinelen = (plfstop-plfstrt+15) & ~7; ! 283: else if ((fmode & 3) == 3) ! 284: plflinelen = (plfstop-plfstrt+63) & ~31; ! 285: else ! 286: plflinelen = (plfstop-plfstrt+31) & ~15; ! 287: ! 288: } ! 289: ! 290: /* ! 291: * Screen update macros/functions ! 292: */ ! 293: ! 294: static void decode_ham6 (int pix, int stoppos) ! 295: { ! 296: static UWORD lastcolor; ! 297: ULONG *buf = ham_linebuf; ! 298: ! 299: if (!bplham || bplplanecnt != 6) ! 300: return; ! 301: ! 302: if (pix <= diwfirstword) { ! 303: pix = diwfirstword; ! 304: lastcolor = bpl_info.color_regs[0]; ! 305: } ! 306: ! 307: while (pix < diwlastword && pix < stoppos) { ! 308: int pv = pixdata.apixels[pix]; ! 309: switch(pv & 0x30) { ! 310: case 0x00: lastcolor = bpl_info.color_regs[pv]; break; ! 311: case 0x10: lastcolor &= 0xFF0; lastcolor |= (pv & 0xF); break; ! 312: case 0x20: lastcolor &= 0x0FF; lastcolor |= (pv & 0xF) << 8; break; ! 313: case 0x30: lastcolor &= 0xF0F; lastcolor |= (pv & 0xF) << 4; break; ! 314: } ! 315: ! 316: buf[pix++] = lastcolor; ! 317: } ! 318: } ! 319: ! 320: static void decode_ham_aga (int pix, int stoppos) ! 321: { ! 322: static ULONG lastcolor; ! 323: ULONG *buf = ham_linebuf; ! 324: ! 325: if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8)) ! 326: return; ! 327: ! 328: if (pix <= diwfirstword) { ! 329: pix = diwfirstword; ! 330: lastcolor = bpl_info.color_regs[0]; ! 331: } ! 332: ! 333: if (bplplanecnt == 6) { ! 334: /* HAM 6 */ ! 335: while (pix < diwlastword && pix < stoppos) { ! 336: int pv = pixdata.apixels[pix]; ! 337: switch(pv & 0x30) { ! 338: case 0x00: lastcolor = bpl_info.color_regs[pv]; break; ! 339: case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break; ! 340: case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break; ! 341: case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break; ! 342: } ! 343: buf[pix++] = lastcolor; ! 344: } ! 345: } else if (bplplanecnt == 8) { ! 346: /* HAM 8 */ ! 347: while (pix < diwlastword && pix < stoppos) { ! 348: int pv = pixdata.apixels[pix]; ! 349: switch(pv & 0x3) { ! 350: case 0x0: lastcolor = bpl_info.color_regs[pv >> 2]; break; ! 351: case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break; ! 352: case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break; ! 353: case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break; ! 354: } ! 355: buf[pix++] = lastcolor; ! 356: } ! 357: } ! 358: } ! 359: ! 360: #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE) \ ! 361: static void NAME(int pix, int stoppos, int offset) \ ! 362: { \ ! 363: TYPE *buf = (TYPE *)xlinebuffer; \ ! 364: int oldpix = pix; \ ! 365: buf -= pix; \ ! 366: if (DO_DOUBLE) offset /= sizeof(TYPE); \ ! 367: while (pix < diwfirstword && pix < stoppos) { \ ! 368: TYPE d = acolors[0]; \ ! 369: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ ! 370: pix++; \ ! 371: } \ ! 372: if (bplham && bplplanecnt == 6) { \ ! 373: /* HAM 6 */ \ ! 374: while (pix < diwlastword && pix < stoppos) { \ ! 375: TYPE d = xcolors[ham_linebuf[pix]]; \ ! 376: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ ! 377: pix++; \ ! 378: } \ ! 379: } else if (bpldualpf) { \ ! 380: /* Dual playfield */ \ ! 381: int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \ ! 382: while (pix < diwlastword && pix < stoppos) { \ ! 383: int pixcol = pixdata.apixels[pix]; \ ! 384: TYPE d; \ ! 385: if (spixstate[pix]) { \ ! 386: d = acolors[pixcol]; \ ! 387: } else { \ ! 388: d = acolors[lookup[pixcol]]; \ ! 389: } \ ! 390: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ ! 391: pix++; \ ! 392: } \ ! 393: } else { \ ! 394: while (pix < diwlastword && pix < stoppos) { \ ! 395: TYPE d = acolors[pixdata.apixels[pix]]; \ ! 396: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ ! 397: pix++; \ ! 398: } \ ! 399: } \ ! 400: while (pix < stoppos) { \ ! 401: TYPE d = acolors[0]; \ ! 402: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ ! 403: pix++; \ ! 404: } \ ! 405: xlinebuffer = (char *)(((TYPE *)xlinebuffer) + pix - oldpix); \ ! 406: } ! 407: ! 408: /* WARNING: Not too much of this will work correctly yet. */ ! 409: ! 410: static void pfield_linetoscr_aga(int pix, int stoppos) ! 411: { ! 412: ULONG *buf = aga_lbufptr; ! 413: int i; ! 414: int xor = (UBYTE)(bpl_info.bplcon4 >> 8); ! 415: int oldpix = pix; \ ! 416: ! 417: buf -= pix; \ ! 418: ! 419: for (i = 0; i < stoppos; i++) ! 420: pixdata.apixels[i] ^= xor; ! 421: ! 422: while (pix < diwfirstword && pix < stoppos) { ! 423: buf[pix++] = bpl_info.color_regs[0]; ! 424: } ! 425: if (bplham) { ! 426: while (pix < diwlastword && pix < stoppos) { ! 427: ULONG d = ham_linebuf[pix]; ! 428: buf[pix] = d; ! 429: pix++; ! 430: } ! 431: } else if (bpldualpf) { ! 432: /* Dual playfield */ ! 433: int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1; ! 434: int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1; ! 435: while (pix < diwlastword && pix < stoppos) { ! 436: int pixcol = pixdata.apixels[pix]; ! 437: int pfno = lookup_no[pixcol]; ! 438: ! 439: if (spixstate[pix]) { ! 440: buf[pix] = bpl_info.color_regs[pixcol]; ! 441: } else { ! 442: int val = lookup[pixdata.apixels[pix]]; ! 443: if (pfno == 2) ! 444: val += dblpfofs[(bpl_info.bplcon2 >> 10) & 7]; ! 445: buf[pix] = bpl_info.color_regs[val]; ! 446: } ! 447: pix++; ! 448: } ! 449: } else if (bplehb) { ! 450: while (pix < diwlastword && pix < stoppos) { ! 451: int pixcol = pixdata.apixels[pix]; ! 452: ULONG d = bpl_info.color_regs[pixcol]; ! 453: /* What about sprites? */ ! 454: if (pixcol & 0x20) ! 455: d = (d & 0x777777) >> 1; ! 456: buf[pix] = d; ! 457: pix++; ! 458: } ! 459: } else { ! 460: while (pix < diwlastword && pix < stoppos) { ! 461: int pixcol = pixdata.apixels[pix]; ! 462: buf[pix] = bpl_info.color_regs[pixcol]; ! 463: pix++; ! 464: } ! 465: } ! 466: while (pix < stoppos) { ! 467: buf[pix++] = bpl_info.color_regs[0]; ! 468: } ! 469: aga_lbufptr += pix - oldpix; ! 470: } ! 471: ! 472: static void aga_translate32(int start, int stop) ! 473: { ! 474: memcpy (((ULONG *)xlinebuffer) + start, aga_linebuf + start, 4*(stop-start)); ! 475: } ! 476: ! 477: static void aga_translate16(int start, int stop) ! 478: { ! 479: int i; ! 480: for (i = start; i < stop; i++) { ! 481: ULONG d = aga_linebuf[i]; ! 482: UWORD v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12); ! 483: ((UWORD *)xlinebuffer)[i] = xcolors[v]; ! 484: } ! 485: } ! 486: ! 487: static void aga_translate8(int start, int stop) ! 488: { ! 489: int i; ! 490: for (i = start; i < stop; i++) { ! 491: ULONG d = aga_linebuf[i]; ! 492: UWORD v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12); ! 493: ((UBYTE *)xlinebuffer)[i] = xcolors[v]; ! 494: } ! 495: } ! 496: ! 497: ! 498: ! 499: #define FILL_LINE(NAME, TYPE) \ ! 500: static void NAME(char *buf) \ ! 501: { \ ! 502: TYPE *b = (TYPE *)buf; \ ! 503: int i;\ ! 504: int maxpos = gfxvidinfo.maxlinetoscr; \ ! 505: xcolnr col = acolors[0]; \ ! 506: if (!maxpos) maxpos = 796; \ ! 507: for (i = 0; i < maxpos; i++) \ ! 508: *b++ = col; \ ! 509: } ! 510: ! 511: LINE_TO_SCR(pfield_linetoscr_8, UBYTE, 0) ! 512: LINE_TO_SCR(pfield_linetoscr_16, UWORD, 0) ! 513: LINE_TO_SCR(pfield_linetoscr_32, ULONG, 0) ! 514: LINE_TO_SCR(pfield_linetoscr_8_double_slow, UBYTE, 1) ! 515: LINE_TO_SCR(pfield_linetoscr_16_double_slow, UWORD, 1) ! 516: LINE_TO_SCR(pfield_linetoscr_32_double_slow, ULONG, 1) ! 517: ! 518: FILL_LINE(fill_line_8, UBYTE) ! 519: FILL_LINE(fill_line_16, UWORD) ! 520: FILL_LINE(fill_line_32, ULONG) ! 521: ! 522: #define pfield_linetoscr_full8 pfield_linetoscr_8 ! 523: #define pfield_linetoscr_full16 pfield_linetoscr_16 ! 524: #define pfield_linetoscr_full32 pfield_linetoscr_32 ! 525: ! 526: #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow ! 527: #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow ! 528: #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow ! 529: ! 530: #if 1 && defined(X86_ASSEMBLY) ! 531: #undef pfield_linetoscr_full8 ! 532: #undef pfield_linetoscr_full16 ! 533: extern void pfield_linetoscr_full8(int, int, int) __asm__("pfield_linetoscr_full8"); ! 534: extern void pfield_linetoscr_full16(int, int, int) __asm__("pfield_linetoscr_full16"); ! 535: #undef pfield_linetoscr_full8_double ! 536: #undef pfield_linetoscr_full16_double ! 537: ! 538: static void pfield_linetoscr_full8_double(int start, int stop, int offset) ! 539: { ! 540: char *oldxlb = (char *)xlinebuffer; ! 541: pfield_linetoscr_full8(start,stop,offset); ! 542: xlinebuffer = oldxlb + offset; ! 543: pfield_linetoscr_full8(start,stop,offset); ! 544: } ! 545: static void pfield_linetoscr_full16_double(int start, int stop, int offset) ! 546: { ! 547: char *oldxlb = (char *)xlinebuffer; ! 548: pfield_linetoscr_full16(start,stop,offset); ! 549: xlinebuffer = oldxlb + offset; ! 550: pfield_linetoscr_full16(start,stop,offset); ! 551: } ! 552: #endif ! 553: ! 554: static __inline__ void fill_line(int y) ! 555: { ! 556: switch (gfxvidinfo.pixbytes) { ! 557: case 1: fill_line_8(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break; ! 558: case 2: fill_line_16(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break; ! 559: case 4: fill_line_32(gfxvidinfo.bufmem + gfxvidinfo.rowbytes * y); break; ! 560: } ! 561: } ! 562: ! 563: static void pfield_do_linetoscr(int start, int stop) ! 564: { ! 565: int factor = use_lores ? 1 : 2; ! 566: int oldstop = stop; ! 567: int real_start, real_stop; ! 568: ! 569: start = PIXEL_XPOS(start); ! 570: if (start < 8*factor) ! 571: start = 8*factor; ! 572: stop = PIXEL_XPOS(stop); ! 573: if (stop > 406*factor) ! 574: stop = 406*factor; ! 575: ! 576: if (start >= stop) ! 577: return; ! 578: if (stop <= gfxvidinfo.x_adjust) ! 579: return; ! 580: ! 581: slowline_lasttoscr = oldstop; ! 582: ! 583: if (start < gfxvidinfo.x_adjust) ! 584: real_start = gfxvidinfo.x_adjust; ! 585: else ! 586: real_start = start; ! 587: ! 588: if (gfxvidinfo.maxlinetoscr) { ! 589: real_stop = gfxvidinfo.x_adjust + gfxvidinfo.maxlinetoscr; ! 590: if (real_stop > stop) ! 591: real_stop = stop; ! 592: } else ! 593: real_stop = stop; ! 594: ! 595: #if AGA_CHIPSET == 0 ! 596: if (start == 8*factor && stop == 406*factor) { ! 597: switch (gfxvidinfo.pixbytes) { ! 598: case 1: pfield_linetoscr_full8 (real_start, real_stop, 0); break; ! 599: case 2: pfield_linetoscr_full16 (real_start, real_stop, 0); break; ! 600: case 4: pfield_linetoscr_full32 (real_start, real_stop, 0); break; ! 601: } ! 602: } else { ! 603: if (real_start >= real_stop) ! 604: return; ! 605: switch (gfxvidinfo.pixbytes) { ! 606: case 1: pfield_linetoscr_8 (real_start, real_stop, 0); break; ! 607: case 2: pfield_linetoscr_16 (real_start, real_stop, 0); break; ! 608: case 4: pfield_linetoscr_32 (real_start, real_stop, 0); break; ! 609: } ! 610: } ! 611: #else ! 612: pfield_linetoscr_aga(real_start, real_stop); ! 613: #endif ! 614: } ! 615: ! 616: static void pfield_do_linetoscr_full(int double_line) ! 617: { ! 618: int factor = use_lores ? 1 : 2; ! 619: int stop, start; ! 620: ! 621: start = 8*factor; ! 622: stop = 406*factor; ! 623: ! 624: if (start < gfxvidinfo.x_adjust) ! 625: start = gfxvidinfo.x_adjust; ! 626: ! 627: if (gfxvidinfo.maxlinetoscr) { ! 628: int tmp = gfxvidinfo.x_adjust + gfxvidinfo.maxlinetoscr; ! 629: if (tmp < stop) ! 630: stop = tmp; ! 631: } ! 632: ! 633: #if AGA_CHIPSET == 0 ! 634: if (double_line) { ! 635: switch (gfxvidinfo.pixbytes) { ! 636: case 1: pfield_linetoscr_full8_double (start, stop, gfxvidinfo.rowbytes); break; ! 637: case 2: pfield_linetoscr_full16_double (start, stop, gfxvidinfo.rowbytes); break; ! 638: case 4: pfield_linetoscr_full32_double (start, stop, gfxvidinfo.rowbytes); break; ! 639: } ! 640: } else ! 641: switch (gfxvidinfo.pixbytes) { ! 642: case 1: pfield_linetoscr_full8 (start, stop, 0); break; ! 643: case 2: pfield_linetoscr_full16 (start, stop, 0); break; ! 644: case 4: pfield_linetoscr_full32 (start, stop, 0); break; ! 645: } ! 646: #else ! 647: pfield_linetoscr_aga(start, stop); ! 648: #endif ! 649: } ! 650: ! 651: /* ! 652: * This function is called whenever a hardware register that controls the ! 653: * screen display is modified. Usually, this routine does nothing. But in ! 654: * some cases, e.g., when a color changes in mid-screen, as in copper-plasma ! 655: * effects, this function switches the update method from the fast full-line ! 656: * update to the much slower single-color-clock update. ! 657: */ ! 658: static void pfield_may_need_update(int colreg) ! 659: { ! 660: int i; ! 661: ! 662: /* Ignore, if this happened before or after the DDF window */ ! 663: /* @@@ This breaks some copper plasmas. Not good... maybe a config ! 664: * option is needed. */ ! 665: if (framecnt != 0 || !pfield_linedmaon || current_hpos() <= plfstrt ! 666: || vpos < plffirstline || vpos < minfirstline || vpos >= plflastline ! 667: || next_lineno >= gfxvidinfo.maxline) ! 668: { ! 669: return; ! 670: } ! 671: /* ! 672: * If a color reg was modified, it is only important if we are within ! 673: * the DIW. ! 674: */ ! 675: if (PIXEL_XPOS(current_hpos()) <= diwfirstword && colreg) ! 676: return; ! 677: ! 678: /* ! 679: * If we are past the DDF window, me might as well draw the complete ! 680: * line now. ! 681: */ ! 682: if (current_hpos() > plfstrt + plflinelen && pfield_fullline) { ! 683: if (!pfield_linedone) ! 684: pfield_doline(); ! 685: pfield_linedone = 1; ! 686: return; ! 687: } ! 688: ! 689: do_sprites(vpos, current_hpos()); ! 690: if (pfield_fullline) { ! 691: pfield_lastpart_hpos = 0; ! 692: memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); ! 693: memset(spixstate,0,sizeof spixstate); ! 694: pfield_fullline = 0; ! 695: slowline_nextpos = -1; ! 696: slowline_linepos = 0; ! 697: slowline_lasttoscr = 0; ! 698: } else { ! 699: assert(pfield_lastpart_hpos <= current_hpos()); ! 700: } ! 701: for (i = pfield_lastpart_hpos; i < current_hpos(); i++) { ! 702: pfield_doline_slow(i); ! 703: } ! 704: if (colreg) { ! 705: pfield_do_linetoscr(slowline_lasttoscr, current_hpos()); ! 706: } ! 707: pfield_lastpart_hpos = current_hpos(); ! 708: } ! 709: ! 710: /* Apparently, the DMA bit is tested by the hardware at some point, ! 711: * presumably at the ddfstart position, to determine whether it ! 712: * ought to draw the line. ! 713: * This is probably not completely correct, but should not matter ! 714: * very much. ! 715: */ ! 716: static void pfield_calclinedma(void) ! 717: { ! 718: if (current_hpos() >= plfstrt) ! 719: return; ! 720: ! 721: pfield_linedmaon = dmaen(DMA_BITPLANE); ! 722: } ! 723: ! 724: /* ! 725: * register functions ! 726: */ ! 727: ! 728: static UWORD DMACONR(void) ! 729: { ! 730: return (dmacon | (bltstate==BLT_done ? 0 : 0x4000) ! 731: | (blt_info.blitzero ? 0x2000 : 0)); ! 732: } ! 733: static UWORD INTENAR(void) { return intena; } ! 734: UWORD INTREQR(void) ! 735: { ! 736: return intreq | (use_serial ? 0x0001 : 0); ! 737: } ! 738: static UWORD ADKCONR(void) { return adkcon; } ! 739: static UWORD VPOSR(void) ! 740: { ! 741: #if AGA_CHIPSET == 1 ! 742: return (vpos >> 8) | lof | 0x2300; ! 743: #elif defined (ECS_AGNUS) ! 744: return (vpos >> 8) | lof | 0x2000; ! 745: #else ! 746: return (vpos >> 8) | lof; ! 747: #endif ! 748: } ! 749: static void VPOSW(UWORD v) { lof = v & 0x8000; } ! 750: static UWORD VHPOSR(void) { return (vpos << 8) | current_hpos(); } ! 751: ! 752: static void COP1LCH(UWORD v) { cop1lc= (cop1lc & 0xffff) | ((ULONG)v << 16); } ! 753: static void COP1LCL(UWORD v) { cop1lc= (cop1lc & ~0xffff) | v; } ! 754: static void COP2LCH(UWORD v) { cop2lc= (cop2lc & 0xffff) | ((ULONG)v << 16); } ! 755: static void COP2LCL(UWORD v) { cop2lc= (cop2lc & ~0xffff) | v; } ! 756: ! 757: static void COPJMP1(UWORD a) ! 758: { ! 759: coplc = cop1lc; copstate = COP_read; ! 760: eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles; ! 761: eventtab[ev_copper].evtime = 4 + cycles; events_schedule(); ! 762: copper_active = 1; ! 763: } ! 764: static void COPJMP2(UWORD a) ! 765: { ! 766: coplc = cop2lc; copstate = COP_read; ! 767: eventtab[ev_copper].active = 1; eventtab[ev_copper].oldcycles = cycles; ! 768: eventtab[ev_copper].evtime = 4 + cycles; events_schedule(); ! 769: copper_active = 1; ! 770: } ! 771: ! 772: static void DMACON(UWORD v) ! 773: { ! 774: int i, need_resched = 0; ! 775: ! 776: UWORD oldcon = dmacon; ! 777: setclr(&dmacon,v); dmacon &= 0x1FFF; ! 778: pfield_calclinedma(); ! 779: ! 780: /* FIXME? Maybe we need to think a bit more about the master DMA enable ! 781: * bit in these cases. */ ! 782: if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { ! 783: COPJMP1(0); ! 784: } ! 785: if ((dmacon & DMA_SPRITE) > (oldcon & DMA_SPRITE)) { ! 786: int i; ! 787: for (i = 0; i < 8; i++) ! 788: spron[i] = 1; ! 789: } ! 790: if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) { ! 791: static int count = 0; ! 792: if (!count) { ! 793: count = 1; ! 794: fprintf(stderr, "warning: program is doing blitpri hacks.\n"); ! 795: } ! 796: regs.spcflags |= SPCFLAG_BLTNASTY; ! 797: } ! 798: #ifndef DONT_WANT_SOUND ! 799: for (i = 0; i < 4; i++) { ! 800: struct audio_channel_data *cdp = audio_channel + i; ! 801: ! 802: cdp->dmaen = (dmacon & 0x200) && (dmacon & (1<<i)); ! 803: if (cdp->dmaen) { ! 804: if (cdp->state == 0) { ! 805: cdp->state = 1; ! 806: cdp->pt = cdp->lc; ! 807: cdp->wper = cdp->per; ! 808: cdp->wlen = cdp->len; ! 809: cdp->data_written = 2; ! 810: eventtab[ev_aud0 + i].oldcycles = eventtab[ev_hsync].oldcycles; ! 811: eventtab[ev_aud0 + i].evtime = eventtab[ev_hsync].evtime; ! 812: eventtab[ev_aud0 + i].active = 1; ! 813: need_resched = 1; /* not _really_ necessary here, but... */ ! 814: } ! 815: } else { ! 816: if (cdp->state == 1 || cdp->state == 5) { ! 817: cdp->state = 0; ! 818: cdp->current_sample = 0; ! 819: eventtab[ev_aud0 + i].active = 0; ! 820: need_resched = 1; ! 821: } ! 822: } ! 823: } ! 824: #endif ! 825: if (copper_active && !eventtab[ev_copper].active) { ! 826: eventtab[ev_copper].active = 1; ! 827: eventtab[ev_copper].oldcycles = cycles; ! 828: eventtab[ev_copper].evtime = 1 + cycles; ! 829: need_resched = 1; ! 830: } ! 831: if (need_resched) ! 832: events_schedule(); ! 833: } ! 834: static void INTENA(UWORD v) { setclr(&intena,v); regs.spcflags |= SPCFLAG_INT; } ! 835: void INTREQ(UWORD v) ! 836: { ! 837: setclr(&intreq,v); ! 838: regs.spcflags |= SPCFLAG_INT; ! 839: if ((v&0x8800)==0x0800) serdat&=0xbfff; ! 840: } ! 841: ! 842: static void ADKCON(UWORD v) { setclr(&adkcon,v); } ! 843: ! 844: static void BPLPTH(UWORD v, int num) { bplpt[num] = (bplpt[num] & 0xffff) | ((ULONG)v << 16); } ! 845: static void BPLPTL(UWORD v, int num) { bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xFFFE); } ! 846: ! 847: /* ! 848: * I've seen the listing of an example program that changes ! 849: * from lo- to hires while a line is being drawn. That's ! 850: * awful, but we want to emulate it. ! 851: */ ! 852: static void BPLCON0(UWORD v) ! 853: { ! 854: if (bpl_info.bplcon0 == v) ! 855: return; ! 856: pfield_may_need_update(0); ! 857: bpl_info.bplcon0 = v; ! 858: bplhires = (v & 0x8000) == 0x8000; ! 859: bplplanecnt = (v & 0x7000) >> 12; ! 860: bplham = (v & 0x800) == 0x800; ! 861: bpldualpf = (v & 0x400) == 0x400; ! 862: bplehb = (v & 0xFDC0) == 0x6000 && !(bpl_info.bplcon2 & 0x200); /* see below */ ! 863: calcdiw(); /* This should go away. */ ! 864: } ! 865: static void BPLCON1(UWORD v) ! 866: { ! 867: if (bpl_info.bplcon1 == v) ! 868: return; ! 869: pfield_may_need_update(0); ! 870: bpl_info.bplcon1 = v; ! 871: bpldelay1 = v & 0xF; ! 872: bpldelay2 = (v >> 4) & 0xF; ! 873: } ! 874: static void BPLCON2(UWORD v) ! 875: { ! 876: if (bpl_info.bplcon2 == v) ! 877: return; ! 878: pfield_may_need_update(0); ! 879: bpl_info.bplcon2 = v; ! 880: bpldualpfpri = (v & 0x40) == 0x40; ! 881: plfpri[1] = 1 << 2*(v & 7); ! 882: plfpri[2] = 1 << 2*((v>>3) & 7); ! 883: bplehb = (bpl_info.bplcon0 & 0xFDC0) == 0x6000 && !(v & 0x200); /* see above */ ! 884: } ! 885: static void BPLCON3(UWORD v) ! 886: { ! 887: if (bpl_info.bplcon3 == v) ! 888: return; ! 889: pfield_may_need_update(0); ! 890: bpl_info.bplcon3 = v; ! 891: } ! 892: static void BPLCON4(UWORD v) ! 893: { ! 894: if (bpl_info.bplcon4 == v) ! 895: return; ! 896: pfield_may_need_update(0); ! 897: bpl_info.bplcon4 = v; ! 898: } ! 899: ! 900: static void BPL1MOD(UWORD v) ! 901: { ! 902: v &= ~1; ! 903: if (bpl1mod == v) ! 904: return; ! 905: pfield_may_need_update(0); ! 906: bpl1mod = v; ! 907: } ! 908: static void BPL2MOD(UWORD v) ! 909: { ! 910: v &= ~1; ! 911: if (bpl2mod == v) ! 912: return; ! 913: pfield_may_need_update(0); ! 914: bpl2mod = v; ! 915: } ! 916: ! 917: static void BPL1DAT(UWORD v) { bpl1dat = v; } ! 918: static void BPL2DAT(UWORD v) { bpl2dat = v; } ! 919: static void BPL3DAT(UWORD v) { bpl3dat = v; } ! 920: static void BPL4DAT(UWORD v) { bpl4dat = v; } ! 921: static void BPL5DAT(UWORD v) { bpl5dat = v; } ! 922: static void BPL6DAT(UWORD v) { bpl6dat = v; } ! 923: ! 924: /* We call pfield_may_need_update() from here. Actually, ! 925: * I have no idea what happens if someone changes ddf or ! 926: * diw mid-line, and I don't really want to know. I doubt ! 927: * that this sort of thing was ever used to create a ! 928: * useful effect. ! 929: */ ! 930: static void DIWSTRT(UWORD v) ! 931: { ! 932: if (bpl_info.diwstrt == v) ! 933: return; ! 934: pfield_may_need_update(0); ! 935: bpl_info.diwstrt = v; ! 936: calcdiw(); ! 937: } ! 938: static void DIWSTOP(UWORD v) ! 939: { ! 940: if (bpl_info.diwstop == v) ! 941: return; ! 942: pfield_may_need_update(0); ! 943: bpl_info.diwstop = v; ! 944: calcdiw(); ! 945: } ! 946: static void DDFSTRT(UWORD v) ! 947: { ! 948: if (bpl_info.ddfstrt == v) ! 949: return; ! 950: pfield_may_need_update(0); ! 951: bpl_info.ddfstrt = v; ! 952: calcdiw(); ! 953: } ! 954: static void DDFSTOP(UWORD v) ! 955: { ! 956: if (bpl_info.ddfstop == v) ! 957: return; ! 958: pfield_may_need_update(0); ! 959: bpl_info.ddfstop = v; ! 960: calcdiw(); ! 961: } ! 962: ! 963: static void BLTADAT(UWORD v) ! 964: { ! 965: maybe_blit(); ! 966: blt_info.bltadat = v; ! 967: } ! 968: static void BLTBDAT(UWORD v) ! 969: { ! 970: maybe_blit(); ! 971: blt_info.bltbdat = v; ! 972: } ! 973: static void BLTCDAT(UWORD v) { maybe_blit(); blt_info.bltcdat = v; } ! 974: ! 975: static void BLTAMOD(UWORD v) { maybe_blit(); blt_info.bltamod = v & 0xFFFE; } ! 976: static void BLTBMOD(UWORD v) { maybe_blit(); blt_info.bltbmod = v & 0xFFFE; } ! 977: static void BLTCMOD(UWORD v) { maybe_blit(); blt_info.bltcmod = v & 0xFFFE; } ! 978: static void BLTDMOD(UWORD v) { maybe_blit(); blt_info.bltdmod = v & 0xFFFE; } ! 979: ! 980: static void BLTCON0(UWORD v) { maybe_blit(); bltcon0 = v; blinea_shift = v >> 12; } ! 981: /* The next category is "Most useless hardware register". ! 982: * And the winner is... */ ! 983: static void BLTCON0L(UWORD v) { maybe_blit(); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); } ! 984: static void BLTCON1(UWORD v) { maybe_blit(); bltcon1 = v; } ! 985: ! 986: static void BLTAFWM(UWORD v) { maybe_blit(); blt_info.bltafwm = v; } ! 987: static void BLTALWM(UWORD v) { maybe_blit(); blt_info.bltalwm = v; } ! 988: ! 989: static void BLTAPTH(UWORD v) { maybe_blit(); bltapt= (bltapt & 0xffff) | ((ULONG)(v & 0x1F) << 16); } ! 990: static void BLTAPTL(UWORD v) { maybe_blit(); bltapt= (bltapt & ~0xffff) | (v & 0xFFFE); } ! 991: static void BLTBPTH(UWORD v) { maybe_blit(); bltbpt= (bltbpt & 0xffff) | ((ULONG)(v & 0x1F) << 16); } ! 992: static void BLTBPTL(UWORD v) { maybe_blit(); bltbpt= (bltbpt & ~0xffff) | (v & 0xFFFE); } ! 993: static void BLTCPTH(UWORD v) { maybe_blit(); bltcpt= (bltcpt & 0xffff) | ((ULONG)(v & 0x1F) << 16); } ! 994: static void BLTCPTL(UWORD v) { maybe_blit(); bltcpt= (bltcpt & ~0xffff) | (v & 0xFFFE); } ! 995: static void BLTDPTH(UWORD v) { maybe_blit(); bltdpt= (bltdpt & 0xffff) | ((ULONG)(v & 0x1F) << 16); } ! 996: static void BLTDPTL(UWORD v) { maybe_blit(); bltdpt= (bltdpt & ~0xffff) | (v & 0xFFFE); } ! 997: static void BLTSIZE(UWORD v) ! 998: { ! 999: bltsize = v; ! 1000: ! 1001: maybe_blit(); ! 1002: ! 1003: blt_info.vblitsize = bltsize >> 6; ! 1004: blt_info.hblitsize = bltsize & 0x3F; ! 1005: if (!blt_info.vblitsize) blt_info.vblitsize = 1024; ! 1006: if (!blt_info.hblitsize) blt_info.hblitsize = 64; ! 1007: ! 1008: bltstate = BLT_init; ! 1009: regs.spcflags |= SPCFLAG_BLIT; ! 1010: } ! 1011: static void BLTSIZV(UWORD v) ! 1012: { ! 1013: maybe_blit(); ! 1014: oldvblts = v & 0x7FFF; ! 1015: } ! 1016: static void BLTSIZH(UWORD v) ! 1017: { ! 1018: maybe_blit(); ! 1019: blt_info.hblitsize = v & 0x7FF; ! 1020: blt_info.vblitsize = oldvblts; ! 1021: if (!blt_info.vblitsize) blt_info.vblitsize = 32768; ! 1022: if (!blt_info.hblitsize) blt_info.hblitsize = 0x800; ! 1023: bltstate = BLT_init; ! 1024: regs.spcflags |= SPCFLAG_BLIT; ! 1025: } ! 1026: static void SPRxCTL_1(UWORD v, int num) ! 1027: { ! 1028: bpl_info.sprctl[num] = v; ! 1029: bpl_info.sprarmed[num] = 0; ! 1030: if (bpl_info.sprpos[num] == 0 && v == 0) ! 1031: spron[num] = 0; ! 1032: else ! 1033: spron[num] |= 2; ! 1034: } ! 1035: static void SPRxPOS_1(UWORD v, int num) ! 1036: { ! 1037: bpl_info.sprpos[num] = v; ! 1038: } ! 1039: static void SPRxDATA_1(UWORD v, int num) ! 1040: { ! 1041: bpl_info.sprdata[num] = v; ! 1042: bpl_info.sprarmed[num] = 1; ! 1043: } ! 1044: static void SPRxDATB_1(UWORD v, int num) ! 1045: { ! 1046: bpl_info.sprdatb[num] = v; ! 1047: } ! 1048: static void SPRxCTL(UWORD v, int num) { pfield_may_need_update(0); SPRxCTL_1(v, num); } ! 1049: static void SPRxPOS(UWORD v, int num) { pfield_may_need_update(0); SPRxPOS_1(v, num); } ! 1050: static void SPRxDATA(UWORD v, int num){ pfield_may_need_update(0); SPRxDATA_1(v, num); } ! 1051: static void SPRxDATB(UWORD v, int num){ pfield_may_need_update(0); SPRxDATB_1(v, num); } ! 1052: static void SPRxPTH(UWORD v, int num) ! 1053: { ! 1054: sprpt[num] &= 0xffff; ! 1055: sprpt[num] |= (ULONG)v << 16; ! 1056: if (!spron[num]) spron[num] = 1; ! 1057: } ! 1058: static void SPRxPTL(UWORD v, int num) ! 1059: { ! 1060: sprpt[num] &= ~0xffff; ! 1061: sprpt[num] |= v; ! 1062: if (!spron[num]) spron[num] = 1; ! 1063: } ! 1064: ! 1065: static void COLOR(UWORD v, int num) ! 1066: { ! 1067: int r,g,b; ! 1068: int cr,cg,cb; ! 1069: int colreg; ! 1070: ! 1071: v &= 0xFFF; ! 1072: #if AGA_CHIPSET == 1 ! 1073: { ! 1074: ULONG cval; ! 1075: colreg = ((bpl_info.bplcon3 >> 13) & 7) * 32 + num; ! 1076: r = (v & 0xF00) >> 8; ! 1077: g = (v & 0xF0) >> 4; ! 1078: b = (v & 0xF) >> 0; ! 1079: cr = bpl_info.color_regs[colreg] >> 16; ! 1080: cg = (bpl_info.color_regs[colreg] >> 8) & 0xFF; ! 1081: cb = bpl_info.color_regs[colreg] & 0xFF; ! 1082: ! 1083: if (bpl_info.bplcon3 & 0x200) { ! 1084: cr &= 0xF0; cr |= r; ! 1085: cg &= 0xF0; cg |= g; ! 1086: cb &= 0xF0; cb |= b; ! 1087: } else { ! 1088: cr = r + (r << 4); ! 1089: cg = g + (g << 4); ! 1090: cb = b + (b << 4); ! 1091: } ! 1092: cval = (cr << 16) | (cg << 8) | cb; ! 1093: if (cval == bpl_info.color_regs[colreg]) ! 1094: return; ! 1095: bpl_info.color_regs[colreg] = cval; ! 1096: pfield_may_need_update(1); ! 1097: } ! 1098: #else ! 1099: { ! 1100: if (bpl_info.color_regs[num] == v) ! 1101: return; ! 1102: pfield_may_need_update(1); ! 1103: bpl_info.color_regs[num] = v; ! 1104: acolors[num] = xcolors[v]; ! 1105: acolors[num+32] = xcolors[(v >> 1) & 0x777]; ! 1106: } ! 1107: #endif ! 1108: } ! 1109: ! 1110: static void DSKSYNC(UWORD v) { dsksync = v; } ! 1111: static void DSKDAT(UWORD v) { fprintf(stderr, "DSKDAT written. Not good.\n"); } ! 1112: static void DSKPTH(UWORD v) { dskpt = (dskpt & 0xffff) | ((ULONG)v << 16); } ! 1113: static void DSKPTL(UWORD v) { dskpt = (dskpt & ~0xffff) | (v); } ! 1114: ! 1115: static void DSKLEN(UWORD v) ! 1116: { ! 1117: if (v & 0x8000) { ! 1118: dskdmaen = dskdmaen == 1 ? 2 : 1; ! 1119: } else { ! 1120: dskdmaen = 0; ! 1121: if (eventtab[ev_diskblk].active) ! 1122: fprintf(stderr, "warning: Disk DMA aborted!\n"); ! 1123: eventtab[ev_diskblk].active = 0; ! 1124: events_schedule(); ! 1125: ! 1126: } ! 1127: dsklen = dsklength = v; dsklength &= 0x3fff; ! 1128: if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) { ! 1129: fprintf(stderr, "Non-standard sync: %04x len: %x\n", dsksync, dsklength); ! 1130: } ! 1131: if (dskdmaen > 1) { ! 1132: if (dsklen & 0x4000) { ! 1133: eventtab[ev_diskblk].active = 1; ! 1134: eventtab[ev_diskblk].oldcycles = cycles; ! 1135: eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */ ! 1136: events_schedule(); ! 1137: } else { ! 1138: int result = DISK_PrepareReadMFM(dsklength, dsksync, adkcon & 0x400); ! 1139: if (result) { ! 1140: eventtab[ev_diskblk].active = 1; ! 1141: eventtab[ev_diskblk].oldcycles = cycles; ! 1142: eventtab[ev_diskblk].evtime = result + cycles; ! 1143: events_schedule(); ! 1144: } ! 1145: } ! 1146: } ! 1147: } ! 1148: ! 1149: static UWORD DSKBYTR(void) ! 1150: { ! 1151: UWORD v = (dsklen >> 1) & 0x6000; ! 1152: UWORD mfm, byte; ! 1153: if (DISK_GetData(&mfm, &byte)) ! 1154: v |= 0x8000; ! 1155: v |= byte; ! 1156: if (dsksync == mfm) v |= 0x1000; ! 1157: return v; ! 1158: } ! 1159: ! 1160: static UWORD DSKDATR(void) ! 1161: { ! 1162: UWORD mfm, byte; ! 1163: DISK_GetData(&mfm, &byte); ! 1164: return mfm; ! 1165: } ! 1166: static UWORD POTGOR(void) ! 1167: { ! 1168: UWORD v = 0xFF00; ! 1169: if (buttonstate[2]) ! 1170: v &= 0xFBFF; ! 1171: ! 1172: if (buttonstate[1]) ! 1173: v &= 0xFEFF; ! 1174: ! 1175: return v; ! 1176: } ! 1177: static UWORD POT0DAT(void) ! 1178: { ! 1179: static UWORD cnt = 0; ! 1180: if (buttonstate[2]) ! 1181: cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00); ! 1182: if (buttonstate[1]) ! 1183: cnt += 0x100; ! 1184: ! 1185: return cnt; ! 1186: } ! 1187: static UWORD JOY0DAT(void) { return joy0x + (joy0y << 8); } ! 1188: static UWORD JOY1DAT(void) ! 1189: { ! 1190: return joy0dir; ! 1191: } ! 1192: static void JOYTEST(UWORD v) ! 1193: { ! 1194: joy0x = joy1x = v & 0xFC; ! 1195: joy0y = joy1y = (v >> 8) & 0xFC; ! 1196: } ! 1197: static void AUDxLCH(int nr, UWORD v) { audio_channel[nr].lc = (audio_channel[nr].lc & 0xffff) | ((ULONG)v << 16); } ! 1198: static void AUDxLCL(int nr, UWORD v) { audio_channel[nr].lc = (audio_channel[nr].lc & ~0xffff) | (v & 0xFFFE); } ! 1199: static void AUDxPER(int nr, UWORD v) ! 1200: { ! 1201: static int warned = 0; ! 1202: if (v <= 0) { ! 1203: if (!warned) ! 1204: fprintf(stderr, "Broken program accessing the sound hardware\n"), warned++; ! 1205: v = 65535; ! 1206: } ! 1207: ! 1208: if (v < maxhpos/2 && produce_sound < 3) ! 1209: v = maxhpos/2; ! 1210: ! 1211: audio_channel[nr].per = v; ! 1212: } ! 1213: ! 1214: static void AUDxVOL(int nr, UWORD v) { audio_channel[nr].vol = v & 64 ? 63 : v & 63; } ! 1215: static void AUDxLEN(int nr, UWORD v) { audio_channel[nr].len = v; } ! 1216: ! 1217: static int copcomp(void) ! 1218: { ! 1219: UWORD vp = vpos & (((copi2 >> 8) & 0x7F) | 0x80); ! 1220: UWORD hp = current_hpos() & (copi2 & 0xFE); ! 1221: UWORD vcmp = copi1 >> 8; ! 1222: UWORD hcmp = copi1 & 0xFE; ! 1223: return (vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000)); ! 1224: } ! 1225: ! 1226: /* ! 1227: * Calculate the minimum number of cycles after which the ! 1228: * copper comparison becomes true. This is quite tricky. I hope it works. ! 1229: */ ! 1230: static int calc_copcomp_true(int currvpos, int currhpos) ! 1231: { ! 1232: UWORD vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); ! 1233: UWORD hp = currhpos & (copi2 & 0xFE); ! 1234: UWORD vcmp = copi1 >> 8; ! 1235: UWORD hcmp = copi1 & 0xFE; ! 1236: int copper_time_hpos; ! 1237: int cycleadd = maxhpos - currhpos; ! 1238: int coptime = 0; ! 1239: ! 1240: if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) && ((copi2 & 0x8000) || !(DMACONR() & 0x4000))) ! 1241: return 0; ! 1242: ! 1243: try_again: ! 1244: ! 1245: while (vp < vcmp) { ! 1246: currvpos++; ! 1247: if (currvpos > maxvpos + 1) ! 1248: return -1; ! 1249: currhpos = 0; ! 1250: coptime += cycleadd; ! 1251: cycleadd = maxhpos; ! 1252: vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); ! 1253: } ! 1254: if (coptime > 0 && bplhires && bplplanecnt == 4) ! 1255: return coptime; ! 1256: copper_time_hpos = currhpos; ! 1257: hp = copper_time_hpos & (copi2 & 0xFE); ! 1258: if (!(vp > vcmp)) { ! 1259: while (hp < hcmp-2) { ! 1260: currhpos++; ! 1261: /* Copper DMA is turned off in Hires 4 bitplane mode */ ! 1262: if (!bplhires || bplplanecnt < 4 || !dmaen(DMA_BITPLANE) ! 1263: || currhpos < plfstrt-2 || currhpos > (plfstop+4)) ! 1264: copper_time_hpos++; ! 1265: ! 1266: if (currhpos > maxhpos-4) { ! 1267: /* Now, what? There might be a good position on the ! 1268: * next line. But it can also be the FFFF FFFE ! 1269: * case. ! 1270: */ ! 1271: currhpos = 0; ! 1272: currvpos++; ! 1273: vp = currvpos & (((copi2 >> 8) & 0x7F) | 0x80); ! 1274: goto try_again; ! 1275: } ! 1276: coptime++; ! 1277: hp = copper_time_hpos & (copi2 & 0xFE); ! 1278: } ! 1279: } ! 1280: if (coptime == 0) /* waiting for the blitter */ ! 1281: return 1; ! 1282: ! 1283: return coptime; ! 1284: } ! 1285: ! 1286: static void copper_read(void) ! 1287: { ! 1288: if (dmaen(DMA_COPPER)){ ! 1289: copi1 = chipmem_bank.wget(coplc); ! 1290: copi2 = chipmem_bank.wget(coplc+2); ! 1291: coplc += 4; ! 1292: eventtab[ev_copper].oldcycles = cycles; ! 1293: eventtab[ev_copper].evtime = ((copi1 & 1) ? (copi2 & 1) ? 10 : 8 : 4) + cycles; ! 1294: copstate = (copi1 & 1) ? (copi2 & 1) ? COP_skip : COP_wait : COP_move; ! 1295: } else { ! 1296: copstate = COP_read; ! 1297: eventtab[ev_copper].active = 0; ! 1298: } ! 1299: } ! 1300: ! 1301: static void do_copper(void) ! 1302: { ! 1303: switch(copstate){ ! 1304: case COP_read: ! 1305: copper_read(); ! 1306: break; ! 1307: case COP_move: ! 1308: if (copi1 >= (copcon & 2 ? 0x40 : 0x80)) { ! 1309: custom_bank.wput(copi1,copi2); ! 1310: copper_read(); ! 1311: } else { ! 1312: copstate = COP_stop; ! 1313: eventtab[ev_copper].active = 0; ! 1314: copper_active = 0; ! 1315: } ! 1316: break; ! 1317: case COP_skip: ! 1318: if (calc_copcomp_true(vpos, current_hpos()) == 0) ! 1319: coplc += 4; ! 1320: copper_read(); ! 1321: break; ! 1322: case COP_wait: { ! 1323: int coptime = calc_copcomp_true(vpos, current_hpos()); ! 1324: if (coptime < 0) { ! 1325: copstate = COP_stop; ! 1326: eventtab[ev_copper].active = 0; ! 1327: copper_active = 0; ! 1328: } else { ! 1329: if (!coptime) ! 1330: copper_read(); ! 1331: else { ! 1332: eventtab[ev_copper].evtime = coptime + cycles; ! 1333: eventtab[ev_copper].oldcycles = cycles; ! 1334: } ! 1335: } ! 1336: break; ! 1337: } ! 1338: case COP_stop: ! 1339: eventtab[ev_copper].active = 0; ! 1340: copper_active = 0; ! 1341: break; ! 1342: } ! 1343: } ! 1344: ! 1345: static void diskblk_handler(void) ! 1346: { ! 1347: regs.spcflags |= SPCFLAG_DISK; ! 1348: eventtab[ev_diskblk].active = 0; ! 1349: } ! 1350: ! 1351: void do_disk(void) ! 1352: { ! 1353: if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) { ! 1354: fprintf(stderr, "BUG!\n"); ! 1355: return; ! 1356: } ! 1357: if (dmaen(0x10)){ ! 1358: if (dsklen & 0x4000) { ! 1359: if (!chipmem_bank.check (dskpt, 2*dsklength)) { ! 1360: fprintf(stderr, "warning: Bad disk write DMA pointer\n"); ! 1361: } else { ! 1362: UBYTE *mfmp = get_real_address (dskpt); ! 1363: int i; ! 1364: DISK_InitWrite(); ! 1365: ! 1366: for (i = 0; i < dsklength; i++) { ! 1367: UWORD d = (*mfmp << 8) + *(mfmp+1); ! 1368: mfmwrite[i] = d; ! 1369: mfmp += 2; ! 1370: } ! 1371: DISK_WriteData(dsklength); ! 1372: } ! 1373: } else { ! 1374: int result = DISK_ReadMFM (dskpt); ! 1375: } ! 1376: regs.spcflags &= ~SPCFLAG_DISK; ! 1377: INTREQ(0x9002); ! 1378: dskdmaen = -1; ! 1379: } ! 1380: } ! 1381: ! 1382: static __inline__ void pfield_fetchdata(void) ! 1383: { ! 1384: if (dmaen(0x100) && pfield_linedmaon) { ! 1385: switch(bplplanecnt){ ! 1386: case 8: ! 1387: bpl8dat = chipmem_bank.wget(bplpt[7]); bplpt[7] += 2; bpl8dat <<= 7; ! 1388: case 7: ! 1389: bpl7dat = chipmem_bank.wget(bplpt[6]); bplpt[6] += 2; bpl7dat <<= 6; ! 1390: case 6: ! 1391: bpl6dat = chipmem_bank.wget(bplpt[5]); bplpt[5] += 2; bpl6dat <<= 5; ! 1392: case 5: ! 1393: bpl5dat = chipmem_bank.wget(bplpt[4]); bplpt[4] += 2; bpl5dat <<= 4; ! 1394: case 4: ! 1395: bpl4dat = chipmem_bank.wget(bplpt[3]); bplpt[3] += 2; bpl4dat <<= 3; ! 1396: case 3: ! 1397: bpl3dat = chipmem_bank.wget(bplpt[2]); bplpt[2] += 2; bpl3dat <<= 2; ! 1398: case 2: ! 1399: bpl2dat = chipmem_bank.wget(bplpt[1]); bplpt[1] += 2; bpl2dat <<= 1; ! 1400: case 1: ! 1401: bpl1dat = chipmem_bank.wget(bplpt[0]); bplpt[0] += 2; ! 1402: } ! 1403: } ! 1404: } ! 1405: ! 1406: static void do_sprites(int currvp, int currhp) ! 1407: { ! 1408: int i; ! 1409: int maxspr = currhp/4 - 0x18/4; ! 1410: ! 1411: if (currvp == 0) ! 1412: return; ! 1413: if (maxspr < 0) ! 1414: return; ! 1415: if (maxspr > 7) ! 1416: maxspr = 7; ! 1417: ! 1418: for(i = last_sprite; i <= maxspr; i++) { ! 1419: int vstart = (bpl_info.sprpos[i] >> 8) | ((bpl_info.sprctl[i] << 6) & 0x100); ! 1420: int vstop = (bpl_info.sprctl[i] >> 8) | ((bpl_info.sprctl[i] << 7) & 0x100); ! 1421: if ((vstart <= currvp && vstop >= currvp) || spron[i] == 1) { ! 1422: if (dmaen(0x20)) { ! 1423: UWORD data1 = chipmem_bank.wget(sprpt[i]); ! 1424: UWORD data2 = chipmem_bank.wget(sprpt[i]+2); ! 1425: sprpt[i] += 4; ! 1426: ! 1427: if (vstop != currvp && spron[i] != 1) { ! 1428: /* Hack for X mouse auto-calibration */ ! 1429: if (i == 0 && !sprvbfl && ((bpl_info.sprpos[0]&0xff)<<2)>0x60) { ! 1430: spr0ctl=bpl_info.sprctl[0]; ! 1431: spr0pos=bpl_info.sprpos[0]; ! 1432: sprvbfl=2; ! 1433: } ! 1434: SPRxDATB_1(data2, i); ! 1435: SPRxDATA_1(data1, i); ! 1436: } else { ! 1437: SPRxPOS_1(data1, i); ! 1438: SPRxCTL_1(data2, i); ! 1439: } ! 1440: } ! 1441: } ! 1442: } ! 1443: last_sprite = maxspr + 1; ! 1444: } ! 1445: ! 1446: static __inline__ void pfield_modulos(int add) ! 1447: { ! 1448: switch(bplplanecnt){ ! 1449: case 8: ! 1450: bplpt[7] += add + bpl2mod; ! 1451: case 7: ! 1452: bplpt[6] += add + bpl1mod; ! 1453: case 6: ! 1454: bplpt[5] += add + bpl2mod; ! 1455: case 5: ! 1456: bplpt[4] += add + bpl1mod; ! 1457: case 4: ! 1458: bplpt[3] += add + bpl2mod; ! 1459: case 3: ! 1460: bplpt[2] += add + bpl1mod; ! 1461: case 2: ! 1462: bplpt[1] += add + bpl2mod; ! 1463: case 1: ! 1464: bplpt[0] += add + bpl1mod; ! 1465: } ! 1466: } ! 1467: ! 1468: #if AGA_CHIPSET == 0 ! 1469: static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb, int lores) ! 1470: { ! 1471: int i; ! 1472: ! 1473: int *lookup = bpldualpf ? (bpldualpfpri ? dblpf_ind2 : dblpf_ind1) : linear_map_256; ! 1474: int *lookup_no = bpldualpf ? (bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1) : lots_of_twos; ! 1475: ! 1476: for(i = 15; i >= 0; i--, data >>= 1, datb >>= 1) { ! 1477: int sprxpos = sprxp + i*(lores ? 1 : 2); ! 1478: int plno; ! 1479: int col; ! 1480: ! 1481: /* When doing the slow line update, the following condition can ! 1482: * happen. Lower-numbered sprites get the higher priority. */ ! 1483: if (spixstate[sprxpos] & ((1 << num)-1)) ! 1484: continue; ! 1485: ! 1486: /* Check the priority, but only if we did not already put a sprite ! 1487: * pixel at this position. If there's already a sprite pixel here, ! 1488: * the priority was previously tested. */ ! 1489: if (!spixstate[sprxpos]) { ! 1490: /* ??? What about hires mode when one hires pixel is 0, enabling the ! 1491: * sprite, and the other is != 0, blocking it? */ ! 1492: plno = lookup_no[pixdata.apixels[sprxpos]]; ! 1493: if (plno != 0 && (1 << num) >= plfpri[plno]) ! 1494: continue; ! 1495: } ! 1496: ! 1497: if ((bpl_info.sprctl[num] & 0x80) && (num & 1)) { ! 1498: /* Attached sprite */ ! 1499: col = ((data << 2) & 4) + ((datb << 3) & 8); ! 1500: spixstate[sprxpos] |= 1 << (num-1); ! 1501: spixels[sprxpos] = col; ! 1502: } else { ! 1503: col = (data & 1) | ((datb << 1) & 2); ! 1504: if (spixstate[sprxpos] & (1 << num)) { ! 1505: /* Finish attached sprite */ ! 1506: /* Did the upper half of the sprite have any bits set? */ ! 1507: if (spixstate[sprxpos] & (1 << (num+1))) ! 1508: col += spixels[sprxpos]; ! 1509: /* Is there any sprite pixel at this position at all? */ ! 1510: if (!col) { ! 1511: spixstate[sprxpos] &= ~(3 << num); ! 1512: } else ! 1513: col += 16; ! 1514: } else { ! 1515: if (col) { ! 1516: col |= 16 | ((num & 6) << 1); ! 1517: } ! 1518: } ! 1519: } ! 1520: if (col) { ! 1521: pixdata.apixels[sprxpos] = col; ! 1522: spixstate[sprxpos] |= 1<<num; ! 1523: if (!lores) { ! 1524: pixdata.apixels[sprxpos+1] = col; ! 1525: spixstate[sprxpos+1] |= 1<<num; ! 1526: } ! 1527: if (bplham && bplplanecnt == 6) { ! 1528: ham_linebuf[sprxpos] = bpl_info.color_regs[col]; ! 1529: if (!lores) ! 1530: ham_linebuf[sprxpos+1] = bpl_info.color_regs[col]; ! 1531: } ! 1532: } ! 1533: } ! 1534: } ! 1535: #else /* AGA version */ ! 1536: static void pfield_sprite (int num, int sprxp, UWORD data, UWORD datb, int lores) ! 1537: { ! 1538: int i; ! 1539: ! 1540: int *lookup = bpldualpf ? (bpldualpfpri ? dblpf_ind2 : dblpf_ind1) : linear_map_256; ! 1541: int *lookup_no = bpldualpf ? (bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1) : lots_of_twos; ! 1542: ! 1543: for(i = 15; i >= 0; i--, data >>= 1, datb >>= 1) { ! 1544: int sprxpos = sprxp + i*(lores ? 1 : 2); ! 1545: int plno; ! 1546: int col; ! 1547: ! 1548: /* When doing the slow line update, the following condition can ! 1549: * happen. Lower-numbered sprites get the higher priority. */ ! 1550: if (spixstate[sprxpos] & ((1 << num)-1)) ! 1551: continue; ! 1552: ! 1553: /* Check the priority, but only if we did not already put a sprite ! 1554: * pixel at this position. If there's already a sprite pixel here, ! 1555: * the priority was previously tested. */ ! 1556: if (!spixstate[sprxpos]) { ! 1557: /* ??? What about hires mode when one hires pixel is 0, enabling the ! 1558: * sprite, and the other is != 0, blocking it? */ ! 1559: plno = lookup_no[pixdata.apixels[sprxpos]]; ! 1560: if (plno != 0 && (1 << num) >= plfpri[plno]) ! 1561: continue; ! 1562: } ! 1563: ! 1564: if ((bpl_info.sprctl[num] & 0x80) && (num & 1)) { ! 1565: /* Attached sprite */ ! 1566: col = ((data << 2) & 4) + ((datb << 3) & 8); ! 1567: spixstate[sprxpos] |= 1 << (num-1); ! 1568: spixels[sprxpos] = col; ! 1569: } else { ! 1570: col = (data & 1) | ((datb << 1) & 2); ! 1571: if (spixstate[sprxpos] & (1 << num)) { ! 1572: /* Finish attached sprite */ ! 1573: /* Did the upper half of the sprite have any bits set? */ ! 1574: if (spixstate[sprxpos] & (1 << (num+1))) ! 1575: col += spixels[sprxpos]; ! 1576: /* Is there any sprite pixel at this position at all? */ ! 1577: if (!col) { ! 1578: spixstate[sprxpos] &= ~(3 << num); ! 1579: } else ! 1580: col += ((bpl_info.bplcon4 << (num & 1 ? 4 : 0)) & 240); ! 1581: } else { ! 1582: if (col) { ! 1583: col |= ((bpl_info.bplcon4 << (num & 1 ? 4 : 0)) & 240) | ((num & 6) << 1); ! 1584: } ! 1585: } ! 1586: } ! 1587: if (col) { ! 1588: pixdata.apixels[sprxpos] = col; ! 1589: spixstate[sprxpos] |= 1<<num; ! 1590: if (!lores) { ! 1591: pixdata.apixels[sprxpos+1] = col; ! 1592: spixstate[sprxpos+1] |= 1<<num; ! 1593: } ! 1594: if (bplham && bplplanecnt == 6) { ! 1595: ham_linebuf[sprxpos] = bpl_info.color_regs[col]; ! 1596: if (!lores) ! 1597: ham_linebuf[sprxpos+1] = bpl_info.color_regs[col]; ! 1598: } ! 1599: } ! 1600: } ! 1601: } ! 1602: #endif ! 1603: ! 1604: static __inline__ UBYTE *pfield_xlateptr(CPTR plpt, int bytecount) ! 1605: { ! 1606: if (!chipmem_bank.check(plpt,bytecount)) { ! 1607: static int count = 0; ! 1608: if (count < 5) { ! 1609: count++; ! 1610: fprintf(stderr, "Warning: Bad playfield pointer"); ! 1611: if (count == 5) fprintf(stderr, " (no further warnings)"); ! 1612: fprintf(stderr, "\n"); ! 1613: } ! 1614: return NULL; ! 1615: } ! 1616: return chipmem_bank.xlateaddr(plpt); ! 1617: } ! 1618: ! 1619: static void pfield_doline_slow_h(int currhpos) ! 1620: { ! 1621: int xpos = currhpos * 4 - 0x60; ! 1622: ! 1623: if (bplhires) { ! 1624: int offs1 = xpos + 16 + bpldelay1*2; ! 1625: int offs2 = xpos + 16 + bpldelay2*2; ! 1626: ! 1627: int pix; ! 1628: for(pix = 15; pix >= 0; pix--) { ! 1629: switch(bplplanecnt) { ! 1630: case 8: ! 1631: pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 1; ! 1632: case 7: ! 1633: pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 1; ! 1634: case 6: ! 1635: pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 1; ! 1636: case 5: ! 1637: pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 1; ! 1638: case 4: ! 1639: pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1; ! 1640: case 3: ! 1641: pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1; ! 1642: case 2: ! 1643: pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1; ! 1644: case 1: ! 1645: pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1; ! 1646: } ! 1647: } ! 1648: } else { ! 1649: int offs1 = xpos + 32 + bpldelay1*2; ! 1650: int offs2 = xpos + 32 + bpldelay2*2; ! 1651: ! 1652: int pix; ! 1653: for(pix = 30; pix >= 0; pix -= 2) { ! 1654: switch(bplplanecnt) { ! 1655: case 8: ! 1656: pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; ! 1657: pixdata.apixels[pix + offs2 + 1] |= bpl8dat & 0x80; bpl8dat >>= 1; ! 1658: case 7: ! 1659: pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; ! 1660: pixdata.apixels[pix + offs1 + 1] |= bpl7dat & 0x40; bpl7dat >>= 1; ! 1661: case 6: ! 1662: pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; ! 1663: pixdata.apixels[pix + offs2 + 1] |= bpl6dat & 0x20; bpl6dat >>= 1; ! 1664: case 5: ! 1665: pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; ! 1666: pixdata.apixels[pix + offs1 + 1] |= bpl5dat & 0x10; bpl5dat >>= 1; ! 1667: case 4: ! 1668: pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; ! 1669: pixdata.apixels[pix + offs2 + 1] |= bpl4dat & 0x8; bpl4dat >>= 1; ! 1670: case 3: ! 1671: pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; ! 1672: pixdata.apixels[pix + offs1 + 1] |= bpl3dat & 0x4; bpl3dat >>= 1; ! 1673: case 2: ! 1674: pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; ! 1675: pixdata.apixels[pix + offs2 + 1] |= bpl2dat & 0x2; bpl2dat >>= 1; ! 1676: case 1: ! 1677: pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; ! 1678: pixdata.apixels[pix + offs1 + 1] |= bpl1dat & 0x1; bpl1dat >>= 1; ! 1679: } ! 1680: } ! 1681: } ! 1682: } ! 1683: ! 1684: static void pfield_doline_slow_l(int currhpos) ! 1685: { ! 1686: int xpos = currhpos * 2 - 0x30; ! 1687: ! 1688: if (bplhires) { ! 1689: int offs1 = xpos + 8 + bpldelay1; ! 1690: int offs2 = xpos + 8 + bpldelay2; ! 1691: ! 1692: int pix; ! 1693: for(pix = 7; pix >= 0; pix--) { ! 1694: switch(bplplanecnt) { ! 1695: case 8: ! 1696: pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 2; ! 1697: case 7: ! 1698: pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 2; ! 1699: case 6: ! 1700: pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 2; ! 1701: case 5: ! 1702: pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 2; ! 1703: case 4: ! 1704: pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 2; ! 1705: case 3: ! 1706: pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 2; ! 1707: case 2: ! 1708: pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 2; ! 1709: case 1: ! 1710: pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 2; ! 1711: } ! 1712: } ! 1713: } else { ! 1714: int offs1 = xpos + 16 + bpldelay1; ! 1715: int offs2 = xpos + 16 + bpldelay2; ! 1716: ! 1717: int pix; ! 1718: for(pix = 15; pix >= 0; pix --) { ! 1719: switch(bplplanecnt) { ! 1720: case 8: ! 1721: pixdata.apixels[pix + offs2] |= bpl8dat & 0x80; bpl8dat >>= 1; ! 1722: case 7: ! 1723: pixdata.apixels[pix + offs1] |= bpl7dat & 0x40; bpl7dat >>= 1; ! 1724: case 6: ! 1725: pixdata.apixels[pix + offs2] |= bpl6dat & 0x20; bpl6dat >>= 1; ! 1726: case 5: ! 1727: pixdata.apixels[pix + offs1] |= bpl5dat & 0x10; bpl5dat >>= 1; ! 1728: case 4: ! 1729: pixdata.apixels[pix + offs2] |= bpl4dat & 0x8; bpl4dat >>= 1; ! 1730: case 3: ! 1731: pixdata.apixels[pix + offs1] |= bpl3dat & 0x4; bpl3dat >>= 1; ! 1732: case 2: ! 1733: pixdata.apixels[pix + offs2] |= bpl2dat & 0x2; bpl2dat >>= 1; ! 1734: case 1: ! 1735: pixdata.apixels[pix + offs1] |= bpl1dat & 0x1; bpl1dat >>= 1; ! 1736: } ! 1737: } ! 1738: } ! 1739: } ! 1740: ! 1741: ULONG hirestab_h[256][2]; ! 1742: ULONG lorestab_h[256][4]; ! 1743: ! 1744: ULONG hirestab_l[256][1]; ! 1745: ULONG lorestab_l[256][2]; ! 1746: ! 1747: static void gen_pfield_tables(void) ! 1748: { ! 1749: int i; ! 1750: union { ! 1751: struct { ! 1752: UBYTE a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p; ! 1753: } foo; ! 1754: struct { ! 1755: ULONG a, b, c, d; ! 1756: } bar; ! 1757: } baz; ! 1758: ! 1759: for (i = 0; i < 256; i++) { ! 1760: /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */ ! 1761: baz.foo.a = i & 64 ? 1 : 0; ! 1762: baz.foo.b = i & 16 ? 1 : 0; ! 1763: baz.foo.c = i & 4 ? 1 : 0; ! 1764: baz.foo.d = i & 1 ? 1 : 0; ! 1765: hirestab_l[i][0] = baz.bar.a; ! 1766: ! 1767: baz.foo.a = i & 128 ? 1 : 0; ! 1768: baz.foo.b = i & 64 ? 1 : 0; ! 1769: baz.foo.c = i & 32 ? 1 : 0; ! 1770: baz.foo.d = i & 16 ? 1 : 0; ! 1771: baz.foo.e = i & 8 ? 1 : 0; ! 1772: baz.foo.f = i & 4 ? 1 : 0; ! 1773: baz.foo.g = i & 2 ? 1 : 0; ! 1774: baz.foo.h = i & 1 ? 1 : 0; ! 1775: lorestab_l[i][0] = baz.bar.a; ! 1776: lorestab_l[i][1] = baz.bar.b; ! 1777: } ! 1778: ! 1779: for (i = 0; i < 256; i++) { ! 1780: baz.foo.a = i & 128 ? 1 : 0; ! 1781: baz.foo.b = i & 64 ? 1 : 0; ! 1782: baz.foo.c = i & 32 ? 1 : 0; ! 1783: baz.foo.d = i & 16 ? 1 : 0; ! 1784: baz.foo.e = i & 8 ? 1 : 0; ! 1785: baz.foo.f = i & 4 ? 1 : 0; ! 1786: baz.foo.g = i & 2 ? 1 : 0; ! 1787: baz.foo.h = i & 1 ? 1 : 0; ! 1788: hirestab_h[i][0] = baz.bar.a; ! 1789: hirestab_h[i][1] = baz.bar.b; ! 1790: ! 1791: baz.foo.a = i & 128 ? 1 : 0; ! 1792: baz.foo.b = i & 128 ? 1 : 0; ! 1793: baz.foo.c = i & 64 ? 1 : 0; ! 1794: baz.foo.d = i & 64 ? 1 : 0; ! 1795: baz.foo.e = i & 32 ? 1 : 0; ! 1796: baz.foo.f = i & 32 ? 1 : 0; ! 1797: baz.foo.g = i & 16 ? 1 : 0; ! 1798: baz.foo.h = i & 16 ? 1 : 0; ! 1799: baz.foo.i = i & 8 ? 1 : 0; ! 1800: baz.foo.j = i & 8 ? 1 : 0; ! 1801: baz.foo.k = i & 4 ? 1 : 0; ! 1802: baz.foo.l = i & 4 ? 1 : 0; ! 1803: baz.foo.m = i & 2 ? 1 : 0; ! 1804: baz.foo.n = i & 2 ? 1 : 0; ! 1805: baz.foo.o = i & 1 ? 1 : 0; ! 1806: baz.foo.p = i & 1 ? 1 : 0; ! 1807: lorestab_h[i][0] = baz.bar.a; ! 1808: lorestab_h[i][1] = baz.bar.b; ! 1809: lorestab_h[i][2] = baz.bar.c; ! 1810: lorestab_h[i][3] = baz.bar.d; ! 1811: } ! 1812: } ! 1813: ! 1814: static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit) ! 1815: { ! 1816: ULONG *pixptr = (ULONG *)dp; ! 1817: ! 1818: *pixptr |= hirestab_h[data >> 8][0] << bit; ! 1819: *(pixptr+1) |= hirestab_h[data >> 8][1] << bit; ! 1820: *(pixptr+2) |= hirestab_h[data & 255][0] << bit; ! 1821: *(pixptr+3) |= hirestab_h[data & 255][1] << bit; ! 1822: } ! 1823: ! 1824: static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit) ! 1825: { ! 1826: ULONG *pixptr = (ULONG *)dp; ! 1827: ! 1828: *pixptr |= lorestab_h[data >> 8][0] << bit; ! 1829: *(pixptr+1) |= lorestab_h[data >> 8][1] << bit; ! 1830: *(pixptr+2) |= lorestab_h[data >> 8][2] << bit; ! 1831: *(pixptr+3) |= lorestab_h[data >> 8][3] << bit; ! 1832: *(pixptr+4) |= lorestab_h[data & 255][0] << bit; ! 1833: *(pixptr+5) |= lorestab_h[data & 255][1] << bit; ! 1834: *(pixptr+6) |= lorestab_h[data & 255][2] << bit; ! 1835: *(pixptr+7) |= lorestab_h[data & 255][3] << bit; ! 1836: } ! 1837: ! 1838: static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit) ! 1839: { ! 1840: ULONG *pixptr = (ULONG *)dp; ! 1841: ! 1842: *pixptr = hirestab_h[data >> 8][0] << bit; ! 1843: *(pixptr+1) = hirestab_h[data >> 8][1] << bit; ! 1844: *(pixptr+2) = hirestab_h[data & 255][0] << bit; ! 1845: *(pixptr+3) = hirestab_h[data & 255][1] << bit; ! 1846: } ! 1847: ! 1848: static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit) ! 1849: { ! 1850: ULONG *pixptr = (ULONG *)dp; ! 1851: ! 1852: *pixptr = lorestab_h[data >> 8][0] << bit; ! 1853: *(pixptr+1) = lorestab_h[data >> 8][1] << bit; ! 1854: *(pixptr+2) = lorestab_h[data >> 8][2] << bit; ! 1855: *(pixptr+3) = lorestab_h[data >> 8][3] << bit; ! 1856: *(pixptr+4) = lorestab_h[data & 255][0] << bit; ! 1857: *(pixptr+5) = lorestab_h[data & 255][1] << bit; ! 1858: *(pixptr+6) = lorestab_h[data & 255][2] << bit; ! 1859: *(pixptr+7) = lorestab_h[data & 255][3] << bit; ! 1860: } ! 1861: ! 1862: static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit) ! 1863: { ! 1864: ULONG *pixptr = (ULONG *)dp; ! 1865: ! 1866: *pixptr |= hirestab_l[data >> 8][0] << bit; ! 1867: *(pixptr+1) |= hirestab_l[data & 255][0] << bit; ! 1868: } ! 1869: ! 1870: static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit) ! 1871: { ! 1872: ULONG *pixptr = (ULONG *)dp; ! 1873: ! 1874: *pixptr |= lorestab_l[data >> 8][0] << bit; ! 1875: *(pixptr+1) |= lorestab_l[data >> 8][1] << bit; ! 1876: *(pixptr+2) |= lorestab_l[data & 255][0] << bit; ! 1877: *(pixptr+3) |= lorestab_l[data & 255][1] << bit; ! 1878: } ! 1879: ! 1880: static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit) ! 1881: { ! 1882: ULONG *pixptr = (ULONG *)dp; ! 1883: ! 1884: *pixptr = hirestab_l[data >> 8][0] << bit; ! 1885: *(pixptr+1) = hirestab_l[data & 255][0] << bit; ! 1886: } ! 1887: ! 1888: static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit) ! 1889: { ! 1890: ULONG *pixptr = (ULONG *)dp; ! 1891: ! 1892: *pixptr = lorestab_l[data >> 8][0] << bit; ! 1893: *(pixptr+1) = lorestab_l[data >> 8][1] << bit; ! 1894: *(pixptr+2) = lorestab_l[data & 255][0] << bit; ! 1895: *(pixptr+3) = lorestab_l[data & 255][1] << bit; ! 1896: } ! 1897: ! 1898: #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \ ! 1899: int i; \ ! 1900: unsigned int bpldat1; \ ! 1901: UWORD data; \ ! 1902: unsigned int bpldat2 = 0; \ ! 1903: for (i = plflinelen; i > 0; i -= LL_SUB) { \ ! 1904: bpldat1 = bpldat2; \ ! 1905: bpldat2 = (*POINTER << 8) | *(POINTER+1); \ ! 1906: POINTER+=2; \ ! 1907: data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \ ! 1908: FUNC(data, app, MULT); \ ! 1909: app += P_ADD; \ ! 1910: } \ ! 1911: data = bpldat2 << (16 - DELAY); \ ! 1912: FUNC(data, app, MULT); \ ! 1913: } ! 1914: ! 1915: #if 1 ! 1916: static void pfield_doline_h(void) ! 1917: { ! 1918: int xpos = plfstrt * 4 - 0x60; ! 1919: int spr, sprites_seen; ! 1920: ! 1921: if (bplhires) { ! 1922: if (bplplanecnt > 0) { ! 1923: int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0); ! 1924: int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0); ! 1925: int delay1 = 2*(bpldelay1 & 7); ! 1926: int delay2 = 2*(bpldelay2 & 7); ! 1927: unsigned char *app = pixdata.apixels + xpos1; ! 1928: ! 1929: DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_hires_h, delay1, 4, 16); ! 1930: if (bplplanecnt > 2) { ! 1931: app = pixdata.apixels + xpos1; ! 1932: DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_hires_h, delay1, 4, 16); ! 1933: } ! 1934: #if AGA_CHIPSET == 1 ! 1935: if (bplplanecnt > 4) { ! 1936: app = pixdata.apixels + xpos1; ! 1937: DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_hires_h, delay1, 4, 16); ! 1938: } ! 1939: if (bplplanecnt > 6) { ! 1940: app = pixdata.apixels + xpos1; ! 1941: DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_hires_h, delay1, 4, 16); ! 1942: } ! 1943: #endif ! 1944: if (bplplanecnt > 1) { ! 1945: app = pixdata.apixels + xpos2; ! 1946: DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_hires_h, delay2, 4, 16); ! 1947: } ! 1948: if (bplplanecnt > 3) { ! 1949: app = pixdata.apixels + xpos2; ! 1950: DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_hires_h, delay2, 4, 16); ! 1951: } ! 1952: #if AGA_CHIPSET == 1 ! 1953: if (bplplanecnt > 5) { ! 1954: app = pixdata.apixels + xpos2; ! 1955: DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_hires_h, delay2, 4, 16); ! 1956: } ! 1957: if (bplplanecnt > 7) { ! 1958: app = pixdata.apixels + xpos2; ! 1959: DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_hires_h, delay2, 4, 16); ! 1960: } ! 1961: #endif ! 1962: } else { ! 1963: memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); ! 1964: } ! 1965: } else { ! 1966: if (bplplanecnt > 0) { ! 1967: int x = xpos + 32; ! 1968: unsigned char *app = pixdata.apixels + x; ! 1969: ! 1970: DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_lores_h, bpldelay1, 8, 32); ! 1971: if (bplplanecnt > 2) { ! 1972: app = pixdata.apixels + x; ! 1973: DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_lores_h, bpldelay1, 8, 32); ! 1974: } ! 1975: if (bplplanecnt > 4) { ! 1976: app = pixdata.apixels + x; ! 1977: DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_lores_h, bpldelay1, 8, 32); ! 1978: } ! 1979: #if AGA_CHIPSET == 1 ! 1980: if (bplplanecnt > 6) { ! 1981: app = pixdata.apixels + x; ! 1982: DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_lores_h, bpldelay1, 8, 32); ! 1983: } ! 1984: #endif ! 1985: if (bplplanecnt > 1) { ! 1986: app = pixdata.apixels + x; ! 1987: DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_lores_h, bpldelay2, 8, 32); ! 1988: } ! 1989: if (bplplanecnt > 3) { ! 1990: app = pixdata.apixels + x; ! 1991: DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_lores_h, bpldelay2, 8, 32); ! 1992: } ! 1993: if (bplplanecnt > 5) { ! 1994: app = pixdata.apixels + x; ! 1995: DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_lores_h, bpldelay2, 8, 32); ! 1996: } ! 1997: #if AGA_CHIPSET == 1 ! 1998: if (bplplanecnt > 7) { ! 1999: app = pixdata.apixels + x; ! 2000: DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_lores_h, bpldelay2, 8, 32); ! 2001: } ! 2002: #endif ! 2003: } else { ! 2004: memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); ! 2005: } ! 2006: } ! 2007: ! 2008: decode_ham6 (16,812); ! 2009: ! 2010: linetoscreen = 1; ! 2011: sprites_seen = 0; ! 2012: ! 2013: for(spr = 7; spr >= 0; spr--) { ! 2014: if (bpl_info.sprarmed[spr]) { ! 2015: int sprxp = ((bpl_info.sprpos[spr] & 0xFF) * 4) - 0x60 + (bpl_info.sprctl[spr] & 1)*2; ! 2016: int i; ! 2017: /* Ugh. Nasty bug. Let's rather lose some sprites than trash ! 2018: * memory. */ ! 2019: if (sprxp >= 0) { ! 2020: if (!sprites_seen) { ! 2021: sprites_seen = 1; ! 2022: memset(spixstate,0,sizeof spixstate); ! 2023: } ! 2024: pfield_sprite (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr], 0); ! 2025: } ! 2026: } ! 2027: } ! 2028: } ! 2029: #endif ! 2030: static void pfield_doline_l(void) ! 2031: { ! 2032: int xpos = plfstrt * 2 - 0x30; ! 2033: int spr; ! 2034: int sprites_seen; ! 2035: ! 2036: if (bplhires) { ! 2037: if (bplplanecnt > 0) { ! 2038: int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0); ! 2039: int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0); ! 2040: int delay1 = (bpldelay1 & 7) * 2; ! 2041: int delay2 = (bpldelay2 & 7) * 2; ! 2042: unsigned char *app = pixdata.apixels + xpos1; ! 2043: ! 2044: DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_hires_l, delay1, 4, 8); ! 2045: if (bplplanecnt > 2) { ! 2046: app = pixdata.apixels + xpos1; ! 2047: DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_hires_l, delay1, 4, 8); ! 2048: } ! 2049: #if AGA_CHIPSET == 1 ! 2050: if (bplplanecnt > 4) { ! 2051: app = pixdata.apixels + xpos1; ! 2052: DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_hires_l, delay1, 4, 8); ! 2053: } ! 2054: if (bplplanecnt > 6) { ! 2055: app = pixdata.apixels + xpos1; ! 2056: DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_hires_l, delay1, 4, 8); ! 2057: } ! 2058: #endif ! 2059: if (bplplanecnt > 1) { ! 2060: app = pixdata.apixels + xpos2; ! 2061: DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_hires_l, delay2, 4, 8); ! 2062: } ! 2063: if (bplplanecnt > 3) { ! 2064: app = pixdata.apixels + xpos2; ! 2065: DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_hires_l, delay2, 4, 8); ! 2066: } ! 2067: #if AGA_CHIPSET == 1 ! 2068: if (bplplanecnt > 5) { ! 2069: app = pixdata.apixels + xpos2; ! 2070: DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_hires_l, delay2, 4, 8); ! 2071: } ! 2072: if (bplplanecnt > 7) { ! 2073: app = pixdata.apixels + xpos2; ! 2074: DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_hires_l, delay2, 4, 8); ! 2075: } ! 2076: #endif ! 2077: } else { ! 2078: memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); ! 2079: } ! 2080: } else { ! 2081: if (bplplanecnt > 0) { ! 2082: int x = xpos + 16; ! 2083: int delay1 = bpldelay1; ! 2084: int delay2 = bpldelay2; ! 2085: unsigned char *app = pixdata.apixels + x; ! 2086: DO_ONE_PLANE(r_bplpt[0], 0, pfield_setword_lores_l, delay1, 8, 16); ! 2087: if (bplplanecnt > 2) { ! 2088: app = pixdata.apixels + x; ! 2089: DO_ONE_PLANE(r_bplpt[2], 2, pfield_orword_lores_l, delay1, 8, 16); ! 2090: } ! 2091: if (bplplanecnt > 4) { ! 2092: app = pixdata.apixels + x; ! 2093: DO_ONE_PLANE(r_bplpt[4], 4, pfield_orword_lores_l, delay1, 8, 16); ! 2094: } ! 2095: #if AGA_CHIPSET == 1 ! 2096: if (bplplanecnt > 6) { ! 2097: app = pixdata.apixels + x; ! 2098: DO_ONE_PLANE(r_bplpt[6], 6, pfield_orword_lores_l, delay1, 8, 16); ! 2099: } ! 2100: #endif ! 2101: if (bplplanecnt > 1) { ! 2102: app = pixdata.apixels + x; ! 2103: DO_ONE_PLANE(r_bplpt[1], 1, pfield_orword_lores_l, delay2, 8, 16); ! 2104: } ! 2105: if (bplplanecnt > 3) { ! 2106: app = pixdata.apixels + x; ! 2107: DO_ONE_PLANE(r_bplpt[3], 3, pfield_orword_lores_l, delay2, 8, 16); ! 2108: } ! 2109: if (bplplanecnt > 5) { ! 2110: app = pixdata.apixels + x; ! 2111: DO_ONE_PLANE(r_bplpt[5], 5, pfield_orword_lores_l, delay2, 8, 16); ! 2112: } ! 2113: #if AGA_CHIPSET == 1 ! 2114: if (bplplanecnt > 7) { ! 2115: app = pixdata.apixels + x; ! 2116: DO_ONE_PLANE(r_bplpt[7], 7, pfield_orword_lores_l, delay2, 8, 16); ! 2117: } ! 2118: #endif ! 2119: } else { ! 2120: memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); ! 2121: } ! 2122: } ! 2123: ! 2124: decode_ham6 (8,406); ! 2125: ! 2126: linetoscreen = 1; ! 2127: sprites_seen = 0; ! 2128: ! 2129: for(spr = 7; spr >= 0; spr--) { ! 2130: if (bpl_info.sprarmed[spr]) { ! 2131: int sprxp = ((bpl_info.sprpos[spr] & 0xFF) * 2) - 0x30 + (bpl_info.sprctl[spr] & 1); ! 2132: int i; ! 2133: /* Ugh. Nasty bug. Let's rather lose some sprites than trash ! 2134: * memory. */ ! 2135: if (sprxp >= 0) { ! 2136: if (!sprites_seen) { ! 2137: sprites_seen = 1; ! 2138: memset(spixstate,0,sizeof spixstate); ! 2139: } ! 2140: pfield_sprite (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr], 1); ! 2141: } ! 2142: } ! 2143: } ! 2144: } ! 2145: ! 2146: static int bpl_data_differs(UBYTE *data, UBYTE *r_addr, int nbytes) ! 2147: { ! 2148: return memcmpy(data, r_addr, nbytes); ! 2149: } ! 2150: ! 2151: static __inline__ int bplinfo_differs(struct bplinfo *a, struct bplinfo *b) ! 2152: { ! 2153: int ncolors; ! 2154: int i; ! 2155: if (a->bplcon0 != b->bplcon0 ! 2156: || a->bplcon1 != b->bplcon1 ! 2157: || a->bplcon2 != b->bplcon2 ! 2158: || a->bplcon3 != b->bplcon3 ! 2159: || a->bplcon4 != b->bplcon4 ! 2160: || a->diwstrt != b->diwstrt ! 2161: || a->diwstop != b->diwstop ! 2162: || a->ddfstrt != b->ddfstrt ! 2163: || a->ddfstop != b->ddfstop) ! 2164: return 1; ! 2165: ! 2166: #if 1 ! 2167: /* This sometimes loses for sprite colors */ ! 2168: ncolors = 1 << ((a->bplcon0 & 0x7000) >> 12); ! 2169: if (ncolors == 64) ! 2170: ncolors = (a->bplcon0 & 0x800) ? 16 : 32; ! 2171: for (i = 0; i < ncolors; i++) ! 2172: if (a->color_regs[i] != b->color_regs[i]) ! 2173: return 1; ! 2174: #else ! 2175: /* ... and this will lose badly on few-color screens when we implement ! 2176: * AGA. ! 2177: */ ! 2178: if (memcmp(a->color_regs, b->color_regs, sizeof a->color_regs) != 0) ! 2179: return 1; ! 2180: #endif ! 2181: for (i = 0; i < 8; i++) { ! 2182: if (a->sprarmed[i] != b->sprarmed[i]) ! 2183: return 1; ! 2184: if (a->sprarmed[i] ! 2185: && (a->sprctl[i] != b->sprctl[i] ! 2186: || a->sprpos[i] != b->sprpos[i] ! 2187: || a->sprdata[i] != b->sprdata[i] ! 2188: || a->sprdatb[i] != b->sprdatb[i])) ! 2189: return 1; ! 2190: } ! 2191: return 0; ! 2192: } ! 2193: ! 2194: static void pfield_doline(void) ! 2195: { ! 2196: int bytecount = plflinelen / (bplhires ? 4 : 8) * 2; ! 2197: int drawit = 0; ! 2198: int i; ! 2199: ! 2200: if (vpos < plffirstline || vpos >= plflastline) ! 2201: return; ! 2202: ! 2203: if (!dmaen(0x100) || !pfield_linedmaon) { ! 2204: line_in_border = 1; ! 2205: return; ! 2206: } ! 2207: ! 2208: for (i = 0; i < bplplanecnt; i++) { ! 2209: r_bplpt[i] = pfield_xlateptr(bplpt[i], bytecount); ! 2210: if (r_bplpt[i] == NULL) ! 2211: return; ! 2212: } ! 2213: ! 2214: #if SMART_UPDATE == 1 ! 2215: drawit = bplinfo_differs(&bpl_info, &linedescr[next_lineno].bpl_info); ! 2216: if (drawit) { ! 2217: linedescr[next_lineno].bpl_info = bpl_info; ! 2218: } ! 2219: drawit |= !linedescr[next_lineno].linedata_valid | frame_redraw_necessary; ! 2220: ! 2221: if (bytecount <= MAX_WORDS_PER_LINE * 2) { ! 2222: linedescr[next_lineno].linedata_valid = 1; ! 2223: for (i = 0; i < bplplanecnt; i++) ! 2224: drawit |= bpl_data_differs(line_data[next_lineno][i],r_bplpt[i], ! 2225: bytecount); ! 2226: ! 2227: } else { ! 2228: linedescr[next_lineno].linedata_valid = 0; ! 2229: } ! 2230: #endif ! 2231: ! 2232: pfield_modulos(bytecount); ! 2233: ! 2234: #if SMART_UPDATE != 0 ! 2235: if (!drawit) ! 2236: return; ! 2237: #endif ! 2238: ! 2239: if (use_lores) ! 2240: pfield_doline_l(); ! 2241: else ! 2242: pfield_doline_h(); ! 2243: } ! 2244: ! 2245: static void pfield_doline_slow(int currhp) ! 2246: { ! 2247: int xpos = PIXEL_XPOS(currhp); ! 2248: ! 2249: if (vpos < plffirstline || vpos >= plflastline) ! 2250: return; ! 2251: ! 2252: if (currhp == plfstrt) ! 2253: slowline_nextpos = currhp; ! 2254: ! 2255: if (currhp == slowline_nextpos) { ! 2256: if (slowline_linepos >= plflinelen) { ! 2257: /* The modulos must get added at exactly this point. */ ! 2258: pfield_modulos(0); ! 2259: slowline_nextpos = -1; ! 2260: } else { ! 2261: slowline_nextpos += bplhires ? 4 : 8; ! 2262: slowline_linepos += bplhires ? 4 : 8; ! 2263: ! 2264: /* Hmmmm..... ! 2265: * In theory, we could use the fast pfield_doline functions even ! 2266: * in this case. We only need to do sprites, ham decoding and ! 2267: * the line_to_scr stuff cycle-per-cycle. However, we would no ! 2268: * longer be able to emulate tricks that switch lores/hires in ! 2269: * the middle of a line, but I'm not sure whether this sort of ! 2270: * thing actually works currently and whether it's worthwhile. ! 2271: */ ! 2272: ! 2273: pfield_fetchdata(); ! 2274: ! 2275: if (use_lores) ! 2276: pfield_doline_slow_l (currhp); ! 2277: else ! 2278: pfield_doline_slow_h (currhp); ! 2279: /* @@@ need to test this */ ! 2280: decode_ham6 (xpos, PIXEL_XPOS(slowline_nextpos)); ! 2281: } ! 2282: } ! 2283: if (currhp > 48) { ! 2284: int spr; ! 2285: for(spr = 7; spr >= 0; spr--) { ! 2286: if (bpl_info.sprarmed[spr] && currhp == (bpl_info.sprpos[spr] & 0xFF)) { ! 2287: int sprxp = xpos + (bpl_info.sprctl[spr] & 1) * (use_lores ? 1 : 2); ! 2288: pfield_sprite (spr, sprxp, bpl_info.sprdata[spr], bpl_info.sprdatb[spr], use_lores); ! 2289: } ! 2290: } ! 2291: } ! 2292: } ! 2293: ! 2294: static int first_drawn_line, last_drawn_line; ! 2295: static int first_block_line, last_block_line; ! 2296: ! 2297: static void init_frame (void) ! 2298: { ! 2299: int i; ! 2300: int maxpos = use_lores ? 400 : 800; ! 2301: int old_pmds = prev_max_diwstop; ! 2302: ! 2303: if (max_diwstop == 0) ! 2304: max_diwstop = diwlastword; ! 2305: ! 2306: if (max_diwstop < (use_lores ? 320 : 640) || max_diwstop > maxpos) ! 2307: prev_max_diwstop = maxpos; ! 2308: else ! 2309: prev_max_diwstop = max_diwstop; ! 2310: ! 2311: max_diwstop = 0; ! 2312: ! 2313: memset(spron, 0, sizeof spron); ! 2314: memset(bpl_info.sprpos, 0, sizeof bpl_info.sprpos); ! 2315: memset(bpl_info.sprctl, 0, sizeof bpl_info.sprctl); ! 2316: last_drawn_line = 0; ! 2317: first_drawn_line = 32767; ! 2318: ! 2319: first_block_line = last_block_line = -2; ! 2320: calc_adjustment(); ! 2321: if (frame_redraw_necessary) ! 2322: frame_redraw_necessary--; ! 2323: ! 2324: if (old_pmds != prev_max_diwstop) { ! 2325: frame_redraw_necessary |= (bpl_info.bplcon0 & 4 ? 2 : 1); ! 2326: } ! 2327: } ! 2328: ! 2329: /* ! 2330: * A raster line has been built in the graphics buffer. Tell the graphics code ! 2331: * to do anything necessary to display it. ! 2332: */ ! 2333: ! 2334: static void do_flush_line (int lineno) ! 2335: { ! 2336: if (lineno < first_drawn_line) ! 2337: first_drawn_line = lineno; ! 2338: if (lineno > last_drawn_line) ! 2339: last_drawn_line = lineno; ! 2340: ! 2341: if (gfxvidinfo.maxblocklines == 0) ! 2342: flush_line(lineno); ! 2343: else { ! 2344: if ((last_block_line+1) != lineno) { ! 2345: if (first_block_line != -2) ! 2346: flush_block (first_block_line, last_block_line); ! 2347: first_block_line = lineno; ! 2348: } ! 2349: last_block_line = lineno; ! 2350: if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) { ! 2351: flush_block (first_block_line, last_block_line); ! 2352: first_block_line = last_block_line = -2; ! 2353: } ! 2354: } ! 2355: } ! 2356: ! 2357: /* ! 2358: * One Amiga frame has been finished. Tell the graphics code about it. ! 2359: * Note that the actual flush_scren() call is a no-op for all reasonable ! 2360: * systems. ! 2361: */ ! 2362: ! 2363: static void do_flush_screen (int start, int stop) ! 2364: { ! 2365: if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) { ! 2366: flush_block (first_block_line, last_block_line); ! 2367: } ! 2368: if (start <= stop) ! 2369: flush_screen (start, stop); ! 2370: } ! 2371: ! 2372: static void setdontcare(void) ! 2373: { ! 2374: fprintf(stderr, "Don't care mouse mode set\n"); ! 2375: mousestate = dont_care_mouse; ! 2376: lastspr0x = lastmx; lastspr0y = lastmy; ! 2377: mstepx = defstepx; mstepy = defstepy; ! 2378: } ! 2379: ! 2380: static void setfollow(void) ! 2381: { ! 2382: fprintf(stderr, "Follow sprite mode set\n"); ! 2383: mousestate = follow_mouse; ! 2384: lastdiffx = lastdiffy = 0; ! 2385: sprvbfl = 0; ! 2386: spr0ctl=spr0pos = 0; ! 2387: mstepx = defstepx; mstepy = defstepy; ! 2388: } ! 2389: ! 2390: void togglemouse(void) ! 2391: { ! 2392: switch(mousestate) { ! 2393: case dont_care_mouse: setfollow(); break; ! 2394: case follow_mouse: setdontcare(); break; ! 2395: default: break; /* Nnnnnghh! */ ! 2396: } ! 2397: } ! 2398: ! 2399: static __inline__ int adjust(int val) ! 2400: { ! 2401: if (val>127) ! 2402: return 127; ! 2403: else if (val<-127) ! 2404: return -127; ! 2405: return val; ! 2406: } ! 2407: ! 2408: static void do_mouse_hack(void) ! 2409: { ! 2410: int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1); ! 2411: int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1; ! 2412: int diffx, diffy; ! 2413: ! 2414: switch (mousestate) { ! 2415: case normal_mouse: ! 2416: diffx = lastmx - lastsampledmx; ! 2417: diffy = lastmy - lastsampledmy; ! 2418: if (!newmousecounters) { ! 2419: if (diffx > 127) diffx = 127; ! 2420: if (diffx < -127) diffx = -127; ! 2421: joy0x += diffx; ! 2422: if (diffy > 127) diffy = 127; ! 2423: if (diffy < -127) diffy = -127; ! 2424: joy0y += diffy; ! 2425: } ! 2426: lastsampledmx += diffx; lastsampledmy += diffy; ! 2427: break; ! 2428: ! 2429: case dont_care_mouse: ! 2430: diffx = adjust (((lastmx-lastspr0x) * mstepx) >> 16); ! 2431: diffy = adjust (((lastmy-lastspr0y) * mstepy) >> 16); ! 2432: lastspr0x=lastmx; lastspr0y=lastmy; ! 2433: joy0x+=diffx; joy0y+=diffy; ! 2434: break; ! 2435: ! 2436: case follow_mouse: ! 2437: if (sprvbfl && sprvbfl-- >1) { ! 2438: int mousexpos, mouseypos; ! 2439: ! 2440: if ((lastdiffx > docal || lastdiffx < -docal) && lastspr0x != spr0x ! 2441: && spr0x > plfstrt*4 + 34 + xcaloff && spr0x < plfstop*4 - xcaloff) ! 2442: { ! 2443: int val = (lastdiffx << 16) / (spr0x - lastspr0x); ! 2444: if (val>=0x8000) mstepx=(mstepx*(calweight-1)+val)/calweight; ! 2445: } ! 2446: if ((lastdiffy > docal || lastdiffy < -docal) && lastspr0y != spr0y ! 2447: && spr0y>plffirstline+ycaloff && spr0y<plflastline-ycaloff) ! 2448: { ! 2449: int val = (lastdiffy<<16) / (spr0y-lastspr0y); ! 2450: if (val>=0x8000) mstepy=(mstepy*(calweight-1)+val)/calweight; ! 2451: } ! 2452: mousexpos = lastmx; ! 2453: if (gfxvidinfo.x_adjust) ! 2454: mousexpos += gfxvidinfo.x_adjust; ! 2455: mouseypos = lastmy; ! 2456: ! 2457: if(!correct_aspect) ! 2458: mouseypos *= 2; ! 2459: if(use_lores) ! 2460: mousexpos *= 2; ! 2461: if (gfxvidinfo.x_adjust) ! 2462: mousexpos -= 16; ! 2463: ! 2464: diffx = adjust ((((mousexpos + 0x70 + xoffs - spr0x) & ~1) * mstepx) >> 16); ! 2465: diffy = adjust ((((mouseypos + yoffs - spr0y+minfirstline*2) & ~1) * mstepy) >> 16); ! 2466: lastspr0x=spr0x; lastspr0y=spr0y; ! 2467: lastdiffx=diffx; lastdiffy=diffy; ! 2468: joy0x+=diffx; joy0y+=diffy; ! 2469: } ! 2470: break; ! 2471: } ! 2472: } ! 2473: ! 2474: static void vsync_handler(void) ! 2475: { ! 2476: UWORD dir; ! 2477: int button; ! 2478: ! 2479: handle_events(); ! 2480: getjoystate(&joy0dir, &joy0button); ! 2481: ! 2482: do_mouse_hack(); ! 2483: ! 2484: INTREQ(0x8020); ! 2485: if (bpl_info.bplcon0 & 4) lof ^= 0x8000; ! 2486: COPJMP1(0); ! 2487: ! 2488: if (framecnt == 0) ! 2489: do_flush_screen (first_drawn_line, last_drawn_line); ! 2490: ! 2491: count_frame(); ! 2492: init_frame(); ! 2493: #ifdef HAVE_GETTIMEOFDAY ! 2494: { ! 2495: struct timeval tv; ! 2496: unsigned long int newtime; ! 2497: ! 2498: gettimeofday(&tv,NULL); ! 2499: newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000; ! 2500: ! 2501: if (!bogusframe) { ! 2502: frametime += newtime - msecs; ! 2503: timeframes++; ! 2504: } ! 2505: msecs = newtime; ! 2506: bogusframe = 0; ! 2507: } ! 2508: #endif ! 2509: CIA_vsync_handler(); ! 2510: } ! 2511: ! 2512: static void hsync_handler(void) ! 2513: { ! 2514: int lineno = vpos - minfirstline; ! 2515: int lineisdouble = 0; ! 2516: int line_was_doubled = 0; ! 2517: ! 2518: do_sprites(vpos, maxhpos); ! 2519: last_sprite = 0; ! 2520: ! 2521: if (correct_aspect) { ! 2522: lineno *= 2; ! 2523: if (bpl_info.bplcon0 & 4) { ! 2524: if(!lof) { ! 2525: lineno++; ! 2526: } ! 2527: } else { ! 2528: lineisdouble = 1; ! 2529: } ! 2530: } ! 2531: ! 2532: eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles; ! 2533: eventtab[ev_hsync].oldcycles = cycles; ! 2534: CIA_hsync_handler(); ! 2535: ! 2536: if (produce_sound > 0) { ! 2537: int nr; ! 2538: /* Sound data is fetched at the beginning of each line */ ! 2539: for (nr = 0; nr < 4; nr++) { ! 2540: struct audio_channel_data *cdp = audio_channel + nr; ! 2541: ! 2542: if (cdp->data_written == 2) { ! 2543: cdp->data_written = 0; ! 2544: cdp->nextdat = chipmem_bank.wget(cdp->pt); ! 2545: cdp->pt += 2; ! 2546: if (cdp->state == 2 || cdp->state == 3) { ! 2547: if (cdp->wlen == 1) { ! 2548: cdp->pt = cdp->lc; ! 2549: cdp->wlen = cdp->len; ! 2550: cdp->intreq2 = 1; ! 2551: } else ! 2552: cdp->wlen--; ! 2553: } ! 2554: } ! 2555: } ! 2556: } ! 2557: ! 2558: if (framecnt == 0 && vpos >= minfirstline && lineno < gfxvidinfo.maxline) { ! 2559: if (vpos >= plffirstline && vpos < plflastline) ! 2560: { ! 2561: /* Finish the line, if we started doing it with the slow update. ! 2562: * Otherwise, draw it entirely. */ ! 2563: if (pfield_fullline) { ! 2564: if (!pfield_linedone) { ! 2565: /* This can turn on line_in_border if DMA is off */ ! 2566: pfield_doline(); ! 2567: } ! 2568: if (linetoscreen) ! 2569: pfield_do_linetoscr_full (line_was_doubled = lineisdouble); ! 2570: } else { ! 2571: int i; ! 2572: for(i = pfield_lastpart_hpos; i < maxhpos; i++) ! 2573: pfield_doline_slow(i); ! 2574: pfield_do_linetoscr(slowline_lasttoscr, maxhpos); ! 2575: /* The COLOR routine masks off the high nibble. This means ! 2576: * that there will never be 0xFFFF in color_regs[0], and this ! 2577: * means that the line will be drawn completely the next time ! 2578: * we get into pfield_doline() ! 2579: */ ! 2580: linedescr[lineno].bpl_info.color_regs[0] = 0xFFFF; ! 2581: linetoscreen = 1; ! 2582: } ! 2583: } else ! 2584: line_in_border = 1; ! 2585: ! 2586: if (line_in_border && ! 2587: (!linedescr[lineno].inborder ! 2588: || linedescr[lineno].bordercol != acolors[0])) ! 2589: { ! 2590: linedescr[lineno].bordercol = acolors[0]; ! 2591: linedescr[lineno].linedata_valid = 0; ! 2592: ! 2593: fill_line (lineno); ! 2594: linetoscreen = 1; ! 2595: } ! 2596: ! 2597: linedescr[lineno].inborder = line_in_border; ! 2598: ! 2599: if (linetoscreen) { ! 2600: #if AGA_CHIPSET == 1 ! 2601: switch (gfxvidinfo.pixbytes) { ! 2602: case 1: aga_translate8 (0, aga_lbufptr-aga_linebuf); break; ! 2603: case 2: aga_translate16 (0, aga_lbufptr-aga_linebuf); break; ! 2604: case 4: aga_translate32 (0, aga_lbufptr-aga_linebuf); break; ! 2605: } ! 2606: #endif ! 2607: do_flush_line (lineno); ! 2608: } ! 2609: if (lineisdouble) { ! 2610: int drawit = 0; ! 2611: ! 2612: if (linedescr[lineno].inborder != linedescr[lineno+1].inborder ! 2613: || (linedescr[lineno].inborder == 1 ! 2614: && linedescr[lineno].bordercol != linedescr[lineno+1].bordercol)) { ! 2615: drawit = 1; ! 2616: ! 2617: } else if (linedescr[lineno].inborder == 0 ! 2618: && (linetoscreen ! 2619: || (bplinfo_differs(&linedescr[lineno].bpl_info, ! 2620: &linedescr[lineno+1].bpl_info)))) { ! 2621: drawit = 1; ! 2622: } ! 2623: ! 2624: if (drawit) { ! 2625: linedescr[lineno+1].inborder = linedescr[lineno].inborder; ! 2626: linedescr[lineno+1].bordercol = linedescr[lineno].bordercol; ! 2627: #if SMART_UPDATE != 0 ! 2628: linedescr[lineno+1].bpl_info = linedescr[lineno].bpl_info; ! 2629: #endif ! 2630: if (!line_was_doubled) { ! 2631: if (line_in_border) ! 2632: fill_line (lineno+1); ! 2633: else ! 2634: memcpy (gfxvidinfo.bufmem + (lineno+1)*gfxvidinfo.rowbytes, ! 2635: gfxvidinfo.bufmem + lineno*gfxvidinfo.rowbytes, ! 2636: gfxvidinfo.rowbytes); ! 2637: } ! 2638: do_flush_line (lineno+1); ! 2639: } ! 2640: } ! 2641: } ! 2642: ! 2643: pfield_calclinedma(); ! 2644: ! 2645: if (++vpos == (maxvpos + (lof != 0))) { ! 2646: vpos = 0; ! 2647: vsync_handler(); ! 2648: } ! 2649: ! 2650: if (framecnt == 0) ! 2651: { ! 2652: lineno = vpos - minfirstline; ! 2653: ! 2654: if (correct_aspect) { ! 2655: lineno *= 2; ! 2656: if ((bpl_info.bplcon0 & 4) && !lof) { ! 2657: lineno++; ! 2658: } ! 2659: } ! 2660: xlinebuffer = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * lineno; ! 2661: aga_lbufptr = aga_linebuf; ! 2662: next_lineno = lineno; ! 2663: linetoscreen = 0; ! 2664: line_in_border = 0; ! 2665: pfield_fullline = 1; ! 2666: pfield_linedone = 0; ! 2667: pfield_lastpart_hpos = 0; ! 2668: } ! 2669: ! 2670: } ! 2671: ! 2672: void customreset(void) ! 2673: { ! 2674: int i; ! 2675: #ifdef HAVE_GETTIMEOFDAY ! 2676: struct timeval tv; ! 2677: #endif ! 2678: inhibit_frame = 0; ! 2679: expamem_reset(); ! 2680: CIA_reset(); ! 2681: cycles = 0; ! 2682: regs.spcflags &= SPCFLAG_BRK; ! 2683: ! 2684: last_sprite = 0; ! 2685: vpos = 0; ! 2686: lof = 0; ! 2687: next_lineno = 0; ! 2688: max_diwstop = 0; ! 2689: ! 2690: if (needmousehack()) { ! 2691: if (mousestate != follow_mouse) setfollow(); ! 2692: } else { ! 2693: mousestate = normal_mouse; ! 2694: } ! 2695: ! 2696: memset(spixstate, 0, sizeof(spixstate)); ! 2697: ! 2698: /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */ ! 2699: ! 2700: for (i = 0; i < numscrlines*2; i++) { ! 2701: linedescr[i].mnn = NULL; ! 2702: linedescr[i].linedata_valid = 0; ! 2703: linedescr[i].bpl_info.color_regs[0] = 0xFFFF; ! 2704: linedescr[i].bplpt[0] = (CPTR)-1; ! 2705: } ! 2706: ! 2707: xlinebuffer = gfxvidinfo.bufmem; ! 2708: ! 2709: dmacon = intena = 0; ! 2710: bltstate = BLT_done; ! 2711: copstate = COP_stop; ! 2712: copcon = 0; ! 2713: dskdmaen = 0; ! 2714: cycles = 0; ! 2715: ! 2716: memset(audio_channel, 0, sizeof audio_channel); ! 2717: ! 2718: bpl_info.bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */ ! 2719: bpl_info.bplcon3 = 0xC00; ! 2720: for(i = 0; i < ev_max; i++) { ! 2721: eventtab[i].active = 0; ! 2722: eventtab[i].oldcycles = 0; ! 2723: } ! 2724: copper_active = 0; ! 2725: eventtab[ev_cia].handler = CIA_handler; ! 2726: eventtab[ev_copper].handler = do_copper; ! 2727: eventtab[ev_hsync].handler = hsync_handler; ! 2728: eventtab[ev_hsync].evtime = maxhpos + cycles; ! 2729: eventtab[ev_hsync].active = 1; ! 2730: ! 2731: eventtab[ev_blitter].handler = blitter_handler; ! 2732: eventtab[ev_blitter].active = 0; ! 2733: eventtab[ev_diskblk].handler = diskblk_handler; ! 2734: eventtab[ev_diskblk].active = 0; ! 2735: eventtab[ev_diskindex].handler = diskindex_handler; ! 2736: eventtab[ev_diskindex].active = 0; ! 2737: #ifndef DONT_WANT_SOUND ! 2738: eventtab[ev_aud0].handler = aud0_handler; ! 2739: eventtab[ev_aud0].active = 0; ! 2740: eventtab[ev_aud1].handler = aud1_handler; ! 2741: eventtab[ev_aud1].active = 0; ! 2742: eventtab[ev_aud2].handler = aud2_handler; ! 2743: eventtab[ev_aud2].active = 0; ! 2744: eventtab[ev_aud3].handler = aud3_handler; ! 2745: eventtab[ev_aud3].active = 0; ! 2746: if (sound_available) { ! 2747: eventtab[ev_sample].active = 1; ! 2748: eventtab[ev_sample].evtime += cycles; ! 2749: eventtab[ev_sample].oldcycles = cycles; ! 2750: } else { ! 2751: eventtab[ev_sample].active = 0; ! 2752: } ! 2753: #endif ! 2754: events_schedule(); ! 2755: ! 2756: init_frame(); ! 2757: #ifdef HAVE_GETTIMEOFDAY ! 2758: gettimeofday(&tv,NULL); ! 2759: seconds_base = tv.tv_sec; ! 2760: bogusframe = 1; ! 2761: #endif ! 2762: } ! 2763: ! 2764: void dumpcustom(void) ! 2765: { ! 2766: int i; ! 2767: fprintf(stderr, "DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(), ! 2768: intena, intreq, vpos, current_hpos()); ! 2769: if (timeframes) { ! 2770: fprintf(stderr, "Average frame time: %d ms [frames: %d time: %d]\n", ! 2771: frametime/timeframes, timeframes, frametime); ! 2772: } ! 2773: /*for (i=0; i<256; i++) if (blitcount[i]) fprintf(stderr, "minterm %x = %d\n",i,blitcount[i]); blitter debug */ ! 2774: } ! 2775: ! 2776: int intlev(void) ! 2777: { ! 2778: UWORD imask = intreq & intena; ! 2779: if (imask && (intena & 0x4000)){ ! 2780: if (imask & 0x2000) return 6; ! 2781: if (imask & 0x1800) return 5; ! 2782: if (imask & 0x0780) return 4; ! 2783: if (imask & 0x0070) return 3; ! 2784: if (imask & 0x0008) return 2; ! 2785: if (imask & 0x0007) return 1; ! 2786: } ! 2787: return -1; ! 2788: } ! 2789: ! 2790: void custom_init(void) ! 2791: { ! 2792: int num; ! 2793: if (needmousehack()) ! 2794: setfollow(); ! 2795: customreset(); ! 2796: for (num = 0; num < 256; num++) { ! 2797: int plane1 = (num & 1) | ((num >> 1) & 2) | ((num >> 2) & 4) | ((num >> 3) & 8); ! 2798: int plane2 = ((num >> 1) & 1) | ((num >> 2) & 2) | ((num >> 3) & 4) | ((num >> 4) & 8); ! 2799: dblpf_2nd1[num] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1; ! 2800: dblpf_2nd2[num] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2; ! 2801: dblpf_aga1[num] = plane1 == 0 ? plane2 : plane1; ! 2802: dblpf_aga2[num] = plane2 == 0 ? plane1 : plane2; ! 2803: if (plane2 > 0) plane2 += 8; ! 2804: dblpf_ind1[num] = plane1 == 0 ? plane2 : plane1; ! 2805: dblpf_ind2[num] = plane2 == 0 ? plane1 : plane2; ! 2806: ! 2807: lots_of_twos[num] = num == 0 ? 0 : 2; ! 2808: linear_map_256[num] = num; ! 2809: } ! 2810: build_blitfilltable(); ! 2811: gen_pfield_tables(); ! 2812: } ! 2813: ! 2814: /* Custom chip memory bank */ ! 2815: ! 2816: static ULONG custom_lget(CPTR) REGPARAM; ! 2817: static UWORD custom_wget(CPTR) REGPARAM; ! 2818: static UBYTE custom_bget(CPTR) REGPARAM; ! 2819: static void custom_lput(CPTR, ULONG) REGPARAM; ! 2820: static void custom_wput(CPTR, UWORD) REGPARAM; ! 2821: static void custom_bput(CPTR, UBYTE) REGPARAM; ! 2822: ! 2823: addrbank custom_bank = { ! 2824: default_alget, default_awget, ! 2825: custom_lget, custom_wget, custom_bget, ! 2826: custom_lput, custom_wput, custom_bput, ! 2827: default_xlate, default_check ! 2828: }; ! 2829: ! 2830: UWORD custom_wget(CPTR addr) ! 2831: { ! 2832: switch(addr & 0x1FE) { ! 2833: case 0x002: return DMACONR(); ! 2834: case 0x004: return VPOSR(); ! 2835: case 0x006: return VHPOSR(); ! 2836: ! 2837: case 0x008: return DSKDATR(); ! 2838: ! 2839: case 0x00A: return JOY0DAT(); ! 2840: case 0x00C: return JOY1DAT(); ! 2841: case 0x010: return ADKCONR(); ! 2842: ! 2843: case 0x012: return POT0DAT(); ! 2844: case 0x016: return POTGOR(); ! 2845: case 0x018: return SERDATR(); ! 2846: case 0x01A: return DSKBYTR(); ! 2847: case 0x01C: return INTENAR(); ! 2848: case 0x01E: return INTREQR(); ! 2849: ! 2850: #if AGA_CHIPSET == 1 ! 2851: case 0x07C: return 0xF8; ! 2852: #elif defined ECS_DENISE ! 2853: case 0x07C: return 0xFC; ! 2854: #endif ! 2855: default: ! 2856: custom_wput(addr,0); ! 2857: return 0xffff; ! 2858: } ! 2859: } ! 2860: ! 2861: UBYTE custom_bget(CPTR addr) ! 2862: { ! 2863: return custom_wget(addr & 0xfffe) >> (addr & 1 ? 0 : 8); ! 2864: } ! 2865: ! 2866: ULONG custom_lget(CPTR addr) ! 2867: { ! 2868: return ((ULONG)custom_wget(addr & 0xfffe) << 16) | custom_wget((addr+2) & 0xfffe); ! 2869: } ! 2870: ! 2871: void custom_wput(CPTR addr, UWORD value) ! 2872: { ! 2873: addr &= 0x1FE; ! 2874: cregs[addr>>1] = value; ! 2875: switch(addr) { ! 2876: case 0x020: DSKPTH(value); break; ! 2877: case 0x022: DSKPTL(value); break; ! 2878: case 0x024: DSKLEN(value); break; ! 2879: case 0x026: DSKDAT(value); break; ! 2880: ! 2881: case 0x02A: VPOSW(value); break; ! 2882: ! 2883: case 0x030: SERDAT(value); break; ! 2884: case 0x032: SERPER(value); break; ! 2885: ! 2886: case 0x040: BLTCON0(value); break; ! 2887: case 0x042: BLTCON1(value); break; ! 2888: ! 2889: case 0x044: BLTAFWM(value); break; ! 2890: case 0x046: BLTALWM(value); break; ! 2891: ! 2892: case 0x050: BLTAPTH(value); break; ! 2893: case 0x052: BLTAPTL(value); break; ! 2894: case 0x04C: BLTBPTH(value); break; ! 2895: case 0x04E: BLTBPTL(value); break; ! 2896: case 0x048: BLTCPTH(value); break; ! 2897: case 0x04A: BLTCPTL(value); break; ! 2898: case 0x054: BLTDPTH(value); break; ! 2899: case 0x056: BLTDPTL(value); break; ! 2900: ! 2901: case 0x058: BLTSIZE(value); break; ! 2902: ! 2903: case 0x064: BLTAMOD(value); break; ! 2904: case 0x062: BLTBMOD(value); break; ! 2905: case 0x060: BLTCMOD(value); break; ! 2906: case 0x066: BLTDMOD(value); break; ! 2907: ! 2908: case 0x070: BLTCDAT(value); break; ! 2909: case 0x072: BLTBDAT(value); break; ! 2910: case 0x074: BLTADAT(value); break; ! 2911: ! 2912: case 0x07E: DSKSYNC(value); break; ! 2913: ! 2914: case 0x080: COP1LCH(value); break; ! 2915: case 0x082: COP1LCL(value); break; ! 2916: case 0x084: COP2LCH(value); break; ! 2917: case 0x086: COP2LCL(value); break; ! 2918: ! 2919: case 0x088: COPJMP1(value); break; ! 2920: case 0x08A: COPJMP2(value); break; ! 2921: ! 2922: case 0x08E: DIWSTRT(value); break; ! 2923: case 0x090: DIWSTOP(value); break; ! 2924: case 0x092: DDFSTRT(value); break; ! 2925: case 0x094: DDFSTOP(value); break; ! 2926: ! 2927: case 0x096: DMACON(value); break; ! 2928: case 0x09A: INTENA(value); break; ! 2929: case 0x09C: INTREQ(value); break; ! 2930: case 0x09E: ADKCON(value); break; ! 2931: ! 2932: case 0x0A0: AUDxLCH(0, value); break; ! 2933: case 0x0A2: AUDxLCL(0, value); break; ! 2934: case 0x0A4: AUDxLEN(0, value); break; ! 2935: case 0x0A6: AUDxPER(0, value); break; ! 2936: case 0x0A8: AUDxVOL(0, value); break; ! 2937: case 0x0AA: AUDxDAT(0, value); break; ! 2938: ! 2939: case 0x0B0: AUDxLCH(1, value); break; ! 2940: case 0x0B2: AUDxLCL(1, value); break; ! 2941: case 0x0B4: AUDxLEN(1, value); break; ! 2942: case 0x0B6: AUDxPER(1, value); break; ! 2943: case 0x0B8: AUDxVOL(1, value); break; ! 2944: case 0x0BA: AUDxDAT(1, value); break; ! 2945: ! 2946: case 0x0C0: AUDxLCH(2, value); break; ! 2947: case 0x0C2: AUDxLCL(2, value); break; ! 2948: case 0x0C4: AUDxLEN(2, value); break; ! 2949: case 0x0C6: AUDxPER(2, value); break; ! 2950: case 0x0C8: AUDxVOL(2, value); break; ! 2951: case 0x0CA: AUDxDAT(2, value); break; ! 2952: ! 2953: case 0x0D0: AUDxLCH(3, value); break; ! 2954: case 0x0D2: AUDxLCL(3, value); break; ! 2955: case 0x0D4: AUDxLEN(3, value); break; ! 2956: case 0x0D6: AUDxPER(3, value); break; ! 2957: case 0x0D8: AUDxVOL(3, value); break; ! 2958: case 0x0DA: AUDxDAT(3, value); break; ! 2959: ! 2960: case 0x0E0: BPLPTH(value, 0); break; ! 2961: case 0x0E2: BPLPTL(value, 0); break; ! 2962: case 0x0E4: BPLPTH(value, 1); break; ! 2963: case 0x0E6: BPLPTL(value, 1); break; ! 2964: case 0x0E8: BPLPTH(value, 2); break; ! 2965: case 0x0EA: BPLPTL(value, 2); break; ! 2966: case 0x0EC: BPLPTH(value, 3); break; ! 2967: case 0x0EE: BPLPTL(value, 3); break; ! 2968: case 0x0F0: BPLPTH(value, 4); break; ! 2969: case 0x0F2: BPLPTL(value, 4); break; ! 2970: case 0x0F4: BPLPTH(value, 5); break; ! 2971: case 0x0F6: BPLPTL(value, 5); break; ! 2972: ! 2973: case 0x100: BPLCON0(value); break; ! 2974: case 0x102: BPLCON1(value); break; ! 2975: case 0x104: BPLCON2(value); break; ! 2976: case 0x106: BPLCON3(value); break; ! 2977: ! 2978: case 0x108: BPL1MOD(value); break; ! 2979: case 0x10A: BPL2MOD(value); break; ! 2980: ! 2981: case 0x110: BPL1DAT(value); break; ! 2982: case 0x112: BPL2DAT(value); break; ! 2983: case 0x114: BPL3DAT(value); break; ! 2984: case 0x116: BPL4DAT(value); break; ! 2985: case 0x118: BPL5DAT(value); break; ! 2986: case 0x11A: BPL6DAT(value); break; ! 2987: ! 2988: case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A: ! 2989: case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196: ! 2990: case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2: ! 2991: case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE: ! 2992: case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: ! 2993: case 0x1BC: case 0x1BE: ! 2994: COLOR(value & 0xFFF, (addr & 0x3E) / 2); ! 2995: break; ! 2996: case 0x120: case 0x124: case 0x128: case 0x12C: ! 2997: case 0x130: case 0x134: case 0x138: case 0x13C: ! 2998: SPRxPTH(value, (addr - 0x120) / 4); ! 2999: break; ! 3000: case 0x122: case 0x126: case 0x12A: case 0x12E: ! 3001: case 0x132: case 0x136: case 0x13A: case 0x13E: ! 3002: SPRxPTL(value, (addr - 0x122) / 4); ! 3003: break; ! 3004: case 0x140: case 0x148: case 0x150: case 0x158: ! 3005: case 0x160: case 0x168: case 0x170: case 0x178: ! 3006: SPRxPOS(value, (addr - 0x140) / 8); ! 3007: break; ! 3008: case 0x142: case 0x14A: case 0x152: case 0x15A: ! 3009: case 0x162: case 0x16A: case 0x172: case 0x17A: ! 3010: SPRxCTL(value, (addr - 0x142) / 8); ! 3011: break; ! 3012: case 0x144: case 0x14C: case 0x154: case 0x15C: ! 3013: case 0x164: case 0x16C: case 0x174: case 0x17C: ! 3014: SPRxDATA(value, (addr - 0x144) / 8); ! 3015: break; ! 3016: case 0x146: case 0x14E: case 0x156: case 0x15E: ! 3017: case 0x166: case 0x16E: case 0x176: case 0x17E: ! 3018: SPRxDATB(value, (addr - 0x146) / 8); ! 3019: break; ! 3020: ! 3021: case 0x36: JOYTEST(value); break; ! 3022: #if defined(ECS_AGNUS) || (AGA_CHIPSET == 1) ! 3023: case 0x5A: BLTCON0L(value); break; ! 3024: case 0x5C: BLTSIZV(value); break; ! 3025: case 0x5E: BLTSIZH(value); break; ! 3026: #endif ! 3027: #if AGA_CHIPSET == 1 ! 3028: case 0x10C: BPLCON4(value); break; ! 3029: case 0x1FC: fmode = value; break; ! 3030: #endif ! 3031: } ! 3032: } ! 3033: ! 3034: void custom_bput(CPTR addr, UBYTE value) ! 3035: { ! 3036: /* Yes, there are programs that do this. The programmers should be shot. ! 3037: * This might actually work sometimes. */ ! 3038: UWORD rval = value; ! 3039: CPTR raddr = addr & 0x1FE; ! 3040: if (addr & 1) { ! 3041: rval |= cregs[raddr >> 1] & 0xFF00; ! 3042: } else { ! 3043: rval <<= 8; ! 3044: rval |= cregs[raddr >> 1] & 0xFF; ! 3045: } ! 3046: custom_wput(raddr, rval); ! 3047: } ! 3048: ! 3049: void custom_lput(CPTR addr, ULONG value) ! 3050: { ! 3051: custom_wput(addr & 0xfffe, value >> 16); ! 3052: custom_wput((addr+2) & 0xfffe, (UWORD)value); ! 3053: } ! 3054:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.