10#include "absl/strings/str_format.h"
13#include "imgui/imgui.h"
21 auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
22 ftime - std::filesystem::file_time_type::clock::now() +
23 std::chrono::system_clock::now());
24 std::time_t cftime = std::chrono::system_clock::to_time_t(sctp);
26 std::strftime(buf,
sizeof(buf),
"%Y-%m-%d %H:%M:%S", std::localtime(&cftime));
27 return std::string(buf);
43 ImGui::TextColored(ImVec4(0.7f, 0.85f, 1.0f, 1.0f),
48 ImGui::TextDisabled(
"No project loaded.");
56 if (manifest.loaded()) {
59 ImGui::Text(
"Loaded: %s", manifest.hack_name().c_str());
61 ImGui::TextColored(ImVec4(0.9f, 0.3f, 0.3f, 1.0f),
ICON_MD_ERROR);
64 ImVec4(0.9f, 0.3f, 0.3f, 1.0f),
65 "No manifest loaded — write conflict detection disabled");
69 if (manifest.loaded()) {
70 if (ImGui::BeginTable(
"ManifestInfo", 2,
71 ImGuiTableFlags_SizingStretchProp)) {
72 ImGui::TableSetupColumn(
"Label", ImGuiTableColumnFlags_WidthFixed, 120);
73 ImGui::TableSetupColumn(
"Value");
75 ImGui::TableNextRow();
76 ImGui::TableSetColumnIndex(0);
77 ImGui::TextDisabled(
"Version");
78 ImGui::TableSetColumnIndex(1);
79 ImGui::Text(
"%d", manifest.manifest_version());
81 ImGui::TableNextRow();
82 ImGui::TableSetColumnIndex(0);
83 ImGui::TextDisabled(
"Total Hooks");
84 ImGui::TableSetColumnIndex(1);
85 ImGui::Text(
"%d", manifest.total_hooks());
87 ImGui::TableNextRow();
88 ImGui::TableSetColumnIndex(0);
89 ImGui::TextDisabled(
"Protected Regions");
90 ImGui::TableSetColumnIndex(1);
91 ImGui::Text(
"%zu", manifest.protected_regions().size());
93 ImGui::TableNextRow();
94 ImGui::TableSetColumnIndex(0);
95 ImGui::TextDisabled(
"Feature Flags");
96 ImGui::TableSetColumnIndex(1);
97 ImGui::Text(
"%zu", manifest.feature_flags().size());
99 ImGui::TableNextRow();
100 ImGui::TableSetColumnIndex(0);
101 ImGui::TextDisabled(
"SRAM Variables");
102 ImGui::TableSetColumnIndex(1);
103 ImGui::Text(
"%zu", manifest.sram_variables().size());
111 if (!manifest_path.empty()) {
112 ImGui::TextDisabled(
"Path:");
114 ImGui::TextWrapped(
"%s", manifest_path.c_str());
118 if (std::filesystem::exists(manifest_path, ec)) {
119 auto mtime = std::filesystem::last_write_time(manifest_path, ec);
121 ImGui::TextDisabled(
"Modified:");
126 ImGui::TextColored(ImVec4(0.9f, 0.6f, 0.2f, 1.0f),
130 ImGui::TextDisabled(
"Path: (not configured)");
150 ImGui::TextColored(ImVec4(0.9f, 0.3f, 0.3f, 1.0f),
"%s",
153 ImGui::TextColored(ImVec4(0.3f, 0.9f, 0.3f, 1.0f),
"%s",
164 ImGui::TextColored(ImVec4(0.7f, 0.85f, 1.0f, 1.0f),
169 ImGui::TextDisabled(
"Load a manifest to view protected regions.");
176 ImGui::SetNextItemWidth(200);
177 ImGui::InputTextWithHint(
"##RegionFilter",
"Filter by module...",
180 ImGui::Text(
"%zu regions", regions.size());
185 constexpr ImGuiTableFlags kTableFlags =
186 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
187 ImGuiTableFlags_Resizable | ImGuiTableFlags_ScrollY |
188 ImGuiTableFlags_SizingFixedFit;
190 float table_height = ImGui::GetContentRegionAvail().y - 4;
191 if (table_height < 100)
194 if (ImGui::BeginTable(
"ProtectedRegions", 5, kTableFlags,
195 ImVec2(0, table_height))) {
196 ImGui::TableSetupScrollFreeze(0, 1);
197 ImGui::TableSetupColumn(
"Start", ImGuiTableColumnFlags_WidthFixed, 80);
198 ImGui::TableSetupColumn(
"End", ImGuiTableColumnFlags_WidthFixed, 80);
199 ImGui::TableSetupColumn(
"Size", ImGuiTableColumnFlags_WidthFixed, 50);
200 ImGui::TableSetupColumn(
"Hooks", ImGuiTableColumnFlags_WidthFixed, 45);
201 ImGui::TableSetupColumn(
"Module", ImGuiTableColumnFlags_WidthStretch);
202 ImGui::TableHeadersRow();
204 std::string filter_lower;
207 for (
auto& c : filter_lower) {
208 c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
212 for (
const auto& region : regions) {
214 if (!filter_lower.empty()) {
215 std::string module_lower = region.module;
216 for (
auto& c : module_lower) {
217 c =
static_cast<char>(std::tolower(
static_cast<unsigned char>(c)));
219 if (module_lower.find(filter_lower) == std::string::npos) {
224 ImGui::TableNextRow();
227 ImGui::TableSetColumnIndex(0);
228 ImGui::Text(
"$%06X", region.start);
231 ImGui::TableSetColumnIndex(1);
232 ImGui::Text(
"$%06X", region.end);
235 ImGui::TableSetColumnIndex(2);
237 (region.end > region.start) ? region.end - region.start : 0;
238 ImGui::Text(
"%u", size);
241 ImGui::TableSetColumnIndex(3);
242 ImGui::Text(
"%d", region.hook_count);
245 ImGui::TableSetColumnIndex(4);
246 ImGui::TextUnformatted(region.module.c_str());
249 if (ImGui::IsItemHovered() &&
250 ImGui::IsMouseClicked(ImGuiMouseButton_Right)) {
251 std::string range_str =
252 absl::StrFormat(
"$%06X-$%06X", region.start, region.end);
253 ImGui::SetClipboardText(range_str.c_str());
260 ImGui::TextDisabled(
"Right-click a module to copy the address range.");
275 "/hack_manifest.json");
277 if (std::filesystem::exists(auto_path, ec)) {
const std::vector< ProtectedRegion > & protected_regions() const
bool loaded() const
Check if the manifest has been loaded.
std::string status_message_
void DrawManifestStatus()
Draw Card B3: manifest status, path, mtime, reload button.
void DrawProtectedRegions()
Draw Card B4: searchable protected regions table.
project::YazeProject * project_
void Draw()
Draw the combined panel content (no ImGui::Begin/End wrapper).
std::string ResolveManifestPath() const
Resolve the absolute path to hack_manifest.json.
#define ICON_MD_CHECK_CIRCLE
#define ICON_MD_DESCRIPTION
std::string FormatFileTime(std::filesystem::file_time_type ftime)
Editors are the view controllers for the application.
core::HackManifest hack_manifest
void ReloadHackManifest()
std::string hack_manifest_file
std::string GetAbsolutePath(const std::string &relative_path) const