extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeApp.shutdown() -- begin"); NativeShutdown(); VFSShutdown(); net::Shutdown(); ILOG("NativeApp.shutdown() -- end"); }
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { if (useCPUThread && graphicsContext) { EmuThreadStop(); while (emuThreadState != (int)EmuThreadState::STOPPED) { graphicsContext->ThreadFrame(); } EmuThreadJoin(); } ILOG("NativeApp.shutdown() -- begin"); if (renderer_inited) { ILOG("Shutting down renderer"); // This will be from the wrong thread? :/ graphicsContext->Shutdown(); delete graphicsContext; graphicsContext = nullptr; renderer_inited = false; } else { ILOG("Not shutting down renderer - not initialized"); } NativeShutdown(); VFSShutdown(); while (frameCommands.size()) frameCommands.pop(); ILOG("NativeApp.shutdown() -- end"); }
Q_DECL_EXPORT #endif int main(int argc, char *argv[]) { #if defined(Q_OS_LINUX) && !defined(MAEMO) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); g_dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); #ifdef __SYMBIAN32__ const char *savegame_dir = "E:/PPSSPP/"; const char *assets_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) const char *savegame_dir = "/accounts/1000/shared/misc/"; const char *assets_dir = "app/native/assets/"; #elif defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; const char *assets_dir = "/opt/PPSSPP/"; #else const char *savegame_dir = "./"; const char *assets_dir = "./"; #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); #ifdef USING_GLES2 emugl = new MainUI(); emugl->resize(pixel_xres, pixel_yres); emugl->showFullScreen(); #endif #ifdef __SYMBIAN32__ // Set RunFast hardware mode for VFPv2. User::SetFloatingPointMode(EFpModeRunFast); // Disable screensaver QScopedPointer<QSystemScreenSaver> ssObject(new QSystemScreenSaver(emugl)); ssObject->setScreenSaverInhibit(); QScopedPointer<SymbianMediaKeys> mediakeys(new SymbianMediaKeys()); #endif QScopedPointer<QThread> thread(new QThread); QScopedPointer<MainAudio> audio(new MainAudio()); audio->moveToThread(thread.data()); QObject::connect(thread.data(), SIGNAL(started()), audio.data(), SLOT(run())); thread->start(); #ifdef QT_HAS_SDL SDLJoystick joy(true); joy.startEventLoop(); #endif int ret = a.exec(); thread->quit(); NativeShutdown(); net::Shutdown(); return ret; }
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeApp.shutdown() -- begin"); NativeShutdown(); VFSShutdown(); net::Shutdown(); ILOG("NativeApp.shutdown() -- end"); }
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { if (renderer_inited && useCPUThread && graphicsContext) { // Only used in Java EGL path. EmuThreadStop(); while (graphicsContext->ThreadFrame()) { continue; } EmuThreadJoin(); graphicsContext->ThreadEnd(); graphicsContext->ShutdownFromRenderThread(); } ILOG("NativeApp.shutdown() -- begin"); if (renderer_inited) { ILOG("Shutting down renderer"); // This will be from the wrong thread? :/ graphicsContext->Shutdown(); delete graphicsContext; graphicsContext = nullptr; renderer_inited = false; } else { ILOG("Not shutting down renderer - not initialized"); } NativeShutdown(); VFSShutdown(); while (frameCommands.size()) frameCommands.pop(); ILOG("NativeApp.shutdown() -- end"); }
void System_SendMessage(const char *command, const char *parameter) { // TODO: Cleaner exit if (!strcmp(command, "finish")) { NativeShutdown(); net::Shutdown(); exit(0); } }
Q_DECL_EXPORT #endif int main(int argc, char *argv[]) { #if defined(Q_OS_LINUX) && !defined(MAEMO) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); g_dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); std::string savegame_dir = "."; std::string assets_dir = "."; #if QT_VERSION > QT_VERSION_CHECK(5, 0, 0) savegame_dir = QStandardPaths::writableLocation(QStandardPaths::HomeLocation).toStdString(); assets_dir = QStandardPaths::writableLocation(QStandardPaths::DataLocation).toStdString(); #elif defined(__SYMBIAN32__) savegame_dir = "E:/PPSSPP"; assets_dir = "E:/PPSSPP"; #elif defined(BLACKBERRY) savegame_dir = "/accounts/1000/shared/misc"; assets_dir = "app/native/assets"; #elif defined(MAEMO) savegame_dir = "/home/user/MyDocs/PPSSPP"; assets_dir = "/opt/PPSSPP"; #endif savegame_dir += "/"; assets_dir += "/"; bool fullscreenCLI=false; for (int i = 1; i < argc; i++) { if (!strcmp(argv[i],"--fullscreen")) fullscreenCLI=true; } NativeInit(argc, (const char **)argv, savegame_dir.c_str(), assets_dir.c_str(), nullptr, fullscreenCLI); int ret = mainInternal(a); #ifndef MOBILE_DEVICE exit(0); #endif NativeShutdownGraphics(); #ifdef SDL SDL_PauseAudio(1); SDL_CloseAudio(); #endif NativeShutdown(); net::Shutdown(); return ret; }
void BlackberryMain::endMain() { screen_stop_events(screen_cxt); bps_shutdown(); NativeShutdownGraphics(); delete audio; NativeShutdown(); killDisplays(); net::Shutdown(); screen_destroy_context(screen_cxt); }
Q_DECL_EXPORT int main(int argc, char *argv[]) { #ifdef Q_WS_X11 QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); g_dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); #ifdef __SYMBIAN32__ char* savegame_dir = "E:/PPSSPP/"; char* assets_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) char* savegame_dir = "/accounts/1000/shared/misc/"; char* assets_dir = "app/native/assets/"; #elif defined(MEEGO_EDITION_HARMATTAN) char* savegame_dir = "/home/user/MyDocs/PPSSPP/"; QDir myDocs("/home/user/MyDocs/"); if (!myDocs.exists("PPSSPP")) myDocs.mkdir("PPSSPP"); char* assets_dir = "/opt/PPSSPP/"; #else char* savegame_dir = "./"; char* assets_dir = "./"; #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); #if !defined(Q_WS_X11) || defined(ARM) MainUI w; w.resize(pixel_xres, pixel_yres); w.showFullScreen(); #endif #ifdef __SYMBIAN32__ // Set RunFast hardware mode for VFPv2. User::SetFloatingPointMode(EFpModeRunFast); // Disable screensaver QSystemScreenSaver *ssObject = new QSystemScreenSaver(&w); ssObject->setScreenSaverInhibit(); #endif MainAudio *audio = new MainAudio(); int ret = a.exec(); delete audio; NativeShutdown(); net::Shutdown(); return ret; }
int main(int argc, char *argv[]) { #ifdef Q_WS_X11 QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); // Lock orientation to landscape on Symbian #ifdef __SYMBIAN32__ QT_TRAP_THROWING(dynamic_cast<CAknAppUi*>(CEikonEnv::Static()->AppUi())->SetOrientationL(CAknAppUi::EAppUiOrientationLandscape)); #endif QSize res = QApplication::desktop()->screenGeometry().size(); #ifdef USING_GLES2 if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); #else // Set resolution to half of the monitor on desktop systems pixel_xres = res.width() / 2; pixel_yres = res.height() / 2; #endif float dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); net::Init(); #ifdef __SYMBIAN32__ NativeInit(argc, (const char **)argv, "E:/PPSSPP/", "E:", "BADCOFFEE"); #elif defined(BLACKBERRY) NativeInit(argc, (const char **)argv, "data/", "/tmp", "BADCOFFEE"); #else NativeInit(argc, (const char **)argv, "./", "/tmp", "BADCOFFEE"); #endif #if defined(Q_WS_X11) && !defined(USING_GLES2) MainWindow mainWindow; mainWindow.show(); #else MainUI w(dpi_scale); w.resize(pixel_xres, pixel_yres); #ifdef USING_GLES2 w.showFullScreen(); #else w.show(); #endif #endif MainAudio *audio = new MainAudio(); int ret = a.exec(); delete audio; NativeShutdown(); net::Shutdown(); return ret; }
extern "C" void Java_com_henrikrydgard_libnative_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeApp.shutdown() -- begin"); if (use_opensl_audio) { AndroidAudio_Shutdown(); } if (renderer_inited) { NativeShutdownGraphics(); renderer_inited = false; } NativeShutdown(); ILOG("VFSShutdown."); VFSShutdown(); net::Shutdown(); ILOG("NativeApp.shutdown() -- end"); }
Q_DECL_EXPORT #endif int main(int argc, char *argv[]) { #if defined(Q_OS_LINUX) && !defined(MAEMO) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); g_dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); #ifdef __SYMBIAN32__ const char *savegame_dir = "E:/PPSSPP/"; const char *assets_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) const char *savegame_dir = "/accounts/1000/shared/misc/"; const char *assets_dir = "app/native/assets/"; #elif defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; const char *assets_dir = "/opt/PPSSPP/"; #elif defined(ANDROID) const char *savegame_dir = QStandardPaths::standardLocations(QStandardPaths::HomeLocation).at(0).toStdString().c_str(); const char *assets_dir = QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).at(0).toStdString().c_str(); setenv("QT_USE_ANDROID_NATIVE_DIALOGS", "1", 1); // Which Qt version does this need? #else const char *savegame_dir = "./"; const char *assets_dir = "./"; #endif for(int i=1; i< argc; ++i) { if(!strcmp(argv[i],"--fullscreen")) { g_Config.bFullScreen = true; } } NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); int ret = mainInternal(a); NativeShutdown(); net::Shutdown(); return ret; }
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { ILOG("NativeApp.shutdown() -- begin"); if (renderer_inited) { ILOG("Shutting down renderer"); graphicsContext->Shutdown(); delete graphicsContext; graphicsContext = nullptr; renderer_inited = false; } else { ILOG("Not shutting down renderer - not initialized"); } NativeShutdown(); VFSShutdown(); while (frameCommands.size()) frameCommands.pop(); ILOG("NativeApp.shutdown() -- end"); }
int main(int argc, char *argv[]) { #ifdef Q_WS_X11 QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); #ifdef __SYMBIAN32__ // Set RunFast hardware mode for VFPv2. Denormalised values are treated as 0. NaN used for all NaN situations. User::SetFloatingPointMode(EFpModeRunFast); #endif QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); float dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); net::Init(); #ifdef __SYMBIAN32__ char* savegame_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) char* savegame_dir = "data/"; #else char* savegame_dir = "./"; #endif NativeInit(argc, (const char **)argv, savegame_dir, QDir::tempPath().toStdString().c_str(), "BADCOFFEE"); #ifndef Q_WS_X11 MainUI w(dpi_scale); w.setAttribute(Qt::WA_LockLandscapeOrientation); w.resize(pixel_xres, pixel_yres); w.showFullScreen(); #endif MainAudio *audio = new MainAudio(); int ret = a.exec(); delete audio; NativeShutdown(); net::Shutdown(); return ret; }
int Shutdown(int errorcode, struct cfgoptions *arg) { if (arg->options & NOACTION) { Logmsg(LOG_DEBUG, "shutdown() errorcode=%i, kexec=%s", errorcode, arg->options & KEXEC ? "true" : "false"); return 0; } if (errorcode != WECMDREBOOT && errorcode != WECMDRESET) { char buf[64] = { "\0" }; snprintf(buf, sizeof(buf), "%d\n", errorcode); if (Spawn (arg->repairBinTimeout, arg, arg->exepathname, arg->exepathname, buf, NULL) == 0) return 0; } EndDaemon(arg, true); //point of no return return NativeShutdown(errorcode, arg->options & KEXEC ? 1 : 0); }
extern "C" void Java_org_ppsspp_ppsspp_NativeApp_shutdown(JNIEnv *, jclass) { if (renderer_inited && useCPUThread && graphicsContext) { // Only used in Java EGL path. EmuThreadStop("shutdown"); ILOG("BeginAndroidShutdown"); graphicsContext->BeginAndroidShutdown(); // Skipping GL calls, the old context is gone. while (graphicsContext->ThreadFrame()) { ILOG("graphicsContext->ThreadFrame executed to clear buffers"); } ILOG("Joining emuthread"); EmuThreadJoin(); ILOG("Joined emuthread"); graphicsContext->ThreadEnd(); graphicsContext->ShutdownFromRenderThread(); ILOG("Graphics context now shut down from NativeApp_shutdown"); } ILOG("NativeApp.shutdown() -- begin"); if (renderer_inited) { ILOG("Shutting down renderer"); // This will be from the wrong thread? :/ graphicsContext->Shutdown(); delete graphicsContext; graphicsContext = nullptr; renderer_inited = false; } else { ILOG("Not shutting down renderer - not initialized"); } NativeShutdown(); VFSShutdown(); while (frameCommands.size()) frameCommands.pop(); ILOG("NativeApp.shutdown() -- end"); }
Q_DECL_EXPORT #endif int main(int argc, char *argv[]) { #if defined(Q_OS_LINUX) && !defined(MAEMO) QApplication::setAttribute(Qt::AA_X11InitThreads, true); #endif QApplication a(argc, argv); QSize res = QApplication::desktop()->screenGeometry().size(); if (res.width() < res.height()) res.transpose(); pixel_xres = res.width(); pixel_yres = res.height(); g_dpi_scale = CalculateDPIScale(); dp_xres = (int)(pixel_xres * g_dpi_scale); dp_yres = (int)(pixel_yres * g_dpi_scale); net::Init(); #ifdef __SYMBIAN32__ const char *savegame_dir = "E:/PPSSPP/"; const char *assets_dir = "E:/PPSSPP/"; #elif defined(BLACKBERRY) const char *savegame_dir = "/accounts/1000/shared/misc/"; const char *assets_dir = "app/native/assets/"; #elif defined(MEEGO_EDITION_HARMATTAN) || defined(MAEMO) const char *savegame_dir = "/home/user/MyDocs/PPSSPP/"; const char *assets_dir = "/opt/PPSSPP/"; #else const char *savegame_dir = "./"; const char *assets_dir = "./"; #endif NativeInit(argc, (const char **)argv, savegame_dir, assets_dir, "BADCOFFEE"); int ret = mainInternal(a); NativeShutdown(); net::Shutdown(); return ret; }
void MenuScreen::render() { UIShader_Prepare(); UIBegin(UIShader_Get()); DrawBackground(1.0f); double xoff = 150 - frames_ * frames_ * 0.4f; if (xoff < -20) xoff = -20; if (frames_ > 200) // seems the above goes nuts after a while... xoff = -20; int w = LARGE_BUTTON_WIDTH + 60; ui_draw2d.DrawTextShadow(UBUNTU48, "PPSSPP", dp_xres + xoff - w/2, 75, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_BOTTOM); ui_draw2d.SetFontScale(0.7f, 0.7f); ui_draw2d.DrawTextShadow(UBUNTU24, PPSSPP_GIT_VERSION, dp_xres + xoff, 85, 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_BOTTOM); ui_draw2d.SetFontScale(1.0f, 1.0f); VLinear vlinear(dp_xres + xoff, 100, 20); I18NCategory *m = GetI18NCategory("MainMenu"); if (UIButton(GEN_ID, vlinear, w, 0, m->T("Load", "Load..."), ALIGN_RIGHT)) { #if defined(USING_QT_UI) && !defined(MEEGO_EDITION_HARMATTAN) QString fileName = QFileDialog::getOpenFileName(NULL, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf)"); if (QFile::exists(fileName)) { QDir newPath; g_Config.currentDirectory = newPath.filePath(fileName).toStdString(); g_Config.Save(); screenManager()->switchScreen(new EmuScreen(fileName.toStdString())); } #elif _WIN32 MainWindow::BrowseAndBoot(""); #else FileSelectScreenOptions options; options.allowChooseDirectory = true; options.filter = "iso:cso:pbp:elf:prx:"; options.folderIcon = I_ICON_FOLDER; options.iconMapping["iso"] = I_ICON_UMD; options.iconMapping["cso"] = I_ICON_UMD; options.iconMapping["pbp"] = I_ICON_EXE; options.iconMapping["elf"] = I_ICON_EXE; screenManager()->switchScreen(new FileSelectScreen(options)); #endif UIReset(); } if (UIButton(GEN_ID, vlinear, w, 0, m->T("Settings"), ALIGN_RIGHT)) { screenManager()->push(new SettingsScreen(), 0); UIReset(); } if (UIButton(GEN_ID, vlinear, w, 0, m->T("Credits"), ALIGN_RIGHT)) { screenManager()->switchScreen(new CreditsScreen()); UIReset(); } if (UIButton(GEN_ID, vlinear, w, 0, m->T("Exit"), ALIGN_RIGHT)) { // TODO: Save when setting changes, rather than when we quit NativeShutdown(); // TODO: Need a more elegant way to quit #ifdef _WIN32 ExitProcess(0); #else exit(0); #endif } if (UIButton(GEN_ID, vlinear, w, 0, "www.ppsspp.org", ALIGN_RIGHT)) { LaunchBrowser("http://www.ppsspp.org/"); } int recentW = 350; if (g_Config.recentIsos.size()) { ui_draw2d.DrawText(UBUNTU24, m->T("Recent"), -xoff, 80, 0xFFFFFFFF, ALIGN_BOTTOMLEFT); } int spacing = 15; float textureButtonWidth = 144; float textureButtonHeight = 80; if (dp_yres < 480) spacing = 8; // On small screens, we can't fit four vertically. if (100 + spacing * 6 + textureButtonHeight * 4 > dp_yres) { textureButtonHeight = (dp_yres - 100 - spacing * 6) / 4; textureButtonWidth = (textureButtonHeight / 80) * 144; } VGrid vgrid_recent(-xoff, 100, std::min(dp_yres-spacing*2, 480), spacing, spacing); for (size_t i = 0; i < g_Config.recentIsos.size(); i++) { std::string filename; std::string rec = g_Config.recentIsos[i]; for (size_t j = 0; j < rec.size(); j++) if (rec[j] == '\\') rec[j] = '/'; SplitPath(rec, nullptr, &filename, nullptr); UIContext *ctx = screenManager()->getUIContext(); // This might create a texture so we must flush first. UIFlush(); GameInfo *ginfo = g_gameInfoCache.GetInfo(g_Config.recentIsos[i], false); if (ginfo && ginfo->fileType != FILETYPE_PSP_ELF) { u32 color; if (ginfo->iconTexture == 0) { color = 0; } else { color = whiteAlpha(ease((time_now_d() - ginfo->timeIconWasLoaded) * 2)); } if (UITextureButton(ctx, (int)GEN_ID_LOOP(i), vgrid_recent, textureButtonWidth, textureButtonHeight, ginfo->iconTexture, ALIGN_LEFT, color, I_DROP_SHADOW)) { UIEnd(); screenManager()->switchScreen(new EmuScreen(g_Config.recentIsos[i])); return; } } else { if (UIButton((int)GEN_ID_LOOP(i), vgrid_recent, textureButtonWidth, textureButtonHeight, filename.c_str(), ALIGN_LEFT)) { UIEnd(); screenManager()->switchScreen(new EmuScreen(g_Config.recentIsos[i])); return; } } } #if defined(_DEBUG) & defined(_WIN32) // Print the current dp_xres/yres in the corner. For UI scaling testing - just // resize to 800x480 to get an idea of what it will look like on a Nexus S. ui_draw2d.SetFontScale(0.4, 0.4); char temptext[64]; sprintf(temptext, "%ix%i", dp_xres, dp_yres); ui_draw2d.DrawTextShadow(UBUNTU24, temptext, 5, dp_yres-5, 0xFFFFFFFF, ALIGN_BOTTOMLEFT); ui_draw2d.SetFontScale(1.0, 1.0); #endif DrawWatermark(); UIEnd(); }
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; }
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; }
void MenuScreen::render() { UIShader_Prepare(); UIBegin(); DrawBackground(1.0f); double xoff = 150 - frames_ * frames_ * 0.4f; if (xoff < -20) xoff = -20; if (frames_ > 200) // seems the above goes nuts after a while... xoff = -20; int w = LARGE_BUTTON_WIDTH + 40; ui_draw2d.DrawTextShadow(UBUNTU48, "PPSSPP", dp_xres + xoff - w/2, 75, 0xFFFFFFFF, ALIGN_HCENTER | ALIGN_BOTTOM); ui_draw2d.SetFontScale(0.7f, 0.7f); ui_draw2d.DrawTextShadow(UBUNTU24, PPSSPP_GIT_VERSION, dp_xres + xoff, 85, 0xFFFFFFFF, ALIGN_RIGHT | ALIGN_BOTTOM); ui_draw2d.SetFontScale(1.0f, 1.0f); VLinear vlinear(dp_xres + xoff, 100, 20); if (UIButton(GEN_ID, vlinear, w, "Load...", ALIGN_RIGHT)) { #if defined(USING_QT_UI) QString fileName = QFileDialog::getOpenFileName(NULL, "Load ROM", g_Config.currentDirectory.c_str(), "PSP ROMs (*.iso *.cso *.pbp *.elf)"); if (QFile::exists(fileName)) { QDir newPath; g_Config.currentDirectory = newPath.filePath(fileName).toStdString(); g_Config.Save(); screenManager()->switchScreen(new EmuScreen(fileName.toStdString())); } #else FileSelectScreenOptions options; options.allowChooseDirectory = true; options.filter = "iso:cso:pbp:elf:prx:"; options.folderIcon = I_ICON_FOLDER; options.iconMapping["iso"] = I_ICON_UMD; options.iconMapping["cso"] = I_ICON_UMD; options.iconMapping["pbp"] = I_ICON_EXE; options.iconMapping["elf"] = I_ICON_EXE; screenManager()->switchScreen(new FileSelectScreen(options)); #endif UIReset(); } if (UIButton(GEN_ID, vlinear, w, "Settings", ALIGN_RIGHT)) { screenManager()->push(new SettingsScreen(), 0); UIReset(); } if (UIButton(GEN_ID, vlinear, w, "Credits", ALIGN_RIGHT)) { screenManager()->switchScreen(new CreditsScreen()); UIReset(); } if (UIButton(GEN_ID, vlinear, w, "Exit", ALIGN_RIGHT)) { // TODO: Save when setting changes, rather than when we quit NativeShutdown(); // TODO: Need a more elegant way to quit exit(0); } if (UIButton(GEN_ID, vlinear, w, "www.ppsspp.org", ALIGN_RIGHT)) { LaunchBrowser("http://www.ppsspp.org/"); } DrawWatermark(); UIEnd(); glsl_bind(UIShader_Get()); ui_draw2d.Flush(UIShader_Get()); }
unsigned int WINAPI TheThread(void *) { _InterlockedExchange(&emuThreadReady, THREAD_INIT); setCurrentThreadName("Emu"); // And graphics... host = new WindowsHost(MainWindow::GetHInstance(), MainWindow::GetHWND(), MainWindow::GetDisplayHWND()); host->SetWindowTitle(nullptr); // Convert the command-line arguments to Unicode, then to proper UTF-8 // (the benefit being that we don't have to pollute the UI project with win32 ifdefs and lots of Convert<whatever>To<whatever>). // This avoids issues with PPSSPP inadvertently destroying paths with Unicode glyphs // (using the ANSI args resulted in Japanese/Chinese glyphs being turned into question marks, at least for me..). // -TheDax std::vector<std::wstring> wideArgs = GetWideCmdLine(); std::vector<std::string> argsUTF8; for (auto& string : wideArgs) { argsUTF8.push_back(ConvertWStringToUTF8(string)); } std::vector<const char *> args; for (auto& string : argsUTF8) { args.push_back(string.c_str()); } bool performingRestart = NativeIsRestarting(); NativeInit(static_cast<int>(args.size()), &args[0], "1234", "1234", nullptr); host->UpdateUI(); GraphicsContext *graphicsContext = nullptr; std::string error_string; if (!host->InitGraphics(&error_string, &graphicsContext)) { // Before anything: are we restarting right now? if (performingRestart) { // Okay, switching graphics didn't work out. Probably a driver bug - fallback to restart. // This happens on NVIDIA when switching OpenGL -> Vulkan. g_Config.Save(); W32Util::ExitAndRestart(); } I18NCategory *err = GetI18NCategory("Error"); Reporting::ReportMessage("Graphics init error: %s", error_string.c_str()); const char *defaultErrorVulkan = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to OpenGL?\n\nError message:"; const char *defaultErrorOpenGL = "Failed initializing graphics. Try upgrading your graphics drivers.\n\nWould you like to try switching to DirectX 9?\n\nError message:"; const char *defaultErrorDirect3D9 = "Failed initializing graphics. Try upgrading your graphics drivers and directx 9 runtime.\n\nWould you like to try switching to OpenGL?\n\nError message:"; const char *genericError; int nextBackend = GPU_BACKEND_DIRECT3D9; switch (g_Config.iGPUBackend) { case GPU_BACKEND_DIRECT3D9: nextBackend = GPU_BACKEND_OPENGL; genericError = err->T("GenericDirect3D9Error", defaultErrorDirect3D9); break; case GPU_BACKEND_VULKAN: nextBackend = GPU_BACKEND_OPENGL; genericError = err->T("GenericVulkanError", defaultErrorVulkan); break; case GPU_BACKEND_OPENGL: default: nextBackend = GPU_BACKEND_DIRECT3D9; genericError = err->T("GenericOpenGLError", defaultErrorOpenGL); break; } std::string full_error = StringFromFormat("%s\n\n%s", genericError, error_string.c_str()); std::wstring title = ConvertUTF8ToWString(err->T("GenericGraphicsError", "Graphics Error")); bool yes = IDYES == MessageBox(0, ConvertUTF8ToWString(full_error).c_str(), title.c_str(), MB_ICONERROR | MB_YESNO); ERROR_LOG(BOOT, full_error.c_str()); if (yes) { // Change the config to the alternative and restart. g_Config.iGPUBackend = nextBackend; g_Config.Save(); W32Util::ExitAndRestart(); } // No safe way out without graphics. ExitProcess(1); } NativeInitGraphics(graphicsContext); NativeResized(); INFO_LOG(BOOT, "Done."); _dbg_update_(); if (coreState == CORE_POWERDOWN) { INFO_LOG(BOOT, "Exit before core loop."); goto shutdown; } _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); if (g_Config.bBrowse) PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); Core_EnableStepping(FALSE); while (GetUIState() != UISTATE_EXIT) { // We're here again, so the game quit. Restart Core_Run() which controls the UI. // This way they can load a new game. if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); Core_Run(graphicsContext); } shutdown: _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); NativeShutdownGraphics(); // NativeShutdown deletes the graphics context through host->ShutdownGraphics(). NativeShutdown(); _InterlockedExchange(&emuThreadReady, THREAD_END); return 0; }
unsigned int WINAPI TheThread(void *) { _InterlockedExchange(&emuThreadReady, THREAD_INIT); setCurrentThreadName("EmuThread"); // Native overwrites host. Can't allow that. Host *oldHost = host; UpdateScreenScale(); NativeInit(__argc, (const char **)__argv, "1234", "1234", "1234"); Host *nativeHost = host; host = oldHost; host->UpdateUI(); //Check Colour depth HDC dc = GetDC(NULL); u32 colour_depth = GetDeviceCaps(dc, BITSPIXEL); ReleaseDC(NULL, dc); if (colour_depth != 32) { MessageBoxA(0, "Please switch your display to 32-bit colour mode", "OpenGL Error", MB_OK); ExitProcess(1); } std::string error_string; if (!host->InitGL(&error_string)) { Reporting::ReportMessage("OpenGL init error: %s", error_string.c_str()); std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str()); MessageBoxA(0, full_error.c_str(), "OpenGL Error", MB_OK | MB_ICONERROR); ERROR_LOG(BOOT, full_error.c_str()); // No safe way out without OpenGL. ExitProcess(1); } NativeInitGraphics(); INFO_LOG(BOOT, "Done."); _dbg_update_(); if (coreState == CORE_POWERDOWN) { INFO_LOG(BOOT, "Exit before core loop."); goto shutdown; } _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); if (g_Config.bBrowse) PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); Core_EnableStepping(FALSE); while (globalUIState != UISTATE_EXIT) { // We're here again, so the game quit. Restart Core_Run() which controls the UI. // This way they can load a new game. if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); Core_Run(); } shutdown: _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); NativeShutdownGraphics(); host->ShutdownSound(); host = nativeHost; NativeShutdown(); host = oldHost; host->ShutdownGL(); _InterlockedExchange(&emuThreadReady, THREAD_END); return 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; }
unsigned int WINAPI TheThread(void *) { _InterlockedExchange(&emuThreadReady, THREAD_INIT); setCurrentThreadName("Emu"); // And graphics... // Native overwrites host. Can't allow that. Host *oldHost = host; // Convert the command-line arguments to Unicode, then to proper UTF-8 // (the benefit being that we don't have to pollute the UI project with win32 ifdefs and lots of Convert<whatever>To<whatever>). // This avoids issues with PPSSPP inadvertently destroying paths with Unicode glyphs // (using the ANSI args resulted in Japanese/Chinese glyphs being turned into question marks, at least for me..). // -TheDax std::vector<std::wstring> wideArgs = GetWideCmdLine(); std::vector<std::string> argsUTF8; for (auto& string : wideArgs) { argsUTF8.push_back(ConvertWStringToUTF8(string)); } std::vector<const char *> args; for (auto& string : argsUTF8) { args.push_back(string.c_str()); } NativeInit(static_cast<int>(args.size()), &args[0], "1234", "1234", "1234"); Host *nativeHost = host; host = oldHost; host->UpdateUI(); //Check Colour depth HDC dc = GetDC(NULL); u32 colour_depth = GetDeviceCaps(dc, BITSPIXEL); ReleaseDC(NULL, dc); if (colour_depth != 32){ MessageBox(0, L"Please switch your display to 32-bit colour mode", L"OpenGL Error", MB_OK); ExitProcess(1); } std::string error_string; if (!host->InitGraphics(&error_string)) { Reporting::ReportMessage("Graphics init error: %s", error_string.c_str()); std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str()); MessageBox(0, ConvertUTF8ToWString(full_error).c_str(), L"OpenGL Error", MB_OK | MB_ICONERROR); ERROR_LOG(BOOT, full_error.c_str()); // No safe way out without OpenGL. ExitProcess(1); } NativeInitGraphics(); NativeResized(); INFO_LOG(BOOT, "Done."); _dbg_update_(); if (coreState == CORE_POWERDOWN) { INFO_LOG(BOOT, "Exit before core loop."); goto shutdown; } _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); if (g_Config.bBrowse) PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); Core_EnableStepping(FALSE); while (GetUIState() != UISTATE_EXIT) { // We're here again, so the game quit. Restart Core_Run() which controls the UI. // This way they can load a new game. if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); Core_Run(); } shutdown: _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); NativeShutdownGraphics(); host->ShutdownSound(); host = nativeHost; NativeShutdown(); host = oldHost; host->ShutdownGraphics(); _InterlockedExchange(&emuThreadReady, THREAD_END); return 0; }
unsigned int WINAPI TheThread(void *) { _InterlockedExchange(&emuThreadReady, THREAD_INIT); setCurrentThreadName("EmuThread"); std::string memstick, flash0; GetSysDirectories(memstick, flash0); // Native overwrites host. Can't allow that. Host *oldHost = host; UpdateScreenScale(); NativeInit(__argc, (const char **)__argv, memstick.c_str(), memstick.c_str(), "1234"); Host *nativeHost = host; host = oldHost; host->UpdateUI(); std::string error_string; if (!host->InitGL(&error_string)) { Reporting::ReportMessage("OpenGL init error: %s", error_string.c_str()); std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str()); MessageBoxA(0, full_error.c_str(), "OpenGL Error", MB_OK | MB_ICONERROR); ERROR_LOG(BOOT, full_error.c_str()); goto shutdown; } NativeInitGraphics(); INFO_LOG(BOOT, "Done."); _dbg_update_(); if (coreState == CORE_POWERDOWN) { INFO_LOG(BOOT, "Exit before core loop."); goto shutdown; } _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); if (g_Config.bBrowse) { PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); //MainWindow::BrowseAndBoot(""); } Core_EnableStepping(FALSE); while (globalUIState != UISTATE_EXIT) { Core_Run(); // We're here again, so the game quit. Restart Core_Run() which controls the UI. // This way they can load a new game. Core_UpdateState(CORE_RUNNING); } shutdown: _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); NativeShutdownGraphics(); host = nativeHost; NativeShutdown(); host = oldHost; host->ShutdownGL(); _InterlockedExchange(&emuThreadReady, THREAD_END); //The CPU should return when a game is stopped and cleanup should be done here, //so we can restart the plugins (or load new ones) for the next game 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 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; }
// Entry Point int main(int argc, char *argv[]) { static screen_context_t screen_cxt; // Receive events from window manager screen_create_context(&screen_cxt, 0); //Initialise Blackberry Platform Services bps_initialize(); net::Init(); init_GLES2(screen_cxt); #ifdef BLACKBERRY10 // Dev Alpha: 1280x768, 4.2", 356DPI, 0.6f scale int dpi; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_DPI, &dpi); #else // Playbook: 1024x600, 7", 170DPI, 1.25f scale int screen_phys_size[2]; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_PHYSICAL_SIZE, screen_phys_size); int screen_resolution[2]; screen_get_display_property_iv(screen_disp, SCREEN_PROPERTY_SIZE, screen_resolution); double diagonal_pixels = sqrt(screen_resolution[0] * screen_resolution[0] + screen_resolution[1] * screen_resolution[1]); double diagonal_inches = 0.0393700787 * sqrt(screen_phys_size[0] * screen_phys_size[0] + screen_phys_size[1] * screen_phys_size[1]); int dpi = (int)(diagonal_pixels / diagonal_inches + 0.5); #endif float dpi_scale = 213.6f / dpi; dp_xres = (int)(pixel_xres * dpi_scale); dp_yres = (int)(pixel_yres * dpi_scale); NativeInit(argc, (const char **)argv, "data/", "/accounts/1000/shared", "BADCOFFEE"); NativeInitGraphics(); screen_request_events(screen_cxt); navigator_request_events(0); dialog_request_events(0); #ifdef BLACKBERRY10 vibration_request_events(0); #endif BlackberryAudio* audio = new BlackberryAudio(); InputState input_state; bool running = true; while (running) { input_state.mouse_valid = false; input_state.accelerometer_valid = false; SimulateGamepad(&input_state); while (true) { // Handle Blackberry events bps_event_t *event = NULL; bps_get_event(&event, 0); if (event == NULL) break; // Ran out of events int domain = bps_event_get_domain(event); if (domain == screen_get_domain()) { int screen_val, buttons, pointerId; int pair[2]; screen_event_t screen_event = screen_event_get_event(event); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TYPE, &screen_val); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_SOURCE_POSITION, pair); screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_TOUCH_ID, &pointerId); input_state.mouse_valid = true; switch(screen_val) { // Touchscreen case SCREEN_EVENT_MTOUCH_TOUCH: case SCREEN_EVENT_MTOUCH_RELEASE: // Up, down input_state.pointer_down[pointerId] = (screen_val == SCREEN_EVENT_MTOUCH_TOUCH); case SCREEN_EVENT_MTOUCH_MOVE: input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; 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[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = true; } else if (input_state.pointer_down[pointerId]) { // Up input_state.pointer_x[pointerId] = pair[0] * dpi_scale; input_state.pointer_y[pointerId] = pair[1] * dpi_scale; input_state.pointer_down[pointerId] = false; } 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); if (flags & (KEY_DOWN | KEY_SYM_VALID)) { for (int b = 0; b < 14; b++) { if (value == buttonMappings[b]) input_state.pad_buttons |= (1<<b); } } break; } } else if (domain == navigator_get_domain()) { switch(bps_event_get_code(event)) { case NAVIGATOR_BACK: case NAVIGATOR_SWIPE_DOWN: input_state.pad_buttons |= PAD_BUTTON_MENU; break; case NAVIGATOR_EXIT: running = false; break; } } } UpdateInputState(&input_state); NativeUpdate(input_state); EndInputState(&input_state); NativeRender(); // On Blackberry, this handles VSync for us eglSwapBuffers(egl_disp, egl_surf); } screen_stop_events(screen_cxt); bps_shutdown(); NativeShutdownGraphics(); delete audio; NativeShutdown(); kill_GLES2(); net::Shutdown(); screen_destroy_context(screen_cxt); exit(0); return 0; }