mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-04 03:38:26 +02:00
commit
4cafdc3d53
21 changed files with 379 additions and 149 deletions
Binary file not shown.
File diff suppressed because one or more lines are too long
6
main.pyw
6
main.pyw
|
@ -16,7 +16,7 @@ from source.definition import *
|
|||
|
||||
class ClassApp():
|
||||
from source.__init__ import __init__
|
||||
from source.translate import translate, change_language, get_language
|
||||
from source.translate import translate
|
||||
from source.Progress import Progress
|
||||
from source.check_update import check_update
|
||||
from source.StateButton import StateButton
|
||||
|
@ -28,6 +28,10 @@ class ClassApp():
|
|||
from source.patch_img_desc import patch_img_desc
|
||||
from source.patch_ct_icon import patch_ct_icon
|
||||
from source.log_error import log_error
|
||||
from source.get_github_file import get_github_file
|
||||
from source.patch_track import count_track, patch_track, patch_autoadd
|
||||
from source.patch_image import patch_image
|
||||
from source.option import load_option, change_option
|
||||
|
||||
|
||||
App = ClassApp()
|
||||
|
|
1
option.json
Normal file
1
option.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"language": "en", "format": "FST", "disable_download": false, "del_track_after_conv": false, "dont_check_for_update": false, "process_track": 8}
|
2
setup.py
2
setup.py
|
@ -15,7 +15,7 @@ include_files = [
|
|||
"./tools",
|
||||
"./source",
|
||||
|
||||
("./file/Track-WU8", "./file/Track-WU8"),
|
||||
# ("./file/Track-WU8", "./file/Track-WU8"),
|
||||
("./file/cup_icon", "./file/cup_icon"),
|
||||
("./file/img_desc", "./file/img_desc"),
|
||||
("./file/video.thp", "./file/video.thp"),
|
||||
|
|
|
@ -11,27 +11,56 @@ from .translate import translate
|
|||
|
||||
def __init__(self):
|
||||
try:
|
||||
self.language = self.get_language()
|
||||
|
||||
self.root = Tk()
|
||||
|
||||
self.load_option()
|
||||
self.stringvar_language = StringVar(value=self.option["language"])
|
||||
self.stringvar_game_format = StringVar(value=self.option["format"])
|
||||
self.boolvar_disable_download = BooleanVar(value=self.option["disable_download"])
|
||||
self.boolvar_del_track_after_conv = BooleanVar(value=self.option["del_track_after_conv"])
|
||||
self.boolvar_dont_check_for_update = BooleanVar(value=self.option["dont_check_for_update"])
|
||||
self.intvar_process_track = IntVar(value=self.option["process_track"])
|
||||
|
||||
self.root.title(self.translate("MKWFaraphel Installateur"))
|
||||
self.root.resizable(False, False)
|
||||
self.root.iconbitmap(bitmap="./icon.ico")
|
||||
|
||||
self.check_update()
|
||||
if not(self.boolvar_dont_check_for_update.get()): self.check_update()
|
||||
self.path_mkwf = None
|
||||
|
||||
|
||||
self.menu_bar = Menu(self.root)
|
||||
self.root.config(menu=self.menu_bar)
|
||||
|
||||
self.menu_language = Menu(self.menu_bar, tearoff=0)
|
||||
self.menu_bar.add_cascade(label=self.translate("Langage"), menu=self.menu_language)
|
||||
self.menu_language.add_radiobutton(label="Français", variable=self.stringvar_language, value="fr", command=lambda: self.change_option("language", "fr", restart=True))
|
||||
self.menu_language.add_radiobutton(label="English", variable=self.stringvar_language, value="en", command=lambda: self.change_option("language", "en", restart=True))
|
||||
|
||||
self.menu_format = Menu(self.menu_bar, tearoff=0)
|
||||
self.menu_bar.add_cascade(label=self.translate("Format"), menu=self.menu_format)
|
||||
self.menu_format.add_radiobutton(label=self.translate("FST (Dossier)"), variable=self.stringvar_game_format, value="FST", command=lambda: self.change_option("format", "FST"))
|
||||
self.menu_format.add_radiobutton(label="ISO", variable=self.stringvar_game_format, value="ISO", command=lambda: self.change_option("format", "ISO"))
|
||||
self.menu_format.add_radiobutton(label="CISO", variable=self.stringvar_game_format, value="CISO", command=lambda: self.change_option("format", "CISO"))
|
||||
self.menu_format.add_radiobutton(label="WBFS", variable=self.stringvar_game_format, value="WBFS", command=lambda: self.change_option("format", "WBFS"))
|
||||
|
||||
self.menu_advanced = Menu(self.menu_bar, tearoff=0)
|
||||
self.menu_bar.add_cascade(label=self.translate("Avancé"), menu=self.menu_advanced)
|
||||
self.menu_advanced.add_checkbutton(label=self.translate("Désactiver les téléchargements"), variable=self.boolvar_disable_download, command=lambda: self.change_option("disable_download", self.boolvar_disable_download))
|
||||
self.menu_advanced.add_checkbutton(label=self.translate("Supprimer les courses wu8 après conversion en szs"), variable=self.boolvar_del_track_after_conv, command=lambda: self.change_option("del_track_after_conv", self.boolvar_del_track_after_conv))
|
||||
self.menu_advanced.add_checkbutton(label=self.translate("Ne pas vérifier les mises à jour"), variable=self.boolvar_dont_check_for_update, command=lambda: self.change_option("dont_check_for_update", self.boolvar_dont_check_for_update))
|
||||
self.menu_advanced.add_separator()
|
||||
self.menu_advanced.add_command(label=self.translate("Nombre de processus de conversion de course :"))
|
||||
self.menu_advanced.add_radiobutton(label=self.translate("1 processus"), variable=self.intvar_process_track, value=1, command=lambda: self.change_option("process_track", 1))
|
||||
self.menu_advanced.add_radiobutton(label=self.translate("2 processus"), variable=self.intvar_process_track, value=2, command=lambda: self.change_option("process_track", 2))
|
||||
self.menu_advanced.add_radiobutton(label=self.translate("4 processus"), variable=self.intvar_process_track, value=4, command=lambda: self.change_option("process_track", 4))
|
||||
self.menu_advanced.add_radiobutton(label=self.translate("8 processus"), variable=self.intvar_process_track, value=8, command=lambda: self.change_option("process_track", 8))
|
||||
|
||||
|
||||
self.frame_language = Frame(self.root)
|
||||
self.frame_language.grid(row=1, column=1, sticky="E")
|
||||
|
||||
Label(self.frame_language, text=self.translate("Langage : ")).grid(row=1, column=1)
|
||||
self.listbox_language = ttk.Combobox(self.frame_language, values=["fr", "en"], width=5)
|
||||
self.listbox_language.set(self.language)
|
||||
self.listbox_language.grid(row=1, column=2)
|
||||
|
||||
|
||||
self.listbox_language.bind("<<ComboboxSelected>>", lambda x: self.change_language())
|
||||
|
||||
self.frame_game_path = LabelFrame(self.root, text=self.translate("Jeu original"))
|
||||
self.frame_game_path.grid(row=2, column=1)
|
||||
|
||||
|
@ -67,7 +96,7 @@ def __init__(self):
|
|||
"Êtes-vous sûr de vouloir l'utiliser ?")):
|
||||
self.path_mkwf = os.path.realpath(path + "/../../")
|
||||
else: return
|
||||
elif extension.upper() in ["ISO", "WBFS", "WIA", "CSIO"]:
|
||||
elif extension.upper() in ["ISO", "WBFS", "CSIO"]:
|
||||
# Fiding a directory name that dosen't already exist
|
||||
directory_name, i = "MKWiiFaraphel", 1
|
||||
while True:
|
||||
|
@ -150,10 +179,7 @@ def __init__(self):
|
|||
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=self.translate("Installer le mod"), relief=RIDGE,
|
||||
command=self.install_mod, width=35)
|
||||
self.listbox_outputformat = ttk.Combobox(self.frame_action, values=[self.translate("Dossier"),
|
||||
"ISO", "WBFS", "CISO"], width=5)
|
||||
self.listbox_outputformat.set(self.translate("Dossier"))
|
||||
command=self.install_mod, width=45)
|
||||
# Le boutton d'installation du mod n'est affiché qu'après avoir préparer les fichiers
|
||||
|
||||
self.progressbar = ttk.Progressbar(self.root)
|
||||
|
|
|
@ -17,8 +17,10 @@ def check_update(self):
|
|||
if ((float(gitversion["version"]) > float(locversion["version"])) or
|
||||
(float(gitversion["version"]) == float(locversion["version"])) and
|
||||
float(gitversion["subversion"]) > float(locversion["subversion"])):
|
||||
if messagebox.askyesno(self.translate("Mise à jour disponible !"), self.translate("Une mise à jour est disponible, souhaitez-vous l'installer ?") +
|
||||
f"\n\nVersion : {locversion['version']}.{locversion['subversion']} -> {gitversion['version']}.{gitversion['subversion']}\n"+\
|
||||
if messagebox.askyesno(
|
||||
self.translate("Mise à jour disponible !"),
|
||||
self.translate("Une mise à jour est disponible, souhaitez-vous l'installer ?") +
|
||||
f"\n\nVersion : {locversion['version']}.{locversion['subversion']} -> {gitversion['version']}.{gitversion['subversion']}\n"
|
||||
f"Changelog :\n{gitversion['changelog']}"):
|
||||
|
||||
if not(os.path.exists("./Updater/Updater.exe")):
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import json
|
||||
from .definition import *
|
||||
|
||||
|
||||
def create_lecode_config(self):
|
||||
|
@ -13,26 +14,19 @@ def create_lecode_config(self):
|
|||
return ""
|
||||
|
||||
def get_ctfile_text(track, race=False):
|
||||
track_name = track["name"].replace("_", "")
|
||||
|
||||
if "prefix" in track: prefix = f"{track['prefix']} "
|
||||
else: prefix = ""
|
||||
if "suffix" in track: suffix = f" ({track['suffix']})"
|
||||
else: suffix = ""
|
||||
|
||||
if race:
|
||||
return f' T {track["music"]}; ' + \
|
||||
f'{track["special"]}; ' + \
|
||||
f'{"0x01" if track["new"] else "0x00"}; ' + \
|
||||
f'"-"; ' + \
|
||||
f'"{get_star_text(track)}{prefix}{track_name}{suffix}\\n{track["author"]}"; ' + \
|
||||
f'"{get_star_text(track)}{get_trackctname(track=track)}\\n{track["author"]}"; ' + \
|
||||
f'"-"\n'
|
||||
else:
|
||||
return f' T {track["music"]}; ' + \
|
||||
f'{track["special"]}; ' + \
|
||||
f'{"0x01" if track["new"] else "0x00"}; ' + \
|
||||
f'"{prefix}{track["name"]}{suffix}"; ' + \
|
||||
f'"{get_star_text(track)}{prefix}{track_name}{suffix}"; ' + \
|
||||
f'"{get_trackctname(track=track)}"; ' + \
|
||||
f'"{get_star_text(track)}{get_trackctname(track=track)}"; ' + \
|
||||
f'"-"\n'
|
||||
|
||||
with open("./ct_config.json", encoding="utf-8") as f:
|
||||
|
|
|
@ -1,10 +1,27 @@
|
|||
CREATE_NO_WINDOW = 0x08000000
|
||||
VERSION = "0.8.1"
|
||||
|
||||
get_filename = lambda file: ".".join(file.split(".")[:-1])
|
||||
get_nodir = lambda file: file.replace("\\", "/").split("/")[-1]
|
||||
get_dir = lambda file: "/".join(file.replace("\\", "/").split("/")[:-1])
|
||||
get_extension = lambda file: file.split(".")[-1]
|
||||
get_track_wu8 = lambda track: f"./file/Track-WU8/{track}.wu8"
|
||||
get_track_szs = lambda track: f"./file/Track/{track}.szs"
|
||||
|
||||
|
||||
def get_trackname(name=None, prefix=None, suffix=None, track=None):
|
||||
if track:
|
||||
name = track["name"]
|
||||
if "prefix" in track: prefix = track["prefix"]
|
||||
if "suffix" in track: suffix = track["suffix"]
|
||||
if prefix: name = prefix + " " + name
|
||||
if suffix: name = name + " (" + suffix + ")"
|
||||
return name
|
||||
|
||||
|
||||
def get_trackctname(name=None, prefix=None, suffix=None, track=None):
|
||||
return get_trackname(name=name, prefix=prefix, suffix=suffix, track=track).replace("_", "")
|
||||
|
||||
CREATE_NO_WINDOW = 0x08000000
|
||||
VERSION = "0.8.1"
|
||||
|
||||
def filecopy(src, dst):
|
||||
with open(src, "rb") as f1:
|
||||
|
|
29
source/get_github_file.py
Normal file
29
source/get_github_file.py
Normal file
|
@ -0,0 +1,29 @@
|
|||
import requests
|
||||
import os
|
||||
|
||||
root = "https://raw.githubusercontent.com/Faraphel/MKWF-Install/master/"
|
||||
|
||||
|
||||
def get_github_file(self, file):
|
||||
try:
|
||||
returncode = 0
|
||||
if self.boolvar_disable_download.get(): return 2
|
||||
|
||||
dl = requests.get(root+file, allow_redirects=True, stream=True)
|
||||
if os.path.exists(file):
|
||||
if int(dl.headers['Content-Length']) == os.path.getsize(file): return 1
|
||||
else: returncode = 3
|
||||
|
||||
if dl.status_code == 200: # if page is found
|
||||
with open(file, "wb") as file:
|
||||
chunk_size = 4096
|
||||
for i, chunk in enumerate(dl.iter_content(chunk_size=chunk_size)):
|
||||
file.write(chunk)
|
||||
file.flush()
|
||||
return returncode
|
||||
else:
|
||||
print(f"error {dl.status_code} {file}")
|
||||
return -1
|
||||
except:
|
||||
self.log_error()
|
||||
return -1
|
|
@ -22,8 +22,7 @@ def install_mod(self):
|
|||
def count_rf(path):
|
||||
nonlocal max_step
|
||||
max_step += 1
|
||||
extension = get_extension(path)
|
||||
if extension == "szs":
|
||||
if get_extension(path) == "szs":
|
||||
if not (os.path.realpath(path) in extracted_file):
|
||||
extracted_file.append(os.path.realpath(path))
|
||||
max_step += 1
|
||||
|
@ -106,7 +105,7 @@ def install_mod(self):
|
|||
|
||||
shutil.rmtree(self.path_mkwf + "/tmp/")
|
||||
|
||||
outputformat = self.listbox_outputformat.get()
|
||||
outputformat = self.stringvar_game_format.get()
|
||||
self.Progress(statut=self.translate("Conversion en")+f" {outputformat}", add=1)
|
||||
|
||||
if outputformat in ["ISO", "WBFS", "CISO"]:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import traceback
|
||||
from tkinter import messagebox
|
||||
|
||||
|
||||
def log_error(self):
|
||||
error = traceback.format_exc()
|
||||
with open("./error.log", "a") as f: f.write(f"---\n{error}\n")
|
||||
|
|
24
source/option.py
Normal file
24
source/option.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
default_option = {
|
||||
"language": "en",
|
||||
"format": "FST",
|
||||
"disable_download": False,
|
||||
"del_track_after_conv": False,
|
||||
"dont_check_for_update": False,
|
||||
"process_track": 8
|
||||
}
|
||||
|
||||
|
||||
def change_option(self, option, value, restart=False):
|
||||
if type(value) in [str, int, bool]: self.option[option] = value
|
||||
else: self.option[option] = value.get()
|
||||
with open("./option.json", "w", encoding="utf-8") as f: json.dump(self.option, f, ensure_ascii=False)
|
||||
if restart: self.restart()
|
||||
|
||||
|
||||
def load_option(self):
|
||||
if not(os.path.exists("./option.json")):
|
||||
with open("./option.json", "w", encoding="utf-8") as f: json.dump(default_option, f, ensure_ascii=False)
|
||||
with open("./option.json", encoding="utf-8") as f: self.option = json.load(f)
|
|
@ -88,7 +88,7 @@ trackname_color = {
|
|||
def patch_bmg(self, gamefile): # gamefile est le fichier .szs trouvé dans le /files/Scene/UI/ du jeu
|
||||
try:
|
||||
bmglang = gamefile[-len("E.txt"):-len(".txt")] # Langue du fichier
|
||||
self.Progress(statut=self.translate("Patch des textes " + bmglang), add=1)
|
||||
self.Progress(statut=self.translate("Patch des textes ") + bmglang, add=1)
|
||||
|
||||
subprocess.run(["./tools/szs/wszst", "EXTRACT", get_nodir(gamefile), "-d", get_nodir(gamefile) + ".d",
|
||||
"--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(gamefile))
|
||||
|
@ -96,8 +96,7 @@ def patch_bmg(self, gamefile): # gamefile est le fichier .szs trouvé dans le /
|
|||
# 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
|
||||
bmgtracks = bmgtracks.decode()
|
||||
check=True, stdout=subprocess.PIPE).stdout.decode()
|
||||
trackheader = "#--- standard track names"
|
||||
trackend = "2328"
|
||||
bmgtracks = bmgtracks[bmgtracks.find(trackheader) + len(trackheader):bmgtracks.find(trackend)]
|
||||
|
|
|
@ -1,113 +1,34 @@
|
|||
from tkinter import messagebox
|
||||
from threading import Thread
|
||||
import subprocess
|
||||
import shutil
|
||||
import json
|
||||
import glob
|
||||
import os
|
||||
|
||||
from .definition import *
|
||||
|
||||
|
||||
def patch_file(self):
|
||||
def func():
|
||||
try:
|
||||
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)
|
||||
if not(os.path.exists("./file/Track-WU8/")): os.makedirs("./file/Track-WU8/")
|
||||
with open("./convert_file.json") as f: fc = json.load(f)
|
||||
tracks, total_track = self.count_track()
|
||||
max_step = len(fc["img"]) + total_track + 3 + len("EGFIS")
|
||||
self.Progress(show=True, indeter=False, statut=self.translate("Conversion des fichiers"), max=max_step, step=0)
|
||||
|
||||
self.Progress(show=True, indeter=False, statut=self.translate("Conversion des fichiers"), max=max_step, step=0)
|
||||
self.Progress(statut=self.translate("Configuration de LE-CODE"), add=1)
|
||||
self.create_lecode_config()
|
||||
|
||||
self.Progress(statut=self.translate("Création de ct_icon.png"), add=1)
|
||||
self.patch_ct_icon()
|
||||
|
||||
self.Progress(statut=self.translate("Création des images descriptives"), add=1)
|
||||
self.patch_img_desc()
|
||||
self.patch_image(fc)
|
||||
for file in glob.glob(self.path_mkwf+"/files/Scene/UI/MenuSingle_?.szs"): self.patch_bmg(file)
|
||||
self.patch_autoadd()
|
||||
if self.patch_track(tracks, total_track) != 0: return
|
||||
|
||||
for i, file in enumerate(fc["img"]):
|
||||
self.Progress(statut=self.translate("Conversion des images")+f"\n({i + 1}/{len(fc['img'])}) {file}", add=1)
|
||||
subprocess.run(["./tools/szs/wimgt", "ENCODE", "./file/" + file, "-x", fc["img"][file], "--overwrite"],
|
||||
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE)
|
||||
|
||||
for file in glob.glob(self.path_mkwf+"/files/Scene/UI/MenuSingle_?.szs"):
|
||||
self.patch_bmg(file)
|
||||
|
||||
if os.path.exists("./file/auto-add"): shutil.rmtree("./file/auto-add")
|
||||
if not(os.path.exists(self.path_mkwf + "/tmp/")): os.makedirs(self.path_mkwf + "/tmp/")
|
||||
subprocess.run(["./tools/szs/wszst", "AUTOADD", get_nodir(self.path_mkwf) + "/files/Race/Course/",
|
||||
"--DEST", get_nodir(self.path_mkwf) + "/tmp/auto-add/"],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path_mkwf),
|
||||
check=True, stdout=subprocess.PIPE)
|
||||
shutil.move(self.path_mkwf + "/tmp/auto-add/", "./file/auto-add/")
|
||||
shutil.rmtree(self.path_mkwf + "/tmp/")
|
||||
|
||||
max_process = 8
|
||||
process_list = {}
|
||||
error_count, error_max = 0, 3
|
||||
|
||||
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=self.translate("Conversion des courses")+f"\n({i + 1}/{total_track})\n" +
|
||||
"\n".join(process_list.keys()), add=1)
|
||||
|
||||
track_szs_file = f"./file/Track/{get_filename(file)}.szs"
|
||||
if os.path.exists(track_szs_file):
|
||||
if os.path.getsize(track_szs_file) < 1000: # File under this size are corrupted
|
||||
os.remove(track_szs_file)
|
||||
|
||||
if not(os.path.exists(track_szs_file)):
|
||||
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, stderr=subprocess.PIPE)
|
||||
break
|
||||
else:
|
||||
for process in process_list:
|
||||
if process_list[process] is not None:
|
||||
returncode = process_list[process].poll()
|
||||
if returncode is None: pass # if the process is still running
|
||||
else: # process ended
|
||||
stderr = process_list[process].stderr.read()
|
||||
if b"wszst: ERROR" in stderr: # Error occured
|
||||
process_list.pop(process)
|
||||
os.remove(f"./file/Track/{get_filename(process)}.szs")
|
||||
error_count += 1
|
||||
if error_count > error_max: # Too much track wasn't correctly converted
|
||||
messagebox.showerror(
|
||||
self.translate("Erreur"),
|
||||
self.translate("Trop de course ont eu une erreur de conversion."))
|
||||
return
|
||||
else: # if the error max hasn't been reach
|
||||
messagebox.showwarning(
|
||||
self.translate("Attention"),
|
||||
self.translate("La course ") +
|
||||
process +
|
||||
self.translate(" n'a pas été correctement converti. (") +
|
||||
str(error_count) + "/"+str(error_max)+")")
|
||||
break
|
||||
|
||||
else:
|
||||
process_list.pop(process)
|
||||
break
|
||||
else:
|
||||
process_list.pop(process)
|
||||
break
|
||||
|
||||
self.button_install_mod.grid(row=2, column=1, sticky="NEWS")
|
||||
self.listbox_outputformat.grid(row=2, column=2, sticky="NEWS")
|
||||
self.button_install_mod.grid(row=2, column=1, columnspan=2, sticky="NEWS")
|
||||
|
||||
except: self.log_error()
|
||||
finally: self.Progress(show=False)
|
||||
|
||||
|
||||
t = Thread(target=func)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
|
9
source/patch_image.py
Normal file
9
source/patch_image.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
from .definition import *
|
||||
import subprocess
|
||||
|
||||
|
||||
def patch_image(self, fc):
|
||||
for i, file in enumerate(fc["img"]):
|
||||
self.Progress(statut=self.translate("Conversion des images") + f"\n({i + 1}/{len(fc['img'])}) {file}", add=1)
|
||||
subprocess.run(["./tools/szs/wimgt", "ENCODE", "./file/" + file, "-x", fc["img"][file], "--overwrite"],
|
||||
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE)
|
127
source/patch_track.py
Normal file
127
source/patch_track.py
Normal file
|
@ -0,0 +1,127 @@
|
|||
from .definition import *
|
||||
from tkinter import messagebox
|
||||
import subprocess
|
||||
import shutil
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
def count_track(self):
|
||||
tracks = []
|
||||
with open("./ct_config.json", encoding="utf-8") as f:
|
||||
ctconfig = json.load(f)
|
||||
for cup in ctconfig["cup"].values():
|
||||
if not (cup["locked"]): tracks.extend(cup["courses"].values())
|
||||
tracks.extend(ctconfig["tracks_list"])
|
||||
tracks = [dict(t) for t in {tuple(d.items()) for d in tracks}]
|
||||
total_track = len(tracks)
|
||||
return tracks, total_track
|
||||
|
||||
|
||||
def patch_autoadd(self):
|
||||
if os.path.exists("./file/auto-add"): shutil.rmtree("./file/auto-add")
|
||||
if not os.path.exists(self.path_mkwf + "/tmp/"): os.makedirs(self.path_mkwf + "/tmp/")
|
||||
subprocess.run(["./tools/szs/wszst", "AUTOADD", get_nodir(self.path_mkwf) + "/files/Race/Course/",
|
||||
"--DEST", get_nodir(self.path_mkwf) + "/tmp/auto-add/"],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path_mkwf),
|
||||
check=True, stdout=subprocess.PIPE)
|
||||
shutil.move(self.path_mkwf + "/tmp/auto-add/", "./file/auto-add/")
|
||||
shutil.rmtree(self.path_mkwf + "/tmp/")
|
||||
|
||||
|
||||
def patch_track(self, tracks, total_track="?"):
|
||||
max_process = self.intvar_process_track.get()
|
||||
process_list = {}
|
||||
error_count, error_max = 0, 3
|
||||
|
||||
def add_process(track_file):
|
||||
nonlocal error_count, error_max, process_list
|
||||
|
||||
process_list[track_file] = None # Used for
|
||||
self.Progress(statut=self.translate("Conversion des courses") + f"\n({i + 1}/{total_track})\n" +
|
||||
"\n".join(process_list.keys()), add=1)
|
||||
|
||||
for _track in [get_track_szs(track_file), get_track_wu8(track_file)]:
|
||||
if os.path.exists(_track):
|
||||
if os.path.getsize(_track) < 1000: # File under this size are corrupted
|
||||
os.remove(_track)
|
||||
|
||||
download_returncode = self.get_github_file(get_track_wu8(track_file))
|
||||
if download_returncode == -1: # can't download
|
||||
error_count += 1
|
||||
if error_count > error_max: # Too much track wasn't correctly converted
|
||||
messagebox.showerror(
|
||||
self.translate("Erreur"),
|
||||
self.translate("Trop de course ont eu une erreur du téléchargement."))
|
||||
return -1
|
||||
else:
|
||||
messagebox.showwarning(self.translate("Attention"),
|
||||
self.translate("Impossible de télécharger cette course ! (") +
|
||||
str(error_count) + "/" + str(error_max) + ")")
|
||||
|
||||
if not (os.path.exists(
|
||||
get_track_szs(track_file))) or download_returncode == 3: # returncode 3 is track has been updated
|
||||
if os.path.exists(get_track_wu8(track_file)):
|
||||
process_list[track_file] = subprocess.Popen([
|
||||
"./tools/szs/wszst", "NORMALIZE", get_track_wu8(track_file), "--DEST",
|
||||
"./file/Track/%N.szs", "--szs", "--overwrite", "--autoadd-path",
|
||||
"./file/auto-add/"], creationflags=CREATE_NO_WINDOW, stderr=subprocess.PIPE)
|
||||
else:
|
||||
messagebox.showerror(self.translate("Erreur"),
|
||||
self.translate("Impossible de convertir la course.\n"
|
||||
"Réactiver le téléchargement des courses et réessayer."))
|
||||
return -1
|
||||
elif self.boolvar_del_track_after_conv.get(): os.remove(get_track_wu8(track_file))
|
||||
return 0
|
||||
|
||||
def clean_process():
|
||||
nonlocal error_count, error_max, process_list
|
||||
|
||||
for track_file, process in process_list.copy().items():
|
||||
if process is not None:
|
||||
if process.poll() is None:
|
||||
print("still running...")
|
||||
pass # if the process is still running
|
||||
else: # process ended
|
||||
process_list.pop(track_file)
|
||||
stderr = process.stderr.read()
|
||||
if b"wszst: ERROR" in stderr: # Error occured
|
||||
os.remove(get_track_szs(track_file))
|
||||
error_count += 1
|
||||
if error_count > error_max: # Too much track wasn't correctly converted
|
||||
messagebox.showerror(
|
||||
self.translate("Erreur"),
|
||||
self.translate("Trop de course ont eu une erreur de conversion."))
|
||||
return -1
|
||||
else: # if the error max hasn't been reach
|
||||
messagebox.showwarning(
|
||||
self.translate("Attention"),
|
||||
self.translate("La course ") +
|
||||
get_track_wu8(track_file) +
|
||||
self.translate(" n'a pas été correctement converti. (") +
|
||||
str(error_count) + "/" + str(error_max) + ")")
|
||||
else:
|
||||
if self.boolvar_del_track_after_conv.get(): os.remove(get_track_wu8(track_file))
|
||||
else:
|
||||
process_list.pop(track_file)
|
||||
if not(any(process_list.values())): return 1 # si il n'y a plus de processus
|
||||
|
||||
if len(process_list): return 1
|
||||
else: return 0
|
||||
|
||||
for i, track in enumerate(tracks):
|
||||
track_file = get_trackname(track=track)
|
||||
while True:
|
||||
if len(process_list) < max_process:
|
||||
returncode = add_process(track_file)
|
||||
if returncode == 0: break
|
||||
elif returncode == -1: return -1 # if error occur, stop function
|
||||
elif clean_process() == -1: return -1
|
||||
|
||||
while True:
|
||||
returncode = clean_process()
|
||||
if returncode == 1: break # End the process if all process ended
|
||||
elif returncode == 0: pass
|
||||
else: return -1
|
||||
|
||||
return 0
|
|
@ -1,7 +1,10 @@
|
|||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
from .definition import *
|
||||
|
||||
|
||||
def restart(self):
|
||||
os.execl(sys.executable, f'"{sys.executable}"', *sys.argv)
|
||||
subprocess.Popen([sys.executable] + sys.argv, creationflags=CREATE_NO_WINDOW, cwd=os.getcwd())
|
||||
sys.exit()
|
|
@ -2,7 +2,7 @@ import json
|
|||
|
||||
|
||||
def translate(self, text, lang = None):
|
||||
if lang == None: lang = self.language
|
||||
if lang == None: lang = self.stringvar_language.get()
|
||||
elif lang == "E": lang = "en"
|
||||
elif lang == "G": lang = "ge"
|
||||
elif lang == "I": lang = "it"
|
||||
|
@ -13,18 +13,8 @@ def translate(self, text, lang = None):
|
|||
if lang in translation:
|
||||
_lang_trad = translation[lang]
|
||||
if text in _lang_trad: return _lang_trad[text]
|
||||
else:
|
||||
print(f"no translation for : \"{text}\"")
|
||||
return text
|
||||
|
||||
|
||||
def change_language(self):
|
||||
with open("./translation.json", encoding="utf-8") as f: translation = json.load(f)
|
||||
translation["selected"] = self.listbox_language.get()
|
||||
with open("./translation.json", "w", encoding="utf-8") as f: json.dump(translation, f)
|
||||
|
||||
self.restart()
|
||||
|
||||
|
||||
def get_language(self):
|
||||
with open("./translation.json", encoding="utf-8") as f: translation = json.load(f)
|
||||
if "selected" in translation: return translation["selected"]
|
||||
else: return "fr"
|
|
@ -1 +1,85 @@
|
|||
{"en": {"La course ": "The track ", " n'a pas été correctement converti. (": "hasn't been correctly converted. (", "Trop de course ont eu une erreur de conversion.": "Too much track had a conversion issue.", "Une erreur est survenue :": "An error occured :", "Cette action va extraire / utiliser la ROM s\u00e9lectionn\u00e9, pr\u00e9parer les fichiers et installer le mod. Voulez-vous continuer ?": "This will extract the selected ROM, prepare files and install mod. Do you wish to continue ?", "Fonctionnalit\u00e9 exp\u00e9rimentale": "Experimental functionality", "Tout faire": "Do everything", "Cr\u00e9ation des images descriptives": "Creation of descriptive images", "Cr\u00e9ation de ct_icon.png": "Creating ct_icon.png", "Patch des textes ": "Patching text ", "Al\u00e9atoire: Toutes les pistes": "Random: All tracks", "Al\u00e9atoire: Pistes Originales": "Random: Original tracks", "Al\u00e9atoire: Custom Tracks": "Random: Custom Tracks", "Al\u00e9atoire: Pistes Nouvelles": "Random: New tracks", "MKWFaraphel Installateur": "MKWFaraphel Installer", "Jeu Wii": "Wii game", "Jeu original": "Original game", "Erreur": "Error", "Le chemin de fichier est invalide": "The file path in invalid", "Attention": "Warning", "Ce dossier sera \u00e9cras\u00e9 si vous installer le mod !\n\u00cates-vous s\u00fbr de vouloir l'utiliser ?": "This directory will be overwritten if you install the mod !\nAre you sure you want to use it ?", "Extraction du jeu...": "Extracting the game...", "Le type de fichier n'est pas reconnu": "This file type is not supported", "Cette ROM est d\u00e9j\u00e0 modd\u00e9, il est d\u00e9conseill\u00e9 de l'utiliser pour installer le mod": "This game is already modded, it is not recommended to use it to install the mod", "Extraire le fichier": "Extract file", "Preparer les fichiers": "Prepare files", "Action": "Action", "Installer le mod": "Install mod", "Dossier": "Directory", "Langage : ": "Language : ", "Mise \u00e0 jour disponible !": "Update available !", "Une mise \u00e0 jour est disponible, souhaitez-vous l'installer ?": "An update is available, do you want to install it ?", "T\u00e9l\u00e9chargement de Updater en cours...": "Downloading the Updater...", "fin du t\u00e9l\u00e9chargement, d\u00e9but de l'extraction...": "end of the download, extracting...", "fin de l'extraction": "finished extracting", "lancement de l'application...": "starting application...", "Modification de": "Modifying", "Recompilation de": "Recompilating", "Conversion en": "Converting to", "Changement de l'ID du jeu": "editing game's ID", "Fin": "End", "L'installation est termin\u00e9 !": "The mod has been installed !", "Conversion des fichiers": "Converting files", "Conversion des images": "Converting images", "Conversion des textes": "Converting texts", "Conversion des courses": "Converting races", "Configuration de LE-CODE": "Configurating LE-CODE"}, "ge": {"Al\u00e9atoire: Toutes les pistes": "Zuf\u00e4llig: Alle Spuren", "Al\u00e9atoire: Pistes Originales": "Zuf\u00e4llig: Original-Spuren", "Al\u00e9atoire: Custom Tracks": "Zuf\u00e4llig: Custom Tracks", "Al\u00e9atoire: Pistes Nouvelles": "Zuf\u00e4llig: Neue Spuren"}, "it": {"Al\u00e9atoire: Toutes les pistes": "Casuale: Tutte le tracce", "Al\u00e9atoire: Pistes Originales": "Casuale: Tracce originali", "Al\u00e9atoire: Custom Tracks": "Casuale: Custom Tracks", "Al\u00e9atoire: Pistes Nouvelles": "Casuale: Nuovi brani"}, "sp": {"Al\u00e9atoire: Toutes les pistes": "Aleatorio: Todas las pistas", "Al\u00e9atoire: Pistes Originales": "Aleatorio: Pistas originales", "Al\u00e9atoire: Custom Tracks": "Aleatorio: Custom Tracks", "Al\u00e9atoire: Pistes Nouvelles": "Aleatorio: Pistas nuevas"}, "selected": "fr"}
|
||||
{
|
||||
"en": {
|
||||
"Patch main.dol": "Patch main.dol",
|
||||
"Patch lecode.bin": "Patch lecode.bin",
|
||||
"Installation du mod": "Installing mod",
|
||||
"Impossible de convertir la course.\nRéactiver le téléchargement des courses et réessayer.": "Impossible to convert track.\nEnable track download and retry.",
|
||||
"Langage": "Language",
|
||||
"Format": "Format",
|
||||
"FST (Dossier)": "FST (Directory)",
|
||||
"Avancé": "Advanced",
|
||||
"Désactiver les téléchargements": "Disable downloads",
|
||||
"Supprimer les courses wu8 après conversion en szs": "Delete wu8 track after conversion to szs",
|
||||
"Ne pas vérifier les mises à jour": "Don't check for update",
|
||||
"Nombre de processus de conversion de course :": "Number of process for track conversion :",
|
||||
"1 processus": "1 process",
|
||||
"2 processus": "2 process",
|
||||
"4 processus": "4 process",
|
||||
"8 processus": "8 process",
|
||||
"La course ": "The track ",
|
||||
" n'a pas été correctement converti. (": "hasn't been correctly converted. (",
|
||||
"Trop de course ont eu une erreur de conversion.": "Too much track had a conversion issue.",
|
||||
"Une erreur est survenue :": "An error occured :",
|
||||
"Cette action va extraire / utiliser la ROM sélectionné, préparer les fichiers et installer le mod. Voulez-vous continuer ?": "This will extract the selected ROM, prepare files and install mod. Do you wish to continue ?",
|
||||
"Fonctionnalité expérimentale": "Experimental functionality",
|
||||
"Tout faire": "Do everything",
|
||||
"Création des images descriptives": "Creation of descriptive images",
|
||||
"Création de ct_icon.png": "Creating ct_icon.png",
|
||||
"Patch des textes ": "Patching text ",
|
||||
"Aléatoire: Toutes les pistes": "Random: All tracks",
|
||||
"Aléatoire: Pistes Originales": "Random: Original tracks",
|
||||
"Aléatoire: Custom Tracks": "Random: Custom Tracks",
|
||||
"Aléatoire: Pistes Nouvelles": "Random: New tracks",
|
||||
"MKWFaraphel Installateur": "MKWFaraphel Installer",
|
||||
"Jeu Wii": "Wii game",
|
||||
"Jeu original": "Original game",
|
||||
"Erreur": "Error",
|
||||
"Le chemin de fichier est invalide": "The file path in invalid",
|
||||
"Attention": "Warning",
|
||||
"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 ?",
|
||||
"Extraction du jeu...": "Extracting the game...",
|
||||
"Le type de fichier n'est pas reconnu": "This file type is not supported",
|
||||
"Cette ROM est déjà moddé, il est déconseillé de l'utiliser pour installer le mod": "This game is already modded, it is not recommended to use it to install the mod",
|
||||
"Extraire le fichier": "Extract file",
|
||||
"Preparer les fichiers": "Prepare files",
|
||||
"Action": "Action",
|
||||
"Installer le mod": "Install mod",
|
||||
"Dossier": "Directory",
|
||||
"Langage : ": "Language : ",
|
||||
"Mise à jour disponible !": "Update available !",
|
||||
"Une mise à jour est disponible, souhaitez-vous l'installer ?": "An update is available, do you want to install it ?",
|
||||
"Téléchargement de Updater en cours...": "Downloading the Updater...",
|
||||
"fin du téléchargement, début de l'extraction...": "end of the download, extracting...",
|
||||
"fin de l'extraction": "finished extracting",
|
||||
"lancement de l'application...": "starting application...",
|
||||
"Modification de": "Modifying",
|
||||
"Recompilation de": "Recompilating",
|
||||
"Conversion en": "Converting to",
|
||||
"Changement de l'ID du jeu": "editing game's ID",
|
||||
"Fin": "End",
|
||||
"L'installation est terminé !": "The mod has been installed !",
|
||||
"Conversion des fichiers": "Converting files",
|
||||
"Conversion des images": "Converting images",
|
||||
"Conversion des textes": "Converting texts",
|
||||
"Conversion des courses": "Converting races",
|
||||
"Configuration de LE-CODE": "Configurating LE-CODE"
|
||||
},
|
||||
"ge": {
|
||||
"Aléatoire: Toutes les pistes": "Zufällig: Alle Spuren",
|
||||
"Aléatoire: Pistes Originales": "Zufällig: Original-Spuren",
|
||||
"Aléatoire: Custom Tracks": "Zufällig: Custom Tracks",
|
||||
"Aléatoire: Pistes Nouvelles": "Zufällig: Neue Spuren"
|
||||
},
|
||||
"it": {
|
||||
"Aléatoire: Toutes les pistes": "Casuale: Tutte le tracce",
|
||||
"Aléatoire: Pistes Originales": "Casuale: Tracce originali",
|
||||
"Aléatoire: Custom Tracks": "Casuale: Custom Tracks",
|
||||
"Aléatoire: Pistes Nouvelles": "Casuale: Nuovi brani"
|
||||
},
|
||||
"sp": {
|
||||
"Aléatoire: Toutes les pistes": "Aleatorio: Todas las pistas",
|
||||
"Aléatoire: Pistes Originales": "Aleatorio: Pistas originales",
|
||||
"Aléatoire: Custom Tracks": "Aleatorio: Custom Tracks",
|
||||
"Aléatoire: Pistes Nouvelles": "Aleatorio: Pistas nuevas"
|
||||
}
|
||||
}
|
8
version
8
version
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"version": "0.6",
|
||||
"subversion": "1",
|
||||
"changelog": "- JAP, USA and KOR version are now supported by the installer !",
|
||||
"download_bin": "https://github.com/Faraphel/MKWF-Install/releases/download/0.6.1/MKWF.v0.6.1.zip",
|
||||
"version": "0.7",
|
||||
"subversion": "0",
|
||||
"changelog": "- \"CNR Outer Space Chase\" avait le préfix \"CTR\", rendant la course inutilisable\n- \"SADX Twinkle Circuit\" avaient le préfix \"SHR\", rendant les courses inutilisables\n- Si une course n'est pas trouvée, elle sera téléchargée depuis le github -> les mises à jour seront bien plus légère car vous ne devrez pas retélécharger toutes les courses. Elles seront également retéléchargées si leur taille ne correspond pas à leur version github\n- le code patch_file.py a été divisé en plusieurs fichier pour simplifier le code\n- Update.exe a été recompilé avec la nouvelle version de cx_freeze pour corriger le problème des dossiers non-ASCII\n- Correction de traduction oubliée\n- Ajout d'une barre de menus, où a été déplacé le langage, le format de sortie et de nouvelles options avancé\n\n- \"CNR Outer Space Chase\" had \"CTR\" prefix, making the map unusable\n- \"SADX Twinkle Circuit\" all had \"SHR\" prefix, making the tracks unusable\n- If a track is not found, the program will download it from the github -> update could be much lighter because you won't have to redownload all tracks. They will also be redownloaded if their size doesn't match with their github one\n- Splitted patch_file.py into multiple file to make the code more readable\n- Recompiled Update.exe with new cx_freeze version to fix issue with non-ASCII directory\n- Fixed missing translation\n- Added a menu bar, moved it language, output format and added new advanced option",
|
||||
"download_bin": "https://github.com/Faraphel/MKWF-Install/releases/download/0.7/MKWF.v0.7.zip",
|
||||
"updater_bin": "https://github.com/Faraphel/MKWF-Install/raw/master/Updater/Updater.zip"
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue