void finalization() { #ifdef F1SPIRIT_DEBUG_MESSAGES output_debug_message("Finalizing SDL\n"); #endif if (network) { SDLNet_Quit(); } delete rg; rg = 0; free_auxiliar_menu_surfaces(); if (sound) Sound_release(); IMG_Quit(); #ifdef HAVE_GLES EGL_Close(); #endif SDL_Quit(); #ifdef F1SPIRIT_DEBUG_MESSAGES output_debug_message("SDL finalized\n"); #endif } /* finalization */
//----------------------------------------------------------------------------- // Dispose //----------------------------------------------------------------------------- void GraphicsPlugin::dispose() { //Dispose of Textures m_textureCache.dispose(); //Dispose of member objects if ( m_vi ) { delete m_vi; m_vi = 0; } if ( m_memory ) { delete m_memory; m_memory = 0; } if ( m_displayListParser ) { delete m_displayListParser; m_displayListParser = 0; } if ( m_fogManager ) { delete m_fogManager; m_fogManager = 0; } m_gbi.dispose(); m_rdp.dispose(); m_rsp.dispose(); //Dispose of OpenGL //framebuffer01.dispose(); // framebuffer02.dispose(); m_openGLMgr.dispose(); if (m_initialized) #ifdef HAVE_GLES { EGL_Close(); SDL_Quit(); // *SEB* *TODO* Close Subsystem only? } #else CoreVideo_Quit(); #endif m_initialized = false; }
/* =============== GLimp_Shutdown =============== */ void GLimp_Shutdown( void ) { IN_Shutdown(); #ifdef HAVE_GLES EGL_Close(); #endif SDL_QuitSubSystem( SDL_INIT_VIDEO ); screen = NULL; Com_Memset( &glConfig, 0, sizeof( glConfig ) ); Com_Memset( &glState, 0, sizeof( glState ) ); }
/** * ANSI main entry point */ int main(int argc, char* argv[]) { unsigned long lvl_id; level::size lvl_sz; bool lvl_wrap; if (parse_cmd_params(argc, argv, lvl_id, lvl_sz, lvl_wrap)) return 0; //Help or version was shown //Initialization if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO) != 0) { fprintf(stderr, "Critical error\nSDL_Init failed: %s\n", SDL_GetError()); return 1; } #ifdef USE_OPENGLES if (EGL_Open()){ fprintf(stderr, "Critical error\nUnable to open egl\n"); return 1; } #endif //Let's get some video information const SDL_VideoInfo* vinfo = SDL_GetVideoInfo(); if (!vinfo) { fprintf(stderr, "Critical error\nUnable to get video information: %s\n", SDL_GetError()); return 1; } //Save desktop size const int desktop_width = vinfo->current_w; const int desktop_height = vinfo->current_h; //Calculate minimum window sizes const int wnd_min_width = PW_SCREEN_WIDTH / 3; const int wnd_min_height = PW_SCREEN_HEIGHT / 3; //Create window #if USE_OPENGLES if (!SDL_SetVideoMode(800, 480, 0, SDL_FULLSCREEN)) { fprintf(stderr, "Critical error\nUnable to set video mode: %s\n", SDL_GetError()); return 1; } int prevcursorstate=SDL_ShowCursor(SDL_QUERY); SDL_ShowCursor(SDL_DISABLE); EGL_Init(); #else if (!SDL_SetVideoMode(PW_SCREEN_WIDTH, PW_SCREEN_HEIGHT, 0, SDL_OPENGL | SDL_RESIZABLE)) { fprintf(stderr, "Critical error\nUnable to set video mode: %s\n", SDL_GetError()); return 1; } #endif SDL_WM_SetCaption(PACKAGE_NAME, PACKAGE_NAME); image wnd_icon; if (wnd_icon.load_XPM(pipewalker_xpm, sizeof(pipewalker_xpm) / sizeof(pipewalker_xpm[0]))) SDL_WM_SetIcon(wnd_icon.get_surface(), NULL); game& game_instance = game::instance(); if (!game_instance.initialize(lvl_id, lvl_sz, lvl_wrap)) return 1; //Timer - about 25 fps SDL_SetTimer(40, &timer_callback); #ifdef WIN32 SDL_SysWMinfo wmi; SDL_VERSION(&wmi.version); if (SDL_GetWMInfo(&wmi)) { //Set own window procedure sdl_wnd_proc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(wmi.window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(&pw_win32_wnd_proc))); //Set normal icon static HICON icon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(0)); if (icon) SetClassLongPtr(wmi.window, GCL_HICON, reinterpret_cast<LONG>(icon)); } #endif // WIN32 bool done = false; Uint8 last_mouse_state = 0; while (!done) { SDL_Event event; if (SDL_WaitEvent(&event) == 0) { fprintf(stderr, "Critical error\nSDL_WaitEvent failed: %s\n", SDL_GetError()); return 1; } switch (event.type) { case SDL_MOUSEMOTION: { Sint32 x, y; SDL_GetMouseState(&x, &y); game_instance.on_mouse_move(x, y); } break; case SDL_MOUSEBUTTONDOWN: //We need to save buttons state - in the SDL_MOUSEBUTTONUP event doesn't have this information last_mouse_state = SDL_GetMouseState(NULL, NULL); break; case SDL_MOUSEBUTTONUP: if (last_mouse_state) { game_instance.on_mouse_click(last_mouse_state); last_mouse_state = 0; } break; case SDL_KEYDOWN: if (event.key.keysym.sym == SDLK_F4 && (SDL_GetModState() == KMOD_LALT || SDL_GetModState() == KMOD_RALT)) done = true; //Alt+F4 pressed else done = game_instance.on_key_press(event.key.keysym.sym); break; case SDL_QUIT: done = true; break; case SDL_VIDEOEXPOSE: game_instance.draw_scene(); break; case SDL_VIDEORESIZE: if (event.resize.w && event.resize.h) { int wnd_width = event.resize.w; int wnd_height = event.resize.h; //Set correct aspect ratio if (wnd_width != desktop_width && wnd_height != desktop_height) { if (wnd_height != vinfo->current_h) wnd_width = static_cast<int>(static_cast<float>(wnd_height) / PW_ASPECT_RATIO); else if (wnd_width != vinfo->current_w) wnd_height = static_cast<int>(static_cast<float>(wnd_width) * PW_ASPECT_RATIO); if (wnd_width < wnd_min_width || wnd_height < wnd_min_height) { //Set minimum window size wnd_width = wnd_min_width; wnd_height = wnd_min_height; } } SDL_SetVideoMode(wnd_width, wnd_height, 0, SDL_OPENGL | SDL_RESIZABLE); game_instance.on_window_resize(wnd_width, wnd_height); SDL_Event expose_event; expose_event.type = SDL_VIDEOEXPOSE; SDL_PushEvent(&expose_event); } break; } } game_instance.finalize(); #if USE_OPENGLES EGL_Close(); SDL_ShowCursor(prevcursorstate); #endif SDL_Quit(); return 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; }
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; }
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { #else int main(int argc, char** argv) { #endif SDL_Surface *screen_sfc; F1SpiritApp *game; KEYBOARDSTATE *k; int time, act_time; SDL_Event event; bool quit = false; bool need_to_redraw = true; #ifdef F1SPIRIT_DEBUG_MESSAGES output_debug_message("Application started\n"); #endif #ifdef HAVE_GLES fullscreen = true; #endif screen_sfc = initialization((fullscreen ? SDL_FULLSCREEN : 0)); if (screen_sfc == 0) return 0; k = new KEYBOARDSTATE(); game = new F1SpiritApp(); #if 0//ndef HAVE_GLES // why recreating the context ??? if (fullscreen) { #ifdef HAVE_GLES EGL_Close(); screen_sfc = SDL_SetVideoMode((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y, COLOUR_DEPTH, (fullscreen ? SDL_FULLSCREEN : 0)); EGL_Open((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y); #else screen_sfc = SDL_SetVideoMode((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y, COLOUR_DEPTH, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)); #endif SDL_WM_SetCaption(application_name, 0); SDL_ShowCursor(SDL_DISABLE); reload_textures++; #ifndef HAVE_GLES 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_DOUBLEBUFFER, 1); #endif } #endif time = init_time = SDL_GetTicks(); IMG_Init(IMG_INIT_JPG|IMG_INIT_PNG); while (!quit) { while ( SDL_PollEvent( &event ) ) { switch ( event.type ) { /* Keyboard event */ case SDL_KEYDOWN: #ifdef __APPLE__ if (event.key.keysym.sym == SDLK_q) { SDLMod modifiers; modifiers = SDL_GetModState(); if ((modifiers &KMOD_META) != 0) { quit = true; } } #else if (event.key.keysym.sym == SDLK_F12) { quit = true; } #endif if (event.key.keysym.sym == SDLK_F10) { game->save_configuration("f1spirit.cfg"); game->load_configuration("f1spirit.cfg"); } #ifdef _WIN32 if (event.key.keysym.sym == SDLK_F4) { SDLMod modifiers; modifiers = SDL_GetModState(); if ((modifiers&KMOD_ALT) != 0) quit = true; } #endif #ifdef __APPLE__ if (event.key.keysym.sym == SDLK_f) { SDLMod modifiers; modifiers = SDL_GetModState(); if ((modifiers&KMOD_META) != 0) { /* Toggle FULLSCREEN mode: */ if (fullscreen) fullscreen = false; else fullscreen = true; screen_sfc = SDL_SetVideoMode((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y, COLOUR_DEPTH, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)); calcMinMax((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y); SDL_WM_SetCaption(application_name, 0); SDL_ShowCursor(SDL_DISABLE); reload_textures++; 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_DOUBLEBUFFER, 1); } } #else if (event.key.keysym.sym == SDLK_RETURN) { SDLMod modifiers; modifiers = SDL_GetModState(); if ((modifiers&KMOD_ALT) != 0) { /* Toggle FULLSCREEN mode: */ if (fullscreen) fullscreen = false; else fullscreen = true; #ifndef HAVE_GLES #ifdef HAVE_GLES EGL_Close(); screen_sfc = SDL_SetVideoMode((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y, COLOUR_DEPTH, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)); EGL_Open((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y); #else screen_sfc = SDL_SetVideoMode((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y, COLOUR_DEPTH, SDL_OPENGL | (fullscreen ? SDL_FULLSCREEN : 0)); #endif calcMinMax((fullscreen)?desktopW:SCREEN_X, (fullscreen)?desktopH:SCREEN_Y); SDL_WM_SetCaption(application_name, 0); SDL_ShowCursor(SDL_DISABLE); reload_textures++; #ifndef HAVE_GLES 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); #endif #endif } } #endif if (event.key.keysym.sym == SDLK_f) { SDLMod modifiers; modifiers = SDL_GetModState(); if ((modifiers&KMOD_ALT) != 0) { /* toggle FPS mode: */ if (show_fps) show_fps = false; else show_fps = true; } } /* Keyboard event */ SDL_keysym *ks; ks = new SDL_keysym(); *ks = event.key.keysym; k->keyevents.Add(ks); break; /* SDL_QUIT event (window close) */ case SDL_QUIT: quit = true; break; } } act_time = SDL_GetTicks(); if (act_time - time >= REDRAWING_PERIOD) { int max_frame_step = 10; /* frames_per_sec_tmp+=1; if ((act_time-init_time)>=1000) { frames_per_sec=frames_per_sec_tmp; frames_per_sec_tmp=0; init_time=act_time; } // if */ // On PANDORA, let's target 25 fps... int min_frame=1; #ifdef PANDORA min_frame=2; #endif do { time += REDRAWING_PERIOD; if ((act_time - time) > 10*REDRAWING_PERIOD) time = act_time; /* cycle */ k->cycle(); if (!game->cycle(k)) quit = true; need_to_redraw = true; k->keyevents.Delete(); act_time = SDL_GetTicks(); max_frame_step--; min_frame--; } while (((act_time - time >= REDRAWING_PERIOD) && (max_frame_step > 0)) || (min_frame > 0)); } /* Redraw */ if (need_to_redraw) { game->draw(); need_to_redraw = false; frames_per_sec_tmp += 1; } if ((act_time - init_time) >= 1000) { frames_per_sec = frames_per_sec_tmp; frames_per_sec_tmp = 0; init_time = act_time; } #ifndef PANDORA SDL_Delay(1); #endif } delete k; k = 0; delete game; game = 0; Stop_playback(); finalization(); #ifdef F1SPIRIT_DEBUG_MESSAGES output_debug_message("Application finished\n"); close_debug_messages(); #endif return 0; } /* main */
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; }
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; }