Beispiel #1
0
    def __init__(self, fsgs):
        super().__init__(fsgs)
        if self.options[Option.DOS_EMULATOR] == "dosbox":
            self.emulator.name = "dosbox"
        elif self.options[Option.DOS_EMULATOR] == "dosbox-svn":
            self.emulator.name = "dosbox-svn"
        else:
            self.emulator.name = "dosbox-fs"

        self.save_handler = SaveHandler(self.fsgc, options=self.options)

        # Right now G-SYNC only works fine with 60Hz modes. There's stuttering
        # when DOSBox outputs 70 fps. Edit: The problem is that G-SYNC is
        # capped to monitors selected refresh rate.
        if self.screen_refresh_rate() < 70.0:
            print("[VIDEO] Screen refresh rate is < 70.0, disabling G-SYNC")
            self.set_allow_gsync(False)

        # self.ultrasnd_drive = None
        self.drives_dir = self.temp_dir("drives")
        self.drives = []
Beispiel #2
0
    def __init__(self, fsgs):
        super().__init__(fsgs)
        if self.options[Option.DOS_EMULATOR] == "dosbox":
            self.emulator.name = "dosbox"
        elif self.options[Option.DOS_EMULATOR] == "dosbox-svn":
            self.emulator.name = "dosbox-svn"
        else:
            self.emulator.name = "dosbox-fs"

        self.save_handler = SaveHandler(self.fsgc, options=self.options)

        # Right now G-SYNC only works fine with 60Hz modes. There's stuttering
        # when DOSBox outputs 70 fps. Edit: The problem is that G-SYNC is
        # capped to monitors selected refresh rate.
        if self.screen_refresh_rate() < 70.0:
            print("[VIDEO] Screen refresh rate is < 70.0, disabling G-SYNC")
            self.set_allow_gsync(False)

        # self.ultrasnd_drive = None
        self.drives_dir = self.temp_dir("drives")
        self.drives = []
Beispiel #3
0
class DosBoxDosDriver(GameDriver):
    def __init__(self, fsgs):
        super().__init__(fsgs)
        if self.options[Option.DOS_EMULATOR] == "dosbox":
            self.emulator.name = "dosbox"
        elif self.options[Option.DOS_EMULATOR] == "dosbox-svn":
            self.emulator.name = "dosbox-svn"
        else:
            self.emulator.name = "dosbox-fs"

        self.save_handler = SaveHandler(self.fsgc, options=self.options)

        # Right now G-SYNC only works fine with 60Hz modes. There's stuttering
        # when DOSBox outputs 70 fps. Edit: The problem is that G-SYNC is
        # capped to monitors selected refresh rate.
        if self.screen_refresh_rate() < 70.0:
            print("[VIDEO] Screen refresh rate is < 70.0, disabling G-SYNC")
            self.set_allow_gsync(False)

        # self.ultrasnd_drive = None
        self.drives_dir = self.temp_dir("drives")
        self.drives = []

    def __del__(self):
        print("DosBoxDosDriver.__del__")

    def prepare(self):
        config_file = self.temp_file("dosbox.cfg").path
        self.prepare_media()
        with open(config_file, "w", encoding="UTF-8") as f:
            self.configure(f)
        self.emulator.args.extend(["-conf", config_file])

        # FIXME: Move to game driver?
        if self.options[Option.VIEWPORT]:
            self.emulator.env["FSGS_VIEWPORT"] = self.options[Option.VIEWPORT]

        # Must run after game hard drives have been unpacked
        for drive, drive_path in self.drives:
            assert drive in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            # print(drive)
            # print(drive_path)
            self.save_handler.register_changes(
                drive_path, os.path.join(self.save_handler.save_dir(), drive))
        self.save_handler.prepare()

    def finish(self):
        self.save_handler.finish()

    def prepare_media(self):
        file_list = json.loads(self.options[Option.FILE_LIST])
        self.unpack_game_hard_drives(file_list)

        if self.options["cue_sheets"]:
            cue_sheets = json.loads(self.options["cue_sheets"])
            for cue_sheet in cue_sheets:
                with open(
                        os.path.join(self.drives_dir.path, cue_sheet["name"]),
                        "wb") as f:
                    f.write(cue_sheet["data"].encode("UTF-8"))

    def unpack_game_hard_drives(self, file_list):
        drives_added = set()
        dir_path = self.drives_dir.path
        for file_entry in file_list:
            # if self.stop_flag:
            #     return

            name = file_entry["name"]
            name = name.upper()

            drives_added.add(name[0])

            # Extract relative path and convert each path component
            # to host file name (where needed).

            rel_path = name
            print("rel_path", rel_path)
            rel_parts = rel_path.split("/")
            # for i, part in enumerate(rel_parts):
            #     # part can be blank if rel_parts is a directory
            #     # (ending with /)
            #     if part:
            #         rel_parts[i] = amiga_filename_to_host_filename(part)
            rel_path = "/".join(rel_parts)

            dst_file = os.path.join(dir_path, rel_path)
            print(repr(dst_file))
            if name.endswith("/"):
                os.makedirs(str_path(dst_file))
                continue
            sha1 = file_entry["sha1"]
            src_file = self.fsgc.file.find_by_sha1(sha1)
            if not os.path.exists(os.path.dirname(dst_file)):
                os.makedirs(os.path.dirname(dst_file))
            stream = self.fsgc.file.open(src_file)
            # archive = Archive(src_file)
            # f = archive.open(src_file)
            data = stream.read()
            assert hashlib.sha1(data).hexdigest() == sha1

            with open(dst_file, "wb") as out_file:
                out_file.write(data)
            if dst_file.endswith(".CUE"):
                with open(dst_file, "r", encoding="ISO-8859-1") as f:
                    data = f.read()
                data = data.upper()
                with open(dst_file, "w", encoding="ISO-8859-1") as f:
                    f.write(data)

        for drive in sorted(drives_added):
            self.drives.append((drive, os.path.join(dir_path, drive)))

    def configure(self, f):
        f.write("# Automatically generated by FSGS\n")
        f.write("\n[sdl]\n")
        f.write("output=opengl\n")

        if self.use_fullscreen():
            f.write("fullscreen=true\n")
        else:
            f.write("fullscreen=false\n")
        f.write("fullresolution={0}x{1}\n".format(*self.screen_size()))

        f.write("\n[render]\n")
        f.write("frameskip=0\n")
        f.write("aspect=true\n")
        # if self.use_stretching():
        #     # This option does not stretch, it merely does not correct
        #     # aspect for non-square pixels resolutions, e.g. 320x200.
        #     # f.write("aspect=false\n")
        #     # This custom environment variable however, does cause stretching.
        #     self.env["FSGS_STRETCH"] = "1"
        # else:
        #     # f.write("aspect=true\n")
        #     self.env["FSGS_STRETCH"] = "0"

        if self.effect() == self.SCALE2X_EFFECT:
            scaler = "advmame2x"
        elif self.effect() == self.HQ2X_EFFECT:
            scaler = "hq2x"
        # elif self.effect() == self.CRT_EFFECT:
        #     scaler = "rgb2x"  # Looks ugly!
        else:
            scaler = "normal2x"

        if scaler:
            f.write("scaler={}\n".format(scaler))

        f.write("\n[cpu]\n")
        cpu_core = "auto"
        if self.options[Option.DOSBOX_CPU_CORE]:
            cpu_core = self.options[Option.DOSBOX_CPU_CORE]
            cpu_core = cpu_core.lower().strip()
        if System.windows and System.x86_64:
            # Dynamic core crashes on Windows x86-64
            print("[DOS] Forcing normal cpu core on Windows x86-64")
            if cpu_core in ["auto", "dynamic"]:
                cpu_core = "normal"
        f.write("core={0}\n".format(cpu_core))
        cpu_cycles = "auto"
        if self.options[Option.DOSBOX_CPU_CPUTYPE]:
            f.write("cputype={0}\n".format(
                self.options[Option.DOSBOX_CPU_CPUTYPE]))
        if self.options[Option.DOSBOX_CPU_CYCLES]:
            cpu_cycles = self.options[Option.DOSBOX_CPU_CYCLES]
            if cpu_cycles.startswith("max "):
                pass
            elif cpu_cycles in ["auto", "max"]:
                pass
            else:
                cpu_cycles = "fixed " + cpu_cycles
        f.write("cycles={0}\n".format(cpu_cycles))

        f.write("\n[dosbox]\n")
        if self.options[Option.DOSBOX_MACHINE]:
            f.write("machine={}\n".format(self.options[Option.DOSBOX_MACHINE]))
        if self.options[Option.DOSBOX_MEMSIZE]:
            f.write("memsize={}\n".format(self.options[Option.DOSBOX_MEMSIZE]))

        self.configure_gus(f)
        self.configure_midi(f)
        self.configure_sblaster(f)

        f.write("\n[autoexec]\n")
        if self.options[Option.AUTO_LOAD] != "0":
            f.write("@ECHO OFF\n")
        # for drive, drive_path in self.drives:
        #     pass
        for name in os.listdir(self.drives_dir.path):
            if name in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
                p = os.path.join(self.drives_dir.path, name, "CD", "IMAGE.CUE")
                if os.path.exists(p):
                    f.write('IMGMOUNT {0} "{1}" -t iso\n'.format(name, p))
                    continue
                p = os.path.join(self.drives_dir.path, name, "CD", "IMAGE.ISO")
                if os.path.exists(p):
                    f.write('IMGMOUNT {0} "{1}" -t iso\n'.format(name, p))
                    continue
                if name in "DEF":
                    f.write('MOUNT {0} "{1}" -t cdrom\n'.format(
                        name, os.path.join(self.drives_dir.path, name)))
                    continue
                f.write('MOUNT {0} "{1}"\n'.format(
                    name, os.path.join(self.drives_dir.path, name)))
        f.write("C:\n")
        f.write("CLS\n")
        # for i in range(25):
        #     f.write("echo.\n")
        if self.options[Option.AUTO_LOAD] == "0":
            f.write("@echo Auto-load is disabled. The following is the "
                    "normal commands to start this game:\n")
            f.write("@echo.\n")
        for command in self.options[Option.COMMAND].split(";"):
            command = command.strip()
            command = command.replace("$DRIVES", self.drives_dir.path)
            if not self.options[Option.AUTO_LOAD] == "0" or \
                    command.lower().split(" ")[0].strip("@") in [
                    "imgmount", "mount"]:
                f.write("{0}\n".format(command))
            else:
                f.write("@echo {0}\n".format(command))
        if self.options[Option.AUTO_LOAD] == "0":
            f.write("@echo.\n")
        else:
            if not self.options[Option.AUTO_QUIT] == "0":
                f.write("exit\n")

        if System.windows:
            # We don't want to open the separate console window on windows.
            self.emulator.args.append("-noconsole")

    def configure_gus(self, f):
        f.write("\n[gus]\n")
        if self.options[Option.DOSBOX_GUS_GUS].lower() == "true":
            f.write("gus=true\n")
            f.write("ultradir=U:\\ULTRASND\n")
            ultrasnd_drive = os.path.join(self.drives_dir.path, "U")
            source_dir = os.path.join(FSGSDirectories.get_data_dir(),
                                      "ULTRASND")
            dest_dir = os.path.join(ultrasnd_drive, "ULTRASND")
            if os.path.exists(source_dir):
                shutil.copytree(source_dir, dest_dir)
            else:
                # FIXME: ADD ULTRASND WARNING
                pass

    def configure_midi(self, f):
        f.write("\n[midi]\n")
        if True:
            f.write("mpu401=intelligent\n")
            # f.write("mpu401=uart\n")
        if System.windows:
            pass
        elif System.macos:
            pass
        else:
            f.write("mididevice=alsa\n")
            f.write("midiconfig=128:0\n")

    def configure_sblaster(self, f):
        f.write("\n[sblaster]\n")
        if self.options[Option.DOSBOX_SBLASTER_SBTYPE]:
            f.write("sbtype={}\n".format(
                self.options[Option.DOSBOX_SBLASTER_SBTYPE]))
        if self.options[Option.DOSBOX_SBLASTER_SBBASE]:
            f.write("sbbase={}\n".format(
                self.options[Option.DOSBOX_SBLASTER_SBBASE]))
        if self.options[Option.DOSBOX_SBLASTER_IRQ]:
            f.write("irq={}\n".format(
                self.options[Option.DOSBOX_SBLASTER_IRQ]))
        if self.options[Option.DOSBOX_SBLASTER_OPLRATE]:
            f.write("oplrate={}\n".format(
                self.options[Option.DOSBOX_SBLASTER_OPLRATE]))
    def prepare(self):
        print("FSUAEAmigaDriver.prepare")

        # self.temp_dir = self.fsgc.temp_dir("amiga")

        # self.change_handler = GameChangeHandler(self.temp_dir)

        # self.firmware_dir = self.prepare_firmware("Amiga Firmware")
        # config = self.fsgc.config.copy()

        model = self.options[Option.AMIGA_MODEL]
        if model.startswith("CD32"):
            platform = "CD32"
        elif model == "CDTV":
            platform = "CDTV"
        else:
            platform = "Amiga"
        # name = Settings.get("config_name")
        # name = self.fsgc.game.name

        # uuid = Config.get("x_game_uuid")
        # uuid = None

        from fsgs.saves import SaveHandler
        save_state_handler = SaveHandler(self.fsgc, self.get_name(), platform)

        print("[INPUT] joystick_port_1", self.options["joystick_port_1"], "->",
              self.ports[0].device_id or "none")
        print("[INPUT] joystick_port_0", self.options["joystick_port_0"], "->",
              self.ports[1].device_id or "none")
        self.options["joystick_port_1"] = self.ports[0].device_id or "none"
        self.options["joystick_port_0"] = self.ports[1].device_id or "none"

        self.launch_handler = LaunchHandler(self.fsgc,
                                            self.get_name(),
                                            self.options,
                                            save_state_handler,
                                            temp_dir=self.cwd.path)

        # self.change_handler.init(self.fsgc.get_game_state_dir(),
        #         ignore=["*.uss", "*.sdf"])

        # self.launch_handler.config["joystick_port_0"] = \
        #         self.inputs[1].device_id
        # self.launch_handler.config["joystick_port_1"] = \
        #         self.inputs[0].device_id

        if self.use_fullscreen():
            self.launch_handler.config["fullscreen"] = "1"
            if not self.launch_handler.config.get("fullscreen_mode", ""):
                # Check if fullscreen mode is overridden by temporary setting.
                if Settings.instance()["__fullscreen_mode"]:
                    self.launch_handler.config["fullscreen_mode"] = \
                        Settings.instance()["__fullscreen_mode"]
            if Settings.instance()["__arcade"]:
                # Remove window border when launched from FS-UAE Arcade in
                # order to reduce flickering
                self.launch_handler.config["window_border"] = "0"
                # Set fade out duration to 500, if not already specified.
                if not self.launch_handler.config.get("fade_out_duration", ""):
                    self.launch_handler.config["fade_out_duration"] = "500"
        else:
            self.launch_handler.config["fullscreen"] = "0"

        self.launch_handler.prepare()
Beispiel #5
0
    def prepare(self):
        print("FSUAEAmigaDriver.prepare")

        if not self.options["joystick_port_0_mode"]:
            self.options["joystick_port_0_mode"] = "mouse"
        if not self.options["joystick_port_1_mode"]:
            if self.options["amiga_model"].startswith("CD32"):
                self.options["joystick_port_1_mode"] = "cd32 gamepad"
            else:
                self.options["joystick_port_1_mode"] = "joystick"
        if not self.options["joystick_port_2_mode"]:
            self.options["joystick_port_2_mode"] = "none"
        if not self.options["joystick_port_3_mode"]:
            self.options["joystick_port_3_mode"] = "none"

        from launcher.devicemanager import DeviceManager

        devices = DeviceManager.get_devices_for_ports(self.options)
        for port in range(4):
            key = "joystick_port_{0}".format(port)
            if not self.options[key]:
                # key not set, use calculated default value
                self.options[key] = devices[port].id

        for remove_key in [
                "database_username",
                "database_password",
                "database_username",
                "database_email",
                "database_auth",
                "device_id",
        ]:
            if remove_key in self.options:
                del self.options[remove_key]

        # overwrite netplay config

        if self.options["__netplay_host"]:
            self.options["netplay_server"] = self.options["__netplay_host"]
        if self.options["__netplay_password"]:
            self.options["netplay_password"] = self.options[
                "__netplay_password"]
        if self.options["__netplay_port"]:
            self.options["netplay_port"] = self.options["__netplay_port"]

        # copy actual kickstart options from x_ options

        self.options["kickstart_file"] = self.options["x_kickstart_file"]
        self.options["kickstart_ext_file"] = self.options[
            "x_kickstart_ext_file"]

        if not self.options["kickstart_file"]:
            # Warning will have been shown on the status bar
            self.options["kickstart_file"] = "internal"

        # Copy default configuration values from model defaults. The main
        # purpose of this is to let the launch code know about implied defaults
        # so it can for example configure correct ROM files for expansions.

        model_config = Amiga.get_current_config(self.options)
        for key, value in model_config["defaults"].items():
            if not self.options[key]:
                self.options[key] = value

        # make sure FS-UAE does not load other config files (Host.fs-uae)
        self.options["end_config"] = "1"
        # Make FS-UAE check that version matches (except for development)
        if VERSION != "9.8.7dummy":
            self.options[Option.EXPECT_VERSION] = VERSION

        if self.options["__netplay_game"]:
            print("\nfixing config for netplay game")
            for key in [x for x in config.keys() if x.startswith("uae_")]:
                print("* removing option", key)
                del self.options[key]

        # self.temp_dir = self.fsgc.temp_dir("amiga")

        # self.change_handler = GameChangeHandler(self.temp_dir)

        # self.firmware_dir = self.prepare_firmware("Amiga Firmware")
        # config = self.fsgc.config.copy()

        model = self.options[Option.AMIGA_MODEL]
        if model.startswith("CD32"):
            platform = "CD32"
        elif model == "CDTV":
            platform = "CDTV"
        else:
            platform = "Amiga"
        # name = Settings.get("config_name")
        # name = self.fsgc.game.name

        # uuid = Config.get("x_game_uuid")
        # uuid = None

        from fsgs.saves import SaveHandler

        # save_state_handler = SaveHandler(self.fsgc, self.get_name(), platform)
        save_state_handler = SaveHandler(
            self.fsgc,
            app.settings.get("config_name"),
            platform,
            options=self.options,
        )

        print(
            "[INPUT] joystick_port_1",
            self.options["joystick_port_1"],
            "->",
            self.ports[0].device_id or "none",
        )
        print(
            "[INPUT] joystick_port_0",
            self.options["joystick_port_0"],
            "->",
            self.ports[1].device_id or "none",
        )
        # self.options["joystick_port_1"] = self.ports[0].device_id or "none"
        # self.options["joystick_port_0"] = self.ports[1].device_id or "none"

        self.launch_handler = LaunchHandler(
            self.fsgc,
            self.get_name(),
            self.options,
            save_state_handler,
            temp_dir=self.cwd.path,
        )

        # self.change_handler.init(self.fsgc.get_game_state_dir(),
        #         ignore=["*.uss", "*.sdf"])

        # self.launch_handler.config["joystick_port_0"] = \
        #         self.inputs[1].device_id
        # self.launch_handler.config["joystick_port_1"] = \
        #         self.inputs[0].device_id

        if self.use_fullscreen():
            self.launch_handler.config["fullscreen"] = "1"
            if not self.launch_handler.config.get("fullscreen_mode", ""):
                # Check if fullscreen mode is overridden by temporary setting.
                if Settings.instance()["__fullscreen_mode"]:
                    self.launch_handler.config[
                        "fullscreen_mode"] = Settings.instance(
                        )["__fullscreen_mode"]
            if Settings.instance()["__arcade"]:
                # Remove window border when launched from FS-UAE Arcade in
                # order to reduce flickering
                self.launch_handler.config["window_border"] = "0"
                # Set fade out duration to 500, if not already specified.
                if not self.launch_handler.config.get("fade_out_duration", ""):
                    self.launch_handler.config["fade_out_duration"] = "500"
        else:
            self.launch_handler.config["fullscreen"] = "0"

        self.launch_handler.prepare()

        config = self.launch_handler.create_config()
        config_file = self.temp_file("config.fs-uae").path
        with open(config_file, "w", encoding="UTF-8") as f:
            for line in config:
                print(line)
                f.write(line + "\n")
        self.emulator.args.extend([config_file])
Beispiel #6
0
    def start_local_game_amiga(cls):
        # make sure x_kickstart_file is initialized
        LauncherConfig.set_kickstart_from_model()

        # if not Config.get("x_kickstart_file"):  # or not \
        #     #  os.path.exists(Config.get("kickstart_file")):
        #     fsui.show_error(
        #         gettext("No kickstart found for this model. Use the 'Import "
        #                 "Kickstarts' function from the menu."))
        #     return
        cs = Amiga.get_model_config(
            LauncherConfig.get("amiga_model"))["ext_roms"]
        if len(cs) > 0:
            # extended kickstart ROM is needed
            if not LauncherConfig.get("x_kickstart_ext_file"):
                fsui.show_error(
                    gettext("No extended kickstart found for this model. "
                            "Try 'scan' function."))
                return

        config = LauncherConfig.copy()
        prepared_config = cls.prepare_config(config)

        model = LauncherConfig.get("amiga_model")
        if model.startswith("CD32"):
            platform = "CD32"
        elif model == "CDTV":
            platform = "CDTV"
        else:
            platform = "Amiga"
        name = LauncherSettings.get("config_name")
        uuid = LauncherConfig.get("x_game_uuid")

        from fsgs.saves import SaveHandler
        save_state_handler = SaveHandler(fsgs, name, platform, uuid)

        from fsgs.amiga.launchhandler import LaunchHandler
        launch_handler = LaunchHandler(fsgs, name, prepared_config,
                                       save_state_handler)

        from .ui.launcherwindow import LauncherWindow
        task = AmigaLaunchTask(launch_handler)
        # dialog = LaunchDialog(MainWindow.instance, launch_handler)
        dialog = LaunchDialog(LauncherWindow.current(),
                              gettext("Launching FS-UAE"), task)
        dialog.show()

        def on_show_license_information(license_text):
            unused(license_text)
            # FIXME: don't depend on wx here
            # noinspection PyUnresolvedReferences
            # import wx
            # license_dialog = wx.MessageDialog(
            #     dialog, license_text, _("Terms of Use"),
            #     wx.OK | wx.CANCEL | wx.CENTRE)
            # license_dialog.CenterOnParent()
            # result = license_dialog.ShowModal()
            # return result == wx.ID_OK
            # FIXME
            return True

        fsgs.file.on_show_license_information = on_show_license_information

        LauncherConfig.set("__running", "1")
        task.start()
Beispiel #7
0
class DosBoxDosDriver(GameDriver):
    def __init__(self, fsgs):
        super().__init__(fsgs)
        if self.options[Option.DOS_EMULATOR] == "dosbox":
            self.emulator.name = "dosbox"
        elif self.options[Option.DOS_EMULATOR] == "dosbox-svn":
            self.emulator.name = "dosbox-svn"
        else:
            self.emulator.name = "dosbox-fs"

        self.save_handler = SaveHandler(self.fsgc, options=self.options)

        # Right now G-SYNC only works fine with 60Hz modes. There's stuttering
        # when DOSBox outputs 70 fps. Edit: The problem is that G-SYNC is
        # capped to monitors selected refresh rate.
        if self.screen_refresh_rate() < 70.0:
            print("[VIDEO] Screen refresh rate is < 70.0, disabling G-SYNC")
            self.set_allow_gsync(False)

        # self.ultrasnd_drive = None
        self.drives_dir = self.temp_dir("drives")
        self.drives = []

    def __del__(self):
        print("DosBoxDosDriver.__del__")

    def prepare(self):
        config_file = self.temp_file("dosbox.cfg").path
        self.prepare_media()
        with open(config_file, "w", encoding="UTF-8") as f:
            self.configure(f)
        self.emulator.args.extend(["-conf", config_file])

        # FIXME: Move to game driver?
        if self.options[Option.VIEWPORT]:
            self.emulator.env["FSGS_VIEWPORT"] = self.options[Option.VIEWPORT]

        # Must run after game hard drives have been unpacked
        for drive, drive_path in self.drives:
            assert drive in "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
            # print(drive)
            # print(drive_path)
            self.save_handler.register_changes(
                drive_path, os.path.join(self.save_handler.save_dir(), drive)
            )
        self.save_handler.prepare()

    def finish(self):
        self.save_handler.finish()

    def prepare_media(self):
        file_list = json.loads(self.options[Option.FILE_LIST])
        self.unpack_game_hard_drives(file_list)

        if self.options["cue_sheets"]:
            cue_sheets = json.loads(self.options["cue_sheets"])
            for cue_sheet in cue_sheets:
                with open(
                    os.path.join(self.drives_dir.path, cue_sheet["name"]), "wb"
                ) as f:
                    f.write(cue_sheet["data"].encode("UTF-8"))

    def unpack_game_hard_drives(self, file_list):
        drives_added = set()
        dir_path = self.drives_dir.path
        for file_entry in file_list:
            # if self.stop_flag:
            #     return

            name = file_entry["name"]
            name = name.upper()

            drives_added.add(name[0])

            # Extract relative path and convert each path component
            # to host file name (where needed).

            rel_path = name
            print("rel_path", rel_path)
            rel_parts = rel_path.split("/")
            # for i, part in enumerate(rel_parts):
            #     # part can be blank if rel_parts is a directory
            #     # (ending with /)
            #     if part:
            #         rel_parts[i] = amiga_filename_to_host_filename(part)
            rel_path = "/".join(rel_parts)

            dst_file = os.path.join(dir_path, rel_path)
            print(repr(dst_file))
            if name.endswith("/"):
                os.makedirs(str_path(dst_file))
                continue
            sha1 = file_entry["sha1"]
            src_file = self.fsgc.file.find_by_sha1(sha1)
            if not os.path.exists(os.path.dirname(dst_file)):
                os.makedirs(os.path.dirname(dst_file))
            stream = self.fsgc.file.open(src_file)
            # archive = Archive(src_file)
            # f = archive.open(src_file)
            data = stream.read()
            assert hashlib.sha1(data).hexdigest() == sha1

            with open(dst_file, "wb") as out_file:
                out_file.write(data)
            if dst_file.endswith(".CUE"):
                with open(dst_file, "r", encoding="ISO-8859-1") as f:
                    data = f.read()
                data = data.upper()
                with open(dst_file, "w", encoding="ISO-8859-1") as f:
                    f.write(data)

        for drive in sorted(drives_added):
            self.drives.append((drive, os.path.join(dir_path, drive)))

    def configure(self, f):
        f.write("# Automatically generated by FSGS\n")
        f.write("\n[sdl]\n")
        f.write("output=opengl\n")

        if self.use_fullscreen():
            f.write("fullscreen=true\n")
        else:
            f.write("fullscreen=false\n")
        f.write("fullresolution={0}x{1}\n".format(*self.screen_size()))

        f.write("\n[render]\n")
        f.write("frameskip=0\n")
        f.write("aspect=true\n")
        # if self.use_stretching():
        #     # This option does not stretch, it merely does not correct
        #     # aspect for non-square pixels resolutions, e.g. 320x200.
        #     # f.write("aspect=false\n")
        #     # This custom environment variable however, does cause stretching.
        #     self.env["FSGS_STRETCH"] = "1"
        # else:
        #     # f.write("aspect=true\n")
        #     self.env["FSGS_STRETCH"] = "0"

        if self.effect() == self.SCALE2X_EFFECT:
            scaler = "advmame2x"
        elif self.effect() == self.HQ2X_EFFECT:
            scaler = "hq2x"
        # elif self.effect() == self.CRT_EFFECT:
        #     scaler = "rgb2x"  # Looks ugly!
        else:
            scaler = "normal2x"

        if scaler:
            f.write("scaler={}\n".format(scaler))

        f.write("\n[cpu]\n")
        cpu_core = "auto"
        if self.options[Option.DOSBOX_CPU_CORE]:
            cpu_core = self.options[Option.DOSBOX_CPU_CORE]
            cpu_core = cpu_core.lower().strip()
        if System.windows and System.x86_64:
            # Dynamic core crashes on Windows x86-64
            print("[DOS] Forcing normal cpu core on Windows x86-64")
            if cpu_core in ["auto", "dynamic"]:
                cpu_core = "normal"
        f.write("core={0}\n".format(cpu_core))
        cpu_cycles = "auto"
        if self.options[Option.DOSBOX_CPU_CPUTYPE]:
            f.write(
                "cputype={0}\n".format(self.options[Option.DOSBOX_CPU_CPUTYPE])
            )
        if self.options[Option.DOSBOX_CPU_CYCLES]:
            cpu_cycles = self.options[Option.DOSBOX_CPU_CYCLES]
            if cpu_cycles.startswith("max "):
                pass
            elif cpu_cycles in ["auto", "max"]:
                pass
            else:
                cpu_cycles = "fixed " + cpu_cycles
        f.write("cycles={0}\n".format(cpu_cycles))

        f.write("\n[dosbox]\n")
        if self.options[Option.DOSBOX_MACHINE]:
            f.write("machine={}\n".format(self.options[Option.DOSBOX_MACHINE]))
        if self.options[Option.DOSBOX_MEMSIZE]:
            f.write("memsize={}\n".format(self.options[Option.DOSBOX_MEMSIZE]))

        self.configure_gus(f)
        self.configure_midi(f)
        self.configure_sblaster(f)

        f.write("\n[autoexec]\n")
        if self.options[Option.AUTO_LOAD] != "0":
            f.write("@ECHO OFF\n")
        # for drive, drive_path in self.drives:
        #     pass
        for name in os.listdir(self.drives_dir.path):
            if name in "ABCDEFGHIJKLMNOPQRSTUVWXYZ":
                p = os.path.join(self.drives_dir.path, name, "CD", "IMAGE.CUE")
                if os.path.exists(p):
                    f.write('IMGMOUNT {0} "{1}" -t iso\n'.format(name, p))
                    continue
                p = os.path.join(self.drives_dir.path, name, "CD", "IMAGE.ISO")
                if os.path.exists(p):
                    f.write('IMGMOUNT {0} "{1}" -t iso\n'.format(name, p))
                    continue
                if name in "DEF":
                    f.write(
                        'MOUNT {0} "{1}" -t cdrom\n'.format(
                            name, os.path.join(self.drives_dir.path, name)
                        )
                    )
                    continue
                f.write(
                    'MOUNT {0} "{1}"\n'.format(
                        name, os.path.join(self.drives_dir.path, name)
                    )
                )
        f.write("C:\n")
        f.write("CLS\n")
        # for i in range(25):
        #     f.write("echo.\n")
        if self.options[Option.AUTO_LOAD] == "0":
            f.write(
                "@echo Auto-load is disabled. The following is the "
                "normal commands to start this game:\n"
            )
            f.write("@echo.\n")
        for command in self.options[Option.COMMAND].split(";"):
            command = command.strip()
            command = command.replace("$DRIVES", self.drives_dir.path)
            if not self.options[
                Option.AUTO_LOAD
            ] == "0" or command.lower().split(" ")[0].strip("@") in [
                "imgmount",
                "mount",
            ]:
                f.write("{0}\n".format(command))
            else:
                f.write("@echo {0}\n".format(command))
        if self.options[Option.AUTO_LOAD] == "0":
            f.write("@echo.\n")
        else:
            if not self.options[Option.AUTO_QUIT] == "0":
                f.write("exit\n")

        if System.windows:
            # We don't want to open the separate console window on windows.
            self.emulator.args.append("-noconsole")

    def configure_gus(self, f):
        f.write("\n[gus]\n")
        if self.options[Option.DOSBOX_GUS_GUS].lower() == "true":
            f.write("gus=true\n")
            f.write("ultradir=U:\\ULTRASND\n")
            ultrasnd_drive = os.path.join(self.drives_dir.path, "U")
            source_dir = os.path.join(
                FSGSDirectories.get_data_dir(), "ULTRASND"
            )
            dest_dir = os.path.join(ultrasnd_drive, "ULTRASND")
            if os.path.exists(source_dir):
                shutil.copytree(source_dir, dest_dir)
            else:
                # FIXME: ADD ULTRASND WARNING
                pass

    def configure_midi(self, f):
        f.write("\n[midi]\n")
        if True:
            f.write("mpu401=intelligent\n")
            # f.write("mpu401=uart\n")
        if System.windows:
            pass
        elif System.macos:
            pass
        else:
            f.write("mididevice=alsa\n")
            f.write("midiconfig=128:0\n")

    def configure_sblaster(self, f):
        f.write("\n[sblaster]\n")
        if self.options[Option.DOSBOX_SBLASTER_SBTYPE]:
            f.write(
                "sbtype={}\n".format(
                    self.options[Option.DOSBOX_SBLASTER_SBTYPE]
                )
            )
        if self.options[Option.DOSBOX_SBLASTER_SBBASE]:
            f.write(
                "sbbase={}\n".format(
                    self.options[Option.DOSBOX_SBLASTER_SBBASE]
                )
            )
        if self.options[Option.DOSBOX_SBLASTER_IRQ]:
            f.write(
                "irq={}\n".format(self.options[Option.DOSBOX_SBLASTER_IRQ])
            )
        if self.options[Option.DOSBOX_SBLASTER_OPLRATE]:
            f.write(
                "oplrate={}\n".format(
                    self.options[Option.DOSBOX_SBLASTER_OPLRATE]
                )
            )