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)
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)
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'
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
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)
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)
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
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")
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)
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
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)
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
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'})
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)
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)
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