diff --git a/Src/Graphics/Legacy3D/Legacy3D.cpp b/Src/Graphics/Legacy3D/Legacy3D.cpp index f01b82e..3f869c5 100644 --- a/Src/Graphics/Legacy3D/Legacy3D.cpp +++ b/Src/Graphics/Legacy3D/Legacy3D.cpp @@ -162,6 +162,11 @@ #include #include +#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++) { diff --git a/Src/Graphics/Legacy3D/Models.cpp b/Src/Graphics/Legacy3D/Models.cpp index 9141f83..6a2d590 100644 --- a/Src/Graphics/Legacy3D/Models.cpp +++ b/Src/Graphics/Legacy3D/Models.cpp @@ -83,6 +83,12 @@ #include #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<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; diff --git a/Src/OSD/SDL/Main.cpp b/Src/OSD/SDL/Main.cpp index 678b7a2..45b4869 100644 --- a/Src/OSD/SDL/Main.cpp +++ b/Src/OSD/SDL/Main.cpp @@ -43,6 +43,8 @@ #include #include #include +#include +#include #include "Pkgs/glew.h" #ifdef SUPERMODEL_OSX #include @@ -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 pixels(new uint8_t[totalXRes*totalYRes*4], std::default_delete()); + 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 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(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(new CModel3()) : static_cast(new CModel3GraphicsState(gfxStatePath)); + IEmulator *Model3 = s_gfxStatePath.empty() ? static_cast(new CModel3()) : static_cast(new CModel3GraphicsState(s_gfxStatePath)); #else IEmulator *Model3 = new CModel3(); #endif diff --git a/Src/OSD/SDL/PolyAnalysis.h b/Src/OSD/SDL/PolyAnalysis.h new file mode 100644 index 0000000..43a7be4 --- /dev/null +++ b/Src/OSD/SDL/PolyAnalysis.h @@ -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 . + **/ + +/* + * PolyAnalysis.h + * + * HTML GUI used to analyze polygon header bits. + */ + +#ifndef INCLUDED_POLYANALYSIS_H +#define INCLUDED_POLYANALYSIS_H + +static const char s_polyAnalysisHTMLPrologue[] = +{ + "\n" + "\n" + " \n" + " \n" + "\n" + "\n" + " \n" + "
\n" + " \n" + "\n" +}; + +#endif // INCLUDED_POLYANALYSIS_H