Initial Vectorail GC format library
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
#ifndef OPENROLLER_GC_EVENTSTREAM_HPP
|
||||
#define OPENROLLER_GC_EVENTSTREAM_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace gc {
|
||||
|
||||
struct GameEvent {
|
||||
uint16_t id = 0;
|
||||
float timestamp = 0.0f;
|
||||
uint16_t a = 0; // unknown (often 0)
|
||||
uint32_t type = 0;
|
||||
float value = 0.0f;
|
||||
uint16_t b = 0; // unknown (often 0)
|
||||
};
|
||||
|
||||
struct EventStreamDecodeResult {
|
||||
size_t recordSize = 16; // 16 or 12 (for now)
|
||||
int alignment = 0; // best alignment within [0,recordSize-1]
|
||||
size_t eventCount = 0; // decoded event count at best alignment (bounded)
|
||||
double padZeroRatio = 0.0; // fraction of padding fields that are zero (0..1)
|
||||
int score = 0; // heuristic score for ranking
|
||||
};
|
||||
|
||||
EventStreamDecodeResult TryDecodeEventStream(const std::vector<uint8_t>& bytes, size_t start, size_t end);
|
||||
|
||||
// Like TryDecodeEventStream, but forces recordSize=12 or 16.
|
||||
EventStreamDecodeResult TryDecodeEventStreamFixed(const std::vector<uint8_t>& bytes, size_t start, size_t end, size_t recordSize);
|
||||
|
||||
// Decodes using a fixed record size (big endian).
|
||||
// recordSize=16: u16 id, f32 timestamp, u16 a, u16 type, f32 value, u16 b
|
||||
// recordSize=12: f32 timestamp, u32 type, f32 value
|
||||
bool DecodeEventStream(
|
||||
const std::vector<uint8_t>& bytes,
|
||||
size_t start,
|
||||
size_t end,
|
||||
size_t recordSize,
|
||||
std::vector<GameEvent>* out,
|
||||
std::string* err);
|
||||
|
||||
} // namespace gc
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,67 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
struct GcUvCell {
|
||||
uint16_t x = 0;
|
||||
uint16_t y = 0;
|
||||
uint16_t width = 0;
|
||||
uint16_t height = 0;
|
||||
};
|
||||
|
||||
struct GcEffectSprite {
|
||||
uint16_t uvRecord = 0;
|
||||
int frame = 0;
|
||||
glm::vec3 offsetPixels{0.0f};
|
||||
glm::vec4 color{1.0f};
|
||||
glm::vec2 scale{1.0f};
|
||||
float rotationDegrees = 0.0f;
|
||||
};
|
||||
|
||||
// Interpreter for the sprite subset of the original common effect format.
|
||||
// It follows game471 FUN_005f2030/FUN_005f2250/FUN_005f23f0 and is enough to
|
||||
// reproduce control-helper effects 61..69, including parent rotation nodes.
|
||||
class GcTargetEffectBank {
|
||||
public:
|
||||
bool load(const std::string& efcPath, const std::string& uvPath, std::string* error = nullptr);
|
||||
int lifetime(int effectId) const;
|
||||
std::vector<GcEffectSprite> evaluate(int effectId, float tick, int uvRecordBase = 0) const;
|
||||
const GcUvCell* uvCell(uint16_t record, int frame) const;
|
||||
int uvTexture(uint16_t record) const;
|
||||
|
||||
private:
|
||||
struct Key {
|
||||
uint16_t time = 0;
|
||||
uint8_t interpolation = 0;
|
||||
std::vector<float> values;
|
||||
};
|
||||
struct Track {
|
||||
uint16_t loopStart = 0;
|
||||
uint16_t loopEnd = 0;
|
||||
std::vector<Key> keys;
|
||||
};
|
||||
struct Child {
|
||||
uint8_t type = 0;
|
||||
uint16_t reference = 0xffff;
|
||||
bool inheritParent = false;
|
||||
std::array<Track, 5> tracks;
|
||||
};
|
||||
struct Effect {
|
||||
uint16_t lifetime = 0;
|
||||
std::vector<Child> children;
|
||||
};
|
||||
struct UvRecord {
|
||||
int16_t textureIndex = -1;
|
||||
std::vector<GcUvCell> cells;
|
||||
};
|
||||
|
||||
static std::vector<float> sampleTrack(const Track& track, float tick, bool* started);
|
||||
|
||||
std::vector<Effect> effects_;
|
||||
std::vector<UvRecord> uvRecords_;
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace gc {
|
||||
|
||||
struct MtxTexture {
|
||||
uint32_t offset = 0;
|
||||
uint32_t size = 0;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
uint32_t bitsPerPixel = 0;
|
||||
uint32_t fourCC = 0;
|
||||
};
|
||||
|
||||
struct MtxArchive {
|
||||
std::vector<MtxTexture> textures;
|
||||
};
|
||||
|
||||
bool ParseMtxArchive(const std::vector<uint8_t>& bytes,
|
||||
MtxArchive* archive,
|
||||
std::string* error = nullptr);
|
||||
|
||||
// MTX stores a normal DDS surface with its four-byte magic replaced by an
|
||||
// internal field. This returns the exact embedded surface with "DDS " put
|
||||
// back, suitable for the existing DDS loader or external inspection tools.
|
||||
bool ExtractMtxTextureDds(const std::vector<uint8_t>& bytes,
|
||||
const MtxTexture& texture,
|
||||
std::vector<uint8_t>* dds,
|
||||
std::string* error = nullptr);
|
||||
|
||||
} // namespace gc
|
||||
@@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace gc {
|
||||
|
||||
// NOTE: these IDs are based on static analysis of a limited sample set and may
|
||||
// need adjustments as we decode more charts.
|
||||
enum class NoteType : uint32_t {
|
||||
// --- System / Timing ---
|
||||
BpmChange = 0x00000000, // Value = BPM? Or a timing/speed scalar.
|
||||
Camera = 0x00000002, // Camera control (hypothesis)
|
||||
MeasureLine = 0x00000004, // Measure start / marker (hypothesis)
|
||||
BeatLine = 0x0000003C, // (60) Visual beat grid line (hypothesis)
|
||||
|
||||
// --- Basic Notes ---
|
||||
Tap = 0x00000029, // (41) HIT: regular tap (hypothesis)
|
||||
Critical = 0x0000002A, // (42) CRITICAL: double tap / star (hypothesis)
|
||||
|
||||
// --- Holds ---
|
||||
HoldStart = 0x0000002B, // (43) HOLD start (hypothesis)
|
||||
HoldEnd = 0x0000002C, // (44) HOLD end (hypothesis)
|
||||
DualHold = 0x0000002F, // (47) Dual hold (hypothesis)
|
||||
|
||||
// --- Slides (Value = Angle in Radians) ---
|
||||
Slide = 0x0000002D, // (45) Slide (hypothesis)
|
||||
DualSlide = 0x0000002E, // (46) Dual slide (hypothesis)
|
||||
SlideHold = 0x00000030, // (48) Slide + hold? (hypothesis)
|
||||
|
||||
// --- Special / Legacy (seen in 10pt8tion) ---
|
||||
Legacy_Tap = 0x00000100,
|
||||
Legacy_Slide = 0x00000A00,
|
||||
|
||||
// --- Unknown ---
|
||||
Unknown = 0xFFFFFFFFu,
|
||||
};
|
||||
|
||||
inline bool IsNote(uint32_t type) {
|
||||
return (type >= 0x29u && type <= 0x30u) || type == 0x100u || type == 0xA00u;
|
||||
}
|
||||
|
||||
} // namespace gc
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include "gc/RvbScene.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace gc {
|
||||
|
||||
struct RvbImageDraw {
|
||||
std::string imageSymbol;
|
||||
std::string instancePath;
|
||||
// top-left, top-right, bottom-left, bottom-right in the RVB canvas
|
||||
std::array<std::array<float, 2>, 4> corners{};
|
||||
std::array<float, 3> color{1.0f, 1.0f, 1.0f};
|
||||
float alpha = 1.0f;
|
||||
uint32_t depth = 0;
|
||||
};
|
||||
|
||||
// A Flash-style MovieClip path mapped to the labeled frame that should be
|
||||
// visible. Paths are the same absolute paths exported in PREP ("/" is the
|
||||
// root timeline). Clips not mentioned here remain on their first FRAM.
|
||||
struct RvbSnapshotState {
|
||||
std::unordered_map<std::string, std::string> frameByPath;
|
||||
bool includeRootOther = false;
|
||||
};
|
||||
|
||||
// Builds the display list produced by the first frame of the root timeline
|
||||
// and the first frame of every placed MovieClip. This is the exact static
|
||||
// base of the original scene; later timeline frames and ActionScript state
|
||||
// changes can be layered on top as their opcodes are recovered.
|
||||
bool BuildRvbInitialSnapshot(const std::vector<uint8_t>& bytes,
|
||||
const RvbScene& scene,
|
||||
std::vector<RvbImageDraw>* draws,
|
||||
std::string* error = nullptr);
|
||||
|
||||
// Builds the display list at selected labeled frames. RVB FRAM records are
|
||||
// deltas, so this applies PLC3/RMOV commands in order through each requested
|
||||
// frame instead of treating a frame as a self-contained draw list.
|
||||
bool BuildRvbSnapshot(const std::vector<uint8_t>& bytes,
|
||||
const RvbScene& scene,
|
||||
const RvbSnapshotState& state,
|
||||
std::vector<RvbImageDraw>* draws,
|
||||
std::string* error = nullptr);
|
||||
|
||||
// Builds an exported/linkage MovieClip without requiring it to be placed on
|
||||
// the root timeline. game471.exe uses this path for the twelve dynamically
|
||||
// instantiated select-music rows (mc_music_link / mc_index_link).
|
||||
bool BuildRvbSymbolSnapshot(const std::vector<uint8_t>& bytes,
|
||||
const RvbScene& scene,
|
||||
const std::string& symbolName,
|
||||
const RvbSnapshotState& state,
|
||||
std::vector<RvbImageDraw>* draws,
|
||||
std::string* error = nullptr);
|
||||
|
||||
} // namespace gc
|
||||
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace gc {
|
||||
|
||||
struct RvbChunk {
|
||||
std::string tag;
|
||||
uint32_t offset = 0;
|
||||
uint32_t size = 0;
|
||||
};
|
||||
|
||||
// A PREP entry binds an animation/action name to an instance path in the
|
||||
// exported menu scene. These names are what game471.exe uses to drive the
|
||||
// select-music and difficulty state machines.
|
||||
struct RvbBinding {
|
||||
std::string action;
|
||||
std::string instancePath;
|
||||
};
|
||||
|
||||
struct RvbImageResource {
|
||||
std::string fileName;
|
||||
std::string symbolName;
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
};
|
||||
|
||||
struct RvbExport {
|
||||
std::string definitionName;
|
||||
std::string linkageName;
|
||||
};
|
||||
|
||||
struct RvbNode {
|
||||
std::string tag;
|
||||
uint32_t offset = 0;
|
||||
uint32_t size = 0;
|
||||
uint32_t localDataOffset = 0;
|
||||
uint32_t localDataSize = 0;
|
||||
std::vector<RvbNode> children;
|
||||
};
|
||||
|
||||
struct RvbScene {
|
||||
uint8_t framesPerSecond = 0;
|
||||
uint16_t sourceWidth = 0;
|
||||
uint16_t sourceHeight = 0;
|
||||
std::vector<RvbChunk> chunks;
|
||||
std::vector<RvbBinding> bindings;
|
||||
std::vector<RvbImageResource> images;
|
||||
std::vector<RvbExport> exports;
|
||||
std::vector<RvbNode> roots;
|
||||
};
|
||||
|
||||
bool ParseRvbScene(const std::vector<uint8_t>& bytes,
|
||||
RvbScene* scene,
|
||||
std::string* error = nullptr);
|
||||
|
||||
} // namespace gc
|
||||
@@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace gc {
|
||||
|
||||
// One 0xb4-byte runtime entry created by game471.exe's stage_param.dat loader.
|
||||
// Strings in the file are byte-length-prefixed and retain the game's source
|
||||
// encoding (mostly CP932 for localized text).
|
||||
struct StageCatalogEntry {
|
||||
uint32_t id = 0;
|
||||
std::string title;
|
||||
std::string imageKey;
|
||||
std::string artist;
|
||||
std::string source;
|
||||
std::string sortKey;
|
||||
uint8_t genre = 0;
|
||||
std::string duration;
|
||||
std::array<uint8_t, 4> difficultyRatings{};
|
||||
std::string bpm;
|
||||
// Per-difficulty percentage levels passed to LoadStageBGM for the two
|
||||
// continuously synchronized stage stems.
|
||||
std::array<uint8_t, 4> bgmVolumes{};
|
||||
std::array<uint8_t, 4> shotVolumes{};
|
||||
std::array<uint32_t, 3> timingValues{};
|
||||
std::array<uint8_t, 2> unknown60{};
|
||||
std::string bgmBase;
|
||||
std::array<std::string, 4> chartGroup0{};
|
||||
std::array<std::string, 4> chartSuffixes{};
|
||||
std::array<std::string, 4> chartIds{};
|
||||
std::string unknown9c;
|
||||
uint32_t unknownA0 = 0;
|
||||
std::array<uint8_t, 2> unknownA4{};
|
||||
std::string unknownAc;
|
||||
uint8_t unknownB0 = 0;
|
||||
};
|
||||
|
||||
bool ParseStageCatalog(const std::vector<uint8_t>& bytes,
|
||||
std::vector<StageCatalogEntry>* entries,
|
||||
std::string* error = nullptr);
|
||||
|
||||
const StageCatalogEntry* FindStageCatalogEntryByChart(
|
||||
const std::vector<StageCatalogEntry>& entries,
|
||||
const std::string& chartId);
|
||||
|
||||
} // namespace gc
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef OPENROLLER_GC_STAGEDAT_HPP
|
||||
#define OPENROLLER_GC_STAGEDAT_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace gc {
|
||||
|
||||
struct Section {
|
||||
size_t start = 0;
|
||||
size_t end = 0;
|
||||
};
|
||||
|
||||
struct StageDat {
|
||||
std::vector<uint8_t> bytes;
|
||||
|
||||
uint32_t headerSize = 0;
|
||||
std::vector<uint32_t> headerWords;
|
||||
std::vector<size_t> offsets; // sorted unique offsets within file
|
||||
std::vector<Section> sections; // derived from offsets
|
||||
|
||||
static bool LoadFromFile(const std::string& path, StageDat& out, std::string* err);
|
||||
};
|
||||
|
||||
} // namespace gc
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
#ifndef OPENROLLER_GC_STAGEPATTERN_HPP
|
||||
#define OPENROLLER_GC_STAGEPATTERN_HPP
|
||||
|
||||
#include "gc/StageDat.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace gc {
|
||||
|
||||
struct Color {
|
||||
uint8_t r = 0;
|
||||
uint8_t g = 0;
|
||||
uint8_t b = 0;
|
||||
uint8_t a = 0;
|
||||
};
|
||||
|
||||
struct StageHeader {
|
||||
uint32_t stageCfg = 0;
|
||||
uint32_t trackDrawDist = 0;
|
||||
uint32_t track = 0;
|
||||
uint32_t notes = 0;
|
||||
uint32_t camera = 0;
|
||||
uint32_t particles = 0;
|
||||
uint32_t visualizer = 0;
|
||||
uint32_t unk1 = 0;
|
||||
uint32_t colors = 0;
|
||||
uint32_t objects = 0;
|
||||
uint32_t unk2 = 0;
|
||||
uint32_t colors2 = 0;
|
||||
uint32_t unk3 = 0;
|
||||
};
|
||||
|
||||
struct BpmChange {
|
||||
uint32_t timeMs = 0;
|
||||
uint32_t bpm = 0;
|
||||
};
|
||||
|
||||
struct NoteSetting {
|
||||
uint32_t timeMs = 0;
|
||||
// TuneTimingData::GetTime: 1 is an absolute millisecond value, 3 uses
|
||||
// the spacing to the next note, and every other mode scales by beat_ms.
|
||||
uint32_t mode = 0;
|
||||
float value = 0.0f;
|
||||
};
|
||||
|
||||
struct StageConfig {
|
||||
float endTime1 = 0.0f;
|
||||
float endTime2 = 0.0f;
|
||||
float outroTime = 0.0f;
|
||||
std::vector<BpmChange> bpmChanges;
|
||||
std::array<std::vector<NoteSetting>, 4> noteSettings;
|
||||
std::string chartName;
|
||||
std::string chartName2;
|
||||
std::string bgmName;
|
||||
std::string shotName;
|
||||
float backwardsDrawDist = 0.0f;
|
||||
float forwardDrawDist = 0.0f;
|
||||
Color trackAheadColor;
|
||||
Color trackBehindColor;
|
||||
uint8_t audioOffset = 0;
|
||||
float visualOffset = 0.0f;
|
||||
Color unkColor;
|
||||
};
|
||||
|
||||
struct DrawDistancePoint {
|
||||
uint32_t timeMs = 0;
|
||||
float distance = 0.0f;
|
||||
};
|
||||
|
||||
struct TrackPiece {
|
||||
uint32_t timeMs = 0;
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
};
|
||||
|
||||
// Type byte used by the original arcade stage-note record. Keep this
|
||||
// distinct from the legacy editor-side NoteType in include/gc/NoteTypes.hpp,
|
||||
// whose numeric IDs describe another interchange format.
|
||||
enum class StageNoteType : uint8_t {
|
||||
None = 0,
|
||||
Normal = 1,
|
||||
Flick = 2,
|
||||
Hold = 3,
|
||||
Scratch = 4,
|
||||
Beat = 5,
|
||||
MerryGoRound = 6,
|
||||
Hidden = 7,
|
||||
Hidden2 = 8,
|
||||
Critical = 9,
|
||||
SlideHold = 10,
|
||||
SlideCounter = 11,
|
||||
Turn = 12,
|
||||
Spin = 13,
|
||||
Finish = 14,
|
||||
DualHold = 15,
|
||||
};
|
||||
|
||||
const char* NoteTypeName(uint8_t rawType);
|
||||
|
||||
// Wire layout recovered from game471.exe: FUN_005ea800 reads exactly 99 bytes
|
||||
// per note. Field semantics remain neutral until their consumers are mapped.
|
||||
struct StageNote {
|
||||
static constexpr size_t kRecordSize = 99;
|
||||
|
||||
uint32_t timeMs = 0;
|
||||
StageNoteType type = StageNoteType::None;
|
||||
uint8_t typeOverride = 0; // original runtime forces type=1 when non-zero
|
||||
std::array<int16_t, 9> params16{};
|
||||
uint8_t flag24 = 0;
|
||||
std::array<float, 3> params25{};
|
||||
uint8_t flag37 = 0;
|
||||
uint8_t flag38 = 0;
|
||||
std::array<float, 4> params39{};
|
||||
std::array<uint32_t, 3> params55{};
|
||||
float param67 = 0.0f;
|
||||
uint32_t param71 = 0;
|
||||
std::array<float, 5> params75{};
|
||||
uint32_t param95 = 0;
|
||||
};
|
||||
|
||||
struct CameraPoint {
|
||||
uint32_t timeMs = 0;
|
||||
uint8_t aMode = 0;
|
||||
uint8_t fMode = 0;
|
||||
float dist = 0.0f;
|
||||
float rotationA[2] = {0.0f, 0.0f};
|
||||
float originOff[3] = {0.0f, 0.0f, 0.0f};
|
||||
uint8_t projType = 0;
|
||||
float fieldFar[3] = {0.0f, 0.0f, 0.0f};
|
||||
float fieldNear[3] = {0.0f, 0.0f, 0.0f};
|
||||
float rotationB = 0.0f;
|
||||
};
|
||||
|
||||
struct ParticlePoint {
|
||||
static constexpr size_t kRecordSize = 44;
|
||||
|
||||
uint32_t timeMs = 0;
|
||||
uint32_t enabled = 0;
|
||||
uint32_t shape = 0;
|
||||
uint32_t texture = 0;
|
||||
Color color;
|
||||
float velocity[3] = {0.0f, 0.0f, 0.0f};
|
||||
float repeatMeasure = 0.0f;
|
||||
float lifespanMeasure = 0.0f;
|
||||
uint32_t groupShapeSize = 0;
|
||||
};
|
||||
|
||||
struct VisualizerPoint {
|
||||
static constexpr size_t kRecordSize = 12;
|
||||
|
||||
uint32_t timeMs = 0;
|
||||
uint32_t type = 0;
|
||||
Color color;
|
||||
};
|
||||
|
||||
struct BackgroundColorPoint {
|
||||
static constexpr size_t kRecordSize = 22;
|
||||
|
||||
uint32_t timeMs = 0;
|
||||
Color topRight;
|
||||
Color topLeft;
|
||||
Color bottomRight;
|
||||
Color bottomLeft;
|
||||
bool interpolateToNext = false;
|
||||
bool audioReactive = false;
|
||||
};
|
||||
|
||||
struct VisibilityPoint {
|
||||
uint32_t timeMs = 0;
|
||||
bool fadeOut = false;
|
||||
bool fadeIn = false;
|
||||
bool visible = false;
|
||||
};
|
||||
|
||||
struct TransformPoint {
|
||||
uint32_t timeMs = 0;
|
||||
bool tweenTowards = false;
|
||||
bool tweenAway = false;
|
||||
float value[3] = {0.0f, 0.0f, 0.0f};
|
||||
};
|
||||
|
||||
struct ObjectColorPoint {
|
||||
uint32_t timeMs = 0;
|
||||
bool tweenTowards = false;
|
||||
bool tweenAway = false;
|
||||
Color color;
|
||||
};
|
||||
|
||||
struct StageObject {
|
||||
uint32_t model = 0;
|
||||
uint32_t fragmentShader = 0;
|
||||
bool wireframe = false;
|
||||
bool flashing = false;
|
||||
bool unknownFlag = false;
|
||||
float position[3] = {0.0f, 0.0f, 0.0f};
|
||||
float scale[3] = {1.0f, 1.0f, 1.0f};
|
||||
float rotation[3] = {0.0f, 0.0f, 0.0f};
|
||||
float color[4] = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
float unknownVector[3] = {0.0f, 0.0f, 0.0f};
|
||||
// game471 supplemental object table (stage format > 0x29ce). A child is
|
||||
// rendered with parent * child transform and component-wise parent color.
|
||||
int32_t parentIndex = -1;
|
||||
std::vector<VisibilityPoint> visibility;
|
||||
std::vector<TransformPoint> movement;
|
||||
std::vector<TransformPoint> scaling;
|
||||
std::vector<TransformPoint> rotations;
|
||||
std::vector<ObjectColorPoint> colorChanges;
|
||||
};
|
||||
|
||||
struct ParsedStagePattern {
|
||||
StageHeader header;
|
||||
StageConfig config;
|
||||
std::vector<DrawDistancePoint> drawDistances;
|
||||
std::vector<TrackPiece> track;
|
||||
std::vector<std::string> noteNames;
|
||||
std::vector<StageNote> notes;
|
||||
std::vector<CameraPoint> cameras;
|
||||
std::vector<ParticlePoint> particles;
|
||||
std::vector<VisualizerPoint> visualizer;
|
||||
std::vector<BackgroundColorPoint> backgroundColors;
|
||||
std::vector<std::string> modelNames;
|
||||
std::vector<std::string> fragmentShaderNames;
|
||||
std::vector<StageObject> objects;
|
||||
};
|
||||
|
||||
bool ParseStagePattern(const StageDat& dat, ParsedStagePattern* out, std::string* err);
|
||||
|
||||
} // namespace gc
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef OPENROLLER_GC_TUMOMODEL_HPP
|
||||
#define OPENROLLER_GC_TUMOMODEL_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace gc {
|
||||
|
||||
struct TumoVertex {
|
||||
float x = 0.0f;
|
||||
float y = 0.0f;
|
||||
float z = 0.0f;
|
||||
};
|
||||
|
||||
struct TumoGeometry {
|
||||
std::vector<TumoVertex> triangles;
|
||||
std::vector<TumoVertex> solidLines;
|
||||
std::vector<TumoVertex> wireframeLines;
|
||||
};
|
||||
|
||||
// Decodes the common one-mesh TUMO layout used by gameplay stage objects.
|
||||
// Polygon fans are expanded on the host so the PSP only has to submit flat
|
||||
// GU_TRIANGLES/GU_LINES arrays.
|
||||
bool LoadTumoGeometry(const std::string& path, TumoGeometry* out, std::string* error);
|
||||
|
||||
} // namespace gc
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user