|
|
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
8: */
9:
1.1.1.8 root 10: /* There are a couple of concepts of "coordinates" in this file.
11: - DIW coordinates
12: - DDF coordinates (essentially cycles, resolution lower than lores by a factor of 2)
13: - Pixel coordinates
14: * in the Amiga's resolution as determined by BPLCON0 ("Amiga coordinates")
15: * in the window resolution as determined by the preferences ("window coordinates").
16: * in the window resolution, and with the origin being the topmost left corner of
17: the window ("native coordinates")
18: One note about window coordinates. The visible area depends on the width of the
19: window, and the centering code. The first visible horizontal window coordinate is
20: often _not_ 0, but the value of VISIBLE_LEFT_BORDER instead.
21:
22: One important thing to remember: DIW coordinates are in the lowest possible
23: resolution.
24:
25: To prevent extremely bad things (think pixels cut in half by window borders) from
26: happening, all ports should restrict window widths to be multiples of 16 pixels. */
27:
1.1 root 28: #include "sysconfig.h"
29: #include "sysdeps.h"
30:
31: #include <ctype.h>
32: #include <assert.h>
33:
34: #include "config.h"
35: #include "options.h"
36: #include "threaddep/penguin.h"
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"
46:
1.1.1.12! root 47: int lores_factor, lores_shift;
1.1 root 48:
1.1.1.8 root 49: /* The shift factor to apply when converting between Amiga coordinates and window
50: coordinates. Zero if the resolution is the same, positive if window coordinates
51: have a higher resolution (i.e. we're stretching the image), negative if window
52: coordinates have a lower resolution (i.e. we're shrinking the image). */
53: static int res_shift;
54:
1.1 root 55: static int interlace_seen = 0;
56:
1.1.1.11 root 57: /* Lookup tables for dual playfields. The dblpf_*1 versions are for the case
58: that playfield 1 has the priority, dbplpf_*2 are used if playfield 2 has
59: priority. If we need an array for non-dual playfield mode, it has no number. */
60: /* The dbplpf_ms? arrays contain a shift value. plf_spritemask is initialized
61: to contain two 16 bit words, with the appropriate mask if pf1 is in the
62: foreground being at bit offset 0, the one used if pf2 is in front being at
63: offset 16. */
1.1.1.12! root 64:
1.1.1.11 root 65: static int dblpf_ms1[256], dblpf_ms2[256], dblpf_ms[256];
66: static int dblpf_ind1[256], dblpf_ind2[256];
1.1.1.12! root 67:
! 68: static int dblpf_2nd1[256], dblpf_2nd2[256];
! 69: static int dblpf_ind1_aga[256], dblpf_ind2_aga[256];
! 70:
1.1 root 71:
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.12! 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.12! root 106: static uae_u32 ham_linebuf[MAX_PIXELS_PER_LINE];
! 107: static uae_u8 spriteagadpfpixels[MAX_PIXELS_PER_LINE]; /* 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. */
134: static int min_diwstart, max_diwstop, prev_x_adjust;
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;
139: static int thisframe_y_adjust, prev_y_adjust;
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.12! root 154: static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt, bplres, sprres;
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.9 root 304: #define AGA 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.9 root 309: #define AGA 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.9 root 314: #define AGA 0
315: #include "linetoscr.c"
316:
317: #define LNAME linetoscr_8_aga
318: #define SRC_INC 1
319: #define HDOUBLE 0
320: #define AGA 1
321: #include "linetoscr.c"
322: #define LNAME linetoscr_8_stretch1_aga
323: #define SRC_INC 1
324: #define HDOUBLE 1
325: #define AGA 1
326: #include "linetoscr.c"
327: #define LNAME linetoscr_8_shrink1_aga
328: #define SRC_INC 2
329: #define HDOUBLE 0
330: #define AGA 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.9 root 339: #define AGA 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.9 root 344: #define AGA 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.9 root 349: #define AGA 0
350: #include "linetoscr.c"
351:
352: #define LNAME linetoscr_16_aga
353: #define SRC_INC 1
354: #define HDOUBLE 0
355: #define AGA 1
356: #include "linetoscr.c"
357: #define LNAME linetoscr_16_stretch1_aga
358: #define SRC_INC 1
359: #define HDOUBLE 1
360: #define AGA 1
361: #include "linetoscr.c"
362: #define LNAME linetoscr_16_shrink1_aga
363: #define SRC_INC 2
364: #define HDOUBLE 0
365: #define AGA 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.9 root 374: #define AGA 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.9 root 379: #define AGA 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.9 root 384: #define AGA 0
385: #include "linetoscr.c"
386:
387: #define LNAME linetoscr_32_aga
388: #define SRC_INC 1
389: #define HDOUBLE 0
390: #define AGA 1
391: #include "linetoscr.c"
392: #define LNAME linetoscr_32_stretch1_aga
393: #define SRC_INC 1
394: #define HDOUBLE 1
395: #define AGA 1
396: #include "linetoscr.c"
397: #define LNAME linetoscr_32_shrink1_aga
398: #define SRC_INC 2
399: #define HDOUBLE 0
400: #define AGA 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)
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: }
502: else
503: abort ();
504:
505: } else {
506:
507: if (res_shift == 0)
508: switch (gfxvidinfo.pixbytes) {
509: case 1: src_pixel = linetoscr_8 (src_pixel, start, stop); break;
510: case 2: src_pixel = linetoscr_16 (src_pixel, start, stop); break;
511: case 4: src_pixel = linetoscr_32 (src_pixel, start, stop); break;
512: }
513: else if (res_shift == 1)
514: switch (gfxvidinfo.pixbytes) {
515: case 1: src_pixel = linetoscr_8_stretch1 (src_pixel, start, stop); break;
516: case 2: src_pixel = linetoscr_16_stretch1 (src_pixel, start, stop); break;
517: case 4: src_pixel = linetoscr_32_stretch1 (src_pixel, start, stop); break;
518: }
519: else if (res_shift == -1)
520: switch (gfxvidinfo.pixbytes) {
521: case 1: src_pixel = linetoscr_8_shrink1 (src_pixel, start, stop); break;
522: case 2: src_pixel = linetoscr_16_shrink1 (src_pixel, start, stop); break;
523: case 4: src_pixel = linetoscr_32_shrink1 (src_pixel, start, stop); break;
524: }
525: else
526: abort ();
527: }
1.1 root 528: }
529:
1.1.1.8 root 530: static void pfield_do_fill_line (int start, int stop)
1.1 root 531: {
1.1.1.8 root 532: switch (gfxvidinfo.pixbytes) {
533: case 1: fill_line_8 (xlinebuffer, start, stop); break;
534: case 2: fill_line_16 (xlinebuffer, start, stop); break;
535: case 4: fill_line_32 (xlinebuffer, start, stop); break;
1.1 root 536: }
537: }
538:
1.1.1.8 root 539: static void pfield_do_linetoscr_full (int double_line)
1.1 root 540: {
541: char *oldxlb = (char *)xlinebuffer;
1.1.1.8 root 542: int old_src_pixel = src_pixel;
543:
544: pfield_do_linetoscr (playfield_start, playfield_end);
1.1 root 545: xlinebuffer = oldxlb + linetoscr_double_offset;
1.1.1.8 root 546: src_pixel = old_src_pixel;
547: pfield_do_linetoscr (playfield_start, playfield_end);
1.1 root 548: }
1.1.1.8 root 549:
550: static void dummy_worker (int start, int stop)
1.1 root 551: {
552: }
553:
1.1.1.8 root 554: static unsigned int ham_lastcolor;
1.1.1.2 root 555:
1.1.1.8 root 556: static int ham_decode_pixel;
1.1 root 557:
1.1.1.8 root 558: /* Decode HAM in the invisible portion of the display (left of VISIBLE_LEFT_BORDER),
559: but don't draw anything in. This is done to prepare HAM_LASTCOLOR for later,
1.1.1.9 root 560: when decode_ham runs. */
1.1.1.8 root 561: static void init_ham_decoding (void)
1.1 root 562: {
1.1.1.8 root 563: int unpainted_amiga = res_shift_from_window (unpainted);
564: ham_decode_pixel = src_pixel;
1.1.1.9 root 565: ham_lastcolor = color_reg_get (&colors_for_drawing, 0);
566:
567: if (currprefs.chipset_mask & CSMASK_AGA) {
568: if (bplplanecnt == 8) { /* AGA mode HAM8 */
569: while (unpainted_amiga-- > 0) {
570: int pv = pixdata.apixels[ham_decode_pixel++];
571: switch (pv & 0x3) {
572: case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
573: case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
574: case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
575: case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
576: }
577: }
578: } else if(bplplanecnt == 6) { /* AGA mode HAM6 */
579: while (unpainted_amiga-- > 0) {
580: int pv = pixdata.apixels[ham_decode_pixel++];
581: switch (pv & 0x30) {
582: case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
583: case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
584: case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
585: case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
586: }
587: }
588: }
589: } else {
590: if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */
591: while (unpainted_amiga-- > 0) {
592: int pv = pixdata.apixels[ham_decode_pixel++];
593: switch (pv & 0x30) {
594: case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
595: case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
596: case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
597: case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
598: }
599: }
1.1 root 600: }
601: }
602: }
603:
1.1.1.9 root 604: static void decode_ham (int pix, int stoppos)
1.1 root 605: {
1.1.1.8 root 606: int todraw_amiga = res_shift_from_window (stoppos - pix);
1.1.1.9 root 607: if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8))
1.1.1.8 root 608: abort ();
1.1 root 609:
1.1.1.9 root 610: if (currprefs.chipset_mask & CSMASK_AGA) {
611: if (bplplanecnt == 8) { /* AGA mode HAM8 */
612: while (todraw_amiga-- > 0) {
613: int pv = pixdata.apixels[ham_decode_pixel];
614: switch (pv & 0x3) {
615: case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
616: case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
617: case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
618: case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
619: }
620: ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
621: }
622: } else if(bplplanecnt == 6) { /* AGA mode HAM6 */
623: while (todraw_amiga-- > 0) {
624: int pv = pixdata.apixels[ham_decode_pixel];
625: switch (pv & 0x30) {
626: case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
627: case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
628: case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
629: case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
630: }
631: ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
632: }
633: }
634: } else {
635: if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */
636: while (todraw_amiga-- > 0) {
637: int pv = pixdata.apixels[ham_decode_pixel];
638: switch (pv & 0x30) {
639: case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
640: case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
641: case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
642: case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
643: }
644: ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
645: }
1.1 root 646: }
647: }
648: }
649:
1.1.1.2 root 650: static void gen_pfield_tables (void)
1.1 root 651: {
652: int i;
653:
654: /* For now, the AGA stuff is broken in the dual playfield case. We encode
655: * sprites in dpf mode by ORing the pixel value with 0x80. To make dual
656: * playfield rendering easy, the lookup tables contain are made linear for
657: * values >= 128. That only works for OCS/ECS, though. */
658:
659: for (i = 0; i < 256; i++) {
660: int plane1 = (i & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
661: int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
1.1.1.11 root 662:
1.1.1.12! root 663: dblpf_2nd1[i] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1;
! 664: dblpf_2nd2[i] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2;
! 665: dblpf_ind1_aga[i] = plane1 == 0 ? plane2 : plane1;
! 666: dblpf_ind2_aga[i] = plane2 == 0 ? plane1 : plane2;
! 667:
1.1.1.11 root 668: dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0;
669: dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8;
670: dblpf_ms[i] = i == 0 ? 16 : 8;
1.1 root 671: if (plane2 > 0)
672: plane2 += 8;
673: dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
674: dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
675:
1.1.1.11 root 676: sprite_offs[i] = (i & 15) ? 0 : 2;
1.1 root 677:
678: clxtab[i] = ((((i & 3) && (i & 12)) << 9)
679: | (((i & 3) && (i & 48)) << 10)
680: | (((i & 3) && (i & 192)) << 11)
681: | (((i & 12) && (i & 48)) << 12)
682: | (((i & 12) && (i & 192)) << 13)
683: | (((i & 48) && (i & 192)) << 14));
684: }
685: }
686:
1.1.1.11 root 687: /* When looking at this function and the ones that inline it, bear in mind
688: what an optimizing compiler will do with this code. All callers of this
689: function only pass in constant arguments (except for E). This means
690: that many of the if statements will go away completely after inlining. */
691: STATIC_INLINE void draw_sprites_1 (struct sprite_entry *e, int ham, int dualpf, int shift, int has_attach)
692: {
693: int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms;
694: uae_u16 *buf = spixels + e->first_pixel;
695: uae_u8 *stbuf = spixstate.bytes + e->first_pixel;
696: int pos, last;
697:
698: buf -= e->pos;
699: stbuf -= e->pos;
700:
701: for (pos = e->pos; pos < e->max; pos++) {
702: int maskshift, plfmask;
703: unsigned int v = buf[pos];
704:
705: /* The value in the shift lookup table is _half_ the shift count we
706: need. This is because we can't shift 32 bits at once (undefined
707: behaviour in C). */
708: maskshift = shift_lookup[pixdata.apixels[(pos << shift) + pixels_offset]];
709: plfmask = (plf_sprite_mask >> maskshift) >> maskshift;
710: v &= ~plfmask;
711: if (v != 0) {
712: unsigned int vlo, vhi, col, col_off;
713: unsigned int v1 = v & 255;
714: /* OFFS determines the sprite pair with the highest priority that has
715: any bits set. E.g. if we have 0xFF00 in the buffer, we have sprite
716: pairs 01 and 23 cleared, and pairs 45 and 67 set, so OFFS will
717: have a value of 4.
718: 2 * OFFS is the bit number in V of the sprite pair, and it also
719: happens to be the color offset for that pair. */
720: int offs;
721: if (v1 == 0)
722: offs = 4 + sprite_offs[v >> 8];
723: else
724: offs = sprite_offs[v1];
725:
726: /* Shift highest priority sprite pair down to bit zero. */
727: v >>= offs * 2;
728: v &= 15;
729:
730: if (has_attach && (stbuf[pos] & (1 << offs))) {
731: col = v;
732: } else {
733: /* This sequence computes the correct color value. We have to select
734: either the lower-numbered or the higher-numbered sprite in the pair.
735: We have to select the high one if the low one has all bits zero.
736: If the lower-numbered sprite has any bits nonzero, (VLO - 1) is in
737: the range of 0..2, and with the mask and shift, VHI will be zero.
738: If the lower-numbered sprite is zero, (VLO - 1) is a mask of
739: 0xFFFFFFFF, and we select the bits of the higher numbered sprite
740: in VHI.
741: This is _probably_ more efficient than doing it with branches. */
742: vlo = v & 3;
743: vhi = (v & (vlo - 1)) >> 2;
744: col = vlo | vhi;
745: col += (offs * 2);
746: }
747: col += dualpf ? 128 + 16 : 16;
1.1 root 748: if (ham) {
1.1.1.9 root 749: col = color_reg_get (&colors_for_drawing, col);
1.1.1.11 root 750: ham_linebuf[(pos << shift) + pixels_offset] = col;
751: if (shift == 1) {
752: ham_linebuf[(pos << shift) + pixels_offset + 1] = col;
1.1 root 753: }
754: } else {
1.1.1.11 root 755: if (shift == 1)
756: pixdata.apixels_w[pos + (pixels_offset >> 1)] = col | (col << 8);
757: else
758: pixdata.apixels[(pos << shift) + pixels_offset] = col;
1.1 root 759: }
760: }
761: }
762: }
1.1.1.11 root 763:
764: /* See comments above. Do not touch if you don't know what's going on.
765: * (We do _not_ want the following to be inlined themselves). */
766: static void draw_sprites_normal_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 0); }
767: static void draw_sprites_normal_dp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 0); }
768: static void draw_sprites_ham_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 0); }
769: static void draw_sprites_normal_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 0); }
770: static void draw_sprites_normal_dp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 0); }
771: static void draw_sprites_ham_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 0); }
772: static void draw_sprites_normal_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 1); }
773: static void draw_sprites_normal_dp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 1); }
774: static void draw_sprites_ham_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 1); }
775: static void draw_sprites_normal_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 1); }
776: static void draw_sprites_normal_dp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 1); }
777: static void draw_sprites_ham_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 1); }
778:
779: STATIC_INLINE void draw_sprites (struct sprite_entry *e)
780: {
781: if (e->has_attached)
782: if (bplres == 1)
783: if (bplham)
784: draw_sprites_ham_sp_hi_at (e);
785: else
786: if (bpldualpf)
787: draw_sprites_normal_dp_hi_at (e);
788: else
789: draw_sprites_normal_sp_hi_at (e);
790: else
791: if (bplham)
792: draw_sprites_ham_sp_lo_at (e);
793: else
794: if (bpldualpf)
795: draw_sprites_normal_dp_lo_at (e);
796: else
797: draw_sprites_normal_sp_lo_at (e);
798: else
799: if (bplres == 1)
800: if (bplham)
801: draw_sprites_ham_sp_hi_nat (e);
802: else
803: if (bpldualpf)
804: draw_sprites_normal_dp_hi_nat (e);
805: else
806: draw_sprites_normal_sp_hi_nat (e);
807: else
808: if (bplham)
809: draw_sprites_ham_sp_lo_nat (e);
810: else
811: if (bpldualpf)
812: draw_sprites_normal_dp_lo_nat (e);
813: else
814: draw_sprites_normal_sp_lo_nat (e);
1.1 root 815: }
816:
1.1.1.8 root 817: #define MERGE(a,b,mask,shift) do {\
818: uae_u32 tmp = mask & (a ^ (b >> shift)); \
819: a ^= tmp; \
820: b ^= (tmp << shift); \
821: } while (0)
822:
1.1.1.11 root 823: #define GETLONG(P) (*(uae_u32 *)P)
824:
825: /* We use the compiler's inlining ability to ensure that PLANES is in effect a compile time
826: constant. That will cause some unnecessary code to be optimized away.
1.1.1.8 root 827: Don't touch this if you don't know what you are doing. */
1.1.1.11 root 828: STATIC_INLINE void pfield_doline_1 (uae_u32 *pixels, int wordcount, int planes)
1.1.1.8 root 829: {
830: while (wordcount-- > 0) {
831: uae_u32 b0, b1, b2, b3, b4, b5, b6, b7;
832:
833: b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0;
834: switch (planes) {
1.1.1.11 root 835: case 8: b0 = GETLONG ((uae_u32 *)real_bplpt[7]); real_bplpt[7] += 4;
836: case 7: b1 = GETLONG ((uae_u32 *)real_bplpt[6]); real_bplpt[6] += 4;
837: case 6: b2 = GETLONG ((uae_u32 *)real_bplpt[5]); real_bplpt[5] += 4;
838: case 5: b3 = GETLONG ((uae_u32 *)real_bplpt[4]); real_bplpt[4] += 4;
839: case 4: b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4;
840: case 3: b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
841: case 2: b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
842: case 1: b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
1.1.1.8 root 843: }
844:
845: MERGE (b0, b1, 0x55555555, 1);
846: MERGE (b2, b3, 0x55555555, 1);
847: MERGE (b4, b5, 0x55555555, 1);
848: MERGE (b6, b7, 0x55555555, 1);
849:
850: MERGE (b0, b2, 0x33333333, 2);
851: MERGE (b1, b3, 0x33333333, 2);
852: MERGE (b4, b6, 0x33333333, 2);
853: MERGE (b5, b7, 0x33333333, 2);
854:
855: MERGE (b0, b4, 0x0f0f0f0f, 4);
856: MERGE (b1, b5, 0x0f0f0f0f, 4);
857: MERGE (b2, b6, 0x0f0f0f0f, 4);
858: MERGE (b3, b7, 0x0f0f0f0f, 4);
859:
860: MERGE (b0, b1, 0x00ff00ff, 8);
861: MERGE (b2, b3, 0x00ff00ff, 8);
862: MERGE (b4, b5, 0x00ff00ff, 8);
863: MERGE (b6, b7, 0x00ff00ff, 8);
864:
865: MERGE (b0, b2, 0x0000ffff, 16);
866: do_put_mem_long (pixels, b0);
867: do_put_mem_long (pixels + 4, b2);
868: MERGE (b1, b3, 0x0000ffff, 16);
869: do_put_mem_long (pixels + 2, b1);
870: do_put_mem_long (pixels + 6, b3);
871: MERGE (b4, b6, 0x0000ffff, 16);
872: do_put_mem_long (pixels + 1, b4);
873: do_put_mem_long (pixels + 5, b6);
874: MERGE (b5, b7, 0x0000ffff, 16);
875: do_put_mem_long (pixels + 3, b5);
876: do_put_mem_long (pixels + 7, b7);
877: pixels += 8;
878: }
879: }
880:
881: /* See above for comments on inlining. These functions should _not_
882: be inlined themselves. */
1.1.1.11 root 883: static void pfield_doline_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 1); }
884: static void pfield_doline_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 2); }
885: static void pfield_doline_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 3); }
886: static void pfield_doline_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 4); }
887: static void pfield_doline_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 5); }
888: static void pfield_doline_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 6); }
889: static void pfield_doline_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 7); }
890: static void pfield_doline_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 8); }
1.1.1.8 root 891:
892: static void pfield_doline (int lineno)
893: {
1.1.1.11 root 894: int wordcount = dp_for_drawing->plflinelen;
1.1.1.12! root 895: uae_u32 *data = pixdata.apixels_l + MAX_PIXELS_PER_LINE/4;
1.1 root 896:
897: #ifdef SMART_UPDATE
1.1.1.8 root 898: #define DATA_POINTER(n) (line_data[lineno] + (n)*MAX_WORDS_PER_LINE*2)
899: real_bplpt[0] = DATA_POINTER (0);
900: real_bplpt[1] = DATA_POINTER (1);
901: real_bplpt[2] = DATA_POINTER (2);
902: real_bplpt[3] = DATA_POINTER (3);
903: real_bplpt[4] = DATA_POINTER (4);
904: real_bplpt[5] = DATA_POINTER (5);
905: real_bplpt[6] = DATA_POINTER (6);
906: real_bplpt[7] = DATA_POINTER (7);
907: #endif
908:
1.1.1.11 root 909: switch (bplplanecnt) {
910: default: break;
911: case 0: memset (data, 0, wordcount * 32); break;
912: case 1: pfield_doline_n1 (data, wordcount); break;
913: case 2: pfield_doline_n2 (data, wordcount); break;
914: case 3: pfield_doline_n3 (data, wordcount); break;
915: case 4: pfield_doline_n4 (data, wordcount); break;
916: case 5: pfield_doline_n5 (data, wordcount); break;
917: case 6: pfield_doline_n6 (data, wordcount); break;
918: case 7: pfield_doline_n7 (data, wordcount); break;
919: case 8: pfield_doline_n8 (data, wordcount); break;
1.1 root 920: }
921: }
922:
923: void init_row_map (void)
924: {
925: int i;
926: if (gfxvidinfo.height > 2048) {
927: write_log ("Resolution too high, aborting\n");
928: abort ();
929: }
930: for (i = 0; i < gfxvidinfo.height + 1; i++)
931: row_map[i] = gfxvidinfo.bufmem + gfxvidinfo.rowbytes * i;
932: }
933:
934: static void init_aspect_maps (void)
935: {
936: int i, maxl;
937: double native_lines_per_amiga_line;
938:
939: if (native2amiga_line_map)
940: free (native2amiga_line_map);
941: if (amiga2aspect_line_map)
942: free (amiga2aspect_line_map);
943:
944: /* At least for this array the +1 is necessary. */
1.1.1.5 root 945: amiga2aspect_line_map = (int *)malloc (sizeof (int) * (MAXVPOS + 1)*2 + 1);
1.1 root 946: native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height);
947:
948: if (currprefs.gfx_correct_aspect)
949: native_lines_per_amiga_line = ((double)gfxvidinfo.height
950: * (currprefs.gfx_lores ? 320 : 640)
951: / (currprefs.gfx_linedbl ? 512 : 256)
952: / gfxvidinfo.width);
953: else
954: native_lines_per_amiga_line = 1;
955:
1.1.1.5 root 956: maxl = (MAXVPOS + 1) * (currprefs.gfx_linedbl ? 2 : 1);
1.1 root 957: min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0);
958: max_drawn_amiga_line = -1;
959: for (i = 0; i < maxl; i++) {
1.1.1.9 root 960: int v = (int) ((i - min_ypos_for_screen) * native_lines_per_amiga_line);
1.1 root 961: if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1)
962: max_drawn_amiga_line = i - min_ypos_for_screen;
963: if (i < min_ypos_for_screen || v >= gfxvidinfo.height)
964: v = -1;
965: amiga2aspect_line_map[i] = v;
966: }
967: if (currprefs.gfx_linedbl)
968: max_drawn_amiga_line >>= 1;
969:
970: if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) {
1.1.1.5 root 971: /* @@@ verify maxvpos vs. MAXVPOS */
1.1 root 972: extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1;
973: if (extra_y_adjust < 0)
974: extra_y_adjust = 0;
975: }
976:
977: for (i = 0; i < gfxvidinfo.height; i++)
978: native2amiga_line_map[i] = -1;
979:
980: if (native_lines_per_amiga_line < 1) {
981: /* Must omit drawing some lines. */
982: for (i = maxl - 1; i > min_ypos_for_screen; i--) {
983: if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) {
984: if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) {
985: /* If only the first line of a line pair would be omitted,
986: * omit the second one instead to avoid problems with line
987: * doubling. */
988: amiga2aspect_line_map[i] = amiga2aspect_line_map[i+1];
989: amiga2aspect_line_map[i+1] = -1;
990: } else
991: amiga2aspect_line_map[i] = -1;
992: }
993: }
994: }
995:
996: for (i = maxl-1; i >= min_ypos_for_screen; i--) {
997: int j;
998: if (amiga2aspect_line_map[i] == -1)
999: continue;
1000: for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++)
1001: native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0);
1002: }
1003: }
1004:
1005: /*
1006: * A raster line has been built in the graphics buffer. Tell the graphics code
1007: * to do anything necessary to display it.
1008: */
1009: static void do_flush_line_1 (int lineno)
1010: {
1011: if (lineno < first_drawn_line)
1012: first_drawn_line = lineno;
1013: if (lineno > last_drawn_line)
1014: last_drawn_line = lineno;
1015:
1016: if (gfxvidinfo.maxblocklines == 0)
1.1.1.11 root 1017: flush_line (lineno);
1.1 root 1018: else {
1019: if ((last_block_line+1) != lineno) {
1020: if (first_block_line != -2)
1021: flush_block (first_block_line, last_block_line);
1022: first_block_line = lineno;
1023: }
1024: last_block_line = lineno;
1025: if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
1026: flush_block (first_block_line, last_block_line);
1027: first_block_line = last_block_line = -2;
1028: }
1029: }
1030: }
1031:
1.1.1.6 root 1032: STATIC_INLINE void do_flush_line (int lineno)
1.1 root 1033: {
1034: do_flush_line_1 (lineno);
1035: }
1036:
1037: /*
1038: * One drawing frame has been finished. Tell the graphics code about it.
1039: * Note that the actual flush_screen() call is a no-op for all reasonable
1040: * systems.
1041: */
1042:
1.1.1.6 root 1043: STATIC_INLINE void do_flush_screen (int start, int stop)
1.1 root 1044: {
1.1.1.6 root 1045: /* TODO: this flush operation is executed outside locked state!
1046: Should be corrected.
1047: (sjo 26.9.99) */
1048:
1.1 root 1049: if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) {
1050: flush_block (first_block_line, last_block_line);
1051: }
1052: if (start <= stop)
1053: flush_screen (start, stop);
1054: }
1055:
1056: static int drawing_color_matches;
1057: static enum { color_match_acolors, color_match_full } color_match_type;
1058:
1.1.1.8 root 1059: /* Set up colors_for_drawing to the state at the beginning of the currently drawn
1060: line. Try to avoid copying color tables around whenever possible. */
1.1 root 1061: static void adjust_drawing_colors (int ctable, int bplham)
1062: {
1063: if (drawing_color_matches != ctable) {
1064: if (bplham) {
1.1.1.9 root 1065: color_reg_cpy (&colors_for_drawing, curr_color_tables + ctable);
1.1 root 1066: color_match_type = color_match_full;
1067: } else {
1068: memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
1.1.1.9 root 1069: sizeof colors_for_drawing.acolors);
1.1 root 1070: color_match_type = color_match_acolors;
1071: }
1072: drawing_color_matches = ctable;
1073: } else if (bplham && color_match_type != color_match_full) {
1.1.1.9 root 1074: color_reg_cpy (&colors_for_drawing, &curr_color_tables[ctable]);
1.1 root 1075: color_match_type = color_match_full;
1076: }
1077: }
1078:
1.1.1.8 root 1079: STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_func worker_pfield)
1.1 root 1080: {
1.1.1.8 root 1081: int i;
1082: int lastpos = visible_left_border;
1.1.1.9 root 1083:
1.1.1.8 root 1084: for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) {
1085: int regno = curr_color_changes[i].regno;
1086: unsigned int value = curr_color_changes[i].value;
1087: int nextpos, nextpos_in_range;
1.1 root 1088: if (i == dip_for_drawing->last_color_change)
1089: nextpos = max_diwlastword;
1090: else
1.1.1.11 root 1091: nextpos = coord_hw_to_window_x (curr_color_changes[i].linepos * 2);
1.1.1.8 root 1092:
1093: nextpos_in_range = nextpos;
1094: if (nextpos > visible_right_border)
1095: nextpos_in_range = visible_right_border;
1096:
1097: if (nextpos_in_range > lastpos) {
1098: if (lastpos < playfield_start) {
1099: int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start;
1100: (*worker_border) (lastpos, t);
1101: lastpos = t;
1102: }
1103: }
1104: if (nextpos_in_range > lastpos) {
1105: if (lastpos >= playfield_start && lastpos < playfield_end) {
1106: int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
1107: (*worker_pfield) (lastpos, t);
1108: lastpos = t;
1109: }
1110: }
1111: if (nextpos_in_range > lastpos) {
1112: if (lastpos >= playfield_end)
1113: (*worker_border) (lastpos, nextpos_in_range);
1114: lastpos = nextpos_in_range;
1115: }
1.1 root 1116: if (i != dip_for_drawing->last_color_change) {
1.1.1.9 root 1117: color_reg_set (&colors_for_drawing, regno, value);
1118: colors_for_drawing.acolors[regno] = getxcolor (value);
1.1 root 1119: }
1.1.1.8 root 1120: if (lastpos >= visible_right_border)
1.1.1.11 root 1121: break;
1122: }
1.1 root 1123: }
1124:
1125: /* We only save hardware registers during the hardware frame. Now, when
1126: * drawing the frame, we expand the data into a slightly more useful
1127: * form. */
1128: static void pfield_expand_dp_bplcon (void)
1129: {
1.1.1.11 root 1130: int plf1pri, plf2pri;
1131: bplres = dp_for_drawing->bplres;
1132: bplplanecnt = dp_for_drawing->nr_planes;
1.1 root 1133: bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800;
1.1.1.9 root 1134: if (currprefs.chipset_mask & CSMASK_AGA) {
1135: /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock
1136: * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */
1137: bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200));
1138: } else {
1139: bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000;
1140: }
1.1.1.11 root 1141: plf1pri = dp_for_drawing->bplcon2 & 7;
1142: plf2pri = (dp_for_drawing->bplcon2 >> 3) & 7;
1143: plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri);
1144: plf_sprite_mask |= (0xFFFF << (4 * plf1pri)) & 0xFFFF;
1.1 root 1145: bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
1146: bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
1.1.1.12! root 1147: bpldualpf2of = (dp_for_drawing->bplcon3 >> 10) & 7;
! 1148: sbasecol[0] = ((dp_for_drawing->bplcon4 >> 4) & 15) << 4;
! 1149: sbasecol[1] = ((dp_for_drawing->bplcon4 >> 0) & 15) << 4;
1.1 root 1150: }
1151:
1152: enum double_how {
1153: dh_buf,
1154: dh_line,
1155: dh_emerg
1156: };
1157:
1.1.1.6 root 1158: STATIC_INLINE void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos)
1.1 root 1159: {
1.1.1.8 root 1160: static int warned = 0;
1.1 root 1161: int border = 0;
1162: int do_double = 0;
1163: enum double_how dh;
1164:
1.1.1.2 root 1165: dp_for_drawing = line_decisions + lineno;
1166: dip_for_drawing = curr_drawinfo + lineno;
1.1 root 1167: switch (linestate[lineno]) {
1.1.1.8 root 1168: case LINE_REMEMBERED_AS_PREVIOUS:
1169: if (!warned)
1170: write_log ("Shouldn't get here... this is a bug.\n"), warned++;
1.1 root 1171: return;
1172:
1.1.1.8 root 1173: case LINE_BLACK:
1.1.1.2 root 1174: linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
1175: border = 2;
1.1 root 1176: break;
1177:
1.1.1.8 root 1178: case LINE_REMEMBERED_AS_BLACK:
1.1.1.2 root 1179: return;
1180:
1.1.1.8 root 1181: case LINE_AS_PREVIOUS:
1.1.1.2 root 1182: dp_for_drawing--;
1183: dip_for_drawing--;
1.1.1.11 root 1184: if (dp_for_drawing->plfleft == -1)
1.1.1.2 root 1185: border = 1;
1186: linestate[lineno] = LINE_DONE_AS_PREVIOUS;
1.1 root 1187: break;
1188:
1.1.1.8 root 1189: case LINE_DONE_AS_PREVIOUS:
1.1 root 1190: /* fall through */
1.1.1.8 root 1191: case LINE_DONE:
1.1 root 1192: return;
1193:
1.1.1.8 root 1194: case LINE_DECIDED_DOUBLE:
1.1 root 1195: if (follow_ypos != -1) {
1196: do_double = 1;
1197: linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos);
1.1.1.2 root 1198: linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
1.1 root 1199: }
1200:
1201: /* fall through */
1.1.1.8 root 1202: default:
1.1.1.11 root 1203: if (dp_for_drawing->plfleft == -1)
1.1 root 1204: border = 1;
1205: linestate[lineno] = LINE_DONE;
1.1.1.2 root 1206: break;
1.1 root 1207: }
1208:
1209: dh = dh_line;
1210: xlinebuffer = gfxvidinfo.linemem;
1.1.1.10 root 1211: if (xlinebuffer == 0 && do_double
1212: && (border == 0 || (border != 1 && dip_for_drawing->nr_color_changes > 0)))
1.1 root 1213: xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg;
1214: if (xlinebuffer == 0)
1215: xlinebuffer = row_map[gfx_ypos], dh = dh_buf;
1216: xlinebuffer -= linetoscr_x_adjust_bytes;
1217:
1.1.1.11 root 1218: if (border == 0) {
1.1 root 1219: pfield_expand_dp_bplcon ();
1220:
1.1.1.8 root 1221: if (bplres == RES_LORES && !currprefs.gfx_lores)
1.1 root 1222: currprefs.gfx_lores = 2;
1223: pfield_init_linetoscr ();
1.1.1.8 root 1224:
1.1.1.11 root 1225: pfield_doline (lineno);
1.1 root 1226:
1227: adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
1228:
1.1.1.9 root 1229: /* The problem is that we must call decode_ham() BEFORE we do the
1.1.1.8 root 1230: sprites. */
1231: if (! border && bplham) {
1232: init_ham_decoding ();
1.1 root 1233: if (dip_for_drawing->nr_color_changes == 0) {
1234: /* The easy case: need to do HAM decoding only once for the
1235: * full line. */
1.1.1.9 root 1236: decode_ham (visible_left_border, visible_right_border);
1.1 root 1237: } else /* Argh. */ {
1.1.1.9 root 1238: do_color_changes (dummy_worker, decode_ham);
1.1 root 1239: adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb);
1240: }
1241: }
1242:
1.1.1.11 root 1243: {
1244: int i;
1245: for (i = 0; i < dip_for_drawing->nr_sprites; i++)
1246: draw_sprites (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i);
1247: }
1.1 root 1248:
1.1.1.8 root 1249: do_color_changes (pfield_do_fill_line, pfield_do_linetoscr);
1.1 root 1250:
1.1.1.8 root 1251: if (dh == dh_emerg)
1252: memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
1.1 root 1253:
1.1.1.8 root 1254: do_flush_line (gfx_ypos);
1255: if (do_double) {
1256: if (dh == dh_emerg)
1257: memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
1258: else if (dh == dh_buf)
1259: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
1260: do_flush_line (follow_ypos);
1.1 root 1261: }
1262: if (currprefs.gfx_lores == 2)
1263: currprefs.gfx_lores = 0;
1.1.1.2 root 1264: } else if (border == 1) {
1.1 root 1265: adjust_drawing_colors (dp_for_drawing->ctable, 0);
1266:
1267: if (dip_for_drawing->nr_color_changes == 0) {
1268: fill_line ();
1269: do_flush_line (gfx_ypos);
1270: #if 0
1271: if (dh == dh_emerg)
1272: abort ();
1273: #endif
1274: if (do_double) {
1275: if (dh == dh_buf) {
1276: xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
1277: fill_line ();
1278: }
1279: /* If dh == dh_line, do_flush_line will re-use the rendered line
1280: * from linemem. */
1281: do_flush_line (follow_ypos);
1282: }
1283: return;
1284: }
1285:
1.1.1.8 root 1286: playfield_start = visible_right_border;
1287: playfield_end = visible_right_border;
1288:
1289: do_color_changes (pfield_do_fill_line, pfield_do_fill_line);
1.1 root 1290:
1291: if (dh == dh_emerg)
1292: memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
1293:
1294: do_flush_line (gfx_ypos);
1295: if (do_double) {
1296: if (dh == dh_emerg)
1297: memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes);
1298: else if (dh == dh_buf)
1299: memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes);
1300: /* If dh == dh_line, do_flush_line will re-use the rendered line
1301: * from linemem. */
1302: do_flush_line (follow_ypos);
1303: }
1.1.1.2 root 1304: } else {
1305: xcolnr tmp = colors_for_drawing.acolors[0];
1.1.1.9 root 1306: colors_for_drawing.acolors[0] = getxcolor (0);
1.1.1.2 root 1307: fill_line ();
1308: do_flush_line (gfx_ypos);
1309: colors_for_drawing.acolors[0] = tmp;
1.1 root 1310: }
1311: }
1312:
1313: static void center_image (void)
1314: {
1.1.1.8 root 1315: prev_x_adjust = visible_left_border;
1.1 root 1316: prev_y_adjust = thisframe_y_adjust;
1317:
1318: if (currprefs.gfx_xcenter) {
1319: if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2)
1320: /* Try to center. */
1.1.1.8 root 1321: visible_left_border = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1;
1.1 root 1322: else
1.1.1.8 root 1323: visible_left_border = max_diwstop - gfxvidinfo.width;
1.1 root 1324:
1325: /* Would the old value be good enough? If so, leave it as it is if we want to
1326: * be clever. */
1327: if (currprefs.gfx_xcenter == 2) {
1.1.1.8 root 1328: if (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart)
1329: visible_left_border = prev_x_adjust;
1.1 root 1330: }
1331: } else
1.1.1.8 root 1332: visible_left_border = max_diwlastword - gfxvidinfo.width;
1333: if (visible_left_border < 0)
1334: visible_left_border = 0;
1335:
1336: linetoscr_x_adjust_bytes = visible_left_border * gfxvidinfo.pixbytes;
1337:
1338: visible_right_border = visible_left_border + gfxvidinfo.width;
1339: if (visible_right_border > max_diwlastword)
1340: visible_right_border = max_diwlastword;
1.1 root 1341:
1342: thisframe_y_adjust = minfirstline;
1343: if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) {
1344: if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
1345: thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
1346: else
1347: thisframe_y_adjust = thisframe_first_drawn_line;
1348: /* Would the old value be good enough? If so, leave it as it is if we want to
1349: * be clever. */
1350: if (currprefs.gfx_ycenter == 2) {
1351: if (thisframe_y_adjust != prev_y_adjust
1352: && prev_y_adjust <= thisframe_first_drawn_line
1353: && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line)
1354: thisframe_y_adjust = prev_y_adjust;
1355: }
1356: /* Make sure the value makes sense */
1357: if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos)
1358: thisframe_y_adjust = maxvpos - max_drawn_amiga_line;
1359: if (thisframe_y_adjust < minfirstline)
1360: thisframe_y_adjust = minfirstline;
1361: }
1362: thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0);
1363: max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0);
1364:
1365: /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably
1366: * better. */
1.1.1.8 root 1367: if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust)
1.1 root 1368: frame_redraw_necessary |= interlace_seen && currprefs.gfx_linedbl ? 2 : 1;
1369:
1370: max_diwstop = 0;
1371: min_diwstart = 10000;
1372: }
1373:
1374: static void init_drawing_frame (void)
1375: {
1376: int i, maxline;
1377:
1378: init_hardware_for_drawing_frame ();
1379:
1380: if (thisframe_first_drawn_line == -1)
1381: thisframe_first_drawn_line = minfirstline;
1382: if (thisframe_first_drawn_line > thisframe_last_drawn_line)
1383: thisframe_last_drawn_line = thisframe_first_drawn_line;
1384:
1385: maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1;
1386: #ifdef SMART_UPDATE
1.1.1.2 root 1387: for (i = 0; i < maxline; i++) {
1388: switch (linestate[i]) {
1389: case LINE_DONE_AS_PREVIOUS:
1390: linestate[i] = LINE_REMEMBERED_AS_PREVIOUS;
1391: break;
1392: case LINE_REMEMBERED_AS_BLACK:
1393: break;
1394: default:
1395: linestate[i] = LINE_UNDECIDED;
1396: break;
1397: }
1398: }
1.1 root 1399: #else
1400: memset (linestate, LINE_UNDECIDED, maxline);
1401: #endif
1402: last_drawn_line = 0;
1403: first_drawn_line = 32767;
1404:
1405: first_block_line = last_block_line = -2;
1406: if (currprefs.test_drawing_speed)
1407: frame_redraw_necessary = 1;
1408: else if (frame_redraw_necessary)
1409: frame_redraw_necessary--;
1410:
1411: center_image ();
1412:
1413: thisframe_first_drawn_line = -1;
1414: thisframe_last_drawn_line = -1;
1415:
1416: drawing_color_matches = -1;
1417: }
1418:
1419: void finish_drawing_frame (void)
1420: {
1421: int i;
1422:
1423: #ifndef SMART_UPDATE
1424: /* @@@ This isn't exactly right yet. FIXME */
1425: if (!interlace_seen) {
1426: do_flush_screen (first_drawn_line, last_drawn_line);
1427: return;
1428: }
1429: #endif
1430: if (! lockscr ()) {
1431: notice_screen_contents_lost ();
1432: return;
1433: }
1434: for (i = 0; i < max_ypos_thisframe; i++) {
1435: int where;
1436: int line = i + thisframe_y_adjust_real;
1437:
1438: if (linestate[line] == LINE_UNDECIDED)
1439: break;
1440:
1441: where = amiga2aspect_line_map[i+min_ypos_for_screen];
1442: if (where >= gfxvidinfo.height)
1443: break;
1444: if (where == -1)
1445: continue;
1446:
1447: pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1448: }
1449: unlockscr ();
1450: do_flush_screen (first_drawn_line, last_drawn_line);
1451: }
1452:
1453: void hardware_line_completed (int lineno)
1454: {
1455: #ifndef SMART_UPDATE
1456: {
1457: int i, where;
1458: /* l is the line that has been finished for drawing. */
1459: i = lineno - thisframe_y_adjust_real;
1460: if (i >= 0 && i < max_ypos_thisframe) {
1461: where = amiga2aspect_line_map[i+min_ypos_for_screen];
1462: if (where < gfxvidinfo.height && where != -1)
1463: pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
1464: }
1465: }
1466: #endif
1467: }
1468:
1.1.1.6 root 1469: STATIC_INLINE void check_picasso (void)
1.1 root 1470: {
1471: #ifdef PICASSO96
1472: if (picasso_on && picasso_redraw_necessary)
1473: picasso_refresh ();
1474: picasso_redraw_necessary = 0;
1475:
1476: if (picasso_requested_on == picasso_on)
1477: return;
1478:
1479: picasso_on = picasso_requested_on;
1480:
1481: if (!picasso_on)
1.1.1.3 root 1482: clear_inhibit_frame (IHF_PICASSO);
1.1 root 1483: else
1.1.1.3 root 1484: set_inhibit_frame (IHF_PICASSO);
1.1 root 1485:
1486: gfx_set_picasso_state (picasso_on);
1487: picasso_enablescreen (picasso_requested_on);
1488:
1489: notice_screen_contents_lost ();
1490: notice_new_xcolors ();
1491: #endif
1492: }
1493:
1494: void vsync_handle_redraw (int long_frame, int lof_changed)
1495: {
1496: last_redraw_point++;
1497: if (lof_changed || ! interlace_seen || last_redraw_point >= 2 || long_frame) {
1498: last_redraw_point = 0;
1499: interlace_seen = 0;
1500:
1501: if (framecnt == 0)
1502: finish_drawing_frame ();
1503:
1504: /* At this point, we have finished both the hardware and the
1505: * drawing frame. Essentially, we are outside of all loops and
1506: * can do some things which would cause confusion if they were
1507: * done at other times.
1508: */
1509:
1510: if (quit_program < 0) {
1511: quit_program = -quit_program;
1.1.1.3 root 1512: set_inhibit_frame (IHF_QUIT_PROGRAM);
1.1.1.11 root 1513: set_special (SPCFLAG_BRK);
1.1 root 1514: filesys_prepare_reset ();
1515: return;
1516: }
1517:
1518: count_frame ();
1519: check_picasso ();
1520:
1.1.1.2 root 1521: check_prefs_changed_audio ();
1.1 root 1522: check_prefs_changed_custom ();
1523: check_prefs_changed_cpu ();
1524: if (check_prefs_changed_gfx ()) {
1525: init_row_map ();
1526: init_aspect_maps ();
1527: notice_screen_contents_lost ();
1528: notice_new_xcolors ();
1529: }
1530:
1531: if (inhibit_frame != 0)
1532: framecnt = 1;
1533:
1534: if (framecnt == 0)
1535: init_drawing_frame ();
1536: }
1537: }
1538:
1.1.1.2 root 1539: void hsync_record_line_state (int lineno, enum nln_how how, int changed)
1.1 root 1540: {
1.1.1.2 root 1541: char *state;
1.1 root 1542: if (framecnt != 0)
1543: return;
1.1.1.2 root 1544:
1545: state = linestate + lineno;
1546: changed += frame_redraw_necessary;
1547:
1.1 root 1548: switch (how) {
1549: case nln_normal:
1.1.1.2 root 1550: *state = changed ? LINE_DECIDED : LINE_DONE;
1.1 root 1551: break;
1552: case nln_doubled:
1.1.1.2 root 1553: *state = changed ? LINE_DECIDED_DOUBLE : LINE_DONE;
1554: changed += state[1] != LINE_REMEMBERED_AS_PREVIOUS;
1555: state[1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS;
1556: break;
1557: case nln_nblack:
1558: *state = changed ? LINE_DECIDED : LINE_DONE;
1559: if (state[1] != LINE_REMEMBERED_AS_BLACK)
1560: state[1] = LINE_BLACK;
1.1 root 1561: break;
1562: case nln_lower:
1.1.1.2 root 1563: if (state[-1] == LINE_UNDECIDED)
1564: state[-1] = LINE_BLACK;
1565: *state = changed ? LINE_DECIDED : LINE_DONE;
1.1 root 1566: break;
1567: case nln_upper:
1.1.1.2 root 1568: *state = changed ? LINE_DECIDED : LINE_DONE;
1569: if (state[1] == LINE_UNDECIDED
1570: || state[1] == LINE_REMEMBERED_AS_PREVIOUS
1571: || state[1] == LINE_AS_PREVIOUS)
1572: state[1] = LINE_BLACK;
1.1 root 1573: break;
1574: }
1575: }
1576:
1577: void notice_interlace_seen (void)
1578: {
1579: interlace_seen = 1;
1580: }
1581:
1582: void reset_drawing (void)
1583: {
1584: int i;
1585:
1586: inhibit_frame = 0;
1587: uae_sem_init (&gui_sem, 0, 1);
1588:
1589: #ifdef PICASSO96
1590: InitPicasso96 ();
1591: picasso_on = 0;
1592: picasso_requested_on = 0;
1593: gfx_set_picasso_state (0);
1594: #endif
1595: max_diwstop = 0;
1596:
1597: lores_factor = currprefs.gfx_lores ? 1 : 2;
1598: lores_shift = currprefs.gfx_lores ? 0 : 1;
1599:
1600: /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */
1601: for (i = 0; i < sizeof linestate / sizeof *linestate; i++)
1602: linestate[i] = LINE_UNDECIDED;
1603:
1604: xlinebuffer = gfxvidinfo.bufmem;
1605:
1606: init_aspect_maps ();
1607:
1608: if (line_drawn == 0)
1609: line_drawn = (char *)malloc (gfxvidinfo.height);
1610:
1611: init_row_map();
1612:
1613: last_redraw_point = 0;
1614:
1.1.1.11 root 1615: memset (spixels, 0, sizeof spixels);
1616: memset (&spixstate, 0, sizeof spixstate);
1617:
1.1 root 1618: init_drawing_frame ();
1619: }
1620:
1621: void drawing_init ()
1622: {
1623: native2amiga_line_map = 0;
1624: amiga2aspect_line_map = 0;
1625: line_drawn = 0;
1626:
1627: gen_pfield_tables();
1628: }
1629:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.