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