merged a maximum of source file with object (object will be re-separated in multiple folder next commit)

This commit is contained in:
raphael60650 2021-07-17 23:32:53 +02:00
parent 2990b1a652
commit d9b9f56169
17 changed files with 605 additions and 623 deletions

View file

@ -1,37 +1,4 @@
from tkinter import *
from PIL import Image, ImageFont, ImageDraw
from tkinter import messagebox, filedialog, ttk
from threading import Thread
import subprocess
import traceback
import requests
import zipfile
import shutil
import json
import glob
import math
import os
from source.Gui import Gui
from source.definition import *
class ClassApp():
from source.__init__ import __init__
from source.translate import translate
from source.Progress import Progress
from source.check_update import check_update
from source.StateButton import StateButton
from source.patch_file import patch_file
from source.patch_bmg import patch_bmg
from source.restart import restart
from source.patch_img_desc import patch_img_desc
from source.log_error import log_error
from source.patch_track import patch_track
from source.patch_image import patch_image
from source.Option import Option
from source.CT_Config import CT_Config
from source.Game import Game, InvalidGamePath, InvalidFormat
App = ClassApp()
App.root.mainloop()
gui = Gui()
gui.root.mainloop()

View file

@ -1,6 +1,8 @@
from . import wszst
from .definition import *
from threading import Thread
from PIL import Image
import subprocess
import shutil
import json
@ -25,6 +27,263 @@ class InvalidFormat(Exception):
super().__init__("This game format is not supported !")
class TooMuchDownloadFailed(Exception):
def __init__(self):
super().__init__("Too much download failed !")
class TooMuchSha1CheckFailed(Exception):
def __init__(self):
super().__init__("Too much sha1 check failed !")
class CantConvertTrack(Exception):
def __init__(self):
super().__init__("Can't convert track, check if download are enabled.")
def patch_img_desc(img_desc_path: str = "./file/img_desc", dest_dir: str = "./file"):
il = Image.open(img_desc_path+"/illustration.png")
il_16_9 = il.resize((832, 456))
il_4_3 = il.resize((608, 456))
for file_lang in glob.glob(img_desc_path+"??.png"):
img_lang = Image.open(file_lang)
img_lang_16_9 = img_lang.resize((832, 456))
img_lang_4_3 = img_lang.resize((608, 456))
new_16_9 = Image.new("RGBA", (832, 456), (0, 0, 0, 255))
new_16_9.paste(il_16_9, (0, 0), il_16_9)
new_16_9.paste(img_lang_16_9, (0, 0), img_lang_16_9)
new_16_9.save(dest_dir+f"/strapA_16_9_832x456{get_filename(get_nodir(file_lang))}.png")
new_4_3 = Image.new("RGBA", (608, 456), (0, 0, 0, 255))
new_4_3.paste(il_4_3, (0, 0), il_4_3)
new_4_3.paste(img_lang_4_3, (0, 0), img_lang_4_3)
new_4_3.save(dest_dir+f"/strapA_608x456{get_filename(get_nodir(file_lang))}.png")
def patch_image(fc, gui):
for i, file in enumerate(fc["img"]):
gui.progress(statut=gui.translate("Converting 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)
def patch_bmg(gamefile: str, gui): # gamefile est le fichier .szs trouvé dans le /files/Scene/UI/ du jeu
NINTENDO_CWF_REPLACE = "Wiimmfi"
MAINMENU_REPLACE = f"MKWFaraphel {gui.ctconfig.version}"
menu_replacement = {
"CWF de Nintendo": NINTENDO_CWF_REPLACE,
"Wi-Fi Nintendo": NINTENDO_CWF_REPLACE,
"CWF Nintendo": NINTENDO_CWF_REPLACE,
"Nintendo WFC": NINTENDO_CWF_REPLACE,
"Wi-Fi": NINTENDO_CWF_REPLACE,
"インターネット": NINTENDO_CWF_REPLACE,
"Menu principal": MAINMENU_REPLACE,
"Menú principal": MAINMENU_REPLACE,
"Main Menu": MAINMENU_REPLACE,
"トップメニュー": MAINMENU_REPLACE,
"Mario Kart Wii": MAINMENU_REPLACE,
}
bmglang = gamefile[-len("E.txt"):-len(".txt")] # Langue du fichier
gui.progress(statut=gui.translate("Patching text", " ", 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))
# Menu.bmg
bmgmenu = subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(gamefile) + ".d/message/Menu.bmg"],
creationflags=CREATE_NO_WINDOW, cwd=get_dir(gamefile),
check=True, stdout=subprocess.PIPE).stdout.decode()
# Common.bmg
bmgtracks = subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(gamefile) + ".d/message/Common.bmg"],
creationflags=CREATE_NO_WINDOW, cwd=get_dir(gamefile),
check=True, stdout=subprocess.PIPE).stdout.decode()
trackheader = "#--- standard track names"
trackend = "2328"
bmgtracks = bmgtracks[bmgtracks.find(trackheader) + len(trackheader):bmgtracks.find(trackend)]
with open("./file/ExtraCommon.txt", "w", encoding="utf8") as f:
f.write("#BMG\n\n"
f" 703e\t= \\\\c{{white}}{gui.translate('Random: All tracks', lang=bmglang)}\n"
f" 703f\t= \\\\c{{white}}{gui.translate('Random: Original tracks', lang=bmglang)}\n"
f" 7040\t= \\\\c{{white}}{gui.translate('Random: Custom Tracks', lang=bmglang)}\n"
f" 7041\t= \\\\c{{white}}{gui.translate('Random: New tracks', lang=bmglang)}\n")
for bmgtrack in bmgtracks.split("\n"):
if "=" in bmgtrack:
prefix = ""
if "T" in bmgtrack[:bmgtrack.find("=")]:
sTid = bmgtrack.find("T")
Tid = bmgtrack[sTid:sTid + 3]
if Tid[1] in "1234":
prefix = trackname_color["Wii"] + " " # Si la course est original à la wii
Tid = hex(bmgID_track_move[Tid])[2:]
else: # Arena
sTid = bmgtrack.find("U") + 1
Tid = bmgtrack[sTid:sTid + 2]
Tid = hex((int(Tid[0]) - 1) * 5 + (int(Tid[1]) - 1) + 0x7020)[2:]
Tname = bmgtrack[bmgtrack.find("= ") + 2:]
f.write(f" {Tid}\t= {prefix}{Tname}\n")
if not (os.path.exists("./file/tmp/")): os.makedirs("./file/tmp/")
filecopy(gamefile + ".d/message/Common.bmg", "./file/tmp/Common.bmg")
bmgcommon = subprocess.run(
["tools/szs/wctct", "bmg", "--le-code", "--long", "./file/CTFILE.txt", "--patch-bmg",
"OVERWRITE=./file/tmp/Common.bmg", "--patch-bmg", "OVERWRITE=./file/ExtraCommon.txt"],
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
rbmgcommon = subprocess.run(
["tools/szs/wctct", "bmg", "--le-code", "--long", "./file/RCTFILE.txt", "--patch-bmg",
"OVERWRITE=./file/tmp/Common.bmg", "--patch-bmg", "OVERWRITE=./file/ExtraCommon.txt"],
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
shutil.rmtree(gamefile + ".d")
os.remove("./file/tmp/Common.bmg")
os.remove("./file/ExtraCommon.txt")
def finalise(file, bmgtext, replacement_list=None):
if replacement_list:
for text, colored_text in replacement_list.items(): bmgtext = bmgtext.replace(text, colored_text)
with open(file, "w", encoding="utf-8") as f:
f.write(bmgtext)
subprocess.run(["./tools/szs/wbmgt", "ENCODE", get_nodir(file), "--overwrite"],
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
os.remove(file)
finalise(f"./file/Menu_{bmglang}.txt", bmgmenu, menu_replacement)
finalise(f"./file/Common_{bmglang}.txt", bmgcommon)
finalise(f"./file/Common_R{bmglang}.txt", rbmgcommon)
def patch_track(gui):
max_process = gui.intvar_process_track.get()
process_list = {}
error_count, error_max = 0, 3
def add_process(track):
nonlocal error_count, error_max, process_list
track_file = track.get_track_name()
total_track = len(gui.ctconfig.all_tracks)
process_list[track_file] = None # Used for showing track in progress even if there's no process
gui.progress(statut=gui.translate("Converting tracks", f"\n({i + 1}/{total_track})\n",
"\n".join(process_list.keys())), add=1)
for _track in [track.file_szs, track.file_wu8]:
if os.path.exists(_track):
if os.path.getsize(_track) < 1000: # File under this size are corrupted
os.remove(_track)
if not gui.boolvar_disable_download.get():
while True:
download_returncode = track.download_wu8()
if download_returncode == -1: # can't download
error_count += 1
if error_count > error_max: # Too much track wasn't correctly converted
"""messagebox.showerror(
gui.translate("Error"),
gui.translate("Too much tracks had a download issue."))
return -1"""
raise TooMuchDownloadFailed()
else:
"""messagebox.showwarning(gui.translate("Warning"),
gui.translate("Can't download this track !",
f" ({error_count} / {error_max})"))"""
elif download_returncode == 2:
break # if download is disabled, do not check sha1
if track.sha1:
if not gui.boolvar_dont_check_track_sha1.get():
if not track.check_sha1(): # Check si le sha1 du fichier est le bon
error_count += 1
if error_count > error_max: # Too much track wasn't correctly converted
"""messagebox.showerror(
gui.translate("Error"),
gui.translate("Too much tracks had an issue during sha1 check."))"""
raise TooMuchSha1CheckFailed()
continue
break
if not (
os.path.exists(track.file_szs)) or download_returncode == 3: # returncode 3 is track has been updated
if os.path.exists(track.file_wu8):
process_list[track_file] = track.convert_wu8_to_szs()
else:
"""messagebox.showerror(gui.translate("Error"),
gui.translate("Can't convert track.\nEnable track download and retry."))"""
raise CantConvertTrack()
elif gui.boolvar_del_track_after_conv.get():
os.remove(track.file_wu8)
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:
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(track.file_szs)
error_count += 1
if error_count > error_max: # Too much track wasn't correctly converted
"""messagebox.showerror(
gui.translate("Error"),
gui.translate("Too much track had a conversion issue."))"""
raise CantConvertTrack
else: # if the error max hasn't been reach
"""messagebox.showwarning(
gui.translate("Warning"),
gui.translate("The track", " ", track.file_wu8,
"do not have been properly converted.",
f" ({error_count} / {error_max})"))"""
else:
if gui.boolvar_del_track_after_conv.get(): os.remove(track.file_wu8)
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(gui.ctconfig.all_tracks):
while True:
if len(process_list) < max_process:
returncode = add_process(track)
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
class Game:
def __init__(self, path: str, region_ID: str = "P", game_ID: str = "RMCP01"):
if not os.path.exists(path): raise InvalidGamePath()
@ -105,10 +364,10 @@ class Game:
###
extracted_file = []
max_step += 4 # PATCH main.dol and PATCH lecode.bin, converting, changing ID
# self.Progress(show=True, indeter=False, statut=self.translate("Installing mod"), max=max_step, step=0)
gui.progress(show=True, indeter=False, statut=gui.translate("Installing mod"), max=max_step, step=0)
def replace_file(path, file, subpath="/"):
# self.Progress(statut=self.translate("Editing", "\n", get_nodir(path)), add=1)
gui.progress(statut=gui.translate("Editing", "\n", get_nodir(path)), add=1)
extension = get_extension(path)
if extension == "szs":
@ -142,18 +401,18 @@ class Game:
for ffp in fs[fp][nf]: replace_file(path=f, subpath=nf, file=ffp)
for file in extracted_file:
# self.Progress(statut=self.translate("Recompilating", "\n", get_nodir(file)), add=1)
gui.progress(statut=gui.translate("Recompilating", "\n", get_nodir(file)), add=1)
subprocess.run(["./tools/szs/wszst", "CREATE", get_nodir(file) + ".d", "-d", get_nodir(file),
"--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
check=True, stdout=subprocess.PIPE)
if os.path.exists(file + ".d"): shutil.rmtree(file + ".d")
# self.Progress(statut=self.translate("Patch main.dol"), add=1)
gui.progress(statut=gui.translate("Patch main.dol"), add=1)
subprocess.run(["./tools/szs/wstrt", "patch", get_nodir(self.path) + "/sys/main.dol", "--clean-dol",
"--add-lecode"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path),
check=True, stdout=subprocess.PIPE)
# self.Progress(statut=self.translate("Patch lecode.bin"), add=1)
gui.progress(statut=gui.translate("Patch lecode.bin"), add=1)
shutil.copytree("./file/Track/", self.path+"/files/Race/Course/", dirs_exist_ok=True)
if not(os.path.exists(self.path+"/tmp/")): os.makedirs(self.path+"/tmp/")
@ -171,7 +430,7 @@ class Game:
shutil.rmtree(self.path + "/tmp/")
output_format = gui.stringvar_game_format.get()
# self.Progress(statut=self.translate("Converting to", " ", output_format), add=1)
gui.progress(statut=gui.translate("Converting to", " ", output_format), add=1)
if output_format in ["ISO", "WBFS", "CISO"]:
path_game_format: str = os.path.realpath(self.path + "/../MKWFaraphel." + output_format.lower())
@ -182,17 +441,17 @@ class Game:
shutil.rmtree(self.path)
self.path = path_game_format
# self.Progress(statut=self.translate("Changing game's ID"), add=1)
gui.progress(statut=gui.translate("Changing game's ID"), add=1)
subprocess.run(["./tools/wit/wit", "EDIT", get_nodir(self.path), "--id",
f"RMC{self.region_ID}60", "--name",
f"Mario Kart Wii Faraphel {gui.ctconfig.version}", "--modify", "ALL"],
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path),
check=True, stdout=subprocess.PIPE)
# messagebox.showinfo(self.translate("End"), self.translate("The mod has been installed !"))
# messagebox.showinfo(gui.translate("End"), gui.translate("The mod has been installed !"))
except: pass # self.log_error()
finally: pass # self.Progress(show=False)
except: gui.log_error()
finally: gui.progress(show=False)
t = Thread(target=func)
t.setDaemon(True)
@ -204,3 +463,39 @@ class Game:
:param format: game format (ISO, WBFS, ...)
:return: converted game path
"""
def patch_file(self, gui):
def func():
try:
if not (os.path.exists("./file/Track-WU8/")): os.makedirs("./file/Track-WU8/")
with open("./convert_file.json") as f:
fc = json.load(f)
max_step = len(fc["img"]) + len(gui.ctconfig.all_tracks) + 3 + len("EGFIS")
gui.progress(show=True, indeter=False, statut=gui.translate("Converting files"), max=max_step, step=0)
gui.progress(statut=gui.translate("Configurating LE-CODE"), add=1)
gui.ctconfig.create_ctfile()
gui.progress(statut=gui.translate("Creating ct_icon.png"), add=1)
ct_icon = gui.ctconfig.get_cticon()
ct_icon.save("./file/ct_icons.tpl.png")
gui.progress(statut=gui.translate("Creating descriptive images"), add=1)
patch_img_desc()
patch_image(fc, gui)
for file in glob.glob(self.path + "/files/Scene/UI/MenuSingle_?.szs"): patch_bmg(file, gui)
# MenuSingle could be any other file, Common and Menu are all the same in all other files.
self.patch_autoadd()
if patch_track(gui) != 0: return
gui.button_install_mod.grid(row=2, column=1, columnspan=2, sticky="NEWS")
gui.button_install_mod.config(
text=gui.translate("Install mod", " (v", gui.ctconfig.version, ")"))
except: gui.log_error()
finally: gui.progress(show=False)
t = Thread(target=func)
t.setDaemon(True)
t.start()
return t

285
source/Gui.py Normal file
View file

@ -0,0 +1,285 @@
from tkinter import *
from tkinter import messagebox, filedialog, ttk
from threading import Thread
import subprocess
import traceback
import glob
import os
from .definition import *
from .CT_Config import *
from .Option import *
from .Game import *
with open("./translation.json", encoding="utf-8") as f:
translation_dict = json.load(f)
def restart():
subprocess.Popen([sys.executable] + sys.argv, creationflags=CREATE_NO_WINDOW, cwd=os.getcwd())
exit()
class Gui():
def __init__(self):
self.root = Tk()
self.option = Option()
self.option.load_from_file("./option.json")
self.ctconfig = CT_Config()
self.ctconfig.load_ctconfig_file("./ct_config.json")
self.is_dev_version = False # Is this installer version a dev ?
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.boolvar_dont_check_track_sha1 = BooleanVar(value=self.option.dont_check_track_sha1)
self.intvar_process_track = IntVar(value=self.option.process_track)
self.boolvar_use_1star_track = BooleanVar(value=True)
self.boolvar_use_2star_track = BooleanVar(value=True)
self.boolvar_use_3star_track = BooleanVar(value=True)
self.stringvar_mark_track_from_version = StringVar(value="None")
self.root.title(self.translate("MKWFaraphel Installer"))
self.root.resizable(False, False)
self.root.iconbitmap(bitmap="./icon.ico")
if not(self.boolvar_dont_check_for_update.get()): self.check_update()
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("Language"), menu=self.menu_language)
self.menu_language.add_radiobutton(label="Français", variable=self.stringvar_language, value="fr", command=lambda: self.option.edit("language", "fr", restart=True))
self.menu_language.add_radiobutton(label="English", variable=self.stringvar_language, value="en", command=lambda: self.option.edit("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 (Directory)"), variable=self.stringvar_game_format, value="FST", command=lambda: self.option.edit("format", "FST"))
self.menu_format.add_radiobutton(label="ISO", variable=self.stringvar_game_format, value="ISO", command=lambda: self.option.edit("format", "ISO"))
self.menu_format.add_radiobutton(label="CISO", variable=self.stringvar_game_format, value="CISO", command=lambda: self.option.edit("format", "CISO"))
self.menu_format.add_radiobutton(label="WBFS", variable=self.stringvar_game_format, value="WBFS", command=lambda: self.option.edit("format", "WBFS"))
self.menu_trackselection = Menu(self.menu_bar, tearoff=0)
self.menu_bar.add_cascade(label=self.translate("Track selection"), menu=self.menu_trackselection)
self.menu_trackselection.add_checkbutton(label=self.translate("Select"," 1 ","star"), variable=self.boolvar_use_1star_track)
self.menu_trackselection.add_checkbutton(label=self.translate("Select"," 2 ","stars"), variable=self.boolvar_use_2star_track)
self.menu_trackselection.add_checkbutton(label=self.translate("Select"," 3 ","stars"), variable=self.boolvar_use_3star_track)
self.menu_trackselection.add_separator()
self.menu_marktrackversion = Menu(self.menu_trackselection, tearoff=0)
self.menu_trackselection.add_cascade(label=self.translate("Mark all tracks from version"), menu=self.menu_marktrackversion)
self.menu_marktrackversion.add_radiobutton(label=self.translate("None"), variable=self.stringvar_mark_track_from_version, value="None")
for version in self.ctconfig.all_version:
self.menu_marktrackversion.add_radiobutton(label=f"v{version}", variable=self.stringvar_mark_track_from_version, value=version)
self.menu_advanced = Menu(self.menu_bar, tearoff=0)
self.menu_bar.add_cascade(label=self.translate("Advanced"), menu=self.menu_advanced)
self.menu_advanced.add_checkbutton(label=self.translate("Disable downloads"), variable=self.boolvar_disable_download, command=lambda: self.option.edit("disable_download", self.boolvar_disable_download))
self.menu_advanced.add_checkbutton(label=self.translate("Delete track after wu8 to szs conversion"), variable=self.boolvar_del_track_after_conv, command=lambda: self.option.edit("del_track_after_conv", self.boolvar_del_track_after_conv))
self.menu_advanced.add_checkbutton(label=self.translate("Don't check for update"), variable=self.boolvar_dont_check_for_update, command=lambda: self.option.edit("dont_check_for_update", self.boolvar_dont_check_for_update))
self.menu_advanced.add_checkbutton(label=self.translate("Don't check track's sha1"), variable=self.boolvar_dont_check_track_sha1, command=lambda: self.option.edit("dont_check_track_sha1",self.boolvar_dont_check_track_sha1))
self.menu_advanced.add_separator()
self.menu_advanced.add_command(label=self.translate("Number of track conversion process", " :"))
self.menu_advanced.add_radiobutton(label=self.translate("1 ", "process"), variable=self.intvar_process_track, value=1, command=lambda: self.option.edit("process_track", 1))
self.menu_advanced.add_radiobutton(label=self.translate("2 ", "process"), variable=self.intvar_process_track, value=2, command=lambda: self.option.edit("process_track", 2))
self.menu_advanced.add_radiobutton(label=self.translate("4 ", "process"), variable=self.intvar_process_track, value=4, command=lambda: self.option.edit("process_track", 4))
self.menu_advanced.add_radiobutton(label=self.translate("8 ", "process"), variable=self.intvar_process_track, value=8, command=lambda: self.option.edit("process_track", 8))
self.frame_language = Frame(self.root)
self.frame_language.grid(row=1, column=1, sticky="E")
self.frame_game_path = LabelFrame(self.root, text=self.translate("Original game"))
self.frame_game_path.grid(row=2, column=1)
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=((self.translate("Wii game"),
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")
self.frame_game_path_action = Frame(self.frame_game_path) # Extract and do everything button
self.frame_game_path_action.grid(row=2, column=1, columnspan=2, sticky="NEWS")
self.frame_game_path_action.columnconfigure(1, weight=1)
def use_path():
def func():
self.frame_action.grid_forget()
try:
self.game = Game(path = entry_game_path.get())
self.progress(show=True, indeter=True, statut=self.translate("Extracting the game..."))
self.game.extract_game()
self.frame_action.grid(row=3, column=1, sticky="NEWS")
except InvalidGamePath:
messagebox.showerror(self.translate("Error"), self.translate("The file path in invalid"))
except InvalidFormat:
messagebox.showerror(self.translate("Error"), self.translate("This game's format is invalid"))
except:
self.log_error()
finally:
self.progress(show=False)
t = Thread(target=func)
t.setDaemon(True)
t.start()
return t
self.button_game_extract = Button(self.frame_game_path_action, text=self.translate("Extract file"),
relief=RIDGE, command=use_path)
self.button_game_extract.grid(row=1, column=1, sticky="NEWS")
def do_everything():
def func():
use_path().join()
self.game.patch_file(gui).join()
self.game.install_mod(self).join()
if messagebox.askyesno(self.translate("Experimental functionality"),
self.translate("This will extract the selected ROM, prepare files and install mod. "
"Do you wish to continue ?")):
t = Thread(target=func)
t.setDaemon(True)
t.start()
self.button_do_everything = Button(self.frame_game_path_action, text=self.translate("Do everything"), relief=RIDGE, command=do_everything)
self.button_do_everything.grid(row=1, column=2, sticky="NEWS")
self.frame_action = LabelFrame(self.root, text=self.translate("Action"))
self.button_prepare_file = Button(self.frame_action, text=self.translate("Prepare files"), relief=RIDGE, command=lambda: self.game.patch_file(self), width=45)
self.button_prepare_file.grid(row=1, column=1, columnspan=2, sticky="NEWS")
self.button_install_mod = Button(self.frame_action, text=self.translate("Install mod"), relief=RIDGE, command=lambda: self.game.install_mod(self), width=45)
# Install mod button will only appear after prepare file step
self.progressbar = ttk.Progressbar(self.root)
self.progresslabel = Label(self.root)
def check_update(self):
try:
gitversion = requests.get(VERSION_FILE_URL, allow_redirects=True).json()
with open("./version", "rb") as f:
locversion = json.load(f)
if ((float(gitversion["version"]) > float(locversion["version"])) or # if github version is newer than
(float(gitversion["version"]) == float(locversion["version"])) and # local version
float(gitversion["subversion"]) > float(locversion["subversion"])):
if messagebox.askyesno(
self.translate("Update available !"),
self.translate("An update is available, do you want to install it ?",
f"\n\nVersion : {locversion['version']}.{locversion['subversion']} -> "
f"{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(self.translate("Downloading the Updater..."))
file.write(dl.content)
print(self.translate("end of the download, extracting..."))
with zipfile.ZipFile("./download.zip") as file:
file.extractall("./Updater/")
print(self.translate("finished extracting"))
os.remove("./download.zip")
print(self.translate("starting application..."))
os.startfile(os.path.realpath("./Updater/Updater.exe"))
if ((float(gitversion["version"]) < float(locversion["version"])) or # if local version is newer than
(float(gitversion["version"]) == float(locversion["version"])) and # github version
float(gitversion["subversion"]) < float(locversion["subversion"])):
self.is_dev_version = True
except requests.ConnectionError:
messagebox.showwarning(self.translate("Warning"),
self.translate("Can't connect to internet. Download will be disabled."))
self.option.disable_download = True
except:
self.log_error()
def log_error(func):
try:
func()
except Exception:
error = traceback.format_exc()
with open("./error.log", "a") as f:
f.write(f"---\n{error}\n")
messagebox.showerror(self.translate("Error"), self.translate("An error occured", " :", "\n", error, "\n\n"))
def translate(self, *texts, lang=None):
if lang is None:
lang = self.stringvar_language.get()
elif lang == "F":
lang = "fr"
elif lang == "G":
lang = "ge"
elif lang == "I":
lang = "it"
elif lang == "S":
lang = "sp"
if lang in translation_dict:
_lang_trad = translation_dict[lang]
translated_text = ""
for text in texts:
if text in _lang_trad:
translated_text += _lang_trad[text]
else:
translated_text += text
return translated_text
return "".join(texts) # if no translation language is found
def progress(self, show=None, indeter=None, step=None, statut=None, max=None, add=None):
if indeter is True:
self.progressbar.config(mode="indeterminate")
self.progressbar.start(50)
elif indeter is False:
self.progressbar.config(mode="determinate")
self.progressbar.stop()
if show is True:
self.state_button(enable=False)
self.progressbar.grid(row=100, column=1, sticky="NEWS")
self.progresslabel.grid(row=101, column=1, sticky="NEWS")
elif show is False:
self.state_button(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 state_button(self, enable=True):
button = [
self.button_game_extract,
self.button_install_mod,
self.button_prepare_file,
self.button_do_everything
]
for widget in button:
if enable:
widget.config(state=NORMAL)
else:
widget.config(state=DISABLED)

View file

@ -1,22 +0,0 @@
def Progress(self, show=None, indeter=None, step=None, statut=None, max=None, add=None):
if indeter is True:
self.progressbar.config(mode="indeterminate")
self.progressbar.start(50)
elif indeter is False:
self.progressbar.config(mode="determinate")
self.progressbar.stop()
if show is 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 is 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)

View file

@ -1,15 +0,0 @@
from tkinter import *
def StateButton(self, enable=True):
button = [
self.button_game_extract,
self.button_install_mod,
self.button_prepare_file,
self.button_do_everything
]
for widget in button:
if enable:
widget.config(state=NORMAL)
else:
widget.config(state=DISABLED)

View file

@ -1,157 +0,0 @@
from tkinter import *
from tkinter import messagebox, filedialog, ttk
from threading import Thread
import subprocess
import glob
import os
from .definition import *
from .check_update import check_update
from .translate import translate
from .CT_Config import *
from .Option import *
from .Game import *
def __init__(self):
self.root = Tk()
self.option = Option()
self.option.load_from_file("./option.json")
self.ctconfig = CT_Config()
self.ctconfig.load_ctconfig_file("./ct_config.json")
self.is_dev_version = False # Is this installer version a dev ?
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.boolvar_dont_check_track_sha1 = BooleanVar(value=self.option.dont_check_track_sha1)
self.intvar_process_track = IntVar(value=self.option.process_track)
self.boolvar_use_1star_track = BooleanVar(value=True)
self.boolvar_use_2star_track = BooleanVar(value=True)
self.boolvar_use_3star_track = BooleanVar(value=True)
self.stringvar_mark_track_from_version = StringVar(value="None")
self.root.title(self.translate("MKWFaraphel Installer"))
self.root.resizable(False, False)
self.root.iconbitmap(bitmap="./icon.ico")
if not(self.boolvar_dont_check_for_update.get()): self.check_update()
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("Language"), menu=self.menu_language)
self.menu_language.add_radiobutton(label="Français", variable=self.stringvar_language, value="fr", command=lambda: self.option.edit("language", "fr", restart=True))
self.menu_language.add_radiobutton(label="English", variable=self.stringvar_language, value="en", command=lambda: self.option.edit("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 (Directory)"), variable=self.stringvar_game_format, value="FST", command=lambda: self.option.edit("format", "FST"))
self.menu_format.add_radiobutton(label="ISO", variable=self.stringvar_game_format, value="ISO", command=lambda: self.option.edit("format", "ISO"))
self.menu_format.add_radiobutton(label="CISO", variable=self.stringvar_game_format, value="CISO", command=lambda: self.option.edit("format", "CISO"))
self.menu_format.add_radiobutton(label="WBFS", variable=self.stringvar_game_format, value="WBFS", command=lambda: self.option.edit("format", "WBFS"))
self.menu_trackselection = Menu(self.menu_bar, tearoff=0)
self.menu_bar.add_cascade(label=self.translate("Track selection"), menu=self.menu_trackselection)
self.menu_trackselection.add_checkbutton(label=self.translate("Select"," 1 ","star"), variable=self.boolvar_use_1star_track)
self.menu_trackselection.add_checkbutton(label=self.translate("Select"," 2 ","stars"), variable=self.boolvar_use_2star_track)
self.menu_trackselection.add_checkbutton(label=self.translate("Select"," 3 ","stars"), variable=self.boolvar_use_3star_track)
self.menu_trackselection.add_separator()
self.menu_marktrackversion = Menu(self.menu_trackselection, tearoff=0)
self.menu_trackselection.add_cascade(label=self.translate("Mark all tracks from version"), menu=self.menu_marktrackversion)
self.menu_marktrackversion.add_radiobutton(label=self.translate("None"), variable=self.stringvar_mark_track_from_version, value="None")
for version in self.ctconfig.all_version:
self.menu_marktrackversion.add_radiobutton(label=f"v{version}", variable=self.stringvar_mark_track_from_version, value=version)
self.menu_advanced = Menu(self.menu_bar, tearoff=0)
self.menu_bar.add_cascade(label=self.translate("Advanced"), menu=self.menu_advanced)
self.menu_advanced.add_checkbutton(label=self.translate("Disable downloads"), variable=self.boolvar_disable_download, command=lambda: self.option.edit("disable_download", self.boolvar_disable_download))
self.menu_advanced.add_checkbutton(label=self.translate("Delete track after wu8 to szs conversion"), variable=self.boolvar_del_track_after_conv, command=lambda: self.option.edit("del_track_after_conv", self.boolvar_del_track_after_conv))
self.menu_advanced.add_checkbutton(label=self.translate("Don't check for update"), variable=self.boolvar_dont_check_for_update, command=lambda: self.option.edit("dont_check_for_update", self.boolvar_dont_check_for_update))
self.menu_advanced.add_checkbutton(label=self.translate("Don't check track's sha1"), variable=self.boolvar_dont_check_track_sha1, command=lambda: self.option.edit("dont_check_track_sha1",self.boolvar_dont_check_track_sha1))
self.menu_advanced.add_separator()
self.menu_advanced.add_command(label=self.translate("Number of track conversion process", " :"))
self.menu_advanced.add_radiobutton(label=self.translate("1 ", "process"), variable=self.intvar_process_track, value=1, command=lambda: self.option.edit("process_track", 1))
self.menu_advanced.add_radiobutton(label=self.translate("2 ", "process"), variable=self.intvar_process_track, value=2, command=lambda: self.option.edit("process_track", 2))
self.menu_advanced.add_radiobutton(label=self.translate("4 ", "process"), variable=self.intvar_process_track, value=4, command=lambda: self.option.edit("process_track", 4))
self.menu_advanced.add_radiobutton(label=self.translate("8 ", "process"), variable=self.intvar_process_track, value=8, command=lambda: self.option.edit("process_track", 8))
self.frame_language = Frame(self.root)
self.frame_language.grid(row=1, column=1, sticky="E")
self.frame_game_path = LabelFrame(self.root, text=self.translate("Original game"))
self.frame_game_path.grid(row=2, column=1)
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=((self.translate("Wii game"),
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")
self.frame_game_path_action = Frame(self.frame_game_path) # Extract and do everything button
self.frame_game_path_action.grid(row=2, column=1, columnspan=2, sticky="NEWS")
self.frame_game_path_action.columnconfigure(1, weight=1)
def use_path():
def func():
self.frame_action.grid_forget()
try:
self.game = Game(path = entry_game_path.get())
self.Progress(show=True, indeter=True, statut=self.translate("Extracting the game..."))
self.game.extract_game()
self.frame_action.grid(row=3, column=1, sticky="NEWS")
except InvalidGamePath:
messagebox.showerror(self.translate("Error"), self.translate("The file path in invalid"))
except InvalidFormat:
messagebox.showerror(self.translate("Error"), self.translate("This game's format is invalid"))
except:
self.log_error()
finally:
self.Progress(show=False)
t = Thread(target=func)
t.setDaemon(True)
t.start()
return t
self.button_game_extract = Button(self.frame_game_path_action, text=self.translate("Extract file"),
relief=RIDGE, command=use_path)
self.button_game_extract.grid(row=1, column=1, sticky="NEWS")
def do_everything():
def func():
use_path().join()
self.patch_file().join()
self.game.install_mod(self).join()
if messagebox.askyesno(self.translate("Experimental functionality"),
self.translate("This will extract the selected ROM, prepare files and install mod. "
"Do you wish to continue ?")):
t = Thread(target=func)
t.setDaemon(True)
t.start()
self.button_do_everything = Button(self.frame_game_path_action, text=self.translate("Do everything"), relief=RIDGE, command=do_everything)
self.button_do_everything.grid(row=1, column=2, sticky="NEWS")
self.frame_action = LabelFrame(self.root, text=self.translate("Action"))
self.button_prepare_file = Button(self.frame_action, text=self.translate("Prepare files"), relief=RIDGE, command=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("Install mod"), relief=RIDGE, command=lambda: self.game.install_mod(self), width=45)
# Install mod button will only appear after prepare file step
self.progressbar = ttk.Progressbar(self.root)
self.progresslabel = Label(self.root)

View file

@ -1,51 +0,0 @@
from tkinter import messagebox
import requests
import zipfile
import json
import os
from .definition import *
def check_update(self):
try:
gitversion = requests.get(VERSION_FILE_URL, allow_redirects=True).json()
with open("./version", "rb") as f:
locversion = json.load(f)
if ((float(gitversion["version"]) > float(locversion["version"])) or # if github version is newer than
(float(gitversion["version"]) == float(locversion["version"])) and # local version
float(gitversion["subversion"]) > float(locversion["subversion"])):
if messagebox.askyesno(
self.translate("Update available !"),
self.translate("An update is available, do you want to install it ?",
f"\n\nVersion : {locversion['version']}.{locversion['subversion']} -> "
f"{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(self.translate("Downloading the Updater..."))
file.write(dl.content)
print(self.translate("end of the download, extracting..."))
with zipfile.ZipFile("./download.zip") as file:
file.extractall("./Updater/")
print(self.translate("finished extracting"))
os.remove("./download.zip")
print(self.translate("starting application..."))
os.startfile(os.path.realpath("./Updater/Updater.exe"))
if ((float(gitversion["version"]) < float(locversion["version"])) or # if local version is newer than
(float(gitversion["version"]) == float(locversion["version"])) and # github version
float(gitversion["subversion"]) < float(locversion["subversion"])):
self.is_dev_version = True
except requests.ConnectionError:
messagebox.showwarning(self.translate("Warning"),
self.translate("Can't connect to internet. Download will be disabled."))
self.option.disable_download = True
except: self.log_error()

View file

@ -24,6 +24,7 @@ bmgID_track_move = {
"T71": 0x7015, "T72": 0x701e, "T73": 0x701d, "T74": 0x7011,
"T81": 0x7018, "T82": 0x7016, "T83": 0x7013, "T84": 0x701c,
}
trackname_color = {
"MSRDS": "\\\\c{green}MSRDS\\\\c{off}",
"CTR": "\\\\c{YOR4}CTR\\\\c{off}",

View file

@ -1,9 +0,0 @@
import traceback
def log_error(func):
try: func()
except Exception:
error = traceback.format_exc()
with open("./error.log", "a") as f: f.write(f"---\n{error}\n")
# messagebox.showerror(self.translate("Error"), self.translate("An error occured", " :", "\n", error, "\n\n"))

View file

@ -1,102 +0,0 @@
import subprocess
import shutil
import os
from .definition import *
def patch_bmg(self, gamefile): # gamefile est le fichier .szs trouvé dans le /files/Scene/UI/ du jeu
try:
NINTENDO_CWF_REPLACE = "Wiimmfi"
MAINMENU_REPLACE = f"MKWFaraphel {self.ctconfig.version}"
menu_replacement = {
"CWF de Nintendo": NINTENDO_CWF_REPLACE,
"Wi-Fi Nintendo": NINTENDO_CWF_REPLACE,
"CWF Nintendo": NINTENDO_CWF_REPLACE,
"Nintendo WFC": NINTENDO_CWF_REPLACE,
"Wi-Fi": NINTENDO_CWF_REPLACE,
"インターネット": NINTENDO_CWF_REPLACE,
"Menu principal": MAINMENU_REPLACE,
"Menú principal": MAINMENU_REPLACE,
"Main Menu": MAINMENU_REPLACE,
"トップメニュー": MAINMENU_REPLACE,
"Mario Kart Wii": MAINMENU_REPLACE,
}
bmglang = gamefile[-len("E.txt"):-len(".txt")] # Langue du fichier
self.Progress(statut=self.translate("Patching text", " ", 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))
# Menu.bmg
bmgmenu = subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(gamefile) + ".d/message/Menu.bmg"],
creationflags=CREATE_NO_WINDOW, cwd=get_dir(gamefile),
check=True, stdout=subprocess.PIPE).stdout.decode()
# Common.bmg
bmgtracks = subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(gamefile) + ".d/message/Common.bmg"],
creationflags=CREATE_NO_WINDOW, cwd=get_dir(gamefile),
check=True, stdout=subprocess.PIPE).stdout.decode()
trackheader = "#--- standard track names"
trackend = "2328"
bmgtracks = bmgtracks[bmgtracks.find(trackheader) + len(trackheader):bmgtracks.find(trackend)]
with open("./file/ExtraCommon.txt", "w", encoding="utf8") as f:
f.write("#BMG\n\n"
f" 703e\t= \\\\c{{white}}{self.translate('Random: All tracks', lang=bmglang)}\n"
f" 703f\t= \\\\c{{white}}{self.translate('Random: Original tracks', lang=bmglang)}\n"
f" 7040\t= \\\\c{{white}}{self.translate('Random: Custom Tracks', lang=bmglang)}\n"
f" 7041\t= \\\\c{{white}}{self.translate('Random: New tracks', lang=bmglang)}\n")
for bmgtrack in bmgtracks.split("\n"):
if "=" in bmgtrack:
prefix = ""
if "T" in bmgtrack[:bmgtrack.find("=")]:
sTid = bmgtrack.find("T")
Tid = bmgtrack[sTid:sTid + 3]
if Tid[1] in "1234":
prefix = trackname_color["Wii"] + " " # Si la course est original à la wii
Tid = hex(bmgID_track_move[Tid])[2:]
else: # Arena
sTid = bmgtrack.find("U") + 1
Tid = bmgtrack[sTid:sTid + 2]
Tid = hex((int(Tid[0]) - 1) * 5 + (int(Tid[1]) - 1) + 0x7020)[2:]
Tname = bmgtrack[bmgtrack.find("= ") + 2:]
f.write(f" {Tid}\t= {prefix}{Tname}\n")
if not(os.path.exists("./file/tmp/")): os.makedirs("./file/tmp/")
filecopy(gamefile+".d/message/Common.bmg", "./file/tmp/Common.bmg")
bmgcommon = subprocess.run(
["tools/szs/wctct", "bmg", "--le-code", "--long", "./file/CTFILE.txt", "--patch-bmg",
"OVERWRITE=./file/tmp/Common.bmg", "--patch-bmg", "OVERWRITE=./file/ExtraCommon.txt"],
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
rbmgcommon = subprocess.run(
["tools/szs/wctct", "bmg", "--le-code", "--long", "./file/RCTFILE.txt", "--patch-bmg",
"OVERWRITE=./file/tmp/Common.bmg", "--patch-bmg", "OVERWRITE=./file/ExtraCommon.txt"],
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
shutil.rmtree(gamefile + ".d")
os.remove("./file/tmp/Common.bmg")
os.remove("./file/ExtraCommon.txt")
def finalise(file, bmgtext, replacement_list=None):
if replacement_list:
for text, colored_text in replacement_list.items(): bmgtext = bmgtext.replace(text, colored_text)
with open(file, "w", encoding="utf-8") as f: f.write(bmgtext)
subprocess.run(["./tools/szs/wbmgt", "ENCODE", get_nodir(file), "--overwrite"],
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
os.remove(file)
finalise(f"./file/Menu_{bmglang}.txt", bmgmenu, menu_replacement)
finalise(f"./file/Common_{bmglang}.txt", bmgcommon)
finalise(f"./file/Common_R{bmglang}.txt", rbmgcommon)
except:
self.log_error()

View file

@ -1,39 +0,0 @@
from threading import Thread
import json
import glob
import os
def patch_file(self):
def func():
try:
if not(os.path.exists("./file/Track-WU8/")): os.makedirs("./file/Track-WU8/")
with open("./convert_file.json") as f: fc = json.load(f)
max_step = len(fc["img"]) + len(self.ctconfig.all_tracks) + 3 + len("EGFIS")
self.Progress(show=True, indeter=False, statut=self.translate("Converting files"), max=max_step, step=0)
self.Progress(statut=self.translate("Configurating LE-CODE"), add=1)
self.ctconfig.create_ctfile()
self.Progress(statut=self.translate("Creating ct_icon.png"), add=1)
ct_icon = self.ctconfig.get_cticon()
ct_icon.save("./file/ct_icons.tpl.png")
self.Progress(statut=self.translate("Creating descriptive images"), add=1)
self.patch_img_desc()
self.patch_image(fc)
for file in glob.glob(self.game.path+"/files/Scene/UI/MenuSingle_?.szs"): self.patch_bmg(file)
# MenuSingle could be any other file, Common and Menu are all the same in all other files.
self.patch_autoadd()
if self.patch_track() != 0: return
self.button_install_mod.grid(row=2, column=1, columnspan=2, sticky="NEWS")
self.button_install_mod.config(text=self.translate("Install mod", " (v", self.ctconfig.version, ")"))
except: self.log_error()
finally: self.Progress(show=False)
t = Thread(target=func)
t.setDaemon(True)
t.start()
return t

View file

@ -1,9 +0,0 @@
from .definition import *
import subprocess
def patch_image(self, fc):
for i, file in enumerate(fc["img"]):
self.Progress(statut=self.translate("Converting 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)

View file

@ -1,29 +0,0 @@
from PIL import Image
import glob
from .definition import *
def patch_img_desc(self):
try:
il = Image.open("./file/img_desc/illustration.png")
il_16_9 = il.resize((832, 456))
il_4_3 = il.resize((608, 456))
for file_lang in glob.glob("./file/img_desc/??.png"):
img_lang = Image.open(file_lang)
img_lang_16_9 = img_lang.resize((832, 456))
img_lang_4_3 = img_lang.resize((608, 456))
new_16_9 = Image.new("RGBA", (832, 456), (0, 0, 0, 255))
new_16_9.paste(il_16_9, (0, 0), il_16_9)
new_16_9.paste(img_lang_16_9, (0, 0), img_lang_16_9)
new_16_9.save(f"./file/strapA_16_9_832x456{get_filename(get_nodir(file_lang))}.png")
new_4_3 = Image.new("RGBA", (608, 456), (0, 0, 0, 255))
new_4_3.paste(il_4_3, (0, 0), il_4_3)
new_4_3.paste(img_lang_4_3, (0, 0), img_lang_4_3)
new_4_3.save(f"./file/strapA_608x456{get_filename(get_nodir(file_lang))}.png")
except:
self.log_error()

View file

@ -1,110 +0,0 @@
from tkinter import messagebox
import os
def patch_track(self):
max_process = self.intvar_process_track.get()
process_list = {}
error_count, error_max = 0, 3
def add_process(track):
nonlocal error_count, error_max, process_list
track_file = track.get_track_name()
total_track = len(self.ctconfig.all_tracks)
process_list[track_file] = None # Used for showing track in progress even if there's no process
self.Progress(statut=self.translate("Converting tracks", f"\n({i + 1}/{total_track})\n",
"\n".join(process_list.keys())), add=1)
for _track in [track.file_szs, track.file_wu8]:
if os.path.exists(_track):
if os.path.getsize(_track) < 1000: # File under this size are corrupted
os.remove(_track)
if not self.boolvar_disable_download.get():
while True:
download_returncode = track.download_wu8()
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("Error"),
self.translate("Too much tracks had a download issue."))
return -1
else:
messagebox.showwarning(self.translate("Warning"),
self.translate("Can't download this track !",
f" ({error_count} / {error_max})"))
elif download_returncode == 2: break # if download is disabled, don't check sha1
if track.sha1:
if not self.boolvar_dont_check_track_sha1.get():
if not track.check_sha1(): # Check si le sha1 du fichier est le bon
error_count += 1
if error_count > error_max: # Too much track wasn't correctly converted
messagebox.showerror(
self.translate("Error"),
self.translate("Too much tracks had an issue during sha1 check."))
return -1
continue
break
if not (os.path.exists(track.file_szs)) or download_returncode == 3: # returncode 3 is track has been updated
if os.path.exists(track.file_wu8):
process_list[track_file] = track.convert_wu8_to_szs()
else:
messagebox.showerror(self.translate("Error"),
self.translate("Can't convert track.\nEnable track download and retry."))
return -1
elif self.boolvar_del_track_after_conv.get(): os.remove(track.file_wu8)
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:
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(track.file_szs)
error_count += 1
if error_count > error_max: # Too much track wasn't correctly converted
messagebox.showerror(
self.translate("Error"),
self.translate("Too much track had a conversion issue."))
return -1
else: # if the error max hasn't been reach
messagebox.showwarning(
self.translate("Warning"),
self.translate("The track", " ", track.file_wu8,
"do not have been properly converted.",
f" ({error_count} / {error_max})"))
else:
if self.boolvar_del_track_after_conv.get(): os.remove(track.file_wu8)
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(self.ctconfig.all_tracks):
while True:
if len(process_list) < max_process:
returncode = add_process(track)
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

View file

@ -1,10 +0,0 @@
import subprocess
import sys
import os
from .definition import *
def restart(self):
subprocess.Popen([sys.executable] + sys.argv, creationflags=CREATE_NO_WINDOW, cwd=os.getcwd())
sys.exit()

View file

@ -1,22 +0,0 @@
import json
with open("./translation.json", encoding="utf-8") as f:
translation_dict = json.load(f)
def translate(self, *texts, lang=None):
if lang is None: lang = self.stringvar_language.get()
elif lang == "F": lang = "fr"
elif lang == "G": lang = "ge"
elif lang == "I": lang = "it"
elif lang == "S": lang = "sp"
if lang in translation_dict:
_lang_trad = translation_dict[lang]
translated_text = ""
for text in texts:
if text in _lang_trad: translated_text += _lang_trad[text]
else: translated_text += text
return translated_text
return "".join(texts) # if no translation language is found

View file

@ -62,3 +62,12 @@ def edit(): pass
def autoadd(): pass
def bmg_decode(): pass
def bmg_encode(): pass
def wctct_bmg(): pass