From 997457c73eda10afb3824ae8786753f857661ec3 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 28 May 2022 21:31:29 +0300 Subject: [PATCH] Sprite collision update, WIP pixel perfect lores/hires mid scanline change. --- custom.cpp | 556 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 421 insertions(+), 135 deletions(-) diff --git a/custom.cpp b/custom.cpp index 58d505eb..7b1df8d6 100644 --- a/custom.cpp +++ b/custom.cpp @@ -436,7 +436,7 @@ int plffirstline_total, plflastline_total; int vblank_firstline_hw; static int autoscale_bordercolors; static int plfstrt, plfstop; -static int sprite_minx; +static int sprite_minx, sprite_maxx; static int first_bpl_vpos; static int last_decide_line_hpos; static int last_fetch_hpos, last_decide_sprite_hpos; @@ -450,6 +450,7 @@ static bool exthblank, exthblank_state, hcenterblank_state; static int last_diw_hpos, last_diw_hpos2; static int last_recorded_diw_hpos; static int last_hblank_start; +static int collision_hpos; int first_planes_vpos, last_planes_vpos; static int first_bplcon0, first_bplcon0_old; @@ -570,6 +571,10 @@ static uae_u16 dmal_alloc_mask; struct custom_store custom_storage[256]; +#define TOSCR_RES_PIXELS_LORES 4 +#define TOSCR_RES_PIXELS_HIRES 2 +#define TOSCR_RES_PIXELS_SHRES 1 + #define TOSCR_NBITS 16 #define TOSCR_NBITSHR 32 @@ -589,8 +594,8 @@ static uae_u32 fetched_aga_spr[MAX_PLANES]; /* Expansions from bplcon0/bplcon1. */ static int toscr_res2p, toscr_res_mult; static int toscr_res, toscr_res_old; -static int toscr_res_pixels, toscr_res_pixels_shift; -static int toscr_res_pixels_hr, toscr_res_pixels_shift_hr, toscr_res_pixels_mask_hr; +static int toscr_res_pixels, toscr_res_pixels_shift, toscr_res_pixels_shift_old; +static int toscr_res_pixels_hr, toscr_res_pixels_shift_hr, toscr_res_pixels_mask_hr, toscr_res_pixels_mask_hr_old, toscr_res_pixels_mask_hr2; static int toscr_nr_planes, toscr_nr_planes2, toscr_nr_planes3, toscr_nr_planes_agnus; static bool toscr_nr_changed; static int toscr_nr_planes_shifter, toscr_nr_planes_shifter_new; @@ -664,6 +669,11 @@ STATIC_INLINE int diw_to_hpos(int diw) } STATIC_INLINE int hpos_to_diw(int pos) +{ + return (pos * 2 - DDF_OFFSET) * 4; +} + +STATIC_INLINE int hpos_to_diwx(int pos) { return ((pos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4; } @@ -932,7 +942,7 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) return; } - int pos = hpos < 0 ? -hpos : hpos_to_diw(hpos); + int pos = hpos < 0 ? -hpos : hpos_to_diwx(hpos); // AGA has extra hires pixel delay in color changes if ((regno < RECORDED_REGISTER_CHANGE_OFFSET || regno == RECORDED_REGISTER_CHANGE_OFFSET + 0x10c) && aga_mode) { @@ -1301,7 +1311,7 @@ static void decide_hdiw(int hpos) return; } int start_diw_hpos = ((last_diw_hpos * 2 - DDF_OFFSET + 1) << 2) + 3; - int end_diw_hpos = ((hpos * 2 + 1) << 2) + 3; + int end_diw_hpos = ((hpos2 * 2 + 1) << 2) + 3; // should handle wrap around.. if (start_diw_hpos < ((1 << 2) + 3)) { start_diw_hpos = (1 << 2) + 3; @@ -1949,8 +1959,6 @@ static void compute_toscr_delay(int bplcon1) { int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6); int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6); - int shdelay1 = (bplcon1 >> 8) & 3; - int shdelay2 = (bplcon1 >> 12) & 3; int delaymask = fetchmode_mask >> toscr_res; compute_shifter_mask(); @@ -1958,12 +1966,22 @@ static void compute_toscr_delay(int bplcon1) toscr_delay_shifter[0] = (delay1 & delaymask) << LORES_TO_SHRES_SHIFT; toscr_delay_shifter[1] = (delay2 & delaymask) << LORES_TO_SHRES_SHIFT; - if (currprefs.chipset_hr) { - toscr_delay_shifter[0] |= shdelay1; - toscr_delay_shifter[1] |= shdelay2; + int shdelay1 = (bplcon1 >> 8) & 3; + int shdelay2 = (bplcon1 >> 12) & 3; + if (!currprefs.chipset_hr) { + // subpixel scrolling not possible + if (toscr_res == RES_HIRES) { + shdelay1 &= ~1; + shdelay2 &= ~1; + } else if (toscr_res == RES_LORES) { + shdelay1 &= ~3; + shdelay2 &= ~3; + } } + toscr_delay_shifter[0] |= shdelay1; + toscr_delay_shifter[1] |= shdelay2; - if (toscr_delay_shifter[0] != toscr_delay_shifter[1]) { + if (toscr_delay_shifter[0] != toscr_delay_shifter[1] || 1) { toscr_scanline_complex_bplcon1 = true; toscr_scanline_complex_bplcon1_off = false; } else { @@ -2030,7 +2048,7 @@ static const uae_u8 bpl_sequence_2[32] = { 2, 1 }; static const uae_u8 *bpl_sequence; /* set currently active Agnus bitplane DMA sequence */ -static void setup_fmodes(int hpos) +static void setup_fmodes(int hpos, uae_u16 con0) { switch (fmode & 3) { @@ -2045,15 +2063,15 @@ static void setup_fmodes(int hpos) fetchmode = 2; break; } - if (GET_RES_AGNUS(bplcon0) != GET_RES_DENISE(bplcon0)) { + if (GET_RES_AGNUS(con0) != GET_RES_DENISE(con0)) { SET_LINE_CYCLEBASED } - bplcon0_res = GET_RES_AGNUS(bplcon0); + bplcon0_res = GET_RES_AGNUS(con0); toscr_res_old = -1; update_toscr_vars(); - bplcon0_planes = GET_PLANES(bplcon0); - bplcon0_planes_limit = GET_PLANES_LIMIT(bplcon0); + bplcon0_planes = GET_PLANES(con0); + bplcon0_planes_limit = GET_PLANES_LIMIT(con0); fetchunit = fetchunits[fetchmode * 4 + bplcon0_res]; fetchunit_mask = fetchunit - 1; fetchstart_shift = fetchstarts[fetchmode * 4 + bplcon0_res]; @@ -2083,7 +2101,7 @@ static void setup_fmodes(int hpos) if (thisline_decision.plfleft < 0) { thisline_decision.bplres = output_res(bplcon0_res); - thisline_decision.bplcon0 = bplcon0; + thisline_decision.bplcon0 = con0; thisline_decision.nr_planes = bplcon0_planes; } @@ -2830,7 +2848,29 @@ STATIC_INLINE void do_delays_fast_3_aga(int nbits, int fm) } } -STATIC_INLINE void do_delays_3_aga_hr(int nbits, int fm) +static void todisplay_copy_hr_oddeven(int oddeven, int fm) +{ + if (todisplay_fetched & (oddeven + 1)) { + int i; + for (i = oddeven; i < toscr_nr_planes_shifter; i += 2) { + todisplay2_aga[i] = todisplay_aga[i]; + todisplay2_lastbit[i] = todisplay_aga[i] & 1; + } + todisplay_fetched -= oddeven + 1; + out_subpix[oddeven] = 0; + if (toscr_nr_changed) { + while (i < toscr_nr_planes2) { + if (todisplay2_lastbit[i]) { + todisplay2_aga[i] = firstpixel[fm]; + todisplay2_lastbit[i] = 0; + } + i += 2; + } + } + } +} + +STATIC_INLINE void do_delays_3_aga_hr2(int nbits, int fm) { int delaypos = delay_cycles; for (int oddeven = 0; oddeven < 2; oddeven++) { @@ -2840,31 +2880,221 @@ STATIC_INLINE void do_delays_3_aga_hr(int nbits, int fm) if (nbits2 > diff) { do_tosrc_hr(oddeven, 2, diff, fm); nbits2 -= diff; - if (todisplay_fetched & (oddeven + 1)) { - int i; - for (i = oddeven; i < toscr_nr_planes_shifter; i += 2) { - todisplay2_aga[i] = todisplay_aga[i]; - todisplay2_lastbit[i] = todisplay_aga[i] & 1; + todisplay_copy_hr_oddeven(oddeven, fm); + } + if (nbits2) { + do_tosrc_hr(oddeven, 2, nbits2, fm); + } + } +} + +#define TOSCR_SPC_LORES 1 +#define TOSCR_SPC_HIRES 2 +#define TOSCR_SPC_LORES_END 16 +#define TOSCR_SPC_HIRES_END 32 +#define TOSCR_SPC_LORES_START 64 +#define TOSCR_SPC_HIRES_START 128 +#define TOSCR_SPC_CLEAR 256 +#define TOSCR_SPC_CLEAR2 512 +#define TOSCR_SPC_6HIRESTOLORES 1024 +#define TOSCR_SPC_MARK 16384 +#define TOSCR_SPC_SKIP 32768 + +static const uae_u16 toscr_spc_aga_lores_to_hires[] = +{ + TOSCR_SPC_LORES | TOSCR_SPC_LORES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_LORES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_LORES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_LORES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_LORES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_LORES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_LORES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_LORES_START | TOSCR_SPC_HIRES_END, + 0, 0, 0, 0 +}; +static const uae_u16 toscr_spc_aga_hires_to_lores[] = +{ + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + 0, 0, 0, 0 +}; + +static const uae_u16 toscr_spc_ecs_lores_to_hires[] = +{ + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END | TOSCR_SPC_CLEAR, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END | TOSCR_SPC_CLEAR, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + 0, 0, 0, 0 +}; +static const uae_u16 toscr_spc_ecs_hires_to_lores[] = +{ + TOSCR_SPC_HIRES | TOSCR_SPC_LORES_START | TOSCR_SPC_LORES_END | TOSCR_SPC_6HIRESTOLORES, + TOSCR_SPC_HIRES | TOSCR_SPC_LORES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_LORES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_LORES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_LORES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_LORES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_LORES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_LORES_START | TOSCR_SPC_LORES_END, + 0, 0, 0, 0 +}; + +static const uae_u16 toscr_spc_ocs_lores_to_hires[] = +{ + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END | TOSCR_SPC_CLEAR, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END | TOSCR_SPC_CLEAR, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END | TOSCR_SPC_CLEAR, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END | TOSCR_SPC_CLEAR, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + TOSCR_SPC_LORES | TOSCR_SPC_HIRES_START | TOSCR_SPC_HIRES_END, + 0, 0, 0, 0 +}; +static const uae_u16 toscr_spc_ocs_hires_to_lores[] = +{ + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + TOSCR_SPC_HIRES | TOSCR_SPC_HIRES_START | TOSCR_SPC_LORES_END, + 0, 0, 0, 0 +}; + +static const uae_u16 *toscr_special_skip_ptr = NULL; + +STATIC_INLINE void toscr_1_hr_nbits(void) +{ + if (out_offs < MAX_WORDS_PER_LINE * 2 / 4 - 1) { + uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4; + for (int i = 0; i < toscr_nr_planes2; i++) { + uae_u64 *dataptr64 = (uae_u64 *)dataptr; + uae_u64 v = (outword64[i] >> 32) | (outword64[i] << 32); + if (*dataptr64 != v) { + thisline_changed = 1; + *dataptr64 = v; + } + dataptr += MAX_WORDS_PER_LINE * 2; + } + out_offs += 2; + } + out_nbits = 0; +} + +static void do_delays_queued(int bitoffset, int mode) +{ + if (out_nbits >= bitoffset) { + + + } +} + +STATIC_INLINE void do_delays_3_aga_hr(int nbits, int fm) +{ + if (toscr_special_skip_ptr) { + int difsize = 0; + int delaypos = delay_cycles; + while (nbits > 0) { + uae_u16 cmd = *toscr_special_skip_ptr; + if (cmd & TOSCR_SPC_6HIRESTOLORES) { + } + if (cmd & TOSCR_SPC_CLEAR) { + for (int i = 0; i < toscr_nr_planes_shifter; i++) { + todisplay2_aga[i] &= ~0x8000; } - todisplay_fetched -= oddeven + 1; - out_subpix[oddeven] = 0; - if (toscr_nr_changed) { - while (i < toscr_nr_planes2) { - if (todisplay2_lastbit[i]) { - todisplay2_aga[i] = firstpixel[fm]; - todisplay2_lastbit[i] = 0; - } - i += 2; + } + if (cmd & TOSCR_SPC_CLEAR2) { + for (int i = 0; i < toscr_nr_planes_shifter; i++) { + todisplay2_aga[i] &= 0xff00; + } + } + if ((cmd & TOSCR_SPC_MARK) && (vpos & 1)) { + for (int i = 0; i < toscr_nr_planes_shifter; i++) { + todisplay2_aga[i] ^= 0x8000; + } + } + if (cmd & TOSCR_SPC_SKIP) { + delay_cycles += difsize * (1 << toscr_res_pixels_shift_hr); + do_delays_3_aga_hr2(1, fm); + delay_cycles -= difsize * (1 << toscr_res_pixels_shift_hr); + } else { + int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6); + int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6); + int delaymask, shiftmask; + if (cmd & TOSCR_SPC_LORES) { + delaymask = fetchmode_mask >> 0; + shiftmask = 63; + } else { + delaymask = fetchmode_mask >> 1; + shiftmask = 31; + } + if (cmd & TOSCR_SPC_HIRES_START) { + toscr_res_pixels_mask_hr = 1 >> toscr_res_pixels_shift_hr; + } + if (cmd & TOSCR_SPC_LORES_START) { + toscr_res_pixels_mask_hr = 3 >> toscr_res_pixels_shift_hr; + } + int shifter[2]; + shifter[0] = (delay1 & delaymask) << LORES_TO_SHRES_SHIFT; + shifter[1] = (delay2 & delaymask) << LORES_TO_SHRES_SHIFT; + for (int oddeven = 0; oddeven < 2; oddeven++) { + int delay = shifter[oddeven]; + int diff = ((delay - delaypos) & shiftmask) >> toscr_res_pixels_shift_hr; + if (diff == 0) { + todisplay_copy_hr_oddeven(oddeven, fm); } + do_tosrc_hr(oddeven, 2, 1, fm); } } + delaypos += 1 << toscr_res_pixels_shift_hr; + nbits--; + difsize++; + if (cmd & TOSCR_SPC_LORES_END) { + toscr_res_pixels_mask_hr = 3 >> toscr_res_pixels_shift_hr; + } + if (cmd & TOSCR_SPC_HIRES_END) { + toscr_res_pixels_mask_hr = 1 >> toscr_res_pixels_shift_hr; + } + toscr_special_skip_ptr += 1 << toscr_res_pixels_shift_hr; + if (*toscr_special_skip_ptr == 0) { + toscr_special_skip_ptr = NULL; + break; + } } - if (nbits2) { - do_tosrc_hr(oddeven, 2, nbits2, fm); + if (nbits > 0) { + delay_cycles += difsize * (1 << toscr_res_pixels_shift_hr); + do_delays_3_aga_hr2(nbits, fm); + delay_cycles -= difsize * (1 << toscr_res_pixels_shift_hr); } + + } else { + do_delays_3_aga_hr2(nbits, fm); } } + STATIC_INLINE void do_delays_fast_3_aga_hr(int nbits, int fm) { int delaypos = delay_cycles; @@ -3139,20 +3369,7 @@ STATIC_INLINE void toscr_1_hr(int nbits, int fm) out_nbits += nbits; if (out_nbits == 64) { - if (out_offs < MAX_WORDS_PER_LINE * 2 / 4 - 1) { - uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4; - for (int i = 0; i < toscr_nr_planes2; i++) { - uae_u64 *dataptr64 = (uae_u64*)dataptr; - uae_u64 v = (outword64[i] >> 32) | (outword64[i] << 32); - if (*dataptr64 != v) { - thisline_changed = 1; - *dataptr64 = v; - } - dataptr += MAX_WORDS_PER_LINE * 2; - } - out_offs += 2; - } - out_nbits = 0; + toscr_1_hr_nbits(); } } @@ -3222,7 +3439,7 @@ static void toscr_hr_fm0(int nbits) { toscr_0_hr(nbits, 0); } static void toscr_hr_fm1(int nbits) { toscr_0_hr(nbits, 1); } static void toscr_hr_fm2(int nbits) { toscr_0_hr(nbits, 2); } -static void flush_plane_data_n(int fm, int hpos) +static void flush_plane_data_n(int fm) { // flush pending data if (out_nbits <= TOSCR_NBITS) { @@ -3238,7 +3455,7 @@ static void flush_plane_data_n(int fm, int hpos) } } -static void flush_plane_data_hr(int fm, int hpos) +static void flush_plane_data_hr(int fm) { // flush pending data if (out_nbits <= TOSCR_NBITSHR) { @@ -3266,6 +3483,19 @@ static void quick_add_delay_cycles(int total) } delay_cycles += total2; delay_cycles2 += total2; + + if (toscr_special_skip_ptr) { + int tot = total2; + while (tot > 0) { + toscr_special_skip_ptr++; + tot--; + if (*toscr_special_skip_ptr == 0) { + toscr_special_skip_ptr = NULL; + break; + } + } + } + total -= total2; if (total <= 0) { break; @@ -3279,12 +3509,12 @@ static void quick_add_delay_cycles(int total) } // flush remaining data but leave data after hsync -static void flush_plane_data(int fm, int hpos) +static void flush_plane_data(int fm) { if (currprefs.chipset_hr) { - flush_plane_data_hr(fm, hpos); + flush_plane_data_hr(fm); } else { - flush_plane_data_n(fm, hpos); + flush_plane_data_n(fm); } } @@ -3401,7 +3631,7 @@ static void hbstrt_bordercheck(int hpos, bool early) return; } // if HBSTRT re-enabled border (and HDIW was already open), BPL1DAT access will disable border again. - uae_u16 pos = hpos_to_diw(hpos); + uae_u16 pos = hpos_to_diwx(hpos); if (early) { pos -= 2; } @@ -3426,7 +3656,7 @@ static void beginning_of_plane_block_early(int hpos) thisline_decision.plfleft = left * 2; if (hdiwstate == diw_states::DIW_waiting_stop && thisline_decision.diwfirstword < 0) { // 1.5 lores pixels - int v = hpos_to_diw(hpos); + int v = hpos_to_diwx(hpos); v += 6; v = adjust_hr(v); thisline_decision.diwfirstword = coord_diw_shres_to_window_x(v); @@ -3903,7 +4133,7 @@ static void finish_final_fetch(int hpos) // This is really the end of scanline, we can finally flush all remaining data. //thisline_decision.plfright += flush_plane_data(fetchmode, hpos); - flush_plane_data(fetchmode, hpos); + flush_plane_data(fetchmode); // This can overflow if display setup is really bad. if (out_offs > MAX_PIXELS_PER_LINE / 32) { @@ -4428,12 +4658,12 @@ typedef int sprbuf_res_t, cclockres_t, hwres_t, bplres_t; /* handle very rarely needed playfield collision (CLXDAT bit 0) */ /* only known game needing this is Rotor */ -static void do_playfield_collisions(void) +static void do_playfield_collisions(int startpos, int endpos) { int bplres = output_res(bplcon0_res); hwres_t ddf_left = (thisline_decision.plfleft - DDF_OFFSET) << bplres; - hwres_t hw_diwlast = coord_window_to_diw_x(thisline_decision.diwlastword); - hwres_t hw_diwfirst = coord_window_to_diw_x(thisline_decision.diwfirstword); + hwres_t hw_diwlast = coord_window_to_diw_x(endpos); + hwres_t hw_diwfirst = coord_window_to_diw_x(startpos); int i, collided, minpos, maxpos; #ifdef AGA int planes = aga_mode ? 8 : 6; @@ -4459,6 +4689,7 @@ static void do_playfield_collisions(void) if (maxpos > hw_diwlast) { maxpos = hw_diwlast; } + for (i = minpos; i < maxpos && !collided; i += 32) { int offs = ((i << bplres) - ddf_left) >> 3; int j; @@ -4498,19 +4729,20 @@ static void do_playfield_collisions(void) /* Sprite-to-sprite collisions are taken care of in record_sprite. This one does playfield/sprite collisions. */ -static void do_sprite_collisions(void) +static void do_sprite_collisions(int startpos, int endpos) { int nr_sprites = curr_drawinfo[next_lineno].nr_sprites; int first = curr_drawinfo[next_lineno].first_sprite_entry; - unsigned int collision_mask = clxmask[clxcon >> 12]; + uae_u32 collision_mask = clxmask[clxcon >> 12]; int bplres = output_res(bplcon0_res); - hwres_t ddf_left = (thisline_decision.plfleft - DDF_OFFSET) << bplres; - hwres_t hw_diwlast = coord_window_to_diw_x(thisline_decision.diwlastword); - hwres_t hw_diwfirst = coord_window_to_diw_x(thisline_decision.diwfirstword); + int ddf_left = (thisline_decision.plfleft - DDF_OFFSET) << bplres; + int hw_diwlast = coord_window_to_diw_x(endpos); + int hw_diwfirst = coord_window_to_diw_x(startpos); if (clxcon_bpl_enable == 0 && !nr_sprites) { return; } + // all sprite to bitplane collision bits already set? if ((clxdat & 0x1fe) == 0x1fe) { return; @@ -4520,8 +4752,8 @@ static void do_sprite_collisions(void) struct sprite_entry *e = curr_sprite_entries + first + i; sprbuf_res_t minpos = e->pos; sprbuf_res_t maxpos = e->max; - hwres_t minp1 = minpos >> sprite_buffer_res; - hwres_t maxp1 = maxpos >> sprite_buffer_res; + int minp1 = minpos >> sprite_buffer_res; + int maxp1 = maxpos >> sprite_buffer_res; if (maxp1 > hw_diwlast) { maxp1 = hw_diwlast; @@ -4611,14 +4843,34 @@ static void do_sprite_collisions(void) #endif } -static void check_sprite_collisions(void) +static void check_collisions(int hpos) { + hpos += hpos_hsync_extra; + if (hpos < collision_hpos) { + return; + } + int startpos = thisline_decision.diwfirstword; + int endpos = thisline_decision.diwlastword; + if (startpos < 0 || endpos < 0) { + return; + } + int start = coord_diw_shres_to_window_x(collision_hpos << CCK_SHRES_SHIFT); + if (startpos < start) { + startpos = start; + } + int end = coord_diw_shres_to_window_x(hpos << CCK_SHRES_SHIFT); + if (endpos > end) { + endpos = end; + } if (sprites_enabled_this_line || brdspractive()) { - if (currprefs.collision_level > 1) - do_sprite_collisions(); - if (currprefs.collision_level > 2) - do_playfield_collisions(); + if (currprefs.collision_level > 1) { + do_sprite_collisions(startpos, endpos); + } } + if (currprefs.collision_level > 2) { + do_playfield_collisions(startpos, endpos); + } + collision_hpos = hpos; } static int tospritexdiw(int diw) @@ -4645,7 +4897,7 @@ static void record_sprite_1(int sprxp, uae_u16 *buf, uae_u32 datab, int num, int unsigned int col = 0; unsigned coltmp = 0; - if (sprxp >= sprite_minx || brdspractive() || hstrobe_conflict) + if ((sprxp >= sprite_minx) || brdspractive() || hstrobe_conflict) col = (datab & 3) << (2 * num); #if 0 if (sprxp == sprite_minx) @@ -4816,14 +5068,20 @@ static void add_sprite(int *countp, int num, int sprxp, int posns[], int nrs[]) nrs[j] = num; count++; *countp = count; + + sprites_enabled_this_line = true; } static void calcsprite(void) { sprite_minx = 0; + sprite_maxx = -1; if (thisline_decision.diwfirstword >= 0) { sprite_minx = tospritexdiw(thisline_decision.diwfirstword); } + if (thisline_decision.diwlastword >= 0) { + sprite_maxx = tospritexdiw(thisline_decision.diwfirstword); + } if (thisline_decision.plfleft >= 0) { int min, max; min = tospritexddf(thisline_decision.plfleft); @@ -4843,7 +5101,6 @@ static void calcsprite(void) * (undocumented feature) */ } - sprite_minx = 0; } static void decide_sprites(int hpos, bool usepointx, bool quick) @@ -4919,7 +5176,6 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) } // (not really mutually exclusive of SSCAN2-bit but not worth the trouble) } - sprites_enabled_this_line = true; } for (int i = 0; i < count; i++) { @@ -5160,6 +5416,8 @@ static void finish_decisions(int hpos) dp->ctable = thisline_decision.ctable; } + check_collisions(hpos); + if (next_color_change >= MAX_REG_CHANGE - 30) { write_log(_T("color_change buffer overflow!\n")); next_color_change = 0; @@ -5263,6 +5521,7 @@ static void reset_decisions_hsync_start(void) bpl1mod_hpos = -1; bpl2mod_hpos = -1; last_recorded_diw_hpos = 0; + collision_hpos = 0; compute_toscr_delay(bplcon1); @@ -6722,6 +6981,10 @@ static void vhpos_adj(uae_u16 *hpp, uae_u16 *vpp) { uae_u16 hp = *hpp; uae_u16 vp = *vpp; + hp++; + if (hp == maxhpos) { + hp = 0; + } if (hp <= 1) { // HP=0-1: VP = previous line. vp = vpos_prev; @@ -7468,6 +7731,8 @@ bool INTREQ_0(uae_u16 v) uae_u16 old = intreq; setclr(&intreq, v); + //write_log("%04x -> %04x %08x\n", old, intreq, M68K_GETPC); + if ((old & 0x0800) && !(intreq & 0x0800)) { serial_rbf_clear(); } @@ -7667,19 +7932,23 @@ static void BPLCON0_Denise(int hpos, uae_u16 v) } } -static void bpldmainitdelay(int hpos) +static void bpldmainit(int hpos, uae_u16 bplcon0) { BPLCON0_Denise(hpos, bplcon0); - setup_fmodes(hpos); + setup_fmodes(hpos, bplcon0); } static void BPLCON0(int hpos, uae_u16 v); -static void bplcon0_denise_change(int hpos, uae_u16 con0) + +static void bplcon0_denise_change_early(int hpos, uae_u16 con0) { - con0 = BPLCON0_Denise_mask(con0); - int np = GET_PLANES(con0); - if (bplcon0d != con0) { - bplcon0d = con0; + uae_u16 dcon0 = BPLCON0_Denise_mask(con0); + uae_u16 dcon0o = BPLCON0_Denise_mask(bplcon0); + + int np = GET_PLANES(dcon0); + int res = GET_RES_DENISE(dcon0); + if (bplcon0d != dcon0) { + bplcon0d = dcon0; bplcon0d_change = true; } if (np == toscr_nr_planes_shifter_new) { @@ -7695,10 +7964,42 @@ static void bplcon0_denise_change(int hpos, uae_u16 con0) toscr_nr_planes_shifter_new = np; if (ecs_denise || aga_mode) { - toscr_nr_changed = np != toscr_nr_planes3; + toscr_nr_changed = np != toscr_nr_planes3 && res == toscr_res; } toscr_nr_planes3 = np; + if (currprefs.chipset_hr && res != toscr_res) { + int oldres = toscr_res; + flush_display(fetchmode); + toscr_res = res; + toscr_res_old = res; + update_toscr_vars(); + compute_toscr_delay(bplcon1); + + if (aga_mode) { + if (oldres == RES_LORES && res == RES_HIRES) { + toscr_special_skip_ptr = toscr_spc_aga_lores_to_hires; + } + if (oldres == RES_HIRES && res == RES_LORES) { + toscr_special_skip_ptr = toscr_spc_aga_hires_to_lores; + } + } else if (1 && ecs_denise) { + if (oldres == RES_LORES && res == RES_HIRES) { + toscr_special_skip_ptr = toscr_spc_ecs_lores_to_hires; + } + if (oldres == RES_HIRES && res == RES_LORES) { + toscr_special_skip_ptr = toscr_spc_ecs_hires_to_lores; + } + } else if (1) { + if (oldres == RES_LORES && res == RES_HIRES) { + toscr_special_skip_ptr = toscr_spc_ocs_lores_to_hires; + } + if (oldres == RES_HIRES && res == RES_LORES) { + toscr_special_skip_ptr = toscr_spc_ocs_hires_to_lores; + } + } + } + #if 0 // TODO: handle mid resolution switches pixel-accurately. // OCS Denise, ECS Denise and AGA have different behavior @@ -7744,7 +8045,6 @@ static void bplcon0_denise_change(int hpos, uae_u16 con0) toscr_nr_planes2 = np; thisline_decision.max_planes = np; } - } static void BPLCON0(int hpos, uae_u16 v) @@ -7803,10 +8103,10 @@ static void BPLCON0(int hpos, uae_u16 v) updateextblk(); } - bpldmainitdelay(hpos); + bpldmainit(hpos, bplcon0); if (!copper_access) { - bplcon0_denise_change(hpos, bplcon0); + bplcon0_denise_change_early(hpos, bplcon0); } } @@ -8067,7 +8367,7 @@ static void FMODE(int hpos, uae_u16 v) SET_LINE_CYCLEBASED; fmode_saved = v; set_chipset_mode(); - bpldmainitdelay(hpos); + bpldmainit(hpos, bplcon0); record_register_change(hpos, 0x1fc, fmode); } @@ -8547,25 +8847,36 @@ static void SPRxPTL(int hpos, uae_u16 v, int num) #endif } -static void CLXCON(uae_u16 v) +static void CLXCON(int hpos, uae_u16 v) { + if (hpos >= 0) { + check_collisions(hpos); + } clxcon = v; clxcon_bpl_enable = (v >> 6) & 63; clxcon_bpl_match = v & 63; + //write_log("%08x %04x %d %d\n", M68K_GETPC, v, clxcon_bpl_enable, clxcon_bpl_match); } -static void CLXCON2(uae_u16 v) +static void CLXCON2(int hpos, uae_u16 v) { if (!aga_mode) return; + if (hpos >= 0) { + check_collisions(hpos); + } clxcon2 = v; clxcon_bpl_enable |= v & (0x40 | 0x80); clxcon_bpl_match |= (v & (0x01 | 0x02)) << 6; } -static uae_u16 CLXDAT(void) +static uae_u16 CLXDAT(int hpos) { + if (hpos >= 0) { + check_collisions(hpos); + } uae_u16 v = clxdat | 0x8000; + //write_log("%08x %04x\n", M68K_GETPC, v); clxdat = 0; return v; } @@ -9153,31 +9464,6 @@ static void decide_line(int endhpos) - Write word from new copper pointer to 8C */ -// "emulate" chip internal delays, not the right place but fast and 99.9% programs -// use only copper to write BPLCON1 etc.. (exception is HulkaMania/TSP..) -// this table should be filled with zeros and done somewhere else.. -static const int customdelay[]= { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 32 0x00 - 0x3e */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x40 - 0x5e */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x60 - 0x7e */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x80 - 0x9e */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 32 0xa0 - 0xde */ - /* BPLxPTH/BPLxPTL */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */ - /* BPLCON0-3,BPLMOD1-2 */ - 1+16,0,0,0,0,0,0,0, /* 8 */ - /* BPLxDAT */ - 0,0,0,0,0,0,0,0, /* 8 */ - /* SPRxPTH/SPRxPTL */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */ - /* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - /* COLORxx */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - /* RESERVED */ - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; - static void do_copper_fetch(int hpos, uae_u16 id) { if (scandoubled_line) { @@ -9406,16 +9692,17 @@ static void do_copper_fetch(int hpos, uae_u16 id) cop_state.last_strobe = 2; cop_state.state = COP_strobe_delay1; } else { - // FIX: all copper writes happen 1 cycle later than CPU writes - int type = customdelay[reg / 2]; - if (1 && type) { - if ((type >> 4) == 1) { - bplcon0_denise_change(hpos, data); - } + if (reg == 0x100) { + // BPLCON0 new value is needed early + bplcon0_denise_change_early(hpos, data); +#if 1 cop_state.moveaddr = reg; cop_state.movedata = data; - cop_state.movedelay = type & 15; + cop_state.movedelay = 1; cop_state.moveptr = cop_state.ip; +#else + custom_wput_copper(hpos, cop_state.ip, reg, data, 0); +#endif } else { custom_wput_copper(hpos, cop_state.ip, reg, data, 0); } @@ -9821,7 +10108,7 @@ static uae_u16 sprite_fetch(struct sprite *s, uaecptr pt, int hpos, int slot, in } #endif #ifdef DEBUGGER - int num = s - &spr[0]; + int num = (int)(s - &spr[0]); if (debug_dma) { record_dma_read(num * 8 + 0x140 + mode * 4 + slot * 2, pt, hpos, vpos, DMARECORD_SPRITE, num); } @@ -11349,7 +11636,6 @@ static void hsync_handler_pre(bool onvsync) // make sure decisions are done to end of scanline finish_partial_decision(maxhpos); clear_bitplane_pipeline(0); - check_sprite_collisions(); /* reset light pen latch */ if (vb_end_line) { @@ -12784,9 +13070,9 @@ void custom_reset(bool hardreset, bool keyboardreset) } refptr_p = refptr; FMODE(0, 0); - CLXCON(0); - CLXCON2(0); - setup_fmodes(0); + CLXCON(-1, 0); + CLXCON2(-1, 0); + setup_fmodes(0, bplcon0); beamcon0 = new_beamcon0 = beamcon0_saved = currprefs.ntscmode ? 0x00 : BEAMCON0_PAL; blt_info.blit_main = 0; blt_info.blit_finald = 0; @@ -12891,8 +13177,8 @@ void custom_reset(bool hardreset, bool keyboardreset) } #endif } - CLXCON(clxcon); - CLXCON2(clxcon2); + CLXCON(-1, clxcon); + CLXCON2(-1, clxcon2); calcdiw(); v = serper; serper = 0; @@ -12921,7 +13207,7 @@ void custom_reset(bool hardreset, bool keyboardreset) for (int i = 0; i < MAX_SPRITES; i++) { spr[i].width = sprite_width; } - setup_fmodes(0); + setup_fmodes(0, bplcon0); shdelay_disabled = false; #ifdef ACTION_REPLAY @@ -13090,7 +13376,7 @@ static uae_u32 REGPARAM2 custom_wget_1(int hpos, uaecptr addr, int noput, bool i case 0x00A: v = JOY0DAT (); break; case 0x00C: v = JOY1DAT (); break; - case 0x00E: v = CLXDAT (); break; + case 0x00E: v = CLXDAT (hpos); break; case 0x010: v = ADKCONR (); break; case 0x012: v = POT0DAT (); break; @@ -13265,7 +13551,7 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n } switch (addr) { - case 0x00E: CLXDAT(); break; + case 0x00E: CLXDAT(hpos); break; case 0x020: DSKPTH(value); break; case 0x022: DSKPTL(value); break; @@ -13321,7 +13607,7 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n case 0x094: DDFSTOP(hpos, value); break; case 0x096: DMACON(hpos, value); break; - case 0x098: CLXCON(value); break; + case 0x098: CLXCON(hpos, value); break; case 0x09A: INTENA(value); break; case 0x09C: INTREQ(value); break; case 0x09E: ADKCON(hpos, value); break; @@ -13381,7 +13667,7 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n case 0x108: BPL1MOD(hpos, value); break; case 0x10A: BPL2MOD(hpos, value); break; #ifdef AGA - case 0x10E: CLXCON2(value); break; + case 0x10E: CLXCON2(hpos, value); break; #endif case 0x110: BPLxDAT(hpos, 0, value); break; @@ -13697,7 +13983,7 @@ uae_u8 *restore_custom(uae_u8 *src) ddfstrt = RW; /* 092 DDFSTRT */ ddfstop = RW; /* 094 DDFSTOP */ dmacon = RW & ~(0x2000|0x4000); /* 096 DMACON */ - CLXCON(RW); /* 098 CLXCON */ + CLXCON(-1, RW); /* 098 CLXCON */ intena = RW; /* 09A INTENA */ intreq = RW; /* 09C INTREQ */ adkcon = RW; /* 09E ADKCON */ @@ -14265,7 +14551,7 @@ uae_u8 *restore_cycles(uae_u8 *src) extra_cycle = restore_u32(); if (extra_cycle >= 2 * CYCLE_UNIT) extra_cycle = 0; - write_log(_T("RESTORECYCLES %08lX\n"), start_cycles); + write_log(_T("RESTORECYCLES %08llX\n"), start_cycles); return src; } -- 2.47.3