def setScript(self, script, japanese = False): data = "" for line in script: if line.startswith( "{WAIT" ): # WAIT <arg> m = re.match(r"{WAIT (\d+)}", line) if not m: raise ValueError, "Syntax error in command '%s' in tutorial script" % line arg = int(m.group(1)) if arg > 0xffff: raise ValueError, "Argument of WAIT command greater than 65535 in tutorial script" data += '\x00' data += struct.pack("<H", arg) elif line.startswith( "{WINDOW" ): # WINDOW <x> <y> m = re.match(r"{WINDOW (\d+) (\d+)}", line) if not m: raise ValueError, "Syntax error in command '%s' in tutorial script" % line x = int(m.group(1)) y = int(m.group(2)) if x > 0xffff: raise ValueError, "First argument of WINDOW command greater than 65535 in tutorial script" if y > 0xffff: raise ValueError, "Second argument of WINDOW command greater than 65535 in tutorial script" data += '\x12' data += struct.pack("<HH", x, y) elif line.startswith( "{" ): # Simple command without arguments try: code = commands[line] data += code except KeyError: raise ValueError, "Unknown command '%s' in tutorial script" % line else: # Text line data += '\x10' + ff7text.encode(line, False, japanese) self.data = data + '\x11'
def encodeFieldText(text, japanese=False): return ff7text.encode(text, True, japanese)
def encodeKernelText(text, japanese=False): return ff7text.encode(text, False, japanese)
def setStrings(self, stringList, japanese = False): self.stringData = [ff7text.encode(s, True, japanese) for s in stringList]
def encodeFieldText(text, japanese = False): return ff7text.encode(text, True, japanese)
def encodeKernelText(text, japanese = False): return ff7text.encode(text, False, japanese)
def getData(self, compress = False): numStrings = len(self.stringList) # Encode all strings offsets = [] data = "" for string in self.stringList: rawString = ff7text.encode(string, False, self.japanese) # Already in string data? offset = data.find(rawString) if offset >= 0: # Yes, just push the offset offsets.append(offset) else: # No, append a new string offset = len(data) offsets.append(offset) # Scan for usable references to previous string data i = 0 while i < len(rawString): c = rawString[i] if c >= '\xea' and c <= '\xf0': # Kernel variable code, copy verbatim data += rawString[i:i+3] i += 3 elif c == '\xf8': # Text box color code, copy verbatim data += rawString[i:i+2] i += 2 elif compress: # Look for 10/8/6/4-byte substring in last 64 bytes of data found = False for refLength in xrange(10, 2, -2): searchFor = rawString[i:i + refLength] if len(searchFor) < refLength: continue # Don't search for control codes; the game cannot resolve them if any((x >= '\xe0' and x <= '\xfe') for x in searchFor): continue searchStart = len(data) - 64 if searchStart < 0: searchStart = 0 refOffset = data.find(searchFor, searchStart) if refOffset >= 0: # Found, encode reference data += '\xf9' data += chr(((refLength - 4) << 5) | (len(data) - refOffset - 2)) i += refLength found = True break if not found: # Encode literal value data += c i += 1 else: # Regular character data += c i += 1 if len(data) % 2: data += '\xff' # align to 16-bit boundary # Encode the offset table offsetData = "" for offset in offsets: offsetData += struct.pack("<H", offset + numStrings*2) return offsetData + data
def setStrings(self, stringList, japanese=False): self.stringData = [ ff7text.encode(s, True, japanese) for s in stringList ]