<commit_before>/*
 * Window.cpp
 *
 * Copyright (C) 2011 by VISUS (Universitaet Stuttgart)
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "glh/glh_extensions.h"
#include "Window.h"
#include "MegaMolCore.h"
#include <tchar.h>
#include <cstdio>
#include <gl/GL.h>
//#include "NVSwapGroup.h"
#pragma warning(disable: 4996)
#include "glh/glh_extensions.h"
#pragma warning(default: 4996)

using namespace megamol::wgl;

/*
 * Window::Window
 */
Window::Window(Instance& inst, int windows) : ApiHandle(), inst(inst),
        renderCallback(), resizeCallback(), renderer(&Window::renderThread),
		activeTiles(0), infoDc(NULL), infoRc(NULL) {

	if (windows <= 0)
	{
		// throw std::invalid_argument("windows must be positive");
		fprintf(stderr, "windows must be positive\n");
		return;
	}

	if (windows > maxTileCount)
	{
		// throw std::invalid_argument("windows is too large");
		fprintf(stderr, "windows is too large\n");
		return;
	}

	ZeroMemory(this->tiles, sizeof(Tile) * maxTileCount);

	for (int i = 0; i < windows; i++)
	{
		if (!tiles[i].Create(this, i))
		{
			Close();
			fprintf(stderr, "Window creation failed\n");
			return;
		}
	}

	// ::wglMakeCurrent(tiles[0].dc, tiles[0].rc);

	// Megamol seems to assume that once a window has been created, an
	// OpenGL context has been set for the calling thread. We don't want to
	// set any of our tile contexts because we'll need them for rendering in
	// the render thread (and they can't be current in two threads at the same
	// time). Therefore, we create a dummy context for the desktop and set
	// that.
	if (CreateRenderContext(NULL, infoDc, infoRc))
		::wglMakeCurrent(infoDc, infoRc);

	activeTiles = windows;
    this->renderer.Start(this);
}

/*
 * Window::~Window
 */
Window::~Window(void) {
    this->Close();

	if (infoRc != NULL)
		::wglDeleteContext(infoRc);
	if (infoDc != NULL)
		::ReleaseDC(NULL, infoDc);
}

/*
 * Window::Close
 */
void Window::Close(void) {

	for (int i = 0; i < maxTileCount; i++)
		tiles[i].End();

	if (this->renderer.IsRunning())
		this->renderer.Join();

	for (int i = 0; i < maxTileCount; i++)
		tiles[i].Destroy();
}

bool Window::IsValid()
{
	for (int i = 0; i < activeTiles; i++) {
		if (!IsWindow(tiles[i].handle))
			return false;
	}
	return true;
}

/*
 * Window::SetHint
 */
void Window::SetHint(unsigned int hint, bool f) {
    switch (hint) {

        case MMV_WINHINT_NODECORATIONS: {
            /* window style for decorations */
            LONG_PTR normWS = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW;
            /* window style without decorations */
            LONG_PTR thinWS = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
			for (int i = 0; i < activeTiles; i++)
				::SetWindowLongPtr(this->tiles[i].handle, GWL_STYLE, f ? thinWS : normWS);
        } break;

        case MMV_WINHINT_HIDECURSOR: {
            HCURSOR cur = f ? NULL : ::LoadCursor(NULL, IDC_ARROW);
            ::SetCursor(cur);
			for (int i = 0; i < activeTiles; i++)
				::SetClassLongPtr(this->tiles[i].handle, GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(cur));
        } break;

        case MMV_WINHINT_STAYONTOP: {
            /* window style for decorations */
			for (int i = 0; i < activeTiles; i++)
				::SetWindowPos(this->tiles[i].handle,
					f ? HWND_TOPMOST : HWND_NOTOPMOST,
					0, 0, 0, 0,
					SWP_NOMOVE | SWP_NOSIZE);
        } break;

        //case MMV_WINHINT_VSYNC: {
        //} break;

        default:
            fprintf(stderr, "Hint %u not supported\n", hint);
            break;
    }

}

void Window::SetTitle(const char *title)
{
	for (int i = 0; i < activeTiles; i++)
		SetWindowTextA(tiles[i].handle, title);
}

void Window::SetTitle(const wchar_t *title)
{
	for (int i = 0; i < activeTiles; i++)
		SetWindowTextW(tiles[i].handle, title);
}

/*void Window::SetPosition(int x, int y, int width, int height)
{
	if (width <= 0)
		width = 0;
	if (height <= 0)
		height = 0;

	int x1 = x + width / 2;
	int y1 = y + height / 2;

	for (int i = 0; i < activeTiles; i++)
	{
		int tx;
		int ty;
		int tw;
		int th;
		if (i % 2 == 0) {
			tx = x;
			tw = x1 - x;
		}
		else
		{
			tx = x1;
			tw = x + width - x1;
		}
		if (i / 2 == 0)
		{
			ty = y;
			th = y1 - y;
		}
		else
		{
			ty = y1;
			th = y + height - y1;
		}
	}
}*/

Window::Tile::Tile() : window(nullptr), index(-1), handle(nullptr), dc(nullptr), rc(nullptr) {

}

bool Window::Tile::Create(Window *window, int index)
{
	const DWORD style = WS_OVERLAPPEDWINDOW;
	const DWORD styleEx = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;

	::wglMakeCurrent(NULL, NULL); // paranoia

	this->window = window;
	this->index = index;

	// Decide where this window is to be placed.
	int x = CW_USEDEFAULT;
	int y = CW_USEDEFAULT;
	int width = CW_USEDEFAULT;
	int height = CW_USEDEFAULT;

	bool useExtension = false;
	if (!useExtension)
	{
		int vsx = GetSystemMetrics(SM_XVIRTUALSCREEN);
		int vsy = GetSystemMetrics(SM_YVIRTUALSCREEN);
		int vsw = GetSystemMetrics(SM_CXVIRTUALSCREEN);
		int vsh = GetSystemMetrics(SM_CYVIRTUALSCREEN);

		if (index % 2 == 0) {
			x = vsx;
			width = vsw / 2;
		}
		else
		{
			x = vsw / 2;
			width = vsw - x;
		}
		if (index / 2 == 0)
		{
			y = vsy;
			height = vsh / 2;
		}
		else
		{
			y = vsh / 2;
			height = vsh - y;
		}
	}

	// Create the tile window.
	handle = ::CreateWindowEx(styleEx, Instance::WindowClassName,
		_T("MegaMol"), style | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
		x, y, width, height,
		NULL, NULL, Instance::HInstance(), this);

	if (handle == NULL)
		return false;

	if (!CreateRenderContext(handle, dc, rc)) {
		DestroyWindow(handle);
		handle = NULL;
		return false;
	}

	// Notify the window of its initial position.
	RECT clientRect;
	::GetClientRect(handle, &clientRect);
	Resized(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);

	return true;
}

void Window::Tile::Destroy()
{
	if (dc != NULL) {
		if (!::ReleaseDC(handle, dc)) {
			fprintf(stderr, "Failed to release device context\n");
		}
		dc = NULL;
	}

	if (handle != NULL) {
		if (!::DestroyWindow(handle)) {
			fprintf(stderr, "Failed to destroy window\n");
		}
		handle = NULL;
	}
}

void Window::Tile::End()
{
	if (rc != NULL) {
		if (!::wglMakeCurrent(NULL, NULL)) {
			fprintf(stderr, "Unable to deactivate rendering context\n");
		}
		if (!::wglDeleteContext(rc)) {
			fprintf(stderr, "Unable to delete rendering context\n");
		}
		rc = NULL;
	}
}

/*
* Window::Resized
*/
void Window::Tile::Resized(unsigned int w, unsigned int h) {
	this->w = w;
	this->h = h;
	unsigned int p[2] = { w, h };
	window->resizeCallback.Call(*window, p);
}

bool Window::CreateRenderContext(HWND window, HDC &dc, HGLRC &rc) {

	const unsigned int colBits = 32;
	const unsigned int depthBits = 32;

	dc = ::GetDC(window);
	if (dc == NULL)
		return false;

	// Initialize the pixel format.
	const static PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR), 1,
		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA, colBits, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		depthBits, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0
	};

	int pixelFormat = ::ChoosePixelFormat(dc, &pfd);
	if (pixelFormat == 0 || !::SetPixelFormat(dc, pixelFormat, &pfd))
	{
		ReleaseDC(window, dc);
		dc = NULL;
		return false;
	}

	// Create an OpenGL render context for the window device context.
	rc = ::wglCreateContext(dc);
	if (rc == NULL)
	{
		ReleaseDC(window, dc);
		dc = NULL;
		return false;
	}

	return true;
}

/*
 * Window::WndProc
 */
LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    Tile *that = reinterpret_cast<Tile*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));

    switch (uMsg) {

        case WM_CREATE: {
            CREATESTRUCT *cs = reinterpret_cast<CREATESTRUCT *>(lParam);
            that = static_cast<Tile*>(cs->lpCreateParams);
            ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
        } break;

        //case WM_ACTIVATE:
        //    //if (!HIWORD(wParam)) {
        //    //    active=TRUE;
        //    //} else {
        //    //    active=FALSE;
        //    //}
        //    return 0;

        case WM_SYSCOMMAND:
            switch (wParam) {
            case SC_SCREENSAVE:
            case SC_MONITORPOWER:
                return 0;
            }
            break;

        case WM_CLOSE:
            ::PostQuitMessage(0);
            that->window->Close();
            return 0;

        case WM_KEYDOWN:
            if (wParam == VK_ESCAPE) {
                ::PostQuitMessage(0);
                that->window->Close();
            }
            //keys[wParam] = TRUE;
            return 0;

        //case WM_KEYUP:
        //    //keys[wParam] = FALSE;
        //    return 0;

        case WM_PAINT:
            //if (that->paintOnPaint) {
            //    that->Paint();
            //}
            ::ValidateRect(that->handle, NULL);
            return 0;

        case WM_SIZE:
            that->Resized(LOWORD(lParam), HIWORD(lParam));
            return 0;

    }

    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

/*
 * Window::renderThread
 */
DWORD Window::renderThread(void *userData) {
    Window *that = static_cast<Window *>(userData);
    mmcRenderViewContext context;

	ZeroMemory(&context, sizeof(context));
	context.Size = sizeof(context);
	context.SynchronisedTime = -1.0;

    // not too good, but ok for now
    vislib::sys::Thread::Sleep(2500);

	while (that->tiles[0].rc != nullptr)
	{
		context.SynchronisedTime = -1.0;

		// Render all windows in turn.
		for (int i = 0; i < that->activeTiles; i++)
		{
			if (that->tiles[i].rc != nullptr)
			{
				// The context must not be bound until ALL windows have been created
				BOOL result1 = ::wglMakeCurrent(that->tiles[i].dc, that->tiles[i].rc);
				GLenum ge = ::glGetError();
				const GLubyte *result = glGetString(GL_EXTENSIONS);
				ge = ::glGetError();
				// GL_INVALID_VALUE

				// int v = glh_extension_supported("WGL_NV_gpu_affinity");

				::glViewport(0, 0, that->tiles[i].w, that->tiles[i].h);

				if (i == 0)
					that->renderCallback.Call(*that, &context);

				::SwapBuffers(that->tiles[i].dc);
			}
		}

		vislib::sys::Thread::Reschedule();
	}

    ::wglMakeCurrent(NULL, NULL);

    return 0;
}
<commit_msg>Fixed synchronised time issue in multiwgl viewer (should we drop this viewer?)<commit_after>/*
 * Window.cpp
 *
 * Copyright (C) 2011 by VISUS (Universitaet Stuttgart)
 * Alle Rechte vorbehalten.
 */

#include "stdafx.h"
#include "glh/glh_extensions.h"
#include "Window.h"
#include "MegaMolCore.h"
#include <tchar.h>
#include <cstdio>
#include <gl/GL.h>
//#include "NVSwapGroup.h"
#pragma warning(disable: 4996)
#include "glh/glh_extensions.h"
#pragma warning(default: 4996)

using namespace megamol::wgl;

/*
 * Window::Window
 */
Window::Window(Instance& inst, int windows) : ApiHandle(), inst(inst),
        renderCallback(), resizeCallback(), renderer(&Window::renderThread),
		activeTiles(0), infoDc(NULL), infoRc(NULL) {

	if (windows <= 0)
	{
		// throw std::invalid_argument("windows must be positive");
		fprintf(stderr, "windows must be positive\n");
		return;
	}

	if (windows > maxTileCount)
	{
		// throw std::invalid_argument("windows is too large");
		fprintf(stderr, "windows is too large\n");
		return;
	}

	ZeroMemory(this->tiles, sizeof(Tile) * maxTileCount);

	for (int i = 0; i < windows; i++)
	{
		if (!tiles[i].Create(this, i))
		{
			Close();
			fprintf(stderr, "Window creation failed\n");
			return;
		}
	}

	// ::wglMakeCurrent(tiles[0].dc, tiles[0].rc);

	// Megamol seems to assume that once a window has been created, an
	// OpenGL context has been set for the calling thread. We don't want to
	// set any of our tile contexts because we'll need them for rendering in
	// the render thread (and they can't be current in two threads at the same
	// time). Therefore, we create a dummy context for the desktop and set
	// that.
	if (CreateRenderContext(NULL, infoDc, infoRc))
		::wglMakeCurrent(infoDc, infoRc);

	activeTiles = windows;
    this->renderer.Start(this);
}

/*
 * Window::~Window
 */
Window::~Window(void) {
    this->Close();

	if (infoRc != NULL)
		::wglDeleteContext(infoRc);
	if (infoDc != NULL)
		::ReleaseDC(NULL, infoDc);
}

/*
 * Window::Close
 */
void Window::Close(void) {

	for (int i = 0; i < maxTileCount; i++)
		tiles[i].End();

	if (this->renderer.IsRunning())
		this->renderer.Join();

	for (int i = 0; i < maxTileCount; i++)
		tiles[i].Destroy();
}

bool Window::IsValid()
{
	for (int i = 0; i < activeTiles; i++) {
		if (!IsWindow(tiles[i].handle))
			return false;
	}
	return true;
}

/*
 * Window::SetHint
 */
void Window::SetHint(unsigned int hint, bool f) {
    switch (hint) {

        case MMV_WINHINT_NODECORATIONS: {
            /* window style for decorations */
            LONG_PTR normWS = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE | WS_OVERLAPPEDWINDOW;
            /* window style without decorations */
            LONG_PTR thinWS = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE;
			for (int i = 0; i < activeTiles; i++)
				::SetWindowLongPtr(this->tiles[i].handle, GWL_STYLE, f ? thinWS : normWS);
        } break;

        case MMV_WINHINT_HIDECURSOR: {
            HCURSOR cur = f ? NULL : ::LoadCursor(NULL, IDC_ARROW);
            ::SetCursor(cur);
			for (int i = 0; i < activeTiles; i++)
				::SetClassLongPtr(this->tiles[i].handle, GCLP_HCURSOR, reinterpret_cast<LONG_PTR>(cur));
        } break;

        case MMV_WINHINT_STAYONTOP: {
            /* window style for decorations */
			for (int i = 0; i < activeTiles; i++)
				::SetWindowPos(this->tiles[i].handle,
					f ? HWND_TOPMOST : HWND_NOTOPMOST,
					0, 0, 0, 0,
					SWP_NOMOVE | SWP_NOSIZE);
        } break;

        //case MMV_WINHINT_VSYNC: {
        //} break;

        default:
            fprintf(stderr, "Hint %u not supported\n", hint);
            break;
    }

}

void Window::SetTitle(const char *title)
{
	for (int i = 0; i < activeTiles; i++)
		SetWindowTextA(tiles[i].handle, title);
}

void Window::SetTitle(const wchar_t *title)
{
	for (int i = 0; i < activeTiles; i++)
		SetWindowTextW(tiles[i].handle, title);
}

/*void Window::SetPosition(int x, int y, int width, int height)
{
	if (width <= 0)
		width = 0;
	if (height <= 0)
		height = 0;

	int x1 = x + width / 2;
	int y1 = y + height / 2;

	for (int i = 0; i < activeTiles; i++)
	{
		int tx;
		int ty;
		int tw;
		int th;
		if (i % 2 == 0) {
			tx = x;
			tw = x1 - x;
		}
		else
		{
			tx = x1;
			tw = x + width - x1;
		}
		if (i / 2 == 0)
		{
			ty = y;
			th = y1 - y;
		}
		else
		{
			ty = y1;
			th = y + height - y1;
		}
	}
}*/

Window::Tile::Tile() : window(nullptr), index(-1), handle(nullptr), dc(nullptr), rc(nullptr) {

}

bool Window::Tile::Create(Window *window, int index)
{
	const DWORD style = WS_OVERLAPPEDWINDOW;
	const DWORD styleEx = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;

	::wglMakeCurrent(NULL, NULL); // paranoia

	this->window = window;
	this->index = index;

	// Decide where this window is to be placed.
	int x = CW_USEDEFAULT;
	int y = CW_USEDEFAULT;
	int width = CW_USEDEFAULT;
	int height = CW_USEDEFAULT;

	bool useExtension = false;
	if (!useExtension)
	{
		int vsx = GetSystemMetrics(SM_XVIRTUALSCREEN);
		int vsy = GetSystemMetrics(SM_YVIRTUALSCREEN);
		int vsw = GetSystemMetrics(SM_CXVIRTUALSCREEN);
		int vsh = GetSystemMetrics(SM_CYVIRTUALSCREEN);

		if (index % 2 == 0) {
			x = vsx;
			width = vsw / 2;
		}
		else
		{
			x = vsw / 2;
			width = vsw - x;
		}
		if (index / 2 == 0)
		{
			y = vsy;
			height = vsh / 2;
		}
		else
		{
			y = vsh / 2;
			height = vsh - y;
		}
	}

	// Create the tile window.
	handle = ::CreateWindowEx(styleEx, Instance::WindowClassName,
		_T("MegaMol"), style | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
		x, y, width, height,
		NULL, NULL, Instance::HInstance(), this);

	if (handle == NULL)
		return false;

	if (!CreateRenderContext(handle, dc, rc)) {
		DestroyWindow(handle);
		handle = NULL;
		return false;
	}

	// Notify the window of its initial position.
	RECT clientRect;
	::GetClientRect(handle, &clientRect);
	Resized(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);

	return true;
}

void Window::Tile::Destroy()
{
	if (dc != NULL) {
		if (!::ReleaseDC(handle, dc)) {
			fprintf(stderr, "Failed to release device context\n");
		}
		dc = NULL;
	}

	if (handle != NULL) {
		if (!::DestroyWindow(handle)) {
			fprintf(stderr, "Failed to destroy window\n");
		}
		handle = NULL;
	}
}

void Window::Tile::End()
{
	if (rc != NULL) {
		if (!::wglMakeCurrent(NULL, NULL)) {
			fprintf(stderr, "Unable to deactivate rendering context\n");
		}
		if (!::wglDeleteContext(rc)) {
			fprintf(stderr, "Unable to delete rendering context\n");
		}
		rc = NULL;
	}
}

/*
* Window::Resized
*/
void Window::Tile::Resized(unsigned int w, unsigned int h) {
	this->w = w;
	this->h = h;
	unsigned int p[2] = { w, h };
	window->resizeCallback.Call(*window, p);
}

bool Window::CreateRenderContext(HWND window, HDC &dc, HGLRC &rc) {

	const unsigned int colBits = 32;
	const unsigned int depthBits = 32;

	dc = ::GetDC(window);
	if (dc == NULL)
		return false;

	// Initialize the pixel format.
	const static PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR), 1,
		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA, colBits, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		depthBits, 0, 0, PFD_MAIN_PLANE, 0, 0, 0, 0
	};

	int pixelFormat = ::ChoosePixelFormat(dc, &pfd);
	if (pixelFormat == 0 || !::SetPixelFormat(dc, pixelFormat, &pfd))
	{
		ReleaseDC(window, dc);
		dc = NULL;
		return false;
	}

	// Create an OpenGL render context for the window device context.
	rc = ::wglCreateContext(dc);
	if (rc == NULL)
	{
		ReleaseDC(window, dc);
		dc = NULL;
		return false;
	}

	return true;
}

/*
 * Window::WndProc
 */
LRESULT CALLBACK Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    Tile *that = reinterpret_cast<Tile*>(::GetWindowLongPtr(hWnd, GWLP_USERDATA));

    switch (uMsg) {

        case WM_CREATE: {
            CREATESTRUCT *cs = reinterpret_cast<CREATESTRUCT *>(lParam);
            that = static_cast<Tile*>(cs->lpCreateParams);
            ::SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
        } break;

        //case WM_ACTIVATE:
        //    //if (!HIWORD(wParam)) {
        //    //    active=TRUE;
        //    //} else {
        //    //    active=FALSE;
        //    //}
        //    return 0;

        case WM_SYSCOMMAND:
            switch (wParam) {
            case SC_SCREENSAVE:
            case SC_MONITORPOWER:
                return 0;
            }
            break;

        case WM_CLOSE:
            ::PostQuitMessage(0);
            that->window->Close();
            return 0;

        case WM_KEYDOWN:
            if (wParam == VK_ESCAPE) {
                ::PostQuitMessage(0);
                that->window->Close();
            }
            //keys[wParam] = TRUE;
            return 0;

        //case WM_KEYUP:
        //    //keys[wParam] = FALSE;
        //    return 0;

        case WM_PAINT:
            //if (that->paintOnPaint) {
            //    that->Paint();
            //}
            ::ValidateRect(that->handle, NULL);
            return 0;

        case WM_SIZE:
            that->Resized(LOWORD(lParam), HIWORD(lParam));
            return 0;

    }

    return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}

/*
 * Window::renderThread
 */
DWORD Window::renderThread(void *userData) {
    Window *that = static_cast<Window *>(userData);
    mmcRenderViewContext context;

	ZeroMemory(&context, sizeof(context));
	context.Size = sizeof(context);
    context.Time = -1.0;

    // not too good, but ok for now
    vislib::sys::Thread::Sleep(2500);

	while (that->tiles[0].rc != nullptr)
	{
		context.Time = -1.0;

		// Render all windows in turn.
		for (int i = 0; i < that->activeTiles; i++)
		{
			if (that->tiles[i].rc != nullptr)
			{
				// The context must not be bound until ALL windows have been created
				BOOL result1 = ::wglMakeCurrent(that->tiles[i].dc, that->tiles[i].rc);
				GLenum ge = ::glGetError();
				const GLubyte *result = glGetString(GL_EXTENSIONS);
				ge = ::glGetError();
				// GL_INVALID_VALUE

				// int v = glh_extension_supported("WGL_NV_gpu_affinity");

				::glViewport(0, 0, that->tiles[i].w, that->tiles[i].h);

				if (i == 0)
					that->renderCallback.Call(*that, &context);

				::SwapBuffers(that->tiles[i].dc);
			}
		}

		vislib::sys::Thread::Reschedule();
	}

    ::wglMakeCurrent(NULL, NULL);

    return 0;
}
<|endoftext|>


<commit_before>/*
 *   CrissCross
 *   A multi-purpose cross-platform library.
 *
 *   A product of Uplink Laboratories.
 *
 *   (c) 2006-2015 Steven Noonan.
 *   Licensed under the New BSD License.
 *
 */

#include <crisscross/universal_include.h>
#include <crisscross/debug.h>
#include <crisscross/filewriter.h>
#include <crisscross/nasty_cast.h>

#include <cstdio>
#include <cstring>

#if defined (TARGET_OS_LINUX) || defined (TARGET_OS_MACOSX) || defined (TARGET_OS_FREEBSD) || defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
#if !defined(TARGET_COMPILER_CLANG)
#include <cxxabi.h>
#else
namespace __cxxabiv1
{
	extern "C"
	{
		char*
		__cxa_demangle(const char* __mangled_name, char* __output_buffer,
					   size_t* __length, int* __status);
	}
}
namespace abi = __cxxabiv1;
#endif
#if defined(TARGET_OS_LINUX) && !defined(TARGET_COMPILER_CYGWIN)
#include <execinfo.h>
#endif
#endif

using namespace CrissCross::IO;

#ifdef TARGET_OS_MACOSX
#include <dlfcn.h>
typedef int (*backtrace_t)(void * *, int);
typedef char **(*backtrace_symbols_t)(void * const *, int);
#endif

#ifndef ENABLE_SYMBOL_ENGINE
#ifdef TARGET_COMPILER_VC
#pragma warning (disable: 4311)
#endif
#else

#include <windows.h>
#include <dbghelp.h>

#pragma warning (disable: 4312)
#pragma comment( lib, "dbghelp" )

class SymbolEngine
{
	public:
		static SymbolEngine & instance();
#if TARGET_CPU_BITS == 32
		std::string addressToString(DWORD address);
#else
		std::string addressToString(DWORD64 address);
#endif
		void StackTrace(PCONTEXT _pContext, CoreIOWriter * _outputBuffer);
	private:
		SymbolEngine(SymbolEngine const &);
		SymbolEngine & operator=(SymbolEngine const &);
		SymbolEngine();
		HANDLE hProcess;
	public:
		~SymbolEngine();
	private:
};

SymbolEngine & SymbolEngine::instance()
{
	static SymbolEngine
	theEngine;

	return theEngine;
}

SymbolEngine::SymbolEngine()
{
	hProcess = GetCurrentProcess();

	DWORD dwOpts = SymGetOptions();

	dwOpts |= SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS;
	SymSetOptions(dwOpts);

	::SymInitialize(hProcess, 0, true);
}

SymbolEngine::~SymbolEngine()
{
	::SymCleanup(hProcess);
}

#if TARGET_CPU_BITS == 32
std::string SymbolEngine::addressToString(DWORD address)
#elif TARGET_CPU_BITS == 64
std::string SymbolEngine::addressToString(DWORD64 address)
#endif
{
	char buffer[4096];
#if TARGET_CPU_BITS == 32
	const char *format = "0x%08x";
#elif TARGET_CPU_BITS == 64
	const char *format = "0x%016x";
#endif

	/* First the raw address */
	sprintf(buffer, format, address);

	/* Then any name for the symbol */
	struct tagSymInfo
	{
		IMAGEHLP_SYMBOL symInfo;
		char nameBuffer[4 * 256];
	} SymInfo = { { sizeof(IMAGEHLP_SYMBOL) } };

	IMAGEHLP_SYMBOL *
	pSym = &SymInfo.symInfo;

	pSym->MaxNameLength =
	        sizeof(SymInfo) - offsetof(tagSymInfo, symInfo.Name);

#if TARGET_CPU_BITS == 32
	DWORD
#elif TARGET_CPU_BITS == 64
	DWORD64
#endif
	dwDisplacement;

	if (SymGetSymFromAddr(GetCurrentProcess(), address, &dwDisplacement, pSym)) {
		strcat(buffer, " ");
		strcat(buffer, pSym->Name);
		/*if ( dwDisplacement != 0 )
		 * oss << "+0x" << std::hex << dwDisplacement << std::dec; */
	}

	/* Finally any file/line number */
	IMAGEHLP_LINE
	lineInfo = { sizeof(IMAGEHLP_LINE) };
	if (SymGetLineFromAddr(GetCurrentProcess(), (DWORD)address, (PDWORD)&dwDisplacement, &lineInfo)) {
		const char *pDelim = strrchr(lineInfo.FileName, '\\');
		char temp[1024];
		sprintf(temp, " at %s(%u)", (pDelim ? pDelim + 1 : lineInfo.FileName), lineInfo.LineNumber);
		strcat(buffer, temp);
	}

	return std::string(buffer);
}

void SymbolEngine::StackTrace(PCONTEXT _pContext, CoreIOWriter * _outputBuffer)
{
#if TARGET_CPU_BITS == 32
	_outputBuffer->WriteLine("  Frame       Address   Code");
#else
	_outputBuffer->WriteLine("  Frame              Address            Code");
#endif

	STACKFRAME stackFrame = { 0 };

	stackFrame.AddrPC.Offset =
#if TARGET_CPU_BITS == 32
		_pContext->Eip;
#else
		_pContext->Rip;
#endif
	stackFrame.AddrPC.Mode = AddrModeFlat;

	stackFrame.AddrFrame.Offset =
#if TARGET_CPU_BITS == 32
		_pContext->Ebp;
#else
		_pContext->Rbp;
#endif
	stackFrame.AddrFrame.Mode = AddrModeFlat;

	stackFrame.AddrStack.Offset =
#if TARGET_CPU_BITS == 32
		_pContext->Esp;
#else
		_pContext->Rsp;
#endif
	stackFrame.AddrStack.Mode = AddrModeFlat;

#ifdef TARGET_CPU_X86
	DWORD machine = IMAGE_FILE_MACHINE_I386;
	const char *format = " 0x%08x %s";
#elif defined(TARGET_CPU_X64)
	DWORD machine = IMAGE_FILE_MACHINE_AMD64;
	const char *format = " 0x%016x %s";
#endif

	while (::StackWalk(machine, hProcess, GetCurrentThread(),        /* this value doesn't matter much if previous one is a real handle */
	                   &stackFrame,
	                   _pContext,
	                   NULL, ::SymFunctionTableAccess, ::SymGetModuleBase,
	                   NULL)) {
		_outputBuffer->WriteLine(format, stackFrame.AddrFrame.Offset,
		                         addressToString(stackFrame.AddrPC.
		                                         Offset).c_str());
	}
}
#endif
void CrissCross::Debug::PrintStackTrace(CrissCross::IO::CoreIOWriter * _outputBuffer)
{
#if !defined (TARGET_OS_NETBSD) && !defined (TARGET_OS_FREEBSD) && !defined (TARGET_OS_OPENBSD) \
 && !defined(TARGET_COMPILER_MINGW) && !defined(TARGET_COMPILER_CYGWIN) && !defined(TARGET_OS_HAIKU)
#ifdef ENABLE_SYMBOL_ENGINE

	CONTEXT context = { CONTEXT_ALL };
	BOOL ret = ::GetThreadContext(GetCurrentThread(), &context);
	CoreAssert(ret != FALSE);
#ifdef TARGET_CPU_X64
	RtlCaptureContext(&context);
#elif defined(TARGET_CPU_X86)
	_asm call $ + 5;
	_asm pop eax;
	_asm mov context.Eip, eax;
	_asm mov eax, esp;
	_asm mov context.Esp, eax;
	_asm mov context.Ebp, ebp;
#endif
	SymbolEngine::instance().StackTrace(&context, _outputBuffer);

#elif defined (ENABLE_BACKTRACE)
#if defined (TARGET_OS_MACOSX)
	backtrace_t backtrace;
	backtrace_symbols_t backtrace_symbols;
	backtrace = nasty_cast<backtrace_t, void*>(dlsym(RTLD_DEFAULT, "backtrace"));
	backtrace_symbols = nasty_cast<backtrace_symbols_t, void*>(dlsym(RTLD_DEFAULT, "backtrace_symbols"));
#endif

	void *array[256];
	int size;
	char * *strings;
	int i;

	memset(array, 0, sizeof(void *) * 256);

	/* use -rdynamic flag when compiling */
	size = backtrace(array, 256);
	strings = backtrace_symbols(array, size);

	_outputBuffer->WriteLine("Obtained %d stack frames.", size);

	std::string bt = "";

	for (i = 0; i < size; i++) {
#if defined (TARGET_OS_LINUX)
		int status;
		/* extract the identifier from strings[i].  It's inside of parens. */
		char *identifier = ::strchr(strings[i], '(');
		char *identifier_end = ::strchr(strings[i], '+');
		char *address = ::strchr(strings[i], '[');
		if (identifier != 0 && identifier_end != 0 && identifier < identifier_end) {
			bt += address;
			bt += " ";
			*identifier_end = '\0';
			char * realname = abi::__cxa_demangle(identifier + 1, 0, 0, &status);
			if (realname != NULL) {
				bt += realname;
			} else {
				bt += (identifier + 1);
			}
			char *off_end = ::strchr(identifier_end + 1, ')');
			if (off_end) {
				*off_end = 0;
				bt += " + ";
				bt += (identifier_end + 1);
			}
			free(realname);
		}
#elif defined (TARGET_OS_MACOSX)
		char *addr = ::strstr(strings[i], "0x");
		char *mangled = ::strchr(addr, ' ') + 1;
		char *offset = ::strchr(addr, '+');
		char *postmangle = ::strchr(mangled, ' ');
		if (mangled) *(mangled - 1) = 0;
		bt += addr;
		int status;
		bt += ": ";
		if (addr && mangled) {
			if (postmangle)
				*postmangle = '\0';
			char *realname = abi::__cxa_demangle(mangled, 0, 0, &status);
			if (realname) {
				bt += realname;
			} else {
				bt += mangled;
			}
			bt += " ";
			bt += offset;
			free(realname);
		}
#endif
		bt += "\n";
	}

	_outputBuffer->WriteLine("%s\n", bt.c_str());

	free(strings);

#else /* defined(ENABLE_SYMBOL_ENGINE) || defined(ENABLE_BACKTRACE) */
	_outputBuffer->WriteLine("FAIL: backtrace() function not available.");
#endif

#else /* !defined (TARGET_OS_NETBSD) && !defined (TARGET_OS_FREEBSD) && !defined (TARGET_OS_OPENBSD) */
	_outputBuffer->WriteLine("Stack traces are not implemented for this platform.");
#endif
}
#ifndef USE_FAST_ASSERT
void Assert(bool _condition, const char *_testcase, const char *_file, int _line)
{
	if (!_condition) {
		char buffer[10240];
		sprintf(buffer, "Assertion failed : '%s'\nFile: %s\nLine: %d\n\n",
		        _testcase, _file, _line);
		fprintf(stderr, "%s", buffer);
		fprintf(stderr, "=== STACK TRACE ===\n");
		CoreIOWriter *stderror = new CoreIOWriter(stderr, false, CC_LN_LF);
		PrintStackTrace(stderror);
		delete stderror;
		#ifndef _DEBUG
		abort();
		#else
		_ASSERT(_condition);
		#endif
	}
}
#endif
<commit_msg>debug: print address even if the symbol can't be resolved<commit_after>/*
 *   CrissCross
 *   A multi-purpose cross-platform library.
 *
 *   A product of Uplink Laboratories.
 *
 *   (c) 2006-2015 Steven Noonan.
 *   Licensed under the New BSD License.
 *
 */

#include <crisscross/universal_include.h>
#include <crisscross/debug.h>
#include <crisscross/filewriter.h>
#include <crisscross/nasty_cast.h>

#include <cstdio>
#include <cstring>

#if defined (TARGET_OS_LINUX) || defined (TARGET_OS_MACOSX) || defined (TARGET_OS_FREEBSD) || defined (TARGET_OS_NETBSD) || defined (TARGET_OS_OPENBSD)
#if !defined(TARGET_COMPILER_CLANG)
#include <cxxabi.h>
#else
namespace __cxxabiv1
{
	extern "C"
	{
		char*
		__cxa_demangle(const char* __mangled_name, char* __output_buffer,
					   size_t* __length, int* __status);
	}
}
namespace abi = __cxxabiv1;
#endif
#if defined(TARGET_OS_LINUX) && !defined(TARGET_COMPILER_CYGWIN)
#include <execinfo.h>
#endif
#endif

using namespace CrissCross::IO;

#ifdef TARGET_OS_MACOSX
#include <dlfcn.h>
typedef int (*backtrace_t)(void * *, int);
typedef char **(*backtrace_symbols_t)(void * const *, int);
#endif

#ifndef ENABLE_SYMBOL_ENGINE
#ifdef TARGET_COMPILER_VC
#pragma warning (disable: 4311)
#endif
#else

#include <windows.h>
#include <dbghelp.h>

#pragma warning (disable: 4312)
#pragma comment( lib, "dbghelp" )

class SymbolEngine
{
	public:
		static SymbolEngine & instance();
#if TARGET_CPU_BITS == 32
		std::string addressToString(DWORD address);
#else
		std::string addressToString(DWORD64 address);
#endif
		void StackTrace(PCONTEXT _pContext, CoreIOWriter * _outputBuffer);
	private:
		SymbolEngine(SymbolEngine const &);
		SymbolEngine & operator=(SymbolEngine const &);
		SymbolEngine();
		HANDLE hProcess;
	public:
		~SymbolEngine();
	private:
};

SymbolEngine & SymbolEngine::instance()
{
	static SymbolEngine
	theEngine;

	return theEngine;
}

SymbolEngine::SymbolEngine()
{
	hProcess = GetCurrentProcess();

	DWORD dwOpts = SymGetOptions();

	dwOpts |= SYMOPT_LOAD_LINES | SYMOPT_DEFERRED_LOADS;
	SymSetOptions(dwOpts);

	::SymInitialize(hProcess, 0, true);
}

SymbolEngine::~SymbolEngine()
{
	::SymCleanup(hProcess);
}

#if TARGET_CPU_BITS == 32
std::string SymbolEngine::addressToString(DWORD address)
#elif TARGET_CPU_BITS == 64
std::string SymbolEngine::addressToString(DWORD64 address)
#endif
{
	char buffer[4096];
#if TARGET_CPU_BITS == 32
	const char *format = "0x%08x";
#elif TARGET_CPU_BITS == 64
	const char *format = "0x%016x";
#endif

	/* First the raw address */
	sprintf(buffer, format, address);

	/* Then any name for the symbol */
	struct tagSymInfo
	{
		IMAGEHLP_SYMBOL symInfo;
		char nameBuffer[4 * 256];
	} SymInfo = { { sizeof(IMAGEHLP_SYMBOL) } };

	IMAGEHLP_SYMBOL *
	pSym = &SymInfo.symInfo;

	pSym->MaxNameLength =
	        sizeof(SymInfo) - offsetof(tagSymInfo, symInfo.Name);

#if TARGET_CPU_BITS == 32
	DWORD
#elif TARGET_CPU_BITS == 64
	DWORD64
#endif
	dwDisplacement;

	if (SymGetSymFromAddr(GetCurrentProcess(), address, &dwDisplacement, pSym)) {
		strcat(buffer, " ");
		strcat(buffer, pSym->Name);
		/*if ( dwDisplacement != 0 )
		 * oss << "+0x" << std::hex << dwDisplacement << std::dec; */
	}

	/* Finally any file/line number */
	IMAGEHLP_LINE
	lineInfo = { sizeof(IMAGEHLP_LINE) };
	if (SymGetLineFromAddr(GetCurrentProcess(), (DWORD)address, (PDWORD)&dwDisplacement, &lineInfo)) {
		const char *pDelim = strrchr(lineInfo.FileName, '\\');
		char temp[1024];
		sprintf(temp, " at %s(%u)", (pDelim ? pDelim + 1 : lineInfo.FileName), lineInfo.LineNumber);
		strcat(buffer, temp);
	}

	return std::string(buffer);
}

void SymbolEngine::StackTrace(PCONTEXT _pContext, CoreIOWriter * _outputBuffer)
{
#if TARGET_CPU_BITS == 32
	_outputBuffer->WriteLine("  Frame       Address   Code");
#else
	_outputBuffer->WriteLine("  Frame              Address            Code");
#endif

	STACKFRAME stackFrame = { 0 };

	stackFrame.AddrPC.Offset =
#if TARGET_CPU_BITS == 32
		_pContext->Eip;
#else
		_pContext->Rip;
#endif
	stackFrame.AddrPC.Mode = AddrModeFlat;

	stackFrame.AddrFrame.Offset =
#if TARGET_CPU_BITS == 32
		_pContext->Ebp;
#else
		_pContext->Rbp;
#endif
	stackFrame.AddrFrame.Mode = AddrModeFlat;

	stackFrame.AddrStack.Offset =
#if TARGET_CPU_BITS == 32
		_pContext->Esp;
#else
		_pContext->Rsp;
#endif
	stackFrame.AddrStack.Mode = AddrModeFlat;

#ifdef TARGET_CPU_X86
	DWORD machine = IMAGE_FILE_MACHINE_I386;
	const char *format = " 0x%08x %s";
#elif defined(TARGET_CPU_X64)
	DWORD machine = IMAGE_FILE_MACHINE_AMD64;
	const char *format = " 0x%016x %s";
#endif

	while (::StackWalk(machine, hProcess, GetCurrentThread(),        /* this value doesn't matter much if previous one is a real handle */
	                   &stackFrame,
	                   _pContext,
	                   NULL, ::SymFunctionTableAccess, ::SymGetModuleBase,
	                   NULL)) {
		_outputBuffer->WriteLine(format, stackFrame.AddrFrame.Offset,
		                         addressToString(stackFrame.AddrPC.
		                                         Offset).c_str());
	}
}
#endif
void CrissCross::Debug::PrintStackTrace(CrissCross::IO::CoreIOWriter * _outputBuffer)
{
#if !defined (TARGET_OS_NETBSD) && !defined (TARGET_OS_FREEBSD) && !defined (TARGET_OS_OPENBSD) \
 && !defined(TARGET_COMPILER_MINGW) && !defined(TARGET_COMPILER_CYGWIN) && !defined(TARGET_OS_HAIKU)
#ifdef ENABLE_SYMBOL_ENGINE

	CONTEXT context = { CONTEXT_ALL };
	BOOL ret = ::GetThreadContext(GetCurrentThread(), &context);
	CoreAssert(ret != FALSE);
#ifdef TARGET_CPU_X64
	RtlCaptureContext(&context);
#elif defined(TARGET_CPU_X86)
	_asm call $ + 5;
	_asm pop eax;
	_asm mov context.Eip, eax;
	_asm mov eax, esp;
	_asm mov context.Esp, eax;
	_asm mov context.Ebp, ebp;
#endif
	SymbolEngine::instance().StackTrace(&context, _outputBuffer);

#elif defined (ENABLE_BACKTRACE)
#if defined (TARGET_OS_MACOSX)
	backtrace_t backtrace;
	backtrace_symbols_t backtrace_symbols;
	backtrace = nasty_cast<backtrace_t, void*>(dlsym(RTLD_DEFAULT, "backtrace"));
	backtrace_symbols = nasty_cast<backtrace_symbols_t, void*>(dlsym(RTLD_DEFAULT, "backtrace_symbols"));
#endif

	void *array[256];
	int size;
	char * *strings;
	int i;

	memset(array, 0, sizeof(void *) * 256);

	/* use -rdynamic flag when compiling */
	size = backtrace(array, 256);
	strings = backtrace_symbols(array, size);

	_outputBuffer->WriteLine("Obtained %d stack frames.", size);

	std::string bt = "";

	for (i = 0; i < size; i++) {
#if defined (TARGET_OS_LINUX)
		int status;
		/* extract the identifier from strings[i].  It's inside of parens. */
		char *identifier = ::strchr(strings[i], '(');
		char *identifier_end = ::strchr(strings[i], '+');
		char *address = ::strchr(strings[i], '[');
		bt += address;
		if (identifier != 0 && identifier_end != 0 && identifier < identifier_end) {
			bt += " ";
			*identifier_end = '\0';
			char * realname = abi::__cxa_demangle(identifier + 1, 0, 0, &status);
			if (realname != NULL) {
				bt += realname;
			} else {
				bt += (identifier + 1);
			}
			char *off_end = ::strchr(identifier_end + 1, ')');
			if (off_end) {
				*off_end = 0;
				bt += " + ";
				bt += (identifier_end + 1);
			}
			free(realname);
		}
#elif defined (TARGET_OS_MACOSX)
		char *addr = ::strstr(strings[i], "0x");
		char *mangled = ::strchr(addr, ' ') + 1;
		char *offset = ::strchr(addr, '+');
		char *postmangle = ::strchr(mangled, ' ');
		if (mangled) *(mangled - 1) = 0;
		bt += addr;
		int status;
		bt += ": ";
		if (addr && mangled) {
			if (postmangle)
				*postmangle = '\0';
			char *realname = abi::__cxa_demangle(mangled, 0, 0, &status);
			if (realname) {
				bt += realname;
			} else {
				bt += mangled;
			}
			bt += " ";
			bt += offset;
			free(realname);
		}
#endif
		bt += "\n";
	}

	_outputBuffer->WriteLine("%s\n", bt.c_str());

	free(strings);

#else /* defined(ENABLE_SYMBOL_ENGINE) || defined(ENABLE_BACKTRACE) */
	_outputBuffer->WriteLine("FAIL: backtrace() function not available.");
#endif

#else /* !defined (TARGET_OS_NETBSD) && !defined (TARGET_OS_FREEBSD) && !defined (TARGET_OS_OPENBSD) */
	_outputBuffer->WriteLine("Stack traces are not implemented for this platform.");
#endif
}
#ifndef USE_FAST_ASSERT
void Assert(bool _condition, const char *_testcase, const char *_file, int _line)
{
	if (!_condition) {
		char buffer[10240];
		sprintf(buffer, "Assertion failed : '%s'\nFile: %s\nLine: %d\n\n",
		        _testcase, _file, _line);
		fprintf(stderr, "%s", buffer);
		fprintf(stderr, "=== STACK TRACE ===\n");
		CoreIOWriter *stderror = new CoreIOWriter(stderr, false, CC_LN_LF);
		PrintStackTrace(stderror);
		delete stderror;
		#ifndef _DEBUG
		abort();
		#else
		_ASSERT(_condition);
		#endif
	}
}
#endif
<|endoftext|>


<commit_before>#if defined(__linux__) || defined(__APPLE__)
#include <unistd.h>
#include <syslog.h>

#include "dobby_internal.h"

#include "Interceptor.h"

__attribute__((constructor)) static void ctor() {
  DLOG(-1, "================================");
  DLOG(-1, "Dobby");
  DLOG(-1, "================================");

  DLOG(-1, "dobby in debug log mode, disable with cmake flag \"-DDOBBY_DEBUG=OFF\"");
}

PUBLIC const char *DobbyBuildVersion() {
  return __DOBBY_BUILD_VERSION__;
}

PUBLIC int DobbyDestroy(void *address) {
  Interceptor *interceptor = Interceptor::SharedInstance();

  // check if we already hook
  HookEntry *entry = interceptor->FindHookEntry(address);
  if (entry) {
    uint8_t *buffer      = entry->origin_chunk_.chunk_buffer;
    uint32_t buffer_size = entry->origin_chunk_.chunk.length;
    CodePatch(address, buffer, buffer_size);
    return RT_SUCCESS;
  }

  return RT_FAILED;
}

#endif<commit_msg>[bug-fix] fix DobbyDestory at arm platform<commit_after>#if defined(__linux__) || defined(__APPLE__)
#include <unistd.h>
#include <syslog.h>

#include "dobby_internal.h"

#include "Interceptor.h"

__attribute__((constructor)) static void ctor() {
  DLOG(-1, "================================");
  DLOG(-1, "Dobby");
  DLOG(-1, "================================");

  DLOG(-1, "dobby in debug log mode, disable with cmake flag \"-DDOBBY_DEBUG=OFF\"");
}

PUBLIC const char *DobbyBuildVersion() {
  return __DOBBY_BUILD_VERSION__;
}

PUBLIC int DobbyDestroy(void *address) {
  Interceptor *interceptor = Interceptor::SharedInstance();

  // check if we already hook
  HookEntry *entry = interceptor->FindHookEntry(address);
  if (entry) {
    uint8_t *buffer      = entry->origin_chunk_.chunk_buffer;
    uint32_t buffer_size = entry->origin_chunk_.chunk.length;
#if defined(TARGET_ARCH_ARM)
    address = (void *)((addr_t)address - 1);
#endif
    CodePatch(address, buffer, buffer_size);
    return RT_SUCCESS;
  }

  return RT_FAILED;
}

#endif<|endoftext|>


<commit_before>// formatxx - C++ string formatting library.
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non - commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org/>
//
// Authors:
//   Sean Middleditch <sean@middleditch.us>

#include "formatxx/format.h"

#include <cstdio>
#include <limits>

namespace
{
	constexpr char sErrBadFormat[]  = "#BADF";
	constexpr char sErrIncomplete[] = "#INCL";
	constexpr char sErrOutOfRange[] = "#RNGE";

	// during integer formatting, we'll work on every two decimal digits (groups of 100). notes taken from cppformat,
	// which took the notes from Alexandrescu from "Three Optimization Tips for C++"
	constexpr char sDecimalTable[] =
		"00010203040506070809"
		"10111213141516171819"
		"20212223242526272829"
		"30313233343536373839"
		"40414243444546474849"
		"50515253545556575859"
		"60616263646566676869"
		"70717273747576777879"
		"80818283848586878889"
		"90919293949596979899";

	// base-10 digits, NUL, sign, signed extension
	constexpr std::size_t kIntBufferSize = std::numeric_limits<unsigned long long>::digits10 + 3;

	char* gen_unsigned_decimal(char buffer[kIntBufferSize], unsigned long long value)
	{
		// we're going to write backwards into the buffer, starting from the end character
		char* end = buffer + kIntBufferSize;

		// ensure we get the NUL character
		*--end = '\0';

		// work on every two decimal digits (groups of 100). notes taken from cppformat,
		// which took the notes from Alexandrescu from "Three Optimization Tips for C++"
		while (value >= 100)
		{
			// I feel like we could do the % and / better... somehow
			// we multiply the index by two to find the pair of digits to index
			unsigned const digit = (value % 100) << 1;
			value /= 100;

			// write out both digits of the given index, starting with the second, since we're writing backwards
			*--end = sDecimalTable[digit + 1];
			*--end = sDecimalTable[digit];
		}

		if (value >= 10)
		{
			// we have two difits left; this is identical to the above loop, but without the division
			unsigned const digit = static_cast<unsigned>(value << 1);
			*--end = sDecimalTable[digit + 1];
			*--end = sDecimalTable[digit];
		}
		else
		{
			// we have but a single digit left, so this is easy
			*--end = static_cast<char>('0' + value);
		}

		// we return the location in the buffer that our formatted string starts at
		return end;
	}

	char* gen_signed_decimal(char buffer[kIntBufferSize], signed long long value)
	{
		// if the value is non-negative, the unsigned version does everything we need
		if (value >= 0)
			return gen_unsigned_decimal(buffer, static_cast<unsigned long long>(value));

		// subtract form 0 _after_ converting to deal with 2's complement format
		unsigned long long abs_value = 0 - static_cast<unsigned long long>(value);
		char* end = gen_unsigned_decimal(buffer, abs_value);
		*--end = '-';
		return end;
	}

	template <size_t N>
	void write_error(formatxx::format_writer& out, const char(&string)[N])
	{
		out.write(formatxx::string_view(string, N - 1));
	}

	template <typename T>
	void write_unsigned(formatxx::format_writer& out, T value, formatxx::format_spec const&)
	{
		char buffer[kIntBufferSize];
		out.write(gen_unsigned_decimal(buffer, value));
	}

	template <typename T>
	void write_signed(formatxx::format_writer& out, T value, formatxx::format_spec const& spec)
	{
		char buffer[kIntBufferSize];
		out.write(gen_signed_decimal(buffer, value));
	}

	char const* parse_unsigned(char const* start, char const* end, unsigned* result)
	{
		*result = 0;
		while (start != end && *start >= '0' && *start <= '9')
		{
			*result *= 10;
			*result += *start - '0';
			++start;
		}
		return start;
	}
}

namespace formatxx
{
	void format_value(format_writer& out, char ch, format_spec const&)
	{
		out.write(string_view(&ch, 1));
	}

	void format_value(format_writer& out, bool value, format_spec const&)
	{
		value ? write_error(out, "true") : write_error(out, "false");
	}

	void format_value(format_writer& out, char* ptr, format_spec const& spec)
	{
		format_value(out, static_cast<char const*>(ptr), spec);
	}

	void format_value(format_writer& out, char const* zstr, format_spec const&)
	{
		out.write(string_view(zstr));
	}

	void format_value(format_writer& out, string_view str, format_spec const&)
	{
		out.write(str);
	}

	void format_value(format_writer& out, signed int value, format_spec const& spec) { write_signed(out, value, spec); }
	void format_value(format_writer& out, signed long value, format_spec const& spec) { write_signed(out, value, spec); }
	void format_value(format_writer& out, signed short value, format_spec const& spec) { write_signed(out, value, spec); }
	void format_value(format_writer& out, signed long long value, format_spec const& spec) { write_signed(out, value, spec); }

	void format_value(format_writer& out, unsigned int value, format_spec const& spec) { write_unsigned(out, value, spec); }
	void format_value(format_writer& out, unsigned long value, format_spec const& spec) { write_unsigned(out, value, spec); }
	void format_value(format_writer& out, unsigned short value, format_spec const& spec) { write_unsigned(out, value, spec); }
	void format_value(format_writer& out, unsigned long long value, format_spec const& spec) { write_unsigned(out, value, spec); }

	void format_value(format_writer& out, float value, format_spec const&)
	{
		char buf[512]; // not actually enough for every float, but...
		int len = std::snprintf(buf, sizeof(buf), "%f", value);
		out.write(string_view(buf, len));
	}

	void format_value(format_writer& out, double value, format_spec const&)
	{
		char buf[1048]; // not actually enough for every float, but...
		int len = std::snprintf(buf, sizeof(buf), "%g", value);
		out.write(string_view(buf, len));
	}

	void format_value(format_writer& out, void* ptr, format_spec const& spec)
	{
		format_value(out, static_cast<void const*>(ptr), spec);
	}

	void format_value(format_writer& out, void const* ptr, format_spec const&)
	{
		char buf[48];
		int len = std::snprintf(buf, sizeof(buf), "%p", ptr);
		out.write(string_view(buf, len));
	}
}

void formatxx::_detail::format_impl(format_writer& out, string_view format, std::size_t count, FormatFunc const* funcs, void const** values)
{
	unsigned next_index = 0;

	char const* span = format.data();
	char const* cur = span;
	char const* const end = span + format.size();
	while (cur < end)
	{
		if (*cur == '{')
		{
			// write out the string so far, since we don't write characters immediately
			if (cur > span)
				out.write(string_view(span, cur - span));

			++cur; // swallow the {

			// if we hit the end of the input, we have an incomplete format, and nothing else we can do
			if (cur == end)
			{
				write_error(out, sErrIncomplete);
				break;
			}

			// if we just have another { then take it as a literal character by starting our next span here,
			// so it'll get written next time we write out the span; nothing else to do for formatting here
			if (*cur == '{')
			{
				span = cur++;
				continue;
			}

			// determine which argument we're going to format
			unsigned index = 0;
			char const* const start = cur;
			char const* cur = parse_unsigned(start, end, &index);

			// if we read nothing, we have a "next index" situation (or an error)
			if (cur == start)
				index = next_index;

			// if we hit the end of the string, we have an incomplete format
			if (cur == end)
			{
				write_error(out, sErrIncomplete);
				break;
			}

			// if a | follows the number, we have some formatting controls
			if (*cur == '|')
			{
				// #FIXME: parse and save these
				while (cur < end && *cur != '}')
					++cur;

				if (cur == end)
				{
					write_error(out, sErrIncomplete);
					break;
				}
			}
			else if (*cur != '}')
			{
				// we have something besides a number, no bueno
				write_error(out, sErrIncomplete);
				span = cur; // make sure we're set up for the next span, which starts at this unknown character
				continue;
			}

			// the current text span begins with the next character following the format directive's end
			span = cur = cur + 1;

			// if the index is out of range, we have nothing to format
			if (index >= count)
			{
				write_error(out, sErrOutOfRange);
				continue;
			}

			// magic!
			format_spec spec;
			funcs[index](out, values[index], spec);

			// if we continue to receive {} then the next index will be the next one after the last one used
			next_index = index + 1;
		}
		else
		{
			++cur;
		}
	}

	// write out tail end of format string
	if (cur > span)
		out.write(string_view(span, cur - span));
}
<commit_msg>Null C strings are printed like null pointers now. Previously they crashed.<commit_after>// formatxx - C++ string formatting library.
//
// This is free and unencumbered software released into the public domain.
//
// Anyone is free to copy, modify, publish, use, compile, sell, or
// distribute this software, either in source code form or as a compiled
// binary, for any purpose, commercial or non - commercial, and by any
// means.
//
// In jurisdictions that recognize copyright laws, the author or authors
// of this software dedicate any and all copyright interest in the
// software to the public domain. We make this dedication for the benefit
// of the public at large and to the detriment of our heirs and
// successors. We intend this dedication to be an overt act of
// relinquishment in perpetuity of all present and future rights to this
// software under copyright law.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
// For more information, please refer to <http://unlicense.org/>
//
// Authors:
//   Sean Middleditch <sean@middleditch.us>

#include "formatxx/format.h"

#include <cstdio>
#include <limits>

namespace
{
	constexpr char sErrBadFormat[]  = "#BADF";
	constexpr char sErrIncomplete[] = "#INCL";
	constexpr char sErrOutOfRange[] = "#RNGE";

	// during integer formatting, we'll work on every two decimal digits (groups of 100). notes taken from cppformat,
	// which took the notes from Alexandrescu from "Three Optimization Tips for C++"
	constexpr char sDecimalTable[] =
		"00010203040506070809"
		"10111213141516171819"
		"20212223242526272829"
		"30313233343536373839"
		"40414243444546474849"
		"50515253545556575859"
		"60616263646566676869"
		"70717273747576777879"
		"80818283848586878889"
		"90919293949596979899";

	// base-10 digits, NUL, sign, signed extension
	constexpr std::size_t kIntBufferSize = std::numeric_limits<unsigned long long>::digits10 + 3;

	char* gen_unsigned_decimal(char buffer[kIntBufferSize], unsigned long long value)
	{
		// we're going to write backwards into the buffer, starting from the end character
		char* end = buffer + kIntBufferSize;

		// ensure we get the NUL character
		*--end = '\0';

		// work on every two decimal digits (groups of 100). notes taken from cppformat,
		// which took the notes from Alexandrescu from "Three Optimization Tips for C++"
		while (value >= 100)
		{
			// I feel like we could do the % and / better... somehow
			// we multiply the index by two to find the pair of digits to index
			unsigned const digit = (value % 100) << 1;
			value /= 100;

			// write out both digits of the given index, starting with the second, since we're writing backwards
			*--end = sDecimalTable[digit + 1];
			*--end = sDecimalTable[digit];
		}

		if (value >= 10)
		{
			// we have two difits left; this is identical to the above loop, but without the division
			unsigned const digit = static_cast<unsigned>(value << 1);
			*--end = sDecimalTable[digit + 1];
			*--end = sDecimalTable[digit];
		}
		else
		{
			// we have but a single digit left, so this is easy
			*--end = static_cast<char>('0' + value);
		}

		// we return the location in the buffer that our formatted string starts at
		return end;
	}

	char* gen_signed_decimal(char buffer[kIntBufferSize], signed long long value)
	{
		// if the value is non-negative, the unsigned version does everything we need
		if (value >= 0)
			return gen_unsigned_decimal(buffer, static_cast<unsigned long long>(value));

		// subtract form 0 _after_ converting to deal with 2's complement format
		unsigned long long abs_value = 0 - static_cast<unsigned long long>(value);
		char* end = gen_unsigned_decimal(buffer, abs_value);
		*--end = '-';
		return end;
	}

	template <size_t N>
	void write_error(formatxx::format_writer& out, const char(&string)[N])
	{
		out.write(formatxx::string_view(string, N - 1));
	}

	template <typename T>
	void write_unsigned(formatxx::format_writer& out, T value, formatxx::format_spec const&)
	{
		char buffer[kIntBufferSize];
		out.write(gen_unsigned_decimal(buffer, value));
	}

	template <typename T>
	void write_signed(formatxx::format_writer& out, T value, formatxx::format_spec const& spec)
	{
		char buffer[kIntBufferSize];
		out.write(gen_signed_decimal(buffer, value));
	}

	char const* parse_unsigned(char const* start, char const* end, unsigned* result)
	{
		*result = 0;
		while (start != end && *start >= '0' && *start <= '9')
		{
			*result *= 10;
			*result += *start - '0';
			++start;
		}
		return start;
	}
}

namespace formatxx
{
	void format_value(format_writer& out, char ch, format_spec const&)
	{
		out.write(string_view(&ch, 1));
	}

	void format_value(format_writer& out, bool value, format_spec const&)
	{
		value ? write_error(out, "true") : write_error(out, "false");
	}

	void format_value(format_writer& out, char* ptr, format_spec const& spec)
	{
		if (ptr != nullptr)
			format_value(out, static_cast<char const*>(ptr), spec);
		else
			format_value(out, static_cast<void const*>(nullptr), spec);
	}

	void format_value(format_writer& out, char const* zstr, format_spec const& spec)
	{
		if (zstr != nullptr)
			out.write(string_view(zstr));
		else
			format_value(out, static_cast<void const*>(nullptr), spec);
	}

	void format_value(format_writer& out, string_view str, format_spec const&)
	{
		out.write(str);
	}

	void format_value(format_writer& out, signed int value, format_spec const& spec) { write_signed(out, value, spec); }
	void format_value(format_writer& out, signed long value, format_spec const& spec) { write_signed(out, value, spec); }
	void format_value(format_writer& out, signed short value, format_spec const& spec) { write_signed(out, value, spec); }
	void format_value(format_writer& out, signed long long value, format_spec const& spec) { write_signed(out, value, spec); }

	void format_value(format_writer& out, unsigned int value, format_spec const& spec) { write_unsigned(out, value, spec); }
	void format_value(format_writer& out, unsigned long value, format_spec const& spec) { write_unsigned(out, value, spec); }
	void format_value(format_writer& out, unsigned short value, format_spec const& spec) { write_unsigned(out, value, spec); }
	void format_value(format_writer& out, unsigned long long value, format_spec const& spec) { write_unsigned(out, value, spec); }

	void format_value(format_writer& out, float value, format_spec const&)
	{
		char buf[512]; // not actually enough for every float, but...
		int len = std::snprintf(buf, sizeof(buf), "%f", value);
		out.write(string_view(buf, len));
	}

	void format_value(format_writer& out, double value, format_spec const&)
	{
		char buf[1048]; // not actually enough for every float, but...
		int len = std::snprintf(buf, sizeof(buf), "%g", value);
		out.write(string_view(buf, len));
	}

	void format_value(format_writer& out, void* ptr, format_spec const& spec)
	{
		format_value(out, static_cast<void const*>(ptr), spec);
	}

	void format_value(format_writer& out, void const* ptr, format_spec const&)
	{
		char buf[48];
		int len = std::snprintf(buf, sizeof(buf), "%p", ptr);
		out.write(string_view(buf, len));
	}
}

void formatxx::_detail::format_impl(format_writer& out, string_view format, std::size_t count, FormatFunc const* funcs, void const** values)
{
	unsigned next_index = 0;

	char const* span = format.data();
	char const* cur = span;
	char const* const end = span + format.size();
	while (cur < end)
	{
		if (*cur == '{')
		{
			// write out the string so far, since we don't write characters immediately
			if (cur > span)
				out.write(string_view(span, cur - span));

			++cur; // swallow the {

			// if we hit the end of the input, we have an incomplete format, and nothing else we can do
			if (cur == end)
			{
				write_error(out, sErrIncomplete);
				break;
			}

			// if we just have another { then take it as a literal character by starting our next span here,
			// so it'll get written next time we write out the span; nothing else to do for formatting here
			if (*cur == '{')
			{
				span = cur++;
				continue;
			}

			// determine which argument we're going to format
			unsigned index = 0;
			char const* const start = cur;
			char const* cur = parse_unsigned(start, end, &index);

			// if we read nothing, we have a "next index" situation (or an error)
			if (cur == start)
				index = next_index;

			// if we hit the end of the string, we have an incomplete format
			if (cur == end)
			{
				write_error(out, sErrIncomplete);
				break;
			}

			// if a | follows the number, we have some formatting controls
			if (*cur == '|')
			{
				// #FIXME: parse and save these
				while (cur < end && *cur != '}')
					++cur;

				if (cur == end)
				{
					write_error(out, sErrIncomplete);
					break;
				}
			}
			else if (*cur != '}')
			{
				// we have something besides a number, no bueno
				write_error(out, sErrIncomplete);
				span = cur; // make sure we're set up for the next span, which starts at this unknown character
				continue;
			}

			// the current text span begins with the next character following the format directive's end
			span = cur = cur + 1;

			// if the index is out of range, we have nothing to format
			if (index >= count)
			{
				write_error(out, sErrOutOfRange);
				continue;
			}

			// magic!
			format_spec spec;
			funcs[index](out, values[index], spec);

			// if we continue to receive {} then the next index will be the next one after the last one used
			next_index = index + 1;
		}
		else
		{
			++cur;
		}
	}

	// write out tail end of format string
	if (cur > span)
		out.write(string_view(span, cur - span));
}
<|endoftext|>


<commit_before>#include "game.hpp"
#include "about.hpp"
#include "box.hpp"
#include "constants.hpp"
#include "data.hpp"
#include "io.hpp"
#include "logger.hpp"
#include "memory.hpp"
#include "menu.hpp"
#include "physics.hpp"
#include "profiler.hpp"
#include "random.hpp"
#include "record.hpp"
#include "text.hpp"
#include "version.hpp"
#include <SDL.h>
#include <cstdlib>
#include <cstring>

#define DEFAULT_LIMIT_PLAYED_MINUTES 2
#define DEFAULT_LIMIT_PLAYED_SECONDS (DEFAULT_LIMIT_PLAYED_MINUTES * 60)
#define DEFAULT_LIMIT_PLAYED_FRAMES DEFAULT_LIMIT_PLAYED_SECONDS *UPS

static const Milliseconds register_score_release_delay = 200;

static size_t get_rigid_matrix_index(const Game *const game, const int x, const int y) {
  const int base_x = x - game->box->min_x;
  const int base_y = y - game->box->min_y;
  return base_x + base_y * game->rigid_matrix_n;
}

unsigned char get_from_rigid_matrix(const Game *const game, const int x, const int y) {
  if (game->box->contains(x, y)) {
    return game->rigid_matrix[get_rigid_matrix_index(game, x, y)];
  }
  return 0;
}

void modify_rigid_matrix_point(const Game *const game, const int x, const int y, S8 delta) {
  if (game->box->contains(x, y)) {
    game->rigid_matrix[get_rigid_matrix_index(game, x, y)] += delta;
  }
}

void modify_rigid_matrix_platform(Game *game, Platform const *platform, S8 delta) {
  for (int x = 0; x < platform->w; ++x) {
    for (int y = 0; y < platform->h; ++y) {
      modify_rigid_matrix_point(game, platform->x + x, platform->y + y, delta);
    }
  }
}

static void initialize_rigid_matrix(Game *game) {
  memset(game->rigid_matrix, 0, game->rigid_matrix_size);
  for (size_t i = 0; i < game->platform_count; i++) {
    modify_rigid_matrix_platform(game, game->platforms.data() + i, 1);
  }
}

static void initialize_bounding_box(Game *game) {
  game->box->min_x = 0;
  game->box->min_y = 0;
  game->box->max_x = get_window_width();
  game->box->max_y = get_window_height() - 2 * get_bar_height();
}

Game::Game(Player *player, Profiler *profiler) : player(player), profiler(profiler) {
  tile_w = get_tile_width();
  tile_h = get_tile_height();
  platform_count = get_platform_count();
  size_t rigid_matrix_bytes;

  box = new BoundingBox;
  initialize_bounding_box(this);

  platforms = generate_platforms(*box, platform_count, tile_w, tile_h);

  current_frame = 0;
  desired_frame = 0;

  played_frames = 0;
  limit_played_frames = DEFAULT_LIMIT_PLAYED_FRAMES;

  paused = false;

  player->w = tile_w;
  player->h = tile_h;

  reposition_player(this);

  perk = PERK_NONE;
  perk_x = 0;
  perk_y = 0;
  /* Don't start with a Perk on the screen. */
  perk_end_frame = PERK_SCREEN_DURATION_IN_FRAMES;

  rigid_matrix_m = static_cast<size_t>(box->max_y - box->min_y + 1);
  rigid_matrix_n = static_cast<size_t>(box->max_x - box->min_x + 1);
  rigid_matrix_size = rigid_matrix_m * rigid_matrix_n;
  rigid_matrix_bytes = sizeof(unsigned char) * rigid_matrix_size;
  rigid_matrix = reinterpret_cast<unsigned char *>(resize_memory(nullptr, rigid_matrix_bytes));
  initialize_rigid_matrix(this);

  message[0] = '\0';
  message_end_frame = 0;
  message_priority = 0;

  log_message("Finished creating the game.");
}

Game::~Game() {
  destroy_player(player);
  rigid_matrix = reinterpret_cast<unsigned char *>(resize_memory(rigid_matrix, 0));
  box = reinterpret_cast<BoundingBox *>(resize_memory(box, 0));
}

Milliseconds update_game(Game *const game) {
  Milliseconds game_update_start;
  game->profiler->start("update_game");
  game_update_start = get_milliseconds();
  if (game->message_end_frame < game->current_frame) {
    game->message[0] = '\0';
  }
  update_platforms(game);
  update_perk(game);
  game->profiler->stop();
  return get_milliseconds() - game_update_start;
}

/**
 * Changes the game message to the provided text, for the provided duration.
 *
 * If there is a message and it has higher priority, it is not changed.
 *
 * This function prevents buffer overflow by truncating the message.
 */
void game_set_message(Game *const game, const char *message, const unsigned long duration,
                      const unsigned int priority) {
  const auto last_has_expired = static_cast<const int>(game->message_end_frame <= game->current_frame);
  const auto last_has_lower_priority = static_cast<const int>(game->message_priority <= priority);
  if ((last_has_expired != 0) || (last_has_lower_priority != 0)) {
    game->message_end_frame = game->current_frame + duration * UPS;
    game->message_priority = priority;
    copy_string(game->message, message, MAXIMUM_STRING_SIZE);
  }
}

static void print_game_result(const Player *player, const int position, SDL_Renderer *renderer) {
  const char *name = player->name;
  const Score score = player->score;
  const ColorPair color = COLOR_PAIR_DEFAULT;
  char first_line[MAXIMUM_STRING_SIZE];
  char empty_line[1] = "";
  char second_line[MAXIMUM_STRING_SIZE];
  sprintf(first_line, "%s died after making %ld points.", name, score);
  if (position > 0) {
    sprintf(second_line, "%s got to position %d!", name, position);
  } else {
    sprintf(second_line, "%s didn't make it to the top scores.", name);
  }
  std::vector<std::string> lines;
  lines.emplace_back(first_line);
  lines.emplace_back(empty_line);
  lines.emplace_back(second_line);
  clear(renderer);
  print_centered_vertically(lines, color, renderer);
  present(renderer);
}

Code register_score(const Game *const game, SDL_Renderer *renderer) {
  const Player *const player = game->player;
  char buffer[MAXIMUM_STRING_SIZE];
  const char *format = "Started registering a score of %d points for %s.";
  Record record{};
  int scoreboard_index;
  int position;
  sprintf(buffer, format, player->score, player->name, renderer);
  log_message(buffer);
  record = make_record(player->name, player->score);
  scoreboard_index = save_record(&record);
  position = scoreboard_index + 1;
  log_message("Saved the record successfully.");
  print_game_result(player, position, renderer);
  const Milliseconds release_time = get_milliseconds() + register_score_release_delay;
  Code code = CODE_OK;
  while ((code = wait_for_input(game->player->table)) == CODE_OK) {
    if (get_milliseconds() > release_time) {
      break;
    }
  }
  return code;
}

/**
 * Runs the main game loop for the Game object and registers the player score.
 */
Code run_game(Game *const game, SDL_Renderer *renderer) {
  unsigned long next_played_frames_score = UPS;
  const Milliseconds interval = 1000 / UPS;
  Milliseconds start_time = 0;
  Milliseconds time_passed = 0;
  Code code = CODE_OK;
  int *lives = &game->player->lives;
  unsigned long limit = game->limit_played_frames;
  CommandTable table{};
  initialize_command_table(&table);
  while ((game->player->table->status[COMMAND_QUIT] == 0.0) && *lives != 0 && game->played_frames < limit) {
    start_time = get_milliseconds();
    if (time_passed >= 2 * interval) {
      fprintf(stderr, "Skipped a frame!\n");
    }
    while (time_passed > interval) {
      time_passed -= interval;
      game->desired_frame++;
    }
    if (game->paused) {
      draw_game(game, renderer);
      read_commands(game->player->table);
      if (test_command_table(game->player->table, COMMAND_CLOSE, REPETITION_DELAY)) {
        code = CODE_CLOSE;
      }
      if (test_command_table(game->player->table, COMMAND_QUIT, REPETITION_DELAY)) {
        code = CODE_QUIT;
      }
      if (test_command_table(game->player->table, COMMAND_PAUSE, REPETITION_DELAY)) {
        game->paused = false;
      }
      continue;
    }
    if (game->played_frames == next_played_frames_score) {
      player_score_add(game->player, 1);
      next_played_frames_score += UPS;
    }
    while (game->current_frame < game->desired_frame) {
      update_game(game);
      update_player(game, game->player);
      game->current_frame++;
    }
    draw_game(game, renderer);
    read_commands(game->player->table);
    if (test_command_table(game->player->table, COMMAND_PAUSE, REPETITION_DELAY)) {
      game->paused = true;
    }
    time_passed += get_milliseconds() - start_time;
  }
  if (code != CODE_CLOSE) {
    code = register_score(game, renderer);
  }
  if (code == CODE_QUIT) {
    /* When the player quits from the game, it should go back to the menu. */
    code = CODE_OK;
  }
  return code;
}
<commit_msg>Should have a soft FPS cap<commit_after>#include "game.hpp"
#include "io.hpp"
#include "memory.hpp"
#include "text.hpp"
#include <cstring>

#define DEFAULT_LIMIT_PLAYED_MINUTES 2
#define DEFAULT_LIMIT_PLAYED_SECONDS (DEFAULT_LIMIT_PLAYED_MINUTES * 60)
#define DEFAULT_LIMIT_PLAYED_FRAMES DEFAULT_LIMIT_PLAYED_SECONDS *UPS

static const Milliseconds register_score_release_delay = 200;
static const Milliseconds milliseconds_in_a_second = 1000;
static const int maximum_fps = 250;

static size_t get_rigid_matrix_index(const Game *const game, const int x, const int y) {
  const int base_x = x - game->box->min_x;
  const int base_y = y - game->box->min_y;
  return base_x + base_y * game->rigid_matrix_n;
}

unsigned char get_from_rigid_matrix(const Game *const game, const int x, const int y) {
  if (game->box->contains(x, y)) {
    return game->rigid_matrix[get_rigid_matrix_index(game, x, y)];
  }
  return 0;
}

void modify_rigid_matrix_point(const Game *const game, const int x, const int y, S8 delta) {
  if (game->box->contains(x, y)) {
    game->rigid_matrix[get_rigid_matrix_index(game, x, y)] += delta;
  }
}

void modify_rigid_matrix_platform(Game *game, Platform const *platform, S8 delta) {
  for (int x = 0; x < platform->w; ++x) {
    for (int y = 0; y < platform->h; ++y) {
      modify_rigid_matrix_point(game, platform->x + x, platform->y + y, delta);
    }
  }
}

static void initialize_rigid_matrix(Game *game) {
  memset(game->rigid_matrix, 0, game->rigid_matrix_size);
  for (size_t i = 0; i < game->platform_count; i++) {
    modify_rigid_matrix_platform(game, game->platforms.data() + i, 1);
  }
}

static void initialize_bounding_box(Game *game) {
  game->box->min_x = 0;
  game->box->min_y = 0;
  game->box->max_x = get_window_width();
  game->box->max_y = get_window_height() - 2 * get_bar_height();
}

Game::Game(Player *player, Profiler *profiler) : player(player), profiler(profiler) {
  tile_w = get_tile_width();
  tile_h = get_tile_height();
  platform_count = get_platform_count();
  size_t rigid_matrix_bytes;

  box = new BoundingBox;
  initialize_bounding_box(this);

  platforms = generate_platforms(*box, platform_count, tile_w, tile_h);

  current_frame = 0;
  desired_frame = 0;

  played_frames = 0;
  limit_played_frames = DEFAULT_LIMIT_PLAYED_FRAMES;

  paused = false;

  player->w = tile_w;
  player->h = tile_h;

  reposition_player(this);

  perk = PERK_NONE;
  perk_x = 0;
  perk_y = 0;
  /* Don't start with a Perk on the screen. */
  perk_end_frame = PERK_SCREEN_DURATION_IN_FRAMES;

  rigid_matrix_m = static_cast<size_t>(box->max_y - box->min_y + 1);
  rigid_matrix_n = static_cast<size_t>(box->max_x - box->min_x + 1);
  rigid_matrix_size = rigid_matrix_m * rigid_matrix_n;
  rigid_matrix_bytes = sizeof(unsigned char) * rigid_matrix_size;
  rigid_matrix = reinterpret_cast<unsigned char *>(resize_memory(nullptr, rigid_matrix_bytes));
  initialize_rigid_matrix(this);

  message[0] = '\0';
  message_end_frame = 0;
  message_priority = 0;

  log_message("Finished creating the game.");
}

Game::~Game() {
  destroy_player(player);
  rigid_matrix = reinterpret_cast<unsigned char *>(resize_memory(rigid_matrix, 0));
  box = reinterpret_cast<BoundingBox *>(resize_memory(box, 0));
}

Milliseconds update_game(Game *const game) {
  Milliseconds game_update_start;
  game->profiler->start("update_game");
  game_update_start = get_milliseconds();
  if (game->message_end_frame < game->current_frame) {
    game->message[0] = '\0';
  }
  update_platforms(game);
  update_perk(game);
  game->profiler->stop();
  return get_milliseconds() - game_update_start;
}

/**
 * Changes the game message to the provided text, for the provided duration.
 *
 * If there is a message and it has higher priority, it is not changed.
 *
 * This function prevents buffer overflow by truncating the message.
 */
void game_set_message(Game *const game, const char *message, const unsigned long duration,
                      const unsigned int priority) {
  const auto last_has_expired = static_cast<const int>(game->message_end_frame <= game->current_frame);
  const auto last_has_lower_priority = static_cast<const int>(game->message_priority <= priority);
  if ((last_has_expired != 0) || (last_has_lower_priority != 0)) {
    game->message_end_frame = game->current_frame + duration * UPS;
    game->message_priority = priority;
    copy_string(game->message, message, MAXIMUM_STRING_SIZE);
  }
}

static void print_game_result(const Player *player, const int position, SDL_Renderer *renderer) {
  const char *name = player->name;
  const Score score = player->score;
  const ColorPair color = COLOR_PAIR_DEFAULT;
  char first_line[MAXIMUM_STRING_SIZE];
  char empty_line[1] = "";
  char second_line[MAXIMUM_STRING_SIZE];
  sprintf(first_line, "%s died after making %ld points.", name, score);
  if (position > 0) {
    sprintf(second_line, "%s got to position %d!", name, position);
  } else {
    sprintf(second_line, "%s didn't make it to the top scores.", name);
  }
  std::vector<std::string> lines;
  lines.emplace_back(first_line);
  lines.emplace_back(empty_line);
  lines.emplace_back(second_line);
  clear(renderer);
  print_centered_vertically(lines, color, renderer);
  present(renderer);
}

Code register_score(const Game *const game, SDL_Renderer *renderer) {
  const Player *const player = game->player;
  char buffer[MAXIMUM_STRING_SIZE];
  const char *format = "Started registering a score of %d points for %s.";
  Record record{};
  int scoreboard_index;
  int position;
  sprintf(buffer, format, player->score, player->name, renderer);
  log_message(buffer);
  record = make_record(player->name, player->score);
  scoreboard_index = save_record(&record);
  position = scoreboard_index + 1;
  log_message("Saved the record successfully.");
  print_game_result(player, position, renderer);
  const Milliseconds release_time = get_milliseconds() + register_score_release_delay;
  Code code = CODE_OK;
  while ((code = wait_for_input(game->player->table)) == CODE_OK) {
    if (get_milliseconds() > release_time) {
      break;
    }
  }
  return code;
}

/**
 * Runs the main game loop for the Game object and registers the player score.
 */
Code run_game(Game *const game, SDL_Renderer *renderer) {
  unsigned long next_played_frames_score = UPS;
  const Milliseconds frame_interval = milliseconds_in_a_second / maximum_fps;
  const Milliseconds logic_interval = milliseconds_in_a_second / UPS;
  Milliseconds start_time = 0;
  Milliseconds time_since_last_logic_update = 0;
  Code code = CODE_OK;
  int *lives = &game->player->lives;
  unsigned long limit = game->limit_played_frames;
  CommandTable table{};
  initialize_command_table(&table);
  while ((game->player->table->status[COMMAND_QUIT] == 0.0) && *lives != 0 && game->played_frames < limit) {
    start_time = get_milliseconds();
    if (time_since_last_logic_update >= 2 * logic_interval) {
      fprintf(stderr, "Skipped a frame!\n");
    }
    while (time_since_last_logic_update > logic_interval) {
      time_since_last_logic_update -= logic_interval;
      game->desired_frame++;
    }
    if (game->paused) {
      draw_game(game, renderer);
      read_commands(game->player->table);
      if (test_command_table(game->player->table, COMMAND_CLOSE, REPETITION_DELAY)) {
        code = CODE_CLOSE;
      }
      if (test_command_table(game->player->table, COMMAND_QUIT, REPETITION_DELAY)) {
        code = CODE_QUIT;
      }
      if (test_command_table(game->player->table, COMMAND_PAUSE, REPETITION_DELAY)) {
        game->paused = false;
      }
      continue;
    }
    if (game->played_frames == next_played_frames_score) {
      player_score_add(game->player, 1);
      next_played_frames_score += UPS;
    }
    while (game->current_frame < game->desired_frame) {
      update_game(game);
      update_player(game, game->player);
      game->current_frame++;
    }
    draw_game(game, renderer);
    read_commands(game->player->table);
    if (test_command_table(game->player->table, COMMAND_PAUSE, REPETITION_DELAY)) {
      game->paused = true;
    }
    const auto time_since_last_frame_update = get_milliseconds() - start_time;
    if (time_since_last_frame_update < frame_interval) {
      sleep_milliseconds(frame_interval - time_since_last_frame_update);
    }
    time_since_last_logic_update += get_milliseconds() - start_time;
  }
  if (code != CODE_CLOSE) {
    code = register_score(game, renderer);
  }
  if (code == CODE_QUIT) {
    /* When the player quits from the game, it should go back to the menu. */
    code = CODE_OK;
  }
  return code;
}
<|endoftext|>


<commit_before>#include <vector>
#include <iostream>
#include <fstream>
#include <math.h>
#include <string>
#include <fstream>
#include <sstream>
#include <stdlib.h>
#include <algorithm>

#define _DEBUG
#define _DUMP

bool fillMatrixFromFile(std::string path, std::vector< std::vector<unsigned short> > &matrix, std::string &x, std::string &y);
void createMatrix(unsigned short l, unsigned short c, std::vector< std::vector<unsigned short> > &matrix);
void processDiagonal(unsigned short col, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void processDiagonal1(unsigned short line, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void processDiagonal2(unsigned short col, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void processDiagonal3(unsigned short col, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void processMatrix(std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void backtrack(std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y, unsigned short i, unsigned short j, std::stringstream &ss);
void printMatrix(std::vector< std::vector<unsigned short> > &matrix);
unsigned short cost(unsigned short x);

int main(int argc, char* argv[]) {

  if(argc != 2){
    std::cout << "Exactly one input parameter is allowed. This should be the name of the input file present in public-instances." << std::endl;
    exit(EXIT_FAILURE);
  }

  std::string path("test-files/");
  path+= argv[1];

  std::vector< std::vector<unsigned short> > matrix;
  std::string x = "";
  std::string y = "";

  std::stringstream ss;

  if(fillMatrixFromFile(path, matrix, x, y)) {
    backtrack(matrix, x, y, x.size(), y.size(), ss);
    std::string result = ss.str();
    std::reverse(result.begin(), result.end());
    std::cout << result.size() << std::endl;
    std::cout << result << std::endl;
  }

  #ifdef _DUMP
  printMatrix(matrix);
  #endif

  return 0;
}

/**
  * Returns true if the file and matrix processing was successful. False otherwise
  */
bool fillMatrixFromFile(std::string path, std::vector< std::vector<unsigned short> > &matrix, std::string &x, std::string &y) {
  std::ios_base::sync_with_stdio (false);

  std::stringstream ss;
  std::ifstream file (path.c_str(), std::ifstream::in);

  if (file.is_open()) {
    std::string line;
    std::getline(file, line);

    ss << line;

    unsigned short nLines, nCols;

    ss >> nLines >> nCols;

    #ifdef _DEBUG
    std::cout << "Number of lines: " << nLines << std::endl;
    std::cout << "Number of cols: " << nCols << std::endl;
    #endif

    std::string string1;
    std::string string2;

    std::getline(file, string1);
    std::getline(file, string2);

    if (string1.size() >= string2.size()) {
      x = string1;
      y = string2;
    } else {
      y = string1;
      x = string2;
    }

    #ifdef _DEBUG
    std::cout << "X: " << x << std::endl;
    std::cout << "Y: " << y << std::endl;
    #endif

    createMatrix(y.size()+1, x.size()+1, matrix);
    processMatrix(matrix, x, y);

    std::cout << "Created Lines: " << matrix[0].size() << std::endl;
    std::cout << "Created Columns: " << matrix.size() << std::endl;

    return true;
  } else {
    return false;
  }
}

void createMatrix(unsigned short l, unsigned short c, std::vector< std::vector<unsigned short> > &matrix) {
    #pragma omp parallel for
    for (unsigned short i = 0; i < c; ++i) {
      std::vector<unsigned short> column(l, 0);
      #pragma omp critical
        matrix.push_back(column);
    }
}

void processMatrix(std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y) {
  unsigned short columns = matrix.size();
  unsigned short lines = matrix[0].size();

  for (unsigned short col = 1; col < columns; ++col) {
    processDiagonal1(col, matrix, x, y);
  }

  unsigned short col = 1;

  //This step is only needed if the matrix is not square
  if (x.size() != y.size()) {
    unsigned short nIter = columns - lines;
    for (col = 1; col <= nIter; ++col) {
      std::cout << "========= START DIAGONAL =========" << std::endl;
      processDiagonal2(col, matrix, x, y);
      std::cout << "========= END DIAGONAL =========" << std::endl;
    }
  }

  for (unsigned short line = 1; line < lines; line++) {
    processDiagonal3(line, matrix, x, y);
  }
}

// Como todas as matrizes são em largura (ou quadradas) o identificador de cada diagonal é a coluna

// Numero de linhas menor que linhas max de matrix (incluindo  first Lmax)
void processDiagonal1(unsigned short line, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y) {

  unsigned short col = 1;

  while(line >= 1) {
    if(x[col-1] == y[line-1]) {
       matrix[col][line] = matrix[col-1][line-1] + 1;
    } else {
       matrix[col][line] = std::max(matrix[col][line-1], matrix[col-1][line]);
    }
    col++;
    line--;
  }

  return;
}

// RECEBE COLUNA COMO IDENTIFICADOR DA DIAGONAL
void processDiagonal2(unsigned short col, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y) {
  unsigned short line = matrix[0].size() - 1;

  while(line >= 1) {
    std::cout << "Line: " << line << " | Col: " << col << std::endl;
    std::cout << "X[] = " << x[col-1] << " | Y[] = " << y[line-1] << std::endl;
    if(x[col-1] == y[line-1]) {
      matrix[col][line] = matrix[col-1][line-1] + 1;
      std::cout << "RESULT = " << matrix[col][line] << std::endl;
    } else {
      matrix[col][line] = std::max(matrix[col][line-1], matrix[col-1][line]);
    }
    col++;
    line--;
  }
}

// RECEBE LINHA COMO IDENTIFICADOR DA DIAGONAL
void processDiagonal3(unsigned short line, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y) {
  unsigned short maxLine = matrix[0].size();
  unsigned short col = matrix.size() - 1;

  if (line == 0) {
    return;
  }

  while(line <= maxLine) {
    if(x[col-1] == y[line-1]) {
       matrix[col][line] = matrix[col-1][line-1] + cost(col);
     } else {
       matrix[col][line] = std::max(matrix[col][line-1], matrix[col-1][line]);
     }
     col--;
     line++;
  }
}

void backtrack(std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y, unsigned short i, unsigned short j, std::stringstream &ss) {

  while(i!=0 && j!=0){
    if(x[i-1] == y[j-1]) {
      ss << std::string(1, x[i-1]);
      i--;
      j--;
    }
    else{
      if(matrix[i][j-1] < matrix[i-1][j]){
        i--;
      }
      else{
        j--;
      }
    }
  }
}

void printMatrix(std::vector< std::vector<unsigned short> > &matrix) {
  for (unsigned short i = 0; i < matrix[i].size(); ++i) {
    for (unsigned short j = 0; j < matrix.size(); ++j) {
      std::cout << matrix[i][j] << " ";
    }
    std::cout << std::endl;
  }
}

unsigned short cost(unsigned short x) {
  unsigned short i, n_iter = 20;
  double dcost = 0;
  for(i = 0; i < n_iter; i++)
    dcost += pow(sin((double) x),2) + pow(cos((double) x),2);
  return (unsigned short) (dcost / n_iter + 0.1);
}
<commit_msg>Cleaned prototypes.<commit_after>#include <vector>
#include <iostream>
#include <fstream>
#include <math.h>
#include <string>
#include <fstream>
#include <sstream>
#include <stdlib.h>
#include <algorithm>

#define _DEBUG
#define _DUMP

bool fillMatrixFromFile(std::string path, std::vector< std::vector<unsigned short> > &matrix, std::string &x, std::string &y);
void createMatrix(unsigned short l, unsigned short c, std::vector< std::vector<unsigned short> > &matrix);
void processDiagonal1(unsigned short col, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void processDiagonal2(unsigned short col, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void processDiagonal3(unsigned short line, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void processMatrix(std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y);
void backtrack(std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y, unsigned short i, unsigned short j, std::stringstream &ss);
void printMatrix(std::vector< std::vector<unsigned short> > &matrix);
unsigned short cost(unsigned short x);

int main(int argc, char* argv[]) {

  if(argc != 2){
    std::cout << "Exactly one input parameter is allowed. This should be the name of the input file present in public-instances." << std::endl;
    exit(EXIT_FAILURE);
  }

  std::string path("test-files/");
  path+= argv[1];

  std::vector< std::vector<unsigned short> > matrix;
  std::string x = "";
  std::string y = "";

  std::stringstream ss;

  if(fillMatrixFromFile(path, matrix, x, y)) {
    backtrack(matrix, x, y, x.size(), y.size(), ss);
    std::string result = ss.str();
    std::reverse(result.begin(), result.end());
    std::cout << result.size() << std::endl;
    std::cout << result << std::endl;
  }

  #ifdef _DUMP
  printMatrix(matrix);
  #endif

  return 0;
}

/**
  * Returns true if the file and matrix processing was successful. False otherwise
  */
bool fillMatrixFromFile(std::string path, std::vector< std::vector<unsigned short> > &matrix, std::string &x, std::string &y) {
  std::ios_base::sync_with_stdio (false);

  std::stringstream ss;
  std::ifstream file (path.c_str(), std::ifstream::in);

  if (file.is_open()) {
    std::string line;
    std::getline(file, line);

    ss << line;

    unsigned short nLines, nCols;

    ss >> nLines >> nCols;

    #ifdef _DEBUG
    std::cout << "Number of lines: " << nLines << std::endl;
    std::cout << "Number of cols: " << nCols << std::endl;
    #endif

    std::string string1;
    std::string string2;

    std::getline(file, string1);
    std::getline(file, string2);

    if (string1.size() >= string2.size()) {
      x = string1;
      y = string2;
    } else {
      y = string1;
      x = string2;
    }

    #ifdef _DEBUG
    std::cout << "X: " << x << std::endl;
    std::cout << "Y: " << y << std::endl;
    #endif

    createMatrix(y.size()+1, x.size()+1, matrix);
    processMatrix(matrix, x, y);

    return true;
  } else {
    return false;
  }
}

void createMatrix(unsigned short l, unsigned short c, std::vector< std::vector<unsigned short> > &matrix) {
    #pragma omp parallel for
    for (unsigned short i = 0; i < c; ++i) {
      std::vector<unsigned short> column(l, 0);
      #pragma omp critical
        matrix.push_back(column);
    }
}

void processMatrix(std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y) {
  unsigned short columns = matrix.size();
  unsigned short lines = matrix[0].size();

  for (unsigned short col = 1; col < columns; ++col) {
    processDiagonal1(col, matrix, x, y);
  }

  unsigned short col = 1;

  //This step is only needed if the matrix is not square
  if (x.size() != y.size()) {
    unsigned short nIter = columns - lines;
    for (col = 1; col <= nIter; ++col) {
      std::cout << "========= START DIAGONAL =========" << std::endl;
      processDiagonal2(col, matrix, x, y);
      std::cout << "========= END DIAGONAL =========" << std::endl;
    }
  }

  for (unsigned short line = 1; line < lines; line++) {
    processDiagonal3(line, matrix, x, y);
  }
}

// Como todas as matrizes são em largura (ou quadradas) o identificador de cada diagonal é a coluna

// Numero de linhas menor que linhas max de matrix (incluindo  first Lmax)
void processDiagonal1(unsigned short line, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y) {

  unsigned short col = 1;

  while(line >= 1) {
    if(x[col-1] == y[line-1]) {
       matrix[col][line] = matrix[col-1][line-1] + 1;
    } else {
       matrix[col][line] = std::max(matrix[col][line-1], matrix[col-1][line]);
    }
    col++;
    line--;
  }

  return;
}

// RECEBE COLUNA COMO IDENTIFICADOR DA DIAGONAL
void processDiagonal2(unsigned short col, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y) {
  unsigned short line = matrix[0].size() - 1;

  while(line >= 1) {
    std::cout << "Line: " << line << " | Col: " << col << std::endl;
    std::cout << "X[] = " << x[col-1] << " | Y[] = " << y[line-1] << std::endl;
    if(x[col-1] == y[line-1]) {
      std::cout << "PRE_RESULT: " << matrix[col-1][line-1] + 1 << std::endl;
      matrix[col][line] = matrix[col-1][line-1] + 1;
      std::cout << "RESULT: " << matrix[col][line] << std::endl;
    } else {
      matrix[col][line] = std::max(matrix[col][line-1], matrix[col-1][line]);
    }
    col++;
    line--;
  }
}

// RECEBE LINHA COMO IDENTIFICADOR DA DIAGONAL
void processDiagonal3(unsigned short line, std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y) {
  unsigned short maxLine = matrix[0].size();
  unsigned short col = matrix.size() - 1;

  if (line == 0) {
    return;
  }

  while(line <= maxLine) {
    if(x[col-1] == y[line-1]) {
       matrix[col][line] = matrix[col-1][line-1] + cost(col);
     } else {
       matrix[col][line] = std::max(matrix[col][line-1], matrix[col-1][line]);
     }
     col--;
     line++;
  }
}

void backtrack(std::vector< std::vector<unsigned short> > &matrix, std::string x, std::string y, unsigned short i, unsigned short j, std::stringstream &ss) {

  while(i!=0 && j!=0){
    if(x[i-1] == y[j-1]) {
      ss << std::string(1, x[i-1]);
      i--;
      j--;
    }
    else{
      if(matrix[i][j-1] < matrix[i-1][j]){
        i--;
      }
      else{
        j--;
      }
    }
  }
}

void printMatrix(std::vector< std::vector<unsigned short> > &matrix) {
  for (unsigned short i = 0; i < matrix[i].size(); ++i) {
    for (unsigned short j = 0; j < matrix.size(); ++j) {
      std::cout << matrix[i][j] << " ";
    }
    std::cout << std::endl;
  }
}

unsigned short cost(unsigned short x) {
  unsigned short i, n_iter = 20;
  double dcost = 0;
  for(i = 0; i < n_iter; i++)
    dcost += pow(sin((double) x),2) + pow(cos((double) x),2);
  return (unsigned short) (dcost / n_iter + 0.1);
}
<|endoftext|>


<commit_before>#include<bits/stdc++.h>
using namespace std;
int main(void)
{
	for(int x=1;x<=1;x++)
	{
		char name1[10] = {0}, name2[10] = {0}, c = 'a';
		int k = x, y = 0, div = 0, tmpint1 = 0, tmpint2 = 0, basetime = 0, endtime = 0;
		string num, tmpstr;
		vector<vector<string>> v, f;
		vector<int> Note[200];
		vector<char> Time[80000];
		string on = "Note_on_c", off = "Note_off_c", head = "Header";
		bool Tr[200] = {0};
		while(k!=0)
		{
			num.push_back(k%10+48);
			k = (k-k%10)/10;
		}
		while(num.size())
		{
			name1[y++] = num.back();
			name2[y-1] = num.back();
			num.pop_back();
		}
		name1[y] = name2[y] = '.';
		name1[y+1] = 'c';
		name1[y+2] = 's';
		name1[y+3] = 'v';
		name2[y+1] = name2[y+3] = 't';
		name2[y+2] = 'x';
		FILE *fp1 = fopen(name1, "r"), *fp2 = fopen("input.txt", "a+");
		if(!fp1||!fp2)
		{
			printf("ERROR!\n");
			continue;
		}
		c = fgetc(fp1);
		while(c!=EOF)
		{
			vector<string> tmp;
			while(c!='\n'&&c!=EOF)
			{
				string temp;
				while(c!='\n'&&c!=','&&c!=EOF)
				{
					if(c == ' ') c = fgetc(fp1);
					if(c == '\n'||c == ',') break;
					temp.push_back(c);
					c = fgetc(fp1);
				}
				tmp.push_back(temp);
				if(c == '\n') break;
				c = fgetc(fp1);
			}
			v.push_back(tmp);
			c = fgetc(fp1);
		}
		for(int i=0;i<v.size();i++)
			if(v[i][2]!=head&&v[i][2]!=on&&v[i][2]!=off)
				v.erase(v.begin()+i--);
			else if(v[i][2] == head) v[i][2] = "h";
			else if(v[i][2] == on) v[i][2] = "n";
			else if(v[i][2] == off) v[i][2] = "f";
		for(int i=1;i<v.size();i++)
		{
			v[i].erase(v[i].begin());
			v[i].erase(v[i].begin()+2);
			v[i].erase(v[i].end());
		}
		tmpstr = v[0][5];
		for(auto i:v[0][5])
			div = 10*div+i-48;
		v.erase(v.begin());
		v.pop_back();
		for(auto i:v)
		{
			tmpint1 = 0;
			for(auto j:i[0])
				tmpint1 = 10*tmpint1+j-48;
			if(tmpint1<basetime) basetime = tmpint1;
		}
		for(auto i:v)
		{
			tmpint1 = 0;
			for(auto j:i[0])
				tmpint1 = 10*tmpint1+j-48;
			if(tmpint1>endtime) endtime = tmpint1;
		}
		endtime = 8*(endtime-basetime)/div;
		printf("%d: %d %d %d\n", x, div, basetime, endtime);
		for(auto i:v)
		{
			tmpint1 = 0;
			tmpint2 = 0;
			for(auto j:i.front())
				tmpint1 = 10*tmpint1+j-48;
			for(auto j:i.back())
				tmpint2 = 10*tmpint2+j-48;
			Note[tmpint2].push_back(8*(tmpint1-basetime)/div);
		}
		for(int i=0;i<200;i++)
			if(Note[i].size()>0)
				for(auto j:Note[i])
					Time[j].push_back(i+12);
		fprintf(fp2, "\n\n%d\n\n", x);
		for(int i=0;i<endtime+100;i++)
		{
			for(auto j:Time[i])
				Tr[j] = 1-Tr[j];
			for(int j=0;j<200;j++)
				if(Tr[j])
					fprintf(fp2, "%c", j);
			fprintf(fp2, " ");
		}
		for(int i=0;i<100;i++)
			fprintf(fp2, " ");
		fclose(fp1);
		fclose(fp2);
	}
}
<commit_msg>Shorter codes<commit_after>#include<bits/stdc++.h>
using namespace std;
int main(void)
{
	for(int x=1;x<=1;x++)
	{
		char name1[10] = {0}, name2[10] = {0}, c = 'a';
		int k = x, y = 0, div = 0, tmpint1 = 0, tmpint2 = 0, basetime = 0, endtime = 0;
		string num, tmpstr;
		vector<vector<string>> v, f;
		vector<int> Note[200];
		vector<char> Time[80000];
		string on = "Note_on_c", off = "Note_off_c", head = "Header";
		bool Tr[200] = {0};
		while(k!=0)
		{
			num.push_back(k%10+48);
			k = (k-k%10)/10;
		}
		while(num.size())
		{
			name1[y++] = num.back();
			name2[y-1] = num.back();
			num.pop_back();
		}
		name1[y] = name2[y] = '.';
		name1[y+1] = 'c';
		name1[y+2] = 's';
		name1[y+3] = 'v';
		name2[y+1] = name2[y+3] = 't';
		name2[y+2] = 'x';
		FILE *fp1 = fopen(name1, "r"), *fp2 = fopen("input.txt", "a+");
		if(!fp1||!fp2)
		{
			printf("ERROR!\n");
			continue;
		}
		c = fgetc(fp1);
		while(c!=EOF)
		{
			vector<string> tmp;
			while(c!='\n'&&c!=EOF)
			{
				string temp;
				while(c!='\n'&&c!=','&&c!=EOF)
				{
					if(c == ' ') c = fgetc(fp1);
					if(c == '\n'||c == ',') break;
					temp.push_back(c);
					c = fgetc(fp1);
				}
				tmp.push_back(temp);
				if(c == '\n') break;
				c = fgetc(fp1);
			}
			v.push_back(tmp);
			c = fgetc(fp1);
		}
		for(int i=0;i<v.size();i++)
			if(v[i][2]!=head&&v[i][2]!=on&&v[i][2]!=off)
				v.erase(v.begin()+i--);
			else if(v[i][2] == head) v[i][2] = "h";
			else if(v[i][2] == on) v[i][2] = "n";
			else if(v[i][2] == off) v[i][2] = "f";
		for(int i=1;i<v.size();i++)
		{
			v[i].erase(v[i].begin());
			v[i].erase(v[i].begin()+2);
			v[i].erase(v[i].end());
		}
		tmpstr = v[0][5];
		for(auto i:v[0][5])
			div = 10*div+i-48;
		v.erase(v.begin());
		v.pop_back();
		for(auto i:v)
		{
			basetime = min(basetime, stoi(i[0]));
			endtime = max(endtime, stoi(i[0]));
		}
		endtime = 8*(endtime-basetime)/div;
		printf("%d: %d %d %d\n", x, div, basetime, endtime);
		for(auto i:v)
			Note[stoi(i.back())].push_back(8*(stoi(i.front())-basetime)/div);
		for(int i=0;i<200;i++)
			if(Note[i].size()>0)
				for(auto j:Note[i])
					Time[j].push_back(i+12);
		fprintf(fp2, "\n\n%d\n\n", x);
		for(int i=0;i<endtime+100;i++)
		{
			for(auto j:Time[i])
				Tr[j] = 1-Tr[j];
			for(int j=0;j<200;j++)
				if(Tr[j])
					fprintf(fp2, "%c", j);
			fprintf(fp2, " ");
		}
		for(int i=0;i<100;i++)
			fprintf(fp2, " ");
		fclose(fp1);
		fclose(fp2);
	}
}
<|endoftext|>