mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-04 11:48:22 +02:00
splited code into multiple file
This commit is contained in:
parent
5532fceb9c
commit
e44b89bc65
9 changed files with 396 additions and 343 deletions
351
main.pyw
351
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
|
||||
|
|
23
source/Progress.py
Normal file
23
source/Progress.py
Normal file
|
@ -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)
|
13
source/StateButton.py
Normal file
13
source/StateButton.py
Normal file
|
@ -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)
|
90
source/__init__.py
Normal file
90
source/__init__.py
Normal file
|
@ -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)
|
38
source/check_update.py
Normal file
38
source/check_update.py
Normal file
|
@ -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)
|
27
source/create_lecode_config.py
Normal file
27
source/create_lecode_config.py
Normal file
|
@ -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')
|
10
source/definition.py
Normal file
10
source/definition.py
Normal file
|
@ -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
|
116
source/install_mod.py
Normal file
116
source/install_mod.py
Normal file
|
@ -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()
|
71
source/patch_file.py
Normal file
71
source/patch_file.py
Normal file
|
@ -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()
|
Loading…
Reference in a new issue