Skip to content

Asobo Arithmetic Coding Compression

widberg edited this page Jul 22, 2022 · 15 revisions

Asobo uses Arithmetic Coding (AC) to compress save game data. RTTI indicates that the AC implementation in FUEL is a modification of the one presented at the end of "Arithmetic Coding revealed - A guided tour from theory to praxis". Both Order 0 and Order 1 AC are present in the executable; however, the Order 0 model appears to be unused as the value which selects between the two when saving and loading is hardcoded to use the Order 1 model when handling save games.

There are several major differences between Asobo's implementation and the one presented in "Arithmetic Coding revealed - A guided tour from theory to praxis". The most notable of which is that the paper only implements the Order 0 model. Less notably, Asobo does not use a sentinel symbol to represent the end of the input. Instead, the compressed data is prefixed with the decompressed size and execution completes when that number of bytes has been written to the output. However, the sentinel check is still present in the decoder even though the encoder never writes it. This is potentially a holdover from the paper's implementation. Other minor differences include different constant values for the ranges and multiple frequency count arrays.

The last byte written to the output when compressing is uninitialized garbage. Therefore, the compression algorithm is nondeterministic. i.e. decompressing and recompressing the same file may yield different results due to this last byte being garbage. This is due to an off-by-one error. The size of the output buffer should be the size of the compressed data plus 8 to accommodate the size information prefix. However, it is actually the size of the compressed data plus 9. When copying the compressed data into this buffer the number of bytes copied is the size of the output buffer minus 8 which should be the size of the compressed data. However, it is actually the size of the compressed data plus 1 due to the previous error. This leads to an out-of-bounds read of uninitialized data. Additionally, the error was perpetuated in the loader which expects this extra byte to be there but does not care about its value. It is unclear if this was intentional, but since there is an out-of-bounds read, I am content with calling it an error. The reference implementations append a null byte to the end of the output instead of a garbage value. This does not affect the game's ability to load the save file since it is truly a garbage byte.

Reference Implementations

The Asobo-ArithmeticCoderC repository contains a minimal C++ implementation of Asobo's Arithmetic Coding Compression. The fuel-save-editor repository contains a Nim implementation of the algorithm as part of the save editing functionality.

References

Home
FAQ

For FMTK Users and Mod Developers

Read the Docs

For FMTK Developers

Asobo BigFile Format Specification
Asobo Classes
      Animation_Z
      Binary_Z
      Bitmap_Z
      Camera_Z
      CollisionVol_Z
      Fonts_Z
      GameObj_Z
      GenWorld_Z
      GwRoad_Z
      Keyframer*_Z
      Light_Z
      LightData_Z
      Lod_Z
      LodData_Z
      Material_Z
      MaterialAnim_Z
      MaterialObj_Z
      Mesh_Z
      MeshData_Z
      Node_Z
      Omni_Z
      Particles_Z
      ParticlesData_Z
      RotShape_Z
      RotShapeData_Z
      Rtc_Z
      Skel_Z
      Skin_Z
      Sound_Z
      Spline_Z
      SplineGraph_Z
      Surface_Z
      SurfaceDatas_Z
      UserDefine_Z
      Warp_Z
      World_Z
      WorldRef_Z
Asobo File Format Idioms
Asobo CRC32
Asobo LZ Compression
Asobo Arithmetic Coding Compression
Asobo Save Game File Format Specification
Asobo Audio Formats
TotemTech/ToonTech/Zouna/ACE/BSSTech/Opal Timeline
Zouna Modding Resources
Miscellaneous

Clone this wiki locally