# Coding guidelines This page contains some tips on how code should be written in this decompilation project. We don't have strict style rules for most things, but you should keep your code readable, and try to stick to the names and style used by the original programmers whenever possible. Naming variables properly isn't required to help with the decompilation. You can submit a PR with code you decompiled even if many of the variable names are just placeholders (e.g. `field_0x290`, `temp`, `r29`, `sp10`, etc) - these names can always be cleaned up later in a documentation pass of the actor. Placeholder names are preferable to coming up with names that are incorrect if you aren't sure exactly what the variables are. ## Table of Contents 1. [Offsets and padding](#offsets-and-padding) 2. [Includes](#includes) 3. [Naming style](#naming-style) 4. [Use the official names where possible](#use-the-official-names-where-possible) 5. [Look at the actor's model](#look-at-the-actors-model) ## Offsets and padding Member variables of classes and structs should all have comments to their left with the hexadecimal data offset of that member: ```cpp struct anm_prm { /* 0x00 */ s8 anmTblIdx; /* 0x01 */ u8 armAnmTblIdx; /* 0x02 */ u8 btpAnmTblIdx; /* 0x04 */ int loopMode; /* 0x08 */ f32 morf; /* 0x0C */ f32 speed; }; ``` Furthermore, padding data should not be written in the class/struct body. In the example above, note that no field is located at offset 0x03, and then `int loopMode;` starts at offset 0x04. This is because `int` needs to be aligned to 4 bytes, so the compiler can't put it at offset 0x03, so it inserts one unused byte of padding before `loopMode`. If a translation unit isn't fully decompiled yet, then there's no way to know if a particular offset is padding or if it actually has a field in there that is used by code that hasn't been decompiled yet. So you should wait until the TU is 100% decompiled before removing fields that look like padding. ## Includes Avoid unnecessary includes, especially in header files. clangd will give you a warning saying "Included header is not used directly (fix available)" if you aren't using a header at all. Forward declaring types where possible will reduce compile times. So instead of putting all the includes in a actor's header file, like so: ```cpp #include "d/d_path.h" #include "d/actor/d_a_obj_search.h" dPath* ppd; daObj_Search::Act_c* mpSearchLight; ``` You could move those includes into the actor's .cpp file where they are actually needed, and add forward declarations to the actor's header like so: ```cpp class dPath; namespace daObj_Search { class Act_c; }; dPath* ppd; daObj_Search::Act_c* mpSearchLight; ``` ## Naming style We try to stick to the same naming style that the original developers used. They didn't have a completely consistent naming style, but they tended to use certain prefixes and styles depending on the type of variable. Function parameters should be prefixed with `i_` (or `o_` if it's an output parameter) and use lowerCamelCase: * `fopAc_ac_c* i_this` * `int i_itemNo` * `GXTlutObj* o_tlutObj` In-function local variables have no prefix and use lower_snake_case: * `int zoff_blend_cnt = 0;` * `int phase_state = ...` Member variables of classes are generally prefixed with `m` (or `mp` for pointers) and use UpperCamelCase: * `fpc_ProcID mTimerID;` * `J3DModel* mpModel;` Member variables of structs (plain old data) have no prefix and use lower_snake_case: * `csXyz shape_angle;` * `int id;` Static variables are prefixed with `l_`, while global variables are prefixed with `g_` (the official names for these are all known from the symbol maps): * `static cXy l_texCoord[] = ...` * `dComIfG_inf_c g_dComIfG_gameInfo;` ## Use the official names where possible If a class has a getter function (whether it's an inline or not) that returns a member variable, you should generally name the member as indicated by its getter. For example: `getChainCnt()` would return `mChainCnt`. Another place that official variable names of all kinds can be revealed is in debug assertion strings. In these cases, you should always use the exact name from the assert, even if it doesn't follow a consistent style. For example, the following are both official names for similar in-function local variables: ```cpp J3DModelData* modelData = ... JUT_ASSERT(98, modelData != NULL); ``` ```cpp J3DModelData* model_data = ... JUT_ASSERT(382, model_data != NULL); ``` ## Look at the actor's model If a variable's name doesn't appear in a function name or assertion string, we'll have to come up with a name for it ourselves. To do this, you usually need to know what the decompiled actor you're looking at actually is in-game before you can start coming up with names. But it's often pretty hard to tell what an actor is just by reading its code. The official TU name of the actor doesn't tell you much, not only because they're frequently in Japanese, but also because they're aggressively abbreviated. e.g. `d_a_nh` is short for "mori **n**o **h**otaru", which is Japanese for "forest firefly", but it would be pretty much impossible to guess that without context, even if you know Japanese. If the actor has a 3D model, you can determine what the actor is by simply viewing the model in a model viewer. First, find the .arc file for this actor. Look in the `createHeap` or `useHeapInit` function for this actor. You should see something like: ```cpp (J3DModelData*)dComIfG_getObjectRes("Bk", BK_BDL_BK) ``` This means the actor's .arc in this example is named "Bk". You can find it your copy of TWW's files at `files/res/Object/Bk.arc`. Next go to https://noclip.website/ and drag-and-drop the .arc file onto the website. It should display all of the 3D models in that archive on top of each other. You can open up the "Layers" menu on the left hand side and toggle off specific models if it's too confusing with them all overlapping. Alternatively, you can also download [GCFT](https://github.com/LagoLunatic/GCFT) (version 2.0.0 or higher) to view models if you prefer an offline program to a website. GCFT allows you to load not just models but also their animations, which may be helpful in determining the exact difference between states if the actor has multiple animations. Drag-and-drop the .arc file onto GCFT to open it, then right click on one of the BDL models and select "Open J3D" to view the model. You can also go back to the RARC tab and right click a BCK animation and select "Load J3D Animation" to view that animation on the model you have loaded.