1 //#define XLINECHECK
2 
3 /*
4  * UAE - The Un*x Amiga Emulator
5  *
6  * Screen drawing functions
7  *
8  * Copyright 1995-2000 Bernd Schmidt
9  * Copyright 1995 Alessandro Bissacco
10  * Copyright 2000-2013 Toni Wilen
11  */
12 
13 /* There are a couple of concepts of "coordinates" in this file.
14    - DIW coordinates
15    - DDF coordinates (essentially cycles, resolution lower than lores by a factor of 2)
16    - Pixel coordinates
17      * in the Amiga's resolution as determined by BPLCON0 ("Amiga coordinates")
18      * in the window resolution as determined by the preferences ("window coordinates").
19      * in the window resolution, and with the origin being the topmost left corner of
20        the window ("native coordinates")
21    One note about window coordinates.  The visible area depends on the width of the
22    window, and the centering code.  The first visible horizontal window coordinate is
23    often _not_ 0, but the value of VISIBLE_LEFT_BORDER instead.
24 
25    One important thing to remember: DIW coordinates are in the lowest possible
26    resolution.
27 
28    To prevent extremely bad things (think pixels cut in half by window borders) from
29    happening, all ports should restrict window widths to be multiples of 16 pixels.  */
30 
31 #include "sysconfig.h"
32 #include "sysdeps.h"
33 
34 #include <ctype.h>
35 #include <assert.h>
36 
37 #include "options.h"
38 #include "threaddep/thread.h"
39 #include "uae.h"
40 #include "memory_uae.h"
41 #include "custom.h"
42 #include "newcpu.h"
43 #include "xwin.h"
44 #include "autoconf.h"
45 #include "gui.h"
46 #include "picasso96.h"
47 #include "drawing.h"
48 #include "savestate.h"
49 #include "statusline.h"
50 #include "inputdevice.h"
51 #include "debug.h"
52 
53 /* internal prototypes */
54 void get_custom_mouse_limits (int *pw, int *ph, int *pdx, int *pdy, int dbl);
55 void init_aspect_maps (void);
56 void finish_drawing_frame (void);
57 void check_picasso (void);
58 void reset_decision_table (void);
59 
60 
61 // extern bool emulate_specialmonitors(struct vidbuffer*, struct vidbuffer*);
62 
63 extern int sprite_buffer_res;
64 int lores_factor, lores_shift;
65 
66 int debug_bpl_mask = 0xff, debug_bpl_mask_one;
67 
lores_reset(void)68 static void lores_reset (void)
69 {
70 	lores_factor = currprefs.gfx_resolution ? 2 : 1;
71 	lores_shift = currprefs.gfx_resolution;
72 	if (doublescan > 0) {
73 		if (lores_shift < 2)
74 			lores_shift++;
75 		lores_factor = 2;
76 	}
77 	sprite_buffer_res = currprefs.gfx_resolution;
78 	if (doublescan > 0 && sprite_buffer_res < RES_SUPERHIRES)
79 		sprite_buffer_res++;
80 }
81 
82 bool aga_mode; /* mirror of chipset_mask & CSMASK_AGA */
83 bool direct_rgb;
84 
85 /* The shift factor to apply when converting between Amiga coordinates and window
86    coordinates.  Zero if the resolution is the same, positive if window coordinates
87    have a higher resolution (i.e. we're stretching the image), negative if window
88    coordinates have a lower resolution (i.e. we're shrinking the image).  */
89 static int res_shift;
90 
91 static int linedbl, linedbld;
92 
93 int interlace_seen = 0;
94 #define AUTO_LORES_FRAMES 10
95 static int can_use_lores = 0, frame_res, frame_res_lace, last_max_ypos;
96 static bool center_reset;
97 
98 /* Lookup tables for dual playfields.  The dblpf_*1 versions are for the case
99    that playfield 1 has the priority, dbplpf_*2 are used if playfield 2 has
100    priority.  If we need an array for non-dual playfield mode, it has no number.  */
101 /* The dbplpf_ms? arrays contain a shift value.  plf_spritemask is initialized
102    to contain two 16 bit words, with the appropriate mask if pf1 is in the
103    foreground being at bit offset 0, the one used if pf2 is in front being at
104    offset 16.  */
105 
106 static int dblpf_ms1[256], dblpf_ms2[256], dblpf_ms[256];
107 static int dblpf_ind1[256], dblpf_ind2[256];
108 
109 static int dblpf_2nd1[256], dblpf_2nd2[256];
110 
111 static const int dblpfofs[] = { 0, 2, 4, 8, 16, 32, 64, 128 };
112 
113 static int sprite_offs[256];
114 
115 static uae_u32 clxtab[256];
116 
117 /* Video buffer description structure. Filled in by the graphics system
118  * dependent code. */
119 
120 struct vidbuf_description gfxvidinfo;
121 
122 /* OCS/ECS color lookup table. */
123 xcolnr xcolors[4096];
124 
125 struct spritepixelsbuf {
126 	uae_u8 attach;
127 	uae_u8 stdata;
128 	uae_u16 data;
129 };
130 static struct spritepixelsbuf spritepixels[MAX_PIXELS_PER_LINE];
131 static int sprite_first_x, sprite_last_x;
132 
133 #ifdef AGA
134 /* AGA mode color lookup tables */
135 unsigned int xredcolors[256], xgreencolors[256], xbluecolors[256];
136 static int dblpf_ind1_aga[256], dblpf_ind2_aga[256];
137 #else
138 static uae_u8 spriteagadpfpixels[1];
139 static int dblpf_ind1_aga[1], dblpf_ind2_aga[1];
140 #endif
141 int xredcolor_s, xredcolor_b, xredcolor_m;
142 int xgreencolor_s, xgreencolor_b, xgreencolor_m;
143 int xbluecolor_s, xbluecolor_b, xbluecolor_m;
144 
145 struct color_entry colors_for_drawing;
146 
147 /* The size of these arrays is pretty arbitrary; it was chosen to be "more
148    than enough".  The coordinates used for indexing into these arrays are
149    almost, but not quite, Amiga coordinates (there's a constant offset).  */
150 union {
151 	/* Let's try to align this thing. */
152 	double uupzuq;
153 	long int cruxmedo;
154 	uae_u8 apixels[MAX_PIXELS_PER_LINE * 2];
155 	uae_u16 apixels_w[MAX_PIXELS_PER_LINE * 2 / sizeof (uae_u16)];
156 	uae_u32 apixels_l[MAX_PIXELS_PER_LINE * 2 / sizeof (uae_u32)];
157 } pixdata;
158 
159 #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
160 uae_u16 *spixels;
161 #else
162 uae_u16 spixels[2 * MAX_SPR_PIXELS];
163 #endif
164 
165 /* Eight bits for every pixel.  */
166 union sps_union spixstate;
167 
168 static uae_u32 ham_linebuf[MAX_PIXELS_PER_LINE * 2];
169 static uae_u8 *real_bplpt[8];
170 
171 static uae_u8 all_ones[MAX_PIXELS_PER_LINE];
172 static uae_u8 all_zeros[MAX_PIXELS_PER_LINE];
173 
174 uae_u8 *xlinebuffer;
175 
176 static int *amiga2aspect_line_map, *native2amiga_line_map;
177 static uae_u8 **row_map;
178 static uae_u8 row_tmp[MAX_PIXELS_PER_LINE * 32 / 8];
179 static int max_drawn_amiga_line;
180 
181 /* line_draw_funcs: pfield_do_linetoscr, pfield_do_fill_line, decode_ham */
182 typedef void (*line_draw_func)(int, int, bool);
183 
184 #define LINE_UNDECIDED 1
185 #define LINE_DECIDED 2
186 #define LINE_DECIDED_DOUBLE 3
187 #define LINE_AS_PREVIOUS 4
188 #define LINE_BLACK 5
189 #define LINE_REMEMBERED_AS_BLACK 6
190 #define LINE_DONE 7
191 #define LINE_DONE_AS_PREVIOUS 8
192 #define LINE_REMEMBERED_AS_PREVIOUS 9
193 
194 #define LINESTATE_SIZE ((MAXVPOS + 2) * 2 + 1)
195 
196 static uae_u8 linestate[LINESTATE_SIZE];
197 
198 uae_u8 line_data[(MAXVPOS + 2) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2];
199 
200 /* Centering variables.  */
201 static int min_diwstart, max_diwstop;
202 /* The visible window: VISIBLE_LEFT_BORDER contains the left border of the visible
203    area, VISIBLE_RIGHT_BORDER the right border.  These are in window coordinates.  */
204 int visible_left_border, visible_right_border;
205 /* Pixels outside of visible_start and visible_stop are always black */
206 static int visible_left_start, visible_right_stop;
207 static int visible_top_start, visible_bottom_stop;
208 /* same for hblank */
209 static int hblank_left_start, hblank_right_stop;
210 
211 static int linetoscr_x_adjust_bytes;
212 #ifdef __LIBRETRO__
213 int thisframe_y_adjust;
214 #else
215 static int thisframe_y_adjust;
216 #endif
217 static int thisframe_y_adjust_real, max_ypos_thisframe, min_ypos_for_screen;
218 static int extra_y_adjust;
219 int thisframe_first_drawn_line, thisframe_last_drawn_line;
220 
221 /* A frame counter that forces a redraw after at least one skipped frame in
222    interlace mode.  */
223 static int last_redraw_point;
224 
225 #define MAX_STOP 30000
226 static int first_drawn_line, last_drawn_line;
227 static int first_block_line, last_block_line;
228 
229 #define NO_BLOCK -3
230 
231 /* These are generated by the drawing code from the line_decisions array for
232    each line that needs to be drawn.  These are basically extracted out of
233    bit fields in the hardware registers.  */
234 static int bplehb, bplham, bpldualpf, bpldualpfpri, bpldualpf2of, bplplanecnt, ecsshres;
235 static bool issprites;
236 static int bplres;
237 static int plf1pri, plf2pri, bplxor;
238 static uae_u32 plf_sprite_mask;
239 static int sbasecol[2] = { 16, 16 };
240 static int hposblank;
241 static bool specialmonitoron;
242 
243 bool picasso_requested_on;
244 bool picasso_on;
245 
246 uae_sem_t gui_sem;
247 int inhibit_frame;
248 
249 int framecnt = 0;
250 static int frame_redraw_necessary;
251 static int picasso_redraw_necessary;
252 
253 #ifdef XLINECHECK
xlinecheck(unsigned int start,unsigned int end)254 static void xlinecheck (unsigned int start, unsigned int end)
255 {
256 	unsigned int xstart = (unsigned int)xlinebuffer + start * gfxvidinfo.pixbytes;
257 	unsigned int xend = (unsigned int)xlinebuffer + end * gfxvidinfo.pixbytes;
258 	unsigned int end1 = (unsigned int)gfxvidinfo.bufmem + gfxvidinfo.rowbytes * gfxvidinfo.height;
259 	int min = linetoscr_x_adjust_bytes / gfxvidinfo.pixbytes;
260 	int ok = 1;
261 
262 	if (xstart >= gfxvidinfo.emergmem && xstart < gfxvidinfo.emergmem + 4096 * gfxvidinfo.pixbytes &&
263 		xend >= gfxvidinfo.emergmem && xend < gfxvidinfo.emergmem + 4096 * gfxvidinfo.pixbytes)
264 		return;
265 
266 	if (xstart < (unsigned int)gfxvidinfo.bufmem || xend < (unsigned int)gfxvidinfo.bufmem)
267 		ok = 0;
268 	if (xend > end1 || xstart >= end1)
269 		ok = 0;
270 	xstart -= (unsigned int)gfxvidinfo.bufmem;
271 	xend -= (unsigned int)gfxvidinfo.bufmem;
272 	if ((xstart % gfxvidinfo.rowbytes) >= gfxvidinfo.width * gfxvidinfo.pixbytes)
273 		ok = 0;
274 	if ((xend % gfxvidinfo.rowbytes) >= gfxvidinfo.width * gfxvidinfo.pixbytes)
275 		ok = 0;
276 	if (xstart >= xend)
277 		ok = 0;
278 	if (xend - xstart > gfxvidinfo.width * gfxvidinfo.pixbytes)
279 		ok = 0;
280 
281 	if (!ok) {
282 		write_log (_T("*** %d-%d (%dx%dx%d %d) %p\n"),
283 			start - min, end - min, gfxvidinfo.width, gfxvidinfo.height,
284 			gfxvidinfo.pixbytes, gfxvidinfo.rowbytes,
285 			xlinebuffer);
286 	}
287 }
288 #else
289 #define xlinecheck(...) { }
290 #endif
291 
292 /*static void clearbuffer (struct vidbuffer *dst)
293 {
294 	if (!dst->bufmem_allocated)
295 		return;
296 	uae_u8 *p = dst->bufmem_allocated;
297 	for (int y = dst->height_allocated; y--) {
298 		memset (p, 0, dst->width_allocated * dst->pixbytes);
299 		p += dst->rowbytes;
300 	}
301 }*/
302 
reset_decision_table(void)303 void reset_decision_table (void)
304 {
305 	for (int i = sizeof linestate / sizeof *linestate; i--; )
306 		linestate[i] = LINE_UNDECIDED;
307 }
308 
count_frame(void)309 STATIC_INLINE void count_frame (void)
310 {
311 	framecnt++;
312 	if (framecnt >= currprefs.gfx_framerate)
313 		framecnt = 0;
314 	if (inhibit_frame)
315 		framecnt = 1;
316 }
317 
xshift(int x,int shift)318 STATIC_INLINE int xshift (int x, int shift)
319 {
320 	if (shift < 0)
321 		return x >> (-shift);
322 	else
323 		return x << shift;
324 }
325 
coord_native_to_amiga_x(int x)326 int coord_native_to_amiga_x (int x)
327 {
328 	x += visible_left_border;
329 	x = xshift (x, 1 - lores_shift);
330 	return x + 2 * DISPLAY_LEFT_SHIFT - 2 * DIW_DDF_OFFSET;
331 }
332 
coord_native_to_amiga_y(int y)333 int coord_native_to_amiga_y (int y)
334 {
335 	return native2amiga_line_map[y] + thisframe_y_adjust - minfirstline;
336 }
337 
res_shift_from_window(int x)338 STATIC_INLINE int res_shift_from_window (int x)
339 {
340 	if (res_shift >= 0)
341 		return x >> res_shift;
342 	return x << -res_shift;
343 }
344 
res_shift_from_amiga(int x)345 STATIC_INLINE int res_shift_from_amiga (int x)
346 {
347 	if (res_shift >= 0)
348 		return x >> res_shift;
349 	return x << -res_shift;
350 }
351 
notice_screen_contents_lost(void)352 void notice_screen_contents_lost (void)
353 {
354 	picasso_redraw_necessary = 1;
355 	frame_redraw_necessary = 2;
356 }
357 
isnativevidbuf(void)358 bool isnativevidbuf (void)
359 {
360 	return true;
361 }
362 
363 extern int plffirstline_total, plflastline_total;
364 extern int first_planes_vpos, last_planes_vpos;
365 extern int diwfirstword_total, diwlastword_total;
366 extern int ddffirstword_total, ddflastword_total;
367 extern int firstword_bplcon1;
368 extern int lof_store;
369 
370 #define MIN_DISPLAY_W 256
371 #define MIN_DISPLAY_H 192
372 #define MAX_DISPLAY_W 362
373 #define MAX_DISPLAY_H 283
374 
375 static int gclow, gcloh, gclox, gcloy, gclorealh;
376 
get_custom_topedge(int * xp,int * yp,bool max)377 void get_custom_topedge (int *xp, int *yp, bool max)
378 {
379 	if (isnativevidbuf () && !max) {
380 		int x, y;
381 		x = visible_left_border + (DISPLAY_LEFT_SHIFT << currprefs.gfx_resolution);
382 		y = minfirstline << currprefs.gfx_vresolution;
383 		*xp = x;
384 		*yp = y;
385 	} else {
386 		*xp = 0;
387 		*yp = 0;
388 	}
389 }
390 
reset_custom_limits(void)391 static void reset_custom_limits (void)
392 {
393 	gclow = gcloh = gclox = gcloy = 0;
394 	gclorealh = -1;
395 }
396 
set_blanking_limits(void)397 static void set_blanking_limits (void)
398 {
399 	hblank_left_start = visible_left_start;
400 	hblank_right_stop = visible_right_stop;
401 
402 	if (programmedmode) {
403 		if (hblank_left_start < coord_hw_to_window_x (hsyncendpos * 2))
404 			hblank_left_start = coord_hw_to_window_x (hsyncendpos * 2);
405 		if (hblank_right_stop > coord_hw_to_window_x (hsyncstartpos * 2))
406 			hblank_right_stop = coord_hw_to_window_x (hsyncstartpos * 2);
407 	}
408 }
409 
set_custom_limits(int w,int h,int dx,int dy)410 void set_custom_limits (int w, int h, int dx, int dy)
411 {
412 	int vls = visible_left_start;
413 	int vrs = visible_right_stop;
414 	int vts = visible_top_start;
415 	int vbs = visible_bottom_stop;
416 
417 	if (w <= 0 || dx < 0) {
418 		visible_left_start = 0;
419 		visible_right_stop = MAX_STOP;
420 	} else {
421 		visible_left_start = visible_left_border + dx;
422 		visible_right_stop = visible_left_start + w;
423 	}
424 	if (h <= 0 || dy < 0) {
425 		visible_top_start = 0;
426 		visible_bottom_stop = MAX_STOP;
427 	} else {
428 		visible_top_start = min_ypos_for_screen + dy;
429 		visible_bottom_stop = visible_top_start + h;
430 	}
431 	if (vls != visible_left_start || vrs != visible_right_stop ||
432 		vts != visible_top_start || vbs != visible_bottom_stop)
433 		notice_screen_contents_lost ();
434 	set_blanking_limits ();
435 }
436 
get_custom_limits(int * pw,int * ph,int * pdx,int * pdy,int * prealh)437 int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy, int *prealh)
438 {
439 	int w, h, dx, dy, y1, y2, dbl1, dbl2;
440 	int ret = 0;
441 
442 	if (!pw || !ph || !pdx || !pdy) {
443 		reset_custom_limits ();
444 		return 0;
445 	}
446 
447 	if (!isnativevidbuf ()) {
448 		*pw = gfxvidinfo.outwidth;
449 		*ph = gfxvidinfo.outheight;
450 		*pdx = 0;
451 		*pdy = 0;
452 		*prealh = -1;
453 		return 1;
454 	}
455 
456 	*pw = gclow;
457 	*ph = gcloh;
458 	*pdx = gclox;
459 	*pdy = gcloy;
460 	*prealh = gclorealh;
461 
462 	if (gclow > 0 && gcloh > 0)
463 		ret = -1;
464 
465 	if (interlace_seen) {
466 		static int interlace_count;
467 		// interlace = only use long frames
468 		if (lof_store && (interlace_count & 1) == 0)
469 			interlace_count++;
470 		if (!lof_store && (interlace_count & 1) != 0)
471 			interlace_count++;
472 		if (interlace_count < 3)
473 			return ret;
474 		if (!lof_store)
475 			return ret;
476 		interlace_count = 0;
477 		/* program may have set last visible line as last possible line (CD32 boot screen) */
478 		if (last_planes_vpos < maxvpos)
479 			last_planes_vpos++;
480 		if (plflastline_total < maxvpos)
481 			plflastline_total++;
482 	}
483 
484 	if (plflastline_total < 4)
485 		plflastline_total = last_planes_vpos;
486 
487 	ddffirstword_total = coord_hw_to_window_x (ddffirstword_total * 2 + DIW_DDF_OFFSET);
488 	ddflastword_total = coord_hw_to_window_x (ddflastword_total * 2 + DIW_DDF_OFFSET);
489 
490 	if (doublescan <= 0 && !programmedmode) {
491 		int min = coord_diw_to_window_x (92);
492 		int max = coord_diw_to_window_x (460);
493 		if (diwfirstword_total < min)
494 			diwfirstword_total = min;
495 		if (diwlastword_total > max)
496 			diwlastword_total = max;
497 		if (ddffirstword_total < min)
498 			ddffirstword_total = min;
499 		if (ddflastword_total > max)
500 			ddflastword_total = max;
501 		if (0 && !(currprefs.chipset_mask & CSMASK_AGA)) {
502 			if (ddffirstword_total > diwfirstword_total)
503 				diwfirstword_total = ddffirstword_total;
504 			if (ddflastword_total < diwlastword_total)
505 				diwlastword_total = ddflastword_total;
506 		}
507 	}
508 
509 	w = diwlastword_total - diwfirstword_total;
510 	dx = diwfirstword_total - visible_left_border;
511 
512 	y2 = plflastline_total;
513 	if (y2 > last_planes_vpos)
514 		y2 = last_planes_vpos;
515 	y1 = plffirstline_total;
516 	if (first_planes_vpos > y1)
517 		y1 = first_planes_vpos;
518 	if (minfirstline > y1)
519 		y1 = minfirstline;
520 
521 	dbl2 = dbl1 = currprefs.gfx_vresolution;
522 	if (doublescan > 0 && interlace_seen <= 0) {
523 		dbl1--;
524 		dbl2--;
525 	}
526 
527 	h = y2 - y1;
528 	dy = y1 - minfirstline;
529 
530 	if (first_planes_vpos == 0) {
531 		// no planes enabled during frame
532 		if (ret < 0)
533 			return 1;
534 		h = currprefs.ntscmode ? 200 : 240;
535 		w = 320 << currprefs.gfx_resolution;
536 		dy = 36 / 2;
537 		dx = 58;
538 	}
539 
540 	if (dx < 0)
541 		dx = 0;
542 
543 	*prealh = -1;
544 	if (!programmedmode && first_planes_vpos) {
545 		int th = (maxvpos - minfirstline) * 95 / 100;
546 		if (th > h) {
547 			th = xshift (th, dbl1);
548 			*prealh = th;
549 		}
550 	}
551 
552 	dy = xshift (dy, dbl2);
553 	h = xshift (h, dbl1);
554 
555 	if (w == 0 || h == 0)
556 		return 0;
557 
558 	if (doublescan <= 0 && !programmedmode) {
559 		if ((w >> currprefs.gfx_resolution) < MIN_DISPLAY_W) {
560 			dx += (w - (MIN_DISPLAY_W << currprefs.gfx_resolution)) / 2;
561 			w = MIN_DISPLAY_W << currprefs.gfx_resolution;
562 		}
563 		if ((h >> dbl1) < MIN_DISPLAY_H) {
564 			dy += (h - (MIN_DISPLAY_H << dbl1)) / 2;
565 			h = MIN_DISPLAY_H << dbl1;
566 		}
567 		if ((w >> currprefs.gfx_resolution) > MAX_DISPLAY_W) {
568 			dx += (w - (MAX_DISPLAY_W << currprefs.gfx_resolution)) / 2;
569 			w = MAX_DISPLAY_W << currprefs.gfx_resolution;
570 		}
571 		if ((h >> dbl1) > MAX_DISPLAY_H) {
572 			dy += (h - (MAX_DISPLAY_H << dbl1)) / 2;
573 			h = MAX_DISPLAY_H << dbl1;
574 		}
575 	}
576 
577 	if (gclow == w && gcloh == h && gclox == dx && gcloy == dy)
578 		return ret;
579 
580 	if (w <= 0 || h <= 0 || dx < 0 || dy < 0)
581 		return ret;
582 	if (doublescan <= 0 && !programmedmode) {
583 		if (dx > gfxvidinfo.inwidth / 3)
584 			return ret;
585 		if (dy > gfxvidinfo.inheight / 3)
586 			return ret;
587 	}
588 
589 	gclow = w;
590 	gcloh = h;
591 	gclox = dx;
592 	gcloy = dy;
593 	gclorealh = *prealh;
594 	*pw = w;
595 	*ph = h;
596 	*pdx = dx;
597 	*pdy = dy;
598 #if 1
599 	write_log (_T("Display Size: %dx%d Offset: %dx%d\n"), w, h, dx, dy);
600 	write_log (_T("First: %d Last: %d MinV: %d MaxV: %d Min: %d\n"),
601 		plffirstline_total, plflastline_total,
602 		first_planes_vpos, last_planes_vpos, minfirstline);
603 #endif
604 	center_reset = true;
605 	return 1;
606 }
607 
get_custom_mouse_limits(int * pw,int * ph,int * pdx,int * pdy,int dbl)608 void get_custom_mouse_limits (int *pw, int *ph, int *pdx, int *pdy, int dbl)
609 {
610 /* REMOVEME:
611  * nowhere used
612  */
613 #if 0
614 	int delay1, delay2;
615 #endif
616 	int w, h, dx, dy, dbl1, dbl2, y1, y2;
617 
618 	w = diwlastword_total - diwfirstword_total;
619 	dx = diwfirstword_total - visible_left_border;
620 
621 	y2 = plflastline_total;
622 	if (y2 > last_planes_vpos)
623 		y2 = last_planes_vpos;
624 	y1 = plffirstline_total;
625 	if (first_planes_vpos > y1)
626 		y1 = first_planes_vpos;
627 	if (minfirstline > y1)
628 		y1 = minfirstline;
629 
630 	h = y2 - y1;
631 	dy = y1 - minfirstline;
632 
633 	if (*pw > 0)
634 		w = *pw;
635 
636 	w = xshift (w, res_shift);
637 
638 	if (*ph > 0)
639 		h = *ph;
640 
641 //	delay1 = (firstword_bplcon1 & 0x0f) | ((firstword_bplcon1 & 0x0c00) >> 6);
642 //	delay2 = ((firstword_bplcon1 >> 4) & 0x0f) | (((firstword_bplcon1 >> 4) & 0x0c00) >> 6);
643 //	if (delay1 == delay2)
644 //		dx += delay1;
645 
646 	dx = xshift (dx, res_shift);
647 
648 	dbl2 = dbl1 = currprefs.gfx_vresolution;
649 	if ((doublescan > 0 || interlace_seen > 0) && !dbl) {
650 		dbl1--;
651 		dbl2--;
652 	}
653 	if (interlace_seen > 0)
654 		dbl2++;
655 	if (interlace_seen <= 0 && dbl)
656 		dbl2--;
657 	h = xshift (h, dbl1);
658 	dy = xshift (dy, dbl2);
659 
660 	if (w < 1)
661 		w = 1;
662 	if (h < 1)
663 		h = 1;
664 	if (dx < 0)
665 		dx = 0;
666 	if (dy < 0)
667 		dy = 0;
668 	*pw = w; *ph = h;
669 	*pdx = dx; *pdy = dy;
670 }
671 
672 static struct decision *dp_for_drawing;
673 static struct draw_info *dip_for_drawing;
674 
675 /* Record DIW of the current line for use by centering code.  */
record_diw_line(int plfstrt,int first,int last)676 void record_diw_line (int plfstrt, int first, int last)
677 {
678 	if (last > max_diwstop)
679 		max_diwstop = last;
680 	if (first < min_diwstart) {
681 		min_diwstart = first;
682 		/*
683 		if (plfstrt * 2 > min_diwstart)
684 		min_diwstart = plfstrt * 2;
685 		*/
686 	}
687 }
688 
689 /*
690  * Screen update macros/functions
691  */
692 
693 /* The important positions in the line: where do we start drawing the left border,
694    where do we start drawing the playfield, where do we start drawing the right border.
695    All of these are forced into the visible window (VISIBLE_LEFT_BORDER .. VISIBLE_RIGHT_BORDER).
696    PLAYFIELD_START and PLAYFIELD_END are in window coordinates.  */
697 static int playfield_start, playfield_end;
698 static int real_playfield_start, real_playfield_end;
699 static int linetoscr_diw_start, linetoscr_diw_end;
700 static int native_ddf_left, native_ddf_right;
701 #if 0
702 static bool can_have_bordersprite;
703 #endif
704 
705 static int pixels_offset;
706 static int src_pixel, ham_src_pixel;
707 /* How many pixels in window coordinates which are to the left of the left border.  */
708 static int unpainted;
709 
getbgc(bool blank)710 STATIC_INLINE xcolnr getbgc (bool blank)
711 {
712 #if 0
713 	if (blank)
714 		return xcolors[0x088];
715 	else if (hposblank == 1)
716 		return xcolors[0xf00];
717 	else if (hposblank == 2)
718 		return xcolors[0x0f0];
719 	else if (hposblank == 3)
720 		return xcolors[0x00f];
721 	else if (colors_for_drawing.borderblank)
722 		return xcolors[0x880];
723 	//return colors_for_drawing.acolors[0];
724 	return xcolors[0xf0f];
725 #endif
726 	return (blank || hposblank || colors_for_drawing.borderblank) ? 0 : colors_for_drawing.acolors[0];
727 }
728 
729 /* Initialize the variables necessary for drawing a line.
730  * This involves setting up start/stop positions and display window
731  * borders.  */
pfield_init_linetoscr(void)732 static void pfield_init_linetoscr (void)
733 {
734 	/* First, get data fetch start/stop in DIW coordinates.  */
735 	int ddf_left = dp_for_drawing->plfleft * 2 + DIW_DDF_OFFSET;
736 	int ddf_right = dp_for_drawing->plfright * 2 + DIW_DDF_OFFSET;
737 	int leftborderhidden;
738 
739 	/* Compute datafetch start/stop in pixels; native display coordinates.  */
740 	native_ddf_left = coord_hw_to_window_x (ddf_left);
741 	native_ddf_right = coord_hw_to_window_x (ddf_right);
742 
743 	if (native_ddf_left < 0)
744 		native_ddf_left = 0;
745 	if (native_ddf_right < native_ddf_left)
746 		native_ddf_right = native_ddf_left;
747 
748 	linetoscr_diw_start = dp_for_drawing->diwfirstword;
749 	linetoscr_diw_end = dp_for_drawing->diwlastword;
750 
751 	/* Perverse cases happen. */
752 	if (linetoscr_diw_end < linetoscr_diw_start)
753 		linetoscr_diw_end = linetoscr_diw_start;
754 
755 	res_shift = lores_shift - bplres;
756 
757 	playfield_start = linetoscr_diw_start;
758 	playfield_end = linetoscr_diw_end;
759 
760 	if (playfield_start < native_ddf_left)
761 		playfield_start = native_ddf_left;
762 	if (playfield_end > native_ddf_right)
763 		playfield_end = native_ddf_right;
764 
765 	if (playfield_start < visible_left_border)
766 		playfield_start = visible_left_border;
767 	if (playfield_start > visible_right_border)
768 		playfield_start = visible_right_border;
769 	if (playfield_end < visible_left_border)
770 		playfield_end = visible_left_border;
771 	if (playfield_end > visible_right_border)
772 		playfield_end = visible_right_border;
773 
774 	real_playfield_end = playfield_end;
775 	real_playfield_start = playfield_start;
776 
777 	// Sprite hpos don't include DIW_DDF_OFFSET and can appear 1 lores pixel
778 	// before first bitplane pixel appears.
779 	// This means "bordersprite" condition is possible under OCS/ECS too. Argh!
780 	if (dip_for_drawing->nr_sprites) {
781 		/* bordersprite off or not supported: sprites are visible until diw_end */
782 		if (playfield_end < linetoscr_diw_end && hblank_right_stop > playfield_end) {
783 			playfield_end = linetoscr_diw_end;
784 		}
785 		int end = coord_hw_to_window_x (dp_for_drawing->plfleft * 2);
786 		if (end < visible_left_border)
787 			end = visible_left_border;
788 		if (end < playfield_start && end > linetoscr_diw_start) {
789 			playfield_start = end;
790 		}
791 	}
792 
793 #ifdef AGA
794 	if (dp_for_drawing->bordersprite_seen && dip_for_drawing->nr_sprites) {
795 		int min = visible_right_border, max = visible_left_border, i;
796 		for (i = 0; i < dip_for_drawing->nr_sprites; i++) {
797 			int x;
798 			x = curr_sprite_entries[dip_for_drawing->first_sprite_entry + i].pos;
799 			if (x < min)
800 				min = x;
801 			x = curr_sprite_entries[dip_for_drawing->first_sprite_entry + i].max;
802 			if (x > max)
803 				max = x;
804 		}
805 		min = coord_hw_to_window_x (min >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift);
806 		max = coord_hw_to_window_x (max >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift);
807 
808 		if (min < playfield_start)
809 			playfield_start = min;
810 		if (playfield_start < visible_left_border)
811 			playfield_start = visible_left_border;
812 		if (max > playfield_end)
813 			playfield_end = max;
814 		if (playfield_end > visible_right_border)
815 			playfield_end = visible_right_border;
816 	}
817 #endif
818 
819 	unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start;
820 	ham_src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window (playfield_start - native_ddf_left);
821 	unpainted = res_shift_from_window (unpainted);
822 
823 	if (sprite_first_x < sprite_last_x) {
824 		if (sprite_first_x < 0)
825 			sprite_first_x = 0;
826 		if (sprite_last_x >= MAX_PIXELS_PER_LINE - 1)
827 			sprite_last_x = MAX_PIXELS_PER_LINE - 2;
828 		if (sprite_first_x < sprite_last_x)
829 			memset (spritepixels + sprite_first_x, 0, sizeof (struct spritepixelsbuf) * (sprite_last_x - sprite_first_x + 1));
830 	}
831 	sprite_last_x = 0;
832 	sprite_first_x = MAX_PIXELS_PER_LINE - 1;
833 
834 	/* Now, compute some offsets.  */
835 	ddf_left -= DISPLAY_LEFT_SHIFT;
836 	pixels_offset = MAX_PIXELS_PER_LINE - (ddf_left << bplres);
837 	ddf_left <<= bplres;
838 
839 	leftborderhidden = playfield_start - native_ddf_left;
840 	if (hblank_left_start > playfield_start)
841 		leftborderhidden += hblank_left_start - playfield_start;
842 	src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window (leftborderhidden);
843 
844 	if (dip_for_drawing->nr_sprites == 0)
845 		return;
846 
847 	/* We need to clear parts of apixels.  */
848 	if (linetoscr_diw_start < native_ddf_left) {
849 		int size = res_shift_from_window (native_ddf_left - linetoscr_diw_start);
850 		linetoscr_diw_start = native_ddf_left;
851 		memset (pixdata.apixels + MAX_PIXELS_PER_LINE - size, 0, size);
852 	}
853 	if (linetoscr_diw_end > native_ddf_right) {
854 		int pos = res_shift_from_window (native_ddf_right - native_ddf_left);
855 		int size = res_shift_from_window (linetoscr_diw_end - native_ddf_right);
856 		linetoscr_diw_start = native_ddf_left;
857 		memset (pixdata.apixels + MAX_PIXELS_PER_LINE + pos, 0, size);
858 	}
859 }
860 
861 // erase sprite graphics in pixdata if they were outside of ddf
pfield_erase_hborder_sprites(void)862 static void pfield_erase_hborder_sprites (void)
863 {
864 	if (sprite_first_x < native_ddf_left) {
865 		int size = res_shift_from_window (native_ddf_left - sprite_first_x);
866 		memset (pixdata.apixels + MAX_PIXELS_PER_LINE - size, 0, size);
867 	}
868 	if (sprite_last_x > native_ddf_right) {
869 		int pos = res_shift_from_window (native_ddf_right - native_ddf_left);
870 		int size = res_shift_from_window (sprite_last_x - native_ddf_right);
871 		memset (pixdata.apixels + MAX_PIXELS_PER_LINE + pos, 0, size);
872 	}
873 }
874 
875 // erase whole viewable area if upper or lower border
pfield_erase_vborder_sprites(void)876 static void pfield_erase_vborder_sprites (void)
877 {
878 	uae_u8 c = colors_for_drawing.borderblank ? 0 : colors_for_drawing.acolors[0];
879 	int size = res_shift_from_window (linetoscr_diw_end - linetoscr_diw_start);
880 	memset (pixdata.apixels + MAX_PIXELS_PER_LINE - size, c, size);
881 }
882 
883 
merge_2pixel16(uae_u16 p1,uae_u16 p2)884 STATIC_INLINE uae_u16 merge_2pixel16 (uae_u16 p1, uae_u16 p2)
885 {
886 	uae_u16 v = ((((p1 >> xredcolor_s) & xredcolor_m) + ((p2 >> xredcolor_s) & xredcolor_m)) / 2) << xredcolor_s;
887 	v |= ((((p1 >> xbluecolor_s) & xbluecolor_m) + ((p2 >> xbluecolor_s) & xbluecolor_m)) / 2) << xbluecolor_s;
888 	v |= ((((p1 >> xgreencolor_s) & xgreencolor_m) + ((p2 >> xgreencolor_s) & xgreencolor_m)) / 2) << xgreencolor_s;
889 	return v;
890 }
merge_2pixel32(uae_u32 p1,uae_u32 p2)891 STATIC_INLINE uae_u32 merge_2pixel32 (uae_u32 p1, uae_u32 p2)
892 {
893 	uae_u32 v = ((((p1 >> 16) & 0xff) + ((p2 >> 16) & 0xff)) / 2) << 16;
894 	v |= ((((p1 >> 8) & 0xff) + ((p2 >> 8) & 0xff)) / 2) << 8;
895 	v |= ((((p1 >> 0) & 0xff) + ((p2 >> 0) & 0xff)) / 2) << 0;
896 	return v;
897 }
898 
fill_line_16(uae_u8 * buf,int start,int stop,bool blank)899 STATIC_INLINE void fill_line_16 (uae_u8 *buf, int start, int stop, bool blank)
900 {
901 	uae_u16 *b = (uae_u16 *)buf;
902 	int i;
903 	unsigned int rem = 0;
904 	xcolnr col = getbgc (blank);
905 	if (((long)&b[start]) & 1)
906 		b[start++] = (uae_u16) col;
907 	if (start >= stop)
908 		return;
909 	if (((long)&b[stop]) & 1) {
910 		rem++;
911 		stop--;
912 	}
913 	for (i = start; i < stop; i += 2) {
914 		uae_u32 *b2 = (uae_u32 *)&b[i];
915 		*b2 = col;
916 	}
917 	if (rem)
918 		b[stop] = (uae_u16)col;
919 }
920 
fill_line_32(uae_u8 * buf,int start,int stop,bool blank)921 STATIC_INLINE void fill_line_32 (uae_u8 *buf, int start, int stop, bool blank)
922 {
923 	uae_u32 *b = (uae_u32 *)buf;
924 	int i;
925 	xcolnr col = getbgc (blank);
926 	for (i = start; i < stop; i++)
927 		b[i] = col;
928 }
pfield_do_fill_line(int start,int stop,bool blank)929 static void pfield_do_fill_line (int start, int stop, bool blank)
930 {
931 	switch (gfxvidinfo.pixbytes) {
932 	case 2: fill_line_16 (xlinebuffer, start, stop, blank); break;
933 	case 4: fill_line_32 (xlinebuffer, start, stop, blank); break;
934 	}
935 }
936 
fill_line2(int startpos,int len)937 STATIC_INLINE void fill_line2 (int startpos, int len)
938 {
939 	int shift;
940 	int nints, nrem;
941 	int *start;
942 	xcolnr val;
943 
944 /*    shift = 0;
945     if (gfxvidinfo.pixbytes == 2)
946 		shift = 1;
947     if (gfxvidinfo.pixbytes == 4)
948 		shift = 2;*/
949     shift = gfxvidinfo.pixbytes >> 1;
950 
951 	nints = len >> (2 - shift);
952 	nrem = nints & 7;
953 	nints &= ~7;
954 	start = (int *)(((uae_u8*)xlinebuffer) + (startpos << shift));
955 	val = getbgc (false);
956 	for (; nints > 0; nints -= 8, start += 8) {
957 		*start = val;
958 		*(start+1) = val;
959 		*(start+2) = val;
960 		*(start+3) = val;
961 		*(start+4) = val;
962 		*(start+5) = val;
963 		*(start+6) = val;
964 		*(start+7) = val;
965 	}
966 
967 	switch (nrem) {
968 	case 7:
969 		*start++ = val;
970 	case 6:
971 		*start++ = val;
972 	case 5:
973 		*start++ = val;
974 	case 4:
975 		*start++ = val;
976 	case 3:
977 		*start++ = val;
978 	case 2:
979 		*start++ = val;
980 	case 1:
981 		*start = val;
982 	}
983 }
984 
fill_line(void)985 static void fill_line (void)
986 {
987 	int hs = coord_hw_to_window_x (hsyncstartpos * 2);
988 	if (hs >= gfxvidinfo.inwidth || hposblank) {
989 		hposblank = 3;
990 		fill_line2 (visible_left_border, gfxvidinfo.inwidth);
991 	} else {
992 		fill_line2 (visible_left_border, hs);
993 		hposblank = 2;
994 		fill_line2 (visible_left_border + hs, gfxvidinfo.inwidth);
995 	}
996 }
997 
998 #define SPRITE_DEBUG 0
render_sprites(int pos,int dualpf,uae_u8 apixel,int aga)999 STATIC_INLINE uae_u8 render_sprites (int pos, int dualpf, uae_u8 apixel, int aga)
1000 {
1001 	struct spritepixelsbuf *spb = &spritepixels[pos];
1002 	unsigned int v = spb->data;
1003 	int *shift_lookup = dualpf ? (bpldualpfpri ? dblpf_ms2 : dblpf_ms1) : dblpf_ms;
1004 	int maskshift, plfmask;
1005 
1006 	/* The value in the shift lookup table is _half_ the shift count we
1007 	   need.  This is because we can't shift 32 bits at once (undefined
1008 	   behaviour in C).  */
1009 	maskshift = shift_lookup[apixel];
1010 	plfmask = (plf_sprite_mask >> maskshift) >> maskshift;
1011 	v &= ~plfmask;
1012 	if (v != 0 || SPRITE_DEBUG) {
1013 		unsigned int vlo, vhi, col;
1014 		unsigned int v1 = v & 255;
1015 		/* OFFS determines the sprite pair with the highest priority that has
1016 		any bits set.  E.g. if we have 0xFF00 in the buffer, we have sprite
1017 		pairs 01 and 23 cleared, and pairs 45 and 67 set, so OFFS will
1018 		have a value of 4.
1019 		2 * OFFS is the bit number in V of the sprite pair, and it also
1020 		happens to be the color offset for that pair.
1021 		*/
1022 		int offs;
1023 		if (v1 == 0)
1024 			offs = 4 + sprite_offs[v >> 8];
1025 		else
1026 			offs = sprite_offs[v1];
1027 
1028 		/* Shift highest priority sprite pair down to bit zero.  */
1029 		v >>= offs * 2;
1030 		v &= 15;
1031 #if SPRITE_DEBUG > 0
1032 		v ^= 8;
1033 #endif
1034 		if (spb->attach && (spb->stdata & (3 << offs))) {
1035 			col = v;
1036 			if (aga)
1037 				col += sbasecol[1];
1038 			else
1039 				col += 16;
1040 		} else {
1041 			/* This sequence computes the correct color value.  We have to select
1042 			   either the lower-numbered or the higher-numbered sprite in the pair.
1043 			   We have to select the high one if the low one has all bits zero.
1044 			   If the lower-numbered sprite has any bits nonzero, (VLO - 1) is in
1045 			   the range of 0..2, and with the mask and shift, VHI will be zero.
1046 			   If the lower-numbered sprite is zero, (VLO - 1) is a mask of
1047 			   0xFFFFFFFF, and we select the bits of the higher numbered sprite
1048 			   in VHI.
1049 			   This is _probably_ more efficient than doing it with branches.  */
1050 			vlo = v & 3;
1051 			vhi = (v & (vlo - 1)) >> 2;
1052 			col = (vlo | vhi);
1053 			if (aga) {
1054 				if (vhi > 0)
1055 					col += sbasecol[1];
1056 				else
1057 					col += sbasecol[0];
1058 			} else {
1059 				col += 16;
1060 			}
1061 			col += offs * 2;
1062 		}
1063 
1064 		return col;
1065 	}
1066 
1067 	return 0;
1068 }
1069 
1070 #define LTPARMS src_pixel, start, stop
1071 
1072 #ifdef MSB_FIRST
1073 #include "linetoscr-be.c"
1074 #else
1075 #include "linetoscr.c"
1076 #endif
1077 
1078 #ifdef ECS_DENISE
1079 /* ECS SuperHires special cases */
1080 
1081 #define PUTBPIX(x) buf[dpix] = (x);
1082 
shsprite(int dpix,uae_u32 spix_val,uae_u32 v,int spr)1083 STATIC_INLINE uae_u32 shsprite (int dpix, uae_u32 spix_val, uae_u32 v, int spr)
1084 {
1085 	uae_u8 sprcol;
1086 	uae_u16 scol;
1087 	if (!spr)
1088 		return v;
1089 	sprcol = render_sprites (dpix, 0, spix_val, 0);
1090 	if (!sprcol)
1091 		return v;
1092 	/* good enough for now.. */
1093 	scol = colors_for_drawing.color_regs_ecs[sprcol] & 0xccc;
1094 	scol |= scol >> 2;
1095 	return xcolors[scol];
1096 }
1097 
linetoscr_16_sh(int spix,int dpix,int stoppos,int spr)1098 static int NOINLINE linetoscr_16_sh (int spix, int dpix, int stoppos, int spr)
1099 {
1100 	uae_u16 *buf = (uae_u16 *) xlinebuffer;
1101 
1102 	while (dpix < stoppos) {
1103 		uae_u16 spix_val1, spix_val2;
1104 		uae_u16 v;
1105 		int off;
1106 		spix_val1 = pixdata.apixels[spix++];
1107 		spix_val2 = pixdata.apixels[spix++];
1108 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1109 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1110 		v |= v >> 2;
1111 		PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr));
1112 		dpix++;
1113 		v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2;
1114 		v |= v >> 2;
1115 		PUTBPIX(shsprite (dpix, spix_val2, xcolors[v], spr));
1116 		dpix++;
1117 	}
1118 	return spix;
1119 }
linetoscr_32_sh(int spix,int dpix,int stoppos,int spr)1120 static int NOINLINE linetoscr_32_sh (int spix, int dpix, int stoppos, int spr)
1121 {
1122 	uae_u32 *buf = (uae_u32 *) xlinebuffer;
1123 
1124 	while (dpix < stoppos) {
1125 		uae_u32 spix_val1, spix_val2;
1126 		uae_u16 v;
1127 		int off;
1128 		spix_val1 = pixdata.apixels[spix++];
1129 		spix_val2 = pixdata.apixels[spix++];
1130 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1131 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1132 		v |= v >> 2;
1133 		PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr));
1134 		dpix++;
1135 		v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2;
1136 		v |= v >> 2;
1137 		PUTBPIX(shsprite (dpix, spix_val2, xcolors[v], spr));
1138 		dpix++;
1139 	}
1140 	return spix;
1141 }
linetoscr_32_shrink1_sh(int spix,int dpix,int stoppos,int spr)1142 static int NOINLINE linetoscr_32_shrink1_sh (int spix, int dpix, int stoppos, int spr)
1143 {
1144 	uae_u32 *buf = (uae_u32 *) xlinebuffer;
1145 
1146 	while (dpix < stoppos) {
1147 		uae_u32 spix_val1, spix_val2;
1148 		uae_u16 v;
1149 		int off;
1150 		spix_val1 = pixdata.apixels[spix++];
1151 		spix_val2 = pixdata.apixels[spix++];
1152 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1153 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1154 		v |= v >> 2;
1155 		PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr));
1156 		dpix++;
1157 	}
1158 	return spix;
1159 }
linetoscr_32_shrink1f_sh(int spix,int dpix,int stoppos,int spr)1160 static int NOINLINE linetoscr_32_shrink1f_sh (int spix, int dpix, int stoppos, int spr)
1161 {
1162 	uae_u32 *buf = (uae_u32 *) xlinebuffer;
1163 
1164 	while (dpix < stoppos) {
1165 		uae_u32 spix_val1, spix_val2, dpix_val1, dpix_val2;
1166 		uae_u16 v;
1167 		int off;
1168 		spix_val1 = pixdata.apixels[spix++];
1169 		spix_val2 = pixdata.apixels[spix++];
1170 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1171 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1172 		v |= v >> 2;
1173 		dpix_val1 = xcolors[v];
1174 		v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2;
1175 		v |= v >> 2;
1176 		dpix_val2 = xcolors[v];
1177 		PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel32 (dpix_val1, dpix_val2), spr));
1178 		dpix++;
1179 	}
1180 	return spix;
1181 }
linetoscr_16_shrink1_sh(int spix,int dpix,int stoppos,int spr)1182 static int NOINLINE linetoscr_16_shrink1_sh (int spix, int dpix, int stoppos, int spr)
1183 {
1184 	uae_u16 *buf = (uae_u16 *) xlinebuffer;
1185 
1186 	while (dpix < stoppos) {
1187 		uae_u16 spix_val1, spix_val2;
1188 		uae_u16 v;
1189 		int off;
1190 		spix_val1 = pixdata.apixels[spix++];
1191 		spix_val2 = pixdata.apixels[spix++];
1192 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1193 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1194 		v |= v >> 2;
1195 		PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr));
1196 		dpix++;
1197 	}
1198 	return spix;
1199 }
linetoscr_16_shrink1f_sh(int spix,int dpix,int stoppos,int spr)1200 static int NOINLINE linetoscr_16_shrink1f_sh (int spix, int dpix, int stoppos, int spr)
1201 {
1202 	uae_u16 *buf = (uae_u16 *) xlinebuffer;
1203 
1204 	while (dpix < stoppos) {
1205 		uae_u16 spix_val1, spix_val2, dpix_val1, dpix_val2;
1206 		uae_u16 v;
1207 		int off;
1208 		spix_val1 = pixdata.apixels[spix++];
1209 		spix_val2 = pixdata.apixels[spix++];
1210 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1211 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1212 		v |= v >> 2;
1213 		dpix_val1 = xcolors[v];
1214 		v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2;
1215 		v |= v >> 2;
1216 		dpix_val2 = xcolors[v];
1217 		PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel16 (dpix_val1, dpix_val2), spr));
1218 		dpix++;
1219 	}
1220 	return spix;
1221 }
1222 
linetoscr_32_shrink2_sh(int spix,int dpix,int stoppos,int spr)1223 static int NOINLINE linetoscr_32_shrink2_sh (int spix, int dpix, int stoppos, int spr)
1224 {
1225 	uae_u32 *buf = (uae_u32 *) xlinebuffer;
1226 
1227 	while (dpix < stoppos) {
1228 		uae_u32 spix_val1, spix_val2;
1229 		uae_u16 v;
1230 		int off;
1231 		spix_val1 = pixdata.apixels[spix++];
1232 		spix_val2 = pixdata.apixels[spix++];
1233 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1234 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1235 		v |= v >> 2;
1236 		PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr));
1237 		spix+=2;
1238 		dpix++;
1239 	}
1240 	return spix;
1241 }
linetoscr_32_shrink2f_sh(int spix,int dpix,int stoppos,int spr)1242 static int NOINLINE linetoscr_32_shrink2f_sh (int spix, int dpix, int stoppos, int spr)
1243 {
1244 	uae_u32 *buf = (uae_u32 *) xlinebuffer;
1245 
1246 	while (dpix < stoppos) {
1247 		uae_u32 spix_val1, spix_val2, dpix_val1, dpix_val2, dpix_val3, dpix_val4;
1248 		uae_u16 v;
1249 		int off;
1250 		spix_val1 = pixdata.apixels[spix++];
1251 		spix_val2 = pixdata.apixels[spix++];
1252 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1253 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1254 		v |= v >> 2;
1255 		dpix_val1 = xcolors[v];
1256 		v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2;
1257 		v |= v >> 2;
1258 		dpix_val2 = xcolors[v];
1259 		dpix_val3 = merge_2pixel32 (dpix_val1, dpix_val2);
1260 		spix_val1 = pixdata.apixels[spix++];
1261 		spix_val2 = pixdata.apixels[spix++];
1262 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1263 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1264 		v |= v >> 2;
1265 		dpix_val1 = xcolors[v];
1266 		v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2;
1267 		v |= v >> 2;
1268 		dpix_val2 = xcolors[v];
1269 		dpix_val4 = merge_2pixel32 (dpix_val1, dpix_val2);
1270 		PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel32 (dpix_val3, dpix_val4), spr));
1271 		dpix++;
1272 	}
1273 	return spix;
1274 }
linetoscr_16_shrink2_sh(int spix,int dpix,int stoppos,int spr)1275 static int NOINLINE linetoscr_16_shrink2_sh (int spix, int dpix, int stoppos, int spr)
1276 {
1277 	uae_u16 *buf = (uae_u16 *) xlinebuffer;
1278 
1279 	while (dpix < stoppos) {
1280 		uae_u16 spix_val1, spix_val2;
1281 		uae_u16 v;
1282 		int off;
1283 		spix_val1 = pixdata.apixels[spix++];
1284 		spix_val2 = pixdata.apixels[spix++];
1285 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1286 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1287 		v |= v >> 2;
1288 		PUTBPIX(shsprite (dpix, spix_val1, xcolors[v], spr));
1289 		spix+=2;
1290 		dpix++;
1291 	}
1292 	return spix;
1293 }
linetoscr_16_shrink2f_sh(int spix,int dpix,int stoppos,int spr)1294 static int NOINLINE linetoscr_16_shrink2f_sh (int spix, int dpix, int stoppos, int spr)
1295 {
1296 	uae_u16 *buf = (uae_u16 *) xlinebuffer;
1297 
1298 	while (dpix < stoppos) {
1299 		uae_u16 spix_val1, spix_val2, dpix_val1, dpix_val2, dpix_val3, dpix_val4;
1300 		uae_u16 v;
1301 		int off;
1302 		spix_val1 = pixdata.apixels[spix++];
1303 		spix_val2 = pixdata.apixels[spix++];
1304 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1305 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1306 		v |= v >> 2;
1307 		dpix_val1 = xcolors[v];
1308 		v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2;
1309 		v |= v >> 2;
1310 		dpix_val2 = xcolors[v];
1311 		dpix_val3 = merge_2pixel32 (dpix_val1, dpix_val2);
1312 		spix_val1 = pixdata.apixels[spix++];
1313 		spix_val2 = pixdata.apixels[spix++];
1314 		off = ((spix_val2 & 3) * 4) + (spix_val1 & 3) + ((spix_val1 | spix_val2) & 16);
1315 		v = (colors_for_drawing.color_regs_ecs[off] & 0xccc) << 0;
1316 		v |= v >> 2;
1317 		dpix_val1 = xcolors[v];
1318 		v = (colors_for_drawing.color_regs_ecs[off] & 0x333) << 2;
1319 		v |= v >> 2;
1320 		dpix_val2 = xcolors[v];
1321 		dpix_val4 = merge_2pixel32 (dpix_val1, dpix_val2);
1322 		PUTBPIX(shsprite (dpix, spix_val1, merge_2pixel16 (dpix_val3, dpix_val4), spr));
1323 		dpix++;
1324 	}
1325 	return spix;
1326 }
1327 #endif
1328 
pfield_do_linetoscr(int start,int stop,bool blank)1329 static void pfield_do_linetoscr (int start, int stop, bool blank)
1330 {
1331 	xlinecheck(start, stop);
1332 #ifdef AGA
1333 	if (issprites && (currprefs.chipset_mask & CSMASK_AGA)) {
1334 		if (res_shift == 0) {
1335 			switch (gfxvidinfo.pixbytes) {
1336 			case 2: src_pixel = linetoscr_16_aga_spr (LTPARMS); break;
1337 			case 4: src_pixel = linetoscr_32_aga_spr (LTPARMS); break;
1338 			}
1339 		} else if (res_shift == 2) {
1340 			switch (gfxvidinfo.pixbytes) {
1341 			case 2: src_pixel = linetoscr_16_stretch2_aga_spr (LTPARMS); break;
1342 			case 4: src_pixel = linetoscr_32_stretch2_aga_spr (LTPARMS); break;
1343 			}
1344 		} else if (res_shift == 1) {
1345 			switch (gfxvidinfo.pixbytes) {
1346 			case 2: src_pixel = linetoscr_16_stretch1_aga_spr (LTPARMS); break;
1347 			case 4: src_pixel = linetoscr_32_stretch1_aga_spr (LTPARMS); break;
1348 			}
1349 		} else if (res_shift == -1) {
1350 			if (currprefs.gfx_lores_mode) {
1351 				switch (gfxvidinfo.pixbytes) {
1352 				case 2: src_pixel = linetoscr_16_shrink1f_aga_spr (LTPARMS); break;
1353 				case 4: src_pixel = linetoscr_32_shrink1f_aga_spr (LTPARMS); break;
1354 				}
1355 			} else {
1356 				switch (gfxvidinfo.pixbytes) {
1357 				case 2: src_pixel = linetoscr_16_shrink1_aga_spr (LTPARMS); break;
1358 				case 4: src_pixel = linetoscr_32_shrink1_aga_spr (LTPARMS); break;
1359 				}
1360 			}
1361 		} else if (res_shift == -2) {
1362 			if (currprefs.gfx_lores_mode) {
1363 				switch (gfxvidinfo.pixbytes) {
1364 				case 2: src_pixel = linetoscr_16_shrink2f_aga_spr (LTPARMS); break;
1365 				case 4: src_pixel = linetoscr_32_shrink2f_aga_spr (LTPARMS); break;
1366 				}
1367 			} else {
1368 				switch (gfxvidinfo.pixbytes) {
1369 				case 2: src_pixel = linetoscr_16_shrink2_aga_spr (LTPARMS); break;
1370 				case 4: src_pixel = linetoscr_32_shrink2_aga_spr (LTPARMS); break;
1371 				}
1372 			}
1373 		}
1374 	} else
1375 		if (currprefs.chipset_mask & CSMASK_AGA) {
1376 			if (res_shift == 0) {
1377 				switch (gfxvidinfo.pixbytes) {
1378 				case 2: src_pixel = linetoscr_16_aga (LTPARMS); break;
1379 				case 4: src_pixel = linetoscr_32_aga (LTPARMS); break;
1380 				}
1381 			} else if (res_shift == 2) {
1382 				switch (gfxvidinfo.pixbytes) {
1383 				case 2: src_pixel = linetoscr_16_stretch2_aga (LTPARMS); break;
1384 				case 4: src_pixel = linetoscr_32_stretch2_aga (LTPARMS); break;
1385 				}
1386 			} else if (res_shift == 1) {
1387 				switch (gfxvidinfo.pixbytes) {
1388 				case 2: src_pixel = linetoscr_16_stretch1_aga (LTPARMS); break;
1389 				case 4: src_pixel = linetoscr_32_stretch1_aga (LTPARMS); break;
1390 				}
1391 			} else if (res_shift == -1) {
1392 				if (currprefs.gfx_lores_mode) {
1393 					switch (gfxvidinfo.pixbytes) {
1394 					case 2: src_pixel = linetoscr_16_shrink1f_aga (LTPARMS); break;
1395 					case 4: src_pixel = linetoscr_32_shrink1f_aga (LTPARMS); break;
1396 					}
1397 				} else {
1398 					switch (gfxvidinfo.pixbytes) {
1399 					case 2: src_pixel = linetoscr_16_shrink1_aga (LTPARMS); break;
1400 					case 4: src_pixel = linetoscr_32_shrink1_aga (LTPARMS); break;
1401 					}
1402 				}
1403 			} else if (res_shift == -2) {
1404 				if (currprefs.gfx_lores_mode) {
1405 					switch (gfxvidinfo.pixbytes) {
1406 					case 2: src_pixel = linetoscr_16_shrink2f_aga (LTPARMS); break;
1407 					case 4: src_pixel = linetoscr_32_shrink2f_aga (LTPARMS); break;
1408 					}
1409 				} else {
1410 					switch (gfxvidinfo.pixbytes) {
1411 					case 2: src_pixel = linetoscr_16_shrink2_aga (LTPARMS); break;
1412 					case 4: src_pixel = linetoscr_32_shrink2_aga (LTPARMS); break;
1413 					}
1414 				}
1415 			}
1416 		} else
1417 #endif
1418 #ifdef ECS_DENISE
1419 			if (ecsshres) {
1420 				if (res_shift == 0) {
1421 					switch (gfxvidinfo.pixbytes) {
1422 					case 2: src_pixel = linetoscr_16_sh (LTPARMS, issprites); break;
1423 					case 4: src_pixel = linetoscr_32_sh (LTPARMS, issprites); break;
1424 					}
1425 				} else if (res_shift == -1) {
1426 					if (currprefs.gfx_lores_mode) {
1427 						switch (gfxvidinfo.pixbytes) {
1428 						case 2: src_pixel = linetoscr_16_shrink1f_sh (LTPARMS, issprites); break;
1429 						case 4: src_pixel = linetoscr_32_shrink1f_sh (LTPARMS, issprites); break;
1430 						}
1431 					} else {
1432 						switch (gfxvidinfo.pixbytes) {
1433 						case 2: src_pixel = linetoscr_16_shrink1_sh (LTPARMS, issprites); break;
1434 						case 4: src_pixel = linetoscr_32_shrink1_sh (LTPARMS, issprites); break;
1435 						}
1436 					}
1437 				} else if (res_shift == -2) {
1438 					if (currprefs.gfx_lores_mode) {
1439 						switch (gfxvidinfo.pixbytes) {
1440 						case 2: src_pixel = linetoscr_16_shrink2f_sh (LTPARMS, issprites); break;
1441 						case 4: src_pixel = linetoscr_32_shrink2f_sh (LTPARMS, issprites); break;
1442 						}
1443 					} else {
1444 						switch (gfxvidinfo.pixbytes) {
1445 						case 2: src_pixel = linetoscr_16_shrink2_sh (LTPARMS, issprites); break;
1446 						case 4: src_pixel = linetoscr_32_shrink2_sh (LTPARMS, issprites); break;
1447 						}
1448 					}
1449 				}
1450 			} else
1451 #endif
1452 				if (issprites) {
1453 					if (res_shift == 0) {
1454 						switch (gfxvidinfo.pixbytes) {
1455 						case 2: src_pixel = linetoscr_16_spr (LTPARMS); break;
1456 						case 4: src_pixel = linetoscr_32_spr (LTPARMS); break;
1457 						}
1458 					} else if (res_shift == 2) {
1459 						switch (gfxvidinfo.pixbytes) {
1460 						case 2: src_pixel = linetoscr_16_stretch2_spr (LTPARMS); break;
1461 						case 4: src_pixel = linetoscr_32_stretch2_spr (LTPARMS); break;
1462 						}
1463 					} else if (res_shift == 1) {
1464 						switch (gfxvidinfo.pixbytes) {
1465 						case 2: src_pixel = linetoscr_16_stretch1_spr (LTPARMS); break;
1466 						case 4: src_pixel = linetoscr_32_stretch1_spr (LTPARMS); break;
1467 						}
1468 					} else if (res_shift == -1) {
1469 						if (currprefs.gfx_lores_mode) {
1470 							switch (gfxvidinfo.pixbytes) {
1471 							case 2: src_pixel = linetoscr_16_shrink1f_spr (LTPARMS); break;
1472 							case 4: src_pixel = linetoscr_32_shrink1f_spr (LTPARMS); break;
1473 							}
1474 						} else {
1475 							switch (gfxvidinfo.pixbytes) {
1476 							case 2: src_pixel = linetoscr_16_shrink1_spr (LTPARMS); break;
1477 							case 4: src_pixel = linetoscr_32_shrink1_spr (LTPARMS); break;
1478 							}
1479 						}
1480 					}
1481 				} else {
1482 					if (res_shift == 0) {
1483 						switch (gfxvidinfo.pixbytes) {
1484 						case 2: src_pixel = linetoscr_16 (LTPARMS); break;
1485 						case 4: src_pixel = linetoscr_32 (LTPARMS); break;
1486 						}
1487 					} else if (res_shift == 2) {
1488 						switch (gfxvidinfo.pixbytes) {
1489 						case 2: src_pixel = linetoscr_16_stretch2 (LTPARMS); break;
1490 						case 4: src_pixel = linetoscr_32_stretch2 (LTPARMS); break;
1491 						}
1492 					} else if (res_shift == 1) {
1493 						switch (gfxvidinfo.pixbytes) {
1494 						case 2: src_pixel = linetoscr_16_stretch1 (LTPARMS); break;
1495 						case 4: src_pixel = linetoscr_32_stretch1 (LTPARMS); break;
1496 						}
1497 					} else if (res_shift == -1) {
1498 						if (currprefs.gfx_lores_mode) {
1499 							switch (gfxvidinfo.pixbytes) {
1500 							case 2: src_pixel = linetoscr_16_shrink1f (LTPARMS); break;
1501 							case 4: src_pixel = linetoscr_32_shrink1f (LTPARMS); break;
1502 							}
1503 						} else {
1504 							switch (gfxvidinfo.pixbytes) {
1505 							case 2: src_pixel = linetoscr_16_shrink1 (LTPARMS); break;
1506 							case 4: src_pixel = linetoscr_32_shrink1 (LTPARMS); break;
1507 							}
1508 						}
1509 					}
1510 				}
1511 
1512 }
1513 
1514 // left or right border sprite
pfield_do_linetoscr_border(int start,int stop,bool blank)1515 static void pfield_do_linetoscr_border (int start, int stop, bool blank)
1516 {
1517 	bool old = issprites;
1518 	issprites = colors_for_drawing.bordersprite != 0;
1519 	pfield_do_linetoscr (start, stop, blank);
1520 	issprites = old;
1521 }
1522 
dummy_worker(int start,int stop,bool blank)1523 static void dummy_worker (int start, int stop, bool blank)
1524 {
1525 }
1526 
1527 static int ham_decode_pixel;
1528 static unsigned int ham_lastcolor;
1529 
1530 /* Decode HAM in the invisible portion of the display (left of VISIBLE_LEFT_BORDER),
1531  * but don't draw anything in.  This is done to prepare HAM_LASTCOLOR for later,
1532  * when decode_ham runs.
1533  *
1534  */
init_ham_decoding(void)1535 static void init_ham_decoding (void)
1536 {
1537 	int unpainted_amiga = unpainted;
1538 
1539 	ham_decode_pixel = ham_src_pixel;
1540 	ham_lastcolor = color_reg_get (&colors_for_drawing, 0);
1541 
1542 	if (!bplham) {
1543 		if (unpainted_amiga > 0) {
1544 			int pv = pixdata.apixels[ham_decode_pixel + unpainted_amiga - 1];
1545 #ifdef AGA
1546 			if (currprefs.chipset_mask & CSMASK_AGA)
1547 				ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor];
1548 			else
1549 #endif
1550 				ham_lastcolor = colors_for_drawing.color_regs_ecs[pv];
1551 		}
1552 #ifdef AGA
1553 	} else if (currprefs.chipset_mask & CSMASK_AGA) {
1554 		if (bplplanecnt >= 7) { /* AGA mode HAM8 */
1555 			while (unpainted_amiga-- > 0) {
1556 				int pv = pixdata.apixels[ham_decode_pixel++] ^ bplxor;
1557 				switch (pv & 0x3)
1558 				{
1559 				case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
1560 				case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
1561 				case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
1562 				case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
1563 				}
1564 			}
1565 		} else { /* AGA mode HAM6 */
1566 			while (unpainted_amiga-- > 0) {
1567 				int pv = pixdata.apixels[ham_decode_pixel++] ^ bplxor;
1568 				switch (pv & 0x30)
1569 				{
1570 				case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
1571 				case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
1572 				case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
1573 				case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
1574 				}
1575 			}
1576 		}
1577 #endif
1578 	} else {
1579 		/* OCS/ECS mode HAM6 */
1580 		while (unpainted_amiga-- > 0) {
1581 			int pv = pixdata.apixels[ham_decode_pixel++];
1582 			switch (pv & 0x30)
1583 			{
1584 			case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
1585 			case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
1586 			case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
1587 			case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
1588 			}
1589 		}
1590 	}
1591 }
1592 
decode_ham(int pix,int stoppos,bool blank)1593 static void decode_ham (int pix, int stoppos, bool blank)
1594 {
1595 	int todraw_amiga = res_shift_from_window (stoppos - pix);
1596 
1597 	if (!bplham) {
1598 		while (todraw_amiga-- > 0) {
1599 			int pv = pixdata.apixels[ham_decode_pixel];
1600 #ifdef AGA
1601 			if (currprefs.chipset_mask & CSMASK_AGA)
1602 				ham_lastcolor = colors_for_drawing.color_regs_aga[pv ^ bplxor];
1603 			else
1604 #endif
1605 				ham_lastcolor = colors_for_drawing.color_regs_ecs[pv];
1606 
1607 			ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
1608 		}
1609 #ifdef AGA
1610 	} else if (currprefs.chipset_mask & CSMASK_AGA) {
1611 		if (bplplanecnt >= 7) { /* AGA mode HAM8 */
1612 			while (todraw_amiga-- > 0) {
1613 				int pv = pixdata.apixels[ham_decode_pixel] ^ bplxor;
1614 				switch (pv & 0x3)
1615 				{
1616 				case 0x0: ham_lastcolor = colors_for_drawing.color_regs_aga[pv >> 2]; break;
1617 				case 0x1: ham_lastcolor &= 0xFFFF03; ham_lastcolor |= (pv & 0xFC); break;
1618 				case 0x2: ham_lastcolor &= 0x03FFFF; ham_lastcolor |= (pv & 0xFC) << 16; break;
1619 				case 0x3: ham_lastcolor &= 0xFF03FF; ham_lastcolor |= (pv & 0xFC) << 8; break;
1620 				}
1621 				ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
1622 			}
1623 		} else { /* AGA mode HAM6 */
1624 			while (todraw_amiga-- > 0) {
1625 				int pv = pixdata.apixels[ham_decode_pixel] ^ bplxor;
1626 				switch (pv & 0x30)
1627 				{
1628 				case 0x00: ham_lastcolor = colors_for_drawing.color_regs_aga[pv]; break;
1629 				case 0x10: ham_lastcolor &= 0xFFFF00; ham_lastcolor |= (pv & 0xF) << 4; break;
1630 				case 0x20: ham_lastcolor &= 0x00FFFF; ham_lastcolor |= (pv & 0xF) << 20; break;
1631 				case 0x30: ham_lastcolor &= 0xFF00FF; ham_lastcolor |= (pv & 0xF) << 12; break;
1632 				}
1633 				ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
1634 			}
1635 		}
1636 #endif
1637 	} else {
1638 		/* OCS/ECS mode HAM6 */
1639 		while (todraw_amiga-- > 0) {
1640 			int pv = pixdata.apixels[ham_decode_pixel];
1641 			switch (pv & 0x30)
1642 			{
1643 			case 0x00: ham_lastcolor = colors_for_drawing.color_regs_ecs[pv]; break;
1644 			case 0x10: ham_lastcolor &= 0xFF0; ham_lastcolor |= (pv & 0xF); break;
1645 			case 0x20: ham_lastcolor &= 0x0FF; ham_lastcolor |= (pv & 0xF) << 8; break;
1646 			case 0x30: ham_lastcolor &= 0xF0F; ham_lastcolor |= (pv & 0xF) << 4; break;
1647 			}
1648 			ham_linebuf[ham_decode_pixel++] = ham_lastcolor;
1649 		}
1650 	}
1651 }
1652 
gen_pfield_tables(void)1653 static void gen_pfield_tables (void)
1654 {
1655 	int i;
1656 
1657 	for (i = 0; i < 256; i++) {
1658 		int plane1 = ((i >> 0) & 1) | ((i >> 1) & 2) | ((i >> 2) & 4) | ((i >> 3) & 8);
1659 		int plane2 = ((i >> 1) & 1) | ((i >> 2) & 2) | ((i >> 3) & 4) | ((i >> 4) & 8);
1660 
1661 		dblpf_2nd1[i] = plane1 == 0 && plane2 != 0;
1662 		dblpf_2nd2[i] = plane2 != 0;
1663 
1664 #ifdef AGA
1665 		dblpf_ind1_aga[i] = plane1 == 0 ? plane2 : plane1;
1666 		dblpf_ind2_aga[i] = plane2 == 0 ? plane1 : plane2;
1667 #endif
1668 
1669 		dblpf_ms1[i] = plane1 == 0 ? (plane2 == 0 ? 16 : 8) : 0;
1670 		dblpf_ms2[i] = plane2 == 0 ? (plane1 == 0 ? 16 : 0) : 8;
1671 		dblpf_ms[i] = i == 0 ? 16 : 8;
1672 
1673 		if (plane2 > 0)
1674 			plane2 += 8;
1675 		dblpf_ind1[i] = i >= 128 ? i & 0x7F : (plane1 == 0 ? plane2 : plane1);
1676 		dblpf_ind2[i] = i >= 128 ? i & 0x7F : (plane2 == 0 ? plane1 : plane2);
1677 
1678 		sprite_offs[i] = (i & 15) ? 0 : 2;
1679 
1680 		clxtab[i] = ((((i & 3) && (i & 12)) << 9)
1681 			| (((i & 3) && (i & 48)) << 10)
1682 			| (((i & 3) && (i & 192)) << 11)
1683 			| (((i & 12) && (i & 48)) << 12)
1684 			| (((i & 12) && (i & 192)) << 13)
1685 			| (((i & 48) && (i & 192)) << 14));
1686 
1687 	}
1688 
1689 	memset (all_ones, 0xff, MAX_PIXELS_PER_LINE);
1690 
1691 }
1692 
1693 /* When looking at this function and the ones that inline it, bear in mind
1694    what an optimizing compiler will do with this code.  All callers of this
1695    function only pass in constant arguments (except for E).  This means
1696    that many of the if statements will go away completely after inlining.  */
draw_sprites_1(struct sprite_entry * e,int dualpf,int has_attach)1697 STATIC_INLINE void draw_sprites_1 (struct sprite_entry *e, int dualpf, int has_attach)
1698 {
1699 	uae_u16 *buf = spixels + e->first_pixel;
1700 	uae_u8 *stbuf = spixstate.bytes + e->first_pixel;
1701 	int spr_pos, pos;
1702 
1703 	buf -= e->pos;
1704 	stbuf -= e->pos;
1705 
1706 	spr_pos = e->pos + ((DIW_DDF_OFFSET - DISPLAY_LEFT_SHIFT) << sprite_buffer_res);
1707 
1708 	if (spr_pos < sprite_first_x)
1709 		sprite_first_x = spr_pos;
1710 
1711 	for (pos = e->pos; pos < e->max; pos++, spr_pos++) {
1712 		if (spr_pos >= 0 && spr_pos < MAX_PIXELS_PER_LINE) {
1713 			spritepixels[spr_pos].data = buf[pos];
1714 			spritepixels[spr_pos].stdata = stbuf[pos];
1715 			spritepixels[spr_pos].attach = has_attach;
1716 		}
1717 	}
1718 
1719 	if (spr_pos > sprite_last_x)
1720 		sprite_last_x = spr_pos;
1721 }
1722 
1723 /* See comments above.  Do not touch if you don't know what's going on.
1724  * (We do _not_ want the following to be inlined themselves).  */
1725 /* lores bitplane, lores sprites */
draw_sprites_normal_sp_nat(struct sprite_entry * e)1726 static void NOINLINE draw_sprites_normal_sp_nat (struct sprite_entry *e) { draw_sprites_1 (e, 0, 0); }
draw_sprites_normal_dp_nat(struct sprite_entry * e)1727 static void NOINLINE draw_sprites_normal_dp_nat (struct sprite_entry *e) { draw_sprites_1 (e, 1, 0); }
draw_sprites_normal_sp_at(struct sprite_entry * e)1728 static void NOINLINE draw_sprites_normal_sp_at (struct sprite_entry *e) { draw_sprites_1 (e, 0, 1); }
draw_sprites_normal_dp_at(struct sprite_entry * e)1729 static void NOINLINE draw_sprites_normal_dp_at (struct sprite_entry *e) { draw_sprites_1 (e, 1, 1); }
1730 
1731 #ifdef AGA
1732 /* not very optimized */
draw_sprites_aga(struct sprite_entry * e,int aga)1733 STATIC_INLINE void draw_sprites_aga (struct sprite_entry *e, int aga)
1734 {
1735 	draw_sprites_1 (e, bpldualpf, e->has_attached);
1736 }
1737 #endif
1738 
draw_sprites_ecs(struct sprite_entry * e)1739 STATIC_INLINE void draw_sprites_ecs (struct sprite_entry *e)
1740 {
1741 	if (e->has_attached) {
1742 		if (bpldualpf)
1743 			draw_sprites_normal_dp_at (e);
1744 		else
1745 			draw_sprites_normal_sp_at (e);
1746 	} else {
1747 		if (bpldualpf)
1748 			draw_sprites_normal_dp_nat (e);
1749 		else
1750 			draw_sprites_normal_sp_nat (e);
1751 	}
1752 }
1753 
1754 #ifdef AGA
1755 /* clear possible bitplane data outside DIW area */
clear_bitplane_border_aga(void)1756 static void clear_bitplane_border_aga (void)
1757 {
1758 	int len, shift = res_shift;
1759 	uae_u8 v = 0;
1760 
1761 	if (shift < 0) {
1762 		shift = -shift;
1763 		len = (real_playfield_start - playfield_start) << shift;
1764 		memset (pixdata.apixels + pixels_offset + (playfield_start << shift), v, len);
1765 		len = (playfield_end - real_playfield_end) << shift;
1766 		memset (pixdata.apixels + pixels_offset + (real_playfield_end << shift), v, len);
1767 	} else {
1768 		len = (real_playfield_start - playfield_start) >> shift;
1769 		memset (pixdata.apixels + pixels_offset + (playfield_start >> shift), v, len);
1770 		len = (playfield_end - real_playfield_end) >> shift;
1771 		memset (pixdata.apixels + pixels_offset + (real_playfield_end >> shift), v, len);
1772 	}
1773 }
1774 #endif
1775 
1776 /* emulate OCS/ECS only undocumented "SWIV" hardware feature */
weird_bitplane_fix(void)1777 static void weird_bitplane_fix (void)
1778 {
1779 	int i;
1780 	int sh = lores_shift;
1781 	uae_u8 *p = pixdata.apixels + pixels_offset;
1782 
1783 	for (i = playfield_start >> sh; i < playfield_end >> sh; i++) {
1784 		if (p[i] > 16)
1785 			p[i] = 16;
1786 	}
1787 }
1788 
1789 #define MERGE(a,b,mask,shift) do {\
1790 	uae_u32 tmp = mask & (a ^ (b >> shift)); \
1791 	a ^= tmp; \
1792 	b ^= (tmp << shift); \
1793 } while (0)
1794 
1795 #define GETLONG(P) (*(uae_u32 *)P)
1796 #if defined(DEBUG) && 0
1797 #define DATA_POINTER(n) ((debug_bpl_mask & (1 << n)) ? (line_data[lineno] + (n) * MAX_WORDS_PER_LINE * 2) : (debug_bpl_mask_one ? all_ones : all_zeros))
1798 #else
1799 #define DATA_POINTER(n) (line_data[lineno] + (n)*MAX_WORDS_PER_LINE*2)
1800 #endif
1801 
1802 #define UNROLL_PFIELD
1803 #ifndef UNROLL_PFIELD
1804 /* We use the compiler's inlining ability to ensure that PLANES is in effect a compile time
1805    constant.  That will cause some unnecessary code to be optimized away.
1806    Don't touch this if you don't know what you are doing.  */
pfield_doline_1(uae_u32 * pixels,int wordcount,int planes)1807 STATIC_INLINE void pfield_doline_1 (uae_u32 *pixels, int wordcount, int planes)
1808 {
1809 	while (wordcount-- > 0) {
1810 		uae_u32 b0, b1, b2, b3, b4, b5, b6, b7;
1811 
1812 		b0 = 0, b1 = 0, b2 = 0, b3 = 0, b4 = 0, b5 = 0, b6 = 0, b7 = 0;
1813 		switch (planes) {
1814 #ifdef AGA
1815 		case 8: b0 = GETLONG (real_bplpt[7]); real_bplpt[7] += 4;
1816 		case 7: b1 = GETLONG (real_bplpt[6]); real_bplpt[6] += 4;
1817 #endif
1818 		case 6: b2 = GETLONG (real_bplpt[5]); real_bplpt[5] += 4;
1819 		case 5: b3 = GETLONG (real_bplpt[4]); real_bplpt[4] += 4;
1820 		case 4: b4 = GETLONG (real_bplpt[3]); real_bplpt[3] += 4;
1821 		case 3: b5 = GETLONG (real_bplpt[2]); real_bplpt[2] += 4;
1822 		case 2: b6 = GETLONG (real_bplpt[1]); real_bplpt[1] += 4;
1823 		case 1: b7 = GETLONG (real_bplpt[0]); real_bplpt[0] += 4;
1824 		}
1825 
1826 		MERGE (b0, b1, 0x55555555, 1);
1827 		MERGE (b2, b3, 0x55555555, 1);
1828 		MERGE (b4, b5, 0x55555555, 1);
1829 		MERGE (b6, b7, 0x55555555, 1);
1830 
1831 		MERGE (b0, b2, 0x33333333, 2);
1832 		MERGE (b1, b3, 0x33333333, 2);
1833 		MERGE (b4, b6, 0x33333333, 2);
1834 		MERGE (b5, b7, 0x33333333, 2);
1835 
1836 		MERGE (b0, b4, 0x0f0f0f0f, 4);
1837 		MERGE (b1, b5, 0x0f0f0f0f, 4);
1838 		MERGE (b2, b6, 0x0f0f0f0f, 4);
1839 		MERGE (b3, b7, 0x0f0f0f0f, 4);
1840 
1841 		MERGE (b0, b1, 0x00ff00ff, 8);
1842 		MERGE (b2, b3, 0x00ff00ff, 8);
1843 		MERGE (b4, b5, 0x00ff00ff, 8);
1844 		MERGE (b6, b7, 0x00ff00ff, 8);
1845 
1846 		MERGE (b0, b2, 0x0000ffff, 16);
1847 		do_put_mem_long (pixels, b0);
1848 		do_put_mem_long (pixels + 4, b2);
1849 		MERGE (b1, b3, 0x0000ffff, 16);
1850 		do_put_mem_long (pixels + 2, b1);
1851 		do_put_mem_long (pixels + 6, b3);
1852 		MERGE (b4, b6, 0x0000ffff, 16);
1853 		do_put_mem_long (pixels + 1, b4);
1854 		do_put_mem_long (pixels + 5, b6);
1855 		MERGE (b5, b7, 0x0000ffff, 16);
1856 		do_put_mem_long (pixels + 3, b5);
1857 		do_put_mem_long (pixels + 7, b7);
1858 		pixels += 8;
1859 	}
1860 }
1861 
1862 /* See above for comments on inlining.  These functions should _not_
1863    be inlined themselves.  */
pfield_doline_n1(uae_u32 * data,int count)1864 static void NOINLINE pfield_doline_n1 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 1); }
pfield_doline_n2(uae_u32 * data,int count)1865 static void NOINLINE pfield_doline_n2 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 2); }
pfield_doline_n3(uae_u32 * data,int count)1866 static void NOINLINE pfield_doline_n3 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 3); }
pfield_doline_n4(uae_u32 * data,int count)1867 static void NOINLINE pfield_doline_n4 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 4); }
pfield_doline_n5(uae_u32 * data,int count)1868 static void NOINLINE pfield_doline_n5 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 5); }
pfield_doline_n6(uae_u32 * data,int count)1869 static void NOINLINE pfield_doline_n6 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 6); }
1870 #ifdef AGA
pfield_doline_n7(uae_u32 * data,int count)1871 static void NOINLINE pfield_doline_n7 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 7); }
pfield_doline_n8(uae_u32 * data,int count)1872 static void NOINLINE pfield_doline_n8 (uae_u32 *data, int count) { pfield_doline_1 (data, count, 8); }
1873 #endif /*AGA*/
1874 
pfield_doline(int lineno)1875 static void pfield_doline (int lineno)
1876 {
1877 	int wordcount = dp_for_drawing->plflinelen;
1878 	uae_u32 *data = pixdata.apixels_l + MAX_PIXELS_PER_LINE / 4;
1879 
1880 #ifdef SMART_UPDATE
1881 	real_bplpt[0] = DATA_POINTER (0);
1882 	real_bplpt[1] = DATA_POINTER (1);
1883 	real_bplpt[2] = DATA_POINTER (2);
1884 	real_bplpt[3] = DATA_POINTER (3);
1885 	real_bplpt[4] = DATA_POINTER (4);
1886 	real_bplpt[5] = DATA_POINTER (5);
1887 #ifdef AGA
1888 	real_bplpt[6] = DATA_POINTER (6);
1889 	real_bplpt[7] = DATA_POINTER (7);
1890 #endif
1891 #endif
1892 
1893 	switch (bplplanecnt) {
1894 	default: break;
1895 	case 0: memset (data, 0, wordcount * 32); break;
1896 	case 1: pfield_doline_n1 (data, wordcount); break;
1897 	case 2: pfield_doline_n2 (data, wordcount); break;
1898 	case 3: pfield_doline_n3 (data, wordcount); break;
1899 	case 4: pfield_doline_n4 (data, wordcount); break;
1900 	case 5: pfield_doline_n5 (data, wordcount); break;
1901 	case 6: pfield_doline_n6 (data, wordcount); break;
1902 #ifdef AGA
1903 	case 7: pfield_doline_n7 (data, wordcount); break;
1904 	case 8: pfield_doline_n8 (data, wordcount); break;
1905 #endif
1906 	}
1907 }
1908 #else /*UNROLL_PFIELD*/
1909 
1910 #define MERGE_0(a,b,mask,shift) {\
1911     register uae_u32 tmp = mask & (b>>shift); \
1912     a = tmp; \
1913     b ^= (tmp << shift); \
1914   }
1915 
1916 #define DO_SWLONG(A,V) {\
1917     register uae_u8 *b = (uae_u8 *)(A); \
1918     register uae_u32 v = (V); \
1919     *b++ = v >> 24; \
1920     *b++ = v >> 16; \
1921     *b++ = v >> 8; \
1922     *b = v; \
1923   }
1924 
1925 //#define LINEDATA_DECL , uae_u8 line_data[(MAXVPOS + 2) * 2][MAX_PLANES * MAX_WORDS_PER_LINE * 2]
1926 //#define LINEDATA_ARG0 ,line_data
1927 #define LINEDATA_DECL
1928 #define LINEDATA_ARG0
1929 
1930 # ifdef USE_ARMNEON
1931 void ARM_doline_n1(uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL);
1932 void NEON_doline_n2(uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL);
1933 void NEON_doline_n3(uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL);
1934 void NEON_doline_n4(uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL);
1935 void NEON_doline_n6(uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL);
1936 void NEON_doline_n8(uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL);
1937 
1938 #include "pfield_doline_arm_neon.c"
1939 # endif /*USE_ARMNEON*/
1940 
pfield_doline_n1(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)1941 static void pfield_doline_n1 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
1942 {
1943   uae_u8 *real_bplpt0;
1944 
1945    real_bplpt0 = DATA_POINTER (0);
1946 
1947    while (wordcount-- > 0) {
1948       uae_u32 b0,b1,b2,b3,b4,b5,b6,b7;
1949       b7 = GETLONG ((uae_u32 *)real_bplpt0); real_bplpt0 += 4;
1950 
1951       MERGE_0(b6, b7, 0x55555555, 1);
1952 
1953       MERGE_0(b4, b6, 0x33333333, 2);
1954       MERGE_0(b5, b7, 0x33333333, 2);
1955 
1956       MERGE_0(b0, b4, 0x0f0f0f0f, 4);
1957       MERGE_0(b1, b5, 0x0f0f0f0f, 4);
1958       MERGE_0(b2, b6, 0x0f0f0f0f, 4);
1959       MERGE_0(b3, b7, 0x0f0f0f0f, 4);
1960 
1961       MERGE (b0, b1, 0x00ff00ff, 8);
1962       MERGE (b2, b3, 0x00ff00ff, 8);
1963       MERGE (b4, b5, 0x00ff00ff, 8);
1964       MERGE (b6, b7, 0x00ff00ff, 8);
1965 
1966       MERGE (b0, b2, 0x0000ffff, 16);
1967       DO_SWLONG(pixels, b0);
1968       DO_SWLONG(pixels + 4, b2);
1969       MERGE (b1, b3, 0x0000ffff, 16);
1970       DO_SWLONG(pixels + 2, b1);
1971       DO_SWLONG(pixels + 6, b3);
1972       MERGE (b4, b6, 0x0000ffff, 16);
1973       DO_SWLONG(pixels + 1, b4);
1974       DO_SWLONG(pixels + 5, b6);
1975       MERGE (b5, b7, 0x0000ffff, 16);
1976       DO_SWLONG(pixels + 3, b5);
1977       DO_SWLONG(pixels + 7, b7);
1978       pixels += 8;
1979    }
1980 }
1981 
pfield_doline_n2(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)1982 static void pfield_doline_n2 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
1983 {
1984   uae_u8 *real_bplpt[2];
1985 
1986    real_bplpt[0] = DATA_POINTER (0);
1987    real_bplpt[1] = DATA_POINTER (1);
1988 
1989    while (wordcount-- > 0) {
1990       uae_u32 b0,b1,b2,b3,b4,b5,b6,b7;
1991       b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
1992       b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
1993 
1994       MERGE (b6, b7, 0x55555555, 1);
1995 
1996       MERGE_0(b4, b6, 0x33333333, 2);
1997       MERGE_0(b5, b7, 0x33333333, 2);
1998 
1999       MERGE_0(b0, b4, 0x0f0f0f0f, 4);
2000       MERGE_0(b1, b5, 0x0f0f0f0f, 4);
2001       MERGE_0(b2, b6, 0x0f0f0f0f, 4);
2002       MERGE_0(b3, b7, 0x0f0f0f0f, 4);
2003 
2004       MERGE (b0, b1, 0x00ff00ff, 8);
2005       MERGE (b2, b3, 0x00ff00ff, 8);
2006       MERGE (b4, b5, 0x00ff00ff, 8);
2007       MERGE (b6, b7, 0x00ff00ff, 8);
2008 
2009       MERGE (b0, b2, 0x0000ffff, 16);
2010       DO_SWLONG(pixels, b0);
2011       DO_SWLONG(pixels + 4, b2);
2012       MERGE (b1, b3, 0x0000ffff, 16);
2013       DO_SWLONG(pixels + 2, b1);
2014       DO_SWLONG(pixels + 6, b3);
2015       MERGE (b4, b6, 0x0000ffff, 16);
2016       DO_SWLONG(pixels + 1, b4);
2017       DO_SWLONG(pixels + 5, b6);
2018       MERGE (b5, b7, 0x0000ffff, 16);
2019       DO_SWLONG(pixels + 3, b5);
2020       DO_SWLONG(pixels + 7, b7);
2021       pixels += 8;
2022    }
2023 }
2024 
pfield_doline_n3(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)2025 static void pfield_doline_n3 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
2026 {
2027   uae_u8 *real_bplpt[3];
2028 
2029    real_bplpt[0] = DATA_POINTER (0);
2030    real_bplpt[1] = DATA_POINTER (1);
2031    real_bplpt[2] = DATA_POINTER (2);
2032 
2033    while (wordcount-- > 0) {
2034       uae_u32 b0,b1,b2,b3,b4,b5,b6,b7;
2035       b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
2036       b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
2037       b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
2038 
2039       MERGE_0(b4, b5, 0x55555555, 1);
2040       MERGE (b6, b7, 0x55555555, 1);
2041 
2042       MERGE (b4, b6, 0x33333333, 2);
2043       MERGE (b5, b7, 0x33333333, 2);
2044 
2045       MERGE_0(b0, b4, 0x0f0f0f0f, 4);
2046       MERGE_0(b1, b5, 0x0f0f0f0f, 4);
2047       MERGE_0(b2, b6, 0x0f0f0f0f, 4);
2048       MERGE_0(b3, b7, 0x0f0f0f0f, 4);
2049 
2050       MERGE (b0, b1, 0x00ff00ff, 8);
2051       MERGE (b2, b3, 0x00ff00ff, 8);
2052       MERGE (b4, b5, 0x00ff00ff, 8);
2053       MERGE (b6, b7, 0x00ff00ff, 8);
2054 
2055       MERGE (b0, b2, 0x0000ffff, 16);
2056       DO_SWLONG(pixels, b0);
2057       DO_SWLONG(pixels + 4, b2);
2058       MERGE (b1, b3, 0x0000ffff, 16);
2059       DO_SWLONG(pixels + 2, b1);
2060       DO_SWLONG(pixels + 6, b3);
2061       MERGE (b4, b6, 0x0000ffff, 16);
2062       DO_SWLONG(pixels + 1, b4);
2063       DO_SWLONG(pixels + 5, b6);
2064       MERGE (b5, b7, 0x0000ffff, 16);
2065       DO_SWLONG(pixels + 3, b5);
2066       DO_SWLONG(pixels + 7, b7);
2067       pixels += 8;
2068    }
2069 }
2070 
pfield_doline_n4(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)2071 static void pfield_doline_n4 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
2072 {
2073 #if defined(__SYMBIAN32__) && !defined(__WINS__) && defined(USE_ASSEMBLER_CODE)
2074    PFIELD_DOLINE_N4 (pixels, wordcount, (uae_u8 *)&line_data[lineno], MAX_WORDS_PER_LINE * 2);
2075 #else
2076 
2077   uae_u8 *real_bplpt[4];
2078 
2079   real_bplpt[0] = DATA_POINTER (0);
2080   real_bplpt[1] = DATA_POINTER (1);
2081   real_bplpt[2] = DATA_POINTER (2);
2082   real_bplpt[3] = DATA_POINTER (3);
2083 
2084    while (wordcount-- > 0) {
2085       uae_u32 b0,b1,b2,b3,b4,b5,b6,b7;
2086       b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4;
2087       b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
2088       b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
2089       b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
2090 
2091       MERGE (b4, b5, 0x55555555, 1);
2092       MERGE (b6, b7, 0x55555555, 1);
2093 
2094       MERGE (b4, b6, 0x33333333, 2);
2095       MERGE (b5, b7, 0x33333333, 2);
2096 
2097       MERGE_0(b0, b4, 0x0f0f0f0f, 4);
2098       MERGE_0(b1, b5, 0x0f0f0f0f, 4);
2099       MERGE_0(b2, b6, 0x0f0f0f0f, 4);
2100       MERGE_0(b3, b7, 0x0f0f0f0f, 4);
2101 
2102       MERGE (b0, b1, 0x00ff00ff, 8);
2103       MERGE (b2, b3, 0x00ff00ff, 8);
2104       MERGE (b4, b5, 0x00ff00ff, 8);
2105       MERGE (b6, b7, 0x00ff00ff, 8);
2106 
2107       MERGE (b0, b2, 0x0000ffff, 16);
2108       DO_SWLONG(pixels, b0);
2109       DO_SWLONG(pixels + 4, b2);
2110       MERGE (b1, b3, 0x0000ffff, 16);
2111       DO_SWLONG(pixels + 2, b1);
2112       DO_SWLONG(pixels + 6, b3);
2113       MERGE (b4, b6, 0x0000ffff, 16);
2114       DO_SWLONG(pixels + 1, b4);
2115       DO_SWLONG(pixels + 5, b6);
2116       MERGE (b5, b7, 0x0000ffff, 16);
2117       DO_SWLONG(pixels + 3, b5);
2118       DO_SWLONG(pixels + 7, b7);
2119       pixels += 8;
2120    }
2121 #endif
2122 }
2123 
pfield_doline_n5(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)2124 static void pfield_doline_n5 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
2125 {
2126 #if defined(__SYMBIAN32__) && !defined(__WINS__) && defined(USE_ASSEMBLER_CODE)
2127    PFIELD_DOLINE_N5 (pixels, wordcount, (uae_u8 *)&line_data[lineno], MAX_WORDS_PER_LINE * 2);
2128 #else
2129   uae_u8 *real_bplpt[5];
2130 
2131    real_bplpt[0] = DATA_POINTER (0);
2132    real_bplpt[1] = DATA_POINTER (1);
2133    real_bplpt[2] = DATA_POINTER (2);
2134    real_bplpt[3] = DATA_POINTER (3);
2135    real_bplpt[4] = DATA_POINTER (4);
2136 
2137    while (wordcount-- > 0) {
2138       uae_u32 b0,b1,b2,b3,b4,b5,b6,b7;
2139       b3 = GETLONG ((uae_u32 *)real_bplpt[4]); real_bplpt[4] += 4;
2140       b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4;
2141       b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
2142       b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
2143       b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
2144 
2145       MERGE_0(b2, b3, 0x55555555, 1);
2146       MERGE (b4, b5, 0x55555555, 1);
2147       MERGE (b6, b7, 0x55555555, 1);
2148 
2149       MERGE_0(b0, b2, 0x33333333, 2);
2150       MERGE_0(b1, b3, 0x33333333, 2);
2151       MERGE (b4, b6, 0x33333333, 2);
2152       MERGE (b5, b7, 0x33333333, 2);
2153 
2154       MERGE (b0, b4, 0x0f0f0f0f, 4);
2155       MERGE (b1, b5, 0x0f0f0f0f, 4);
2156       MERGE (b2, b6, 0x0f0f0f0f, 4);
2157       MERGE (b3, b7, 0x0f0f0f0f, 4);
2158 
2159       MERGE (b0, b1, 0x00ff00ff, 8);
2160       MERGE (b2, b3, 0x00ff00ff, 8);
2161       MERGE (b4, b5, 0x00ff00ff, 8);
2162       MERGE (b6, b7, 0x00ff00ff, 8);
2163 
2164       MERGE (b0, b2, 0x0000ffff, 16);
2165       DO_SWLONG(pixels, b0);
2166       DO_SWLONG(pixels + 4, b2);
2167       MERGE (b1, b3, 0x0000ffff, 16);
2168       DO_SWLONG(pixels + 2, b1);
2169       DO_SWLONG(pixels + 6, b3);
2170       MERGE (b4, b6, 0x0000ffff, 16);
2171       DO_SWLONG(pixels + 1, b4);
2172       DO_SWLONG(pixels + 5, b6);
2173       MERGE (b5, b7, 0x0000ffff, 16);
2174       DO_SWLONG(pixels + 3, b5);
2175       DO_SWLONG(pixels + 7, b7);
2176       pixels += 8;
2177    }
2178 #endif
2179 }
2180 
pfield_doline_n6(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)2181 static void pfield_doline_n6 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
2182 {
2183 #if defined(__SYMBIAN32__) && !defined(__WINS__) && defined(USE_ASSEMBLER_CODE)
2184    PFIELD_DOLINE_N6 (pixels, wordcount, (uae_u8 *)&line_data[lineno], MAX_WORDS_PER_LINE * 2);
2185 #else
2186   uae_u8 *real_bplpt[6];
2187 
2188    real_bplpt[0] = DATA_POINTER (0);
2189    real_bplpt[1] = DATA_POINTER (1);
2190    real_bplpt[2] = DATA_POINTER (2);
2191    real_bplpt[3] = DATA_POINTER (3);
2192    real_bplpt[4] = DATA_POINTER (4);
2193    real_bplpt[5] = DATA_POINTER (5);
2194 
2195    while (wordcount-- > 0) {
2196       uae_u32 b0,b1,b2,b3,b4,b5,b6,b7;
2197       b2 = GETLONG ((uae_u32 *)real_bplpt[5]); real_bplpt[5] += 4;
2198       b3 = GETLONG ((uae_u32 *)real_bplpt[4]); real_bplpt[4] += 4;
2199       b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4;
2200       b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
2201       b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
2202       b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
2203 
2204       MERGE (b2, b3, 0x55555555, 1);
2205       MERGE (b4, b5, 0x55555555, 1);
2206       MERGE (b6, b7, 0x55555555, 1);
2207 
2208       MERGE_0(b0, b2, 0x33333333, 2);
2209       MERGE_0(b1, b3, 0x33333333, 2);
2210       MERGE (b4, b6, 0x33333333, 2);
2211       MERGE (b5, b7, 0x33333333, 2);
2212 
2213       MERGE (b0, b4, 0x0f0f0f0f, 4);
2214       MERGE (b1, b5, 0x0f0f0f0f, 4);
2215       MERGE (b2, b6, 0x0f0f0f0f, 4);
2216       MERGE (b3, b7, 0x0f0f0f0f, 4);
2217 
2218       MERGE (b0, b1, 0x00ff00ff, 8);
2219       MERGE (b2, b3, 0x00ff00ff, 8);
2220       MERGE (b4, b5, 0x00ff00ff, 8);
2221       MERGE (b6, b7, 0x00ff00ff, 8);
2222 
2223       MERGE (b0, b2, 0x0000ffff, 16);
2224       DO_SWLONG(pixels, b0);
2225       DO_SWLONG(pixels + 4, b2);
2226       MERGE (b1, b3, 0x0000ffff, 16);
2227       DO_SWLONG(pixels + 2, b1);
2228       DO_SWLONG(pixels + 6, b3);
2229       MERGE (b4, b6, 0x0000ffff, 16);
2230       DO_SWLONG(pixels + 1, b4);
2231       DO_SWLONG(pixels + 5, b6);
2232       MERGE (b5, b7, 0x0000ffff, 16);
2233       DO_SWLONG(pixels + 3, b5);
2234       DO_SWLONG(pixels + 7, b7);
2235       pixels += 8;
2236    }
2237 #endif
2238 }
2239 
2240 #ifdef AGA
pfield_doline_n7(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)2241 static void pfield_doline_n7 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
2242 {
2243 #if defined(__SYMBIAN32__) && !defined(__WINS__) && defined(USE_ASSEMBLER_CODE)
2244    PFIELD_DOLINE_N7 (pixels, wordcount, (uae_u8 *)&line_data[lineno], MAX_WORDS_PER_LINE * 2);
2245 #else
2246   uae_u8 *real_bplpt[7];
2247    real_bplpt[0] = DATA_POINTER (0);
2248    real_bplpt[1] = DATA_POINTER (1);
2249    real_bplpt[2] = DATA_POINTER (2);
2250    real_bplpt[3] = DATA_POINTER (3);
2251    real_bplpt[4] = DATA_POINTER (4);
2252    real_bplpt[5] = DATA_POINTER (5);
2253    real_bplpt[6] = DATA_POINTER (6);
2254 
2255    while (wordcount-- > 0) {
2256       uae_u32 b0,b1,b2,b3,b4,b5,b6,b7;
2257       b1 = GETLONG ((uae_u32 *)real_bplpt[6]); real_bplpt[6] += 4;
2258       b2 = GETLONG ((uae_u32 *)real_bplpt[5]); real_bplpt[5] += 4;
2259       b3 = GETLONG ((uae_u32 *)real_bplpt[4]); real_bplpt[4] += 4;
2260       b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4;
2261       b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
2262       b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
2263       b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
2264 
2265       MERGE_0(b0, b1, 0x55555555, 1);
2266       MERGE (b2, b3, 0x55555555, 1);
2267       MERGE (b4, b5, 0x55555555, 1);
2268       MERGE (b6, b7, 0x55555555, 1);
2269 
2270       MERGE (b0, b2, 0x33333333, 2);
2271       MERGE (b1, b3, 0x33333333, 2);
2272       MERGE (b4, b6, 0x33333333, 2);
2273       MERGE (b5, b7, 0x33333333, 2);
2274 
2275       MERGE (b0, b4, 0x0f0f0f0f, 4);
2276       MERGE (b1, b5, 0x0f0f0f0f, 4);
2277       MERGE (b2, b6, 0x0f0f0f0f, 4);
2278       MERGE (b3, b7, 0x0f0f0f0f, 4);
2279 
2280       MERGE (b0, b1, 0x00ff00ff, 8);
2281       MERGE (b2, b3, 0x00ff00ff, 8);
2282       MERGE (b4, b5, 0x00ff00ff, 8);
2283       MERGE (b6, b7, 0x00ff00ff, 8);
2284 
2285       MERGE (b0, b2, 0x0000ffff, 16);
2286       DO_SWLONG(pixels, b0);
2287       DO_SWLONG(pixels + 4, b2);
2288       MERGE (b1, b3, 0x0000ffff, 16);
2289       DO_SWLONG(pixels + 2, b1);
2290       DO_SWLONG(pixels + 6, b3);
2291       MERGE (b4, b6, 0x0000ffff, 16);
2292       DO_SWLONG(pixels + 1, b4);
2293       DO_SWLONG(pixels + 5, b6);
2294       MERGE (b5, b7, 0x0000ffff, 16);
2295       DO_SWLONG(pixels + 3, b5);
2296       DO_SWLONG(pixels + 7, b7);
2297       pixels += 8;
2298    }
2299 #endif
2300 }
2301 
pfield_doline_n8(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)2302 static void pfield_doline_n8 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
2303 {
2304 #if defined(__SYMBIAN32__) && !defined(__WINS__) && defined(USE_ASSEMBLER_CODE)
2305    PFIELD_DOLINE_N8 (pixels, wordcount, (uae_u8 *)&line_data[lineno], MAX_WORDS_PER_LINE * 2);
2306 #else
2307   uae_u8 *real_bplpt[8];
2308 
2309   real_bplpt[0] = DATA_POINTER (0);
2310   real_bplpt[1] = DATA_POINTER (1);
2311   real_bplpt[2] = DATA_POINTER (2);
2312   real_bplpt[3] = DATA_POINTER (3);
2313   real_bplpt[4] = DATA_POINTER (4);
2314   real_bplpt[5] = DATA_POINTER (5);
2315   real_bplpt[6] = DATA_POINTER (6);
2316   real_bplpt[7] = DATA_POINTER (7);
2317 
2318    while (wordcount-- > 0) {
2319       uae_u32 b0,b1,b2,b3,b4,b5,b6,b7;
2320       b0 = GETLONG ((uae_u32 *)real_bplpt[7]); real_bplpt[7] += 4;
2321       b1 = GETLONG ((uae_u32 *)real_bplpt[6]); real_bplpt[6] += 4;
2322       b2 = GETLONG ((uae_u32 *)real_bplpt[5]); real_bplpt[5] += 4;
2323       b3 = GETLONG ((uae_u32 *)real_bplpt[4]); real_bplpt[4] += 4;
2324       b4 = GETLONG ((uae_u32 *)real_bplpt[3]); real_bplpt[3] += 4;
2325       b5 = GETLONG ((uae_u32 *)real_bplpt[2]); real_bplpt[2] += 4;
2326       b6 = GETLONG ((uae_u32 *)real_bplpt[1]); real_bplpt[1] += 4;
2327       b7 = GETLONG ((uae_u32 *)real_bplpt[0]); real_bplpt[0] += 4;
2328 
2329       MERGE (b0, b1, 0x55555555, 1);
2330       MERGE (b2, b3, 0x55555555, 1);
2331       MERGE (b4, b5, 0x55555555, 1);
2332       MERGE (b6, b7, 0x55555555, 1);
2333 
2334       MERGE (b0, b2, 0x33333333, 2);
2335       MERGE (b1, b3, 0x33333333, 2);
2336       MERGE (b4, b6, 0x33333333, 2);
2337       MERGE (b5, b7, 0x33333333, 2);
2338 
2339       MERGE (b0, b4, 0x0f0f0f0f, 4);
2340       MERGE (b1, b5, 0x0f0f0f0f, 4);
2341       MERGE (b2, b6, 0x0f0f0f0f, 4);
2342       MERGE (b3, b7, 0x0f0f0f0f, 4);
2343 
2344       MERGE (b0, b1, 0x00ff00ff, 8);
2345       MERGE (b2, b3, 0x00ff00ff, 8);
2346       MERGE (b4, b5, 0x00ff00ff, 8);
2347       MERGE (b6, b7, 0x00ff00ff, 8);
2348 
2349       MERGE (b0, b2, 0x0000ffff, 16);
2350       DO_SWLONG(pixels, b0);
2351       DO_SWLONG(pixels + 4, b2);
2352       MERGE (b1, b3, 0x0000ffff, 16);
2353       DO_SWLONG(pixels + 2, b1);
2354       DO_SWLONG(pixels + 6, b3);
2355       MERGE (b4, b6, 0x0000ffff, 16);
2356       DO_SWLONG(pixels + 1, b4);
2357       DO_SWLONG(pixels + 5, b6);
2358       MERGE (b5, b7, 0x0000ffff, 16);
2359       DO_SWLONG(pixels + 3, b5);
2360       DO_SWLONG(pixels + 7, b7);
2361       pixels += 8;
2362    }
2363 #endif
2364 }
2365 #else /*AGA*/
2366 #define pfield_doline_n7 pfield_doline_dummy
2367 #define pfield_doline_n8 pfield_doline_dummy
2368 #endif /*AGA*/
2369 
pfield_doline_n0(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)2370 static void pfield_doline_n0 (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
2371 {
2372 	uae4all_memclr(pixels, wordcount << 5);
2373 }
2374 
pfield_doline_dummy(uae_u32 * pixels,int wordcount,int lineno LINEDATA_DECL)2375 static void pfield_doline_dummy (uae_u32 *pixels, int wordcount, int lineno LINEDATA_DECL)
2376 {
2377 }
2378 
2379 typedef void (*pfield_doline_func)(uae_u32 *_GCCRES_, int, int LINEDATA_DECL);
2380 
2381 # ifdef USE_ARMNEON
2382 static pfield_doline_func pfield_doline_n[16]={
2383 	pfield_doline_n0, ARM_doline_n1, NEON_doline_n2, NEON_doline_n3,
2384 	NEON_doline_n4, pfield_doline_n5, NEON_doline_n6, pfield_doline_n7,
2385 	NEON_doline_n8, pfield_doline_dummy,pfield_doline_dummy,pfield_doline_dummy,
2386 	pfield_doline_dummy,pfield_doline_dummy,pfield_doline_dummy,pfield_doline_dummy
2387 };
2388 # else /*USE_ARMNEON*/
2389 static pfield_doline_func pfield_doline_n[16]={
2390 	pfield_doline_n0, pfield_doline_n1,pfield_doline_n2,pfield_doline_n3,
2391 	pfield_doline_n4, pfield_doline_n5,pfield_doline_n6,pfield_doline_n7,
2392 	pfield_doline_n8, pfield_doline_dummy,pfield_doline_dummy,pfield_doline_dummy,
2393 	pfield_doline_dummy,pfield_doline_dummy,pfield_doline_dummy,pfield_doline_dummy
2394 };
2395 # endif /*USE_ARMNEON*/
2396 
pfield_doline(int lineno)2397 static __inline__ void pfield_doline (int lineno)
2398 {
2399   pfield_doline_n[bplplanecnt](pixdata.apixels_l + MAX_PIXELS_PER_LINE/4,dp_for_drawing->plflinelen,lineno LINEDATA_ARG0);
2400 }
2401 #endif /*UNROLL_PFIELD*/
2402 
2403 
init_row_map(void)2404 void init_row_map (void)
2405 {
2406 	static uae_u8 *oldbufmem;
2407 	static int oldheight, oldpitch;
2408 	int i, j;
2409 
2410 	if (gfxvidinfo.height_allocated > MAX_UAE_HEIGHT) {
2411 		write_log (_T("Resolution too high, aborting\n"));
2412 		abort ();
2413 	}
2414 	if (!row_map)
2415 		row_map = xmalloc (uae_u8*, MAX_UAE_HEIGHT + 1);
2416 
2417 	if (oldbufmem && oldbufmem == gfxvidinfo.bufmem &&
2418 		oldheight == gfxvidinfo.height_allocated &&
2419 		oldpitch == gfxvidinfo.rowbytes)
2420 		return;
2421 	j = oldheight == 0 ? MAX_UAE_HEIGHT : oldheight;
2422 	for (i = gfxvidinfo.height_allocated; i < MAX_UAE_HEIGHT + 1 && i < j + 1; i++)
2423 		row_map[i] = row_tmp;
2424 	for (i = 0, j = 0; i < gfxvidinfo.height_allocated; i++, j += gfxvidinfo.rowbytes)
2425 		row_map[i] = gfxvidinfo.bufmem + j;
2426 	oldbufmem = gfxvidinfo.bufmem;
2427 	oldheight = gfxvidinfo.height_allocated;
2428 	oldpitch = gfxvidinfo.rowbytes;
2429 }
2430 
init_aspect_maps(void)2431 void init_aspect_maps (void)
2432 {
2433 	int i, maxl, h;
2434 
2435 	h = gfxvidinfo.height_allocated;
2436 
2437 	if (h == 0)
2438 		/* Do nothing if the gfx driver hasn't initialized the screen yet */
2439 		return;
2440 
2441 	linedbld = linedbl = currprefs.gfx_vresolution;
2442 	if (doublescan > 0 && interlace_seen <= 0) {
2443 		linedbl = 0;
2444 		linedbld = 1;
2445 	}
2446 
2447 	if (native2amiga_line_map)
2448 		xfree (native2amiga_line_map);
2449 	if (amiga2aspect_line_map)
2450 		xfree (amiga2aspect_line_map);
2451 
2452 	/* At least for this array the +1 is necessary. */
2453 	amiga2aspect_line_map = xmalloc (int, (MAXVPOS + 1) * 2 + 1);
2454 	native2amiga_line_map = xmalloc (int, h);
2455 
2456 	maxl = (MAXVPOS + 1) << linedbld;
2457 	min_ypos_for_screen = minfirstline << linedbl;
2458 	max_drawn_amiga_line = -1;
2459 	for (i = 0; i < maxl; i++) {
2460 		int v = i - min_ypos_for_screen;
2461 		if (v >= h && max_drawn_amiga_line < 0)
2462 			max_drawn_amiga_line = i - min_ypos_for_screen;
2463 		if (i < min_ypos_for_screen || v >= h)
2464 			v = -1;
2465 		amiga2aspect_line_map[i] = v;
2466 	}
2467 	if (max_drawn_amiga_line < 0)
2468 		max_drawn_amiga_line = maxl - min_ypos_for_screen;
2469 	max_drawn_amiga_line >>= linedbl;
2470 
2471 	if (currprefs.gfx_ycenter && !currprefs.gfx_filter_autoscale) {
2472 		/* @@@ verify maxvpos vs. MAXVPOS */
2473 		extra_y_adjust = (h - (maxvpos_nom << linedbl)) >> 1;
2474 		if (extra_y_adjust < 0)
2475 			extra_y_adjust = 0;
2476 	}
2477 
2478 	for (i = h; i--; )
2479 		native2amiga_line_map[i] = -1;
2480 
2481 	for (i = maxl - 1; i >= min_ypos_for_screen; i--) {
2482 		int j;
2483 		if (amiga2aspect_line_map[i] == -1)
2484 			continue;
2485 		for (j = amiga2aspect_line_map[i]; j < h && native2amiga_line_map[j] == -1; j++)
2486 			native2amiga_line_map[j] = i >> linedbl;
2487 	}
2488 
2489 	gfxvidinfo.xchange = 1 << (RES_MAX - currprefs.gfx_resolution);
2490 	gfxvidinfo.ychange = linedbl ? 1 : 2;
2491 
2492 	visible_left_start = 0;
2493 	visible_right_stop = MAX_STOP;
2494 	visible_top_start = 0;
2495 	visible_bottom_stop = MAX_STOP;
2496 	set_blanking_limits ();
2497 }
2498 
2499 /*
2500  * A raster line has been built in the graphics buffer. Tell the graphics code
2501  * to do anything necessary to display it.
2502  */
do_flush_line_1(int lineno)2503 static void do_flush_line_1 (int lineno)
2504 {
2505 	if (lineno < first_drawn_line)
2506 		first_drawn_line = lineno;
2507 	if (lineno > last_drawn_line)
2508 		last_drawn_line = lineno;
2509 
2510 	if (gfxvidinfo.maxblocklines == 0)
2511 		flush_line (lineno);
2512 	else {
2513 		if ((last_block_line + 2) < lineno) {
2514 			if (first_block_line != NO_BLOCK)
2515 				flush_block (first_block_line, last_block_line);
2516 			first_block_line = lineno;
2517 		}
2518 		last_block_line = lineno;
2519 		if (last_block_line - first_block_line >= gfxvidinfo.maxblocklines) {
2520 			flush_block (first_block_line, last_block_line);
2521 			first_block_line = last_block_line = NO_BLOCK;
2522 		}
2523 	}
2524 }
2525 
do_flush_line(int lineno)2526 STATIC_INLINE void do_flush_line (int lineno)
2527 {
2528 	do_flush_line_1 (lineno);
2529 }
2530 
2531 /*
2532  * One drawing frame has been finished. Tell the graphics code about it.
2533  * Note that the actual flush_screen() call is a no-op for all reasonable
2534  * systems.
2535  */
2536 
do_flush_screen(int start,int stop)2537 STATIC_INLINE void do_flush_screen (int start, int stop)
2538 {
2539 	/* TODO: this flush operation is executed outside locked state!
2540 	Should be corrected.
2541 	(sjo 26.9.99) */
2542 
2543 	xlinecheck (start, stop);
2544 	if (gfxvidinfo.maxblocklines != 0 && first_block_line != NO_BLOCK) {
2545 		flush_block (first_block_line, last_block_line);
2546 	}
2547 	unlockscr ();
2548 	if (start <= stop)
2549 		flush_screen (start, stop);
2550 	else if (isvsync_chipset ())
2551 		flush_screen (0, 0); /* vsync mode */
2552 }
2553 
2554 /* We only save hardware registers during the hardware frame. Now, when
2555  * drawing the frame, we expand the data into a slightly more useful
2556  * form. */
pfield_expand_dp_bplcon(void)2557 static void pfield_expand_dp_bplcon (void)
2558 {
2559 // REMOVEME:
2560 #if 0
2561 	static int b2;
2562 #endif
2563 
2564 	bplres = dp_for_drawing->bplres;
2565 	bplplanecnt = dp_for_drawing->nr_planes;
2566 	bplham = dp_for_drawing->ham_seen;
2567 	bplehb = dp_for_drawing->ehb_seen;
2568 	if ((currprefs.chipset_mask & CSMASK_AGA) && (dp_for_drawing->bplcon2 & 0x0200))
2569 		bplehb = 0;
2570 	issprites = dip_for_drawing->nr_sprites > 0;
2571 #ifdef ECS_DENISE
2572 	ecsshres = bplres == RES_SUPERHIRES && (currprefs.chipset_mask & CSMASK_ECS_DENISE) && !(currprefs.chipset_mask & CSMASK_AGA);
2573 #endif
2574 
2575 	plf1pri = dp_for_drawing->bplcon2 & 7;
2576 	plf2pri = (dp_for_drawing->bplcon2 >> 3) & 7;
2577 	plf_sprite_mask = 0xFFFF0000 << (4 * plf2pri);
2578 	plf_sprite_mask |= (0x0000FFFF << (4 * plf1pri)) & 0xFFFF;
2579 	bpldualpf = (dp_for_drawing->bplcon0 & 0x400) == 0x400;
2580 	bpldualpfpri = (dp_for_drawing->bplcon2 & 0x40) == 0x40;
2581 
2582 #ifdef AGA
2583 	bpldualpf2of = (dp_for_drawing->bplcon3 >> 10) & 7;
2584 	sbasecol[0] = ((dp_for_drawing->bplcon4 >> 4) & 15) << 4;
2585 	sbasecol[1] = ((dp_for_drawing->bplcon4 >> 0) & 15) << 4;
2586 	bplxor = dp_for_drawing->bplcon4 >> 8;
2587 #endif
2588 }
2589 
isham(uae_u16 bplcon0)2590 static bool isham (uae_u16 bplcon0)
2591 {
2592 	int p = GET_PLANES (bplcon0);
2593 	if (!(bplcon0 & 0x800))
2594 		return 0;
2595 	if (currprefs.chipset_mask & CSMASK_AGA) {
2596 		// AGA only has 6 or 8 plane HAM
2597 		if (p == 6 || p == 8)
2598 			return 1;
2599 	} else {
2600 		// OCS/ECS also supports 5 plane HAM
2601 		if (GET_RES_DENISE (bplcon0) > 0)
2602 			return 0;
2603 		if (p >= 5)
2604 			return 1;
2605 	}
2606 	return 0;
2607 }
2608 
pfield_expand_dp_bplconx(int regno,int v)2609 static void pfield_expand_dp_bplconx (int regno, int v)
2610 {
2611 	if (regno == 0xffff) {
2612 		hposblank = 1;
2613 		return;
2614 	}
2615 	regno -= 0x1000;
2616 	switch (regno)
2617 	{
2618 	case 0x100: // BPLCON1
2619 		dp_for_drawing->bplcon0 = v;
2620 		dp_for_drawing->bplres = GET_RES_DENISE (v);
2621 		dp_for_drawing->nr_planes = GET_PLANES (v);
2622 		dp_for_drawing->ham_seen = isham (v);
2623 		break;
2624 	case 0x104: // BPLCON2
2625 		dp_for_drawing->bplcon2 = v;
2626 		break;
2627 #ifdef ECS_DENISE
2628 	case 0x106: // BPLCON3
2629 		dp_for_drawing->bplcon3 = v;
2630 		break;
2631 #endif
2632 #ifdef AGA
2633 	case 0x10c: // BPLCON4
2634 		dp_for_drawing->bplcon4 = v;
2635 		break;
2636 #endif
2637 	}
2638 	pfield_expand_dp_bplcon ();
2639 	res_shift = lores_shift - bplres;
2640 }
2641 
2642 static int drawing_color_matches;
2643 static enum { color_match_acolors, color_match_full } color_match_type;
2644 
2645 /* Set up colors_for_drawing to the state at the beginning of the currently drawn
2646    line.  Try to avoid copying color tables around whenever possible.  */
adjust_drawing_colors(int ctable,int need_full)2647 static void adjust_drawing_colors (int ctable, int need_full)
2648 {
2649 	if (drawing_color_matches != ctable) {
2650 		if (need_full) {
2651 			color_reg_cpy (&colors_for_drawing, curr_color_tables + ctable);
2652 			color_match_type = color_match_full;
2653 		} else {
2654 			memcpy (colors_for_drawing.acolors, curr_color_tables[ctable].acolors,
2655 				sizeof colors_for_drawing.acolors);
2656 			colors_for_drawing.borderblank = curr_color_tables[ctable].borderblank;
2657 			colors_for_drawing.bordersprite = curr_color_tables[ctable].bordersprite;
2658 			color_match_type = color_match_acolors;
2659 		}
2660 		drawing_color_matches = ctable;
2661 	} else if (need_full && color_match_type != color_match_full) {
2662 		color_reg_cpy (&colors_for_drawing, &curr_color_tables[ctable]);
2663 		color_match_type = color_match_full;
2664 	}
2665 }
2666 
do_color_changes(line_draw_func worker_border,line_draw_func worker_pfield,int vp)2667 static void do_color_changes (line_draw_func worker_border, line_draw_func worker_pfield, int vp)
2668 {
2669 	int i;
2670 	int lastpos = visible_left_border;
2671 	int endpos = visible_left_border + gfxvidinfo.inwidth;
2672 
2673 	for (i = dip_for_drawing->first_color_change; i <= dip_for_drawing->last_color_change; i++) {
2674 		int regno = curr_color_changes[i].regno;
2675 		unsigned int value = curr_color_changes[i].value;
2676 		int nextpos, nextpos_in_range;
2677 
2678 		if (i == dip_for_drawing->last_color_change)
2679 			nextpos = endpos;
2680 		else
2681 			nextpos = coord_hw_to_window_x (curr_color_changes[i].linepos);
2682 
2683 		nextpos_in_range = nextpos;
2684 		if (nextpos > endpos)
2685 			nextpos_in_range = endpos;
2686 
2687 		// left hblank (left edge to hblank end)
2688 		if (nextpos_in_range > lastpos && lastpos < hblank_left_start) {
2689 			int t = nextpos_in_range <= hblank_left_start ? nextpos_in_range : hblank_left_start;
2690 			(*worker_border) (lastpos, t, true);
2691 			lastpos = t;
2692 		}
2693 
2694 		// left border (hblank end to playfield start)
2695 		if (nextpos_in_range > lastpos && lastpos < playfield_start) {
2696 				int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start;
2697 				(*worker_border) (lastpos, t, false);
2698 				lastpos = t;
2699 			}
2700 
2701 		// playfield
2702 		if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end) {
2703 				int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end;
2704 				(*worker_pfield) (lastpos, t, false);
2705 				lastpos = t;
2706 			}
2707 
2708 		// right border (playfield end to hblank start)
2709 		if (nextpos_in_range > lastpos && lastpos >= playfield_end) {
2710 			int t = nextpos_in_range <= hblank_right_stop ? nextpos_in_range : hblank_right_stop;
2711 			(*worker_border) (lastpos, t, false);
2712 			lastpos = t;
2713 		}
2714 
2715 		// right hblank (hblank start to right edge, hblank start may be earlier than playfield end)
2716 		if (nextpos_in_range > hblank_right_stop) {
2717 			(*worker_border) (hblank_right_stop, nextpos_in_range, true);
2718 			lastpos = nextpos_in_range;
2719 		}
2720 
2721 		if (regno >= 0x1000) {
2722 			pfield_expand_dp_bplconx (regno, value);
2723 		} else if (regno >= 0) {
2724 			if (regno == 0 && (value & COLOR_CHANGE_BRDBLANK)) {
2725 				colors_for_drawing.borderblank = (value & 1) != 0;
2726 				colors_for_drawing.bordersprite = (value & 3) == 2;
2727 			} else {
2728 			color_reg_set (&colors_for_drawing, regno, value);
2729 			colors_for_drawing.acolors[regno] = getxcolor (value);
2730 		}
2731 		}
2732 		if (lastpos >= endpos)
2733 			break;
2734 	}
2735 /*	if (vp < visible_top_start || vp >= visible_bottom_stop) {
2736 		// outside of visible area
2737 		// Just overwrite with black. Above code needs to run because of custom registers,
2738 		// not worth the trouble for separate code path just for max 10 lines or so
2739 		(*worker_border) (visible_left_border, visible_left_border + gfxvidinfo.inwidth, true);
2740 	}*/
2741 
2742 }
2743 enum double_how {
2744 	dh_buf,
2745 	dh_line,
2746 	dh_emerg
2747 };
2748 
pfield_draw_line(int lineno,int gfx_ypos,int follow_ypos)2749 static void pfield_draw_line (int lineno, int gfx_ypos, int follow_ypos)
2750 {
2751 // REMOVEME:
2752 #if 0
2753 	static int warned = 0;
2754 #endif
2755 	int border = 0;
2756 	int do_double = 0;
2757 	enum double_how dh;
2758 
2759 	dp_for_drawing = line_decisions + lineno;
2760 	dip_for_drawing = curr_drawinfo + lineno;
2761 
2762 	switch (linestate[lineno])
2763 	{
2764 	case LINE_REMEMBERED_AS_PREVIOUS:
2765 // REMOVEME:
2766 #if 0
2767 		if (!warned) // happens when program messes up with VPOSW
2768 			write_log (_T("Shouldn't get here... this is a bug.\n")), warned++;
2769 #endif
2770 		return;
2771 
2772 	case LINE_BLACK:
2773 		linestate[lineno] = LINE_REMEMBERED_AS_BLACK;
2774 		border = -1;
2775 		break;
2776 
2777 	case LINE_REMEMBERED_AS_BLACK:
2778 		return;
2779 
2780 	case LINE_AS_PREVIOUS:
2781 		dp_for_drawing--;
2782 		dip_for_drawing--;
2783 		linestate[lineno] = LINE_DONE_AS_PREVIOUS;
2784 		if (dp_for_drawing->plfleft < 0)
2785 			border = 1;
2786 		break;
2787 
2788 	case LINE_DONE_AS_PREVIOUS:
2789 		/* fall through */
2790 	case LINE_DONE:
2791 		return;
2792 
2793 	case LINE_DECIDED_DOUBLE:
2794 		if (follow_ypos >= 0) {
2795 			do_double = 1;
2796 			linestate[lineno + 1] = LINE_DONE_AS_PREVIOUS;
2797 		}
2798 
2799 		/* fall through */
2800 	default:
2801 		if (dp_for_drawing->plfleft < 0)
2802 			border = 1;
2803 		linestate[lineno] = LINE_DONE;
2804 		break;
2805 	}
2806 
2807 	dh = dh_line;
2808 	xlinebuffer = gfxvidinfo.linemem;
2809 	if (xlinebuffer == 0 && do_double
2810 		&& (border == 0 || dip_for_drawing->nr_color_changes > 0))
2811 		xlinebuffer = gfxvidinfo.emergmem, dh = dh_emerg;
2812 	if (xlinebuffer == 0)
2813 		xlinebuffer = row_map[gfx_ypos], dh = dh_buf;
2814 	xlinebuffer -= linetoscr_x_adjust_bytes;
2815 
2816 	if (border == 0) {
2817 
2818 		pfield_expand_dp_bplcon ();
2819 		pfield_init_linetoscr ();
2820 		pfield_doline (lineno);
2821 
2822 		adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb || ecsshres);
2823 
2824 		/* The problem is that we must call decode_ham() BEFORE we do the
2825 		   sprites. */
2826 		if (dp_for_drawing->ham_seen) {
2827 			init_ham_decoding ();
2828 			if (dip_for_drawing->nr_color_changes == 0) {
2829 				/* The easy case: need to do HAM decoding only once for the
2830 				 * full line. */
2831 				decode_ham (visible_left_border, visible_right_border, false);
2832 			} else /* Argh. */ {
2833 				int ohposblank = hposblank;
2834 				do_color_changes (dummy_worker, decode_ham, lineno);
2835 				hposblank = ohposblank;
2836 				adjust_drawing_colors (dp_for_drawing->ctable, dp_for_drawing->ham_seen || bplehb);
2837 			}
2838 			bplham = dp_for_drawing->ham_at_start;
2839 		}
2840 
2841 		if (plf2pri > 5 && bplplanecnt == 5 && !(currprefs.chipset_mask & CSMASK_AGA))
2842 			weird_bitplane_fix ();
2843 
2844 		if (dip_for_drawing->nr_sprites) {
2845 			int i;
2846 #ifdef AGA
2847 			if (colors_for_drawing.bordersprite)
2848 				clear_bitplane_border_aga ();
2849 #endif
2850 
2851 			for (i = 0; i < dip_for_drawing->nr_sprites; i++) {
2852 #ifdef AGA
2853 				if (currprefs.chipset_mask & CSMASK_AGA)
2854 					draw_sprites_aga (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i, 1);
2855 				else
2856 #endif
2857 					draw_sprites_ecs (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i);
2858 			}
2859 		}
2860 
2861 		do_color_changes (pfield_do_fill_line, pfield_do_linetoscr, lineno);
2862 
2863 		if (dh == dh_emerg)
2864 			memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.inwidth);
2865 
2866 		do_flush_line (gfx_ypos);
2867 		if (do_double) {
2868 			if (dh == dh_emerg)
2869 				memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.inwidth);
2870 			else if (dh == dh_buf)
2871 				memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.pixbytes * gfxvidinfo.inwidth);
2872 			do_flush_line (follow_ypos);
2873 		}
2874 
2875 		if (dip_for_drawing->nr_sprites)
2876 			pfield_erase_hborder_sprites ();
2877 
2878 	} else if (border > 0) {
2879 		// border > 0: top or bottom border
2880 		bool dosprites = false;
2881 
2882 		adjust_drawing_colors (dp_for_drawing->ctable, 0);
2883 
2884 #ifdef AGA /* this makes things complex.. */
2885 		if (dp_for_drawing->bordersprite_seen && dip_for_drawing->nr_sprites) {
2886 			dosprites = true;
2887 			pfield_expand_dp_bplcon ();
2888 			pfield_init_linetoscr ();
2889 			pfield_erase_vborder_sprites ();
2890 		}
2891 #endif
2892 
2893 		if (!dosprites && dip_for_drawing->nr_color_changes == 0) {
2894 			fill_line ();
2895 			do_flush_line (gfx_ypos);
2896 
2897 			if (do_double) {
2898 				if (dh == dh_buf) {
2899 					xlinebuffer = row_map[follow_ypos] - linetoscr_x_adjust_bytes;
2900 					fill_line ();
2901 				}
2902 				/* If dh == dh_line, do_flush_line will re-use the rendered line
2903 				 * from linemem.  */
2904 				do_flush_line (follow_ypos);
2905 			}
2906 			return;
2907 		}
2908 
2909 		if (dosprites) {
2910 
2911 			int i;
2912 			for (i = 0; i < dip_for_drawing->nr_sprites; i++)
2913 				draw_sprites_aga (curr_sprite_entries + dip_for_drawing->first_sprite_entry + i, 1);
2914 			uae_u16 oxor = bplxor;
2915 			memset (pixdata.apixels, 0, sizeof pixdata);
2916 			bplxor = 0;
2917 			do_color_changes (pfield_do_fill_line, pfield_do_linetoscr_border, lineno);
2918 			bplxor = oxor;
2919 
2920 		} else {
2921 
2922 			playfield_start = visible_right_border;
2923 			playfield_end = visible_right_border;
2924 			do_color_changes (pfield_do_fill_line, pfield_do_fill_line, lineno);
2925 
2926 		}
2927 
2928 		if (dh == dh_emerg)
2929 			memcpy (row_map[gfx_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.inwidth);
2930 
2931 		do_flush_line (gfx_ypos);
2932 		if (do_double) {
2933 			if (dh == dh_emerg)
2934 				memcpy (row_map[follow_ypos], xlinebuffer + linetoscr_x_adjust_bytes, gfxvidinfo.pixbytes * gfxvidinfo.inwidth);
2935 			else if (dh == dh_buf)
2936 				memcpy (row_map[follow_ypos], row_map[gfx_ypos], gfxvidinfo.pixbytes * gfxvidinfo.inwidth);
2937 			do_flush_line (follow_ypos);
2938 		}
2939 
2940 	} else {
2941 
2942 		int tmp = hposblank;
2943 		hposblank = colors_for_drawing.borderblank;
2944 		fill_line ();
2945 		do_flush_line (gfx_ypos);
2946 		hposblank = tmp;
2947 
2948 	}
2949 }
2950 
center_image(void)2951 static void center_image (void)
2952 {
2953 	int prev_x_adjust = visible_left_border;
2954 	int prev_y_adjust = thisframe_y_adjust;
2955 	int tmp;
2956 
2957 	int w = gfxvidinfo.inwidth;
2958 	if (currprefs.gfx_xcenter && !currprefs.gfx_filter_autoscale && max_diwstop > 0) {
2959 
2960 		if (max_diwstop - min_diwstart < w && currprefs.gfx_xcenter == 2)
2961 			/* Try to center. */
2962 			visible_left_border = (max_diwstop - min_diwstart - w) / 2 + min_diwstart;
2963 		else
2964 			visible_left_border = max_diwstop - w - (max_diwstop - min_diwstart - w) / 2;
2965 		visible_left_border &= ~((xshift (1, lores_shift)) - 1);
2966 
2967 		/* Would the old value be good enough? If so, leave it as it is if we want to
2968 		* be clever. */
2969 		if (currprefs.gfx_xcenter == 2) {
2970 			if (center_reset || (visible_left_border < prev_x_adjust && prev_x_adjust < min_diwstart && min_diwstart - visible_left_border <= 32))
2971 				visible_left_border = prev_x_adjust;
2972 		}
2973 	} else if (gfxvidinfo.extrawidth) {
2974 		visible_left_border = max_diwlastword - w;
2975 		if (gfxvidinfo.extrawidth > 0)
2976 			visible_left_border += gfxvidinfo.extrawidth << currprefs.gfx_resolution;
2977 	} else {
2978 		if (gfxvidinfo.inxoffset < 0) {
2979 			visible_left_border = 0;
2980 		} else {
2981 			visible_left_border = gfxvidinfo.inxoffset - DISPLAY_LEFT_SHIFT;
2982 		}
2983 	}
2984 
2985 	if (visible_left_border > max_diwlastword - 32)
2986 		visible_left_border = max_diwlastword - 32;
2987 	if (visible_left_border < 0)
2988 		visible_left_border = 0;
2989 	visible_left_border &= ~((xshift (1, lores_shift)) - 1);
2990 
2991 	//write_log (_T("%d %d %d %d %d\n"), max_diwlastword, gfxvidinfo.drawbuffer.width, lores_shift, currprefs.gfx_resolution, visible_left_border);
2992 
2993 	linetoscr_x_adjust_bytes = visible_left_border * gfxvidinfo.pixbytes;
2994 
2995 	visible_right_border = visible_left_border + w;
2996 	if (visible_right_border > max_diwlastword)
2997 		visible_right_border = max_diwlastword;
2998 
2999 #ifndef __LIBRETRO__
3000 	thisframe_y_adjust = minfirstline;
3001 	if (currprefs.gfx_ycenter && thisframe_first_drawn_line >= 0 && !currprefs.gfx_filter_autoscale) {
3002 
3003 		if (thisframe_last_drawn_line - thisframe_first_drawn_line < max_drawn_amiga_line && currprefs.gfx_ycenter == 2)
3004 			thisframe_y_adjust = (thisframe_last_drawn_line - thisframe_first_drawn_line - max_drawn_amiga_line) / 2 + thisframe_first_drawn_line;
3005 		else
3006 			thisframe_y_adjust = thisframe_first_drawn_line + ((thisframe_last_drawn_line - thisframe_first_drawn_line) - max_drawn_amiga_line) / 2;
3007 
3008 		/* Would the old value be good enough? If so, leave it as it is if we want to
3009 		 * be clever. */
3010 		if (currprefs.gfx_ycenter == 2 && thisframe_y_adjust != prev_y_adjust) {
3011 			if (center_reset || (prev_y_adjust <= thisframe_first_drawn_line && prev_y_adjust + max_drawn_amiga_line > thisframe_last_drawn_line))
3012 				thisframe_y_adjust = prev_y_adjust;
3013 		}
3014 	}
3015 
3016 	/* Make sure the value makes sense */
3017 	if (thisframe_y_adjust + max_drawn_amiga_line > maxvpos_nom)
3018 		thisframe_y_adjust = maxvpos_nom - max_drawn_amiga_line;
3019 	if (thisframe_y_adjust < minfirstline)
3020 		thisframe_y_adjust = minfirstline;
3021 #endif
3022 
3023 	thisframe_y_adjust_real = thisframe_y_adjust << linedbl;
3024 	tmp = (maxvpos_nom - thisframe_y_adjust + 1) << linedbl;
3025 	if (tmp != max_ypos_thisframe) {
3026 		last_max_ypos = tmp;
3027 		if (last_max_ypos < 0)
3028 			last_max_ypos = 0;
3029 	}
3030 	max_ypos_thisframe = tmp;
3031 
3032 	/* @@@ interlace_seen used to be (bplcon0 & 4), but this is probably
3033 	 * better.  */
3034 	if (prev_x_adjust != visible_left_border || prev_y_adjust != thisframe_y_adjust)
3035 		frame_redraw_necessary |= (interlace_seen > 0 && linedbl) ? 2 : 1;
3036 
3037 	max_diwstop = 0;
3038 	min_diwstart = MAX_STOP;
3039 
3040 	gfxvidinfo.xoffset = (DISPLAY_LEFT_SHIFT << RES_MAX) + (visible_left_border << (RES_MAX - currprefs.gfx_resolution));
3041 	gfxvidinfo.yoffset = thisframe_y_adjust << VRES_MAX;
3042 	center_reset = false;
3043 }
3044 
3045 static int frame_res_cnt;
init_drawing_frame(void)3046 static void init_drawing_frame (void)
3047 {
3048 	int i, maxline;
3049 #if 1
3050 	static int frame_res_old;
3051 
3052 	if (currprefs.gfx_autoresolution && frame_res >= 0 && frame_res_lace >= 0) {
3053 		if (frame_res_cnt > 0 && frame_res_old == frame_res * 2 + frame_res_lace) {
3054 			frame_res_cnt--;
3055 			if (frame_res_cnt == 0) {
3056 				int m = frame_res * 2 + frame_res_lace;
3057 				struct wh *dst = currprefs.gfx_apmode[0].gfx_fullscreen ? &changed_prefs.gfx_size_fs : &changed_prefs.gfx_size_win;
3058 				while (m < 3 * 2) {
3059 					struct wh *src = currprefs.gfx_apmode[0].gfx_fullscreen ? &currprefs.gfx_size_fs_xtra[m] : &currprefs.gfx_size_win_xtra[m];
3060 					if ((src->width > 0 && src->height > 0) || (currprefs.gfx_api || currprefs.gfx_filter > 0)) {
3061 						int nr = m >> 1;
3062 						int nl = (m & 1) == 0 ? 0 : 1;
3063 						int nr_o = nr;
3064 						int nl_o = nl;
3065 
3066 						if (currprefs.gfx_autoresolution_minh < 0) {
3067 							if (nr < nl)
3068 								nr = nl;
3069 						} else if (nr < currprefs.gfx_autoresolution_minh) {
3070 							nr = currprefs.gfx_autoresolution_minh;
3071 						}
3072 						if (currprefs.gfx_autoresolution_minv < 0) {
3073 							if (nl < nr)
3074 								nl = nr;
3075 						} else if (nl < currprefs.gfx_autoresolution_minv) {
3076 							nl = currprefs.gfx_autoresolution_minv;
3077 						}
3078 
3079 						if (nr > gfxvidinfo.gfx_resolution_reserved)
3080 							nr = gfxvidinfo.gfx_resolution_reserved;
3081 						if (nl > gfxvidinfo.gfx_vresolution_reserved)
3082 							nl = gfxvidinfo.gfx_vresolution_reserved;
3083 
3084 						if (changed_prefs.gfx_resolution != nr || changed_prefs.gfx_vresolution != nl) {
3085 							changed_prefs.gfx_resolution = nr;
3086 							changed_prefs.gfx_vresolution = nl;
3087 							write_log (_T("RES -> %d (%d) LINE -> %d (%d) (%d - %d, %d - %d)\n"), nr, nr_o, nl, nl_o,
3088 								currprefs.gfx_autoresolution_minh, currprefs.gfx_autoresolution_minv,
3089 								gfxvidinfo.gfx_resolution_reserved, gfxvidinfo.gfx_vresolution_reserved);
3090 							config_changed = 1;
3091 							//activate_debugger ();
3092 						}
3093 						if (src->width > 0 && src->height > 0) {
3094 							if (memcmp (dst, src, sizeof *dst)) {
3095 								*dst = *src;
3096 								config_changed = 1;
3097 							}
3098 						}
3099 						break;
3100 					}
3101 					m++;
3102 				}
3103 				frame_res_cnt = currprefs.gfx_autoresolution_delay;
3104 			}
3105 		} else {
3106 			frame_res_old = frame_res * 2 + frame_res_lace;
3107 			frame_res_cnt = currprefs.gfx_autoresolution_delay;
3108 			if (frame_res_cnt <= 0)
3109 				frame_res_cnt = 1;
3110 		}
3111 	}
3112 	frame_res = -1;
3113 	frame_res_lace = 0;
3114 
3115 	if (can_use_lores > AUTO_LORES_FRAMES && 0) {
3116 		lores_factor = 1;
3117 		lores_shift = 0;
3118 	} else {
3119 		can_use_lores++;
3120 		lores_reset ();
3121 	}
3122 #endif
3123 
3124 	init_hardware_for_drawing_frame ();
3125 
3126 	if (thisframe_first_drawn_line < 0)
3127 		thisframe_first_drawn_line = minfirstline;
3128 	if (thisframe_first_drawn_line > thisframe_last_drawn_line)
3129 		thisframe_last_drawn_line = thisframe_first_drawn_line;
3130 
3131 	maxline = ((maxvpos_nom + 1) << linedbl) + 2;
3132 #ifdef SMART_UPDATE
3133 	for (i = 0; i < maxline; i++) {
3134 		switch (linestate[i]) {
3135 		case LINE_DONE_AS_PREVIOUS:
3136 			linestate[i] = LINE_REMEMBERED_AS_PREVIOUS;
3137 			break;
3138 		case LINE_REMEMBERED_AS_BLACK:
3139 			break;
3140 		default:
3141 			linestate[i] = LINE_UNDECIDED;
3142 			break;
3143 		}
3144 	}
3145 #else
3146 	memset (linestate, LINE_UNDECIDED, maxline);
3147 #endif
3148 	last_drawn_line = 0;
3149 	first_drawn_line = 32767;
3150 
3151 	first_block_line = last_block_line = NO_BLOCK;
3152 	if (frame_redraw_necessary)
3153 		frame_redraw_necessary--;
3154 
3155 	center_image ();
3156 
3157 	thisframe_first_drawn_line = -1;
3158 	thisframe_last_drawn_line = -1;
3159 
3160 	drawing_color_matches = -1;
3161 }
3162 
putpixel(uae_u8 * buf,int bpp,int x,xcolnr c8,int opaq)3163 void putpixel (uae_u8 *buf, int bpp, int x, xcolnr c8, int opaq)
3164 {
3165 	if (x <= 0)
3166 		return;
3167 
3168 	switch (bpp) {
3169 	case 1:
3170 		buf[x] = (uae_u8)c8;
3171 		break;
3172 	case 2:
3173 		{
3174 			uae_u16 *p = (uae_u16*)buf + x;
3175 			*p = (uae_u16)c8;
3176 			break;
3177 		}
3178 	case 3:
3179 		/* no 24 bit yet */
3180 		break;
3181 	case 4:
3182 		{
3183 			int i;
3184 			if (1 || opaq || currprefs.gfx_filter == 0) {
3185 				uae_u32 *p = (uae_u32*)buf + x;
3186 				*p = c8;
3187 			} else {
3188 				for (i = 0; i < 4; i++) {
3189 					int v1 = buf[i + bpp * x];
3190 					int v2 = (c8 >> (i * 8)) & 255;
3191 					v1 = (v1 * 2 + v2 * 3) / 5;
3192 					if (v1 > 255)
3193 						v1 = 255;
3194 					buf[i + bpp * x] = v1;
3195 				}
3196 			}
3197 			break;
3198 		}
3199 	}
3200 }
3201 
draw_status_line(int line,int statusy)3202 static void draw_status_line (int line, int statusy)
3203 {
3204 /* REMOVEME:
3205  * nowhere used
3206  */
3207 #if 0
3208 	int y;
3209 #endif
3210 	int bpp;
3211 	uae_u8 *buf;
3212 
3213 	if (!(currprefs.leds_on_screen & STATUSLINE_CHIPSET) || (currprefs.leds_on_screen & STATUSLINE_TARGET))
3214 		return;
3215 	bpp = gfxvidinfo.pixbytes;
3216 /* REMOVEME:
3217  * nowhere used
3218  */
3219 #if 0
3220 	y = line - (gfxvidinfo.outheight - TD_TOTAL_HEIGHT);
3221 #endif
3222 	xlinebuffer = gfxvidinfo.linemem;
3223 	if (xlinebuffer == 0)
3224 		xlinebuffer = row_map[line];
3225 	buf = xlinebuffer;
3226 	draw_status_line_single (buf, bpp, statusy, gfxvidinfo.outwidth, xredcolors, xgreencolors, xbluecolors, NULL);
3227 }
3228 
draw_debug_status_line(int line)3229 static void draw_debug_status_line (int line)
3230 {
3231 	xlinebuffer = gfxvidinfo.linemem;
3232 	if (xlinebuffer == 0)
3233 		xlinebuffer = row_map[line];
3234 	debug_draw_cycles (xlinebuffer, gfxvidinfo.pixbytes, line, gfxvidinfo.outwidth, gfxvidinfo.outheight, xredcolors, xgreencolors, xbluecolors);
3235 }
3236 
3237 #define LIGHTPEN_HEIGHT 12
3238 #define LIGHTPEN_WIDTH 17
3239 
3240 /* UNUSED:
3241  * only used by lightpen_update(), which is unused since its
3242  * call in finish_drawing_frame() is marked "if 0".
3243  */
3244 #if 0
3245 static const char *lightpen_cursor = {
3246 	"------.....------"
3247 	"------.xxx.------"
3248 	"------.xxx.------"
3249 	"------.xxx.------"
3250 	".......xxx......."
3251 	".xxxxxxxxxxxxxxx."
3252 	".xxxxxxxxxxxxxxx."
3253 	".......xxx......."
3254 	"------.xxx.------"
3255 	"------.xxx.------"
3256 	"------.xxx.------"
3257 	"------.....------"
3258 };
3259 
3260 static void draw_lightpen_cursor (int x, int y, int line, int onscreen)
3261 {
3262 	int i;
3263 	const char *p;
3264 	int color1 = onscreen ? 0xff0 : 0xf00;
3265 	int color2 = 0x000;
3266 
3267 	xlinebuffer = gfxvidinfo.linemem;
3268 	if (xlinebuffer == 0)
3269 		xlinebuffer = row_map[line];
3270 
3271 	p = lightpen_cursor + y * LIGHTPEN_WIDTH;
3272 	for (i = 0; i < LIGHTPEN_WIDTH; i++) {
3273 		int xx = x + i - LIGHTPEN_WIDTH / 2;
3274 		if (*p != '-' && xx >= 0 && xx < gfxvidinfo.outwidth)
3275 			putpixel (xlinebuffer, gfxvidinfo.pixbytes, xx, *p == 'x' ? xcolors[color1] : xcolors[color2], 1);
3276 		p++;
3277 	}
3278 }
3279 #endif
3280 
3281 static int lightpen_y1, lightpen_y2;
3282 
3283 /* UNUSED:
3284  * the only call is in finish_drawing_frame(), but
3285  * it has been marked out with "if 0"
3286  */
3287 #if 0
3288 static void lightpen_update (void)
3289 {
3290 	int i;
3291 
3292 	if (lightpen_x < LIGHTPEN_WIDTH + 1)
3293 		lightpen_x = LIGHTPEN_WIDTH + 1;
3294 	if (lightpen_x >= gfxvidinfo.inwidth - LIGHTPEN_WIDTH - 1)
3295 		lightpen_x = gfxvidinfo.inwidth - LIGHTPEN_WIDTH - 2;
3296 	if (lightpen_y < LIGHTPEN_HEIGHT + 1)
3297 		lightpen_y = LIGHTPEN_HEIGHT + 1;
3298 	if (lightpen_y >= gfxvidinfo.inheight - LIGHTPEN_HEIGHT - 1)
3299 		lightpen_y = gfxvidinfo.inheight - LIGHTPEN_HEIGHT - 2;
3300 	if (lightpen_y >= max_ypos_thisframe - LIGHTPEN_HEIGHT - 1)
3301 		lightpen_y = max_ypos_thisframe - LIGHTPEN_HEIGHT - 2;
3302 
3303 	lightpen_cx = (((lightpen_x + visible_left_border) >> lores_shift) >> 1) + DISPLAY_LEFT_SHIFT - DIW_DDF_OFFSET;
3304 
3305 	lightpen_cy = lightpen_y;
3306 	lightpen_cy >>= linedbl;
3307 	lightpen_cy += minfirstline;
3308 
3309 	if (lightpen_cx < 0x18)
3310 		lightpen_cx = 0x18;
3311 	if (lightpen_cx >= maxhpos)
3312 		lightpen_cx -= maxhpos;
3313 	if (lightpen_cy < minfirstline)
3314 		lightpen_cy = minfirstline;
3315 	if (lightpen_cy >= maxvpos)
3316 		lightpen_cy = maxvpos - 1;
3317 
3318 	for (i = 0; i < LIGHTPEN_HEIGHT; i++) {
3319 		int line = lightpen_y + i - LIGHTPEN_HEIGHT / 2;
3320 		if (line >= 0 || line < max_ypos_thisframe) {
3321 			if (lightpen_active > 0)
3322 				draw_lightpen_cursor (lightpen_x, i, line, lightpen_cx > 0);
3323 			flush_line (line);
3324 		}
3325 	}
3326 	lightpen_y1 = lightpen_y - LIGHTPEN_HEIGHT / 2 - 1 + min_ypos_for_screen;
3327 	lightpen_y2 = lightpen_y1 + LIGHTPEN_HEIGHT + 2;
3328 
3329 	if (lightpen_active < 0)
3330 		lightpen_active = 0;
3331 }
3332 #endif
3333 
draw_frame2(void)3334 static void draw_frame2 (void)
3335 {
3336 	for (int i = 0; i < max_ypos_thisframe; i++) {
3337 		int i1 = i + min_ypos_for_screen;
3338 		int line = i + thisframe_y_adjust_real;
3339 		int where2;
3340 
3341 		where2 = amiga2aspect_line_map[i1];
3342 		if (where2 >= gfxvidinfo.inheight)
3343 			break;
3344 		if (where2 < 0)
3345 			continue;
3346 		hposblank = 0;
3347 		pfield_draw_line (line, where2, amiga2aspect_line_map[i1 + 1]);
3348 	}
3349 #if 0
3350 	/* clear possible old garbage at the bottom if emulated area become smaller */
3351 	for (i = last_max_ypos; i < gfxvidinfo.outheight; i++) {
3352 		int i1 = i + min_ypos_for_screen;
3353 		int line = i + thisframe_y_adjust_real;
3354 		int where2 = amiga2aspect_line_map[i1];
3355 
3356 		if (where2 >= gfxvidinfo.outheight)
3357 			break;
3358 		if (where2 < 0)
3359 			continue;
3360 
3361 		hposblank = i > last_max_ypos || i >= max_ypos_thisframe;
3362 
3363 		xlinebuffer = gfxvidinfo.linemem;
3364 		if (xlinebuffer == 0)
3365 			xlinebuffer = row_map[where2];
3366 		xlinebuffer -= linetoscr_x_adjust_bytes;
3367 		fill_line ();
3368 		if (line < max_ypos_thisframe)
3369 			linestate[line] = LINE_UNDECIDED;
3370 		do_flush_line (where2);
3371 	}
3372 #endif
3373 }
3374 
draw_frame(struct vidbuffer * vb)3375 bool draw_frame (struct vidbuffer *vb)
3376 {
3377 	uae_u8 oldstate[LINESTATE_SIZE];
3378 
3379 	init_row_map ();
3380 	memcpy (oldstate, linestate, LINESTATE_SIZE);
3381 	for (int i = 0; i < LINESTATE_SIZE; i++) {
3382 		uae_u8 v = linestate[i];
3383 		if (v == LINE_REMEMBERED_AS_PREVIOUS) {
3384 			linestate[i - 1] = LINE_DECIDED_DOUBLE;
3385 			v = LINE_AS_PREVIOUS;
3386 		} else if (v == LINE_DONE_AS_PREVIOUS) {
3387 			linestate[i - 1] = LINE_DECIDED_DOUBLE;
3388 			v = LINE_AS_PREVIOUS;
3389 		} else if (v == LINE_REMEMBERED_AS_BLACK) {
3390 			v = LINE_BLACK;
3391 		} else if (v == LINE_DONE) {
3392 			v = LINE_DECIDED;
3393 		}
3394 		linestate[i] = v;
3395 	}
3396 	last_drawn_line = 0;
3397 	first_drawn_line = 32767;
3398 	drawing_color_matches = -1;
3399 	draw_frame2 ();
3400 	last_drawn_line = 0;
3401 	first_drawn_line = 32767;
3402 	drawing_color_matches = -1;
3403 	memcpy (linestate, oldstate, LINESTATE_SIZE);
3404 	init_row_map ();
3405 	return true;
3406 }
3407 
finish_drawing_frame(void)3408 void finish_drawing_frame (void)
3409 {
3410 	int i;
3411 	bool didflush = false;
3412 
3413 	// Leave if the screen isn't allocated, yet:
3414 	if (0 == gfxvidinfo.height_allocated)
3415 		return;
3416 
3417 	if (! lockscr ()) {
3418 		notice_screen_contents_lost ();
3419 		return;
3420 	}
3421 
3422 #ifndef SMART_UPDATE
3423 	/* @@@ This isn't exactly right yet. FIXME */
3424 	if (!interlace_seen)
3425 		do_flush_screen (first_drawn_line, last_drawn_line);
3426 	else
3427 		unlockscr ();
3428 	return;
3429 #endif
3430 
3431 	draw_frame2 ();
3432 
3433 	if (currprefs.leds_on_screen) {
3434 		int slx, sly;
3435 		statusline_getpos (&slx, &sly, gfxvidinfo.outwidth, gfxvidinfo.outheight);
3436 		for (i = 0; i < TD_TOTAL_HEIGHT; i++) {
3437 			int line = sly + i;
3438 			draw_status_line (line, i);
3439 			do_flush_line (line);
3440 		}
3441 	}
3442 #ifdef DEBUGGER
3443 	if (debug_dma > 1) {
3444 		for (i = 0; i < gfxvidinfo.outheight; i++) {
3445 			int line = i;
3446 			draw_debug_status_line (line);
3447 			do_flush_line (line);
3448 		}
3449 	}
3450 #endif
3451 
3452 /* UNUSED:
3453  *
3454  */
3455 #if 0
3456 	if (lightpen_active)
3457 		lightpen_update ();
3458 #endif
3459 
3460 /*	if (currprefs.monitoremu && gfxvidinfo.tempbuffer.bufmem_allocated) {
3461 		static bool specialon;
3462 		if (emulate_specialmonitors (vb, &gfxvidinfo.tempbuffer)) {
3463 			vb = gfxvidinfo.outbuffer = &gfxvidinfo.tempbuffer;
3464 			if (vb->nativepositioning) {
3465 				vb->inwidth = gfxvidinfo.drawbuffer.inwidth;
3466 				vb->inheight = gfxvidinfo.drawbuffer.inheight;
3467 				vb->inwidth2 = gfxvidinfo.drawbuffer.inwidth2;
3468 				vb->inheight2 = gfxvidinfo.drawbuffer.inheight2;
3469 				vb->outwidth = gfxvidinfo.drawbuffer.outwidth;
3470 				vb->outheight = gfxvidinfo.drawbuffer.outheight;
3471 			}
3472 			gfxvidinfo.drawbuffer.tempbufferinuse = true;
3473 			if (!specialmonitoron)
3474 				compute_framesync ();
3475 			specialmonitoron = true;
3476 			do_flush_screen (vb, 0, vb->outheight);
3477 			didflush = true;
3478 		} else {
3479 			gfxvidinfo.drawbuffer.tempbufferinuse = false;
3480 			if (specialmonitoron)
3481 				compute_framesync ();
3482 			specialmonitoron = false;
3483 		}
3484         }*/
3485 
3486 	if (!didflush)
3487 		do_flush_screen (first_drawn_line, last_drawn_line);
3488 }
3489 
hardware_line_completed(int lineno)3490 void hardware_line_completed (int lineno)
3491 {
3492 #ifndef SMART_UPDATE
3493 	{
3494 		int i, where;
3495 		/* l is the line that has been finished for drawing. */
3496 		i = lineno - thisframe_y_adjust_real;
3497 		if (i >= 0 && i < max_ypos_thisframe) {
3498 			where = amiga2aspect_line_map[i+min_ypos_for_screen];
3499 			if (where < gfxvidinfo.outheight && where >= 0)
3500 				pfield_draw_line (lineno, where, amiga2aspect_line_map[i+min_ypos_for_screen+1]);
3501 		}
3502 	}
3503 #endif
3504 }
3505 
check_picasso(void)3506 void check_picasso (void)
3507 {
3508 #ifdef PICASSO96
3509 	if (picasso_on && picasso_redraw_necessary)
3510 		picasso_refresh ();
3511 	picasso_redraw_necessary = 0;
3512 
3513 	if (picasso_requested_on == picasso_on)
3514 		return;
3515 
3516 	picasso_on = picasso_requested_on;
3517 
3518 	if (!picasso_on)
3519 		clear_inhibit_frame (IHF_PICASSO);
3520 	else
3521 		set_inhibit_frame (IHF_PICASSO);
3522 
3523 	gfx_set_picasso_state (picasso_on);
3524 	picasso_enablescreen (picasso_requested_on);
3525 
3526 	notice_screen_contents_lost ();
3527 	notice_new_xcolors ();
3528 	count_frame ();
3529 #endif
3530 }
3531 
redraw_frame(void)3532 void redraw_frame (void)
3533 {
3534 	last_drawn_line = 0;
3535 	first_drawn_line = 32767;
3536 	finish_drawing_frame ();
3537 	flush_screen (0, 0);
3538 }
3539 
vsync_handle_check(void)3540 bool vsync_handle_check (void)
3541 {
3542 	int changed = check_prefs_changed_gfx ();
3543 	if (changed > 0) {
3544 		reset_drawing ();
3545 		init_row_map ();
3546 		init_aspect_maps ();
3547 		notice_screen_contents_lost ();
3548 		notice_new_xcolors ();
3549 	} else if (changed < 0) {
3550 		reset_drawing ();
3551 		init_row_map ();
3552 		init_aspect_maps ();
3553 		notice_screen_contents_lost ();
3554 		notice_new_xcolors ();
3555 	}
3556 	check_prefs_changed_audio ();
3557 #ifdef SCSI
3558 	check_prefs_changed_cd ();
3559 #endif
3560 	check_prefs_changed_custom ();
3561 	check_prefs_changed_cpu ();
3562 	check_picasso ();
3563 	return changed != 0;
3564 }
3565 
vsync_handle_redraw(int long_frame,int lof_changed,uae_u16 bplcon0p,uae_u16 bplcon3p)3566 void vsync_handle_redraw (int long_frame, int lof_changed, uae_u16 bplcon0p, uae_u16 bplcon3p)
3567 {
3568 	last_redraw_point++;
3569 	if (lof_changed || interlace_seen <= 0 || last_redraw_point >= 2 || long_frame || doublescan < 0) {
3570 		last_redraw_point = 0;
3571 
3572 		if (framecnt == 0)
3573 			finish_drawing_frame ();
3574 #if 0
3575 		if (interlace_seen > 0) {
3576 			interlace_seen = -1;
3577 		} else if (interlace_seen == -1) {
3578 			interlace_seen = 0;
3579 			if (currprefs.gfx_scandoubler && currprefs.gfx_vresolution)
3580 				notice_screen_contents_lost ();
3581 		}
3582 #endif
3583 
3584 		if (quit_program < 0) {
3585 #ifdef SAVESTATE
3586 			if (!savestate_state) {
3587 				if (currprefs.quitstatefile[0]) {
3588 					savestate_initsave (currprefs.quitstatefile, 1, 1, true);
3589 					save_state (currprefs.quitstatefile, _T(""));
3590 				}
3591 			}
3592 #endif
3593 			quit_program = -quit_program;
3594 			set_inhibit_frame (IHF_QUIT_PROGRAM);
3595 			set_special (SPCFLAG_BRK);
3596 			return;
3597 		}
3598 
3599 		count_frame ();
3600 
3601 		if (framecnt == 0)
3602 			init_drawing_frame ();
3603 		else if (currprefs.cpu_cycle_exact)
3604 			init_hardware_for_drawing_frame ();
3605 	} else {
3606 		if (isvsync_chipset ())
3607 			flush_screen (0, 0); /* vsync mode */
3608 	}
3609 
3610 	gui_flicker_led (-1, 0, 0);
3611 #ifdef AVIOUTPUT
3612 	if (!picasso_on)
3613 		frame_drawn ();
3614 #endif
3615 }
3616 
hsync_record_line_state(int lineno,enum nln_how how,int changed)3617 void hsync_record_line_state (int lineno, enum nln_how how, int changed)
3618 {
3619 	uae_u8 *state;
3620 
3621 	if (framecnt != 0)
3622 		return;
3623 
3624 	state = linestate + lineno;
3625 	changed += frame_redraw_necessary + ((lineno >= lightpen_y1 && lineno <= lightpen_y2) ? 1 : 0);
3626 
3627 	switch (how) {
3628 	case nln_normal:
3629 		*state = changed ? LINE_DECIDED : LINE_DONE;
3630 		break;
3631 	case nln_doubled:
3632 		*state = changed ? LINE_DECIDED_DOUBLE : LINE_DONE;
3633 		changed += state[1] != LINE_REMEMBERED_AS_PREVIOUS;
3634 		state[1] = changed ? LINE_AS_PREVIOUS : LINE_DONE_AS_PREVIOUS;
3635 		break;
3636 	case nln_nblack:
3637 		*state = changed ? LINE_DECIDED : LINE_DONE;
3638 		if (state[1] != LINE_REMEMBERED_AS_BLACK)
3639 			state[1] = LINE_BLACK;
3640 		break;
3641 	case nln_lower:
3642 		if (state[-1] == LINE_UNDECIDED)
3643 			state[-1] = LINE_DECIDED; //LINE_BLACK;
3644 		*state = changed ? LINE_DECIDED : LINE_DONE;
3645 		break;
3646 	case nln_upper:
3647 		*state = changed ? LINE_DECIDED : LINE_DONE;
3648 		if (state[1] == LINE_UNDECIDED
3649 			|| state[1] == LINE_REMEMBERED_AS_PREVIOUS
3650 			|| state[1] == LINE_AS_PREVIOUS)
3651 			state[1] = LINE_DECIDED; //LINE_BLACK;
3652 		break;
3653 	}
3654 }
3655 
3656 /* REMOVEME:
3657  * nowhere used
3658  */
3659 #if 0
3660 static void dummy_flush_line (struct vidbuf_description *gfxinfo, int line_no)
3661 {
3662 }
3663 
3664 static void dummy_flush_block (struct vidbuf_description *gfxinfo, int first_line, int last_line)
3665 {
3666 }
3667 
3668 static void dummy_flush_screen (struct vidbuf_description *gfxinfo, int first_line, int last_line)
3669 {
3670 }
3671 
3672 static void dummy_flush_clear_screen (struct vidbuf_description *gfxinfo)
3673 {
3674 }
3675 
3676 static int  dummy_lock (struct vidbuf_description *gfxinfo)
3677 {
3678 	return 1;
3679 }
3680 
3681 static void dummy_unlock (struct vidbuf_description *gfxinfo)
3682 {
3683 }
3684 
3685 static void gfxbuffer_reset (void)
3686 {
3687 	gfxvidinfo.flush_line         = dummy_flush_line;
3688 	gfxvidinfo.flush_block        = dummy_flush_block;
3689 	gfxvidinfo.flush_screen       = dummy_flush_screen;
3690 	gfxvidinfo.flush_clear_screen = dummy_flush_clear_screen;
3691 	gfxvidinfo.lockscr            = dummy_lock;
3692 	gfxvidinfo.unlockscr          = dummy_unlock;
3693 }
3694 #endif
3695 
notice_resolution_seen(int res,bool lace)3696 void notice_resolution_seen (int res, bool lace)
3697 {
3698 	if (res > frame_res)
3699 		frame_res = res;
3700 	if (res > 0)
3701 		can_use_lores = 0;
3702 	if (!frame_res_lace && lace)
3703 		frame_res_lace = lace;
3704 }
3705 
notice_interlace_seen(bool lace)3706 bool notice_interlace_seen (bool lace)
3707 {
3708 	bool changed = false;
3709 	// non-lace to lace switch (non-lace active at least one frame)?
3710 	if (lace) {
3711 		if (interlace_seen == 0) {
3712 			changed = true;
3713 			//write_log (_T("->lace PC=%x\n"), m68k_getpc ());
3714 		}
3715 		interlace_seen = currprefs.gfx_vresolution ? 1 : -1;
3716 	} else {
3717 		if (interlace_seen) {
3718 			changed = true;
3719 			//write_log (_T("->non-lace PC=%x\n"), m68k_getpc ());
3720 		}
3721 		interlace_seen = 0;
3722 	}
3723 	return changed;
3724 }
3725 
reset_drawing(void)3726 void reset_drawing (void)
3727 {
3728 	max_diwstop = 0;
3729 
3730 	lores_reset ();
3731 
3732 	reset_decision_table ();
3733 
3734 	init_aspect_maps ();
3735 
3736 	init_row_map ();
3737 
3738 	last_redraw_point = 0;
3739 
3740 	memset (spixels, 0, sizeof spixels);
3741 	memset (&spixstate, 0, sizeof spixstate);
3742 
3743 	init_drawing_frame ();
3744 
3745 	notice_screen_contents_lost ();
3746 	frame_res_cnt = currprefs.gfx_autoresolution_delay;
3747 	lightpen_y1 = lightpen_y2 = -1;
3748 
3749 	reset_custom_limits ();
3750 
3751 //	clearbuffer (&gfxvidinfo.drawbuffer);
3752 //	clearbuffer (&gfxvidinfo.tempbuffer);
3753 
3754 	center_reset = true;
3755 	specialmonitoron = false;
3756 }
3757 
drawing_init(void)3758 void drawing_init (void)
3759 {
3760 	gen_pfield_tables ();
3761 
3762 	uae_sem_init (&gui_sem, 0, 1);
3763 #ifdef PICASSO96
3764 	if (!isrestore ()) {
3765 		picasso_on = 0;
3766 		picasso_requested_on = 0;
3767 		gfx_set_picasso_state (0);
3768 	}
3769 #endif
3770 	xlinebuffer = gfxvidinfo.bufmem;
3771 
3772 	inhibit_frame = 0;
3773 
3774 /* REMOVEME
3775  * orphaned
3776  */
3777 #if 0
3778 //	gfxbuffer_reset ();
3779 #endif
3780 	reset_drawing ();
3781 }
3782 
isvsync_chipset(void)3783 int isvsync_chipset (void)
3784 {
3785 	if (picasso_on || !currprefs.gfx_apmode[0].gfx_vsync || (currprefs.gfx_apmode[0].gfx_vsync == 0 && !currprefs.gfx_apmode[0].gfx_fullscreen))
3786 		return 0;
3787 	if (currprefs.gfx_apmode[0].gfx_vsyncmode == 0)
3788 		return 1;
3789 	if (currprefs.m68k_speed >= 0)
3790 		return -1;
3791 	return currprefs.cachesize ? -3 : -2;
3792 }
3793 
isvsync_rtg(void)3794 int isvsync_rtg (void)
3795 {
3796 	if (!picasso_on || !currprefs.gfx_apmode[1].gfx_vsync || (currprefs.gfx_apmode[1].gfx_vsync == 0 && !currprefs.gfx_apmode[1].gfx_fullscreen))
3797 		return 0;
3798 	if (currprefs.gfx_apmode[1].gfx_vsyncmode == 0)
3799 		return 1;
3800 	if (currprefs.m68k_speed >= 0)
3801 		return -1;
3802 	return currprefs.cachesize ? -3 : -2;
3803 }
3804 
isvsync(void)3805 int isvsync (void)
3806 {
3807 	if (picasso_on)
3808 		return isvsync_rtg ();
3809 	else
3810 		return isvsync_chipset ();
3811 }
3812