|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Screen drawing functions
5: *
6: * Copyright 1995-1998 Bernd Schmidt
7: * Copyright 1995 Alessandro Bissacco
8: */
9:
10: #include "sysconfig.h"
11: #include "sysdeps.h"
12:
13: #include <ctype.h>
14: #include <assert.h>
15:
16: #include "config.h"
17: #include "options.h"
18: #include "threaddep/penguin.h"
19: #include "uae.h"
20: #include "memory.h"
21: #include "custom.h"
22: #include "readcpu.h"
23: #include "newcpu.h"
24: #include "xwin.h"
25: #include "autoconf.h"
26: #include "gui.h"
27: #include "picasso96.h"
28: #include "drawing.h"
29: #include "p2c.h"
30:
31: #if defined X86_ASSEMBLY
32: #define LORES_HACK
33: #endif
34:
35: int lores_factor, lores_shift, sprite_width;
36:
37: static int interlace_seen = 0;
38:
39: static int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256];
40: static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256];
41:
42: static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
43:
44: /* Big lookup tables for planar to chunky conversion. */
45:
46: uae_u32 hirestab_h[256][2];
47: uae_u32 lorestab_h[256][4];
48:
49: uae_u32 hirestab_l[256][1];
50: uae_u32 lorestab_l[256][2];
51:
52: static uae_u32 clxtab[256];
53:
54: /* Video buffer description structure. Filled in by the graphics system
55: * dependent code. */
56:
57: struct vidbuf_description gfxvidinfo;
58:
59: /* The color lookup table. */
60:
61: xcolnr xcolors[4096];
62:
63: struct color_entry colors_for_drawing;
64:
65: /* 880 isn't a magic number, it's a safe number with some padding at the end.
66: * This used to be 1000, but that's excessive. (840 is too low). I'm too lazy
67: * to figure out the exact space needed. */
68: union {
69: /* Let's try to align this thing. */
70: double uupzuq;
71: long int cruxmedo;
72: unsigned char apixels[880];
73: } pixdata;
74:
75: uae_u32 ham_linebuf[880];
76: uae_u32 aga_linebuf[880], *aga_lbufptr;
77:
78: char *xlinebuffer;
79:
80: static int *amiga2aspect_line_map, *native2amiga_line_map;
81: static char *row_map[2049];
82: static int max_drawn_amiga_line;
83:
84: /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */
85: typedef void (*line_draw_func)(int, int);
86:
87: #define LINE_UNDECIDED 1
88: #define LINE_DECIDED 2
89: #define LINE_DECIDED_DOUBLE 3
90: #define LINE_AS_PREVIOUS 4
1.1.1.2 root 91: #define LINE_BLACK 5
92: #define LINE_REMEMBERED_AS_BLACK 6
1.1 root 93: #define LINE_DONE 7
94: #define LINE_DONE_AS_PREVIOUS 8
95: #define LINE_REMEMBERED_AS_PREVIOUS 9
96:
97: static char *line_drawn;
1.1.1.5 root 98: static char linestate[(MAXVPOS + 1)*2 + 1];
1.1 root 99:
1.1.1.5 root 100: uae_u8 line_data[(MAXVPOS + 1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
1.1 root 101:
102: static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x;
103: static int linetoscr_x_adjust_bytes;
104: static int thisframe_y_adjust, prev_y_adjust;
105: static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
106: static int extra_y_adjust;
107: int thisframe_first_drawn_line, thisframe_last_drawn_line;
108:
109: static int last_redraw_point;
110:
111: static int first_drawn_line, last_drawn_line;
112: static int first_block_line, last_block_line;
113:
114: /* These are generated by the drawing code from the line_decisions array for
115: * each line that needs to be drawn. */
1.1.1.5 root 116: static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplres;
1.1 root 117: static int bpldelay1, bpldelay2;
118: static int plfpri[3];
119:
120: int picasso_requested_on;
121: int picasso_on;
122:
123: uae_sem_t gui_sem;
124: int inhibit_frame;
125:
126: int framecnt = 0;
127: static int frame_redraw_necessary;
128: static int picasso_redraw_necessary;
129:
1.1.1.6 root 130: STATIC_INLINE void count_frame (void)
1.1 root 131: {
132: framecnt++;
1.1.1.5 root 133: if (framecnt >= currprefs.gfx_framerate)
1.1 root 134: framecnt = 0;
135: }
136:
137: int coord_native_to_amiga_x (int x)
138: {
139: x += linetoscr_x_adjust;
140: x <<= (1 - lores_shift);
141: return x + 2*DISPLAY_LEFT_SHIFT;
142: }
143:
144: int coord_native_to_amiga_y (int y)
145: {
146: return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline;
147: }
148:
149: void notice_screen_contents_lost (void)
150: {
151: picasso_redraw_necessary = 1;
152: frame_redraw_necessary = 2;
153: }
154:
155: static struct decision *dp_for_drawing;
156: static struct draw_info *dip_for_drawing;
157:
158: void record_diw_line (int first, int last)
159: {
160: if (last > max_diwstop)
161: max_diwstop = last;
162: if (first < min_diwstart)
163: min_diwstart = first;
164: }
165:
166: /*
167: * Screen update macros/functions
168: */
169:
170: static unsigned int ham_lastcolor;
171:
172: static void init_ham_decoding(int first)
173: {
174: int pix = dp_for_drawing->diwfirstword;
175: ham_lastcolor = colors_for_drawing.color_regs[0];
176: while (pix < first) {
177: int pv = pixdata.apixels[pix];
178: switch(pv & 0x30) {
179: case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
180: case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
181: case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
182: case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
183: }
184: pix++;
185: }
186: }
187:
188: static void decode_ham6 (int pix, int stoppos)
189: {
190: uae_u32 *buf = ham_linebuf;
191:
192: if (!bplham || bplplanecnt != 6)
193: return;
194:
195: if (stoppos > dp_for_drawing->diwlastword)
196: stoppos = dp_for_drawing->diwlastword;
197: if (pix < dp_for_drawing->diwfirstword) {
198: ham_lastcolor = colors_for_drawing.color_regs[0];
199: pix = dp_for_drawing->diwfirstword;
200: }
201: #ifdef LORES_HACK
202: if (currprefs.gfx_lores == 2)
203: pix <<= 1, stoppos <<= 1;
204: #endif
205: while (pix < stoppos) {
206: int pv = pixdata.apixels[pix];
207: switch(pv & 0x30) {
208: case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break;
209: case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
210: case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
211: case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
212: }
213:
214: buf[pix++] = ham_lastcolor;
215: }
216: }
217: #if 0
218: static void decode_ham_aga (int pix, int stoppos)
219: {
220: static uae_u32 lastcolor;
221: uae_u32 *buf = ham_linebuf;
222:
223: if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
224: return;
225:
226: if (pix <= dp_for_drawing->diwfirstword) {
227: pix = dp_for_drawing->diwfirstword;
228: lastcolor = colors_for_drawing.color_regs[0];
229: }
230:
231: if (dp_for_drawing->bplplanecnt == 6) {
232: /* HAM 6 */
233: while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
234: int pv = pixdata.apixels[pix];
235: switch(pv & 0x30) {
236: case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break;
237: case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break;
238: case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break;
239: case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break;
240: }
241: buf[pix++] = lastcolor;
242: }
243: } else if (dp_for_drawing->bplplanecnt == 8) {
244: /* HAM 8 */
245: while (pix < dp_for_drawing->diwlastword && pix < stoppos) {
246: int pv = pixdata.apixels[pix];
247: switch(pv & 0x3) {
248: case 0x0: lastcolor = colors_for_drawing.color_regs[pv >> 2]; break;
249: case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break;
250: case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break;
251: case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break;
252: }
253: buf[pix++] = lastcolor;
254: }
255: }
256: }
257: #endif
258:
1.1.1.2 root 259: static int linetoscr_double_offset;
260:
1.1 root 261: #if AGA_CHIPSET != 0
262: /* WARNING: Not too much of this will work correctly yet. */
263:
1.1.1.2 root 264: static void pfield_linetoscr_aga (int pix, int lframe_end, int diw_end, int stoppos)
1.1 root 265: {
266: uae_u32 *buf = aga_lbufptr;
267: int i;
1.1.1.2 root 268: int xor = (uae_u8)(dp_for_drawing->bplcon4 >> 8);
269: int oldpix = pix;
1.1 root 270:
1.1.1.2 root 271: buf -= pix;
1.1 root 272:
273: for (i = 0; i < stoppos; i++)
274: pixdata.apixels[i] ^= xor;
275:
1.1.1.2 root 276: while (pix < lframe_end) {
1.1 root 277: buf[pix++] = colors_for_drawing.color_regs[0];
278: }
279: if (bplham) {
1.1.1.2 root 280: while (pix < diw_end) {
1.1 root 281: uae_u32 d = ham_linebuf[pix];
282: buf[pix] = d;
283: pix++;
284: }
285: } else if (bpldualpf) {
1.1.1.2 root 286: #if 0 /* FIXME */
1.1 root 287: /* Dual playfield */
288: int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1;
289: int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1;
1.1.1.2 root 290: while (pix < diw_end) {
1.1 root 291: int pixcol = pixdata.apixels[pix];
292: int pfno = lookup_no[pixcol];
293:
294: if (spixstate[pix]) {
295: buf[pix] = colors_for_drawing.color_regs[pixcol];
296: } else {
297: int val = lookup[pixdata.apixels[pix]];
298: if (pfno == 2)
1.1.1.2 root 299: val += dblpfofs[(dp_for_drawing->bplcon2 >> 10) & 7];
1.1 root 300: buf[pix] = colors_for_drawing.color_regs[val];
301: }
302: pix++;
303: }
1.1.1.2 root 304: #endif
1.1 root 305: } else if (bplehb) {
1.1.1.2 root 306: while (pix < diw_end) {
1.1 root 307: int pixcol = pixdata.apixels[pix];
308: uae_u32 d = colors_for_drawing.color_regs[pixcol];
309: /* What about sprites? */
310: if (pixcol & 0x20)
311: d = (d & 0x777777) >> 1;
312: buf[pix] = d;
313: pix++;
314: }
315: } else {
1.1.1.2 root 316: while (pix < diw_end) {
1.1 root 317: int pixcol = pixdata.apixels[pix];
318: buf[pix] = colors_for_drawing.color_regs[pixcol];
319: pix++;
320: }
321: }
322: while (pix < stoppos) {
323: buf[pix++] = colors_for_drawing.color_regs[0];
324: }
325: aga_lbufptr += pix - oldpix;
326: }
327:
1.1.1.2 root 328: static void aga_translate32 (int start, int stop)
1.1 root 329: {
1.1.1.2 root 330: memcpy (((uae_u32 *)xlinebuffer) + start, aga_lbufptr, 4*(stop-start));
331: aga_lbufptr += stop - start;
1.1 root 332: }
333:
1.1.1.2 root 334: static void aga_translate16 (int start, int stop)
1.1 root 335: {
336: int i;
337: for (i = start; i < stop; i++) {
338: uae_u32 d = aga_linebuf[i];
339: uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
340: ((uae_u16 *)xlinebuffer)[i] = xcolors[v];
341: }
342: }
343:
1.1.1.2 root 344: static void aga_translate8 (int start, int stop)
1.1 root 345: {
346: int i;
347: for (i = start; i < stop; i++) {
348: uae_u32 d = aga_linebuf[i];
349: uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12);
350: ((uae_u8 *)xlinebuffer)[i] = xcolors[v];
351: }
352: }
353:
1.1.1.2 root 354: static void aga_fill_line_32 (char *buf, int start, int stop)
355: {
356: int i;
357: for (i = start; i < stop; i++) {
358: ((uae_u32 *)buf)[i] = colors_for_drawing.color_regs[0];
359: }
360: }
361:
362: static void fill_line (void)
363: {
364: aga_fill_line_32 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width);
365: }
366:
367: #else /* no AGA_CHIPSET */
1.1 root 368:
369: #define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \
370: static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \
371: { \
372: TYPE *buf = ((TYPE *)xlinebuffer); \
373: /* int oldpix = pix;*/ \
374: /* These are different for register-allocation purposes. */ \
375: TYPE d1, d2; \
376: int offset; \
377: \
378: if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \
379: \
380: d1 = CONVERT(colors_for_drawing.acolors[0]); \
381: while (pix < lframe_end) { \
382: buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \
383: pix++; \
384: } \
385: if (bplham && bplplanecnt == 6) { \
386: /* HAM 6 */ \
387: while (pix < diw_end) { \
388: TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \
389: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
390: pix++; \
391: } \
392: } else if (bpldualpf) { \
393: /* Dual playfield */ \
394: int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \
395: while (pix < diw_end) { \
396: int pixcol = pixdata.apixels[pix]; \
397: TYPE d; \
398: d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \
399: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
400: pix++; \
401: } \
402: } else if (bplehb) { \
403: while (pix < diw_end) { \
404: int p = pixdata.apixels[pix]; \
405: TYPE d = CONVERT (colors_for_drawing.acolors[p]); \
406: if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \
407: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
408: pix++; \
409: } \
410: } else { \
411: while (pix < diw_end) { \
412: TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \
413: buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \
414: pix++; \
415: } \
416: } \
417: d2 = CONVERT (colors_for_drawing.acolors[0]); \
418: while (pix < stoppos) { \
419: buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \
420: pix++; \
421: } \
422: }
423:
424: #define FILL_LINE(NAME, TYPE, CONVERT) \
1.1.1.2 root 425: static void NAME (char *buf, int start, int stop) \
1.1 root 426: { \
427: TYPE *b = (TYPE *)buf; \
428: int i;\
429: xcolnr col = colors_for_drawing.acolors[0]; \
430: for (i = start; i < stop; i++) \
431: b[i] = CONVERT (col); \
432: }
433:
434: LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,)
435: LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,)
436: LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,)
437: LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,)
438: LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,)
439: LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,)
440:
441: FILL_LINE(fill_line_8, uae_u8,)
442: FILL_LINE(fill_line_16, uae_u16,)
443: FILL_LINE(fill_line_32, uae_u32,)
444:
445: #ifdef HAVE_UAE_U24
446: LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert)
447: LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert)
448: FILL_LINE(fill_line_24, uae_u24, uae24_convert)
449: #else
450: /* Dummy versions */
451: static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos)
452: {
453: }
454: static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos)
455: {
456: }
457: static void fill_line_24 (char *buf, int start, int stop)
458: {
459: }
460: #endif
461:
1.1.1.6 root 462: STATIC_INLINE void fill_line_full (void)
1.1 root 463: {
464: switch (gfxvidinfo.pixbytes) {
1.1.1.2 root 465: case 1: fill_line_8 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
466: case 2: fill_line_16 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
467: case 3: fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
468: case 4: fill_line_32 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break;
1.1 root 469: }
470: }
471:
472: #define fill_line fill_line_full
473:
474: #define pfield_linetoscr_full8 pfield_linetoscr_8
475: #define pfield_linetoscr_full16 pfield_linetoscr_16
476: #define pfield_linetoscr_full24 pfield_linetoscr_24
477: #define pfield_linetoscr_full32 pfield_linetoscr_32
478:
479: #define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow
480: #define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow
481: #define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow
482: #define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow
483:
484: #if 1
485: #undef fill_line
1.1.1.6 root 486: STATIC_INLINE void fill_line (void)
1.1 root 487: {
488: int shift;
489: int nints, nrem;
490: int *start;
491: xcolnr val;
492:
493: #ifdef HAVE_UAE_U24
494: if (gfxvidinfo.pixbytes == 3) {
495: fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width);
496: return;
497: }
498: #endif
499:
500: shift = 0;
501: if (gfxvidinfo.pixbytes == 2)
502: shift = 1;
503: if (gfxvidinfo.pixbytes == 4)
504: shift = 2;
505:
506: nints = gfxvidinfo.width >> (2-shift);
507: nrem = nints & 7;
508: nints &= ~7;
509: start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift));
510: val = colors_for_drawing.acolors[0];
511: for (; nints > 0; nints -= 8, start += 8) {
512: *start = val;
513: *(start+1) = val;
514: *(start+2) = val;
515: *(start+3) = val;
516: *(start+4) = val;
517: *(start+5) = val;
518: *(start+6) = val;
519: *(start+7) = val;
520: }
521:
522: switch (nrem) {
523: case 7:
524: *start++ = val;
525: case 6:
526: *start++ = val;
527: case 5:
528: *start++ = val;
529: case 4:
530: *start++ = val;
531: case 3:
532: *start++ = val;
533: case 2:
534: *start++ = val;
535: case 1:
536: *start = val;
537: }
538: }
539:
540: #ifdef X86_ASSEMBLY
541:
542: #undef pfield_linetoscr_full8
543: /* The types are lies, of course. */
1.1.1.2 root 544: extern void pfield_linetoscr_normal_asm8 (void) __asm__("pfield_linetoscr_normal_asm8");
545: extern void pfield_linetoscr_ehb_asm8 (void) __asm__("pfield_linetoscr_ehb_asm8");
546: extern void pfield_linetoscr_ham6_asm8 (void) __asm__("pfield_linetoscr_ham6_asm8");
547: extern void pfield_linetoscr_dualpf_asm8 (void) __asm__("pfield_linetoscr_dualpf_asm8");
548: extern void pfield_linetoscr_hdouble_asm8 (void) __asm__("pfield_linetoscr_hdouble_asm8");
549: extern void pfield_linetoscr_hdouble_dpf_asm8 (void) __asm__("pfield_linetoscr_hdouble_dpf_asm8");
550: extern void pfield_linetoscr_hdouble_ehb_asm8 (void) __asm__("pfield_linetoscr_hdouble_ehb_asm8");
551: extern void pfield_linetoscr_asm8 (void (*) (void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8");
1.1 root 552:
1.1.1.2 root 553: static void pfield_linetoscr_full8 (int pix, int lframe_end, int diw_end, int stoppos)
1.1 root 554: {
555: int lframe_end_1, diw_end_1;
556:
557: lframe_end_1 = pix + ((lframe_end - pix) & ~3);
558: diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
559:
560: if (bplham && bplplanecnt == 6) {
1.1.1.2 root 561: pfield_linetoscr_asm8 (pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 562: } else if (bpldualpf) {
563: #ifdef LORES_HACK
564: if (currprefs.gfx_lores == 2)
1.1.1.2 root 565: pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
1.1 root 566: bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
567: else
568: #endif
1.1.1.2 root 569: pfield_linetoscr_asm8 (pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos,
1.1 root 570: bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
571: } else if (bplehb) {
572: #ifdef LORES_HACK
573: if (currprefs.gfx_lores == 2)
1.1.1.2 root 574: pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 575: else
576: #endif
1.1.1.2 root 577: pfield_linetoscr_asm8 (pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 578: } else {
579: #ifdef LORES_HACK
580: if (currprefs.gfx_lores == 2)
1.1.1.2 root 581: pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 582: else
583: #endif
1.1.1.2 root 584: pfield_linetoscr_asm8 (pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 585: }
586:
587: /* The assembly functions work on aligned data, so we may have to do some
588: * additional work at the edges. */
589: if (lframe_end != lframe_end_1) {
590: int i, c = colors_for_drawing.acolors[0];
591: for (i = lframe_end_1; i < lframe_end; i++)
592: xlinebuffer[i] = c;
593: }
594: if (diw_end != diw_end_1) {
595: int i, c = colors_for_drawing.acolors[0];
596: for (i = diw_end; i < diw_end_1; i++)
597: xlinebuffer[i] = c;
598: }
599: }
600:
601: #undef pfield_linetoscr_full16
1.1.1.2 root 602: extern void pfield_linetoscr_normal_asm16 (void) __asm__("pfield_linetoscr_normal_asm16");
603: extern void pfield_linetoscr_ehb_asm16 (void) __asm__("pfield_linetoscr_ehb_asm16");
604: extern void pfield_linetoscr_ham6_asm16 (void) __asm__("pfield_linetoscr_ham6_asm16");
605: extern void pfield_linetoscr_dualpf_asm16 (void) __asm__("pfield_linetoscr_dualpf_asm16");
606: extern void pfield_linetoscr_hdouble_asm16 (void) __asm__("pfield_linetoscr_hdouble_asm16");
607: extern void pfield_linetoscr_hdouble_dpf_asm16 (void) __asm__("pfield_linetoscr_hdouble_dpf_asm16");
608: extern void pfield_linetoscr_hdouble_ehb_asm16 (void) __asm__("pfield_linetoscr_hdouble_ehb_asm16");
609: extern void pfield_linetoscr_asm16 (void (*) (void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16");
1.1 root 610:
1.1.1.2 root 611: static void pfield_linetoscr_full16 (int pix, int lframe_end, int diw_end, int stoppos)
1.1 root 612: {
613: int lframe_end_1, diw_end_1;
614:
615: lframe_end_1 = pix + ((lframe_end - pix) & ~3);
616: diw_end_1 = stoppos - ((stoppos - diw_end) & ~3);
617:
618: if (bplham && bplplanecnt == 6) {
1.1.1.2 root 619: pfield_linetoscr_asm16 (pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 620: } else if (bpldualpf) {
621: #ifdef LORES_HACK
622: if (currprefs.gfx_lores == 2)
1.1.1.2 root 623: pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
1.1 root 624: bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
625: else
626: #endif
1.1.1.2 root 627: pfield_linetoscr_asm16 (pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos,
1.1 root 628: bpldualpfpri ? dblpf_ind2 : dblpf_ind1);
629: } else if (bplehb) {
630: #ifdef LORES_HACK
631: if (currprefs.gfx_lores == 2)
1.1.1.2 root 632: pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 633: else
634: #endif
1.1.1.2 root 635: pfield_linetoscr_asm16 (pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 636: } else {
637: #ifdef LORES_HACK
638: if (currprefs.gfx_lores == 2)
1.1.1.2 root 639: pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 640: else
641: #endif
1.1.1.2 root 642: pfield_linetoscr_asm16 (pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos);
1.1 root 643: }
644:
645: /* The assembly functions work on aligned data, so we may have to do some
646: * additional work at the edges. */
647: if (lframe_end != lframe_end_1) {
648: int i, c = colors_for_drawing.acolors[0];
649: for (i = lframe_end_1; i < lframe_end; i++)
650: ((uae_u16 *)xlinebuffer)[i] = c;
651: }
652: if (diw_end != diw_end_1) {
653: int i, c = colors_for_drawing.acolors[0];
654: for (i = diw_end; i < diw_end_1; i++)
655: ((uae_u16 *)xlinebuffer)[i] = c;
656: }
657: }
658: #endif
659:
660: #ifndef NO_DOUBLING_LINETOSCR
661: #define NO_DOUBLING_LINETOSCR
662: #endif
663:
664: #endif
665:
666: #ifdef NO_DOUBLING_LINETOSCR
667: #undef pfield_linetoscr_full8_double
668: #undef pfield_linetoscr_full16_double
1.1.1.2 root 669: static void pfield_linetoscr_full8_double (int start, int lframe_end, int diw_end, int stop)
1.1 root 670: {
671: char *oldxlb = (char *)xlinebuffer;
1.1.1.2 root 672: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop);
1.1 root 673: xlinebuffer = oldxlb + linetoscr_double_offset;
1.1.1.2 root 674: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop);
1.1 root 675: }
1.1.1.2 root 676: static void pfield_linetoscr_full16_double (int start, int lframe_end, int diw_end, int stop)
1.1 root 677: {
678: char *oldxlb = (char *)xlinebuffer;
1.1.1.2 root 679: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop);
1.1 root 680: xlinebuffer = oldxlb + linetoscr_double_offset;
1.1.1.2 root 681: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop);
1.1 root 682: }
683: #endif
684:
1.1.1.2 root 685: #endif /* no AGA_CHIPSET */
686:
1.1 root 687: static int linetoscr_diw_end, linetoscr_diw_start;
688:
689: /* Initialize the variables necessary for drawing a line.
690: * This involves setting up start/stop positions and display window
691: * borders. Also, since the drawing code may not fully overwrite all
692: * releveant areas in the pixdata.apixels array for speed reasons, parts of
693: * it must possibly be cleared here. */
694: static void pfield_init_linetoscr (void)
695: {
696: int mindelay = bpldelay1, maxdelay = bpldelay2;
697: if (bpldelay1 > bpldelay2)
698: maxdelay = bpldelay1, mindelay = bpldelay2;
699:
700: linetoscr_diw_start = dp_for_drawing->diwfirstword;
701: linetoscr_diw_end = dp_for_drawing->diwlastword;
702:
703: /* We should really look at DDF also when calculating max_diwstop/min_diwstrt,
704: * so that centering works better, but I'm afraid that might cost too many
705: * cycles. Plus it's dangerous, see the code below that handles the case
1.1.1.5 root 706: * with sprites.
707: * The fuzzy_memset_le32 code won't work for AGA, so skip this part here.
708: */
709: if (dip_for_drawing->nr_sprites == 0 || (currprefs.chipset_mask & CSMASK_AGA)) {
710: int hiresadjust = RES_ADJUST (bplres);
711: int ddf_left = (((dp_for_drawing->plfstrt + hiresadjust)*2
712: + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift);
713: int ddf_right = (((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2
714: + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift);
1.1 root 715:
716: if (linetoscr_diw_start < ddf_left)
717: linetoscr_diw_start = ddf_left;
718: if (linetoscr_diw_end > ddf_right)
719: linetoscr_diw_end = ddf_right;
720:
721: if (mindelay != maxdelay) {
722: /* Raahh...
723: * We just clear the maximum amount of space that may need to be
724: * cleared. We could do this exactly, but it would come out slower
725: * because of the overhead. */
726: if (currprefs.gfx_lores == 2) {
727: fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15);
728: fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15);
729: } else if (currprefs.gfx_lores) {
730: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15);
731: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15);
732: } else {
733: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30);
734: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30);
735: }
736: }
737: } else {
1.1.1.5 root 738: /* Conservative case. */
739: int hiresadjust = RES_ADJUST (bplres);
1.1 root 740: /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check.
741: * Since we have to do a memset anyway (because there may be sprites),
742: * we might as well clear all at once. */
1.1.1.5 root 743: int ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2
744: + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
745: int ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2
746: + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
747:
1.1 root 748: if (linetoscr_diw_start < ddf_left) {
749: int strt = linetoscr_diw_start;
750: int stop = ddf_left;
751: #ifdef LORES_HACK
752: if (currprefs.gfx_lores == 2)
753: strt >>= 1, stop >>= 1;
754: #endif
755: if (strt < stop)
756: fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
757: }
758:
759: if (linetoscr_diw_end > ddf_right) {
760: int strt = ddf_right;
761: int stop = linetoscr_diw_end;
762: #ifdef LORES_HACK
763: if (currprefs.gfx_lores == 2)
764: strt >>= 1, stop >>= 1;
765: #endif
766: if (strt < stop)
767: fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
768: }
769: }
770: /* Perverse cases happen. */
771: if (linetoscr_diw_end < linetoscr_diw_start)
772: linetoscr_diw_end = linetoscr_diw_start;
773: }
774:
775: static void pfield_do_linetoscr(int start, int stop)
776: {
777: int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
778:
779: if (stop > linetoscr_right_x)
780: stop = linetoscr_right_x;
781: if (start < linetoscr_x_adjust)
782: start = linetoscr_x_adjust;
783:
784: if (lframe_end < start)
785: lframe_end = start;
786: if (diw_end > stop)
787: diw_end = stop;
788:
789: if (start >= stop)
790: return;
791:
792: #if AGA_CHIPSET == 0
793: if (start == linetoscr_x_adjust && stop == linetoscr_right_x) {
794: switch (gfxvidinfo.pixbytes) {
795: case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
796: case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
797: case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
798: case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
799: }
800: } else {
801: switch (gfxvidinfo.pixbytes) {
802: case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break;
803: case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break;
804: case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break;
805: case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break;
806: }
807: }
808: #else
1.1.1.2 root 809: pfield_linetoscr_aga (start, lframe_end, diw_end, stop);
1.1 root 810: #endif
811: }
812:
1.1.1.2 root 813: static void pfield_do_fill_line (int start, int stop)
1.1 root 814: {
815: if (stop > linetoscr_right_x)
816: stop = linetoscr_right_x;
817: if (start < linetoscr_x_adjust)
818: start = linetoscr_x_adjust;
819:
820: if (start >= stop)
821: return;
822:
1.1.1.2 root 823: #if AGA_CHIPSET == 0
1.1 root 824: switch (gfxvidinfo.pixbytes) {
825: case 1: fill_line_8 (xlinebuffer, start, stop); break;
826: case 2: fill_line_16 (xlinebuffer, start, stop); break;
827: case 3: fill_line_24 (xlinebuffer, start, stop); break;
828: case 4: fill_line_32 (xlinebuffer, start, stop); break;
829: }
1.1.1.2 root 830: #else
831: aga_fill_line_32 (xlinebuffer, start, stop);
832: /* FIXME */
833: #endif
1.1 root 834: }
835:
1.1.1.2 root 836: static void pfield_do_linetoscr_full (int double_line)
1.1 root 837: {
838: int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width;
839: int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
840: if (lframe_end < start)
841: lframe_end = start;
842: if (diw_end > stop)
843: diw_end = stop;
844:
845: #if AGA_CHIPSET == 0
846: if (double_line) {
847: switch (gfxvidinfo.pixbytes) {
848: case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break;
849: case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break;
850: case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break;
851: case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break;
852: }
853: } else
854: switch (gfxvidinfo.pixbytes) {
855: case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
856: case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
857: case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
858: case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
859: }
860: #else
1.1.1.2 root 861: pfield_linetoscr_aga (start, lframe_end, diw_end, stop);
1.1 root 862: #endif
863: }
864:
1.1.1.2 root 865: static void gen_pfield_tables (void)
1.1 root 866: {
867: int i;
868: union {
869: struct {
870: uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
871: } foo;
872: struct {
873: uae_u32 a, b, c, d;
874: } bar;
875: } baz;
876:
877: /* For now, the AGA stuff is broken in the dual playfield case. We encode
878: * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
879: * playfield rendering easy, the lookup tables contain are made linear for
880: * values >= 128. That only works for OCS/ECS, though. */
881:
882: for (i = 0; i < 256; i++) {
883: int plane1 = (i & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
884: int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
885: dblpf_2nd1[i] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
886: dblpf_2nd2[i] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
887: if (plane2 > 0)
888: plane2 += 8;
889: dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
890: dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
891:
892: lots_of_twos[i] = i == 0 ? 0 : 2;
893: linear_map_256[i] = i;
894: }
895:
896: for (i = 0; i < 256; i++) {
897: /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
898: baz.foo.a = i & 64 ? 1 : 0;
899: baz.foo.b = i & 16 ? 1 : 0;
900: baz.foo.c = i & 4 ? 1 : 0;
901: baz.foo.d = i & 1 ? 1 : 0;
902: hirestab_l[i][0] = baz.bar.a;
903:
904: baz.foo.a = i & 128 ? 1 : 0;
905: baz.foo.b = i & 64 ? 1 : 0;
906: baz.foo.c = i & 32 ? 1 : 0;
907: baz.foo.d = i & 16 ? 1 : 0;
908: baz.foo.e = i & 8 ? 1 : 0;
909: baz.foo.f = i & 4 ? 1 : 0;
910: baz.foo.g = i & 2 ? 1 : 0;
911: baz.foo.h = i & 1 ? 1 : 0;
912: lorestab_l[i][0] = baz.bar.a;
913: lorestab_l[i][1] = baz.bar.b;
914: clxtab[i] = ((((i & 3) && (i & 12)) << 9)
915: | (((i & 3) && (i & 48)) << 10)
916: | (((i & 3) && (i & 192)) << 11)
917: | (((i & 12) && (i & 48)) << 12)
918: | (((i & 12) && (i & 192)) << 13)
919: | (((i & 48) && (i & 192)) << 14));
920: }
921:
922: for (i = 0; i < 256; i++) {
923: baz.foo.a = i & 128 ? 1 : 0;
924: baz.foo.b = i & 64 ? 1 : 0;
925: baz.foo.c = i & 32 ? 1 : 0;
926: baz.foo.d = i & 16 ? 1 : 0;
927: baz.foo.e = i & 8 ? 1 : 0;
928: baz.foo.f = i & 4 ? 1 : 0;
929: baz.foo.g = i & 2 ? 1 : 0;
930: baz.foo.h = i & 1 ? 1 : 0;
931: hirestab_h[i][0] = baz.bar.a;
932: hirestab_h[i][1] = baz.bar.b;
933:
934: baz.foo.a = i & 128 ? 1 : 0;
935: baz.foo.b = i & 128 ? 1 : 0;
936: baz.foo.c = i & 64 ? 1 : 0;
937: baz.foo.d = i & 64 ? 1 : 0;
938: baz.foo.e = i & 32 ? 1 : 0;
939: baz.foo.f = i & 32 ? 1 : 0;
940: baz.foo.g = i & 16 ? 1 : 0;
941: baz.foo.h = i & 16 ? 1 : 0;
942: baz.foo.i = i & 8 ? 1 : 0;
943: baz.foo.j = i & 8 ? 1 : 0;
944: baz.foo.k = i & 4 ? 1 : 0;
945: baz.foo.l = i & 4 ? 1 : 0;
946: baz.foo.m = i & 2 ? 1 : 0;
947: baz.foo.n = i & 2 ? 1 : 0;
948: baz.foo.o = i & 1 ? 1 : 0;
949: baz.foo.p = i & 1 ? 1 : 0;
950: lorestab_h[i][0] = baz.bar.a;
951: lorestab_h[i][1] = baz.bar.b;
952: lorestab_h[i][2] = baz.bar.c;
953: lorestab_h[i][3] = baz.bar.d;
954: }
955: }
956:
957: static uae_u32 attach_2nd;
958:
959: static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr)
960: {
961: int j;
962: int sprxp = spd[i].linepos;
963: uae_u32 datab = spd[i].datab;
964: uae_u32 mask2 = 0;
965: int sbit = 1 << spd[i].num;
966: int sprx_shift = 1;
967: int attach_compare = -1;
968: if (currprefs.gfx_lores != 1)
969: sprx_shift = 0;
970:
971: attach_2nd = 0;
972: if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80)
973: attach_compare = spd[i].num - 1;
974:
975: for (j = prev_overlap; j < i; j++) {
976: uae_u32 mask1;
977: int off;
978:
979: if (spd[i].num < spd[j].num)
980: continue;
981:
982: off = sprxp - spd[j].linepos;
983: off <<= sprx_shift;
984: mask1 = spd[j].datab >> off;
985:
986: /* If j is an attachment for i, then j doesn't block i */
987: if (spd[j].num == attach_compare) {
988: attach_2nd |= mask1;
989: } else {
990: mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
991: mask1 |= (mask1 & 0x55555555) << 1;
992: if (datab & mask1)
993: clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
994: mask2 |= mask1;
995: }
996: }
997: for (j = i+1; j < nr_spr; j++) {
998: uae_u32 mask1;
999: int off = spd[j].linepos - sprxp;
1000:
1001: if (off >= sprite_width || spd[i].num < spd[j].num)
1002: break;
1003:
1004: off <<= sprx_shift;
1005: mask1 = spd[j].datab << off;
1006:
1007: /* If j is an attachment for i, then j doesn't block i */
1008: if (spd[j].num == attach_compare) {
1009: attach_2nd |= mask1;
1010: } else {
1011: mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
1012: mask1 |= (mask1 & 0x55555555) << 1;
1013: if (datab & mask1)
1014: clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
1015: mask2 |= mask1;
1016: }
1017: }
1018: datab &= ~mask2;
1019: return datab;
1020: }
1021:
1.1.1.6 root 1022: STATIC_INLINE void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc)
1.1 root 1023: {
1024: uae_u32 datcd;
1025: int basecol = 16;
1026: if (!attch)
1027: basecol += (spr & ~1)*2;
1028: if (bpldualpf)
1029: basecol |= 128;
1030: if (attch)
1031: datcd = attach_2nd;
1032:
1033: for(; attch ? datab | datcd : datab; sprxp += sprx_inc) {
1034: int col;
1035:
1036: if (attch) {
1037: col = ((datab & 3) << 2) | (datcd & 3);
1038: datcd >>= 2;
1039: } else
1040: col = datab & 3;
1041: datab >>= 2;
1042: if (col) {
1043: col |= basecol;
1044: if (ham) {
1045: col = colors_for_drawing.color_regs[col];
1046: ham_linebuf[sprxp] = col;
1047: if (sprx_inc == 2) {
1048: ham_linebuf[sprxp+1] = col;
1049: }
1050: } else {
1051: pixdata.apixels[sprxp] = col;
1052: if (sprx_inc == 2) {
1053: pixdata.apixels[sprxp+1] = col;
1054: }
1055: }
1056: }
1057: }
1058: }
1059:
1060: static void walk_sprites (struct sprite_draw *spd, int nr_spr)
1061: {
1062: int i, prev_overlap;
1063: int last_sprite_pos = -64;
1064: uae_u32 plane1 = 0, plane2 = 0;
1065: int sprx_inc = 1, sprx_shift = 1;
1066:
1067: if (currprefs.gfx_lores == 0)
1068: sprx_inc = 2, sprx_shift = 0;
1069:
1070: prev_overlap = 0;
1071: for (i = 0; i < nr_spr; i++) {
1072: int sprxp = spd[i].linepos;
1073: int m = 1 << spd[i].num;
1074: uae_u32 datab;
1075: while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp)
1076: prev_overlap++;
1077:
1078: datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr);
1079: #ifdef LORES_HACK
1080: if (currprefs.gfx_lores == 2)
1081: sprxp >>= 1;
1082: #endif
1083: if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) {
1084: if (sprxp != last_sprite_pos) {
1085: int ok = last_sprite_pos-sprxp+16;
1086: int ok2;
1087: if (ok <= 0) {
1088: ok = ok2 = 0;
1089: plane1 = 0;
1090: plane2 = 0;
1091: } else {
1092: ok2 = ok << sprx_shift;
1093: plane1 >>= 32 - ok2;
1094: plane2 >>= 32 - ok2;
1095: }
1096: last_sprite_pos = sprxp;
1097:
1098: if (bpldualpf) {
1099: uae_u32 mask = 3 << ok2;
1100: int p = sprxp+ok;
1101:
1102: for (; mask; mask <<= 2, p += sprx_inc) {
1103: int data = pixdata.apixels[p];
1104: if (dblpf_2nd2[data] == 2)
1105: plane2 |= mask;
1106: if (dblpf_2nd1[data] == 1)
1107: plane1 |= mask;
1108: }
1109: } else {
1110: uae_u32 mask = 3 << ok2;
1111: int p = sprxp+ok;
1112:
1113: for (; mask; mask <<= 2, p += sprx_inc) {
1114: if (pixdata.apixels[p])
1115: plane2 |= mask;
1116: }
1117: }
1118: }
1119: if (bpldualpf && m >= plfpri[1]) {
1120: datab &= ~plane1;
1121: attach_2nd &= ~plane1;
1122: }
1123: if (m >= plfpri[2]) {
1124: datab &= ~plane2;
1125: attach_2nd &= ~plane2;
1126: }
1127: }
1128: if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) {
1129: /* Attached sprite */
1130: if (bplham) {
1131: if (sprx_inc == 1) {
1132: render_sprite (spd[i].num, sprxp, datab, 1, 1, 1);
1133: } else {
1134: render_sprite (spd[i].num, sprxp, datab, 1, 1, 2);
1135: }
1136: } else {
1137: if (sprx_inc == 1) {
1138: render_sprite (spd[i].num, sprxp, datab, 0, 1, 1);
1139: } else {
1140: render_sprite (spd[i].num, sprxp, datab, 0, 1, 2);
1141: }
1142: }
1143: /* This still leaves one attached sprite bug, but at the moment I'm too lazy */
1144: if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos)
1145: i++;
1146: } else {
1147: if (bplham) {
1148: if (sprx_inc == 1) {
1149: render_sprite (spd[i].num, sprxp, datab, 1, 0, 1);
1150: } else {
1151: render_sprite (spd[i].num, sprxp, datab, 1, 0, 2);
1152: }
1153: } else {
1154: if (sprx_inc == 1) {
1155: render_sprite (spd[i].num, sprxp, datab, 0, 0, 1);
1156: } else {
1157: render_sprite (spd[i].num, sprxp, datab, 0, 0, 2);
1158: }
1159: }
1160: }
1161: }
1162: }
1163:
1164: #ifndef SMART_UPDATE
1165: #undef UNALIGNED_PROFITABLE
1166: #endif
1167:
1168: #ifdef UNALIGNED_PROFITABLE
1169:
1170: static void pfield_doline_unaligned_h (int lineno)
1171: {
1172: int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
1173:
1.1.1.5 root 1174: if (bplres == RES_HIRES) {
1.1 root 1175: int xpos1 = xpos + 16 + bpldelay1*2;
1176: int xpos2;
1177: uae_u8 *dataptr = line_data[lineno];
1178: int len = dp_for_drawing->plflinelen >> 1;
1179:
1180: if (len <= 0)
1181: return;
1182:
1183: if (bpldelay1 == bpldelay2) {
1184: switch (bplplanecnt) {
1185: case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1186: case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1187: case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1188: case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1189: case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1190: case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1191: case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1192: case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1193: }
1194: } else {
1195: switch (bplplanecnt) {
1196: case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1197: case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1198: case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1199: case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1200: }
1201:
1202: xpos2 = xpos + 16 + bpldelay2*2;
1203: switch (bplplanecnt) {
1204: case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1205: case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1206: case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1207: case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1208: }
1209: }
1210: } else {
1211: int xpos1 = xpos + 32 + bpldelay1*2;
1212: int xpos2;
1213: uae_u8 *dataptr = line_data[lineno];
1214: int len = dp_for_drawing->plflinelen >> 2;
1215:
1216: if (len <= 0)
1217: return;
1218:
1219: if (bpldelay1 == bpldelay2) {
1220: switch (bplplanecnt) {
1221: case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1222: case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1223: case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1224: case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1225: case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1226: case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1227: case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1228: case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1229: }
1230: } else {
1231: switch (bplplanecnt) {
1232: case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1233: case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1234: case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1235: case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1236: }
1237:
1238: xpos2 = xpos + 32 + bpldelay2*2;
1239: switch (bplplanecnt) {
1240: case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1241: case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1242: case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1243: case 8: set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1244: }
1245: }
1246: }
1247: }
1248:
1249: static void pfield_doline_unaligned_l (int lineno)
1250: {
1251: int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
1252:
1.1.1.5 root 1253: if (bplres == RES_HIRES) {
1.1 root 1254: int xpos1 = xpos + 8 + bpldelay1;
1255: int xpos2;
1256: uae_u8 *dataptr = line_data[lineno];
1257: int len = dp_for_drawing->plflinelen >> 1;
1258:
1259: if (len <= 0)
1260: return;
1261:
1262: if (bpldelay1 == bpldelay2) {
1263: switch (bplplanecnt) {
1264: case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1265: case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1266: case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1267: case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1268: case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1269: case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1270: case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1271: case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1272: }
1273: } else {
1274: switch (bplplanecnt) {
1275: case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1276: case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1277: case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1278: case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1279: }
1280:
1281: xpos2 = xpos + 8 + bpldelay2;
1282: switch (bplplanecnt) {
1283: case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1284: case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1285: case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1286: case 8: set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1287: }
1288: }
1289: } else {
1290: int xpos1 = xpos + 16 + bpldelay1;
1291: int xpos2;
1292: uae_u8 *dataptr = line_data[lineno];
1293: int len = dp_for_drawing->plflinelen >> 2;
1294:
1295: if (len <= 0)
1296: return;
1297:
1298: if (bpldelay1 == bpldelay2) {
1299: switch (bplplanecnt) {
1300: case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1301: case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1302: case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1303: case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1304: case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1305: case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1306: case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1307: case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1308: }
1309: } else {
1310: switch (bplplanecnt) {
1311: case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1312: case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1313: case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1314: case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1315: }
1316:
1317: xpos2 = xpos + 16 + bpldelay2;
1318: switch (bplplanecnt) {
1319: case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1320: case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1321: case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1322: case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1323: }
1324: }
1325: }
1326: }
1327:
1328: #define pfield_doline_h pfield_doline_unaligned_h
1329: #define pfield_doline_l pfield_doline_unaligned_l
1330:
1331: #else /* not UNALIGNED_PROFITABLE */
1332:
1333:
1.1.1.6 root 1334: STATIC_INLINE void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
1.1 root 1335: {
1336: uae_u32 *pixptr = (uae_u32 *)dp;
1337:
1338: *pixptr |= hirestab_h[data >> 8][0] << bit;
1339: *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
1340: *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
1341: *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
1342: }
1343:
1.1.1.6 root 1344: STATIC_INLINE void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
1.1 root 1345: {
1346: uae_u32 *pixptr = (uae_u32 *)dp;
1347:
1348: *pixptr |= lorestab_h[data >> 8][0] << bit;
1349: *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
1350: *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
1351: *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
1352: *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
1353: *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
1354: *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
1355: *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
1356: }
1357:
1.1.1.6 root 1358: STATIC_INLINE void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
1.1 root 1359: {
1360: uae_u32 *pixptr = (uae_u32 *)dp;
1361:
1362: *pixptr = hirestab_h[data >> 8][0] << bit;
1363: *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
1364: *(pixptr+2) = hirestab_h[data & 255][0] << bit;
1365: *(pixptr+3) = hirestab_h[data & 255][1] << bit;
1366: }
1367:
1.1.1.6 root 1368: STATIC_INLINE void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
1.1 root 1369: {
1370: uae_u32 *pixptr = (uae_u32 *)dp;
1371:
1372: *pixptr = lorestab_h[data >> 8][0] << bit;
1373: *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
1374: *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
1375: *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
1376: *(pixptr+4) = lorestab_h[data & 255][0] << bit;
1377: *(pixptr+5) = lorestab_h[data & 255][1] << bit;
1378: *(pixptr+6) = lorestab_h[data & 255][2] << bit;
1379: *(pixptr+7) = lorestab_h[data & 255][3] << bit;
1380: }
1381:
1.1.1.6 root 1382: STATIC_INLINE void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
1.1 root 1383: {
1384: uae_u32 *pixptr = (uae_u32 *)dp;
1385:
1386: *pixptr |= hirestab_l[data >> 8][0] << bit;
1387: *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
1388: }
1389:
1.1.1.6 root 1390: STATIC_INLINE void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
1.1 root 1391: {
1392: uae_u32 *pixptr = (uae_u32 *)dp;
1393:
1394: *pixptr |= lorestab_l[data >> 8][0] << bit;
1395: *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
1396: *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
1397: *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
1398: }
1399:
1.1.1.6 root 1400: STATIC_INLINE void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
1.1 root 1401: {
1402: uae_u32 *pixptr = (uae_u32 *)dp;
1403:
1404: *pixptr = hirestab_l[data >> 8][0] << bit;
1405: *(pixptr+1) = hirestab_l[data & 255][0] << bit;
1406: }
1407:
1.1.1.6 root 1408: STATIC_INLINE void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
1.1 root 1409: {
1410: uae_u32 *pixptr = (uae_u32 *)dp;
1411:
1412: *pixptr = lorestab_l[data >> 8][0] << bit;
1413: *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
1414: *(pixptr+2) = lorestab_l[data & 255][0] << bit;
1415: *(pixptr+3) = lorestab_l[data & 255][1] << bit;
1416: }
1417:
1418: #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
1419: int i; \
1420: unsigned int bpldat1; \
1421: uae_u16 data; \
1422: unsigned int bpldat2 = 0; \
1423: uae_u8 *ptr = (POINTER); \
1424: for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \
1425: bpldat1 = bpldat2; \
1426: bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \
1427: ptr+=2; \
1428: data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
1429: FUNC(data, app, MULT); \
1430: app += P_ADD; \
1431: } \
1432: data = bpldat2 << (16 - DELAY); \
1433: FUNC(data, app, MULT); \
1434: }
1435:
1436: #ifdef SMART_UPDATE
1437: #define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2)
1438: #else
1439: #define DATA_POINTER(n) (real_bplpt[n])
1440: #endif
1441:
1442: static void pfield_doline_aligned_h (int lineno)
1443: {
1444: int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
1445:
1.1.1.5 root 1446: if (bplres == RES_HIRES) {
1.1 root 1447: if (bplplanecnt > 0) {
1448: int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
1449: int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
1450: int delay1 = 2*(bpldelay1 & 7);
1451: int delay2 = 2*(bpldelay2 & 7);
1452: unsigned char *app = pixdata.apixels + xpos1;
1453: uae_u8 *dataptr = line_data[lineno];
1454:
1455: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16);
1456: if (bplplanecnt > 2) {
1457: app = pixdata.apixels + xpos1;
1458: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16);
1459: }
1460: #if AGA_CHIPSET == 1
1461: if (bplplanecnt > 4) {
1462: app = pixdata.apixels + xpos1;
1463: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16);
1464: }
1465: if (bplplanecnt > 6) {
1466: app = pixdata.apixels + xpos1;
1467: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16);
1468: }
1469: #endif
1470: if (bplplanecnt > 1) {
1471: app = pixdata.apixels + xpos2;
1472: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16);
1473: }
1474: if (bplplanecnt > 3) {
1475: app = pixdata.apixels + xpos2;
1476: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16);
1477: }
1478: #if AGA_CHIPSET == 1
1479: if (bplplanecnt > 5) {
1480: app = pixdata.apixels + xpos2;
1481: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16);
1482: }
1483: if (bplplanecnt > 7) {
1484: app = pixdata.apixels + xpos2;
1485: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16);
1486: }
1487: #endif
1488: } else {
1.1.1.5 root 1489: memset (pixdata.apixels, 0, sizeof(pixdata.apixels));
1.1 root 1490: }
1491: } else {
1492: if (bplplanecnt > 0) {
1493: int x = xpos + 32;
1494: unsigned char *app = pixdata.apixels + x;
1495: uae_u8 *dataptr = line_data[lineno];
1496:
1497: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32);
1498: if (bplplanecnt > 2) {
1499: app = pixdata.apixels + x;
1500: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32);
1501: }
1502: if (bplplanecnt > 4) {
1503: app = pixdata.apixels + x;
1504: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32);
1505: }
1506: #if AGA_CHIPSET == 1
1507: if (bplplanecnt > 6) {
1508: app = pixdata.apixels + x;
1509: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32);
1510: }
1511: #endif
1512: if (bplplanecnt > 1) {
1513: app = pixdata.apixels + x;
1514: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32);
1515: }
1516: if (bplplanecnt > 3) {
1517: app = pixdata.apixels + x;
1518: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32);
1519: }
1520: if (bplplanecnt > 5) {
1521: app = pixdata.apixels + x;
1522: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32);
1523: }
1524: #if AGA_CHIPSET == 1
1525: if (bplplanecnt > 7) {
1526: app = pixdata.apixels + x;
1527: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32);
1528: }
1529: #endif
1530: } else {
1.1.1.5 root 1531: memset (pixdata.apixels, 0, sizeof(pixdata.apixels));
1.1 root 1532: }
1533: }
1534: }
1535:
1536: static void pfield_doline_aligned_l (int lineno)
1537: {
1538: int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
1539:
1.1.1.5 root 1540: if (bplres == RES_HIRES) {
1.1 root 1541: if (bplplanecnt > 0) {
1542: int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
1543: int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
1544: int delay1 = (bpldelay1 & 7) * 2;
1545: int delay2 = (bpldelay2 & 7) * 2;
1546: unsigned char *app = pixdata.apixels + xpos1;
1547: uae_u8 *dataptr = line_data[lineno];
1548:
1549: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8);
1550: if (bplplanecnt > 2) {
1551: app = pixdata.apixels + xpos1;
1552: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8);
1553: }
1554: #if AGA_CHIPSET == 1
1555: if (bplplanecnt > 4) {
1556: app = pixdata.apixels + xpos1;
1557: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8);
1558: }
1559: if (bplplanecnt > 6) {
1560: app = pixdata.apixels + xpos1;
1561: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8);
1562: }
1563: #endif
1564: if (bplplanecnt > 1) {
1565: app = pixdata.apixels + xpos2;
1566: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8);
1567: }
1568: if (bplplanecnt > 3) {
1569: app = pixdata.apixels + xpos2;
1570: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8);
1571: }
1572: #if AGA_CHIPSET == 1
1573: if (bplplanecnt > 5) {
1574: app = pixdata.apixels + xpos2;
1575: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8);
1576: }
1577: if (bplplanecnt > 7) {
1578: app = pixdata.apixels + xpos2;
1579: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8);
1580: }
1581: #endif
1582: } else {
1583: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
1584: }
1585: } else {
1586: if (bplplanecnt > 0) {
1587: int x = xpos + 16;
1588: int delay1 = bpldelay1;
1589: int delay2 = bpldelay2;
1590: unsigned char *app = pixdata.apixels + x;
1591: uae_u8 *dataptr = line_data[lineno];
1592:
1593: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16);
1594: if (bplplanecnt > 2) {
1595: app = pixdata.apixels + x;
1596: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16);
1597: }
1598: if (bplplanecnt > 4) {
1599: app = pixdata.apixels + x;
1600: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16);
1601: }
1602: #if AGA_CHIPSET == 1
1603: if (bplplanecnt > 6) {
1604: app = pixdata.apixels + x;
1605: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16);
1606: }
1607: #endif
1608: if (bplplanecnt > 1) {
1609: app = pixdata.apixels + x;
1610: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16);
1611: }
1612: if (bplplanecnt > 3) {
1613: app = pixdata.apixels + x;
1614: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16);
1615: }
1616: if (bplplanecnt > 5) {
1617: app = pixdata.apixels + x;
1618: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16);
1619: }
1620: #if AGA_CHIPSET == 1
1621: if (bplplanecnt > 7) {
1622: app = pixdata.apixels + x;
1623: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16);
1624: }
1625: #endif
1626: } else {
1627: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
1628: }
1629: }
1630: }
1631:
1632: #define pfield_doline_h pfield_doline_aligned_h
1633: #define pfield_doline_l pfield_doline_aligned_l
1634:
1635: #endif /* UNALIGNED_PROFITABLE */
1636:
1637: static void pfield_adjust_delay (void)
1638: {
1639: int ddf_left = dp_for_drawing->plfstrt;
1640: int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen;
1641: int i;
1642:
1643: for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) {
1644: int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value;
1645: int delay1 = delayreg & 0xF;
1646: int delay2 = (delayreg >> 4) & 0xF;
1647: int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos;
1648: int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos;
1649: int j;
1.1.1.5 root 1650: startpos = PIXEL_XPOS (startpos + RES_ADJUST (bplres));
1651: stoppos = PIXEL_XPOS (stoppos + RES_ADJUST (bplres));
1.1 root 1652: if (currprefs.gfx_lores == 0)
1653: delay1 <<= 1, delay2 <<= 1;
1654: else if (currprefs.gfx_lores == 2)
1655: startpos >>= 1, stoppos >>= 1;
1656: for (j = startpos-1; j >= stoppos; j--) {
1657: pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA);
1658: }
1659: }
1660: }
1661:
1662: void init_row_map (void)
1663: {
1664: int i;
1665: if (gfxvidinfo.height > 2048) {
1666: write_log ("Resolution too high, aborting\n");
1667: abort ();
1668: }
1669: for (i = 0; i < gfxvidinfo.height + 1; i++)
1670: row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
1671: }
1672:
1673: static void init_aspect_maps (void)
1674: {
1675: int i, maxl;
1676: double native_lines_per_amiga_line;
1677:
1678: if (native2amiga_line_map)
1679: free (native2amiga_line_map);
1680: if (amiga2aspect_line_map)
1681: free (amiga2aspect_line_map);
1682:
1683: /* At least for this array the +1 is necessary. */
1.1.1.5 root 1684: amiga2aspect_line_map = (int *)malloc (sizeof (int) * (MAXVPOS + 1)*2 + 1);
1.1 root 1685: native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
1686:
1687: if (currprefs.gfx_correct_aspect)
1688: native_lines_per_amiga_line = ((double)gfxvidinfo.height
1689: * (currprefs.gfx_lores ? 320 : 640)
1690: / (currprefs.gfx_linedbl ? 512 : 256)
1691: / gfxvidinfo.width);
1692: else
1693: native_lines_per_amiga_line = 1;
1694:
1.1.1.5 root 1695: maxl = (MAXVPOS + 1) * (currprefs.gfx_linedbl ? 2 : 1);
1.1 root 1696: min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
1697: max_drawn_amiga_line = -1;
1698: for (i = 0; i < maxl; i++) {
1699: int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line;
1700: if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
1701: max_drawn_amiga_line = i - min_ypos_for_screen;
1702: if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
1703: v = -1;
1704: amiga2aspect_line_map[i] = v;
1705: }
1706: if (currprefs.gfx_linedbl)
1707: max_drawn_amiga_line >>= 1;
1708:
1709: if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
1.1.1.5 root 1710: /* @@@ verify maxvpos vs. MAXVPOS */
1.1 root 1711: extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
1712: if (extra_y_adjust < 0)
1713: extra_y_adjust = 0;
1714: }
1715:
1716: for (i = 0; i < gfxvidinfo.height; i++)
1717: native2amiga_line_map[i] = -1;
1718:
1719: if (native_lines_per_amiga_line < 1) {
1720: /* Must omit drawing some lines. */
1721: for (i = maxl - 1; i > min_ypos_for_screen; i--) {
1722: if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
1723: if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
1724: /* If only the first line of a line pair would be omitted,
1725: * omit the second one instead to avoid problems with line
1726: * doubling. */
1727: amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
1728: amiga2aspect_line_map[i+1] = -1;
1729: } else
1730: amiga2aspect_line_map[i] = -1;
1731: }
1732: }
1733: }
1734:
1735: for (i = maxl-1; i >= min_ypos_for_screen; i--) {
1736: int j;
1737: if (amiga2aspect_line_map[i] == -1)
1738: continue;
1739: for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
1740: native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
1741: }
1742: }
1743:
1744: /*
1745: * A raster line has been built in the graphics buffer. Tell the graphics code
1746: * to do anything necessary to display it.
1747: */
1748: static void do_flush_line_1 (int lineno)
1749: {
1750: if (lineno < first_drawn_line)
1751: first_drawn_line = lineno;
1752: if (lineno > last_drawn_line)
1753: last_drawn_line = lineno;
1754:
1755: if (gfxvidinfo.maxblocklines == 0)
1756: flush_line(lineno);
1757: else {
1758: if ((last_block_line+1) != lineno) {
1759: if (first_block_line != -2)
1760: flush_block (first_block_line, last_block_line);
1761: first_block_line = lineno;
1762: }
1763: last_block_line = lineno;
1764: if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
1765: flush_block (first_block_line, last_block_line);
1766: first_block_line = last_block_line = -2;
1767: }
1768: }
1769: }
1770:
1.1.1.6 root 1771: STATIC_INLINE void do_flush_line (int lineno)
1.1 root 1772: {
1773: /* We don't want to call X libraries from the second thread right now. */
1774: #ifndef SUPPORT_PENGUINS
1775: do_flush_line_1 (lineno);
1776: #else
1777: line_drawn[lineno] = 1;
1778: #endif
1779: }
1780:
1781: /*
1782: * One drawing frame has been finished. Tell the graphics code about it.
1783: * Note that the actual flush_screen() call is a no-op for all reasonable
1784: * systems.
1785: */
1786:
1.1.1.6 root 1787: STATIC_INLINE void do_flush_screen (int start, int stop)
1.1 root 1788: {
1789: #ifdef SUPPORT_PENGUINS
1790: int i;
1791: for (i = 0; i < gfxvidinfo.height; i++) {
1792: if (line_drawn[i])
1793: do_flush_line_1 (i);
1794: }
1795: #endif
1.1.1.6 root 1796:
1797: /* TODO: this flush operation is executed outside locked state!
1798: Should be corrected.
1799: (sjo 26.9.99) */
1800:
1.1 root 1801: if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
1802: flush_block (first_block_line, last_block_line);
1803: }
1804: if (start <= stop)
1805: flush_screen (start, stop);
1806: }
1807:
1.1.1.6 root 1808: STATIC_INLINE void finish_line_aga (void)
1.1.1.2 root 1809: {
1810: #if AGA_CHIPSET != 0
1811: aga_lbufptr = aga_linebuf;
1812: aga_translate32 (linetoscr_x_adjust_bytes, linetoscr_x_adjust_bytes + gfxvidinfo.width);
1813: #endif
1814: }
1815:
1.1 root 1816: static int drawing_color_matches;
1817: static enum { color_match_acolors, color_match_full } color_match_type;
1818:
1819: static void adjust_drawing_colors (int ctable, int bplham)
1820: {
1.1.1.2 root 1821: #if AGA_CHIPSET == 0
1.1 root 1822: if (drawing_color_matches != ctable) {
1823: if (bplham) {
1824: memcpy (&colors_for_drawing, curr_color_tables + ctable,
1825: sizeof colors_for_drawing);
1826: color_match_type = color_match_full;
1827: } else {
1828: memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
1829: sizeof colors_for_drawing.acolors);
1830: color_match_type = color_match_acolors;
1831: }
1832: drawing_color_matches = ctable;
1833: } else if (bplham && color_match_type != color_match_full) {
1834: memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs,
1835: sizeof colors_for_drawing.color_regs);
1836: color_match_type = color_match_full;
1837: }
1.1.1.2 root 1838: #else
1839: if (drawing_color_matches != ctable) {
1840: memcpy (&colors_for_drawing, curr_color_tables + ctable,
1841: sizeof colors_for_drawing);
1842: drawing_color_matches = ctable;
1843: }
1844: #endif
1.1 root 1845: }
1846:
1.1.1.6 root 1847: STATIC_INLINE void adjust_color0_for_color_change (void)
1.1 root 1848: {
1849: drawing_color_matches = -1;
1850: if (dp_for_drawing->color0 != 0xFFFFFFFFul) {
1851: colors_for_drawing.color_regs[0] = dp_for_drawing->color0;
1.1.1.2 root 1852: #if AGA_CHIPSET == 0
1.1 root 1853: colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0];
1.1.1.2 root 1854: #endif
1.1 root 1855: }
1856: }
1857:
1.1.1.7 ! root 1858: #define COPPER_MAGIC_FUDGE -1
1.1 root 1859:
1.1.1.6 root 1860: STATIC_INLINE void do_color_changes (line_draw_func worker)
1.1 root 1861: {
1862: int lastpos = 0, nextpos, i;
1863: struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change;
1864:
1865: for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) {
1866: if (i == dip_for_drawing->last_color_change)
1867: nextpos = max_diwlastword;
1868: else
1869: nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift);
1870: worker (lastpos, nextpos);
1871: if (i != dip_for_drawing->last_color_change) {
1872: colors_for_drawing.color_regs[cc->regno] = cc->value;
1.1.1.2 root 1873: #if AGA_CHIPSET == 0
1.1 root 1874: colors_for_drawing.acolors[cc->regno] = xcolors[cc->value];
1.1.1.2 root 1875: #endif
1.1 root 1876: }
1877: if (nextpos > lastpos) {
1878: lastpos = nextpos;
1879: if (lastpos >= linetoscr_right_x)
1880: break;
1881: }
1882: }
1883: }
1884:
1885: /* We only save hardware registers during the hardware frame. Now, when
1886: * drawing the frame, we expand the data into a slightly more useful
1887: * form. */
1888: static void pfield_expand_dp_bplcon (void)
1889: {
1.1.1.5 root 1890: bplres = RES_LORES;
1891: if (dp_for_drawing->bplcon0 & 0x8000)
1892: bplres = RES_HIRES;
1893: if (dp_for_drawing->bplcon0 & 0x40)
1894: bplres = RES_SUPERHIRES;
1.1.1.3 root 1895: bplplanecnt = GET_PLANES (dp_for_drawing->bplcon0);
1.1 root 1896: bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
1897: #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
1898: * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
1899: bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
1900: #else
1901: bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
1902: #endif
1903: bpldelay1 = dp_for_drawing->bplcon1 & 0xF;
1904: bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF;
1905: plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7);
1906: plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7);
1907: bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
1908: bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
1909: }
1910:
1911: enum double_how {
1912: dh_buf,
1913: dh_line,
1914: dh_emerg
1915: };
1916:
1.1.1.6 root 1917: STATIC_INLINE void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos)
1.1 root 1918: {
1919: int border = 0;
1920: int do_double = 0;
1921: enum double_how dh;
1922:
1.1.1.2 root 1923: dp_for_drawing = line_decisions + lineno;
1924: dip_for_drawing = curr_drawinfo + lineno;
1.1 root 1925: switch (linestate[lineno]) {
1926: case LINE_REMEMBERED_AS_PREVIOUS:
1927: {
1928: static int warned = 0;
1929: if (!warned)
1930: write_log ("Shouldn't get here... this is a bug.\n"), warned++;
1931: }
1932: line_decisions[lineno].which = -2;
1933: return;
1934:
1.1.1.2 root 1935: case LINE_BLACK:
1936: line_decisions[lineno].which = -2;
1937: linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
1938: border = 2;
1.1 root 1939: break;
1940:
1.1.1.2 root 1941: case LINE_REMEMBERED_AS_BLACK:
1942: return;
1943:
1944: case LINE_AS_PREVIOUS:
1945: dp_for_drawing--;
1946: dip_for_drawing--;
1947: if (dp_for_drawing->which != 1)
1948: border = 1;
1949: line_decisions[lineno].which = -2;
1950: linestate[lineno] = LINE_DONE_AS_PREVIOUS;
1.1 root 1951: break;
1952:
1953: case LINE_DONE_AS_PREVIOUS:
1954: line_decisions[lineno].which = -2;
1955: /* fall through */
1956: case LINE_DONE:
1957: return;
1958:
1959: case LINE_DECIDED_DOUBLE:
1960: line_decisions[lineno+1].which = -2;
1961: if (follow_ypos != -1) {
1962: do_double = 1;
1963: linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
1.1.1.2 root 1964: linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
1.1 root 1965: }
1966:
1967: /* fall through */
1968: default:
1969: if (dp_for_drawing->which != 1)
1970: border = 1;
1971: linestate[lineno] = LINE_DONE;
1.1.1.2 root 1972: break;
1.1 root 1973: }
1974:
1975: dh = dh_line;
1976: xlinebuffer = gfxvidinfo.linemem;
1.1.1.2 root 1977: if (xlinebuffer == 0 && do_double && border != 2 && dip_for_drawing->nr_color_changes != 0)
1.1 root 1978: xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg;
1979: if (xlinebuffer == 0)
1980: xlinebuffer = row_map[gfx_ypos], dh = dh_buf;
1981: xlinebuffer -= linetoscr_x_adjust_bytes;
1982: aga_lbufptr = aga_linebuf;
1983:
1.1.1.2 root 1984: if (border == 0) {
1.1 root 1985: pfield_expand_dp_bplcon ();
1986:
1987: #ifdef LORES_HACK
1.1.1.5 root 1988: if (gfxvidinfo.can_double && bplres == RES_LORES && !currprefs.gfx_lores
1.1 root 1989: && dip_for_drawing->nr_color_changes == 0 && !bplham)
1990: currprefs.gfx_lores = 2;
1991: #endif
1992: pfield_init_linetoscr ();
1993: if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) {
1994: bpldelay1 = bpldelay2 = 0;
1995: if (currprefs.gfx_lores)
1996: pfield_doline_l (lineno);
1997: else
1998: pfield_doline_h (lineno);
1999: pfield_adjust_delay ();
2000: } else {
2001: if (currprefs.gfx_lores)
2002: pfield_doline_l (lineno);
2003: else
2004: pfield_doline_h (lineno);
2005: }
2006:
2007: /* Check color0 adjust only if we have color changes - shouldn't happen
2008: * otherwise. */
2009: adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
2010:
2011: /* The problem is that we must call decode_ham6() BEFORE we do the
2012: * sprites. */
2013: if (bplham) {
2014: init_ham_decoding(linetoscr_x_adjust);
2015: if (dip_for_drawing->nr_color_changes == 0) {
2016: /* The easy case: need to do HAM decoding only once for the
2017: * full line. */
2018: decode_ham6 (linetoscr_x_adjust, linetoscr_right_x);
2019: } else /* Argh. */ {
2020: adjust_color0_for_color_change ();
2021: do_color_changes (decode_ham6);
2022: adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
2023: }
2024: }
2025:
2026: if (dip_for_drawing->nr_sprites != 0)
2027: walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites);
2028:
2029: if (dip_for_drawing->nr_color_changes == 0) {
2030: pfield_do_linetoscr_full (dh == dh_buf ? do_double : 0);
1.1.1.2 root 2031: finish_line_aga ();
1.1 root 2032: do_flush_line (gfx_ypos);
2033: #if 0
2034: if (dh == dh_emerg)
2035: abort ();
2036: #endif
2037: if (do_double) {
2038: /* If dh == dh_line, do_flush_line will re-use the rendered line
2039: * from linemem. If dh == dh_buf, the line will have been doubled
2040: * by pfield_do_linetoscr_full. */
2041: do_flush_line (follow_ypos);
2042: }
2043: } else {
2044: adjust_color0_for_color_change ();
2045: do_color_changes (pfield_do_linetoscr);
1.1.1.2 root 2046: finish_line_aga ();
1.1 root 2047:
2048: if (dh == dh_emerg)
2049: memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
2050:
2051: do_flush_line (gfx_ypos);
2052: if (do_double) {
2053: if (dh == dh_emerg)
2054: memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
2055: else if (dh == dh_buf)
2056: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
2057: line_decisions[lineno + 1].which = -2;
2058: do_flush_line (follow_ypos);
2059: }
2060: }
2061: #ifdef LORES_HACK
2062: if (currprefs.gfx_lores == 2)
2063: currprefs.gfx_lores = 0;
2064: #endif
1.1.1.2 root 2065: } else if (border == 1) {
1.1 root 2066: adjust_drawing_colors (dp_for_drawing->ctable, 0);
2067:
2068: /* Check color0 adjust only if we have color changes - shouldn't happen
2069: * otherwise. */
2070:
2071: if (dip_for_drawing->nr_color_changes == 0) {
2072: fill_line ();
2073: do_flush_line (gfx_ypos);
2074: #if 0
2075: if (dh == dh_emerg)
2076: abort ();
2077: #endif
2078: if (do_double) {
2079: if (dh == dh_buf) {
2080: xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
2081: fill_line ();
2082: }
2083: /* If dh == dh_line, do_flush_line will re-use the rendered line
2084: * from linemem. */
2085: do_flush_line (follow_ypos);
2086: }
2087: return;
2088: }
2089:
2090: adjust_color0_for_color_change ();
2091: do_color_changes (pfield_do_fill_line);
2092:
2093: if (dh == dh_emerg)
2094: memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
2095:
2096: do_flush_line (gfx_ypos);
2097: if (do_double) {
2098: if (dh == dh_emerg)
2099: memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
2100: else if (dh == dh_buf)
2101: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
2102: /* If dh == dh_line, do_flush_line will re-use the rendered line
2103: * from linemem. */
2104: do_flush_line (follow_ypos);
2105: line_decisions[lineno + 1].which = -2;
2106: }
1.1.1.2 root 2107: } else {
2108: #if AGA_CHIPSET == 0
2109: xcolnr tmp = colors_for_drawing.acolors[0];
2110: colors_for_drawing.acolors[0] = xcolors[0];
2111: fill_line ();
2112: do_flush_line (gfx_ypos);
2113: colors_for_drawing.acolors[0] = tmp;
2114: #endif
1.1 root 2115: }
2116: }
2117:
2118: #ifdef SUPPORT_PENGUINS
2119: static smp_comm_pipe drawing_pipe;
2120: static uae_sem_t drawing_lock;
2121:
2122: static void *drawing_penguin (void *cruxmedo)
2123: {
2124: int l;
2125: fprintf (stderr, "Hello, world!\n");
2126:
2127: for (;;) {
2128: /* Start of a frame. */
2129: int k;
2130: new_frame:
2131: k = read_comm_pipe_int_blocking (&drawing_pipe);
2132:
2133: switch (k) {
2134: case -2:
2135: /* Hoopy */
2136: break;
2137:
2138: default:
2139: write_log ("Penguin got out of sync.\n");
2140: /* what can we do? Try to reduce the damage */
2141: for (;;) {
2142: k = read_comm_pipe_int_blocking (&drawing_pipe);
2143: if (k == -3)
2144: break;
2145: if (k == -1) {
2146: uae_sem_post (&drawing_lock);
2147: goto new_frame;
2148: }
2149: }
2150: case -3:
2151: UAE_PENGUIN_EXIT;
2152: /* Can't happen */
2153: return 0;
2154: }
2155:
2156: for (;;) {
2157: int i, where;
2158: int l = read_comm_pipe_int_blocking (&drawing_pipe);
2159: switch (l) {
2160: case -1:
2161: /* End-of-frame synchronization. */
2162: uae_sem_post (&drawing_lock);
2163: goto new_frame;
2164: case -2:
2165: /* customreset called a bit too often. That's harmless. */
2166: continue;
2167: case -3:
2168: write_log ("Penguin got out of sync.\n");
2169: UAE_PENGUIN_EXIT;
2170: return 0;
2171: }
2172:
2173: /* l is the line that has been finished for drawing. */
2174: i = l - thisframe_y_adjust_real;
2175: if (i < 0 || i >= max_ypos_thisframe)
2176: continue;
2177:
2178: if (linestate[l] == LINE_UNDECIDED) {
2179: fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l);
2180: continue;
2181: }
2182: if (inhibit_frame != 0)
2183: continue;
2184: where = amiga2aspect_line_map[i+min_ypos_for_screen];
2185: if (where >= gfxvidinfo.height || where == -1)
2186: continue;
2187:
2188: pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
2189: }
2190: }
2191: }
2192:
2193: static penguin_id our_penguin;
2194:
2195: static void kill_drawing_penguin (void)
2196: {
2197: /* ??? does libpthread do that for us? */
2198: }
2199:
2200: #endif
2201:
2202: static int penguins_enabled_thisframe;
2203:
2204: static void center_image (void)
2205: {
2206: prev_x_adjust = linetoscr_x_adjust;
2207: prev_y_adjust = thisframe_y_adjust;
2208:
2209: if (currprefs.gfx_xcenter) {
2210: if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
2211: /* Try to center. */
2212: linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
2213: else
2214: linetoscr_x_adjust = max_diwstop - gfxvidinfo.width;
2215:
2216: /* Would the old value be good enough? If so, leave it as it is if we want to
2217: * be clever. */
2218: if (currprefs.gfx_xcenter == 2) {
2219: if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart)
2220: linetoscr_x_adjust = prev_x_adjust;
2221: }
2222: } else
2223: linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width;
2224: if (linetoscr_x_adjust < 0)
2225: linetoscr_x_adjust = 0;
2226:
2227: linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes;
2228:
2229: linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width;
2230: if (linetoscr_right_x > max_diwlastword)
2231: linetoscr_right_x = max_diwlastword;
2232:
2233: thisframe_y_adjust = minfirstline;
2234: if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
2235: if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
2236: thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
2237: else
2238: thisframe_y_adjust = thisframe_first_drawn_line;
2239: /* Would the old value be good enough? If so, leave it as it is if we want to
2240: * be clever. */
2241: if (currprefs.gfx_ycenter == 2) {
2242: if (thisframe_y_adjust != prev_y_adjust
2243: && prev_y_adjust <= thisframe_first_drawn_line
2244: && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
2245: thisframe_y_adjust = prev_y_adjust;
2246: }
2247: /* Make sure the value makes sense */
2248: if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
2249: thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
2250: if (thisframe_y_adjust < minfirstline)
2251: thisframe_y_adjust = minfirstline;
2252: }
2253: thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
2254: max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
2255:
2256: /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably
2257: * better. */
2258: if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust)
2259: frame_redraw_necessary |= interlace_seen && currprefs.gfx_linedbl ? 2 : 1;
2260:
2261: max_diwstop = 0;
2262: min_diwstart = 10000;
2263: }
2264:
2265: static void init_drawing_frame (void)
2266: {
2267: int i, maxline;
2268:
2269: init_hardware_for_drawing_frame ();
2270:
2271: if (max_diwstop == 0)
2272: max_diwstop = diwlastword;
2273: if (min_diwstart > max_diwstop)
2274: min_diwstart = 0;
2275:
2276: if (thisframe_first_drawn_line == -1)
2277: thisframe_first_drawn_line = minfirstline;
2278: if (thisframe_first_drawn_line > thisframe_last_drawn_line)
2279: thisframe_last_drawn_line = thisframe_first_drawn_line;
2280:
2281: maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
2282: #ifdef SMART_UPDATE
1.1.1.2 root 2283: for (i = 0; i < maxline; i++) {
2284: switch (linestate[i]) {
2285: case LINE_DONE_AS_PREVIOUS:
2286: linestate[i] = LINE_REMEMBERED_AS_PREVIOUS;
2287: break;
2288: case LINE_REMEMBERED_AS_BLACK:
2289: break;
2290: default:
2291: linestate[i] = LINE_UNDECIDED;
2292: break;
2293: }
2294: }
1.1 root 2295: #else
2296: memset (linestate, LINE_UNDECIDED, maxline);
2297: #endif
2298: last_drawn_line = 0;
2299: first_drawn_line = 32767;
2300:
2301: first_block_line = last_block_line = -2;
2302: if (currprefs.test_drawing_speed)
2303: frame_redraw_necessary = 1;
2304: else if (frame_redraw_necessary)
2305: frame_redraw_necessary--;
2306:
2307: center_image ();
2308:
2309: thisframe_first_drawn_line = -1;
2310: thisframe_last_drawn_line = -1;
2311: #ifdef SUPPORT_PENGUINS
2312: penguins_enabled_thisframe = 1;
2313: /* Tell the other thread that it can now expect data from us. */
2314: write_comm_pipe_int (&drawing_pipe, -2, 1);
2315: memset (line_drawn, 0, sizeof line_drawn);
2316: #endif
2317:
2318: drawing_color_matches = -1;
2319: }
2320:
2321: void finish_drawing_frame (void)
2322: {
2323: int i;
2324:
2325: #ifdef SUPPORT_PENGUINS
2326: /* Synchronize with other thread, then see whether there's something left for
2327: * us to draw. @@@ This is probably a big waste of cycles if the two threads
2328: * run at very different speeds - this one could draw stuff as well. */
2329: write_comm_pipe_int (&drawing_pipe, -1, 1);
2330: uae_sem_wait (&drawing_lock);
2331: #else
2332:
2333: #ifndef SMART_UPDATE
2334: /* @@@ This isn't exactly right yet. FIXME */
2335: if (!interlace_seen) {
2336: do_flush_screen (first_drawn_line, last_drawn_line);
2337: return;
2338: }
2339: #endif
2340: if (! lockscr ()) {
2341: notice_screen_contents_lost ();
2342: return;
2343: }
2344: for (i = 0; i < max_ypos_thisframe; i++) {
2345: int where;
2346: int line = i + thisframe_y_adjust_real;
2347:
2348: if (linestate[line] == LINE_UNDECIDED)
2349: break;
2350:
2351: where = amiga2aspect_line_map[i+min_ypos_for_screen];
2352: if (where >= gfxvidinfo.height)
2353: break;
2354: if (where == -1)
2355: continue;
2356:
2357: pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
2358: }
2359: unlockscr ();
2360: #endif
2361: do_flush_screen (first_drawn_line, last_drawn_line);
2362: }
2363:
2364: void hardware_line_completed (int lineno)
2365: {
2366: #ifdef SUPPORT_PENGUINS
2367: if (framecnt == 0 && penguins_enabled_thisframe) {
2368: write_comm_pipe_int (&drawing_pipe, lineno, 0);
2369: }
2370: #endif
2371: #ifndef SMART_UPDATE
2372: {
2373: int i, where;
2374: /* l is the line that has been finished for drawing. */
2375: i = lineno - thisframe_y_adjust_real;
2376: if (i >= 0 && i < max_ypos_thisframe) {
2377: where = amiga2aspect_line_map[i+min_ypos_for_screen];
2378: if (where < gfxvidinfo.height && where != -1)
2379: pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
2380: }
2381: }
2382: #endif
2383: }
2384:
1.1.1.6 root 2385: STATIC_INLINE void check_picasso (void)
1.1 root 2386: {
2387: #ifdef PICASSO96
2388: if (picasso_on && picasso_redraw_necessary)
2389: picasso_refresh ();
2390: picasso_redraw_necessary = 0;
2391:
2392: if (picasso_requested_on == picasso_on)
2393: return;
2394:
2395: picasso_on = picasso_requested_on;
2396:
2397: if (!picasso_on)
1.1.1.3 root 2398: clear_inhibit_frame (IHF_PICASSO);
1.1 root 2399: else
1.1.1.3 root 2400: set_inhibit_frame (IHF_PICASSO);
1.1 root 2401:
2402: gfx_set_picasso_state (picasso_on);
2403: picasso_enablescreen (picasso_requested_on);
2404:
2405: notice_screen_contents_lost ();
2406: notice_new_xcolors ();
2407: #endif
2408: }
2409:
2410: void vsync_handle_redraw (int long_frame, int lof_changed)
2411: {
2412: last_redraw_point++;
2413: if (lof_changed || ! interlace_seen || last_redraw_point >= 2 || long_frame) {
2414: last_redraw_point = 0;
2415: interlace_seen = 0;
2416:
2417: if (framecnt == 0)
2418: finish_drawing_frame ();
2419:
2420: /* At this point, we have finished both the hardware and the
2421: * drawing frame. Essentially, we are outside of all loops and
2422: * can do some things which would cause confusion if they were
2423: * done at other times.
2424: */
2425:
2426: if (quit_program < 0) {
2427: quit_program = -quit_program;
1.1.1.3 root 2428: set_inhibit_frame (IHF_QUIT_PROGRAM);
1.1 root 2429: regs.spcflags |= SPCFLAG_BRK;
2430: filesys_prepare_reset ();
2431: #ifdef SUPPORT_PENGUINS
2432: if (quit_program == 1)
2433: /* Stop eating herring */
2434: write_comm_pipe_int (&drawing_pipe, -3, 1);
2435: #endif
2436: return;
2437: }
2438:
2439: count_frame ();
2440: check_picasso ();
2441:
1.1.1.2 root 2442: check_prefs_changed_audio ();
1.1 root 2443: check_prefs_changed_custom ();
2444: check_prefs_changed_cpu ();
2445: if (check_prefs_changed_gfx ()) {
2446: init_row_map ();
2447: init_aspect_maps ();
2448: notice_screen_contents_lost ();
2449: notice_new_xcolors ();
2450: }
2451:
2452: if (inhibit_frame != 0)
2453: framecnt = 1;
2454:
2455: if (framecnt == 0)
2456: init_drawing_frame ();
2457: }
2458: }
2459:
1.1.1.2 root 2460: void hsync_record_line_state (int lineno, enum nln_how how, int changed)
1.1 root 2461: {
1.1.1.2 root 2462: char *state;
1.1 root 2463: if (framecnt != 0)
2464: return;
1.1.1.2 root 2465:
2466: state = linestate + lineno;
2467: changed += frame_redraw_necessary;
2468:
1.1 root 2469: switch (how) {
2470: case nln_normal:
1.1.1.2 root 2471: *state = changed ? LINE_DECIDED : LINE_DONE;
1.1 root 2472: break;
2473: case nln_doubled:
1.1.1.2 root 2474: *state = changed ? LINE_DECIDED_DOUBLE : LINE_DONE;
2475: changed += state[1] != LINE_REMEMBERED_AS_PREVIOUS;
2476: state[1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS;
2477: break;
2478: case nln_nblack:
2479: *state = changed ? LINE_DECIDED : LINE_DONE;
2480: if (state[1] != LINE_REMEMBERED_AS_BLACK)
2481: state[1] = LINE_BLACK;
1.1 root 2482: break;
2483: case nln_lower:
1.1.1.2 root 2484: if (state[-1] == LINE_UNDECIDED)
2485: state[-1] = LINE_BLACK;
2486: *state = changed ? LINE_DECIDED : LINE_DONE;
1.1 root 2487: break;
2488: case nln_upper:
1.1.1.2 root 2489: *state = changed ? LINE_DECIDED : LINE_DONE;
2490: if (state[1] == LINE_UNDECIDED
2491: || state[1] == LINE_REMEMBERED_AS_PREVIOUS
2492: || state[1] == LINE_AS_PREVIOUS)
2493: state[1] = LINE_BLACK;
1.1 root 2494: break;
2495: }
2496: }
2497:
2498: void notice_interlace_seen (void)
2499: {
2500: interlace_seen = 1;
2501: penguins_enabled_thisframe = 0;
2502: }
2503:
2504: void reset_drawing (void)
2505: {
2506: int i;
2507:
2508: inhibit_frame = 0;
2509: uae_sem_init (&gui_sem, 0, 1);
2510:
2511: #ifdef PICASSO96
2512: InitPicasso96 ();
2513: picasso_on = 0;
2514: picasso_requested_on = 0;
2515: gfx_set_picasso_state (0);
2516: #endif
2517: max_diwstop = 0;
2518:
2519: lores_factor = currprefs.gfx_lores ? 1 : 2;
2520: lores_shift = currprefs.gfx_lores ? 0 : 1;
2521: sprite_width = currprefs.gfx_lores ? 16 : 32;
2522:
2523: /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */
2524: for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
2525: linestate[i] = LINE_UNDECIDED;
2526:
2527: xlinebuffer = gfxvidinfo.bufmem;
2528:
2529: init_aspect_maps ();
2530:
2531: if (line_drawn == 0)
2532: line_drawn = (char *)malloc (gfxvidinfo.height);
2533:
2534: init_row_map();
2535:
2536: last_redraw_point = 0;
2537:
2538: init_drawing_frame ();
2539: }
2540:
2541: void drawing_init ()
2542: {
2543: native2amiga_line_map = 0;
2544: amiga2aspect_line_map = 0;
2545: line_drawn = 0;
2546:
2547: gen_pfield_tables();
2548:
2549: #ifdef SUPPORT_PENGUINS
2550: init_comm_pipe (&drawing_pipe, 800, 5);
2551: uae_sem_init (&drawing_lock, 0, 0);
2552: start_penguin (drawing_penguin, 0, &our_penguin);
2553: /*atexit(kill_drawing_penguin);*/
2554: #endif
2555: }
2556:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.