def setStrings(self, strings, japanese=False): currentString = 0 for scriptsOfEntity in self.enemyScripts: if scriptsOfEntity is None: continue for script in scriptsOfEntity: if script is None: continue # Changing strings of MES instructions changes their size, # so we need to fixup jump targets. We do this by first # converting target offsets to target instruction indexes, # changing instructions, and then converting the indexes # back to offsets again. # Construct list of all instruction offsets instrOffsets = [instr.offset for instr in script] # Find the target instruction indexes of all jumps jumpMap = { } # maps index of jump instruction to index of target for index in xrange(len(script)): instr = script[index] if instr.op in [Op.JMPZ, Op.JMPNE, Op.JMP]: targetOffset = struct.unpack("<H", instr.code[1:])[0] targetIndex = instrOffsets.index(targetOffset) jumpMap[index] = targetIndex # Replace the strings in all MES instructions for index in xrange(len(script)): if script[index].op == Op.MES: rawString = ff7.encodeKernelText( strings[currentString], japanese) script[index].setArg(rawString) currentString += 1 # Recalculate all instruction offsets offset = 0 for index in xrange(len(script)): script[index].setOffset(offset) offset += script[index].size # Fixup the target offsets of jumps for index in xrange(len(script)): if script[index].op in [Op.JMPZ, Op.JMPNE, Op.JMP]: targetIndex = jumpMap[index] targetOffset = script[targetIndex].offset script[index].setArg(struct.pack("<H", targetOffset)) # Convert scripts back to binary data self.insertScripts(self.enemyScripts, self.aiDataOffset, 3, len(self.data))
def setStrings(self, strings, japanese = False): currentString = 0 for scriptsOfEntity in self.enemyScripts: if scriptsOfEntity is None: continue for script in scriptsOfEntity: if script is None: continue # Changing strings of MES instructions changes their size, # so we need to fixup jump targets. We do this by first # converting target offsets to target instruction indexes, # changing instructions, and then converting the indexes # back to offsets again. # Construct list of all instruction offsets instrOffsets = [instr.offset for instr in script] # Find the target instruction indexes of all jumps jumpMap = {} # maps index of jump instruction to index of target for index in xrange(len(script)): instr = script[index] if instr.op in [Op.JMPZ, Op.JMPNE, Op.JMP]: targetOffset = struct.unpack("<H", instr.code[1:])[0] targetIndex = instrOffsets.index(targetOffset) jumpMap[index] = targetIndex # Replace the strings in all MES instructions for index in xrange(len(script)): if script[index].op == Op.MES: rawString = ff7.encodeKernelText(strings[currentString], japanese) script[index].setArg(rawString) currentString += 1 # Recalculate all instruction offsets offset = 0 for index in xrange(len(script)): script[index].setOffset(offset) offset += script[index].size # Fixup the target offsets of jumps for index in xrange(len(script)): if script[index].op in [Op.JMPZ, Op.JMPNE, Op.JMP]: targetIndex = jumpMap[index] targetOffset = script[targetIndex].offset script[index].setArg(struct.pack("<H", targetOffset)) # Convert scripts back to binary data self.insertScripts(self.enemyScripts, self.aiDataOffset, 3, len(self.data))
def setAbilityNames(self, abilities, japanese = False): for i in xrange(32): rawString = ff7.encodeKernelText(abilities[i], japanese) rawStringSize = len(rawString) if rawStringSize > self.maxStringSize: raise EnvironmentError, "Ability name '%s' in scene %d is too long when encoded (%d > %d bytes)" % (abilities[i], self.index, rawStringSize, self.maxStringSize) if rawStringSize < self.maxStringSize: rawString += '\xff' * (self.maxStringSize - rawStringSize) # pad with 0xff bytes offset = self.abilitiesOffset + i * self.maxStringSize self.data = self.data[:offset] + rawString + self.data[offset + self.maxStringSize:]
def setEnemyNames(self, enemies, japanese=False): for i in xrange(3): rawString = ff7.encodeKernelText(enemies[i], japanese) rawStringSize = len(rawString) if rawStringSize > self.maxStringSize: raise EnvironmentError, "Enemy name '%s' in scene %d is too long when encoded (%d > %d bytes)" % ( enemies[i], self.index, rawStringSize, self.maxStringSize) if rawStringSize < self.maxStringSize: rawString += '\xff' * (self.maxStringSize - rawStringSize ) # pad with 0xff bytes offset = self.enemyDataOffset + i * self.enemyDataSize self.data = self.data[:offset] + rawString + self.data[ offset + self.maxStringSize:]