{
int i = 0;
- while (out_nbits) {
+ if (out_nbits) {
int m = 64 - out_nbits;
- if (m > 16)
- m = 16;
toscr_1_hr(m, fm);
i += m;
}
- i += 32;
- toscr_1_hr(16, fm);
- toscr_1_hr(16, fm);
- i += 32;
- toscr_1_hr(16, fm);
- toscr_1_hr(16, fm);
+ i += 64;
+ toscr_1_hr(64, fm);
if (fm == 2) {
/* flush AGA full 64-bit shift register + possible data in todisplay */
- i += 32;
- toscr_1_hr(16, fm);
- toscr_1_hr(16, fm);
- i += 32;
- toscr_1_hr(16, fm);
- toscr_1_hr(16, fm);
+ i += 64;
+ toscr_1_hr(64, fm);
}
return i >> (1 + toscr_res);
static void calcdiw (void)
{
- int hstrt = diwstrt & 0xFF;
- int hstop = diwstop & 0xFF;
+ int hstrt = (diwstrt & 0xFF) << 2;
+ int hstop = (diwstop & 0xFF) << 2;
int vstrt = diwstrt >> 8;
int vstop = diwstop >> 8;
- // vertical in ECS Agnus
+ // ECS Agnus/AGA: DIWHIGH vertical high bits.
if (diwhigh_written && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
vstrt |= (diwhigh & 7) << 8;
vstop |= ((diwhigh >> 8) & 7) << 8;
if ((vstop & 0x80) == 0)
vstop |= 0x100;
}
- // horizontal in ECS Denise
+ // ECS Denise/AGA: horizontal DIWHIGH high bit.
if (diwhigh_written && (currprefs.chipset_mask & CSMASK_ECS_DENISE)) {
- hstrt |= ((diwhigh >> 5) & 1) << 8;
- hstop |= ((diwhigh >> 13) & 1) << 8;
+ hstrt |= ((diwhigh >> 5) & 1) << (8 + 2);
+ hstop |= ((diwhigh >> 13) & 1) << (8 + 2);
} else {
- hstop += 0x100;
+ hstop |= 0x100 << 2;
+ }
+ // AGA only: horizontal DIWHIGH hires/shres bits.
+ if (currprefs.chipset_hr && diwhigh_written && (currprefs.chipset_mask & CSMASK_AGA)) {
+ hstrt |= (diwhigh >> 3) & 3;
+ hstop |= (diwhigh >> 11) & 3;
}
- diw_hstrt = hstrt;
- diw_hstop = hstop;
+ diw_hstrt = hstrt >> 2;
+ diw_hstop = hstop >> 2;
- diwfirstword = coord_diw_to_window_x (hstrt);
- diwlastword = coord_diw_to_window_x (hstop);
+ diwfirstword = coord_diw_shres_to_window_x(hstrt);
+ diwlastword = coord_diw_shres_to_window_x(hstop);
if (diwfirstword >= diwlastword) {
diwfirstword = min_diwlastword;
if (vpos >= first_planes_vpos && vpos <= last_planes_vpos) {
if (diwlastword > diwlastword_total) {
diwlastword_total = diwlastword;
- if (diwlastword_total > coord_diw_to_window_x (hsyncstartpos * 2))
- diwlastword_total = coord_diw_to_window_x (hsyncstartpos * 2);
+ if (diwlastword_total > coord_diw_lores_to_window_x(hsyncstartpos * 2))
+ diwlastword_total = coord_diw_lores_to_window_x(hsyncstartpos * 2);
}
if (diwfirstword < diwfirstword_total) {
diwfirstword_total = diwfirstword;
- if (diwfirstword_total < coord_diw_to_window_x (hsyncendpos * 2))
- diwfirstword_total = coord_diw_to_window_x (hsyncendpos * 2);
+ if (diwfirstword_total < coord_diw_lores_to_window_x(hsyncendpos * 2))
+ diwfirstword_total = coord_diw_lores_to_window_x(hsyncendpos * 2);
firstword_bplcon1 = bplcon1;
}
}
extern int sprite_buffer_res;
static int lores_factor;
-int lores_shift;
+int lores_shift, shres_shift;
static void pfield_set_linetoscr(void);
{
int old = lores_shift;
lores_shift = lores;
- if (lores_shift != old)
+ if (lores_shift != old) {
+ shres_shift = RES_MAX - lores;
pfield_set_linetoscr();
+ }
}
static void lores_reset (void)
ddflastword_total = coord_hw_to_window_x (ddflastword_total * 2 + DIW_DDF_OFFSET);
if (doublescan <= 0 && !programmedmode) {
- int min = coord_diw_to_window_x (92);
- int max = coord_diw_to_window_x (460);
+ int min = coord_diw_lores_to_window_x (92);
+ int max = coord_diw_lores_to_window_x (460);
if (diwfirstword_total < min)
diwfirstword_total = min;
if (diwlastword_total > max)
where do we start drawing the playfield, where do we start drawing the right border.
All of these are forced into the visible window (VISIBLE_LEFT_BORDER .. VISIBLE_RIGHT_BORDER).
PLAYFIELD_START and PLAYFIELD_END are in window coordinates. */
-static int playfield_start_pre;
+static int playfield_start_pre, playfield_end_pre;
static int playfield_start, playfield_end;
static int real_playfield_start, real_playfield_end;
static int sprite_playfield_start;
}
#endif
- // AGA borderblank starts horizontally 1 hires pixel before bitplanes start, leaving 1 hires background color gap
+ // AGA borderblank starts horizontally 1 hires pixel before bitplanes start, leaving 1 hires pixel background color gap
playfield_start_pre = playfield_start;
- if (currprefs.chipset_hr && (currprefs.chipset_mask & CSMASK_AGA) && currprefs.gfx_resolution > 0) {
- playfield_start_pre -= 2;
+ playfield_end_pre = playfield_end;
+ if (currprefs.chipset_hr && (currprefs.chipset_mask & CSMASK_AGA) && bplres > 0) {
+ playfield_start_pre -= bplres;
+ playfield_end_pre -= bplres;
}
unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start;
lastpos = t;
}
+ // normal
if (playfield_start_pre >= playfield_start || !ce_is_borderblank(colors_for_drawing.extra)) {
+
// normal left border (hblank end to playfield start)
if (nextpos_in_range > lastpos && lastpos < playfield_start) {
int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start;
(*worker_border) (lastpos, t, 0);
lastpos = t;
}
+
+ // playfield
+ if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end) {
+ int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
+ if ((plf2pri >= 5 || plf1pri >= 5) && !(currprefs.chipset_mask & CSMASK_AGA))
+ weird_bitplane_fix(lastpos, t);
+ if (bplxor && may_require_hard_way && worker_pfield != pfield_do_linetoscr_bordersprite_aga)
+ playfield_hard_way(worker_pfield, lastpos, t);
+ else
+ (*worker_pfield) (lastpos, t, 0);
+ lastpos = t;
+ }
+
} else {
+ // special AGA borderblank 1 hires pixel delay
+
// borderblank left border (hblank end to playfield_start_pre)
if (nextpos_in_range > lastpos && lastpos < playfield_start_pre) {
int t = nextpos_in_range <= playfield_start_pre ? nextpos_in_range : playfield_start_pre;
(*worker_border) (lastpos, t, 0);
lastpos = t;
}
- // AGA "buggy" borderblank, real background color visible.
+ // AGA "buggy" borderblank, real background color visible, single hires 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
- if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end) {
- int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
- if ((plf2pri >= 5 || plf1pri >= 5) && !(currprefs.chipset_mask & CSMASK_AGA))
- weird_bitplane_fix (lastpos, t);
- if (bplxor && may_require_hard_way && worker_pfield != pfield_do_linetoscr_bordersprite_aga)
- playfield_hard_way(worker_pfield, lastpos, t);
- else
- (*worker_pfield) (lastpos, t, 0);
- lastpos = t;
+ // playfield with last hires 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 (bplxor && may_require_hard_way && worker_pfield != pfield_do_linetoscr_bordersprite_aga)
+ playfield_hard_way(worker_pfield, lastpos, t);
+ else
+ (*worker_pfield) (lastpos, t, 0);
+ lastpos = t;
+ }
+
+ // last 1 hires 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);
+ lastpos = t;
+ }
+
}
// right border (playfield end to hblank start)
- if (nextpos_in_range > lastpos && lastpos >= playfield_end) {
+ if (nextpos_in_range > lastpos && lastpos >= playfield_end_pre) {
int t = nextpos_in_range <= hblank_right_stop ? nextpos_in_range : hblank_right_stop;
(*worker_border) (lastpos, t, 0);
lastpos = t;
playfield_start = visible_right_border;
playfield_end = visible_right_border;
playfield_start_pre = playfield_start;
+ playfield_end_pre = playfield_end;
do_color_changes (pfield_do_fill_line, pfield_do_fill_line, lineno);
}
/* According to the HRM, pixel data spends a couple of cycles somewhere in the chips
before it appears on-screen. (TW: display emulation now does this automatically) */
#define DIW_DDF_OFFSET 1
+#define DIW_DDF_OFFSET_SHRES (DIW_DDF_OFFSET << 2)
/* this many cycles starting from hpos=0 are visible on right border */
#define HBLANK_OFFSET 9
/* We ignore that many lores pixels at the start of the display. These are
* invisible anyway due to hardware DDF limits. */
#define DISPLAY_LEFT_SHIFT 0x38
+#define DISPLAY_LEFT_SHIFT_SHRES (DISPLAY_LEFT_SHIFT << 2)
#endif
#define PIXEL_XPOS(HPOS) (((HPOS)*2 - DISPLAY_LEFT_SHIFT + DIW_DDF_OFFSET - 1) << lores_shift)
#define min_diwlastword (0)
#define max_diwlastword (PIXEL_XPOS(0x1d4 >> 1))
-extern int lores_shift, interlace_seen;
+extern int lores_shift, shres_shift, interlace_seen;
extern bool aga_mode, direct_rgb;
extern int visible_left_border, visible_right_border;
extern int detected_screen_resolution;
return x + DISPLAY_LEFT_SHIFT;
}
-STATIC_INLINE int coord_diw_to_window_x (int x)
+STATIC_INLINE int coord_diw_lores_to_window_x(int x)
{
return (x - DISPLAY_LEFT_SHIFT + DIW_DDF_OFFSET - 1) << lores_shift;
}
+STATIC_INLINE int coord_diw_shres_to_window_x (int x)
+{
+ return (x - DISPLAY_LEFT_SHIFT_SHRES + DIW_DDF_OFFSET_SHRES - (1 << 2)) >> shres_shift;
+}
+
STATIC_INLINE int coord_window_to_diw_x (int x)
{
x = coord_window_to_hw_x (x);