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