home *** CD-ROM | disk | FTP | other *** search
/ Amiga ISO Collection / AmigaUtilCD1.iso / Emulatoren / UAE061.LZH / uae-0.6.1 / custom.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-28  |  82.0 KB  |  3,018 lines

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