Param Files (Smash 4)
Smash 4 stores most of it's runtime and constant values in param files. These files control everything from Character Attributes, to the CSS layout and even character costume count!
The param files have little to no structure which makes them fairly hard to read generically. The game has a function specific to each param file to read from it, meaning that the information to parse the file is entirely different depending on the param file you're looking at. Despite this, it is possible to parse and edit most files (around 80% of them or so).
The param files are essentially just an array of values, preceded by a type code for the value. The alignment is mostly 0xCCXXXXXXXX where CC is the typecode and XXXXXXXX is the value, but a few types differ. For example strings are typecode 8, followed by a 32 bit signed integer specifying the string length, and finally the string itself.
NOTE: The header seems to contain a field for endianness, however it doesn't seem to be used as the param files are always big endian regardless of whether the game is being run on the 3ds or WiiU.
|0x1||u8 - unsigned 8-bit integer|
|0x2||s8 - signed 8-bit integer|
|0x3||u16 - unsigned 16-bit integer|
|0x4||s16 - signed 16-bit integer|
|0x5||u32 - unsigned 32-bit integer|
|0x6||s32 - signed 32-bit integer|
|0x7||f32 - 32-bit floating point number|
|0x8||str - variable length string|
|0x20||group - Starts a new value group with X number of entries.|
Reading the param files
Reading the param files is done by walking the values starting at 0x08, adding each value to an array or "group" object until a 0x20 group typecode is reached. The values read before a 0x20 typecode is reached are just a list of values. Once a group is reached, the values that follow belong to a group specific structure. To parse the group, you must first read all the values until you hit a new 0x20 group typecode into an array. Then, divide the total number of values read by the first group's numEntry value and split the value array into that many subgroups. Then repeat for the new group typecode that was reached while reading the previous group's values. This repeats until the end of the file is reached.