summaryrefslogtreecommitdiff
path: root/ZAPD/ZDisplayList.cpp
diff options
context:
space:
mode:
authorfig02 <fig02srl@gmail.com>2021-03-12 15:51:39 -0500
committerGitHub <noreply@github.com>2021-03-12 15:51:39 -0500
commit55718b1090083e1f5e9b1b1cc09ebcb329baa74f (patch)
treeae890ccd6bfeded507518d227a0002f8fc136bcf /ZAPD/ZDisplayList.cpp
parent1e67767cf988af08e79d8cea4ee1e4d47658fe29 (diff)
Use libgfxd (gfxdis) for display lists (#84)
* start * dlists work * progress * vtx works * texture wip * debugging * palletes sorta working * pal issue sort of fixed * progress * fiix * switching to master * progress * OK * fixes * whitespace * libgfxd update * prep for merge * use new seg2filespace function * vtx
Diffstat (limited to 'ZAPD/ZDisplayList.cpp')
-rw-r--r--ZAPD/ZDisplayList.cpp267
1 files changed, 233 insertions, 34 deletions
diff --git a/ZAPD/ZDisplayList.cpp b/ZAPD/ZDisplayList.cpp
index c69e1a8..4754c03 100644
--- a/ZAPD/ZDisplayList.cpp
+++ b/ZAPD/ZDisplayList.cpp
@@ -1,8 +1,10 @@
#include "ZDisplayList.h"
#include "BitConverter.h"
#include "StringHelper.h"
+#include "OutputFormatter.h"
#include "HighLevel/HLModelIntermediette.h"
#include "Globals.h"
+#include "gfxd.h"
#include <chrono>
#include <algorithm>
#include <File.h>
@@ -68,7 +70,7 @@ ZDisplayList::ZDisplayList(vector<uint8_t> nRawData, int nRawDataIndex, int rawD
{
fileData = nRawData;
rawDataIndex = nRawDataIndex;
- name = StringHelper::Sprintf("Dlist0x%06X", rawDataIndex);
+ name = StringHelper::Sprintf("DL_%06X", rawDataIndex);
rawData = vector<uint8_t>(nRawData.data() + rawDataIndex, nRawData.data() + rawDataIndex + rawDataSize);
ParseRawData();
}
@@ -1428,48 +1430,241 @@ string ZDisplayList::GetSourceOutputHeader(const std::string& prefix)
return "";
}
-string ZDisplayList::GetSourceOutputCode(const std::string& prefix)
+static int GfxdCallback_FormatSingleEntry(void)
{
- char line[4096];
- string sourceOutput = "";
+ gfxd_puts("\t");
+ gfxd_macro_dflt();
+ gfxd_puts(",");
- for (int i = 0; i < instructions.size(); i++)
- {
- uint8_t opcode = (uint8_t)(instructions[i] >> 56);
- uint64_t data = instructions[i];
- sourceOutput += " ";
+ // dont print a new line after the last command
+ if (gfxd_macro_id() != gfxd_SPEndDisplayList) {
+ gfxd_puts("\n");
+ }
- auto start = chrono::steady_clock::now();
+ return 0;
+}
- int optimizationResult = OptimizationChecks(i, sourceOutput, prefix);
+static int GfxdCallback_Vtx(uint32_t seg, int32_t count)
+{
+ ZDisplayList* instance = ZDisplayList::static_instance;
+ uint32_t vtxOffset = Seg2Filespace(seg, instance->parent->baseAddress);
+ string vtxName = "";
- if (optimizationResult != -1)
+ if (!Globals::Instance->HasSegment(GETSEGNUM(seg))) // Probably an external asset we are unable to track
+ {
+ vtxName = StringHelper::Sprintf("0x%08X", seg);
+ }
+ else
+ {
+ instance->references.push_back(vtxOffset);
+
+ // Check for vertex intersections from other display lists
+ // TODO: These two could probably be condenced to one...
+ if (instance->parent->GetDeclarationRanged(vtxOffset + (count * 16)) != nullptr)
{
- i += optimizationResult - 1;
- line[0] = '\0';
+ Declaration* decl = instance->parent->GetDeclarationRanged(vtxOffset + (count * 16));
+ uint32_t addr = instance->parent->GetDeclarationRangedAddress(vtxOffset + (count * 16));
+ int diff = addr - vtxOffset;
+
+ if (diff > 0)
+ count = diff / 16;
+ else
+ count = 0;
}
- else
+
+ if (instance->parent->GetDeclarationRanged(vtxOffset) != nullptr)
{
- if (dListType == DListType::F3DZEX)
- ParseF3DZEX((F3DZEXOpcode)opcode, data, i, prefix, line);
+ Declaration* decl = instance->parent->GetDeclarationRanged(vtxOffset);
+ uint32_t addr = instance->parent->GetDeclarationRangedAddress(vtxOffset);
+ int diff = addr - vtxOffset;
+
+ if (diff > 0)
+ count = diff / 16;
else
- ParseF3DEX((F3DEXOpcode)opcode, data, i, prefix, line);
+ count = 0;
}
- auto end = chrono::steady_clock::now();
- auto diff = chrono::duration_cast<chrono::milliseconds>(end - start).count();
+ if (count > 0)
+ {
+ vector<Vertex> vtxList = vector<Vertex>();
+ vtxList.reserve(count);
+
+ uint32_t currentPtr = vtxOffset;
+ for (int i = 0; i < count; i++)
+ {
+ Vertex vtx = Vertex(instance->fileData, currentPtr);
+ vtxList.push_back(vtx);
+ currentPtr += 16;
+ }
+ instance->vertices[vtxOffset] = vtxList;
+ }
+
+ vtxName = "@r";
+ }
+
+ gfxd_puts(vtxName.c_str());
+
+ return 1;
+}
+
+static int GfxdCallback_Texture(uint32_t seg, int32_t fmt, int32_t siz, int32_t width, int32_t height, int32_t pal)
+{
+ ZDisplayList* instance = ZDisplayList::static_instance;
+ uint32_t texOffset = Seg2Filespace(seg, instance->parent->baseAddress);
+ uint32_t texSegNum = GETSEGNUM(seg);
+ Declaration* texDecl = nullptr;
+ string texName = "";
+
+ if (instance->parent != nullptr && texSegNum != 2) // HACK: Until we have declarations use segment addresses, we'll exclude scene references...
+ {
+ texDecl = instance->parent->GetDeclaration(texOffset);
+
+ if (texDecl == nullptr)
+ texDecl = instance->parent->GetDeclaration(seg);
+ }
+
+ if (!Globals::Instance->HasSegment(texSegNum)) // Probably an external asset we are unable to track
+ texName = StringHelper::Sprintf("0x%08X", seg);
+ else if (texDecl != nullptr)
+ texName = StringHelper::Sprintf("%s", texDecl->varName.c_str());
+ else if (texSegNum == 2)
+ texName = StringHelper::Sprintf("%sTex_%06X", instance->scene->GetName().c_str(), texOffset);
+ else
+ texName = StringHelper::Sprintf("%sTex_%06X", instance->curPrefix.c_str(), texOffset);
+
+ instance->lastTexWidth = width;
+ instance->lastTexHeight = height;
+ instance->lastTexAddr = texOffset;
+ instance->lastTexSeg = seg;
+ instance->lastTexFmt = (F3DZEXTexFormats)fmt;
+ instance->lastTexSiz = (F3DZEXTexSizes)siz;
+ instance->lastTexLoaded = true;
+ instance->lastTexIsPalette = false;
+
+ instance->TextureGenCheck(instance->curPrefix);
+ gfxd_puts(texName.c_str());
+
+ return 1;
+}
+
+static int GfxdCallback_Palette(uint32_t seg, int32_t idx, int32_t count)
+{
+ ZDisplayList* instance = ZDisplayList::static_instance;
+ uint32_t palOffset = Seg2Filespace(seg, instance->parent->baseAddress);
+ uint32_t palSegNum = GETSEGNUM(seg);
+ Declaration* palDecl = nullptr;
+ string palName = "";
+
+ if (instance->parent != nullptr && palSegNum != 2) // HACK: Until we have declarations use segment addresses, we'll exclude scene references...
+ {
+ palDecl = instance->parent->GetDeclaration(palOffset);
+
+ if (palDecl == nullptr)
+ palDecl = instance->parent->GetDeclaration(seg);
+ }
+
+ if (!Globals::Instance->HasSegment(palSegNum)) // Probably an external asset we are unable to track
+ palName = StringHelper::Sprintf("0x%08X", seg);
+ else if (palDecl != nullptr)
+ palName = StringHelper::Sprintf("%s", palDecl->varName.c_str());
+ else if (palSegNum == 2)
+ palName = StringHelper::Sprintf("%sTex_%06X", instance->scene->GetName().c_str(), palOffset);
+ else
+ palName = StringHelper::Sprintf("%sTex_%06X", instance->curPrefix.c_str(), palOffset);
+
+ instance->lastTexWidth = sqrt(count);
+ instance->lastTexHeight = sqrt(count);
+ instance->lastTexAddr = palOffset;
+ instance->lastTexSeg = seg;
+ instance->lastTexSiz = F3DZEXTexSizes::G_IM_SIZ_16b;
+ instance->lastTexFmt = F3DZEXTexFormats::G_IM_FMT_RGBA;
+ instance->lastTexLoaded = true;
+ instance->lastTexIsPalette = true;
+
+ instance->TextureGenCheck(instance->curPrefix);
+ gfxd_puts(palName.c_str());
+
+ return 1;
+}
+
+static int GfxdCallback_DisplayList(uint32_t seg)
+{
+ ZDisplayList* instance = ZDisplayList::static_instance;
+ uint32_t dListOffset = GETSEGOFFSET(seg);
+ uint32_t dListSegNum = GETSEGNUM(seg);
+ Declaration* dListDecl = nullptr;
+ string dListName = "";
-#if _MSC_VER
- //if (diff > 5)
- //printf("F3DOP: 0x%02X, TIME: %ims\n", opcode, diff);
-#endif
+ if (instance->parent != nullptr)
+ dListDecl = instance->parent->GetDeclaration(dListOffset);
- sourceOutput += line;
+ if (!Globals::Instance->HasSegment(dListSegNum)) // Probably an external asset we are unable to track
+ dListName = StringHelper::Sprintf("0x%08X", seg);
+ else if (dListDecl != nullptr)
+ dListName = StringHelper::Sprintf("%s", dListDecl->varName.c_str());
+ else
+ dListName = StringHelper::Sprintf("%sDL_%06X", instance->curPrefix.c_str(), dListOffset);
- if (i < instructions.size() - 1)
- sourceOutput += "\n";
+ if (dListSegNum <= 6)
+ {
+ ZDisplayList* newDList = new ZDisplayList(instance->fileData, dListOffset, instance->GetDListLength(instance->fileData, dListOffset, instance->dListType));
+ newDList->scene = instance->scene;
+ newDList->parent = instance->parent;
+ instance->otherDLists.push_back(newDList);
}
+ gfxd_puts(dListName.c_str());
+
+ return 1;
+}
+
+static int GfxdCallback_Matrix(uint32_t seg)
+{
+ string mtxName = "";
+
+ if (Globals::Instance->symbolMap.find(seg) != Globals::Instance->symbolMap.end())
+ mtxName = StringHelper::Sprintf("&%s", Globals::Instance->symbolMap[seg].c_str());
+ else
+ mtxName = StringHelper::Sprintf("0x%08X", seg);
+
+ gfxd_puts(mtxName.c_str());
+
+ return 1;
+}
+
+ZDisplayList* ZDisplayList::static_instance;
+
+string ZDisplayList::GetSourceOutputCode(const std::string& prefix)
+{
+ OutputFormatter outputformatter;
+ string sourceOutput = "";
+ int dListSize = instructions.size() * sizeof(instructions[0]);
+
+ gfxd_input_buffer(instructions.data(), dListSize);
+ gfxd_endian(gfxd_endian_little, sizeof(uint64_t)); // tell gfxdis what format the data is
+
+ gfxd_macro_fn(GfxdCallback_FormatSingleEntry); // format for each command entry
+ gfxd_vtx_callback(GfxdCallback_Vtx); // handle vertices
+ gfxd_timg_callback(GfxdCallback_Texture); // handle textures
+ gfxd_tlut_callback(GfxdCallback_Palette); // handle palettes
+ gfxd_dl_callback(GfxdCallback_DisplayList); // handle child display lists
+ gfxd_mtx_callback(GfxdCallback_Matrix); // handle matrices
+ gfxd_output_callback(outputformatter.static_writer()); // convert tabs to 4 spaces and enforce 120 line limit
+
+ gfxd_enable(gfxd_emit_dec_color); // use decimal for colors
+
+ // set microcode. see gfxd.h for more options.
+ if (dListType == DListType::F3DZEX) {
+ gfxd_target(gfxd_f3dex2);
+ } else {
+ gfxd_target(gfxd_f3dex);
+ }
+
+ this->curPrefix = prefix;
+ static_instance = this;
+ gfxd_execute(); // generate display list
+ sourceOutput += outputformatter.get_output(); // write formatted display list
+
// Iterate through our vertex lists, connect intersecting lists.
if (vertices.size() > 0)
{
@@ -1704,17 +1899,21 @@ TextureType ZDisplayList::TexFormatToTexType(F3DZEXTexFormats fmt, F3DZEXTexSize
else if (siz == F3DZEXTexSizes::G_IM_SIZ_32b)
return TextureType::RGBA32bpp;
}
- else if (fmt == F3DZEXTexFormats::G_IM_FMT_CI)
- {
- //if (siz == F3DZEXTexSizes::G_IM_SIZ_8b)
- return TextureType::Palette8bpp;
- }
+ else if (fmt == F3DZEXTexFormats::G_IM_FMT_CI)
+ {
+ if (siz == F3DZEXTexSizes::G_IM_SIZ_4b)
+ return TextureType::Palette4bpp;
+ else if (siz == F3DZEXTexSizes::G_IM_SIZ_8b)
+ return TextureType::Palette8bpp;
+ }
else if (fmt == F3DZEXTexFormats::G_IM_FMT_IA)
{
- if (siz == F3DZEXTexSizes::G_IM_SIZ_16b)
- return TextureType::GrayscaleAlpha16bpp;
+ if (siz == F3DZEXTexSizes::G_IM_SIZ_4b)
+ return TextureType::Grayscale4bpp;
else if (siz == F3DZEXTexSizes::G_IM_SIZ_8b)
return TextureType::GrayscaleAlpha8bpp;
+ else if (siz == F3DZEXTexSizes::G_IM_SIZ_16b)
+ return TextureType::GrayscaleAlpha16bpp;
}
else if (fmt == F3DZEXTexFormats::G_IM_FMT_I)
{