def rebuild_comm(filename, comm_data): # COMM chunk is *always* 0x430 bytes in size # Read in the JSON file and start plugging in data with open(filename + ".json", 'r') as json_in: data = json_in.read() decoded_data = json.loads(data) json_in.close() COMM_layout = pw64_lib.COMM_layout comm_assembler = io.BytesIO() comm_assembler.write(comm_data) comm_assembler.seek(COMM_layout["pilot_class"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["pilot_class"])) comm_assembler.seek(COMM_layout["vehicle"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["vehicle"])) comm_assembler.seek(COMM_layout["test_number"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["test_number"])) comm_assembler.seek(COMM_layout["level"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["level"])) comm_assembler.seek(COMM_layout["skybox"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["skybox"])) comm_assembler.seek(COMM_layout["snow"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["snow"])) comm_assembler.seek(COMM_layout["wind_WE"], 0) comm_assembler.write(pw64_lib.float_to_hex( decoded_data["COMM"]["wind_WE"])) comm_assembler.seek(COMM_layout["wind_SN"], 0) comm_assembler.write(pw64_lib.float_to_hex( decoded_data["COMM"]["wind_SN"])) comm_assembler.seek(COMM_layout["wind_UD"], 0) comm_assembler.write(pw64_lib.float_to_hex( decoded_data["COMM"]["wind_UD"])) # These get converted from int() to bytes([]) comm_assembler.seek(COMM_layout["THER"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["THER"]])) comm_assembler.seek(COMM_layout["LWND"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["LWND"]])) comm_assembler.seek(COMM_layout["TPAD"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["TPAD"]])) comm_assembler.seek(COMM_layout["LPAD"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["LPAD"]])) comm_assembler.seek(COMM_layout["LSTP"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["LSTP"]])) comm_assembler.seek(COMM_layout["RNGS"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["RNGS"]])) comm_assembler.seek(COMM_layout["BALS"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["BALS"]])) comm_assembler.seek(COMM_layout["TARG"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["TARG"]])) comm_assembler.seek(COMM_layout["HPAD"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["HPAD"]])) comm_assembler.seek(COMM_layout["BTGT"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["BTGT"]])) comm_assembler.seek(COMM_layout["PHTS"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["PHTS"]])) comm_assembler.seek(COMM_layout["FALC"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["FALC"]])) comm_assembler.seek(COMM_layout["UNKN"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["UNKN"]])) comm_assembler.seek(COMM_layout["CNTG"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["CNTG"]])) comm_assembler.seek(COMM_layout["HOPD"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["HOPD"]])) # Rewind and populate the data to return. Yeah I know this can be optimized. Bite me. comm_assembler.seek(0) final_comm_data = comm_assembler.read() print("* COMM data rebuilt.") return final_comm_data
def rebuild_upwt_chunk(filename, chunk): # This function does the actual "rebuilding" of objects from JSON data. # If an object doesn't exist in the JSON input, it won't get added to the UPWT container. Related to COMM counts. # Read in the JSON file and start plugging in data with open(filename + ".json", 'r') as json_in: data = json_in.read() decoded_data = json.loads(data) json_in.close() # Stock chunks from ROM, to be modified if JSON data differs # This _mostly_ should be OK in terms of "unknown" bytes in the data stream... seems to work out fine at least for E_GC_1 TPAD_template = bytes.fromhex( 'C222EB85C3CADCAC4120000041C00000000000000000000000000000000000000000000000000000000000003F800000' ) RNGS_template = bytes.fromhex( 'C392E937432F03D7425C000041B8000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000201000000000000000000006E0000004000000000000000000000007901000000000000000000000000000000000000' ) LSTP_template = bytes.fromhex( 'C1E68F5CC3D80E3541200000C316D74CC31E0C4A412000000000000001000000420C000000000000' ) BALS_template = bytes.fromhex( 'C290210643A74D71433600008000000000000000000000000000000041200000000000003C23D70A0000000000000000402000000000001E0000000000000000411CCCCD0000000000000000000000000000000000000000000000003F80000000000000411CCCCD' ) upwt_io = io.BytesIO() if chunk == "TPAD": XPAD_layout = pw64_lib.TPAD_layout upwt_io.write(TPAD_template) # Lay down the default, unmodified chunk elif chunk == "LSTP": XPAD_layout = pw64_lib.LSTP_layout upwt_io.write(LSTP_template) elif chunk == "BALS": BALS_layout = pw64_lib.BALS_layout upwt_io.write(BALS_template) # Set up a stream object just in case we have >1 BALS chunk bals_stack = io.BytesIO() if decoded_data["COMM"]["BALS"] >= 1: for ball_num in range(1, decoded_data["COMM"]["BALS"] + 1): #print(binascii.hexlify(BALS_template)) ball_num = str(ball_num) upwt_io.seek(0) # Go through our structure and populate the template, convert all floats back to hex upwt_io.seek(BALS_layout["x"], 0) upwt_io.write( pw64_lib.float_to_hex(decoded_data[chunk][ball_num]["x"])) upwt_io.seek(BALS_layout["z"], 0) upwt_io.write( pw64_lib.float_to_hex(decoded_data[chunk][ball_num]["z"])) upwt_io.seek(BALS_layout["y"], 0) upwt_io.write( pw64_lib.float_to_hex(decoded_data[chunk][ball_num]["y"])) upwt_io.seek(BALS_layout["scale"], 0) upwt_io.write( pw64_lib.float_to_hex( decoded_data[chunk][ball_num]["scale"])) # Things that don't get converted to float or decoded are straight ASCII hex upwt_io.seek(BALS_layout["color"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ball_num]["color"])) upwt_io.seek(BALS_layout["type"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ball_num]["type"])) upwt_io.seek(BALS_layout["solidity"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ball_num]["solidity"])) upwt_io.seek(BALS_layout["weight"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ball_num]["weight"])) upwt_io.seek(BALS_layout["popforce"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ball_num]["popforce"])) # Go to the end of the BALS stack, add current ring bals_stack.seek(0, 2) upwt_io.seek(0, 0) bals_stack.write(upwt_io.read()) # Seek to start of bals_stack then return the ring stack (containing the X number of BALS) bals_stack.seek(0, 0) bals_data = bals_stack.read() bals_stack.close() print("* UPWT data chunk(s) rebuilt: %s" % chunk) return bals_data elif chunk == "RNGS": RNGS_layout = pw64_lib.RNGS_layout upwt_io.write(RNGS_template) # We likely have more than one ring so lets make a buffer for it rngs_stack = io.BytesIO() ring_count = decoded_data["COMM"]["RNGS"] if ring_count >= 1: for ring_num in range(1, ring_count + 1): ring_num = str(ring_num) upwt_io.seek(0) # Go through our structure and populate the template, convert all floats back to hex upwt_io.seek(RNGS_layout["x"], 0) upwt_io.write( pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["x"])) upwt_io.seek(RNGS_layout["z"], 0) upwt_io.write( pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["z"])) upwt_io.seek(RNGS_layout["y"], 0) upwt_io.write( pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["y"])) upwt_io.seek(RNGS_layout["yaw"], 0) upwt_io.write( pw64_lib.float_to_hex( decoded_data[chunk][ring_num]["yaw"])) upwt_io.seek(RNGS_layout["pitch"], 0) upwt_io.write( pw64_lib.float_to_hex( decoded_data[chunk][ring_num]["pitch"])) upwt_io.seek(RNGS_layout["roll"], 0) upwt_io.write( pw64_lib.float_to_hex( decoded_data[chunk][ring_num]["roll"])) upwt_io.seek(RNGS_layout["size"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ring_num]["size"])) upwt_io.seek(RNGS_layout["state"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ring_num]["state"])) upwt_io.seek(RNGS_layout["motion_axis"], 0) upwt_io.write( bytes.fromhex( decoded_data[chunk][ring_num]["motion_axis"])) upwt_io.seek(RNGS_layout["motion_rad_start"], 0) upwt_io.write( bytes.fromhex( decoded_data[chunk][ring_num]["motion_rad_start"])) upwt_io.seek(RNGS_layout["motion_rad_end"], 0) upwt_io.write( bytes.fromhex( decoded_data[chunk][ring_num]["motion_rad_end"])) upwt_io.seek(RNGS_layout["rotation"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ring_num]["rotation"])) upwt_io.seek(RNGS_layout["rotation_speed"], 0) upwt_io.write( bytes.fromhex( decoded_data[chunk][ring_num]["rotation_speed"])) upwt_io.seek(RNGS_layout["ring_special"], 0) upwt_io.write( bytes.fromhex( decoded_data[chunk][ring_num]["ring_special"])) upwt_io.seek(RNGS_layout["next_ring_unknown"], 0) upwt_io.write( bytes.fromhex( decoded_data[chunk][ring_num]["next_ring_unknown"])) upwt_io.seek(RNGS_layout["next_ring_order_count"], 0) upwt_io.write( bytes.fromhex(decoded_data[chunk][ring_num] ["next_ring_order_count"])) if int(decoded_data[chunk][ring_num]["next_ring_order_count"], 16) >= 1: for ring_index in range( 0, int( decoded_data[chunk][ring_num] ["next_ring_order_count"], 16)): upwt_io.seek( RNGS_layout["next_ring_index"][ring_index], 0) upwt_io.write( bytes.fromhex( decoded_data[chunk][ring_num] ["next_ring_index"][str(ring_index)])) else: # This is a new one I found out while writing this tool... # There seems to be form of list of rings to clear in order in some tasks. Sometimes its linear, sometimes there's choices. # Prior to reading the next ring we have to clear the current/old index data of the "available" rings. # Otherwise the next ring (even if it has 0 for the count) will re-use the RNGS_template with the previous ring's ring count. # Im so tired and not sure why this works... but it will probably break for any level other than E_GC_1 # This will need attention later for sure. upwt_io.seek(RNGS_layout["next_ring_index"][ring_index], 0) upwt_io.write(bytes.fromhex("00000000")) # Add to our stack rngs_stack.seek(0, 2) upwt_io.seek(0, 0) rngs_stack.write(upwt_io.read()) # For some reason theres another 0x4 bytes at the end of the RNGS chunk... rngs_stack.seek(0, 2) rngs_stack.write(b'\x00\x00\x00\x00') # Seek to start of rngs_stack, then dump the whole ring stack to a var for return rngs_stack.seek(0, 0) #upwt_io.seek(0, 0) ring_data = rngs_stack.read() rngs_stack.close() print("* UPWT data chunk(s) rebuilt: %s" % chunk) return ring_data if chunk == "TPAD" or chunk == "LSTP": upwt_io.seek(0) # Go through our structure and populate the template, convert all floats back to hex upwt_io.seek(XPAD_layout["x"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["x"])) upwt_io.seek(XPAD_layout["z"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["z"])) upwt_io.seek(XPAD_layout["y"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["y"])) upwt_io.seek(XPAD_layout["yaw"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["yaw"])) upwt_io.seek(XPAD_layout["roll"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["roll"])) upwt_io.seek(XPAD_layout["pitch"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["pitch"])) if chunk == "TPAD": upwt_io.seek(XPAD_layout["vehicle_fuel"], 0) upwt_io.write( pw64_lib.float_to_hex(decoded_data[chunk]["vehicle_fuel"])) # If we reach here, we return one of the singular objects like TakeOff Pad or Landing Strip. upwt_io.seek(0) upwt_output_chunk = upwt_io.read() upwt_io.close() print("* UPWT data chunk(s) rebuilt: %s" % chunk) return upwt_output_chunk
def rebuild_comm(filename, comm_data): # COMM chunk is *always* 0x430 bytes in size UPWT_COMM_maker_and_size = b'434F4D4D00000430' # TODO: Update UPWT size when chunks are added # Read in the JSON file and start plugging in data with open(filename + ".json", 'r') as json_in: data = json_in.read() decoded_data = json.loads(data) json_in.close() UPWT_COMM_template_bytes = comm_data COMM_layout = pw64_lib.COMM_layout print("pilot_class: %s" % UPWT_COMM_template_bytes[COMM_layout["pilot_class"]]) print("vehicle: %s" % UPWT_COMM_template_bytes[COMM_layout["vehicle"]]) print("test_number: %s" % UPWT_COMM_template_bytes[COMM_layout["test_number"]]) print("level: %s" % UPWT_COMM_template_bytes[COMM_layout["level"]]) print("skybox: %s" % UPWT_COMM_template_bytes[COMM_layout["skybox"]]) print("snow: %s" % UPWT_COMM_template_bytes[COMM_layout["snow"]]) print("wind_WE: %x%x%x%x" % (int(UPWT_COMM_template_bytes[COMM_layout["wind_WE"]]),int(UPWT_COMM_template_bytes[COMM_layout["wind_WE"]+1]), int(UPWT_COMM_template_bytes[COMM_layout["wind_WE"]+2]), int(UPWT_COMM_template_bytes[COMM_layout["wind_WE"]+3]))) print("wind_SN: %x%x%x%x" % (int(UPWT_COMM_template_bytes[COMM_layout["wind_SN"]]),int(UPWT_COMM_template_bytes[COMM_layout["wind_SN"]+1]), int(UPWT_COMM_template_bytes[COMM_layout["wind_SN"]+2]), int(UPWT_COMM_template_bytes[COMM_layout["wind_SN"]+3]))) print("wind_UD: %x%x%x%x" % (int(UPWT_COMM_template_bytes[COMM_layout["wind_UD"]]),int(UPWT_COMM_template_bytes[COMM_layout["wind_UD"]+1]), int(UPWT_COMM_template_bytes[COMM_layout["wind_UD"]+2]), int(UPWT_COMM_template_bytes[COMM_layout["wind_UD"]+3]))) print("BALS: %s" % UPWT_COMM_template_bytes[COMM_layout["BALS"]]) print("RNGS: %s" % UPWT_COMM_template_bytes[COMM_layout["RNGS"]]) # For manipulating the bytes comm_assembler = io.BytesIO() #comm_assembler.write(UPWT_COMM_maker_and_size) For when we need tochange COMM size? But this should never be needed comm_assembler.write(UPWT_COMM_template_bytes) comm_assembler.seek(COMM_layout["pilot_class"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["pilot_class"])) comm_assembler.seek(COMM_layout["vehicle"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["vehicle"])) comm_assembler.seek(COMM_layout["test_number"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["test_number"])) comm_assembler.seek(COMM_layout["level"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["level"])) comm_assembler.seek(COMM_layout["skybox"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["skybox"])) comm_assembler.seek(COMM_layout["snow"], 0) comm_assembler.write(bytes.fromhex(decoded_data["COMM"]["snow"])) comm_assembler.seek(COMM_layout["wind_WE"], 0) comm_assembler.write(pw64_lib.float_to_hex(decoded_data["COMM"]["wind_WE"])) comm_assembler.seek(COMM_layout["wind_SN"], 0) comm_assembler.write(pw64_lib.float_to_hex(decoded_data["COMM"]["wind_SN"])) comm_assembler.seek(COMM_layout["wind_UD"], 0) comm_assembler.write(pw64_lib.float_to_hex(decoded_data["COMM"]["wind_UD"])) # These get converted from int() to bytes([]) comm_assembler.seek(COMM_layout["THER"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["THER"]])) comm_assembler.seek(COMM_layout["LWND"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["LWND"]])) comm_assembler.seek(COMM_layout["TPAD"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["TPAD"]])) comm_assembler.seek(COMM_layout["LPAD"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["LPAD"]])) comm_assembler.seek(COMM_layout["LSTP"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["LSTP"]])) comm_assembler.seek(COMM_layout["RNGS"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["RNGS"]])) comm_assembler.seek(COMM_layout["BALS"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["BALS"]])) comm_assembler.seek(COMM_layout["TARG"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["TARG"]])) comm_assembler.seek(COMM_layout["HPAD"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["HPAD"]])) comm_assembler.seek(COMM_layout["BTGT"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["BTGT"]])) comm_assembler.seek(COMM_layout["PHTS"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["PHTS"]])) comm_assembler.seek(COMM_layout["FALC"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["FALC"]])) comm_assembler.seek(COMM_layout["UNKN"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["UNKN"]])) comm_assembler.seek(COMM_layout["CNTG"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["CNTG"]])) comm_assembler.seek(COMM_layout["HOPD"], 0) comm_assembler.write(bytes([decoded_data["COMM"]["HOPD"]])) # Rewind and populate the data to return comm_assembler.seek(0) final_comm_data = comm_assembler.read() return final_comm_data
def parse_upwt_json_test(filename): with open(filename + ".json", 'r') as json_in: data = json_in.read() #print(json.dumps(data)) decoded_data = json.loads(data) print(decoded_data) print(decoded_data["task_id"]) print(decoded_data["COMM"]) print(decoded_data["COMM"]["vehicle"]) ring_count = decoded_data["COMM"]["RNGS"] print("Number of Rings: %s" % ring_count) for ring in range(1, ring_count+1): print("Ring %s - X %f / %s" %(ring, decoded_data["RNGS"][str(ring)]["x"], binascii.hexlify(pw64_lib.float_to_hex(decoded_data["RNGS"][str(ring)]["x"])))) json_in.close()
def parse_upwt_json(filename, chunk): # Read in the JSON file and start plugging in data with open(filename + ".json", 'r') as json_in: data = json_in.read() decoded_data = json.loads(data) json_in.close() # Stock chunks from ROM, to be modified if JSON data differs # This _mostly_ should be OK in terms of "unknown" bytes in the data stream... seems to work out fine at least for E_GC_1 TPAD_template = bytes.fromhex('C222EB85C3CADCAC4120000041C00000000000000000000000000000000000000000000000000000000000003F800000') RNGS_template = bytes.fromhex('C392E937432F03D7425C000041B8000000000000000000000000000000010000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000201000000000000000000006E0000004000000000000000000000007901000000000000000000000000000000000000') LSTP_template = bytes.fromhex('C1E68F5CC3D80E3541200000C316D74CC31E0C4A412000000000000001000000420C000000000000') BALS_template = bytes.fromhex('C290210643A74D71433600008000000000000000000000000000000041200000000000003C23D70A0000000000000000402000000000001E0000000000000000411CCCCD0000000000000000000000000000000000000000000000003F80000000000000411CCCCD') upwt_io = io.BytesIO() if chunk == "TPAD": XPAD_layout = pw64_lib.TPAD_layout upwt_io.write(TPAD_template) # Lay down the default, unmodified chunk elif chunk == "LSTP": XPAD_layout = pw64_lib.LSTP_layout upwt_io.write(LSTP_template) elif chunk == "BALS": BALS_layout = pw64_lib.BALS_layout upwt_io.write(BALS_template) # For when we have >1 BALS chunk bals_stack = io.BytesIO() if decoded_data["COMM"]["BALS"] >= 1: for ball_num in range(1, decoded_data["COMM"]["BALS"] + 1): #print(binascii.hexlify(BALS_template)) ball_num = str(ball_num) upwt_io.seek(0) # Go through our structure and populate the template, convert all floats back to hex upwt_io.seek(BALS_layout["x"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ball_num]["x"])) upwt_io.seek(BALS_layout["z"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ball_num]["z"])) upwt_io.seek(BALS_layout["y"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ball_num]["y"])) upwt_io.seek(BALS_layout["scale"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ball_num]["scale"])) #print("* %s" % decoded_data[chunk][ball_num]["scale"]) upwt_io.seek(BALS_layout["color"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ball_num]["color"])) upwt_io.seek(BALS_layout["type"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ball_num]["type"])) upwt_io.seek(BALS_layout["solidity"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ball_num]["solidity"])) upwt_io.seek(BALS_layout["weight"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ball_num]["weight"])) upwt_io.seek(BALS_layout["popforce"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ball_num]["popforce"])) # Add to our stack bals_stack.seek(0, 2) upwt_io.seek(0, 0) bals_stack.write(upwt_io.read()) # Seek to start of rngs_stack and upwt_io, then dump the ring stack into the upwt_io bals_stack.seek(0, 0) #upwt_io.seek(0, 0) bals_data = bals_stack.read() bals_stack.close() return bals_data elif chunk == "RNGS": RNGS_layout = pw64_lib.RNGS_layout upwt_io.write(RNGS_template) # we likely have more than one ring so lets make a buffer for it rngs_stack = io.BytesIO() ring_count = decoded_data["COMM"]["RNGS"] if ring_count >= 1: for ring_num in range(1, ring_count + 1): ring_num = str(ring_num) upwt_io.seek(0) # Go through our structure and populate the template, convert all floats back to hex upwt_io.seek(RNGS_layout["x"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["x"])) upwt_io.seek(RNGS_layout["z"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["z"])) upwt_io.seek(RNGS_layout["y"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["y"])) upwt_io.seek(RNGS_layout["yaw"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["yaw"])) upwt_io.seek(RNGS_layout["pitch"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["pitch"])) upwt_io.seek(RNGS_layout["roll"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk][ring_num]["roll"])) upwt_io.seek(RNGS_layout["size"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["size"])) upwt_io.seek(RNGS_layout["state"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["state"])) upwt_io.seek(RNGS_layout["motion_axis"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["motion_axis"])) upwt_io.seek(RNGS_layout["motion_rad_start"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["motion_rad_start"])) upwt_io.seek(RNGS_layout["motion_rad_end"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["motion_rad_end"])) upwt_io.seek(RNGS_layout["rotation"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["rotation"])) upwt_io.seek(RNGS_layout["rotation_speed"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["rotation_speed"])) upwt_io.seek(RNGS_layout["ring_special"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["ring_special"])) upwt_io.seek(RNGS_layout["next_ring_unknown"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["next_ring_unknown"])) upwt_io.seek(RNGS_layout["next_ring_order_count"], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["next_ring_order_count"])) if int(decoded_data[chunk][ring_num]["next_ring_order_count"], 16) >= 1: for ring_index in range(0, int(decoded_data[chunk][ring_num]["next_ring_order_count"], 16)): print("!!!: %s" % ring_index) upwt_io.seek(RNGS_layout["next_ring_index"][ring_index], 0) upwt_io.write(bytes.fromhex(decoded_data[chunk][ring_num]["next_ring_index"][str(ring_index)])) else: # Prior to reading the next index we have to clear the index data of the available rings. # Otherwise the next ring (even if it has 0 for the count) will re-use the RNGS_template with the previous ring's ring count. # Im so tired and not sure why this works... but it will probably break for any level other than E_GC_1 # This will need attention later for sure. print(ring_index) upwt_io.seek(RNGS_layout["next_ring_index"][ring_index], 0) upwt_io.write(bytes.fromhex("00000000")) # Add to our stack rngs_stack.seek(0, 2) upwt_io.seek(0, 0) rngs_stack.write(upwt_io.read()) ### Test #upwt_io.seek(0, 0) #print("Ring: %s" % ring_num) #print(binascii.hexlify(upwt_io.read())) #upwt_io.seek(0, 0) #print("---") #rngs_dump_test(upwt_io.read()) #print("---") # For some reason theres another 0x4 bytes at the end of the RNGS chunk... rngs_stack.seek(0, 2) rngs_stack.write(b'\x00\x00\x00\x00') # Seek to start of rngs_stack and upwt_io, then dump the ring stack into the upwt_io rngs_stack.seek(0, 0) #upwt_io.seek(0, 0) ring_data = rngs_stack.read() print("FINAL:") print(binascii.hexlify(ring_data)) rngs_stack.close() return ring_data if chunk == "TPAD" or chunk == "LSTP": #print(binascii.hexlify(TPAD_template)) upwt_io.seek(0) # Go through our structure and populate the template, convert all floats back to hex upwt_io.seek(XPAD_layout["x"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["x"])) upwt_io.seek(XPAD_layout["z"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["z"])) upwt_io.seek(XPAD_layout["y"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["y"])) upwt_io.seek(XPAD_layout["yaw"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["yaw"])) upwt_io.seek(XPAD_layout["roll"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["roll"])) upwt_io.seek(XPAD_layout["pitch"], 0) upwt_io.write(pw64_lib.float_to_hex(decoded_data[chunk]["pitch"])) upwt_io.seek(0) upwt_output_chunk = upwt_io.read() upwt_io.close() #sys.exit(0) return upwt_output_chunk