add more commands to dl viewer (#3504)

This commit is contained in:
Adam Bird 2023-12-26 17:13:48 -05:00 committed by GitHub
parent 99194a75f1
commit 6a7bcc4a5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,6 +9,7 @@
#include <bit> #include <bit>
#include <map> #include <map>
#include <string> #include <string>
#include <regex>
#include <libultraship/libultraship.h> #include <libultraship/libultraship.h>
#include "dlViewer.h" #include "dlViewer.h"
@ -18,15 +19,13 @@ extern "C" {
#include "variables.h" #include "variables.h"
#include "functions.h" #include "functions.h"
#include "macros.h" #include "macros.h"
extern PlayState* gPlayState;
char** ResourceMgr_ListFiles(const char* searchMask, int* resultSize);
} }
char searchString[64] = ""; char searchString[64] = "";
int displayListsSearchResultsCount; std::string activeDisplayList = "";
char** displayListsSearchResults; std::vector<std::string> displayListSearchResults;
char* activeDisplayList = nullptr; int16_t searchDebounceFrames = -1;
bool doSearch = false;
std::map<int, std::string> cmdMap = { std::map<int, std::string> cmdMap = {
{ G_SETPRIMCOLOR, "gsDPSetPrimColor" }, { G_SETPRIMCOLOR, "gsDPSetPrimColor" },
@ -36,8 +35,63 @@ std::map<int, std::string> cmdMap = {
{ G_SETINTENSITY, "gsDPSetGrayscaleColor" }, { G_SETINTENSITY, "gsDPSetGrayscaleColor" },
{ G_LOADTLUT, "gsDPLoadTLUT" }, { G_LOADTLUT, "gsDPLoadTLUT" },
{ G_ENDDL, "gsSPEndDisplayList" }, { G_ENDDL, "gsSPEndDisplayList" },
{ G_TEXTURE, "gsSPTexture" },
{ G_SETTIMG, "gsDPSetTextureImage" },
{ G_SETTIMG_OTR_HASH, "gsDPSetTextureImage" },
{ G_SETTIMG_OTR_FILEPATH, "gsDPSetTextureImage" },
{ G_RDPTILESYNC, "gsDPTileSync" },
{ G_SETTILE, "gsDPSetTile" },
{ G_RDPLOADSYNC, "gsDPLoadSync" },
{ G_LOADBLOCK, "gsDPLoadBlock" },
{ G_SETTILESIZE, "gsDPSetTileSize" },
{ G_DL, "gsSPDisplayList" },
{ G_DL_OTR_FILEPATH, "gsSPDisplayList" },
{ G_DL_OTR_HASH, "gsSPDisplayList" },
{ G_MTX, "gsSPMatrix" },
{ G_MTX_OTR, "gsSPMatrix" },
{ G_VTX, "gsSPVertex" },
{ G_VTX_OTR_FILEPATH, "gsSPVertex" },
{ G_VTX_OTR_HASH, "gsSPVertex" },
{ G_GEOMETRYMODE, "gsSPSetGeometryMode" },
{ G_SETOTHERMODE_H, "gsSPSetOtherMode_H" },
{ G_SETOTHERMODE_L, "gsSPSetOtherMode_L" },
{ G_TRI1, "gsSP1Triangle" },
{ G_TRI1_OTR, "gsSP1Triangle" },
{ G_TRI2, "gsSP2Triangles" },
{ G_SETCOMBINE, "gsDPSetCombineLERP" },
{ G_CULLDL, "gsSPCullDisplayList" },
{ G_NOOP, "gsDPNoOp" },
{ G_SPNOOP, "gsSPNoOp" },
{ G_MARKER, "LUS Custom Marker" },
}; };
void PerformDisplayListSearch() {
auto result = LUS::Context::GetInstance()->GetResourceManager()->GetArchive()->ListFiles("*" + std::string(searchString) + "*DL*");
std::regex dlSearch(".*((DL)|(DL_.*))$");
displayListSearchResults.clear();
// Filter the file results even further as StormLib can only use wildcard searching
for (size_t i = 0; i < result->size(); i++) {
std::string val = result->at(i);
if (std::regex_search(val.c_str(), dlSearch)) {
displayListSearchResults.push_back(val);
}
}
// Sort the final list
std::sort(displayListSearchResults.begin(), displayListSearchResults.end(), [](const std::string& a, const std::string& b) {
return std::lexicographical_compare(
a.begin(), a.end(),
b.begin(), b.end(),
[](char c1, char c2) {
return std::tolower(c1) < std::tolower(c2);
}
);
});
}
void DLViewerWindow::DrawElement() { void DLViewerWindow::DrawElement() {
ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver); ImGui::SetNextWindowSize(ImVec2(520, 600), ImGuiCond_FirstUseEver);
if (!ImGui::Begin("Display List Viewer", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) { if (!ImGui::Begin("Display List Viewer", &mIsVisible, ImGuiWindowFlags_NoFocusOnAppearing)) {
@ -45,22 +99,50 @@ void DLViewerWindow::DrawElement() {
return; return;
} }
ImGui::Text("%d", searchDebounceFrames);
// Debounce the search field as listing otr files is expensive
if (ImGui::InputText("Search Display Lists", searchString, ARRAY_COUNT(searchString))) { if (ImGui::InputText("Search Display Lists", searchString, ARRAY_COUNT(searchString))) {
displayListsSearchResults = ResourceMgr_ListFiles(("*" + std::string(searchString) + "*DL").c_str(), &displayListsSearchResultsCount); doSearch = true;
searchDebounceFrames = 30;
} }
if (ImGui::BeginCombo("Active Display List", activeDisplayList)) { if (doSearch) {
for (int i = 0; i < displayListsSearchResultsCount; i++) { if (searchDebounceFrames == 0) {
if (ImGui::Selectable(displayListsSearchResults[i])) { doSearch = false;
activeDisplayList = displayListsSearchResults[i]; PerformDisplayListSearch();
}
searchDebounceFrames--;
}
if (ImGui::BeginCombo("Active Display List", activeDisplayList.c_str())) {
for (size_t i = 0; i < displayListSearchResults.size(); i++) {
if (ImGui::Selectable(displayListSearchResults[i].c_str())) {
activeDisplayList = displayListSearchResults[i];
break; break;
} }
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
if (activeDisplayList != nullptr) {
if (activeDisplayList == "") {
ImGui::End();
return;
}
try {
auto res = std::static_pointer_cast<LUS::DisplayList>(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList)); auto res = std::static_pointer_cast<LUS::DisplayList>(LUS::Context::GetInstance()->GetResourceManager()->LoadResource(activeDisplayList));
for (int i = 0; i < res->Instructions.size(); i++) {
if (res->GetInitData()->Type != LUS::ResourceType::DisplayList) {
ImGui::Text("Resource type is not a Display List. Please choose another.");
ImGui::End();
return;
}
ImGui::Text("Total Instruction Size: %lu", res->Instructions.size());
for (size_t i = 0; i < res->Instructions.size(); i++) {
std::string id = "##CMD" + std::to_string(i); std::string id = "##CMD" + std::to_string(i);
Gfx* gfx = (Gfx*)&res->Instructions[i]; Gfx* gfx = (Gfx*)&res->Instructions[i];
int cmd = gfx->words.w0 >> 24; int cmd = gfx->words.w0 >> 24;
@ -70,10 +152,11 @@ void DLViewerWindow::DrawElement() {
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::PushItemWidth(25.0f); ImGui::PushItemWidth(25.0f);
ImGui::Text("%d", i); ImGui::Text("%lu", i);
ImGui::PopItemWidth(); ImGui::PopItemWidth();
ImGui::SameLine(); ImGui::SameLine();
ImGui::PushItemWidth(150.0f); ImGui::PushItemWidth(175.0f);
if (ImGui::BeginCombo(("CMD" + id).c_str(), cmdLabel.c_str())) { if (ImGui::BeginCombo(("CMD" + id).c_str(), cmdLabel.c_str())) {
if (ImGui::Selectable("gsDPSetPrimColor") && cmd != G_SETPRIMCOLOR) { if (ImGui::Selectable("gsDPSetPrimColor") && cmd != G_SETPRIMCOLOR) {
*gfx = gsDPSetPrimColor(0, 0, 0, 0, 0, 255); *gfx = gsDPSetPrimColor(0, 0, 0, 0, 0, 255);
@ -92,8 +175,10 @@ void DLViewerWindow::DrawElement() {
} }
ImGui::EndCombo(); ImGui::EndCombo();
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
if (gfx->words.w0 >> 24 == G_SETPRIMCOLOR || gfx->words.w0 >> 24 == G_SETINTENSITY || gfx->words.w0 >> 24 == G_SETENVCOLOR) {
if (cmd == G_SETPRIMCOLOR || cmd == G_SETINTENSITY || cmd == G_SETENVCOLOR) {
uint8_t r = _SHIFTR(gfx->words.w1, 24, 8); uint8_t r = _SHIFTR(gfx->words.w1, 24, 8);
uint8_t g = _SHIFTR(gfx->words.w1, 16, 8); uint8_t g = _SHIFTR(gfx->words.w1, 16, 8);
uint8_t b = _SHIFTR(gfx->words.w1, 8, 8); uint8_t b = _SHIFTR(gfx->words.w1, 8, 8);
@ -117,21 +202,141 @@ void DLViewerWindow::DrawElement() {
} }
ImGui::PopItemWidth(); ImGui::PopItemWidth();
} }
if (gfx->words.w0 >> 24 == G_RDPPIPESYNC) { if (cmd == G_RDPPIPESYNC) {
} }
if (gfx->words.w0 >> 24 == G_SETGRAYSCALE) { if (cmd == G_SETGRAYSCALE) {
bool* state = (bool*)&gfx->words.w1; bool* state = (bool*)&gfx->words.w1;
ImGui::SameLine(); ImGui::SameLine();
if (ImGui::Checkbox(("state" + id).c_str(), state)) { if (ImGui::Checkbox(("state" + id).c_str(), state)) {
// //
} }
} }
if (cmd == G_SETTILE) {
ImGui::SameLine();
ImGui::Text("FMT: %u", _SHIFTR(gfx->words.w0, 21, 3));
ImGui::SameLine();
ImGui::Text("SIZ: %u", _SHIFTR(gfx->words.w0, 19, 2));
ImGui::SameLine();
ImGui::Text("LINE: %u", _SHIFTR(gfx->words.w0, 9, 9));
ImGui::SameLine();
ImGui::Text("TMEM: %u", _SHIFTR(gfx->words.w0, 0, 9));
ImGui::SameLine();
ImGui::Text("TILE: %u", _SHIFTR(gfx->words.w1, 24, 3));
ImGui::SameLine();
ImGui::Text("PAL: %u", _SHIFTR(gfx->words.w1, 20, 4));
ImGui::SameLine();
ImGui::Text("CMT: %u", _SHIFTR(gfx->words.w1, 18, 2));
ImGui::SameLine();
ImGui::Text("MASKT: %u", _SHIFTR(gfx->words.w1, 14, 4));
ImGui::SameLine();
ImGui::Text("SHIFT: %u", _SHIFTR(gfx->words.w1, 10, 4));
ImGui::SameLine();
ImGui::Text("CMS: %u", _SHIFTR(gfx->words.w1, 8, 2));
ImGui::SameLine();
ImGui::Text("MASKS: %u", _SHIFTR(gfx->words.w1, 4, 4));
ImGui::SameLine();
ImGui::Text("SHIFTS: %u", _SHIFTR(gfx->words.w1, 0, 4));
}
if (cmd == G_SETTIMG) {
ImGui::SameLine();
ImGui::Text("FMT: %u", _SHIFTR(gfx->words.w0, 21, 3));
ImGui::SameLine();
ImGui::Text("SIZ: %u", _SHIFTR(gfx->words.w0, 19, 2));
ImGui::SameLine();
ImGui::Text("WIDTH: %u", _SHIFTR(gfx->words.w0, 0, 10));
ImGui::SameLine();
}
if (cmd == G_SETTIMG_OTR_HASH) {
gfx++;
uint64_t hash = ((uint64_t)gfx->words.w0 << 32) + (uint64_t)gfx->words.w1;
const char* fileName = ResourceGetNameByCrc(hash);
gfx--;
ImGui::SameLine();
ImGui::Text("FMT: %u", _SHIFTR(gfx->words.w0, 21, 3));
ImGui::SameLine();
ImGui::Text("SIZ: %u", _SHIFTR(gfx->words.w0, 19, 2));
ImGui::SameLine();
ImGui::Text("WIDTH: %u", _SHIFTR(gfx->words.w0, 0, 10));
ImGui::SameLine();
ImGui::Text("Texture Name: %s", fileName);
}
if (cmd == G_SETTIMG_OTR_FILEPATH) {
char* fileName = (char*)gfx->words.w1;
gfx++;
ImGui::SameLine();
ImGui::Text("FMT: %u", _SHIFTR(gfx->words.w0, 21, 3));
ImGui::SameLine();
ImGui::Text("SIZ: %u", _SHIFTR(gfx->words.w0, 19, 2));
ImGui::SameLine();
ImGui::Text("WIDTH: %u", _SHIFTR(gfx->words.w0, 0, 10));
ImGui::SameLine();
ImGui::Text("Texture Name: %s", fileName);
}
if (cmd == G_VTX) {
ImGui::SameLine();
ImGui::Text("Num VTX: %u", _SHIFTR(gfx->words.w0, 12, 8));
ImGui::SameLine();
ImGui::Text("Offset: %u", _SHIFTR(gfx->words.w0, 1, 7) - _SHIFTR(gfx->words.w0, 12, 8));
}
if (cmd == G_VTX_OTR_HASH) {
gfx++;
uint64_t hash = ((uint64_t)gfx->words.w0 << 32) + (uint64_t)gfx->words.w1;
const char* fileName = ResourceGetNameByCrc(hash);
gfx--;
ImGui::SameLine();
ImGui::Text("Num VTX: %u", _SHIFTR(gfx->words.w0, 12, 8));
ImGui::SameLine();
ImGui::Text("Offset: %u", _SHIFTR(gfx->words.w0, 1, 7) - _SHIFTR(gfx->words.w0, 12, 8));
ImGui::SameLine();
ImGui::Text("Vertex Name: %s", fileName);
}
if (cmd == G_VTX_OTR_FILEPATH) {
char* fileName = (char*)gfx->words.w1;
gfx++;
ImGui::SameLine();
ImGui::Text("Num VTX: %u", _SHIFTR(gfx->words.w0, 12, 8));
ImGui::SameLine();
ImGui::Text("Offset: %u", _SHIFTR(gfx->words.w0, 1, 7) - _SHIFTR(gfx->words.w0, 12, 8));
ImGui::SameLine();
ImGui::Text("Vertex Name: %s", fileName);
}
if (cmd == G_DL) {
}
if (cmd == G_DL_OTR_HASH) {
gfx++;
uint64_t hash = ((uint64_t)gfx->words.w0 << 32) + (uint64_t)gfx->words.w1;
const char* fileName = ResourceGetNameByCrc(hash);
ImGui::SameLine();
ImGui::Text("DL Name: %s", fileName);
}
if (cmd == G_DL_OTR_FILEPATH) {
char* fileName = (char*)gfx->words.w1;
ImGui::SameLine();
ImGui::Text("DL Name: %s", fileName);
}
// Skip second half of instructions that are over 128-bit wide
if (cmd == G_SETTIMG_OTR_HASH || cmd == G_DL_OTR_HASH || cmd == G_VTX_OTR_HASH ||
cmd == G_BRANCH_Z_OTR || cmd == G_MARKER || cmd == G_MTX_OTR) {
i++;
ImGui::Text("%lu - Reserved - Second half of %s", i, cmdLabel.c_str());
}
ImGui::EndGroup(); ImGui::EndGroup();
} }
} catch (const std::exception& e) {
ImGui::Text("Error displaying DL instructions.");
ImGui::End();
return;
} }
ImGui::End(); ImGui::End();
} }
void DLViewerWindow::InitElement() { void DLViewerWindow::InitElement() {
displayListsSearchResults = ResourceMgr_ListFiles("*DL", &displayListsSearchResultsCount); PerformDisplayListSearch();
} }