the code now support multiple Pack, allow a better image generator (used for the bootscreen image in MKWF), customisable directory for the generated ct_icons, patched bmg, directory with all the icons, directory with lecode.
Before Width: | Height: | Size: 192 B After Width: | Height: | Size: 192 B |
BIN
Pack/MKWFaraphel/file/specific/SuperMario256.ttf
Normal file
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 322 B After Width: | Height: | Size: 322 B |
Before Width: | Height: | Size: 337 B After Width: | Height: | Size: 337 B |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 293 B After Width: | Height: | Size: 293 B |
Before Width: | Height: | Size: 271 B After Width: | Height: | Size: 271 B |
|
@ -60,40 +60,101 @@
|
||||||
"Wi-Fi": "{ONLINE_SERVICE}",
|
"Wi-Fi": "{ONLINE_SERVICE}",
|
||||||
"インターネット": "{ONLINE_SERVICE}",
|
"インターネット": "{ONLINE_SERVICE}",
|
||||||
|
|
||||||
"Menu principal": "{MOD_NICKNAME} v{MOD_VERSION}{MOD_CUSTOMIZED}",
|
"Menu principal": "{MOD_NICKNAME} v{MOD_VERSION} {MOD_CUSTOMIZED}",
|
||||||
"Menú principal": "{MOD_NICKNAME} v{MOD_VERSION}{MOD_CUSTOMIZED}",
|
"Menú principal": "{MOD_NICKNAME} v{MOD_VERSION} {MOD_CUSTOMIZED}",
|
||||||
"Main Menu": "{MOD_NICKNAME} v{MOD_VERSION}{MOD_CUSTOMIZED}",
|
"Main Menu": "{MOD_NICKNAME} v{MOD_VERSION} {MOD_CUSTOMIZED}",
|
||||||
"トップメニュー": "{MOD_NICKNAME} v{MOD_VERSION}{MOD_CUSTOMIZED}",
|
"トップメニュー": "{MOD_NICKNAME} v{MOD_VERSION} {MOD_CUSTOMIZED}",
|
||||||
|
|
||||||
"Mario Kart Wii": "{MOD_NICKNAME} v{MOD_VERSION}{MOD_CUSTOMIZED}"
|
"Mario Kart Wii": "{MOD_NICKNAME} v{MOD_VERSION} {MOD_CUSTOMIZED}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
|
"img_generator": {
|
||||||
|
"/generated/strapA_16_9_832x456de.png": {
|
||||||
|
"width": 832,
|
||||||
|
"height": 456,
|
||||||
|
"format": "RGB",
|
||||||
|
"color": [0, 0, 0],
|
||||||
|
"layers": [
|
||||||
|
{"type": "color", "color": [0, 0, 0], "x_start": 0.2, "y_start": 0.2, "x_end": 0.8, "y_end": 0.8},
|
||||||
|
{"type": "image", "path": "/img_desc/illustration.png", "x_start": 0.2, "y_start": 0.2, "x_end": 0.8, "y_end": 0.8},
|
||||||
|
{"type": "text", "x": 0.2, "y": 0.2, "text": "test", "text_size": 0.1, "color": [255, 255, 255], "font": "/specific/SuperMario256.ttf"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"/generated/strapA_608x456de.png": {
|
||||||
|
"width": 608, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
|
},
|
||||||
|
|
||||||
"img": {
|
"/generated/strapA_16_9_832x456fr.png": {
|
||||||
"tt_hatena_64x64.tpl.png": "TPL.RGB5A3",
|
"width": 832, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
"tt_obi_bottom_curve_000.tpl.png": "TPL.RGB5A3",
|
},
|
||||||
"tt_obi_bottom_left_000.tpl.png": "TPL.RGB5A3",
|
"/generated/strapA_608x456fr.png": {
|
||||||
"tt_obi_bottom_right_000.tpl.png": "TPL.RGB5A3",
|
"width": 608, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
"tt_obi_check_000.tpl.png": "TPL.RGB5A3",
|
},
|
||||||
"tt_obi_top_curve_000.tpl.png": "TPL.RGB5A3",
|
|
||||||
"tt_obi_top_left_000.tpl.png": "TPL.RGB5A3",
|
"/generated/strapA_16_9_832x456en.png": {
|
||||||
"tt_obi_top_right_000.tpl.png": "TPL.RGB5A3",
|
"width": 832, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
"strapA_16_9_832x456de.png": "TEX.RGB565",
|
},
|
||||||
"strapA_16_9_832x456en.png": "TEX.RGB565",
|
"/generated/strapA_608x456en.png": {
|
||||||
"strapA_16_9_832x456es.png": "TEX.RGB565",
|
"width": 608, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
"strapA_16_9_832x456fr.png": "TEX.RGB565",
|
},
|
||||||
"strapA_16_9_832x456ge.png": "TEX.RGB565",
|
|
||||||
"strapA_16_9_832x456it.png": "TEX.RGB565",
|
"/generated/strapA_16_9_832x456ge.png": {
|
||||||
"strapA_608x456de.png": "TEX.RGB565",
|
"width": 832, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
"strapA_608x456en.png": "TEX.RGB565",
|
},
|
||||||
"strapA_608x456es.png": "TEX.RGB565",
|
"/generated/strapA_608x456ge.png": {
|
||||||
"strapA_608x456fr.png": "TEX.RGB565",
|
"width": 608, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
"strapA_608x456ge.png": "TEX.RGB565",
|
},
|
||||||
"strapA_608x456it.png": "TEX.RGB565",
|
|
||||||
"savebanner.tpl.png": "TPL.RGB565",
|
"/generated/strapA_16_9_832x456it.png": {
|
||||||
"ct_icons.tpl.png": "TPL.CMPR"
|
"width": 832, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
|
},
|
||||||
|
"/generated/strapA_608x456it.png": {
|
||||||
|
"width": 608, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
|
},
|
||||||
|
|
||||||
|
"/generated/strapA_16_9_832x456es.png": {
|
||||||
|
"width": 832, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
|
},
|
||||||
|
"/generated/strapA_608x456es.png": {
|
||||||
|
"width": 608, "height": 456, "layers": [{"type": "image", "path": "/generated/strapA_16_9_832x456de.png"}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"img_encode": {
|
||||||
|
"/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"},
|
||||||
|
"/specific/tt_obi_bottom_right_000.tpl.png": {"format": "TPL.RGB5A3", "dest": "/generated/%N"},
|
||||||
|
"/specific/tt_obi_check_000.tpl.png": {"format": "TPL.RGB5A3", "dest": "/generated/%N"},
|
||||||
|
"/specific/tt_obi_top_curve_000.tpl.png": {"format": "TPL.RGB5A3", "dest": "/generated/%N"},
|
||||||
|
"/specific/tt_obi_top_left_000.tpl.png": {"format": "TPL.RGB5A3", "dest": "/generated/%N"},
|
||||||
|
"/specific/tt_obi_top_right_000.tpl.png": {"format": "TPL.RGB5A3", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_16_9_832x456de.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_16_9_832x456en.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_16_9_832x456es.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_16_9_832x456fr.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_16_9_832x456ge.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_16_9_832x456it.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_608x456de.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_608x456en.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_608x456es.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_608x456fr.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_608x456ge.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/strapA_608x456it.png": {"format": "TEX.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/specific/savebanner.tpl.png": {"format": "TPL.RGB565", "dest": "/generated/%N"},
|
||||||
|
"/generated/ct_icons.tpl.png": {"format": "TPL.CMPR", "dest": "/generated/%N"}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
"placement": {
|
||||||
|
"ct_icons": "/generated/ct_icons.tpl.png",
|
||||||
|
"bmg_patch_dir": "/generated/",
|
||||||
|
"cup_icon_dir": "/cup_icon/",
|
||||||
|
"lecode_bin_dir": "/essentials/",
|
||||||
|
"lpar_dir": "/essentials/"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,131 +1,131 @@
|
||||||
{
|
{
|
||||||
"Scene/UI/*[!_]?.szs": {
|
"Scene/UI/*[!_]?.szs": {
|
||||||
"/button/blyt/": "cup_icon_64x64_common.brlyt",
|
"/button/blyt/": "/essentials/cup_icon_64x64_common.brlyt",
|
||||||
"/button/ctrl/": [
|
"/button/ctrl/": [
|
||||||
"Back.brctr",
|
"/essentials/Back.brctr",
|
||||||
"CupSelectCup.brctr"
|
"/essentials/CupSelectCup.brctr"
|
||||||
],
|
],
|
||||||
"/control/blyt/": "cup_icon_64x64_common.brlyt",
|
"/control/blyt/": "/essentials/cup_icon_64x64_common.brlyt",
|
||||||
"/control/ctrl/": "CourseSelectCup.brctr",
|
"/control/ctrl/": "/essentials/CourseSelectCup.brctr",
|
||||||
"/demo/blyt/": "course_name.brlyt",
|
"/demo/blyt/": "/essentials/course_name.brlyt",
|
||||||
"/demo/timg/": "tt_hatena_64x64.tpl",
|
"/demo/timg/": "/generated/tt_hatena_64x64.tpl",
|
||||||
|
|
||||||
"/bg/timg/": [
|
"/bg/timg/": [
|
||||||
"tt_obi_bottom_curve_000.tpl",
|
"/generated/tt_obi_bottom_curve_000.tpl",
|
||||||
"tt_obi_bottom_left_000.tpl",
|
"/generated/tt_obi_bottom_left_000.tpl",
|
||||||
"tt_obi_bottom_right_000.tpl",
|
"/generated/tt_obi_bottom_right_000.tpl",
|
||||||
"tt_obi_check_000.tpl",
|
"/generated/tt_obi_check_000.tpl",
|
||||||
"tt_obi_top_curve_000.tpl",
|
"/generated/tt_obi_top_curve_000.tpl",
|
||||||
"tt_obi_top_left_000.tpl",
|
"/generated/tt_obi_top_left_000.tpl",
|
||||||
"tt_obi_top_right_000.tpl"
|
"/generated/tt_obi_top_right_000.tpl"
|
||||||
],
|
],
|
||||||
"/button/timg/": "ct_icons.tpl",
|
"/button/timg/": "/generated/ct_icons.tpl",
|
||||||
"/control/timg/": "ct_icons.tpl"
|
"/control/timg/": "/generated/ct_icons.tpl"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
"Scene/UI/*_E.szs": {"/message/Common.bmg": "Common_E.bmg", "/message/Menu.bmg": "Menu_E.bmg"},
|
"Scene/UI/*_E.szs": {"/message/Common.bmg": "/generated/Common_E.bmg", "/message/Menu.bmg": "/generated/Menu_E.bmg"},
|
||||||
"Scene/UI/*_K.szs": {"/message/Common.bmg": "Common_K.bmg", "/message/Menu.bmg": "Menu_K.bmg"},
|
"Scene/UI/*_K.szs": {"/message/Common.bmg": "/generated/Common_K.bmg", "/message/Menu.bmg": "/generated/Menu_K.bmg"},
|
||||||
"Scene/UI/*_J.szs": {"/message/Common.bmg": "Common_J.bmg", "/message/Menu.bmg": "Menu_J.bmg"},
|
"Scene/UI/*_J.szs": {"/message/Common.bmg": "/generated/Common_J.bmg", "/message/Menu.bmg": "/generated/Menu_J.bmg"},
|
||||||
"Scene/UI/*_U.szs": {"/message/Common.bmg": "Common_U.bmg", "/message/Menu.bmg": "Menu_U.bmg"},
|
"Scene/UI/*_U.szs": {"/message/Common.bmg": "/generated/Common_U.bmg", "/message/Menu.bmg": "/generated/Menu_U.bmg"},
|
||||||
"Scene/UI/*_F.szs": {"/message/Common.bmg": "Common_F.bmg", "/message/Menu.bmg": "Menu_F.bmg"},
|
"Scene/UI/*_F.szs": {"/message/Common.bmg": "/generated/Common_F.bmg", "/message/Menu.bmg": "/generated/Menu_F.bmg"},
|
||||||
"Scene/UI/*_Q.szs": {"/message/Common.bmg": "Common_Q.bmg", "/message/Menu.bmg": "Menu_Q.bmg"},
|
"Scene/UI/*_Q.szs": {"/message/Common.bmg": "/generated/Common_Q.bmg", "/message/Menu.bmg": "/generated/Menu_Q.bmg"},
|
||||||
"Scene/UI/*_G.szs": {"/message/Common.bmg": "Common_G.bmg", "/message/Menu.bmg": "Menu_G.bmg"},
|
"Scene/UI/*_G.szs": {"/message/Common.bmg": "/generated/Common_G.bmg", "/message/Menu.bmg": "/generated/Menu_G.bmg"},
|
||||||
"Scene/UI/*_I.szs": {"/message/Common.bmg": "Common_I.bmg", "/message/Menu.bmg": "Menu_I.bmg"},
|
"Scene/UI/*_I.szs": {"/message/Common.bmg": "/generated/Common_I.bmg", "/message/Menu.bmg": "/generated/Menu_I.bmg"},
|
||||||
"Scene/UI/*_S.szs": {"/message/Common.bmg": "Common_S.bmg", "/message/Menu.bmg": "Menu_S.bmg"},
|
"Scene/UI/*_S.szs": {"/message/Common.bmg": "/generated/Common_S.bmg", "/message/Menu.bmg": "/generated/Menu_S.bmg"},
|
||||||
"Scene/UI/*_M.szs": {"/message/Common.bmg": "Common_M.bmg", "/message/Menu.bmg": "Menu_M.bmg"},
|
"Scene/UI/*_M.szs": {"/message/Common.bmg": "/generated/Common_M.bmg", "/message/Menu.bmg": "/generated/Menu_M.bmg"},
|
||||||
|
|
||||||
"Scene/UI/Race_E.szs": {"/message/Common.bmg": "Common_RE.bmg"},
|
"Scene/UI/Race_E.szs": {"/message/Common.bmg": "/generated/Common_RE.bmg"},
|
||||||
"Scene/UI/Race_K.szs": {"/message/Common.bmg": "Common_RK.bmg"},
|
"Scene/UI/Race_K.szs": {"/message/Common.bmg": "/generated/Common_RK.bmg"},
|
||||||
"Scene/UI/Race_J.szs": {"/message/Common.bmg": "Common_RJ.bmg"},
|
"Scene/UI/Race_J.szs": {"/message/Common.bmg": "/generated/Common_RJ.bmg"},
|
||||||
"Scene/UI/Race_U.szs": {"/message/Common.bmg": "Common_RU.bmg"},
|
"Scene/UI/Race_U.szs": {"/message/Common.bmg": "/generated/Common_RU.bmg"},
|
||||||
"Scene/UI/Race_F.szs": {"/message/Common.bmg": "Common_RF.bmg"},
|
"Scene/UI/Race_F.szs": {"/message/Common.bmg": "/generated/Common_RF.bmg"},
|
||||||
"Scene/UI/Race_Q.szs": {"/message/Common.bmg": "Common_RQ.bmg"},
|
"Scene/UI/Race_Q.szs": {"/message/Common.bmg": "/generated/Common_RQ.bmg"},
|
||||||
"Scene/UI/Race_G.szs": {"/message/Common.bmg": "Common_RG.bmg"},
|
"Scene/UI/Race_G.szs": {"/message/Common.bmg": "/generated/Common_RG.bmg"},
|
||||||
"Scene/UI/Race_I.szs": {"/message/Common.bmg": "Common_RI.bmg"},
|
"Scene/UI/Race_I.szs": {"/message/Common.bmg": "/generated/Common_RI.bmg"},
|
||||||
"Scene/UI/Race_S.szs": {"/message/Common.bmg": "Common_RS.bmg"},
|
"Scene/UI/Race_S.szs": {"/message/Common.bmg": "/generated/Common_RS.bmg"},
|
||||||
"Scene/UI/Race_M.szs": {"/message/Common.bmg": "Common_RM.bmg"},
|
"Scene/UI/Race_M.szs": {"/message/Common.bmg": "/generated/Common_RM.bmg"},
|
||||||
|
|
||||||
"Scene/UI/Font.szs": {"/": "kart_kanji_font.brfnt"},
|
"Scene/UI/Font.szs": {"/": "/specific/kart_kanji_font.brfnt"},
|
||||||
|
|
||||||
"Boot/Strap/eu/Dutch.szs": {
|
"Boot/Strap/eu/Dutch.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456de",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456de",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456de",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456de",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456de",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456de",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456de"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456de"
|
||||||
},
|
},
|
||||||
"Boot/Strap/eu/English.szs": {
|
"Boot/Strap/eu/English.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456en",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456en",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456en"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456en"
|
||||||
},
|
},
|
||||||
"Boot/Strap/us/English.szs": {
|
"Boot/Strap/us/English.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456en",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456en",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456en"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456en"
|
||||||
},
|
},
|
||||||
"Boot/Strap/jp/jp.szs": {
|
"Boot/Strap/jp/jp.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456en",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456en",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456en"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456en"
|
||||||
},
|
},
|
||||||
"Boot/Strap/kr/Korean.szs": {
|
"Boot/Strap/kr/Korean.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456en",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456en",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456en"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456en"
|
||||||
},
|
},
|
||||||
"Boot/Strap/ch/Chinese.szs": {
|
"Boot/Strap/ch/Chinese.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456en",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456en",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456en",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456en",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608cccx456en"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608cccx456en"
|
||||||
},
|
},
|
||||||
"Boot/Strap/eu/French.szs": {
|
"Boot/Strap/eu/French.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456fr",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456fr",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456fr",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456fr",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456fr",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456fr",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456fr"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456fr"
|
||||||
},
|
},
|
||||||
"Boot/Strap/us/French.szs": {
|
"Boot/Strap/us/French.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456fr",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456fr",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456fr",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456fr",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456fr",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456fr",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456fr"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456fr"
|
||||||
},
|
},
|
||||||
"Boot/Strap/eu/German.szs": {
|
"Boot/Strap/eu/German.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456ge",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456ge",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456ge",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456ge",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456ge",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456ge",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456ge"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456ge"
|
||||||
},
|
},
|
||||||
"Boot/Strap/eu/Italian.szs": {
|
"Boot/Strap/eu/Italian.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456it",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456it",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456it",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456it",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456it",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456it",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456it"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456it"
|
||||||
},
|
},
|
||||||
"Boot/Strap/eu/Spanish_EU.szs": {
|
"Boot/Strap/eu/Spanish_EU.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456es",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456es",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456es",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456es",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456es",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456es",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456es"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456es"
|
||||||
},
|
},
|
||||||
"Boot/Strap/eu/Spanish_US.szs": {
|
"Boot/Strap/eu/Spanish_US.szs": {
|
||||||
"/Textures(NW4R)/strapA_16_9_832x456": "strapA_16_9_832x456es",
|
"/Textures(NW4R)/strapA_16_9_832x456": "/generated/strapA_16_9_832x456es",
|
||||||
"/Textures(NW4R)/strapB_16_9_832x456": "strapA_16_9_832x456es",
|
"/Textures(NW4R)/strapB_16_9_832x456": "/generated/strapA_16_9_832x456es",
|
||||||
"/Textures(NW4R)/strapA_608x456": "strapA_608x456es",
|
"/Textures(NW4R)/strapA_608x456": "/generated/strapA_608x456es",
|
||||||
"/Textures(NW4R)/strapB_608x456": "strapA_608x456es"
|
"/Textures(NW4R)/strapB_608x456": "/generated/strapA_608x456es"
|
||||||
},
|
},
|
||||||
"Boot/": "savebanner.tpl",
|
"Boot/": "/generated/savebanner.tpl",
|
||||||
|
|
||||||
"thp/*/*.thp": "video.thp",
|
"thp/*/*.thp": "/essentials/video.thp",
|
||||||
|
|
||||||
"Race/Common.szs": {
|
"Race/Common.szs": {
|
||||||
"/": "itemBoxNiseRtpa.brres",
|
"/": "/specific/itemBoxNiseRtpa.brres",
|
||||||
"/Effect/": "RKRace.breff"
|
"/Effect/": "/specific/RKRace.breff"
|
||||||
}
|
}
|
||||||
}
|
}
|
2
setup.py
|
@ -31,7 +31,7 @@ include_files = [
|
||||||
("./file/lecode-JAP.bin", "./file/lecode-JAP.bin"),
|
("./file/lecode-JAP.bin", "./file/lecode-JAP.bin"),
|
||||||
("./file/lecode-KOR.bin", "./file/lecode-KOR.bin"),
|
("./file/lecode-KOR.bin", "./file/lecode-KOR.bin"),
|
||||||
("./file/itemBoxNiseRtpa.brres", "./file/itemBoxNiseRtpa.brres"),
|
("./file/itemBoxNiseRtpa.brres", "./file/itemBoxNiseRtpa.brres"),
|
||||||
("./file/lpar-default.txt", "./file/lpar-default.txt"),
|
("./file/lpar-normal.txt", "./file/lpar-normal.txt"),
|
||||||
("./file/RKRace.breff", "./file/RKRace.breff"),
|
("./file/RKRace.breff", "./file/RKRace.breff"),
|
||||||
|
|
||||||
("./file/tt_hatena_64x64.tpl.png", "./file/tt_hatena_64x64.tpl.png"),
|
("./file/tt_hatena_64x64.tpl.png", "./file/tt_hatena_64x64.tpl.png"),
|
||||||
|
|
|
@ -11,7 +11,8 @@ class CT_Config:
|
||||||
def __init__(self, version: str = None, name: str = None, nickname: str = None,
|
def __init__(self, version: str = None, name: str = None, nickname: str = None,
|
||||||
game_variant: str = "01", gui=None, region: int = None, cheat_region: int = None,
|
game_variant: str = "01", gui=None, region: int = None, cheat_region: int = None,
|
||||||
tags_color: dict = {}, prefix_list: list = [], suffix_list: list = [],
|
tags_color: dict = {}, prefix_list: list = [], suffix_list: list = [],
|
||||||
tag_retro: str = "Retro", default_track: Track = None, pack_path: str = ""):
|
tag_retro: str = "Retro", default_track: Track = None, pack_path: str = "",
|
||||||
|
file_process: dict = None, file_structure: dict = None):
|
||||||
|
|
||||||
self.version = version
|
self.version = version
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -33,6 +34,9 @@ class CT_Config:
|
||||||
|
|
||||||
self.pack_path = pack_path
|
self.pack_path = pack_path
|
||||||
|
|
||||||
|
self.file_process = file_process
|
||||||
|
self.file_structure = file_structure
|
||||||
|
|
||||||
def add_ordered_cup(self, cup: Cup) -> None:
|
def add_ordered_cup(self, cup: Cup) -> None:
|
||||||
"""
|
"""
|
||||||
add a cup to the config
|
add a cup to the config
|
||||||
|
@ -95,14 +99,17 @@ class CT_Config:
|
||||||
ctfile.write(cup.get_ctfile_cup(race=False, **kwargs))
|
ctfile.write(cup.get_ctfile_cup(race=False, **kwargs))
|
||||||
rctfile.write(cup.get_ctfile_cup(race=True, **kwargs))
|
rctfile.write(cup.get_ctfile_cup(race=True, **kwargs))
|
||||||
|
|
||||||
def get_cup_icon(self, cup_id: [str, int], font_path: str = "./assets/SuperMario256.ttf",
|
def get_cup_icon(self, cup_id: [str, int], font_path: str = "./assets/SuperMario256.ttf") -> Image:
|
||||||
cup_icon_dir: str = "./file/cup_icon") -> Image:
|
|
||||||
"""
|
"""
|
||||||
:param cup_id: id of the cup
|
:param cup_id: id of the cup
|
||||||
:param cup_icon_dir: directory to cup icon
|
|
||||||
:param font_path: path to the font used to generate icon
|
:param font_path: path to the font used to generate icon
|
||||||
:return: cup icon
|
:return: cup icon
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
dir = self.file_process['placement'].get('cup_icon_dir')
|
||||||
|
if not dir: dir = "/ct_icons/"
|
||||||
|
cup_icon_dir = f"{self.pack_path}/file/{dir}/"
|
||||||
|
|
||||||
if os.path.exists(f"{cup_icon_dir}/{cup_id}.png"):
|
if os.path.exists(f"{cup_icon_dir}/{cup_id}.png"):
|
||||||
cup_icon = Image.open(f"{cup_icon_dir}/{cup_id}.png").resize((128, 128))
|
cup_icon = Image.open(f"{cup_icon_dir}/{cup_id}.png").resize((128, 128))
|
||||||
|
|
||||||
|
@ -132,7 +139,7 @@ class CT_Config:
|
||||||
|
|
||||||
for index, cup_id in enumerate(icon_files):
|
for index, cup_id in enumerate(icon_files):
|
||||||
# index is a number, id can be string or number ("left", 0, 12, ...)
|
# index is a number, id can be string or number ("left", 0, 12, ...)
|
||||||
cup_icon = self.get_cup_icon(cup_id, cup_icon_dir=self.pack_path+"/file/cup_icon/")
|
cup_icon = self.get_cup_icon(cup_id)
|
||||||
ct_icon.paste(cup_icon, (0, index * CT_ICON_WIDTH))
|
ct_icon.paste(cup_icon, (0, index * CT_ICON_WIDTH))
|
||||||
|
|
||||||
return ct_icon
|
return ct_icon
|
||||||
|
@ -185,6 +192,11 @@ class CT_Config:
|
||||||
for param in ["region", "cheat_region", "tags_color", "prefix_list", "suffix_list", "tag_retro"]:
|
for param in ["region", "cheat_region", "tags_color", "prefix_list", "suffix_list", "tag_retro"]:
|
||||||
setattr(self, param, ctconfig_json.get(param))
|
setattr(self, param, ctconfig_json.get(param))
|
||||||
|
|
||||||
|
with open(f"{pack_path}/file_process.json", encoding="utf8") as fp_file:
|
||||||
|
self.file_process = json.load(fp_file)
|
||||||
|
with open(f"{pack_path}/file_structure.json", encoding="utf8") as fs_file:
|
||||||
|
self.file_structure = json.load(fs_file)
|
||||||
|
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def search_tracks(self, values_list=False, not_value=False, only_unordered_track=False, **kwargs) -> list:
|
def search_tracks(self, values_list=False, not_value=False, only_unordered_track=False, **kwargs) -> list:
|
||||||
|
|
199
source/Game.py
|
@ -1,5 +1,5 @@
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
from PIL import Image
|
from PIL import Image, ImageDraw, ImageFont
|
||||||
import shutil
|
import shutil
|
||||||
import glob
|
import glob
|
||||||
import json
|
import json
|
||||||
|
@ -24,11 +24,6 @@ class InvalidFormat(Exception):
|
||||||
super().__init__("This game format is not supported !")
|
super().__init__("This game format is not supported !")
|
||||||
|
|
||||||
|
|
||||||
class TooMuchDownloadFailed(Exception):
|
|
||||||
def __init__(self):
|
|
||||||
super().__init__("Too much download failed !")
|
|
||||||
|
|
||||||
|
|
||||||
class TooMuchSha1CheckFailed(Exception):
|
class TooMuchSha1CheckFailed(Exception):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("Too much sha1 check failed !")
|
super().__init__("Too much sha1 check failed !")
|
||||||
|
@ -36,7 +31,7 @@ class TooMuchSha1CheckFailed(Exception):
|
||||||
|
|
||||||
class CantConvertTrack(Exception):
|
class CantConvertTrack(Exception):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("Can't convert track, check if download are enabled.")
|
super().__init__("Can't convert track.")
|
||||||
|
|
||||||
|
|
||||||
class NoGui:
|
class NoGui:
|
||||||
|
@ -144,13 +139,13 @@ class Game:
|
||||||
if glob.glob(self.path + "/files/rel/lecode-???.bin"): # if a LECODE file is already here
|
if glob.glob(self.path + "/files/rel/lecode-???.bin"): # if a LECODE file is already here
|
||||||
raise RomAlreadyPatched() # warning already patched
|
raise RomAlreadyPatched() # warning already patched
|
||||||
|
|
||||||
with open(self.path + "/setup.txt") as f:
|
if os.path.exists(self.path + "/setup.txt"):
|
||||||
setup = f.read()
|
with open(self.path + "/setup.txt") as f: setup = f.read()
|
||||||
setup = setup[setup.find("!part-id = ") + len("!part-id = "):]
|
setup = setup[setup.find("!part-id = ") + len("!part-id = "):]
|
||||||
self.game_ID = setup[:setup.find("\n")]
|
self.game_ID = setup[:setup.find("\n")]
|
||||||
|
|
||||||
self.region_ID = self.game_ID[3]
|
self.region_ID = self.game_ID[3]
|
||||||
self.region = region_id_to_name[self.region_ID] if self.region_ID in region_id_to_name else self.region
|
self.region = region_id_to_name[self.region_ID] if self.region_ID in region_id_to_name else self.region
|
||||||
|
|
||||||
def count_patch_subfile_operation(self) -> int:
|
def count_patch_subfile_operation(self) -> int:
|
||||||
"""
|
"""
|
||||||
|
@ -205,22 +200,22 @@ class Game:
|
||||||
self.gui.progress(statut=self.gui.translate("Editing", "\n", get_nodir(path)), add=1)
|
self.gui.progress(statut=self.gui.translate("Editing", "\n", get_nodir(path)), add=1)
|
||||||
extension = get_extension(path)
|
extension = get_extension(path)
|
||||||
|
|
||||||
|
source_file = f"{self.ctconfig.pack_path}/file/{file}"
|
||||||
|
dest_file = path
|
||||||
|
|
||||||
if extension == "szs":
|
if extension == "szs":
|
||||||
if not (os.path.realpath(path) in extracted_file):
|
if os.path.realpath(path) not in extracted_file:
|
||||||
szs.extract(file=path)
|
szs.extract(file=path)
|
||||||
extracted_file.append(os.path.realpath(path))
|
extracted_file.append(os.path.realpath(path))
|
||||||
|
|
||||||
szs_extract_path = path + ".d"
|
szs_extract_path = path + ".d"
|
||||||
if os.path.exists(szs_extract_path + subpath):
|
if os.path.exists(szs_extract_path + subpath):
|
||||||
if subpath[-1] == "/":
|
dest_file = szs_extract_path + subpath
|
||||||
shutil.copyfile(f"{self.ctconfig.pack_path}/file/{file}", szs_extract_path + subpath + file)
|
if subpath[-1] == "/": dest_file += get_nodir(file)
|
||||||
else:
|
|
||||||
shutil.copyfile(f"{self.ctconfig.pack_path}/file/{file}", szs_extract_path + subpath)
|
|
||||||
|
|
||||||
elif path[-1] == "/":
|
elif path[-1] == "/": dest_file += get_nodir(file)
|
||||||
shutil.copyfile(f"{self.ctconfig.pack_path}/file/{file}", path + file)
|
|
||||||
else:
|
shutil.copyfile(source_file, dest_file)
|
||||||
shutil.copyfile(f"{self.ctconfig.pack_path}/file/{file}", path)
|
|
||||||
|
|
||||||
for fp in fs:
|
for fp in fs:
|
||||||
for f in glob.glob(self.path + "/files/" + fp, recursive=True):
|
for f in glob.glob(self.path + "/files/" + fp, recursive=True):
|
||||||
|
@ -236,8 +231,7 @@ class Game:
|
||||||
for file in extracted_file:
|
for file in extracted_file:
|
||||||
self.gui.progress(statut=self.gui.translate("Recompilating", "\n", get_nodir(file)), add=1)
|
self.gui.progress(statut=self.gui.translate("Recompilating", "\n", get_nodir(file)), add=1)
|
||||||
szs.create(file=file)
|
szs.create(file=file)
|
||||||
if os.path.exists(file + ".d"):
|
shutil.rmtree(file + ".d", ignore_errors=True)
|
||||||
shutil.rmtree(file + ".d")
|
|
||||||
|
|
||||||
def install_copy_mystuff(self) -> None:
|
def install_copy_mystuff(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
@ -282,11 +276,19 @@ class Game:
|
||||||
"""
|
"""
|
||||||
self.gui.progress(statut=self.gui.translate("Patch lecode.bin"), add=1)
|
self.gui.progress(statut=self.gui.translate("Patch lecode.bin"), add=1)
|
||||||
|
|
||||||
lpar_path = f"{self.ctconfig.pack_path}/file/lpar-debug.txt" \
|
lpar_path = self.ctconfig.file_process["placement"].get("lpar_dir")
|
||||||
if self.gui.boolvar_use_debug_mode.get() else f"{self.ctconfig.pack_path}/file/lpar-default.txt"
|
if not lpar_path: f""
|
||||||
|
lpar_path = (
|
||||||
|
f"{self.ctconfig.pack_path}/file/{lpar_path}/"
|
||||||
|
f"lpar-{'debug' if self.gui.boolvar_use_debug_mode.get() else 'normal'}"
|
||||||
|
)
|
||||||
|
|
||||||
|
lecode_file = self.ctconfig.file_process["placement"].get("lecode_bin_dir")
|
||||||
|
if not lecode_file: lecode_file = ""
|
||||||
|
lecode_file = f"{self.ctconfig.pack_path}/file/{lecode_file}/lecode-{self.region}.bin"
|
||||||
|
|
||||||
lec.patch(
|
lec.patch(
|
||||||
lecode_file=f"{self.ctconfig.pack_path}/file/lecode-{self.region}.bin",
|
lecode_file=lecode_file,
|
||||||
dest_lecode_file=f"{self.path}/files/rel/lecode-{self.region}.bin",
|
dest_lecode_file=f"{self.path}/files/rel/lecode-{self.region}.bin",
|
||||||
game_track_path=f"{self.path}/files/Race/Course/",
|
game_track_path=f"{self.path}/files/Race/Course/",
|
||||||
copy_track_paths=[f"./file/Track/"],
|
copy_track_paths=[f"./file/Track/"],
|
||||||
|
@ -389,7 +391,7 @@ class Game:
|
||||||
"MOD_NAME": self.ctconfig.name,
|
"MOD_NAME": self.ctconfig.name,
|
||||||
"MOD_NICKNAME": self.ctconfig.nickname,
|
"MOD_NICKNAME": self.ctconfig.nickname,
|
||||||
"MOD_VERSION": self.ctconfig.version,
|
"MOD_VERSION": self.ctconfig.version,
|
||||||
"MOD_CUSTOMIZED": "" if self.gui.is_using_official_config() else " (custom)",
|
"MOD_CUSTOMIZED": "" if self.gui.is_using_official_config() else "(custom)",
|
||||||
"ONLINE_SERVICE": "Wiimmfi",
|
"ONLINE_SERVICE": "Wiimmfi",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,9 +464,17 @@ class Game:
|
||||||
bmg.encode(file)
|
bmg.encode(file)
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
|
|
||||||
save_bmg(f"{self.ctconfig.pack_path}/file/Menu_{bmglang}.txt", process_bmg_replacement(bmgmenu, bmglang))
|
bmg_dir = self.ctconfig.file_process["placement"].get("bmg_patch_dir")
|
||||||
save_bmg(f"{self.ctconfig.pack_path}/file/Common_{bmglang}.txt", process_bmg_replacement(bmgcommon, bmglang))
|
bmg_dir = f"{self.ctconfig.pack_path}/file/{bmg_dir if bmg_dir else ''}"
|
||||||
save_bmg(f"{self.ctconfig.pack_path}/file/Common_R{bmglang}.txt", process_bmg_replacement(rbmgcommon, bmglang))
|
os.makedirs(get_dir(bmg_dir), exist_ok=True)
|
||||||
|
|
||||||
|
save_bmg(f"{bmg_dir}/Menu_{bmglang}.txt", process_bmg_replacement(bmgmenu, bmglang))
|
||||||
|
save_bmg(f"{bmg_dir}/Common_{bmglang}.txt", process_bmg_replacement(bmgcommon, bmglang))
|
||||||
|
save_bmg(f"{bmg_dir}/Common_R{bmglang}.txt", process_bmg_replacement(rbmgcommon, bmglang))
|
||||||
|
|
||||||
|
def patch_all_bmg(self) -> None:
|
||||||
|
for file in glob.glob(f"{self.path}/files/Scene/UI/MenuSingle_?.szs"):
|
||||||
|
self.patch_bmg(file)
|
||||||
|
|
||||||
def patch_file(self):
|
def patch_file(self):
|
||||||
"""
|
"""
|
||||||
|
@ -473,9 +483,10 @@ class Game:
|
||||||
try:
|
try:
|
||||||
os.makedirs(f"{self.ctconfig.pack_path}/file/Track-WU8/", exist_ok=True)
|
os.makedirs(f"{self.ctconfig.pack_path}/file/Track-WU8/", exist_ok=True)
|
||||||
|
|
||||||
with open(f"{self.ctconfig.pack_path}/file_process.json", encoding="utf8") as fp_file:
|
max_step = len(self.ctconfig.file_process["img_encode"]) + \
|
||||||
file_process = json.load(fp_file)
|
len(self.ctconfig.all_tracks) + \
|
||||||
max_step = len(file_process["img"]) + len(self.ctconfig.all_tracks) + 3 + len("EGFIS")
|
3 + \
|
||||||
|
len("EGFIS")
|
||||||
|
|
||||||
self.gui.progress(show=True, indeter=False, statut=self.gui.translate("Converting files"),
|
self.gui.progress(show=True, indeter=False, statut=self.gui.translate("Converting files"),
|
||||||
max=max_step, step=0)
|
max=max_step, step=0)
|
||||||
|
@ -485,18 +496,10 @@ class Game:
|
||||||
sort_track_by=self.gui.stringvar_sort_track_by.get()
|
sort_track_by=self.gui.stringvar_sort_track_by.get()
|
||||||
)
|
)
|
||||||
|
|
||||||
self.gui.progress(statut=self.gui.translate("Creating ct_icon.png"), add=1)
|
self.generate_cticons()
|
||||||
ct_icon = self.ctconfig.get_cticon()
|
self.generate_all_image()
|
||||||
ct_icon.save(f"{self.ctconfig.pack_path}/file/ct_icons.tpl.png")
|
self.patch_image()
|
||||||
|
self.patch_all_bmg()
|
||||||
self.gui.progress(statut=self.gui.translate("Creating descriptive images"), add=1)
|
|
||||||
self.patch_img_desc(
|
|
||||||
img_desc_path=self.ctconfig.pack_path+"/file/img_desc/",
|
|
||||||
dest_dir=self.ctconfig.pack_path+"/file/"
|
|
||||||
)
|
|
||||||
self.patch_image(file_process["img"])
|
|
||||||
for file in glob.glob(self.path + "/files/Scene/UI/MenuSingle_?.szs"): self.patch_bmg(file)
|
|
||||||
# MenuSingle could be any other file, Common and Menu are all the same in all other files.
|
|
||||||
self.patch_autoadd()
|
self.patch_autoadd()
|
||||||
self.patch_tracks()
|
self.patch_tracks()
|
||||||
|
|
||||||
|
@ -507,45 +510,93 @@ class Game:
|
||||||
finally:
|
finally:
|
||||||
self.gui.progress(show=False)
|
self.gui.progress(show=False)
|
||||||
|
|
||||||
def patch_image(self, fp_img: dict) -> None:
|
def generate_cticons(self):
|
||||||
|
file = self.ctconfig.file_process["placement"].get("ct_icons")
|
||||||
|
if not file: file = "ct_icons.tpl.png"
|
||||||
|
file = f"{self.ctconfig.pack_path}/file/{file}"
|
||||||
|
|
||||||
|
os.makedirs(get_dir(file), exist_ok=True)
|
||||||
|
self.ctconfig.get_cticon().save(file)
|
||||||
|
|
||||||
|
def patch_image(self) -> None:
|
||||||
"""
|
"""
|
||||||
Convert .png image into the format wrote in convert_file
|
Convert .png image into the format wrote in convert_file
|
||||||
:param fp_img: file convert, a dictionnary indicating which format a file need to be converted
|
|
||||||
"""
|
"""
|
||||||
for i, file in enumerate(fp_img):
|
|
||||||
self.gui.progress(statut=self.gui.translate("Converting images") + f"\n({i + 1}/{len(fp_img)}) {file}",
|
image_amount = len(self.ctconfig.file_process["img_encode"])
|
||||||
add=1)
|
|
||||||
# TODO: IMG DESC AND THIS PART REALLY NEED A REWRITE !
|
for i, (file, data) in enumerate(self.ctconfig.file_process["img_encode"].items()):
|
||||||
|
self.gui.progress(
|
||||||
|
statut=self.gui.translate("Converting images") + f"\n({i + 1}/{image_amount}) {file}",
|
||||||
|
add=1
|
||||||
|
)
|
||||||
|
|
||||||
img.encode(
|
img.encode(
|
||||||
file=f"{self.ctconfig.pack_path}/file/{file}",
|
file=f"{self.ctconfig.pack_path}/file/{file}",
|
||||||
format=fp_img[file]
|
format=data["format"],
|
||||||
|
dest_file=f"{self.ctconfig.pack_path}/file/{data['dest']}" if "dest" in data else None
|
||||||
)
|
)
|
||||||
|
|
||||||
def patch_img_desc(self, img_desc_path: str = "./file/img_desc/", dest_dir: str = "./file/") -> None:
|
def generate_image(self, generator: dict) -> Image.Image:
|
||||||
"""
|
def get_layer_xy(layer: dict) -> tuple:
|
||||||
patch descriptive image used when the game boot
|
return (
|
||||||
:param img_desc_path: directory where original part of the image are stored
|
int(layer["x"] * generator["width"]) if "x" in layer else 0,
|
||||||
:param dest_dir: directory where patched image will be saved
|
int(layer["y"] * generator["height"]) if "y" in layer else 0,
|
||||||
"""
|
)
|
||||||
il = Image.open(img_desc_path + "/illustration.png")
|
|
||||||
il_16_9 = il.resize((832, 456))
|
|
||||||
il_4_3 = il.resize((608, 456))
|
|
||||||
|
|
||||||
for file_lang in glob.glob(img_desc_path + "/??.png"):
|
def get_layer_bbox(layer: dict) -> tuple:
|
||||||
img_lang = Image.open(file_lang)
|
return (
|
||||||
img_lang_16_9 = img_lang.resize((832, 456))
|
int(layer["x_start"] * generator["width"]) if "x_start" in layer else 0,
|
||||||
img_lang_4_3 = img_lang.resize((608, 456))
|
int(layer["y_start"] * generator["height"]) if "y_start" in layer else 0,
|
||||||
|
int(layer["x_end"] * generator["width"]) if "x_end" in layer else generator["width"],
|
||||||
|
int(layer["y_end"] * generator["height"]) if "y_end" in layer else generator["height"]
|
||||||
|
)
|
||||||
|
|
||||||
new_16_9 = Image.new("RGBA", (832, 456), (0, 0, 0, 255))
|
def get_layer_size(layer: dict) -> tuple:
|
||||||
new_16_9.paste(il_16_9, (0, 0), il_16_9)
|
x1, y1, x2, y2 = get_layer_bbox(layer)
|
||||||
new_16_9.paste(img_lang_16_9, (0, 0), img_lang_16_9)
|
return x2-x1, y2-y1
|
||||||
new_16_9.save(dest_dir + f"/strapA_16_9_832x456{get_filename(get_nodir(file_lang))}.png")
|
|
||||||
|
|
||||||
new_4_3 = Image.new("RGBA", (608, 456), (0, 0, 0, 255))
|
image = Image.new(
|
||||||
new_4_3.paste(il_4_3, (0, 0), il_4_3)
|
generator["format"] if "format" in generator else "RGB",
|
||||||
new_4_3.paste(img_lang_4_3, (0, 0), img_lang_4_3)
|
(generator["width"], generator["height"]),
|
||||||
new_4_3.save(dest_dir + f"/strapA_608x456{get_filename(get_nodir(file_lang))}.png")
|
tuple(generator["color"]) if "color" in generator else 0
|
||||||
|
)
|
||||||
|
draw = ImageDraw.Draw(image)
|
||||||
|
|
||||||
|
for layer in generator["layers"]:
|
||||||
|
if "type" not in layer: continue
|
||||||
|
if layer["type"] == "color":
|
||||||
|
draw.rectangle(
|
||||||
|
get_layer_bbox(layer),
|
||||||
|
tuple(layer["color"]) if "color" in layer else 0
|
||||||
|
)
|
||||||
|
if layer["type"] == "image":
|
||||||
|
layer_image = Image.open(f'{self.ctconfig.pack_path}/file/{layer["path"]}')
|
||||||
|
layer_image = layer_image.resize(get_layer_size(layer)).convert("RGBA")
|
||||||
|
image.paste(
|
||||||
|
layer_image,
|
||||||
|
box=get_layer_bbox(layer),
|
||||||
|
mask=layer_image
|
||||||
|
)
|
||||||
|
if layer["type"] == "text":
|
||||||
|
font = ImageFont.truetype(
|
||||||
|
font=f'{self.ctconfig.pack_path}/file/{layer["font"]}' if "font" in layer else None,
|
||||||
|
size=int(layer["text_size"] * generator["height"]) if "text_size" in layer else 10,
|
||||||
|
)
|
||||||
|
draw.text(
|
||||||
|
get_layer_xy(layer),
|
||||||
|
text=layer["text"] if "text" in layer else "<Missing text>",
|
||||||
|
fill=tuple(layer["color"]) if "color" in layer else 255,
|
||||||
|
font=font
|
||||||
|
)
|
||||||
|
|
||||||
|
return image
|
||||||
|
|
||||||
|
def generate_all_image(self) -> None:
|
||||||
|
for file, generator in self.ctconfig.file_process["img_generator"].items():
|
||||||
|
file = f"{self.ctconfig.pack_path}/file/{file}"
|
||||||
|
os.makedirs(get_dir(file), exist_ok=True)
|
||||||
|
self.generate_image(generator).save(file)
|
||||||
|
|
||||||
def patch_tracks(self) -> None:
|
def patch_tracks(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -13,5 +13,5 @@ def encode(file: str, format: str, dest_file: str = None) -> None:
|
||||||
:param format: new image format
|
:param format: new image format
|
||||||
"""
|
"""
|
||||||
cmd = [WIMGT_PATH, "ENCODE", file, "-x", format, "--overwrite"]
|
cmd = [WIMGT_PATH, "ENCODE", file, "-x", format, "--overwrite"]
|
||||||
if dest_file: cmd.extend(["--dest", dest_file])
|
if dest_file: cmd.extend(["--DEST", dest_file])
|
||||||
subprocess.run(cmd, creationflags=subprocess.CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE)
|
subprocess.run(cmd, creationflags=subprocess.CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE)
|
||||||
|
|
|
@ -11,7 +11,7 @@ def patch(lecode_file: str = f"./file/lecode-PAL.bin",
|
||||||
copy_track_paths: list = [],
|
copy_track_paths: list = [],
|
||||||
move_track_paths: list = [],
|
move_track_paths: list = [],
|
||||||
ctfile_path: str = "./file/CTFILE.txt",
|
ctfile_path: str = "./file/CTFILE.txt",
|
||||||
lpar_path: str = "./file/lpar-default.txt") -> None:
|
lpar_path: str = "./file/lpar-normal.txt") -> None:
|
||||||
"""
|
"""
|
||||||
Patch the file with a lecode file (this is the adding track part)
|
Patch the file with a lecode file (this is the adding track part)
|
||||||
:param lecode_file: path to the lecode file
|
:param lecode_file: path to the lecode file
|
||||||
|
|