mirror of
https://github.com/RetroDECK/Supermodel.git
synced 2024-11-26 15:45:41 +00:00
Polygon header bit analysis code (need to #define DEBUG and use -gfx-state option)
This commit is contained in:
parent
04fba1466d
commit
c0ec610e99
|
@ -162,6 +162,11 @@
|
|||
#include <cmath>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef DEBUG
|
||||
extern bool g_forceFlushModels;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Legacy3D {
|
||||
|
||||
// Microsoft doesn't provide isnan() and isinf()
|
||||
|
@ -989,7 +994,10 @@ void CLegacy3D::RenderFrame(void)
|
|||
if (fogIntensityLoc != -1) glEnableVertexAttribArray(fogIntensityLoc);
|
||||
|
||||
// Draw
|
||||
//ClearModelCache(&VROMCache); // only enable this for debugging
|
||||
#ifdef DEBUG
|
||||
if (g_forceFlushModels)
|
||||
ClearModelCache(&VROMCache);
|
||||
#endif
|
||||
ClearModelCache(&PolyCache);
|
||||
for (int pri = 0; pri <= 3; pri++)
|
||||
{
|
||||
|
|
|
@ -83,6 +83,12 @@
|
|||
#include <cstring>
|
||||
#include "Supermodel.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
extern int g_testPolyHeaderIdx;
|
||||
extern uint32_t g_testPolyHeaderMask;
|
||||
#endif
|
||||
|
||||
|
||||
namespace Legacy3D {
|
||||
|
||||
/******************************************************************************
|
||||
|
@ -545,32 +551,6 @@ void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P,
|
|||
if (!(P->header[0]&0x80) || (shininess == 0)) // bit 0x80 seems to enable specular lighting
|
||||
shininess = -1; // disable
|
||||
|
||||
#if 0
|
||||
if (texFormat==5)//texFormat==6||texFormat==2)
|
||||
{
|
||||
//printf("%03X\n", P->header[4]>>8);
|
||||
//texEnable=0;
|
||||
g=b=1.0;
|
||||
r=1.0f;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
int testWord = 0;
|
||||
int testBit = 7;
|
||||
//if ((P->header[testWord]&(1<<testBit)))
|
||||
if (((P->header[0]>>24) & 0x3) != 0)
|
||||
//if (!((P->header[0]>>26) & 0x3F) && (P->header[0]&0x80))
|
||||
{
|
||||
texEnable = 0;
|
||||
r=b=0;
|
||||
g=1.0f;
|
||||
g = ((P->header[0]>>26)&0x3F) * (1.0f/64.0f);
|
||||
//if (!lightEnable)
|
||||
// b=1.0f;
|
||||
lightEnable=0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Determine whether polygon is translucent
|
||||
GLfloat translucence = (GLfloat) ((P->header[6]>>18)&0x1F) * (1.0f/31.0f);
|
||||
if ((P->header[6]&0x00800000)) // if set, polygon is opaque
|
||||
|
@ -595,6 +575,24 @@ void CLegacy3D::InsertVertex(ModelCache *Cache, const Vertex *V, const Poly *P,
|
|||
((texFormat==3) && (P->header[6]&4))) // A4L4 interleaved
|
||||
contourProcessing = 1.0f;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (g_testPolyHeaderIdx >= 0)
|
||||
{
|
||||
if ((P->header[g_testPolyHeaderIdx] & g_testPolyHeaderMask))
|
||||
{
|
||||
r = 0.;
|
||||
g = 1.;
|
||||
b = 0.;
|
||||
lightEnable = 0;
|
||||
texEnable = 0;
|
||||
contourProcessing = 0.;
|
||||
fogIntensity = 0.;
|
||||
translucence = 1.;
|
||||
shininess = -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Store to local vertex buffer
|
||||
size_t s = P->state;
|
||||
size_t baseIdx = Cache->curVertIdx[s]*VBO_VERTEX_SIZE;
|
||||
|
|
|
@ -43,6 +43,8 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include "Pkgs/glew.h"
|
||||
#ifdef SUPERMODEL_OSX
|
||||
#include <SDL/SDL.h>
|
||||
|
@ -51,16 +53,13 @@
|
|||
#endif
|
||||
|
||||
#include "Supermodel.h"
|
||||
#include "Util/Format.h"
|
||||
#include "SDLInputSystem.h"
|
||||
#ifdef SUPERMODEL_WIN32
|
||||
#include "DirectInputSystem.h"
|
||||
#include "WinOutputs.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#include "Model3/Model3GraphicsState.h"
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Error and Debug Logging
|
||||
|
@ -414,6 +413,88 @@ static void DumpPPCRegisters(IBus *bus)
|
|||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Render State Analysis
|
||||
******************************************************************************/
|
||||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include "Model3/Model3GraphicsState.h"
|
||||
#include "Util/BMPFile.h"
|
||||
#include "OSD/SDL/PolyAnalysis.h"
|
||||
|
||||
static void SaveFrameBuffer(const std::string &file)
|
||||
{
|
||||
std::shared_ptr<uint8_t> pixels(new uint8_t[totalXRes*totalYRes*4], std::default_delete<uint8_t[]>());
|
||||
glReadPixels(0, 0, totalXRes, totalYRes, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get());
|
||||
Util::WriteRGBA8SurfaceToBMP(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 GetFileBaseName(const std::string &file)
|
||||
{
|
||||
std::string base = file;
|
||||
size_t pos = file.find_last_of('/');
|
||||
if (pos != std::string::npos)
|
||||
base = file.substr(pos + 1);
|
||||
pos = file.find_last_of('\\');
|
||||
if (pos != std::string::npos)
|
||||
base = file.substr(pos + 1);
|
||||
return base;
|
||||
}
|
||||
|
||||
static void TestPolygonHeaderBits(IEmulator *Emu)
|
||||
{
|
||||
const static std::vector<uint32_t> unknownPolyBits
|
||||
{
|
||||
0x000003b0, // not sure about specular
|
||||
0x000000a9,
|
||||
0x000000fc,
|
||||
0x000000c0,
|
||||
0x000000a0,
|
||||
0xffffff60,
|
||||
0xff8200ff // not sure about contour and luminous
|
||||
};
|
||||
// Render separate image for each unknown bit
|
||||
g_forceFlushModels = true;
|
||||
for (int idx = 0; idx < 7; idx++)
|
||||
{
|
||||
for (int bit = 0; bit < 32; bit++)
|
||||
{
|
||||
uint32_t mask = 1 << bit;
|
||||
g_testPolyHeaderIdx = idx;
|
||||
g_testPolyHeaderMask = mask;
|
||||
if ((unknownPolyBits[idx] & mask))
|
||||
{
|
||||
Emu->RenderFrame();
|
||||
std::string file = Util::Format() << "Analysis/" << GetFileBaseName(s_gfxStatePath) << "." << idx << "_" << Util::Hex(mask) << ".bmp";
|
||||
SaveFrameBuffer(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Generate the HTML GUI
|
||||
std::string file = Util::Format() << "Analysis/_" << GetFileBaseName(s_gfxStatePath) << ".html";
|
||||
std::ofstream fs(file);
|
||||
if (!fs.good())
|
||||
ErrorLog("Unable to open '%s' for writing.", file.c_str());
|
||||
else
|
||||
{
|
||||
std::string contents = s_polyAnalysisHTMLPrologue;
|
||||
contents += " var g_file_base_name = '" + GetFileBaseName(s_gfxStatePath) + "';\n";
|
||||
contents += " var g_unknown_bits = [" + std::string(Util::Format(",").Join(unknownPolyBits)) + "];\n";
|
||||
contents += s_polyAnalysisHTMLEpilogue;
|
||||
fs << contents;
|
||||
printf("Produced %s\n", file.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
Configuration
|
||||
|
||||
|
@ -951,6 +1032,13 @@ int Supermodel(const char *zipFile, IEmulator *Model3, CInputs *Inputs, COutputs
|
|||
quit = false;
|
||||
paused = false;
|
||||
dumpTimings = false;
|
||||
#ifdef DEBUG
|
||||
if (dynamic_cast<CModel3GraphicsState *>(Model3))
|
||||
{
|
||||
TestPolygonHeaderBits(Model3);
|
||||
quit = true;
|
||||
}
|
||||
#endif
|
||||
while (!quit)
|
||||
{
|
||||
// Render if paused, otherwise run a frame
|
||||
|
@ -1491,7 +1579,6 @@ int main(int argc, char **argv)
|
|||
bool cmdPrintInputs = false;
|
||||
bool cmdConfigInputs = false;
|
||||
bool cmdDis = false;
|
||||
std::string gfxStatePath;
|
||||
CINIFile CmdLine; // not associated with any files, only holds command line options
|
||||
CmdLine.SetDefaultSectionName("Global"); // command line settings are global-level
|
||||
for (int i = 1; i < argc; i++)
|
||||
|
@ -1744,7 +1831,7 @@ int main(int argc, char **argv)
|
|||
else if (argv[i][10] == '\0')
|
||||
ErrorLog("'-gfx-state' requires a file path.");
|
||||
else
|
||||
gfxStatePath.assign(&argv[i][11]);
|
||||
s_gfxStatePath.assign(&argv[i][11]);
|
||||
}
|
||||
#endif
|
||||
else if (argv[i][0] == '-')
|
||||
|
@ -1767,7 +1854,7 @@ int main(int argc, char **argv)
|
|||
|
||||
// Create Model 3 emulator
|
||||
#ifdef DEBUG
|
||||
IEmulator *Model3 = gfxStatePath.empty() ? static_cast<IEmulator *>(new CModel3()) : static_cast<IEmulator *>(new CModel3GraphicsState(gfxStatePath));
|
||||
IEmulator *Model3 = s_gfxStatePath.empty() ? static_cast<IEmulator *>(new CModel3()) : static_cast<IEmulator *>(new CModel3GraphicsState(s_gfxStatePath));
|
||||
#else
|
||||
IEmulator *Model3 = new CModel3();
|
||||
#endif
|
||||
|
|
99
Src/OSD/SDL/PolyAnalysis.h
Normal file
99
Src/OSD/SDL/PolyAnalysis.h
Normal file
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
** Supermodel
|
||||
** A Sega Model 3 Arcade Emulator.
|
||||
** Copyright 2011-2016 Bart Trzynadlowski, Nik Henson
|
||||
**
|
||||
** This file is part of Supermodel.
|
||||
**
|
||||
** Supermodel 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, either version 3 of the License, or (at your option)
|
||||
** any later version.
|
||||
**
|
||||
** Supermodel 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 for
|
||||
** more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License along
|
||||
** with Supermodel. If not, see <http://www.gnu.org/licenses/>.
|
||||
**/
|
||||
|
||||
/*
|
||||
* PolyAnalysis.h
|
||||
*
|
||||
* HTML GUI used to analyze polygon header bits.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_POLYANALYSIS_H
|
||||
#define INCLUDED_POLYANALYSIS_H
|
||||
|
||||
static const char s_polyAnalysisHTMLPrologue[] =
|
||||
{
|
||||
"<html>\n"
|
||||
"<head>\n"
|
||||
" <style>\n"
|
||||
" table { table-layout: fixed; }\n"
|
||||
" td { border: 1px solid black; width: 1em; }\n"
|
||||
" td.nonselectable { background-color: gray; }\n"
|
||||
" td.selectable { background-color: #5555ee; }\n"
|
||||
" td.selected { background-color: #22ff22; }\n"
|
||||
" </style>\n"
|
||||
" <script src='https://ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js'></script>\n"
|
||||
"</head>\n"
|
||||
"<body>\n"
|
||||
" <div id='Header'></div>\n"
|
||||
" <div><img id='Image' /></div>\n"
|
||||
" <script>\n"
|
||||
// Insert g_file_base_name and g_unknown bits here, then append epilogue
|
||||
};
|
||||
|
||||
static const char s_polyAnalysisHTMLEpilogue[] =
|
||||
{
|
||||
" function hex32(val)\n"
|
||||
" {\n"
|
||||
" return '0x' + ('0000000'+Number(val).toString(16)).slice(-8);\n"
|
||||
" }\n"
|
||||
" function getOnClickHandler(table, td, word, mask)\n"
|
||||
" {\n"
|
||||
" return function()\n"
|
||||
" {\n"
|
||||
" var file = g_file_base_name + '.' + word + '_' + hex32(mask) + '.bmp';\n"
|
||||
" table.find('td').removeClass('selected'); // remove from all cells\n"
|
||||
" td.addClass('selected');\n"
|
||||
" $('#Image').empty();\n"
|
||||
" $('#Image').attr('src', file);\n"
|
||||
" };\n"
|
||||
" }\n"
|
||||
" $(document).ready(function()\n"
|
||||
" {\n"
|
||||
" // Construct table\n"
|
||||
" var table = $('<table></table>');\n"
|
||||
" var bits_tr = $('<tr></tr>'); // first row will be bit legend\n"
|
||||
" bits_tr.append($('<td></td>')); // column for word numbers\n"
|
||||
" for (var bit = 31; bit >= 0; bit--)\n"
|
||||
" bits_tr.append($('<td>'+bit+'</td>'));\n"
|
||||
" table.append(bits_tr);\n"
|
||||
" for (var word = 0; word < 7; word++)\n"
|
||||
" {\n"
|
||||
" var tr = $('<tr></tr>');\n"
|
||||
" tr.append($('<td>'+word+'</td>'));\n"
|
||||
" for (var bit = 31; bit >= 0; bit--)\n"
|
||||
" {\n"
|
||||
" var mask = 1 << bit;\n"
|
||||
" var td = $('<td></td>');\n"
|
||||
" if (g_unknown_bits[word] & mask)\n"
|
||||
" td.addClass('selectable').click(getOnClickHandler(table, td, word, mask));\n"
|
||||
" else"
|
||||
" td.addClass('nonselectable');\n"
|
||||
" tr.append(td);\n"
|
||||
" }\n"
|
||||
" table.append(tr);\n"
|
||||
" }\n"
|
||||
" $('#Header').append(table);\n"
|
||||
" });\n"
|
||||
" </script>\n"
|
||||
"</body>\n"
|
||||
};
|
||||
|
||||
#endif // INCLUDED_POLYANALYSIS_H
|
Loading…
Reference in a new issue