mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-29 23:27:25 -04:00
73 lines
2.6 KiB
C++
73 lines
2.6 KiB
C++
#include "dusk/batch.hpp"
|
|
#include "dusk/logging.h"
|
|
|
|
#include <aurora/dl.hpp>
|
|
#include <dolphin/gx/GXEnum.h>
|
|
|
|
namespace dusk::batch {
|
|
|
|
void decode_leaf_template(const u8* dl, u32 size, LeafTemplate& out) {
|
|
out.vtxCount = 0;
|
|
out.posRefCount = 0;
|
|
bool posSeen[256] = {};
|
|
|
|
static constexpr GXVtxDescList kLeafDesc[] = {
|
|
{GX_VA_POS, GX_INDEX8},
|
|
{GX_VA_NRM, GX_INDEX8},
|
|
{GX_VA_CLR0, GX_INDEX8},
|
|
{GX_VA_TEX0, GX_INDEX8},
|
|
{GX_VA_NULL, GX_NONE},
|
|
};
|
|
|
|
aurora::gx::dl::Reader reader{dl, size, kLeafDesc};
|
|
while (const auto cmd = reader.next()) {
|
|
if (cmd->kind == aurora::gx::dl::Command::Kind::Passthrough) {
|
|
if (cmd->data[0] != GX_NOP) {
|
|
DuskLog.fatal("decode_leaf_template: unexpected opcode {:#x}", cmd->data[0]);
|
|
}
|
|
continue;
|
|
}
|
|
if (cmd->kind != aurora::gx::dl::Command::Kind::Draw) {
|
|
DuskLog.fatal("decode_leaf_template: unexpected pre-optimized draw");
|
|
}
|
|
|
|
const auto& draw = cmd->draw;
|
|
bool overflow = false;
|
|
const bool expanded =
|
|
aurora::gx::dl::expand_triangles(draw.prim, draw.vtxCount, [&](u16 i0, u16 i1, u16 i2) {
|
|
if (overflow || out.vtxCount + 3 > LeafTemplate::kMaxVtx) {
|
|
overflow = true;
|
|
return;
|
|
}
|
|
for (const u16 elem : {i0, i1, i2}) {
|
|
LeafTemplate::Vtx& v = out.vtx[out.vtxCount++];
|
|
v.pos = draw.attr_idx(elem, GX_VA_POS);
|
|
v.nrm = draw.attr_idx(elem, GX_VA_NRM);
|
|
v.clr = draw.attr_idx(elem, GX_VA_CLR0);
|
|
v.tex = draw.attr_idx(elem, GX_VA_TEX0);
|
|
if (!posSeen[v.pos]) {
|
|
posSeen[v.pos] = true;
|
|
if (out.posRefCount >= LeafTemplate::kMaxPosRefs) {
|
|
overflow = true;
|
|
return;
|
|
}
|
|
out.posRefs[out.posRefCount++] = v.pos;
|
|
}
|
|
}
|
|
});
|
|
if (!expanded) {
|
|
DuskLog.fatal("decode_leaf_template: untriangulable draw (prim {:#x}, {} verts)",
|
|
static_cast<u32>(draw.prim), draw.vtxCount);
|
|
}
|
|
if (overflow) {
|
|
DuskLog.fatal("decode_leaf_template: template overflow ({} verts, {} positions)",
|
|
out.vtxCount, out.posRefCount);
|
|
}
|
|
}
|
|
if (reader.failed()) {
|
|
DuskLog.fatal("decode_leaf_template: failed to walk display list");
|
|
}
|
|
}
|
|
|
|
} // namespace dusk::batch
|