#!/usr/bin/env python3 # -*- coding: cp437 -*- import sys from insert import TryProcessFileInclusion, TryProcessConditionalCompilation CharMap = "charmap.tbl" SpecialBuffers = { ".": ["B0"], "BUFFER": ["FD"], "ATTACKER": ["FD", "0F"], "TARGET": ["FD", "10"], "EFFECT_BANK": ["FD", "11"], "SCRIPTING_BANK": ["FD", "13"], "CURRENT_MOVE": ["FD", "14"], "LAST_ITEM": ["FD", "16"], "LAST_ABILITY": ["FD", "17"], "ATTACKER_ABILITY": ["FD", "18"], "TARGET_ABILITY": ["FD", "19"], "SCRIPTING_BANK_ABILITY": ["FD", "1A"], "PLAYER_NAME": ["FD", "23"], "PLAYER": ["FD", "01"], "BUFFER1": ["FD", "02"], "BUFFER2": ["FD", "03"], "BUFFER3": ["FD", "04"], "RIVAL": ["FD", "06"], "WHITE": ["FC", "01", "01"], "BLACK": ["FC", "01", "02"], "GRAY": ["FC", "01", "03"], "RED": ["FC", "01", "04"], "ORANGE": ["FC", "01", "05"], "GREEN": ["FC", "01", "06"], "LIGHT_GREEN": ["FC", "01", "07"], "BLUE": ["FC", "01", "08"], "LIGHT_BLUE": ["FC", "01", "09"], "ARROW_UP": ["79"], "ARROW_DOWN": ["7A"], "ARROW_LEFT": ["7B"], "ARROW_RIGHT": ["7C"], "SHRINK": ["FC", "06", "00"], "PAUSE": ["FC", "08"], "PAUSE_UNTIL_PRESS": ["FC", "09"], "PLAY_BGM": ["FC", "0B"], "ESCAPE": ["FC", "0C"], "SHIFT_TEXT": ["FC", "0D"], "PLAY_SE": ["FC", "10"], "CLEAR": ["FC", "11"], "SKIP": ["FC", "12"], "ALIGN": ["FC", "13"], "MIN_LETTER_SPACING": ["FC", "14"], "PAUSE_MUSIC": ["FC", "17"], "RESUME_MUSIC": ["FC", "18"], "A_BUTTON": ["F8", "00"], "B_BUTTON": ["F8", "01"], "L_BUTTON": ["F8", "02"], "R_BUTTON": ["F8", "03"], "START_BUTTON": ["F8", "04"], "SELECT_BUTTON": ["F8", "05"], "DPAD_UP": ["F8", "06"], "DPAD_DOWN": ["F8", "07"], "DPAD_LEFT": ["F8", "08"], "DPAD_RIGHT": ["F8", "09"], "DPAD_UP_DOWN": ["F8", "0A"], "DPAD_LEFT_RIGHT": ["F8", "0B"], "DPAD": ["F8", "0C"], } def StringFileConverter(fileName: str): stringToWrite = ".thumb\n.text\n.align 2\n\n" with open(fileName, 'r', encoding="ISO-8859-1") as file: maxLength = 0 fillFF = False readingState = 0 lineNum = 0 definesDict = {} conditionals = [] for line in file: lineNum += 1 line = line.rstrip("\n\r") # Remove only newline characters if TryProcessFileInclusion(line, definesDict): continue if TryProcessConditionalCompilation(line, definesDict, conditionals): continue if line.strip() == "" or line[:2] == "//": # Ignore blank lines and comment lines continue if readingState == 0: # Only when the file starts line = line.strip() if line[:6].upper() == "#ORG @" and line[6:] != "": title = line[6:] stringToWrite += ".global " + title + "\n" + title + ":\n" readingState = 1 elif "MAX_LENGTH" in line and "=" in line: try: maxLength = int(line.split("=")[1]) except: print('Error reading max length on line ' + str(lineNum) + ' in file: "' + fileName + '"') sys.exit(0) elif "FILL_FF" in line and "=" in line: try: fillFF = bool(line.split("=")[1]) except: print('Error reading FF fill on line ' + str(lineNum) + ' in file: "' + fileName + '"') sys.exit(0) else: print('Warning! Error on line ' + str(lineNum) + ' in file: "' + fileName + '"') elif readingState == 1: if line[:6].upper() == "#ORG @" and line[6:] != "": line = line.strip() title = line[6:] stringToWrite += ".global " + title + "\n" + title + ":\n" else: stringToWrite += ProcessString(line, lineNum, maxLength, fillFF) stringToWrite += "0xFF\n\n" # Only print line in everything went alright output = open(fileName.split(".string")[0] + '.s', 'w') # Only open file once we know everything went okay. output.write(stringToWrite) output.close() def ProcessString(string: str, lineNum: int, maxLength=0, fillWithFF=False) -> str: charMap = PokeByteTableMaker() stringToWrite = ".byte " buffer = False escapeChar = False bufferChars = "" strLen = 0 for char in string: if 0 < maxLength <= strLen: print('Warning: The string "' + string + '" has exceeded the maximum length of ' + str(maxLength) + ' and has been truncated!') break if buffer is True: if char == ']': buffer = False if bufferChars in SpecialBuffers: for bufferChar in SpecialBuffers[bufferChars]: if 0 < maxLength <= strLen: # End buffer in middle print('Warning: The string buffer "' + bufferChars + '" has exceeded the maximum length of ' + str(maxLength) + ' and has been truncated!') break stringToWrite += ("0x" + bufferChar + ", ") strLen += 1 elif len(bufferChars) > 2: # Unrecognized buffer print('Warning: The string buffer "' + bufferChars + '" is not recognized!') stringToWrite += "0x0, " # Place whitespace where the buffer should have gone strLen += 1 else: stringToWrite += ("0x" + bufferChars + ", ") strLen += 1 bufferChars = "" else: bufferChars += char elif escapeChar is True: escapeChar = False try: stringToWrite += hex(charMap["\\" + char]) + ", " strLen += 1 except KeyError: print('Error parsing string: "' + string + '" (Line ' + str(lineNum) + ')') sys.exit(0) else: try: stringToWrite += hex(charMap[char]) + ", " strLen += 1 except KeyError: if char == '[': buffer = True elif char == '\\': escapeChar = True elif char == '"': stringToWrite += hex(charMap["\\" + char]) strLen += 1 else: print('Error parsing string on line ' + str(lineNum) + ' at character "' + char + '".') sys.exit(1) if strLen < maxLength and fillWithFF: while strLen < maxLength: stringToWrite += "0xFF, " strLen += 1 return stringToWrite def PokeByteTableMaker(): dictionary = {} with open(CharMap, 'r', encoding="ISO-8859-1") as file: for line in file: if line.strip() != "/FF" and line.strip() != "": if line[2] == '=' and line[3] != "": try: if line[3] == '\\': dictionary[line[3] + line[4]] = int(line.split('=')[0], 16) else: dictionary[line[3]] = int(line.split('=')[0], 16) except: pass dictionary[' '] = 0 return dictionary