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