--- uae/src/drawing.c 2018/04/24 17:00:11 1.1.1.13 +++ uae/src/drawing.c 2018/04/24 17:18:28 1.1.1.20 @@ -32,9 +32,8 @@ #include #include -#include "config.h" #include "options.h" -#include "threaddep/penguin.h" +#include "threaddep/thread.h" #include "uae.h" #include "memory.h" #include "custom.h" @@ -132,12 +131,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; @@ -149,17 +148,19 @@ static int last_redraw_point; static int first_drawn_line, last_drawn_line; static int first_block_line, last_block_line; +#define NO_BLOCK -3 + /* 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, bpldualpf2of, bplplanecnt, bplres; +static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt; +static int bplres, adjusted_bplres; static uae_u32 plf_sprite_mask; static int sbasecol[2]; int picasso_requested_on; int picasso_on; -uae_sem_t gui_sem; int inhibit_frame; int framecnt = 0; @@ -302,33 +303,33 @@ static void pfield_init_linetoscr (void) #define LNAME linetoscr_8 #define SRC_INC 1 #define HDOUBLE 0 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_8_stretch1 #define SRC_INC 1 #define HDOUBLE 1 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_8_shrink1 #define SRC_INC 2 #define HDOUBLE 0 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_8_aga #define SRC_INC 1 #define HDOUBLE 0 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #define LNAME linetoscr_8_stretch1_aga #define SRC_INC 1 #define HDOUBLE 1 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #define LNAME linetoscr_8_shrink1_aga #define SRC_INC 2 #define HDOUBLE 0 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #undef TYPE @@ -337,33 +338,33 @@ static void pfield_init_linetoscr (void) #define LNAME linetoscr_16 #define SRC_INC 1 #define HDOUBLE 0 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_16_stretch1 #define SRC_INC 1 #define HDOUBLE 1 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_16_shrink1 #define SRC_INC 2 #define HDOUBLE 0 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_16_aga #define SRC_INC 1 #define HDOUBLE 0 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #define LNAME linetoscr_16_stretch1_aga #define SRC_INC 1 #define HDOUBLE 1 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #define LNAME linetoscr_16_shrink1_aga #define SRC_INC 2 #define HDOUBLE 0 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #undef TYPE @@ -372,33 +373,33 @@ static void pfield_init_linetoscr (void) #define LNAME linetoscr_32 #define SRC_INC 1 #define HDOUBLE 0 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_32_stretch1 #define SRC_INC 1 #define HDOUBLE 1 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_32_shrink1 #define SRC_INC 2 #define HDOUBLE 0 -#define AGA 0 +#define AGAC 0 #include "linetoscr.c" #define LNAME linetoscr_32_aga #define SRC_INC 1 #define HDOUBLE 0 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #define LNAME linetoscr_32_stretch1_aga #define SRC_INC 1 #define HDOUBLE 1 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #define LNAME linetoscr_32_shrink1_aga #define SRC_INC 2 #define HDOUBLE 0 -#define AGA 1 +#define AGAC 1 #include "linetoscr.c" #undef TYPE @@ -447,7 +448,7 @@ STATIC_INLINE void fill_line (void) start = (int *)(((char *)xlinebuffer) + (visible_left_border << shift)); val = colors_for_drawing.acolors[0]; if (gfxvidinfo.pixbytes == 2) - val |= val << 16; + val |= val << 16; for (; nints > 0; nints -= 8, start += 8) { *start = val; *(start+1) = val; @@ -488,22 +489,22 @@ static void pfield_do_linetoscr (int sta 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) + else if (res_shift > 0) 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) + else if (res_shift < 0) 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 + else abort (); } else { - if (res_shift == 0) + 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; @@ -563,7 +564,15 @@ static void init_ham_decoding (void) ham_decode_pixel = src_pixel; ham_lastcolor = color_reg_get (&colors_for_drawing, 0); - if (currprefs.chipset_mask & CSMASK_AGA) { + 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++]; @@ -574,9 +583,9 @@ static void init_ham_decoding (void) case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break; } } - } else if(bplplanecnt == 6) { /* AGA mode HAM6 */ + } else if (bplplanecnt == 6) { /* AGA mode HAM6 */ while (unpainted_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel++]; + 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; @@ -586,7 +595,7 @@ static void init_ham_decoding (void) } } } else { - if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */ + if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */ while (unpainted_amiga-- > 0) { int pv = pixdata.apixels[ham_decode_pixel++]; switch (pv & 0x30) { @@ -603,10 +612,18 @@ static void init_ham_decoding (void) static void decode_ham (int pix, int stoppos) { int todraw_amiga = res_shift_from_window (stoppos - pix); - if (!bplham) - abort (); - if (currprefs.chipset_mask & CSMASK_AGA) { + 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]; @@ -618,7 +635,7 @@ static void decode_ham (int pix, int sto } ham_linebuf[ham_decode_pixel++] = ham_lastcolor; } - } else if(bplplanecnt == 6) { /* AGA mode HAM6 */ + } else if (bplplanecnt == 6) { /* AGA mode HAM6 */ while (todraw_amiga-- > 0) { int pv = pixdata.apixels[ham_decode_pixel]; switch (pv & 0x30) { @@ -631,9 +648,9 @@ static void decode_ham (int pix, int sto } } } else { - if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */ + if (bplplanecnt == 6) { /* OCS/ECS mode HAM6 */ while (todraw_amiga-- > 0) { - int pv = pixdata.apixels[ham_decode_pixel]; + 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; @@ -733,7 +750,7 @@ STATIC_INLINE void draw_sprites_1 (struc /* 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) @@ -794,32 +811,32 @@ STATIC_INLINE void draw_sprites_1 (struc 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 draw_sprites_normal_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 0, 0, 0); } -static void draw_sprites_normal_dp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 0, 0, 0); } -static void draw_sprites_ham_sp_lo_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 0, 0, 0); } -static void draw_sprites_normal_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 0, 0, 1, 0); } -static void draw_sprites_normal_dp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 0, 0, 1, 0); } -static void draw_sprites_ham_sp_lo_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 0, 0, 1, 0); } +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 draw_sprites_normal_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 0, 0, 0); } -static void draw_sprites_normal_dp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 0, 0, 0); } -static void draw_sprites_ham_sp_hi_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 0, 0, 0); } -static void draw_sprites_normal_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0, 1, 0, 1, 0); } -static void draw_sprites_normal_dp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1, 1, 0, 1, 0); } -static void draw_sprites_ham_sp_hi_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0, 1, 0, 1, 0); } +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, bplham, bpldualpf, 0, diff, e->has_attached, 1); + draw_sprites_1 (e, dp_for_drawing->ham_seen, bpldualpf, 0, diff, e->has_attached, 1); else - draw_sprites_1 (e, bplham, bpldualpf, -diff, 0, e->has_attached, 1); + draw_sprites_1 (e, dp_for_drawing->ham_seen, bpldualpf, -diff, 0, e->has_attached, 1); } @@ -827,7 +844,7 @@ STATIC_INLINE void draw_sprites_ecs (str { if (e->has_attached) if (bplres == 1) - if (bplham) + if (dp_for_drawing->ham_seen) draw_sprites_ham_sp_hi_at (e); else if (bpldualpf) @@ -835,7 +852,7 @@ STATIC_INLINE void draw_sprites_ecs (str else draw_sprites_normal_sp_hi_at (e); else - if (bplham) + if (dp_for_drawing->ham_seen) draw_sprites_ham_sp_lo_at (e); else if (bpldualpf) @@ -844,7 +861,7 @@ STATIC_INLINE void draw_sprites_ecs (str draw_sprites_normal_sp_lo_at (e); else if (bplres == 1) - if (bplham) + if (dp_for_drawing->ham_seen) draw_sprites_ham_sp_hi_nat (e); else if (bpldualpf) @@ -852,7 +869,7 @@ STATIC_INLINE void draw_sprites_ecs (str else draw_sprites_normal_sp_hi_nat (e); else - if (bplham) + if (dp_for_drawing->ham_seen) draw_sprites_ham_sp_lo_nat (e); else if (bpldualpf) @@ -928,19 +945,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_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 1); } -static void pfield_doline_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 2); } -static void pfield_doline_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 3); } -static void pfield_doline_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 4); } -static void pfield_doline_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 5); } -static void pfield_doline_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 6); } -static void pfield_doline_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 7); } -static void pfield_doline_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, 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) { int wordcount = dp_for_drawing->plflinelen; - uae_u32 *data = pixdata.apixels_l + MAX_PIXELS_PER_LINE/4; + 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) @@ -993,16 +1010,16 @@ static void init_aspect_maps (void) amiga2aspect_line_map = (int *)malloc (sizeof (int) * (MAXVPOS + 1)*2 + 1); native2amiga_line_map = (int *)malloc (sizeof (int) * gfxvidinfo.height); - if (currprefs.gfx_correct_aspect) + if (curr_gfx->correct_aspect) native_lines_per_amiga_line = ((double)gfxvidinfo.height - * (currprefs.gfx_lores ? 320 : 640) - / (currprefs.gfx_linedbl ? 512 : 256) + * (curr_gfx->lores ? 320 : 640) + / (curr_gfx->linedbl ? 512 : 256) / gfxvidinfo.width); else native_lines_per_amiga_line = 1; - maxl = (MAXVPOS + 1) * (currprefs.gfx_linedbl ? 2 : 1); - min_ypos_for_screen = minfirstline << (currprefs.gfx_linedbl ? 1 : 0); + maxl = (MAXVPOS + 1) * (curr_gfx->linedbl ? 2 : 1); + min_ypos_for_screen = minfirstline << (curr_gfx->linedbl ? 1 : 0); max_drawn_amiga_line = -1; for (i = 0; i < maxl; i++) { int v = (int) ((i - min_ypos_for_screen) * native_lines_per_amiga_line); @@ -1012,12 +1029,12 @@ static void init_aspect_maps (void) v = -1; amiga2aspect_line_map[i] = v; } - if (currprefs.gfx_linedbl) + if (curr_gfx->linedbl) max_drawn_amiga_line >>= 1; - if (currprefs.gfx_ycenter && !(currprefs.gfx_correct_aspect)) { + if (curr_gfx->ycenter && !(curr_gfx->correct_aspect)) { /* @@@ verify maxvpos vs. MAXVPOS */ - extra_y_adjust = (gfxvidinfo.height - (maxvpos << (currprefs.gfx_linedbl ? 1 : 0))) >> 1; + extra_y_adjust = (gfxvidinfo.height - (maxvpos << (curr_gfx->linedbl ? 1 : 0))) >> 1; if (extra_y_adjust < 0) extra_y_adjust = 0; } @@ -1029,7 +1046,7 @@ static void init_aspect_maps (void) /* Must omit drawing some lines. */ for (i = maxl - 1; i > min_ypos_for_screen; i--) { if (amiga2aspect_line_map[i] == amiga2aspect_line_map[i-1]) { - if (currprefs.gfx_linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) { + if (curr_gfx->linedbl && (i & 1) == 0 && amiga2aspect_line_map[i+1] != -1) { /* If only the first line of a line pair would be omitted, * omit the second one instead to avoid problems with line * doubling. */ @@ -1046,7 +1063,7 @@ static void init_aspect_maps (void) if (amiga2aspect_line_map[i] == -1) continue; for (j = amiga2aspect_line_map[i]; j < gfxvidinfo.height && native2amiga_line_map[j] == -1; j++) - native2amiga_line_map[j] = i >> (currprefs.gfx_linedbl ? 1 : 0); + native2amiga_line_map[j] = i >> (curr_gfx->linedbl ? 1 : 0); } } @@ -1065,14 +1082,14 @@ static void do_flush_line_1 (int lineno) flush_line (lineno); else { if ((last_block_line+1) != lineno) { - if (first_block_line != -2) + if (first_block_line != NO_BLOCK) flush_block (first_block_line, last_block_line); first_block_line = lineno; } last_block_line = lineno; if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) { flush_block (first_block_line, last_block_line); - first_block_line = last_block_line = -2; + first_block_line = last_block_line = NO_BLOCK; } } } @@ -1094,31 +1111,60 @@ STATIC_INLINE void do_flush_screen (int Should be corrected. (sjo 26.9.99) */ - if (gfxvidinfo.maxblocklines != 0 && first_block_line != -2) { + if (gfxvidinfo.maxblocklines != 0 && first_block_line != NO_BLOCK) { flush_block (first_block_line, last_block_line); } + unlockscr (); if (start <= stop) flush_screen (start, stop); } +/* We only save hardware registers during the hardware frame. Now, when + * drawing the frame, we expand the data into a slightly more useful + * form. */ +static void pfield_expand_dp_bplcon (void) +{ + 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; +} + static int drawing_color_matches; static enum { color_match_acolors, color_match_full } color_match_type; /* Set up colors_for_drawing to the state at the beginning of the currently drawn line. Try to avoid copying color tables around whenever possible. */ -static void adjust_drawing_colors (int ctable, int bplham) +static void adjust_drawing_colors (int ctable, int need_full) { if (drawing_color_matches != ctable) { - if (bplham) { + 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) { + } 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; } @@ -1162,43 +1208,18 @@ STATIC_INLINE void do_color_changes (lin lastpos = nextpos_in_range; } if (i != dip_for_drawing->last_color_change) { - color_reg_set (&colors_for_drawing, regno, value); - colors_for_drawing.acolors[regno] = getxcolor (value); + 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; } } -/* We only save hardware registers during the hardware frame. Now, when - * drawing the frame, we expand the data into a slightly more useful - * form. */ -static void pfield_expand_dp_bplcon (void) -{ - int plf1pri, plf2pri; - bplres = dp_for_drawing->bplres; - bplplanecnt = dp_for_drawing->nr_planes; - bplham = ((dp_for_drawing->bplcon0 & 0x800) == 0x800 - && (bplplanecnt == 6 - || ((currprefs.chipset_mask & CSMASK_AGA) != 0 && bplplanecnt == 8))); - 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 { dh_buf, dh_line, @@ -1268,17 +1289,17 @@ STATIC_INLINE void pfield_draw_line (int if (border == 0) { pfield_expand_dp_bplcon (); - if (bplres == RES_LORES && ! currprefs.gfx_lores) - currprefs.gfx_lores = 2; + if (bplres == RES_LORES && ! curr_gfx->lores) + curr_gfx->lores = 2; pfield_init_linetoscr (); pfield_doline (lineno); - 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_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 @@ -1286,8 +1307,9 @@ STATIC_INLINE void pfield_draw_line (int decode_ham (visible_left_border, visible_right_border); } else /* Argh. */ { do_color_changes (dummy_worker, decode_ham); - adjust_drawing_colors (dp_for_drawing->ctable, bplham || bplehb); + adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb); } + bplham = dp_for_drawing->ham_at_start; } { @@ -1295,25 +1317,25 @@ STATIC_INLINE void pfield_draw_line (int 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 + else draw_sprites_ecs (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i); } } 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); + memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.pixbytes * gfxvidinfo.width); do_flush_line (follow_ypos); } - if (currprefs.gfx_lores == 2) - currprefs.gfx_lores = 0; + if (curr_gfx->lores == 2) + curr_gfx->lores = 0; } else if (border == 1) { adjust_drawing_colors (dp_for_drawing->ctable, 0); @@ -1342,14 +1364,14 @@ STATIC_INLINE void pfield_draw_line (int 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); @@ -1365,11 +1387,11 @@ 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) + if (curr_gfx->xcenter) { + if (max_diwstop - min_diwstart < gfxvidinfo.width && curr_gfx->xcenter == 2) /* Try to center. */ visible_left_border = ((max_diwstop - min_diwstart - gfxvidinfo.width) / 2 + min_diwstart) & ~1; else @@ -1377,7 +1399,7 @@ static void center_image (void) /* 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 (curr_gfx->xcenter == 2) { if (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart) visible_left_border = prev_x_adjust; } @@ -1393,14 +1415,14 @@ static void center_image (void) visible_right_border = max_diwlastword; thisframe_y_adjust = minfirstline; - if (currprefs.gfx_ycenter && thisframe_first_drawn_line != -1) { - if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2) + if (curr_gfx->ycenter && thisframe_first_drawn_line != -1) { + if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && curr_gfx->ycenter == 2) thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line; else thisframe_y_adjust = thisframe_first_drawn_line; /* Would the old value be good enough? If so, leave it as it is if we want to * be clever. */ - if (currprefs.gfx_ycenter == 2) { + if (curr_gfx->ycenter == 2) { if (thisframe_y_adjust != prev_y_adjust && prev_y_adjust <= thisframe_first_drawn_line && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line) @@ -1412,13 +1434,13 @@ static void center_image (void) if (thisframe_y_adjust < minfirstline) thisframe_y_adjust = minfirstline; } - thisframe_y_adjust_real = thisframe_y_adjust << (currprefs.gfx_linedbl ? 1 : 0); - max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (currprefs.gfx_linedbl ? 1 : 0); + thisframe_y_adjust_real = thisframe_y_adjust << (curr_gfx->linedbl ? 1 : 0); + max_ypos_thisframe = (maxvpos - thisframe_y_adjust) << (curr_gfx->linedbl ? 1 : 0); /* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably * better. */ if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust) - frame_redraw_necessary |= interlace_seen && currprefs.gfx_linedbl ? 2 : 1; + frame_redraw_necessary |= interlace_seen && curr_gfx->linedbl ? 2 : 1; max_diwstop = 0; min_diwstart = 10000; @@ -1435,7 +1457,10 @@ static void init_drawing_frame (void) if (thisframe_first_drawn_line > thisframe_last_drawn_line) thisframe_last_drawn_line = thisframe_first_drawn_line; - maxline = currprefs.gfx_linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1; + if (!curr_gfx) + return; + + maxline = curr_gfx->linedbl ? (maxvpos+1) * 2 + 1 : (maxvpos+1) + 1; #ifdef SMART_UPDATE for (i = 0; i < maxline; i++) { switch (linestate[i]) { @@ -1455,7 +1480,7 @@ static void init_drawing_frame (void) last_drawn_line = 0; first_drawn_line = 32767; - first_block_line = last_block_line = -2; + first_block_line = last_block_line = NO_BLOCK; if (currprefs.test_drawing_speed) frame_redraw_necessary = 1; else if (frame_redraw_necessary) @@ -1469,37 +1494,188 @@ 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 16 + +#define TD_BORDER 0x333 + +static const char *numbers = { /* ugly 0123456789CHD%+- */ +"+++++++--++++-+++++++++++++++++-++++++++++++++++++++++++++++++++++++++++++++-++++++-++++----++---+--------------" +"+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+---+x+-+xxxxx++xxxxx++xxxxx++xxxxx++xxxxx+--++x+-+xxxxx++xxxxx++x+----+xxxx+-+x++x+----+x+--+xxx+--+xxx+-" +"+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; + int 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]; + if (y == 0 || y == TD_TOTAL_HEIGHT - 1) + c = xcolors[TD_BORDER]; + + x = x_start + pos * TD_WIDTH; + putpixel (x - 1, xcolors[TD_BORDER]); + for (j = 0; j < TD_LED_WIDTH; j++) + putpixel (x + j, c); + putpixel (x + j, xcolors[TD_BORDER]); + + if (y >= TD_PADY && y - TD_PADY < TD_NUM_HEIGHT) { + if (num3 >= 0) { + int tn = num1 > 0 ? 3 : 2; + x += (TD_LED_WIDTH - tn * TD_NUM_WIDTH) / 2; + if (num1 > 0) { + write_tdnumber (x, y - TD_PADY, num1); + x += TD_NUM_WIDTH; + } + write_tdnumber (x, y - TD_PADY, num2); + x += TD_NUM_WIDTH; + write_tdnumber (x, y - TD_PADY, num3); + x += TD_NUM_WIDTH; + if (num4 > 0) + write_tdnumber (x, 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 - (curr_gfx->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 (curr_gfx->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); } @@ -1544,6 +1720,56 @@ STATIC_INLINE void check_picasso (void) #endif } +int check_prefs_changed_gfx (void) +{ + int params_changed = 0, screen_changed = 0; + int old_x, old_y; + + if (!screen_is_picasso) { + if (curr_gfx == &currprefs.gfx_w + && memcmp (&changed_prefs.gfx_w, &currprefs.gfx_w, sizeof (struct gfx_params)) != 0) + { + old_x = currprefs.gfx_w.width; + old_y = currprefs.gfx_w.height; + fixup_prefs_dimensions (&changed_prefs.gfx_w, gfx_windowed_modes, n_windowed_modes); + currprefs.gfx_w = changed_prefs.gfx_w; + params_changed = 1; + screen_changed = (old_x != currprefs.gfx_w.width + || old_y != currprefs.gfx_w.height); + } else if (curr_gfx == &currprefs.gfx_f + && memcmp (&changed_prefs.gfx_f, &currprefs.gfx_f, sizeof (struct gfx_params)) != 0) + { + old_x = currprefs.gfx_f.width; + old_y = currprefs.gfx_f.height; + fixup_prefs_dimensions (&changed_prefs.gfx_f, gfx_fullscreen_modes, n_fullscreen_modes); + currprefs.gfx_f = changed_prefs.gfx_f; + params_changed = 1; + screen_changed = (old_x != currprefs.gfx_f.width + || old_y != currprefs.gfx_f.height); + } + if (changed_prefs.gfx_afullscreen != currprefs.gfx_afullscreen) { + screen_changed = 1; + } + } else if (changed_prefs.gfx_pfullscreen != currprefs.gfx_pfullscreen) { + screen_changed = 1; + } + + currprefs.gfx_afullscreen = changed_prefs.gfx_afullscreen; + currprefs.gfx_pfullscreen = changed_prefs.gfx_pfullscreen; + + if (screen_changed) { + graphics_subshutdown (0); + + gui_update_gfx (); + + graphics_subinit (); + + reset_drawing (); + } + + return params_changed || screen_changed; +} + void vsync_handle_redraw (int long_frame, int lof_changed) { last_redraw_point++; @@ -1567,11 +1793,7 @@ void vsync_handle_redraw (int long_frame savestate_state = 0; } else if (savestate_state == STATE_DORESTORE) { savestate_state = STATE_RESTORE; - uae_reset (); - restore_state (savestate_filename); -#if 0 - activate_debugger (); -#endif + uae_reset (0); } if (quit_program < 0) { @@ -1585,14 +1807,20 @@ void vsync_handle_redraw (int long_frame count_frame (); check_picasso (); + currprefs.keyboard_lang = changed_prefs.keyboard_lang; check_prefs_changed_audio (); check_prefs_changed_custom (); check_prefs_changed_cpu (); if (check_prefs_changed_gfx ()) { - init_row_map (); - init_aspect_maps (); + if (curr_gfx) { + init_row_map (); + init_aspect_maps (); + } notice_screen_contents_lost (); notice_new_xcolors (); + + if (screen_is_picasso) + picasso_enablescreen (1); } if (inhibit_frame != 0) @@ -1650,19 +1878,12 @@ void reset_drawing (void) { int i; - inhibit_frame = 0; - uae_sem_init (&gui_sem, 0, 1); - -#ifdef PICASSO96 - InitPicasso96 (); - picasso_on = 0; - picasso_requested_on = 0; - gfx_set_picasso_state (0); -#endif max_diwstop = 0; - lores_factor = currprefs.gfx_lores ? 1 : 2; - lores_shift = currprefs.gfx_lores ? 0 : 1; + if (!curr_gfx) + return; + lores_factor = curr_gfx->lores ? 1 : 2; + lores_shift = curr_gfx->lores ? 0 : 1; /*memset(blitcount, 0, sizeof(blitcount)); blitter debug */ for (i = 0; i < sizeof linestate / sizeof *linestate; i++) @@ -1685,12 +1906,24 @@ void reset_drawing (void) init_drawing_frame (); } +void init_drawing_at_reset (void) +{ + InitPicasso96 (); + picasso_requested_on = 0; + picasso_on = 0; + gfx_set_picasso_state (0); + + inhibit_frame = 0; +} + void drawing_init () { + inhibit_frame = 0; + native2amiga_line_map = 0; amiga2aspect_line_map = 0; line_drawn = 0; - gen_pfield_tables(); + gen_pfield_tables (); }