diff --git a/CMakeLists.txt b/CMakeLists.txt
index a7b642a3ec..3f7b1ff615 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -645,6 +645,7 @@ add_library(Common STATIC
Common/Data/Collections/Hashmaps.h
Common/Data/Collections/TinySet.h
Common/Data/Collections/FastVec.h
+ Common/Data/Collections/CyclicBuffer.h
Common/Data/Collections/ThreadSafeList.h
Common/Data/Color/RGBAUtil.cpp
Common/Data/Color/RGBAUtil.h
diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj
index 0b65c4e83c..68bd679caf 100644
--- a/Common/Common.vcxproj
+++ b/Common/Common.vcxproj
@@ -882,6 +882,7 @@
+
diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index 6541f4776e..10010e8c16 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -994,6 +994,9 @@
Data\Collections
+
+ Data\Collections
+
GPU
diff --git a/Common/Data/Collections/CyclicBuffer.h b/Common/Data/Collections/CyclicBuffer.h
new file mode 100644
index 0000000000..7eaa042198
--- /dev/null
+++ b/Common/Data/Collections/CyclicBuffer.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2024- PPSSPP Project.
+
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, version 2.0 or later versions.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License 2.0 for more details.
+
+// A copy of the GPL 2.0 should have been included with the program.
+// If not, see http://www.gnu.org/licenses/
+
+// Official git repository and contact information can be found at
+// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
+
+#pragma once
+
+#include
+
+#include "Common/CommonTypes.h"
+
+
+template
+struct CyclicBuffer {
+ std::vector buffer;
+ u32 current_index;
+ bool overflow;
+
+ explicit CyclicBuffer(u32 capacity) : buffer(capacity, T()), current_index(0), overflow(false) {}
+
+ CyclicBuffer(): buffer(), current_index(0), overflow(false) {}
+
+ void push_back(const T& value);
+ void push_back(T&& value);
+
+ void clear();
+ void resize(u32 new_capacity);
+
+ std::vector get_content() const;
+};
+
+template
+std::vector CyclicBuffer::get_content() const {
+ if (!overflow) {
+ return std::vector(buffer.begin(), buffer.begin() + current_index);
+ }
+
+ std::vector ans;
+ ans.reserve(buffer.size());
+ std::copy(buffer.begin() + current_index, buffer.end(), std::back_inserter(ans));
+ std::copy(buffer.begin(), buffer.begin() + current_index, std::back_inserter(ans));
+ return ans;
+}
+
+template
+void CyclicBuffer::push_back(const T& value) {
+ buffer[current_index] = value;
+ ++current_index;
+ if (current_index == buffer.size()) {
+ current_index = 0;
+ overflow = true;
+ }
+}
+
+template
+void CyclicBuffer::push_back(T&& value) {
+ buffer[current_index] = std::move(value);
+ ++current_index;
+ if (current_index == buffer.size()) {
+ current_index = 0;
+ overflow = true;
+ }
+}
+
+template
+void CyclicBuffer::clear() {
+ buffer.clear();
+ current_index = 0;
+ overflow = false;
+}
+
+template
+void CyclicBuffer::resize(u32 new_capacity) {
+ buffer.resize(new_capacity);
+}
diff --git a/Core/MIPS/MIPSTracer.cpp b/Core/MIPS/MIPSTracer.cpp
index 20289a5d92..628f58adeb 100644
--- a/Core/MIPS/MIPSTracer.cpp
+++ b/Core/MIPS/MIPSTracer.cpp
@@ -100,6 +100,11 @@ void MIPSTracer::prepare_block(const MIPSComp::IRBlock* block, MIPSComp::IRBlock
}
bool MIPSTracer::flush_to_file() {
+ if (logging_path.empty()) {
+ WARN_LOG(Log::JIT, "The path is empty, cannot flush the trace!");
+ return false;
+ }
+
INFO_LOG(Log::JIT, "Flushing the trace to a file...");
output = File::OpenCFile(logging_path, "w");
diff --git a/Core/MIPS/MIPSTracer.h b/Core/MIPS/MIPSTracer.h
index 8ba1bef6e8..d9c873323d 100644
--- a/Core/MIPS/MIPSTracer.h
+++ b/Core/MIPS/MIPSTracer.h
@@ -26,6 +26,7 @@
#include "Core/MIPS/IR/IRJit.h"
#include "Common/Log.h"
#include "Common/File/Path.h"
+#include "Common/Data/Collections/CyclicBuffer.h"
struct TraceBlockInfo {
@@ -60,70 +61,6 @@ struct TraceBlockStorage {
};
-template
-struct CyclicBuffer {
- std::vector buffer;
- u32 current_index;
- bool overflow;
-
- explicit CyclicBuffer(u32 capacity) : buffer(capacity, T()), current_index(0), overflow(false) {}
-
- CyclicBuffer(): buffer(), current_index(0), overflow(false) {}
-
- void push_back(const T& value);
- void push_back(T&& value);
-
- void clear();
- void resize(u32 new_capacity);
-
- std::vector get_content() const;
-};
-
-template
-std::vector CyclicBuffer::get_content() const {
- if (!overflow) {
- return std::vector(buffer.begin(), buffer.begin() + current_index);
- }
-
- std::vector ans;
- ans.reserve(buffer.size());
- std::copy(buffer.begin() + current_index, buffer.end(), std::back_inserter(ans));
- std::copy(buffer.begin(), buffer.begin() + current_index, std::back_inserter(ans));
- return ans;
-}
-
-template
-void CyclicBuffer::push_back(const T& value) {
- buffer[current_index] = value;
- ++current_index;
- if (current_index == buffer.size()) {
- current_index = 0;
- overflow = true;
- }
-}
-
-template
-void CyclicBuffer::push_back(T&& value) {
- buffer[current_index] = std::move(value);
- ++current_index;
- if (current_index == buffer.size()) {
- current_index = 0;
- overflow = true;
- }
-}
-
-template
-void CyclicBuffer::clear() {
- buffer.clear();
- current_index = 0;
- overflow = false;
-}
-
-template
-void CyclicBuffer::resize(u32 new_capacity) {
- buffer.resize(new_capacity);
-}
-
// This system is meant for trace recording.
// A trace here stands for a sequence of instructions and their respective addresses in RAM.
diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp
index 2545438e71..0199a7d2d7 100644
--- a/UI/GameSettingsScreen.cpp
+++ b/UI/GameSettingsScreen.cpp
@@ -1894,16 +1894,16 @@ void DeveloperToolsScreen::CreateViews() {
list->Add(new ItemHeader(dev->T("MIPSTracer")));
MIPSTracerEnabled_ = mipsTracer.tracing_enabled;
- CheckBox *MIPSLoggerEnabled = new CheckBox(&MIPSTracerEnabled_, dev->T("MIPSTracer enabled"));
- list->Add(MIPSLoggerEnabled)->OnClick.Handle(this, &DeveloperToolsScreen::OnMIPSTracerEnabled);
- MIPSLoggerEnabled->SetEnabledFunc([]() {
+ CheckBox *MIPSTracerEnabled = new CheckBox(&MIPSTracerEnabled_, dev->T("MIPSTracer enabled"));
+ list->Add(MIPSTracerEnabled)->OnClick.Handle(this, &DeveloperToolsScreen::OnMIPSTracerEnabled);
+ MIPSTracerEnabled->SetEnabledFunc([]() {
bool temp = g_Config.iCpuCore == static_cast(CPUCore::IR_INTERPRETER) && PSP_IsInited();
return temp && Core_IsStepping() && coreState != CORE_POWERDOWN;
});
- Choice *MIPSlogging_path = list->Add(new Choice(dev->T("Select the output logging file")));
- MIPSlogging_path->OnClick.Handle(this, &DeveloperToolsScreen::OnMIPSTracerPathChanged);
- MIPSlogging_path->SetEnabledFunc([]() {
+ Choice *TraceDumpPath = list->Add(new Choice(dev->T("Select the file path for the trace")));
+ TraceDumpPath->OnClick.Handle(this, &DeveloperToolsScreen::OnMIPSTracerPathChanged);
+ TraceDumpPath->SetEnabledFunc([]() {
if (!PSP_IsInited())
return false;
return true;
@@ -2159,10 +2159,9 @@ UI::EventReturn DeveloperToolsScreen::OnMIPSTracerPathChanged(UI::EventParams &e
}
UI::EventReturn DeveloperToolsScreen::OnMIPSTracerFlushTrace(UI::EventParams &e) {
- bool success = mipsTracer.flush_to_file();
- if (!success) {
- WARN_LOG(Log::JIT, "Error: cannot flush the trace to the specified file!");
- }
+ mipsTracer.flush_to_file();
+ // The error logs are emitted inside the tracer
+
return UI::EVENT_DONE;
}
diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj
index 195b61c8b4..17feea19a7 100644
--- a/UWP/CommonUWP/CommonUWP.vcxproj
+++ b/UWP/CommonUWP/CommonUWP.vcxproj
@@ -115,6 +115,7 @@
+
diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters
index f38724008a..eaf244e0cb 100644
--- a/UWP/CommonUWP/CommonUWP.vcxproj.filters
+++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters
@@ -597,6 +597,9 @@
Data\Collections
+
+ Data\Collections
+
Data\Random