mirror of
https://github.com/Virtual-World-RE/NeoGF.git
synced 2024-11-15 10:45:33 +01:00
Update pzztool.py
Added file_format autodetect ->TPL format is now handled
This commit is contained in:
parent
5fe8aecfbf
commit
54bf1b1d02
52
pzztool.py
52
pzztool.py
|
@ -6,7 +6,7 @@ from struct import unpack
|
||||||
from os import listdir
|
from os import listdir
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
__version__ = "1.4.0"
|
__version__ = "1.4.1"
|
||||||
__author__ = "rigodron, algoflash, GGLinnk"
|
__author__ = "rigodron, algoflash, GGLinnk"
|
||||||
__OriginalAutor__ = "infval"
|
__OriginalAutor__ = "infval"
|
||||||
__license__ = "MIT"
|
__license__ = "MIT"
|
||||||
|
@ -20,6 +20,19 @@ __status__ = "developpement"
|
||||||
BIT_COMPRESSION_FLAG = 0x40000000
|
BIT_COMPRESSION_FLAG = 0x40000000
|
||||||
FILE_LENGTH_MASK = 0x3FFFFFFF
|
FILE_LENGTH_MASK = 0x3FFFFFFF
|
||||||
CHUNK_SIZE = 0x800
|
CHUNK_SIZE = 0x800
|
||||||
|
TPL_MAGIC_NUMBER = b"\x00\x20\xAF\x30" # http://virtualre.rf.gd/index.php/TPL_(Format_de_fichier)
|
||||||
|
|
||||||
|
|
||||||
|
def get_file_ext(file_content: bytes):
|
||||||
|
if file_content[0:4] == TPL_MAGIC_NUMBER:
|
||||||
|
return ".tpl"
|
||||||
|
# Par défaut
|
||||||
|
return ".dat"
|
||||||
|
|
||||||
|
|
||||||
|
def bytes_align(bout: bytes):
|
||||||
|
while len(bout) % CHUNK_SIZE > 0:
|
||||||
|
bout.extend(b"\x00")
|
||||||
|
|
||||||
|
|
||||||
def pzz_decompress(compressed_bytes: bytes):
|
def pzz_decompress(compressed_bytes: bytes):
|
||||||
|
@ -64,11 +77,6 @@ def pzz_decompress(compressed_bytes: bytes):
|
||||||
return uncompressed_bytes
|
return uncompressed_bytes
|
||||||
|
|
||||||
|
|
||||||
def bytes_align(bout: bytes):
|
|
||||||
while len(bout) % CHUNK_SIZE > 0:
|
|
||||||
bout.extend(b"\x00")
|
|
||||||
|
|
||||||
|
|
||||||
def pzz_compress(b: bytes):
|
def pzz_compress(b: bytes):
|
||||||
bout = bytearray()
|
bout = bytearray()
|
||||||
size_b = len(b) // 2 * 2
|
size_b = len(b) // 2 * 2
|
||||||
|
@ -191,25 +199,29 @@ def pzz_unpack(pzz_path: Path, dest_folder: Path, auto_decompress: bool = False)
|
||||||
|
|
||||||
# On forme le nom du nouveau fichier que l'on va extraire
|
# On forme le nom du nouveau fichier que l'on va extraire
|
||||||
filename = f"{index:03}{compression_status}_{pzz_path.stem}"
|
filename = f"{index:03}{compression_status}_{pzz_path.stem}"
|
||||||
if auto_decompress or compression_status == 'U':
|
file_path = unpacked_pzz_path / filename
|
||||||
file_path = (unpacked_pzz_path / filename).with_suffix(".dat")
|
|
||||||
else:
|
|
||||||
file_path = (unpacked_pzz_path / filename).with_suffix(".pzzp")
|
|
||||||
|
|
||||||
logging.debug(f" -> Offset: {offset:010} - {file_path}")
|
logging.debug(f" -> Offset: {offset:010} - {file_path}")
|
||||||
|
|
||||||
# Si la taille est nulle, on créé un fichier vide et on passe au descripteur de fichier suivant
|
# Si la taille est nulle, on créé un fichier vide et on passe au descripteur de fichier suivant
|
||||||
if file_len == 0:
|
if file_len == 0:
|
||||||
file_path.touch()
|
file_path.with_suffix(".dat").touch()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# On se positionne au début du fichier dans l'archive
|
# On se positionne au début du fichier dans l'archive
|
||||||
pzz_file.seek(offset)
|
pzz_file.seek(offset)
|
||||||
# On extrait notre fichier et on le décompresse
|
# On extrait notre fichier et on le décompresse
|
||||||
if compression_status == 'C' and auto_decompress:
|
if compression_status == 'C' and auto_decompress:
|
||||||
file_path.write_bytes(pzz_decompress(pzz_file.read(file_len)))
|
file_content = pzz_decompress(pzz_file.read(file_len))
|
||||||
else:
|
else:
|
||||||
file_path.write_bytes(pzz_file.read(file_len))
|
file_content = pzz_file.read(file_len)
|
||||||
|
|
||||||
|
if not auto_decompress and compression_status != 'U':
|
||||||
|
file_path = file_path.with_suffix(".pzzp")
|
||||||
|
else:
|
||||||
|
file_path = file_path.with_suffix(get_file_ext(file_content))
|
||||||
|
|
||||||
|
file_path.write_bytes(file_content)
|
||||||
|
|
||||||
# Enfin, on ajoute la taille du fichier afin de pointer sur le fichier suivant
|
# Enfin, on ajoute la taille du fichier afin de pointer sur le fichier suivant
|
||||||
# La taille du fichier étant un multiple de CHUNK_SIZE, on aura complété les 2048 octets finaux avec des 0x00
|
# La taille du fichier étant un multiple de CHUNK_SIZE, on aura complété les 2048 octets finaux avec des 0x00
|
||||||
|
@ -336,15 +348,17 @@ if __name__ == '__main__':
|
||||||
p_output.write_bytes(pzz_compress(p_input.read_bytes()))
|
p_output.write_bytes(pzz_compress(p_input.read_bytes()))
|
||||||
elif args.decompress:
|
elif args.decompress:
|
||||||
logging.info("### Decompress")
|
logging.info("### Decompress")
|
||||||
if(p_output == Path(".")):
|
if p_output == Path("."):
|
||||||
p_output = p_input.parent / (p_input.stem+".dat")
|
p_output = p_input.parent / p_input.stem
|
||||||
|
|
||||||
# Si on a pas la bonne extension on ne decompresse pas le fichier
|
# Si on a pas la bonne extension on ne decompresse pas le fichier
|
||||||
if not args.disable_ignore and p_input.suffix != ".pzzp":
|
if not args.disable_ignore and p_input.suffix != ".pzzp":
|
||||||
logging.warning(f"Ignored - {p_input} - bad extension - must be a pzzp")
|
logging.warning(f"Ignored - {p_input} - bad extension - must be a pzzp")
|
||||||
else:
|
else:
|
||||||
|
output_file_content = pzz_decompress(p_input.read_bytes())
|
||||||
|
p_output = p_output.with_suffix(get_file_ext(output_file_content))
|
||||||
logging.info(f"Decompressing {p_input} in {p_output}")
|
logging.info(f"Decompressing {p_input} in {p_output}")
|
||||||
p_output.write_bytes(pzz_decompress(p_input.read_bytes()))
|
p_output.write_bytes(output_file_content)
|
||||||
elif args.batch_compress:
|
elif args.batch_compress:
|
||||||
logging.info("### Batch Compress")
|
logging.info("### Batch Compress")
|
||||||
p_output.mkdir(exist_ok=True)
|
p_output.mkdir(exist_ok=True)
|
||||||
|
@ -370,8 +384,10 @@ if __name__ == '__main__':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
logging.info(f"Decompressing {filename}")
|
logging.info(f"Decompressing {filename}")
|
||||||
with open(p_output / (Path(filename).stem+".dat"), 'wb') as uncompressed, open(p_input / filename, 'rb') as compressed:
|
with open(p_input / filename, 'rb') as compressed:
|
||||||
uncompressed.write(pzz_decompress(compressed.read()))
|
uncompressed_content = pzz_decompress(compressed.read())
|
||||||
|
with open(p_output / Path(filename).with_suffix(get_file_ext(uncompressed_content)), 'wb') as uncompressed :
|
||||||
|
uncompressed.write(uncompressed_content)
|
||||||
elif args.pack:
|
elif args.pack:
|
||||||
logging.info("### Pack")
|
logging.info("### Pack")
|
||||||
pzz_pack(p_input, p_output)
|
pzz_pack(p_input, p_output)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user