From: Toni Wilen Date: Sun, 29 Aug 2021 16:59:16 +0000 (+0300) Subject: Custom chipset WIP updates. X-Git-Tag: 4900~79 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=041c1fbe5706f7ca5c7eece0809837c8f2c71285;p=francis%2Fwinuae.git Custom chipset WIP updates. --- diff --git a/blitter.cpp b/blitter.cpp index 3a058259..c9725631 100644 --- a/blitter.cpp +++ b/blitter.cpp @@ -394,12 +394,12 @@ static void check_channel_mods(int hpos, int ch, uaecptr *pt) if (bltptxpos != hpos) return; if (ch == bltptxc) { - bltptxpos = -1; - *pt = bltptx; if (blit_warned > 0) { write_log(_T("BLITTER: %08X -> %08X write to %cPT ignored! %08x\n"), bltptx, *pt, ch + 'A' - 1, m68k_getpc()); blit_warned--; } + bltptxpos = -1; + *pt = bltptx; } } @@ -913,6 +913,7 @@ static void blit_bltset(int con) blit_changed = true; if (blit_warned > 0) { write_log(_T("BLITTER: BLTCON0 %04x -> %04x BLTCON1 %04x -> %04x PC=%08x (%d %d)\n"), bltcon0_old, bltcon0, bltcon1_old, bltcon1, M68K_GETPC, current_hpos(), vpos); + blitter_dump(); blitshifterdebug(bltcon0_old, false); blit_warned--; //activate_debugger(); diff --git a/custom.cpp b/custom.cpp index 50e22445..93adae57 100644 --- a/custom.cpp +++ b/custom.cpp @@ -51,7 +51,6 @@ #define CYCLE_CONFLICT_LOGGING 0 #define SPEEDUP 1 - #define CUSTOM_DEBUG 0 #define SPRITE_DEBUG 0 #define SPRITE_DEBUG_MINY 0 @@ -72,7 +71,7 @@ #define EXTRAWIDTH_BROADCAST 15 #define EXTRAHEIGHT_BROADCAST_TOP 0 #define EXTRAHEIGHT_BROADCAST_BOTTOM 0 -#define EXTRAWIDTH_EXTREME 31 +#define EXTRAWIDTH_EXTREME 33 #define EXTRAHEIGHT_EXTREME 24 #define LORES_TO_SHRES_SHIFT 2 @@ -326,14 +325,15 @@ static uae_u16 bplcon3_saved, bplcon4_saved; static int varsync_changed; uae_u16 vtotal, htotal; static int maxvpos_stored, maxhpos_stored; -uae_u16 hsstop, hsstrt; +uae_u16 hsstop, hsstop_detect, hsstrt; static uae_u16 hbstop, hbstrt; static uae_u16 vsstop, vsstrt; -static uae_u16 vbstop, vbstrt; -static uae_u16 hcenter; +static uae_u16 vbstop, vbstopm1, vbstrt; +static uae_u16 hcenter, hcenter_v2, hcenter_v2_end; static uae_u16 hbstop_v, hbstrt_v, hbstop_v2, hbstrt_v2, hbstrt_v2o, hbstop_v2o; static int vsstrt_m, vsstop_m, vbstrt_m, vbstop_m; -static bool vs_state, vb_state, vb_end_line; +static bool vb_state, vb_end_line; +static bool vs_state, vs_state_on, vs_state_hw; static bool vb_end_next_line; static int vb_start_line; static bool ocs_blanked; @@ -358,6 +358,7 @@ struct sprite { int dmastate; int dmacycle; int width; + bool ecs_denise_hires; uae_u16 ctl, pos; #ifdef AGA @@ -369,7 +370,6 @@ struct sprite { static struct sprite spr[MAX_SPRITES]; static int plfstrt_sprite; - uaecptr sprite_0; int sprite_0_width, sprite_0_height, sprite_0_doubled; uae_u32 sprite_0_colors[4]; @@ -413,7 +413,7 @@ enum diw_states static int plffirstline, plflastline; int plffirstline_total, plflastline_total; -int vblank_firstline_hw, vblank_lastline_hw; +int vblank_firstline_hw; static int autoscale_bordercolors; static int plfstrt, plfstop; static int sprite_minx; @@ -429,6 +429,8 @@ static int diwstate_vpos; static int bpl_hstart; static bool exthblank, exthblank_state; static int last_diw_hpos, last_diw_hpos2; +static int last_recorded_diw_hpos; +static int last_hblank_start; int first_planes_vpos, last_planes_vpos; static int first_bplcon0, first_bplcon0_old; @@ -535,6 +537,7 @@ static int bprun; static int bprun_cycle; static int bprun_pipeline_flush_delay; static bool plane0, plane0p, plane0p_enabled, plane0p_forced, plane0_first_done; +static int last_bpl1dat_hpos; static bool harddis_v, harddis_h; static uae_u16 dmal_alloc_mask; @@ -609,6 +612,19 @@ STATIC_INLINE int nodraw(void) return !currprefs.cpu_memory_cycle_exact && ad->framecnt != 0; } +STATIC_INLINE int diw_to_hpos(int diw) +{ + diw /= 4; + diw += DDF_OFFSET; + diw /= 2; + return diw; +} + +STATIC_INLINE int hpos_to_diw(int pos) +{ + return ((pos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4; +} + static int doflickerfix(void) { return currprefs.gfx_vresolution && doublescan < 0 && vpos < MAXVPOS; @@ -646,17 +662,26 @@ static void setclr(uae_u16 *p, uae_u16 val) } } -static void adjust_hr(uae_u16 *vp) +static int adjust_hr(int v) { - uae_u16 v = *vp; if (currprefs.chipset_hr) { v &= ~(3 >> currprefs.gfx_resolution); } else { v &= ~3; } - *vp = v; + return v; +} +static int adjust_hr2(int v) +{ + if (currprefs.chipset_hr) { + v &= ~(1 >> currprefs.gfx_resolution); + } else { + v &= ~1; + } + return v; } + static void alloc_cycle(int hpos, int type) { #ifdef CPUEMU_13 @@ -837,14 +862,15 @@ static void hblank_reset(int hblankpos) if (thisline_decision.plfleft < 0) { return; } - hb_last_diwlastword = coord_diw_shres_to_window_x(hblankpos); + // border re-enable takes 1 lores pixel + hb_last_diwlastword = hblankpos + 4; SET_LINE_CYCLEBASED; } static void record_color_change2(int hpos, int regno, uae_u32 value) { color_change *cc; - int pos = hpos < 0 ? -hpos : ((hpos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4; + int pos = hpos < 0 ? -hpos : hpos_to_diw(hpos); if (scandoubled_line) { return; @@ -878,13 +904,46 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) } } + // HCENTER blanking + if (hcenter_v2 && vs_state_on && vpos < maxvpos_display_vsync && lof_current) { + int chpos = pos; + if (hcenter_v2_end == 0xffff && hcenter_v2 < chpos && hcenter_v2 >= last_recorded_diw_hpos) { + cc = &curr_color_changes[next_color_change]; + cc->linepos = hcenter_v2; + cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; + cc->value = 1; + next_color_change++; + cc[1].regno = -1; + last_recorded_diw_hpos = cc->linepos; + hcenter_v2_end = hcenter_v2; + hcenter_v2_end += ((beamcon0 & 0x20) ? 8 : 9) << CCK_SHRES_SHIFT; + if (hcenter_v2_end >= maxhpos << CCK_SHRES_SHIFT) { + hcenter_v2_end -= maxhpos << CCK_SHRES_SHIFT; + } + if (debug_dma) { + record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos); + } + } + if (!exthblank_state && hcenter_v2_end < chpos && hcenter_v2_end >= last_recorded_diw_hpos) { + cc = &curr_color_changes[next_color_change]; + cc->linepos = hcenter_v2_end; + cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; + cc->value = 0; + next_color_change++; + cc[1].regno = -1; + last_recorded_diw_hpos = cc->linepos; + hcenter_v2_end = 0xffff; + if (debug_dma) { + record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos); + } + } + } + if (exthblank) { - cc = &curr_color_changes[next_color_change]; - int prevpos = last_color_change == next_color_change ? 0 : cc[-1].linepos; int chpos = pos; // inject programmed hblank start and end in color changes - if (hbstrt_v2 <= hbstop_v2) { - if (chpos >= hbstrt_v2 && prevpos < hbstrt_v2) { + if (hbstrt_v2 < hbstop_v2) { + if (hbstrt_v2 < chpos && hbstrt_v2 >= last_recorded_diw_hpos) { cc = &curr_color_changes[next_color_change]; cc->linepos = hbstrt_v2; cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; @@ -893,8 +952,21 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) cc[1].regno = -1; hblank_reset(hbstrt_v2); exthblank_state = true; + last_recorded_diw_hpos = cc->linepos; + last_hblank_start = cc->linepos; + if (debug_dma) { + record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos); + } } - if (chpos >= hbstop_v2 && prevpos < hbstop_v2) { + if (hbstop_v2 < chpos && hbstop_v2 >= last_recorded_diw_hpos) { + // do_color_changes() HBLANK workaround + if (next_color_change == last_color_change && exthblank_state) { + cc = &curr_color_changes[next_color_change]; + cc->linepos = 0; + cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; + cc->value = 1; + next_color_change++; + } cc = &curr_color_changes[next_color_change]; cc->linepos = hbstop_v2; cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; @@ -902,9 +974,20 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) next_color_change++; cc[1].regno = -1; exthblank_state = false; + last_recorded_diw_hpos = cc->linepos; + if (debug_dma) { + record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos); + } } - } else { - if (chpos >= hbstop_v2 && prevpos < hbstop_v2) { + } else if (hbstrt_v2 > hbstop_v2) { + if (hbstop_v2 < chpos && hbstop_v2 >= last_recorded_diw_hpos) { + if (next_color_change == last_color_change && exthblank_state) { + cc = &curr_color_changes[next_color_change]; + cc->linepos = 0; + cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; + cc->value = 1; + next_color_change++; + } cc = &curr_color_changes[next_color_change]; cc->linepos = hbstop_v2; cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; @@ -912,8 +995,12 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) next_color_change++; cc[1].regno = -1; exthblank_state = false; + last_recorded_diw_hpos = cc->linepos; + if (debug_dma) { + record_dma_event(DMA_EVENT_HBE, diw_to_hpos(cc->linepos), vpos); + } } - if (chpos >= hbstrt_v2 && prevpos < hbstrt_v2) { + if (hbstrt_v2 < chpos && hbstrt_v2 >= last_recorded_diw_hpos) { cc = &curr_color_changes[next_color_change]; cc->linepos = hbstrt_v2; cc->regno = RECORDED_REGISTER_CHANGE_OFFSET + 0x200; @@ -922,6 +1009,11 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) cc[1].regno = -1; hblank_reset(hbstrt_v2); exthblank_state = true; + last_recorded_diw_hpos = cc->linepos; + last_hblank_start = cc->linepos; + if (debug_dma) { + record_dma_event(DMA_EVENT_HBS, diw_to_hpos(cc->linepos), vpos); + } } } } @@ -934,20 +1026,34 @@ static void record_color_change2(int hpos, int regno, uae_u32 value) next_color_change++; cc[1].regno = -1; } + + if (pos > last_recorded_diw_hpos) { + last_recorded_diw_hpos = pos; + } + +} + +static void sync_color_changes(int hpos) +{ + record_color_change2(hpos, 0xffff, 0); } // hdiw opened again in same scanline // erase (color0 or bblank) area between previous end and new start static void hdiw_restart(int diw_last, int diw_current) { + if (diw_last >= diw_current) { + return; + } // update state - record_color_change2(-(diw_current - 1), 0xffff, 0); + diw_current = adjust_hr(diw_current); + record_color_change2(-diw_current, 0xffff, 0); // find slot to insert into int i; for (i = last_color_change; i < next_color_change; i++) { struct color_change *cc = &curr_color_changes[i]; - if (cc->linepos >= diw_last) { + if (cc->linepos > diw_last) { break; } } @@ -970,50 +1076,62 @@ static void hdiw_restart(int diw_last, int diw_current) * machine at the current position. It might have changed since we last * checked. */ -static void decide_diw_check_start(int start_diw_hpos, int end_diw_hpos) +static void decide_diw_check_start(int start_diw_hpos, int end_diw_hpos, int extrahpos) { if (hdiwstate == DIW_waiting_start) { - if (diw_hstrt > start_diw_hpos && diw_hstrt <= end_diw_hpos) { - int first = diwfirstword + coord_diw_shres_to_window_x(hpos_hsync_extra << CCK_SHRES_SHIFT); + if (diw_hstrt > start_diw_hpos && diw_hstrt < end_diw_hpos) { + int first = diwfirstword + extrahpos; if (last_diwlastword >= 0) { + int first2 = first * 2; + first2 = adjust_hr(first2); // was closed previously in same line: blank closed part. - hdiw_restart(last_diwlastword * 2, first * 2); + hdiw_restart(last_diwlastword, first2); last_diwlastword = -1; + if (debug_dma) { + record_dma_event(DMA_EVENT_HDIWS, diw_to_hpos(first2), vpos); + } } if (thisline_decision.diwfirstword < 0) { - thisline_decision.diwfirstword = first; + thisline_decision.diwfirstword = adjust_hr2(first); // opened before first BPL1DAT? if (!plane0_first_done) { plane0p_enabled = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20); } + if (debug_dma) { + record_dma_event(DMA_EVENT_HDIWS, diw_to_hpos(first), vpos); + } } hdiwstate = DIW_waiting_stop; } } } -static void decide_diw_check_stop(int start_diw_hpos, int end_diw_hpos) +static void decide_diw_check_stop(int start_diw_hpos, int end_diw_hpos, int extrahpos) { if (hdiwstate == DIW_waiting_stop) { if (diw_hstop > start_diw_hpos && diw_hstop <= end_diw_hpos) { - int last = diwlastword + coord_diw_shres_to_window_x(hpos_hsync_extra << CCK_SHRES_SHIFT); + int last = diwlastword + extrahpos; if (last > thisline_decision.diwlastword) { - thisline_decision.diwlastword = last; + thisline_decision.diwlastword = adjust_hr2(last); // if HDIW opens again in same line - last_diwlastword = thisline_decision.diwlastword; + int v = thisline_decision.diwlastword * 2; + last_diwlastword = adjust_hr(v); + if (debug_dma) { + record_dma_event(DMA_EVENT_HDIWE, diw_to_hpos(last), vpos); + } } hdiwstate = DIW_waiting_start; } } } -static void decide_diw_check(int start_diw_hpos, int end_diw_hpos) +static void decide_diw_check(int start_diw_hpos, int end_diw_hpos, int extrahpos) { - if (diw_hstrt <= diw_hstop) { - decide_diw_check_start(start_diw_hpos, end_diw_hpos); - decide_diw_check_stop(start_diw_hpos, end_diw_hpos); + if (diw_hstrt < diw_hstop) { + decide_diw_check_start(start_diw_hpos, end_diw_hpos, extrahpos); + decide_diw_check_stop(start_diw_hpos, end_diw_hpos, extrahpos); } else { - decide_diw_check_stop(start_diw_hpos, end_diw_hpos); - decide_diw_check_start(start_diw_hpos, end_diw_hpos); + decide_diw_check_stop(start_diw_hpos, end_diw_hpos, extrahpos); + decide_diw_check_start(start_diw_hpos, end_diw_hpos, extrahpos); } } @@ -1029,22 +1147,26 @@ static void decide_diw(int hpos) if (hpos2 <= last_diw_hpos2) { return; } - - int start_diw_hpos = last_diw_hpos * 2 + 1; - int end_diw_hpos = hpos * 2 + 1; + int start_diw_hpos = ((last_diw_hpos * 2 - DDF_OFFSET + 1) << 2) + 3; + int end_diw_hpos = (hpos * 2 + 1) << 2; + // should handle wrap around.. + if (start_diw_hpos < ((1 << 2) + 3)) { + start_diw_hpos = (1 << 2) + 3; + } + int extrahpos = coord_diw_shres_to_window_x(hpos_hsync_extra << CCK_SHRES_SHIFT); if (!ecs_denise && vpos <= get_equ_vblank_endline()) { // free running horizontal counter - start_diw_hpos = diw_hcounter; - end_diw_hpos = diw_hcounter + end_diw_hpos; - decide_diw_check(start_diw_hpos, end_diw_hpos); - if (end_diw_hpos >= maxhpos * 2 + 1) { - start_diw_hpos = 1; - end_diw_hpos -= maxhpos * 2 + 1; - decide_diw_check(start_diw_hpos, end_diw_hpos); + start_diw_hpos = (diw_hcounter & 511) << 2; + end_diw_hpos = start_diw_hpos + end_diw_hpos; + decide_diw_check(start_diw_hpos, end_diw_hpos, extrahpos); + if (end_diw_hpos >= (512 << 2)) { + start_diw_hpos = -1; + end_diw_hpos -= (512 << 2); + decide_diw_check(start_diw_hpos, end_diw_hpos, extrahpos); } } else { - decide_diw_check(start_diw_hpos, end_diw_hpos); + decide_diw_check(start_diw_hpos, end_diw_hpos, extrahpos); } last_diw_hpos = hpos; last_diw_hpos2 = hpos2; @@ -1264,12 +1386,14 @@ static void clear_bitplane_pipeline(int type) #define ESTIMATED_FETCH_MODE 1 #define OPTIMIZED_ESTIMATE 1 -static uae_u8 estimated_cycles_buf[256]; +static uae_u8 estimated_cycles_buf0[256]; +static uae_u8 estimated_cycles_buf1[256]; static uae_u8 estimated_cycles_empty[256]; static int estimate_cycles_empty_index = -1; static uae_u16 estimated_bplcon0, estimated_fm, estimated_plfstrt, estimated_plfstop; static uae_u8* estimated_cycles = estimated_cycles_empty; static bool estimated_empty; +static int estimated_maxhpos[2]; #if ESTIMATED_FETCH_MODE @@ -1288,11 +1412,11 @@ static void end_estimate_last_fetch_cycle(int hpos) estimate_cycles_empty_index = hpos; for (int i = 0; i < RGA_PIPELINE_ADJUST; i++) { int pos = (hpos + i) % maxhpos; - estimated_cycles_empty[pos] = estimated_cycles_buf[pos]; + estimated_cycles_empty[pos] = maxhposeven ? estimated_cycles_buf1[pos] : estimated_cycles_buf0[pos]; } } #else - estimated_cycles = estimated_cycles_buf; + estimated_cycles = estimated_cycles_buf0; int start_pos = (hpos + RGA_PIPELINE_ADJUST) % maxhpos; if (start_pos >= hpos) { memset(estimated_cycles + start_pos, 0, maxhpos - start_pos); @@ -1314,8 +1438,16 @@ static void estimate_last_fetch_cycle(int hpos) #if OPTIMIZED_ESTIMATE if (estimated_bplcon0 == bplcon0 && plfstrt == hpos && estimated_plfstrt == plfstrt && estimated_plfstop == plfstop && estimated_fm == fetchmode) { - estimated_cycles = estimated_cycles_buf; - return; + if (maxhpos == estimated_maxhpos[0]) { + estimated_cycles = estimated_cycles_buf0; + return; + } + if (maxhpos == estimated_maxhpos[1]) { + estimated_cycles = estimated_cycles_buf1; + return; + } + } else { + estimated_maxhpos[0] = estimated_maxhpos[1] = -1; } #endif #if 0 @@ -1375,7 +1507,11 @@ static void estimate_last_fetch_cycle(int hpos) estimated_cycle_count = (starting_last_block_at - fc) + lastfetchunit; } - estimated_cycles = estimated_cycles_buf; +#if OPTIMIZED_ESTIMATE + estimated_cycles = maxhposeven ? estimated_cycles_buf1 : estimated_cycles_buf0; +#else + estimated_cycles = estimated_cycles_buf0; +#endif // bitplane DMA end can wrap around, even in non-overrun cases int start_pos = (hpos + RGA_PIPELINE_ADJUST) % maxhpos; int start_pos2 = start_pos; @@ -1425,8 +1561,11 @@ static void estimate_last_fetch_cycle(int hpos) estimated_plfstrt = plfstrt; estimated_plfstop = plfstop; estimated_fm = fetchmode; + estimated_maxhpos[maxhposeven] = maxhpos; } else { estimated_fm = 0xffff; + estimated_maxhpos[0] = -1; + estimated_maxhpos[1] = -1; } #endif } @@ -1551,6 +1690,7 @@ static void set_chipset_mode(void) spr[i].width = sprite_width; } shdelay_disabled = false; + exthblank_state = false; calcdiw(); } @@ -1791,36 +1931,24 @@ static void setup_fmodes(int hpos) SET_LINE_CYCLEBASED; } -static int fetch_warn(int nr, int hpos) +static int fetch_warn(int nr, int hpos, bool *addmodulop) { static int warned1 = 30, warned2 = 30; int add = fetchmode_bytes; - if (cycle_line_slot[hpos] == CYCLE_REFRESH) { + if (cycle_line_slot[hpos] == CYCLE_STROBE) { if (warned1 >= 0) { - write_log(_T("WARNING: BPL fetch conflictconflicts with strobe refresh slot, hpos %02X!\n"), hpos); + write_log(_T("WARNING: BPL strobe refresh conflict, hpos %02X!\n"), hpos); warned1--; } + *addmodulop = false; add = refptr_val; } else { if (warned2 >= 0) { warned2--; - write_log(_T("WARNING: BPL fetch at hpos %02X!\n"), hpos); + write_log(_T("WARNING: BPL refresh conflict, hpos %02X!\n"), hpos); } add = refptr_val; - } - if (beamcon0 & 0x80) { - add = fetchmode_bytes; - } else { -#if 0 - line_cyclebased = vpos; - corrupt_offset = (vpos ^ (timeframes << 12)) & 0xff00; - for (int i = 0; i < bplcon0_planes_limit; i++) { - uae_u16 v; - v = bplpt[i] & 0xffff; - v += corrupt_offset; - bplpt[i] = (bplpt[i] & 0xffff0000) | v; - } -#endif + *addmodulop = false; } return add; } @@ -1829,11 +1957,17 @@ static bool fetch(int nr, int fm, int hpos, bool addmodulo) { int add = fetchmode_bytes; - if (cycle_line_slot[hpos] == CYCLE_REFRESH || cycle_line_slot[hpos] == CYCLE_STROBE) { + if (cycle_line_slot[hpos] == CYCLE_STROBE) { + // strobe refresh conflict + add = fetch_warn(nr, hpos, &addmodulo); + } else if (cycle_line_slot[hpos] == CYCLE_REFRESH) { // refresh conflict - add = fetch_warn(nr, hpos); + add = fetch_warn(nr, hpos, &addmodulo); } else if (cycle_line_slot[hpos] == CYCLE_MISC) { // DMAL conflict + // AUDxDAT AND BPLxDAT = read-only register + // DSKDATR AND BLPxDAT = read-only register + // DSKDAT AND BPLxDAT = read-only register return false; } else { cycle_line_slot[hpos] = CYCLE_BITPLANE; @@ -2760,17 +2894,22 @@ static void update_toscr_planes(int fm) thisline_decision.nr_planes = toscr_nr_planes_agnus; } -static void hbstrt_bordercheck(int hpos) +static void hbstrt_bordercheck(int hpos, bool early) { + if (exthblank) { + sync_color_changes(hpos); + } if (hb_last_diwlastword < 0) { return; } // if HBSTRT re-enabled border (and HDIW was already open), BPL1DAT access will disable border again. - record_color_change2(hpos - 1, 0xffff, 0); - uae_u16 pos = (((hpos + hpos_hsync_extra) * 2 - DDF_OFFSET) * 4); + uae_u16 pos = hpos_to_diw(hpos); + if (early) { + pos -= 2; + } pos -= 2; // 1 hires pixel early - adjust_hr(&pos); - hdiw_restart(hb_last_diwlastword * 2, coord_diw_shres_to_window_x(pos * 2)); + pos = adjust_hr(pos); + hdiw_restart(hb_last_diwlastword, pos); hb_last_diwlastword = -1; } @@ -2789,9 +2928,13 @@ static void beginning_of_plane_block_early(int hpos) thisline_decision.plfleft = left * 2; if (hdiwstate == DIW_waiting_stop && thisline_decision.diwfirstword < 0) { // 1.5 lores pixels - thisline_decision.diwfirstword = coord_diw_shres_to_window_x(((left - DDF_OFFSET / 2) << CCK_SHRES_SHIFT) + 6); + int v = hpos_to_diw(hpos); + v += 6; + v = adjust_hr(v); + thisline_decision.diwfirstword = coord_diw_shres_to_window_x(v); + } - hbstrt_bordercheck(hpos); + hbstrt_bordercheck(hpos, false); } /* Called when all planes have been fetched, i.e. when a new block @@ -2814,6 +2957,7 @@ static void beginning_of_plane_block(int hpos) todisplay_fetched = 3; sprites_enabled_this_line = true; plane0_first_done = true; + last_bpl1dat_hpos = hpos; if (thisline_decision.plfleft < 0) { int left = hpos + hpos_hsync_extra; @@ -2828,7 +2972,7 @@ static void beginning_of_plane_block(int hpos) } } - hbstrt_bordercheck(hpos); + hbstrt_bordercheck(hpos, true); update_denise(hpos); if (toscr_nr_planes_agnus > thisline_decision.nr_planes) { @@ -3521,6 +3665,9 @@ static void update_fetch(int until, int fm) bprun_pipeline_flush_delay = 0; } } + if (plane0) { + last_bpl1dat_hpos = hpos; + } } } #endif @@ -3597,13 +3744,13 @@ static void decide_vline(void) } static void update_copper(int until_hpos); -static void decide_sprite_fetch(int endhpos); +static void decide_sprites_fetch(int endhpos); static void decide_line(int endhpos); static void decide_line_decision_fetches(int endhpos) { decide_bpl_fetch(endhpos); - decide_sprite_fetch(endhpos); + decide_sprites_fetch(endhpos); } static void decide_fetch_safe(int endhpos) @@ -3760,7 +3907,7 @@ static void do_playfield_collisions(void) if (maxpos > hw_diwlast) { maxpos = hw_diwlast; } - for (i = minpos; i < maxpos && !collided; i+= 32) { + for (i = minpos; i < maxpos && !collided; i += 32) { int offs = ((i << bplres) - ddf_left) >> 3; int j; uae_u32 total = 0xffffffff; @@ -4156,7 +4303,7 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) return; point = (hpos + hpos_hsync_extra) * 2 - DDF_OFFSET; - if (point == last_sprite_point) { + if (point <= last_sprite_point) { return; } @@ -4179,7 +4326,7 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) int hw_xp = sprxp >> sprite_buffer_res; int pointx = usepointx && (s->ctl & sprite_sprctlmask) ? 0 : 1; - if (xpos < 0) { + if (hw_xp <= 0 || hw_xp > maxhpos * 2 + 1) { continue; } @@ -4191,6 +4338,12 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) continue; } + if (s->ecs_denise_hires && (bplcon0d & 0x0040)) { + xpos |= 2 >> (RES_MAX - sprite_buffer_res); + sprxp = xpos; + hw_xp = sprxp >> sprite_buffer_res; + } + if (hw_xp > last_sprite_point && hw_xp <= point + pointx) { add_sprite(&count, i, sprxp, posns, nrs); } @@ -4202,7 +4355,7 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) if (hw_xp > last_sprite_point && hw_xp <= point + pointx) { add_sprite(&count, MAX_SPRITES + i, sprxp, posns, nrs); } - } else if (!(fmode & 0x80) && xpos >= (2 << sprite_buffer_res) && xpos <= (extrahpos << sprite_buffer_res)) { + } else if (xpos >= (2 << sprite_buffer_res) && xpos <= (extrahpos << sprite_buffer_res)) { // right border wrap around. SPRxCTL horizontal bits do not matter. sprxp += (maxhpos * 2) << sprite_buffer_res; hw_xp = sprxp >> sprite_buffer_res; @@ -4216,6 +4369,10 @@ static void decide_sprites(int hpos, bool usepointx, bool quick) for (int i = 0; i < count; i++) { int nr = nrs[i] & (MAX_SPRITES - 1); struct sprite *s = &spr[nr]; + if (s->ecs_denise_hires && !(bplcon0d & 0x40)) { + s->data[0] &= 0x7fff; + s->datb[0] &= 0x7fff; + } record_sprite(nr, posns[i], s->data, s->datb, s->ctl); /* get left and right sprite edge if brdsprt enabled */ @@ -4263,17 +4420,6 @@ static void decide_sprites(int hpos) { decide_sprites(hpos, false, false); } -static void maybe_decide_sprites(int spnr, int hpos) -{ - struct sprite *s = &spr[spnr]; - if (!s->armed) { - return; - } - if (!s->data && !s->datb) { - return; - } - decide_sprites(hpos, true, true); -} static int sprites_differ(struct draw_info *dip, struct draw_info *dip_old) { @@ -4364,7 +4510,7 @@ static void finish_decisions(int hpos) thisline_decision.bplres = output_res(RES_LORES); } - record_color_change2(hpos + 1, 0xffff, 0); + sync_color_changes(hpos + 1); /* Large DIWSTOP values can cause the stop position never to be * reached, so the state machine always stays in the same state and @@ -4451,7 +4597,6 @@ static void reset_decisions_scanline_start(void) last_copper_hpos = 0; ddfstrt_hpos = -1; ddfstop_hpos = -1; - sprites_enabled_this_line = false; last_diw_hpos = 0; last_diw_hpos2 = 0; @@ -4502,8 +4647,10 @@ static void reset_decisions_hsync_start(void) next_sprite_forced = 1; last_sprite_point = 0; + sprites_enabled_this_line = false; bpl1mod_hpos = -1; bpl2mod_hpos = -1; + last_recorded_diw_hpos = 0; compute_toscr_delay(bplcon1); @@ -4537,7 +4684,7 @@ static void reset_decisions_hsync_start(void) //bool t = thisline_decision.plfleft >= 0 && (thisline_decision.vb & 1) == 0 && !vb_state && !vb_end_line; thisline_decision.vb = vb_start_line > 1 + vblank_extraline ? 0 : 1; // if programmed vblank - if (!thisline_decision.vb && (beamcon0 & 0x1000) && aga_mode) { + if (!thisline_decision.vb && (beamcon0 & 0x1000) && ecs_agnus) { thisline_decision.vb |= 2; } if (!ecs_denise && vb_end_line && currprefs.cs_ocshblankbug) { @@ -4572,7 +4719,7 @@ static void reset_decisions_hsync_start(void) if (1 && fetchmode >= 2 && !doflickerfix()) { // handle bitplane data wrap around bool toshift = false; - if ((exthblank || (beamcon0 & 0x0110)) && thisline_decision.bplres == 0) { + if ((exthblank || (beamcon0 & 0x0110)) && (thisline_decision.bplres == 0 || currprefs.chipset_hr)) { for (int i = 0; i < thisline_decision.nr_planes; i++) { if (todisplay2_aga_saved[i]) { toshift = true; @@ -4604,6 +4751,30 @@ static void reset_decisions_hsync_start(void) bprun_pipeline_flush_delay = maxhpos; plane0p_enabled = true; plane0p_forced = true; + + // HBLANK start before HSYNC (or HBLANK never triggered) and BPL1DAT between HBLANK and HSYNC? + if (exthblank) { + int hblankstart = 0; + if (last_hblank_start >= 0) { + hblankstart = diw_to_hpos(last_hblank_start + 4); + } + else { + hblankstart = last_bpl1dat_hpos - 1; + } + int bpl1 = last_bpl1dat_hpos; + if (bpl1 < hblankstart) { + bpl1 += maxhpos; + } + int hp = hpos; + if (hp < hblankstart || hp < bpl1) { + hp += maxhpos; + } + int comp = maxhpos / 2 - 1; + if (bpl1 > hblankstart && bpl1 < hp && (bpl1 - hblankstart) < comp && (bpl1 - hp) < comp) { + // Close border. (HBLANK start opens border, BPL1DAT closes it) + thisline_decision.plfleft = hpos * 2; + } + } } } @@ -4624,7 +4795,14 @@ static void reset_decisions_hsync_start(void) #endif } + if (debug_dma && (new_beamcon0 & (0x000 | 0x0010))) { + record_dma_event(DMA_EVENT_HSS, hpos, vpos); + record_dma_event(DMA_EVENT_HSE, hsstop, vpos); + } + toscr_hend = 0; + last_bpl1dat_hpos = -1; + last_hblank_start = -1; } int vsynctimebase_orig; @@ -4690,7 +4868,7 @@ devices_update_sync(svpos, syncadjust); void getsyncregisters(uae_u16 *phsstrt, uae_u16 *phsstop, uae_u16 *pvsstrt, uae_u16 *pvsstop) { *phsstrt = hsstrt; - *phsstop = hsstop; + *phsstop = hsstop_detect; *pvsstrt = vsstrt; *pvsstop = vsstop; } @@ -4702,16 +4880,14 @@ static void dumpsync(void) return; } cnt--; - write_log(_T("BEAMCON0=%04X VTOTAL=%04X HTOTAL=%04X\n"), new_beamcon0, vtotal, htotal); + write_log(_T("BEAMCON0=%04X VTOTAL=%03d HTOTAL=%03d (%03X)\n"), new_beamcon0, vtotal, htotal, htotal); write_log(_T(" HS=%04X-%04X HB=%04X-%04X HC=%04X\n"), hsstrt, hsstop, hbstrt, hbstop, hcenter); - write_log(_T(" VS=%04X-%04X VB=%04X-%04X\n"), vsstrt, vsstop, vbstrt, vbstop); + write_log(_T(" VS=%04d-%04d VB=%04d-%04d\n"), vsstrt, vsstop, vbstrt, vbstop); write_log(_T(" HSYNCSTART=%04X.%d HSYNCEND=%04X.%d\n"), hsyncstartpos >> CCK_SHRES_SHIFT, hsyncstartpos & ((1 << CCK_SHRES_SHIFT) - 1), hsyncendpos >> CCK_SHRES_SHIFT, hsyncendpos & ((1 << CCK_SHRES_SHIFT) - 1)); - write_log(_T(" LINES=%d-%d VB=%d-%d\n"), - minfirstline, maxvpos_display + maxvpos_display_vsync, - vblank_firstline_hw, vblank_lastline_hw); - + write_log(_T(" Lines=%d-%d\n"), + minfirstline, maxvpos_display + maxvpos_display_vsync); } int current_maxvpos(void) @@ -4751,6 +4927,28 @@ static void checklacecount(bool lace) } #endif +static void set_hcenter(void) +{ + if (!aga_mode && ecs_denise && (bplcon0 & 1)) { + if (beamcon0 & 0x0210) { + hcenter_v2 = (hcenter & 0xff) << CCK_SHRES_SHIFT; + } else { + hcenter_v2 = 132 << CCK_SHRES_SHIFT; + } + } else { + hcenter_v2 = 0; + } + uae_u16 hc = hcenter_v2; + hcenter_v2 -= 3; + if (hc >= (1 << CCK_SHRES_SHIFT) && hcenter_v2 < (1 << CCK_SHRES_SHIFT)) { + hcenter_v2 += maxhpos << CCK_SHRES_SHIFT; + } + hcenter_v2 = adjust_hr(hcenter_v2); + if (hcenter_v2 < (1 << CCK_SHRES_SHIFT)) { + hcenter_v2 = 0; + } +} + static void updateextblk(void) { hsyncstartpos_start_hw = 13; @@ -4766,12 +4964,12 @@ static void updateextblk(void) hbstop_v |= (hbstop >> 8) & 7; } if (aga_mode) { - // 1.5 hires pixel offset - hbstrt_v2 = hbstrt_v - 3; + // hblank has 1 lores pixel offset + hbstrt_v2 = hbstrt_v - 4; if (hbstrt_v >= (1 << CCK_SHRES_SHIFT) && hbstrt_v2 < (1 << CCK_SHRES_SHIFT)) { hbstrt_v2 += maxhpos << CCK_SHRES_SHIFT; } - hbstop_v2 = hbstop_v - 3; + hbstop_v2 = hbstop_v - 4; if (hbstop_v >= (1 << CCK_SHRES_SHIFT) && hbstop_v2 < (1 << CCK_SHRES_SHIFT)) { hbstop_v2 += maxhpos << CCK_SHRES_SHIFT; } @@ -4790,9 +4988,13 @@ static void updateextblk(void) if (new_beamcon0 & 0x0110) { // VARHSYEN | VARCSYEN hsyncstartpos = hsstrt; - hsyncendpos = hsstop; + hsstop_detect = hsstrt + 17; + if (hsstop_detect >= maxhpos) { + hsstop_detect -= maxhpos; + } + hsyncendpos = hsstop_detect; - hsync_end_left_border = hsstop + 1; + hsync_end_left_border = hsstop_detect; hsyncstartpos_start = hsyncstartpos; if (hsyncstartpos < hsyncendpos) { @@ -4851,8 +5053,25 @@ static void updateextblk(void) hbstop_v2 += maxhpos << CCK_SHRES_SHIFT; } - adjust_hr(&hbstrt_v2); - adjust_hr(&hbstop_v2); + int strt = hbstrt_v2; + int stop = hbstop_v2; + hbstrt_v2 = adjust_hr(hbstrt_v2); + hbstop_v2 = adjust_hr(hbstop_v2); + // if same after rounding: increase start/stop by minimum unit + if (hbstrt_v2 == hbstop_v2) { + int add = currprefs.chipset_hr ? (1 << currprefs.gfx_resolution) : 4; + if (strt < stop) { + hbstop_v2 += add; + if (hbstop_v2 >= (maxhpos << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) { + hbstop_v2 = 0; + } + } else if (strt > stop) { + hbstrt_v2 += add; + if (hbstrt_v2 >= (maxhpos << CCK_SHRES_SHIFT) + (1 << CCK_SHRES_SHIFT)) { + hbstrt_v2 = 0; + } + } + } hsyncstartpos_start_hw <<= CCK_SHRES_SHIFT; hsyncstartpos_hw <<= CCK_SHRES_SHIFT; @@ -4870,6 +5089,8 @@ static void updateextblk(void) hsynctotal += 1 << (CCK_SHRES_SHIFT - 1); } + set_hcenter(); + calcdiw(); } @@ -5018,10 +5239,10 @@ void compute_framesync(void) vres2 = VRES_QUAD; int start = hsyncstartpos >> CCK_SHRES_SHIFT; - int stop = hsyncendpos >> CCK_SHRES_SHIFT; + int stop = hsyncstartpos_start_cycles; vidinfo->drawbuffer.inwidth = ((maxhpos - (maxhpos - start + DISPLAY_LEFT_SHIFT / 2) + 1) * 2) << res2; - vidinfo->drawbuffer.inxoffset = hsstop * 2; + vidinfo->drawbuffer.inxoffset = stop * 2; vidinfo->drawbuffer.extrawidth = 0; vidinfo->drawbuffer.inwidth2 = vidinfo->drawbuffer.inwidth; @@ -5166,6 +5387,18 @@ static void init_hz(bool checkvposw) vblank_hz_lace = clk / ((maxvpos + 0.5) * (maxhpos + 0.5)); } + if (beamcon0 & 0x80) { + // programmable scanrates (ECS Agnus) + if (vtotal >= MAXVPOS) { + vtotal = MAXVPOS - 1; + } + maxvpos = vtotal + 1; + if (htotal >= MAXHPOS) { + htotal = MAXHPOS - 1; + } + maxhpos = htotal + 1; + } + maxhpos_display = AMIGA_WIDTH_MAX; maxvpos_nom = maxvpos; maxvpos_display = maxvpos; @@ -5199,8 +5432,6 @@ static void init_hz(bool checkvposw) vblank_extraline = !currprefs.cs_dipagnus && !ecs_denise ? 1 : 0; - vblank_lastline_hw = maxvpos + maxvpos_display_vsync + vblank_extraline; - int minfirstline_hw = minfirstline; if (currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) { minfirstline_hw -= EXTRAHEIGHT_EXTREME / 2; @@ -5308,16 +5539,12 @@ static void init_hz(bool checkvposw) } } + vbstopm1 = vbstop - 1; + if (vbstopm1 < 0) { + vbstopm1 += maxvpos; + } + if (beamcon0 & 0x80) { - // programmable scanrates (ECS Agnus) - if (vtotal >= MAXVPOS) { - vtotal = MAXVPOS - 1; - } - maxvpos = vtotal + 1; - if (htotal >= MAXHPOS) { - htotal = MAXHPOS - 1; - } - maxhpos = htotal + 1; vblank_hz_nom = vblank_hz = clk / (maxvpos * maxhpos); vblank_hz_shf = vblank_hz; vblank_hz_lof = clk / ((maxvpos + 1) * maxhpos); @@ -5450,8 +5677,8 @@ static void calcdiw(void) hstop |= (diwhigh >> 11) & 3; } - diw_hstrt = hstrt >> 2; - diw_hstop = hstop >> 2; + diw_hstrt = hstrt; + diw_hstop = hstop; diwfirstword = coord_diw_shres_to_window_x(hstrt); diwlastword = coord_diw_shres_to_window_x(hstop); @@ -6480,6 +6707,10 @@ static void BPLCON0(int hpos, uae_u16 v) decide_line(hpos); decide_fetch_safe(hpos); + if ((v & 1) != (bplcon0 & 1)) { + sync_color_changes(hpos); + } + if (!issyncstopped()) { vpos_previous = vpos; hpos_previous = hpos; @@ -6560,7 +6791,7 @@ static void BPLCON3(int hpos, uae_u16 v) return; } if (!aga_mode) { - v &= 0x003f; + v &= (0x0020 | 0x0010 | 0x004 | 0x001); v |= 0x0c00; } #if SPRBORDER @@ -6571,6 +6802,9 @@ static void BPLCON3(int hpos, uae_u16 v) } decide_line(hpos); decide_sprites(hpos); + if ((bplcon3 & 1) != (v & 1)) { + sync_color_changes(hpos); + } bplcon3 = v; if ((bplcon3 & 1) != (old & 1)) { updateextblk(); @@ -6670,8 +6904,8 @@ static void DIWSTRT(int hpos, uae_u16 v) return; } // if hpos matches previous hstart: it gets ignored. - if (diw_hstrt + DDF_OFFSET >= hpos * 2 - 2 && diw_hstrt + DDF_OFFSET <= hpos * 2 + 2) { - diw_hstrt = max_diwlastword; + if ((diw_hstrt >> 2) + DDF_OFFSET >= hpos * 2 - 2 && (diw_hstrt >> 2) + DDF_OFFSET <= hpos * 2 + 2) { + diw_hstrt = max_diwlastword << 2; } decide_diw(hpos); decide_line(hpos); @@ -6685,8 +6919,8 @@ static void DIWSTOP(int hpos, uae_u16 v) if (diwstop == v && !diwhigh_written) { return; } - if (diw_hstop + DDF_OFFSET >= hpos * 2 - 2 && diw_hstop + DDF_OFFSET <= hpos * 2 + 2) { - diw_hstop = min_diwlastword; + if ((diw_hstop >> 2) + DDF_OFFSET >= hpos * 2 - 2 && (diw_hstop >> 2) + DDF_OFFSET <= hpos * 2 + 2) { + diw_hstop = min_diwlastword << 2; } decide_diw(hpos); decide_line(hpos); @@ -6981,6 +7215,7 @@ static void SPRxCTLPOS(int num) sprxp = (s->pos & 0xFF) * 2 + (s->ctl & 1); sprxp <<= sprite_buffer_res; s->dblscan = 0; + s->ecs_denise_hires = 0; /* Quite a bit salad in this register... */ if (0) { } @@ -6991,8 +7226,11 @@ static void SPRxCTLPOS(int num) } #endif #ifdef ECS_DENISE - else if (ecs_denise) { - sprxp |= ((s->ctl >> 3) & 2) >> (RES_MAX - sprite_buffer_res); + else if (ecs_denise && (s->ctl & 0x10)) { + // This bit only works as documented if superhires bitplane resolution. + // If bitplane resolution is lores or hires: sprite's first pixel row + // becomes transparent. + s->ecs_denise_hires = 1; } #endif s->xpos = sprxp; @@ -7544,7 +7782,7 @@ static void decide_line(int endhpos) // ECS/AGA // BPRUN latched: on - if (bprun < 0) { + if (bprun < 0 && (hpos & 1)) { decide_line_decision_fetches(hpos); bprun = 1; bprun_pipeline_flush_delay = maxhpos; @@ -7671,7 +7909,7 @@ static void decide_line(int endhpos) // OCS // BPRUN latched: On - if (bprun < 0) { + if (bprun < 0 && (hpos & 1)) { decide_line_decision_fetches(hpos); bprun = 1; bprun_pipeline_flush_delay = maxhpos; @@ -7767,7 +8005,7 @@ static void decide_line(int endhpos) hpos++; } - decide_sprite_fetch(endhpos); + decide_sprites_fetch(endhpos); last_decide_line_hpos = endhpos; } @@ -8562,23 +8800,15 @@ static void do_sprite_fetch(int hpos, uae_u8 dat) bool slot = (dat & 8) != 0; bool dmastate = (dat & 0x10) != 0; + // render sprites first + decide_sprites(hpos, false, true); + sprite_fetch_full(s, hpos, slot, false, &data, &data321, &data322); int sprxp = s->xpos >> (sprite_buffer_res + 1); - bool start_before_dma = hpos >= sprxp && sprxp >= 16; if (dmastate) { if (!slot) { - // if xpos is earlier than this cycle, decide it first. - if (start_before_dma) { - maybe_decide_sprites(num, hpos); - } SPRxDATA_1(data, num, hpos); } else { - // This is needed if xpos is between DATA and DATB fetches - // Test does not need to be accurate, only purpose is to - // not lose performance when sprites have "normal" positioning. - if (start_before_dma) { - maybe_decide_sprites(num, hpos); - } SPRxDATB_1(data, num, hpos); } #ifdef AGA @@ -8610,9 +8840,6 @@ static void do_sprite_fetch(int hpos, uae_u8 dat) #endif } else { if (!slot) { - if (start_before_dma && s->armed) { - maybe_decide_sprites(num, hpos); - } SPRxPOS_1(data, num, hpos); } else { SPRxCTL_1(data, num, hpos); @@ -8632,7 +8859,7 @@ static void do_sprite_fetch(int hpos, uae_u8 dat) } -static void decide_sprite_fetch(int endhpos) +static void decide_sprites_fetch(int endhpos) { int hpos = last_decide_sprite_hpos; if (hpos >= endhpos) { @@ -8731,10 +8958,12 @@ void init_hardware_for_drawing_frame(void) if (prev_sprite_entries) { int first_pixel = prev_sprite_entries[0].first_pixel; int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel; - memset(spixels + first_pixel, 0, npixels * sizeof *spixels); - memset(spixstate.stb + first_pixel, 0, npixels * sizeof *spixstate.stb); - if (aga_mode) { - memset(spixstate.stbfm + first_pixel, 0, npixels * sizeof *spixstate.stbfm); + if (npixels > 0) { + memset(spixels + first_pixel, 0, npixels * sizeof * spixels); + memset(spixstate.stb + first_pixel, 0, npixels * sizeof * spixstate.stb); + if (aga_mode) { + memset(spixstate.stbfm + first_pixel, 0, npixels * sizeof * spixstate.stbfm); + } } } prev_next_sprite_entry = next_sprite_entry; @@ -9833,6 +10062,7 @@ static void hsync_handlerh(bool onvsync) } eventtab[ev_hsynch].evtime = get_cycles() + HSYNCTIME; + eventtab[ev_hsynch].active = 1; eventtab[ev_hsynch].oldcycles = get_cycles(); events_schedule(); } @@ -9886,7 +10116,6 @@ static void hsync_handler_pre(bool onvsync) } if (ecs_denise || vpos > get_equ_vblank_endline() || (currprefs.cs_dipagnus && vpos == 0)) { diw_hcounter = maxhpos * 2; - last_hdiw = 2 - 1; } } @@ -9923,6 +10152,8 @@ static void hsync_handler_pre(bool onvsync) eventtab[ev_hsynch].active = 1; events_schedule(); } + + debug_hsync(); } STATIC_INLINE bool is_last_line(void) @@ -10753,7 +10984,7 @@ static void hsync_handler_post (bool onvsync) vb_start_line = 1; vb_state = true; } - if (vbstop == vpos) { + if (vbstopm1 == vpos) { vbstop_m = vpos; vb_end_line = true; vb_state = false; @@ -10788,6 +11019,31 @@ static void hsync_handler_post (bool onvsync) } hhpos &= 0xff; } + + if (beamcon0 & 0x20) { + if (vpos == 2 && !lof_current) { + vs_state_hw = true; + } + if (vpos == 3 && lof_current) { + vs_state_hw = true; + } + if (vpos == 5) { + vs_state_hw = false; + } + } else { + if (vpos == 3) { + vs_state_hw = true; + } + if (vpos == 6) { + vs_state_hw = false; + } + } + if (new_beamcon0 & (0x0200 | 0x0010)) { + vs_state_on = vs_state; + } else { + vs_state_on = vs_state_hw; + } + if (!(new_beamcon0 & 0x1000)) { vb_check(); } @@ -10796,18 +11052,22 @@ static void hsync_handler_post (bool onvsync) int hp = REFRESH_FIRST_HPOS; for (int i = 0; i < 4; i++) { - alloc_cycle(hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */ + bool type = i == 0 || (i == 1 && ecs_agnus && lol); + alloc_cycle(hp, type ? CYCLE_STROBE : CYCLE_REFRESH); #ifdef DEBUGGER if (debug_dma) { - uae_u16 strobe = 0x3c; - if (vb_state && vpos < equ_vblank_endline) { - strobe = 0x38; - } else if (vb_state) { - strobe = 0x3a; - } else if (ecs_agnus && lol) { + uae_u16 strobe = 0x1fe; + if (i == 0) { + strobe = 0x3c; + if (vb_state && vpos < equ_vblank_endline) { + strobe = 0x38; + } else if (vb_state) { + strobe = 0x3a; + } + } else if (i == 1 && ecs_agnus && lol) { strobe = 0x3e; } - record_dma_read(i == 0 ? strobe : 0x1fe, 0xffffffff, hp, vpos, DMARECORD_REFRESH, i); + record_dma_read(strobe, 0xffffffff, hp, vpos, DMARECORD_REFRESH, i); record_dma_read_value(0xffff); } #endif @@ -10817,6 +11077,25 @@ static void hsync_handler_post (bool onvsync) } } + if (debug_dma) { + if (vs_state_on) { + record_dma_event(DMA_EVENT_VS, REFRESH_FIRST_HPOS, vpos); + } + if (vb_start_line) { + record_dma_event(DMA_EVENT_VB, REFRESH_FIRST_HPOS, vpos); + } + if (diwstate == DIW_waiting_stop) { + record_dma_event(DMA_EVENT_VDIW, REFRESH_FIRST_HPOS, vpos); + } + if (lof_current) { + record_dma_event(DMA_EVENT_LOF, REFRESH_FIRST_HPOS + 2, vpos); + } + if (lol) { + record_dma_event(DMA_EVENT_LOL, REFRESH_FIRST_HPOS + 2, vpos); + } + } + + events_dmal_hsync (); #if 0 // AF testing stuff @@ -11106,6 +11385,9 @@ void custom_reset(bool hardreset, bool keyboardreset) nr_armed = 0; next_lineno = 0; vb_start_line = 0; + vs_state = false; + vs_state_hw = false; + vs_state_on = false; memset(custom_storage, 0, sizeof(custom_storage)); if (!currprefs.cs_dipagnus) { vb_start_line = 1; @@ -11116,6 +11398,10 @@ void custom_reset(bool hardreset, bool keyboardreset) estimated_fm = 0xffff; exthblank = false; exthblank_state = false; + hbstrt_v2 = 0; + hbstop_v2 = 0; + hcenter_v2 = 0; + set_hcenter(); if (!savestate_state) { cia_hsync = 0; @@ -11841,18 +12127,14 @@ static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int n break; case 0x1C4: if (hbstrt != value) { - if (exthblank) { - record_color_change2(hpos, 0xffff, 0); - } + sync_color_changes(hpos); hbstrt = value & 0x7ff; varsync(addr, 0); } break; case 0x1C6: if (hbstop != value) { - if (exthblank) { - record_color_change2(hpos, 0xffff, 0); - } + sync_color_changes(hpos); hbstop = value & 0x7ff; varsync(addr, 0); } @@ -12118,8 +12400,8 @@ uae_u8 *restore_custom(uae_u8 *src) SPRHSTOP(-1, RW); /* 1D2 SPRHSTOP */ BPLHSTRT(-1, RW); /* 1D4 BPLHSTRT */ BPLHSTOP(-1, RW); /* 1D6 BPLHSTOP */ - hhpos = RW; /* 1D8 HHPOS */ - RW; /* 1DA ? */ + hhpos = RW; /* 1D8 HHPOSW */ + RW; /* 1DA HHPOSR */ new_beamcon0 = RW; /* 1DC BEAMCON0 */ hsstrt = RW; /* 1DE HSSTRT */ vsstrt = RW; /* 1E0 VSSTT */ @@ -12127,8 +12409,8 @@ uae_u8 *restore_custom(uae_u8 *src) diwhigh = RW; /* 1E4 DIWHIGH */ diwhigh_written = (diwhigh & 0x8000) ? 1 : 0; hdiwstate = (diwhigh & 0x4000) ? DIW_waiting_stop : DIW_waiting_start; - diwstate = (diwhigh & 0x2000) ? DIW_waiting_start : DIW_waiting_stop; - diwhigh &= 0x1fff; + diwstate = (diwhigh & 0x0080) ? DIW_waiting_start : DIW_waiting_stop; + diwhigh &= 0x3f3f; RW; /* 1E6 ? */ RW; /* 1E8 ? */ RW; /* 1EA ? */ @@ -12332,12 +12614,12 @@ uae_u8 *save_custom(int *len, uae_u8 *dstptr, int full) SW(bplhstrt); /* 1D4 BPLHSTRT */ SW(bplhstop); /* 1D6 BPLHSTOP */ SW(hhpos); /* 1D8 HHPOSW */ - SW(0); /* 1DA */ + SW(HHPOSR()); /* 1DA HHPOSR */ SW(new_beamcon0); /* 1DC BEAMCON0 */ SW(hsstrt); /* 1DE HSSTRT */ SW(vsstrt); /* 1E0 VSSTRT */ SW(hcenter); /* 1E2 HCENTER */ - SW(diwhigh | (diwhigh_written ? 0x8000 : 0) | (hdiwstate == DIW_waiting_stop ? 0x4000 : 0) | (diwstate == DIW_waiting_start ? 0x2000 : 0)); /* 1E4 DIWHIGH */ + SW(diwhigh | (diwhigh_written ? 0x8000 : 0) | (hdiwstate == DIW_waiting_stop ? 0x4000 : 0) | (diwstate == DIW_waiting_start ? 0x0080 : 0)); /* 1E4 DIWHIGH */ SW(0); /* 1E6 */ SW(0); /* 1E8 */ SW(0); /* 1EA */ diff --git a/debug.cpp b/debug.cpp index 2f6135bb..f0ed240e 100644 --- a/debug.cpp +++ b/debug.cpp @@ -1796,7 +1796,7 @@ static void memwatch_heatmap (uaecptr addr, int rwi, int size, uae_u32 accessmas hm->mask |= accessmask; } -void record_dma_event (int evt, int hpos, int vpos) +void record_dma_event (uae_u32 evt, int hpos, int vpos) { struct dma_rec *dr; @@ -1935,6 +1935,7 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32 TCHAR srtext[10]; bool extra64 = false; uae_u32 extraval; + bool noval = false; if (l1) l1[0] = 0; @@ -1989,6 +1990,7 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32 } else if (dr->type == DMARECORD_REFRESH) { sr = _T("RFS"); chcnt = br; + noval = true; } else if (dr->type == DMARECORD_AUDIO) { sr = _T("AUD"); chcnt = br; @@ -2039,7 +2041,7 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32 _stprintf(l2, _T("%5s %02X"), srtext, r); } } - if (l3) { + if (l3 && !noval) { uae_u64 v = dr->dat; if (longsize == 4) { _stprintf(l3, _T("%08X"), (uae_u32)v); @@ -2094,6 +2096,48 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32 l3[cl2++] = '1'; if (dr->evt & DMA_EVENT_DDFSTOP2) l3[cl2++] = '2'; + + if (dr->evt & DMA_EVENT_HDIWS) { + l3[cl2++] = '('; + } + if (dr->evt & DMA_EVENT_HDIWE) { + l3[cl2++] = ')'; + } + + if (dr->evt & DMA_EVENT_HBS) { + l3[cl2++] = '['; + } + if (dr->evt & DMA_EVENT_HBE) { + l3[cl2++] = ']'; + } + if (dr->evt & DMA_EVENT_HSS) { + l3[cl2++] = '{'; + } + if (dr->evt & DMA_EVENT_HSE) { + l3[cl2++] = '}'; + } + + if (dr->evt & (DMA_EVENT_VB | DMA_EVENT_VS | DMA_EVENT_LOL | DMA_EVENT_LOF | DMA_EVENT_VDIW)) { + l3[cl2++] = '*'; + } + if (dr->evt & DMA_EVENT_VS) { + l3[cl2++] = 'S'; + } + if (dr->evt & DMA_EVENT_VB) { + l3[cl2++] = 'B'; + } + if (dr->evt & DMA_EVENT_LOL) { + l3[cl2++] = 'L'; + } + if (dr->evt & DMA_EVENT_LOF) { + l3[cl2++] = 'F'; + } + if (dr->evt & DMA_EVENT_VDIW) { + l3[cl2++] = '='; + } + if (dr->evt & (DMA_EVENT_VB | DMA_EVENT_VS | DMA_EVENT_LOL | DMA_EVENT_LOF | DMA_EVENT_VDIW)) { + l3[cl2++] = 0; + } } if (l5) { _stprintf (l5, _T("%08X"), cycles + (vpos * maxhpos + hpos) * CYCLE_UNIT); @@ -2109,25 +2153,25 @@ static bool get_record_dma_info(struct dma_rec *dr, int hpos, int vpos, uae_u32 static void decode_dma_record (int hpos, int vpos, int toggle, bool logfile) { - struct dma_rec *dr; + struct dma_rec *dr, *dr_start; int h, i, maxh; uae_u32 cycles; if (!dma_record[0] || hpos < 0 || vpos < 0) return; - dr = &dma_record[dma_record_toggle ^ toggle][vpos * NR_DMA_REC_HPOS]; + dr_start = dr = &dma_record[dma_record_toggle ^ toggle][vpos * NR_DMA_REC_HPOS]; if (logfile) write_dlog (_T("Line: %02X %3d HPOS %02X %3d:\n"), vpos, vpos, hpos, hpos); else console_out_f (_T("Line: %02X %3d HPOS %02X %3d:\n"), vpos, vpos, hpos, hpos); h = hpos; dr += hpos; - maxh = hpos + (logfile ? maxhpos : 80); - if (maxh > maxhpos) - maxh = maxhpos; + maxh = hpos + (logfile ? maxhpos_short : 80); + if (maxh > maxhpos_short) + maxh = maxhpos_short; cycles = vsync_cycles; if (toggle) - cycles -= maxvpos * maxhpos * CYCLE_UNIT; + cycles -= maxvpos * maxhpos_short * CYCLE_UNIT; while (h < maxh) { int cols = (logfile ? 16 : 8); TCHAR l1[200]; @@ -2144,6 +2188,11 @@ static void decode_dma_record (int hpos, int vpos, int toggle, bool logfile) TCHAR l1l[16], l2l[16], l3l[16], l4l[16], l5l[16]; get_record_dma_info(dr, h, vpos, cycles, l1l, l2l, l3l, l4l, l5l); + if (dr_start[3 + 2].evt & DMA_EVENT_LOL) { + if (maxh == maxhpos_short) { + maxh++; + } + } TCHAR *p = l1 + _tcslen(l1); _stprintf(p, _T("%9s "), l1l); @@ -4807,11 +4856,33 @@ static void show_exec_lists (TCHAR *t) } } +static int debug_vpos = -1; +static int debug_hpos = -1; + static void breakfunc(uae_u32 v) { write_log(_T("Cycle breakpoint hit\n")); debugging = 1; - set_special (SPCFLAG_BRK); + set_special(SPCFLAG_BRK); +} + +void debug_hsync(void) +{ + if (debug_vpos < 0) { + return; + } + if (debug_vpos != vpos) { + return; + } + if (debug_hpos <= 0) { + breakfunc(0); + } else { + if (current_hpos() < debug_hpos) { + event2_newevent_x(-1, debug_hpos - current_hpos(), 0, breakfunc); + } else { + breakfunc(0); + } + } } static int cycle_breakpoint(TCHAR **c) @@ -4822,27 +4893,22 @@ static int cycle_breakpoint(TCHAR **c) int count = readint(c); if (nc == 's') { if (more_params(c)) { - int mvp = maxvpos + lof_store; - int hp = readint(c); - int chp = current_hpos(); - if (count == vpos && chp < hp) { - count += mvp - vpos; - } else if (count >= vpos) { - count = count - vpos; + debug_vpos = count; + debug_hpos = readint(c); + if (debug_vpos == vpos && debug_hpos > current_hpos()) { + debug_vpos = -1; + count = debug_hpos - current_hpos(); + debug_hpos = -1; } else { - count += mvp - vpos; - } - count *= maxhpos; - if (hp >= chp) { - count += hp - chp; - } else { - count += maxhpos - chp; + return 1; } } else { count *= maxhpos; } } - event2_newevent_x(-1, count, 0, breakfunc); + if (count > 0) { + event2_newevent_x(-1, count, 0, breakfunc); + } return 1; } return 0; diff --git a/drawing.cpp b/drawing.cpp index 4abf7dba..d79129d5 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -252,8 +252,7 @@ static int visible_top_start, visible_bottom_stop; /* same for blank */ static int vblank_top_start, vblank_bottom_stop; static int hblank_left_start, hblank_right_stop; -static bool exthblank; -static bool extborder; +static bool exthblank, extborder, exthblanken; static int linetoscr_x_adjust_pixbytes, linetoscr_x_adjust_pixels; static int thisframe_y_adjust; @@ -471,12 +470,10 @@ static void reset_custom_limits(void) center_reset = true; } -static void set_blanking_limits(void) +static void reset_hblanking_limits(void) { hblank_left_start = visible_left_start; hblank_right_stop = visible_right_stop; - vblank_top_start = visible_top_start; - vblank_bottom_stop = visible_bottom_stop; if (hblank_left_start < visible_left_border) { hblank_left_start = visible_left_border; @@ -484,6 +481,15 @@ static void set_blanking_limits(void) if (hblank_right_stop > visible_right_border) { hblank_right_stop = visible_right_border; } +} + +// this handles hardwired vblank +// vb_state in do_color_changes() handles programmed vblank +static void set_vblanking_limits(void) +{ + vblank_top_start = visible_top_start; + vblank_bottom_stop = visible_bottom_stop; + if (vblank_top_start < visible_top_start) { vblank_top_start = visible_top_start; } @@ -491,6 +497,34 @@ static void set_blanking_limits(void) vblank_bottom_stop = visible_bottom_stop; } + bool hardwired = false; + if (ecs_agnus) { + hardwired = (new_beamcon0 & 0x1000) == 0; + } + if (hardwired) { + int vbstrt = vblank_firstline_hw; + int vbstop = maxvpos + lof_store; + if (currprefs.cs_dipagnus) { + vbstop++; + } + if (currprefs.gfx_overscanmode < OVERSCANMODE_OVERSCAN) { + int mult = (OVERSCANMODE_OVERSCAN - currprefs.gfx_overscanmode) * 5; + vbstrt += mult; + vbstop -= mult; + } + vbstrt <<= currprefs.gfx_vresolution; + vbstop <<= currprefs.gfx_vresolution; + if (vblank_top_start < vbstrt) { + vblank_top_start = vbstrt; + } + if (vblank_bottom_stop > vbstop) { + vblank_bottom_stop = vbstop; + } + } +} + +static void set_hblanking_limits(void) +{ // horizontal blanking bool hardwired = !dp_for_drawing || !ce_is_extblankset(colors_for_drawing.extra); bool doblank = false; @@ -507,7 +541,6 @@ static void set_blanking_limits(void) } } if (hardwired) { - exthblank = false; doblank = true; } else if (currprefs.gfx_overscanmode <= OVERSCANMODE_OVERSCAN) { doblank = true; @@ -538,31 +571,6 @@ static void set_blanking_limits(void) hblank_right_stop = coord_hw_to_window_x_shres(hbstrt); } } - - if (aga_mode) { - hardwired = (new_beamcon0 & 0x1000) == 0; - } - // vb_state handles programmed vblank - if (hardwired) { - int vbstrt = vblank_firstline_hw; - int vbstop = vblank_lastline_hw; - - if (currprefs.gfx_overscanmode < OVERSCANMODE_OVERSCAN) { - int mult = (OVERSCANMODE_OVERSCAN - currprefs.gfx_overscanmode) * 5; - vbstrt += mult; - vbstop -= mult; - } - - vbstrt <<= currprefs.gfx_vresolution; - vbstop <<= currprefs.gfx_vresolution; - if (vblank_top_start < vbstrt) { - vblank_top_start = vbstrt; - } - if (vblank_bottom_stop > vbstop) { - vblank_bottom_stop = vbstop; - } - } - } void get_custom_raw_limits(int *pw, int *ph, int *pdx, int *pdy) @@ -1141,12 +1149,17 @@ static void pfield_init_linetoscr (int lineno, bool border) } #endif - // AGA borderblank starts horizontally 1 hires pixel before bitplanes start, leaving 1 hires pixel background color gap + // AGA borderblank starts horizontally 1 shres pixel before bitplanes start playfield_start_pre = playfield_start; playfield_end_pre = playfield_end; if (currprefs.chipset_hr && aga_mode && bplres > 0) { - playfield_start_pre -= bplres; - playfield_end_pre -= bplres; + if (currprefs.gfx_resolution == RES_SUPERHIRES) { + playfield_start_pre -= 1; + playfield_end_pre -= 1; + } else { + playfield_start_pre &= ~1; + playfield_end_pre &= ~1; + } } unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start; @@ -1375,7 +1388,7 @@ static void fill_line_border(int lineno) { struct vidbuf_description *vidinfo = &adisplays[0].gfxvidinfo; int lastpos = visible_left_border; - int endpos = visible_right_border; + int endpos = visible_left_border + vidinfo->drawbuffer.inwidth; int w = endpos - lastpos; if (lineno < visible_top_start || lineno < vblank_top_start || lineno >= visible_bottom_stop || lineno >= vblank_bottom_stop) { @@ -1432,6 +1445,13 @@ static uae_u8 render_sprites(int pos, int dualpf, uae_u8 apixel, int aga) int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms; int maskshift, plfmask; + if (exthblank) { + return 0; + } + if (extborder && (ce_is_borderblank(colors_for_drawing.extra) || !ce_is_bordersprite(colors_for_drawing.extra))) { + return 0; + } + // If 64 pixel wide sprite and FMODE gets lowered when sprite's // first 32 pixels are being drawn: matching pixel(s) in second // 32 pixel part gets blanked. @@ -3054,6 +3074,16 @@ static bool isham(uae_u16 bplcon0) return 0; } +static void extblankcheck(void) +{ + if (exthblanken && ((dp_for_drawing->bplcon3 & 1) && (dp_for_drawing->bplcon0 & 1))) { + exthblank = true; + } + if (exthblanken && (!(dp_for_drawing->bplcon3 & 1) || !(dp_for_drawing->bplcon0 & 1))) { + exthblank = false; + } +} + static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp) { regno -= RECORDED_REGISTER_CHANGE_OFFSET; @@ -3068,6 +3098,7 @@ static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp) dp_for_drawing->ham_seen = isham(v); if (currprefs.chipset_hr && dp_for_drawing->bplres < currprefs.gfx_resolution) dp_for_drawing->bplres = currprefs.gfx_resolution; + extblankcheck(); break; case 0x104: // BPLCON2 dp_for_drawing->bplcon2 = v; @@ -3075,6 +3106,7 @@ static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp) #ifdef ECS_DENISE case 0x106: // BPLCON3 dp_for_drawing->bplcon3 = v; + extblankcheck(); break; #endif #ifdef AGA @@ -3089,7 +3121,17 @@ static void pfield_expand_dp_bplconx (int regno, int v, int hp, int vp) dp_for_drawing->fmode = v; break; case 0x200: // hblank - exthblank = v != 0; + if (v) { + exthblanken = true; + if (vp >= 0) { + extblankcheck(); + } else { + exthblank = true; + } + } else { + exthblanken = false; + exthblank = false; + } return; #endif } @@ -3102,15 +3144,15 @@ 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 need_full) +static void adjust_drawing_colors (int ctable, int need_full, bool blankcheck) { + uae_u16 oe = colors_for_drawing.extra; if (drawing_color_matches != ctable || need_full < 0) { 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); + memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors, sizeof colors_for_drawing.acolors); colors_for_drawing.extra = curr_color_tables[ctable].extra; color_match_type = color_match_acolors; } @@ -3119,6 +3161,10 @@ static void adjust_drawing_colors (int ctable, int need_full) color_reg_cpy (&colors_for_drawing, &curr_color_tables[ctable]); color_match_type = color_match_full; } + if (colors_for_drawing.extra != oe) { + reset_hblanking_limits(); + set_hblanking_limits(); + } } static void playfield_hard_way(line_draw_func worker_pfield, int first, int last) @@ -3222,7 +3268,7 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker } } else { - // special AGA borderblank 1 hires pixel delay + // special AGA borderblank 1 shres pixel delay // borderblank left border (hblank end to playfield_start_pre) if (nextpos_in_range > lastpos && lastpos < playfield_start_pre) { @@ -3230,14 +3276,14 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker (*worker_border)(lastpos, t, 0); lastpos = t; } - // AGA "buggy" borderblank, real background color visible, single hires pixel wide. + // AGA "buggy" borderblank, real background color visible, single shres pixel wide. if (nextpos_in_range > lastpos && lastpos < playfield_start) { int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; (*worker_border)(lastpos, t, -1); lastpos = t; } - // playfield with last hires pixel not drawn. + // playfield with last shres pixel not drawn. if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end_pre) { int t = nextpos_in_range <= playfield_end_pre ? nextpos_in_range : playfield_end_pre; if (may_require_hard_way && (may_require_hard_way < 0 || (bplxor && may_require_hard_way && worker_pfield != pfield_do_linetoscr_bordersprite_aga))) { @@ -3248,7 +3294,7 @@ static void do_color_changes(line_draw_func worker_border, line_draw_func worker lastpos = t; } - // last 1 hires pixel of playfield blanked + // last shres pixel of playfield blanked if (nextpos_in_range > lastpos && lastpos >= playfield_end_pre && lastpos < playfield_end) { int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; (*worker_border)(lastpos, t, 0); @@ -3424,12 +3470,11 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int if (border == 0) { pfield_expand_dp_bplcon(); - set_blanking_limits(); + // must be after pfield_expand_dp_bplcon + adjust_drawing_colors(dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb || ecsshres, true); pfield_init_linetoscr(lineno, false); pfield_doline(lineno); - adjust_drawing_colors(dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb || ecsshres); - /* The problem is that we must call decode_ham() BEFORE we do the sprites. */ if (dp_for_drawing->ham_seen) { int ohposblank = hposblank; @@ -3443,7 +3488,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int do_color_changes(dummy_worker, decode_ham, lineno); if (have_color_changes) { // do_color_changes() did color changes and register changes, restore them. - adjust_drawing_colors(dp_for_drawing->ctable, -1); + adjust_drawing_colors(dp_for_drawing->ctable, -1, false); dp_for_drawing->bplcon0 = b0; dp_for_drawing->bplcon2 = b2; dp_for_drawing->bplcon3 = b3; @@ -3502,7 +3547,7 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int bool dosprites = false; - adjust_drawing_colors(dp_for_drawing->ctable, 0); + adjust_drawing_colors(dp_for_drawing->ctable, 0, true); #ifdef AGA /* this makes things complex.. */ if (dp_for_drawing->bordersprite_seen && !ce_is_borderblank(colors_for_drawing.extra) && dip_for_drawing->nr_sprites) { @@ -3578,8 +3623,6 @@ static void pfield_draw_line(struct vidbuffer *vb, int lineno, int gfx_ypos, int } } -extern int hsync_end_left_border; - static void center_image (void) { struct amigadisplay *ad = &adisplays[0]; @@ -3608,7 +3651,7 @@ static void center_image (void) #endif } else if (vidinfo->drawbuffer.extrawidth > 0 || currprefs.gfx_overscanmode == OVERSCANMODE_EXTREME) { // extreme wide mode - visible_left_border = (hsync_end_left_border * 2) << currprefs.gfx_resolution; + visible_left_border = (hsync_end_left_border * 2 + 1) << currprefs.gfx_resolution; } else if (ew == -1) { // wide mode visible_left_border = (hsync_end_left_border * 2) << currprefs.gfx_resolution; @@ -4132,7 +4175,9 @@ static void draw_frame2(struct vidbuffer *vbin, struct vidbuffer *vbout) int largest = 0; #endif - set_blanking_limits(); + set_vblanking_limits(); + reset_hblanking_limits(); + set_hblanking_limits(); bool firstline = true; int lastline = thisframe_y_adjust_real - (1 << linedbl); @@ -4166,6 +4211,9 @@ static void draw_frame2(struct vidbuffer *vbin, struct vidbuffer *vbout) largest = whereline; #endif + reset_hblanking_limits(); + set_hblanking_limits(); + hposblank = 0; pfield_draw_line(vbout, line, whereline, wherenext); } @@ -4243,7 +4291,9 @@ void draw_lines(int end, int section) if (!lockscr(vb, false, vb->last_drawn_line ? false : true)) return; - set_blanking_limits(); + set_vblanking_limits(); + reset_hblanking_limits(); + set_hblanking_limits(); bool firstline = true; int lastline = thisframe_y_adjust_real - (1 << linedbl); @@ -4828,6 +4878,9 @@ void reset_drawing(void) max_diwstop = 0; vb_state = 0; + exthblank = false; + exthblanken = false; + extborder = false; lores_reset (); diff --git a/identify.cpp b/identify.cpp index 67d8d97c..f0038910 100644 --- a/identify.cpp +++ b/identify.cpp @@ -366,12 +366,12 @@ const struct customData custd[] = { _T("VSSTOP"), 0xdff1CA, CD_WO | CD_ECS_AGNUS }, /* Vert line for VBLANK start */ { _T("VBSTRT"), 0xdff1CC, CD_WO | CD_ECS_AGNUS }, /* Vert line for VBLANK start */ { _T("VBSTOP"), 0xdff1CE, CD_WO | CD_ECS_AGNUS }, /* Vert line for VBLANK stop */ - { _T("-"), 0xdff1D0, CD_NONE }, /* UHRES sprite vertical start */ - { _T("-"), 0xdff1D2, CD_NONE }, /* UHRES sprite vertical stop */ - { _T("-"), 0xdff1D4, CD_NONE }, /* UHRES bit plane vertical stop */ - { _T("-"), 0xdff1D6, CD_NONE }, /* UHRES bit plane vertical stop */ - { _T("-"), 0xdff1D8, CD_NONE }, /* DUAL mode hires H beam counter write */ - { _T("-"), 0xdff1DA, CD_NONE }, /* DUAL mode hires H beam counter read */ + { _T("SPRHSTRT"), 0xdff1D0, CD_WO | CD_ECS_AGNUS }, /* UHRES sprite vertical start */ + { _T("SPRHSTOP"), 0xdff1D2, CD_WO | CD_ECS_AGNUS }, /* UHRES sprite vertical stop */ + { _T("BPLHSTRT"), 0xdff1D4, CD_WO | CD_ECS_AGNUS }, /* UHRES bit plane vertical stop */ + { _T("BPLHSTOP"), 0xdff1D6, CD_WO | CD_ECS_AGNUS }, /* UHRES bit plane vertical stop */ + { _T("HHPOSW"), 0xdff1D8, CD_WO | CD_ECS_AGNUS }, /* DUAL mode hires H beam counter write */ + { _T("HHPOSR"), 0xdff1DA, 0 | CD_ECS_AGNUS }, /* DUAL mode hires H beam counter read */ { _T("BEAMCON0"), 0xdff1DC, CD_WO | CD_ECS_AGNUS }, /* Beam counter control register (SHRES,UHRES,PAL) */ { _T("HSSTRT"), 0xdff1DE, CD_WO | CD_ECS_DENISE }, /* Horizontal sync start (VARHSY) */ { _T("VSSTRT"), 0xdff1E0, CD_WO | CD_ECS_DENISE }, /* Vertical sync start (VARVSY) */ diff --git a/include/custom.h b/include/custom.h index d510aae9..15dbd371 100644 --- a/include/custom.h +++ b/include/custom.h @@ -135,7 +135,7 @@ extern float vblank_hz, fake_vblank_hz; extern float hblank_hz; extern int vblank_skip, doublescan; extern int programmedmode; -extern int vblank_firstline_hw, vblank_lastline_hw; +extern int vblank_firstline_hw; #define DMA_AUD0 0x0001 #define DMA_AUD1 0x0002 @@ -165,11 +165,12 @@ extern unsigned long frametime, timeframes; extern uae_u16 htotal, vtotal, beamcon0, new_beamcon0; // 100 words give you 1600 horizontal pixels. Should be more than enough for superhires. +// Extreme overscan superhires needs more. // must be divisible by 8 #ifdef CUSTOM_SIMPLE #define MAX_WORDS_PER_LINE 56 #else -#define MAX_WORDS_PER_LINE 104 +#define MAX_WORDS_PER_LINE 112 #endif extern uae_u32 hirestab_h[256][2]; diff --git a/include/debug.h b/include/debug.h index d00a4e9d..85413322 100644 --- a/include/debug.h +++ b/include/debug.h @@ -71,6 +71,7 @@ extern int memwatch_access_validator; #define DEBUG_SPRINTF_ADDRESS 0xbfff00 extern bool debug_sprintf(uaecptr, uae_u32, int); extern bool debug_get_prefetch(int idx, uae_u16 *opword); +extern void debug_hsync(void); extern void debug_init_trainer(const TCHAR*); extern void debug_trainer_match(void); @@ -218,7 +219,7 @@ struct dma_rec uae_u64 dat; uae_u16 size; uae_u32 addr; - uae_u16 evt; + uae_u32 evt; uae_s16 type; uae_u16 extra; uae_s8 intlev; @@ -243,6 +244,18 @@ extern struct dma_rec *last_dma_rec; #define DMA_EVENT_DDFSTOP 8192 #define DMA_EVENT_DDFSTOP2 16384 #define DMA_EVENT_SPECIAL 32768 +#define DMA_EVENT_VB 0x10000 +#define DMA_EVENT_VS 0x20000 +#define DMA_EVENT_LOF 0x40000 +#define DMA_EVENT_LOL 0x80000 +#define DMA_EVENT_HBS 0x100000 +#define DMA_EVENT_HBE 0x200000 +#define DMA_EVENT_HDIWS 0x400000 +#define DMA_EVENT_HDIWE 0x800000 +#define DMA_EVENT_VDIW 0x1000000 +#define DMA_EVENT_HSS 0x2000000 +#define DMA_EVENT_HSE 0x4000000 + #define DMARECORD_REFRESH 1 #define DMARECORD_CPU 2 @@ -260,7 +273,7 @@ extern void record_dma_read_value(uae_u32 v); extern void record_dma_read_value_wide(uae_u64 v, bool quad); extern void record_dma_replace(int hpos, int vpos, int type, int extra); extern void record_dma_reset(void); -extern void record_dma_event(int evt, int hpos, int vpos); +extern void record_dma_event(uae_u32 evt, int hpos, int vpos); extern void debug_draw(uae_u8 *buf, int bpp, int line, int width, int height, uae_u32 *xredcolors, uae_u32 *xgreencolors, uae_u32 *xbluescolors); #define TRACE_SKIP_INS 1 diff --git a/include/drawing.h b/include/drawing.h index cc552f02..34713abc 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -248,7 +248,7 @@ struct color_change { #ifdef UAE_MINI #define MAX_PIXELS_PER_LINE 880 #else -#define MAX_PIXELS_PER_LINE 2048 +#define MAX_PIXELS_PER_LINE 2304 #endif #define MAXVPOS_WRAPLINES 10 diff --git a/include/events.h b/include/events.h index ec9ec74a..71575781 100644 --- a/include/events.h +++ b/include/events.h @@ -107,6 +107,7 @@ STATIC_INLINE void set_cycles (unsigned long int x) { currcycle = x; eventtab[ev_hsync].oldcycles = x; + eventtab[ev_hsynch].active = 0; #ifdef EVT_DEBUG if (currcycle & (CYCLE_UNIT - 1)) write_log (_T("%x\n"), currcycle);