--- uae/src/drawing.c 2018/04/24 16:48:44 1.1.1.6 +++ uae/src/drawing.c 2018/04/24 17:14:23 1.1.1.18 @@ -3,10 +3,29 @@ * * Screen drawing functions * - * Copyright 1995-1998 Bernd Schmidt + * Copyright 1995-2000 Bernd Schmidt * Copyright 1995 Alessandro Bissacco + * Copyright 2000,2001 Toni Wilen */ +/* 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" @@ -15,39 +34,45 @@ #include "config.h" #include "options.h" -#include "threaddep/penguin.h" +#include "threaddep/thread.h" #include "uae.h" #include "memory.h" #include "custom.h" -#include "readcpu.h" #include "newcpu.h" #include "xwin.h" #include "autoconf.h" #include "gui.h" #include "picasso96.h" #include "drawing.h" -#include "p2c.h" +#include "savestate.h" -#if defined X86_ASSEMBLY -#define LORES_HACK -#endif +int lores_factor, lores_shift; -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; -static int dblpf_ind1[256], dblpf_ind2[256], dblpf_2nd1[256], dblpf_2nd2[256]; -static int dblpf_aga1[256], dblpf_aga2[256], linear_map_256[256], lots_of_twos[256]; +/* Lookup tables for dual playfields. The dblpf_*1 versions are for the case + that playfield 1 has the priority, dbplpf_*2 are used if playfield 2 has + priority. If we need an array for non-dual playfield mode, it has no number. */ +/* The dbplpf_ms? arrays contain a shift value. plf_spritemask is initialized + to contain two 16 bit words, with the appropriate mask if pf1 is in the + foreground being at bit offset 0, the one used if pf2 is in front being at + offset 16. */ -static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; +static int dblpf_ms1[256], dblpf_ms2[256], dblpf_ms[256]; +static int dblpf_ind1[256], dblpf_ind2[256]; -/* Big lookup tables for planar to chunky conversion. */ +static int dblpf_2nd1[256], dblpf_2nd2[256]; +static int dblpf_ind1_aga[256], dblpf_ind2_aga[256]; -uae_u32 hirestab_h[256][2]; -uae_u32 lorestab_h[256][4]; +static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; -uae_u32 hirestab_l[256][1]; -uae_u32 lorestab_l[256][2]; +static int sprite_offs[256]; static uae_u32 clxtab[256]; @@ -56,24 +81,31 @@ 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[MAX_PIXELS_PER_LINE * 2]; + uae_u16 apixels_w[MAX_PIXELS_PER_LINE * 2 / 2]; + uae_u32 apixels_l[MAX_PIXELS_PER_LINE * 2 / 4]; } pixdata; -uae_u32 ham_linebuf[880]; -uae_u32 aga_linebuf[880], *aga_lbufptr; +uae_u16 spixels[2 * MAX_SPR_PIXELS]; +/* Eight bits for every pixel. */ +union sps_union spixstate; + +static uae_u32 ham_linebuf[MAX_PIXELS_PER_LINE * 2]; +static uae_u8 spriteagadpfpixels[MAX_PIXELS_PER_LINE * 2]; /* AGA dualplayfield sprite */ char *xlinebuffer; @@ -81,7 +113,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 @@ -99,23 +131,30 @@ static char linestate[(MAXVPOS + 1)*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; +/* 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; 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, bplres; -static int bpldelay1, bpldelay2; -static int plfpri[3]; + 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, bpldualpf2of, bplplanecnt, bplres; +static uae_u32 plf_sprite_mask; +static int sbasecol[2]; int picasso_requested_on; int picasso_on; @@ -136,9 +175,9 @@ STATIC_INLINE void count_frame (void) 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; + return x + 2*DISPLAY_LEFT_SHIFT - 2*DIW_DDF_OFFSET; } int coord_native_to_amiga_y (int y) @@ -146,6 +185,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 +208,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,322 +221,213 @@ void record_diw_line (int first, int las * Screen update macros/functions */ -static unsigned int ham_lastcolor; +/* 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; -static void init_ham_decoding(int first) +/* 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) { - 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++; + /* First, get data fetch start/stop in DIW coordinates. */ + int ddf_left = dp_for_drawing->plfleft * 2 + DIW_DDF_OFFSET; + int ddf_right = dp_for_drawing->plfright * 2 + DIW_DDF_OFFSET; + /* Compute datafetch start/stop in pixels; native display coordinates. */ + int native_ddf_left = coord_hw_to_window_x (ddf_left); + int native_ddf_right = coord_hw_to_window_x (ddf_right); + + int linetoscr_diw_start = dp_for_drawing->diwfirstword; + int linetoscr_diw_end = dp_for_drawing->diwlastword; + + 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; } -} -static void decode_ham6 (int pix, int stoppos) -{ - uae_u32 *buf = ham_linebuf; + /* Perverse cases happen. */ + if (linetoscr_diw_end < linetoscr_diw_start) + linetoscr_diw_end = linetoscr_diw_start; - if (!bplham || bplplanecnt != 6) - return; + playfield_start = linetoscr_diw_start; + playfield_end = linetoscr_diw_end; - 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; - } + 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. */ + + res_shift = lores_shift - bplres; + ddf_left -= DISPLAY_LEFT_SHIFT; + ddf_left <<= bplres; + pixels_offset = MAX_PIXELS_PER_LINE - ddf_left; - buf[pix++] = ham_lastcolor; - } -} -#if 0 -static void decode_ham_aga (int pix, int stoppos) -{ - static uae_u32 lastcolor; - uae_u32 *buf = ham_linebuf; + unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start; + src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window (playfield_start - native_ddf_left + unpainted); - if (!bplham || (bplplanecnt != 6 && bplplanecnt != 8)) + 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 + MAX_PIXELS_PER_LINE - 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 + MAX_PIXELS_PER_LINE + 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 AGAC 0 +#include "linetoscr.c" +#define LNAME linetoscr_8_stretch1 +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGAC 0 +#include "linetoscr.c" +#define LNAME linetoscr_8_shrink1 +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGAC 0 +#include "linetoscr.c" + +#define LNAME linetoscr_8_aga +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGAC 1 +#include "linetoscr.c" +#define LNAME linetoscr_8_stretch1_aga +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGAC 1 +#include "linetoscr.c" +#define LNAME linetoscr_8_shrink1_aga +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGAC 1 +#include "linetoscr.c" + +#undef TYPE + +#define TYPE uae_u16 +#define LNAME linetoscr_16 +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGAC 0 +#include "linetoscr.c" +#define LNAME linetoscr_16_stretch1 +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGAC 0 +#include "linetoscr.c" +#define LNAME linetoscr_16_shrink1 +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGAC 0 +#include "linetoscr.c" + +#define LNAME linetoscr_16_aga +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGAC 1 +#include "linetoscr.c" +#define LNAME linetoscr_16_stretch1_aga +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGAC 1 +#include "linetoscr.c" +#define LNAME linetoscr_16_shrink1_aga +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGAC 1 +#include "linetoscr.c" + +#undef TYPE + +#define TYPE uae_u32 +#define LNAME linetoscr_32 +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGAC 0 +#include "linetoscr.c" +#define LNAME linetoscr_32_stretch1 +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGAC 0 +#include "linetoscr.c" +#define LNAME linetoscr_32_shrink1 +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGAC 0 +#include "linetoscr.c" + +#define LNAME linetoscr_32_aga +#define SRC_INC 1 +#define HDOUBLE 0 +#define AGAC 1 +#include "linetoscr.c" +#define LNAME linetoscr_32_stretch1_aga +#define SRC_INC 1 +#define HDOUBLE 1 +#define AGAC 1 +#include "linetoscr.c" +#define LNAME linetoscr_32_shrink1_aga +#define SRC_INC 2 +#define HDOUBLE 0 +#define AGAC 1 +#include "linetoscr.c" - 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; - } - } -} -#endif - -static int linetoscr_double_offset; +#undef TYPE -#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) +static void fill_line_8 (char *buf, int start, int stop) { - uae_u32 *buf = aga_lbufptr; + uae_u8 *b = (uae_u8 *)buf; int i; - int xor = (uae_u8)(dp_for_drawing->bplcon4 >> 8); - int oldpix = pix; - - buf -= pix; - - for (i = 0; i < stoppos; i++) - pixdata.apixels[i] ^= xor; - - 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]; - - 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; -} - -static void aga_translate32 (int start, int stop) -{ - memcpy (((uae_u32 *)xlinebuffer) + start, aga_lbufptr, 4*(stop-start)); - aga_lbufptr += stop - start; -} - -static void aga_translate16 (int start, int stop) -{ - 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) { int shift; @@ -490,13 +435,6 @@ STATIC_INLINE void fill_line (void) 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 +444,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,342 +477,194 @@ STATIC_INLINE void fill_line (void) } } -#ifdef X86_ASSEMBLY +static int linetoscr_double_offset; -#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); +static void pfield_do_linetoscr (int start, int stop) +{ + 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 -#endif - pfield_linetoscr_asm8 (pfield_linetoscr_ehb_asm8, pix, lframe_end_1, diw_end_1, stoppos); + abort (); } else { -#ifdef LORES_HACK - if (currprefs.gfx_lores == 2) - pfield_linetoscr_asm8 (pfield_linetoscr_hdouble_asm8, 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_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; + abort (); } } -#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 void pfield_linetoscr_full16 (int pix, int lframe_end, int diw_end, int stoppos) +static void pfield_do_fill_line (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 (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); - else -#endif - pfield_linetoscr_asm16 (pfield_linetoscr_normal_asm16, 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++) - ((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; + 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 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. - * The fuzzy_memset_le32 code won't work for AGA, so skip this part here. - */ - if (dip_for_drawing->nr_sprites == 0 || (currprefs.chipset_mask & CSMASK_AGA)) { - int hiresadjust = RES_ADJUST (bplres); - int ddf_left = (((dp_for_drawing->plfstrt + hiresadjust)*2 - + mindelay - DISPLAY_LEFT_SHIFT) << lores_shift); - int 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 (! bplham || (bplplanecnt != 6 && ((currprefs.chipset_mask & CSMASK_AGA) == 0 || bplplanecnt != 8))) { + if (unpainted_amiga > 0) { + int pv = pixdata.apixels[ham_decode_pixel + unpainted_amiga - 1]; + if (currprefs.chipset_mask & CSMASK_AGA) + ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; + else + ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; + } + } else 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 { - /* Conservative case. */ - int hiresadjust = RES_ADJUST (bplres); - /* 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. */ - int ddf_left = ((dp_for_drawing->plfstrt + hiresadjust)*2 - + maxdelay - DISPLAY_LEFT_SHIFT) << lores_shift; - int 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; + int todraw_amiga = res_shift_from_window (stoppos - pix); - if (lframe_end < start) - lframe_end = start; - if (diw_end > stop) - diw_end = stop; - - if (start >= stop) - return; + if (! bplham || (bplplanecnt != 6 && ((currprefs.chipset_mask & CSMASK_AGA) == 0 || bplplanecnt != 8))) { + while (todraw_amiga-- > 0) { + int pv = pixdata.apixels[ham_decode_pixel]; + if (currprefs.chipset_mask & CSMASK_AGA) + ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; + else + ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; -#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; + ham_linebuf[ham_decode_pixel++] = ham_lastcolor; + } + } else 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 @@ -882,35 +674,22 @@ static void gen_pfield_tables (void) for (i = 0; i < 256; i++) { int plane1 = (i & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8); int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8); + dblpf_2nd1[i] = plane1 == 0 ? (plane2 == 0 ? 0 : 2) : 1; dblpf_2nd2[i] = plane2 == 0 ? (plane1 == 0 ? 0 : 1) : 2; + dblpf_ind1_aga[i] = plane1 == 0 ? plane2 : plane1; + dblpf_ind2_aga[i] = plane2 == 0 ? plane1 : plane2; + + dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0; + dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8; + dblpf_ms[i] = i == 0 ? 16 : 8; if (plane2 > 0) plane2 += 8; dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1); dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2); - lots_of_twos[i] = i == 0 ? 0 : 2; - linear_map_256[i] = i; - } + sprite_offs[i] = (i & 15) ? 0 : 2; - 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) @@ -918,744 +697,290 @@ 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; - -static uae_u32 do_sprite_collisions (struct sprite_draw *spd, int prev_overlap, int i, int nr_spr) -{ - int j; - int sprxp = spd[i].linepos; - uae_u32 datab = spd[i].datab; - uae_u32 mask2 = 0; - int sbit = 1 << spd[i].num; - int sprx_shift = 1; - int attach_compare = -1; - if (currprefs.gfx_lores != 1) - sprx_shift = 0; - - attach_2nd = 0; - if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) - attach_compare = spd[i].num - 1; - - for (j = prev_overlap; j < i; j++) { - uae_u32 mask1; - int off; - - if (spd[i].num < spd[j].num) - continue; - - off = sprxp - spd[j].linepos; - off <<= sprx_shift; - mask1 = spd[j].datab >> off; - - /* If j is an attachment for i, then j doesn't block i */ - if (spd[j].num == attach_compare) { - attach_2nd |= mask1; - } else { - mask1 |= (mask1 & 0xAAAAAAAA) >> 1; - mask1 |= (mask1 & 0x55555555) << 1; - if (datab & mask1) - clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask]; - mask2 |= mask1; - } - } - for (j = i+1; j < nr_spr; j++) { - uae_u32 mask1; - int off = spd[j].linepos - sprxp; - - if (off >= sprite_width || spd[i].num < spd[j].num) - break; - - off <<= sprx_shift; - mask1 = spd[j].datab << off; - - /* If j is an attachment for i, then j doesn't block i */ - if (spd[j].num == attach_compare) { - attach_2nd |= mask1; - } else { - mask1 |= (mask1 & 0xAAAAAAAA) >> 1; - mask1 |= (mask1 & 0x55555555) << 1; - if (datab & mask1) - clxdat |= clxtab[(sbit | (1 << spd[j].num)) & clx_sprmask]; - mask2 |= mask1; - } - } - datab &= ~mask2; - return datab; -} - -STATIC_INLINE void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc) -{ - uae_u32 datcd; - int basecol = 16; - if (!attch) - basecol += (spr & ~1)*2; - if (bpldualpf) - basecol |= 128; - if (attch) - datcd = attach_2nd; - - for(; attch ? datab | datcd : datab; sprxp += sprx_inc) { - int col; - - if (attch) { - col = ((datab & 3) << 2) | (datcd & 3); - datcd >>= 2; - } else - col = datab & 3; - datab >>= 2; - if (col) { - col |= basecol; - if (ham) { - col = colors_for_drawing.color_regs[col]; - ham_linebuf[sprxp] = col; - if (sprx_inc == 2) { - ham_linebuf[sprxp+1] = col; - } - } else { - pixdata.apixels[sprxp] = col; - if (sprx_inc == 2) { - pixdata.apixels[sprxp+1] = col; - } - } - } - } -} - -static void walk_sprites (struct sprite_draw *spd, int nr_spr) -{ - int i, prev_overlap; - int last_sprite_pos = -64; - uae_u32 plane1 = 0, plane2 = 0; - int sprx_inc = 1, sprx_shift = 1; - - if (currprefs.gfx_lores == 0) - sprx_inc = 2, sprx_shift = 0; - - prev_overlap = 0; - for (i = 0; i < nr_spr; i++) { - int sprxp = spd[i].linepos; - int m = 1 << spd[i].num; - uae_u32 datab; - while (prev_overlap < i && spd[prev_overlap].linepos + sprite_width <= sprxp) - 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; - int ok2; - if (ok <= 0) { - ok = ok2 = 0; - plane1 = 0; - plane2 = 0; - } else { - ok2 = ok << sprx_shift; - plane1 >>= 32 - ok2; - plane2 >>= 32 - ok2; - } - last_sprite_pos = sprxp; - - if (bpldualpf) { - uae_u32 mask = 3 << ok2; - int p = sprxp+ok; - - for (; mask; mask <<= 2, p += sprx_inc) { - int data = pixdata.apixels[p]; - if (dblpf_2nd2[data] == 2) - plane2 |= mask; - if (dblpf_2nd1[data] == 1) - plane1 |= mask; - } - } else { - uae_u32 mask = 3 << ok2; - int p = sprxp+ok; +/* When looking at this function and the ones that inline it, bear in mind + what an optimizing compiler will do with this code. All callers of this + function only pass in constant arguments (except for E). This means + that many of the if statements will go away completely after inlining. */ +STATIC_INLINE void draw_sprites_1 (struct sprite_entry *e, int ham, int dualpf, + int doubling, int skip, int has_attach, int aga) +{ + int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms; + uae_u16 *buf = spixels + e->first_pixel; + uae_u8 *stbuf = spixstate.bytes + e->first_pixel; + int pos, window_pos; + uae_u8 xor_val = (uae_u8)(dp_for_drawing->bplcon4 >> 8); + + buf -= e->pos; + stbuf -= e->pos; + + window_pos = e->pos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << (aga ? 1 : 0)); + if (skip) + window_pos >>= 1; + else if (doubling) + window_pos <<= 1; + window_pos += pixels_offset; + for (pos = e->pos; pos < e->max; pos += 1 << skip) { + int maskshift, plfmask; + unsigned int v = buf[pos]; + + /* The value in the shift lookup table is _half_ the shift count we + need. This is because we can't shift 32 bits at once (undefined + behaviour in C). */ + maskshift = shift_lookup[pixdata.apixels[window_pos]]; + plfmask = (plf_sprite_mask >> maskshift) >> maskshift; + v &= ~plfmask; + if (v != 0) { + unsigned int vlo, vhi, col; + unsigned int v1 = v & 255; + /* OFFS determines the sprite pair with the highest priority that has + any bits set. E.g. if we have 0xFF00 in the buffer, we have sprite + pairs 01 and 23 cleared, and pairs 45 and 67 set, so OFFS will + have a value of 4. + 2 * OFFS is the bit number in V of the sprite pair, and it also + happens to be the color offset for that pair. */ + int offs; + if (v1 == 0) + offs = 4 + sprite_offs[v >> 8]; + else + offs = sprite_offs[v1]; - for (; mask; mask <<= 2, p += sprx_inc) { - if (pixdata.apixels[p]) - plane2 |= mask; - } - } - } - if (bpldualpf && m >= plfpri[1]) { - datab &= ~plane1; - attach_2nd &= ~plane1; - } - if (m >= plfpri[2]) { - datab &= ~plane2; - attach_2nd &= ~plane2; - } - } - if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) { - /* Attached sprite */ - if (bplham) { - if (sprx_inc == 1) { - render_sprite (spd[i].num, sprxp, datab, 1, 1, 1); - } else { - render_sprite (spd[i].num, sprxp, datab, 1, 1, 2); - } + /* Shift highest priority sprite pair down to bit zero. */ + v >>= offs * 2; + v &= 15; + + if (has_attach && (stbuf[pos] & (1 << offs))) { + col = v; + if (aga) + col += sbasecol[1]; + else + col += 16; } else { - if (sprx_inc == 1) { - render_sprite (spd[i].num, sprxp, datab, 0, 1, 1); + /* This sequence computes the correct color value. We have to select + either the lower-numbered or the higher-numbered sprite in the pair. + We have to select the high one if the low one has all bits zero. + If the lower-numbered sprite has any bits nonzero, (VLO - 1) is in + the range of 0..2, and with the mask and shift, VHI will be zero. + If the lower-numbered sprite is zero, (VLO - 1) is a mask of + 0xFFFFFFFF, and we select the bits of the higher numbered sprite + in VHI. + This is _probably_ more efficient than doing it with branches. */ + vlo = v & 3; + vhi = (v & (vlo - 1)) >> 2; + col = (vlo | vhi); + if (aga) { + if (vhi > 0) + col += sbasecol[1]; + else + col += sbasecol[0]; } else { - render_sprite (spd[i].num, sprxp, datab, 0, 1, 2); + col += 16; } + col += (offs * 2); } - /* This still leaves one attached sprite bug, but at the moment I'm too lazy */ - 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 (sprx_inc == 1) { - render_sprite (spd[i].num, sprxp, datab, 1, 0, 1); + if (dualpf) { + if (aga) { + spriteagadpfpixels[window_pos] = col; + if (doubling) + spriteagadpfpixels[window_pos + 1] = col; } else { - render_sprite (spd[i].num, sprxp, datab, 1, 0, 2); + col += 128; + if (doubling) + pixdata.apixels_w[window_pos >> 1] = col | (col << 8); + else + pixdata.apixels[window_pos] = col; } + } else if (ham) { + col = color_reg_get (&colors_for_drawing, col); + if (aga) + col ^= xor_val; + ham_linebuf[window_pos] = col; + if (doubling) + ham_linebuf[window_pos + 1] = col; } else { - if (sprx_inc == 1) { - render_sprite (spd[i].num, sprxp, datab, 0, 0, 1); - } else { - render_sprite (spd[i].num, sprxp, datab, 0, 0, 2); - } - } - } - } -} - -#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 (bplres == RES_HIRES) { - 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 (bplres == RES_HIRES) { - 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; - } - } + if (aga) + col ^= xor_val; + if (doubling) + pixdata.apixels_w[window_pos >> 1] = col | (col << 8); + else + pixdata.apixels[window_pos] = col; + } + } + window_pos += 1 << doubling; } } -#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; +/* See comments above. Do not touch if you don't know what's going on. + * (We do _not_ want the following to be inlined themselves). */ +/* lores bitplane, lores sprites */ +static void NOINLINE draw_sprites_normal_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 0, 0, 0); } +static void NOINLINE draw_sprites_normal_dp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 0, 0, 0); } +static void NOINLINE draw_sprites_ham_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 0, 0, 0); } +static void NOINLINE draw_sprites_normal_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 0, 1, 0); } +static void NOINLINE draw_sprites_normal_dp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 0, 1, 0); } +static void NOINLINE draw_sprites_ham_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 0, 1, 0); } +/* hires bitplane, lores sprites */ +static void NOINLINE draw_sprites_normal_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 0, 0, 0); } +static void NOINLINE draw_sprites_normal_dp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 0, 0, 0); } +static void NOINLINE draw_sprites_ham_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 0, 0, 0); } +static void NOINLINE draw_sprites_normal_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 0, 1, 0); } +static void NOINLINE draw_sprites_normal_dp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 0, 1, 0); } +static void NOINLINE draw_sprites_ham_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 0, 1, 0); } + +/* not very optimized */ +STATIC_INLINE void draw_sprites_aga (struct sprite_entry *e) +{ + int diff = RES_HIRES - bplres; + if (diff > 0) + draw_sprites_1 (e, dp_for_drawing->ham_seen, bpldualpf, 0, diff, e->has_attached, 1); + else + draw_sprites_1 (e, dp_for_drawing->ham_seen, bpldualpf, -diff, 0, e->has_attached, 1); } -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) +STATIC_INLINE void draw_sprites_ecs (struct sprite_entry *e) { - uae_u32 *pixptr = (uae_u32 *)dp; - - *pixptr = hirestab_l[data >> 8][0] << bit; - *(pixptr+1) = hirestab_l[data & 255][0] << bit; -} + if (e->has_attached) + if (bplres == 1) + if (dp_for_drawing->ham_seen) + draw_sprites_ham_sp_hi_at (e); + else + if (bpldualpf) + draw_sprites_normal_dp_hi_at (e); + else + draw_sprites_normal_sp_hi_at (e); + else + if (dp_for_drawing->ham_seen) + draw_sprites_ham_sp_lo_at (e); + else + if (bpldualpf) + draw_sprites_normal_dp_lo_at (e); + else + draw_sprites_normal_sp_lo_at (e); + else + if (bplres == 1) + if (dp_for_drawing->ham_seen) + draw_sprites_ham_sp_hi_nat (e); + else + if (bpldualpf) + draw_sprites_normal_dp_hi_nat (e); + else + draw_sprites_normal_sp_hi_nat (e); + else + if (dp_for_drawing->ham_seen) + draw_sprites_ham_sp_lo_nat (e); + else + if (bpldualpf) + draw_sprites_normal_dp_lo_nat (e); + else + draw_sprites_normal_sp_lo_nat (e); +} + + +#define MERGE(a,b,mask,shift) do {\ + uae_u32 tmp = mask & (a ^ (b >> shift)); \ + a ^= tmp; \ + b ^= (tmp << shift); \ +} while (0) + +#define GETLONG(P) (*(uae_u32 *)P) + +/* We use the compiler's inlining ability to ensure that PLANES is in effect a compile time + constant. 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 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]); real_bplpt[7] += 4; + case 7: b1 = GETLONG ((uae_u32 *)real_bplpt[6]); real_bplpt[6] += 4; + case 6: b2 = GETLONG ((uae_u32 *)real_bplpt[5]); real_bplpt[5] += 4; + case 5: b3 = GETLONG ((uae_u32 *)real_bplpt[4]); real_bplpt[4] += 4; + case 4: b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4; + case 3: b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4; + case 2: b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4; + case 1: b7 = GETLONG ((uae_u32 *)real_bplpt[0]); 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 NOINLINE pfield_doline_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 1); } +static void NOINLINE pfield_doline_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 2); } +static void NOINLINE pfield_doline_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 3); } +static void NOINLINE pfield_doline_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 4); } +static void NOINLINE pfield_doline_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 5); } +static void NOINLINE pfield_doline_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 6); } +static void NOINLINE pfield_doline_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 7); } +static void NOINLINE pfield_doline_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 8); } -STATIC_INLINE void pfield_setword_lores_l(int data, unsigned char *dp, int bit) +static void pfield_doline (int lineno) { - 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); \ -} + int wordcount = dp_for_drawing->plflinelen; + uae_u32 *data = pixdata.apixels_l + MAX_PIXELS_PER_LINE/4; #ifdef SMART_UPDATE -#define DATA_POINTER(n) (dataptr + (n)*MAX_WORDS_PER_LINE*2) -#else -#define DATA_POINTER(n) (real_bplpt[n]) -#endif - -static void pfield_doline_aligned_h (int lineno) -{ - int xpos = dp_for_drawing->plfstrt * 4 - DISPLAY_LEFT_SHIFT * 2; - - if (bplres == RES_HIRES) { - 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)); - } - } -} - -static void pfield_doline_aligned_l (int lineno) -{ - int xpos = dp_for_drawing->plfstrt * 2 - DISPLAY_LEFT_SHIFT; - - if (bplres == RES_HIRES) { - 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)); - } - } -} - -#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 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 stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos; - int j; - startpos = PIXEL_XPOS (startpos + RES_ADJUST (bplres)); - stoppos = PIXEL_XPOS (stoppos + RES_ADJUST (bplres)); - if (currprefs.gfx_lores == 0) - delay1 <<= 1, delay2 <<= 1; - else if (currprefs.gfx_lores == 2) - startpos >>= 1, stoppos >>= 1; - for (j = startpos-1; j >= stoppos; j--) { - pixdata.apixels [j] = (pixdata.apixels[j-delay1] & 0x55) | (pixdata.apixels[j-delay2] & 0xAA); - } +#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 + + switch (bplplanecnt) { + default: break; + case 0: memset (data, 0, wordcount * 32); break; + case 1: pfield_doline_n1 (data, wordcount); break; + case 2: pfield_doline_n2 (data, wordcount); break; + case 3: pfield_doline_n3 (data, wordcount); break; + case 4: pfield_doline_n4 (data, wordcount); break; + case 5: pfield_doline_n5 (data, wordcount); break; + case 6: pfield_doline_n6 (data, wordcount); break; + case 7: pfield_doline_n7 (data, wordcount); break; + case 8: pfield_doline_n8 (data, wordcount); break; } } @@ -1696,7 +1021,7 @@ static void init_aspect_maps (void) 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) @@ -1753,7 +1078,7 @@ static void do_flush_line_1 (int lineno) last_drawn_line = lineno; if (gfxvidinfo.maxblocklines == 0) - flush_line(lineno); + flush_line (lineno); else { if ((last_block_line+1) != lineno) { if (first_block_line != -2) @@ -1770,12 +1095,7 @@ static void do_flush_line_1 (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 } /* @@ -1786,14 +1106,6 @@ STATIC_INLINE void do_flush_line (int li 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) */ @@ -1801,87 +1113,81 @@ STATIC_INLINE void do_flush_screen (int if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) { flush_block (first_block_line, last_block_line); } + unlockscr (); if (start <= stop) 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; -static void adjust_drawing_colors (int ctable, int bplham) +/* 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 need_full) { -#if AGA_CHIPSET == 0 if (drawing_color_matches != ctable) { - if (bplham) { - memcpy (&colors_for_drawing, curr_color_tables + ctable, - sizeof colors_for_drawing); + if (need_full) { + 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); + } else if (need_full && color_match_type != color_match_full) { + 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) -{ - 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 - } } -/* 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 - -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); - 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 + nextpos = coord_hw_to_window_x (curr_color_changes[i].linepos * 2); + + 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 (nextpos > lastpos) { - lastpos = nextpos; - if (lastpos >= linetoscr_right_x) - break; + if (i != dip_for_drawing->last_color_change) { + if (regno == -1) + bplham = value; + else { + color_reg_set (&colors_for_drawing, regno, value); + colors_for_drawing.acolors[regno] = getxcolor (value); + } } + if (lastpos >= visible_right_border) + break; } } @@ -1890,25 +1196,27 @@ STATIC_INLINE void do_color_changes (lin * form. */ static void pfield_expand_dp_bplcon (void) { - 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; - plfpri[1] = 1 << 2*(dp_for_drawing->bplcon2 & 7); - plfpri[2] = 1 << 2*((dp_for_drawing->bplcon2 >> 3) & 7); + int plf1pri, plf2pri; + bplres = dp_for_drawing->bplres; + bplplanecnt = dp_for_drawing->nr_planes; + bplham = dp_for_drawing->ham_at_start; + + 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; + } + plf1pri = dp_for_drawing->bplcon2 & 7; + plf2pri = (dp_for_drawing->bplcon2 >> 3) & 7; + plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri); + plf_sprite_mask |= (0xFFFF << (4 * plf1pri)) & 0xFFFF; bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400; bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40; + bpldualpf2of = (dp_for_drawing->bplcon3 >> 10) & 7; + sbasecol[0] = ((dp_for_drawing->bplcon4 >> 4) & 15) << 4; + sbasecol[1] = ((dp_for_drawing->bplcon4 >> 0) & 15) << 4; } enum double_how { @@ -1919,6 +1227,7 @@ enum double_how { 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; @@ -1926,41 +1235,33 @@ STATIC_INLINE void pfield_draw_line (int 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++; - } - line_decisions[lineno].which = -2; + case LINE_REMEMBERED_AS_PREVIOUS: + if (!warned) + write_log ("Shouldn't get here... this is a bug.\n"), warned++; return; - case LINE_BLACK: - line_decisions[lineno].which = -2; + case LINE_BLACK: 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) + if (dp_for_drawing->plfleft == -1) border = 1; - line_decisions[lineno].which = -2; linestate[lineno] = LINE_DONE_AS_PREVIOUS; break; - case LINE_DONE_AS_PREVIOUS: - line_decisions[lineno].which = -2; + case LINE_DONE_AS_PREVIOUS: /* fall through */ - case LINE_DONE: + case LINE_DONE: return; - case LINE_DECIDED_DOUBLE: - line_decisions[lineno+1].which = -2; + case LINE_DECIDED_DOUBLE: if (follow_ypos != -1) { do_double = 1; linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos); @@ -1968,8 +1269,8 @@ STATIC_INLINE void pfield_draw_line (int } /* fall through */ - default: - if (dp_for_drawing->which != 1) + default: + if (dp_for_drawing->plfleft == -1) border = 1; linestate[lineno] = LINE_DONE; break; @@ -1977,100 +1278,66 @@ STATIC_INLINE void pfield_draw_line (int dh = dh_line; xlinebuffer = gfxvidinfo.linemem; - if (xlinebuffer == 0 && do_double && border != 2 && dip_for_drawing->nr_color_changes != 0) + if (xlinebuffer == 0 && do_double + && (border == 0 || (border != 1 && dip_for_drawing->nr_color_changes > 0))) xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg; if (xlinebuffer == 0) xlinebuffer = row_map[gfx_ypos], dh = dh_buf; xlinebuffer -= linetoscr_x_adjust_bytes; - aga_lbufptr = aga_linebuf; if (border == 0) { pfield_expand_dp_bplcon (); -#ifdef LORES_HACK - if (gfxvidinfo.can_double && bplres == RES_LORES && !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); - } + pfield_doline (lineno); - /* Check color0 adjust only if we have color changes - shouldn't happen - * otherwise. */ - adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); + adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || 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 && dp_for_drawing->ham_seen) { + 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); - adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); + do_color_changes (dummy_worker, decode_ham); + adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb); } + bplham = dp_for_drawing->ham_at_start; } - 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); + { + int i; + for (i = 0; i < dip_for_drawing->nr_sprites; i++) { + if (currprefs.chipset_mask & CSMASK_AGA) + draw_sprites_aga (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i); + else + draw_sprites_ecs (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i); } - } else { - adjust_color0_for_color_change (); - do_color_changes (pfield_do_linetoscr); - finish_line_aga (); + } - if (dh == dh_emerg) - memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes); + 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.pixbytes * gfxvidinfo.width); - 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.pixbytes * gfxvidinfo.width); + else if (dh == dh_buf) + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.pixbytes * gfxvidinfo.width); + 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); - /* Check color0 adjust only if we have color changes - shouldn't happen - * otherwise. */ - if (dip_for_drawing->nr_color_changes == 0) { fill_line (); do_flush_line (gfx_ypos); @@ -2090,148 +1357,61 @@ STATIC_INLINE void pfield_draw_line (int return; } - adjust_color0_for_color_change (); - do_color_changes (pfield_do_fill_line); + playfield_start = visible_right_border; + playfield_end = visible_right_border; + + 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); + memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.width); do_flush_line (gfx_ypos); if (do_double) { if (dh == dh_emerg) - memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes); + memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.width); else if (dh == dh_buf) - memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.rowbytes); + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.pixbytes * gfxvidinfo.width); /* If dh == dh_line, do_flush_line will re-use the rendered line * from linemem. */ do_flush_line (follow_ypos); - 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_y_adjust = thisframe_y_adjust; + int prev_x_adjust = visible_left_border; + int 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) { @@ -2258,7 +1438,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; @@ -2271,11 +1451,6 @@ static void init_drawing_frame (void) init_hardware_for_drawing_frame (); - if (max_diwstop == 0) - max_diwstop = diwlastword; - if (min_diwstart > max_diwstop) - min_diwstart = 0; - if (thisframe_first_drawn_line == -1) thisframe_first_drawn_line = minfirstline; if (thisframe_first_drawn_line > thisframe_last_drawn_line) @@ -2311,66 +1486,189 @@ 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; } +/* + * Some code to put status information on the screen. + */ + +#define TD_PADX 10 +#define TD_PADY 2 +#define TD_WIDTH 32 +#define TD_LED_WIDTH 24 +#define TD_LED_HEIGHT 4 + +#define TD_RIGHT 1 +#define TD_BOTTOM 2 + +static int td_pos = (TD_RIGHT|TD_BOTTOM); + +#define TD_NUM_WIDTH 7 +#define TD_NUM_HEIGHT 7 + +#define TD_TOTAL_HEIGHT (TD_PADY * 2 + TD_NUM_HEIGHT) + +#define NUMBERS_NUM 14 + +static char *numbers = { /* ugly */ +"+++++++--++++-+++++++++++++++++-++++++++++++++++++++++++++++++++++++++++++++-++++++-++++----++---+" +"+xxxxx+--+xx+-+xxxxx++xxxxx++x+-+x++xxxxx++xxxxx++xxxxx++xxxxx++xxxxx++xxxx+-+x++x+-+xxx++-+xx+-+x" +"+x+++x+--++x+-+++++x++++++x++x+++x++x++++++x++++++++++x++x+++x++x+++x++x++++-+x++x+-+x++x+--+x++x+" +"+x+-+x+---+x+-+xxxxx++xxxxx++xxxxx++xxxxx++xxxxx+--++x+-+xxxxx++xxxxx++x+----+xxxx+-+x++x+----+x+-" +"+x+++x+---+x+-+x++++++++++x++++++x++++++x++x+++x+--+x+--+x+++x++++++x++x++++-+x++x+-+x++x+---+x+x+" +"+xxxxx+---+x+-+xxxxx++xxxxx+----+x++xxxxx++xxxxx+--+x+--+xxxxx++xxxxx++xxxx+-+x++x+-+xxx+---+x++xx" +"+++++++---+++-++++++++++++++----+++++++++++++++++--+++--++++++++++++++++++++-++++++-++++----------" +}; + +STATIC_INLINE void putpixel (int x, xcolnr c8) +{ + switch(gfxvidinfo.pixbytes) + { + case 1: + xlinebuffer[x] = (uae_u8)c8; + break; + case 2: + { + uae_u16 *p = (uae_u16 *)xlinebuffer + x; + *p = (uae_u16)c8; + break; + } + case 3: + /* no 24 bit yet */ + break; + case 4: + { + uae_u32 *p = (uae_u32 *)xlinebuffer + x; + *p = c8; + break; + } + } +} + +static void write_tdnumber (int x, int y, int num) +{ + int j; + uae_u8 *numptr; + + numptr = numbers + num * TD_NUM_WIDTH + NUMBERS_NUM * TD_NUM_WIDTH * y; + for (j = 0; j < TD_NUM_WIDTH; j++) { + if (*numptr == 'x') + putpixel (x + j, xcolors[0xfff]); + else if (*numptr == '+') + putpixel (x + j, xcolors[0x000]); + numptr++; + } +} + +static void draw_status_line (int line) +{ + int x_start, y, j, led; + + if (td_pos & TD_RIGHT) + x_start = gfxvidinfo.width - TD_PADX - 5 * TD_WIDTH; + else + x_start = TD_PADX; + + y = line - (gfxvidinfo.height - TD_TOTAL_HEIGHT); + xlinebuffer = gfxvidinfo.linemem; + if (xlinebuffer == 0) + xlinebuffer = row_map[line]; + + memset (xlinebuffer, 0, gfxvidinfo.width * gfxvidinfo.pixbytes); + + for (led = 0; led < 5; led++) { + int side, pos, num1 = -1, num2 = -1, num3 = -1, num4 = -1, x, off_rgb, on_rgb, c, on = 0; + if (led > 0) { + int pled = led - 1; + int track = gui_data.drive_track[pled]; + pos = 1 + pled; + on_rgb = 0x0c0; + off_rgb = 0x030; + if (1 /*!gui_data.drive_disabled[pled]*/) { + num1 = -1; + num2 = track / 10; + num3 = track % 10; + on = gui_data.drive_motor[pled]; + if (gui_data.drive_writing[pled]) + on_rgb = 0xc00; + } + /*side = gui_data.drive_side;*/ + } else { + pos = 0; + on = gui_data.powerled; + on_rgb = 0xc00; + off_rgb = 0x300; + } + c = xcolors[on ? on_rgb : off_rgb]; + + x = x_start + pos * TD_WIDTH; + for (j = 0; j < TD_LED_WIDTH; j++) + putpixel (x + j, c); + + if (y >= TD_PADY && y - TD_PADY < TD_NUM_HEIGHT) { + if (num3 >= 0) { + int tn = num1 > 0 ? 3 : 2; + int offs = (TD_LED_WIDTH - tn * TD_NUM_WIDTH) / 2; + if (num1 > 0) { + write_tdnumber (x + offs, y - TD_PADY, num1); + offs += TD_NUM_WIDTH; + } + write_tdnumber (x + offs, y - TD_PADY, num2); + write_tdnumber (x + offs + TD_NUM_WIDTH, y - TD_PADY, num3); + if (num4 > 0) + write_tdnumber (x + offs + 2 * TD_NUM_WIDTH, y - TD_PADY, num4); + } + } + } +} + 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 + if (! lockscr ()) { + notice_screen_contents_lost (); + return; + } #ifndef SMART_UPDATE /* @@@ This isn't exactly right yet. FIXME */ - if (!interlace_seen) { + if (!interlace_seen) do_flush_screen (first_drawn_line, last_drawn_line); - return; - } + else + unlockscr (); + return; #endif - if (! lockscr ()) { - notice_screen_contents_lost (); - return; - } for (i = 0; i < max_ypos_thisframe; i++) { int where; + int i1 = i + min_ypos_for_screen; int line = i + thisframe_y_adjust_real; if (linestate[line] == LINE_UNDECIDED) break; - where = amiga2aspect_line_map[i+min_ypos_for_screen]; - if (where >= gfxvidinfo.height) + where = amiga2aspect_line_map[i1]; + if (where >= gfxvidinfo.height - (currprefs.leds_on_screen ? TD_TOTAL_HEIGHT : 0)) break; if (where == -1) continue; - pfield_draw_line (line, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]); + pfield_draw_line (line, where, amiga2aspect_line_map[i1 + 1]); + } + if (currprefs.leds_on_screen) { + for (i = 0; i < TD_TOTAL_HEIGHT; i++) { + int line = gfxvidinfo.height - TD_TOTAL_HEIGHT + i; + draw_status_line (line); + do_flush_line (line); + } } - 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; @@ -2426,16 +1724,21 @@ void vsync_handle_redraw (int long_frame * done at other times. */ + if (savestate_state == STATE_DOSAVE) { + custom_prepare_savestate (); + savestate_state = STATE_SAVE; + save_state (savestate_filename, "Description!"); + savestate_state = 0; + } else if (savestate_state == STATE_DORESTORE) { + savestate_state = STATE_RESTORE; + uae_reset (0); + } + if (quit_program < 0) { quit_program = -quit_program; set_inhibit_frame (IHF_QUIT_PROGRAM); - regs.spcflags |= SPCFLAG_BRK; + set_special (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; } @@ -2501,7 +1804,6 @@ void hsync_record_line_state (int lineno void notice_interlace_seen (void) { interlace_seen = 1; - penguins_enabled_thisframe = 0; } void reset_drawing (void) @@ -2521,7 +1823,6 @@ void reset_drawing (void) lores_factor = currprefs.gfx_lores ? 1 : 2; lores_shift = currprefs.gfx_lores ? 0 : 1; - sprite_width = currprefs.gfx_lores ? 16 : 32; /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */ for (i = 0; i < sizeof linestate / sizeof *linestate; i++) @@ -2538,6 +1839,9 @@ void reset_drawing (void) last_redraw_point = 0; + memset (spixels, 0, sizeof spixels); + memset (&spixstate, 0, sizeof spixstate); + init_drawing_frame (); } @@ -2548,12 +1852,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 }