From 1a7afe84e1d2b562938d0f38281c969057e923a5 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 24 Sep 2022 20:22:28 +0300 Subject: [PATCH] Genlock emulation fixes and genlock_effects genlock manual feature enable. --- cfgfile.cpp | 71 +++++++++++++++++++++++++ custom.cpp | 10 ++-- drawing.cpp | 119 ++++++++++++++++++++++++++---------------- genlinetoscr.cpp | 39 +++++++------- include/options.h | 3 ++ od-win32/win32gfx.cpp | 2 +- specialmonitors.cpp | 2 +- 7 files changed, 177 insertions(+), 69 deletions(-) diff --git a/cfgfile.cpp b/cfgfile.cpp index a4600c35..97a3a27b 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -2429,6 +2429,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) cfgfile_dwrite_str (f, _T("waiting_blits"), waitblits[p->waiting_blits]); cfgfile_dwrite (f, _T("blitter_throttle"), _T("%.8f"), p->blitter_speed_throttle); cfgfile_write_bool (f, _T("ntsc"), p->ntscmode); + cfgfile_write_bool(f, _T("genlock"), p->genlock); cfgfile_dwrite_bool(f, _T("genlock_alpha"), p->genlock_alpha); cfgfile_dwrite_bool(f, _T("genlock_aspect"), p->genlock_aspect); @@ -2437,6 +2438,38 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type) cfgfile_dwrite_str(f, _T("genlock_video"), p->genlock_video_file); cfgfile_dwrite(f, _T("genlock_mix"), _T("%d"), p->genlock_mix); cfgfile_dwrite(f, _T("genlock_scale"), _T("%d"), p->genlock_scale); + if (p->genlock_effects) { + tmp[0] = 0; + if (p->genlock_effects & (1 << 4)) { + _tcscat(tmp, _T("brdntran")); + } + if (p->genlock_effects & (1 << 5)) { + if (tmp[0]) { + _tcscat(tmp, _T(",")); + } + _tcscat(tmp, _T("brdrblnk")); + } + for (int i = 0; i < 256; i++) { + uae_u64 v = p->ecs_genlock_features_colorkey_mask[i / 64]; + if (v & (1LL << (i & 63))) { + if (tmp[0]) { + _tcscat(tmp, _T(",")); + } + _stprintf(tmp + _tcslen(tmp), _T("%d"), i); + } + } + for (int i = 0; i < 8; i++) { + if (p->ecs_genlock_features_plane_mask & (1 << i)) { + if (tmp[0]) { + _tcscat(tmp, _T(",")); + } + _stprintf(tmp + _tcslen(tmp), _T("p%d"), i); + } + } + cfgfile_dwrite_str(f, _T("genlock_effects"), tmp); + } + + cfgfile_dwrite_str(f, _T("monitoremu"), specialmonitorconfignames[p->monitoremu]); cfgfile_dwrite(f, _T("monitoremu_monitor"), _T("%d"), p->monitoremu_mon); cfgfile_dwrite_coords(f, _T("lightpen_offset"), p->lightpen_offset[0], p->lightpen_offset[1]); @@ -6159,6 +6192,44 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH return 1; } + if (cfgfile_string(option, value, _T("genlock_effects"), tmpbuf, sizeof(tmpbuf) / sizeof(TCHAR))) { + TCHAR *s = tmpbuf; + TCHAR *endptr; + if (cfgfile_option_get(value, _T("brdntran"))) { + p->genlock_effects |= 1 << 4; + } + if (cfgfile_option_get(value, _T("brdrblnk"))) { + p->genlock_effects |= 1 << 5; + } + while (s && s[0]) { + TCHAR *tmpp = _tcschr (s, ','); + if (tmpp) { + *tmpp++ = 0; + } + int plane = 0; + if (s[0] == 'p' || s[0] == 'P') { + s++; + plane = 1; + } + int val = _tcstol(s, &endptr, 10); + if (val > 0 || (val == 0 && s[0] == '0')) { + if (plane == 1) { + p->ecs_genlock_features_plane_mask |= 1 << val; + p->genlock_effects |= 2; + } else { + for (int i = 0; i < 4 && val >= 0; i++, val -= 64) { + if (val < 64) { + p->ecs_genlock_features_colorkey_mask[i] |= 1LL << val; + p->genlock_effects |= 1; + } + } + } + } + s = tmpp; + } + return 1; + } + if (cfgfile_parse_filesys (p, option, value)) return 1; diff --git a/custom.cpp b/custom.cpp index 10449025..15e4e10e 100644 --- a/custom.cpp +++ b/custom.cpp @@ -4586,8 +4586,8 @@ static bool isbrdblank(int hpos, uae_u16 bplcon0, uae_u16 bplcon3) { bool brdblank, brdntrans, extblank; #ifdef ECS_DENISE - brdblank = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20); - brdntrans = ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x10); + brdblank = (ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x20)) || (currprefs.genlock_effects & (1 << 5)); + brdntrans = (ecs_denise && (bplcon0 & 1) && (bplcon3 & 0x10)) || (currprefs.genlock_effects & (1 << 4)); // ECSENA=0: hardwired horizontal, strobe vertical // ECSENA=1: EXTBLKEN=0: hardwired blanking, strobe vertical // ECSENA=1: EXTBLKEN=1: blanking equals HSYNC if VARCSYEN=1, blanking equals HBSTRT-HBSTOP if VARCSYEN=0, no vertical, AGA: programmed horizontal, strobe vertical @@ -6948,7 +6948,7 @@ STATIC_INLINE int islightpentriggered(void) } STATIC_INLINE int issyncstopped(void) { - return (bplcon0 & 2) && !currprefs.genlock; + return (bplcon0 & 2) && (!currprefs.genlock || currprefs.genlock_effects); } STATIC_INLINE int GETVPOS(void) @@ -6963,7 +6963,7 @@ STATIC_INLINE int GETHPOS(void) // fake changing hpos when rom genlock test runs and genlock is connected static bool hsyncdelay(void) { - if (!currprefs.genlock) { + if (!currprefs.genlock || currprefs.genlock_effects) { return false; } if (currprefs.cpu_memory_cycle_exact || currprefs.m68k_speed >= 0) { @@ -11098,7 +11098,7 @@ static void vsync_handler_post(void) genlockvtoggle = lof_store ? 1 : 0; } - if ((bplcon0 & 2) && !currprefs.genlock) { + if ((bplcon0 & 2) && (!currprefs.genlock || currprefs.genlock_effects)) { nosignal_trigger = true; } // Inverted CSYNC diff --git a/drawing.cpp b/drawing.cpp index 92a9ea6c..77138594 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -1429,6 +1429,67 @@ STATIC_INLINE uae_u32 merge_2pixel32 (uae_u32 p1, uae_u32 p2) return v; } +static bool get_genlock_very_rare_and_complex_case(uae_u8 v) +{ + if (ecs_genlock_features_colorkey) { + if (currprefs.genlock_effects) { + if (v < 64 && (currprefs.ecs_genlock_features_colorkey_mask[0] & (1LL << v))) { + return false; + } + if (v >= 64 && v < 128 && (currprefs.ecs_genlock_features_colorkey_mask[1] & (1LL << (v - 64)))) { + return false; + } + if (v >= 128 && v < 192 && (currprefs.ecs_genlock_features_colorkey_mask[2] & (1LL << (v - 128)))) { + return false; + } + if (v >= 192 && v < 256 && (currprefs.ecs_genlock_features_colorkey_mask[3] & (1LL << (v - 192)))) { + return false; + } + } else { + // color key match? + if (aga_mode) { + if (colors_for_drawing.color_regs_aga[v] & 0x80000000) + return false; + } else { + if (colors_for_drawing.color_regs_ecs[v] & 0x8000) + return false; + } + } + } + // plane mask match? + if (currprefs.genlock_effects) { + if (v & currprefs.ecs_genlock_features_plane_mask) + return false; + } else { + if (v & ecs_genlock_features_mask) + return false; + } + return true; +} +// false = transparent +STATIC_INLINE bool get_genlock_transparency(uae_u8 v) +{ + if (!ecs_genlock_features_active) { + if (v == 0) + return false; + return true; + } else { + return get_genlock_very_rare_and_complex_case(v); + } +} + +STATIC_INLINE bool get_genlock_transparency_border(void) +{ + if (!ecs_genlock_features_active) { + return false; + } else { + // border color with BRDNTRAN bit set = not transparent + if (ce_is_borderntrans(colors_for_drawing.extra)) + return true; + return get_genlock_very_rare_and_complex_case(0); + } +} + STATIC_INLINE void fill_line_16 (uae_u8 *buf, int start, int stop, int blank) { uae_u16 *b = (uae_u16 *)buf; @@ -1470,7 +1531,7 @@ static void pfield_do_fill_line (int start, int stop, int blank) case 4: fill_line_32 (xlinebuffer, start, stop, blank); break; } if (need_genlock_data) { - memset(xlinebuffer_genlock + start, 0, stop - start); + memset(xlinebuffer_genlock + start, get_genlock_transparency_border(), stop - start); } } @@ -1537,7 +1598,7 @@ static void fill_line_border(int lineno) hposblank = 3; fill_line2(lastpos, w); if (need_genlock_data) { - memset(xlinebuffer_genlock + lastpos, 0, w); + memset(xlinebuffer_genlock + lastpos, get_genlock_transparency_border(), w); } hposblank = b; return; @@ -1548,7 +1609,7 @@ static void fill_line_border(int lineno) hposblank = 3; fill_line2(lastpos, w); if (need_genlock_data) { - memset(xlinebuffer_genlock + lastpos, 0, w); + memset(xlinebuffer_genlock + lastpos, get_genlock_transparency_border(), w); } return; } @@ -1556,7 +1617,7 @@ static void fill_line_border(int lineno) if (hblank_left <= lastpos && hblank_right >= endpos) { fill_line2(lastpos, w); if (need_genlock_data) { - memset(xlinebuffer_genlock + lastpos, 0, w); + memset(xlinebuffer_genlock + lastpos, get_genlock_transparency_border(), w); } return; } @@ -1670,38 +1731,6 @@ static uae_u8 render_sprites(int pos, int dualpf, uae_u8 apixel, int aga) return 0; } -static bool get_genlock_very_rare_and_complex_case(uae_u8 v) -{ - // border color without BRDNTRAN bit set = transparent - if (v == 0 && !ce_is_borderntrans(colors_for_drawing.extra)) - return false; - if (ecs_genlock_features_colorkey) { - // color key match? - if (aga_mode) { - if (colors_for_drawing.color_regs_aga[v] & 0x80000000) - return false; - } else { - if (colors_for_drawing.color_regs_ecs[v] & 0x8000) - return false; - } - } - // plane mask match? - if (v & ecs_genlock_features_mask) - return false; - return true; -} -// false = transparent -STATIC_INLINE bool get_genlock_transparency(uae_u8 v) -{ - if (!ecs_genlock_features_active) { - if (v == 0) - return false; - return true; - } else { - return get_genlock_very_rare_and_complex_case(v); - } -} - #include "linetoscr.cpp" #define LTPARMS src_pixel, start, stop @@ -3282,14 +3311,16 @@ static void pfield_expand_dp_bplcon(void) sprite_smaller_than_64_inuse = true; sprite_smaller_than_64 = (dp_for_drawing->fmode & 0x0c) != 0x0c; #endif - ecs_genlock_features_active = ecs_denise && ((dp_for_drawing->bplcon2 & 0x0c00) || ce_is_borderntrans(colors_for_drawing.extra)) ? 1 : 0; + ecs_genlock_features_active = (ecs_denise && ((dp_for_drawing->bplcon2 & 0x0c00) || ce_is_borderntrans(colors_for_drawing.extra))) || (currprefs.genlock_effects ? 1 : 0); if (ecs_genlock_features_active) { - ecs_genlock_features_colorkey = false; - ecs_genlock_features_mask = 0; - if (dp_for_drawing->bplcon3 & 0x0800) { - ecs_genlock_features_mask = 1 << ((dp_for_drawing->bplcon2 >> 12) & 7); - } - if (dp_for_drawing->bplcon3 & 0x0400) { + uae_u16 bc2 = dp_for_drawing->bplcon2; + ecs_genlock_features_colorkey = currprefs.ecs_genlock_features_colorkey_mask[0] || currprefs.ecs_genlock_features_colorkey_mask[1] || + currprefs.ecs_genlock_features_colorkey_mask[2] || currprefs.ecs_genlock_features_colorkey_mask[3]; + ecs_genlock_features_mask = currprefs.ecs_genlock_features_plane_mask; + if (bc2 & 0x0800) { + ecs_genlock_features_mask = 1 << ((bc2 >> 12) & 7); + } + if (bc2 & 0x0400) { ecs_genlock_features_colorkey = true; } } @@ -4741,7 +4772,7 @@ static void finish_drawing_frame(bool drawlines) } // genlock - if (currprefs.genlock_image && currprefs.genlock && !currprefs.monitoremu && vidinfo->tempbuffer.bufmem_allocated) { + if (currprefs.genlock_image && (currprefs.genlock || currprefs.genlock_effects) && !currprefs.monitoremu && vidinfo->tempbuffer.bufmem_allocated) { setspecialmonitorpos(&vidinfo->tempbuffer); if (init_genlock_data != specialmonitor_need_genlock()) { need_genlock_data = init_genlock_data = specialmonitor_need_genlock(); diff --git a/genlinetoscr.cpp b/genlinetoscr.cpp index 28923be5..cfbf3fa2 100644 --- a/genlinetoscr.cpp +++ b/genlinetoscr.cpp @@ -243,12 +243,14 @@ static void out_linetoscr_do_incspix (DEPTH_T bpp, HMODE_T hmode, int aga, CMODE } } -static void put_dpixsprgenlock(int offset, int genlock) +static void put_dpixsprgenlock(int offset, int genlock, bool subpixel) { if (!genlock) return; - if (offset) - outlnf(" genlock_buf[dpix + %d] = get_genlock_transparency(sprcol);", offset); + if (offset && subpixel) + outlnf(" genlock_buf[dpix + %d] = get_genlock_transparency(sprcol);\n", offset); + else if (offset && !subpixel) + outlnf(" genlock_buf[dpix + %d] = genlock_buf[dpix];\n", offset); else outlnf(" genlock_buf[dpix] = get_genlock_transparency(sprcol);"); } @@ -258,12 +260,10 @@ static void put_dpixgenlock(int offset, CMODE_T cmode, int aga, int genlock, con if (!genlock) return; outindent(); - if (offset) - outf(" genlock_buf[dpix + %d] = get_genlock_transparency(", offset); - else + if (offset) { + outf(" genlock_buf[dpix + %d] = genlock_buf[dpix];\n", offset); + } else { outf(" genlock_buf[dpix] = get_genlock_transparency("); - - if (genlock) { if (cmode == CMODE_EXTRAHB) { outf("%s", var2 ? var2 : "spix_val & 31"); } @@ -281,8 +281,8 @@ static void put_dpixgenlock(int offset, CMODE_T cmode, int aga, int genlock, con else { outf("%s", var2 ? var2 : "spix_val"); } + outf(");\n"); } - outf(");\n"); } static void put_dpix (const char *var) @@ -298,7 +298,7 @@ static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga); outlnf(" if (sprcol) {"); outlnf ( " out_val = p_acolors[sprcol];"); - put_dpixsprgenlock(0, genlock); + put_dpixsprgenlock(0, genlock, true); outlnf(" }"); outlnf(" }"); put_dpix("out_val"); @@ -310,14 +310,14 @@ static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga); outlnf ( " if (sprcol) {"); outlnf ( " out_val1 = p_acolors[sprcol];"); - put_dpixsprgenlock(0, genlock); + put_dpixsprgenlock(0, genlock, true); outlnf(" }"); outlnf(" }"); outlnf ( " if (spritepixels[dpix + 1].data) {"); outlnf ( " sprcol = render_sprites (dpix + 1, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga); outlnf ( " if (sprcol) {"); outlnf ( " out_val2 = p_acolors[sprcol];"); - put_dpixsprgenlock(1, genlock); + put_dpixsprgenlock(1, genlock, true); outlnf(" }"); outlnf(" }"); put_dpix("out_val1"); @@ -333,28 +333,28 @@ static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int outlnf ( " sprcol = render_sprites (dpix + 0, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga); outlnf ( " if (sprcol) {"); outlnf ( " out_val1 = p_acolors[sprcol];"); - put_dpixsprgenlock(0, genlock); + put_dpixsprgenlock(0, genlock, true); outlnf(" }"); outlnf(" }"); outlnf ( " if (spritepixels[dpix + 1].data) {"); outlnf ( " sprcol = render_sprites (dpix + 1, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga); outlnf ( " if (sprcol) {"); outlnf ( " out_val2 = p_acolors[sprcol];"); - put_dpixsprgenlock(1, genlock); + put_dpixsprgenlock(1, genlock, true); outlnf(" }"); outlnf(" }"); outlnf ( " if (spritepixels[dpix + 2].data) {"); outlnf ( " sprcol = render_sprites (dpix + 2, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga); outlnf ( " if (sprcol) {"); outlnf ( " out_val3 = p_acolors[sprcol];"); - put_dpixsprgenlock(2, genlock); + put_dpixsprgenlock(2, genlock, true); outlnf(" }"); outlnf(" }"); outlnf ( " if (spritepixels[dpix + 3].data) {"); outlnf ( " sprcol = render_sprites (dpix + 3, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga); outlnf ( " if (sprcol) {"); outlnf ( " out_val4 = p_acolors[sprcol];"); - put_dpixsprgenlock(3, genlock); + put_dpixsprgenlock(3, genlock, true); outlnf(" }"); outlnf(" }"); put_dpix("out_val1"); @@ -366,14 +366,17 @@ static void out_sprite (DEPTH_T bpp, HMODE_T hmode, CMODE_T cmode, int aga, int } else { outlnf ( " if (spritepixels[dpix].data) {"); outlnf ( " sprcol = render_sprites (dpix, %d, sprpix_val, %d);", cmode == CMODE_DUALPF ? 1 : 0, aga); - put_dpixsprgenlock(0, genlock); outlnf(" if (sprcol) {"); outlnf ( " uae_u32 spcol = p_acolors[sprcol];"); outlnf ( " out_val = spcol;"); + for (int i = 0; i < cnt; i++) { + put_dpixsprgenlock(i, genlock, false); + } outlnf ( " }"); outlnf ( " }"); - while (cnt-- > 0) + for (int i = 0; i < cnt; i++) { put_dpix("out_val"); + } } } diff --git a/include/options.h b/include/options.h index 95bf1c1b..2704cbb5 100644 --- a/include/options.h +++ b/include/options.h @@ -601,6 +601,9 @@ struct uae_prefs { int genlock_mix; int genlock_scale; int genlock_aspect; + int genlock_effects; + uae_u64 ecs_genlock_features_colorkey_mask[4]; + uae_u8 ecs_genlock_features_plane_mask; bool genlock_alpha; TCHAR genlock_image_file[MAX_DPATH]; TCHAR genlock_video_file[MAX_DPATH]; diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index b58026ea..5753925f 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -3954,7 +3954,7 @@ retry: allocsoftbuffer(mon->monitor_id, _T("draw"), &avidinfo->drawbuffer, mon->currentmode.flags, 1920, 1280, mon->currentmode.current_depth); - if (currprefs.monitoremu || currprefs.cs_cd32fmv || (currprefs.genlock && currprefs.genlock_image) || currprefs.cs_color_burst || currprefs.gfx_grayscale) { + if (currprefs.monitoremu || currprefs.cs_cd32fmv || ((currprefs.genlock || currprefs.genlock_effects) && currprefs.genlock_image) || currprefs.cs_color_burst || currprefs.gfx_grayscale) { allocsoftbuffer(mon->monitor_id, _T("monemu"), &avidinfo->tempbuffer, mon->currentmode.flags, mon->currentmode.amiga_width > 1024 ? mon->currentmode.amiga_width : 1024, mon->currentmode.amiga_height > 1024 ? mon->currentmode.amiga_height : 1024, diff --git a/specialmonitors.cpp b/specialmonitors.cpp index 3ed0c85d..2feba598 100755 --- a/specialmonitors.cpp +++ b/specialmonitors.cpp @@ -3626,7 +3626,7 @@ bool specialmonitor_need_genlock(void) case MONITOREMU_COLORBURST: return true; } - if (currprefs.genlock_image && currprefs.genlock) + if (currprefs.genlock_image && (currprefs.genlock || currprefs.genlock_effects)) return true; return false; } -- 2.47.3