void EmuScreen::sendMessage(const char *message, const char *value) { // External commands, like from the Windows UI. if (!strcmp(message, "pause")) { screenManager()->push(new GamePauseScreen(gamePath_)); } else if (!strcmp(message, "stop")) { // We will push MainScreen in update(). PSP_Shutdown(); bootPending_ = false; invalid_ = true; host->UpdateDisassembly(); } else if (!strcmp(message, "reset")) { PSP_Shutdown(); bootPending_ = true; invalid_ = true; host->UpdateDisassembly(); std::string resetError; if (!PSP_InitStart(PSP_CoreParameter(), &resetError)) { ELOG("Error resetting: %s", resetError.c_str()); screenManager()->switchScreen(new MainScreen()); System_SendMessage("event", "failstartgame"); return; } } else if (!strcmp(message, "boot")) { const char *ext = strrchr(value, '.'); if (!strcmp(ext, ".ppst")) { SaveState::Load(value, &AfterStateLoad); } else { PSP_Shutdown(); bootPending_ = true; bootGame(value); } } else if (!strcmp(message, "control mapping")) { UpdateUIState(UISTATE_MENU); screenManager()->push(new ControlMappingScreen()); } else if (!strcmp(message, "settings")) { UpdateUIState(UISTATE_MENU); screenManager()->push(new GameSettingsScreen(gamePath_)); } else if (!strcmp(message, "gpu resized") || !strcmp(message, "gpu clear cache")) { if (gpu) { gpu->ClearCacheNextFrame(); gpu->Resized(); } Reporting::UpdateConfig(); RecreateViews(); } else if (!strcmp(message, "gpu dump next frame")) { if (gpu) gpu->DumpNextFrame(); } else if (!strcmp(message, "clear jit")) { currentMIPS->ClearJitCache(); if (PSP_IsInited()) { currentMIPS->UpdateCore(g_Config.bJit ? CPU_JIT : CPU_INTERPRETER); } } else if (!strcmp(message, "window minimized")) { if (!strcmp(value, "true")) { gstate_c.skipDrawReason |= SKIPDRAW_WINDOW_MINIMIZED; } else { gstate_c.skipDrawReason &= ~SKIPDRAW_WINDOW_MINIMIZED; } } }
void EmuScreen::sendMessage(const char *message, const char *value) { // External commands, like from the Windows UI. if (!strcmp(message, "pause")) { screenManager()->push(new GamePauseScreen(gamePath_)); } else if (!strcmp(message, "stop")) { screenManager()->switchScreen(new MainScreen()); } else if (!strcmp(message, "reset")) { PSP_Shutdown(); std::string resetError; if (!PSP_Init(PSP_CoreParameter(), &resetError)) { ELOG("Error resetting: %s", resetError.c_str()); screenManager()->switchScreen(new MainScreen()); return; } host->BootDone(); host->UpdateDisassembly(); #ifdef _WIN32 if (g_Config.bAutoRun) { Core_EnableStepping(false); } else { Core_EnableStepping(true); } #endif } else if (!strcmp(message, "boot")) { PSP_Shutdown(); bootGame(value); } }
void EmuScreen::sendMessage(const char *message, const char *value) { // External commands, like from the Windows UI. if (!strcmp(message, "pause")) { screenManager()->push(new GamePauseScreen(gamePath_)); } else if (!strcmp(message, "stop")) { // We will push MainScreen in update(). PSP_Shutdown(); booted_ = false; invalid_ = true; } else if (!strcmp(message, "reset")) { PSP_Shutdown(); booted_ = false; invalid_ = true; std::string resetError; if (!PSP_InitStart(PSP_CoreParameter(), &resetError)) { ELOG("Error resetting: %s", resetError.c_str()); screenManager()->switchScreen(new MainScreen()); System_SendMessage("event", "failstartgame"); return; } #ifndef MOBILE_DEVICE if (g_Config.bAutoRun) { Core_EnableStepping(false); } else { Core_EnableStepping(true); } #endif } else if (!strcmp(message, "boot")) { PSP_Shutdown(); booted_ = false; bootGame(value); } else if (!strcmp(message, "control mapping")) { UpdateUIState(UISTATE_MENU); screenManager()->push(new ControlMappingScreen()); } else if (!strcmp(message, "settings")) { UpdateUIState(UISTATE_MENU); screenManager()->push(new GameSettingsScreen(gamePath_)); } else if (!strcmp(message, "gpu resized") || !strcmp(message, "gpu clear cache")) { if (gpu) { gpu->ClearCacheNextFrame(); gpu->Resized(); } Reporting::UpdateConfig(); RecreateViews(); } else if (!strcmp(message, "gpu dump next frame")) { if (gpu) gpu->DumpNextFrame(); } else if (!strcmp(message, "clear jit")) { if (MIPSComp::jit) { MIPSComp::jit->ClearCache(); } } }
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) { INFO_LOG(BOOT, "PPSSPP %s", PPSSPP_GIT_VERSION); coreParameter = coreParam; coreParameter.errorString = ""; if (g_Config.bSeparateCPUThread) { Core_ListenShutdown(System_Wake); CPU_SetState(CPU_THREAD_PENDING); cpuThread = new std::thread(&CPU_RunLoop); cpuThread->detach(); CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady); } else { CPU_Init(); } bool success = coreParameter.fileToStart != ""; *error_string = coreParameter.errorString; if (success) { success = GPU_Init(); if (!success) { PSP_Shutdown(); *error_string = "Unable to initialize rendering engine."; } } return success; }
bool HandleFailure() { // Okay, first, let's give the rewind state a shot - maybe we can at least not reset entirely. // Even if this was a rewind, maybe we can still load a previous one. CChunkFileReader::Error result; do result = rewindStates.Restore(); while (result == CChunkFileReader::ERROR_BROKEN_STATE); if (result == CChunkFileReader::ERROR_NONE) { return true; } // We tried, our only remaining option is to reset the game. PSP_Shutdown(); std::string resetError; if (!PSP_Init(PSP_CoreParameter(), &resetError)) { ERROR_LOG(BOOT, "Error resetting: %s", resetError.c_str()); // TODO: This probably doesn't clean up well enough. Core_Stop(); return false; } host->BootDone(); host->UpdateDisassembly(); return false; }
void EmuScreen::sendMessage(const char *message, const char *value) { // External commands, like from the Windows UI. if (!strcmp(message, "pause")) { screenManager()->push(new GamePauseScreen(gamePath_)); } else if (!strcmp(message, "stop")) { // We will push MainScreen in update(). PSP_Shutdown(); } else if (!strcmp(message, "reset")) { PSP_Shutdown(); std::string resetError; if (!PSP_Init(PSP_CoreParameter(), &resetError)) { ELOG("Error resetting: %s", resetError.c_str()); screenManager()->switchScreen(new MainScreen()); return; } host->BootDone(); host->UpdateDisassembly(); #ifdef _WIN32 if (g_Config.bAutoRun) { Core_EnableStepping(false); } else { Core_EnableStepping(true); } #endif } else if (!strcmp(message, "boot")) { PSP_Shutdown(); bootGame(value); } else if (!strcmp(message, "control mapping")) { UpdateUIState(UISTATE_MENU); screenManager()->push(new ControlMappingScreen()); } else if (!strcmp(message, "settings")) { UpdateUIState(UISTATE_MENU); screenManager()->push(new GameSettingsScreen(gamePath_)); } else if (!strcmp(message, "gpu resized")) { if (gpu) gpu->Resized(); } else if (!strcmp(message, "gpu clear cache")) { if (gpu) gpu->ClearCacheNextFrame(); } else if (!strcmp(message, "gpu dump next frame")) { if (gpu) gpu->DumpNextFrame(); } }
EmuScreen::~EmuScreen() { if (!invalid_) { // If we were invalid, it would already be shutdown. host->PrepareShutdown(); PSP_Shutdown(); } }
void EmuScreen::checkPowerDown() { if (coreState == CORE_POWERDOWN && !PSP_IsIniting()) { if (PSP_IsInited()) { PSP_Shutdown(); } ILOG("SELF-POWERDOWN!"); screenManager()->switchScreen(new MainScreen()); bootPending_ = false; invalid_ = true; } }
void EmuThread::stopGame() { Core_Stop(); gameMutex->lock(); gameRunning = false; PSP_Shutdown(); // TODO //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 frames_ = 0; gameMutex->unlock(); }
bool PSP_InitUpdate(std::string *error_string) { if (pspIsInited || !pspIsIniting) { return true; } if (g_Config.bSeparateCPUThread && !CPU_IsReady()) { return false; } bool success = coreParameter.fileToStart != ""; *error_string = coreParameter.errorString; if (success) { success = GPU_Init(); if (!success) { PSP_Shutdown(); *error_string = "Unable to initialize rendering engine."; } } pspIsInited = success; pspIsIniting = false; return true; }
void EmuThread::Shutdown() { host->PrepareShutdown(); PSP_Shutdown(); FinalShutdown(); }
int main(int argc, const char* argv[]) { bool fullLog = false; bool useJit = false; bool fastInterpreter = false; bool autoCompare = false; bool useGraphics = false; const char *bootFilename = 0; const char *mountIso = 0; bool readMount = false; for (int i = 1; i < argc; i++) { if (readMount) { mountIso = argv[i]; readMount = false; continue; } if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--mount")) readMount = true; else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log")) fullLog = true; else if (!strcmp(argv[i], "-j")) useJit = true; else if (!strcmp(argv[i], "-f")) fastInterpreter = true; else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compare")) autoCompare = true; else if (!strcmp(argv[i], "--graphics")) useGraphics = true; else if (bootFilename == 0) bootFilename = argv[i]; else { if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) printUsage(argv[0], NULL); else { std::string reason = "Unexpected argument " + std::string(argv[i]); printUsage(argv[0], reason.c_str()); } return 1; } } if (readMount) { printUsage(argv[0], "Missing argument after -m"); return 1; } if (!bootFilename) { printUsage(argv[0], argc <= 1 ? NULL : "No executable specified"); return 1; } HeadlessHost *headlessHost = useGraphics ? new HEADLESSHOST_CLASS() : new HeadlessHost(); host = headlessHost; host->InitGL(); LogManager::Init(); LogManager *logman = LogManager::GetInstance(); PrintfLogger *printfLogger = new PrintfLogger(); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; logman->SetEnable(type, fullLog); logman->SetLogLevel(type, LogTypes::LDEBUG); logman->AddListener(type, printfLogger); } CoreParameter coreParameter; coreParameter.fileToStart = bootFilename; coreParameter.mountIso = mountIso ? mountIso : ""; coreParameter.startPaused = false; coreParameter.cpuCore = useJit ? CPU_JIT : (fastInterpreter ? CPU_FASTINTERPRETER : CPU_INTERPRETER); coreParameter.gpuCore = headlessHost->isGLWorking() ? GPU_GLES : GPU_NULL; coreParameter.enableSound = false; coreParameter.headLess = true; coreParameter.printfEmuLog = true; g_Config.bEnableSound = false; g_Config.bFirstRun = false; g_Config.bIgnoreBadMemAccess = true; std::string error_string; if (!PSP_Init(coreParameter, &error_string)) { fprintf(stderr, "Failed to start %s. Error: %s\n", coreParameter.fileToStart.c_str(), error_string.c_str()); printf("TESTERROR\n"); return 1; } host->BootDone(); coreState = CORE_RUNNING; while (coreState == CORE_RUNNING) { // Run for a frame at a time, just because. u64 nowTicks = CoreTiming::GetTicks(); u64 frameTicks = usToCycles(1000000/60); mipsr4k.RunLoopUntil(nowTicks + frameTicks); // If we were rendering, this might be a nice time to do something about it. if (coreState == CORE_NEXTFRAME) coreState = CORE_RUNNING; } host->ShutdownGL(); PSP_Shutdown(); delete host; host = NULL; headlessHost = NULL; if (autoCompare) { std::string expect_filename = std::string(bootFilename).substr(strlen(bootFilename - 4)) + ".expected"; if (File::Exists(expect_filename)) { // TODO: Do the compare here } else { fprintf(stderr, "Expectation file %s not found", expect_filename.c_str()); } } return 0; }
void RunTests() { std::string output; #ifdef IOS const std::string baseDirectory = g_Config.flash0Directory + "../"; #else const std::string baseDirectory = g_Config.memStickDirectory; #endif CoreParameter coreParam; coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER; coreParam.gpuCore = g_Config.bSoftwareRendering ? GPU_SOFTWARE : GPU_GLES; coreParam.enableSound = g_Config.bEnableSound; coreParam.graphicsContext = PSP_CoreParameter().graphicsContext; coreParam.mountIso = ""; coreParam.mountRoot = baseDirectory + "pspautotests/"; coreParam.startPaused = false; coreParam.printfEmuLog = false; coreParam.headLess = true; coreParam.renderWidth = 480; coreParam.renderHeight = 272; coreParam.pixelWidth = 480; coreParam.pixelHeight = 272; coreParam.collectEmuLog = &output; coreParam.unthrottle = true; coreParam.updateRecent = false; // Never report from tests. std::string savedReportHost = g_Config.sReportHost; g_Config.sReportHost = ""; for (size_t i = 0; i < ARRAY_SIZE(testsToRun); i++) { const char *testName = testsToRun[i]; coreParam.fileToStart = baseDirectory + "pspautotests/tests/" + testName + ".prx"; std::string expectedFile = baseDirectory + "pspautotests/tests/" + testName + ".expected"; ILOG("Preparing to execute %s", testName); std::string error_string; output = ""; if (!PSP_Init(coreParam, &error_string)) { ELOG("Failed to init unittest %s : %s", testsToRun[i], error_string.c_str()); PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; return; } // Run the emu until the test exits while (true) { int blockTicks = usToCycles(1000000 / 10); while (coreState == CORE_RUNNING) { PSP_RunLoopFor(blockTicks); } // Hopefully coreState is now CORE_NEXTFRAME if (coreState == CORE_NEXTFRAME) { // set back to running for the next frame coreState = CORE_RUNNING; } else if (coreState == CORE_POWERDOWN) { ILOG("Finished running test %s", testName); break; } } std::ifstream expected(expectedFile.c_str(), std::ios_base::in); if (!expected) { ELOG("Error opening expectedFile %s", expectedFile.c_str()); break; } std::istringstream logoutput(output); int line = 0; while (true) { ++line; std::string e, o; std::getline(expected, e); std::getline(logoutput, o); // Remove stray returns e = TrimNewlines(e); o = TrimNewlines(o); if (e != o) { ELOG("DIFF on line %i!", line); ELOG("O: %s", o.c_str()); ELOG("E: %s", e.c_str()); } if (expected.eof()) { break; } if (logoutput.eof()) { break; } } PSP_Shutdown(); } glViewport(0,0,pixel_xres,pixel_yres); PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; PSP_CoreParameter().headLess = false; g_Config.sReportHost = savedReportHost; }
void EmuScreen::render() { if (invalid_) return; if (PSP_CoreParameter().freezeNext) { PSP_CoreParameter().frozen = true; PSP_CoreParameter().freezeNext = false; SaveState::SaveToRam(freezeState_); } else if (PSP_CoreParameter().frozen) { if (CChunkFileReader::ERROR_NONE != SaveState::LoadFromRam(freezeState_)) { ERROR_LOG(HLE, "Failed to load freeze state. Unfreezing."); PSP_CoreParameter().frozen = false; } } // Reapply the graphics state of the PSP ReapplyGfxState(); // We just run the CPU until we get to vblank. This will quickly sync up pretty nicely. // The actual number of cycles doesn't matter so much here as we will break due to CORE_NEXTFRAME, most of the time hopefully... int blockTicks = usToCycles(1000000 / 10); // Run until CORE_NEXTFRAME while (coreState == CORE_RUNNING) { PSP_RunLoopFor(blockTicks); } // Hopefully coreState is now CORE_NEXTFRAME if (coreState == CORE_NEXTFRAME) { // set back to running for the next frame coreState = CORE_RUNNING; } else if (coreState == CORE_POWERDOWN) { PSP_Shutdown(); ILOG("SELF-POWERDOWN!"); screenManager()->switchScreen(new MainScreen()); invalid_ = true; } if (invalid_) return; bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; if (useBufferedRendering) fbo_unbind(); UIShader_Prepare(); uiTexture->Bind(0); glstate.viewport.set(0, 0, pixel_xres, pixel_yres); glstate.viewport.restore(); ui_draw2d.Begin(UIShader_Get(), DBMODE_NORMAL); if (root_) { UI::LayoutViewHierarchy(*screenManager()->getUIContext(), root_); root_->Draw(*screenManager()->getUIContext()); } if (!osm.IsEmpty()) { osm.Draw(ui_draw2d, screenManager()->getUIContext()->GetBounds()); } if (g_Config.bShowDebugStats) { char statbuf[4096] = {0}; __DisplayGetDebugStats(statbuf); if (statbuf[4095]) { ELOG("Statbuf too small! :("); } ui_draw2d.SetFontScale(.7f, .7f); ui_draw2d.DrawText(UBUNTU24, statbuf, 11, 11, 0xc0000000, FLAG_DYNAMIC_ASCII); ui_draw2d.DrawText(UBUNTU24, statbuf, 10, 10, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII); ui_draw2d.SetFontScale(1.0f, 1.0f); } if (g_Config.iShowFPSCounter) { float vps, fps, actual_fps; __DisplayGetFPS(&vps, &fps, &actual_fps); char fpsbuf[256]; switch (g_Config.iShowFPSCounter) { case 1: sprintf(fpsbuf, "Speed: %0.1f%%", vps / (59.94f / 100.0f)); break; case 2: sprintf(fpsbuf, "FPS: %0.1f", actual_fps); break; case 3: sprintf(fpsbuf, "%0.0f/%0.0f (%0.1f%%)", actual_fps, fps, vps / (59.94f / 100.0f)); break; default: return; } const Bounds &bounds = screenManager()->getUIContext()->GetBounds(); ui_draw2d.SetFontScale(0.7f, 0.7f); ui_draw2d.DrawText(UBUNTU24, fpsbuf, bounds.x2() - 8, 12, 0xc0000000, ALIGN_TOPRIGHT | FLAG_DYNAMIC_ASCII); ui_draw2d.DrawText(UBUNTU24, fpsbuf, bounds.x2() - 10, 10, 0xFF3fFF3f, ALIGN_TOPRIGHT | FLAG_DYNAMIC_ASCII); ui_draw2d.SetFontScale(1.0f, 1.0f); } glsl_bind(UIShader_Get()); ui_draw2d.End(); ui_draw2d.Flush(); // Tiled renderers like PowerVR should benefit greatly from this. However - seems I can't call it? #if defined(USING_GLES2) bool hasDiscard = gl_extensions.EXT_discard_framebuffer; // TODO if (hasDiscard) { //const GLenum targets[3] = { GL_COLOR_EXT, GL_DEPTH_EXT, GL_STENCIL_EXT }; //glDiscardFramebufferEXT(GL_FRAMEBUFFER, 3, targets); } #endif }
int main(int argc, const char* argv[]) { bool fullLog = false; bool useJit = true; bool autoCompare = false; bool useGraphics = false; const char *bootFilename = 0; const char *mountIso = 0; const char *screenshotFilename = 0; bool readMount = false; for (int i = 1; i < argc; i++) { if (readMount) { mountIso = argv[i]; readMount = false; continue; } if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--mount")) readMount = true; else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log")) fullLog = true; else if (!strcmp(argv[i], "-i")) useJit = false; else if (!strcmp(argv[i], "-j")) useJit = true; else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compare")) autoCompare = true; else if (!strcmp(argv[i], "--graphics")) useGraphics = true; else if (!strncmp(argv[i], "--screenshot=", strlen("--screenshot=")) && strlen(argv[i]) > strlen("--screenshot=")) screenshotFilename = argv[i] + strlen("--screenshot="); else if (bootFilename == 0) bootFilename = argv[i]; else { if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) printUsage(argv[0], NULL); else { std::string reason = "Unexpected argument " + std::string(argv[i]); printUsage(argv[0], reason.c_str()); } return 1; } } if (readMount) { printUsage(argv[0], "Missing argument after -m"); return 1; } if (!bootFilename) { printUsage(argv[0], argc <= 1 ? NULL : "No executable specified"); return 1; } HeadlessHost *headlessHost = useGraphics ? new HEADLESSHOST_CLASS() : new HeadlessHost(); host = headlessHost; std::string error_string; bool glWorking = host->InitGL(&error_string); LogManager::Init(); LogManager *logman = LogManager::GetInstance(); PrintfLogger *printfLogger = new PrintfLogger(); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; logman->SetEnable(type, fullLog); logman->SetLogLevel(type, LogTypes::LDEBUG); logman->AddListener(type, printfLogger); } CoreParameter coreParameter; coreParameter.cpuCore = useJit ? CPU_JIT : CPU_INTERPRETER; coreParameter.gpuCore = glWorking ? GPU_GLES : GPU_NULL; coreParameter.enableSound = false; coreParameter.fileToStart = bootFilename; coreParameter.mountIso = mountIso ? mountIso : ""; coreParameter.startPaused = false; coreParameter.enableDebugging = false; coreParameter.printfEmuLog = true; coreParameter.headLess = true; coreParameter.renderWidth = 480; coreParameter.renderHeight = 272; coreParameter.outputWidth = 480; coreParameter.outputHeight = 272; coreParameter.pixelWidth = 480; coreParameter.pixelHeight = 272; coreParameter.unthrottle = true; g_Config.bEnableSound = false; g_Config.bFirstRun = false; g_Config.bIgnoreBadMemAccess = true; // Never report from tests. g_Config.sReportHost = ""; g_Config.bAutoSaveSymbolMap = false; g_Config.iRenderingMode = true; g_Config.bHardwareTransform = true; #ifdef USING_GLES2 g_Config.iAnisotropyLevel = 0; #else g_Config.iAnisotropyLevel = 8; #endif g_Config.bVertexCache = true; g_Config.bTrueColor = true; g_Config.ilanguage = PSP_SYSTEMPARAM_LANGUAGE_ENGLISH; g_Config.iTimeFormat = PSP_SYSTEMPARAM_TIME_FORMAT_24HR; g_Config.bEncryptSave = true; g_Config.sNickName = "shadow"; g_Config.iTimeZone = 60; g_Config.iDateFormat = PSP_SYSTEMPARAM_DATE_FORMAT_DDMMYYYY; g_Config.iButtonPreference = PSP_SYSTEMPARAM_BUTTON_CROSS; g_Config.iLockParentalLevel = 9; #if defined(ANDROID) #elif defined(BLACKBERRY) || defined(__SYMBIAN32__) #elif !defined(_WIN32) g_Config.memCardDirectory = std::string(getenv("HOME"))+"/.ppsspp/"; g_Config.flashDirectory = g_Config.memCardDirectory+"/flash/"; #endif if (!PSP_Init(coreParameter, &error_string)) { fprintf(stderr, "Failed to start %s. Error: %s\n", coreParameter.fileToStart.c_str(), error_string.c_str()); printf("TESTERROR\n"); return 1; } host->BootDone(); if (screenshotFilename != 0) headlessHost->SetComparisonScreenshot(screenshotFilename); coreState = CORE_RUNNING; while (coreState == CORE_RUNNING) { int blockTicks = usToCycles(1000000 / 10); PSP_RunLoopFor(blockTicks); // If we were rendering, this might be a nice time to do something about it. if (coreState == CORE_NEXTFRAME) { coreState = CORE_RUNNING; headlessHost->SwapBuffers(); } } host->ShutdownGL(); PSP_Shutdown(); delete host; host = NULL; headlessHost = NULL; if (autoCompare) CompareOutput(bootFilename); return 0; }
void RunTests() { std::string output; CoreParameter coreParam; coreParam.cpuCore = g_Config.bJit ? CPU_JIT : CPU_INTERPRETER; coreParam.gpuCore = GPU_GLES; coreParam.enableSound = g_Config.bEnableSound; coreParam.mountIso = ""; coreParam.startPaused = false; coreParam.enableDebugging = false; coreParam.printfEmuLog = false; coreParam.headLess = false; coreParam.renderWidth = 480; coreParam.renderHeight = 272; coreParam.outputWidth = 480; coreParam.outputHeight = 272; coreParam.pixelWidth = 480; coreParam.pixelHeight = 272; coreParam.useMediaEngine = false; coreParam.collectEmuLog = &output; // Never report from tests. std::string savedReportHost = g_Config.sReportHost; g_Config.sReportHost = ""; for (int i = 0; i < ARRAY_SIZE(testsToRun); i++) { const char *testName = testsToRun[i]; coreParam.fileToStart = g_Config.memCardDirectory + "pspautotests/tests/" + testName + ".prx"; std::string expectedFile = g_Config.memCardDirectory + "pspautotests/tests/" + testName + ".expected"; ILOG("Preparing to execute %s", testName) std::string error_string; output = ""; if (!PSP_Init(coreParam, &error_string)) { ELOG("Failed to init unittest %s : %s", testsToRun[i], error_string.c_str()); return; } // Run the emu until the test exits while (true) { int blockTicks = usToCycles(1000000 / 10); while (coreState == CORE_RUNNING) { u64 nowTicks = CoreTiming::GetTicks(); mipsr4k.RunLoopUntil(nowTicks + blockTicks); } // Hopefully coreState is now CORE_NEXTFRAME if (coreState == CORE_NEXTFRAME) { // set back to running for the next frame coreState = CORE_RUNNING; } else if (coreState == CORE_POWERDOWN) { ILOG("Finished running test %s", testName); break; } } std::ifstream expected(expectedFile.c_str(), std::ios_base::in); if (!expected) { ELOG("Error opening expectedFile %s", expectedFile.c_str()); return; } std::istringstream logoutput(output); int line = 0; while (true) { ++line; std::string e, o; std::getline(expected, e); std::getline(logoutput, o); // Remove stray returns while (e[e.size()-1] == 10 || e[e.size()-1] == 13) e = e.substr(0, e.size() - 1); // For some reason we get some extra character while (o[o.size()-1] == 10 || o[o.size()-1] == 13) o = o.substr(0, o.size() - 1); // For some reason we get some extra character if (e != o) { ELOG("DIFF on line %i!", line); ILOG("O: %s", o.c_str()); ILOG("E: %s", e.c_str()); } if (expected.eof()) { break; } if (logoutput.eof()) { break; } } PSP_Shutdown(); } glstate.Restore(); glstate.viewport.set(0,0,pixel_xres,pixel_yres); g_Config.sReportHost = savedReportHost; }
int main(int argc, const char* argv[]) { bool fullLog = false; bool useJit = false; bool autoCompare = false; const char *bootFilename = argc > 1 ? argv[1] : 0; const char *mountIso = 0; bool readMount = false; for (int i = 2; i < argc; i++) { if (readMount) { mountIso = argv[i]; readMount = false; continue; } if (!strcmp(argv[i], "-m")) readMount = true; else if (!strcmp(argv[i], "-l")) fullLog = true; else if (!strcmp(argv[i], "-j")) useJit = true; else if (!strcmp(argv[i], "-c")) autoCompare = true; } if (!bootFilename) { printUsage(); return 1; } host = new HeadlessHost(); LogManager::Init(); LogManager *logman = LogManager::GetInstance(); PrintfLogger *printfLogger = new PrintfLogger(); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; logman->SetEnable(type, fullLog); logman->SetLogLevel(type, LogTypes::LDEBUG); logman->AddListener(type, printfLogger); } CoreParameter coreParameter; coreParameter.fileToStart = bootFilename; coreParameter.mountIso = mountIso ? mountIso : ""; coreParameter.startPaused = false; coreParameter.cpuCore = useJit ? CPU_JIT : CPU_INTERPRETER; coreParameter.gpuCore = GPU_NULL; coreParameter.enableSound = false; coreParameter.headLess = true; coreParameter.printfEmuLog = true; g_Config.bEnableSound = false; g_Config.bFirstRun = false; g_Config.bIgnoreBadMemAccess = true; std::string error_string; if (!PSP_Init(coreParameter, &error_string)) { fprintf(stderr, "Failed to start %s. Error: %s\n", coreParameter.fileToStart.c_str(), error_string.c_str()); printf("TESTERROR\n"); return 1; } coreState = CORE_RUNNING; while (coreState == CORE_RUNNING) { // Run for a frame at a time, just because. u64 nowTicks = CoreTiming::GetTicks(); u64 frameTicks = usToCycles(1000000/60); mipsr4k.RunLoopUntil(nowTicks + frameTicks); } // NOTE: we won't get here until I've gotten rid of the exit(0) in sceExitProcess or whatever it's called PSP_Shutdown(); if (autoCompare) { std::string expect_filename = std::string(bootFilename).substr(strlen(bootFilename - 4)) + ".expected"; if (File::Exists(expect_filename)) { // TODO: Do the compare here } else { fprintf(stderr, "Expectation file %s not found", expect_filename.c_str()); } } return 0; }
DWORD TheThread(LPVOID x) { setCurrentThreadName("EmuThread"); g_State.bEmuThreadStarted = true; host->UpdateUI(); host->InitGL(); INFO_LOG(BOOT, "Starting up hardware."); CoreParameter coreParameter; coreParameter.fileToStart = fileToStart; coreParameter.enableSound = true; coreParameter.gpuCore = GPU_GLES; coreParameter.cpuCore = g_Config.bJIT ? CPU_JIT : CPU_INTERPRETER; coreParameter.enableDebugging = true; coreParameter.printfEmuLog = false; coreParameter.headLess = false; //true; std::string error_string; if (!PSP_Init(coreParameter, &error_string)) { ERROR_LOG(BOOT, "Error loading: %s", error_string.c_str()); goto shutdown; } INFO_LOG(BOOT, "Done."); _dbg_update_(); if (g_Config.bAutoRun) { #ifdef _DEBUG host->UpdateDisassembly(); #endif Core_EnableStepping(FALSE); } else { #ifdef _DEBUG host->UpdateDisassembly(); #endif Core_EnableStepping(TRUE); } g_State.bBooted = true; #ifdef _DEBUG host->UpdateMemView(); #endif host->BootDone(); Core_Run(); host->PrepareShutdown(); PSP_Shutdown(); shutdown: host->ShutdownGL(); //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 g_State.bEmuThreadStarted = false; _endthreadex(0); return 0; }
bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, bool autoCompare, bool verbose, double timeout) { if (teamCityMode) { // Kinda ugly, trying to guesstimate the test name from filename... teamCityName = GetTestName(coreParameter.fileToStart); } std::string output; if (autoCompare) coreParameter.collectEmuLog = &output; std::string error_string; if (!PSP_Init(coreParameter, &error_string)) { fprintf(stderr, "Failed to start %s. Error: %s\n", coreParameter.fileToStart.c_str(), error_string.c_str()); printf("TESTERROR\n"); TeamCityPrint("##teamcity[testIgnored name='%s' message='PRX/ELF missing']\n", teamCityName.c_str()); return false; } TeamCityPrint("##teamcity[testStarted name='%s' captureStandardOutput='true']\n", teamCityName.c_str()); host->BootDone(); if (autoCompare) headlessHost->SetComparisonScreenshot(ExpectedScreenshotFromFilename(coreParameter.fileToStart)); time_update(); bool passed = true; // TODO: We must have some kind of stack overflow or we're not following the ABI right. // This gets trashed if it's not static. static double deadline; deadline = time_now() + timeout; coreState = CORE_RUNNING; while (coreState == CORE_RUNNING) { int blockTicks = usToCycles(1000000 / 10); PSP_RunLoopFor(blockTicks); // If we were rendering, this might be a nice time to do something about it. if (coreState == CORE_NEXTFRAME) { coreState = CORE_RUNNING; headlessHost->SwapBuffers(); } time_update(); if (time_now_d() > deadline) { // Don't compare, print the output at least up to this point, and bail. printf("%s", output.c_str()); passed = false; host->SendDebugOutput("TIMEOUT\n"); TeamCityPrint("##teamcity[testFailed name='%s' message='Test timeout']\n", teamCityName.c_str()); Core_Stop(); } } PSP_Shutdown(); headlessHost->FlushDebugOutput(); if (autoCompare && passed) passed = CompareOutput(coreParameter.fileToStart, output, verbose); TeamCityPrint("##teamcity[testFinished name='%s']\n", teamCityName.c_str()); return passed; }
int main(int argc, const char* argv[]) { bool fullLog = false; bool useJit = true; bool autoCompare = false; bool useGraphics = false; const char *bootFilename = 0; const char *mountIso = 0; const char *screenshotFilename = 0; bool readMount = false; for (int i = 1; i < argc; i++) { if (readMount) { mountIso = argv[i]; readMount = false; continue; } if (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--mount")) readMount = true; else if (!strcmp(argv[i], "-l") || !strcmp(argv[i], "--log")) fullLog = true; else if (!strcmp(argv[i], "-i")) useJit = false; else if (!strcmp(argv[i], "-j")) useJit = true; else if (!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compare")) autoCompare = true; else if (!strcmp(argv[i], "--graphics")) useGraphics = true; else if (!strncmp(argv[i], "--screenshot=", strlen("--screenshot=")) && strlen(argv[i]) > strlen("--screenshot=")) screenshotFilename = argv[i] + strlen("--screenshot="); else if (bootFilename == 0) bootFilename = argv[i]; else { if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) printUsage(argv[0], NULL); else { std::string reason = "Unexpected argument " + std::string(argv[i]); printUsage(argv[0], reason.c_str()); } return 1; } } if (readMount) { printUsage(argv[0], "Missing argument after -m"); return 1; } if (!bootFilename) { printUsage(argv[0], argc <= 1 ? NULL : "No executable specified"); return 1; } HeadlessHost *headlessHost = useGraphics ? new HEADLESSHOST_CLASS() : new HeadlessHost(); host = headlessHost; std::string error_string; host->InitGL(&error_string); LogManager::Init(); LogManager *logman = LogManager::GetInstance(); PrintfLogger *printfLogger = new PrintfLogger(); for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++) { LogTypes::LOG_TYPE type = (LogTypes::LOG_TYPE)i; logman->SetEnable(type, fullLog); logman->SetLogLevel(type, LogTypes::LDEBUG); logman->AddListener(type, printfLogger); } CoreParameter coreParameter; coreParameter.fileToStart = bootFilename; coreParameter.mountIso = mountIso ? mountIso : ""; coreParameter.startPaused = false; coreParameter.cpuCore = useJit ? CPU_JIT : CPU_INTERPRETER; coreParameter.gpuCore = headlessHost->isGLWorking() ? GPU_GLES : GPU_NULL; coreParameter.enableSound = false; coreParameter.headLess = true; coreParameter.printfEmuLog = true; coreParameter.useMediaEngine = false; g_Config.bEnableSound = false; g_Config.bFirstRun = false; g_Config.bIgnoreBadMemAccess = true; // Never report from tests. g_Config.sReportHost = ""; #if defined(ANDROID) #elif defined(BLACKBERRY) || defined(__SYMBIAN32__) #elif !defined(_WIN32) g_Config.memCardDirectory = std::string(getenv("HOME"))+"/.ppsspp/"; g_Config.flashDirectory = g_Config.memCardDirectory+"/flash/"; #endif if (!PSP_Init(coreParameter, &error_string)) { fprintf(stderr, "Failed to start %s. Error: %s\n", coreParameter.fileToStart.c_str(), error_string.c_str()); printf("TESTERROR\n"); return 1; } host->BootDone(); if (screenshotFilename != 0) headlessHost->SetComparisonScreenshot(screenshotFilename); coreState = CORE_RUNNING; while (coreState == CORE_RUNNING) { // Run for a frame at a time, just because. u64 nowTicks = CoreTiming::GetTicks(); u64 frameTicks = usToCycles(1000000/60); mipsr4k.RunLoopUntil(nowTicks + frameTicks); // If we were rendering, this might be a nice time to do something about it. if (coreState == CORE_NEXTFRAME) { coreState = CORE_RUNNING; headlessHost->SwapBuffers(); } } host->ShutdownGL(); PSP_Shutdown(); delete host; host = NULL; headlessHost = NULL; if (autoCompare) CompareOutput(bootFilename); return 0; }