OBD:CRSA

From OniGalore
Jump to navigation Jump to search

CRSA - Corpse Array

Related : Level files Oni Binary Data

The array consists of a 32-byte header, followed by a number of fixed-size corpse chunks (1100 bytes each).

The resulting file is completed to a 32-byte multiple with the 0xADDE blank filler

Since the capacity of the array is always the same (20 corpses), CRSA files are all the same size (0x5620 bytes). The array actually takes up 0x5610 bytes : the last 16 bytes are filled with the blank filler 0xADDE.

Header

What's in the header?
  • File ID and level ID as usual : 4 bytes each
  • A blank field filled with 0xADDE (dead) : 12 bytes
  • Array size (number of corpses) duplicated : 2x4 bytes
  • Array capacity (maximum number of corpses, always 20) : another 4 bytes
Example
00565-.CRSA in level3_Final.dat
Header
Offset Raw hex/string Value Meaning
0x00 01 35 02 00 565 File ID for 00565-.CRSA
0x04 01 00 00 06 3 Level ID
0x08
0x0C
0x010
AD DE AD DE
AD DE AD DE
AD DE AD DE
DEAD blank filler
0x14 11 00 00 00 17 17 corpses (array size)
0x18 11 00 00 00 17 17 corpses (array size again)
0x1C 14 00 00 00 20 Room for 20 corpses (array capacity)

Corpse chunks

They follow the header directly

What's in a corpse?
  • A space for notes (160 bytes) : often the name of the file the corpse was taken from when packing the array.
  • A link to the ONCC (model that should be used for the corpse) : that's 4 bytes as usual.
  • Then, 19 bones, each of them defined by absolute orientation and position (unlike in a TRAM, where orientations are relative)
    Every bone is (3x3 + 3)x4 = 48 bytes, so that's 19x48 = 912 bytes.
  • Finally, an axis-aligned bounding box (2x3x4 = 24 bytes)

The total size of a corpse is thus 1100 bytes.

What's in a bone?
The absolute orientation is defined in a "heavy" way via an orthonormal trihedron :
three 3D vectors x, y and z, each of length 1, at right angles with each other, and ordered "directly"
(like Oni's world axes : if x points left and y points up then z points to front, not back).
Each one of those vectors is stored as 3 floats (3x4 bytes), first x, then y, then z (so 3x3x4 = 36 bytes in total).
The absolute position R of a bone (of its parent node, actually) is stored as 3 floats right after the orientation trihedron.
That's another 12 bytes, so 48 bytes in total.

Reminder : the 2nd coordinate of R aka y is the height; same for x, y and z.

Example
first corpse of 00565-.CRSA in level3_Final.dat.
Offsets are measured from the start of the corpse chunk : add 0x20 for the offset from the start of file.
Notes and ONCC link
Offset Raw hex/string Value Meaning
0x00 _lvl_3_Intro_TCL_A_corpse.dat probably the name of the source file
0xA0 01 36 02 00 566 Link to 00566-TCTF_lite_1.ONCC
Bone orientation and position
Offset Bone Raw hex Value/Meaning
0xA4 Pelvis C1 74 66 3F 00 78 3E 3D 45 AB DD 3E
A6 8B 7D 3D 19 73 7F BF EE 67 B0 BC
03 AE DC 3E 82 2C 3D 3D 8D B2 66 BF
C5 FA E7 41 2E 2B CB C1 58 B4 45 C1
x = (0.900219, 0.046501, 0.432947)
y = (0.061901, -0.997850, -0.021534)
z = (0.431015, 0.0461850, -0.901162)
R = (28.997446, -25.396084, -12.356529)
0xD4 Lt Thigh ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x104 Lt Calf ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x134 Lt Foot ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x164 Rt Thigh ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x194 Rt Calf ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x1C4 Rt Foot ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x1F4 Mid ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x224 Chest ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x254 Neck ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x284 Head ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x2B4 Lt Shoulder ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x2E4 Lt Arm ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x314 Lt Wrist ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x344 Lt Fist ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x374 Rt Shoulder ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x3A4 Rt Arm ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x3D4 Rt Wrist ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
0x404 Rt Fist ... x = (, , )
y = (, , )
z = (, , )
R = (, , )
axis-aligned bounding box
Offset Raw hex/string Value Meaning
0x434 D4 22 8C 41 95 50 E9 C1 BC 31 9C C1 (17.517006, -29.164347, -19.524284) "minimal" corner of the AABB
0x440 75 E6 14 42 2E 20 B1 C1 07 B1 D3 C0 (37.225056, -22.140713, -6.615360) "maximal" corner of the AABB



Screenshot

The example is the same as above : 00565-.CRSA in level3_Final.dat

The first corpse chunk has been outlined in black.

crsa_a.gif