class Exporter: def __init__(self, TekkenVersion, folder_destination='./extracted_chars/'): game_addresses.reloadValues() self.T = GameClass("TekkenGame-Win64-Shipping.exe" if TekkenVersion == 7 else "Cemu.exe") self.TekkenVersion = TekkenVersion self.ptr_size = 8 if TekkenVersion == 7 else 4 self.base = 0x0 if TekkenVersion == 7 else game_addresses.addr['cemu_base'] self.endian = 'little' if TekkenVersion == 7 else 'big' self.folder_destination = folder_destination if self.base == 0x9999999999999999: raise Exception("Cemu base address has not been modified yet, please insert the correct cemu_base address in game_address.txt") if not os.path.isdir(folder_destination): os.mkdir(folder_destination) def getCemuP1Addr(self): windowTitle = self.T.getWindowTitle() p = re.compile("TitleId: ([0-9a-fA-F]{8}\-[0-9a-fA-F]{8})") match = p.search(windowTitle) if match == None: return None key = match.group(1) + '_p1_addr' return None if key not in game_addresses.addr else game_addresses.addr[key] def readInt(self, addr, len): return self.T.readInt(addr, len, endian=self.endian) def readBytes(self, addr, len): return self.T.readBytes(addr, len) def readString(self, addr): offset = 0 while self.readInt(addr + offset, 1) != 0: offset += 1 return self.readBytes(addr, offset).decode("ascii") def readStringPtr(self, addr): return self.readString(self.base + self.readInt(addr, self.ptr_size)) def bToInt(self, data, offset, length, ed=None): return int.from_bytes(data[offset:offset + length], ed if ed != None else self.endian) def getMotbinPtr(self, playerAddress): motbin_ptr_addr = (playerAddress + game_addresses.addr['motbin_offset']) if self.TekkenVersion == 7 else playerAddress - 0x98 return self.readInt(motbin_ptr_addr, self.ptr_size) def getPlayerMovesetName(self, playerAddress): motbin_ptr = self.getMotbinPtr(self.base + playerAddress) return self.readStringPtr(self.base + motbin_ptr + 8) def exportMoveset(self, playerAddress, name=''): motbin_ptr = self.getMotbinPtr(self.base + playerAddress) m = Motbin(self.base + motbin_ptr, self, name) m.getCharacterId(playerAddress) m.extractMoveset() return m
def __init__(self, TekkenVersion, folder_destination='./extracted_chars/'): game_addresses.reloadValues() self.T = GameClass("TekkenGame-Win64-Shipping.exe" if TekkenVersion == 7 else "Cemu.exe") self.TekkenVersion = TekkenVersion self.ptr_size = 8 if TekkenVersion == 7 else 4 self.base = 0x0 if TekkenVersion == 7 else game_addresses.addr['cemu_base'] self.endian = 'little' if TekkenVersion == 7 else 'big' self.folder_destination = folder_destination if not os.path.isdir(folder_destination): os.mkdir(folder_destination)
def __init__(self, TekkenVersion, folder_destination='./extracted_chars/'): game_addresses.reloadValues() self.T = GameClass("TekkenGame-Win64-Shipping.exe" if TekkenVersion == 7 else "Cemu.exe") self.TekkenVersion = TekkenVersion self.ptr_size = 8 if TekkenVersion == 7 else 4 self.base = 0x0 if TekkenVersion == 7 else game_addresses.addr['cemu_base'] self.endian = 'little' if TekkenVersion == 7 else 'big' self.folder_destination = folder_destination if self.base == 0x9999999999999999: raise Exception("Cemu base address has not been modified yet, please insert the correct cemu_base address in game_address.txt") if not os.path.isdir(folder_destination): os.mkdir(folder_destination)
class Exporter: def __init__(self, TekkenVersion, folder_destination='./extracted_chars/'): game_addresses.reloadValues() self.T = GameClass("TekkenGame-Win64-Shipping.exe" if TekkenVersion == 7 else "Cemu.exe") self.TekkenVersion = TekkenVersion self.ptr_size = 8 if TekkenVersion == 7 else 4 self.base = 0x0 if TekkenVersion == 7 else game_addresses.addr['cemu_base'] self.endian = 'little' if TekkenVersion == 7 else 'big' self.folder_destination = folder_destination if not os.path.isdir(folder_destination): os.mkdir(folder_destination) def readInt(self, addr, len): return self.T.readInt(addr, len, endian=self.endian) def readBytes(self, addr, len): return self.T.readBytes(addr, len) def readString(self, addr): offset = 0 while self.readInt(addr + offset, 1) != 0: offset += 1 return self.readBytes(addr, offset).decode("ascii") def readStringPtr(self, addr): return self.readString(self.base + self.readInt(addr, self.ptr_size)) def bToInt(self, data, offset, length, ed=None): return int.from_bytes(data[offset:offset + length], ed if ed != None else self.endian) def getMotbinPtr(self, playerAddress): motbin_ptr_addr = (playerAddress + 0x14a0) if self.TekkenVersion == 7 else playerAddress - 0x98 return self.readInt(motbin_ptr_addr, self.ptr_size) def getPlayerMovesetName(self, playerAddress): motbin_ptr = self.getMotbinPtr(self.base + playerAddress) return self.readStringPtr(self.base + motbin_ptr + 8) def exportMoveset(self, playerAddress, name=''): motbin_ptr = self.getMotbinPtr(self.base + playerAddress) m = Motbin(self.base + motbin_ptr, self, name) m.extractMoveset() return m
def __init__(self): self.T = GameClass("TekkenGame-Win64-Shipping.exe")
class Importer: def __init__(self): self.T = GameClass("TekkenGame-Win64-Shipping.exe") def readInt(self, addr, bytes_length=4): return self.T.readInt(addr, bytes_length) def writeInt(self, addr, value, bytes_length=0): return self.T.writeInt(addr, value, bytes_length=bytes_length) def readBytes(self, addr, bytes_length): return self.T.readBytes(addr, bytes_length) def writeBytes(self, addr, data): return self.T.writeBytes(addr, data) def writeString(self, addr, text): return self.writeBytes(addr, bytes(text + "\x00", 'ascii')) def readString(self, addr): offset = 0 while self.readInt(addr + offset, 1) != 0: offset += 1 return self.readBytes(addr, offset).decode("ascii") def allocateMem(self, allocSize): return VirtualAllocEx(self.T.handle, 0, allocSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) def importMoveset(self, playerAddr, folderName, moveset=None, charactersPath='extracted_chars/'): moveset = self.loadMoveset(folderName=folderName, moveset=moveset, charactersPath=charactersPath) motbin_ptr_addr = playerAddr + game_addresses.addr['t7_motbin_offset'] current_motbin_ptr = self.readInt(motbin_ptr_addr, 8) old_character_name = self.readString( self.readInt(current_motbin_ptr + 0x8, 8)) moveset.copyMotaOffsets(current_motbin_ptr) moveset.applyCharacterIDAliases(playerAddr) print("\nOLD moveset pointer: 0x%x (%s)" % (current_motbin_ptr, old_character_name)) print("NEW moveset pointer: 0x%x (%s)" % (moveset.motbin_ptr, moveset.m['character_name'])) self.writeInt(motbin_ptr_addr, moveset.motbin_ptr, 8) return moveset def loadMoveset(self, folderName=None, moveset=None, charactersPath=None): if moveset == None: jsonFilename = next(file for file in os.listdir(folderName) if file.endswith(".json")) print("Reading %s..." % (jsonFilename)) with open("%s/%s" % (folderName, jsonFilename), "r") as f: m = json.load(f) f.close() else: m = deepcopy(moveset) if 'export_version' not in m or not versionMatches( m['export_version']): print( "Error: trying to import outdated moveset, please extract again." ) raise Exception("Moveset version: %s. Importer version: %s." % (m['export_version'], importVersion)) fillAliasesDictonnaries(m['version']) ApplyCharacterFixes(m) p = MotbinStruct(m, folderName, self, animSearchFolder=charactersPath) character_name = p.writeString(m['character_name']) creator_name = p.writeString(m['creator_name']) date = p.writeString(m['date']) fulldate = p.writeString(m['fulldate']) requirements_ptr, requirement_count = p.allocateRequirements() cancel_extradata_ptr, cancel_extradata_size = p.allocateCancelExtradata( ) cancel_ptr, cancel_count = p.allocateCancels(m['cancels']) group_cancel_ptr, group_cancel_count = p.allocateCancels( m['group_cancels'], grouped=True) pushback_extras_ptr, pushback_extras_count = p.allocatePushbackExtras() pushback_ptr, pushback_list_count = p.allocatePushbacks() reaction_list_ptr, reaction_list_count = p.allocateReactionList() extra_move_properties_ptr, extra_move_properties_count = p.allocateExtraMoveProperties( ) voiceclip_list_ptr, voiceclip_list_count = p.allocateVoiceclipIds() hit_conditions_ptr, hit_conditions_count = p.allocateHitConditions() moves_ptr, move_count = p.allocateMoves() input_extradata_ptr, input_extradata_count = p.allocateInputExtradata() input_sequences_ptr, input_sequences_count = p.allocateInputSequences() projectiles_ptr, projectiles_count = p.allocateProjectiles() throw_extras_ptr, throw_extras_count = p.allocateThrowExtras() throws_ptr, throws_count = p.allocateThrows() parry_related_ptr, parry_related_count = p.allocateParryRelated() p.allocateMota() self.writeInt(p.motbin_ptr + 0x0, 65536, 4) self.writeInt(p.motbin_ptr + 0x4, 4475208, 4) self.writeInt(p.motbin_ptr + 0x8, character_name, 8) self.writeInt(p.motbin_ptr + 0x10, creator_name, 8) self.writeInt(p.motbin_ptr + 0x18, date, 8) self.writeInt(p.motbin_ptr + 0x20, fulldate, 8) self.writeAliases(p.motbin_ptr, m) self.writeInt(p.motbin_ptr + 0x150, reaction_list_ptr, 8) self.writeInt(p.motbin_ptr + 0x158, reaction_list_count, 8) self.writeInt(p.motbin_ptr + 0x160, requirements_ptr, 8) self.writeInt(p.motbin_ptr + 0x168, requirement_count, 8) self.writeInt(p.motbin_ptr + 0x170, hit_conditions_ptr, 8) self.writeInt(p.motbin_ptr + 0x178, hit_conditions_count, 8) self.writeInt(p.motbin_ptr + 0x180, projectiles_ptr, 8) self.writeInt(p.motbin_ptr + 0x188, projectiles_count, 8) self.writeInt(p.motbin_ptr + 0x190, pushback_ptr, 8) self.writeInt(p.motbin_ptr + 0x198, pushback_list_count, 8) self.writeInt(p.motbin_ptr + 0x1A0, pushback_extras_ptr, 8) self.writeInt(p.motbin_ptr + 0x1A8, pushback_extras_count, 8) self.writeInt(p.motbin_ptr + 0x1b0, cancel_ptr, 8) self.writeInt(p.motbin_ptr + 0x1b8, cancel_count, 8) self.writeInt(p.motbin_ptr + 0x1c0, group_cancel_ptr, 8) self.writeInt(p.motbin_ptr + 0x1c8, group_cancel_count, 8) self.writeInt(p.motbin_ptr + 0x1d0, cancel_extradata_ptr, 8) self.writeInt(p.motbin_ptr + 0x1d8, cancel_extradata_size, 8) self.writeInt(p.motbin_ptr + 0x1e0, extra_move_properties_ptr, 8) self.writeInt(p.motbin_ptr + 0x1e8, extra_move_properties_count, 8) self.writeInt(p.motbin_ptr + 0x1f0, 0, 8) self.writeInt(p.motbin_ptr + 0x1f8, 0, 8) self.writeInt(p.motbin_ptr + 0x200, 0, 8) self.writeInt(p.motbin_ptr + 0x208, 0, 8) self.writeInt(p.motbin_ptr + 0x210, moves_ptr, 8) self.writeInt(p.motbin_ptr + 0x218, move_count, 8) self.writeInt(p.motbin_ptr + 0x220, voiceclip_list_ptr, 8) self.writeInt(p.motbin_ptr + 0x228, voiceclip_list_count, 8) self.writeInt(p.motbin_ptr + 0x230, input_sequences_ptr, 8) self.writeInt(p.motbin_ptr + 0x238, input_sequences_count, 8) self.writeInt(p.motbin_ptr + 0x240, input_extradata_ptr, 8) self.writeInt(p.motbin_ptr + 0x248, input_extradata_count, 8) self.writeInt(p.motbin_ptr + 0x250, parry_related_ptr, 8) self.writeInt(p.motbin_ptr + 0x258, parry_related_count, 8) self.writeInt(p.motbin_ptr + 0x260, throw_extras_ptr, 8) self.writeInt(p.motbin_ptr + 0x268, throw_extras_count, 8) self.writeInt(p.motbin_ptr + 0x270, throws_ptr, 8) self.writeInt(p.motbin_ptr + 0x278, throws_count, 8) p.applyMotaOffsets() print("%s (ID: %d) successfully imported in memory at 0x%x." % (m['character_name'], m['character_id'], p.motbin_ptr)) print("%d/%d bytes left." % (p.size - (p.curr_ptr - p.head_ptr), p.size)) return p def writeAliases(self, motbin_ptr, m): alias_offset = 0x28 for alias in m['aliases']: self.writeInt(motbin_ptr + alias_offset, alias, 2) alias_offset += 2 if 'aliases2' in m: alias_offset = 0x108 for alias in m['aliases2']: self.writeInt(motbin_ptr + alias_offset, alias, 2) alias_offset += 2
def __init__(self): self.T = GameClass("TekkenGame-Win64-Shipping.exe") self.T.applyModuleAddress(game_addresses)