# GC Track and Background Reverse Notes Status: linear track evaluation and the base background color table are implemented in the Vectorail player. Camera mode bytes, fade modes and stage objects still need deeper mapping. ## Track wire data The main stage file stores track keys as big-endian records: ```text u32 count repeat count times: u32 time_ms f32 x f32 y f32 z ``` The stage constructor `FUN_005ed4c0` loads these into 16-byte runtime entries. The fourth float is not read from disk: the constructor computes the physical length to the next point and stores it there. It also accumulates the complete track length at stage-object offset `+0xb0`. ## Confirmed evaluation `FUN_005e9690` evaluates a track position at an integer timestamp. It finds the adjacent `time_ms` keys and computes: ```text u = (time_ms - key[i].time_ms) / (key[i+1].time_ms - key[i].time_ms) position = key[i] + (key[i+1] - key[i]) * u ``` There is no Catmull-Rom or other spline interpolation in this path. The Android symbol `GameScene::DrawWay` (`0x001b3b68`) establishes how the visible route itself is rendered. It clips the authored point list to the requested first and last timestamps, inserts linearly interpolated points at both exact boundaries, interpolates an RGBA color over that time interval, and submits the result as primitive mode 3: a line strip. It does not generate a camera-facing ribbon, resample by physical distance, or cull triangles. `FUN_005e9990` is a separate physical-distance sampler used while constructing duration-note paths. It carries leftover distance between segments so those generated samples remain uniform over corners; it is not the normal route renderer. The player now mirrors `DrawWay`: it uploads the original authored points plus the two exact timestamp intersections and draws separate behind/current and current/ahead line strips with endpoint color gradients. The stage values `backwardsDrawDist` and `forwardDrawDist` behave as seconds and are converted to milliseconds before comparison with track and note timestamps. Dynamic `TrackDrawDist` records are step changes, not interpolation keys. The StageConfig forward distance remains active until the timestamp of the first matching record, then each record replaces it. This matters for Knight Rider: its only record is `128400 ms: 0`, which hides the route at the end of the song; using the first record before its timestamp incorrectly hid the entire future route from the beginning. For `ac_10pt8tion_hard.dat`: ```text first track key: 0 ms, (0, 0, 0) second track key: 6486 ms, (0, 0, 199.985) draw behind: 10 s draw ahead: 7 s ``` Treating 7/10 as world units collapses the visible rail to a tiny fraction of the first segment; timestamp clipping produces the expected visible range. ## Track colors The stage config stores two RGBA colors directly after the draw-range values. They are used for the forward and already-travelled portions of the rail. For `10pt8tion_hard` they are `(255,0,128)` ahead and `(255,255,255)` behind. ## Base background The main `.dat` contains a `ColorTable` section. Each 22-byte record is: ```text u32 time_ms rgba top_right rgba top_left rgba bottom_right rgba bottom_left u8 interpolate_to_next u8 audio_reactive_color ``` `FUN_00642390` holds the active colors unless `interpolate_to_next` is set; in that case it linearly interpolates all four RGBA values to the following key. `audio_reactive_color` applies `FUN_005d9650` to each active color using the runtime analyser value. The Linux player now implements the exact hold versus interpolate selection and keeps the second mode at its neutral color factor until the analyser feeding `stage renderer +0x24` is ported. `data/stage/2d/_menu.dds` is not the gameplay background. It is a 512x256 UI atlas whose top-left 197x197 cell is the song jacket. The player has a small uncompressed DDS loader, but the jacket is disabled by default and is only an explicit debug comparison layer (`B`). The inherited procedural blue/black square grid has also been removed: the base layer is now only the stage-authored color table before particles, visualizers and objects are drawn. The remaining original scene is produced by the stage `particles`, `visualizer`, and `objects` sections (plus `.tumo` models), not by a single background bitmap. These sections are now decoded completely by `StagePattern`: particle records are 44 bytes, visualizer records are 12 bytes, and every variable-length object record is consumed through its visibility, movement, scaling, rotation and color-key arrays. Oshama contains 5 particle keys, 19 visualizer keys, 46 model names and 316 object instances; 10pt8tion contains 2, 28, 37 and 352 respectively. The Vectorail level data retains this decoded scene for the model-rendering pass. The PSP package now retains all three timelines. The particle constructor at `FUN_005f0940` creates a 64-instance pool for every configured particle key. `FUN_005f0130` scales both `repeatMeasure` and `lifespanMeasure` by the active beat duration. Recovered spawn layouts are: type 1, a deterministic/random point; type 2, a screen/grid group using `groupShapeSize`; type 3, six points at 60-degree intervals around a circle. The PSP implementation follows these timing and layout rules, but substitutes geometry for the original particle texture resource until that resource binding is mapped. The common `.tumo` container is also big-endian. Its outer count is followed, for each mesh, by resource names, an XYZ vertex table, eight bound floats, render parts, and polygon lists. A polygon corner is `u32 vertexIndex, f32 u, f32 v`; a separate block contains explicit line-index pairs. The player now triangulates polygon fans, retains line primitives, and renders stage objects with the original five animation channels: visibility, movement, scaling, linearly interpolated Euler rotation, and RGBA color. The final rotation uses the recovered `(-Y, X, Z)` quaternion-builder convention. Base and animated transform components are composed as separate matrices, matching `FUN_00643b20`; visibility fades use the original fixed 250 ms window. All 46 unique Oshama models and all 37 unique 10pt8tion models decode. `O` toggles this object layer for comparison. For stage format versions newer than `0x29ce`, the supplemental table beginning at the header's `ColorTable2` offset has a relative pointer at `base + 8`. Its stream is `u32 objectCount` followed by one signed big-endian `int16` `parentIndex` per object (`-1` means no parent). `FUN_006445b0` evaluates one parent level and renders `parentTransform * childTransform`; parent and child RGBA are multiplied component-wise. Oshama uses this on 80 of 316 objects and 10pt8tion on 87 of 352, so omitting it visibly loses grouped scale, placement, and opacity. The object's `wireframe` byte also selects mutually exclusive model paths: `FUN_005dd8e0` draws polygon parts, while `FUN_005dd7f0` draws the explicit TUMO edge buffer. The player previously drew both. Polygon/edge selection now matches the flag. `FUN_00648c30` enables `D3DRS_ZENABLE` and `D3DRS_ZWRITEENABLE` for the complete authored object loop, then disables both before the rail and markers are submitted. Objects therefore depth-test one another in file order, but never hide gameplay geometry drawn afterwards. ### Per-frame object clipping The stage loader also opens `data/stage/_clip.dat`. `FUN_005ed4c0` decodes it as: ```text u32be object_count u32be frame_count u8 visible[object_count][frame_count] ``` The payload is object-major. `FUN_006445b0` selects frame `round(time_ms / (1000 / 60))` and skips the object when the byte is zero; when the table is absent or the requested frame is past its end, it falls back to the normal authored-visibility path. Knight Rider has 178 objects and 7909 clip frames. Ignoring this table submits many objects which the original never draws in that camera frame and turns its background into overlapping full-screen geometry. The Linux player now applies the same test before object animation and submission. `FUN_005dd8e0` itself supports two TUMO part types. Type `0` is a triangle list; type `1` is a line list. Type-1 source polygons contain exactly two corners. Oshama's models contain ten such parts, including one with 1498 line vertices; treating them as polygon fans silently discarded all of them. The player now keeps solid line parts separate from both triangle parts and the wireframe edge buffer. All Oshama and 10pt8tion models end with a zero node count, so an internal model hierarchy is not responsible for their transforms.