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