From e44b89bc65ff4edaa4bccaec8d26af094a17937d Mon Sep 17 00:00:00 2001 From: raphael60650 Date: Sun, 23 May 2021 19:45:50 +0200 Subject: [PATCH] splited code into multiple file --- main.pyw | 351 +-------------------------------- source/Progress.py | 23 +++ source/StateButton.py | 13 ++ source/__init__.py | 90 +++++++++ source/check_update.py | 38 ++++ source/create_lecode_config.py | 27 +++ source/definition.py | 10 + source/install_mod.py | 116 +++++++++++ source/patch_file.py | 71 +++++++ 9 files changed, 396 insertions(+), 343 deletions(-) create mode 100644 source/Progress.py create mode 100644 source/StateButton.py create mode 100644 source/__init__.py create mode 100644 source/check_update.py create mode 100644 source/create_lecode_config.py create mode 100644 source/definition.py create mode 100644 source/install_mod.py create mode 100644 source/patch_file.py diff --git a/main.pyw b/main.pyw index 6cb193f..e3cb836 100644 --- a/main.pyw +++ b/main.pyw @@ -9,352 +9,17 @@ import json import glob import os -def filecopy(src, dst): - with open(src, "rb") as f1: - with open(dst, "wb") as f2: - f2.write(f1.read()) # could be buffered - -get_filename = lambda file: ".".join(file.split(".")[:-1]) -get_nodir = lambda file: file.split("/")[-1].split("\\")[-1] -get_extension = lambda file: file.split(".")[-1] - -VERSION_FILE_URL = "https://raw.githubusercontent.com/Faraphel/MKWF-Install/master/version" -CREATE_NO_WINDOW = 0x08000000 - -def check_update(): - try: - gitversion = requests.get(VERSION_FILE_URL, allow_redirects=True).json() - with open("version", "rb") as f: - locversion = json.load(f) - - if gitversion["version"] != locversion["version"]: - if messagebox.askyesno("Mise à jour disponible !", "Une mise à jour est disponible, souhaitez-vous l'installer ?\n\n"+ \ - f"Version : {locversion['version']}.{locversion['subversion']} -> {gitversion['version']}.{gitversion['subversion']}\n"+\ - f"Changelog :\n{gitversion['changelog']}"): - - if not(os.path.exists("./Updater/Updater.exe")): - dl = requests.get(gitversion["updater_bin"], allow_redirects=True) - with open("./download.zip", "wb") as file: - print(f"Téléchargement de Updater en cours...") - file.write(dl.content) - print("fin du téléchargement, début de l'extraction...") - - with zipfile.ZipFile("./download.zip") as file: - file.extractall("./Updater/") - print("fin de l'extraction") - - os.remove("./download.zip") - print("lancement de l'application...") - os.startfile(os.path.realpath("./Updater/Updater.exe")) - sys.exit() - - except Exception as e: - print(e) +from source.definition import * +from source.check_update import * class ClassApp(): - def __init__(self): - self.root = Tk() - self.root.title("MKWFaraphel Installateur") - self.root.resizable(False, False) - self.root.iconbitmap(bitmap="./icon.ico") + from source.__init__ import __init__ + from source.Progress import Progress + from source.StateButton import StateButton + from source.create_lecode_config import create_lecode_config + from source.patch_file import patch_file + from source.install_mod import install_mod - self.frame_game_path = LabelFrame(self.root, text="Jeu original") - self.frame_game_path.grid(row=1,column=1) - - check_update() - self.path_mkwf = None - - entry_game_path = Entry(self.frame_game_path,width=50) - entry_game_path.grid(row=1,column=1,sticky="NEWS") - - def select_path(): - path = filedialog.askopenfilename(filetypes = (("Jeu Wii", r"*.iso *.wbfs main.dol *.wia *.ciso"),)) - if os.path.exists(path): - entry_game_path.delete(0, END) - entry_game_path.insert(0, path) - Button(self.frame_game_path, text="...", relief=RIDGE, command=select_path).grid(row=1,column=2,sticky="NEWS") - - def use_path(): - def func(): - self.frame_action.grid_forget() - path = entry_game_path.get() - if not(os.path.exists(path)): - messagebox.showerror("Erreur", "Le chemin de fichier est invalide") - return - - extension = get_extension(path) - if extension.upper() == "DOL": - if messagebox.askyesno("Attention", "Ce dossier sera écrasé si vous installer le mod !\n" +\ - "Êtes-vous sûr de vouloir l'utiliser ?"): - self.path_mkwf = os.path.realpath(path + "/../../") - elif extension.upper() in ["ISO", "WBFS", "WIA", "CSIO"]: - self.path_mkwf, i = os.path.realpath(path + "/../MKWiiFaraphel"), 1 - - while True: - if not(os.path.exists(self.path_mkwf)): break - self.path_mkwf, i = os.path.realpath(path + f"/../MKWiiFaraphel ({i})"), i+1 - - self.Progress(show=True, indeter=True, statut="Extraction du jeu...") - subprocess.call(["./tools/wit/wit", "EXTRACT", path, "--DEST", self.path_mkwf] - ,creationflags=CREATE_NO_WINDOW) - self.Progress(show=False) - - else: - messagebox.showerror("Erreur", "Le type de fichier n'est pas reconnu") - self.Progress(show=False) - return - - if os.path.exists(self.path_mkwf + "/files/rel/lecode-PAL.bin"): - messagebox.showwarning("Attention", "Cette ROM est déjà moddé, "+\ - "il est déconseillé de l'utiliser pour installer le mod") - - self.frame_action.grid(row=2, column=1,sticky="NEWS") - self.Progress(show=False) - - - t=Thread(target=func) - t.setDaemon(True) - t.start() - - - self.button_game_extract = Button(self.frame_game_path, text="Extraire le fichier", relief=RIDGE, command=use_path) - self.button_game_extract.grid(row=2,column=1,columnspan=2,sticky="NEWS") - - self.frame_action = LabelFrame(self.root, text="Action") - - self.button_prepare_file = Button(self.frame_action, text="Preparer les fichiers", relief=RIDGE, command=self.patch_file, width=45) - self.button_prepare_file.grid(row=1, column=1, columnspan=2, sticky="NEWS") - self.button_install_mod = Button(self.frame_action, text="Installer le mod", relief=RIDGE, command=self.install_mod, width=35) - self.listbox_outputformat = ttk.Combobox(self.frame_action, values=["Dossier", "ISO", "WBFS", "CISO"], width=5) - self.listbox_outputformat.set("Dossier") - # Le boutton d'installation du mod n'est affiché qu'après avoir préparer les fichiers - - self.progressbar = ttk.Progressbar(self.root) - self.progresslabel = Label(self.root) - - - def Progress(self, show=None, indeter=None, step=None, statut=None, max=None, add=None): - if indeter == True: - self.progressbar.config(mode="indeterminate") - self.progressbar.start(50) - elif indeter == False: - self.progressbar.config(mode="determinate") - self.progressbar.stop() - if show == True: - self.StateButton(enable=False) - self.progressbar.grid(row=100, column=1, sticky="NEWS") - self.progresslabel.grid(row=101, column=1, sticky="NEWS") - - elif show == False: - self.StateButton(enable=True) - self.progressbar.grid_forget() - self.progresslabel.grid_forget() - - if statut: self.progresslabel.config(text=statut) - if step: self.progressbar["value"] = step - if max: - self.progressbar["maximum"] = max - self.progressbar["value"] = 0 - if add: self.progressbar.step(add) - - - def StateButton(self, enable=True): - button = [ - self.button_game_extract, - self.button_install_mod, - self.button_prepare_file - ] - for widget in button: - if enable: widget.config(state=NORMAL) - else: widget.config(state=DISABLED) - - - def create_lecode_config(self): - with open("./ct_config.json") as f: ctconfig = json.load(f) - with open("./file/CTFILE.txt", "w") as ctfile: - ctfile.write( - "#CT-CODE\n"+ - "[RACING-TRACK-LIST]\n"+ - "%LE-FLAGS=1\n"+ - "%WIIMM-CUP=1\n"+ - "N N$SWAP | N$F_WII\n\n") - - for cup in ctconfig["cup"]: - _cup_config = ctconfig["cup"][cup] - if int(cup) >= 9: # Course qui ne sont ni les originales, ni les courses aléatoires. - ctfile.write(f'\nC "{_cup_config["name"]}"\n') - - for course in _cup_config["courses"]: - _course_config = _cup_config["courses"][course] - ctfile.write(f'T {_course_config["music"]}; '+ - f'{_course_config["special"]}; '+ - f'{"0x01" if _course_config["new"] else "0x00"}; '+ - f'"{_course_config["name"]}"; '+ - f'"{_course_config["name"]}"; '+ - f'"-"\n') - - - def patch_file(self): - def func(): - if os.path.exists("./file/Track-WU8/"): total_track = len(os.listdir("./file/Track-WU8/")) - else: total_track = 0 - with open("./convert_file.json") as f: fc = json.load(f) - max_step = len(fc["img"])+len(fc["bmg"])+total_track+1 - self.Progress(show=True, indeter=False, statut="Conversion des fichiers", max=max_step, step=0) - - for i, file in enumerate(fc["img"]): - self.Progress(statut=f"Conversion des images\n({i+1}/{len(fc['img'])}) {file}", add=1) - if not(os.path.exists("./file/"+get_filename(file))): - subprocess.call(["./tools/szs/wimgt", "ENCODE", "./file/"+file, "-x", fc["img"][file]] - ,creationflags=CREATE_NO_WINDOW) - - for i, file in enumerate(fc["bmg"]): - self.Progress(statut=f"Conversion des textes\n({i+1}/{len(fc['bmg'])}) {file}", add=1) - if not(os.path.exists("./file/"+get_filename(file)+".bmg")): - subprocess.call(["./tools/szs/wbmgt", "ENCODE", "./file/"+file] - ,creationflags=CREATE_NO_WINDOW) - - if not(os.path.exists("./file/auto-add/")): - subprocess.call(["./tools/szs/wszst", "AUTOADD", self.path_mkwf+"/files/Race/Course/", "--DEST", - "./file/auto-add/"], creationflags=CREATE_NO_WINDOW) - - max_process = 8 - process_list = {} - - for i, file in enumerate(os.listdir("./file/Track-WU8/")): - while True: - if len(process_list) < max_process: - process_list[file] = None - self.Progress(statut=f"Conversion des courses\n({i + 1}/{total_track})\n" + - "\n".join(process_list.keys()), add=1) - - if not(os.path.exists("./file/Track/"+get_filename(file)+".szs")): - process_list[file] = subprocess.Popen([ - "./tools/szs/wszst", "NORMALIZE", "./file/Track-WU8/"+file, "--DEST", - "./file/Track/%N.szs", "--szs", "--overwrite", "--autoadd-path", - "./file/auto-add/"], creationflags=CREATE_NO_WINDOW) - break - else: - for process in process_list: - if process_list[process] is not None: - if not(process_list[process].poll() is None): - process_list.pop(process) - break - else: - process_list.pop(process) - break - - self.Progress(statut="Création de LE-CODE", add=1) - self.create_lecode_config() - - self.Progress(show=False) - self.button_install_mod.grid(row=2,column=1,sticky="NEWS") - self.listbox_outputformat.grid(row=2, column=2, sticky="NEWS") - - t=Thread(target=func) - t.setDaemon(True) - t.start() - - - def install_mod(self): - def func(): - with open("./fs.json") as f: fs = json.load(f) - - ### This part is used to estimate the max_step - extracted_file = [] - max_step, step = 1, 0 - - def count_rf(path, file, subpath="/"): - nonlocal max_step - max_step += 1 - extension = get_extension(path) - if extension == "szs": - if not(os.path.realpath(path) in extracted_file): - extracted_file.append(os.path.realpath(path)) - max_step += 1 - - for fp in fs: - for f in glob.glob(self.path_mkwf + "/files/" + fp, recursive=True): - if type(fs[fp]) == str: count_rf(path=f, file=fs[fp]) - elif type(fs[fp]) == dict: - for nf in fs[fp]: - if type(fs[fp][nf]) == str: count_rf(path=f, subpath=nf, file=fs[fp][nf]) - elif type(fs[fp][nf]) == list: - for ffp in fs[fp][nf]: count_rf(path=f, subpath=nf, file=ffp) - ### - extracted_file = [] - max_step += 4 # PATCH main.dol et PATCH lecode.bin, conversion, changement d'ID - self.Progress(show=True, indeter=False, statut="Installation du mod", max=max_step, step=0) - - - - def replace_file(path, file, subpath="/"): - self.Progress(statut=f"Modification de\n{get_nodir(path)}", add=1) - #print(path, subpath, file) - extension = get_extension(path) - - if extension == "szs": - if not(os.path.realpath(path) in extracted_file): - subprocess.call(["./tools/szs/wszst", "EXTRACT", path, "-d", path+".d", "--overwrite"] - ,creationflags=CREATE_NO_WINDOW) - extracted_file.append(os.path.realpath(path)) - - szs_extract_path = path+".d" - if os.path.exists(szs_extract_path+subpath): - if subpath[-1] == "/": filecopy(f"./file/{file}", szs_extract_path+subpath+file) - else: filecopy(f"./file/{file}", szs_extract_path+subpath) - - elif path[-1] == "/": filecopy(f"./file/{file}", path+file) - else: filecopy(f"./file/{file}", path) - - for fp in fs: - for f in glob.glob(self.path_mkwf + "/files/" + fp, recursive=True): - if type(fs[fp]) == str: replace_file(path=f, file=fs[fp]) - elif type(fs[fp]) == dict: - for nf in fs[fp]: - if type(fs[fp][nf]) == str: replace_file(path=f, subpath=nf, file=fs[fp][nf]) - elif type(fs[fp][nf]) == list: - for ffp in fs[fp][nf]: replace_file(path=f, subpath=nf, file=ffp) - - - for file in extracted_file: - self.Progress(statut=f"Recompilation de\n{get_nodir(file)}", add=1) - subprocess.call(["./tools/szs/wszst", "CREATE", file+".d", "-d", file, - "--overwrite"], creationflags=CREATE_NO_WINDOW) - if os.path.exists(file+".d"): shutil.rmtree(file+".d") - - self.Progress(statut=f"Patch main.dol", add=1) - subprocess.call(["./tools/szs/wstrt", "patch", self.path_mkwf+"/sys/main.dol", "--clean-dol", - "--add-lecode"], creationflags=CREATE_NO_WINDOW) - - self.Progress(statut=f"Patch lecode-PAL.bin", add=1) - - subprocess.call( - ["./tools/szs/wlect", "patch", "./file/lecode-PAL.bin", "-od", self.path_mkwf+"/files/rel/lecode-PAL.bin", - "--track-dir", self.path_mkwf+"/files/Race/Course/", "--copy-tracks", "./file/Track/", - "--move-tracks", self.path_mkwf+"/files/Race/Course/", "--le-define", - "./file/CTFILE.txt", "--lpar", "./file/lpar-default.txt", "--overwrite"], creationflags=CREATE_NO_WINDOW) - - outputformat=self.listbox_outputformat.get() - self.Progress(statut=f"Conversion en {outputformat}", add=1) - - if outputformat in ["ISO", "WBFS", "CISO"]: - self.path_mkwf_format = os.path.realpath(self.path_mkwf+"/../MKWFaraphel."+outputformat.lower()) - subprocess.call(["./tools/wit/wit", "COPY", self.path_mkwf, "--DEST", - self.path_mkwf_format, f"--{outputformat.lower()}", "--overwrite"] - ,creationflags=CREATE_NO_WINDOW) - shutil.rmtree(self.path_mkwf) - - self.Progress(statut=f"Changement de l'ID du jeu", add=1) - subprocess.call(["./tools/wit/wit", "EDIT", self.path_mkwf_format, "--id", "RMCP60"] - ,creationflags=CREATE_NO_WINDOW) - - self.Progress(show=False) - messagebox.showinfo("Fin", "L'installation est terminé !") - - t = Thread(target=func) - t.setDaemon(True) - t.start() # TODO: Langue # TODO: Split Code into multiple file diff --git a/source/Progress.py b/source/Progress.py new file mode 100644 index 0000000..5573acc --- /dev/null +++ b/source/Progress.py @@ -0,0 +1,23 @@ +def Progress(self, show=None, indeter=None, step=None, statut=None, max=None, add=None): + if indeter == True: + self.progressbar.config(mode="indeterminate") + self.progressbar.start(50) + elif indeter == False: + self.progressbar.config(mode="determinate") + self.progressbar.stop() + if show == True: + self.StateButton(enable=False) + self.progressbar.grid(row=100, column=1, sticky="NEWS") + self.progresslabel.grid(row=101, column=1, sticky="NEWS") + + elif show == False: + self.StateButton(enable=True) + self.progressbar.grid_forget() + self.progresslabel.grid_forget() + + if statut: self.progresslabel.config(text=statut) + if step: self.progressbar["value"] = step + if max: + self.progressbar["maximum"] = max + self.progressbar["value"] = 0 + if add: self.progressbar.step(add) \ No newline at end of file diff --git a/source/StateButton.py b/source/StateButton.py new file mode 100644 index 0000000..5d5bb62 --- /dev/null +++ b/source/StateButton.py @@ -0,0 +1,13 @@ +from tkinter import * + +def StateButton(self, enable=True): + button = [ + self.button_game_extract, + self.button_install_mod, + self.button_prepare_file + ] + for widget in button: + if enable: + widget.config(state=NORMAL) + else: + widget.config(state=DISABLED) diff --git a/source/__init__.py b/source/__init__.py new file mode 100644 index 0000000..7df1d16 --- /dev/null +++ b/source/__init__.py @@ -0,0 +1,90 @@ +from tkinter import * +from tkinter import messagebox, filedialog, ttk +from threading import Thread +import subprocess +import os + +from .definition import * +from .check_update import check_update + + +def __init__(self): + self.root = Tk() + self.root.title("MKWFaraphel Installateur") + self.root.resizable(False, False) + self.root.iconbitmap(bitmap="./icon.ico") + + self.frame_game_path = LabelFrame(self.root, text="Jeu original") + self.frame_game_path.grid(row=1, column=1) + + check_update() + self.path_mkwf = None + + entry_game_path = Entry(self.frame_game_path, width=50) + entry_game_path.grid(row=1, column=1, sticky="NEWS") + + def select_path(): + path = filedialog.askopenfilename(filetypes=(("Jeu Wii", r"*.iso *.wbfs main.dol *.wia *.ciso"),)) + if os.path.exists(path): + entry_game_path.delete(0, END) + entry_game_path.insert(0, path) + + Button(self.frame_game_path, text="...", relief=RIDGE, command=select_path).grid(row=1, column=2, sticky="NEWS") + + def use_path(): + def func(): + self.frame_action.grid_forget() + path = entry_game_path.get() + if not (os.path.exists(path)): + messagebox.showerror("Erreur", "Le chemin de fichier est invalide") + return + + extension = get_extension(path) + if extension.upper() == "DOL": + if messagebox.askyesno("Attention", "Ce dossier sera écrasé si vous installer le mod !\n" + \ + "Êtes-vous sûr de vouloir l'utiliser ?"): + self.path_mkwf = os.path.realpath(path + "/../../") + elif extension.upper() in ["ISO", "WBFS", "WIA", "CSIO"]: + self.path_mkwf, i = os.path.realpath(path + "/../MKWiiFaraphel"), 1 + + while True: + if not (os.path.exists(self.path_mkwf)): break + self.path_mkwf, i = os.path.realpath(path + f"/../MKWiiFaraphel ({i})"), i + 1 + + self.Progress(show=True, indeter=True, statut="Extraction du jeu...") + subprocess.call(["./tools/wit/wit", "EXTRACT", path, "--DEST", self.path_mkwf] + , creationflags=CREATE_NO_WINDOW) + self.Progress(show=False) + + else: + messagebox.showerror("Erreur", "Le type de fichier n'est pas reconnu") + self.Progress(show=False) + return + + if os.path.exists(self.path_mkwf + "/files/rel/lecode-PAL.bin"): + messagebox.showwarning("Attention", "Cette ROM est déjà moddé, " + \ + "il est déconseillé de l'utiliser pour installer le mod") + + self.frame_action.grid(row=2, column=1, sticky="NEWS") + self.Progress(show=False) + + t = Thread(target=func) + t.setDaemon(True) + t.start() + + self.button_game_extract = Button(self.frame_game_path, text="Extraire le fichier", relief=RIDGE, command=use_path) + self.button_game_extract.grid(row=2, column=1, columnspan=2, sticky="NEWS") + + self.frame_action = LabelFrame(self.root, text="Action") + + self.button_prepare_file = Button(self.frame_action, text="Preparer les fichiers", relief=RIDGE, + command=self.patch_file, width=45) + self.button_prepare_file.grid(row=1, column=1, columnspan=2, sticky="NEWS") + self.button_install_mod = Button(self.frame_action, text="Installer le mod", relief=RIDGE, command=self.install_mod, + width=35) + self.listbox_outputformat = ttk.Combobox(self.frame_action, values=["Dossier", "ISO", "WBFS", "CISO"], width=5) + self.listbox_outputformat.set("Dossier") + # Le boutton d'installation du mod n'est affiché qu'après avoir préparer les fichiers + + self.progressbar = ttk.Progressbar(self.root) + self.progresslabel = Label(self.root) diff --git a/source/check_update.py b/source/check_update.py new file mode 100644 index 0000000..872154d --- /dev/null +++ b/source/check_update.py @@ -0,0 +1,38 @@ +from tkinter import messagebox +from . import * +import requests +import zipfile +import json +import sys +import os + +VERSION_FILE_URL = "https://raw.githubusercontent.com/Faraphel/MKWF-Install/master/version" +def check_update(): + try: + gitversion = requests.get(VERSION_FILE_URL, allow_redirects=True).json() + with open("version", "rb") as f: + locversion = json.load(f) + + if gitversion["version"] != locversion["version"]: + if messagebox.askyesno("Mise à jour disponible !", "Une mise à jour est disponible, souhaitez-vous l'installer ?\n\n"+ \ + f"Version : {locversion['version']}.{locversion['subversion']} -> {gitversion['version']}.{gitversion['subversion']}\n"+\ + f"Changelog :\n{gitversion['changelog']}"): + + if not(os.path.exists("./Updater/Updater.exe")): + dl = requests.get(gitversion["updater_bin"], allow_redirects=True) + with open("./download.zip", "wb") as file: + print(f"Téléchargement de Updater en cours...") + file.write(dl.content) + print("fin du téléchargement, début de l'extraction...") + + with zipfile.ZipFile("./download.zip") as file: + file.extractall("./Updater/") + print("fin de l'extraction") + + os.remove("./download.zip") + print("lancement de l'application...") + os.startfile(os.path.realpath("./Updater/Updater.exe")) + sys.exit() + + except Exception as e: + print(e) \ No newline at end of file diff --git a/source/create_lecode_config.py b/source/create_lecode_config.py new file mode 100644 index 0000000..500dd7c --- /dev/null +++ b/source/create_lecode_config.py @@ -0,0 +1,27 @@ +import json + + +def create_lecode_config(self): + with open("./ct_config.json") as f: + ctconfig = json.load(f) + with open("./file/CTFILE.txt", "w") as ctfile: + ctfile.write( + "#CT-CODE\n" + + "[RACING-TRACK-LIST]\n" + + "%LE-FLAGS=1\n" + + "%WIIMM-CUP=1\n" + + "N N$SWAP | N$F_WII\n\n") + + for cup in ctconfig["cup"]: + _cup_config = ctconfig["cup"][cup] + if int(cup) >= 9: # Course qui ne sont ni les originales, ni les courses aléatoires. + ctfile.write(f'\nC "{_cup_config["name"]}"\n') + + for course in _cup_config["courses"]: + _course_config = _cup_config["courses"][course] + ctfile.write(f'T {_course_config["music"]}; ' + + f'{_course_config["special"]}; ' + + f'{"0x01" if _course_config["new"] else "0x00"}; ' + + f'"{_course_config["name"]}"; ' + + f'"{_course_config["name"]}"; ' + + f'"-"\n') diff --git a/source/definition.py b/source/definition.py new file mode 100644 index 0000000..ccaedf6 --- /dev/null +++ b/source/definition.py @@ -0,0 +1,10 @@ +get_filename = lambda file: ".".join(file.split(".")[:-1]) +get_nodir = lambda file: file.split("/")[-1].split("\\")[-1] +get_extension = lambda file: file.split(".")[-1] + +CREATE_NO_WINDOW = 0x08000000 + +def filecopy(src, dst): + with open(src, "rb") as f1: + with open(dst, "wb") as f2: + f2.write(f1.read()) # could be buffered \ No newline at end of file diff --git a/source/install_mod.py b/source/install_mod.py new file mode 100644 index 0000000..5e95c89 --- /dev/null +++ b/source/install_mod.py @@ -0,0 +1,116 @@ +from tkinter import messagebox +from threading import Thread +import subprocess +import shutil +import json +import glob +import os + +from .definition import * + + +def install_mod(self): + def func(): + with open("./fs.json") as f: + fs = json.load(f) + + # This part is used to estimate the max_step + extracted_file = [] + max_step, step = 1, 0 + + def count_rf(path, file, subpath="/"): + nonlocal max_step + max_step += 1 + extension = get_extension(path) + if extension == "szs": + if not (os.path.realpath(path) in extracted_file): + extracted_file.append(os.path.realpath(path)) + max_step += 1 + + for fp in fs: + for f in glob.glob(self.path_mkwf + "/files/" + fp, recursive=True): + if type(fs[fp]) == str: + count_rf(path=f, file=fs[fp]) + elif type(fs[fp]) == dict: + for nf in fs[fp]: + if type(fs[fp][nf]) == str: + count_rf(path=f, subpath=nf, file=fs[fp][nf]) + elif type(fs[fp][nf]) == list: + for ffp in fs[fp][nf]: count_rf(path=f, subpath=nf, file=ffp) + ### + extracted_file = [] + max_step += 4 # PATCH main.dol et PATCH lecode.bin, conversion, changement d'ID + self.Progress(show=True, indeter=False, statut="Installation du mod", max=max_step, step=0) + + def replace_file(path, file, subpath="/"): + self.Progress(statut=f"Modification de\n{get_nodir(path)}", add=1) + # print(path, subpath, file) + extension = get_extension(path) + + if extension == "szs": + if not (os.path.realpath(path) in extracted_file): + subprocess.call(["./tools/szs/wszst", "EXTRACT", path, "-d", path + ".d", "--overwrite"] + , creationflags=CREATE_NO_WINDOW) + extracted_file.append(os.path.realpath(path)) + + szs_extract_path = path + ".d" + if os.path.exists(szs_extract_path + subpath): + if subpath[-1] == "/": + filecopy(f"./file/{file}", szs_extract_path + subpath + file) + else: + filecopy(f"./file/{file}", szs_extract_path + subpath) + + elif path[-1] == "/": + filecopy(f"./file/{file}", path + file) + else: + filecopy(f"./file/{file}", path) + + for fp in fs: + for f in glob.glob(self.path_mkwf + "/files/" + fp, recursive=True): + if type(fs[fp]) == str: + replace_file(path=f, file=fs[fp]) + elif type(fs[fp]) == dict: + for nf in fs[fp]: + if type(fs[fp][nf]) == str: + replace_file(path=f, subpath=nf, file=fs[fp][nf]) + elif type(fs[fp][nf]) == list: + for ffp in fs[fp][nf]: replace_file(path=f, subpath=nf, file=ffp) + + for file in extracted_file: + self.Progress(statut=f"Recompilation de\n{get_nodir(file)}", add=1) + subprocess.call(["./tools/szs/wszst", "CREATE", file + ".d", "-d", file, + "--overwrite"], creationflags=CREATE_NO_WINDOW) + if os.path.exists(file + ".d"): shutil.rmtree(file + ".d") + + self.Progress(statut=f"Patch main.dol", add=1) + subprocess.call(["./tools/szs/wstrt", "patch", self.path_mkwf + "/sys/main.dol", "--clean-dol", + "--add-lecode"], creationflags=CREATE_NO_WINDOW) + + self.Progress(statut=f"Patch lecode-PAL.bin", add=1) + + subprocess.call( + ["./tools/szs/wlect", "patch", "./file/lecode-PAL.bin", "-od", self.path_mkwf + "/files/rel/lecode-PAL.bin", + "--track-dir", self.path_mkwf + "/files/Race/Course/", "--copy-tracks", "./file/Track/", + "--move-tracks", self.path_mkwf + "/files/Race/Course/", "--le-define", + "./file/CTFILE.txt", "--lpar", "./file/lpar-default.txt", "--overwrite"], creationflags=CREATE_NO_WINDOW) + + outputformat = self.listbox_outputformat.get() + self.Progress(statut=f"Conversion en {outputformat}", add=1) + + if outputformat in ["ISO", "WBFS", "CISO"]: + self.path_mkwf_format = os.path.realpath(self.path_mkwf + "/../MKWFaraphel." + outputformat.lower()) + subprocess.call(["./tools/wit/wit", "COPY", self.path_mkwf, "--DEST", + self.path_mkwf_format, f"--{outputformat.lower()}", "--overwrite"] + , creationflags=CREATE_NO_WINDOW) + shutil.rmtree(self.path_mkwf) + + self.Progress(statut=f"Changement de l'ID du jeu", add=1) + subprocess.call(["./tools/wit/wit", "EDIT", self.path_mkwf_format, "--id", "RMCP60"] + , creationflags=CREATE_NO_WINDOW) + + self.Progress(show=False) + messagebox.showinfo("Fin", "L'installation est terminé !") + + t = Thread(target=func) + t.setDaemon(True) + t.start() diff --git a/source/patch_file.py b/source/patch_file.py new file mode 100644 index 0000000..a32f0f6 --- /dev/null +++ b/source/patch_file.py @@ -0,0 +1,71 @@ +from threading import Thread +import subprocess +import json +import os + +from .definition import * + + +def patch_file(self): + def func(): + if os.path.exists("./file/Track-WU8/"): + total_track = len(os.listdir("./file/Track-WU8/")) + else: + total_track = 0 + with open("./convert_file.json") as f: + fc = json.load(f) + max_step = len(fc["img"]) + len(fc["bmg"]) + total_track + 1 + self.Progress(show=True, indeter=False, statut="Conversion des fichiers", max=max_step, step=0) + + for i, file in enumerate(fc["img"]): + self.Progress(statut=f"Conversion des images\n({i + 1}/{len(fc['img'])}) {file}", add=1) + if not (os.path.exists("./file/" + get_filename(file))): + subprocess.call(["./tools/szs/wimgt", "ENCODE", "./file/" + file, "-x", fc["img"][file]] + , creationflags=CREATE_NO_WINDOW) + + for i, file in enumerate(fc["bmg"]): + self.Progress(statut=f"Conversion des textes\n({i + 1}/{len(fc['bmg'])}) {file}", add=1) + if not (os.path.exists("./file/" + get_filename(file) + ".bmg")): + subprocess.call(["./tools/szs/wbmgt", "ENCODE", "./file/" + file] + , creationflags=CREATE_NO_WINDOW) + + if not (os.path.exists("./file/auto-add/")): + subprocess.call(["./tools/szs/wszst", "AUTOADD", self.path_mkwf + "/files/Race/Course/", "--DEST", + "./file/auto-add/"], creationflags=CREATE_NO_WINDOW) + + max_process = 8 + process_list = {} + + for i, file in enumerate(os.listdir("./file/Track-WU8/")): + while True: + if len(process_list) < max_process: + process_list[file] = None + self.Progress(statut=f"Conversion des courses\n({i + 1}/{total_track})\n" + + "\n".join(process_list.keys()), add=1) + + if not (os.path.exists("./file/Track/" + get_filename(file) + ".szs")): + process_list[file] = subprocess.Popen([ + "./tools/szs/wszst", "NORMALIZE", "./file/Track-WU8/" + file, "--DEST", + "./file/Track/%N.szs", "--szs", "--overwrite", "--autoadd-path", + "./file/auto-add/"], creationflags=CREATE_NO_WINDOW) + break + else: + for process in process_list: + if process_list[process] is not None: + if not (process_list[process].poll() is None): + process_list.pop(process) + break + else: + process_list.pop(process) + break + + self.Progress(statut="Création de LE-CODE", add=1) + self.create_lecode_config() + + self.Progress(show=False) + self.button_install_mod.grid(row=2, column=1, sticky="NEWS") + self.listbox_outputformat.grid(row=2, column=2, sticky="NEWS") + + t = Thread(target=func) + t.setDaemon(True) + t.start()