Skip to content

4) Arabiki64: Example S64 to Display List Converter

Buu342 edited this page Jun 12, 2024 · 13 revisions

This page contains extra information regarding Arabiki64.

Materials

Because display lists require material information, the program will request input from the user to fill in those details. This process can be automated by feeding the tool a text file with list of material information. The material information can be created either by hand, or using the Chorizo application. The syntax of the text file is as follows:

NAME TYPE INFO FLAGS

Where:

  • NAME should be the name of the material.
  • TYPE should be the type of the material. Accepted values are TEXTURE, PRIMCOL, or OMIT. Using the OMIT type will prevent Arabiki64 from generating display list commands for this material.
  • INFO should be information relevant to the material. If the given type was TEXTURE, then the width and height of the texture in texels should be given (separated by spaces). If the given type was PRIMCOL, then RGB values should be provided (ranging from 0 to 255, separated by spaces).
  • FLAGS are any relevant flags for this material. You can change cycle type, combine modes, render modes, texture filters, image format (RGBA, Color Index, etc...), image pixel size, texture modes (like mirror and clamp), or geometry modes. Most of these are Libultra specific, except the texture filter and geometry flags. All you need to do is to provide those macros, separated by spaces (please note that Arabiki does not validate whether the macro is valid or not). Example: G_CC_2CYCLE G_RM_AA_ZB_TEX_EDGE G_RM_AA_ZB_TEX_EDGE2 G_IM_FMT_RGBA G_IM_SIZ_32b G_TX_CLAMP G_TX_CLAMP.

You can use the DONTLOAD flag to prevent Arabiki64 from generating display list commands for loading the material, but still generate the change of flags. This is useful, for instance, if you have a dynamic material.

Although, in order to change the material before calling the display list, you need some sort of guarantee that said material will always be first in the list... You can use the LOADFIRST flag to tell Arabiki64 to load this material first. You obviously can't have multiple material with this flag in one mesh.

The default flags for all materials are as follows:

Defualt Cycle: G_CYC_1CYCLE
Default Texture Filter: G_TF_BILERP
Default Combine Mode (For Textures): G_CC_MODULATEIDECALA G_CC_MODULATEIDECALA
Default Combine Mode (For Primitive Colors): G_CC_PRIMLITE G_CC_PRIMLITE
Default Render Mode: G_RM_AA_ZB_OPA_SURF G_RM_AA_ZB_OPA_SURF2
Default Texture Type: G_IM_FMT_RGBA
Default Texture Size: G_IM_SIZ_16b
Default Texture Modes: G_TX_MIRROR G_TX_MIRROR
Default Geometry Mode: G_SHADE | G_ZBUFFER | G_CULL_BACK | G_SHADING_SMOOTH | G_LIGHTING

G_CC_PRIMLITE is a custom combine mode that allows for mixing of primitive colors with lighting (for Libultra). Arabiki64 will generate a macro for this in your display list file.

If you wish to remove one of the default geometry modes, you can do so by listing it in the flags with an exclamation mark. For instance, if you wanted to have a material without backface culling, you'd provide the flag: !G_CULL_BACK.

Each material should be separated by a new line. For an example material list, check sample/CatherineMaterials.txt.

Important note regarding material sorting

One of the important optimization steps performed by Arabiki involves it trying to find the best material loading order to reduce material changes during mesh swaps. This, however, can be problematic if a specific mesh in your model has a lot of materials.

Consider a single mesh which has 9 materials. Arabiki attempts to generate all possible combinations of material loads to determine which is best. A model with 9 materials will have 9 factorial combinations (this means 9x8x7x...x2x1 combinations, equivalent to 362,880)! It's likely that your computer won't have enough memory to sort such a model.

A bodge solution which I have included to fix this is to give the problematic mesh the NoSort property.

Select the problem mesh's bone in Pose Mode. Then, go to the bone tab, and scroll to the bottom. You should see a section called "Custom Properties". Add a new custom property and name it NoSort, its value doesn't matter, only the name. Your bone will not have its materials sorted during Arabiki's optimization stage.

Export Format

For a while, Arabiki was designed to export models in array format, which you could then #include in your project. This was not the ideal way of generating models, but it was a temporary solution. However the Sausage64 library and Arabiki tool have been since updated to add support for custom binary model format.

The binary model format is preferred because it allows the developer to load models from ROM and unload them when they're no longer necessary. Furthermore, said models can be loaded anywhere in memory, which wouldn't be possible with the old array format since the pointers would no longer be static.

If you do have a good reason to use the array format (such as engine-specific models which are never unloaded), you can use the -s flag to enable the old behavior.

Binary format description

This section describes the export format that was mentioned in the previous section. Please be aware that the numbers are stored in big endian format, and that all offsets are relative to the starting address of the file.

  • 4 byte header. First 3 bytes contain the characters 'S' '6' '4', and the last byte contains the version number
  • 2 bytes for the mesh count
  • 2 bytes for the material count
  • 2 bytes for the animation count
  • 4 bytes containing the offset of the mesh Table of Contents
  • 4 bytes containing the offset of the material Table of Contents
  • 4 bytes containing the offset of the animation Table of Contents

The mesh TOC is as follows:

  • 4 bytes with the meshdata offset
  • 4 bytes with the meshdata size
  • 4 bytes with the vertexdata offset
  • 4 bytes with the vertexdata size
  • 4 bytes with the facedata offset (OpenGL only)
  • 4 bytes with the facedata size (OpenGL only)
  • 4 bytes with the dldata offset
  • 4 bytes with the dldata size
  • 4 bytes with the number of Gfx slots (or renderblocks in OpenGL's case) the dldata will occupy

There will be as many mesh TOCs as the mesh count

The meshdata is as follows:

  • 2 bytes with the parent mesh index
  • 1 byte that describes if this mesh is a billboard
  • N bytes containing the name of the mesh

The vertexdata is as follows:

  • 6 bytes containing X Y Z coordinates as an integer
  • 2 bytes of padding
  • 4 bytes with texture U V values as an integer
  • 4 bytes containing either R G B A values, or containing normal vector X Y Z values (plus one more byte of padding)

The dldata format in Libultra is a bit complex and beyond the scope of this wiki. For more information, read the dlist.c. In libdragon, the dldata instead is as follows:

  • 2 bytes with the vertex count
  • 2 bytes with the vertex offset
  • 2 bytes with the face count
  • 2 bytes with the face offset
  • 4 bytes with the material id

There will be as many meshdata+vertexdata+(facedata)+dldata groups as the mesh count. In libdragon, the number of dldatas is described by the slot count.

The material TOC is as follows:

  • 4 bytes with the matdata offset
  • 4 bytes with the matdata size
  • 4 bytes with the material offset
  • 4 bytes with the material size

There will be as many material TOCs as the material count

The matdata is as follows:

  • 1 byte with the material type
  • 1 byte with the lighting flag
  • 1 byte with the frontface culling flag
  • 1 byte with the backface culling flag
  • 1 byte with the smooth shading flag
  • 1 byte with the depthtest flag
  • N bytes containing the name of the material

If the matdata type is a texture:

  • 4 bytes with the texture width
  • 4 bytes with the texture height
  • 4 bytes with the texture filter
  • 2 bytes with the texture wrapping on the S axis
  • 2 bytes with the texture wrapping on the T axis

If the matdata type is primcolor:

  • 1 byte with R color
  • 1 byte with G color
  • 1 byte with B color
  • 1 byte with A color

There will be as many texture+primcolor groups as the material count

The animation TOC is as follows:

  • 4 bytes with the animdata offset
  • 4 bytes with the animdata size
  • 4 bytes with the keyframedata offset
  • 4 bytes with the keyframedata size

There will be as many animation TOCs as the animation count

The animdata is as follows:

  • 4 bytes with the keyframe count
  • N bytes (equivalent to keyframe count multiplied by 2) with the keyframe indices. Each keyframe index is 2 bytes
  • N bytes with the animation name

The keyframedata is as follows:

  • 12 bytes with X Y Z vector translation (stored as a float)
  • 16 bytes with W X Y Z quaternion rotation (stored as a float)
  • 12 bytes with X Y Z vector scale (stored as a float)

There will be as many animdata+keyframedata groups as the animation count