#define CYCLE_CONFLICT_LOGGING 0
#define SPEEDUP 1
-
#define CUSTOM_DEBUG 0
#define SPRITE_DEBUG 0
#define SPRITE_DEBUG_MINY 0
#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
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;
int dmastate;
int dmacycle;
int width;
+ bool ecs_denise_hires;
uae_u16 ctl, pos;
#ifdef AGA
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];
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;
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;
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;
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;
}
}
-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
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;
}
}
+ // 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;
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;
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;
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;
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);
+ }
}
}
}
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;
}
}
* 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);
}
}
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;
#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
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);
#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
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;
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
}
spr[i].width = sprite_width;
}
shdelay_disabled = false;
+ exthblank_state = false;
calcdiw();
}
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;
}
{
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;
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;
}
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
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;
}
}
- hbstrt_bordercheck(hpos);
+ hbstrt_bordercheck(hpos, true);
update_denise(hpos);
if (toscr_nr_planes_agnus > thisline_decision.nr_planes) {
bprun_pipeline_flush_delay = 0;
}
}
+ if (plane0) {
+ last_bpl1dat_hpos = hpos;
+ }
}
}
#endif
}
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)
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;
return;
point = (hpos + hpos_hsync_extra) * 2 - DDF_OFFSET;
- if (point == last_sprite_point) {
+ if (point <= last_sprite_point) {
return;
}
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;
}
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);
}
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;
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 */
{
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)
{
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
last_copper_hpos = 0;
ddfstrt_hpos = -1;
ddfstop_hpos = -1;
- sprites_enabled_this_line = false;
last_diw_hpos = 0;
last_diw_hpos2 = 0;
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);
//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) {
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;
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;
+ }
+ }
}
}
#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;
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;
}
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)
}
#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;
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;
}
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) {
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;
hsynctotal += 1 << (CCK_SHRES_SHIFT - 1);
}
+ set_hcenter();
+
calcdiw();
}
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;
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;
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;
}
}
+ 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);
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);
decide_line(hpos);
decide_fetch_safe(hpos);
+ if ((v & 1) != (bplcon0 & 1)) {
+ sync_color_changes(hpos);
+ }
+
if (!issyncstopped()) {
vpos_previous = vpos;
hpos_previous = hpos;
return;
}
if (!aga_mode) {
- v &= 0x003f;
+ v &= (0x0020 | 0x0010 | 0x004 | 0x001);
v |= 0x0c00;
}
#if SPRBORDER
}
decide_line(hpos);
decide_sprites(hpos);
+ if ((bplcon3 & 1) != (v & 1)) {
+ sync_color_changes(hpos);
+ }
bplcon3 = v;
if ((bplcon3 & 1) != (old & 1)) {
updateextblk();
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);
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);
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) {
}
}
#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;
// 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;
// OCS
// BPRUN latched: On
- if (bprun < 0) {
+ if (bprun < 0 && (hpos & 1)) {
decide_line_decision_fetches(hpos);
bprun = 1;
bprun_pipeline_flush_delay = maxhpos;
hpos++;
}
- decide_sprite_fetch(endhpos);
+ decide_sprites_fetch(endhpos);
last_decide_line_hpos = endhpos;
}
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
#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);
}
-static void decide_sprite_fetch(int endhpos)
+static void decide_sprites_fetch(int endhpos)
{
int hpos = last_decide_sprite_hpos;
if (hpos >= endhpos) {
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;
}
eventtab[ev_hsynch].evtime = get_cycles() + HSYNCTIME;
+ eventtab[ev_hsynch].active = 1;
eventtab[ev_hsynch].oldcycles = get_cycles();
events_schedule();
}
}
if (ecs_denise || vpos > get_equ_vblank_endline() || (currprefs.cs_dipagnus && vpos == 0)) {
diw_hcounter = maxhpos * 2;
- last_hdiw = 2 - 1;
}
}
eventtab[ev_hsynch].active = 1;
events_schedule();
}
+
+ debug_hsync();
}
STATIC_INLINE bool is_last_line(void)
vb_start_line = 1;
vb_state = true;
}
- if (vbstop == vpos) {
+ if (vbstopm1 == vpos) {
vbstop_m = vpos;
vb_end_line = true;
vb_state = false;
}
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();
}
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
}
}
+ 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
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;
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;
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);
}
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 */
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 ? */
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 */
/* 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;
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;
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;
}
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;
}
}
if (hardwired) {
- exthblank = false;
doblank = true;
} else if (currprefs.gfx_overscanmode <= OVERSCANMODE_OVERSCAN) {
doblank = true;
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)
}
#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;
{
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) {
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.
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;
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;
#ifdef ECS_DENISE
case 0x106: // BPLCON3
dp_for_drawing->bplcon3 = v;
+ extblankcheck();
break;
#endif
#ifdef AGA
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
}
/* 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;
}
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)
}
} 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) {
(*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))) {
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);
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;
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;
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) {
}
}
-extern int hsync_end_left_border;
-
static void center_image (void)
{
struct amigadisplay *ad = &adisplays[0];
#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;
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);
largest = whereline;
#endif
+ reset_hblanking_limits();
+ set_hblanking_limits();
+
hposblank = 0;
pfield_draw_line(vbout, line, whereline, wherenext);
}
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);
max_diwstop = 0;
vb_state = 0;
+ exthblank = false;
+ exthblanken = false;
+ extborder = false;
lores_reset ();