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