From 4cfef2adb3a2a0404c4ded6e97e6d3612ebc3a8d Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 17 Mar 2013 17:29:32 +0200 Subject: [PATCH] 2600b12 --- blitter.cpp | 10 ++- custom.cpp | 24 ++++++- drawing.cpp | 128 ++++++++++++++++------------------- gencpu.cpp | 21 ++---- include/drawing.h | 3 +- include/newcpu.h | 1 + main.cpp | 1 + memory.cpp | 5 +- newcpu.cpp | 28 +++++++- od-win32/win32.h | 4 +- od-win32/win32gfx.cpp | 5 +- od-win32/win32gui.cpp | 2 +- od-win32/winuaechangelog.txt | 13 ++++ 13 files changed, 150 insertions(+), 95 deletions(-) diff --git a/blitter.cpp b/blitter.cpp index f50d4789..9e33273c 100644 --- a/blitter.cpp +++ b/blitter.cpp @@ -354,7 +354,7 @@ static void blitter_done (int hpos) record_dma_event (DMA_EVENT_BLITFINISHED, hpos, vpos); event2_remevent (ev2_blitter); unset_special (SPCFLAG_BLTNASTY); - if (log_blitter) + if (log_blitter & 1) write_log (_T("cycles %d, missed %d, total %d\n"), blit_totalcyclecounter, blit_misscyclecounter, blit_totalcyclecounter + blit_misscyclecounter); } @@ -1083,6 +1083,12 @@ void decide_blitter (int hpos) } blitter_nasty++; + + if (v <= 0) { + blit_misscyclecounter++; + break; + } + blt_info.got_cycle = 1; if (c == 4) { blitter_doddma (last_blitter_hpos); @@ -1365,7 +1371,7 @@ static void do_blitter2 (int hpos, int copper) original_line = blitline; } - if (log_blitter) { + if (log_blitter & 1) { blitter_dontdo = 0; if (1) { int ch = 0; diff --git a/custom.cpp b/custom.cpp index 11cfdb8f..a634092f 100644 --- a/custom.cpp +++ b/custom.cpp @@ -2073,13 +2073,32 @@ static bool isbrdblank (int hpos, uae_u16 bplcon0, uae_u16 bplcon3) brdblank = false; #endif if (hpos >= 0 && current_colors.borderblank != brdblank) { - record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0)); + record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (brdblank ? 1 : 0) | (current_colors.bordersprite ? 2 : 0)); current_colors.borderblank = brdblank; remembered_color_entry = -1; } return brdblank; } + +static bool issprbrd (int hpos, uae_u16 bplcon0, uae_u16 bplcon3) +{ + bool brdsprt; +#ifdef AGA + brdsprt = (currprefs.chipset_mask & CSMASK_AGA) && (bplcon0 & 1) && (bplcon3 & 0x02); +#else + brdsprt = false; +#endif + if (hpos >= 0 && current_colors.bordersprite != brdsprt) { + record_color_change (hpos, 0, COLOR_CHANGE_BRDBLANK | (current_colors.borderblank ? 1 : 0) | (brdsprt ? 2 : 0)); + current_colors.bordersprite = brdsprt; + remembered_color_entry = -1; + if (brdsprt) + thisline_decision.bordersprite_seen = true; + } + return brdsprt; +} + static void record_register_change (int hpos, int regno, uae_u16 value) { if (regno == 0x100) { // BPLCON0 @@ -2087,10 +2106,12 @@ static void record_register_change (int hpos, int regno, uae_u16 value) thisline_decision.ham_seen = 1; thisline_decision.ehb_seen = isehb (value, bplcon2); isbrdblank (hpos, value, bplcon3); + issprbrd (hpos, value, bplcon3); } else if (regno == 0x104) { // BPLCON2 thisline_decision.ehb_seen = isehb (bplcon0, value); } else if (regno == 0x106) { // BPLCON3 isbrdblank (hpos, bplcon0, value); + issprbrd (hpos, bplcon0, value); } record_color_change (hpos, regno + 0x1000, value); } @@ -2747,6 +2768,7 @@ static void reset_decisions (void) thisline_decision.ham_seen = !! (bplcon0 & 0x800); thisline_decision.ehb_seen = !! isehb (bplcon0, bplcon2); thisline_decision.ham_at_start = !! (bplcon0 & 0x800); + thisline_decision.bordersprite_seen = issprbrd (-1, bplcon0, bplcon3); /* decided_res shouldn't be touched before it's initialized by decide_line(). */ thisline_decision.diwfirstword = -1; diff --git a/drawing.cpp b/drawing.cpp index 85db2425..9537eeee 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -195,6 +195,8 @@ int visible_left_border, visible_right_border; /* Pixels outside of visible_start and visible_stop are always black */ static int visible_left_start, visible_right_stop; static int visible_top_start, visible_bottom_stop; +/* same for hblank */ +static int hblank_left_start, hblank_right_stop; static int linetoscr_x_adjust_bytes; static int thisframe_y_adjust; @@ -220,7 +222,6 @@ static int bplres; static int plf1pri, plf2pri, bplxor; static uae_u32 plf_sprite_mask; static int sbasecol[2] = { 16, 16 }; -static bool brdsprt, brdblank; static int hposblank; static bool specialmonitoron; @@ -376,6 +377,19 @@ static void reset_custom_limits (void) gclorealh = -1; } +static void set_blanking_limits (void) +{ + hblank_left_start = visible_left_start; + hblank_right_stop = visible_right_stop; + + if (programmedmode) { + if (hblank_left_start < coord_hw_to_window_x (hsyncendpos * 2)) + hblank_left_start = coord_hw_to_window_x (hsyncendpos * 2); + if (hblank_right_stop > coord_hw_to_window_x (hsyncstartpos * 2)) + hblank_right_stop = coord_hw_to_window_x (hsyncstartpos * 2); + } +} + void set_custom_limits (int w, int h, int dx, int dy) { int vls = visible_left_start; @@ -400,6 +414,7 @@ void set_custom_limits (int w, int h, int dx, int dy) if (vls != visible_left_start || vrs != visible_right_stop || vts != visible_top_start || vbs != visible_bottom_stop) notice_screen_contents_lost (); + set_blanking_limits (); } int get_custom_limits (int *pw, int *ph, int *pdx, int *pdy, int *prealh) @@ -679,7 +694,7 @@ STATIC_INLINE xcolnr getbgc (bool blank) return xcolors[0x0f0]; else if (hposblank == 3) return xcolors[0x00f]; - else if (brdblank) + else if ( colors_for_drawing.borderblank) return xcolors[0x880]; //return colors_for_drawing.acolors[0]; return xcolors[0xf0f]; @@ -705,26 +720,16 @@ static void pfield_init_linetoscr (void) res_shift = lores_shift - bplres; - if (dip_for_drawing->nr_sprites == 0) { - if (linetoscr_diw_start < native_ddf_left) - linetoscr_diw_start = native_ddf_left; - if (linetoscr_diw_end > native_ddf_right) - linetoscr_diw_end = native_ddf_right; - } - /* Perverse cases happen. */ if (linetoscr_diw_end < linetoscr_diw_start) linetoscr_diw_end = linetoscr_diw_start; playfield_start = linetoscr_diw_start; playfield_end = linetoscr_diw_end; - - if (beamcon0 & 0x80) { - if (playfield_start < coord_hw_to_window_x (hsyncendpos * 2 + DIW_DDF_OFFSET)) - playfield_start = coord_hw_to_window_x (hsyncendpos * 2 + DIW_DDF_OFFSET); - if (playfield_end > coord_hw_to_window_x (hsyncstartpos * 2 + DIW_DDF_OFFSET)) - playfield_end = coord_hw_to_window_x (hsyncstartpos * 2 + DIW_DDF_OFFSET); - } + if (playfield_start < native_ddf_left) + playfield_start = native_ddf_left; + if (playfield_end > native_ddf_right) + playfield_end = native_ddf_right; unpainted = visible_left_border < playfield_start ? 0 : visible_left_border - playfield_start; ham_src_pixel = MAX_PIXELS_PER_LINE + res_shift_from_window (playfield_start - native_ddf_left); @@ -741,8 +746,9 @@ static void pfield_init_linetoscr (void) real_playfield_end = playfield_end; real_playfield_start = playfield_start; + #ifdef AGA - if (brdsprt && dip_for_drawing->nr_sprites) { + if (dp_for_drawing->bordersprite_seen && dip_for_drawing->nr_sprites) { int min = visible_right_border, max = visible_left_border, i; for (i = 0; i < dip_for_drawing->nr_sprites; i++) { int x; @@ -755,12 +761,7 @@ static void pfield_init_linetoscr (void) } min = coord_hw_to_window_x (min >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift); max = coord_hw_to_window_x (max >> sprite_buffer_res) + (DIW_DDF_OFFSET << lores_shift); - if (beamcon0 & 0x80) { - if (min < coord_hw_to_window_x (hsyncendpos * 2 + DIW_DDF_OFFSET)) - min = coord_hw_to_window_x (hsyncendpos * 2 + DIW_DDF_OFFSET); - if (min > coord_hw_to_window_x (hsyncstartpos * 2 + DIW_DDF_OFFSET)) - min = coord_hw_to_window_x (hsyncstartpos * 2 + DIW_DDF_OFFSET); - } + if (min < playfield_start) playfield_start = min; if (playfield_start < visible_left_border) @@ -852,30 +853,13 @@ STATIC_INLINE void fill_line_32 (uae_u8 *buf, int start, int stop, bool blank) for (i = start; i < stop; i++) b[i] = col; } -static void pfield_do_fill_line2 (int start, int stop, bool blank) +static void pfield_do_fill_line (int start, int stop, bool blank) { switch (gfxvidinfo.drawbuffer.pixbytes) { case 2: fill_line_16 (xlinebuffer, start, stop, blank); break; case 4: fill_line_32 (xlinebuffer, start, stop, blank); break; } } -static void pfield_do_fill_line (int start, int stop, bool blank) -{ - xlinecheck(start, stop); - if (!blank) { - if (start < visible_left_start) { - pfield_do_fill_line2 (start, visible_left_start, true); - start = visible_left_start; - } - if (stop > visible_right_stop) { - pfield_do_fill_line2 (start, visible_right_stop, false); - blank = true; - start = visible_right_stop; - } - } - pfield_do_fill_line2 (start, stop, blank); -} - STATIC_INLINE void fill_line2 (int startpos, int len) { @@ -1920,6 +1904,7 @@ void init_aspect_maps (void) visible_right_stop = MAX_STOP; visible_top_start = 0; visible_bottom_stop = MAX_STOP; + set_blanking_limits (); } /* @@ -2009,7 +1994,6 @@ static void pfield_expand_dp_bplcon (void) bpldualpf2of = (dp_for_drawing->bplcon3 >> 10) & 7; sbasecol[0] = ((dp_for_drawing->bplcon4 >> 4) & 15) << 4; sbasecol[1] = ((dp_for_drawing->bplcon4 >> 0) & 15) << 4; - brdsprt = !brdblank && (currprefs.chipset_mask & CSMASK_AGA) && (dp_for_drawing->bplcon0 & 1) && (dp_for_drawing->bplcon3 & 0x02); bplxor = dp_for_drawing->bplcon4 >> 8; #endif } @@ -2110,28 +2094,37 @@ static void do_color_changes (line_draw_func worker_border, line_draw_func worke if (nextpos > endpos) nextpos_in_range = endpos; - if (nextpos_in_range > lastpos) { - if (lastpos < playfield_start) { - int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; - (*worker_border) (lastpos, t, false); - lastpos = t; - } + // left hblank (left edge to hblank end) + if (nextpos_in_range > lastpos && lastpos < hblank_left_start) { + int t = nextpos_in_range <= hblank_left_start ? nextpos_in_range : hblank_left_start; + (*worker_border) (lastpos, t, true); + lastpos = t; } - if (nextpos_in_range > lastpos) { - if (lastpos >= playfield_start && lastpos < playfield_end) { - int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; - (*worker_pfield) (lastpos, t, false); - /* blank start and end that shouldn't be visible */ - if (lastpos < visible_left_start) - (*worker_border) (lastpos, visible_left_start, true); - if (t > visible_right_stop) - (*worker_border) (visible_right_stop, endpos, true); - lastpos = t; - } + + // left border (hblank end to playfield start) + if (nextpos_in_range > lastpos && lastpos < playfield_start) { + int t = nextpos_in_range <= playfield_start ? nextpos_in_range : playfield_start; + (*worker_border) (lastpos, t, false); + lastpos = t; + } + + // playfield + if (nextpos_in_range > lastpos && lastpos >= playfield_start && lastpos < playfield_end) { + int t = nextpos_in_range <= playfield_end ? nextpos_in_range : playfield_end; + (*worker_pfield) (lastpos, t, false); + lastpos = t; } - if (nextpos_in_range > lastpos) { - if (lastpos >= playfield_end) - (*worker_border) (lastpos, nextpos_in_range, false); + + // right border (playfield end to hblank start) + if (nextpos_in_range > lastpos && lastpos >= playfield_end) { + int t = nextpos_in_range <= hblank_right_stop ? nextpos_in_range : hblank_right_stop; + (*worker_border) (lastpos, t, false); + lastpos = t; + } + + // right hblank (hblank start to right edge, hblank start may be earlier than playfield end) + if (nextpos_in_range > hblank_right_stop) { + (*worker_border) (hblank_right_stop, nextpos_in_range, true); lastpos = nextpos_in_range; } @@ -2140,6 +2133,7 @@ static void do_color_changes (line_draw_func worker_border, line_draw_func worke } else if (regno >= 0) { if (regno == 0 && (value & COLOR_CHANGE_BRDBLANK)) { colors_for_drawing.borderblank = (value & 1) != 0; + colors_for_drawing.bordersprite = (value & 2) != 0; } else { color_reg_set (&colors_for_drawing, regno, value); colors_for_drawing.acolors[regno] = getxcolor (value); @@ -2252,7 +2246,7 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in if (dip_for_drawing->nr_sprites) { int i; #ifdef AGA - if (brdsprt) + if (dp_for_drawing->bordersprite_seen) clear_bitplane_border_aga (); #endif for (i = 0; i < dip_for_drawing->nr_sprites; i++) { @@ -2280,13 +2274,13 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in } } else if (border == 1) { - int dosprites = 0; + bool dosprites = false; adjust_drawing_colors (dp_for_drawing->ctable, 0); #ifdef AGA /* this makes things complex.. */ - if (brdsprt && dip_for_drawing->nr_sprites > 0) { - dosprites = 1; + if (dp_for_drawing->bordersprite_seen && dip_for_drawing->nr_sprites > 0) { + dosprites = true; pfield_expand_dp_bplcon (); pfield_init_linetoscr (); memset (pixdata.apixels + MAX_PIXELS_PER_LINE, colors_for_drawing.borderblank ? 0 : colors_for_drawing.acolors[0], MAX_PIXELS_PER_LINE); @@ -2309,7 +2303,6 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in return; } - if (dosprites) { int i; @@ -2344,7 +2337,6 @@ static void pfield_draw_line (struct vidbuffer *vb, int lineno, int gfx_ypos, in } else { int tmp = hposblank; - //hposblank = brdblank; hposblank = colors_for_drawing.borderblank; fill_line (); do_flush_line (vb, gfx_ypos); diff --git a/gencpu.cpp b/gencpu.cpp index 86751bc7..7604adf7 100644 --- a/gencpu.cpp +++ b/gencpu.cpp @@ -2919,13 +2919,8 @@ static void gen_opcode (unsigned long int opcode) genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0); printf ("\tCLEAR_CZNV ();\n"); printf ("\tif (src == 0) {\n"); - if (cpu_level > 0) { - /* 68020 sets V when dividing by zero and N if dst is negative - * 68000 clears both - */ - printf("\t\tSET_VFLG (1);\n"); - printf("\t\tif (dst < 0) SET_NFLG (1);\n"); - } + if (cpu_level > 0) + printf ("\t\tdivbyzero_special (0, dst);\n"); incpc ("%d", m68k_pc_offset); printf ("\t\tException (5);\n"); printf ("\t\tgoto %s;\n", endlabelstr); @@ -2964,22 +2959,16 @@ static void gen_opcode (unsigned long int opcode) case i_DIVS: genamode (curi->smode, "srcreg", sz_word, "src", 1, 0, 0); genamode (curi->dmode, "dstreg", sz_long, "dst", 1, 0, 0); - printf ("\tCLEAR_CZNV ();\n"); printf ("\tif (src == 0) {\n"); - if (cpu_level > 0) { - /* 68000 Set Z. Clear N, V, C. - * 68020 Set V, Z. Clear C and N. Keep X. - * 68060 Clear C, everything else is kept. - */ - printf("\t\tSET_VFLG (1);\n"); - printf("\t\tSET_ZFLG (1);\n"); - } + if (cpu_level > 0) + printf ("\t\tdivbyzero_special (1, dst);\n"); incpc ("%d", m68k_pc_offset); printf ("\t\tException (5);\n"); printf ("\t\tgoto %s;\n", endlabelstr); printf ("\t} else {\n"); printf ("\t\tuae_s32 newv = (uae_s32)dst / (uae_s32)(uae_s16)src;\n"); printf ("\t\tuae_u16 rem = (uae_s32)dst %% (uae_s32)(uae_s16)src;\n"); + printf ("\t\tCLEAR_CZNV ();\n"); fill_prefetch_next (); if (using_ce) { start_brace (); diff --git a/include/drawing.h b/include/drawing.h index 86147878..df3367c2 100644 --- a/include/drawing.h +++ b/include/drawing.h @@ -85,7 +85,7 @@ struct color_entry { xcolnr acolors[256]; uae_u32 color_regs_aga[256]; #endif - bool borderblank; + bool borderblank, bordersprite; }; #ifdef AGA @@ -233,6 +233,7 @@ struct decision { bool ehb_seen; bool ham_seen; bool ham_at_start; + bool bordersprite_seen; }; /* Anything related to changes in hw registers during the DDF for one diff --git a/include/newcpu.h b/include/newcpu.h index 7605321a..31957fb0 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -412,6 +412,7 @@ extern void m68k_dumpstate (uaecptr, uaecptr *); extern void m68k_reset (int); extern int getDivu68kCycles (uae_u32 dividend, uae_u16 divisor); extern int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor); +extern void divbyzero_special (bool issigned, uae_s32 dst); extern void m68k_do_rte (void); extern void protect_roms (bool); extern void unprotect_maprom (void); diff --git a/main.cpp b/main.cpp index 942e1373..646ca62d 100644 --- a/main.cpp +++ b/main.cpp @@ -166,6 +166,7 @@ void fixup_prefs_dimensions (struct uae_prefs *prefs) for (int i = 0; i < 2; i++) { struct apmode *ap = &prefs->gfx_apmode[i]; ap->gfx_vflip = 0; + ap->gfx_strobo = false; if (ap->gfx_vsync) { if (ap->gfx_vsyncmode) { // low latency vsync: no flip only if no-buffer diff --git a/memory.cpp b/memory.cpp index c3a690e0..261f432f 100644 --- a/memory.cpp +++ b/memory.cpp @@ -1246,9 +1246,10 @@ uae_u8 *REGPARAM2 default_xlate (uaecptr a) uaecptr a2 = a - 32; uaecptr a3 = m68k_getpc () - 32; write_log (_T("Your Amiga program just did something terribly stupid %08X PC=%08X\n"), a, M68K_GETPC); - if (debugging || DEBUG_STUPID) + if (debugging || DEBUG_STUPID) { activate_debugger (); - m68k_dumpstate (0); + m68k_dumpstate (0); + } for (i = 0; i < 10; i++) { write_log (_T("%08X "), i >= 5 ? a3 : a2); for (j = 0; j < 16; j += 2) { diff --git a/newcpu.cpp b/newcpu.cpp index dd352a25..c6aaf05f 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -4292,12 +4292,14 @@ void cpu_halt (int id) regs.halted = id; gui_data.cpu_halted = true; gui_led (LED_CPU, 0); + regs.intmask = 7; + MakeSR (); } while (regs.halted) { x_do_cycles (8 * CYCLE_UNIT); cpu_cycles = adjust_cycles (cpu_cycles); if (regs.spcflags) { - if (do_specialties (cpu_cycles)) + if ((regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE))) return; } } @@ -6095,6 +6097,30 @@ int getDivs68kCycles (uae_s32 dividend, uae_s16 divisor) return mcycles * 2; } +/* 68000 Z=1. NVC=0 + * 68020 Signed: Z=1 NVC=0. Unsigned: V=1 N= 68040) { + SET_CFLG (0); + } else { + // 68000/010 + CLEAR_CZNV (); + } +} + STATIC_INLINE void fill_cache040 (uae_u32 addr) { int index, i, lws; diff --git a/od-win32/win32.h b/od-win32/win32.h index 1dff30be..3c80a758 100644 --- a/od-win32/win32.h +++ b/od-win32/win32.h @@ -19,11 +19,11 @@ #define LANG_DLL 1 #if WINUAEPUBLICBETA -#define WINUAEBETA _T("11") +#define WINUAEBETA _T("12") #else #define WINUAEBETA _T("") #endif -#define WINUAEDATE MAKEBD(2013, 3, 16) +#define WINUAEDATE MAKEBD(2013, 3, 17) #define WINUAEEXTRA _T("") //#define WINUAEEXTRA _T("AmiKit Preview") #define WINUAEREV _T("") diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index 2bcbaa6e..d1959046 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -3101,7 +3101,10 @@ static unsigned int __stdcall vblankthread (void *dummy) vblankthread_oddeven = (vp & 1) != 0; } if (!doflipped && ap->gfx_vflip > 0) { - doflipevent (1 | 2); + int flag = 1; + if (ap->gfx_strobo && vblank_skipeveryother) + flag |= 2; + doflipevent (flag); doflipped = true; } ok = vblank_getstate (&vb, &vp); diff --git a/od-win32/win32gui.cpp b/od-win32/win32gui.cpp index 1814c791..e13ce16c 100644 --- a/od-win32/win32gui.cpp +++ b/od-win32/win32gui.cpp @@ -3615,7 +3615,7 @@ struct miscentry { int type; int canactive; - TCHAR *name; + const TCHAR *name; bool *b; int *i; int ival, imask; diff --git a/od-win32/winuaechangelog.txt b/od-win32/winuaechangelog.txt index 6b23ca33..95e08759 100644 --- a/od-win32/winuaechangelog.txt +++ b/od-win32/winuaechangelog.txt @@ -1,6 +1,19 @@ - restore only single input target to default. +Beta 12: + +- AGA border sprite feature emulation is now also cycle-exact. Similar update to borderblank was done in 2.5.0. For example + it was possible that sprites were hidden when border sprite bit was set and zero bit planes enabled. + (Noticed when doing some unrelated real hardware limit tests) +- Black frame insertion was incorrectly used (if enabled) in <100Hz fastest possible CPU modes. +- Horizontal blanking rewritten, should be more accurate now, programmed display modes only. +- Display emulation tweak, Super72 sprite display corruption is gone. +- Fixed bug introduced in b5, blitter emulation ignored DMA off state in cycle exact mode. +- Emulate DIV divide by zero undocumented flags when CPU >=68020. So far 68020 and 68060 tested and confirmed. + Odyssey / Alcatraz and 68020+ CPU does not anymore get stuck in part where spaceship flies above ground. +- CPU halted state didn't disable CPU interrupts. + Beta 11: - Blank left and right border if programmed mode and part of original borders would be outside of programmed hsync start and end period. -- 2.47.3