Skip to content

Pack structure

Faraphel edited this page Mar 1, 2022 · 4 revisions

Using MKWF-Install for your own project

If you want to use this program for your own mod, there's no problem ! You can use this page to find how Pack work. This page can seem complex at first, don't hesitate to look at the structure used by MKWFaraphel to better understand or ask on the discord help.

CT_Config

./<PACK>/ct_config.json is one of the most important file in the project : it contains information about the mod version and all the tracks.

Track Structure

First, you need to know how track are represented :

TRACK_STRUCTURE = {
  # absolutely needed :
  "sha1": (string) track's sha1,

  # recommanded :
  "name": (string) [default: " "] name of the track, 
  "music": (string | int) [default: "T11"] track's music slot, 
  "special": (string | int) [default: "T11"] track's property slot,
  "author": (string | list of string) [default: "Nintendo"] track's author(s), 
  "tags": (list of string) tags list, can be anything ("Retro", "Wii U", "3DS", "Blue", "Purple", ...),

  # other : 
  "score": (int) [default: -1] track's score (used by MKWFaraphel),
  "warning": (int) [default: 0] track's warning level : 1 is low, 2 is high, 3 is dolphin only,
  "since_version": [string | int] since which version of the mod this track is available, 
  "track_version": [string] track's version,
  "weight": (int) [default : 1] track's weight (a track with a weight of 7 will be duplicated 7 times),
  "group": (list of TRACK_STRUCTURE) track group members : if this track is selected, one of its member will be used instead randomly

  # you can add your own parameter to a track, but it will be ignored.
}

Note : Music and special slot can be written in the "T11", "137" or "gPB" format

Example with "8-Bit Way" from MKWFaraphel
{
    "name":"8-Bit Way",
    "author":[
        "CarryOn",
        "Whipinsnapper"
    ],
    "special":"T11",
    "music":"T11",
    "score": 2,
    "since_version":"0.8",
    "sha1":"485ffdc676e646f70aa811a365be37617e2be567",
    "version":"v1",
    "family":8247,
    "tags":[
        "CT Jam"
    ]
}

Cup structure

Cup are represented like this :

CUP_STRUCTURE = {
  "name": (string) cup's name,
  "tracks": (list from 0 to 4 TRACK_STRUCTURE)
}

If the cup is not full (tracks list is less than 4 tracks) than it will be filled with the default track (see CT_Config structure)

Example with the cup "Switch1" from MKWFaraphel
{
    "name":"Switch1",
    "tracks":[
        {
            "name":"Excitebike adventure",
            "sha1":"e782de12471731e9bb155eea6872cd5b2303357d",
        },
        ...
    ]
}  

CT_Config structure

./<PACK>/ct_config.json structure is the following :

CTCONFIG_STRUCTURE = {
  "version": (string) mod's version,
  "name": (string) mod's name,
  "nickname": (string) [default: copy "name" value] mod's nickname,

  "game_variant": (string) [default: "01"] mario kart wii are identified by RMCxYY where x is the region and YY the "game variant",
  "region": (int) region used by your mod for wiimmfi,
  "cheat_region": (int) region used by your mod for wiimmfi if the track selection tools have been used to modify the installation,
  "prefix_list": (list of string) list of track tags that correspond to a prefix ("Wii U", "3DS", ...), 
  "suffix_list": (list of string) list of track tags that correspond to a suffix ("Boost", "Day", "Night", ...),
  "tags_color": (dict {string: string}) dict associating all tags to a color ({"Wii U": "green", "3DS": "red", ...}),
  "tag_retro": (string) [default: "Retro"] tag used to determinate if a track is new for the "random: new track" option in the random cup,
  "default_sort": (string) [default: "name"] track property that will be used to automatically sort the tracks,
  "add_original_track_prefix": (boolean) [default: true] should the original track get their respective prefix,
  "swap_original_order": (boolean) [default: true] this option make the original cup layout looks like the original mkwii one,
  "keep_original_track": (boolean) [default: true] should the original track be keeped or removed,
  "enable_random_cup": (boolean) [default: true] should the random track cup be enabled,

  "default_track": (TRACK_STRUCTURE) default track used to fill non-complete cup,
  "cup": (list of CUP_STRUCTURE) list of cups,
  "tracks_list": (list of TRACK_STRUCTURE) list of unorganized tracks,
  "arenas": (list of TRACK_STUCTURE) list of arenas
}

for every TRACK_STRUCTURE, you have to place the tracks file in the .wu8 format (same as .wbz but with .wu8 extension) and put them in the track folder (see Placement). For the program to find your track, you have to rename the file "track's sha1.wu8"


File Structure

./<PACK>/file_structure.json contains information about which "subfile" should be replaced in the game.

You can define which game file should be replaced by which pack's file. Syntax :

  • "game file path": "pack's file path" -> game file will be replaced by the pack file (relative to the ./<PACK>/file/ directory)
  • "game directory path": "pack's file path" -> the file in the game directory with the same name as the pack file will be replaced by it.
  • "game file path.szs": {"szs file path": "pack's file", ...} -> if the file have .szs extension, you can replace the "subfile" inside by the pack file.

example 1 :

{
  "Boot/": "savebanner.tpl",
  ...
}

This mean that GAME_DIRECTORY/files/Boot/savebanner.tpl will be replaced by ./<PACK>/file/savebanner.tpl

example 2 :

{
  "Race/Common.szs": {
    "/": "itemBoxNiseRtpa.brres",
    "/Effect/": "RKRace.breff"
  }
  ...
}

This mean that GAME_DIRECTORY/files/Race/Common.szs will be extracted, and inside it ./itemBoxNiseRtpa.brres will be replaced by ./<PACK>/file/itemBoxNiseRtpa.brres, and ./Effect/RKRace.breff will be replaced by ./<PACK>/file/RKRace.breff

example 3 :

{
  "thp/*/*.thp": "video.thp",
  ...
}

This is a python glob selector, * mean any "file / directory". This will replace all file in all directory in GAME_DIRECTORY/files/thp/ by the file ./<PACK>/file/video.thp

example 4 :

{
  "Scene/UI/*_E.szs": {
    "/message/Common.bmg": "Common_E.bmg", 
    "/message/Menu.bmg": "Menu_E.bmg"
  },
  ...
}

For every file that end with _E.szs in GAME_DIRECTORY/files/Scene/UI/, they will be extracted and then /message/Common.bmg will be replaced by ./<PACK>/file/Common_E.bmg, and /message/Menu.bmg by ./<PACK>/file/Menu_E.bmg.


cup_icons

If you want to have custom cup icon, put them in the cup's icons folder (see Placement).

  • The default cup use mushroom.png, shell.png, flower.png, banana.png, star.png, leaf.png, special.png and lightning.png
  • The random cup use random.png
  • For your own cup, use the name you gave them in their definition followed by .png

If a cup don't have icon (for example there is no Switch.png for the "Switch" cup), a default track icon will be generated with the font Super Mario 256


File Process

bmg extra processing

You can add / modify text by using file_process. A bmg modifier looks like this :

PROCESS_BMG_STRUCTURE = {
  "mode": ("overwrite_id" | "replace_text") choose the way the text will be replaced,
  "language": (list of string) [default: all language] letter of the language(s) that will receive(s) this modfication,
  "data": {
    # if "overwrite_id" : 
    "0x1053": "new text" # the text at the id "0x1053" will be replaced by "new text",

    # if "replace_text" : 
    "Main Menu": "test" # all "Main Menu" text will be replaced by "test"
    # Note : the installer offer some "macro" to autocatically replace some value that could change : 
    "Main Menu": "{MOD_NICKNAME} v{MOD_VERSION} {MOD_CUSTOMIZED}"
    # Here, all "Main Menu" text will be replaced by the value corresponding to the macro. For MKWFaraphel, this would result in
    # "MKWF vX.XX (custom)" if the track selection option have been used or "MKWF vX.XX" if not
  }
}

image generator

You can also generate some simple image with the images generator :

PROCESS_IMGLAYER_STRUCTURE = {
  "type": ("image" | "text" | "color") type of the layer
  
  # if type is color
  "color": (list of int) [default: (0, 0, 0)] color to fill,
  "x_start": (0 <= float =< 1) x1 of the rectangle to fill (in percent of the total x),
  "y_start": (0 <= float =< 1) y1 of the rectangle to fill (in percent of the total y),
  "x_end": (0 <= float =< 1) x2 of the rectangle to fill (in percent of the total x),
  "y_end": (0 <= float =< 1) y2 of the rectangle to fill (in percent of the total y),

  # if type is image
  "path": (string) path to the image (relative to `./<PACK>/file/`)
  "x_start": (0 <= float =< 1) x start for the image (in percent of the total x),
  "y_start": (0 <= float =< 1) y start for the image (in percent of the total y),
  "x_end": (0 <= float =< 1) x end for the image (in percent of the total x),
  "y_end": (0 <= float =< 1) y end for the image (in percent of the total y),
  
  # if type is text
  "font": (string) path to the font (relative to `./<PACK>/file/`),
  "text_size": (0 <= float =< 1) [default: 10] size of the font (in percent of the total y),
  "color": (list of int) [default: 255] text's color,
  "text": (string) [default: "<Missing text>"] text to show,
  "x": (0 <= float =< 1) x start for the text (in percent of the total x),
  "y": (0 <= float =< 1) y start for the text (in percent of the total y)
}

PROCESS_IMGGENERATOR_STRUCTURE = {
  "width": (int) image's width,
  "height": (int) image's height,
  "format": (string) [default: "RGB"] image's format,
  "color": (list of int) [default: (0, 0, 0)] image's default color,
  "layers": (list of PROCESS_IMGPLAYER_STRUCTURE) generator layer
}

Note : all image generator are associated to the result image path in the ./file_process.json file

Example with MKWFaraphel
"/generated/strapA_16_9_832x456ge.png": {
    "width": 832,
    "height": 456,
    "format": "RGB",
    "color": [0, 0, 0],
    "layers": [
        {"type": "image", "path": "/specific/bootscreen-base.png"},
        {"type": "text", "x": 0.01, "y": 0.00, "text": "Mario Kart Wii - Faraphel", "text_size": 0.04, "color": [100, 100, 100], "font": "/specific/CenturyGothicBold.ttf"}
    ]
}

image encoding

To make image edition easier, the installer allow you to automatically encode an image, it simply need to be declared by :

PROCESS_IMGENCODE_STRUCTURE = {
  "format": (string) encoding format for the image (TEX.RGB565, TPL.CMPR, ...)
  "dest": (string) output path for the image
}

(in file_process.json, a value corresponding to the file to convert is associated with this dictionnary)

Example with MKWFaraphel
{
    "/essentials/tt_hatena_64x64.tpl.png": {"format": "TPL.RGB5A3", "dest": "/generated/%N"},
    "/specific/tt_obi_bottom_curve_000.tpl.png": {"format": "TPL.RGB5A3", "dest": "/generated/%N"},
    "/specific/tt_obi_bottom_left_000.tpl.png": {"format": "TPL.RGB5A3", "dest": "/generated/%N"}
}

(the %N used in dest mean the same file name without the extension)

Placement

you can change the placement of important directory in this section :

"placement": {
    "ct_icons": (string) output of the generated ct_icons.tpl file,
    "bmg_patch_dir": (string) output of the generated bmg file,
    "cup_icon_dir": (string) directory containing all the seperated cup icons,
    "lecode_bin_dir": (string) directory containing the lecode-???.bin files,
    "lpar_dir": (string) directory containing the lpar definitions,
    "track_dir": (string) directory containing the wu8 tracks
  }
Example from MKWFaraphel
"placement": {
    "ct_icons": "/generated/ct_icons.tpl.png",
    "bmg_patch_dir": "/generated/",
    "cup_icon_dir": "/cup_icon/",
    "lecode_bin_dir": "/essentials/",
    "lpar_dir": "/essentials/",
    "track_dir": "/Track-WU8/"
}

file_process.json

Here how everything assemble in the ./<PACK>/file_process.json file :

{
  "bmg": (list of PROCESS_BMG_STRUCTURE),
  "img_generator": (dict of image path associated with PROCESS_IMGGENERATOR_STRUCTURE),
  "img_encode": (dict of image path associated with PROCESS_IMGENCODE_STRUCTURE),
  "placement": (dict of directory identifiant associated with their directory path)
}