mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-29 17:15:40 +00:00
Extended -gfx-state to produce culling node analysis
This commit is contained in:
parent
9dd2b24729
commit
76817790d4
|
@ -162,11 +162,6 @@
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
extern bool g_forceFlushModels;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
namespace Legacy3D {
|
namespace Legacy3D {
|
||||||
|
|
||||||
// Microsoft doesn't provide isnan() and isinf()
|
// Microsoft doesn't provide isnan() and isinf()
|
||||||
|
@ -668,9 +663,13 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
m_colorTableAddr &= 0x000FFFFF; // clamp to 4MB (in words) range
|
m_colorTableAddr &= 0x000FFFFF; // clamp to 4MB (in words) range
|
||||||
}
|
}
|
||||||
|
|
||||||
//printf("%08x NODE %d\n", addr, stackDepth);
|
#ifdef DEBUG
|
||||||
//for (int i = 0; i < 8; i++)
|
bool oldDebugHighlightAll = m_debugHighlightAll;
|
||||||
// printf(" %08x\n", node[i]);
|
m_debugHighlightAll = (m_debugHighlightCullingNodeIdx >= 0) && (node[m_debugHighlightCullingNodeIdx] & m_debugHighlightCullingNodeMask) != 0;
|
||||||
|
#endif
|
||||||
|
//printf("%08x NODE %d\n", addr, stackDepth);
|
||||||
|
//for (int i = 0; i < 8; i++)
|
||||||
|
// printf(" %08x\n", node[i]);
|
||||||
|
|
||||||
// Debug: texture offset? (NOTE: offsets 1 and 2 don't exist on step 1.0)
|
// Debug: texture offset? (NOTE: offsets 1 and 2 don't exist on step 1.0)
|
||||||
//if (node[0x02]&0xFFFF)
|
//if (node[0x02]&0xFFFF)
|
||||||
|
@ -716,6 +715,9 @@ void CLegacy3D::DescendCullingNode(UINT32 addr)
|
||||||
|
|
||||||
// Proceed to second link
|
// Proceed to second link
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
#ifdef DEBUG
|
||||||
|
m_debugHighlightAll = oldDebugHighlightAll;
|
||||||
|
#endif
|
||||||
if ((node[0x00] & 0x07) != 0x06) // seems to indicate second link is invalid (fixes circular references)
|
if ((node[0x00] & 0x07) != 0x06) // seems to indicate second link is invalid (fixes circular references)
|
||||||
DescendNodePtr(node2Ptr);
|
DescendNodePtr(node2Ptr);
|
||||||
--stackDepth;
|
--stackDepth;
|
||||||
|
@ -1001,7 +1003,11 @@ void CLegacy3D::RenderFrame(void)
|
||||||
|
|
||||||
// Draw
|
// Draw
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (g_forceFlushModels)
|
m_debugHighlightPolyHeaderIdx = m_config["Debug/HighlightPolyHeaderIdx"].ValueAsDefault<int>(-1);
|
||||||
|
m_debugHighlightPolyHeaderMask = m_config["Debug/HighlightPolyHeaderMask"].ValueAsDefault<uint32_t>(0);
|
||||||
|
m_debugHighlightCullingNodeIdx = m_config["Debug/HighlightCullingNodeIdx"].ValueAsDefault<int>(-1);
|
||||||
|
m_debugHighlightCullingNodeMask = m_config["Debug/HighlightCullingNodeMask"].ValueAsDefault<uint32_t>(0);
|
||||||
|
if (m_config["Debug/ForceFlushModels"].ValueAsDefault<bool>(false))
|
||||||
ClearModelCache(&VROMCache);
|
ClearModelCache(&VROMCache);
|
||||||
#endif
|
#endif
|
||||||
ClearModelCache(&PolyCache);
|
ClearModelCache(&PolyCache);
|
||||||
|
|
|
@ -390,6 +390,15 @@ private:
|
||||||
|
|
||||||
const Util::Config::Node &m_config;
|
const Util::Config::Node &m_config;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
// Debug
|
||||||
|
int m_debugHighlightPolyHeaderIdx = -1;
|
||||||
|
uint32_t m_debugHighlightPolyHeaderMask = 0;
|
||||||
|
int m_debugHighlightCullingNodeIdx = -1;
|
||||||
|
uint32_t m_debugHighlightCullingNodeMask = 0;
|
||||||
|
bool m_debugHighlightAll = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Stepping
|
// Stepping
|
||||||
int step;
|
int step;
|
||||||
int offset; // offset to subtract for words 3 and higher of culling nodes
|
int offset; // offset to subtract for words 3 and higher of culling nodes
|
||||||
|
|
|
@ -754,9 +754,9 @@ void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P,
|
||||||
contourProcessing = 1.0f;
|
contourProcessing = 1.0f;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (g_testPolyHeaderIdx >= 0)
|
if (m_debugHighlightPolyHeaderIdx >= 0 || m_debugHighlightAll)
|
||||||
{
|
{
|
||||||
if ((P->header[g_testPolyHeaderIdx] & g_testPolyHeaderMask))
|
if ((P->header[m_debugHighlightPolyHeaderIdx] & m_debugHighlightPolyHeaderMask) || m_debugHighlightAll)
|
||||||
{
|
{
|
||||||
r = 0.;
|
r = 0.;
|
||||||
g = 1.;
|
g = 1.;
|
||||||
|
|
|
@ -410,9 +410,6 @@ static void SaveFrameBuffer(const std::string &file)
|
||||||
Util::WriteSurfaceToBMP<Util::RGBA8>(file, pixels.get(), totalXRes, totalYRes, true);
|
Util::WriteSurfaceToBMP<Util::RGBA8>(file, pixels.get(), totalXRes, totalYRes, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool g_forceFlushModels = false;
|
|
||||||
int g_testPolyHeaderIdx = -1;
|
|
||||||
uint32_t g_testPolyHeaderMask = 0;
|
|
||||||
static std::string s_gfxStatePath;
|
static std::string s_gfxStatePath;
|
||||||
|
|
||||||
static std::string GetFileBaseName(const std::string &file)
|
static std::string GetFileBaseName(const std::string &file)
|
||||||
|
@ -440,23 +437,53 @@ static void TestPolygonHeaderBits(IEmulator *Emu)
|
||||||
0xff0300ff // contour, luminous, etc.
|
0xff0300ff // contour, luminous, etc.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const std::vector<uint32_t> unknownCullingNodeBits
|
||||||
|
{
|
||||||
|
0xffffffff,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000,
|
||||||
|
0x00000000
|
||||||
|
};
|
||||||
|
|
||||||
GLint readBuffer;
|
GLint readBuffer;
|
||||||
glGetIntegerv(GL_READ_BUFFER, &readBuffer);
|
glGetIntegerv(GL_READ_BUFFER, &readBuffer);
|
||||||
glReadBuffer(GL_FRONT);
|
glReadBuffer(GL_FRONT);
|
||||||
|
|
||||||
// Render separate image for each unknown bit
|
// Render separate image for each unknown bit
|
||||||
g_forceFlushModels = true;
|
s_runtime_config.Set("Debug/ForceFlushModels", true);
|
||||||
for (int idx = 0; idx < 7; idx++)
|
for (int idx = 0; idx < 7; idx++)
|
||||||
{
|
{
|
||||||
for (int bit = 0; bit < 32; bit++)
|
for (int bit = 0; bit < 32; bit++)
|
||||||
{
|
{
|
||||||
uint32_t mask = 1 << bit;
|
uint32_t mask = 1 << bit;
|
||||||
g_testPolyHeaderIdx = idx;
|
s_runtime_config.Set("Debug/HighlightPolyHeaderIdx", idx);
|
||||||
g_testPolyHeaderMask = mask;
|
s_runtime_config.Set("Debug/HighlightPolyHeaderMask", mask);
|
||||||
if ((unknownPolyBits[idx] & mask))
|
if ((unknownPolyBits[idx] & mask))
|
||||||
{
|
{
|
||||||
Emu->RenderFrame();
|
Emu->RenderFrame();
|
||||||
std::string file = Util::Format() << "Analysis/" << GetFileBaseName(s_gfxStatePath) << "." << idx << "_" << Util::Hex(mask) << ".bmp";
|
std::string file = Util::Format() << "Analysis/" << GetFileBaseName(s_gfxStatePath) << "." << "poly" << "." << idx << "_" << Util::Hex(mask) << ".bmp";
|
||||||
|
SaveFrameBuffer(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int idx = 0; idx < 10; idx++)
|
||||||
|
{
|
||||||
|
for (int bit = 0; bit < 32; bit++)
|
||||||
|
{
|
||||||
|
uint32_t mask = 1 << bit;
|
||||||
|
s_runtime_config.Set("Debug/HighlightCullingNodeIdx", idx);
|
||||||
|
s_runtime_config.Set("Debug/HighlightCullingNodeMask", mask);
|
||||||
|
if ((unknownCullingNodeBits[idx] & mask))
|
||||||
|
{
|
||||||
|
Emu->RenderFrame();
|
||||||
|
std::string file = Util::Format() << "Analysis/" << GetFileBaseName(s_gfxStatePath) << "." << "culling" << "." << idx << "_" << Util::Hex(mask) << ".bmp";
|
||||||
SaveFrameBuffer(file);
|
SaveFrameBuffer(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -473,7 +500,8 @@ static void TestPolygonHeaderBits(IEmulator *Emu)
|
||||||
{
|
{
|
||||||
std::string contents = s_polyAnalysisHTMLPrologue;
|
std::string contents = s_polyAnalysisHTMLPrologue;
|
||||||
contents += " var g_file_base_name = '" + GetFileBaseName(s_gfxStatePath) + "';\n";
|
contents += " var g_file_base_name = '" + GetFileBaseName(s_gfxStatePath) + "';\n";
|
||||||
contents += " var g_unknown_bits = [" + std::string(Util::Format(",").Join(unknownPolyBits)) + "];\n";
|
contents += " var g_unknown_poly_bits = [" + std::string(Util::Format(",").Join(unknownPolyBits)) + "];\n";
|
||||||
|
contents += " var g_unknown_culling_bits = [" + std::string(Util::Format(",").Join(unknownCullingNodeBits)) + "];\n";
|
||||||
contents += s_polyAnalysisHTMLEpilogue;
|
contents += s_polyAnalysisHTMLEpilogue;
|
||||||
fs << contents;
|
fs << contents;
|
||||||
printf("Produced: %s\n", file.c_str());
|
printf("Produced: %s\n", file.c_str());
|
||||||
|
|
|
@ -33,6 +33,7 @@ static const char s_polyAnalysisHTMLPrologue[] =
|
||||||
"<html>\n"
|
"<html>\n"
|
||||||
"<head>\n"
|
"<head>\n"
|
||||||
" <style>\n"
|
" <style>\n"
|
||||||
|
" left { float: left; }\n"
|
||||||
" table { table-layout: fixed; }\n"
|
" table { table-layout: fixed; }\n"
|
||||||
" td { border: 1px solid black; width: 1em; }\n"
|
" td { border: 1px solid black; width: 1em; }\n"
|
||||||
" td.nonselectable { background-color: gray; }\n"
|
" td.nonselectable { background-color: gray; }\n"
|
||||||
|
@ -42,10 +43,13 @@ static const char s_polyAnalysisHTMLPrologue[] =
|
||||||
" <script src='https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js'></script>\n"
|
" <script src='https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js'></script>\n"
|
||||||
"</head>\n"
|
"</head>\n"
|
||||||
"<body>\n"
|
"<body>\n"
|
||||||
" <div id='Header'></div>\n"
|
" <div id='Header'>\n"
|
||||||
|
" <div id='PolyBits' class='left'></div>\n"
|
||||||
|
" <div id='CullingBits' class='left'></div>\n"
|
||||||
|
" </div>\n"
|
||||||
" <div><img id='Image' /></div>\n"
|
" <div><img id='Image' /></div>\n"
|
||||||
" <script>\n"
|
" <script>\n"
|
||||||
// Insert g_file_base_name and g_unknown bits here, then append epilogue
|
// Insert g_file_base_name, g_unknown_poly_bits, and g_unknown_culling_bits here, then append epilogue
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char s_polyAnalysisHTMLEpilogue[] =
|
static const char s_polyAnalysisHTMLEpilogue[] =
|
||||||
|
@ -54,27 +58,28 @@ static const char s_polyAnalysisHTMLEpilogue[] =
|
||||||
" {\n"
|
" {\n"
|
||||||
" return '0x' + ('0000000'+Number(val).toString(16)).slice(-8);\n"
|
" return '0x' + ('0000000'+Number(val).toString(16)).slice(-8);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" function getOnClickHandler(table, td, word, mask)\n"
|
|
||||||
|
" function createOnClickHandler(type, table, td, word, mask)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" return function()\n"
|
" return function()\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" var file = g_file_base_name + '.' + word + '_' + hex32(mask) + '.bmp';\n"
|
" var file = g_file_base_name + '.' + type + '.' + word + '_' + hex32(mask) + '.bmp';\n"
|
||||||
" table.find('td').removeClass('selected'); // remove from all cells\n"
|
" $('td').removeClass('selected'); // remove from all cells\n"
|
||||||
" td.addClass('selected');\n"
|
" td.addClass('selected');\n"
|
||||||
" $('#Image').empty();\n"
|
" $('#Image').empty();\n"
|
||||||
" $('#Image').attr('src', file);\n"
|
" $('#Image').attr('src', file);\n"
|
||||||
" };\n"
|
" };\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" $(document).ready(function()\n"
|
|
||||||
|
" function buildTable(num_words, type, unknown_bits)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" // Construct table\n"
|
|
||||||
" var table = $('<table></table>');\n"
|
" var table = $('<table></table>');\n"
|
||||||
" var bits_tr = $('<tr></tr>'); // first row will be bit legend\n"
|
" var bits_tr = $('<tr></tr>'); // first row will be bit legend\n"
|
||||||
" bits_tr.append($('<td></td>')); // column for word numbers\n"
|
" bits_tr.append($('<td></td>')); // column for word numbers\n"
|
||||||
" for (var bit = 31; bit >= 0; bit--)\n"
|
" for (var bit = 31; bit >= 0; bit--)\n"
|
||||||
" bits_tr.append($('<td>'+bit+'</td>'));\n"
|
" bits_tr.append($('<td>'+bit+'</td>'));\n"
|
||||||
" table.append(bits_tr);\n"
|
" table.append(bits_tr);\n"
|
||||||
" for (var word = 0; word < 7; word++)\n"
|
" for (var word = 0; word < num_words; word++)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" var tr = $('<tr></tr>');\n"
|
" var tr = $('<tr></tr>');\n"
|
||||||
" tr.append($('<td>'+word+'</td>'));\n"
|
" tr.append($('<td>'+word+'</td>'));\n"
|
||||||
|
@ -82,15 +87,28 @@ static const char s_polyAnalysisHTMLEpilogue[] =
|
||||||
" {\n"
|
" {\n"
|
||||||
" var mask = 1 << bit;\n"
|
" var mask = 1 << bit;\n"
|
||||||
" var td = $('<td></td>');\n"
|
" var td = $('<td></td>');\n"
|
||||||
" if (g_unknown_bits[word] & mask)\n"
|
" if (unknown_bits[word] & mask)\n"
|
||||||
" td.addClass('selectable').click(getOnClickHandler(table, td, word, mask));\n"
|
" td.addClass('selectable').click(createOnClickHandler(type, table, td, word, mask));\n"
|
||||||
" else\n"
|
" else\n"
|
||||||
" td.addClass('nonselectable');\n"
|
" td.addClass('nonselectable');\n"
|
||||||
" tr.append(td);\n"
|
" tr.append(td);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" table.append(tr);\n"
|
" table.append(tr);\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" $('#Header').append(table);\n"
|
" return table;"
|
||||||
|
" }\n"
|
||||||
|
|
||||||
|
" $(document).ready(function()\n"
|
||||||
|
" {\n"
|
||||||
|
" // Construct tables\n"
|
||||||
|
" var poly_table = buildTable(7, 'poly', g_unknown_poly_bits);\n"
|
||||||
|
" var poly_title = $('<p></p>').text('Polygon Header');\n"
|
||||||
|
" $('#PolyBits').append(poly_title);\n"
|
||||||
|
" $('#PolyBits').append(poly_table);\n"
|
||||||
|
" var culling_table = buildTable(10, 'culling', g_unknown_culling_bits);\n"
|
||||||
|
" var culling_title = $('<p></p>').text('Culling Node');\n"
|
||||||
|
" $('#CullingBits').append(culling_title);\n"
|
||||||
|
" $('#CullingBits').append(culling_table);\n"
|
||||||
" });\n"
|
" });\n"
|
||||||
" </script>\n"
|
" </script>\n"
|
||||||
"</body>\n"
|
"</body>\n"
|
||||||
|
|
Loading…
Reference in a new issue