From 0528cb5edfd84df14443be5dd9479947401781e8 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sat, 10 Feb 2024 18:51:49 +0200 Subject: [PATCH] Genlock positioning/scaling fixes. Manual offset config entries added. --- cfgfile.cpp | 6 ++++ custom.cpp | 15 ++++++++++ include/custom.h | 1 + include/options.h | 2 ++ include/videograb.h | 2 ++ od-win32/win32_videograb.cpp | 56 ++++++++++++++++++++++++++++++++---- od-win32/win32gfx.cpp | 4 +++ specialmonitors.cpp | 50 +++++++++++++++++++++++--------- 8 files changed, 117 insertions(+), 19 deletions(-) diff --git a/cfgfile.cpp b/cfgfile.cpp index 8b84fc8a..d76d1e76 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -2563,6 +2563,8 @@ 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); + cfgfile_dwrite(f, _T("genlock_offset_x"), _T("%d"), p->genlock_offset_x); + cfgfile_dwrite(f, _T("genlock_offset_y"), _T("%d"), p->genlock_offset_y); if (p->genlock_effects) { tmp[0] = 0; if (p->genlock_effects & (1 << 4)) { @@ -5967,6 +5969,8 @@ static int cfgfile_parse_hardware (struct uae_prefs *p, const TCHAR *option, TCH || cfgfile_intval(option, value, _T("monitoremu_monitor"), &p->monitoremu_mon, 1) || cfgfile_intval(option, value, _T("genlock_scale"), &p->genlock_scale, 1) || cfgfile_intval(option, value, _T("genlock_mix"), &p->genlock_mix, 1) + || cfgfile_intval(option, value, _T("genlock_offset_x"), &p->genlock_offset_x, 1) + || cfgfile_intval(option, value, _T("genlock_offset_y"), &p->genlock_offset_y, 1) || cfgfile_intval(option, value, _T("keyboard_handshake"), &p->cs_kbhandshake, 1) || cfgfile_intval(option, value, _T("eclockphase"), &p->cs_eclockphase, 1) || cfgfile_intval(option, value, _T("chipset_rtc_adjust"), &p->cs_rtc_adjust, 1) @@ -8579,6 +8583,8 @@ void default_prefs (struct uae_prefs *p, bool reset, int type) p->genlock = 0; p->genlock_image = 0; p->genlock_mix = 0; + p->genlock_offset_x = 0; + p->genlock_offset_y = 0; p->ntscmode = 0; p->filesys_limit = 0; p->filesys_max_name = 107; diff --git a/custom.cpp b/custom.cpp index d9d24fa5..c81a74c8 100644 --- a/custom.cpp +++ b/custom.cpp @@ -7785,6 +7785,21 @@ static void check_line_enabled(void) line_disabled |= custom_disabled ? 2 : 0; } +void get_mode_blanking_limits(int *phbstop, int *phbstrt, int *pvbstop, int *pvbstrt) +{ + if (new_beamcon0 & BEAMCON0_VARVBEN) { + *pvbstop = vbstop; + *pvbstrt = vbstrt; + *phbstop = hbstop_v; + *phbstrt = hbstrt_v; + } else { + *pvbstop = hardwired_vbstop; + *pvbstrt = hardwired_vbstrt; + *phbstop = (47 << CCK_SHRES_SHIFT) - 7; + *phbstrt = ((maxhpos_short + 8) << CCK_SHRES_SHIFT) - 3; + } +} + static void vb_check(void) { check_line_enabled(); diff --git a/include/custom.h b/include/custom.h index 4ba4b806..8651a6f3 100644 --- a/include/custom.h +++ b/include/custom.h @@ -254,6 +254,7 @@ void custom_cpuchange(void); bool bitplane_dma_access(int hpos, int offset); void custom_dumpstate(int); bool get_ras_cas(uaecptr, int*, int*); +void get_mode_blanking_limits(int *phbstop, int *phbstrt, int *pvbstop, int *pvbstrt); #define RGA_PIPELINE_ADJUST 4 #define MAX_CHIPSETSLOTS 256 diff --git a/include/options.h b/include/options.h index 283b761b..06da514a 100644 --- a/include/options.h +++ b/include/options.h @@ -628,6 +628,7 @@ struct uae_prefs { int genlock_scale; int genlock_aspect; int genlock_effects; + int genlock_offset_x, genlock_offset_y; uae_u64 ecs_genlock_features_colorkey_mask[4]; uae_u8 ecs_genlock_features_plane_mask; bool genlock_alpha; @@ -910,6 +911,7 @@ struct uae_prefs { bool win32_shutdown_notification; bool win32_warn_exit; bool win32_gui_control; + bool win32_videograb_balance; bool right_control_is_right_win_key; #ifdef WITH_SLIRP struct slirp_redir slirp_redirs[MAX_SLIRP_REDIRS]; diff --git a/include/videograb.h b/include/videograb.h index 3873664c..1bfeb1c7 100644 --- a/include/videograb.h +++ b/include/videograb.h @@ -4,7 +4,9 @@ void uninitvideograb(void); bool getvideograb(long **buffer, int *width, int *height); void pausevideograb(int pause); uae_s64 getsetpositionvideograb(uae_s64 framepos); +uae_s64 getdurationvideograb(void); bool isvideograb(void); bool getpausevideograb(void); void setvolumevideograb(int volume); +void setchflagsvideograb(int chflags); void isvideograb_status(void); diff --git a/od-win32/win32_videograb.cpp b/od-win32/win32_videograb.cpp index 16bab06d..de669223 100644 --- a/od-win32/win32_videograb.cpp +++ b/od-win32/win32_videograb.cpp @@ -51,17 +51,20 @@ static CComPtr mediaSeeking; static CComPtr mediaEvent; static CComPtr audio; static bool videoInitialized; -static bool videoPaused; +static int videoPaused; static long *frameBuffer; static long bufferSize; static int videoWidth, videoHeight; +static int audio_chflags, audio_volume; void uninitvideograb(void) { write_log(_T("uninitvideograb\n")); videoInitialized = false; - videoPaused = false; + videoPaused = -1; + audio_chflags = 0; + audio_volume = 0; sampleGrabber.Release(); mediaSeeking.Release(); @@ -311,6 +314,7 @@ bool initvideograb(const TCHAR *filename) hr = filterGraph->QueryInterface(IID_IBasicAudio, (void**)&audio); setvolumevideograb(100 - currprefs.sound_volume_genlock); + setchflagsvideograb(0); hr = filterGraph->QueryInterface(IID_IMediaControl, (void**)&mediaControl); if (FAILED(hr)) { @@ -332,6 +336,16 @@ bool initvideograb(const TCHAR *filename) } } +uae_s64 getdurationvideograb(void) +{ + LONGLONG dura; + HRESULT hr = mediaSeeking->GetDuration(&dura); + if (FAILED(hr)) { + return 0; + } + return dura; +} + uae_s64 getsetpositionvideograb(uae_s64 framepos) { if (!videoInitialized || !mediaSeeking) @@ -351,8 +365,32 @@ uae_s64 getsetpositionvideograb(uae_s64 framepos) hr = mediaSeeking->SetPositions(&pos, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning); if (FAILED(hr)) { write_log(_T("SetPositions %lld failed %08x\n"), framepos, hr); + return 0; } - return 0; + return pos; + } +} + +void setchflagsvideograb(int chflags) +{ + if (!audio) + return; + audio_chflags = chflags; + long bal; + if (chflags == 1) { + bal = -10000; + } else if (chflags == 2) { + bal = 10000; + } else { + bal = 0; + } + if (!currprefs.win32_videograb_balance) { + audio->put_Balance(bal); + } + if (chflags) { + setvolumevideograb(audio_volume); + } else if (!chflags) { + audio->put_Volume(0); } } @@ -360,13 +398,17 @@ void setvolumevideograb(int volume) { if (!audio) return; + audio_volume = volume; + if (!audio_chflags) { + volume = 0; + } long vol = (long)(log10((float)volume / 100.0) * 4000.0); audio->put_Volume(vol); } bool getpausevideograb(void) { - return videoPaused != 0; + return videoPaused > 0; } void pausevideograb(int pause) @@ -374,17 +416,19 @@ void pausevideograb(int pause) HRESULT hr; if (!videoInitialized) return; + if (videoPaused == pause) + return; if (pause < 0) { pause = videoPaused ? 0 : 1; } if (pause > 0) { hr = mediaControl->Pause(); if (SUCCEEDED(hr)) - videoPaused = true; + videoPaused = 1; } else if (pause == 0) { hr = mediaControl->Run(); if (SUCCEEDED(hr)) - videoPaused = false; + videoPaused = 0; } } diff --git a/od-win32/win32gfx.cpp b/od-win32/win32gfx.cpp index eb258c09..2d47b3b3 100644 --- a/od-win32/win32gfx.cpp +++ b/od-win32/win32gfx.cpp @@ -2264,6 +2264,8 @@ int check_prefs_changed_gfx(void) c |= currprefs.genlock_mix != changed_prefs.genlock_mix ? (1 | 256) : 0; c |= currprefs.genlock_aspect != changed_prefs.genlock_aspect ? (1 | 256) : 0; c |= currprefs.genlock_scale != changed_prefs.genlock_scale ? (1 | 256) : 0; + c |= currprefs.genlock_offset_x != changed_prefs.genlock_offset_x ? (1 | 256) : 0; + c |= currprefs.genlock_offset_y != changed_prefs.genlock_offset_y ? (1 | 256) : 0; c |= _tcsicmp(currprefs.genlock_image_file, changed_prefs.genlock_image_file) ? (2 | 8) : 0; c |= _tcsicmp(currprefs.genlock_video_file, changed_prefs.genlock_video_file) ? (2 | 8) : 0; @@ -2368,6 +2370,8 @@ int check_prefs_changed_gfx(void) currprefs.genlock_alpha = changed_prefs.genlock_alpha; currprefs.genlock_aspect = changed_prefs.genlock_aspect; currprefs.genlock_scale = changed_prefs.genlock_scale; + currprefs.genlock_offset_x = changed_prefs.genlock_offset_x; + currprefs.genlock_offset_y = changed_prefs.genlock_offset_y; _tcscpy(currprefs.genlock_image_file, changed_prefs.genlock_image_file); _tcscpy(currprefs.genlock_video_file, changed_prefs.genlock_video_file); diff --git a/specialmonitors.cpp b/specialmonitors.cpp index ea567f96..b20347bf 100755 --- a/specialmonitors.cpp +++ b/specialmonitors.cpp @@ -2399,7 +2399,7 @@ static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool double struct vidbuf_description *avidinfo = &adisplays[dst->monitor_id].gfxvidinfo; int y, x, vdbl, hdbl; - int ystart, yend; + int ystart, yend, xstart, xend; int mix1 = 0, mix2 = 0; int genlock_image_pixbytes = 4; @@ -2536,8 +2536,7 @@ skip: else hdbl = 2; // lores - ystart = minfirstline; - yend = maxvpos; + get_mode_blanking_limits(&xstart, &xend, &ystart, ¥d); init_noise(); @@ -2548,11 +2547,25 @@ skip: uae_u8 amix1 = 255 - (currprefs.genlock_mix > 255 ? 255 : 0); uae_u8 amix2 = 255 - amix1; - int ah = (((yend - ystart) * 2) >> vdbl); - int aw = src->inwidth; + int ah = (((yend - ystart) * 2) >> 0); + int aw = ((xend - xstart) >> 1); - int deltax = genlock_image_width * 65536 / aw; - int deltay = genlock_image_height * 65536 / ah; + if (ah < 16 || aw < 16) { + return false; + } + + int deltax = 65536; + int deltay = 65536; + + if (abs(genlock_image_width - aw) > 8) { + deltax = genlock_image_width * 65536 / aw; + } + if (abs(genlock_image_height - ah) > 8) { + deltay = genlock_image_height * 65536 / ah; + } + deltay <<= vdbl; + deltax <<= hdbl; + deltax >>= 1; deltax -= currprefs.genlock_scale * 256; deltay -= currprefs.genlock_scale * 256; @@ -2561,20 +2574,31 @@ skip: int offsety = 0; if (deltax && deltay) { - offsetx = (aw - genlock_image_width * 65536 / deltax) / 2; - offsety = (ah - genlock_image_height * 65536 / deltay) / 2; + offsetx = ((aw - genlock_image_width) * 65536 / deltax) / 2; + offsety = ((ah - genlock_image_height) * 65536 / deltay) / 2; if (currprefs.genlock_aspect) { if (deltax < deltay) { - offsetx = (aw - genlock_image_width * 65536 / deltay) / 2; + offsetx = ((aw - genlock_image_width) * 65536 / deltay) / 2; deltax = deltay; } else { - offsety = (ah - genlock_image_height * 65536 / deltax) / 2; + offsety = ((ah - genlock_image_height) * 65536 / deltax) / 2; deltay = deltax; } } } + int gen_xoffset = 0; + int gen_yoffset = 0; + + if (currprefs.gfx_overscanmode >= OVERSCANMODE_EXTREME) { + gen_xoffset = (xstart / 2) - hsync_end_left_border * 2; + } + gen_yoffset = (ystart - minfirstline) * 2; + + gen_xoffset += currprefs.genlock_offset_x; + gen_yoffset += currprefs.genlock_offset_y; + uae_u8 r = 0, g = 0, b = 0, a = 0; for (y = ystart; y < yend; y++) { int yoff = (y * 2 + oddlines) - src->yoffset; @@ -2588,7 +2612,7 @@ skip: uae_u8 *lineprev = yoff > 0 ? src->bufmem + (yoff - 1) * src->rowbytes : NULL; uae_u8 *dstline = dst->bufmem + ((y * 2 + oddlines) - dst->yoffset) * dst->rowbytes; uae_u8 *line_genlock = row_map_genlock[yoff]; - int gy = ((y * 2 + oddlines) - src->yoffset - offsety) * deltay / 65536; + int gy = ((y * 2 + oddlines) - src->yoffset + offsety - gen_yoffset) * deltay / 65536; if (genlock_image_upsidedown) gy = (genlock_image_height - 1) - gy; uae_u8 *image_genlock = genlock_image + gy * genlock_image_pitch; @@ -2611,7 +2635,7 @@ skip: } else if (genlock_blank) { r = g = b = 0; } else if (genlock_image) { - int gx = (x - offsetx) * deltax / 65536; + int gx = (x + offsetx - gen_xoffset) * deltax / 65536; if (gx >= 0 && gx < genlock_image_width && gy >= 0 && gy < genlock_image_height) { uae_u8 *s_genlock_image = image_genlock + gx * genlock_image_pixbytes; r = s_genlock_image[genlock_image_red_index]; -- 2.47.3