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(¤t_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, ¤t_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], ¤t_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