/*
 * videowin.cpp
 *
 *  Created on: 03/mar/2022
 *      Author: chessaa
 */


#include "videowin.h"

#include "windows.h"
#include "windowsx.h"

#include <stdio.h>
#include <stdint.h>

#include "AviFile.h"

#include "gtl_cmdio.h"

static const int DX=640;
static const int DY=512;


static char video_src_file_name[512];

static HINSTANCE myInstance()
{
	return GetModuleHandle(NULL);
}

struct WinCx
{
	int display_num;
	unsigned int win_flags;
	bool standalone;
	int ox;
	int oy;
	unsigned int wbg;

	HINSTANCE hInstance;
	HANDLE mutex;
	HANDLE evn;
	HANDLE thread;

	HWND window;
    BITMAPINFO bmi;
    HBITMAP hBmi;

    uint32_t* ppvBits;

    HDC hdc;
    HDC hBmiDC;

    HICON hIcon;

    HMENU hMenu;

    HBRUSH hBg;

    char win_title[512];

    float el_pos;
};

static WinCx winCx;



static VOID APIENTRY DisplayContextMenu(HWND hwnd, POINT pt)
{
#if 0
    HMENU hmenu=winCx.hMenu;            // top-level menu
    HMENU hmenuTrackPopup;  // shortcut menu

    // Load the menu resource.

    //if ((hmenu = LoadMenu(winCx.hInstance, "DisplayContextMenu")) == NULL)
    //    return;

    if (hmenu ==0)
    		return;

    // TrackPopupMenu cannot display the menu bar so get
    // a handle to the first shortcut menu.

    hmenuTrackPopup = GetSubMenu(hmenu, 0);


    CheckMenuItem(hmenuTrackPopup, 1, RisStartIsRecording() ? MF_CHECKED : MF_UNCHECKED);

    CheckMenuItem(hmenuTrackPopup, 21, RisTargetsEnabled() ? MF_CHECKED : MF_UNCHECKED);

    CheckMenuItem(hmenuTrackPopup, 30, mode_label_view_hide ? MF_CHECKED : MF_UNCHECKED);

    CheckMenuItem(hmenuTrackPopup, 31, RisShowOnScreenExtraInfoVisible()/*cmp_dbg_display_hide_!=0xFFFFFFFF*/ ? MF_CHECKED : MF_UNCHECKED);

    CheckMenuItem(hmenuTrackPopup, 40, RisWowStatus() ? MF_CHECKED : MF_UNCHECKED);

    CheckMenuItem(hmenuTrackPopup, 50, bsk_rtg_win32_console_log_is_open() ? MF_CHECKED : MF_UNCHECKED);

    unsigned int fmask=RisBite::getFailMask();
    CheckMenuItem(hmenuTrackPopup, 401, (fmask & RisBite::unit_rep) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hmenuTrackPopup, 402, (fmask & RisBite::unit_aesa) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hmenuTrackPopup, 403, (fmask & RisBite::unit_pps) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hmenuTrackPopup, 404, (fmask & RisBite::unit_lcu) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hmenuTrackPopup, 405, (fmask & RisBite::unit_cal) ? MF_CHECKED : MF_UNCHECKED);

    CheckMenuItem(hmenuTrackPopup, 411, (fmask & (RisBite::unit_rep<<8)) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hmenuTrackPopup, 412, (fmask & (RisBite::unit_aesa<<8)) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hmenuTrackPopup, 413, (fmask & (RisBite::unit_pps<<8)) ? MF_CHECKED : MF_UNCHECKED);
    CheckMenuItem(hmenuTrackPopup, 414, (fmask & (RisBite::unit_lcu<<8)) ? MF_CHECKED : MF_UNCHECKED);

    //Check scenarios
    {
    	for (int i=1; i<=7; ++i)
    	{
    		char buffer[256];
    		snprintf(buffer, sizeof buffer, RIS_USER_FOLDER "\\scenario_%d.txt", i);
    		FILE* fd=fopen(buffer, "r");
    		if (fd)
    		{
    			EnableMenuItem(hmenuTrackPopup, 12+i, MF_ENABLED);
    		}
    		else
    		{
    			EnableMenuItem(hmenuTrackPopup, 12+i, MF_GRAYED);
    		}
    	}
    }

    // Display the shortcut menu. Track the right mouse
    // button.

    TrackPopupMenu(hmenuTrackPopup,
            TPM_LEFTALIGN | TPM_RIGHTBUTTON,
            pt.x, pt.y, 0, hwnd, NULL);

    // Destroy the menu.

    //DestroyMenu(hmenu);
#endif
}

static BOOL WINAPI OnContextMenu(HWND hwnd, int x, int y, bool check_pos=true)
{
    POINT pt = { x, y };        // location of mouse click


    if (check_pos)
    {
        RECT rc;                    // client area of window
        // Get the bounding rectangle of the client area.
        // If the position is in the client area, display a
        // shortcut menu.
        GetClientRect(hwnd, &rc);
        // Convert the mouse position to client coordinates.
        ScreenToClient(hwnd, &pt);
		if (PtInRect(&rc, pt))
		{
			ClientToScreen(hwnd, &pt);
			DisplayContextMenu(hwnd, pt);
			return TRUE;
		}
    }
    else
    {
		DisplayContextMenu(hwnd, pt);
		return TRUE;
    }

    return FALSE;
}


void rtg_win32_menu_shortcut()
{
	POINT pos;
	GetCursorPos(&pos);
	//OnContextMenu(winCx.window, pos.x, pos.y, false);
	if (winCx.window)
		SendNotifyMessage(winCx.window, WM_COMMAND, 500, pos.x|(pos.y<<16));
}

static LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	enum { IDM_REC_START=1, IDM_REC_STOP=2};

	static bool mouseCapture=false;
	//static int xPos=0;
	//static int yPos=0;

	    HDC hdc;
	    PAINTSTRUCT ps;

	    switch (message)
	    {
	    case WM_MOUSELEAVE:
	    	mouseCapture=false;
	    	break;

	    case WM_MOUSEWHEEL:
	    	{
	    		short delta=HIWORD(wParam);
	    		if (delta>0)
	    		{
	    			winCx.el_pos+=0.017453293;
	    			if (winCx.el_pos>2)
	    				winCx.el_pos=2;
	    		}
	    		else if (delta<0)
	    		{
	    			winCx.el_pos-=0.017453293;
	    			if (winCx.el_pos<-2)
	    				winCx.el_pos=-2;
	    		}
	    	}
	    	break;

	    case WM_LBUTTONUP:
	    	mouseCapture=false;
    		//if (winCx.mcs)
    		//	winCx.mcs->setMoveCursor(0, 0, false);
	    	break;

	    case WM_LBUTTONDOWN:
	    	mouseCapture=true;
#if 0
	    	xPos=GET_X_LPARAM(lParam);
	    	yPos=GET_Y_LPARAM(lParam);
    		if (winCx.mcs)
    			winCx.mcs->setMoveCursor(0, 0, false);
#endif
	    	break;

	    case WM_MOUSEMOVE:
	    	if (mouseCapture && (LOWORD(wParam) & MK_LBUTTON))
	    	{
	    		//int xNew = GET_X_LPARAM(lParam);
	    		//int yNew = GET_Y_LPARAM(lParam);

	    		//if (winCx.mcs)
	    		//	winCx.mcs->setMoveCursor(xNew-xPos, yNew-yPos, true);

	    		//xPos=xNew;
	    		//yPos=yNew;
	    	}
	    	break;

	    case WM_DROPFILES:
	    	{
	    		static char dropped_file[2048];
	    		HDROP hDrop=(HDROP)wParam;
	    		UINT r=DragQueryFileA(hDrop, 0xFFFFFFFF, dropped_file, sizeof dropped_file);
	    		if (r==1)
	    		{
		    		r=DragQueryFileA(hDrop, 0, dropped_file, sizeof dropped_file);
	    			//printf("Dropped file: %s\n", dropped_file);
		    		if (r)
		    		{
		    			//process_dropped_file(dropped_file);
		    		}
	    		}
	    		DragFinish(hDrop);
	    	}
	    	return 0;

	    case WM_CONTEXTMENU:
	        if (OnContextMenu(hWnd, GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)))
	        	return 0;
	        break;
	    case WM_COMMAND:
	    	switch(LOWORD(wParam))
	    	{
	    	default:
	    		//if (processMcs(LOWORD(wParam)))
				//	return 0;
	    		break;

	    	case 500:
	    	{
	    		OnContextMenu(hWnd, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam), false);
	    		return 0;
	    	}
	    	case IDM_REC_START:
#if 0
	    		if (RisStartIsRecording())
		    		RisStopRecorder();
	    		else
	    			RisStartRecorder();
#endif
	    		return 0;
#if 0
	    	case IDM_REC_STOP:
	    		RisStopRecorder();
	    		return 0;
#endif
	    	case 10:
	    	case 11:
	    	case 12:
	    		//RadarInterfaceSimulator::instance().runScenario(LOWORD(wParam)-10);
	    		return 0;
	    	case 13:
	    	case 14:
	    	case 15:
	    	case 16:
	    	case 17:
	    	case 18:
	    	case 19:
	    		{
	        		//char buffer[256];
	        		//snprintf(buffer, sizeof buffer, RIS_USER_FOLDER "\\scenario_%d.txt", LOWORD(wParam)-12);
	    			//process_dropped_file(buffer);
	    		}
	    		return 0;
	    	case 20://restart
	    		//RisTargetsRestartAll();
	    		return 0;
	    	case 21:
#if 0
	    		{
	    			bool active=RisTargetsEnabled();
	    			if (active)
	    				RisTargetsStopAll();
	    			else
	    				RisTargetsContinueAll();
	    		}
#endif
	    		return 0;
#if 0
	    	case 21://stop
	    		RisTargetsStopAll();
	    		//SimpleTgtSimInfo::instance().enabled=0;
	    		return 0;
	    	case 22://continue
	    		RisTargetsContinueAll();
	    		SimpleTgtSimInfo::instance().enabled=1;
	    		return 0;
#endif
	    	case 30:
	    		{
	    			//mode_label_view_hide=!mode_label_view_hide;
	    			//GraphicComputerFactory::instance().setForceWDNSFailInfoFlag(mode_label_view_hide);
	    		}
	    		return 0;
	    	case 31:
#if 0
	    		{
	    			if (RisShowOnScreenExtraInfoVisible())
	    				RisShowOnScreenExtraInfo(false);
	    			else
	    				RisShowOnScreenExtraInfo(true);
	    		}
#endif
	    		return 0;
	    	case 40: //WoW
	    		{
	    			//bool active=RisWowStatus();
	    			//RisWowSimulate(active ? false : true);
	    		}
	    		return 0;
	    	case 50:
	    		{
#if 0
	    			bool is_open=bsk_rtg_win32_console_log_is_open();
	    			if (is_open)
	    				bsk_rtg_win32_console_log_close();
	    			else
	    				bsk_rtg_win32_console_log_open(RIS_REC_FOLDER);
#endif
	    		}
	    		return 0;
	    	case 80:
	    		//openFolder(RIS_USER_FOLDER);
	    		return 0;
	    	case 81:
	    		//openFolder(RIS_REC_FOLDER);
	    		return 0;

	    	case 400:
	    		//RisBite::resetFail();
	    		return 0;
	    	case 401:
	    		//RisBite::setFailMask(RisBite::unit_rep, -1);
	    		return 0;
	    	case 402:
	    		//RisBite::setFailMask(RisBite::unit_aesa, -1);
	    		return 0;
	    	case 403:
	    		//RisBite::setFailMask(RisBite::unit_pps, -1);
	    		return 0;
	    	case 404:
	    		//RisBite::setFailMask(RisBite::unit_lcu, -1);
	    		return 0;
	    	case 405:
	    		//RisBite::setFailMask(RisBite::unit_cal, -1);
	    		return 0;
	    	case 411:
	    		//RisBite::setOvertemp(RisBite::unit_rep, -1);
	    		return 0;
	    	case 412:
	    		//RisBite::setOvertemp(RisBite::unit_aesa, -1);
	    		return 0;
	    	case 413:
	    		//RisBite::setOvertemp(RisBite::unit_pps, -1);
	    		return 0;
	    	case 414:
	    		//RisBite::setOvertemp(RisBite::unit_lcu, -1);
	    		return 0;
	    	}
	    	break;
	    case WM_CLOSE:
	    	return 0;
	    	//break;
	    case WM_PAINT:
	        hdc = BeginPaint (hWnd, &ps);
	        //SetDIBitsToDevice(hdc, 0, 0, 512, 512, 0, 0, 0, 0, winCx.ppvBits, &winCx.bmi, DIB_RGB_COLORS);
	        //HDC hdcSrc=CreateCompatibleDC(hdc);
	        SelectObject(winCx.hBmiDC, winCx.hBmi);
	        {
	        	BitBlt(hdc, winCx.ox, winCx.oy, DX, DY, winCx.hBmiDC, 0, 0, SRCCOPY);
	        }
	        //SetBkColor(hdc, 0);
	        //SetTextColor(hdc, 0xFFFFFF);
	        //TextOutA(hdc, 0, 486, video_src_file_name, strlen(video_src_file_name));

	        EndPaint(hWnd, &ps);
	        //ADD_FRAME_FROM_DIB_TO_AVI(winCx.hBmi, 0,  25);
	        break;
#if 0
	        //get the dimensions of the window
	        GetClientRect(hWnd, &rt);

	        //start drawing on devicce context
	        hdc = BeginPaint (hWnd, &ps);

	        //draw some text
	        DrawText(hdc, szHello, strlen(szHello), &rt, DT_CENTER);
	        j = (rand()*100);

	        c = RGB(0, 0, 0);

	        while( x<25000)
	        {

	            SetPixel(hdc,  rand()%400,  rand()%400, rand()%255);
	            x++;
	        }

	        //stop drawing
	        EndPaint(hWnd, &ps);
#endif
	        break;

	    case WM_DESTROY:
	        PostQuitMessage(0);
	        break;
	    }
	    return DefWindowProc(hWnd, message, wParam, lParam);
}

static ATOM MyRegisterClass(HINSTANCE hInstance)
{
   //create the window class structure
	WNDCLASSEX wc;
	wc.cbSize = sizeof(WNDCLASSEX);

	HICON hIcon=LoadIconA(hInstance, MAKEINTRESOURCEA(0));
	//if (hIcon==0)
	//	hIcon=LoadIconA(0, IDI_QUESTION);

	unsigned int r=0;
	unsigned int g=128;
	unsigned int b=0;

	if (winCx.win_flags & (1<<10))
		winCx.hBg=CreateSolidBrush(winCx.wbg);
	else
		winCx.hBg=CreateSolidBrush(RGB(r, g, b));
#if 0
	HWND hConsole=GetConsoleWindow();
	if (hConsole)
	{
		//SetClassLongPtr(hConsole, GCLP_HICON, (LONG_PTR)hIcon);
		SendMessage(hConsole, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
		SendMessage(hConsole, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
	}
#endif
	//fill the struct with info
	wc.style                 = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc           = (WNDPROC)WinProc;
	wc.cbClsExtra            = 0;
	wc.cbWndExtra            = 0;
	wc.hInstance             = hInstance;
	wc.hIcon                 = hIcon;
	wc.hCursor               = LoadCursor(0, IDC_ARROW);
	wc.hbrBackground         = winCx.hBg; //(HBRUSH) GetStockObject(DKGRAY_BRUSH); //BLACK_BRUSH,WHITE_BRUSH;
	wc.lpszMenuName          = 0;
	wc.lpszClassName         = "GRIFO-E-RIS-Window";
	wc.hIconSm               = 0;

	//set up the window with the class info
	return RegisterClassEx(&wc);
}


static DWORD WINAPI WinThread(void* /*arg*/)
{
	//static char win_title[2048];

	winCx.hInstance=myInstance();

	MyRegisterClass(winCx.hInstance);

    winCx.bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    winCx.bmi.bmiHeader.biWidth = DX;
    winCx.bmi.bmiHeader.biHeight = DY;
    winCx.bmi.bmiHeader.biPlanes = 1;
    winCx.bmi.bmiHeader.biBitCount = 32;
    winCx.bmi.bmiHeader.biCompression = BI_RGB;
    winCx.bmi.bmiHeader.biSizeImage = 0;
    winCx.bmi.bmiHeader.biXPelsPerMeter = 1;
    winCx.bmi.bmiHeader.biYPelsPerMeter = 1;
    winCx.bmi.bmiHeader.biClrUsed = 0;
    winCx.bmi.bmiHeader.biClrImportant = 0;


    DWORD wFlags=(DWORD)(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE);

    bool border_less=false; //winCx.win_flags & ris_win_flag_set_boarderless;
    if (border_less)//border less
    {
		wFlags=WS_POPUP|WS_VISIBLE;
    }
    //else
    //	wFlags|=WS_THICKFRAME;


    RECT rect;
    rect.left=0;
    rect.top= 0;
    rect.right= DX - 1;
    rect.bottom= DY - 1;
    //AdjustWindowRect(&rect,WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,false);
    AdjustWindowRect(&rect,wFlags/*WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX |WS_THICKFRAME*/,false);
    int border1 = (int)((rect.right - rect.left + 1 - DX)/2);
    int border2 = (int)(rect.bottom - rect.top + 1 - DY - border1);

    int wx=0;
    int wy=0;

    bool full_screen=false; //winCx.win_flags & ris_win_flag_set_fullscreen;

    if (border_less)
    {
    	border1=0;
    	border2=0;
    	if (full_screen)
    	{
    		wx=0;
    		wy=0;
    	}
    	else
    	{
    		wx=winCx.ox;
    		wy=winCx.oy;
    	}
    }

    int ww = DX + 2*border1;
    int wh = DY + border1 + border2;


    if (full_screen)
    {
    	POINT pt={0,0};
    	HMONITOR hM=MonitorFromPoint(pt,MONITOR_DEFAULTTOPRIMARY);
    	BOOL mOk=FALSE;
    	static MONITORINFO minfo;
    	minfo.cbSize=sizeof minfo;

    	if (hM)
    	{
    		mOk=GetMonitorInfo(hM, &minfo);
    		wx=0;
    		wy=0;
    	}

    	if ((winCx.display_num) && mOk)
    	{
    		wy=0;
    		if (winCx.display_num>0)  //right
    		{
    			wx=minfo.rcMonitor.right;
        		pt.x=wx+100;
    		}
    		else
    		{
    			wx=minfo.rcMonitor.left;
        		pt.x=wx-100;
    		}
    		hM=MonitorFromPoint(pt,MONITOR_DEFAULTTOPRIMARY);
    		mOk=GetMonitorInfo(hM, &minfo);
    		if (mOk && (winCx.display_num<0))
    		{
    			wx=minfo.rcMonitor.left;
    		}
    		else
    			wx=minfo.rcMonitor.left;
    	}
    	if (mOk)
    	{
    		ww=minfo.rcMonitor.right-minfo.rcMonitor.left;
    		wh=minfo.rcMonitor.bottom-minfo.rcMonitor.top;
    		//wFlags=WS_POPUP|WS_VISIBLE;
    	}
    	//printf("\nSecondary Monitor: %d", wx);
    }
    else
    {
    	winCx.ox=0;
    	winCx.oy=0;
    }
    //wx+=winCx.ox;
    //wy+=winCx.oy;

	//printf("\n**Window #%d,%d  %dx%d\n", wx, wy, ww, wh);

    snprintf(winCx.win_title, sizeof winCx.win_title, "GRIFO-E RIS Display"); // %s", versign_application_signature_.data.vstr);//, versign_application_ext_signature_.data.buildid);

    winCx.window = CreateWindowA("GRIFO-E-RIS-Window", winCx.win_title, //"GRIFO-E RIS Display",
                                  wFlags, //(DWORD)(WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE),
                                  wx,wy,ww,wh,0,0,0,0);


    SetWindowLong(winCx.window,GWL_WNDPROC,(LONG)WinProc);

    winCx.hdc=GetDC(winCx.window);

    winCx.hBmiDC = CreateCompatibleDC(winCx.hdc);

    winCx.hBmi=CreateDIBSection(winCx.hBmiDC, &winCx.bmi, DIB_RGB_COLORS, (void**)&winCx.ppvBits, 0, 0);

    SetEvent(winCx.evn);

    ShowWindow(winCx.window, SW_SHOW);
    UpdateWindow(winCx.window);

    winCx.hMenu = LoadMenu(winCx.hInstance, "DisplayContextMenu");

    bool standalone=false; //(winCx.win_flags & ris_win_flag_standalone) ? true : false;
    winCx.standalone=standalone;

    if (!standalone)
    {
		if (winCx.hMenu)
		{
			HMENU hmenuTrackPopup = GetSubMenu(winCx.hMenu, 0);
			RemoveMenu(hmenuTrackPopup, 0, MF_BYPOSITION);
		}
		//winCx.mcs=0;
    }
    else
    {
    	//winCx.mcs=&RisMiniMCS::instance();
    }

    //DragAcceptFiles(winCx.window, TRUE);

    MSG msg;

    while(GetMessage(&msg,0,0,0))
    {
    	DispatchMessage(&msg);
    }
    return 0;
}

static void win_init()
{

	winCx.mutex = CreateMutex(0,FALSE,0);
	winCx.evn = CreateEvent(0,FALSE,FALSE,0);
	winCx.thread = CreateThread(0,0,WinThread,0,0,0);
    WaitForSingleObject(winCx.evn,INFINITE);
}

class CImgHelper
{
public:
	uint32_t* palette;
	uint8_t buffer[1024];

	void init()
	{
		win_init();
	}
	uint8_t& visu(int,int,int,int)
	{
		return buffer[0];
	}

	void update()
	{
	}
};

static CImgHelper* helper;

static int videowin_mode;

//bool bsk_rtg_win32_get_com_drs();

static bool avi_save;

static AviFile* aviFile;

int vsave_frame_rate=-1;
const char* vsave_filename="video-capture.avi";

void gc_set_file_name(const char* fn)
{
	strncpy(video_src_file_name, fn, sizeof video_src_file_name);
	char* p=strrchr(video_src_file_name, '.');
	if (p)
		*p=0;
}

//int gc_remote_intruder(const uint8_t* src, unsigned int /*rows*/, unsigned int /*cols*/, unsigned int pitch, uint32_t* new_palette)
int gc_remote_intruder(const gc_vcr_frame_t* frame)
{
	static bool fix_frate_logged;

	static bool pwow;
	static bool already_init;

	static bool fix_frate=false;
	static unsigned int fix_frate_ref;


	int frame_rate=(25*10)/2;

	if (!already_init)
	{
		if (vsave_frame_rate>0)
			frame_rate=(vsave_frame_rate*10)/2;
		else if (vsave_frame_rate<0)
			fix_frate=true;

		fix_frate_ref=frame->fnum;
		already_init=true;
	}

	const uint8_t* src=(uint8_t*)&frame[1];
	//unsigned int rows=frame->dx;
	//unsigned int cols=frame->dy;
	unsigned int pitch=frame->stride;
	uint32_t* new_palette=(unsigned int*)frame->palette;

	static struct
	{
		double align;
		uint32_t image[640][640];
		uint32_t spare[1024];
	} tmp_image;

	static bool avi_ready;

	if (!avi_ready)
	{
		if (avi_save)
		{
			aviFile=AviFile::instance(); //new AviFile; //START_AVI("video-capture.avi");
			aviFile->open(vsave_filename /*"video-capture.avi"*/);
			aviFile->openVideoStream(frame_rate, 640, 512);
		}
	    avi_ready=1;
	}

	if (helper)
	{
		bool wow=false; //bsk_rtg_win32_get_com_drs();
		if (pwow!=wow)
		{
			//RisWowSimulate(wow ? true : false);

			if (winCx.window)
			{
				if (wow)
				{
					char title_buffer[512];
					snprintf(title_buffer, sizeof title_buffer, "%s - %s", winCx.win_title, "DRS=WoW");
					SetWindowText(winCx.window, title_buffer);

				}
				else
					SetWindowText(winCx.window, winCx.win_title);
			}
			pwow=wow;
		}

		if (new_palette)
			helper->palette=new_palette;
		if (!helper->palette)
			return 0;

		//PAINTSTRUCT ps;
        //HDC hdc = BeginPaint (winCx.window, &ps);

		uint32_t* dst=winCx.ppvBits;
		dst=&dst[DX*(DY-1)];
		const uint8_t* s=&src[0];

		for(int y=0; y<DY; ++y)
		{
			//const uint8_t* s=&src[y*pitch];


			for(int x=0; x<DX; ++x)
			{
				uint32_t c=helper->palette[s[x]];
				//helper->visu(x, y, 0, 0)=c & 0x0FF;
				//helper->visu(y, y, 0, 1)=(c>>8) & 0x0FF;
				//helper->visu(x, y, 0, 2)=(c>>16) & 0x0FF;
				//SetPixel(hdc, x, y, c);
				dst[x]=c;
				tmp_image.image[(DY-1)-y][x]=c;
			}
			dst-=DX;
			s+=pitch;
		}

		if (avi_save)
		{
			static int frame_decimator;

			if (true) //frame_decimator==0)
			{
				static BITMAPINFO tmp_info;
				tmp_info.bmiHeader.biSize=sizeof tmp_info.bmiHeader;

				{
			        SetBkColor(winCx.hBmiDC, 0);
			        //SetBkMode(winCx.hBmiDC, TRANSPARENT);
			        SetTextColor(winCx.hBmiDC, 0xFFFFFF);
			        int tx=DX-420;
			        int ty=20;
			        SIZE txtSize;
			        int str_len=strlen(video_src_file_name);
			        BOOL ok=GetTextExtentPoint32A(winCx.hBmiDC, video_src_file_name, str_len, &txtSize);
			        if (ok)
			        {
			        	tx=1+txtSize.cx;
			        	ty=1+txtSize.cy;
			        }
			        TextOutA(winCx.hBmiDC, DX-tx/*370*/, DY-ty /*512-20*/, video_src_file_name, strlen(video_src_file_name));
				}

				int ok=GetDIBits(winCx.hBmiDC, winCx.hBmi, 0, 0, 0, &tmp_info, DIB_RGB_COLORS);
				if (!ok)
					cmdio_perror("GetDIBits()");
				else
				{
					tmp_info.bmiHeader.biCompression=0;
					const void* img_raw=winCx.ppvBits; //tmp_image.image
					//ADD_FRAME_FROM_DIB_TO_AVI(tmp_image.image, &tmp_info.bmiHeader, winCx.hBmi, 0,  25);
					if (fix_frate)
					{
						static unsigned int p_delta=1;

						unsigned int current_frame=frame->fnum;
						unsigned int n_frames=1;
						if (current_frame>fix_frate_ref)
						{
							n_frames=current_frame-fix_frate_ref;
							if ((n_frames*20)/2>frame_rate)
								n_frames=1;
						}
						if (p_delta!=n_frames)
						{
							if (!fix_frate_logged)
							{
								cmdio_pwarning("Frame rate fix %u", n_frames);
								fix_frate_logged=true;
							}
							p_delta=n_frames;
						}

						for(unsigned nf=0; nf<n_frames; ++nf)
						{
							aviFile->addVideoFrame(img_raw); //tmp_image.image);
						}
						fix_frate_ref=current_frame;
					}
					else
						aviFile->addVideoFrame(img_raw); //tmp_image.image);

				}
			}
			frame_decimator^=1;
		}

		InvalidateRect(winCx.window, 0, FALSE);
		UpdateWindow(winCx.window);
        //EndPaint(winCx.window, &ps);

		helper->update();
		return videowin_mode;
	}
	return 0;
}

//void VideoWin(int mode, unsigned int win_flags, int display_num, int dx, int dy)
void RisWinStart(unsigned int wmode, unsigned int w_flags, int display_num, int dx, int dy, int wx, int wy, unsigned int bg)
{
	int mode=wmode;

	//if ((dx>=0) || (dy>=0))
	//		setCrtMode((dx>0) ? dx : 132, (dy>0) ? dy : 50);

	winCx.display_num=0; //(w_flags & ris_win_flag_set_monitor) ? display_num : 0;
	winCx.win_flags=w_flags;
	//if (w_flags & ris_win_flag_set_ox)
	//	winCx.ox=wx;
	//if (w_flags & ris_win_flag_set_oy)
	//	winCx.oy=wy;
	winCx.wbg=bg;


	HICON hIcon=LoadIconA(myInstance(), MAKEINTRESOURCEA(0));
	if (hIcon)
	{
		HWND hConsole=0; //GetConsoleWindow();
		if (hConsole)
		{
			//SetClassLongPtr(hConsole, GCLP_HICON, (LONG_PTR)hIcon);
			SendMessage(hConsole, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
			SendMessage(hConsole, WM_SETICON, ICON_SMALL, (LPARAM)hIcon);
		}
	}

	if (mode>-1000)
	{
		static CImgHelper v;
		videowin_mode=mode;
		v.init();
		helper=&v;
	}
}


void win_sleep(unsigned int ms)
{
	Sleep(ms);
}


void gc_save()
{
	avi_save=true;
}

void gc_close()
{
	if (avi_save)
	{
		aviFile->close(); //STOP_AVI();
	}
}

//int gc_save(const uint8_t* src, unsigned int /*rows*/, unsigned int /*cols*/, unsigned int pitch, uint32_t* new_palette)
//{
//}
