Exemplo n.º 1
0
    def __init__(self, rom, config):
        '''Set up and show the main view.'''
        self.rom = rom
        self.config = config

        self.currentScriptgroup = None
        self.startvars = {}
        try:
            self.mapmgr = PokeMapManager(self.rom)
            self.overworld = OverWorldSprites(self.rom)
            self.mainview = MainView(self)
            self.mapchange(4, 0)

        except Exception as e:
            print(e)
            showError(
                None,
                "There was an unexpected error, the program will quit.\n\n" +
                "Possible cautions:\n1) the opened ROM is no GBA Pokemon Game, or\n2) the"
                +
                "provided METADATA file is incomplete, or contains invalid values.\n\n"
                + "DEBUG information:\n" + str(e),
                quitapp=False)
            raise e
 def __init__(self, rom, config):
     '''Set up and show the main view.'''
     self.rom = rom
     self.config = config
     
     self.currentScriptgroup = None
     self.startvars = {}
     try:
         self.mapmgr = PokeMapManager(self.rom)
         self.overworld = OverWorldSprites(self.rom)
         self.mainview = MainView(self)
         self.mapchange(4, 0)
         
     except Exception as e:
         print(e)
         showError(None, 
             "There was an unexpected error, the program will quit.\n\n"+
             "Possible cautions:\n1) the opened ROM is no GBA Pokemon Game, or\n2) the"+
             "provided METADATA file is incomplete, or contains invalid values.\n\n"+
             "DEBUG information:\n"+str(e), quitapp=False)
         raise e
Exemplo n.º 3
0
class Controller():
    def __init__(self, rom, config):
        '''Set up and show the main view.'''
        self.rom = rom
        self.config = config

        self.currentScriptgroup = None
        self.startvars = {}
        try:
            self.mapmgr = PokeMapManager(self.rom)
            self.overworld = OverWorldSprites(self.rom)
            self.mainview = MainView(self)
            self.mapchange(4, 0)

        except Exception as e:
            print(e)
            showError(
                None,
                "There was an unexpected error, the program will quit.\n\n" +
                "Possible cautions:\n1) the opened ROM is no GBA Pokemon Game, or\n2) the"
                +
                "provided METADATA file is incomplete, or contains invalid values.\n\n"
                + "DEBUG information:\n" + str(e),
                quitapp=False)
            raise e

    def getOverworld(self):
        return self.overworld

    def showcommandslist(self):
        webbrowser.open(docuri(self.rom.getScriptLang().getSubLang()))

    def showpokescriptdoc(self):
        webbrowser.open(pokescriptdocuri)

    def mapchange(self, bankid, mapid):
        currentMap = self.mapmgr.getMap(bankid, mapid)
        self.mainview.setScriptList(currentMap)

    def setScripts(self, scriptStructs):
        '''
        Sets the current script, based on the info in the scriptEvent.
        ScriptEvent should be a subclass of: gbahackpkmn.pokemap.MapScriptStruct.
        Gets a list of objects that subclass gbahackpkmn.pokemap.scripts.scriptStruct.
        '''

        startvars = {}

        #Create a scriptgroup with all structs loaded
        scriptgroup = pokescript.ScriptGroup()
        startvarname = "$start"

        prescript = ""
        uniqueid = 0

        for scriptstruct in scriptStructs:
            scriptoffset = scriptstruct.scriptpointer
            if len(scriptStructs) > 1:
                startvarname = "$start[%d]" % uniqueid
                uniqueid += 1

            startvars[startvarname] = scriptstruct
            if scriptoffset:
                pokescript.loadGroup(self.rom, scriptoffset, scriptgroup,
                                     startvarname)
            else:
                prescript += "'No script attatched to the selected scriptstruct %s\n" % repr(
                    scriptstruct)
                prescript += "' If you want to attatch a script, you can uncomment the following lines:\n\n"
                prescript += "'#script %s\n" % startvarname
                prescript += "'  end\n\n"

        self.currentScriptgroup = scriptgroup
        self.startvars = startvars

        self.updateResources(scriptgroup)
        self.resourceSelected(('scripteditor', None))
        self.mainview.setScript(prescript + self.scriptToText(scriptgroup))

    def scriptToText(self, scriptgroup):
        '''
        Starts decompiling at a given pointers.
        Returns all the related scripts as a text-string.
        '''
        starts = []
        scripts = []
        others = []
        for varname in sorted(scriptgroup.getPointerlist().keys(),
                              key=natsort):
            if varname.startswith("$start"):
                starts.append(varname)
            elif varname.startswith("$script"):
                scripts.append(varname)
            else:
                others.append(varname)

        text = ""
        for varname in starts + scripts + others:
            text += scriptgroup.getAST(varname).text() + "\n\n"

        return text

    def testScript(self):
        '''Try to compile the script in the sourceview.'''
        sg = self._compileandtest()
        if sg != None:
            showInfo(self.mainview, "Test OK, the script contains no errors.")

    def _compileandtest(self):
        try:
            sg = self._compile()
        except Exception as e:
            showError(self.mainview, "Compiling failed.\n\nDEBUG: " + str(e))
            raise e
            return None

        try:
            self._validate(sg)
        except Exception as e:
            showError(self.mainview,
                      "There are one or multiple error in script:\n" + str(e))
            raise e
            return None

        return sg

    def burnScript(self):
        '''Compiles the source, if succesful updates the in-game scripts.'''
        sg = self._compileandtest()
        if sg == None:
            return

        try:
            try:
                pointers = self.currentScriptgroup.getPointerlist()
            except:
                pointers = {}
            rom = self.rom

            #set pointers in new scriptgroup related to old scriptgroup
            for varname in sg.getPointerlist():
                if varname in pointers:
                    sg.setPointer(varname, pointers[varname])

            print("______________________")
            print("Burning")
            b = ScriptBurner(rom)
            _ = b.burn(sg)  #newpointers

            print("______________________")
            print("Update script pointers")
            pointerslist = sg.getPointerlist()
            for varname, resource in self.startvars.items():
                try:
                    resource.scriptpointer = pointerslist[varname]
                except:
                    resource.scriptpointer = 0
                self.rom.getRM().store(resource)

            print("")
            print("!! All done! Script injection was succesful!")
            self.currentScriptgroup = sg
            showInfo(self.mainview,
                     "Script was succesfully written to the ROM.")

        except Exception as e:
            showError(
                self.mainview,
                "The script compiled succesfully, but writing the changes to the ROM failed.\n\nDEBUG: "
                + str(e))
            raise e

    def _compile(self):
        '''Compiles the Pokescript, returns a unrelated to original source scriptgroup.'''
        script = self.mainview.getScript()

        print("---------------------")
        print("Compiling")

        try:
            c = ScriptParser(self.rom.getScriptLang())
            c.parselines(script.split("\n"), None)
            print("> Compiling was succesful!")
            return c.scriptgroup()

        except Exception as e:
            print("> Someting went wrong:")
            print(str(e))
            raise e

    def _validate(self, scriptgroup):
        '''Validates a scriptgroup. Throws an exception if there are errors in it.'''
        #TODO: Move to somewhere else? :P

        import gbahackpkmn.pokescript.analysis as ana

        w, e = ana.analyzeScript(scriptgroup)
        errors = []
        for _, w_ in w:
            errors.append(w_)
        for _, e_ in e:
            errors.append(e_)

        if len(errors) > 0:
            raise Exception("\n".join(errors))

    def resourceSelected(self, data):
        rtype, value = data

        if rtype == "trainerbattle":
            from gbapkmneditor.trainers.controller import TrainerEditorController
            self.mainview.setEditor(
                TrainerEditorController(self.rom, value).getView())
        else:
            self.mainview.setEditor(None)

    def updateResources(self, scriptgroup):
        # Look up different kind of resources in the script
        #  Think of: TrainerBattles
        #            Movements
        #            Shop lists (TODO)

        trainerbattles = FindTrainerBattles()
        for astnode in scriptgroup.getASTNodes():
            astnode.collectFromASTs([trainerbattles])

        resources = []
        for trainerbattle in trainerbattles.getTrainerBattles():
            resources.append(("trainerbattle", trainerbattle))

        self.mainview.setResoursesList(resources)

    def startEmulator(self):
        '''Starts the loaded ROM in an emulator.'''
        print(self.config)
        if not 'emulator' in self.config:
            showInfo(
                self.mainview,
                "No emulator is set in the config file! Can not emulate the ROM."
            )
            return
        try:
            command = [
                x if x != "%u" else self.rom.filename
                for x in shlex.split(self.config['emulator'])
            ]
            subprocess.Popen(command)
        except Exception as e:
            showError(self.mainview,
                      "Could not start the emulator:\n" + repr(e))
class Controller():
    def __init__(self, rom, config):
        '''Set up and show the main view.'''
        self.rom = rom
        self.config = config
        
        self.currentScriptgroup = None
        self.startvars = {}
        try:
            self.mapmgr = PokeMapManager(self.rom)
            self.overworld = OverWorldSprites(self.rom)
            self.mainview = MainView(self)
            self.mapchange(4, 0)
            
        except Exception as e:
            print(e)
            showError(None, 
                "There was an unexpected error, the program will quit.\n\n"+
                "Possible cautions:\n1) the opened ROM is no GBA Pokemon Game, or\n2) the"+
                "provided METADATA file is incomplete, or contains invalid values.\n\n"+
                "DEBUG information:\n"+str(e), quitapp=False)
            raise e
        
    def getOverworld(self):
        return self.overworld
    
    def showcommandslist(self):
        webbrowser.open(docuri(self.rom.getScriptLang().getSubLang()))

    def showpokescriptdoc(self):
        webbrowser.open(pokescriptdocuri)

    def mapchange(self, bankid, mapid):
        currentMap = self.mapmgr.getMap(bankid, mapid) 
        self.mainview.setScriptList(currentMap)
        
    def setScripts(self, scriptStructs):
        '''
        Sets the current script, based on the info in the scriptEvent.
        ScriptEvent should be a subclass of: gbahackpkmn.pokemap.MapScriptStruct.
        Gets a list of objects that subclass gbahackpkmn.pokemap.scripts.scriptStruct.
        '''
        
        startvars = {}
        
        #Create a scriptgroup with all structs loaded
        scriptgroup = pokescript.ScriptGroup()
        startvarname = "$start"
        
        prescript = ""
        uniqueid = 0
        
        for scriptstruct in scriptStructs:
            scriptoffset = scriptstruct.scriptpointer
            if len(scriptStructs) > 1:
                startvarname = "$start[%d]"%uniqueid
                uniqueid+=1
            
            startvars[startvarname] = scriptstruct
            if scriptoffset:
                pokescript.loadGroup(self.rom, scriptoffset, scriptgroup, startvarname)
            else:
                prescript += "'No script attatched to the selected scriptstruct %s\n"%repr(scriptstruct)
                prescript += "' If you want to attatch a script, you can uncomment the following lines:\n\n"
                prescript += "'#script %s\n"%startvarname
                prescript += "'  end\n\n"

        self.currentScriptgroup = scriptgroup
        self.startvars = startvars
        
        self.updateResources(scriptgroup)
        self.resourceSelected(('scripteditor', None))
        self.mainview.setScript(prescript+self.scriptToText(scriptgroup))
        


    def scriptToText(self, scriptgroup):
        '''
        Starts decompiling at a given pointers.
        Returns all the related scripts as a text-string.
        '''
        starts = []
        scripts = []
        others = []
        for varname in sorted(scriptgroup.getPointerlist().keys(), key=natsort):
            if varname.startswith("$start"):
                starts.append(varname)
            elif varname.startswith("$script"):
                scripts.append(varname)
            else:
                others.append(varname)
        
        text = ""
        for varname in starts + scripts + others:
            text += scriptgroup.getAST(varname).text()+"\n\n"
        
        return text
    

    def testScript(self):
        '''Try to compile the script in the sourceview.'''
        sg = self._compileandtest()
        if sg != None:
            showInfo(self.mainview, "Test OK, the script contains no errors.")
        
        
    def _compileandtest(self):
        try:
            sg = self._compile()
        except Exception as e:
            showError(self.mainview, "Compiling failed.\n\nDEBUG: "+str(e))
            raise e
            return None
            
        try:
            self._validate(sg)
        except Exception as e:
            showError(self.mainview, "There are one or multiple error in script:\n"+str(e))
            raise e
            return None
        
        return sg
    
    
    def burnScript(self):
        '''Compiles the source, if succesful updates the in-game scripts.'''
        sg = self._compileandtest()
        if sg == None:
            return
        
        try:
            try:
                pointers = self.currentScriptgroup.getPointerlist()
            except:
                pointers = {}
            rom = self.rom
            
            #set pointers in new scriptgroup related to old scriptgroup
            for varname in sg.getPointerlist():
                if varname in pointers:
                    sg.setPointer(varname, pointers[varname])
            
            print("______________________")
            print("Burning")
            b = ScriptBurner(rom)
            _ = b.burn(sg) #newpointers
            
            print("______________________")
            print("Update script pointers")
            pointerslist = sg.getPointerlist()
            for varname, resource in self.startvars.items():
                try:
                    resource.scriptpointer = pointerslist[varname]
                except:
                    resource.scriptpointer = 0
                self.rom.getRM().store(resource)
            
            print("")
            print("!! All done! Script injection was succesful!")
            self.currentScriptgroup = sg
            showInfo(self.mainview, "Script was succesfully written to the ROM.")
            
        except Exception as e:
            showError(self.mainview, "The script compiled succesfully, but writing the changes to the ROM failed.\n\nDEBUG: "+str(e))
            raise e
    
    
    def _compile(self):
        '''Compiles the Pokescript, returns a unrelated to original source scriptgroup.'''
        script = self.mainview.getScript()
        
        print("---------------------")
        print("Compiling")
        
        try:
            c = ScriptParser(self.rom.getScriptLang())
            c.parselines(script.split("\n"), None)
            print("> Compiling was succesful!")
            return c.scriptgroup()
        
        except Exception as e:
            print("> Someting went wrong:")
            print(str(e))
            raise e
    
    
    def _validate(self, scriptgroup):
        '''Validates a scriptgroup. Throws an exception if there are errors in it.'''
        #TODO: Move to somewhere else? :P
        
        import gbahackpkmn.pokescript.analysis as ana
        
        w, e = ana.analyzeScript(scriptgroup)
        errors = []
        for _, w_ in w:
            errors.append(w_)
        for _, e_ in e:
            errors.append(e_)
        
        if len(errors) > 0:
            raise Exception("\n".join(errors))
    
    
    def resourceSelected(self, data):
        rtype, value = data
        
        if rtype == "trainerbattle":
            from gbapkmneditor.trainers.controller import TrainerEditorController
            self.mainview.setEditor(TrainerEditorController(self.rom, value).getView())
        else:
            self.mainview.setEditor(None)

    
    def updateResources(self, scriptgroup):
        # Look up different kind of resources in the script
        #  Think of: TrainerBattles
        #            Movements
        #            Shop lists (TODO)
        
        trainerbattles = FindTrainerBattles()
        for astnode in scriptgroup.getASTNodes():
            astnode.collectFromASTs([trainerbattles])
        
        resources = []
        for trainerbattle in trainerbattles.getTrainerBattles():
            resources.append(("trainerbattle", trainerbattle))
        
        self.mainview.setResoursesList(resources)
        
        
    def startEmulator(self):
        '''Starts the loaded ROM in an emulator.'''
        print(self.config)
        if not 'emulator' in self.config:
            showInfo(self.mainview, "No emulator is set in the config file! Can not emulate the ROM.")
            return
        try:
            command = [x if x != "%u" else self.rom.filename for x in shlex.split(self.config['emulator'])]
            subprocess.Popen(command)
        except Exception as e:
            showError(self.mainview, "Could not start the emulator:\n"+repr(e))