diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 9060f82acc..2882749884 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -139,6 +139,8 @@ void hleAfterFlip(u64 userdata, int cyclesLate); void __DisplayVblankBeginCallback(SceUID threadID, SceUID prevCallbackId); void __DisplayVblankEndCallback(SceUID threadID, SceUID prevCallbackId); +int __DisplayGetFlipCount() { return actualFlips; } +int __DisplayGetVCount() { return vCount; } void __DisplayInit() { gpuStats.Reset(); diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index 5219718453..cce482a410 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -37,3 +37,5 @@ void __DisplayGetDebugStats(char stats[2048]); void __DisplayGetFPS(float *out_vps, float *out_fps, float *out_actual_fps); void __DisplayGetVPS(float *out_vps); void __DisplayGetAveragedFPS(float *out_vps, float *out_fps); +int __DisplayGetVCount(); +int __DisplayGetFlipCount(); diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index cf545f8675..6ecaaf6e41 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -200,17 +200,18 @@ namespace SaveState return !rewindStates.Empty(); } - + static const char *STATE_EXTENSION = "ppst"; + static const char *SCREENSHOT_EXTENSION = "jpg"; // Slot utilities - std::string GenerateSaveSlotFilename(int slot) + std::string GenerateSaveSlotFilename(int slot, const char *extension) { char discID[256]; char temp[256]; sprintf(discID, "%s_%s", g_paramSFO.GetValueString("DISC_ID").c_str(), g_paramSFO.GetValueString("DISC_VERSION").c_str()); - sprintf(temp, "ms0:/PSP/PPSSPP_STATE/%s_%i.ppst", discID, slot); + sprintf(temp, "ms0:/PSP/PPSSPP_STATE/%s_%i.%s", discID, slot, extension); std::string hostPath; if (pspFileSystem.GetHostPath(std::string(temp), hostPath)) { return hostPath; @@ -221,7 +222,7 @@ namespace SaveState void LoadSlot(int slot, Callback callback, void *cbUserData) { - std::string fn = GenerateSaveSlotFilename(slot); + std::string fn = GenerateSaveSlotFilename(slot, STATE_EXTENSION); if (!fn.empty()) { Load(fn, callback, cbUserData); } else { @@ -234,7 +235,7 @@ namespace SaveState void SaveSlot(int slot, Callback callback, void *cbUserData) { - std::string fn = GenerateSaveSlotFilename(slot); + std::string fn = GenerateSaveSlotFilename(slot, STATE_EXTENSION); if (!fn.empty()) { Save(fn, callback, cbUserData); } else { @@ -247,7 +248,13 @@ namespace SaveState bool HasSaveInSlot(int slot) { - std::string fn = GenerateSaveSlotFilename(slot); + std::string fn = GenerateSaveSlotFilename(slot, STATE_EXTENSION); + return File::Exists(fn); + } + + bool HasScreenshotInSlot(int slot) + { + std::string fn = GenerateSaveSlotFilename(slot, SCREENSHOT_EXTENSION); return File::Exists(fn); } @@ -271,7 +278,7 @@ namespace SaveState int newestSlot = -1; tm newestDate = {0}; for (int i = 0; i < SAVESTATESLOTS; i++) { - std::string fn = GenerateSaveSlotFilename(i); + std::string fn = GenerateSaveSlotFilename(i, STATE_EXTENSION); if (File::Exists(fn)) { tm time = File::GetModifTime(fn); if (newestDate < time) { diff --git a/Core/SaveState.h b/Core/SaveState.h index 808597580b..088600b904 100644 --- a/Core/SaveState.h +++ b/Core/SaveState.h @@ -33,9 +33,12 @@ namespace SaveState void LoadSlot(int slot, Callback callback, void *cbUserData = 0); // Checks whether there's an existing save in the specified slot. bool HasSaveInSlot(int slot); + bool HasScreenshotInSlot(int slot); // Returns -1 if there's no newest slot. int GetNewestSlot(); + std::string GenerateSaveSlotFilename(int slot, const char *extension); + // Load the specified file into the current state (async.) // Warning: callback will be called on a different thread. void Load(const std::string &filename, Callback callback = 0, void *cbUserData = 0); diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 5a332daac0..eb6b0c6762 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -19,6 +19,7 @@ #include "gfx_es2/gl_state.h" #include "gfx_es2/fbo.h" +#include "base/timeutil.h" #include "math/lin/matrix4x4.h" #include "Core/Host.h" @@ -26,6 +27,7 @@ #include "Core/Config.h" #include "Core/System.h" #include "Core/Reporting.h" +#include "Core/HLE/sceDisplay.h" #include "GPU/ge_constants.h" #include "GPU/GPUState.h" @@ -234,11 +236,12 @@ void FramebufferManager::CompileDraw2DProgram() { } int deltaLoc = glsl_uniform_loc(postShaderProgram_, "u_texelDelta"); - if (deltaLoc != -1) - glUniform2f(deltaLoc, u_delta, v_delta); + glUniform2f(deltaLoc, u_delta, v_delta); int pixelDeltaLoc = glsl_uniform_loc(postShaderProgram_, "u_pixelDelta"); - if (pixelDeltaLoc != -1) - glUniform2f(pixelDeltaLoc, u_pixel_delta, v_pixel_delta); + glUniform2f(pixelDeltaLoc, u_pixel_delta, v_pixel_delta); + timeLoc_ = glsl_uniform_loc(postShaderProgram_, "u_time"); + glUniform4f(timeLoc_, 0.0f, 0.0f, 0.0f, 0.0f); + usePostShader_ = true; } } else { @@ -275,8 +278,9 @@ FramebufferManager::FramebufferManager() : convBuf(0), draw2dprogram_(0), postShaderProgram_(0), - postShaderAtOutputResolution_(false), plainColorLoc_(-1), + timeLoc_(-1), + postShaderAtOutputResolution_(false), resized_(false), textureCache_(0), shaderManager_(0), @@ -503,6 +507,12 @@ void FramebufferManager::DrawActiveTexture(GLuint texture, float x, float y, flo } glsl_bind(program); + if (program == postShaderProgram_ && timeLoc_ != -1) { + int flipCount = __DisplayGetFlipCount(); + int vCount = __DisplayGetVCount(); + float time[4] = {time_now(), (vCount % 60) * 1.0f/60.0f, (float)vCount, (float)(flipCount % 60)}; + glUniform4fv(timeLoc_, 1, time); + } glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glEnableVertexAttribArray(program->a_position); diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index 3caf665782..f61750ecad 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -204,6 +204,7 @@ private: GLSLProgram *plainColorProgram_; GLSLProgram *postShaderProgram_; int plainColorLoc_; + int timeLoc_; TextureCache *textureCache_; ShaderManager *shaderManager_;