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