Example #1
0
 def _prepargs(self, command, args):
     #Rewrite references to AST Reference nodes
     rawargs = []
     i_args = 0
     for i in range(0, len(command.params)):
         commandparam = command.getParam(i)
         #print(repr(commandparam))
         if commandparam.defaultvalue == None:
             #print(" -> consume! "+repr(args[i_args]))
             if ParamType.ispointer(commandparam.ptype):
                 rawargs.append(ast.ASTRef(args[i_args]))
             elif commandparam.definevaluestype != None:
                 defines = self.langdef.getDefines(commandparam.definevaluestype)
                 #Reversed defines lookup, not as elegant as I hoped it
                 key = args[i_args].upper()
                 val = None
                 try:
                     #If defines is a list:
                     try:
                         val = defines.index(key)
                     except:
                         val = next((dval for dval, dkey in defines.items() if dkey == key))
                     rawargs.append(ast.ASTDefinedValue(key, val))
                 except:
                     #There is no define for the value, parse it as is
                     # but then ofc. it should be an int.
                     try:
                         rawargs.append(toint(args[i_args]))
                     except:
                         raise Exception("%s is not defined, and could not be converted to an integer!"%args[i_args])
             else:
                 rawargs.append(toint(args[i_args]))
             i_args += 1
     return rawargs
Example #2
0
    def parseline(self, line, lastcommand):
        if True:
            instructions = line.split('\'')[0].strip().split(" ")
            instructions = list(map(lambda x: x.strip(), instructions))
            instruction  = instructions[0].lower()
            
            if instruction == "#include":
                self.handleInclude(instructions[1])
                
            elif instruction == "#define":
                deftype = instructions[1]
                defkey  = instructions[2].upper()
                defval  = toint(instructions[3])
                if not deftype in self.defines:
                    self.defines[deftype] = {}
                self.defines[deftype][defval] = defkey
                
            elif instruction[0:len("addcmmd")] == "addcmmd":
                commandname = instructions[1].lower()
                commandcode = toint(instructions[2])
                lastcommand = Command(commandname, commandcode, self.defines)
                lastcommand.setDescription(stripDescription(line))
                
                #Only store commands of interest for future reference, but keep
                # lastcommand to append its args to (otherwise they are appended to
                # the wrong arg)
                sublangs = re.findall(r"\[([^\]]*)\]", instruction[len("addcmmd"):])
                if len(sublangs)==0 or self.sublang in sublangs:
                    self.commands[commandname] = lastcommand
                         
            elif instruction == "alias":
                lastcommand = Alias(' '.join(instructions[1:]), self.commands)
                lastcommand.setDescription(stripDescription(line))
                self.aliases.append(lastcommand)
                
            elif instruction == "addparm":
                defaultvalue = None
                instructiontype = int(instructions[1].split(":")[0])
                try:
                    definevaluestype = instructions[1].split(":")[1].strip().lower()
                except:
                    definevaluestype = None

                if len(instructions) > 2:
                    try: defaultvalue = toint(instructions[2])
                    except:
                        if instructions[2][0:4] == "bind":
                            pass #TODO: Restriction
                            
                        elif instructions[2][0:5] == "mask(": #format: mask(number)
                            defaultvalue = toint(instructions[2][5:-1])
                        elif instructiontype == ParamType.command:
                            defaultvalue = instructions[2] 
                        else:
                            raise Exception("Unknown default value for param: "+repr(instructions[2]))
                
                lastcommand.addParam(instructiontype, defaultvalue, definevaluestype=definevaluestype, description=stripDescription(line))
        return lastcommand
    def compile(self, *args):
        #print("Compile "+repr(self.code)+" with args "+repr(args))
        self.checkParamscount(len(args))

        usedargs = 0

        cbytes = array('B')
        cbytes.append(self.code)

        for param in self.params:
            value = None
            if param.defaultvalue == None:
                value = args[usedargs]
                usedargs += 1

            else:
                value = param.defaultvalue

            try:
                value = toint(value)
            except:  #value may not be an integer, but may be a (defined) constant!
                try:
                    value = value.lower()
                    if value in self.constants:
                        value = self.constants[value]
                    else:
                        raise Exception()
                except:
                    raise Exception(
                        "The given parameter could not be converted to integer and is also not defined as a constant: "
                        + repr(value))

            cbytes.fromstring(ParamType.rewrite(param.ptype, value))

        return cbytes
    def compile(self, *args):
        #print("Compile "+repr(self.code)+" with args "+repr(args))
        self.checkParamscount(len(args))
             
        usedargs = 0
        
        cbytes = array('B')
        cbytes.append(self.code)
        
        for param in self.params:
            value = None
            if param.defaultvalue == None:
                value = args[usedargs]
                usedargs += 1
                
            else:
                value = param.defaultvalue

            try:
                value = toint(value)
            except: #value may not be an integer, but may be a (defined) constant!
                try:
                    value = value.lower()
                    if value in self.constants:
                        value = self.constants[value]
                    else:
                        raise Exception()
                except:
                    raise Exception("The given parameter could not be converted to integer and is also not defined as a constant: "+repr(value))
                
            cbytes.fromstring(ParamType.rewrite(param.ptype, value))
        
        return cbytes
        
 def userargsorder(self):
     '''Returns the order of which user args are required,
     it is possible to first get $2, and next $1.'''
     ordered = []
     for sigarg in self.signature:
         if sigarg[0] == "$":
             ordered.append(toint(sigarg[1:]))
     return ordered
 def userargsorder(self):
     '''Returns the order of which user args are required,
     it is possible to first get $2, and next $1.'''
     ordered = []
     for sigarg in self.signature:
         if sigarg[0] == "$":
             ordered.append(toint(sigarg[1:]))
     return ordered
Example #7
0
    def parseline(self, line, lastcommand):
        if True:
            instructions = line.split('\'')[0].strip().split(" ")
            instructions = list(map(lambda x: x.strip(), instructions))
            instruction = instructions[0].lower()

            if instruction == "#include":
                self.handleInclude(instructions[1])

            elif instruction == "#define":
                deftype = instructions[1]
                defkey = instructions[2].upper()
                defval = toint(instructions[3])
                if not deftype in self.defines:
                    self.defines[deftype] = {}
                self.defines[deftype][defval] = defkey

            elif instruction[0:len("addcmmd")] == "addcmmd":
                commandname = instructions[1].lower()
                commandcode = toint(instructions[2])
                lastcommand = Command(commandname, commandcode, self.defines)
                lastcommand.setDescription(stripDescription(line))

                #Only store commands of interest for future reference, but keep
                # lastcommand to append its args to (otherwise they are appended to
                # the wrong arg)
                sublangs = re.findall(r"\[([^\]]*)\]",
                                      instruction[len("addcmmd"):])
                if len(sublangs) == 0 or self.sublang in sublangs:
                    self.commands[commandname] = lastcommand

            elif instruction == "alias":
                lastcommand = Alias(' '.join(instructions[1:]), self.commands)
                lastcommand.setDescription(stripDescription(line))
                self.aliases.append(lastcommand)

            elif instruction == "addparm":
                defaultvalue = None
                instructiontype = int(instructions[1].split(":")[0])
                try:
                    definevaluestype = instructions[1].split(
                        ":")[1].strip().lower()
                except:
                    definevaluestype = None

                if len(instructions) > 2:
                    try:
                        defaultvalue = toint(instructions[2])
                    except:
                        if instructions[2][0:4] == "bind":
                            pass  #TODO: Restriction

                        elif instructions[2][
                                0:5] == "mask(":  #format: mask(number)
                            defaultvalue = toint(instructions[2][5:-1])
                        elif instructiontype == ParamType.command:
                            defaultvalue = instructions[2]
                        else:
                            raise Exception(
                                "Unknown default value for param: " +
                                repr(instructions[2]))

                lastcommand.addParam(instructiontype,
                                     defaultvalue,
                                     definevaluestype=definevaluestype,
                                     description=stripDescription(line))
        return lastcommand
## Load chars etc. used by the PokeString encode/decode functions
## definitions are placed in files: ./textchars and ./texthashes

#  texthash: <hash>\t<value>  text hash, replace this complete thing with values in a text-string
#  textchar <char>\t<value>   text letter rewrite to hex

textchars = {}
texthash = {}

dirname = os.path.join(os.path.dirname(sys.argv[0]), "gbahackpkmn", "strings")
for line in open(dirname + "/textchars", 'r', encoding="iso-8859-15"):
    if line:
        (char, val) = line.split("\t")
        if len(char) > 1:  #Chars can be represented as hex numers (&hxx)
            char = chr(toint(char))
        #print("Adding char. "+repr(char))
        textchars[char] = toint(val)

for line in open(dirname + "/texthashes", 'r', encoding="iso-8859-15"):
    if line:
        (hashv, val) = line.split("\t")
        texthash[hashv] = toint(val)

textcharsinv = dict(zip(textchars.values(), textchars))
texthashinv = dict(zip(texthash.values(), texthash))


def decodeChar(char):
    if char == 0x00:  #special case
        return " "
Example #9
0
    def parseline(self, line_raw, resource):
        line = line_raw
        
        #remove any comments, if any
        commentstart = line.find("'")
        if commentstart >= 0:
            line = line[:commentstart]
        
        line = line.lstrip()
        lineargs = self._line2args(line)
        
        if len(lineargs) == 0:
            return resource
        
        command = lineargs[0]
        args = lineargs[1:]
        
        if command == "#script":
            offset = args[0]  #TODO Validate
            return self.routineDef(offset)

        if command == "#text":
            offset = args[0]  #TODO: Validate
            return self.textDef(offset)
        
        if command == "#movement":
            offset = args[0]
            return self.movementDef(offset)
        
        if command[0] == "$":
            #$var = Hi I'm John! is sugar for #inline $var
            return self.parseline ("#inline "+line, resource)

        #Handle inline commands: #inline $Variable = Hi I'm John!
        if command == "#inline":   
            offset  = args[0]  #TODO: Validate
            #ctype   = args[1]  #TODO: Make use of it :)
            
            raise Exception("TODO, not supported yet") #TODO
            
            #All done, inline is over. Continue with normal param
            return resource
        
        #A set of raw commands is added to the stream
        if command == "#binary" or command == "#raw":            
            if not isinstance(resource, Routine):
                raise WrongCommandException()
                
            for byte in args:
                resource.ast().append(ast.ASTByte(toint(byte)))
            return resource
        
        #Parse movements
        if command[0] == ":":
            if not isinstance(resource, PokeMovement):
                raise WrongCommandException
            
            for byte in args:
                resource.append(toint(byte))
            return resource
        
        #Parse strings
        if command[0] == "=":
            if not isinstance(resource, PokeString):
                raise WrongCommandException()
            
            resource.append(line_raw[1:].lstrip())
            return resource
        
        
        # Still here? -> No pre-defined elements, check aliases and commands for
        #                possible command-compile 

        #Try to find an alias for this line, if it is there, take it.
        # Only if there is no matching alias, we look for a command to match
        for alias in self.langdef.aliases:
            if alias.matches(line):
                rawargs = self._prepargs(alias, alias.stripParams(line))
                resource.ast().append(ast.ASTCommand(alias, rawargs))
                return resource
            
        
        #Parse a command
        if command in self.langdef.commands:
            if not isinstance(resource, Routine):
                raise WrongCommandException()
            
            lcommand = self.langdef.commands[command]
            rawargs = self._prepargs(lcommand, args)

            resource.ast().append(ast.ASTCommand(lcommand, rawargs))
            return resource
        
        raise Exception("Could not parse line, no rules matched: %s"%line)
## Load chars etc. used by the PokeString encode/decode functions
## definitions are placed in files: ./textchars and ./texthashes

#  texthash: <hash>\t<value>  text hash, replace this complete thing with values in a text-string
#  textchar <char>\t<value>   text letter rewrite to hex

textchars = {}
texthash = {}

dirname = os.path.join(os.path.dirname(sys.argv[0]), "gbahackpkmn", "strings")
for line in open(dirname + "/textchars", 'r', encoding="iso-8859-15"):
    if line:
        (char, val) = line.split("\t")
        if len(char) > 1: #Chars can be represented as hex numers (&hxx)
            char = chr(toint(char))
        #print("Adding char. "+repr(char))
        textchars[char] = toint(val)

for line in open(dirname + "/texthashes", 'r', encoding="iso-8859-15"):
    if line:
        (hashv, val) = line.split("\t")
        texthash[hashv] = toint(val)

textcharsinv = dict(zip(textchars.values(), textchars))
texthashinv = dict(zip(texthash.values(), texthash))


def decodeChar(char):
    if char == 0x00: #special case
        return " "