--- uae/src/drawing.c 2018/04/24 16:51:28 1.1.1.8 +++ uae/src/drawing.c 2018/04/24 17:14:23 1.1.1.18 @@ -5,6 +5,7 @@ * * 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. @@ -33,19 +34,19 @@ #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 "savestate.h" -int lores_factor, lores_shift, sprite_width; +int lores_factor, lores_shift; /* The shift factor to apply when converting between Amiga coordinates and window coordinates. Zero if the resolution is the same, positive if window coordinates @@ -55,11 +56,24 @@ 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 dblpf_ms1[256], dblpf_ms2[256], dblpf_ms[256]; +static int dblpf_ind1[256], dblpf_ind2[256]; + +static int dblpf_2nd1[256], dblpf_2nd2[256]; +static int dblpf_ind1_aga[256], dblpf_ind2_aga[256]; static int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 }; +static int sprite_offs[256]; + static uae_u32 clxtab[256]; /* Video buffer description structure. Filled in by the graphics system @@ -67,9 +81,10 @@ 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; @@ -80,12 +95,17 @@ union { /* Let's try to align this thing. */ double uupzuq; long int cruxmedo; - uae_u8 apixels[1760]; - uae_u16 apixels_w[880]; - uae_u32 apixels_l[440]; + 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[1760]; +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; @@ -93,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 @@ -112,12 +132,12 @@ static char linestate[(MAXVPOS + 1)*2 + uae_u8 line_data[(MAXVPOS + 1) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]; /* Centering variables. */ -static int min_diwstart, max_diwstop, prev_x_adjust; +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; @@ -132,9 +152,9 @@ static int first_block_line, last_block_ /* These are generated by the drawing code from the line_decisions array for each line that needs to be drawn. These are basically extracted out of bit fields in the hardware registers. */ -static int bplehb, bplham, bpldualpf, bpldualpfpri, bplplanecnt, bplres; -static int bpldelay1, bpldelay2; -static int plfpri[3]; +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; @@ -157,7 +177,7 @@ int coord_native_to_amiga_x (int x) { 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) @@ -217,16 +237,12 @@ static int unpainted; * borders. */ static void pfield_init_linetoscr (void) { - int delay_changes = dip_for_drawing->last_delay_change != dip_for_drawing->first_delay_change; - int mindelay = delay_changes ? 0 : bpldelay1 > bpldelay2 ? bpldelay2 : bpldelay1; - int maxdelay = delay_changes ? 15 : bpldelay1 < bpldelay2 ? bpldelay2 : bpldelay1; - int hiresadjust = RES_ADJUST (bplres); /* First, get data fetch start/stop in DIW coordinates. */ - int ddf_left = (dp_for_drawing->plfstrt + hiresadjust) * 2; - int ddf_right = (dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust) * 2; + 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 + mindelay); - int native_ddf_right = coord_hw_to_window_x (ddf_right + maxdelay); + 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; @@ -256,16 +272,13 @@ static void pfield_init_linetoscr (void) /* Now, compute some offsets. */ - /* Convert ddf_left/ddf_right into Amiga coordinate system used by the - sprite drawing code. */ - ddf_left = ddf_left + mindelay - DISPLAY_LEFT_SHIFT; - if (currprefs.gfx_lores == 0) - ddf_left <<= 1; - res_shift = lores_shift - bplres; - pixels_offset = 880 - ddf_left; + ddf_left -= DISPLAY_LEFT_SHIFT; + ddf_left <<= bplres; + pixels_offset = MAX_PIXELS_PER_LINE - ddf_left; + unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start; - src_pixel = 880 + res_shift_from_window (playfield_start - native_ddf_left + unpainted); + src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window (playfield_start - native_ddf_left + unpainted); if (dip_for_drawing->nr_sprites == 0) return; @@ -273,13 +286,13 @@ static void pfield_init_linetoscr (void) if (linetoscr_diw_start < native_ddf_left) { int size = res_shift_from_window (native_ddf_left - linetoscr_diw_start); linetoscr_diw_start = native_ddf_left; - memset (pixdata.apixels + 880 - size, 0, size); + 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 + 880 + pos, 0, size); + memset (pixdata.apixels + MAX_PIXELS_PER_LINE + pos, 0, size); } } @@ -289,46 +302,107 @@ static void pfield_init_linetoscr (void) #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 LNAME linetoscr_8_stretch1 +#define AGAC 0 #include "linetoscr.c" +#define LNAME linetoscr_8_shrink1 #define SRC_INC 2 #define HDOUBLE 0 -#define LNAME linetoscr_8_shrink1 +#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 LNAME linetoscr_16_stretch1 +#define AGAC 0 #include "linetoscr.c" +#define LNAME linetoscr_16_shrink1 #define SRC_INC 2 #define HDOUBLE 0 -#define LNAME linetoscr_16_shrink1 +#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 LNAME linetoscr_32_stretch1 +#define AGAC 0 #include "linetoscr.c" +#define LNAME linetoscr_32_shrink1 #define SRC_INC 2 #define HDOUBLE 0 -#define LNAME linetoscr_32_shrink1 +#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" +#undef TYPE + static void fill_line_8 (char *buf, int start, int stop) { uae_u8 *b = (uae_u8 *)buf; @@ -372,6 +446,8 @@ STATIC_INLINE void fill_line (void) nints &= ~7; 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; @@ -405,26 +481,49 @@ static int linetoscr_double_offset; static void pfield_do_linetoscr (int start, int stop) { - 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 - abort (); + if (currprefs.chipset_mask & CSMASK_AGA) { + if (res_shift == 0) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8_aga (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_aga (src_pixel, start, stop); break; + } + else if (res_shift == 1) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8_stretch1_aga (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16_stretch1_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_stretch1_aga (src_pixel, start, stop); break; + } + else if (res_shift == -1) + switch (gfxvidinfo.pixbytes) { + case 1: src_pixel = linetoscr_8_shrink1_aga (src_pixel, start, stop); break; + case 2: src_pixel = linetoscr_16_shrink1_aga (src_pixel, start, stop); break; + case 4: src_pixel = linetoscr_32_shrink1_aga (src_pixel, start, stop); break; + } + else + abort (); + } else { + 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 + abort (); + } } static void pfield_do_fill_line (int start, int stop) @@ -457,39 +556,109 @@ static int ham_decode_pixel; /* 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_ham6 runs. */ + 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 = colors_for_drawing.color_regs[0]; - while (unpainted_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel++]; - 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; + 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 { + 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; + } + } } } } -static void decode_ham6 (int pix, int stoppos) +static void decode_ham (int pix, int stoppos) { int todraw_amiga = res_shift_from_window (stoppos - pix); - if (!bplham || bplplanecnt != 6) - abort (); - while (todraw_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel]; - 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 (! 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]; + + 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 { + 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; + } } - - ham_linebuf[ham_decode_pixel++] = ham_lastcolor; } } @@ -505,15 +674,21 @@ 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; clxtab[i] = ((((i & 3) && (i & 12)) << 9) | (((i & 3) && (i & 48)) << 10) @@ -524,247 +699,211 @@ static void gen_pfield_tables (void) } } -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; -} - -/* We use the compiler's inlining ability to ensure that HAM, ATTCH and - SPRX_INC are in effect compile time constants. That will cause some - unnecessary code to be optimized away. - Don't touch this if you don't know what you are doing. */ -static void render_sprite (int spr, int sprxp, uae_u32 datab, int ham, int attch, int sprx_inc) -{ - uae_u32 datcd; - int basecol = 16; - 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 + pixels_offset] = col; - if (sprx_inc == 2) { - ham_linebuf[sprxp + pixels_offset + 1] = col; - } +/* 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]; + + /* 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 { - pixdata.apixels[sprxp + pixels_offset] = col; - if (sprx_inc == 2) { - pixdata.apixels[sprxp + pixels_offset + 1] = col; - } - } - } - } -} - -STATIC_INLINE 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); - if (currprefs.gfx_lores == 2) - sprxp >>= 1; - 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; + /* 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 { - 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 + pixels_offset]; - if (dblpf_2nd2[data] == 2) - plane2 |= mask; - if (dblpf_2nd1[data] == 1) - plane1 |= mask; - } - } else { - uae_u32 mask = 3 << ok2; - int p = sprxp+ok; - - for (; mask; mask <<= 2, p += sprx_inc) { - if (pixdata.apixels[p + pixels_offset]) - plane2 |= mask; - } + col += 16; } + col += (offs * 2); } - if (bpldualpf && m >= plfpri[1]) { - datab &= ~plane1; - attach_2nd &= ~plane1; - } - if (m >= plfpri[2]) { - datab &= ~plane2; - attach_2nd &= ~plane2; - } - } - /* If this seems strange to you, see the comment near render_sprite - about inlining. If it still seems strange, don't touch any of - this. */ - if ((spd[i].num & 1) == 1 && (spd[i].ctl & 0x80) == 0x80) { - /* Attached sprite */ - if (bplham) { - if (sprx_inc == 1) { - render_sprite (spd[i].num, sprxp, datab, 1, 1, 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, 1, 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, 1, 1); - } else { - render_sprite (spd[i].num, sprxp, datab, 0, 1, 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 (0 && bplham) { - if (sprx_inc == 1) { - render_sprite (spd[i].num, sprxp, datab, 1, 0, 1); - } else { - render_sprite (spd[i].num, sprxp, datab, 1, 0, 2); - } - } 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); - } + 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; } } +/* 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 draw_sprites_ecs (struct sprite_entry *e) +{ + 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, SHIFT, SHIFT_ZERO) \ - ((SHIFT_ZERO) ? do_get_mem_long (P) \ - : (do_get_mem_long (P) << (32 - (SHIFT))) | (do_get_mem_long ((P) + 1) >> (SHIFT))) - -/* We use the compiler's inlining ability to ensure that PLANES, D1Z and D2Z - are in effect compile time constants. That will cause some unnecessary - code to be optimized away. +#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 delay1, int delay2, int d1z, int d2z, - int wordcount, int planes) +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 7: case 8: - case 6: b2 = GETLONG ((uae_u32 *)real_bplpt[5], delay2, d2z); real_bplpt[5] += 4; - case 5: b3 = GETLONG ((uae_u32 *)real_bplpt[4], delay1, d1z); real_bplpt[4] += 4; - case 4: b4 = GETLONG ((uae_u32 *)real_bplpt[3], delay2, d2z); real_bplpt[3] += 4; - case 3: b5 = GETLONG ((uae_u32 *)real_bplpt[2], delay1, d1z); real_bplpt[2] += 4; - case 2: b6 = GETLONG ((uae_u32 *)real_bplpt[1], delay2, d2z); real_bplpt[1] += 4; - case 1: b7 = GETLONG ((uae_u32 *)real_bplpt[0], delay1, d1z); real_bplpt[0] += 4; + 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); @@ -805,42 +944,19 @@ STATIC_INLINE void pfield_doline_1 (uae_ /* See above for comments on inlining. These functions should _not_ be inlined themselves. */ -static void pfield_doline_none_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 1); } -static void pfield_doline_none_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 2); } -static void pfield_doline_none_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 3); } -static void pfield_doline_none_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 4); } -static void pfield_doline_none_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 5); } -static void pfield_doline_none_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 6); } -static void pfield_doline_none_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 7); } -static void pfield_doline_none_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, 0, 0, 1, 1, count, 8); } - -static void pfield_doline_2_n1 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 1); } -static void pfield_doline_2_n2 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 2); } -static void pfield_doline_2_n3 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 3); } -static void pfield_doline_2_n4 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 4); } -static void pfield_doline_2_n5 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 5); } -static void pfield_doline_2_n6 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 6); } -static void pfield_doline_2_n7 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 7); } -static void pfield_doline_2_n8 (uae_u32 *data, int delay2, int count) { pfield_doline_1 (data, 0, delay2, 1, 0, count, 8); } - -static void pfield_doline_1_n1 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 1); } -static void pfield_doline_1_n2 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 2); } -static void pfield_doline_1_n3 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 3); } -static void pfield_doline_1_n4 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 4); } -static void pfield_doline_1_n5 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 5); } -static void pfield_doline_1_n6 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 6); } -static void pfield_doline_1_n7 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 7); } -static void pfield_doline_1_n8 (uae_u32 *data, int delay1, int count) { pfield_doline_1 (data, delay1, 0, 0, 1, count, 8); } +static void 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 void pfield_doline (int lineno) { - /* Delay values in pixels (adjusted to the resolution). */ - int delay1 = bpldelay1 << bplres; - int delay2 = bpldelay2 << bplres; - int mindelay = delay1 < delay2 ? delay1 : delay2; - int wordcount = (dp_for_drawing->plflinelen + (RES_SHIFT (bplres) * 2 - 1)) / (RES_SHIFT (bplres) * 2); - uae_u32 *data = pixdata.apixels_l + 220; - int dsub1, dsub2; + int wordcount = dp_for_drawing->plflinelen; + uae_u32 *data = pixdata.apixels_l + MAX_PIXELS_PER_LINE/4; #ifdef SMART_UPDATE #define DATA_POINTER(n) (line_data[lineno] + (n)*MAX_WORDS_PER_LINE*2) @@ -854,94 +970,17 @@ static void pfield_doline (int lineno) real_bplpt[7] = DATA_POINTER (7); #endif - delay1 -= mindelay; - delay2 -= mindelay; - - dsub1 = (delay1 + 31) >> 5; - dsub2 = (delay2 + 31) >> 5; - real_bplpt[0] -= dsub1 * 4; - real_bplpt[2] -= dsub1 * 4; - real_bplpt[4] -= dsub1 * 4; - real_bplpt[1] -= dsub2 * 4; - real_bplpt[3] -= dsub2 * 4; - real_bplpt[5] -= dsub2 * 4; - - if (dsub1 > dsub2) - wordcount += dsub1; - else - wordcount += dsub2; - - delay1 &= 31; - delay2 &= 31; - - if (delay1) - switch (bplplanecnt) { - default: break; - case 1: pfield_doline_1_n1 (data, delay1, wordcount); break; - case 2: pfield_doline_1_n2 (data, delay1, wordcount); break; - case 3: pfield_doline_1_n3 (data, delay1, wordcount); break; - case 4: pfield_doline_1_n4 (data, delay1, wordcount); break; - case 5: pfield_doline_1_n5 (data, delay1, wordcount); break; - case 6: pfield_doline_1_n6 (data, delay1, wordcount); break; - case 7: pfield_doline_1_n7 (data, delay1, wordcount); break; - case 8: pfield_doline_1_n8 (data, delay1, wordcount); break; - } - else if (delay2) - switch (bplplanecnt) { - default: break; - case 1: pfield_doline_2_n1 (data, delay2, wordcount); break; - case 2: pfield_doline_2_n2 (data, delay2, wordcount); break; - case 3: pfield_doline_2_n3 (data, delay2, wordcount); break; - case 4: pfield_doline_2_n4 (data, delay2, wordcount); break; - case 5: pfield_doline_2_n5 (data, delay2, wordcount); break; - case 6: pfield_doline_2_n6 (data, delay2, wordcount); break; - case 7: pfield_doline_2_n7 (data, delay2, wordcount); break; - case 8: pfield_doline_2_n8 (data, delay2, wordcount); break; - } - else - switch (bplplanecnt) { - default: break; - case 1: pfield_doline_none_n1 (data, wordcount); break; - case 2: pfield_doline_none_n2 (data, wordcount); break; - case 3: pfield_doline_none_n3 (data, wordcount); break; - case 4: pfield_doline_none_n4 (data, wordcount); break; - case 5: pfield_doline_none_n5 (data, wordcount); break; - case 6: pfield_doline_none_n6 (data, wordcount); break; - case 7: pfield_doline_none_n7 (data, wordcount); break; - case 8: pfield_doline_none_n8 (data, wordcount); break; - } -} - -static void pfield_adjust_delay (void) -{ - int hiresadjust = RES_ADJUST (bplres); - int ddf_left = dp_for_drawing->plfstrt + hiresadjust; - int ddf_right = dp_for_drawing->plfstrt + dp_for_drawing->plflinelen + hiresadjust; - 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 delayreg_masked = delayreg & (bplres == RES_HIRES ? 0x77 : 0xFF); - int delay1 = delayreg & 0xF; - int delay2 = (delayreg >> 4) & 0xF; - int startpos = i == dip_for_drawing->last_delay_change - 1 ? ddf_right : delay_changes[i+1].linepos; - int stoppos = i < dip_for_drawing->first_delay_change ? ddf_left : delay_changes[i].linepos; - int j; - startpos = ((startpos - ddf_left) * 2) << bplres; - stoppos = ((stoppos - ddf_left) * 2) << bplres; - - delay1 <<= bplres; - delay2 <<= bplres; - startpos += 880; stoppos += 880; - for (j = startpos-1; j >= stoppos; j--) { - int t1 = pixdata.apixels[j - delay1]; - int t2 = pixdata.apixels[j - delay2]; -#if 0 - pixdata.apixels[j - delay1] &= 0xAA; - pixdata.apixels[j - delay2] &= 0x55; -#endif - pixdata.apixels[j] = (t1 & 0x55) | (t2 & 0xAA); - } + 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; } } @@ -982,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) @@ -1039,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) @@ -1074,6 +1113,7 @@ 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); } @@ -1083,44 +1123,29 @@ static enum { color_match_acolors, color /* Set up colors_for_drawing to the state at the beginning of the currently drawn line. Try to avoid copying color tables around whenever possible. */ -static void adjust_drawing_colors (int ctable, int bplham) +static void adjust_drawing_colors (int ctable, int need_full) { 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; } } -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 - } -} - -#define COPPER_MAGIC_FUDGE -1 - STATIC_INLINE void do_color_changes (line_draw_func worker_border, line_draw_func worker_pfield) { int i; int lastpos = visible_left_border; - + 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; @@ -1128,7 +1153,7 @@ STATIC_INLINE void do_color_changes (lin if (i == dip_for_drawing->last_color_change) nextpos = max_diwlastword; else - nextpos = PIXEL_XPOS (curr_color_changes[i].linepos) + (COPPER_MAGIC_FUDGE << lores_shift); + nextpos = coord_hw_to_window_x (curr_color_changes[i].linepos * 2); nextpos_in_range = nextpos; if (nextpos > visible_right_border) @@ -1154,10 +1179,12 @@ STATIC_INLINE void do_color_changes (lin lastpos = nextpos_in_range; } if (i != dip_for_drawing->last_color_change) { - colors_for_drawing.color_regs[regno] = value; -#if AGA_CHIPSET == 0 - colors_for_drawing.acolors[regno] = xcolors[value]; -#endif + 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; @@ -1169,29 +1196,27 @@ STATIC_INLINE void do_color_changes (lin * form. */ static void pfield_expand_dp_bplcon (void) { - unsigned int con1; - 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 - con1 = dp_for_drawing->bplcon1; - if (bplres == RES_HIRES) - con1 &= 0x77; - bpldelay1 = con1 & 0xF; - bpldelay2 = (con1 >> 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 { @@ -1213,12 +1238,9 @@ STATIC_INLINE void pfield_draw_line (int case LINE_REMEMBERED_AS_PREVIOUS: if (!warned) write_log ("Shouldn't get here... this is a bug.\n"), warned++; - - line_decisions[lineno].which = -2; return; case LINE_BLACK: - line_decisions[lineno].which = -2; linestate[lineno] = LINE_REMEMBERED_AS_BLACK; border = 2; break; @@ -1229,20 +1251,17 @@ STATIC_INLINE void pfield_draw_line (int 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; /* fall through */ case LINE_DONE: return; case LINE_DECIDED_DOUBLE: - line_decisions[lineno+1].which = -2; if (follow_ypos != -1) { do_double = 1; linetoscr_double_offset = gfxvidinfo.rowbytes * (follow_ypos - gfx_ypos); @@ -1251,7 +1270,7 @@ STATIC_INLINE void pfield_draw_line (int /* fall through */ default: - if (dp_for_drawing->which != 1) + if (dp_for_drawing->plfleft == -1) border = 1; linestate[lineno] = LINE_DONE; break; @@ -1259,63 +1278,59 @@ 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; - if (border == 0 || (dp_for_drawing->plfleft >= 0 && dip_for_drawing->nr_sprites > 0)) { + if (border == 0) { pfield_expand_dp_bplcon (); - if (bplres == RES_LORES && !currprefs.gfx_lores) + if (bplres == RES_LORES && ! currprefs.gfx_lores) currprefs.gfx_lores = 2; - pfield_init_linetoscr (); - if (! border) { - if (dip_for_drawing->first_delay_change != dip_for_drawing->last_delay_change) { - bpldelay1 = bpldelay2 = 0; - pfield_doline (lineno); - pfield_adjust_delay (); - } else - pfield_doline (lineno); - } + pfield_init_linetoscr (); + 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 + /* The problem is that we must call decode_ham() BEFORE we do the sprites. */ - if (! border && bplham) { + 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 (visible_left_border, visible_right_border); + decode_ham (visible_left_border, visible_right_border); } else /* Argh. */ { - adjust_color0_for_color_change (); - do_color_changes (dummy_worker, 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); + { + 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); + } + } - adjust_color0_for_color_change (); do_color_changes (pfield_do_fill_line, pfield_do_linetoscr); - if (dh == dh_emerg) - memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.rowbytes); + 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); - line_decisions[lineno + 1].which = -2; + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.pixbytes * gfxvidinfo.width); do_flush_line (follow_ypos); } if (currprefs.gfx_lores == 2) @@ -1323,9 +1338,6 @@ STATIC_INLINE void pfield_draw_line (int } 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); @@ -1348,26 +1360,24 @@ STATIC_INLINE void pfield_draw_line (int playfield_start = visible_right_border; playfield_end = visible_right_border; - adjust_color0_for_color_change (); 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 { 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; @@ -1376,8 +1386,8 @@ STATIC_INLINE void pfield_draw_line (int static void center_image (void) { - prev_x_adjust = visible_left_border; - 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) @@ -1441,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) @@ -1485,37 +1490,180 @@ static void init_drawing_frame (void) 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; -#ifndef SMART_UPDATE - /* @@@ This isn't exactly right yet. FIXME */ - if (!interlace_seen) { - do_flush_screen (first_drawn_line, last_drawn_line); - return; - } -#endif if (! lockscr ()) { notice_screen_contents_lost (); return; } + +#ifndef SMART_UPDATE + /* @@@ This isn't exactly right yet. FIXME */ + if (!interlace_seen) + do_flush_screen (first_drawn_line, last_drawn_line); + else + unlockscr (); + return; +#endif 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 (); do_flush_screen (first_drawn_line, last_drawn_line); } @@ -1576,10 +1724,20 @@ 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 (); return; } @@ -1665,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++) @@ -1682,6 +1839,9 @@ void reset_drawing (void) last_redraw_point = 0; + memset (spixels, 0, sizeof spixels); + memset (&spixstate, 0, sizeof spixstate); + init_drawing_frame (); }