Esempio n. 1
0
    def copy_whdload_kickstart(self, base_dir, name, checksums):
        dest = os.path.join(base_dir, "Devs", "Kickstarts")
        if not os.path.exists(dest):
            os.makedirs(dest)
        dest = os.path.join(dest, name)
        for checksum in checksums:
            # print("find kickstart with sha1", checksum)
            path = self.fsgs.file.find_by_sha1(checksum)
            if path:  # and os.path.exists(path):
                print("found kickstart for", name, "at", path)
                archive = Archive(path)
                if archive.exists(path):
                    with open(dest, "wb") as f:
                        ROMManager.decrypt_archive_rom(archive, path, file=f)
                    print(repr(dest))
                    break
                else:
                    stream = self.fsgs.file.open(path)
                    if stream is None:
                        raise Exception("Cannot find kickstart " + repr(path))
                    with open(dest, "wb") as f:
                        f.write(stream.read())

        else:
            print("did not find kickstart for", name)
Esempio n. 2
0
    def unpack_archive(self, path, destination):
        print("unpack", path, "to", destination)
        archive = Archive(path)
        print(archive)
        print(archive.get_handler())
        for name in archive.list_files():
            if self.stop_flag:
                return

            print(name)
            n = name[len(path) + 2:]
            out_path = os.path.join(destination, n)
            print("out path", out_path)

            if name.endswith("/"):
                os.makedirs(out_path)
            else:
                if not os.path.exists(os.path.dirname(out_path)):
                    os.makedirs(os.path.dirname(out_path))
                f = archive.open(name)
                with open(out_path, "wb") as out_f:
                    while True:
                        data = f.read(65536)
                        if not data:
                            break
                        out_f.write(data)
Esempio n. 3
0
    def multi_select(cls, parent=None):
        default_dir = FSGSDirectories.get_floppies_dir()
        dialog = LauncherFilePicker(parent,
                                    gettext("Select Multiple Floppies"),
                                    "floppy",
                                    multiple=True)
        if not dialog.show_modal():
            return
        original_paths = dialog.get_paths()
        original_paths.sort()
        paths = []
        for path in original_paths:
            path = Paths.get_real_case(path)
            embedded_files = []
            if path.endswith(".zip"):
                archive = Archive(path)
                files = archive.list_files()
                for file in files:
                    name, ext = os.path.splitext(file)
                    # FIXME: get list of floppy extensions from a central
                    # place
                    if ext in [".adf", ".ipf"]:
                        embedded_files.append(file)
            if len(embedded_files) > 0:
                embedded_files.sort()
                print("found embedded floppy images:")
                print(embedded_files)
                for file in embedded_files:
                    paths.append(file)
            else:
                paths.append(path)

        checksum_tool = ChecksumTool(parent)
        for i, path in enumerate(paths):
            sha1 = checksum_tool.checksum(path)
            path = Paths.contract_path(path,
                                       default_dir,
                                       force_real_case=False)

            if i < 4:
                LauncherConfig.set_multiple([
                    ("floppy_drive_{0}".format(i), path),
                    ("x_floppy_drive_{0}_sha1".format(i), sha1)
                ])
            LauncherConfig.set_multiple([("floppy_image_{0}".format(i), path),
                                         ("x_floppy_image_{0}_sha1".format(i),
                                          sha1)])

        # blank the rest of the drives
        for i in range(len(paths), 4):
            LauncherConfig.set_multiple([("floppy_drive_{0}".format(i), ""),
                                         ("x_floppy_drive_{0}_sha1".format(i),
                                          "")])
        # blank the rest of the image list
        for i in range(len(paths), 20):
            LauncherConfig.set_multiple([("floppy_image_{0}".format(i), ""),
                                         ("x_floppy_image_{0}_sha1".format(i),
                                          "")])
Esempio n. 4
0
    def scan_file(self, database, path):
        name = os.path.basename(path)
        # path = os.path.normcase(os.path.normpath(path))

        self.scan_count += 1
        self.set_status(
            gettext("Scanning files ({count} scanned)").format(
                count=self.scan_count), name)

        try:
            st = os.stat(path)
        except:
            print("error stat-ing file", repr(path))
            return
        size = st.st_size
        mtime = int(st.st_mtime)

        result = database.find_file(path=path)
        # print(result)
        if result["path"]:
            if size == result["size"] and mtime == result["mtime"]:

                self.database_file_ids.remove(result["id"])
                # self.database_file_ids.difference_update(
                #         database.get_file_hierarchy_ids(path + "#"))

                # self.database_file_ids.difference_update(
                #         database.get_child_ids(id=result["id"]))
                return

        archive = Archive(path)
        # if archive.is_archive():

        file_id = self.scan_archive_stream(database, archive, path, name, size,
                                           mtime)

        for p in archive.list_files():
            if p.endswith("/"):
                # don't index archive directory entries
                continue
            # print(p)
            if self.stop_check():
                return
            # n = p.replace("\\", "/").replace("|", "/").split("/")[-1]
            n = os.path.basename(p)
            self.scan_count += 1
            self.scan_archive_stream(database,
                                     archive,
                                     p,
                                     n,
                                     size,
                                     mtime,
                                     parent=file_id)
        if self.stop_check():
            return
    def multiselect(cls, parent=None):
        default_dir = FSGSDirectories.get_floppies_dir()
        dialog = LauncherFilePicker(
            parent, gettext("Select Multiple Floppies"),
            "floppy", multiple=True)
        if not dialog.show_modal():
            return
        original_paths = dialog.get_paths()
        original_paths.sort()
        paths = []
        for path in original_paths:
            path = Paths.get_real_case(path)
            embedded_files = []
            if path.endswith(".zip"):
                archive = Archive(path)
                files = archive.list_files()
                for file in files:
                    name, ext = os.path.splitext(file)
                    # FIXME: get list of floppy extensions from a central
                    # place
                    if ext in [".adf", ".ipf"]:
                        embedded_files.append(file)
            if len(embedded_files) > 0:
                embedded_files.sort()
                print("found embedded floppy images:")
                print(embedded_files)
                for file in embedded_files:
                    paths.append(file)
            else:
                paths.append(path)

        checksum_tool = ChecksumTool(parent)
        for i, path in enumerate(paths):
            sha1 = checksum_tool.checksum(path)
            path = Paths.contract_path(
                path, default_dir, force_real_case=False)

            if i < 4:
                LauncherConfig.set_multiple([
                    ("floppy_drive_{0}".format(i), path),
                    ("x_floppy_drive_{0}_sha1".format(i), sha1)])
            LauncherConfig.set_multiple([
                ("floppy_image_{0}".format(i), path),
                ("x_floppy_image_{0}_sha1".format(i), sha1)])

        # blank the rest of the drives
        for i in range(len(paths), 4):
            LauncherConfig.set_multiple([
                ("floppy_drive_{0}".format(i), ""),
                ("x_floppy_drive_{0}_sha1".format(i), "")])
        # blank the rest of the image list
        for i in range(len(paths), 20):
            LauncherConfig.set_multiple([
                ("floppy_image_{0}".format(i), ""),
                ("x_floppy_image_{0}_sha1".format(i), "")])
Esempio n. 6
0
    def decrypt_archive_rom(cls, archive, path, file=None):
        print("decrypt_archive_rom", path)
        result = {}
        f = archive.open(path)
        data = f.read(len("AMIROMTYPE1"))
        out_data = b""
        sha1 = hashlib.sha1()
        if data != b"AMIROMTYPE1":
            # not encrypted, write raw data
            sha1.update(data)
            out_data += data
            data = f.read()
            sha1.update(data)
            out_data += data
            result["data"] = out_data
            result["sha1"] = sha1.hexdigest()
            cls.patch_rom(result)
            if file is not None:
                file.write(result["data"])
            return result

        key_path = archive.join(archive.dirname(path), "rom.key")
        key_archive = Archive(key_path)
        try:
            f2 = key_archive.open(key_path)
        except Exception:
            raise Exception("did not find rom.key to decrypt ROM with")
        print("using key file", key_path)
        # if not os.path.exists(key_file):
        #     raise Exception("did not find rom.key to decrypt ROM with")
        key_data = f2.read()
        f2.close()

        while True:
            data = f.read(len(key_data))
            if not data:
                break
            dec = []
            for i in range(len(data)):
                dec.append(data[i] ^ key_data[i])
            dec_data = bytes(dec)
            # if file is not None:
            #     file.write(dec_data)
            out_data += dec_data
            if sha1 is not None:
                sha1.update(dec_data)
        result["data"] = out_data
        result["sha1"] = sha1.hexdigest()
        cls.patch_rom(result)
        if file is not None:
            file.write(result["data"])
        return result
Esempio n. 7
0
    def scan_file(self, database, path):
        name = os.path.basename(path)
        # path = os.path.normcase(os.path.normpath(path))

        self.scan_count += 1
        self.set_status(
            gettext("Scanning files ({count} scanned)").format(
                count=self.scan_count), name)

        try:
            st = os.stat(path)
        except:
            print("error stat-ing file", repr(path))
            return
        size = st.st_size
        mtime = int(st.st_mtime)

        result = database.find_file(path=path)
        # print(result)
        if result["path"]:
            if size == result["size"] and mtime == result["mtime"]:

                self.database_file_ids.remove(result["id"])
                # self.database_file_ids.difference_update(
                #         database.get_file_hierarchy_ids(path + "#"))

                # self.database_file_ids.difference_update(
                #         database.get_child_ids(id=result["id"]))
                return

        archive = Archive(path)
        # if archive.is_archive():

        file_id = self.scan_archive_stream(
            database, archive, path, name, size, mtime)

        for p in archive.list_files():
            if p.endswith("/"):
                # don't index archive directory entries
                continue
            # print(p)
            if self.stop_check():
                return
            # n = p.replace("\\", "/").replace("|", "/").split("/")[-1]
            n = os.path.basename(p)
            self.scan_count += 1
            self.scan_archive_stream(
                database, archive, p, n, size, mtime, parent=file_id)
        if self.stop_check():
            return
Esempio n. 8
0
 def calculate_whdload_args(cls, archive_path):
     archive = Archive(archive_path)
     slave = ""
     for path in archive.list_files():
         name = os.path.basename(path)
         name_lower = name.lower()
         if name_lower.endswith(".slave"):
             if slave:
                 print("already found one slave, don't know which "
                       "one to choose")
                 return ""
             slave = name
         elif name_lower == "startup-sequence":
             print("found startup-sequence, assuming non-whdload "
                   "archive")
     return slave
Esempio n. 9
0
 def calculate_whdload_args(cls, archive_path):
     archive = Archive(archive_path)
     slave = ""
     for path in archive.list_files():
         name = os.path.basename(path)
         name_lower = name.lower()
         if name_lower.endswith(".slave"):
             if slave:
                 print("already found one slave, don't know which "
                       "one to choose")
                 return ""
             slave = name
         elif name_lower == "startup-sequence":
             print("found startup-sequence, assuming non-whdload "
                   "archive")
     return slave
Esempio n. 10
0
    def insert_multiple_floppies(self, insert_paths):
        paths = []
        for path in insert_paths:
            embedded_files = []
            if path.endswith(".zip"):
                archive = Archive(path)
                files = archive.list_files()
                for file in files:
                    name, ext = os.path.splitext(file)
                    # FIXME: get list of floppy extensions from a central
                    # place
                    if ext in [".adf", ".ipf"]:
                        embedded_files.append(file)
            if len(embedded_files) > 0:
                embedded_files.sort()
                print("found embedded floppy images:")
                print(embedded_files)
                for file in embedded_files:
                    paths.append(file)
            else:
                paths.append(path)

        default_dir = FSGSDirectories.get_floppies_dir()
        checksum_tool = ChecksumTool()
        for i, path in enumerate(paths):
            sha1 = checksum_tool.checksum(path)
            path = Paths.contract_path(path, default_dir)

            if i < 4:
                self.set_config([
                    ("floppy_drive_{0}".format(i), path),
                    ("x_floppy_drive_{0}_sha1".format(i), sha1)])
            self.set_config([
                ("floppy_image_{0}".format(i), path),
                ("x_floppy_image_{0}_sha1".format(i), sha1)])

        # blank the rest of the drives
        for i in range(len(paths), 4):
            self.set_config([
                ("floppy_drive_{0}".format(i), ""),
                ("x_floppy_drive_{0}_sha1".format(i), "")])
        # blank the rest of the image list
        for i in range(len(paths), 20):
            self.set_config([
                ("floppy_image_{0}".format(i), ""),
                ("x_floppy_image_{0}_sha1".format(i), "")])
Esempio n. 11
0
    def upload_prefix(self, prefix):
        self.stop_check()
        result = self.upload_check(prefix)
        print(len(result))
        for k in range(0, len(result), 20):
            self.stop_check()

            sha1 = result[k:k + 20]
            path = fsgs.file.find_by_sha1(bytes_to_hex(sha1))
            if not path:
                continue
            try:
                # this is done to properly handle encrypted ROMs
                archive = Archive(path)
                data = ROMManager.decrypt_archive_rom(archive, path)["data"]
            except Exception:
                traceback.print_exc()
                uri = "sha1://{0}".format(bytes_to_hex(sha1))
                print(uri)
                try:
                    input_stream = fsgs.file.open(uri)
                    data = input_stream.read()
                except Exception:
                    continue
                assert not input_stream.read()

            print("uploading file of size ", len(data))

            # self.progressed(gettext("Verifying {name}").format(
            #                 name=bytes_to_hex(sha1)))
            self.progressed(
                gettext("Uploading {name}").format(name=bytes_to_hex(sha1)))
            import hashlib
            new_hash = hashlib.sha1(data).hexdigest()
            print(new_hash, "vs", bytes_to_hex(sha1))
            if hashlib.sha1(data).hexdigest() != bytes_to_hex(sha1):
                print("hash mismatch, probably Cloanto ROM...")
                continue

            retry_seconds = 1
            while True:
                try:
                    self.client.post("/api/locker-upload-file", data=data)
                except OGDClient.NonRetryableHTTPError as e:
                    raise e
                except Exception:
                    traceback.print_exc()
                    self.progressed(
                        gettext("Re-trying in {0} seconds...").format(
                            retry_seconds))
                    for _ in range(retry_seconds):
                        self.stop_check()
                        time.sleep(1.0)
                    retry_seconds = min(retry_seconds * 2, 60 * 10)
                else:
                    break
Esempio n. 12
0
    def insert_multiple_floppies(self, insert_paths):
        paths = []
        for path in insert_paths:
            embedded_files = []
            if path.endswith(".zip"):
                archive = Archive(path)
                files = archive.list_files()
                for file in files:
                    name, ext = os.path.splitext(file)
                    # FIXME: get list of floppy extensions from a central
                    # place
                    if ext in [".adf", ".ipf"]:
                        embedded_files.append(file)
            if len(embedded_files) > 0:
                embedded_files.sort()
                print("found embedded floppy images:")
                print(embedded_files)
                for file in embedded_files:
                    paths.append(file)
            else:
                paths.append(path)

        default_dir = FSGSDirectories.get_floppies_dir()
        checksum_tool = ChecksumTool()
        for i, path in enumerate(paths):
            sha1 = checksum_tool.checksum(path)
            path = Paths.contract_path(path, default_dir)

            if i < 4:
                self.set_config([("floppy_drive_{0}".format(i), path),
                                 ("x_floppy_drive_{0}_sha1".format(i), sha1)])
            self.set_config([("floppy_image_{0}".format(i), path),
                             ("x_floppy_image_{0}_sha1".format(i), sha1)])

        # blank the rest of the drives
        for i in range(len(paths), 4):
            self.set_config([("floppy_drive_{0}".format(i), ""),
                             ("x_floppy_drive_{0}_sha1".format(i), "")])
        # blank the rest of the image list
        for i in range(len(paths), 20):
            self.set_config([("floppy_image_{0}".format(i), ""),
                             ("x_floppy_image_{0}_sha1".format(i), "")])
Esempio n. 13
0
 def download_game_file_archive(self, url):
     print("\ndownload_game_file_archive", url)
     archive_path = Downloader.cache_file_from_url(url)
     archive = Archive(archive_path)
     archive_files = archive.list_files()
     print(archive_files)
     for name in archive_files:
         print(name)
         ifs = archive.open(name)
         data = ifs.read()
         Downloader.cache_data(data)
     if len(archive_files) == 0:
         # might not be an archive then
         with open(archive_path, "rb") as f:
             data = f.read()
         Downloader.cache_data(data)
     # the downloaded archive is no longer needed, now that we have
     # extracted all the files
     os.remove(archive_path)
     print("\n")
Esempio n. 14
0
    def checksum(self, path):
        print("checksum", repr(path))
        archive = Archive(path)
        if os.path.exists(path):
            size = os.path.getsize(path)
            if size == 0:
                # either a real 0-byte file or a device node on a BSD
                # system (could be large). To reliably get the size we could
                # use ioctl, but we simply return the checksum for a 0-byte
                # file anyway
                return ZERO_SHA1

        s = hashlib.sha1()
        f = archive.open(path)
        while True:
            data = f.read(65536)
            if not data:
                break
            s.update(data)
        return s.hexdigest()
 def download_game_file_archive(self, url):
     print("\ndownload_game_file_archive", url)
     archive_path = Downloader.cache_file_from_url(url)
     archive = Archive(archive_path)
     archive_files = archive.list_files()
     print(archive_files)
     for name in archive_files:
         print(name)
         ifs = archive.open(name)
         data = ifs.read()
         Downloader.cache_data(data)
     if len(archive_files) == 0:
         # might not be an archive then
         with open(archive_path, "rb") as f:
             data = f.read()
         Downloader.cache_data(data)
     # the downloaded archive is no longer needed, now that we have
     # extracted all the files
     os.remove(archive_path)
     print("\n")
Esempio n. 16
0
 def convert_uri(self, uri, prefer_path=False):
     if uri.startswith("sha1://"):
         return self.open_sha1_uri(uri)
     elif uri.startswith("db://"):
         # old name for sha1://
         return self.open_sha1_uri(uri)
     elif is_http_url(uri):
         return self.open_url(uri)
     elif uri.startswith("locker://"):
         return open_locker_uri(uri,
                                opener_cache_dict=self.opener_cache_dict)
     else:
         if prefer_path and os.path.exists(uri):
             # return helper object so isinstance does not match with str
             return File(uri)
         return Archive(uri).open(uri)
Esempio n. 17
0
 def expand_default_path(self, src, default_dir):
     if "://" in src:
         return src, None
     src = Paths.expand_path(src, default_dir)
     archive = Archive(src)
     # if not archive.exists(src):
     #     dirs = [default_dir]
     #     for dir in dirs:
     #         path = os.path.join(dir, src)
     #         print("checking", repr(path))
     #         archive = Archive(path)
     #         if archive.exists(path):
     #         #if os.path.exists(path):
     #             src = path
     #             break
     #     else:
     #         raise Exception("Cannot find path for " + repr(src))
     return src, archive
Esempio n. 18
0
 def add_rom_to_database(cls, path, database, log_function=None):
     if log_function is None:
         log_function = print
     try:
         archive = Archive(path)
         rom = ROMManager.decrypt_archive_rom(archive, path)
     except Exception:
         import traceback
         traceback.print_exc()
         return
     try:
         st = os.stat(path)
     except:
         log_function("Error stat-ing file {0}".format(repr(path)))
         return
     size = st.st_size
     mtime = int(st.st_mtime)
     log_function("Adding ROM \"{0}\" to database (SHA-1: {1})".format(
                  path, rom["sha1"]))
     database.delete_file(path=path)
     database.add_file(path=path, sha1=rom["sha1"], mtime=mtime, size=size)
Esempio n. 19
0
    def run_config_or_game(cls):
        config_path = None
        archive_path = None
        floppy_image_paths = []
        cdrom_image_paths = []
        config_uuid = None
        floppy_exts = (".adf", ".ipf", ".dms", ".adz")
        cdrom_exts = (".cue", ".iso")
        archive_exts = (".zip", ".lha")

        # FIXME: replace argument "parsing" with use of argparse module
        # at some point

        last_arg = sys.argv[-1]
        file_ext = os.path.splitext(last_arg)[-1].lower()
        if file_ext == ".fs-uae":
            config_path = last_arg
        elif file_ext in archive_exts:
            archive_path = last_arg
        # elif file_ext in floppy_exts:
        #     floppy_image_paths = [last_arg]
        elif is_uuid(last_arg):
            config_uuid = last_arg.lower()
        for arg in sys.argv[1:]:
            if not arg.startswith("--"):
                _, ext = os.path.splitext(arg)
                if ext in floppy_exts:
                    floppy_image_paths.append(arg)
                elif ext in cdrom_exts:
                    cdrom_image_paths.append(arg)

        if config_path:
            print("config path given:", config_path)
            if not os.path.exists(config_path):
                print("config path does not exist", file=sys.stderr)
                return True
            LauncherConfig.load_file(config_path)
            fsgs.config.add_from_argv()
            return cls.run_config_directly()

        if archive_path:
            print("archive path given:", archive_path)
            if not os.path.exists(archive_path):
                print("archive path does not exist", file=sys.stderr)
                return True
            archive = Archive(os.path.realpath(archive_path))
            # We want to exclude pure directory entries when checking for
            # archives with only floppies.
            arc_files = [x for x in archive.list_files() if not x.endswith("/")]
            if all(map(lambda f: f.lower().endswith(floppy_exts), arc_files)):
                print("archive contains floppy disk images only")
                floppy_image_paths = arc_files
            else:
                values = HardDriveGroup.generate_config_for_archive(
                    archive_path)
                values["hard_drive_0"] = archive_path
                values.update(fsgs.config.config_from_argv())
                return cls.run_config_directly_with_values(values)

        if floppy_image_paths:
            enum_paths = tuple(enumerate(floppy_image_paths))
            values = {}
            values.update(fsgs.config.config_from_argv())
            max_drives = int(values.get("floppy_drive_count", "4"))
            values.update({"floppy_drive_{0}".format(k): v
                           for k, v in enum_paths[:max_drives]})
            values.update({"floppy_image_{0}".format(k): v
                           for k, v in enum_paths[:20]})
            return cls.run_config_directly_with_values(values)

        if cdrom_image_paths:
            enum_paths = tuple(enumerate(cdrom_image_paths))
            values = {"amiga_model": "CD32"}
            values.update(fsgs.config.config_from_argv())
            max_drives = int(values.get("cdrom_drive_count", "1"))
            values.update({"cdrom_drive_{0}".format(k): v
                           for k, v in enum_paths[:max_drives]})
            values.update({"cdrom_image_{0}".format(k): v
                           for k, v in enum_paths[:20]})
            return cls.run_config_directly_with_values(values)

        if config_uuid:
            print("config uuid given:", config_uuid)
            variant_uuid = config_uuid
            # values = fsgs.game.set_from_variant_uuid(variant_uuid)
            if fsgs.load_game_variant(variant_uuid):
                print("loaded variant")
            else:
                print("could not load variant, try to load game")
                game_uuid = config_uuid
                variant_uuid = fsgs.find_preferred_game_variant(game_uuid)
                print("preferred variant:", variant_uuid)
                fsgs.load_game_variant(variant_uuid)
            fsgs.config.add_from_argv()
            LauncherConfig.post_load_values(fsgs.config)
            return cls.run_config_directly()
Esempio n. 20
0
 def checksum_rom(self, path):
     print("checksum_rom", repr(path))
     archive = Archive(path)
     return ROMManager.decrypt_archive_rom(archive, path)["sha1"]
Esempio n. 21
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