Skip to content

Instantly share code, notes, and snippets.

@TeoTwawki
Forked from zach2good/npc_renamer.py
Created November 10, 2022 16:56
Show Gist options
  • Save TeoTwawki/ca03343c490086958b1abfdc4438f381 to your computer and use it in GitHub Desktop.
Save TeoTwawki/ca03343c490086958b1abfdc4438f381 to your computer and use it in GitHub Desktop.
NPC DAT Renamer script for FFXI
#!/usr/bin/env python
# npc_renamer by zach2good, use as you please!
#
# For use on the NPC DATs listed here:
# https://www.reddit.com/r/ffximodding/comments/9ndg2d/complete_list_of_zone_dats_by_zone_id/
#
# Usage: npc_renamer.py <input file to read>
# : If the input file is .DAT, a corresponding .json file will be made.
# : If the input file is .json, a corresponding .new.DAT file will be made.
#
# Alternate usage: npc_renamer.py <filename1> <filename2>
# : You can use the script this way to binary compare two files.
#
# Examples:
#
# Prints the help message:
# .\npc_renamer.py
#
# Will generate 114.json, which you can edit the strings inside:
# .\npc_renamer.py 114.DAT
#
# Will generate 114.new.DAT, which you can rename and use with XIPivot or whatever:
# .\npc_renamer.py 114.json
#
# Will binary compare two files (useful to make sure the script is working as expected
# with no edits):
# .\npc_renamer.py 114.DAT 114.new.DAT
import sys
import json
import filecmp
def to_json_file(dat_filename, json_filename):
out_dict = {}
with open(dat_filename, mode="rb") as file:
index = 0
while data := file.read(32):
last_four_bytes = list(data[0x1C:])
data = data.split(b"\x00")[0]
data = data.decode(encoding="ascii", errors="ignore")
out_dict[index] = (data, last_four_bytes)
index = index + 1
json_data = json.dumps(out_dict, indent=4)
with open(json_filename, "w") as out_file:
out_file.write(json_data)
def to_dat_file(json_filename, dat_filename):
data = {}
with open(json_filename) as json_file:
data = json.load(json_file)
with open(dat_filename, "wb") as out_file:
for value in data.values():
name = value[0]
if len(name) > 27:
print(f"Name is too long!: {name}")
print(f"Maximum length is 27, got {len(name)}.")
sys.exit(-1)
last_four_bytes = value[1]
data = bytearray(32)
data[0 : len(name)] = bytearray(name, encoding="ascii")
data[0x1C] = last_four_bytes[0]
data[0x1D] = last_four_bytes[1]
data[0x1E] = last_four_bytes[2]
data[0x1F] = last_four_bytes[3]
out_file.write(data)
def compare(file1, file2):
print(file1)
print(file2)
if filecmp.cmp(file1, file2):
print("Files are binary twins!")
else:
print("Files are different!")
def print_help():
print("Usage: npc_renamer.py <input file to read>")
print(" : If the input file is .DAT, a corresponding .json file will be made.")
print(" : If the input file is .json, a corresponding .new.DAT file will be made.")
print("")
print("Alternate usage: npc_renamer.py <filename1> <filename2>")
print(" : You can use the script this way to binary compare two files.")
def main() -> int:
if len(sys.argv) == 1:
print_help()
return -1
if len(sys.argv) == 2:
input_filename = sys.argv[1]
if input_filename.endswith(".DAT"):
output_filename = input_filename.replace(".DAT", ".json")
to_json_file(input_filename, output_filename)
elif input_filename.endswith(".json"):
output_filename = input_filename.replace(".json", ".new.DAT")
to_dat_file(input_filename, output_filename)
elif len(sys.argv) == 3:
filename1 = sys.argv[1]
filename2 = sys.argv[2]
compare(filename1, filename2)
return 0
if __name__ == "__main__":
sys.exit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment