|
|
1.1 root 1: /*
2: * UAE - The Un*x Amiga Emulator
3: *
4: * Screen drawing functions
5: *
1.1.1.8 root 6: * Copyright 1995-2000 Bernd Schmidt
1.1 root 7: * Copyright 1995 Alessandro Bissacco
1.1.1.13 root 8: * Copyright 2000,2001 Toni Wilen
1.1 root 9: */
10:
1.1.1.8 root 11: /* There are a couple of concepts of "coordinates" in this file.
12: - DIW coordinates
13: - DDF coordinates (essentially cycles, resolution lower than lores by a factor of 2)
14: - Pixel coordinates
15: * in the Amiga's resolution as determined by BPLCON0 ("Amiga coordinates")
16: * in the window resolution as determined by the preferences ("window coordinates").
17: * in the window resolution, and with the origin being the topmost left corner of
18: the window ("native coordinates")
19: One note about window coordinates. The visible area depends on the width of the
20: window, and the centering code. The first visible horizontal window coordinate is
21: often _not_ 0, but the value of VISIBLE_LEFT_BORDER instead.
22:
23: One important thing to remember: DIW coordinates are in the lowest possible
24: resolution.
25:
26: To prevent extremely bad things (think pixels cut in half by window borders) from
27: happening, all ports should restrict window widths to be multiples of 16 pixels. */
28:
1.1 root 29: #include "sysconfig.h"
30: #include "sysdeps.h"
31:
32: #include <ctype.h>
33: #include <assert.h>
34:
35: #include "options.h"
1.1.1.14 root 36: #include "threaddep/thread.h"
1.1 root 37: #include "uae.h"
38: #include "memory.h"
39: #include "custom.h"
40: #include "newcpu.h"
41: #include "xwin.h"
42: #include "autoconf.h"
43: #include "gui.h"
44: #include "picasso96.h"
45: #include "drawing.h"
1.1.1.13 root 46: #include "savestate.h"
1.1 root 47:
1.1.1.12 root 48: int lores_factor, lores_shift;
1.1 root 49:
1.1.1.8 root 50: /* The shift factor to apply when converting between Amiga coordinates and window
51: coordinates. Zero if the resolution is the same, positive if window coordinates
52: have a higher resolution (i.e. we're stretching the image), negative if window
53: coordinates have a lower resolution (i.e. we're shrinking the image). */
54: static int res_shift;
55:
1.1 root 56: static int interlace_seen = 0;
57:
1.1.1.11 root 58: /* Lookup tables for dual playfields. The dblpf_*1 versions are for the case
59: that playfield 1 has the priority, dbplpf_*2 are used if playfield 2 has
60: priority. If we need an array for non-dual playfield mode, it has no number. */
61: /* The dbplpf_ms? arrays contain a shift value. plf_spritemask is initialized
62: to contain two 16 bit words, with the appropriate mask if pf1 is in the
63: foreground being at bit offset 0, the one used if pf2 is in front being at
64: offset 16. */
1.1.1.12 root 65:
1.1.1.11 root 66: static int dblpf_ms1[256], dblpf_ms2[256], dblpf_ms[256];
67: static int dblpf_ind1[256], dblpf_ind2[256];
1.1.1.12 root 68:
69: static int dblpf_2nd1[256], dblpf_2nd2[256];
70: static int dblpf_ind1_aga[256], dblpf_ind2_aga[256];
71:
1.1 root 72: static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
73:
1.1.1.11 root 74: static int sprite_offs[256];
75:
1.1 root 76: static uae_u32 clxtab[256];
77:
78: /* Video buffer description structure. Filled in by the graphics system
79: * dependent code. */
80:
81: struct vidbuf_description gfxvidinfo;
82:
1.1.1.9 root 83: /* OCS/ECS color lookup table. */
1.1 root 84: xcolnr xcolors[4096];
1.1.1.9 root 85: /* AGA mode color lookup tables */
86: unsigned int xredcolors[256], xgreencolors[256], xbluecolors[256];
1.1 root 87:
88: struct color_entry colors_for_drawing;
89:
1.1.1.8 root 90: /* The size of these arrays is pretty arbitrary; it was chosen to be "more
91: than enough". The coordinates used for indexing into these arrays are
92: almost, but not quite, Amiga coordinates (there's a constant offset). */
1.1 root 93: union {
94: /* Let's try to align this thing. */
95: double uupzuq;
96: long int cruxmedo;
1.1.1.13 root 97: uae_u8 apixels[MAX_PIXELS_PER_LINE * 2];
98: uae_u16 apixels_w[MAX_PIXELS_PER_LINE * 2 / 2];
99: uae_u32 apixels_l[MAX_PIXELS_PER_LINE * 2 / 4];
1.1 root 100: } pixdata;
101:
1.1.1.11 root 102: uae_u16 spixels[2 * MAX_SPR_PIXELS];
103: /* Eight bits for every pixel. */
104: union sps_union spixstate;
105:
1.1.1.13 root 106: static uae_u32 ham_linebuf[MAX_PIXELS_PER_LINE * 2];
107: static uae_u8 spriteagadpfpixels[MAX_PIXELS_PER_LINE * 2]; /* AGA dualplayfield sprite */
1.1 root 108:
109: char *xlinebuffer;
110:
111: static int *amiga2aspect_line_map, *native2amiga_line_map;
112: static char *row_map[2049];
113: static int max_drawn_amiga_line;
114:
1.1.1.9 root 115: /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham */
1.1 root 116: typedef void (*line_draw_func)(int, int);
117:
118: #define LINE_UNDECIDED 1
119: #define LINE_DECIDED 2
120: #define LINE_DECIDED_DOUBLE 3
121: #define LINE_AS_PREVIOUS 4
1.1.1.2 root 122: #define LINE_BLACK 5
123: #define LINE_REMEMBERED_AS_BLACK 6
1.1 root 124: #define LINE_DONE 7
125: #define LINE_DONE_AS_PREVIOUS 8
126: #define LINE_REMEMBERED_AS_PREVIOUS 9
127:
128: static char *line_drawn;
1.1.1.5 root 129: static char linestate[(MAXVPOS + 1)*2 + 1];
1.1 root 130:
1.1.1.5 root 131: uae_u8 line_data[(MAXVPOS + 1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
1.1 root 132:
1.1.1.8 root 133: /* Centering variables. */
1.1.1.17 root 134: static int min_diwstart, max_diwstop;
1.1.1.8 root 135: /* The visible window: VISIBLE_LEFT_BORDER contains the left border of the visible
136: area, VISIBLE_RIGHT_BORDER the right border. These are in window coordinates. */
137: static int visible_left_border, visible_right_border;
1.1 root 138: static int linetoscr_x_adjust_bytes;
1.1.1.17 root 139: static int thisframe_y_adjust;
1.1 root 140: static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
141: static int extra_y_adjust;
142: int thisframe_first_drawn_line, thisframe_last_drawn_line;
143:
1.1.1.8 root 144: /* A frame counter that forces a redraw after at least one skipped frame in
145: interlace mode. */
1.1 root 146: static int last_redraw_point;
147:
148: static int first_drawn_line, last_drawn_line;
149: static int first_block_line, last_block_line;
150:
151: /* These are generated by the drawing code from the line_decisions array for
1.1.1.8 root 152: each line that needs to be drawn. These are basically extracted out of
153: bit fields in the hardware registers. */
1.1.1.13 root 154: static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt, bplres;
1.1.1.11 root 155: static uae_u32 plf_sprite_mask;
1.1.1.12 root 156: static int sbasecol[2];
1.1 root 157:
158: int picasso_requested_on;
159: int picasso_on;
160:
161: uae_sem_t gui_sem;
162: int inhibit_frame;
163:
164: int framecnt = 0;
165: static int frame_redraw_necessary;
166: static int picasso_redraw_necessary;
167:
1.1.1.6 root 168: STATIC_INLINE void count_frame (void)
1.1 root 169: {
170: framecnt++;
1.1.1.5 root 171: if (framecnt >= currprefs.gfx_framerate)
1.1 root 172: framecnt = 0;
173: }
174:
175: int coord_native_to_amiga_x (int x)
176: {
1.1.1.8 root 177: x += visible_left_border;
1.1 root 178: x <<= (1 - lores_shift);
1.1.1.11 root 179: return x + 2*DISPLAY_LEFT_SHIFT - 2*DIW_DDF_OFFSET;
1.1 root 180: }
181:
182: int coord_native_to_amiga_y (int y)
183: {
184: return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline;
185: }
186:
1.1.1.8 root 187: STATIC_INLINE int res_shift_from_window (int x)
188: {
189: if (res_shift >= 0)
190: return x >> res_shift;
191: return x << -res_shift;
192: }
193:
194: STATIC_INLINE int res_shift_from_amiga (int x)
195: {
196: if (res_shift >= 0)
197: return x >> res_shift;
198: return x << -res_shift;
199: }
200:
1.1 root 201: void notice_screen_contents_lost (void)
202: {
203: picasso_redraw_necessary = 1;
204: frame_redraw_necessary = 2;
205: }
206:
207: static struct decision *dp_for_drawing;
208: static struct draw_info *dip_for_drawing;
209:
1.1.1.8 root 210: /* Record DIW of the current line for use by centering code. */
1.1 root 211: void record_diw_line (int first, int last)
212: {
213: if (last > max_diwstop)
214: max_diwstop = last;
215: if (first < min_diwstart)
216: min_diwstart = first;
217: }
218:
219: /*
220: * Screen update macros/functions
221: */
222:
1.1.1.8 root 223: /* The important positions in the line: where do we start drawing the left border,
224: where do we start drawing the playfield, where do we start drawing the right border.
225: All of these are forced into the visible window (VISIBLE_LEFT_BORDER .. VISIBLE_RIGHT_BORDER).
226: PLAYFIELD_START and PLAYFIELD_END are in window coordinates. */
227: static int playfield_start, playfield_end;
228:
229: static int pixels_offset;
230: static int src_pixel;
231: /* How many pixels in window coordinates which are to the left of the left border. */
232: static int unpainted;
1.1 root 233:
1.1.1.8 root 234: /* Initialize the variables necessary for drawing a line.
235: * This involves setting up start/stop positions and display window
236: * borders. */
237: static void pfield_init_linetoscr (void)
1.1 root 238: {
1.1.1.8 root 239: /* First, get data fetch start/stop in DIW coordinates. */
1.1.1.11 root 240: int ddf_left = dp_for_drawing->plfleft * 2 + DIW_DDF_OFFSET;
241: int ddf_right = dp_for_drawing->plfright * 2 + DIW_DDF_OFFSET;
1.1.1.8 root 242: /* Compute datafetch start/stop in pixels; native display coordinates. */
1.1.1.11 root 243: int native_ddf_left = coord_hw_to_window_x (ddf_left);
244: int native_ddf_right = coord_hw_to_window_x (ddf_right);
1.1.1.8 root 245:
246: int linetoscr_diw_start = dp_for_drawing->diwfirstword;
247: int linetoscr_diw_end = dp_for_drawing->diwlastword;
248:
249: if (dip_for_drawing->nr_sprites == 0) {
250: if (linetoscr_diw_start < native_ddf_left)
251: linetoscr_diw_start = native_ddf_left;
252: if (linetoscr_diw_end > native_ddf_right)
253: linetoscr_diw_end = native_ddf_right;
1.1 root 254: }
255:
1.1.1.8 root 256: /* Perverse cases happen. */
257: if (linetoscr_diw_end < linetoscr_diw_start)
258: linetoscr_diw_end = linetoscr_diw_start;
1.1 root 259:
1.1.1.8 root 260: playfield_start = linetoscr_diw_start;
261: playfield_end = linetoscr_diw_end;
1.1 root 262:
1.1.1.8 root 263: if (playfield_start < visible_left_border)
264: playfield_start = visible_left_border;
265: if (playfield_start > visible_right_border)
266: playfield_start = visible_right_border;
267: if (playfield_end < visible_left_border)
268: playfield_end = visible_left_border;
269: if (playfield_end > visible_right_border)
270: playfield_end = visible_right_border;
271:
272: /* Now, compute some offsets. */
273:
274: res_shift = lores_shift - bplres;
1.1.1.11 root 275: ddf_left -= DISPLAY_LEFT_SHIFT;
276: ddf_left <<= bplres;
1.1.1.12 root 277: pixels_offset = MAX_PIXELS_PER_LINE - ddf_left;
1.1.1.11 root 278:
1.1.1.8 root 279: unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start;
1.1.1.12 root 280: src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window (playfield_start - native_ddf_left + unpainted);
1.1 root 281:
1.1.1.8 root 282: if (dip_for_drawing->nr_sprites == 0)
1.1 root 283: return;
1.1.1.8 root 284: /* Must clear parts of apixels. */
285: if (linetoscr_diw_start < native_ddf_left) {
286: int size = res_shift_from_window (native_ddf_left - linetoscr_diw_start);
287: linetoscr_diw_start = native_ddf_left;
1.1.1.12 root 288: memset (pixdata.apixels + MAX_PIXELS_PER_LINE - size, 0, size);
1.1.1.8 root 289: }
290: if (linetoscr_diw_end > native_ddf_right) {
291: int pos = res_shift_from_window (native_ddf_right - native_ddf_left);
292: int size = res_shift_from_window (linetoscr_diw_end - native_ddf_right);
293: linetoscr_diw_start = native_ddf_left;
1.1.1.12 root 294: memset (pixdata.apixels + MAX_PIXELS_PER_LINE + pos, 0, size);
1.1 root 295: }
296: }
1.1.1.2 root 297:
1.1.1.8 root 298: /* If C++ compilers didn't suck, we'd use templates. */
299:
300: #define TYPE uae_u8
301: #define LNAME linetoscr_8
302: #define SRC_INC 1
303: #define HDOUBLE 0
1.1.1.17 root 304: #define AGAC 0
1.1.1.8 root 305: #include "linetoscr.c"
1.1.1.9 root 306: #define LNAME linetoscr_8_stretch1
1.1.1.8 root 307: #define SRC_INC 1
308: #define HDOUBLE 1
1.1.1.17 root 309: #define AGAC 0
1.1.1.8 root 310: #include "linetoscr.c"
1.1.1.9 root 311: #define LNAME linetoscr_8_shrink1
1.1.1.8 root 312: #define SRC_INC 2
313: #define HDOUBLE 0
1.1.1.17 root 314: #define AGAC 0
1.1.1.9 root 315: #include "linetoscr.c"
316:
317: #define LNAME linetoscr_8_aga
318: #define SRC_INC 1
319: #define HDOUBLE 0
1.1.1.17 root 320: #define AGAC 1
1.1.1.9 root 321: #include "linetoscr.c"
322: #define LNAME linetoscr_8_stretch1_aga
323: #define SRC_INC 1
324: #define HDOUBLE 1
1.1.1.17 root 325: #define AGAC 1
1.1.1.9 root 326: #include "linetoscr.c"
327: #define LNAME linetoscr_8_shrink1_aga
328: #define SRC_INC 2
329: #define HDOUBLE 0
1.1.1.17 root 330: #define AGAC 1
1.1.1.8 root 331: #include "linetoscr.c"
332:
333: #undef TYPE
1.1.1.9 root 334:
1.1.1.8 root 335: #define TYPE uae_u16
336: #define LNAME linetoscr_16
337: #define SRC_INC 1
338: #define HDOUBLE 0
1.1.1.17 root 339: #define AGAC 0
1.1.1.8 root 340: #include "linetoscr.c"
1.1.1.9 root 341: #define LNAME linetoscr_16_stretch1
1.1.1.8 root 342: #define SRC_INC 1
343: #define HDOUBLE 1
1.1.1.17 root 344: #define AGAC 0
1.1.1.8 root 345: #include "linetoscr.c"
1.1.1.9 root 346: #define LNAME linetoscr_16_shrink1
1.1.1.8 root 347: #define SRC_INC 2
348: #define HDOUBLE 0
1.1.1.17 root 349: #define AGAC 0
1.1.1.9 root 350: #include "linetoscr.c"
351:
352: #define LNAME linetoscr_16_aga
353: #define SRC_INC 1
354: #define HDOUBLE 0
1.1.1.17 root 355: #define AGAC 1
1.1.1.9 root 356: #include "linetoscr.c"
357: #define LNAME linetoscr_16_stretch1_aga
358: #define SRC_INC 1
359: #define HDOUBLE 1
1.1.1.17 root 360: #define AGAC 1
1.1.1.9 root 361: #include "linetoscr.c"
362: #define LNAME linetoscr_16_shrink1_aga
363: #define SRC_INC 2
364: #define HDOUBLE 0
1.1.1.17 root 365: #define AGAC 1
1.1.1.8 root 366: #include "linetoscr.c"
367:
368: #undef TYPE
1.1.1.9 root 369:
1.1.1.8 root 370: #define TYPE uae_u32
371: #define LNAME linetoscr_32
372: #define SRC_INC 1
373: #define HDOUBLE 0
1.1.1.17 root 374: #define AGAC 0
1.1.1.8 root 375: #include "linetoscr.c"
1.1.1.9 root 376: #define LNAME linetoscr_32_stretch1
1.1.1.8 root 377: #define SRC_INC 1
378: #define HDOUBLE 1
1.1.1.17 root 379: #define AGAC 0
1.1.1.8 root 380: #include "linetoscr.c"
1.1.1.9 root 381: #define LNAME linetoscr_32_shrink1
1.1.1.8 root 382: #define SRC_INC 2
383: #define HDOUBLE 0
1.1.1.17 root 384: #define AGAC 0
1.1.1.9 root 385: #include "linetoscr.c"
386:
387: #define LNAME linetoscr_32_aga
388: #define SRC_INC 1
389: #define HDOUBLE 0
1.1.1.17 root 390: #define AGAC 1
1.1.1.9 root 391: #include "linetoscr.c"
392: #define LNAME linetoscr_32_stretch1_aga
393: #define SRC_INC 1
394: #define HDOUBLE 1
1.1.1.17 root 395: #define AGAC 1
1.1.1.9 root 396: #include "linetoscr.c"
397: #define LNAME linetoscr_32_shrink1_aga
398: #define SRC_INC 2
399: #define HDOUBLE 0
1.1.1.17 root 400: #define AGAC 1
1.1.1.8 root 401: #include "linetoscr.c"
1.1 root 402:
1.1.1.9 root 403: #undef TYPE
404:
1.1.1.8 root 405: static void fill_line_8 (char *buf, int start, int stop)
1.1 root 406: {
1.1.1.8 root 407: uae_u8 *b = (uae_u8 *)buf;
1.1 root 408: int i;
1.1.1.8 root 409: xcolnr col = colors_for_drawing.acolors[0];
410: for (i = start; i < stop; i++)
411: b[i] = col;
1.1 root 412: }
1.1.1.8 root 413: static void fill_line_16 (char *buf, int start, int stop)
1.1 root 414: {
1.1.1.8 root 415: uae_u16 *b = (uae_u16 *)buf;
1.1 root 416: int i;
1.1.1.8 root 417: xcolnr col = colors_for_drawing.acolors[0];
418: for (i = start; i < stop; i++)
419: b[i] = col;
1.1 root 420: }
1.1.1.8 root 421: static void fill_line_32 (char *buf, int start, int stop)
1.1 root 422: {
1.1.1.8 root 423: uae_u32 *b = (uae_u32 *)buf;
1.1 root 424: int i;
1.1.1.8 root 425: xcolnr col = colors_for_drawing.acolors[0];
426: for (i = start; i < stop; i++)
427: b[i] = col;
1.1.1.2 root 428: }
429:
1.1.1.6 root 430: STATIC_INLINE void fill_line (void)
1.1 root 431: {
432: int shift;
433: int nints, nrem;
434: int *start;
435: xcolnr val;
436:
437: shift = 0;
438: if (gfxvidinfo.pixbytes == 2)
439: shift = 1;
440: if (gfxvidinfo.pixbytes == 4)
441: shift = 2;
442:
443: nints = gfxvidinfo.width >> (2-shift);
444: nrem = nints & 7;
445: nints &= ~7;
1.1.1.8 root 446: start = (int *)(((char *)xlinebuffer) + (visible_left_border << shift));
1.1 root 447: val = colors_for_drawing.acolors[0];
1.1.1.9 root 448: if (gfxvidinfo.pixbytes == 2)
1.1.1.18 root 449: val |= val << 16;
1.1 root 450: for (; nints > 0; nints -= 8, start += 8) {
451: *start = val;
452: *(start+1) = val;
453: *(start+2) = val;
454: *(start+3) = val;
455: *(start+4) = val;
456: *(start+5) = val;
457: *(start+6) = val;
458: *(start+7) = val;
459: }
460:
461: switch (nrem) {
462: case 7:
463: *start++ = val;
464: case 6:
465: *start++ = val;
466: case 5:
467: *start++ = val;
468: case 4:
469: *start++ = val;
470: case 3:
471: *start++ = val;
472: case 2:
473: *start++ = val;
474: case 1:
475: *start = val;
476: }
477: }
478:
1.1.1.8 root 479: static int linetoscr_double_offset;
1.1 root 480:
1.1.1.8 root 481: static void pfield_do_linetoscr (int start, int stop)
482: {
1.1.1.9 root 483: if (currprefs.chipset_mask & CSMASK_AGA) {
484: if (res_shift == 0)
485: switch (gfxvidinfo.pixbytes) {
486: case 1: src_pixel = linetoscr_8_aga (src_pixel, start, stop); break;
487: case 2: src_pixel = linetoscr_16_aga (src_pixel, start, stop); break;
488: case 4: src_pixel = linetoscr_32_aga (src_pixel, start, stop); break;
489: }
490: else if (res_shift == 1)
491: switch (gfxvidinfo.pixbytes) {
492: case 1: src_pixel = linetoscr_8_stretch1_aga (src_pixel, start, stop); break;
493: case 2: src_pixel = linetoscr_16_stretch1_aga (src_pixel, start, stop); break;
494: case 4: src_pixel = linetoscr_32_stretch1_aga (src_pixel, start, stop); break;
495: }
496: else if (res_shift == -1)
497: switch (gfxvidinfo.pixbytes) {
498: case 1: src_pixel = linetoscr_8_shrink1_aga (src_pixel, start, stop); break;
499: case 2: src_pixel = linetoscr_16_shrink1_aga (src_pixel, start, stop); break;
500: case 4: src_pixel = linetoscr_32_shrink1_aga (src_pixel, start, stop); break;
501: }
1.1.1.18 root 502: else
1.1.1.9 root 503: abort ();
504: } else {
1.1.1.18 root 505: if (res_shift == 0)
1.1.1.9 root 506: switch (gfxvidinfo.pixbytes) {
507: case 1: src_pixel = linetoscr_8 (src_pixel, start, stop); break;
508: case 2: src_pixel = linetoscr_16 (src_pixel, start, stop); break;
509: case 4: src_pixel = linetoscr_32 (src_pixel, start, stop); break;
510: }
511: else if (res_shift == 1)
512: switch (gfxvidinfo.pixbytes) {
513: case 1: src_pixel = linetoscr_8_stretch1 (src_pixel, start, stop); break;
514: case 2: src_pixel = linetoscr_16_stretch1 (src_pixel, start, stop); break;
515: case 4: src_pixel = linetoscr_32_stretch1 (src_pixel, start, stop); break;
516: }
517: else if (res_shift == -1)
518: switch (gfxvidinfo.pixbytes) {
519: case 1: src_pixel = linetoscr_8_shrink1 (src_pixel, start, stop); break;
520: case 2: src_pixel = linetoscr_16_shrink1 (src_pixel, start, stop); break;
521: case 4: src_pixel = linetoscr_32_shrink1 (src_pixel, start, stop); break;
522: }
523: else
524: abort ();
525: }
1.1 root 526: }
527:
1.1.1.8 root 528: static void pfield_do_fill_line (int start, int stop)
1.1 root 529: {
1.1.1.8 root 530: switch (gfxvidinfo.pixbytes) {
531: case 1: fill_line_8 (xlinebuffer, start, stop); break;
532: case 2: fill_line_16 (xlinebuffer, start, stop); break;
533: case 4: fill_line_32 (xlinebuffer, start, stop); break;
1.1 root 534: }
535: }
536:
1.1.1.8 root 537: static void pfield_do_linetoscr_full (int double_line)
1.1 root 538: {
539: char *oldxlb = (char *)xlinebuffer;
1.1.1.8 root 540: int old_src_pixel = src_pixel;
541:
542: pfield_do_linetoscr (playfield_start, playfield_end);
1.1 root 543: xlinebuffer = oldxlb + linetoscr_double_offset;
1.1.1.8 root 544: src_pixel = old_src_pixel;
545: pfield_do_linetoscr (playfield_start, playfield_end);
1.1 root 546: }
1.1.1.8 root 547:
548: static void dummy_worker (int start, int stop)
1.1 root 549: {
550: }
551:
1.1.1.8 root 552: static unsigned int ham_lastcolor;
1.1.1.2 root 553:
1.1.1.8 root 554: static int ham_decode_pixel;
1.1 root 555:
1.1.1.8 root 556: /* Decode HAM in the invisible portion of the display (left of VISIBLE_LEFT_BORDER),
557: but don't draw anything in. This is done to prepare HAM_LASTCOLOR for later,
1.1.1.9 root 558: when decode_ham runs. */
1.1.1.8 root 559: static void init_ham_decoding (void)
1.1 root 560: {
1.1.1.8 root 561: int unpainted_amiga = res_shift_from_window (unpainted);
562: ham_decode_pixel = src_pixel;
1.1.1.9 root 563: ham_lastcolor = color_reg_get (&colors_for_drawing, 0);
564:
1.1.1.15 root 565: if (! bplham || (bplplanecnt != 6 && ((currprefs.chipset_mask & CSMASK_AGA) == 0 || bplplanecnt != 8))) {
566: if (unpainted_amiga > 0) {
567: int pv = pixdata.apixels[ham_decode_pixel + unpainted_amiga - 1];
568: if (currprefs.chipset_mask & CSMASK_AGA)
569: ham_lastcolor = colors_for_drawing.color_regs_aga[pv];
570: else
571: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv];
572: }
573: } else if (currprefs.chipset_mask & CSMASK_AGA) {
1.1.1.9 root 574: if (bplplanecnt == 8) { /* AGA mode HAM8 */
575: while (unpainted_amiga-- > 0) {
576: int pv = pixdata.apixels[ham_decode_pixel++];
577: switch (pv & 0x3) {
578: case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
579: case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
580: case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
581: case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
582: }
583: }
1.1.1.15 root 584: } else if (bplplanecnt == 6) { /* AGA mode HAM6 */
1.1.1.9 root 585: while (unpainted_amiga-- > 0) {
1.1.1.18 root 586: int pv = pixdata.apixels[ham_decode_pixel++];
1.1.1.9 root 587: switch (pv & 0x30) {
588: case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
589: case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
590: case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
591: case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
592: }
593: }
594: }
595: } else {
1.1.1.18 root 596: if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */
1.1.1.9 root 597: while (unpainted_amiga-- > 0) {
598: int pv = pixdata.apixels[ham_decode_pixel++];
599: switch (pv & 0x30) {
600: case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
601: case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
602: case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
603: case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
604: }
605: }
1.1 root 606: }
607: }
608: }
609:
1.1.1.9 root 610: static void decode_ham (int pix, int stoppos)
1.1 root 611: {
1.1.1.8 root 612: int todraw_amiga = res_shift_from_window (stoppos - pix);
1.1 root 613:
1.1.1.15 root 614: if (! bplham || (bplplanecnt != 6 && ((currprefs.chipset_mask & CSMASK_AGA) == 0 || bplplanecnt != 8))) {
615: while (todraw_amiga-- > 0) {
616: int pv = pixdata.apixels[ham_decode_pixel];
617: if (currprefs.chipset_mask & CSMASK_AGA)
618: ham_lastcolor = colors_for_drawing.color_regs_aga[pv];
619: else
620: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv];
621:
622: ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
623: }
624: } else if (currprefs.chipset_mask & CSMASK_AGA) {
1.1.1.9 root 625: if (bplplanecnt == 8) { /* AGA mode HAM8 */
626: while (todraw_amiga-- > 0) {
627: int pv = pixdata.apixels[ham_decode_pixel];
628: switch (pv & 0x3) {
629: case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
630: case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
631: case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
632: case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
633: }
634: ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
635: }
1.1.1.15 root 636: } else if (bplplanecnt == 6) { /* AGA mode HAM6 */
1.1.1.9 root 637: while (todraw_amiga-- > 0) {
638: int pv = pixdata.apixels[ham_decode_pixel];
639: switch (pv & 0x30) {
640: case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
641: case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
642: case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
643: case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
644: }
645: ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
646: }
647: }
648: } else {
1.1.1.18 root 649: if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */
1.1.1.9 root 650: while (todraw_amiga-- > 0) {
1.1.1.18 root 651: int pv = pixdata.apixels[ham_decode_pixel];
1.1.1.9 root 652: switch (pv & 0x30) {
653: case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
654: case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
655: case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
656: case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
657: }
658: ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
659: }
1.1 root 660: }
661: }
662: }
663:
1.1.1.2 root 664: static void gen_pfield_tables (void)
1.1 root 665: {
666: int i;
667:
668: /* For now, the AGA stuff is broken in the dual playfield case. We encode
669: * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
670: * playfield rendering easy, the lookup tables contain are made linear for
671: * values >= 128. That only works for OCS/ECS, though. */
672:
673: for (i = 0; i < 256; i++) {
674: int plane1 = (i & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
675: int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
1.1.1.11 root 676:
1.1.1.12 root 677: dblpf_2nd1[i] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
678: dblpf_2nd2[i] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
679: dblpf_ind1_aga[i] = plane1 == 0 ? plane2 : plane1;
680: dblpf_ind2_aga[i] = plane2 == 0 ? plane1 : plane2;
681:
1.1.1.11 root 682: dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0;
683: dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8;
684: dblpf_ms[i] = i == 0 ? 16 : 8;
1.1 root 685: if (plane2 > 0)
686: plane2 += 8;
687: dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
688: dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
689:
1.1.1.11 root 690: sprite_offs[i] = (i & 15) ? 0 : 2;
1.1 root 691:
692: clxtab[i] = ((((i & 3) && (i & 12)) << 9)
693: | (((i & 3) && (i & 48)) << 10)
694: | (((i & 3) && (i & 192)) << 11)
695: | (((i & 12) && (i & 48)) << 12)
696: | (((i & 12) && (i & 192)) << 13)
697: | (((i & 48) && (i & 192)) << 14));
698: }
699: }
700:
1.1.1.11 root 701: /* When looking at this function and the ones that inline it, bear in mind
702: what an optimizing compiler will do with this code. All callers of this
703: function only pass in constant arguments (except for E). This means
704: that many of the if statements will go away completely after inlining. */
1.1.1.13 root 705: STATIC_INLINE void draw_sprites_1 (struct sprite_entry *e, int ham, int dualpf,
706: int doubling, int skip, int has_attach, int aga)
1.1.1.11 root 707: {
708: int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms;
709: uae_u16 *buf = spixels + e->first_pixel;
710: uae_u8 *stbuf = spixstate.bytes + e->first_pixel;
1.1.1.13 root 711: int pos, window_pos;
712: uae_u8 xor_val = (uae_u8)(dp_for_drawing->bplcon4 >> 8);
1.1.1.11 root 713:
714: buf -= e->pos;
715: stbuf -= e->pos;
716:
1.1.1.13 root 717: window_pos = e->pos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << (aga ? 1 : 0));
718: if (skip)
719: window_pos >>= 1;
720: else if (doubling)
721: window_pos <<= 1;
722: window_pos += pixels_offset;
723: for (pos = e->pos; pos < e->max; pos += 1 << skip) {
1.1.1.11 root 724: int maskshift, plfmask;
725: unsigned int v = buf[pos];
726:
727: /* The value in the shift lookup table is _half_ the shift count we
728: need. This is because we can't shift 32 bits at once (undefined
729: behaviour in C). */
1.1.1.13 root 730: maskshift = shift_lookup[pixdata.apixels[window_pos]];
1.1.1.11 root 731: plfmask = (plf_sprite_mask >> maskshift) >> maskshift;
732: v &= ~plfmask;
733: if (v != 0) {
1.1.1.13 root 734: unsigned int vlo, vhi, col;
1.1.1.11 root 735: unsigned int v1 = v & 255;
736: /* OFFS determines the sprite pair with the highest priority that has
737: any bits set. E.g. if we have 0xFF00 in the buffer, we have sprite
738: pairs 01 and 23 cleared, and pairs 45 and 67 set, so OFFS will
739: have a value of 4.
740: 2 * OFFS is the bit number in V of the sprite pair, and it also
741: happens to be the color offset for that pair. */
742: int offs;
743: if (v1 == 0)
744: offs = 4 + sprite_offs[v >> 8];
745: else
746: offs = sprite_offs[v1];
747:
748: /* Shift highest priority sprite pair down to bit zero. */
749: v >>= offs * 2;
750: v &= 15;
1.1.1.18 root 751:
1.1.1.11 root 752: if (has_attach && (stbuf[pos] & (1 << offs))) {
753: col = v;
1.1.1.13 root 754: if (aga)
755: col += sbasecol[1];
756: else
757: col += 16;
1.1.1.11 root 758: } else {
759: /* This sequence computes the correct color value. We have to select
760: either the lower-numbered or the higher-numbered sprite in the pair.
761: We have to select the high one if the low one has all bits zero.
762: If the lower-numbered sprite has any bits nonzero, (VLO - 1) is in
763: the range of 0..2, and with the mask and shift, VHI will be zero.
764: If the lower-numbered sprite is zero, (VLO - 1) is a mask of
765: 0xFFFFFFFF, and we select the bits of the higher numbered sprite
766: in VHI.
767: This is _probably_ more efficient than doing it with branches. */
768: vlo = v & 3;
769: vhi = (v & (vlo - 1)) >> 2;
1.1.1.13 root 770: col = (vlo | vhi);
771: if (aga) {
772: if (vhi > 0)
773: col += sbasecol[1];
774: else
775: col += sbasecol[0];
776: } else {
777: col += 16;
778: }
1.1.1.11 root 779: col += (offs * 2);
780: }
1.1.1.13 root 781: if (dualpf) {
782: if (aga) {
783: spriteagadpfpixels[window_pos] = col;
784: if (doubling)
785: spriteagadpfpixels[window_pos + 1] = col;
786: } else {
787: col += 128;
788: if (doubling)
789: pixdata.apixels_w[window_pos >> 1] = col | (col << 8);
790: else
791: pixdata.apixels[window_pos] = col;
1.1 root 792: }
1.1.1.13 root 793: } else if (ham) {
794: col = color_reg_get (&colors_for_drawing, col);
795: if (aga)
796: col ^= xor_val;
797: ham_linebuf[window_pos] = col;
798: if (doubling)
799: ham_linebuf[window_pos + 1] = col;
1.1 root 800: } else {
1.1.1.13 root 801: if (aga)
802: col ^= xor_val;
803: if (doubling)
804: pixdata.apixels_w[window_pos >> 1] = col | (col << 8);
1.1.1.11 root 805: else
1.1.1.13 root 806: pixdata.apixels[window_pos] = col;
1.1 root 807: }
808: }
1.1.1.13 root 809: window_pos += 1 << doubling;
1.1 root 810: }
811: }
1.1.1.18 root 812:
1.1.1.11 root 813: /* See comments above. Do not touch if you don't know what's going on.
814: * (We do _not_ want the following to be inlined themselves). */
1.1.1.13 root 815: /* lores bitplane, lores sprites */
1.1.1.17 root 816: static void NOINLINE draw_sprites_normal_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 0, 0, 0); }
817: static void NOINLINE draw_sprites_normal_dp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 0, 0, 0); }
818: static void NOINLINE draw_sprites_ham_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 0, 0, 0); }
819: static void NOINLINE draw_sprites_normal_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 0, 1, 0); }
820: static void NOINLINE draw_sprites_normal_dp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 0, 1, 0); }
821: static void NOINLINE draw_sprites_ham_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 0, 1, 0); }
1.1.1.13 root 822: /* hires bitplane, lores sprites */
1.1.1.17 root 823: static void NOINLINE draw_sprites_normal_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 0, 0, 0); }
824: static void NOINLINE draw_sprites_normal_dp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 0, 0, 0); }
825: static void NOINLINE draw_sprites_ham_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 0, 0, 0); }
826: static void NOINLINE draw_sprites_normal_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 0, 1, 0); }
827: static void NOINLINE draw_sprites_normal_dp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 0, 1, 0); }
828: static void NOINLINE draw_sprites_ham_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 0, 1, 0); }
1.1.1.13 root 829:
830: /* not very optimized */
831: STATIC_INLINE void draw_sprites_aga (struct sprite_entry *e)
832: {
833: int diff = RES_HIRES - bplres;
834: if (diff > 0)
1.1.1.15 root 835: draw_sprites_1 (e, dp_for_drawing->ham_seen, bpldualpf, 0, diff, e->has_attached, 1);
1.1.1.13 root 836: else
1.1.1.15 root 837: draw_sprites_1 (e, dp_for_drawing->ham_seen, bpldualpf, -diff, 0, e->has_attached, 1);
1.1.1.13 root 838: }
839:
1.1.1.11 root 840:
1.1.1.13 root 841: STATIC_INLINE void draw_sprites_ecs (struct sprite_entry *e)
1.1.1.11 root 842: {
843: if (e->has_attached)
844: if (bplres == 1)
1.1.1.15 root 845: if (dp_for_drawing->ham_seen)
1.1.1.11 root 846: draw_sprites_ham_sp_hi_at (e);
847: else
848: if (bpldualpf)
849: draw_sprites_normal_dp_hi_at (e);
850: else
851: draw_sprites_normal_sp_hi_at (e);
852: else
1.1.1.15 root 853: if (dp_for_drawing->ham_seen)
1.1.1.11 root 854: draw_sprites_ham_sp_lo_at (e);
855: else
856: if (bpldualpf)
857: draw_sprites_normal_dp_lo_at (e);
858: else
859: draw_sprites_normal_sp_lo_at (e);
860: else
861: if (bplres == 1)
1.1.1.15 root 862: if (dp_for_drawing->ham_seen)
1.1.1.11 root 863: draw_sprites_ham_sp_hi_nat (e);
864: else
865: if (bpldualpf)
866: draw_sprites_normal_dp_hi_nat (e);
867: else
868: draw_sprites_normal_sp_hi_nat (e);
869: else
1.1.1.15 root 870: if (dp_for_drawing->ham_seen)
1.1.1.11 root 871: draw_sprites_ham_sp_lo_nat (e);
872: else
873: if (bpldualpf)
874: draw_sprites_normal_dp_lo_nat (e);
875: else
876: draw_sprites_normal_sp_lo_nat (e);
1.1 root 877: }
878:
1.1.1.13 root 879:
1.1.1.8 root 880: #define MERGE(a,b,mask,shift) do {\
881: uae_u32 tmp = mask & (a ^ (b >> shift)); \
882: a ^= tmp; \
883: b ^= (tmp << shift); \
884: } while (0)
885:
1.1.1.11 root 886: #define GETLONG(P) (*(uae_u32 *)P)
887:
888: /* We use the compiler's inlining ability to ensure that PLANES is in effect a compile time
889: constant. That will cause some unnecessary code to be optimized away.
1.1.1.8 root 890: Don't touch this if you don't know what you are doing. */
1.1.1.11 root 891: STATIC_INLINE void pfield_doline_1 (uae_u32 *pixels, int wordcount, int planes)
1.1.1.8 root 892: {
893: while (wordcount-- > 0) {
894: uae_u32 b0, b1, b2, b3, b4, b5, b6, b7;
895:
896: b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0;
897: switch (planes) {
1.1.1.11 root 898: case 8: b0 = GETLONG ((uae_u32 *)real_bplpt[7]); real_bplpt[7] += 4;
899: case 7: b1 = GETLONG ((uae_u32 *)real_bplpt[6]); real_bplpt[6] += 4;
900: case 6: b2 = GETLONG ((uae_u32 *)real_bplpt[5]); real_bplpt[5] += 4;
901: case 5: b3 = GETLONG ((uae_u32 *)real_bplpt[4]); real_bplpt[4] += 4;
902: case 4: b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4;
903: case 3: b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
904: case 2: b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
905: case 1: b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
1.1.1.8 root 906: }
907:
908: MERGE (b0, b1, 0x55555555, 1);
909: MERGE (b2, b3, 0x55555555, 1);
910: MERGE (b4, b5, 0x55555555, 1);
911: MERGE (b6, b7, 0x55555555, 1);
912:
913: MERGE (b0, b2, 0x33333333, 2);
914: MERGE (b1, b3, 0x33333333, 2);
915: MERGE (b4, b6, 0x33333333, 2);
916: MERGE (b5, b7, 0x33333333, 2);
917:
918: MERGE (b0, b4, 0x0f0f0f0f, 4);
919: MERGE (b1, b5, 0x0f0f0f0f, 4);
920: MERGE (b2, b6, 0x0f0f0f0f, 4);
921: MERGE (b3, b7, 0x0f0f0f0f, 4);
922:
923: MERGE (b0, b1, 0x00ff00ff, 8);
924: MERGE (b2, b3, 0x00ff00ff, 8);
925: MERGE (b4, b5, 0x00ff00ff, 8);
926: MERGE (b6, b7, 0x00ff00ff, 8);
927:
928: MERGE (b0, b2, 0x0000ffff, 16);
929: do_put_mem_long (pixels, b0);
930: do_put_mem_long (pixels + 4, b2);
931: MERGE (b1, b3, 0x0000ffff, 16);
932: do_put_mem_long (pixels + 2, b1);
933: do_put_mem_long (pixels + 6, b3);
934: MERGE (b4, b6, 0x0000ffff, 16);
935: do_put_mem_long (pixels + 1, b4);
936: do_put_mem_long (pixels + 5, b6);
937: MERGE (b5, b7, 0x0000ffff, 16);
938: do_put_mem_long (pixels + 3, b5);
939: do_put_mem_long (pixels + 7, b7);
940: pixels += 8;
941: }
942: }
943:
944: /* See above for comments on inlining. These functions should _not_
945: be inlined themselves. */
1.1.1.17 root 946: static void NOINLINE pfield_doline_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 1); }
947: static void NOINLINE pfield_doline_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 2); }
948: static void NOINLINE pfield_doline_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 3); }
949: static void NOINLINE pfield_doline_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 4); }
950: static void NOINLINE pfield_doline_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 5); }
951: static void NOINLINE pfield_doline_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 6); }
952: static void NOINLINE pfield_doline_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 7); }
953: static void NOINLINE pfield_doline_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 8); }
1.1.1.8 root 954:
955: static void pfield_doline (int lineno)
956: {
1.1.1.11 root 957: int wordcount = dp_for_drawing->plflinelen;
1.1.1.12 root 958: uae_u32 *data = pixdata.apixels_l + MAX_PIXELS_PER_LINE/4;
1.1 root 959:
960: #ifdef SMART_UPDATE
1.1.1.8 root 961: #define DATA_POINTER(n) (line_data[lineno] + (n)*MAX_WORDS_PER_LINE*2)
962: real_bplpt[0] = DATA_POINTER (0);
963: real_bplpt[1] = DATA_POINTER (1);
964: real_bplpt[2] = DATA_POINTER (2);
965: real_bplpt[3] = DATA_POINTER (3);
966: real_bplpt[4] = DATA_POINTER (4);
967: real_bplpt[5] = DATA_POINTER (5);
968: real_bplpt[6] = DATA_POINTER (6);
969: real_bplpt[7] = DATA_POINTER (7);
970: #endif
971:
1.1.1.11 root 972: switch (bplplanecnt) {
973: default: break;
974: case 0: memset (data, 0, wordcount * 32); break;
975: case 1: pfield_doline_n1 (data, wordcount); break;
976: case 2: pfield_doline_n2 (data, wordcount); break;
977: case 3: pfield_doline_n3 (data, wordcount); break;
978: case 4: pfield_doline_n4 (data, wordcount); break;
979: case 5: pfield_doline_n5 (data, wordcount); break;
980: case 6: pfield_doline_n6 (data, wordcount); break;
981: case 7: pfield_doline_n7 (data, wordcount); break;
982: case 8: pfield_doline_n8 (data, wordcount); break;
1.1 root 983: }
984: }
985:
986: void init_row_map (void)
987: {
988: int i;
989: if (gfxvidinfo.height > 2048) {
990: write_log ("Resolution too high, aborting\n");
991: abort ();
992: }
993: for (i = 0; i < gfxvidinfo.height + 1; i++)
994: row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
995: }
996:
997: static void init_aspect_maps (void)
998: {
999: int i, maxl;
1000: double native_lines_per_amiga_line;
1001:
1002: if (native2amiga_line_map)
1003: free (native2amiga_line_map);
1004: if (amiga2aspect_line_map)
1005: free (amiga2aspect_line_map);
1006:
1007: /* At least for this array the +1 is necessary. */
1.1.1.5 root 1008: amiga2aspect_line_map = (int *)malloc (sizeof (int) * (MAXVPOS + 1)*2 + 1);
1.1 root 1009: native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
1010:
1.1.1.19! root 1011: if (curr_gfx->correct_aspect)
1.1 root 1012: native_lines_per_amiga_line = ((double)gfxvidinfo.height
1.1.1.19! root 1013: * (curr_gfx->lores ? 320 : 640)
! 1014: / (curr_gfx->linedbl ? 512 : 256)
1.1 root 1015: / gfxvidinfo.width);
1016: else
1017: native_lines_per_amiga_line = 1;
1018:
1.1.1.19! root 1019: maxl = (MAXVPOS + 1) * (curr_gfx->linedbl ? 2 : 1);
! 1020: min_ypos_for_screen = minfirstline << (curr_gfx->linedbl ? 1 : 0);
1.1 root 1021: max_drawn_amiga_line = -1;
1022: for (i = 0; i < maxl; i++) {
1.1.1.9 root 1023: int v = (int) ((i - min_ypos_for_screen) * native_lines_per_amiga_line);
1.1 root 1024: if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
1025: max_drawn_amiga_line = i - min_ypos_for_screen;
1026: if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
1027: v = -1;
1028: amiga2aspect_line_map[i] = v;
1029: }
1.1.1.19! root 1030: if (curr_gfx->linedbl)
1.1 root 1031: max_drawn_amiga_line >>= 1;
1032:
1.1.1.19! root 1033: if (curr_gfx->ycenter && !(curr_gfx->correct_aspect)) {
1.1.1.5 root 1034: /* @@@ verify maxvpos vs. MAXVPOS */
1.1.1.19! root 1035: extra_y_adjust = (gfxvidinfo.height - (maxvpos << (curr_gfx->linedbl ? 1 : 0))) >> 1;
1.1 root 1036: if (extra_y_adjust < 0)
1037: extra_y_adjust = 0;
1038: }
1039:
1040: for (i = 0; i < gfxvidinfo.height; i++)
1041: native2amiga_line_map[i] = -1;
1042:
1043: if (native_lines_per_amiga_line < 1) {
1044: /* Must omit drawing some lines. */
1045: for (i = maxl - 1; i > min_ypos_for_screen; i--) {
1046: if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
1.1.1.19! root 1047: if (curr_gfx->linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
1.1 root 1048: /* If only the first line of a line pair would be omitted,
1049: * omit the second one instead to avoid problems with line
1050: * doubling. */
1051: amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
1052: amiga2aspect_line_map[i+1] = -1;
1053: } else
1054: amiga2aspect_line_map[i] = -1;
1055: }
1056: }
1057: }
1058:
1059: for (i = maxl-1; i >= min_ypos_for_screen; i--) {
1060: int j;
1061: if (amiga2aspect_line_map[i] == -1)
1062: continue;
1063: for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
1.1.1.19! root 1064: native2amiga_line_map[j] = i >> (curr_gfx->linedbl ? 1 : 0);
1.1 root 1065: }
1066: }
1067:
1068: /*
1069: * A raster line has been built in the graphics buffer. Tell the graphics code
1070: * to do anything necessary to display it.
1071: */
1072: static void do_flush_line_1 (int lineno)
1073: {
1074: if (lineno < first_drawn_line)
1075: first_drawn_line = lineno;
1076: if (lineno > last_drawn_line)
1077: last_drawn_line = lineno;
1078:
1079: if (gfxvidinfo.maxblocklines == 0)
1.1.1.11 root 1080: flush_line (lineno);
1.1 root 1081: else {
1082: if ((last_block_line+1) != lineno) {
1083: if (first_block_line != -2)
1084: flush_block (first_block_line, last_block_line);
1085: first_block_line = lineno;
1086: }
1087: last_block_line = lineno;
1088: if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
1089: flush_block (first_block_line, last_block_line);
1090: first_block_line = last_block_line = -2;
1091: }
1092: }
1093: }
1094:
1.1.1.6 root 1095: STATIC_INLINE void do_flush_line (int lineno)
1.1 root 1096: {
1097: do_flush_line_1 (lineno);
1098: }
1099:
1100: /*
1101: * One drawing frame has been finished. Tell the graphics code about it.
1102: * Note that the actual flush_screen() call is a no-op for all reasonable
1103: * systems.
1104: */
1105:
1.1.1.6 root 1106: STATIC_INLINE void do_flush_screen (int start, int stop)
1.1 root 1107: {
1.1.1.6 root 1108: /* TODO: this flush operation is executed outside locked state!
1109: Should be corrected.
1110: (sjo 26.9.99) */
1111:
1.1 root 1112: if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
1113: flush_block (first_block_line, last_block_line);
1114: }
1.1.1.15 root 1115: unlockscr ();
1.1 root 1116: if (start <= stop)
1117: flush_screen (start, stop);
1118: }
1119:
1120: static int drawing_color_matches;
1121: static enum { color_match_acolors, color_match_full } color_match_type;
1122:
1.1.1.8 root 1123: /* Set up colors_for_drawing to the state at the beginning of the currently drawn
1124: line. Try to avoid copying color tables around whenever possible. */
1.1.1.15 root 1125: static void adjust_drawing_colors (int ctable, int need_full)
1.1 root 1126: {
1127: if (drawing_color_matches != ctable) {
1.1.1.15 root 1128: if (need_full) {
1.1.1.9 root 1129: color_reg_cpy (&colors_for_drawing, curr_color_tables + ctable);
1.1 root 1130: color_match_type = color_match_full;
1131: } else {
1132: memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
1.1.1.18 root 1133: sizeof colors_for_drawing.acolors);
1.1 root 1134: color_match_type = color_match_acolors;
1135: }
1136: drawing_color_matches = ctable;
1.1.1.15 root 1137: } else if (need_full && color_match_type != color_match_full) {
1.1.1.9 root 1138: color_reg_cpy (&colors_for_drawing, &curr_color_tables[ctable]);
1.1 root 1139: color_match_type = color_match_full;
1140: }
1141: }
1142:
1.1.1.8 root 1143: STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_func worker_pfield)
1.1 root 1144: {
1.1.1.8 root 1145: int i;
1146: int lastpos = visible_left_border;
1.1.1.9 root 1147:
1.1.1.8 root 1148: for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) {
1149: int regno = curr_color_changes[i].regno;
1150: unsigned int value = curr_color_changes[i].value;
1151: int nextpos, nextpos_in_range;
1.1 root 1152: if (i == dip_for_drawing->last_color_change)
1153: nextpos = max_diwlastword;
1154: else
1.1.1.11 root 1155: nextpos = coord_hw_to_window_x (curr_color_changes[i].linepos * 2);
1.1.1.8 root 1156:
1157: nextpos_in_range = nextpos;
1158: if (nextpos > visible_right_border)
1159: nextpos_in_range = visible_right_border;
1160:
1161: if (nextpos_in_range > lastpos) {
1162: if (lastpos < playfield_start) {
1163: int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start;
1164: (*worker_border) (lastpos, t);
1165: lastpos = t;
1166: }
1167: }
1168: if (nextpos_in_range > lastpos) {
1169: if (lastpos >= playfield_start && lastpos < playfield_end) {
1170: int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
1171: (*worker_pfield) (lastpos, t);
1172: lastpos = t;
1173: }
1174: }
1175: if (nextpos_in_range > lastpos) {
1176: if (lastpos >= playfield_end)
1177: (*worker_border) (lastpos, nextpos_in_range);
1178: lastpos = nextpos_in_range;
1179: }
1.1 root 1180: if (i != dip_for_drawing->last_color_change) {
1.1.1.15 root 1181: if (regno == -1)
1182: bplham = value;
1183: else {
1184: color_reg_set (&colors_for_drawing, regno, value);
1185: colors_for_drawing.acolors[regno] = getxcolor (value);
1186: }
1.1 root 1187: }
1.1.1.8 root 1188: if (lastpos >= visible_right_border)
1.1.1.11 root 1189: break;
1190: }
1.1 root 1191: }
1192:
1193: /* We only save hardware registers during the hardware frame. Now, when
1194: * drawing the frame, we expand the data into a slightly more useful
1195: * form. */
1196: static void pfield_expand_dp_bplcon (void)
1197: {
1.1.1.11 root 1198: int plf1pri, plf2pri;
1199: bplres = dp_for_drawing->bplres;
1200: bplplanecnt = dp_for_drawing->nr_planes;
1.1.1.15 root 1201: bplham = dp_for_drawing->ham_at_start;
1202:
1.1.1.9 root 1203: if (currprefs.chipset_mask & CSMASK_AGA) {
1204: /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
1205: * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
1206: bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
1207: } else {
1208: bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
1209: }
1.1.1.11 root 1210: plf1pri = dp_for_drawing->bplcon2 & 7;
1211: plf2pri = (dp_for_drawing->bplcon2 >> 3) & 7;
1212: plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri);
1213: plf_sprite_mask |= (0xFFFF << (4 * plf1pri)) & 0xFFFF;
1.1 root 1214: bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
1215: bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
1.1.1.12 root 1216: bpldualpf2of = (dp_for_drawing->bplcon3 >> 10) & 7;
1217: sbasecol[0] = ((dp_for_drawing->bplcon4 >> 4) & 15) << 4;
1218: sbasecol[1] = ((dp_for_drawing->bplcon4 >> 0) & 15) << 4;
1.1 root 1219: }
1220:
1221: enum double_how {
1222: dh_buf,
1223: dh_line,
1224: dh_emerg
1225: };
1226:
1.1.1.6 root 1227: STATIC_INLINE void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos)
1.1 root 1228: {
1.1.1.8 root 1229: static int warned = 0;
1.1 root 1230: int border = 0;
1231: int do_double = 0;
1232: enum double_how dh;
1233:
1.1.1.2 root 1234: dp_for_drawing = line_decisions + lineno;
1235: dip_for_drawing = curr_drawinfo + lineno;
1.1 root 1236: switch (linestate[lineno]) {
1.1.1.8 root 1237: case LINE_REMEMBERED_AS_PREVIOUS:
1238: if (!warned)
1239: write_log ("Shouldn't get here... this is a bug.\n"), warned++;
1.1 root 1240: return;
1241:
1.1.1.8 root 1242: case LINE_BLACK:
1.1.1.2 root 1243: linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
1244: border = 2;
1.1 root 1245: break;
1246:
1.1.1.8 root 1247: case LINE_REMEMBERED_AS_BLACK:
1.1.1.2 root 1248: return;
1249:
1.1.1.8 root 1250: case LINE_AS_PREVIOUS:
1.1.1.2 root 1251: dp_for_drawing--;
1252: dip_for_drawing--;
1.1.1.11 root 1253: if (dp_for_drawing->plfleft == -1)
1.1.1.2 root 1254: border = 1;
1255: linestate[lineno] = LINE_DONE_AS_PREVIOUS;
1.1 root 1256: break;
1257:
1.1.1.8 root 1258: case LINE_DONE_AS_PREVIOUS:
1.1 root 1259: /* fall through */
1.1.1.8 root 1260: case LINE_DONE:
1.1 root 1261: return;
1262:
1.1.1.8 root 1263: case LINE_DECIDED_DOUBLE:
1.1 root 1264: if (follow_ypos != -1) {
1265: do_double = 1;
1266: linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
1.1.1.2 root 1267: linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
1.1 root 1268: }
1269:
1270: /* fall through */
1.1.1.8 root 1271: default:
1.1.1.11 root 1272: if (dp_for_drawing->plfleft == -1)
1.1 root 1273: border = 1;
1274: linestate[lineno] = LINE_DONE;
1.1.1.2 root 1275: break;
1.1 root 1276: }
1277:
1278: dh = dh_line;
1279: xlinebuffer = gfxvidinfo.linemem;
1.1.1.10 root 1280: if (xlinebuffer == 0 && do_double
1281: && (border == 0 || (border != 1 && dip_for_drawing->nr_color_changes > 0)))
1.1 root 1282: xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg;
1283: if (xlinebuffer == 0)
1284: xlinebuffer = row_map[gfx_ypos], dh = dh_buf;
1285: xlinebuffer -= linetoscr_x_adjust_bytes;
1286:
1.1.1.11 root 1287: if (border == 0) {
1.1 root 1288: pfield_expand_dp_bplcon ();
1289:
1.1.1.19! root 1290: if (bplres == RES_LORES && ! curr_gfx->lores)
! 1291: curr_gfx->lores = 2;
1.1.1.8 root 1292:
1.1.1.13 root 1293: pfield_init_linetoscr ();
1.1.1.11 root 1294: pfield_doline (lineno);
1.1 root 1295:
1.1.1.15 root 1296: adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb);
1.1 root 1297:
1.1.1.9 root 1298: /* The problem is that we must call decode_ham() BEFORE we do the
1.1.1.8 root 1299: sprites. */
1.1.1.15 root 1300: if (! border && dp_for_drawing->ham_seen) {
1.1.1.8 root 1301: init_ham_decoding ();
1.1 root 1302: if (dip_for_drawing->nr_color_changes == 0) {
1303: /* The easy case: need to do HAM decoding only once for the
1304: * full line. */
1.1.1.9 root 1305: decode_ham (visible_left_border, visible_right_border);
1.1 root 1306: } else /* Argh. */ {
1.1.1.9 root 1307: do_color_changes (dummy_worker, decode_ham);
1.1.1.15 root 1308: adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb);
1.1 root 1309: }
1.1.1.15 root 1310: bplham = dp_for_drawing->ham_at_start;
1.1 root 1311: }
1312:
1.1.1.11 root 1313: {
1314: int i;
1.1.1.13 root 1315: for (i = 0; i < dip_for_drawing->nr_sprites; i++) {
1316: if (currprefs.chipset_mask & CSMASK_AGA)
1317: draw_sprites_aga (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i);
1.1.1.15 root 1318: else
1.1.1.13 root 1319: draw_sprites_ecs (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i);
1320: }
1.1.1.11 root 1321: }
1.1 root 1322:
1.1.1.8 root 1323: do_color_changes (pfield_do_fill_line, pfield_do_linetoscr);
1324: if (dh == dh_emerg)
1.1.1.14 root 1325: memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.width);
1.1 root 1326:
1.1.1.8 root 1327: do_flush_line (gfx_ypos);
1328: if (do_double) {
1329: if (dh == dh_emerg)
1.1.1.14 root 1330: memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.width);
1.1.1.8 root 1331: else if (dh == dh_buf)
1.1.1.14 root 1332: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.pixbytes * gfxvidinfo.width);
1.1.1.8 root 1333: do_flush_line (follow_ypos);
1.1 root 1334: }
1.1.1.19! root 1335: if (curr_gfx->lores == 2)
! 1336: curr_gfx->lores = 0;
1.1.1.2 root 1337: } else if (border == 1) {
1.1 root 1338: adjust_drawing_colors (dp_for_drawing->ctable, 0);
1339:
1340: if (dip_for_drawing->nr_color_changes == 0) {
1341: fill_line ();
1342: do_flush_line (gfx_ypos);
1343: #if 0
1344: if (dh == dh_emerg)
1345: abort ();
1346: #endif
1347: if (do_double) {
1348: if (dh == dh_buf) {
1349: xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
1350: fill_line ();
1351: }
1352: /* If dh == dh_line, do_flush_line will re-use the rendered line
1353: * from linemem. */
1354: do_flush_line (follow_ypos);
1355: }
1356: return;
1357: }
1358:
1.1.1.8 root 1359: playfield_start = visible_right_border;
1360: playfield_end = visible_right_border;
1361:
1362: do_color_changes (pfield_do_fill_line, pfield_do_fill_line);
1.1 root 1363:
1364: if (dh == dh_emerg)
1.1.1.14 root 1365: memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.width);
1.1 root 1366:
1367: do_flush_line (gfx_ypos);
1368: if (do_double) {
1369: if (dh == dh_emerg)
1.1.1.14 root 1370: memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.width);
1.1 root 1371: else if (dh == dh_buf)
1.1.1.14 root 1372: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.pixbytes * gfxvidinfo.width);
1.1 root 1373: /* If dh == dh_line, do_flush_line will re-use the rendered line
1374: * from linemem. */
1375: do_flush_line (follow_ypos);
1376: }
1.1.1.2 root 1377: } else {
1378: xcolnr tmp = colors_for_drawing.acolors[0];
1.1.1.9 root 1379: colors_for_drawing.acolors[0] = getxcolor (0);
1.1.1.2 root 1380: fill_line ();
1381: do_flush_line (gfx_ypos);
1382: colors_for_drawing.acolors[0] = tmp;
1.1 root 1383: }
1384: }
1385:
1386: static void center_image (void)
1387: {
1.1.1.17 root 1388: int prev_x_adjust = visible_left_border;
1389: int prev_y_adjust = thisframe_y_adjust;
1.1 root 1390:
1.1.1.19! root 1391: if (curr_gfx->xcenter) {
! 1392: if (max_diwstop - min_diwstart < gfxvidinfo.width && curr_gfx->xcenter == 2)
1.1 root 1393: /* Try to center. */
1.1.1.8 root 1394: visible_left_border = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
1.1 root 1395: else
1.1.1.8 root 1396: visible_left_border = max_diwstop - gfxvidinfo.width;
1.1 root 1397:
1398: /* Would the old value be good enough? If so, leave it as it is if we want to
1399: * be clever. */
1.1.1.19! root 1400: if (curr_gfx->xcenter == 2) {
1.1.1.8 root 1401: if (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart)
1402: visible_left_border = prev_x_adjust;
1.1 root 1403: }
1404: } else
1.1.1.8 root 1405: visible_left_border = max_diwlastword - gfxvidinfo.width;
1406: if (visible_left_border < 0)
1407: visible_left_border = 0;
1408:
1409: linetoscr_x_adjust_bytes = visible_left_border * gfxvidinfo.pixbytes;
1410:
1411: visible_right_border = visible_left_border + gfxvidinfo.width;
1412: if (visible_right_border > max_diwlastword)
1413: visible_right_border = max_diwlastword;
1.1 root 1414:
1415: thisframe_y_adjust = minfirstline;
1.1.1.19! root 1416: if (curr_gfx->ycenter && thisframe_first_drawn_line != -1) {
! 1417: if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && curr_gfx->ycenter == 2)
1.1 root 1418: thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
1419: else
1420: thisframe_y_adjust = thisframe_first_drawn_line;
1421: /* Would the old value be good enough? If so, leave it as it is if we want to
1422: * be clever. */
1.1.1.19! root 1423: if (curr_gfx->ycenter == 2) {
1.1 root 1424: if (thisframe_y_adjust != prev_y_adjust
1425: && prev_y_adjust <= thisframe_first_drawn_line
1426: && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
1427: thisframe_y_adjust = prev_y_adjust;
1428: }
1429: /* Make sure the value makes sense */
1430: if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
1431: thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
1432: if (thisframe_y_adjust < minfirstline)
1433: thisframe_y_adjust = minfirstline;
1434: }
1.1.1.19! root 1435: thisframe_y_adjust_real = thisframe_y_adjust << (curr_gfx->linedbl ? 1 : 0);
! 1436: max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (curr_gfx->linedbl ? 1 : 0);
1.1 root 1437:
1438: /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably
1439: * better. */
1.1.1.8 root 1440: if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust)
1.1.1.19! root 1441: frame_redraw_necessary |= interlace_seen && curr_gfx->linedbl ? 2 : 1;
1.1 root 1442:
1443: max_diwstop = 0;
1444: min_diwstart = 10000;
1445: }
1446:
1447: static void init_drawing_frame (void)
1448: {
1449: int i, maxline;
1450:
1451: init_hardware_for_drawing_frame ();
1452:
1453: if (thisframe_first_drawn_line == -1)
1454: thisframe_first_drawn_line = minfirstline;
1455: if (thisframe_first_drawn_line > thisframe_last_drawn_line)
1456: thisframe_last_drawn_line = thisframe_first_drawn_line;
1457:
1.1.1.19! root 1458: if (!curr_gfx)
! 1459: return;
! 1460:
! 1461: maxline = curr_gfx->linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
1.1 root 1462: #ifdef SMART_UPDATE
1.1.1.2 root 1463: for (i = 0; i < maxline; i++) {
1464: switch (linestate[i]) {
1465: case LINE_DONE_AS_PREVIOUS:
1466: linestate[i] = LINE_REMEMBERED_AS_PREVIOUS;
1467: break;
1468: case LINE_REMEMBERED_AS_BLACK:
1469: break;
1470: default:
1471: linestate[i] = LINE_UNDECIDED;
1472: break;
1473: }
1474: }
1.1 root 1475: #else
1476: memset (linestate, LINE_UNDECIDED, maxline);
1477: #endif
1478: last_drawn_line = 0;
1479: first_drawn_line = 32767;
1480:
1481: first_block_line = last_block_line = -2;
1482: if (currprefs.test_drawing_speed)
1483: frame_redraw_necessary = 1;
1484: else if (frame_redraw_necessary)
1485: frame_redraw_necessary--;
1486:
1487: center_image ();
1488:
1489: thisframe_first_drawn_line = -1;
1490: thisframe_last_drawn_line = -1;
1491:
1492: drawing_color_matches = -1;
1493: }
1494:
1.1.1.14 root 1495: /*
1496: * Some code to put status information on the screen.
1497: */
1498:
1499: #define TD_PADX 10
1500: #define TD_PADY 2
1501: #define TD_WIDTH 32
1502: #define TD_LED_WIDTH 24
1503: #define TD_LED_HEIGHT 4
1504:
1505: #define TD_RIGHT 1
1506: #define TD_BOTTOM 2
1507:
1508: static int td_pos = (TD_RIGHT|TD_BOTTOM);
1509:
1510: #define TD_NUM_WIDTH 7
1511: #define TD_NUM_HEIGHT 7
1512:
1513: #define TD_TOTAL_HEIGHT (TD_PADY * 2 + TD_NUM_HEIGHT)
1514:
1.1.1.17 root 1515: #define NUMBERS_NUM 14
1516:
1.1.1.14 root 1517: static char *numbers = { /* ugly */
1.1.1.17 root 1518: "+++++++--++++-+++++++++++++++++-++++++++++++++++++++++++++++++++++++++++++++-++++++-++++----++---+"
1519: "+xxxxx+--+xx+-+xxxxx++xxxxx++x+-+x++xxxxx++xxxxx++xxxxx++xxxxx++xxxxx++xxxx+-+x++x+-+xxx++-+xx+-+x"
1520: "+x+++x+--++x+-+++++x++++++x++x+++x++x++++++x++++++++++x++x+++x++x+++x++x++++-+x++x+-+x++x+--+x++x+"
1521: "+x+-+x+---+x+-+xxxxx++xxxxx++xxxxx++xxxxx++xxxxx+--++x+-+xxxxx++xxxxx++x+----+xxxx+-+x++x+----+x+-"
1522: "+x+++x+---+x+-+x++++++++++x++++++x++++++x++x+++x+--+x+--+x+++x++++++x++x++++-+x++x+-+x++x+---+x+x+"
1523: "+xxxxx+---+x+-+xxxxx++xxxxx+----+x++xxxxx++xxxxx+--+x+--+xxxxx++xxxxx++xxxx+-+x++x+-+xxx+---+x++xx"
1524: "+++++++---+++-++++++++++++++----+++++++++++++++++--+++--++++++++++++++++++++-++++++-++++----------"
1.1.1.14 root 1525: };
1526:
1527: STATIC_INLINE void putpixel (int x, xcolnr c8)
1528: {
1529: switch(gfxvidinfo.pixbytes)
1530: {
1531: case 1:
1532: xlinebuffer[x] = (uae_u8)c8;
1533: break;
1534: case 2:
1535: {
1536: uae_u16 *p = (uae_u16 *)xlinebuffer + x;
1.1.1.17 root 1537: *p = (uae_u16)c8;
1.1.1.14 root 1538: break;
1539: }
1540: case 3:
1541: /* no 24 bit yet */
1542: break;
1543: case 4:
1544: {
1545: uae_u32 *p = (uae_u32 *)xlinebuffer + x;
1546: *p = c8;
1547: break;
1548: }
1549: }
1550: }
1551:
1552: static void write_tdnumber (int x, int y, int num)
1553: {
1554: int j;
1555: uae_u8 *numptr;
1.1.1.18 root 1556:
1.1.1.17 root 1557: numptr = numbers + num * TD_NUM_WIDTH + NUMBERS_NUM * TD_NUM_WIDTH * y;
1.1.1.14 root 1558: for (j = 0; j < TD_NUM_WIDTH; j++) {
1.1.1.17 root 1559: if (*numptr == 'x')
1560: putpixel (x + j, xcolors[0xfff]);
1561: else if (*numptr == '+')
1562: putpixel (x + j, xcolors[0x000]);
1.1.1.14 root 1563: numptr++;
1564: }
1565: }
1566:
1567: static void draw_status_line (int line)
1568: {
1.1.1.17 root 1569: int x_start, y, j, led;
1570:
1.1.1.14 root 1571: if (td_pos & TD_RIGHT)
1.1.1.18 root 1572: x_start = gfxvidinfo.width - TD_PADX - 5 * TD_WIDTH;
1.1.1.14 root 1573: else
1.1.1.18 root 1574: x_start = TD_PADX;
1.1.1.14 root 1575:
1576: y = line - (gfxvidinfo.height - TD_TOTAL_HEIGHT);
1577: xlinebuffer = gfxvidinfo.linemem;
1578: if (xlinebuffer == 0)
1579: xlinebuffer = row_map[line];
1580:
1581: memset (xlinebuffer, 0, gfxvidinfo.width * gfxvidinfo.pixbytes);
1582:
1583: for (led = 0; led < 5; led++) {
1.1.1.17 root 1584: int side, pos, num1 = -1, num2 = -1, num3 = -1, num4 = -1, x, off_rgb, on_rgb, c, on = 0;
1.1.1.14 root 1585: if (led > 0) {
1.1.1.17 root 1586: int pled = led - 1;
1587: int track = gui_data.drive_track[pled];
1588: pos = 1 + pled;
1589: on_rgb = 0x0c0;
1590: off_rgb = 0x030;
1591: if (1 /*!gui_data.drive_disabled[pled]*/) {
1592: num1 = -1;
1593: num2 = track / 10;
1594: num3 = track % 10;
1.1.1.18 root 1595: on = gui_data.drive_motor[pled];
1596: if (gui_data.drive_writing[pled])
1.1.1.17 root 1597: on_rgb = 0xc00;
1598: }
1599: /*side = gui_data.drive_side;*/
1.1.1.14 root 1600: } else {
1.1.1.17 root 1601: pos = 0;
1.1.1.14 root 1602: on = gui_data.powerled;
1.1.1.17 root 1603: on_rgb = 0xc00;
1604: off_rgb = 0x300;
1.1.1.14 root 1605: }
1606: c = xcolors[on ? on_rgb : off_rgb];
1607:
1.1.1.17 root 1608: x = x_start + pos * TD_WIDTH;
1.1.1.18 root 1609: for (j = 0; j < TD_LED_WIDTH; j++)
1.1.1.14 root 1610: putpixel (x + j, c);
1611:
1612: if (y >= TD_PADY && y - TD_PADY < TD_NUM_HEIGHT) {
1.1.1.17 root 1613: if (num3 >= 0) {
1614: int tn = num1 > 0 ? 3 : 2;
1615: int offs = (TD_LED_WIDTH - tn * TD_NUM_WIDTH) / 2;
1616: if (num1 > 0) {
1617: write_tdnumber (x + offs, y - TD_PADY, num1);
1618: offs += TD_NUM_WIDTH;
1619: }
1.1.1.18 root 1620: write_tdnumber (x + offs, y - TD_PADY, num2);
1.1.1.17 root 1621: write_tdnumber (x + offs + TD_NUM_WIDTH, y - TD_PADY, num3);
1622: if (num4 > 0)
1623: write_tdnumber (x + offs + 2 * TD_NUM_WIDTH, y - TD_PADY, num4);
1.1.1.14 root 1624: }
1625: }
1626: }
1627: }
1628:
1.1 root 1629: void finish_drawing_frame (void)
1630: {
1631: int i;
1632:
1633: if (! lockscr ()) {
1634: notice_screen_contents_lost ();
1635: return;
1636: }
1.1.1.15 root 1637:
1638: #ifndef SMART_UPDATE
1639: /* @@@ This isn't exactly right yet. FIXME */
1640: if (!interlace_seen)
1641: do_flush_screen (first_drawn_line, last_drawn_line);
1642: else
1643: unlockscr ();
1644: return;
1645: #endif
1.1 root 1646: for (i = 0; i < max_ypos_thisframe; i++) {
1647: int where;
1.1.1.14 root 1648: int i1 = i + min_ypos_for_screen;
1.1 root 1649: int line = i + thisframe_y_adjust_real;
1650:
1651: if (linestate[line] == LINE_UNDECIDED)
1652: break;
1653:
1.1.1.14 root 1654: where = amiga2aspect_line_map[i1];
1.1.1.17 root 1655: if (where >= gfxvidinfo.height - (currprefs.leds_on_screen ? TD_TOTAL_HEIGHT : 0))
1.1 root 1656: break;
1657: if (where == -1)
1658: continue;
1659:
1.1.1.14 root 1660: pfield_draw_line (line, where, amiga2aspect_line_map[i1 + 1]);
1.1 root 1661: }
1.1.1.17 root 1662: if (currprefs.leds_on_screen) {
1663: for (i = 0; i < TD_TOTAL_HEIGHT; i++) {
1664: int line = gfxvidinfo.height - TD_TOTAL_HEIGHT + i;
1665: draw_status_line (line);
1666: do_flush_line (line);
1667: }
1.1.1.14 root 1668: }
1.1 root 1669: do_flush_screen (first_drawn_line, last_drawn_line);
1670: }
1671:
1672: void hardware_line_completed (int lineno)
1673: {
1674: #ifndef SMART_UPDATE
1675: {
1676: int i, where;
1677: /* l is the line that has been finished for drawing. */
1678: i = lineno - thisframe_y_adjust_real;
1679: if (i >= 0 && i < max_ypos_thisframe) {
1680: where = amiga2aspect_line_map[i+min_ypos_for_screen];
1681: if (where < gfxvidinfo.height && where != -1)
1682: pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1683: }
1684: }
1685: #endif
1686: }
1687:
1.1.1.6 root 1688: STATIC_INLINE void check_picasso (void)
1.1 root 1689: {
1690: #ifdef PICASSO96
1691: if (picasso_on && picasso_redraw_necessary)
1692: picasso_refresh ();
1693: picasso_redraw_necessary = 0;
1694:
1695: if (picasso_requested_on == picasso_on)
1696: return;
1697:
1698: picasso_on = picasso_requested_on;
1699:
1700: if (!picasso_on)
1.1.1.3 root 1701: clear_inhibit_frame (IHF_PICASSO);
1.1 root 1702: else
1.1.1.3 root 1703: set_inhibit_frame (IHF_PICASSO);
1.1 root 1704:
1705: gfx_set_picasso_state (picasso_on);
1706: picasso_enablescreen (picasso_requested_on);
1707:
1708: notice_screen_contents_lost ();
1709: notice_new_xcolors ();
1710: #endif
1711: }
1712:
1713: void vsync_handle_redraw (int long_frame, int lof_changed)
1714: {
1715: last_redraw_point++;
1716: if (lof_changed || ! interlace_seen || last_redraw_point >= 2 || long_frame) {
1717: last_redraw_point = 0;
1718: interlace_seen = 0;
1719:
1720: if (framecnt == 0)
1721: finish_drawing_frame ();
1722:
1723: /* At this point, we have finished both the hardware and the
1724: * drawing frame. Essentially, we are outside of all loops and
1725: * can do some things which would cause confusion if they were
1726: * done at other times.
1727: */
1728:
1.1.1.13 root 1729: if (savestate_state == STATE_DOSAVE) {
1730: custom_prepare_savestate ();
1731: savestate_state = STATE_SAVE;
1732: save_state (savestate_filename, "Description!");
1733: savestate_state = 0;
1734: } else if (savestate_state == STATE_DORESTORE) {
1735: savestate_state = STATE_RESTORE;
1.1.1.18 root 1736: uae_reset (0);
1.1.1.13 root 1737: }
1738:
1.1 root 1739: if (quit_program < 0) {
1740: quit_program = -quit_program;
1.1.1.3 root 1741: set_inhibit_frame (IHF_QUIT_PROGRAM);
1.1.1.11 root 1742: set_special (SPCFLAG_BRK);
1.1 root 1743: filesys_prepare_reset ();
1744: return;
1745: }
1746:
1747: count_frame ();
1748: check_picasso ();
1749:
1.1.1.2 root 1750: check_prefs_changed_audio ();
1.1 root 1751: check_prefs_changed_custom ();
1752: check_prefs_changed_cpu ();
1753: if (check_prefs_changed_gfx ()) {
1.1.1.19! root 1754: if (curr_gfx) {
! 1755: init_row_map ();
! 1756: init_aspect_maps ();
! 1757: }
1.1 root 1758: notice_screen_contents_lost ();
1759: notice_new_xcolors ();
1760: }
1761:
1762: if (inhibit_frame != 0)
1763: framecnt = 1;
1764:
1765: if (framecnt == 0)
1766: init_drawing_frame ();
1767: }
1768: }
1769:
1.1.1.2 root 1770: void hsync_record_line_state (int lineno, enum nln_how how, int changed)
1.1 root 1771: {
1.1.1.2 root 1772: char *state;
1.1 root 1773: if (framecnt != 0)
1774: return;
1.1.1.2 root 1775:
1776: state = linestate + lineno;
1777: changed += frame_redraw_necessary;
1778:
1.1 root 1779: switch (how) {
1780: case nln_normal:
1.1.1.2 root 1781: *state = changed ? LINE_DECIDED : LINE_DONE;
1.1 root 1782: break;
1783: case nln_doubled:
1.1.1.2 root 1784: *state = changed ? LINE_DECIDED_DOUBLE : LINE_DONE;
1785: changed += state[1] != LINE_REMEMBERED_AS_PREVIOUS;
1786: state[1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS;
1787: break;
1788: case nln_nblack:
1789: *state = changed ? LINE_DECIDED : LINE_DONE;
1790: if (state[1] != LINE_REMEMBERED_AS_BLACK)
1791: state[1] = LINE_BLACK;
1.1 root 1792: break;
1793: case nln_lower:
1.1.1.2 root 1794: if (state[-1] == LINE_UNDECIDED)
1795: state[-1] = LINE_BLACK;
1796: *state = changed ? LINE_DECIDED : LINE_DONE;
1.1 root 1797: break;
1798: case nln_upper:
1.1.1.2 root 1799: *state = changed ? LINE_DECIDED : LINE_DONE;
1800: if (state[1] == LINE_UNDECIDED
1801: || state[1] == LINE_REMEMBERED_AS_PREVIOUS
1802: || state[1] == LINE_AS_PREVIOUS)
1803: state[1] = LINE_BLACK;
1.1 root 1804: break;
1805: }
1806: }
1807:
1808: void notice_interlace_seen (void)
1809: {
1810: interlace_seen = 1;
1811: }
1812:
1813: void reset_drawing (void)
1814: {
1815: int i;
1816:
1817: inhibit_frame = 0;
1818: uae_sem_init (&gui_sem, 0, 1);
1819:
1820: max_diwstop = 0;
1821:
1.1.1.19! root 1822: if (!curr_gfx)
! 1823: return;
! 1824: lores_factor = curr_gfx->lores ? 1 : 2;
! 1825: lores_shift = curr_gfx->lores ? 0 : 1;
1.1 root 1826:
1827: /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */
1828: for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
1829: linestate[i] = LINE_UNDECIDED;
1830:
1831: xlinebuffer = gfxvidinfo.bufmem;
1832:
1833: init_aspect_maps ();
1834:
1835: if (line_drawn == 0)
1836: line_drawn = (char *)malloc (gfxvidinfo.height);
1837:
1838: init_row_map();
1839:
1840: last_redraw_point = 0;
1841:
1.1.1.11 root 1842: memset (spixels, 0, sizeof spixels);
1843: memset (&spixstate, 0, sizeof spixstate);
1844:
1.1 root 1845: init_drawing_frame ();
1846: }
1847:
1848: void drawing_init ()
1849: {
1850: native2amiga_line_map = 0;
1851: amiga2aspect_line_map = 0;
1852: line_drawn = 0;
1853:
1854: gen_pfield_tables();
1855: }
1856:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.