19#include "imgui/imgui.h"
20#include "imgui/misc/cpp/imgui_stdlib.h"
32 "97C05",
"98219",
"9871E",
"98C00",
"99084",
"995AF",
"99DE0",
"9A27E",
33 "9A741",
"9AC31",
"9B07E",
"9B55C",
"9B963",
"9BB99",
"9C009",
"9C4B4",
34 "9C92B",
"9CDD6",
"9D2C2",
"9E037",
"9E527",
"9EA56",
"9EF65",
"9FCD1",
35 "A0193",
"A059E",
"A0B17",
"A0FB6",
"A14A5",
"A1988",
"A1E66",
"A232B",
36 "A27F0",
"A2B6E",
"A302C",
"A3453",
"A38CA",
"A42BB",
"A470C",
"A4BA9",
37 "A5089",
"A5385",
"A5742",
"A5BCC",
"A6017",
"A6361",
"A66F8"};
40 "A8E5D",
"A9435",
"A9934",
"A9D83",
"AA2F1",
"AA6D4",
"AABE4",
"AB127",
41 "AB65A",
"ABBDD",
"AC38D",
"AC797",
"ACCC8",
"AD0AE",
"AD245",
"AD554",
42 "ADAAC",
"ADECC",
"AE453",
"AE9D2",
"AEF40",
"AF3C9",
"AF92E",
"AFE9D",
43 "B03D2",
"B09AC",
"B0F0C",
"B1430",
"B1859",
"B1E01",
"B229A",
"B2854",
44 "B2D27",
"B31D7",
"B3B58",
"B40B5",
"B45A5",
"B4D64",
"B5031",
"B555F",
45 "B5F30",
"B6858",
"B70DD",
"B7526",
"B79EC",
"B7C83",
"B80F7",
"B85CC",
46 "B8A3F",
"B8F97",
"B94F2",
"B9A20",
"B9E9A",
"BA3A2",
"BA8F6",
"BACDC",
47 "BB1F9",
"BB781",
"BBCCA",
"BC26D",
"BC7D4",
"BCBB0",
"BD082",
"BD5FC",
48 "BE115",
"BE5C2",
"BEB63",
"BF0CB",
"BF607",
"BFA55",
"BFD71",
"C017D",
49 "C0567",
"C0981",
"C0BA7",
"C116D",
"C166A",
"C1FE0",
"C24CE",
"C2B19"};
55 return std::filesystem::absolute(path).string();
85 constexpr ImGuiTableFlags kWorkspaceFlags =
86 ImGuiTableFlags_Resizable | ImGuiTableFlags_SizingStretchProp |
87 ImGuiTableFlags_NoSavedSettings;
89 if (ImGui::BeginTable(
"##PrototypeWorkspace", 2, kWorkspaceFlags)) {
90 ImGui::TableSetupColumn(
"Inspector", ImGuiTableColumnFlags_WidthFixed,
92 ImGui::TableSetupColumn(
"Preview", ImGuiTableColumnFlags_WidthStretch,
94 ImGui::TableNextColumn();
96 ImGui::TableNextColumn();
108 "Decode CGX, SCR, COL, and raw prototype data directly inside the "
109 "graphics workspace so research assets can be compared without leaving "
112 "SCR files are SNES tilemaps. Pair them with matching CGX and COL data "
113 "to reconstruct early HUDs, menus, and screen layouts.",
122 "Load a CGX, BIN, or Super Donkey source to start previewing.",
169 ImGui::BeginChild(
"##PrototypeInspector", ImVec2(0, 0),
false,
170 ImGuiWindowFlags_AlwaysVerticalScrollbar);
172 auto sync_status = [
this](
const absl::Status& section_status) {
177 ImGuiTreeNodeFlags_DefaultOpen)) {
184 ImGuiTreeNodeFlags_DefaultOpen)) {
188 if (ImGui::CollapsingHeader(
ICON_MD_BUILD " Advanced Inputs",
189 ImGuiTreeNodeFlags_DefaultOpen)) {
200 ImGui::BeginChild(
"##PrototypePreview", ImVec2(0, 0),
false,
201 ImGuiWindowFlags_AlwaysVerticalScrollbar);
204 if (ImGui::BeginTabBar(
"##PrototypePreviewTabs")) {
205 if (ImGui::BeginTabItem(
"Graphics")) {
209 if (ImGui::BeginTabItem(
"Screen")) {
213 if (ImGui::BeginTabItem(
"Super Donkey")) {
226 "Load a CGX tilesheet or decode a BIN source.");
233 if (has_cgx_preview && has_bin_preview) {
243 "Switch between the direct CGX decode and the generic BIN preview.");
250 const char* preview_label =
263 "No screen preview available",
264 "Load SCR data after CGX to reconstruct a prototype screen.");
277 "Use the experimental decoder after loading the prototype "
282 ImGui::SetNextItemWidth(120.0f);
285 ImGui::SetNextItemWidth(120.0f);
290 int current_column = 0;
292 ImGui::BeginChild(
"##SuperDonkeySheets", ImVec2(0, 0),
true,
293 ImGuiWindowFlags_AlwaysVerticalScrollbar);
296 if (!bitmap.is_active() || !bitmap.texture()) {
301 ImGui::Image((ImTextureID)(intptr_t)bitmap.texture(),
302 ImVec2(tile_width, tile_height));
303 ImGui::Text(
"Sheet %02zu", i);
317 const char* detail) {
320 ImGui::TextWrapped(
"%s", detail);
328 ImGui::SetNextWindowSize(ImVec2(900.0f, 540.0f), ImGuiCond_FirstUseEver);
329 ImGui::SetNextWindowSizeConstraints(ImVec2(720.0f, 420.0f),
330 ImVec2(1600.0f, FLT_MAX));
344 const char* browse_label,
345 const char* browse_spec) {
346 bool changed =
false;
348 options.
filters.push_back({browse_label, browse_spec});
349 options.
filters.push_back({
"All Files",
"*"});
352 ImGui::SetNextItemWidth(-68.0f);
353 changed = ImGui::InputTextWithHint(
"##Path", hint, path);
357 if (!selected.empty()) {
358 *path = NormalizeSelectedPath(selected);
362 if (ImGui::IsItemHovered()) {
363 ImGui::SetTooltip(
"Browse");
366 ImGui::BeginDisabled(path->empty());
368 ImGui::SetClipboardText(path->c_str());
370 if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
371 ImGui::SetTooltip(
"Copy path");
373 ImGui::EndDisabled();
379 ImGui::SeparatorText(
"CGX Tilesheet");
381 "CGX Files",
"cgx,bin");
383 ImGui::SetNextItemWidth(120.0f);
393 ImGui::EndDisabled();
399 ImGui::SeparatorText(
"SCR Screen");
401 "SCR Files",
"scr,pnl,bin,bak");
403 ImGui::SetNextItemWidth(120.0f);
412 ImGui::EndDisabled();
415 "SCR preview depends on an already decoded CGX tilesheet. Use this "
416 "to reconstruct prototype HUDs and menus from raw SNES tilemaps.");
423 ImGui::SeparatorText(
"Palette Source");
426 "COL Files",
"col,bak,bin");
433 ImGui::EndDisabled();
436 if (ImGui::Checkbox(
"Prefer external COL palette",
441 bool disabled_toggle =
false;
442 ImGui::BeginDisabled();
443 ImGui::Checkbox(
"Prefer external COL palette", &disabled_toggle);
444 ImGui::EndDisabled();
448 bool refresh_palette =
false;
453 if (refresh_palette) {
459 ImGui::SetNextItemWidth(220.0f);
460 bool palette_changed = ImGui::Combo(
462 IM_ARRAYSIZE(kPaletteGroupAddressesKeys));
465 ImGui::SetNextItemWidth(120.0f);
466 if (ImGui::InputInt(
"ROM Palette", &palette_index)) {
468 palette_changed =
true;
471 if (palette_changed) {
476 "Load a ROM or a COL file to apply palette data to prototype previews.",
484 ImGui::SeparatorText(
"Raw BIN / ROM Decompression");
486 "Binary Sources",
"bin,hex,sfc,smc");
497 ImGui::EndDisabled();
503 ImGui::SeparatorText(
"Clipboard Source");
514 ImGui::EndDisabled();
523 const int decode_size =
524 static_cast<int>(
clipboard_size_ == 0 ? kDefaultClipboardDecompressSize
529 ImGui::EndDisabled();
535 ImGui::SeparatorText(
"OBJ Source");
537 "OBJ Files",
"obj,bak");
544 ImGui::EndDisabled();
555 ImGui::SeparatorText(
"Tilemap Source");
557 "Tilemap Files",
"dat,bin,hex");
564 ImGui::EndDisabled();
568 "Tilemap bytes loaded for research. Structured preview is pending.",
576 ImGui::SeparatorText(
"Experimental");
587 ImGui::EndDisabled();
589 "Run the prototype sheet decoder against the currently selected BIN "
606 return absl::OkStatus();
616 return absl::FailedPreconditionError(
"SCR data is not loaded.");
619 return absl::FailedPreconditionError(
620 "Decode a CGX tilesheet before reconstructing the SCR preview.");
630 return absl::OkStatus();
649 return absl::OkStatus();
660 return absl::OkStatus();
668 if (!decomp_sheet.ok()) {
669 return decomp_sheet.status();
672 return absl::OkStatus();
676 const char* text = ImGui::GetClipboardText();
677 if (!text || *text ==
'\0') {
678 return absl::InvalidArgumentError(
"Clipboard is empty.");
681 const auto clipboard_data = std::vector<uint8_t>(text, text + strlen(text));
684 return absl::OkStatus();
699 return absl::OkStatus();
705 const int offset_value = std::stoi(offset,
nullptr, 16);
717 const int offset_value = std::stoi(offset,
nullptr, 16);
730 return absl::OkStatus();
766 if (palette_group && rom_palette_index_ < palette_group->size()) {
773 QueueTextureRefresh(&bitmap);
absl::Status LoadFromFile(const std::string &filename, const LoadOptions &options=LoadOptions::Defaults())
absl::Status LoadFromData(const std::vector< uint8_t > &data, const LoadOptions &options=LoadOptions::Defaults())
absl::Status DrawTilemapImportSection()
gfx::SnesPalette col_file_palette_
std::vector< uint8_t > extra_cgx_data_
absl::Status RebuildScreenPreview()
absl::Status DrawClipboardSection()
void ApplyPreviewPalette(gfx::Bitmap &bitmap)
uint64_t num_sheets_to_load_
std::vector< uint8_t > decoded_scr_data_
void DrawGraphicsPreview()
void DrawInspectorColumn()
std::vector< uint8_t > scr_data_
void DrawEmptyState(const char *title, const char *detail)
uint64_t rom_palette_index_
std::vector< uint8_t > import_data_
int rom_palette_group_index_
absl::Status LoadBinPreview()
int prototype_sheet_columns_
int active_graphics_preview_
absl::Status LoadCgxData()
uint64_t clipboard_offset_
std::vector< SDL_Color > decoded_col_
zelda3::GameData * game_data_
gui::Canvas import_canvas_
absl::Status DrawScrImportSection()
absl::Status DrawExperimentalSection()
void DrawMemoryEditorWindow()
absl::Status LoadColData()
bool HasScreenPreview() const
absl::Status DrawBinImportSection()
uint64_t external_palette_index_
std::array< gfx::Bitmap, zelda3::kNumGfxSheets > gfx_sheets_
bool DrawPathEditor(const char *id, const char *hint, std::string *path, const char *browse_label, const char *browse_spec)
std::vector< uint8_t > cgx_data_
gfx::PaletteGroup col_file_palette_group_
std::string tilemap_path_
bool HasGraphicsPreview() const
absl::Status DrawCgxImportSection()
void DrawLoadedAssetBadges()
absl::Status ImportClipboard()
absl::Status LoadObjData()
absl::Status DecompressImportData(int size)
absl::Status LoadScrData()
void RefreshPreviewPalettes()
std::vector< uint8_t > decoded_cgx_
float prototype_sheet_scale_
bool use_external_palette_
absl::Status DrawPaletteSection()
void Draw(bool *p_open) override
Draw the panel content.
absl::Status LoadTilemapData()
void DrawSuperDonkeyPreview()
absl::Status DrawObjImportSection()
bool UsingExternalPalette() const
absl::Status DecompressSuperDonkey()
bool HasPrototypeSheetPreview() const
void QueueTextureCommand(TextureCommandType type, Bitmap *bitmap)
Represents a bitmap image optimized for SNES ROM hacking.
void Create(int width, int height, int depth, std::span< uint8_t > data)
Create a bitmap with the given dimensions and data.
TextureHandle texture() const
void SetPalette(const SnesPalette &palette)
Set the palette for the bitmap using SNES palette format.
SDL_Surface * surface() const
Represents a palette of colors for the Super Nintendo Entertainment System (SNES).
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_SCREEN_SEARCH_DESKTOP
#define ICON_MD_TRAVEL_EXPLORE
#define ICON_MD_CONTENT_PASTE
#define ICON_MD_IMAGE_SEARCH
#define ICON_MD_CONTENT_COPY
#define ASSIGN_OR_RETURN(type_variable_name, expression)
std::string NormalizeSelectedPath(const std::string &path)
void QueueTextureRefresh(gfx::Bitmap *bitmap)
constexpr uint64_t kDefaultClipboardDecompressSize
const std::string kSuperDonkeySprites[]
const std::string kSuperDonkeyTiles[]
absl::StatusOr< std::vector< uint8_t > > DecompressV2(const uint8_t *data, int offset, int size, int mode, size_t rom_size)
Decompresses a buffer of data using the LC_LZ2 algorithm.
constexpr int kNintendoMode1
absl::Status LoadScr(std::string_view filename, uint8_t input_value, std::vector< uint8_t > &map_data)
Load Scr file (screen data)
std::vector< SDL_Color > DecodeColFile(const std::string_view filename)
Decode color file.
constexpr int kTilesheetHeight
constexpr int kTilesheetWidth
absl::Status LoadCgx(uint8_t bpp, std::string_view filename, std::vector< uint8_t > &cgx_data, std::vector< uint8_t > &cgx_loaded, std::vector< uint8_t > &cgx_header)
Load Cgx file (graphical content)
constexpr const char * kPaletteGroupAddressesKeys[]
absl::Status DrawScrWithCgx(uint8_t bpp, std::vector< uint8_t > &map_bitmap_data, std::vector< uint8_t > &map_data, std::vector< uint8_t > &cgx_loaded)
Draw screen tilemap with graphical data.
constexpr int kTilesheetDepth
std::vector< uint8_t > SnesTo8bppSheet(std::span< const uint8_t > sheet, int bpp, int num_sheets)
absl::StatusOr< PaletteGroup > CreatePaletteGroupFromColFile(std::vector< SnesColor > &palette_rows)
std::vector< SnesColor > GetColFileData(uint8_t *data)
void BitmapCanvasPipeline(gui::Canvas &canvas, gfx::Bitmap &bitmap, int width, int height, int tile_size, bool is_loaded, bool scrollbar, int canvas_id)
void ColoredText(const char *text, const ImVec4 &color)
bool SliderFloatWheel(const char *label, float *v, float v_min, float v_max, const char *format, float wheel_step, ImGuiSliderFlags flags)
void SectionHeader(const char *icon, const char *label, const ImVec4 &color)
bool ToggleButton(const char *label, bool active, const ImVec2 &size)
bool InputHex(const char *label, uint64_t *data)
bool ColoredButton(const char *label, ButtonType type, const ImVec2 &size)
ImVec4 GetDisabledColor()
void ColoredTextF(const ImVec4 &color, const char *fmt,...)
void SelectablePalettePipeline(uint64_t &palette_id, bool &refresh_graphics, gfx::SnesPalette &palette)
void HelpMarker(const char *desc)
void StatusBadge(const char *text, ButtonType type)
#define RETURN_IF_ERROR(expr)
PaletteGroup * get_group(const std::string &group_name)
std::vector< FileDialogFilter > filters
gfx::PaletteGroupMap palette_groups