diff --git a/CMakeLists.txt b/CMakeLists.txt index 40a03672fb..0456d57654 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1027,6 +1027,7 @@ set(NativeAppSource UI/MenuScreens.cpp UI/GamepadEmu.cpp UI/UIShader.cpp + UI/OnScreenDisplay.cpp UI/ui_atlas.cpp) if(ANDROID) set(NativeAppSource ${NativeAppSource} android/jni/ArmEmitterTest.cpp) diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index fcc9d19f1a..77efef6c7b 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -15,20 +15,22 @@ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. -#include "../Common/StdMutex.h" -#include "../Common/FileUtil.h" #include -#include "SaveState.h" -#include "Core.h" -#include "CoreTiming.h" -#include "HLE/HLE.h" -#include "HLE/sceKernel.h" +#include "Common/StdMutex.h" +#include "Common/FileUtil.h" + +#include "Core/SaveState.h" +#include "Core/Core.h" +#include "Core/CoreTiming.h" +#include "Core/HLE/HLE.h" +#include "Core/HLE/sceKernel.h" #include "HW/MemoryStick.h" -#include "MemMap.h" -#include "MIPS/MIPS.h" -#include "MIPS/JitCommon/JitCommon.h" -#include "System.h" +#include "Core/MemMap.h" +#include "Core/MIPS/MIPS.h" +#include "Core/MIPS/JitCommon/JitCommon.h" +#include "Core/System.h" +#include "UI/OnScreenDisplay.h" namespace SaveState { @@ -223,6 +225,7 @@ namespace SaveState if (MIPSComp::jit) MIPSComp::jit->ClearCache(); INFO_LOG(COMMON, "Loading state from %s", op.filename.c_str()); + osm.Show("Loaded state", 2.0); result = CChunkFileReader::Load(op.filename, REVISION, state); break; @@ -230,6 +233,7 @@ namespace SaveState if (MIPSComp::jit) MIPSComp::jit->ClearCache(); INFO_LOG(COMMON, "Saving state to %s", op.filename.c_str()); + osm.Show("Saved state", 2.0); result = CChunkFileReader::Save(op.filename, REVISION, state); break; diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index b903a38ea1..4d49cbf33f 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -37,6 +37,7 @@ #include "Core/HLE/sceDisplay.h" #include "Core/Debugger/SymbolMap.h" +#include "UI/OnScreenDisplay.h" #include "UI/ui_atlas.h" #include "UI/GamepadEmu.h" #include "UI/UIShader.h" @@ -214,6 +215,14 @@ void EmuScreen::update(InputState &input) { __CtrlSetAnalog(stick_x, stick_y, 0); __CtrlSetAnalog(rightstick_x, rightstick_x, 1); + if (PSP_CoreParameter().fpsLimit != 2) { + if (input.pad_buttons_down & PAD_BUTTON_UNTHROTTLE) { + osm.Show("Speed: unlimited!", 1.0, 0x50E0FF); + } + if (input.pad_buttons_up & PAD_BUTTON_UNTHROTTLE) { + osm.Show("Speed: standard", 1.0); + } + } if (input.pad_buttons & PAD_BUTTON_UNTHROTTLE) { PSP_CoreParameter().unthrottle = true; } else { @@ -225,19 +234,20 @@ void EmuScreen::update(InputState &input) { } //Toggle between 3 different states of fpsLimit if (input.pad_buttons_down & PAD_BUTTON_LEFT_THUMB) { - if (PSP_CoreParameter().fpsLimit == 0){ + if (PSP_CoreParameter().fpsLimit == 0) { PSP_CoreParameter().fpsLimit = 1; + osm.Show("Speed: fixed", 1.0); } else if (PSP_CoreParameter().fpsLimit == 1){ PSP_CoreParameter().fpsLimit = 2; + osm.Show("Speed: unlimited!", 1.0, 0x50E0FF); } else if (PSP_CoreParameter().fpsLimit == 2){ PSP_CoreParameter().fpsLimit = 0; + osm.Show("Speed: standard", 1.0); } } - - - + if (input.pad_buttons_down & (PAD_BUTTON_MENU | PAD_BUTTON_BACK | PAD_BUTTON_RIGHT_THUMB)) { if (g_Config.bBufferedRendering) @@ -291,6 +301,10 @@ void EmuScreen::render() { DrawWatermark(); + if (!osm.IsEmpty()) { + osm.Draw(ui_draw2d); + } + if (g_Config.bShowDebugStats) { char statbuf[4096] = {0}; __DisplayGetDebugStats(statbuf); diff --git a/UI/EmuScreen.h b/UI/EmuScreen.h index 4369fca8cc..a4cd0caf95 100644 --- a/UI/EmuScreen.h +++ b/UI/EmuScreen.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include "ui/screen.h" @@ -37,4 +38,4 @@ private: // Something invalid was loaded, don't try to emulate bool invalid_; std::string errorMessage_; -}; +}; \ No newline at end of file diff --git a/UI/OnScreenDisplay.cpp b/UI/OnScreenDisplay.cpp new file mode 100644 index 0000000000..04f3e215aa --- /dev/null +++ b/UI/OnScreenDisplay.cpp @@ -0,0 +1,52 @@ +#include "UI/OnScreenDisplay.h" +#include "UI/ui_atlas.h" + +#include "base/colorutil.h" +#include "base/display.h" +#include "base/timeutil.h" +#include "gfx_es2/draw_buffer.h" + +OnScreenMessages osm; + +void OnScreenMessages::Draw(DrawBuffer &draw) { + // First, clean out old messages. + std::lock_guard guard(mutex_); + +restart: + double now = time_now_d(); + for (auto iter = messages_.begin(); iter != messages_.end(); iter++) { + if (iter->endTime < now) { + messages_.erase(iter); + goto restart; + } + } + + // Get height + float w, h; + draw.MeasureText(UBUNTU24, "Wg", &w, &h); + + float y = 10.0f; + // Then draw them all. + for (auto iter = messages_.begin(); iter != messages_.end(); ++iter) { + float alpha = (iter->endTime - time_now_d()) * 4; + if (alpha > 1.0) alpha = 1.0; + if (alpha < 0.0) alpha = 0.0; + draw.DrawTextShadow(UBUNTU24, iter->text.c_str(), dp_xres / 2, y, colorAlpha(iter->color, alpha), ALIGN_TOP | ALIGN_HCENTER); + y += h; + } +} + +void OnScreenMessages::Show(const std::string &message, float duration_s, uint32_t color, int icon) { + std::lock_guard guard(mutex_); + double now = time_now_d(); + Message msg; + msg.text = message; + msg.color = color; + msg.endTime = now + duration_s; + msg.icon = icon; + messages_.insert(messages_.begin(), msg); +} + +void OnScreenMessages::ShowOnOff(const std::string &message, bool b, float duration_s, uint32_t color, int icon) { + Show(message + (b ? ": on" : ": off"), duration_s, color, icon); +} diff --git a/UI/OnScreenDisplay.h b/UI/OnScreenDisplay.h new file mode 100644 index 0000000000..d5e4b63ee6 --- /dev/null +++ b/UI/OnScreenDisplay.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include + +#include "base/basictypes.h" +#include "Common/StdMutex.h" + +class DrawBuffer; + +class OnScreenMessages { +public: + void Show(const std::string &message, float duration_s = 1.0f, uint32_t color = 0xFFFFFF, int icon = -1); + void ShowOnOff(const std::string &message, bool b, float duration_s = 1.0f, uint32_t color = 0xFFFFFF, int icon = -1); + void Draw(DrawBuffer &draw); + bool IsEmpty() const { return messages_.empty(); } + +private: + struct Message { + int icon; + uint32_t color; + std::string text; + double endTime; + double duration; + }; + + std::list messages_; + std::recursive_mutex mutex_; +}; + +extern OnScreenMessages osm; diff --git a/UI/UI.vcxproj b/UI/UI.vcxproj index e63b525c5f..f672b79b56 100644 --- a/UI/UI.vcxproj +++ b/UI/UI.vcxproj @@ -1,157 +1,159 @@ - - - - - Debug - Win32 - - - Debug - x64 - - - Release - Win32 - - - Release - x64 - - - - - - - - - - - - - - - - - - - - - {004B8D11-2BE3-4BD9-AB40-2BE04CF2096F} - Win32Proj - UI - - - - StaticLibrary - true - v100 - MultiByte - - - StaticLibrary - true - v100 - MultiByte - - - StaticLibrary - false - v100 - true - MultiByte - - - StaticLibrary - false - v100 - true - MultiByte - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ../common;..;../native;../native/ext/glew;../ext/zlib - - - Windows - true - - - - - - - Level3 - Disabled - WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) - ../common;..;../native;../native/ext/glew;../ext/zlib - - - Windows - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ../common;..;../native;../native/ext/glew;../ext/zlib - false - Speed - - - Windows - true - true - true - - - - - Level3 - - - MaxSpeed - true - true - WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) - ../common;..;../native;../native/ext/glew;../ext/zlib - false - - - Windows - true - true - true - - - - - + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + + + + + + + + + + + + + + + {004B8D11-2BE3-4BD9-AB40-2BE04CF2096F} + Win32Proj + UI + + + + StaticLibrary + true + v100 + MultiByte + + + StaticLibrary + true + v100 + MultiByte + + + StaticLibrary + false + v100 + true + MultiByte + + + StaticLibrary + false + v100 + true + MultiByte + + + + + + + + + + + + + + + + + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ../common;..;../native;../native/ext/glew;../ext/zlib + + + Windows + true + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) + ../common;..;../native;../native/ext/glew;../ext/zlib + + + Windows + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ../common;..;../native;../native/ext/glew;../ext/zlib + false + Speed + + + Windows + true + true + true + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) + ../common;..;../native;../native/ext/glew;../ext/zlib + false + + + Windows + true + true + true + + + + + \ No newline at end of file diff --git a/UI/UI.vcxproj.filters b/UI/UI.vcxproj.filters index 1252386915..58a6a583d1 100644 --- a/UI/UI.vcxproj.filters +++ b/UI/UI.vcxproj.filters @@ -1,20 +1,22 @@ - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index dbaf4078f5..b57eedb4e2 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -36,6 +36,8 @@ #include "native/image/png_load.h" #include "GPU/GLES/TextureScaler.h" #include "ControlMapping.h" +#include "UI/OnScreenDisplay.h" +#include "i18n/i18n.h" #ifdef THEMES #include "XPTheme.h" @@ -376,6 +378,8 @@ namespace MainWindow int wmId, wmEvent; std::string fn; + I18NCategory *g = GetI18NCategory("Graphics"); + switch (message) { case WM_CREATE: @@ -556,6 +560,7 @@ namespace MainWindow case ID_OPTIONS_BUFFEREDRENDERING: g_Config.bBufferedRendering = !g_Config.bBufferedRendering; + osm.ShowOnOff(g->T("Buffered Rendering"), g_Config.bBufferedRendering); if (gpu) gpu->Resized(); // easy way to force a clear... break; @@ -566,6 +571,7 @@ namespace MainWindow case ID_OPTIONS_HARDWARETRANSFORM: g_Config.bHardwareTransform = !g_Config.bHardwareTransform; + osm.ShowOnOff(g->T("Hardware Transform"), g_Config.bHardwareTransform); break; case ID_OPTIONS_STRETCHDISPLAY: @@ -576,10 +582,12 @@ namespace MainWindow case ID_OPTIONS_FRAMESKIP: g_Config.iFrameSkip = g_Config.iFrameSkip == 0 ? 1 : 0; + osm.ShowOnOff(g->T("Frame Skipping"), g_Config.iFrameSkip != 0); break; case ID_OPTIONS_USEMEDIAENGINE: g_Config.bUseMediaEngine = !g_Config.bUseMediaEngine; + osm.ShowOnOff(g->T("Media Engine"), g_Config.bUseMediaEngine); break; case ID_FILE_EXIT: @@ -588,6 +596,7 @@ namespace MainWindow case ID_CPU_DYNAREC: g_Config.bJit = true; + osm.ShowOnOff(g->T("Dynarec", "Dynarec (JIT)"), g_Config.bJit); break; case ID_CPU_INTERPRETER: diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 5134c68fac..c2569d0646 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -133,6 +133,7 @@ LOCAL_SRC_FILES := \ $(SRC)/UI/UIShader.cpp \ $(SRC)/UI/GamepadEmu.cpp \ $(SRC)/UI/GameInfoCache.cpp \ + $(SRC)/UI/OnScreenDisplay.cpp \ $(SRC)/native/android/app-android.cpp \ $(SRC)/ext/disarm.cpp \ $(SRC)/ext/libkirk/AES.c \ diff --git a/headless/Headless.vcxproj b/headless/Headless.vcxproj index 39f2c12bcc..91aa2805d0 100644 --- a/headless/Headless.vcxproj +++ b/headless/Headless.vcxproj @@ -168,6 +168,7 @@ + NotUsing @@ -201,6 +202,7 @@ + diff --git a/headless/Headless.vcxproj.filters b/headless/Headless.vcxproj.filters index e0debd7e7b..8c2ba66c5f 100644 --- a/headless/Headless.vcxproj.filters +++ b/headless/Headless.vcxproj.filters @@ -1,17 +1,19 @@ - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + \ No newline at end of file