--- uae/src/custom.c 2018/04/24 17:07:27 1.1.1.19 +++ uae/src/custom.c 2018/04/24 17:18:35 1.1.1.25 @@ -3,9 +3,9 @@ * * Custom chip emulation * - * Copyright 1995-2001 Bernd Schmidt + * Copyright 1995-2002 Bernd Schmidt * Copyright 1995 Alessandro Bissacco - * Copyright 2000,2001 Toni Wilen + * Copyright 2000-2002 Toni Wilen */ #include "sysconfig.h" @@ -14,7 +14,6 @@ #include #include -#include "config.h" #include "options.h" #include "threaddep/thread.h" #include "uae.h" @@ -28,38 +27,29 @@ #include "disk.h" #include "blitter.h" #include "xwin.h" -#include "joystick.h" #include "audio.h" -#include "keybuf.h" #include "serial.h" #include "osemu.h" +#include "traps.h" #include "autoconf.h" +#include "inputdevice.h" +#include "keybuf.h" #include "gui.h" #include "picasso96.h" #include "drawing.h" #include "savestate.h" +#include "gayle.h" -static unsigned int n_consecutive_skipped = 0; -static unsigned int total_skipped = 0; +#define SPR0_HPOS 0x15 #define SPRITE_COLLISIONS -/* Mouse and joystick emulation */ - -int buttonstate[3]; -static int mouse_x, mouse_y; -int joy0button, joy1button; -unsigned int joy0dir, joy1dir; - -/* Events */ - -unsigned long int currcycle, nextevent, is_lastline; -static int rpt_did_reset; -struct ev eventtab[ev_max]; +static uae_u16 last_custom_value; -frame_time_t vsynctime, vsyncmintime; +static unsigned int n_consecutive_skipped = 0; +static unsigned int total_skipped = 0; -static int vpos; +int vpos; static uae_u16 lof; static int next_lineno; static enum nln_how nextline_how; @@ -83,25 +73,26 @@ uae_u16 dmacon; uae_u16 adkcon; /* used by audio code */ static uae_u32 cop1lc,cop2lc,copcon; - + int maxhpos = MAXHPOS_PAL; int maxvpos = MAXVPOS_PAL; -int minfirstline = MINFIRSTLINE_PAL; -int vblank_endline = VBLANK_ENDLINE_PAL; +int minfirstline = VBLANK_ENDLINE_PAL; int vblank_hz = VBLANK_HZ_PAL; -unsigned long syncbase; static int fmode; static unsigned int beamcon0, new_beamcon0; +uae_u16 vtotal = MAXVPOS_PAL, htotal = MAXHPOS_PAL; +static uae_u16 hsstop, hbstrt, hbstop, vsstop, vbstrt, vbstop, hsstrt, vsstrt, hcenter; + +#define HSYNCTIME (maxhpos * CYCLE_UNIT) #define MAX_SPRITES 8 /* This is but an educated guess. It seems to be correct, but this stuff * isn't documented well. */ -enum sprstate { SPR_stop, SPR_restart, SPR_waiting_start, SPR_waiting_stop }; +enum sprstate { SPR_restart, SPR_waiting_start, SPR_waiting_stop }; struct sprite { uaecptr pt; - int on; int xpos; int vstart; int vstop; @@ -109,9 +100,9 @@ struct sprite { enum sprstate state; }; -static struct sprite spr[8]; +static struct sprite spr[MAX_SPRITES]; -static int sprite_vblank_endline = VBLANK_ENDLINE_NTSC + 2; +static int sprite_vblank_endline = 25; static unsigned int sprctl[MAX_SPRITES], sprpos[MAX_SPRITES]; static uae_u16 sprdata[MAX_SPRITES][4], sprdatb[MAX_SPRITES][4]; @@ -142,12 +133,11 @@ enum diw_states DIW_waiting_start, DIW_waiting_stop }; -static int plffirstline, plflastline; -static int plfstrt, plfstop; +int plffirstline, plflastline, plfstrt, plfstop; static int last_diw_pix_hpos, last_ddf_pix_hpos, last_decide_line_hpos; static int last_fetch_hpos, last_sprite_hpos; int diwfirstword, diwlastword; -static enum diw_states diwstate, hdiwstate; +static enum diw_states diwstate, hdiwstate, ddfstate; /* Sprite collisions */ static unsigned int clxdat, clxcon, clxcon2, clxcon_bpl_enable, clxcon_bpl_match; @@ -181,31 +171,10 @@ struct copper { unsigned int ignore_next; int vcmp, hcmp; - /* When we schedule a copper event, knowing a few things about the future - of the copper list can reduce the number of sync_with_cpu calls - dramatically. */ - unsigned int first_sync; - unsigned int regtypes_modified; + int strobe; /* COPJMP1 / COPJMP2 accessed */ + int last_write, last_write_hpos; }; -#define REGTYPE_NONE 0 -#define REGTYPE_COLOR 1 -#define REGTYPE_SPRITE 2 -#define REGTYPE_PLANE 4 -#define REGTYPE_BLITTER 8 -#define REGTYPE_JOYPORT 16 -#define REGTYPE_DISK 32 -#define REGTYPE_POS 64 -#define REGTYPE_AUDIO 128 - -#define REGTYPE_ALL 255 -/* Always set in regtypes_modified, to enable a forced update when things like - DMACON, BPLCON0, COPJMPx get written. */ -#define REGTYPE_FORCE 256 - - -static unsigned int regtypes[512]; - static struct copper cop_state; static int copper_enabled_thisline; static int cop_min_waittime; @@ -296,6 +265,11 @@ enum fetchstate { * helper functions */ +STATIC_INLINE int nodraw (void) +{ + return framecnt != 0 || !curr_gfx; +} + uae_u32 get_copper_address (int copno) { switch (copno) { @@ -333,40 +307,6 @@ int find_copper_record (uaecptr addr, in return 0; } -int rpt_available = 0; - -void reset_frame_rate_hack (void) -{ - if (currprefs.m68k_speed != -1) - return; - - if (! rpt_available) { - currprefs.m68k_speed = 0; - return; - } - - rpt_did_reset = 1; - is_lastline = 0; - vsyncmintime = read_processor_time() + vsynctime; - write_log ("Resetting frame rate hack\n"); -} - -void check_prefs_changed_custom (void) -{ - currprefs.gfx_framerate = changed_prefs.gfx_framerate; - /* Not really the right place... */ - if (currprefs.jport0 != changed_prefs.jport0 - || currprefs.jport1 != changed_prefs.jport1) { - currprefs.jport0 = changed_prefs.jport0; - currprefs.jport1 = changed_prefs.jport1; - joystick_setting_changed (); - } - currprefs.immediate_blits = changed_prefs.immediate_blits; - currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled; - currprefs.collision_level = changed_prefs.collision_level; - currprefs.fast_copper = changed_prefs.fast_copper; -} - STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val) { if (val & 0x8000) @@ -396,14 +336,14 @@ STATIC_INLINE void docols (struct color_ int i; if (currprefs.chipset_mask & CSMASK_AGA) { - for (i = 0; i < 256; i++) { + for (i = 0; i < 256; i++) { int v = color_reg_get (colentry, i); if (v < 0 || v > 16777215) continue; colentry->acolors[i] = CONVERT_RGB (v); } } else { - for (i = 0; i < 32; i++) { + for (i = 0; i < 32; i++) { int v = color_reg_get (colentry, i); if (v < 0 || v > 4095) continue; @@ -424,7 +364,7 @@ void notice_new_xcolors (void) } } -static void do_sprites (int currvp, int currhp); +static void do_sprites (int currhp); static void remember_ctable (void) { @@ -487,19 +427,42 @@ static void decide_diw (int hpos) last_diw_pix_hpos = pix_hpos; } + +static int fetchmode; +static int maxplanes_ocs[]={ 6,4,0,0 }; +static int maxplanes_ecs[]={ 6,4,2,0 }; +static int maxplanes_aga[]={ 8,4,2,0, 8,8,4,0, 8,8,8,0 }; + +static int get_maxplanes (int res) +{ + int *planes; + if (currprefs.chipset_mask & CSMASK_AGA) + planes = maxplanes_aga; + else if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE)) + planes = maxplanes_ocs; + else + planes = maxplanes_ecs; + return planes[fetchmode * 4 + res]; +} + +/* Disable bitplane DMA if planes > maxplanes. This is needed e.g. by the + Sanity WOC demo (at the "Party Effect"). */ +STATIC_INLINE int GET_PLANES_LIMIT (uae_u16 v) +{ + if (GET_PLANES(v) > get_maxplanes (GET_RES(v))) + v &= ~0x7010; + return GET_PLANES (v); +} + /* The HRM says 0xD8, but that can't work... */ -#define HARD_DDF_STOP (0xD4) +#define HARD_DDF_STOP 0xd4 +#define HARD_DDF_START 0x18 -static void finish_playfield_line (void) +static void add_modulos (void) { int m1, m2; - /* The latter condition might be able to happen in interlaced frames. */ - if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line)) - thisframe_first_drawn_line = vpos; - thisframe_last_drawn_line = vpos; - - if ((currprefs.chipset_mask & CSMASK_AGA) && (fmode & 0x4000)) { + if (fmode & 0x4000) { if (((diwstrt >> 8) ^ vpos) & 1) m1 = m2 = bpl2mod; else @@ -510,7 +473,7 @@ static void finish_playfield_line (void) } if (dmaen (DMA_BITPLANE)) - switch (GET_PLANES (bplcon0)) { + switch (GET_PLANES_LIMIT (bplcon0)) { case 8: bplpt[7] += m2; case 7: bplpt[6] += m1; case 6: bplpt[5] += m2; @@ -520,6 +483,16 @@ static void finish_playfield_line (void) case 2: bplpt[1] += m2; case 1: bplpt[0] += m1; } +} + +static void finish_playfield_line (void) +{ + /* The latter condition might be able to happen in interlaced frames. */ + if (vpos >= minfirstline && (thisframe_first_drawn_line == -1 || vpos < thisframe_first_drawn_line)) + thisframe_first_drawn_line = vpos; + thisframe_last_drawn_line = vpos; + + add_modulos (); /* These are for comparison. */ thisline_decision.bplcon0 = bplcon0; @@ -539,8 +512,6 @@ static void finish_playfield_line (void) thisline_changed = 1; } -static int fetchmode; - /* The fetch unit mainly controls ddf stop. It's the number of cycles that are contained in an indivisible block during which ddf is active. E.g. if DDF starts at 0x30, and fetchunit is 8, then possible DDF stops are @@ -559,15 +530,17 @@ static int fetchstart, fetchstart_shift, static int fm_maxplane, fm_maxplane_shift; /* The corresponding values, by fetchmode and display resolution. */ -static int fetchunits[] = { 8,8,8,0, 16,8,8,0, 32,16,8,0 }; -static int fetchstarts[] = { 3,2,1,0, 4,3,2,0, 5,4,3,0 }; -static int fm_maxplanes[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 }; +static const int fetchunits[] = { 8,8,8,0, 16,8,8,0, 32,16,8,0 }; +static const int fetchstarts[] = { 3,2,1,0, 4,3,2,0, 5,4,3,0 }; +static const int fm_maxplanes[] = { 3,2,1,0, 3,3,2,0, 3,3,3,0 }; static int cycle_diagram_table[3][3][9][32]; +static int cycle_diagram_free_cycles[3][3][9]; +static int cycle_diagram_total_cycles[3][3][9]; static int *curr_diagram; -static 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 }; +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 }; -static void debug_cycle_diagram(void) +static void debug_cycle_diagram (void) { int fm, res, planes, cycle, v; char aa; @@ -576,25 +549,26 @@ static void debug_cycle_diagram(void) write_log ("FMODE %d\n=======\n", fm); for (res = 0; res <= 2; res++) { for (planes = 0; planes <= 8; planes++) { - write_log("%d: ",planes); + write_log ("%d: ",planes); for (cycle = 0; cycle < 32; cycle++) { v=cycle_diagram_table[fm][res][planes][cycle]; if (v==0) aa='-'; else if(v>0) aa='1'; else aa='X'; - write_log("%c",aa); + write_log ("%c",aa); } - write_log("\n"); + write_log (" %d:%d\n", + cycle_diagram_free_cycles[fm][res][planes], cycle_diagram_total_cycles[fm][res][planes]); } - write_log("\n"); + write_log ("\n"); } } fm=0; } -static void create_cycle_diagram_table(void) +static void create_cycle_diagram_table (void) { int fm, res, cycle, planes, v; - int fetch_start, max_planes; - int *cycle_sequence; + int fetch_start, max_planes, freecycles; + const int *cycle_sequence; for (fm = 0; fm <= 2; fm++) { for (res = 0; res <= 2; res++) { @@ -603,18 +577,22 @@ static void create_cycle_diagram_table(v cycle_sequence = &cycle_sequences[(max_planes - 1) * 8]; max_planes = 1 << max_planes; for (planes = 0; planes <= 8; planes++) { + freecycles = 0; for (cycle = 0; cycle < 32; cycle++) cycle_diagram_table[fm][res][planes][cycle] = -1; if (planes <= max_planes) { for (cycle = 0; cycle < fetch_start; cycle++) { if (cycle < max_planes && planes >= cycle_sequence[cycle & 7]) { - v = 1; + v = cycle_sequence[cycle & 7]; } else { v = 0; + freecycles++; } cycle_diagram_table[fm][res][planes][cycle] = v; } } + cycle_diagram_free_cycles[fm][res][planes] = freecycles; + cycle_diagram_total_cycles[fm][res][planes] = fetch_start; } } } @@ -658,10 +636,10 @@ static uae_u32 fetched_aga1[MAX_PLANES]; /* Expansions from bplcon0/bplcon1. */ static int toscr_res, toscr_delay1, toscr_delay2, toscr_nr_planes, fetchwidth; -/* The number of bits left from the last fetched words. +/* The number of bits left from the last fetched words. This is an optimization - conceptually, we have to make sure the result is the same as if toscr is called in each clock cycle. However, to speed this - up, we accumulate display data; this variable keeps track of how much. + up, we accumulate display data; this variable keeps track of how much. Thus, once we do call toscr_nbits (which happens at least every 16 bits), we can do more work at once. */ static int toscr_nbits; @@ -696,10 +674,6 @@ static void expand_fmodes (void) fm_maxplane = 1 << fm_maxplane_shift; } -static int maxplanes_ocs[]={ 6,4,0,0 }; -static int maxplanes_ecs[]={ 6,4,2,0 }; -static int maxplanes_aga[]={ 8,4,2,0, 8,8,4,0, 8,8,8,0 }; - /* Expand bplcon0/bplcon1 into the toscr_xxx variables. */ static void compute_toscr_delay_1 (void) { @@ -717,23 +691,8 @@ static void compute_toscr_delay_1 (void) static void compute_toscr_delay (int hpos) { - int v = bplcon0; - int *planes; - - if (currprefs.chipset_mask & CSMASK_AGA) - planes = maxplanes_aga; - else if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE)) - planes = maxplanes_ocs; - else - planes = maxplanes_ecs; - /* Disable bitplane DMA if planes > maxplanes. This is needed e.g. by the - Sanity WOC demo (at the "Party Effect"). */ - if (GET_PLANES(v) > planes[fetchmode*4 + GET_RES (v)]) - v &= ~0x7010; - toscr_res = GET_RES (v); - - toscr_nr_planes = GET_PLANES (v); - + toscr_res = GET_RES (bplcon0); + toscr_nr_planes = GET_PLANES_LIMIT (bplcon0); compute_toscr_delay_1 (); } @@ -754,7 +713,7 @@ STATIC_INLINE void fetch (int nr, int fm p = bplpt[nr] + bpl_off[nr]; switch (fm) { case 0: - fetched[nr] = chipmem_wget (p); + fetched[nr] = chipmem_agnus_wget (p); bplpt[nr] += 2; break; case 1: @@ -976,14 +935,14 @@ STATIC_INLINE void flush_display (int fm /* Called when all planes have been fetched, i.e. when a new block of data is available to be displayed. The data in fetched[] is moved into todisplay[]. */ -STATIC_INLINE void beginning_of_plane_block (int pos, int dma, int fm) +STATIC_INLINE void beginning_of_plane_block (int pos, int fm) { int i; flush_display (fm); if (fm == 0) - for (i = 0; i < MAX_PLANES; i++) + for (i = 0; i < MAX_PLANES; i++) todisplay[i][0] |= fetched[i]; else for (i = 0; i < MAX_PLANES; i++) { @@ -1003,7 +962,7 @@ STATIC_INLINE void beginning_of_plane_bl STATIC_INLINE void long_fetch_ecs (int plane, int nwords, int weird_number_of_bits, int dma) { uae_u16 *real_pt = (uae_u16 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2); - int delay = ((plane & 1) ? toscr_delay2 : toscr_delay1); + int delay = (plane & 1) ? toscr_delay2 : toscr_delay1; int tmp_nbits = out_nbits; uae_u32 shiftbuffer = todisplay[plane][0]; uae_u32 outval = outword[plane]; @@ -1058,7 +1017,7 @@ STATIC_INLINE void long_fetch_ecs (int p STATIC_INLINE void long_fetch_aga (int plane, int nwords, int weird_number_of_bits, int fm, int dma) { uae_u32 *real_pt = (uae_u32 *)pfield_xlateptr (bplpt[plane] + bpl_off[plane], nwords * 2); - int delay = ((plane & 1) ? toscr_delay2 : toscr_delay1); + int delay = (plane & 1) ? toscr_delay2 : toscr_delay1; int tmp_nbits = out_nbits; uae_u32 *shiftbuffer = todisplay[plane]; uae_u32 outval = outword[plane]; @@ -1142,7 +1101,6 @@ static void long_fetch_aga_2_1 (int hpos static void do_long_fetch (int hpos, int nwords, int dma, int fm) { - int added; int i; flush_display (fm); @@ -1191,13 +1149,15 @@ static void finish_final_fetch (int i, i { passed_plfstop = 3; - if (thisline_decision.plfleft != -1) { - i += flush_plane_data (fm); - thisline_decision.plfright = i; - thisline_decision.plflinelen = out_offs; - thisline_decision.bplres = toscr_res; - finish_playfield_line (); - } + if (thisline_decision.plfleft == -1) + return; + + ddfstate = DIW_waiting_start; + i += flush_plane_data (fm); + thisline_decision.plfright = i; + thisline_decision.plflinelen = out_offs; + thisline_decision.bplres = toscr_res; + finish_playfield_line (); } STATIC_INLINE int one_fetch_cycle_0 (int i, int ddfstop_to_test, int dma, int fm) @@ -1268,7 +1228,7 @@ STATIC_INLINE int one_fetch_cycle (int i case 0: return one_fetch_cycle_fm0 (i, ddfstop_to_test, dma); case 1: return one_fetch_cycle_fm1 (i, ddfstop_to_test, dma); case 2: return one_fetch_cycle_fm2 (i, ddfstop_to_test, dma); - default: abort (); + default: uae_abort ("fm corrupt"); } } @@ -1279,7 +1239,7 @@ STATIC_INLINE void update_fetch (int unt int ddfstop_to_test; - if (framecnt != 0 || passed_plfstop == 3) + if (nodraw () || passed_plfstop == 3) return; /* We need an explicit test against HARD_DDF_STOP here to guard against @@ -1362,7 +1322,7 @@ STATIC_INLINE void update_fetch (int unt #endif for (; pos < until; pos++) { if (fetch_state == fetch_was_plane0) - beginning_of_plane_block (pos, dma, fm); + beginning_of_plane_block (pos, fm); fetch_state = fetch_started; if (one_fetch_cycle (pos, ddfstop_to_test, dma, fm)) @@ -1392,6 +1352,53 @@ STATIC_INLINE void decide_fetch (int hpo last_fetch_hpos = hpos; } +static void start_bpl_dma (int hstart) +{ + fetch_state = fetch_started; + fetch_cycle = 0; + last_fetch_hpos = hstart; + out_nbits = 0; + out_offs = 0; + toscr_nbits = 0; + + ddfstate = DIW_waiting_stop; + compute_toscr_delay (last_fetch_hpos); + + /* If someone already wrote BPL1DAT, clear the area between that point and + the real fetch start. */ + if (!nodraw ()) { + if (thisline_decision.plfleft != -1) { + out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res); + out_offs = out_nbits >> 5; + out_nbits &= 31; + } + update_toscr_planes (); + } +} + +/* this may turn on datafetch if program turns dma on during the ddf */ +static void maybe_start_bpl_dma (int hpos) +{ + /* OCS: BPL DMA never restarts if DMA is turned on during DDF + * ECS/AGA: BPL DMA restarts but only if DMA was turned off + outside of DDF or during current line, otherwise display + processing jumps immediately to "DDFSTOP passed"-condition */ + if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS)) + return; + if (fetch_state != fetch_not_started) + return; + if (diwstate != DIW_waiting_stop) + return; + if (hpos <= plfstrt) + return; + if (hpos > plfstop - fetchunit) + return; + if (ddfstate != DIW_waiting_start) + passed_plfstop = 1; + + start_bpl_dma (hpos); +} + /* This function is responsible for turning on datafetch if necessary. */ STATIC_INLINE void decide_line (int hpos) { @@ -1416,34 +1423,17 @@ STATIC_INLINE void decide_line (int hpos if (dmaen (DMA_BITPLANE) && diwstate == DIW_waiting_stop) { - fetch_state = fetch_started; - fetch_cycle = 0; - last_fetch_hpos = plfstrt; - out_nbits = 0; - out_offs = 0; - toscr_nbits = 0; - - compute_toscr_delay (last_fetch_hpos); - - /* If someone already wrote BPL1DAT, clear the area between that point and - the real fetch start. */ - if (framecnt == 0) { - if (thisline_decision.plfleft != -1) { - out_nbits = (plfstrt - thisline_decision.plfleft) << (1 + toscr_res); - out_offs = out_nbits >> 5; - out_nbits &= 31; - } - update_toscr_planes (); - } + start_bpl_dma (plfstrt); + estimate_last_fetch_cycle (plfstrt); last_decide_line_hpos = hpos; - do_sprites (vpos, plfstrt); + do_sprites (plfstrt); return; } } if (last_decide_line_hpos < 0x34) - do_sprites (vpos, hpos); + do_sprites (hpos); last_decide_line_hpos = hpos; } @@ -1454,12 +1444,12 @@ static void record_color_change (int hpo { if (regno == -1 && value) { thisline_decision.ham_seen = 1; - if (hpos < 0x18) + if (hpos < HARD_DDF_START) thisline_decision.ham_at_start = 1; } /* Early positions don't appear on-screen. */ - if (framecnt != 0 || vpos < minfirstline || hpos < 0x18 + if (nodraw () || vpos < minfirstline || hpos < HARD_DDF_START /*|| currprefs.emul_accuracy == 0*/) return; @@ -1491,7 +1481,7 @@ static void do_playfield_collisions (voi clxdat |= 1; return; } - + for (i = thisline_decision.plfleft; i < thisline_decision.plfright; i += 2) { int j; uae_u32 total = 0xFFFFFFFF; @@ -1506,7 +1496,7 @@ static void do_playfield_collisions (voi total &= t; } if (total) - clxdat |= 1; + clxdat |= 1; } } @@ -1647,7 +1637,7 @@ static void record_sprite (int line, int uae_u16 *buf; uae_u32 collision_mask; int width = sprite_width; - int dbl = 0; + int dbl = 0, half = 0; unsigned int mask = 0; if (sprres != RES_LORES) @@ -1656,6 +1646,10 @@ static void record_sprite (int line, int if (currprefs.chipset_mask & CSMASK_AGA) { width = (width << 1) >> sprres; dbl = sprite_buffer_res - sprres; + if (dbl < 0) { + half = -dbl; + dbl = 0; + } mask = sprres == RES_SUPERHIRES ? 1 : 0; } @@ -1669,7 +1663,7 @@ static void record_sprite (int line, int } if (sprxp < e->pos) - abort (); + uae_abort ("sprxp < e->pos"); e->max = sprxp + width; e[1].first_pixel = e->first_pixel + ((e->max - e->pos + 3) & ~3); @@ -1684,7 +1678,7 @@ static void record_sprite (int line, int uae_u32 datab = ((sprtaba[da & 0xFF] << 16) | sprtaba[da >> 8] | (sprtabb[db & 0xFF] << 16) | sprtabb[db >> 8]); - buf = spixels + word_offs + (i << dbl); + buf = spixels + word_offs + ((i << dbl) >> half); if (currprefs.collision_level > 0 && collision_mask) record_sprite_1 (buf, datab, num, dbl, mask, 1, collision_mask); else @@ -1699,7 +1693,7 @@ static void record_sprite (int line, int if (ctl & (num << 7) & 0x80) { uae_u32 state = 0x01010101 << (num - 1); uae_u32 *stbuf = spixstate.words + (word_offs >> 2); - uae_u8 *stb1 = spixstate.bytes + word_offs; + uae_u8 *stb1 = spixstate.bytes + word_offs; for (i = 0; i < width; i += 8) { stb1[0] |= state; stb1[1] |= state; @@ -1723,7 +1717,7 @@ static void decide_sprites (int hpos) int width = sprite_width; int window_width = (width << lores_shift) >> sprres; - if (framecnt != 0 || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point) + if (nodraw () || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point) return; decide_diw (hpos); @@ -1741,13 +1735,6 @@ static void decide_sprites (int hpos) int window_xp = coord_hw_to_window_x (hw_xp) + (DIW_DDF_OFFSET << lores_shift); int j, bestp; - /* ??? It is uncertain where exactly sprite data is needed. It appears - to be used some time after the actual position given in SPRxPOS. - How soon after is an open question. For Battle Squadron, using a - value of 5 seems to be enough to meet all timing constraints. - This gives it 2 more color clock cycles until the data appears on - the screen. */ - hw_xp += 5; if (! spr[i].armed || sprxp < 0 || hw_xp <= last_sprite_point || hw_xp > point) continue; if ((thisline_decision.diwfirstword >= 0 && window_xp + window_width < thisline_decision.diwfirstword) @@ -1770,7 +1757,7 @@ static void decide_sprites (int hpos) count++; } for (i = 0; i < count; i++) { - int nr = nrs[i]; + int nr = nrs[i]; record_sprite (next_lineno, nr, spr[nr].xpos, sprdata[nr], sprdatb[nr], sprctl[nr]); } last_sprite_point = point; @@ -1786,7 +1773,7 @@ STATIC_INLINE int sprites_differ (struct if (dip->nr_sprites != dip_old->nr_sprites) return 1; - + if (dip->nr_sprites == 0) return 0; @@ -1809,7 +1796,7 @@ STATIC_INLINE int color_changes_differ ( { if (dip->nr_color_changes != dip_old->nr_color_changes) return 1; - + if (dip->nr_color_changes == 0) return 0; if (memcmp (curr_color_changes + dip->first_color_change, @@ -1829,7 +1816,7 @@ static void finish_decisions (void) int changed; int hpos = current_hpos (); - if (framecnt != 0) + if (nodraw ()) return; decide_diw (hpos); @@ -1897,7 +1884,7 @@ static void finish_decisions (void) /* Set the state of all decisions to "undecided" for a new scanline. */ static void reset_decisions (void) { - if (framecnt != 0) + if (nodraw ()) return; thisline_decision.any_hires_sprites = 0; @@ -1941,6 +1928,18 @@ static void reset_decisions (void) last_fetch_hpos = -1; } +static void dumpsync (void) +{ + static int cnt = 10; + if (cnt < 0) + return; + cnt--; + write_log ("BEAMCON0=%04.4X VTOTAL=%04.4X HTOTAL=%04.4X\n", new_beamcon0, vtotal, htotal); + write_log ("HSSTOP=%04.4X HBSTRT=%04.4X HBSTOP=%04.4X\n", hsstop, hbstrt, hbstop); + write_log ("VSSTOP=%04.4X VBSTRT=%04.4X VBSTOP=%04.4X\n", vsstop, vbstrt, vbstop); + write_log ("HSSTRT=%04.4X VSSTRT=%04.4X HCENTER=%04.4X\n", hsstrt, vsstrt, hcenter); +} + /* set PAL or NTSC timing variables */ static void init_hz (void) @@ -1953,19 +1952,39 @@ static void init_hz (void) if (!isntsc) { maxvpos = MAXVPOS_PAL; maxhpos = MAXHPOS_PAL; - minfirstline = MINFIRSTLINE_PAL; - vblank_endline = VBLANK_ENDLINE_PAL; + minfirstline = VBLANK_ENDLINE_PAL; vblank_hz = VBLANK_HZ_PAL; + sprite_vblank_endline = VBLANK_SPRITE_PAL; } else { maxvpos = MAXVPOS_NTSC; maxhpos = MAXHPOS_NTSC; - minfirstline = MINFIRSTLINE_NTSC; - vblank_endline = VBLANK_ENDLINE_NTSC; + minfirstline = VBLANK_ENDLINE_NTSC; vblank_hz = VBLANK_HZ_NTSC; + sprite_vblank_endline = VBLANK_SPRITE_NTSC; + } + if (beamcon0 & 0x80) { + if (vtotal >= MAXVPOS) + vtotal = MAXVPOS - 1; + maxvpos = vtotal + 1; + if (htotal >= MAXHPOS) + htotal = MAXHPOS - 1; + maxhpos = htotal + 1; + vblank_hz = 227 * 312 * 50 / (maxvpos * maxhpos); + minfirstline = vsstop; + if (minfirstline < 2) + minfirstline = 2; + if (minfirstline >= maxvpos) + minfirstline = maxvpos - 1; + sprite_vblank_endline = minfirstline - 2; + dumpsync (); } - vsynctime = syncbase / vblank_hz; + eventtab[ev_hsync].oldcycles = get_cycles (); + eventtab[ev_hsync].evtime = get_cycles() + HSYNCTIME; + events_schedule (); + compute_vsynctime (); - write_log ("Using %s timing\n", isntsc ? "NTSC" : "PAL"); + write_log ("%s mode, %dHz (h=%d v=%d)\n", + isntsc ? "NTSC" : "PAL", vblank_hz, maxhpos, maxvpos); } static void calcdiw (void) @@ -2014,180 +2033,9 @@ static void calcdiw (void) plfstrt = 0x18; } -/* Mousehack stuff */ - -#define defstepx (1<<16) -#define defstepy (1<<16) -#define defxoffs 0 -#define defyoffs 0 - -static const int docal = 60, xcaloff = 40, ycaloff = 20; -static const int calweight = 3; -static int lastsampledmx, lastsampledmy; -static int lastspr0x,lastspr0y,lastdiffx,lastdiffy,spr0pos,spr0ctl; -static int mstepx,mstepy,xoffs=defxoffs,yoffs=defyoffs; -static int sprvbfl; - -int lastmx, lastmy; -int newmousecounters; -int ievent_alive = 0; - -static enum { unknown_mouse, normal_mouse, dont_care_mouse, follow_mouse } mousestate; - -static void mousehack_setdontcare (void) -{ - if (mousestate == dont_care_mouse) - return; - - write_log ("Don't care mouse mode set\n"); - mousestate = dont_care_mouse; - lastspr0x = lastmx; lastspr0y = lastmy; - mstepx = defstepx; mstepy = defstepy; -} - -static void mousehack_setfollow (void) -{ - if (mousestate == follow_mouse) - return; - - write_log ("Follow sprite mode set\n"); - mousestate = follow_mouse; - lastdiffx = lastdiffy = 0; - sprvbfl = 0; - spr0ctl = spr0pos = 0; - mstepx = defstepx; mstepy = defstepy; -} - -static uae_u32 mousehack_helper (void) -{ - int mousexpos, mouseypos; - -#ifdef PICASSO96 - if (picasso_on) { - picasso_clip_mouse (&lastmx, &lastmy); - mousexpos = lastmx; - mouseypos = lastmy; - } else -#endif - { - /* @@@ This isn't completely right, it doesn't deal with virtual - screen sizes larger than physical very well. */ - if (lastmy >= gfxvidinfo.height) - lastmy = gfxvidinfo.height - 1; - if (lastmy < 0) - lastmy = 0; - if (lastmx < 0) - lastmx = 0; - if (lastmx >= gfxvidinfo.width) - lastmx = gfxvidinfo.width - 1; - mouseypos = coord_native_to_amiga_y (lastmy) << 1; - mousexpos = coord_native_to_amiga_x (lastmx); - } - - switch (m68k_dreg (regs, 0)) { - case 0: - return ievent_alive ? -1 : needmousehack (); - case 1: - ievent_alive = 10; - return mousexpos; - case 2: - return mouseypos; - } - return 0; -} - -void togglemouse (void) -{ - switch (mousestate) { - case dont_care_mouse: mousehack_setfollow (); break; - case follow_mouse: mousehack_setdontcare (); break; - default: break; /* Nnnnnghh! */ - } -} - -STATIC_INLINE int adjust (int val) -{ - if (val > 127) - return 127; - else if (val < -127) - return -127; - return val; -} - -static void do_mouse_hack (void) -{ - int spr0x = ((spr0pos & 0xff) << 2) | ((spr0ctl & 1) << 1); - int spr0y = ((spr0pos >> 8) | ((spr0ctl & 4) << 6)) << 1; - int diffx, diffy; - - if (ievent_alive > 0) { - mouse_x = mouse_y = 0; - return; - } - switch (mousestate) { - case normal_mouse: - diffx = lastmx - lastsampledmx; - diffy = lastmy - lastsampledmy; - if (!newmousecounters) { - if (diffx > 127) diffx = 127; - if (diffx < -127) diffx = -127; - mouse_x += diffx; - if (diffy > 127) diffy = 127; - if (diffy < -127) diffy = -127; - mouse_y += diffy; - } - lastsampledmx += diffx; lastsampledmy += diffy; - break; - - case dont_care_mouse: - diffx = adjust (((lastmx - lastspr0x) * mstepx) >> 16); - diffy = adjust (((lastmy - lastspr0y) * mstepy) >> 16); - lastspr0x = lastmx; lastspr0y = lastmy; - mouse_x += diffx; mouse_y += diffy; - break; - - case follow_mouse: - if (sprvbfl && sprvbfl-- > 1) { - int mousexpos, mouseypos; - - if ((lastdiffx > docal || lastdiffx < -docal) - && lastspr0x != spr0x - && spr0x > plfstrt*4 + 34 + xcaloff - && spr0x < plfstop*4 - xcaloff) - { - int val = (lastdiffx << 16) / (spr0x - lastspr0x); - if (val >= 0x8000) - mstepx = (mstepx * (calweight - 1) + val) / calweight; - } - if ((lastdiffy > docal || lastdiffy < -docal) - && lastspr0y != spr0y - && spr0y > plffirstline + ycaloff - && spr0y < plflastline - ycaloff) - { - int val = (lastdiffy << 16) / (spr0y - lastspr0y); - if (val >= 0x8000) - mstepy = (mstepy * (calweight - 1) + val) / calweight; - } - if (lastmy >= gfxvidinfo.height) - lastmy = gfxvidinfo.height-1; - mouseypos = coord_native_to_amiga_y (lastmy) << 1; - mousexpos = coord_native_to_amiga_x (lastmx); - diffx = adjust ((((mousexpos + xoffs - spr0x) & ~1) * mstepx) >> 16); - diffy = adjust ((((mouseypos + yoffs - spr0y) & ~1) * mstepy) >> 16); - lastspr0x = spr0x; lastspr0y = spr0y; - lastdiffx = diffx; lastdiffy = diffy; - mouse_x += diffx; mouse_y += diffy; - } - break; - - default: - abort (); - } -} - static int timehack_alive = 0; -static uae_u32 timehack_helper (void) +static uae_u32 timehack_helper (TrapContext *dummy) { #ifdef HAVE_GETTIMEOFDAY struct timeval tv; @@ -2216,23 +2064,28 @@ STATIC_INLINE uae_u16 DENISEID (void) return 0xFC; return 0xFFFF; } + STATIC_INLINE uae_u16 DMACONR (void) { return (dmacon | (bltstate==BLT_done ? 0 : 0x4000) | (blt_info.blitzero ? 0x2000 : 0)); } + STATIC_INLINE uae_u16 INTENAR (void) { return intena; } + uae_u16 INTREQR (void) { - return intreq /* | (currprefs.use_serial ? 0x0001 : 0) */; + return intreq; } + STATIC_INLINE uae_u16 ADKCONR (void) { return adkcon; } + STATIC_INLINE uae_u16 VPOSR (void) { unsigned int csbit = currprefs.ntscmode ? 0x1000 : 0; @@ -2240,6 +2093,7 @@ STATIC_INLINE uae_u16 VPOSR (void) csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0; return (vpos >> 8) | lof | csbit; } + static void VPOSW (uae_u16 v) { if (lof != (v & 0x8000)) @@ -2261,9 +2115,10 @@ STATIC_INLINE void COP1LCL (uae_u16 v) { STATIC_INLINE void COP2LCH (uae_u16 v) { cop2lc = (cop2lc & 0xffff) | ((uae_u32)v << 16); } STATIC_INLINE void COP2LCL (uae_u16 v) { cop2lc = (cop2lc & ~0xffff) | (v & 0xfffe); } -static void start_copper (void) +static void COPJMP (int num) { int was_active = eventtab[ev_copper].active; + cop_state.ip = num == 1 ? cop1lc : cop2lc; eventtab[ev_copper].active = 0; if (was_active) events_schedule (); @@ -2279,24 +2134,12 @@ static void start_copper (void) } } -static void COPJMP1 (uae_u16 a) -{ - cop_state.ip = cop1lc; - start_copper (); -} - -static void COPJMP2 (uae_u16 a) -{ - cop_state.ip = cop2lc; - start_copper (); -} - STATIC_INLINE void COPCON (uae_u16 a) { copcon = a; } -static void DMACON (int hpos, uae_u16 v) +static void DMACON (unsigned int hpos, uae_u16 v) { int i; @@ -2339,25 +2182,33 @@ static void DMACON (int hpos, uae_u16 v) if ((dmacon & (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) != (DMA_BLITPRI | DMA_BLITTER | DMA_MASTER)) unset_special (SPCFLAG_BLTNASTY); - if (currprefs.produce_sound > 0) { - update_audio (); + if (currprefs.produce_sound > 0) + update_audio_dmacon (); - for (i = 0; i < 4; i++) { - struct audio_channel_data *cdp = audio_channel + i; - int chan_ena = (dmacon & 0x200) && (dmacon & (1<dmaen == chan_ena) - continue; - cdp->dmaen = chan_ena; - if (cdp->dmaen) - audio_channel_enable_dma (cdp); - else - audio_channel_disable_dma (cdp); - } - schedule_audio (); - } events_schedule(); } +/* + * Get level of interrupt request presented to CPU. + * + * If no IRQs are active and enabled, returns -1. + * If none of the active IRQs have yet reached the CPU, returns 0. + * Otherwise, returns the priority level of the highest priorty active IRQ. + */ +int intlev (void) +{ + uae_u16 imask = intreq & intena; + if (imask && (intena & 0x4000)){ + if (imask & 0x2000) return 6; + if (imask & 0x1800) return 5; + if (imask & 0x0780) return 4; + if (imask & 0x0070) return 3; + if (imask & 0x0008) return 2; + if (imask & 0x0007) return 1; + } + return -1; +} + /*static int trace_intena = 0;*/ STATIC_INLINE void INTENA (uae_u16 v) @@ -2366,7 +2217,7 @@ STATIC_INLINE void INTENA (uae_u16 v) write_log ("INTENA: %04x\n", v);*/ setclr (&intena,v); /* There's stupid code out there that does - [some INTREQ bits at level 3 are set] + [some INTREQ bits at level 3 are set] clear all INTREQ bits Enable one INTREQ level 3 bit Set level 3 handler @@ -2393,17 +2244,6 @@ void INTREQ (uae_u16 v) rethink_cias (); } -static void update_adkmasks (void) -{ - unsigned long t; - - t = adkcon | (adkcon >> 4); - audio_channel[0].adk_mask = (((t >> 0) & 1) - 1); - audio_channel[1].adk_mask = (((t >> 1) & 1) - 1); - audio_channel[2].adk_mask = (((t >> 2) & 1) - 1); - audio_channel[3].adk_mask = (((t >> 3) & 1) - 1); -} - static void ADKCON (uae_u16 v) { if (currprefs.produce_sound > 0) @@ -2415,17 +2255,32 @@ static void ADKCON (uae_u16 v) static void BEAMCON0 (uae_u16 v) { - if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) - new_beamcon0 = v & 0x20; + if (currprefs.chipset_mask & CSMASK_ECS_AGNUS) { + if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) + v &= 0x20; + if (v != new_beamcon0) { + new_beamcon0 = v; + if (v & ~0x20) + write_log ("warning: %04.4X written to BEAMCON0\n", v); + } + } } -static void BPLPTH (int hpos, uae_u16 v, int num) +static void varsync (void) +{ + if (!(currprefs.chipset_mask & CSMASK_ECS_DENISE)) + return; + if (!(beamcon0 & 0x80)) + return; +} + +static void BPLxPTH (int hpos, uae_u16 v, int num) { decide_line (hpos); decide_fetch (hpos); bplpt[num] = (bplpt[num] & 0xffff) | ((uae_u32)v << 16); } -static void BPLPTL (int hpos, uae_u16 v, int num) +static void BPLxPTL (int hpos, uae_u16 v, int num) { decide_line (hpos); decide_fetch (hpos); @@ -2448,7 +2303,7 @@ static void BPLCON0 (int hpos, uae_u16 v if ((bplcon0 ^ v) & 0x800) { record_color_change (hpos, -1, !! (v & 0x800)); } - + bplcon0 = v; curr_diagram = cycle_diagram_table[fetchmode][GET_RES(bplcon0)][GET_PLANES (v)]; @@ -2715,20 +2570,13 @@ static void BLTSIZH (uae_u16 v) do_blitter (); } -STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num) +STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num, int hpos) { int sprxp; + struct sprite *s = &spr[num]; sprctl[num] = v; - nr_armed -= spr[num].armed; - spr[num].armed = 0; - if (sprpos[num] == 0 && v == 0) { - spr[num].state = SPR_stop; - spr[num].on = 0; - } else if (spr[num].state != SPR_waiting_stop) { - spr[num].state = SPR_waiting_start; - spr[num].on = 1; - } - + nr_armed -= s->armed; + s->armed = 0; sprxp = (sprpos[num] & 0xFF) * 2 + (v & 1); /* Quite a bit salad in this register... */ @@ -2739,14 +2587,19 @@ STATIC_INLINE void SPRxCTL_1 (uae_u16 v, sprxp <<= 1; sprxp |= (v >> 4) & 1; } - spr[num].xpos = sprxp; - spr[num].vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); - spr[num].vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100); - + s->xpos = sprxp; + s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); + s->vstop = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100); + if (vpos == s->vstart) + s->state = SPR_waiting_stop; +#ifdef SPRITE_DEBUG + write_log ("%d:%d:SPR%dCTL V=%04.4X STATE=%d ARMED=%d\n", vpos, hpos, num, v, s->state, s->armed); +#endif } -STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num) +STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num, int hpos) { int sprxp; + struct sprite *s = &spr[num]; sprpos[num] = v; sprxp = (v & 0xFF) * 2 + (sprctl[num] & 1); @@ -2754,8 +2607,11 @@ STATIC_INLINE void SPRxPOS_1 (uae_u16 v, sprxp <<= 1; sprxp |= (sprctl[num] >> 4) & 1; } - spr[num].xpos = sprxp; - spr[num].vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); + s->xpos = sprxp; + s->vstart = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); +#ifdef SPRITE_DEBUG + write_log ("%d:%d:SPR%dPOS %04.4X STATE=%d ARMED=%d\n", vpos, hpos, num, v, s->state, s->armed); +#endif } STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num) { @@ -2769,28 +2625,27 @@ STATIC_INLINE void SPRxDATB_1 (uae_u16 v } static void SPRxDATA (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATA_1 (v, num); } static void SPRxDATB (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxDATB_1 (v, num); } -static void SPRxCTL (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxCTL_1 (v, num); } -static void SPRxPOS (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxPOS_1 (v, num); } +static void SPRxCTL (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxCTL_1 (v, num, hpos); } +static void SPRxPOS (int hpos, uae_u16 v, int num) { decide_sprites (hpos); SPRxPOS_1 (v, num, hpos); } static void SPRxPTH (int hpos, uae_u16 v, int num) { decide_sprites (hpos); spr[num].pt &= 0xffff; spr[num].pt |= (uae_u32)v << 16; - - if (spr[num].state == SPR_stop || vpos < sprite_vblank_endline) - spr[num].state = SPR_restart; - spr[num].on = 1; +#ifdef SPRITE_DEBUG + write_log ("%d:%d:SPR%dPTH %08.8X\n", vpos, hpos, num, spr[num].pt); +#endif } static void SPRxPTL (int hpos, uae_u16 v, int num) { decide_sprites (hpos); spr[num].pt &= ~0xffff; spr[num].pt |= v; - - if (spr[num].state == SPR_stop || vpos < sprite_vblank_endline) - spr[num].state = SPR_restart; - spr[num].on = 1; +#ifdef SPRITE_DEBUG + write_log ("%d:%d:SPR%dPTL %08.8X\n", vpos, hpos, num, spr[num].pt); +#endif } + static void CLXCON (uae_u16 v) { clxcon = v; @@ -2882,81 +2737,14 @@ static void COLOR_WRITE (int hpos, uae_u } } -static uae_u16 potgo_value; - -static void POTGO (uae_u16 v) -{ - potgo_value = v; -} - -static uae_u16 POTGOR (void) -{ - uae_u16 v = (potgo_value | (potgo_value >> 1)) & 0x5500; - - v |= (~potgo_value & 0xAA00) >> 1; - - if (JSEM_ISMOUSE (0, &currprefs)) { - if (buttonstate[2]) - v &= 0xFBFF; - - if (buttonstate[1]) - v &= 0xFEFF; - } else if (JSEM_ISJOY0 (0, &currprefs) || JSEM_ISJOY1 (0, &currprefs)) { - if (joy0button & 2) v &= 0xfbff; - if (joy0button & 4) v &= 0xfeff; - } - - if (JSEM_ISJOY0 (1, &currprefs) || JSEM_ISJOY1 (1, &currprefs)) { - if (joy1button & 2) v &= 0xbfff; - if (joy1button & 4) v &= 0xefff; - } - - return v; -} - -static uae_u16 POT0DAT (void) -{ - static uae_u16 cnt = 0; - if (JSEM_ISMOUSE (0, &currprefs)) { - if (buttonstate[2]) - cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00); - if (buttonstate[1]) - cnt += 0x100; - } - - return cnt; -} -static uae_u16 JOY0DAT (void) -{ - if (JSEM_ISMOUSE (0, &currprefs)) { - do_mouse_hack (); - return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8); - } - return joy0dir; -} -static uae_u16 JOY1DAT (void) -{ - if (JSEM_ISMOUSE (1, &currprefs)) { - do_mouse_hack (); - return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8); - } - return joy1dir; -} -static void JOYTEST (uae_u16 v) -{ - if (JSEM_ISMOUSE (0, &currprefs)) { - mouse_x = v & 0xFC; - mouse_y = (v >> 8) & 0xFC; - } -} - /* The copper code. The biggest nightmare in the whole emulator. Alright. The current theory: - 1. Copper moves happen 4 cycles after state READ2 is reached. + 1. Copper moves happen 2 cycles after state READ2 is reached. It can't happen immediately when we reach READ2, because the - data needs time to get back from the bus. 4 cycles appears - to be the time a chip memory access takes on the Amiga. + data needs time to get back from the bus. An additional 2 + cycles are needed for non-Agnus registers, to take into account + the delay for moving data from chip to chip. 2. As stated in the HRM, a WAIT really does need an extra cycle to wake up. This is implemented by _not_ falling through from a successful wait to READ1, but by starting the next cycle. @@ -3021,155 +2809,15 @@ STATIC_INLINE int dangerous_reg (int reg return 1; } -#define FAST_COPPER 1 - -/* The future, Conan? - We try to look ahead in the copper list to avoid doing continuous calls - to updat_copper (which is what happens when SPCFLAG_COPPER is set). If - we find that the same effect can be achieved by setting a delayed event - and then doing multiple copper insns in one batch, we can get a massive - speedup. - - We don't try to be precise here. All copper reads take exactly 2 cycles, - the effect of bitplane contention is ignored. Trying to get it exactly - right would be much more complex and as such carry a huge risk of getting - it subtly wrong; and it would also be more expensive - we want this code - to be fast. */ -static void predict_copper (void) -{ - uaecptr ip = cop_state.ip; - unsigned int c_hpos = cop_state.hpos; - enum copper_states state = cop_state.state; - unsigned int w1, w2, cycle_count; - - switch (state) { - case COP_read1_wr_in2: - case COP_read2_wr_in2: - case COP_read1_wr_in4: - if (dangerous_reg (cop_state.saved_i1)) - return; - state = state == COP_read2_wr_in2 ? COP_read2 : COP_read1; - break; - - case COP_read1_in2: - c_hpos += 2; - state = COP_read1; - break; - - case COP_stop: - case COP_bltwait: - case COP_wait1: - case COP_skip_in4: - case COP_skip_in2: - return; - - case COP_wait_in4: - c_hpos += 2; - /* fallthrough */ - case COP_wait_in2: - c_hpos += 2; - /* fallthrough */ - case COP_wait: - state = COP_wait; - break; - - default: - break; - } - /* Only needed for COP_wait, but let's shut up the compiler. */ - w1 = cop_state.saved_i1; - w2 = cop_state.saved_i2; - cop_state.first_sync = c_hpos; - cop_state.regtypes_modified = REGTYPE_FORCE; - - /* Get this case out of the way, so that the loop below only has to deal - with read1 and wait. */ - if (state == COP_read2) { - w1 = cop_state.i1; - if (w1 & 1) { - w2 = chipmem_wget (ip); - if (w2 & 1) - goto done; - state = COP_wait; - c_hpos += 4; - } else if (dangerous_reg (w1)) { - c_hpos += 4; - goto done; - } else { - cop_state.regtypes_modified |= regtypes[w1 & 0x1FE]; - state = COP_read1; - c_hpos += 2; - } - ip += 2; - } - - while (c_hpos + 1 < maxhpos) { - if (state == COP_read1) { - w1 = chipmem_wget (ip); - if (w1 & 1) { - w2 = chipmem_wget (ip + 2); - if (w2 & 1) - break; - state = COP_wait; - c_hpos += 6; - } else if (dangerous_reg (w1)) { - c_hpos += 6; - goto done; - } else { - cop_state.regtypes_modified |= regtypes[w1 & 0x1FE]; - c_hpos += 4; - } - ip += 4; - } else if (state == COP_wait) { - if ((w2 & 0xFE) != 0xFE) - break; - else { - unsigned int vcmp = (w1 & (w2 | 0x8000)) >> 8; - unsigned int hcmp = (w1 & 0xFE); - - unsigned int vp = vpos & (((w2 >> 8) & 0x7F) | 0x80); - if (vp < vcmp) { - /* Whee. We can wait until the end of the line! */ - c_hpos = maxhpos; - } else if (vp > vcmp || hcmp <= c_hpos) { - state = COP_read1; - /* minimum wakeup time */ - c_hpos += 2; - } else { - state = COP_read1; - c_hpos = hcmp; - } - /* If this is the current instruction, remember that we don't - need to sync CPU and copper anytime soon. */ - if (cop_state.ip == ip) { - cop_state.first_sync = c_hpos; - } - } - } else - abort (); - } - - done: - cycle_count = c_hpos - cop_state.hpos; - if (cycle_count >= 8) { - unset_special (SPCFLAG_COPPER); - eventtab[ev_copper].active = 1; - eventtab[ev_copper].oldcycles = get_cycles (); - eventtab[ev_copper].evtime = get_cycles () + cycle_count * CYCLE_UNIT; - events_schedule (); - } -} - static void perform_copper_write (int old_hpos) { int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); - int hp; unsigned int address = cop_state.saved_i1 & 0x1FE; record_copper (cop_state.saved_ip - 4, old_hpos, vpos); if (address < (copcon & 2 ? ((currprefs.chipset_mask & CSMASK_AGA) ? 0 : 0x40u) : 0x80u)) { - cop_state.state = COP_stop; + cop_state.state = COP_stop; copper_enabled_thisline = 0; unset_special (SPCFLAG_COPPER); return; @@ -3185,9 +2833,29 @@ static void perform_copper_write (int ol custom_wput_1 (old_hpos, address, cop_state.saved_i2); } +static int isagnus[]= { + 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 */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 27 0x40 - 0x74 */ + + 0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0, /* 21 */ + 1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0, /* 32 0xa0 - 0xde */ + /* BPLxPTH/BPLxPTL */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */ + /* BPLCON0-3,BPLMOD1-2 */ + 0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0, /* 16 */ + /* SPRxPTH/SPRxPTL */ + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 16 */ + /* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */ + 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, + /* COLORxx */ + 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, + /* RESERVED */ + 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 +}; + static void update_copper (int until_hpos) { - int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); + int vp = vpos & (((cop_state.saved_i2 >> 8) & 0x7F) | 0x80); int c_hpos = cop_state.hpos; if (eventtab[ev_copper].active) @@ -3280,7 +2948,7 @@ static void update_copper (int until_hpo case COP_read1_wr_in2: case COP_read1: - cop_state.i1 = chipmem_wget (cop_state.ip); + cop_state.i1 = chipmem_agnus_wget (cop_state.ip); cop_state.ip += 2; cop_state.state = cop_state.state == COP_read1 ? COP_read2 : COP_read2_wr_in2; break; @@ -3289,7 +2957,7 @@ static void update_copper (int until_hpo abort (); case COP_read2: - cop_state.i2 = chipmem_wget (cop_state.ip); + cop_state.i2 = chipmem_agnus_wget (cop_state.ip); cop_state.ip += 2; if (cop_state.ignore_next) { cop_state.ignore_next = 0; @@ -3306,11 +2974,29 @@ static void update_copper (int until_hpo cop_state.state = COP_skip_in4; else cop_state.state = COP_wait_in4; - } else - cop_state.state = COP_read1_wr_in4; + } else { + unsigned int reg = cop_state.i1 & 0x1FE; + cop_state.state = isagnus[reg >> 1] ? COP_read1_wr_in2 : COP_read1_wr_in4; + } break; case COP_wait1: + /* There's a nasty case here. As stated in the "Theory" comment above, we + test against the incremented copper position. I believe this means that + we have to increment the _vertical_ position at the last cycle in the line, + and set the horizontal position to 0. + Normally, this isn't going to make a difference, since we consider these + last cycles unavailable for the copper, so waking up in the last cycle has + the same effect as waking up at the start of the line. However, there is + one possible problem: If we're at 0xFFE0, any wait for an earlier position + must _not_ complete (since, in effect, the current position will be back + at 0/0). This can be seen in the Superfrog copper list. + Things get monstrously complicated if we try to handle this "properly" by + incrementing vpos and setting c_hpos to 0. Especially the various speedup + hacks really assume that vpos remains constant during one line. Hence, + this hack: defer the entire decision until the next line if necessary. */ + if (c_hpos >= (maxhpos & ~1)) + break; cop_state.state = COP_wait; cop_state.vcmp = (cop_state.saved_i1 & (cop_state.saved_i2 | 0x8000)) >> 8; @@ -3339,16 +3025,6 @@ static void update_copper (int until_hpo hp = c_hpos & (cop_state.saved_i2 & 0xFE); if (vp == cop_state.vcmp && hp < cop_state.hcmp) { /* Position not reached yet. */ - if (currprefs.fast_copper && (cop_state.saved_i2 & 0xFE) == 0xFE) { - int wait_finish = cop_state.hcmp - 2; - /* This will leave c_hpos untouched if it's equal to wait_finish. */ - if (wait_finish < c_hpos) - abort (); - else if (wait_finish <= until_hpos) { - c_hpos = wait_finish; - } else - c_hpos = until_hpos; - } break; } @@ -3374,12 +3050,6 @@ static void update_copper (int until_hpo out: cop_state.hpos = c_hpos; - - /* The test against maxhpos also prevents us from calling predict_copper - when we are being called from hsync_handler, which would not only be - stupid, but actively harmful. */ - if (currprefs.fast_copper && (regs.spcflags & SPCFLAG_COPPER) && c_hpos + 8 < maxhpos) - predict_copper (); } static void compute_spcflag_copper (void) @@ -3397,9 +3067,6 @@ static void compute_spcflag_copper (void } copper_enabled_thisline = 1; - if (currprefs.fast_copper) - predict_copper (); - if (! eventtab[ev_copper].active) set_special (SPCFLAG_COPPER); } @@ -3420,9 +3087,10 @@ void blitter_done_notify (void) if (cop_state.state != COP_bltwait) return; - copper_enabled_thisline = 1; - set_special (SPCFLAG_COPPER); + cop_state.hpos = current_hpos () & ~1; + cop_state.vpos = vpos; cop_state.state = COP_wait; + compute_spcflag_copper (); } void do_copper (void) @@ -3433,22 +3101,11 @@ void do_copper (void) /* ADDR is the address that is going to be read/written; this access is the reason why we want to update the copper. This function is also - used from hsync_handler to finish up the line; for this case, we check - hpos against maxhpos. */ -STATIC_INLINE void sync_copper_with_cpu (int hpos, int do_schedule, unsigned int addr) + used from hsync_handler to finish up the line. */ +STATIC_INLINE void sync_copper_with_cpu (int hpos, int do_schedule) { /* Need to let the copper advance to the current position. */ if (eventtab[ev_copper].active) { - if (hpos != maxhpos) { - /* There might be reasons why we don't actually need to bother - updating the copper. */ - if (hpos < cop_state.first_sync) - return; - - if ((cop_state.regtypes_modified & regtypes[addr & 0x1FE]) == 0) - return; - } - eventtab[ev_copper].active = 0; if (do_schedule) events_schedule (); @@ -3458,11 +3115,87 @@ STATIC_INLINE void sync_copper_with_cpu update_copper (hpos); } -static void do_sprites (int currvp, int hpos) +STATIC_INLINE uae_u16 sprite_fetch (struct sprite *s, int dma) +{ + uae_u16 data = last_custom_value; + if (dma) + data = last_custom_value = chipmem_agnus_wget (s->pt); + s->pt += 2; + return data; +} + +STATIC_INLINE void do_sprites_1 (int num, int cycle, int hpos) +{ + struct sprite *s = &spr[num]; + int dma; + + if (cycle == 0) { + if (vpos == s->vstart) + s->state = SPR_waiting_stop; + if (vpos == s->vstop) + s->state = SPR_restart; + } + if (!dmaen (DMA_SPRITE)) + return; + dma = hpos < ddfstrt || diwstate != DIW_waiting_stop || !dmaen (DMA_BITPLANE); + if (s->state == SPR_restart || vpos == sprite_vblank_endline) { + uae_u16 data = sprite_fetch (s, dma); + s->pt += (sprite_width >> 3) - 2; +#ifdef SPRITE_DEBUG + write_log ("dma:"); +#endif + if (cycle == 0) { + SPRxPOS_1 (dma ? data : sprpos[num], num, hpos); + } else { + s->state = SPR_waiting_start; + SPRxCTL_1 (dma ? data : sprctl[num], num, hpos); + } + } else if (s->state == SPR_waiting_stop) { + uae_u16 data = sprite_fetch (s, dma); + + if (cycle == 0) + SPRxDATA_1 (dma ? data : sprdata[num][0], num); + else + SPRxDATB_1 (dma ? data : sprdatb[num][0], num); + switch (sprite_width) + { + case 64: + { + uae_u32 data32 = sprite_fetch (s, dma); + uae_u32 data641 = sprite_fetch (s, dma); + uae_u32 data642 = sprite_fetch (s, dma); + if (dma) { + if (cycle == 0) { + sprdata[num][3] = data642; + sprdata[num][2] = data641; + sprdata[num][1] = data32; + } else { + sprdatb[num][3] = data642; + sprdatb[num][2] = data641; + sprdatb[num][1] = data32; + } + } + } + break; + case 32: + { + uae_u32 data32 = sprite_fetch (s, dma); + if (dma) { + if (cycle == 0) + sprdata[num][1] = data32; + else + sprdatb[num][1] = data32; + } + } + break; + } + } +} + +static void do_sprites (int hpos) { - int i; int maxspr, minspr; - int sw = sprite_width >> 3; + int i; /* I don't know whether this is right. Some programs write the sprite pointers * directly at the start of the copper list. With the test against currvp, the @@ -3481,72 +3214,33 @@ static void do_sprites (int currvp, int * demo). */ /* Maximum for Sanity Turmoil: 27. Minimum for Sanity Arte: 22. */ - if (currvp < sprite_vblank_endline) + if (vpos < sprite_vblank_endline) return; - /* The graph in the HRM, p. 195 seems to indicate that sprite 0 is - * fetched at cycle 0x14 and thus can't be disabled by bitplane DMA. */ - maxspr = hpos / 4 - 0x14 / 4; - minspr = last_sprite_hpos / 4 - 0x14 / 4; + maxspr = hpos; + minspr = last_sprite_hpos; - if (minspr > MAX_SPRITES || maxspr < 0) + if (minspr >= SPR0_HPOS + MAX_SPRITES * 4 || maxspr < SPR0_HPOS) return; - if (maxspr > MAX_SPRITES) - maxspr = MAX_SPRITES; - if (minspr < 0) - minspr = 0; + if (maxspr > SPR0_HPOS + MAX_SPRITES * 4) + maxspr = SPR0_HPOS + MAX_SPRITES * 4; + if (minspr < SPR0_HPOS) + minspr = SPR0_HPOS; for (i = minspr; i < maxspr; i++) { - int fetch = 0; - - if (spr[i].on == 0) - continue; - - if (spr[i].state == SPR_restart) { - fetch = 2; - spr[i].on = 1; - } else if ((spr[i].state == SPR_waiting_start && spr[i].vstart == vpos) || spr[i].state == SPR_waiting_stop) { - fetch = 1; - spr[i].state = SPR_waiting_stop; - } - if ((spr[i].state == SPR_waiting_stop || spr[i].state == SPR_waiting_start) && spr[i].vstop == vpos) { - fetch = 2; - spr[i].state = SPR_waiting_start; - } - - if (fetch && dmaen (DMA_SPRITE)) { - uae_u16 data1 = chipmem_wget (spr[i].pt); - uae_u16 data2 = chipmem_wget (spr[i].pt + sw); - - if (fetch == 1) { - /* Hack for X mouse auto-calibration */ - if (i == 0 && !sprvbfl && ((sprpos[0] & 0xff) << 2) > 2 * DISPLAY_LEFT_SHIFT) { - spr0ctl = sprctl[0]; - spr0pos = sprpos[0]; - sprvbfl = 2; - } - SPRxDATB_1 (data2, i); - SPRxDATA_1 (data1, i); - switch (sw) - { - case 64 >> 3: - sprdata[i][3] = chipmem_wget (spr[i].pt + 6); - sprdatb[i][3] = chipmem_wget (spr[i].pt + 6 + sw); - sprdata[i][2] = chipmem_wget (spr[i].pt + 4); - sprdatb[i][2] = chipmem_wget (spr[i].pt + 4 + sw); - /* fall through */ - case 32 >> 3: - sprdata[i][1] = chipmem_wget (spr[i].pt + 2); - sprdatb[i][1] = chipmem_wget (spr[i].pt + 2 + sw); - break; - } - } else { - SPRxPOS_1 (data1, i); - SPRxCTL_1 (data2, i); - } - spr[i].pt += sw * 2; + int cycle = -1; + switch ((i - SPR0_HPOS) & 3) + { + case 0: + cycle = 0; + break; + case 2: + cycle = 1; + break; } + if (cycle >= 0) + do_sprites_1 ((i - SPR0_HPOS) / 4, cycle, i); } last_sprite_hpos = hpos; } @@ -3555,12 +3249,8 @@ static void init_sprites (void) { int i; - for (i = 0; i < MAX_SPRITES; i++) { - /* ???? */ - spr[i].state = SPR_stop; - spr[i].on = 0; - } - + for (i = 0; i < MAX_SPRITES; i++) + spr[i].state = SPR_restart; memset (sprpos, 0, sizeof sprpos); memset (sprctl, 0, sizeof sprctl); } @@ -3603,8 +3293,8 @@ static void init_hardware_frame (void) nextline_how = nln_normal; diwstate = DIW_waiting_start; hdiwstate = DIW_waiting_start; + ddfstate = DIW_waiting_start; } - void init_hardware_for_drawing_frame (void) { adjust_array_sizes (); @@ -3645,31 +3335,16 @@ static void do_savestate(void); static void vsync_handler (void) { -#if 0 - static int old_clxdat; - if (clxdat != old_clxdat) { - printf ("CLXDAT %04x\n", clxdat); - old_clxdat = clxdat; - } -#endif + int i; + for (i = 0; i < MAX_SPRITES; i++) + spr[i].state = SPR_waiting_start; + n_frames++; - if (currprefs.m68k_speed == -1) { - frame_time_t curr_time = read_processor_time (); - vsyncmintime += vsynctime; - /* @@@ Mathias? How do you think we should do this? */ - /* If we are too far behind, or we just did a reset, adjust the - * needed time. */ - if ((long int)(curr_time - vsyncmintime) > 0 || rpt_did_reset) - vsyncmintime = curr_time + vsynctime; - rpt_did_reset = 0; - } + time_vsync (); handle_events (); - getjoystate (0, &joy0dir, &joy0button); - getjoystate (1, &joy1dir, &joy1button); - INTREQ (0x8020); if (bplcon0 & 4) lof ^= 0x8000; @@ -3723,19 +3398,6 @@ static void vsync_handler (void) if (!bogusframe) { lastframetime = newtime - msecs; -#if 0 /* This doesn't appear to work too well yet... later. */ - if (n_consecutive_skipped > currprefs.sound_pri_cutoff - || lastframetime < currprefs.sound_pri_time) - { - n_consecutive_skipped = 0; - clear_inhibit_frame (IHF_SOUNDADJUST); - } else { - n_consecutive_skipped++; - set_inhibit_frame (IHF_SOUNDADJUST); - total_skipped++; - } -#endif - frametime += lastframetime; timeframes++; @@ -3746,18 +3408,15 @@ static void vsync_handler (void) bogusframe = 0; } #endif - if (ievent_alive > 0) - ievent_alive--; if (timehack_alive > 0) timehack_alive--; + inputdevice_vsync (); CIA_vsync_handler (); } static void hsync_handler (void) { - /* Using 0x8A makes sure that we don't accidentally trip over the - modified_regtypes check. */ - sync_copper_with_cpu (maxhpos, 0, 0x8A); + sync_copper_with_cpu (maxhpos, 0); finish_decisions (); if (thisline_decision.plfleft != -1) { @@ -3772,30 +3431,8 @@ static void hsync_handler (void) eventtab[ev_hsync].oldcycles = get_cycles (); CIA_hsync_handler (); - if (currprefs.produce_sound > 0) { - int nr; - - update_audio (); - - /* Sound data is fetched at the beginning of each line */ - for (nr = 0; nr < 4; nr++) { - struct audio_channel_data *cdp = audio_channel + nr; - - if (cdp->data_written == 2) { - cdp->data_written = 0; - cdp->nextdat = chipmem_wget (cdp->pt); - cdp->pt += 2; - if (cdp->state == 2 || cdp->state == 3) { - if (cdp->wlen == 1) { - cdp->pt = cdp->lc; - cdp->wlen = cdp->len; - cdp->intreq2 = 1; - } else - cdp->wlen = (cdp->wlen - 1) & 0xFFFF; - } - } - } - } + if (currprefs.produce_sound > 0) + audio_hsync (1); hardware_line_completed (next_lineno); @@ -3804,24 +3441,27 @@ static void hsync_handler (void) with vpos going into the thousands (and all the nasty consequences this has). */ - if (++vpos >= (maxvpos + (lof != 0))) { + if (++vpos >= (maxvpos + (lof == 0 ? 0 : 1))) { vpos = 0; vsync_handler (); } DISK_update (); - is_lastline = vpos + 1 == maxvpos + (lof != 0) && currprefs.m68k_speed == -1 && ! rpt_did_reset; + is_lastline = (!sync_with_sound + && vpos + 1 == maxvpos + (lof == 0 ? 0 : 1) + && currprefs.m68k_speed == -1 + && vsyncmintime_valid); - if ((bplcon0 & 4) && currprefs.gfx_linedbl) + if ((bplcon0 & 4) && curr_gfx && curr_gfx->linedbl) notice_interlace_seen (); - if (framecnt == 0) { + if (!nodraw ()) { int lineno = vpos; nextline_how = nln_normal; - if (currprefs.gfx_linedbl) { + if (curr_gfx->linedbl) { lineno *= 2; - nextline_how = currprefs.gfx_linedbl == 1 ? nln_doubled : nln_nblack; + nextline_how = curr_gfx->linedbl == 1 ? nln_doubled : nln_nblack; if (bplcon0 & 4) { if (!lof) { lineno++; @@ -3841,57 +3481,8 @@ static void hsync_handler (void) /* See if there's a chance of a copper wait ending this line. */ cop_state.hpos = 0; compute_spcflag_copper (); -} - -static void init_regtypes (void) -{ - int i; - for (i = 0; i < 512; i += 2) { - regtypes[i] = REGTYPE_ALL; - if ((i >= 0x20 && i < 0x28) || i == 0x08 || i == 0x7E) - regtypes[i] = REGTYPE_DISK; - else if (i >= 0x68 && i < 0x70) - regtypes[i] = REGTYPE_NONE; - else if (i >= 0x40 && i < 0x78) - regtypes[i] = REGTYPE_BLITTER; - else if (i >= 0xA0 && i < 0xE0 && (i & 0xF) < 0xE) - regtypes[i] = REGTYPE_AUDIO; - else if (i >= 0xA0 && i < 0xE0) - regtypes[i] = REGTYPE_NONE; - else if (i >= 0xE0 && i < 0x100) - regtypes[i] = REGTYPE_PLANE; - else if (i >= 0x120 && i < 0x180) - regtypes[i] = REGTYPE_SPRITE; - else if (i >= 0x180 && i < 0x1C0) - regtypes[i] = REGTYPE_COLOR; - else switch (i) { - case 0x02: - /* DMACONR - setting this to REGTYPE_BLITTER will cause it to - conflict with DMACON (since that is REGTYPE_ALL), and the - blitter registers (for the BBUSY bit), but nothing else, - which is (I think) what we want. */ - regtypes[i] = REGTYPE_BLITTER; - break; - case 0x04: case 0x06: case 0x2A: case 0x2C: - regtypes[i] = REGTYPE_POS; - break; - case 0x0A: case 0x0C: - case 0x12: case 0x14: case 0x16: - case 0x36: - regtypes[i] = REGTYPE_JOYPORT; - break; - case 0x104: - case 0x102: - regtypes[i] = REGTYPE_PLANE; - break; - case 0x88: case 0x8A: - case 0x8E: case 0x90: case 0x92: case 0x94: - case 0x96: - case 0x100: - regtypes[i] |= REGTYPE_FORCE; - break; - } - } + inputdevice_hsync (); + gayle_hsync (); } void init_eventtab (void) @@ -3906,7 +3497,7 @@ void init_eventtab (void) eventtab[ev_cia].handler = CIA_handler; eventtab[ev_hsync].handler = hsync_handler; - eventtab[ev_hsync].evtime = maxhpos * CYCLE_UNIT + get_cycles (); + eventtab[ev_hsync].evtime = HSYNCTIME + get_cycles (); eventtab[ev_hsync].active = 1; eventtab[ev_copper].handler = copper_handler; @@ -3928,15 +3519,18 @@ void customreset (void) struct timeval tv; #endif + /* If we're in a loop of quick successive resets, we should give + the GUI some time to respond to a "Quit" event. */ + handle_events (); + if (! savestate_state) { - currprefs.chipset_mask = changed_prefs.chipset_mask; if ((currprefs.chipset_mask & CSMASK_AGA) == 0) { for (i = 0; i < 32; i++) { current_colors.color_regs_ecs[i] = 0; current_colors.acolors[i] = xcolors[0]; } } else { - for (i = 0; i < 256; i++) { + for (i = 0; i < 256; i++) { current_colors.color_regs_aga[i] = 0; current_colors.acolors[i] = CONVERT_RGB (zero); } @@ -3960,29 +3554,21 @@ void customreset (void) FMODE (0); CLXCON (0); + lof = 0; } n_frames = 0; + gayle_reset (1); expamem_reset (); - + a1000_reset (); DISK_reset (); CIA_reset (); unset_special (~(SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)); vpos = 0; - lof = 0; - if (needmousehack ()) { -#if 0 - mousehack_setfollow(); -#else - mousehack_setdontcare(); -#endif - } else { - mousestate = normal_mouse; - } - ievent_alive = 0; + inputdevice_reset (); timehack_alive = 0; curr_sprite_entries = 0; @@ -4000,15 +3586,21 @@ void customreset (void) hdiwstate = DIW_waiting_start; currcycle = 0; + currprefs.ntscmode = changed_prefs.ntscmode; new_beamcon0 = currprefs.ntscmode ? 0x00 : 0x20; init_hz (); audio_reset (); + if (savestate_state != STATE_RESTORE) { + /* must be called after audio_reset */ + adkcon = 0; + update_adkmasks (); + } init_sprites (); init_hardware_frame (); - reset_drawing (); + init_drawing_at_reset (); reset_decisions (); @@ -4018,8 +3610,6 @@ void customreset (void) bogusframe = 1; #endif - init_regtypes (); - sprite_buffer_res = currprefs.chipset_mask & CSMASK_AGA ? RES_HIRES : RES_LORES; if (savestate_state == STATE_RESTORE) { uae_u16 v; @@ -4031,9 +3621,9 @@ void customreset (void) #if 0 DMACON (0, 0); #endif - COPJMP1 (0); if (diwhigh) diwhigh_written = 1; + COPJMP (1); v = bplcon0; BPLCON0 (0, 0); BPLCON0 (0, v); @@ -4049,7 +3639,7 @@ void customreset (void) } } else { for(i = 0 ; i < 256 ; i++) { - vv = current_colors.color_regs_aga[i]; + vv = current_colors.color_regs_aga[i]; current_colors.color_regs_aga[i] = -1; record_color_change (0, i, vv); remembered_color_entry = -1; @@ -4064,45 +3654,35 @@ void customreset (void) dumpcustom (); for (i = 0; i < 8; i++) nr_armed += spr[i].armed != 0; + if (! currprefs.produce_sound) { + eventtab[ev_audio].active = 0; + events_schedule (); + } } expand_sprres (); } void dumpcustom (void) { - write_log ("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(), - (unsigned int)intena, (unsigned int)intreq, (unsigned int)vpos, (unsigned int)current_hpos()); - write_log ("COP1LC: %08lx, COP2LC: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc); - write_log ("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n", - (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop); + console_out ("DMACON: %x INTENA: %x INTREQ: %x VPOS: %x HPOS: %x\n", DMACONR(), + (unsigned int)intena, (unsigned int)intreq, (unsigned int)vpos, (unsigned int)current_hpos()); + console_out ("COP1LC: %08lx, COP2LC: %08lx COPPTR: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc, cop_state.ip); + console_out ("DIWSTRT: %04x DIWSTOP: %04x DDFSTRT: %04x DDFSTOP: %04x\n", + (unsigned int)diwstrt, (unsigned int)diwstop, (unsigned int)ddfstrt, (unsigned int)ddfstop); + console_out ("BPLCON 0: %04x 1: %04x 2: %04x 3: %04x 4: %04x\n", bplcon0, bplcon1, bplcon2, bplcon3, bplcon4); if (timeframes) { - write_log ("Average frame time: %d ms [frames: %d time: %d]\n", - frametime / timeframes, timeframes, frametime); + console_out ("Average frame time: %f ms [frames: %d time: %d]\n", + (double)frametime / timeframes, timeframes, frametime); if (total_skipped) - write_log ("Skipped frames: %d\n", total_skipped); - } - /*for (i=0; i<256; i++) if (blitcount[i]) write_log ("minterm %x = %d\n",i,blitcount[i]); blitter debug */ -} - -int intlev (void) -{ - uae_u16 imask = intreq & intena; - if (imask && (intena & 0x4000)){ - if (imask & 0x2000) return 6; - if (imask & 0x1800) return 5; - if (imask & 0x0780) return 4; - if (imask & 0x0070) return 3; - if (imask & 0x0008) return 2; - if (imask & 0x0007) return 1; + console_out ("Skipped frames: %d\n", total_skipped); } - return -1; + /*for (i=0; i<256; i++) if (blitcount[i]) console_out ("minterm %x = %d\n",i,blitcount[i]); blitter debug */ } static void gen_custom_tables (void) { int i; for (i = 0; i < 256; i++) { - unsigned int j; sprtaba[i] = ((((i >> 7) & 1) << 0) | (((i >> 6) & 1) << 2) | (((i >> 5) & 1) << 4) @@ -4159,11 +3739,6 @@ void custom_init (void) drawing_init (); - mousestate = unknown_mouse; - - if (needmousehack ()) - mousehack_setfollow (); - create_cycle_diagram_table (); } @@ -4179,31 +3754,32 @@ static void custom_bput (uaecptr, uae_u3 addrbank custom_bank = { custom_lget, custom_wget, custom_bget, custom_lput, custom_wput, custom_bput, - default_xlate, default_check, NULL + default_xlate, default_check, NULL, "Custom chipset" }; STATIC_INLINE uae_u32 REGPARAM2 custom_wget_1 (uaecptr addr) { - special_mem |= S_READ; + uae_u16 v; switch (addr & 0x1FE) { - case 0x002: return DMACONR (); - case 0x004: return VPOSR (); - case 0x006: return VHPOSR (); - - case 0x008: return DSKDATR (current_hpos ()); - - case 0x00A: return JOY0DAT (); - case 0x00C: return JOY1DAT (); - case 0x00E: return CLXDAT (); - case 0x010: return ADKCONR (); - - case 0x012: return POT0DAT (); - case 0x016: return POTGOR (); - case 0x018: return SERDATR (); - case 0x01A: return DSKBYTR (current_hpos ()); - case 0x01C: return INTENAR (); - case 0x01E: return INTREQR (); - case 0x07C: return DENISEID (); + case 0x002: v = DMACONR (); break; + case 0x004: v = VPOSR (); break; + case 0x006: v = VHPOSR (); break; + + case 0x008: v = DSKDATR (current_hpos ()); break; + + case 0x00A: v = JOY0DAT (); break; + case 0x00C: v = JOY1DAT (); break; + case 0x00E: v = CLXDAT (); break; + case 0x010: v = ADKCONR (); break; + + case 0x012: v = POT0DAT (); break; + case 0x014: v = POT1DAT (); break; + case 0x016: v = POTGOR (); break; + case 0x018: v = SERDATR (); break; + case 0x01A: v = DSKBYTR (current_hpos ()); break; + case 0x01C: v = INTENAR (); break; + case 0x01E: v = INTREQR (); break; + case 0x07C: v = DENISEID (); break; case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A: case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196: @@ -4211,206 +3787,222 @@ STATIC_INLINE uae_u32 REGPARAM2 custom_w case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE: case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: case 0x1BC: case 0x1BE: - return COLOR_READ ((addr & 0x3E) / 2); + v = COLOR_READ ((addr & 0x3E) / 2); break; default: - custom_wput (addr, 0); - return 0xffff; + v = last_custom_value; + custom_wput (addr, v); + last_custom_value = 0xffff; + return v; } + last_custom_value = v; + return v; } uae_u32 REGPARAM2 custom_wget (uaecptr addr) { - sync_copper_with_cpu (current_hpos (), 1, addr); + sync_copper_with_cpu (current_hpos (), 1); return custom_wget_1 (addr); } uae_u32 REGPARAM2 custom_bget (uaecptr addr) { - special_mem |= S_READ; return custom_wget (addr & 0xfffe) >> (addr & 1 ? 0 : 8); } uae_u32 REGPARAM2 custom_lget (uaecptr addr) { - special_mem |= S_READ; return ((uae_u32)custom_wget (addr & 0xfffe) << 16) | custom_wget ((addr + 2) & 0xfffe); } void REGPARAM2 custom_wput_1 (int hpos, uaecptr addr, uae_u32 value) { addr &= 0x1FE; + last_custom_value = value; switch (addr) { - case 0x020: DSKPTH (value); break; - case 0x022: DSKPTL (value); break; - case 0x024: DSKLEN (value, hpos); break; - case 0x026: DSKDAT (value); break; - - case 0x02A: VPOSW (value); break; - case 0x02E: COPCON (value); break; - case 0x030: SERDAT (value); break; - case 0x032: SERPER (value); break; - case 0x034: POTGO (value); break; - case 0x040: BLTCON0 (value); break; - case 0x042: BLTCON1 (value); break; - - case 0x044: BLTAFWM (value); break; - case 0x046: BLTALWM (value); break; - - case 0x050: BLTAPTH (value); break; - case 0x052: BLTAPTL (value); break; - case 0x04C: BLTBPTH (value); break; - case 0x04E: BLTBPTL (value); break; - case 0x048: BLTCPTH (value); break; - case 0x04A: BLTCPTL (value); break; - case 0x054: BLTDPTH (value); break; - case 0x056: BLTDPTL (value); break; - - case 0x058: BLTSIZE (value); break; - - case 0x064: BLTAMOD (value); break; - case 0x062: BLTBMOD (value); break; - case 0x060: BLTCMOD (value); break; - case 0x066: BLTDMOD (value); break; - - case 0x070: BLTCDAT (value); break; - case 0x072: BLTBDAT (value); break; - case 0x074: BLTADAT (value); break; - - case 0x07E: DSKSYNC (value); break; - - case 0x080: COP1LCH (value); break; - case 0x082: COP1LCL (value); break; - case 0x084: COP2LCH (value); break; - case 0x086: COP2LCL (value); break; - - case 0x088: COPJMP1 (value); break; - case 0x08A: COPJMP2 (value); break; - - case 0x08E: DIWSTRT (hpos, value); break; - case 0x090: DIWSTOP (hpos, value); break; - case 0x092: DDFSTRT (hpos, value); break; - case 0x094: DDFSTOP (hpos, value); break; - - case 0x096: DMACON (hpos, value); break; - case 0x098: CLXCON (value); break; - case 0x09A: INTENA (value); break; - case 0x09C: INTREQ (value); break; - case 0x09E: ADKCON (value); break; - - case 0x0A0: AUDxLCH (0, value); break; - case 0x0A2: AUDxLCL (0, value); break; - case 0x0A4: AUDxLEN (0, value); break; - case 0x0A6: AUDxPER (0, value); break; - case 0x0A8: AUDxVOL (0, value); break; - case 0x0AA: AUDxDAT (0, value); break; - - case 0x0B0: AUDxLCH (1, value); break; - case 0x0B2: AUDxLCL (1, value); break; - case 0x0B4: AUDxLEN (1, value); break; - case 0x0B6: AUDxPER (1, value); break; - case 0x0B8: AUDxVOL (1, value); break; - case 0x0BA: AUDxDAT (1, value); break; - - case 0x0C0: AUDxLCH (2, value); break; - case 0x0C2: AUDxLCL (2, value); break; - case 0x0C4: AUDxLEN (2, value); break; - case 0x0C6: AUDxPER (2, value); break; - case 0x0C8: AUDxVOL (2, value); break; - case 0x0CA: AUDxDAT (2, value); break; - - case 0x0D0: AUDxLCH (3, value); break; - case 0x0D2: AUDxLCL (3, value); break; - case 0x0D4: AUDxLEN (3, value); break; - case 0x0D6: AUDxPER (3, value); break; - case 0x0D8: AUDxVOL (3, value); break; - case 0x0DA: AUDxDAT (3, value); break; - - case 0x0E0: BPLPTH (hpos, value, 0); break; - case 0x0E2: BPLPTL (hpos, value, 0); break; - case 0x0E4: BPLPTH (hpos, value, 1); break; - case 0x0E6: BPLPTL (hpos, value, 1); break; - case 0x0E8: BPLPTH (hpos, value, 2); break; - case 0x0EA: BPLPTL (hpos, value, 2); break; - case 0x0EC: BPLPTH (hpos, value, 3); break; - case 0x0EE: BPLPTL (hpos, value, 3); break; - case 0x0F0: BPLPTH (hpos, value, 4); break; - case 0x0F2: BPLPTL (hpos, value, 4); break; - case 0x0F4: BPLPTH (hpos, value, 5); break; - case 0x0F6: BPLPTL (hpos, value, 5); break; - case 0x0F8: BPLPTH (hpos, value, 6); break; - case 0x0FA: BPLPTL (hpos, value, 6); break; - case 0x0FC: BPLPTH (hpos, value, 7); break; - case 0x0FE: BPLPTL (hpos, value, 7); break; - - case 0x100: BPLCON0 (hpos, value); break; - case 0x102: BPLCON1 (hpos, value); break; - case 0x104: BPLCON2 (hpos, value); break; - case 0x106: BPLCON3 (hpos, value); break; - - case 0x108: BPL1MOD (hpos, value); break; - case 0x10A: BPL2MOD (hpos, value); break; - case 0x10E: CLXCON2 (value); break; - - case 0x110: BPL1DAT (hpos, value); break; - case 0x112: BPL2DAT (value); break; - case 0x114: BPL3DAT (value); break; - case 0x116: BPL4DAT (value); break; - case 0x118: BPL5DAT (value); break; - case 0x11A: BPL6DAT (value); break; - case 0x11C: BPL7DAT (value); break; - case 0x11E: BPL8DAT (value); break; - - case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A: - case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196: - case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2: - case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE: - case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: - case 0x1BC: case 0x1BE: + case 0x020: DSKPTH (value); break; + case 0x022: DSKPTL (value); break; + case 0x024: DSKLEN (value, hpos); break; + case 0x026: DSKDAT (value); break; + + case 0x02A: VPOSW (value); break; + case 0x02E: COPCON (value); break; + case 0x030: SERDAT (value); break; + case 0x032: SERPER (value); break; + case 0x034: POTGO (value); break; + case 0x040: BLTCON0 (value); break; + case 0x042: BLTCON1 (value); break; + + case 0x044: BLTAFWM (value); break; + case 0x046: BLTALWM (value); break; + + case 0x050: BLTAPTH (value); break; + case 0x052: BLTAPTL (value); break; + case 0x04C: BLTBPTH (value); break; + case 0x04E: BLTBPTL (value); break; + case 0x048: BLTCPTH (value); break; + case 0x04A: BLTCPTL (value); break; + case 0x054: BLTDPTH (value); break; + case 0x056: BLTDPTL (value); break; + + case 0x058: BLTSIZE (value); break; + + case 0x064: BLTAMOD (value); break; + case 0x062: BLTBMOD (value); break; + case 0x060: BLTCMOD (value); break; + case 0x066: BLTDMOD (value); break; + + case 0x070: BLTCDAT (value); break; + case 0x072: BLTBDAT (value); break; + case 0x074: BLTADAT (value); break; + + case 0x07E: DSKSYNC (value); break; + + case 0x080: COP1LCH (value); break; + case 0x082: COP1LCL (value); break; + case 0x084: COP2LCH (value); break; + case 0x086: COP2LCL (value); break; + + case 0x088: COPJMP (1); break; + case 0x08A: COPJMP (2); break; + + case 0x08E: DIWSTRT (hpos, value); break; + case 0x090: DIWSTOP (hpos, value); break; + case 0x092: DDFSTRT (hpos, value); break; + case 0x094: DDFSTOP (hpos, value); break; + + case 0x096: DMACON (hpos, value); break; + case 0x098: CLXCON (value); break; + case 0x09A: INTENA (value); break; + case 0x09C: INTREQ (value); break; + case 0x09E: ADKCON (value); break; + + case 0x0A0: AUDxLCH (0, value); break; + case 0x0A2: AUDxLCL (0, value); break; + case 0x0A4: AUDxLEN (0, value); break; + case 0x0A6: AUDxPER (0, value); break; + case 0x0A8: AUDxVOL (0, value); break; + case 0x0AA: AUDxDAT (0, value); break; + + case 0x0B0: AUDxLCH (1, value); break; + case 0x0B2: AUDxLCL (1, value); break; + case 0x0B4: AUDxLEN (1, value); break; + case 0x0B6: AUDxPER (1, value); break; + case 0x0B8: AUDxVOL (1, value); break; + case 0x0BA: AUDxDAT (1, value); break; + + case 0x0C0: AUDxLCH (2, value); break; + case 0x0C2: AUDxLCL (2, value); break; + case 0x0C4: AUDxLEN (2, value); break; + case 0x0C6: AUDxPER (2, value); break; + case 0x0C8: AUDxVOL (2, value); break; + case 0x0CA: AUDxDAT (2, value); break; + + case 0x0D0: AUDxLCH (3, value); break; + case 0x0D2: AUDxLCL (3, value); break; + case 0x0D4: AUDxLEN (3, value); break; + case 0x0D6: AUDxPER (3, value); break; + case 0x0D8: AUDxVOL (3, value); break; + case 0x0DA: AUDxDAT (3, value); break; + + case 0x0E0: BPLxPTH (hpos, value, 0); break; + case 0x0E2: BPLxPTL (hpos, value, 0); break; + case 0x0E4: BPLxPTH (hpos, value, 1); break; + case 0x0E6: BPLxPTL (hpos, value, 1); break; + case 0x0E8: BPLxPTH (hpos, value, 2); break; + case 0x0EA: BPLxPTL (hpos, value, 2); break; + case 0x0EC: BPLxPTH (hpos, value, 3); break; + case 0x0EE: BPLxPTL (hpos, value, 3); break; + case 0x0F0: BPLxPTH (hpos, value, 4); break; + case 0x0F2: BPLxPTL (hpos, value, 4); break; + case 0x0F4: BPLxPTH (hpos, value, 5); break; + case 0x0F6: BPLxPTL (hpos, value, 5); break; + case 0x0F8: BPLxPTH (hpos, value, 6); break; + case 0x0FA: BPLxPTL (hpos, value, 6); break; + case 0x0FC: BPLxPTH (hpos, value, 7); break; + case 0x0FE: BPLxPTL (hpos, value, 7); break; + + case 0x100: BPLCON0 (hpos, value); break; + case 0x102: BPLCON1 (hpos, value); break; + case 0x104: BPLCON2 (hpos, value); break; + case 0x106: BPLCON3 (hpos, value); break; + + case 0x108: BPL1MOD (hpos, value); break; + case 0x10A: BPL2MOD (hpos, value); break; + case 0x10E: CLXCON2 (value); break; + + case 0x110: BPL1DAT (hpos, value); break; + case 0x112: BPL2DAT (value); break; + case 0x114: BPL3DAT (value); break; + case 0x116: BPL4DAT (value); break; + case 0x118: BPL5DAT (value); break; + case 0x11A: BPL6DAT (value); break; + case 0x11C: BPL7DAT (value); break; + case 0x11E: BPL8DAT (value); break; + + case 0x180: case 0x182: case 0x184: case 0x186: case 0x188: case 0x18A: + case 0x18C: case 0x18E: case 0x190: case 0x192: case 0x194: case 0x196: + case 0x198: case 0x19A: case 0x19C: case 0x19E: case 0x1A0: case 0x1A2: + case 0x1A4: case 0x1A6: case 0x1A8: case 0x1AA: case 0x1AC: case 0x1AE: + case 0x1B0: case 0x1B2: case 0x1B4: case 0x1B6: case 0x1B8: case 0x1BA: + case 0x1BC: case 0x1BE: COLOR_WRITE (hpos, value & 0xFFF, (addr & 0x3E) / 2); break; - case 0x120: case 0x124: case 0x128: case 0x12C: - case 0x130: case 0x134: case 0x138: case 0x13C: + case 0x120: case 0x124: case 0x128: case 0x12C: + case 0x130: case 0x134: case 0x138: case 0x13C: SPRxPTH (hpos, value, (addr - 0x120) / 4); break; - case 0x122: case 0x126: case 0x12A: case 0x12E: - case 0x132: case 0x136: case 0x13A: case 0x13E: + case 0x122: case 0x126: case 0x12A: case 0x12E: + case 0x132: case 0x136: case 0x13A: case 0x13E: SPRxPTL (hpos, value, (addr - 0x122) / 4); break; - case 0x140: case 0x148: case 0x150: case 0x158: - case 0x160: case 0x168: case 0x170: case 0x178: + case 0x140: case 0x148: case 0x150: case 0x158: + case 0x160: case 0x168: case 0x170: case 0x178: SPRxPOS (hpos, value, (addr - 0x140) / 8); break; - case 0x142: case 0x14A: case 0x152: case 0x15A: - case 0x162: case 0x16A: case 0x172: case 0x17A: + case 0x142: case 0x14A: case 0x152: case 0x15A: + case 0x162: case 0x16A: case 0x172: case 0x17A: SPRxCTL (hpos, value, (addr - 0x142) / 8); break; - case 0x144: case 0x14C: case 0x154: case 0x15C: - case 0x164: case 0x16C: case 0x174: case 0x17C: + case 0x144: case 0x14C: case 0x154: case 0x15C: + case 0x164: case 0x16C: case 0x174: case 0x17C: SPRxDATA (hpos, value, (addr - 0x144) / 8); break; - case 0x146: case 0x14E: case 0x156: case 0x15E: - case 0x166: case 0x16E: case 0x176: case 0x17E: + case 0x146: case 0x14E: case 0x156: case 0x15E: + case 0x166: case 0x16E: case 0x176: case 0x17E: SPRxDATB (hpos, value, (addr - 0x146) / 8); break; - case 0x36: JOYTEST (value); break; - case 0x5A: BLTCON0L (value); break; - case 0x5C: BLTSIZV (value); break; - case 0x5E: BLTSIZH (value); break; - case 0x1E4: DIWHIGH (hpos, value); break; - case 0x10C: BPLCON4 (hpos, value); break; - case 0x1FC: FMODE (value); break; + case 0x36: JOYTEST (value); break; + case 0x5A: BLTCON0L (value); break; + case 0x5C: BLTSIZV (value); break; + case 0x5E: BLTSIZH (value); break; + case 0x1E4: DIWHIGH (hpos, value); break; + case 0x10C: BPLCON4 (hpos, value); break; + + case 0x1DC: BEAMCON0 (value); break; + case 0x1C0: if (htotal != value) { htotal = value; varsync (); } break; + case 0x1C2: if (hsstop != value) { hsstop = value; varsync (); } break; + case 0x1C4: if (hbstrt != value) { hbstrt = value; varsync (); } break; + case 0x1C6: if (hbstop != value) { hbstop = value; varsync (); } break; + case 0x1C8: if (vtotal != value) { vtotal = value; varsync (); } break; + case 0x1CA: if (vsstop != value) { vsstop = value; varsync (); } break; + case 0x1CC: if (vbstrt < value || vbstrt > value + 1) { vbstrt = value; varsync (); } break; + case 0x1CE: if (vbstop < value || vbstop > value + 1) { vbstop = value; varsync (); } break; + case 0x1DE: if (hsstrt != value) { hsstrt = value; varsync (); } break; + case 0x1E0: if (vsstrt != value) { vsstrt = value; varsync (); } break; + case 0x1E2: if (hcenter != value) { hcenter = value; varsync (); } break; + + case 0x1FC: FMODE (value); break; } } void REGPARAM2 custom_wput (uaecptr addr, uae_u32 value) { int hpos = current_hpos (); - special_mem |= S_WRITE; - sync_copper_with_cpu (hpos, 1, addr); + sync_copper_with_cpu (hpos, 1); custom_wput_1 (hpos, addr, value); } @@ -4419,7 +4011,6 @@ void REGPARAM2 custom_bput (uaecptr addr static int warned = 0; /* Is this correct now? (There are people who bput things to the upper byte of AUDxVOL). */ uae_u16 rval = (value << 8) | (value & 0xFF); - special_mem |= S_WRITE; custom_wput (addr, rval); if (!warned) write_log ("Byte put to custom register.\n"), warned++; @@ -4427,7 +4018,6 @@ void REGPARAM2 custom_bput (uaecptr addr void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value) { - special_mem |= S_WRITE; custom_wput (addr & 0xfffe, value >> 16); custom_wput ((addr + 2) & 0xfffe, (uae_u16)value); } @@ -4447,7 +4037,7 @@ void custom_prepare_savestate (void) #define RW restore_u16 () #define RL restore_u32 () -uae_u8 *restore_custom (uae_u8 *src) +const uae_u8 *restore_custom (const uae_u8 *src) { uae_u16 dsklen, dskbytr, dskdatr; int dskpt; @@ -4455,7 +4045,7 @@ uae_u8 *restore_custom (uae_u8 *src) audio_reset (); - currprefs.chipset_mask = RL; + changed_prefs.chipset_mask = currprefs.chipset_mask = RL; RW; /* 000 ? */ RW; /* 002 DMACONR */ RW; /* 004 VPOSR */ @@ -4543,14 +4133,14 @@ uae_u8 *restore_custom (uae_u8 *src) RW; /* BPLXDAT */ for(i = 0; i < 32; i++) current_colors.color_regs_ecs[i] = RW; /* 180 COLORxx */ - RW; /* 1C0 ? */ - RW; /* 1C2 ? */ - RW; /* 1C4 ? */ - RW; /* 1C6 ? */ - RW; /* 1C8 ? */ - RW; /* 1CA ? */ - RW; /* 1CC ? */ - RW; /* 1CE ? */ + htotal = RW; /* 1C0 HTOTAL */ + hsstop = RW; /* 1C2 HSTOP ? */ + hbstrt = RW; /* 1C4 HBSTRT ? */ + hbstop = RW; /* 1C6 HBSTOP ? */ + vtotal = RW; /* 1C8 VTOTAL */ + vsstop = RW; /* 1CA VSSTOP */ + vbstrt = RW; /* 1CC VBSTRT */ + vbstop = RW; /* 1CE VBSTOP */ RW; /* 1D0 ? */ RW; /* 1D2 ? */ RW; /* 1D4 ? */ @@ -4558,10 +4148,12 @@ uae_u8 *restore_custom (uae_u8 *src) RW; /* 1D8 ? */ RW; /* 1DA ? */ new_beamcon0 = RW; /* 1DC BEAMCON0 */ - RW; /* 1DE ? */ - RW; /* 1E0 ? */ - RW; /* 1E2 ? */ - RW; /* 1E4 ? */ + hsstrt = RW; /* 1DE HSSTRT */ + vsstrt = RW; /* 1E0 VSSTT */ + hcenter = RW; /* 1E2 HCENTER */ + diwhigh = RW; /* 1E4 DIWHIGH */ + diwhigh_written = (diwhigh & 0x8000) ? 1 : 0; + diwhigh &= 0x7fff; RW; /* 1E6 ? */ RW; /* 1E8 ? */ RW; /* 1EA ? */ @@ -4574,7 +4166,7 @@ uae_u8 *restore_custom (uae_u8 *src) RW; /* 1F8 ? */ RW; /* 1FA ? */ fmode = RW; /* 1FC FMODE */ - RW; /* 1FE ? */ + last_custom_value = RW; /* 1FE ? */ DISK_restore_custom (dskpt, dsklen, dskdatr, dskbytr); @@ -4588,7 +4180,7 @@ uae_u8 *restore_custom (uae_u8 *src) extern uae_u16 serper; -uae_u8 *save_custom (int *len) +uae_u8 *save_custom (int *len, uae_u8 *dstptr, int full) { uae_u8 *dstbak, *dst; int i; @@ -4596,7 +4188,12 @@ uae_u8 *save_custom (int *len) uae_u16 dsklen, dsksync, dskdatr, dskbytr; DISK_save_custom (&dskpt, &dsklen, &dsksync, &dskdatr, &dskbytr); - dstbak = dst = malloc (8+256*2); + + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = malloc (8 + 256 * 2); + SL (currprefs.chipset_mask); SW (0); /* 000 ? */ SW (dmacon); /* 002 DMACONR */ @@ -4685,14 +4282,14 @@ uae_u8 *save_custom (int *len) SW (0); /* 110 BPLxDAT */ for ( i = 0; i < 32; i++) SW (current_colors.color_regs_ecs[i]); /* 180-1BE COLORxx */ - SW (0); /* 1C0 */ - SW (0); /* 1C2 */ - SW (0); /* 1C4 */ - SW (0); /* 1C6 */ - SW (0); /* 1C8 */ - SW (0); /* 1CA */ - SW (0); /* 1CC */ - SW (0); /* 1CE */ + SW (htotal); /* 1C0 HTOTAL */ + SW (hsstop); /* 1C2 HSTOP*/ + SW (hbstrt); /* 1C4 HBSTRT */ + SW (hbstop); /* 1C6 HBSTOP */ + SW (vtotal); /* 1C8 VTOTAL */ + SW (vsstop); /* 1CA VSSTOP */ + SW (vbstrt); /* 1CC VBSTRT */ + SW (vbstop); /* 1CE VBSTOP */ SW (0); /* 1D0 */ SW (0); /* 1D2 */ SW (0); /* 1D4 */ @@ -4700,10 +4297,10 @@ uae_u8 *save_custom (int *len) SW (0); /* 1D8 */ SW (0); /* 1DA */ SW (beamcon0); /* 1DC BEAMCON0 */ - SW (0); /* 1DE */ - SW (0); /* 1E0 */ - SW (0); /* 1E2 */ - SW (0); /* 1E4 */ + SW (hsstrt); /* 1DE HSSTRT */ + SW (vsstrt); /* 1E0 VSSTRT */ + SW (hcenter); /* 1E2 HCENTER */ + SW (diwhigh | (diwhigh_written ? 0x8000 : 0)); /* 1E4 DIWHIGH */ SW (0); /* 1E6 */ SW (0); /* 1E8 */ SW (0); /* 1EA */ @@ -4716,13 +4313,13 @@ uae_u8 *save_custom (int *len) SW (0); /* 1F8 */ SW (0); /* 1FA */ SW (fmode); /* 1FC FMODE */ - SW (0xffff); /* 1FE */ + SW (last_custom_value); /* 1FE */ *len = dst - dstbak; return dstbak; } -uae_u8 *restore_custom_agacolors (uae_u8 *src) +const uae_u8 *restore_custom_agacolors (const uae_u8 *src) { int i; @@ -4731,19 +4328,22 @@ uae_u8 *restore_custom_agacolors (uae_u8 return src; } -uae_u8 *save_custom_agacolors (int *len) +uae_u8 *save_custom_agacolors (int *len, uae_u8 *dstptr) { uae_u8 *dstbak, *dst; int i; - dstbak = dst = malloc (256*4); + if (dstptr) + dstbak = dst = dstptr; + else + dstbak = dst = malloc (256*4); for (i = 0; i < 256; i++) SL (current_colors.color_regs_aga[i]); *len = dst - dstbak; return dstbak; } -uae_u8 *restore_custom_sprite (uae_u8 *src, int num) +const uae_u8 *restore_custom_sprite (int num, const uae_u8 *src) { spr[num].pt = RL; /* 120-13E SPRxPT */ sprpos[num] = RW; /* 1x0 SPRxPOS */ @@ -4760,7 +4360,7 @@ uae_u8 *restore_custom_sprite (uae_u8 *s return src; } -uae_u8 *save_custom_sprite(int *len, int num) +uae_u8 *save_custom_sprite(int num, int *len) { uae_u8 *dstbak, *dst; @@ -4780,3 +4380,15 @@ uae_u8 *save_custom_sprite(int *len, int *len = dst - dstbak; return dstbak; } + +void check_prefs_changed_custom (void) +{ + currprefs.gfx_framerate = changed_prefs.gfx_framerate; + if (inputdevice_config_change_test ()) { + inputdevice_copyconfig (&changed_prefs, &currprefs); + inputdevice_updateconfig (&currprefs); + } + currprefs.immediate_blits = changed_prefs.immediate_blits; + currprefs.blits_32bit_enabled = changed_prefs.blits_32bit_enabled; + currprefs.collision_level = changed_prefs.collision_level; +}