static const TCHAR *cdconmodes[] = { _T(""), _T("uae"), _T("ide"), _T("scsi"), _T("cdtv"), _T("cd32"), 0 };
static const TCHAR *specialmonitors[] = { _T("none"), _T("autodetect"), _T("a2024"), _T("graffiti"),
_T("ham_e"), _T("ham_e_plus"), _T("videodac18"), _T("avideo12"), _T("avideo24"), _T("firecracker24"), _T("dctv"), _T("opalvision"), _T("colorburst"), 0 };
-static const TCHAR *genlockmodes[] = { _T("none"), _T("noise"), _T("testcard"), NULL };
+static const TCHAR *genlockmodes[] = { _T("none"), _T("noise"), _T("testcard"), _T("image"), _T("video"), _T("stream"), NULL };
static const TCHAR *ppc_implementations[] = {
_T("auto"),
_T("dummy"),
cfgfile_write_bool (f, _T("immediate_blits"), p->immediate_blits);
cfgfile_dwrite_str (f, _T("waiting_blits"), waitblits[p->waiting_blits]);
cfgfile_write_bool (f, _T("ntsc"), p->ntscmode);
- cfgfile_write_bool (f, _T("genlock"), p->genlock);
+ cfgfile_write_bool(f, _T("genlock"), p->genlock);
cfgfile_dwrite_str(f, _T("genlockmode"), genlockmodes[p->genlock_image]);
cfgfile_dwrite_str(f, _T("genlock_image"), p->genlock_image_file);
+ cfgfile_dwrite_str(f, _T("genlock_video"), p->genlock_video_file);
cfgfile_dwrite(f, _T("genlock_mix"), _T("%d"), p->genlock_mix);
cfgfile_dwrite_str(f, _T("monitoremu"), specialmonitors[p->monitoremu]);
|| cfgfile_path (option, value, _T("rtc_file"), p->rtcfile, sizeof p->rtcfile / sizeof (TCHAR), &p->path_rom)
|| cfgfile_path(option, value, _T("picassoiv_rom_file"), p->picassoivromfile, sizeof p->picassoivromfile / sizeof(TCHAR), &p->path_rom)
|| cfgfile_string(option, value, _T("genlock_image"), p->genlock_image_file, sizeof p->genlock_image_file / sizeof(TCHAR))
+ || cfgfile_string(option, value, _T("genlock_video"), p->genlock_video_file, sizeof p->genlock_video_file / sizeof(TCHAR))
|| cfgfile_string(option, value, _T ("pci_devices"), p->pci_devices, sizeof p->pci_devices / sizeof(TCHAR))
|| cfgfile_string (option, value, _T("ghostscript_parameters"), p->ghostscript_parameters, sizeof p->ghostscript_parameters / sizeof (TCHAR)))
return 1;
addbcromtype(p, ROMTYPE_NE2KPCMCIA, p->ne2000pcmcianame[0] != 0, NULL, 0);
addbcromtype(p, ROMTYPE_NE2KPCI, p->ne2000pciname[0] != 0, NULL, 0);
- static int restricted_net[] = { ROMTYPE_A2065, ROMTYPE_NE2KPCMCIA, ROMTYPE_NE2KPCI, ROMTYPE_NE2KISA, 0 };
+ static int restricted_net[] = { ROMTYPE_A2065, ROMTYPE_NE2KPCMCIA, ROMTYPE_NE2KPCI, ROMTYPE_NE2KISA, ROMTYPE_ARIADNE2, 0 };
static int restricted_x86[] = { ROMTYPE_A1060, ROMTYPE_A2088, ROMTYPE_A2088T, ROMTYPE_A2286, ROMTYPE_A2386, 0 };
static int restricted_pci[] = { ROMTYPE_GREX, ROMTYPE_MEDIATOR, ROMTYPE_PROMETHEUS, 0 };
romtype_restricted(p, restricted_net);
int genlock_image;
int genlock_mix;
TCHAR genlock_image_file[MAX_DPATH];
+ TCHAR genlock_video_file[MAX_DPATH];
int monitoremu;
double chipset_refreshrate;
struct chipset_refresh cr[MAX_CHIPSET_REFRESH + 2];
--- /dev/null
+
+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
--- /dev/null
+
+/* UAE Win32 Video frame grabber support
+ * Toni Wilen 2016
+ */
+
+#include "sysconfig.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "sysdeps.h"
+#include "options.h"
+
+#include <windows.h>
+#include <dshow.h>
+#include <atlcomcli.h>
+
+#include "videograb.h"
+
+#pragma comment(lib,"Strmiids.lib")
+
+// following have been removed from newer SDKs
+
+static const IID IID_ISampleGrabber = { 0x6B652FFF, 0x11FE, 0x4fce, { 0x92, 0xAD, 0x02, 0x66, 0xB5, 0xD7, 0xC7, 0x8F } };
+static const CLSID CLSID_SampleGrabber = { 0xC1F400A0, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
+static const CLSID CLSID_NullRenderer = { 0xC1F400A4, 0x3F08, 0x11d3, { 0x9F, 0x0B, 0x00, 0x60, 0x08, 0x03, 0x9E, 0x37 } };
+
+interface ISampleGrabberCB : public IUnknown
+{
+ virtual STDMETHODIMP SampleCB(double SampleTime, IMediaSample *pSample) = 0;
+ virtual STDMETHODIMP BufferCB(double SampleTime, BYTE *pBuffer, long BufferLen) = 0;
+};
+interface ISampleGrabber : public IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE SetOneShot(BOOL OneShot) = 0;
+ virtual HRESULT STDMETHODCALLTYPE SetMediaType(const AM_MEDIA_TYPE *pType) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetConnectedMediaType(AM_MEDIA_TYPE *pType) = 0;
+ virtual HRESULT STDMETHODCALLTYPE SetBufferSamples(BOOL BufferThem) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentBuffer(long *pBufferSize, long *pBuffer) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetCurrentSample(IMediaSample **ppSample) = 0;
+ virtual HRESULT STDMETHODCALLTYPE SetCallback(ISampleGrabberCB *pCallback, long WhichMethodToCallback) = 0;
+};
+
+// based on code from: http://forum.devmaster.net/t/generating-textures-from-video-frames/8259
+
+static CComPtr<ICaptureGraphBuilder2> graphBuilder;
+static CComPtr<IFilterGraph2> filterGraph;
+static CComPtr<ISampleGrabber> sampleGrabber;
+static CComPtr<IMediaControl> mediaControl;
+static bool videoInitialized;
+static long *frameBuffer;
+static long bufferSize;
+static int videoWidth, videoHeight;
+
+void uninitvideograb(void)
+{
+ write_log(_T("uninitvideograb\n"));
+
+ videoInitialized = false;
+
+ sampleGrabber.Release();
+ if (mediaControl) {
+ mediaControl->Stop();
+ }
+ mediaControl.Release();
+ filterGraph.Release();
+ graphBuilder.Release();
+
+ delete[] frameBuffer;
+ frameBuffer = NULL;
+}
+
+static void FindPin(IBaseFilter* baseFilter, PIN_DIRECTION direction, int pinNumber, IPin** destPin)
+{
+ CComPtr<IEnumPins> enumPins;
+
+ *destPin = NULL;
+
+ if (SUCCEEDED(baseFilter->EnumPins(&enumPins))) {
+ ULONG numFound;
+ IPin* tmpPin;
+
+ while (SUCCEEDED(enumPins->Next(1, &tmpPin, &numFound))) {
+ PIN_DIRECTION pinDirection;
+
+ tmpPin->QueryDirection(&pinDirection);
+ if (pinDirection == direction) {
+ if (pinNumber == 0) {
+ // Return the pin's interface
+ *destPin = tmpPin;
+ break;
+ }
+ pinNumber--;
+ }
+ tmpPin->Release();
+ }
+ }
+}
+
+static bool ConnectPins(IBaseFilter* outputFilter, unsigned int outputNum, IBaseFilter* inputFilter, unsigned int inputNum)
+{
+ CComPtr<IPin> inputPin;
+ CComPtr<IPin> outputPin;
+
+ if (!outputFilter || !inputFilter) {
+ write_log(_T("ConnectPins OUT=%d IN=%d\n"), outputFilter != 0, inputFilter != 0);
+ return false;
+ }
+
+ FindPin(outputFilter, PINDIR_OUTPUT, outputNum, &outputPin);
+ FindPin(inputFilter, PINDIR_INPUT, inputNum, &inputPin);
+
+ if (inputPin && outputPin) {
+ HRESULT hr = filterGraph->Connect(outputPin, inputPin);
+ if (SUCCEEDED(hr))
+ return true;
+ write_log(_T("ConnectPins Connect %08x\n"), hr);
+ } else {
+ write_log(_T("ConnectPins OUTPIN=%d INPIN=%d\n"), outputPin != 0, inputPin != 0);
+
+ }
+ return false;
+}
+
+bool initvideograb(const TCHAR *filename)
+{
+ HRESULT hr;
+
+ uninitvideograb();
+
+ write_log(_T("initvideograb '%s'\n"), filename ? filename : _T("<null>"));
+
+ graphBuilder.CoCreateInstance(CLSID_CaptureGraphBuilder2);
+ filterGraph.CoCreateInstance(CLSID_FilterGraph);
+ graphBuilder->SetFiltergraph(filterGraph);
+ CComPtr<IBaseFilter> sourceFilter;
+
+ if (filename != NULL && filename[0]) {
+ // This takes the absolute filename path and
+ // Loads the appropriate file reader and splitter
+ // Depending in the file type.
+ hr = filterGraph->AddSourceFilter(filename, L"Video Source", &sourceFilter);
+ if (FAILED(hr)) {
+ write_log(_T("AddSourceFilter failed %08x\n"), hr);
+ uninitvideograb();
+ return false;
+ }
+ } else {
+ // capture device mode
+ IMoniker *pMoniker;
+ CComPtr<ICreateDevEnum> pCreateDevEnum;
+ hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void**)&pCreateDevEnum);
+ if (FAILED(hr)) {
+ write_log(_T("CLSID_SystemDeviceEnum IID_ICreateDevEnum failed %08x\n"), hr);
+ uninitvideograb();
+ return false;
+ }
+ CComPtr<IEnumMoniker> pEmum;
+ hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEmum, 0);
+ if (FAILED(hr)) {
+ write_log(_T("CreateClassEnumerator CLSID_VideoInputDeviceCategory failed %08x\n"), hr);
+ uninitvideograb();
+ return false;
+ }
+ if (hr == S_FALSE) {
+ write_log(_T("initvideograb CreateDevEnum: didn't find any capture devices.\n"));
+ uninitvideograb();
+ return false;
+ }
+ pEmum->Reset();
+ ULONG cFetched = 0;
+ //Take the first capture device found
+ hr = pEmum->Next(1, &pMoniker, &cFetched);
+ if (FAILED(hr)) {
+ write_log(_T("initvideograb Next: didn't find any capture devices.\n"));
+ uninitvideograb();
+ return false;
+ }
+ pMoniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&sourceFilter);
+ pMoniker->Release();
+ filterGraph->AddFilter(sourceFilter, L"Video Capture");
+ }
+
+ // Create the Sample Grabber which we will use
+ // To take each frame for texture generation
+ CComPtr<IBaseFilter> grabberFilter;
+ grabberFilter.CoCreateInstance(CLSID_SampleGrabber);
+ grabberFilter->QueryInterface(IID_ISampleGrabber, reinterpret_cast<void**>(&sampleGrabber));
+
+ filterGraph->AddFilter(grabberFilter, L"Sample Grabber");
+
+ // We have to set the 24-bit RGB desire here
+ // So that the proper conversion filters
+ // Are added automatically.
+ AM_MEDIA_TYPE desiredType;
+ memset(&desiredType, 0, sizeof(desiredType));
+ desiredType.majortype = MEDIATYPE_Video;
+ desiredType.subtype = MEDIASUBTYPE_RGB24;
+ desiredType.formattype = FORMAT_VideoInfo;
+
+ sampleGrabber->SetMediaType(&desiredType);
+ sampleGrabber->SetBufferSamples(TRUE);
+
+ // Use pin connection methods instead of
+ // ICaptureGraphBuilder::RenderStream because of
+ // the SampleGrabber setting we're using.
+ if (!ConnectPins(sourceFilter, 0, grabberFilter, 0)) {
+ uninitvideograb();
+ return false;
+ }
+
+ // A Null Renderer does not display the video
+ // But it allows the Sample Grabber to run
+ // And it will keep proper playback timing
+ // Unless specified otherwise.
+ CComPtr<IBaseFilter> nullRenderer;
+ nullRenderer.CoCreateInstance(CLSID_NullRenderer);
+
+ filterGraph->AddFilter(nullRenderer, L"Null Renderer");
+
+ if (!ConnectPins(grabberFilter, 0, nullRenderer, 0)) {
+ uninitvideograb();
+ return false;
+ }
+
+ // Just a little trick so that we don't have to know
+ // The video resolution when calling this method.
+ bool mediaConnected = false;
+ AM_MEDIA_TYPE connectedType;
+ if (SUCCEEDED(sampleGrabber->GetConnectedMediaType(&connectedType))) {
+ if (connectedType.formattype == FORMAT_VideoInfo) {
+ VIDEOINFOHEADER* infoHeader = (VIDEOINFOHEADER*)connectedType.pbFormat;
+ videoWidth = infoHeader->bmiHeader.biWidth;
+ videoHeight = infoHeader->bmiHeader.biHeight;
+ mediaConnected = true;
+ }
+ CoTaskMemFree(connectedType.pbFormat);
+ }
+
+ if (!mediaConnected) {
+ uninitvideograb();
+ return false;
+ }
+
+ hr = filterGraph->QueryInterface(IID_IMediaControl, (void**)&mediaControl);
+ if (FAILED(hr)) {
+ uninitvideograb();
+ return false;
+ }
+ if (SUCCEEDED(mediaControl->Run())) {
+ videoInitialized = true;
+ return true;
+ } else {
+ uninitvideograb();
+ return false;
+ }
+}
+
+void pausevideograb(bool pause)
+{
+ if (!videoInitialized)
+ return;
+ if (pause) {
+ mediaControl->Pause();
+ } else {
+ mediaControl->Run();
+ }
+}
+
+bool getvideograb(long **buffer, int *width, int *height)
+{
+ HRESULT hr;
+
+ if (!videoInitialized)
+ return false;
+
+ // Only need to do this once
+ if (!frameBuffer) {
+ // The Sample Grabber requires an arbitrary buffer
+ // That we only know at runtime.
+ // (width * height * 3) bytes will not work.
+ hr = sampleGrabber->GetCurrentBuffer(&bufferSize, NULL);
+ if (FAILED(hr)) {
+ write_log(_T("getvideograb get size %08x\n"), hr);
+ return false;
+ }
+ frameBuffer = new long[bufferSize];
+ }
+
+ hr = sampleGrabber->GetCurrentBuffer(&bufferSize, (long*)frameBuffer);
+ if (SUCCEEDED(hr)) {
+ *buffer = frameBuffer;
+ *width = videoWidth;
+ *height = videoHeight;
+ return true;
+ }
+ write_log(_T("getvideograb get buffer %08x\n"), hr);
+ return false;
+}
#include "specialmonitors.h"
#include "debug.h"
#include "zfile.h"
+#include "videograb.h"
+
+#define VIDEOGRAB 1
+
static int opal_debug = 1;
return true;
}
-static uae_u8 *genlock_image;
+static uae_u8 *genlock_image_data;
+static bool genlock_video;
static int genlock_image_width, genlock_image_height, genlock_image_pitch;
+static TCHAR genlock_video_file[MAX_DPATH], genlock_image_file[MAX_DPATH];
static uae_u8 noise_buffer[1024];
static uae_u32 noise_seed, noise_add, noise_index;
+static bool genlock_error;
static uae_u32 quickrand(void)
{
cb->size -= count;
}
-static void load_genlock_image(void)
+static bool load_genlock_image(void)
{
extern unsigned char test_card_png[];
extern unsigned int test_card_png_len;
struct png_cb cb;
png_bytepp row_pp;
png_size_t cols;
+ bool ok = false;
- xfree(genlock_image);
- genlock_image = NULL;
+ xfree(genlock_image_data);
+ genlock_image_data = NULL;
- if (currprefs.genlock_image == 3) {
+ if (currprefs.genlock_image_file[0] && currprefs.genlock_image == 3) {
int size;
uae_u8 *bb = zfile_load_file(currprefs.genlock_image_file, &size);
- if (bb) {
- file_size = size;
- b = bb;
- bfree = bb;
- }
+ if (!bb)
+ goto end;
+ file_size = size;
+ b = bb;
+ bfree = bb;
}
if (!png_check_sig(b, 8))
row_pp = new png_bytep[height];
- genlock_image = xcalloc(uae_u8, width * height * 4);
+ genlock_image_data = xcalloc(uae_u8, width * height * 4);
for (int i = 0; i < height; i++) {
- row_pp[i] = (png_bytep) &genlock_image[i * genlock_image_pitch];
+ row_pp[i] = (png_bytep) &genlock_image_data[i * genlock_image_pitch];
}
png_read_image(png_ptr, row_pp);
png_destroy_read_struct(&png_ptr, &info_ptr, 0);
delete[] row_pp;
+
+ ok = true;
end:
xfree(bfree);
+
+ return ok;
}
static bool do_genlock(struct vidbuffer *src, struct vidbuffer *dst, bool doublelines, int oddlines)
{
int y, x, vdbl, hdbl;
int ystart, yend, isntsc;
- int gl_vdbl_l, gl_vdbl_r;
+ int gl_vdbl_l, gl_vdbl_r, gl_vdbl;
int gl_hdbl_l, gl_hdbl_r, gl_hdbl;
int gl_hcenter, gl_vcenter;
int mix1 = 0, mix2 = 0;
+ int genlock_image_pixbytes = 4;
+ int genlock_image_red_index = 0;
+ int genlock_image_green_index = 1;
+ int genlock_image_blue_index = 2;
+ bool genlock_image_upsidedown = false;
+
+ uae_u8 *genlock_image = NULL;
+
isntsc = (beamcon0 & 0x20) ? 0 : 1;
if (!(currprefs.chipset_mask & CSMASK_ECS_AGNUS))
isntsc = currprefs.ntscmode ? 1 : 0;
- if (!genlock_image && currprefs.genlock_image == 2) {
- load_genlock_image();
+#if VIDEOGRAB
+ if (currprefs.genlock_image == 5) {
+ if ((!genlock_video && !genlock_error) || _tcsicmp(_T(":CAPTURE:"), genlock_video_file)) {
+ _tcscpy(genlock_video_file, _T(":CAPTURE:"));
+ genlock_video = initvideograb(NULL);
+ if (!genlock_video) {
+ genlock_error = true;
+ }
+ } else {
+ genlock_error = true;
+ }
+ int vidw = 0, vidh = 0;
+ long *vidbuf = NULL;
+ if (genlock_video && getvideograb(&vidbuf, &vidw, &vidh)) {
+ genlock_image = (uae_u8*)vidbuf;
+ genlock_image_width = vidw;
+ genlock_image_height = vidh;
+ genlock_image_pixbytes = 3;
+ genlock_image_pitch = genlock_image_width * genlock_image_pixbytes;
+ genlock_image_red_index = 2;
+ genlock_image_green_index = 1;
+ genlock_image_blue_index = 0;
+ genlock_image_upsidedown = true;
+ genlock_error = false;
+ }
+ else {
+ genlock_error = true;
+ }
+ } else if (currprefs.genlock_image == 4) {
+ if (currprefs.genlock_video_file[0]) {
+ if ((!genlock_video && !genlock_error) || _tcsicmp(currprefs.genlock_video_file, genlock_video_file)) {
+ _tcscpy(genlock_video_file, currprefs.genlock_video_file);
+ genlock_video = initvideograb(currprefs.genlock_video_file);
+ if (!genlock_video) {
+ genlock_error = true;
+ }
+ }
+ } else {
+ genlock_error = true;
+ }
+ int vidw = 0, vidh = 0;
+ long *vidbuf = NULL;
+ if (genlock_video && getvideograb(&vidbuf, &vidw, &vidh)) {
+ genlock_image = (uae_u8*)vidbuf;
+ genlock_image_width = vidw;
+ genlock_image_height = vidh;
+ genlock_image_pixbytes = 3;
+ genlock_image_pitch = genlock_image_width * genlock_image_pixbytes;
+ genlock_image_red_index = 2;
+ genlock_image_green_index = 1;
+ genlock_image_blue_index = 0;
+ genlock_image_upsidedown = true;
+ genlock_error = false;
+ } else {
+ genlock_error = true;
+ }
}
- if (genlock_image && currprefs.genlock_image != 2) {
- xfree(genlock_image);
- genlock_image = NULL;
+#endif
+ if (currprefs.genlock_image == 1) {
+ genlock_error = false;
+ } else if (currprefs.genlock_image == 2) {
+ genlock_error = false;
+ if (!genlock_image_data) {
+ load_genlock_image();
+ }
+ genlock_image = genlock_image_data;
+ } else if (currprefs.genlock_image == 3) {
+ if (!currprefs.genlock_image_file[0]) {
+ genlock_error = true;
+ } else {
+ if ((!genlock_image_data && !genlock_error) || _tcsicmp(genlock_image_file, currprefs.genlock_image_file)) {
+ _tcscpy(genlock_image_file, currprefs.genlock_image_file);
+ genlock_error = load_genlock_image() == 0;
+ }
+ }
+ genlock_image = genlock_image_data;
+ }
+
+ if (genlock_image_data && currprefs.genlock_image != 2 && currprefs.genlock_image != 3) {
+ xfree(genlock_image_data);
+ genlock_image_data = NULL;
+ }
+#if VIDEOGRAB
+ if (genlock_video && currprefs.genlock_image != 4 && currprefs.genlock_image != 5) {
+ uninitvideograb();
+ genlock_video = false;
+ }
+#endif
+ if (currprefs.genlock_image != 4 && currprefs.genlock_image != 5) {
+ genlock_video_file[0] = 0;
+ }
+ if (currprefs.genlock_image != 3) {
+ genlock_image_file[0] = 0;
}
if (gfxvidinfo.xchange == 1)
- hdbl = 0;
+ hdbl = 0; // shres
else if (gfxvidinfo.xchange == 2)
- hdbl = 1;
+ hdbl = 1; // hires
else
- hdbl = 2;
+ hdbl = 2; // lores
gl_hdbl_l = gl_hdbl_r = 0;
if (genlock_image_width < 600) {
- gl_hdbl = 0;
- } else if (genlock_image_width < 1000) {
+ gl_hdbl = 2;
+ } else if (genlock_image_width < 1300) {
gl_hdbl = 1;
} else {
- gl_hdbl = 2;
+ gl_hdbl = 0;
}
if (hdbl >= gl_hdbl) {
gl_hdbl_l = hdbl - gl_hdbl;
}
if (gfxvidinfo.ychange == 1)
- vdbl = 0;
+ vdbl = 0; // double
else
- vdbl = 1;
+ vdbl = 1; // single
gl_vdbl_l = gl_vdbl_r = 0;
+ if (genlock_image_height < 400) {
+ gl_vdbl = 1;
+ } else {
+ gl_vdbl = 0;
+ }
+ if (vdbl >= gl_vdbl) {
+ gl_vdbl_l = vdbl - gl_vdbl;
+ } else {
+ gl_vdbl_r = gl_vdbl - vdbl;
+ }
- gl_hcenter = (genlock_image_width - ((src->inwidth << hdbl) >> gl_hdbl)) / 2;
+ gl_hcenter = (((genlock_image_width << gl_hdbl_r) >> gl_hdbl_l) - src->inwidth) / 2;
ystart = isntsc ? VBLANK_ENDLINE_NTSC : VBLANK_ENDLINE_PAL;
yend = isntsc ? MAXVPOS_NTSC : MAXVPOS_PAL;
- gl_vcenter = (((genlock_image_height << gl_vdbl_l) >> gl_vdbl_r) - (((yend - ystart) * 2))) / 2;
+ gl_vcenter = (((genlock_image_height << gl_vdbl_r) >> gl_vdbl_l) - (((yend - ystart) * 2))) / 2;
init_noise();
uae_u8 *line = src->bufmem + yoff * src->rowbytes;
uae_u8 *dstline = dst->bufmem + (((y * 2 + oddlines) - dst->yoffset) >> vdbl) * dst->rowbytes;
uae_u8 *line_genlock = row_map_genlock[yoff];
- int gy = ((((y * 2 + oddlines) - dst->yoffset) << gl_vdbl_l) >> gl_vdbl_r) + gl_vcenter;
+ int gy = ((((y * 2 + oddlines) - dst->yoffset + gl_vcenter) >> gl_vdbl_r) << gl_vdbl_l);
+ if (genlock_image_upsidedown)
+ gy = (genlock_image_height - 1) - gy;
uae_u8 *image_genlock = genlock_image + gy * genlock_image_pitch;
r = g = b = 0;
noise_add = (quickrand() & 15) | 1;
uae_u8 *d2 = d + dst->rowbytes;
if (is_transparent(*s_genlock)) {
- if (genlock_image) {
- int gx = (((x + gl_hcenter) << gl_hdbl_l) >> gl_hdbl_r);
+ if (genlock_error) {
+ r = 0x00;
+ g = 0x00;
+ b = 0xdd;
+ } else if (genlock_image) {
+ int gx = (((x + gl_hcenter) >> gl_hdbl_r) << gl_hdbl_l);
if (gx >= 0 && gx < genlock_image_width && gy >= 0 && gy < genlock_image_height) {
- uae_u8 *s_genlock_image = image_genlock + gx * 4;
- r = s_genlock_image[0];
- g = s_genlock_image[1];
- b = s_genlock_image[2];
+ uae_u8 *s_genlock_image = image_genlock + gx * genlock_image_pixbytes;
+ r = s_genlock_image[genlock_image_red_index];
+ g = s_genlock_image[genlock_image_green_index];
+ b = s_genlock_image[genlock_image_blue_index];
} else {
r = g = b = 0;
}
}
if (c[18] || c[19] || c[11])
write_log(_T("UNIMPLEMENTED BITS!\n"));
- opal->dual_play = c[7];
- opal->latched = c[10];
- opal->wren = c[4];
- opal->colcopro = c[5];
+ opal->dual_play = c[7] != 0;
+ opal->latched = c[10] != 0;
+ opal->wren = c[4] != 0;
+ opal->colcopro = c[5] != 0;
opal->bank_field = c[8];
- opal->auto_field = c[9];
+ opal->auto_field = c[9] != 0;
opal->active_banks[0] = c[12];
opal->active_banks[1] = c[13];
opal->active_banks[2] = c[14];
}
if (c[15])
write_log(_T("UNIMPLEMENTED BITS!\n"));
- opal->wren = c[4];
- opal->colcopro = c[5];
+ opal->wren = c[4] != 0;
+ opal->colcopro = c[5] != 0;
opal->bank_field = c[11];
opal->auto_field = false;
opal->active_banks[0] = c[8];
{
if (!currprefs.monitoremu)
return;
+ uninitvideograb();
specialmonitor_store_fmode(-1, -1, 0);
fc24_reset();
}