|
|
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;
98: static char linestate[(maxvpos + 1)*2 + 1];
99:
100: uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
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. */
116: static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires;
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:
130: static __inline__ void count_frame (void)
131: {
132: framecnt++;
133: if (framecnt >= currprefs.framerate)
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:
462: static __inline__ void fill_line_full (void)
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
486: static __inline__ void fill_line (void)
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 ddf_left, ddf_right;
697: int mindelay = bpldelay1, maxdelay = bpldelay2;
698: if (bpldelay1 > bpldelay2)
699: maxdelay = bpldelay1, mindelay = bpldelay2;
700:
701: linetoscr_diw_start = dp_for_drawing->diwfirstword;
702: linetoscr_diw_end = dp_for_drawing->diwlastword;
703:
704: /* We should really look at DDF also when calculating max_diwstop/min_diwstrt,
705: * so that centering works better, but I'm afraid that might cost too many
706: * cycles. Plus it's dangerous, see the code below that handles the case
707: * with sprites. */
708: if (dip_for_drawing->nr_sprites == 0) {
709: int hiresadjust = bplhires ? 4 : 8;
1.1.1.4 ! root 710: ddf_left = (((dp_for_drawing->plfstrt + hiresadjust)*2
! 711: + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift);
! 712: ddf_right = (((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2
! 713: + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift);
1.1 root 714:
715: if (linetoscr_diw_start < ddf_left)
716: linetoscr_diw_start = ddf_left;
717: if (linetoscr_diw_end > ddf_right)
718: linetoscr_diw_end = ddf_right;
719:
720: if (mindelay != maxdelay) {
721: /* Raahh...
722: * We just clear the maximum amount of space that may need to be
723: * cleared. We could do this exactly, but it would come out slower
724: * because of the overhead. */
725: if (currprefs.gfx_lores == 2) {
726: fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15);
727: fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15);
728: } else if (currprefs.gfx_lores) {
729: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15);
730: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15);
731: } else {
732: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30);
733: fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30);
734: }
735: }
736: } else {
737: int hiresadjust = bplhires ? 4 : 8;
738: /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check.
739: * Since we have to do a memset anyway (because there may be sprites),
740: * we might as well clear all at once. */
741: ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift;
742: ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift;
743: if (linetoscr_diw_start < ddf_left) {
744: int strt = linetoscr_diw_start;
745: int stop = ddf_left;
746: #ifdef LORES_HACK
747: if (currprefs.gfx_lores == 2)
748: strt >>= 1, stop >>= 1;
749: #endif
750: if (strt < stop)
751: fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
752: }
753:
754: if (linetoscr_diw_end > ddf_right) {
755: int strt = ddf_right;
756: int stop = linetoscr_diw_end;
757: #ifdef LORES_HACK
758: if (currprefs.gfx_lores == 2)
759: strt >>= 1, stop >>= 1;
760: #endif
761: if (strt < stop)
762: fuzzy_memset (pixdata.apixels, 0, strt, stop - strt);
763: }
764: }
765: /* Perverse cases happen. */
766: if (linetoscr_diw_end < linetoscr_diw_start)
767: linetoscr_diw_end = linetoscr_diw_start;
768: }
769:
770: static void pfield_do_linetoscr(int start, int stop)
771: {
772: int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
773:
774: if (stop > linetoscr_right_x)
775: stop = linetoscr_right_x;
776: if (start < linetoscr_x_adjust)
777: start = linetoscr_x_adjust;
778:
779: if (lframe_end < start)
780: lframe_end = start;
781: if (diw_end > stop)
782: diw_end = stop;
783:
784: if (start >= stop)
785: return;
786:
787: #if AGA_CHIPSET == 0
788: if (start == linetoscr_x_adjust && stop == linetoscr_right_x) {
789: switch (gfxvidinfo.pixbytes) {
790: case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
791: case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
792: case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
793: case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
794: }
795: } else {
796: switch (gfxvidinfo.pixbytes) {
797: case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break;
798: case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break;
799: case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break;
800: case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break;
801: }
802: }
803: #else
1.1.1.2 root 804: pfield_linetoscr_aga (start, lframe_end, diw_end, stop);
1.1 root 805: #endif
806: }
807:
1.1.1.2 root 808: static void pfield_do_fill_line (int start, int stop)
1.1 root 809: {
810: if (stop > linetoscr_right_x)
811: stop = linetoscr_right_x;
812: if (start < linetoscr_x_adjust)
813: start = linetoscr_x_adjust;
814:
815: if (start >= stop)
816: return;
817:
1.1.1.2 root 818: #if AGA_CHIPSET == 0
1.1 root 819: switch (gfxvidinfo.pixbytes) {
820: case 1: fill_line_8 (xlinebuffer, start, stop); break;
821: case 2: fill_line_16 (xlinebuffer, start, stop); break;
822: case 3: fill_line_24 (xlinebuffer, start, stop); break;
823: case 4: fill_line_32 (xlinebuffer, start, stop); break;
824: }
1.1.1.2 root 825: #else
826: aga_fill_line_32 (xlinebuffer, start, stop);
827: /* FIXME */
828: #endif
1.1 root 829: }
830:
1.1.1.2 root 831: static void pfield_do_linetoscr_full (int double_line)
1.1 root 832: {
833: int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width;
834: int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end;
835: if (lframe_end < start)
836: lframe_end = start;
837: if (diw_end > stop)
838: diw_end = stop;
839:
840: #if AGA_CHIPSET == 0
841: if (double_line) {
842: switch (gfxvidinfo.pixbytes) {
843: case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break;
844: case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break;
845: case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break;
846: case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break;
847: }
848: } else
849: switch (gfxvidinfo.pixbytes) {
850: case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break;
851: case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break;
852: case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break;
853: case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break;
854: }
855: #else
1.1.1.2 root 856: pfield_linetoscr_aga (start, lframe_end, diw_end, stop);
1.1 root 857: #endif
858: }
859:
1.1.1.2 root 860: static void gen_pfield_tables (void)
1.1 root 861: {
862: int i;
863: union {
864: struct {
865: uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p;
866: } foo;
867: struct {
868: uae_u32 a, b, c, d;
869: } bar;
870: } baz;
871:
872: /* For now, the AGA stuff is broken in the dual playfield case. We encode
873: * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
874: * playfield rendering easy, the lookup tables contain are made linear for
875: * values >= 128. That only works for OCS/ECS, though. */
876:
877: for (i = 0; i < 256; i++) {
878: int plane1 = (i & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
879: int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
880: dblpf_2nd1[i] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
881: dblpf_2nd2[i] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
882: if (plane2 > 0)
883: plane2 += 8;
884: dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
885: dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
886:
887: lots_of_twos[i] = i == 0 ? 0 : 2;
888: linear_map_256[i] = i;
889: }
890:
891: for (i = 0; i < 256; i++) {
892: /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */
893: baz.foo.a = i & 64 ? 1 : 0;
894: baz.foo.b = i & 16 ? 1 : 0;
895: baz.foo.c = i & 4 ? 1 : 0;
896: baz.foo.d = i & 1 ? 1 : 0;
897: hirestab_l[i][0] = baz.bar.a;
898:
899: baz.foo.a = i & 128 ? 1 : 0;
900: baz.foo.b = i & 64 ? 1 : 0;
901: baz.foo.c = i & 32 ? 1 : 0;
902: baz.foo.d = i & 16 ? 1 : 0;
903: baz.foo.e = i & 8 ? 1 : 0;
904: baz.foo.f = i & 4 ? 1 : 0;
905: baz.foo.g = i & 2 ? 1 : 0;
906: baz.foo.h = i & 1 ? 1 : 0;
907: lorestab_l[i][0] = baz.bar.a;
908: lorestab_l[i][1] = baz.bar.b;
909: clxtab[i] = ((((i & 3) && (i & 12)) << 9)
910: | (((i & 3) && (i & 48)) << 10)
911: | (((i & 3) && (i & 192)) << 11)
912: | (((i & 12) && (i & 48)) << 12)
913: | (((i & 12) && (i & 192)) << 13)
914: | (((i & 48) && (i & 192)) << 14));
915: }
916:
917: for (i = 0; i < 256; i++) {
918: baz.foo.a = i & 128 ? 1 : 0;
919: baz.foo.b = i & 64 ? 1 : 0;
920: baz.foo.c = i & 32 ? 1 : 0;
921: baz.foo.d = i & 16 ? 1 : 0;
922: baz.foo.e = i & 8 ? 1 : 0;
923: baz.foo.f = i & 4 ? 1 : 0;
924: baz.foo.g = i & 2 ? 1 : 0;
925: baz.foo.h = i & 1 ? 1 : 0;
926: hirestab_h[i][0] = baz.bar.a;
927: hirestab_h[i][1] = baz.bar.b;
928:
929: baz.foo.a = i & 128 ? 1 : 0;
930: baz.foo.b = i & 128 ? 1 : 0;
931: baz.foo.c = i & 64 ? 1 : 0;
932: baz.foo.d = i & 64 ? 1 : 0;
933: baz.foo.e = i & 32 ? 1 : 0;
934: baz.foo.f = i & 32 ? 1 : 0;
935: baz.foo.g = i & 16 ? 1 : 0;
936: baz.foo.h = i & 16 ? 1 : 0;
937: baz.foo.i = i & 8 ? 1 : 0;
938: baz.foo.j = i & 8 ? 1 : 0;
939: baz.foo.k = i & 4 ? 1 : 0;
940: baz.foo.l = i & 4 ? 1 : 0;
941: baz.foo.m = i & 2 ? 1 : 0;
942: baz.foo.n = i & 2 ? 1 : 0;
943: baz.foo.o = i & 1 ? 1 : 0;
944: baz.foo.p = i & 1 ? 1 : 0;
945: lorestab_h[i][0] = baz.bar.a;
946: lorestab_h[i][1] = baz.bar.b;
947: lorestab_h[i][2] = baz.bar.c;
948: lorestab_h[i][3] = baz.bar.d;
949: }
950: }
951:
952: static uae_u32 attach_2nd;
953:
954: static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr)
955: {
956: int j;
957: int sprxp = spd[i].linepos;
958: uae_u32 datab = spd[i].datab;
959: uae_u32 mask2 = 0;
960: int sbit = 1 << spd[i].num;
961: int sprx_shift = 1;
962: int attach_compare = -1;
963: if (currprefs.gfx_lores != 1)
964: sprx_shift = 0;
965:
966: attach_2nd = 0;
967: if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80)
968: attach_compare = spd[i].num - 1;
969:
970: for (j = prev_overlap; j < i; j++) {
971: uae_u32 mask1;
972: int off;
973:
974: if (spd[i].num < spd[j].num)
975: continue;
976:
977: off = sprxp - spd[j].linepos;
978: off <<= sprx_shift;
979: mask1 = spd[j].datab >> off;
980:
981: /* If j is an attachment for i, then j doesn't block i */
982: if (spd[j].num == attach_compare) {
983: attach_2nd |= mask1;
984: } else {
985: mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
986: mask1 |= (mask1 & 0x55555555) << 1;
987: if (datab & mask1)
988: clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
989: mask2 |= mask1;
990: }
991: }
992: for (j = i+1; j < nr_spr; j++) {
993: uae_u32 mask1;
994: int off = spd[j].linepos - sprxp;
995:
996: if (off >= sprite_width || spd[i].num < spd[j].num)
997: break;
998:
999: off <<= sprx_shift;
1000: mask1 = spd[j].datab << off;
1001:
1002: /* If j is an attachment for i, then j doesn't block i */
1003: if (spd[j].num == attach_compare) {
1004: attach_2nd |= mask1;
1005: } else {
1006: mask1 |= (mask1 & 0xAAAAAAAA) >> 1;
1007: mask1 |= (mask1 & 0x55555555) << 1;
1008: if (datab & mask1)
1009: clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask];
1010: mask2 |= mask1;
1011: }
1012: }
1013: datab &= ~mask2;
1014: return datab;
1015: }
1016:
1017: static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc)
1018: {
1019: uae_u32 datcd;
1020: int basecol = 16;
1021: if (!attch)
1022: basecol += (spr & ~1)*2;
1023: if (bpldualpf)
1024: basecol |= 128;
1025: if (attch)
1026: datcd = attach_2nd;
1027:
1028: for(; attch ? datab | datcd : datab; sprxp += sprx_inc) {
1029: int col;
1030:
1031: if (attch) {
1032: col = ((datab & 3) << 2) | (datcd & 3);
1033: datcd >>= 2;
1034: } else
1035: col = datab & 3;
1036: datab >>= 2;
1037: if (col) {
1038: col |= basecol;
1039: if (ham) {
1040: col = colors_for_drawing.color_regs[col];
1041: ham_linebuf[sprxp] = col;
1042: if (sprx_inc == 2) {
1043: ham_linebuf[sprxp+1] = col;
1044: }
1045: } else {
1046: pixdata.apixels[sprxp] = col;
1047: if (sprx_inc == 2) {
1048: pixdata.apixels[sprxp+1] = col;
1049: }
1050: }
1051: }
1052: }
1053: }
1054:
1055: static void walk_sprites (struct sprite_draw *spd, int nr_spr)
1056: {
1057: int i, prev_overlap;
1058: int last_sprite_pos = -64;
1059: uae_u32 plane1 = 0, plane2 = 0;
1060: int sprx_inc = 1, sprx_shift = 1;
1061:
1062: if (currprefs.gfx_lores == 0)
1063: sprx_inc = 2, sprx_shift = 0;
1064:
1065: prev_overlap = 0;
1066: for (i = 0; i < nr_spr; i++) {
1067: int sprxp = spd[i].linepos;
1068: int m = 1 << spd[i].num;
1069: uae_u32 datab;
1070: while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp)
1071: prev_overlap++;
1072:
1073: datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr);
1074: #ifdef LORES_HACK
1075: if (currprefs.gfx_lores == 2)
1076: sprxp >>= 1;
1077: #endif
1078: if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) {
1079: if (sprxp != last_sprite_pos) {
1080: int ok = last_sprite_pos-sprxp+16;
1081: int ok2;
1082: if (ok <= 0) {
1083: ok = ok2 = 0;
1084: plane1 = 0;
1085: plane2 = 0;
1086: } else {
1087: ok2 = ok << sprx_shift;
1088: plane1 >>= 32 - ok2;
1089: plane2 >>= 32 - ok2;
1090: }
1091: last_sprite_pos = sprxp;
1092:
1093: if (bpldualpf) {
1094: uae_u32 mask = 3 << ok2;
1095: int p = sprxp+ok;
1096:
1097: for (; mask; mask <<= 2, p += sprx_inc) {
1098: int data = pixdata.apixels[p];
1099: if (dblpf_2nd2[data] == 2)
1100: plane2 |= mask;
1101: if (dblpf_2nd1[data] == 1)
1102: plane1 |= mask;
1103: }
1104: } else {
1105: uae_u32 mask = 3 << ok2;
1106: int p = sprxp+ok;
1107:
1108: for (; mask; mask <<= 2, p += sprx_inc) {
1109: if (pixdata.apixels[p])
1110: plane2 |= mask;
1111: }
1112: }
1113: }
1114: if (bpldualpf && m >= plfpri[1]) {
1115: datab &= ~plane1;
1116: attach_2nd &= ~plane1;
1117: }
1118: if (m >= plfpri[2]) {
1119: datab &= ~plane2;
1120: attach_2nd &= ~plane2;
1121: }
1122: }
1123: if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) {
1124: /* Attached sprite */
1125: if (bplham) {
1126: if (sprx_inc == 1) {
1127: render_sprite (spd[i].num, sprxp, datab, 1, 1, 1);
1128: } else {
1129: render_sprite (spd[i].num, sprxp, datab, 1, 1, 2);
1130: }
1131: } else {
1132: if (sprx_inc == 1) {
1133: render_sprite (spd[i].num, sprxp, datab, 0, 1, 1);
1134: } else {
1135: render_sprite (spd[i].num, sprxp, datab, 0, 1, 2);
1136: }
1137: }
1138: /* This still leaves one attached sprite bug, but at the moment I'm too lazy */
1139: if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos)
1140: i++;
1141: } else {
1142: if (bplham) {
1143: if (sprx_inc == 1) {
1144: render_sprite (spd[i].num, sprxp, datab, 1, 0, 1);
1145: } else {
1146: render_sprite (spd[i].num, sprxp, datab, 1, 0, 2);
1147: }
1148: } else {
1149: if (sprx_inc == 1) {
1150: render_sprite (spd[i].num, sprxp, datab, 0, 0, 1);
1151: } else {
1152: render_sprite (spd[i].num, sprxp, datab, 0, 0, 2);
1153: }
1154: }
1155: }
1156: }
1157: }
1158:
1159: #ifndef SMART_UPDATE
1160: #undef UNALIGNED_PROFITABLE
1161: #endif
1162:
1163: #ifdef UNALIGNED_PROFITABLE
1164:
1165: static void pfield_doline_unaligned_h (int lineno)
1166: {
1167: int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
1168:
1169: if (bplhires) {
1170: int xpos1 = xpos + 16 + bpldelay1*2;
1171: int xpos2;
1172: uae_u8 *dataptr = line_data[lineno];
1173: int len = dp_for_drawing->plflinelen >> 1;
1174:
1175: if (len <= 0)
1176: return;
1177:
1178: if (bpldelay1 == bpldelay2) {
1179: switch (bplplanecnt) {
1180: case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1181: case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1182: case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1183: case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1184: case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1185: case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1186: case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1187: case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1188: }
1189: } else {
1190: switch (bplplanecnt) {
1191: case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1192: case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1193: case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1194: case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1195: }
1196:
1197: xpos2 = xpos + 16 + bpldelay2*2;
1198: switch (bplplanecnt) {
1199: case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1200: case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1201: case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1202: case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1203: }
1204: }
1205: } else {
1206: int xpos1 = xpos + 32 + bpldelay1*2;
1207: int xpos2;
1208: uae_u8 *dataptr = line_data[lineno];
1209: int len = dp_for_drawing->plflinelen >> 2;
1210:
1211: if (len <= 0)
1212: return;
1213:
1214: if (bpldelay1 == bpldelay2) {
1215: switch (bplplanecnt) {
1216: case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1217: case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1218: case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1219: case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1220: case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1221: case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1222: case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1223: case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1224: }
1225: } else {
1226: switch (bplplanecnt) {
1227: case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1228: case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1229: case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1230: case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1231: }
1232:
1233: xpos2 = xpos + 32 + bpldelay2*2;
1234: switch (bplplanecnt) {
1235: case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1236: case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1237: case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1238: case 8: set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1239: }
1240: }
1241: }
1242: }
1243:
1244: static void pfield_doline_unaligned_l (int lineno)
1245: {
1246: int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
1247:
1248: if (bplhires) {
1249: int xpos1 = xpos + 8 + bpldelay1;
1250: int xpos2;
1251: uae_u8 *dataptr = line_data[lineno];
1252: int len = dp_for_drawing->plflinelen >> 1;
1253:
1254: if (len <= 0)
1255: return;
1256:
1257: if (bpldelay1 == bpldelay2) {
1258: switch (bplplanecnt) {
1259: case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1260: case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1261: case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1262: case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1263: case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1264: case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1265: case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1266: case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1267: }
1268: } else {
1269: switch (bplplanecnt) {
1270: case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1271: case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1272: case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1273: case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1274: }
1275:
1276: xpos2 = xpos + 8 + bpldelay2;
1277: switch (bplplanecnt) {
1278: case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1279: case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1280: case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1281: case 8: set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1282: }
1283: }
1284: } else {
1285: int xpos1 = xpos + 16 + bpldelay1;
1286: int xpos2;
1287: uae_u8 *dataptr = line_data[lineno];
1288: int len = dp_for_drawing->plflinelen >> 2;
1289:
1290: if (len <= 0)
1291: return;
1292:
1293: if (bpldelay1 == bpldelay2) {
1294: switch (bplplanecnt) {
1295: case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1296: case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1297: case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1298: case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1299: case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1300: case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1301: case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1302: case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1303: }
1304: } else {
1305: switch (bplplanecnt) {
1306: case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1307: case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1308: case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1309: case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break;
1310: }
1311:
1312: xpos2 = xpos + 16 + bpldelay2;
1313: switch (bplplanecnt) {
1314: case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1315: case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1316: case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1317: case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break;
1318: }
1319: }
1320: }
1321: }
1322:
1323: #define pfield_doline_h pfield_doline_unaligned_h
1324: #define pfield_doline_l pfield_doline_unaligned_l
1325:
1326: #else /* not UNALIGNED_PROFITABLE */
1327:
1328:
1329: static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit)
1330: {
1331: uae_u32 *pixptr = (uae_u32 *)dp;
1332:
1333: *pixptr |= hirestab_h[data >> 8][0] << bit;
1334: *(pixptr+1) |= hirestab_h[data >> 8][1] << bit;
1335: *(pixptr+2) |= hirestab_h[data & 255][0] << bit;
1336: *(pixptr+3) |= hirestab_h[data & 255][1] << bit;
1337: }
1338:
1339: static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit)
1340: {
1341: uae_u32 *pixptr = (uae_u32 *)dp;
1342:
1343: *pixptr |= lorestab_h[data >> 8][0] << bit;
1344: *(pixptr+1) |= lorestab_h[data >> 8][1] << bit;
1345: *(pixptr+2) |= lorestab_h[data >> 8][2] << bit;
1346: *(pixptr+3) |= lorestab_h[data >> 8][3] << bit;
1347: *(pixptr+4) |= lorestab_h[data & 255][0] << bit;
1348: *(pixptr+5) |= lorestab_h[data & 255][1] << bit;
1349: *(pixptr+6) |= lorestab_h[data & 255][2] << bit;
1350: *(pixptr+7) |= lorestab_h[data & 255][3] << bit;
1351: }
1352:
1353: static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit)
1354: {
1355: uae_u32 *pixptr = (uae_u32 *)dp;
1356:
1357: *pixptr = hirestab_h[data >> 8][0] << bit;
1358: *(pixptr+1) = hirestab_h[data >> 8][1] << bit;
1359: *(pixptr+2) = hirestab_h[data & 255][0] << bit;
1360: *(pixptr+3) = hirestab_h[data & 255][1] << bit;
1361: }
1362:
1363: static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit)
1364: {
1365: uae_u32 *pixptr = (uae_u32 *)dp;
1366:
1367: *pixptr = lorestab_h[data >> 8][0] << bit;
1368: *(pixptr+1) = lorestab_h[data >> 8][1] << bit;
1369: *(pixptr+2) = lorestab_h[data >> 8][2] << bit;
1370: *(pixptr+3) = lorestab_h[data >> 8][3] << bit;
1371: *(pixptr+4) = lorestab_h[data & 255][0] << bit;
1372: *(pixptr+5) = lorestab_h[data & 255][1] << bit;
1373: *(pixptr+6) = lorestab_h[data & 255][2] << bit;
1374: *(pixptr+7) = lorestab_h[data & 255][3] << bit;
1375: }
1376:
1377: static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit)
1378: {
1379: uae_u32 *pixptr = (uae_u32 *)dp;
1380:
1381: *pixptr |= hirestab_l[data >> 8][0] << bit;
1382: *(pixptr+1) |= hirestab_l[data & 255][0] << bit;
1383: }
1384:
1385: static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit)
1386: {
1387: uae_u32 *pixptr = (uae_u32 *)dp;
1388:
1389: *pixptr |= lorestab_l[data >> 8][0] << bit;
1390: *(pixptr+1) |= lorestab_l[data >> 8][1] << bit;
1391: *(pixptr+2) |= lorestab_l[data & 255][0] << bit;
1392: *(pixptr+3) |= lorestab_l[data & 255][1] << bit;
1393: }
1394:
1395: static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit)
1396: {
1397: uae_u32 *pixptr = (uae_u32 *)dp;
1398:
1399: *pixptr = hirestab_l[data >> 8][0] << bit;
1400: *(pixptr+1) = hirestab_l[data & 255][0] << bit;
1401: }
1402:
1403: static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit)
1404: {
1405: uae_u32 *pixptr = (uae_u32 *)dp;
1406:
1407: *pixptr = lorestab_l[data >> 8][0] << bit;
1408: *(pixptr+1) = lorestab_l[data >> 8][1] << bit;
1409: *(pixptr+2) = lorestab_l[data & 255][0] << bit;
1410: *(pixptr+3) = lorestab_l[data & 255][1] << bit;
1411: }
1412:
1413: #define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \
1414: int i; \
1415: unsigned int bpldat1; \
1416: uae_u16 data; \
1417: unsigned int bpldat2 = 0; \
1418: uae_u8 *ptr = (POINTER); \
1419: for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \
1420: bpldat1 = bpldat2; \
1421: bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \
1422: ptr+=2; \
1423: data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \
1424: FUNC(data, app, MULT); \
1425: app += P_ADD; \
1426: } \
1427: data = bpldat2 << (16 - DELAY); \
1428: FUNC(data, app, MULT); \
1429: }
1430:
1431: #ifdef SMART_UPDATE
1432: #define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2)
1433: #else
1434: #define DATA_POINTER(n) (real_bplpt[n])
1435: #endif
1436:
1437: static void pfield_doline_aligned_h (int lineno)
1438: {
1439: int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2;
1440:
1441: if (bplhires) {
1442: if (bplplanecnt > 0) {
1443: int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0);
1444: int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0);
1445: int delay1 = 2*(bpldelay1 & 7);
1446: int delay2 = 2*(bpldelay2 & 7);
1447: unsigned char *app = pixdata.apixels + xpos1;
1448: uae_u8 *dataptr = line_data[lineno];
1449:
1450: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16);
1451: if (bplplanecnt > 2) {
1452: app = pixdata.apixels + xpos1;
1453: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16);
1454: }
1455: #if AGA_CHIPSET == 1
1456: if (bplplanecnt > 4) {
1457: app = pixdata.apixels + xpos1;
1458: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16);
1459: }
1460: if (bplplanecnt > 6) {
1461: app = pixdata.apixels + xpos1;
1462: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16);
1463: }
1464: #endif
1465: if (bplplanecnt > 1) {
1466: app = pixdata.apixels + xpos2;
1467: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16);
1468: }
1469: if (bplplanecnt > 3) {
1470: app = pixdata.apixels + xpos2;
1471: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16);
1472: }
1473: #if AGA_CHIPSET == 1
1474: if (bplplanecnt > 5) {
1475: app = pixdata.apixels + xpos2;
1476: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16);
1477: }
1478: if (bplplanecnt > 7) {
1479: app = pixdata.apixels + xpos2;
1480: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16);
1481: }
1482: #endif
1483: } else {
1484: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
1485: }
1486: } else {
1487: if (bplplanecnt > 0) {
1488: int x = xpos + 32;
1489: unsigned char *app = pixdata.apixels + x;
1490: uae_u8 *dataptr = line_data[lineno];
1491:
1492: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32);
1493: if (bplplanecnt > 2) {
1494: app = pixdata.apixels + x;
1495: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32);
1496: }
1497: if (bplplanecnt > 4) {
1498: app = pixdata.apixels + x;
1499: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32);
1500: }
1501: #if AGA_CHIPSET == 1
1502: if (bplplanecnt > 6) {
1503: app = pixdata.apixels + x;
1504: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32);
1505: }
1506: #endif
1507: if (bplplanecnt > 1) {
1508: app = pixdata.apixels + x;
1509: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32);
1510: }
1511: if (bplplanecnt > 3) {
1512: app = pixdata.apixels + x;
1513: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32);
1514: }
1515: if (bplplanecnt > 5) {
1516: app = pixdata.apixels + x;
1517: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32);
1518: }
1519: #if AGA_CHIPSET == 1
1520: if (bplplanecnt > 7) {
1521: app = pixdata.apixels + x;
1522: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32);
1523: }
1524: #endif
1525: } else {
1526: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
1527: }
1528: }
1529: }
1530:
1531: static void pfield_doline_aligned_l (int lineno)
1532: {
1533: int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT;
1534:
1535: if (bplhires) {
1536: if (bplplanecnt > 0) {
1537: int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0);
1538: int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0);
1539: int delay1 = (bpldelay1 & 7) * 2;
1540: int delay2 = (bpldelay2 & 7) * 2;
1541: unsigned char *app = pixdata.apixels + xpos1;
1542: uae_u8 *dataptr = line_data[lineno];
1543:
1544: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8);
1545: if (bplplanecnt > 2) {
1546: app = pixdata.apixels + xpos1;
1547: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8);
1548: }
1549: #if AGA_CHIPSET == 1
1550: if (bplplanecnt > 4) {
1551: app = pixdata.apixels + xpos1;
1552: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8);
1553: }
1554: if (bplplanecnt > 6) {
1555: app = pixdata.apixels + xpos1;
1556: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8);
1557: }
1558: #endif
1559: if (bplplanecnt > 1) {
1560: app = pixdata.apixels + xpos2;
1561: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8);
1562: }
1563: if (bplplanecnt > 3) {
1564: app = pixdata.apixels + xpos2;
1565: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8);
1566: }
1567: #if AGA_CHIPSET == 1
1568: if (bplplanecnt > 5) {
1569: app = pixdata.apixels + xpos2;
1570: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8);
1571: }
1572: if (bplplanecnt > 7) {
1573: app = pixdata.apixels + xpos2;
1574: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8);
1575: }
1576: #endif
1577: } else {
1578: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
1579: }
1580: } else {
1581: if (bplplanecnt > 0) {
1582: int x = xpos + 16;
1583: int delay1 = bpldelay1;
1584: int delay2 = bpldelay2;
1585: unsigned char *app = pixdata.apixels + x;
1586: uae_u8 *dataptr = line_data[lineno];
1587:
1588: DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16);
1589: if (bplplanecnt > 2) {
1590: app = pixdata.apixels + x;
1591: DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16);
1592: }
1593: if (bplplanecnt > 4) {
1594: app = pixdata.apixels + x;
1595: DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16);
1596: }
1597: #if AGA_CHIPSET == 1
1598: if (bplplanecnt > 6) {
1599: app = pixdata.apixels + x;
1600: DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16);
1601: }
1602: #endif
1603: if (bplplanecnt > 1) {
1604: app = pixdata.apixels + x;
1605: DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16);
1606: }
1607: if (bplplanecnt > 3) {
1608: app = pixdata.apixels + x;
1609: DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16);
1610: }
1611: if (bplplanecnt > 5) {
1612: app = pixdata.apixels + x;
1613: DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16);
1614: }
1615: #if AGA_CHIPSET == 1
1616: if (bplplanecnt > 7) {
1617: app = pixdata.apixels + x;
1618: DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16);
1619: }
1620: #endif
1621: } else {
1622: memset(pixdata.apixels, 0, sizeof(pixdata.apixels));
1623: }
1624: }
1625: }
1626:
1627: #define pfield_doline_h pfield_doline_aligned_h
1628: #define pfield_doline_l pfield_doline_aligned_l
1629:
1630: #endif /* UNALIGNED_PROFITABLE */
1631:
1632: static void pfield_adjust_delay (void)
1633: {
1634: int ddf_left = dp_for_drawing->plfstrt;
1635: int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen;
1636: int i;
1637:
1638: for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) {
1639: int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value;
1640: int delay1 = delayreg & 0xF;
1641: int delay2 = (delayreg >> 4) & 0xF;
1642: int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos;
1643: int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos;
1644: int j;
1645: startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8));
1646: stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8));
1647: if (currprefs.gfx_lores == 0)
1648: delay1 <<= 1, delay2 <<= 1;
1649: else if (currprefs.gfx_lores == 2)
1650: startpos >>= 1, stoppos >>= 1;
1651: for (j = startpos-1; j >= stoppos; j--) {
1652: pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA);
1653: }
1654: }
1655: }
1656:
1657: void init_row_map (void)
1658: {
1659: int i;
1660: if (gfxvidinfo.height > 2048) {
1661: write_log ("Resolution too high, aborting\n");
1662: abort ();
1663: }
1664: for (i = 0; i < gfxvidinfo.height + 1; i++)
1665: row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
1666: }
1667:
1668: static void init_aspect_maps (void)
1669: {
1670: int i, maxl;
1671: double native_lines_per_amiga_line;
1672:
1673: if (native2amiga_line_map)
1674: free (native2amiga_line_map);
1675: if (amiga2aspect_line_map)
1676: free (amiga2aspect_line_map);
1677:
1678: /* At least for this array the +1 is necessary. */
1679: amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1);
1680: native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
1681:
1682: if (currprefs.gfx_correct_aspect)
1683: native_lines_per_amiga_line = ((double)gfxvidinfo.height
1684: * (currprefs.gfx_lores ? 320 : 640)
1685: / (currprefs.gfx_linedbl ? 512 : 256)
1686: / gfxvidinfo.width);
1687: else
1688: native_lines_per_amiga_line = 1;
1689:
1690: maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1);
1691: min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
1692: max_drawn_amiga_line = -1;
1693: for (i = 0; i < maxl; i++) {
1694: int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line;
1695: if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
1696: max_drawn_amiga_line = i - min_ypos_for_screen;
1697: if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
1698: v = -1;
1699: amiga2aspect_line_map[i] = v;
1700: }
1701: if (currprefs.gfx_linedbl)
1702: max_drawn_amiga_line >>= 1;
1703:
1704: if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
1705: extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
1706: if (extra_y_adjust < 0)
1707: extra_y_adjust = 0;
1708: }
1709:
1710: for (i = 0; i < gfxvidinfo.height; i++)
1711: native2amiga_line_map[i] = -1;
1712:
1713: if (native_lines_per_amiga_line < 1) {
1714: /* Must omit drawing some lines. */
1715: for (i = maxl - 1; i > min_ypos_for_screen; i--) {
1716: if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
1717: if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
1718: /* If only the first line of a line pair would be omitted,
1719: * omit the second one instead to avoid problems with line
1720: * doubling. */
1721: amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
1722: amiga2aspect_line_map[i+1] = -1;
1723: } else
1724: amiga2aspect_line_map[i] = -1;
1725: }
1726: }
1727: }
1728:
1729: for (i = maxl-1; i >= min_ypos_for_screen; i--) {
1730: int j;
1731: if (amiga2aspect_line_map[i] == -1)
1732: continue;
1733: for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
1734: native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
1735: }
1736: }
1737:
1738: /*
1739: * A raster line has been built in the graphics buffer. Tell the graphics code
1740: * to do anything necessary to display it.
1741: */
1742: static void do_flush_line_1 (int lineno)
1743: {
1744: if (lineno < first_drawn_line)
1745: first_drawn_line = lineno;
1746: if (lineno > last_drawn_line)
1747: last_drawn_line = lineno;
1748:
1749: if (gfxvidinfo.maxblocklines == 0)
1750: flush_line(lineno);
1751: else {
1752: if ((last_block_line+1) != lineno) {
1753: if (first_block_line != -2)
1754: flush_block (first_block_line, last_block_line);
1755: first_block_line = lineno;
1756: }
1757: last_block_line = lineno;
1758: if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
1759: flush_block (first_block_line, last_block_line);
1760: first_block_line = last_block_line = -2;
1761: }
1762: }
1763: }
1764:
1765: static __inline__ void do_flush_line (int lineno)
1766: {
1767: /* We don't want to call X libraries from the second thread right now. */
1768: #ifndef SUPPORT_PENGUINS
1769: do_flush_line_1 (lineno);
1770: #else
1771: line_drawn[lineno] = 1;
1772: #endif
1773: }
1774:
1775: /*
1776: * One drawing frame has been finished. Tell the graphics code about it.
1777: * Note that the actual flush_screen() call is a no-op for all reasonable
1778: * systems.
1779: */
1780:
1781: static __inline__ void do_flush_screen (int start, int stop)
1782: {
1783: #ifdef SUPPORT_PENGUINS
1784: int i;
1785: for (i = 0; i < gfxvidinfo.height; i++) {
1786: if (line_drawn[i])
1787: do_flush_line_1 (i);
1788: }
1789: #endif
1790: if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
1791: flush_block (first_block_line, last_block_line);
1792: }
1793: if (start <= stop)
1794: flush_screen (start, stop);
1795: }
1796:
1.1.1.2 root 1797: static __inline__ void finish_line_aga (void)
1798: {
1799: #if AGA_CHIPSET != 0
1800: aga_lbufptr = aga_linebuf;
1801: aga_translate32 (linetoscr_x_adjust_bytes, linetoscr_x_adjust_bytes + gfxvidinfo.width);
1802: #endif
1803: }
1804:
1.1 root 1805: static int drawing_color_matches;
1806: static enum { color_match_acolors, color_match_full } color_match_type;
1807:
1808: static void adjust_drawing_colors (int ctable, int bplham)
1809: {
1.1.1.2 root 1810: #if AGA_CHIPSET == 0
1.1 root 1811: if (drawing_color_matches != ctable) {
1812: if (bplham) {
1813: memcpy (&colors_for_drawing, curr_color_tables + ctable,
1814: sizeof colors_for_drawing);
1815: color_match_type = color_match_full;
1816: } else {
1817: memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
1818: sizeof colors_for_drawing.acolors);
1819: color_match_type = color_match_acolors;
1820: }
1821: drawing_color_matches = ctable;
1822: } else if (bplham && color_match_type != color_match_full) {
1823: memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs,
1824: sizeof colors_for_drawing.color_regs);
1825: color_match_type = color_match_full;
1826: }
1.1.1.2 root 1827: #else
1828: if (drawing_color_matches != ctable) {
1829: memcpy (&colors_for_drawing, curr_color_tables + ctable,
1830: sizeof colors_for_drawing);
1831: drawing_color_matches = ctable;
1832: }
1833: #endif
1.1 root 1834: }
1835:
1836: static __inline__ void adjust_color0_for_color_change (void)
1837: {
1838: drawing_color_matches = -1;
1839: if (dp_for_drawing->color0 != 0xFFFFFFFFul) {
1840: colors_for_drawing.color_regs[0] = dp_for_drawing->color0;
1.1.1.2 root 1841: #if AGA_CHIPSET == 0
1.1 root 1842: colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0];
1.1.1.2 root 1843: #endif
1.1 root 1844: }
1845: }
1846:
1847: /* Fetched data spends 9 lores pixels somewhere in the chips before it appears
1848: * on-screen. We don't emulate this. Instead, we cheat with the copper to
1849: * compensate (much easier that way). */
1850: #define COPPER_MAGIC_FUDGE -9
1851:
1852: static __inline__ void do_color_changes (line_draw_func worker)
1853: {
1854: int lastpos = 0, nextpos, i;
1855: struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change;
1856:
1857: for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) {
1858: if (i == dip_for_drawing->last_color_change)
1859: nextpos = max_diwlastword;
1860: else
1861: nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift);
1862: worker (lastpos, nextpos);
1863: if (i != dip_for_drawing->last_color_change) {
1864: colors_for_drawing.color_regs[cc->regno] = cc->value;
1.1.1.2 root 1865: #if AGA_CHIPSET == 0
1.1 root 1866: colors_for_drawing.acolors[cc->regno] = xcolors[cc->value];
1.1.1.2 root 1867: #endif
1.1 root 1868: }
1869: if (nextpos > lastpos) {
1870: lastpos = nextpos;
1871: if (lastpos >= linetoscr_right_x)
1872: break;
1873: }
1874: }
1875: }
1876:
1877: /* We only save hardware registers during the hardware frame. Now, when
1878: * drawing the frame, we expand the data into a slightly more useful
1879: * form. */
1880: static void pfield_expand_dp_bplcon (void)
1881: {
1882: bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000;
1.1.1.3 root 1883: bplplanecnt = GET_PLANES (dp_for_drawing->bplcon0);
1.1 root 1884: bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
1885: #if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
1886: * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
1887: bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
1888: #else
1889: bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
1890: #endif
1891: bpldelay1 = dp_for_drawing->bplcon1 & 0xF;
1892: bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF;
1893: plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7);
1894: plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7);
1895: bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
1896: bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
1897: }
1898:
1899: enum double_how {
1900: dh_buf,
1901: dh_line,
1902: dh_emerg
1903: };
1904:
1905: static __inline__ void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos)
1906: {
1907: int border = 0;
1908: int do_double = 0;
1909: enum double_how dh;
1910:
1.1.1.2 root 1911: dp_for_drawing = line_decisions + lineno;
1912: dip_for_drawing = curr_drawinfo + lineno;
1.1 root 1913: switch (linestate[lineno]) {
1914: case LINE_REMEMBERED_AS_PREVIOUS:
1915: {
1916: static int warned = 0;
1917: if (!warned)
1918: write_log ("Shouldn't get here... this is a bug.\n"), warned++;
1919: }
1920: line_decisions[lineno].which = -2;
1921: return;
1922:
1.1.1.2 root 1923: case LINE_BLACK:
1924: line_decisions[lineno].which = -2;
1925: linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
1926: border = 2;
1.1 root 1927: break;
1928:
1.1.1.2 root 1929: case LINE_REMEMBERED_AS_BLACK:
1930: return;
1931:
1932: case LINE_AS_PREVIOUS:
1933: dp_for_drawing--;
1934: dip_for_drawing--;
1935: if (dp_for_drawing->which != 1)
1936: border = 1;
1937: line_decisions[lineno].which = -2;
1938: linestate[lineno] = LINE_DONE_AS_PREVIOUS;
1.1 root 1939: break;
1940:
1941: case LINE_DONE_AS_PREVIOUS:
1942: line_decisions[lineno].which = -2;
1943: /* fall through */
1944: case LINE_DONE:
1945: return;
1946:
1947: case LINE_DECIDED_DOUBLE:
1948: line_decisions[lineno+1].which = -2;
1949: if (follow_ypos != -1) {
1950: do_double = 1;
1951: linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
1.1.1.2 root 1952: linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
1.1 root 1953: }
1954:
1955: /* fall through */
1956: default:
1957: if (dp_for_drawing->which != 1)
1958: border = 1;
1959: linestate[lineno] = LINE_DONE;
1.1.1.2 root 1960: break;
1.1 root 1961: }
1962:
1963: dh = dh_line;
1964: xlinebuffer = gfxvidinfo.linemem;
1.1.1.2 root 1965: if (xlinebuffer == 0 && do_double && border != 2 && dip_for_drawing->nr_color_changes != 0)
1.1 root 1966: xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg;
1967: if (xlinebuffer == 0)
1968: xlinebuffer = row_map[gfx_ypos], dh = dh_buf;
1969: xlinebuffer -= linetoscr_x_adjust_bytes;
1970: aga_lbufptr = aga_linebuf;
1971:
1.1.1.2 root 1972: if (border == 0) {
1.1 root 1973: pfield_expand_dp_bplcon ();
1974:
1975: #ifdef LORES_HACK
1976: if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores
1977: && dip_for_drawing->nr_color_changes == 0 && !bplham)
1978: currprefs.gfx_lores = 2;
1979: #endif
1980: pfield_init_linetoscr ();
1981: if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) {
1982: bpldelay1 = bpldelay2 = 0;
1983: if (currprefs.gfx_lores)
1984: pfield_doline_l (lineno);
1985: else
1986: pfield_doline_h (lineno);
1987: pfield_adjust_delay ();
1988: } else {
1989: if (currprefs.gfx_lores)
1990: pfield_doline_l (lineno);
1991: else
1992: pfield_doline_h (lineno);
1993: }
1994:
1995: /* Check color0 adjust only if we have color changes - shouldn't happen
1996: * otherwise. */
1997: adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
1998:
1999: /* The problem is that we must call decode_ham6() BEFORE we do the
2000: * sprites. */
2001: if (bplham) {
2002: init_ham_decoding(linetoscr_x_adjust);
2003: if (dip_for_drawing->nr_color_changes == 0) {
2004: /* The easy case: need to do HAM decoding only once for the
2005: * full line. */
2006: decode_ham6 (linetoscr_x_adjust, linetoscr_right_x);
2007: } else /* Argh. */ {
2008: adjust_color0_for_color_change ();
2009: do_color_changes (decode_ham6);
2010: adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
2011: }
2012: }
2013:
2014: if (dip_for_drawing->nr_sprites != 0)
2015: walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites);
2016:
2017: if (dip_for_drawing->nr_color_changes == 0) {
2018: pfield_do_linetoscr_full (dh == dh_buf ? do_double : 0);
1.1.1.2 root 2019: finish_line_aga ();
1.1 root 2020: do_flush_line (gfx_ypos);
2021: #if 0
2022: if (dh == dh_emerg)
2023: abort ();
2024: #endif
2025: if (do_double) {
2026: /* If dh == dh_line, do_flush_line will re-use the rendered line
2027: * from linemem. If dh == dh_buf, the line will have been doubled
2028: * by pfield_do_linetoscr_full. */
2029: do_flush_line (follow_ypos);
2030: }
2031: } else {
2032: adjust_color0_for_color_change ();
2033: do_color_changes (pfield_do_linetoscr);
1.1.1.2 root 2034: finish_line_aga ();
1.1 root 2035:
2036: if (dh == dh_emerg)
2037: memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
2038:
2039: do_flush_line (gfx_ypos);
2040: if (do_double) {
2041: if (dh == dh_emerg)
2042: memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
2043: else if (dh == dh_buf)
2044: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
2045: line_decisions[lineno + 1].which = -2;
2046: do_flush_line (follow_ypos);
2047: }
2048: }
2049: #ifdef LORES_HACK
2050: if (currprefs.gfx_lores == 2)
2051: currprefs.gfx_lores = 0;
2052: #endif
1.1.1.2 root 2053: } else if (border == 1) {
1.1 root 2054: adjust_drawing_colors (dp_for_drawing->ctable, 0);
2055:
2056: /* Check color0 adjust only if we have color changes - shouldn't happen
2057: * otherwise. */
2058:
2059: if (dip_for_drawing->nr_color_changes == 0) {
2060: fill_line ();
2061: do_flush_line (gfx_ypos);
2062: #if 0
2063: if (dh == dh_emerg)
2064: abort ();
2065: #endif
2066: if (do_double) {
2067: if (dh == dh_buf) {
2068: xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
2069: fill_line ();
2070: }
2071: /* If dh == dh_line, do_flush_line will re-use the rendered line
2072: * from linemem. */
2073: do_flush_line (follow_ypos);
2074: }
2075: return;
2076: }
2077:
2078: adjust_color0_for_color_change ();
2079: do_color_changes (pfield_do_fill_line);
2080:
2081: if (dh == dh_emerg)
2082: memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
2083:
2084: do_flush_line (gfx_ypos);
2085: if (do_double) {
2086: if (dh == dh_emerg)
2087: memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
2088: else if (dh == dh_buf)
2089: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
2090: /* If dh == dh_line, do_flush_line will re-use the rendered line
2091: * from linemem. */
2092: do_flush_line (follow_ypos);
2093: line_decisions[lineno + 1].which = -2;
2094: }
1.1.1.2 root 2095: } else {
2096: #if AGA_CHIPSET == 0
2097: xcolnr tmp = colors_for_drawing.acolors[0];
2098: colors_for_drawing.acolors[0] = xcolors[0];
2099: fill_line ();
2100: do_flush_line (gfx_ypos);
2101: colors_for_drawing.acolors[0] = tmp;
2102: #endif
1.1 root 2103: }
2104: }
2105:
2106: #ifdef SUPPORT_PENGUINS
2107: static smp_comm_pipe drawing_pipe;
2108: static uae_sem_t drawing_lock;
2109:
2110: static void *drawing_penguin (void *cruxmedo)
2111: {
2112: int l;
2113: fprintf (stderr, "Hello, world!\n");
2114:
2115: for (;;) {
2116: /* Start of a frame. */
2117: int k;
2118: new_frame:
2119: k = read_comm_pipe_int_blocking (&drawing_pipe);
2120:
2121: switch (k) {
2122: case -2:
2123: /* Hoopy */
2124: break;
2125:
2126: default:
2127: write_log ("Penguin got out of sync.\n");
2128: /* what can we do? Try to reduce the damage */
2129: for (;;) {
2130: k = read_comm_pipe_int_blocking (&drawing_pipe);
2131: if (k == -3)
2132: break;
2133: if (k == -1) {
2134: uae_sem_post (&drawing_lock);
2135: goto new_frame;
2136: }
2137: }
2138: case -3:
2139: UAE_PENGUIN_EXIT;
2140: /* Can't happen */
2141: return 0;
2142: }
2143:
2144: for (;;) {
2145: int i, where;
2146: int l = read_comm_pipe_int_blocking (&drawing_pipe);
2147: switch (l) {
2148: case -1:
2149: /* End-of-frame synchronization. */
2150: uae_sem_post (&drawing_lock);
2151: goto new_frame;
2152: case -2:
2153: /* customreset called a bit too often. That's harmless. */
2154: continue;
2155: case -3:
2156: write_log ("Penguin got out of sync.\n");
2157: UAE_PENGUIN_EXIT;
2158: return 0;
2159: }
2160:
2161: /* l is the line that has been finished for drawing. */
2162: i = l - thisframe_y_adjust_real;
2163: if (i < 0 || i >= max_ypos_thisframe)
2164: continue;
2165:
2166: if (linestate[l] == LINE_UNDECIDED) {
2167: fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l);
2168: continue;
2169: }
2170: if (inhibit_frame != 0)
2171: continue;
2172: where = amiga2aspect_line_map[i+min_ypos_for_screen];
2173: if (where >= gfxvidinfo.height || where == -1)
2174: continue;
2175:
2176: pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
2177: }
2178: }
2179: }
2180:
2181: static penguin_id our_penguin;
2182:
2183: static void kill_drawing_penguin (void)
2184: {
2185: /* ??? does libpthread do that for us? */
2186: }
2187:
2188: #endif
2189:
2190: static int penguins_enabled_thisframe;
2191:
2192: static void center_image (void)
2193: {
2194: prev_x_adjust = linetoscr_x_adjust;
2195: prev_y_adjust = thisframe_y_adjust;
2196:
2197: if (currprefs.gfx_xcenter) {
2198: if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
2199: /* Try to center. */
2200: linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
2201: else
2202: linetoscr_x_adjust = max_diwstop - gfxvidinfo.width;
2203:
2204: /* Would the old value be good enough? If so, leave it as it is if we want to
2205: * be clever. */
2206: if (currprefs.gfx_xcenter == 2) {
2207: if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart)
2208: linetoscr_x_adjust = prev_x_adjust;
2209: }
2210: } else
2211: linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width;
2212: if (linetoscr_x_adjust < 0)
2213: linetoscr_x_adjust = 0;
2214:
2215: linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes;
2216:
2217: linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width;
2218: if (linetoscr_right_x > max_diwlastword)
2219: linetoscr_right_x = max_diwlastword;
2220:
2221: thisframe_y_adjust = minfirstline;
2222: if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
2223: if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
2224: thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
2225: else
2226: thisframe_y_adjust = thisframe_first_drawn_line;
2227: /* Would the old value be good enough? If so, leave it as it is if we want to
2228: * be clever. */
2229: if (currprefs.gfx_ycenter == 2) {
2230: if (thisframe_y_adjust != prev_y_adjust
2231: && prev_y_adjust <= thisframe_first_drawn_line
2232: && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
2233: thisframe_y_adjust = prev_y_adjust;
2234: }
2235: /* Make sure the value makes sense */
2236: if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
2237: thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
2238: if (thisframe_y_adjust < minfirstline)
2239: thisframe_y_adjust = minfirstline;
2240: }
2241: thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
2242: max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
2243:
2244: /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably
2245: * better. */
2246: if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust)
2247: frame_redraw_necessary |= interlace_seen && currprefs.gfx_linedbl ? 2 : 1;
2248:
2249: max_diwstop = 0;
2250: min_diwstart = 10000;
2251: }
2252:
2253: static void init_drawing_frame (void)
2254: {
2255: int i, maxline;
2256:
2257: init_hardware_for_drawing_frame ();
2258:
2259: if (max_diwstop == 0)
2260: max_diwstop = diwlastword;
2261: if (min_diwstart > max_diwstop)
2262: min_diwstart = 0;
2263:
2264: if (thisframe_first_drawn_line == -1)
2265: thisframe_first_drawn_line = minfirstline;
2266: if (thisframe_first_drawn_line > thisframe_last_drawn_line)
2267: thisframe_last_drawn_line = thisframe_first_drawn_line;
2268:
2269: maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
2270: #ifdef SMART_UPDATE
1.1.1.2 root 2271: for (i = 0; i < maxline; i++) {
2272: switch (linestate[i]) {
2273: case LINE_DONE_AS_PREVIOUS:
2274: linestate[i] = LINE_REMEMBERED_AS_PREVIOUS;
2275: break;
2276: case LINE_REMEMBERED_AS_BLACK:
2277: break;
2278: default:
2279: linestate[i] = LINE_UNDECIDED;
2280: break;
2281: }
2282: }
1.1 root 2283: #else
2284: memset (linestate, LINE_UNDECIDED, maxline);
2285: #endif
2286: last_drawn_line = 0;
2287: first_drawn_line = 32767;
2288:
2289: first_block_line = last_block_line = -2;
2290: if (currprefs.test_drawing_speed)
2291: frame_redraw_necessary = 1;
2292: else if (frame_redraw_necessary)
2293: frame_redraw_necessary--;
2294:
2295: center_image ();
2296:
2297: thisframe_first_drawn_line = -1;
2298: thisframe_last_drawn_line = -1;
2299: #ifdef SUPPORT_PENGUINS
2300: penguins_enabled_thisframe = 1;
2301: /* Tell the other thread that it can now expect data from us. */
2302: write_comm_pipe_int (&drawing_pipe, -2, 1);
2303: memset (line_drawn, 0, sizeof line_drawn);
2304: #endif
2305:
2306: drawing_color_matches = -1;
2307: }
2308:
2309: void finish_drawing_frame (void)
2310: {
2311: int i;
2312:
2313: #ifdef SUPPORT_PENGUINS
2314: /* Synchronize with other thread, then see whether there's something left for
2315: * us to draw. @@@ This is probably a big waste of cycles if the two threads
2316: * run at very different speeds - this one could draw stuff as well. */
2317: write_comm_pipe_int (&drawing_pipe, -1, 1);
2318: uae_sem_wait (&drawing_lock);
2319: #else
2320:
2321: #ifndef SMART_UPDATE
2322: /* @@@ This isn't exactly right yet. FIXME */
2323: if (!interlace_seen) {
2324: do_flush_screen (first_drawn_line, last_drawn_line);
2325: return;
2326: }
2327: #endif
2328: if (! lockscr ()) {
2329: notice_screen_contents_lost ();
2330: return;
2331: }
2332: for (i = 0; i < max_ypos_thisframe; i++) {
2333: int where;
2334: int line = i + thisframe_y_adjust_real;
2335:
2336: if (linestate[line] == LINE_UNDECIDED)
2337: break;
2338:
2339: where = amiga2aspect_line_map[i+min_ypos_for_screen];
2340: if (where >= gfxvidinfo.height)
2341: break;
2342: if (where == -1)
2343: continue;
2344:
2345: pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
2346: }
2347: unlockscr ();
2348: #endif
2349: do_flush_screen (first_drawn_line, last_drawn_line);
2350: }
2351:
2352: void hardware_line_completed (int lineno)
2353: {
2354: #ifdef SUPPORT_PENGUINS
2355: if (framecnt == 0 && penguins_enabled_thisframe) {
2356: write_comm_pipe_int (&drawing_pipe, lineno, 0);
2357: }
2358: #endif
2359: #ifndef SMART_UPDATE
2360: {
2361: int i, where;
2362: /* l is the line that has been finished for drawing. */
2363: i = lineno - thisframe_y_adjust_real;
2364: if (i >= 0 && i < max_ypos_thisframe) {
2365: where = amiga2aspect_line_map[i+min_ypos_for_screen];
2366: if (where < gfxvidinfo.height && where != -1)
2367: pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
2368: }
2369: }
2370: #endif
2371: }
2372:
2373: static __inline__ void check_picasso (void)
2374: {
2375: #ifdef PICASSO96
2376: if (picasso_on && picasso_redraw_necessary)
2377: picasso_refresh ();
2378: picasso_redraw_necessary = 0;
2379:
2380: if (picasso_requested_on == picasso_on)
2381: return;
2382:
2383: picasso_on = picasso_requested_on;
2384:
2385: if (!picasso_on)
1.1.1.3 root 2386: clear_inhibit_frame (IHF_PICASSO);
1.1 root 2387: else
1.1.1.3 root 2388: set_inhibit_frame (IHF_PICASSO);
1.1 root 2389:
2390: gfx_set_picasso_state (picasso_on);
2391: picasso_enablescreen (picasso_requested_on);
2392:
2393: notice_screen_contents_lost ();
2394: notice_new_xcolors ();
2395: #endif
2396: }
2397:
2398: void vsync_handle_redraw (int long_frame, int lof_changed)
2399: {
2400: last_redraw_point++;
2401: if (lof_changed || ! interlace_seen || last_redraw_point >= 2 || long_frame) {
2402: last_redraw_point = 0;
2403: interlace_seen = 0;
2404:
2405: if (framecnt == 0)
2406: finish_drawing_frame ();
2407:
2408: /* At this point, we have finished both the hardware and the
2409: * drawing frame. Essentially, we are outside of all loops and
2410: * can do some things which would cause confusion if they were
2411: * done at other times.
2412: */
2413:
2414: if (quit_program < 0) {
2415: quit_program = -quit_program;
1.1.1.3 root 2416: set_inhibit_frame (IHF_QUIT_PROGRAM);
1.1 root 2417: regs.spcflags |= SPCFLAG_BRK;
2418: filesys_prepare_reset ();
2419: #ifdef SUPPORT_PENGUINS
2420: if (quit_program == 1)
2421: /* Stop eating herring */
2422: write_comm_pipe_int (&drawing_pipe, -3, 1);
2423: #endif
2424: return;
2425: }
2426:
2427: count_frame ();
2428: check_picasso ();
2429:
1.1.1.2 root 2430: check_prefs_changed_audio ();
1.1 root 2431: check_prefs_changed_custom ();
2432: check_prefs_changed_cpu ();
2433: if (check_prefs_changed_gfx ()) {
2434: init_row_map ();
2435: init_aspect_maps ();
2436: notice_screen_contents_lost ();
2437: notice_new_xcolors ();
2438: }
2439:
2440: if (inhibit_frame != 0)
2441: framecnt = 1;
2442:
2443: if (framecnt == 0)
2444: init_drawing_frame ();
2445: }
2446: }
2447:
1.1.1.2 root 2448: void hsync_record_line_state (int lineno, enum nln_how how, int changed)
1.1 root 2449: {
1.1.1.2 root 2450: char *state;
1.1 root 2451: if (framecnt != 0)
2452: return;
1.1.1.2 root 2453:
2454: state = linestate + lineno;
2455: changed += frame_redraw_necessary;
2456:
1.1 root 2457: switch (how) {
2458: case nln_normal:
1.1.1.2 root 2459: *state = changed ? LINE_DECIDED : LINE_DONE;
1.1 root 2460: break;
2461: case nln_doubled:
1.1.1.2 root 2462: *state = changed ? LINE_DECIDED_DOUBLE : LINE_DONE;
2463: changed += state[1] != LINE_REMEMBERED_AS_PREVIOUS;
2464: state[1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS;
2465: break;
2466: case nln_nblack:
2467: *state = changed ? LINE_DECIDED : LINE_DONE;
2468: if (state[1] != LINE_REMEMBERED_AS_BLACK)
2469: state[1] = LINE_BLACK;
1.1 root 2470: break;
2471: case nln_lower:
1.1.1.2 root 2472: if (state[-1] == LINE_UNDECIDED)
2473: state[-1] = LINE_BLACK;
2474: *state = changed ? LINE_DECIDED : LINE_DONE;
1.1 root 2475: break;
2476: case nln_upper:
1.1.1.2 root 2477: *state = changed ? LINE_DECIDED : LINE_DONE;
2478: if (state[1] == LINE_UNDECIDED
2479: || state[1] == LINE_REMEMBERED_AS_PREVIOUS
2480: || state[1] == LINE_AS_PREVIOUS)
2481: state[1] = LINE_BLACK;
1.1 root 2482: break;
2483: }
2484: }
2485:
2486: void notice_interlace_seen (void)
2487: {
2488: interlace_seen = 1;
2489: penguins_enabled_thisframe = 0;
2490: }
2491:
2492: void reset_drawing (void)
2493: {
2494: int i;
2495:
2496: inhibit_frame = 0;
2497: uae_sem_init (&gui_sem, 0, 1);
2498:
2499: #ifdef PICASSO96
2500: InitPicasso96 ();
2501: picasso_on = 0;
2502: picasso_requested_on = 0;
2503: gfx_set_picasso_state (0);
2504: #endif
2505: max_diwstop = 0;
2506:
2507: lores_factor = currprefs.gfx_lores ? 1 : 2;
2508: lores_shift = currprefs.gfx_lores ? 0 : 1;
2509: sprite_width = currprefs.gfx_lores ? 16 : 32;
2510:
2511: /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */
2512: for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
2513: linestate[i] = LINE_UNDECIDED;
2514:
2515: xlinebuffer = gfxvidinfo.bufmem;
2516:
2517: init_aspect_maps ();
2518:
2519: if (line_drawn == 0)
2520: line_drawn = (char *)malloc (gfxvidinfo.height);
2521:
2522: init_row_map();
2523:
2524: last_redraw_point = 0;
2525:
2526: init_drawing_frame ();
2527: }
2528:
2529: void drawing_init ()
2530: {
2531: native2amiga_line_map = 0;
2532: amiga2aspect_line_map = 0;
2533: line_drawn = 0;
2534:
2535: gen_pfield_tables();
2536:
2537: #ifdef SUPPORT_PENGUINS
2538: init_comm_pipe (&drawing_pipe, 800, 5);
2539: uae_sem_init (&drawing_lock, 0, 0);
2540: start_penguin (drawing_penguin, 0, &our_penguin);
2541: /*atexit(kill_drawing_penguin);*/
2542: #endif
2543: }
2544:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.