--- uae/src/custom.c 2018/04/24 16:42:15 1.1.1.4 +++ uae/src/custom.c 2018/04/24 16:50:11 1.1.1.9 @@ -38,6 +38,9 @@ #include "picasso96.h" #include "drawing.h" +static unsigned int n_consecutive_skipped = 0; +static unsigned int total_skipped = 0; + #define SPRITE_COLLISIONS /* Mouse and joystick emulation */ @@ -71,8 +74,6 @@ static uae_u32 sprtaba[256],sprtabb[256] static void custom_wput_1 (int, uaecptr, uae_u32) REGPARAM; -static int fmode; - static uae_u16 cregs[256]; uae_u16 intena,intreq; @@ -80,6 +81,18 @@ 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 vblank_hz = VBLANK_HZ_PAL; +unsigned long syncbase; +static int fmode; +static unsigned int beamcon0, new_beamcon0; +static int ntscmode = 0; + +#define MAX_SPRITES 32 /* This is but an educated guess. It seems to be correct, but this stuff * isn't documented well. */ @@ -89,8 +102,12 @@ static int spron[8]; static uaecptr sprpt[8]; static int sprxpos[8], sprvstart[8], sprvstop[8]; -static uae_u32 bpl1dat,bpl2dat,bpl3dat,bpl4dat,bpl5dat,bpl6dat,bpl7dat,bpl8dat; -static uae_s16 bpl1mod,bpl2mod; +static unsigned int sprdata[MAX_SPRITES], sprdatb[MAX_SPRITES], sprctl[MAX_SPRITES], sprpos[MAX_SPRITES]; +static int sprarmed[MAX_SPRITES], sprite_last_drawn_at[MAX_SPRITES]; +static int last_sprite_point, nr_armed; + +static uae_u32 bpl1dat, bpl2dat, bpl3dat, bpl4dat, bpl5dat, bpl6dat, bpl7dat, bpl8dat; +static uae_s16 bpl1mod, bpl2mod; static uaecptr bplpt[8]; #ifndef SMART_UPDATE @@ -100,17 +117,15 @@ static char *real_bplpt[8]; /*static int blitcount[256]; blitter debug */ static struct color_entry current_colors; -static unsigned int bplcon0,bplcon1,bplcon2,bplcon3,bplcon4; +static unsigned int bplcon0, bplcon1, bplcon2, bplcon3, bplcon4; static int nr_planes_from_bplcon0, corrected_nr_planes_from_bplcon0; static unsigned int diwstrt, diwstop, diwhigh; static int diwhigh_written; static unsigned int ddfstrt, ddfstop; -static unsigned int sprdata[8], sprdatb[8], sprctl[8], sprpos[8]; -static int sprarmed[8], sprite_last_drawn_at[8]; -static int last_sprite_point, nr_armed; + static uae_u32 dskpt; -static uae_u16 dsklen,dsksync; -static int dsklength; +static uae_u16 dsklen, dsksync; +static int dsklength, syncfound; /* The display and data fetch windows */ @@ -119,8 +134,9 @@ enum diw_states DIW_waiting_start, DIW_waiting_stop }; -static int plffirstline,plflastline,plfstrt,plfstop,plflinelen; -int diwfirstword,diwlastword; +static int plffirstline, plflastline, plfstrt, plfstop, plflinelen; +static int last_diw_pix_hpos, last_ddf_pix_hpos; +int diwfirstword, diwlastword; static enum diw_states diwstate, hdiwstate; /* Sprite collisions */ @@ -131,7 +147,7 @@ enum copper_states { COP_stop, COP_rdelay1, COP_read1, COP_read2, COP_bltwait, - COP_wait1, COP_wait1b, COP_wait2, + COP_wait }; struct copper { @@ -142,22 +158,19 @@ struct copper { uaecptr ip; int hpos, vpos, count; unsigned int ignore_next; - unsigned int do_move; - enum diw_states vdiw; + unsigned int vcmp, hcmp; }; static struct copper cop_state; -static void prepare_copper_1 (void); - -int dskdmaen; /* used in cia.c */ +static int dskdmaen; /* * Statistics */ /* Used also by bebox.cpp */ -unsigned long int msecs = 0, frametime = 0, timeframes = 0; +unsigned long int msecs = 0, frametime = 0, lastframetime = 0, timeframes = 0; static unsigned long int seconds_base; int bogusframe; @@ -187,9 +200,9 @@ struct color_change color_changes[2][MAX struct delay_change delay_changes[MAX_REG_CHANGE]; #endif -struct decision line_decisions[2 * (maxvpos+1) + 1]; -struct draw_info line_drawinfo[2][2 * (maxvpos+1) + 1]; -struct color_entry color_tables[2][(maxvpos+1) * 2]; +struct decision line_decisions[2 * (MAXVPOS + 1) + 1]; +struct draw_info line_drawinfo[2][2 * (MAXVPOS + 1) + 1]; +struct color_entry color_tables[2][(MAXVPOS + 1) * 2]; struct sprite_draw *curr_sprite_positions, *prev_sprite_positions; struct color_change *curr_color_changes, *prev_color_changes; @@ -202,14 +215,15 @@ static int color_src_match, color_dest_m /* These few are only needed during/at the end of the scanline, and don't * have to be remembered. */ -static int decided_bpl1mod, decided_bpl2mod, decided_nr_planes, decided_hires; +static int decided_bpl1mod, decided_bpl2mod, decided_nr_planes, decided_res; + +static char thisline_changed; -char line_changed[2 * (maxvpos+1)]; #ifdef SMART_UPDATE -#define MARK_LINE_CHANGED(l) do { line_changed[l] = 1; } while (0) +#define MARK_LINE_CHANGED do { thisline_changed = 1; } while (0) #else -#define MARK_LINE_CHANGED(l) do { } while (0) +#define MARK_LINE_CHANGED do { ; } while (0) #endif static struct decision thisline_decision; @@ -237,23 +251,14 @@ void reset_frame_rate_hack (void) write_log ("Resetting frame rate hack\n"); } -static __inline__ void prepare_copper (void) -{ - if (cop_state.vpos > vpos - || cop_state.state == COP_stop) - { - eventtab[ev_copper].active = 0; - return; - } - prepare_copper_1 (); -} - void check_prefs_changed_custom (void) { - currprefs.framerate = changed_prefs.framerate; + currprefs.gfx_framerate = changed_prefs.gfx_framerate; /* Not really the right place... */ - if (currprefs.fake_joystick != changed_prefs.fake_joystick) { - currprefs.fake_joystick = changed_prefs.fake_joystick; + 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; @@ -261,13 +266,12 @@ void check_prefs_changed_custom (void) } -static __inline__ void setclr (uae_u16 *p, uae_u16 val) +STATIC_INLINE void setclr (uae_u16 *p, uae_u16 val) { - if (val & 0x8000) { + if (val & 0x8000) *p |= val & 0x7FFF; - } else { + else *p &= ~val; - } } __inline__ int current_hpos (void) @@ -275,7 +279,7 @@ __inline__ int current_hpos (void) return cycles - eventtab[ev_hsync].oldcycles; } -static __inline__ uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount) +STATIC_INLINE uae_u8 *pfield_xlateptr (uaecptr plpt, int bytecount) { if (!chipmem_bank.check (plpt, bytecount)) { static int count = 0; @@ -286,7 +290,7 @@ static __inline__ uae_u8 *pfield_xlatept return chipmem_bank.xlateaddr (plpt); } -static __inline__ void docols(struct color_entry *colentry) +STATIC_INLINE void docols (struct color_entry *colentry) { #if AGA_CHIPSET == 0 int i; @@ -305,7 +309,7 @@ void notice_new_xcolors (void) docols(¤t_colors); /* docols(&colors_for_drawing);*/ - for (i = 0; i < (maxvpos+1)*2; i++) { + for (i = 0; i < (MAXVPOS + 1)*2; i++) { docols(color_tables[0]+i); docols(color_tables[1]+i); } @@ -341,13 +345,11 @@ static void remember_ctable (void) color_src_match = oldctable; color_dest_match = remembered_color_entry; } - if (changed) { - line_changed[next_lineno] = 1; - } + thisline_changed |= changed; } else { /* We know the result of the comparison */ if (color_compare_result) - line_changed[next_lineno] = 1; + thisline_changed = 1; } } @@ -361,8 +363,9 @@ static void remember_ctable_for_border ( * checked. */ static void decide_diw (int hpos) { + int pix_hpos = PIXEL_XPOS (hpos); if (hdiwstate == DIW_waiting_start && thisline_decision.diwfirstword == -1 - && PIXEL_XPOS (hpos) >= diwfirstword) + && pix_hpos >= diwfirstword && last_diw_pix_hpos < diwfirstword) { thisline_decision.diwfirstword = diwfirstword; hdiwstate = DIW_waiting_stop; @@ -370,22 +373,23 @@ static void decide_diw (int hpos) * some programs change them after DDF start but before DIW start. */ thisline_decision.bplcon1 = bplcon1; if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) - MARK_LINE_CHANGED (next_lineno); + MARK_LINE_CHANGED; thisline_decision.diwlastword = -1; } if (hdiwstate == DIW_waiting_stop && thisline_decision.diwlastword == -1 - && PIXEL_XPOS (hpos) >= diwlastword) + && pix_hpos >= diwlastword && last_diw_pix_hpos < diwlastword) { thisline_decision.diwlastword = diwlastword; hdiwstate = DIW_waiting_start; if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) - MARK_LINE_CHANGED (next_lineno); + MARK_LINE_CHANGED; } + last_diw_pix_hpos = pix_hpos; } /* Called when we know that the line is not in the border and we want to draw * it. The data fetch starting position and length are passed as parameters. */ -static __inline__ void decide_as_playfield (int startpos, int len) +STATIC_INLINE void decide_as_playfield (int startpos, int len) { thisline_decision.which = 1; @@ -414,7 +418,7 @@ static __inline__ void decide_as_playfie #endif ) #endif /* SMART_UPDATE */ - line_changed[next_lineno] = 1; + thisline_changed = 1; } /* Called when we already decided whether the line is playfield or border, @@ -449,9 +453,16 @@ static void adjust_broken_program (int h { int tmp1, tmp2; int i; - if (decided_hires) { + + /* Magic again... :-/ */ + hpos += 4; + + if (decided_res == RES_HIRES) { tmp1 = hpos & 3; tmp2 = hpos & ~3; + } else if (decided_res == RES_SUPERHIRES) { + tmp1 = hpos & 1; + tmp2 = hpos & ~1; } else { tmp1 = hpos & 7; tmp2 = hpos & ~7; @@ -459,7 +470,9 @@ static void adjust_broken_program (int h for (i = 0; i < decided_nr_planes; i++) { if (broken_plane_sub[i] != -1) continue; - if (decided_hires) { + /* FIXME: superhires, AGA playfields */ + /* Actually, I don't want to support this crap for AGA if we can avoid it. */ + if (decided_res == RES_HIRES) { broken_plane_sub[i] = (tmp2 - thisline_decision.plfstrt) / 4 * 2; switch (i) { case 3: broken_plane_sub[i] += 2; break; /* @@@ break was missing */ @@ -481,11 +494,20 @@ static void adjust_broken_program (int h } } -static __inline__ void post_decide_line (int hpos) +STATIC_INLINE void set_decided_res (void) +{ + decided_res = RES_LORES; + if (bplcon0 & 0x8000) + decided_res = RES_HIRES; + if (bplcon0 & 0x40) + decided_res = RES_SUPERHIRES; +} + +STATIC_INLINE void post_decide_line (int hpos) { if (thisline_decision.which == 1 && hpos < thisline_decision.plfstrt + thisline_decision.plflinelen - && ((bplcon0 & 0x7000) == 0 || !dmaen (DMA_BITPLANE))) + && (GET_PLANES (bplcon0) == 0 || !dmaen (DMA_BITPLANE))) { /* This is getting gross... */ thisline_decision.plflinelen = hpos - thisline_decision.plfstrt; @@ -498,7 +520,7 @@ static __inline__ void post_decide_line } if (diwstate == DIW_waiting_start - || (bplcon0 & 0x7000) == 0 + || GET_PLANES (bplcon0) == 0 || !dmaen (DMA_BITPLANE) || hpos >= thisline_decision.plfstrt + thisline_decision.plflinelen) return; @@ -507,13 +529,13 @@ static __inline__ void post_decide_line && hpos > thisline_decision.plfstrt && decided_nr_planes < nr_planes_from_bplcon0) { - decided_hires = (bplcon0 & 0x8000) == 0x8000; + set_decided_res (); init_broken_program (); decided_nr_planes = nr_planes_from_bplcon0; - thisline_decision.bplcon0 &= 0xFFF; - thisline_decision.bplcon0 |= bplcon0 & 0xF000; + thisline_decision.bplcon0 &= 0xFEF; + thisline_decision.bplcon0 |= bplcon0 & 0xF010; adjust_broken_program (hpos); - MARK_LINE_CHANGED (next_lineno); /* Play safe. */ + MARK_LINE_CHANGED; /* Play safe. */ return; } @@ -532,10 +554,10 @@ static __inline__ void post_decide_line init_broken_program (); decided_nr_planes = nr_planes_from_bplcon0; - thisline_decision.bplcon0 &= 0xFFF; - thisline_decision.bplcon0 |= bplcon0 & 0xF000; + thisline_decision.bplcon0 &= 0xFEF; + thisline_decision.bplcon0 |= bplcon0 & 0xF010; - MARK_LINE_CHANGED (next_lineno); /* Play safe. */ + MARK_LINE_CHANGED; /* Play safe. */ decide_as_playfield (plfstrt, plflinelen); adjust_broken_program (hpos); } @@ -566,21 +588,21 @@ static void decide_line_1 (int hpos) return; } - decided_hires = (bplcon0 & 0x8000) == 0x8000; + set_decided_res (); decided_nr_planes = nr_planes_from_bplcon0; #if 0 /* The blitter gets slower if there's high bitplane activity. * @@@ but the values must be different. FIXME */ if (bltstate != BLT_done - && ((decided_hires && decided_nr_planes > 2) - || (!decided_hires && decided_nr_planes > 4))) + && ((decided_res == RES_HIRES && decided_nr_planes > 2) + || (decided_res == RES_LORES && decided_nr_planes > 4))) { int pl = decided_nr_planes; unsigned int n = (eventtab[ev_blitter].evtime-cycles); if (n > plflinelen) n = plflinelen; n >>= 1; - if (decided_hires) + if (decided_res == RES_HIRES) pl <<= 1; if (pl == 8) eventtab[ev_blitter].evtime += plflinelen; @@ -596,7 +618,7 @@ static void decide_line_1 (int hpos) /* Main entry point for deciding how to draw a line. May either do * nothing, decide the line as border, or decide the line as playfield. */ -static __inline__ void decide_line (int hpos) +STATIC_INLINE void decide_line (int hpos) { if (thisline_decision.which == 0 && hpos >= plfstrt) decide_line_1 (hpos); @@ -642,7 +664,7 @@ static void record_color_change (int hpo if (regno == 0 && thisline_decision.color0 == 0xFFFFFFFFul && thisline_decision.diwfirstword < 0) { thisline_decision.color0 = current_colors.color_regs[0]; if (line_decisions[next_lineno].color0 != value) - line_changed[next_lineno] = 1; + thisline_changed = 1; } /* Anything else gets recorded in the color_changes table. */ #ifdef OS_WITHOUT_MEMORY_MANAGEMENT @@ -708,13 +730,14 @@ static void decide_plane (int hpos) plane_decided = 1; - bytecount = plflinelen / (decided_hires ? 4 : 8) * 2; + bytecount = plflinelen / RES_SHIFT (decided_res) * 2; if (bytecount > MAX_WORDS_PER_LINE * 2) { /* Can't happen. */ static int warned = 0; if (!warned) write_log ("Mysterious bug in decide_plane(). Please report.\n"); + warned = 1; bytecount = 0; } if (!very_broken_program) { @@ -726,11 +749,11 @@ static void decide_plane (int hpos) real_ptr = pfield_xlateptr(0, 0); #ifdef SMART_UPDATE #if 1 - if (line_changed[next_lineno]) + if (thisline_changed) memcpy (dataptr, real_ptr, bytecount); else #endif - line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount); + thisline_changed |= memcmpy (dataptr, real_ptr, bytecount); #else real_bplpt[i] = real_ptr; #endif @@ -746,8 +769,8 @@ static void decide_plane (int hpos) if (real_ptr == NULL) real_ptr = pfield_xlateptr(0, 0); #ifdef SMART_UPDATE - if (!line_changed[next_lineno]) - line_changed[next_lineno] |= memcmpy (dataptr, real_ptr, bytecount); + if (!thisline_changed) + thisline_changed |= memcmpy (dataptr, real_ptr, bytecount); else memcpy (dataptr, real_ptr, bytecount); #else @@ -766,7 +789,8 @@ static void decide_modulos (int hpos) { /* All this effort just for the Sanity WOC demo... */ decide_line (hpos); - if (decided_nr_planes != -1 && hpos >= thisline_decision.plfstrt + thisline_decision.plflinelen) + if (decided_nr_planes != -1 + && hpos >= thisline_decision.plfstrt + thisline_decision.plflinelen) return; decided_bpl1mod = bpl1mod; decided_bpl2mod = bpl2mod; @@ -786,7 +810,7 @@ static void do_modulos (int hpos) if (decided_nr_planes != -1 && plane_decided && !modulos_added && hpos >= thisline_decision.plfstrt + thisline_decision.plflinelen) { - int bytecount = thisline_decision.plflinelen / (decided_hires ? 4 : 8) * 2; + int bytecount = thisline_decision.plflinelen / RES_SHIFT (decided_res) * 2; int add1 = bytecount + decided_bpl1mod; int add2 = bytecount + decided_bpl2mod; @@ -816,7 +840,7 @@ static void do_modulos (int hpos) } } -static __inline__ void record_sprite (int spr, int sprxp) +STATIC_INLINE void record_sprite (int spr, int sprxp) { int pos = next_sprite_draw; unsigned int data, datb; @@ -827,9 +851,6 @@ static __inline__ void record_sprite (in return; } #endif - data = sprdata[spr]; - datb = sprdatb[spr]; - /* XXX FIXME, this isn't very clever, but it might do */ for (;;) { if (pos == curr_drawinfo[next_lineno].first_sprite_draw) @@ -852,6 +873,8 @@ static __inline__ void record_sprite (in curr_sprite_positions[pos].linepos = sprxp; curr_sprite_positions[pos].num = spr; curr_sprite_positions[pos].ctl = sprctl[spr]; + data = sprdata[spr]; + datb = sprdatb[spr]; curr_sprite_positions[pos].datab = ((sprtaba[data & 0xFF] << 16) | sprtaba[data >> 8] | (sprtabb[datb & 0xFF] << 16) | sprtabb[datb >> 8]); next_sprite_draw++; @@ -859,7 +882,8 @@ static __inline__ void record_sprite (in static void decide_sprites (int hpos) { - int nrs[8], posns[8], count, i; + int nrs[MAX_SPRITES], posns[MAX_SPRITES]; + int count, i; int point = PIXEL_XPOS (hpos); if (framecnt != 0 || hpos < 0x14 || nr_armed == 0 || point == last_sprite_point) @@ -924,17 +948,17 @@ static void finish_decisions (void) if (hdiwstate == DIW_waiting_stop) { thisline_decision.diwlastword = max_diwlastword; if (thisline_decision.diwlastword != line_decisions[next_lineno].diwlastword) - MARK_LINE_CHANGED (next_lineno); + MARK_LINE_CHANGED; } if (line_decisions[next_lineno].which != thisline_decision.which) - line_changed[next_lineno] = 1; + thisline_changed = 1; decide_plane (hpos); dip = curr_drawinfo + next_lineno; dip_old = prev_drawinfo + next_lineno; dp = line_decisions + next_lineno; - changed = line_changed[next_lineno]; + changed = thisline_changed; if (thisline_decision.which == 1) { record_diw_line (diwfirstword, diwlastword); @@ -979,7 +1003,7 @@ static void finish_decisions (void) changed = 1; if (changed) { - line_changed[next_lineno] = 1; + thisline_changed = 1; *dp = thisline_decision; } else /* The only one that may differ: */ @@ -996,18 +1020,18 @@ static void reset_decisions (void) decided_bpl2mod = bpl2mod; decided_nr_planes = -1; - /* decided_hires shouldn't be touched before it's initialized by decide_line(). */ + /* decided_res shouldn't be touched before it's initialized by decide_line(). */ thisline_decision.diwfirstword = -1; thisline_decision.diwlastword = -2; if (hdiwstate == DIW_waiting_stop) { thisline_decision.diwfirstword = PIXEL_XPOS (DISPLAY_LEFT_SHIFT/2); if (thisline_decision.diwfirstword != line_decisions[next_lineno].diwfirstword) - MARK_LINE_CHANGED (next_lineno); + MARK_LINE_CHANGED; } thisline_decision.ctable = -1; thisline_decision.color0 = 0xFFFFFFFFul; - line_changed[next_lineno] = 0; + thisline_changed = 0; curr_drawinfo[next_lineno].first_color_change = next_color_change; curr_drawinfo[next_lineno].first_delay_change = next_delay_change; curr_drawinfo[next_lineno].first_sprite_draw = next_sprite_draw; @@ -1018,6 +1042,9 @@ static void reset_decisions (void) plane_decided = 0; color_decided = 0; very_broken_program = 0; + + last_diw_pix_hpos = -1; + last_ddf_pix_hpos = -1; } /* Initialize the decision array, once before the emulator really starts. */ @@ -1029,10 +1056,40 @@ static void init_decisions (void) } } +/* set PAL or NTSC timing variables */ + +static void init_hz (void) +{ + int isntsc; + + beamcon0 = new_beamcon0; + init_decisions (); + + isntsc = beamcon0 & 0x20 ? 0 : 1; + if (!isntsc) { + maxvpos = MAXVPOS_PAL; + maxhpos = MAXHPOS_PAL; + minfirstline = MINFIRSTLINE_PAL; + vblank_endline = VBLANK_ENDLINE_PAL; + vblank_hz = VBLANK_HZ_PAL; + } else { + maxvpos = MAXVPOS_NTSC; + maxhpos = MAXHPOS_NTSC; + minfirstline = MINFIRSTLINE_NTSC; + vblank_endline = VBLANK_ENDLINE_NTSC; + vblank_hz = VBLANK_HZ_NTSC; + } + vsynctime = syncbase / vblank_hz; + + write_log ("Using %s timing\n", isntsc ? "NTSC" : "PAL"); +} + /* Calculate display window and data fetch values from the corresponding * hardware registers. */ static void calcdiw (void) { + int mask, add, mask2, add2, plfold; + int hstrt = diwstrt & 0xFF; int hstop = diwstop & 0xFF; int vstrt = diwstrt >> 8; @@ -1076,27 +1133,85 @@ static void calcdiw (void) plflastline = 313; } #endif + plfstrt = ddfstrt; plfstop = ddfstop; + /* @@@ Toni... these ones might be wrong for AGA? */ if (plfstrt < 0x18) plfstrt = 0x18; if (plfstop < 0x18) plfstop = 0x18; if (plfstop > 0xD8) plfstop = 0xD8; - if (plfstrt > plfstop) plfstrt = plfstop; /* ! If the masking operation is changed, the pfield_doline code could break * on some systems (alignment) */ /* This actually seems to be correct now, at least the non-AGA stuff... */ - plfstrt &= ~3; - plfstop &= ~3; - /* @@@ Start looking for AGA bugs here... (or maybe even in the above masking ops) */ - if ((fmode & 3) == 0) - plflinelen = (plfstop-plfstrt+15) & ~7; - else if ((fmode & 3) == 3) - plflinelen = (plfstop-plfstrt+63) & ~31; - else - plflinelen = (plfstop-plfstrt+31) & ~15; + + if ((fmode & 3) == 0) { + /* FMODE=0 */ + mask = ~7; + add = 15; + mask2 = ~3; + add2 = 0; + } else if ((fmode & 3) == 3) { + /* FMODE=3 */ + if(bplcon0 & 0x8000) { + mask = ~15; + add = 31; + mask2 = ~7; + add2 = 4; + } else { + mask = ~31; + add = 63; + mask2 = ~15; + add2 = 8; + } + } else { + /* FMODE=1/2 */ + if(bplcon0 & 0x8000) { + mask = ~15; + add = 31; + mask2 = ~15; + add2 = 4; + } else { + mask = ~15; + add = 31; + mask2 = ~15; + add2 = 8; + + } + } + /* ugh.. This works in every demo and game I have tested, but can't be correct, + * it looks too complex and stupid, does anybody know how this really works? (TW) + */ + plfold = plfstrt; + plfstrt &= mask2; + plfstrt += add2; + /* @@@ This one is different from the pre-AGA version. It shouldn't make + * a difference in OCS modes, though. */ + plfstop += plfstrt - plfold; + plfstop &= mask2; + plfstop += add2; + plflinelen = (plfstop-plfstrt+add) & mask; + + if (plfstrt > plfstop) + plfstrt = plfstop; + +#if 0 + if (plflinelen > 100 && (bplcon0 & 0x8000)) + write_log("vpos: %d fmode: %d, hires %d strt1 %d stop1 %d strt2 %d stop2 %d,plflinelen %d\n", + vpos,fmode&3,(bplcon0&0x8000)?1:0,ddfstrt,ddfstop,plfstrt,plfstop,plflinelen); +#endif } +/* + * lores,fmode=3 24 184 = 192 + * hires,fmode=3 40 200 = 176 + * hires,fmode=3 40 216 = 192 + * hires,fmode=1 56 200 = 160 + * hires,fmode=1 56 208 = 160 + * lores,fmode=1 48 200 = 176 + * lores,fmode=1 72 168 = 112 +*/ + /* Mousehack stuff */ #define defstepx (1<<16) @@ -1141,7 +1256,7 @@ static void mousehack_setfollow (void) mstepx = defstepx; mstepy = defstepy; } -uae_u32 mousehack_helper (void) +static uae_u32 mousehack_helper (void) { int mousexpos, mouseypos; @@ -1179,7 +1294,7 @@ void togglemouse (void) } } -static __inline__ int adjust (int val) +STATIC_INLINE int adjust (int val) { if (val > 127) return 127; @@ -1259,36 +1374,60 @@ static void do_mouse_hack (void) } } +static int timehack_alive = 0; + +static uae_u32 timehack_helper (void) +{ +#ifdef HAVE_GETTIMEOFDAY + struct timeval tv; + if (m68k_dreg (regs, 0) == 0) + return timehack_alive; + + timehack_alive = 10; + + gettimeofday (&tv, NULL); + put_long (m68k_areg (regs, 0), tv.tv_sec - (((365 * 8 + 2) * 24 - 2) * 60 * 60)); + put_long (m68k_areg (regs, 0) + 4, tv.tv_usec); + return 0; +#else + return 2; +#endif +} + /* * register functions */ - -static __inline__ uae_u16 DMACONR (void) +STATIC_INLINE uae_u16 DENISEID (void) +{ + if (currprefs.chipset_mask & CSMASK_AGA) + return 0xF8; + if (currprefs.chipset_mask & CSMASK_ECS_DENISE) + 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) +STATIC_INLINE uae_u16 INTENAR (void) { return intena; } uae_u16 INTREQR (void) { - return intreq | (currprefs.use_serial ? 0x0001 : 0); + return intreq /* | (currprefs.use_serial ? 0x0001 : 0) */; } -static __inline__ uae_u16 ADKCONR (void) +STATIC_INLINE uae_u16 ADKCONR (void) { return adkcon; } -static __inline__ uae_u16 VPOSR (void) +STATIC_INLINE uae_u16 VPOSR (void) { -#if AGA_CHIPSET == 1 - return (vpos >> 8) | lof | 0x2300; -#elif defined (ECS_AGNUS) - return (vpos >> 8) | lof | 0x2000; -#else - return (vpos >> 8) | lof; -#endif + unsigned int csbit = ntscmode ? 0x1000 : 0; + csbit |= (currprefs.chipset_mask & CSMASK_AGA) ? 0x2300 : 0; + csbit |= (currprefs.chipset_mask & CSMASK_ECS_AGNUS) ? 0x2000 : 0; + return (vpos >> 8) | lof | csbit; } static void VPOSW (uae_u16 v) { @@ -1301,47 +1440,41 @@ static void VPOSW (uae_u16 v) */ } -static __inline__ uae_u16 VHPOSR (void) +STATIC_INLINE uae_u16 VHPOSR (void) { return (vpos << 8) | current_hpos(); } -static __inline__ void COP1LCH (uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); } -static __inline__ void COP1LCL (uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); } -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_INLINE void COP1LCH (uae_u16 v) { cop1lc = (cop1lc & 0xffff) | ((uae_u32)v << 16); } +STATIC_INLINE void COP1LCL (uae_u16 v) { cop1lc = (cop1lc & ~0xffff) | (v & 0xfffe); } +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 COPJMP1 (uae_u16 a) +static void start_copper (void) { - cop_state.ip = cop1lc; - cop_state.do_move = 0; cop_state.ignore_next = 0; cop_state.state = COP_read1; cop_state.vpos = vpos; cop_state.hpos = current_hpos () & ~1; - cop_state.count = current_hpos () & ~1; - prepare_copper (); - if (eventtab[ev_copper].evtime == cycles && eventtab[ev_copper].active) - abort (); - events_schedule (); + cop_state.count = cop_state.hpos + 2; + + if (dmaen (DMA_COPPER)) + regs.spcflags |= SPCFLAG_COPPER; +} + +static void COPJMP1 (uae_u16 a) +{ + cop_state.ip = cop1lc; + start_copper (); } static void COPJMP2 (uae_u16 a) { cop_state.ip = cop2lc; - cop_state.do_move = 0; - cop_state.ignore_next = 0; - cop_state.state = COP_read1; - cop_state.vpos = vpos; - cop_state.hpos = current_hpos () & ~1; - cop_state.count = current_hpos () & ~1; - prepare_copper (); - if (eventtab[ev_copper].evtime == cycles && eventtab[ev_copper].active) - abort (); - events_schedule (); + start_copper (); } -static __inline__ void COPCON (uae_u16 a) +STATIC_INLINE void COPCON (uae_u16 a) { copcon = a; } @@ -1360,17 +1493,22 @@ static void DMACON (uae_u16 v) * bit in these cases. */ if ((dmacon & DMA_COPPER) > (oldcon & DMA_COPPER)) { cop_state.ip = cop1lc; - cop_state.do_move = 0; cop_state.ignore_next = 0; cop_state.state = COP_read1; cop_state.vpos = vpos; cop_state.hpos = current_hpos () & ~1; - cop_state.count = current_hpos () & ~1; - prepare_copper (); - if (eventtab[ev_copper].evtime == cycles && eventtab[ev_copper].active) - abort (); - need_resched = 1; + cop_state.count = (current_hpos () & ~1) + 2; + regs.spcflags |= SPCFLAG_COPPER; + } + if (! (dmacon & DMA_COPPER)) { + regs.spcflags &= ~SPCFLAG_COPPER; + cop_state.state = COP_stop; + } + + if ((dmacon & DMA_DISK) > (oldcon & DMA_DISK)) { + DISK_reset_cycles (); } + if ((dmacon & DMA_BLITPRI) > (oldcon & DMA_BLITPRI) && bltstate != BLT_done) { static int count = 0; if (!count) { @@ -1379,6 +1517,8 @@ static void DMACON (uae_u16 v) } regs.spcflags |= SPCFLAG_BLTNASTY; } + if (! (dmacon & DMA_BLITPRI)) + regs.spcflags &= ~SPCFLAG_BLTNASTY; update_audio (); @@ -1398,6 +1538,7 @@ static void DMACON (uae_u16 v) } else { if (cdp->state == 1 || cdp->state == 5) { cdp->state = 0; + cdp->last_sample = 0; cdp->current_sample = 0; } } @@ -1409,7 +1550,7 @@ static void DMACON (uae_u16 v) /*static int trace_intena = 0;*/ -static __inline__ void INTENA (uae_u16 v) +STATIC_INLINE void INTENA (uae_u16 v) { /* if (trace_intena) fprintf (stderr, "INTENA: %04x\n", v);*/ @@ -1437,6 +1578,11 @@ static void ADKCON (uae_u16 v) audio_channel[3].adk_mask = (((t >> 3) & 1) - 1); } +static void BEAMCON0 (uae_u16 v) +{ + new_beamcon0 = v & 0x20; +} + static void BPLPTH (int hpos, uae_u16 v, int num) { decide_line (hpos); @@ -1454,25 +1600,35 @@ static void BPLPTL (int hpos, uae_u16 v, static void BPLCON0 (int hpos, uae_u16 v) { -#if AGA_CHIPSET == 0 - v &= 0xFF0E; - /* The Sanity WOC demo needs this at one place (at the end of the "Party Effect") - * Disable bitplane DMA if someone tries to do more than 4 Hires bitplanes. */ - if ((v & 0xF000) > 0xC000) - v &= 0xFFF; - /* Don't want 7 lores planes either. */ - if ((v & 0x8000) == 0 && (v & 0x7000) == 0x7000) - v &= 0xEFFF; -#endif + if (! (currprefs.chipset_mask & CSMASK_AGA)) { + v &= 0xFF0E; + /* The Sanity WOC demo needs this at one place (at the end of the "Party Effect") + * Disable bitplane DMA if someone tries to do more than 4 Hires bitplanes. */ + if ((v & 0xF000) > 0xC000) + v &= 0xFFF; + /* Don't want 7 lores planes either. */ + if ((v & 0x8000) == 0 && (v & 0x7000) == 0x7000) + v &= 0xEFFF; + } if (bplcon0 == v) return; decide_line (hpos); + /* if ((bplcon0 ^ v) & 0x8000)*/ + calcdiw (); bplcon0 = v; - nr_planes_from_bplcon0 = (bplcon0 >> 12) & 7; - corrected_nr_planes_from_bplcon0 = ((bplcon0 >> 12) & 7) << (bplcon0 & 0x8000 ? 1 : 0); + nr_planes_from_bplcon0 = GET_PLANES (v); + + if (currprefs.chipset_mask & CSMASK_AGA) + /* It's not clear how the copper timings are affected by the number + * of bitplanes on AGA machines */ + corrected_nr_planes_from_bplcon0 = 4; + else + corrected_nr_planes_from_bplcon0 = nr_planes_from_bplcon0 << (bplcon0 & 0x8000 ? 1 : 0); + post_decide_line (hpos); } -static __inline__ void BPLCON1 (int hpos, uae_u16 v) + +STATIC_INLINE void BPLCON1 (int hpos, uae_u16 v) { if (bplcon1 == v) return; @@ -1480,22 +1636,27 @@ static __inline__ void BPLCON1 (int hpos bplcon1 = v; decide_delay (hpos); } -static __inline__ void BPLCON2 (int hpos, uae_u16 v) +STATIC_INLINE void BPLCON2 (int hpos, uae_u16 v) { - if (bplcon2 != v) - decide_line (hpos); + if (bplcon2 == v) + return; + decide_line (hpos); bplcon2 = v; } -static __inline__ void BPLCON3 (int hpos, uae_u16 v) +STATIC_INLINE void BPLCON3 (int hpos, uae_u16 v) { - if (bplcon3 != v) - decide_line (hpos); + if (bplcon3 == v) + return; + decide_line (hpos); bplcon3 = v; } -static __inline__ void BPLCON4 (int hpos, uae_u16 v) +STATIC_INLINE void BPLCON4 (int hpos, uae_u16 v) { - if (bplcon4 != v) - decide_line (hpos); + if (! (currprefs.chipset_mask & CSMASK_AGA)) + return; + if (bplcon4 == v) + return; + decide_line (hpos); bplcon4 = v; } @@ -1518,12 +1679,14 @@ static void BPL2MOD (int hpos, uae_u16 v } /* We could do as well without those... */ -static __inline__ void BPL1DAT (uae_u16 v) { bpl1dat = v; } -static __inline__ void BPL2DAT (uae_u16 v) { bpl2dat = v; } -static __inline__ void BPL3DAT (uae_u16 v) { bpl3dat = v; } -static __inline__ void BPL4DAT (uae_u16 v) { bpl4dat = v; } -static __inline__ void BPL5DAT (uae_u16 v) { bpl5dat = v; } -static __inline__ void BPL6DAT (uae_u16 v) { bpl6dat = v; } +STATIC_INLINE void BPL1DAT (uae_u16 v) { bpl1dat = v; } +STATIC_INLINE void BPL2DAT (uae_u16 v) { bpl2dat = v; } +STATIC_INLINE void BPL3DAT (uae_u16 v) { bpl3dat = v; } +STATIC_INLINE void BPL4DAT (uae_u16 v) { bpl4dat = v; } +STATIC_INLINE void BPL5DAT (uae_u16 v) { bpl5dat = v; } +STATIC_INLINE void BPL6DAT (uae_u16 v) { bpl6dat = v; } +STATIC_INLINE void BPL7DAT (uae_u16 v) { bpl7dat = v; } +STATIC_INLINE void BPL8DAT (uae_u16 v) { bpl8dat = v; } static void DIWSTRT (int hpos, uae_u16 v) { @@ -1547,6 +1710,8 @@ static void DIWSTOP (int hpos, uae_u16 v static void DIWHIGH (int hpos, uae_u16 v) { + if (! (currprefs.chipset_mask & CSMASK_ECS_DENISE)) + return; if (diwhigh_written && diwhigh == v) return; decide_line (hpos); @@ -1557,7 +1722,7 @@ static void DIWHIGH (int hpos, uae_u16 v static void DDFSTRT (int hpos, uae_u16 v) { - v &= 0xFF; + v &= (currprefs.chipset_mask & CSMASK_AGA) ? 0x1FC : 0xFC; if (ddfstrt == v) return; decide_line (hpos); @@ -1566,7 +1731,7 @@ static void DDFSTRT (int hpos, uae_u16 v } static void DDFSTOP (int hpos, uae_u16 v) { - v &= 0xFF; + v &= (currprefs.chipset_mask & CSMASK_AGA) ? 0x1FC : 0xFC; if (ddfstop == v) return; decide_line (hpos); @@ -1574,6 +1739,14 @@ static void DDFSTOP (int hpos, uae_u16 v calcdiw (); } +static void FMODE (uae_u16 v) +{ + if (! (currprefs.chipset_mask & CSMASK_AGA)) + return; + fmode = v; + calcdiw (); +} + static void BLTADAT (uae_u16 v) { maybe_blit(); @@ -1605,7 +1778,12 @@ static void BLTDMOD (uae_u16 v) { maybe_ static void BLTCON0 (uae_u16 v) { maybe_blit (); bltcon0 = v; blinea_shift = v >> 12; } /* The next category is "Most useless hardware register". * And the winner is... */ -static void BLTCON0L (uae_u16 v) { maybe_blit (); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); } +static void BLTCON0L (uae_u16 v) +{ + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) + return; + maybe_blit (); bltcon0 = (bltcon0 & 0xFF00) | (v & 0xFF); +} static void BLTCON1 (uae_u16 v) { maybe_blit (); bltcon1 = v; } static void BLTAFWM (uae_u16 v) { maybe_blit (); blt_info.bltafwm = v; } @@ -1637,22 +1815,26 @@ static void BLTSIZE (uae_u16 v) static void BLTSIZV (uae_u16 v) { + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) + return; maybe_blit (); oldvblts = v & 0x7FFF; } static void BLTSIZH (uae_u16 v) { + if (! (currprefs.chipset_mask & CSMASK_ECS_AGNUS)) + return; maybe_blit (); blt_info.hblitsize = v & 0x7FF; blt_info.vblitsize = oldvblts; if (!blt_info.vblitsize) blt_info.vblitsize = 32768; if (!blt_info.hblitsize) blt_info.hblitsize = 0x800; bltstate = BLT_init; - do_blitter(); + do_blitter (); } -static __inline__ void SPRxCTL_1 (uae_u16 v, int num) +STATIC_INLINE void SPRxCTL_1 (uae_u16 v, int num) { int sprxp; sprctl[num] = v; @@ -1669,7 +1851,7 @@ static __inline__ void SPRxCTL_1 (uae_u1 sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); sprvstop[num] = (sprctl[num] >> 8) | ((sprctl[num] << 7) & 0x100); } -static __inline__ void SPRxPOS_1 (uae_u16 v, int num) +STATIC_INLINE void SPRxPOS_1 (uae_u16 v, int num) { int sprxp; sprpos[num] = v; @@ -1677,13 +1859,13 @@ static __inline__ void SPRxPOS_1 (uae_u1 sprxpos[num] = sprxp; sprvstart[num] = (sprpos[num] >> 8) | ((sprctl[num] << 6) & 0x100); } -static __inline__ void SPRxDATA_1 (uae_u16 v, int num) +STATIC_INLINE void SPRxDATA_1 (uae_u16 v, int num) { sprdata[num] = v; nr_armed += 1 - sprarmed[num]; sprarmed[num] = 1; } -static __inline__ void SPRxDATB_1 (uae_u16 v, int num) +STATIC_INLINE void SPRxDATB_1 (uae_u16 v, int num) { sprdatb[num] = v; } @@ -1697,7 +1879,7 @@ static void SPRxPTH (int hpos, uae_u16 v sprpt[num] &= 0xffff; sprpt[num] |= (uae_u32)v << 16; - if (sprst[num] == SPR_stop || vpos < vblank_endline) + if (sprst[num] == SPR_stop || vpos < VBLANK_ENDLINE_NTSC) sprst[num] = SPR_restart; spron[num] = 1; } @@ -1707,7 +1889,7 @@ static void SPRxPTL (int hpos, uae_u16 v sprpt[num] &= ~0xffff; sprpt[num] |= v; - if (sprst[num] == SPR_stop || vpos < vblank_endline) + if (sprst[num] == SPR_stop || vpos < VBLANK_ENDLINE_NTSC) sprst[num] = SPR_restart; spron[num] = 1; } @@ -1738,9 +1920,9 @@ static void COLOR (int hpos, uae_u16 v, r = (v & 0xF00) >> 8; g = (v & 0xF0) >> 4; b = (v & 0xF) >> 0; - cr = color_regs[colreg] >> 16; - cg = (color_regs[colreg] >> 8) & 0xFF; - cb = color_regs[colreg] & 0xFF; + cr = current_colors.color_regs[colreg] >> 16; + cg = (current_colors.color_regs[colreg] >> 8) & 0xFF; + cb = current_colors.color_regs[colreg] & 0xFF; if (bplcon3 & 0x200) { cr &= 0xF0; cr |= r; @@ -1752,10 +1934,14 @@ static void COLOR (int hpos, uae_u16 v, cb = b + (b << 4); } cval = (cr << 16) | (cg << 8) | cb; - if (cval == color_regs[colreg]) + if (cval == current_colors.color_regs[colreg]) return; - color_regs[colreg] = cval; - pfield_may_need_update(1); + + /* Call this with the old table still intact. */ + record_color_change (hpos, colreg, v); + remembered_color_entry = -1; + current_colors.color_regs[colreg] = cval; +/* current_colors.acolors[colreg] = xcolors[v];*/ } #else { @@ -1785,36 +1971,75 @@ static void DSKLEN (uae_u16 v) write_log ("warning: Disk DMA aborted!\n"); eventtab[ev_diskblk].active = 0; events_schedule(); - } dsklen = dsklength = v; dsklength &= 0x3fff; if (dskdmaen == 2 && dsksync != 0x4489 && (adkcon & 0x400)) { write_log ("Non-standard sync: %04x len: %x\n", dsksync, dsklength); } - if (dskdmaen > 1) { - if (dsklen & 0x4000) { - eventtab[ev_diskblk].active = 1; - eventtab[ev_diskblk].oldcycles = cycles; - eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */ - events_schedule(); - } else { - int result = DISK_PrepareReadMFM(dsklength, dsksync, adkcon & 0x400); - if (result) { - eventtab[ev_diskblk].active = 1; - eventtab[ev_diskblk].oldcycles = cycles; - eventtab[ev_diskblk].evtime = result + cycles; - events_schedule(); - } - } + if (dskdmaen <= 1) + return; + + if (dsklen & 0x4000) { + eventtab[ev_diskblk].active = 1; + eventtab[ev_diskblk].oldcycles = cycles; + eventtab[ev_diskblk].evtime = 40 + cycles; /* ??? */ + events_schedule(); + dskdmaen = 3; + } else { + DISK_StartRead (); + syncfound = !(adkcon & 0x400); } } +static int update_disk_reads (void) +{ + int retval = 0; + /* If we get called from DSKBYTR or DSKDATR, we may not actually be + reading from disk, so skip the DMA update. */ + if (dskdmaen != 2) { + DISK_update_reads (0, 0, 0, 0); + return 0; + } + if (dsklength == 0) + write_log ("Bug in disk code: dsklength == 0\n"); + else + retval = DISK_update_reads (&dskpt, &dsklength, &syncfound, dsksync); + + if (dsklength == 0) { + dskdmaen = -1; + /* DISKBLK */ + INTREQ (0x8002); + } + return retval; +} + +static void disksync_handler (void) +{ + uae_u16 mfm, byte; + + eventtab[ev_disksync].active = 0; + + /* If no DMA, something weird happened. It's not clear what to do + about it. */ + if (! dmaen (0x10) || dskdmaen != 2) + return; + + /* Likewise... */ + if (! update_disk_reads ()) + return; + DISK_GetData (&mfm, &byte); + + if (dsksync == mfm) + INTREQ (0x9000); +} + static uae_u16 DSKBYTR (void) { uae_u16 v = (dsklen >> 1) & 0x6000; uae_u16 mfm, byte; - if (DISK_GetData (&mfm, &byte)) + if (update_disk_reads ()) v |= 0x8000; + DISK_GetData (&mfm, &byte); v |= byte; if (dsksync == mfm) v |= 0x1000; @@ -1824,6 +2049,7 @@ static uae_u16 DSKBYTR (void) static uae_u16 DSKDATR (void) { uae_u16 mfm, byte; + update_disk_reads (); DISK_GetData (&mfm, &byte); return mfm; } @@ -1840,18 +2066,18 @@ static uae_u16 POTGOR (void) uae_u16 v = (potgo_value | (potgo_value << 1)) & 0xAA00; v |= v >> 1; - if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + if (JSEM_ISMOUSE (0, &currprefs)) { if (buttonstate[2]) v &= 0xFBFF; if (buttonstate[1]) v &= 0xFEFF; - } else if (JSEM_ISJOY0 (0, currprefs.fake_joystick) || JSEM_ISJOY1 (0, currprefs.fake_joystick)) { + } 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.fake_joystick) || JSEM_ISJOY1 (1, currprefs.fake_joystick)) { + if (JSEM_ISJOY0 (1, &currprefs) || JSEM_ISJOY1 (1, &currprefs)) { if (joy1button & 2) v &= 0xbfff; if (joy1button & 4) v &= 0xefff; } @@ -1862,7 +2088,7 @@ static uae_u16 POTGOR (void) static uae_u16 POT0DAT (void) { static uae_u16 cnt = 0; - if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + if (JSEM_ISMOUSE (0, &currprefs)) { if (buttonstate[2]) cnt = ((cnt + 1) & 0xFF) | (cnt & 0xFF00); if (buttonstate[1]) @@ -1873,7 +2099,7 @@ static uae_u16 POT0DAT (void) } static uae_u16 JOY0DAT (void) { - if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + if (JSEM_ISMOUSE (0, &currprefs)) { do_mouse_hack (); return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8); } @@ -1881,7 +2107,7 @@ static uae_u16 JOY0DAT (void) } static uae_u16 JOY1DAT (void) { - if (JSEM_ISMOUSE (1, currprefs.fake_joystick)) { + if (JSEM_ISMOUSE (1, &currprefs)) { do_mouse_hack (); return ((uae_u8)mouse_x) + ((uae_u16)mouse_y << 8); } @@ -1889,7 +2115,7 @@ static uae_u16 JOY1DAT (void) } static void JOYTEST (uae_u16 v) { - if (JSEM_ISMOUSE (0, currprefs.fake_joystick)) { + if (JSEM_ISMOUSE (0, &currprefs)) { mouse_x = v & 0xFC; mouse_y = (v >> 8) & 0xFC; } @@ -1899,14 +2125,6 @@ static void JOYTEST (uae_u16 v) * Here starts the copper code. Can you believe it used to be worse? */ -static __inline__ void copper_adjust_diw (struct copper *cst) -{ - if (cst->vdiw == DIW_waiting_start && vpos == plffirstline) - cst->vdiw = DIW_waiting_stop; - if (cst->vdiw == DIW_waiting_stop && vpos == plflastline) - cst->vdiw = DIW_waiting_start; -} - /* Determine which cycles are available for the copper in a display * with a agiven number of planes. */ static int cycles_for_plane[9][8] = { @@ -1915,7 +2133,7 @@ static int cycles_for_plane[9][8] = { { 0, -1, 0, -1, 0, -1, 0, -1 }, { 0, -1, 0, -1, 0, -1, 0, -1 }, { 0, -1, 0, -1, 0, -1, 0, -1 }, - { 0, -1, 1, -1, 0, -1, 0, -1 }, + { 0, -1, 0, -1, 0, -1, 1, -1 }, { 0, -1, 1, -1, 0, -1, 1, -1 }, { 1, -1, 1, -1, 1, -1, 1, -1 }, { 1, -1, 1, -1, 1, -1, 1, -1 } @@ -1923,21 +2141,23 @@ static int cycles_for_plane[9][8] = { static unsigned int waitmasktab[256]; -#define COP_OFFSET 4 - -static __inline__ int copper_in_playfield (enum diw_states diw, int hpos) +STATIC_INLINE int copper_in_playfield (enum diw_states diw, int hpos) { - hpos -= COP_OFFSET; return diw == DIW_waiting_stop && hpos >= plfstrt && hpos < plfstrt + plflinelen; } -static __inline__ int copper_cant_read (enum diw_states diw, int hpos, int planes) +STATIC_INLINE int copper_cant_read (enum diw_states diw, int hpos, int planes) { int t; + /* @@@ */ if (hpos >= ((maxhpos - 2) & ~1)) return 1; + if (currprefs.chipset_mask & CSMASK_AGA) + /* FIXME */ + return 0; + if (! copper_in_playfield (diw, hpos)) return 0; @@ -1949,77 +2169,45 @@ static __inline__ int copper_cant_read ( return t; } -static void update_copper_1 (int until_hpos) +static void update_copper (int until_hpos) { - unsigned int vp, hp, vcmp, hcmp; + unsigned int vp, hp; int c_hpos = cop_state.hpos; - int c_vpos = cop_state.vpos; vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80); hp = cop_state.count & (cop_state.i2 & 0xFE); - vcmp = ((cop_state.i1 & (cop_state.i2 | 0x8000)) >> 8); - hcmp = (cop_state.i1 & cop_state.i2 & 0xFE); - - if (cop_state.state == COP_wait2) - cop_state.state = COP_wait1b; for (;;) { - if (c_hpos == (maxhpos & ~1)) { - c_hpos = 0; - cop_state.count = 0; - c_vpos++; - } - - if (! dmaen (DMA_COPPER)) - cop_state.state = COP_stop; - - if (c_vpos > vpos + if (c_hpos >= (maxhpos & ~1) || c_hpos > until_hpos - || cop_state.state == COP_stop) + || cop_state.state == COP_stop + || (regs.spcflags & SPCFLAG_COPPER) == 0) break; - if (c_hpos - COP_OFFSET == plfstrt) - copper_adjust_diw (&cop_state); + /* So we know about the vertical DIW. */ + decide_line (c_hpos); switch (cop_state.state) { - case COP_rdelay1: + case COP_stop: + abort (); + + case COP_rdelay1: cop_state.state = COP_read1; break; - case COP_read1: - if (copper_cant_read (cop_state.vdiw, c_hpos, corrected_nr_planes_from_bplcon0)) + case COP_read1: + if (copper_cant_read (diwstate, c_hpos, corrected_nr_planes_from_bplcon0)) break; - if (cop_state.do_move) { - cop_state.do_move = 0; - if (cop_state.i1 < (copcon & 2 ? 0x40u : 0x80u)) { - cop_state.state = COP_stop; - break; - } - switch (cop_state.i1) { - case 0x088: - cop_state.ip = cop1lc; - cop_state.state = COP_rdelay1; - break; - case 0x08A: - cop_state.ip = cop2lc; - cop_state.state = COP_rdelay1; - break; - default: - custom_wput_1 (c_hpos, cop_state.i1, cop_state.i2); - break; - } - if (cop_state.state != COP_read1) - break; - } cop_state.i1 = chipmem_bank.wget (cop_state.ip); cop_state.ip += 2; cop_state.state = COP_read2; break; - case COP_read2: - if (copper_cant_read (cop_state.vdiw, c_hpos, corrected_nr_planes_from_bplcon0)) + case COP_read2: + if (copper_cant_read (diwstate, c_hpos, corrected_nr_planes_from_bplcon0)) break; + cop_state.i2 = chipmem_bank.wget (cop_state.ip); cop_state.ip += 2; if (cop_state.ignore_next) { @@ -2027,83 +2215,68 @@ static void update_copper_1 (int until_h cop_state.state = COP_read1; break; } + /* Perform moves immediately. */ if ((cop_state.i1 & 1) == 0) { cop_state.state = COP_read1; - cop_state.do_move = 1; - } else { - vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80); - hp = cop_state.count & (cop_state.i2 & 0xFE); - vcmp = ((cop_state.i1 & (cop_state.i2 | 0x8000)) >> 8); - hcmp = (cop_state.i1 & cop_state.i2 & 0xFE); - - if ((cop_state.i2 & 1) == 0) { - cop_state.state = COP_wait1; - if (cop_state.i1 == 0xFFFF && cop_state.i2 == 0xFFFE) - cop_state.state = COP_stop; - } else { - /* Skip instruction. */ - if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) - && ((cop_state.i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000))) - cop_state.ignore_next = 1; + if (cop_state.i1 < (copcon & 2 ? ((currprefs.chipset_mask & CSMASK_AGA) ? 0 : 0x40u) : 0x80u)) { + cop_state.state = COP_stop; + break; + } + switch (cop_state.i1) { + case 0x088: + cop_state.ip = cop1lc; cop_state.state = COP_read1; + break; + case 0x08A: + cop_state.ip = cop2lc; + cop_state.state = COP_read1; + break; + default: + custom_wput_1 (c_hpos, cop_state.i1, cop_state.i2); + break; } - } - break; - - case COP_wait1: - if (copper_cant_read (cop_state.vdiw, c_hpos, corrected_nr_planes_from_bplcon0)) break; + } - /* fall through */ + vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80); + hp = cop_state.count & (cop_state.i2 & 0xFE); + cop_state.vcmp = ((cop_state.i1 & (cop_state.i2 | 0x8000)) >> 8); + cop_state.hcmp = (cop_state.i1 & cop_state.i2 & 0xFE); - case COP_wait1b: - { - int do_wait2 = cop_state.state == COP_wait1b; - cop_state.state = COP_wait2; - if (vp == vcmp && corrected_nr_planes_from_bplcon0 < 8) { - int t = cop_state.count + 2; - int next_count = (t & waitmasktab[cop_state.i2 & 0xfe]) | hcmp; - int nexthpos; - if (next_count < t) - next_count = t; - nexthpos = c_hpos + next_count - cop_state.count; - if (nexthpos < (maxhpos & ~1)) { - if (c_hpos - COP_OFFSET < plfstrt && nexthpos - COP_OFFSET >= plfstrt) - copper_adjust_diw (&cop_state); - c_hpos = nexthpos; - cop_state.count = next_count; - do_wait2 = 1; - } - } - if (! do_wait2) - break; + if ((cop_state.i2 & 1) == 1) { + /* Skip instruction. */ + if ((vp > cop_state.vcmp || (vp == cop_state.vcmp && hp >= cop_state.hcmp)) + && ((cop_state.i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000))) + cop_state.ignore_next = 1; + cop_state.state = COP_read1; + break; } + cop_state.state = COP_wait; + if (cop_state.i1 == 0xFFFF && cop_state.i2 == 0xFFFE) { + cop_state.state = COP_stop; + break; + } + break; - /* fall through */ - - case COP_wait2: - if (vp < vcmp) { - if (c_hpos - COP_OFFSET < plfstrt) - copper_adjust_diw (&cop_state); - - c_vpos++; - c_hpos = 0; - cop_state.count = 0; + case COP_wait: + if (vp < cop_state.vcmp) { + regs.spcflags &= ~SPCFLAG_COPPER; continue; } + if (copper_cant_read (diwstate, c_hpos, corrected_nr_planes_from_bplcon0)) + break; + hp = cop_state.count & (cop_state.i2 & 0xFE); - if (vp == vcmp && hp < hcmp) + if (vp == cop_state.vcmp && hp < cop_state.hcmp) break; /* Now we know that the comparisons were successful. */ if ((cop_state.i2 & 0x8000) == 0x8000 || ! (DMACONR() & 0x4000)) cop_state.state = COP_read1; else { - /* We need to wait for the blitter. It won't stop while - * we're in update_copper, so we _could_ as well proceed to - * until_hpos in one big step. There are some tricky - * issues to be considered, though, so use the slow method - * for now. */ + /* We need to wait for the blitter. */ cop_state.state = COP_bltwait; + regs.spcflags &= ~SPCFLAG_COPPER; + continue; } break; @@ -2112,238 +2285,61 @@ static void update_copper_1 (int until_h break; } - c_hpos += 2; - if (corrected_nr_planes_from_bplcon0 < 8 || ! copper_in_playfield (cop_state.vdiw, c_hpos)) + if (corrected_nr_planes_from_bplcon0 < 8 || ! copper_in_playfield (diwstate, c_hpos)) cop_state.count += 2; + c_hpos += 2; } cop_state.hpos = c_hpos; - cop_state.vpos = c_vpos; -} - -static __inline__ void update_copper (int until_hpos) -{ - if (cop_state.vpos > vpos - || cop_state.hpos > until_hpos - || cop_state.state == COP_stop) - return; - update_copper_1 (until_hpos); } -static int dangerous_reg (int reg) +static void compute_spcflag_copper (void) { - /* Safe: - * Bitplane pointers, control registers, modulos and data. - * Sprite pointers, control registers, and data. - * Color registers. */ - if (reg >= 0xE0 && reg < 0x1C0) - return 0; - return 1; -} - -static void prepare_copper_1 (void) -{ - struct copper cst = cop_state; - unsigned int vp, hp, vcmp, hcmp; - - vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80); - hp = cop_state.count & (cop_state.i2 & 0xFE); - vcmp = ((cop_state.i1 & (cop_state.i2 | 0x8000)) >> 8); - hcmp = (cop_state.i1 & cop_state.i2 & 0xFE); - - if (cst.state == COP_wait2) - cst.state = COP_wait1b; - - for (;;) { - if (cst.hpos == (maxhpos & ~1)) { - cst.hpos = 0; - cst.count = 0; - cst.vpos++; - } - - if (! dmaen (DMA_COPPER)) - cst.state = COP_stop; - - if (cst.vpos > vpos - || cst.state == COP_stop) - { - eventtab[ev_copper].active = 0; - return; - } - - if (cst.hpos - COP_OFFSET == plfstrt) - copper_adjust_diw (&cst); - - switch (cst.state) { - case COP_rdelay1: - cst.state = COP_read1; - break; - - case COP_read1: - if (copper_cant_read (cst.vdiw, cst.hpos, corrected_nr_planes_from_bplcon0)) - break; - - if (cst.do_move) { - cst.do_move = 0; - if (cst.i1 < (copcon & 2 ? 0x40u : 0x80u)) { - cst.state = COP_stop; - eventtab[ev_copper].active = 0; - return; - } else if (dangerous_reg (cst.i1)) { - eventtab[ev_copper].active = 1; - eventtab[ev_copper].oldcycles = cycles; - eventtab[ev_copper].evtime = cycles + cst.hpos - current_hpos () + (cst.vpos - cop_state.vpos) * maxhpos; - return; - } - } - - cst.i1 = chipmem_bank.wget (cst.ip); - cst.ip += 2; - cst.state = COP_read2; - break; - - case COP_read2: - if (copper_cant_read (cst.vdiw, cst.hpos, corrected_nr_planes_from_bplcon0)) - break; - cst.i2 = chipmem_bank.wget (cst.ip); - cst.ip += 2; - if (cst.ignore_next) { - cst.ignore_next = 0; - cst.state = COP_read1; - break; - } - if ((cst.i1 & 1) == 0) { - cst.state = COP_read1; - cst.do_move = 1; - } else { - vp = vpos & (((cst.i2 >> 8) & 0x7F) | 0x80); - hp = cst.count & (cst.i2 & 0xFE); - vcmp = ((cst.i1 & (cst.i2 | 0x8000)) >> 8); - hcmp = (cst.i1 & cst.i2 & 0xFE); - - if ((cst.i2 & 1) == 0) { - cst.state = COP_wait1; - if (cst.i1 == 0xFFFF && cst.i2 == 0xFFFE) - cst.state = COP_stop; - } else { - /* Skip instruction. */ - if ((vp > vcmp || (vp == vcmp && hp >= hcmp)) - && ((cst.i2 & 0x8000) != 0 || ! (DMACONR() & 0x4000))) - cst.ignore_next = 1; - cst.state = COP_read1; - } - } - break; - - case COP_wait1: - if (copper_cant_read (cst.vdiw, cst.hpos, corrected_nr_planes_from_bplcon0)) - break; - - /* fall through */ - - case COP_wait1b: - { - int do_wait2 = cst.state == COP_wait1b; - cst.state = COP_wait2; - if (vp == vcmp && corrected_nr_planes_from_bplcon0 < 8) { - int t = cst.count + 2; - int next_count = (t & waitmasktab[cst.i2 & 0xfe]) | hcmp; - int nexthpos; - if (next_count < t) - next_count = t; - nexthpos = cst.hpos + next_count - cst.count; - if (nexthpos < (maxhpos & ~1)) { - if (cst.hpos - COP_OFFSET < plfstrt && nexthpos - COP_OFFSET >= plfstrt) - copper_adjust_diw (&cst); - cst.hpos = nexthpos; - cst.count = next_count; - do_wait2 = 1; - } - } - if (! do_wait2) - break; - } - - /* fall through */ - - case COP_wait2: - if (vp < vcmp) { - if (cst.hpos - COP_OFFSET < plfstrt) - copper_adjust_diw (&cst); - - cst.vpos++; - cst.count = 0; - cst.hpos = 0; - continue; - } - hp = cst.count & (cst.i2 & 0xFE); - if (vp == vcmp && hp < hcmp) - break; -#if 0 - if (nexthpos != -1) - if (nexthpos != cst.count) - printf ("ERROR\n"); - nexthpos = -1; -#endif - /* Now we know that the comparisons were successful. */ - if ((cst.i2 & 0x8000) == 0x8000 || ! (DMACONR() & 0x4000)) - cst.state = COP_read1; - else { - /* We need to wait for the blitter. It won't stop while - * we're in update_copper, so we _could_ as well proceed to - * until_hpos in one big step. There are some tricky - * issues to be considered, though, so use the slow method - * for now. */ - cst.state = COP_bltwait; - } - break; - - default: - /* Delay cycles. */ - break; - } - - cst.hpos += 2; - if (corrected_nr_planes_from_bplcon0 < 8 || ! copper_in_playfield (cst.vdiw, cst.hpos)) - cst.count += 2; + unsigned long v = 0; + int vp; + switch (cop_state.state) { + case COP_rdelay1: + case COP_read1: + case COP_read2: + if (dmaen (DMA_COPPER)) + v = SPCFLAG_COPPER; + break; + case COP_wait: + vp = vpos & (((cop_state.i2 >> 8) & 0x7F) | 0x80); + if (vp >= cop_state.vcmp) + v = SPCFLAG_COPPER; + break; + case COP_bltwait: + break; } + regs.spcflags &= ~SPCFLAG_COPPER; + regs.spcflags |= v; } void blitter_done_notify (void) { if (cop_state.state != COP_bltwait) return; - update_copper (current_hpos ()); - cop_state.state = COP_wait2; - eventtab[ev_copper].active = 1; - eventtab[ev_copper].oldcycles = cycles; - eventtab[ev_copper].evtime = (cycles + 2) & ~1; - events_schedule (); + regs.spcflags |= SPCFLAG_COPPER; + cop_state.state = COP_wait; } -static void do_copper (void) +void do_copper (void) { int hpos = current_hpos (); update_copper (hpos); - prepare_copper (); - if (eventtab[ev_copper].evtime == cycles && eventtab[ev_copper].active) - abort (); } static void diskblk_handler (void) { - regs.spcflags |= SPCFLAG_DISK; eventtab[ev_diskblk].active = 0; -} -void do_disk (void) -{ - if (dskdmaen != 2 && (regs.spcflags & SPCFLAG_DISK)) { + if (dskdmaen != 3) { static int warned = 0; if (!warned) warned++, write_log ("BUG!\n"); return; } - if (dmaen(0x10)){ + if (dmaen (0x10)){ if (dsklen & 0x4000) { if (!chipmem_bank.check (dskpt, 2*dsklength)) { write_log ("warning: Bad disk write DMA pointer\n"); @@ -2359,10 +2355,8 @@ void do_disk (void) } DISK_WriteData(dsklength); } - } else { - DISK_ReadMFM (dskpt); - } - regs.spcflags &= ~SPCFLAG_DISK; + } else + write_log ("warning: diskblk_handler trying to read!\n"); INTREQ(0x9002); dskdmaen = -1; } @@ -2390,7 +2384,9 @@ static void do_sprites (int currvp, int * second time only _after_ the VBlank interval, and it showed the same behaviour * as it did unmodified under UAE with the above check. This indicates that the * solution below is correct. */ - if (currvp < vblank_endline) + /* Another update: seems like we have to use the NTSC value here (see Sanity Turmoil + * demo). */ + if (currvp < VBLANK_ENDLINE_NTSC) return; #endif @@ -2415,28 +2411,28 @@ static void do_sprites (int currvp, int fetch = 1; sprst[i] = SPR_waiting_stop; } - if (sprst[i] == SPR_waiting_stop && sprvstop[i] == vpos) { + if ((sprst[i] == SPR_waiting_stop || sprst[i] == SPR_waiting_start) && sprvstop[i] == vpos) { fetch = 2; sprst[i] = SPR_waiting_start; } - if (fetch && dmaen(DMA_SPRITE)) { - uae_u16 data1 = chipmem_bank.wget(sprpt[i]); - uae_u16 data2 = chipmem_bank.wget(sprpt[i]+2); + if (fetch && dmaen (DMA_SPRITE)) { + uae_u16 data1 = chipmem_bank.wget (sprpt[i]); + uae_u16 data2 = chipmem_bank.wget (sprpt[i] + 2); sprpt[i] += 4; 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; + spr0ctl = sprctl[0]; + spr0pos = sprpos[0]; + sprvbfl = 2; } - SPRxDATB_1(data2, i); - SPRxDATA_1(data1, i); + SPRxDATB_1 (data2, i); + SPRxDATA_1 (data1, i); } else { - SPRxPOS_1(data1, i); - SPRxCTL_1(data2, i); + SPRxPOS_1 (data1, i); + SPRxCTL_1 (data2, i); } } } @@ -2567,16 +2563,21 @@ static void vsync_handler (void) cnt--; } + /* For now, let's only allow this to change at vsync time. It gets too + * hairy otherwise. */ + if (beamcon0 != new_beamcon0) + init_hz (); + lof_changed = 0; cop_state.ip = cop1lc; cop_state.state = COP_read1; cop_state.vpos = 0; cop_state.hpos = 0; - cop_state.count = 0; - cop_state.do_move = 0; + cop_state.count = 2; cop_state.ignore_next = 0; - cop_state.vdiw = DIW_waiting_start; + if (dmaen (DMA_COPPER)) + regs.spcflags |= SPCFLAG_COPPER; init_hardware_frame (); @@ -2585,12 +2586,30 @@ static void vsync_handler (void) struct timeval tv; unsigned long int newtime; - gettimeofday(&tv,NULL); + gettimeofday (&tv,NULL); newtime = (tv.tv_sec-seconds_base) * 1000 + tv.tv_usec / 1000; if (!bogusframe) { - frametime += newtime - msecs; + 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++; + + if ((timeframes & 127) == 0) + gui_fps (1000 * timeframes / frametime); } msecs = newtime; bogusframe = 0; @@ -2598,21 +2617,27 @@ static void vsync_handler (void) #endif if (ievent_alive > 0) ievent_alive--; + if (timehack_alive > 0) + timehack_alive--; CIA_vsync_handler(); } static void hsync_handler (void) { update_copper (maxhpos); - finish_decisions (); do_modulos (current_hpos ()); - hsync_record_line_state (next_lineno, nextline_how); + hsync_record_line_state (next_lineno, nextline_how, thisline_changed); eventtab[ev_hsync].evtime += cycles - eventtab[ev_hsync].oldcycles; eventtab[ev_hsync].oldcycles = cycles; - CIA_hsync_handler(); + CIA_hsync_handler (); + + if (dskdmaen == 2 && dmaen (0x10)) { + update_disk_reads (); + DISK_search_sync (maxhpos, dsksync); + } if (currprefs.produce_sound > 0) { int nr; @@ -2656,7 +2681,7 @@ static void hsync_handler (void) nextline_how = nln_normal; if (currprefs.gfx_linedbl) { lineno *= 2; - nextline_how = nln_doubled; + nextline_how = currprefs.gfx_linedbl == 1 ? nln_doubled : nln_nblack; if (bplcon0 & 4) { if (!lof) { lineno++; @@ -2673,10 +2698,10 @@ static void hsync_handler (void) set_uae_int_flag (); INTREQ (0xA000); } - update_copper (0); - prepare_copper (); - if (eventtab[ev_copper].evtime == cycles && eventtab[ev_copper].active) - abort (); + /* See if there's a chance of a copper wait ending this line. */ + cop_state.hpos = 0; + cop_state.count = 2; + compute_spcflag_copper (); } static void init_eventtab (void) @@ -2689,7 +2714,6 @@ static void init_eventtab (void) } eventtab[ev_cia].handler = CIA_handler; - eventtab[ev_copper].handler = do_copper; eventtab[ev_hsync].handler = hsync_handler; eventtab[ev_hsync].evtime = maxhpos + cycles; eventtab[ev_hsync].active = 1; @@ -2700,6 +2724,8 @@ static void init_eventtab (void) eventtab[ev_diskblk].active = 0; eventtab[ev_diskindex].handler = diskindex_handler; eventtab[ev_diskindex].active = 0; + eventtab[ev_disksync].handler = disksync_handler; + eventtab[ev_disksync].active = 0; events_schedule (); } @@ -2711,8 +2737,10 @@ void customreset (void) struct timeval tv; #endif - for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++) - current_colors.color_regs[i] = -1; + for (i = 0; i < sizeof current_colors.color_regs / sizeof *current_colors.color_regs; i++) { + current_colors.color_regs[i] = 0; + current_colors.acolors[i] = xcolors[0]; + } expamem_reset (); @@ -2733,6 +2761,7 @@ void customreset (void) mousestate = normal_mouse; } ievent_alive = 0; + timehack_alive = 0; clx_sprmask = 0xFF; clxdat = 0; @@ -2749,11 +2778,14 @@ void customreset (void) dskdmaen = 0; cycles = 0; - audio_reset (); - bplcon4 = 0x11; /* Get AGA chipset into ECS compatibility mode */ bplcon3 = 0xC00; + new_beamcon0 = ntscmode ? 0x00 : 0x20; + init_hz (); + + audio_reset (); + init_eventtab (); init_sprites (); @@ -2772,12 +2804,14 @@ void customreset (void) void dumpcustom (void) { - fprintf (stderr, "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()); - fprintf (stderr, "COP1LC: %08lx, COP2LC: %08lx\n", (unsigned long)cop1lc, (unsigned long)cop2lc); + 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); if (timeframes) { - fprintf (stderr, "Average frame time: %d ms [frames: %d time: %d]\n", - frametime/timeframes, timeframes, frametime); + write_log ("Average frame time: %d ms [frames: %d time: %d]\n", + frametime / timeframes, timeframes, frametime); + if (total_skipped) + write_log ("Skipped frames: %d\n", total_skipped); } dump_audio_bench (); /*for (i=0; i<256; i++) if (blitcount[i]) fprintf (stderr, "minterm %x = %d\n",i,blitcount[i]); blitter debug */ @@ -2819,6 +2853,8 @@ static void gen_custom_tables (void) void custom_init (void) { + uaecptr pos; + #ifdef OS_WITHOUT_MEMORY_MANAGEMENT int num; @@ -2829,6 +2865,18 @@ void custom_init (void) delay_changes = xmalloc (max_delay_change * sizeof (struct delay_change)); #endif + pos = here (); + + org (0xF0FF70); + calltrap (deftrap (mousehack_helper)); + dw (RTS); + + org (0xF0FFA0); + calltrap (deftrap (timehack_helper)); + dw (RTS); + + org (pos); + init_decisions (); gen_custom_tables (); @@ -2877,11 +2925,7 @@ uae_u32 REGPARAM2 custom_wget (uaecptr a case 0x01A: return DSKBYTR(); case 0x01C: return INTENAR(); case 0x01E: return INTREQR(); -#if AGA_CHIPSET == 1 - case 0x07C: return 0xF8; -#elif defined ECS_DENISE - case 0x07C: return 0xFC; -#endif + case 0x07C: return DENISEID(); default: custom_wput(addr,0); return 0xffff; @@ -2999,6 +3043,10 @@ void REGPARAM2 custom_wput_1 (int hpos, 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; @@ -3014,6 +3062,8 @@ void REGPARAM2 custom_wput_1 (int hpos, 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: @@ -3049,18 +3099,12 @@ void REGPARAM2 custom_wput_1 (int hpos, break; case 0x36: JOYTEST (value); break; -#if defined (ECS_AGNUS) || (AGA_CHIPSET == 1) - case 0x5A: BLTCON0L(value); break; + case 0x5A: BLTCON0L (value); break; case 0x5C: BLTSIZV (value); break; case 0x5E: BLTSIZH (value); break; -#endif -#ifdef ECS_DENISE case 0x1E4: DIWHIGH (hpos, value); break; -#endif -#if AGA_CHIPSET == 1 case 0x10C: BPLCON4 (hpos, value); break; - case 0x1FC: fmode = value; break; -#endif + case 0x1FC: FMODE (value); break; } } @@ -3076,13 +3120,13 @@ 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); - custom_wput(addr, rval); + custom_wput (addr, rval); if (!warned) write_log ("Byte put to custom register.\n"), warned++; } void REGPARAM2 custom_lput(uaecptr addr, uae_u32 value) { - custom_wput(addr & 0xfffe, value >> 16); - custom_wput((addr+2) & 0xfffe, (uae_u16)value); + custom_wput (addr & 0xfffe, value >> 16); + custom_wput ((addr + 2) & 0xfffe, (uae_u16)value); }