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