Advertisement
ETikhonov

Wizardry 8 save character export

Nov 4th, 2023 (edited)
1,105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 2.18 KB | Gaming | 0 0
  1. """
  2. LICENCE: free, do whatever you want
  3. This script exports characters from Wizardry 8 save games into CHR files.
  4.  
  5. OFFSETS:
  6. NAME, NICKNAME  9, 29
  7. For future use
  8. STRENGTH        233, 237
  9. INTELLIGENCE    253, 257
  10. PIETY           273, 277
  11. VITALITY        293, 297
  12. DEXTERITY       313, 317
  13. SPEED           333, 337
  14. SENSES          353, 357
  15.  
  16. """
  17.  
  18. from pathlib import Path
  19. from argparse import ArgumentParser
  20.  
  21. # Constants: starting byte sequence of character and character data length
  22. HEADER = b'b\x18\x00\x00\x01\x00\x00\x00'
  23. CHRLEN = 6246
  24.  
  25.  
  26. def find_all(a_str, sub):
  27.     """
  28.    Function to find all occurrence of substring in string
  29.    :param a_str: string to search in
  30.    :param sub: substring to search for
  31.    :return: found offsets
  32.    """
  33.     start = 0
  34.     while True:
  35.         start = a_str.find(sub, start)
  36.         if start == -1:
  37.             return
  38.         yield start
  39.         start += len(sub)
  40.  
  41.  
  42. def main(args):
  43.     savebin = Path(args.save).read_bytes()
  44.     party_offsets = list(find_all(savebin, HEADER))
  45.     if len(party_offsets) == 0:
  46.         print('No characters found!')
  47.     for offset in party_offsets:
  48.         chrbin = savebin[offset:offset+CHRLEN]
  49.         name = ''
  50.         index = 29
  51.         nextchar = chrbin[index:index+1].hex()
  52.         # print(chrbin[:28].hex(' '))
  53.         while str(nextchar) != '00':
  54.             name += chr(int(nextchar, 16))
  55.             index += 2
  56.             nextchar = chrbin[index:index+1].hex()
  57.         print(f'Character: {name}')
  58.         ascii = chrbin.hex(' ').split()
  59.         ascii[8] = '00'  # clear flag "character is in party"
  60.         export_bin = bytearray.fromhex("".join(ascii))
  61.         Path(f'{args.folder}/{name}_{args.suffix}.CHR').write_bytes(export_bin)
  62.         print(f'Exported file: {args.folder}/{name}_{args.suffix}.CHR')
  63.  
  64.  
  65. if __name__ == '__main__':
  66.     parser = ArgumentParser()
  67.     parser.add_argument('--save', required=True, help="Path to Wizardry 8 SAV file")
  68.     parser.add_argument('--suffix', default='exported', help="Suffix to add to exported CHR name")
  69.     parser.add_argument('--folder', default='./', help="Folder to save characters")
  70.     args = parser.parse_args()
  71.     main(args)
  72.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement