1 /*
2 * UAE - The Un*x Amiga Emulator
3 *
4 * Custom chip emulation
5 *
6 * Copyright 1995-2002 Bernd Schmidt
7 * Copyright 1995 Alessandro Bissacco
8 * Copyright 2000-2015 Toni Wilen
9 */
10 
11 #include "sysconfig.h"
12 #include "sysdeps.h"
13 
14 #include <ctype.h>
15 #include <assert.h>
16 #include <math.h>
17 
18 #include "options.h"
19 #include "uae.h"
20 #include "gensound.h"
21 #include "audio.h"
22 #include "sounddep/sound.h"
23 #include "events.h"
24 #include "uae/memory.h"
25 #include "custom.h"
26 #include "newcpu.h"
27 #include "cia.h"
28 #include "disk.h"
29 #include "blitter.h"
30 #include "xwin.h"
31 #include "inputdevice.h"
32 #include "serial.h"
33 #include "autoconf.h"
34 #include "traps.h"
35 #include "gui.h"
36 #include "picasso96.h"
37 #include "drawing.h"
38 #include "savestate.h"
39 #include "ar.h"
40 #include "debug.h"
41 #if defined(ENFORCER)
42 #include "enforcer.h"
43 #endif
44 #include "threaddep/thread.h"
45 #include "luascript.h"
46 #include "devices.h"
47 #include "rommgr.h"
48 #include "specialmonitors.h"
49 
50 #define CUSTOM_DEBUG 0
51 #define SPRITE_DEBUG 0
52 #define SPRITE_DEBUG_MINY 0
53 #define SPRITE_DEBUG_MAXY 0x30
54 #define SPR0_HPOS 0x15
55 #define MAX_SPRITES 8
56 #define SPEEDUP 1
57 #define AUTOSCALE_SPRITES 1
58 
59 #define SPRBORDER 0
60 
61 extern uae_u16 serper;
62 
63 #ifdef FSUAE // NL
64 #include <fs/emu/hacks.h>
65 int g_frame_debug_logging = 0;
66 #endif
67 
nocustom(void)68 STATIC_INLINE bool nocustom (void)
69 {
70 	if (picasso_on && currprefs.picasso96_nocustom)
71 		return true;
72 	return false;
73 }
74 
uae_abort(const TCHAR * format,...)75 static void uae_abort (const TCHAR *format,...)
76 {
77 	static int nomore;
78 	va_list parms;
79 	TCHAR buffer[1000];
80 
81 	va_start (parms, format);
82 	_vsntprintf (buffer, sizeof (buffer) - 1, format, parms );
83 	va_end (parms);
84 	if (nomore) {
85 		write_log (_T("%s\n"), buffer);
86 		return;
87 	}
88 	gui_message (buffer);
89 	nomore = 1;
90 }
91 
92 #if 0
93 void customhack_put (struct customhack *ch, uae_u16 v, int hpos)
94 {
95 	ch->v = v;
96 	ch->vpos = vpos;
97 	ch->hpos = hpos;
98 }
99 
100 uae_u16 customhack_get (struct customhack *ch, int hpos)
101 {
102 	if (ch->vpos == vpos && ch->hpos == hpos) {
103 		ch->vpos = -1;
104 		return 0xffff;
105 	}
106 	return ch->v;
107 }
108 #endif
109 
110 static unsigned int n_consecutive_skipped = 0;
111 static unsigned int total_skipped = 0;
112 
113 STATIC_INLINE void sync_copper (int hpos);
114 
115 
116 /* Events */
117 
118 unsigned long int vsync_cycles;
119 static int extra_cycle;
120 
121 static int rpt_did_reset;
122 struct ev eventtab[ev_max];
123 struct ev2 eventtab2[ev2_max];
124 
125 int hpos_offset;
126 int vpos;
127 static int vpos_count, vpos_count_diff;
128 int lof_store; // real bit in custom registers
129 static int lof_current; // what display device thinks
130 static bool lof_lastline, lof_prev_lastline;
131 static int lol;
132 static int next_lineno, prev_lineno;
133 static enum nln_how nextline_how;
134 static int lof_changed = 0, lof_changing = 0, interlace_changed = 0;
135 static int lof_changed_previous_field;
136 static int vposw_change;
137 static bool lof_lace;
138 static bool bplcon0_interlace_seen;
139 static int scandoubled_line;
140 static bool vsync_rendered, frame_rendered, frame_shown;
141 static int vsynctimeperline;
142 static int frameskiptime;
143 static bool genlockhtoggle;
144 static bool genlockvtoggle;
145 static bool graphicsbuffer_retry;
146 static int scanlinecount;
147 
148 #ifdef FSUAE // NL
149 int g_uae_min_first_line_pal = VBLANK_ENDLINE_PAL;
150 int g_uae_min_first_line_ntsc = VBLANK_ENDLINE_NTSC;
151 #endif
152 
153 #define LOF_TOGGLES_NEEDED 3
154 //#define NLACE_CNT_NEEDED 50
155 static int lof_togglecnt_lace, lof_togglecnt_nlace; //, nlace_cnt;
156 
157 /* Stupid genlock-detection prevention hack.
158 * We should stop calling vsync_handler() and
159 * hstop_handler() completely but it is not
160 * worth the trouble..
161 */
162 static int vpos_previous, hpos_previous;
163 static int vpos_lpen, hpos_lpen, lightpen_triggered;
164 int lightpen_x = -1, lightpen_y = -1, lightpen_cx, lightpen_cy, lightpen_active, lightpen_enabled;
165 
166 static uae_u32 sprtaba[256],sprtabb[256];
167 static uae_u32 sprite_ab_merge[256];
168 /* Tables for collision detection.  */
169 static uae_u32 sprclx[16], clxmask[16];
170 
171 /* T genlock bit in ECS Denise and AGA color registers */
172 static uae_u8 color_regs_genlock[256];
173 
174 /*
175 * Hardware registers of all sorts.
176 */
177 
178 static int REGPARAM3 custom_wput_1 (int, uaecptr, uae_u32, int) REGPARAM;
179 
180 static uae_u16 cregs[256];
181 
182 uae_u16 intena, intreq;
183 uae_u16 dmacon;
184 uae_u16 adkcon; /* used by audio code */
185 uae_u32 last_custom_value1;
186 
187 static uae_u32 cop1lc, cop2lc, copcon;
188 
189 int maxhpos = MAXHPOS_PAL;
190 int maxhpos_short = MAXHPOS_PAL;
191 int maxvpos = MAXVPOS_PAL;
192 int maxvpos_nom = MAXVPOS_PAL; // nominal value (same as maxvpos but "faked" maxvpos in fake 60hz modes)
193 int maxvpos_display = MAXVPOS_PAL; // value used for display size
194 int hsyncendpos, hsyncstartpos;
195 static int maxvpos_total = 511;
196 int minfirstline = VBLANK_ENDLINE_PAL;
197 int firstblankedline;
198 static int equ_vblank_endline = EQU_ENDLINE_PAL;
199 static bool equ_vblank_toggle = true;
200 double vblank_hz = VBLANK_HZ_PAL, fake_vblank_hz, vblank_hz_stored, vblank_hz_nom;
201 double hblank_hz;
202 static float vblank_hz_lof, vblank_hz_shf, vblank_hz_lace;
203 static int vblank_hz_mult, vblank_hz_state;
204 static struct chipset_refresh *stored_chipset_refresh;
205 int doublescan;
206 bool programmedmode;
207 int syncbase;
208 static int fmode_saved, fmode;
209 uae_u16 beamcon0, new_beamcon0;
210 static bool varsync_changed;
211 uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL;
212 static int maxvpos_stored, maxhpos_stored;
213 static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter;
214 static int ciavsyncmode;
215 static int diw_hstrt, diw_hstop;
216 static int diw_hcounter;
217 static uae_u16 refptr;
218 static uae_u32 refptr_val;
219 
220 #define HSYNCTIME (maxhpos * CYCLE_UNIT)
221 
222 struct sprite {
223 	uaecptr pt;
224 	int xpos;
225 	int vstart;
226 	int vstop;
227 	int dblscan; /* AGA SSCAN2 */
228 	int armed;
229 	int dmastate;
230 	int dmacycle;
231 	int ptxhpos;
232 	int ptxhpos2, ptxvpos2;
233 	bool ignoreverticaluntilnextline;
234 };
235 
236 static struct sprite spr[MAX_SPRITES];
237 static int plfstrt_sprite;
238 static bool sprite_ignoreverticaluntilnextline;
239 
240 uaecptr sprite_0;
241 int sprite_0_width, sprite_0_height, sprite_0_doubled;
242 uae_u32 sprite_0_colors[4];
243 static uae_u8 magic_sprite_mask = 0xff;
244 
245 static int sprite_vblank_endline = VBLANK_SPRITE_PAL;
246 
247 static uae_u16 sprctl[MAX_SPRITES], sprpos[MAX_SPRITES];
248 #ifdef AGA
249 static uae_u16 sprdata[MAX_SPRITES][4], sprdatb[MAX_SPRITES][4];
250 #else
251 static uae_u16 sprdata[MAX_SPRITES][1], sprdatb[MAX_SPRITES][1];
252 #endif
253 static int sprite_last_drawn_at[MAX_SPRITES];
254 static int last_sprite_point, nr_armed;
255 static int sprite_width, sprres;
256 static int sprite_sprctlmask;
257 int sprite_buffer_res;
258 
259 #ifdef CPUEMU_13
260 uae_u8 cycle_line[256 + 1];
261 #endif
262 
263 static bool bpl1dat_written, bpl1dat_written_at_least_once;
264 static bool bpldmawasactive;
265 static uae_s16 bpl1mod, bpl2mod, dbpl1mod, dbpl2mod;
266 static int dbpl1mod_on, dbpl2mod_on;
267 static uaecptr prevbpl[2][MAXVPOS][8];
268 static uaecptr bplpt[8], bplptx[8];
269 #if 0
270 static uaecptr dbplptl[8], dbplpth[8];
271 static int dbplptl_on[8], dbplpth_on[8], dbplptl_on2, dbplpth_on2;
272 #endif
273 static int bitplane_line_crossing;
274 
275 static struct color_entry current_colors;
276 unsigned int bplcon0;
277 static unsigned int bplcon1, bplcon2, bplcon3, bplcon4;
278 static unsigned int bplcon0d, bplcon0dd, bplcon0_res, bplcon0_planes, bplcon0_planes_limit;
279 static unsigned int diwstrt, diwstop, diwhigh;
280 static int diwhigh_written;
281 static unsigned int ddfstrt, ddfstop;
282 static int line_cyclebased, badmode, diw_change;
283 static int bplcon1_fetch;
284 static int hpos_is_zero_bplcon1_hack = -1;
285 
286 #define SET_LINE_CYCLEBASED line_cyclebased = 2;
287 
288 /* The display and data fetch windows */
289 
290 enum diw_states
291 {
292 	DIW_waiting_start, DIW_waiting_stop
293 };
294 
295 static int plffirstline, plflastline;
296 int plffirstline_total, plflastline_total;
297 static int autoscale_bordercolors;
298 static int plfstrt, plfstop;
299 static int sprite_minx, sprite_maxx;
300 static int first_bpl_vpos;
301 static int last_ddf_pix_hpos;
302 static int last_decide_line_hpos;
303 static int last_fetch_hpos, last_sprite_hpos;
304 static int diwfirstword, diwlastword;
305 static int last_hdiw;
306 static enum diw_states diwstate, hdiwstate, ddfstate;
307 static int bpl_hstart;
308 
309 int first_planes_vpos, last_planes_vpos;
310 static int first_bplcon0, first_bplcon0_old;
311 static int first_planes_vpos_old, last_planes_vpos_old;
312 int diwfirstword_total, diwlastword_total;
313 int ddffirstword_total, ddflastword_total;
314 static int diwfirstword_total_old, diwlastword_total_old;
315 static int ddffirstword_total_old, ddflastword_total_old;
316 bool vertical_changed, horizontal_changed;
317 int firstword_bplcon1;
318 
319 static int last_copper_hpos;
320 static int copper_access;
321 
322 /* Sprite collisions */
323 static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match;
324 
325 enum copper_states {
326 	COP_stop,
327 	COP_waitforever,
328 	COP_read1,
329 	COP_read2,
330 	COP_bltwait,
331 	COP_wait_in2,
332 	COP_skip_in2,
333 	COP_wait1,
334 	COP_wait,
335 	COP_skip1,
336 	COP_strobe_delay1,
337 	COP_strobe_delay2,
338 	COP_strobe_delay1x,
339 	COP_strobe_delay2x,
340 	COP_strobe_extra, // just to skip current cycle when CPU wrote to COPJMP
341 	COP_start_delay
342 };
343 
344 struct copper {
345 	/* The current instruction words.  */
346 	unsigned int i1, i2;
347 	unsigned int saved_i1, saved_i2;
348 	enum copper_states state, state_prev;
349 	/* Instruction pointer.  */
350 	uaecptr ip, saved_ip;
351 	int hpos, vpos;
352 	unsigned int ignore_next;
353 	int vcmp, hcmp;
354 
355 	int strobe; /* COPJMP1 / COPJMP2 accessed */
356 	int moveaddr, movedata, movedelay;
357 };
358 
359 static struct copper cop_state;
360 static int copper_enabled_thisline;
361 static int cop_min_waittime;
362 
363 /*
364 * Statistics
365 */
366 unsigned long int frametime = 0, lastframetime = 0, timeframes = 0;
367 unsigned long hsync_counter = 0, vsync_counter = 0;
368 unsigned long int idletime;
369 int bogusframe;
370 
371 #ifdef FSUAE // NL
372 int g_uae_vsync_counter = 0;
373 //int g_uae_hsync_counter = 0;
374 #endif
375 
376 /* Recording of custom chip register changes.  */
377 static int current_change_set;
378 static struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16];
379 static struct color_change color_changes[2][MAX_REG_CHANGE];
380 
381 struct decision line_decisions[2 * (MAXVPOS + 2) + 1];
382 static struct draw_info line_drawinfo[2][2 * (MAXVPOS + 2) + 1];
383 #define COLOR_TABLE_SIZE (MAXVPOS + 2) * 2
384 static struct color_entry color_tables[2][COLOR_TABLE_SIZE];
385 
386 static int next_sprite_entry = 0;
387 static int prev_next_sprite_entry;
388 static int next_sprite_forced = 1;
389 
390 struct sprite_entry *curr_sprite_entries, *prev_sprite_entries;
391 struct color_change *curr_color_changes, *prev_color_changes;
392 struct draw_info *curr_drawinfo, *prev_drawinfo;
393 struct color_entry *curr_color_tables, *prev_color_tables;
394 
395 static int next_color_change;
396 static int next_color_entry, remembered_color_entry;
397 static int color_src_match, color_dest_match, color_compare_result;
398 
399 static uae_u32 thisline_changed;
400 
401 #ifdef SMART_UPDATE
402 #define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0)
403 #else
404 #define MARK_LINE_CHANGED do { ; } while (0)
405 #endif
406 
407 static struct decision thisline_decision;
408 static int fetch_cycle, fetch_modulo_cycle;
409 static bool aga_plf_passed_stop2;
410 static int plf_start_hpos, plf_end_hpos;
411 static int ddfstop_written_hpos;
412 static int bitplane_off_delay;
413 static bool ocs_agnus_ddf_enable_toggle;
414 static int bpl_dma_off_when_active;
415 static int bitplane_maybe_start_hpos;
416 static bool ddfstop_matched;
417 
418 enum plfstate
419 {
420 	plf_idle,
421 	// enable passed
422 	plf_passed_enable,
423 	// ddfstrt match
424 	plf_passed_start,
425 	// active (ddfstrt + 4 match)
426 	plf_active,
427 	// inactive, waiting
428 	plf_wait,
429 	// ddfstop passed
430 	plf_passed_stop,
431 	// ddfstop+4 passed
432 	plf_passed_stop_act,
433 	// last block finished
434 	plf_passed_stop2,
435 	plf_end
436 } plf_state;
437 
438 enum plfrenderstate
439 {
440 	plfr_idle,
441 	plfr_active,
442 	plfr_end,
443 	plfr_finished
444 } plfr_state;
445 
446 enum fetchstate {
447 	fetch_not_started,
448 	fetch_started_first,
449 	fetch_started,
450 	fetch_was_plane0
451 } fetch_state;
452 
453 /*
454 * helper functions
455 */
456 
ecsshres(void)457 STATIC_INLINE int ecsshres(void)
458 {
459 	return bplcon0_res == RES_SUPERHIRES && (currprefs.chipset_mask & CSMASK_ECS_DENISE) && !(currprefs.chipset_mask & CSMASK_AGA);
460 }
461 
nodraw(void)462 STATIC_INLINE int nodraw (void)
463 {
464 	return !currprefs.cpu_memory_cycle_exact && framecnt != 0;
465 }
466 
doflickerfix(void)467 static int doflickerfix (void)
468 {
469 	return currprefs.gfx_vresolution && doublescan < 0 && vpos < MAXVPOS;
470 }
471 
get_copper_address(int copno)472 uae_u32 get_copper_address (int copno)
473 {
474 	switch (copno) {
475 	case 1: return cop1lc;
476 	case 2: return cop2lc;
477 	case -1: return cop_state.ip;
478 	default: return 0;
479 	}
480 }
481 
reset_frame_rate_hack(void)482 void reset_frame_rate_hack (void)
483 {
484 	if (currprefs.m68k_speed >= 0)
485 		return;
486 
487 	rpt_did_reset = 1;
488 	is_syncline = 0;
489 	vsyncmintime = read_processor_time () + vsynctimebase;
490 	write_log (_T("Resetting frame rate hack\n"));
491 }
492 
setclr(uae_u16 * p,uae_u16 val)493 STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val)
494 {
495 	if (val & 0x8000)
496 		*p |= val & 0x7FFF;
497 	else
498 		*p &= ~val;
499 }
500 
alloc_cycle(int hpos,int type)501 STATIC_INLINE void alloc_cycle (int hpos, int type)
502 {
503 #ifdef CPUEMU_13
504 #if 0
505 	if (cycle_line[hpos])
506 		write_log (_T("hpos=%d, old=%d, new=%d\n"), hpos, cycle_line[hpos], type);
507 	if ((type == CYCLE_COPPER) && (hpos & 1) && hpos != maxhpos - 2)
508 		write_log (_T("odd %d cycle %d\n"), hpos);
509 	if (!(hpos & 1) && (type == CYCLE_SPRITE || type == CYCLE_REFRESH || type == CYCLE_MISC))
510 		write_log (_T("even %d cycle %d\n"), type, hpos);
511 #endif
512 	cycle_line[hpos] = type;
513 #endif
514 }
alloc_cycle_maybe(int hpos,int type)515 STATIC_INLINE void alloc_cycle_maybe (int hpos, int type)
516 {
517 	if ((cycle_line[hpos] & CYCLE_MASK) == 0)
518 		alloc_cycle (hpos, type);
519 }
520 
alloc_cycle_ext(int hpos,int type)521 void alloc_cycle_ext (int hpos, int type)
522 {
523 	alloc_cycle (hpos, type);
524 }
525 
alloc_cycle_blitter(int hpos,uaecptr * ptr,int chnum)526 void alloc_cycle_blitter (int hpos, uaecptr *ptr, int chnum)
527 {
528 	if (cycle_line[hpos] & CYCLE_COPPER_SPECIAL) {
529 		static int warned = 100;
530 		uaecptr srcptr = cop_state.strobe == 1 ? cop1lc : cop2lc;
531 		if (warned > 0) {
532 			write_log (_T("buggy copper cycle conflict with blitter ch %c %08x <- %08x PC=%08x\n"), 'A' + (chnum - 1), *ptr, srcptr, m68k_getpc ());
533 			warned--;
534 			//activate_debugger ();
535 		}
536 		//if ((currprefs.cs_hacks & 1) && currprefs.cpu_model == 68000)
537 		if (currprefs.cpu_model == 68000 && currprefs.cpu_cycle_exact && currprefs.blitter_cycle_exact)
538 			*ptr = srcptr;
539 	}
540 	alloc_cycle (hpos, CYCLE_BLITTER);
541 }
542 
set_chipset_mode(void)543 static void set_chipset_mode(void)
544 {
545 	if (currprefs.chipset_mask & CSMASK_AGA) {
546 		fmode = fmode_saved;
547 	} else {
548 		fmode = 0;
549 	}
550 	sprite_width = GET_SPRITEWIDTH (fmode);
551 }
552 
update_mirrors(void)553 static void update_mirrors (void)
554 {
555 	aga_mode = (currprefs.chipset_mask & CSMASK_AGA) != 0;
556 	direct_rgb = aga_mode;
557 	if (currprefs.chipset_mask & CSMASK_AGA)
558 		sprite_sprctlmask = 0x01 | 0x08 | 0x10;
559 	else if (currprefs.chipset_mask & CSMASK_ECS_DENISE)
560 		sprite_sprctlmask = 0x01 | 0x10;
561 	else
562 		sprite_sprctlmask = 0x01;
563 	set_chipset_mode();
564 }
565 
pfield_xlateptr(uaecptr plpt,int bytecount)566 STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount)
567 {
568 	if (!chipmem_check_indirect (plpt, bytecount)) {
569 		static int count = 0;
570 		if (!count)
571 			count++, write_log (_T("Warning: Bad playfield pointer %08x\n"), plpt);
572 		return NULL;
573 	}
574 	return chipmem_xlate_indirect (plpt);
575 }
docols(struct color_entry * colentry)576 static void docols (struct color_entry *colentry)
577 {
578 	int i;
579 
580 #ifdef AGA
581 #ifdef FSUAE
582 #if 0
583 	// if (currprefs.chipset_mask & CSMASK_AGA) {
584 	// color_reg_get checks aga_mode, so use that here too so
585 	// static analyzers don't complain about out-of-bounds accesses
586 	if (aga_mode) {
587 #endif
588 #endif
589 	if (currprefs.chipset_mask & CSMASK_AGA) {
590 		for (i = 0; i < 256; i++) {
591 			int v = color_reg_get (colentry, i);
592 			if (v < 0 || v > 16777215)
593 				continue;
594 			colentry->acolors[i] = getxcolor (v);
595 		}
596 	} else {
597 #endif
598 		for (i = 0; i < 32; i++) {
599 			int v = color_reg_get (colentry, i);
600 			if (v < 0 || v > 4095)
601 				continue;
602 			colentry->acolors[i] = getxcolor (v);
603 		}
604 #ifdef AGA
605 	}
606 #endif
607 }
608 
609 extern struct color_entry colors_for_drawing;
610 
611 void notice_new_xcolors (void)
612 {
613 	int i;
614 
615 	update_mirrors ();
616 	docols (&current_colors);
617 	docols (&colors_for_drawing);
618 	for (i = 0; i < (MAXVPOS + 1) * 2; i++) {
619 		docols (color_tables[0] + i);
620 		docols (color_tables[1] + i);
621 	}
622 }
623 
624 static void do_sprites (int currhp);
625 
626 static void remember_ctable (void)
627 {
628 	/* This can happen when program crashes very badly */
629 	if (next_color_entry >= COLOR_TABLE_SIZE)
630 		return;
631 	if (remembered_color_entry < 0) {
632 		/* The colors changed since we last recorded a color map. Record a
633 		* new one. */
634 		color_reg_cpy (curr_color_tables + next_color_entry, &current_colors);
635 		remembered_color_entry = next_color_entry++;
636 	}
637 	thisline_decision.ctable = remembered_color_entry;
638 	if (color_src_match < 0 || color_dest_match != remembered_color_entry
639 		|| line_decisions[next_lineno].ctable != color_src_match)
640 	{
641 		/* The remembered comparison didn't help us - need to compare again. */
642 		int oldctable = line_decisions[next_lineno].ctable;
643 		int changed = 0;
644 
645 		if (oldctable < 0) {
646 			changed = 1;
647 			color_src_match = color_dest_match = -1;
648 		} else {
649 			color_compare_result = color_reg_cmp (&prev_color_tables[oldctable], &current_colors) != 0;
650 			if (color_compare_result)
651 				changed = 1;
652 			color_src_match = oldctable;
653 			color_dest_match = remembered_color_entry;
654 		}
655 		thisline_changed |= changed;
656 	} else {
657 		/* We know the result of the comparison */
658 		if (color_compare_result)
659 			thisline_changed = 1;
660 	}
661 }
662 
663 static void remember_ctable_for_border (void)
664 {
665 	remember_ctable ();
666 }
667 
668 STATIC_INLINE int get_equ_vblank_endline (void)
669 {
670 	return equ_vblank_endline + (equ_vblank_toggle ? (lof_current ? 1 : 0) : 0);
671 }
672 
673 #define DDF_OFFSET 4
674 #define HARD_DDF_LIMITS_DISABLED ((beamcon0 & 0x80) || (beamcon0 & 0x4000) || (bplcon0 & 0x40))
675 /* The HRM says 0xD8, but that can't work... */
676 #define HARD_DDF_STOP (HARD_DDF_LIMITS_DISABLED ? maxhpos : 0xd4)
677 #define HARD_DDF_START_REAL 0x14
678 /* Programmed rates or superhires (!) disable normal DMA limits */
679 #define HARD_DDF_START (HARD_DDF_LIMITS_DISABLED ? 0x04 : 0x14)
680 
681 /* Called to determine the state of the horizontal display window state
682 * machine at the current position. It might have changed since we last
683 * checked.  */
684 static void decide_diw (int hpos)
685 {
686 	/* Last hpos = hpos + 0.5, eg. normal PAL end hpos is 227.5 * 2 = 455
687 	   OCS Denise: 9 bit hdiw counter does not reset during lines 0 to 9
688 	   (PAL) or lines 0 to 10 (NTSC). A1000 PAL: 1 to 9, NTSC: 1 to 10.
689 	   ECS Denise and AGA: no above "features"
690 	*/
691 
692 	int hdiw = hpos >= maxhpos ? maxhpos * 2 + 1 : hpos * 2 + 2;
693 	if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE) && vpos <= get_equ_vblank_endline ())
694 		hdiw = diw_hcounter;
695 	/* always mask, bad programs may have set maxhpos = 256 */
696 	hdiw &= 511;
697 	for (;;) {
698 		int lhdiw = hdiw;
699 		if (last_hdiw > lhdiw)
700 			lhdiw = 512;
701 
702 		if (lhdiw >= diw_hstrt && last_hdiw < diw_hstrt && hdiwstate == DIW_waiting_start) {
703 			if (thisline_decision.diwfirstword < 0)
704 				thisline_decision.diwfirstword = diwfirstword < 0 ? PIXEL_XPOS(0) : diwfirstword;
705 			hdiwstate = DIW_waiting_stop;
706 		}
707 		if (((hpos >= maxhpos && HARD_DDF_LIMITS_DISABLED) || (lhdiw >= diw_hstop && last_hdiw < diw_hstop)) && hdiwstate == DIW_waiting_stop) {
708 			if (thisline_decision.diwlastword < 0)
709 				thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword;
710 			hdiwstate = DIW_waiting_start;
711 		}
712 		if (lhdiw != 512)
713 			break;
714 		last_hdiw = 0 - 1;
715 	}
716 	last_hdiw = hdiw;
717 }
718 
719 static int fetchmode, fetchmode_size, fetchmode_mask, fetchmode_bytes;
720 static int real_bitplane_number[3][3][9];
721 
722 /* Disable bitplane DMA if planes > available DMA slots. This is needed
723 e.g. by the Sanity WOC demo (at the "Party Effect").  */
724 STATIC_INLINE int GET_PLANES_LIMIT (uae_u16 bc0)
725 {
726 	int res = GET_RES_AGNUS (bc0);
727 	int planes = GET_PLANES (bc0);
728 	return real_bitplane_number[fetchmode][res][planes];
729 }
730 
731 #if 0
732 static void reset_dbplh(int hpos, int num)
733 {
734 	if (dbplpth_on[num] && hpos >= dbplpth_on[num]) {
735 		bplpt[num] = dbplpth[num] | (bplpt[num] & 0x0000fffe);
736 		dbplpth_on[num] = 0;
737 		dbplpth_on2--;
738 	}
739 }
740 
741 static void reset_dbplh_all (int hpos)
742 {
743 	if (dbplpth_on2) {
744 		for (int num = 0; num < MAX_PLANES; num++) {
745 			reset_dbplh(hpos, num);
746 		}
747 		dbplpth_on2 = 0;
748 	}
749 }
750 
751 static void reset_dbpll (int hpos, int num)
752 {
753 	if (dbplptl_on[num] && hpos >= dbplptl_on[num]) {
754 		bplpt[num] = (bplpt[num] & 0xffff0000) | dbplptl[num];
755 		dbplptl_on[num] = 0;
756 		dbplptl_on2--;
757 	}
758 }
759 
760 static void reset_dbpll_all (int hpos)
761 {
762 	if (dbplptl_on2) {
763 		for (int num = 0; num < MAX_PLANES; num++) {
764 			reset_dbpll(hpos, num);
765 		}
766 		dbplptl_on2 = 0;
767 	}
768 }
769 #endif
770 
771 static void reset_moddelays (void)
772 {
773 	if (dbpl1mod_on > 0) {
774 		bpl1mod = dbpl1mod;
775 		dbpl1mod_on = 0;
776 	}
777 	if (dbpl2mod_on > 0) {
778 		bpl2mod = dbpl2mod;
779 		dbpl2mod_on = 0;
780 	}
781 }
782 
783 static void add_modulo (int hpos, int nr)
784 {
785 	int mod;
786 
787 	if (dbpl1mod_on != hpos && dbpl1mod_on) {
788 		bpl1mod = dbpl1mod;
789 		dbpl1mod_on = 0;
790 	}
791 	if (dbpl2mod_on != hpos && dbpl2mod_on) {
792 		bpl2mod = dbpl2mod;
793 		dbpl2mod_on = 0;
794 	}
795 	if (fmode & 0x4000) {
796 		if (((diwstrt >> 8) ^ vpos) & 1)
797 			mod = bpl2mod;
798 		else
799 			mod = bpl1mod;
800 	} else if (nr & 1)
801 		mod = bpl2mod;
802 	else
803 		mod = bpl1mod;
804 	bplpt[nr] += mod;
805 	bplptx[nr] += mod;
806 	reset_moddelays ();
807 #if 0
808 	reset_dbpll_all (-1);
809 #endif
810 }
811 
812 static void add_modulos (void)
813 {
814 	int m1, m2;
815 
816 	reset_moddelays ();
817 #if 0
818 	reset_dbpll_all(-1);
819 #endif
820 	if (fmode & 0x4000) {
821 		if (((diwstrt >> 8) ^ vpos) & 1)
822 			m1 = m2 = bpl2mod;
823 		else
824 			m1 = m2 = bpl1mod;
825 	} else {
826 		m1 = bpl1mod;
827 		m2 = bpl2mod;
828 	}
829 
830 	switch (bplcon0_planes_limit) {
831 #ifdef AGA
832 	case 8: bplpt[7] += m2; bplptx[7] += m2;
833 	case 7: bplpt[6] += m1; bplptx[6] += m1;
834 #endif
835 	case 6: bplpt[5] += m2; bplptx[5] += m2;
836 	case 5: bplpt[4] += m1; bplptx[4] += m1;
837 	case 4: bplpt[3] += m2; bplptx[3] += m2;
838 	case 3: bplpt[2] += m1; bplptx[2] += m1;
839 	case 2: bplpt[1] += m2; bplptx[1] += m2;
840 	case 1: bplpt[0] += m1; bplptx[0] += m1;
841 	}
842 }
843 
844 static void finish_playfield_line (void)
845 {
846 	/* The latter condition might be able to happen in interlaced frames. */
847 	if (vpos >= minfirstline && (thisframe_first_drawn_line < 0 || vpos < thisframe_first_drawn_line))
848 		thisframe_first_drawn_line = vpos;
849 	thisframe_last_drawn_line = vpos;
850 
851 #ifdef SMART_UPDATE
852 	if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
853 		|| line_decisions[next_lineno].plfleft != thisline_decision.plfleft
854 		|| line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
855 		|| line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
856 #ifdef ECS_DENISE
857 		|| line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3
858 #endif
859 #ifdef AGA
860 		|| line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
861 #endif
862 		)
863 #endif /* SMART_UPDATE */
864 		thisline_changed = 1;
865 }
866 
867 /* The fetch unit mainly controls ddf stop.  It's the number of cycles that
868 are contained in an indivisible block during which ddf is active.  E.g.
869 if DDF starts at 0x30, and fetchunit is 8, then possible DDF stops are
870 0x30 + n * 8.  */
871 static int fetchunit, fetchunit_mask;
872 /* The delay before fetching the same bitplane again.  Can be larger than
873 the number of bitplanes; in that case there are additional empty cycles
874 with no data fetch (this happens for high fetchmodes and low
875 resolutions).  */
876 static int fetchstart, fetchstart_shift, fetchstart_mask;
877 /* fm_maxplane holds the maximum number of planes possible with the current
878 fetch mode.  This selects the cycle diagram:
879 8 planes: 73516240
880 4 planes: 3120
881 2 planes: 10.  */
882 static int fm_maxplane, fm_maxplane_shift;
883 
884 /* The corresponding values, by fetchmode and display resolution.  */
885 static const int fetchunits[] = { 8,8,8,0, 16,8,8,0, 32,16,8,0 };
886 static const int fetchstarts[] = { 3,2,1,0, 4,3,2,0, 5,4,3,0 };
887 static const int fm_maxplanes[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 };
888 
889 static int cycle_diagram_table[3][3][9][32];
890 static int cycle_diagram_free_cycles[3][3][9];
891 static int cycle_diagram_total_cycles[3][3][9];
892 static int *curr_diagram;
893 static const int cycle_sequences[3 * 8] = { 2,1,2,1,2,1,2,1, 4,2,3,1,4,2,3,1, 8,4,6,2,7,3,5,1 };
894 
895 static void debug_cycle_diagram (void)
896 {
897 	int fm, res, planes, cycle, v;
898 	TCHAR aa;
899 
900 	for (fm = 0; fm <= 2; fm++) {
901 		write_log (_T("FMODE %d\n=======\n"), fm);
902 		for (res = 0; res <= 2; res++) {
903 			for (planes = 0; planes <= 8; planes++) {
904 				write_log (_T("%d: "),planes);
905 				for (cycle = 0; cycle < 32; cycle++) {
906 					v=cycle_diagram_table[fm][res][planes][cycle];
907 					if (v==0) aa='-'; else if(v>0) aa='1'; else aa='X';
908 					write_log (_T("%c"),aa);
909 				}
910 				write_log (_T(" %d:%d\n"),
911 					cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]);
912 			}
913 			write_log (_T("\n"));
914 		}
915 	}
916 	fm=0;
917 }
918 
919 static void create_cycle_diagram_table (void)
920 {
921 	int fm, res, cycle, planes, rplanes, v;
922 	int fetch_start, max_planes, freecycles;
923 	const int *cycle_sequence;
924 
925 	for (fm = 0; fm <= 2; fm++) {
926 		for (res = 0; res <= 2; res++) {
927 			max_planes = fm_maxplanes[fm * 4 + res];
928 			fetch_start = 1 << fetchstarts[fm * 4 + res];
929 			cycle_sequence = &cycle_sequences[(max_planes - 1) * 8];
930 			max_planes = 1 << max_planes;
931 			for (planes = 0; planes <= 8; planes++) {
932 				freecycles = 0;
933 				for (cycle = 0; cycle < 32; cycle++)
934 					cycle_diagram_table[fm][res][planes][cycle] = -1;
935 				if (planes <= max_planes) {
936 					for (cycle = 0; cycle < fetch_start; cycle++) {
937 						if (cycle < max_planes && planes >= cycle_sequence[cycle & 7]) {
938 							v = cycle_sequence[cycle & 7];
939 						} else {
940 							v = 0;
941 							freecycles++;
942 						}
943 						cycle_diagram_table[fm][res][planes][cycle] = v;
944 					}
945 				}
946 				cycle_diagram_free_cycles[fm][res][planes] = freecycles;
947 				cycle_diagram_total_cycles[fm][res][planes] = fetch_start;
948 				rplanes = planes;
949 				if (rplanes > max_planes)
950 					rplanes = 0;
951 				if (rplanes == 7 && fm == 0 && res == 0 && !(currprefs.chipset_mask & CSMASK_AGA))
952 					rplanes = 4;
953 				real_bitplane_number[fm][res][planes] = rplanes;
954 			}
955 		}
956 	}
957 #if 0
958 	debug_cycle_diagram ();
959 #endif
960 }
961 
962 
963 /* Used by the copper.  */
964 static int estimated_last_fetch_cycle;
965 static int cycle_diagram_shift;
966 
967 static void estimate_last_fetch_cycle (int hpos)
968 {
969 	int fetchunit = fetchunits[fetchmode * 4 + bplcon0_res];
970 	// Last fetch is always max 8 even if fetchunit is larger.
971 	int lastfetchunit = fetchunit >= 8 ? 8 : fetchunit;
972 
973 	if (plf_state < plf_passed_stop) {
974 		int stop;
975 
976 		if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
977 			// ECS: stop wins if start == stop
978 			stop = plfstop + DDF_OFFSET < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop;
979 		} else {
980 			// OCS: start wins if start == stop
981 			stop = plfstop + DDF_OFFSET <= hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop;
982 		}
983 		/* We know that fetching is up-to-date up until hpos, so we can use fetch_cycle.  */
984 		int fetch_cycle_at_stop = fetch_cycle + (stop - hpos + DDF_OFFSET);
985 		int starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1);
986 
987 		estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + lastfetchunit;
988 	} else {
989 		int starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1);
990 		if (plf_state == plf_passed_stop2)
991 			starting_last_block_at -= fetchunit;
992 
993 		estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + lastfetchunit;
994 	}
995 }
996 
997 static uae_u32 outword[MAX_PLANES];
998 static int out_nbits, out_offs;
999 static uae_u16 todisplay[MAX_PLANES], todisplay2[MAX_PLANES];
1000 static uae_u16 fetched[MAX_PLANES];
1001 static bool todisplay_fetched[2];
1002 #ifdef AGA
1003 static uae_u64 todisplay_aga[MAX_PLANES], todisplay2_aga[MAX_PLANES];
1004 static uae_u64 fetched_aga[MAX_PLANES];
1005 #endif
1006 
1007 /* Expansions from bplcon0/bplcon1.  */
1008 static int toscr_res, toscr_res2p;
1009 static int toscr_nr_planes, toscr_nr_planes2, toscr_nr_planes_agnus, toscr_nr_planes_shifter;
1010 static int fetchwidth;
1011 static int toscr_delay[2], toscr_delay_adjusted[2], toscr_delay_sh[2];
1012 static int delay_cycles, delay_lastcycle[2];
1013 static bool bplcon1_written;
1014 
1015 #define PLANE_RESET_HPOS 8
1016 static int planesactiveatresetpoint;
1017 
1018 /* The number of bits left from the last fetched words.
1019 This is an optimization - conceptually, we have to make sure the result is
1020 the same as if toscr is called in each clock cycle.  However, to speed this
1021 up, we accumulate display data; this variable keeps track of how much.
1022 Thus, once we do call toscr_nbits (which happens at least every 16 bits),
1023 we can do more work at once.  */
1024 static int toscr_nbits;
1025 
1026 #if 0
1027 /* undocumented bitplane delay hardware feature */
1028 static int delayoffset;
1029 
1030 STATIC_INLINE void compute_delay_offset (void)
1031 {
1032 	delayoffset = (16 << fetchmode) - (((plfstrt - HARD_DDF_START_REAL) & fetchstart_mask) << 1);
1033 	/* maybe we can finally get rid of this stupid table.. */
1034 	if (tmp == 4)
1035 		delayoffset = 4; // Loons Docs
1036 	else if (tmp == 8)
1037 		delayoffset = 8;
1038 	else if (tmp == 12) // Loons Docs
1039 		delayoffset = 4;
1040 	else if (tmp == 16) /* Overkill AGA */
1041 		delayoffset = 48;
1042 	else if (tmp == 24) /* AB 2 */
1043 		delayoffset = 8;
1044 	else if (tmp == 32)
1045 		delayoffset = 32;
1046 	else if (tmp == 48) /* Pinball Illusions AGA, ingame */
1047 		delayoffset = 16;
1048 	else /* what about 40 and 56? */
1049 		delayoffset = 0;
1050 	//write_log (_T("%d:%d "), vpos, delayoffset);
1051 }
1052 #endif
1053 
1054 static void record_color_change2 (int hpos, int regno, unsigned long value)
1055 {
1056 	int pos = hpos * 2;
1057 	if (regno == 0x1000 + 0x10c)
1058 		pos++; // BPLCON4 change needs 1 lores pixel delay
1059 	curr_color_changes[next_color_change].linepos = pos;
1060 	curr_color_changes[next_color_change].regno = regno;
1061 	curr_color_changes[next_color_change].value = value;
1062 	next_color_change++;
1063 	curr_color_changes[next_color_change].regno = -1;
1064 }
1065 
1066 static bool isehb (uae_u16 bplcon0, uae_u16 bplcon2)
1067 {
1068 	bool bplehb;
1069 	if (currprefs.chipset_mask & CSMASK_AGA)
1070 		bplehb = (bplcon0 & 0x7010) == 0x6000;
1071 	else if (currprefs.chipset_mask & CSMASK_ECS_DENISE)
1072 		bplehb = ((bplcon0 & 0xFC00) == 0x6000 || (bplcon0 & 0xFC00) == 0x7000);
1073 	else
1074 		bplehb = ((bplcon0 & 0xFC00) == 0x6000 || (bplcon0 & 0xFC00) == 0x7000) && !currprefs.cs_denisenoehb;
1075 	return bplehb;
1076 }
1077 
1078 // OCS/ECS, lores, 7 planes = 4 "real" planes + BPL5DAT and BPL6DAT as static 5th and 6th plane
1079 STATIC_INLINE int isocs7planes (void)
1080 {
1081 	return !(currprefs.chipset_mask & CSMASK_AGA) && bplcon0_res == 0 && bplcon0_planes == 7;
1082 }
1083 
1084 int is_bitplane_dma (int hpos)
1085 {
1086 	if (hpos < bpl_hstart || fetch_state == fetch_not_started || plf_state == plf_wait)
1087 		return 0;
1088 	if ((plf_state >= plf_end && hpos >= thisline_decision.plfright)
1089 		|| hpos >= estimated_last_fetch_cycle)
1090 		return 0;
1091 	return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask];
1092 }
1093 
1094 STATIC_INLINE int is_bitplane_dma_inline (int hpos)
1095 {
1096 	if (hpos < bpl_hstart || fetch_state == fetch_not_started || plf_state == plf_wait)
1097 		return 0;
1098 	if ((plf_state >= plf_end && hpos >= thisline_decision.plfright)
1099 		|| hpos >= estimated_last_fetch_cycle)
1100 		return 0;
1101 	return curr_diagram[(hpos - cycle_diagram_shift) & fetchstart_mask];
1102 }
1103 
1104 static int islinetoggle (void)
1105 {
1106 	int linetoggle = 0;
1107 	if (!(beamcon0 & 0x0800) && !(beamcon0 & 0x0020) && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
1108 		linetoggle = 1; // NTSC and !LOLDIS -> LOL toggles every line
1109 	} else if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS) && currprefs.ntscmode) {
1110 		linetoggle = 1; // hardwired NTSC Agnus
1111 	}
1112 	return linetoggle;
1113 }
1114 
1115 /* Expand bplcon0/bplcon1 into the toscr_xxx variables.  */
1116 static void compute_toscr_delay (int bplcon1)
1117 {
1118 	int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6);
1119 	int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6);
1120 	int shdelay1 = (bplcon1 >> 8) & 3;
1121 	int shdelay2 = (bplcon1 >> 12) & 3;
1122 	int delaymask = fetchmode_mask >> toscr_res;
1123 
1124 	toscr_delay[0] = (delay1 & delaymask) << toscr_res;
1125 	toscr_delay[0] |= shdelay1 >> (RES_MAX - toscr_res);
1126 	toscr_delay[1] = (delay2 & delaymask) << toscr_res;
1127 	toscr_delay[1] |= shdelay2 >> (RES_MAX - toscr_res);
1128 
1129 #if SPEEDUP
1130 	/* SPEEDUP code still needs this hack */
1131 	int	delayoffset = fetchmode_size - (((bpl_hstart - (HARD_DDF_START_REAL + DDF_OFFSET)) & fetchstart_mask) << 1);
1132 	delay1 += delayoffset;
1133 	delay2 += delayoffset;
1134 	toscr_delay_adjusted[0] = (delay1 & delaymask) << toscr_res;
1135 	toscr_delay_adjusted[0] |= shdelay1 >> (RES_MAX - toscr_res);
1136 	toscr_delay_adjusted[1] = (delay2 & delaymask) << toscr_res;
1137 	toscr_delay_adjusted[1] |= shdelay2 >> (RES_MAX - toscr_res);
1138 #endif
1139 }
1140 
1141 static void set_delay_lastcycle (void)
1142 {
1143 	if (HARD_DDF_LIMITS_DISABLED) {
1144 		delay_lastcycle[0] = (256 * 2) << bplcon0_res;
1145 		delay_lastcycle[1] = (256 * 2) << bplcon0_res;
1146 	} else {
1147 		delay_lastcycle[0] = ((maxhpos + 1) * 2 + 0) << bplcon0_res;
1148 		delay_lastcycle[1] = delay_lastcycle[0];
1149 		if (islinetoggle ())
1150 			delay_lastcycle[1]++;
1151 	}
1152 }
1153 
1154 static int bpldmasetuphpos, bpldmasetuphpos_diff;
1155 static int bpldmasetupphase;
1156 static void update_toscr_planes (int fm);
1157 /* set currently active Agnus bitplane DMA sequence */
1158 static void setup_fmodes (int hpos)
1159 {
1160 	switch (fmode & 3)
1161 	{
1162 	case 0:
1163 		fetchmode = 0;
1164 		break;
1165 	case 1:
1166 	case 2:
1167 		fetchmode = 1;
1168 		break;
1169 	case 3:
1170 		fetchmode = 2;
1171 		break;
1172 	}
1173 	badmode = GET_RES_AGNUS (bplcon0) != GET_RES_DENISE (bplcon0);
1174 	bplcon0_res = GET_RES_AGNUS (bplcon0);
1175 	bplcon0_planes = GET_PLANES (bplcon0);
1176 	bplcon0_planes_limit = GET_PLANES_LIMIT (bplcon0);
1177 	fetchunit = fetchunits[fetchmode * 4 + bplcon0_res];
1178 	fetchunit_mask = fetchunit - 1;
1179 	fetchstart_shift = fetchstarts[fetchmode * 4 + bplcon0_res];
1180 	fetchstart = 1 << fetchstart_shift;
1181 	fetchstart_mask = fetchstart - 1;
1182 	fm_maxplane_shift = fm_maxplanes[fetchmode * 4 + bplcon0_res];
1183 	fm_maxplane = 1 << fm_maxplane_shift;
1184 	fetch_modulo_cycle = fetchunit - fetchstart;
1185 	fetchmode_size = 16 << fetchmode;
1186 	fetchmode_bytes = 2 << fetchmode;
1187 	fetchmode_mask = fetchmode_size - 1;
1188 	set_delay_lastcycle ();
1189 	compute_toscr_delay (bplcon1);
1190 
1191 	if (thisline_decision.plfleft < 0) {
1192 		thisline_decision.bplres = bplcon0_res;
1193 		thisline_decision.bplcon0 = bplcon0;
1194 		thisline_decision.nr_planes = bplcon0_planes;
1195 	}
1196 
1197 	if (is_bitplane_dma (hpos - 1))
1198 		cycle_line[hpos - 1] = 1;
1199 	curr_diagram = cycle_diagram_table[fetchmode][bplcon0_res][bplcon0_planes_limit];
1200 	estimate_last_fetch_cycle (hpos);
1201 #ifdef DEBUGGER
1202 	if (bpldmasetuphpos >= 0 && debug_dma)
1203 		record_dma_event (DMA_EVENT_BPLFETCHUPDATE, hpos, vpos);
1204 #endif
1205 	bpldmasetuphpos = -1;
1206 	bpldmasetupphase = 0;
1207 	toscr_nr_planes_agnus = bplcon0_planes;
1208 	if (isocs7planes ()) {
1209 		toscr_nr_planes_agnus = 6;
1210 	}
1211 	SET_LINE_CYCLEBASED;
1212 }
1213 
1214 static void BPLCON0_Denise (int hpos, uae_u16 v, bool);
1215 
1216 // writing to BPLCON0 adds 4 cycle delay before Agnus bitplane DMA sequence changes
1217 // (Note that Denise sees the change after 1 cycle)
1218 // AGA needs extra cycle in some specific situations (Brian The Lion "dialog") but not
1219 // in all situations (Superstardust weapon panel)
1220 #define BPLCON_AGNUS_DELAY (3 + (copper_access ? 1 : 0) + (bplcon0_planes == 8 ? 1 : 0))
1221 #define BPLCON_DENISE_DELAY (copper_access ? 1 : 0)
1222 
1223 static void maybe_setup_fmodes (int hpos)
1224 {
1225 	switch (bpldmasetupphase)
1226 	{
1227 	case 0:
1228 		BPLCON0_Denise (hpos, bplcon0, false);
1229 		bpldmasetupphase++;
1230 		bpldmasetuphpos += bpldmasetuphpos_diff;
1231 		break;
1232 	case 1:
1233 		setup_fmodes (hpos);
1234 		break;
1235 	}
1236 }
1237 
1238 STATIC_INLINE void maybe_check (int hpos)
1239 {
1240 	if (bpldmasetuphpos > 0 && hpos >= bpldmasetuphpos)
1241 		maybe_setup_fmodes (hpos);
1242 }
1243 
1244 static void bpldmainitdelay (int hpos)
1245 {
1246 	SET_LINE_CYCLEBASED;
1247 	if (hpos + BPLCON_AGNUS_DELAY < 0x14) {
1248 		BPLCON0_Denise (hpos, bplcon0, false);
1249 		setup_fmodes (hpos);
1250 		return;
1251 	}
1252 	if (bpldmasetuphpos < 0) {
1253 		bpldmasetuphpos = hpos + BPLCON_DENISE_DELAY;
1254 		bpldmasetuphpos_diff = BPLCON_AGNUS_DELAY - BPLCON_DENISE_DELAY;
1255 		bpldmasetupphase = 0;
1256 		if (BPLCON_DENISE_DELAY == 0) {
1257 			maybe_setup_fmodes (hpos);
1258 		}
1259 	}
1260 }
1261 
1262 STATIC_INLINE void clear_fetchbuffer (uae_u32 *ptr, int nwords)
1263 {
1264 	int i;
1265 
1266 	if (! thisline_changed) {
1267 		for (i = 0; i < nwords; i++) {
1268 			if (ptr[i]) {
1269 				thisline_changed = 1;
1270 				break;
1271 			}
1272 		}
1273 	}
1274 	memset (ptr, 0, nwords * 4);
1275 }
1276 
1277 static void update_toscr_planes (int fm)
1278 {
1279 	// This must be called just before new bitplane block starts,
1280 	// not when depth value changes. Depth can change early and can leave
1281 	// 16+ pixel horizontal line of old data visible.
1282 	if (toscr_nr_planes_agnus > thisline_decision.nr_planes) {
1283 		if (out_offs) {
1284 			int j;
1285 			for (j = thisline_decision.nr_planes; j < toscr_nr_planes_agnus; j++) {
1286 				clear_fetchbuffer ((uae_u32 *)(line_data[next_lineno] + 2 * MAX_WORDS_PER_LINE * j), out_offs);
1287 				if (thisline_decision.plfleft >= 0) {
1288 					todisplay[j] = 0;
1289 #ifdef AGA
1290 					if (fm)
1291 						todisplay_aga[j] = 0;
1292 #endif
1293 				}
1294 			}
1295 		}
1296 		thisline_decision.nr_planes = toscr_nr_planes_agnus;
1297 	}
1298 }
1299 
1300 STATIC_INLINE void maybe_first_bpl1dat (int hpos)
1301 {
1302 	if (thisline_decision.plfleft < 0)
1303 		thisline_decision.plfleft = hpos;
1304 }
1305 
1306 static int fetch_warn (int nr, int hpos)
1307 {
1308 	static int warned1 = 30, warned2 = 30;
1309 	int add = fetchmode_bytes;
1310 	if (hpos == maxhpos - 1) {
1311 		if (warned1 >= 0) {
1312 			write_log (_T("WARNING: BPL fetch conflicts with strobe refresh slot!\n"));
1313 			warned1--;
1314 		}
1315 		add = refptr_val;
1316 	} else {
1317 		if (warned2 >= 0) {
1318 			warned2--;
1319 			write_log (_T("WARNING: BPL fetch at hpos 0x%02X!\n"), hpos);
1320 		}
1321 		add = refptr_val;
1322 	}
1323 	bitplane_line_crossing = hpos;
1324 #if 0
1325 	line_cyclebased = vpos;
1326 	corrupt_offset = (vpos ^ (timeframes << 12)) & 0xff00;
1327 	for (int i = 0; i < bplcon0_planes_limit; i++) {
1328 		uae_u16 v;
1329 		v = bplpt[i] & 0xffff;
1330 		v += corrupt_offset;
1331 		bplpt[i] = (bplpt[i] & 0xffff0000) | v;
1332 	}
1333 #endif
1334 	return add;
1335 }
1336 
1337 static void fetch (int nr, int fm, int hpos)
1338 {
1339 	if (nr < bplcon0_planes_limit) {
1340 		uaecptr p;
1341 		int add = fetchmode_bytes;
1342 
1343 		if (hpos > maxhpos - HPOS_SHIFT && !(beamcon0 & 0x80)) {
1344 			add = fetch_warn (nr, hpos);
1345 		}
1346 
1347 		p = bplpt[nr];
1348 		bplpt[nr] += add;
1349 		bplptx[nr] += add;
1350 
1351 #if 0
1352 		if (dbplpth_on2)
1353 			reset_dbplh (hpos, nr);
1354 		if (dbplptl_on2)
1355 			reset_dbpll (hpos, nr);
1356 #endif
1357 
1358 		if (nr == 0)
1359 			bpl1dat_written = true;
1360 
1361 #ifdef DEBUGGER
1362 		if (debug_dma)
1363 			record_dma (0x110 + nr * 2, chipmem_wget_indirect (p), p, hpos, vpos, DMARECORD_BITPLANE);
1364 		if (memwatch_enabled)
1365 			debug_wgetpeekdma_chipram(p, chipmem_wget_indirect (p), MW_MASK_BPL_0 << nr, 0x110 + nr * 2);
1366 #endif
1367 		switch (fm)
1368 		{
1369 		case 0:
1370 			fetched[nr] = chipmem_wget_indirect (p);
1371 			last_custom_value1 = fetched[nr];
1372 			break;
1373 #ifdef AGA
1374 		case 1:
1375 			fetched_aga[nr] = chipmem_lget_indirect (p);
1376 			last_custom_value1 = fetched_aga[nr];
1377 			fetched[nr] = (uae_u16)fetched_aga[nr];
1378 			break;
1379 		case 2:
1380 			fetched_aga[nr] = ((uae_u64)chipmem_lget_indirect (p)) << 32;
1381 			fetched_aga[nr] |= chipmem_lget_indirect (p + 4);
1382 			last_custom_value1 = (uae_u32)fetched_aga[nr];
1383 			fetched[nr] = (uae_u16)fetched_aga[nr];
1384 			break;
1385 #endif
1386 		}
1387 		if (plf_state == plf_passed_stop2 && fetch_cycle >= (fetch_cycle & ~fetchunit_mask) + fetch_modulo_cycle)
1388 			add_modulo (hpos, nr);
1389 	}
1390 }
1391 
1392 STATIC_INLINE void toscr_3_ecs (int oddeven, int step, int nbits)
1393 {
1394 	int i;
1395 	int shift = 16 - nbits;
1396 
1397 	// if number of planes decrease (or go to zero), we still need to
1398 	// shift all possible remaining pixels out of Denise's shift register
1399 	for (i = oddeven; i < thisline_decision.nr_planes; i += step) {
1400 		outword[i] <<= nbits;
1401 	}
1402 
1403 	for (i = oddeven; i < toscr_nr_planes2; i += step) {
1404 		outword[i] |= todisplay2[i] >> shift;
1405 		todisplay2[i] <<= nbits;
1406 	}
1407 }
1408 
1409 #ifdef AGA
1410 
1411 STATIC_INLINE void toscr_3_aga (int oddeven, int step, int nbits, int fm)
1412 {
1413 	int i;
1414 	uae_u32 mask = 0xFFFF >> (16 - nbits);
1415 	int shift = fetchmode_size - nbits;
1416 
1417 	for (i = oddeven; i < thisline_decision.nr_planes; i += step) {
1418 		outword[i] <<= nbits;
1419 	}
1420 
1421 	for (i = oddeven; i < toscr_nr_planes2; i += step) {
1422 		outword[i] |= (todisplay2_aga[i] >> shift) & mask;
1423 		todisplay2_aga[i] <<= nbits;
1424 	}
1425 }
1426 
1427 #endif
1428 
1429 static void toscr_2_0 (int nbits) { toscr_3_ecs (0, 1, nbits); }
1430 static void toscr_2_0_oe (int oddeven, int step, int nbits) { toscr_3_ecs (oddeven, step, nbits); }
1431 #ifdef AGA
1432 static void toscr_2_1 (int nbits) { toscr_3_aga (0, 1, nbits, 1); }
1433 static void toscr_2_1_oe (int oddeven, int step, int nbits) { toscr_3_aga (oddeven, step, nbits, 1); }
1434 static void toscr_2_2 (int nbits) { toscr_3_aga (0, 1, nbits, 2); }
1435 static void toscr_2_2_oe (int oddeven, int step, int nbits) { toscr_3_aga (oddeven, step, nbits, 2); }
1436 #endif
1437 
1438 STATIC_INLINE void do_tosrc (int oddeven, int step, int nbits, int fm)
1439 {
1440 	switch (fm) {
1441 	case 0:
1442 		if (step == 2)
1443 			toscr_2_0_oe (oddeven, step, nbits);
1444 		else
1445 			toscr_2_0 (nbits);
1446 		break;
1447 #ifdef AGA
1448 	case 1:
1449 		if (step == 2)
1450 			toscr_2_1_oe (oddeven, step, nbits);
1451 		else
1452 			toscr_2_1 (nbits);
1453 		break;
1454 	case 2:
1455 		if (step == 2)
1456 			toscr_2_2_oe (oddeven, step, nbits);
1457 		else
1458 			toscr_2_2 (nbits);
1459 		break;
1460 #endif
1461 	}
1462 }
1463 
1464 STATIC_INLINE void do_delays_3_ecs (int nbits)
1465 {
1466 	int delaypos = delay_cycles & fetchmode_mask;
1467 	for (int oddeven = 0; oddeven < 2; oddeven++) {
1468 		int delay = toscr_delay[oddeven];
1469 #if 0
1470 		for (int j = 0; j < nbits; j++) {
1471 			int dp = (delay_cycles + j);
1472 			if (dp >= (maxhpos * 2) << toscr_res)
1473 				dp -= (maxhpos * 2) << toscr_res;
1474 			dp &= fetchmode_mask;
1475 			do_tosrc (oddeven, 2, 1, 0);
1476 
1477 
1478 			if (todisplay_fetched[oddeven] && dp == delay) {
1479 				for (int i = oddeven; i < toscr_nr_planes_shifter; i += 2) {
1480 					todisplay2[i] = todisplay[i];
1481 				}
1482 				todisplay_fetched[oddeven] = false;
1483 			}
1484 		}
1485 
1486 #else
1487 		if (delaypos > delay)
1488 			delay += fetchmode_size;
1489 		int diff = delay - delaypos;
1490 		int nbits2 = nbits;
1491 		if (nbits2 > diff) {
1492 			do_tosrc (oddeven, 2, diff, 0);
1493 			nbits2 -= diff;
1494 			if (todisplay_fetched[oddeven]) {
1495 				for (int i = oddeven; i < toscr_nr_planes_shifter; i += 2)
1496 					todisplay2[i] = todisplay[i];
1497 				todisplay_fetched[oddeven] = false;
1498 			}
1499 		}
1500 		if (nbits2)
1501 			do_tosrc (oddeven, 2, nbits2, 0);
1502 #endif
1503 	}
1504 }
1505 
1506 STATIC_INLINE void do_delays_fast_3_ecs (int nbits)
1507 {
1508 	int delaypos = delay_cycles & fetchmode_mask;
1509 	int delay = toscr_delay[0];
1510 	if (delaypos > delay)
1511 		delay += fetchmode_size;
1512 	int diff = delay - delaypos;
1513 	int nbits2 = nbits;
1514 	if (nbits2 > diff) {
1515 		do_tosrc (0, 1, diff, 0);
1516 		nbits2 -= diff;
1517 		if (todisplay_fetched[0]) {
1518 			for (int i = 0; i < toscr_nr_planes_shifter; i++)
1519 				todisplay2[i] = todisplay[i];
1520 			todisplay_fetched[0] = false;
1521 			todisplay_fetched[1] = false;
1522 		}
1523 	}
1524 	if (nbits2)
1525 		do_tosrc (0, 1, nbits2, 0);
1526 }
1527 
1528 #ifdef AGA
1529 
1530 STATIC_INLINE void do_delays_3_aga (int nbits, int fm)
1531 {
1532 	int delaypos = delay_cycles & fetchmode_mask;
1533 	for (int oddeven = 0; oddeven < 2; oddeven++) {
1534 		int delay = toscr_delay[oddeven];
1535 		if (delaypos > delay)
1536 			delay += fetchmode_size;
1537 		int diff = delay - delaypos;
1538 		int nbits2 = nbits;
1539 		if (nbits2 > diff) {
1540 			do_tosrc (oddeven, 2, diff, fm);
1541 			nbits2 -= diff;
1542 			if (todisplay_fetched[oddeven]) {
1543 				for (int i = oddeven; i < toscr_nr_planes_shifter; i += 2)
1544 					todisplay2_aga[i] = todisplay_aga[i];
1545 				todisplay_fetched[oddeven] = false;
1546 			}
1547 		}
1548 		if (nbits2)
1549 			do_tosrc (oddeven, 2, nbits2, fm);
1550 	}
1551 }
1552 
1553 STATIC_INLINE void do_delays_fast_3_aga (int nbits, int fm)
1554 {
1555 	int delaypos = delay_cycles & fetchmode_mask;
1556 	int delay = toscr_delay[0];
1557 	if (delaypos > delay)
1558 		delay += fetchmode_size;
1559 	int diff = delay - delaypos;
1560 	int nbits2 = nbits;
1561 	if (nbits2 > diff) {
1562 		do_tosrc (0, 1, diff, fm);
1563 		nbits2 -= diff;
1564 		if (todisplay_fetched[0]) {
1565 			for (int i = 0; i < toscr_nr_planes_shifter; i++)
1566 				todisplay2_aga[i] = todisplay_aga[i];
1567 			todisplay_fetched[0] = false;
1568 			todisplay_fetched[1] = false;
1569 		}
1570 	}
1571 	if (nbits2)
1572 		do_tosrc (0, 1, nbits2, fm);
1573 }
1574 
1575 #endif
1576 
1577 static void do_delays_2_0 (int nbits) { do_delays_3_ecs (nbits); }
1578 #ifdef AGA
1579 static void do_delays_2_1 (int nbits) { do_delays_3_aga (nbits, 1); }
1580 static void do_delays_2_2 (int nbits) { do_delays_3_aga (nbits, 2); }
1581 #endif
1582 static void do_delays_fast_2_0 (int nbits) { do_delays_fast_3_ecs (nbits); }
1583 #ifdef AGA
1584 static void do_delays_fast_2_1 (int nbits) { do_delays_fast_3_aga (nbits, 1); }
1585 static void do_delays_fast_2_2 (int nbits) { do_delays_fast_3_aga (nbits, 2); }
1586 #endif
1587 
1588 
1589 // slower version, odd and even delays are different or crosses maxhpos
1590 STATIC_INLINE void do_delays (int nbits, int fm)
1591 {
1592 	switch (fm) {
1593 	case 0:
1594 		do_delays_2_0 (nbits);
1595 		break;
1596 #ifdef AGA
1597 	case 1:
1598 		do_delays_2_1 (nbits);
1599 		break;
1600 	case 2:
1601 		do_delays_2_2 (nbits);
1602 		break;
1603 #endif
1604 	}
1605 }
1606 
1607 // common optimized case: odd delay == even delay
1608 STATIC_INLINE void do_delays_fast (int nbits, int fm)
1609 {
1610 	switch (fm) {
1611 	case 0:
1612 		do_delays_fast_2_0 (nbits);
1613 		break;
1614 #ifdef AGA
1615 	case 1:
1616 		do_delays_fast_2_1 (nbits);
1617 		break;
1618 	case 2:
1619 		do_delays_fast_2_2 (nbits);
1620 		break;
1621 #endif
1622 	}
1623 }
1624 
1625 static void toscr_right_edge (int nbits, int fm)
1626 {
1627 	// Emulate hpos counter (delay_cycles) reseting at the end of scanline.
1628 	// (Result is ugly shift in graphics in far right overscan)
1629 	int diff = delay_lastcycle[lol] - delay_cycles;
1630 	int nbits2 = nbits;
1631 	if (nbits2 >= diff) {
1632 		do_delays (diff, fm);
1633 		nbits2 -= diff;
1634 		delay_cycles = 0;
1635 		if (hpos_is_zero_bplcon1_hack >= 0) {
1636 			compute_toscr_delay(hpos_is_zero_bplcon1_hack);
1637 			hpos_is_zero_bplcon1_hack = -1;
1638 		}
1639 		toscr_delay[0] -= 2;
1640 		toscr_delay[0] &= fetchmode_mask;
1641 		toscr_delay[1] -= 2;
1642 		toscr_delay[1] &= fetchmode_mask;
1643 	}
1644 	if (nbits2) {
1645 		do_delays (nbits2, fm);
1646 		delay_cycles += nbits2;
1647 	}
1648 }
1649 
1650 STATIC_INLINE void toscr_1 (int nbits, int fm)
1651 {
1652 	if (delay_cycles + nbits >= delay_lastcycle[lol]) {
1653 		toscr_right_edge (nbits, fm);
1654 	} else if (toscr_delay[0] == toscr_delay[1]) {
1655 		// Most common case.
1656 		do_delays_fast (nbits, fm);
1657 		delay_cycles += nbits;
1658 	} else {
1659 		do_delays (nbits, fm);
1660 		delay_cycles += nbits;
1661 	}
1662 
1663 	out_nbits += nbits;
1664 	if (out_nbits == 32) {
1665 		int i;
1666 		uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
1667 		for (i = 0; i < thisline_decision.nr_planes; i++) {
1668 			uae_u32 *dataptr32 = (uae_u32 *)dataptr;
1669 			if (*dataptr32 != outword[i]) {
1670 				thisline_changed = 1;
1671 				*dataptr32 = outword[i];
1672 			}
1673 			outword[i] = 0;
1674 			dataptr += MAX_WORDS_PER_LINE * 2;
1675 		}
1676 		out_offs++;
1677 		out_nbits = 0;
1678 	}
1679 }
1680 
1681 static void toscr_fm0 (int);
1682 static void toscr_fm1 (int);
1683 static void toscr_fm2 (int);
1684 
1685 STATIC_INLINE void toscr (int nbits, int fm)
1686 {
1687 	switch (fm) {
1688 	case 0: toscr_fm0 (nbits); break;
1689 #ifdef AGA
1690 	case 1: toscr_fm1 (nbits); break;
1691 	case 2: toscr_fm2 (nbits); break;
1692 #endif
1693 	}
1694 }
1695 
1696 STATIC_INLINE void toscr_0 (int nbits, int fm)
1697 {
1698 	int t;
1699 
1700 	if (nbits > 16) {
1701 		toscr (16, fm);
1702 		nbits -= 16;
1703 	}
1704 
1705 	t = 32 - out_nbits;
1706 	if (t < nbits) {
1707 		toscr_1 (t, fm);
1708 		nbits -= t;
1709 	}
1710 	toscr_1 (nbits, fm);
1711 }
1712 
1713 static void toscr_fm0 (int nbits) { toscr_0 (nbits, 0); }
1714 static void toscr_fm1 (int nbits) { toscr_0 (nbits, 1); }
1715 static void toscr_fm2 (int nbits) { toscr_0 (nbits, 2); }
1716 
1717 static int flush_plane_data (int fm)
1718 {
1719 	int i = 0;
1720 
1721 	if (out_nbits <= 16) {
1722 		i += 16;
1723 		toscr_1 (16, fm);
1724 	}
1725 	if (out_nbits != 0) {
1726 		i += 32 - out_nbits;
1727 		toscr_1 (32 - out_nbits, fm);
1728 	}
1729 
1730 	i += 32;
1731 	toscr_1 (16, fm);
1732 	toscr_1 (16, fm);
1733 
1734 	if (fm == 2) {
1735 		/* flush AGA full 64-bit shift register + possible data in todisplay */
1736 		i += 32;
1737 		toscr_1 (16, fm);
1738 		toscr_1 (16, fm);
1739 		i += 32;
1740 		toscr_1 (16, fm);
1741 		toscr_1 (16, fm);
1742 	}
1743 
1744 	return i >> (1 + toscr_res);
1745 }
1746 
1747 STATIC_INLINE void flush_display (int fm)
1748 {
1749 	if (toscr_nbits > 0 && thisline_decision.plfleft >= 0)
1750 		toscr (toscr_nbits, fm);
1751 	toscr_nbits = 0;
1752 }
1753 
1754 static void record_color_change(int hpos, int regno, unsigned long value);
1755 
1756 static void hack_shres_delay(int hpos)
1757 {
1758 	if (!(currprefs.chipset_mask & CSMASK_AGA) && !toscr_delay_sh[0] && !toscr_delay_sh[1])
1759 		return;
1760 	int o0 = toscr_delay_sh[0];
1761 	int o1 = toscr_delay_sh[1];
1762 	int shdelay1 = (bplcon1 >> 8) & 3;
1763 	int shdelay2 = (bplcon1 >> 12) & 3;
1764 	toscr_delay_sh[0] = (shdelay1 & 3) >> toscr_res;
1765 	toscr_delay_sh[1] = (shdelay2 & 3) >> toscr_res;
1766 	if (hpos >= 0 && toscr_delay_sh[0] != o0 || toscr_delay_sh[1] != o1) {
1767 		record_color_change(hpos, 0, COLOR_CHANGE_SHRES_DELAY | toscr_delay_sh[0]);
1768 		current_colors.extra &= ~(1 << CE_SHRES_DELAY);
1769 		current_colors.extra &= ~(1 << (CE_SHRES_DELAY + 1));
1770 		current_colors.extra |= toscr_delay_sh[0] << CE_SHRES_DELAY;
1771 		remembered_color_entry = -1;
1772 	}
1773 }
1774 
1775 static void update_denise_shifter_planes (int hpos)
1776 {
1777 	int np = GET_PLANES (bplcon0d);
1778 	// if DMA has ended but there is still data waiting in todisplay,
1779 	// it must be flushed out before number of planes change
1780 	if (np < toscr_nr_planes_shifter && hpos > thisline_decision.plfright && thisline_decision.plfright && (todisplay_fetched[0] || todisplay_fetched[1])) {
1781 		int diff = (hpos - thisline_decision.plfright) << (1 + toscr_res);
1782 		while (diff >= 16) {
1783 			toscr_1 (16, fetchmode);
1784 			diff -= 16;
1785 		}
1786 		if (diff)
1787 			toscr_1 (diff, fetchmode);
1788 		thisline_decision.plfright += hpos - thisline_decision.plfright;
1789 	}
1790 	// FIXME: Samplers / Back In 90 vs Disposable Hero title screen in fast modes
1791 	if (currprefs.cpu_model < 68020) {
1792 		toscr_nr_planes_shifter = np;
1793 		if (isocs7planes()) {
1794 			if (toscr_nr_planes_shifter < 6)
1795 				toscr_nr_planes_shifter = 6;
1796 		}
1797 	}
1798 }
1799 
1800 static void update_denise (int hpos)
1801 {
1802 	int res = GET_RES_DENISE (bplcon0d);
1803 	if (res != toscr_res)
1804 		flush_display (fetchmode);
1805 	toscr_res = GET_RES_DENISE (bplcon0d);
1806 	toscr_res2p = 2 << toscr_res;
1807 	delay_cycles = (hpos * 2) << toscr_res;
1808 	if (bplcon0dd != bplcon0d) {
1809 		record_color_change2 (hpos, 0x100 + 0x1000, bplcon0d);
1810 		bplcon0dd = bplcon0d;
1811 	}
1812 	toscr_nr_planes = GET_PLANES (bplcon0d);
1813 	if (isocs7planes ()) {
1814 		if (toscr_nr_planes2 < 6)
1815 			toscr_nr_planes2 = 6;
1816 	} else {
1817 		toscr_nr_planes2 = toscr_nr_planes;
1818 	}
1819 	toscr_nr_planes_shifter = toscr_nr_planes2;
1820 	hack_shres_delay(hpos);
1821 }
1822 
1823 STATIC_INLINE void fetch_start (int hpos)
1824 {
1825 	fetch_state = fetch_started;
1826 }
1827 
1828 /* Called when all planes have been fetched, i.e. when a new block
1829 of data is available to be displayed.  The data in fetched[] is
1830 moved into todisplay[].  */
1831 static void beginning_of_plane_block (int hpos, int fm)
1832 {
1833 	int i;
1834 
1835 	if (fm == 0)
1836 		for (i = 0; i < MAX_PLANES; i++) {
1837 			todisplay[i] = fetched[i];
1838 		}
1839 #ifdef AGA
1840 	else
1841 		for (i = 0; i < MAX_PLANES; i++) {
1842 			todisplay_aga[i] = fetched_aga[i];
1843 		}
1844 #endif
1845 	todisplay_fetched[0] = todisplay_fetched[1] = true;
1846 	maybe_first_bpl1dat (hpos);
1847 	update_denise (hpos);
1848 	if (toscr_nr_planes_agnus > thisline_decision.nr_planes)
1849 		update_toscr_planes (fm);
1850 }
1851 
1852 
1853 #if SPEEDUP
1854 
1855 /* The usual inlining tricks - don't touch unless you know what you are doing. */
1856 STATIC_INLINE void long_fetch_16 (int plane, int nwords, int weird_number_of_bits, int dma)
1857 {
1858 	uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane], nwords * 2);
1859 	int delay = toscr_delay_adjusted[plane & 1];
1860 	int tmp_nbits = out_nbits;
1861 	uae_u32 shiftbuffer;
1862 	uae_u32 outval = outword[plane];
1863 	uae_u32 fetchval = fetched[plane];
1864 	uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
1865 
1866 	if (dma) {
1867 		bplpt[plane] += nwords * 2;
1868 		bplptx[plane] += nwords * 2;
1869 	}
1870 
1871 	if (real_pt == 0)
1872 		/* @@@ Don't do this, fall back on chipmem_wget instead.  */
1873 		return;
1874 
1875 	shiftbuffer = todisplay2[plane] << delay;
1876 
1877 	while (nwords > 0) {
1878 		int bits_left = 32 - tmp_nbits;
1879 		uae_u32 t;
1880 
1881 		shiftbuffer |= fetchval;
1882 
1883 		t = (shiftbuffer >> delay) & 0xffff;
1884 
1885 		if (weird_number_of_bits && bits_left < 16) {
1886 			outval <<= bits_left;
1887 			outval |= t >> (16 - bits_left);
1888 			thisline_changed |= *dataptr ^ outval;
1889 			*dataptr++ = outval;
1890 
1891 			outval = t;
1892 			tmp_nbits = 16 - bits_left;
1893 		} else {
1894 			outval = (outval << 16) | t;
1895 			tmp_nbits += 16;
1896 			if (tmp_nbits == 32) {
1897 				thisline_changed |= *dataptr ^ outval;
1898 				*dataptr++ = outval;
1899 				tmp_nbits = 0;
1900 			}
1901 		}
1902 		shiftbuffer <<= 16;
1903 		nwords--;
1904 		if (dma) {
1905 			fetchval = do_get_mem_word (real_pt);
1906 #if 0
1907 			if (plane == 0)
1908 				fetchval ^= 0x55555555;
1909 #endif
1910 			real_pt++;
1911 		}
1912 	}
1913 	fetched[plane] = fetchval;
1914 	todisplay2[plane] = shiftbuffer >> delay;
1915 	outword[plane] = outval;
1916 }
1917 
1918 #ifdef AGA
1919 STATIC_INLINE void long_fetch_32 (int plane, int nwords, int weird_number_of_bits, int dma)
1920 {
1921 	uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane], nwords * 2);
1922 	int delay = toscr_delay_adjusted[plane & 1];
1923 	int tmp_nbits = out_nbits;
1924 	uae_u64 shiftbuffer;
1925 	uae_u32 outval = outword[plane];
1926 	uae_u32 fetchval = fetched_aga[plane];
1927 	uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
1928 
1929 	if (dma) {
1930 		bplpt[plane] += nwords * 2;
1931 		bplptx[plane] += nwords * 2;
1932 	}
1933 
1934 	if (real_pt == 0)
1935 		/* @@@ Don't do this, fall back on chipmem_wget instead.  */
1936 		return;
1937 
1938 	shiftbuffer = todisplay2_aga[plane] << delay;
1939 
1940 	while (nwords > 0) {
1941 
1942 		shiftbuffer |= fetchval;
1943 
1944 		for (int i = 0; i < 2; i++) {
1945 			uae_u32 t;
1946 			int bits_left = 32 - tmp_nbits;
1947 
1948 			t = (shiftbuffer >> (16 + delay)) & 0xffff;
1949 
1950 			if (weird_number_of_bits && bits_left < 16) {
1951 				outval <<= bits_left;
1952 				outval |= t >> (16 - bits_left);
1953 
1954 				thisline_changed |= *dataptr ^ outval;
1955 				*dataptr++ = outval;
1956 
1957 				outval = t;
1958 				tmp_nbits = 16 - bits_left;
1959 			} else {
1960 				outval = (outval << 16) | t;
1961 				tmp_nbits += 16;
1962 				if (tmp_nbits == 32) {
1963 					thisline_changed |= *dataptr ^ outval;
1964 					*dataptr++ = outval;
1965 					tmp_nbits = 0;
1966 				}
1967 			}
1968 			shiftbuffer <<= 16;
1969 		}
1970 		nwords -= 2;
1971 		if (dma) {
1972 			fetchval = do_get_mem_long (real_pt);
1973 			real_pt++;
1974 #if 0
1975 			if (plane == 0)
1976 				fetchval ^= 0x5555555555555555;
1977 #endif
1978 		}
1979 
1980 	}
1981 	fetched_aga[plane] = fetchval;
1982 	todisplay2_aga[plane] = (shiftbuffer >> delay) & 0xffffffff;
1983 	outword[plane] = outval;
1984 }
1985 
1986 #ifdef HAVE_UAE_U128
1987 /* uae_u128 is available, custom shift functions not necessary */
1988 #else
1989 
1990 STATIC_INLINE void shift32plus (uae_u64 *p, int n)
1991 {
1992 	uae_u64 t = p[1];
1993 	t <<= n;
1994 	t |= p[0] >> (64 - n);
1995 	p[1] = t;
1996 }
1997 
1998 STATIC_INLINE void aga_shift (uae_u64 *p, int n)
1999 {
2000 	if (n == 0) return;
2001 	shift32plus (p, n);
2002 	p[0] <<= n;
2003 }
2004 
2005 STATIC_INLINE void shift32plusn (uae_u64 *p, int n)
2006 {
2007 	uae_u64 t = p[0];
2008 	t >>= n;
2009 	t |= p[1] << (64 - n);
2010 	p[0] = t;
2011 }
2012 
2013 STATIC_INLINE void aga_shift_n (uae_u64 *p, int n)
2014 {
2015 	if (n == 0) return;
2016 	shift32plusn (p, n);
2017 	p[1] >>= n;
2018 }
2019 
2020 #endif
2021 
2022 STATIC_INLINE void long_fetch_64 (int plane, int nwords, int weird_number_of_bits, int dma)
2023 {
2024 	uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane], nwords * 2);
2025 	int delay = toscr_delay_adjusted[plane & 1];
2026 	int tmp_nbits = out_nbits;
2027 #ifdef HAVE_UAE_U128
2028 	uae_u128 shiftbuffer;
2029 #else
2030 	uae_u64 shiftbuffer[2];
2031 #endif
2032 	uae_u32 outval = outword[plane];
2033 	uae_u64 fetchval = fetched_aga[plane];
2034 	uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
2035 	int shift = (64 - 16) + delay;
2036 
2037 	if (dma) {
2038 		bplpt[plane] += nwords * 2;
2039 		bplptx[plane] += nwords * 2;
2040 	}
2041 
2042 	if (real_pt == 0)
2043 		/* @@@ Don't do this, fall back on chipmem_wget instead.  */
2044 		return;
2045 
2046 #ifdef HAVE_UAE_U128
2047 	shiftbuffer = ((uae_u128) todisplay2_aga[plane]) << delay;
2048 #else
2049 	shiftbuffer[1] = 0;
2050 	shiftbuffer[0] = todisplay2_aga[plane];
2051 	aga_shift (shiftbuffer, delay);
2052 #endif
2053 
2054 	while (nwords > 0) {
2055 		int i;
2056 
2057 #ifdef HAVE_UAE_U128
2058 		shiftbuffer |= fetchval;
2059 #else
2060 		shiftbuffer[0] |= fetchval;
2061 #endif
2062 
2063 		for (i = 0; i < 4; i++) {
2064 			uae_u32 t;
2065 			int bits_left = 32 - tmp_nbits;
2066 
2067 #ifdef HAVE_UAE_U128
2068 			t = (shiftbuffer >> shift) & 0xffff;
2069 #else
2070 			if (64 - shift > 0) {
2071 				t = shiftbuffer[1] << (64 - shift);
2072 				t |= shiftbuffer[0] >> shift;
2073 			} else {
2074 				t = shiftbuffer[1] >> (shift - 64);
2075 			}
2076 			t &= 0xffff;
2077 #endif
2078 
2079 			if (weird_number_of_bits && bits_left < 16) {
2080 				outval <<= bits_left;
2081 				outval |= t >> (16 - bits_left);
2082 
2083 				thisline_changed |= *dataptr ^ outval;
2084 				*dataptr++ = outval;
2085 
2086 				outval = t;
2087 				tmp_nbits = 16 - bits_left;
2088 			} else {
2089 				outval = (outval << 16) | t;
2090 				tmp_nbits += 16;
2091 				if (tmp_nbits == 32) {
2092 					thisline_changed |= *dataptr ^ outval;
2093 					*dataptr++ = outval;
2094 					tmp_nbits = 0;
2095 				}
2096 			}
2097 #ifdef HAVE_UAE_U128
2098 			shiftbuffer <<= 16;
2099 #else
2100 			aga_shift (shiftbuffer, 16);
2101 #endif
2102 		}
2103 
2104 		nwords -= 4;
2105 
2106 		if (dma) {
2107 			fetchval = ((uae_u64)do_get_mem_long (real_pt)) << 32;
2108 			fetchval |= do_get_mem_long (real_pt + 1);
2109 #if 0
2110 			if (plane == 0)
2111 				fetchval ^= 0x5555555555555555;
2112 #endif
2113 			real_pt += 2;
2114 		}
2115 	}
2116 	fetched_aga[plane] = fetchval;
2117 #ifdef HAVE_UAE_U128
2118 	todisplay2_aga[plane] = shiftbuffer >> delay;
2119 #else
2120 	aga_shift_n (shiftbuffer, delay);
2121 	todisplay2_aga[plane] = shiftbuffer[0];
2122 #endif
2123 	outword[plane] = outval;
2124 }
2125 #endif
2126 
2127 static void long_fetch_16_0 (int hpos, int nwords, int dma) { long_fetch_16 (hpos, nwords, 0, dma); }
2128 static void long_fetch_16_1 (int hpos, int nwords, int dma) { long_fetch_16 (hpos, nwords, 1, dma); }
2129 #ifdef AGA
2130 static void long_fetch_32_0 (int hpos, int nwords, int dma) { long_fetch_32 (hpos, nwords, 0, dma); }
2131 static void long_fetch_32_1 (int hpos, int nwords, int dma) { long_fetch_32 (hpos, nwords, 1, dma); }
2132 static void long_fetch_64_0 (int hpos, int nwords, int dma) { long_fetch_64 (hpos, nwords, 0, dma); }
2133 static void long_fetch_64_1 (int hpos, int nwords, int dma) { long_fetch_64 (hpos, nwords, 1, dma); }
2134 #endif
2135 
2136 static void do_long_fetch (int hpos, int nwords, int dma, int fm)
2137 {
2138 	int i;
2139 
2140 	flush_display (fm);
2141 	beginning_of_plane_block (hpos, fm);
2142 
2143 	switch (fm) {
2144 	case 0:
2145 		if (out_nbits & 15) {
2146 			for (i = 0; i < toscr_nr_planes; i++)
2147 				long_fetch_16_1 (i, nwords, dma);
2148 		} else {
2149 			for (i = 0; i < toscr_nr_planes; i++)
2150 				long_fetch_16_0 (i, nwords, dma);
2151 		}
2152 		break;
2153 #ifdef AGA
2154 	case 1:
2155 		if (out_nbits & 15) {
2156 			for (i = 0; i < toscr_nr_planes; i++)
2157 				long_fetch_32_1 (i, nwords, dma);
2158 		} else {
2159 			for (i = 0; i < toscr_nr_planes; i++)
2160 				long_fetch_32_0 (i, nwords, dma);
2161 		}
2162 		break;
2163 	case 2:
2164 		if (out_nbits & 15) {
2165 			for (i = 0; i < toscr_nr_planes; i++)
2166 				long_fetch_64_1 (i, nwords, dma);
2167 		} else {
2168 			for (i = 0; i < toscr_nr_planes; i++)
2169 				long_fetch_64_0 (i, nwords, dma);
2170 		}
2171 		break;
2172 #endif
2173 	}
2174 
2175 	out_nbits += nwords * 16;
2176 	out_offs += out_nbits >> 5;
2177 	out_nbits &= 31;
2178 	delay_cycles += nwords * 16;
2179 
2180 	if (dma && toscr_nr_planes > 0)
2181 		fetch_state = fetch_was_plane0;
2182 }
2183 
2184 #endif
2185 
2186 static void finish_last_fetch (int pos, int fm, bool reallylast)
2187 {
2188 	if (thisline_decision.plfleft < 0)
2189 		return;
2190 	if (plfr_state >= plfr_end)
2191 		return;
2192 	plfr_state = plfr_end;
2193 
2194 	flush_display (fm);
2195 	// This may not be the last fetch, store current endpos for future use.
2196 	// There is at least one demo that has two DDFSTRT-DDFSTOP horizontal sections
2197 	// Subtle Shades / Nuance.
2198 	thisline_decision.plfright = pos;
2199 
2200 	if (!reallylast) {
2201 		if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
2202 			ddfstate = DIW_waiting_start;
2203 			fetch_state = fetch_not_started;
2204 		}
2205 	}
2206 }
2207 /* check special case where last fetch wraps to next line
2208  * this makes totally corrupted and flickering display on
2209  * real hardware due to refresh cycle conflicts
2210  */
2211 static void maybe_finish_last_fetch (int pos, int fm)
2212 {
2213 	static int warned = 20;
2214 	bool done = false;
2215 
2216 	if (plf_state != plf_passed_stop2 || (fetch_state != fetch_started && fetch_state != fetch_started_first) || aga_plf_passed_stop2 || !dmaen (DMA_BITPLANE)) {
2217 		finish_last_fetch (pos, fm, true);
2218 		return;
2219 	}
2220 	do {
2221 		int cycle_start = fetch_cycle & fetchstart_mask;
2222 		switch (fm_maxplane) {
2223 		case 8:
2224 			switch (cycle_start) {
2225 			case 0: fetch (7, fm, pos); break;
2226 			case 1: fetch (3, fm, pos); break;
2227 			case 2: fetch (5, fm, pos); break;
2228 			case 3: fetch (1, fm, pos); break;
2229 			case 4: fetch (6, fm, pos); break;
2230 			case 5: fetch (2, fm, pos); break;
2231 			case 6: fetch (4, fm, pos); break;
2232 			case 7: fetch (0, fm, pos); break;
2233 			default:
2234 			goto end;
2235 			}
2236 			break;
2237 		case 4:
2238 			switch (cycle_start) {
2239 			case 0: fetch (3, fm, pos); break;
2240 			case 1: fetch (1, fm, pos); break;
2241 			case 2: fetch (2, fm, pos); break;
2242 			case 3: fetch (0, fm, pos); break;
2243 			default:
2244 			goto end;
2245 			}
2246 			break;
2247 		case 2:
2248 			switch (cycle_start) {
2249 			case 0: fetch (1, fm, pos); break;
2250 			case 1: fetch (0, fm, pos); break;
2251 			default:
2252 			goto end;
2253 			}
2254 			break;
2255 		}
2256 		fetch_cycle++;
2257 		toscr_nbits += toscr_res2p;
2258 
2259 		if (toscr_nbits > 16)
2260 			toscr_nbits = 0;
2261 		if (toscr_nbits == 16)
2262 			flush_display (fm);
2263 		done = true;
2264 		bitplane_line_crossing = pos;
2265 	} while ((fetch_cycle & fetchunit_mask) != 0);
2266 
2267 	if (done && warned > 0) {
2268 		warned--;
2269 		write_log (_T("WARNING: bitplane DMA crossing scanlines!\n"));
2270 	}
2271 
2272 end:
2273 	finish_last_fetch (pos, fm, true);
2274 }
2275 
2276 
2277 /* make sure fetch that goes beyond maxhpos is finished */
2278 static void finish_final_fetch (void)
2279 {
2280 	if (thisline_decision.plfleft < 0)
2281 		return;
2282 
2283 	if (plfr_state < plfr_end)
2284 		finish_last_fetch (maxhpos, fetchmode, true);
2285 	plfr_state = plfr_finished;
2286 
2287 	// workaround for too long fetches that don't pass plf_passed_stop2 before end of scanline
2288 	if (aga_plf_passed_stop2 && plf_state >= plf_passed_stop)
2289 		plf_state = plf_end;
2290 
2291 	// This is really the end of scanline, we can finally flush all remaining data.
2292 	thisline_decision.plfright += flush_plane_data (fetchmode);
2293 	thisline_decision.plflinelen = out_offs;
2294 
2295 	finish_playfield_line ();
2296 }
2297 
2298 STATIC_INLINE int one_fetch_cycle_0 (int pos, int dma, int fm)
2299 {
2300 	bool bplactive = true;
2301 	bool diw = diwstate == DIW_waiting_stop;
2302 	if (plf_state == plf_wait && dma && diw) {
2303 		// same timings as when switching off, see below
2304 		bpl_dma_off_when_active = 0;
2305 		bplactive = false;
2306 		if (bitplane_off_delay >= 0)
2307 			bitplane_off_delay = !dma ? -4 : -5;
2308 		if (bitplane_off_delay < 0) {
2309 			bitplane_off_delay++;
2310 			if (bitplane_off_delay == 0) {
2311 				if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
2312 					plf_state = plf_passed_stop;
2313 				} else {
2314 					plf_state = plf_active;
2315 				}
2316 			}
2317 		}
2318 	} else if (!dma || !diw) {
2319 		bplactive = false;
2320 		// dma off: turn off bitplane output after 4 cycles
2321 		// (yes, switching DMA off won't disable it immediately)
2322 		// diw off: turn off bitplane output after 5 cycles
2323 		// (Starflight / Phenomena jumping scroller in ECS)
2324 		// This is not correctly emulated, there probably is
2325 		// 4+ stage shift register that causes these delays.
2326 		if (plf_state == plf_active || plf_state == plf_passed_stop || plf_state == plf_passed_stop_act) {
2327 			bpl_dma_off_when_active = 1;
2328 			if (bitplane_off_delay <= 0)
2329 				bitplane_off_delay = !dma ? 4 : 5;
2330 		}
2331 		if (bitplane_off_delay > 0) {
2332 			bplactive = true;
2333 			bitplane_off_delay--;
2334 			if (bitplane_off_delay == 0) {
2335 				bplactive = false;
2336 				plf_state = plf_wait;
2337 			}
2338 		}
2339 	}
2340 
2341 	if ((dma && diw) || (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
2342 		if (plf_state != plf_wait) {
2343 			if (pos == plfstop && ddfstop_written_hpos != pos) {
2344 				if (plf_state < plf_passed_stop) {
2345 					plf_state = plf_passed_stop;
2346 				}
2347 				plf_end_hpos = pos + DDF_OFFSET;
2348 			} else if (pos == plf_end_hpos) {
2349 				ddfstop_matched = true;
2350 				if (plf_state < plf_passed_stop_act) {
2351 					plf_state = plf_passed_stop_act;
2352 				}
2353 			}
2354 		}
2355 	}
2356 
2357 	if ((fetch_cycle & fetchunit_mask) == 0) {
2358 		if (plf_state == plf_passed_stop2) {
2359 			finish_last_fetch(pos, fm, false);
2360 			return 1;
2361 		}
2362 		if (plf_state == plf_passed_stop_act) {
2363 			plf_state = plf_passed_stop2;
2364 		}
2365 	}
2366 
2367 	// must be after above test, otherwise same fetch
2368 	// block may pass both stop_act and stop2 tests.
2369 	if (pos == HARD_DDF_STOP) {
2370 		if (plf_state < plf_wait) {
2371 			plf_state = plf_passed_stop_act;
2372 		}
2373 	}
2374 
2375 	maybe_check (pos);
2376 
2377 	if (bplactive) {
2378 		/* fetchstart_mask can be larger than fm_maxplane if FMODE > 0.  This means
2379 		that the remaining cycles are idle; we'll fall through the whole switch
2380 		without doing anything.  */
2381 		int cycle_start = fetch_cycle & fetchstart_mask;
2382 		switch (fm_maxplane) {
2383 		case 8:
2384 			switch (cycle_start) {
2385 			case 0: fetch (7, fm, pos); break;
2386 			case 1: fetch (3, fm, pos); break;
2387 			case 2: fetch (5, fm, pos); break;
2388 			case 3: fetch (1, fm, pos); break;
2389 			case 4: fetch (6, fm, pos); break;
2390 			case 5: fetch (2, fm, pos); break;
2391 			case 6: fetch (4, fm, pos); break;
2392 			case 7: fetch (0, fm, pos); break;
2393 #ifdef AGA
2394 			default:
2395 			// if AGA: consider plf_passed_stop2 already
2396 			// active when last plane has been written,
2397 			// even if there is still idle cycles left
2398 			if (plf_state == plf_passed_stop_act)
2399 				aga_plf_passed_stop2 = true;
2400 			break;
2401 #endif
2402 			}
2403 			break;
2404 		case 4:
2405 			switch (cycle_start) {
2406 			case 0: fetch (3, fm, pos); break;
2407 			case 1: fetch (1, fm, pos); break;
2408 			case 2: fetch (2, fm, pos); break;
2409 			case 3: fetch (0, fm, pos); break;
2410 #ifdef AGA
2411 			default:
2412 			if (plf_state == plf_passed_stop_act)
2413 				aga_plf_passed_stop2 = true;
2414 			break;
2415 #endif
2416 			}
2417 			break;
2418 		case 2:
2419 			switch (cycle_start) {
2420 			case 0: fetch (1, fm, pos); break;
2421 			case 1: fetch (0, fm, pos); break;
2422 #ifdef AGA
2423 			default:
2424 			if (plf_state == plf_passed_stop_act)
2425 				aga_plf_passed_stop2 = true;
2426 			break;
2427 #endif
2428 			}
2429 			break;
2430 		}
2431 	}
2432 
2433 	if (bpl1dat_written) {
2434 		// do this here because if program plays with BPLCON0 during scanline
2435 		// it is possible that one DMA BPL1DAT write is completely missed
2436 		// and we must not draw anything at all in next dma block if this happens
2437 		// (Disposable Hero titlescreen)
2438 		fetch_state = fetch_was_plane0;
2439 		bpl1dat_written = false;
2440 	}
2441 
2442 	fetch_cycle++;
2443 	toscr_nbits += toscr_res2p;
2444 
2445 	if (bplcon1_written) {
2446 		flush_display (fm);
2447 		compute_toscr_delay (bplcon1);
2448 		bplcon1_written = false;
2449 	}
2450 
2451 	if (toscr_nbits > 16) {
2452 		uae_abort (_T("toscr_nbits > 16 (%d)"), toscr_nbits);
2453 		toscr_nbits = 0;
2454 	}
2455 	if (toscr_nbits == 16)
2456 		flush_display (fm);
2457 
2458 	return 0;
2459 }
2460 
2461 static int one_fetch_cycle_fm0 (int pos, int dma) { return one_fetch_cycle_0 (pos, dma, 0); }
2462 static int one_fetch_cycle_fm1 (int pos, int dma) { return one_fetch_cycle_0 (pos, dma, 1); }
2463 static int one_fetch_cycle_fm2 (int pos, int dma) { return one_fetch_cycle_0 (pos, dma, 2); }
2464 
2465 STATIC_INLINE int one_fetch_cycle (int pos, int dma, int fm)
2466 {
2467 	switch (fm) {
2468 	case 0: return one_fetch_cycle_fm0 (pos, dma);
2469 #ifdef AGA
2470 	case 1: return one_fetch_cycle_fm1 (pos, dma);
2471 	case 2: return one_fetch_cycle_fm2 (pos, dma);
2472 #endif
2473 	default: uae_abort (_T("fm corrupt")); return 0;
2474 	}
2475 }
2476 
2477 static void update_fetch_x (int until, int fm)
2478 {
2479 	int pos;
2480 
2481 	if (nodraw ())
2482 		return;
2483 
2484 	pos = last_fetch_hpos;
2485 	update_toscr_planes (fm);
2486 
2487 	// not optimized, update_fetch_x() is extremely rarely used.
2488 	for (; pos < until; pos++) {
2489 
2490 		toscr_nbits += toscr_res2p;
2491 
2492 		if (toscr_nbits > 16) {
2493 			uae_abort (_T("xtoscr_nbits > 16 (%d)"), toscr_nbits);
2494 			toscr_nbits = 0;
2495 		}
2496 		if (toscr_nbits == 16)
2497 			flush_display (fm);
2498 
2499 	}
2500 
2501 	if (until >= maxhpos) {
2502 		maybe_finish_last_fetch (pos, fm);
2503 		return;
2504 	}
2505 
2506 	flush_display (fm);
2507 }
2508 
2509 static void update_fetch (int until, int fm)
2510 {
2511 	int pos;
2512 	int dma = dmaen (DMA_BITPLANE);
2513 
2514 	if (nodraw () || plf_state >= plf_end)
2515 		return;
2516 
2517 	pos = last_fetch_hpos;
2518 	cycle_diagram_shift = last_fetch_hpos - fetch_cycle;
2519 
2520 	/* First, a loop that prepares us for the speedup code.  We want to enter
2521 	the SPEEDUP case with fetch_state == fetch_was_plane0 or it is the very
2522 	first fetch cycle (which equals to same state as fetch_was_plane0)
2523     and then unroll whole blocks, so that we end on the same fetch_state again.  */
2524 	for (; ; pos++) {
2525 		if (pos == until) {
2526 			if (until >= maxhpos) {
2527 				maybe_finish_last_fetch (pos, fm);
2528 				return;
2529 			}
2530 			return;
2531 		}
2532 
2533 		if (fetch_state == fetch_was_plane0)
2534 			break;
2535 #if 0
2536 		if (fetch_state == fetch_started_first) {
2537 #if SPEEDUP
2538 			if (until >= maxhpos) {
2539 				fetch_state = fetch_was_plane0;
2540 				break;
2541 			}
2542 #endif
2543 			fetch_state = fetch_started;
2544 		}
2545 #endif
2546 		fetch_start (pos);
2547 		if (one_fetch_cycle (pos, dma, fm))
2548 			return;
2549 	}
2550 
2551 #if SPEEDUP
2552 	/* Unrolled version of the for loop below.  */
2553 	if (plf_state == plf_active && !line_cyclebased && dma
2554 		&& (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask)
2555 		&& !badmode
2556 #ifdef DEBUGGER
2557 		&& !debug_dma
2558 #endif
2559 		&& toscr_nr_planes == toscr_nr_planes_agnus)
2560 	{
2561 		int ddfstop_to_test_ddf = HARD_DDF_STOP;
2562 		if (plfstop >= last_fetch_hpos - DDF_OFFSET && plfstop < ddfstop_to_test_ddf)
2563 			ddfstop_to_test_ddf = plfstop;
2564 		int ddfstop_to_test = ddfstop_to_test_ddf + DDF_OFFSET;
2565 		int offs = (pos - fetch_cycle) & fetchunit_mask;
2566 		int ddf2 = ((ddfstop_to_test - offs + fetchunit - 1) & ~fetchunit_mask) + offs;
2567 		int ddf3 = ddf2 + fetchunit;
2568 		int stop = until < ddf2 ? until : until < ddf3 ? ddf2 : ddf3;
2569 		int count;
2570 
2571 		count = stop - pos;
2572 		if (count >= fetchstart) {
2573 			count &= ~fetchstart_mask;
2574 			int stoppos = pos + count;
2575 
2576 			if (thisline_decision.plfleft < 0) {
2577 				compute_toscr_delay (bplcon1);
2578 			}
2579 
2580 			do_long_fetch (pos, count >> (3 - toscr_res), dma, fm);
2581 
2582 			/* This must come _after_ do_long_fetch so as not to confuse flush_display
2583 			into thinking the first fetch has produced any output worth emitting to
2584 			the screen.  But the calculation of delay_offset must happen _before_.  */
2585 			maybe_first_bpl1dat (pos);
2586 
2587 			if (pos <= plfstop && stoppos > plfstop) {
2588 				plf_state = plf_passed_stop;
2589 				plf_end_hpos = plfstop + DDF_OFFSET;
2590 			}
2591 			if (pos <= plfstop + DDF_OFFSET && stoppos > plfstop + DDF_OFFSET) {
2592 				plf_state = plf_passed_stop_act;
2593 				plf_end_hpos = 256 + DDF_OFFSET;
2594 				ddfstop_matched = true;
2595 			}
2596 			if (pos <= HARD_DDF_STOP && stoppos > HARD_DDF_STOP) {
2597 				if (plf_state < plf_wait)
2598 					plf_state = plf_passed_stop_act;
2599 			}
2600 			if (pos <= ddfstop_to_test && stoppos > ddf2) {
2601 				plf_state = plf_passed_stop2;
2602 			}
2603 			if (pos <= ddf2 && stoppos >= ddf2 + fm_maxplane) {
2604 				add_modulos ();
2605 			}
2606 			pos += count;
2607 			fetch_cycle += count;
2608 		}
2609 	}
2610 #endif
2611 	for (; pos < until; pos++) {
2612 
2613 		if (fetch_state == fetch_was_plane0) {
2614 			flush_display (fm);
2615 			beginning_of_plane_block (pos, fm);
2616 		}
2617 
2618 		fetch_start (pos);
2619 
2620 		if (one_fetch_cycle (pos, dma, fm))
2621 			return;
2622 	}
2623 	if (until >= maxhpos) {
2624 		maybe_finish_last_fetch (pos, fm);
2625 		return;
2626 	}
2627 	flush_display (fm);
2628 }
2629 
2630 static void update_fetch_0 (int hpos) { update_fetch (hpos, 0); }
2631 static void update_fetch_1 (int hpos) { update_fetch (hpos, 1); }
2632 static void update_fetch_2 (int hpos) { update_fetch (hpos, 2); }
2633 
2634 static void decide_fetch (int hpos)
2635 {
2636 	if (hpos > last_fetch_hpos) {
2637 		if (fetch_state != fetch_not_started) {
2638 			switch (fetchmode) {
2639 			case 0: update_fetch_0 (hpos); break;
2640 #ifdef AGA
2641 			case 1: update_fetch_1 (hpos); break;
2642 			case 2: update_fetch_2 (hpos); break;
2643 #endif
2644 			default: uae_abort (_T("fetchmode corrupt"));
2645 			}
2646 		} else if (bpl1dat_written_at_least_once) {
2647 			// "PIO" mode display
2648 			update_fetch_x (hpos, fetchmode);
2649 			bpl1dat_written = false;
2650 		}
2651 
2652 		maybe_check (hpos);
2653 		last_fetch_hpos = hpos;
2654 	}
2655 }
2656 
2657 STATIC_INLINE void decide_fetch_safe (int hpos)
2658 {
2659 	if (!blitter_dangerous_bpl) {
2660 		decide_fetch (hpos);
2661 		decide_blitter (hpos);
2662 	} else {
2663 		while (hpos > last_fetch_hpos) {
2664 			decide_fetch (last_fetch_hpos + 1);
2665 			decide_blitter (last_fetch_hpos + 1);
2666 		}
2667 	}
2668 }
2669 
2670 static void reset_bpl_vars (void)
2671 {
2672 	out_nbits = 0;
2673 	out_offs = 0;
2674 	toscr_nbits = 0;
2675 	thisline_decision.bplres = bplcon0_res;
2676 }
2677 
2678 static void start_bpl_dma (int hstart)
2679 {
2680 	if (first_bpl_vpos < 0)
2681 		first_bpl_vpos = vpos;
2682 
2683 	if (doflickerfix () && interlace_seen > 0 && !scandoubled_line) {
2684 		int i;
2685 		for (i = 0; i < 8; i++) {
2686 			prevbpl[lof_current][vpos][i] = bplptx[i];
2687 			if (!lof_current && (bplcon0 & 4))
2688 				bplpt[i] = prevbpl[1 - lof_current][vpos][i];
2689 			if (!(bplcon0 & 4) || interlace_seen < 0)
2690 				prevbpl[1 - lof_current][vpos][i] = prevbpl[lof_current][vpos][i] = 0;
2691 		}
2692 	}
2693 
2694 #if 0
2695 	fetch_state = (fm_maxplane == fetchstart) ? fetch_started_first : fetch_started;
2696 #else
2697 	fetch_state = fetch_started;
2698 #endif
2699 	plfr_state = plfr_active;
2700 	ddfstate = DIW_waiting_stop;
2701 	bpl_hstart = hstart;
2702 
2703 	if (!bpldmawasactive) {
2704 
2705 		if (last_fetch_hpos < 0)
2706 			last_fetch_hpos = 0;
2707 		plfstrt_sprite = hstart;
2708 		// OCS Agnus needs at least 1 empty cycle between
2709 		// sprite fetch and bitplane cycle sequence start.
2710 		if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2711 			plfstrt_sprite--;
2712 		fetch_cycle = 0;
2713 		update_denise (last_fetch_hpos);
2714 		if (bpl1dat_written_at_least_once && hstart > last_fetch_hpos) {
2715 			update_fetch_x (hstart, fetchmode);
2716 			bpl1dat_written_at_least_once = false;
2717 		} else {
2718 			reset_bpl_vars ();
2719 		}
2720 		cycle_diagram_shift = hstart;
2721 
2722 		bpldmawasactive = true;
2723 
2724 	} else {
2725 
2726 		flush_display (fetchmode);
2727 		// Calculate difference between last end to new start
2728 		int diff = (hstart - thisline_decision.plfright) << (1 + toscr_res);
2729 		// Render all missing pixels, use toscr because previous data may
2730 		// still be in buffers.
2731 		while (diff >= 16) {
2732 			toscr_1 (16, fetchmode);
2733 			diff -= 16;
2734 		}
2735 		if (diff)
2736 			toscr_1 (diff, fetchmode);
2737 
2738 		cycle_diagram_shift = hstart;
2739 		update_denise (last_fetch_hpos);
2740 		update_fetch_x (hstart, fetchmode);
2741 	}
2742 
2743 	last_fetch_hpos = hstart;
2744 	estimate_last_fetch_cycle (hstart);
2745 
2746 }
2747 
2748 STATIC_INLINE bool cant_this_last_line (void)
2749 {
2750 	// Last line..
2751 	// ..works normally if A1000 Agnus
2752 	if (currprefs.cs_dipagnus)
2753 		return false;
2754 	// ..inhibits bitplane and sprite DMA if later Agnus revision.
2755 	return vpos + 1 >= maxvpos + lof_store;
2756 }
2757 
2758 /* This function is responsible for turning on datafetch if necessary. */
2759 static void decide_line (int hpos)
2760 {
2761 	bool ecs = (currprefs.chipset_mask & CSMASK_ECS_AGNUS) != 0;
2762 
2763 	/* Take care of the vertical DIW.  */
2764 	if (vpos == plffirstline) {
2765 		// A1000 Agnus won't start bitplane DMA if vertical diw is zero.
2766 		if (vpos > 0 || (vpos == 0 && !currprefs.cs_dipagnus)) {
2767 			diwstate = DIW_waiting_stop;
2768 			SET_LINE_CYCLEBASED;
2769 		}
2770 	}
2771 	// last line of field can never have bitplane dma active if not A1000 Agnus.
2772 	if (vpos == plflastline || cant_this_last_line () || (vpos == 0 && currprefs.cs_dipagnus)) {
2773 		diwstate = DIW_waiting_start;
2774 		SET_LINE_CYCLEBASED;
2775 	}
2776 
2777 	if (hpos <= last_decide_line_hpos)
2778 		return;
2779 
2780 	bool dma = dmaen (DMA_BITPLANE) != 0;
2781 	bool diw = diwstate == DIW_waiting_stop;
2782 
2783 	if (ecs) {
2784 		if (1) {
2785 			if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
2786 				ddfstop_matched = false;
2787 			}
2788 		}
2789 	} else {
2790 		if (1) {
2791 			if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
2792 				ddfstop_matched = false;
2793 				// plfstrt==0 works strangely (Nakudemo / Vision-X)
2794 				if (plfstrt > -DDF_OFFSET)
2795 					ocs_agnus_ddf_enable_toggle = false;
2796 			}
2797 		}
2798 	}
2799 
2800 	if (fetch_state == fetch_not_started) {
2801 		bool strtpassed = false;
2802 		plfstate nextstate = plf_end;
2803 		int hstart;
2804 
2805 		hstart = last_decide_line_hpos;
2806 		if (hstart < bitplane_maybe_start_hpos)
2807 			hstart = bitplane_maybe_start_hpos;
2808 		if (hstart < HARD_DDF_START_REAL + DDF_OFFSET)
2809 			hstart = HARD_DDF_START_REAL + DDF_OFFSET;
2810 		// DMA enabled mid-line: DDF_OFFSET delay first
2811 		if (bitplane_maybe_start_hpos + DDF_OFFSET > hstart)
2812 			hstart = bitplane_maybe_start_hpos + DDF_OFFSET;
2813 		if (hstart & 1)
2814 			hstart++;
2815 
2816 		if (ecs) {
2817 			// ECS DDFSTRT/STOP matching does not require DMA or DIW.
2818 			if (1) {
2819 				if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
2820 					// active == already started because ddfstop was not detected in last line
2821 					if (plf_state != plf_active) {
2822 						plf_state = plf_passed_start;
2823 						strtpassed = true;
2824 						plf_start_hpos = plfstrt + DDF_OFFSET;
2825 					}
2826 				}
2827 			}
2828 			if (1) {
2829 				if ((strtpassed && hpos >= plf_start_hpos) || (last_decide_line_hpos < plf_start_hpos && hpos >= plf_start_hpos)) {
2830 					if (plf_state == plf_passed_start) {
2831 						plf_state = plf_active;
2832 						hstart = plf_start_hpos;
2833 					}
2834 				}
2835 			}
2836 		} else {
2837 			if (1) {
2838 				int start = HARD_DDF_START_REAL;
2839 				if (last_decide_line_hpos < start && hpos >= start) {
2840 					if (!ocs_agnus_ddf_enable_toggle)
2841 						plf_state = plf_passed_enable;
2842 					ocs_agnus_ddf_enable_toggle = true;
2843 				}
2844 			}
2845 			// OCS DDFSTRT/STOP matching requires DMA and DIW enabled.
2846 			if (dma && diw) {
2847 				if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
2848 					if (plf_state == plf_passed_enable) {
2849 						plf_state = plf_passed_start;
2850 						strtpassed = true;
2851 						plf_start_hpos = plfstrt + DDF_OFFSET;
2852 					}
2853 					ocs_agnus_ddf_enable_toggle = false;
2854 				}
2855 			}
2856 			if (dma && diw) {
2857 				if ((strtpassed && hpos >= plf_start_hpos) || (last_decide_line_hpos < plf_start_hpos && hpos >= plf_start_hpos)) {
2858 					if (plf_state == plf_passed_start) {
2859 						plf_state = plf_active;
2860 						hstart = plf_start_hpos;
2861 					}
2862 				}
2863 			}
2864 		}
2865 
2866 		if (diw && dma) {
2867 			bool test = false;
2868 			if (ecs) {
2869 				test = (plf_state == plf_active && (hpos >= HARD_DDF_START_REAL + DDF_OFFSET || HARD_DDF_LIMITS_DISABLED));
2870 				if (bpl_dma_off_when_active) {
2871 					if (plfstop < hstart) {
2872 						test = false;
2873 					}
2874 				}
2875 			} else {
2876 				test = (plf_state == plf_active);
2877 				// if DMA enabled mid-scanline but ddfstrt not matched (dma was off): start when ddfstop is matched
2878 				// (Crash Landing crack intro / Scoopex)
2879 				if (!test && last_decide_line_hpos < plfstop && hstart > plfstop) {
2880 					if (hstart == ((bitplane_maybe_start_hpos + DDF_OFFSET + 1) & ~1)) {
2881 						hstart = plfstop + DDF_OFFSET;
2882 						test = true;
2883 						nextstate = plf_passed_stop;
2884 					}
2885 				}
2886 			}
2887 			if (test) {
2888 				start_bpl_dma (hstart);
2889 				// if ECS: pre-set plf_end_hpos if we have already passed virtual ddfstop
2890 				if (ecs) {
2891 					if (last_decide_line_hpos < hstart && hstart >= plfstop && hstart - plfstop <= DDF_OFFSET) {
2892 						plf_end_hpos = plfstop + DDF_OFFSET;
2893 						nextstate = plf_passed_stop;
2894 					}
2895 					if (last_decide_line_hpos < HARD_DDF_STOP && hstart > HARD_DDF_STOP) {
2896 						plf_end_hpos = HARD_DDF_STOP + DDF_OFFSET;
2897 						nextstate = plf_passed_stop;
2898 					}
2899 					if (bpl_dma_off_when_active) {
2900 						nextstate = plf_passed_stop_act;
2901 						bpl_dma_off_when_active = 0;
2902 					}
2903 				}
2904 				if (nextstate != plf_end) {
2905 					plf_state = nextstate;
2906 					estimate_last_fetch_cycle(hstart);
2907 				}
2908 				last_decide_line_hpos = hpos;
2909 				do_sprites (hpos);
2910 				return;
2911 			}
2912 
2913 		}
2914 
2915 		if (ecs) {
2916 			if (1) {
2917 				// ddfstrt == ddfstop: ddfstrt wins.
2918 				if (plfstrt != plfstop && last_decide_line_hpos < plfstop && hpos >= plfstop && plfstop <= maxhpos - DDF_OFFSET) {
2919 					ddfstop_matched = true;
2920 					if (plf_state != plf_wait && plf_state < plf_passed_stop) {
2921 						plf_state = plf_passed_stop;
2922 						plf_end_hpos = plfstop + DDF_OFFSET;
2923 					}
2924 				}
2925 				if (last_decide_line_hpos < HARD_DDF_STOP && hpos >= HARD_DDF_STOP) {
2926 					plf_state = plf_passed_stop_act;
2927 				}
2928 			}
2929 		} else {
2930 			if (dma && diw) {
2931 				if (last_decide_line_hpos < plfstop && hpos >= plfstop && plfstop <= maxhpos - DDF_OFFSET && plf_state != plf_wait) {
2932 					ddfstop_matched = true;
2933 				}
2934 			}
2935 		}
2936 	}
2937 
2938 	if (hpos > last_sprite_hpos && last_sprite_hpos < SPR0_HPOS + 4 * MAX_SPRITES)
2939 		do_sprites (hpos);
2940 
2941 	last_decide_line_hpos = hpos;
2942 }
2943 
2944 /* Called when a color is about to be changed (write to a color register),
2945 * but the new color has not been entered into the table yet. */
2946 static void record_color_change (int hpos, int regno, unsigned long value)
2947 {
2948 	if (regno < 0x1000 && nodraw ())
2949 		return;
2950 	/* Early positions don't appear on-screen. */
2951 	if (vpos < minfirstline)
2952 		return;
2953 
2954 	decide_diw (hpos);
2955 	decide_line (hpos);
2956 
2957 	if (thisline_decision.ctable < 0)
2958 		remember_ctable ();
2959 
2960 	if  ((regno < 0x1000 || regno == 0x1000 + 0x10c) && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) {
2961 		struct draw_info *pdip = curr_drawinfo + prev_lineno;
2962 		int idx = pdip->last_color_change;
2963 		int extrahpos = regno == 0x1000 + 0x10c ? 1 : 0;
2964 		bool lastsync = false;
2965 		/* Move color changes in horizontal cycles 0 to HBLANK_OFFSET to end of previous line.
2966 		* Cycles 0 to HBLANK_OFFSET are visible in right border on real Amigas. (because of late hsync)
2967 		*/
2968 		if (curr_color_changes[idx - 1].regno == 0xffff) {
2969 			idx--;
2970 			lastsync = true;
2971 		}
2972 		pdip->last_color_change++;
2973 		pdip->nr_color_changes++;
2974 		curr_color_changes[idx].linepos = (hpos + maxhpos) * 2 + extrahpos;
2975 		curr_color_changes[idx].regno = regno;
2976 		curr_color_changes[idx].value = value;
2977 		if (lastsync) {
2978 			curr_color_changes[idx + 1].linepos = hsyncstartpos * 2;
2979 			curr_color_changes[idx + 1].regno = 0xffff;
2980 			curr_color_changes[idx + 2].regno = -1;
2981 		} else {
2982 			curr_color_changes[idx + 1].regno = -1;
2983 		}
2984 	}
2985 	record_color_change2 (hpos, regno, value);
2986 }
2987 
2988 static bool isbrdblank (int hpos, uae_u16 bplcon0, uae_u16 bplcon3)
2989 {
2990 	bool brdblank, brdntrans;
2991 #ifdef ECS_DENISE
2992 	brdblank = (currprefs.chipset_mask & CSMASK_ECS_DENISE) && (bplcon0 & 1) && (bplcon3 & 0x20);
2993 	brdntrans = (currprefs.chipset_mask & CSMASK_ECS_DENISE) && (bplcon0 & 1) && (bplcon3 & 0x10);
2994 #else
2995 	brdblank = false;
2996 	brdntrans = false;
2997 #endif
2998 	if (hpos >= 0 && (ce_is_borderblank(current_colors.extra) != brdblank || ce_is_borderntrans(current_colors.extra) != brdntrans)) {
2999 		record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0) | (ce_is_bordersprite(current_colors.extra) ? 2 : 0) | (brdntrans ? 4 : 0));
3000 		current_colors.extra &= ~(1 << CE_BORDERBLANK);
3001 		current_colors.extra &= ~(1 << CE_BORDERNTRANS);
3002 		current_colors.extra |= brdblank ? (1 << CE_BORDERBLANK) : 0;
3003 		current_colors.extra |= brdntrans ? (1 << CE_BORDERNTRANS) : 0;
3004 		remembered_color_entry = -1;
3005 	}
3006 	return brdblank;
3007 }
3008 
3009 static bool issprbrd (int hpos, uae_u16 bplcon0, uae_u16 bplcon3)
3010 {
3011 	bool brdsprt;
3012 #ifdef AGA
3013 	brdsprt = (currprefs.chipset_mask & CSMASK_AGA) && (bplcon0 & 1) && (bplcon3 & 0x02);
3014 #else
3015 	brdsprt = false;
3016 #endif
3017 	if (hpos >= 0 && ce_is_bordersprite(current_colors.extra) != brdsprt) {
3018 		record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (ce_is_borderblank(current_colors.extra) ? 1 : 0) | (ce_is_borderntrans(current_colors.extra) ? 4 : 0) | (brdsprt ? 2 : 0));
3019 		current_colors.extra &= ~(1 << CE_BORDERSPRITE);
3020 		current_colors.extra |= brdsprt ? (1 << CE_BORDERSPRITE) : 0;
3021 		remembered_color_entry = -1;
3022 		if (brdsprt && !ce_is_borderblank(current_colors.extra))
3023 			thisline_decision.bordersprite_seen = true;
3024 	}
3025 	return brdsprt && !ce_is_borderblank(current_colors.extra);
3026 }
3027 
3028 static void record_register_change (int hpos, int regno, uae_u16 value)
3029 {
3030 	if (regno == 0x100) { // BPLCON0
3031 		if (value & 0x800)
3032 			thisline_decision.ham_seen = 1;
3033 		thisline_decision.ehb_seen = isehb (value, bplcon2);
3034 		isbrdblank (hpos, value, bplcon3);
3035 		issprbrd (hpos, value, bplcon3);
3036 	} else if (regno == 0x104) { // BPLCON2
3037 		thisline_decision.ehb_seen = isehb (bplcon0, value);
3038 	} else if (regno == 0x106) { // BPLCON3
3039 		isbrdblank (hpos, bplcon0, value);
3040 		issprbrd (hpos, bplcon0, value);
3041 	}
3042 	record_color_change (hpos, regno + 0x1000, value);
3043 }
3044 
3045 typedef int sprbuf_res_t, cclockres_t, hwres_t,	bplres_t;
3046 
3047 static int expand_sprres (uae_u16 con0, uae_u16 con3)
3048 {
3049 	int res;
3050 
3051 	switch ((con3 >> 6) & 3)
3052 	{
3053 	default:
3054 		res = RES_LORES;
3055 		break;
3056 #ifdef ECS_DENISE
3057 	case 0: /* ECS defaults (LORES,HIRES=LORES sprite,SHRES=HIRES sprite) */
3058 		if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) && GET_RES_DENISE (con0) == RES_SUPERHIRES)
3059 			res = RES_HIRES;
3060 		else
3061 			res = RES_LORES;
3062 		break;
3063 #endif
3064 #ifdef AGA
3065 	case 1:
3066 		res = RES_LORES;
3067 		break;
3068 	case 2:
3069 		res = RES_HIRES;
3070 		break;
3071 	case 3:
3072 		res = RES_SUPERHIRES;
3073 		break;
3074 #endif
3075 	}
3076 	return res;
3077 }
3078 
3079 /* handle very rarely needed playfield collision (CLXDAT bit 0) */
3080 /* only known game needing this is Rotor */
3081 static void do_playfield_collisions (void)
3082 {
3083 	int bplres = bplcon0_res;
3084 	hwres_t ddf_left = thisline_decision.plfleft * 2 << bplres;
3085 	hwres_t hw_diwlast = coord_window_to_diw_x (thisline_decision.diwlastword);
3086 	hwres_t hw_diwfirst = coord_window_to_diw_x (thisline_decision.diwfirstword);
3087 	int i, collided, minpos, maxpos;
3088 #ifdef AGA
3089 	int planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6;
3090 #else
3091 	int planes = 6;
3092 #endif
3093 
3094 	if (clxcon_bpl_enable == 0) {
3095 		clxdat |= 1;
3096 		return;
3097 	}
3098 	if (clxdat & 1)
3099 		return;
3100 
3101 	collided = 0;
3102 	minpos = thisline_decision.plfleft * 2;
3103 	if (minpos < hw_diwfirst)
3104 		minpos = hw_diwfirst;
3105 	maxpos = thisline_decision.plfright * 2;
3106 	if (maxpos > hw_diwlast)
3107 		maxpos = hw_diwlast;
3108 	for (i = minpos; i < maxpos && !collided; i+= 32) {
3109 		int offs = ((i << bplres) - ddf_left) >> 3;
3110 		int j;
3111 		uae_u32 total = 0xffffffff;
3112 		for (j = 0; j < planes; j++) {
3113 			int ena = (clxcon_bpl_enable >> j) & 1;
3114 			int match = (clxcon_bpl_match >> j) & 1;
3115 			uae_u32 t = 0xffffffff;
3116 			if (ena) {
3117 				if (j < thisline_decision.nr_planes) {
3118 					t = *(uae_u32 *)(line_data[next_lineno] + offs + 2 * j * MAX_WORDS_PER_LINE);
3119 					t ^= (match & 1) - 1;
3120 				} else {
3121 					t = (match & 1) - 1;
3122 				}
3123 			}
3124 			total &= t;
3125 		}
3126 		if (total) {
3127 			collided = 1;
3128 #if 0
3129 			{
3130 				int k;
3131 				for (k = 0; k < 1; k++) {
3132 					uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + offs + 2 * k * MAX_WORDS_PER_LINE);
3133 					*ldata ^= 0x5555555555;
3134 				}
3135 			}
3136 #endif
3137 
3138 		}
3139 	}
3140 	if (collided)
3141 		clxdat |= 1;
3142 }
3143 
3144 /* Sprite-to-sprite collisions are taken care of in record_sprite.  This one does
3145 playfield/sprite collisions. */
3146 static void do_sprite_collisions (void)
3147 {
3148 	int nr_sprites = curr_drawinfo[next_lineno].nr_sprites;
3149 	int first = curr_drawinfo[next_lineno].first_sprite_entry;
3150 	int i;
3151 	unsigned int collision_mask = clxmask[clxcon >> 12];
3152 	int bplres = bplcon0_res;
3153 	hwres_t ddf_left = thisline_decision.plfleft * 2 << bplres;
3154 	hwres_t hw_diwlast = coord_window_to_diw_x (thisline_decision.diwlastword);
3155 	hwres_t hw_diwfirst = coord_window_to_diw_x (thisline_decision.diwfirstword);
3156 
3157 	if (clxcon_bpl_enable == 0) {
3158 		clxdat |= 0x1FE;
3159 		return;
3160 	}
3161 
3162 	for (i = 0; i < nr_sprites; i++) {
3163 		struct sprite_entry *e = curr_sprite_entries + first + i;
3164 		sprbuf_res_t j;
3165 		sprbuf_res_t minpos = e->pos;
3166 		sprbuf_res_t maxpos = e->max;
3167 		hwres_t minp1 = minpos >> sprite_buffer_res;
3168 		hwres_t maxp1 = maxpos >> sprite_buffer_res;
3169 
3170 		if (maxp1 > hw_diwlast)
3171 			maxpos = hw_diwlast << sprite_buffer_res;
3172 		if (maxp1 > thisline_decision.plfright * 2)
3173 			maxpos = thisline_decision.plfright * 2 << sprite_buffer_res;
3174 		if (minp1 < hw_diwfirst)
3175 			minpos = hw_diwfirst << sprite_buffer_res;
3176 		if (minp1 < thisline_decision.plfleft * 2)
3177 			minpos = thisline_decision.plfleft * 2 << sprite_buffer_res;
3178 
3179 		for (j = minpos; j < maxpos; j++) {
3180 			int sprpix = spixels[e->first_pixel + j - e->pos] & collision_mask;
3181 			int k, offs, match = 1;
3182 
3183 			if (sprpix == 0)
3184 				continue;
3185 
3186 			offs = ((j << bplres) >> sprite_buffer_res) - ddf_left;
3187 			sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2);
3188 			sprpix <<= 1;
3189 
3190 			/* Loop over number of playfields.  */
3191 			for (k = 1; k >= 0; k--) {
3192 				int l;
3193 #ifdef AGA
3194 				int planes = (currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6;
3195 #else
3196 				int planes = 6;
3197 #endif
3198 				if (bplcon0 & 0x400)
3199 					match = 1;
3200 				for (l = k; match && l < planes; l += 2) {
3201 					int t = 0;
3202 					if (l < thisline_decision.nr_planes) {
3203 						uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE);
3204 						uae_u32 word = ldata[offs >> 5];
3205 						t = (word >> (31 - (offs & 31))) & 1;
3206 #if 0 /* debug: draw collision mask */
3207 						if (1) {
3208 							int m;
3209 							for (m = 0; m < 5; m++) {
3210 								ldata = (uae_u32 *)(line_data[next_lineno] + 2 * m * MAX_WORDS_PER_LINE);
3211 								ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31));
3212 							}
3213 						}
3214 #endif
3215 					}
3216 					if (clxcon_bpl_enable & (1 << l)) {
3217 						if (t != ((clxcon_bpl_match >> l) & 1))
3218 							match = 0;
3219 					}
3220 				}
3221 				if (match) {
3222 #if 0 /* debug: mark lines where collisions are detected */
3223 					if (0) {
3224 						int l;
3225 						for (l = 0; l < 5; l++) {
3226 							uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE);
3227 							ldata[(offs >> 5) + 1] |= 15 << (31 - (offs & 31));
3228 						}
3229 					}
3230 #endif
3231 					clxdat |= sprpix << (k * 4);
3232 				}
3233 			}
3234 		}
3235 	}
3236 #if 0
3237 	{
3238 		static int olx;
3239 		if (clxdat != olx)
3240 			write_log (_T("%d: %04X\n"), vpos, clxdat);
3241 		olx = clxdat;
3242 	}
3243 #endif
3244 }
3245 
3246 static void record_sprite_1 (int sprxp, uae_u16 *buf, uae_u32 datab, int num, int dbl,
3247 	unsigned int mask, int do_collisions, uae_u32 collision_mask)
3248 {
3249 	int j = 0;
3250 	while (datab) {
3251 		unsigned int col = 0;
3252 		unsigned coltmp = 0;
3253 
3254 		if ((sprxp >= sprite_minx && sprxp < sprite_maxx) || (bplcon3 & 2))
3255 			col = (datab & 3) << (2 * num);
3256 #if 0
3257 		if (sprxp == sprite_minx || sprxp == sprite_maxx - 1)
3258 			col ^= (uaerand () << 16) | uaerand ();
3259 #endif
3260 		if ((j & mask) == 0) {
3261 			unsigned int tmp = (*buf) | col;
3262 			*buf++ = tmp;
3263 			if (do_collisions)
3264 				coltmp |= tmp;
3265 			sprxp++;
3266 		}
3267 		if (dbl > 0) {
3268 			unsigned int tmp = (*buf) | col;
3269 			*buf++ = tmp;
3270 			if (do_collisions)
3271 				coltmp |= tmp;
3272 			sprxp++;
3273 		}
3274 		if (dbl > 1) {
3275 			unsigned int tmp;
3276 			tmp = (*buf) | col;
3277 			*buf++ = tmp;
3278 			if (do_collisions)
3279 				coltmp |= tmp;
3280 			tmp = (*buf) | col;
3281 			*buf++ = tmp;
3282 			if (do_collisions)
3283 				coltmp |= tmp;
3284 			sprxp++;
3285 			sprxp++;
3286 		}
3287 		j++;
3288 		datab >>= 2;
3289 		if (do_collisions) {
3290 			coltmp &= collision_mask;
3291 			if (coltmp) {
3292 				unsigned int shrunk_tmp = sprite_ab_merge[coltmp & 255] | (sprite_ab_merge[coltmp >> 8] << 2);
3293 				clxdat |= sprclx[shrunk_tmp];
3294 			}
3295 		}
3296 	}
3297 }
3298 
3299 /* DATAB contains the sprite data; 16 pixels in two-bit packets.  Bits 0/1
3300 determine the color of the leftmost pixel, bits 2/3 the color of the next
3301 etc.
3302 This function assumes that for all sprites in a given line, SPRXP either
3303 stays equal or increases between successive calls.
3304 
3305 The data is recorded either in lores pixels (if OCS/ECS), or in hires or
3306 superhires pixels (if AGA).  */
3307 
3308 static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl)
3309 {
3310 	struct sprite_entry *e = curr_sprite_entries + next_sprite_entry;
3311 	int i;
3312 	int word_offs;
3313 	uae_u32 collision_mask;
3314 	int width, dbl, half;
3315 	unsigned int mask = 0;
3316 	int attachment;
3317 
3318 	half = 0;
3319 	dbl = sprite_buffer_res - sprres;
3320 	if (dbl < 0) {
3321 		half = -dbl;
3322 		dbl = 0;
3323 		mask = 1 << half;
3324 	}
3325 	width = (sprite_width << sprite_buffer_res) >> sprres;
3326 	attachment = sprctl[num | 1] & 0x80;
3327 
3328 	/* Try to coalesce entries if they aren't too far apart  */
3329 	if (!next_sprite_forced && e[-1].max + sprite_width >= sprxp) {
3330 		e--;
3331 	} else {
3332 		next_sprite_entry++;
3333 		e->pos = sprxp;
3334 		e->has_attached = 0;
3335 	}
3336 
3337 	if (sprxp < e->pos)
3338 		uae_abort (_T("sprxp < e->pos"));
3339 
3340 	e->max = sprxp + width;
3341 	e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3);
3342 	next_sprite_forced = 0;
3343 
3344 	collision_mask = clxmask[clxcon >> 12];
3345 	word_offs = e->first_pixel + sprxp - e->pos;
3346 
3347 	for (i = 0; i < sprite_width; i += 16) {
3348 		unsigned int da = *data;
3349 		unsigned int db = *datb;
3350 		uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8]
3351 			| (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]);
3352 		int off = (i << dbl) >> half;
3353 		uae_u16 *buf = spixels + word_offs + off;
3354 		if (currprefs.collision_level > 0 && collision_mask)
3355 			record_sprite_1 (sprxp + off, buf, datab, num, dbl, mask, 1, collision_mask);
3356 		else
3357 			record_sprite_1 (sprxp + off, buf, datab, num, dbl, mask, 0, collision_mask);
3358 		data++;
3359 		datb++;
3360 	}
3361 
3362 	/* We have 8 bits per pixel in spixstate, two for every sprite pair.  The
3363 	low order bit records whether the attach bit was set for this pair.  */
3364 	if (attachment && !ecsshres ()) {
3365 		uae_u32 state = 0x01010101 << (num & ~1);
3366 		uae_u8 *stb1 = spixstate.bytes + word_offs;
3367 		for (i = 0; i < width; i += 8) {
3368 			stb1[0] |= state;
3369 			stb1[1] |= state;
3370 			stb1[2] |= state;
3371 			stb1[3] |= state;
3372 			stb1[4] |= state;
3373 			stb1[5] |= state;
3374 			stb1[6] |= state;
3375 			stb1[7] |= state;
3376 			stb1 += 8;
3377 		}
3378 		e->has_attached = 1;
3379 	}
3380 }
3381 
3382 static void add_sprite (int *countp, int num, int sprxp, int posns[], int nrs[])
3383 {
3384 	int count = *countp;
3385 	int j, bestp;
3386 
3387 	/* Sort the sprites in order of ascending X position before recording them.  */
3388 	for (bestp = 0; bestp < count; bestp++) {
3389 		if (posns[bestp] > sprxp)
3390 			break;
3391 		if (posns[bestp] == sprxp && nrs[bestp] < num)
3392 			break;
3393 	}
3394 	for (j = count; j > bestp; j--) {
3395 		posns[j] = posns[j - 1];
3396 		nrs[j] = nrs[j - 1];
3397 	}
3398 	posns[j] = sprxp;
3399 	nrs[j] = num;
3400 	count++;
3401 	*countp = count;
3402 }
3403 
3404 static int tospritexdiw (int diw)
3405 {
3406 	return  coord_window_to_hw_x (diw - (DIW_DDF_OFFSET << lores_shift)) << sprite_buffer_res;
3407 }
3408 static int tospritexddf (int ddf)
3409 {
3410 	return (ddf * 2 - DIW_DDF_OFFSET) << sprite_buffer_res;
3411 }
3412 static int fromspritexdiw (int ddf)
3413 {
3414 	return coord_hw_to_window_x (ddf >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift);
3415 }
3416 
3417 static void calcsprite (void)
3418 {
3419 	sprite_maxx = 0x7fff;
3420 	sprite_minx = 0;
3421 	if (thisline_decision.diwlastword >= 0)
3422 		sprite_maxx = tospritexdiw (thisline_decision.diwlastword);
3423 	if (thisline_decision.diwfirstword >= 0)
3424 		sprite_minx = tospritexdiw (thisline_decision.diwfirstword);
3425 	if (thisline_decision.plfleft >= 0) {
3426 		int min, max;
3427 		min = tospritexddf (thisline_decision.plfleft);
3428 		max = tospritexddf (thisline_decision.plfright);
3429 		if (min > sprite_minx && min < max) { /* min < max = full line ddf */
3430 			if (currprefs.chipset_mask & CSMASK_ECS_DENISE) {
3431 				sprite_minx = min;
3432 			} else {
3433 				if (thisline_decision.plfleft >= 0x28 || bpldmawasactive)
3434 					sprite_minx = min;
3435 			}
3436 		}
3437 		/* sprites are visible from first BPL1DAT write to end of line
3438 		 * ECS Denise/AGA: no limits
3439 		 * OCS Denise: BPL1DAT write only enables sprite if hpos >= 0x28 or so.
3440 		 * (undocumented feature)
3441 		 */
3442 	}
3443 }
3444 
3445 static void decide_sprites (int hpos, bool usepointx)
3446 {
3447 	int nrs[MAX_SPRITES * 2], posns[MAX_SPRITES * 2];
3448 	int count, i;
3449 	int point;
3450 	int width = sprite_width;
3451 	int sscanmask = 0x100 << sprite_buffer_res;
3452 	int gotdata = 0;
3453 
3454 	if (thisline_decision.plfleft < 0 && !(bplcon3 & 2))
3455 		return;
3456 
3457 	// let sprite shift register empty completely
3458 	// if sprite is at the very edge of right border
3459 	point = hpos * 2;
3460 	if (hpos >= maxhpos)
3461 		point += ((9 - 2) * 2) * sprite_buffer_res;
3462 
3463 	if (nodraw () || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point)
3464 		return;
3465 
3466 	decide_diw (hpos);
3467 	decide_line (hpos);
3468 	calcsprite ();
3469 
3470 	count = 0;
3471 	for (i = 0; i < MAX_SPRITES; i++) {
3472 		int xpos = spr[i].xpos;
3473 		int sprxp = (fmode & 0x8000) ? (xpos & ~sscanmask) : xpos;
3474 		int hw_xp = sprxp >> sprite_buffer_res;
3475 		int pointx = usepointx && (sprctl[i] & sprite_sprctlmask) ? 0 : 1;
3476 
3477 		if (xpos < 0)
3478 			continue;
3479 
3480 		if (!((debug_sprite_mask & magic_sprite_mask) & (1 << i)))
3481 			continue;
3482 
3483 		if (! spr[i].armed)
3484 			continue;
3485 
3486 		if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
3487 			add_sprite (&count, i, sprxp, posns, nrs);
3488 		}
3489 
3490 		/* SSCAN2-bit is fun.. */
3491 		if ((fmode & 0x8000) && !(sprxp & sscanmask)) {
3492 			sprxp |= sscanmask;
3493 			hw_xp = sprxp >> sprite_buffer_res;
3494 			if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
3495 				add_sprite (&count, MAX_SPRITES + i, sprxp, posns, nrs);
3496 			}
3497 		} else if (!(fmode & 0x80) && xpos >= (2 << sprite_buffer_res) && xpos <= (9 << sprite_buffer_res)) {
3498 			// right border wrap around. SPRxCTL horizontal bits do not matter.
3499 			sprxp += (maxhpos * 2) << sprite_buffer_res;
3500 			hw_xp = sprxp >> sprite_buffer_res;
3501 			if (hw_xp > last_sprite_point && hw_xp <= point + pointx) {
3502 				add_sprite(&count, MAX_SPRITES + i, sprxp, posns, nrs);
3503 			}
3504 			// (not really mutually exclusive of SSCAN2-bit but not worth the trouble)
3505 		}
3506 	}
3507 
3508 	for (i = 0; i < count; i++) {
3509 		int nr = nrs[i] & (MAX_SPRITES - 1);
3510 		record_sprite (next_lineno, nr, posns[i], sprdata[nr], sprdatb[nr], sprctl[nr]);
3511 		/* get left and right sprite edge if brdsprt enabled */
3512 #if AUTOSCALE_SPRITES
3513 		if (dmaen (DMA_SPRITE) && (bplcon0 & 1) && (bplcon3 & 0x02) && !(bplcon3 & 0x20) && nr > 0) {
3514 			int j, jj;
3515 			for (j = 0, jj = 0; j < sprite_width; j+= 16, jj++) {
3516 				int nx = fromspritexdiw (posns[i] + j);
3517 				if (sprdata[nr][jj] || sprdatb[nr][jj]) {
3518 					if (diwfirstword_total > nx && nx >= (48 << currprefs.gfx_resolution))
3519 						diwfirstword_total = nx;
3520 					if (diwlastword_total < nx + 16 && nx <= (448 << currprefs.gfx_resolution))
3521 						diwlastword_total = nx + 16;
3522 				}
3523 			}
3524 			gotdata = 1;
3525 		}
3526 #endif
3527 	}
3528 	last_sprite_point = point;
3529 
3530 #if AUTOSCALE_SPRITES
3531 	/* get upper and lower sprite position if brdsprt enabled */
3532 	if (gotdata) {
3533 		if (vpos < first_planes_vpos)
3534 			first_planes_vpos = vpos;
3535 		if (vpos < plffirstline_total)
3536 			plffirstline_total = vpos;
3537 		if (vpos > last_planes_vpos)
3538 			last_planes_vpos = vpos;
3539 		if (vpos > plflastline_total)
3540 			plflastline_total = vpos;
3541 	}
3542 #endif
3543 }
3544 static void decide_sprites(int hpos)
3545 {
3546 	decide_sprites(hpos, false);
3547 }
3548 
3549 static int sprites_differ (struct draw_info *dip, struct draw_info *dip_old)
3550 {
3551 	struct sprite_entry *this_first = curr_sprite_entries + dip->first_sprite_entry;
3552 	struct sprite_entry *this_last = curr_sprite_entries + dip->last_sprite_entry;
3553 	struct sprite_entry *prev_first = prev_sprite_entries + dip_old->first_sprite_entry;
3554 	int npixels;
3555 	int i;
3556 
3557 	if (dip->nr_sprites != dip_old->nr_sprites)
3558 		return 1;
3559 
3560 	if (dip->nr_sprites == 0)
3561 		return 0;
3562 
3563 	for (i = 0; i < dip->nr_sprites; i++) {
3564 		if (this_first[i].pos != prev_first[i].pos
3565 			|| this_first[i].max != prev_first[i].max
3566 			|| this_first[i].has_attached != prev_first[i].has_attached)
3567 			return 1;
3568 	}
3569 
3570     npixels = this_last->first_pixel + (this_last->max - this_last->pos) - this_first->first_pixel;
3571 	if (memcmp (spixels + this_first->first_pixel, spixels + prev_first->first_pixel,
3572 		npixels * sizeof (uae_u16)) != 0)
3573 		return 1;
3574 	if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0)
3575 		return 1;
3576 	return 0;
3577 }
3578 
3579 static int color_changes_differ (struct draw_info *dip, struct draw_info *dip_old)
3580 {
3581 	if (dip->nr_color_changes != dip_old->nr_color_changes)
3582 		return 1;
3583 
3584 	if (dip->nr_color_changes == 0)
3585 		return 0;
3586 	if (memcmp (curr_color_changes + dip->first_color_change,
3587 		prev_color_changes + dip_old->first_color_change,
3588 		dip->nr_color_changes * sizeof *curr_color_changes) != 0)
3589 		return 1;
3590 	return 0;
3591 }
3592 
3593 /* End of a horizontal scan line. Finish off all decisions that were not
3594 * made yet. */
3595 static void finish_decisions (void)
3596 {
3597 	struct draw_info *dip;
3598 	struct draw_info *dip_old;
3599 	struct decision *dp;
3600 	int changed;
3601 	int hpos = maxhpos;
3602 
3603 	if (nodraw ())
3604 		return;
3605 
3606 	decide_diw (hpos);
3607 	decide_line (hpos);
3608 	decide_fetch_safe (hpos);
3609 	finish_final_fetch ();
3610 
3611 	record_color_change2 (hsyncstartpos, 0xffff, 0);
3612 	if (thisline_decision.plfleft >= 0 && thisline_decision.plflinelen < 0) {
3613 		if (fetch_state != fetch_not_started) {
3614 			write_log (_T("fetch_state=%d plfleft=%d,len=%d,vpos=%d,hpos=%d\n"),
3615 				fetch_state, thisline_decision.plfleft, thisline_decision.plflinelen,
3616 				vpos, hpos);
3617 			uae_abort (_T("fetch_state != fetch_not_started"));
3618 		}
3619 		thisline_decision.plfright = thisline_decision.plfleft;
3620 		thisline_decision.plflinelen = 0;
3621 		thisline_decision.bplres = RES_LORES;
3622 	}
3623 
3624 	/* Large DIWSTOP values can cause the stop position never to be
3625 	* reached, so the state machine always stays in the same state and
3626 	* there's a more-or-less full-screen DIW. */
3627 	if (hdiwstate == DIW_waiting_stop) {
3628 		thisline_decision.diwlastword = max_diwlastword;
3629 		if (thisline_decision.diwfirstword < 0)
3630 			thisline_decision.diwfirstword = min_diwlastword;
3631 	}
3632 
3633 	if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
3634 		MARK_LINE_CHANGED;
3635 	if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
3636 		MARK_LINE_CHANGED;
3637 
3638 	dip = curr_drawinfo + next_lineno;
3639 	dip_old = prev_drawinfo + next_lineno;
3640 	dp = line_decisions + next_lineno;
3641 	changed = thisline_changed | custom_frame_redraw_necessary;
3642 	if (thisline_decision.plfleft >= 0 && thisline_decision.nr_planes > 0)
3643 		record_diw_line (thisline_decision.plfleft, diwfirstword, diwlastword);
3644 
3645 	decide_sprites (hpos + 1);
3646 
3647 	dip->last_sprite_entry = next_sprite_entry;
3648 	dip->last_color_change = next_color_change;
3649 
3650 	if (thisline_decision.ctable < 0) {
3651 		if (thisline_decision.plfleft < 0)
3652 			remember_ctable_for_border ();
3653 		else
3654 			remember_ctable ();
3655 	}
3656 
3657 	dip->nr_color_changes = next_color_change - dip->first_color_change;
3658 	dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry;
3659 
3660 	if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft)
3661 		changed = 1;
3662 	if (! changed && color_changes_differ (dip, dip_old))
3663 		changed = 1;
3664 	if (!changed && /* bitplane visible in this line OR border sprites enabled */
3665 		(thisline_decision.plfleft >= 0 || ((thisline_decision.bplcon0 & 1) && (thisline_decision.bplcon3 & 0x02) && !(thisline_decision.bplcon3 & 0x20)))
3666 		&& sprites_differ (dip, dip_old))
3667 	{
3668 		changed = 1;
3669 	}
3670 
3671 	if (changed) {
3672 		thisline_changed = 1;
3673 		*dp = thisline_decision;
3674 	} else {
3675 		/* The only one that may differ: */
3676 		dp->ctable = thisline_decision.ctable;
3677 	}
3678 
3679 	/* leave free space for possible extra color changes at the end of line */
3680 	next_color_change += (HBLANK_OFFSET + 1) / 2;
3681 
3682 	diw_hcounter += maxhpos * 2;
3683 	if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE) && vpos == get_equ_vblank_endline () - 1)
3684 		diw_hcounter++;
3685 	if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) || vpos > get_equ_vblank_endline () || (currprefs.cs_dipagnus && vpos == 0)) {
3686 		diw_hcounter = maxhpos * 2;
3687 		last_hdiw = 2 - 1;
3688 	}
3689 
3690 	if (next_color_change >= MAX_REG_CHANGE - 30) {
3691 		write_log (_T("color_change buffer overflow!\n"));
3692 		next_color_change = 0;
3693 		dip->nr_color_changes = 0;
3694 		dip->first_color_change = 0;
3695 		dip->last_color_change = 0;
3696 	}
3697 }
3698 
3699 /* Set the state of all decisions to "undecided" for a new scanline. */
3700 static void reset_decisions (void)
3701 {
3702 	if (nodraw ())
3703 		return;
3704 
3705 	toscr_nr_planes = toscr_nr_planes2 = 0;
3706 	thisline_decision.bplres = bplcon0_res;
3707 	thisline_decision.nr_planes = 0;
3708 	bpl1dat_written = false;
3709 	bpl1dat_written_at_least_once = false;
3710 
3711 	thisline_decision.plfleft = -1;
3712 	thisline_decision.plflinelen = -1;
3713 	thisline_decision.ham_seen = !! (bplcon0 & 0x800);
3714 	thisline_decision.ehb_seen = !! isehb (bplcon0, bplcon2);
3715 	thisline_decision.ham_at_start = !! (bplcon0 & 0x800);
3716 	thisline_decision.bordersprite_seen = issprbrd (-1, bplcon0, bplcon3);
3717 
3718 	/* decided_res shouldn't be touched before it's initialized by decide_line(). */
3719 	thisline_decision.diwfirstword = -1;
3720 	thisline_decision.diwlastword = -1;
3721 	if (hdiwstate == DIW_waiting_stop) {
3722 		thisline_decision.diwfirstword = min_diwlastword;
3723 		if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
3724 			MARK_LINE_CHANGED;
3725 	}
3726 	thisline_decision.ctable = -1;
3727 
3728 	thisline_changed = 0;
3729 	curr_drawinfo[next_lineno].first_color_change = next_color_change;
3730 	curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry;
3731 	next_sprite_forced = 1;
3732 
3733 	last_sprite_point = 0;
3734 	fetch_state = fetch_not_started;
3735 	if (bpldmasetuphpos >= 0) {
3736 		// this can happen in "too fast" modes
3737 		BPLCON0_Denise (0, bplcon0, true);
3738 		setup_fmodes (0);
3739 	}
3740 	bpldmasetuphpos = -1;
3741 	bpldmasetupphase = 0;
3742 	bpldmawasactive = false;
3743 	reset_moddelays ();
3744 #if 0
3745 	reset_dbpll_all (256);
3746 	reset_dbplh_all (256);
3747 #endif
3748 	delay_cycles = 0;
3749 	compute_toscr_delay (bplcon1);
3750 
3751 	if (plf_state >= plf_passed_stop2 || plf_state == plf_wait)
3752 		plf_state = plf_idle;
3753 
3754 	// Only ECS Agnus can keep DDF open between lines
3755 	if ((currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
3756 		if (!ddfstop_matched) {
3757 			plf_state = plf_active;
3758 		}
3759 	}
3760 
3761 	bpl_hstart = 256;
3762 	plfr_state = plfr_idle;
3763 	plf_start_hpos = 256 + DDF_OFFSET;
3764 	plf_end_hpos = 256 + DDF_OFFSET;
3765 	ddfstop_written_hpos = -1;
3766 	bitplane_maybe_start_hpos = -1;
3767 	bitplane_off_delay = -1;
3768 
3769 	if (line_cyclebased) {
3770 		line_cyclebased--;
3771 		if (!line_cyclebased) {
3772 			bpl_dma_off_when_active = 0;
3773 		}
3774 	}
3775 
3776 	memset (outword, 0, sizeof outword);
3777 	// fetched[] must not be cleared (Sony VX-90 / Royal Amiga Force)
3778 	todisplay_fetched[0] = todisplay_fetched[1] = false;
3779 	memset (todisplay, 0, sizeof todisplay);
3780 	memset (todisplay2, 0, sizeof todisplay2);
3781 #ifdef AGA
3782 	if (currprefs.chipset_mask & CSMASK_AGA) {
3783 		memset (todisplay_aga, 0, sizeof todisplay_aga);
3784 		memset (todisplay2_aga, 0, sizeof todisplay2_aga);
3785 	}
3786 	aga_plf_passed_stop2 = false;
3787 #endif
3788 
3789 	if (bitplane_line_crossing) {
3790 		// BPL1DAT would have been written after end of last scanline.
3791 		// Set BPL1DAT "written at least once" state for new scanline.
3792 		bitplane_line_crossing -= maxhpos - HPOS_SHIFT;
3793 		if (bitplane_line_crossing > 0) {
3794 			bpl1dat_written = true;
3795 			bpl1dat_written_at_least_once = true;
3796 			reset_bpl_vars ();
3797 			beginning_of_plane_block (bitplane_line_crossing, fetchmode);
3798 		}
3799 		bitplane_line_crossing = 0;
3800 	} else {
3801 		reset_bpl_vars ();
3802 	}
3803 
3804 	last_decide_line_hpos = -(DDF_OFFSET + 1);
3805 	last_ddf_pix_hpos = -1;
3806 	last_sprite_hpos = -1;
3807 	last_fetch_hpos = -1;
3808 
3809 	if (sprite_ignoreverticaluntilnextline) {
3810 		sprite_ignoreverticaluntilnextline = false;
3811 		for (int i = 0; i < MAX_SPRITES; i++)
3812 			spr[i].ignoreverticaluntilnextline = false;
3813 	}
3814 
3815 	/* These are for comparison. */
3816 	thisline_decision.bplcon0 = bplcon0;
3817 	thisline_decision.bplcon2 = bplcon2;
3818 #ifdef ECS_DENISE
3819 	thisline_decision.bplcon3 = bplcon3;
3820 #endif
3821 #ifdef AGA
3822 	thisline_decision.bplcon4 = bplcon4;
3823 #endif
3824 	scanlinecount++;
3825 }
3826 
3827 int vsynctimebase_orig;
3828 
3829 void compute_vsynctime (void)
3830 {
3831 	double svpos = maxvpos_nom;
3832 	double shpos = maxhpos_short;
3833 	double syncadjust = 1.0;
3834 
3835 	fake_vblank_hz = 0;
3836 	vblank_hz_mult = 0;
3837 	vblank_hz_state = 1;
3838 	if (fabs (currprefs.chipset_refreshrate) > 0.1) {
3839 		syncadjust = currprefs.chipset_refreshrate / vblank_hz_nom;
3840 		vblank_hz = currprefs.chipset_refreshrate;
3841 		if (isvsync_chipset ()) {
3842 			int mult = 0;
3843 			if (getvsyncrate (vblank_hz, &mult) != vblank_hz) {
3844 				vblank_hz = getvsyncrate (vblank_hz, &vblank_hz_mult);
3845 				if (vblank_hz_mult > 0)
3846 					vblank_hz_state = 0;
3847 			}
3848 		}
3849 	}
3850 	if (!fake_vblank_hz)
3851 		fake_vblank_hz = vblank_hz;
3852 
3853 	if (currprefs.turbo_emulation) {
3854 		if (currprefs.turbo_emulation_limit > 0) {
3855 			vsynctimebase = (int)(syncbase / currprefs.turbo_emulation_limit);
3856 		} else {
3857 			vsynctimebase = 1;
3858 		}
3859 	} else {
3860 		vsynctimebase = (int)(syncbase / fake_vblank_hz);
3861 	}
3862 	vsynctimebase_orig = vsynctimebase;
3863 
3864 #if 0
3865 	if (!picasso_on) {
3866 		updatedisplayarea ();
3867 	}
3868 #endif
3869 
3870 	if (islinetoggle ()) {
3871 		shpos += 0.5;
3872 	}
3873 	if (interlace_seen) {
3874 		svpos += 0.5;
3875 	} else if (lof_current) {
3876 		svpos += 1.0;
3877 	}
3878 	if (currprefs.produce_sound > 1) {
3879 		double clk = svpos * shpos * fake_vblank_hz;
3880 		//write_log (_T("SNDRATE %.1f*%.1f*%.6f=%.6f\n"), svpos, shpos, fake_vblank_hz, clk);
3881 		devices_update_sound(clk, syncadjust);
3882 	}
3883 	devices_update_sync(svpos, syncadjust);
3884 }
3885 
3886 void getsyncregisters(uae_u16 *phsstrt, uae_u16 *phsstop, uae_u16 *pvsstrt, uae_u16 *pvsstop)
3887 {
3888 	*phsstrt = hsstrt;
3889 	*phsstop = hsstop;
3890 	*pvsstrt = vsstrt;
3891 	*pvsstop = vsstop;
3892 }
3893 
3894 static void dumpsync (void)
3895 {
3896 	static int cnt = 100;
3897 	if (cnt < 0)
3898 		return;
3899 	cnt--;
3900 	write_log (_T("BEAMCON0=%04X VTOTAL=%04X  HTOTAL=%04X\n"), new_beamcon0, vtotal, htotal);
3901 	write_log (_T("  HSSTOP=%04X HBSTRT=%04X  HBSTOP=%04X\n"), hsstop, hbstrt, hbstop);
3902 	write_log (_T("  VSSTOP=%04X VBSTRT=%04X  VBSTOP=%04X\n"), vsstop, vbstrt, vbstop);
3903 	write_log (_T("  HSSTRT=%04X VSSTRT=%04X HCENTER=%04X\n"), hsstrt, vsstrt, hcenter);
3904 	write_log (_T("  HSYNCSTART=%04X HSYNCEND=%04X\n"), hsyncstartpos, hsyncendpos);
3905 }
3906 
3907 int current_maxvpos (void)
3908 {
3909 	return maxvpos + (lof_store ? 1 : 0);
3910 }
3911 
3912 #if 0
3913 static void checklacecount (bool lace)
3914 {
3915 	if (!interlace_changed) {
3916 		if (nlace_cnt >= NLACE_CNT_NEEDED && lace) {
3917 			lof_togglecnt_lace = LOF_TOGGLES_NEEDED;
3918 			lof_togglecnt_nlace = 0;
3919 			//write_log (_T("immediate lace\n"));
3920 			nlace_cnt = 0;
3921 		} else if (nlace_cnt <= -NLACE_CNT_NEEDED && !lace) {
3922 			lof_togglecnt_nlace = LOF_TOGGLES_NEEDED;
3923 			lof_togglecnt_lace = 0;
3924 			//write_log (_T("immediate nlace\n"));
3925 			nlace_cnt = 0;
3926 		}
3927 	}
3928 	if (lace) {
3929 		if (nlace_cnt > 0)
3930 			nlace_cnt = 0;
3931 		nlace_cnt--;
3932 		if (nlace_cnt < -NLACE_CNT_NEEDED * 2)
3933 			nlace_cnt = -NLACE_CNT_NEEDED * 2;
3934 	} else if (!lace) {
3935 		if (nlace_cnt < 0)
3936 			nlace_cnt = 0;
3937 		nlace_cnt++;
3938 		if (nlace_cnt > NLACE_CNT_NEEDED * 2)
3939 			nlace_cnt = NLACE_CNT_NEEDED * 2;
3940 	}
3941 }
3942 #endif
3943 
3944 struct chipset_refresh *get_chipset_refresh (void)
3945 {
3946 	int islace = interlace_seen ? 1 : 0;
3947 	int isntsc = (beamcon0 & 0x20) ? 0 : 1;
3948 
3949 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
3950 		isntsc = currprefs.ntscmode ? 1 : 0;
3951 
3952 	for (int i = 0; i < MAX_CHIPSET_REFRESH_TOTAL; i++) {
3953 		struct chipset_refresh *cr = &currprefs.cr[i];
3954 		if ((cr->horiz < 0 || cr->horiz == maxhpos) &&
3955 			(cr->vert < 0 || cr->vert == maxvpos_display) &&
3956 			(cr->ntsc < 0 || (cr->ntsc > 0 && isntsc) || (cr->ntsc == 0 && !isntsc)) &&
3957 			(cr->lace < 0 || (cr->lace > 0 && islace) || (cr->lace == 0 && !islace)) &&
3958 			(cr->framelength < 0 || (cr->framelength > 0 && lof_store) || (cr->framelength == 0 && !lof_store) || (cr->framelength >= 0 && islace)) &&
3959 			((cr->rtg && picasso_on) || (!cr->rtg && !picasso_on)) &&
3960 			(cr->vsync < 0 || (cr->vsync > 0 && isvsync_chipset ()) || (cr->vsync == 0 && !isvsync_chipset ())))
3961 				return cr;
3962 	}
3963 	return NULL;
3964 }
3965 
3966 static bool changed_chipset_refresh (void)
3967 {
3968 	return stored_chipset_refresh != get_chipset_refresh ();
3969 }
3970 
3971 void compute_framesync (void)
3972 {
3973 	int islace = interlace_seen ? 1 : 0;
3974 	int isntsc = (beamcon0 & 0x20) ? 0 : 1;
3975 	bool found = false;
3976 
3977 	if (islace) {
3978 		vblank_hz = vblank_hz_lace;
3979 	} else if (lof_current) {
3980 		vblank_hz = vblank_hz_lof;
3981 	} else {
3982 		vblank_hz = vblank_hz_shf;
3983 	}
3984 
3985 	struct chipset_refresh *cr = get_chipset_refresh ();
3986 	while (cr) {
3987 		double v = -1;
3988 		if (!picasso_on && !picasso_requested_on) {
3989 			if (isvsync_chipset ()) {
3990 				if (cr->index == CHIPSET_REFRESH_PAL || cr->index == CHIPSET_REFRESH_NTSC) {
3991 					if ((fabs (vblank_hz - 50) < 1 || fabs (vblank_hz - 60) < 1 || fabs (vblank_hz - 100) < 1 || fabs (vblank_hz - 120) < 1) && currprefs.gfx_apmode[0].gfx_vsync == 2 && currprefs.gfx_apmode[0].gfx_fullscreen > 0) {
3992 						vsync_switchmode ((int)vblank_hz);
3993 					}
3994 				}
3995 				if (isvsync_chipset () < 0) {
3996 					double v2;
3997 					v2 = vblank_calibrate (cr->locked ? cr->rate : vblank_hz, cr->locked);
3998 					if (!cr->locked)
3999 						v = v2;
4000 				} else if (isvsync_chipset () > 0) {
4001 					if (currprefs.gfx_apmode[0].gfx_refreshrate)
4002 						v = abs (currprefs.gfx_apmode[0].gfx_refreshrate);
4003 				}
4004 			} else {
4005 				if (cr->locked == false) {
4006 					changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = vblank_hz;
4007 					cfgfile_parse_lines (&changed_prefs, cr->commands, -1);
4008 					if (cr->commands[0])
4009 						write_log (_T("CMD1: '%s'\n"), cr->commands);
4010 					break;
4011 				} else {
4012 					v = cr->rate;
4013 				}
4014 			}
4015 			if (v < 0)
4016 				v = cr->rate;
4017 			if (v > 0) {
4018 				changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = v;
4019 				cfgfile_parse_lines (&changed_prefs, cr->commands, -1);
4020 				if (cr->commands[0])
4021 					write_log (_T("CMD2: '%s'\n"), cr->commands);
4022 			}
4023 		} else {
4024 			if (cr->locked == false)
4025 				v = vblank_hz;
4026 			else
4027 				v = cr->rate;
4028 			changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = v;
4029 			cfgfile_parse_lines (&changed_prefs, cr->commands, -1);
4030 			if (cr->commands[0])
4031 				write_log (_T("CMD3: '%s'\n"), cr->commands);
4032 		}
4033 		found = true;
4034 		break;
4035 	}
4036 	if (!found) {
4037 		changed_prefs.chipset_refreshrate = currprefs.chipset_refreshrate = vblank_hz;
4038 	}
4039 	stored_chipset_refresh = cr;
4040 	interlace_changed = 0;
4041 	lof_togglecnt_lace = 0;
4042 	lof_togglecnt_nlace = 0;
4043 	//nlace_cnt = NLACE_CNT_NEEDED;
4044 	lof_changing = 0;
4045 	gfxvidinfo.drawbuffer.inxoffset = -1;
4046 	gfxvidinfo.drawbuffer.inyoffset = -1;
4047 
4048 	if (beamcon0 & 0x80) {
4049 		int res = GET_RES_AGNUS (bplcon0);
4050 		int vres = islace ? 1 : 0;
4051 		int res2, vres2;
4052 
4053 		res2 = currprefs.gfx_resolution;
4054 		if (doublescan > 0)
4055 			res2++;
4056 		if (res2 > RES_MAX)
4057 			res2 = RES_MAX;
4058 
4059 		vres2 = currprefs.gfx_vresolution;
4060 		if (doublescan > 0 && !islace)
4061 			vres2--;
4062 
4063 		if (vres2 < 0)
4064 			vres2 = 0;
4065 		if (vres2 > VRES_QUAD)
4066 			vres2 = VRES_QUAD;
4067 
4068 		int start = hsyncstartpos; //hbstrt;
4069 		int stop = hsyncendpos; //hbstop;
4070 
4071 		gfxvidinfo.drawbuffer.inwidth = ((maxhpos - (maxhpos - start + DISPLAY_LEFT_SHIFT / 2) + 1) * 2) << res2;
4072 		gfxvidinfo.drawbuffer.inxoffset = stop * 2;
4073 
4074 		gfxvidinfo.drawbuffer.extrawidth = 0;
4075 		gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.inwidth;
4076 
4077 		gfxvidinfo.drawbuffer.inheight = ((firstblankedline < maxvpos ? firstblankedline : maxvpos) - minfirstline + 1) << vres2;
4078 		gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.inheight;
4079 
4080 	} else {
4081 
4082 		gfxvidinfo.drawbuffer.inwidth = AMIGA_WIDTH_MAX << currprefs.gfx_resolution;
4083 		gfxvidinfo.drawbuffer.extrawidth = currprefs.gfx_extrawidth ? currprefs.gfx_extrawidth : -1;
4084 		gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.inwidth;
4085 		gfxvidinfo.drawbuffer.inheight = (maxvpos_display - minfirstline + 1) << currprefs.gfx_vresolution;
4086 		gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.inheight;
4087 
4088 	}
4089 
4090 	if (gfxvidinfo.drawbuffer.inwidth > gfxvidinfo.drawbuffer.width_allocated)
4091 		gfxvidinfo.drawbuffer.inwidth = gfxvidinfo.drawbuffer.width_allocated;
4092 	if (gfxvidinfo.drawbuffer.inwidth2 > gfxvidinfo.drawbuffer.width_allocated)
4093 		gfxvidinfo.drawbuffer.inwidth2 = gfxvidinfo.drawbuffer.width_allocated;
4094 
4095 	if (gfxvidinfo.drawbuffer.inheight > gfxvidinfo.drawbuffer.height_allocated)
4096 		gfxvidinfo.drawbuffer.inheight = gfxvidinfo.drawbuffer.height_allocated;
4097 	if (gfxvidinfo.drawbuffer.inheight2 > gfxvidinfo.drawbuffer.height_allocated)
4098 		gfxvidinfo.drawbuffer.inheight2 = gfxvidinfo.drawbuffer.height_allocated;
4099 
4100 	gfxvidinfo.drawbuffer.outwidth = gfxvidinfo.drawbuffer.inwidth;
4101 	gfxvidinfo.drawbuffer.outheight = gfxvidinfo.drawbuffer.inheight;
4102 
4103 	if (gfxvidinfo.drawbuffer.outwidth > gfxvidinfo.drawbuffer.width_allocated)
4104 		gfxvidinfo.drawbuffer.outwidth = gfxvidinfo.drawbuffer.width_allocated;
4105 
4106 	if (gfxvidinfo.drawbuffer.outheight > gfxvidinfo.drawbuffer.height_allocated)
4107 		gfxvidinfo.drawbuffer.outheight = gfxvidinfo.drawbuffer.height_allocated;
4108 
4109 	memset (line_decisions, 0, sizeof line_decisions);
4110 	memset (line_drawinfo, 0, sizeof line_drawinfo);
4111 	for (int i = 0; i < sizeof (line_decisions) / sizeof *line_decisions; i++) {
4112 		line_decisions[i].plfleft = -2;
4113 	}
4114 
4115 	compute_vsynctime ();
4116 
4117 	hblank_hz = (double)(currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL) / (maxhpos + (islinetoggle() ? 0.5 : 0));
4118 
4119 	write_log (_T("%s mode%s%s V=%.4fHz H=%0.4fHz (%dx%d+%d) IDX=%d (%s) D=%d RTG=%d/%d\n"),
4120 		isntsc ? _T("NTSC") : _T("PAL"),
4121 		islace ? _T(" lace") : (lof_lace ? _T(" loflace") : _T("")),
4122 		doublescan > 0 ? _T(" dblscan") : _T(""),
4123 		vblank_hz,
4124 		hblank_hz,
4125 		maxhpos, maxvpos, lof_store ? 1 : 0,
4126 		cr ? cr->index : -1,
4127 		cr != NULL && cr->label != NULL ? cr->label : _T("<?>"),
4128 		currprefs.gfx_apmode[picasso_on ? 1 : 0].gfx_display, picasso_on, picasso_requested_on
4129 	);
4130 
4131 	set_config_changed ();
4132 
4133 	if (target_graphics_buffer_update ()) {
4134 		reset_drawing ();
4135 	}
4136 }
4137 
4138 /* set PAL/NTSC or custom timing variables */
4139 static void init_hz (bool checkvposw)
4140 {
4141 	int isntsc, islace;
4142 	int odbl = doublescan, omaxvpos = maxvpos;
4143 	double ovblank = vblank_hz;
4144 	int hzc = 0;
4145 
4146 	if (!checkvposw)
4147 		vpos_count = 0;
4148 
4149 	vpos_count_diff = vpos_count;
4150 
4151 	doublescan = 0;
4152 	programmedmode = false;
4153 	if ((beamcon0 & 0xA0) != (new_beamcon0 & 0xA0))
4154 		hzc = 1;
4155 	if (beamcon0 != new_beamcon0) {
4156 		write_log (_T("BEAMCON0 %04x -> %04x PC=%08x\n"), beamcon0, new_beamcon0, M68K_GETPC);
4157 		vpos_count_diff = vpos_count = 0;
4158 	}
4159 	beamcon0 = new_beamcon0;
4160 	isntsc = (beamcon0 & 0x20) ? 0 : 1;
4161 	islace = (interlace_seen) ? 1 : 0;
4162 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
4163 		isntsc = currprefs.ntscmode ? 1 : 0;
4164 	int clk = currprefs.ntscmode ? CHIPSET_CLOCK_NTSC : CHIPSET_CLOCK_PAL;
4165 	if (!isntsc) {
4166 		maxvpos = MAXVPOS_PAL;
4167 		maxhpos = MAXHPOS_PAL;
4168 #ifdef FSUAE
4169 		minfirstline = g_uae_min_first_line_pal;
4170 #else
4171 		minfirstline = VBLANK_ENDLINE_PAL;
4172 #endif
4173 		vblank_hz_nom = vblank_hz = VBLANK_HZ_PAL;
4174 		sprite_vblank_endline = VBLANK_SPRITE_PAL;
4175 		equ_vblank_endline = EQU_ENDLINE_PAL;
4176 		equ_vblank_toggle = true;
4177 		vblank_hz_shf = (double)clk / ((maxvpos + 0) * maxhpos);
4178 		vblank_hz_lof = (double)clk / ((maxvpos + 1) * maxhpos);
4179 		vblank_hz_lace = (double)clk / ((maxvpos + 0.5) * maxhpos);
4180 	} else {
4181 		maxvpos = MAXVPOS_NTSC;
4182 		maxhpos = MAXHPOS_NTSC;
4183 #ifdef FSUAE
4184 		minfirstline = g_uae_min_first_line_ntsc;
4185 #else
4186 		minfirstline = VBLANK_ENDLINE_NTSC;
4187 #endif
4188 		vblank_hz_nom = vblank_hz = VBLANK_HZ_NTSC;
4189 		sprite_vblank_endline = VBLANK_SPRITE_NTSC;
4190 		equ_vblank_endline = EQU_ENDLINE_NTSC;
4191 		equ_vblank_toggle = false;
4192 		vblank_hz_shf = (double)clk / ((maxvpos + 0) * (maxhpos + 0.5));
4193 		vblank_hz_lof = (double)clk / ((maxvpos + 1) * (maxhpos + 0.5));
4194 		vblank_hz_lace = (double)clk / ((maxvpos + 0.5) * (maxhpos + 0.5));
4195 	}
4196 
4197 	maxvpos_nom = maxvpos;
4198 	maxvpos_display = maxvpos;
4199 	if (vpos_count > 0) {
4200 		// we come here if vpos_count != maxvpos and beamcon0 didn't change
4201 		// (someone poked VPOSW)
4202 		if (vpos_count < 10)
4203 			vpos_count = 10;
4204 		vblank_hz = (isntsc ? 15734.0 : 15625.0) / vpos_count;
4205 		vblank_hz_nom = vblank_hz_shf = vblank_hz_lof = vblank_hz_lace = vblank_hz;
4206 		maxvpos_nom = vpos_count - (lof_current ? 1 : 0);
4207 		if ((maxvpos_nom >= 256 && maxvpos_nom <= 313) || (beamcon0 & 0x80)) {
4208 			maxvpos_display = maxvpos_nom;
4209 		} else if (maxvpos_nom < 256) {
4210 			maxvpos_display = 255;
4211 		} else {
4212 			maxvpos_display = 313;
4213 		}
4214 		reset_drawing ();
4215 	} else if (vpos_count == 0) {
4216 		// mode reset
4217 		vpos_count = maxvpos;
4218 		vpos_count_diff = maxvpos;
4219 	}
4220 	firstblankedline = maxvpos + 1;
4221 
4222 	if (beamcon0 & 0x80) {
4223 		// programmable scanrates (ECS Agnus)
4224 		if (vtotal >= MAXVPOS)
4225 			vtotal = MAXVPOS - 1;
4226 		maxvpos = vtotal + 1;
4227 		firstblankedline = maxvpos + 1;
4228 		if (htotal >= MAXHPOS)
4229 			htotal = MAXHPOS - 1;
4230 		maxhpos = htotal + 1;
4231 		vblank_hz_nom = vblank_hz = 227.0 * 312.0 * 50.0 / (maxvpos * maxhpos);
4232 		vblank_hz_shf = vblank_hz;
4233 		vblank_hz_lof = 227.0 * 313.0 * 50.0 / (maxvpos * maxhpos);;
4234 		vblank_hz_lace = 227.0 * 312.5 * 50.0 / (maxvpos * maxhpos);;
4235 
4236 		if ((beamcon0 & 0x1000) && (beamcon0 & 0x0200)) { // VARVBEN + VARVSYEN
4237 			minfirstline = vsstop > vbstop ? vsstop : vbstop;
4238 			if (minfirstline > maxvpos / 2)
4239 				minfirstline = vsstop > vbstop ? vbstop : vsstop;
4240 			firstblankedline = vbstrt;
4241 		} else if (beamcon0 & 0x0200) {
4242 			minfirstline = vsstop;
4243 			if (minfirstline > maxvpos / 2)
4244 				minfirstline = 0;
4245 		} else if (beamcon0 & 0x1000) {
4246 			minfirstline = vbstop;
4247 			if (minfirstline > maxvpos / 2)
4248 				minfirstline = 0;
4249 			firstblankedline = vbstrt;
4250 		}
4251 
4252 		if (minfirstline < 2)
4253 			minfirstline = 2;
4254 		if (minfirstline >= maxvpos)
4255 			minfirstline = maxvpos - 1;
4256 
4257 		if (firstblankedline < minfirstline)
4258 			firstblankedline = maxvpos + 1;
4259 
4260 		sprite_vblank_endline = minfirstline - 2;
4261 		maxvpos_nom = maxvpos;
4262 		maxvpos_display = maxvpos;
4263 		equ_vblank_endline = -1;
4264 		doublescan = htotal <= 164 && vtotal >= 350 ? 1 : 0;
4265 		// if superhires and wide enough: not doublescan
4266 		if (doublescan && htotal >= 140 && (bplcon0 & 0x0040))
4267 			doublescan = 0;
4268 		programmedmode = true;
4269 		varsync_changed = true;
4270 		vpos_count = maxvpos_nom;
4271 		vpos_count_diff = maxvpos_nom;
4272 		hzc = 1;
4273 	}
4274 	if (maxvpos_nom >= MAXVPOS)
4275 		maxvpos_nom = MAXVPOS;
4276 	if (maxvpos_display >= MAXVPOS)
4277 		maxvpos_display = MAXVPOS;
4278 	if (currprefs.gfx_scandoubler && doublescan == 0)
4279 		doublescan = -1;
4280 	if (doublescan != odbl || maxvpos != omaxvpos)
4281 		hzc = 1;
4282 	/* limit to sane values */
4283 	if (vblank_hz < 10)
4284 		vblank_hz = 10;
4285 	if (vblank_hz > 300)
4286 		vblank_hz = 300;
4287 	maxhpos_short = maxhpos;
4288 	set_delay_lastcycle ();
4289 	if ((beamcon0 & 0x80) && (beamcon0 & 0x0100)) {
4290 
4291 		hsyncstartpos = hsstrt;
4292 		hsyncendpos = hsstop;
4293 
4294 		if ((bplcon0 & 1) && (bplcon3 & 1)) {
4295 
4296 			if (hbstrt > maxhpos / 2) {
4297 				if (hsyncstartpos < hbstrt)
4298 					hsyncstartpos = hbstrt;
4299 			} else {
4300 				if (hsyncstartpos > hbstrt)
4301 					hsyncstartpos = hbstrt;
4302 			}
4303 
4304 			if (hbstop > maxhpos / 2) {
4305 				if (hsyncendpos > hbstop)
4306 					hsyncendpos = hbstop;
4307 			} else {
4308 				if (hsyncendpos < hbstop)
4309 					hsyncendpos = hbstop;
4310 			}
4311 		}
4312 
4313 		if (hsyncstartpos < hsyncendpos)
4314 			hsyncstartpos = maxhpos + hsyncstartpos;
4315 
4316 		hsyncendpos--;
4317 
4318 		if (hsyncendpos < 2)
4319 			hsyncendpos = 2;
4320 	} else {
4321 		hsyncstartpos = maxhpos_short + 13;
4322 		hsyncendpos = 24;
4323 	}
4324 	hpos_offset = 0;
4325 	eventtab[ev_hsync].oldcycles = get_cycles ();
4326 	eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME;
4327 	events_schedule ();
4328 	if (hzc) {
4329 		interlace_seen = islace;
4330 		reset_drawing ();
4331 	}
4332 
4333 	maxvpos_total = (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? (MAXVPOS_LINES_ECS - 1) : (MAXVPOS_LINES_OCS - 1);
4334 	if (maxvpos_total > MAXVPOS)
4335 		maxvpos_total = MAXVPOS;
4336 #ifdef PICASSO96
4337 	if (!p96refresh_active) {
4338 		maxvpos_stored = maxvpos;
4339 		maxhpos_stored = maxhpos;
4340 		vblank_hz_stored = vblank_hz;
4341 	}
4342 #endif
4343 
4344 	compute_framesync ();
4345 	devices_syncchange();
4346 
4347 #ifdef PICASSO96
4348 	init_hz_p96 ();
4349 #endif
4350 	if (vblank_hz != ovblank)
4351 		updatedisplayarea ();
4352 	inputdevice_tablet_strobe ();
4353 
4354 	if (varsync_changed) {
4355 		varsync_changed = false;
4356 		dumpsync ();
4357 	}
4358 }
4359 
4360 static void init_hz_vposw (void)
4361 {
4362 	init_hz (true);
4363 }
4364 
4365 void init_hz_normal (void)
4366 {
4367 	init_hz (false);
4368 }
4369 
4370 static void calcdiw (void)
4371 {
4372 	int hstrt = diwstrt & 0xFF;
4373 	int hstop = diwstop & 0xFF;
4374 	int vstrt = diwstrt >> 8;
4375 	int vstop = diwstop >> 8;
4376 
4377 	// vertical in ECS Agnus
4378 	if (diwhigh_written && (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) {
4379 		vstrt |= (diwhigh & 7) << 8;
4380 		vstop |= ((diwhigh >> 8) & 7) << 8;
4381 	} else {
4382 		if ((vstop & 0x80) == 0)
4383 			vstop |= 0x100;
4384 	}
4385 	// horizontal in ECS Denise
4386 	if (diwhigh_written && (currprefs.chipset_mask & CSMASK_ECS_DENISE)) {
4387 		hstrt |= ((diwhigh >> 5) & 1) << 8;
4388 		hstop |= ((diwhigh >> 13) & 1) << 8;
4389 	} else {
4390 		hstop += 0x100;
4391 	}
4392 
4393 	diw_hstrt = hstrt;
4394 	diw_hstop = hstop;
4395 
4396 	diwfirstword = coord_diw_to_window_x (hstrt);
4397 	diwlastword = coord_diw_to_window_x (hstop);
4398 
4399 	if (diwfirstword >= diwlastword) {
4400 		diwfirstword = min_diwlastword;
4401 		diwlastword = max_diwlastword;
4402 	}
4403 	if (diwfirstword < min_diwlastword)
4404 		diwfirstword = min_diwlastword;
4405 
4406 	if (vstrt == vpos && vstop != vpos && diwstate == DIW_waiting_start) {
4407 		// This may start BPL DMA immediately.
4408 		SET_LINE_CYCLEBASED;
4409 		bitplane_maybe_start_hpos = current_hpos();
4410 	}
4411 
4412 	plffirstline = vstrt;
4413 	plflastline = vstop;
4414 
4415 	plfstrt = ddfstrt - DDF_OFFSET;
4416 	plfstop = ddfstop - DDF_OFFSET;
4417 
4418 	diw_change = 2;
4419 }
4420 
4421 /* display mode changed (lores, doubling etc..), recalculate everything */
4422 void init_custom (void)
4423 {
4424 	update_mirrors();
4425 	create_cycle_diagram_table();
4426 	reset_drawing();
4427 	init_hz_normal();
4428 	calcdiw();
4429 }
4430 
4431 static int timehack_alive = 0;
4432 
4433 static uae_u32 REGPARAM2 timehack_helper (TrapContext *context)
4434 {
4435 #ifdef HAVE_GETTIMEOFDAY
4436 	struct timeval tv;
4437 	if (m68k_dreg (regs, 0) == 0)
4438 		return timehack_alive;
4439 
4440 	timehack_alive = 10;
4441 
4442 	gettimeofday (&tv, NULL);
4443 	put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24) * 60 * 60));
4444 	put_long (m68k_areg (regs, 0) + 4, tv.tv_usec);
4445 	return 0;
4446 #else
4447 	return 2;
4448 #endif
4449 }
4450 
4451 /*
4452 * register functions
4453 */
4454 static uae_u16 DENISEID (int *missing)
4455 {
4456 	*missing = 0;
4457 	if (currprefs.cs_deniserev >= 0)
4458 		return currprefs.cs_deniserev;
4459 #ifdef AGA
4460 	if (currprefs.chipset_mask & CSMASK_AGA) {
4461 		if (currprefs.cs_ide == IDE_A4000)
4462 			return 0xFCF8;
4463 		return 0x00F8;
4464 	}
4465 #endif
4466 	if (currprefs.chipset_mask & CSMASK_ECS_DENISE)
4467 		return 0xFFFC;
4468 	if (currprefs.cpu_model == 68000 && (currprefs.cpu_compatible || currprefs.cpu_cycle_exact))
4469 		*missing = 1;
4470 	return 0xFFFF;
4471 }
4472 STATIC_INLINE uae_u16 DMACONR (int hpos)
4473 {
4474 	decide_line (hpos);
4475 	decide_fetch_safe (hpos);
4476 	dmacon &= ~(0x4000 | 0x2000);
4477 	dmacon |= ((blit_interrupt || (!blit_interrupt && currprefs.cs_agnusbltbusybug && !blt_info.got_cycle)) ? 0 : 0x4000)
4478 		| (blt_info.blitzero ? 0x2000 : 0);
4479 	return dmacon;
4480 }
4481 STATIC_INLINE uae_u16 INTENAR (void)
4482 {
4483 	return intena;
4484 }
4485 uae_u16 INTREQR (void)
4486 {
4487 	return intreq;
4488 }
4489 STATIC_INLINE uae_u16 ADKCONR (void)
4490 {
4491 	return adkcon;
4492 }
4493 
4494 STATIC_INLINE int islightpentriggered (void)
4495 {
4496 	if (beamcon0 & 0x2000) // LPENDIS
4497 		return 0;
4498 	return lightpen_triggered > 0;
4499 }
4500 STATIC_INLINE int issyncstopped (void)
4501 {
4502 	return (bplcon0 & 2) && !currprefs.genlock;
4503 }
4504 
4505 STATIC_INLINE int GETVPOS (void)
4506 {
4507 	return islightpentriggered () ? vpos_lpen : (issyncstopped () ? vpos_previous : vpos);
4508 }
4509 STATIC_INLINE int GETHPOS (void)
4510 {
4511 	return islightpentriggered () ? hpos_lpen : (issyncstopped () ? hpos_previous : current_hpos ());
4512 }
4513 
4514 // fake changing hpos when rom genlock test runs and genlock is connected
4515 static bool hsyncdelay (void)
4516 {
4517 	if (!currprefs.genlock)
4518 		return false;
4519 	if (currprefs.cpu_cycle_exact || currprefs.m68k_speed >= 0)
4520 		return false;
4521 	if (bplcon0 == (0x0100 | 0x0002)) {
4522 		return true;
4523 	}
4524 	return false;
4525 }
4526 
4527 #define CPU_ACCURATE (currprefs.cpu_model < 68020 || (currprefs.cpu_model == 68020 && currprefs.cpu_cycle_exact))
4528 
4529 // DFF006 = 0.W must be valid result but better do this only in 68000 modes (whdload black screen!)
4530 // HPOS is shifted by 3 cycles and VPOS increases when shifted HPOS==1
4531 #define HPOS_OFFSET (CPU_ACCURATE ? HPOS_SHIFT : 0)
4532 #define VPOS_INC_DELAY (HPOS_OFFSET ? 1 : 0)
4533 
4534 static uae_u16 VPOSR (void)
4535 {
4536 	unsigned int csbit = 0;
4537 	uae_u16 vp = GETVPOS ();
4538 	uae_u16 hp = GETHPOS ();
4539 	int lof = lof_store;
4540 
4541 	if (vp + 1 == maxvpos + lof_store && (hp == maxhpos - 1 || hp == maxhpos - 2)) {
4542 		// lof toggles 2 cycles before maxhpos, so do fake toggle here.
4543 		if ((bplcon0 & 4) && CPU_ACCURATE)
4544 			lof = lof ? 0 : 1;
4545 	}
4546 	if (hp + HPOS_OFFSET >= maxhpos + VPOS_INC_DELAY) {
4547 		vp++;
4548 		if (vp >= maxvpos + lof_store)
4549 			vp = 0;
4550 	}
4551 	vp = (vp >> 8) & 7;
4552 
4553 	if (currprefs.cs_agnusrev >= 0) {
4554 		csbit |= currprefs.cs_agnusrev << 8;
4555 	} else {
4556 #ifdef AGA
4557 		csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0;
4558 #endif
4559 		csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0;
4560 #if 0 /* apparently "8372 (Fat-hr) (agnushr),rev 5" does not exist */
4561 		if (currprefs.chipmem_size > 1024 * 1024 && (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
4562 			csbit |= 0x2100;
4563 #endif
4564 		if (currprefs.ntscmode)
4565 			csbit |= 0x1000;
4566 	}
4567 
4568 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
4569 		vp &= 1;
4570 	vp |= (lof ? 0x8000 : 0) | csbit;
4571 	if (currprefs.chipset_mask & CSMASK_ECS_AGNUS)
4572 		vp |= lol ? 0x80 : 0;
4573 	hsyncdelay ();
4574 #if 0
4575 	if (1 || (M68K_GETPC < 0x00f00000 || M68K_GETPC >= 0x10000000))
4576 		write_log (_T("VPOSR %04x at %08x\n"), vp, M68K_GETPC);
4577 #endif
4578 	return vp;
4579 }
4580 
4581 static void vposback (int oldvpos)
4582 {
4583 	if (cop_state.state == COP_wait && oldvpos == cop_state.vcmp) {
4584 		copper_enabled_thisline = 0;
4585 		unset_special (SPCFLAG_COPPER);
4586 	}
4587 }
4588 
4589 static void VPOSW (uae_u16 v)
4590 {
4591 	int oldvpos = vpos;
4592 #if 0
4593 	if (M68K_GETPC < 0xf00000 || 1)
4594 		write_log (_T("VPOSW %04X PC=%08x\n"), v, M68K_GETPC);
4595 #endif
4596 	if (lof_store != ((v & 0x8000) ? 1 : 0)) {
4597 		lof_store = (v & 0x8000) ? 1 : 0;
4598 		lof_changing = lof_store ? 1 : -1;
4599 	}
4600 	if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
4601 		lol = (v & 0x0080) ? 1 : 0;
4602 		if (!islinetoggle ())
4603 			lol = 0;
4604 	}
4605 	if (lof_changing)
4606 		return;
4607 	vpos &= 0x00ff;
4608 	v &= 7;
4609 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
4610 		v &= 1;
4611 	vpos |= v << 8;
4612 	if (vpos != oldvpos)
4613 		vposw_change++;
4614 	if (vpos < oldvpos)
4615 		vpos = oldvpos;
4616 }
4617 
4618 
4619 static void VHPOSW (uae_u16 v)
4620 {
4621 	int oldvpos = vpos;
4622 	bool changed = false;
4623 #if 0
4624 	if (M68K_GETPC < 0xf00000 || 1)
4625 		write_log (_T("VHPOSW %04X PC=%08x\n"), v, M68K_GETPC);
4626 #endif
4627 
4628 #if 0
4629 	/* This is not that easy, need to decouple denise and paula hpos counters
4630 	 * from master counter.
4631 	 * All this just to fix Upfront-CoolFridge Smooth Copper part..
4632 	 */
4633 	if (oldhpos != newhpos) {
4634 		oldhpos = current_hpos();
4635 		int newhpos = v & 0xff;
4636 		if (newhpos >= maxhpos)
4637 			newhpos = maxhpos - 1;
4638 		hpos_offset = newhpos - oldhpos;
4639 		eventtab[ev_hsync].evtime = get_cycles() + HSYNCTIME - (newhpos * CYCLE_UNIT);
4640 		eventtab[ev_hsync].oldcycles = get_cycles() - newhpos * CYCLE_UNIT;
4641 		events_schedule();
4642 		newhpos2 = current_hpos();
4643 #ifdef CPUEMU_13
4644 		if (currprefs.cpu_cycle_exact || currprefs.blitter_cycle_exact) {
4645 			memset(cycle_line + newhpos, 0, maxhpos - newhpos);
4646 			int hp = maxhpos - 1, i;
4647 			for (i = 0; i < 4; i++) {
4648 				alloc_cycle (hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH);
4649 			hp += 2;
4650 			if (hp >= maxhpos)
4651 				hp -= maxhpos;
4652 		}
4653 	}
4654 #endif
4655 		vposw_change++;
4656 		changed = true;
4657 	}
4658 #endif
4659 
4660 	v >>= 8;
4661 	vpos &= 0xff00;
4662 	vpos |= v;
4663 	if (vpos != oldvpos && !changed)
4664 		vposw_change++;
4665 	if (vpos < oldvpos) {
4666 		vpos = oldvpos;
4667 	} else if (vpos < minfirstline && oldvpos < minfirstline) {
4668 		vpos = oldvpos;
4669 	}
4670 #if 0
4671 	if (vpos < oldvpos)
4672 		vposback (oldvpos);
4673 #endif
4674 }
4675 
4676 static uae_u16 VHPOSR (void)
4677 {
4678 	static uae_u16 oldhp;
4679 	uae_u16 vp = GETVPOS ();
4680 	uae_u16 hp = GETHPOS ();
4681 
4682 	hp += HPOS_OFFSET;
4683 	if (hp >= maxhpos) {
4684 		hp -= maxhpos;
4685 		// vpos increases when hp==1, not when hp==0
4686 		if (hp >= VPOS_INC_DELAY) {
4687 			vp++;
4688 			if (vp >= maxvpos + lof_store)
4689 				vp = 0;
4690 		}
4691 	}
4692 	if (HPOS_OFFSET) {
4693 		hp += 1;
4694 		if (hp >= maxhpos)
4695 			hp -= maxhpos;
4696 	}
4697 
4698 	vp <<= 8;
4699 
4700 	if (hsyncdelay ()) {
4701 		// fake continuously changing hpos in fastest possible modes
4702 		hp = oldhp % maxhpos;
4703 		oldhp++;
4704 	}
4705 
4706 	vp |= hp;
4707 
4708 #if 0
4709 	if (M68K_GETPC < 0x00f00000 || M68K_GETPC >= 0x10000000)
4710 		write_log (_T("VPOS %04x %04x at %08x\n"), VPOSR (), vp, M68K_GETPC);
4711 #endif
4712 	return vp;
4713 }
4714 
4715 static void REFPTR(uae_u16 v)
4716 {
4717 	/*
4718 	 ECS Agnus:
4719 
4720 	 b15 8000: R 040
4721 	 b14 4000: R 020
4722 	 b13 2000: R 010
4723 	 b12 1000: R 008
4724 	 b11 0800: R 004
4725 	 b10 0400: R 002
4726 	 b09 0200: R 001
4727 	 b08 0100: C 080
4728 	 b07 0080: C 040
4729 	 b06 0040: C 020
4730 	 b05 0020: C 010
4731 	 b04 0010: C 008
4732 	 b03 0008: C 004
4733 	 b02 0004: C 002 C 100
4734 	 b01 0002: C 001 R 100
4735 	 b00 0001: R 080
4736 
4737 	*/
4738 
4739 	refptr = v;
4740 	refptr_val = (v & 0xfe00) | ((v & 0x01fe) >> 1);
4741 	if (v & 1) {
4742 		refptr_val |= 0x80 << 9;
4743 	}
4744 	if (v & 2) {
4745 		refptr_val |= 1;
4746 		refptr_val |= 0x100 << 9;
4747 	}
4748 	if (v & 4) {
4749 		refptr_val |= 2;
4750 		refptr_val |= 0x100;
4751 	}
4752 }
4753 
4754 static int test_copper_dangerous (unsigned int address)
4755 {
4756 	int addr = address & 0x01fe;
4757 	if (addr < ((copcon & 2) ? ((currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0 : 0x40) : 0x80)) {
4758 		cop_state.state = COP_stop;
4759 		copper_enabled_thisline = 0;
4760 		unset_special (SPCFLAG_COPPER);
4761 		return 1;
4762 	}
4763 	return 0;
4764 }
4765 
4766 static void immediate_copper (int num)
4767 {
4768 	int pos = 0;
4769 	int oldpos = 0;
4770 
4771 	cop_state.state = COP_stop;
4772 	cop_state.vpos = vpos;
4773 	cop_state.hpos = current_hpos () & ~1;
4774 	cop_state.ip = num == 1 ? cop1lc : cop2lc;
4775 
4776 	while (pos < (maxvpos << 5)) {
4777 		if (oldpos > pos)
4778 			pos = oldpos;
4779 		if (!dmaen(DMA_COPPER))
4780 			break;
4781 		if (cop_state.ip >= currprefs.chipmem_size && cop_state.ip < currprefs.z3chipmem_start && cop_state.ip >= currprefs.z3chipmem_start + currprefs.z3chipmem_size)
4782 			break;
4783 		pos++;
4784 		oldpos = pos;
4785 		cop_state.i1 = chipmem_wget_indirect (cop_state.ip);
4786 		cop_state.i2 = chipmem_wget_indirect (cop_state.ip + 2);
4787 		cop_state.ip += 4;
4788 		if (!(cop_state.i1 & 1)) { // move
4789 			cop_state.i1 &= 0x1fe;
4790 			if (cop_state.i1 == 0x88) {
4791 				cop_state.ip = cop1lc;
4792 				continue;
4793 			}
4794 			if (cop_state.i1 == 0x8a) {
4795 				cop_state.ip = cop2lc;
4796 				continue;
4797 			}
4798 			if (test_copper_dangerous (cop_state.i1))
4799 				break;
4800 			custom_wput_1 (0, cop_state.i1, cop_state.i2, 0);
4801 		} else { // wait or skip
4802 			if ((cop_state.i1 >> 8) > ((pos >> 5) & 0xff))
4803 				pos = (((pos >> 5) & 0x100) | ((cop_state.i1 >> 8)) << 5) | ((cop_state.i1 & 0xff) >> 3);
4804 			if (cop_state.i1 >= 0xffdf && cop_state.i2 == 0xfffe)
4805 				break;
4806 		}
4807 	}
4808 	cop_state.state = COP_stop;
4809 	unset_special (SPCFLAG_COPPER);
4810 }
4811 
4812 STATIC_INLINE void COP1LCH (uae_u16 v)
4813 {
4814 	cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16);
4815 }
4816 STATIC_INLINE void COP1LCL (uae_u16 v)
4817 {
4818 	cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe);
4819 }
4820 STATIC_INLINE void COP2LCH (uae_u16 v)
4821 {
4822 	cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16);
4823 }
4824 STATIC_INLINE void COP2LCL (uae_u16 v)
4825 {
4826 	cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe);
4827 }
4828 
4829 static void compute_spcflag_copper (int hpos);
4830 
4831 // vblank = copper starts at hpos=2
4832 // normal COPJMP write: takes 2 more cycles
4833 static void COPJMP (int num, int vblank)
4834 {
4835 	int oldstrobe = cop_state.strobe;
4836 	bool wasstopped = cop_state.state == COP_stop && !vblank;
4837 
4838 #if CUSTOM_DEBUG > 0
4839 	if (dmaen (DMA_COPPER) && (cop_state.saved_i1 != 0xffff || cop_state.saved_i2 != 0xfffe))
4840 		write_log (_T("vblank without copper ending %08x (%08x %08x)\n"), cop_state.ip, cop1lc, cop2lc);
4841 #endif
4842 
4843 	unset_special (SPCFLAG_COPPER);
4844 	cop_state.ignore_next = 0;
4845 
4846 	if (!oldstrobe)
4847 		cop_state.state_prev = cop_state.state;
4848 	if ((cop_state.state == COP_wait || cop_state.state == COP_waitforever) && !vblank && dmaen(DMA_COPPER)) {
4849 		cop_state.state = COP_strobe_delay1x;
4850 	} else {
4851 		cop_state.state = vblank ? COP_start_delay : (copper_access ? COP_strobe_delay1 : COP_strobe_extra);
4852 	}
4853 	cop_state.vpos = vpos;
4854 	cop_state.hpos = current_hpos () & ~1;
4855 	copper_enabled_thisline = 0;
4856 	cop_state.strobe = num;
4857 
4858 	if (nocustom ()) {
4859 		immediate_copper (num);
4860 		return;
4861 	}
4862 
4863 	if (dmaen (DMA_COPPER)) {
4864 		compute_spcflag_copper (current_hpos ());
4865 	} else if (wasstopped || (oldstrobe > 0 && oldstrobe != num && cop_state.state_prev == COP_wait)) {
4866 		/* dma disabled, copper idle and accessed both COPxJMPs -> copper stops! */
4867 		cop_state.state = COP_stop;
4868 	}
4869 }
4870 
4871 STATIC_INLINE void COPCON (uae_u16 a)
4872 {
4873 	copcon = a;
4874 }
4875 
4876 static void check_copper_stop(void)
4877 {
4878 	if (copper_enabled_thisline < 0 && !((dmacon & DMA_COPPER) && (dmacon & DMA_MASTER))) {
4879 		copper_enabled_thisline = 0;
4880 		unset_special (SPCFLAG_COPPER);
4881 	}
4882 }
4883 
4884 static void copper_stop(void)
4885 {
4886 	if (copper_enabled_thisline) {
4887 		// let MOVE to finish
4888 		switch (cop_state.state)
4889 		{
4890 			case COP_read2:
4891 			copper_enabled_thisline = -1;
4892 			break;
4893 		}
4894 	}
4895 	if (copper_enabled_thisline >= 0) {
4896 		copper_enabled_thisline = 0;
4897 		unset_special (SPCFLAG_COPPER);
4898 	}
4899 }
4900 
4901 static void DMACON (int hpos, uae_u16 v)
4902 {
4903 	int oldcop, newcop;
4904 	uae_u16 changed;
4905 
4906 	uae_u16 oldcon = dmacon;
4907 
4908 	decide_line (hpos);
4909 	decide_fetch_safe (hpos);
4910 
4911 	setclr (&dmacon, v);
4912 	dmacon &= 0x07FF;
4913 
4914 	changed = dmacon ^ oldcon;
4915 #if 0
4916 	if (changed)
4917 		write_log (_T("%04x -> %04x %08x\n"), oldcon, dmacon, m68k_getpc ());
4918 #endif
4919 	oldcop = (oldcon & DMA_COPPER) && (oldcon & DMA_MASTER);
4920 	newcop = (dmacon & DMA_COPPER) && (dmacon & DMA_MASTER);
4921 
4922 	if (oldcop != newcop) {
4923 		if (newcop && !oldcop) {
4924 			compute_spcflag_copper (hpos);
4925 		} else if (!newcop) {
4926 			copper_stop();
4927 		}
4928 	}
4929 
4930 #if 0
4931 	int oldb = (oldcon & DMA_BLITTER) && (oldcon & DMA_MASTER);
4932 	int newb = (dmacon & DMA_BLITTER) && (dmacon & DMA_MASTER);
4933 	int oldbn = (oldcon & DMA_BLITPRI) != 0;
4934 	int newbn = (dmacon & DMA_BLITPRI) != 0;
4935 	if (oldbn != newbn)
4936 		write_log (_T("BLITTER NASTY: %d -> %d %08x\n"), oldbn, newbn, m68k_getpc ());
4937 #endif
4938 
4939 #if SPRITE_DEBUG > 0
4940 	{
4941 		int olds = (oldcon & DMA_SPRITE) && (oldcon & DMA_MASTER);
4942 		int news = (dmacon & DMA_SPRITE) && (dmacon & DMA_MASTER);
4943 		if (olds != news)
4944 			write_log (_T("SPRITE DMA: %d -> %d %08x\n"), olds, news, m68k_getpc ());
4945 	}
4946 #endif
4947 
4948 	if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done)
4949 		set_special (SPCFLAG_BLTNASTY);
4950 
4951 	if (dmaen (DMA_BLITTER) && bltstate == BLT_init) {
4952 		blitter_check_start ();
4953 	}
4954 
4955 	if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER))
4956 		unset_special (SPCFLAG_BLTNASTY);
4957 
4958 	if (changed & (DMA_MASTER | 0x0f))
4959 		audio_state_machine ();
4960 
4961 	if (changed & (DMA_MASTER | DMA_BITPLANE)) {
4962 		SET_LINE_CYCLEBASED;
4963 		bitplane_maybe_start_hpos = hpos;
4964 #if 0
4965 		if (dmaen (DMA_BITPLANE)) {
4966 			if (vpos == 0xba)
4967 				write_log (_T("*"));
4968 //			maybe_start_bpl_dma (hpos);
4969 		} else {
4970 			write_log (_T("!"));
4971 		}
4972 #endif
4973 	}
4974 }
4975 
4976 static int irq_nmi;
4977 
4978 void NMI_delayed (void)
4979 {
4980 	irq_nmi = 1;
4981 }
4982 
4983 static uae_u16 intreq_internal, intena_internal;
4984 
4985 int intlev (void)
4986 {
4987 	uae_u16 imask = intreq_internal & intena_internal;
4988 	if (irq_nmi) {
4989 		irq_nmi = 0;
4990 		return 7;
4991 	}
4992 	if (!(imask && (intena_internal & 0x4000)))
4993 		return -1;
4994 	if (imask & (0x4000 | 0x2000))						// 13 14
4995 		return 6;
4996 	if (imask & (0x1000 | 0x0800))						// 11 12
4997 		return 5;
4998 	if (imask & (0x0400 | 0x0200 | 0x0100 | 0x0080))	// 7 8 9 10
4999 		return 4;
5000 	if (imask & (0x0040 | 0x0020 | 0x0010))				// 4 5 6
5001 		return 3;
5002 	if (imask & 0x0008)									// 3
5003 		return 2;
5004 	if (imask & (0x0001 | 0x0002 | 0x0004))				// 0 1 2
5005 		return 1;
5006 	return -1;
5007 }
5008 
5009 #define INT_PROCESSING_DELAY (3 * CYCLE_UNIT)
5010 STATIC_INLINE int use_eventmode (uae_u16 v)
5011 {
5012 	if (currprefs.cpu_cycle_exact && currprefs.cpu_model <= 68020)
5013 		return 1;
5014 	return 0;
5015 }
5016 
5017 static void rethink_intreq (void)
5018 {
5019 	serial_check_irq ();
5020 	devices_rethink();
5021 }
5022 
5023 static void send_interrupt_do (uae_u32 v)
5024 {
5025 	INTREQ_0 (0x8000 | (1 << v));
5026 }
5027 
5028 void send_interrupt (int num, int delay)
5029 {
5030 	if (use_eventmode (0x8000) && delay > 0) {
5031 		// always queue interrupt if it is active because
5032 		// next instruction in bad code can switch it off..
5033 		// Absolute Inebriation / Virtual Dreams "big glenz" part
5034 		if (!(intreq & (1 << num)) || (intena & (1 << num)))
5035 			event2_newevent_xx (-1, delay, num, send_interrupt_do);
5036 	} else {
5037 		send_interrupt_do (num);
5038 	}
5039 }
5040 
5041 static int int_recursive; // yes, bad idea.
5042 
5043 static void send_intena_do (uae_u32 v)
5044 {
5045 	setclr (&intena_internal, v);
5046 	doint ();
5047 }
5048 
5049 static void send_intreq_do (uae_u32 v)
5050 {
5051 	setclr (&intreq_internal, v);
5052 	int_recursive++;
5053 	rethink_intreq ();
5054 	int_recursive--;
5055 	doint ();
5056 }
5057 
5058 static void INTENA (uae_u16 v)
5059 {
5060 	uae_u16 old = intena;
5061 	setclr (&intena, v);
5062 
5063 	if (!(v & 0x8000) && old == intena && intena == intena_internal)
5064 		return;
5065 
5066 	//write_log (_T("%04x %04x %04x %04x\n"), intena, intena_internal, intreq, intreq_internal);
5067 
5068 	if (use_eventmode (v)) {
5069 		if (old == intena && intena == intena_internal)
5070 			return;
5071 		event2_newevent_xx (-1, INT_PROCESSING_DELAY, v, send_intena_do);
5072 	} else {
5073 		intena_internal = intena;
5074 		if (v & 0x8000)
5075 			doint ();
5076 	}
5077 #if 0
5078 	if (v & 0x40)
5079 		write_log (_T("INTENA %04X (%04X) %p\n"), intena, v, M68K_GETPC);
5080 #endif
5081 }
5082 
5083 static void INTREQ_nodelay (uae_u16 v)
5084 {
5085 	setclr (&intreq, v);
5086 	setclr (&intreq_internal, v);
5087 	doint ();
5088 }
5089 
5090 void INTREQ_f (uae_u16 v)
5091 {
5092 	if (use_eventmode (v)) {
5093 		setclr (&intreq, v);
5094 		send_intreq_do (v);
5095 	} else {
5096 		uae_u16 old = intreq;
5097 		setclr (&intreq, v);
5098 		setclr (&intreq_internal, v);
5099 		if ((old & 0x0800) && !(intreq & 0x0800))
5100 			serial_rbf_clear();
5101 	}
5102 }
5103 
5104 bool INTREQ_0 (uae_u16 v)
5105 {
5106 #if 0
5107 	if (!(v & 0x8000) && (v & (0x80 | 0x100 | 0x200 | 0x400) != 0x0780))
5108 		write_log (_T("audirq clear %04x %04x\n"), v, intreq);
5109 #endif
5110 	uae_u16 old = intreq;
5111 	setclr (&intreq, v);
5112 
5113 	if ((old & 0x0800) && !(intreq & 0x0800))
5114 		serial_rbf_clear();
5115 
5116 	if (int_recursive) {
5117 		// don't add new event if this call came from send_intreq_do/rethink
5118 		// and intreq didn't change.
5119 		// it wouldn't make any difference except to slow down everything
5120 		if (old == intreq)
5121 			return false;
5122 	}
5123 
5124 	if (use_eventmode (v)) {
5125 		// don't bother to waste time for interrupt queuing if nothing changes
5126 		// but only if we are sure there is no other queued changes
5127 		if (old == intreq && intreq_internal == intreq)
5128 			return false;
5129 		event2_newevent_xx (-1, INT_PROCESSING_DELAY, v, send_intreq_do);
5130 		return false;
5131 	} else {
5132 		uae_u16 old2 = intreq_internal;
5133 		intreq_internal = intreq;
5134 		if (old == intreq && old2 == intreq_internal)
5135 			return false;
5136 		if (v & 0x8000)
5137 			doint ();
5138 		return true;
5139 	}
5140 }
5141 
5142 void INTREQ (uae_u16 data)
5143 {
5144 	if (INTREQ_0 (data))
5145 		rethink_intreq ();
5146 }
5147 
5148 static void ADKCON (int hpos, uae_u16 v)
5149 {
5150 	if (currprefs.produce_sound > 0)
5151 		update_audio ();
5152 	DISK_update (hpos);
5153 	DISK_update_adkcon (hpos, v);
5154 	setclr (&adkcon, v);
5155 	audio_update_adkmasks ();
5156 	if ((v >> 11) & 1)
5157 		serial_uartbreak ((adkcon >> 11) & 1);
5158 }
5159 
5160 static void BEAMCON0 (uae_u16 v)
5161 {
5162 	if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
5163 		if (v != new_beamcon0) {
5164 			new_beamcon0 = v;
5165 			if (v & ~0x20) {
5166 				write_log (_T("warning: %04X written to BEAMCON0 PC=%08X\n"), v, M68K_GETPC);
5167 				dumpsync();
5168 			}
5169 		}
5170 		calcdiw();
5171 	}
5172 }
5173 
5174 static void varsync (void)
5175 {
5176 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
5177 		return;
5178 #ifdef PICASSO96
5179 	if (picasso_on && p96refresh_active) {
5180 		vtotal = p96refresh_active;
5181 		return;
5182 	}
5183 #endif
5184 	if (!(beamcon0 & 0x80))
5185 		return;
5186 	varsync_changed = true;
5187 }
5188 
5189 #ifdef PICASSO96
5190 void set_picasso_hack_rate (int hz)
5191 {
5192 	if (!picasso_on)
5193 		return;
5194 	vpos_count = 0;
5195 	p96refresh_active = (int)(maxvpos_stored * vblank_hz_stored / hz);
5196 	if (!currprefs.cs_ciaatod)
5197 		changed_prefs.cs_ciaatod = currprefs.cs_ciaatod = currprefs.ntscmode ? 2 : 1;
5198 	if (p96refresh_active > 0) {
5199 		new_beamcon0 |= 0x80;
5200 	}
5201 }
5202 #endif
5203 
5204 /* "Dangerous" blitter D-channel: Writing to memory which is also currently
5205  * read by bitplane DMA
5206  */
5207 static void dcheck_is_blit_dangerous (void)
5208 {
5209 	check_is_blit_dangerous (bplpt, bplcon0_planes, 50 << bplcon0_res);
5210 }
5211 
5212 static void BPLxPTH (int hpos, uae_u16 v, int num)
5213 {
5214 	decide_line (hpos);
5215 	decide_fetch_safe (hpos);
5216 	if (copper_access && is_bitplane_dma (hpos + 1) == num + 1) {
5217 #if 0
5218 		if (is_bitplane_dma(hpos + 2)) {
5219 			dbplpth[num] = (v << 16) & 0xffff0000;
5220 			dbplpth_on[num] = hpos;
5221 			dbplpth_on2++;
5222 		}
5223 #endif
5224 		SET_LINE_CYCLEBASED;
5225 		return;
5226 	}
5227 
5228 	bplpt[num] = (bplpt[num] & 0x0000ffff) | ((uae_u32)v << 16);
5229 	bplptx[num] = (bplptx[num] & 0x0000ffff) | ((uae_u32)v << 16);
5230 	dcheck_is_blit_dangerous ();
5231 	//write_log (_T("%d:%d:BPL%dPTH %08X COP=%08x\n"), hpos, vpos, num, bplpt[num], cop_state.ip);
5232 }
5233 static void BPLxPTL (int hpos, uae_u16 v, int num)
5234 {
5235 	decide_line (hpos);
5236 	decide_fetch_safe (hpos);
5237 #if 0
5238 	reset_dbplh (hpos, num);
5239 #endif
5240 	/* chipset feature:
5241 	 * BPLxPTL write and next cycle doing DMA fetch using same pointer register ->
5242 	 * next DMA cycle uses old value.
5243 	 * (Multiscroll / Cult)
5244 	 *
5245 	 * If following cycle is not BPL DMA: written value is lost
5246 	 *
5247 	 * last fetch block does not have this side-effect, probably due to modulo adds.
5248 	 * Also it seems only plane 0 fetches have this feature (because of above reason!)
5249 	 * (MoreNewStuffy / PlasmaForce)
5250 	 */
5251 	/* only detect copper accesses to prevent too fast CPU mode glitches */
5252 	if (copper_access && is_bitplane_dma (hpos + 1) == num + 1) {
5253 #if 0
5254 		if (num == 0 && plf_state >= plf_passed_stop) {
5255 			/* modulo adds use old value! Argh! (This is wrong and disabled) */
5256 			dbplptl[num] = v & 0x0000fffe;
5257 			dbplptl_on[num] = -1;
5258 			dbplptl_on2++;
5259 		} else if (is_bitplane_dma(hpos + 2)) {
5260 			dbplptl[num] = v & 0x0000fffe;
5261 			dbplptl_on[num] = hpos;
5262 			dbplptl_on2++;
5263 		}
5264 #endif
5265 		SET_LINE_CYCLEBASED;
5266 		return;
5267 	}
5268 	bplpt[num] = (bplpt[num] & 0xffff0000) | (v & 0x0000fffe);
5269 	bplptx[num] = (bplptx[num] & 0xffff0000) | (v & 0x0000fffe);
5270 	dcheck_is_blit_dangerous ();
5271 	//write_log (_T("%d:%d:BPL%dPTL %08X COP=%08x\n"), hpos, vpos, num, bplpt[num], cop_state.ip);
5272 }
5273 
5274 static void BPLCON0_Denise (int hpos, uae_u16 v, bool immediate)
5275 {
5276 	if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
5277 		v &= ~0x00F1;
5278 	else if (! (currprefs.chipset_mask & CSMASK_AGA))
5279 		v &= ~0x00B0;
5280 	v &= ~(0x0200 | 0x0100 | 0x0080 | 0x0020);
5281 #if SPRBORDER
5282 	v |= 1;
5283 #endif
5284 
5285 	if (bplcon0d == v && !immediate)
5286 		return;
5287 
5288 	bplcon0dd = -1;
5289 	// fake unused 0x0080 bit as an EHB bit (see below)
5290 	if (isehb (bplcon0d, bplcon2))
5291 		v |= 0x80;
5292 	if (immediate) {
5293 		record_register_change (hpos, 0x100, v);
5294 	} else {
5295 		record_register_change (hpos, 0x100, (bplcon0d & ~(0x800 | 0x400 | 0x80)) | (v & (0x0800 | 0x400 | 0x80 | 0x01)));
5296 	}
5297 
5298 	bplcon0d = v & ~0x80;
5299 
5300 #ifdef ECS_DENISE
5301 	if (currprefs.chipset_mask & CSMASK_ECS_DENISE) {
5302 		decide_sprites (hpos);
5303 		sprres = expand_sprres (v, bplcon3);
5304 	}
5305 #endif
5306 	if (thisline_decision.plfleft < 0)
5307 		update_denise (hpos);
5308 	else
5309 		update_denise_shifter_planes (hpos);
5310 }
5311 
5312 static void BPLCON0 (int hpos, uae_u16 v)
5313 {
5314 	if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
5315 		v &= ~0x00F1;
5316 	else if (! (currprefs.chipset_mask & CSMASK_AGA))
5317 		v &= ~0x00B0;
5318 	v &= ~(0x0080 | 0x0020);
5319 
5320 #if SPRBORDER
5321 	v |= 1;
5322 #endif
5323 	if (bplcon0 == v)
5324 		return;
5325 
5326 	SET_LINE_CYCLEBASED;
5327 	decide_diw (hpos);
5328 	decide_line (hpos);
5329 	decide_fetch_safe (hpos);
5330 
5331 	if (!issyncstopped ()) {
5332 		vpos_previous = vpos;
5333 		hpos_previous = hpos;
5334 	}
5335 
5336 	if (bplcon0 & 4)
5337 		bplcon0_interlace_seen = true;
5338 
5339 	bplcon0 = v;
5340 
5341 	bpldmainitdelay (hpos);
5342 
5343 	if (thisline_decision.plfleft < 0)
5344 		BPLCON0_Denise (hpos, v, true);
5345 }
5346 
5347 static void BPLCON1 (int hpos, uae_u16 v)
5348 {
5349 	if (!(currprefs.chipset_mask & CSMASK_AGA))
5350 		v &= 0xff;
5351 	if (bplcon1 == v)
5352 		return;
5353 	SET_LINE_CYCLEBASED;
5354 	decide_line (hpos);
5355 	decide_fetch_safe (hpos);
5356 	bplcon1_written = true;
5357 	bplcon1 = v;
5358 	hack_shres_delay(hpos);
5359 }
5360 
5361 static void BPLCON2(int hpos, uae_u16 v)
5362 {
5363 	if (!(currprefs.chipset_mask & CSMASK_AGA))
5364 		v &= 0x7f;
5365 	if ((bplcon2 & 0x3fff) == (v & 0x3fff))
5366 		return;
5367 	decide_line (hpos);
5368 	bplcon2 = v;
5369 	record_register_change (hpos, 0x104, bplcon2);
5370 }
5371 
5372 #ifdef ECS_DENISE
5373 static void BPLCON3(int hpos, uae_u16 v)
5374 {
5375 	if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE))
5376 		return;
5377 	if (!(currprefs.chipset_mask & CSMASK_AGA)) {
5378 		v &= 0x003f;
5379 		v |= 0x0c00;
5380 	}
5381 #if SPRBORDER
5382 	v |= 2;
5383 #endif
5384 	if (bplcon3 == v)
5385 		return;
5386 	decide_line (hpos);
5387 	decide_sprites (hpos);
5388 	bplcon3 = v;
5389 	sprres = expand_sprres (bplcon0, bplcon3);
5390 	record_register_change (hpos, 0x106, v);
5391 }
5392 #endif
5393 #ifdef AGA
5394 static void BPLCON4(int hpos, uae_u16 v)
5395 {
5396 	if (!(currprefs.chipset_mask & CSMASK_AGA))
5397 		return;
5398 	if (bplcon4 == v)
5399 		return;
5400 	decide_line (hpos);
5401 	bplcon4 = v;
5402 	record_register_change (hpos, 0x10c, v);
5403 }
5404 #endif
5405 
5406 static void BPL1MOD (int hpos, uae_u16 v)
5407 {
5408 	v &= ~1;
5409 	if ((uae_s16)bpl1mod != (uae_s16)v) {
5410 		decide_line (hpos);
5411 		decide_fetch_safe (hpos);
5412 	}
5413 	// write to BPLxMOD one cycle before
5414 	// BPL fetch that also adds modulo:
5415 	// Old BPLxMOD value is added.
5416 	if (1 && (is_bitplane_dma (hpos + 1) & 1)) {
5417 		dbpl1mod = v;
5418 		dbpl1mod_on = hpos + 1;
5419 	} else {
5420 		bpl1mod = v;
5421 		dbpl1mod_on = 0;
5422 	}
5423 }
5424 
5425 static void BPL2MOD (int hpos, uae_u16 v)
5426 {
5427 	v &= ~1;
5428 	if ((uae_s16)bpl2mod != (uae_s16)v) {
5429 		decide_line (hpos);
5430 		decide_fetch_safe (hpos);
5431 	}
5432 	if (1 && (is_bitplane_dma (hpos + 1) & 2)) {
5433 		dbpl2mod = v;
5434 		dbpl2mod_on = hpos + 1;
5435 	} else {
5436 		bpl2mod = v;
5437 		dbpl2mod_on = 0;
5438 	}
5439 }
5440 
5441 /* Needed in special OCS/ECS "7-plane" mode,
5442  * also handles CPU generated bitplane data
5443  */
5444 static void BPLxDAT (int hpos, int num, uae_u16 v)
5445 {
5446 	// only BPL1DAT access can do anything visible
5447 	if (num == 0 && hpos >= 8) {
5448 		decide_line (hpos);
5449 		decide_fetch_safe (hpos);
5450 	}
5451 	flush_display (fetchmode);
5452 	fetched[num] = v;
5453 #ifdef AGA
5454 	fetched_aga[num] = v;
5455 #endif
5456 	if (num == 0 && hpos >= 8) {
5457 		bpl1dat_written = true;
5458 		bpl1dat_written_at_least_once = true;
5459 		if (thisline_decision.plfleft < 0)
5460 			reset_bpl_vars ();
5461 		beginning_of_plane_block (hpos, fetchmode);
5462 	}
5463 }
5464 
5465 static void DIWSTRT (int hpos, uae_u16 v)
5466 {
5467 	if (diwstrt == v && ! diwhigh_written)
5468 		return;
5469 	decide_diw (hpos);
5470 	decide_line (hpos);
5471 	diwhigh_written = 0;
5472 	diwstrt = v;
5473 	calcdiw ();
5474 }
5475 
5476 static void DIWSTOP (int hpos, uae_u16 v)
5477 {
5478 	if (diwstop == v && ! diwhigh_written)
5479 		return;
5480 	decide_diw (hpos);
5481 	decide_line (hpos);
5482 	diwhigh_written = 0;
5483 	diwstop = v;
5484 	calcdiw ();
5485 }
5486 
5487 static void DIWHIGH (int hpos, uae_u16 v)
5488 {
5489 	if (!(currprefs.chipset_mask & (CSMASK_ECS_DENISE | CSMASK_ECS_AGNUS)))
5490 		return;
5491 	if (!(currprefs.chipset_mask & CSMASK_AGA))
5492 		v &= ~(0x0008 | 0x0010 | 0x1000 | 0x0800);
5493 	v &= ~(0x8000 | 0x4000 | 0x0080 | 0x0040);
5494 	if (diwhigh_written && diwhigh == v)
5495 		return;
5496 	decide_line (hpos);
5497 	diwhigh_written = 1;
5498 	diwhigh = v;
5499 	calcdiw ();
5500 }
5501 
5502 static void DDFSTRT (int hpos, uae_u16 v)
5503 {
5504 	v &= 0xfe;
5505 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
5506 		v &= 0xfc;
5507 	decide_line (hpos);
5508 	SET_LINE_CYCLEBASED;
5509 	// Move state back to passed_enable if this DDFSTRT write was done exactly when
5510 	// it would match and start bitplane DMA.
5511 	if (hpos == ddfstrt - DDF_OFFSET && plf_state == plf_passed_start && plf_start_hpos == hpos + DDF_OFFSET) {
5512 		plf_state = plf_passed_enable;
5513 		plf_start_hpos = maxhpos;
5514 	}
5515 	ddfstrt = v;
5516 	calcdiw ();
5517 	if (fetch_state != fetch_not_started)
5518 		estimate_last_fetch_cycle (hpos);
5519 	if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
5520 		static int last_warned;
5521 		last_warned = (last_warned + 1) & 4095;
5522 		if (last_warned == 0)
5523 			write_log (_T("WARNING! Very strange DDF values (%x %x).\n"), ddfstrt, ddfstop);
5524 	}
5525 }
5526 
5527 static void DDFSTOP (int hpos, uae_u16 v)
5528 {
5529 	v &= 0xfe;
5530 	if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
5531 		v &= 0xfc;
5532 	decide_line (hpos);
5533 	decide_fetch_safe (hpos);
5534 	SET_LINE_CYCLEBASED;
5535 	// DDFSTOP write when old DDFSTOP value match: old value matches normally.
5536 	// Works differently than DDFSTRT which is interesting.
5537 	if (hpos == v - DDF_OFFSET) {
5538 		if (plf_state == plf_passed_stop && plf_end_hpos == hpos + DDF_OFFSET) {
5539 			plf_state = plf_active;
5540 			plf_end_hpos = 256 + DDF_OFFSET;
5541 			// don't let one_fetch_cycle_0() to do this again
5542 			ddfstop_written_hpos = hpos;
5543 		}
5544 	} else if (hpos == ddfstop - DDF_OFFSET) {
5545 		// if old ddfstop would have matched, emulate it here
5546 		if (plf_state == plf_active) {
5547 			plf_state = plf_passed_stop;
5548 			plf_end_hpos = hpos + DDF_OFFSET;
5549 		}
5550 	}
5551 	ddfstop = v;
5552 	calcdiw ();
5553 	if (fetch_state != fetch_not_started)
5554 		estimate_last_fetch_cycle (hpos);
5555 	if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
5556 		static int last_warned;
5557 		if (last_warned == 0)
5558 			write_log (_T("WARNING! Very strange DDF values (%x).\n"), ddfstop);
5559 		last_warned = (last_warned + 1) & 4095;
5560 	}
5561 }
5562 
5563 static void FMODE (int hpos, uae_u16 v)
5564 {
5565 	if (!(currprefs.chipset_mask & CSMASK_AGA)) {
5566 		if (currprefs.monitoremu)
5567 			specialmonitor_store_fmode(vpos, hpos, v);
5568 		v = 0;
5569 	}
5570 	v &= 0xC00F;
5571 	if (fmode == v)
5572 		return;
5573 	SET_LINE_CYCLEBASED;
5574 	fmode_saved = v;
5575 	set_chipset_mode();
5576 	bpldmainitdelay (hpos);
5577 }
5578 
5579 static void FNULL (uae_u16 v)
5580 {
5581 
5582 }
5583 
5584 static void BLTADAT (int hpos, uae_u16 v)
5585 {
5586 	maybe_blit (hpos, 0);
5587 
5588 	blt_info.bltadat = v;
5589 }
5590 /*
5591 * "Loading data shifts it immediately" says the HRM. Well, that may
5592 * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
5593 * loaded for every word so that AFWM and ALWM can be applied.
5594 */
5595 static void BLTBDAT (int hpos, uae_u16 v)
5596 {
5597 	maybe_blit (hpos, 0);
5598 
5599 	if (bltcon1 & 2)
5600 		blt_info.bltbhold = v << (bltcon1 >> 12);
5601 	else
5602 		blt_info.bltbhold = v >> (bltcon1 >> 12);
5603 	blt_info.bltbdat = v;
5604 }
5605 static void BLTCDAT (int hpos, uae_u16 v) { maybe_blit (hpos, 0); blt_info.bltcdat = v; reset_blit (0); }
5606 
5607 static void BLTAMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltamod = (uae_s16)(v & 0xFFFE); reset_blit (0); }
5608 static void BLTBMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); reset_blit (0); }
5609 static void BLTCMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); reset_blit (0); }
5610 static void BLTDMOD (int hpos, uae_u16 v) { maybe_blit (hpos, 1); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); reset_blit (0); }
5611 
5612 static void BLTCON0 (int hpos, uae_u16 v) { maybe_blit (hpos, 2); bltcon0 = v; reset_blit (1); }
5613 /* The next category is "Most useless hardware register".
5614 * And the winner is... */
5615 static void BLTCON0L (int hpos, uae_u16 v)
5616 {
5617 	if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
5618 		return; // ei voittoa.
5619 	maybe_blit (hpos, 2); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
5620 	reset_blit (1);
5621 }
5622 static void BLTCON1 (int hpos, uae_u16 v) { maybe_blit (hpos, 2); bltcon1 = v; reset_blit (2); }
5623 
5624 static void BLTAFWM (int hpos, uae_u16 v) { maybe_blit (hpos, 2); blt_info.bltafwm = v; reset_blit (0); }
5625 static void BLTALWM (int hpos, uae_u16 v) { maybe_blit (hpos, 2); blt_info.bltalwm = v; reset_blit (0); }
5626 
5627 static void BLTAPTH (int hpos, uae_u16 v)
5628 {
5629 	maybe_blit (hpos, 0);
5630 	if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_cycle_exact) {
5631 		bltptx = (bltapt & 0xffff) | ((uae_u32)v << 16);
5632 		bltptxpos = hpos;
5633 		bltptxc = 1;
5634 	} else {
5635 		bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16);
5636 	}
5637 }
5638 static void BLTAPTL (int hpos, uae_u16 v)
5639 {
5640 	maybe_blit (hpos, 0);
5641 	if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_cycle_exact) {
5642 		bltptx = (bltapt & ~0xffff) | (v & 0xFFFE);
5643 		bltptxpos = hpos;
5644 		bltptxc = 1;
5645 	} else {
5646 		bltapt = (bltapt & ~0xffff) | (v & 0xFFFE);
5647 	}
5648 }
5649 static void BLTBPTH (int hpos, uae_u16 v)
5650 {
5651 	maybe_blit (hpos, 0);
5652 	if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_cycle_exact) {
5653 		bltptx = (bltapt & 0xffff) | ((uae_u32)v << 16);
5654 		bltptxpos = hpos;
5655 		bltptxc = 2;
5656 	} else {
5657 		bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16);
5658 	}
5659 }
5660 static void BLTBPTL (int hpos, uae_u16 v)
5661 {
5662 	maybe_blit (hpos, 0);
5663 	if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_cycle_exact) {
5664 		bltptx = (bltbpt & ~0xffff) | (v & 0xFFFE);
5665 		bltptxpos = hpos;
5666 		bltptxc = 2;
5667 	} else {
5668 		bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE);
5669 	}
5670 }
5671 static void BLTCPTH (int hpos, uae_u16 v)
5672 {
5673 	maybe_blit (hpos, 0);
5674 	if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_cycle_exact) {
5675 		bltptx = (bltcpt & 0xffff) | ((uae_u32)v << 16);
5676 		bltptxpos = hpos;
5677 		bltptxc = 3;
5678 	} else {
5679 		bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16);
5680 	}
5681 }
5682 static void BLTCPTL (int hpos, uae_u16 v)
5683 {
5684 	maybe_blit (hpos, 0);
5685 	if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_cycle_exact) {
5686 		bltptx = (bltcpt & ~0xffff) | (v & 0xFFFE);
5687 		bltptxpos = hpos;
5688 		bltptxc = 3;
5689 	} else {
5690 		bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE);
5691 	}
5692 }
5693 static void BLTDPTH (int hpos, uae_u16 v)
5694 {
5695 	maybe_blit (hpos, 0);
5696 	if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_cycle_exact) {
5697 		bltptx = (bltdpt & 0xffff) | ((uae_u32)v << 16);
5698 		bltptxpos = hpos;
5699 		bltptxc = 4;
5700 	} else {
5701 		bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16);
5702 	}
5703 }
5704 static void BLTDPTL (int hpos, uae_u16 v)
5705 {
5706 	maybe_blit (hpos, 0);
5707 	if (bltstate != BLT_done && currprefs.blitter_cycle_exact && currprefs.cpu_cycle_exact) {
5708 		bltptx = (bltdpt & ~0xffff) | (v & 0xFFFE);
5709 		bltptxpos = hpos;
5710 		bltptxc = 4;
5711 	} else {
5712 		bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE);
5713 	}
5714 }
5715 
5716 static void BLTSIZE (int hpos, uae_u16 v)
5717 {
5718 	maybe_blit (hpos, 0);
5719 
5720 	blt_info.vblitsize = v >> 6;
5721 	blt_info.hblitsize = v & 0x3F;
5722 	if (!blt_info.vblitsize)
5723 		blt_info.vblitsize = 1024;
5724 	if (!blt_info.hblitsize)
5725 		blt_info.hblitsize = 64;
5726 	do_blitter (hpos, copper_access);
5727 	dcheck_is_blit_dangerous ();
5728 }
5729 
5730 static void BLTSIZV (int hpos, uae_u16 v)
5731 {
5732 	if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
5733 		return;
5734 	maybe_blit (hpos, 0);
5735 	blt_info.vblitsize = v & 0x7FFF;
5736 }
5737 
5738 static void BLTSIZH (int hpos, uae_u16 v)
5739 {
5740 	if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
5741 		return;
5742 	maybe_blit (hpos, 0);
5743 	blt_info.hblitsize = v & 0x7FF;
5744 	if (!blt_info.vblitsize)
5745 		blt_info.vblitsize = 0x8000;
5746 	if (!blt_info.hblitsize)
5747 		blt_info.hblitsize = 0x0800;
5748 	do_blitter (hpos, copper_access);
5749 }
5750 
5751 STATIC_INLINE void spr_arm (int num, int state)
5752 {
5753 #if SPRITE_DEBUG > 0
5754 	if (spr[num].armed != state)
5755 		write_log (_T("SPR%d ARM=%d\n"), num, state);
5756 #endif
5757 	switch (state) {
5758 	case 0:
5759 		nr_armed -= spr[num].armed;
5760 		spr[num].armed = 0;
5761 		break;
5762 	default:
5763 		nr_armed += 1 - spr[num].armed;
5764 		spr[num].armed = 1;
5765 		break;
5766 	}
5767 }
5768 
5769 STATIC_INLINE void sprstartstop (struct sprite *s)
5770 {
5771 	if (vpos < sprite_vblank_endline || cant_this_last_line () || s->ignoreverticaluntilnextline)
5772 		return;
5773 	if (vpos == s->vstart)
5774 		s->dmastate = 1;
5775 	if (vpos == s->vstop)
5776 		s->dmastate = 0;
5777 }
5778 
5779 static void SPRxCTLPOS(int num)
5780 {
5781 	int sprxp;
5782 	struct sprite *s = &spr[num];
5783 
5784 	sprstartstop (s);
5785 	sprxp = (sprpos[num] & 0xFF) * 2 + (sprctl[num] & 1);
5786 	sprxp <<= sprite_buffer_res;
5787 	/* Quite a bit salad in this register... */
5788 	if (0) {
5789 	}
5790 #ifdef AGA
5791 	else if (currprefs.chipset_mask & CSMASK_AGA) {
5792 		sprxp |= ((sprctl[num] >> 3) & 3) >> (RES_MAX - sprite_buffer_res);
5793 		s->dblscan = sprpos[num] & 0x80;
5794 	}
5795 #endif
5796 #ifdef ECS_DENISE
5797 	else if (currprefs.chipset_mask & CSMASK_ECS_DENISE) {
5798 		sprxp |= ((sprctl[num] >> 3) & 2) >> (RES_MAX - sprite_buffer_res);
5799 	}
5800 #endif
5801 	s->xpos = sprxp;
5802 	s->vstart = sprpos[num] >> 8;
5803 	s->vstart |= (sprctl[num] & 0x04) ? 0x0100 : 0;
5804 	s->vstop = sprctl[num] >> 8;
5805 	s->vstop |= (sprctl[num] & 0x02) ? 0x100 : 0;
5806 	if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
5807 		s->vstart |= (sprctl[num] & 0x40) ? 0x0200 : 0;
5808 		s->vstop |= (sprctl[num] & 0x20) ? 0x0200 : 0;
5809 	}
5810 	sprstartstop (s);
5811 }
5812 
5813 static void SPRxCTL_1(uae_u16 v, int num, int hpos)
5814 {
5815 	if (hpos >= maxhpos - 2 && sprctl[num] != v && vpos < maxvpos - 1) {
5816 		struct sprite *s = &spr[num];
5817 		vpos++;
5818 		sprstartstop(s);
5819 		vpos--;
5820 		s->ignoreverticaluntilnextline = true;
5821 		sprite_ignoreverticaluntilnextline = true;
5822 	}
5823 	sprctl[num] = v;
5824 	spr_arm (num, 0);
5825 	SPRxCTLPOS (num);
5826 
5827 #if SPRITE_DEBUG > 0
5828 	struct sprite *s = &spr[num];
5829 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
5830 		write_log (_T("%d:%d:SPR%dCTL %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x\n"),
5831 			vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC);
5832 	}
5833 #endif
5834 
5835 }
5836 static void SPRxPOS_1(uae_u16 v, int num, int hpos)
5837 {
5838 	if (hpos >= maxhpos - 2 && sprpos[num] != v && vpos < maxvpos - 1) {
5839 		struct sprite *s = &spr[num];
5840 		vpos++;
5841 		sprstartstop(s);
5842 		vpos--;
5843 		s->ignoreverticaluntilnextline = true;
5844 		sprite_ignoreverticaluntilnextline = true;
5845 	}
5846 	sprpos[num] = v;
5847 	SPRxCTLPOS (num);
5848 #if SPRITE_DEBUG > 0
5849 	struct sprite *s = &spr[num];
5850 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
5851 		write_log (_T("%d:%d:SPR%dPOS %04X P=%06X VSTRT=%d VSTOP=%d HSTRT=%d D=%d A=%d CP=%x PC=%x\n"),
5852 			vpos, hpos, num, v, s->pt, s->vstart, s->vstop, s->xpos, spr[num].dmastate, spr[num].armed, cop_state.ip, M68K_GETPC);
5853 	}
5854 #endif
5855 }
5856 static void SPRxDATA_1(uae_u16 v, int num, int hpos)
5857 {
5858 	sprdata[num][0] = v;
5859 #ifdef AGA
5860 	sprdata[num][1] = v;
5861 	sprdata[num][2] = v;
5862 	sprdata[num][3] = v;
5863 #endif
5864 	spr_arm (num, 1);
5865 #if SPRITE_DEBUG >= 256
5866 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
5867 		write_log (_T("%d:%d:SPR%dDATA %04X P=%06X D=%d A=%d PC=%x\n"),
5868 			vpos, hpos, num, v, spr[num].pt, spr[num].dmastate, spr[num].armed, M68K_GETPC);
5869 	}
5870 #endif
5871 }
5872 static void SPRxDATB_1(uae_u16 v, int num, int hpos)
5873 {
5874 	sprdatb[num][0] = v;
5875 #ifdef AGA
5876 	sprdatb[num][1] = v;
5877 	sprdatb[num][2] = v;
5878 	sprdatb[num][3] = v;
5879 #endif
5880 #if SPRITE_DEBUG >= 256
5881 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
5882 		write_log (_T("%d:%d:SPR%dDATB %04X P=%06X D=%d A=%d PC=%x\n"),
5883 			vpos, hpos, num, v, spr[num].pt, spr[num].dmastate, spr[num].armed, M68K_GETPC);
5884 	}
5885 #endif
5886 }
5887 
5888 /*
5889  SPRxDATA and SPRxDATB is moved to shift register when SPRxPOS matches.
5890 
5891  When copper writes to SPRxDATx exactly when SPRxPOS matches:
5892  - If sprite low x bit (SPRCTL bit 0) is not set, shift register copy
5893    is done first (previously loaded SPRxDATx value is shown) and then
5894    new SPRxDATx gets stored for future use.
5895  - If sprite low x bit is set, new SPRxDATx is stored, then SPRxPOS
5896    matches and value written to SPRxDATx is visible.
5897 
5898  - Writing to SPRxPOS when SPRxPOS matches: shift register
5899    copy is always done first, then new SPRxPOS value is stored
5900    for future use. (SPRxCTL not tested)
5901 */
5902 
5903 static void SPRxDATA (int hpos, uae_u16 v, int num)
5904 {
5905 	decide_sprites(hpos, true);
5906 	SPRxDATA_1(v, num, hpos);
5907 }
5908 static void SPRxDATB (int hpos, uae_u16 v, int num)
5909 {
5910 	decide_sprites(hpos, true);
5911 	SPRxDATB_1(v, num, hpos);
5912 }
5913 
5914 static void SPRxCTL (int hpos, uae_u16 v, int num)
5915 {
5916 #if SPRITE_DEBUG > 0
5917 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
5918 		write_log(_T("%d:%d:SPR%dCTLC %06X\n"), vpos, hpos, num, spr[num].pt);
5919 	}
5920 #endif
5921 
5922 	decide_sprites(hpos);
5923 	SPRxCTL_1(v, num, hpos);
5924 }
5925 static void SPRxPOS (int hpos, uae_u16 v, int num)
5926 {
5927 	struct sprite *s = &spr[num];
5928 	int oldvpos;
5929 #if SPRITE_DEBUG > 0
5930 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
5931 		write_log(_T("%d:%d:SPR%dPOSC %06X\n"), vpos, hpos, num, s->pt);
5932 	}
5933 #endif
5934 	decide_sprites(hpos);
5935 	oldvpos = s->vstart;
5936 	SPRxPOS_1(v, num, hpos);
5937 	// Superfrog flashing intro bees fix.
5938 	// if SPRxPOS is written one cycle before sprite's first DMA slot and sprite's vstart matches after
5939 	// SPRxPOS write, current line's DMA slot's stay idle. DMA decision seems to be done 4 cycles earlier.
5940 	if (hpos >= SPR0_HPOS + num * 4 - 4 && hpos <= SPR0_HPOS + num * 4 - 1 && oldvpos != vpos) {
5941 		s->ptxvpos2 = vpos;
5942 		s->ptxhpos2 = hpos + 4;
5943 	}
5944 }
5945 
5946 static void SPRxPTH (int hpos, uae_u16 v, int num)
5947 {
5948 	decide_sprites (hpos);
5949 	if (hpos - 1 != spr[num].ptxhpos) {
5950 		spr[num].pt &= 0xffff;
5951 		spr[num].pt |= (uae_u32)v << 16;
5952 	}
5953 #if SPRITE_DEBUG > 0
5954 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
5955 		write_log (_T("%d:%d:SPR%dPTH %06X\n"), vpos, hpos, num, spr[num].pt);
5956 	}
5957 #endif
5958 }
5959 static void SPRxPTL (int hpos, uae_u16 v, int num)
5960 {
5961 	decide_sprites (hpos);
5962 	if (hpos - 1 != spr[num].ptxhpos) {
5963 		spr[num].pt &= ~0xffff;
5964 		spr[num].pt |= v & ~1;
5965 	}
5966 #if SPRITE_DEBUG > 0
5967 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
5968 		write_log (_T("%d:%d:SPR%dPTL %06X\n"), vpos, hpos, num, spr[num].pt);
5969 	}
5970 #endif
5971 }
5972 
5973 static void CLXCON (uae_u16 v)
5974 {
5975 	clxcon = v;
5976 	clxcon_bpl_enable = (v >> 6) & 63;
5977 	clxcon_bpl_match = v & 63;
5978 }
5979 
5980 static void CLXCON2 (uae_u16 v)
5981 {
5982 	if (!(currprefs.chipset_mask & CSMASK_AGA))
5983 		return;
5984 	clxcon2 = v;
5985 	clxcon_bpl_enable |= v & (0x40 | 0x80);
5986 	clxcon_bpl_match |= (v & (0x01 | 0x02)) << 6;
5987 }
5988 
5989 static uae_u16 CLXDAT (void)
5990 {
5991 	uae_u16 v = clxdat | 0x8000;
5992 	clxdat = 0;
5993 	return v;
5994 }
5995 
5996 #ifdef AGA
5997 
5998 void dump_aga_custom (void)
5999 {
6000 	int c1, c2, c3, c4;
6001 	uae_u32 rgb1, rgb2, rgb3, rgb4;
6002 
6003 	for (c1 = 0; c1 < 64; c1++) {
6004 		c2 = c1 + 64;
6005 		c3 = c2 + 64;
6006 		c4 = c3 + 64;
6007 		rgb1 = current_colors.color_regs_aga[c1];
6008 		rgb2 = current_colors.color_regs_aga[c2];
6009 		rgb3 = current_colors.color_regs_aga[c3];
6010 		rgb4 = current_colors.color_regs_aga[c4];
6011 		console_out_f (_T("%3d %08X %3d %08X %3d %08X %3d %08X\n"),
6012 			c1, rgb1, c2, rgb2, c3, rgb3, c4, rgb4);
6013 	}
6014 }
6015 
6016 static uae_u16 COLOR_READ (int num)
6017 {
6018 	int cr, cg, cb, colreg;
6019 	uae_u16 cval;
6020 
6021 	if (!(currprefs.chipset_mask & CSMASK_AGA) || !(bplcon2 & 0x0100))
6022 		return 0xffff;
6023 
6024 	colreg = ((bplcon3 >> 13) & 7) * 32 + num;
6025 	cr = (current_colors.color_regs_aga[colreg] >> 16) & 0xFF;
6026 	cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
6027 	cb = current_colors.color_regs_aga[colreg] & 0xFF;
6028 	if (bplcon3 & 0x200) {
6029 		cval = ((cr & 15) << 8) | ((cg & 15) << 4) | ((cb & 15) << 0);
6030 	} else {
6031 		cval = ((cr >> 4) << 8) | ((cg >> 4) << 4) | ((cb >> 4) << 0);
6032 		if (color_regs_genlock[num])
6033 			cval |= 0x8000;
6034 	}
6035 	return cval;
6036 }
6037 #endif
6038 
6039 static void checkautoscalecol0 (void)
6040 {
6041 	if (!copper_access)
6042 		return;
6043 	if (vpos < 20)
6044 		return;
6045 	if (isbrdblank (-1, bplcon0, bplcon3))
6046 		return;
6047 	// autoscale if copper changes COLOR00 on top or bottom of screen
6048 	if (vpos >= minfirstline) {
6049 		int vpos2 = autoscale_bordercolors ? minfirstline : vpos;
6050 		if (first_planes_vpos == 0)
6051 			first_planes_vpos = vpos2 - 2;
6052 		if (plffirstline_total == current_maxvpos ())
6053 			plffirstline_total = vpos2 - 2;
6054 		if (vpos2 > last_planes_vpos || vpos2 > plflastline_total)
6055 			plflastline_total = last_planes_vpos = vpos2 + 3;
6056 		autoscale_bordercolors = 0;
6057 	} else {
6058 		autoscale_bordercolors++;
6059 	}
6060 }
6061 
6062 static void COLOR_WRITE (int hpos, uae_u16 v, int num)
6063 {
6064 	bool colzero = false;
6065 #ifdef AGA
6066 	if (currprefs.chipset_mask & CSMASK_AGA) {
6067 		int r,g,b;
6068 		int cr,cg,cb;
6069 		int colreg;
6070 		uae_u32 cval;
6071 
6072 		/* writing is disabled when RDRAM=1 */
6073 		if (bplcon2 & 0x0100)
6074 			return;
6075 
6076 		colreg = ((bplcon3 >> 13) & 7) * 32 + num;
6077 		r = (v & 0xF00) >> 8;
6078 		g = (v & 0xF0) >> 4;
6079 		b = (v & 0xF) >> 0;
6080 		cr = (current_colors.color_regs_aga[colreg] >> 16) & 0xFF;
6081 		cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
6082 		cb = current_colors.color_regs_aga[colreg] & 0xFF;
6083 
6084 		if (bplcon3 & 0x200) {
6085 			cr &= 0xF0; cr |= r;
6086 			cg &= 0xF0; cg |= g;
6087 			cb &= 0xF0; cb |= b;
6088 		} else {
6089 			cr = r + (r << 4);
6090 			cg = g + (g << 4);
6091 			cb = b + (b << 4);
6092 			color_regs_genlock[colreg] = v >> 15;
6093 		}
6094 		cval = (cr << 16) | (cg << 8) | cb | (color_regs_genlock[colreg] ? 0x80000000 : 0);
6095 		if (cval && colreg == 0)
6096 			colzero = true;
6097 
6098 		if (cval == current_colors.color_regs_aga[colreg])
6099 			return;
6100 
6101 		if (colreg == 0)
6102 			checkautoscalecol0 ();
6103 
6104 		/* Call this with the old table still intact. */
6105 		record_color_change (hpos, colreg, cval);
6106 		remembered_color_entry = -1;
6107 		current_colors.color_regs_aga[colreg] = cval;
6108 		current_colors.acolors[colreg] = getxcolor (cval);
6109 
6110 	} else {
6111 #endif
6112 		v &= 0x8fff;
6113 		if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE))
6114 			v &= 0xfff;
6115 		color_regs_genlock[num] = v >> 15;
6116 		if (num && v == 0)
6117 			colzero = true;
6118 		if (current_colors.color_regs_ecs[num] == v)
6119 			return;
6120 		if (num == 0)
6121 			checkautoscalecol0 ();
6122 
6123 		/* Call this with the old table still intact. */
6124 		record_color_change (hpos, num, v);
6125 		remembered_color_entry = -1;
6126 		current_colors.color_regs_ecs[num] = v;
6127 		current_colors.acolors[num] = getxcolor (v);
6128 #ifdef AGA
6129 	}
6130 #endif
6131 }
6132 
6133 /* The copper code.  The biggest nightmare in the whole emulator.
6134 
6135 Alright.  The current theory:
6136 1. Copper moves happen 2 cycles after state READ2 is reached.
6137 It can't happen immediately when we reach READ2, because the
6138 data needs time to get back from the bus.  An additional 2
6139 cycles are needed for non-Agnus registers, to take into account
6140 the delay for moving data from chip to chip.
6141 2. As stated in the HRM, a WAIT really does need an extra cycle
6142 to wake up.  This is implemented by _not_ falling through from
6143 a successful wait to READ1, but by starting the next cycle.
6144 (Note: the extra cycle for the WAIT apparently really needs a
6145 free cycle; i.e. contention with the bitplane fetch can slow
6146 it down).
6147 3. Apparently, to compensate for the extra wake up cycle, a WAIT
6148 will use the _incremented_ horizontal position, so the WAIT
6149 cycle normally finishes two clocks earlier than the position
6150 it was waiting for.  The extra cycle then takes us to the
6151 position that was waited for.
6152 If the earlier cycle is busy with a bitplane, things change a bit.
6153 E.g., waiting for position 0x50 in a 6 plane display: In cycle
6154 0x4e, we fetch BPL5, so the wait wakes up in 0x50, the extra cycle
6155 takes us to 0x54 (since 0x52 is busy), then we have READ1/READ2,
6156 and the next register write is at 0x5c.
6157 4. The last cycle in a line is not usable for the copper.
6158 5. A 4 cycle delay also applies to the WAIT instruction.  This means
6159 that the second of two back-to-back WAITs (or a WAIT whose
6160 condition is immediately true) takes 8 cycles.
6161 6. This also applies to a SKIP instruction.  The copper does not
6162 fetch the next instruction while waiting for the second word of
6163 a WAIT or a SKIP to arrive.
6164 7. A SKIP also seems to need an unexplained additional two cycles
6165 after its second word arrives; this is _not_ a memory cycle (I
6166 think, the documentation is pretty clear on this).
6167 8. Two additional cycles are inserted when writing to COPJMP1/2.  */
6168 
6169 /* Determine which cycles are available for the copper in a display
6170 * with a agiven number of planes.  */
6171 
6172 STATIC_INLINE int copper_cant_read2 (int hpos, int alloc)
6173 {
6174 	if (hpos + 1 >= maxhpos) // first refresh slot
6175 		return 1;
6176 	if ((hpos == maxhpos - 3) && (maxhpos & 1) && alloc >= 0) {
6177 		if (alloc) {
6178 			alloc_cycle (hpos, CYCLE_COPPER);
6179 #ifdef DEBUGGER
6180 			if (debug_dma)
6181 				record_dma_event (DMA_EVENT_COPPERWANTED, hpos, vpos);
6182 #endif
6183 		}
6184 		return -1;
6185 	}
6186 	return is_bitplane_dma_inline (hpos);
6187 }
6188 
6189 static int copper_cant_read (int hpos, int alloc)
6190 {
6191 	int cant = copper_cant_read2 (hpos, alloc);
6192 #ifdef DEBUGGER
6193 	if (cant && debug_dma && alloc)
6194 		record_dma_event (DMA_EVENT_COPPERWANTED, hpos, vpos);
6195 #endif
6196 	return cant;
6197 }
6198 
6199 static int custom_wput_copper (int hpos, uaecptr addr, uae_u32 value, int noget)
6200 {
6201 	int v;
6202 
6203 	value = debug_wputpeekdma_chipset (0xdff000 + addr, value, MW_MASK_COPPER, 0x08c);
6204 	copper_access = 1;
6205 	v = custom_wput_1 (hpos, addr, value, noget);
6206 	copper_access = 0;
6207 	return v;
6208 }
6209 
6210 static void dump_copper (const TCHAR *error, int until_hpos)
6211 {
6212 	write_log (_T("\n"));
6213 	write_log (_T("%s: vpos=%d until_hpos=%d vp=%d\n"),
6214 		error, vpos, until_hpos, vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80));
6215 	write_log (_T("cvcmp=%d chcmp=%d chpos=%d cvpos=%d ci1=%04X ci2=%04X\n"),
6216 		cop_state.vcmp, cop_state.hcmp, cop_state.hpos, cop_state.vpos, cop_state.saved_i1, cop_state.saved_i2);
6217 	write_log (_T("cstate=%d ip=%x SPCFLAGS=%x iscline=%d\n"),
6218 		cop_state.state, cop_state.ip, regs.spcflags, copper_enabled_thisline);
6219 	write_log (_T("\n"));
6220 }
6221 
6222 // "emulate" chip internal delays, not the right place but fast and 99.9% programs
6223 // use only copper to write BPLCON1 etc.. (exception is HulkaMania/TSP..)
6224 // this table should be filled with zeros and done somewhere else..
6225 static int customdelay[]= {
6226 	1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 32 0x00 - 0x3e */
6227 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x40 - 0x5e */
6228 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x60 - 0x7e */
6229 	0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0, /* 0x80 - 0x9e */
6230 	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 32 0xa0 - 0xde */
6231 	/* BPLxPTH/BPLxPTL */
6232 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 16 */
6233 	/* BPLCON0-3,BPLMOD1-2 */
6234 	0,0,0,0,0,0,0,0, /* 8 */
6235 	/* BPLxDAT */
6236 	0,0,0,0,0,0,0,0, /* 8 */
6237 	/* SPRxPTH/SPRxPTL */
6238 	1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */
6239 	/* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */
6240 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6241 	/* COLORxx */
6242 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
6243 	/* RESERVED */
6244 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
6245 };
6246 
6247 static void copper_write (uae_u32 v)
6248 {
6249 	custom_wput_copper (current_hpos (), v >> 16, v & 0xffff, 0);
6250 }
6251 
6252 static void update_copper (int until_hpos)
6253 {
6254 	int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
6255 	int c_hpos = cop_state.hpos;
6256 
6257 	if (nocustom ())
6258 		return;
6259 
6260 	if (cop_state.state == COP_wait && vp < cop_state.vcmp) {
6261 		dump_copper (_T("error2"), until_hpos);
6262 		copper_enabled_thisline = 0;
6263 		cop_state.state = COP_stop;
6264 		unset_special (SPCFLAG_COPPER);
6265 		return;
6266 	}
6267 
6268 	if (until_hpos <= last_copper_hpos)
6269 		return;
6270 
6271 	if (until_hpos > (maxhpos & ~1))
6272 		until_hpos = maxhpos & ~1;
6273 
6274 	for (;;) {
6275 		int old_hpos = c_hpos;
6276 		int hp;
6277 
6278 		if (c_hpos >= until_hpos)
6279 			break;
6280 
6281 
6282 		/* So we know about the fetch state.  */
6283 		decide_line (c_hpos);
6284 		// bitplane only, don't want blitter to steal our cycles.
6285 		decide_fetch (c_hpos);
6286 
6287 		if (cop_state.movedelay > 0) {
6288 			cop_state.movedelay--;
6289 			if (cop_state.movedelay == 0) {
6290 				custom_wput_copper (c_hpos, cop_state.moveaddr, cop_state.movedata, 0);
6291 			}
6292 		}
6293 
6294 		if ((c_hpos == maxhpos - 3) && (maxhpos & 1))
6295 			c_hpos += 1;
6296 		else
6297 			c_hpos += 2;
6298 
6299 		switch (cop_state.state)
6300 		{
6301 		case COP_wait_in2:
6302 			if (copper_cant_read (old_hpos, 0))
6303 				continue;
6304 			cop_state.state = COP_wait1;
6305 			break;
6306 		case COP_skip_in2:
6307 			if (copper_cant_read (old_hpos, 0))
6308 				continue;
6309 			cop_state.state = COP_skip1;
6310 			break;
6311 
6312 		case COP_strobe_extra:
6313 			// Wait 1 copper cycle doing nothing
6314 			cop_state.state = COP_strobe_delay1;
6315 			break;
6316 		case COP_strobe_delay1:
6317 			// First cycle after COPJMP is just like normal first read cycle
6318 			// Cycle is used and needs to be free.
6319 			if (copper_cant_read (old_hpos, 1))
6320 				continue;
6321 			alloc_cycle (old_hpos, CYCLE_COPPER);
6322 #ifdef DEBUGGER
6323 			if (debug_dma)
6324 				record_dma (0x8c, chipmem_wget_indirect (cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
6325 			if (memwatch_enabled)
6326 				debug_wgetpeekdma_chipram(cop_state.ip, chipmem_wget_indirect (cop_state.ip), MW_MASK_COPPER, 0x8c);
6327 #endif
6328 			if (old_hpos == maxhpos - 2) {
6329 				// if COP_strobe_delay2 would cross scanlines (positioned immediately
6330 				// after first strobe/refresh slot) it will disappear!
6331 				cop_state.state = COP_read1;
6332 				if (cop_state.strobe == 1)
6333 					cop_state.ip = cop1lc;
6334 				else
6335 					cop_state.ip = cop2lc;
6336 				cop_state.strobe = 0;
6337 			} else {
6338 				cop_state.state = COP_strobe_delay2;
6339 				cop_state.ip += 2;
6340 			}
6341 			break;
6342 		case COP_strobe_delay2:
6343 			// Second cycle after COPJMP. This is the strange one.
6344 			// This cycle does not need to be free
6345 			// But it still gets allocated by copper if it is free = CPU and blitter can't use it.
6346 			if (!copper_cant_read (old_hpos, 0)) {
6347 				alloc_cycle (old_hpos, CYCLE_COPPER);
6348 #ifdef DEBUGGER
6349 				if (debug_dma)
6350 					record_dma (0x1fe, chipmem_wget_indirect (cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
6351 				if (memwatch_enabled)
6352 					debug_wgetpeekdma_chipram(cop_state.ip, chipmem_wget_indirect (cop_state.ip), MW_MASK_COPPER, 0x1fe);
6353 #endif
6354 			}
6355 			cop_state.state = COP_read1;
6356 			// Next cycle finally reads from new pointer
6357 			if (cop_state.strobe == 1)
6358 				cop_state.ip = cop1lc;
6359 			else
6360 				cop_state.ip = cop2lc;
6361 			cop_state.strobe = 0;
6362 			break;
6363 
6364 		case COP_strobe_delay1x:
6365 			// First cycle after COPJMP and Copper was waiting. This is the buggy one.
6366 			// Cycle can be free and copper won't allocate it.
6367 			// If Blitter uses this cycle = Copper's PC gets copied to blitter DMA pointer..
6368 			cop_state.state = COP_strobe_delay2x;
6369 			break;
6370 		case COP_strobe_delay2x:
6371 			// Second cycle fetches following word and tosses it away. Must be free cycle
6372 			// but it is not allocated, blitter or cpu can still use it.
6373 			if (copper_cant_read (old_hpos, 1))
6374 				continue;
6375 			cycle_line[old_hpos] |= CYCLE_COPPER_SPECIAL;
6376 #ifdef DEBUGGER
6377 			if (debug_dma)
6378 				record_dma (0x1fe, chipmem_wget_indirect (cop_state.ip), cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
6379 			if (memwatch_enabled)
6380 				debug_wgetpeekdma_chipram(cop_state.ip, chipmem_wget_indirect (cop_state.ip), MW_MASK_COPPER, 0x1fe);
6381 #endif
6382 			cop_state.state = COP_read1;
6383 			// Next cycle finally reads from new pointer
6384 			if (cop_state.strobe == 1)
6385 				cop_state.ip = cop1lc;
6386 			else
6387 				cop_state.ip = cop2lc;
6388 			cop_state.strobe = 0;
6389 		break;
6390 
6391 
6392 		case COP_start_delay:
6393 			// cycle after vblank strobe fetches word from old pointer first
6394 			if (copper_cant_read (old_hpos, 1))
6395 				continue;
6396 			cop_state.state = COP_read1;
6397 			cop_state.i1 = last_custom_value1 = chipmem_wget_indirect (cop_state.ip);
6398 			alloc_cycle (old_hpos, CYCLE_COPPER);
6399 #ifdef DEBUGGER
6400 			if (debug_dma)
6401 				record_dma (0x1fe, cop_state.i1, cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
6402 			if (memwatch_enabled)
6403 				debug_wgetpeekdma_chipram(cop_state.ip, cop_state.i1, MW_MASK_COPPER, 0x1fe);
6404 #endif
6405 			cop_state.ip = cop1lc;
6406 			break;
6407 
6408 		case COP_read1:
6409 			if (copper_cant_read (old_hpos, 1))
6410 				continue;
6411 			cop_state.i1 = last_custom_value1 = chipmem_wget_indirect (cop_state.ip);
6412 			alloc_cycle (old_hpos, CYCLE_COPPER);
6413 #ifdef DEBUGGER
6414 			if (debug_dma)
6415 				record_dma (0x8c, cop_state.i1, cop_state.ip, old_hpos, vpos, DMARECORD_COPPER);
6416 			if (memwatch_enabled)
6417 				debug_wgetpeekdma_chipram(cop_state.ip, cop_state.i1, MW_MASK_COPPER, 0x8c);
6418 #endif
6419 			cop_state.ip += 2;
6420 			cop_state.state = COP_read2;
6421 			break;
6422 
6423 		case COP_read2:
6424 			if (copper_cant_read (old_hpos, 1))
6425 				continue;
6426 			cop_state.i2 = last_custom_value1 = chipmem_wget_indirect (cop_state.ip);
6427 			alloc_cycle (old_hpos, CYCLE_COPPER);
6428 			cop_state.ip += 2;
6429 			cop_state.saved_i1 = cop_state.i1;
6430 			cop_state.saved_i2 = cop_state.i2;
6431 			cop_state.saved_ip = cop_state.ip;
6432 
6433 			if (cop_state.i1 & 1) { // WAIT or SKIP
6434 				cop_state.ignore_next = 0;
6435 				if (cop_state.i2 & 1)
6436 					cop_state.state = COP_skip_in2;
6437 				else
6438 					cop_state.state = COP_wait_in2;
6439 #ifdef DEBUGGER
6440 				if (debug_dma)
6441 					record_dma (0x8c, cop_state.i2, cop_state.ip - 2, old_hpos, vpos, DMARECORD_COPPER);
6442 				if (memwatch_enabled)
6443 					debug_wgetpeekdma_chipram(cop_state.ip - 2, cop_state.i2, MW_MASK_COPPER, 0x8c);
6444 #endif
6445 			} else { // MOVE
6446 #ifdef DEBUGGER
6447 				uaecptr debugip = cop_state.ip;
6448 #endif
6449 				unsigned int reg = cop_state.i1 & 0x1FE;
6450 				uae_u16 data = cop_state.i2;
6451 				cop_state.state = COP_read1;
6452 #ifdef DEBUGGER
6453 				if (debug_dma)
6454 					record_dma (reg, data, cop_state.ip - 2, old_hpos, vpos, DMARECORD_COPPER);
6455 				if (memwatch_enabled)
6456 					debug_wgetpeekdma_chipram(cop_state.ip - 2, data, MW_MASK_COPPER, reg);
6457 #endif
6458 				test_copper_dangerous (reg);
6459 				if (! copper_enabled_thisline)
6460 					goto out; // was "dangerous" register -> copper stopped
6461 
6462 				if (cop_state.ignore_next)
6463 					reg = 0x1fe;
6464 
6465 				if (reg == 0x88) {
6466 					cop_state.strobe = 1;
6467 					cop_state.state = COP_strobe_delay1;
6468 				} else if (reg == 0x8a) {
6469 					cop_state.strobe = 2;
6470 					cop_state.state = COP_strobe_delay1;
6471 				} else {
6472 #if 0
6473 					event2_newevent2 (1, (reg << 16) | data, copper_write);
6474 #else
6475 					// FIX: all copper writes happen 1 cycle later than CPU writes
6476 					if (customdelay[reg / 2]) {
6477 						cop_state.moveaddr = reg;
6478 						cop_state.movedata = data;
6479 						cop_state.movedelay = customdelay[cop_state.moveaddr / 2];
6480 					} else {
6481 						custom_wput_copper (old_hpos, reg, data, 0);
6482 					}
6483 #endif
6484 				}
6485 #ifdef DEBUGGER
6486 				if (debug_copper && !cop_state.ignore_next)
6487 					record_copper (debugip - 4, cop_state.saved_i1, cop_state.saved_i2, old_hpos, vpos);
6488 #endif
6489 				cop_state.ignore_next = 0;
6490 			}
6491 			check_copper_stop();
6492 			break;
6493 
6494 		case COP_wait1:
6495 #if 0
6496 			/* There's a nasty case here.  As stated in the "Theory" comment above, we
6497 			test against the incremented copper position.  I believe this means that
6498 			we have to increment the _vertical_ position at the last cycle in the line,
6499 			and set the horizontal position to 0.
6500 			Normally, this isn't going to make a difference, since we consider these
6501 			last cycles unavailable for the copper, so waking up in the last cycle has
6502 			the same effect as waking up at the start of the line.  However, there is
6503 			one possible problem:  If we're at 0xFFE0, any wait for an earlier position
6504 			must _not_ complete (since, in effect, the current position will be back
6505 			at 0/0).  This can be seen in the Superfrog copper list.
6506 			Things get monstrously complicated if we try to handle this "properly" by
6507 			incrementing vpos and setting c_hpos to 0.  Especially the various speedup
6508 			hacks really assume that vpos remains constant during one line.  Hence,
6509 			this hack: defer the entire decision until the next line if necessary.  */
6510 #endif
6511 #if 0
6512 			/* Above is not true anymore */
6513 			if (c_hpos >= (maxhpos & ~1) || (c_hpos & 1)) {
6514 				break;
6515 			}
6516 #endif
6517 			cop_state.state = COP_wait;
6518 
6519 			cop_state.vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
6520 			cop_state.hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
6521 
6522 			vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
6523 
6524 			if (cop_state.saved_i1 == 0xFFFF && cop_state.saved_i2 == 0xFFFE) {
6525 				cop_state.state = COP_waitforever;
6526 				copper_enabled_thisline = 0;
6527 				unset_special (SPCFLAG_COPPER);
6528 				goto out;
6529 			}
6530 			if (vp < cop_state.vcmp) {
6531 				copper_enabled_thisline = 0;
6532 				unset_special (SPCFLAG_COPPER);
6533 				goto out;
6534 			}
6535 
6536 			/* fall through */
6537 		case COP_wait:
6538 			{
6539 				int ch_comp = c_hpos;
6540 				if (ch_comp & 1)
6541 					ch_comp = 0;
6542 
6543 				/* First handle possible blitter wait
6544 				 * Must be before following free cycle check
6545 				 */
6546 				if ((cop_state.saved_i2 & 0x8000) == 0) {
6547 					decide_blitter(old_hpos);
6548 					if (bltstate != BLT_done) {
6549 						/* We need to wait for the blitter.  */
6550 						cop_state.state = COP_bltwait;
6551 						copper_enabled_thisline = 0;
6552 						unset_special(SPCFLAG_COPPER);
6553 						goto out;
6554 					}
6555 				}
6556 
6557 				if (copper_cant_read(old_hpos, 0))
6558 					continue;
6559 
6560 				hp = ch_comp & (cop_state.saved_i2 & 0xFE);
6561 				if (vp == cop_state.vcmp && hp < cop_state.hcmp)
6562 					break;
6563 
6564 #ifdef DEBUGGER
6565 				if (debug_dma)
6566 					record_dma_event (DMA_EVENT_COPPERWAKE, old_hpos, vp);
6567 				if (debug_copper)
6568 					record_copper (cop_state.ip - 4, cop_state.saved_i1, cop_state.saved_i2, old_hpos, vpos);
6569 #endif
6570 
6571 				cop_state.state = COP_read1;
6572 			}
6573 			break;
6574 
6575 		case COP_skip1:
6576 			{
6577 				unsigned int vcmp, hcmp, vp1, hp1;
6578 
6579 				if (c_hpos >= (maxhpos & ~1) || (c_hpos & 1))
6580 					break;
6581 
6582 				if (copper_cant_read (old_hpos, 0))
6583 					continue;
6584 
6585 				vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
6586 				hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
6587 				vp1 = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
6588 				hp1 = c_hpos & (cop_state.saved_i2 & 0xFE);
6589 
6590 				if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp)) && ((cop_state.saved_i2 & 0x8000) != 0 || bltstate == BLT_done))
6591 					cop_state.ignore_next = 1;
6592 
6593 				cop_state.state = COP_read1;
6594 
6595 #ifdef DEBUGGER
6596 				if (debug_copper)
6597 					record_copper (cop_state.ip - 4, cop_state.saved_i1, cop_state.saved_i2, old_hpos, vpos);
6598 #endif
6599 
6600 				break;
6601 			}
6602 		default:
6603 			break;
6604 		}
6605 	}
6606 
6607 out:
6608 	cop_state.hpos = c_hpos;
6609 	last_copper_hpos = until_hpos;
6610 }
6611 
6612 static void compute_spcflag_copper (int hpos)
6613 {
6614 	int wasenabled = copper_enabled_thisline;
6615 
6616 	copper_enabled_thisline = 0;
6617 	unset_special (SPCFLAG_COPPER);
6618 	if (!dmaen (DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_waitforever || cop_state.state == COP_bltwait || nocustom ())
6619 		return;
6620 
6621 	if (cop_state.state == COP_wait) {
6622 		int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
6623 
6624 		if (vp < cop_state.vcmp)
6625 			return;
6626 	}
6627 	// do not use past cycles if starting for the first time in this line
6628 	// (write to DMACON for example) hpos+1 for long lines
6629 	if (!wasenabled && cop_state.hpos < hpos && hpos < maxhpos) {
6630 		hpos = (hpos + 2) & ~1;
6631 		if (hpos > (maxhpos_short & ~1))
6632 			hpos = maxhpos_short & ~1;
6633 		cop_state.hpos = hpos;
6634 	}
6635 
6636 	// if COPJMPx was written while DMA was disabled, advance to next state,
6637 	// COP_strobe_extra is single cycle only and does not need free bus.
6638 	// (copper state emulation does not run if DMA is disabled)
6639 	if (!wasenabled && cop_state.state == COP_strobe_extra)
6640 		cop_state.state = COP_strobe_delay1;
6641 
6642 	copper_enabled_thisline = 1;
6643 	set_special (SPCFLAG_COPPER);
6644 }
6645 
6646 void blitter_done_notify (int hpos)
6647 {
6648 	if (cop_state.state != COP_bltwait)
6649 		return;
6650 
6651 	int vp_wait = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
6652 	int vp = vpos;
6653 
6654 	hpos++;
6655 	hpos &= ~1;
6656 	if (hpos >= maxhpos) {
6657 		hpos -= maxhpos;
6658 		vp++;
6659 	}
6660 	cop_state.hpos = hpos;
6661 	cop_state.vpos = vp;
6662 	cop_state.state = COP_wait;
6663 	/* No need to check blitter state again */
6664 	cop_state.saved_i2 |= 0x8000;
6665 
6666 #ifdef DEBUGGER
6667 	if (debug_dma)
6668 		record_dma_event(DMA_EVENT_COPPERWAKE, hpos, vp);
6669 	if (debug_copper)
6670 		record_copper_blitwait(cop_state.ip - 4, hpos, vp);
6671 #endif
6672 
6673 	if (dmaen(DMA_COPPER) && vp_wait >= cop_state.vcmp) {
6674 		copper_enabled_thisline = 1;
6675 		set_special(SPCFLAG_COPPER);
6676 	} else {
6677 		unset_special (SPCFLAG_COPPER);
6678 	}
6679 }
6680 
6681 void do_copper (void)
6682 {
6683 	int hpos = current_hpos ();
6684 	update_copper (hpos);
6685 }
6686 
6687 /* ADDR is the address that is going to be read/written; this access is
6688 the reason why we want to update the copper.  This function is also
6689 used from hsync_handler to finish up the line; for this case, we check
6690 hpos against maxhpos.  */
6691 STATIC_INLINE void sync_copper_with_cpu (int hpos, int do_schedule)
6692 {
6693 	/* Need to let the copper advance to the current position.  */
6694 	if (copper_enabled_thisline)
6695 		update_copper (hpos);
6696 }
6697 
6698 static void cursorsprite (void)
6699 {
6700 	if (!dmaen (DMA_SPRITE) || first_planes_vpos == 0)
6701 		return;
6702 	sprite_0 = spr[0].pt;
6703 	sprite_0_height = spr[0].vstop - spr[0].vstart;
6704 	sprite_0_colors[0] = 0;
6705 	sprite_0_doubled = 0;
6706 	if (sprres == 0)
6707 		sprite_0_doubled = 1;
6708 	if (0) {
6709 #ifdef AGA
6710 	} else if (currprefs.chipset_mask & CSMASK_AGA) {
6711 		int sbasecol = ((bplcon4 >> 4) & 15) << 4;
6712 		sprite_0_colors[1] = current_colors.color_regs_aga[sbasecol + 1];
6713 		sprite_0_colors[2] = current_colors.color_regs_aga[sbasecol + 2];
6714 		sprite_0_colors[3] = current_colors.color_regs_aga[sbasecol + 3];
6715 #endif
6716 	} else {
6717 		sprite_0_colors[1] = xcolors[current_colors.color_regs_ecs[17]];
6718 		sprite_0_colors[2] = xcolors[current_colors.color_regs_ecs[18]];
6719 		sprite_0_colors[3] = xcolors[current_colors.color_regs_ecs[19]];
6720 	}
6721 	sprite_0_width = sprite_width;
6722 	if (currprefs.input_tablet && currprefs.input_magic_mouse) {
6723 		if (currprefs.input_magic_mouse_cursor == MAGICMOUSE_HOST_ONLY && mousehack_alive ())
6724 			magic_sprite_mask &= ~1;
6725 		else
6726 			magic_sprite_mask |= 1;
6727 	}
6728 }
6729 
6730 static uae_u16 sprite_fetch(struct sprite *s, int dma, int hpos, int cycle, int mode)
6731 {
6732 	uae_u16 data = last_custom_value1;
6733 	if (dma) {
6734 		if (cycle && currprefs.cpu_cycle_exact)
6735 			s->ptxhpos = hpos;
6736 		data = last_custom_value1 = chipmem_wget_indirect (s->pt);
6737 		alloc_cycle (hpos, CYCLE_SPRITE);
6738 #ifdef DEBUGGER
6739 		if (debug_dma)
6740 			record_dma ((s - &spr[0]) * 8 + 0x140 + mode * 4 + cycle * 2, data, s->pt, hpos, vpos, DMARECORD_SPRITE);
6741 		if (memwatch_enabled)
6742 			debug_wgetpeekdma_chipram(s->pt, data, MW_MASK_SPR_0 << (s - &spr[0]), (s - &spr[0]) * 8 + 0x140 + mode * 4 + cycle * 2);
6743 #endif
6744 	}
6745 	s->pt += 2;
6746 	return data;
6747 }
6748 static uae_u16 sprite_fetch2(struct sprite *s, int hpos, int cycle, int mode)
6749 {
6750 	uae_u16 data = chipmem_wget_indirect (s->pt);
6751 	s->pt += 2;
6752 	return data;
6753 }
6754 
6755 static void do_sprites_1(int num, int cycle, int hpos)
6756 {
6757 	struct sprite *s = &spr[num];
6758 	int dma, posctl = 0;
6759 	uae_u16 data;
6760 	// fetch both sprite pairs even if DMA was switched off between sprites
6761 	int isdma = dmaen (DMA_SPRITE) || ((num & 1) && spr[num & ~1].dmacycle);
6762 
6763 	if (cant_this_last_line())
6764 		return;
6765 
6766 //	see SPRxCTRL below
6767 //	if (isdma && vpos == sprite_vblank_endline)
6768 //		spr_arm (num, 0);
6769 
6770 #ifdef AGA
6771 	if (isdma && s->dblscan && (fmode & 0x8000) && (vpos & 1) != (s->vstart & 1) && s->dmastate) {
6772 		spr_arm (num, 1);
6773 		return;
6774 	}
6775 #endif
6776 #if SPRITE_DEBUG >= 3 * 256
6777 	if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num)))
6778 		write_log (_T("%d:%d:slot%d:%d\n"), vpos, hpos, num, cycle);
6779 #endif
6780 	if (vpos == s->vstart) {
6781 #if SPRITE_DEBUG > 0
6782 		if (!s->dmastate && vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num)))
6783 			write_log (_T("%d:%d:SPR%d START\n"), vpos, hpos, num);
6784 #endif
6785 		s->dmastate = 1;
6786 		if (s->ptxvpos2 == vpos && hpos < s->ptxhpos2)
6787 			return;
6788 		if (num == 0 && cycle == 0)
6789 			cursorsprite ();
6790 	}
6791 	if (vpos == s->vstop || vpos == sprite_vblank_endline) {
6792 #if SPRITE_DEBUG > 0
6793 		if (s->dmastate && vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num)))
6794 			write_log (_T("%d:%d:SPR%d STOP\n"), vpos, hpos, num);
6795 #endif
6796 		s->dmastate = 0;
6797 	}
6798 
6799 	if (!isdma)
6800 		return;
6801 
6802 	dma = hpos < plfstrt_sprite || diwstate != DIW_waiting_stop;
6803 	if (vpos == s->vstop || vpos == sprite_vblank_endline) {
6804 		s->dmastate = 0;
6805 		posctl = 1;
6806 		if (dma) {
6807 			data = sprite_fetch (s, dma, hpos, cycle, 0);
6808 			switch (sprite_width)
6809 			{
6810 			case 64:
6811 				sprite_fetch2 (s, hpos, cycle, 0);
6812 				sprite_fetch2 (s, hpos, cycle, 0);
6813 			case 32:
6814 				sprite_fetch2 (s, hpos, cycle, 0);
6815 				break;
6816 			}
6817 			//write_log (_T("%d:%d: %04X=%04X\n"), vpos, hpos, 0x140 + cycle * 2 + num * 8, data);
6818 			if (cycle == 0) {
6819 				SPRxPOS_1 (data, num, hpos);
6820 				s->dmacycle = 1;
6821 			} else {
6822 				// This is needed to disarm previous field's sprite.
6823 				// It can be seen on OCS Agnus + ECS Denise combination where
6824 				// this cycle is disabled due to weird DDFTSTR=$18 copper list
6825 				// which causes corrupted sprite to "wrap around" the display.
6826 				SPRxCTL_1 (data, num, hpos);
6827 				s->dmastate = 0;
6828 				sprstartstop (s);
6829 			}
6830 		}
6831 		if (vpos == sprite_vblank_endline) {
6832 			// s->vstart == sprite_vblank_endline won't enable the sprite.
6833 			s->dmastate = 0;
6834 		}
6835 #if SPRITE_DEBUG >= 256
6836 		if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
6837 			write_log (_T("%d:%d:dma:P=%06X "), vpos, hpos, s->pt);
6838 		}
6839 #endif
6840 	}
6841 	if (s->dmastate && !posctl && dma) {
6842 		uae_u16 data;
6843 
6844 		data = sprite_fetch (s, dma, hpos, cycle, 1);
6845 #if SPRITE_DEBUG >= 256
6846 		if (vpos >= SPRITE_DEBUG_MINY && vpos <= SPRITE_DEBUG_MAXY && (SPRITE_DEBUG & (1 << num))) {
6847 			write_log (_T("%d:%d:dma:P=%06X "), vpos, hpos, s->pt);
6848 		}
6849 #endif
6850 		if (cycle == 0) {
6851 			SPRxDATA_1 (data, num, hpos);
6852 			s->dmacycle = 1;
6853 		} else {
6854 			SPRxDATB_1 (data, num, hpos);
6855 			spr_arm (num, 1);
6856 		}
6857 #ifdef AGA
6858 		switch (sprite_width)
6859 		{
6860 		case 64:
6861 			{
6862 				uae_u16 data32 = sprite_fetch2 (s, hpos, cycle, 1);
6863 				uae_u16 data641 = sprite_fetch2 (s, hpos, cycle, 1);
6864 				uae_u16 data642 = sprite_fetch2 (s, hpos, cycle, 1);
6865 				if (dma) {
6866 					if (cycle == 0) {
6867 						sprdata[num][3] = data642;
6868 						sprdata[num][2] = data641;
6869 						sprdata[num][1] = data32;
6870 					} else {
6871 						sprdatb[num][3] = data642;
6872 						sprdatb[num][2] = data641;
6873 						sprdatb[num][1] = data32;
6874 					}
6875 				}
6876 			}
6877 			break;
6878 		case 32:
6879 			{
6880 				uae_u16 data32 = sprite_fetch2 (s, hpos, cycle, 1);
6881 				if (dma) {
6882 					if (cycle == 0)
6883 						sprdata[num][1] = data32;
6884 					else
6885 						sprdatb[num][1] = data32;
6886 				}
6887 			}
6888 			break;
6889 		}
6890 #endif
6891 	}
6892 }
6893 
6894 static void do_sprites (int hpos)
6895 {
6896 	int maxspr, minspr;
6897 	int i;
6898 
6899 	if (vpos < sprite_vblank_endline)
6900 		return;
6901 
6902 	if (doflickerfix () && interlace_seen && (next_lineno & 1))
6903 		return;
6904 
6905 	maxspr = hpos;
6906 	minspr = last_sprite_hpos + 1;
6907 
6908 	if (minspr >= maxspr || last_sprite_hpos == hpos)
6909 		return;
6910 
6911 	if (maxspr >= SPR0_HPOS + MAX_SPRITES * 4)
6912 		maxspr = SPR0_HPOS + MAX_SPRITES * 4 - 1;
6913 	if (minspr < SPR0_HPOS)
6914 		minspr = SPR0_HPOS;
6915 
6916 	if (minspr == maxspr)
6917 		return;
6918 
6919 	for (i = minspr; i <= maxspr; i++) {
6920 		int cycle = -1;
6921 		int num = (i - SPR0_HPOS) / 4;
6922 		switch ((i - SPR0_HPOS) & 3)
6923 		{
6924 		case 0:
6925 			cycle = 0;
6926 			spr[num].dmacycle = 0;
6927 			break;
6928 		case 2:
6929 			cycle = 1;
6930 			break;
6931 		}
6932 		if (cycle >= 0) {
6933 			spr[num].ptxhpos = MAXHPOS;
6934 			do_sprites_1 (num, cycle, i);
6935 		}
6936 	}
6937 
6938 	last_sprite_hpos = hpos;
6939 }
6940 
6941 static void init_sprites (void)
6942 {
6943 	memset (sprpos, 0, sizeof sprpos);
6944 	memset (sprctl, 0, sizeof sprctl);
6945 }
6946 
6947 static void init_hardware_frame (void)
6948 {
6949 	int i;
6950 
6951 	first_bpl_vpos = -1;
6952 	next_lineno = 0;
6953 	prev_lineno = -1;
6954 	nextline_how = nln_normal;
6955 	diwstate = DIW_waiting_start;
6956 	ddfstate = DIW_waiting_start;
6957 
6958 	if (first_bplcon0 != first_bplcon0_old) {
6959 		vertical_changed = horizontal_changed = true;
6960 	}
6961 	first_bplcon0_old = first_bplcon0;
6962 
6963 	if (first_planes_vpos != first_planes_vpos_old ||
6964 		last_planes_vpos != last_planes_vpos_old) {
6965 		vertical_changed = true;
6966 	}
6967 	first_planes_vpos_old = first_planes_vpos;
6968 	last_planes_vpos_old = last_planes_vpos;
6969 
6970 	if (diwfirstword_total != diwfirstword_total_old ||
6971 		diwlastword_total != diwlastword_total_old ||
6972 		ddffirstword_total != ddffirstword_total_old ||
6973 		ddflastword_total != ddflastword_total_old) {
6974 		horizontal_changed = true;
6975 	}
6976 	diwfirstword_total_old = diwfirstword_total;
6977 	diwlastword_total_old = diwlastword_total;
6978 	ddffirstword_total_old = ddffirstword_total;
6979 	ddflastword_total_old = ddflastword_total;
6980 
6981 	first_planes_vpos = 0;
6982 	last_planes_vpos = 0;
6983 	diwfirstword_total = max_diwlastword;
6984 	diwlastword_total = 0;
6985 	ddffirstword_total = max_diwlastword;
6986 	ddflastword_total = 0;
6987 	plflastline_total = 0;
6988 	plffirstline_total = current_maxvpos ();
6989 	first_bplcon0 = 0;
6990 	autoscale_bordercolors = 0;
6991 
6992 	for (i = 0; i < MAX_SPRITES; i++) {
6993 		spr[i].ptxhpos = MAXHPOS;
6994 		spr[i].ptxvpos2 = -1;
6995 	}
6996 	plf_state = plf_end;
6997 }
6998 
6999 void init_hardware_for_drawing_frame (void)
7000 {
7001 	/* Avoid this code in the first frame after a customreset.  */
7002 	if (prev_sprite_entries) {
7003 		int first_pixel = prev_sprite_entries[0].first_pixel;
7004 		int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel;
7005 		memset (spixels + first_pixel, 0, npixels * sizeof *spixels);
7006 		memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes);
7007 	}
7008 	prev_next_sprite_entry = next_sprite_entry;
7009 
7010 	next_color_change = 0;
7011 	next_sprite_entry = 0;
7012 	next_color_entry = 0;
7013 	remembered_color_entry = -1;
7014 
7015 	prev_sprite_entries = sprite_entries[current_change_set];
7016 	curr_sprite_entries = sprite_entries[current_change_set ^ 1];
7017 	prev_color_changes = color_changes[current_change_set];
7018 	curr_color_changes = color_changes[current_change_set ^ 1];
7019 	prev_color_tables = color_tables[current_change_set];
7020 	curr_color_tables = color_tables[current_change_set ^ 1];
7021 
7022 	prev_drawinfo = line_drawinfo[current_change_set];
7023 	curr_drawinfo = line_drawinfo[current_change_set ^ 1];
7024 	current_change_set ^= 1;
7025 
7026 	color_src_match = color_dest_match = -1;
7027 
7028 	/* Use both halves of the array in alternating fashion.  */
7029 	curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS;
7030 	next_sprite_forced = 1;
7031 }
7032 
7033 static int rpt_vsync (int adjust)
7034 {
7035 	frame_time_t curr_time = read_processor_time ();
7036 	int v = curr_time - vsyncwaittime + adjust;
7037 	if (v > syncbase || v < -syncbase) {
7038 		vsyncmintime = vsyncmaxtime = vsyncwaittime = curr_time;
7039 		v = 0;
7040 	}
7041 	return v;
7042 }
7043 
7044 static void rtg_vsync (void)
7045 {
7046 #ifdef PICASSO96
7047 	frame_time_t start, end;
7048 	start = read_processor_time ();
7049 	picasso_handle_vsync ();
7050 	end = read_processor_time ();
7051 	frameskiptime += end - start;
7052 #endif
7053 }
7054 
7055 static void rtg_vsynccheck (void)
7056 {
7057 	if (vblank_found_rtg) {
7058 		vblank_found_rtg = false;
7059 		rtg_vsync ();
7060 	}
7061 }
7062 
7063 
7064 // moving average algorithm
7065 #define MAVG_MAX_SIZE 128
7066 struct mavg_data
7067 {
7068 	int values[MAVG_MAX_SIZE];
7069 	int size;
7070 	int offset;
7071 	int mavg;
7072 };
7073 
7074 static void mavg_clear (struct mavg_data *md)
7075 {
7076 	md->size = 0;
7077 	md->offset = 0;
7078 	md->mavg = 0;
7079 }
7080 
7081 static int mavg (struct mavg_data *md, int newval, int size)
7082 {
7083 	if (md->size < size) {
7084 		md->values[md->size++] = newval;
7085 		md->mavg += newval;
7086 	} else {
7087 		md->mavg -= md->values[md->offset];
7088 		md->values[md->offset] = newval;
7089 		md->mavg += newval;
7090 		md->offset++;
7091 		if (md->offset >= size)
7092 			md->offset -= size;
7093 	}
7094 	return md->mavg / md->size;
7095 }
7096 
7097 #define MAVG_VSYNC_SIZE 128
7098 
7099 extern int log_vsync, debug_vsync_min_delay, debug_vsync_forced_delay;
7100 
7101 #ifdef FSUAE // NL
7102 static bool framewait_2 (void)
7103 #else
7104 static bool framewait (void)
7105 #endif
7106 {
7107 	frame_time_t curr_time;
7108 	frame_time_t start;
7109 	int vs = isvsync_chipset ();
7110 	int status = 0;
7111 
7112 	is_syncline = 0;
7113 
7114 	static struct mavg_data ma_frameskipt;
7115 	int frameskipt_avg = mavg (&ma_frameskipt, frameskiptime, MAVG_VSYNC_SIZE);
7116 
7117 	frameskiptime = 0;
7118 
7119 	if (vs > 0) {
7120 
7121 		static struct mavg_data ma_legacy;
7122 		static frame_time_t vsync_time;
7123 		int t;
7124 
7125 		curr_time = read_processor_time ();
7126 		vsyncwaittime = vsyncmaxtime = curr_time + vsynctimebase;
7127 		if (!frame_rendered && !picasso_on)
7128 			frame_rendered = render_screen (false);
7129 
7130 		start = read_processor_time ();
7131 		t = 0;
7132 		if ((int)start - (int)vsync_time >= 0 && (int)start - (int)vsync_time < vsynctimebase)
7133 			t += (int)start - (int)vsync_time;
7134 
7135 		if (!frame_shown) {
7136 #ifdef FSUAE
7137 #ifdef DEBUG_SHOW_SCREEN
7138 			printf("vframewait_2 -> show_screen(1)\n");
7139 #endif
7140 #endif
7141 			show_screen (1);
7142 			if (currprefs.gfx_apmode[0].gfx_strobo)
7143 				show_screen (2);
7144 		}
7145 
7146 		int legacy_avg = mavg (&ma_legacy, t, MAVG_VSYNC_SIZE);
7147 		if (t > legacy_avg)
7148 			legacy_avg = t;
7149 		t = legacy_avg;
7150 
7151 		if (debug_vsync_min_delay && t < debug_vsync_min_delay * vsynctimebase / 100)
7152 			t = debug_vsync_min_delay * vsynctimebase / 100;
7153 		if (debug_vsync_forced_delay > 0)
7154 			t = debug_vsync_forced_delay * vsynctimebase / 100;
7155 
7156 		vsync_time = read_processor_time ();
7157 		if (t > vsynctimebase * 2 / 3)
7158 			t = vsynctimebase * 2 / 3;
7159 
7160 		if (currprefs.m68k_speed < 0) {
7161 			vsynctimeperline = (vsynctimebase - t) / (maxvpos_display + 1);
7162 		} else {
7163 			vsynctimeperline = (vsynctimebase - t) / 3;
7164 		}
7165 
7166 		if (vsynctimeperline < 1)
7167 			vsynctimeperline = 1;
7168 
7169 		if (0 || (log_vsync & 2)) {
7170 			write_log (_T("%06d %06d/%06d %03d%%\n"), t, vsynctimeperline, vsynctimebase, t * 100 / vsynctimebase);
7171 		}
7172 
7173 		frame_shown = true;
7174 		return 1;
7175 
7176 	} else if (vs < 0) {
7177 
7178 		int freetime;
7179 		extern int extraframewait;
7180 
7181 		if (!vblank_hz_state)
7182 			return status != 0;
7183 
7184 		if (vs == -2 || vs == -3) {
7185 
7186 			// fastest possible
7187 			int max, adjust, flipdelay, val;
7188 			frame_time_t now;
7189 			static struct mavg_data ma_skip, ma_adjust;
7190 
7191 			val = 0;
7192 
7193 			if (!frame_rendered && !picasso_on) {
7194 				frame_time_t start, end;
7195 				start = read_processor_time ();
7196 				frame_rendered = render_screen (currprefs.gfx_apmode[0].gfx_vflip == 0);
7197 				end = read_processor_time ();
7198 				val += end - start;
7199 			}
7200 
7201 			curr_time = vsync_busywait_end (&flipdelay); // vsync time
7202 			status = vsync_busywait_do (NULL, (bplcon0 & 4) != 0 && !lof_changed && !lof_changing, lof_store != 0);
7203 			vsync_busywait_start ();
7204 
7205 			now = read_processor_time (); // current time
7206 			adjust = (int)now - (int)curr_time;
7207 			//write_log (_T("%d "), adjust);
7208 			if (adjust < 0 || adjust >= vsynctimebase)
7209 				adjust = 0;
7210 			if (adjust > vsynctimebase * 2 / 3)
7211 				adjust = vsynctimebase * 2 / 3;
7212 
7213 			int adjust_avg = mavg (&ma_adjust, adjust, MAVG_VSYNC_SIZE);
7214 
7215 			val += adjust_avg;
7216 
7217 			int flipdelay_avg = mavg (&ma_skip, flipdelay, MAVG_VSYNC_SIZE);
7218 			if (flipdelay > flipdelay_avg)
7219 				flipdelay_avg = flipdelay;
7220 			if (currprefs.gfx_apmode[0].gfx_vflip == 0) {
7221 				val += flipdelay_avg;
7222 				//write_log (_T("%d "), skipcnt);
7223 			}
7224 			val += frameskipt_avg;
7225 
7226 			if (currprefs.gfx_apmode[0].gfx_vflip == 0) {
7227 				if (debug_vsync_min_delay && val < debug_vsync_min_delay * vsynctimebase / 100)
7228 					val = debug_vsync_min_delay * vsynctimebase / 100;
7229 				if (debug_vsync_forced_delay > 0)
7230 					val = debug_vsync_forced_delay * vsynctimebase / 100;
7231 			}
7232 
7233 			//write_log (_T("%d "), adjust);
7234 
7235 			if (val > vsynctimebase * 2 / 3)
7236 				val = vsynctimebase * 2 / 3;
7237 
7238 			max = (int)((vsynctimebase - val) * (1000.0 + currprefs.m68k_speed_throttle) / 1000.0);
7239 			if (max < 1)
7240 				max = 1;
7241 
7242 			vsyncmintime = now;
7243 			vsyncwaittime = curr_time + (vsynctimebase - 0);
7244 
7245 			vsynctimeperline = max / (maxvpos_display + 1);
7246 			if (status <= 0 || vsynctimeperline < 1)
7247 				vsynctimeperline = 1;
7248 			vsyncmaxtime = now + max;
7249 
7250 			if (0 || (log_vsync & 2)) {
7251 				write_log (_T("%05d:%05d:%05d=%05d:%05d/%05d %03d%%\n"), adjust_avg, frameskipt_avg, flipdelay_avg,
7252 					val, vsynctimeperline, vsynctimebase, val * 100 / vsynctimebase);
7253 			}
7254 
7255 			frame_shown = true;
7256 
7257 		} else {
7258 
7259 			int max, adjust, flipdelay, flipdelay_avg;
7260 			static struct mavg_data ma_skip;
7261 			frame_time_t now;
7262 
7263 			flipdelay = 0;
7264 			curr_time = vsync_busywait_end (&flipdelay);
7265 			if (!frame_rendered && !picasso_on)
7266 				frame_rendered = render_screen (false);
7267 
7268 			status = vsync_busywait_do (&freetime, (bplcon0 & 4) != 0 && !lof_changed && !lof_changing, lof_store != 0);
7269 			vsync_busywait_start ();
7270 
7271 			now = read_processor_time ();
7272 
7273 			if (extraframewait && !currprefs.turbo_emulation)
7274 				cpu_sleep_millis(extraframewait);
7275 
7276 			adjust = (int)now - (int)curr_time;
7277 			int adjustx = adjust;
7278 			if (adjust < 0)
7279 				adjust = 0;
7280 			if (adjust > vsynctimebase)
7281 				adjust = 0;
7282 			if (adjust > vsynctimebase / 2)
7283 				adjust = vsynctimebase / 2;
7284 
7285 			vsyncmintime = now;
7286 			vsyncwaittime = curr_time + vsynctimebase;
7287 
7288 			if (currprefs.gfx_apmode[0].gfx_vflip == 0) {
7289 				flipdelay_avg = mavg (&ma_skip, flipdelay, MAVG_VSYNC_SIZE);
7290 				if (flipdelay > flipdelay_avg)
7291 					flipdelay_avg = flipdelay;
7292 			} else {
7293 				flipdelay_avg = 0;
7294 			}
7295 
7296 			max = vsynctimebase - adjust - flipdelay_avg;
7297 
7298 			if (currprefs.gfx_apmode[0].gfx_vflip == 0) {
7299 				int val = vsynctimebase - max;
7300 				if (debug_vsync_min_delay && val < debug_vsync_min_delay * vsynctimebase / 100)
7301 					val = debug_vsync_min_delay * vsynctimebase / 100;
7302 				if (debug_vsync_forced_delay > 0)
7303 					val = debug_vsync_forced_delay * vsynctimebase / 100;
7304 				max = vsynctimebase - val;
7305 			}
7306 
7307 			vsynctimeperline = max / 3;
7308 			if (status <= 0 || vsynctimeperline < 1)
7309 				vsynctimeperline = 1;
7310 			vsyncmaxtime = now + max;
7311 
7312 			if (0 || (log_vsync & 2)) {
7313 				write_log (_T("%06d:%06d:%06d:%06d %06d/%06d %03d%%\n"), frameskipt_avg, flipdelay_avg, adjust, adjustx,
7314 					vsynctimeperline, vsynctimebase, (vsynctimebase - max) * 100 / vsynctimebase);
7315 			}
7316 
7317 			frame_shown = true;
7318 		}
7319 		return status != 0;
7320 	}
7321 
7322 	status = 1;
7323 
7324 	int clockadjust = 0;
7325 	int vstb = vsynctimebase;
7326 
7327 	if (currprefs.m68k_speed < 0 && !currprefs.cpu_memory_cycle_exact) {
7328 
7329 #if 0
7330 		static uae_u32 prevtick;
7331 		static int frametickcnt;
7332 
7333 		uae_u32 tick = read_system_time (); // milliseconds
7334 		uae_s32 tickdiff = tick - prevtick;
7335 		uae_s32 framems = (frametickcnt * 1000) / (int)(vblank_hz + 0.5);
7336 		if (abs (framems - tickdiff) >= 2000) {
7337 			framems = 0;
7338 			tickdiff = 0;
7339 			prevtick = tick;
7340 			frametickcnt = 0;
7341 			write_log (_T("Clock sync reset!\n"));
7342 		} else {
7343 			frametickcnt++;
7344 		}
7345 		int diff = (framems - tickdiff) / 1;
7346 		if (diff < -100)
7347 			diff = -100;
7348 		else if (diff > 100)
7349 			diff = 100;
7350 		clockadjust = -vsynctimebase * diff / 10000;
7351 		//write_log (_T("%05d:%05d:%05d\n"), framems - tickdiff, diff, clockadjust);
7352 #endif
7353 
7354 		if (!frame_rendered && !picasso_on)
7355 			frame_rendered = render_screen (false);
7356 
7357 		if (currprefs.m68k_speed_throttle) {
7358 			// this delay can safely overshoot frame time by 1-2 ms, following code will compensate for it.
7359 			for (;;) {
7360 				curr_time = read_processor_time ();
7361 				if ((int)vsyncwaittime  - (int)curr_time <= 0 || (int)vsyncwaittime  - (int)curr_time > 2 * vsynctimebase)
7362 					break;
7363 				rtg_vsynccheck ();
7364 				cpu_sleep_millis(1);
7365 			}
7366 		} else {
7367 			curr_time = read_processor_time ();
7368 		}
7369 
7370 		int max;
7371 		int adjust = 0;
7372 		if ((int)curr_time - (int)vsyncwaittime > 0 && (int)curr_time - (int)vsyncwaittime < vstb / 2)
7373 			adjust += curr_time - vsyncwaittime;
7374 		adjust += clockadjust;
7375 		max = (int)(vstb * (1000.0 + currprefs.m68k_speed_throttle) / 1000.0 - adjust);
7376 		vsyncwaittime = curr_time + vstb - adjust;
7377 		vsyncmintime = curr_time;
7378 
7379 		if (max < 0) {
7380 			max = 0;
7381 			vsynctimeperline = 1;
7382 		} else {
7383 			vsynctimeperline = max / (maxvpos_display + 1);
7384 		}
7385 		vsyncmaxtime = curr_time + max;
7386 
7387 		if (0)
7388 			write_log (_T("%06d:%06d/%06d\n"), adjust, vsynctimeperline, vstb);
7389 
7390 	} else {
7391 
7392 		int t = 0;
7393 
7394 		if (!frame_rendered && !picasso_on) {
7395 			start = read_processor_time ();
7396 			frame_rendered = render_screen (false);
7397 			t = read_processor_time () - start;
7398 		}
7399 		while (!currprefs.turbo_emulation) {
7400 			double v = rpt_vsync (clockadjust) / (syncbase / 1000.0);
7401 			if (v >= -4)
7402 				break;
7403 			rtg_vsynccheck ();
7404 			cpu_sleep_millis(2);
7405 		}
7406 		curr_time = start = read_processor_time ();
7407 		while (rpt_vsync (clockadjust) < 0)
7408 			rtg_vsynccheck ();
7409 		idletime += read_processor_time() - start;
7410 		curr_time = read_processor_time ();
7411 		vsyncmintime = curr_time;
7412 		vsyncmaxtime = vsyncwaittime = curr_time + vstb;
7413 		if (frame_rendered) {
7414 #ifdef FSUAE
7415 #ifdef DEBUG_SHOW_SCREEN
7416 			printf("framewait_2 -> show_screen(0)\n");
7417 #endif
7418 #endif
7419 			show_screen (0);
7420 			t += read_processor_time () - curr_time;
7421 		}
7422 		t += frameskipt_avg;
7423 		vsynctimeperline = (vstb - t) / 3;
7424 		if (vsynctimeperline < 0)
7425 			vsynctimeperline = 0;
7426 		else if (vsynctimeperline > vstb / 3)
7427 			vsynctimeperline = vstb / 3;
7428 
7429 		frame_shown = true;
7430 
7431 	}
7432 	return status != 0;
7433 }
7434 
7435 #ifdef FSUAE // NL
7436 
7437 static bool framewait (void)
7438 {
7439     // printf("currprefs.m68k_speed = %d\n", currprefs.m68k_speed);
7440     if (currprefs.m68k_speed == -1) {
7441         return framewait_2();
7442     }
7443     //currprefs.cpu_idle = 150;
7444     //rtg_vsync ();
7445 
7446     if (!frame_rendered && !picasso_on) {
7447     // if (!frame_rendered) {
7448         frame_rendered = render_screen (false);
7449     }
7450     //if (!frame_shown) {
7451     // FIXME: hack: don't show frame if picasso is enabled
7452     if (!frame_shown && !picasso_on) {
7453 #ifdef DEBUG_SHOW_SCREEN
7454         printf("framewait -> show_screen(0)\n");
7455 #endif
7456         show_screen (0);
7457         frame_shown = true;
7458     }
7459 
7460     static frame_time_t target_time = 0;
7461 
7462     frame_time_t curr_time;
7463     frame_time_t start;
7464     curr_time = start = read_processor_time ();
7465     if (target_time == 0) {
7466         target_time = curr_time;
7467     }
7468     else if (target_time < curr_time - vsynctimebase) {
7469         target_time = curr_time;
7470     }
7471     else if (target_time > curr_time + vsynctimebase) {
7472         target_time = curr_time;
7473     }
7474 
7475     target_time = target_time + vsynctimebase;
7476 
7477 	if (fs_emu_frame_wait > 0 && !currprefs.turbo_emulation) {
7478 		// printf("wait sleep millis %d\n", fs_emu_frame_wait);
7479 		cpu_sleep_millis(fs_emu_frame_wait);
7480 	}
7481 
7482     //printf("%lld\n", vsynctimebase);
7483     //static frame_time_t last_time = curr_time;
7484     //while (rpt_vsync (clockadjust) < 0)
7485     //    rtg_vsynccheck ();
7486     //idletime += read_processor_time() - start;
7487     curr_time = read_processor_time ();
7488     vsyncmintime = curr_time;
7489     //vsyncmaxtime = vsyncwaittime = curr_time + vsynctimebase;
7490     vsyncwaittime = target_time;
7491     vsyncmaxtime = target_time;
7492 
7493     //if (frame_rendered) {
7494     //    show_screen ();
7495     //    t += read_processor_time () - curr_time;
7496     //}
7497     //t += frameskipt_avg;
7498 
7499     frame_time_t t = 0;
7500     vsynctimeperline = (vsynctimebase - t) / 3;
7501     if (vsynctimeperline < 0)
7502         vsynctimeperline = 0;
7503     else if (vsynctimeperline > vsynctimebase / 3)
7504         vsynctimeperline = vsynctimebase / 3;
7505     frame_shown = true;
7506 
7507     vsynctimeperline = 0;
7508 
7509     return 1;
7510 }
7511 #endif
7512 
7513 #define FPSCOUNTER_MAVG_SIZE 10
7514 static struct mavg_data fps_mavg, idle_mavg;
7515 
7516 void fpscounter_reset (void)
7517 {
7518 	mavg_clear (&fps_mavg);
7519 	mavg_clear (&idle_mavg);
7520 	bogusframe = 2;
7521 	lastframetime = read_processor_time ();
7522 	idletime = 0;
7523 }
7524 
7525 
7526 static void fpscounter (bool frameok)
7527 {
7528 	frame_time_t now, last;
7529 
7530 	now = read_processor_time ();
7531 	last = now - lastframetime;
7532 	lastframetime = now;
7533 
7534 	if (bogusframe || (int)last < 0)
7535 		return;
7536 
7537 	mavg (&fps_mavg, last / 10, FPSCOUNTER_MAVG_SIZE);
7538 	mavg (&idle_mavg, idletime / 10, FPSCOUNTER_MAVG_SIZE);
7539 	idletime = 0;
7540 
7541 	frametime += last;
7542 	timeframes++;
7543 
7544 #ifdef FSUAE
7545 	// the following code can crash with 0div error when running in benchmark
7546 	// mode
7547 #else
7548 	if ((timeframes & 7) == 0) {
7549 		double idle = 1000 - (idle_mavg.mavg == 0 ? 0.0 : (double)idle_mavg.mavg * 1000.0 / vsynctimebase);
7550 		int fps = fps_mavg.mavg == 0 ? 0 : syncbase * 10 / fps_mavg.mavg;
7551 		if (fps > 9999)
7552 			fps = 9999;
7553 		if (idle < 0)
7554 			idle = 0;
7555 		if (idle > 100 * 10)
7556 			idle = 100 * 10;
7557 		if (fake_vblank_hz * 10 > fps) {
7558 			double mult = (double)fake_vblank_hz * 10.0 / fps;
7559 			idle *= mult;
7560 		}
7561 		if (currprefs.turbo_emulation && idle < 100 * 10)
7562 			idle = 100 * 10;
7563 		gui_data.fps = fps;
7564 		gui_data.idle = (int)idle;
7565 		gui_data.fps_color = frameok ? 0 : 1;
7566 		if ((timeframes & 15) == 0) {
7567 			gui_fps (fps, (int)idle, frameok ? 0 : 1);
7568 		}
7569 	}
7570 #endif
7571 }
7572 
7573 // vsync functions that are not hardware timing related
7574 static void vsync_handler_pre (void)
7575 {
7576 	if (bogusframe > 0)
7577 		bogusframe--;
7578 
7579 	while (handle_events ()) {
7580 		// we are paused, do all config checks but don't do any emulation
7581 		if (vsync_handle_check ()) {
7582 			redraw_frame ();
7583 #ifdef FSUAE
7584 #ifdef DEBUG_SHOW_SCREEN
7585 			printf("vsync_handler_pre -> render_screen + show_screen\n");
7586 #endif
7587 #endif
7588 			render_screen (true);
7589 			show_screen (0);
7590 		}
7591 		config_check_vsync ();
7592 	}
7593 
7594 	if (quit_program > 0) {
7595 		/* prevent possible infinite loop at wait_cycles().. */
7596 		framecnt = 0;
7597 		reset_decisions ();
7598 		return;
7599 	}
7600 
7601 	config_check_vsync ();
7602 	if (timehack_alive > 0)
7603 		timehack_alive--;
7604 
7605 	devices_vsync_pre();
7606 #ifdef PICASSO96
7607 	if (isvsync_rtg () >= 0)
7608 		rtg_vsync ();
7609 #endif
7610 
7611 	if (!vsync_rendered) {
7612 		frame_time_t start, end;
7613 		start = read_processor_time ();
7614 		vsync_handle_redraw (lof_store, lof_changed, bplcon0, bplcon3);
7615 		vsync_rendered = true;
7616 		end = read_processor_time ();
7617 		frameskiptime += end - start;
7618 	}
7619 
7620 	bool frameok = framewait ();
7621 
7622 	if (!picasso_on) {
7623 		if (!frame_rendered && vblank_hz_state) {
7624 #ifdef FSUAE
7625 #ifdef DEBUG_SHOW_SCREEN
7626 			printf("vsync_handler_pre -> render_screen\n");
7627 #endif
7628 #endif
7629 			frame_rendered = render_screen (false);
7630 		}
7631 		if (frame_rendered && !frame_shown) {
7632 #ifdef FSUAE
7633 #ifdef DEBUG_SHOW_SCREEN
7634 			printf("vsync_handler_pre -> show_screen_maybe\n");
7635 #endif
7636 #endif
7637 			frame_shown = show_screen_maybe (isvsync_chipset () >= 0);
7638 		}
7639 	}
7640 
7641 	fpscounter (frameok);
7642 
7643 	vsync_rendered = false;
7644 	frame_shown = false;
7645 	frame_rendered = false;
7646 
7647 	if (vblank_hz_mult > 0)
7648 		vblank_hz_state ^= 1;
7649 	else
7650 		vblank_hz_state = 1;
7651 
7652 	vsync_handle_check ();
7653 	//checklacecount (bplcon0_interlace_seen || lof_lace);
7654 }
7655 
7656 // emulated hardware vsync
7657 static void vsync_handler_post (void)
7658 {
7659 #ifdef FSUAE
7660 #if 0
7661     if (g_frame_debug_logging) {
7662         write_log("%6d  vsync_handler_post  %08x\n", vsync_counter,
7663                 uae_get_memory_checksum());
7664     }
7665 
7666     char *buffer = strdup("/Users/frode/states/0000000000.uss");
7667     sprintf(buffer, "/Users/frode/states/%d.uss", g_uae_vsync_counter);
7668     if (savestate_state == 0) {
7669 	    save_state (buffer, _T(""));
7670 	}
7671 	else {
7672 		unlink(buffer);
7673 	}
7674     free(buffer);
7675 #endif
7676 #endif
7677 	static frame_time_t prevtime;
7678 
7679 	//write_log (_T("%d %d %d\n"), vsynctimebase, read_processor_time () - vsyncmintime, read_processor_time () - prevtime);
7680 	prevtime = read_processor_time ();
7681 
7682 #if CUSTOM_DEBUG > 1
7683 	if ((intreq & 0x0020) && (intena & 0x0020))
7684 		write_log (_T("vblank interrupt not cleared\n"));
7685 #endif
7686 	DISK_vsync ();
7687 
7688 #ifdef WITH_LUA
7689 	uae_lua_run_handler ("on_uae_vsync");
7690 #endif
7691 
7692 	if (bplcon0 & 4) {
7693 		lof_store = lof_store ? 0 : 1;
7694 	}
7695 	if ((bplcon0 & 2) && currprefs.genlock) {
7696 		genlockvtoggle = lof_store ? 1 : 0;
7697 	}
7698 
7699 	if (lof_prev_lastline != lof_lastline) {
7700 		if (lof_togglecnt_lace < LOF_TOGGLES_NEEDED)
7701 			lof_togglecnt_lace++;
7702 		if (lof_togglecnt_lace >= LOF_TOGGLES_NEEDED)
7703 			lof_togglecnt_nlace = 0;
7704 	} else {
7705 		// only 1-2 vblanks with bplcon0 lace bit set?
7706 		// lets check if lof has changed
7707 		if (!(bplcon0 & 4) && lof_togglecnt_lace > 0 && lof_togglecnt_lace < LOF_TOGGLES_NEEDED && !interlace_seen) {
7708 			lof_changed = 1;
7709 		}
7710 		lof_togglecnt_nlace = LOF_TOGGLES_NEEDED;
7711 		lof_togglecnt_lace = 0;
7712 #if 0
7713 		if (lof_togglecnt_nlace < LOF_TOGGLES_NEEDED)
7714 			lof_togglecnt_nlace++;
7715 		if (lof_togglecnt_nlace >= LOF_TOGGLES_NEEDED)
7716 			lof_togglecnt_lace = 0;
7717 #endif
7718 	}
7719 	lof_prev_lastline = lof_lastline;
7720 	lof_current = lof_store;
7721 	if (lof_togglecnt_lace >= LOF_TOGGLES_NEEDED) {
7722 		interlace_changed = notice_interlace_seen (true);
7723 		if (interlace_changed) {
7724 			notice_screen_contents_lost ();
7725 		}
7726 	} else if (lof_togglecnt_nlace >= LOF_TOGGLES_NEEDED) {
7727 		interlace_changed = notice_interlace_seen (false);
7728 		if (interlace_changed) {
7729 			notice_screen_contents_lost ();
7730 		}
7731 	}
7732 	if (lof_changing) {
7733 		// still same? Trigger change now.
7734 		if ((!lof_store && lof_changing < 0) || (lof_store && lof_changing > 0)) {
7735 			lof_changed_previous_field++;
7736 			lof_changed = 1;
7737 			// lof toggling? decide as interlace.
7738 			if (lof_changed_previous_field >= LOF_TOGGLES_NEEDED) {
7739 				lof_changed_previous_field = LOF_TOGGLES_NEEDED;
7740 				if (lof_lace == false)
7741 					lof_lace = true;
7742 				else
7743 					lof_changed = 0;
7744 			}
7745 			if (bplcon0 & 4)
7746 				lof_changed = 0;
7747 		}
7748 		lof_changing = 0;
7749 	} else {
7750 		lof_changed_previous_field = 0;
7751 		lof_lace = false;
7752 	}
7753 
7754 #ifdef DEBUGGER
7755 	if (debug_copper)
7756 		record_copper_reset ();
7757 	if (debug_dma)
7758 		record_dma_reset ();
7759 #endif
7760 
7761 #ifdef PICASSO96
7762 	if (p96refresh_active) {
7763 		vpos_count = p96refresh_active;
7764 		vtotal = vpos_count;
7765 	}
7766 #endif
7767 
7768 	devices_vsync_post();
7769 
7770 	if (varsync_changed || (beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200)) != (new_beamcon0 & (0x10 | 0x20 | 0x80 | 0x100 | 0x200))) {
7771 		init_hz_normal();
7772 	} else if (vpos_count > 0 && abs (vpos_count - vpos_count_diff) > 1 && vposw_change < 4) {
7773 		init_hz_vposw();
7774 	} else if (interlace_changed || changed_chipset_refresh () || lof_changed) {
7775 		compute_framesync ();
7776 	}
7777 
7778 	lof_changed = 0;
7779 	vposw_change = 0;
7780 	bplcon0_interlace_seen = false;
7781 
7782 	COPJMP (1, 1);
7783 
7784 	init_hardware_frame ();
7785 
7786 	vsync_cycles = get_cycles ();
7787 }
7788 
7789 static void copper_check (int n)
7790 {
7791 	if (cop_state.state == COP_wait) {
7792 		int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
7793 		if (vp < cop_state.vcmp) {
7794 			if (copper_enabled_thisline)
7795 				write_log (_T("COPPER BUG %d: vp=%d vpos=%d vcmp=%d thisline=%d\n"), n, vp, vpos, cop_state.vcmp, copper_enabled_thisline);
7796 		}
7797 	}
7798 }
7799 
7800 /*
7801 
7802 0 0 -
7803 1 1 --
7804 2 2 -
7805 3 3 --
7806 4 4 -
7807 5 5 --
7808 
7809 0 x -+
7810 1 0 --
7811 2 1 -
7812 3 2 --
7813 4 3 -
7814 5 4 --
7815 
7816 */
7817 
7818 static void hsync_scandoubler (void)
7819 {
7820 	int i, idx1;
7821 	struct draw_info *dip1;
7822 	uaecptr bpltmp[8], bpltmpx[8];
7823 
7824 	if (lof_store && vpos >= maxvpos_nom - 1)
7825 		return;
7826 
7827 	next_lineno++;
7828 	scandoubled_line = 1;
7829 #ifdef DEBUGGER
7830 	debug_dma = 0;
7831 #endif
7832 
7833 	for (i = 0; i < 8; i++) {
7834 		int diff;
7835 		bpltmp[i] = bplpt[i];
7836 		bpltmpx[i] = bplptx[i];
7837 		if (prevbpl[lof_store][vpos][i] && prevbpl[1 - lof_store][vpos][i]) {
7838 			diff = prevbpl[lof_store][vpos][i] - prevbpl[1 - lof_store][vpos][i];
7839 			if (lof_store) {
7840 				if (bplcon0 & 4)
7841 					bplpt[i] = prevbpl[lof_store][vpos][i] - diff;
7842 			} else {
7843 				if (bplcon0 & 4)
7844 					bplpt[i] = prevbpl[lof_store][vpos][i];
7845 				else
7846 					bplpt[i] = bplpt[i] - diff;
7847 
7848 			}
7849 		}
7850 	}
7851 
7852 	reset_decisions ();
7853 	plf_state = plf_idle;
7854 	plfr_state = plfr_idle;
7855 
7856 	// copy color changes
7857 	dip1 = curr_drawinfo + next_lineno - 1;
7858 	for (idx1 = dip1->first_color_change; idx1 < dip1->last_color_change; idx1++) {
7859 		struct color_change *cs2 = &curr_color_changes[idx1];
7860 		int regno = cs2->regno;
7861 		int hpos = cs2->linepos;
7862 		if (regno < 0x1000 && hpos < HBLANK_OFFSET && !(beamcon0 & 0x80) && prev_lineno >= 0) {
7863 			struct draw_info *pdip = curr_drawinfo + next_lineno - 1;
7864 			int idx = pdip->last_color_change;
7865 			pdip->last_color_change++;
7866 			pdip->nr_color_changes++;
7867 			curr_color_changes[idx].linepos = hpos + maxhpos + 1;
7868 			curr_color_changes[idx].regno = regno;
7869 			curr_color_changes[idx].value = cs2->value;
7870 			curr_color_changes[idx + 1].regno = -1;
7871 		} else {
7872 			struct color_change *cs1 = &curr_color_changes[next_color_change];
7873 			memcpy (cs1, cs2, sizeof (struct color_change));
7874 			next_color_change++;
7875 		}
7876 	}
7877 	curr_color_changes[next_color_change].regno = -1;
7878 
7879 	finish_decisions ();
7880 	hsync_record_line_state (next_lineno, nln_normal, thisline_changed);
7881 	hardware_line_completed (next_lineno);
7882 	scandoubled_line = 0;
7883 
7884 	for (i = 0; i < 8; i++) {
7885 		bplpt[i] = bpltmp[i];
7886 		bplptx[i] = bpltmpx[i];
7887 	}
7888 }
7889 
7890 static void events_dmal (int);
7891 static uae_u16 dmal, dmal_hpos;
7892 
7893 static void dmal_emu (uae_u32 v)
7894 {
7895 	// Disk and Audio DMA bits are ignored by Agnus, Agnus only checks DMAL and master bit
7896 	if (!(dmacon & DMA_MASTER))
7897 		return;
7898 	int hpos = current_hpos ();
7899 	if (v >= 6) {
7900 		v -= 6;
7901 		int nr = v / 2;
7902 		uaecptr pt = audio_getpt (nr, (v & 1) != 0);
7903 		uae_u16 dat = chipmem_wget_indirect (pt);
7904 #ifdef DEBUGGER
7905 		if (debug_dma)
7906 			record_dma (0xaa + nr * 16, dat, pt, hpos, vpos, DMARECORD_AUDIO);
7907 		if (memwatch_enabled)
7908 			debug_wgetpeekdma_chipram(pt, dat, MW_MASK_AUDIO_0 << nr, 0xaa + nr * 16);
7909 #endif
7910 		last_custom_value1 = dat;
7911 		AUDxDAT (nr, dat, pt);
7912 	} else {
7913 		uae_u16 dat;
7914 		int w = v & 1;
7915 		uaecptr pt = disk_getpt ();
7916 		// disk_fifostatus() needed in >100% disk speed modes
7917 		if (w) {
7918 			// write to disk
7919 			if (disk_fifostatus () <= 0) {
7920 				dat = chipmem_wget_indirect (pt);
7921 				last_custom_value1 = dat;
7922 				DSKDAT (dat);
7923 			}
7924 		} else {
7925 			// read from disk
7926 			if (disk_fifostatus () >= 0) {
7927 				dat = DSKDATR ();
7928 				chipmem_wput_indirect (pt, dat);
7929 			}
7930 		}
7931 #ifdef DEBUGGER
7932 		if (debug_dma)
7933 			record_dma (w ? 0x26 : 0x08, dat, pt, hpos, vpos, DMARECORD_DISK);
7934 		if (memwatch_enabled)
7935 			debug_wgetpeekdma_chipram(pt, dat, MW_MASK_DISK, w ? 0x26 : 0x08);
7936 #endif
7937 	}
7938 }
7939 
7940 static void dmal_func (uae_u32 v)
7941 {
7942 	dmal_emu (v);
7943 	events_dmal (0);
7944 }
7945 
7946 static void dmal_func2 (uae_u32 v)
7947 {
7948 	while (dmal) {
7949 		if (dmal & 3)
7950 			dmal_emu (dmal_hpos + ((dmal & 2) ? 1 : 0));
7951 		dmal_hpos += 2;
7952 		dmal >>= 2;
7953 	}
7954 }
7955 
7956 static void events_dmal (int hp)
7957 {
7958 	if (!dmal)
7959 		return;
7960 	if (currprefs.cpu_cycle_exact) {
7961 		while (dmal) {
7962 			if (dmal & 3)
7963 				break;
7964 			hp += 2;
7965 			dmal >>= 2;
7966 			dmal_hpos += 2;
7967 		}
7968 		event2_newevent2 (hp, dmal_hpos + ((dmal & 2) ? 1 : 0), dmal_func);
7969 		dmal &= ~3;
7970 	} else if (currprefs.cachesize) {
7971 		dmal_func2 (0);
7972 	} else {
7973 		event2_newevent2 (hp, 13, dmal_func2);
7974 	}
7975 }
7976 
7977 static void events_dmal_hsync (void)
7978 {
7979 	if (dmal)
7980 		write_log (_T("DMAL error!? %04x\n"), dmal);
7981 	dmal = audio_dmal ();
7982 	dmal <<= 6;
7983 	dmal |= disk_dmal ();
7984 	if (!dmal)
7985 		return;
7986 	dmal_hpos = 0;
7987 	if (currprefs.cpu_cycle_exact) {
7988 		for (int i = 0; i < 6 + 8; i += 2) {
7989 			if (dmal & (3 << i)) {
7990 				alloc_cycle_ext (i + 7, CYCLE_MISC);
7991 			}
7992 		}
7993 	}
7994 	events_dmal (7);
7995 }
7996 
7997 static bool is_custom_vsync (void)
7998 {
7999 	int vp = vpos + 1;
8000 	int vpc = vpos_count + 1;
8001 	/* Agnus vpos counter keeps counting until it wraps around if VPOSW writes put it past maxvpos */
8002 	if (vp >= maxvpos_total)
8003 		vp = 0;
8004 	if (vp == maxvpos + lof_store || vp == maxvpos + lof_store + 1 || vpc >= MAXVPOS) {
8005 		// vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely
8006 		return true;
8007 	}
8008 	return false;
8009 }
8010 
8011 static void set_hpos (void)
8012 {
8013 	maxhpos = maxhpos_short + lol;
8014 	hpos_offset = 0;
8015 	eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME;
8016 	eventtab[ev_hsync].oldcycles = get_cycles ();
8017 }
8018 
8019 // this finishes current line
8020 static void hsync_handler_pre (bool onvsync)
8021 {
8022 	int hpos = current_hpos ();
8023 
8024 	if (!nocustom ()) {
8025 		sync_copper_with_cpu (maxhpos, 0);
8026 
8027 		// Seven Seas scrolling quick fix hack
8028 		// checks if copper is going to modify BPLCON1 in next cycle.
8029 		if (copper_enabled_thisline && cop_state.state == COP_read2 && (cop_state.i1 & 0x1fe) == 0x102) {
8030 			// it did, pre-load value for Denise shifter emulation
8031 			hpos_is_zero_bplcon1_hack = chipmem_wget_indirect(cop_state.ip);
8032 			// following finish_decision() is going to finish this line
8033 			// it is too late when copper actually does the move
8034 		}
8035 
8036 		finish_decisions ();
8037 		if (thisline_decision.plfleft >= 0) {
8038 			if (currprefs.collision_level > 1)
8039 				do_sprite_collisions ();
8040 			if (currprefs.collision_level > 2)
8041 				do_playfield_collisions ();
8042 		}
8043 		hsync_record_line_state (next_lineno, nextline_how, thisline_changed);
8044 		/* reset light pen latch */
8045 		if (vpos == sprite_vblank_endline) {
8046 			lightpen_triggered = 0;
8047 			sprite_0 = 0;
8048 		}
8049 		if (lightpen_enabled && lightpen_cx > 0 && (bplcon0 & 8) && !lightpen_triggered && lightpen_cy == vpos) {
8050 			vpos_lpen = vpos;
8051 			hpos_lpen = lightpen_cx;
8052 			lightpen_triggered = 1;
8053 		}
8054 		hardware_line_completed (next_lineno);
8055 		if (doflickerfix () && interlace_seen > 0)
8056 			hsync_scandoubler ();
8057 		notice_resolution_seen (GET_RES_AGNUS (bplcon0), interlace_seen != 0);
8058 	}
8059 
8060 	devices_hsync();
8061 
8062 	hsync_counter++;
8063 
8064 	refptr += 0x0200 * 4;
8065 	refptr_val += 0x0200 * 4;
8066 
8067 	if (islinetoggle ())
8068 		lol ^= 1;
8069 	else
8070 		lol = 0;
8071 
8072 	vpos++;
8073 	vpos_count++;
8074 	if (vpos >= maxvpos_total)
8075 		vpos = 0;
8076 	if (onvsync) {
8077 		vpos = 0;
8078 		vsync_counter++;
8079 #ifdef FSUAE
8080 	g_uae_vsync_counter++;
8081 #endif
8082 	}
8083 	set_hpos ();
8084 #if 0
8085 	static int ppp = 2;
8086 	if (input_record && hsync_counter == 100 * 313 + 1) {
8087 		ppp--;
8088 		if (ppp == 0)
8089 			activate_debugger ();
8090 	}
8091 #endif
8092 }
8093 
8094 STATIC_INLINE bool is_last_line (void)
8095 {
8096 	return vpos + 1 == maxvpos + lof_store;
8097 }
8098 
8099 // this prepares for new line
8100 static void hsync_handler_post (bool onvsync)
8101 {
8102 	last_copper_hpos = 0;
8103 #ifdef CPUEMU_13
8104 	if (currprefs.cpu_memory_cycle_exact || currprefs.blitter_cycle_exact) {
8105 		memset (cycle_line, 0, sizeof cycle_line);
8106 	}
8107 #endif
8108 
8109 	// genlock active:
8110 	// vertical: interlaced = toggles every other field, non-interlaced = both fields (normal)
8111 	// horizontal: PAL = every line, NTSC = every other line
8112 	genlockhtoggle = !genlockhtoggle;
8113 	bool ciahsyncs = !(bplcon0 & 2) || ((bplcon0 & 2) && currprefs.genlock && (!currprefs.ntscmode || genlockhtoggle));
8114 	bool ciavsyncs = !(bplcon0 & 2) || ((bplcon0 & 2) && currprefs.genlock && genlockvtoggle);
8115 
8116 	CIA_hsync_posthandler (ciahsyncs);
8117 	if (ciahsyncs) {
8118 		if (beamcon0 & (0x80 | 0x100)) {
8119 			if (hsstop < (maxhpos & ~1) && hsstrt < maxhpos)
8120 				CIAB_tod_handler(hsstop);
8121 		} else {
8122 			CIAB_tod_handler(18);
8123 		}
8124 	}
8125 	if (currprefs.cs_ciaatod > 0) {
8126 #if 0
8127 		static uae_s32 oldtick;
8128 		uae_s32 tick = read_system_time (); // milliseconds
8129 		int ms = 1000 / (currprefs.cs_ciaatod == 2 ? 60 : 50);
8130 		if (tick - oldtick > 2000 || tick - oldtick < -2000) {
8131 			oldtick = tick - ms;
8132 			write_log (_T("RESET\n"));
8133 		}
8134 		if (tick - oldtick >= ms) {
8135 			CIA_vsync_posthandler (1);
8136 			oldtick += ms;
8137 		}
8138 #else
8139 		static int cia_hsync;
8140 		if (cia_hsync < maxhpos) {
8141 			int newcount;
8142 			CIAA_tod_inc (cia_hsync);
8143 			newcount = (vblank_hz * (2 * maxvpos + (interlace_seen ? 1 : 0)) * (2 * maxhpos + (islinetoggle () ? 1 : 0))) / ((currprefs.cs_ciaatod == 2 ? 60 : 50) * 4);
8144 			cia_hsync += newcount;
8145 		} else {
8146 			cia_hsync -= maxhpos;
8147 		}
8148 #endif
8149 	} else if (currprefs.cs_ciaatod == 0 && ciavsyncs) {
8150 		// CIA-A TOD counter increases when vsync pulse ends
8151 		if (beamcon0 & (0x80 | 0x200)) {
8152 			if (vpos == vsstop && vsstrt <= maxvpos)
8153 				CIAA_tod_inc (lof_store ? hsstop : hsstop + hcenter);
8154 		} else {
8155 			if (vpos == (currprefs.ntscmode ? VSYNC_ENDLINE_NTSC : VSYNC_ENDLINE_PAL)) {
8156 				CIAA_tod_inc (lof_store ? 132 : 18);
8157 			}
8158 		}
8159 	}
8160 
8161 	inputdevice_hsync ();
8162 
8163 	if (!nocustom ()) {
8164 		if (!currprefs.blitter_cycle_exact && bltstate != BLT_done && dmaen (DMA_BITPLANE) && diwstate == DIW_waiting_stop) {
8165 			blitter_slowdown (thisline_decision.plfleft, thisline_decision.plfright - (16 << fetchmode),
8166 				cycle_diagram_total_cycles[fetchmode][GET_RES_AGNUS (bplcon0)][GET_PLANES_LIMIT (bplcon0)],
8167 				cycle_diagram_free_cycles[fetchmode][GET_RES_AGNUS (bplcon0)][GET_PLANES_LIMIT (bplcon0)]);
8168 		}
8169 	}
8170 
8171 	if (onvsync) {
8172 		// vpos_count >= MAXVPOS just to not crash if VPOSW writes prevent vsync completely
8173 		if ((bplcon0 & 8) && !lightpen_triggered) {
8174 			vpos_lpen = vpos - 1;
8175 			hpos_lpen = maxhpos;
8176 			lightpen_triggered = 1;
8177 		}
8178 		vpos = 0;
8179 		vsync_handler_post ();
8180 		vpos_count = 0;
8181 	}
8182 	// A1000 DIP Agnus (8361): vblank interrupt is triggered on line 1!
8183 	if (currprefs.cs_dipagnus) {
8184 		if (vpos == 1)
8185 			send_interrupt (5, 1 * CYCLE_UNIT);
8186 	} else {
8187 		if (vpos == 0)
8188 			send_interrupt (5, 1 * CYCLE_UNIT);
8189 	}
8190 	// lastline - 1?
8191 	if (vpos + 1 == maxvpos + lof_store || vpos + 1 == maxvpos + lof_store + 1) {
8192 		lof_lastline = lof_store != 0;
8193 	}
8194 
8195 #ifdef CPUEMU_13
8196 	if (currprefs.cpu_memory_cycle_exact || currprefs.blitter_cycle_exact) {
8197 		int hp = maxhpos - 1, i;
8198 		for (i = 0; i < 4; i++) {
8199 			alloc_cycle (hp, i == 0 ? CYCLE_STROBE : CYCLE_REFRESH); /* strobe */
8200 #ifdef DEBUGGER
8201 			if (debug_dma) {
8202 				uae_u16 strobe = 0x3c;
8203 				if (vpos < equ_vblank_endline)
8204 					strobe = 0x38;
8205 				else if (vpos < minfirstline)
8206 					strobe = 0x3a;
8207 				else if (vpos + 1 == maxvpos + lof_store)
8208 					strobe = 0x38;
8209 				else if ((currprefs.chipset_mask & CSMASK_ECS_AGNUS) && lol)
8210 					strobe = 0x3e;
8211 				record_dma (i == 0 ? strobe : 0x1fe, 0xffff, 0xffffffff, hp, vpos, DMARECORD_REFRESH);
8212 			}
8213 #endif
8214 			hp += 2;
8215 			if (hp >= maxhpos)
8216 				hp -= maxhpos;
8217 		}
8218 	}
8219 #endif
8220 
8221 	events_dmal_hsync ();
8222 #if 0
8223 	// AF testing stuff
8224 	static int cnt = 0;
8225 	cnt++;
8226 	if (cnt == 500) {
8227 		int port_insert_custom (int inputmap_port, int devicetype, DWORD flags, const TCHAR *custom);
8228 		//port_insert_custom (0, 2, 0, _T("Left=0xCB Right=0xCD Up=0xC8 Down=0xD0 Fire=0x39 Fire.autorepeat=0xD2"));
8229 		port_insert_custom (1, 2, 0, _T("Left=0x1E Right=0x20 Up=0x11 Down=0x1F Fire=0x38"));
8230 	} else if (0 && cnt == 1000) {
8231 		TCHAR out[256];
8232 		bool port_get_custom (int inputmap_port, TCHAR *out);
8233 		port_get_custom (0, out);
8234 		port_get_custom (1, out);
8235 	}
8236 #endif
8237 	if (!currprefs.cpu_thread && currprefs.m68k_speed < 0 && !currprefs.cpu_memory_cycle_exact) {
8238 		static int sleeps_remaining;
8239 		if (is_last_line ()) {
8240 			sleeps_remaining = (165 - currprefs.cpu_idle) / 6;
8241 			if (sleeps_remaining < 0)
8242 				sleeps_remaining = 0;
8243 			/* really last line, just run the cpu emulation until whole vsync time has been used */
8244 			if (regs.stopped && currprefs.cpu_idle) {
8245 				// CPU in STOP state: sleep if enough time left.
8246 				frame_time_t rpt = read_processor_time ();
8247 				while (!vsync_isdone () && (int)vsyncmintime - (int)(rpt + vsynctimebase / 10) > 0 && (int)vsyncmintime - (int)rpt < vsynctimebase) {
8248 					if (!execute_other_cpu(rpt + vsynctimebase / 10))
8249 						cpu_sleep_millis(1);
8250 					rpt = read_processor_time ();
8251 				}
8252 			} else if (currprefs.m68k_speed_throttle) {
8253 				vsyncmintime = read_processor_time (); /* end of CPU emulation time */
8254 				is_syncline = 0;
8255 			} else {
8256 				vsyncmintime = vsyncmaxtime; /* emulate if still time left */
8257 				is_syncline_end = read_processor_time () + vsynctimebase; /* far enough in future, we never wait that long */
8258 				is_syncline = 2;
8259 			}
8260 		} else {
8261 			static int linecounter;
8262 			/* end of scanline, run cpu emulation as long as we still have time */
8263 			vsyncmintime += vsynctimeperline;
8264 			linecounter++;
8265 			is_syncline = 0;
8266 			if (!vsync_isdone () && !currprefs.turbo_emulation) {
8267 				if ((int)vsyncmaxtime - (int)vsyncmintime > 0) {
8268 					if ((int)vsyncwaittime - (int)vsyncmintime > 0) {
8269 						frame_time_t rpt = read_processor_time ();
8270 						/* Extra time left? Do some extra CPU emulation */
8271 						if ((int)vsyncmintime - (int)rpt > 0) {
8272 							if (regs.stopped && currprefs.cpu_idle && sleeps_remaining > 0) {
8273 								// STOP STATE: sleep.
8274 								cpu_sleep_millis(1);
8275 								sleeps_remaining--;
8276 							} else {
8277 								is_syncline = 1;
8278 								/* limit extra time */
8279 								is_syncline_end = rpt + vsynctimeperline;
8280 								linecounter = 0;
8281 							}
8282 						}
8283 					}
8284 					if (!isvsync ()) {
8285 						// extra cpu emulation time if previous 10 lines without extra time.
8286 						if (!is_syncline && linecounter >= 10 && (!regs.stopped || !currprefs.cpu_idle)) {
8287 							is_syncline = -1;
8288 							is_syncline_end = read_processor_time () + vsynctimeperline;
8289 							linecounter = 0;
8290 						}
8291 					}
8292 				}
8293 			}
8294 		}
8295 	} else if (!currprefs.cpu_thread) {
8296 		if (vpos + 1 < maxvpos + lof_store && (vpos == maxvpos_display * 1 / 3 || vpos == maxvpos_display * 2 / 3)) {
8297 			vsyncmintime += vsynctimeperline;
8298 			if (!vsync_isdone () && !currprefs.turbo_emulation) {
8299 				frame_time_t rpt = read_processor_time ();
8300 				// sleep if more than 2ms "free" time
8301 				while (!vsync_isdone () && (int)vsyncmintime - (int)(rpt + vsynctimebase / 10) > 0 && (int)vsyncmintime - (int)rpt < vsynctimebase) {
8302 					if (!execute_other_cpu(rpt + vsynctimebase / 10))
8303 						cpu_sleep_millis(1);
8304 					rpt = read_processor_time ();
8305 					//write_log (_T("*"));
8306 				}
8307 			}
8308 		}
8309 	}
8310 
8311 	if (!nocustom ()) {
8312 		int lineno = vpos;
8313 		if (lineno >= MAXVPOS)
8314 			lineno %= MAXVPOS;
8315 		nextline_how = nln_normal;
8316 		if (doflickerfix () && interlace_seen > 0) {
8317 			lineno *= 2;
8318 		} else if (!interlace_seen && doublescan <= 0 && currprefs.gfx_vresolution && currprefs.gfx_pscanlines > 1) {
8319 			lineno *= 2;
8320 			if (timeframes & 1) {
8321 				lineno++;
8322 				nextline_how = currprefs.gfx_pscanlines == 3 ? nln_lower_black_always : nln_lower_black;
8323 			} else {
8324 				nextline_how = currprefs.gfx_pscanlines == 3 ? nln_upper_black_always : nln_upper_black;
8325 			}
8326 		} else if ((doublescan <= 0 || interlace_seen > 0) && currprefs.gfx_vresolution && currprefs.gfx_iscanlines) {
8327 			lineno *= 2;
8328 			if (interlace_seen) {
8329 				if (!lof_current) {
8330 					lineno++;
8331 					nextline_how = currprefs.gfx_iscanlines == 2 ? nln_lower_black_always : nln_lower_black;
8332 				} else {
8333 					nextline_how = currprefs.gfx_iscanlines == 2 ? nln_upper_black_always : nln_upper_black;
8334 				}
8335 			} else {
8336 				nextline_how = currprefs.gfx_vresolution > VRES_NONDOUBLE && currprefs.gfx_pscanlines == 1 ? nln_nblack : nln_doubled;
8337 			}
8338 		} else if (currprefs.gfx_vresolution && (doublescan <= 0 || interlace_seen > 0)) {
8339 			lineno *= 2;
8340 			if (interlace_seen) {
8341 				if (!lof_current) {
8342 					lineno++;
8343 					nextline_how = nln_lower;
8344 				} else {
8345 					nextline_how = nln_upper;
8346 				}
8347 			} else {
8348 				nextline_how = currprefs.gfx_vresolution > VRES_NONDOUBLE && currprefs.gfx_pscanlines == 1 ? nln_nblack : nln_doubled;
8349 			}
8350 		}
8351 		prev_lineno = next_lineno;
8352 		next_lineno = lineno;
8353 		reset_decisions ();
8354 	}
8355 
8356 	if (uae_int_requested) {
8357 		if (uae_int_requested & 0xff00)
8358 			INTREQ(0x8000 | 0x2000);
8359 		if (uae_int_requested & 0x00ff)
8360 			INTREQ(0x8000 | 0x0008);
8361 	}
8362 
8363 	{
8364 		if (uaenet_int_requested || (uaenet_vsync_requested && vpos == 10)) {
8365 			INTREQ (0x8000 | 0x0008);
8366 		}
8367 	}
8368 
8369 	{
8370 		extern void bsdsock_fake_int_handler (void);
8371 		extern int volatile bsd_int_requested;
8372 		if (bsd_int_requested)
8373 			bsdsock_fake_int_handler ();
8374 	}
8375 
8376 	/* Default to no bitplane DMA overriding sprite DMA */
8377 	plfstrt_sprite = 0xff;
8378 	/* See if there's a chance of a copper wait ending this line.  */
8379 	cop_state.hpos = 0;
8380 	compute_spcflag_copper (maxhpos);
8381 
8382 #ifdef FSUAE
8383 	filesys_hsync();
8384 #endif
8385 	//copper_check (2);
8386 
8387 	if (GET_PLANES (bplcon0) > 0 && dmaen (DMA_BITPLANE)) {
8388 		if (first_bplcon0 == 0)
8389 			first_bplcon0 = bplcon0;
8390 		if (vpos > last_planes_vpos)
8391 			last_planes_vpos = vpos;
8392 		if (vpos >= minfirstline && first_planes_vpos == 0) {
8393 			first_planes_vpos = vpos > minfirstline ? vpos - 1 : vpos;
8394 		} else if (vpos >= current_maxvpos () - 1) {
8395 			last_planes_vpos = current_maxvpos ();
8396 		}
8397 	}
8398 	if (diw_change == 0) {
8399 		if (vpos >= first_planes_vpos && vpos <= last_planes_vpos) {
8400 			if (diwlastword > diwlastword_total) {
8401 				diwlastword_total = diwlastword;
8402 				if (diwlastword_total > coord_diw_to_window_x (hsyncstartpos * 2))
8403 					diwlastword_total = coord_diw_to_window_x (hsyncstartpos * 2);
8404 			}
8405 			if (diwfirstword < diwfirstword_total) {
8406 				diwfirstword_total = diwfirstword;
8407 				if (diwfirstword_total < coord_diw_to_window_x (hsyncendpos * 2))
8408 					diwfirstword_total = coord_diw_to_window_x (hsyncendpos * 2);
8409 				firstword_bplcon1 = bplcon1;
8410 			}
8411 		}
8412 		if (diwstate == DIW_waiting_stop) {
8413 			int f = 8 << fetchmode;
8414 			if (plfstrt + f < ddffirstword_total + f)
8415 				ddffirstword_total = plfstrt + f;
8416 			if (plfstop + 2 * f > ddflastword_total + 2 * f)
8417 				ddflastword_total = plfstop + 2 * f;
8418 		}
8419 		if ((plffirstline < plffirstline_total || (plffirstline_total == minfirstline && vpos > minfirstline)) && plffirstline < vpos / 2) {
8420 			firstword_bplcon1 = bplcon1;
8421 			if (plffirstline < minfirstline)
8422 				plffirstline_total = minfirstline;
8423 			else
8424 				plffirstline_total = plffirstline;
8425 		}
8426 		if (plflastline > plflastline_total && plflastline > plffirstline_total && plflastline > maxvpos / 2)
8427 			plflastline_total = plflastline;
8428 	}
8429 	if (diw_change > 0)
8430 		diw_change--;
8431 
8432 	/* fastest possible + last line and no vflip wait: render the frame as early as possible */
8433 	if (is_last_line () && isvsync_chipset () <= -2 && !vsync_rendered && currprefs.gfx_apmode[0].gfx_vflip == 0) {
8434 		frame_time_t start, end;
8435 		start = read_processor_time ();
8436 		vsync_rendered = true;
8437 		vsync_handle_redraw (lof_store, lof_changed, bplcon0, bplcon3);
8438 		if (vblank_hz_state) {
8439 			frame_rendered = render_screen (true);
8440 		}
8441 		end = read_processor_time ();
8442 		frameskiptime += end - start;
8443 	}
8444 
8445 	rtg_vsynccheck ();
8446 
8447 #if 0
8448 	{
8449 		static int skip;
8450 		if (M68K_GETPC >= 0x0C0D7A2 && M68K_GETPC < 0x00C0D7B2 && vpos == 0xf3) {
8451 			if (!skip)
8452 				activate_debugger ();
8453 			skip = 1;
8454 		}
8455 		if (vpos != 0xf3)
8456 			skip = 0;
8457 	}
8458 #endif
8459 }
8460 
8461 static void hsync_handler (void)
8462 {
8463 	bool vs = is_custom_vsync ();
8464 	hsync_handler_pre (vs);
8465 	if (vs) {
8466 		vsync_handler_pre ();
8467 #ifdef SAVESTATE
8468 		if (savestate_check ()) {
8469 			uae_reset (0, 0);
8470 			return;
8471 		}
8472 #endif
8473 	}
8474 	hsync_handler_post (vs);
8475 }
8476 
8477 void init_eventtab (void)
8478 {
8479 	int i;
8480 
8481 	nextevent = 0;
8482 	for (i = 0; i < ev_max; i++) {
8483 		eventtab[i].active = 0;
8484 		eventtab[i].oldcycles = get_cycles ();
8485 	}
8486 	for (i = 0; i < ev2_max; i++) {
8487 		eventtab2[i].active = 0;
8488 	}
8489 
8490 	eventtab[ev_cia].handler = CIA_handler;
8491 	eventtab[ev_hsync].handler = hsync_handler;
8492 	eventtab[ev_hsync].evtime = get_cycles () + HSYNCTIME;
8493 	eventtab[ev_hsync].active = 1;
8494 	eventtab[ev_misc].handler = MISC_handler;
8495 	eventtab[ev_audio].handler = audio_evhandler;
8496 
8497 	eventtab2[ev2_blitter].handler = blitter_handler;
8498 	eventtab2[ev2_disk].handler = DISK_handler;
8499 
8500 	events_schedule ();
8501 }
8502 
8503 void custom_prepare (void)
8504 {
8505 	set_hpos ();
8506 	hsync_handler_post (true);
8507 }
8508 
8509 void custom_reset (bool hardreset, bool keyboardreset)
8510 {
8511 	int i;
8512 
8513 	target_reset ();
8514 	reset_all_systems ();
8515 	write_log (_T("Reset at %08X. Chipset mask = %08X\n"), M68K_GETPC, currprefs.chipset_mask);
8516 	memory_map_dump ();
8517 
8518 	lightpen_active = -1;
8519 	lightpen_triggered = 0;
8520 	lightpen_cx = lightpen_cy = -1;
8521 	nr_armed = 0;
8522 
8523 	if (!savestate_state) {
8524 		extra_cycle = 0;
8525 		hsync_counter = 0;
8526 		vsync_counter = 0;
8527 		currprefs.chipset_mask = changed_prefs.chipset_mask;
8528 		update_mirrors ();
8529 		blitter_reset ();
8530 
8531 		if (hardreset) {
8532 			if (!aga_mode) {
8533 				uae_u16 c = (((currprefs.chipset_mask & CSMASK_ECS_DENISE) && !(currprefs.chipset_mask & CSMASK_AGA)) || currprefs.cs_denisenoehb) ? 0xfff : 0x000;
8534 				for (i = 0; i < 32; i++) {
8535 					current_colors.color_regs_ecs[i] = c;
8536 					current_colors.acolors[i] = getxcolor (c);
8537 				}
8538 	#ifdef AGA
8539 			} else {
8540 				uae_u32 c = 0;
8541 				for (i = 0; i < 256; i++) {
8542 					current_colors.color_regs_aga[i] = c;
8543 					current_colors.acolors[i] = getxcolor (c);
8544 				}
8545 	#endif
8546 			}
8547 		}
8548 
8549 		clxdat = 0;
8550 
8551 		/* Clear the armed flags of all sprites.  */
8552 		memset (spr, 0, sizeof spr);
8553 
8554 		dmacon = 0;
8555 		intreq_internal = 0;
8556 		intena = intena_internal = 0;
8557 
8558 		copcon = 0;
8559 		DSKLEN (0, 0);
8560 
8561 		bplcon0 = 0;
8562 		bplcon4 = 0x0011; /* Get AGA chipset into ECS compatibility mode */
8563 		bplcon3 = 0x0C00;
8564 
8565 		diwhigh = 0;
8566 		diwhigh_written = 0;
8567 		hdiwstate = DIW_waiting_start; // this does not reset at vblank
8568 
8569 		refptr = 0xffff;
8570 		FMODE (0, 0);
8571 		CLXCON (0);
8572 		CLXCON2 (0);
8573 		setup_fmodes (0);
8574 		sprite_width = GET_SPRITEWIDTH (fmode);
8575 		beamcon0 = new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20;
8576 		bltstate = BLT_done;
8577 		blit_interrupt = 1;
8578 		lof_store = lof_current = 0;
8579 		lof_lace = false;
8580 		init_sprites ();
8581 	}
8582 
8583 	devices_reset(hardreset);
8584 	specialmonitor_reset();
8585 
8586 	unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE));
8587 
8588 	vpos = 0;
8589 	vpos_count = vpos_count_diff = 0;
8590 
8591 	inputdevice_reset ();
8592 	timehack_alive = 0;
8593 
8594 	curr_sprite_entries = 0;
8595 	prev_sprite_entries = 0;
8596 	sprite_entries[0][0].first_pixel = 0;
8597 	sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS;
8598 	sprite_entries[0][1].first_pixel = 0;
8599 	sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS;
8600 	memset (spixels, 0, 2 * MAX_SPR_PIXELS * sizeof *spixels);
8601 	memset (&spixstate, 0, sizeof spixstate);
8602 	toscr_delay_sh[0] = 0;
8603 	toscr_delay_sh[1] = 0;
8604 
8605 	cop_state.state = COP_stop;
8606 	cop_state.movedelay = 0;
8607 	cop_state.strobe = 0;
8608 	cop_state.ignore_next = 0;
8609 	diwstate = DIW_waiting_start;
8610 
8611 	dmal = 0;
8612 	init_hz_normal();
8613 	vpos_lpen = -1;
8614 	lof_changing = 0;
8615 	lof_togglecnt_nlace = lof_togglecnt_lace = 0;
8616 	//nlace_cnt = NLACE_CNT_NEEDED;
8617 
8618 	audio_reset ();
8619 	if (!isrestore ()) {
8620 		/* must be called after audio_reset */
8621 		adkcon = 0;
8622 		serial_uartbreak (0);
8623 		audio_update_adkmasks ();
8624 	}
8625 
8626 	init_hardware_frame ();
8627 	drawing_init ();
8628 
8629 	reset_decisions ();
8630 
8631 	bogusframe = 1;
8632 
8633 	if (isrestore ()) {
8634 		uae_u16 v;
8635 		uae_u32 vv;
8636 
8637 		audio_update_adkmasks ();
8638 		INTENA (0);
8639 		INTREQ (0);
8640 		COPJMP (1, 1);
8641 		v = bplcon0;
8642 		BPLCON0 (0, 0);
8643 		BPLCON0 (0, v);
8644 		FMODE (0, fmode);
8645 		if (!(currprefs.chipset_mask & CSMASK_AGA)) {
8646 			for(i = 0 ; i < 32 ; i++)  {
8647 				vv = current_colors.color_regs_ecs[i];
8648 				current_colors.color_regs_ecs[i] = -1;
8649 				record_color_change (0, i, vv);
8650 				remembered_color_entry = -1;
8651 				current_colors.color_regs_ecs[i] = vv;
8652 				current_colors.acolors[i] = xcolors[vv];
8653 			}
8654 #ifdef AGA
8655 		} else {
8656 			for(i = 0 ; i < 256 ; i++)  {
8657 				vv = current_colors.color_regs_aga[i];
8658 				current_colors.color_regs_aga[i] = -1;
8659 				record_color_change (0, i, vv);
8660 				remembered_color_entry = -1;
8661 				current_colors.color_regs_aga[i] = vv;
8662 				current_colors.acolors[i] = CONVERT_RGB (vv);
8663 			}
8664 #endif
8665 		}
8666 		CLXCON (clxcon);
8667 		CLXCON2 (clxcon2);
8668 		calcdiw ();
8669 		v = serper;
8670 		serper = 0;
8671 		SERPER(v);
8672 		for (i = 0; i < 8; i++) {
8673 			SPRxCTLPOS (i);
8674 			nr_armed += spr[i].armed != 0;
8675 		}
8676 		if (! currprefs.produce_sound) {
8677 			eventtab[ev_audio].active = 0;
8678 			events_schedule ();
8679 		}
8680 
8681 		write_log (_T("CPU=%d Chipset=%s %s\n"),
8682 			currprefs.cpu_model,
8683 			(currprefs.chipset_mask & CSMASK_AGA) ? _T("AGA") :
8684 			(currprefs.chipset_mask & (CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE)) == (CSMASK_ECS_AGNUS | CSMASK_ECS_DENISE) ? _T("Full ECS") :
8685 			(currprefs.chipset_mask & CSMASK_ECS_DENISE) ? _T("ECS Denise") :
8686 			(currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? _T("ECS") :
8687 			_T("OCS"), currprefs.ntscmode ? _T("NTSC") : _T("PAL"));
8688 		write_log (_T("State restored\n"));
8689 	}
8690 	sprres = expand_sprres (bplcon0, bplcon3);
8691 	sprite_width = GET_SPRITEWIDTH (fmode);
8692 	setup_fmodes (0);
8693 
8694 #ifdef ACTION_REPLAY
8695 	/* Doing this here ensures we can use the 'reset' command from within AR */
8696 	action_replay_reset (hardreset, keyboardreset);
8697 #endif
8698 #if defined(ENFORCER)
8699 	enforcer_disable ();
8700 #endif
8701 
8702 	if (hardreset)
8703 		rtc_hardreset();
8704 
8705 #ifdef PICASSO96
8706 	picasso_reset ();
8707 #endif
8708 }
8709 
8710 void dumpcustom (void)
8711 {
8712 	console_out_f (_T("DMACON: %04x INTENA: %04x (%04x) INTREQ: %04x (%04x) VPOS: %x HPOS: %x\n"), DMACONR (current_hpos ()),
8713 		intena, intena_internal, intreq, intreq_internal, vpos, current_hpos ());
8714 	console_out_f (_T("INT: %04x IPL: %d\n"), intena & intreq, intlev());
8715 	console_out_f (_T("COP1LC: %08lx, COP2LC: %08lx COPPTR: %08lx\n"), (unsigned long)cop1lc, (unsigned long)cop2lc, cop_state.ip);
8716 	console_out_f (_T("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n"),
8717 		(unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop);
8718 	console_out_f (_T("BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x LOF=%d/%d HDIW=%d VDIW=%d\n"),
8719 		bplcon0, bplcon1, bplcon2, bplcon3, bplcon4,
8720 		lof_current, lof_store,
8721 		hdiwstate == DIW_waiting_start ? 0 : 1, diwstate == DIW_waiting_start ? 0 : 1);
8722 	if (timeframes) {
8723 		console_out_f (_T("Average frame time: %.2f ms [frames: %d time: %d]\n"),
8724 			(double)frametime / timeframes, timeframes, frametime);
8725 		if (total_skipped)
8726 			console_out_f (_T("Skipped frames: %d\n"), total_skipped);
8727 	}
8728 }
8729 
8730 static void gen_custom_tables (void)
8731 {
8732 	int i;
8733 	for (i = 0; i < 256; i++) {
8734 		sprtaba[i] = ((((i >> 7) & 1) << 0)
8735 			| (((i >> 6) & 1) << 2)
8736 			| (((i >> 5) & 1) << 4)
8737 			| (((i >> 4) & 1) << 6)
8738 			| (((i >> 3) & 1) << 8)
8739 			| (((i >> 2) & 1) << 10)
8740 			| (((i >> 1) & 1) << 12)
8741 			| (((i >> 0) & 1) << 14));
8742 		sprtabb[i] = sprtaba[i] * 2;
8743 		sprite_ab_merge[i] = (((i & 15) ? 1 : 0)
8744 			| ((i & 240) ? 2 : 0));
8745 	}
8746 	for (i = 0; i < 16; i++) {
8747 		clxmask[i] = (((i & 1) ? 0xF : 0x3)
8748 			| ((i & 2) ? 0xF0 : 0x30)
8749 			| ((i & 4) ? 0xF00 : 0x300)
8750 			| ((i & 8) ? 0xF000 : 0x3000));
8751 		sprclx[i] = (((i & 0x3) == 0x3 ? 1 : 0)
8752 			| ((i & 0x5) == 0x5 ? 2 : 0)
8753 			| ((i & 0x9) == 0x9 ? 4 : 0)
8754 			| ((i & 0x6) == 0x6 ? 8 : 0)
8755 			| ((i & 0xA) == 0xA ? 16 : 0)
8756 			| ((i & 0xC) == 0xC ? 32 : 0)) << 9;
8757 	}
8758 }
8759 
8760 /* mousehack is now in "filesys boot rom" */
8761 static uae_u32 REGPARAM2 mousehack_helper_old (struct TrapContext *ctx)
8762 {
8763 	return 0;
8764 }
8765 
8766 int custom_init (void)
8767 {
8768 
8769 #ifdef AUTOCONFIG
8770 	if (uae_boot_rom_type) {
8771 		uaecptr pos;
8772 		pos = here ();
8773 
8774 		org (rtarea_base + 0xFF70);
8775 		calltrap (deftrap (mousehack_helper_old));
8776 		dw (RTS);
8777 
8778 		org (rtarea_base + 0xFFA0);
8779 		calltrap (deftrap (timehack_helper));
8780 		dw (RTS);
8781 
8782 		org (pos);
8783 	}
8784 #endif
8785 
8786 	gen_custom_tables ();
8787 	build_blitfilltable ();
8788 
8789 	drawing_init ();
8790 
8791 	create_cycle_diagram_table ();
8792 
8793 	return 1;
8794 }
8795 
8796 /* Custom chip memory bank */
8797 
8798 static uae_u32 REGPARAM3 custom_lget (uaecptr) REGPARAM;
8799 static uae_u32 REGPARAM3 custom_wget (uaecptr) REGPARAM;
8800 static uae_u32 REGPARAM3 custom_bget (uaecptr) REGPARAM;
8801 static uae_u32 REGPARAM3 custom_lgeti (uaecptr) REGPARAM;
8802 static uae_u32 REGPARAM3 custom_wgeti (uaecptr) REGPARAM;
8803 static void REGPARAM3 custom_lput (uaecptr, uae_u32) REGPARAM;
8804 static void REGPARAM3 custom_wput (uaecptr, uae_u32) REGPARAM;
8805 static void REGPARAM3 custom_bput (uaecptr, uae_u32) REGPARAM;
8806 
8807 addrbank custom_bank = {
8808 	custom_lget, custom_wget, custom_bget,
8809 	custom_lput, custom_wput, custom_bput,
8810 	default_xlate, default_check, NULL, NULL, _T("Custom chipset"),
8811 	custom_lgeti, custom_wgeti,
8812 	ABFLAG_IO, S_READ, S_WRITE, NULL, 0x1ff, 0xdff000
8813 };
8814 
8815 static uae_u32 REGPARAM2 custom_wgeti (uaecptr addr)
8816 {
8817 	if (currprefs.cpu_model >= 68020)
8818 		return dummy_wgeti (addr);
8819 	return custom_wget (addr);
8820 }
8821 static uae_u32 REGPARAM2 custom_lgeti (uaecptr addr)
8822 {
8823 	if (currprefs.cpu_model >= 68020)
8824 		return dummy_lgeti (addr);
8825 	return custom_lget (addr);
8826 }
8827 
8828 static uae_u32 REGPARAM2 custom_wget_1(int hpos, uaecptr addr, int noput, bool isbyte)
8829 {
8830 	uae_u16 v;
8831 	int missing;
8832 	addr &= 0xfff;
8833 #if CUSTOM_DEBUG > 2
8834 	write_log (_T("%d:%d:wget: %04X=%04X pc=%p\n"), current_hpos(), vpos, addr, addr & 0x1fe, m68k_getpc ());
8835 #endif
8836 	switch (addr & 0x1fe) {
8837 	case 0x002: v = DMACONR (hpos); break;
8838 	case 0x004: v = VPOSR (); break;
8839 	case 0x006: v = VHPOSR (); break;
8840 
8841 	case 0x00A: v = JOY0DAT (); break;
8842 	case 0x00C: v = JOY1DAT (); break;
8843 	case 0x00E: v = CLXDAT (); break;
8844 	case 0x010: v = ADKCONR (); break;
8845 
8846 	case 0x012: v = POT0DAT (); break;
8847 	case 0x014: v = POT1DAT (); break;
8848 	case 0x016: v = POTGOR (); break;
8849 	case 0x018: v = SERDATR (); break;
8850 	case 0x01A: v = DSKBYTR (hpos); break;
8851 	case 0x01C: v = INTENAR (); break;
8852 	case 0x01E: v = INTREQR (); break;
8853 	case 0x07C:
8854 		v = DENISEID (&missing);
8855 		if (missing)
8856 			goto writeonly;
8857 		break;
8858 
8859 #ifdef AGA
8860 	case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
8861 	case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
8862 	case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
8863 	case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
8864 	case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
8865 	case 0x1BC: case 0x1BE:
8866 		if (!(currprefs.chipset_mask & CSMASK_AGA))
8867 			goto writeonly;
8868 		v = COLOR_READ ((addr & 0x3E) / 2);
8869 		break;
8870 #endif
8871 
8872 	default:
8873 writeonly:
8874 		/* OCS/ECS:
8875 		* reading write-only register causes write with last value in chip
8876 		* bus (custom registers, chipram, slowram)
8877 		* and finally returns either all ones or something weird if DMA happens
8878 		* in next (or previous) cycle.. FIXME.
8879 		*
8880 		* OCS-only special case: DFF000 (BLTDDAT) will always return whatever was left in bus
8881 		*
8882 		* AGA:
8883 		* Can also return last CPU accessed value
8884 		* Remembers old last_custom_value1
8885 		*/
8886 		v = last_custom_value1;
8887 		SET_LINE_CYCLEBASED;
8888 		if (!noput) {
8889 			int r, c, bmdma;
8890 			uae_u16 l;
8891 
8892 			if (currprefs.chipset_mask & CSMASK_AGA) {
8893 				l = 0;
8894 			} else {
8895 				// last chip bus value (read or write) is written to register
8896 				if (currprefs.cpu_compatible && currprefs.cpu_model == 68000) {
8897 					if (isbyte)
8898 						l = (regs.chipset_latch_rw << 8) | (regs.chipset_latch_rw & 0xff);
8899 					else
8900 						l = regs.chipset_latch_rw;
8901 				} else {
8902 					l = regs.chipset_latch_rw;
8903 				}
8904 			}
8905 			decide_line (hpos);
8906 			decide_fetch_safe (hpos);
8907 			debug_wputpeek (0xdff000 + addr, l);
8908 			r = custom_wput_1 (hpos, addr, l, 1);
8909 
8910 			// CPU gets back (OCS/ECS only):
8911 			// - if last cycle was DMA cycle: DMA cycle data
8912 			// - if last cycle was not DMA cycle: FFFF or some ANDed old data.
8913 			//
8914 			c = cycle_line[hpos] & CYCLE_MASK;
8915 			bmdma = is_bitplane_dma(hpos);
8916 			if (currprefs.chipset_mask & CSMASK_AGA) {
8917 				if (bmdma || (c > CYCLE_REFRESH && c < CYCLE_CPU)) {
8918 					v = last_custom_value1;
8919 				} else if (c == CYCLE_CPU) {
8920 					v = regs.db;
8921 				} else {
8922 					v = last_custom_value1 >> ((addr & 2) ? 0 : 16);
8923 				}
8924 			} else {
8925 				if (bmdma || (c > CYCLE_REFRESH && c < CYCLE_CPU)) {
8926 					v = last_custom_value1;
8927 				} else {
8928 					// refresh checked because refresh cycles do not always
8929 					// set last_custom_value1 for performance reasons.
8930 					v = 0xffff;
8931 				}
8932 			}
8933 #if CUSTOM_DEBUG > 0
8934 			write_log (_T("%08X read = %04X. Value written=%04X PC=%08x\n"), 0xdff000 | addr, v, l, M68K_GETPC);
8935 #endif
8936 			return v;
8937 		}
8938 	}
8939 	return v;
8940 }
8941 
8942 static uae_u32 custom_wget2(uaecptr addr, bool byte)
8943 {
8944 	uae_u32 v;
8945 	int hpos = current_hpos ();
8946 
8947 	sync_copper_with_cpu (hpos, 1);
8948 	v = custom_wget_1 (hpos, addr, 0, byte);
8949 #ifdef ACTION_REPLAY
8950 #ifdef ACTION_REPLAY_COMMON
8951 	addr &= 0x1ff;
8952 	ar_custom[addr + 0] = (uae_u8)(v >> 8);
8953 	ar_custom[addr + 1] = (uae_u8)(v);
8954 #endif
8955 #endif
8956 	return v;
8957 }
8958 
8959 static uae_u32 REGPARAM2 custom_wget (uaecptr addr)
8960 {
8961 	uae_u32 v;
8962 
8963 	if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0)
8964 		return dummy_get(addr, 2, false, 0);
8965 	if (addr & 1) {
8966 		/* think about move.w $dff005,d0.. (68020+ only) */
8967 		addr &= ~1;
8968 		v = custom_wget2 (addr, false) << 8;
8969 		v |= custom_wget2 (addr + 2, false) >> 8;
8970 		return v;
8971 	}
8972 	return custom_wget2 (addr, false);
8973 }
8974 
8975 static uae_u32 REGPARAM2 custom_bget (uaecptr addr)
8976 {
8977 	uae_u32 v;
8978 	if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0)
8979 		return dummy_get(addr, 1, false, 0);
8980 	v = custom_wget2 (addr & ~1, true);
8981 	v >>= (addr & 1 ? 0 : 8);
8982 	return v;
8983 }
8984 
8985 static uae_u32 REGPARAM2 custom_lget (uaecptr addr)
8986 {
8987 	if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0)
8988 		return dummy_get(addr, 4, false, 0);
8989 	return ((uae_u32)custom_wget (addr) << 16) | custom_wget (addr + 2);
8990 }
8991 static int REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value, int noget)
8992 {
8993 	addr &= 0x1FE;
8994 	value &= 0xffff;
8995 #ifdef ACTION_REPLAY
8996 #ifdef ACTION_REPLAY_COMMON
8997 	ar_custom[addr+0]=(uae_u8)(value>>8);
8998 	ar_custom[addr+1]=(uae_u8)(value);
8999 #endif
9000 #endif
9001 	switch (addr) {
9002 	case 0x00E: CLXDAT (); break;
9003 
9004 	case 0x020: DSKPTH (value); break;
9005 	case 0x022: DSKPTL (value); break;
9006 	case 0x024: DSKLEN (value, hpos); break;
9007 	case 0x026: /* DSKDAT (value). Writing to DMA write registers won't do anything */; break;
9008 	case 0x028: REFPTR (value); break;
9009 	case 0x02A: VPOSW (value); break;
9010 	case 0x02C: VHPOSW (value); break;
9011 	case 0x02E: COPCON (value); break;
9012 	case 0x030: SERDAT (value); break;
9013 	case 0x032: SERPER (value); break;
9014 	case 0x034: POTGO (value); break;
9015 
9016 	case 0x040: BLTCON0 (hpos, value); break;
9017 	case 0x042: BLTCON1 (hpos, value); break;
9018 
9019 	case 0x044: BLTAFWM (hpos, value); break;
9020 	case 0x046: BLTALWM (hpos, value); break;
9021 
9022 	case 0x050: BLTAPTH (hpos, value); break;
9023 	case 0x052: BLTAPTL (hpos, value); break;
9024 	case 0x04C: BLTBPTH (hpos, value); break;
9025 	case 0x04E: BLTBPTL (hpos, value); break;
9026 	case 0x048: BLTCPTH (hpos, value); break;
9027 	case 0x04A: BLTCPTL (hpos, value); break;
9028 	case 0x054: BLTDPTH (hpos, value); break;
9029 	case 0x056: BLTDPTL (hpos, value); break;
9030 
9031 	case 0x058: BLTSIZE (hpos, value); break;
9032 
9033 	case 0x064: BLTAMOD (hpos, value); break;
9034 	case 0x062: BLTBMOD (hpos, value); break;
9035 	case 0x060: BLTCMOD (hpos, value); break;
9036 	case 0x066: BLTDMOD (hpos, value); break;
9037 
9038 	case 0x070: BLTCDAT (hpos, value); break;
9039 	case 0x072: BLTBDAT (hpos, value); break;
9040 	case 0x074: BLTADAT (hpos, value); break;
9041 
9042 	case 0x07E: DSKSYNC (hpos, value); break;
9043 
9044 	case 0x080: COP1LCH (value); break;
9045 	case 0x082: COP1LCL (value); break;
9046 	case 0x084: COP2LCH (value); break;
9047 	case 0x086: COP2LCL (value); break;
9048 
9049 	case 0x088: COPJMP (1, 0); break;
9050 	case 0x08A: COPJMP (2, 0); break;
9051 
9052 	case 0x08E: DIWSTRT (hpos, value); break;
9053 	case 0x090: DIWSTOP (hpos, value); break;
9054 	case 0x092: DDFSTRT (hpos, value); break;
9055 	case 0x094: DDFSTOP (hpos, value); break;
9056 
9057 	case 0x096: DMACON (hpos, value); break;
9058 	case 0x098: CLXCON (value); break;
9059 	case 0x09A: INTENA (value); break;
9060 	case 0x09C: INTREQ (value); break;
9061 	case 0x09E: ADKCON (hpos, value); break;
9062 
9063 	case 0x0A0: AUDxLCH (0, value); break;
9064 	case 0x0A2: AUDxLCL (0, value); break;
9065 	case 0x0A4: AUDxLEN (0, value); break;
9066 	case 0x0A6: AUDxPER (0, value); break;
9067 	case 0x0A8: AUDxVOL (0, value); break;
9068 	case 0x0AA: AUDxDAT (0, value); break;
9069 
9070 	case 0x0B0: AUDxLCH (1, value); break;
9071 	case 0x0B2: AUDxLCL (1, value); break;
9072 	case 0x0B4: AUDxLEN (1, value); break;
9073 	case 0x0B6: AUDxPER (1, value); break;
9074 	case 0x0B8: AUDxVOL (1, value); break;
9075 	case 0x0BA: AUDxDAT (1, value); break;
9076 
9077 	case 0x0C0: AUDxLCH (2, value); break;
9078 	case 0x0C2: AUDxLCL (2, value); break;
9079 	case 0x0C4: AUDxLEN (2, value); break;
9080 	case 0x0C6: AUDxPER (2, value); break;
9081 	case 0x0C8: AUDxVOL (2, value); break;
9082 	case 0x0CA: AUDxDAT (2, value); break;
9083 
9084 	case 0x0D0: AUDxLCH (3, value); break;
9085 	case 0x0D2: AUDxLCL (3, value); break;
9086 	case 0x0D4: AUDxLEN (3, value); break;
9087 	case 0x0D6: AUDxPER (3, value); break;
9088 	case 0x0D8: AUDxVOL (3, value); break;
9089 	case 0x0DA: AUDxDAT (3, value); break;
9090 
9091 	case 0x0E0: BPLxPTH (hpos, value, 0); break;
9092 	case 0x0E2: BPLxPTL (hpos, value, 0); break;
9093 	case 0x0E4: BPLxPTH (hpos, value, 1); break;
9094 	case 0x0E6: BPLxPTL (hpos, value, 1); break;
9095 	case 0x0E8: BPLxPTH (hpos, value, 2); break;
9096 	case 0x0EA: BPLxPTL (hpos, value, 2); break;
9097 	case 0x0EC: BPLxPTH (hpos, value, 3); break;
9098 	case 0x0EE: BPLxPTL (hpos, value, 3); break;
9099 	case 0x0F0: BPLxPTH (hpos, value, 4); break;
9100 	case 0x0F2: BPLxPTL (hpos, value, 4); break;
9101 	case 0x0F4: BPLxPTH (hpos, value, 5); break;
9102 	case 0x0F6: BPLxPTL (hpos, value, 5); break;
9103 	case 0x0F8: BPLxPTH (hpos, value, 6); break;
9104 	case 0x0FA: BPLxPTL (hpos, value, 6); break;
9105 	case 0x0FC: BPLxPTH (hpos, value, 7); break;
9106 	case 0x0FE: BPLxPTL (hpos, value, 7); break;
9107 
9108 	case 0x100: BPLCON0 (hpos, value); break;
9109 	case 0x102: BPLCON1 (hpos, value); break;
9110 	case 0x104: BPLCON2 (hpos, value); break;
9111 #ifdef ECS_DENISE
9112 	case 0x106: BPLCON3 (hpos, value); break;
9113 #endif
9114 
9115 	case 0x108: BPL1MOD (hpos, value); break;
9116 	case 0x10A: BPL2MOD (hpos, value); break;
9117 #ifdef AGA
9118 	case 0x10E: CLXCON2 (value); break;
9119 #endif
9120 
9121 	case 0x110: BPLxDAT (hpos, 0, value); break;
9122 	case 0x112: BPLxDAT (hpos, 1, value); break;
9123 	case 0x114: BPLxDAT (hpos, 2, value); break;
9124 	case 0x116: BPLxDAT (hpos, 3, value); break;
9125 	case 0x118: BPLxDAT (hpos, 4, value); break;
9126 	case 0x11A: BPLxDAT (hpos, 5, value); break;
9127 	case 0x11C: BPLxDAT (hpos, 6, value); break;
9128 	case 0x11E: BPLxDAT (hpos, 7, value); break;
9129 
9130 	case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
9131 	case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
9132 	case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
9133 	case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
9134 	case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
9135 	case 0x1BC: case 0x1BE:
9136 		COLOR_WRITE (hpos, value & 0xFFF, (addr & 0x3E) / 2);
9137 		break;
9138 	case 0x120: case 0x124: case 0x128: case 0x12C:
9139 	case 0x130: case 0x134: case 0x138: case 0x13C:
9140 		SPRxPTH (hpos, value, (addr - 0x120) / 4);
9141 		break;
9142 	case 0x122: case 0x126: case 0x12A: case 0x12E:
9143 	case 0x132: case 0x136: case 0x13A: case 0x13E:
9144 		SPRxPTL (hpos, value, (addr - 0x122) / 4);
9145 		break;
9146 	case 0x140: case 0x148: case 0x150: case 0x158:
9147 	case 0x160: case 0x168: case 0x170: case 0x178:
9148 		SPRxPOS (hpos, value, (addr - 0x140) / 8);
9149 		break;
9150 	case 0x142: case 0x14A: case 0x152: case 0x15A:
9151 	case 0x162: case 0x16A: case 0x172: case 0x17A:
9152 		SPRxCTL (hpos, value, (addr - 0x142) / 8);
9153 		break;
9154 	case 0x144: case 0x14C: case 0x154: case 0x15C:
9155 	case 0x164: case 0x16C: case 0x174: case 0x17C:
9156 		SPRxDATA (hpos, value, (addr - 0x144) / 8);
9157 		break;
9158 	case 0x146: case 0x14E: case 0x156: case 0x15E:
9159 	case 0x166: case 0x16E: case 0x176: case 0x17E:
9160 		SPRxDATB (hpos, value, (addr - 0x146) / 8);
9161 		break;
9162 
9163 	case 0x36: JOYTEST (value); break;
9164 	case 0x5A: BLTCON0L (hpos, value); break;
9165 	case 0x5C: BLTSIZV (hpos, value); break;
9166 	case 0x5E: BLTSIZH (hpos, value); break;
9167 	case 0x1E4: DIWHIGH (hpos, value); break;
9168 #ifdef AGA
9169 	case 0x10C: BPLCON4 (hpos, value); break;
9170 #endif
9171 
9172 	case 0x1DC: BEAMCON0 (value); break;
9173 	case 0x1C0: if (htotal != value) { htotal = value & (MAXHPOS_ROWS - 1); varsync (); } break;
9174 	case 0x1C2: if (hsstop != value) { hsstop = value & (MAXHPOS_ROWS - 1); varsync (); } break;
9175 	case 0x1C4: if (hbstrt != value) { hbstrt = value & (MAXHPOS_ROWS - 1); varsync (); } break;
9176 	case 0x1C6:	if (hbstop != value) { hbstop = value & (MAXHPOS_ROWS - 1); varsync ();} break;
9177 	case 0x1C8: if (vtotal != value) { vtotal = value & (MAXVPOS_LINES_ECS - 1); varsync (); } break;
9178 	case 0x1CA: if (vsstop != value) { vsstop = value & (MAXVPOS_LINES_ECS - 1); varsync (); } break;
9179 	case 0x1CC: if (vbstrt < value || vbstrt > (value & (MAXVPOS_LINES_ECS - 1)) + 1) { vbstrt = value & (MAXVPOS_LINES_ECS - 1); varsync (); } break;
9180 	case 0x1CE: if (vbstop < value || vbstop > (value & (MAXVPOS_LINES_ECS - 1)) + 1) { vbstop = value & (MAXVPOS_LINES_ECS - 1); varsync (); } break;
9181 	case 0x1DE: if (hsstrt != value) { hsstrt = value & (MAXHPOS_ROWS - 1); varsync (); } break;
9182 	case 0x1E0: if (vsstrt != value) { vsstrt = value & (MAXVPOS_LINES_ECS - 1); varsync (); } break;
9183 	case 0x1E2: if (hcenter != value) { hcenter = value & (MAXHPOS_ROWS - 1); varsync (); } break;
9184 
9185 #ifdef AGA
9186 	case 0x1FC: FMODE (hpos, value); break;
9187 #endif
9188 	case 0x1FE: FNULL (value); break;
9189 
9190 		/* writing to read-only register causes read access */
9191 	default:
9192 		if (!noget) {
9193 #if CUSTOM_DEBUG > 0
9194 			write_log (_T("%04X written %08x\n"), addr, M68K_GETPC);
9195 #endif
9196 			custom_wget_1 (hpos, addr, 1, false);
9197 		}
9198 		return 1;
9199 	}
9200 	return 0;
9201 }
9202 
9203 static void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value)
9204 {
9205 	int hpos = current_hpos ();
9206 
9207 	if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0) {
9208 		dummy_put(addr, 2, value);
9209 		return;
9210 	}
9211 #if CUSTOM_DEBUG > 2
9212 	write_log (_T("%d:%d:wput: %04X %04X pc=%p\n"), hpos, vpos, addr & 0x01fe, value & 0xffff, m68k_getpc ());
9213 #endif
9214 	sync_copper_with_cpu (hpos, 1);
9215 	if (addr & 1) {
9216 		addr &= ~1;
9217 		custom_wput_1 (hpos, addr, (value >> 8) | (value & 0xff00), 0);
9218 		custom_wput_1 (hpos, addr + 2, (value << 8) | (value & 0x00ff), 0);
9219 		return;
9220 	}
9221 	custom_wput_1 (hpos, addr, value, 0);
9222 }
9223 
9224 static void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value)
9225 {
9226 	uae_u16 rval;
9227 
9228 	if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0) {
9229 		dummy_put(addr, 1, value);
9230 		return;
9231 	}
9232 	if (currprefs.chipset_mask & CSMASK_AGA) {
9233 		if (addr & 1) {
9234 			rval = value & 0xff;
9235 		} else {
9236 			rval = (value << 8) | (value & 0xFF);
9237 		}
9238 	} else {
9239 		rval = (value << 8) | (value & 0xff);
9240 	}
9241 
9242 	if (currprefs.cs_bytecustomwritebug) {
9243 		if (addr & 1)
9244 			custom_wput (addr & ~1, rval);
9245 		else
9246 			custom_wput (addr, value << 8);
9247 	} else {
9248 		custom_wput (addr & ~1, rval);
9249 	}
9250 }
9251 
9252 static void REGPARAM2 custom_lput (uaecptr addr, uae_u32 value)
9253 {
9254 	if ((addr & 0xffff) < 0x8000 && currprefs.cs_fatgaryrev >= 0) {
9255 		dummy_put(addr, 4, value);
9256 		return;
9257 	}
9258 	custom_wput (addr & 0xfffe, value >> 16);
9259 	custom_wput ((addr + 2) & 0xfffe, (uae_u16)value);
9260 }
9261 
9262 #ifdef SAVESTATE
9263 
9264 void custom_prepare_savestate (void)
9265 {
9266 	int i;
9267 
9268 	for (i = 0; i < ev2_max; i++) {
9269 		if (eventtab2[i].active) {
9270 			eventtab2[i].active = 0;
9271 			eventtab2[i].handler (eventtab2[i].data);
9272 		}
9273 	}
9274 }
9275 
9276 #define RB restore_u8 ()
9277 #define SRB (uae_s8)restore_u8 ()
9278 #define RBB restore_u8 () != 0
9279 #define RW restore_u16 ()
9280 #define RL restore_u32 ()
9281 
9282 uae_u8 *restore_custom (uae_u8 *src)
9283 {
9284 	uae_u16 dsklen, dskbytr;
9285 	int dskpt;
9286 	int i;
9287 
9288 	audio_reset ();
9289 
9290 	changed_prefs.chipset_mask = currprefs.chipset_mask = RL & CSMASK_MASK;
9291 	update_mirrors ();
9292 	RW;						/* 000 BLTDDAT */
9293 	RW;						/* 002 DMACONR */
9294 	RW;						/* 004 VPOSR */
9295 	RW;						/* 006 VHPOSR */
9296 	RW;						/* 008 DSKDATR (dummy register) */
9297 	JOYSET(0, RW);			/* 00A JOY0DAT */
9298 	JOYSET(1, RW);			/* 00C JOY1DAT */
9299 	clxdat = RW;			/* 00E CLXDAT */
9300 	RW;						/* 010 ADKCONR */
9301 	RW;						/* 012 POT0DAT* */
9302 	RW;						/* 014 POT1DAT* */
9303 	RW;						/* 016 POTINP* */
9304 	RW;						/* 018 SERDATR* */
9305 	dskbytr = RW;			/* 01A DSKBYTR */
9306 	RW;						/* 01C INTENAR */
9307 	RW;						/* 01E INTREQR */
9308 	dskpt = RL;				/* 020-022 DSKPT */
9309 	dsklen = RW;			/* 024 DSKLEN */
9310 	RW;						/* 026 DSKDAT */
9311 	refptr = RW;			/* 028 REFPTR */
9312 	i = RW; lof_store = lof_current = (i & 0x8000) ? 1 : 0; lol = (i & 0x0080) ? 1 : 0; /* 02A VPOSW */
9313 	RW;						/* 02C VHPOSW */
9314 	COPCON (RW);			/* 02E COPCON */
9315 	RW;						/* 030 SERDAT* */
9316 	serper = RW;			/* 032 SERPER* */
9317 	potgo_value = 0; POTGO (RW); /* 034 POTGO */
9318 	RW;						/* 036 JOYTEST* */
9319 	RW;						/* 038 STREQU */
9320 	RW;						/* 03A STRVHBL */
9321 	RW;						/* 03C STRHOR */
9322 	RW;						/* 03E STRLONG */
9323 	BLTCON0 (0, RW);		/* 040 BLTCON0 */
9324 	BLTCON1 (0, RW);		/* 042 BLTCON1 */
9325 	BLTAFWM (0, RW);		/* 044 BLTAFWM */
9326 	BLTALWM (0, RW);		/* 046 BLTALWM */
9327 	BLTCPTH (0, RW);BLTCPTL(0, RW);	/* 048-04B BLTCPT */
9328 	BLTBPTH (0, RW);BLTBPTL(0, RW);	/* 04C-04F BLTBPT */
9329 	BLTAPTH (0, RW);BLTAPTL(0, RW);	/* 050-053 BLTAPT */
9330 	BLTDPTH (0, RW);BLTDPTL(0, RW);	/* 054-057 BLTDPT */
9331 	RW;						/* 058 BLTSIZE */
9332 	RW;						/* 05A BLTCON0L */
9333 	blt_info.vblitsize = RW;/* 05C BLTSIZV */
9334 	blt_info.hblitsize = RW;/* 05E BLTSIZH */
9335 	BLTCMOD (0, RW);		/* 060 BLTCMOD */
9336 	BLTBMOD (0, RW);		/* 062 BLTBMOD */
9337 	BLTAMOD (0, RW);		/* 064 BLTAMOD */
9338 	BLTDMOD (0, RW);		/* 066 BLTDMOD */
9339 	RW;						/* 068 ? */
9340 	RW;						/* 06A ? */
9341 	RW;						/* 06C ? */
9342 	RW;						/* 06E ? */
9343 	BLTCDAT (0, RW);		/* 070 BLTCDAT */
9344 	BLTBDAT (0, RW);		/* 072 BLTBDAT */
9345 	BLTADAT (0, RW);		/* 074 BLTADAT */
9346 	RW;						/* 076 ? */
9347 	RW;						/* 078 ? */
9348 	RW;						/* 07A ? */
9349 	RW;						/* 07C LISAID */
9350 	DSKSYNC (-1, RW);		/* 07E DSKSYNC */
9351 	cop1lc = RL;			/* 080/082 COP1LC */
9352 	cop2lc = RL;			/* 084/086 COP2LC */
9353 	RW;						/* 088 ? */
9354 	RW;						/* 08A ? */
9355 	RW;						/* 08C ? */
9356 	diwstrt = RW;			/* 08E DIWSTRT */
9357 	diwstop = RW;			/* 090 DIWSTOP */
9358 	ddfstrt = RW;			/* 092 DDFSTRT */
9359 	ddfstop = RW;			/* 094 DDFSTOP */
9360 	dmacon = RW & ~(0x2000|0x4000); /* 096 DMACON */
9361 	CLXCON (RW);			/* 098 CLXCON */
9362 	intena = intena_internal = RW;	/* 09A INTENA */
9363 	intreq = RW;			/* 09C INTREQ */
9364 	intreq_internal = intreq;
9365 	adkcon = RW;			/* 09E ADKCON */
9366 	for (i = 0; i < 8; i++)
9367 		bplptx[i] = bplpt[i] = RL;
9368 	bplcon0 = RW;			/* 100 BPLCON0 */
9369 	bplcon1 = RW;			/* 102 BPLCON1 */
9370 	bplcon2 = RW;			/* 104 BPLCON2 */
9371 	bplcon3 = RW;			/* 106 BPLCON3 */
9372 	bpl1mod = RW;			/* 108 BPL1MOD */
9373 	bpl2mod = RW;			/* 10A BPL2MOD */
9374 	bplcon4 = RW;			/* 10C BPLCON4 */
9375 	clxcon2 = RW;			/* 10E CLXCON2* */
9376 	for(i = 0; i < 8; i++)
9377 		fetched[i] = RW;	/*     BPLXDAT */
9378 	for(i = 0; i < 32; i++) {
9379 		uae_u16 v = RW;
9380 		color_regs_genlock[i] = (v & 0x8000) != 0;
9381 		current_colors.color_regs_ecs[i] = v & 0xfff; /* 180 COLORxx */
9382 	}
9383 	htotal = RW;			/* 1C0 HTOTAL */
9384 	hsstop = RW;			/* 1C2 HSTOP ? */
9385 	hbstrt = RW;			/* 1C4 HBSTRT ? */
9386 	hbstop = RW;			/* 1C6 HBSTOP ? */
9387 	vtotal = RW;			/* 1C8 VTOTAL */
9388 	vsstop = RW;			/* 1CA VSSTOP */
9389 	vbstrt = RW;			/* 1CC VBSTRT */
9390 	vbstop = RW;			/* 1CE VBSTOP */
9391 	RW;						/* 1D0 ? */
9392 	RW;						/* 1D2 ? */
9393 	RW;						/* 1D4 ? */
9394 	RW;						/* 1D6 ? */
9395 	RW;						/* 1D8 ? */
9396 	RW;						/* 1DA ? */
9397 	new_beamcon0 = RW;		/* 1DC BEAMCON0 */
9398 	hsstrt = RW;			/* 1DE HSSTRT */
9399 	vsstrt = RW;			/* 1E0 VSSTT  */
9400 	hcenter = RW;			/* 1E2 HCENTER */
9401 	diwhigh = RW;			/* 1E4 DIWHIGH */
9402 	diwhigh_written = (diwhigh & 0x8000) ? 1 : 0;
9403 	hdiwstate = (diwhigh & 0x4000) ? DIW_waiting_stop : DIW_waiting_start;
9404 	diwhigh &= 0x3fff;
9405 	RW;						/* 1E6 ? */
9406 	RW;						/* 1E8 ? */
9407 	RW;						/* 1EA ? */
9408 	RW;						/* 1EC ? */
9409 	RW;						/* 1EE ? */
9410 	RW;						/* 1F0 ? */
9411 	RW;						/* 1F2 ? */
9412 	RW;						/* 1F4 ? */
9413 	RW;						/* 1F6 ? */
9414 	RW;						/* 1F8 ? */
9415 	i = RW;					/* 1FA ? */
9416 	if (i & 0x8000)
9417 		currprefs.ntscmode = changed_prefs.ntscmode = i & 1;
9418 	fmode = fmode_saved = RW; /* 1FC FMODE */
9419 	last_custom_value1 = RW;/* 1FE ? */
9420 
9421 	current_colors.extra = 0;
9422 	if (isbrdblank (-1, bplcon0, bplcon3))
9423 		current_colors.extra |= 1 << CE_BORDERBLANK;
9424 	if (issprbrd(-1, bplcon0, bplcon3))
9425 		current_colors.extra |= 1 << CE_BORDERSPRITE;
9426 	if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) && (bplcon0 & 1) && (bplcon3 & 0x10))
9427 		current_colors.extra |= 1 << CE_BORDERNTRANS;
9428 
9429 	DISK_restore_custom (dskpt, dsklen, dskbytr);
9430 
9431 	return src;
9432 }
9433 
9434 #endif /* SAVESTATE */
9435 
9436 #if defined SAVESTATE || defined DEBUGGER
9437 
9438 #define SB save_u8
9439 #define SW save_u16
9440 #define SL save_u32
9441 
9442 uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
9443 {
9444 	uae_u8 *dstbak, *dst;
9445 	int i, dummy;
9446 	uae_u32 dskpt;
9447 	uae_u16 dsklen, dsksync, dskbytr;
9448 
9449 	DISK_save_custom (&dskpt, &dsklen, &dsksync, &dskbytr);
9450 
9451 	if (dstptr)
9452 		dstbak = dst = dstptr;
9453 	else
9454 		dstbak = dst = xmalloc (uae_u8, 8 + 256 * 2);
9455 
9456 	SL (currprefs.chipset_mask);
9457 	SW (0);					/* 000 BLTDDAT */
9458 	SW (dmacon);			/* 002 DMACONR */
9459 	SW (VPOSR ());			/* 004 VPOSR */
9460 	SW (VHPOSR ());			/* 006 VHPOSR */
9461 	SW (0);					/* 008 DSKDATR */
9462 	SW (JOYGET (0));		/* 00A JOY0DAT */
9463 	SW (JOYGET (1));		/* 00C JOY1DAT */
9464 	SW (clxdat | 0x8000);	/* 00E CLXDAT */
9465 	SW (ADKCONR ());		/* 010 ADKCONR */
9466 	SW (POT0DAT ());		/* 012 POT0DAT */
9467 	SW (POT1DAT ());		/* 014 POT1DAT */
9468 	SW (0)	;				/* 016 POTINP * */
9469 	SW (0);					/* 018 SERDATR * */
9470 	SW (dskbytr);			/* 01A DSKBYTR */
9471 	SW (INTENAR ());		/* 01C INTENAR */
9472 	SW (INTREQR ());		/* 01E INTREQR */
9473 	SL (dskpt);				/* 020-023 DSKPT */
9474 	SW (dsklen);			/* 024 DSKLEN */
9475 	SW (0);					/* 026 DSKDAT */
9476 	SW (refptr);			/* 028 REFPTR */
9477 	SW ((lof_store ? 0x8001 : 0) | (lol ? 0x0080 : 0));/* 02A VPOSW */
9478 	SW (0);					/* 02C VHPOSW */
9479 	SW (copcon);			/* 02E COPCON */
9480 	SW (serdat);			/* 030 SERDAT * */
9481 	SW (serper);			/* 032 SERPER * */
9482 	SW (potgo_value);		/* 034 POTGO */
9483 	SW (0);					/* 036 JOYTEST * */
9484 	SW (0);					/* 038 STREQU */
9485 	SW (0);					/* 03A STRVBL */
9486 	SW (0);					/* 03C STRHOR */
9487 	SW (0);					/* 03E STRLONG */
9488 	SW (bltcon0);			/* 040 BLTCON0 */
9489 	SW (bltcon1);			/* 042 BLTCON1 */
9490 	SW (blt_info.bltafwm);	/* 044 BLTAFWM */
9491 	SW (blt_info.bltalwm);	/* 046 BLTALWM */
9492 	SL (bltcpt);			/* 048-04B BLTCPT */
9493 	SL (bltbpt);			/* 04C-04F BLTCPT */
9494 	SL (bltapt);			/* 050-053 BLTCPT */
9495 	SL (bltdpt);			/* 054-057 BLTCPT */
9496 	SW (0);					/* 058 BLTSIZE */
9497 	SW (0);					/* 05A BLTCON0L (use BLTCON0 instead) */
9498 	SW (blt_info.vblitsize);/* 05C BLTSIZV */
9499 	SW (blt_info.hblitsize);/* 05E BLTSIZH */
9500 	SW (blt_info.bltcmod);	/* 060 BLTCMOD */
9501 	SW (blt_info.bltbmod);	/* 062 BLTBMOD */
9502 	SW (blt_info.bltamod);	/* 064 BLTAMOD */
9503 	SW (blt_info.bltdmod);	/* 066 BLTDMOD */
9504 	SW (0);					/* 068 ? */
9505 	SW (0);					/* 06A ? */
9506 	SW (0);					/* 06C ? */
9507 	SW (0);					/* 06E ? */
9508 	SW (blt_info.bltcdat);	/* 070 BLTCDAT */
9509 	SW (blt_info.bltbdat);	/* 072 BLTBDAT */
9510 	SW (blt_info.bltadat);	/* 074 BLTADAT */
9511 	SW (0);					/* 076 ? */
9512 	SW (0);					/* 078 ? */
9513 	SW (0);					/* 07A ? */
9514 	SW (DENISEID (&dummy));	/* 07C DENISEID/LISAID */
9515 	SW (dsksync);			/* 07E DSKSYNC */
9516 	SL (cop1lc);			/* 080-083 COP1LC */
9517 	SL (cop2lc);			/* 084-087 COP2LC */
9518 	SW (0);					/* 088 ? */
9519 	SW (0);					/* 08A ? */
9520 	SW (0);					/* 08C ? */
9521 	SW (diwstrt);			/* 08E DIWSTRT */
9522 	SW (diwstop);			/* 090 DIWSTOP */
9523 	SW (ddfstrt);			/* 092 DDFSTRT */
9524 	SW (ddfstop);			/* 094 DDFSTOP */
9525 	SW (dmacon);			/* 096 DMACON */
9526 	SW (clxcon);			/* 098 CLXCON */
9527 	SW (intena);			/* 09A INTENA */
9528 	SW (intreq);			/* 09C INTREQ */
9529 	SW (adkcon);			/* 09E ADKCON */
9530 	for (i = 0; full && i < 32; i++)
9531 		SW (0);
9532 	for (i = 0; i < 8; i++)
9533 		SL (bplpt[i]);		/* 0E0-0FE BPLxPT */
9534 	SW (bplcon0);			/* 100 BPLCON0 */
9535 	SW (bplcon1);			/* 102 BPLCON1 */
9536 	SW (bplcon2);			/* 104 BPLCON2 */
9537 	SW (bplcon3);			/* 106 BPLCON3 */
9538 	SW (bpl1mod);			/* 108 BPL1MOD */
9539 	SW (bpl2mod);			/* 10A BPL2MOD */
9540 	SW (bplcon4);			/* 10C BPLCON4 */
9541 	SW (clxcon2);			/* 10E CLXCON2 */
9542 	for (i = 0;i < 8; i++)
9543 		SW (fetched[i]);	/* 110 BPLxDAT */
9544 	if (full) {
9545 		for (i = 0; i < 8; i++) {
9546 			SL (spr[i].pt);	/* 120-13E SPRxPT */
9547 		}
9548 		for (i = 0; i < 8; i++) {
9549 			SW (sprpos[i]);	/* 1x0 SPRxPOS */
9550 			SW (sprctl[i]);	/* 1x2 SPRxPOS */
9551 			SW (sprdata[i][0]);	/* 1x4 SPRxDATA */
9552 			SW (sprdatb[i][0]);	/* 1x6 SPRxDATB */
9553 		}
9554 	}
9555 	for (i = 0; i < 32; i++) {
9556 		if (0) {
9557 #ifdef AGA
9558 		} else if (currprefs.chipset_mask & CSMASK_AGA) {
9559 			uae_u32 v = current_colors.color_regs_aga[i];
9560 			uae_u16 v2;
9561 			v &= 0x00f0f0f0;
9562 			v2 = (v >> 4) & 15;
9563 			v2 |= ((v >> 12) & 15) << 4;
9564 			v2 |= ((v >> 20) & 15) << 8;
9565 			SW (v2);
9566 #endif
9567 		} else {
9568 			uae_u16 v = current_colors.color_regs_ecs[i];
9569 			if (color_regs_genlock[i])
9570 				v |= 0x8000;
9571 			SW (v); /* 180-1BE COLORxx */
9572 		}
9573 	}
9574 	SW (htotal);		/* 1C0 HTOTAL */
9575 	SW (hsstop);		/* 1C2 HSTOP*/
9576 	SW (hbstrt);		/* 1C4 HBSTRT */
9577 	SW (hbstop);		/* 1C6 HBSTOP */
9578 	SW (vtotal);		/* 1C8 VTOTAL */
9579 	SW (vsstop);		/* 1CA VSSTOP */
9580 	SW (vbstrt);		/* 1CC VBSTRT */
9581 	SW (vbstop);		/* 1CE VBSTOP */
9582 	SW (0);			/* 1D0 */
9583 	SW (0);			/* 1D2 */
9584 	SW (0);			/* 1D4 */
9585 	SW (0);			/* 1D6 */
9586 	SW (0);			/* 1D8 */
9587 	SW (0);			/* 1DA */
9588 	SW (beamcon0);		/* 1DC BEAMCON0 */
9589 	SW (hsstrt);		/* 1DE HSSTRT */
9590 	SW (vsstrt);		/* 1E0 VSSTRT */
9591 	SW (hcenter);		/* 1E2 HCENTER */
9592 	SW (diwhigh | (diwhigh_written ? 0x8000 : 0) | (hdiwstate == DIW_waiting_stop ? 0x4000 : 0)); /* 1E4 DIWHIGH */
9593 	SW (0);			/* 1E6 */
9594 	SW (0);			/* 1E8 */
9595 	SW (0);			/* 1EA */
9596 	SW (0);			/* 1EC */
9597 	SW (0);			/* 1EE */
9598 	SW (0);			/* 1F0 */
9599 	SW (0);			/* 1F2 */
9600 	SW (0);			/* 1F4 */
9601 	SW (0);			/* 1F6 */
9602 	SW (0);			/* 1F8 */
9603 	SW (0x8000 | (currprefs.ntscmode ? 1 : 0));			/* 1FA (re-used for NTSC) */
9604 	SW (fmode);			/* 1FC FMODE */
9605 	SW (last_custom_value1);	/* 1FE */
9606 
9607 	*len = dst - dstbak;
9608 	return dstbak;
9609 }
9610 
9611 #endif /* SAVESTATE || DEBUGGER */
9612 
9613 #ifdef SAVESTATE
9614 
9615 uae_u8 *restore_custom_agacolors (uae_u8 *src)
9616 {
9617 	int i;
9618 
9619 	for (i = 0; i < 256; i++) {
9620 #ifdef AGA
9621 		uae_u32 v = RL;
9622 		color_regs_genlock[i] = 0;
9623 		if (v & 0x80000000)
9624 			color_regs_genlock[i] = 1;
9625 		v &= 0x80ffffff;
9626 		current_colors.color_regs_aga[i] = v;
9627 #else
9628 		RL;
9629 #endif
9630 	}
9631 	return src;
9632 }
9633 
9634 uae_u8 *save_custom_agacolors (int *len, uae_u8 *dstptr)
9635 {
9636 	uae_u8 *dstbak, *dst;
9637 	int i;
9638 
9639 	if (dstptr)
9640 		dstbak = dst = dstptr;
9641 	else
9642 		dstbak = dst = xmalloc (uae_u8, 256 * 4);
9643 	for (i = 0; i < 256; i++)
9644 #ifdef AGA
9645 		SL (current_colors.color_regs_aga[i] | (color_regs_genlock[i] ? 0x80000000 : 0));
9646 #else
9647 		SL (0);
9648 #endif
9649 	*len = dst - dstbak;
9650 	return dstbak;
9651 }
9652 
9653 uae_u8 *restore_custom_sprite (int num, uae_u8 *src)
9654 {
9655 	memset (&spr[num], 0, sizeof (struct sprite));
9656 	spr[num].pt = RL;		/* 120-13E SPRxPT */
9657 	sprpos[num] = RW;		/* 1x0 SPRxPOS */
9658 	sprctl[num] = RW;		/* 1x2 SPRxPOS */
9659 	sprdata[num][0] = RW;	/* 1x4 SPRxDATA */
9660 	sprdatb[num][0] = RW;	/* 1x6 SPRxDATB */
9661 	sprdata[num][1] = RW;
9662 	sprdatb[num][1] = RW;
9663 	sprdata[num][2] = RW;
9664 	sprdatb[num][2] = RW;
9665 	sprdata[num][3] = RW;
9666 	sprdatb[num][3] = RW;
9667 	spr[num].armed = RB & 1;
9668 	return src;
9669 }
9670 
9671 uae_u8 *save_custom_sprite (int num, int *len, uae_u8 *dstptr)
9672 {
9673 	uae_u8 *dstbak, *dst;
9674 
9675 	if (dstptr)
9676 		dstbak = dst = dstptr;
9677 	else
9678 		dstbak = dst = xmalloc (uae_u8, 30);
9679 	SL (spr[num].pt);		/* 120-13E SPRxPT */
9680 	SW (sprpos[num]);		/* 1x0 SPRxPOS */
9681 	SW (sprctl[num]);		/* 1x2 SPRxPOS */
9682 	SW (sprdata[num][0]);	/* 1x4 SPRxDATA */
9683 	SW (sprdatb[num][0]);	/* 1x6 SPRxDATB */
9684 	SW (sprdata[num][1]);
9685 	SW (sprdatb[num][1]);
9686 	SW (sprdata[num][2]);
9687 	SW (sprdatb[num][2]);
9688 	SW (sprdata[num][3]);
9689 	SW (sprdatb[num][3]);
9690 	SB (spr[num].armed ? 1 : 0);
9691 	*len = dst - dstbak;
9692 	return dstbak;
9693 }
9694 
9695 uae_u8 *restore_custom_extra (uae_u8 *src)
9696 {
9697 	uae_u32 v = restore_u32 ();
9698 
9699 	if (!(v & 1))
9700 		v = 0;
9701 	currprefs.cs_compatible = changed_prefs.cs_compatible = v >> 24;
9702 	cia_set_overlay ((v & 2) != 0);
9703 
9704 	currprefs.genlock = changed_prefs.genlock = RBB;
9705 	currprefs.cs_rtc = changed_prefs.cs_rtc = RB;
9706 	currprefs.cs_rtc_adjust = changed_prefs.cs_rtc_adjust = RL;
9707 
9708 	currprefs.cs_a1000ram = changed_prefs.cs_a1000ram = RBB;
9709 	currprefs.cs_slowmemisfast = changed_prefs.cs_slowmemisfast = RBB;
9710 
9711 	//currprefs.a2091rom.enabled = changed_prefs.a2091rom.enabled = RBB;
9712 	//currprefs.a4091rom.enabled = changed_prefs.a4091rom.enabled = RBB;
9713 	RBB;
9714 	RBB;
9715 	currprefs.cs_cdtvscsi = changed_prefs.cs_cdtvscsi = RBB;
9716 
9717 	currprefs.cs_pcmcia = changed_prefs.cs_pcmcia = RBB;
9718 	currprefs.cs_ciaatod = changed_prefs.cs_ciaatod = RB;
9719 	currprefs.cs_ciaoverlay = changed_prefs.cs_ciaoverlay = RBB;
9720 
9721 	currprefs.cs_agnusbltbusybug = changed_prefs.cs_agnusbltbusybug = RBB;
9722 	currprefs.cs_denisenoehb = changed_prefs.cs_denisenoehb = RBB;
9723 
9724 	currprefs.cs_agnusrev = changed_prefs.cs_agnusrev = SRB;
9725 	currprefs.cs_deniserev = changed_prefs.cs_deniserev = SRB;
9726 	currprefs.cs_fatgaryrev = changed_prefs.cs_fatgaryrev = SRB;
9727 	currprefs.cs_ramseyrev = changed_prefs.cs_ramseyrev = SRB;
9728 
9729 	currprefs.cs_cd32c2p = changed_prefs.cs_cd32c2p = RBB;
9730 	currprefs.cs_cd32cd = changed_prefs.cs_cd32cd = RBB;
9731 	currprefs.cs_cd32nvram = changed_prefs.cs_cd32nvram = RBB;
9732 	currprefs.cs_cdtvcd = changed_prefs.cs_cdtvcd = RBB;
9733 	currprefs.cs_cdtvram = changed_prefs.cs_cdtvram = RBB;
9734 	currprefs.cs_cdtvcard = changed_prefs.cs_cdtvcard = RB;
9735 
9736 	currprefs.cs_df0idhw = changed_prefs.cs_df0idhw = RBB;
9737 	currprefs.cs_dipagnus = changed_prefs.cs_dipagnus = RBB;
9738 	currprefs.cs_ide = changed_prefs.cs_ide = RB;
9739 	currprefs.cs_mbdmac = changed_prefs.cs_mbdmac = RB;
9740 	currprefs.cs_ksmirror_a8 = changed_prefs.cs_ksmirror_a8 = RBB;
9741 	currprefs.cs_ksmirror_e0 = changed_prefs.cs_ksmirror_e0 = RBB;
9742 	currprefs.cs_resetwarning = changed_prefs.cs_resetwarning = RBB;
9743 	currprefs.cs_z3autoconfig = changed_prefs.cs_z3autoconfig = RBB;
9744 	currprefs.cs_1mchipjumper = changed_prefs.cs_1mchipjumper = RBB;
9745 
9746 	return src;
9747 }
9748 
9749 uae_u8 *save_custom_extra (int *len, uae_u8 *dstptr)
9750 {
9751 	uae_u8 *dstbak, *dst;
9752 
9753 	if (dstptr)
9754 		dstbak = dst = dstptr;
9755 	else
9756 		dstbak = dst = xmalloc (uae_u8, 1000);
9757 
9758 	SL ((currprefs.cs_compatible << 24) | (get_mem_bank_real(0) != &chipmem_bank ? 2 : 0) | 1);
9759 	SB (currprefs.genlock ? 1 : 0);
9760 	SB (currprefs.cs_rtc);
9761 	SL (currprefs.cs_rtc_adjust);
9762 
9763 	SB (currprefs.cs_a1000ram ? 1 : 0);
9764 	SB (currprefs.cs_slowmemisfast ? 1 : 0);
9765 
9766 	SB (cfgfile_board_enabled(&currprefs, ROMTYPE_A2091, 0) ? 1 : 0);
9767 	SB (cfgfile_board_enabled(&currprefs, ROMTYPE_A4091, 0) ? 1 : 0);
9768 	SB (currprefs.cs_cdtvscsi ? 1 : 0);
9769 
9770 	SB (currprefs.cs_pcmcia ? 1 : 0);
9771 	SB (currprefs.cs_ciaatod);
9772 	SB (currprefs.cs_ciaoverlay ? 1 : 0);
9773 
9774 	SB (currprefs.cs_agnusbltbusybug ? 1 : 0);
9775 	SB (currprefs.cs_denisenoehb ? 1 : 0);
9776 
9777 	SB (currprefs.cs_agnusrev);
9778 	SB (currprefs.cs_deniserev);
9779 	SB (currprefs.cs_fatgaryrev);
9780 	SB (currprefs.cs_ramseyrev);
9781 
9782 	SB (currprefs.cs_cd32c2p);
9783 	SB (currprefs.cs_cd32cd);
9784 	SB (currprefs.cs_cd32nvram);
9785 	SB (currprefs.cs_cdtvcd ? 1 : 0);
9786 	SB (currprefs.cs_cdtvram ? 1 : 0);
9787 	SB (currprefs.cs_cdtvcard);
9788 
9789 	SB (currprefs.cs_df0idhw ? 1 : 0);
9790 	SB (currprefs.cs_dipagnus ? 1 : 0);
9791 	SB (currprefs.cs_ide);
9792 	SB (currprefs.cs_mbdmac);
9793 	SB (currprefs.cs_ksmirror_a8 ? 1 : 0);
9794 	SB (currprefs.cs_ksmirror_e0 ? 1 : 0);
9795 	SB (currprefs.cs_resetwarning ? 1 : 0);
9796 	SB (currprefs.cs_z3autoconfig ? 1 : 0);
9797 	SB (currprefs.cs_1mchipjumper ? 1 : 0);
9798 
9799 	*len = dst - dstbak;
9800 	return dstbak;
9801 }
9802 
9803 uae_u8 *restore_custom_event_delay (uae_u8 *src)
9804 {
9805 	if (restore_u32 () != 1)
9806 		return src;
9807 	int cnt = restore_u8 ();
9808 	for (int i = 0; i < cnt; i++) {
9809 		uae_u8 type = restore_u8 ();
9810 		evt e = restore_u64 ();
9811 		uae_u32 data = restore_u32 ();
9812 		if (type == 1)
9813 			event2_newevent_xx (-1, e, data, send_interrupt_do);
9814 	}
9815 	return src;
9816 }
9817 uae_u8 *save_custom_event_delay (int *len, uae_u8 *dstptr)
9818 {
9819 	uae_u8 *dstbak, *dst;
9820 	int cnt = 0;
9821 
9822 	for (int i = ev2_misc; i < ev2_max; i++) {
9823 		struct ev2 *e = &eventtab2[i];
9824 		if (e->active && e->handler == send_interrupt_do) {
9825 			cnt++;
9826 		}
9827 	}
9828 	if (cnt == 0)
9829 		return NULL;
9830 
9831 	if (dstptr)
9832 		dstbak = dst = dstptr;
9833 	else
9834 		dstbak = dst = xmalloc (uae_u8, 1000);
9835 
9836 	save_u32 (1);
9837 	save_u8 (cnt);
9838 	for (int i = ev2_misc; i < ev2_max; i++) {
9839 		struct ev2 *e = &eventtab2[i];
9840 		if (e->active && e->handler == send_interrupt_do) {
9841 			save_u8 (1);
9842 			save_u64 (e->evtime - get_cycles ());
9843 			save_u32 (e->data);
9844 
9845 		}
9846 	}
9847 
9848 	*len = dst - dstbak;
9849 	return dstbak;
9850 }
9851 
9852 
9853 uae_u8 *save_cycles (int *len, uae_u8 *dstptr)
9854 {
9855 	uae_u8 *dstbak, *dst;
9856 	if (dstptr)
9857 		dstbak = dst = dstptr;
9858 	else
9859 		dstbak = dst = xmalloc (uae_u8, 1000);
9860 	save_u32 (1);
9861 	save_u32 (CYCLE_UNIT);
9862 	save_u64 (get_cycles ());
9863 	save_u32 (extra_cycle);
9864 	write_log (_T("SAVECYCLES %08lX\n"), get_cycles ());
9865 	*len = dst - dstbak;
9866 	return dstbak;
9867 }
9868 
9869 uae_u8 *restore_cycles (uae_u8 *src)
9870 {
9871 	if (restore_u32 () != 1)
9872 		return src;
9873 	restore_u32 ();
9874 	start_cycles = restore_u64 ();
9875 	extra_cycle = restore_u32 ();
9876 	if (extra_cycle < 0 || extra_cycle >= 2 * CYCLE_UNIT)
9877 		extra_cycle = 0;
9878 	write_log (_T("RESTORECYCLES %08lX\n"), start_cycles);
9879 	return src;
9880 }
9881 
9882 #endif /* SAVESTATE */
9883 
9884 void check_prefs_changed_custom (void)
9885 {
9886 	if (!config_changed)
9887 		return;
9888 	currprefs.gfx_framerate = changed_prefs.gfx_framerate;
9889 	if (currprefs.turbo_emulation_limit != changed_prefs.turbo_emulation_limit) {
9890 		currprefs.turbo_emulation_limit = changed_prefs.turbo_emulation_limit;
9891 		if (changed_prefs.turbo_emulation) {
9892 			warpmode (changed_prefs.turbo_emulation);
9893 		}
9894 	}
9895 	if (currprefs.turbo_emulation != changed_prefs.turbo_emulation)
9896 		warpmode (changed_prefs.turbo_emulation);
9897 	if (inputdevice_config_change_test ())
9898 		inputdevice_copyconfig (&changed_prefs, &currprefs);
9899 	currprefs.immediate_blits = changed_prefs.immediate_blits;
9900 	currprefs.waiting_blits = changed_prefs.waiting_blits;
9901 	currprefs.collision_level = changed_prefs.collision_level;
9902 
9903 	currprefs.cs_ciaatod = changed_prefs.cs_ciaatod;
9904 	currprefs.cs_rtc = changed_prefs.cs_rtc;
9905 	currprefs.cs_cd32cd = changed_prefs.cs_cd32cd;
9906 	currprefs.cs_cd32c2p = changed_prefs.cs_cd32c2p;
9907 	currprefs.cs_cd32nvram = changed_prefs.cs_cd32nvram;
9908 	currprefs.cs_cdtvcd = changed_prefs.cs_cdtvcd;
9909 	currprefs.cs_ide = changed_prefs.cs_ide;
9910 	currprefs.cs_pcmcia = changed_prefs.cs_pcmcia;
9911 	currprefs.cs_fatgaryrev = changed_prefs.cs_fatgaryrev;
9912 	currprefs.cs_ramseyrev = changed_prefs.cs_ramseyrev;
9913 	currprefs.cs_agnusrev = changed_prefs.cs_agnusrev;
9914 	currprefs.cs_deniserev = changed_prefs.cs_deniserev;
9915 	currprefs.cs_mbdmac = changed_prefs.cs_mbdmac;
9916 	currprefs.cs_df0idhw = changed_prefs.cs_df0idhw;
9917 	currprefs.cs_slowmemisfast = changed_prefs.cs_slowmemisfast;
9918 	currprefs.cs_dipagnus = changed_prefs.cs_dipagnus;
9919 	currprefs.cs_denisenoehb = changed_prefs.cs_denisenoehb;
9920 	currprefs.cs_z3autoconfig = changed_prefs.cs_z3autoconfig;
9921 
9922 	if (currprefs.chipset_mask != changed_prefs.chipset_mask ||
9923 		currprefs.picasso96_nocustom != changed_prefs.picasso96_nocustom ||
9924 		currprefs.ntscmode != changed_prefs.ntscmode) {
9925 			currprefs.picasso96_nocustom = changed_prefs.picasso96_nocustom;
9926 			currprefs.chipset_mask = changed_prefs.chipset_mask;
9927 			if (currprefs.ntscmode != changed_prefs.ntscmode) {
9928 				currprefs.ntscmode = changed_prefs.ntscmode;
9929 				new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20;
9930 			}
9931 			init_custom ();
9932 	}
9933 #ifdef GFXFILTER
9934 	struct gfx_filterdata *fd = &currprefs.gf[0];
9935 	struct gfx_filterdata *fdcp = &changed_prefs.gf[0];
9936 
9937 	fd->gfx_filter_horiz_zoom = fdcp->gfx_filter_horiz_zoom;
9938 	fd->gfx_filter_vert_zoom = fdcp->gfx_filter_vert_zoom;
9939 	fd->gfx_filter_horiz_offset = fdcp->gfx_filter_horiz_offset;
9940 	fd->gfx_filter_vert_offset = fdcp->gfx_filter_vert_offset;
9941 	fd->gfx_filter_scanlines = fdcp->gfx_filter_scanlines;
9942 
9943 	fd->gfx_filter_left_border = fdcp->gfx_filter_left_border;
9944 	fd->gfx_filter_right_border = fdcp->gfx_filter_right_border;
9945 	fd->gfx_filter_top_border = fdcp->gfx_filter_top_border;
9946 	fd->gfx_filter_bottom_border = fdcp->gfx_filter_bottom_border;
9947 #endif
9948 }
9949 
9950 #ifdef CPUEMU_13
9951 
9952 STATIC_INLINE void sync_copper (int hpos)
9953 {
9954 	if (copper_enabled_thisline)
9955 		update_copper (hpos);
9956 }
9957 
9958 STATIC_INLINE void decide_fetch_ce (int hpos)
9959 {
9960 	if ((line_cyclebased || blitter_dangerous_bpl) && vpos < current_maxvpos ())
9961 		decide_fetch (hpos);
9962 }
9963 
9964 #define BLIT_NASTY 4
9965 
9966 // blitter not in nasty mode = CPU gets one cycle if it has been waiting
9967 // at least 4 cycles (all DMA cycles count, not just blitter cycles, even
9968 // blitter idle cycles do count!)
9969 
9970 extern int cpu_tracer;
9971 static int dma_cycle (void)
9972 {
9973 	int hpos, hpos_old;
9974 
9975 	blitter_nasty = 1;
9976 	if (cpu_tracer  < 0)
9977 		return current_hpos ();
9978 	if (!currprefs.cpu_memory_cycle_exact)
9979 		return current_hpos ();
9980 	while (currprefs.cpu_memory_cycle_exact) {
9981 		int bpldma;
9982 		int blitpri = dmacon & DMA_BLITPRI;
9983 		hpos_old = current_hpos ();
9984 		hpos = hpos_old + 1;
9985 		decide_line (hpos);
9986 		sync_copper (hpos);
9987 		decide_fetch_ce (hpos);
9988 		bpldma = is_bitplane_dma (hpos_old);
9989 		if (bltstate != BLT_done) {
9990 			if (!blitpri && blitter_nasty >= BLIT_NASTY && (cycle_line[hpos_old] & CYCLE_MASK) == 0 && !bpldma) {
9991 				alloc_cycle (hpos_old, CYCLE_CPUNASTY);
9992 				break;
9993 			}
9994 			decide_blitter (hpos);
9995 			// copper may have been waiting for the blitter
9996 			sync_copper (hpos);
9997 		}
9998 		if ((cycle_line[hpos_old] & CYCLE_MASK) == 0 && !bpldma) {
9999 			alloc_cycle (hpos_old, CYCLE_CPU);
10000 			break;
10001 		}
10002 		do_cycles (1 * CYCLE_UNIT);
10003 		/* bus was allocated to dma channel, wait for next cycle.. */
10004 	}
10005 	return hpos_old;
10006 }
10007 
10008 STATIC_INLINE void checknasty (int hpos, int vpos)
10009 {
10010 	if (blitter_nasty >= BLIT_NASTY && !(dmacon & DMA_BLITPRI))
10011 		record_dma_event (DMA_EVENT_BLITNASTY, hpos, vpos);
10012 }
10013 
10014 static void sync_ce020 (void)
10015 {
10016 	unsigned long c;
10017 	int extra;
10018 
10019 	c = get_cycles ();
10020 	extra = c & (CYCLE_UNIT - 1);
10021 	if (extra) {
10022 		extra = CYCLE_UNIT - extra;
10023 		do_cycles (extra);
10024 	}
10025 }
10026 
10027 #define SETIFCHIP \
10028 	if (addr < 0xd80000) \
10029 		last_custom_value1 = v;
10030 
10031 uae_u32 wait_cpu_cycle_read (uaecptr addr, int mode)
10032 {
10033 	uae_u32 v = 0;
10034 	int hpos;
10035 
10036 	hpos = dma_cycle ();
10037 	x_do_cycles_pre (CYCLE_UNIT);
10038 
10039 #ifdef DEBUGGER
10040 	struct dma_rec *dr = NULL;
10041 	if (debug_dma) {
10042 		int reg = 0x1000;
10043 		if (mode < 0)
10044 			reg |= 4;
10045 		else if (mode > 0)
10046 			reg |= 2;
10047 		else
10048 			reg |= 1;
10049 		dr = record_dma (reg, v, addr, hpos, vpos, mode == -2 || mode == 2 ? DMARECORD_CPU_I : DMARECORD_CPU_D);
10050 		checknasty (hpos, vpos);
10051 	}
10052 #endif
10053 	switch(mode)
10054 	{
10055 		case -1:
10056 		v = get_long(addr);
10057 		break;
10058 		case -2:
10059 		v = get_longi(addr);
10060 		break;
10061 		case 1:
10062 		v = get_word(addr);
10063 		break;
10064 		case 2:
10065 		v = get_wordi(addr);
10066 		break;
10067 		case 0:
10068 		v = get_byte(addr);
10069 		break;
10070 	}
10071 
10072 #ifdef DEBUGGER
10073 	if (debug_dma)
10074 		dr->dat = v;
10075 #endif
10076 
10077 	x_do_cycles_post (CYCLE_UNIT, v);
10078 
10079 	regs.chipset_latch_rw = regs.chipset_latch_read = v;
10080 	SETIFCHIP
10081 	return v;
10082 }
10083 
10084 uae_u32 wait_cpu_cycle_read_ce020 (uaecptr addr, int mode)
10085 {
10086 	uae_u32 v = 0;
10087 	int hpos;
10088 
10089 	sync_ce020 ();
10090 	hpos = dma_cycle ();
10091 	x_do_cycles_pre (CYCLE_UNIT);
10092 
10093 #ifdef DEBUGGER
10094 	struct dma_rec *dr = NULL;
10095 	if (debug_dma) {
10096 		int reg = 0x1000;
10097 		if (mode < 0)
10098 			reg |= 4;
10099 		else if (mode > 0)
10100 			reg |= 2;
10101 		else
10102 			reg |= 1;
10103 		dr = record_dma (reg, v, addr, hpos, vpos, mode == -2 || mode == 2 ? DMARECORD_CPU_I : DMARECORD_CPU_D);
10104 		checknasty (hpos, vpos);
10105 	}
10106 #endif
10107 	switch (mode) {
10108 		case -1:
10109 		v = get_long(addr);
10110 		break;
10111 		case -2:
10112 		v = get_longi(addr);
10113 		break;
10114 		case 1:
10115 		v = get_word(addr);
10116 		break;
10117 		case 2:
10118 		v = get_wordi(addr);
10119 		break;
10120 		case 0:
10121 		v = get_byte(addr);
10122 		break;
10123 	}
10124 
10125 #ifdef DEBUGGER
10126 	if (debug_dma)
10127 		dr->dat = v;
10128 #endif
10129 	if (currprefs.cpu_model == 68020)
10130 		x_do_cycles_post (CYCLE_UNIT / 2, v);
10131 
10132 	regs.chipset_latch_rw = regs.chipset_latch_read = v;
10133 	SETIFCHIP
10134 	return v;
10135 }
10136 
10137 void wait_cpu_cycle_write (uaecptr addr, int mode, uae_u32 v)
10138 {
10139 	int hpos;
10140 
10141 	hpos = dma_cycle ();
10142 	x_do_cycles_pre (CYCLE_UNIT);
10143 
10144 #ifdef DEBUGGER
10145 	if (debug_dma) {
10146 		int reg = 0x1100;
10147 		if (mode < 0)
10148 			reg |= 4;
10149 		else if (mode > 0)
10150 			reg |= 2;
10151 		else
10152 			reg |= 1;
10153 		record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU_D);
10154 		checknasty (hpos, vpos);
10155 	}
10156 #endif
10157 
10158 	if (mode < 0)
10159 		put_long (addr, v);
10160 	else if (mode > 0)
10161 		put_word (addr, v);
10162 	else if (mode == 0)
10163 		put_byte (addr, v);
10164 
10165 	x_do_cycles_post (CYCLE_UNIT, v);
10166 
10167 	regs.chipset_latch_rw = regs.chipset_latch_write = v;
10168 	SETIFCHIP
10169 }
10170 
10171 void wait_cpu_cycle_write_ce020 (uaecptr addr, int mode, uae_u32 v)
10172 {
10173 	int hpos;
10174 
10175 	sync_ce020 ();
10176 	hpos = dma_cycle ();
10177 	x_do_cycles_pre (CYCLE_UNIT);
10178 
10179 #ifdef DEBUGGER
10180 	if (debug_dma) {
10181 		int reg = 0x1100;
10182 		if (mode < 0)
10183 			reg |= 4;
10184 		else if (mode > 0)
10185 			reg |= 2;
10186 		else
10187 			reg |= 1;
10188 		record_dma (reg, v, addr, hpos, vpos, DMARECORD_CPU_D);
10189 		checknasty (hpos, vpos);
10190 	}
10191 #endif
10192 
10193 	if (mode < 0)
10194 		put_long (addr, v);
10195 	else if (mode > 0)
10196 		put_word (addr, v);
10197 	else if (mode == 0)
10198 		put_byte (addr, v);
10199 
10200 	if (currprefs.cpu_model == 68020)
10201 		x_do_cycles_post (CYCLE_UNIT / 2, v);
10202 
10203 	regs.chipset_latch_rw = regs.chipset_latch_write = v;
10204 	SETIFCHIP
10205 }
10206 
10207 void do_cycles_ce (unsigned long cycles)
10208 {
10209 	cycles += extra_cycle;
10210 	while (cycles >= CYCLE_UNIT) {
10211 		int hpos = current_hpos () + 1;
10212 		decide_line (hpos);
10213 		sync_copper (hpos);
10214 		decide_fetch_ce (hpos);
10215 		if (bltstate != BLT_done)
10216 			decide_blitter (hpos);
10217 		do_cycles (1 * CYCLE_UNIT);
10218 		cycles -= CYCLE_UNIT;
10219 	}
10220 	extra_cycle = cycles;
10221 }
10222 
10223 void do_cycles_ce020 (unsigned long cycles)
10224 {
10225 	unsigned long c;
10226 	int extra;
10227 
10228 	if (!cycles)
10229 		return;
10230 	c = get_cycles ();
10231 	extra = c & (CYCLE_UNIT - 1);
10232 	if (extra) {
10233 		extra = CYCLE_UNIT - extra;
10234 		if (extra >= cycles) {
10235 			do_cycles (cycles);
10236 			return;
10237 		}
10238 		do_cycles (extra);
10239 		cycles -= extra;
10240 	}
10241 	c = cycles;
10242 	while (c) {
10243 		int hpos = current_hpos () + 1;
10244 		decide_line (hpos);
10245 		sync_copper (hpos);
10246 		decide_fetch_ce (hpos);
10247 		if (bltstate != BLT_done)
10248 			decide_blitter (hpos);
10249 		if (c < CYCLE_UNIT)
10250 			break;
10251 		do_cycles (1 * CYCLE_UNIT);
10252 		c -= CYCLE_UNIT;
10253 	}
10254 	if (c > 0)
10255 		do_cycles (c);
10256 }
10257 
10258 
10259 int is_cycle_ce (void)
10260 {
10261 	int hpos = current_hpos ();
10262 	return cycle_line[hpos] & CYCLE_MASK;
10263 }
10264 
10265 #endif
10266 
10267 bool isvga(void)
10268 {
10269 	if (!(beamcon0 & 0x80))
10270 		return false;
10271 	if (hblank_hz >= 20000)
10272 		return true;
10273 	return false;
10274 }
10275 
10276 bool ispal(void)
10277 {
10278 	if (beamcon0 & 0x80)
10279 		return currprefs.ntscmode == 0;
10280 	return maxvpos_display >= MAXVPOS_NTSC + (MAXVPOS_PAL - MAXVPOS_NTSC) / 2;
10281 }
10282