From: Toni Wilen Date: Sat, 15 Oct 2016 16:30:31 +0000 (+0300) Subject: screenshot/avioutput genlock alpha. X-Git-Tag: 3400~53 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=0297ae6bd06e3a0123e0e41c6598297f774898f0;p=francis%2Fwinuae.git screenshot/avioutput genlock alpha. --- diff --git a/drawing.cpp b/drawing.cpp index 092d2a4d..5bfbae7e 100644 --- a/drawing.cpp +++ b/drawing.cpp @@ -104,7 +104,8 @@ int detected_screen_resolution; static int can_use_lores = 0, frame_res, frame_res_lace; static int resolution_count[RES_MAX + 1], lines_count; static bool center_reset; -static bool need_genlock_data, init_genlock_data; +static bool init_genlock_data; +bool need_genlock_data; /* Lookup tables for dual playfields. The dblpf_*1 versions are for the case that playfield 1 has the priority, dbplpf_*2 are used if playfield 2 has @@ -510,6 +511,11 @@ void set_custom_limits (int w, int h, int dx, int dy) int vts = visible_top_start; int vbs = visible_bottom_stop; + if (specialmonitor_uses_control_lines()) { + w = -1; + h = -1; + } + if (w <= 0 || dx < 0) { visible_left_start = 0; visible_right_stop = MAX_STOP; diff --git a/include/keyboard.h b/include/keyboard.h index 63eb2e07..da39da89 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -177,6 +177,7 @@ enum aks { AKS_ENTERGUI = 0x200, AKS_RTG_C, AKS_RTG_0, AKS_RTG_1, AKS_RTG_2, AKS_RTG_3, AKS_CDTV_FRONT_PANEL_STOP, AKS_CDTV_FRONT_PANEL_PLAYPAUSE, AKS_CDTV_FRONT_PANEL_PREV, AKS_CDTV_FRONT_PANEL_NEXT, AKS_CDTV_FRONT_PANEL_REW, AKS_CDTV_FRONT_PANEL_FF, + AKS_VIDEOGRAB_RESTART, AKS_VIDEOGRAB_PAUSE, AKS_VIDEOGRAB_PREV, AKS_VIDEOGRAB_NEXT, AKS_QUALIFIER1, AKS_QUALIFIER2, AKS_QUALIFIER3, AKS_QUALIFIER4, AKS_QUALIFIER5, AKS_QUALIFIER6, AKS_QUALIFIER7, AKS_QUALIFIER8, AKS_QUALIFIER_SPECIAL, AKS_QUALIFIER_SHIFT, AKS_QUALIFIER_CONTROL, diff --git a/include/specialmonitors.h b/include/specialmonitors.h index 96ba90a6..c735a14f 100644 --- a/include/specialmonitors.h +++ b/include/specialmonitors.h @@ -4,11 +4,14 @@ #include "memory.h" bool emulate_specialmonitors(struct vidbuffer *src, struct vidbuffer *dst); +bool emulate_specialmonitors_line(struct vidbuffer *src, struct vidbuffer *dst, int line); void specialmonitor_store_fmode(int vpos, int hpos, uae_u16 fmode); void specialmonitor_reset(void); bool specialmonitor_need_genlock(void); +bool specialmonitor_uses_control_lines(void); bool specialmonitor_autoconfig_init(struct autoconfig_info*); bool emulate_genlock(struct vidbuffer*, struct vidbuffer*); bool emulate_grayscale(struct vidbuffer*, struct vidbuffer*); +bool specialmonitor_linebased(void); #endif /* UAE_SPECIALMONITORS_H */ diff --git a/include/videograb.h b/include/videograb.h index f38e52ff..9ca681e0 100644 --- a/include/videograb.h +++ b/include/videograb.h @@ -2,4 +2,5 @@ bool initvideograb(const TCHAR *filename); void uninitvideograb(void); bool getvideograb(long **buffer, int *width, int *height); -void pausevideograb(bool pause); \ No newline at end of file +void pausevideograb(int pause); +uae_s64 getsetpositionvideograb(uae_s64 framepos); \ No newline at end of file diff --git a/inputdevice.cpp b/inputdevice.cpp index 3b6b41d5..c62a58c1 100644 --- a/inputdevice.cpp +++ b/inputdevice.cpp @@ -59,6 +59,7 @@ #include "tabletlibrary.h" #include "statusline.h" #include "native2amiga_api.h" +#include "videograb.h" #if SIZEOF_TCHAR != 1 /* FIXME: replace strcasecmp with _tcsicmp in source code instead */ @@ -4117,6 +4118,31 @@ static bool inputdevice_handle_inputcode2 (int code, int state) case AKS_RTG_3: toggle_rtg(code - AKS_RTG_C); break; + case AKS_VIDEOGRAB_RESTART: + getsetpositionvideograb(0); + pausevideograb(0); + break; + case AKS_VIDEOGRAB_PAUSE: + pausevideograb(-1); + break; + case AKS_VIDEOGRAB_PREV: + { + pausevideograb(1); + uae_s64 pos = getsetpositionvideograb(-1); + pos--; + if (pos >= 0) + getsetpositionvideograb(pos); + break; + } + case AKS_VIDEOGRAB_NEXT: + { + pausevideograb(1); + uae_s64 pos = getsetpositionvideograb(-1); + pos++; + getsetpositionvideograb(pos); + break; + } + #ifdef CDTV case AKS_CDTV_FRONT_PANEL_STOP: case AKS_CDTV_FRONT_PANEL_PLAYPAUSE: diff --git a/inputevents.def b/inputevents.def index 5349ffad..cd2a3156 100644 --- a/inputevents.def +++ b/inputevents.def @@ -414,4 +414,9 @@ DEFEVENT(SPC_CDTV_FRONT_PANEL_NEXT,_T("CDTV Front Panel Next"),AM_K,0,0,AKS_CDTV DEFEVENT(SPC_CDTV_FRONT_PANEL_REW,_T("CDTV Front Panel Rewind"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_REW) DEFEVENT(SPC_CDTV_FRONT_PANEL_FF,_T("CDTV Front Panel Fast Forward"),AM_K,0,0,AKS_CDTV_FRONT_PANEL_FF) +DEFEVENT(SPC_VIDEOGRAB_RESTART,_T("VideoGrab Restart"),AM_K,0,0,AKS_VIDEOGRAB_RESTART) +DEFEVENT(SPC_VIDEOGRAB_PAUSE,_T("VideoGrab Pause"),AM_K,0,0,AKS_VIDEOGRAB_PAUSE) +DEFEVENT(SPC_VIDEOGRAB_PREV,_T("VideoGrab Previous Frame"),AM_K,0,0,AKS_VIDEOGRAB_PREV) +DEFEVENT(SPC_VIDEOGRAB_NEXT,_T("VideoGrab Next Frame"),AM_K,0,0,AKS_VIDEOGRAB_NEXT) + DEFEVENT(SPC_LAST, _T(""), AM_DUMMY, 0,0,0) diff --git a/od-win32/avioutput.cpp b/od-win32/avioutput.cpp index 5995e285..5b3a9c92 100644 --- a/od-win32/avioutput.cpp +++ b/od-win32/avioutput.cpp @@ -128,6 +128,13 @@ static AVICOMPRESSOPTIONS FAR * aOptions[] = { &videoOptions }; // array of poin static LPBITMAPINFOHEADER lpbi; static PCOMPVARS pcompvars; +extern bool need_genlock_data; +extern uae_u8 **row_map_genlock; + +static bool usealpha(void) +{ + return need_genlock_data != 0 && row_map_genlock && currprefs.genlock_image && currprefs.genlock_alpha; +} void avi_message (const TCHAR *format,...) { @@ -568,6 +575,8 @@ static int AVIOutput_AllocateVideo (void) avioutput_bits = 24; if (avioutput_bits > 24) avioutput_bits = 24; + if (usealpha() && avioutput_bits == 24) + avioutput_bits = 32; lpbi = (LPBITMAPINFOHEADER)xcalloc (uae_u8, lpbisize ()); lpbi->biSize = sizeof (BITMAPINFOHEADER); lpbi->biWidth = aviout_width_out; @@ -951,7 +960,12 @@ static int getFromRenderTarget(struct avientry *avie) d[0] = v >> 0; d[1] = v >> 8; d[2] = v >> 16; - d += 3; + if (avioutput_bits == 32) { + d[3] = v >> 24; + d += 4; + } else { + d += 3; + } } } } else if (bits == 16 || bits == 15) { @@ -1014,7 +1028,7 @@ static int getFromDC (struct avientry *avie) static int rgb_type; -void AVIOutput_RGBinfo (int rb, int gb, int bb, int rs, int gs, int bs) +void AVIOutput_RGBinfo (int rb, int gb, int bb, int ab, int rs, int gs, int bs, int as) { if (bs == 0 && gs == 5 && rs == 11) rgb_type = 1; diff --git a/od-win32/avioutput.h b/od-win32/avioutput.h index a5a9c9b8..88523910 100644 --- a/od-win32/avioutput.h +++ b/od-win32/avioutput.h @@ -32,11 +32,11 @@ extern void AVIOutput_End (void); extern void AVIOutput_Begin (void); extern void AVIOutput_Release (void); extern void AVIOutput_Initialize (void); -extern void AVIOutput_RGBinfo (int,int,int,int,int,int); +extern void AVIOutput_RGBinfo (int,int,int,int,int,int,int,int); extern void AVIOutput_GetSettings (void); extern void AVIOutput_SetSettings (void); -extern void Screenshot_RGBinfo (int,int,int,int,int,int); +extern void Screenshot_RGBinfo (int,int,int,int,int,int,int,int); #define AVIAUDIO_AVI 1 #define AVIAUDIO_WAV 2 diff --git a/od-win32/screenshot.cpp b/od-win32/screenshot.cpp index 8f75730f..2f6e18d6 100644 --- a/od-win32/screenshot.cpp +++ b/od-win32/screenshot.cpp @@ -28,6 +28,14 @@ int screenshot_originalsize = 0; int screenshot_clipmode = 0; int screenshot_multi = 0; +extern bool need_genlock_data; +extern uae_u8 **row_map_genlock; + +static bool usealpha(void) +{ + return need_genlock_data != 0 && row_map_genlock && currprefs.genlock_image && currprefs.genlock_alpha; +} + static void namesplit (TCHAR *s) { int l; @@ -96,13 +104,14 @@ void screenshot_free (void) screenshot_prepared = FALSE; } -static int rgb_rb, rgb_gb, rgb_bb, rgb_rs, rgb_gs, rgb_bs; +static int rgb_rb, rgb_gb, rgb_bb, rgb_rs, rgb_gs, rgb_bs, rgb_ab, rgb_as; static int screenshot_prepare (int imagemode, struct vidbuffer *vb) { int width, height; HGDIOBJ hgdiobj; int bits; + int depth = usealpha() ? 32 : 24; screenshot_free (); @@ -116,8 +125,8 @@ static int screenshot_prepare (int imagemode, struct vidbuffer *vb) uae_u8 *src, *dst, *mem; bool needfree = false; uae_u8 *palette = NULL; - int rgb_bb2, rgb_gb2, rgb_rb2; - int rgb_bs2, rgb_gs2, rgb_rs2; + int rgb_bb2, rgb_gb2, rgb_rb2, rgb_ab2; + int rgb_bs2, rgb_gs2, rgb_rs2, rgb_as2; uae_u8 pal[256 * 3]; int screenshot_width = 0, screenshot_height = 0; int screenshot_xoffset = -1, screenshot_yoffset = -1; @@ -128,9 +137,11 @@ static int screenshot_prepare (int imagemode, struct vidbuffer *vb) rgb_bb2 = 8; rgb_gb2 = 8; rgb_rb2 = 8; + rgb_ab2 = 8; rgb_bs2 = 0; rgb_gs2 = 8; rgb_rs2 = 16; + rgb_as2 = 24; } else if (vb) { width = vb->outwidth; height = vb->outheight; @@ -140,18 +151,22 @@ static int screenshot_prepare (int imagemode, struct vidbuffer *vb) rgb_bb2 = rgb_bb; rgb_gb2 = rgb_gb; rgb_rb2 = rgb_rb; + rgb_ab2 = rgb_ab; rgb_bs2 = rgb_bs; rgb_gs2 = rgb_gs; rgb_rs2 = rgb_rs; + rgb_as2 = rgb_as; } else { src = mem = getfilterbuffer (&width, &height, &spitch, &bits); needfree = true; rgb_bb2 = rgb_bb; rgb_gb2 = rgb_gb; rgb_rb2 = rgb_rb; + rgb_ab2 = rgb_ab; rgb_bs2 = rgb_bs; rgb_gs2 = rgb_gs; rgb_rs2 = rgb_rs; + rgb_as2 = rgb_as; } if (src == NULL) goto donormal; @@ -237,7 +252,7 @@ static int screenshot_prepare (int imagemode, struct vidbuffer *vb) bi->bmiHeader.biWidth = screenshot_width * screenshot_xmult; bi->bmiHeader.biHeight = screenshot_height * screenshot_ymult; bi->bmiHeader.biPlanes = 1; - bi->bmiHeader.biBitCount = bits <= 8 ? 8 : 24; + bi->bmiHeader.biBitCount = bits <= 8 ? 8 : depth; bi->bmiHeader.biCompression = BI_RGB; dpitch = ((bi->bmiHeader.biWidth * bi->bmiHeader.biBitCount + 31) & ~31) / 8; bi->bmiHeader.biSizeImage = dpitch * bi->bmiHeader.biHeight; @@ -314,7 +329,7 @@ static int screenshot_prepare (int imagemode, struct vidbuffer *vb) } else { int shift; uae_u32 v = 0; - uae_u32 v2, v2a, v2b, v2c; + uae_u32 v2, v2a, v2b, v2c, v2d; if (bits == 16) v = ((uae_u16*)s)[x]; @@ -342,12 +357,28 @@ static int screenshot_prepare (int imagemode, struct vidbuffer *vb) v2 |= (v2 >> shift) & ((1 < shift) - 1); v2c = v2; + if (depth == 32) { + shift = 8 - rgb_ab2; + v2 = (v >> rgb_as2) & ((1 << rgb_ab2) - 1); + v2 <<= (8 - rgb_ab2); + if (rgb_ab < 8) + v2 |= (v2 >> shift) & ((1 < shift) - 1); + v2d = v2; + } + uae_u8 *d2 = d; for (int y2 = 0; y2 < ymult; y2++) { for (int x2 = 0; x2 < xmult; x2++) { - d2[(xx + x2) * 3 + 0] = v2a; - d2[(xx + x2) * 3 + 1] = v2b; - d2[(xx + x2) * 3 + 2] = v2c; + if (depth == 32) { + d2[(xx + x2) * 4 + 0] = v2a; + d2[(xx + x2) * 4 + 1] = v2b; + d2[(xx + x2) * 4 + 2] = v2c; + d2[(xx + x2) * 4 + 3] = v2d; + } else { + d2[(xx + x2) * 3 + 0] = v2a; + d2[(xx + x2) * 3 + 1] = v2b; + d2[(xx + x2) * 3 + 2] = v2c; + } } d2 += dpitch2; } @@ -378,7 +409,7 @@ donormal: if (s) { hr = s->LockRect(&l, NULL, D3DLOCK_READONLY); if (SUCCEEDED(hr)) { - int dpitch = (((w * 24 + 31) & ~31) / 8); + int dpitch = (((w * depth + 31) & ~31) / 8); lpvBits = xmalloc(uae_u8, dpitch * h); ZeroMemory(bi, sizeof(bi)); @@ -386,7 +417,7 @@ donormal: bi->bmiHeader.biWidth = w; bi->bmiHeader.biHeight = h; bi->bmiHeader.biPlanes = 1; - bi->bmiHeader.biBitCount = 24; + bi->bmiHeader.biBitCount = depth; bi->bmiHeader.biCompression = BI_RGB; bi->bmiHeader.biSizeImage = dpitch * bi->bmiHeader.biHeight; bi->bmiHeader.biXPelsPerMeter = 0; @@ -404,7 +435,12 @@ donormal: d[0] = v >> 0; d[1] = v >> 8; d[2] = v >> 16; - d += 3; + if (depth == 32) { + d[3] = v >> 24; + d += 4; + } else { + d += 3; + } } } } else if (bits == 16 || bits == 15) { @@ -507,16 +543,18 @@ int screenshot_prepare (void) return screenshot_prepare (-1); } -void Screenshot_RGBinfo (int rb, int gb, int bb, int rs, int gs, int bs) +void Screenshot_RGBinfo (int rb, int gb, int bb, int ab, int rs, int gs, int bs, int as) { if (!bi) bi = xcalloc (BITMAPINFO, sizeof(BITMAPINFO) + 256 * sizeof(RGBQUAD)); rgb_rb = rb; rgb_gb = gb; rgb_bb = rb; + rgb_ab = ab; rgb_rs = rs; rgb_gs = gs; rgb_bs = bs; + rgb_as = as; } #if PNG_SCREENSHOTS > 0 @@ -532,7 +570,7 @@ static void _cdecl pngtest_blah (png_structp png_ptr, png_const_charp message) #endif } -static int savepng (FILE *fp) +static int savepng(FILE *fp, bool alpha) { png_structp png_ptr; png_infop info_ptr; @@ -559,7 +597,7 @@ static int savepng (FILE *fp) png_init_io (png_ptr, fp); png_set_filter (png_ptr, 0, PNG_FILTER_NONE); png_set_IHDR (png_ptr, info_ptr, - w, h, 8, d <= 8 ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB, + w, h, 8, d <= 8 ? PNG_COLOR_TYPE_PALETTE : (alpha ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_RGB), PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); if (d <= 8) { for (i = 0; i < (1 << d); i++) { @@ -572,7 +610,7 @@ static int savepng (FILE *fp) row_pointers = xmalloc (png_bytep, h); for (i = 0; i < h; i++) { int j = h - i - 1; - row_pointers[i] = (uae_u8*)lpvBits + j * (((w * (d <= 8 ? 8 : 24) + 31) & ~31) / 8); + row_pointers[i] = (uae_u8*)lpvBits + j * (((w * (d <= 8 ? 8 : (alpha ? 32 : 24)) + 31) & ~31) / 8); } png_set_rows (png_ptr, info_ptr, row_pointers); png_write_png (png_ptr,info_ptr, PNG_TRANSFORM_BGR, NULL); @@ -582,7 +620,7 @@ static int savepng (FILE *fp) } #endif -static int savebmp (FILE *fp) +static int savebmp (FILE *fp, bool alpha) { BITMAPFILEHEADER bfh; // write the file header, bitmap information and pixel data @@ -622,6 +660,7 @@ int screenshotf (const TCHAR *spath, int mode, int doprepare, int imagemode, str int failed = 0; int screenshot_max = 1000; // limit 999 iterations / screenshots TCHAR *format = _T("%s%s%s%03d.%s"); + bool alpha = usealpha(); HBITMAP offscreen_bitmap = NULL; // bitmap that is converted to a DIB HDC offscreen_dc = NULL; // offscreen DC that we can select offscreen bitmap into @@ -652,10 +691,10 @@ int screenshotf (const TCHAR *spath, int mode, int doprepare, int imagemode, str if (fp) { #if PNG_SCREENSHOTS > 0 if (screenshotmode) - failed = savepng (fp); + failed = savepng (fp, alpha); else #endif - failed = savebmp (fp); + failed = savebmp (fp, alpha); fclose(fp); fp = NULL; if (failed) @@ -710,10 +749,10 @@ int screenshotf (const TCHAR *spath, int mode, int doprepare, int imagemode, str } #if PNG_SCREENSHOTS > 0 if (screenshotmode) - nok = savepng (fp); + nok = savepng (fp, alpha); else #endif - nok = savebmp (fp); + nok = savebmp (fp, alpha); fclose(fp); if (nok && fp) { _tunlink(filename); @@ -780,4 +819,4 @@ void screenshot (int mode, int doprepare) screenshotf (_T("c:\\temp\\1.bmp"), 1, 1, 1, &vb); freevidbuffer (&vb); #endif -} \ No newline at end of file +} diff --git a/od-win32/win32_videograb.cpp b/od-win32/win32_videograb.cpp index fd660003..f996c79c 100644 --- a/od-win32/win32_videograb.cpp +++ b/od-win32/win32_videograb.cpp @@ -47,7 +47,9 @@ static CComPtr graphBuilder; static CComPtr filterGraph; static CComPtr sampleGrabber; static CComPtr mediaControl; +static CComPtr mediaSeeking; static bool videoInitialized; +static bool videoPaused; static long *frameBuffer; static long bufferSize; static int videoWidth, videoHeight; @@ -57,8 +59,10 @@ void uninitvideograb(void) write_log(_T("uninitvideograb\n")); videoInitialized = false; + videoPaused = false; sampleGrabber.Release(); + mediaSeeking.Release(); if (mediaControl) { mediaControl->Stop(); } @@ -242,6 +246,8 @@ bool initvideograb(const TCHAR *filename) return false; } + hr = filterGraph->QueryInterface(IID_IMediaSeeking, (void**)&mediaSeeking); + hr = filterGraph->QueryInterface(IID_IMediaControl, (void**)&mediaControl); if (FAILED(hr)) { uninitvideograb(); @@ -249,6 +255,7 @@ bool initvideograb(const TCHAR *filename) } if (SUCCEEDED(mediaControl->Run())) { videoInitialized = true; + write_log(_T("Playing '%s'\n"), filename ? filename : _T("")); return true; } else { uninitvideograb(); @@ -256,14 +263,46 @@ bool initvideograb(const TCHAR *filename) } } -void pausevideograb(bool pause) +uae_s64 getsetpositionvideograb(uae_s64 framepos) { + if (!videoInitialized || !mediaSeeking) + return 0; + LONGLONG pos; + HRESULT hr = mediaSeeking->SetTimeFormat(&TIME_FORMAT_FRAME); + if (FAILED(hr)) + write_log(_T("SetTimeFormat format %08x\n"), hr); + if (framepos < 0) { + LONGLONG stoppos; + hr = mediaSeeking->GetPositions(&pos, &stoppos); + if (FAILED(hr)) { + write_log(_T("GetPositions failed %08x\n"), hr); + pos = 0; + } + return pos; + } else { + LONGLONG pos = 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; + } +} + +void pausevideograb(int pause) +{ + HRESULT hr; if (!videoInitialized) return; - if (pause) { - mediaControl->Pause(); - } else { - mediaControl->Run(); + if (pause < 0) { + pause = videoPaused ? 0 : 1; + } + if (pause > 0) { + hr = mediaControl->Pause(); + videoPaused = true; + } else if (pause == 0) { + hr = mediaControl->Run(); + videoPaused = false; } } diff --git a/specialmonitors.cpp b/specialmonitors.cpp index 2744d091..a65dbc2e 100755 --- a/specialmonitors.cpp +++ b/specialmonitors.cpp @@ -136,6 +136,22 @@ STATIC_INLINE void PRGB(struct vidbuffer *dst, uae_u8 *dataline, uae_u8 r, uae_u } } +STATIC_INLINE void PRGBA(struct vidbuffer *dst, uae_u8 *dataline, uae_u8 r, uae_u8 g, uae_u8 b, uae_u8 a) +{ + if (dst->pixbytes == 4) { + dataline[0] = b; + dataline[1] = g; + dataline[2] = r; + dataline[3] = a; + } else { + r >>= 3; + g >>= 2; + b >>= 3; + ((uae_u16*)dataline)[0] = (r << 11) | (g << 5) | b; + } +} + + STATIC_INLINE void PUT_PRGB(uae_u8 *d, uae_u8 *d2, struct vidbuffer *dst, uae_u8 r, uae_u8 g, uae_u8 b, int xadd, int doublelines, bool hdouble) { if (hdouble) @@ -158,6 +174,28 @@ STATIC_INLINE void PUT_PRGB(uae_u8 *d, uae_u8 *d2, struct vidbuffer *dst, uae_u8 } } +STATIC_INLINE void PUT_PRGBA(uae_u8 *d, uae_u8 *d2, struct vidbuffer *dst, uae_u8 r, uae_u8 g, uae_u8 b, uae_u8 a, int xadd, int doublelines, bool hdouble) +{ + if (hdouble) + PRGBA(dst, d - dst->pixbytes, r, g, b, a); + PRGBA(dst, d, r, g, b, a); + if (xadd >= 2) { + PRGBA(dst, d + 1 * dst->pixbytes, r, g, b, a); + if (hdouble) + PRGBA(dst, d + 2 * dst->pixbytes, r, g, b, a); + } + if (doublelines) { + if (hdouble) + PRGBA(dst, d2 - dst->pixbytes, r, g, b, a); + PRGBA(dst, d2, r, g, b, a); + if (xadd >= 2) { + PRGBA(dst, d2 + 1 * dst->pixbytes, r, g, b, a); + if (hdouble) + PRGBA(dst, d2 + 2 * dst->pixbytes, r, g, b, a); + } + } +} + STATIC_INLINE void PUT_AMIGARGB(uae_u8 *d, uae_u8 *s, uae_u8 *d2, uae_u8 *s2, struct vidbuffer *dst, int xadd, int doublelines, bool hdouble) { if (dst->pixbytes == 4) { @@ -182,6 +220,30 @@ STATIC_INLINE void PUT_AMIGARGB(uae_u8 *d, uae_u8 *s, uae_u8 *d2, uae_u8 *s2, st } } +STATIC_INLINE void PUT_AMIGARGBA(uae_u8 *d, uae_u8 *s, uae_u8 *d2, uae_u8 *s2, struct vidbuffer *dst, int xadd, int doublelines, bool hdouble) +{ + if (dst->pixbytes == 4) { + if (hdouble) + ((uae_u32*)d)[-1] = (((uae_u32*)s)[-1]) | 0xff000000; + ((uae_u32*)d)[0] = (((uae_u32*)s)[0]) | 0xff000000; + } else { + if (hdouble) + ((uae_u16*)d)[-1] = (((uae_u16*)s)[-1]) | 0xff000000; + ((uae_u16*)d)[0] = (((uae_u16*)s)[0]) | 0xff000000; + } + if (doublelines) { + if (dst->pixbytes == 4) { + if (hdouble) + ((uae_u32*)d2)[-1] = (((uae_u32*)s2)[-1]) | 0xff000000; + ((uae_u32*)d2)[0] = (((uae_u32*)s2)[0]) | 0xff000000; + } else { + if (hdouble) + ((uae_u16*)d2)[-1] = (((uae_u16*)s2)[-1]) | 0xff000000; + ((uae_u16*)d2)[0] = (((uae_u16*)s2)[0]) | 0xff000000; + } + } +} + static void clearmonitor(struct vidbuffer *dst) { uae_u8 *p = dst->bufmem; @@ -2414,8 +2476,10 @@ static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool double mix1 = 256 - currprefs.genlock_mix; mix2 = currprefs.genlock_mix; } + uae_u8 amix1 = 255 - (currprefs.genlock_mix > 255 ? 255 : 0); + uae_u8 amix2 = 255 - amix1; - uae_u8 r = 0, g = 0, b = 0; + uae_u8 r = 0, g = 0, b = 0, a = 0; for (y = ystart; y < yend; y++) { int yoff = (((y * 2 + oddlines) - src->yoffset) >> vdbl); if (yoff < 0) @@ -2430,7 +2494,8 @@ static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool double if (genlock_image_upsidedown) gy = (genlock_image_height - 1) - gy; uae_u8 *image_genlock = genlock_image + gy * genlock_image_pitch; - r = g = b = 0; + r = g = b; + a = amix1; noise_add = (quickrand() & 15) | 1; for (x = 0; x < src->inwidth; x++) { uae_u8 *s = line + x * src->pixbytes; @@ -2440,6 +2505,7 @@ static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool double uae_u8 *d2 = d + dst->rowbytes; if (is_transparent(*s_genlock)) { + a = amix2; if (genlock_error) { r = 0x00; g = 0x00; @@ -2462,9 +2528,9 @@ static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool double g = (mix1 * g + mix2 * FVG(src, s)) / 256; b = (mix1 * b + mix2 * FVB(src, s)) / 256; } - PUT_PRGB(d, d2, dst, r, g, b, 0, doublelines, false); + PUT_PRGBA(d, d2, dst, r, g, b, a, 0, doublelines, false); } else { - PUT_AMIGARGB(d, s, d2, s2, dst, 0, doublelines, false); + PUT_AMIGARGBA(d, s, d2, s2, dst, 0, doublelines, false); } } } @@ -2669,6 +2735,19 @@ struct opals { int address_load; int rowbytes; uae_u8 control_line[OPAL_CONTROL_LINE_LENGTH]; + + int palcoprocnt; + bool copro_hires; + int copro_bank_offset[2]; + int copro_vdm; + bool copro_prior_mode; + bool copro_priority; + bool copro_dual_disp; + int address_load_sync; + int vram_write_offset; + int vram_read_offset; + int control_y; + bool detected; }; static struct opals *opal; @@ -2726,9 +2805,9 @@ static void opal_pixel(struct opals *opal, uae_u8 *d, uae_u8 *d2, uae_u8 *s, uae } } -#define OPAL_SWAP_BANK (opal->dual_play && pf && !copro_hires) || (opal->v2 && opal->opal && opal->dual_play && copro_hires && s_genlock && is_transparent(*s_genlock)) +#define OPAL_SWAP_BANK (opal->dual_play && pf && !opal->copro_hires) || (opal->v2 && opal->opal && opal->dual_play && opal->copro_hires && s_genlock && is_transparent(*s_genlock)) -static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines, bool isopal) +static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines, int yline, bool isopal) { int y, x, vdbl, hdbl; int isntsc; @@ -2759,20 +2838,27 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double int yimgstart = ystart + 6; int yend = (isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL) + 1; - int palcoprocnt = 0; - - bool copro_hires = false; - int copro_bank_offset[2] = { 0, 0 }; - int copro_vdm = 0; - bool copro_prior_mode = false; - bool copro_priority = false; - bool copro_dual_disp = false; - int address_load_sync = -1; - int vram_write_offset = 0; - int vram_read_offset = 0; - int control_y = 0; + if (yline < 0 || yline == ystart) { + opal->address_load_sync = -1; + opal->vram_write_offset = 0; + opal->vram_read_offset = 0; + opal->control_y = 0; + opal->copro_prior_mode = false; + opal->copro_priority = false; + opal->copro_dual_disp = false; + opal->copro_vdm = 0; + opal->copro_hires = 0; + opal->palcoprocnt = 0; + opal->detected = opal->latched; + } + + if (yline < 0) { + y = ystart; + } else { + y = yline; + } - for (y = ystart; y < yend; y++) { + for (; y < yend; y++) { uae_u8 *line = NULL; uae_u8 *line_genlock = NULL; @@ -2791,27 +2877,27 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double uae_u8 copro = opal->copro[y - ystart]; if (opal->opal) { - copro_prior_mode = (copro & 0x40) != 0; - copro_priority = (copro & 0x20) != 0; - copro_dual_disp = (copro & 0x10) != 0; - copro_hires = (copro & 8) != 0; - copro_bank_offset[0] = (copro & 4) ? 6 * OPAL_SEGMENT_SIZE : 0; - copro_bank_offset[1] = (copro & 4) ? 0 : 6 * OPAL_SEGMENT_SIZE; - copro_vdm = copro & 3; + opal->copro_prior_mode = (copro & 0x40) != 0; + opal->copro_priority = (copro & 0x20) != 0; + opal->copro_dual_disp = (copro & 0x10) != 0; + opal->copro_hires = (copro & 8) != 0; + opal->copro_bank_offset[0] = (copro & 4) ? 6 * OPAL_SEGMENT_SIZE : 0; + opal->copro_bank_offset[1] = (copro & 4) ? 0 : 6 * OPAL_SEGMENT_SIZE; + opal->copro_vdm = copro & 3; } else { - copro_vdm = (((copro >> 6) & 1) << 1) | opal->control_line[7]; - copro_hires = (copro & 0x20) != 0; - copro_prior_mode = (copro & 0x10) != 0; - copro_priority = (copro & 8) != 0; - copro_dual_disp = (copro & 4) != 0; + opal->copro_vdm = (((copro >> 6) & 1) << 1) | opal->control_line[7]; + opal->copro_hires = (copro & 0x20) != 0; + opal->copro_prior_mode = (copro & 0x10) != 0; + opal->copro_priority = (copro & 8) != 0; + opal->copro_dual_disp = (copro & 4) != 0; opal->dual_play = (copro & 2) != 0; - copro_bank_offset[0] = (copro & 1) ? 6 * OPAL_SEGMENT_SIZE : 0; - copro_bank_offset[1] = (copro & 1) ? 0 : 6 * OPAL_SEGMENT_SIZE; + opal->copro_bank_offset[0] = (copro & 1) ? 6 * OPAL_SEGMENT_SIZE : 0; + opal->copro_bank_offset[1] = (copro & 1) ? 0 : 6 * OPAL_SEGMENT_SIZE; } - opal->priority_stencil_mode = (copro_prior_mode ? 2 : 0) | (copro_priority ? 4 : 0) | (copro_dual_disp ? 8 : 0); + opal->priority_stencil_mode = (opal->copro_prior_mode ? 2 : 0) | (opal->copro_priority ? 4 : 0) | (opal->copro_dual_disp ? 8 : 0); if (!(copro & 0x80)) { // Add_Load - vram_read_offset = opal->address_load; + opal->vram_read_offset = opal->address_load; } @@ -2827,8 +2913,8 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double if (!line) continue; - int vram_write_pixel_offset = vram_write_offset; - int vram_read_pixel_offset = vram_read_offset; + int vram_write_pixel_offset = opal->vram_write_offset; + int vram_read_pixel_offset = opal->vram_read_offset; // behavior not fully known if ((!opal->auto_field && opal->bank_field) || (opal->auto_field && oddlines)) { @@ -2859,67 +2945,67 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double uae_u8 pf, pr; int bidx; - if (copro_vdm == 0) { + if (opal->copro_vdm == 0) { // 24-bit truecolor (palette) uae_u8 m = opal->pixel_read_mask; - r = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 0 * OPAL_SEGMENT_SIZE] & m) + 0]; - g = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE] & m) + 1]; - b = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE] & m) + 2]; + r = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 0 * OPAL_SEGMENT_SIZE] & m) + 0]; + g = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE] & m) + 1]; + b = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE] & m) + 2]; pf = g & 1; pr = b & 1; if (OPAL_SWAP_BANK) { - r = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + 0 * OPAL_SEGMENT_SIZE] & m) + 0]; - g = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + 1 * OPAL_SEGMENT_SIZE] & m) + 1]; - b = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + 2 * OPAL_SEGMENT_SIZE] & m) + 2]; + r = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + 0 * OPAL_SEGMENT_SIZE] & m) + 0]; + g = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + 1 * OPAL_SEGMENT_SIZE] & m) + 1]; + b = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + 2 * OPAL_SEGMENT_SIZE] & m) + 2]; bidx = 0; } else { bidx = 1; } - opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !copro_hires, false); + opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !opal->copro_hires, false); - if (copro_hires) { - r = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 0 * OPAL_SEGMENT_SIZE] & m) + 0]; - g = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 1 * OPAL_SEGMENT_SIZE] & m) + 1]; - b = opal->palette[4 * (opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 2 * OPAL_SEGMENT_SIZE] & m) + 2]; + if (opal->copro_hires) { + r = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 0 * OPAL_SEGMENT_SIZE] & m) + 0]; + g = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 1 * OPAL_SEGMENT_SIZE] & m) + 1]; + b = opal->palette[4 * (opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 2 * OPAL_SEGMENT_SIZE] & m) + 2]; pr = b & 1; opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, false, true); } - } else if (copro_vdm == 1) { + } else if (opal->copro_vdm == 1) { // 24-bit truecolor (bypass palette) - r = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 0 * OPAL_SEGMENT_SIZE]; - g = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE]; - b = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE]; + r = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 0 * OPAL_SEGMENT_SIZE]; + g = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE]; + b = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE]; pf = g & 1; pr = b & 1; if (OPAL_SWAP_BANK) { - r = opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + 0 * OPAL_SEGMENT_SIZE]; - g = opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + 1 * OPAL_SEGMENT_SIZE]; - b = opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + 2 * OPAL_SEGMENT_SIZE]; + r = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + 0 * OPAL_SEGMENT_SIZE]; + g = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + 1 * OPAL_SEGMENT_SIZE]; + b = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + 2 * OPAL_SEGMENT_SIZE]; bidx = 0; } else { bidx = 1; } - opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !copro_hires, false); + opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !opal->copro_hires, false); - if (copro_hires) { - r = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 0 * OPAL_SEGMENT_SIZE]; - g = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 1 * OPAL_SEGMENT_SIZE]; - b = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 2 * OPAL_SEGMENT_SIZE]; + if (opal->copro_hires) { + r = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 0 * OPAL_SEGMENT_SIZE]; + g = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 1 * OPAL_SEGMENT_SIZE]; + b = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 2 * OPAL_SEGMENT_SIZE]; pr = b & 1; opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, false, true); } - } else if (copro_vdm == 2) { + } else if (opal->copro_vdm == 2) { // 8-bit palette - uae_u8 v0 = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + opal->color_offset] & opal->pixel_read_mask; - pf = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE] & 1; - pr = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE] & 1; + uae_u8 v0 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + opal->color_offset] & opal->pixel_read_mask; + pf = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE] & 1; + pr = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE] & 1; if (OPAL_SWAP_BANK) { - v0 = opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + opal->color_offset] & opal->pixel_read_mask; + v0 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + opal->color_offset] & opal->pixel_read_mask; bidx = 0; } else { bidx = 1; @@ -2927,40 +3013,40 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double r = opal->palette[v0 * 4 + 0]; g = opal->palette[v0 * 4 + 1]; b = opal->palette[v0 * 4 + 2]; - opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !copro_hires, false); + opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !opal->copro_hires, false); - if (copro_hires) { - uae_u8 v1 = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + opal->color_offset] & opal->pixel_read_mask; + if (opal->copro_hires) { + uae_u8 v1 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + opal->color_offset] & opal->pixel_read_mask; r = opal->palette[v1 * 4 + 0]; g = opal->palette[v1 * 4 + 1]; b = opal->palette[v1 * 4 + 2]; opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, false, true); } - } else if (copro_vdm == 3) { + } else if (opal->copro_vdm == 3) { if (((opal->video_command >> 6) & 3) == 3) { // 15 bit true color - uae_u8 v0 = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 0 * OPAL_SEGMENT_SIZE]; - uae_u8 v1 = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE]; + uae_u8 v0 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 0 * OPAL_SEGMENT_SIZE]; + uae_u8 v1 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE]; r = ((v0 >> 2) & 31) << (8 - 5); g = (((v0 & 3) << 3) | ((v1 >> 5) &7)) << (8 - 5); b = ((v1 & 31)) << (8 - 5); pf = v1 & 1; - pr = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE] & 1; + pr = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE] & 1; if (OPAL_SWAP_BANK) { - v0 = opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + 0 * OPAL_SEGMENT_SIZE]; - v1 = opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + 1 * OPAL_SEGMENT_SIZE]; + v0 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + 0 * OPAL_SEGMENT_SIZE]; + v1 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + 1 * OPAL_SEGMENT_SIZE]; bidx = 0; } else { bidx = 1; } - opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !copro_hires, false); + opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !opal->copro_hires, false); - if (copro_hires) { - v0 = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 0 * OPAL_SEGMENT_SIZE]; - v1 = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 1 * OPAL_SEGMENT_SIZE]; - pr = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 2 * OPAL_SEGMENT_SIZE] & 1; + if (opal->copro_hires) { + v0 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 0 * OPAL_SEGMENT_SIZE]; + v1 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 1 * OPAL_SEGMENT_SIZE]; + pr = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 2 * OPAL_SEGMENT_SIZE] & 1; r = ((v0 >> 2) & 31) << (8 - 5); g = (((v0 & 3) << 3) | ((v1 >> 5) & 7)) << (8 - 5); b = ((v1 & 31)) << (8 - 5); @@ -2969,26 +3055,26 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double } else { // 8-bit true color - uae_u8 v0 = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + opal->color_offset]; + uae_u8 v0 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + opal->color_offset]; r = ((v0 >> 5) & 7) << (8 - 3); g = ((v0 >> 2) & 7) << (8 - 3); b = ((v0 >> 0) & 3) << (8 - 2); - pf = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE] & 1; - pr = opal->vram[vram_read_pixel_offset + copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE] & 1; + pf = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 1 * OPAL_SEGMENT_SIZE] & 1; + pr = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[0] + 2 * OPAL_SEGMENT_SIZE] & 1; if (OPAL_SWAP_BANK) { - v0 = opal->vram[vram_read_pixel_offset + copro_bank_offset[1] + opal->color_offset]; + v0 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[1] + opal->color_offset]; bidx = 0; } else { bidx = 1; } - opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !copro_hires, false); + opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, !opal->copro_hires, false); - if (copro_hires) { - uae_u8 v1 = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + opal->color_offset] & opal->pixel_read_mask; + if (opal->copro_hires) { + uae_u8 v1 = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + opal->color_offset] & opal->pixel_read_mask; r = ((v0 >> 5) & 7) << (8 - 3); g = ((v0 >> 2) & 7) << (8 - 3); b = ((v0 >> 0) & 3) << (8 - 2); - pr = opal->vram[vram_read_pixel_offset + copro_bank_offset[bidx] + 2 * OPAL_SEGMENT_SIZE] & 1; + pr = opal->vram[vram_read_pixel_offset + opal->copro_bank_offset[bidx] + 2 * OPAL_SEGMENT_SIZE] & 1; opal_pixel(opal, d, d2, s, s2, s_genlock, src, dst, r, g, b, pr, doublelines, false, true); } } @@ -3068,7 +3154,7 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double } } - if (control_y && y >= control_y) { + if (opal->control_y && y >= opal->control_y) { if (opal_debug & 2) write_log(_T("%02x."), val); @@ -3076,7 +3162,7 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double if (pixcnt >= 1 && pixcnt < 4) { if (val != 0x00) - control_y = 0; + opal->control_y = 0; } else if (pixcnt > 0) { @@ -3088,21 +3174,21 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double } else if (opal->colcopro) { if ((pixcnt & 3) != 0) { - if (palcoprocnt < OPAL_MAXLINES) { + if (opal->palcoprocnt < OPAL_MAXLINES) { if (opal->wren) - opal->copro[palcoprocnt] = val; - } else if (palcoprocnt == OPAL_MAXLINES + 7) { + opal->copro[opal->palcoprocnt] = val; + } else if (opal->palcoprocnt == OPAL_MAXLINES + 7) { opal->video_command = val; command_update = true; } else if (val != 0x00) { - write_log(_T("COPRO %d = %02x\n"), palcoprocnt, val); + write_log(_T("COPRO %d = %02x\n"), opal->palcoprocnt, val); } - palcoprocnt++; + opal->palcoprocnt++; } } else { - if (y == control_y) { + if (y == opal->control_y) { if (pixcnt == 5) { opal->palette_load = val; @@ -3117,29 +3203,29 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double command_update = true; } } - if ((((y == control_y && pixcnt > 8) || (y > control_y)) && palcoprocnt < 4 * 256) && opal->wren) { + if ((((y == opal->control_y && pixcnt > 8) || (y > opal->control_y)) && opal->palcoprocnt < 4 * 256) && opal->wren) { if (!(opal->video_command & 0x10)) { // 6-bit palette (2 low bits are simply cleared) val <<= 2; } - opal->palette[(palcoprocnt + (opal->palette_load * 4)) & 1023] = val; - palcoprocnt++; + opal->palette[(opal->palcoprocnt + (opal->palette_load * 4)) & 1023] = val; + opal->palcoprocnt++; } } - } else if (pixcnt < 0 && y == control_y + 2) { + } else if (pixcnt < 0 && y == opal->control_y + 2) { - if (address_load_sync < 0 && val == 0xff) - address_load_sync = 0; - if (address_load_sync > 0 && address_load_sync < 4) { - if (address_load_sync == 1 && (val & 0xfe)) + if (opal->address_load_sync < 0 && val == 0xff) + opal->address_load_sync = 0; + if (opal->address_load_sync > 0 && opal->address_load_sync < 4) { + if (opal->address_load_sync == 1 && (val & 0xfe)) write_log(_T("Address load %02x\n"), val); opal->address_load <<= 8; opal->address_load |= val; opal->address_load &= (OPAL_SEGMENT_SIZE - 1); } - if (address_load_sync >= 0) - address_load_sync++; + if (opal->address_load_sync >= 0) + opal->address_load_sync++; } if (pixcnt >= 0) pixcnt++; @@ -3153,13 +3239,13 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double opal->color_offset = ((opal->video_command >> 6) & 3) * OPAL_SEGMENT_SIZE; } - vram_write_offset += opal->rowbytes; - vram_write_offset &= (OPAL_SEGMENT_SIZE - 1); + opal->vram_write_offset += opal->rowbytes; + opal->vram_write_offset &= (OPAL_SEGMENT_SIZE - 1); - vram_read_offset += opal->rowbytes; - vram_read_offset &= (OPAL_SEGMENT_SIZE - 1); + opal->vram_read_offset += opal->rowbytes; + opal->vram_read_offset &= (OPAL_SEGMENT_SIZE - 1); - if (control_y && y >= control_y && (opal_debug & 2)) { + if (opal->control_y && y >= opal->control_y && (opal_debug & 2)) { write_log(_T("\n")); } @@ -3167,16 +3253,17 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double write_log(_T("\n")); } - if (y == control_y + 3) { - control_y = 0; + if (y == opal->control_y + 3) { + opal->control_y = 0; } if (opal->opal && controlcnt >= OPAL_CONTROL_LINE_LENGTH) { memcpy(opal->control_line, control_line_tmp, OPAL_CONTROL_LINE_LENGTH); detected = opal->control_line[0] && opal->control_line[2] && !opal->control_line[1] && !opal->control_line[3]; + opal->detected |= detected; if (detected) { - palcoprocnt = 0; - control_y = y + 1; + opal->palcoprocnt = 0; + opal->control_y = y + 1; uae_u8 *c = opal->control_line; if (opal_debug & 1) { write_log(_T("WREN=%d COPRO=%d AUTO=%d DP=%d FIELD=%d FM=%d Latch=%d FGrab=%d\n"), @@ -3202,9 +3289,10 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double } else if (!opal->opal && controlcnt >= COLORBURST_CONTROL_LINE_LENGTH) { memcpy(opal->control_line, control_line_tmp, COLORBURST_CONTROL_LINE_LENGTH); detected = !opal->control_line[0] && !opal->control_line[2] && opal->control_line[1] && opal->control_line[3]; + opal->detected |= detected; if (detected) { - palcoprocnt = 0; - control_y = y + 1; + opal->palcoprocnt = 0; + opal->control_y = y + 1; uae_u8 *c = opal->control_line; if (opal_debug & 1) { write_log(_T("WREN=%d COPRO=%d AUTO=%d S0=%d\n"), @@ -3227,11 +3315,17 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double } } + if (yline >= 0) + break; + if (y >= yimgstart && !detected) return false; } + if (!opal->detected && y == yend) + return false; + if (opal->opal && monitor != MONITOREMU_OPALVISION) { monitor = MONITOREMU_OPALVISION; write_log(_T("Opalvision control line detected\n")); @@ -3244,26 +3338,26 @@ static bool opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool double return true; } -static bool do_opalvision(struct vidbuffer *src, struct vidbuffer *dst, bool opal) +static bool do_opalvision(struct vidbuffer *src, struct vidbuffer *dst, int line, bool opal) { bool v; if (interlace_seen) { if (currprefs.gfx_iscanlines) { - v = opalvision(src, dst, false, lof_store ? 0 : 1, opal); + v = opalvision(src, dst, false, lof_store ? 0 : 1, line, opal); if (v && currprefs.gfx_iscanlines > 1) blank_generic(src, dst, lof_store ? 1 : 0); } else { - v = opalvision(src, dst, false, 0, opal); - v |= opalvision(src, dst, false, 1, opal); + v = opalvision(src, dst, false, 0, line, opal); + v |= opalvision(src, dst, false, 1, line, opal); } } else { - v = opalvision(src, dst, true, 0, opal); + v = opalvision(src, dst, true, 0, line, opal); } return v; } -static bool emulate_specialmonitors2(struct vidbuffer *src, struct vidbuffer *dst) +static bool emulate_specialmonitors2(struct vidbuffer *src, struct vidbuffer *dst, int line) { automatic = false; if (currprefs.monitoremu == MONITOREMU_AUTO) { @@ -3278,9 +3372,9 @@ static bool emulate_specialmonitors2(struct vidbuffer *src, struct vidbuffer *ds v = do_avideo(src, dst); } if (!v) - v = do_opalvision(src, dst, true); + v = do_opalvision(src, dst, line, true); if (!v) - v = do_opalvision(src, dst, false); + v = do_opalvision(src, dst, line, false); return v; } else if (currprefs.monitoremu == MONITOREMU_A2024) { return a2024(src, dst); @@ -3298,9 +3392,9 @@ static bool emulate_specialmonitors2(struct vidbuffer *src, struct vidbuffer *ds } else if (currprefs.monitoremu == MONITOREMU_FIRECRACKER24) { return do_firecracker24(src, dst); } else if (currprefs.monitoremu == MONITOREMU_OPALVISION) { - return do_opalvision(src, dst, true); + return do_opalvision(src, dst, line, true); } else if (currprefs.monitoremu == MONITOREMU_COLORBURST) { - return do_opalvision(src, dst, false); + return do_opalvision(src, dst, line, false); } return false; } @@ -3308,7 +3402,7 @@ static bool emulate_specialmonitors2(struct vidbuffer *src, struct vidbuffer *ds bool emulate_specialmonitors(struct vidbuffer *src, struct vidbuffer *dst) { - if (!emulate_specialmonitors2(src, dst)) { + if (!emulate_specialmonitors2(src, dst, -1)) { if (monitor) { clearmonitor(dst); monitor = 0; @@ -3319,6 +3413,11 @@ bool emulate_specialmonitors(struct vidbuffer *src, struct vidbuffer *dst) return true; } +bool emulate_specialmonitors_line(struct vidbuffer *src, struct vidbuffer *dst, int line) +{ + return emulate_specialmonitors2(src, dst, line); +} + void specialmonitor_reset(void) { if (!currprefs.monitoremu) @@ -3343,3 +3442,26 @@ bool specialmonitor_need_genlock(void) return true; return false; } + +bool specialmonitor_uses_control_lines(void) +{ + switch (currprefs.monitoremu) { + case MONITOREMU_GRAFFITI: + case MONITOREMU_HAM_E: + case MONITOREMU_HAM_E_PLUS: + case MONITOREMU_OPALVISION: + case MONITOREMU_COLORBURST: + return true; + } + return false; +} + +bool specialmonitor_linebased(void) +{ + switch (currprefs.monitoremu) { + case MONITOREMU_OPALVISION: + case MONITOREMU_COLORBURST: + return true; + } + return false; +}