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-2002 Toni Wilen
9   */
10 
11 #include "sysconfig.h"
12 #include "sysdeps.h"
13 
14 #include <ctype.h>
15 #include <assert.h>
16 
17 #include "options.h"
18 #include "threaddep/thread.h"
19 #include "uae.h"
20 #include "gensound.h"
21 #include "sounddep/sound.h"
22 #include "events.h"
23 #include "memory.h"
24 #include "custom.h"
25 #include "newcpu.h"
26 #include "cia.h"
27 #include "disk.h"
28 #include "blitter.h"
29 #include "xwin.h"
30 #include "audio.h"
31 #include "serial.h"
32 #include "osemu.h"
33 #include "traps.h"
34 #include "autoconf.h"
35 #include "inputdevice.h"
36 #include "keybuf.h"
37 #include "gui.h"
38 #include "picasso96.h"
39 #include "drawing.h"
40 #include "savestate.h"
41 #include "gayle.h"
42 
43 #define SPR0_HPOS 0x15
44 
45 #define SPRITE_COLLISIONS
46 
47 static uae_u16 last_custom_value;
48 
49 static unsigned int n_consecutive_skipped = 0;
50 static unsigned int total_skipped = 0;
51 
52 int vpos;
53 static uae_u16 lof;
54 static int next_lineno;
55 static enum nln_how nextline_how;
56 static int lof_changed = 0;
57 
58 static uae_u32 sprtaba[256],sprtabb[256];
59 static uae_u32 sprite_ab_merge[256];
60 /* Tables for collision detection.  */
61 static uae_u32 sprclx[16], clxmask[16];
62 
63 /*
64  * Hardware registers of all sorts.
65  */
66 
67 static void custom_wput_1 (int, uaecptr, uae_u32) REGPARAM;
68 
69 static uae_u16 cregs[256];
70 
71 uae_u16 intena,intreq;
72 uae_u16 dmacon;
73 uae_u16 adkcon; /* used by audio code */
74 
75 static uae_u32 cop1lc,cop2lc,copcon;
76 
77 int maxhpos = MAXHPOS_PAL;
78 int maxvpos = MAXVPOS_PAL;
79 int minfirstline = VBLANK_ENDLINE_PAL;
80 int vblank_hz = VBLANK_HZ_PAL;
81 static int fmode;
82 static unsigned int beamcon0, new_beamcon0;
83 uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL;
84 static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter;
85 
86 #define HSYNCTIME (maxhpos * CYCLE_UNIT)
87 
88 #define MAX_SPRITES 8
89 
90 /* This is but an educated guess. It seems to be correct, but this stuff
91  * isn't documented well. */
92 enum sprstate { SPR_restart, SPR_waiting_start, SPR_waiting_stop };
93 
94 struct sprite {
95     uaecptr pt;
96     int xpos;
97     int vstart;
98     int vstop;
99     int armed;
100     enum sprstate state;
101 };
102 
103 static struct sprite spr[MAX_SPRITES];
104 
105 static int sprite_vblank_endline = 25;
106 
107 static unsigned int sprctl[MAX_SPRITES], sprpos[MAX_SPRITES];
108 static uae_u16 sprdata[MAX_SPRITES][4], sprdatb[MAX_SPRITES][4];
109 static int sprite_last_drawn_at[MAX_SPRITES];
110 static int last_sprite_point, nr_armed;
111 static int sprite_width, sprres, sprite_buffer_res;
112 
113 static uae_u32 bpl1dat, bpl2dat, bpl3dat, bpl4dat, bpl5dat, bpl6dat, bpl7dat, bpl8dat;
114 static uae_s16 bpl1mod, bpl2mod;
115 
116 static uaecptr bplpt[8];
117 uae_u8 *real_bplpt[8];
118 /* Used as a debugging aid, to offset any bitplane temporarily.  */
119 int bpl_off[8];
120 
121 /*static int blitcount[256];  blitter debug */
122 
123 static struct color_entry current_colors;
124 static unsigned int bplcon0, bplcon1, bplcon2, bplcon3, bplcon4;
125 static unsigned int diwstrt, diwstop, diwhigh;
126 static int diwhigh_written;
127 static int ddfstrt, ddfstop;
128 
129 /* The display and data fetch windows */
130 
131 enum diw_states
132 {
133     DIW_waiting_start, DIW_waiting_stop
134 };
135 
136 int plffirstline, plflastline, plfstrt, plfstop;
137 static int last_diw_pix_hpos, last_ddf_pix_hpos, last_decide_line_hpos;
138 static int last_fetch_hpos, last_sprite_hpos;
139 int diwfirstword, diwlastword;
140 static enum diw_states diwstate, hdiwstate, ddfstate;
141 
142 /* Sprite collisions */
143 static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match;
144 static int clx_sprmask;
145 
146 enum copper_states {
147     COP_stop,
148     COP_read1_in2,
149     COP_read1_wr_in4,
150     COP_read1_wr_in2,
151     COP_read1,
152     COP_read2_wr_in2,
153     COP_read2,
154     COP_bltwait,
155     COP_wait_in4,
156     COP_wait_in2,
157     COP_skip_in4,
158     COP_skip_in2,
159     COP_wait1,
160     COP_wait
161 };
162 
163 struct copper {
164     /* The current instruction words.  */
165     unsigned int i1, i2;
166     unsigned int saved_i1, saved_i2;
167     enum copper_states state;
168     /* Instruction pointer.  */
169     uaecptr ip, saved_ip;
170     int hpos, vpos;
171     unsigned int ignore_next;
172     int vcmp, hcmp;
173 
174     int strobe; /* COPJMP1 / COPJMP2 accessed */
175     int last_write, last_write_hpos;
176 };
177 
178 static struct copper cop_state;
179 static int copper_enabled_thisline;
180 static int cop_min_waittime;
181 
182 /*
183  * Statistics
184  */
185 
186 /* Used also by bebox.cpp */
187 unsigned long int msecs = 0, frametime = 0, lastframetime = 0, timeframes = 0;
188 static unsigned long int seconds_base;
189 int bogusframe;
190 int n_frames;
191 
192 #define DEBUG_COPPER 0
193 #if DEBUG_COPPER
194 /* 10000 isn't enough!  */
195 #define NR_COPPER_RECORDS 40000
196 #else
197 #define NR_COPPER_RECORDS 1
198 #endif
199 
200 /* Record copper activity for the debugger.  */
201 struct cop_record
202 {
203   int hpos, vpos;
204   uaecptr addr;
205 };
206 static struct cop_record cop_record[2][NR_COPPER_RECORDS];
207 static int nr_cop_records[2];
208 static int curr_cop_set;
209 
210 /* Recording of custom chip register changes.  */
211 static int current_change_set;
212 
213 #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
214 /* sam: Those arrays uses around 7Mb of BSS... That seems  */
215 /* too much for AmigaDOS (uae crashes as soon as one loads */
216 /* it. So I use a different strategy here (realloc the     */
217 /* arrays when needed. That strategy might be usefull for  */
218 /* computer with low memory.                               */
219 struct sprite_entry  *sprite_entries[2];
220 struct color_change *color_changes[2];
221 static int max_sprite_entry = 400;
222 static int delta_sprite_entry = 0;
223 static int max_color_change = 400;
224 static int delta_color_change = 0;
225 #else
226 struct sprite_entry sprite_entries[2][MAX_SPR_PIXELS / 16];
227 struct color_change color_changes[2][MAX_REG_CHANGE];
228 #endif
229 
230 struct decision line_decisions[2 * (MAXVPOS + 1) + 1];
231 struct draw_info line_drawinfo[2][2 * (MAXVPOS + 1) + 1];
232 struct color_entry color_tables[2][(MAXVPOS + 1) * 2];
233 
234 static int next_sprite_entry = 0;
235 static int prev_next_sprite_entry;
236 static int next_sprite_forced = 1;
237 
238 struct sprite_entry *curr_sprite_entries, *prev_sprite_entries;
239 struct color_change *curr_color_changes, *prev_color_changes;
240 struct draw_info *curr_drawinfo, *prev_drawinfo;
241 struct color_entry *curr_color_tables, *prev_color_tables;
242 
243 static int next_color_change;
244 static int next_color_entry, remembered_color_entry;
245 static int color_src_match, color_dest_match, color_compare_result;
246 
247 static uae_u32 thisline_changed;
248 
249 #ifdef SMART_UPDATE
250 #define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0)
251 #else
252 #define MARK_LINE_CHANGED do { ; } while (0)
253 #endif
254 
255 static struct decision thisline_decision;
256 static int passed_plfstop, fetch_cycle;
257 
258 enum fetchstate {
259     fetch_not_started,
260     fetch_started,
261     fetch_was_plane0
262 } fetch_state;
263 
264 /*
265  * helper functions
266  */
267 
nodraw(void)268 STATIC_INLINE int nodraw (void)
269 {
270     return framecnt != 0 || !curr_gfx;
271 }
272 
get_copper_address(int copno)273 uae_u32 get_copper_address (int copno)
274 {
275     switch (copno) {
276     case 1: return cop1lc;
277     case 2: return cop2lc;
278     default: return 0;
279     }
280 }
281 
record_copper(uaecptr addr,int hpos,int vpos)282 STATIC_INLINE void record_copper (uaecptr addr, int hpos, int vpos)
283 {
284 #if DEBUG_COPPER
285     int t = nr_cop_records[curr_cop_set];
286     if (t < NR_COPPER_RECORDS) {
287 	cop_record[curr_cop_set][t].addr = addr;
288 	cop_record[curr_cop_set][t].hpos = hpos;
289 	cop_record[curr_cop_set][t].vpos = vpos;
290 	nr_cop_records[curr_cop_set] = t + 1;
291     }
292 #endif
293 }
294 
find_copper_record(uaecptr addr,int * phpos,int * pvpos)295 int find_copper_record (uaecptr addr, int *phpos, int *pvpos)
296 {
297     int s = curr_cop_set ^ 1;
298     int t = nr_cop_records[s];
299     int i;
300     for (i = 0; i < t; i++) {
301 	if (cop_record[s][i].addr == addr) {
302 	    *phpos = cop_record[s][i].hpos;
303 	    *pvpos = cop_record[s][i].vpos;
304 	    return 1;
305 	}
306     }
307     return 0;
308 }
309 
setclr(uae_u16 * p,uae_u16 val)310 STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val)
311 {
312     if (val & 0x8000)
313 	*p |= val & 0x7FFF;
314     else
315 	*p &= ~val;
316 }
317 
current_hpos(void)318 __inline__ int current_hpos (void)
319 {
320     return (get_cycles () - eventtab[ev_hsync].oldcycles) / CYCLE_UNIT;
321 }
322 
pfield_xlateptr(uaecptr plpt,int bytecount)323 STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount)
324 {
325     if (!chipmem_bank.check (plpt, bytecount)) {
326 	static int count = 0;
327 	if (!count)
328 	    count++, write_log ("Warning: Bad playfield pointer\n");
329 	return NULL;
330     }
331     return chipmem_bank.xlateaddr (plpt);
332 }
333 
docols(struct color_entry * colentry)334 STATIC_INLINE void docols (struct color_entry *colentry)
335 {
336     int i;
337 
338     if (currprefs.chipset_mask & CSMASK_AGA) {
339 	for (i = 0; i < 256; i++) {
340 	    int v = color_reg_get (colentry, i);
341 	    if (v < 0 || v > 16777215)
342 		continue;
343 	    colentry->acolors[i] = CONVERT_RGB (v);
344 	}
345     } else {
346 	for (i = 0; i < 32; i++) {
347 	    int v = color_reg_get (colentry, i);
348 	    if (v < 0 || v > 4095)
349 		continue;
350 	    colentry->acolors[i] = xcolors[v];
351 	}
352     }
353 }
354 
notice_new_xcolors(void)355 void notice_new_xcolors (void)
356 {
357     int i;
358 
359     docols(&current_colors);
360 /*    docols(&colors_for_drawing);*/
361     for (i = 0; i < (MAXVPOS + 1)*2; i++) {
362 	docols(color_tables[0]+i);
363 	docols(color_tables[1]+i);
364     }
365 }
366 
367 static void do_sprites (int currhp);
368 
remember_ctable(void)369 static void remember_ctable (void)
370 {
371     if (remembered_color_entry == -1) {
372 	/* The colors changed since we last recorded a color map. Record a
373 	 * new one. */
374 	color_reg_cpy (curr_color_tables + next_color_entry, &current_colors);
375 	remembered_color_entry = next_color_entry++;
376     }
377     thisline_decision.ctable = remembered_color_entry;
378     if (color_src_match == -1 || color_dest_match != remembered_color_entry
379 	|| line_decisions[next_lineno].ctable != color_src_match)
380     {
381 	/* The remembered comparison didn't help us - need to compare again. */
382 	int oldctable = line_decisions[next_lineno].ctable;
383 	int changed = 0;
384 
385 	if (oldctable == -1) {
386 	    changed = 1;
387 	    color_src_match = color_dest_match = -1;
388 	} else {
389 	    color_compare_result = color_reg_cmp (&prev_color_tables[oldctable], &current_colors) != 0;
390 	    if (color_compare_result)
391 		changed = 1;
392 	    color_src_match = oldctable;
393 	    color_dest_match = remembered_color_entry;
394 	}
395 	thisline_changed |= changed;
396     } else {
397 	/* We know the result of the comparison */
398 	if (color_compare_result)
399 	    thisline_changed = 1;
400     }
401 }
402 
remember_ctable_for_border(void)403 static void remember_ctable_for_border (void)
404 {
405     remember_ctable ();
406 }
407 
408 /* Called to determine the state of the horizontal display window state
409  * machine at the current position. It might have changed since we last
410  * checked.  */
decide_diw(int hpos)411 static void decide_diw (int hpos)
412 {
413     int pix_hpos = coord_diw_to_window_x (hpos * 2);
414     if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1
415 	&& pix_hpos >= diwfirstword && last_diw_pix_hpos < diwfirstword)
416     {
417 	thisline_decision.diwfirstword = diwfirstword < 0 ? 0 : diwfirstword;
418 	hdiwstate = DIW_waiting_stop;
419 	thisline_decision.diwlastword = -1;
420     }
421     if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1
422 	&& pix_hpos >= diwlastword && last_diw_pix_hpos < diwlastword)
423     {
424 	thisline_decision.diwlastword = diwlastword < 0 ? 0 : diwlastword;
425 	hdiwstate = DIW_waiting_start;
426     }
427     last_diw_pix_hpos = pix_hpos;
428 }
429 
430 
431 static int fetchmode;
432 static int maxplanes_ocs[]={ 6,4,0,0 };
433 static int maxplanes_ecs[]={ 6,4,2,0 };
434 static int maxplanes_aga[]={ 8,4,2,0, 8,8,4,0, 8,8,8,0 };
435 
get_maxplanes(int res)436 static int get_maxplanes (int res)
437 {
438     int *planes;
439     if (currprefs.chipset_mask & CSMASK_AGA)
440 	planes = maxplanes_aga;
441     else if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
442 	planes = maxplanes_ocs;
443     else
444 	planes = maxplanes_ecs;
445     return planes[fetchmode * 4 + res];
446 }
447 
448 /* Disable bitplane DMA if planes > maxplanes.  This is needed e.g. by the
449    Sanity WOC demo (at the "Party Effect").  */
GET_PLANES_LIMIT(uae_u16 v)450 STATIC_INLINE int GET_PLANES_LIMIT (uae_u16 v)
451 {
452     if (GET_PLANES(v) > get_maxplanes (GET_RES(v)))
453 	v &= ~0x7010;
454     return GET_PLANES (v);
455 }
456 
457 /* The HRM says 0xD8, but that can't work... */
458 #define HARD_DDF_STOP 0xd4
459 #define HARD_DDF_START 0x18
460 
add_modulos(void)461 static void add_modulos (void)
462 {
463     int m1, m2;
464 
465     if (fmode & 0x4000) {
466 	if (((diwstrt >> 8) ^ vpos) & 1)
467 	    m1 = m2 = bpl2mod;
468 	else
469 	    m1 = m2 = bpl1mod;
470     } else {
471 	m1 = bpl1mod;
472 	m2 = bpl2mod;
473     }
474 
475     if (dmaen (DMA_BITPLANE))
476 	switch (GET_PLANES_LIMIT (bplcon0)) {
477 	case 8: bplpt[7] += m2;
478 	case 7: bplpt[6] += m1;
479 	case 6: bplpt[5] += m2;
480 	case 5: bplpt[4] += m1;
481 	case 4: bplpt[3] += m2;
482 	case 3: bplpt[2] += m1;
483 	case 2: bplpt[1] += m2;
484 	case 1: bplpt[0] += m1;
485 	}
486 }
487 
finish_playfield_line(void)488 static void finish_playfield_line (void)
489 {
490     /* The latter condition might be able to happen in interlaced frames. */
491     if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line))
492 	thisframe_first_drawn_line = vpos;
493     thisframe_last_drawn_line = vpos;
494 
495     add_modulos ();
496 
497     /* These are for comparison. */
498     thisline_decision.bplcon0 = bplcon0;
499     thisline_decision.bplcon2 = bplcon2;
500     thisline_decision.bplcon3 = bplcon3;
501     thisline_decision.bplcon4 = bplcon4;
502 
503 #ifdef SMART_UPDATE
504     if (line_decisions[next_lineno].plflinelen != thisline_decision.plflinelen
505 	|| line_decisions[next_lineno].plfleft != thisline_decision.plfleft
506 	|| line_decisions[next_lineno].bplcon0 != thisline_decision.bplcon0
507 	|| line_decisions[next_lineno].bplcon2 != thisline_decision.bplcon2
508 	|| line_decisions[next_lineno].bplcon3 != thisline_decision.bplcon3
509 	|| line_decisions[next_lineno].bplcon4 != thisline_decision.bplcon4
510 	)
511 #endif /* SMART_UPDATE */
512 	thisline_changed = 1;
513 }
514 
515 /* The fetch unit mainly controls ddf stop.  It's the number of cycles that
516    are contained in an indivisible block during which ddf is active.  E.g.
517    if DDF starts at 0x30, and fetchunit is 8, then possible DDF stops are
518    0x30 + n * 8.  */
519 static int fetchunit, fetchunit_mask;
520 /* The delay before fetching the same bitplane again.  Can be larger than
521    the number of bitplanes; in that case there are additional empty cycles
522    with no data fetch (this happens for high fetchmodes and low
523    resolutions).  */
524 static int fetchstart, fetchstart_shift, fetchstart_mask;
525 /* fm_maxplane holds the maximum number of planes possible with the current
526    fetch mode.  This selects the cycle diagram:
527    8 planes: 73516240
528    4 planes: 3120
529    2 planes: 10.  */
530 static int fm_maxplane, fm_maxplane_shift;
531 
532 /* The corresponding values, by fetchmode and display resolution.  */
533 static const int fetchunits[] = { 8,8,8,0, 16,8,8,0, 32,16,8,0 };
534 static const int fetchstarts[] = { 3,2,1,0, 4,3,2,0, 5,4,3,0 };
535 static const int fm_maxplanes[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 };
536 
537 static int cycle_diagram_table[3][3][9][32];
538 static int cycle_diagram_free_cycles[3][3][9];
539 static int cycle_diagram_total_cycles[3][3][9];
540 static int *curr_diagram;
541 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 };
542 
debug_cycle_diagram(void)543 static void debug_cycle_diagram (void)
544 {
545     int fm, res, planes, cycle, v;
546     char aa;
547 
548     for (fm = 0; fm < 3; fm++) {
549 	write_log ("FMODE %d\n=======\n", fm);
550 	for (res = 0; res <= 2; res++) {
551 	    for (planes = 0; planes <= 8; planes++) {
552 		write_log ("%d: ",planes);
553 		for (cycle = 0; cycle < 32; cycle++) {
554 		    v=cycle_diagram_table[fm][res][planes][cycle];
555 		    if (v==0) aa='-'; else if(v>0) aa='1'; else aa='X';
556 		    write_log ("%c",aa);
557 		}
558 		write_log (" %d:%d\n",
559 			  cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]);
560 	    }
561 	    write_log ("\n");
562 	}
563     }
564     fm=0;
565 }
566 
create_cycle_diagram_table(void)567 static void create_cycle_diagram_table (void)
568 {
569     int fm, res, cycle, planes, v;
570     int fetch_start, max_planes, freecycles;
571     const int *cycle_sequence;
572 
573     for (fm = 0; fm <= 2; fm++) {
574 	for (res = 0; res <= 2; res++) {
575 	    max_planes = fm_maxplanes[fm * 4 + res];
576 	    fetch_start = 1 << fetchstarts[fm * 4 + res];
577 	    cycle_sequence = &cycle_sequences[(max_planes - 1) * 8];
578 	    max_planes = 1 << max_planes;
579 	    for (planes = 0; planes <= 8; planes++) {
580 		freecycles = 0;
581 		for (cycle = 0; cycle < 32; cycle++)
582 		    cycle_diagram_table[fm][res][planes][cycle] = -1;
583 		if (planes <= max_planes) {
584 		    for (cycle = 0; cycle < fetch_start; cycle++) {
585 			if (cycle < max_planes && planes >= cycle_sequence[cycle & 7]) {
586 			    v = cycle_sequence[cycle & 7];
587 			} else {
588 			    v = 0;
589 			    freecycles++;
590 			}
591 			cycle_diagram_table[fm][res][planes][cycle] = v;
592 		    }
593 		}
594 		cycle_diagram_free_cycles[fm][res][planes] = freecycles;
595 		cycle_diagram_total_cycles[fm][res][planes] = fetch_start;
596 	    }
597 	}
598     }
599 #if 0
600     debug_cycle_diagram ();
601 #endif
602 }
603 
604 
605 /* Used by the copper.  */
606 static int estimated_last_fetch_cycle;
607 static int cycle_diagram_shift;
608 
estimate_last_fetch_cycle(int hpos)609 static void estimate_last_fetch_cycle (int hpos)
610 {
611     int fetchunit = fetchunits[fetchmode * 4 + GET_RES (bplcon0)];
612 
613     if (! passed_plfstop) {
614 	int stop = plfstop < hpos || plfstop > HARD_DDF_STOP ? HARD_DDF_STOP : plfstop;
615 	/* We know that fetching is up-to-date up until hpos, so we can use fetch_cycle.  */
616 	int fetch_cycle_at_stop = fetch_cycle + (stop - hpos);
617 	int starting_last_block_at = (fetch_cycle_at_stop + fetchunit - 1) & ~(fetchunit - 1);
618 
619 	estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
620     } else {
621 	int starting_last_block_at = (fetch_cycle + fetchunit - 1) & ~(fetchunit - 1);
622 	if (passed_plfstop == 2)
623 	    starting_last_block_at -= fetchunit;
624 
625 	estimated_last_fetch_cycle = hpos + (starting_last_block_at - fetch_cycle) + fetchunit;
626     }
627 }
628 
629 static uae_u32 outword[MAX_PLANES];
630 static int out_nbits, out_offs;
631 static uae_u32 todisplay[MAX_PLANES][4];
632 static uae_u32 fetched[MAX_PLANES];
633 static uae_u32 fetched_aga0[MAX_PLANES];
634 static uae_u32 fetched_aga1[MAX_PLANES];
635 
636 /* Expansions from bplcon0/bplcon1.  */
637 static int toscr_res, toscr_delay1, toscr_delay2, toscr_nr_planes, fetchwidth;
638 
639 /* The number of bits left from the last fetched words.
640    This is an optimization - conceptually, we have to make sure the result is
641    the same as if toscr is called in each clock cycle.  However, to speed this
642    up, we accumulate display data; this variable keeps track of how much.
643    Thus, once we do call toscr_nbits (which happens at least every 16 bits),
644    we can do more work at once.  */
645 static int toscr_nbits;
646 
647 static int delayoffset;
648 
compute_delay_offset(int hpos)649 STATIC_INLINE void compute_delay_offset (int hpos)
650 {
651     /* this fixes most horizontal scrolling jerkyness but can't be correct */
652     delayoffset = ((hpos - fm_maxplane - 0x18) & fetchstart_mask) << 1;
653     delayoffset &= ~7;
654     if (delayoffset & 8)
655 	delayoffset = 8;
656     else if (delayoffset & 16)
657 	delayoffset = 16;
658     else if (delayoffset & 32)
659 	delayoffset = 32;
660     else
661 	delayoffset = 0;
662 }
663 
expand_fmodes(void)664 static void expand_fmodes (void)
665 {
666     int res = GET_RES(bplcon0);
667     int fm = fetchmode;
668     fetchunit = fetchunits[fm * 4 + res];
669     fetchunit_mask = fetchunit - 1;
670     fetchstart_shift = fetchstarts[fm * 4 + res];
671     fetchstart = 1 << fetchstart_shift;
672     fetchstart_mask = fetchstart - 1;
673     fm_maxplane_shift = fm_maxplanes[fm * 4 + res];
674     fm_maxplane = 1 << fm_maxplane_shift;
675 }
676 
677 /* Expand bplcon0/bplcon1 into the toscr_xxx variables.  */
compute_toscr_delay_1(void)678 static void compute_toscr_delay_1 (void)
679 {
680     int delay1 = (bplcon1 & 0x0f) | ((bplcon1 & 0x0c00) >> 6);
681     int delay2 = ((bplcon1 >> 4) & 0x0f) | (((bplcon1 >> 4) & 0x0c00) >> 6);
682     int delaymask;
683     int fetchwidth = 16 << fetchmode;
684 
685     delay1 += delayoffset;
686     delay2 += delayoffset;
687     delaymask = (fetchwidth - 1) >> toscr_res;
688     toscr_delay1 = (delay1 & delaymask) << toscr_res;
689     toscr_delay2 = (delay2 & delaymask) << toscr_res;
690 }
691 
compute_toscr_delay(int hpos)692 static void compute_toscr_delay (int hpos)
693 {
694     toscr_res = GET_RES (bplcon0);
695     toscr_nr_planes = GET_PLANES_LIMIT (bplcon0);
696     compute_toscr_delay_1 ();
697 }
698 
maybe_first_bpl1dat(int hpos)699 STATIC_INLINE void maybe_first_bpl1dat (int hpos)
700 {
701     if (thisline_decision.plfleft == -1) {
702 	thisline_decision.plfleft = hpos;
703 	compute_delay_offset (hpos);
704 	compute_toscr_delay_1 ();
705     }
706 }
707 
fetch(int nr,int fm)708 STATIC_INLINE void fetch (int nr, int fm)
709 {
710     uaecptr p;
711     if (nr >= toscr_nr_planes)
712 	return;
713     p = bplpt[nr] + bpl_off[nr];
714     switch (fm) {
715     case 0:
716 	fetched[nr] = chipmem_agnus_wget (p);
717 	bplpt[nr] += 2;
718 	break;
719     case 1:
720 	fetched_aga0[nr] = chipmem_lget (p);
721 	bplpt[nr] += 4;
722 	break;
723     case 2:
724 	fetched_aga1[nr] = chipmem_lget (p);
725 	fetched_aga0[nr] = chipmem_lget (p + 4);
726 	bplpt[nr] += 8;
727 	break;
728     }
729     if (nr == 0)
730 	fetch_state = fetch_was_plane0;
731 }
732 
clear_fetchbuffer(uae_u32 * ptr,int nwords)733 static void clear_fetchbuffer (uae_u32 *ptr, int nwords)
734 {
735     int i;
736 
737     if (! thisline_changed)
738 	for (i = 0; i < nwords; i++)
739 	    if (ptr[i]) {
740 		thisline_changed = 1;
741 		break;
742 	    }
743 
744     memset (ptr, 0, nwords * 4);
745 }
746 
update_toscr_planes(void)747 static void update_toscr_planes (void)
748 {
749     if (toscr_nr_planes > thisline_decision.nr_planes) {
750 	int j;
751 	for (j = thisline_decision.nr_planes; j < toscr_nr_planes; j++)
752 	    clear_fetchbuffer ((uae_u32 *)(line_data[next_lineno] + 2 * MAX_WORDS_PER_LINE * j), out_offs);
753 #if 0
754 	if (thisline_decision.nr_planes > 0)
755 	    printf ("Planes from %d to %d\n", thisline_decision.nr_planes, toscr_nr_planes);
756 #endif
757 	thisline_decision.nr_planes = toscr_nr_planes;
758     }
759 }
760 
toscr_3_ecs(int nbits)761 STATIC_INLINE void toscr_3_ecs (int nbits)
762 {
763     int delay1 = toscr_delay1;
764     int delay2 = toscr_delay2;
765     int i;
766     uae_u32 mask = 0xFFFF >> (16 - nbits);
767 
768     for (i = 0; i < toscr_nr_planes; i += 2) {
769 	outword[i] <<= nbits;
770 	outword[i] |= (todisplay[i][0] >> (16 - nbits + delay1)) & mask;
771 	todisplay[i][0] <<= nbits;
772     }
773     for (i = 1; i < toscr_nr_planes; i += 2) {
774 	outword[i] <<= nbits;
775 	outword[i] |= (todisplay[i][0] >> (16 - nbits + delay2)) & mask;
776 	todisplay[i][0] <<= nbits;
777     }
778 }
779 
shift32plus(uae_u32 * p,int n)780 STATIC_INLINE void shift32plus (uae_u32 *p, int n)
781 {
782     uae_u32 t = p[1];
783     t <<= n;
784     t |= p[0] >> (32 - n);
785     p[1] = t;
786 }
787 
aga_shift(uae_u32 * p,int n,int fm)788 STATIC_INLINE void aga_shift (uae_u32 *p, int n, int fm)
789 {
790     if (fm == 2) {
791 	shift32plus (p + 2, n);
792 	shift32plus (p + 1, n);
793     }
794     shift32plus (p + 0, n);
795     p[0] <<= n;
796 }
797 
toscr_3_aga(int nbits,int fm)798 STATIC_INLINE void toscr_3_aga (int nbits, int fm)
799 {
800     int delay1 = toscr_delay1;
801     int delay2 = toscr_delay2;
802     int i;
803     uae_u32 mask = 0xFFFF >> (16 - nbits);
804 
805     {
806 	int offs = (16 << fm) - nbits + delay1;
807 	int off1 = offs >> 5;
808 	if (off1 == 3)
809 	    off1 = 2;
810 	offs -= off1 * 32;
811 	for (i = 0; i < toscr_nr_planes; i += 2) {
812 	    uae_u32 t0 = todisplay[i][off1];
813 	    uae_u32 t1 = todisplay[i][off1 + 1];
814 	    uae_u64 t = (((uae_u64)t1) << 32) | t0;
815 	    outword[i] <<= nbits;
816 	    outword[i] |= (t >> offs) & mask;
817 	    aga_shift (todisplay[i], nbits, fm);
818 	}
819     }
820     {
821 	int offs = (16 << fm) - nbits + delay2;
822 	int off1 = offs >> 5;
823 	if (off1 == 3)
824 	    off1 = 2;
825 	offs -= off1 * 32;
826 	for (i = 1; i < toscr_nr_planes; i += 2) {
827 	    uae_u32 t0 = todisplay[i][off1];
828 	    uae_u32 t1 = todisplay[i][off1 + 1];
829 	    uae_u64 t = (((uae_u64)t1) << 32) | t0;
830 	    outword[i] <<= nbits;
831 	    outword[i] |= (t >> offs) & mask;
832 	    aga_shift (todisplay[i], nbits, fm);
833 	}
834     }
835 }
836 
toscr_2_0(int nbits)837 static void toscr_2_0 (int nbits) { toscr_3_ecs (nbits); }
toscr_2_1(int nbits)838 static void toscr_2_1 (int nbits) { toscr_3_aga (nbits, 1); }
toscr_2_2(int nbits)839 static void toscr_2_2 (int nbits) { toscr_3_aga (nbits, 2); }
840 
toscr_1(int nbits,int fm)841 STATIC_INLINE void toscr_1 (int nbits, int fm)
842 {
843     switch (fm) {
844     case 0:
845 	toscr_2_0 (nbits);
846 	break;
847     case 1:
848 	toscr_2_1 (nbits);
849 	break;
850     case 2:
851 	toscr_2_2 (nbits);
852 	break;
853     }
854 
855     out_nbits += nbits;
856     if (out_nbits == 32) {
857 	int i;
858 	uae_u8 *dataptr = line_data[next_lineno] + out_offs * 4;
859 	/* Don't use toscr_nr_planes here; if the plane count drops during the
860 	   line we still want the data to be correct for the full number of planes
861 	   over the full width of the line.  */
862 	for (i = 0; i < thisline_decision.nr_planes; i++) {
863 	    uae_u32 *dataptr32 = (uae_u32 *)dataptr;
864 	    if (*dataptr32 != outword[i])
865 		thisline_changed = 1;
866 	    *dataptr32 = outword[i];
867 	    dataptr += MAX_WORDS_PER_LINE * 2;
868 	}
869 	out_offs++;
870 	out_nbits = 0;
871     }
872 }
873 
874 static void toscr_fm0 (int);
875 static void toscr_fm1 (int);
876 static void toscr_fm2 (int);
877 
toscr(int nbits,int fm)878 STATIC_INLINE void toscr (int nbits, int fm)
879 {
880     switch (fm) {
881     case 0: toscr_fm0 (nbits); break;
882     case 1: toscr_fm1 (nbits); break;
883     case 2: toscr_fm2 (nbits); break;
884     }
885 }
886 
toscr_0(int nbits,int fm)887 STATIC_INLINE void toscr_0 (int nbits, int fm)
888 {
889     int t;
890 
891     if (nbits > 16) {
892 	toscr (16, fm);
893 	nbits -= 16;
894     }
895 
896     t = 32 - out_nbits;
897     if (t < nbits) {
898 	toscr_1 (t, fm);
899 	nbits -= t;
900     }
901     toscr_1 (nbits, fm);
902 }
903 
toscr_fm0(int nbits)904 static void toscr_fm0 (int nbits) { toscr_0 (nbits, 0); }
toscr_fm1(int nbits)905 static void toscr_fm1 (int nbits) { toscr_0 (nbits, 1); }
toscr_fm2(int nbits)906 static void toscr_fm2 (int nbits) { toscr_0 (nbits, 2); }
907 
flush_plane_data(int fm)908 static int flush_plane_data (int fm)
909 {
910     int i = 0;
911     int fetchwidth = 16 << fm;
912 
913     if (out_nbits <= 16) {
914 	i += 16;
915 	toscr_1 (16, fm);
916     }
917     if (out_nbits != 0) {
918 	i += 32 - out_nbits;
919 	toscr_1 (32 - out_nbits, fm);
920     }
921     i += 32;
922 
923     toscr_1 (16, fm);
924     toscr_1 (16, fm);
925     return i >> (1 + toscr_res);
926 }
927 
flush_display(int fm)928 STATIC_INLINE void flush_display (int fm)
929 {
930     if (toscr_nbits > 0 && thisline_decision.plfleft != -1)
931 	toscr (toscr_nbits, fm);
932     toscr_nbits = 0;
933 }
934 
935 /* Called when all planes have been fetched, i.e. when a new block
936    of data is available to be displayed.  The data in fetched[] is
937    moved into todisplay[].  */
beginning_of_plane_block(int pos,int fm)938 STATIC_INLINE void beginning_of_plane_block (int pos, int fm)
939 {
940     int i;
941 
942     flush_display (fm);
943 
944     if (fm == 0)
945 	for (i = 0; i < MAX_PLANES; i++)
946 	    todisplay[i][0] |= fetched[i];
947     else
948 	for (i = 0; i < MAX_PLANES; i++) {
949 	    if (fm == 2)
950 		todisplay[i][1] = fetched_aga1[i];
951 	    todisplay[i][0] = fetched_aga0[i];
952 	}
953 
954     maybe_first_bpl1dat (pos);
955 }
956 
957 #define SPEEDUP
958 
959 #ifdef SPEEDUP
960 
961 /* 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)962 STATIC_INLINE void long_fetch_ecs (int plane, int nwords, int weird_number_of_bits, int dma)
963 {
964     uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2);
965     int delay = (plane & 1) ? toscr_delay2 : toscr_delay1;
966     int tmp_nbits = out_nbits;
967     uae_u32 shiftbuffer = todisplay[plane][0];
968     uae_u32 outval = outword[plane];
969     uae_u32 fetchval = fetched[plane];
970     uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
971 
972     if (dma)
973 	bplpt[plane] += nwords * 2;
974 
975     if (real_pt == 0)
976 	/* @@@ Don't do this, fall back on chipmem_wget instead.  */
977 	return;
978 
979     while (nwords > 0) {
980 	int bits_left = 32 - tmp_nbits;
981 	uae_u32 t;
982 
983 	shiftbuffer |= fetchval;
984 
985 	t = (shiftbuffer >> delay) & 0xFFFF;
986 
987 	if (weird_number_of_bits && bits_left < 16) {
988 	    outval <<= bits_left;
989 	    outval |= t >> (16 - bits_left);
990 	    thisline_changed |= *dataptr ^ outval;
991 	    *dataptr++ = outval;
992 
993 	    outval = t;
994 	    tmp_nbits = 16 - bits_left;
995 	    shiftbuffer <<= 16;
996 	} else {
997 	    outval = (outval << 16) | t;
998 	    shiftbuffer <<= 16;
999 	    tmp_nbits += 16;
1000 	    if (tmp_nbits == 32) {
1001 		thisline_changed |= *dataptr ^ outval;
1002 		*dataptr++ = outval;
1003 		tmp_nbits = 0;
1004 	    }
1005 	}
1006 	nwords--;
1007 	if (dma) {
1008 	    fetchval = do_get_mem_word (real_pt);
1009 	    real_pt++;
1010 	}
1011     }
1012     fetched[plane] = fetchval;
1013     todisplay[plane][0] = shiftbuffer;
1014     outword[plane] = outval;
1015 }
1016 
long_fetch_aga(int plane,int nwords,int weird_number_of_bits,int fm,int dma)1017 STATIC_INLINE void long_fetch_aga (int plane, int nwords, int weird_number_of_bits, int fm, int dma)
1018 {
1019     uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2);
1020     int delay = (plane & 1) ? toscr_delay2 : toscr_delay1;
1021     int tmp_nbits = out_nbits;
1022     uae_u32 *shiftbuffer = todisplay[plane];
1023     uae_u32 outval = outword[plane];
1024     uae_u32 fetchval0 = fetched_aga0[plane];
1025     uae_u32 fetchval1 = fetched_aga1[plane];
1026     uae_u32 *dataptr = (uae_u32 *)(line_data[next_lineno] + 2 * plane * MAX_WORDS_PER_LINE + 4 * out_offs);
1027     int offs = (16 << fm) - 16 + delay;
1028     int off1 = offs >> 5;
1029     if (off1 == 3)
1030 	off1 = 2;
1031     offs -= off1 * 32;
1032 
1033     if (dma)
1034 	bplpt[plane] += nwords * 2;
1035 
1036     if (real_pt == 0)
1037 	/* @@@ Don't do this, fall back on chipmem_wget instead.  */
1038 	return;
1039 
1040     while (nwords > 0) {
1041 	int i;
1042 
1043 	shiftbuffer[0] = fetchval0;
1044 	if (fm == 2)
1045 	    shiftbuffer[1] = fetchval1;
1046 
1047 	for (i = 0; i < (1 << fm); i++) {
1048 	    int bits_left = 32 - tmp_nbits;
1049 
1050 	    uae_u32 t0 = shiftbuffer[off1];
1051 	    uae_u32 t1 = shiftbuffer[off1 + 1];
1052 	    uae_u64 t = (((uae_u64)t1) << 32) | t0;
1053 
1054 	    t0 = (t >> offs) & 0xFFFF;
1055 
1056 	    if (weird_number_of_bits && bits_left < 16) {
1057 		outval <<= bits_left;
1058 		outval |= t0 >> (16 - bits_left);
1059 
1060 		thisline_changed |= *dataptr ^ outval;
1061 		*dataptr++ = outval;
1062 
1063 		outval = t0;
1064 		tmp_nbits = 16 - bits_left;
1065 		aga_shift (shiftbuffer, 16, fm);
1066 	    } else {
1067 		outval = (outval << 16) | t0;
1068 		aga_shift (shiftbuffer, 16, fm);
1069 		tmp_nbits += 16;
1070 		if (tmp_nbits == 32) {
1071 		    thisline_changed |= *dataptr ^ outval;
1072 		    *dataptr++ = outval;
1073 		    tmp_nbits = 0;
1074 		}
1075 	    }
1076 	}
1077 
1078 	nwords -= 1 << fm;
1079 
1080 	if (dma) {
1081 	    if (fm == 1)
1082 		fetchval0 = do_get_mem_long (real_pt);
1083 	    else {
1084 		fetchval1 = do_get_mem_long (real_pt);
1085 		fetchval0 = do_get_mem_long (real_pt + 1);
1086 	    }
1087 	    real_pt += fm;
1088 	}
1089     }
1090     fetched_aga0[plane] = fetchval0;
1091     fetched_aga1[plane] = fetchval1;
1092     outword[plane] = outval;
1093 }
1094 
long_fetch_ecs_0(int hpos,int nwords,int dma)1095 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)1096 static void long_fetch_ecs_1 (int hpos, int nwords, int dma) { long_fetch_ecs (hpos, nwords, 1, dma); }
long_fetch_aga_1_0(int hpos,int nwords,int dma)1097 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)1098 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)1099 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)1100 static void long_fetch_aga_2_1 (int hpos, int nwords, int dma) { long_fetch_aga (hpos, nwords,  1, 2, dma); }
1101 
do_long_fetch(int hpos,int nwords,int dma,int fm)1102 static void do_long_fetch (int hpos, int nwords, int dma, int fm)
1103 {
1104     int i;
1105 
1106     flush_display (fm);
1107     switch (fm) {
1108     case 0:
1109 	if (out_nbits & 15) {
1110 	    for (i = 0; i < toscr_nr_planes; i++)
1111 		long_fetch_ecs_1 (i, nwords, dma);
1112 	} else {
1113 	    for (i = 0; i < toscr_nr_planes; i++)
1114 		long_fetch_ecs_0 (i, nwords, dma);
1115 	}
1116 	break;
1117     case 1:
1118 	if (out_nbits & 15) {
1119 	    for (i = 0; i < toscr_nr_planes; i++)
1120 		long_fetch_aga_1_1 (i, nwords, dma);
1121 	} else {
1122 	    for (i = 0; i < toscr_nr_planes; i++)
1123 		long_fetch_aga_1_0 (i, nwords, dma);
1124 	}
1125 	break;
1126     case 2:
1127 	if (out_nbits & 15) {
1128 	    for (i = 0; i < toscr_nr_planes; i++)
1129 		long_fetch_aga_2_1 (i, nwords, dma);
1130 	} else {
1131 	    for (i = 0; i < toscr_nr_planes; i++)
1132 		long_fetch_aga_2_0 (i, nwords, dma);
1133 	}
1134 	break;
1135     }
1136 
1137     out_nbits += nwords * 16;
1138     out_offs += out_nbits >> 5;
1139     out_nbits &= 31;
1140 
1141     if (dma && toscr_nr_planes > 0)
1142 	fetch_state = fetch_was_plane0;
1143 }
1144 
1145 #endif
1146 
1147 /* make sure fetch that goes beyond maxhpos is finished */
finish_final_fetch(int i,int fm)1148 static void finish_final_fetch (int i, int fm)
1149 {
1150     passed_plfstop = 3;
1151 
1152     if (thisline_decision.plfleft == -1)
1153 	return;
1154 
1155     ddfstate = DIW_waiting_start;
1156     i += flush_plane_data (fm);
1157     thisline_decision.plfright = i;
1158     thisline_decision.plflinelen = out_offs;
1159     thisline_decision.bplres = toscr_res;
1160     finish_playfield_line ();
1161 }
1162 
one_fetch_cycle_0(int i,int ddfstop_to_test,int dma,int fm)1163 STATIC_INLINE int one_fetch_cycle_0 (int i, int ddfstop_to_test, int dma, int fm)
1164 {
1165     if (! passed_plfstop && i == ddfstop_to_test)
1166 	passed_plfstop = 1;
1167 
1168     if ((fetch_cycle & fetchunit_mask) == 0) {
1169 	if (passed_plfstop == 2) {
1170 	    finish_final_fetch (i, fm);
1171 	    return 1;
1172 	}
1173 	if (passed_plfstop)
1174 	    passed_plfstop++;
1175     }
1176     if (dma) {
1177 	/* fetchstart_mask can be larger than fm_maxplane if FMODE > 0.  This means
1178 	   that the remaining cycles are idle; we'll fall through the whole switch
1179 	   without doing anything.  */
1180 	int cycle_start = fetch_cycle & fetchstart_mask;
1181 	switch (fm_maxplane) {
1182 	case 8:
1183 	    switch (cycle_start) {
1184 	    case 0: fetch (7, fm); break;
1185 	    case 1: fetch (3, fm); break;
1186 	    case 2: fetch (5, fm); break;
1187 	    case 3: fetch (1, fm); break;
1188 	    case 4: fetch (6, fm); break;
1189 	    case 5: fetch (2, fm); break;
1190 	    case 6: fetch (4, fm); break;
1191 	    case 7: fetch (0, fm); break;
1192 	    }
1193 	    break;
1194 	case 4:
1195 	    switch (cycle_start) {
1196 	    case 0: fetch (3, fm); break;
1197 	    case 1: fetch (1, fm); break;
1198 	    case 2: fetch (2, fm); break;
1199 	    case 3: fetch (0, fm); break;
1200 	    }
1201 	    break;
1202 	case 2:
1203 	    switch (cycle_start) {
1204 	    case 0: fetch (1, fm); break;
1205 	    case 1: fetch (0, fm); break;
1206 	    }
1207 	    break;
1208 	}
1209     }
1210     fetch_cycle++;
1211     toscr_nbits += 2 << toscr_res;
1212 
1213     if (toscr_nbits == 16)
1214 	flush_display (fm);
1215     if (toscr_nbits > 16)
1216 	abort ();
1217 
1218     return 0;
1219 }
1220 
one_fetch_cycle_fm0(int i,int ddfstop_to_test,int dma)1221 static int one_fetch_cycle_fm0 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 0); }
one_fetch_cycle_fm1(int i,int ddfstop_to_test,int dma)1222 static int one_fetch_cycle_fm1 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 1); }
one_fetch_cycle_fm2(int i,int ddfstop_to_test,int dma)1223 static int one_fetch_cycle_fm2 (int i, int ddfstop_to_test, int dma) { return one_fetch_cycle_0 (i, ddfstop_to_test, dma, 2); }
1224 
one_fetch_cycle(int i,int ddfstop_to_test,int dma,int fm)1225 STATIC_INLINE int one_fetch_cycle (int i, int ddfstop_to_test, int dma, int fm)
1226 {
1227     switch (fm) {
1228     case 0: return one_fetch_cycle_fm0 (i, ddfstop_to_test, dma);
1229     case 1: return one_fetch_cycle_fm1 (i, ddfstop_to_test, dma);
1230     case 2: return one_fetch_cycle_fm2 (i, ddfstop_to_test, dma);
1231     default: uae_abort ("fm corrupt");
1232     }
1233 }
1234 
update_fetch(int until,int fm)1235 STATIC_INLINE void update_fetch (int until, int fm)
1236 {
1237     int pos;
1238     int dma = dmaen (DMA_BITPLANE);
1239 
1240     int ddfstop_to_test;
1241 
1242     if (nodraw () || passed_plfstop == 3)
1243 	return;
1244 
1245     /* We need an explicit test against HARD_DDF_STOP here to guard against
1246        programs that move the DDFSTOP before our current position before we
1247        reach it.  */
1248     ddfstop_to_test = HARD_DDF_STOP;
1249     if (ddfstop >= last_fetch_hpos && ddfstop < HARD_DDF_STOP)
1250 	ddfstop_to_test = ddfstop;
1251 
1252     compute_toscr_delay (last_fetch_hpos);
1253     update_toscr_planes ();
1254 
1255     pos = last_fetch_hpos;
1256     cycle_diagram_shift = (last_fetch_hpos - fetch_cycle) & fetchstart_mask;
1257 
1258     /* First, a loop that prepares us for the speedup code.  We want to enter
1259        the SPEEDUP case with fetch_state == fetch_was_plane0, and then unroll
1260        whole blocks, so that we end on the same fetch_state again.  */
1261     for (; ; pos++) {
1262 	if (pos == until) {
1263 	    if (until >= maxhpos && passed_plfstop == 2) {
1264 		finish_final_fetch (pos, fm);
1265 		return;
1266 	    }
1267 	    flush_display (fm);
1268 	    return;
1269 	}
1270 
1271 	if (fetch_state == fetch_was_plane0)
1272 	    break;
1273 
1274 	fetch_state = fetch_started;
1275 	if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm))
1276 	    return;
1277     }
1278 
1279 #ifdef SPEEDUP
1280     /* Unrolled version of the for loop below.  */
1281     if (! passed_plfstop
1282 	&& dma
1283 	&& (fetch_cycle & fetchstart_mask) == (fm_maxplane & fetchstart_mask)
1284 # if 0
1285 	/* @@@ We handle this case, but the code would be simpler if we
1286 	 * disallowed it - it may even be possible to guarantee that
1287 	 * this condition never is false.  Later.  */
1288 	&& (out_nbits & 15) == 0
1289 # endif
1290 	&& toscr_nr_planes == thisline_decision.nr_planes)
1291     {
1292 	int offs = (pos - fetch_cycle) & fetchunit_mask;
1293 	int ddf2 = ((ddfstop_to_test - offs + fetchunit - 1) & ~fetchunit_mask) + offs;
1294 	int ddf3 = ddf2 + fetchunit;
1295 	int stop = until < ddf2 ? until : until < ddf3 ? ddf2 : ddf3;
1296 	int count;
1297 
1298 	count = stop - pos;
1299 
1300 	if (count >= fetchstart) {
1301 	    count &= ~fetchstart_mask;
1302 
1303 	    if (thisline_decision.plfleft == -1) {
1304 		compute_delay_offset (pos);
1305 		compute_toscr_delay_1 ();
1306 	    }
1307 	    do_long_fetch (pos, count >> (3 - toscr_res), dma, fm);
1308 
1309 	    /* This must come _after_ do_long_fetch so as not to confuse flush_display
1310 	       into thinking the first fetch has produced any output worth emitting to
1311 	       the screen.  But the calculation of delay_offset must happen _before_.  */
1312 	    maybe_first_bpl1dat (pos);
1313 
1314 	    if (pos <= ddfstop_to_test && pos + count > ddfstop_to_test)
1315 		passed_plfstop = 1;
1316 	    if (pos <= ddfstop_to_test && pos + count > ddf2)
1317 		passed_plfstop = 2;
1318 	    pos += count;
1319 	    fetch_cycle += count;
1320 	}
1321     }
1322 #endif
1323     for (; pos < until; pos++) {
1324 	if (fetch_state == fetch_was_plane0)
1325 	    beginning_of_plane_block (pos, fm);
1326 	fetch_state = fetch_started;
1327 
1328 	if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm))
1329 	    return;
1330     }
1331     if (until >= maxhpos && passed_plfstop == 2) {
1332 	finish_final_fetch (pos, fm);
1333 	return;
1334     }
1335     flush_display (fm);
1336 }
1337 
update_fetch_0(int hpos)1338 static void update_fetch_0 (int hpos) { update_fetch (hpos, 0); }
update_fetch_1(int hpos)1339 static void update_fetch_1 (int hpos) { update_fetch (hpos, 1); }
update_fetch_2(int hpos)1340 static void update_fetch_2 (int hpos) { update_fetch (hpos, 2); }
1341 
decide_fetch(int hpos)1342 STATIC_INLINE void decide_fetch (int hpos)
1343 {
1344     if (fetch_state != fetch_not_started && hpos > last_fetch_hpos) {
1345 	switch (fetchmode) {
1346 	case 0: update_fetch_0 (hpos); break;
1347 	case 1: update_fetch_1 (hpos); break;
1348 	case 2: update_fetch_2 (hpos); break;
1349 	default: abort ();
1350 	}
1351     }
1352     last_fetch_hpos = hpos;
1353 }
1354 
start_bpl_dma(int hstart)1355 static void start_bpl_dma (int hstart)
1356 {
1357     fetch_state = fetch_started;
1358     fetch_cycle = 0;
1359     last_fetch_hpos = hstart;
1360     out_nbits = 0;
1361     out_offs = 0;
1362     toscr_nbits = 0;
1363 
1364     ddfstate = DIW_waiting_stop;
1365     compute_toscr_delay (last_fetch_hpos);
1366 
1367     /* If someone already wrote BPL1DAT, clear the area between that point and
1368        the real fetch start.  */
1369     if (!nodraw ()) {
1370 	if (thisline_decision.plfleft != -1) {
1371 	    out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res);
1372 	    out_offs = out_nbits >> 5;
1373 	    out_nbits &= 31;
1374 	}
1375 	update_toscr_planes ();
1376     }
1377 }
1378 
1379 /* this may turn on datafetch if program turns dma on during the ddf */
maybe_start_bpl_dma(int hpos)1380 static void maybe_start_bpl_dma (int hpos)
1381 {
1382     /* OCS: BPL DMA never restarts if DMA is turned on during DDF
1383      * ECS/AGA: BPL DMA restarts but only if DMA was turned off
1384        outside of DDF or during current line, otherwise display
1385        processing jumps immediately to "DDFSTOP passed"-condition */
1386     if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
1387 	return;
1388     if (fetch_state != fetch_not_started)
1389 	return;
1390     if (diwstate != DIW_waiting_stop)
1391 	return;
1392     if (hpos <= plfstrt)
1393 	return;
1394     if (hpos > plfstop - fetchunit)
1395 	return;
1396     if (ddfstate != DIW_waiting_start)
1397 	passed_plfstop = 1;
1398 
1399     start_bpl_dma (hpos);
1400 }
1401 
1402 /* This function is responsible for turning on datafetch if necessary.  */
decide_line(int hpos)1403 STATIC_INLINE void decide_line (int hpos)
1404 {
1405     if (hpos <= last_decide_line_hpos)
1406 	return;
1407     if (fetch_state != fetch_not_started)
1408 	return;
1409 
1410     /* Test if we passed the start of the DDF window.  */
1411     if (last_decide_line_hpos < plfstrt && hpos >= plfstrt) {
1412 	/* First, take care of the vertical DIW.  Surprisingly enough, this seems to be
1413 	   correct here - putting this into decide_diw() results in garbage.  */
1414 	if (diwstate == DIW_waiting_start && vpos == plffirstline) {
1415 	    diwstate = DIW_waiting_stop;
1416 	}
1417 	if (diwstate == DIW_waiting_stop && vpos == plflastline) {
1418 	    diwstate = DIW_waiting_start;
1419 	}
1420 
1421 	/* If DMA isn't on by the time we reach plfstrt, then there's no
1422 	   bitplane DMA at all for the whole line.  */
1423 	if (dmaen (DMA_BITPLANE)
1424 	    && diwstate == DIW_waiting_stop)
1425 	{
1426 	    start_bpl_dma (plfstrt);
1427 
1428 	    estimate_last_fetch_cycle (plfstrt);
1429 	    last_decide_line_hpos = hpos;
1430 	    do_sprites (plfstrt);
1431 	    return;
1432 	}
1433     }
1434 
1435     if (last_decide_line_hpos < 0x34)
1436 	do_sprites (hpos);
1437 
1438     last_decide_line_hpos = hpos;
1439 }
1440 
1441 /* Called when a color is about to be changed (write to a color register),
1442  * but the new color has not been entered into the table yet. */
record_color_change(int hpos,int regno,unsigned long value)1443 static void record_color_change (int hpos, int regno, unsigned long value)
1444 {
1445     if (regno == -1 && value) {
1446 	thisline_decision.ham_seen = 1;
1447 	if (hpos < HARD_DDF_START)
1448 	    thisline_decision.ham_at_start = 1;
1449     }
1450 
1451     /* Early positions don't appear on-screen. */
1452     if (nodraw () || vpos < minfirstline || hpos < HARD_DDF_START
1453 	/*|| currprefs.emul_accuracy == 0*/)
1454 	return;
1455 
1456     decide_diw (hpos);
1457     decide_line (hpos);
1458 
1459     if (thisline_decision.ctable == -1)
1460 	remember_ctable ();
1461 
1462 #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
1463     if (next_color_change >= max_color_change) {
1464 	++delta_color_change;
1465 	return;
1466     }
1467 #endif
1468     curr_color_changes[next_color_change].linepos = hpos;
1469     curr_color_changes[next_color_change].regno = regno;
1470     curr_color_changes[next_color_change++].value = value;
1471 }
1472 
1473 typedef int sprbuf_res_t, cclockres_t, hwres_t, bplres_t;
1474 
do_playfield_collisions(void)1475 static void do_playfield_collisions (void)
1476 {
1477     uae_u8 *ld = line_data[next_lineno];
1478     int i;
1479 
1480     if (clxcon_bpl_enable == 0) {
1481 	clxdat |= 1;
1482 	return;
1483     }
1484 
1485     for (i = thisline_decision.plfleft; i < thisline_decision.plfright; i += 2) {
1486 	int j;
1487 	uae_u32 total = 0xFFFFFFFF;
1488 	for (j = 0; j < 8; j++) {
1489 	    uae_u32 t = 0;
1490 	    if ((clxcon_bpl_enable & (1 << j)) == 0)
1491 		t = 0xFFFFFFFF;
1492 	    else if (j < thisline_decision.nr_planes) {
1493 		t = *(uae_u32 *)(line_data[next_lineno] + 2 * i + 2 * j * MAX_WORDS_PER_LINE);
1494 		t ^= ~(((clxcon_bpl_match >> j) & 1) - 1);
1495 	    }
1496 	    total &= t;
1497 	}
1498 	if (total)
1499 	    clxdat |= 1;
1500     }
1501 }
1502 
1503 /* Sprite-to-sprite collisions are taken care of in record_sprite.  This one does
1504    playfield/sprite collisions.
1505    That's the theory.  In practice this doesn't work yet.  I also suspect this code
1506    is way too slow.  */
do_sprite_collisions(void)1507 static void do_sprite_collisions (void)
1508 {
1509     int nr_sprites = curr_drawinfo[next_lineno].nr_sprites;
1510     int first = curr_drawinfo[next_lineno].first_sprite_entry;
1511     int i;
1512     unsigned int collision_mask = clxmask[clxcon >> 12];
1513     int bplres = GET_RES (bplcon0);
1514     hwres_t ddf_left = thisline_decision.plfleft * 2 << bplres;
1515     hwres_t hw_diwlast = coord_window_to_diw_x (thisline_decision.diwlastword);
1516     hwres_t hw_diwfirst = coord_window_to_diw_x (thisline_decision.diwfirstword);
1517 
1518     if (clxcon_bpl_enable == 0) {
1519 	clxdat |= 0x1FE;
1520 	return;
1521     }
1522 
1523     for (i = 0; i < nr_sprites; i++) {
1524 	struct sprite_entry *e = curr_sprite_entries + first + i;
1525 	sprbuf_res_t j;
1526 	sprbuf_res_t minpos = e->pos;
1527 	sprbuf_res_t maxpos = e->max;
1528 	hwres_t minp1 = minpos >> sprite_buffer_res;
1529 	hwres_t maxp1 = maxpos >> sprite_buffer_res;
1530 
1531 	if (maxp1 > hw_diwlast)
1532 	    maxpos = hw_diwlast << sprite_buffer_res;
1533 	if (maxp1 > thisline_decision.plfright * 2)
1534 	    maxpos = thisline_decision.plfright * 2 << sprite_buffer_res;
1535 	if (minp1 < hw_diwfirst)
1536 	    minpos = hw_diwfirst << sprite_buffer_res;
1537 	if (minp1 < thisline_decision.plfleft * 2)
1538 	    minpos = thisline_decision.plfleft * 2 << sprite_buffer_res;
1539 
1540 	for (j = minpos; j < maxpos; j++) {
1541 	    int sprpix = spixels[e->first_pixel + j - e->pos] & collision_mask;
1542 	    int k;
1543 	    int offs;
1544 
1545 	    if (sprpix == 0)
1546 		continue;
1547 
1548 	    offs = ((j << bplres) >> sprite_buffer_res) - ddf_left;
1549 	    sprpix = sprite_ab_merge[sprpix & 255] | (sprite_ab_merge[sprpix >> 8] << 2);
1550 	    sprpix <<= 1;
1551 
1552 	    /* Loop over number of playfields.  */
1553 	    for (k = 0; k < 2; k++) {
1554 		int l;
1555 		int match = 1;
1556 		int planes = ((currprefs.chipset_mask & CSMASK_AGA) ? 8 : 6);
1557 
1558 		for (l = k; match && l < planes; l += 2) {
1559 		    if (clxcon_bpl_enable & (1 << l)) {
1560 			int t = 0;
1561 			if (l < thisline_decision.nr_planes) {
1562 			    uae_u32 *ldata = (uae_u32 *)(line_data[next_lineno] + 2 * l * MAX_WORDS_PER_LINE);
1563 			    uae_u32 word = ldata[offs >> 5];
1564 			    t = (word >> (31 - (offs & 31))) & 1;
1565 			}
1566 			if (t != ((clxcon_bpl_match >> l) & 1))
1567 			    match = 0;
1568 		    }
1569 		}
1570 		if (match)
1571 		    clxdat |= sprpix;
1572 		sprpix <<= 4;
1573 	    }
1574 	}
1575     }
1576 }
1577 
expand_sprres(void)1578 static void expand_sprres (void)
1579 {
1580     switch ((bplcon3 >> 6) & 3) {
1581     case 0: /* ECS defaults (LORES,HIRES=140ns,SHRES=70ns) */
1582 	if ((currprefs.chipset_mask & CSMASK_ECS_DENISE) && GET_RES (bplcon0) == RES_SUPERHIRES)
1583 	    sprres = RES_HIRES;
1584 	else
1585 	    sprres = RES_LORES;
1586 	break;
1587     case 1:
1588 	sprres = RES_LORES;
1589 	break;
1590     case 2:
1591 	sprres = RES_HIRES;
1592 	break;
1593     case 3:
1594 	sprres = RES_SUPERHIRES;
1595 	break;
1596     }
1597 }
1598 
record_sprite_1(uae_u16 * buf,uae_u32 datab,int num,int dbl,unsigned int mask,int do_collisions,uae_u32 collision_mask)1599 STATIC_INLINE void record_sprite_1 (uae_u16 *buf, uae_u32 datab, int num, int dbl,
1600 				    unsigned int mask, int do_collisions, uae_u32 collision_mask)
1601 {
1602     int j = 0;
1603     while (datab) {
1604 	unsigned int tmp = *buf;
1605 	unsigned int col = (datab & 3) << (2 * num);
1606 	tmp |= col;
1607 	if ((j & mask) == 0)
1608 	    *buf++ = tmp;
1609 	if (dbl)
1610 	    *buf++ = tmp;
1611 	j++;
1612 	datab >>= 2;
1613 	if (do_collisions) {
1614 	    tmp &= collision_mask;
1615 	    if (tmp) {
1616 		unsigned int shrunk_tmp = sprite_ab_merge[tmp & 255] | (sprite_ab_merge[tmp >> 8] << 2);
1617 		clxdat |= sprclx[shrunk_tmp];
1618 	    }
1619 	}
1620     }
1621 }
1622 
1623 /* DATAB contains the sprite data; 16 pixels in two-bit packets.  Bits 0/1
1624    determine the color of the leftmost pixel, bits 2/3 the color of the next
1625    etc.
1626    This function assumes that for all sprites in a given line, SPRXP either
1627    stays equal or increases between successive calls.
1628 
1629    The data is recorded either in lores pixels (if ECS), or in hires pixels
1630    (if AGA).  No support for SHRES sprites.  */
1631 
record_sprite(int line,int num,int sprxp,uae_u16 * data,uae_u16 * datb,unsigned int ctl)1632 static void record_sprite (int line, int num, int sprxp, uae_u16 *data, uae_u16 *datb, unsigned int ctl)
1633 {
1634     struct sprite_entry *e = curr_sprite_entries + next_sprite_entry;
1635     int i;
1636     int word_offs;
1637     uae_u16 *buf;
1638     uae_u32 collision_mask;
1639     int width = sprite_width;
1640     int dbl = 0, half = 0;
1641     unsigned int mask = 0;
1642 
1643     if (sprres != RES_LORES)
1644 	thisline_decision.any_hires_sprites = 1;
1645 
1646     if (currprefs.chipset_mask & CSMASK_AGA) {
1647 	width = (width << 1) >> sprres;
1648 	dbl = sprite_buffer_res - sprres;
1649 	if (dbl < 0) {
1650 	    half = -dbl;
1651 	    dbl = 0;
1652 	}
1653 	mask = sprres == RES_SUPERHIRES ? 1 : 0;
1654     }
1655 
1656     /* Try to coalesce entries if they aren't too far apart.  */
1657     if (! next_sprite_forced && e[-1].max + 16 >= sprxp) {
1658 	e--;
1659     } else {
1660 	next_sprite_entry++;
1661 	e->pos = sprxp;
1662 	e->has_attached = 0;
1663     }
1664 
1665     if (sprxp < e->pos)
1666 	uae_abort ("sprxp < e->pos");
1667 
1668     e->max = sprxp + width;
1669     e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3);
1670     next_sprite_forced = 0;
1671 
1672     collision_mask = clxmask[clxcon >> 12];
1673     word_offs = e->first_pixel + sprxp - e->pos;
1674 
1675     for (i = 0; i < sprite_width; i += 16) {
1676 	unsigned int da = *data;
1677 	unsigned int db = *datb;
1678 	uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8]
1679 			 | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]);
1680 
1681 	buf = spixels + word_offs + ((i << dbl) >> half);
1682 	if (currprefs.collision_level > 0 && collision_mask)
1683 	    record_sprite_1 (buf, datab, num, dbl, mask, 1, collision_mask);
1684 	else
1685 	    record_sprite_1 (buf, datab, num, dbl, mask, 0, collision_mask);
1686 	data++;
1687 	datb++;
1688     }
1689 
1690     /* We have 8 bits per pixel in spixstate, two for every sprite pair.  The
1691        low order bit records whether the attach bit was set for this pair.  */
1692 
1693     if (ctl & (num << 7) & 0x80) {
1694 	uae_u32 state = 0x01010101 << (num - 1);
1695 	uae_u32 *stbuf = spixstate.words + (word_offs >> 2);
1696 	uae_u8 *stb1 = spixstate.bytes + word_offs;
1697 	for (i = 0; i < width; i += 8) {
1698 	    stb1[0] |= state;
1699 	    stb1[1] |= state;
1700 	    stb1[2] |= state;
1701 	    stb1[3] |= state;
1702 	    stb1[4] |= state;
1703 	    stb1[5] |= state;
1704 	    stb1[6] |= state;
1705 	    stb1[7] |= state;
1706 	    stb1 += 8;
1707 	}
1708 	e->has_attached = 1;
1709     }
1710 }
1711 
decide_sprites(int hpos)1712 static void decide_sprites (int hpos)
1713 {
1714     int nrs[MAX_SPRITES], posns[MAX_SPRITES];
1715     int count, i;
1716     int point = hpos * 2;
1717     int width = sprite_width;
1718     int window_width = (width << lores_shift) >> sprres;
1719 
1720     if (nodraw () || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point)
1721 	return;
1722 
1723     decide_diw (hpos);
1724     decide_line (hpos);
1725 
1726 #if 0
1727     /* This tries to detect whether the line is border, but that doesn't work, it's too early.  */
1728     if (thisline_decision.plfleft == -1)
1729 	return;
1730 #endif
1731     count = 0;
1732     for (i = 0; i < MAX_SPRITES; i++) {
1733 	int sprxp = spr[i].xpos;
1734 	int hw_xp = (sprxp >> sprite_buffer_res);
1735 	int window_xp = coord_hw_to_window_x (hw_xp) + (DIW_DDF_OFFSET << lores_shift);
1736 	int j, bestp;
1737 
1738 	if (! spr[i].armed || sprxp < 0 || hw_xp <= last_sprite_point || hw_xp > point)
1739 	    continue;
1740 	if ((thisline_decision.diwfirstword >= 0 && window_xp + window_width < thisline_decision.diwfirstword)
1741 	    || (thisline_decision.diwlastword >= 0 && window_xp > thisline_decision.diwlastword))
1742 	    continue;
1743 
1744 	/* Sort the sprites in order of ascending X position before recording them.  */
1745 	for (bestp = 0; bestp < count; bestp++) {
1746 	    if (posns[bestp] > sprxp)
1747 		break;
1748 	    if (posns[bestp] == sprxp && nrs[bestp] < i)
1749 		break;
1750 	}
1751 	for (j = count; j > bestp; j--) {
1752 	    posns[j] = posns[j-1];
1753 	    nrs[j] = nrs[j-1];
1754 	}
1755 	posns[j] = sprxp;
1756 	nrs[j] = i;
1757 	count++;
1758     }
1759     for (i = 0; i < count; i++) {
1760 	int nr = nrs[i];
1761 	record_sprite (next_lineno, nr, spr[nr].xpos, sprdata[nr], sprdatb[nr], sprctl[nr]);
1762     }
1763     last_sprite_point = point;
1764 }
1765 
sprites_differ(struct draw_info * dip,struct draw_info * dip_old)1766 STATIC_INLINE int sprites_differ (struct draw_info *dip, struct draw_info *dip_old)
1767 {
1768     struct sprite_entry *this_first = curr_sprite_entries + dip->first_sprite_entry;
1769     struct sprite_entry *this_last = curr_sprite_entries + dip->last_sprite_entry;
1770     struct sprite_entry *prev_first = prev_sprite_entries + dip_old->first_sprite_entry;
1771     int npixels;
1772     int i;
1773 
1774     if (dip->nr_sprites != dip_old->nr_sprites)
1775 	return 1;
1776 
1777     if (dip->nr_sprites == 0)
1778 	return 0;
1779 
1780     for (i = 0; i < dip->nr_sprites; i++)
1781 	if (this_first[i].pos != prev_first[i].pos
1782 	    || this_first[i].max != prev_first[i].max
1783 	    || this_first[i].has_attached != prev_first[i].has_attached)
1784 	    return 1;
1785 
1786     npixels = this_last->first_pixel + (this_last->max - this_last->pos) - this_first->first_pixel;
1787     if (memcmp (spixels + this_first->first_pixel, spixels + prev_first->first_pixel,
1788 		npixels * sizeof (uae_u16)) != 0)
1789 	return 1;
1790     if (memcmp (spixstate.bytes + this_first->first_pixel, spixstate.bytes + prev_first->first_pixel, npixels) != 0)
1791 	return 1;
1792     return 0;
1793 }
1794 
color_changes_differ(struct draw_info * dip,struct draw_info * dip_old)1795 STATIC_INLINE int color_changes_differ (struct draw_info *dip, struct draw_info *dip_old)
1796 {
1797     if (dip->nr_color_changes != dip_old->nr_color_changes)
1798 	return 1;
1799 
1800     if (dip->nr_color_changes == 0)
1801 	return 0;
1802     if (memcmp (curr_color_changes + dip->first_color_change,
1803 		prev_color_changes + dip_old->first_color_change,
1804 		dip->nr_color_changes * sizeof *curr_color_changes) != 0)
1805 	return 1;
1806     return 0;
1807 }
1808 
1809 /* End of a horizontal scan line. Finish off all decisions that were not
1810  * made yet. */
finish_decisions(void)1811 static void finish_decisions (void)
1812 {
1813     struct draw_info *dip;
1814     struct draw_info *dip_old;
1815     struct decision *dp;
1816     int changed;
1817     int hpos = current_hpos ();
1818 
1819     if (nodraw ())
1820 	return;
1821 
1822     decide_diw (hpos);
1823     decide_line (hpos);
1824     decide_fetch (hpos);
1825 
1826     if (thisline_decision.plfleft != -1 && thisline_decision.plflinelen == -1) {
1827 	if (fetch_state != fetch_not_started)
1828 	    abort ();
1829 	thisline_decision.plfright = thisline_decision.plfleft;
1830 	thisline_decision.plflinelen = 0;
1831 	thisline_decision.bplres = RES_LORES;
1832     }
1833 
1834     /* Large DIWSTOP values can cause the stop position never to be
1835      * reached, so the state machine always stays in the same state and
1836      * there's a more-or-less full-screen DIW. */
1837     if (hdiwstate == DIW_waiting_stop || thisline_decision.diwlastword > max_diwlastword)
1838 	thisline_decision.diwlastword = max_diwlastword;
1839 
1840     if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
1841 	MARK_LINE_CHANGED;
1842     if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword)
1843 	MARK_LINE_CHANGED;
1844 
1845     dip = curr_drawinfo + next_lineno;
1846     dip_old = prev_drawinfo + next_lineno;
1847     dp = line_decisions + next_lineno;
1848     changed = thisline_changed;
1849 
1850     if (thisline_decision.plfleft != -1) {
1851 	record_diw_line (thisline_decision.diwfirstword, thisline_decision.diwlastword);
1852 
1853 	decide_sprites (hpos);
1854     }
1855 
1856     dip->last_sprite_entry = next_sprite_entry;
1857     dip->last_color_change = next_color_change;
1858 
1859     if (thisline_decision.ctable == -1) {
1860 	if (thisline_decision.plfleft == -1)
1861 	    remember_ctable_for_border ();
1862 	else
1863 	    remember_ctable ();
1864     }
1865 
1866     dip->nr_color_changes = next_color_change - dip->first_color_change;
1867     dip->nr_sprites = next_sprite_entry - dip->first_sprite_entry;
1868 
1869     if (thisline_decision.plfleft != line_decisions[next_lineno].plfleft)
1870 	changed = 1;
1871     if (! changed && color_changes_differ (dip, dip_old))
1872 	changed = 1;
1873     if (!changed && thisline_decision.plfleft != -1 && sprites_differ (dip, dip_old))
1874 	changed = 1;
1875 
1876     if (changed) {
1877 	thisline_changed = 1;
1878 	*dp = thisline_decision;
1879     } else
1880 	/* The only one that may differ: */
1881 	dp->ctable = thisline_decision.ctable;
1882 }
1883 
1884 /* Set the state of all decisions to "undecided" for a new scanline. */
reset_decisions(void)1885 static void reset_decisions (void)
1886 {
1887     if (nodraw ())
1888 	return;
1889 
1890     thisline_decision.any_hires_sprites = 0;
1891     thisline_decision.nr_planes = 0;
1892 
1893     thisline_decision.plfleft = -1;
1894     thisline_decision.plflinelen = -1;
1895     thisline_decision.ham_seen = !! (bplcon0 & 0x800);
1896     thisline_decision.ham_at_start = !! (bplcon0 & 0x800);
1897 
1898     /* decided_res shouldn't be touched before it's initialized by decide_line(). */
1899     thisline_decision.diwfirstword = -1;
1900     thisline_decision.diwlastword = -2;
1901     if (hdiwstate == DIW_waiting_stop) {
1902 	thisline_decision.diwfirstword = 0;
1903 	if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword)
1904 	    MARK_LINE_CHANGED;
1905     }
1906     thisline_decision.ctable = -1;
1907 
1908     thisline_changed = 0;
1909     curr_drawinfo[next_lineno].first_color_change = next_color_change;
1910     curr_drawinfo[next_lineno].first_sprite_entry = next_sprite_entry;
1911     next_sprite_forced = 1;
1912 
1913     /* memset(sprite_last_drawn_at, 0, sizeof sprite_last_drawn_at); */
1914     last_sprite_point = 0;
1915     fetch_state = fetch_not_started;
1916     passed_plfstop = 0;
1917 
1918     memset (todisplay, 0, sizeof todisplay);
1919     memset (fetched, 0, sizeof fetched);
1920     memset (fetched_aga0, 0, sizeof fetched_aga0);
1921     memset (fetched_aga1, 0, sizeof fetched_aga1);
1922     memset (outword, 0, sizeof outword);
1923 
1924     last_decide_line_hpos = -1;
1925     last_diw_pix_hpos = -1;
1926     last_ddf_pix_hpos = -1;
1927     last_sprite_hpos = -1;
1928     last_fetch_hpos = -1;
1929 }
1930 
dumpsync(void)1931 static void dumpsync (void)
1932 {
1933     static int cnt = 10;
1934     if (cnt < 0)
1935 	return;
1936     cnt--;
1937     write_log ("BEAMCON0=%04.4X VTOTAL=%04.4X HTOTAL=%04.4X\n", new_beamcon0, vtotal, htotal);
1938     write_log ("HSSTOP=%04.4X HBSTRT=%04.4X HBSTOP=%04.4X\n", hsstop, hbstrt, hbstop);
1939     write_log ("VSSTOP=%04.4X VBSTRT=%04.4X VBSTOP=%04.4X\n", vsstop, vbstrt, vbstop);
1940     write_log ("HSSTRT=%04.4X VSSTRT=%04.4X HCENTER=%04.4X\n", hsstrt, vsstrt, hcenter);
1941 }
1942 
1943 /* set PAL or NTSC timing variables */
1944 
init_hz(void)1945 static void init_hz (void)
1946 {
1947     int isntsc;
1948 
1949     beamcon0 = new_beamcon0;
1950 
1951     isntsc = beamcon0 & 0x20 ? 0 : 1;
1952     if (!isntsc) {
1953 	maxvpos = MAXVPOS_PAL;
1954 	maxhpos = MAXHPOS_PAL;
1955 	minfirstline = VBLANK_ENDLINE_PAL;
1956 	vblank_hz = VBLANK_HZ_PAL;
1957 	sprite_vblank_endline = VBLANK_SPRITE_PAL;
1958     } else {
1959 	maxvpos = MAXVPOS_NTSC;
1960 	maxhpos = MAXHPOS_NTSC;
1961 	minfirstline = VBLANK_ENDLINE_NTSC;
1962 	vblank_hz = VBLANK_HZ_NTSC;
1963 	sprite_vblank_endline = VBLANK_SPRITE_NTSC;
1964     }
1965     if (beamcon0 & 0x80) {
1966 	if (vtotal >= MAXVPOS)
1967 	    vtotal = MAXVPOS - 1;
1968 	maxvpos = vtotal + 1;
1969 	if (htotal >= MAXHPOS)
1970 	    htotal = MAXHPOS - 1;
1971 	maxhpos = htotal + 1;
1972 	vblank_hz = 227 * 312 * 50 / (maxvpos * maxhpos);
1973 	minfirstline = vsstop;
1974 	if (minfirstline < 2)
1975 	    minfirstline = 2;
1976 	if (minfirstline >= maxvpos)
1977 	    minfirstline = maxvpos - 1;
1978 	sprite_vblank_endline = minfirstline - 2;
1979 	dumpsync ();
1980     }
1981     eventtab[ev_hsync].oldcycles = get_cycles ();
1982     eventtab[ev_hsync].evtime = get_cycles() + HSYNCTIME;
1983     events_schedule ();
1984     compute_vsynctime ();
1985 
1986     write_log ("%s mode, %dHz (h=%d v=%d)\n",
1987 	       isntsc ? "NTSC" : "PAL", vblank_hz, maxhpos, maxvpos);
1988 }
1989 
calcdiw(void)1990 static void calcdiw (void)
1991 {
1992     int hstrt = diwstrt & 0xFF;
1993     int hstop = diwstop & 0xFF;
1994     int vstrt = diwstrt >> 8;
1995     int vstop = diwstop >> 8;
1996 
1997     if (diwhigh_written) {
1998 	hstrt |= ((diwhigh >> 5) & 1) << 8;
1999 	hstop |= ((diwhigh >> 13) & 1) << 8;
2000 	vstrt |= (diwhigh & 7) << 8;
2001 	vstop |= ((diwhigh >> 8) & 7) << 8;
2002     } else {
2003 	hstop += 0x100;
2004 	if ((vstop & 0x80) == 0)
2005 	    vstop |= 0x100;
2006     }
2007 
2008     diwfirstword = coord_diw_to_window_x (hstrt);
2009     diwlastword = coord_diw_to_window_x (hstop);
2010     if (diwfirstword < 0)
2011 	diwfirstword = 0;
2012 
2013     plffirstline = vstrt;
2014     plflastline = vstop;
2015 
2016 #if 0
2017     /* This happens far too often. */
2018     if (plffirstline < minfirstline) {
2019 	write_log ("Warning: Playfield begins before line %d!\n", minfirstline);
2020 	plffirstline = minfirstline;
2021     }
2022 #endif
2023 
2024 #if 0 /* Turrican does this */
2025     if (plflastline > 313) {
2026 	write_log ("Warning: Playfield out of range!\n");
2027 	plflastline = 313;
2028     }
2029 #endif
2030     plfstrt = ddfstrt;
2031     plfstop = ddfstop;
2032     if (plfstrt < 0x18)
2033 	plfstrt = 0x18;
2034 }
2035 
2036 static int timehack_alive = 0;
2037 
timehack_helper(TrapContext * dummy)2038 static uae_u32 timehack_helper (TrapContext *dummy)
2039 {
2040 #ifdef HAVE_GETTIMEOFDAY
2041     struct timeval tv;
2042     if (m68k_dreg (regs, 0) == 0)
2043 	return timehack_alive;
2044 
2045     timehack_alive = 10;
2046 
2047     gettimeofday (&tv, NULL);
2048     put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24 - 2) * 60 * 60));
2049     put_long (m68k_areg (regs, 0) + 4, tv.tv_usec);
2050     return 0;
2051 #else
2052     return 2;
2053 #endif
2054 }
2055 
2056  /*
2057   * register functions
2058   */
DENISEID(void)2059 STATIC_INLINE uae_u16 DENISEID (void)
2060 {
2061     if (currprefs.chipset_mask & CSMASK_AGA)
2062 	return 0xF8;
2063     if (currprefs.chipset_mask & CSMASK_ECS_DENISE)
2064 	return 0xFC;
2065     return 0xFFFF;
2066 }
2067 
DMACONR(void)2068 STATIC_INLINE uae_u16 DMACONR (void)
2069 {
2070     return (dmacon | (bltstate==BLT_done ? 0 : 0x4000)
2071 	    | (blt_info.blitzero ? 0x2000 : 0));
2072 }
2073 
INTENAR(void)2074 STATIC_INLINE uae_u16 INTENAR (void)
2075 {
2076     return intena;
2077 }
2078 
INTREQR(void)2079 uae_u16 INTREQR (void)
2080 {
2081     return intreq;
2082 }
2083 
ADKCONR(void)2084 STATIC_INLINE uae_u16 ADKCONR (void)
2085 {
2086     return adkcon;
2087 }
2088 
VPOSR(void)2089 STATIC_INLINE uae_u16 VPOSR (void)
2090 {
2091     unsigned int csbit = currprefs.ntscmode ? 0x1000 : 0;
2092     csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0;
2093     csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0;
2094     return (vpos >> 8) | lof | csbit;
2095 }
2096 
VPOSW(uae_u16 v)2097 static void VPOSW (uae_u16 v)
2098 {
2099     if (lof != (v & 0x8000))
2100 	lof_changed = 1;
2101     lof = v & 0x8000;
2102     /*
2103      * This register is much more fun on a real Amiga. You can program
2104      * refresh rates with it ;) But I won't emulate this...
2105      */
2106 }
2107 
VHPOSR(void)2108 STATIC_INLINE uae_u16 VHPOSR (void)
2109 {
2110     return (vpos << 8) | current_hpos ();
2111 }
2112 
COP1LCH(uae_u16 v)2113 STATIC_INLINE void COP1LCH (uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); }
COP1LCL(uae_u16 v)2114 STATIC_INLINE void COP1LCL (uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); }
COP2LCH(uae_u16 v)2115 STATIC_INLINE void COP2LCH (uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); }
COP2LCL(uae_u16 v)2116 STATIC_INLINE void COP2LCL (uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); }
2117 
COPJMP(int num)2118 static void COPJMP (int num)
2119 {
2120     int was_active = eventtab[ev_copper].active;
2121     cop_state.ip = num == 1 ? cop1lc : cop2lc;
2122     eventtab[ev_copper].active = 0;
2123     if (was_active)
2124 	events_schedule ();
2125 
2126     cop_state.ignore_next = 0;
2127     cop_state.state = COP_read1;
2128     cop_state.vpos = vpos;
2129     cop_state.hpos = current_hpos () & ~1;
2130 
2131     if (dmaen (DMA_COPPER)) {
2132 	copper_enabled_thisline = 1;
2133 	set_special (SPCFLAG_COPPER);
2134     }
2135 }
2136 
COPCON(uae_u16 a)2137 STATIC_INLINE void COPCON (uae_u16 a)
2138 {
2139     copcon = a;
2140 }
2141 
DMACON(unsigned int hpos,uae_u16 v)2142 static void DMACON (unsigned int hpos, uae_u16 v)
2143 {
2144     int i;
2145 
2146     uae_u16 oldcon = dmacon;
2147 
2148     decide_line (hpos);
2149     decide_fetch (hpos);
2150 
2151     setclr (&dmacon, v);
2152     dmacon &= 0x1FFF;
2153 
2154     /* FIXME? Maybe we need to think a bit more about the master DMA enable
2155      * bit in these cases. */
2156     if ((dmacon & DMA_COPPER) != (oldcon & DMA_COPPER)) {
2157 	eventtab[ev_copper].active = 0;
2158     }
2159     if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) {
2160 	cop_state.ip = cop1lc;
2161 	cop_state.ignore_next = 0;
2162 	cop_state.state = COP_read1;
2163 	cop_state.vpos = vpos;
2164 	cop_state.hpos = hpos & ~1;
2165 	copper_enabled_thisline = 1;
2166 	set_special (SPCFLAG_COPPER);
2167     }
2168     if (! (dmacon & DMA_COPPER)) {
2169 	copper_enabled_thisline = 0;
2170 	unset_special (SPCFLAG_COPPER);
2171 	cop_state.state = COP_stop;
2172     }
2173 
2174     if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) {
2175 	static int count = 0;
2176 	if (!count) {
2177 	    count = 1;
2178 	    write_log ("warning: program is doing blitpri hacks.\n");
2179 	}
2180 	set_special (SPCFLAG_BLTNASTY);
2181     }
2182     if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER))
2183 	unset_special (SPCFLAG_BLTNASTY);
2184 
2185     if (currprefs.produce_sound > 0)
2186 	update_audio_dmacon ();
2187 
2188     events_schedule();
2189 }
2190 
2191 /*
2192  * Get level of interrupt request presented to CPU.
2193  *
2194  * If no IRQs are active and enabled, returns -1.
2195  * If none of the active IRQs have yet reached the CPU, returns 0.
2196  * Otherwise, returns the priority level of the highest priorty active IRQ.
2197  */
intlev(void)2198 int intlev (void)
2199 {
2200     uae_u16 imask = intreq & intena;
2201     if (imask && (intena & 0x4000)){
2202 	if (imask & 0x2000) return 6;
2203 	if (imask & 0x1800) return 5;
2204 	if (imask & 0x0780) return 4;
2205 	if (imask & 0x0070) return 3;
2206 	if (imask & 0x0008) return 2;
2207 	if (imask & 0x0007) return 1;
2208     }
2209     return -1;
2210 }
2211 
2212 /*static int trace_intena = 0;*/
2213 
INTENA(uae_u16 v)2214 STATIC_INLINE void INTENA (uae_u16 v)
2215 {
2216 /*    if (trace_intena)
2217 	write_log ("INTENA: %04x\n", v);*/
2218     setclr (&intena,v);
2219     /* There's stupid code out there that does
2220 	[some INTREQ bits at level 3 are set]
2221 	clear all INTREQ bits
2222 	Enable one INTREQ level 3 bit
2223 	Set level 3 handler
2224 
2225 	If we set SPCFLAG_INT for the clear, then by the time the enable happens,
2226 	we'll have SPCFLAG_DOINT set, and the interrupt happens immediately, but
2227 	it needs to happen one insn later, when the new L3 handler has been
2228 	installed.  */
2229     if (v & 0x8000)
2230 	set_special (SPCFLAG_INT);
2231 }
2232 
INTREQ_0(uae_u16 v)2233 void INTREQ_0 (uae_u16 v)
2234 {
2235     setclr (&intreq,v);
2236     set_special (SPCFLAG_INT);
2237 }
2238 
INTREQ(uae_u16 v)2239 void INTREQ (uae_u16 v)
2240 {
2241     INTREQ_0 (v);
2242     if ((v & 0x8800) == 0x0800)
2243 	serdat &= 0xbfff;
2244     rethink_cias ();
2245 }
2246 
ADKCON(uae_u16 v)2247 static void ADKCON (uae_u16 v)
2248 {
2249     if (currprefs.produce_sound > 0)
2250 	update_audio ();
2251 
2252     setclr (&adkcon,v);
2253     update_adkmasks ();
2254 }
2255 
BEAMCON0(uae_u16 v)2256 static void BEAMCON0 (uae_u16 v)
2257 {
2258     if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) {
2259 	if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE))
2260 	    v &= 0x20;
2261 	if (v != new_beamcon0) {
2262 	    new_beamcon0 = v;
2263 	    if (v & ~0x20)
2264 		write_log ("warning: %04.4X written to BEAMCON0\n", v);
2265 	}
2266     }
2267 }
2268 
varsync(void)2269 static void varsync (void)
2270 {
2271     if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE))
2272 	return;
2273     if (!(beamcon0 & 0x80))
2274 	return;
2275 }
2276 
BPLxPTH(int hpos,uae_u16 v,int num)2277 static void BPLxPTH (int hpos, uae_u16 v, int num)
2278 {
2279     decide_line (hpos);
2280     decide_fetch (hpos);
2281     bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16);
2282 }
BPLxPTL(int hpos,uae_u16 v,int num)2283 static void BPLxPTL (int hpos, uae_u16 v, int num)
2284 {
2285     decide_line (hpos);
2286     decide_fetch (hpos);
2287     bplpt[num] = (bplpt[num] & ~0xffff) | (v & 0xfffe);
2288 }
2289 
BPLCON0(int hpos,uae_u16 v)2290 static void BPLCON0 (int hpos, uae_u16 v)
2291 {
2292     if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
2293 	v &= ~0x00F1;
2294     else if (! (currprefs.chipset_mask & CSMASK_AGA))
2295 	v &= ~0x00B1;
2296 
2297     if (bplcon0 == v)
2298 	return;
2299     decide_line (hpos);
2300     decide_fetch (hpos);
2301 
2302     /* HAM change?  */
2303     if ((bplcon0 ^ v) & 0x800) {
2304 	record_color_change (hpos, -1, !! (v & 0x800));
2305     }
2306 
2307     bplcon0 = v;
2308     curr_diagram = cycle_diagram_table[fetchmode][GET_RES(bplcon0)][GET_PLANES (v)];
2309 
2310     if (currprefs.chipset_mask & CSMASK_AGA) {
2311 	decide_sprites (hpos);
2312 	expand_sprres ();
2313     }
2314 
2315     expand_fmodes ();
2316 }
2317 
BPLCON1(int hpos,uae_u16 v)2318 STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v)
2319 {
2320     if (bplcon1 == v)
2321 	return;
2322     decide_line (hpos);
2323     decide_fetch (hpos);
2324     bplcon1 = v;
2325 }
2326 
BPLCON2(int hpos,uae_u16 v)2327 STATIC_INLINE void BPLCON2 (int hpos, uae_u16 v)
2328 {
2329     if (bplcon2 == v)
2330 	return;
2331     decide_line (hpos);
2332     bplcon2 = v;
2333 }
2334 
BPLCON3(int hpos,uae_u16 v)2335 STATIC_INLINE void BPLCON3 (int hpos, uae_u16 v)
2336 {
2337     if (! (currprefs.chipset_mask & CSMASK_AGA))
2338 	return;
2339     if (bplcon3 == v)
2340 	return;
2341     decide_line (hpos);
2342     decide_sprites (hpos);
2343     bplcon3 = v;
2344     expand_sprres ();
2345 }
2346 
BPLCON4(int hpos,uae_u16 v)2347 STATIC_INLINE void BPLCON4 (int hpos, uae_u16 v)
2348 {
2349     if (! (currprefs.chipset_mask & CSMASK_AGA))
2350 	return;
2351     if (bplcon4 == v)
2352 	return;
2353     decide_line (hpos);
2354     bplcon4 = v;
2355 }
2356 
BPL1MOD(int hpos,uae_u16 v)2357 static void BPL1MOD (int hpos, uae_u16 v)
2358 {
2359     v &= ~1;
2360     if ((uae_s16)bpl1mod == (uae_s16)v)
2361 	return;
2362     decide_line (hpos);
2363     decide_fetch (hpos);
2364     bpl1mod = v;
2365 }
2366 
BPL2MOD(int hpos,uae_u16 v)2367 static void BPL2MOD (int hpos, uae_u16 v)
2368 {
2369     v &= ~1;
2370     if ((uae_s16)bpl2mod == (uae_s16)v)
2371 	return;
2372     decide_line (hpos);
2373     decide_fetch (hpos);
2374     bpl2mod = v;
2375 }
2376 
BPL1DAT(int hpos,uae_u16 v)2377 STATIC_INLINE void BPL1DAT (int hpos, uae_u16 v)
2378 {
2379     decide_line (hpos);
2380     bpl1dat = v;
2381 
2382     maybe_first_bpl1dat (hpos);
2383 }
2384 /* We could do as well without those... */
BPL2DAT(uae_u16 v)2385 STATIC_INLINE void BPL2DAT (uae_u16 v) { bpl2dat = v; }
BPL3DAT(uae_u16 v)2386 STATIC_INLINE void BPL3DAT (uae_u16 v) { bpl3dat = v; }
BPL4DAT(uae_u16 v)2387 STATIC_INLINE void BPL4DAT (uae_u16 v) { bpl4dat = v; }
BPL5DAT(uae_u16 v)2388 STATIC_INLINE void BPL5DAT (uae_u16 v) { bpl5dat = v; }
BPL6DAT(uae_u16 v)2389 STATIC_INLINE void BPL6DAT (uae_u16 v) { bpl6dat = v; }
BPL7DAT(uae_u16 v)2390 STATIC_INLINE void BPL7DAT (uae_u16 v) { bpl7dat = v; }
BPL8DAT(uae_u16 v)2391 STATIC_INLINE void BPL8DAT (uae_u16 v) { bpl8dat = v; }
2392 
DIWSTRT(int hpos,uae_u16 v)2393 static void DIWSTRT (int hpos, uae_u16 v)
2394 {
2395     if (diwstrt == v && ! diwhigh_written)
2396 	return;
2397     decide_line (hpos);
2398     diwhigh_written = 0;
2399     diwstrt = v;
2400     calcdiw ();
2401 }
2402 
DIWSTOP(int hpos,uae_u16 v)2403 static void DIWSTOP (int hpos, uae_u16 v)
2404 {
2405     if (diwstop == v && ! diwhigh_written)
2406 	return;
2407     decide_line (hpos);
2408     diwhigh_written = 0;
2409     diwstop = v;
2410     calcdiw ();
2411 }
2412 
DIWHIGH(int hpos,uae_u16 v)2413 static void DIWHIGH (int hpos, uae_u16 v)
2414 {
2415     if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE))
2416 	return;
2417     if (diwhigh_written && diwhigh == v)
2418 	return;
2419     decide_line (hpos);
2420     diwhigh_written = 1;
2421     diwhigh = v;
2422     calcdiw ();
2423 }
2424 
DDFSTRT(int hpos,uae_u16 v)2425 static void DDFSTRT (int hpos, uae_u16 v)
2426 {
2427     v &= 0xFC;
2428     if (ddfstrt == v)
2429 	return;
2430     decide_line (hpos);
2431     ddfstrt = v;
2432     calcdiw ();
2433     if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
2434 	static int last_warned;
2435 	last_warned = (last_warned + 1) & 4095;
2436 	if (last_warned == 0)
2437 	    write_log ("WARNING! Very strange DDF values.\n");
2438     }
2439 }
2440 
DDFSTOP(int hpos,uae_u16 v)2441 static void DDFSTOP (int hpos, uae_u16 v)
2442 {
2443     /* ??? "Virtual Meltdown" sets this to 0xD2 and expects it to behave
2444        differently from 0xD0.  RSI Megademo sets it to 0xd1 and expects it
2445        to behave like 0xd0.  Some people also write the high 8 bits and
2446        expect them to be ignored.  So mask it with 0xFE.  */
2447     v &= 0xFE;
2448     if (ddfstop == v)
2449 	return;
2450     decide_line (hpos);
2451     decide_fetch (hpos);
2452     ddfstop = v;
2453     calcdiw ();
2454     if (fetch_state != fetch_not_started)
2455 	estimate_last_fetch_cycle (hpos);
2456     if (ddfstop > 0xD4 && (ddfstrt & 4) == 4) {
2457 	static int last_warned;
2458 	last_warned = (last_warned + 1) & 4095;
2459 	if (last_warned == 0)
2460 	    write_log ("WARNING! Very strange DDF values.\n");
2461 	write_log ("WARNING! Very strange DDF values.\n");
2462     }
2463 }
2464 
FMODE(uae_u16 v)2465 static void FMODE (uae_u16 v)
2466 {
2467     if (! (currprefs.chipset_mask & CSMASK_AGA))
2468 	v = 0;
2469 
2470     fmode = v;
2471     sprite_width = GET_SPRITEWIDTH (fmode);
2472     switch (fmode & 3) {
2473     case 0:
2474 	fetchmode = 0;
2475 	break;
2476     case 1:
2477     case 2:
2478 	fetchmode = 1;
2479 	break;
2480     case 3:
2481 	fetchmode = 2;
2482 	break;
2483     }
2484     curr_diagram = cycle_diagram_table[fetchmode][GET_RES (v)][GET_PLANES (bplcon0)];
2485     expand_fmodes ();
2486 }
2487 
BLTADAT(uae_u16 v)2488 static void BLTADAT (uae_u16 v)
2489 {
2490     maybe_blit (0);
2491 
2492     blt_info.bltadat = v;
2493 }
2494 /*
2495  * "Loading data shifts it immediately" says the HRM. Well, that may
2496  * be true for BLTBDAT, but not for BLTADAT - it appears the A data must be
2497  * loaded for every word so that AFWM and ALWM can be applied.
2498  */
BLTBDAT(uae_u16 v)2499 static void BLTBDAT (uae_u16 v)
2500 {
2501     maybe_blit (0);
2502 
2503     if (bltcon1 & 2)
2504 	blt_info.bltbhold = v << (bltcon1 >> 12);
2505     else
2506 	blt_info.bltbhold = v >> (bltcon1 >> 12);
2507     blt_info.bltbdat = v;
2508 }
BLTCDAT(uae_u16 v)2509 static void BLTCDAT (uae_u16 v) { maybe_blit (0); blt_info.bltcdat = v; }
2510 
BLTAMOD(uae_u16 v)2511 static void BLTAMOD (uae_u16 v) { maybe_blit (1); blt_info.bltamod = (uae_s16)(v & 0xFFFE); }
BLTBMOD(uae_u16 v)2512 static void BLTBMOD (uae_u16 v) { maybe_blit (1); blt_info.bltbmod = (uae_s16)(v & 0xFFFE); }
BLTCMOD(uae_u16 v)2513 static void BLTCMOD (uae_u16 v) { maybe_blit (1); blt_info.bltcmod = (uae_s16)(v & 0xFFFE); }
BLTDMOD(uae_u16 v)2514 static void BLTDMOD (uae_u16 v) { maybe_blit (1); blt_info.bltdmod = (uae_s16)(v & 0xFFFE); }
2515 
BLTCON0(uae_u16 v)2516 static void BLTCON0 (uae_u16 v) { maybe_blit (0); bltcon0 = v; blinea_shift = v >> 12; }
2517 /* The next category is "Most useless hardware register".
2518  * And the winner is... */
BLTCON0L(uae_u16 v)2519 static void BLTCON0L (uae_u16 v)
2520 {
2521     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2522 	return;
2523     maybe_blit (0); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF);
2524 }
BLTCON1(uae_u16 v)2525 static void BLTCON1 (uae_u16 v) { maybe_blit (0); bltcon1 = v; }
2526 
BLTAFWM(uae_u16 v)2527 static void BLTAFWM (uae_u16 v) { maybe_blit (0); blt_info.bltafwm = v; }
BLTALWM(uae_u16 v)2528 static void BLTALWM (uae_u16 v) { maybe_blit (0); blt_info.bltalwm = v; }
2529 
BLTAPTH(uae_u16 v)2530 static void BLTAPTH (uae_u16 v) { maybe_blit (0); bltapt = (bltapt & 0xffff) | ((uae_u32)v << 16); }
BLTAPTL(uae_u16 v)2531 static void BLTAPTL (uae_u16 v) { maybe_blit (0); bltapt = (bltapt & ~0xffff) | (v & 0xFFFE); }
BLTBPTH(uae_u16 v)2532 static void BLTBPTH (uae_u16 v) { maybe_blit (0); bltbpt = (bltbpt & 0xffff) | ((uae_u32)v << 16); }
BLTBPTL(uae_u16 v)2533 static void BLTBPTL (uae_u16 v) { maybe_blit (0); bltbpt = (bltbpt & ~0xffff) | (v & 0xFFFE); }
BLTCPTH(uae_u16 v)2534 static void BLTCPTH (uae_u16 v) { maybe_blit (0); bltcpt = (bltcpt & 0xffff) | ((uae_u32)v << 16); }
BLTCPTL(uae_u16 v)2535 static void BLTCPTL (uae_u16 v) { maybe_blit (0); bltcpt = (bltcpt & ~0xffff) | (v & 0xFFFE); }
BLTDPTH(uae_u16 v)2536 static void BLTDPTH (uae_u16 v) { maybe_blit (0); bltdpt = (bltdpt & 0xffff) | ((uae_u32)v << 16); }
BLTDPTL(uae_u16 v)2537 static void BLTDPTL (uae_u16 v) { maybe_blit (0); bltdpt = (bltdpt & ~0xffff) | (v & 0xFFFE); }
2538 
BLTSIZE(uae_u16 v)2539 static void BLTSIZE (uae_u16 v)
2540 {
2541     maybe_blit (0);
2542 
2543     blt_info.vblitsize = v >> 6;
2544     blt_info.hblitsize = v & 0x3F;
2545     if (!blt_info.vblitsize) blt_info.vblitsize = 1024;
2546     if (!blt_info.hblitsize) blt_info.hblitsize = 64;
2547 
2548     bltstate = BLT_init;
2549     do_blitter ();
2550 }
2551 
BLTSIZV(uae_u16 v)2552 static void BLTSIZV (uae_u16 v)
2553 {
2554     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2555 	return;
2556     maybe_blit (0);
2557     oldvblts = v & 0x7FFF;
2558 }
2559 
BLTSIZH(uae_u16 v)2560 static void BLTSIZH (uae_u16 v)
2561 {
2562     if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS))
2563 	return;
2564     maybe_blit (0);
2565     blt_info.hblitsize = v & 0x7FF;
2566     blt_info.vblitsize = oldvblts;
2567     if (!blt_info.vblitsize) blt_info.vblitsize = 32768;
2568     if (!blt_info.hblitsize) blt_info.hblitsize = 0x800;
2569     bltstate = BLT_init;
2570     do_blitter ();
2571 }
2572 
SPRxCTL_1(uae_u16 v,int num,int hpos)2573 STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num, int hpos)
2574 {
2575     int sprxp;
2576     struct sprite *s = &spr[num];
2577     sprctl[num] = v;
2578     nr_armed -= s->armed;
2579     s->armed = 0;
2580     sprxp = (sprpos[num] & 0xFF) * 2 + (v & 1);
2581 
2582     /* Quite a bit salad in this register... */
2583     if (currprefs.chipset_mask & CSMASK_AGA) {
2584 	/* We ignore the SHRES 35ns increment for now; SHRES support doesn't
2585 	   work anyway, so we may as well restrict AGA sprites to a 70ns
2586 	   resolution.  */
2587 	sprxp <<= 1;
2588 	sprxp |= (v >> 4) & 1;
2589     }
2590     s->xpos = sprxp;
2591     s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
2592     s->vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100);
2593     if (vpos == s->vstart)
2594 	s->state = SPR_waiting_stop;
2595 #ifdef SPRITE_DEBUG
2596     write_log ("%d:%d:SPR%dCTL V=%04.4X STATE=%d ARMED=%d\n", vpos, hpos, num, v, s->state, s->armed);
2597 #endif
2598 }
SPRxPOS_1(uae_u16 v,int num,int hpos)2599 STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num, int hpos)
2600 {
2601     int sprxp;
2602     struct sprite *s = &spr[num];
2603     sprpos[num] = v;
2604     sprxp = (v & 0xFF) * 2 + (sprctl[num] & 1);
2605 
2606     if (currprefs.chipset_mask & CSMASK_AGA) {
2607 	sprxp <<= 1;
2608 	sprxp |= (sprctl[num] >> 4) & 1;
2609     }
2610     s->xpos = sprxp;
2611     s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100);
2612 #ifdef SPRITE_DEBUG
2613     write_log ("%d:%d:SPR%dPOS %04.4X STATE=%d ARMED=%d\n", vpos, hpos, num, v, s->state, s->armed);
2614 #endif
2615 }
SPRxDATA_1(uae_u16 v,int num)2616 STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num)
2617 {
2618     sprdata[num][0] = v;
2619     nr_armed += 1 - spr[num].armed;
2620     spr[num].armed = 1;
2621 }
SPRxDATB_1(uae_u16 v,int num)2622 STATIC_INLINE void SPRxDATB_1 (uae_u16 v, int num)
2623 {
2624     sprdatb[num][0] = v;
2625 }
SPRxDATA(int hpos,uae_u16 v,int num)2626 static void SPRxDATA (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATA_1 (v, num); }
SPRxDATB(int hpos,uae_u16 v,int num)2627 static void SPRxDATB (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATB_1 (v, num); }
SPRxCTL(int hpos,uae_u16 v,int num)2628 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)2629 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)2630 static void SPRxPTH (int hpos, uae_u16 v, int num)
2631 {
2632     decide_sprites (hpos);
2633     spr[num].pt &= 0xffff;
2634     spr[num].pt |= (uae_u32)v << 16;
2635 #ifdef SPRITE_DEBUG
2636     write_log ("%d:%d:SPR%dPTH %08.8X\n", vpos, hpos, num, spr[num].pt);
2637 #endif
2638 }
SPRxPTL(int hpos,uae_u16 v,int num)2639 static void SPRxPTL (int hpos, uae_u16 v, int num)
2640 {
2641     decide_sprites (hpos);
2642     spr[num].pt &= ~0xffff;
2643     spr[num].pt |= v;
2644 #ifdef SPRITE_DEBUG
2645     write_log ("%d:%d:SPR%dPTL %08.8X\n", vpos, hpos, num, spr[num].pt);
2646 #endif
2647 }
2648 
CLXCON(uae_u16 v)2649 static void CLXCON (uae_u16 v)
2650 {
2651     clxcon = v;
2652     clxcon_bpl_enable = (v >> 6) & 63;
2653     clxcon_bpl_match = v & 63;
2654     clx_sprmask = ((((v >> 15) & 1) << 7) | (((v >> 14) & 1) << 5) | (((v >> 13) & 1) << 3) | (((v >> 12) & 1) << 1) | 0x55);
2655 }
CLXCON2(uae_u16 v)2656 static void CLXCON2 (uae_u16 v)
2657 {
2658     if (!(currprefs.chipset_mask & CSMASK_AGA))
2659 	return;
2660     clxcon2 = v;
2661     clxcon_bpl_enable |= v & (0x40|0x80);
2662     clxcon_bpl_match |= (v & (0x01|0x02)) << 6;
2663  }
CLXDAT(void)2664 static uae_u16 CLXDAT (void)
2665 {
2666     uae_u16 v = clxdat;
2667     clxdat = 0;
2668     return v;
2669 }
2670 
COLOR_READ(int num)2671 static uae_u16 COLOR_READ (int num)
2672 {
2673     int cr, cg, cb, colreg;
2674     uae_u16 cval;
2675 
2676     if (!(currprefs.chipset_mask & CSMASK_AGA) || !(bplcon2 & 0x0100))
2677 	return 0xffff;
2678 
2679     colreg = ((bplcon3 >> 13) & 7) * 32 + num;
2680     cr = current_colors.color_regs_aga[colreg] >> 16;
2681     cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
2682     cb = current_colors.color_regs_aga[colreg] & 0xFF;
2683     if (bplcon3 & 0x200)
2684 	cval = ((cr & 15) << 8) | ((cg & 15) << 4) | ((cb & 15) << 0);
2685     else
2686 	cval = ((cr >> 4) << 8) | ((cg >> 4) << 4) | ((cb >> 4) << 0);
2687     return cval;
2688 }
2689 
COLOR_WRITE(int hpos,uae_u16 v,int num)2690 static void COLOR_WRITE (int hpos, uae_u16 v, int num)
2691 {
2692     v &= 0xFFF;
2693     if (currprefs.chipset_mask & CSMASK_AGA) {
2694 	int r,g,b;
2695 	int cr,cg,cb;
2696 	int colreg;
2697 	uae_u32 cval;
2698 
2699 	/* writing is disabled when RDRAM=1 */
2700 	if (bplcon2 & 0x0100)
2701 	    return;
2702 
2703 	colreg = ((bplcon3 >> 13) & 7) * 32 + num;
2704 	r = (v & 0xF00) >> 8;
2705 	g = (v & 0xF0) >> 4;
2706 	b = (v & 0xF) >> 0;
2707 	cr = current_colors.color_regs_aga[colreg] >> 16;
2708 	cg = (current_colors.color_regs_aga[colreg] >> 8) & 0xFF;
2709 	cb = current_colors.color_regs_aga[colreg] & 0xFF;
2710 
2711 	if (bplcon3 & 0x200) {
2712 	    cr &= 0xF0; cr |= r;
2713 	    cg &= 0xF0; cg |= g;
2714 	    cb &= 0xF0; cb |= b;
2715 	} else {
2716 	    cr = r + (r << 4);
2717 	    cg = g + (g << 4);
2718 	    cb = b + (b << 4);
2719 	}
2720 	cval = (cr << 16) | (cg << 8) | cb;
2721 	if (cval == current_colors.color_regs_aga[colreg])
2722 	    return;
2723 
2724 	/* Call this with the old table still intact. */
2725 	record_color_change (hpos, colreg, cval);
2726 	remembered_color_entry = -1;
2727 	current_colors.color_regs_aga[colreg] = cval;
2728 	current_colors.acolors[colreg] = CONVERT_RGB (cval);
2729    } else {
2730 	if (current_colors.color_regs_ecs[num] == v)
2731 	    return;
2732 	/* Call this with the old table still intact. */
2733 	record_color_change (hpos, num, v);
2734 	remembered_color_entry = -1;
2735 	current_colors.color_regs_ecs[num] = v;
2736 	current_colors.acolors[num] = xcolors[v];
2737     }
2738 }
2739 
2740 /* The copper code.  The biggest nightmare in the whole emulator.
2741 
2742    Alright.  The current theory:
2743    1. Copper moves happen 2 cycles after state READ2 is reached.
2744       It can't happen immediately when we reach READ2, because the
2745       data needs time to get back from the bus.  An additional 2
2746       cycles are needed for non-Agnus registers, to take into account
2747       the delay for moving data from chip to chip.
2748    2. As stated in the HRM, a WAIT really does need an extra cycle
2749       to wake up.  This is implemented by _not_ falling through from
2750       a successful wait to READ1, but by starting the next cycle.
2751       (Note: the extra cycle for the WAIT apparently really needs a
2752       free cycle; i.e. contention with the bitplane fetch can slow
2753       it down).
2754    3. Apparently, to compensate for the extra wake up cycle, a WAIT
2755       will use the _incremented_ horizontal position, so the WAIT
2756       cycle normally finishes two clocks earlier than the position
2757       it was waiting for.  The extra cycle then takes us to the
2758       position that was waited for.
2759       If the earlier cycle is busy with a bitplane, things change a bit.
2760       E.g., waiting for position 0x50 in a 6 plane display: In cycle
2761       0x4e, we fetch BPL5, so the wait wakes up in 0x50, the extra cycle
2762       takes us to 0x54 (since 0x52 is busy), then we have READ1/READ2,
2763       and the next register write is at 0x5c.
2764    4. The last cycle in a line is not usable for the copper.
2765    5. A 4 cycle delay also applies to the WAIT instruction.  This means
2766       that the second of two back-to-back WAITs (or a WAIT whose
2767       condition is immediately true) takes 8 cycles.
2768    6. This also applies to a SKIP instruction.  The copper does not
2769       fetch the next instruction while waiting for the second word of
2770       a WAIT or a SKIP to arrive.
2771    7. A SKIP also seems to need an unexplained additional two cycles
2772       after its second word arrives; this is _not_ a memory cycle (I
2773       think, the documentation is pretty clear on this).
2774    8. Two additional cycles are inserted when writing to COPJMP1/2.  */
2775 
2776 /* Determine which cycles are available for the copper in a display
2777  * with a agiven number of planes.  */
2778 
copper_cant_read(int hpos)2779 STATIC_INLINE int copper_cant_read (int hpos)
2780 {
2781     int t;
2782 
2783     if (hpos + 1 >= maxhpos)
2784 	return 1;
2785 
2786     if (fetch_state == fetch_not_started || hpos < thisline_decision.plfleft)
2787 	return 0;
2788 
2789     if ((passed_plfstop == 3 && hpos >= thisline_decision.plfright)
2790 	|| hpos >= estimated_last_fetch_cycle)
2791 	return 0;
2792 
2793     t = curr_diagram[(hpos + cycle_diagram_shift) & fetchstart_mask];
2794 #if 0
2795     if (t == -1)
2796 	abort ();
2797 #endif
2798     return t;
2799 }
2800 
dangerous_reg(int reg)2801 STATIC_INLINE int dangerous_reg (int reg)
2802 {
2803     /* Safe:
2804      * Bitplane pointers, control registers, modulos and data.
2805      * Sprite pointers, control registers, and data.
2806      * Color registers.  */
2807     if (reg >= 0xE0 && reg < 0x1C0)
2808 	return 0;
2809     return 1;
2810 }
2811 
perform_copper_write(int old_hpos)2812 static void perform_copper_write (int old_hpos)
2813 {
2814     int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
2815     unsigned int address = cop_state.saved_i1 & 0x1FE;
2816 
2817     record_copper (cop_state.saved_ip - 4, old_hpos, vpos);
2818 
2819     if (address < (copcon & 2 ? ((currprefs.chipset_mask & CSMASK_AGA) ? 0 : 0x40u) : 0x80u)) {
2820 	cop_state.state = COP_stop;
2821 	copper_enabled_thisline = 0;
2822 	unset_special (SPCFLAG_COPPER);
2823 	return;
2824     }
2825 
2826     if (address == 0x88) {
2827 	cop_state.ip = cop1lc;
2828 	cop_state.state = COP_read1_in2;
2829     } else if (address == 0x8A) {
2830 	cop_state.ip = cop2lc;
2831 	cop_state.state = COP_read1_in2;
2832     } else
2833 	custom_wput_1 (old_hpos, address, cop_state.saved_i2);
2834 }
2835 
2836 static int isagnus[]= {
2837     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 */
2838     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, /* 27 0x40 - 0x74 */
2839 
2840     0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, /* 21 */
2841     1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0, /* 32 0xa0 - 0xde */
2842     /* BPLxPTH/BPLxPTL */
2843     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */
2844     /* BPLCON0-3,BPLMOD1-2 */
2845     0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0, /* 16 */
2846     /* SPRxPTH/SPRxPTL */
2847     1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */
2848     /* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */
2849     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,
2850     /* COLORxx */
2851     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,
2852     /* RESERVED */
2853     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
2854 };
2855 
update_copper(int until_hpos)2856 static void update_copper (int until_hpos)
2857 {
2858     int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
2859     int c_hpos = cop_state.hpos;
2860 
2861     if (eventtab[ev_copper].active)
2862 	abort ();
2863 
2864     if (cop_state.state == COP_wait && vp < cop_state.vcmp)
2865 	abort ();
2866 
2867     until_hpos &= ~1;
2868 
2869     if (until_hpos > (maxhpos & ~1))
2870 	until_hpos = maxhpos & ~1;
2871 
2872     until_hpos += 2;
2873     for (;;) {
2874 	int old_hpos = c_hpos;
2875 	int hp;
2876 
2877 	if (c_hpos >= until_hpos)
2878 	    break;
2879 
2880 	/* So we know about the fetch state.  */
2881 	decide_line (c_hpos);
2882 
2883 	switch (cop_state.state) {
2884 	case COP_read1_in2:
2885 	    cop_state.state = COP_read1;
2886 	    break;
2887 	case COP_read1_wr_in2:
2888 	    cop_state.state = COP_read1;
2889 	    perform_copper_write (old_hpos);
2890 	    /* That could have turned off the copper.  */
2891 	    if (! copper_enabled_thisline)
2892 		goto out;
2893 
2894 	    break;
2895 	case COP_read1_wr_in4:
2896 	    cop_state.state = COP_read1_wr_in2;
2897 	    break;
2898 	case COP_read2_wr_in2:
2899 	    cop_state.state = COP_read2;
2900 	    perform_copper_write (old_hpos);
2901 	    /* That could have turned off the copper.  */
2902 	    if (! copper_enabled_thisline)
2903 		goto out;
2904 
2905 	    break;
2906 	case COP_wait_in2:
2907 	    cop_state.state = COP_wait1;
2908 	    break;
2909 	case COP_wait_in4:
2910 	    cop_state.state = COP_wait_in2;
2911 	    break;
2912 	case COP_skip_in2:
2913 	{
2914 	    static int skipped_before;
2915 	    unsigned int vcmp, hcmp, vp1, hp1;
2916 	    cop_state.state = COP_read1_in2;
2917 
2918 	    vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
2919 	    hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
2920 
2921 	    if (! skipped_before) {
2922 		skipped_before = 1;
2923 		write_log ("Program uses Copper SKIP instruction.\n");
2924 	    }
2925 
2926 	    vp1 = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
2927 	    hp1 = old_hpos & (cop_state.saved_i2 & 0xFE);
2928 
2929 	    if ((vp1 > vcmp || (vp1 == vcmp && hp1 >= hcmp))
2930 		&& ((cop_state.saved_i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000)))
2931 		cop_state.ignore_next = 1;
2932 	    break;
2933 	}
2934 	case COP_skip_in4:
2935 	    cop_state.state = COP_skip_in2;
2936 	    break;
2937 	default:
2938 	    break;
2939 	}
2940 
2941 	c_hpos += 2;
2942 	if (copper_cant_read (old_hpos))
2943 	    continue;
2944 
2945 	switch (cop_state.state) {
2946 	case COP_read1_wr_in4:
2947 	    abort ();
2948 
2949 	case COP_read1_wr_in2:
2950 	case COP_read1:
2951 	    cop_state.i1 = chipmem_agnus_wget (cop_state.ip);
2952 	    cop_state.ip += 2;
2953 	    cop_state.state = cop_state.state == COP_read1 ? COP_read2 : COP_read2_wr_in2;
2954 	    break;
2955 
2956 	case COP_read2_wr_in2:
2957 	    abort ();
2958 
2959 	case COP_read2:
2960 	    cop_state.i2 = chipmem_agnus_wget (cop_state.ip);
2961 	    cop_state.ip += 2;
2962 	    if (cop_state.ignore_next) {
2963 		cop_state.ignore_next = 0;
2964 		cop_state.state = COP_read1;
2965 		break;
2966 	    }
2967 
2968 	    cop_state.saved_i1 = cop_state.i1;
2969 	    cop_state.saved_i2 = cop_state.i2;
2970 	    cop_state.saved_ip = cop_state.ip;
2971 
2972 	    if (cop_state.i1 & 1) {
2973 		if (cop_state.i2 & 1)
2974 		    cop_state.state = COP_skip_in4;
2975 		else
2976 		    cop_state.state = COP_wait_in4;
2977 	    } else {
2978 		unsigned int reg = cop_state.i1 & 0x1FE;
2979 		cop_state.state = isagnus[reg >> 1] ? COP_read1_wr_in2 : COP_read1_wr_in4;
2980 	    }
2981 	    break;
2982 
2983 	case COP_wait1:
2984 	    /* There's a nasty case here.  As stated in the "Theory" comment above, we
2985 	       test against the incremented copper position.  I believe this means that
2986 	       we have to increment the _vertical_ position at the last cycle in the line,
2987 	       and set the horizontal position to 0.
2988 	       Normally, this isn't going to make a difference, since we consider these
2989 	       last cycles unavailable for the copper, so waking up in the last cycle has
2990 	       the same effect as waking up at the start of the line.  However, there is
2991 	       one possible problem:  If we're at 0xFFE0, any wait for an earlier position
2992 	       must _not_ complete (since, in effect, the current position will be back
2993 	       at 0/0).  This can be seen in the Superfrog copper list.
2994 	       Things get monstrously complicated if we try to handle this "properly" by
2995 	       incrementing vpos and setting c_hpos to 0.  Especially the various speedup
2996 	       hacks really assume that vpos remains constant during one line.  Hence,
2997 	       this hack: defer the entire decision until the next line if necessary.  */
2998 	    if (c_hpos >= (maxhpos & ~1))
2999 		break;
3000 	    cop_state.state = COP_wait;
3001 
3002 	    cop_state.vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8;
3003 	    cop_state.hcmp = (cop_state.saved_i1 & cop_state.saved_i2 & 0xFE);
3004 
3005 	    vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3006 
3007 	    if (cop_state.saved_i1 == 0xFFFF && cop_state.saved_i2 == 0xFFFE) {
3008 		cop_state.state = COP_stop;
3009 		copper_enabled_thisline = 0;
3010 		unset_special (SPCFLAG_COPPER);
3011 		goto out;
3012 	    }
3013 	    if (vp < cop_state.vcmp) {
3014 		copper_enabled_thisline = 0;
3015 		unset_special (SPCFLAG_COPPER);
3016 		goto out;
3017 	    }
3018 
3019 	    /* fall through */
3020 	do_wait:
3021 	case COP_wait:
3022 	    if (vp < cop_state.vcmp)
3023 		abort ();
3024 
3025 	    hp = c_hpos & (cop_state.saved_i2 & 0xFE);
3026 	    if (vp == cop_state.vcmp && hp < cop_state.hcmp) {
3027 		/* Position not reached yet.  */
3028 		break;
3029 	    }
3030 
3031 	    /* Now we know that the comparisons were successful.  We might still
3032 	       have to wait for the blitter though.  */
3033 	    if ((cop_state.saved_i2 & 0x8000) == 0 && (DMACONR() & 0x4000)) {
3034 		/* We need to wait for the blitter.  */
3035 		cop_state.state = COP_bltwait;
3036 		copper_enabled_thisline = 0;
3037 		unset_special (SPCFLAG_COPPER);
3038 		goto out;
3039 	    }
3040 
3041 	    record_copper (cop_state.ip - 4, old_hpos, vpos);
3042 
3043 	    cop_state.state = COP_read1;
3044 	    break;
3045 
3046 	default:
3047 	    break;
3048 	}
3049     }
3050 
3051   out:
3052     cop_state.hpos = c_hpos;
3053 }
3054 
compute_spcflag_copper(void)3055 static void compute_spcflag_copper (void)
3056 {
3057     copper_enabled_thisline = 0;
3058     unset_special (SPCFLAG_COPPER);
3059     if (! dmaen (DMA_COPPER) || cop_state.state == COP_stop || cop_state.state == COP_bltwait)
3060 	return;
3061 
3062     if (cop_state.state == COP_wait) {
3063 	int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80);
3064 
3065 	if (vp < cop_state.vcmp)
3066 	    return;
3067     }
3068     copper_enabled_thisline = 1;
3069 
3070     if (! eventtab[ev_copper].active)
3071 	set_special (SPCFLAG_COPPER);
3072 }
3073 
copper_handler(void)3074 static void copper_handler (void)
3075 {
3076     /* This will take effect immediately, within the same cycle.  */
3077     set_special (SPCFLAG_COPPER);
3078 
3079     if (! copper_enabled_thisline)
3080 	abort ();
3081 
3082     eventtab[ev_copper].active = 0;
3083 }
3084 
blitter_done_notify(void)3085 void blitter_done_notify (void)
3086 {
3087     if (cop_state.state != COP_bltwait)
3088 	return;
3089 
3090     cop_state.hpos = current_hpos () & ~1;
3091     cop_state.vpos = vpos;
3092     cop_state.state = COP_wait;
3093     compute_spcflag_copper ();
3094 }
3095 
do_copper(void)3096 void do_copper (void)
3097 {
3098     int hpos = current_hpos ();
3099     update_copper (hpos);
3100 }
3101 
3102 /* ADDR is the address that is going to be read/written; this access is
3103    the reason why we want to update the copper.  This function is also
3104    used from hsync_handler to finish up the line.  */
sync_copper_with_cpu(int hpos,int do_schedule)3105 STATIC_INLINE void sync_copper_with_cpu (int hpos, int do_schedule)
3106 {
3107     /* Need to let the copper advance to the current position.  */
3108     if (eventtab[ev_copper].active) {
3109 	eventtab[ev_copper].active = 0;
3110 	if (do_schedule)
3111 	    events_schedule ();
3112 	set_special (SPCFLAG_COPPER);
3113     }
3114     if (copper_enabled_thisline)
3115 	update_copper (hpos);
3116 }
3117 
sprite_fetch(struct sprite * s,int dma)3118 STATIC_INLINE uae_u16 sprite_fetch (struct sprite *s, int dma)
3119 {
3120     uae_u16 data = last_custom_value;
3121     if (dma)
3122 	data = last_custom_value = chipmem_agnus_wget (s->pt);
3123     s->pt += 2;
3124     return data;
3125 }
3126 
do_sprites_1(int num,int cycle,int hpos)3127 STATIC_INLINE void do_sprites_1 (int num, int cycle, int hpos)
3128 {
3129     struct sprite *s = &spr[num];
3130     int dma;
3131 
3132     if (cycle == 0) {
3133 	if (vpos == s->vstart)
3134 	    s->state = SPR_waiting_stop;
3135 	if (vpos == s->vstop)
3136 	    s->state = SPR_restart;
3137     }
3138     if (!dmaen (DMA_SPRITE))
3139 	return;
3140     dma = hpos < ddfstrt || diwstate != DIW_waiting_stop || !dmaen (DMA_BITPLANE);
3141     if (s->state == SPR_restart || vpos == sprite_vblank_endline) {
3142 	uae_u16 data = sprite_fetch (s, dma);
3143 	s->pt += (sprite_width >> 3) - 2;
3144 #ifdef SPRITE_DEBUG
3145 	write_log ("dma:");
3146 #endif
3147 	if (cycle == 0) {
3148 	    SPRxPOS_1 (dma ? data : sprpos[num], num, hpos);
3149 	} else {
3150 	    s->state = SPR_waiting_start;
3151 	    SPRxCTL_1 (dma ? data : sprctl[num], num, hpos);
3152 	}
3153     } else if (s->state == SPR_waiting_stop) {
3154 	uae_u16 data = sprite_fetch (s, dma);
3155 
3156 	if (cycle == 0)
3157 	    SPRxDATA_1 (dma ? data : sprdata[num][0], num);
3158 	else
3159 	    SPRxDATB_1 (dma ? data : sprdatb[num][0], num);
3160 	switch (sprite_width)
3161 	    {
3162 	    case 64:
3163 	    {
3164 		uae_u32 data32 = sprite_fetch (s, dma);
3165 		uae_u32 data641 = sprite_fetch (s, dma);
3166 		uae_u32 data642 = sprite_fetch (s, dma);
3167 		if (dma) {
3168 		    if (cycle == 0) {
3169 			sprdata[num][3] = data642;
3170 			sprdata[num][2] = data641;
3171 			sprdata[num][1] = data32;
3172 		    } else {
3173 			sprdatb[num][3] = data642;
3174 			sprdatb[num][2] = data641;
3175 			sprdatb[num][1] = data32;
3176 		    }
3177 		}
3178 	    }
3179 	    break;
3180 	    case 32:
3181 	    {
3182 		uae_u32 data32 = sprite_fetch (s, dma);
3183 		if (dma) {
3184 		    if (cycle == 0)
3185 			sprdata[num][1] = data32;
3186 		    else
3187 			sprdatb[num][1] = data32;
3188 		}
3189 	    }
3190 	    break;
3191 	}
3192     }
3193 }
3194 
do_sprites(int hpos)3195 static void do_sprites (int hpos)
3196 {
3197     int maxspr, minspr;
3198     int i;
3199 
3200     /* I don't know whether this is right. Some programs write the sprite pointers
3201      * directly at the start of the copper list. With the test against currvp, the
3202      * first two words of data are read on the second line in the frame. The problem
3203      * occurs when the program jumps to another copperlist a few lines further down
3204      * which _also_ writes the sprite pointer registers. This means that a) writing
3205      * to the sprite pointers sets the state to SPR_restart; or b) that sprite DMA
3206      * is disabled until the end of the vertical blanking interval. The HRM
3207      * isn't clear - it says that the vertical sprite position can be set to any
3208      * value, but this wouldn't be the first mistake... */
3209     /* Update: I modified one of the programs to write the sprite pointers the
3210      * second time only _after_ the VBlank interval, and it showed the same behaviour
3211      * as it did unmodified under UAE with the above check. This indicates that the
3212      * solution below is correct. */
3213     /* Another update: seems like we have to use the NTSC value here (see Sanity Turmoil
3214      * demo).  */
3215     /* Maximum for Sanity Turmoil: 27.
3216        Minimum for Sanity Arte: 22.  */
3217     if (vpos < sprite_vblank_endline)
3218 	return;
3219 
3220     maxspr = hpos;
3221     minspr = last_sprite_hpos;
3222 
3223     if (minspr >= SPR0_HPOS + MAX_SPRITES * 4 || maxspr < SPR0_HPOS)
3224 	return;
3225 
3226     if (maxspr > SPR0_HPOS + MAX_SPRITES * 4)
3227 	maxspr = SPR0_HPOS + MAX_SPRITES * 4;
3228     if (minspr < SPR0_HPOS)
3229 	minspr = SPR0_HPOS;
3230 
3231     for (i = minspr; i < maxspr; i++) {
3232 	int cycle = -1;
3233 	switch ((i - SPR0_HPOS) & 3)
3234 	{
3235 	case 0:
3236 	    cycle = 0;
3237 	    break;
3238 	case 2:
3239 	    cycle = 1;
3240 	    break;
3241 	}
3242 	if (cycle >= 0)
3243 	    do_sprites_1 ((i - SPR0_HPOS) / 4, cycle, i);
3244     }
3245     last_sprite_hpos = hpos;
3246 }
3247 
init_sprites(void)3248 static void init_sprites (void)
3249 {
3250     int i;
3251 
3252     for (i = 0; i < MAX_SPRITES; i++)
3253 	spr[i].state = SPR_restart;
3254     memset (sprpos, 0, sizeof sprpos);
3255     memset (sprctl, 0, sizeof sprctl);
3256 }
3257 
adjust_array_sizes(void)3258 static void adjust_array_sizes (void)
3259 {
3260 #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
3261     if (delta_sprite_entry) {
3262 	void *p1,*p2;
3263 	int mcc = max_sprite_entry + 50 + delta_sprite_entry;
3264 	delta_sprite_entry = 0;
3265 	p1 = realloc (sprite_entries[0], mcc * sizeof (struct sprite_entry));
3266 	p2 = realloc (sprite_entries[1], mcc * sizeof (struct sprite_entry));
3267 	if (p1) sprite_entries[0] = p1;
3268 	if (p2) sprite_entries[1] = p2;
3269 	if (p1 && p2) {
3270 	    write_log ("new max_sprite_entry=%d\n",mcc);
3271 	    max_sprite_entry = mcc;
3272 	}
3273     }
3274     if (delta_color_change) {
3275 	void *p1,*p2;
3276 	int mcc = max_color_change + 200 + delta_color_change;
3277 	delta_color_change = 0;
3278 	p1 = realloc (color_changes[0], mcc * sizeof (struct color_change));
3279 	p2 = realloc (color_changes[1], mcc * sizeof (struct color_change));
3280 	if (p1) color_changes[0] = p1;
3281 	if (p2) color_changes[1] = p2;
3282 	if (p1 && p2) {
3283 	    write_log ("new max_color_change=%d\n",mcc);
3284 	    max_color_change = mcc;
3285 	}
3286     }
3287 #endif
3288 }
3289 
init_hardware_frame(void)3290 static void init_hardware_frame (void)
3291 {
3292     next_lineno = 0;
3293     nextline_how = nln_normal;
3294     diwstate = DIW_waiting_start;
3295     hdiwstate = DIW_waiting_start;
3296     ddfstate = DIW_waiting_start;
3297 }
init_hardware_for_drawing_frame(void)3298 void init_hardware_for_drawing_frame (void)
3299 {
3300     adjust_array_sizes ();
3301 
3302     /* Avoid this code in the first frame after a customreset.  */
3303     if (prev_sprite_entries) {
3304 	int first_pixel = prev_sprite_entries[0].first_pixel;
3305 	int npixels = prev_sprite_entries[prev_next_sprite_entry].first_pixel - first_pixel;
3306 	memset (spixels + first_pixel, 0, npixels * sizeof *spixels);
3307 	memset (spixstate.bytes + first_pixel, 0, npixels * sizeof *spixstate.bytes);
3308     }
3309     prev_next_sprite_entry = next_sprite_entry;
3310 
3311     next_color_change = 0;
3312     next_sprite_entry = 0;
3313     next_color_entry = 0;
3314     remembered_color_entry = -1;
3315 
3316     prev_sprite_entries = sprite_entries[current_change_set];
3317     curr_sprite_entries = sprite_entries[current_change_set ^ 1];
3318     prev_color_changes = color_changes[current_change_set];
3319     curr_color_changes = color_changes[current_change_set ^ 1];
3320     prev_color_tables = color_tables[current_change_set];
3321     curr_color_tables = color_tables[current_change_set ^ 1];
3322 
3323     prev_drawinfo = line_drawinfo[current_change_set];
3324     curr_drawinfo = line_drawinfo[current_change_set ^ 1];
3325     current_change_set ^= 1;
3326 
3327     color_src_match = color_dest_match = -1;
3328 
3329     /* Use both halves of the array in alternating fashion.  */
3330     curr_sprite_entries[0].first_pixel = current_change_set * MAX_SPR_PIXELS;
3331     next_sprite_forced = 1;
3332 }
3333 
3334 static void do_savestate(void);
3335 
vsync_handler(void)3336 static void vsync_handler (void)
3337 {
3338     int i;
3339     for (i = 0; i < MAX_SPRITES; i++)
3340 	spr[i].state = SPR_waiting_start;
3341 
3342     n_frames++;
3343 
3344     time_vsync ();
3345 
3346     handle_events ();
3347 
3348     INTREQ (0x8020);
3349     if (bplcon0 & 4)
3350 	lof ^= 0x8000;
3351 
3352 #ifdef PICASSO96
3353     if (picasso_on)
3354 	picasso_handle_vsync ();
3355 #endif
3356     vsync_handle_redraw (lof, lof_changed);
3357 
3358     if (quit_program > 0)
3359 	return;
3360 
3361     {
3362 	static int cnt = 0;
3363 	if (cnt == 0) {
3364 	    /* resolution_check_change (); */
3365 	    DISK_check_change ();
3366 	    cnt = 5;
3367 	}
3368 	cnt--;
3369     }
3370 
3371     /* Start a new set of copper records.  */
3372     curr_cop_set ^= 1;
3373     nr_cop_records[curr_cop_set] = 0;
3374 
3375     /* For now, let's only allow this to change at vsync time.  It gets too
3376      * hairy otherwise.  */
3377     if (beamcon0 != new_beamcon0)
3378 	init_hz ();
3379 
3380     lof_changed = 0;
3381 
3382     cop_state.ip = cop1lc;
3383     cop_state.state = COP_read1;
3384     cop_state.vpos = 0;
3385     cop_state.hpos = 0;
3386     cop_state.ignore_next = 0;
3387 
3388     init_hardware_frame ();
3389 
3390 #ifdef HAVE_GETTIMEOFDAY
3391     {
3392 	struct timeval tv;
3393 	unsigned long int newtime;
3394 
3395 	gettimeofday (&tv,NULL);
3396 	newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000;
3397 
3398 	if (!bogusframe) {
3399 	    lastframetime = newtime - msecs;
3400 
3401 	    frametime += lastframetime;
3402 	    timeframes++;
3403 
3404 	    if ((timeframes & 127) == 0)
3405 		gui_fps (1000 * timeframes / frametime);
3406 	}
3407 	msecs = newtime;
3408 	bogusframe = 0;
3409     }
3410 #endif
3411     if (timehack_alive > 0)
3412 	timehack_alive--;
3413     inputdevice_vsync ();
3414     CIA_vsync_handler ();
3415 }
3416 
hsync_handler(void)3417 static void hsync_handler (void)
3418 {
3419     sync_copper_with_cpu (maxhpos, 0);
3420 
3421     finish_decisions ();
3422     if (thisline_decision.plfleft != -1) {
3423 	if (currprefs.collision_level > 1)
3424 	    do_sprite_collisions ();
3425 	if (currprefs.collision_level > 2)
3426 	    do_playfield_collisions ();
3427     }
3428     hsync_record_line_state (next_lineno, nextline_how, thisline_changed);
3429 
3430     eventtab[ev_hsync].evtime += get_cycles () - eventtab[ev_hsync].oldcycles;
3431     eventtab[ev_hsync].oldcycles = get_cycles ();
3432     CIA_hsync_handler ();
3433 
3434     if (currprefs.produce_sound > 0)
3435 	audio_hsync (1);
3436 
3437     hardware_line_completed (next_lineno);
3438 
3439     /* In theory only an equality test is needed here - but if a program
3440        goes haywire with the VPOSW register, it can cause us to miss this,
3441        with vpos going into the thousands (and all the nasty consequences
3442        this has).  */
3443 
3444     if (++vpos >= (maxvpos + (lof == 0 ? 0 : 1))) {
3445 	vpos = 0;
3446 	vsync_handler ();
3447     }
3448 
3449     DISK_update ();
3450 
3451     is_lastline = (!sync_with_sound
3452 		   && vpos + 1 == maxvpos + (lof == 0 ? 0 : 1)
3453 		   && currprefs.m68k_speed == -1
3454 		   && vsyncmintime_valid);
3455 
3456     if ((bplcon0 & 4) && curr_gfx && curr_gfx->linedbl)
3457 	notice_interlace_seen ();
3458 
3459     if (!nodraw ()) {
3460 	int lineno = vpos;
3461 	nextline_how = nln_normal;
3462 	if (curr_gfx->linedbl) {
3463 	    lineno *= 2;
3464 	    nextline_how = curr_gfx->linedbl == 1 ? nln_doubled : nln_nblack;
3465 	    if (bplcon0 & 4) {
3466 		if (!lof) {
3467 		    lineno++;
3468 		    nextline_how = nln_lower;
3469 		} else {
3470 		    nextline_how = nln_upper;
3471 		}
3472 	    }
3473 	}
3474 	next_lineno = lineno;
3475 	reset_decisions ();
3476     }
3477     if (uae_int_requested) {
3478 	set_uae_int_flag ();
3479 	INTREQ (0xA000);
3480     }
3481     /* See if there's a chance of a copper wait ending this line.  */
3482     cop_state.hpos = 0;
3483     compute_spcflag_copper ();
3484     inputdevice_hsync ();
3485     gayle_hsync ();
3486 }
3487 
init_eventtab(void)3488 void init_eventtab (void)
3489 {
3490     int i;
3491 
3492     currcycle = 0;
3493     for (i = 0; i < ev_max; i++) {
3494 	eventtab[i].active = 0;
3495 	eventtab[i].oldcycles = 0;
3496     }
3497 
3498     eventtab[ev_cia].handler = CIA_handler;
3499     eventtab[ev_hsync].handler = hsync_handler;
3500     eventtab[ev_hsync].evtime = HSYNCTIME + get_cycles ();
3501     eventtab[ev_hsync].active = 1;
3502 
3503     eventtab[ev_copper].handler = copper_handler;
3504     eventtab[ev_copper].active = 0;
3505     eventtab[ev_blitter].handler = blitter_handler;
3506     eventtab[ev_blitter].active = 0;
3507     eventtab[ev_disk].handler = DISK_handler;
3508     eventtab[ev_disk].active = 0;
3509     eventtab[ev_audio].handler = audio_evhandler;
3510     eventtab[ev_audio].active = 0;
3511     events_schedule ();
3512 }
3513 
customreset(void)3514 void customreset (void)
3515 {
3516     int i;
3517     int zero = 0;
3518 #ifdef HAVE_GETTIMEOFDAY
3519     struct timeval tv;
3520 #endif
3521 
3522     /* If we're in a loop of quick successive resets, we should give
3523        the GUI some time to respond to a "Quit" event.  */
3524     handle_events ();
3525 
3526     if (! savestate_state) {
3527 	if ((currprefs.chipset_mask & CSMASK_AGA) == 0) {
3528 	    for (i = 0; i < 32; i++) {
3529 		current_colors.color_regs_ecs[i] = 0;
3530 		current_colors.acolors[i] = xcolors[0];
3531 	    }
3532 	} else {
3533 	    for (i = 0; i < 256; i++) {
3534 		current_colors.color_regs_aga[i] = 0;
3535 		current_colors.acolors[i] = CONVERT_RGB (zero);
3536 	    }
3537 	}
3538 
3539 	clx_sprmask = 0xFF;
3540 	clxdat = 0;
3541 
3542 	/* Clear the armed flags of all sprites.  */
3543 	memset (spr, 0, sizeof spr);
3544 	nr_armed = 0;
3545 
3546 	dmacon = intena = 0;
3547 
3548 	copcon = 0;
3549 	DSKLEN (0, 0);
3550 
3551 	bplcon0 = 0;
3552 	bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */
3553 	bplcon3 = 0xC00;
3554 
3555 	FMODE (0);
3556 	CLXCON (0);
3557 	lof = 0;
3558     }
3559 
3560     n_frames = 0;
3561 
3562     gayle_reset (1);
3563     expamem_reset ();
3564     a1000_reset ();
3565     DISK_reset ();
3566     CIA_reset ();
3567     unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE));
3568 
3569     vpos = 0;
3570 
3571     inputdevice_reset ();
3572     timehack_alive = 0;
3573 
3574     curr_sprite_entries = 0;
3575     prev_sprite_entries = 0;
3576     sprite_entries[0][0].first_pixel = 0;
3577     sprite_entries[1][0].first_pixel = MAX_SPR_PIXELS;
3578     sprite_entries[0][1].first_pixel = 0;
3579     sprite_entries[1][1].first_pixel = MAX_SPR_PIXELS;
3580     memset (spixels, 0, sizeof spixels);
3581     memset (&spixstate, 0, sizeof spixstate);
3582 
3583     bltstate = BLT_done;
3584     cop_state.state = COP_stop;
3585     diwstate = DIW_waiting_start;
3586     hdiwstate = DIW_waiting_start;
3587     currcycle = 0;
3588 
3589     currprefs.ntscmode = changed_prefs.ntscmode;
3590     new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20;
3591     init_hz ();
3592 
3593     audio_reset ();
3594     if (savestate_state != STATE_RESTORE) {
3595 	/* must be called after audio_reset */
3596 	adkcon = 0;
3597 	update_adkmasks ();
3598     }
3599 
3600     init_sprites ();
3601 
3602     init_hardware_frame ();
3603     init_drawing_at_reset ();
3604 
3605     reset_decisions ();
3606 
3607 #ifdef HAVE_GETTIMEOFDAY
3608     gettimeofday (&tv, NULL);
3609     seconds_base = tv.tv_sec;
3610     bogusframe = 1;
3611 #endif
3612 
3613     sprite_buffer_res = currprefs.chipset_mask & CSMASK_AGA ? RES_HIRES : RES_LORES;
3614     if (savestate_state == STATE_RESTORE) {
3615 	uae_u16 v;
3616 	uae_u32 vv;
3617 
3618 	update_adkmasks ();
3619 	INTENA (0);
3620 	INTREQ (0);
3621 #if 0
3622 	DMACON (0, 0);
3623 #endif
3624 	if (diwhigh)
3625 	    diwhigh_written = 1;
3626 	COPJMP (1);
3627 	v = bplcon0;
3628 	BPLCON0 (0, 0);
3629 	BPLCON0 (0, v);
3630 	FMODE (fmode);
3631 	if (!(currprefs.chipset_mask & CSMASK_AGA)) {
3632 	    for(i = 0 ; i < 32 ; i++)  {
3633 		vv = current_colors.color_regs_ecs[i];
3634 		current_colors.color_regs_ecs[i] = -1;
3635 		record_color_change (0, i, vv);
3636 		remembered_color_entry = -1;
3637 		current_colors.color_regs_ecs[i] = vv;
3638 		current_colors.acolors[i] = xcolors[vv];
3639 	    }
3640 	} else {
3641 	    for(i = 0 ; i < 256 ; i++)  {
3642 		vv = current_colors.color_regs_aga[i];
3643 		current_colors.color_regs_aga[i] = -1;
3644 		record_color_change (0, i, vv);
3645 		remembered_color_entry = -1;
3646 		current_colors.color_regs_aga[i] = vv;
3647 		current_colors.acolors[i] = CONVERT_RGB(vv);
3648 	    }
3649 	}
3650 	CLXCON (clxcon);
3651 	CLXCON2 (clxcon2);
3652 	calcdiw ();
3653 	write_log ("State restored\n");
3654 	dumpcustom ();
3655 	for (i = 0; i < 8; i++)
3656 	    nr_armed += spr[i].armed != 0;
3657 	if (! currprefs.produce_sound) {
3658 	    eventtab[ev_audio].active = 0;
3659 	    events_schedule ();
3660 	}
3661     }
3662     expand_sprres ();
3663 }
3664 
dumpcustom(void)3665 void dumpcustom (void)
3666 {
3667     console_out ("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(),
3668 		 (unsigned int)intena, (unsigned int)intreq, (unsigned int)vpos, (unsigned int)current_hpos());
3669     console_out ("COP1LC: %08lx, COP2LC: %08lx COPPTR: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc, cop_state.ip);
3670     console_out ("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n",
3671 		 (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop);
3672     console_out ("BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x\n", bplcon0, bplcon1, bplcon2, bplcon3, bplcon4);
3673     if (timeframes) {
3674 	console_out ("Average frame time: %f ms [frames: %d time: %d]\n",
3675 		     (double)frametime / timeframes, timeframes, frametime);
3676 	if (total_skipped)
3677 	    console_out ("Skipped frames: %d\n", total_skipped);
3678     }
3679     /*for (i=0; i<256; i++) if (blitcount[i]) console_out ("minterm %x = %d\n",i,blitcount[i]);  blitter debug */
3680 }
3681 
gen_custom_tables(void)3682 static void gen_custom_tables (void)
3683 {
3684     int i;
3685     for (i = 0; i < 256; i++) {
3686 	sprtaba[i] = ((((i >> 7) & 1) << 0)
3687 		      | (((i >> 6) & 1) << 2)
3688 		      | (((i >> 5) & 1) << 4)
3689 		      | (((i >> 4) & 1) << 6)
3690 		      | (((i >> 3) & 1) << 8)
3691 		      | (((i >> 2) & 1) << 10)
3692 		      | (((i >> 1) & 1) << 12)
3693 		      | (((i >> 0) & 1) << 14));
3694 	sprtabb[i] = sprtaba[i] * 2;
3695 	sprite_ab_merge[i] = (((i & 15) ? 1 : 0)
3696 			      | ((i & 240) ? 2 : 0));
3697     }
3698     for (i = 0; i < 16; i++) {
3699 	clxmask[i] = (((i & 1) ? 0xF : 0x3)
3700 		      | ((i & 2) ? 0xF0 : 0x30)
3701 		      | ((i & 4) ? 0xF00 : 0x300)
3702 		      | ((i & 8) ? 0xF000 : 0x3000));
3703 	sprclx[i] = (((i & 0x3) == 0x3 ? 1 : 0)
3704 		     | ((i & 0x5) == 0x5 ? 2 : 0)
3705 		     | ((i & 0x9) == 0x9 ? 4 : 0)
3706 		     | ((i & 0x6) == 0x6 ? 8 : 0)
3707 		     | ((i & 0xA) == 0xA ? 16 : 0)
3708 		     | ((i & 0xC) == 0xC ? 32 : 0)) << 9;
3709     }
3710 }
3711 
custom_init(void)3712 void custom_init (void)
3713 {
3714     uaecptr pos;
3715 
3716 #ifdef OS_WITHOUT_MEMORY_MANAGEMENT
3717     int num;
3718 
3719     for (num = 0; num < 2; num++) {
3720        sprite_entries[num] = xmalloc (max_sprite_entry * sizeof (struct sprite_entry));
3721        color_changes[num] = xmalloc (max_color_change * sizeof (struct color_change));
3722     }
3723 #endif
3724 
3725     pos = here ();
3726 
3727     org (RTAREA_BASE+0xFF70);
3728     calltrap (deftrap (mousehack_helper));
3729     dw (RTS);
3730 
3731     org (RTAREA_BASE+0xFFA0);
3732     calltrap (deftrap (timehack_helper));
3733     dw (RTS);
3734 
3735     org (pos);
3736 
3737     gen_custom_tables ();
3738     build_blitfilltable ();
3739 
3740     drawing_init ();
3741 
3742     create_cycle_diagram_table ();
3743 }
3744 
3745 /* Custom chip memory bank */
3746 
3747 static uae_u32 custom_lget (uaecptr) REGPARAM;
3748 static uae_u32 custom_wget (uaecptr) REGPARAM;
3749 static uae_u32 custom_bget (uaecptr) REGPARAM;
3750 static void custom_lput (uaecptr, uae_u32) REGPARAM;
3751 static void custom_wput (uaecptr, uae_u32) REGPARAM;
3752 static void custom_bput (uaecptr, uae_u32) REGPARAM;
3753 
3754 addrbank custom_bank = {
3755     custom_lget, custom_wget, custom_bget,
3756     custom_lput, custom_wput, custom_bput,
3757     default_xlate, default_check, NULL, "Custom chipset"
3758 };
3759 
custom_wget_1(uaecptr addr)3760 STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (uaecptr addr)
3761 {
3762     uae_u16 v;
3763     switch (addr & 0x1FE) {
3764      case 0x002: v = DMACONR (); break;
3765      case 0x004: v = VPOSR (); break;
3766      case 0x006: v = VHPOSR (); break;
3767 
3768      case 0x008: v = DSKDATR (current_hpos ()); break;
3769 
3770      case 0x00A: v = JOY0DAT (); break;
3771      case 0x00C: v = JOY1DAT (); break;
3772      case 0x00E: v = CLXDAT (); break;
3773      case 0x010: v = ADKCONR (); break;
3774 
3775      case 0x012: v = POT0DAT (); break;
3776      case 0x014: v = POT1DAT (); break;
3777      case 0x016: v = POTGOR (); break;
3778      case 0x018: v = SERDATR (); break;
3779      case 0x01A: v = DSKBYTR (current_hpos ()); break;
3780      case 0x01C: v = INTENAR (); break;
3781      case 0x01E: v = INTREQR (); break;
3782      case 0x07C: v = DENISEID (); break;
3783 
3784      case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
3785      case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
3786      case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
3787      case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
3788      case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
3789      case 0x1BC: case 0x1BE:
3790 	v = COLOR_READ ((addr & 0x3E) / 2);
3791 	break;
3792 
3793      default:
3794        v = last_custom_value;
3795        custom_wput (addr, v);
3796        last_custom_value = 0xffff;
3797        return v;
3798     }
3799     last_custom_value = v;
3800     return v;
3801 }
3802 
custom_wget(uaecptr addr)3803 uae_u32 REGPARAM2 custom_wget (uaecptr addr)
3804 {
3805     sync_copper_with_cpu (current_hpos (), 1);
3806     return custom_wget_1 (addr);
3807 }
3808 
custom_bget(uaecptr addr)3809 uae_u32 REGPARAM2 custom_bget (uaecptr addr)
3810 {
3811     return custom_wget (addr & 0xfffe) >> (addr & 1 ? 0 : 8);
3812 }
3813 
custom_lget(uaecptr addr)3814 uae_u32 REGPARAM2 custom_lget (uaecptr addr)
3815 {
3816     return ((uae_u32)custom_wget (addr & 0xfffe) << 16) | custom_wget ((addr + 2) & 0xfffe);
3817 }
3818 
custom_wput_1(int hpos,uaecptr addr,uae_u32 value)3819 void REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value)
3820 {
3821     addr &= 0x1FE;
3822     last_custom_value = value;
3823     switch (addr) {
3824     case 0x020: DSKPTH (value); break;
3825     case 0x022: DSKPTL (value); break;
3826     case 0x024: DSKLEN (value, hpos); break;
3827     case 0x026: DSKDAT (value); break;
3828 
3829     case 0x02A: VPOSW (value); break;
3830     case 0x02E: COPCON (value); break;
3831     case 0x030: SERDAT (value); break;
3832     case 0x032: SERPER (value); break;
3833     case 0x034: POTGO (value); break;
3834     case 0x040: BLTCON0 (value); break;
3835     case 0x042: BLTCON1 (value); break;
3836 
3837     case 0x044: BLTAFWM (value); break;
3838     case 0x046: BLTALWM (value); break;
3839 
3840     case 0x050: BLTAPTH (value); break;
3841     case 0x052: BLTAPTL (value); break;
3842     case 0x04C: BLTBPTH (value); break;
3843     case 0x04E: BLTBPTL (value); break;
3844     case 0x048: BLTCPTH (value); break;
3845     case 0x04A: BLTCPTL (value); break;
3846     case 0x054: BLTDPTH (value); break;
3847     case 0x056: BLTDPTL (value); break;
3848 
3849     case 0x058: BLTSIZE (value); break;
3850 
3851     case 0x064: BLTAMOD (value); break;
3852     case 0x062: BLTBMOD (value); break;
3853     case 0x060: BLTCMOD (value); break;
3854     case 0x066: BLTDMOD (value); break;
3855 
3856     case 0x070: BLTCDAT (value); break;
3857     case 0x072: BLTBDAT (value); break;
3858     case 0x074: BLTADAT (value); break;
3859 
3860     case 0x07E: DSKSYNC (value); break;
3861 
3862     case 0x080: COP1LCH (value); break;
3863     case 0x082: COP1LCL (value); break;
3864     case 0x084: COP2LCH (value); break;
3865     case 0x086: COP2LCL (value); break;
3866 
3867     case 0x088: COPJMP (1); break;
3868     case 0x08A: COPJMP (2); break;
3869 
3870     case 0x08E: DIWSTRT (hpos, value); break;
3871     case 0x090: DIWSTOP (hpos, value); break;
3872     case 0x092: DDFSTRT (hpos, value); break;
3873     case 0x094: DDFSTOP (hpos, value); break;
3874 
3875     case 0x096: DMACON (hpos, value); break;
3876     case 0x098: CLXCON (value); break;
3877     case 0x09A: INTENA (value); break;
3878     case 0x09C: INTREQ (value); break;
3879     case 0x09E: ADKCON (value); break;
3880 
3881     case 0x0A0: AUDxLCH (0, value); break;
3882     case 0x0A2: AUDxLCL (0, value); break;
3883     case 0x0A4: AUDxLEN (0, value); break;
3884     case 0x0A6: AUDxPER (0, value); break;
3885     case 0x0A8: AUDxVOL (0, value); break;
3886     case 0x0AA: AUDxDAT (0, value); break;
3887 
3888     case 0x0B0: AUDxLCH (1, value); break;
3889     case 0x0B2: AUDxLCL (1, value); break;
3890     case 0x0B4: AUDxLEN (1, value); break;
3891     case 0x0B6: AUDxPER (1, value); break;
3892     case 0x0B8: AUDxVOL (1, value); break;
3893     case 0x0BA: AUDxDAT (1, value); break;
3894 
3895     case 0x0C0: AUDxLCH (2, value); break;
3896     case 0x0C2: AUDxLCL (2, value); break;
3897     case 0x0C4: AUDxLEN (2, value); break;
3898     case 0x0C6: AUDxPER (2, value); break;
3899     case 0x0C8: AUDxVOL (2, value); break;
3900     case 0x0CA: AUDxDAT (2, value); break;
3901 
3902     case 0x0D0: AUDxLCH (3, value); break;
3903     case 0x0D2: AUDxLCL (3, value); break;
3904     case 0x0D4: AUDxLEN (3, value); break;
3905     case 0x0D6: AUDxPER (3, value); break;
3906     case 0x0D8: AUDxVOL (3, value); break;
3907     case 0x0DA: AUDxDAT (3, value); break;
3908 
3909     case 0x0E0: BPLxPTH (hpos, value, 0); break;
3910     case 0x0E2: BPLxPTL (hpos, value, 0); break;
3911     case 0x0E4: BPLxPTH (hpos, value, 1); break;
3912     case 0x0E6: BPLxPTL (hpos, value, 1); break;
3913     case 0x0E8: BPLxPTH (hpos, value, 2); break;
3914     case 0x0EA: BPLxPTL (hpos, value, 2); break;
3915     case 0x0EC: BPLxPTH (hpos, value, 3); break;
3916     case 0x0EE: BPLxPTL (hpos, value, 3); break;
3917     case 0x0F0: BPLxPTH (hpos, value, 4); break;
3918     case 0x0F2: BPLxPTL (hpos, value, 4); break;
3919     case 0x0F4: BPLxPTH (hpos, value, 5); break;
3920     case 0x0F6: BPLxPTL (hpos, value, 5); break;
3921     case 0x0F8: BPLxPTH (hpos, value, 6); break;
3922     case 0x0FA: BPLxPTL (hpos, value, 6); break;
3923     case 0x0FC: BPLxPTH (hpos, value, 7); break;
3924     case 0x0FE: BPLxPTL (hpos, value, 7); break;
3925 
3926     case 0x100: BPLCON0 (hpos, value); break;
3927     case 0x102: BPLCON1 (hpos, value); break;
3928     case 0x104: BPLCON2 (hpos, value); break;
3929     case 0x106: BPLCON3 (hpos, value); break;
3930 
3931     case 0x108: BPL1MOD (hpos, value); break;
3932     case 0x10A: BPL2MOD (hpos, value); break;
3933     case 0x10E: CLXCON2 (value); break;
3934 
3935     case 0x110: BPL1DAT (hpos, value); break;
3936     case 0x112: BPL2DAT (value); break;
3937     case 0x114: BPL3DAT (value); break;
3938     case 0x116: BPL4DAT (value); break;
3939     case 0x118: BPL5DAT (value); break;
3940     case 0x11A: BPL6DAT (value); break;
3941     case 0x11C: BPL7DAT (value); break;
3942     case 0x11E: BPL8DAT (value); break;
3943 
3944     case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A:
3945     case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196:
3946     case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2:
3947     case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE:
3948     case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA:
3949     case 0x1BC: case 0x1BE:
3950 	COLOR_WRITE (hpos, value & 0xFFF, (addr & 0x3E) / 2);
3951 	break;
3952     case 0x120: case 0x124: case 0x128: case 0x12C:
3953     case 0x130: case 0x134: case 0x138: case 0x13C:
3954 	SPRxPTH (hpos, value, (addr - 0x120) / 4);
3955 	break;
3956     case 0x122: case 0x126: case 0x12A: case 0x12E:
3957     case 0x132: case 0x136: case 0x13A: case 0x13E:
3958 	SPRxPTL (hpos, value, (addr - 0x122) / 4);
3959 	break;
3960     case 0x140: case 0x148: case 0x150: case 0x158:
3961     case 0x160: case 0x168: case 0x170: case 0x178:
3962 	SPRxPOS (hpos, value, (addr - 0x140) / 8);
3963 	break;
3964     case 0x142: case 0x14A: case 0x152: case 0x15A:
3965     case 0x162: case 0x16A: case 0x172: case 0x17A:
3966 	SPRxCTL (hpos, value, (addr - 0x142) / 8);
3967 	break;
3968     case 0x144: case 0x14C: case 0x154: case 0x15C:
3969     case 0x164: case 0x16C: case 0x174: case 0x17C:
3970 	SPRxDATA (hpos, value, (addr - 0x144) / 8);
3971 	break;
3972     case 0x146: case 0x14E: case 0x156: case 0x15E:
3973     case 0x166: case 0x16E: case 0x176: case 0x17E:
3974 	SPRxDATB (hpos, value, (addr - 0x146) / 8);
3975 	break;
3976 
3977     case 0x36: JOYTEST (value); break;
3978     case 0x5A: BLTCON0L (value); break;
3979     case 0x5C: BLTSIZV (value); break;
3980     case 0x5E: BLTSIZH (value); break;
3981     case 0x1E4: DIWHIGH (hpos, value); break;
3982     case 0x10C: BPLCON4 (hpos, value); break;
3983 
3984     case 0x1DC: BEAMCON0 (value); break;
3985     case 0x1C0: if (htotal != value) { htotal = value; varsync (); } break;
3986     case 0x1C2: if (hsstop != value) { hsstop = value; varsync (); } break;
3987     case 0x1C4: if (hbstrt != value) { hbstrt = value; varsync (); } break;
3988     case 0x1C6: if (hbstop != value) { hbstop = value; varsync (); } break;
3989     case 0x1C8: if (vtotal != value) { vtotal = value; varsync (); } break;
3990     case 0x1CA: if (vsstop != value) { vsstop = value; varsync (); } break;
3991     case 0x1CC: if (vbstrt < value || vbstrt > value + 1) { vbstrt = value; varsync (); } break;
3992     case 0x1CE: if (vbstop < value || vbstop > value + 1) { vbstop = value; varsync (); } break;
3993     case 0x1DE: if (hsstrt != value) { hsstrt = value; varsync (); } break;
3994     case 0x1E0: if (vsstrt != value) { vsstrt = value; varsync (); } break;
3995     case 0x1E2: if (hcenter != value) { hcenter = value; varsync (); } break;
3996 
3997     case 0x1FC: FMODE (value); break;
3998     }
3999 }
4000 
custom_wput(uaecptr addr,uae_u32 value)4001 void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value)
4002 {
4003     int hpos = current_hpos ();
4004 
4005     sync_copper_with_cpu (hpos, 1);
4006     custom_wput_1 (hpos, addr, value);
4007 }
4008 
custom_bput(uaecptr addr,uae_u32 value)4009 void REGPARAM2 custom_bput (uaecptr addr, uae_u32 value)
4010 {
4011     static int warned = 0;
4012     /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */
4013     uae_u16 rval = (value << 8) | (value & 0xFF);
4014     custom_wput (addr, rval);
4015     if (!warned)
4016 	write_log ("Byte put to custom register.\n"), warned++;
4017 }
4018 
custom_lput(uaecptr addr,uae_u32 value)4019 void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value)
4020 {
4021     custom_wput (addr & 0xfffe, value >> 16);
4022     custom_wput ((addr + 2) & 0xfffe, (uae_u16)value);
4023 }
4024 
custom_prepare_savestate(void)4025 void custom_prepare_savestate (void)
4026 {
4027     /* force blitter to finish, no support for saving full blitter state yet */
4028     if (eventtab[ev_blitter].active) {
4029 	unsigned int olddmacon = dmacon;
4030 	dmacon |= DMA_BLITTER; /* ugh.. */
4031 	blitter_handler ();
4032 	dmacon = olddmacon;
4033     }
4034 }
4035 
4036 #define RB restore_u8 ()
4037 #define RW restore_u16 ()
4038 #define RL restore_u32 ()
4039 
restore_custom(const uae_u8 * src)4040 const uae_u8 *restore_custom (const uae_u8 *src)
4041 {
4042     uae_u16 dsklen, dskbytr, dskdatr;
4043     int dskpt;
4044     int i;
4045 
4046     audio_reset ();
4047 
4048     changed_prefs.chipset_mask = currprefs.chipset_mask = RL;
4049     RW;				/* 000 ? */
4050     RW;				/* 002 DMACONR */
4051     RW;				/* 004 VPOSR */
4052     RW;				/* 006 VHPOSR */
4053     dskdatr = RW;		/* 008 DSKDATR */
4054     RW;				/* 00A JOY0DAT */
4055     RW;				/* 00C JOY1DAT */
4056     clxdat = RW;		/* 00E CLXDAT */
4057     RW;				/* 010 ADKCONR */
4058     RW;				/* 012 POT0DAT* */
4059     RW;				/* 014 POT1DAT* */
4060     RW;				/* 016 POTINP* */
4061     RW;				/* 018 SERDATR* */
4062     dskbytr = RW;		/* 01A DSKBYTR */
4063     RW;				/* 01C INTENAR */
4064     RW;				/* 01E INTREQR */
4065     dskpt = RL;			/* 020-022 DSKPT */
4066     dsklen = RW;		/* 024 DSKLEN */
4067     RW;				/* 026 DSKDAT */
4068     RW;				/* 028 REFPTR */
4069     lof = RW;			/* 02A VPOSW */
4070     RW;				/* 02C VHPOSW */
4071     COPCON(RW);			/* 02E COPCON */
4072     RW;				/* 030 SERDAT* */
4073     RW;				/* 032 SERPER* */
4074     POTGO(RW);			/* 034 POTGO */
4075     RW;				/* 036 JOYTEST* */
4076     RW;				/* 038 STREQU */
4077     RW;				/* 03A STRVHBL */
4078     RW;				/* 03C STRHOR */
4079     RW;				/* 03E STRLONG */
4080     BLTCON0(RW);		/* 040 BLTCON0 */
4081     BLTCON1(RW);		/* 042 BLTCON1 */
4082     BLTAFWM(RW);		/* 044 BLTAFWM */
4083     BLTALWM(RW);		/* 046 BLTALWM */
4084     BLTCPTH(RL);		/* 048-04B BLTCPT */
4085     BLTBPTH(RL);		/* 04C-04F BLTBPT */
4086     BLTAPTH(RL);		/* 050-053 BLTAPT */
4087     BLTDPTH(RL);		/* 054-057 BLTDPT */
4088     RW;				/* 058 BLTSIZE */
4089     RW;				/* 05A BLTCON0L */
4090     oldvblts = RW;		/* 05C BLTSIZV */
4091     RW;				/* 05E BLTSIZH */
4092     BLTCMOD(RW);		/* 060 BLTCMOD */
4093     BLTBMOD(RW);		/* 062 BLTBMOD */
4094     BLTAMOD(RW);		/* 064 BLTAMOD */
4095     BLTDMOD(RW);		/* 066 BLTDMOD */
4096     RW;				/* 068 ? */
4097     RW;				/* 06A ? */
4098     RW;				/* 06C ? */
4099     RW;				/* 06E ? */
4100     BLTCDAT(RW);		/* 070 BLTCDAT */
4101     BLTBDAT(RW);		/* 072 BLTBDAT */
4102     BLTADAT(RW);		/* 074 BLTADAT */
4103     RW;				/* 076 ? */
4104     RW;				/* 078 ? */
4105     RW;				/* 07A ? */
4106     RW;				/* 07C LISAID */
4107     DSKSYNC(RW);		/* 07E DSKSYNC */
4108     cop1lc = RL;		/* 080/082 COP1LC */
4109     cop2lc = RL;		/* 084/086 COP2LC */
4110     RW;				/* 088 ? */
4111     RW;				/* 08A ? */
4112     RW;				/* 08C ? */
4113     diwstrt = RW;		/* 08E DIWSTRT */
4114     diwstop = RW;		/* 090 DIWSTOP */
4115     ddfstrt = RW;		/* 092 DDFSTRT */
4116     ddfstop = RW;		/* 094 DDFSTOP */
4117     dmacon = RW & ~(0x2000|0x4000); /* 096 DMACON */
4118     CLXCON(RW);			/* 098 CLXCON */
4119     intena = RW;		/* 09A INTENA */
4120     intreq = RW;		/* 09C INTREQ */
4121     adkcon = RW;		/* 09E ADKCON */
4122     for (i = 0; i < 8; i++)
4123 	bplpt[i] = RL;
4124     bplcon0 = RW;		/* 100 BPLCON0 */
4125     bplcon1 = RW;		/* 102 BPLCON1 */
4126     bplcon2 = RW;		/* 104 BPLCON2 */
4127     bplcon3 = RW;		/* 106 BPLCON3 */
4128     bpl1mod = RW;		/* 108 BPL1MOD */
4129     bpl2mod = RW;		/* 10A BPL2MOD */
4130     bplcon4 = RW;		/* 10C BPLCON4 */
4131     clxcon2 = RW;		/* 10E CLXCON2* */
4132     for(i = 0; i < 8; i++)
4133 	RW;			/*     BPLXDAT */
4134     for(i = 0; i < 32; i++)
4135 	current_colors.color_regs_ecs[i] = RW; /* 180 COLORxx */
4136     htotal = RW;		/* 1C0 HTOTAL */
4137     hsstop = RW;		/* 1C2 HSTOP ? */
4138     hbstrt = RW;		/* 1C4 HBSTRT ? */
4139     hbstop = RW;		/* 1C6 HBSTOP ? */
4140     vtotal = RW;		/* 1C8 VTOTAL */
4141     vsstop = RW;		/* 1CA VSSTOP */
4142     vbstrt = RW;		/* 1CC VBSTRT */
4143     vbstop = RW;		/* 1CE VBSTOP */
4144     RW;				/* 1D0 ? */
4145     RW;				/* 1D2 ? */
4146     RW;				/* 1D4 ? */
4147     RW;				/* 1D6 ? */
4148     RW;				/* 1D8 ? */
4149     RW;				/* 1DA ? */
4150     new_beamcon0 = RW;		/* 1DC BEAMCON0 */
4151     hsstrt = RW;		/* 1DE HSSTRT */
4152     vsstrt = RW;		/* 1E0 VSSTT  */
4153     hcenter = RW;		/* 1E2 HCENTER */
4154     diwhigh = RW;		/* 1E4 DIWHIGH */
4155     diwhigh_written = (diwhigh & 0x8000) ? 1 : 0;
4156     diwhigh &= 0x7fff;
4157     RW;				/* 1E6 ? */
4158     RW;				/* 1E8 ? */
4159     RW;				/* 1EA ? */
4160     RW;				/* 1EC ? */
4161     RW;				/* 1EE ? */
4162     RW;				/* 1F0 ? */
4163     RW;				/* 1F2 ? */
4164     RW;				/* 1F4 ? */
4165     RW;				/* 1F6 ? */
4166     RW;				/* 1F8 ? */
4167     RW;				/* 1FA ? */
4168     fmode = RW;			/* 1FC FMODE */
4169     last_custom_value = RW;	/* 1FE ? */
4170 
4171     DISK_restore_custom (dskpt, dsklen, dskdatr, dskbytr);
4172 
4173     return src;
4174 }
4175 
4176 
4177 #define SB save_u8
4178 #define SW save_u16
4179 #define SL save_u32
4180 
4181 extern uae_u16 serper;
4182 
save_custom(int * len,uae_u8 * dstptr,int full)4183 uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full)
4184 {
4185     uae_u8 *dstbak, *dst;
4186     int i;
4187     uae_u32 dskpt;
4188     uae_u16 dsklen, dsksync, dskdatr, dskbytr;
4189 
4190     DISK_save_custom (&dskpt, &dsklen, &dsksync, &dskdatr, &dskbytr);
4191 
4192     if (dstptr)
4193 	dstbak = dst = dstptr;
4194     else
4195 	dstbak = dst = malloc (8 + 256 * 2);
4196 
4197     SL (currprefs.chipset_mask);
4198     SW (0);			/* 000 ? */
4199     SW (dmacon);		/* 002 DMACONR */
4200     SW (VPOSR());		/* 004 VPOSR */
4201     SW (VHPOSR());		/* 006 VHPOSR */
4202     SW (dskdatr);		/* 008 DSKDATR */
4203     SW (JOY0DAT());		/* 00A JOY0DAT */
4204     SW (JOY1DAT());		/* 00C JOY1DAT */
4205     SW (clxdat);		/* 00E CLXDAT */
4206     SW (ADKCONR());		/* 010 ADKCONR */
4207     SW (POT0DAT());		/* 012 POT0DAT */
4208     SW (POT0DAT());		/* 014 POT1DAT */
4209     SW (0)	;		/* 016 POTINP * */
4210     SW (0);			/* 018 SERDATR * */
4211     SW (dskbytr);		/* 01A DSKBYTR */
4212     SW (INTENAR());		/* 01C INTENAR */
4213     SW (INTREQR());		/* 01E INTREQR */
4214     SL (dskpt);			/* 020-023 DSKPT */
4215     SW (dsklen);		/* 024 DSKLEN */
4216     SW (0);			/* 026 DSKDAT */
4217     SW (0);			/* 028 REFPTR */
4218     SW (lof);			/* 02A VPOSW */
4219     SW (0);			/* 02C VHPOSW */
4220     SW (copcon);		/* 02E COPCON */
4221     SW (serper);		/* 030 SERDAT * */
4222     SW (serdat);		/* 032 SERPER * */
4223     SW (potgo_value);		/* 034 POTGO */
4224     SW (0);			/* 036 JOYTEST * */
4225     SW (0);			/* 038 STREQU */
4226     SW (0);			/* 03A STRVBL */
4227     SW (0);			/* 03C STRHOR */
4228     SW (0);			/* 03E STRLONG */
4229     SW (bltcon0);		/* 040 BLTCON0 */
4230     SW (bltcon1);		/* 042 BLTCON1 */
4231     SW (blt_info.bltafwm);	/* 044 BLTAFWM */
4232     SW (blt_info.bltalwm);	/* 046 BLTALWM */
4233     SL (bltcpt);		/* 048-04B BLTCPT */
4234     SL (bltbpt);		/* 04C-04F BLTCPT */
4235     SL (bltapt);		/* 050-043 BLTCPT */
4236     SL (bltdpt);		/* 054-057 BLTCPT */
4237     SW (0);			/* 058 BLTSIZE */
4238     SW (0);			/* 05A BLTCON0L (use BLTCON0 instead) */
4239     SW (oldvblts);		/* 05C BLTSIZV */
4240     SW (blt_info.hblitsize);	/* 05E BLTSIZH */
4241     SW (blt_info.bltcmod);	/* 060 BLTCMOD */
4242     SW (blt_info.bltbmod);	/* 062 BLTBMOD */
4243     SW (blt_info.bltamod);	/* 064 BLTAMOD */
4244     SW (blt_info.bltdmod);	/* 066 BLTDMOD */
4245     SW (0);			/* 068 ? */
4246     SW (0);			/* 06A ? */
4247     SW (0);			/* 06C ? */
4248     SW (0);			/* 06E ? */
4249     SW (blt_info.bltcdat);	/* 070 BLTCDAT */
4250     SW (blt_info.bltbdat);	/* 072 BLTBDAT */
4251     SW (blt_info.bltadat);	/* 074 BLTADAT */
4252     SW (0);			/* 076 ? */
4253     SW (0);			/* 078 ? */
4254     SW (0);			/* 07A ? */
4255     SW (DENISEID());		/* 07C DENISEID/LISAID */
4256     SW (dsksync);		/* 07E DSKSYNC */
4257     SL (cop1lc);		/* 080-083 COP1LC */
4258     SL (cop2lc);		/* 084-087 COP2LC */
4259     SW (0);			/* 088 ? */
4260     SW (0);			/* 08A ? */
4261     SW (0);			/* 08C ? */
4262     SW (diwstrt);		/* 08E DIWSTRT */
4263     SW (diwstop);		/* 090 DIWSTOP */
4264     SW (ddfstrt);		/* 092 DDFSTRT */
4265     SW (ddfstop);		/* 094 DDFSTOP */
4266     SW (dmacon);		/* 096 DMACON */
4267     SW (clxcon);		/* 098 CLXCON */
4268     SW (intena);		/* 09A INTENA */
4269     SW (intreq);		/* 09C INTREQ */
4270     SW (adkcon);		/* 09E ADKCON */
4271     for (i = 0; i < 8; i++)
4272 	SL (bplpt[i]);		/* 0E0-0FE BPLxPT */
4273     SW (bplcon0);		/* 100 BPLCON0 */
4274     SW (bplcon1);		/* 102 BPLCON1 */
4275     SW (bplcon2);		/* 104 BPLCON2 */
4276     SW (bplcon3);		/* 106 BPLCON3 */
4277     SW (bpl1mod);		/* 108 BPL1MOD */
4278     SW (bpl2mod);		/* 10A BPL2MOD */
4279     SW (bplcon4);		/* 10C BPLCON4 */
4280     SW (clxcon2);		/* 10E CLXCON2 */
4281     for (i = 0;i < 8; i++)
4282 	SW (0);			/* 110 BPLxDAT */
4283     for ( i = 0; i < 32; i++)
4284 	SW (current_colors.color_regs_ecs[i]); /* 180-1BE COLORxx */
4285     SW (htotal);		/* 1C0 HTOTAL */
4286     SW (hsstop);		/* 1C2 HSTOP*/
4287     SW (hbstrt);		/* 1C4 HBSTRT */
4288     SW (hbstop);		/* 1C6 HBSTOP */
4289     SW (vtotal);		/* 1C8 VTOTAL */
4290     SW (vsstop);		/* 1CA VSSTOP */
4291     SW (vbstrt);		/* 1CC VBSTRT */
4292     SW (vbstop);		/* 1CE VBSTOP */
4293     SW (0);			/* 1D0 */
4294     SW (0);			/* 1D2 */
4295     SW (0);			/* 1D4 */
4296     SW (0);			/* 1D6 */
4297     SW (0);			/* 1D8 */
4298     SW (0);			/* 1DA */
4299     SW (beamcon0);		/* 1DC BEAMCON0 */
4300     SW (hsstrt);		/* 1DE HSSTRT */
4301     SW (vsstrt);		/* 1E0 VSSTRT */
4302     SW (hcenter);		/* 1E2 HCENTER */
4303     SW (diwhigh | (diwhigh_written ? 0x8000 : 0)); /* 1E4 DIWHIGH */
4304     SW (0);			/* 1E6 */
4305     SW (0);			/* 1E8 */
4306     SW (0);			/* 1EA */
4307     SW (0);			/* 1EC */
4308     SW (0);			/* 1EE */
4309     SW (0);			/* 1F0 */
4310     SW (0);			/* 1F2 */
4311     SW (0);			/* 1F4 */
4312     SW (0);			/* 1F6 */
4313     SW (0);			/* 1F8 */
4314     SW (0);			/* 1FA */
4315     SW (fmode);			/* 1FC FMODE */
4316     SW (last_custom_value);	/* 1FE */
4317 
4318     *len = dst - dstbak;
4319     return dstbak;
4320 }
4321 
restore_custom_agacolors(const uae_u8 * src)4322 const uae_u8 *restore_custom_agacolors (const uae_u8 *src)
4323 {
4324     int i;
4325 
4326     for (i = 0; i < 256; i++)
4327 	current_colors.color_regs_aga[i] = RL;
4328     return src;
4329 }
4330 
save_custom_agacolors(int * len,uae_u8 * dstptr)4331 uae_u8 *save_custom_agacolors (int *len, uae_u8 *dstptr)
4332 {
4333     uae_u8 *dstbak, *dst;
4334     int i;
4335 
4336     if (dstptr)
4337 	dstbak = dst = dstptr;
4338     else
4339 	dstbak = dst = malloc (256*4);
4340     for (i = 0; i < 256; i++)
4341 	SL (current_colors.color_regs_aga[i]);
4342     *len = dst - dstbak;
4343     return dstbak;
4344 }
4345 
restore_custom_sprite(int num,const uae_u8 * src)4346 const uae_u8 *restore_custom_sprite (int num, const uae_u8 *src)
4347 {
4348     spr[num].pt = RL;		/* 120-13E SPRxPT */
4349     sprpos[num] = RW;		/* 1x0 SPRxPOS */
4350     sprctl[num] = RW;		/* 1x2 SPRxPOS */
4351     sprdata[num][0] = RW;	/* 1x4 SPRxDATA */
4352     sprdatb[num][0] = RW;	/* 1x6 SPRxDATB */
4353     sprdata[num][1] = RW;
4354     sprdatb[num][1] = RW;
4355     sprdata[num][2] = RW;
4356     sprdatb[num][2] = RW;
4357     sprdata[num][3] = RW;
4358     sprdatb[num][3] = RW;
4359     spr[num].armed = RB;
4360     return src;
4361 }
4362 
save_custom_sprite(int num,int * len)4363 uae_u8 *save_custom_sprite(int num, int *len)
4364 {
4365     uae_u8 *dstbak, *dst;
4366 
4367     dstbak = dst = malloc (25);
4368     SL (spr[num].pt);		/* 120-13E SPRxPT */
4369     SW (sprpos[num]);		/* 1x0 SPRxPOS */
4370     SW (sprctl[num]);		/* 1x2 SPRxPOS */
4371     SW (sprdata[num][0]);	/* 1x4 SPRxDATA */
4372     SW (sprdatb[num][0]);	/* 1x6 SPRxDATB */
4373     SW (sprdata[num][1]);
4374     SW (sprdatb[num][1]);
4375     SW (sprdata[num][2]);
4376     SW (sprdatb[num][2]);
4377     SW (sprdata[num][3]);
4378     SW (sprdatb[num][3]);
4379     SB (spr[num].armed ? 1 : 0);
4380     *len = dst - dstbak;
4381     return dstbak;
4382 }
4383 
check_prefs_changed_custom(void)4384 void check_prefs_changed_custom (void)
4385 {
4386     currprefs.gfx_framerate = changed_prefs.gfx_framerate;
4387     if (inputdevice_config_change_test ()) {
4388 	inputdevice_copyconfig (&changed_prefs, &currprefs);
4389 	inputdevice_updateconfig (&currprefs);
4390     }
4391     currprefs.immediate_blits = changed_prefs.immediate_blits;
4392     currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled;
4393     currprefs.collision_level = changed_prefs.collision_level;
4394 }
4395