Exemple #1
0
    def __init__(self, name, rom):
        self.name = name

        # read the configuration from the system name
        self.config = Emulator.get_system_config(self.name, "/recalbox/system/configgen/configgen-defaults.yml", "/recalbox/system/configgen/configgen-defaults-arch.yml")
        if "emulator" not in self.config or self.config["emulator"] == "":
            eslog.log("no emulator defined. exiting.")
            raise Exception("No emulator found")

        # load configuration from batocera.conf
        recalSettings = UnixSettings(batoceraFiles.batoceraConf)
        globalSettings = recalSettings.loadAll('global')
        systemSettings = recalSettings.loadAll(self.name)
        gameSettings = recalSettings.loadAll(os.path.basename(rom))

        # update config
        Emulator.updateConfiguration(self.config, globalSettings)
        Emulator.updateConfiguration(self.config, systemSettings)
        Emulator.updateConfiguration(self.config, gameSettings)
        self.updateDrawFPS()

        # update renderconfig
        self.renderconfig = {}
        if "shaderset" in self.config and self.config["shaderset"] != "none":
            self.renderconfig = Emulator.get_generic_config(self.name, "/usr/share/batocera/shaders/configs/" + self.config["shaderset"] + "/rendering-defaults.yml", "/usr/share/batocera/shaders/configs/" + self.config["shaderset"] + "/rendering-defaults-arch.yml")
        if "shaderset" not in self.config: # auto
            self.renderconfig = Emulator.get_generic_config(self.name, "/usr/share/batocera/shaders/configs/rendering-defaults.yml", "/usr/share/batocera/shaders/configs/rendering-defaults-arch.yml")

        systemSettings = recalSettings.loadAll(self.name + "-renderer")
        gameSettings = recalSettings.loadAll(os.path.basename(rom) + "-renderer")

        # es only allow to update systemSettings and gameSettings in fact for the moment
        Emulator.updateConfiguration(self.renderconfig, systemSettings)
        Emulator.updateConfiguration(self.renderconfig, gameSettings)
Exemple #2
0
def getDefaultEmulator(systemName):
    system = get_system_config(systemName)
    if "emulator" not in system or system["emulator"] == "":
        eslog.log("no emulator defined. exiting.")
        raise Exception("No emulator found")

    return Emulator(name=systemName, config=system)
Exemple #3
0
    def findBestTos(biosdir, machine, tos_version, language):
        # all languages by preference, when value is "auto"
        all_languages = ["us", "uk", "de", "es", "fr", "it", "nl", "ru", "se", ""]

        # machine bioses by prefered orders, when value is "auto"
        all_machines_bios = {
            "st":      ["104", "102", "100"],
            "ste":     ["162", "106"],
            "megaste": ["206", "205"]
        }
        
        if machine in all_machines_bios:
            l_tos = []
            if tos_version != "auto":
                l_tos = [tos_version]
            l_tos.extend(all_machines_bios[machine])
            for v_tos_version in l_tos:
                l_lang = []
                if l_lang != "auto":
                    l_lang = [language]
                l_lang.extend(all_languages)
                for v_language in l_lang:
                    filename = "tos{}{}.img".format(v_tos_version, v_language)
                    if os.path.exists("{}/{}".format(biosdir, filename)):
                        eslog.log("tos filename: {}".format(filename))
                        return filename
                    else:
                        eslog.log("tos filename {} not found".format(filename))

        raise Exception("no bios found for machine {}".format(machine))
    def getRomType(self, filepath):
        extension = os.path.splitext(filepath)[1][1:].lower()

        if extension == "lha":
            return 'WHDL'
        elif extension == 'hdf':
            return 'HDF'
        elif extension in ['iso', 'cue']:
            return 'CD'
        elif extension in ['adf', 'ipf']:
            return 'DISK'
        elif extension == "zip":
            # can be either whdl or adf
            with zipfile.ZipFile(filepath) as zip:
                for zipfilename in zip.namelist():
                    if zipfilename.find('/') == -1:  # at the root
                        extension = os.path.splitext(zipfilename)[1][1:]
                        if extension == "info":
                            return 'WHDL'
                        elif extension == 'lha':
                            eslog.log(
                                "Amiberry doesn't support .lha inside a .zip")
                            return 'UNKNOWN'
                        elif extension == 'adf':
                            return 'DISK'
            # no info or adf file found
            return 'UNKNOWN'

        return 'UNKNOWN'
Exemple #5
0
def generateControllerConfig(controller):
    # Set config file name
    configFileName = "{}/evdev_{}.cfg".format(batoceraFiles.flycastMapping,
                                              controller.realName)
    Config = configparser.ConfigParser(interpolation=None)

    if not os.path.exists(os.path.dirname(configFileName)):
        os.makedirs(os.path.dirname(configFileName))

    cfgfile = open(configFileName, 'w+')

    # create ini sections
    for section in sections:
        Config.add_section(section)

    # Add controller name
    Config.set("emulator", "mapping_name", controller.realName)

    l2_r2_flag = False
    if 'r2' in controller.inputs:
        l2_r2_flag = True

    # Parse controller inputs
    for index in controller.inputs:
        input = controller.inputs[index]

        if input.name not in flycastMapping:
            continue
        if input.type not in flycastMapping[input.name]:
            continue
        var = flycastMapping[input.name][input.type]
        eslog.log("Var: {}".format(var))
        for i in sections:
            if var in sections[i]:
                section = i
                break

        if l2_r2_flag and (input.name == 'pageup' or input.name == 'pagedown'):
            continue

        # batocera doesn't retrieve the code for hats, however, this is 16/17+input.id in linux/input.h
        if input.type == 'hat':
            if input.name == 'up':  #Default values for hat0.  Formula for calculation is 16+input.id*2 and 17+input.id*2
                code = 17 + 2 * int(input.id)  # ABS_HAT0Y=17
            else:
                code = 16 + 2 * int(input.id)  # ABS_HAT0X=16
            Config.set(section, var, str(code))
        else:
            if input.code is not None:
                code = input.code
                Config.set(section, var, code)
            else:
                eslog.log("code not found for key " + input.name + " on pad " +
                          controller.realName +
                          " (please reconfigure your pad)")

    Config.write(cfgfile)
    cfgfile.close()
    return configFileName
def generateControllerConfig(controller):
    # Set config file name
    configFileName = "{}/evdev_{}.cfg".format(batoceraFiles.flycastMapping,
                                              controller.realName)
    Config = configparser.ConfigParser()

    if not os.path.exists(os.path.dirname(configFileName)):
        os.makedirs(os.path.dirname(configFileName))

    cfgfile = open(configFileName, 'w+')

    # create ini sections
    for section in sections:
        Config.add_section(section)

    # Add controller name
    Config.set("emulator", "mapping_name", controller.realName)

    l2_r2_flag = False
    if 'r2' in controller.inputs:
        l2_r2_flag = True
    # Parse controller inputs
    for index in controller.inputs:
        input = controller.inputs[index]

        if input.name not in flycastMapping:
            continue
        if input.type not in flycastMapping[input.name]:
            continue
        var = flycastMapping[input.name][input.type]
        eslog.log("Var: {}".format(var))
        for i in sections:
            if var in sections[i]:
                section = i
                break

        # Sadly, we don't get the right axis code for Y hats. So, dirty hack time
        if not (l2_r2_flag and
                (input.name == 'pageup' or input.name == 'pagedown')):
            if input.code is not None:
                code = input.code
                Config.set(section, var, code)
            elif input.type == 'hat':
                if input.code is None:  #handles pads that don't have hat codes set
                    if input.name == 'up':  #Default values for hat0.  Formula for calculation is 16+input.id*2 and 17+input.id*2
                        code = 17 + 2 * int(input.id)  # ABS_HAT0Y=17
                    else:
                        code = 16 + 2 * int(input.id)  # ABS_HAT0X=16
                else:
                    code = input.code
                Config.set(section, var, code)
            else:
                eslog.log("code not found for key " + input.name + " on pad " +
                          controller.realName +
                          " (please reconfigure your pad)")

    Config.write(cfgfile)
    cfgfile.close()
    return configFileName
Exemple #7
0
def callExternalScripts(folder, event, args):
    if not os.path.isdir(folder):
        return

    for file in os.listdir(folder):
        if os.path.isdir(os.path.join(folder, file)):
            callExternalScripts(os.path.join(folder, file), event, args)
        else:
            if os.access(os.path.join(folder, file), os.X_OK):
                eslog.log("calling external script: " + str([os.path.join(folder, file), event] + args))
                subprocess.call([os.path.join(folder, file), event] + args)
Exemple #8
0
    def generate(self, system, rom, playersControllers, gameResolution):
        configDir = batoceraFiles.CONF + '/openbor'
        if not os.path.exists(configDir):
            os.makedirs(configDir)

        savesDir = batoceraFiles.SAVES + '/openbor'
        if not os.path.exists(savesDir):
            os.makedirs(savesDir)

        # guess the version to run
        core = system.config['core']
        if system.config["core-forced"] == False:
            core = OpenborGenerator.guessCore(rom)
        eslog.log("core taken is {}".format(core))

        # config file
        configfilename = "config6510.ini"
        if core == "openbor4432":
            configfilename = "config4432.ini"
        elif core == "openbor6330":
            configfilename = "config6330.ini"
        elif core == "openbor6412":
            configfilename = "config6412.ini"
        elif core == "openbor6510":
            configfilename = "config6510.ini"

        config = UnixSettings(configDir + "/" + configfilename, separator='')

        # general
        config.save("fullscreen", "1")
        config.save("vsync", "1")
        config.save("usegl", "1")
        config.save("usejoy", "1")

        # options
        if system.isOptSet("ratio"):
            config.save("stretch", system.config["ratio"])
        else:
            config.remove("stretch")

        if system.isOptSet("filter"):
            config.save("swfilter", system.config["filter"])
        else:
            config.remove("swfilter")

        # controllers
        openborControllers.generateControllerConfig(config, playersControllers,
                                                    core)

        config.write()

        return OpenborGenerator.executeCore(core, rom)
Exemple #9
0
    def __init__(self, name, rom):
        self.name = name

        # read the configuration from the system name
        self.config = Emulator.get_system_config(
            self.name, "/usr/share/batocera/configgen/configgen-defaults.yml",
            "/usr/share/batocera/configgen/configgen-defaults-arch.yml")
        if "emulator" not in self.config or self.config["emulator"] == "":
            eslog.log("no emulator defined. exiting.")
            raise Exception("No emulator found")

        # load configuration from batocera.conf
        recalSettings = UnixSettings(batoceraFiles.batoceraConf)
        globalSettings = recalSettings.loadAll('global')
        systemSettings = recalSettings.loadAll(self.name)
        gameSettings = recalSettings.loadAll(self.name + "[\"" +
                                             os.path.basename(rom) + "\"]")

        # update config
        Emulator.updateConfiguration(self.config, globalSettings)
        Emulator.updateConfiguration(self.config, systemSettings)
        Emulator.updateConfiguration(self.config, gameSettings)
        self.updateFromESSettings()
        eslog.log("uimode: {}".format(self.config['uimode']))

        # update renderconfig
        self.renderconfig = {}
        if "shaderset" in self.config and self.config["shaderset"] != "none":
            self.renderconfig = Emulator.get_generic_config(
                self.name, "/usr/share/batocera/shaders/configs/" +
                self.config["shaderset"] + "/rendering-defaults.yml",
                "/usr/share/batocera/shaders/configs/" +
                self.config["shaderset"] + "/rendering-defaults-arch.yml")
        if "shaderset" not in self.config:  # auto
            self.renderconfig = Emulator.get_generic_config(
                self.name,
                "/usr/share/batocera/shaders/configs/rendering-defaults.yml",
                "/usr/share/batocera/shaders/configs/rendering-defaults-arch.yml"
            )

        # for compatibility with earlier Batocera versions, let's keep -renderer
        # but it should be reviewed when we refactor configgen (to Python3?)
        # so that we can fetch them from system.shader without -renderer
        systemSettings = recalSettings.loadAll(self.name + "-renderer")
        gameSettings = recalSettings.loadAll(self.name + "[\"" +
                                             os.path.basename(rom) + "\"]" +
                                             "-renderer")

        # es only allow to update systemSettings and gameSettings in fact for the moment
        Emulator.updateConfiguration(self.renderconfig, systemSettings)
        Emulator.updateConfiguration(self.renderconfig, gameSettings)
def generateControllerConfig_any_from_profiles(f, pad):
    for profileFile in glob.glob(
            "/userdata/system/configs/dolphin-emu/Profiles/GCPad/*.ini"):
        try:
            eslog.log("Looking profile : {}".format(profileFile))
            profileConfig = configparser.ConfigParser(interpolation=None)
            # To prevent ConfigParser from converting to lower case
            profileConfig.optionxform = str
            profileConfig.read(profileFile)
            profileDevice = profileConfig.get("Profile", "Device")
            eslog.log("Profile device : {}".format(profileDevice))

            deviceVals = re.match("^([^/]*)/[0-9]*/(.*)$", profileDevice)
            if deviceVals is not None:
                if deviceVals.group(1) == "evdev" and deviceVals.group(
                        2).strip() == pad.realName.strip():
                    eslog.log("Eligible profile device found")
                    for key, val in profileConfig.items("Profile"):
                        if key != "Device":
                            f.write("{} = {}\n".format(key, val))
                    return True
        except:
            eslog.log("profile {} : FAILED".format(profileFile))

    return False
def rpcs3_mappingValue(name, type, code, value):
    if type == "button":
        return code
    elif type == "hat":
        if value == 1:
            return -1017
        if value == 2:
            return 1016
        if value == 4:
            return 1017
        if value == 8:
            return -1016
        raise Exception("invalid hat value {}".format(value))
    elif type == "axis":
        res = int(code) + 1000
        if value < 0:
            eslog.log("name = {} and value = {}".format(name, value))
            res = res * -1
        return res
    return None
def generateInputConfigs(controllers):
    if not path.isdir(batoceraFiles.CONF + "/rpcs3/InputConfigs/Evdev"):
        os.makedirs(batoceraFiles.CONF + "/rpcs3/InputConfigs/Evdev")
    nplayer = 1
    for controller, pad in sorted(controllers.items()):
        if nplayer <= 7:
            configFileName = "{}/{}/pad{}.yml".format(
                batoceraFiles.CONF, "rpcs3/InputConfigs/Evdev", nplayer)
            f = codecs.open(configFileName, "w", encoding="utf_8_sig")
            for inputIdx in pad.inputs:
                input = pad.inputs[inputIdx]
                key = rpcs3_mappingKey(input.name)
                if key is not None:
                    f.write("{}: {}\n".format(
                        key,
                        rpcs3_mappingValue(input.name, input.type, input.code,
                                           int(input.value))))
                else:
                    eslog.log("no rpcs3 mapping found for {}".format(
                        input.name))

                # write the reverse
                if input.name == "joystick1up" or input.name == "joystick1left" or input.name == "joystick2up" or input.name == "joystick2left":
                    reversedName = rpcs3_reverseMapping(input.name)
                    key = rpcs3_mappingKey(reversedName)
                    if key is not None:
                        f.write("{}: {}\n".format(
                            key,
                            rpcs3_mappingValue(reversedName, input.type,
                                               input.code,
                                               int(input.value) * -1)))
                    else:
                        eslog.log("no rpcs3 mapping found for {}".format(
                            input.name))

            rpcs3_otherKeys(f, controller)
            f.close()
        nplayer += 1
def runCommand(command):
    global proc

    command.env.update(os.environ)
    eslog.log("command: {}".format(str(command)))
    eslog.log("command: {}".format(str(command.array)))
    eslog.log("env: {}".format(str(command.env)))
    proc = subprocess.Popen(command.array, env=command.env, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    exitcode = -1
    try:
        out, err = proc.communicate()
        exitcode = proc.returncode
        sys.stdout.write(out)
        sys.stderr.write(err)
    except:
        eslog.log("emulator exited")

    return exitcode
Exemple #14
0
    def __init__(self, name):
        self.name = name

        # read the configuration from the system name
        self.config = Emulator.get_system_config(
            self.name, "/recalbox/system/configgen/configgen-defaults.yml",
            "/recalbox/system/configgen/configgen-defaults-arch.yml")
        if "emulator" not in self.config or self.config["emulator"] == "":
            eslog.log("no emulator defined. exiting.")
            raise Exception("No emulator found")

        # load configuration from batocera.conf
        recalSettings = UnixSettings(batoceraFiles.batoceraConf)
        globalSettings = recalSettings.loadAll('global')
        systemSettings = recalSettings.loadAll(self.name)

        # update config
        Emulator.updateConfiguration(self.config, globalSettings)
        Emulator.updateConfiguration(self.config, systemSettings)
        self.updateDrawFPS()

        # update renderconfig
        self.renderconfig = Emulator.get_generic_config(
            self.name,
            "/usr/share/batocera/shaders/configs/rendering-defaults.yml",
            "/usr/share/batocera/shaders/configs/rendering-defaults-arch.yml")
        if "shaderset" in self.config and self.config["shaderset"] != "none":
            eslog.log("shaderset={}".format(self.config["shaderset"]))
            globalSettings = recalSettings.loadAll('global-renderer-' +
                                                   self.config["shaderset"])
            systemSettings = recalSettings.loadAll(self.name + "-renderer-" +
                                                   self.config["shaderset"])
            self.renderconfig = Emulator.get_generic_config(
                self.name, "/usr/share/batocera/shaders/configs/" +
                self.config["shaderset"] + "/rendering-defaults.yml",
                "/usr/share/batocera/shaders/configs/" +
                self.config["shaderset"] + "/rendering-defaults-arch.yml")
            Emulator.updateConfiguration(self.renderconfig, globalSettings)
            Emulator.updateConfiguration(self.renderconfig, systemSettings)
            eslog.log("shader file={}".format(self.renderconfig["shader"]))
        else:
            eslog.log("no shader")
Exemple #15
0
    def generate(self, system, rom, playersControllers, gameResolution):
        # Test if it's a m3u file
        if os.path.splitext(rom)[1] == ".m3u":
            rom = rewriteM3uFullPath(rom)

        commandArray = ["duckstation", "-batch", "-fullscreen", "--", rom]

        settings = configparser.ConfigParser(interpolation=None)
        # To prevent ConfigParser from converting to lower case
        settings.optionxform = str
        settings_path = batoceraFiles.SAVES + "/duckstation/settings.ini"
        if os.path.exists(settings_path):
            settings.read(settings_path)

        ## [MAIN]
        if not settings.has_section("Main"):
            settings.add_section("Main")

        # Settings, Language and ConfirmPowerOff
        settings.set("Main", "SettingsVersion",
                     "3")  # Probably to be updated in the future
        settings.set("Main", "Language", getLangFromEnvironment())
        settings.set("Main", "ConfirmPowerOff", "false")
        # Force Fullscreen
        settings.set("Main", "EnableFullscreenUI", "true")
        # Controller backend
        settings.set("Main", "ControllerBackend", "SDL")
        # Force applying game Settings fixes
        settings.set("Main", "ApplyGameSettings", "true")

        # Rewind
        #if system.isOptSet('rewind') and system.getOptBoolean('rewind') == True:
        settings.set("Main", "RewindEnable", "true")
        settings.set("Main", "RewindFrequency",
                     "1")  # Frame skipped each seconds
        if system.isOptSet("duckstation_rewind"
                           ) and system.config["duckstation_rewind"] == '120':
            settings.set("Main", "RewindSaveSlots",
                         "120")  # Total duration available in sec
        elif system.isOptSet("duckstation_rewind"
                             ) and system.config["duckstation_rewind"] == '90':
            settings.set("Main", "RewindSaveSlots", "90")
        elif system.isOptSet("duckstation_rewind"
                             ) and system.config["duckstation_rewind"] == '60':
            settings.set("Main", "RewindSaveSlots", "60")
        elif system.isOptSet("duckstation_rewind"
                             ) and system.config["duckstation_rewind"] == '30':
            settings.set("Main", "RewindSaveSlots", "30")
        elif system.isOptSet("duckstation_rewind"
                             ) and system.config["duckstation_rewind"] == '15':
            settings.set("Main", "RewindSaveSlots", "15")
        elif system.isOptSet("duckstation_rewind"
                             ) and system.config["duckstation_rewind"] == '10':
            settings.set("Main", "RewindSaveSlots", "100")
            settings.set("Main", "RewindFrequency", "0,100000")
        elif system.isOptSet("duckstation_rewind"
                             ) and system.config["duckstation_rewind"] == '5':
            settings.set("Main", "RewindSaveSlots", "50")
            settings.set("Main", "RewindFrequency", "0,100000")
        else:
            settings.set("Main", "RewindEnable", "false")

        ## [UI]
        if not settings.has_section("UI"):
            settings.add_section("UI")
        # Show Messages
        settings.set("UI", "ShowOSDMessages", "true")

        ## [CONSOLE]
        if not settings.has_section("Console"):
            settings.add_section("Console")
        # Region
        settings.set("Console", "Region", "Auto")

        ## [BIOS]
        if not settings.has_section("BIOS"):
            settings.add_section("BIOS")
        settings.set("BIOS", "SearchDirectory", "/userdata/bios")  # Path
        # Boot Logo
        if system.isOptSet("duckstation_PatchFastBoot") and system.config[
                "duckstation_PatchFastBoot"] != '0':
            settings.set("BIOS", "PatchFastBoot", "true")
        else:
            settings.set("BIOS", "PatchFastBoot", "false")

        ## [GPU]
        if not settings.has_section("GPU"):
            settings.add_section("GPU")

        # Backend - Default OpenGL
        if system.isOptSet(
                "gfxbackend") and system.config["gfxbackend"] == 'Vulkan':
            settings.set("GPU", "Renderer", "Vulkan")
        else:
            settings.set("GPU", "Renderer", "OpenGL")
        # Multisampling force (MSAA or SSAA)
        settings.set("GPU", "PerSampleShading", "false")
        if system.isOptSet("duckstation_antialiasing") and system.config[
                "duckstation_antialiasing"] != '1':
            tab = system.config["duckstation_antialiasing"].split('-')
            settings.set("GPU", "Multisamples", tab[0])
            if len(tab) > 1:
                settings.set("GPU", "PerSampleShading", "true")
        else:
            settings.set("GPU", "Multisamples", "1")
        # Threaded Presentation (Vulkan Improve)
        if system.isOptSet(
                "duckstation_threadedpresentation"
        ) and system.config["duckstation_threadedpresentation"] != '0':
            settings.set("GPU", "ThreadedPresentation", "true")
        else:
            settings.set("GPU", "ThreadedPresentation", "false")
        # Internal resolution
        if system.isOptSet("duckstation_resolution_scale") and system.config[
                "duckstation_resolution_scale"] != '1':
            settings.set("GPU", "ResolutionScale",
                         system.config["duckstation_resolution_scale"])
        else:
            settings.set("GPU", "ResolutionScale", "1")
        # WideScreen Hack
        if system.isOptSet('duckstation_widescreen_hack') and system.config[
                "duckstation_widescreen_hack"] != '0' and system.config[
                    "ratio"] == "16/9":  # and system.config["bezel"] == "none"::
            settings.set("GPU", "WidescreenHack", "true")
        else:
            settings.set("GPU", "WidescreenHack", "false")
        # TextureFiltering
        if system.isOptSet("duckstation_texture_filtering") and system.config[
                "duckstation_texture_filtering"] != 'Nearest':
            settings.set("GPU", "TextureFilter",
                         system.config["duckstation_texture_filtering"])
        else:
            settings.set("GPU", "TextureFilter", "Nearest")

        ## [DISPLAY]
        if not settings.has_section("Display"):
            settings.add_section("Display")

        # Aspect Ratio
        settings.set("Display", "AspectRatio",
                     getGfxRatioFromConfig(system.config, gameResolution))
        # Vsync
        if system.isOptSet("duckstation_vsync"
                           ) and system.config["duckstation_vsync"] != '1':
            settings.set("Display", "Vsync", "false")
        else:
            settings.set("Display", "Vsync", "true")
        # CropMode
        if system.isOptSet("duckstation_CropMode") and system.config[
                "duckstation_CropMode"] != 'None':
            settings.set("Display", "CropMode",
                         system.config["duckstation_CropMode"])
        else:
            settings.set("Display", "CropMode", "Overscan")
        # Enable Frameskipping
        if system.isOptSet('duckstation_frameskip'
                           ) and system.config["duckstation_frameskip"] != '0':
            settings.set("Display", "DisplayAllFrames", "true")
        else:
            settings.set("Display", "DisplayAllFrames", "false")

        ## [CHEEVOS]
        if not settings.has_section("Cheevos"):
            settings.add_section("Cheevos")

        # Retroachievements : TODO
        #settings.set("Cheevos", "Enabled",  "true")
        #settings.set("Cheevos", "Username", "")
        #settings.set("Cheevos", "Token",    "")                      # http://retroachievements.org/dorequest.php?r=login&u=%s&p=%s
        #settings.set("Cheevos", "UseFirstDiscFromPlaylist", "false") # When enabled, the first disc in a playlist will be used for achievements, regardless of which disc is active
        #settings.set("Cheevos", "RichPresence",  "true")             # Enable rich presence information will be collected and sent to the server where supported
        #settings.set("Cheevos", "ChallengeMode", "false")            # Disables save states, cheats, slowdown functions but you receive 2x achievements points.
        #settings.set("Cheevos", "TestMode",      "false")            # DuckStation will assume all achievements are locked and not send any unlock notifications to the server.

        ## [CONTROLLERPORTS]
        if not settings.has_section("ControllerPorts"):
            settings.add_section("ControllerPorts")

        # Multitap
        if system.isOptSet("duckstation_multitap") and system.config[
                "duckstation_multitap"] != 'Disabled':
            settings.set("ControllerPorts", "MultitapMode",
                         system.config["duckstation_multitap"])
        else:
            settings.set("ControllerPorts", "MultitapMode", "Disabled")

        ## [CONTROLLERS]
        configurePads(settings, playersControllers, system)

        ## [HOTKEYS]
        if not settings.has_section("Hotkeys"):
            settings.add_section("Hotkeys")

        # Force defaults to be aligned with evmapy
        settings.set("Hotkeys", "FastForward", "Keyboard/Tab")
        settings.set("Hotkeys", "TogglePause", "Keyboard/Pause")
        settings.set("Hotkeys", "PowerOff", "Keyboard/Escape")
        settings.set("Hotkeys", "LoadSelectedSaveState", "Keyboard/F1")
        settings.set("Hotkeys", "SaveSelectedSaveState", "Keyboard/F2")
        settings.set("Hotkeys", "SelectPreviousSaveStateSlot", "Keyboard/F3")
        settings.set("Hotkeys", "SelectNextSaveStateSlot", "Keyboard/F4")
        settings.set("Hotkeys", "Screenshot", "Keyboard/F10")
        settings.set("Hotkeys", "Rewind", "Keyboard/F5")

        # Show FPS (Debug)
        if system.isOptSet("showFPS") and system.getOptBoolean("showFPS"):
            settings.set("Display", "ShowFPS", "true")
            settings.set("Display", "ShowSpeed", "true")
            settings.set("Display", "ShowVPS", "true")
            settings.set("Display", "ShowResolution", "true")
        else:
            settings.set("Display", "ShowFPS", "false")
            settings.set("Display", "ShowSpeed", "false")
            settings.set("Display", "ShowVPS", "false")
            settings.set("Display", "ShowResolution", "false")

        # RetroAchievements
        if not settings.has_section("Cheevos"):
            settings.add_section("Cheevos")
        if system.isOptSet('retroachievements') and system.getOptBoolean(
                'retroachievements') == True:
            headers = {"Content-type": "text/plain"}
            login_url = "https://retroachievements.org/"
            username = system.config.get('retroachievements.username', "")
            password = system.config.get('retroachievements.password', "")
            login_cmd = "dorequest.php?r=login&u={}&p={}".format(
                username, password)
            try:
                cnx = httplib2.Http()
            except:
                eslog.log("ERROR: Unable to connect to " + login_url)
            try:
                res, rout = cnx.request(login_url + login_cmd,
                                        method="GET",
                                        body=None,
                                        headers=headers)
                if (res.status != 200):
                    eslog.log(
                        "ERROR: RetroAchievements.org responded with #{} [{}] {}"
                        .format(res.status, res.reason, rout))
                    settings.set("Cheevos", "Enabled", "false")
                else:
                    parsedout = json.loads((rout.decode('utf-8')))
                    if not parsedout['Success']:
                        eslog.log(
                            "ERROR: RetroAchievements login failed with ({})".
                            format(str(parsedout)))
                    token = parsedout['Token']
                    settings.set("Cheevos", "Enabled", "true")
                    settings.set("Cheevos", "Username", username)
                    settings.set("Cheevos", "Token", token)
                    eslog.log(
                        "Duckstation RetroAchievements enabled for {}".format(
                            username))
            except Exception as e:
                eslog.log(
                    "ERROR: Impossible to get a RetroAchievements token ({})".
                    format(e))
                settings.set("Cheevos", "Enabled", "false")
        else:
            settings.set("Cheevos", "Enabled", "false")

        # Save config
        if not os.path.exists(os.path.dirname(settings_path)):
            os.makedirs(os.path.dirname(settings_path))

        with open(settings_path, 'w') as configfile:
            settings.write(configfile)

        env = {
            "XDG_CONFIG_HOME": batoceraFiles.CONF,
            "XDG_DATA_HOME": batoceraFiles.SAVES,
            "QT_QPA_PLATFORM": "xcb"
        }
        return Command.Command(array=commandArray, env=env)
Exemple #16
0
def createLibretroConfig(system, controllers, rom, bezel, gameResolution):
    # Create/update retroarch-core-options.cfg
    libretroOptions.generateCoreSettings(batoceraFiles.retroarchCoreCustom,
                                         system)

    # Create/update hatari.cfg
    if system.name == 'atarist':
        libretroOptions.generateHatariConf(batoceraFiles.hatariConf)

    retroarchConfig = dict()
    systemConfig = system.config
    renderConfig = system.renderconfig

    # basic configuration
    retroarchConfig[
        'quit_press_twice'] = 'false'  # not aligned behavior on other emus
    retroarchConfig['video_driver'] = '"gl"'  # needed for the ozone menu
    retroarchConfig[
        'video_black_frame_insertion'] = 'false'  # don't use anymore this value while it doesn't allow the shaders to work
    retroarchConfig[
        'pause_nonactive'] = 'false'  # required at least on x86 x86_64 otherwise, the game is paused at launch
    retroarchConfig[
        'audio_driver'] = 'alsa'  # force ALSA. TODO: check audio.backend
    retroarchConfig['midi_driver'] = 'alsa'
    retroarchConfig['cache_directory'] = '/userdata/system/.cache'

    # fs is required at least for x86* and odroidn2
    retroarchConfig['video_fullscreen'] = 'true'

    if system.isOptSet('smooth') and system.getOptBoolean('smooth') == True:
        retroarchConfig['video_smooth'] = 'true'
    else:
        retroarchConfig['video_smooth'] = 'false'

    if 'shader' in renderConfig and renderConfig['shader'] != None:
        retroarchConfig['video_shader_enable'] = 'true'
        retroarchConfig[
            'video_smooth'] = 'false'  # seems to be necessary for weaker SBCs
        shaderFilename = renderConfig['shader'] + ".glslp"
        if os.path.exists("/userdata/shaders/" + shaderFilename):
            retroarchConfig['video_shader_dir'] = "/userdata/shaders"
            eslog.log(
                "shader {} found in /userdata/shaders".format(shaderFilename))
        else:
            retroarchConfig['video_shader_dir'] = "/usr/share/batocera/shaders"
    else:
        retroarchConfig['video_shader_enable'] = 'false'

    retroarchConfig[
        'aspect_ratio_index'] = ''  # reset in case config was changed (or for overlays)
    if defined('ratio', systemConfig):
        if systemConfig['ratio'] in ratioIndexes:
            retroarchConfig['aspect_ratio_index'] = ratioIndexes.index(
                systemConfig['ratio'])
            retroarchConfig['video_aspect_ratio_auto'] = 'false'
        elif systemConfig['ratio'] == "custom":
            retroarchConfig['video_aspect_ratio_auto'] = 'false'
        else:
            retroarchConfig['video_aspect_ratio_auto'] = 'true'
            retroarchConfig['aspect_ratio_index'] = ''

    retroarchConfig['rewind_enable'] = 'false'

    if system.isOptSet('rewind') and system.getOptBoolean('rewind') == True:
        if (not system.name in systemNoRewind):
            retroarchConfig['rewind_enable'] = 'true'
    else:
        retroarchConfig['rewind_enable'] = 'false'

    retroarchConfig['run_ahead_enabled'] = 'false'
    retroarchConfig['run_ahead_frames'] = '0'
    retroarchConfig['run_ahead_secondary_instance'] = 'false'

    if system.isOptSet('runahead') and int(system.config['runahead']) > 0:
        if (not system.name in systemNoRunahead):
            retroarchConfig['run_ahead_enabled'] = 'true'
            retroarchConfig['run_ahead_frames'] = system.config['runahead']
            if system.isOptSet('secondinstance') and system.getOptBoolean(
                    'secondinstance') == True:
                retroarchConfig['run_ahead_secondary_instance'] = 'true'

    if system.isOptSet('autosave') and system.getOptBoolean(
            'autosave') == True:
        retroarchConfig['savestate_auto_save'] = 'true'
        retroarchConfig['savestate_auto_load'] = 'true'
    else:
        retroarchConfig['savestate_auto_save'] = 'false'
        retroarchConfig['savestate_auto_load'] = 'false'

    retroarchConfig['input_joypad_driver'] = 'udev'
    retroarchConfig['input_max_users'] = "16"  # allow up to 16 players

    retroarchConfig[
        'savestate_directory'] = batoceraFiles.savesDir + system.name
    retroarchConfig[
        'savefile_directory'] = batoceraFiles.savesDir + system.name

    retroarchConfig['input_libretro_device_p1'] = '1'
    retroarchConfig['input_libretro_device_p2'] = '1'

    if (system.config['core'] in coreToP1Device):
        retroarchConfig['input_libretro_device_p1'] = coreToP1Device[
            system.config['core']]

    if (system.config['core'] in coreToP2Device):
        retroarchConfig['input_libretro_device_p2'] = coreToP2Device[
            system.config['core']]

    if len(controllers) > 2 and (system.config['core'] == 'snes9x_next'
                                 or system.config['core'] == 'snes9x'):
        retroarchConfig['input_libretro_device_p2'] = '257'

    if system.config['core'] == 'atari800':
        retroarchConfig['input_libretro_device_p1'] = '513'
        retroarchConfig['input_libretro_device_p2'] = '513'

    retroarchConfig['cheevos_enable'] = 'false'
    retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
    retroarchConfig['cheevos_leaderboards_enable'] = 'false'
    retroarchConfig['cheevos_verbose_enable'] = 'false'
    retroarchConfig['cheevos_auto_screenshot'] = 'false'

    if system.isOptSet('retroachievements') and system.getOptBoolean(
            'retroachievements') == True:
        if (system.name in systemToRetroachievements):
            retroarchConfig['cheevos_enable'] = 'true'
            retroarchConfig['cheevos_username'] = systemConfig.get(
                'retroachievements.username', "")
            retroarchConfig['cheevos_password'] = systemConfig.get(
                'retroachievements.password', "")
            # retroachievements_hardcore_mode
            if system.isOptSet(
                    'retroachievements.hardcore') and system.getOptBoolean(
                        'retroachievements.hardcore') == True:
                retroarchConfig['cheevos_hardcore_mode_enable'] = 'true'
            else:
                retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
            # retroachievements_leaderboards
            if system.isOptSet(
                    'retroachievements.leaderboards') and system.getOptBoolean(
                        'retroachievements.leaderboards') == True:
                retroarchConfig['cheevos_leaderboards_enable'] = 'true'
            else:
                retroarchConfig['cheevos_leaderboards_enable'] = 'false'
            # retroachievements_verbose_mode
            if system.isOptSet(
                    'retroachievements.verbose') and system.getOptBoolean(
                        'retroachievements.verbose') == True:
                retroarchConfig['cheevos_verbose_enable'] = 'true'
            else:
                retroarchConfig['cheevos_verbose_enable'] = 'false'
            # retroachievements_automatic_screenshot
            if system.isOptSet(
                    'retroachievements.screenshot') and system.getOptBoolean(
                        'retroachievements.screenshot') == True:
                retroarchConfig['cheevos_auto_screenshot'] = 'true'
            else:
                retroarchConfig['cheevos_auto_screenshot'] = 'false'
    else:
        retroarchConfig['cheevos_enable'] = 'false'

    if system.isOptSet('integerscale') and system.getOptBoolean(
            'integerscale') == True:
        retroarchConfig['video_scale_integer'] = 'true'
    else:
        retroarchConfig['video_scale_integer'] = 'false'

    # disable the threaded video while it is causing issues to several people ?
    # this must be set to true on xu4 for performance issues
    if system.config['video_threaded']:
        retroarchConfig['video_threaded'] = 'true'
    else:
        retroarchConfig['video_threaded'] = 'false'

    # core options
    if (system.name in systemToBluemsx):
        if system.config['core'] == 'bluemsx':
            retroarchConfig['input_libretro_device_p1'] = systemToP1Device[
                system.name]
            retroarchConfig['input_libretro_device_p2'] = systemToP2Device[
                system.name]
    # forced values (so that if the config is not correct, fix it)
    if system.config['core'] == 'tgbdual':
        retroarchConfig['aspect_ratio_index'] = str(
            ratioIndexes.index("core"))  # reset each time in this function

    # Virtual keyboard for Amstrad CPC (select+start)
    if system.config['core'] == 'cap32':
        retroarchConfig['cap32_combokey'] = 'y'

    # Netplay management
    if 'netplay.mode' in system.config and system.config[
            'netplay.mode'] in systemNetplayModes:
        # Security : hardcore mode disables save states, which would kill netplay
        retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
        # Quite strangely, host mode requires netplay_mode to be set to false when launched from command line
        retroarchConfig['netplay_mode'] = "false"
        retroarchConfig['netplay_ip_port'] = systemConfig.get(
            'netplay.server.port', "")
        retroarchConfig['netplay_delay_frames'] = systemConfig.get(
            'netplay.frames', "")
        retroarchConfig['netplay_nickname'] = systemConfig.get(
            'netplay.nickname', "")
        retroarchConfig['netplay_client_swap_input'] = "false"
        if system.config['netplay.mode'] == 'client':
            # But client needs netplay_mode = true ... bug ?
            retroarchConfig['netplay_mode'] = "true"
            retroarchConfig['netplay_ip_address'] = systemConfig.get(
                'netplay.server.ip', "")
            retroarchConfig['netplay_client_swap_input'] = "true"
        # mode spectator
        if system.isOptSet('netplay.spectator') and system.getOptBoolean(
                'netplay.spectator') == True:
            retroarchConfig['netplay_spectator_mode_enable'] = 'true'
        else:
            retroarchConfig['netplay_spectator_mode_enable'] = 'false'
        # relay
        if 'netplay.relay' in system.config and system.config[
                'netplay.relay'] != "":
            retroarchConfig['netplay_use_mitm_server'] = "true"
            retroarchConfig['netplay_mitm_server'] = systemConfig.get(
                'netplay.relay', "")
        else:
            retroarchConfig['netplay_use_mitm_server'] = "false"

    # Display FPS
    if system.isOptSet('showFPS') and system.getOptBoolean('showFPS') == True:
        retroarchConfig['fps_show'] = 'true'
    else:
        retroarchConfig['fps_show'] = 'false'

    # adaptation for small resolution
    if isLowResolution(gameResolution):
        retroarchConfig['video_font_size'] = '12'
        retroarchConfig['menu_driver'] = 'rgui'
        retroarchConfig['width'] = gameResolution[
            "width"] * 2  # on low resolution, higher values for width and height makes a nicer image (640x480 on the gpi case)
        retroarchConfig[
            'height'] = gameResolution["height"] * 2  # default value
    else:
        retroarchConfig['video_font_size'] = '32'
        retroarchConfig['menu_driver'] = 'ozone'
        # force the assets directory while it was wrong in some beta versions
        retroarchConfig['assets_directory'] = '/usr/share/libretro/assets'
        retroarchConfig['width'] = gameResolution["width"]  # default value
        retroarchConfig['height'] = gameResolution["height"]  # default value

    # AI service for game translations
    if system.isOptSet('ai_service_enabled') and system.getOptBoolean(
            'ai_service_enabled') == True:
        retroarchConfig['ai_service_enable'] = 'true'
        retroarchConfig['ai_service_mode'] = '0'
        retroarchConfig['ai_service_source_lang'] = '0'
        if system.isOptSet('ai_target_lang'):
            chosen_lang = system.config['ai_target_lang']
        else:
            chosen_lang = 'En'
        if system.isOptSet(
                'ai_service_url') and system.config['ai_service_url']:
            retroarchConfig['ai_service_url'] = system.config[
                'ai_service_url'] + '&mode=Fast&output=png&target_lang=' + chosen_lang
        else:
            retroarchConfig[
                'ai_service_url'] = 'http://ztranslate.net/service?api_key=BATOCERA&mode=Fast&output=png&target_lang=' + chosen_lang
        if system.isOptSet('ai_service_pause') and system.getOptBoolean(
                'ai_service_pause') == True:
            retroarchConfig['ai_service_pause'] = 'true'
        else:
            retroarchConfig['ai_service_pause'] = 'false'
    else:
        retroarchConfig['ai_service_enable'] = 'false'

    # bezel
    if system.isOptSet('bezel_stretch') and system.getOptBoolean(
            'bezel_stretch') == True:
        bezel_stretch = True
    else:
        bezel_stretch = False
    try:
        writeBezelConfig(bezel, retroarchConfig, system.name, rom,
                         gameResolution, bezel_stretch)
    except:
        # error with bezels, disabling them
        writeBezelConfig(None, retroarchConfig, system.name, rom,
                         gameResolution, bezel_stretch)

    # custom : allow the user to configure directly retroarch.cfg via batocera.conf via lines like : snes.retroarch.menu_driver=rgui
    for user_config in systemConfig:
        if user_config[:10] == "retroarch.":
            retroarchConfig[user_config[10:]] = systemConfig[user_config]

    return retroarchConfig
Exemple #17
0
def writeBezelConfig(bezel, retroarchConfig, systemName, rom, gameResolution,
                     bezel_stretch):
    # disable the overlay
    # if all steps are passed, enable them
    retroarchConfig['input_overlay_hide_in_menu'] = "false"
    overlay_cfg_file = batoceraFiles.overlayConfigFile

    # bezel are disabled
    # default values in case something wrong append
    retroarchConfig['input_overlay_enable'] = "false"
    retroarchConfig['video_message_pos_x'] = 0.05
    retroarchConfig['video_message_pos_y'] = 0.05

    if bezel is None:
        return

    # by order choose :
    # rom name in the system subfolder of the user directory (gb/mario.png)
    # rom name in the system subfolder of the system directory (gb/mario.png)
    # rom name in the user directory (mario.png)
    # rom name in the system directory (mario.png)
    # system name in the user directory (gb.png)
    # system name in the system directory (gb.png)
    # default name (default.png)
    # else return
    romBase = os.path.splitext(
        os.path.basename(rom))[0]  # filename without extension
    overlay_info_file = batoceraFiles.overlayUser + "/" + bezel + "/games/" + systemName + "/" + romBase + ".info"
    overlay_png_file = batoceraFiles.overlayUser + "/" + bezel + "/games/" + systemName + "/" + romBase + ".png"
    bezel_game = True
    if not os.path.exists(overlay_png_file):
        overlay_info_file = batoceraFiles.overlaySystem + "/" + bezel + "/games/" + systemName + "/" + romBase + ".info"
        overlay_png_file = batoceraFiles.overlaySystem + "/" + bezel + "/games/" + systemName + "/" + romBase + ".png"
        bezel_game = True
        if not os.path.exists(overlay_png_file):
            overlay_info_file = batoceraFiles.overlayUser + "/" + bezel + "/games/" + romBase + ".info"
            overlay_png_file = batoceraFiles.overlayUser + "/" + bezel + "/games/" + romBase + ".png"
            bezel_game = True
            if not os.path.exists(overlay_png_file):
                overlay_info_file = batoceraFiles.overlaySystem + "/" + bezel + "/games/" + romBase + ".info"
                overlay_png_file = batoceraFiles.overlaySystem + "/" + bezel + "/games/" + romBase + ".png"
                bezel_game = True
                if not os.path.exists(overlay_png_file):
                    overlay_info_file = batoceraFiles.overlayUser + "/" + bezel + "/systems/" + systemName + ".info"
                    overlay_png_file = batoceraFiles.overlayUser + "/" + bezel + "/systems/" + systemName + ".png"
                    bezel_game = False
                    if not os.path.exists(overlay_png_file):
                        overlay_info_file = batoceraFiles.overlaySystem + "/" + bezel + "/systems/" + systemName + ".info"
                        overlay_png_file = batoceraFiles.overlaySystem + "/" + bezel + "/systems/" + systemName + ".png"
                        bezel_game = False
                        if not os.path.exists(overlay_png_file):
                            overlay_info_file = batoceraFiles.overlayUser + "/" + bezel + "/default.info"
                            overlay_png_file = batoceraFiles.overlayUser + "/" + bezel + "/default.png"
                            bezel_game = True
                            if not os.path.exists(overlay_png_file):
                                overlay_info_file = batoceraFiles.overlaySystem + "/" + bezel + "/default.info"
                                overlay_png_file = batoceraFiles.overlaySystem + "/" + bezel + "/default.png"
                                bezel_game = True
                                if not os.path.exists(overlay_png_file):
                                    return

    # only the png file is mandatory
    if os.path.exists(overlay_info_file):
        try:
            infos = json.load(open(overlay_info_file))
        except:
            infos = {}
    else:
        infos = {}

    # if image is not at the correct size, find the correct size
    bezelNeedAdaptation = False
    viewPortUsed = True
    if "width" not in infos or "height" not in infos or "top" not in infos or "left" not in infos or "bottom" not in infos or "right" not in infos:
        viewPortUsed = False

    gameRatio = float(gameResolution["width"]) / float(
        gameResolution["height"])

    if viewPortUsed:
        if gameResolution["width"] != infos["width"] or gameResolution[
                "height"] != infos["height"]:
            infosRatio = float(infos["width"]) / float(infos["height"])
            if gameRatio < infosRatio - 0.1:  # keep a margin
                return
            else:
                bezelNeedAdaptation = True
        retroarchConfig['aspect_ratio_index'] = str(
            ratioIndexes.index(
                "custom"))  # overwritten from the beginning of this file
    else:
        # when there is no information about width and height in the .info, assume that the tv is HD 16/9 and infos are core provided
        infosRatio = 1920.0 / 1080.0
        if gameRatio < infosRatio - 0.1:  # keep a margin
            return
        else:
            # No info on the bezel, let's get the bezel image width and height and apply the
            # ratios from usual 16:9 1920x1080 bezels (example: theBezelProject)
            try:
                infos["width"], infos["height"] = fast_image_size(
                    overlay_png_file)
                infos["top"] = int(infos["height"] * 2 / 1080)
                infos["left"] = int(
                    infos["width"] * 241 / 1920
                )  # 241 = (1920 - (1920 / (4:3))) / 2 + 1 pixel = where viewport start
                infos["bottom"] = int(infos["height"] * 2 / 1080)
                infos["right"] = int(infos["width"] * 241 / 1920)
                bezelNeedAdaptation = True
            except:
                pass  # outch, no ratio will be applied.
        retroarchConfig['aspect_ratio_index'] = str(
            ratioIndexes.index(
                "custom"))  # overwritten from the beginning of this file

    retroarchConfig['input_overlay_enable'] = "true"
    retroarchConfig['input_overlay_scale'] = "1.0"
    retroarchConfig['input_overlay'] = overlay_cfg_file
    retroarchConfig['input_overlay_hide_in_menu'] = "true"

    if "opacity" not in infos:
        infos["opacity"] = 1.0
    if "messagex" not in infos:
        infos["messagex"] = 0.0
    if "messagey" not in infos:
        infos["messagey"] = 0.0

    retroarchConfig['input_overlay_opacity'] = infos["opacity"]

    if bezelNeedAdaptation:
        wratio = gameResolution["width"] / float(infos["width"])
        hratio = gameResolution["height"] / float(infos["height"])

        # If width or height < original, can't add black borders, need to stretch
        if gameResolution["width"] < infos["width"] or gameResolution[
                "height"] < infos["height"]:
            bezel_stretch = True

        if bezel_stretch:
            retroarchConfig['custom_viewport_x'] = infos["left"] * wratio
            retroarchConfig['custom_viewport_y'] = infos["top"] * hratio
            retroarchConfig['custom_viewport_width'] = (
                infos["width"] - infos["left"] - infos["right"]) * wratio
            retroarchConfig['custom_viewport_height'] = (
                infos["height"] - infos["top"] - infos["bottom"]) * hratio
            retroarchConfig['video_message_pos_x'] = infos["messagex"] * wratio
            retroarchConfig['video_message_pos_y'] = infos["messagey"] * hratio
        else:
            if bezel_game is True:
                output_png_file = "/tmp/bezel_game_adapted.png"
                create_new_bezel_file = True
            else:
                create_new_bezel_file = False
                output_png_file = "/tmp/" + os.path.splitext(
                    os.path.basename(overlay_png_file))[0] + "_adapted.png"
                if os.path.exists(output_png_file) is False:
                    create_new_bezel_file = True
                else:
                    if os.path.getmtime(output_png_file) < os.path.getmtime(
                            overlay_png_file):
                        create_new_bezel_file = True
            # fast way of checking the size of a png
            oldwidth, oldheight = fast_image_size(output_png_file)
            if (oldwidth != gameResolution["width"]
                    or oldheight != gameResolution["height"]):
                create_new_bezel_file = True

            xoffset = gameResolution["width"] - infos["width"]
            yoffset = gameResolution["height"] - infos["height"]
            retroarchConfig['custom_viewport_x'] = infos["left"] + xoffset / 2
            retroarchConfig['custom_viewport_y'] = infos["top"] + yoffset / 2
            retroarchConfig['custom_viewport_width'] = infos["width"] - infos[
                "left"] - infos["right"]
            retroarchConfig['custom_viewport_height'] = infos[
                "height"] - infos["top"] - infos["bottom"]
            retroarchConfig[
                'video_message_pos_x'] = infos["messagex"] + xoffset / 2
            retroarchConfig[
                'video_message_pos_y'] = infos["messagey"] + yoffset / 2

            if create_new_bezel_file is True:
                # Padding left and right borders for ultrawide screens (larger than 16:9 aspect ratio)
                # or up/down for 4K
                eslog.log("Generating a new adapted bezel file {}".format(
                    output_png_file))
                fillcolor = 'black'

                borderw = 0
                borderh = 0
                if wratio > 1:
                    borderw = xoffset / 2
                if hratio > 1:
                    borderh = yoffset / 2
                imgin = Image.open(overlay_png_file)
                if imgin.mode != "RGBA":
                    # TheBezelProject have Palette + alpha, not RGBA. PIL can't convert from P+A to RGBA.
                    # Even if it can load P+A, it can't save P+A as PNG. So we have to recreate a new image to adapt it.
                    if not 'transparency' in imgin.info:
                        return  # no transparent layer for the viewport, abort
                    alpha = imgin.split()[
                        -1]  # alpha from original palette + alpha
                    ix, iy = imgin.size
                    imgnew = Image.new("RGBA", (ix, iy), (0, 0, 0, 255))
                    imgnew.paste(alpha, (0, 0, ix, iy))
                    imgout = ImageOps.expand(imgnew,
                                             border=(borderw, borderh,
                                                     xoffset - borderw,
                                                     yoffset - borderh),
                                             fill=fillcolor)
                    imgout.save(output_png_file, mode="RGBA", format="PNG")
                else:
                    imgout = ImageOps.expand(imgin,
                                             border=(borderw, borderh,
                                                     xoffset - borderw,
                                                     yoffset - borderh),
                                             fill=fillcolor)
                    imgout.save(output_png_file, mode="RGBA", format="PNG")
            overlay_png_file = output_png_file  # replace by the new file (recreated or cached in /tmp)
    else:
        if viewPortUsed:
            retroarchConfig['custom_viewport_x'] = infos["left"]
            retroarchConfig['custom_viewport_y'] = infos["top"]
            retroarchConfig['custom_viewport_width'] = infos["width"] - infos[
                "left"] - infos["right"]
            retroarchConfig['custom_viewport_height'] = infos[
                "height"] - infos["top"] - infos["bottom"]
        retroarchConfig['video_message_pos_x'] = infos["messagex"]
        retroarchConfig['video_message_pos_y'] = infos["messagey"]

    eslog.log("Bezel file set to {}".format(overlay_png_file))
    writeBezelCfgConfig(overlay_cfg_file, overlay_png_file)
Exemple #18
0
    def __prepare(system, emulator, core, rom, playersControllers):
        # consider files here in this order to get a configuration
        for keysfile in [
                "{}.keys".format(rom),
                "{}/padto.keys".format(
                    rom),  # case when the rom is a directory
                #"/userdata/system/configs/evmapy/{}.{}.{}.keys" .format (system, emulator, core),
                #"/userdata/system/configs/evmapy/{}.{}.keys" .format (system, emulator),
                "/userdata/system/configs/evmapy/{}.keys".format(system),
                #"/usr/share/evmapy/{}.{}.{}.keys" .format (system, emulator, core),
                "/usr/share/evmapy/{}.{}.keys".format(system, emulator),
                "/usr/share/evmapy/{}.keys".format(system)
        ]:
            if os.path.exists(keysfile) and not (
                    os.path.isdir(rom) and keysfile == "{}.keys".format(rom)
            ):  # "{}.keys" .format (rom) is forbidden for directories, it must be inside
                eslog.log("evmapy on {}".format(keysfile))
                subprocess.call(["batocera-evmapy", "clear"])

                padActionConfig = json.load(open(keysfile))

                # configure each player
                nplayer = 1
                for playercontroller, pad in sorted(
                        playersControllers.items()):
                    if "actions_player" + str(nplayer) in padActionConfig:
                        configfile = "/var/run/evmapy/{}.json".format(
                            os.path.basename(pad.dev))
                        eslog.log(
                            "config file for keysfile is {} (from {})".format(
                                configfile, keysfile))

                        # create mapping
                        padConfig = {}
                        padConfig["axes"] = []
                        padConfig["buttons"] = []
                        padConfig["grab"] = False
                        absbasex_positive = True
                        absbasey_positive = True

                        # define buttons / axes
                        known_buttons_names = {}
                        known_buttons_codes = {}
                        known_buttons_alias = {}
                        for index in pad.inputs:
                            input = pad.inputs[index]
                            if input.type == "button":
                                # don't add 2 times the same button (ie select as hotkey)
                                if input.code is not None:
                                    if input.code not in known_buttons_codes:
                                        known_buttons_names[input.name] = True
                                        known_buttons_codes[
                                            input.
                                            code] = input.name  # keep the master name for aliases
                                        padConfig["buttons"].append({
                                            "name":
                                            input.name,
                                            "code":
                                            int(input.code)
                                        })
                                    else:
                                        known_buttons_alias[
                                            input.name] = known_buttons_codes[
                                                input.code]
                            elif input.type == "hat":
                                if int(input.value) in [
                                        1, 2
                                ]:  # don't duplicate values
                                    if int(input.value) == 1:
                                        name = "X"
                                        isYAsInt = 0
                                    else:
                                        name = "Y"
                                        isYAsInt = 1
                                    known_buttons_names["HAT" + input.id +
                                                        name + ":min"] = True
                                    known_buttons_names["HAT" + input.id +
                                                        name + ":max"] = True
                                    padConfig["axes"].append({
                                        "name":
                                        "HAT" + input.id + name,
                                        "code":
                                        int(input.id) + 16 +
                                        isYAsInt,  # 16 = HAT0X in linux/input.h
                                        "min":
                                        -1,
                                        "max":
                                        1
                                    })
                            elif input.type == "axis":
                                axisId = None
                                axisName = None
                                if input.name == "joystick1up" or input.name == "joystick1left":
                                    axisId = "0"
                                elif input.name == "joystick2up" or input.name == "joystick2left":
                                    axisId = "1"
                                if input.name == "joystick1up" or input.name == "joystick2up":
                                    axisName = "Y"
                                elif input.name == "joystick1left" or input.name == "joystick2left":
                                    axisName = "X"
                                elif input.name == "up":
                                    axisId = "BASE"
                                    axisName = "Y"
                                    absbasey_positive = int(input.value) >= 0
                                elif input.name == "left":
                                    axisId = "BASE"
                                    axisName = "X"
                                    absbasex_positive = int(input.value) >= 0
                                else:
                                    axisId = "_OTHERS_"
                                    axisName = input.name

                                if ((axisId in ["0", "1", "BASE"] and axisName
                                     in ["X", "Y"]) or axisId == "_OTHERS_"
                                    ) and input.code is not None:
                                    axisMin, axisMax = Evmapy.__getPadMinMaxAxis(
                                        pad.dev, int(input.code))
                                    known_buttons_names["ABS" + axisId +
                                                        axisName +
                                                        ":min"] = True
                                    known_buttons_names["ABS" + axisId +
                                                        axisName +
                                                        ":max"] = True
                                    known_buttons_names["ABS" + axisId +
                                                        axisName +
                                                        ":val"] = True

                                    padConfig["axes"].append({
                                        "name":
                                        "ABS" + axisId + axisName,
                                        "code":
                                        int(input.code),
                                        "min":
                                        axisMin,
                                        "max":
                                        axisMax
                                    })

                        # only add actions for which buttons are defined (otherwise, evmapy doesn't like it)
                        padActionsPreDefined = padActionConfig["actions_player"
                                                               + str(nplayer)]
                        padActionsFiltered = []

                        # handle mouse events : only joystick1 or joystick2 defined for 2 events
                        padActionsDefined = []
                        for action in padActionsPreDefined:
                            if "type" in action and action[
                                    "type"] == "mouse" and "target" not in action and "trigger" in action:
                                if action["trigger"] == "joystick1":
                                    newaction = action.copy()
                                    newaction["trigger"] = "joystick1x"
                                    newaction["target"] = 'X'
                                    padActionsDefined.append(newaction)
                                    newaction = action.copy()
                                    newaction["trigger"] = "joystick1y"
                                    newaction["target"] = 'Y'
                                    padActionsDefined.append(newaction)
                                elif action["trigger"] == "joystick2":
                                    newaction = action.copy()
                                    newaction["trigger"] = "joystick2x"
                                    newaction["target"] = 'X'
                                    padActionsDefined.append(newaction)
                                    newaction = action.copy()
                                    newaction["trigger"] = "joystick2y"
                                    newaction["target"] = 'Y'
                                    padActionsDefined.append(newaction)
                            else:
                                padActionsDefined.append(action)

                        # define actions
                        for action in padActionsDefined:
                            if "trigger" in action:
                                trigger = Evmapy.__trigger_mapper(
                                    action["trigger"], known_buttons_alias,
                                    known_buttons_names, absbasex_positive,
                                    absbasey_positive)
                                if "mode" not in action:
                                    mode = Evmapy.__trigger_mapper_mode(
                                        action["trigger"])
                                    if mode != None:
                                        action["mode"] = mode
                                action["trigger"] = trigger
                                if isinstance(trigger, list):
                                    allfound = True
                                    for x in trigger:
                                        if x not in known_buttons_names and (
                                                "ABS_OTHERS_" + x + ":max"
                                        ) not in known_buttons_names:
                                            allfound = False
                                    if allfound:
                                        # rewrite axis buttons
                                        x = 0
                                        for val in trigger:
                                            if "ABS_OTHERS_" + val + ":max" in known_buttons_names:
                                                action["trigger"][
                                                    x] = "ABS_OTHERS_" + val + ":max"
                                            x = x + 1
                                        padActionsFiltered.append(action)
                                else:
                                    if trigger in known_buttons_names:
                                        padActionsFiltered.append(action)
                                    if "ABS_OTHERS_" + trigger + ":max" in known_buttons_names:
                                        action[
                                            "trigger"] = "ABS_OTHERS_" + action[
                                                "trigger"] + ":max"
                                        padActionsFiltered.append(action)
                                padConfig["actions"] = padActionsFiltered

                        # remove comments
                        for action in padConfig["actions"]:
                            if "description" in action:
                                del action["description"]

                        # use full axis for mouse and 50% for keys
                        axis_for_mouse = {}
                        for action in padConfig["actions"]:
                            if "type" in action and action["type"] == "mouse":
                                if isinstance(action["trigger"], list):
                                    for x in action["trigger"]:
                                        axis_for_mouse[x] = True
                                else:
                                    axis_for_mouse[action["trigger"]] = True

                        for axis in padConfig["axes"]:
                            if axis["name"] + ":val" not in axis_for_mouse and axis[
                                    "name"] + ":min" not in axis_for_mouse and axis[
                                        "name"] + ":max" not in axis_for_mouse:
                                min, max = Evmapy.__getPadMinMaxAxisForKeys(
                                    axis["min"], axis["max"])
                                axis["min"] = min
                                axis["max"] = max

                        # save config file
                        with open(configfile, "w") as fd:
                            fd.write(json.dumps(padConfig, indent=4))

                    nplayer += 1
                return True
        # otherwise, preparation did nothing
        return False
Exemple #19
0
    def generate(self, system, rom, playersControllers, gameResolution):
        retroconfig = UnixSettings(batoceraFiles.amiberryRetroarchCustom, separator=' ')
        if not os.path.exists(dirname(batoceraFiles.amiberryRetroarchCustom)):
            os.makedirs(dirname(batoceraFiles.amiberryRetroarchCustom))
        
        romType = self.getRomType(rom)
        eslog.log("romType"+romType)
        if romType != 'UNKNOWN' :           
            commandArray = [ batoceraFiles.batoceraBins[system.config['emulator']], "-G" ]
            if romType != 'WHDL' :
                commandArray.append("-model=" + system.config['core'])
            
            if romType == 'WHDL' :
                commandArray.append("-autoload="+rom)
            elif romType == 'HDF' :
                commandArray.append("-s")
                commandArray.append("hardfile2=rw,DH0:"+rom+",32,1,2,512,0,,uae0")
                commandArray.append("-s")
                commandArray.append("uaehf0=hdf,rw,DH0:"+rom+",32,1,2,512,0,,uae0")
            elif romType == 'CD' :
                commandArray.append("-cdimage="+rom)
            elif romType == 'DISK':
                # floppies
                n = 0
                for img in self.floppiesFromRom(rom):
                    if n < 4:
                        commandArray.append("-" + str(n))
                        commandArray.append(img)
                    n += 1
                # floppy path
                commandArray.append("-s")
                # Use disk folder as floppy path
                romPathIndex = rom.rfind('/')
                commandArray.append("amiberry.floppy_path="+rom[0:romPathIndex])

            # controller
            libretroControllers.writeControllersConfig(retroconfig, system, playersControllers)

            if not os.path.exists(batoceraFiles.amiberryRetroarchInputsDir):
                os.makedirs(batoceraFiles.amiberryRetroarchInputsDir)
            nplayer = 1
            for playercontroller, pad in sorted(playersControllers.items()):
                replacements = {'_player' + str(nplayer) + '_':'_'}
                # amiberry remove / included in pads names like "USB Downlo01.80 PS3/USB Corded Gamepad"
                padfilename = pad.realName.replace("/", "")
                playerInputFilename = batoceraFiles.amiberryRetroarchInputsDir + "/" + padfilename + ".cfg"
                with open(batoceraFiles.amiberryRetroarchCustom) as infile, open(playerInputFilename, 'w') as outfile:
                    for line in infile:
                        for src, target in replacements.iteritems():
                            newline = line.replace(src, target)
                            if not newline.isspace():
                                outfile.write(newline)
                if nplayer == 1: # 1 = joystick port
                    commandArray.append("-s")
                    commandArray.append("joyport1_friendlyname=" + padfilename)
                    if romType == 'CD' :
                        commandArray.append("-s")
                        commandArray.append("joyport1_mode=cd32joy")
                if nplayer == 2: # 0 = mouse for the player 2
                    commandArray.append("-s")
                    commandArray.append("joyport0_friendlyname=" + padfilename)
                nplayer += 1

            # fps
            if system.config['showFPS'] == 'true':
                commandArray.append("-s")
                commandArray.append("show_leds=true")

            # disable port 2 (otherwise, the joystick goes on it)
            commandArray.append("-s")
            commandArray.append("joyport2=")

            # display vertical centering
            commandArray.append("-s")
            commandArray.append("gfx_center_vertical=smart")

            os.chdir("/usr/share/amiberry")
            return Command.Command(array=commandArray)
def main(args, maxnbplayers):
    playersControllers = dict()

    controllersInput = []
    for p in range(1, maxnbplayers + 1):
        ci = {}
        ci["index"] = getattr(args, "p{}index".format(p))
        ci["guid"] = getattr(args, "p{}guid".format(p))
        ci["name"] = getattr(args, "p{}name".format(p))
        ci["devicepath"] = getattr(args, "p{}devicepath".format(p))
        ci["nbbuttons"] = getattr(args, "p{}nbbuttons".format(p))
        ci["nbhats"] = getattr(args, "p{}nbhats".format(p))
        ci["nbaxes"] = getattr(args, "p{}nbaxes".format(p))
        controllersInput.append(ci)

    # Read the controller configuration
    playersControllers = controllers.loadControllerConfig(controllersInput)
    # find the system to run
    systemName = args.system
    eslog.log("Running system: {}".format(systemName))
    system = Emulator(systemName, args.rom)

    if args.emulator is not None:
        system.config["emulator"] = args.emulator
        system.config["emulator-forced"] = True
    if args.core is not None:
        system.config["core"] = args.core
        system.config["core-forced"] = True
    debugDisplay = system.config.copy()
    if "retroachievements.password" in debugDisplay:
        debugDisplay["retroachievements.password"] = "******"
    eslog.debug("Settings: {}".format(debugDisplay))
    if "emulator" in system.config and "core" in system.config:
        eslog.log("emulator: {}, core: {}".format(system.config["emulator"],
                                                  system.config["core"]))
    else:
        if "emulator" in system.config:
            eslog.log("emulator: {}".format(system.config["emulator"]))

    # the resolution must be changed before configuration while the configuration may depend on it (ie bezels)
    wantedGameMode = generators[system.config['emulator']].getResolutionMode(
        system.config)
    systemMode = videoMode.getCurrentMode()

    resolutionChanged = False
    mouseChanged = False
    exitCode = -1
    try:
        # lower the resolution if mode is auto
        newsystemMode = systemMode  # newsystemmode is the mode after minmax (ie in 1K if tv was in 4K), systemmode is the mode before (ie in es)
        if system.config["videomode"] == "" or system.config[
                "videomode"] == "default":
            eslog.log("minTomaxResolution")
            eslog.log("video mode before minmax: {}".format(systemMode))
            videoMode.minTomaxResolution()
            newsystemMode = videoMode.getCurrentMode()
            if newsystemMode != systemMode:
                resolutionChanged = True

        eslog.log("current video mode: {}".format(newsystemMode))
        eslog.log("wanted video mode: {}".format(wantedGameMode))

        if wantedGameMode != 'default' and wantedGameMode != newsystemMode:
            videoMode.changeMode(wantedGameMode)
            resolutionChanged = True
        gameResolution = videoMode.getCurrentResolution()

        # if resolution is reversed (ie ogoa boards), reverse it in the gameResolution to have it correct
        if system.isOptSet('resolutionIsReversed') and system.getOptBoolean(
                'resolutionIsReversed') == True:
            x = gameResolution["width"]
            gameResolution["width"] = gameResolution["height"]
            gameResolution["height"] = x
        eslog.log("resolution: {}x{}".format(str(gameResolution["width"]),
                                             str(gameResolution["height"])))

        # savedir: create the save directory if not already done
        dirname = os.path.join(batoceraFiles.savesDir, system.name)
        if not os.path.exists(dirname):
            os.makedirs(dirname)

        # core
        effectiveCore = ""
        if "core" in system.config and system.config["core"] is not None:
            effectiveCore = system.config["core"]
        effectiveRom = ""
        if args.rom is not None:
            effectiveRom = args.rom

        # network options
        if args.netplaymode is not None:
            system.config["netplay.mode"] = args.netplaymode
        if args.netplaypass is not None:
            system.config["netplay.password"] = args.netplaypass
        if args.netplayip is not None:
            system.config["netplay.server.ip"] = args.netplayip
        if args.netplayport is not None:
            system.config["netplay.server.port"] = args.netplayport

        # autosave arguments
        if args.state_slot is not None:
            system.config["state_slot"] = args.state_slot
        if args.autosave is not None:
            system.config["autosave"] = args.autosave

        if generators[system.config['emulator']].getMouseMode(system.config):
            mouseChanged = True
            videoMode.changeMouse(True)

        # run a script before emulator starts
        callExternalScripts("/usr/share/batocera/configgen/scripts",
                            "gameStart", [
                                systemName, system.config['emulator'],
                                effectiveCore, effectiveRom
                            ])
        callExternalScripts("/userdata/system/scripts", "gameStart", [
            systemName, system.config['emulator'], effectiveCore, effectiveRom
        ])

        # run the emulator
        try:
            Evmapy.start(systemName, system.config['emulator'], effectiveCore,
                         effectiveRom, playersControllers)
            exitCode = runCommand(
                generators[system.config['emulator']].generate(
                    system, args.rom, playersControllers, gameResolution))
        finally:
            Evmapy.stop()

        # run a script after emulator shuts down
        callExternalScripts("/userdata/system/scripts", "gameStop", [
            systemName, system.config['emulator'], effectiveCore, effectiveRom
        ])
        callExternalScripts("/usr/share/batocera/configgen/scripts",
                            "gameStop", [
                                systemName, system.config['emulator'],
                                effectiveCore, effectiveRom
                            ])

    finally:
        # always restore the resolution
        if resolutionChanged:
            try:
                videoMode.changeMode(systemMode)
            except Exception:
                pass  # don't fail

        if mouseChanged:
            try:
                videoMode.changeMouse(False)
            except Exception:
                pass  # don't fail

    # exit
    return exitCode
    def generate(self, system, rom, playersControllers, gameResolution):

        # basis
        commandArray = [
            "solarus-run", "-fullscreen=yes", "-cursor-visible=no",
            "-lua-console=no"
        ]

        # hotkey to exit
        nplayer = 1
        for playercontroller, pad in sorted(playersControllers.items()):
            if nplayer == 1:
                if "hotkey" in pad.inputs and "start" in pad.inputs:
                    commandArray.append("-quit-combo={}+{}".format(
                        pad.inputs["hotkey"].id, pad.inputs["start"].id))
                    commandArray.append("-joypad-num={}".format(pad.index))
            nplayer += 1

        # player pad
        SolarusGenerator.padConfig(system, playersControllers)

        # saves (for first run, needs init on RPi4 at least)
        romName = os.path.basename(rom)
        try:
            with zipfile.ZipFile(rom, 'r') as zip:
                zip.extract('quest.dat', '/tmp')
                eslog.log("Extracting {}".format(romName))
        except:
            eslog.log("Failing {} extraction".format(romName))
            return
        qst = dict()
        quest = open('/tmp/quest.dat', 'r')
        qlines = quest.readlines()
        for l in qlines:
            try:
                row = l.strip().split("=")
                qst[row[0].strip()] = row[1].strip('", ')
            except:
                continue
        quest.close()
        try:
            folder = qst['write_dir']
        except:
            folder = ''
        cfg = batoceraFiles.solarusSaves + '/{}'.format(folder)
        eslog.log("Solarus save folder: {}".format(cfg))
        try:
            os.makedirs(cfg)
        except:
            pass  # save folder already exists
        par = dict()
        try:
            settings = open(cfg + '/settings.dat', 'r+')
            try:
                slines = settings.readlines()
                for l in slines:
                    try:
                        row = l.strip().split("=")
                        par[row[0].strip()] = row[1].strip()
                    except:
                        continue
            except:
                pass
        except:
            settings = open(cfg + '/settings.dat', 'w')
        if not 'fullscreen' in par.keys():
            eslog.log(
                "Initializing solarus settings in {}".format(cfg +
                                                             '/settings.dat'))
            settings.write("fullscreen = true")
        settings.close()

        # rom
        commandArray.append(rom)

        return Command.Command(array=commandArray,
                               env={'SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS': '0'})
Exemple #22
0
def createLibretroConfig(system, controllers, rom, bezel, gameResolution):
    # Create/update retroarch-core-options.cfg
    libretroOptions.generateCoreSettings(batoceraFiles.retroarchCoreCustom,
                                         system)

    # Create/update hatari.cfg
    if system.name == 'atarist':
        libretroOptions.generateHatariConf(batoceraFiles.hatariConf)

    retroarchConfig = dict()
    systemConfig = system.config
    renderConfig = system.renderconfig

    # fs is required at least for x86* and odroidn2
    retroarchConfig['video_fullscreen'] = 'true'

    if system.isOptSet('smooth') and system.getOptBoolean('smooth') == True:
        retroarchConfig['video_smooth'] = 'true'
    else:
        retroarchConfig['video_smooth'] = 'false'

    if 'shader' in renderConfig and renderConfig['shader'] != None:
        retroarchConfig['video_shader_enable'] = 'true'
        retroarchConfig['video_smooth'] = 'false'
        shaderFilename = renderConfig['shader'] + ".glslp"

        eslog.log("searching shader {}".format(shaderFilename))
        if os.path.exists("/userdata/shaders/" + shaderFilename):
            retroarchConfig['video_shader_dir'] = "/userdata/shaders"
            eslog.log(
                "shader {} found in /userdata/shaders".format(shaderFilename))
        else:
            retroarchConfig['video_shader_dir'] = "/usr/share/batocera/shaders"

        retroarchConfig['video_shader'] = retroarchConfig[
            'video_shader_dir'] + "/" + shaderFilename
    else:
        retroarchConfig['video_shader_enable'] = 'false'

    retroarchConfig[
        'aspect_ratio_index'] = ''  # reset in case config was changed (or for overlays)
    if defined('ratio', systemConfig):
        if systemConfig['ratio'] in ratioIndexes:
            retroarchConfig['aspect_ratio_index'] = ratioIndexes.index(
                systemConfig['ratio'])
            retroarchConfig['video_aspect_ratio_auto'] = 'false'
        elif systemConfig['ratio'] == "custom":
            retroarchConfig['video_aspect_ratio_auto'] = 'false'
        else:
            retroarchConfig['video_aspect_ratio_auto'] = 'true'
            retroarchConfig['aspect_ratio_index'] = ''

    retroarchConfig['rewind_enable'] = 'false'

    if system.isOptSet('rewind') and system.getOptBoolean('rewind') == True:
        if (not system.name in systemNoRewind):
            retroarchConfig['rewind_enable'] = 'true'
    else:
        retroarchConfig['rewind_enable'] = 'false'

    if system.isOptSet('autosave') and system.getOptBoolean(
            'autosave') == True:
        retroarchConfig['savestate_auto_save'] = 'true'
        retroarchConfig['savestate_auto_load'] = 'true'
    else:
        retroarchConfig['savestate_auto_save'] = 'false'
        retroarchConfig['savestate_auto_load'] = 'false'

    retroarchConfig['input_joypad_driver'] = 'udev'

    retroarchConfig[
        'savestate_directory'] = batoceraFiles.savesDir + system.name
    retroarchConfig[
        'savefile_directory'] = batoceraFiles.savesDir + system.name

    retroarchConfig['input_libretro_device_p1'] = '1'
    retroarchConfig['input_libretro_device_p2'] = '1'

    if (system.config['core'] in coreToP1Device):
        retroarchConfig['input_libretro_device_p1'] = coreToP1Device[
            system.config['core']]

    if (system.config['core'] in coreToP2Device):
        retroarchConfig['input_libretro_device_p2'] = coreToP2Device[
            system.config['core']]

    if len(controllers) > 2 and (system.config['core'] == 'snes9x_next'
                                 or system.config['core'] == 'snes9x'):
        retroarchConfig['input_libretro_device_p2'] = '257'

    if system.config['core'] == 'atari800':
        retroarchConfig['input_libretro_device_p1'] = '513'
        retroarchConfig['input_libretro_device_p2'] = '513'

    retroarchConfig['cheevos_enable'] = 'false'
    retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
    retroarchConfig['cheevos_leaderboards_enable'] = 'false'
    retroarchConfig['cheevos_verbose_enable'] = 'false'
    retroarchConfig['cheevos_auto_screenshot'] = 'false'

    if system.isOptSet('retroachievements') and system.getOptBoolean(
            'retroachievements') == True:
        if (system.name in systemToRetroachievements):
            retroarchConfig['cheevos_enable'] = 'true'
            retroarchConfig['cheevos_username'] = systemConfig.get(
                'retroachievements.username', "")
            retroarchConfig['cheevos_password'] = systemConfig.get(
                'retroachievements.password', "")
            # retroachievements_hardcore_mode
            if system.isOptSet(
                    'retroachievements.hardcore') and system.getOptBoolean(
                        'retroachievements.hardcore') == True:
                retroarchConfig['cheevos_hardcore_mode_enable'] = 'true'
            else:
                retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
            # retroachievements_leaderboards
            if system.isOptSet(
                    'retroachievements.leaderboards') and system.getOptBoolean(
                        'retroachievements.leaderboards') == True:
                retroarchConfig['cheevos_leaderboards_enable'] = 'true'
            else:
                retroarchConfig['cheevos_leaderboards_enable'] = 'false'
            # retroachievements_verbose_mode
            if system.isOptSet(
                    'retroachievements.verbose') and system.getOptBoolean(
                        'retroachievements.verbose') == True:
                retroarchConfig['cheevos_verbose_enable'] = 'true'
            else:
                retroarchConfig['cheevos_verbose_enable'] = 'false'
            # retroachievements_automatic_screenshot
            if system.isOptSet(
                    'retroachievements.screenshot') and system.getOptBoolean(
                        'retroachievements.screenshot') == True:
                retroarchConfig['cheevos_auto_screenshot'] = 'true'
            else:
                retroarchConfig['cheevos_auto_screenshot'] = 'false'
    else:
        retroarchConfig['cheevos_enable'] = 'false'

    if system.isOptSet('integerscale') and system.getOptBoolean(
            'integerscale') == True:
        retroarchConfig['video_scale_integer'] = 'true'
    else:
        retroarchConfig['video_scale_integer'] = 'false'

    # disable the threaded video while it is causing issues to several people ?
    # this must be set to true on xu4 for performance issues
    if system.config['video_threaded']:
        retroarchConfig['video_threaded'] = 'true'
    else:
        retroarchConfig['video_threaded'] = 'false'

    # core options
    if (system.name in systemToBluemsx):
        if system.config['core'] == 'bluemsx':
            retroarchConfig['input_libretro_device_p1'] = systemToP1Device[
                system.name]
            retroarchConfig['input_libretro_device_p2'] = systemToP2Device[
                system.name]
    # forced values (so that if the config is not correct, fix it)
    if system.config['core'] == 'tgbdual':
        retroarchConfig['aspect_ratio_index'] = str(
            ratioIndexes.index("core"))  # reset each time in this function

    # Netplay management
    if 'netplaymode' in system.config and system.config[
            'netplaymode'] in systemNetplayModes:
        # Security : hardcore mode disables save states, which would kill netplay
        retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
        # Quite strangely, host mode requires netplay_mode to be set to false when launched from command line
        retroarchConfig['netplay_mode'] = "false"
        retroarchConfig['netplay_ip_port'] = systemConfig.get(
            'netplay.server.port', "")
        retroarchConfig['netplay_delay_frames'] = systemConfig.get(
            'netplay.frames', "")
        retroarchConfig['netplay_nickname'] = systemConfig.get(
            'netplay.nick', "")
        retroarchConfig['netplay_client_swap_input'] = "false"
        if system.config['netplaymode'] == 'client':
            # But client needs netplay_mode = true ... bug ?
            retroarchConfig['netplay_mode'] = "true"
            retroarchConfig['netplay_ip_address'] = systemConfig.get(
                'netplay.server.ip', "")
            retroarchConfig['netplay_client_swap_input'] = "true"

    # Display FPS
    if system.isOptSet('showFPS') and system.getOptBoolean('showFPS') == True:
        retroarchConfig['fps_show'] = 'true'
    else:
        retroarchConfig['fps_show'] = 'false'

    # adaptation for small resolution
    if gameResolution["width"] < 400 and gameResolution["height"] < 400:
        retroarchConfig['video_font_size'] = '12'
        retroarchConfig['menu_driver'] = 'rgui'
    else:
        retroarchConfig['video_font_size'] = '32'
        retroarchConfig['menu_driver'] = 'ozone'
        # force the assets directory while it was wrong in some beta versions
        retroarchConfig['assets_directory'] = '/usr/share/retroarch/assets'

    # bezel
    writeBezelConfig(bezel, retroarchConfig, system.name, rom, gameResolution)

    return retroarchConfig
def createLibretroConfig(system, controllers, rom, bezel, gameResolution):

    # retroarch-core-options.cfg
    retroarchCore = batoceraFiles.retroarchCoreCustom
    if not os.path.exists(os.path.dirname(retroarchCore)):
        os.makedirs(os.path.dirname(retroarchCore))

    try:
        coreSettings = UnixSettings(retroarchCore, separator=' ')
    except UnicodeError:
        # invalid retroarch-core-options.cfg
        # remove it and try again
        os.remove(retroarchCore)
        coreSettings = UnixSettings(retroarchCore, separator=' ')

    # Create/update retroarch-core-options.cfg
    libretroOptions.generateCoreSettings(coreSettings, system, rom)

    # Create/update hatari.cfg
    if system.name == 'atarist':
        libretroOptions.generateHatariConf(batoceraFiles.hatariConf)

    retroarchConfig = dict()
    systemConfig = system.config
    renderConfig = system.renderconfig

    # Basic configuration
    retroarchConfig['quit_press_twice'] = 'false'               # not aligned behavior on other emus
    retroarchConfig['video_driver'] = '"gl"'                    # needed for the ozone menu

    if system.isOptSet("gfxbackend") and system.config["gfxbackend"] == "vulkan":
        retroarchConfig['video_driver'] = '"vulkan"'

    retroarchConfig['video_black_frame_insertion'] = 'false'    # don't use anymore this value while it doesn't allow the shaders to work
    retroarchConfig['pause_nonactive'] = 'false'                # required at least on x86 x86_64 otherwise, the game is paused at launch
    retroarchConfig['audio_driver'] = 'alsa'                    # force ALSA. TODO: check audio.backend
    retroarchConfig['midi_driver'] = 'alsa'
    retroarchConfig['cache_directory'] = '/userdata/system/.cache'

    retroarchConfig['video_fullscreen'] = 'true'                # Fullscreen is required at least for x86* and odroidn2

    retroarchConfig['savestate_directory'] = batoceraFiles.savesDir + system.name
    retroarchConfig['savefile_directory'] = batoceraFiles.savesDir + system.name

    # Forced values (so that if the config is not correct, fix it)
    if system.config['core'] == 'tgbdual':
        retroarchConfig['aspect_ratio_index'] = str(ratioIndexes.index("core")) # Reset each time in this function

    # Disable internal image viewer (ES does it, and pico-8 won't load .p8.png)
    retroarchConfig['builtin_imageviewer_enable'] = 'false'

    # Disable the threaded video while it is causing issues to several people ?
    # This must be set to true on xu4 for performance issues
    if system.config['video_threaded']:
        retroarchConfig['video_threaded'] = 'true'
    else:
        retroarchConfig['video_threaded'] = 'false'

    # Input configuration
    retroarchConfig['input_joypad_driver'] = 'udev'
    retroarchConfig['input_max_users'] = "16"                   # Allow up to 16 players

    retroarchConfig['input_libretro_device_p1'] = '1'           # Default devices choices
    retroarchConfig['input_libretro_device_p2'] = '1'

    ## Specific choices
    if(system.config['core'] in coreToP1Device):
        retroarchConfig['input_libretro_device_p1'] = coreToP1Device[system.config['core']]
    if(system.config['core'] in coreToP2Device):
        retroarchConfig['input_libretro_device_p2'] = coreToP2Device[system.config['core']]

    if len(controllers) > 2 and (system.config['core'] == 'snes9x_next' or system.config['core'] == 'snes9x'):
        retroarchConfig['input_libretro_device_p2'] = '257'

    ## BlueMSX choices by System
    if(system.name in systemToBluemsx):
        if system.config['core'] == 'bluemsx':
            retroarchConfig['input_libretro_device_p1'] = systemToP1Device[system.name]
            retroarchConfig['input_libretro_device_p2'] = systemToP2Device[system.name]

    ## PlayStation controller
    if (system.config['core'] == 'mednafen_psx'):               # Madnafen
        if system.isOptSet('beetle_psx_Controller1'):
            retroarchConfig['input_libretro_device_p1'] = system.config['beetle_psx_Controller1']
        if system.isOptSet('beetle_psx_Controller2'):
            retroarchConfig['input_libretro_device_p2'] = system.config['beetle_psx_Controller2']
    if (system.config['core'] == 'pcsx_rearmed'):               # PCSX Rearmed
        if system.isOptSet('controller1_pcsx'):
            retroarchConfig['input_libretro_device_p1'] = system.config['controller1_pcsx']
        if system.isOptSet('controller2_pcsx'):
            retroarchConfig['input_libretro_device_p2'] = system.config['controller2_pcsx']

    ## Sega Megadrive controller
    if system.config['core'] == 'genesisplusgx' and system.name == 'megadrive':
        if system.isOptSet('controller1_md'):
            retroarchConfig['input_libretro_device_p1'] = system.config['controller1_md']
        else:
            retroarchConfig['input_libretro_device_p1'] = '513' # 6 button
        if system.isOptSet('controller2_md'):
            retroarchConfig['input_libretro_device_p2'] = system.config['controller2_md']
        else:
            retroarchConfig['input_libretro_device_p2'] = '513' # 6 button

    ## Sega Mastersystem controller
    if system.config['core'] == 'genesisplusgx' and system.name == 'mastersystem':
        if system.isOptSet('controller1_ms'):
            retroarchConfig['input_libretro_device_p1'] = system.config['controller1_ms']
        else:
            retroarchConfig['input_libretro_device_p1'] = '769'
        if system.isOptSet('controller2_ms'):
            retroarchConfig['input_libretro_device_p2'] = system.config['controller2_ms']
        else:
            retroarchConfig['input_libretro_device_p2'] = '769'


    # Smooth option
    if system.isOptSet('smooth') and system.getOptBoolean('smooth') == True:
        retroarchConfig['video_smooth'] = 'true'
    else:
        retroarchConfig['video_smooth'] = 'false'

    # Shader option
    if 'shader' in renderConfig and renderConfig['shader'] != None:
        retroarchConfig['video_shader_enable'] = 'true'
        retroarchConfig['video_smooth']        = 'false'     # seems to be necessary for weaker SBCs
        shaderFilename = renderConfig['shader'] + ".glslp"
        if os.path.exists("/userdata/shaders/" + shaderFilename):
            retroarchConfig['video_shader_dir'] = "/userdata/shaders"
            eslog.log("shader {} found in /userdata/shaders".format(shaderFilename))
        else:
            retroarchConfig['video_shader_dir'] = "/usr/share/batocera/shaders"
    else:
        retroarchConfig['video_shader_enable'] = 'false'

    # Ratio option
    retroarchConfig['aspect_ratio_index'] = ''              # reset in case config was changed (or for overlays)
    if defined('ratio', systemConfig):
        if systemConfig['ratio'] in ratioIndexes:
            retroarchConfig['aspect_ratio_index'] = ratioIndexes.index(systemConfig['ratio'])
            retroarchConfig['video_aspect_ratio_auto'] = 'false'
        elif systemConfig['ratio'] == "custom":
            retroarchConfig['video_aspect_ratio_auto'] = 'false'
        else:
            retroarchConfig['video_aspect_ratio_auto'] = 'true'
            retroarchConfig['aspect_ratio_index'] = ''

    # Rewind option
    retroarchConfig['rewind_enable'] = 'false'
    if system.isOptSet('rewind') and system.getOptBoolean('rewind') == True:
        if(not system.name in systemNoRewind):
            retroarchConfig['rewind_enable'] = 'true'
    else:
        retroarchConfig['rewind_enable'] = 'false'

    # Retroachievement option
    retroarchConfig['run_ahead_enabled'] = 'false'
    retroarchConfig['run_ahead_frames'] = '0'
    retroarchConfig['run_ahead_secondary_instance'] = 'false'
    if system.isOptSet('runahead') and int(system.config['runahead']) >0:
       if (not system.name in systemNoRunahead):
          retroarchConfig['run_ahead_enabled'] = 'true'
          retroarchConfig['run_ahead_frames'] = system.config['runahead']
          if system.isOptSet('secondinstance') and system.getOptBoolean('secondinstance') == True:
              retroarchConfig['run_ahead_secondary_instance'] = 'true'

    # Autosave option
    if system.isOptSet('autosave') and system.getOptBoolean('autosave') == True:
        retroarchConfig['savestate_auto_save'] = 'true'
        retroarchConfig['savestate_auto_load'] = 'true'
    else:
        retroarchConfig['savestate_auto_save'] = 'false'
        retroarchConfig['savestate_auto_load'] = 'false'

    # Retroachievements option
    retroarchConfig['cheevos_enable'] = 'false'
    retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
    retroarchConfig['cheevos_leaderboards_enable'] = 'false'
    retroarchConfig['cheevos_verbose_enable'] = 'false'
    retroarchConfig['cheevos_auto_screenshot'] = 'false'

    if system.isOptSet('retroachievements') and system.getOptBoolean('retroachievements') == True:
        if(system.name in systemToRetroachievements):
            retroarchConfig['cheevos_enable'] = 'true'
            retroarchConfig['cheevos_username'] = systemConfig.get('retroachievements.username', "")
            retroarchConfig['cheevos_password'] = systemConfig.get('retroachievements.password', "")
            # retroachievements_hardcore_mode
            if system.isOptSet('retroachievements.hardcore') and system.getOptBoolean('retroachievements.hardcore') == True:
                retroarchConfig['cheevos_hardcore_mode_enable'] = 'true'
            else:
                retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
            # retroachievements_leaderboards
            if system.isOptSet('retroachievements.leaderboards') and system.getOptBoolean('retroachievements.leaderboards') == True:
                retroarchConfig['cheevos_leaderboards_enable'] = 'true'
            else:
                retroarchConfig['cheevos_leaderboards_enable'] = 'false'
            # retroachievements_verbose_mode
            if system.isOptSet('retroachievements.verbose') and system.getOptBoolean('retroachievements.verbose') == True:
                retroarchConfig['cheevos_verbose_enable'] = 'true'
            else:
                retroarchConfig['cheevos_verbose_enable'] = 'false'
            # retroachievements_automatic_screenshot
            if system.isOptSet('retroachievements.screenshot') and system.getOptBoolean('retroachievements.screenshot') == True:
                retroarchConfig['cheevos_auto_screenshot'] = 'true'
            else:
                retroarchConfig['cheevos_auto_screenshot'] = 'false'
    else:
        retroarchConfig['cheevos_enable'] = 'false'

    if system.isOptSet('integerscale') and system.getOptBoolean('integerscale') == True:
        retroarchConfig['video_scale_integer'] = 'true'
    else:
        retroarchConfig['video_scale_integer'] = 'false'

    # Netplay management
    if 'netplay.mode' in system.config and system.config['netplay.mode'] in systemNetplayModes:
        # Security : hardcore mode disables save states, which would kill netplay
        retroarchConfig['cheevos_hardcore_mode_enable'] = 'false'
        # Quite strangely, host mode requires netplay_mode to be set to false when launched from command line
        retroarchConfig['netplay_mode']              = "false"
        retroarchConfig['netplay_ip_port']           = systemConfig.get('netplay.port', "")
        retroarchConfig['netplay_delay_frames']      = systemConfig.get('netplay.frames', "")
        retroarchConfig['netplay_nickname']          = systemConfig.get('netplay.nickname', "")
        retroarchConfig['netplay_client_swap_input'] = "false"
        if system.config['netplay.mode'] == 'client' or system.config['netplay.mode'] == 'spectator':
            # But client needs netplay_mode = true ... bug ?
            retroarchConfig['netplay_mode']              = "true"
            retroarchConfig['netplay_ip_address']        = systemConfig.get('netplay.server.ip', "")
            retroarchConfig['netplay_ip_port']           = systemConfig.get('netplay.server.port', "")
            retroarchConfig['netplay_client_swap_input'] = "true"

        # Connect as client
        if system.config['netplay.mode'] == 'client':
            if 'netplay.password' in system.config:
                retroarchConfig['netplay_password'] = '******' + systemConfig.get("netplay.password", "") + '"'
            else:
                retroarchConfig['netplay_password'] = ""

        # Connect as spectator
        if system.config['netplay.mode'] == 'spectator':
            retroarchConfig['netplay_start_as_spectator'] = "true"
            if 'netplay.password' in system.config:
                retroarchConfig['netplay_spectate_password'] = '******' + systemConfig.get("netplay.password", "") + '"'
            else:
                retroarchConfig['netplay_spectate_password'] = ""
        else:
            retroarchConfig['netplay_start_as_spectator'] = "false"            

         # Netplay host passwords
        if system.config['netplay.mode'] == 'host':
            retroarchConfig['netplay_password'] = '******' + systemConfig.get("netplay.password", "") + '"'
            retroarchConfig['netplay_spectate_password'] = '******' + systemConfig.get("netplay.spectatepassword", "") + '"'

        # Enable or disable server spectator mode
        if system.isOptSet('netplay.spectator') and system.getOptBoolean('netplay.spectator') == True:
            retroarchConfig['netplay_spectator_mode_enable'] = 'true'
        else:
            retroarchConfig['netplay_spectator_mode_enable'] = 'false'

        # Relay
        if 'netplay.relay' in system.config and system.config['netplay.relay'] != "" and system.config['netplay.relay'] != "none" :
            retroarchConfig['netplay_use_mitm_server'] = "true"
            retroarchConfig['netplay_mitm_server'] = systemConfig.get('netplay.relay', "")
        else:
            retroarchConfig['netplay_use_mitm_server'] = "false"

    # Display FPS
    if system.isOptSet('showFPS') and system.getOptBoolean('showFPS') == True:
        retroarchConfig['fps_show'] = 'true'
    else:
        retroarchConfig['fps_show'] = 'false'

    # Adaptation for small resolution
    if isLowResolution(gameResolution):
        retroarchConfig['video_font_size'] = '12'
        retroarchConfig['menu_driver'] = 'rgui'
        retroarchConfig['width']  = gameResolution["width"]  *2 # on low resolution, higher values for width and height makes a nicer image (640x480 on the gpi case)
        retroarchConfig['height'] = gameResolution["height"] *2 # default value
        retroarchConfig['menu_linear_filter'] = 'true'
        retroarchConfig['rgui_aspect_ratio'] = '0'
        retroarchConfig['rgui_aspect_ratio_lock'] = '3'
    else:
        retroarchConfig['video_font_size'] = '32'
        retroarchConfig['menu_driver'] = 'ozone'
        # force the assets directory while it was wrong in some beta versions
        retroarchConfig['assets_directory'] = '/usr/share/libretro/assets'
        retroarchConfig['width']  = gameResolution["width"]  # default value
        retroarchConfig['height'] = gameResolution["height"] # default value

    # AI option (service for game translations)
    if system.isOptSet('ai_service_enabled') and system.getOptBoolean('ai_service_enabled') == True:
        retroarchConfig['ai_service_enable'] = 'true'
        retroarchConfig['ai_service_mode'] = '0'
        retroarchConfig['ai_service_source_lang'] = '0'
        if system.isOptSet('ai_target_lang'):
            chosen_lang=system.config['ai_target_lang']
        else:
            chosen_lang='En'
        if system.isOptSet('ai_service_url') and system.config['ai_service_url']:
            retroarchConfig['ai_service_url'] = system.config['ai_service_url']+'&mode=Fast&output=png&target_lang='+chosen_lang
        else:
            retroarchConfig['ai_service_url'] = 'http://ztranslate.net/service?api_key=BATOCERA&mode=Fast&output=png&target_lang='+chosen_lang
        if system.isOptSet('ai_service_pause') and system.getOptBoolean('ai_service_pause') == True:
            retroarchConfig['ai_service_pause'] = 'true'
        else:
            retroarchConfig['ai_service_pause'] = 'false'
    else:
        retroarchConfig['ai_service_enable'] = 'false'

    # Bezel option
    if system.isOptSet('bezel_stretch') and system.getOptBoolean('bezel_stretch') == True:
        bezel_stretch = True
    else:
        bezel_stretch = False
    try:
        writeBezelConfig(bezel, retroarchConfig, system.name, rom, gameResolution, bezel_stretch)
    except:
        # error with bezels, disabling them
        writeBezelConfig(None, retroarchConfig, system.name, rom, gameResolution, bezel_stretch)

    # custom : allow the user to configure directly retroarch.cfg via batocera.conf via lines like : snes.retroarch.menu_driver=rgui
    for user_config in systemConfig:
        if user_config[:10] == "retroarch.":
            retroarchConfig[user_config[10:]] = systemConfig[user_config]

    return retroarchConfig
def main(args):
    playersControllers = dict()
    # Read the controller configuration
    playersControllers = controllers.loadControllerConfig(
        args.p1index, args.p1guid, args.p1name, args.p1devicepath,
        args.p1nbaxes, args.p2index, args.p2guid, args.p2name,
        args.p2devicepath, args.p2nbaxes, args.p3index, args.p3guid,
        args.p3name, args.p3devicepath, args.p3nbaxes, args.p4index,
        args.p4guid, args.p4name, args.p4devicepath, args.p4nbaxes,
        args.p5index, args.p5guid, args.p5name, args.p5devicepath,
        args.p5nbaxes)
    # find the system to run
    systemName = args.system
    eslog.log("Running system: {}".format(systemName))
    system = Emulator(systemName)
    eslog.debug("Settings: {}".format(system.config))
    if "emulator" in system.config and "core" in system.config:
        eslog.log("emulator: {}, core: {}".format(system.config["emulator"],
                                                  system.config["core"]))
    else:
        if "emulator" in system.config:
            eslog.log("emulator: {}".format(system.config["emulator"]))

    # the resolution must be changed before configuration while the configuration may depend on it (ie bezels)
    wantedGameMode = generators[system.config['emulator']].getResolutionMode(
        system.config)
    systemMode = videoMode.getCurrentMode()
    resolutionChanged = False
    exitCode = -1
    try:
        eslog.log("current video mode: {}".format(systemMode))
        eslog.log("wanted video mode: {}".format(wantedGameMode))
        if wantedGameMode != 'default' and wantedGameMode != systemMode:
            videoMode.changeMode(wantedGameMode)
            resolutionChanged = True
        gameResolution = videoMode.getCurrentResolution()
        eslog.log("resolution: {}x{}".format(str(gameResolution["width"]),
                                             str(gameResolution["height"])))

        # savedir: create the save directory if not already done
        dirname = os.path.join(batoceraFiles.savesDir, system.name)
        if not os.path.exists(dirname):
            os.makedirs(dirname)

        # run the emulator
        exitCode = runCommand(generators[system.config['emulator']].generate(
            system, args.rom, playersControllers, gameResolution))
    finally:
        # always restore the resolution
        if resolutionChanged:
            try:
                videoMode.changeMode(systemMode)
            except Exception:
                pass  # don't fail
    # exit
    return exitCode
    def generate(self, system, rom, playersControllers, gameResolution):
        # Settings batocera default config file if no user defined one
        if not 'configfile' in system.config:
            # Using batocera config file
            system.config['configfile'] = batoceraFiles.retroarchCustom
            # Create retroarchcustom.cfg if does not exists
            if not os.path.isfile(batoceraFiles.retroarchCustom):
                libretroRetroarchCustom.generateRetroarchCustom()
            #  Write controllers configuration files
            retroconfig = UnixSettings(batoceraFiles.retroarchCustom,
                                       separator=' ')
            libretroControllers.writeControllersConfig(retroconfig, system,
                                                       playersControllers)
            # force pathes
            libretroRetroarchCustom.generateRetroarchCustomPathes(retroconfig)
            # Write configuration to retroarchcustom.cfg
            if 'bezel' not in system.config or system.config['bezel'] == '':
                bezel = None
            else:
                bezel = system.config['bezel']
            # some systems (ie gw) won't bezels
            if system.isOptSet('forceNoBezel') and system.getOptBoolean(
                    'forceNoBezel'):
                bezel = None

            libretroConfig.writeLibretroConfig(retroconfig, system,
                                               playersControllers, rom, bezel,
                                               gameResolution)

        # Retroarch core on the filesystem
        retroarchCore = batoceraFiles.retroarchCores + system.config[
            'core'] + batoceraFiles.libretroExt
        romName = os.path.basename(rom)

        # the command to run
        # For the NeoGeo CD (lr-fbneo) it is necessary to add the parameter: --subsystem neocd
        if system.name == 'neogeocd' and system.config['core'] == "fbneo":
            commandArray = [
                batoceraFiles.batoceraBins[system.config['emulator']], "-L",
                retroarchCore, "--subsystem", "neocd", "--config",
                system.config['configfile']
            ]
        elif system.name == 'dos':
            commandArray = [
                batoceraFiles.batoceraBins[system.config['emulator']], "-L",
                retroarchCore, "--config", system.config['configfile'],
                rom + "/dosbox.bat"
            ]
        else:
            commandArray = [
                batoceraFiles.batoceraBins[system.config['emulator']], "-L",
                retroarchCore, "--config", system.config['configfile']
            ]

        configToAppend = []

        # Custom configs - per core
        customCfg = "{}/{}.cfg".format(batoceraFiles.retroarchRoot,
                                       system.name)
        if os.path.isfile(customCfg):
            configToAppend.append(customCfg)

        # Custom configs - per game
        customGameCfg = "{}/{}/{}.cfg".format(batoceraFiles.retroarchRoot,
                                              system.name, romName)
        if os.path.isfile(customGameCfg):
            configToAppend.append(customGameCfg)

        # Overlay management
        overlayFile = "{}/{}/{}.cfg".format(batoceraFiles.OVERLAYS,
                                            system.name, romName)
        if os.path.isfile(overlayFile):
            configToAppend.append(overlayFile)

        # RetroArch 1.7.8 (Batocera 5.24) now requires the shaders to be passed as command line argument
        renderConfig = system.renderconfig
        if 'shader' in renderConfig and renderConfig['shader'] != None:
            shaderFilename = renderConfig['shader'] + ".glslp"
            eslog.log("searching shader {}".format(shaderFilename))
            if os.path.exists("/userdata/shaders/" + shaderFilename):
                video_shader_dir = "/userdata/shaders"
                eslog.log("shader {} found in /userdata/shaders".format(
                    shaderFilename))
            else:
                video_shader_dir = "/usr/share/batocera/shaders"
            video_shader = video_shader_dir + "/" + shaderFilename
            commandArray.extend(["--set-shader", video_shader])

        # Generate the append
        if configToAppend:
            commandArray.extend(["--appendconfig", "|".join(configToAppend)])

        # Netplay mode
        if 'netplay.mode' in system.config:
            if system.config['netplay.mode'] == 'host':
                commandArray.append("--host")
            elif system.config['netplay.mode'] == 'client':
                commandArray.extend(
                    ["--connect", system.config['netplay.server.ip']])
            if 'netplay.server.port' in system.config:
                commandArray.extend(
                    ["--port", system.config['netplay.server.port']])
            if 'netplay.nickname' in system.config:
                commandArray.extend(
                    ["--nick", system.config['netplay.nickname']])

        # Verbose logs
        commandArray.extend(['--verbose'])

        # Extension used by hypseus .daphne but lr-daphne starts with .zip
        if system.name == 'daphne':
            romName = os.path.splitext(os.path.basename(rom))[0]
            rom = batoceraFiles.daphneDatadir + '/roms/' + romName + '.zip'

        if system.name == 'dos':
            rom = 'set ROOT=' + rom

        commandArray.append(rom)
        return Command.Command(array=commandArray)
Exemple #26
0
def main(args, maxnbplayers):
    playersControllers = dict()

    controllersInput = []
    for p in range(1, maxnbplayers + 1):
        ci = {}
        ci["index"] = getattr(args, "p{}index".format(p))
        ci["guid"] = getattr(args, "p{}guid".format(p))
        ci["name"] = getattr(args, "p{}name".format(p))
        ci["devicepath"] = getattr(args, "p{}devicepath".format(p))
        ci["nbbuttons"] = getattr(args, "p{}nbbuttons".format(p))
        ci["nbhats"] = getattr(args, "p{}nbhats".format(p))
        ci["nbaxes"] = getattr(args, "p{}nbaxes".format(p))
        controllersInput.append(ci)

    # Read the controller configuration
    playersControllers = controllers.loadControllerConfig(controllersInput)
    # find the system to run
    systemName = args.system
    eslog.log("Running system: {}".format(systemName))
    system = Emulator(systemName, args.rom)

    system.config["emulator-forced"] = False
    system.config["core-forced"] = False
    if args.emulator is not None:
        system.config["emulator"] = args.emulator
        system.config[
            "emulator-forced"] = True  # tip to indicated that the emulator was forced
    if args.core is not None:
        system.config["core"] = args.core
        system.config["core-forced"] = True

    eslog.debug("Settings: {}".format(system.config))
    if "emulator" in system.config and "core" in system.config:
        eslog.log("emulator: {}, core: {}".format(system.config["emulator"],
                                                  system.config["core"]))
    else:
        if "emulator" in system.config:
            eslog.log("emulator: {}".format(system.config["emulator"]))

    # the resolution must be changed before configuration while the configuration may depend on it (ie bezels)
    wantedGameMode = generators[system.config['emulator']].getResolutionMode(
        system.config)
    systemMode = videoMode.getCurrentMode()
    resolutionChanged = False
    exitCode = -1
    try:
        eslog.log("current video mode: {}".format(systemMode))
        eslog.log("wanted video mode: {}".format(wantedGameMode))
        if wantedGameMode != 'default' and wantedGameMode != systemMode:
            videoMode.changeMode(wantedGameMode)
            resolutionChanged = True
        gameResolution = videoMode.getCurrentResolution()
        eslog.log("resolution: {}x{}".format(str(gameResolution["width"]),
                                             str(gameResolution["height"])))

        # savedir: create the save directory if not already done
        dirname = os.path.join(batoceraFiles.savesDir, system.name)
        if not os.path.exists(dirname):
            os.makedirs(dirname)

        # core
        effectiveCore = ""
        if "core" in system.config and system.config["core"] is not None:
            effectiveCore = system.config["core"]
        effectiveRom = ""
        if args.rom is not None:
            effectiveRom = args.rom

        # network options
        if args.netplaymode is not None:
            system.config["netplay.mode"] = args.netplaymode
        if args.netplayspectator is not None:
            system.config["netplay.spectator"] = args.netplayspectator
        if args.netplayip is not None:
            system.config["netplay.server.ip"] = args.netplayip
        if args.netplayport is not None:
            system.config["netplay.server.port"] = args.netplayport

        # run a script before emulator starts
        callExternalScripts("/usr/share/batocera/configgen/scripts",
                            "gameStart", [
                                systemName, system.config['emulator'],
                                effectiveCore, effectiveRom
                            ])
        callExternalScripts("/userdata/system/scripts", "gameStart", [
            systemName, system.config['emulator'], effectiveCore, effectiveRom
        ])

        # run the emulator
        exitCode = runCommand(generators[system.config['emulator']].generate(
            system, args.rom, playersControllers, gameResolution))

        # run a script after emulator shuts down
        callExternalScripts("/userdata/system/scripts", "gameStop", [
            systemName, system.config['emulator'], effectiveCore, effectiveRom
        ])
        callExternalScripts("/usr/share/batocera/configgen/scripts",
                            "gameStop", [
                                systemName, system.config['emulator'],
                                effectiveCore, effectiveRom
                            ])

    finally:
        # always restore the resolution
        if resolutionChanged:
            try:
                videoMode.changeMode(systemMode)
            except Exception:
                pass  # don't fail
    # exit
    return exitCode
    parser.add_argument("-core",
                        help="force emulator core",
                        type=str,
                        required=False)
    parser.add_argument("-ratio",
                        help="force game ratio",
                        type=str,
                        required=False)
    parser.add_argument("-netplay",
                        help="host/client",
                        type=str,
                        required=False)

    args = parser.parse_args()
    try:
        exitcode = -1
        exitcode = main(args)
    except Exception as e:
        eslog.error("configgen exception: ", exc_info=True)
    time.sleep(
        1
    )  # this seems to be required so that the gpu memory is restituated and available for es
    eslog.log("Exiting configgen with status {}".format(str(exitcode)))
    exit(exitcode)

# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
# End:
# vim: set expandtab tabstop=4 shiftwidth=4:
    def generate(self, system, rom, playersControllers, gameResolution):
        wineprefix = batoceraFiles.SAVES + "/fpinball"

        if not os.path.exists(wineprefix):
            os.makedirs(wineprefix)

        if not os.path.exists(wineprefix + "/wsh57.done"):
            ## run winetricks to be sure that wsh57 is here (it does nothing if already done)
            ##  if /userdata/bios/wsh57/scripten.exe is not here, it will tries to download it if network is available
            cmd = ["/usr/wine/winetricks", "wsh57"]
            env = {
                "W_CACHE": "/userdata/bios",
                "LD_LIBRARY_PATH": "/lib32:/usr/wine/lutris/lib/wine",
                "WINEPREFIX": "/userdata/saves/fpinball"
            }
            env.update(os.environ)
            env["PATH"] = "/usr/wine/lutris/bin:/bin:/usr/bin"
            eslog.log("command: {}".format(str(cmd)))
            proc = subprocess.Popen(cmd,
                                    env=env,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            out, err = proc.communicate()
            exitcode = proc.returncode
            eslog.log(out.decode())
            eslog.log(err.decode())
            with open(wineprefix + "/wsh57.done", "w") as f:
                f.write("done")

        commandArray = [
            "/usr/wine/lutris/bin/wine", "explorer",
            "/desktop=Wine,{}x{}".format(gameResolution["width"],
                                         gameResolution["height"]),
            "/usr/fpinball/Future Pinball.exe", "/open", "z:" + rom, "/play",
            "/exit"
        ]

        # config
        if not os.path.exists("/userdata/system/configs/fpinball"):
            os.makedirs("/userdata/system/configs/fpinball")
        with open("/userdata/system/configs/fpinball/batocera.confg.reg",
                  "w") as f:
            f.write("Windows Registry Editor Version 5.00\r\n\r\n")
            f.write(
                "[HKEY_CURRENT_USER\\Software\\Future Pinball\\GamePlayer]\r\n"
            )
            f.write("\"AspectRatio\"=dword:{:08x}\r\n".format(
                FpinballGenerator.getGfxRatioFromConfig(
                    system.config, gameResolution)))
            f.write("\"FullScreen\"=dword:00000001\r\n")
            f.write("\"Width\"=dword:{:08x}\r\n".format(
                gameResolution["width"]))
            f.write("\"Height\"=dword:{:08x}\r\n".format(
                gameResolution["height"]))
            f.write("\"JoypadNameNum\"=dword:00000001\r\n")
            f.write("\r\n")

            mapping = {
                "a": "JoypadBackbox",
                "b": "JoypadDigitalPlunger",
                "x": "JoypadPause",
                "y": "JoypadNextCamera",
                "pageup": "JoypadLeftFlipper",
                "pagedown": "JoypadRightFlipper",
                "start": "JoypadStartGame",
                "select": "JoypadInsertCoin",
                "r3": "JoypadToggleHud"
            }

            nplayer = 1
            for playercontroller, pad in sorted(playersControllers.items()):
                joystickname = pad.realName
                unassigned_value = int("ffffffff", 16)
                assigns = {
                    "JoypadBackbox": unassigned_value,
                    "JoypadDigitalPlunger": unassigned_value,
                    "JoypadInsertCoin": unassigned_value,
                    "JoypadNextCamera": unassigned_value,
                    "JoypadLeftFlipper": unassigned_value,
                    "JoypadRightFlipper": unassigned_value,
                    "JoypadPause": unassigned_value,
                    "JoypadStartGame": unassigned_value,
                    "JoypadToggleHud": unassigned_value
                }
                for x in pad.inputs:
                    if x in mapping:
                        if mapping[x] in assigns:
                            if pad.inputs[x].type == "button":
                                assigns[mapping[x]] = int(pad.inputs[x].id)

                f.write(
                    "[HKEY_CURRENT_USER\\Software\\Future Pinball\\GamePlayer\\Joypads\\{} (js)]\r\n"
                    .format(joystickname))
                f.write("\"JoypadBackbox\"=dword:{:08x}\r\n".format(
                    assigns["JoypadBackbox"]))
                f.write("\"JoypadDeadZone\"=dword:00000064\r\n")
                f.write("\"JoypadDigitalPlunger\"=dword:{:08x}\r\n".format(
                    assigns["JoypadDigitalPlunger"]))
                f.write("\"JoypadExit\"=dword:ffffffff\r\n")
                f.write("\"JoypadInsertCoin\"=dword:{:08x}\r\n".format(
                    assigns["JoypadInsertCoin"]))
                f.write("\"JoypadInsertCoin2\"=dword:ffffffff\r\n")
                f.write("\"JoypadInsertCoin3\"=dword:ffffffff\r\n")
                f.write("\"JoypadLeft2ndFlipper\"=dword:ffffffff\r\n")
                f.write("\"JoypadLeftFlipper\"=dword:{:08x}\r\n".format(
                    assigns["JoypadLeftFlipper"]))
                f.write("\"JoypadMusicDown\"=dword:ffffffff\r\n")
                f.write("\"JoypadMusicUp\"=dword:ffffffff\r\n")
                f.write("\"JoypadNextCamera\"=dword:{:08x}\r\n".format(
                    assigns["JoypadNextCamera"]))
                f.write("\"JoypadNudgeAxisX\"=dword:ffffffff\r\n")
                f.write("\"JoypadNudgeAxisY\"=dword:ffffffff\r\n")
                f.write("\"JoypadNudgeGainX\"=dword:000003e8\r\n")
                f.write("\"JoypadNudgeGainXMax\"=dword:00000002\r\n")
                f.write("\"JoypadNudgeGainY\"=dword:000003e8\r\n")
                f.write("\"JoypadNudgeGainYMax\"=dword:00000002\r\n")
                f.write("\"JoypadPause\"=dword:{:08x}\r\n".format(
                    assigns["JoypadPause"]))
                f.write("\"JoypadPinballRoller\"=dword:ffffffff\r\n")
                f.write("\"JoypadPinballRollerAxisX\"=dword:ffffffff\r\n")
                f.write("\"JoypadPinballRollerAxisY\"=dword:ffffffff\r\n")
                f.write("\"JoypadPinballRollerGainX\"=dword:000003e8\r\n")
                f.write("\"JoypadPinballRollerGainXMax\"=dword:00000002\r\n")
                f.write("\"JoypadPinballRollerGainY\"=dword:000003e8\r\n")
                f.write("\"JoypadPinballRollerGainYMax\"=dword:00000002\r\n")
                f.write("\"JoypadPlungerAxis\"=dword:00000001\r\n")
                f.write("\"JoypadPlungerGain\"=dword:000003e8\r\n")
                f.write("\"JoypadPlungerGainMax\"=dword:00000002\r\n")
                f.write("\"JoypadRight2ndFlipper\"=dword:ffffffff\r\n")
                f.write("\"JoypadRightFlipper\"=dword:{:08x}\r\n".format(
                    assigns["JoypadRightFlipper"]))
                f.write("\"JoypadService\"=dword:ffffffff\r\n")
                f.write("\"JoypadSpecial1\"=dword:ffffffff\r\n")
                f.write("\"JoypadSpecial2\"=dword:ffffffff\r\n")
                f.write("\"JoypadStartGame\"=dword:{:08x}\r\n".format(
                    assigns["JoypadStartGame"]))
                f.write(
                    "\"JoypadSupport\"=dword:00000001\r\n")  # enable joystick
                f.write("\"JoypadTest\"=dword:ffffffff\r\n")
                f.write("\"JoypadToggleHud\"=dword:{:08x}\r\n".format(
                    assigns["JoypadToggleHud"]))
                f.write("\"JoypadVolumeDown\"=dword:ffffffff\r\n")
                f.write("\"JoypadVolumeUp\"=dword:ffffffff\r\n")
                f.write("\r\n")

        cmd = [
            "wine", "regedit",
            "/userdata/system/configs/fpinball/batocera.confg.reg"
        ]
        env = {
            "LD_LIBRARY_PATH": "/lib32:/usr/wine/lutris/lib/wine",
            "WINEPREFIX": "/userdata/saves/fpinball"
        }
        env.update(os.environ)
        env["PATH"] = "/usr/wine/lutris/bin:/bin:/usr/bin"
        eslog.log("command: {}".format(str(cmd)))
        proc = subprocess.Popen(cmd,
                                env=env,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
        out, err = proc.communicate()
        exitcode = proc.returncode
        eslog.log(out.decode())
        eslog.log(err.decode())

        return Command.Command(
            array=commandArray,
            env={
                "WINEPREFIX": wineprefix,
                "LD_LIBRARY_PATH": "/lib32:/usr/wine/lutris/lib/wine",
                "LIBGL_DRIVERS_PATH": "/lib32/dri"
                #"SDL_GAMECONTROLLERCONFIG": controllersConfig.generateSdlGameControllerConfig(playersControllers)
            })
def generateControllerConfig_emulatedwiimotes(playersControllers, rom):
    wiiMapping = {
        'x': 'Buttons/2',
        'b': 'Buttons/A',
        'y': 'Buttons/1',
        'a': 'Buttons/B',
        'pageup': 'Buttons/-',
        'pagedown': 'Buttons/+',
        'select': 'Buttons/Home',
        'up': 'D-Pad/Up',
        'down': 'D-Pad/Down',
        'left': 'D-Pad/Left',
        'right': 'D-Pad/Right',
        'joystick1up': 'IR/Up',
        'joystick1left': 'IR/Left',
        'joystick2up': 'Tilt/Forward',
        'joystick2left': 'Tilt/Left'
    }
    wiiReverseAxes = {
        'D-Pad/Up': 'D-Pad/Down',
        'D-Pad/Left': 'D-Pad/Right',
        'IR/Up': 'IR/Down',
        'IR/Left': 'IR/Right',
        'Swing/Up': 'Swing/Down',
        'Swing/Left': 'Swing/Right',
        'Tilt/Left': 'Tilt/Right',
        'Tilt/Forward': 'Tilt/Backward',
        'Nunchuk/Stick/Up': 'Nunchuk/Stick/Down',
        'Nunchuk/Stick/Left': 'Nunchuk/Stick/Right',
        'Classic/Right Stick/Up': 'Classic/Right Stick/Down',
        'Classic/Right Stick/Left': 'Classic/Right Stick/Right',
        'Classic/Left Stick/Up': 'Classic/Left Stick/Down',
        'Classic/Left Stick/Left': 'Classic/Left Stick/Right'
    }

    extraOptions = {}
    extraOptions["Source"] = "1"

    # side wiimote
    if ".side." in rom:
        extraOptions["Options/Sideways Wiimote"] = "1"
        wiiMapping['x'] = 'Buttons/B'
        wiiMapping['y'] = 'Buttons/A'
        wiiMapping['a'] = 'Buttons/2'
        wiiMapping['b'] = 'Buttons/1'

    # i: infrared, s: swing, t: tilt, n: nunchuk
    # 12 possible combinations : is si / it ti / in ni / st ts / sn ns / tn nt

    # i
    if ".is." in rom or ".it." in rom or ".in." in rom:
        wiiMapping['joystick1up'] = 'IR/Up'
        wiiMapping['joystick1left'] = 'IR/Left'
    if ".si." in rom or ".ti." in rom or ".ni." in rom:
        wiiMapping['joystick2up'] = 'IR/Up'
        wiiMapping['joystick2left'] = 'IR/Left'

    # s
    if ".si." in rom or ".st." in rom or ".sn." in rom:
        wiiMapping['joystick1up'] = 'Swing/Up'
        wiiMapping['joystick1left'] = 'Swing/Left'
    if ".is." in rom or ".ts." in rom or ".ns." in rom:
        wiiMapping['joystick2up'] = 'Swing/Up'
        wiiMapping['joystick2left'] = 'Swing/Left'

    # t
    if ".ti." in rom or ".ts." in rom or ".tn." in rom:
        wiiMapping['joystick1up'] = 'Tilt/Forward'
        wiiMapping['joystick1left'] = 'Tilt/Left'
    if ".it." in rom or ".st." in rom or ".nt." in rom:
        wiiMapping['joystick2up'] = 'Tilt/Forward'
        wiiMapping['joystick2left'] = 'Tilt/Left'

    # n
    if ".ni." in rom or ".ns." in rom or ".nt." in rom:
        extraOptions['Extension'] = 'Nunchuk'
        wiiMapping['l2'] = 'Nunchuk/Buttons/C'
        wiiMapping['r2'] = 'Nunchuk/Buttons/Z'
        wiiMapping['joystick1up'] = 'Nunchuk/Stick/Up'
        wiiMapping['joystick1left'] = 'Nunchuk/Stick/Left'
    if ".in." in rom or ".sn." in rom or ".tn." in rom:
        extraOptions['Extension'] = 'Nunchuk'
        wiiMapping['l2'] = 'Nunchuk/Buttons/C'
        wiiMapping['r2'] = 'Nunchuk/Buttons/Z'
        wiiMapping['joystick2up'] = 'Nunchuk/Stick/Up'
        wiiMapping['joystick2left'] = 'Nunchuk/Stick/Left'

    if ".cc." in rom:  #Classic Controller Settings
        extraOptions['Extension'] = 'Classic'
        wiiMapping['x'] = 'Classic/Buttons/X'
        wiiMapping['y'] = 'Classic/Buttons/Y'
        wiiMapping['b'] = 'Classic/Buttons/B'
        wiiMapping['a'] = 'Classic/Buttons/A'
        wiiMapping['select'] = 'Classic/Buttons/-'
        wiiMapping['start'] = 'Classic/Buttons/+'
        wiiMapping['pageup'] = 'Classic/Triggers/L'
        wiiMapping['pagedown'] = 'Classic/Triggers/R'
        wiiMapping['l2'] = 'Classic/Buttons/ZL'
        wiiMapping['r2'] = 'Classic/Buttons/ZR'
        wiiMapping['up'] = 'Classic/D-Pad/Up'
        wiiMapping['down'] = 'Classic/D-Pad/Down'
        wiiMapping['left'] = 'Classic/D-Pad/Left'
        wiiMapping['right'] = 'Classic/D-Pad/Right'
        wiiMapping['joystick1up'] = 'Classic/Left Stick/Up'
        wiiMapping['joystick1left'] = 'Classic/Left Stick/Left'
        wiiMapping['joystick2up'] = 'Classic/Right Stick/Up'
        wiiMapping['joystick2left'] = 'Classic/Right Stick/Left'

    #This section allows a per ROM override of the default key options.
    configname = rom + ".cfg"  #Define ROM configuration name
    if os.path.isfile(configname):  #file exists
        import ast
        with open(configname) as cconfig:
            line = cconfig.readline()
            while line:
                entry = "{" + line + "}"
                res = ast.literal_eval(entry)
                wiiMapping.update(res)
                line = cconfig.readline()

    eslog.log("Extra Options: {}".format(extraOptions))
    eslog.log("Wii Mappings: {}".format(wiiMapping))

    generateControllerConfig_any(playersControllers, "WiimoteNew.ini",
                                 "Wiimote", wiiMapping, wiiReverseAxes, None,
                                 extraOptions)
Exemple #30
0
def main(args):
    playersControllers = dict()
    # Read the controller configuration
    playersControllers = controllers.loadControllerConfig(
        args.p1index, args.p1guid, args.p1name, args.p1devicepath,
        args.p1nbaxes, args.p2index, args.p2guid, args.p2name,
        args.p2devicepath, args.p2nbaxes, args.p3index, args.p3guid,
        args.p3name, args.p3devicepath, args.p3nbaxes, args.p4index,
        args.p4guid, args.p4name, args.p4devicepath, args.p4nbaxes,
        args.p5index, args.p5guid, args.p5name, args.p5devicepath,
        args.p5nbaxes)
    # find the system to run
    systemName = args.system
    eslog.log("Running system: {}".format(systemName))
    system = Emulator(systemName, args.rom)

    if args.emulator is not None:
        system.config["emulator"] = args.emulator
    if args.core is not None:
        system.config["core"] = args.core

    eslog.debug("Settings: {}".format(system.config))
    if "emulator" in system.config and "core" in system.config:
        eslog.log("emulator: {}, core: {}".format(system.config["emulator"],
                                                  system.config["core"]))
    else:
        if "emulator" in system.config:
            eslog.log("emulator: {}".format(system.config["emulator"]))

    # the resolution must be changed before configuration while the configuration may depend on it (ie bezels)
    wantedGameMode = generators[system.config['emulator']].getResolutionMode(
        system.config)
    systemMode = videoMode.getCurrentMode()
    resolutionChanged = False
    exitCode = -1
    try:
        eslog.log("current video mode: {}".format(systemMode))
        eslog.log("wanted video mode: {}".format(wantedGameMode))
        if wantedGameMode != 'default' and wantedGameMode != systemMode:
            videoMode.changeMode(wantedGameMode)
            resolutionChanged = True
        gameResolution = videoMode.getCurrentResolution()
        eslog.log("resolution: {}x{}".format(str(gameResolution["width"]),
                                             str(gameResolution["height"])))

        # savedir: create the save directory if not already done
        dirname = os.path.join(batoceraFiles.savesDir, system.name)
        if not os.path.exists(dirname):
            os.makedirs(dirname)

        # core
        effectiveCore = ""
        if "core" in system.config and system.config["core"] is not None:
            effectiveCore = system.config["core"]
        effectiveRom = ""
        if args.rom is not None:
            effectiveRom = args.rom

        # network options
        if args.netplaymode is not None:
            system.config["netplay.mode"] = args.netplaymode
        if args.netplayip is not None:
            system.config["netplay.server.ip"] = args.netplayip
        if args.netplayport is not None:
            system.config["netplay.server.port"] = args.netplayport

        # run a script before emulator starts
        callExternalScripts("/userdata/system/scripts", "gameStart", [
            systemName, system.config['emulator'], effectiveCore, effectiveRom
        ])

        # run the emulator
        exitCode = runCommand(generators[system.config['emulator']].generate(
            system, args.rom, playersControllers, gameResolution))

        # run a script after emulator shuts down
        callExternalScripts("/userdata/system/scripts", "gameStop", [
            systemName, system.config['emulator'], effectiveCore, effectiveRom
        ])

    finally:
        # always restore the resolution
        if resolutionChanged:
            try:
                videoMode.changeMode(systemMode)
            except Exception:
                pass  # don't fail
    # exit
    return exitCode