Since a lot of people modding Outbreak have next to zero
experience of writing or reading C code, I feel like this
small article might be a bit useful.
Most file formats in this info dump will be described as snippets of C structure declarations, which I personally find very easy and understandable to both read and write, as long as you're not using C's crazy declaration rules to its full extent (which is the entire reason this website exists.)
C structures usually follow this, ehm, structure:
struct <name> {
<first member>;
<second member>;
...
<N-th member>;
};
While not always being the case in actual C, in this info dump you can assume that members have zero padding in between. That is, bytes of the next member start immediately after the previous one.
In this info dump, each member in a structure will more or less follow this template:
<datatype> <name> [array-size]
<datatype>
is either a previously defined structure name or a basic
data unit, like an integer or float.<name>
is, obviously, how the member is named.[array-size]
is optional. If it's there, it means that the member
is an array of <datatype>
, with the size specified inside the square brackets. C uses char
, short
, int
, long
, float
basic data types, however,
their size is usually ambigious. So, for the sake of clarity, I'll be using
these data type names instead:
Name | Description | Size (in bytes) |
---|---|---|
u8 |
unsigned 8-bit integer, also known as a byte | 1 |
s8 |
signed 8-bit integer | 1 |
u16 |
unsigned 16-bit integer | 2 |
s16 |
signed 16-bit integer | 2 |
u32 |
unsigned 32-bit integer | 4 |
s32 |
signed 32-bit integer | 4 |
f32 |
32-bit floating point value | 4 |
integer
means that the value can hold only whole numbers. It cannot
have fractions.unsigned
means that the value cannot hold negative numbers. It can
hold only positive numbers (and zero).signed
means that the value can hold both positive and negative numbers.floating point
means that the value can hold fractions. For more information,
look up the IEEE 754 standard.One more important thing to keep in mind is that PS2 is a little-endian system,
which means that the multi-byte values are encoded sort of backwards.
For example, if you'd take an integer 12345
and convert it to hexidecimal, it
would become 0x3039
, but when writing it as bytes, you'll have to write bytes
39 30
.
If we have the following structures:
struct Foo {
f32 val;
s8 arr[4];
};
struct Bar {
s16 a;
s16 b;
u32 c;
Foo foo;
};
and, say, we want to convert the structure into bytes with the data set to these values:
Bar.a = -2;
Bar.b = -3;
Bar.c = 514;
Bar.foo.val = 1.0;
Bar.foo.arr[0] = 1;
Bar.foo.arr[1] = 2;
Bar.foo.arr[2] = 3;
Bar.foo.arr[3] = 4;
In this case, the bytes for the Bar
structure will be as follows:
FE FF // Bar.a
FD FF // Bar.b
02 02 00 00 // Bar.c
00 00 80 3F // Bar.foo.val
01 // Bar.foo.arr[0]
02 // Bar.foo.arr[1]
03 // Bar.foo.arr[2]
04 // Bar.foo.arr[3]
Without any comments and formatting (so, like in a hex editor), it would be
FE FF FD FF 02 02 00 00 00 00 80 3F 01 02 03 04
Last updated on 2024-10-18.