mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-03 19:28:25 +02:00
added in_thread decorator, wszst module is now always used to edit file, ctconfig is now property of Game class and no more Gui
This commit is contained in:
parent
014e4fe259
commit
01ac79f623
7 changed files with 271 additions and 252 deletions
|
@ -79,8 +79,7 @@ class CT_Config:
|
||||||
"%LE-FLAGS=1\n"
|
"%LE-FLAGS=1\n"
|
||||||
"%WIIMM-CUP=1\n"
|
"%WIIMM-CUP=1\n"
|
||||||
"N N$SWAP | N$F_WII\n\n")
|
"N N$SWAP | N$F_WII\n\n")
|
||||||
ctfile.write(header);
|
ctfile.write(header); rctfile.write(header)
|
||||||
rctfile.write(header)
|
|
||||||
|
|
||||||
# generate cup for undefined track
|
# generate cup for undefined track
|
||||||
unordered_cups = []
|
unordered_cups = []
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from source.Track import Track
|
from .Track import Track
|
||||||
|
|
||||||
|
|
||||||
class Cup:
|
class Cup:
|
||||||
|
|
362
source/Game.py
362
source/Game.py
|
@ -1,16 +1,20 @@
|
||||||
from tkinter import messagebox
|
from tkinter import messagebox
|
||||||
from threading import Thread
|
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import subprocess
|
|
||||||
import shutil
|
import shutil
|
||||||
import glob
|
import glob
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from .CT_Config import CT_Config
|
||||||
from .definition import *
|
from .definition import *
|
||||||
from . import wszst
|
from . import wszst
|
||||||
|
|
||||||
|
|
||||||
|
class RomAlreadyPatched(Exception):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("ROM Already patched !")
|
||||||
|
|
||||||
|
|
||||||
class InvalidGamePath(Exception):
|
class InvalidGamePath(Exception):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__("This path is not valid !")
|
super().__init__("This path is not valid !")
|
||||||
|
@ -37,14 +41,20 @@ class CantConvertTrack(Exception):
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
def __init__(self, path: str, region_ID: str = "P", game_ID: str = "RMCP01", gui=None):
|
def __init__(self, path: str = "", region_ID: str = "P", game_ID: str = "RMCP01", gui=None):
|
||||||
if not os.path.exists(path): raise InvalidGamePath()
|
if not os.path.exists(path) and path: raise InvalidGamePath()
|
||||||
self.extension = get_extension(path).upper()
|
self.extension = None
|
||||||
self.path = path
|
self.path = path
|
||||||
|
self.set_path(path)
|
||||||
self.region = region_id_to_name[region_ID]
|
self.region = region_id_to_name[region_ID]
|
||||||
self.region_ID = region_ID
|
self.region_ID = region_ID
|
||||||
self.game_ID = game_ID
|
self.game_ID = game_ID
|
||||||
self.gui = gui
|
self.gui = gui
|
||||||
|
self.ctconfig = CT_Config()
|
||||||
|
|
||||||
|
def set_path(self, path):
|
||||||
|
self.extension = get_extension(path).upper()
|
||||||
|
self.path = path
|
||||||
|
|
||||||
def convert_to(self, format: str = "FST"):
|
def convert_to(self, format: str = "FST"):
|
||||||
"""
|
"""
|
||||||
|
@ -53,19 +63,12 @@ class Game:
|
||||||
"""
|
"""
|
||||||
if format in ["ISO", "WBFS", "CISO"]:
|
if format in ["ISO", "WBFS", "CISO"]:
|
||||||
path_game_format: str = os.path.realpath(self.path + "/../MKWFaraphel." + format.lower())
|
path_game_format: str = os.path.realpath(self.path + "/../MKWFaraphel." + format.lower())
|
||||||
subprocess.run(["./tools/wit/wit", "COPY", get_nodir(self.path), "--DEST",
|
wszst.wit_copy(self.path, path_game_format, format)
|
||||||
get_nodir(path_game_format), f"--{format.lower()}", "--overwrite"],
|
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(path_game_format),
|
|
||||||
check=True, stdout=subprocess.PIPE)
|
|
||||||
shutil.rmtree(self.path)
|
shutil.rmtree(self.path)
|
||||||
self.path = path_game_format
|
self.path = path_game_format
|
||||||
|
|
||||||
self.gui.progress(statut=self.gui.translate("Changing game's ID"), add=1)
|
self.gui.progress(statut=self.gui.translate("Changing game's ID"), add=1)
|
||||||
subprocess.run(["./tools/wit/wit", "EDIT", get_nodir(self.path), "--id",
|
wszst.edit(self.path, region_ID=self.region_ID, name=f"Mario Kart Wii Faraphel {self.ctconfig.version}")
|
||||||
f"RMC{self.region_ID}60", "--name",
|
|
||||||
f"Mario Kart Wii Faraphel {self.gui.ctconfig.version}", "--modify", "ALL"],
|
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path),
|
|
||||||
check=True, stdout=subprocess.PIPE)
|
|
||||||
|
|
||||||
def extract(self):
|
def extract(self):
|
||||||
if self.extension == "DOL":
|
if self.extension == "DOL":
|
||||||
|
@ -79,7 +82,7 @@ class Game:
|
||||||
if not (os.path.exists(path_dir)): break
|
if not (os.path.exists(path_dir)): break
|
||||||
directory_name, i = f"MKWiiFaraphel ({i})", i + 1
|
directory_name, i = f"MKWiiFaraphel ({i})", i + 1
|
||||||
|
|
||||||
wszst.extract(self.path, path_dir)
|
wszst.wit_extract(self.path, path_dir)
|
||||||
|
|
||||||
self.path = path_dir
|
self.path = path_dir
|
||||||
if os.path.exists(self.path + "/DATA"): self.path += "/DATA"
|
if os.path.exists(self.path + "/DATA"): self.path += "/DATA"
|
||||||
|
@ -89,7 +92,7 @@ class Game:
|
||||||
raise InvalidFormat()
|
raise InvalidFormat()
|
||||||
|
|
||||||
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 Warning("ROM Already patched") # warning already patched
|
raise RomAlreadyPatched() # warning already patched
|
||||||
|
|
||||||
with open(self.path + "/setup.txt") as f:
|
with open(self.path + "/setup.txt") as f:
|
||||||
setup = f.read()
|
setup = f.read()
|
||||||
|
@ -99,133 +102,118 @@ class Game:
|
||||||
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
|
||||||
|
|
||||||
|
@in_thread
|
||||||
def install_mod(self):
|
def install_mod(self):
|
||||||
def func():
|
try:
|
||||||
try:
|
with open("./fs.json") as f:
|
||||||
with open("./fs.json") as f:
|
fs = json.load(f)
|
||||||
fs = json.load(f)
|
|
||||||
|
|
||||||
# This part is used to estimate the max_step
|
# This part is used to estimate the max_step
|
||||||
extracted_file = []
|
extracted_file = []
|
||||||
max_step, step = 1, 0
|
max_step, step = 1, 0
|
||||||
|
|
||||||
def count_rf(path):
|
def count_rf(path):
|
||||||
nonlocal max_step
|
nonlocal max_step
|
||||||
max_step += 1
|
max_step += 1
|
||||||
if get_extension(path) == "szs":
|
if get_extension(path) == "szs":
|
||||||
if not (os.path.realpath(path) in extracted_file):
|
if not (os.path.realpath(path) in extracted_file):
|
||||||
extracted_file.append(os.path.realpath(path))
|
extracted_file.append(os.path.realpath(path))
|
||||||
max_step += 1
|
max_step += 1
|
||||||
|
|
||||||
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):
|
||||||
if type(fs[fp]) == str:
|
if type(fs[fp]) == str:
|
||||||
count_rf(path=f)
|
count_rf(path=f)
|
||||||
elif type(fs[fp]) == dict:
|
elif type(fs[fp]) == dict:
|
||||||
for nf in fs[fp]:
|
for nf in fs[fp]:
|
||||||
if type(fs[fp][nf]) == str:
|
if type(fs[fp][nf]) == str:
|
||||||
count_rf(path=f)
|
count_rf(path=f)
|
||||||
elif type(fs[fp][nf]) == list:
|
elif type(fs[fp][nf]) == list:
|
||||||
for ffp in fs[fp][nf]: count_rf(path=f)
|
for ffp in fs[fp][nf]: count_rf(path=f)
|
||||||
###
|
###
|
||||||
extracted_file = []
|
extracted_file = []
|
||||||
max_step += 4 # PATCH main.dol and PATCH lecode.bin, converting, changing ID
|
max_step += 4 # PATCH main.dol and PATCH lecode.bin, converting, changing ID
|
||||||
self.gui.progress(show=True, indeter=False, statut=self.gui.translate("Installing mod"), max=max_step,
|
self.gui.progress(show=True, indeter=False, statut=self.gui.translate("Installing mod"), max=max_step,
|
||||||
step=0)
|
step=0)
|
||||||
|
|
||||||
def replace_file(path, file, subpath="/"):
|
def replace_file(path, file, subpath="/"):
|
||||||
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)
|
||||||
|
|
||||||
if extension == "szs":
|
if extension == "szs":
|
||||||
if not (os.path.realpath(path) in extracted_file):
|
if not (os.path.realpath(path) in extracted_file):
|
||||||
subprocess.run(
|
wszst.szs_extract(path, get_nodir(path))
|
||||||
["./tools/szs/wszst", "EXTRACT", get_nodir(path), "-d", get_nodir(path) + ".d",
|
extracted_file.append(os.path.realpath(path))
|
||||||
"--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(path),
|
|
||||||
check=True, stdout=subprocess.PIPE)
|
|
||||||
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] == "/":
|
if subpath[-1] == "/":
|
||||||
filecopy(f"./file/{file}", szs_extract_path + subpath + file)
|
filecopy(f"./file/{file}", szs_extract_path + subpath + file)
|
||||||
else:
|
else:
|
||||||
filecopy(f"./file/{file}", szs_extract_path + subpath)
|
filecopy(f"./file/{file}", szs_extract_path + subpath)
|
||||||
|
|
||||||
elif path[-1] == "/":
|
elif path[-1] == "/":
|
||||||
filecopy(f"./file/{file}", path + file)
|
filecopy(f"./file/{file}", path + file)
|
||||||
else:
|
else:
|
||||||
filecopy(f"./file/{file}", path)
|
filecopy(f"./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):
|
||||||
if type(fs[fp]) == str:
|
if type(fs[fp]) == str:
|
||||||
replace_file(path=f, file=fs[fp])
|
replace_file(path=f, file=fs[fp])
|
||||||
elif type(fs[fp]) == dict:
|
elif type(fs[fp]) == dict:
|
||||||
for nf in fs[fp]:
|
for nf in fs[fp]:
|
||||||
if type(fs[fp][nf]) == str:
|
if type(fs[fp][nf]) == str:
|
||||||
replace_file(path=f, subpath=nf, file=fs[fp][nf])
|
replace_file(path=f, subpath=nf, file=fs[fp][nf])
|
||||||
elif type(fs[fp][nf]) == list:
|
elif type(fs[fp][nf]) == list:
|
||||||
for ffp in fs[fp][nf]: replace_file(path=f, subpath=nf, file=ffp)
|
for ffp in fs[fp][nf]: replace_file(path=f, subpath=nf, file=ffp)
|
||||||
|
|
||||||
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)
|
||||||
subprocess.run(["./tools/szs/wszst", "CREATE", get_nodir(file) + ".d", "-d", get_nodir(file),
|
wszst.create(file)
|
||||||
"--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
if os.path.exists(file + ".d"):
|
||||||
check=True, stdout=subprocess.PIPE)
|
shutil.rmtree(file + ".d")
|
||||||
if os.path.exists(file + ".d"): shutil.rmtree(file + ".d")
|
|
||||||
|
|
||||||
self.gui.progress(statut=self.gui.translate("Patch main.dol"), add=1)
|
self.gui.progress(statut=self.gui.translate("Patch main.dol"), add=1)
|
||||||
subprocess.run(["./tools/szs/wstrt", "patch", get_nodir(self.path) + "/sys/main.dol", "--clean-dol",
|
wszst.str_patch(self.path)
|
||||||
"--add-lecode"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path),
|
|
||||||
check=True, stdout=subprocess.PIPE)
|
|
||||||
|
|
||||||
self.gui.progress(statut=self.gui.translate("Patch lecode.bin"), add=1)
|
self.gui.progress(statut=self.gui.translate("Patch lecode.bin"), add=1)
|
||||||
|
|
||||||
shutil.copytree("./file/Track/", self.path + "/files/Race/Course/", dirs_exist_ok=True)
|
shutil.copytree("./file/Track/", self.path + "/files/Race/Course/", dirs_exist_ok=True)
|
||||||
if not (os.path.exists(self.path + "/tmp/")): os.makedirs(self.path + "/tmp/")
|
if not (os.path.exists(self.path + "/tmp/")): os.makedirs(self.path + "/tmp/")
|
||||||
filecopy("./file/CTFILE.txt", self.path + "/tmp/CTFILE.txt")
|
filecopy("./file/CTFILE.txt", self.path + "/tmp/CTFILE.txt")
|
||||||
filecopy("./file/lpar-default.txt", self.path + "/tmp/lpar-default.txt")
|
filecopy("./file/lpar-default.txt", self.path + "/tmp/lpar-default.txt")
|
||||||
filecopy(f"./file/lecode-{self.region}.bin", self.path + f"/tmp/lecode-{self.region}.bin")
|
filecopy(f"./file/lecode-{self.region}.bin", self.path + f"/tmp/lecode-{self.region}.bin")
|
||||||
|
|
||||||
subprocess.run(
|
wszst.lec_patch(
|
||||||
["./tools/szs/wlect", "patch", f"./tmp/lecode-{self.region}.bin", "-od",
|
self.path,
|
||||||
f"./files/rel/lecode-{self.region}.bin", "--track-dir", "./files/Race/Course/",
|
lecode_file=f"./tmp/lecode-{self.region}.bin",
|
||||||
"--move-tracks", "./files/Race/Course/", "--le-define", "./tmp/CTFILE.txt", "--lpar",
|
dest_lecode_file=f"./files/rel/lecode-{self.region}.bin",
|
||||||
"./tmp/lpar-default.txt", "--overwrite"],
|
)
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=self.path, check=True, stdout=subprocess.PIPE)
|
|
||||||
|
|
||||||
shutil.rmtree(self.path + "/tmp/")
|
shutil.rmtree(self.path + "/tmp/")
|
||||||
|
|
||||||
output_format = self.gui.stringvar_game_format.get()
|
output_format = self.gui.stringvar_game_format.get()
|
||||||
self.gui.progress(statut=self.gui.translate("Converting to", " ", output_format), add=1)
|
self.gui.progress(statut=self.gui.translate("Converting to", " ", output_format), add=1)
|
||||||
self.convert_to(output_format)
|
self.convert_to(output_format)
|
||||||
|
|
||||||
messagebox.showinfo(self.gui.translate("End"), self.gui.translate("The mod has been installed !"))
|
messagebox.showinfo(self.gui.translate("End"), self.gui.translate("The mod has been installed !"))
|
||||||
|
|
||||||
except:
|
except:
|
||||||
self.gui.log_error()
|
self.gui.log_error()
|
||||||
finally:
|
finally:
|
||||||
self.gui.progress(show=False)
|
self.gui.progress(show=False)
|
||||||
|
|
||||||
t = Thread(target=func)
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
return t
|
|
||||||
|
|
||||||
def patch_autoadd(self, auto_add_dir: str = "./file/auto-add"):
|
def patch_autoadd(self, auto_add_dir: str = "./file/auto-add"):
|
||||||
if os.path.exists(auto_add_dir): shutil.rmtree(auto_add_dir)
|
if os.path.exists(auto_add_dir): shutil.rmtree(auto_add_dir)
|
||||||
if not os.path.exists(self.path + "/tmp/"): os.makedirs(self.path + "/tmp/")
|
if not os.path.exists(self.path + "/tmp/"): os.makedirs(self.path + "/tmp/")
|
||||||
subprocess.run(["./tools/szs/wszst", "AUTOADD", get_nodir(self.path) + "/files/Race/Course/",
|
wszst.autoadd(self.path, get_nodir(self.path) + "/tmp/auto-add/")
|
||||||
"--DEST", get_nodir(self.path) + "/tmp/auto-add/"],
|
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path),
|
|
||||||
check=True, stdout=subprocess.PIPE)
|
|
||||||
shutil.move(self.path + "/tmp/auto-add/", auto_add_dir)
|
shutil.move(self.path + "/tmp/auto-add/", auto_add_dir)
|
||||||
shutil.rmtree(self.path + "/tmp/")
|
shutil.rmtree(self.path + "/tmp/")
|
||||||
|
|
||||||
def patch_bmg(self, gamefile: str): # gamefile est le fichier .szs trouvé dans le /files/Scene/UI/ du jeu
|
def patch_bmg(self, gamefile: str): # gamefile est le fichier .szs trouvé dans le /files/Scene/UI/ du jeu
|
||||||
NINTENDO_CWF_REPLACE = "Wiimmfi"
|
NINTENDO_CWF_REPLACE = "Wiimmfi"
|
||||||
MAINMENU_REPLACE = f"MKWFaraphel {self.gui.ctconfig.version}"
|
MAINMENU_REPLACE = f"MKWFaraphel {self.ctconfig.version}"
|
||||||
menu_replacement = {
|
menu_replacement = {
|
||||||
"CWF de Nintendo": NINTENDO_CWF_REPLACE,
|
"CWF de Nintendo": NINTENDO_CWF_REPLACE,
|
||||||
"Wi-Fi Nintendo": NINTENDO_CWF_REPLACE,
|
"Wi-Fi Nintendo": NINTENDO_CWF_REPLACE,
|
||||||
|
@ -245,18 +233,11 @@ class Game:
|
||||||
bmglang = gamefile[-len("E.txt"):-len(".txt")] # Langue du fichier
|
bmglang = gamefile[-len("E.txt"):-len(".txt")] # Langue du fichier
|
||||||
self.gui.progress(statut=self.gui.translate("Patching text", " ", bmglang), add=1)
|
self.gui.progress(statut=self.gui.translate("Patching text", " ", bmglang), add=1)
|
||||||
|
|
||||||
subprocess.run(["./tools/szs/wszst", "EXTRACT", get_nodir(gamefile), "-d", get_nodir(gamefile) + ".d",
|
wszst.szs_extract(gamefile, get_nodir(gamefile))
|
||||||
"--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(gamefile))
|
|
||||||
|
|
||||||
# Menu.bmg
|
bmgmenu = wszst.bmg_cat(gamefile, ".d/message/Menu.bmg") # Menu.bmg
|
||||||
bmgmenu = subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(gamefile) + ".d/message/Menu.bmg"],
|
bmgtracks = wszst.bmg_cat(gamefile, ".d/message/Common.bmg") # Common.bmg
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(gamefile),
|
|
||||||
check=True, stdout=subprocess.PIPE).stdout.decode()
|
|
||||||
|
|
||||||
# Common.bmg
|
|
||||||
bmgtracks = subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(gamefile) + ".d/message/Common.bmg"],
|
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(gamefile),
|
|
||||||
check=True, stdout=subprocess.PIPE).stdout.decode()
|
|
||||||
trackheader = "#--- standard track names"
|
trackheader = "#--- standard track names"
|
||||||
trackend = "2328"
|
trackend = "2328"
|
||||||
bmgtracks = bmgtracks[bmgtracks.find(trackheader) + len(trackheader):bmgtracks.find(trackend)]
|
bmgtracks = bmgtracks[bmgtracks.find(trackheader) + len(trackheader):bmgtracks.find(trackend)]
|
||||||
|
@ -290,14 +271,10 @@ class Game:
|
||||||
if not (os.path.exists("./file/tmp/")): os.makedirs("./file/tmp/")
|
if not (os.path.exists("./file/tmp/")): os.makedirs("./file/tmp/")
|
||||||
|
|
||||||
filecopy(gamefile + ".d/message/Common.bmg", "./file/tmp/Common.bmg")
|
filecopy(gamefile + ".d/message/Common.bmg", "./file/tmp/Common.bmg")
|
||||||
bmgcommon = subprocess.run(
|
bmgcommon = wszst.ctc_patch_bmg(ctfile="./file/CTFILE.txt",
|
||||||
["tools/szs/wctct", "bmg", "--le-code", "--long", "./file/CTFILE.txt", "--patch-bmg",
|
bmgs=["./file/tmp/Common.bmg", "./file/ExtraCommon.txt"])
|
||||||
"OVERWRITE=./file/tmp/Common.bmg", "--patch-bmg", "OVERWRITE=./file/ExtraCommon.txt"],
|
rbmgcommon = wszst.ctc_patch_bmg(ctfile="./file/RCTFILE.txt",
|
||||||
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
|
bmgs=["./file/tmp/Common.bmg", "./file/ExtraCommon.txt"])
|
||||||
rbmgcommon = subprocess.run(
|
|
||||||
["tools/szs/wctct", "bmg", "--le-code", "--long", "./file/RCTFILE.txt", "--patch-bmg",
|
|
||||||
"OVERWRITE=./file/tmp/Common.bmg", "--patch-bmg", "OVERWRITE=./file/ExtraCommon.txt"],
|
|
||||||
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
|
|
||||||
|
|
||||||
shutil.rmtree(gamefile + ".d")
|
shutil.rmtree(gamefile + ".d")
|
||||||
os.remove("./file/tmp/Common.bmg")
|
os.remove("./file/tmp/Common.bmg")
|
||||||
|
@ -308,59 +285,52 @@ class Game:
|
||||||
for text, colored_text in replacement_list.items(): bmgtext = bmgtext.replace(text, colored_text)
|
for text, colored_text in replacement_list.items(): bmgtext = bmgtext.replace(text, colored_text)
|
||||||
with open(file, "w", encoding="utf-8") as f:
|
with open(file, "w", encoding="utf-8") as f:
|
||||||
f.write(bmgtext)
|
f.write(bmgtext)
|
||||||
subprocess.run(["./tools/szs/wbmgt", "ENCODE", get_nodir(file), "--overwrite"],
|
wszst.bmg_encode(file)
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
|
||||||
os.remove(file)
|
os.remove(file)
|
||||||
|
|
||||||
finalise(f"./file/Menu_{bmglang}.txt", bmgmenu, menu_replacement)
|
finalise(f"./file/Menu_{bmglang}.txt", bmgmenu, menu_replacement)
|
||||||
finalise(f"./file/Common_{bmglang}.txt", bmgcommon)
|
finalise(f"./file/Common_{bmglang}.txt", bmgcommon)
|
||||||
finalise(f"./file/Common_R{bmglang}.txt", rbmgcommon)
|
finalise(f"./file/Common_R{bmglang}.txt", rbmgcommon)
|
||||||
|
|
||||||
|
@in_thread
|
||||||
def patch_file(self):
|
def patch_file(self):
|
||||||
def func():
|
try:
|
||||||
try:
|
if not (os.path.exists("./file/Track-WU8/")): os.makedirs("./file/Track-WU8/")
|
||||||
if not (os.path.exists("./file/Track-WU8/")): os.makedirs("./file/Track-WU8/")
|
with open("./convert_file.json") as f:
|
||||||
with open("./convert_file.json") as f:
|
fc = json.load(f)
|
||||||
fc = json.load(f)
|
max_step = len(fc["img"]) + len(self.ctconfig.all_tracks) + 3 + len("EGFIS")
|
||||||
max_step = len(fc["img"]) + len(self.gui.ctconfig.all_tracks) + 3 + len("EGFIS")
|
|
||||||
|
|
||||||
self.gui.progress(show=True, indeter=False, statut=self.gui.translate("Converting files"), max=max_step,
|
self.gui.progress(show=True, indeter=False, statut=self.gui.translate("Converting files"),
|
||||||
step=0)
|
max=max_step, step=0)
|
||||||
self.gui.progress(statut=self.gui.translate("Configurating LE-CODE"), add=1)
|
self.gui.progress(statut=self.gui.translate("Configurating LE-CODE"), add=1)
|
||||||
self.gui.ctconfig.create_ctfile()
|
self.ctconfig.create_ctfile()
|
||||||
|
|
||||||
self.gui.progress(statut=self.gui.translate("Creating ct_icon.png"), add=1)
|
self.gui.progress(statut=self.gui.translate("Creating ct_icon.png"), add=1)
|
||||||
ct_icon = self.gui.ctconfig.get_cticon()
|
ct_icon = self.ctconfig.get_cticon()
|
||||||
ct_icon.save("./file/ct_icons.tpl.png")
|
ct_icon.save("./file/ct_icons.tpl.png")
|
||||||
|
|
||||||
self.gui.progress(statut=self.gui.translate("Creating descriptive images"), add=1)
|
self.gui.progress(statut=self.gui.translate("Creating descriptive images"), add=1)
|
||||||
self.patch_img_desc()
|
self.patch_img_desc()
|
||||||
self.patch_image(fc)
|
self.patch_image(fc)
|
||||||
for file in glob.glob(self.path + "/files/Scene/UI/MenuSingle_?.szs"): self.patch_bmg(file)
|
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.
|
# MenuSingle could be any other file, Common and Menu are all the same in all other files.
|
||||||
self.patch_autoadd()
|
self.patch_autoadd()
|
||||||
if self.patch_tracks() != 0: return
|
if self.patch_tracks() != 0: return
|
||||||
|
|
||||||
self.gui.button_install_mod.grid(row=2, column=1, columnspan=2, sticky="NEWS")
|
self.gui.button_install_mod.grid(row=2, column=1, columnspan=2, sticky="NEWS")
|
||||||
self.gui.button_install_mod.config(
|
self.gui.button_install_mod.config(
|
||||||
text=self.gui.translate("Install mod", " (v", self.gui.ctconfig.version, ")"))
|
text=self.gui.translate("Install mod", " (v", self.ctconfig.version, ")"))
|
||||||
|
|
||||||
except:
|
except:
|
||||||
self.gui.log_error()
|
self.gui.log_error()
|
||||||
finally:
|
finally:
|
||||||
self.gui.progress(show=False)
|
self.gui.progress(show=False)
|
||||||
|
|
||||||
t = Thread(target=func)
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
return t
|
|
||||||
|
|
||||||
def patch_image(self, fc):
|
def patch_image(self, fc):
|
||||||
for i, file in enumerate(fc["img"]):
|
for i, file in enumerate(fc["img"]):
|
||||||
self.gui.progress(statut=self.gui.translate("Converting images") + f"\n({i + 1}/{len(fc['img'])}) {file}",
|
self.gui.progress(statut=self.gui.translate("Converting images") + f"\n({i + 1}/{len(fc['img'])}) {file}",
|
||||||
add=1)
|
add=1)
|
||||||
subprocess.run(["./tools/szs/wimgt", "ENCODE", "./file/" + file, "-x", fc["img"][file], "--overwrite"],
|
wszst.img_encode("./file/" + file, fc["img"][file])
|
||||||
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE)
|
|
||||||
|
|
||||||
def patch_img_desc(self, img_desc_path: str = "./file/img_desc", dest_dir: str = "./file"):
|
def patch_img_desc(self, img_desc_path: str = "./file/img_desc", dest_dir: str = "./file"):
|
||||||
il = Image.open(img_desc_path + "/illustration.png")
|
il = Image.open(img_desc_path + "/illustration.png")
|
||||||
|
@ -390,7 +360,7 @@ class Game:
|
||||||
def add_process(track):
|
def add_process(track):
|
||||||
nonlocal error_count, error_max, process_list
|
nonlocal error_count, error_max, process_list
|
||||||
track_file = track.get_track_name()
|
track_file = track.get_track_name()
|
||||||
total_track = len(self.gui.ctconfig.all_tracks)
|
total_track = len(self.ctconfig.all_tracks)
|
||||||
|
|
||||||
process_list[track_file] = None # Used for showing track in progress even if there's no process
|
process_list[track_file] = None # Used for showing track in progress even if there's no process
|
||||||
self.gui.progress(statut=self.gui.translate("Converting tracks", f"\n({i + 1}/{total_track})\n",
|
self.gui.progress(statut=self.gui.translate("Converting tracks", f"\n({i + 1}/{total_track})\n",
|
||||||
|
@ -407,15 +377,14 @@ class Game:
|
||||||
if download_returncode == -1: # can't download
|
if download_returncode == -1: # can't download
|
||||||
error_count += 1
|
error_count += 1
|
||||||
if error_count > error_max: # Too much track wasn't correctly converted
|
if error_count > error_max: # Too much track wasn't correctly converted
|
||||||
"""messagebox.showerror(
|
messagebox.showerror(
|
||||||
gui.translate("Error"),
|
self.gui.translate("Error"),
|
||||||
gui.translate("Too much tracks had a download issue."))
|
self.gui.translate("Too much tracks had a download issue."))
|
||||||
return -1"""
|
|
||||||
raise TooMuchDownloadFailed()
|
raise TooMuchDownloadFailed()
|
||||||
else:
|
else:
|
||||||
"""messagebox.showwarning(gui.translate("Warning"),
|
messagebox.showwarning(self.gui.translate("Warning"),
|
||||||
gui.translate("Can't download this track !",
|
self.gui.translate("Can't download this track !",
|
||||||
f" ({error_count} / {error_max})"))"""
|
f" ({error_count} / {error_max})"))
|
||||||
elif download_returncode == 2:
|
elif download_returncode == 2:
|
||||||
break # if download is disabled, do not check sha1
|
break # if download is disabled, do not check sha1
|
||||||
|
|
||||||
|
@ -424,22 +393,21 @@ class Game:
|
||||||
if not track.check_sha1(): # Check si le sha1 du fichier est le bon
|
if not track.check_sha1(): # Check si le sha1 du fichier est le bon
|
||||||
error_count += 1
|
error_count += 1
|
||||||
if error_count > error_max: # Too much track wasn't correctly converted
|
if error_count > error_max: # Too much track wasn't correctly converted
|
||||||
"""messagebox.showerror(
|
messagebox.showerror(
|
||||||
gui.translate("Error"),
|
self.gui.translate("Error"),
|
||||||
gui.translate("Too much tracks had an issue during sha1 check."))"""
|
self.gui.translate("Too much tracks had an issue during sha1 check."))
|
||||||
raise TooMuchSha1CheckFailed()
|
raise TooMuchSha1CheckFailed()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
if not (
|
if not (os.path.exists(track.file_szs)) or download_returncode == 3:
|
||||||
os.path.exists(
|
# returncode 3 is track has been updated
|
||||||
track.file_szs)) or download_returncode == 3: # returncode 3 is track has been updated
|
|
||||||
if os.path.exists(track.file_wu8):
|
if os.path.exists(track.file_wu8):
|
||||||
process_list[track_file] = track.convert_wu8_to_szs()
|
process_list[track_file] = track.convert_wu8_to_szs()
|
||||||
else:
|
else:
|
||||||
"""messagebox.showerror(gui.translate("Error"),
|
messagebox.showerror(self.gui.translate("Error"),
|
||||||
gui.translate("Can't convert track.\nEnable track download and retry."))"""
|
self.gui.translate("Can't convert track.\nEnable track download and retry."))
|
||||||
raise CantConvertTrack()
|
raise CantConvertTrack()
|
||||||
elif self.gui.boolvar_del_track_after_conv.get():
|
elif self.gui.boolvar_del_track_after_conv.get():
|
||||||
os.remove(track.file_wu8)
|
os.remove(track.file_wu8)
|
||||||
|
@ -459,28 +427,28 @@ class Game:
|
||||||
os.remove(track.file_szs)
|
os.remove(track.file_szs)
|
||||||
error_count += 1
|
error_count += 1
|
||||||
if error_count > error_max: # Too much track wasn't correctly converted
|
if error_count > error_max: # Too much track wasn't correctly converted
|
||||||
"""messagebox.showerror(
|
messagebox.showerror(
|
||||||
gui.translate("Error"),
|
self.gui.translate("Error"),
|
||||||
gui.translate("Too much track had a conversion issue."))"""
|
self.gui.translate("Too much track had a conversion issue."))
|
||||||
raise CantConvertTrack
|
raise CantConvertTrack()
|
||||||
else: # if the error max hasn't been reach
|
else: # if the error max hasn't been reach
|
||||||
"""messagebox.showwarning(
|
messagebox.showwarning(
|
||||||
gui.translate("Warning"),
|
self.gui.translate("Warning"),
|
||||||
gui.translate("The track", " ", track.file_wu8,
|
self.gui.translate("The track", " ", track.file_wu8,
|
||||||
"do not have been properly converted.",
|
"do not have been properly converted.",
|
||||||
f" ({error_count} / {error_max})"))"""
|
f" ({error_count} / {error_max})"))
|
||||||
else:
|
else:
|
||||||
if self.gui.boolvar_del_track_after_conv.get(): os.remove(track.file_wu8)
|
if self.gui.boolvar_del_track_after_conv.get(): os.remove(track.file_wu8)
|
||||||
else:
|
else:
|
||||||
process_list.pop(track_file)
|
process_list.pop(track_file)
|
||||||
if not (any(process_list.values())): return 1 # si il n'y a plus de processus
|
if not (any(process_list.values())): return 1 # if there is no more process
|
||||||
|
|
||||||
if len(process_list):
|
if len(process_list):
|
||||||
return 1
|
return 1
|
||||||
else:
|
else:
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
for i, track in enumerate(self.gui.ctconfig.all_tracks):
|
for i, track in enumerate(self.ctconfig.all_tracks):
|
||||||
while True:
|
while True:
|
||||||
if len(process_list) < max_process:
|
if len(process_list) < max_process:
|
||||||
returncode = add_process(track)
|
returncode = add_process(track)
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from tkinter import filedialog, ttk
|
from tkinter import filedialog, ttk
|
||||||
from tkinter import *
|
from tkinter import *
|
||||||
import zipfile
|
import subprocess
|
||||||
import traceback
|
import traceback
|
||||||
import requests
|
import requests
|
||||||
|
import zipfile
|
||||||
|
|
||||||
from source.CT_Config import CT_Config
|
|
||||||
from source.Option import Option
|
from source.Option import Option
|
||||||
from source.Game import *
|
from source.Game import *
|
||||||
|
|
||||||
|
@ -24,8 +24,8 @@ class Gui:
|
||||||
|
|
||||||
self.option = Option()
|
self.option = Option()
|
||||||
self.option.load_from_file("./option.json")
|
self.option.load_from_file("./option.json")
|
||||||
self.ctconfig = CT_Config()
|
self.game = Game(gui=self)
|
||||||
self.ctconfig.load_ctconfig_file("./ct_config.json")
|
self.game.ctconfig.load_ctconfig_file("./ct_config.json")
|
||||||
|
|
||||||
self.is_dev_version = False # Is this installer version a dev ?
|
self.is_dev_version = False # Is this installer version a dev ?
|
||||||
self.stringvar_language = StringVar(value=self.option.language)
|
self.stringvar_language = StringVar(value=self.option.language)
|
||||||
|
@ -70,7 +70,7 @@ class Gui:
|
||||||
self.menu_marktrackversion = Menu(self.menu_trackselection, tearoff=0)
|
self.menu_marktrackversion = Menu(self.menu_trackselection, tearoff=0)
|
||||||
self.menu_trackselection.add_cascade(label=self.translate("Mark all tracks from version"), menu=self.menu_marktrackversion)
|
self.menu_trackselection.add_cascade(label=self.translate("Mark all tracks from version"), menu=self.menu_marktrackversion)
|
||||||
self.menu_marktrackversion.add_radiobutton(label=self.translate("None"), variable=self.stringvar_mark_track_from_version, value="None")
|
self.menu_marktrackversion.add_radiobutton(label=self.translate("None"), variable=self.stringvar_mark_track_from_version, value="None")
|
||||||
for version in self.ctconfig.all_version:
|
for version in self.game.ctconfig.all_version:
|
||||||
self.menu_marktrackversion.add_radiobutton(label=f"v{version}", variable=self.stringvar_mark_track_from_version, value=version)
|
self.menu_marktrackversion.add_radiobutton(label=f"v{version}", variable=self.stringvar_mark_track_from_version, value=version)
|
||||||
|
|
||||||
self.menu_advanced = Menu(self.menu_bar, tearoff=0)
|
self.menu_advanced = Menu(self.menu_bar, tearoff=0)
|
||||||
|
@ -109,53 +109,48 @@ class Gui:
|
||||||
self.frame_game_path_action.grid(row=2, column=1, columnspan=2, sticky="NEWS")
|
self.frame_game_path_action.grid(row=2, column=1, columnspan=2, sticky="NEWS")
|
||||||
self.frame_game_path_action.columnconfigure(1, weight=1)
|
self.frame_game_path_action.columnconfigure(1, weight=1)
|
||||||
|
|
||||||
|
@in_thread
|
||||||
def use_path():
|
def use_path():
|
||||||
def func():
|
self.frame_action.grid_forget()
|
||||||
self.frame_action.grid_forget()
|
try:
|
||||||
try:
|
self.game.set_path(entry_game_path.get())
|
||||||
self.game = Game(path=entry_game_path.get(), gui=self)
|
self.progress(show=True, indeter=True, statut=self.translate("Extracting the game..."))
|
||||||
self.progress(show=True, indeter=True, statut=self.translate("Extracting the game..."))
|
self.game.extract()
|
||||||
self.game.extract()
|
self.frame_action.grid(row=3, column=1, sticky="NEWS")
|
||||||
self.frame_action.grid(row=3, column=1, sticky="NEWS")
|
except RomAlreadyPatched:
|
||||||
except InvalidGamePath:
|
messagebox.showerror(self.translate("Error"), self.translate("This game is already modded"))
|
||||||
messagebox.showerror(self.translate("Error"), self.translate("The file path in invalid"))
|
except InvalidGamePath:
|
||||||
except InvalidFormat:
|
messagebox.showerror(self.translate("Error"), self.translate("The file path in invalid"))
|
||||||
messagebox.showerror(self.translate("Error"), self.translate("This game's format is invalid"))
|
except InvalidFormat:
|
||||||
except:
|
messagebox.showerror(self.translate("Error"), self.translate("This game's format is invalid"))
|
||||||
self.log_error()
|
except:
|
||||||
finally:
|
self.log_error()
|
||||||
self.progress(show=False)
|
finally:
|
||||||
|
self.progress(show=False)
|
||||||
t = Thread(target=func)
|
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
return t
|
|
||||||
|
|
||||||
self.button_game_extract = Button(self.frame_game_path_action, text=self.translate("Extract file"),
|
self.button_game_extract = Button(self.frame_game_path_action, text=self.translate("Extract file"),
|
||||||
relief=RIDGE, command=use_path)
|
relief=RIDGE, command=use_path)
|
||||||
self.button_game_extract.grid(row=1, column=1, sticky="NEWS")
|
self.button_game_extract.grid(row=1, column=1, sticky="NEWS")
|
||||||
|
|
||||||
|
@in_thread
|
||||||
def do_everything():
|
def do_everything():
|
||||||
def func():
|
use_path().join()
|
||||||
use_path().join()
|
self.game.patch_file().join()
|
||||||
self.game.patch_file(self).join()
|
self.game.install_mod().join()
|
||||||
self.game.install_mod(self).join()
|
|
||||||
|
|
||||||
if messagebox.askyesno(self.translate("Experimental functionality"),
|
if messagebox.askyesno(self.translate("Experimental functionality"),
|
||||||
self.translate("This will extract the selected ROM, prepare files and install mod. "
|
self.translate("This will extract the selected ROM, prepare files and install mod. "
|
||||||
"Do you wish to continue ?")):
|
"Do you wish to continue ?")):
|
||||||
t = Thread(target=func)
|
do_everything()
|
||||||
t.setDaemon(True)
|
|
||||||
t.start()
|
|
||||||
|
|
||||||
self.button_do_everything = Button(self.frame_game_path_action, text=self.translate("Do everything"), relief=RIDGE, command=do_everything)
|
self.button_do_everything = Button(self.frame_game_path_action, text=self.translate("Do everything"), relief=RIDGE, command=do_everything)
|
||||||
self.button_do_everything.grid(row=1, column=2, sticky="NEWS")
|
self.button_do_everything.grid(row=1, column=2, sticky="NEWS")
|
||||||
|
|
||||||
self.frame_action = LabelFrame(self.root, text=self.translate("Action"))
|
self.frame_action = LabelFrame(self.root, text=self.translate("Action"))
|
||||||
|
|
||||||
self.button_prepare_file = Button(self.frame_action, text=self.translate("Prepare files"), relief=RIDGE, command=lambda: self.game.patch_file(self), width=45)
|
self.button_prepare_file = Button(self.frame_action, text=self.translate("Prepare files"), relief=RIDGE, command=lambda: self.game.patch_file(), width=45)
|
||||||
self.button_prepare_file.grid(row=1, column=1, columnspan=2, sticky="NEWS")
|
self.button_prepare_file.grid(row=1, column=1, columnspan=2, sticky="NEWS")
|
||||||
self.button_install_mod = Button(self.frame_action, text=self.translate("Install mod"), relief=RIDGE, command=lambda: self.game.install_mod(self), width=45)
|
self.button_install_mod = Button(self.frame_action, text=self.translate("Install mod"), relief=RIDGE, command=lambda: self.game.install_mod(), width=45)
|
||||||
# Install mod button will only appear after prepare file step
|
# Install mod button will only appear after prepare file step
|
||||||
|
|
||||||
self.progressbar = ttk.Progressbar(self.root)
|
self.progressbar = ttk.Progressbar(self.root)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
CREATE_NO_WINDOW = 0x08000000
|
CREATE_NO_WINDOW = 0x08000000
|
||||||
GITHUB_REPOSITORY = "Faraphel/MKWF-Install"
|
GITHUB_REPOSITORY = "Faraphel/MKWF-Install"
|
||||||
GITHUB_MASTER_BRANCH = f"https://raw.githubusercontent.com/{GITHUB_REPOSITORY}/master/"
|
GITHUB_MASTER_BRANCH = f"https://raw.githubusercontent.com/{GITHUB_REPOSITORY}/master/"
|
||||||
|
@ -94,7 +96,18 @@ region_id_to_name = {
|
||||||
"E": "USA"
|
"E": "USA"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def filecopy(src, dst):
|
def filecopy(src, dst):
|
||||||
with open(src, "rb") as f1:
|
with open(src, "rb") as f1:
|
||||||
with open(dst, "wb") as f2:
|
with open(dst, "wb") as f2:
|
||||||
f2.write(f1.read()) # could be buffered
|
f2.write(f1.read()) # could be buffered
|
||||||
|
|
||||||
|
|
||||||
|
def in_thread(func):
|
||||||
|
def wrapped_func(*args, **kwargs):
|
||||||
|
thread = Thread(target=func, args=args, kwargs=kwargs)
|
||||||
|
thread.setDaemon(True)
|
||||||
|
thread.start()
|
||||||
|
return thread
|
||||||
|
|
||||||
|
return wrapped_func
|
||||||
|
|
|
@ -31,7 +31,7 @@ def normalize(src_file: str, dest_dir: str = "./file/Track/", dest_name: str = "
|
||||||
autoadd_path], creationflags=CREATE_NO_WINDOW, stderr=subprocess.PIPE)
|
autoadd_path], creationflags=CREATE_NO_WINDOW, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def extract(file: str, dest_dir: str):
|
def wit_extract(file: str, dest_dir: str):
|
||||||
"""
|
"""
|
||||||
:param file: game's file to extract (can be WBFS, ISO, CISO)
|
:param file: game's file to extract (can be WBFS, ISO, CISO)
|
||||||
:param dest_dir: where to extract the game
|
:param dest_dir: where to extract the game
|
||||||
|
@ -42,35 +42,79 @@ def extract(file: str, dest_dir: str):
|
||||||
|
|
||||||
|
|
||||||
def create(file: str):
|
def create(file: str):
|
||||||
pass
|
"""
|
||||||
|
:param file: create a .szs file from the directory {file}.d
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
subprocess.run(["./tools/szs/wszst", "CREATE", get_nodir(file) + ".d", "-d", get_nodir(file),
|
||||||
|
"--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
||||||
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def wstrt_patch(file: str):
|
def str_patch(file: str):
|
||||||
pass
|
subprocess.run(["./tools/szs/wstrt", "patch", get_nodir(file) + "/sys/main.dol", "--clean-dol",
|
||||||
|
"--add-lecode"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
||||||
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def wlect_patch(file: str,
|
def lec_patch(file: str,
|
||||||
lecode_file: str = f"./files/rel/lecode-PAL.bin",
|
lecode_file: str = f"./tmp/lecode-PAL.bin",
|
||||||
game_track_path: str = "./files/Race/Course/",
|
dest_lecode_file: str = f"./files/rel/lecode-PAL.bin",
|
||||||
move_track_path: str = "./files/Race/Course/",
|
game_track_path: str = "./files/Race/Course/",
|
||||||
ctfile_path: str = "./tmp/CTFILE.txt",
|
move_track_path: str = "./files/Race/Course/",
|
||||||
lpar_path: str = "./tmp/lpar-default.txt"):
|
ctfile_path: str = "./tmp/CTFILE.txt",
|
||||||
pass
|
lpar_path: str = "./tmp/lpar-default.txt"):
|
||||||
|
subprocess.run(
|
||||||
|
["./tools/szs/wlect", "patch", lecode_file, "-od",
|
||||||
|
dest_lecode_file, "--track-dir", game_track_path,
|
||||||
|
"--move-tracks", move_track_path, "--le-define", ctfile_path, "--lpar",
|
||||||
|
lpar_path, "--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=file, check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def edit(): pass
|
def edit(file, region_ID: str = "P", name: str = "Mario Kart Wii"):
|
||||||
|
subprocess.run(["./tools/wit/wit", "EDIT", get_nodir(file), "--id",
|
||||||
|
f"RMC{region_ID}60", "--name", name, "--modify", "ALL"],
|
||||||
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
||||||
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def autoadd(): pass
|
def autoadd(file: str, dest_dir: str):
|
||||||
|
subprocess.run(["./tools/szs/wszst", "AUTOADD", get_nodir(file) + "/files/Race/Course/", "--DEST", dest_dir],
|
||||||
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
||||||
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def bmg_decode(): pass
|
def bmg_encode(file: str):
|
||||||
|
subprocess.run(["./tools/szs/wbmgt", "ENCODE", get_nodir(file), "--overwrite"],
|
||||||
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
||||||
|
|
||||||
|
|
||||||
def bmg_encode(): pass
|
def bmg_cat(path: str, subfile: str = ".d/message/Common.bmg"):
|
||||||
|
return subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(path) + subfile],
|
||||||
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(path),
|
||||||
|
check=True, stdout=subprocess.PIPE).stdout.decode()
|
||||||
|
|
||||||
|
|
||||||
def wctct_bmg(): pass
|
def wit_copy(src_path, dst_path, format: str = "ISO"):
|
||||||
|
subprocess.run(["./tools/wit/wit", "COPY", get_nodir(src_path), "--DEST",
|
||||||
|
get_nodir(dst_path), f"--{format.lower()}", "--overwrite"],
|
||||||
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(dst_path),
|
||||||
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def wit_copy(): pass
|
def ctc_patch_bmg(bmgs: list, ctfile: str = "./file/CTFILE.txt"):
|
||||||
|
bmg_cmd = []
|
||||||
|
for bmg in bmgs: bmg_cmd.extend(["--patch-bmg", f"OVERWRITE={bmg}"])
|
||||||
|
return subprocess.run(
|
||||||
|
["tools/szs/wctct", "bmg", "--le-code", "--long", ctfile, *bmg_cmd],
|
||||||
|
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
|
||||||
|
|
||||||
|
|
||||||
|
def img_encode(src_file, format):
|
||||||
|
subprocess.run(["./tools/szs/wimgt", "ENCODE", src_file, "-x", format, "--overwrite"],
|
||||||
|
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
|
def szs_extract(file, dest_dir):
|
||||||
|
subprocess.run(["./tools/szs/wszst", "EXTRACT", get_nodir(file), "--DEST", dest_dir+".d"],
|
||||||
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
|
@ -19,7 +19,7 @@
|
||||||
"This directory will be overwritten if you install the mod !\nAre you sure you want to use it ?": "Ce dossier sera écrasé si vous installer le mod !\nÊtes-vous sûr de vouloir l'utiliser ?",
|
"This directory will be overwritten if you install the mod !\nAre you sure you want to use it ?": "Ce dossier sera écrasé si vous installer le mod !\nÊtes-vous sûr de vouloir l'utiliser ?",
|
||||||
"Extracting the game...": "Extraction du jeu...",
|
"Extracting the game...": "Extraction du jeu...",
|
||||||
"This file type is not supported": "Le type de fichier n'est pas reconnu",
|
"This file type is not supported": "Le type de fichier n'est pas reconnu",
|
||||||
"This game is already modded, it is not recommended to use it to install the mod": "Cette ROM est déjà moddé, il est déconseillé de l'utiliser pour installer le mod",
|
"This game is already modded": "Cette ROM est déjà moddé",
|
||||||
"Can't find game region.\nPAL region will be used.": "Impossible de trouver la région de votre jeu.\nla région PAL sera utilisé par défaut.",
|
"Can't find game region.\nPAL region will be used.": "Impossible de trouver la région de votre jeu.\nla région PAL sera utilisé par défaut.",
|
||||||
"Extract file": "Extraire le fichier",
|
"Extract file": "Extraire le fichier",
|
||||||
"Experimental functionality": "Fonctionnalité expérimentale",
|
"Experimental functionality": "Fonctionnalité expérimentale",
|
||||||
|
|
Loading…
Reference in a new issue