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