mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-02 18:58:27 +02:00
edited source to use CT_Config, Game, Cup and Track
This commit is contained in:
parent
c041f55cb9
commit
57efdf2da3
20 changed files with 169 additions and 375 deletions
8
main.pyw
8
main.pyw
|
@ -20,18 +20,18 @@ class ClassApp():
|
|||
from source.Progress import Progress
|
||||
from source.check_update import check_update
|
||||
from source.StateButton import StateButton
|
||||
from source.create_lecode_config import create_lecode_config
|
||||
from source.patch_file import patch_file
|
||||
from source.patch_bmg import patch_bmg
|
||||
from source.install_mod import install_mod
|
||||
from source.restart import restart
|
||||
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, check_track_sha1
|
||||
from source.patch_track import load_ct_config, patch_track, patch_autoadd, get_trackctname, get_trackname
|
||||
from source.get_github_file import get_github_file
|
||||
from source.patch_track import patch_track, patch_autoadd
|
||||
from source.patch_image import patch_image
|
||||
from source.option import load_option, change_option
|
||||
from source.CT_Config import CT_Config
|
||||
from source.Game import Game, InvalidGamePath, InvalidFormat
|
||||
|
||||
|
||||
App = ClassApp()
|
||||
|
|
|
@ -1,30 +1,37 @@
|
|||
from .Cup import *
|
||||
import math
|
||||
from PIL import Image, ImageFont, ImageDraw
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
def get_cup_icon(i):
|
||||
if os.path.exists(f"./file/cup_icon/{i}.png"):
|
||||
cup_icon = Image.open(f"./file/cup_icon/{i}.png").resize((128, 128))
|
||||
def get_cup_icon(cup_id, font_path: str = "./file/SuperMario256.ttf", cup_icon_dir: str = "./file/cup_icon"):
|
||||
"""
|
||||
:param cup_icon_dir: directory to cup icon
|
||||
:param font_path: path to the font used to generate icon
|
||||
:param cup_id: id of the cup
|
||||
:return: cup icon
|
||||
"""
|
||||
if os.path.exists(f"{cup_icon_dir}/{cup_id}.png"):
|
||||
cup_icon = Image.open(f"{cup_icon_dir}/{cup_id}.png").resize((128, 128))
|
||||
|
||||
else:
|
||||
cup_icon = Image.new("RGBA", (128, 128))
|
||||
draw = ImageDraw.Draw(cup_icon)
|
||||
font = ImageFont.truetype("./file/SuperMario256.ttf", 90)
|
||||
font = ImageFont.truetype(font_path, 90)
|
||||
draw.text((4 - 2, 4 - 2), "CT", (0, 0, 0), font=font)
|
||||
draw.text((4 + 2, 4 - 2), "CT", (0, 0, 0), font=font)
|
||||
draw.text((4 - 2, 4 + 2), "CT", (0, 0, 0), font=font)
|
||||
draw.text((4 + 2, 4 + 2), "CT", (0, 0, 0), font=font)
|
||||
draw.text((4, 4), "CT", (255, 165, 0), font=font)
|
||||
|
||||
font = ImageFont.truetype("./file/SuperMario256.ttf", 60)
|
||||
draw.text((5 - 2, 80 - 2), "%03i" % i, (0, 0, 0), font=font)
|
||||
draw.text((5 + 2, 80 - 2), "%03i" % i, (0, 0, 0), font=font)
|
||||
draw.text((5 - 2, 80 + 2), "%03i" % i, (0, 0, 0), font=font)
|
||||
draw.text((5 + 2, 80 + 2), "%03i" % i, (0, 0, 0), font=font)
|
||||
font = ImageFont.truetype(font_path, 60)
|
||||
draw.text((5 - 2, 80 - 2), "%03i" % cup_id, (0, 0, 0), font=font)
|
||||
draw.text((5 + 2, 80 - 2), "%03i" % cup_id, (0, 0, 0), font=font)
|
||||
draw.text((5 - 2, 80 + 2), "%03i" % cup_id, (0, 0, 0), font=font)
|
||||
draw.text((5 + 2, 80 + 2), "%03i" % cup_id, (0, 0, 0), font=font)
|
||||
|
||||
draw.text((5, 80), "%03i" % i, (255, 165, 0), font=font)
|
||||
draw.text((5, 80), "%03i" % cup_id, (255, 165, 0), font=font)
|
||||
return cup_icon
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
from .Track import *
|
||||
from PIL import Image
|
||||
from .patch_ct_icon import get_cup_icon
|
||||
|
||||
|
||||
class Cup:
|
||||
|
@ -8,8 +6,7 @@ class Cup:
|
|||
track1: Track = None,
|
||||
track2: Track = None,
|
||||
track3: Track = None,
|
||||
track4: Track = None,
|
||||
icon: Image = None, locked: bool = False,
|
||||
track4: Track = None, locked: bool = False,
|
||||
*args, **kwargs):
|
||||
|
||||
self.name = name
|
||||
|
@ -19,7 +16,6 @@ class Cup:
|
|||
track3 if track3 else Track(),
|
||||
track4 if track4 else Track()
|
||||
]
|
||||
self.icon = icon
|
||||
self.locked = locked
|
||||
|
||||
def load_from_json(self, cup: dict):
|
||||
|
@ -38,10 +34,3 @@ class Cup:
|
|||
for track in self.tracks:
|
||||
ctfile_cup += track.get_ctfile_track(race)
|
||||
return ctfile_cup
|
||||
|
||||
def get_icon(self, id: int):
|
||||
"""
|
||||
:param id: cup number
|
||||
:return: icon of the cup
|
||||
"""
|
||||
return self.icon if self.icon else get_cup_icon(id)
|
||||
|
|
|
@ -3,33 +3,52 @@ from .definition import *
|
|||
import glob
|
||||
import os
|
||||
|
||||
region_id_to_name = {
|
||||
"J": "JAP",
|
||||
"P": "PAL",
|
||||
"K": "KO",
|
||||
"E": "USA"
|
||||
}
|
||||
|
||||
class InvalidGamePath(Exception):
|
||||
def __init__(self):
|
||||
super().__init__("This path is not valid !")
|
||||
|
||||
|
||||
class InvalidFormat(Exception):
|
||||
def __init__(self):
|
||||
super().__init__("This game format is not supported !")
|
||||
|
||||
|
||||
class Game:
|
||||
def __init__(self, path: str, region: str = "PAL", game_ID: str = "RMCP01"):
|
||||
self.extension = get_extension(path)
|
||||
def __init__(self, path: str, region_ID: str = "P", game_ID: str = "RMCP01"):
|
||||
if not os.path.exists(path): raise InvalidGamePath()
|
||||
self.extension = get_extension(path).upper()
|
||||
self.path = path
|
||||
self.region_ID = region_ID[region]
|
||||
self.region = region
|
||||
self.region = region_id_to_name[region_ID]
|
||||
self.region_ID = region_ID
|
||||
self.game_ID = game_ID
|
||||
|
||||
def extract_game(self):
|
||||
if self.extension.upper() == "DOL":
|
||||
if self.extension == "DOL":
|
||||
self.path = os.path.realpath(self.path + "/../../") # main.dol is in PATH/sys/, so go back 2 dir upper
|
||||
|
||||
elif self.extension.upper() in ["ISO", "WBFS", "CSIO"]:
|
||||
elif self.extension in ["ISO", "WBFS", "CSIO"]:
|
||||
# Fiding a directory name that doesn't already exist
|
||||
directory_name, i = "MKWiiFaraphel", 1
|
||||
while True:
|
||||
self.path = os.path.realpath(self.path + f"/../{directory_name}")
|
||||
if not (os.path.exists(self.path)): break
|
||||
path_dir = os.path.realpath(self.path + f"/../{directory_name}")
|
||||
if not (os.path.exists(path_dir)): break
|
||||
directory_name, i = f"MKWiiFaraphel ({i})", i + 1
|
||||
|
||||
wszst.extract(self.path, self.path)
|
||||
wszst.extract(self.path, path_dir)
|
||||
|
||||
self.path = path_dir
|
||||
if os.path.exists(self.path + "/DATA"): self.path += "/DATA"
|
||||
self.extension = "DOL"
|
||||
|
||||
else:
|
||||
raise Exception("This format is not supported !")
|
||||
raise InvalidFormat()
|
||||
|
||||
if glob.glob(self.path + "/files/rel/lecode-???.bin"): # if a LECODE file is already here
|
||||
raise Warning("ROM Already patched") # warning already patched
|
||||
|
@ -39,7 +58,7 @@ class Game:
|
|||
self.game_ID = setup[:setup.find("\n")]
|
||||
|
||||
self.region_ID = self.game_ID[3]
|
||||
self.region = region_ID[self.region_ID] if self.region_ID in region_ID else self.region
|
||||
self.region = region_id_to_name[self.region_ID] if self.region_ID in region_id_to_name else self.region
|
||||
|
||||
def install_mod(self):
|
||||
pass
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
def Progress(self, show=None, indeter=None, step=None, statut=None, max=None, add=None):
|
||||
if indeter == True:
|
||||
if indeter is True:
|
||||
self.progressbar.config(mode="indeterminate")
|
||||
self.progressbar.start(50)
|
||||
elif indeter == False:
|
||||
elif indeter is False:
|
||||
self.progressbar.config(mode="determinate")
|
||||
self.progressbar.stop()
|
||||
if show == True:
|
||||
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 == False:
|
||||
elif show is False:
|
||||
self.StateButton(enable=True)
|
||||
self.progressbar.grid_forget()
|
||||
self.progresslabel.grid_forget()
|
||||
|
|
|
@ -19,11 +19,11 @@ class Track:
|
|||
self.score = score # Track score between 1 and 3 stars
|
||||
self.warning = warning # Track bug level (1 = minor, 2 = major)
|
||||
self.note = note # Note about the track
|
||||
self.file_wu8 = file_wu8
|
||||
self.file_szs = file_szs
|
||||
self.file_wu8 = f"./file/Track-WU8/{self.get_track_name()}.wu8"
|
||||
self.file_szs = f"./file/Track/{self.get_track_name()}.szs"
|
||||
|
||||
def __repr__(self):
|
||||
return f"{self.get_track_name()} sha1={self.sha1}"
|
||||
return f"{self.get_track_name()} sha1={self.sha1} score={self.score}"
|
||||
|
||||
def get_track_name(self):
|
||||
prefix = self.prefix + " " if self.prefix else ""
|
||||
|
@ -61,11 +61,11 @@ class Track:
|
|||
suffix = "(" + trackname_color[self.suffix] + ")"
|
||||
|
||||
name = (star_text + prefix + hl_prefix + self.name + hl_suffix + suffix)
|
||||
name = name.replace("_", "")
|
||||
name = name.replace("_", " ")
|
||||
return name
|
||||
|
||||
def convert_wu8_to_szs(self):
|
||||
source.wszst.normalize(src_file=self.file_wu8)
|
||||
return source.wszst.normalize(src_file=self.file_wu8, use_popen=True)
|
||||
|
||||
def download_wu8(self): pass
|
||||
|
||||
|
@ -96,3 +96,5 @@ class Track:
|
|||
)
|
||||
|
||||
return ctfile_text
|
||||
|
||||
# TODO: code download_wu8
|
|
@ -8,14 +8,16 @@ import os
|
|||
from .definition import *
|
||||
from .check_update import check_update
|
||||
from .translate import translate
|
||||
from .CT_Config import *
|
||||
from .Game import *
|
||||
|
||||
def __init__(self):
|
||||
try:
|
||||
|
||||
self.root = Tk()
|
||||
|
||||
self.load_option()
|
||||
self.load_ct_config()
|
||||
self.ctconfig = CT_Config()
|
||||
self.ctconfig.load_ctconfig_file("./ct_config.json")
|
||||
|
||||
self.stringvar_language = StringVar(value=self.option["language"])
|
||||
self.stringvar_game_format = StringVar(value=self.option["format"])
|
||||
|
@ -61,7 +63,7 @@ def __init__(self):
|
|||
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.ALL_VERSION:
|
||||
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)
|
||||
|
@ -103,62 +105,18 @@ def __init__(self):
|
|||
|
||||
def use_path():
|
||||
def func():
|
||||
self.frame_action.grid_forget()
|
||||
try:
|
||||
self.frame_action.grid_forget()
|
||||
path = entry_game_path.get()
|
||||
if not (os.path.exists(path)):
|
||||
messagebox.showerror(self.translate("Error"), self.translate("The file path in invalid"))
|
||||
return
|
||||
|
||||
extension = get_extension(path)
|
||||
if extension.upper() == "DOL":
|
||||
if messagebox.askyesno(self.translate("Warning"),
|
||||
self.translate("This directory will be overwritten if you install the "
|
||||
"mod !\n Are you sure you want to use it ?")):
|
||||
self.path_mkwf = os.path.realpath(path + "/../../")
|
||||
else: return
|
||||
elif extension.upper() in ["ISO", "WBFS", "CSIO"]:
|
||||
# Fiding a directory name that dosen't already exist
|
||||
directory_name, i = "MKWiiFaraphel", 1
|
||||
while True:
|
||||
self.path_mkwf = os.path.realpath(path + f"/../{directory_name}")
|
||||
if not(os.path.exists(self.path_mkwf)): break
|
||||
directory_name, i = f"MKWiiFaraphel ({i})", i + 1
|
||||
|
||||
self.Progress(show=True, indeter=True, statut=self.translate("Extracting the game..."))
|
||||
subprocess.call(["./tools/wit/wit", "EXTRACT", get_nodir(path), "--DEST", directory_name]
|
||||
, creationflags=CREATE_NO_WINDOW, cwd=get_dir(path))
|
||||
|
||||
if os.path.exists(self.path_mkwf + "/DATA"): self.path_mkwf += "/DATA"
|
||||
|
||||
self.Progress(show=False)
|
||||
|
||||
else:
|
||||
messagebox.showerror(self.translate("Error"), self.translate("This file type is not supported"))
|
||||
self.Progress(show=False)
|
||||
return
|
||||
|
||||
if glob.glob(self.path_mkwf + "/files/rel/lecode-???.bin"): # if a LECODE file is already here
|
||||
messagebox.showwarning(self.translate("Warning"),
|
||||
self.translate("This game is already modded, it is not recommended to "
|
||||
"use it to install the mod"))
|
||||
|
||||
try:
|
||||
with open(self.path_mkwf + "/setup.txt") as f: setup = f.read()
|
||||
setup = setup[setup.find("!part-id = ")+len("!part-id = "):]
|
||||
self.original_game_ID = setup[:setup.find("\n")]
|
||||
except:
|
||||
messagebox.showwarning(self.translate("Warning"),
|
||||
self.transate("Can't find game region.\nPAL region will be used."))
|
||||
self.original_game_ID = "RMCP01"
|
||||
try:
|
||||
self.original_region_ID = self.original_game_ID[3]
|
||||
self.original_region = region_ID[self.original_region_ID]
|
||||
except: self.original_region = "PAL"
|
||||
|
||||
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: self.log_error()
|
||||
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)
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ from tkinter import messagebox
|
|||
import requests
|
||||
import zipfile
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
|
||||
from .definition import *
|
||||
|
@ -38,12 +37,10 @@ def check_update(self):
|
|||
os.remove("./download.zip")
|
||||
print(self.translate("starting application..."))
|
||||
os.startfile(os.path.realpath("./Updater/Updater.exe"))
|
||||
sys.exit()
|
||||
|
||||
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 SystemExit: pass
|
||||
except: self.log_error()
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
import json
|
||||
from .definition import *
|
||||
|
||||
|
||||
def create_lecode_config(self):
|
||||
try:
|
||||
def get_star_text(track):
|
||||
|
||||
if "score" in track:
|
||||
if 0 < track["score"] <= 3:
|
||||
star_text = "★" * track["score"] + "☆" * (3 - track["score"])
|
||||
return trackname_color[star_text] + " "
|
||||
return ""
|
||||
|
||||
def get_ctfile_text(track, race=False):
|
||||
if race:
|
||||
return (f' T {track["music"]}; '
|
||||
f'{track["special"]}; '
|
||||
f'{"0x01" if track["new"] else "0x00"}; '
|
||||
f'"-"; '
|
||||
f'"{get_star_text(track)}{self.get_trackctname(track=track, color=True)}\\n{track["author"]}"; '
|
||||
f'"-"\n')
|
||||
else:
|
||||
return (f' T {track["music"]}; '
|
||||
f'{track["special"]}; '
|
||||
f'{"0x01" if track["new"] else "0x00"}; '
|
||||
f'"{self.get_trackctname(track=track)}"; '
|
||||
f'"{get_star_text(track)}{self.get_trackctname(track=track, color=True)}"; '
|
||||
f'"-"\n')
|
||||
|
||||
with open("./ct_config.json", encoding="utf-8") as f:
|
||||
ctconfig = json.load(f)
|
||||
|
||||
with open("./file/CTFILE.txt", "w", encoding="utf-8") as ctfile, \
|
||||
open("./file/RCTFILE.txt", "w", encoding="utf-8") as rctfile:
|
||||
|
||||
header = ("#CT-CODE\n"
|
||||
"[RACING-TRACK-LIST]\n"
|
||||
"%LE-FLAGS=1\n"
|
||||
"%WIIMM-CUP=1\n"
|
||||
"N N$SWAP | N$F_WII\n\n")
|
||||
ctfile.write(header)
|
||||
rctfile.write(header)
|
||||
|
||||
for cup in ctconfig["cup"]: # defined cup section
|
||||
_cup_config = ctconfig["cup"][cup]
|
||||
if int(cup) >= 9: # Track that are not original and not random selection
|
||||
cup = f'\nC "{_cup_config["name"]}"\n'
|
||||
ctfile.write(cup)
|
||||
rctfile.write(cup)
|
||||
|
||||
for course in _cup_config["courses"]:
|
||||
_course_config = _cup_config["courses"][course]
|
||||
ctfile.write(get_ctfile_text(_course_config, race=False))
|
||||
rctfile.write(get_ctfile_text(_course_config, race=True))
|
||||
|
||||
tracks_list = ctconfig["tracks_list"]
|
||||
if not self.boolvar_use_1star_track.get(): # if 1 star track are disabled, remove them
|
||||
tracks_list = list(filter(lambda track: track.get("score") != 1, tracks_list))
|
||||
if not self.boolvar_use_2star_track.get(): # if 2 stars track are disabled, remove them
|
||||
tracks_list = list(filter(lambda track: track.get("score") != 2, tracks_list))
|
||||
if not self.boolvar_use_3star_track.get(): # if 3 stars track are disabled, remove them
|
||||
tracks_list = list(filter(lambda track: track.get("score") != 3, tracks_list))
|
||||
# using dict.get allow track that with no "score" attribute to not raise an exception by returning None
|
||||
|
||||
for i, _course_config in enumerate(tracks_list): # undefined cup section
|
||||
if i % 4 == 0:
|
||||
cup = f'\nC "TL{i//4}"\n'
|
||||
ctfile.write(cup)
|
||||
rctfile.write(cup)
|
||||
|
||||
ctfile.write(get_ctfile_text(_course_config, race=False))
|
||||
rctfile.write(get_ctfile_text(_course_config, race=True))
|
||||
|
||||
for _ in range(1, 4-(i%4)): # Complete cup if track are missing
|
||||
ctfile.write(EMPTY_TRACK)
|
||||
rctfile.write(EMPTY_TRACK)
|
||||
|
||||
except:
|
||||
self.log_error()
|
|
@ -1,5 +1,3 @@
|
|||
import json
|
||||
|
||||
CREATE_NO_WINDOW = 0x08000000
|
||||
GITHUB_REPOSITORY = "Faraphel/MKWF-Install"
|
||||
GITHUB_CONTENT_ROOT = f"https://raw.githubusercontent.com/{GITHUB_REPOSITORY}/master/"
|
||||
|
@ -9,31 +7,19 @@ 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"
|
||||
|
||||
region_ID = {
|
||||
"J": "JAP",
|
||||
"P": "PAL",
|
||||
"K": "KO",
|
||||
"E": "USA"
|
||||
}
|
||||
|
||||
EMPTY_TRACK = ' T T44; T44; 0x00; "_"; ""; "-"\n'
|
||||
|
||||
with open("./translation.json", encoding="utf-8") as f:
|
||||
translation_dict = json.load(f)
|
||||
|
||||
bmgID_track_move = {
|
||||
"T11": 0x7008, "T12": 0x7001, "T13": 0x7002, "T14": 0x7004,
|
||||
"T21": 0x7000, "T22": 0x7005, "T23": 0x7006, "T24": 0x7007,
|
||||
"T31": 0x7009, "T32": 0x700f, "T33": 0x700b, "T34": 0x7003,
|
||||
"T41": 0x700e, "T42": 0x700a, "T43": 0x700c, "T44": 0x700d,
|
||||
"T11": 0x7008, "T12": 0x7001, "T13": 0x7002, "T14": 0x7004,
|
||||
"T21": 0x7000, "T22": 0x7005, "T23": 0x7006, "T24": 0x7007,
|
||||
"T31": 0x7009, "T32": 0x700f, "T33": 0x700b, "T34": 0x7003,
|
||||
"T41": 0x700e, "T42": 0x700a, "T43": 0x700c, "T44": 0x700d,
|
||||
|
||||
"T51": 0x7010, "T52": 0x7014, "T53": 0x7019, "T54": 0x701a,
|
||||
"T61": 0x701b, "T62": 0x701f, "T63": 0x7017, "T64": 0x7012,
|
||||
"T71": 0x7015, "T72": 0x701e, "T73": 0x701d, "T74": 0x7011,
|
||||
"T81": 0x7018, "T82": 0x7016, "T83": 0x7013, "T84": 0x701c,
|
||||
"T51": 0x7010, "T52": 0x7014, "T53": 0x7019, "T54": 0x701a,
|
||||
"T61": 0x701b, "T62": 0x701f, "T63": 0x7017, "T64": 0x7012,
|
||||
"T71": 0x7015, "T72": 0x701e, "T73": 0x701d, "T74": 0x7011,
|
||||
"T81": 0x7018, "T82": 0x7016, "T83": 0x7013, "T84": 0x701c,
|
||||
}
|
||||
trackname_color = {
|
||||
"MSRDS": "\\\\c{green}MSRDS\\\\c{off}",
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import requests
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
from .definition import *
|
||||
|
@ -29,10 +28,4 @@ def get_github_file(self, file):
|
|||
self.log_error()
|
||||
return -1
|
||||
|
||||
|
||||
def check_track_sha1(self, file, excepted_sha1):
|
||||
sha1 = subprocess.run(["./tools/szs/wszst", "SHA1", file, "--autoadd-path", "./file/auto-add/"],
|
||||
check=True, creationflags=CREATE_NO_WINDOW,
|
||||
stdout=subprocess.PIPE).stdout.decode().split(" ")[0]
|
||||
if excepted_sha1 == sha1: return 0
|
||||
else: return -1
|
||||
# TODO: if version > github version, do not search in master branch but dev branch
|
||||
|
|
|
@ -28,7 +28,7 @@ def install_mod(self):
|
|||
max_step += 1
|
||||
|
||||
for fp in fs:
|
||||
for f in glob.glob(self.path_mkwf + "/files/" + fp, recursive=True):
|
||||
for f in glob.glob(self.game.path + "/files/" + fp, recursive=True):
|
||||
if type(fs[fp]) == str:
|
||||
count_rf(path=f)
|
||||
elif type(fs[fp]) == dict:
|
||||
|
@ -66,7 +66,7 @@ def install_mod(self):
|
|||
filecopy(f"./file/{file}", path)
|
||||
|
||||
for fp in fs:
|
||||
for f in glob.glob(self.path_mkwf + "/files/" + fp, recursive=True):
|
||||
for f in glob.glob(self.game.path + "/files/" + fp, recursive=True):
|
||||
if type(fs[fp]) == str:
|
||||
replace_file(path=f, file=fs[fp])
|
||||
elif type(fs[fp]) == dict:
|
||||
|
@ -84,43 +84,44 @@ def install_mod(self):
|
|||
if os.path.exists(file + ".d"): shutil.rmtree(file + ".d")
|
||||
|
||||
self.Progress(statut=self.translate("Patch main.dol"), add=1)
|
||||
subprocess.run(["./tools/szs/wstrt", "patch", get_nodir(self.path_mkwf) + "/sys/main.dol", "--clean-dol",
|
||||
"--add-lecode"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path_mkwf),
|
||||
subprocess.run(["./tools/szs/wstrt", "patch", get_nodir(self.game.path) + "/sys/main.dol", "--clean-dol",
|
||||
"--add-lecode"], creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.game.path),
|
||||
check=True, stdout=subprocess.PIPE)
|
||||
|
||||
self.Progress(statut=self.translate("Patch lecode.bin"), add=1)
|
||||
|
||||
shutil.copytree("./file/Track/", self.path_mkwf+"/files/Race/Course/", dirs_exist_ok=True)
|
||||
if not(os.path.exists(self.path_mkwf+"/tmp/")): os.makedirs(self.path_mkwf+"/tmp/")
|
||||
filecopy("./file/CTFILE.txt", self.path_mkwf+"/tmp/CTFILE.txt")
|
||||
filecopy("./file/lpar-default.txt", self.path_mkwf + "/tmp/lpar-default.txt")
|
||||
filecopy(f"./file/lecode-{self.original_region}.bin", self.path_mkwf + f"/tmp/lecode-{self.original_region}.bin")
|
||||
shutil.copytree("./file/Track/", self.game.path+"/files/Race/Course/", dirs_exist_ok=True)
|
||||
if not(os.path.exists(self.game.path+"/tmp/")): os.makedirs(self.game.path+"/tmp/")
|
||||
filecopy("./file/CTFILE.txt", self.game.path+"/tmp/CTFILE.txt")
|
||||
filecopy("./file/lpar-default.txt", self.game.path + "/tmp/lpar-default.txt")
|
||||
filecopy(f"./file/lecode-{self.game.region}.bin", self.game.path + f"/tmp/lecode-{self.game.region}.bin")
|
||||
|
||||
subprocess.run(
|
||||
["./tools/szs/wlect", "patch", f"./tmp/lecode-{self.original_region}.bin", "-od",
|
||||
f"./files/rel/lecode-{self.original_region}.bin", "--track-dir", "./files/Race/Course/",
|
||||
["./tools/szs/wlect", "patch", f"./tmp/lecode-{self.game.region}.bin", "-od",
|
||||
f"./files/rel/lecode-{self.game.region}.bin", "--track-dir", "./files/Race/Course/",
|
||||
"--move-tracks", "./files/Race/Course/", "--le-define", "./tmp/CTFILE.txt", "--lpar",
|
||||
"./tmp/lpar-default.txt", "--overwrite"],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=self.path_mkwf, check=True, stdout=subprocess.PIPE)
|
||||
creationflags=CREATE_NO_WINDOW, cwd=self.game.path, check=True, stdout=subprocess.PIPE)
|
||||
|
||||
shutil.rmtree(self.path_mkwf + "/tmp/")
|
||||
shutil.rmtree(self.game.path + "/tmp/")
|
||||
|
||||
outputformat = self.stringvar_game_format.get()
|
||||
self.Progress(statut=self.translate("Converting to", " ", outputformat), add=1)
|
||||
|
||||
if outputformat in ["ISO", "WBFS", "CISO"]:
|
||||
self.path_mkwf_format = os.path.realpath(self.path_mkwf + "/../MKWFaraphel." + outputformat.lower())
|
||||
subprocess.run(["./tools/wit/wit", "COPY", get_nodir(self.path_mkwf), "--DEST",
|
||||
get_nodir(self.path_mkwf_format), f"--{outputformat.lower()}", "--overwrite"],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path_mkwf),
|
||||
path_game_format: str = os.path.realpath(self.game.path + "/../MKWFaraphel." + outputformat.lower())
|
||||
subprocess.run(["./tools/wit/wit", "COPY", get_nodir(self.game.path), "--DEST",
|
||||
get_nodir(path_game_format), f"--{outputformat.lower()}", "--overwrite"],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(path_game_format),
|
||||
check=True, stdout=subprocess.PIPE)
|
||||
shutil.rmtree(self.path_mkwf)
|
||||
shutil.rmtree(self.game.path)
|
||||
self.game.path = path_game_format
|
||||
|
||||
self.Progress(statut=self.translate("Changing game's ID"), add=1)
|
||||
subprocess.run(["./tools/wit/wit", "EDIT", get_nodir(self.path_mkwf_format), "--id",
|
||||
f"RMC{self.original_region_ID}60", "--name", f"Mario Kart Wii Faraphel {self.VERSION}",
|
||||
"--modify", "ALL"],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.path_mkwf_format),
|
||||
subprocess.run(["./tools/wit/wit", "EDIT", get_nodir(self.game.path), "--id",
|
||||
f"RMC{self.game.region_ID}60", "--name",
|
||||
f"Mario Kart Wii Faraphel {self.ctconfig.version}", "--modify", "ALL"],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.game.path),
|
||||
check=True, stdout=subprocess.PIPE)
|
||||
|
||||
messagebox.showinfo(self.translate("End"), self.translate("The mod has been installed !"))
|
||||
|
|
|
@ -11,6 +11,9 @@ default_option = {
|
|||
"process_track": 8
|
||||
}
|
||||
|
||||
with open("./translation.json", encoding="utf-8") as f:
|
||||
translation_dict = json.load(f)
|
||||
|
||||
|
||||
def change_option(self, option, value, restart=False):
|
||||
if type(value) in [str, int, bool]: self.option[option] = value
|
||||
|
|
|
@ -8,7 +8,7 @@ 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.VERSION}"
|
||||
MAINMENU_REPLACE = f"MKWFaraphel {self.ctconfig.version}"
|
||||
menu_replacement = {
|
||||
"CWF de Nintendo": NINTENDO_CWF_REPLACE,
|
||||
"Wi-Fi Nintendo": NINTENDO_CWF_REPLACE,
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
from PIL import Image, ImageFont, ImageDraw
|
||||
import json
|
||||
import math
|
||||
import os
|
||||
|
||||
|
||||
def get_cup_icon(i):
|
||||
if os.path.exists(f"./file/cup_icon/{id}.png"):
|
||||
cup_icon = Image.open(f"./file/cup_icon/{id}.png").resize((128, 128))
|
||||
|
||||
else:
|
||||
cup_icon = Image.new("RGBA", (128, 128))
|
||||
draw = ImageDraw.Draw(cup_icon)
|
||||
font = ImageFont.truetype("./file/SuperMario256.ttf", 90)
|
||||
draw.text((4 - 2, 4 - 2), "CT", (0, 0, 0), font=font)
|
||||
draw.text((4 + 2, 4 - 2), "CT", (0, 0, 0), font=font)
|
||||
draw.text((4 - 2, 4 + 2), "CT", (0, 0, 0), font=font)
|
||||
draw.text((4 + 2, 4 + 2), "CT", (0, 0, 0), font=font)
|
||||
draw.text((4, 4), "CT", (255, 165, 0), font=font)
|
||||
|
||||
font = ImageFont.truetype("./file/SuperMario256.ttf", 60)
|
||||
draw.text((5 - 2, 80 - 2), "%03i" % (i - 10), (0, 0, 0), font=font) # i-10 because first 8 cup are not
|
||||
draw.text((5 + 2, 80 - 2), "%03i" % (i - 10), (0, 0, 0), font=font) # counted as new, random cup,
|
||||
draw.text((5 - 2, 80 + 2), "%03i" % (i - 10), (0, 0, 0), font=font) # left and right arrow
|
||||
draw.text((5 + 2, 80 + 2), "%03i" % (i - 10), (0, 0, 0), font=font)
|
||||
|
||||
draw.text((5, 80), "%03i" % (i - 10), (255, 165, 0), font=font)
|
||||
return cup_icon
|
||||
|
||||
|
||||
def patch_ct_icon(self):
|
||||
try:
|
||||
with open("./ct_config.json", encoding="utf8") as f: config = json.load(f)
|
||||
|
||||
cup_number = len(config["cup"]) + math.ceil(len(config["tracks_list"]) / 4)
|
||||
ct_icon = Image.new("RGBA", (128, 128 * (cup_number + 2)))
|
||||
|
||||
files = ["left", "right"]
|
||||
files.extend(config["cup"].keys())
|
||||
files.extend(["_"] * ((len(config["tracks_list"]) // 4) + 1))
|
||||
|
||||
for i, id in enumerate(files):
|
||||
cup_icon = get_cup_icon(i)
|
||||
ct_icon.paste(cup_icon, (0, i * 128))
|
||||
|
||||
ct_icon.save("./file/ct_icons.tpl.png")
|
||||
|
||||
except:
|
||||
self.log_error()
|
|
@ -9,23 +9,26 @@ def patch_file(self):
|
|||
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"]) + self.TOTAL_TRACK + 3 + len("EGFIS")
|
||||
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.create_lecode_config()
|
||||
self.ctconfig.create_ctfile()
|
||||
|
||||
self.Progress(statut=self.translate("Creating ct_icon.png"), add=1)
|
||||
self.patch_ct_icon()
|
||||
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.path_mkwf+"/files/Scene/UI/MenuSingle_?.szs"): self.patch_bmg(file)
|
||||
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.VERSION, ")"))
|
||||
self.button_install_mod.config(text=self.translate("Install mod", " (v", self.ctconfig.version, ")"))
|
||||
|
||||
except: self.log_error()
|
||||
finally: self.Progress(show=False)
|
||||
|
|
|
@ -2,69 +2,18 @@ from .definition import *
|
|||
from tkinter import messagebox
|
||||
import subprocess
|
||||
import shutil
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
def get_trackname(self, track, color=False):
|
||||
hl_prefix, hl_suffix = "", ""
|
||||
if color:
|
||||
if track.get("since_version") == self.stringvar_mark_track_from_version.get():
|
||||
hl_prefix, hl_suffix = "\\\\c{blue1}", "\\\\c{off}"
|
||||
|
||||
name = track["name"]
|
||||
name = hl_prefix + name + hl_suffix
|
||||
|
||||
if "prefix" in track:
|
||||
prefix = track["prefix"]
|
||||
if color:
|
||||
if prefix in trackname_color:
|
||||
prefix = trackname_color[prefix]
|
||||
name = prefix + " " + name
|
||||
if "suffix" in track:
|
||||
suffix = track["suffix"]
|
||||
if color:
|
||||
if suffix in trackname_color:
|
||||
suffix = trackname_color[suffix]
|
||||
name = name + " (" + suffix + ")"
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def get_trackctname(self, *args, **kwargs):
|
||||
return self.get_trackname(*args, **kwargs).replace("_", "")
|
||||
|
||||
|
||||
def load_ct_config(self):
|
||||
tracks = []
|
||||
with open("./ct_config.json", encoding="utf-8") as f: ctconfig = json.load(f)
|
||||
|
||||
for cup in ctconfig["cup"].values(): # defined order tracks
|
||||
if not (cup["locked"]): tracks.extend(cup["courses"].values())
|
||||
|
||||
tracks.extend(ctconfig["tracks_list"]) # unordered tracks
|
||||
|
||||
self.TRACKS = [dict(t) for t in {tuple(d.items()) for d in tracks}] # removing duplicate
|
||||
self.TOTAL_TRACK = len(tracks)
|
||||
|
||||
self.VERSION = ctconfig["version"]
|
||||
|
||||
self.ALL_VERSION = []
|
||||
for track in self.TRACKS:
|
||||
if not track.get("since_version") in self.ALL_VERSION:
|
||||
self.ALL_VERSION.append(track["since_version"])
|
||||
self.ALL_VERSION.sort()
|
||||
|
||||
|
||||
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),
|
||||
if not os.path.exists(self.game.path + "/tmp/"): os.makedirs(self.game.path + "/tmp/")
|
||||
subprocess.run(["./tools/szs/wszst", "AUTOADD", get_nodir(self.game.path) + "/files/Race/Course/",
|
||||
"--DEST", get_nodir(self.game.path) + "/tmp/auto-add/"],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(self.game.path),
|
||||
check=True, stdout=subprocess.PIPE)
|
||||
shutil.move(self.path_mkwf + "/tmp/auto-add/", "./file/auto-add/")
|
||||
shutil.rmtree(self.path_mkwf + "/tmp/")
|
||||
shutil.move(self.game.path + "/tmp/auto-add/", "./file/auto-add/")
|
||||
shutil.rmtree(self.game.path + "/tmp/")
|
||||
|
||||
|
||||
def patch_track(self):
|
||||
|
@ -73,20 +22,21 @@ def patch_track(self):
|
|||
error_count, error_max = 0, 3
|
||||
|
||||
def add_process(track):
|
||||
track_file = self.get_trackname(track=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
|
||||
self.Progress(statut=self.translate("Converting tracks", f"\n({i + 1}/{self.TOTAL_TRACK})\n",
|
||||
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 [get_track_szs(track_file), get_track_wu8(track_file)]:
|
||||
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)
|
||||
|
||||
while True:
|
||||
download_returncode = self.get_github_file(get_track_wu8(track_file))
|
||||
download_returncode = self.get_github_file(track.file_wu8)
|
||||
if download_returncode == -1: # can't download
|
||||
error_count += 1
|
||||
if error_count > error_max: # Too much track wasn't correctly converted
|
||||
|
@ -100,9 +50,9 @@ def patch_track(self):
|
|||
f" ({error_count} / {error_max})"))
|
||||
elif download_returncode == 2: break # if download is disabled, don't check sha1
|
||||
|
||||
if "sha1" in track:
|
||||
if track.sha1:
|
||||
if not self.boolvar_dont_check_track_sha1.get():
|
||||
if not self.check_track_sha1(get_track_wu8(track_file), track["sha1"]) == 0: # La course est correcte
|
||||
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(
|
||||
|
@ -113,18 +63,14 @@ def patch_track(self):
|
|||
|
||||
break
|
||||
|
||||
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)
|
||||
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(get_track_wu8(track_file))
|
||||
elif self.boolvar_del_track_after_conv.get(): os.remove(track.file_wu8)
|
||||
return 0
|
||||
|
||||
def clean_process():
|
||||
|
@ -138,7 +84,7 @@ def patch_track(self):
|
|||
process_list.pop(track_file)
|
||||
stderr = process.stderr.read()
|
||||
if b"wszst: ERROR" in stderr: # Error occured
|
||||
os.remove(get_track_szs(track_file))
|
||||
os.remove(track.file_szs)
|
||||
error_count += 1
|
||||
if error_count > error_max: # Too much track wasn't correctly converted
|
||||
messagebox.showerror(
|
||||
|
@ -152,7 +98,7 @@ def patch_track(self):
|
|||
"do not have been properly converted.",
|
||||
f" ({error_count} / {error_max})"))
|
||||
else:
|
||||
if self.boolvar_del_track_after_conv.get(): os.remove(get_track_wu8(track_file))
|
||||
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
|
||||
|
@ -160,7 +106,7 @@ def patch_track(self):
|
|||
if len(process_list): return 1
|
||||
else: return 0
|
||||
|
||||
for i, track in enumerate(self.TRACKS):
|
||||
for i, track in enumerate(self.ctconfig.all_tracks):
|
||||
while True:
|
||||
if len(process_list) < max_process:
|
||||
returncode = add_process(track)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from .definition import translation_dict
|
||||
from .option import translation_dict
|
||||
|
||||
|
||||
def translate(self, *texts, lang=None):
|
||||
|
|
|
@ -13,8 +13,9 @@ def sha1(file):
|
|||
|
||||
|
||||
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/", use_popen: bool = False):
|
||||
"""
|
||||
:param use_popen: True if you want to use Popen to convert
|
||||
:param src_file: source file
|
||||
:param dest_dir: destination directory
|
||||
:param dest_name: destination filename (%N mean same name as src_file)
|
||||
|
@ -22,13 +23,31 @@ def normalize(src_file: str, dest_dir: str = "./file/Track/", dest_name: str = "
|
|||
:param autoadd_path: path of the auto-add directory
|
||||
:return: 0
|
||||
"""
|
||||
subprocess.run([
|
||||
if use_popen: cmd_process = subprocess.Popen
|
||||
else: cmd_process = subprocess.run
|
||||
return cmd_process([
|
||||
"./tools/szs/wszst", "NORMALIZE", src_file, "--DEST",
|
||||
dest_dir+dest_name, "--"+output_format, "--overwrite", "--autoadd-path",
|
||||
autoadd_path], creationflags=CREATE_NO_WINDOW, stderr=subprocess.PIPE)
|
||||
return 0
|
||||
|
||||
|
||||
def extract(file: str, dest_dir: str):
|
||||
subprocess.call(["./tools/wit/wit", "EXTRACT", get_nodir(file), "--DEST", dest_dir],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
||||
subprocess.run(["./tools/wit/wit", "EXTRACT", get_nodir(file), "--DEST", dest_dir],
|
||||
creationflags=CREATE_NO_WINDOW, cwd=get_dir(file))
|
||||
|
||||
|
||||
def create(file: str):
|
||||
pass
|
||||
|
||||
|
||||
def wstrt_patch(file: str):
|
||||
pass
|
||||
|
||||
|
||||
def wlect_patch(file: str,
|
||||
lecode_file: str = f"./files/rel/lecode-PAL.bin",
|
||||
game_track_path: str = "./files/Race/Course/",
|
||||
move_track_path: str = "./files/Race/Course/",
|
||||
ctfile_path: str = "./tmp/CTFILE.txt",
|
||||
lpar_path: str = "./tmp/lpar-default.txt"):
|
||||
pass
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
"Wii game": "Jeu Wii",
|
||||
"Error": "Erreur",
|
||||
"The file path in invalid": "Le chemin de fichier est invalide",
|
||||
"This game's format is invalid": "Le format du jeu est invalide",
|
||||
"Warning": "Attention",
|
||||
"This directory will be overwritten if you install the mod !\nAre you sure you want to use it ?": "Ce dossier sera écrasé si vous installer le mod !\nÊtes-vous sûr de vouloir l'utiliser ?",
|
||||
"Extracting the game...": "Extraction du jeu...",
|
||||
|
|
Loading…
Reference in a new issue