--- uae/src/drawing.c 2018/04/24 16:46:14 1.1.1.4 +++ uae/src/drawing.c 2018/04/24 16:53:01 1.1.1.9 @@ -3,10 +3,28 @@ * * Screen drawing functions * - * Copyright 1995-1998 Bernd Schmidt + * Copyright 1995-2000 Bernd Schmidt * Copyright 1995 Alessandro Bissacco */ +/* There are a couple of concepts of "coordinates" in this file. + - DIW coordinates + - DDF coordinates (essentially cycles, resolution lower than lores by a factor of 2) + - Pixel coordinates + * in the Amiga's resolution as determined by BPLCON0 ("Amiga coordinates") + * in the window resolution as determined by the preferences ("window coordinates"). + * in the window resolution, and with the origin being the topmost left corner of + the window ("native coordinates") + One note about window coordinates. The visible area depends on the width of the + window, and the centering code. The first visible horizontal window coordinate is + often _not_ 0, but the value of VISIBLE_LEFT_BORDER instead. + + One important thing to remember: DIW coordinates are in the lowest possible + resolution. + + To prevent extremely bad things (think pixels cut in half by window borders) from + happening, all ports should restrict window widths to be multiples of 16 pixels. */ + #include "sysconfig.h" #include "sysdeps.h" @@ -26,13 +44,15 @@ #include "gui.h" #include "picasso96.h" #include "drawing.h" -#include "p2c.h" -#if defined X86_ASSEMBLY -#define LORES_HACK -#endif +int lores_factor, lores_shift, sprite_width, borderblank; +int fetchmode, fetchstart, fetchstart_shift, prefetch, fetchsize; -int lores_factor, lores_shift, sprite_width; +/* The shift factor to apply when converting between Amiga coordinates and window + coordinates. Zero if the resolution is the same, positive if window coordinates + have a higher resolution (i.e. we're stretching the image), negative if window + coordinates have a lower resolution (i.e. we're shrinking the image). */ +static int res_shift; static int interlace_seen = 0; @@ -41,14 +61,6 @@ static int dblpf_aga1[256], dblpf_aga2[2 static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; -/* Big lookup tables for planar to chunky conversion. */ - -uae_u32 hirestab_h[256][2]; -uae_u32 lorestab_h[256][4]; - -uae_u32 hirestab_l[256][1]; -uae_u32 lorestab_l[256][2]; - static uae_u32 clxtab[256]; /* Video buffer description structure. Filled in by the graphics system @@ -56,24 +68,26 @@ static uae_u32 clxtab[256]; struct vidbuf_description gfxvidinfo; -/* The color lookup table. */ - +/* OCS/ECS color lookup table. */ xcolnr xcolors[4096]; +/* AGA mode color lookup tables */ +unsigned int xredcolors[256], xgreencolors[256], xbluecolors[256]; struct color_entry colors_for_drawing; -/* 880 isn't a magic number, it's a safe number with some padding at the end. - * This used to be 1000, but that's excessive. (840 is too low). I'm too lazy - * to figure out the exact space needed. */ +/* The size of these arrays is pretty arbitrary; it was chosen to be "more + than enough". The coordinates used for indexing into these arrays are + almost, but not quite, Amiga coordinates (there's a constant offset). */ union { /* Let's try to align this thing. */ double uupzuq; long int cruxmedo; - unsigned char apixels[880]; + uae_u8 apixels[1760]; + uae_u16 apixels_w[880]; + uae_u32 apixels_l[440]; } pixdata; -uae_u32 ham_linebuf[880]; -uae_u32 aga_linebuf[880], *aga_lbufptr; +uae_u32 ham_linebuf[1760]; char *xlinebuffer; @@ -81,7 +95,7 @@ static int *amiga2aspect_line_map, *nati static char *row_map[2049]; static int max_drawn_amiga_line; -/* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham6 */ +/* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham */ typedef void (*line_draw_func)(int, int); #define LINE_UNDECIDED 1 @@ -95,25 +109,32 @@ typedef void (*line_draw_func)(int, int) #define LINE_REMEMBERED_AS_PREVIOUS 9 static char *line_drawn; -static char linestate[(maxvpos + 1)*2 + 1]; +static char linestate[(MAXVPOS + 1)*2 + 1]; -uae_u8 line_data[(maxvpos+1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; +uae_u8 line_data[(MAXVPOS + 1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; -static int min_diwstart, max_diwstop, prev_x_adjust, linetoscr_x_adjust, linetoscr_right_x; +/* Centering variables. */ +static int min_diwstart, max_diwstop, prev_x_adjust; +/* The visible window: VISIBLE_LEFT_BORDER contains the left border of the visible + area, VISIBLE_RIGHT_BORDER the right border. These are in window coordinates. */ +static int visible_left_border, visible_right_border; static int linetoscr_x_adjust_bytes; static int thisframe_y_adjust, prev_y_adjust; static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen; static int extra_y_adjust; int thisframe_first_drawn_line, thisframe_last_drawn_line; +/* A frame counter that forces a redraw after at least one skipped frame in + interlace mode. */ static int last_redraw_point; static int first_drawn_line, last_drawn_line; static int first_block_line, last_block_line; /* These are generated by the drawing code from the line_decisions array for - * each line that needs to be drawn. */ -static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplhires; + each line that needs to be drawn. These are basically extracted out of + bit fields in the hardware registers. */ +static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplres; static int bpldelay1, bpldelay2; static int plfpri[3]; @@ -127,16 +148,16 @@ int framecnt = 0; static int frame_redraw_necessary; static int picasso_redraw_necessary; -static __inline__ void count_frame (void) +STATIC_INLINE void count_frame (void) { framecnt++; - if (framecnt >= currprefs.framerate) + if (framecnt >= currprefs.gfx_framerate) framecnt = 0; } int coord_native_to_amiga_x (int x) { - x += linetoscr_x_adjust; + x += visible_left_border; x <<= (1 - lores_shift); return x + 2*DISPLAY_LEFT_SHIFT; } @@ -146,6 +167,20 @@ int coord_native_to_amiga_y (int y) return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline; } +STATIC_INLINE int res_shift_from_window (int x) +{ + if (res_shift >= 0) + return x >> res_shift; + return x << -res_shift; +} + +STATIC_INLINE int res_shift_from_amiga (int x) +{ + if (res_shift >= 0) + return x >> res_shift; + return x << -res_shift; +} + void notice_screen_contents_lost (void) { picasso_redraw_necessary = 1; @@ -155,6 +190,7 @@ void notice_screen_contents_lost (void) static struct decision *dp_for_drawing; static struct draw_info *dip_for_drawing; +/* Record DIW of the current line for use by centering code. */ void record_diw_line (int first, int last) { if (last > max_diwstop) @@ -167,336 +203,226 @@ void record_diw_line (int first, int las * Screen update macros/functions */ -static unsigned int ham_lastcolor; - -static void init_ham_decoding(int first) -{ - int pix = dp_for_drawing->diwfirstword; - ham_lastcolor = colors_for_drawing.color_regs[0]; - while (pix < first) { - int pv = pixdata.apixels[pix]; - switch(pv & 0x30) { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break; - case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; - case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; - case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; - } - pix++; - } -} - -static void decode_ham6 (int pix, int stoppos) -{ - uae_u32 *buf = ham_linebuf; - - if (!bplham || bplplanecnt != 6) - return; - - if (stoppos > dp_for_drawing->diwlastword) - stoppos = dp_for_drawing->diwlastword; - if (pix < dp_for_drawing->diwfirstword) { - ham_lastcolor = colors_for_drawing.color_regs[0]; - pix = dp_for_drawing->diwfirstword; - } -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - pix <<= 1, stoppos <<= 1; -#endif - while (pix < stoppos) { - int pv = pixdata.apixels[pix]; - switch(pv & 0x30) { - case 0x00: ham_lastcolor = colors_for_drawing.color_regs[pv]; break; - case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; - case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; - case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; - } +/* The important positions in the line: where do we start drawing the left border, + where do we start drawing the playfield, where do we start drawing the right border. + All of these are forced into the visible window (VISIBLE_LEFT_BORDER .. VISIBLE_RIGHT_BORDER). + PLAYFIELD_START and PLAYFIELD_END are in window coordinates. */ +static int playfield_start, playfield_end; + +static int pixels_offset; +static int src_pixel; +/* How many pixels in window coordinates which are to the left of the left border. */ +static int unpainted; - buf[pix++] = ham_lastcolor; - } -} -#if 0 -static void decode_ham_aga (int pix, int stoppos) +/* Initialize the variables necessary for drawing a line. + * This involves setting up start/stop positions and display window + * borders. */ +static void pfield_init_linetoscr (void) { - static uae_u32 lastcolor; - uae_u32 *buf = ham_linebuf; + int delay_changes = dip_for_drawing->last_delay_change != dip_for_drawing->first_delay_change; + int mindelay = delay_changes ? 0 : bpldelay1 > bpldelay2 ? bpldelay2 : bpldelay1; + int maxdelay = delay_changes ? (16 << fetchmode) - 1 : bpldelay1 < bpldelay2 ? bpldelay2 : bpldelay1; + /* First, get data fetch start/stop in DIW coordinates. */ + int ddf_left = (dp_for_drawing->plfstrt + prefetch) * 2; + int ddf_right = (dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + prefetch) * 2; + /* Compute datafetch start/stop in pixels; native display coordinates. */ + int native_ddf_left = coord_hw_to_window_x (ddf_left + mindelay); + int native_ddf_right = coord_hw_to_window_x (ddf_right + maxdelay); - if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8)) - return; + int linetoscr_diw_start = dp_for_drawing->diwfirstword; + int linetoscr_diw_end = dp_for_drawing->diwlastword; - if (pix <= dp_for_drawing->diwfirstword) { - pix = dp_for_drawing->diwfirstword; - lastcolor = colors_for_drawing.color_regs[0]; - } - - if (dp_for_drawing->bplplanecnt == 6) { - /* HAM 6 */ - while (pix < dp_for_drawing->diwlastword && pix < stoppos) { - int pv = pixdata.apixels[pix]; - switch(pv & 0x30) { - case 0x00: lastcolor = colors_for_drawing.color_regs[pv]; break; - case 0x10: lastcolor &= 0xFFFF00; lastcolor |= (pv & 0xF)*0x11; break; - case 0x20: lastcolor &= 0x00FFFF; lastcolor |= (pv & 0xF)*0x11 << 16; break; - case 0x30: lastcolor &= 0xFF00FF; lastcolor |= (pv & 0xF)*0x11 << 8; break; - } - buf[pix++] = lastcolor; - } - } else if (dp_for_drawing->bplplanecnt == 8) { - /* HAM 8 */ - while (pix < dp_for_drawing->diwlastword && pix < stoppos) { - int pv = pixdata.apixels[pix]; - switch(pv & 0x3) { - case 0x0: lastcolor = colors_for_drawing.color_regs[pv >> 2]; break; - case 0x1: lastcolor &= 0xFFFF03; lastcolor |= (pv & 0xFC); break; - case 0x2: lastcolor &= 0x03FFFF; lastcolor |= (pv & 0xFC) << 16; break; - case 0x3: lastcolor &= 0xFF03FF; lastcolor |= (pv & 0xFC) << 8; break; - } - buf[pix++] = lastcolor; - } + if (dip_for_drawing->nr_sprites == 0) { + if (linetoscr_diw_start < native_ddf_left) + linetoscr_diw_start = native_ddf_left; + if (linetoscr_diw_end > native_ddf_right) + linetoscr_diw_end = native_ddf_right; } -} -#endif - -static int linetoscr_double_offset; - -#if AGA_CHIPSET != 0 -/* WARNING: Not too much of this will work correctly yet. */ -static void pfield_linetoscr_aga (int pix, int lframe_end, int diw_end, int stoppos) -{ - uae_u32 *buf = aga_lbufptr; - int i; - int xor = (uae_u8)(dp_for_drawing->bplcon4 >> 8); - int oldpix = pix; + /* Perverse cases happen. */ + if (linetoscr_diw_end < linetoscr_diw_start) + linetoscr_diw_end = linetoscr_diw_start; - buf -= pix; + playfield_start = linetoscr_diw_start; + playfield_end = linetoscr_diw_end; - for (i = 0; i < stoppos; i++) - pixdata.apixels[i] ^= xor; + if (playfield_start < visible_left_border) + playfield_start = visible_left_border; + if (playfield_start > visible_right_border) + playfield_start = visible_right_border; + if (playfield_end < visible_left_border) + playfield_end = visible_left_border; + if (playfield_end > visible_right_border) + playfield_end = visible_right_border; + + /* Now, compute some offsets. */ + + /* Convert ddf_left/ddf_right into Amiga coordinate system used by the + sprite drawing code. */ + ddf_left = ddf_left + mindelay - DISPLAY_LEFT_SHIFT; + if (currprefs.gfx_lores == 0) + ddf_left <<= 1; - while (pix < lframe_end) { - buf[pix++] = colors_for_drawing.color_regs[0]; - } - if (bplham) { - while (pix < diw_end) { - uae_u32 d = ham_linebuf[pix]; - buf[pix] = d; - pix++; - } - } else if (bpldualpf) { -#if 0 /* FIXME */ - /* Dual playfield */ - int *lookup = bpldualpfpri ? dblpf_aga2 : dblpf_aga1; - int *lookup_no = bpldualpfpri ? dblpf_2nd2 : dblpf_2nd1; - while (pix < diw_end) { - int pixcol = pixdata.apixels[pix]; - int pfno = lookup_no[pixcol]; + res_shift = lores_shift - bplres; + pixels_offset = 880 - ddf_left; + unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start; + src_pixel = 880 + res_shift_from_window (playfield_start - native_ddf_left + unpainted); - if (spixstate[pix]) { - buf[pix] = colors_for_drawing.color_regs[pixcol]; - } else { - int val = lookup[pixdata.apixels[pix]]; - if (pfno == 2) - val += dblpfofs[(dp_for_drawing->bplcon2 >> 10) & 7]; - buf[pix] = colors_for_drawing.color_regs[val]; - } - pix++; - } -#endif - } else if (bplehb) { - while (pix < diw_end) { - int pixcol = pixdata.apixels[pix]; - uae_u32 d = colors_for_drawing.color_regs[pixcol]; - /* What about sprites? */ - if (pixcol & 0x20) - d = (d & 0x777777) >> 1; - buf[pix] = d; - pix++; - } - } else { - while (pix < diw_end) { - int pixcol = pixdata.apixels[pix]; - buf[pix] = colors_for_drawing.color_regs[pixcol]; - pix++; - } - } - while (pix < stoppos) { - buf[pix++] = colors_for_drawing.color_regs[0]; - } - aga_lbufptr += pix - oldpix; -} + if (dip_for_drawing->nr_sprites == 0) + return; + /* Must clear parts of apixels. */ + if (linetoscr_diw_start < native_ddf_left) { + int size = res_shift_from_window (native_ddf_left - linetoscr_diw_start); + linetoscr_diw_start = native_ddf_left; + memset (pixdata.apixels + 880 - size, 0, size); + } + if (linetoscr_diw_end > native_ddf_right) { + int pos = res_shift_from_window (native_ddf_right - native_ddf_left); + int size = res_shift_from_window (linetoscr_diw_end - native_ddf_right); + linetoscr_diw_start = native_ddf_left; + memset (pixdata.apixels + 880 + pos, 0, size); + } +} + +/* If C++ compilers didn't suck, we'd use templates. */ + +#define TYPE uae_u8 +#define LNAME linetoscr_8 +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGA 0 +#include "linetoscr.c" +#define LNAME linetoscr_8_stretch1 +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGA 0 +#include "linetoscr.c" +#define LNAME linetoscr_8_shrink1 +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGA 0 +#include "linetoscr.c" + +#define LNAME linetoscr_8_aga +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGA 1 +#include "linetoscr.c" +#define LNAME linetoscr_8_stretch1_aga +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGA 1 +#include "linetoscr.c" +#define LNAME linetoscr_8_shrink1_aga +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGA 1 +#include "linetoscr.c" + +#undef TYPE + +#define TYPE uae_u16 +#define LNAME linetoscr_16 +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGA 0 +#include "linetoscr.c" +#define LNAME linetoscr_16_stretch1 +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGA 0 +#include "linetoscr.c" +#define LNAME linetoscr_16_shrink1 +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGA 0 +#include "linetoscr.c" + +#define LNAME linetoscr_16_aga +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGA 1 +#include "linetoscr.c" +#define LNAME linetoscr_16_stretch1_aga +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGA 1 +#include "linetoscr.c" +#define LNAME linetoscr_16_shrink1_aga +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGA 1 +#include "linetoscr.c" + +#undef TYPE + +#define TYPE uae_u32 +#define LNAME linetoscr_32 +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGA 0 +#include "linetoscr.c" +#define LNAME linetoscr_32_stretch1 +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGA 0 +#include "linetoscr.c" +#define LNAME linetoscr_32_shrink1 +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGA 0 +#include "linetoscr.c" + +#define LNAME linetoscr_32_aga +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGA 1 +#include "linetoscr.c" +#define LNAME linetoscr_32_stretch1_aga +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGA 1 +#include "linetoscr.c" +#define LNAME linetoscr_32_shrink1_aga +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGA 1 +#include "linetoscr.c" -static void aga_translate32 (int start, int stop) -{ - memcpy (((uae_u32 *)xlinebuffer) + start, aga_lbufptr, 4*(stop-start)); - aga_lbufptr += stop - start; -} +#undef TYPE -static void aga_translate16 (int start, int stop) +static void fill_line_8 (char *buf, int start, int stop) { + uae_u8 *b = (uae_u8 *)buf; int i; - for (i = start; i < stop; i++) { - uae_u32 d = aga_linebuf[i]; - uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12); - ((uae_u16 *)xlinebuffer)[i] = xcolors[v]; - } + xcolnr col = colors_for_drawing.acolors[0]; + for (i = start; i < stop; i++) + b[i] = col; } - -static void aga_translate8 (int start, int stop) +static void fill_line_16 (char *buf, int start, int stop) { + uae_u16 *b = (uae_u16 *)buf; int i; - for (i = start; i < stop; i++) { - uae_u32 d = aga_linebuf[i]; - uae_u16 v = ((d & 0xF0) >> 4) | ((d & 0xF000) >> 8) | ((d & 0xF00000) >> 12); - ((uae_u8 *)xlinebuffer)[i] = xcolors[v]; - } + xcolnr col = colors_for_drawing.acolors[0]; + for (i = start; i < stop; i++) + b[i] = col; } - -static void aga_fill_line_32 (char *buf, int start, int stop) +static void fill_line_32 (char *buf, int start, int stop) { + uae_u32 *b = (uae_u32 *)buf; int i; - for (i = start; i < stop; i++) { - ((uae_u32 *)buf)[i] = colors_for_drawing.color_regs[0]; - } -} - -static void fill_line (void) -{ - aga_fill_line_32 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); -} - -#else /* no AGA_CHIPSET */ - -#define LINE_TO_SCR(NAME, TYPE, DO_DOUBLE, CONVERT) \ -static void NAME(int pix, int lframe_end, int diw_end, int stoppos) \ -{ \ - TYPE *buf = ((TYPE *)xlinebuffer); \ -/* int oldpix = pix;*/ \ - /* These are different for register-allocation purposes. */ \ - TYPE d1, d2; \ - int offset; \ -\ - if (DO_DOUBLE) offset = linetoscr_double_offset / sizeof(TYPE); \ -\ - d1 = CONVERT(colors_for_drawing.acolors[0]); \ - while (pix < lframe_end) { \ - buf[pix] = d1; if (DO_DOUBLE) buf[pix+offset] = d1; \ - pix++; \ - } \ - if (bplham && bplplanecnt == 6) { \ - /* HAM 6 */ \ - while (pix < diw_end) { \ - TYPE d = CONVERT(xcolors[ham_linebuf[pix]]); \ - buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ - pix++; \ - } \ - } else if (bpldualpf) { \ - /* Dual playfield */ \ - int *lookup = bpldualpfpri ? dblpf_ind2 : dblpf_ind1; \ - while (pix < diw_end) { \ - int pixcol = pixdata.apixels[pix]; \ - TYPE d; \ - d = CONVERT(colors_for_drawing.acolors[lookup[pixcol]]); \ - buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ - pix++; \ - } \ - } else if (bplehb) { \ - while (pix < diw_end) { \ - int p = pixdata.apixels[pix]; \ - TYPE d = CONVERT (colors_for_drawing.acolors[p]); \ - if (p >= 32) d = CONVERT(xcolors[(colors_for_drawing.color_regs[p-32] >> 1) & 0x777]); \ - buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ - pix++; \ - } \ - } else { \ - while (pix < diw_end) { \ - TYPE d = CONVERT (colors_for_drawing.acolors[pixdata.apixels[pix]]); \ - buf[pix] = d; if (DO_DOUBLE) buf[pix+offset] = d; \ - pix++; \ - } \ - } \ - d2 = CONVERT (colors_for_drawing.acolors[0]); \ - while (pix < stoppos) { \ - buf[pix] = d2; if (DO_DOUBLE) buf[pix+offset] = d2; \ - pix++; \ - } \ -} - -#define FILL_LINE(NAME, TYPE, CONVERT) \ -static void NAME (char *buf, int start, int stop) \ -{ \ - TYPE *b = (TYPE *)buf; \ - int i;\ - xcolnr col = colors_for_drawing.acolors[0]; \ - for (i = start; i < stop; i++) \ - b[i] = CONVERT (col); \ -} - -LINE_TO_SCR(pfield_linetoscr_8, uae_u8, 0,) -LINE_TO_SCR(pfield_linetoscr_16, uae_u16, 0,) -LINE_TO_SCR(pfield_linetoscr_32, uae_u32, 0,) -LINE_TO_SCR(pfield_linetoscr_8_double_slow, uae_u8, 1,) -LINE_TO_SCR(pfield_linetoscr_16_double_slow, uae_u16, 1,) -LINE_TO_SCR(pfield_linetoscr_32_double_slow, uae_u32, 1,) - -FILL_LINE(fill_line_8, uae_u8,) -FILL_LINE(fill_line_16, uae_u16,) -FILL_LINE(fill_line_32, uae_u32,) - -#ifdef HAVE_UAE_U24 -LINE_TO_SCR(pfield_linetoscr_24, uae_u24, 0, uae24_convert) -LINE_TO_SCR(pfield_linetoscr_24_double_slow, uae_u24, 1, uae24_convert) -FILL_LINE(fill_line_24, uae_u24, uae24_convert) -#else -/* Dummy versions */ -static void pfield_linetoscr_24 (int pix, int lframe_end, int diw_end, int stoppos) -{ -} -static void pfield_linetoscr_24_double_slow (int pix, int lframe_end, int diw_end, int stoppos) -{ -} -static void fill_line_24 (char *buf, int start, int stop) -{ + xcolnr col = colors_for_drawing.acolors[0]; + for (i = start; i < stop; i++) + b[i] = col; } -#endif -static __inline__ void fill_line_full (void) -{ - switch (gfxvidinfo.pixbytes) { - case 1: fill_line_8 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; - case 2: fill_line_16 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; - case 3: fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; - case 4: fill_line_32 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); break; - } -} - -#define fill_line fill_line_full - -#define pfield_linetoscr_full8 pfield_linetoscr_8 -#define pfield_linetoscr_full16 pfield_linetoscr_16 -#define pfield_linetoscr_full24 pfield_linetoscr_24 -#define pfield_linetoscr_full32 pfield_linetoscr_32 - -#define pfield_linetoscr_full8_double pfield_linetoscr_8_double_slow -#define pfield_linetoscr_full16_double pfield_linetoscr_16_double_slow -#define pfield_linetoscr_full24_double pfield_linetoscr_24_double_slow -#define pfield_linetoscr_full32_double pfield_linetoscr_32_double_slow - -#if 1 -#undef fill_line -static __inline__ void fill_line (void) +STATIC_INLINE void fill_line (void) { int shift; int nints, nrem; int *start; xcolnr val; -#ifdef HAVE_UAE_U24 - if (gfxvidinfo.pixbytes == 3) { - fill_line_24 (xlinebuffer, linetoscr_x_adjust, linetoscr_x_adjust + gfxvidinfo.width); - return; - } -#endif - shift = 0; if (gfxvidinfo.pixbytes == 2) shift = 1; @@ -506,8 +432,10 @@ static __inline__ void fill_line (void) nints = gfxvidinfo.width >> (2-shift); nrem = nints & 7; nints &= ~7; - start = (int *)(((char *)xlinebuffer) + (linetoscr_x_adjust << shift)); + start = (int *)(((char *)xlinebuffer) + (visible_left_border << shift)); val = colors_for_drawing.acolors[0]; + if (gfxvidinfo.pixbytes == 2) + val |= val << 16; for (; nints > 0; nints -= 8, start += 8) { *start = val; *(start+1) = val; @@ -537,337 +465,180 @@ static __inline__ void fill_line (void) } } -#ifdef X86_ASSEMBLY - -#undef pfield_linetoscr_full8 -/* The types are lies, of course. */ -extern void pfield_linetoscr_normal_asm8 (void) __asm__("pfield_linetoscr_normal_asm8"); -extern void pfield_linetoscr_ehb_asm8 (void) __asm__("pfield_linetoscr_ehb_asm8"); -extern void pfield_linetoscr_ham6_asm8 (void) __asm__("pfield_linetoscr_ham6_asm8"); -extern void pfield_linetoscr_dualpf_asm8 (void) __asm__("pfield_linetoscr_dualpf_asm8"); -extern void pfield_linetoscr_hdouble_asm8 (void) __asm__("pfield_linetoscr_hdouble_asm8"); -extern void pfield_linetoscr_hdouble_dpf_asm8 (void) __asm__("pfield_linetoscr_hdouble_dpf_asm8"); -extern void pfield_linetoscr_hdouble_ehb_asm8 (void) __asm__("pfield_linetoscr_hdouble_ehb_asm8"); -extern void pfield_linetoscr_asm8 (void (*) (void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm8"); - -static void pfield_linetoscr_full8 (int pix, int lframe_end, int diw_end, int stoppos) -{ - int lframe_end_1, diw_end_1; - - lframe_end_1 = pix + ((lframe_end - pix) & ~3); - diw_end_1 = stoppos - ((stoppos - diw_end) & ~3); - - if (bplham && bplplanecnt == 6) { - pfield_linetoscr_asm8 (pfield_linetoscr_ham6_asm8, pix, lframe_end_1, diw_end_1, stoppos); - } else if (bpldualpf) { -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_dpf_asm8, pix, lframe_end_1, diw_end_1, stoppos, - bpldualpfpri ? dblpf_ind2 : dblpf_ind1); - else -#endif - pfield_linetoscr_asm8 (pfield_linetoscr_dualpf_asm8, pix, lframe_end_1, diw_end_1, stoppos, - bpldualpfpri ? dblpf_ind2 : dblpf_ind1); - } else if (bplehb) { -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos); - else -#endif - pfield_linetoscr_asm8 (pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos); - } else { -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_asm8, pix, lframe_end_1, diw_end_1, stoppos); - else -#endif - pfield_linetoscr_asm8 (pfield_linetoscr_normal_asm8, pix, lframe_end_1, diw_end_1, stoppos); - } - - /* The assembly functions work on aligned data, so we may have to do some - * additional work at the edges. */ - if (lframe_end != lframe_end_1) { - int i, c = colors_for_drawing.acolors[0]; - for (i = lframe_end_1; i < lframe_end; i++) - xlinebuffer[i] = c; - } - if (diw_end != diw_end_1) { - int i, c = colors_for_drawing.acolors[0]; - for (i = diw_end; i < diw_end_1; i++) - xlinebuffer[i] = c; - } -} - -#undef pfield_linetoscr_full16 -extern void pfield_linetoscr_normal_asm16 (void) __asm__("pfield_linetoscr_normal_asm16"); -extern void pfield_linetoscr_ehb_asm16 (void) __asm__("pfield_linetoscr_ehb_asm16"); -extern void pfield_linetoscr_ham6_asm16 (void) __asm__("pfield_linetoscr_ham6_asm16"); -extern void pfield_linetoscr_dualpf_asm16 (void) __asm__("pfield_linetoscr_dualpf_asm16"); -extern void pfield_linetoscr_hdouble_asm16 (void) __asm__("pfield_linetoscr_hdouble_asm16"); -extern void pfield_linetoscr_hdouble_dpf_asm16 (void) __asm__("pfield_linetoscr_hdouble_dpf_asm16"); -extern void pfield_linetoscr_hdouble_ehb_asm16 (void) __asm__("pfield_linetoscr_hdouble_ehb_asm16"); -extern void pfield_linetoscr_asm16 (void (*) (void), int, int, int, int, ...) __asm__("pfield_linetoscr_asm16"); +static int linetoscr_double_offset; -static void pfield_linetoscr_full16 (int pix, int lframe_end, int diw_end, int stoppos) +static void pfield_do_linetoscr (int start, int stop) { - int lframe_end_1, diw_end_1; - - lframe_end_1 = pix + ((lframe_end - pix) & ~3); - diw_end_1 = stoppos - ((stoppos - diw_end) & ~3); + if (currprefs.chipset_mask & CSMASK_AGA) { + if (res_shift == 0) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8_aga (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_aga (src_pixel, start, stop); break; + } + else if (res_shift == 1) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8_stretch1_aga (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16_stretch1_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch1_aga (src_pixel, start, stop); break; + } + else if (res_shift == -1) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8_shrink1_aga (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16_shrink1_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1_aga (src_pixel, start, stop); break; + } + else + abort (); - if (bplham && bplplanecnt == 6) { - pfield_linetoscr_asm16 (pfield_linetoscr_ham6_asm16, pix, lframe_end_1, diw_end_1, stoppos); - } else if (bpldualpf) { -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_dpf_asm16, pix, lframe_end_1, diw_end_1, stoppos, - bpldualpfpri ? dblpf_ind2 : dblpf_ind1); - else -#endif - pfield_linetoscr_asm16 (pfield_linetoscr_dualpf_asm16, pix, lframe_end_1, diw_end_1, stoppos, - bpldualpfpri ? dblpf_ind2 : dblpf_ind1); - } else if (bplehb) { -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos); - else -#endif - pfield_linetoscr_asm16 (pfield_linetoscr_ehb_asm16, pix, lframe_end_1, diw_end_1, stoppos); } else { -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - pfield_linetoscr_asm16 (pfield_linetoscr_hdouble_asm16, pix, lframe_end_1, diw_end_1, stoppos); + + if (res_shift == 0) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8 (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16 (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32 (src_pixel, start, stop); break; + } + else if (res_shift == 1) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8_stretch1 (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16_stretch1 (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch1 (src_pixel, start, stop); break; + } + else if (res_shift == -1) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8_shrink1 (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16_shrink1 (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1 (src_pixel, start, stop); break; + } else -#endif - pfield_linetoscr_asm16 (pfield_linetoscr_normal_asm16, pix, lframe_end_1, diw_end_1, stoppos); + abort (); } +} - /* The assembly functions work on aligned data, so we may have to do some - * additional work at the edges. */ - if (lframe_end != lframe_end_1) { - int i, c = colors_for_drawing.acolors[0]; - for (i = lframe_end_1; i < lframe_end; i++) - ((uae_u16 *)xlinebuffer)[i] = c; - } - if (diw_end != diw_end_1) { - int i, c = colors_for_drawing.acolors[0]; - for (i = diw_end; i < diw_end_1; i++) - ((uae_u16 *)xlinebuffer)[i] = c; +static void pfield_do_fill_line (int start, int stop) +{ + switch (gfxvidinfo.pixbytes) { + case 1: fill_line_8 (xlinebuffer, start, stop); break; + case 2: fill_line_16 (xlinebuffer, start, stop); break; + case 4: fill_line_32 (xlinebuffer, start, stop); break; } } -#endif - -#ifndef NO_DOUBLING_LINETOSCR -#define NO_DOUBLING_LINETOSCR -#endif - -#endif -#ifdef NO_DOUBLING_LINETOSCR -#undef pfield_linetoscr_full8_double -#undef pfield_linetoscr_full16_double -static void pfield_linetoscr_full8_double (int start, int lframe_end, int diw_end, int stop) +static void pfield_do_linetoscr_full (int double_line) { char *oldxlb = (char *)xlinebuffer; - pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); + int old_src_pixel = src_pixel; + + pfield_do_linetoscr (playfield_start, playfield_end); xlinebuffer = oldxlb + linetoscr_double_offset; - pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); + src_pixel = old_src_pixel; + pfield_do_linetoscr (playfield_start, playfield_end); } -static void pfield_linetoscr_full16_double (int start, int lframe_end, int diw_end, int stop) + +static void dummy_worker (int start, int stop) { - char *oldxlb = (char *)xlinebuffer; - pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); - xlinebuffer = oldxlb + linetoscr_double_offset; - pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); } -#endif -#endif /* no AGA_CHIPSET */ +static unsigned int ham_lastcolor; -static int linetoscr_diw_end, linetoscr_diw_start; +static int ham_decode_pixel; -/* Initialize the variables necessary for drawing a line. - * This involves setting up start/stop positions and display window - * borders. Also, since the drawing code may not fully overwrite all - * releveant areas in the pixdata.apixels array for speed reasons, parts of - * it must possibly be cleared here. */ -static void pfield_init_linetoscr (void) -{ - int ddf_left, ddf_right; - int mindelay = bpldelay1, maxdelay = bpldelay2; - if (bpldelay1 > bpldelay2) - maxdelay = bpldelay1, mindelay = bpldelay2; - - linetoscr_diw_start = dp_for_drawing->diwfirstword; - linetoscr_diw_end = dp_for_drawing->diwlastword; - - /* We should really look at DDF also when calculating max_diwstop/min_diwstrt, - * so that centering works better, but I'm afraid that might cost too many - * cycles. Plus it's dangerous, see the code below that handles the case - * with sprites. */ - if (dip_for_drawing->nr_sprites == 0) { - int hiresadjust = bplhires ? 4 : 8; - ddf_left = (((dp_for_drawing->plfstrt + hiresadjust)*2 - + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift); - ddf_right = (((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 - + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift); - - if (linetoscr_diw_start < ddf_left) - linetoscr_diw_start = ddf_left; - if (linetoscr_diw_end > ddf_right) - linetoscr_diw_end = ddf_right; - - if (mindelay != maxdelay) { - /* Raahh... - * We just clear the maximum amount of space that may need to be - * cleared. We could do this exactly, but it would come out slower - * because of the overhead. */ - if (currprefs.gfx_lores == 2) { - fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_left>>1), 15); - fuzzy_memset_le32 (pixdata.apixels, 0, (ddf_right>>1) - 15, 15); - } else if (currprefs.gfx_lores) { - fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 15); - fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 15, 15); - } else { - fuzzy_memset_le32 (pixdata.apixels, 0, ddf_left, 30); - fuzzy_memset_le32 (pixdata.apixels, 0, ddf_right - 30, 30); +/* Decode HAM in the invisible portion of the display (left of VISIBLE_LEFT_BORDER), + but don't draw anything in. This is done to prepare HAM_LASTCOLOR for later, + when decode_ham runs. */ +static void init_ham_decoding (void) +{ + int unpainted_amiga = res_shift_from_window (unpainted); + ham_decode_pixel = src_pixel; + ham_lastcolor = color_reg_get (&colors_for_drawing, 0); + + if (currprefs.chipset_mask & CSMASK_AGA) { + if (bplplanecnt == 8) { /* AGA mode HAM8 */ + while (unpainted_amiga-- > 0) { + int pv = pixdata.apixels[ham_decode_pixel++]; + switch (pv & 0x3) { + case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break; + case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break; + case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break; + case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; + } + } + } else if(bplplanecnt == 6) { /* AGA mode HAM6 */ + while (unpainted_amiga-- > 0) { + int pv = pixdata.apixels[ham_decode_pixel++]; + switch (pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break; + case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break; + case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break; + case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break; + } } } } else { - int hiresadjust = bplhires ? 4 : 8; - /* We swap mindelay and maxdelay here to get rid of the mindelay != maxdelay check. - * Since we have to do a memset anyway (because there may be sprites), - * we might as well clear all at once. */ - ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift; - ddf_right = ((dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust)*2 + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift; - if (linetoscr_diw_start < ddf_left) { - int strt = linetoscr_diw_start; - int stop = ddf_left; -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - strt >>= 1, stop >>= 1; -#endif - if (strt < stop) - fuzzy_memset (pixdata.apixels, 0, strt, stop - strt); - } - - if (linetoscr_diw_end > ddf_right) { - int strt = ddf_right; - int stop = linetoscr_diw_end; -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - strt >>= 1, stop >>= 1; -#endif - if (strt < stop) - fuzzy_memset (pixdata.apixels, 0, strt, stop - strt); + if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */ + while (unpainted_amiga-- > 0) { + int pv = pixdata.apixels[ham_decode_pixel++]; + switch (pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break; + case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; + case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; + case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; + } + } } } - /* Perverse cases happen. */ - if (linetoscr_diw_end < linetoscr_diw_start) - linetoscr_diw_end = linetoscr_diw_start; } -static void pfield_do_linetoscr(int start, int stop) +static void decode_ham (int pix, int stoppos) { - int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end; - - if (stop > linetoscr_right_x) - stop = linetoscr_right_x; - if (start < linetoscr_x_adjust) - start = linetoscr_x_adjust; - - if (lframe_end < start) - lframe_end = start; - if (diw_end > stop) - diw_end = stop; - - if (start >= stop) - return; + int todraw_amiga = res_shift_from_window (stoppos - pix); + if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8)) + abort (); -#if AGA_CHIPSET == 0 - if (start == linetoscr_x_adjust && stop == linetoscr_right_x) { - switch (gfxvidinfo.pixbytes) { - case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break; - case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break; - case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break; - case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break; + if (currprefs.chipset_mask & CSMASK_AGA) { + if (bplplanecnt == 8) { /* AGA mode HAM8 */ + while (todraw_amiga-- > 0) { + int pv = pixdata.apixels[ham_decode_pixel]; + switch (pv & 0x3) { + case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break; + case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break; + case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break; + case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; + } + ham_linebuf[ham_decode_pixel++] = ham_lastcolor; + } + } else if(bplplanecnt == 6) { /* AGA mode HAM6 */ + while (todraw_amiga-- > 0) { + int pv = pixdata.apixels[ham_decode_pixel]; + switch (pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break; + case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break; + case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break; + case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break; + } + ham_linebuf[ham_decode_pixel++] = ham_lastcolor; + } } } else { - switch (gfxvidinfo.pixbytes) { - case 1: pfield_linetoscr_8 (start, lframe_end, diw_end, stop); break; - case 2: pfield_linetoscr_16 (start, lframe_end, diw_end, stop); break; - case 3: pfield_linetoscr_24 (start, lframe_end, diw_end, stop); break; - case 4: pfield_linetoscr_32 (start, lframe_end, diw_end, stop); break; + if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */ + while (todraw_amiga-- > 0) { + int pv = pixdata.apixels[ham_decode_pixel]; + switch (pv & 0x30) { + case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break; + case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break; + case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break; + case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break; + } + ham_linebuf[ham_decode_pixel++] = ham_lastcolor; + } } } -#else - pfield_linetoscr_aga (start, lframe_end, diw_end, stop); -#endif -} - -static void pfield_do_fill_line (int start, int stop) -{ - if (stop > linetoscr_right_x) - stop = linetoscr_right_x; - if (start < linetoscr_x_adjust) - start = linetoscr_x_adjust; - - if (start >= stop) - return; - -#if AGA_CHIPSET == 0 - switch (gfxvidinfo.pixbytes) { - case 1: fill_line_8 (xlinebuffer, start, stop); break; - case 2: fill_line_16 (xlinebuffer, start, stop); break; - case 3: fill_line_24 (xlinebuffer, start, stop); break; - case 4: fill_line_32 (xlinebuffer, start, stop); break; - } -#else - aga_fill_line_32 (xlinebuffer, start, stop); - /* FIXME */ -#endif -} - -static void pfield_do_linetoscr_full (int double_line) -{ - int start = linetoscr_x_adjust, stop = start + gfxvidinfo.width; - int lframe_end = linetoscr_diw_start, diw_end = linetoscr_diw_end; - if (lframe_end < start) - lframe_end = start; - if (diw_end > stop) - diw_end = stop; - -#if AGA_CHIPSET == 0 - if (double_line) { - switch (gfxvidinfo.pixbytes) { - case 1: pfield_linetoscr_full8_double (start, lframe_end, diw_end, stop); break; - case 2: pfield_linetoscr_full16_double (start, lframe_end, diw_end, stop); break; - case 3: pfield_linetoscr_full24_double (start, lframe_end, diw_end, stop); break; - case 4: pfield_linetoscr_full32_double (start, lframe_end, diw_end, stop); break; - } - } else - switch (gfxvidinfo.pixbytes) { - case 1: pfield_linetoscr_full8 (start, lframe_end, diw_end, stop); break; - case 2: pfield_linetoscr_full16 (start, lframe_end, diw_end, stop); break; - case 3: pfield_linetoscr_full24 (start, lframe_end, diw_end, stop); break; - case 4: pfield_linetoscr_full32 (start, lframe_end, diw_end, stop); break; - } -#else - pfield_linetoscr_aga (start, lframe_end, diw_end, stop); -#endif } static void gen_pfield_tables (void) { int i; - union { - struct { - uae_u8 a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p; - } foo; - struct { - uae_u32 a, b, c, d; - } bar; - } baz; /* For now, the AGA stuff is broken in the dual playfield case. We encode * sprites in dpf mode by ORing the pixel value with 0x80. To make dual @@ -886,26 +657,7 @@ static void gen_pfield_tables (void) lots_of_twos[i] = i == 0 ? 0 : 2; linear_map_256[i] = i; - } - for (i = 0; i < 256; i++) { - /* We lose every second pixel in HiRes if UAE runs in a 320x200 screen. */ - baz.foo.a = i & 64 ? 1 : 0; - baz.foo.b = i & 16 ? 1 : 0; - baz.foo.c = i & 4 ? 1 : 0; - baz.foo.d = i & 1 ? 1 : 0; - hirestab_l[i][0] = baz.bar.a; - - baz.foo.a = i & 128 ? 1 : 0; - baz.foo.b = i & 64 ? 1 : 0; - baz.foo.c = i & 32 ? 1 : 0; - baz.foo.d = i & 16 ? 1 : 0; - baz.foo.e = i & 8 ? 1 : 0; - baz.foo.f = i & 4 ? 1 : 0; - baz.foo.g = i & 2 ? 1 : 0; - baz.foo.h = i & 1 ? 1 : 0; - lorestab_l[i][0] = baz.bar.a; - lorestab_l[i][1] = baz.bar.b; clxtab[i] = ((((i & 3) && (i & 12)) << 9) | (((i & 3) && (i & 48)) << 10) | (((i & 3) && (i & 192)) << 11) @@ -913,40 +665,6 @@ static void gen_pfield_tables (void) | (((i & 12) && (i & 192)) << 13) | (((i & 48) && (i & 192)) << 14)); } - - for (i = 0; i < 256; i++) { - baz.foo.a = i & 128 ? 1 : 0; - baz.foo.b = i & 64 ? 1 : 0; - baz.foo.c = i & 32 ? 1 : 0; - baz.foo.d = i & 16 ? 1 : 0; - baz.foo.e = i & 8 ? 1 : 0; - baz.foo.f = i & 4 ? 1 : 0; - baz.foo.g = i & 2 ? 1 : 0; - baz.foo.h = i & 1 ? 1 : 0; - hirestab_h[i][0] = baz.bar.a; - hirestab_h[i][1] = baz.bar.b; - - baz.foo.a = i & 128 ? 1 : 0; - baz.foo.b = i & 128 ? 1 : 0; - baz.foo.c = i & 64 ? 1 : 0; - baz.foo.d = i & 64 ? 1 : 0; - baz.foo.e = i & 32 ? 1 : 0; - baz.foo.f = i & 32 ? 1 : 0; - baz.foo.g = i & 16 ? 1 : 0; - baz.foo.h = i & 16 ? 1 : 0; - baz.foo.i = i & 8 ? 1 : 0; - baz.foo.j = i & 8 ? 1 : 0; - baz.foo.k = i & 4 ? 1 : 0; - baz.foo.l = i & 4 ? 1 : 0; - baz.foo.m = i & 2 ? 1 : 0; - baz.foo.n = i & 2 ? 1 : 0; - baz.foo.o = i & 1 ? 1 : 0; - baz.foo.p = i & 1 ? 1 : 0; - lorestab_h[i][0] = baz.bar.a; - lorestab_h[i][1] = baz.bar.b; - lorestab_h[i][2] = baz.bar.c; - lorestab_h[i][3] = baz.bar.d; - } } static uae_u32 attach_2nd; @@ -1014,7 +732,11 @@ static uae_u32 do_sprite_collisions (str return datab; } -static __inline__ void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc) +/* We use the compiler's inlining ability to ensure that HAM, ATTCH and + SPRX_INC are in effect compile time constants. That will cause some + unnecessary code to be optimized away. + Don't touch this if you don't know what you are doing. */ +static void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc) { uae_u32 datcd; int basecol = 16; @@ -1025,7 +747,7 @@ static __inline__ void render_sprite (in if (attch) datcd = attach_2nd; - for(; attch ? datab | datcd : datab; sprxp += sprx_inc) { + for (; attch ? datab | datcd : datab; sprxp += sprx_inc) { int col; if (attch) { @@ -1037,22 +759,22 @@ static __inline__ void render_sprite (in if (col) { col |= basecol; if (ham) { - col = colors_for_drawing.color_regs[col]; - ham_linebuf[sprxp] = col; + col = color_reg_get (&colors_for_drawing, col); + ham_linebuf[sprxp + pixels_offset] = col; if (sprx_inc == 2) { - ham_linebuf[sprxp+1] = col; + ham_linebuf[sprxp + pixels_offset + 1] = col; } } else { - pixdata.apixels[sprxp] = col; + pixdata.apixels[sprxp + pixels_offset] = col; if (sprx_inc == 2) { - pixdata.apixels[sprxp+1] = col; + pixdata.apixels[sprxp + pixels_offset + 1] = col; } } } } } -static void walk_sprites (struct sprite_draw *spd, int nr_spr) +STATIC_INLINE void walk_sprites (struct sprite_draw *spd, int nr_spr) { int i, prev_overlap; int last_sprite_pos = -64; @@ -1071,10 +793,8 @@ static void walk_sprites (struct sprite_ prev_overlap++; datab = do_sprite_collisions (spd, prev_overlap, i, nr_spr); -#ifdef LORES_HACK if (currprefs.gfx_lores == 2) sprxp >>= 1; -#endif if ((bpldualpf && plfpri[1] < 256) || (plfpri[2] < 256)) { if (sprxp != last_sprite_pos) { int ok = last_sprite_pos-sprxp+16; @@ -1095,7 +815,7 @@ static void walk_sprites (struct sprite_ int p = sprxp+ok; for (; mask; mask <<= 2, p += sprx_inc) { - int data = pixdata.apixels[p]; + int data = pixdata.apixels[p + pixels_offset]; if (dblpf_2nd2[data] == 2) plane2 |= mask; if (dblpf_2nd1[data] == 1) @@ -1106,7 +826,7 @@ static void walk_sprites (struct sprite_ int p = sprxp+ok; for (; mask; mask <<= 2, p += sprx_inc) { - if (pixdata.apixels[p]) + if (pixdata.apixels[p + pixels_offset]) plane2 |= mask; } } @@ -1120,6 +840,9 @@ static void walk_sprites (struct sprite_ attach_2nd &= ~plane2; } } + /* If this seems strange to you, see the comment near render_sprite + about inlining. If it still seems strange, don't touch any of + this. */ if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) { /* Attached sprite */ if (bplham) { @@ -1139,7 +862,7 @@ static void walk_sprites (struct sprite_ if (i + 1 < nr_spr && spd[i+1].num == spd[i].num - 1 && spd[i+1].linepos == spd[i].linepos) i++; } else { - if (bplham) { + if (0 && bplham) { if (sprx_inc == 1) { render_sprite (spd[i].num, sprxp, datab, 1, 0, 1); } else { @@ -1156,500 +879,230 @@ static void walk_sprites (struct sprite_ } } -#ifndef SMART_UPDATE -#undef UNALIGNED_PROFITABLE -#endif - -#ifdef UNALIGNED_PROFITABLE - -static void pfield_doline_unaligned_h (int lineno) -{ - int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2; - - if (bplhires) { - int xpos1 = xpos + 16 + bpldelay1*2; - int xpos2; - uae_u8 *dataptr = line_data[lineno]; - int len = dp_for_drawing->plflinelen >> 1; - - if (len <= 0) - return; - - if (bpldelay1 == bpldelay2) { - switch (bplplanecnt) { - case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - } - } else { - switch (bplplanecnt) { - case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - } - - xpos2 = xpos + 16 + bpldelay2*2; - switch (bplplanecnt) { - case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - } - } - } else { - int xpos1 = xpos + 32 + bpldelay1*2; - int xpos2; - uae_u8 *dataptr = line_data[lineno]; - int len = dp_for_drawing->plflinelen >> 2; - - if (len <= 0) - return; - - if (bpldelay1 == bpldelay2) { - switch (bplplanecnt) { - case 1: set_lores_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 2: set_lores_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 3: set_lores_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 4: set_lores_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 5: set_lores_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 6: set_lores_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 7: set_lores_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 8: set_lores_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - } - } else { - switch (bplplanecnt) { - case 1: case 2: set_lores_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 3: case 4: set_lores_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 5: case 6: set_lores_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 7: case 8: set_lores_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - } - - xpos2 = xpos + 32 + bpldelay2*2; - switch (bplplanecnt) { - case 2: case 3: set_lores_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 4: case 5: set_lores_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 6: case 7: set_lores_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 8: set_lores_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - } - } - } -} - -static void pfield_doline_unaligned_l (int lineno) -{ - int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT; - - if (bplhires) { - int xpos1 = xpos + 8 + bpldelay1; - int xpos2; - uae_u8 *dataptr = line_data[lineno]; - int len = dp_for_drawing->plflinelen >> 1; - - if (len <= 0) - return; - - if (bpldelay1 == bpldelay2) { - switch (bplplanecnt) { - case 1: set_hires_l_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 2: set_hires_l_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 3: set_hires_l_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 4: set_hires_l_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 5: set_hires_l_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 6: set_hires_l_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 7: set_hires_l_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 8: set_hires_l_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - } - } else { - switch (bplplanecnt) { - case 1: case 2: set_hires_l_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 3: case 4: set_hires_l_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 5: case 6: set_hires_l_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 7: case 8: set_hires_l_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - } - - xpos2 = xpos + 8 + bpldelay2; - switch (bplplanecnt) { - case 2: case 3: set_hires_l_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 4: case 5: set_hires_l_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 6: case 7: set_hires_l_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 8: set_hires_l_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - } - } - } else { - int xpos1 = xpos + 16 + bpldelay1; - int xpos2; - uae_u8 *dataptr = line_data[lineno]; - int len = dp_for_drawing->plflinelen >> 2; - - if (len <= 0) - return; - - if (bpldelay1 == bpldelay2) { - switch (bplplanecnt) { - case 1: set_hires_h_0_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 2: set_hires_h_1_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 3: set_hires_h_2_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 4: set_hires_h_3_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 5: set_hires_h_4_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 6: set_hires_h_5_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 7: set_hires_h_6_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 8: set_hires_h_7_0 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - } - } else { - switch (bplplanecnt) { - case 1: case 2: set_hires_h_0_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 3: case 4: set_hires_h_1_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 5: case 6: set_hires_h_2_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - case 7: case 8: set_hires_h_3_1 ((uae_u32 *)(pixdata.apixels + xpos1), dataptr, len); break; - } - - xpos2 = xpos + 16 + bpldelay2; - switch (bplplanecnt) { - case 2: case 3: set_hires_h_0_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 4: case 5: set_hires_h_1_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 6: case 7: set_hires_h_2_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - case 8: set_hires_h_3_2 ((uae_u32 *)(pixdata.apixels + xpos2), dataptr, len); break; - } - } - } -} - -#define pfield_doline_h pfield_doline_unaligned_h -#define pfield_doline_l pfield_doline_unaligned_l - -#else /* not UNALIGNED_PROFITABLE */ - - -static __inline__ void pfield_orword_hires_h(int data, unsigned char *dp, int bit) -{ - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr |= hirestab_h[data >> 8][0] << bit; - *(pixptr+1) |= hirestab_h[data >> 8][1] << bit; - *(pixptr+2) |= hirestab_h[data & 255][0] << bit; - *(pixptr+3) |= hirestab_h[data & 255][1] << bit; -} - -static __inline__ void pfield_orword_lores_h(int data, unsigned char *dp, int bit) -{ - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr |= lorestab_h[data >> 8][0] << bit; - *(pixptr+1) |= lorestab_h[data >> 8][1] << bit; - *(pixptr+2) |= lorestab_h[data >> 8][2] << bit; - *(pixptr+3) |= lorestab_h[data >> 8][3] << bit; - *(pixptr+4) |= lorestab_h[data & 255][0] << bit; - *(pixptr+5) |= lorestab_h[data & 255][1] << bit; - *(pixptr+6) |= lorestab_h[data & 255][2] << bit; - *(pixptr+7) |= lorestab_h[data & 255][3] << bit; -} - -static __inline__ void pfield_setword_hires_h(int data, unsigned char *dp, int bit) -{ - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr = hirestab_h[data >> 8][0] << bit; - *(pixptr+1) = hirestab_h[data >> 8][1] << bit; - *(pixptr+2) = hirestab_h[data & 255][0] << bit; - *(pixptr+3) = hirestab_h[data & 255][1] << bit; -} - -static __inline__ void pfield_setword_lores_h(int data, unsigned char *dp, int bit) -{ - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr = lorestab_h[data >> 8][0] << bit; - *(pixptr+1) = lorestab_h[data >> 8][1] << bit; - *(pixptr+2) = lorestab_h[data >> 8][2] << bit; - *(pixptr+3) = lorestab_h[data >> 8][3] << bit; - *(pixptr+4) = lorestab_h[data & 255][0] << bit; - *(pixptr+5) = lorestab_h[data & 255][1] << bit; - *(pixptr+6) = lorestab_h[data & 255][2] << bit; - *(pixptr+7) = lorestab_h[data & 255][3] << bit; -} - -static __inline__ void pfield_orword_hires_l(int data, unsigned char *dp, int bit) -{ - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr |= hirestab_l[data >> 8][0] << bit; - *(pixptr+1) |= hirestab_l[data & 255][0] << bit; -} - -static __inline__ void pfield_orword_lores_l(int data, unsigned char *dp, int bit) -{ - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr |= lorestab_l[data >> 8][0] << bit; - *(pixptr+1) |= lorestab_l[data >> 8][1] << bit; - *(pixptr+2) |= lorestab_l[data & 255][0] << bit; - *(pixptr+3) |= lorestab_l[data & 255][1] << bit; -} - -static __inline__ void pfield_setword_hires_l(int data, unsigned char *dp, int bit) -{ - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr = hirestab_l[data >> 8][0] << bit; - *(pixptr+1) = hirestab_l[data & 255][0] << bit; -} - -static __inline__ void pfield_setword_lores_l(int data, unsigned char *dp, int bit) -{ - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr = lorestab_l[data >> 8][0] << bit; - *(pixptr+1) = lorestab_l[data >> 8][1] << bit; - *(pixptr+2) = lorestab_l[data & 255][0] << bit; - *(pixptr+3) = lorestab_l[data & 255][1] << bit; -} - -#define DO_ONE_PLANE(POINTER, MULT, FUNC, DELAY, LL_SUB, P_ADD) { \ - int i; \ - unsigned int bpldat1; \ - uae_u16 data; \ - unsigned int bpldat2 = 0; \ - uae_u8 *ptr = (POINTER); \ - for (i = dp_for_drawing->plflinelen; i > 0; i -= LL_SUB) { \ - bpldat1 = bpldat2; \ - bpldat2 = do_get_mem_word ((uae_u16 *)ptr); \ - ptr+=2; \ - data = (bpldat1 << (16 - DELAY)) | (bpldat2 >> DELAY); \ - FUNC(data, app, MULT); \ - app += P_ADD; \ - } \ - data = bpldat2 << (16 - DELAY); \ - FUNC(data, app, MULT); \ -} +#define MERGE(a,b,mask,shift) do {\ + uae_u32 tmp = mask & (a ^ (b >> shift)); \ + a ^= tmp; \ + b ^= (tmp << shift); \ +} while (0) + +#define GETLONG(P, SHIFT, SHIFT_ZERO) \ + ((SHIFT_ZERO) ? do_get_mem_long (P) \ + : (do_get_mem_long (P) << (32 - (SHIFT))) | (do_get_mem_long ((P) + 1) >> (SHIFT))) + +/* We use the compiler's inlining ability to ensure that PLANES, D1Z and D2Z + are in effect compile time constants. That will cause some unnecessary + code to be optimized away. + Don't touch this if you don't know what you are doing. */ +STATIC_INLINE void pfield_doline_1 (uae_u32 *pixels, int delay1, int delay2, int d1z, int d2z, + int wordcount, int planes) +{ + while (wordcount-- > 0) { + uae_u32 b0, b1, b2, b3, b4, b5, b6, b7; + + b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0; + switch (planes) { + case 8: b0 = GETLONG ((uae_u32 *)real_bplpt[7], delay2, d2z); real_bplpt[7] += 4; + case 7: b1 = GETLONG ((uae_u32 *)real_bplpt[6], delay1, d1z); real_bplpt[6] += 4; + case 6: b2 = GETLONG ((uae_u32 *)real_bplpt[5], delay2, d2z); real_bplpt[5] += 4; + case 5: b3 = GETLONG ((uae_u32 *)real_bplpt[4], delay1, d1z); real_bplpt[4] += 4; + case 4: b4 = GETLONG ((uae_u32 *)real_bplpt[3], delay2, d2z); real_bplpt[3] += 4; + case 3: b5 = GETLONG ((uae_u32 *)real_bplpt[2], delay1, d1z); real_bplpt[2] += 4; + case 2: b6 = GETLONG ((uae_u32 *)real_bplpt[1], delay2, d2z); real_bplpt[1] += 4; + case 1: b7 = GETLONG ((uae_u32 *)real_bplpt[0], delay1, d1z); real_bplpt[0] += 4; + } + + MERGE (b0, b1, 0x55555555, 1); + MERGE (b2, b3, 0x55555555, 1); + MERGE (b4, b5, 0x55555555, 1); + MERGE (b6, b7, 0x55555555, 1); + + MERGE (b0, b2, 0x33333333, 2); + MERGE (b1, b3, 0x33333333, 2); + MERGE (b4, b6, 0x33333333, 2); + MERGE (b5, b7, 0x33333333, 2); + + MERGE (b0, b4, 0x0f0f0f0f, 4); + MERGE (b1, b5, 0x0f0f0f0f, 4); + MERGE (b2, b6, 0x0f0f0f0f, 4); + MERGE (b3, b7, 0x0f0f0f0f, 4); + + MERGE (b0, b1, 0x00ff00ff, 8); + MERGE (b2, b3, 0x00ff00ff, 8); + MERGE (b4, b5, 0x00ff00ff, 8); + MERGE (b6, b7, 0x00ff00ff, 8); + + MERGE (b0, b2, 0x0000ffff, 16); + do_put_mem_long (pixels, b0); + do_put_mem_long (pixels + 4, b2); + MERGE (b1, b3, 0x0000ffff, 16); + do_put_mem_long (pixels + 2, b1); + do_put_mem_long (pixels + 6, b3); + MERGE (b4, b6, 0x0000ffff, 16); + do_put_mem_long (pixels + 1, b4); + do_put_mem_long (pixels + 5, b6); + MERGE (b5, b7, 0x0000ffff, 16); + do_put_mem_long (pixels + 3, b5); + do_put_mem_long (pixels + 7, b7); + pixels += 8; + } +} + +/* See above for comments on inlining. These functions should _not_ + be inlined themselves. */ +static void pfield_doline_none_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 1); } +static void pfield_doline_none_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 2); } +static void pfield_doline_none_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 3); } +static void pfield_doline_none_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 4); } +static void pfield_doline_none_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 5); } +static void pfield_doline_none_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 6); } +static void pfield_doline_none_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 7); } +static void pfield_doline_none_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 8); } + +static void pfield_doline_2_n1 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 1); } +static void pfield_doline_2_n2 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 2); } +static void pfield_doline_2_n3 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 3); } +static void pfield_doline_2_n4 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 4); } +static void pfield_doline_2_n5 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 5); } +static void pfield_doline_2_n6 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 6); } +static void pfield_doline_2_n7 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 7); } +static void pfield_doline_2_n8 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 8); } + +static void pfield_doline_1_n1 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 1); } +static void pfield_doline_1_n2 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 2); } +static void pfield_doline_1_n3 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 3); } +static void pfield_doline_1_n4 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 4); } +static void pfield_doline_1_n5 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 5); } +static void pfield_doline_1_n6 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 6); } +static void pfield_doline_1_n7 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 7); } +static void pfield_doline_1_n8 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 8); } + +static void pfield_doline (int lineno) +{ + /* Delay values in pixels (adjusted to the resolution). */ + int delay1 = bpldelay1 << bplres; + int delay2 = bpldelay2 << bplres; + int mindelay = delay1 < delay2 ? delay1 : delay2; + int wordcount = (dp_for_drawing->plflinelen + (RES_SHIFT (bplres) * 2 - 1)) / (RES_SHIFT (bplres) * 2); + uae_u32 *data = pixdata.apixels_l + 220; + int dsub1, dsub2; #ifdef SMART_UPDATE -#define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2) -#else -#define DATA_POINTER(n) (real_bplpt[n]) -#endif +#define DATA_POINTER(n) (line_data[lineno] + (n)*MAX_WORDS_PER_LINE*2) + real_bplpt[0] = DATA_POINTER (0); + real_bplpt[1] = DATA_POINTER (1); + real_bplpt[2] = DATA_POINTER (2); + real_bplpt[3] = DATA_POINTER (3); + real_bplpt[4] = DATA_POINTER (4); + real_bplpt[5] = DATA_POINTER (5); + real_bplpt[6] = DATA_POINTER (6); + real_bplpt[7] = DATA_POINTER (7); +#endif + + delay1 -= mindelay; + delay2 -= mindelay; + + dsub1 = (delay1 + 31) >> 5; + dsub2 = (delay2 + 31) >> 5; + real_bplpt[0] -= dsub1 * 4; + real_bplpt[2] -= dsub1 * 4; + real_bplpt[4] -= dsub1 * 4; + real_bplpt[1] -= dsub2 * 4; + real_bplpt[3] -= dsub2 * 4; + real_bplpt[5] -= dsub2 * 4; + real_bplpt[6] -= dsub1 * 4; + real_bplpt[7] -= dsub2 * 4; + + if (dsub1 > dsub2) + wordcount += dsub1; + else + wordcount += dsub2; -static void pfield_doline_aligned_h (int lineno) -{ - int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2; + delay1 &= 31; + delay2 &= 31; - if (bplhires) { - if (bplplanecnt > 0) { - int xpos1 = xpos + 16 + (bpldelay1 >= 8 ? 16 : 0); - int xpos2 = xpos + 16 + (bpldelay2 >= 8 ? 16 : 0); - int delay1 = 2*(bpldelay1 & 7); - int delay2 = 2*(bpldelay2 & 7); - unsigned char *app = pixdata.apixels + xpos1; - uae_u8 *dataptr = line_data[lineno]; - - DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_h, delay1, 4, 16); - if (bplplanecnt > 2) { - app = pixdata.apixels + xpos1; - DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_h, delay1, 4, 16); - } -#if AGA_CHIPSET == 1 - if (bplplanecnt > 4) { - app = pixdata.apixels + xpos1; - DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_h, delay1, 4, 16); - } - if (bplplanecnt > 6) { - app = pixdata.apixels + xpos1; - DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_h, delay1, 4, 16); - } -#endif - if (bplplanecnt > 1) { - app = pixdata.apixels + xpos2; - DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_h, delay2, 4, 16); - } - if (bplplanecnt > 3) { - app = pixdata.apixels + xpos2; - DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_h, delay2, 4, 16); - } -#if AGA_CHIPSET == 1 - if (bplplanecnt > 5) { - app = pixdata.apixels + xpos2; - DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_h, delay2, 4, 16); - } - if (bplplanecnt > 7) { - app = pixdata.apixels + xpos2; - DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_h, delay2, 4, 16); - } -#endif - } else { - memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); - } - } else { - if (bplplanecnt > 0) { - int x = xpos + 32; - unsigned char *app = pixdata.apixels + x; - uae_u8 *dataptr = line_data[lineno]; - - DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_h, bpldelay1, 8, 32); - if (bplplanecnt > 2) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_h, bpldelay1, 8, 32); - } - if (bplplanecnt > 4) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_h, bpldelay1, 8, 32); - } -#if AGA_CHIPSET == 1 - if (bplplanecnt > 6) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_h, bpldelay1, 8, 32); - } -#endif - if (bplplanecnt > 1) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_h, bpldelay2, 8, 32); - } - if (bplplanecnt > 3) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_h, bpldelay2, 8, 32); - } - if (bplplanecnt > 5) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_h, bpldelay2, 8, 32); - } -#if AGA_CHIPSET == 1 - if (bplplanecnt > 7) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_h, bpldelay2, 8, 32); - } -#endif - } else { - memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); + if (delay1) + switch (bplplanecnt) { + default: break; + case 1: pfield_doline_1_n1 (data, delay1, wordcount); break; + case 2: pfield_doline_1_n2 (data, delay1, wordcount); break; + case 3: pfield_doline_1_n3 (data, delay1, wordcount); break; + case 4: pfield_doline_1_n4 (data, delay1, wordcount); break; + case 5: pfield_doline_1_n5 (data, delay1, wordcount); break; + case 6: pfield_doline_1_n6 (data, delay1, wordcount); break; + case 7: pfield_doline_1_n7 (data, delay1, wordcount); break; + case 8: pfield_doline_1_n8 (data, delay1, wordcount); break; + } + else if (delay2) + switch (bplplanecnt) { + default: break; + case 1: pfield_doline_2_n1 (data, delay2, wordcount); break; + case 2: pfield_doline_2_n2 (data, delay2, wordcount); break; + case 3: pfield_doline_2_n3 (data, delay2, wordcount); break; + case 4: pfield_doline_2_n4 (data, delay2, wordcount); break; + case 5: pfield_doline_2_n5 (data, delay2, wordcount); break; + case 6: pfield_doline_2_n6 (data, delay2, wordcount); break; + case 7: pfield_doline_2_n7 (data, delay2, wordcount); break; + case 8: pfield_doline_2_n8 (data, delay2, wordcount); break; } - } + else + switch (bplplanecnt) { + default: break; + case 1: pfield_doline_none_n1 (data, wordcount); break; + case 2: pfield_doline_none_n2 (data, wordcount); break; + case 3: pfield_doline_none_n3 (data, wordcount); break; + case 4: pfield_doline_none_n4 (data, wordcount); break; + case 5: pfield_doline_none_n5 (data, wordcount); break; + case 6: pfield_doline_none_n6 (data, wordcount); break; + case 7: pfield_doline_none_n7 (data, wordcount); break; + case 8: pfield_doline_none_n8 (data, wordcount); break; + } } -static void pfield_doline_aligned_l (int lineno) -{ - int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT; - if (bplhires) { - if (bplplanecnt > 0) { - int xpos1 = xpos + 8 + (bpldelay1 >= 8 ? 8 : 0); - int xpos2 = xpos + 8 + (bpldelay2 >= 8 ? 8 : 0); - int delay1 = (bpldelay1 & 7) * 2; - int delay2 = (bpldelay2 & 7) * 2; - unsigned char *app = pixdata.apixels + xpos1; - uae_u8 *dataptr = line_data[lineno]; - - DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_hires_l, delay1, 4, 8); - if (bplplanecnt > 2) { - app = pixdata.apixels + xpos1; - DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_hires_l, delay1, 4, 8); - } -#if AGA_CHIPSET == 1 - if (bplplanecnt > 4) { - app = pixdata.apixels + xpos1; - DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_hires_l, delay1, 4, 8); - } - if (bplplanecnt > 6) { - app = pixdata.apixels + xpos1; - DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_hires_l, delay1, 4, 8); - } -#endif - if (bplplanecnt > 1) { - app = pixdata.apixels + xpos2; - DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_hires_l, delay2, 4, 8); - } - if (bplplanecnt > 3) { - app = pixdata.apixels + xpos2; - DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_hires_l, delay2, 4, 8); - } -#if AGA_CHIPSET == 1 - if (bplplanecnt > 5) { - app = pixdata.apixels + xpos2; - DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_hires_l, delay2, 4, 8); - } - if (bplplanecnt > 7) { - app = pixdata.apixels + xpos2; - DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_hires_l, delay2, 4, 8); - } -#endif - } else { - memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); - } - } else { - if (bplplanecnt > 0) { - int x = xpos + 16; - int delay1 = bpldelay1; - int delay2 = bpldelay2; - unsigned char *app = pixdata.apixels + x; - uae_u8 *dataptr = line_data[lineno]; - - DO_ONE_PLANE(DATA_POINTER(0), 0, pfield_setword_lores_l, delay1, 8, 16); - if (bplplanecnt > 2) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(2), 2, pfield_orword_lores_l, delay1, 8, 16); - } - if (bplplanecnt > 4) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(4), 4, pfield_orword_lores_l, delay1, 8, 16); - } -#if AGA_CHIPSET == 1 - if (bplplanecnt > 6) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(6), 6, pfield_orword_lores_l, delay1, 8, 16); - } -#endif - if (bplplanecnt > 1) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(1), 1, pfield_orword_lores_l, delay2, 8, 16); - } - if (bplplanecnt > 3) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(3), 3, pfield_orword_lores_l, delay2, 8, 16); - } - if (bplplanecnt > 5) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(5), 5, pfield_orword_lores_l, delay2, 8, 16); - } -#if AGA_CHIPSET == 1 - if (bplplanecnt > 7) { - app = pixdata.apixels + x; - DO_ONE_PLANE(DATA_POINTER(7), 7, pfield_orword_lores_l, delay2, 8, 16); - } -#endif - } else { - memset(pixdata.apixels, 0, sizeof(pixdata.apixels)); - } - } +static void fix_delays(int delay, int *dst1, int *dst2) +{ + int delay1 = (delay & 0x0f) | ((delay & 0x0c00) >> 6); + int delay2 = ((delay >> 4) & 0x0f) | (((delay >> 4) & 0x0c00) >> 6); + /* this may not be 100% correct yet but at least it fixes all tested games with incorrect + * horiz position/scrolling (ex: New Zealand Story, James Pond II AGA, Action Snooker...) + */ + int delayoffset = ( (dp_for_drawing->plfstrt - 0x18) & ( (fetchstart - 1) & ~3) ) << 1; + int delaymask = ((16 << fetchmode) - 1) >> bplres; + delay1 += delayoffset; + delay2 += delayoffset; + delay1 &= delaymask; + delay2 &= delaymask; + *dst1 = delay1; + *dst2 = delay2; } -#define pfield_doline_h pfield_doline_aligned_h -#define pfield_doline_l pfield_doline_aligned_l - -#endif /* UNALIGNED_PROFITABLE */ - static void pfield_adjust_delay (void) { - int ddf_left = dp_for_drawing->plfstrt; - int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen; + int ddf_left = dp_for_drawing->plfstrt + prefetch; + int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + prefetch; int i; for (i = dip_for_drawing->last_delay_change-1; i >= dip_for_drawing->first_delay_change-1; i--) { int delayreg = i < dip_for_drawing->first_delay_change ? dp_for_drawing->bplcon1 : delay_changes[i].value; - int delay1 = delayreg & 0xF; - int delay2 = (delayreg >> 4) & 0xF; - int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right + 8 : delay_changes[i+1].linepos; + int delay1, delay2; + int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right : delay_changes[i+1].linepos; int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos; int j; - startpos = PIXEL_XPOS (startpos + (bplhires ? 4 : 8)); - stoppos = PIXEL_XPOS (stoppos + (bplhires ? 4 : 8)); - if (currprefs.gfx_lores == 0) - delay1 <<= 1, delay2 <<= 1; - else if (currprefs.gfx_lores == 2) - startpos >>= 1, stoppos >>= 1; + startpos = ((startpos - ddf_left) * 2) << bplres; + stoppos = ((stoppos - ddf_left) * 2) << bplres; + + fix_delays (delayreg, &delay1, & delay2); + delay1 <<= bplres; + delay2 <<= bplres; + startpos += 880; stoppos += 880; for (j = startpos-1; j >= stoppos; j--) { - pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA); + int t1 = pixdata.apixels[j - delay1]; + int t2 = pixdata.apixels[j - delay2]; +#if 0 + pixdata.apixels[j - delay1] &= 0xAA; + pixdata.apixels[j - delay2] &= 0x55; +#endif + pixdata.apixels[j] = (t1 & 0x55) | (t2 & 0xAA); } } } @@ -1676,7 +1129,7 @@ static void init_aspect_maps (void) free (amiga2aspect_line_map); /* At least for this array the +1 is necessary. */ - amiga2aspect_line_map = (int *)malloc (sizeof (int) * (maxvpos+1)*2 + 1); + amiga2aspect_line_map = (int *)malloc (sizeof (int) * (MAXVPOS + 1)*2 + 1); native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height); if (currprefs.gfx_correct_aspect) @@ -1687,11 +1140,11 @@ static void init_aspect_maps (void) else native_lines_per_amiga_line = 1; - maxl = (maxvpos+1) * (currprefs.gfx_linedbl ? 2 : 1); + maxl = (MAXVPOS + 1) * (currprefs.gfx_linedbl ? 2 : 1); min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0); max_drawn_amiga_line = -1; for (i = 0; i < maxl; i++) { - int v = (i - min_ypos_for_screen) * native_lines_per_amiga_line; + int v = (int) ((i - min_ypos_for_screen) * native_lines_per_amiga_line); if (v >= gfxvidinfo.height && max_drawn_amiga_line == -1) max_drawn_amiga_line = i - min_ypos_for_screen; if (i < min_ypos_for_screen || v >= gfxvidinfo.height) @@ -1702,6 +1155,7 @@ static void init_aspect_maps (void) max_drawn_amiga_line >>= 1; if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) { + /* @@@ verify maxvpos vs. MAXVPOS */ extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1; if (extra_y_adjust < 0) extra_y_adjust = 0; @@ -1762,14 +1216,9 @@ static void do_flush_line_1 (int lineno) } } -static __inline__ void do_flush_line (int lineno) +STATIC_INLINE void do_flush_line (int lineno) { - /* We don't want to call X libraries from the second thread right now. */ -#ifndef SUPPORT_PENGUINS do_flush_line_1 (lineno); -#else - line_drawn[lineno] = 1; -#endif } /* @@ -1778,15 +1227,12 @@ static __inline__ void do_flush_line (in * systems. */ -static __inline__ void do_flush_screen (int start, int stop) +STATIC_INLINE void do_flush_screen (int start, int stop) { -#ifdef SUPPORT_PENGUINS - int i; - for (i = 0; i < gfxvidinfo.height; i++) { - if (line_drawn[i]) - do_flush_line_1 (i); - } -#endif + /* TODO: this flush operation is executed outside locked state! + Should be corrected. + (sjo 26.9.99) */ + if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) { flush_block (first_block_line, last_block_line); } @@ -1794,84 +1240,84 @@ static __inline__ void do_flush_screen ( flush_screen (start, stop); } -static __inline__ void finish_line_aga (void) -{ -#if AGA_CHIPSET != 0 - aga_lbufptr = aga_linebuf; - aga_translate32 (linetoscr_x_adjust_bytes, linetoscr_x_adjust_bytes + gfxvidinfo.width); -#endif -} - static int drawing_color_matches; static enum { color_match_acolors, color_match_full } color_match_type; +/* Set up colors_for_drawing to the state at the beginning of the currently drawn + line. Try to avoid copying color tables around whenever possible. */ static void adjust_drawing_colors (int ctable, int bplham) { -#if AGA_CHIPSET == 0 if (drawing_color_matches != ctable) { if (bplham) { - memcpy (&colors_for_drawing, curr_color_tables + ctable, - sizeof colors_for_drawing); + color_reg_cpy (&colors_for_drawing, curr_color_tables + ctable); color_match_type = color_match_full; } else { memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors, - sizeof colors_for_drawing.acolors); + sizeof colors_for_drawing.acolors); color_match_type = color_match_acolors; } drawing_color_matches = ctable; } else if (bplham && color_match_type != color_match_full) { - memcpy (colors_for_drawing.color_regs, curr_color_tables[ctable].color_regs, - sizeof colors_for_drawing.color_regs); + color_reg_cpy (&colors_for_drawing, &curr_color_tables[ctable]); color_match_type = color_match_full; } -#else - if (drawing_color_matches != ctable) { - memcpy (&colors_for_drawing, curr_color_tables + ctable, - sizeof colors_for_drawing); - drawing_color_matches = ctable; - } -#endif } -static __inline__ void adjust_color0_for_color_change (void) +STATIC_INLINE void adjust_color0_for_color_change (void) { drawing_color_matches = -1; if (dp_for_drawing->color0 != 0xFFFFFFFFul) { - colors_for_drawing.color_regs[0] = dp_for_drawing->color0; -#if AGA_CHIPSET == 0 - colors_for_drawing.acolors[0] = xcolors[dp_for_drawing->color0]; -#endif + color_reg_set (&colors_for_drawing, 0, dp_for_drawing->color0); + colors_for_drawing.acolors[0] = getxcolor (dp_for_drawing->color0); } } -/* Fetched data spends 9 lores pixels somewhere in the chips before it appears - * on-screen. We don't emulate this. Instead, we cheat with the copper to - * compensate (much easier that way). */ -#define COPPER_MAGIC_FUDGE -9 +#define COPPER_MAGIC_FUDGE -1 -static __inline__ void do_color_changes (line_draw_func worker) +STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_func worker_pfield) { - int lastpos = 0, nextpos, i; - struct color_change *cc = curr_color_changes + dip_for_drawing->first_color_change; + int i; + int lastpos = visible_left_border; - for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++, cc++) { + for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) { + int regno = curr_color_changes[i].regno; + unsigned int value = curr_color_changes[i].value; + int nextpos, nextpos_in_range; if (i == dip_for_drawing->last_color_change) nextpos = max_diwlastword; else - nextpos = PIXEL_XPOS (cc->linepos) + (COPPER_MAGIC_FUDGE << lores_shift); - worker (lastpos, nextpos); + nextpos = PIXEL_XPOS (curr_color_changes[i].linepos) + (COPPER_MAGIC_FUDGE << lores_shift); + + nextpos_in_range = nextpos; + if (nextpos > visible_right_border) + nextpos_in_range = visible_right_border; + + if (nextpos_in_range > lastpos) { + if (lastpos < playfield_start) { + int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; + (*worker_border) (lastpos, t); + lastpos = t; + } + } + if (nextpos_in_range > lastpos) { + if (lastpos >= playfield_start && lastpos < playfield_end) { + int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; + (*worker_pfield) (lastpos, t); + lastpos = t; + } + } + if (nextpos_in_range > lastpos) { + if (lastpos >= playfield_end) + (*worker_border) (lastpos, nextpos_in_range); + lastpos = nextpos_in_range; + } if (i != dip_for_drawing->last_color_change) { - colors_for_drawing.color_regs[cc->regno] = cc->value; -#if AGA_CHIPSET == 0 - colors_for_drawing.acolors[cc->regno] = xcolors[cc->value]; -#endif + color_reg_set (&colors_for_drawing, regno, value); + colors_for_drawing.acolors[regno] = getxcolor (value); } - if (nextpos > lastpos) { - lastpos = nextpos; - if (lastpos >= linetoscr_right_x) + if (lastpos >= visible_right_border) break; } - } } /* We only save hardware registers during the hardware frame. Now, when @@ -1879,17 +1325,22 @@ static __inline__ void do_color_changes * form. */ static void pfield_expand_dp_bplcon (void) { - bplhires = (dp_for_drawing->bplcon0 & 0x8000) == 0x8000; + bplres = RES_LORES; + if (dp_for_drawing->bplcon0 & 0x8000) + bplres = RES_HIRES; + if (dp_for_drawing->bplcon0 & 0x40) + bplres = RES_SUPERHIRES; bplplanecnt = GET_PLANES (dp_for_drawing->bplcon0); bplham = (dp_for_drawing->bplcon0 & 0x800) == 0x800; -#if AGA_CHIPSET == 1 /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock - * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */ - bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200)); -#else - bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000; -#endif - bpldelay1 = dp_for_drawing->bplcon1 & 0xF; - bpldelay2 = (dp_for_drawing->bplcon1 >> 4) & 0xF; + if (currprefs.chipset_mask & CSMASK_AGA) { + /* The KILLEHB bit exists in ECS, but is apparently meant for Genlock + * stuff, and it's set by some demos (e.g. Andromeda Seven Seas) */ + bplehb = ((dp_for_drawing->bplcon0 & 0xFCC0) == 0x6000 && !(dp_for_drawing->bplcon2 & 0x200)); + } else { + bplehb = (dp_for_drawing->bplcon0 & 0xFC00) == 0x6000; + } + expand_fetchmodes (dp_for_drawing->fmode, dp_for_drawing->bplcon0); + fix_delays (dp_for_drawing->bplcon1, &bpldelay1, &bpldelay2); plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7); plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7); bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400; @@ -1902,8 +1353,9 @@ enum double_how { dh_emerg }; -static __inline__ void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos) +STATIC_INLINE void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos) { + static int warned = 0; int border = 0; int do_double = 0; enum double_how dh; @@ -1911,25 +1363,23 @@ static __inline__ void pfield_draw_line dp_for_drawing = line_decisions + lineno; dip_for_drawing = curr_drawinfo + lineno; switch (linestate[lineno]) { - case LINE_REMEMBERED_AS_PREVIOUS: - { - static int warned = 0; - if (!warned) - write_log ("Shouldn't get here... this is a bug.\n"), warned++; - } + case LINE_REMEMBERED_AS_PREVIOUS: + if (!warned) + write_log ("Shouldn't get here... this is a bug.\n"), warned++; + line_decisions[lineno].which = -2; return; - case LINE_BLACK: + case LINE_BLACK: line_decisions[lineno].which = -2; linestate[lineno] = LINE_REMEMBERED_AS_BLACK; border = 2; break; - case LINE_REMEMBERED_AS_BLACK: + case LINE_REMEMBERED_AS_BLACK: return; - case LINE_AS_PREVIOUS: + case LINE_AS_PREVIOUS: dp_for_drawing--; dip_for_drawing--; if (dp_for_drawing->which != 1) @@ -1938,13 +1388,13 @@ static __inline__ void pfield_draw_line linestate[lineno] = LINE_DONE_AS_PREVIOUS; break; - case LINE_DONE_AS_PREVIOUS: + case LINE_DONE_AS_PREVIOUS: line_decisions[lineno].which = -2; /* fall through */ - case LINE_DONE: + case LINE_DONE: return; - case LINE_DECIDED_DOUBLE: + case LINE_DECIDED_DOUBLE: line_decisions[lineno+1].which = -2; if (follow_ypos != -1) { do_double = 1; @@ -1953,7 +1403,7 @@ static __inline__ void pfield_draw_line } /* fall through */ - default: + default: if (dp_for_drawing->which != 1) border = 1; linestate[lineno] = LINE_DONE; @@ -1967,46 +1417,38 @@ static __inline__ void pfield_draw_line if (xlinebuffer == 0) xlinebuffer = row_map[gfx_ypos], dh = dh_buf; xlinebuffer -= linetoscr_x_adjust_bytes; - aga_lbufptr = aga_linebuf; - if (border == 0) { + if (border == 0 || (dp_for_drawing->plfleft >= 0 && dip_for_drawing->nr_sprites > 0)) { pfield_expand_dp_bplcon (); -#ifdef LORES_HACK - if (gfxvidinfo.can_double && !bplhires && !currprefs.gfx_lores - && dip_for_drawing->nr_color_changes == 0 && !bplham) + if (bplres == RES_LORES && !currprefs.gfx_lores) currprefs.gfx_lores = 2; -#endif pfield_init_linetoscr (); - if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) { - bpldelay1 = bpldelay2 = 0; - if (currprefs.gfx_lores) - pfield_doline_l (lineno); - else - pfield_doline_h (lineno); - pfield_adjust_delay (); - } else { - if (currprefs.gfx_lores) - pfield_doline_l (lineno); - else - pfield_doline_h (lineno); + + if (! border) { + if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) { + bpldelay1 = bpldelay2 = 0; + pfield_doline (lineno); + pfield_adjust_delay (); + } else + pfield_doline (lineno); } /* Check color0 adjust only if we have color changes - shouldn't happen - * otherwise. */ + otherwise. */ adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); - /* The problem is that we must call decode_ham6() BEFORE we do the - * sprites. */ - if (bplham) { - init_ham_decoding(linetoscr_x_adjust); + /* The problem is that we must call decode_ham() BEFORE we do the + sprites. */ + if (! border && bplham) { + init_ham_decoding (); if (dip_for_drawing->nr_color_changes == 0) { /* The easy case: need to do HAM decoding only once for the * full line. */ - decode_ham6 (linetoscr_x_adjust, linetoscr_right_x); + decode_ham (visible_left_border, visible_right_border); } else /* Argh. */ { adjust_color0_for_color_change (); - do_color_changes (decode_ham6); + do_color_changes (dummy_worker, decode_ham); adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); } } @@ -2014,42 +1456,23 @@ static __inline__ void pfield_draw_line if (dip_for_drawing->nr_sprites != 0) walk_sprites (curr_sprite_positions + dip_for_drawing->first_sprite_draw, dip_for_drawing->nr_sprites); - if (dip_for_drawing->nr_color_changes == 0) { - pfield_do_linetoscr_full (dh == dh_buf ? do_double : 0); - finish_line_aga (); - do_flush_line (gfx_ypos); -#if 0 - if (dh == dh_emerg) - abort (); -#endif - if (do_double) { - /* If dh == dh_line, do_flush_line will re-use the rendered line - * from linemem. If dh == dh_buf, the line will have been doubled - * by pfield_do_linetoscr_full. */ - do_flush_line (follow_ypos); - } - } else { - adjust_color0_for_color_change (); - do_color_changes (pfield_do_linetoscr); - finish_line_aga (); + adjust_color0_for_color_change (); + do_color_changes (pfield_do_fill_line, pfield_do_linetoscr); - if (dh == dh_emerg) - memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes); + if (dh == dh_emerg) + memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes); - do_flush_line (gfx_ypos); - if (do_double) { - if (dh == dh_emerg) - memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes); - else if (dh == dh_buf) - memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); - line_decisions[lineno + 1].which = -2; - do_flush_line (follow_ypos); - } + do_flush_line (gfx_ypos); + if (do_double) { + if (dh == dh_emerg) + memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes); + else if (dh == dh_buf) + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); + line_decisions[lineno + 1].which = -2; + do_flush_line (follow_ypos); } -#ifdef LORES_HACK if (currprefs.gfx_lores == 2) currprefs.gfx_lores = 0; -#endif } else if (border == 1) { adjust_drawing_colors (dp_for_drawing->ctable, 0); @@ -2075,8 +1498,11 @@ static __inline__ void pfield_draw_line return; } + playfield_start = visible_right_border; + playfield_end = visible_right_border; + adjust_color0_for_color_change (); - do_color_changes (pfield_do_fill_line); + do_color_changes (pfield_do_fill_line, pfield_do_fill_line); if (dh == dh_emerg) memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes); @@ -2093,130 +1519,42 @@ static __inline__ void pfield_draw_line line_decisions[lineno + 1].which = -2; } } else { -#if AGA_CHIPSET == 0 xcolnr tmp = colors_for_drawing.acolors[0]; - colors_for_drawing.acolors[0] = xcolors[0]; + colors_for_drawing.acolors[0] = getxcolor (0); fill_line (); do_flush_line (gfx_ypos); colors_for_drawing.acolors[0] = tmp; -#endif } } -#ifdef SUPPORT_PENGUINS -static smp_comm_pipe drawing_pipe; -static uae_sem_t drawing_lock; - -static void *drawing_penguin (void *cruxmedo) -{ - int l; - fprintf (stderr, "Hello, world!\n"); - - for (;;) { - /* Start of a frame. */ - int k; - new_frame: - k = read_comm_pipe_int_blocking (&drawing_pipe); - - switch (k) { - case -2: - /* Hoopy */ - break; - - default: - write_log ("Penguin got out of sync.\n"); - /* what can we do? Try to reduce the damage */ - for (;;) { - k = read_comm_pipe_int_blocking (&drawing_pipe); - if (k == -3) - break; - if (k == -1) { - uae_sem_post (&drawing_lock); - goto new_frame; - } - } - case -3: - UAE_PENGUIN_EXIT; - /* Can't happen */ - return 0; - } - - for (;;) { - int i, where; - int l = read_comm_pipe_int_blocking (&drawing_pipe); - switch (l) { - case -1: - /* End-of-frame synchronization. */ - uae_sem_post (&drawing_lock); - goto new_frame; - case -2: - /* customreset called a bit too often. That's harmless. */ - continue; - case -3: - write_log ("Penguin got out of sync.\n"); - UAE_PENGUIN_EXIT; - return 0; - } - - /* l is the line that has been finished for drawing. */ - i = l - thisframe_y_adjust_real; - if (i < 0 || i >= max_ypos_thisframe) - continue; - - if (linestate[l] == LINE_UNDECIDED) { - fprintf (stderr, "Line scheduled for drawing, but undecided %d!?\n", l); - continue; - } - if (inhibit_frame != 0) - continue; - where = amiga2aspect_line_map[i+min_ypos_for_screen]; - if (where >= gfxvidinfo.height || where == -1) - continue; - - pfield_draw_line (l, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); - } - } -} - -static penguin_id our_penguin; - -static void kill_drawing_penguin (void) -{ - /* ??? does libpthread do that for us? */ -} - -#endif - -static int penguins_enabled_thisframe; - static void center_image (void) { - prev_x_adjust = linetoscr_x_adjust; + prev_x_adjust = visible_left_border; prev_y_adjust = thisframe_y_adjust; if (currprefs.gfx_xcenter) { if (max_diwstop - min_diwstart < gfxvidinfo.width && currprefs.gfx_xcenter == 2) /* Try to center. */ - linetoscr_x_adjust = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1; + visible_left_border = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1; else - linetoscr_x_adjust = max_diwstop - gfxvidinfo.width; + visible_left_border = max_diwstop - gfxvidinfo.width; /* Would the old value be good enough? If so, leave it as it is if we want to * be clever. */ if (currprefs.gfx_xcenter == 2) { - if (linetoscr_x_adjust < prev_x_adjust && prev_x_adjust < min_diwstart) - linetoscr_x_adjust = prev_x_adjust; + if (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart) + visible_left_border = prev_x_adjust; } } else - linetoscr_x_adjust = max_diwlastword - gfxvidinfo.width; - if (linetoscr_x_adjust < 0) - linetoscr_x_adjust = 0; - - linetoscr_x_adjust_bytes = linetoscr_x_adjust * gfxvidinfo.pixbytes; - - linetoscr_right_x = linetoscr_x_adjust + gfxvidinfo.width; - if (linetoscr_right_x > max_diwlastword) - linetoscr_right_x = max_diwlastword; + visible_left_border = max_diwlastword - gfxvidinfo.width; + if (visible_left_border < 0) + visible_left_border = 0; + + linetoscr_x_adjust_bytes = visible_left_border * gfxvidinfo.pixbytes; + + visible_right_border = visible_left_border + gfxvidinfo.width; + if (visible_right_border > max_diwlastword) + visible_right_border = max_diwlastword; thisframe_y_adjust = minfirstline; if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) { @@ -2243,7 +1581,7 @@ static void center_image (void) /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably * better. */ - if (prev_x_adjust != linetoscr_x_adjust || prev_y_adjust != thisframe_y_adjust) + if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust) frame_redraw_necessary |= interlace_seen && currprefs.gfx_linedbl ? 2 : 1; max_diwstop = 0; @@ -2296,12 +1634,6 @@ static void init_drawing_frame (void) thisframe_first_drawn_line = -1; thisframe_last_drawn_line = -1; -#ifdef SUPPORT_PENGUINS - penguins_enabled_thisframe = 1; - /* Tell the other thread that it can now expect data from us. */ - write_comm_pipe_int (&drawing_pipe, -2, 1); - memset (line_drawn, 0, sizeof line_drawn); -#endif drawing_color_matches = -1; } @@ -2310,14 +1642,6 @@ void finish_drawing_frame (void) { int i; -#ifdef SUPPORT_PENGUINS - /* Synchronize with other thread, then see whether there's something left for - * us to draw. @@@ This is probably a big waste of cycles if the two threads - * run at very different speeds - this one could draw stuff as well. */ - write_comm_pipe_int (&drawing_pipe, -1, 1); - uae_sem_wait (&drawing_lock); -#else - #ifndef SMART_UPDATE /* @@@ This isn't exactly right yet. FIXME */ if (!interlace_seen) { @@ -2345,17 +1669,11 @@ void finish_drawing_frame (void) pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); } unlockscr (); -#endif do_flush_screen (first_drawn_line, last_drawn_line); } void hardware_line_completed (int lineno) { -#ifdef SUPPORT_PENGUINS - if (framecnt == 0 && penguins_enabled_thisframe) { - write_comm_pipe_int (&drawing_pipe, lineno, 0); - } -#endif #ifndef SMART_UPDATE { int i, where; @@ -2370,7 +1688,7 @@ void hardware_line_completed (int lineno #endif } -static __inline__ void check_picasso (void) +STATIC_INLINE void check_picasso (void) { #ifdef PICASSO96 if (picasso_on && picasso_redraw_necessary) @@ -2416,11 +1734,6 @@ void vsync_handle_redraw (int long_frame set_inhibit_frame (IHF_QUIT_PROGRAM); regs.spcflags |= SPCFLAG_BRK; filesys_prepare_reset (); -#ifdef SUPPORT_PENGUINS - if (quit_program == 1) - /* Stop eating herring */ - write_comm_pipe_int (&drawing_pipe, -3, 1); -#endif return; } @@ -2486,7 +1799,6 @@ void hsync_record_line_state (int lineno void notice_interlace_seen (void) { interlace_seen = 1; - penguins_enabled_thisframe = 0; } void reset_drawing (void) @@ -2533,12 +1845,5 @@ void drawing_init () line_drawn = 0; gen_pfield_tables(); - -#ifdef SUPPORT_PENGUINS - init_comm_pipe (&drawing_pipe, 800, 5); - uae_sem_init (&drawing_lock, 0, 0); - start_penguin (drawing_penguin, 0, &our_penguin); - /*atexit(kill_drawing_penguin);*/ -#endif }