Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/Companion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,8 @@ void Companion::ParseCurrentFileConfig(YAML::Node node, std::atomic<size_t>& ass
}
}

this->gCurrentFileConfig.reset(node);

if (node["directory"]) {
this->gCurrentDirectory = node["directory"].as<std::string>();
}
Expand Down Expand Up @@ -1295,6 +1297,7 @@ void Companion::ProcessFile(YAML::Node root, std::atomic<size_t>& assetCount) {
this->gCurrentExternalFiles.clear();
this->gSubFileList.clear();
this->gManualSegments.clear();
this->gCurrentFileConfig.reset(YAML::Node());
GFXDOverride::ClearVtx();

if (root[":config"]) {
Expand Down Expand Up @@ -1447,7 +1450,11 @@ void Companion::Process(std::atomic<size_t>& assetCount) {
}
}
this->gAssetPath = (this->gSourceDirectory / rom["path"].as<std::string>()).string();
this->gCommonAssetPath = (this->gSourceDirectory / rom["common_path"].as<std::string>()).string();
// Optional: a rom that keeps all its ymls under one tree has no common dir, and
// getRecursiveEntries already treats an empty path as "nothing to add".
if (rom["common_path"]) {
this->gCommonAssetPath = (this->gSourceDirectory / rom["common_path"].as<std::string>()).string();
}

if (rom["filelist"]) {
const std::string filelistPath = (this->gSourceDirectory / rom["filelist"].as<std::string>()).string();
Expand Down
48 changes: 5 additions & 43 deletions src/factories/bk64/ModelFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,9 +483,10 @@ std::optional<std::shared_ptr<IParsedData>> ModelFactory::parse(std::vector<uint
uint32_t tlutSize = 0;
uint16_t tlutColors = 0;

// Stash texture metadata for the binary exporter. Type 0x1 just means "has a TLUT" —
// it's both CI4 and CI8. We can't tell which until all the headers are in, so the real
// bit depth gets resolved further down.
// Stash texture metadata for the binary exporter. Type 0x1 is CI4
// and 0x2 is CI8: every type 0x2 region in the ROM holds a 256
// entry TLUT and 8-bit pixels, and no type 0x1 region has room for
// one.
TexInfo texInfo;
texInfo.type = textureType;
texInfo.width = static_cast<uint8_t>(width);
Expand All @@ -495,7 +496,7 @@ std::optional<std::shared_ptr<IParsedData>> ModelFactory::parse(std::vector<uint

switch (textureType) {
case 0x1:
// Sorted out later, once every header is read
texInfo.tlutColors = 0x10;
break;
case 0x2:
texInfo.tlutColors = 0x100;
Expand All @@ -516,45 +517,6 @@ std::optional<std::shared_ptr<IParsedData>> ModelFactory::parse(std::vector<uint
modelOffset + textureSetupOffset + TEXTURE_HEADER_SIZE + textureCount * TEXTURE_METADATA_SIZE;
modelData->mTexDataSize = textureDataSize;

// Now disambiguate the type 0x1 textures. 0x1 means "has TLUT", which is either CI4
// (16-entry palette) or CI8 (256-entry palette) — the header doesn't say which. Trick is
// to measure the gap to the next texture: if it's big enough for a full CI8 payload
// (0x200 TLUT + W*H pixels), call it CI8, otherwise CI4. The last texture in a list can be
// padded, hence >= instead of ==. CI8 always needs more room than CI4 at the same W*H
// (delta = 0x1E0 - W*H/2 > 0 for any BK texture up to 64x64), so there's no overlap to
// worry about.
for (uint16_t i = 0; i < textureCount; i++) {
auto& tex = modelData->mTexInfos[i];
if (tex.type != 0x1) {
continue;
}

uint32_t nextOffset =
(i + 1 < textureCount) ? modelData->mTexInfos[i + 1].textureDataOffset : textureDataSize;
uint32_t gap = nextOffset - tex.textureDataOffset;
uint32_t ci4Size = 0x20 + ((uint32_t)tex.width * tex.height) / 2; // 16-entry TLUT + CI4 pixels
uint32_t ci8Size = 0x200 + (uint32_t)tex.width * tex.height; // 256-entry TLUT + CI8 pixels

if (gap >= ci8Size) {
tex.type = 0x2; // CI8
tex.tlutColors = 0x100;
if (gap != ci8Size) {
SPDLOG_INFO("[BK64::Model] tex[{}] {}x{}: gap=0x{:X} >= CI8 (0x{:X}), classified CI8 (pad=0x{:X})",
i, tex.width, tex.height, gap, ci8Size, gap - ci8Size);
}
} else {
tex.tlutColors = 0x10; // CI4
if (gap < ci4Size) {
SPDLOG_WARN("[BK64::Model] tex[{}] {}x{}: gap=0x{:X} smaller than CI4 (0x{:X}), data may be "
"truncated",
i, tex.width, tex.height, gap, ci4Size);
} else if (gap != ci4Size) {
SPDLOG_INFO("[BK64::Model] tex[{}] {}x{}: gap=0x{:X} (CI4 0x{:X}, pad=0x{:X})", i, tex.width,
tex.height, gap, ci4Size, gap - ci4Size);
}
}
}

// [port] Grab the entire raw texture area so animated frames and any unlisted bytes
// between textures survive into the binary.
if (textureDataSize > 0 && texDataStart + textureDataSize <= segment.size) {
Expand Down
Loading