Exemplo n.º 1
0
    def synchronize(self):
        if not is_locker_enabled():
            return
        if "locker" not in self.context.meta:
            # We haven't looked up synchronization information from the server,
            # that probably means we didn't want to synchronize with the
            # server now, therefore we just return.
            return
        if self.stop_check():
            return
        database = LockerDatabase.instance()
        sync_version = database.get_sync_version()
        if sync_version == self.context.meta["locker"]["sync"]:
            print("[SYNC] Locker data already up to date")
            return

        self.set_status(gettext("Fetching locker data..."))
        data = self.fetch_data("/api/locker-sync/1")
        assert len(data) % 20 == 0
        self.set_status(gettext("Updating locker data..."))
        database.clear()
        k = 0
        while k < len(data):
            sha1_bytes = data[k:k + 20]
            database.add_sha1_binary(sha1_bytes)
            k += 20

        database.set_sync_version(self.context.meta["locker"]["sync"])
        self.set_status(gettext("Committing locker data..."))
        self.update_file_database_timestamps()
        database.commit()
Exemplo n.º 2
0
    def synchronize(self):
        if not is_locker_enabled():
            return
        if "locker" not in self.context.meta:
            # We haven't looked up synchronization information from the server,
            # that probably means we didn't want to synchronize with the
            # server now, therefore we just return.
            return
        if self.stop_check():
            return
        database = LockerDatabase.instance()
        sync_version = database.get_sync_version()
        if sync_version == self.context.meta["locker"]["sync"]:
            print("[SYNC] Locker data already up to date")
            return

        self.set_status(gettext("Fetching locker data..."))
        data = self.fetch_data("/api/locker-sync/1")
        assert len(data) % 20 == 0
        self.set_status(gettext("Updating locker data..."))
        database.clear()
        k = 0
        while k < len(data):
            sha1_bytes = data[k : k + 20]
            database.add_sha1_binary(sha1_bytes)
            k += 20

        database.set_sync_version(self.context.meta["locker"]["sync"])
        self.set_status(gettext("Committing locker data..."))
        self.update_file_database_timestamps()
        database.commit()
Exemplo n.º 3
0
 def fetch_data(self, url):
     for i in range(10):
         try:
             return self.fetch_data_attempt(url)
         except Exception as e:
             print(e)
             sleep_time = 2.0 + i * 0.3
             # FIXME: change second {0} to {1}
             self.set_status(
                 gettext("Download failed (attempt {0}) - retrying in {0} "
                         "seconds").format(i + 1, int(sleep_time)))
             time.sleep(sleep_time)
             self.set_status(
                 gettext("Retrying last operation (attempt {0})").format(i +
                                                                         1))
     return self.fetch_data_attempt(url)
Exemplo n.º 4
0
 def fetch_data(self, url):
     for i in range(10):
         try:
             return self.fetch_data_attempt(url)
         except Exception as e:
             print(e)
             sleep_time = 2.0 + i * 0.3
             # FIXME: change second {0} to {1}
             self.set_status(
                 gettext("Download failed (attempt {0}) - retrying in {0} "
                         "seconds").format(i + 1, int(sleep_time)))
             time.sleep(sleep_time)
             self.set_status(
                 gettext("Retrying last operation (attempt {0})").format(
                     i + 1))
     return self.fetch_data_attempt(url)
Exemplo n.º 5
0
    def synchronize(self):
        if "game-database-version" not in self.context.meta:
            # we haven't looked up synchronization information from the server,
            # that probably means we didn't want to synchronize with the
            # server now, therefore we just return
            return

        self._synchronize()
        if self.stop_check():
            self.client.database.rollback()
        else:
            print("committing data")
            self.set_status(gettext("Updating database"),
                            gettext("Committing data..."))
            self.database.commit()
            print("done")
Exemplo n.º 6
0
 def synchronize(self):
     if self.stop_check():
         return
     if not app.settings["database_auth"]:
         # not logged in
         return
     self.set_status(gettext("Fetching synchronization information..."))
     self.context.meta = self.fetch_json("/api/sync")
Exemplo n.º 7
0
    def synchronize(self):
        if self.stop_check():
            return

        if "lists" not in self.context.meta:
            # Haven't looked up synchronization information from the server.
            return

        self.set_status(gettext("Updating game lists..."))

        database = Database.instance()
        cursor = database.cursor()
        cursor.execute("SELECT uuid, name, sync FROM game_list")
        # existing_lists = {}
        existing_syncs = {}
        for row in cursor:
            uuid, name, sync = row
            # existing_lists[uuid] = {
            #     "name": name,
            #     "sync": sync,
            # }
            existing_syncs[uuid] = sync
        # existing_syncs.sort()

        for list_uuid, list_info in self.context.meta["lists"].items():
            if list_info["sync"] == existing_syncs.get(list_uuid, None):
                print("[SYNC] List {} already synced".format(list_uuid))
            else:
                self.set_status(
                    gettext("Updating list '{0}'...".format(list_info["name"]))
                )
                self.synchronize_list(database, list_uuid, list_info)

        for existing_list_uuid in existing_syncs:
            for list_uuid in self.context.meta["lists"]:
                if list_uuid == existing_list_uuid:
                    break
            else:
                # this old list should be removed
                self.set_status(
                    gettext("Removing list {0}".format(existing_list_uuid))
                )
                self.remove_list(database, existing_list_uuid)

        database.commit()
Exemplo n.º 8
0
    def synchronize(self):
        if self.stop_check():
            return

        if not app.settings["database_auth"]:
            # not logged in
            return

        self.set_status(gettext("Fetching synchronization information..."))
        self.context.meta = self.fetch_json("/api/sync/1")
Exemplo n.º 9
0
    def synchronize(self):
        if "database" not in self.context.meta:
            # we haven't looked up synchronization information from the server,
            # that probably means we didn't want to synchronize with the
            # server now, therefore we just return
            return

        self._synchronize()
        if self.stop_check():
            self.client.database.rollback()
        else:
            print("committing data")
            self.set_status(gettext("Updating database"),
                            gettext("Committing data..."))
            self.database.commit()
            print("done")

        if os.environ.get("FSGS_WRITE_DAT_FILES", "") == "1":
            self.write_dat_file()
Exemplo n.º 10
0
    def prepare_hard_drives(self):
        print("LaunchHandler.prepare_hard_drives")
        current_task.set_progress(gettext("Preparing hard drives..."))
        # self.on_progress(gettext("Preparing hard drives..."))

        for i in range(0, 10):
            key = "hard_drive_{0}".format(i)
            src = self.config.get(key, "")
            dummy, ext = os.path.splitext(src)
            ext = ext.lower()

            if is_http_url(src):
                name = src.rsplit("/", 1)[-1]
                name = urllib.parse.unquote(name)
                self.on_progress(gettext("Downloading {0}...".format(name)))
                dest = os.path.join(self.temp_dir, name)
                Downloader.install_file_from_url(src, dest)
                src = dest
            elif src.startswith("hd://game/"):
                self.unpack_game_hard_drive(i, src)
                self.disable_save_states()
                return
            elif src.startswith("hd://template/workbench/"):
                self.prepare_workbench_hard_drive(i, src)
                self.disable_save_states()
                return
            elif src.startswith("hd://template/empty/"):
                self.prepare_empty_hard_drive(i, src)
                self.disable_save_states()
                return

            if ext in Archive.extensions:
                print("zipped hard drive", src)
                self.unpack_hard_drive(i, src)
                self.disable_save_states()

            elif src.endswith("HardDrive"):
                print("XML-described hard drive", src)
                self.unpack_hard_drive(i, src)
                self.disable_save_states()
            else:
                src = Paths.expand_path(src)
                self.config[key] = src
Exemplo n.º 11
0
 def fetch_json(self, url):
     for i in range(20):
         try:
             return self.fetch_json_attempt(url)
         except Exception as e:
             print(e)
             sleep_time = 2.0 + i * 0.3
             # FIXME: change second {0} to {1}
             self.set_status(gettext("Download failed (attempt {0}) - "
                                     "retrying in {1} seconds").format(
                 i + 1, int(sleep_time)))
             for _ in range(int(sleep_time) * 10):
                 time.sleep(0.1)
                 if self.stop_check():
                     return
             self.set_status(
                 gettext("Retrying last operation (attempt {0})").format(
                     i + 1))
     return self.fetch_json_attempt(url)
Exemplo n.º 12
0
 def fetch_game_sync_data(self):
     last_id = self.database.get_last_game_id()
     self.set_status(
         gettext("Fetching database entries ({0})").format(last_id + 1))
     url = "{0}/api/sync/{1}/games?v=2&last={2}".format(
         self.url_prefix(), self.platform_id, last_id)
     print(url)
     data = self.fetch_data(url)
     self.downloaded_size += len(data)
     return data
Exemplo n.º 13
0
 def fetch_game_sync_data(self):
     last_id = self.database.get_last_game_id()
     if self.context.meta["games"][self.platform_id]["sync"] == last_id:
         print("[SYNC] Platform {} already synced".format(self.platform_id))
         return b""
     self.set_status(
         gettext("Fetching database entries ({0})").format(last_id + 1))
     url = "{0}/api/sync/{1}/games?v=3&sync={2}".format(
         self.url_prefix(), self.platform_id, last_id)
     print(url)
     data = self.fetch_data(url)
     # self.downloaded_size += len(data)
     return data
Exemplo n.º 14
0
 def fetch_game_sync_data(self):
     last_id = self.database.get_last_game_id()
     if self.context.meta["games"][self.platform_id]["sync"] == last_id:
         print("[SYNC] Platform {} already synced".format(self.platform_id))
         return b""
     self.set_status(
         gettext("Fetching database entries ({0})").format(last_id + 1)
     )
     url = "{0}/api/sync/{1}/games?v=3&sync={2}".format(
         self.url_prefix(), self.platform_id, last_id
     )
     print(url)
     data = self.fetch_data(url)
     self.downloaded_size += len(data)
     return data
Exemplo n.º 15
0
 def fetch_rating_entries(self):
     cursor = self.client.database.cursor()
     cursor.execute("SELECT max(updated) FROM rating")
     row = cursor.fetchone()
     last_time = row[0]
     if not last_time:
         last_time = "2012-01-01 00:00:00"
     self.set_status(
         gettext("Fetching game ratings ({0})").format(last_time))
     url = "{0}/api/sync/{1}/ratings?from={2}".format(
         self.url_prefix(), self.platform_id, quote_plus(last_time))
     print(url)
     data, json_data = self.fetch_json(url)
     self.downloaded_size += len(data)
     return json_data
Exemplo n.º 16
0
 def cleanup(self):
     print("LaunchHandler.cleanup")
     self.on_progress(gettext("Cleaning up..."))
     # self.delete_tree(self.temp_dir)
     shutil.rmtree(self.temp_dir, ignore_errors=True)
     state_dir = self.get_state_dir()
     try:
         # this will only succeed if the directory is empty -we don't
         # want to leave unnecessary empty state directories
         os.rmdir(state_dir)
         print("removed", repr(state_dir))
         # also try to remove the parent (letter dir)
         os.rmdir(os.path.dirname(state_dir))
         print("removed", repr(os.path.dirname(state_dir)))
     except OSError:
         # could not delete directories - ok - probably has content
         pass
Exemplo n.º 17
0
    def prepare_floppies(self):
        print("LaunchHandler.copy_floppies")
        current_task.set_progress(gettext("Preparing floppy images..."))
        # self.on_progress(gettext("Preparing floppy images..."))

        floppies = []
        for i in range(Amiga.MAX_FLOPPY_DRIVES):
            key = "floppy_drive_{0}".format(i)
            if self.config.get(key, ""):
                floppies.append(self.config[key])
            self.prepare_floppy(key)

        for i in range(Amiga.MAX_FLOPPY_IMAGES):
            key = "floppy_image_{0}".format(i)
            if self.config.get(key, ""):
                break
        else:
            print("floppy image list is empty")
            for j, floppy in enumerate(floppies):
                self.config["floppy_image_{0}".format(j)] = floppy

        max_image = -1
        for i in range(Amiga.MAX_FLOPPY_IMAGES):
            key = "floppy_image_{0}".format(i)
            self.prepare_floppy(key)
            if self.config.get(key, ""):
                max_image = i

        save_image = max_image + 1

        if self.config.get("save_disk", "") != "0":
            s = Resources("fsgs", "res").stream("amiga/adf_save_disk.dat")
            data = s.read()
            data = zlib.decompress(data)
            save_disk = os.path.join(self.temp_dir, "Save Disk.adf")
            with open(save_disk, "wb") as f:
                f.write(data)
            key = "floppy_image_{0}".format(save_image)
            self.config[key] = "Save Disk.adf"
Exemplo n.º 18
0
    def _synchronize(self):
        if (self.context.meta["database"]["version"] !=
                self.database.get_game_database_version()):
            self.set_status(gettext("Resetting game database..."))
            self.database.clear()
            self.database.set_game_database_version(
                self.context.meta["database"]["version"])

        self.set_status(gettext("Synchronizing game database..."))

        while True:
            if self.stop_check():
                return
            data = self.fetch_game_sync_data()
            if self.stop_check():
                return
            if not data:
                print("no more changes")
                break

            t1 = time.time()
            k = 0
            while k < len(data):
                game_sync_id = bytes_to_int(data[k:k + 4])
                k += 4
                game_uuid = data[k:k + 16]
                k += 16
                game_data_size = bytes_to_int(data[k:k + 4])
                k += 4
                game_data = data[k:k + game_data_size]
                k += game_data_size
                # print("game data len:", len(game_data))
                if len(game_data) > 0:
                    self.database.add_game(game_sync_id, game_uuid, game_data)
                else:
                    self.database.delete_game(game_sync_id, game_uuid)
            t2 = time.time()
            print("  {0:0.2f} seconds".format(t2 - t1))

        last_json_data = ""
        while True:
            if self.stop_check():
                return
            json_data = self.fetch_rating_entries()
            if self.stop_check():
                return
            if json_data == last_json_data:
                print("no more changes")
                break
            last_json_data = json_data
            num_changes = len(json_data["ratings"])
            print("  processing {0} entries".format(num_changes))
            t1 = time.time()
            for update in json_data["ratings"]:
                cursor = self.client.database.cursor()
                cursor.execute(
                    "SELECT count(*) FROM rating WHERE game_uuid = "
                    "? AND work_rating = ? AND like_rating = ? "
                    "AND updated = ?",
                    (
                        update["game"],
                        update["work"],
                        update["like"],
                        update["updated"],
                    ),
                )
                if cursor.fetchone()[0] == 1:
                    # we want to avoid needlessly creating update transactions
                    continue
                cursor.execute("DELETE FROM rating WHERE game_uuid = ?",
                               (update["game"], ))
                cursor.execute(
                    "INSERT INTO rating (game_uuid, work_rating, "
                    "like_rating, updated) VALUES (?, ?, ?, ?)",
                    (
                        update["game"],
                        update["work"],
                        update["like"],
                        update["updated"],
                    ),
                )
            t2 = time.time()
            print("  {0:0.2f} seconds".format(t2 - t1))
    def _synchronize(self):
        if self.context.meta["game-database-version"] != \
                self.database.get_game_database_version():
            self.set_status(gettext("Resetting game database..."))
            self.database.clear()
            self.database.set_game_database_version(
                self.context.meta["game-database-version"])

        self.set_status(gettext("Synchronizing game database..."))

        while True:
            if self.stop_check():
                return
            data = self.fetch_game_sync_data()
            if self.stop_check():
                return
            if not data:
                print("no more changes")
                break

            t1 = time.time()
            k = 0
            while k < len(data):
                game_sync_id = bytes_to_int(data[k:k + 4])
                k += 4
                game_uuid = data[k:k + 16]
                k += 16
                game_data_size = bytes_to_int(data[k:k + 4])
                k += 4
                game_data = data[k:k + game_data_size]
                k += game_data_size
                # print("game data len:", len(game_data))
                if len(game_data) > 0:
                    self.database.add_game(game_sync_id, game_uuid, game_data)
                else:
                    self.database.delete_game(game_sync_id, game_uuid)
            t2 = time.time()
            print("  {0:0.2f} seconds".format(t2 - t1))

        last_json_data = ""
        while True:
            if self.stop_check():
                return
            json_data = self.fetch_rating_entries()
            if self.stop_check():
                return
            if json_data == last_json_data:
                print("no more changes")
                break
            last_json_data = json_data
            num_changes = len(json_data["ratings"])
            print("  processing {0} entries".format(num_changes))
            t1 = time.time()
            for update in json_data["ratings"]:
                cursor = self.client.database.cursor()
                cursor.execute(
                    "SELECT count(*) FROM rating WHERE game_uuid = "
                    "? AND work_rating = ? AND like_rating = ? "
                    "AND updated = ?", (update["game"], update["work"],
                                        update["like"], update["updated"]))
                if cursor.fetchone()[0] == 1:
                    # we want to avoid needlessly creating update transactions
                    continue
                cursor.execute("DELETE FROM rating WHERE game_uuid = ?",
                               (update["game"],))
                cursor.execute(
                    "INSERT INTO rating (game_uuid, work_rating, "
                    "like_rating, updated) VALUES (?, ?, ?, ?)",
                    (update["game"], update["work"], update["like"],
                     update["updated"]))
            t2 = time.time()
            print("  {0:0.2f} seconds".format(t2 - t1))

        print("downloaded size: {0:0.2f} MiB".format(
            self.downloaded_size / (1024 * 1024)))
Exemplo n.º 20
0
 def prepare_hard_drives(self):
     print("LaunchHandler.prepare_hard_drives")
     current_task.set_progress(gettext("Preparing hard drives..."))
     # self.on_progress(gettext("Preparing hard drives..."))
     for i in range(0, 10):
         self.prepare_hard_drive(i)
Exemplo n.º 21
0
 def update_changes(self):
     print("LaunchHandler.update_changes")
     self.on_progress(gettext("Saving changes..."))
     self.change_handler.update(self.get_state_dir())
Exemplo n.º 22
0
 def init_changes(self):
     print("LaunchHandler.init_changes")
     self.on_progress(gettext("Restoring changes..."))
     self.change_handler.init(
         self.get_state_dir(), ignore=["*.uss", "*.sdf"])
Exemplo n.º 23
0
 def prepare_hard_drives(self):
     print("LaunchHandler.prepare_hard_drives")
     current_task.set_progress(gettext("Preparing hard drives..."))
     # self.on_progress(gettext("Preparing hard drives..."))
     for i in range(0, 10):
         self.prepare_hard_drive(i)
Exemplo n.º 24
0
    def copy_whdload_files(self, dest_dir, s_dir):
        whdload_args = self.config.get("x_whdload_args", "").strip()
        if not whdload_args:
            return
        print("LaunchHandler.copy_whdload_files")
        current_task.set_progress(gettext("Preparing WHDLoad..."))
        # self.on_progress(gettext("Preparing WHDLoad..."))
        print("copy_whdload_files, dest_dir = ", dest_dir)

        whdload_dir = ""
        slave = whdload_args.split(" ", 1)[0]
        slave = slave.lower()
        found_slave = False
        for dir_path, dir_names, file_names in os.walk(dest_dir):
            for name in file_names:
                # print(name, slave)
                if name.lower() == slave:
                    print("found", name)
                    found_slave = True
                    whdload_dir = dir_path[len(dest_dir):]
                    whdload_dir = whdload_dir.replace("\\", "/")
                    if not whdload_dir:
                        # slave was found in root directory
                        pass
                    elif whdload_dir[0] == "/":
                        whdload_dir = whdload_dir[1:]
                    break
            if found_slave:
                break
        if not found_slave:
            raise Exception(
                "Did not find the specified WHDLoad slave. "
                "Check the WHDLoad arguments")
        print("WHDLoad dir:", repr(whdload_dir))
        print("WHDLoad args:", whdload_args)

        self.copy_whdload_kickstart(
            dest_dir, "kick34005.A500",
            ["891e9a547772fe0c6c19b610baf8bc4ea7fcb785"])
        self.copy_whdload_kickstart(
            dest_dir, "kick40068.A1200",
            ["e21545723fe8374e91342617604f1b3d703094f1"])
        self.copy_whdload_kickstart(
            dest_dir, "kick40068.A4000",
            ["5fe04842d04a489720f0f4bb0e46948199406f49"])
        self.create_whdload_prefs_file(os.path.join(s_dir, "WHDLoad.prefs"))

        whdload_version = self.config["x_whdload_version"]
        if not whdload_version:
            whdload_version = DEFAULT_WHDLOAD_VERSION

        for key, value in whdload_files[whdload_version].items():
            self.install_whdload_file(key, dest_dir, value)
        for key, value in whdload_support_files.items():
            self.install_whdload_file(key, dest_dir, value)

        if self.config.get("__netplay_game", ""):
            print("WHDLoad key is not copied in net play mode")
        else:
            key_file = os.path.join(
                self.fsgs.amiga.get_base_dir(), "WHDLoad.key")
            if os.path.exists(key_file):
                print("found WHDLoad.key at ", key_file)
                shutil.copy(key_file, os.path.join(s_dir, "WHDLoad.key"))
            else:
                print("WHDLoad key not found in base dir (FS-UAE dir)")

            # temporary feature, at least until it's possible to set more
            # WHDLoad settings directly in the Launcher
            prefs_file = os.path.join(
                self.fsgs.amiga.get_base_dir(), "WHDLoad.prefs")
            if os.path.exists(prefs_file):
                print("found WHDLoad.prefs at ", prefs_file)
                shutil.copy(prefs_file, os.path.join(s_dir, "WHDLoad.prefs"))
            else:
                print("WHDLoad key not found in base dir (FS-UAE dir)")

        if self.config.get("__netplay_game", ""):
            print("WHDLoad base dir is not copied in net play mode")
        else:
            src_dir = self.fsgs.amiga.get_whdload_dir()
            if src_dir and os.path.exists(src_dir):
                print("WHDLoad base dir exists, copying resources...")
                self.copy_folder_tree(src_dir, dest_dir)

        # icon = self.config.get("__whdload_icon", "")
        icon = ""
        if icon:
            shutil.copy(os.path.expanduser("~/kgiconload"), 
                        os.path.join(dest_dir, "C", "kgiconload"))
            icon_path = os.path.join(dest_dir, icon)
            print("create icon at ", icon_path)
            create_slave_icon(icon_path, whdload_args)
            self.write_startup_sequence(
                s_dir,
                "cd \"{0}\"\n"
                "kgiconload {1}\n"
                "uae-configuration SPC_QUIT 1\n".format(
                    whdload_dir, os.path.basename(icon)))
        else:
            self.write_startup_sequence(
                s_dir, whdload_sequence.format(whdload_dir, whdload_args))
Exemplo n.º 25
0
 def install_whdload_file(self, sha1, dest_dir, rel_path):
     abs_path = os.path.join(dest_dir, rel_path)
     name = os.path.basename(rel_path)
     self.on_progress(gettext("Downloading {0}...".format(name)))
     Downloader.install_file_by_sha1(sha1, name, abs_path)
Exemplo n.º 26
0
    def prepare_roms(self):
        print("LaunchHandler.prepare_roms")
        current_task.set_progress(gettext("Preparing kickstart ROMs..."))
        amiga_model = self.config.get("amiga_model", "A500")
        model_config = Amiga.get_model_config(amiga_model)

        roms = [("kickstart_file", model_config["kickstarts"])]
        if self.config["kickstart_ext_file"] or model_config["ext_roms"]:
            # not all Amigas have extended ROMs
            roms.append(("kickstart_ext_file", model_config["ext_roms"]))
        if amiga_model.lower() == "cd32/fmv":
            roms.append(("fvm_rom", [CD32_FMV_ROM]))

        if self.config["graphics_card"].lower().startswith("picasso-iv"):
            roms.append(("graphics_card_rom", [PICASSO_IV_74_ROM]))

        if self.config["accelerator"].lower() == "cyberstorm-ppc":
            roms.append(("accelerator_rom", ["cyberstormppc.rom"]))

        if self.config["freezer_cartridge"] == "action-replay-2":
            # Ideally, we would want to recognize ROMs based on zeroing the
            # first four bytes, but right now we simply recognize a common
            # additional version. freezer_cartridge_rom isn't a real option,
            # we just want to copy the rom file and let FS-UAE find it
            roms.append(("[freezer_cartridge]",
                         [ACTION_REPLAY_MK_II_2_14_ROM.sha1,
                          ACTION_REPLAY_MK_II_2_14_MOD_ROM.sha1]))
        elif self.config["freezer_cartridge"] == "action-replay-3":
            roms.append(("[freezer_cartridge]",
                         [ACTION_REPLAY_MK_III_3_17_ROM.sha1,
                          ACTION_REPLAY_MK_III_3_17_MOD_ROM.sha1]))

        for config_key, default_roms in roms:
            print("ROM:", config_key, default_roms)
            src = self.config[config_key]
            if not src:
                for sha1 in default_roms:
                    if is_sha1(sha1):
                        rom_src = self.fsgs.file.find_by_sha1(sha1)
                        if rom_src:
                            src = rom_src
                            break
                    else:
                        # roms_dir = FSGSDirectories.get_kickstarts_dir()
                        # src = os.path.join(roms_dir, sha1)
                        # if os.path.exists(src):
                        #     break
                        # loop up file in roms dir instead
                        src = sha1
            elif src == "internal":
                continue
            elif src:
                src = Paths.expand_path(src)
            if not src:
                raise TaskFailure(
                    gettext("Did not find required Kickstart or "
                            "ROM for {}. Wanted one of these files: {}".format(
                                config_key, repr(default_roms))))

            use_temp_kickstarts_dir = False

            dest = os.path.join(self.temp_dir, os.path.basename(src))
            archive = Archive(src)
            stream = None
            if not archive.exists(src):
                dirs = [self.fsgs.amiga.get_kickstarts_dir()]
                for dir in dirs:
                    path = os.path.join(dir, src)
                    print("checking", repr(path))
                    archive = Archive(path)
                    if archive.exists(path):
                        src = path
                        break
                else:
                    try:
                        stream = self.fsgs.file.open(src)
                        if stream is None:
                            raise FileNotFoundError(src)
                    except FileNotFoundError:
                        raise TaskFailure(gettext(
                            "Cannot find required ROM "
                            "file: {name}".format(name=repr(src))))

            with open(dest, "wb") as f:
                if stream:
                    f.write(stream.read())
                else:
                    ROMManager.decrypt_archive_rom(archive, src, file=f)
                if use_temp_kickstarts_dir:
                    self.config[config_key] = os.path.basename(src)
                else:
                    self.config[config_key] = dest
            if use_temp_kickstarts_dir:
                self.config["kickstarts_dir"] = self.temp_dir