diff options
author | B. Stack <bgstack15@gmail.com> | 2024-03-10 23:05:43 -0400 |
---|---|---|
committer | B. Stack <bgstack15@gmail.com> | 2024-03-10 23:05:43 -0400 |
commit | 1d0a6c692218703677cdcf8e6ceb98640ad36515 (patch) | |
tree | 2ae00011c4026a95f84efa9864097231261924fb /srb_lib.py | |
parent | progress for day (diff) | |
download | srb_lib-1d0a6c692218703677cdcf8e6ceb98640ad36515.tar.gz srb_lib-1d0a6c692218703677cdcf8e6ceb98640ad36515.tar.bz2 srb_lib-1d0a6c692218703677cdcf8e6ceb98640ad36515.zip |
add get/set name
Diffstat (limited to 'srb_lib.py')
-rw-r--r-- | srb_lib.py | 54 |
1 files changed, 51 insertions, 3 deletions
@@ -18,16 +18,19 @@ # winetricks vd=1024x768 # winetricks vd=off # Dependencies: -# python3-crcmod import sys, struct -srb_lib_version = "20240309a" +srb_lib_version = "20240310a" # Table of byte positions of values in the savegame file, minus the first four bytes which are the checksum. Due to zero-indexing of python lists, but for ease of usage, we will always put a zero as the value of index 0. That is, profile 1 will use index 1 of the list. # money is 0x270 bytes after the "Z<dddddddd" start. PROFILE_START_POSITION = [0, 0x10, 0x142C, 0x2848] POS_MONEY = 0x270 POS_EQUIPPED_WEAPON = 0x284 +POS_PROFILE_IN_USE = 0x290 +POS_NAME = 0x294 + +NAME_CHARS = " ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!?" # stinger purchased is relative 0x28C, value 0x40 (b01000000) or 64 # water-balloon-gun is relative 0x2D, value 0x0001 @@ -190,6 +193,7 @@ def crc_poly(data, n, poly, crc=0, ref_in=False, ref_out=False, xor_out=0): def _get_data_from_data_object(data_object): """ Helper function to either open file, or pass bytes through. """ + data = None if type(data_object) == str: _, data = read_file(data_object) elif type(data_object) == bytes: @@ -268,7 +272,7 @@ def get_level_status(data_object,profile_id,level): profile_level_status = data[PROFILE_START_POSITION[profile_id]+POS_LEVEL_START+(4*level_obj["pos_r"])] # it comes back as an int, but does it look better as a hex? return hex(profile_level_status) - + def get_level_info(level): """ Returns dictionary of level from LEVELS, searching by id or name. """ try: @@ -293,6 +297,50 @@ def get_level_info(level): return -1, f"invalid level index {level}; use 0-{len(LEVELS)}" return -1, f"invalid way to reference level: [{type(level)}]. Use id or name." +def get_name(data_object,profile_id): + """ Print the name of the profile_id. """ + data = _get_data_from_data_object(data_object) + name_array = struct.unpack_from('<8i',data,PROFILE_START_POSITION[profile_id]+POS_NAME) + #print(f"debug: name_array: {name_array}, type {type(name_array)}") + name_str = "" + for i in name_array: + name_str += NAME_CHARS[i] + return name_str + +def set_name(data_object,profile_id,new_name): + """ Set the name of the profile_id. Note that this allows you to set a name for a profile that is not in use, which preseeds the name when you select to make a profile in this slot in-game. """ + data = _get_data_from_data_object(data_object) + data_bytearray = bytearray(data) + # convert new_name to tuple of integer values + name_array = [] + for i in new_name.upper(): + try: + j = NAME_CHARS.index(i) + except ValueError: + return -1, f"Invalid characters in requested name {new_name}." + name_array.append(j) + # right-pad with spaces + while len(name_array) < 8: + name_array.append(0) + if len(name_array) > 8 or len(name_array) < 0: + return -1, f"Invalid length {len(name_array)} of name {new_name}." + x = 0 + # for some reason I cannot figure out '<8i' with a tuple or list of ints. So just do it manually. + for i in name_array: + struct.pack_into('<1i',data_bytearray,PROFILE_START_POSITION[profile_id]+POS_NAME+(4*x),i) + x = x + 1 + data = bytes(data_bytearray) + #print(f"debug: after setting name to {new_name}, we checked and got {get_name(data,profile_id)}") + return data, "" + +def get_profile_in_use(data_object,profile_id): + """ Print if the profile_id is in use. """ + data = _get_data_from_data_object(data_object) + # it always comes as a tuple + in_use = struct.unpack_from('<1?',data,PROFILE_START_POSITION[profile_id]+POS_PROFILE_IN_USE)[0] + #print(f"debug: in_use: {in_use}, type {type(in_use)}") + return in_use + def calculate_checksum(data): """ Return the 4-byte checksum used by the game for the provided data. """ # aka # CRC-32/BZIP2 |