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