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