Ejemplo n.º 1
0
extern "C" void JNICALL Java_com_henrikrydgard_libnative_NativeApp_touch
	(JNIEnv *, jclass, float x, float y, int code, int pointerId) {
	// ELOG("Touch Enter %i", pointerId);

	float scaledX = (int)(x * dp_xscale);	// why the (int) cast?
	float scaledY = (int)(y * dp_yscale);

	TouchInput touch;
	touch.id = pointerId;
	touch.x = scaledX;
	touch.y = scaledY;
	if (code == 1) {
		input_state.pointer_down[pointerId] = true;
		touch.flags = TOUCH_DOWN;
	} else if (code == 2) {
		input_state.pointer_down[pointerId] = false;
		touch.flags = TOUCH_UP;
	} else {
		touch.flags = TOUCH_MOVE;
	}
	NativeTouch(touch);


	lock_guard guard(input_state.lock);

	if (pointerId >= MAX_POINTERS) {
		ELOG("Too many pointers: %i", pointerId);
		return;	// We ignore 8+ pointers entirely.
	}
	input_state.pointer_x[pointerId] = scaledX;
	input_state.pointer_y[pointerId] = scaledY;
	input_state.mouse_valid = true;

	// ELOG("Touch Exit %i", pointerId);
}
Ejemplo n.º 2
0
extern "C" jboolean JNICALL Java_org_ppsspp_ppsspp_NativeApp_touch
	(JNIEnv *, jclass, float x, float y, int code, int pointerId) {
	float scaledX = x * dp_xscale;
	float scaledY = y * dp_yscale;

	TouchInput touch;
	touch.id = pointerId;
	touch.x = scaledX;
	touch.y = scaledY;
	touch.flags = code;
	if (code & 2) {
		input_state.pointer_down[pointerId] = true;
	} else if (code & 4) {
		input_state.pointer_down[pointerId] = false;
	}

	bool retval = NativeTouch(touch);
	{
		lock_guard guard(input_state.lock);
		if (pointerId >= MAX_POINTERS) {
			ELOG("Too many pointers: %i", pointerId);
			return false;	// We ignore 8+ pointers entirely.
		}
		input_state.pointer_x[pointerId] = scaledX;
		input_state.pointer_y[pointerId] = scaledY;
		input_state.mouse_valid = true;
	}
	return retval;
}
Ejemplo n.º 3
0
void TouchInputHandler::touchDown(int id, float x, float y){
	TouchInput touchevent;
	touchevent.id = id;
	touchevent.x = x;
	touchevent.y = y;
	touchevent.flags = TOUCH_DOWN;
	NativeTouch(touchevent);
}
Ejemplo n.º 4
0
void TouchInputHandler::touchMove(int id, float x, float y){
	TouchInput touchevent;
	touchevent.id = id;
	touchevent.x = x;
	touchevent.y = y;
	touchevent.flags = TOUCH_MOVE;
	NativeTouch(touchevent);
}
Ejemplo n.º 5
0
void QtEmuGL::mouseMoveEvent(QMouseEvent *e)
{
	TouchInput input;
	input.x = e->x();
	input.y = e->y();
	input.flags = TOUCH_MOVE;
	input.id = 0;
	NativeTouch(input);
}
Ejemplo n.º 6
0
void QtEmuGL::mouseReleaseEvent(QMouseEvent *e)
{
	TouchInput input;
	input_state->pointer_down[0] = false;

	input.x = e->x();
	input.y = e->y();
	input.flags = TOUCH_UP;
	input.id = 0;
	NativeTouch(input);
}
Ejemplo n.º 7
0
void TouchInputHandler::touchMove(int id, float x, float y){
	TouchInput touchevent;
	touchevent.id = id;
	touchevent.x = x;
	touchevent.y = y;
	touchevent.flags = TOUCH_MOVE;
	input_state.lock.lock();
	input_state.pointer_x[id] = x;
	input_state.pointer_y[id] = y;
	input_state.lock.unlock();
	NativeTouch(touchevent);
}
Ejemplo n.º 8
0
void QtEmuGL::mousePressEvent(QMouseEvent *e)
{
	TouchInput input;
	input_state->pointer_down[0] = true;
	input_state->pointer_x[0] = e->x();
	input_state->pointer_y[0] = e->y();

	input.x = e->x();
	input.y = e->y();
	input.flags = TOUCH_DOWN;
	input.id = 0;
	NativeTouch(input);
}
Ejemplo n.º 9
0
void TouchInputHandler::touchDown(int id, float x, float y){
	TouchInput touchevent;
	touchevent.id = id;
	touchevent.x = x;
	touchevent.y = y;
	touchevent.flags = TOUCH_DOWN;
	input_state.lock.lock();
	input_state.pointer_down[id] = true;
	input_state.pointer_x[id] = x;
	input_state.pointer_y[id] = y;
	input_state.lock.unlock();
	NativeTouch(touchevent);
}
Ejemplo n.º 10
0
extern "C" jboolean JNICALL Java_org_ppsspp_ppsspp_NativeApp_touch
	(JNIEnv *, jclass, float x, float y, int code, int pointerId) {

	float scaledX = x * dp_xscale;
	float scaledY = y * dp_yscale;

	TouchInput touch;
	touch.id = pointerId;
	touch.x = scaledX;
	touch.y = scaledY;
	touch.flags = code;

	bool retval = NativeTouch(touch);
	return retval;
}
Ejemplo n.º 11
0
bool MainUI::event(QEvent *e)
{
    TouchInput input;
    QList<QTouchEvent::TouchPoint> touchPoints;
    switch(e->type())
    {
    case QEvent::TouchBegin:
    case QEvent::TouchUpdate:
    case QEvent::TouchEnd:
        touchPoints = static_cast<QTouchEvent *>(e)->touchPoints();
        foreach (const QTouchEvent::TouchPoint &touchPoint, touchPoints) {
            switch (touchPoint.state()) {
            case Qt::TouchPointStationary:
                break;
            case Qt::TouchPointPressed:
            case Qt::TouchPointReleased:
                input_state.pointer_down[touchPoint.id()] = (touchPoint.state() == Qt::TouchPointPressed);
                input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * g_dpi_scale * xscale;
                input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * g_dpi_scale * yscale;

                input.x = touchPoint.pos().x() * g_dpi_scale * xscale;
                input.y = touchPoint.pos().y() * g_dpi_scale * yscale;
                input.flags = (touchPoint.state() == Qt::TouchPointPressed) ? TOUCH_DOWN : TOUCH_UP;
                input.id = touchPoint.id();
                NativeTouch(input);
                break;
            case Qt::TouchPointMoved:
                input_state.pointer_x[touchPoint.id()] = touchPoint.pos().x() * g_dpi_scale * xscale;
                input_state.pointer_y[touchPoint.id()] = touchPoint.pos().y() * g_dpi_scale * yscale;

                input.x = touchPoint.pos().x() * g_dpi_scale * xscale;
                input.y = touchPoint.pos().y() * g_dpi_scale * yscale;
                input.flags = TOUCH_MOVE;
                input.id = touchPoint.id();
                NativeTouch(input);
                break;
            default:
                break;
            }
        }
        break;
    case QEvent::MouseButtonDblClick:
        if (!g_Config.bShowTouchControls || GetUIState() != UISTATE_INGAME)
            emit doubleClick();
        break;
    case QEvent::MouseButtonPress:
    case QEvent::MouseButtonRelease:
        input_state.pointer_down[0] = (e->type() == QEvent::MouseButtonPress);
        input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * g_dpi_scale * xscale;
        input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * g_dpi_scale * yscale;

        input.x = ((QMouseEvent*)e)->pos().x() * g_dpi_scale * xscale;
        input.y = ((QMouseEvent*)e)->pos().y() * g_dpi_scale * yscale;
        input.flags = (e->type() == QEvent::MouseButtonPress) ? TOUCH_DOWN : TOUCH_UP;
        input.id = 0;
        NativeTouch(input);
        break;
    case QEvent::MouseMove:
        input_state.pointer_x[0] = ((QMouseEvent*)e)->pos().x() * g_dpi_scale * xscale;
        input_state.pointer_y[0] = ((QMouseEvent*)e)->pos().y() * g_dpi_scale * yscale;

        input.x = ((QMouseEvent*)e)->pos().x() * g_dpi_scale * xscale;
        input.y = ((QMouseEvent*)e)->pos().y() * g_dpi_scale * yscale;
        input.flags = TOUCH_MOVE;
        input.id = 0;
        NativeTouch(input);
        break;
    case QEvent::Wheel:
        NativeKey(KeyInput(DEVICE_ID_MOUSE, ((QWheelEvent*)e)->delta()<0 ? NKCODE_EXT_MOUSEWHEEL_DOWN : NKCODE_EXT_MOUSEWHEEL_UP, KEY_DOWN));
        break;
    case QEvent::KeyPress:
        NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(((QKeyEvent*)e)->key())->second, KEY_DOWN));
        break;
    case QEvent::KeyRelease:
        NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawQttoNative.find(((QKeyEvent*)e)->key())->second, KEY_UP));
        break;
    default:
        return QWidget::event(e);
    }
    e->accept();
    return true;
}
Ejemplo n.º 12
0
	LRESULT CALLBACK DisplayProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
	{
		switch (message) 
		{
		case WM_ACTIVATE:
			break;
		case WM_SETFOCUS:
			break;
		case WM_SIZE:
			break;

		case WM_ERASEBKGND:
	  	return DefWindowProc(hWnd, message, wParam, lParam);

		// Poor man's touch - mouse input. We send the data both as an input_state pointer,
		// and as asynchronous touch events for minimal latency.

		case WM_LBUTTONDOWN:
			{
				// Hack: Take the opportunity to show the cursor.
				mouseButtonDown = true;
				{
					lock_guard guard(input_state.lock);
					input_state.mouse_valid = true;
					input_state.pointer_down[0] = true;

					int factor = g_Config.iWindowZoom == 1 ? 2 : 1;
					input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; 
					input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor;
				}

				TouchInput touch;
				touch.id = 0;
				touch.flags = TOUCH_DOWN;
				touch.x = input_state.pointer_x[0];
				touch.y = input_state.pointer_y[0];
				NativeTouch(touch);
				SetCapture(hWnd);
				break;
			}

		case WM_MOUSEMOVE:
			{
				// Hack: Take the opportunity to show the cursor.
				mouseButtonDown = (wParam & MK_LBUTTON) != 0;
				int cursorX = GET_X_LPARAM(lParam);
				int cursorY = GET_Y_LPARAM(lParam);
				if (abs(cursorX - prevCursorX) > 1 || abs(cursorY - prevCursorY) > 1) {
					hideCursor = false;
					SetTimer(hwndMain, TIMER_CURSORMOVEUPDATE, CURSORUPDATE_MOVE_TIMESPAN_MS, 0);
				}
				prevCursorX = cursorX;
				prevCursorY = cursorY;

				{
					lock_guard guard(input_state.lock);
					int factor = g_Config.iWindowZoom == 1 ? 2 : 1;
					input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; 
					input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor;
				}

				if (wParam & MK_LBUTTON) {
					TouchInput touch;
					touch.id = 0;
					touch.flags = TOUCH_MOVE;
					touch.x = input_state.pointer_x[0];
					touch.y = input_state.pointer_y[0];
					NativeTouch(touch);
				}
			}
			break;

		case WM_LBUTTONUP:
			{
				// Hack: Take the opportunity to hide the cursor.
				mouseButtonDown = false;
				{
					lock_guard guard(input_state.lock);
					input_state.pointer_down[0] = false;
					int factor = g_Config.iWindowZoom == 1 ? 2 : 1;
					input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; 
					input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor;
				}
				TouchInput touch;
				touch.id = 0;
				touch.flags = TOUCH_UP;
				touch.x = input_state.pointer_x[0];
				touch.y = input_state.pointer_y[0];
				NativeTouch(touch);
				ReleaseCapture();
				break;
			}

		// Actual touch! Unfinished

		case WM_TOUCH:
			{
				// TODO: Enabling this section will probably break things on Windows XP.
				// We probably need to manually fetch pointers to GetTouchInputInfo and CloseTouchInputHandle.
#if ENABLE_TOUCH
				UINT inputCount = LOWORD(wParam);
				TOUCHINPUT *inputs = new TOUCHINPUT[inputCount];
				if (GetTouchInputInfo((HTOUCHINPUT)lParam,
					inputCount,
					inputs,
					sizeof(TOUCHINPUT)))
				{
					for (int i = 0; i < inputCount; i++) {
						// TODO: process inputs here!

					}

					if (!CloseTouchInputHandle((HTOUCHINPUT)lParam))
					{
						// error handling
					}
				}
				else
				{
					// GetLastError() and error handling
				}
				delete [] inputs;
				return DefWindowProc(hWnd, message, wParam, lParam);
#endif
			}


		case WM_PAINT:
			return DefWindowProc(hWnd, message, wParam, lParam);
		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		return 0;
	}
Ejemplo n.º 13
0
int main(int argc, char *argv[]) {
	std::string app_name;
	std::string app_name_nice;
	bool landscape;
	NativeGetAppInfo(&app_name, &app_name_nice, &landscape);

	net::Init();
#ifdef __APPLE__
	// Make sure to request a somewhat modern GL context at least - the
	// latest supported by MacOSX (really, really sad...)
	// Requires SDL 2.0
	// We really should upgrade to SDL 2.0 soon.
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
#endif

	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) {
		fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
		return 1;
	}
#ifdef EGL
	if (EGL_Open())
		return 1;
#endif

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);

	int mode;
#ifdef USING_GLES2
	mode = SDL_SWSURFACE | SDL_FULLSCREEN;
#else
	mode = SDL_OPENGL;
	for (int i = 1; i < argc; i++)
		if (!strcmp(argv[i],"--fullscreen"))
			mode |= SDL_FULLSCREEN;
#endif
	if (mode & SDL_FULLSCREEN) {
		const SDL_VideoInfo* info = SDL_GetVideoInfo();
		pixel_xres = info->current_w;
		pixel_yres = info->current_h;
		g_Config.bFullScreen = true;
	} else {
		// set a sensible default resolution (2x)
		pixel_xres = 480 * 2;
		pixel_yres = 272 * 2;
		g_Config.bFullScreen = false;
	}
	dp_xres = (float)pixel_xres;
	dp_yres = (float)pixel_yres;

	if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode) == NULL) {
		fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError());
		SDL_Quit();
		return(2);
	}
#ifdef EGL
	EGL_Init();
#endif

	SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL);
#ifdef MAEMO
	SDL_ShowCursor(SDL_DISABLE);
#endif


#ifndef USING_GLES2
	if (GLEW_OK != glewInit()) {
		printf("Failed to initialize glew!\n");
		return 1;
	}

	if (GLEW_VERSION_2_0) {
		printf("OpenGL 2.0 or higher.\n");
	} else {
		printf("Sorry, this program requires OpenGL 2.0.\n");
		return 1;
	}
#endif

#ifdef _MSC_VER
	// VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\"));
	TCHAR path[MAX_PATH];
	SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path);
	PathAppend(path, (app_name + "\\").c_str());
#else
	// Mac / Linux
	char path[512];
	const char *the_path = getenv("HOME");
	if (!the_path) {
		struct passwd* pwd = getpwuid(getuid());
		if (pwd)
			the_path = pwd->pw_dir;
	}
	strcpy(path, the_path);
	if (path[strlen(path)-1] != '/')
		strcat(path, "/");
#endif

#ifdef _WIN32
	NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE");
#else
	NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE");
#endif

	pixel_in_dps = (float)pixel_xres / dp_xres;

	float dp_xscale = (float)dp_xres / pixel_xres;
	float dp_yscale = (float)dp_yres / pixel_yres;

	g_dpi_scale = dp_xres / (float)pixel_xres;

	printf("Pixels: %i x %i\n", pixel_xres, pixel_yres);
	printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres);
	NativeInitGraphics();

	SDL_AudioSpec fmt;
	fmt.freq = 44100;
	fmt.format = AUDIO_S16;
	fmt.channels = 2;
	fmt.samples = 2048;
	fmt.callback = &mixaudio;
	fmt.userdata = (void *)0;

	if (SDL_OpenAudio(&fmt, NULL) < 0)
		ELOG("Failed to open audio: %s", SDL_GetError());

	// Audio must be unpaused _after_ NativeInit()
	SDL_PauseAudio(0);
#ifdef PANDORA
	int numjoys = SDL_NumJoysticks();
	// Joysticks init, we the nubs if setup as Joystick
	if (numjoys > 0) {
		ljoy = SDL_JoystickOpen(0);
		if (numjoys > 1)
			rjoy = SDL_JoystickOpen(1);
	}
#else
	joystick = new SDLJoystick();
#endif
	EnableFZ();

	int framecount = 0;
	float t = 0;
	float lastT = 0;
	while (true) {
		input_state.accelerometer_valid = false;
		input_state.mouse_valid = true;
		int quitRequested = 0;

		SDL_Event event;
		while (SDL_PollEvent(&event)) {
			float mx = event.motion.x * dp_xscale;
			float my = event.motion.y * dp_yscale;

			switch (event.type) {
			case SDL_QUIT:
				quitRequested = 1;
				break;
			case SDL_KEYDOWN:
				{
					int k = event.key.keysym.sym;
					KeyInput key;
					key.flags = KEY_DOWN;
					key.keyCode = KeyMapRawSDLtoNative.find(k)->second;
					key.deviceId = DEVICE_ID_KEYBOARD;
					NativeKey(key);
					break;
				}
			case SDL_KEYUP:
				{
					int k = event.key.keysym.sym;
					KeyInput key;
					key.flags = KEY_UP;
					key.keyCode = KeyMapRawSDLtoNative.find(k)->second;
					key.deviceId = DEVICE_ID_KEYBOARD;
					NativeKey(key);
					break;
				}
			case SDL_MOUSEBUTTONDOWN:
				switch (event.button.button) {
				case SDL_BUTTON_LEFT:
					{
						input_state.pointer_x[0] = mx;
						input_state.pointer_y[0] = my;
						//input_state.mouse_buttons_down = 1;
						input_state.pointer_down[0] = true;
						input_state.mouse_valid = true;
						TouchInput input;
						input.x = mx;
						input.y = my;
						input.flags = TOUCH_DOWN;
						input.id = 0;
						NativeTouch(input);
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN);
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_RIGHT:
					{
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN);
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_WHEELUP:
					{
						KeyInput key;
						key.deviceId = DEVICE_ID_MOUSE;
						key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP;
						key.flags = KEY_DOWN;
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_WHEELDOWN:
					{
						KeyInput key;
						key.deviceId = DEVICE_ID_MOUSE;
						key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN;
						key.flags = KEY_DOWN;
						NativeKey(key);
					}
					break;
				}
				break;
			case SDL_MOUSEMOTION:
				if (input_state.pointer_down[0]) {
					input_state.pointer_x[0] = mx;
					input_state.pointer_y[0] = my;
					input_state.mouse_valid = true;
					TouchInput input;
					input.x = mx;
					input.y = my;
					input.flags = TOUCH_MOVE;
					input.id = 0;
					NativeTouch(input);
				}
				break;
			case SDL_MOUSEBUTTONUP:
				switch (event.button.button) {
				case SDL_BUTTON_LEFT:
					{
						input_state.pointer_x[0] = mx;
						input_state.pointer_y[0] = my;
						input_state.pointer_down[0] = false;
						input_state.mouse_valid = true;
						//input_state.mouse_buttons_up = 1;
						TouchInput input;
						input.x = mx;
						input.y = my;
						input.flags = TOUCH_UP;
						input.id = 0;
						NativeTouch(input);
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP);
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_RIGHT:
					{
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP);
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_WHEELUP:
					{
						KeyInput key;
						key.deviceId = DEVICE_ID_DEFAULT;
						key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP;
						key.flags = KEY_UP;
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_WHEELDOWN:
					{
						KeyInput key;
						key.deviceId = DEVICE_ID_DEFAULT;
						key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN;
						key.flags = KEY_UP;
						NativeKey(key);
					}
					break;
				}
				break;
			default:
				joystick->ProcessInput(event);
				break;
			}
		}

		if (quitRequested)
			break;

		const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL);
		SimulateGamepad(keys, &input_state);
		UpdateInputState(&input_state);
		NativeUpdate(input_state);
		NativeRender();
#ifndef MAEMO
		if (lastUIState != globalUIState) {
			lastUIState = globalUIState;
			if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls)
				SDL_ShowCursor(SDL_DISABLE);
			if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen)
				SDL_ShowCursor(SDL_ENABLE);
		}
#endif

		EndInputState(&input_state);

		if (framecount % 60 == 0) {
			// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
		}

#ifdef EGL
		eglSwapBuffers(g_eglDisplay, g_eglSurface);
#else
		if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0)
		{
			SDL_GL_SwapBuffers();
			lastT = t;
		}
#endif
		time_update();
		t = time_now();
		framecount++;
	}
#ifndef PANDORA
	delete joystick;
	joystick = NULL;
#endif
	// Faster exit, thanks to the OS. Remove this if you want to debug shutdown
	// The speed difference is only really noticable on Linux. On Windows you do notice it though
#ifdef _WIN32
	exit(0);
#endif
	NativeShutdownGraphics();
	SDL_PauseAudio(1);
	SDL_CloseAudio();
	NativeShutdown();
#ifdef EGL
	EGL_Close();
#endif
	SDL_Quit();
	net::Shutdown();
	exit(0);
	return 0;
}
Ejemplo n.º 14
0
void BlackberryMain::handleInput(screen_event_t screen_event)
{
	TouchInput input;
	KeyInput key;
	int val, buttons, pointerId;
	int pair[2];
	screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &val);
	screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair);

	input_state.mouse_valid = true;
	switch(val)
	{
	// Touchscreen
	case SCREEN_EVENT_MTOUCH_TOUCH:
	case SCREEN_EVENT_MTOUCH_RELEASE: 	// Up, down
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId);
		input_state.pointer_down[pointerId] = (val == SCREEN_EVENT_MTOUCH_TOUCH);
		input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
		input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;

		input.x = pair[0] * g_dpi_scale;
		input.y = pair[1] * g_dpi_scale;
		input.flags = (val == SCREEN_EVENT_MTOUCH_TOUCH) ? TOUCH_DOWN : TOUCH_UP;
		input.id = pointerId;
		NativeTouch(input);
		break;
	case SCREEN_EVENT_MTOUCH_MOVE:
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId);
		input_state.pointer_x[pointerId] = pair[0] * g_dpi_scale;
		input_state.pointer_y[pointerId] = pair[1] * g_dpi_scale;

		input.x = pair[0] * g_dpi_scale;
		input.y = pair[1] * g_dpi_scale;
		input.flags = TOUCH_MOVE;
		input.id = pointerId;
		NativeTouch(input);
		break;
	// Mouse, Simulator
	case SCREEN_EVENT_POINTER:
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons);
		if (buttons == SCREEN_LEFT_MOUSE_BUTTON) { // Down
			input_state.pointer_x[0] = pair[0] * g_dpi_scale;
			input_state.pointer_y[0] = pair[1] * g_dpi_scale;
			input_state.pointer_down[0] = true;

			input.x = pair[0] * g_dpi_scale;
			input.y = pair[1] * g_dpi_scale;
			input.flags = TOUCH_DOWN;
			input.id = 0;
			NativeTouch(input);
		} else if (input_state.pointer_down[0]) {	// Up
			input_state.pointer_x[0] = pair[0] * g_dpi_scale;
			input_state.pointer_y[0] = pair[1] * g_dpi_scale;
			input_state.pointer_down[0] = false;

			input.x = pair[0] * g_dpi_scale;
			input.y = pair[1] * g_dpi_scale;
			input.flags = TOUCH_UP;
			input.id = 0;
			NativeTouch(input);
		}
		break;
	// Keyboard
	case SCREEN_EVENT_KEYBOARD:
		int flags, value;
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_FLAGS, &flags);
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_KEY_SYM, &value);
		NativeKey(KeyInput(DEVICE_ID_KEYBOARD, KeyMapRawBlackberrytoNative.find(value)->second, (flags & KEY_DOWN) ? KEY_DOWN : KEY_UP));
		break;
	// Gamepad
	case SCREEN_EVENT_GAMEPAD:
	case SCREEN_EVENT_JOYSTICK:
		int analog0[3];
		screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &buttons);
		for (int i = 0; i < 32; i++) {
			int mask = 1 << i;
			if ((old_buttons & mask) != (buttons & mask))
				NativeKey(KeyInput(DEVICE_ID_PAD_0, KeyMapPadBlackberrytoNative.find(mask)->second, (buttons & mask) ? KEY_DOWN : KEY_UP));
		}
		if (!screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ANALOG0, analog0)) {
			for (int i = 0; i < 2; i++) {
				AxisInput axis;
				axis.axisId = JOYSTICK_AXIS_X + i;
				// 1.2 to try to approximate the PSP's clamped rectangular range.
				axis.value = 1.2 * analog0[i] / 128.0f;
				if (axis.value > 1.0f) axis.value = 1.0f;
				if (axis.value < -1.0f) axis.value = -1.0f;
				axis.deviceId = DEVICE_ID_PAD_0;
				axis.flags = 0;
				NativeAxis(axis);
			}
		}
		old_buttons = buttons;
		break;
	case SCREEN_EVENT_DISPLAY:
		screen_display_t new_dpy = NULL;
		screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DISPLAY, (void **)&new_dpy);
		for (int i = 0; i < ndisplays; i++) {
			if (new_dpy != screen_dpy[i])
				continue;
			int active = 0;
			screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ATTACHED, &active);
			if (active) {
				int size[2];
				screen_get_display_property_iv(screen_dpy[i], SCREEN_PROPERTY_SIZE, size);
				if (size[0] == 0 || size[1] == 0)
					active = 0;
			}
			if (active && !displays[i].attached)
				realiseDisplay(i);
			else if (!active && displays[i].attached && displays[i].realised)
				unrealiseDisplay(i);
			displays[i].attached = active;
		}
		break;
	}
}
Ejemplo n.º 15
0
int main(int argc, char *argv[]) {
	glslang::InitializeProcess();

#if PPSSPP_PLATFORM(RPI)
	bcm_host_init();
#endif
	putenv((char*)"SDL_VIDEO_CENTERED=1");
	SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");

	if (VulkanMayBeAvailable()) {
		printf("Vulkan might be available.\n");
	} else {
		printf("Vulkan is not available.\n");
	}

	int set_xres = -1;
	int set_yres = -1;
	bool portrait = false;
	bool set_ipad = false;
	float set_dpi = 1.0f;
	float set_scale = 1.0f;

	// Produce a new set of arguments with the ones we skip.
	int remain_argc = 1;
	const char *remain_argv[256] = { argv[0] };

	Uint32 mode = 0;
	for (int i = 1; i < argc; i++) {
		if (!strcmp(argv[i],"--fullscreen"))
			mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
		else if (set_xres == -2)
			set_xres = parseInt(argv[i]);
		else if (set_yres == -2)
			set_yres = parseInt(argv[i]);
		else if (set_dpi == -2)
			set_dpi = parseFloat(argv[i]);
		else if (set_scale == -2)
			set_scale = parseFloat(argv[i]);
		else if (!strcmp(argv[i],"--xres"))
			set_xres = -2;
		else if (!strcmp(argv[i],"--yres"))
			set_yres = -2;
		else if (!strcmp(argv[i],"--dpi"))
			set_dpi = -2;
		else if (!strcmp(argv[i],"--scale"))
			set_scale = -2;
		else if (!strcmp(argv[i],"--ipad"))
			set_ipad = true;
		else if (!strcmp(argv[i],"--portrait"))
			portrait = true;
		else {
			remain_argv[remain_argc++] = argv[i];
		}
	}

	std::string app_name;
	std::string app_name_nice;
	std::string version;
	bool landscape;
	NativeGetAppInfo(&app_name, &app_name_nice, &landscape, &version);

	bool joystick_enabled = true;
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0) {
		fprintf(stderr, "Failed to initialize SDL with joystick support. Retrying without.\n");
		joystick_enabled = false;
		if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
			fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
			return 1;
		}
	}

	// TODO: How do we get this into the GraphicsContext?
#ifdef USING_EGL
	if (EGL_Open())
		return 1;
#endif

	// Get the video info before doing anything else, so we don't get skewed resolution results.
	// TODO: support multiple displays correctly
	SDL_DisplayMode displayMode;
	int should_be_zero = SDL_GetCurrentDisplayMode(0, &displayMode);
	if (should_be_zero != 0) {
		fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError());
		return 1;
	}
	g_DesktopWidth = displayMode.w;
	g_DesktopHeight = displayMode.h;

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetSwapInterval(1);

	// Is resolution is too low to run windowed
	if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) {
		mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
	}

	if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) {
		pixel_xres = g_DesktopWidth;
		pixel_yres = g_DesktopHeight;
		g_Config.bFullScreen = true;
	} else {
		// set a sensible default resolution (2x)
		pixel_xres = 480 * 2 * set_scale;
		pixel_yres = 272 * 2 * set_scale;
		if (portrait) {
			std::swap(pixel_xres, pixel_yres);
		}
		g_Config.bFullScreen = false;
	}

	set_dpi = 1.0f / set_dpi;

	if (set_ipad) {
		pixel_xres = 1024;
		pixel_yres = 768;
	}
	if (!landscape) {
		std::swap(pixel_xres, pixel_yres);
	}

	if (set_xres > 0) {
		pixel_xres = set_xres;
	}
	if (set_yres > 0) {
		pixel_yres = set_yres;
	}
	float dpi_scale = 1.0f;
	if (set_dpi > 0) {
		dpi_scale = set_dpi;
	}

	dp_xres = (float)pixel_xres * dpi_scale;
	dp_yres = (float)pixel_yres * dpi_scale;

	// Mac / Linux
	char path[2048];
	const char *the_path = getenv("HOME");
	if (!the_path) {
		struct passwd* pwd = getpwuid(getuid());
		if (pwd)
			the_path = pwd->pw_dir;
	}
	strcpy(path, the_path);
	if (path[strlen(path)-1] != '/')
		strcat(path, "/");

	NativeInit(remain_argc, (const char **)remain_argv, path, "/tmp", nullptr);

	// Use the setting from the config when initing the window.
	if (g_Config.bFullScreen)
		mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;

	int x = SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber());
	int y = SDL_WINDOWPOS_UNDEFINED;

	pixel_in_dps_x = (float)pixel_xres / dp_xres;
	pixel_in_dps_y = (float)pixel_yres / dp_yres;
	g_dpi_scale_x = dp_xres / (float)pixel_xres;
	g_dpi_scale_y = dp_yres / (float)pixel_yres;
	g_dpi_scale_real_x = g_dpi_scale_x;
	g_dpi_scale_real_y = g_dpi_scale_y;

	printf("Pixels: %i x %i\n", pixel_xres, pixel_yres);
	printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres);

	GraphicsContext *graphicsContext = nullptr;
	SDL_Window *window = nullptr;

	std::string error_message;
	if (g_Config.iGPUBackend == (int)GPUBackend::OPENGL) {
		SDLGLGraphicsContext *ctx = new SDLGLGraphicsContext();
		if (ctx->Init(window, x, y, mode, &error_message) != 0) {
			printf("GL init error '%s'\n", error_message.c_str());
		}
		graphicsContext = ctx;
	} else if (g_Config.iGPUBackend == (int)GPUBackend::VULKAN) {
		SDLVulkanGraphicsContext *ctx = new SDLVulkanGraphicsContext();
		if (!ctx->Init(window, x, y, mode, &error_message)) {
			printf("Vulkan init error '%s' - falling back to GL\n", error_message.c_str());
			g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
			SetGPUBackend((GPUBackend)g_Config.iGPUBackend);
			delete ctx;
			SDLGLGraphicsContext *glctx = new SDLGLGraphicsContext();
			glctx->Init(window, x, y, mode, &error_message);
			graphicsContext = glctx;
		} else {
			graphicsContext = ctx;
		}
	}

	bool useEmuThread = g_Config.iGPUBackend == (int)GPUBackend::OPENGL;

	SDL_SetWindowTitle(window, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str());

	// Since we render from the main thread, there's nothing done here, but we call it to avoid confusion.
	if (!graphicsContext->InitFromRenderThread(&error_message)) {
		printf("Init from thread error: '%s'\n", error_message.c_str());
	}

#ifdef MOBILE_DEVICE
	SDL_ShowCursor(SDL_DISABLE);
#endif

	if (!useEmuThread) {
		NativeInitGraphics(graphicsContext);
		NativeResized();
	}

	SDL_AudioSpec fmt, ret_fmt;
	memset(&fmt, 0, sizeof(fmt));
	fmt.freq = 44100;
	fmt.format = AUDIO_S16;
	fmt.channels = 2;
	fmt.samples = 2048;
	fmt.callback = &mixaudio;
	fmt.userdata = (void *)0;

	if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) {
		ELOG("Failed to open audio: %s", SDL_GetError());
	} else {
		if (ret_fmt.samples != fmt.samples) // Notify, but still use it
			ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples);
		if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) {
			ELOG("Sound buffer format does not match requested format.");
			ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq);
			ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format);
			ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels);
			ELOG("Provided output format does not match requirement, turning audio off");
			SDL_CloseAudio();
		}
	}

	// Audio must be unpaused _after_ NativeInit()
	SDL_PauseAudio(0);
	if (joystick_enabled) {
		joystick = new SDLJoystick();
	} else {
		joystick = nullptr;
	}
	EnableFZ();

	int framecount = 0;
	bool mouseDown = false;

	if (useEmuThread) {
		EmuThreadStart(graphicsContext);
	}
	graphicsContext->ThreadStart();

	while (true) {
		SDL_Event event;
		while (SDL_PollEvent(&event)) {
			float mx = event.motion.x * g_dpi_scale_x;
			float my = event.motion.y * g_dpi_scale_y;

			switch (event.type) {
			case SDL_QUIT:
				g_QuitRequested = 1;
				break;

#if !defined(MOBILE_DEVICE)
			case SDL_WINDOWEVENT:
				switch (event.window.event) {
				case SDL_WINDOWEVENT_RESIZED:
				{
					Uint32 window_flags = SDL_GetWindowFlags(window);
					bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN);

					pixel_xres = event.window.data1;
					pixel_yres = event.window.data2;
					dp_xres = (float)pixel_xres * dpi_scale;
					dp_yres = (float)pixel_yres * dpi_scale;
					NativeResized();

					// Set variable here in case fullscreen was toggled by hotkey
					g_Config.bFullScreen = fullscreen;

					// Hide/Show cursor correctly toggling fullscreen
					if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) {
						SDL_ShowCursor(SDL_DISABLE);
					} else if (lastUIState != UISTATE_INGAME || !fullscreen) {
						SDL_ShowCursor(SDL_ENABLE);
					}
					break;
				}

				default:
					break;
				}
				break;
#endif
			case SDL_KEYDOWN:
				{
					if (event.key.repeat > 0) { break;}
					int k = event.key.keysym.sym;
					KeyInput key;
					key.flags = KEY_DOWN;
					auto mapped = KeyMapRawSDLtoNative.find(k);
					if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) {
						break;
					}
					key.keyCode = mapped->second;
					key.deviceId = DEVICE_ID_KEYBOARD;
					NativeKey(key);
					break;
				}
			case SDL_KEYUP:
				{
					if (event.key.repeat > 0) { break;}
					int k = event.key.keysym.sym;
					KeyInput key;
					key.flags = KEY_UP;
					auto mapped = KeyMapRawSDLtoNative.find(k);
					if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) {
						break;
					}
					key.keyCode = mapped->second;
					key.deviceId = DEVICE_ID_KEYBOARD;
					NativeKey(key);
					break;
				}
			case SDL_TEXTINPUT:
				{
					int pos = 0;
					int c = u8_nextchar(event.text.text, &pos);
					KeyInput key;
					key.flags = KEY_CHAR;
					key.keyCode = c;
					key.deviceId = DEVICE_ID_KEYBOARD;
					NativeKey(key);
					break;
				}
			case SDL_MOUSEBUTTONDOWN:
				switch (event.button.button) {
				case SDL_BUTTON_LEFT:
					{
						mouseDown = true;
						TouchInput input;
						input.x = mx;
						input.y = my;
						input.flags = TOUCH_DOWN | TOUCH_MOUSE;
						input.id = 0;
						NativeTouch(input);
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN);
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_RIGHT:
					{
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN);
						NativeKey(key);
					}
					break;
				}
				break;
			case SDL_MOUSEWHEEL:
				{
					KeyInput key;
					key.deviceId = DEVICE_ID_MOUSE;
					if (event.wheel.y > 0) {
						key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP;
					} else {
						key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN;
					}
					key.flags = KEY_DOWN;
					NativeKey(key);

					// SDL2 doesn't consider the mousewheel a button anymore
					// so let's send the KEY_UP right away.
					// Maybe KEY_UP alone will suffice?
					key.flags = KEY_UP;
					NativeKey(key);
				}
			case SDL_MOUSEMOTION:
				if (mouseDown) {
					TouchInput input;
					input.x = mx;
					input.y = my;
					input.flags = TOUCH_MOVE | TOUCH_MOUSE;
					input.id = 0;
					NativeTouch(input);
				}
				break;
			case SDL_MOUSEBUTTONUP:
				switch (event.button.button) {
				case SDL_BUTTON_LEFT:
					{
						mouseDown = false;
						TouchInput input;
						input.x = mx;
						input.y = my;
						input.flags = TOUCH_UP | TOUCH_MOUSE;
						input.id = 0;
						NativeTouch(input);
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP);
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_RIGHT:
					{
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP);
						NativeKey(key);
					}
					break;
				}
				break;
			default:
				if (joystick) {
					joystick->ProcessInput(event);
				}
				break;
			}
		}
		if (g_QuitRequested)
			break;
		const uint8_t *keys = SDL_GetKeyboardState(NULL);
		if (emuThreadState == (int)EmuThreadState::DISABLED) {
			UpdateRunLoop();
		}
		if (g_QuitRequested)
			break;
#if !defined(MOBILE_DEVICE)
		if (lastUIState != GetUIState()) {
			lastUIState = GetUIState();
			if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls)
				SDL_ShowCursor(SDL_DISABLE);
			if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen)
				SDL_ShowCursor(SDL_ENABLE);
		}
#endif

		if (framecount % 60 == 0) {
			// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
		}

		if (emuThreadState != (int)EmuThreadState::DISABLED) {
			if (!graphicsContext->ThreadFrame())
				break;
		}
		graphicsContext->SwapBuffers();

		ToggleFullScreenIfFlagSet(window);
		time_update();
		framecount++;
	}

	if (useEmuThread) {
		EmuThreadStop();
		while (emuThreadState != (int)EmuThreadState::STOPPED) {
			// Need to keep eating frames to allow the EmuThread to exit correctly.
			graphicsContext->ThreadFrame();
		}
		EmuThreadJoin();
	}

	delete joystick;

	if (!useEmuThread) {
		NativeShutdownGraphics();
	}
	graphicsContext->Shutdown();
	graphicsContext->ThreadEnd();
	graphicsContext->ShutdownFromRenderThread();

	NativeShutdown();
	delete graphicsContext;

	SDL_PauseAudio(1);
	SDL_CloseAudio();
	SDL_Quit();
#if PPSSPP_PLATFORM(RPI)
	bcm_host_deinit();
#endif

	glslang::FinalizeProcess();
	ILOG("Leaving main");
	return 0;
}
Ejemplo n.º 16
0
	LRESULT CALLBACK DisplayProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
		static bool firstErase = true;

		switch (message) {
		case WM_ACTIVATE:
			if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
				g_activeWindow = WINDOW_MAINWINDOW;
			}
			break;

		case WM_SIZE:
			break;

		case WM_SETFOCUS:
			break;

		case WM_ERASEBKGND:
			if (firstErase) {
				firstErase = false;
				// Paint black on first erase while OpenGL stuff is loading
				return DefWindowProc(hWnd, message, wParam, lParam);
			}
			// Then never erase, let the OpenGL drawing take care of everything.
			return 1;

		// Poor man's touch - mouse input. We send the data  asynchronous touch events for minimal latency.
		case WM_LBUTTONDOWN:
			if (!touchHandler.hasTouch() ||
				(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
			{
				// Hack: Take the opportunity to show the cursor.
				mouseButtonDown = true;

				float x = GET_X_LPARAM(lParam) * g_dpi_scale_x;
				float y = GET_Y_LPARAM(lParam) * g_dpi_scale_y;
				WindowsRawInput::SetMousePos(x, y);

				TouchInput touch;
				touch.id = 0;
				touch.flags = TOUCH_DOWN;
				touch.x = x;
				touch.y = y;
				NativeTouch(touch);
				SetCapture(hWnd);

				// Simulate doubleclick, doesn't work with RawInput enabled
				static double lastMouseDown;
				double now = real_time_now();
				if ((now - lastMouseDown) < 0.001 * GetDoubleClickTime()) {
					if (!g_Config.bShowTouchControls && !g_Config.bMouseControl && GetUIState() == UISTATE_INGAME && g_Config.bFullscreenOnDoubleclick) {
						SendToggleFullscreen(!g_Config.bFullScreen);
					}
					lastMouseDown = 0.0;
				} else {
					lastMouseDown = real_time_now();
				}
			}
			break;

		case WM_MOUSEMOVE:
			if (!touchHandler.hasTouch() ||
				(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
			{
				// Hack: Take the opportunity to show the cursor.
				mouseButtonDown = (wParam & MK_LBUTTON) != 0;
				int cursorX = GET_X_LPARAM(lParam);
				int cursorY = GET_Y_LPARAM(lParam);
				if (abs(cursorX - prevCursorX) > 1 || abs(cursorY - prevCursorY) > 1) {
					hideCursor = false;
					SetTimer(hwndMain, TIMER_CURSORMOVEUPDATE, CURSORUPDATE_MOVE_TIMESPAN_MS, 0);
				}
				prevCursorX = cursorX;
				prevCursorY = cursorY;

				float x = (float)cursorX * g_dpi_scale_x;
				float y = (float)cursorY * g_dpi_scale_y;
				WindowsRawInput::SetMousePos(x, y);

				if (wParam & MK_LBUTTON) {
					TouchInput touch;
					touch.id = 0;
					touch.flags = TOUCH_MOVE;
					touch.x = x;
					touch.y = y;
					NativeTouch(touch);
				}
			}
			break;

		case WM_LBUTTONUP:
			if (!touchHandler.hasTouch() ||
				(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
			{
				// Hack: Take the opportunity to hide the cursor.
				mouseButtonDown = false;

				float x = (float)GET_X_LPARAM(lParam) * g_dpi_scale_x;
				float y = (float)GET_Y_LPARAM(lParam) * g_dpi_scale_y;
				WindowsRawInput::SetMousePos(x, y);

				TouchInput touch;
				touch.id = 0;
				touch.flags = TOUCH_UP;
				touch.x = x;
				touch.y = y;
				NativeTouch(touch);
				ReleaseCapture();
			}
			break;

		case WM_TOUCH:
			{
				touchHandler.handleTouchEvent(hWnd, message, wParam, lParam);
				return 0;
			}

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		return 0;
	}
Ejemplo n.º 17
0
int main(int argc, char *argv[]) {
	std::string app_name;
	std::string app_name_nice;

	float zoom = 1.0f;
	bool tablet = false;
	bool aspect43 = false;
	const char *zoomenv = getenv("ZOOM");
	const char *tabletenv = getenv("TABLET");
	const char *ipad = getenv("IPAD");

	if (zoomenv) {
		zoom = atof(zoomenv);
	}
	if (tabletenv) {
		tablet = atoi(tabletenv) ? true : false;
	}
	if (ipad) aspect43 = true;
	
	bool landscape;
	NativeGetAppInfo(&app_name, &app_name_nice, &landscape);
	
	// Change these to temporarily test other resolutions.
	aspect43 = false;
	tablet = false;
	float density = 1.0f;
	//zoom = 1.5f;

	if (landscape) {
		if (tablet) {
			pixel_xres = 1280 * zoom;
			pixel_yres = 800 * zoom;
		} else if (aspect43) {
			pixel_xres = 1024 * zoom;
			pixel_yres = 768 * zoom;
		} else {
			pixel_xres = 800 * zoom;
			pixel_yres = 480 * zoom;
		}
	} else {
		// PC development hack for more space
		//pixel_xres = 1580 * zoom;
		//pixel_yres = 1000 * zoom;
		if (tablet) {
			pixel_xres = 800 * zoom;
			pixel_yres = 1280 * zoom;
		} else if (aspect43) {
			pixel_xres = 768 * zoom;
			pixel_yres = 1024 * zoom;
		} else {
			pixel_xres = 480 * zoom;
			pixel_yres = 800 * zoom;
		}
	}

	net::Init();
#ifdef __APPLE__
	// Make sure to request a somewhat modern GL context at least - the
	// latest supported by MacOSX (really, really sad...)
	// Requires SDL 2.0 (which is even more sad, as that hasn't been released yet)
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
#endif

	if (SDL_Init(SDL_INIT_VIDEO) < 0) {
		fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
		return 1;
	}
#ifdef EGL
	if (EGL_Open())
		return 1;
#endif

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);

	if (SDL_SetVideoMode(pixel_xres, pixel_yres, 0, 
#ifdef USING_GLES2
		SDL_SWSURFACE | SDL_FULLSCREEN
#else
		SDL_OPENGL
#endif
		) == NULL) {
		fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError());
		SDL_Quit();
		return(2);
	}
#ifdef EGL
	EGL_Init();
#endif

	SDL_WM_SetCaption(app_name_nice.c_str(), NULL);
#ifdef MAEMO
	SDL_ShowCursor(SDL_DISABLE);
#endif


#ifndef USING_GLES2
	if (GLEW_OK != glewInit()) {
		printf("Failed to initialize glew!\n");
		return 1;
	}

	if (GLEW_VERSION_2_0) {
		printf("OpenGL 2.0 or higher.\n");
	} else {
		printf("Sorry, this program requires OpenGL 2.0.\n");
		return 1;
	}
#endif

#ifdef _MSC_VER
	// VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\"));
	TCHAR path[MAX_PATH];
	SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path);
	PathAppend(path, (app_name + "\\").c_str());
#else
	// Mac / Linux
	char path[512];
	const char *the_path = getenv("HOME");
	if (!the_path) {
		struct passwd* pwd = getpwuid(getuid());
		if (pwd)
			the_path = pwd->pw_dir;
	}
	strcpy(path, the_path);
	if (path[strlen(path)-1] != '/')
		strcat(path, "/");
#endif

#ifdef _WIN32
	NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE");
#else
	NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE");
#endif

	dp_xres = (float)pixel_xres * density / zoom;
	dp_yres = (float)pixel_yres * density / zoom;
	pixel_in_dps = (float)pixel_xres / dp_xres;

	NativeInitGraphics();
	glstate.viewport.set(0, 0, pixel_xres, pixel_yres);

	float dp_xscale = (float)dp_xres / pixel_xres;
	float dp_yscale = (float)dp_yres / pixel_yres;


	printf("Pixels: %i x %i\n", pixel_xres, pixel_yres);
	printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres);

	SDL_AudioSpec fmt;
	fmt.freq = 44100;
	fmt.format = AUDIO_S16;
	fmt.channels = 2;
	fmt.samples = 1024;
	fmt.callback = &mixaudio;
	fmt.userdata = (void *)0;

	if (SDL_OpenAudio(&fmt, NULL) < 0) {
		ELOG("Failed to open audio: %s", SDL_GetError());
		return 1;
	}

	// Audio must be unpaused _after_ NativeInit()
	SDL_PauseAudio(0);
#ifdef PANDORA
	// Joysticks init, we the nubs if setup as Joystick
	int numjoys = SDL_NumJoysticks();
	if (numjoys>0)
		for (int i=0; i<numjoys; i++)
		{
			if (strncmp(SDL_JoystickName(i), "nub0", 4) == 0)
				ljoy=SDL_JoystickOpen(i);
			if (strncmp(SDL_JoystickName(i), "nub1", 4) == 0)
				rjoy=SDL_JoystickOpen(i);
		}
#endif

	int framecount = 0;
	bool nextFrameMD = 0;
	float t = 0, lastT = 0;
	while (true) {
		input_state.accelerometer_valid = false;
		input_state.mouse_valid = true;
		int quitRequested = 0;

		SDL_Event event;
		while (SDL_PollEvent(&event)) {
			float mx = event.motion.x * dp_xscale;
			float my = event.motion.y * dp_yscale;

			if (event.type == SDL_QUIT) {
				quitRequested = 1;
			} else if (event.type == SDL_KEYDOWN) {
				if (event.key.keysym.sym == SDLK_ESCAPE) {
					quitRequested = 1;
				}
			} else if (event.type == SDL_MOUSEMOTION) {
				input_state.pointer_x[0] = mx;
				input_state.pointer_y[0] = my;
				NativeTouch(0, mx, my, 0, TOUCH_MOVE);
			} else if (event.type == SDL_MOUSEBUTTONDOWN) {
				if (event.button.button == SDL_BUTTON_LEFT) {
					//input_state.mouse_buttons_down = 1;
					input_state.pointer_down[0] = true;
					nextFrameMD = true;
					NativeTouch(0, mx, my, 0, TOUCH_DOWN);
				}
			} else if (event.type == SDL_MOUSEBUTTONUP) {
				if (event.button.button == SDL_BUTTON_LEFT) {
					input_state.pointer_down[0] = false;
					nextFrameMD = false;
					//input_state.mouse_buttons_up = 1;
					NativeTouch(0, mx, my, 0, TOUCH_UP);
				}
			}
		}

		if (quitRequested)
			break;

		const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL);
		if (keys[SDLK_ESCAPE])
			break;
		SimulateGamepad(keys, &input_state);
		UpdateInputState(&input_state);
		NativeUpdate(input_state);
		NativeRender();

		EndInputState(&input_state);

		if (framecount % 60 == 0) {
			// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
		}

#ifdef EGL
		eglSwapBuffers(g_eglDisplay, g_eglSurface);
#else
		if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0)
		{
			SDL_GL_SwapBuffers();
			lastT = t;
		}
#endif

		// Simple frame rate limiting
//		while (time_now() < t + 1.0f/60.0f) {
//			sleep_ms(0);
//			time_update();
//		}
		time_update();
		t = time_now();
		framecount++;
	}
	// Faster exit, thanks to the OS. Remove this if you want to debug shutdown
	// The speed difference is only really noticable on Linux. On Windows you do notice it though
#ifdef _WIN32
	exit(0);
#endif
	NativeShutdownGraphics();
	SDL_PauseAudio(1);
	SDL_CloseAudio();
	NativeShutdown();
#ifdef EGL
	EGL_Close();
#endif
	SDL_Quit();
	net::Shutdown();
	exit(0);
	return 0;
}
Ejemplo n.º 18
0
	LRESULT CALLBACK DisplayProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
		// Only apply a factor > 1 in windowed mode.
		int factor = !IsZoomed(GetHWND()) && !g_Config.bFullScreen && IsWindowSmall() ? 2 : 1;
		static bool firstErase = true;

		switch (message) {
		case WM_ACTIVATE:
			if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) {
				g_activeWindow = WINDOW_MAINWINDOW;
			}
			break;

		case WM_SIZE:
			break;

		case WM_SETFOCUS:
			break;

		case WM_ERASEBKGND:
			if (firstErase) {
				firstErase = false;
				// Paint black on first erase while OpenGL stuff is loading
				return DefWindowProc(hWnd, message, wParam, lParam);
			}
			// Then never erase, let the OpenGL drawing take care of everything.
			return 1;

		// Poor man's touch - mouse input. We send the data both as an input_state pointer,
		// and as asynchronous touch events for minimal latency.
		case WM_LBUTTONDOWN:
			if (!touchHandler.hasTouch() ||
				(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
			{
				// Hack: Take the opportunity to show the cursor.
				mouseButtonDown = true;
				{
					lock_guard guard(input_state.lock);
					input_state.mouse_valid = true;
					input_state.pointer_down[0] = true;

					input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; 
					input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor;
				}

				TouchInput touch;
				touch.id = 0;
				touch.flags = TOUCH_DOWN;
				touch.x = input_state.pointer_x[0];
				touch.y = input_state.pointer_y[0];
				NativeTouch(touch);
				SetCapture(hWnd);

				// Simulate doubleclick, doesn't work with RawInput enabled
				static double lastMouseDown;
				double now = real_time_now();
				if ((now - lastMouseDown) < 0.001 * GetDoubleClickTime()) {
					if (!g_Config.bShowTouchControls && GetUIState() == UISTATE_INGAME) {
						PostMessage(hwndMain, WM_USER_TOGGLE_FULLSCREEN, 0, 0);
					}
					lastMouseDown = 0.0;
				} else {
					lastMouseDown = real_time_now();
				}
			}
			break;

		case WM_MOUSEMOVE:
			if (!touchHandler.hasTouch() ||
				(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
			{
				// Hack: Take the opportunity to show the cursor.
				mouseButtonDown = (wParam & MK_LBUTTON) != 0;
				int cursorX = GET_X_LPARAM(lParam);
				int cursorY = GET_Y_LPARAM(lParam);
				if (abs(cursorX - prevCursorX) > 1 || abs(cursorY - prevCursorY) > 1) {
					hideCursor = false;
					SetTimer(hwndMain, TIMER_CURSORMOVEUPDATE, CURSORUPDATE_MOVE_TIMESPAN_MS, 0);
				}
				prevCursorX = cursorX;
				prevCursorY = cursorY;

				{
					lock_guard guard(input_state.lock);
					input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; 
					input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor;
				}

				if (wParam & MK_LBUTTON) {
					TouchInput touch;
					touch.id = 0;
					touch.flags = TOUCH_MOVE;
					touch.x = input_state.pointer_x[0];
					touch.y = input_state.pointer_y[0];
					NativeTouch(touch);
				}
			}
			break;

		case WM_LBUTTONUP:
			if (!touchHandler.hasTouch() ||
				(GetMessageExtraInfo() & MOUSEEVENTF_MASK_PLUS_PENTOUCH) != MOUSEEVENTF_FROMTOUCH_NOPEN)
			{
				// Hack: Take the opportunity to hide the cursor.
				mouseButtonDown = false;
				{
					lock_guard guard(input_state.lock);
					input_state.pointer_down[0] = false;
					input_state.pointer_x[0] = GET_X_LPARAM(lParam) * factor; 
					input_state.pointer_y[0] = GET_Y_LPARAM(lParam) * factor;
				}
				TouchInput touch;
				touch.id = 0;
				touch.flags = TOUCH_UP;
				touch.x = input_state.pointer_x[0];
				touch.y = input_state.pointer_y[0];
				NativeTouch(touch);
				ReleaseCapture();
			}
			break;

		case WM_TOUCH:
			{
				touchHandler.handleTouchEvent(hWnd, message, wParam, lParam);
				return 0;
			}

		default:
			return DefWindowProc(hWnd, message, wParam, lParam);
		}
		return 0;
	}
Ejemplo n.º 19
0
int main(int argc, char *argv[]) {
#if PPSSPP_PLATFORM(RPI)
	bcm_host_init();
#endif
	putenv((char*)"SDL_VIDEO_CENTERED=1");
	SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");

	std::string app_name;
	std::string app_name_nice;
	std::string version;
	bool landscape;
	NativeGetAppInfo(&app_name, &app_name_nice, &landscape, &version);

	bool joystick_enabled = true;
	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_AUDIO) < 0) {
		joystick_enabled = false;
		if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0) {
			fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
			return 1;
		}
	}

#ifdef __APPLE__
	// Make sure to request a somewhat modern GL context at least - the
	// latest supported by MacOSX (really, really sad...)
	// Requires SDL 2.0
	// We really should upgrade to SDL 2.0 soon.
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
#endif

#ifdef USING_EGL
	if (EGL_Open())
		return 1;
#endif

	// Get the video info before doing anything else, so we don't get skewed resolution results.
	// TODO: support multiple displays correctly
	SDL_DisplayMode displayMode;
	int should_be_zero = SDL_GetCurrentDisplayMode(0, &displayMode);
	if (should_be_zero != 0) {
		fprintf(stderr, "Could not get display mode: %s\n", SDL_GetError());
		return 1;
	}
	g_DesktopWidth = displayMode.w;
	g_DesktopHeight = displayMode.h;

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
	SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetSwapInterval(1);

	Uint32 mode;
#ifdef USING_GLES2
	mode = SDL_WINDOW_OPENGL | SDL_WINDOW_FULLSCREEN;
#else
	mode = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE;
#endif
	int set_xres = -1;
	int set_yres = -1;
	bool portrait = false;
	bool set_ipad = false;
	float set_dpi = 1.0f;
	float set_scale = 1.0f;

	// Produce a new set of arguments with the ones we skip.
	int remain_argc = 1;
	const char *remain_argv[256] = { argv[0] };

	for (int i = 1; i < argc; i++) {
		if (!strcmp(argv[i],"--fullscreen"))
			mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
		else if (set_xres == -2)
			set_xres = parseInt(argv[i]);
		else if (set_yres == -2)
			set_yres = parseInt(argv[i]);
		else if (set_dpi == -2)
			set_dpi = parseFloat(argv[i]);
		else if (set_scale == -2)
			set_scale = parseFloat(argv[i]);
		else if (!strcmp(argv[i],"--xres"))
			set_xres = -2;
		else if (!strcmp(argv[i],"--yres"))
			set_yres = -2;
		else if (!strcmp(argv[i],"--dpi"))
			set_dpi = -2;
		else if (!strcmp(argv[i],"--scale"))
			set_scale = -2;
		else if (!strcmp(argv[i],"--ipad"))
			set_ipad = true;
		else if (!strcmp(argv[i],"--portrait"))
			portrait = true;
		else {
			remain_argv[remain_argc++] = argv[i];
		}
	}

	// Is resolution is too low to run windowed
	if (g_DesktopWidth < 480 * 2 && g_DesktopHeight < 272 * 2) {
		mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;
	}

	if (mode & SDL_WINDOW_FULLSCREEN_DESKTOP) {
		pixel_xres = g_DesktopWidth;
		pixel_yres = g_DesktopHeight;
		g_Config.bFullScreen = true;
	} else {
		// set a sensible default resolution (2x)
		pixel_xres = 480 * 2 * set_scale;
		pixel_yres = 272 * 2 * set_scale;
		if (portrait) {
			std::swap(pixel_xres, pixel_yres);
		}
		g_Config.bFullScreen = false;
	}

	set_dpi = 1.0f / set_dpi;

	if (set_ipad) {
		pixel_xres = 1024;
		pixel_yres = 768;
	}
	if (!landscape) {
		std::swap(pixel_xres, pixel_yres);
	}

	if (set_xres > 0) {
		pixel_xres = set_xres;
	}
	if (set_yres > 0) {
		pixel_yres = set_yres;
	}
	float dpi_scale = 1.0f;
	if (set_dpi > 0) {
		dpi_scale = set_dpi;
	}

	dp_xres = (float)pixel_xres * dpi_scale;
	dp_yres = (float)pixel_yres * dpi_scale;

#ifdef _MSC_VER
	// VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\"));
	TCHAR path[MAX_PATH];
	SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path);
	PathAppend(path, (app_name + "\\").c_str());
#else
	// Mac / Linux
	char path[2048];
	const char *the_path = getenv("HOME");
	if (!the_path) {
		struct passwd* pwd = getpwuid(getuid());
		if (pwd)
			the_path = pwd->pw_dir;
	}
	strcpy(path, the_path);
	if (path[strlen(path)-1] != '/')
		strcat(path, "/");
#endif

#ifdef _WIN32
	NativeInit(remain_argc, (const char **)remain_argv, path, "D:\\", nullptr);
#else
	NativeInit(remain_argc, (const char **)remain_argv, path, "/tmp", nullptr);
#endif

	// Use the setting from the config when initing the window.
	if (g_Config.bFullScreen)
		mode |= SDL_WINDOW_FULLSCREEN_DESKTOP;

	g_Screen = SDL_CreateWindow(app_name_nice.c_str(), SDL_WINDOWPOS_UNDEFINED_DISPLAY(getDisplayNumber()),\
					SDL_WINDOWPOS_UNDEFINED, pixel_xres, pixel_yres, mode);

	if (g_Screen == NULL) {
		NativeShutdown();
		fprintf(stderr, "SDL_CreateWindow failed: %s\n", SDL_GetError());
		SDL_Quit();
		return 2;
	}

	SDL_GLContext glContext = SDL_GL_CreateContext(g_Screen);
	if (glContext == NULL) {
		NativeShutdown();
		fprintf(stderr, "SDL_GL_CreateContext failed: %s\n", SDL_GetError());
		SDL_Quit();
		return 2;
	}

#ifdef USING_EGL
	EGL_Init();
#endif

	SDL_SetWindowTitle(g_Screen, (app_name_nice + " " + PPSSPP_GIT_VERSION).c_str());

#ifdef MOBILE_DEVICE
	SDL_ShowCursor(SDL_DISABLE);
#endif


#ifndef USING_GLES2
	// Some core profile drivers elide certain extensions from GL_EXTENSIONS/etc.
	// glewExperimental allows us to force GLEW to search for the pointers anyway.
	if (gl_extensions.IsCoreContext)
		glewExperimental = true;
	if (GLEW_OK != glewInit()) {
		printf("Failed to initialize glew!\n");
		return 1;
	}
	// Unfortunately, glew will generate an invalid enum error, ignore.
	if (gl_extensions.IsCoreContext)
		glGetError();

	if (GLEW_VERSION_2_0) {
		printf("OpenGL 2.0 or higher.\n");
	} else {
		printf("Sorry, this program requires OpenGL 2.0.\n");
		return 1;
	}
#endif


	pixel_in_dps_x = (float)pixel_xres / dp_xres;
	pixel_in_dps_y = (float)pixel_yres / dp_yres;
	g_dpi_scale_x = dp_xres / (float)pixel_xres;
	g_dpi_scale_y = dp_yres / (float)pixel_yres;
	g_dpi_scale_real_x = g_dpi_scale_x;
	g_dpi_scale_real_y = g_dpi_scale_y;

	printf("Pixels: %i x %i\n", pixel_xres, pixel_yres);
	printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres);

	GraphicsContext *graphicsContext = new GLDummyGraphicsContext();
	NativeInitGraphics(graphicsContext);

	NativeResized();

	SDL_AudioSpec fmt, ret_fmt;
	memset(&fmt, 0, sizeof(fmt));
	fmt.freq = 44100;
	fmt.format = AUDIO_S16;
	fmt.channels = 2;
	fmt.samples = 2048;
	fmt.callback = &mixaudio;
	fmt.userdata = (void *)0;

	if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) {
		ELOG("Failed to open audio: %s", SDL_GetError());
	} else {
		if (ret_fmt.samples != fmt.samples) // Notify, but still use it
			ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, fmt.samples);
		if (ret_fmt.freq != fmt.freq || ret_fmt.format != fmt.format || ret_fmt.channels != fmt.channels) {
			ELOG("Sound buffer format does not match requested format.");
			ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, fmt.freq);
			ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, fmt.format);
			ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, fmt.channels);
			ELOG("Provided output format does not match requirement, turning audio off");
			SDL_CloseAudio();
		}
	}

	// Audio must be unpaused _after_ NativeInit()
	SDL_PauseAudio(0);
#ifndef _WIN32
	if (joystick_enabled) {
		joystick = new SDLJoystick();
	} else {
		joystick = nullptr;
	}
#endif
	EnableFZ();

	int framecount = 0;
	float t = 0;
	float lastT = 0;
	bool mouseDown = false;

	while (true) {
		SDL_Event event;
		while (SDL_PollEvent(&event)) {
			float mx = event.motion.x * g_dpi_scale_x;
			float my = event.motion.y * g_dpi_scale_y;

			switch (event.type) {
			case SDL_QUIT:
				g_QuitRequested = 1;
				break;

#if !defined(MOBILE_DEVICE)
			case SDL_WINDOWEVENT:
				switch (event.window.event) {
				case SDL_WINDOWEVENT_RESIZED:
				{
					Uint32 window_flags = SDL_GetWindowFlags(g_Screen);
					bool fullscreen = (window_flags & SDL_WINDOW_FULLSCREEN);

					pixel_xres = event.window.data1;
					pixel_yres = event.window.data2;
					dp_xres = (float)pixel_xres * dpi_scale;
					dp_yres = (float)pixel_yres * dpi_scale;
					NativeResized();

					// Set variable here in case fullscreen was toggled by hotkey
					g_Config.bFullScreen = fullscreen;

					// Hide/Show cursor correctly toggling fullscreen
					if (lastUIState == UISTATE_INGAME && fullscreen && !g_Config.bShowTouchControls) {
						SDL_ShowCursor(SDL_DISABLE);
					} else if (lastUIState != UISTATE_INGAME || !fullscreen) {
						SDL_ShowCursor(SDL_ENABLE);
					}
					break;
				}

				default:
					break;
				}
				break;
#endif
			case SDL_KEYDOWN:
				{
					if (event.key.repeat > 0) { break;}
					int k = event.key.keysym.sym;
					KeyInput key;
					key.flags = KEY_DOWN;
					auto mapped = KeyMapRawSDLtoNative.find(k);
					if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) {
						break;
					}
					key.keyCode = mapped->second;
					key.deviceId = DEVICE_ID_KEYBOARD;
					NativeKey(key);
					break;
				}
			case SDL_KEYUP:
				{
					if (event.key.repeat > 0) { break;}
					int k = event.key.keysym.sym;
					KeyInput key;
					key.flags = KEY_UP;
					auto mapped = KeyMapRawSDLtoNative.find(k);
					if (mapped == KeyMapRawSDLtoNative.end() || mapped->second == NKCODE_UNKNOWN) {
						break;
					}
					key.keyCode = mapped->second;
					key.deviceId = DEVICE_ID_KEYBOARD;
					NativeKey(key);
					break;
				}
			case SDL_TEXTINPUT:
				{
					int pos = 0;
					int c = u8_nextchar(event.text.text, &pos);
					KeyInput key;
					key.flags = KEY_CHAR;
					key.keyCode = c;
					key.deviceId = DEVICE_ID_KEYBOARD;
					NativeKey(key);
					break;
				}
			case SDL_MOUSEBUTTONDOWN:
				switch (event.button.button) {
				case SDL_BUTTON_LEFT:
					{
						mouseDown = true;
						TouchInput input;
						input.x = mx;
						input.y = my;
						input.flags = TOUCH_DOWN | TOUCH_MOUSE;
						input.id = 0;
						NativeTouch(input);
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN);
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_RIGHT:
					{
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN);
						NativeKey(key);
					}
					break;
				}
				break;
			case SDL_MOUSEWHEEL:
				{
					KeyInput key;
					key.deviceId = DEVICE_ID_MOUSE;
					if (event.wheel.y > 0) {
						key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP;
					} else {
						key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN;
					}
					key.flags = KEY_DOWN;
					NativeKey(key);

					// SDL2 doesn't consider the mousewheel a button anymore
					// so let's send the KEY_UP right away.
					// Maybe KEY_UP alone will suffice?
					key.flags = KEY_UP;
					NativeKey(key);
				}
			case SDL_MOUSEMOTION:
				if (mouseDown) {
					TouchInput input;
					input.x = mx;
					input.y = my;
					input.flags = TOUCH_MOVE | TOUCH_MOUSE;
					input.id = 0;
					NativeTouch(input);
				}
				break;
			case SDL_MOUSEBUTTONUP:
				switch (event.button.button) {
				case SDL_BUTTON_LEFT:
					{
						mouseDown = false;
						TouchInput input;
						input.x = mx;
						input.y = my;
						input.flags = TOUCH_UP | TOUCH_MOUSE;
						input.id = 0;
						NativeTouch(input);
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP);
						NativeKey(key);
					}
					break;
				case SDL_BUTTON_RIGHT:
					{
						KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP);
						NativeKey(key);
					}
					break;
				}
				break;
			default:
#ifndef _WIN32
				if (joystick) {
					joystick->ProcessInput(event);
				}
#endif
				break;
			}
		}
		if (g_QuitRequested)
			break;
		const uint8_t *keys = SDL_GetKeyboardState(NULL);
		UpdateRunLoop();
		if (g_QuitRequested)
			break;
#if !defined(MOBILE_DEVICE)
		if (lastUIState != GetUIState()) {
			lastUIState = GetUIState();
			if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls)
				SDL_ShowCursor(SDL_DISABLE);
			if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen)
				SDL_ShowCursor(SDL_ENABLE);
		}
#endif

		if (framecount % 60 == 0) {
			// glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
		}

#ifdef USING_EGL
		eglSwapBuffers(g_eglDisplay, g_eglSurface);
#else
		if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0) {
			SDL_GL_SwapWindow(g_Screen);
			lastT = t;
		}
#endif

		ToggleFullScreenIfFlagSet();
		time_update();
		t = time_now();
		framecount++;
	}
#ifndef _WIN32
	delete joystick;
#endif
	NativeShutdownGraphics();
	graphicsContext->Shutdown();
	NativeShutdown();
	delete graphicsContext;
	// Faster exit, thanks to the OS. Remove this if you want to debug shutdown
	// The speed difference is only really noticable on Linux. On Windows you do notice it though
#ifndef MOBILE_DEVICE
	exit(0);
#endif
	SDL_PauseAudio(1);
	SDL_CloseAudio();
#ifdef USING_EGL
	EGL_Close();
#endif
	SDL_GL_DeleteContext(glContext);
	SDL_Quit();
#if PPSSPP_PLATFORM(RPI)
	bcm_host_deinit();
#endif

	exit(0);
	return 0;
}
Ejemplo n.º 20
0
int main(int argc, char *argv[]) {
#ifdef RPI
    bcm_host_init();
#endif
    putenv((char*)"SDL_VIDEO_CENTERED=1");

    std::string app_name;
    std::string app_name_nice;
    bool landscape;
    NativeGetAppInfo(&app_name, &app_name_nice, &landscape);

    net::Init();
#ifdef __APPLE__
    // Make sure to request a somewhat modern GL context at least - the
    // latest supported by MacOSX (really, really sad...)
    // Requires SDL 2.0
    // We really should upgrade to SDL 2.0 soon.
    //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    //SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
#endif

    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_AUDIO) < 0) {
        fprintf(stderr, "Unable to initialize SDL: %s\n", SDL_GetError());
        return 1;
    }
#ifdef USING_EGL
    if (EGL_Open())
        return 1;
#endif

    // Get the video info before doing anything else, so we don't get skewed resolution results.
    const SDL_VideoInfo* desktopVideoInfo = SDL_GetVideoInfo();
    g_DesktopWidth = desktopVideoInfo->current_w;
    g_DesktopHeight = desktopVideoInfo->current_h;

    SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
    SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8);
    SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
    SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);

    int mode;
#ifdef USING_GLES2
    mode = SDL_SWSURFACE | SDL_FULLSCREEN;
#else
    mode = SDL_OPENGL | SDL_RESIZABLE;
#endif
    int set_xres = -1;
    int set_yres = -1;
    bool portrait = false;
    bool set_ipad = false;
    float set_dpi = 1.0f;
    float set_scale = 1.0f;

    for (int i = 1; i < argc; i++) {
        if (!strcmp(argv[i],"--fullscreen"))
            mode |= SDL_FULLSCREEN;
        if (set_xres == -2) {
            set_xres = parseInt(argv[i]);
        } else if (set_yres == -2) {
            set_yres = parseInt(argv[i]);
        }
        if (set_dpi == -2)
            set_dpi = parseFloat(argv[i]);
        if (set_scale == -2)
            set_scale = parseFloat(argv[i]);

        if (!strcmp(argv[i],"--xres"))
            set_xres = -2;
        if (!strcmp(argv[i],"--yres"))
            set_yres = -2;
        if (!strcmp(argv[i],"--dpi"))
            set_dpi = -2;
        if (!strcmp(argv[i],"--scale"))
            set_scale = -2;

        if (!strcmp(argv[i],"--ipad"))
            set_ipad = true;
        if (!strcmp(argv[i],"--portrait"))
            portrait = true;
    }

    if (mode & SDL_FULLSCREEN) {
        const SDL_VideoInfo* info = SDL_GetVideoInfo();
        pixel_xres = info->current_w;
        pixel_yres = info->current_h;
#ifdef PPSSPP
        g_Config.bFullScreen = true;
#endif
    } else {
        // set a sensible default resolution (2x)
        pixel_xres = 480 * 2 * set_scale;
        pixel_yres = 272 * 2 * set_scale;
        if (portrait) {
            std::swap(pixel_xres, pixel_yres);
        }
#ifdef PPSSPP
        g_Config.bFullScreen = false;
#endif
    }

    set_dpi = 1.0f / set_dpi;

    if (set_ipad) {
        pixel_xres = 1024;
        pixel_yres = 768;
    }
    if (!landscape) {
        std::swap(pixel_xres, pixel_yres);
    }

    if (set_xres > 0) {
        pixel_xres = set_xres;
    }
    if (set_yres > 0) {
        pixel_yres = set_yres;
    }
    float dpi_scale = 1.0f;
    if (set_dpi > 0) {
        dpi_scale = set_dpi;
    }

    dp_xres = (float)pixel_xres * dpi_scale;
    dp_yres = (float)pixel_yres * dpi_scale;

    g_Screen = SDL_SetVideoMode(pixel_xres, pixel_yres, 0, mode);
    if (g_Screen == NULL) {
        fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError());
        SDL_Quit();
        return 2;
    }

#ifdef USING_EGL
    EGL_Init();
#endif

#ifdef PPSSPP
    SDL_WM_SetCaption((app_name_nice + " " + PPSSPP_GIT_VERSION).c_str(), NULL);
#endif

#ifdef MOBILE_DEVICE
    SDL_ShowCursor(SDL_DISABLE);
#endif


#ifndef USING_GLES2
    if (GLEW_OK != glewInit()) {
        printf("Failed to initialize glew!\n");
        return 1;
    }

    if (GLEW_VERSION_2_0) {
        printf("OpenGL 2.0 or higher.\n");
    } else {
        printf("Sorry, this program requires OpenGL 2.0.\n");
        return 1;
    }
#endif

#ifdef _MSC_VER
    // VFSRegister("temp/", new DirectoryAssetReader("E:\\Temp\\"));
    TCHAR path[MAX_PATH];
    SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path);
    PathAppend(path, (app_name + "\\").c_str());
#else
    // Mac / Linux
    char path[512];
    const char *the_path = getenv("HOME");
    if (!the_path) {
        struct passwd* pwd = getpwuid(getuid());
        if (pwd)
            the_path = pwd->pw_dir;
    }
    strcpy(path, the_path);
    if (path[strlen(path)-1] != '/')
        strcat(path, "/");
#endif

#ifdef _WIN32
    NativeInit(argc, (const char **)argv, path, "D:\\", "BADCOFFEE");
#else
    NativeInit(argc, (const char **)argv, path, "/tmp", "BADCOFFEE");
#endif

    pixel_in_dps = (float)pixel_xres / dp_xres;
    g_dpi_scale = dp_xres / (float)pixel_xres;

    printf("Pixels: %i x %i\n", pixel_xres, pixel_yres);
    printf("Virtual pixels: %i x %i\n", dp_xres, dp_yres);

    NativeInitGraphics();
    NativeResized();

    SDL_AudioSpec fmt, ret_fmt;
    memset(&fmt, 0, sizeof(fmt));
    fmt.freq = 44100;
    fmt.format = AUDIO_S16;
    fmt.channels = 2;
    fmt.samples = 2048;
    fmt.callback = &mixaudio;
    fmt.userdata = (void *)0;

    if (SDL_OpenAudio(&fmt, &ret_fmt) < 0) {
        ELOG("Failed to open audio: %s", SDL_GetError());
    } else {
        if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2 || fmt.samples != 2048) {
            ELOG("Sound buffer format does not match requested format.");
            ELOG("Output audio freq: %d (requested: %d)", ret_fmt.freq, 44100);
            ELOG("Output audio format: %d (requested: %d)", ret_fmt.format, AUDIO_S16);
            ELOG("Output audio channels: %d (requested: %d)", ret_fmt.channels, 2);
            ELOG("Output audio samples: %d (requested: %d)", ret_fmt.samples, 2048);
        }

        if (ret_fmt.freq != 44100 || ret_fmt.format != AUDIO_S16 || ret_fmt.channels != 2) {
            ELOG("Provided output format does not match requirement, turning audio off");
            SDL_CloseAudio();
        } else {
            ELOG("Provided output audio format is usable, thus using it");
        }
    }

    // Audio must be unpaused _after_ NativeInit()
    SDL_PauseAudio(0);
#ifndef _WIN32
    joystick = new SDLJoystick();
#endif
    EnableFZ();

    int framecount = 0;
    float t = 0;
    float lastT = 0;
    uint32_t pad_buttons = 0;	 // legacy pad buttons
    while (true) {
        input_state.accelerometer_valid = false;
        input_state.mouse_valid = true;

        SDL_Event event;
        while (SDL_PollEvent(&event)) {
            float mx = event.motion.x * g_dpi_scale;
            float my = event.motion.y * g_dpi_scale;

            switch (event.type) {
            case SDL_QUIT:
                g_QuitRequested = 1;
                break;
#if !defined(MOBILE_DEVICE)
            case SDL_VIDEORESIZE:
            {
                g_Screen = SDL_SetVideoMode(event.resize.w, event.resize.h, 0, SDL_OPENGL | SDL_RESIZABLE);
                if (g_Screen == NULL) {
                    fprintf(stderr, "SDL SetVideoMode failed: Unable to create OpenGL screen: %s\n", SDL_GetError());
                    SDL_Quit();
                    return 2;
                }
                pixel_xres = event.resize.w;
                pixel_yres = event.resize.h;
                dp_xres = (float)pixel_xres * dpi_scale;
                dp_yres = (float)pixel_yres * dpi_scale;
                NativeResized();
                break;
            }
#endif
            case SDL_KEYDOWN:
            {
                int k = event.key.keysym.sym;
                KeyInput key;
                key.flags = KEY_DOWN;
                key.keyCode = KeyMapRawSDLtoNative.find(k)->second;
                key.deviceId = DEVICE_ID_KEYBOARD;
                NativeKey(key);

                for (int i = 0; i < ARRAY_SIZE(legacyKeyMap); i++) {
                    if (legacyKeyMap[i] == key.keyCode)
                        pad_buttons |= 1 << i;
                }
                break;
            }
            case SDL_KEYUP:
            {
                int k = event.key.keysym.sym;
                KeyInput key;
                key.flags = KEY_UP;
                key.keyCode = KeyMapRawSDLtoNative.find(k)->second;
                key.deviceId = DEVICE_ID_KEYBOARD;
                NativeKey(key);
                for (int i = 0; i < ARRAY_SIZE(legacyKeyMap); i++) {
                    if (legacyKeyMap[i] == key.keyCode)
                        pad_buttons &= ~(1 << i);
                }
                break;
            }
            case SDL_MOUSEBUTTONDOWN:
                switch (event.button.button) {
                case SDL_BUTTON_LEFT:
                {
                    input_state.pointer_x[0] = mx;
                    input_state.pointer_y[0] = my;
                    input_state.pointer_down[0] = true;
                    input_state.mouse_valid = true;
                    TouchInput input;
                    input.x = mx;
                    input.y = my;
                    input.flags = TOUCH_DOWN;
                    input.id = 0;
                    NativeTouch(input);
                    KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_DOWN);
                    NativeKey(key);
                }
                break;
                case SDL_BUTTON_RIGHT:
                {
                    KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_DOWN);
                    NativeKey(key);
                }
                break;
                case SDL_BUTTON_WHEELUP:
                {
                    KeyInput key;
                    key.deviceId = DEVICE_ID_MOUSE;
                    key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP;
                    key.flags = KEY_DOWN;
                    NativeKey(key);
                }
                break;
                case SDL_BUTTON_WHEELDOWN:
                {
                    KeyInput key;
                    key.deviceId = DEVICE_ID_MOUSE;
                    key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN;
                    key.flags = KEY_DOWN;
                    NativeKey(key);
                }
                break;
                }
                break;
            case SDL_MOUSEMOTION:
                if (input_state.pointer_down[0]) {
                    input_state.pointer_x[0] = mx;
                    input_state.pointer_y[0] = my;
                    input_state.mouse_valid = true;
                    TouchInput input;
                    input.x = mx;
                    input.y = my;
                    input.flags = TOUCH_MOVE;
                    input.id = 0;
                    NativeTouch(input);
                }
                break;
            case SDL_MOUSEBUTTONUP:
                switch (event.button.button) {
                case SDL_BUTTON_LEFT:
                {
                    input_state.pointer_x[0] = mx;
                    input_state.pointer_y[0] = my;
                    input_state.pointer_down[0] = false;
                    input_state.mouse_valid = true;
                    //input_state.mouse_buttons_up = 1;
                    TouchInput input;
                    input.x = mx;
                    input.y = my;
                    input.flags = TOUCH_UP;
                    input.id = 0;
                    NativeTouch(input);
                    KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_1, KEY_UP);
                    NativeKey(key);
                }
                break;
                case SDL_BUTTON_RIGHT:
                {
                    KeyInput key(DEVICE_ID_MOUSE, NKCODE_EXT_MOUSEBUTTON_2, KEY_UP);
                    NativeKey(key);
                }
                break;
                case SDL_BUTTON_WHEELUP:
                {
                    KeyInput key;
                    key.deviceId = DEVICE_ID_DEFAULT;
                    key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP;
                    key.flags = KEY_UP;
                    NativeKey(key);
                }
                break;
                case SDL_BUTTON_WHEELDOWN:
                {
                    KeyInput key;
                    key.deviceId = DEVICE_ID_DEFAULT;
                    key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN;
                    key.flags = KEY_UP;
                    NativeKey(key);
                }
                break;
                }
                break;
            default:
#ifndef _WIN32
                joystick->ProcessInput(event);
#endif
                break;
            }
        }
        if (g_QuitRequested)
            break;
        const uint8 *keys = (const uint8 *)SDL_GetKeyState(NULL);
        SimulateGamepad(keys, &input_state);
        input_state.pad_buttons = pad_buttons;
        UpdateInputState(&input_state, true);
        NativeUpdate(input_state);
        if (g_QuitRequested)
            break;
        NativeRender();
#if defined(PPSSPP) && !defined(MOBILE_DEVICE)
        if (lastUIState != globalUIState) {
            lastUIState = globalUIState;
            if (lastUIState == UISTATE_INGAME && g_Config.bFullScreen && !g_Config.bShowTouchControls)
                SDL_ShowCursor(SDL_DISABLE);
            if (lastUIState != UISTATE_INGAME && g_Config.bFullScreen)
                SDL_ShowCursor(SDL_ENABLE);
        }
#endif

        EndInputState(&input_state);

        if (framecount % 60 == 0) {
            // glsl_refresh(); // auto-reloads modified GLSL shaders once per second.
        }

#ifdef USING_EGL
        eglSwapBuffers(g_eglDisplay, g_eglSurface);
#else
        if (!keys[SDLK_TAB] || t - lastT >= 1.0/60.0)
        {
            SDL_GL_SwapBuffers();
            lastT = t;
        }
#endif

        ToggleFullScreenIfFlagSet();
        time_update();
        t = time_now();
        framecount++;
    }
#ifndef _WIN32
    delete joystick;
#endif
    // Faster exit, thanks to the OS. Remove this if you want to debug shutdown
    // The speed difference is only really noticable on Linux. On Windows you do notice it though
#ifndef MOBILE_DEVICE
    exit(0);
#endif
    NativeShutdownGraphics();
    SDL_PauseAudio(1);
    SDL_CloseAudio();
    NativeShutdown();
#ifdef USING_EGL
    EGL_Close();
#endif
    SDL_Quit();
    net::Shutdown();
#ifdef RPI
    bcm_host_deinit();
#endif

    exit(0);
    return 0;
}