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