mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-03 19:28:25 +02:00
added doctype and type hint to all function, replaced copyfile function by shutil.copyfile
This commit is contained in:
parent
a6ec86c61d
commit
fc3030532b
8 changed files with 195 additions and 83 deletions
|
@ -7,9 +7,9 @@ from .Cup import Cup
|
||||||
from .Track import Track
|
from .Track import Track
|
||||||
|
|
||||||
|
|
||||||
def get_cup_icon(id, font_path: str = "./file/SuperMario256.ttf", cup_icon_dir: str = "./file/cup_icon"):
|
def get_cup_icon(id, font_path: str = "./file/SuperMario256.ttf", cup_icon_dir: str = "./file/cup_icon") -> Image:
|
||||||
"""
|
"""
|
||||||
:param id:
|
:param id: id of the cup
|
||||||
:param cup_icon_dir: directory to cup icon
|
:param cup_icon_dir: directory to cup icon
|
||||||
:param font_path: path to the font used to generate icon
|
:param font_path: path to the font used to generate icon
|
||||||
:return: cup icon
|
:return: cup icon
|
||||||
|
@ -37,8 +37,9 @@ class CT_Config:
|
||||||
self.all_version = {version}
|
self.all_version = {version}
|
||||||
self.gui = gui
|
self.gui = gui
|
||||||
|
|
||||||
def add_ordered_cup(self, cup: Cup):
|
def add_ordered_cup(self, cup: Cup) -> None:
|
||||||
"""
|
"""
|
||||||
|
add a cup to the config
|
||||||
:param cup: a Cup object to add as an ordered cup
|
:param cup: a Cup object to add as an ordered cup
|
||||||
:return: ?
|
:return: ?
|
||||||
"""
|
"""
|
||||||
|
@ -47,8 +48,9 @@ class CT_Config:
|
||||||
self.all_version.add(track.since_version)
|
self.all_version.add(track.since_version)
|
||||||
self.all_tracks.append(track)
|
self.all_tracks.append(track)
|
||||||
|
|
||||||
def add_unordered_track(self, track: Track):
|
def add_unordered_track(self, track: Track) -> None:
|
||||||
"""
|
"""
|
||||||
|
add a single track to the config
|
||||||
:param track: a Track object to add as an unordered tracks
|
:param track: a Track object to add as an unordered tracks
|
||||||
:return: ?
|
:return: ?
|
||||||
"""
|
"""
|
||||||
|
@ -56,9 +58,10 @@ class CT_Config:
|
||||||
self.all_version.add(track.since_version)
|
self.all_version.add(track.since_version)
|
||||||
self.all_tracks.append(track)
|
self.all_tracks.append(track)
|
||||||
|
|
||||||
def create_ctfile(self, directory="./file/", highlight_version=None):
|
def create_ctfile(self, directory: str = "./file/", highlight_version: str = None) -> None:
|
||||||
"""
|
"""
|
||||||
:param highlight_version:
|
create a ctfile configuration in a directory
|
||||||
|
:param highlight_version: highlight a specific version in light blue
|
||||||
:param directory: create CTFILE.txt and RCTFILE.txt in this directory
|
:param directory: create CTFILE.txt and RCTFILE.txt in this directory
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
@ -94,7 +97,7 @@ class CT_Config:
|
||||||
ctfile.write(cup.get_ctfile_cup(race=False, highlight_version=highlight_version))
|
ctfile.write(cup.get_ctfile_cup(race=False, highlight_version=highlight_version))
|
||||||
rctfile.write(cup.get_ctfile_cup(race=True, highlight_version=highlight_version))
|
rctfile.write(cup.get_ctfile_cup(race=True, highlight_version=highlight_version))
|
||||||
|
|
||||||
def get_cticon(self):
|
def get_cticon(self) -> Image:
|
||||||
"""
|
"""
|
||||||
get all cup icon into a single image
|
get all cup icon into a single image
|
||||||
:return: ct_icon image
|
:return: ct_icon image
|
||||||
|
@ -114,19 +117,19 @@ class CT_Config:
|
||||||
|
|
||||||
return ct_icon
|
return ct_icon
|
||||||
|
|
||||||
def load_ctconfig_file(self, ctconfig_file: str = "./ct_config.json"):
|
def load_ctconfig_file(self, ctconfig_file: str = "./ct_config.json") -> None:
|
||||||
"""
|
"""
|
||||||
|
load a ctconfig from a json file
|
||||||
:param ctconfig_file: path to the ctconfig file
|
:param ctconfig_file: path to the ctconfig file
|
||||||
:return: ?
|
|
||||||
"""
|
"""
|
||||||
with open(ctconfig_file, encoding="utf-8") as f:
|
with open(ctconfig_file, encoding="utf-8") as f:
|
||||||
ctconfig_json = json.load(f)
|
ctconfig_json = json.load(f)
|
||||||
self.load_ctconfig_json(ctconfig_json)
|
self.load_ctconfig_json(ctconfig_json)
|
||||||
|
|
||||||
def load_ctconfig_json(self, ctconfig_json: dict):
|
def load_ctconfig_json(self, ctconfig_json: dict) -> None:
|
||||||
"""
|
"""
|
||||||
|
load ctconfig from a dictionnary
|
||||||
:param ctconfig_json: json of the ctconfig to load
|
:param ctconfig_json: json of the ctconfig to load
|
||||||
:return: ?
|
|
||||||
"""
|
"""
|
||||||
self.ordered_cups = []
|
self.ordered_cups = []
|
||||||
self.unordered_tracks = []
|
self.unordered_tracks = []
|
||||||
|
@ -152,7 +155,7 @@ class CT_Config:
|
||||||
self.all_version.add(track.since_version)
|
self.all_version.add(track.since_version)
|
||||||
self.all_version = sorted(self.all_version)
|
self.all_version = sorted(self.all_version)
|
||||||
|
|
||||||
def search_tracks(self, values_list=False, not_value=False, only_unordered_track=False, **kwargs):
|
def search_tracks(self, values_list=False, not_value=False, only_unordered_track=False, **kwargs) -> list:
|
||||||
"""
|
"""
|
||||||
:param only_unordered_track: only search in unordered track
|
:param only_unordered_track: only search in unordered track
|
||||||
:param values_list: search track with a value list instead of a single value
|
:param values_list: search track with a value list instead of a single value
|
||||||
|
|
|
@ -6,20 +6,33 @@ class Cup:
|
||||||
track1: Track = None,
|
track1: Track = None,
|
||||||
track2: Track = None,
|
track2: Track = None,
|
||||||
track3: Track = None,
|
track3: Track = None,
|
||||||
track4: Track = None, locked: bool = False,
|
track4: Track = None,
|
||||||
|
locked: bool = False,
|
||||||
*args, **kwargs):
|
*args, **kwargs):
|
||||||
|
"""
|
||||||
|
class of a cup
|
||||||
|
:param name: name of the cup
|
||||||
|
:param track1: first track
|
||||||
|
:param track2: second track
|
||||||
|
:param track3: third track
|
||||||
|
:param track4: fourth track
|
||||||
|
:param locked: is the track locked (used to load ctconfig in CT_Config)
|
||||||
|
:param args: other args that I could add in the future
|
||||||
|
:param kwargs: other kwargs that I could add in the future
|
||||||
|
"""
|
||||||
|
|
||||||
self.name = name
|
self.name = name
|
||||||
|
self.locked = locked
|
||||||
self.tracks = [
|
self.tracks = [
|
||||||
track1 if track1 else Track(),
|
track1 if track1 else Track(),
|
||||||
track2 if track2 else Track(),
|
track2 if track2 else Track(),
|
||||||
track3 if track3 else Track(),
|
track3 if track3 else Track(),
|
||||||
track4 if track4 else Track()
|
track4 if track4 else Track()
|
||||||
]
|
]
|
||||||
self.locked = locked
|
|
||||||
|
|
||||||
def get_ctfile_cup(self, *args, **kwargs):
|
def get_ctfile_cup(self, *args, **kwargs) -> str:
|
||||||
"""
|
"""
|
||||||
|
get the ctfile definition for the cup
|
||||||
:param race: is it a text used for Race_*.szs ?
|
:param race: is it a text used for Race_*.szs ?
|
||||||
:return: ctfile definition for the cup
|
:return: ctfile definition for the cup
|
||||||
"""
|
"""
|
||||||
|
@ -28,7 +41,11 @@ class Cup:
|
||||||
ctfile_cup += track.get_ctfile(*args, **kwargs)
|
ctfile_cup += track.get_ctfile(*args, **kwargs)
|
||||||
return ctfile_cup
|
return ctfile_cup
|
||||||
|
|
||||||
def load_from_json(self, cup: dict):
|
def load_from_json(self, cup: dict) -> None:
|
||||||
|
"""
|
||||||
|
load the cup from a dictionnary
|
||||||
|
:param cup: dictionnary cup
|
||||||
|
"""
|
||||||
for key, value in cup.items(): # load all value in the json as class attribute
|
for key, value in cup.items(): # load all value in the json as class attribute
|
||||||
if key != "tracks":
|
if key != "tracks":
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from tkinter import messagebox, StringVar, BooleanVar, IntVar
|
from tkinter import messagebox
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import shutil
|
import shutil
|
||||||
import glob
|
import glob
|
||||||
|
@ -7,6 +7,7 @@ import os
|
||||||
|
|
||||||
from .CT_Config import CT_Config
|
from .CT_Config import CT_Config
|
||||||
from .definition import *
|
from .definition import *
|
||||||
|
from .Gui import NoGui
|
||||||
from . import wszst
|
from . import wszst
|
||||||
|
|
||||||
|
|
||||||
|
@ -40,23 +41,6 @@ class CantConvertTrack(Exception):
|
||||||
super().__init__("Can't convert track, check if download are enabled.")
|
super().__init__("Can't convert track, check if download are enabled.")
|
||||||
|
|
||||||
|
|
||||||
class NoGui:
|
|
||||||
"""
|
|
||||||
'fake' gui if no gui are used for compatibility.
|
|
||||||
"""
|
|
||||||
def progression(self, *args, **kwargs): print(args, kwargs)
|
|
||||||
def translate(self, *args, **kwargs): return ""
|
|
||||||
def log_error(self, *args, **kwargs): print(args, kwargs)
|
|
||||||
|
|
||||||
is_dev_version = False
|
|
||||||
|
|
||||||
stringvar_game_format = StringVar()
|
|
||||||
boolvar_disable_download = BooleanVar()
|
|
||||||
intvar_process_track = IntVar()
|
|
||||||
boolvar_dont_check_track_sha1 = BooleanVar()
|
|
||||||
boolvar_del_track_after_conv = BooleanVar()
|
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
def __init__(self, path: str = "", region_ID: str = "P", game_ID: str = "RMCP01", gui=None):
|
def __init__(self, path: str = "", region_ID: str = "P", game_ID: str = "RMCP01", gui=None):
|
||||||
"""
|
"""
|
||||||
|
@ -170,7 +154,13 @@ class Game:
|
||||||
self.gui.progress(show=True, indeter=False, statut=self.gui.translate("Installing mod"), max=max_step,
|
self.gui.progress(show=True, indeter=False, statut=self.gui.translate("Installing mod"), max=max_step,
|
||||||
step=0)
|
step=0)
|
||||||
|
|
||||||
def replace_file(path, file, subpath="/"):
|
def replace_file(path, file, subpath="/") -> None:
|
||||||
|
"""
|
||||||
|
Replace subfile in the .szs file
|
||||||
|
:param path: path to the .szs file
|
||||||
|
:param file: file to replace
|
||||||
|
:param subpath: directory between .szs file and file inside to replace
|
||||||
|
"""
|
||||||
self.gui.progress(statut=self.gui.translate("Editing", "\n", get_nodir(path)), add=1)
|
self.gui.progress(statut=self.gui.translate("Editing", "\n", get_nodir(path)), add=1)
|
||||||
extension = get_extension(path)
|
extension = get_extension(path)
|
||||||
|
|
||||||
|
@ -182,14 +172,14 @@ class Game:
|
||||||
szs_extract_path = path + ".d"
|
szs_extract_path = path + ".d"
|
||||||
if os.path.exists(szs_extract_path + subpath):
|
if os.path.exists(szs_extract_path + subpath):
|
||||||
if subpath[-1] == "/":
|
if subpath[-1] == "/":
|
||||||
filecopy(f"./file/{file}", szs_extract_path + subpath + file)
|
shutil.copyfile(f"./file/{file}", szs_extract_path + subpath + file)
|
||||||
else:
|
else:
|
||||||
filecopy(f"./file/{file}", szs_extract_path + subpath)
|
shutil.copyfile(f"./file/{file}", szs_extract_path + subpath)
|
||||||
|
|
||||||
elif path[-1] == "/":
|
elif path[-1] == "/":
|
||||||
filecopy(f"./file/{file}", path + file)
|
shutil.copyfile(f"./file/{file}", path + file)
|
||||||
else:
|
else:
|
||||||
filecopy(f"./file/{file}", path)
|
shutil.copyfile(f"./file/{file}", path)
|
||||||
|
|
||||||
for fp in fs:
|
for fp in fs:
|
||||||
for f in glob.glob(self.path + "/files/" + fp, recursive=True):
|
for f in glob.glob(self.path + "/files/" + fp, recursive=True):
|
||||||
|
@ -215,9 +205,9 @@ class Game:
|
||||||
|
|
||||||
shutil.copytree("./file/Track/", self.path + "/files/Race/Course/", dirs_exist_ok=True)
|
shutil.copytree("./file/Track/", self.path + "/files/Race/Course/", dirs_exist_ok=True)
|
||||||
if not (os.path.exists(self.path + "/tmp/")): os.makedirs(self.path + "/tmp/")
|
if not (os.path.exists(self.path + "/tmp/")): os.makedirs(self.path + "/tmp/")
|
||||||
filecopy("./file/CTFILE.txt", self.path + "/tmp/CTFILE.txt")
|
shutil.copyfile("./file/CTFILE.txt", self.path + "/tmp/CTFILE.txt")
|
||||||
filecopy("./file/lpar-default.txt", self.path + "/tmp/lpar-default.txt")
|
shutil.copyfile("./file/lpar-default.txt", self.path + "/tmp/lpar-default.txt")
|
||||||
filecopy(f"./file/lecode-{self.region}.bin", self.path + f"/tmp/lecode-{self.region}.bin")
|
shutil.copyfile(f"./file/lecode-{self.region}.bin", self.path + f"/tmp/lecode-{self.region}.bin")
|
||||||
|
|
||||||
wszst.lec_patch(
|
wszst.lec_patch(
|
||||||
self.path,
|
self.path,
|
||||||
|
@ -315,7 +305,7 @@ class Game:
|
||||||
|
|
||||||
if not os.path.exists("./file/tmp/"): os.makedirs("./file/tmp/")
|
if not os.path.exists("./file/tmp/"): os.makedirs("./file/tmp/")
|
||||||
|
|
||||||
filecopy(gamefile + ".d/message/Common.bmg", "./file/tmp/Common.bmg")
|
shutil.copyfile(gamefile + ".d/message/Common.bmg", "./file/tmp/Common.bmg")
|
||||||
bmgcommon = wszst.ctc_patch_bmg(ctfile="./file/CTFILE.txt",
|
bmgcommon = wszst.ctc_patch_bmg(ctfile="./file/CTFILE.txt",
|
||||||
bmgs=["./file/tmp/Common.bmg", "./file/ExtraCommon.txt"])
|
bmgs=["./file/tmp/Common.bmg", "./file/ExtraCommon.txt"])
|
||||||
rbmgcommon = wszst.ctc_patch_bmg(ctfile="./file/RCTFILE.txt",
|
rbmgcommon = wszst.ctc_patch_bmg(ctfile="./file/RCTFILE.txt",
|
||||||
|
@ -374,11 +364,10 @@ class Game:
|
||||||
finally:
|
finally:
|
||||||
self.gui.progress(show=False)
|
self.gui.progress(show=False)
|
||||||
|
|
||||||
def patch_image(self, fc) -> None:
|
def patch_image(self, fc: dict) -> None:
|
||||||
"""
|
"""
|
||||||
Convert .png image into the format wrote in convert_file
|
Convert .png image into the format wrote in convert_file
|
||||||
:param fc:
|
:param fc: file convert, a dictionnary indicating which format a file need to be converted
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
for i, file in enumerate(fc["img"]):
|
for i, file in enumerate(fc["img"]):
|
||||||
self.gui.progress(statut=self.gui.translate("Converting images") + f"\n({i + 1}/{len(fc['img'])}) {file}",
|
self.gui.progress(statut=self.gui.translate("Converting images") + f"\n({i + 1}/{len(fc['img'])}) {file}",
|
||||||
|
@ -390,7 +379,6 @@ class Game:
|
||||||
patch descriptive image used when the game boot
|
patch descriptive image used when the game boot
|
||||||
:param img_desc_path: directory where original part of the image are stored
|
:param img_desc_path: directory where original part of the image are stored
|
||||||
:param dest_dir: directory where patched image will be saved
|
:param dest_dir: directory where patched image will be saved
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
il = Image.open(img_desc_path + "/illustration.png")
|
il = Image.open(img_desc_path + "/illustration.png")
|
||||||
il_16_9 = il.resize((832, 456))
|
il_16_9 = il.resize((832, 456))
|
||||||
|
|
|
@ -18,6 +18,28 @@ def restart():
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
|
|
||||||
|
class NoGui:
|
||||||
|
"""
|
||||||
|
'fake' gui if no gui are used for compatibility.
|
||||||
|
"""
|
||||||
|
class NoButton:
|
||||||
|
def grid(self, *args, **kwargs): pass
|
||||||
|
def config(self, *args, **kwargs): pass
|
||||||
|
|
||||||
|
def progress(*args, **kwargs): print(args, kwargs)
|
||||||
|
def translate(*args, **kwargs): return ""
|
||||||
|
def log_error(*args, **kwargs): print(args, kwargs)
|
||||||
|
def restart(self): restart()
|
||||||
|
|
||||||
|
is_dev_version = False
|
||||||
|
button_install_mod = NoButton()
|
||||||
|
stringvar_game_format = StringVar()
|
||||||
|
boolvar_disable_download = BooleanVar()
|
||||||
|
intvar_process_track = IntVar()
|
||||||
|
boolvar_dont_check_track_sha1 = BooleanVar()
|
||||||
|
boolvar_del_track_after_conv = BooleanVar()
|
||||||
|
|
||||||
|
|
||||||
class Gui:
|
class Gui:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -4,6 +4,9 @@ import os
|
||||||
|
|
||||||
class Option:
|
class Option:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
"""
|
||||||
|
class for Option
|
||||||
|
"""
|
||||||
self.language = "en"
|
self.language = "en"
|
||||||
self.format = "FST"
|
self.format = "FST"
|
||||||
self.disable_download = False
|
self.disable_download = False
|
||||||
|
@ -12,7 +15,14 @@ class Option:
|
||||||
self.dont_check_track_sha1 = False
|
self.dont_check_track_sha1 = False
|
||||||
self.process_track = 8
|
self.process_track = 8
|
||||||
|
|
||||||
def edit(self, option, value, need_restart=False, gui=None):
|
def edit(self, option: str, value: any, need_restart: bool = False, gui=None) -> None:
|
||||||
|
"""
|
||||||
|
Change the value of a parameter
|
||||||
|
:param option: the name of the option to change
|
||||||
|
:param value: the new value for the option
|
||||||
|
:param need_restart: do this value need a restart ?
|
||||||
|
:param gui: the gui object to restart
|
||||||
|
"""
|
||||||
if type(value) in [str, int, bool]:
|
if type(value) in [str, int, bool]:
|
||||||
setattr(self, option, value)
|
setattr(self, option, value)
|
||||||
else:
|
else:
|
||||||
|
@ -20,17 +30,29 @@ class Option:
|
||||||
self.save_to_file()
|
self.save_to_file()
|
||||||
if need_restart: gui.restart()
|
if need_restart: gui.restart()
|
||||||
|
|
||||||
def load_from_file(self, option_file: str = "./option.json"):
|
def load_from_file(self, option_file: str = "./option.json") -> None:
|
||||||
|
"""
|
||||||
|
Load all options from a json file
|
||||||
|
:param option_file: the file where to load option
|
||||||
|
"""
|
||||||
if os.path.exists(option_file):
|
if os.path.exists(option_file):
|
||||||
with open(option_file, encoding="utf-8") as file:
|
with open(option_file, encoding="utf-8") as file:
|
||||||
file_json = json.load(file)
|
file_json = json.load(file)
|
||||||
self.load_from_json(file_json)
|
self.load_from_json(file_json)
|
||||||
|
|
||||||
def load_from_json(self, option_json: dict):
|
def load_from_json(self, option_json: dict) -> None:
|
||||||
|
"""
|
||||||
|
Load all options from a dictionnary
|
||||||
|
:param option_json: the dictionnary to load
|
||||||
|
"""
|
||||||
for key, value in option_json.items(): # load all value in the json as class attribute
|
for key, value in option_json.items(): # load all value in the json as class attribute
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
def save_to_file(self, option_file: str = "./option.json"):
|
def save_to_file(self, option_file: str = "./option.json") -> None:
|
||||||
|
"""
|
||||||
|
Save all options to a file
|
||||||
|
:param option_file: the file where to save option
|
||||||
|
"""
|
||||||
option_json: dict = self.__dict__ # this return all attribute of the class as a dict
|
option_json: dict = self.__dict__ # this return all attribute of the class as a dict
|
||||||
with open(option_file, "w", encoding="utf-8") as file:
|
with open(option_file, "w", encoding="utf-8") as file:
|
||||||
json.dump(option_json, file, ensure_ascii=False)
|
json.dump(option_json, file, ensure_ascii=False)
|
||||||
|
|
|
@ -65,12 +65,11 @@ class Track:
|
||||||
if wszst.sha1(self.file_wu8) == self.sha1: return 0
|
if wszst.sha1(self.file_wu8) == self.sha1: return 0
|
||||||
else: return -1
|
else: return -1
|
||||||
|
|
||||||
def convert_wu8_to_szs(self) -> str:
|
def convert_wu8_to_szs(self) -> None:
|
||||||
"""
|
"""
|
||||||
convert track to szs
|
convert track to szs
|
||||||
:return: path to szs track
|
|
||||||
"""
|
"""
|
||||||
return wszst.normalize(src_file=self.file_wu8)
|
wszst.normalize(src_file=self.file_wu8)
|
||||||
|
|
||||||
def download_wu8(self, github_content_root: str) -> int:
|
def download_wu8(self, github_content_root: str) -> int:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -95,14 +95,19 @@ region_id_to_name = {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def filecopy(src, dst):
|
|
||||||
with open(src, "rb") as f1:
|
|
||||||
with open(dst, "wb") as f2:
|
|
||||||
f2.write(f1.read()) # could be buffered
|
|
||||||
|
|
||||||
|
|
||||||
def in_thread(func):
|
def in_thread(func):
|
||||||
def wrapped_func(*args, **kwargs):
|
"""
|
||||||
|
instead of calling a function, this will start it in a thread
|
||||||
|
:param func: function to thread
|
||||||
|
:return: threaded function
|
||||||
|
"""
|
||||||
|
def wrapped_func(*args, **kwargs) -> Thread:
|
||||||
|
"""
|
||||||
|
function that will be returned instead of the function, will call it in a thread
|
||||||
|
:param args: args of the original function
|
||||||
|
:param kwargs: kwargs of the original function
|
||||||
|
:return: thread object to the function
|
||||||
|
"""
|
||||||
thread = Thread(target=func, args=args, kwargs=kwargs)
|
thread = Thread(target=func, args=args, kwargs=kwargs)
|
||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
100
source/wszst.py
100
source/wszst.py
|
@ -2,9 +2,9 @@ from .definition import *
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
def sha1(file, autoadd_path: str = "./file/auto-add/"):
|
def sha1(file, autoadd_path: str = "./file/auto-add/") -> str:
|
||||||
"""
|
"""
|
||||||
:param autoadd_path:
|
:param autoadd_path: directory where is autoadd directory
|
||||||
:param file: track file to check sha1
|
:param file: track file to check sha1
|
||||||
:return: track's sha1
|
:return: track's sha1
|
||||||
"""
|
"""
|
||||||
|
@ -14,86 +14,126 @@ def sha1(file, autoadd_path: str = "./file/auto-add/"):
|
||||||
|
|
||||||
|
|
||||||
def normalize(src_file: str, dest_dir: str = "./file/Track/", dest_name: str = "%N.szs",
|
def normalize(src_file: str, dest_dir: str = "./file/Track/", dest_name: str = "%N.szs",
|
||||||
output_format: str = "szs", autoadd_path: str = "./file/auto-add/"):
|
output_format: str = "szs", autoadd_path: str = "./file/auto-add/") -> None:
|
||||||
"""
|
"""
|
||||||
:param use_popen: True if you want to use Popen to convert
|
convert a track into an another format
|
||||||
:param src_file: source file
|
:param src_file: source file
|
||||||
:param dest_dir: destination directory
|
:param dest_dir: destination directory
|
||||||
:param dest_name: destination filename (%N mean same name as src_file)
|
:param dest_name: destination filename (%N mean same name as src_file)
|
||||||
:param output_format: format of the destination track
|
:param output_format: format of the destination track
|
||||||
:param autoadd_path: path of the auto-add directory
|
:param autoadd_path: path of the auto-add directory
|
||||||
:return: 0
|
|
||||||
"""
|
"""
|
||||||
subprocess.run(["./tools/szs/wszst", "NORMALIZE", src_file, "--DEST",
|
subprocess.run(["./tools/szs/wszst", "NORMALIZE", src_file, "--DEST",
|
||||||
dest_dir+dest_name, "--"+output_format, "--overwrite", "--autoadd-path",
|
dest_dir+dest_name, "--"+output_format, "--overwrite", "--autoadd-path",
|
||||||
autoadd_path], creationflags=CREATE_NO_WINDOW, stderr=subprocess.PIPE)
|
autoadd_path], creationflags=CREATE_NO_WINDOW, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def wit_extract(file: str, dest_dir: str):
|
def wit_extract(file: str, dest_dir: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
extract the game into a directory
|
||||||
:param file: game's file to extract (can be WBFS, ISO, CISO)
|
:param file: game's file to extract (can be WBFS, ISO, CISO)
|
||||||
:param dest_dir: where to extract the game
|
:param dest_dir: where to extract the game
|
||||||
:return: ?
|
|
||||||
"""
|
"""
|
||||||
subprocess.run(["./tools/wit/wit", "EXTRACT", get_nodir(file), "--DEST", dest_dir],
|
subprocess.run(["./tools/wit/wit", "EXTRACT", get_nodir(file), "--DEST", dest_dir],
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
||||||
|
|
||||||
|
|
||||||
def create(file: str):
|
def create(file: str) -> None:
|
||||||
"""
|
"""
|
||||||
|
convert a directory into a szs file
|
||||||
:param file: create a .szs file from the directory {file}.d
|
:param file: create a .szs file from the directory {file}.d
|
||||||
:return:
|
|
||||||
"""
|
"""
|
||||||
subprocess.run(["./tools/szs/wszst", "CREATE", get_nodir(file) + ".d", "-d", get_nodir(file),
|
subprocess.run(["./tools/szs/wszst", "CREATE", get_nodir(file) + ".d", "-d", get_nodir(file),
|
||||||
"--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
"--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
||||||
check=True, stdout=subprocess.PIPE)
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def str_patch(file: str):
|
def str_patch(path: str) -> None:
|
||||||
subprocess.run(["./tools/szs/wstrt", "patch", get_nodir(file) + "/sys/main.dol", "--clean-dol",
|
"""
|
||||||
"--add-lecode"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
Patch the main.dol file
|
||||||
|
:param path: path to the game
|
||||||
|
"""
|
||||||
|
subprocess.run(["./tools/szs/wstrt", "patch", get_nodir(path) + "/sys/main.dol", "--clean-dol",
|
||||||
|
"--add-lecode"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(path),
|
||||||
check=True, stdout=subprocess.PIPE)
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def lec_patch(file: str,
|
def lec_patch(path: str,
|
||||||
lecode_file: str = f"./tmp/lecode-PAL.bin",
|
lecode_file: str = f"./tmp/lecode-PAL.bin",
|
||||||
dest_lecode_file: str = f"./files/rel/lecode-PAL.bin",
|
dest_lecode_file: str = f"./files/rel/lecode-PAL.bin",
|
||||||
game_track_path: str = "./files/Race/Course/",
|
game_track_path: str = "./files/Race/Course/",
|
||||||
move_track_path: str = "./files/Race/Course/",
|
move_track_path: str = "./files/Race/Course/",
|
||||||
ctfile_path: str = "./tmp/CTFILE.txt",
|
ctfile_path: str = "./tmp/CTFILE.txt",
|
||||||
lpar_path: str = "./tmp/lpar-default.txt"):
|
lpar_path: str = "./tmp/lpar-default.txt") -> None:
|
||||||
|
"""
|
||||||
|
Patch the file with a lecode file (this is the adding track part)
|
||||||
|
:param path: path to the game file
|
||||||
|
:param lecode_file: path to the lecode file
|
||||||
|
:param dest_lecode_file: destination of the lecode file
|
||||||
|
:param game_track_path: subpath to the track directory
|
||||||
|
:param move_track_path: where are stored the track to move
|
||||||
|
:param ctfile_path: where is the ctfile (track and cup definition)
|
||||||
|
:param lpar_path: where is the lpar_path (game modification like speed, speedometer, ...)
|
||||||
|
"""
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["./tools/szs/wlect", "patch", lecode_file, "-od",
|
["./tools/szs/wlect", "patch", lecode_file, "-od",
|
||||||
dest_lecode_file, "--track-dir", game_track_path,
|
dest_lecode_file, "--track-dir", game_track_path,
|
||||||
"--move-tracks", move_track_path, "--le-define", ctfile_path, "--lpar",
|
"--move-tracks", move_track_path, "--le-define", ctfile_path, "--lpar",
|
||||||
lpar_path, "--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=file, check=True, stdout=subprocess.PIPE)
|
lpar_path, "--overwrite"], creationflags=CREATE_NO_WINDOW, cwd=path, check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def edit(file, region_ID: str = "P", name: str = "Mario Kart Wii"):
|
def edit(file: str, region_ID: str = "P", name: str = "Mario Kart Wii") -> None:
|
||||||
|
"""
|
||||||
|
Edit game property like region or name
|
||||||
|
:param file: game's file
|
||||||
|
:param region_ID: new region_ID
|
||||||
|
:param name: new name
|
||||||
|
"""
|
||||||
subprocess.run(["./tools/wit/wit", "EDIT", get_nodir(file), "--id",
|
subprocess.run(["./tools/wit/wit", "EDIT", get_nodir(file), "--id",
|
||||||
f"RMC{region_ID}60", "--name", name, "--modify", "ALL"],
|
f"RMC{region_ID}60", "--name", name, "--modify", "ALL"],
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
||||||
check=True, stdout=subprocess.PIPE)
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def autoadd(file: str, dest_dir: str):
|
def autoadd(file: str, dest_dir: str) -> None:
|
||||||
|
"""
|
||||||
|
Create an auto_add directory from a game file
|
||||||
|
:param file: the game's path
|
||||||
|
:param dest_dir: directory where to store autoadd file
|
||||||
|
"""
|
||||||
subprocess.run(["./tools/szs/wszst", "AUTOADD", get_nodir(file) + "/files/Race/Course/", "--DEST", dest_dir],
|
subprocess.run(["./tools/szs/wszst", "AUTOADD", get_nodir(file) + "/files/Race/Course/", "--DEST", dest_dir],
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file),
|
||||||
check=True, stdout=subprocess.PIPE)
|
check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def bmg_encode(file: str):
|
def bmg_encode(file: str) -> None:
|
||||||
|
"""
|
||||||
|
Encode a txt file into a bmg file
|
||||||
|
:param file: txt file to convert
|
||||||
|
"""
|
||||||
subprocess.run(["./tools/szs/wbmgt", "ENCODE", get_nodir(file), "--overwrite"],
|
subprocess.run(["./tools/szs/wbmgt", "ENCODE", get_nodir(file), "--overwrite"],
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
||||||
|
|
||||||
|
|
||||||
def bmg_cat(path: str, subfile: str = ".d/message/Common.bmg"):
|
def bmg_cat(path: str, subfile: str = ".d/message/Common.bmg") -> str:
|
||||||
|
"""
|
||||||
|
read a bmg file
|
||||||
|
:param path: path to a szs file
|
||||||
|
:param subfile: path to a subdirectory
|
||||||
|
:return: bmg definition
|
||||||
|
"""
|
||||||
return subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(path) + subfile],
|
return subprocess.run(["./tools/szs/wbmgt", "CAT", get_nodir(path) + subfile],
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(path),
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(path),
|
||||||
check=True, stdout=subprocess.PIPE).stdout.decode()
|
check=True, stdout=subprocess.PIPE).stdout.decode()
|
||||||
|
|
||||||
|
|
||||||
def wit_copy(src_path, dst_path, format: str = "ISO"):
|
def wit_copy(src_path, dst_path, format: str = "ISO") -> None:
|
||||||
|
"""
|
||||||
|
Copy the game into an another format
|
||||||
|
:param src_path: original game path
|
||||||
|
:param dst_path: new game path
|
||||||
|
:param format: format for the new game
|
||||||
|
"""
|
||||||
subprocess.run(["./tools/wit/wit", "COPY", get_nodir(src_path), "--DEST",
|
subprocess.run(["./tools/wit/wit", "COPY", get_nodir(src_path), "--DEST",
|
||||||
get_nodir(dst_path), f"--{format.lower()}", "--overwrite"],
|
get_nodir(dst_path), f"--{format.lower()}", "--overwrite"],
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(dst_path),
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(dst_path),
|
||||||
|
@ -101,6 +141,12 @@ def wit_copy(src_path, dst_path, format: str = "ISO"):
|
||||||
|
|
||||||
|
|
||||||
def ctc_patch_bmg(bmgs: list, ctfile: str = "./file/CTFILE.txt"):
|
def ctc_patch_bmg(bmgs: list, ctfile: str = "./file/CTFILE.txt"):
|
||||||
|
"""
|
||||||
|
Patch a bmg file with a ctfile with OVERWRITE option
|
||||||
|
:param bmgs: all bmg files
|
||||||
|
:param ctfile: the ctfile path
|
||||||
|
:return: combined bmg
|
||||||
|
"""
|
||||||
bmg_cmd = []
|
bmg_cmd = []
|
||||||
for bmg in bmgs: bmg_cmd.extend(["--patch-bmg", f"OVERWRITE={bmg}"])
|
for bmg in bmgs: bmg_cmd.extend(["--patch-bmg", f"OVERWRITE={bmg}"])
|
||||||
return subprocess.run(
|
return subprocess.run(
|
||||||
|
@ -108,11 +154,21 @@ def ctc_patch_bmg(bmgs: list, ctfile: str = "./file/CTFILE.txt"):
|
||||||
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
|
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE).stdout.decode()
|
||||||
|
|
||||||
|
|
||||||
def img_encode(src_file, format):
|
def img_encode(src_file: str, format: str) -> None:
|
||||||
|
"""
|
||||||
|
Encode an .png image into a new format
|
||||||
|
:param src_file: .png image
|
||||||
|
:param format: new image format
|
||||||
|
"""
|
||||||
subprocess.run(["./tools/szs/wimgt", "ENCODE", src_file, "-x", format, "--overwrite"],
|
subprocess.run(["./tools/szs/wimgt", "ENCODE", src_file, "-x", format, "--overwrite"],
|
||||||
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE)
|
creationflags=CREATE_NO_WINDOW, check=True, stdout=subprocess.PIPE)
|
||||||
|
|
||||||
|
|
||||||
def szs_extract(file, dest_dir):
|
def szs_extract(file: str, dest_dir: str) -> None:
|
||||||
|
"""
|
||||||
|
Extract an szs in a directory
|
||||||
|
:param file: .szs file
|
||||||
|
:param dest_dir: directory where to extract the file
|
||||||
|
"""
|
||||||
subprocess.run(["./tools/szs/wszst", "EXTRACT", get_nodir(file), "--DEST", dest_dir+".d"],
|
subprocess.run(["./tools/szs/wszst", "EXTRACT", get_nodir(file), "--DEST", dest_dir+".d"],
|
||||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
Loading…
Reference in a new issue