diff --git a/Common/Arm64Emitter.cpp b/Common/Arm64Emitter.cpp index b3ef8540db..ecff815da1 100644 --- a/Common/Arm64Emitter.cpp +++ b/Common/Arm64Emitter.cpp @@ -1979,7 +1979,7 @@ void ARM64XEmitter::MOVI2R(ARM64Reg Rd, u64 imm, bool optimize) u64 aligned_pc = (u64)GetCodePointer() & ~0xFFF; s64 aligned_offset = (s64)imm - (s64)aligned_pc; - if (Count(upload_part) > 1 && abs64(aligned_offset) < 0xFFFFFFFFLL) + if (Count(upload_part) > 1 && abs64(aligned_offset) < 0x7FFFFFFFLL) { // Immediate we are loading is within 4GB of our aligned range // Most likely a address that we can load in one or two instructions diff --git a/Core/Host.h b/Core/Host.h index 0268a7587f..c7eed94de1 100644 --- a/Core/Host.h +++ b/Core/Host.h @@ -63,6 +63,7 @@ public: virtual bool CreateDesktopShortcut(std::string argumentPath, std::string title) {return false;} virtual void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) {} + virtual void SendUIMessage(const std::string &message, const std::string &value) {} // Used for headless. virtual bool ShouldSkipUI() { return false; } diff --git a/Core/PSPLoaders.cpp b/Core/PSPLoaders.cpp index 64577f4e1b..9df9f4e5ef 100644 --- a/Core/PSPLoaders.cpp +++ b/Core/PSPLoaders.cpp @@ -248,6 +248,7 @@ bool Load_PSP_ISO(FileLoader *fileLoader, std::string *error_string) { //in case we didn't go through EmuScreen::boot g_Config.loadGameConfig(id); + host->SendUIMessage("config_loaded", ""); INFO_LOG(LOADER,"Loading %s...", bootpath.c_str()); return __KernelLoadExec(bootpath.c_str(), 0, error_string); } diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index ffec95f590..806aec4bfc 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -328,6 +328,9 @@ void TextureCacheCommon::SetTexture(bool force) { TexCache::iterator iter = cache_.find(cachekey); TexCacheEntry *entry = nullptr; + + // Note: It's necessary to reset needshadertexclamp, for otherwise DIRTY_TEXCLAMP won't get set later. + // Should probably revisit how this works.. gstate_c.SetNeedShaderTexclamp(false); gstate_c.skipDrawReason &= ~SKIPDRAW_BAD_FB_TEXTURE; if (gstate_c.bgraTexture != isBgraBackend_) { diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index c669843952..7cba85b02b 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -156,6 +156,14 @@ void DrawEngineGLES::RestoreVAO() { } } +void DrawEngineGLES::DeviceLost() { + DestroyDeviceObjects(); +} + +void DrawEngineGLES::DeviceRestore() { + InitDeviceObjects(); +} + void DrawEngineGLES::InitDeviceObjects() { if (bufferNameCache_.empty()) { bufferNameCache_.resize(VERTEXCACHE_NAME_CACHE_SIZE); diff --git a/GPU/GLES/DrawEngineGLES.h b/GPU/GLES/DrawEngineGLES.h index d3e695a158..037758d670 100644 --- a/GPU/GLES/DrawEngineGLES.h +++ b/GPU/GLES/DrawEngineGLES.h @@ -119,8 +119,9 @@ public: fragmentTestCache_ = testCache; } void RestoreVAO(); - void InitDeviceObjects(); - void DestroyDeviceObjects(); + + void DeviceLost(); + void DeviceRestore(); void ClearTrackedVertexArrays() override; void DecimateTrackedVertexArrays(); @@ -151,6 +152,9 @@ public: void DecimateBuffers(); private: + void InitDeviceObjects(); + void DestroyDeviceObjects(); + void DoFlush(); void ApplyDrawState(int prim); void ApplyDrawStateLate(); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 9624c41253..8ba73cbd87 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -391,7 +391,7 @@ void GPU_GLES::DeviceLost() { textureCacheGL_->Clear(false); fragmentTestCache_.Clear(false); depalShaderCache_.Clear(); - drawEngine_.ClearTrackedVertexArrays(); + drawEngine_.DeviceLost(); framebufferManagerGL_->DeviceLost(); } @@ -404,6 +404,7 @@ void GPU_GLES::DeviceRestore() { textureCacheGL_->DeviceRestore(draw_); framebufferManagerGL_->DeviceRestore(draw_); + drawEngine_.DeviceRestore(); } void GPU_GLES::Reinitialize() { diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 06d2e795bf..bc462f13fc 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -948,7 +948,7 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r // TODO: We really, really should avoid calling glGetError. GLenum err = glGetError(); if (err == GL_OUT_OF_MEMORY) { - WARN_LOG(G3D, "Texture cache ran out of GPU memory; switching to low memory mode"); + WARN_LOG_REPORT(G3D, "Texture cache ran out of GPU memory; switching to low memory mode"); lowMemoryMode_ = true; decimationCounter_ = 0; Decimate(); diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index a69e122469..241181a2c7 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -144,7 +144,6 @@ void EmuScreen::bootGame(const std::string &filename) { return; } bootComplete(); - RecreateViews(); } return; } @@ -155,6 +154,8 @@ void EmuScreen::bootGame(const std::string &filename) { std::shared_ptr info = g_gameInfoCache->GetInfo(nullptr, filename, 0); if (info && !info->id.empty()) { g_Config.loadGameConfig(info->id); + // Reset views in case controls are in a different place. + RecreateViews(); } invalid_ = true; @@ -356,6 +357,9 @@ void EmuScreen::sendMessage(const char *message, const char *value) { bootPending_ = true; gamePath_ = value; } + } else if (!strcmp(message, "config_loaded")) { + // In case we need to position touch controls differently. + RecreateViews(); } else if (!strcmp(message, "control mapping") && screenManager()->topScreen() == this) { UpdateUIState(UISTATE_MENU); releaseButtons(); diff --git a/UI/HostTypes.h b/UI/HostTypes.h index 137684ec7f..102d583ce7 100644 --- a/UI/HostTypes.h +++ b/UI/HostTypes.h @@ -53,6 +53,10 @@ public: void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override { osm.Show(message, duration, color, -1, true, id); } + + void SendUIMessage(const std::string &message, const std::string &value) override { + NativeMessageReceived(message.c_str(), value.c_str()); + } }; #if !defined(MOBILE_DEVICE) && defined(USING_QT_UI) @@ -134,6 +138,10 @@ public: osm.Show(message, duration, color, -1, true, id); } + void SendUIMessage(const std::string &message, const std::string &value) override { + NativeMessageReceived(message.c_str(), value.c_str()); + } + bool GPUDebuggingActive() { auto dialogDisplayList = mainWindow->GetDialogDisplaylist(); diff --git a/Windows/WindowsHost.cpp b/Windows/WindowsHost.cpp index 302545f190..921f195167 100644 --- a/Windows/WindowsHost.cpp +++ b/Windows/WindowsHost.cpp @@ -371,3 +371,7 @@ void WindowsHost::ToggleDebugConsoleVisibility() { void WindowsHost::NotifyUserMessage(const std::string &message, float duration, u32 color, const char *id) { osm.Show(message, duration, color, -1, true, id); } + +void WindowsHost::SendUIMessage(const std::string &message, const std::string &value) { + NativeMessageReceived(message.c_str(), value.c_str()); +} diff --git a/Windows/WindowsHost.h b/Windows/WindowsHost.h index cb5cba2f1f..d7d2198c35 100644 --- a/Windows/WindowsHost.h +++ b/Windows/WindowsHost.h @@ -65,6 +65,7 @@ public: bool CreateDesktopShortcut(std::string argumentPath, std::string title) override; void NotifyUserMessage(const std::string &message, float duration = 1.0f, u32 color = 0x00FFFFFF, const char *id = nullptr) override; + void SendUIMessage(const std::string &message, const std::string &value) override; std::shared_ptr keyboard; diff --git a/ext/native/ui/ui_tween.cpp b/ext/native/ui/ui_tween.cpp index ea132505f4..b9daf58deb 100644 --- a/ext/native/ui/ui_tween.cpp +++ b/ext/native/ui/ui_tween.cpp @@ -12,6 +12,46 @@ void Tween::Apply(View *view) { DoApply(view, pos); } +template +void TweenBase::PersistData(PersistStatus status, std::string anonId, PersistMap &storage) { + struct TweenData { + float start; + float duration; + Value from; + Value to; + bool finishApplied; + }; + + PersistBuffer &buffer = storage["TweenBase::" + anonId]; + + switch (status) { + case UI::PERSIST_SAVE: + buffer.resize(sizeof(TweenData) / sizeof(int)); + { + TweenData &data = *(TweenData *)&buffer[0]; + data.start = start_; + data.duration = duration_; + data.from = from_; + data.to = to_; + data.finishApplied = finishApplied_; + } + break; + case UI::PERSIST_RESTORE: + if (buffer.size() >= sizeof(TweenData) / sizeof(int)) { + TweenData data = *(TweenData *)&buffer[0]; + start_ = data.start; + duration_ = data.duration; + from_ = data.from; + to_ = data.to; + finishApplied_ = data.finishApplied; + } + break; + } +} + +template void TweenBase::PersistData(PersistStatus status, std::string anonId, PersistMap &storage); +template void TweenBase::PersistData(PersistStatus status, std::string anonId, PersistMap &storage); + uint32_t ColorTween::Current(float pos) { return colorBlend(to_, from_, pos); } diff --git a/ext/native/ui/ui_tween.h b/ext/native/ui/ui_tween.h index 04ba166890..a17218fba3 100644 --- a/ext/native/ui/ui_tween.h +++ b/ext/native/ui/ui_tween.h @@ -23,6 +23,8 @@ public: return finishApplied_ && time_now() >= start_ + duration_; } + virtual void PersistData(PersistStatus status, std::string anonId, PersistMap &storage) = 0; + protected: float DurationOffset() { return time_now() - start_; @@ -41,6 +43,7 @@ protected: }; // This is the class all tweens inherit from. Shouldn't be used directly, see below. +// Note: Value cannot safely be a pointer (without overriding PersistData.) template class TweenBase: public Tween { public: @@ -102,6 +105,8 @@ public: return Current(Position()); } + void PersistData(PersistStatus status, std::string anonId, PersistMap &storage) override; + protected: virtual Value Current(float pos) = 0; diff --git a/ext/native/ui/view.cpp b/ext/native/ui/view.cpp index 60a41f71de..8ac8178a86 100644 --- a/ext/native/ui/view.cpp +++ b/ext/native/ui/view.cpp @@ -224,6 +224,11 @@ void View::PersistData(PersistStatus status, std::string anonId, PersistMap &sto } break; } + + ITOA stringify; + for (int i = 0; i < (int)tweens_.size(); ++i) { + tweens_[i]->PersistData(status, tag + "/" + stringify.p((int)i), storage); + } } Point View::GetFocusPosition(FocusDirection dir) {