Extend GC stage and TUMO parsing

This commit is contained in:
2026-08-15 13:01:11 +02:00
parent 8c4e1bcacb
commit c9575e1a9b
7 changed files with 406 additions and 150 deletions
+47
View File
@@ -0,0 +1,47 @@
#include "gc/StagePattern.hpp"
#include <fstream>
#include <iostream>
#include <iterator>
#include <map>
#include <string>
#include <vector>
int main(int argc, char** argv) {
if (argc < 2) {
std::cerr << "Usage: " << argv[0] << " <stage_ext.dat> [...]\n";
return 2;
}
bool okay = true;
for (int i = 1; i < argc; ++i) {
std::ifstream file(argv[i], std::ios::binary);
if (!file) {
std::cerr << argv[i] << ": could not open file\n";
okay = false;
continue;
}
std::vector<uint8_t> bytes((std::istreambuf_iterator<char>(file)), {});
gc::StageExtension extension;
std::string error;
if (!gc::ParseStageExtension(bytes, &extension, &error)) {
std::cerr << argv[i] << ": " << error << '\n';
okay = false;
continue;
}
std::map<uint8_t, size_t> types;
for (const gc::StageNote& note : extension.notes) {
++types[static_cast<uint8_t>(note.type)];
}
std::cout << argv[i] << ": notes=" << extension.notes.size()
<< " trailing=" << extension.trailingBytes << " timing=";
for (const auto& list : extension.noteSettings) std::cout << list.size() << ',';
std::cout << " types=";
for (const auto& [type, count] : types) {
std::cout << static_cast<unsigned>(type) << ':' << count << ',';
}
std::cout << '\n';
}
return okay ? 0 : 1;
}
+50 -1
View File
@@ -39,12 +39,29 @@ bool probe(const std::string& path) {
size_t flashingObjects = 0;
size_t noGlobalFadeObjects = 0;
size_t translucentObjects = 0;
size_t objectAnimationKeys = 0;
size_t objectRepeatKeys = 0;
size_t objectInterpolateKeys = 0;
size_t objectDifferingFlagKeys = 0;
const auto countAnimationKeys = [&](const auto& keys) {
objectAnimationKeys += keys.size();
for (const auto& key : keys) {
objectRepeatKeys += key.repeat ? 1 : 0;
objectInterpolateKeys += key.interpolate ? 1 : 0;
objectDifferingFlagKeys += key.repeat != key.interpolate ? 1 : 0;
}
};
for (const gc::StageObject& object : stage.objects) {
if (object.parentIndex >= 0) ++parentedObjects;
if (object.wireframe) ++wireframeObjects;
if (object.flashing) ++flashingObjects;
if (object.unknownFlag) ++noGlobalFadeObjects;
if (object.color[3] < 0.999f) ++translucentObjects;
countAnimationKeys(object.visibility);
countAnimationKeys(object.movement);
countAnimationKeys(object.scaling);
countAnimationKeys(object.rotations);
countAnimationKeys(object.colorChanges);
}
std::cout << path
@@ -67,6 +84,8 @@ bool probe(const std::string& path) {
<< " noteNames=" << stage.noteNames.size()
<< "\n background: particles=" << stage.particles.size()
<< " visualizerKeys=" << stage.visualizer.size()
<< " imageTextures=" << stage.backgroundTextureNames.size()
<< " imageKeys=" << stage.backgroundImages.size()
<< " colorKeys=" << stage.backgroundColors.size()
<< " models=" << stage.modelNames.size()
<< " objects=" << stage.objects.size()
@@ -74,7 +93,11 @@ bool probe(const std::string& path) {
<< " wire=" << wireframeObjects
<< " flashing=" << flashingObjects
<< " noGlobalFade=" << noGlobalFadeObjects
<< " translucent=" << translucentObjects;
<< " translucent=" << translucentObjects
<< " objectKeys=" << objectAnimationKeys
<< " repeat=" << objectRepeatKeys
<< " interpolate=" << objectInterpolateKeys
<< " differingFlags=" << objectDifferingFlagKeys;
if (!stage.notes.empty()) {
const auto [lo, hi] = std::minmax_element(
stage.notes.begin(), stage.notes.end(),
@@ -96,6 +119,32 @@ bool probe(const std::string& path) {
for (const auto& key : stage.visualizer) ++visualizerTypes[key.type];
std::cout << "\n visualizerTypes:";
for (const auto& [type, count] : visualizerTypes) std::cout << ' ' << type << '=' << count;
std::cout << "\n visualizerKeys:";
for (const auto& key : stage.visualizer) {
std::cout << ' ' << key.timeMs << ":type=" << key.type
<< ",rgba=" << static_cast<unsigned>(key.color.r) << ','
<< static_cast<unsigned>(key.color.g) << ','
<< static_cast<unsigned>(key.color.b) << ','
<< static_cast<unsigned>(key.color.a);
}
}
if (!stage.backgroundTextureNames.empty()) {
std::cout << "\n backgroundTextures:";
for (size_t i = 0; i < stage.backgroundTextureNames.size(); ++i) {
std::cout << ' ' << i << '=' << stage.backgroundTextureNames[i];
}
}
if (!stage.backgroundImages.empty()) {
std::cout << "\n backgroundImageKeys:";
for (const auto& image : stage.backgroundImages) {
std::cout << ' ' << image.timeMs << ":mode=" << image.mode
<< ",atlas=" << image.atlasIndex
<< ",texture=" << image.textureIndex
<< ",rgba=" << static_cast<unsigned>(image.color.r) << ','
<< static_cast<unsigned>(image.color.g) << ','
<< static_cast<unsigned>(image.color.b) << ','
<< static_cast<unsigned>(image.color.a);
}
}
if (!stage.drawDistances.empty()) {
std::cout << "\n drawDistance=" << stage.drawDistances.front().timeMs << ':'