Actions

SCHG

Sonic Forces/Formats/BINA/GEdit

From Sonic Retro

Sonic Community Hacking Guide
Sonic Forces
File Index
wars_0

wars_1
wars_patch

BINA Formats
GEdit

The GEdit format is used for defining "set data" (stage object layouts). You can find each stage's gedit files in "wars_patch.cpk" (for some reason not in wars_0 or wars_1), inside the PAC file named like [stage ID]_gedit.pac under the "gedit" folder (E.G. w5a01_gedit.pac).

Data

The GEdit format is a BINA format, therefore it contains a BINA Header, String Table, and Offset Table as described in the above section on the BINA format. The format-specific "Data" portion of the GEdit format works as follows:

struct Header
{
    ulong Padding1 = 0;
    ulong Padding2 = 0;
    
    ulong ObjectOffsetTableOffset;
    ulong ObjectCount;

    // Not sure why the object count is in here twice? Lol.
    // Skyth says it might be because they used a vector for objects, which has a count as well as a capacity.
    ulong ObjectCount2 = ObjectCount;
    ulong Padding3 = 0;

    ulong[ObjectCount] ObjectOffsetTable; // An array of offsets to each object entry
    ObjectEntry[ObjectCount] Objects;
}

class ObjectEntry
{
    ulong Padding1 = 0;
    ulong ObjectTypeOffset; // Non-absolute offset to the object's type in the BINA String Table.

    ulong ObjectNameOffset; // Non-absolute offset to the object's name in the BINA String Table.
    ForcesObjectReference ID; // The information used to reference this object.
    ForcesObjectReference ParentID; // A reference to this object's parent. Simply set to null if this object has no parent.

    float[3] Position;
    float[3] Rotation; // In Euler angles represented via radians, NOT degrees!

    // If any objects have this object set as their parent, their position/rotation will be
    // overridden with this object's position/rotation + ChildPositionOffset/ChildRotationOffset.
    float[3] ChildPositionOffset;
    float[3] ChildRotationOffset; // Also in radians
    
    // See the following section for more information on tags
    ulong TagsOffsetTableOffset;
    ulong TagCount; // ?
    ulong TagCount2 = TagCount; // Probably because they used a vector for tags, just like with objects??
    ulong Padding3 = 0;

    // Parameters are hard-coded for each object type. Since there are too
    // many object-specific parameters to list on one page, see our Forces
    // object templates on the HedgeLib repository for type-specific parameter
    // specificatons. (https://goo.gl/e1tYXT)
    ulong ParametersOffset;
    
    ulong[TagCount] TagsOffsetTable; // An array of offsets to each tag
    Tag[TagCount] Tags;
}

// These are also used by parameters to reference other objects
class ForcesObjectReference
{
    // The object's ID, local to the object's "group", or the .gedit
    // file the object is defined in if no group is specified.
    ushort ID;

    // The ID of the object's "group" (or 0 if the object is not
    // part of a group), which is global, I.E. it can be used to
    // reference objects from any .gedit file within the same pac.
    ushort GroupID;
}

Tags

Tags are a special type of data that can be assigned to an object.

They act very similarly to the object's parameters, except tags actually have types that are included in the set data, as well as a pre-defined structure that can be used to read them even if their type is not known!

class Tag
{
    ulong Padding1 = 0;
    ulong TypeOffset; // Points to the tag's type in the BINA String Table
    ulong DataLength;
    ulong DataOffset;

    // The actual data in this array has to be parsed differently based on the tag's type.
    // See the following section for currently-known tags.
    byte[DataLength] Data;
}


While the data itself can be read due to this structure even if the type of tag being read is unknown, actually parsing it unfortunately still requires type-specific code or templates. Here are the specifications for every currently-known type:

RangeSpawning

class RangeSpawning
{
    // How close the player needs to get to the
    // object before the object will spawn.
    float RangeIn;

    // How far the player needs to move away from the object once
    // it has spawned before the object will de-spawn.
    float RangeOut;
}

...And that appears to be the only type of tag used in Forces! Oh, Sonic Team.

References


Sonic Community Hacking Guide
General
SonED2 Manual | Subroutine Equivalency List
Game-Specific
Sonic the Hedgehog (16-bit) | Sonic the Hedgehog (8-bit) | Sonic CD (prototype 510) | Sonic CD | Sonic CD (PC) | Sonic CD (2011) | Sonic 2 (Simon Wai prototype) | Sonic 2 (16-bit) | Sonic 2 (Master System) | Sonic 3 | Sonic 3 & Knuckles | Chaotix | Sonic Jam | Sonic Jam 6 | Sonic Adventure | Sonic Adventure DX: Director's Cut | Sonic Adventure DX: PC | Sonic Adventure (2010) | Sonic Adventure 2 | Sonic Adventure 2: Battle | Sonic Adventure 2 (PC) | Sonic Heroes | Sonic Riders | Sonic the Hedgehog (2006) | Sonic & Sega All-Stars Racing | Sonic Unleashed (Xbox 360/PS3) | Sonic Colours | Sonic Generations | Sonic Forces
Technical information
Sonic Eraser | Sonic 2 (Nick Arcade prototype) | Sonic CD (prototype; 1992-12-04) | Dr. Robotnik's Mean Bean Machine | Sonic Triple Trouble | Tails Adventures | Sonic Crackers | Sonic 3D: Flickies' Island | Sonic & Knuckles Collection | Sonic R | Sonic Shuffle | Sonic Advance | Sonic Advance 3 | Sonic Battle | Shadow the Hedgehog | Sonic Rush | Sonic Classic Collection | Sonic Free Riders | Sonic Lost World
Legacy Guides
The Nemesis Hacking Guides The Esrael Hacking Guides
ROM: Sonic 1 | Sonic 2 | Sonic 2 Beta | Sonic 3

Savestate: Sonic 1 | Sonic 2 Beta/Final | Sonic 3

Sonic 1 (English / Portuguese) | Sonic 2 Beta (English / Portuguese) | Sonic 2 and Knuckles (English / Portuguese)
Move to Sega Retro
Number Systems (or scrap) | Assembly Hacking Guide | 68000 Instruction Set | 68000 ASM-to-Hex Code Reference | SMPS Music Hacking Guide | Mega Drive technical information