From 3f960205be3b51a5f2cef312157b536807ecd903 Mon Sep 17 00:00:00 2001 From: atoring Date: Fri, 6 Jul 2018 14:59:34 +0900 Subject: [PATCH] add: patch movie --- frostpunk_mod/archive.py | 1 + frostpunk_mod/backup.py | 2 + frostpunk_mod/gui.py | 70 ++++++++++++++++++++++++------ frostpunk_mod/patch_japanese.py | 77 +++++++++++++++++++++++++++++++++ 4 files changed, 136 insertions(+), 14 deletions(-) diff --git a/frostpunk_mod/archive.py b/frostpunk_mod/archive.py index e9c072a..23a4a5d 100644 --- a/frostpunk_mod/archive.py +++ b/frostpunk_mod/archive.py @@ -16,6 +16,7 @@ polish_lang_id = 0x7d919140 russian_lang_id = 0xf2232be3 chinese_lang_id = 0xfce49418 +intro_mov_id = 0xc3470d1b lang_ids = [ english_lang_id, french_lang_id, diff --git a/frostpunk_mod/backup.py b/frostpunk_mod/backup.py index b1a8cf7..17386b1 100644 --- a/frostpunk_mod/backup.py +++ b/frostpunk_mod/backup.py @@ -12,6 +12,8 @@ "common.dat", "localizations.idx", "localizations.dat", + "videos.idx", + "videos.dat", ] class Backup(): diff --git a/frostpunk_mod/gui.py b/frostpunk_mod/gui.py index b9e05f1..618143d 100644 --- a/frostpunk_mod/gui.py +++ b/frostpunk_mod/gui.py @@ -33,7 +33,7 @@ _def_game_path2 = r"C:\Program Files\Steam\SteamApps\common\Frostpunk" _game_exe = "Frostpunk.exe" -_win_size = "420x535" +_win_size = "420x585" _win_frame_col = "gray" _version_fg_col = "darkblue" _inf_fg_col = "darkgreen" @@ -83,8 +83,8 @@ def exec_path(path, cur_path): subprocess.Popen([path], cwd=cur_path) def open_csv(path): - "execute .csv program" - log("execute .csv program", path) + "execute csv program" + log("execute csv program", path) path = correct_path(path) if check_path(path): subprocess.Popen(["start", "", path], shell=True) @@ -278,9 +278,9 @@ def __init__(self, master=None): self.frame = LabelFrame(master, text="設定") self.game_path_frame = Frame(self.frame) - self.game_path_label = Label(self.game_path_frame, text="ゲームパス:") + self.game_path_label = Label(self.game_path_frame, text="ゲームパス") self.game_path_entry = Entry(self.game_path_frame, text=master.game_path) - self.open_game_dlg_btn = LButton(self.game_path_frame, text="...", command=self.open_game_dlg) + self.open_game_dlg_btn = LButton(self.game_path_frame, text="参照", command=self.open_game_dlg) self.game_misc_frame = Frame(self.frame) self.exec_game_btn = LButton(self.game_misc_frame, text="ゲームを起動", command=self.exec_game) @@ -338,11 +338,12 @@ def __init__(self, master=None): "constructor" self.frame = LabelFrame(master, text="データ管理") - self.backup_btn = Button(self.frame, text="パッチに関係するデータ(4ファイル)をバックアップ", command=lambda arg=master: self.backup(arg)) - self.restore_btn = Button(self.frame, risk=True, text="パッチに関係するデータ(4ファイル)をリストア", command=lambda arg=master: self.restore(arg)) + self.backup_btn = Button(self.frame, text="パッチに関係するデータ(6ファイル)をバックアップ", command=lambda arg=master: self.backup(arg)) + self.restore_btn = Button(self.frame, risk=True, text="パッチに関係するデータ(6ファイル)をリストア", command=lambda arg=master: self.restore(arg)) self.open_data_exp_btn = Button(self.frame, text="バックアップデータフォルダを開く", command=self.open_backup_path) - self.download_sheet_btn = Button(self.frame, text="翻訳シート(.csv)をWebサイトからダウンロード", command=self.download_sheet) - self.open_sheet_btn = Button(self.frame, text="ダウンロードした翻訳シート(.csv)を開く", command=self.open_sheet) + self.download_sheet_btn = Button(self.frame, text="翻訳シート(csv)をWebサイトからダウンロード", command=self.download_sheet) + self.open_sheet_btn = Button(self.frame, text="ダウンロードした翻訳シート(csv)を開く", command=self.open_sheet) + self.download_movie_btn = Button(self.frame, text="( 字幕付き動画をダウンロード(任意) )", command=self.download_movie) def backup(self, master): "backup data" @@ -411,8 +412,8 @@ def download_sheet(self): error_msg("翻訳シートをダウンロードできませんでした。") def open_sheet(self): - "open .csv sheet" - log("open .csv sheet") + "open csv sheet" + log("open csv sheet") sheet = patch_japanese.Sheet() if not sheet.exists: error_msg("翻訳シートがありません。\n一度ダウンロードする必要があります。") @@ -421,6 +422,22 @@ def open_sheet(self): if check_path(path): open_csv(path) + def download_movie(self): + "download movie" + log("download movie") + ret = question_msg("字幕付き動画をダウンロードします。若干時間が掛かります。\n300Mバイトほどのファイルをダウンロードします。\nよろしいですか?") + if ret != "yes": + return + movie = patch_japanese.Movie() + if movie.exists: + ret = question_msg("動画を上書きします。\nよろしいですか?", risk=True) + if ret != "yes": + return + if movie.fetch(): + info_msg("動画をダウンロードしました。") + else: + error_msg("動画をダウンロードできませんでした。") + class Patch(): "patch frame" @@ -430,7 +447,8 @@ def __init__(self, master=None): self.patch_font_btn = Button(self.frame, risk=True, text="フォント(binfont)パッチを適応", command=lambda arg=master: self.patch_font(arg)) self.patch_lang_btn = Button(self.frame, risk=True, text="翻訳(lang)パッチを適応", command=lambda arg=master: self.patch_lang(arg)) - self.open_lang_btn = Button(self.frame, text="ゲームの翻訳シート(.csv)を開く", command=self.open_lang) + self.open_lang_btn = Button(self.frame, text="ゲームの翻訳シート(csv)を開く", command=self.open_lang) + self.patch_movie_btn = Button(self.frame, risk=True, text="( 動画パッチを適応(任意) )", command=lambda arg=master: self.patch_movie(arg)) def patch_font(self, master): "patch font" @@ -477,8 +495,8 @@ def patch_lang(self, master): error_msg("翻訳パッチを適応できませんでした。") def open_lang(self): - "open lang .csv sheet" - log("open lang .csv sheet") + "open lang csv sheet" + log("open lang csv sheet") patch = patch_japanese.Patch() if not patch.lang_exists: error_msg("ゲームの翻訳シートがありません。\n一度翻訳パッチを適応する必要があります。") @@ -487,6 +505,30 @@ def open_lang(self): if check_path(path): open_csv(path) + def patch_movie(self, master): + "patch movie" + log("patch movie") + path = master.config.game_path + if not path: + error_msg("ゲームパスを設定してください。") + return + bk = backup.Backup() + if not bk.exists: + error_msg("バックアップデータがありません。\n一度バックアップをする必要があります。") + return + movie = patch_japanese.Movie() + if not movie.exists: + error_msg("字幕付き動画がありません。\n一度ダウンロードする必要があります。") + return + ret = question_msg("動画パッチを適応します。若干時間が掛かります。\nよろしいですか?", risk=True) + if ret != "yes": + return + patch = patch_japanese.Patch() + if patch.patch_movie(path): + info_msg("動画パッチを適応しました。") + else: + error_msg("動画パッチを適応できませんでした。") + class Link(): "link frame" diff --git a/frostpunk_mod/patch_japanese.py b/frostpunk_mod/patch_japanese.py index 524956a..73bba30 100644 --- a/frostpunk_mod/patch_japanese.py +++ b/frostpunk_mod/patch_japanese.py @@ -18,8 +18,13 @@ _sheet_path = "data" _sheet_file = "Frostpunk 翻訳作業所 - 翻訳.csv" +_movie_url = "https://raw.githubusercontent.com/atoring/frostpunk_mod/develop/movie/url.txt" +_movie_path = "data" +_movie_file = "intro_wide_ja.ogv" + _cmn_file = "common" _loc_file = "localizations" +_vid_file = "videos" _font_path = "data" _font_zip_file = "notosanscjksc-medium.otf.binfont.zip" @@ -141,6 +146,45 @@ def sheet_path(self): "get sheet path" return self.__sheet_file +class Movie(): + "subtitled movie" + + def __init__(self): + "constructor" + path = os.path.join(get_prog_path(), _movie_path) + path = path.replace("/", os.sep) + self.__movie_path = path + path = os.path.join(path, _movie_file) + self.__movie_file = path + + def fetch(self): + "fetch movie" + log("fetch movie", _movie_url) + try: + url = urllib.request.urlopen(_movie_url).read().decode("utf-8-sig") + log("movie url", url) + data = urllib.request.urlopen(url).read() + except: + log("error", "fetch movie", _movie_url) + return False + if not make_dir(self.__movie_path): + return False + if not write_bin(self.__movie_file, data): + return False + # write Zone.Identifier to NTFS stream of csv file + write_txt(self.__movie_file+":Zone.Identifier", "[ZoneTransfer]\nZoneId=3", "ascii") + return True + + @property + def exists(self): + "check exsits movie file" + return os.path.isfile(self.__movie_file) + + @property + def movie_path(self): + "get movie path" + return self.__movie_file + class Patch(): "patch japanese translation" @@ -162,6 +206,12 @@ def __init__(self): path = os.path.join(path, _lang_file) self.__lang_file = path + path = os.path.join(get_prog_path(), _movie_path) + path = path.replace("/", os.sep) + self.__movie_path = path + path = os.path.join(self.__movie_path, _movie_file) + self.__movie_file = path + path = os.path.join(get_prog_path(), _tmp_path) path = path.replace("/", os.sep) self.__tmp_path = path @@ -260,6 +310,33 @@ def patch_lang(self, path): delete_dir(self.__tmp_path) return True + def patch_movie(self, path): + "patch movie file" + log("patch movie file", path) + bk = backup.Backup() + bk_vid_path = os.path.join(bk.backup_path, _vid_file) + tmp_vid_path = os.path.join(self.__tmp_path, _vid_file) + game_vid_path = os.path.join(path, _vid_file) + movie = read_bin(self.__movie_file) + if not movie: + return False + with archive.Archive() as arc: + if not arc.read_archive(bk_vid_path): + return False + if not arc.set_file(archive.intro_mov_id, movie): + return False + if not make_dir(self.__tmp_path): + return False + if not arc.write_archive(tmp_vid_path): + delete_dir(self.__tmp_path) + return False + if not self.__copy_archive(game_vid_path, tmp_vid_path): + self.__copy_archive(game_vid_path, bk_vid_path) + delete_dir(self.__tmp_path) + return False + delete_dir(self.__tmp_path) + return True + def __copy_archive(self, dst, src): "copy archive file" log("copy archive file", dst, src)