예제 #1
0
 def get_list_contents(self):
     result = set()
     print("read_list_contents", self.list_path)
     with open(self.list_path, "rb") as f:
         for line in f.readlines():
             line = line.strip()
             if not line:
                 continue
             print(line)
             parts = line.rsplit("(", 1)
             name = parts[0]
             platform = None
             if len(parts) == 2:
                 parts = parts[1][:-1].split(",", 1)
                 platform = parts[0]
                 if len(parts) == 2:
                     # FIXME variant...
                     pass
             print(name, platform)
             cmp_game = GameNameUtil.create_cmpname(name)
             if platform:
                 cmp_platform = GameNameUtil.create_cmpname(platform)
                 result.add((cmp_game, cmp_platform))
             else:
                 result.add(cmp_game)
     return result
예제 #2
0
 def game_filter(row):
     # print(game_info)
     game_filter_set = self.get_list_contents()
     # print(self.game_filter_set)
     cmp_game = GameNameUtil.create_cmpname(row[ROW_NAME])
     # print("check -- ", cmp_game)
     if cmp_game in game_filter_set:
         return True
     cmp_platform = GameNameUtil.create_cmpname(row[ROW_PLATFORM])
     # print("check -- ", (cmp_game, cmp_platform))
     if (cmp_game, cmp_platform) in game_filter_set:
         return True
     return False
예제 #3
0
    def _get_state_dir(self):
        config_name = self.config_name
        if not config_name:
            config_name = "Default"

        # Use a temporary state dir, for now, to avoid problems with
        # floppy overlays etc interfering with net play.
        if self.fsgc.netplay.enabled:
            # It is possible to manually specify the state dir.
            config_name = self.fsgc.config.get("__netplay_state_dir_name")
            if not config_name:
                # This is the default behavior, create a clean state
                # dir for the net play session.
                netplay_game = self.fsgc.config.get("__netplay_game")
                if netplay_game:
                    config_name = "Net Play ({0})".format(netplay_game)

        # Convert the config name to a name which can be represented on
        # the file system (really all/most filesystems).
        config_name = GameNameUtil.create_fs_name(config_name)

        letter = self.get_letter(config_name)
        if not letter:
            config_name = "Default"
            letter = self.get_letter(config_name)
        # We use an existing state dir in a "letter" dir if it already
        # exists (legacy support).
        path = os.path.join(
            FSGSDirectories.get_save_states_dir(), letter, config_name
        )
        if os.path.exists(path):
            return path
        # If not, we use a direct sub-folder of save states dir.
        path = os.path.join(FSGSDirectories.get_save_states_dir(), config_name)
        return path
    def update_search(self):
        search = LauncherSettings.get("config_search").strip().lower()
        print("search for", search)
        words = []
        special = []
        for word in search.split(" "):
            word = word.strip()
            if not word:
                continue
            if ":" in word[1:-1]:
                special.append(word)
            else:
                words.append(word)
        terms = GameNameUtil.extract_search_terms(" ".join(words))
        terms.update(special)

        database = Database.get_instance()

        try:
            have = int(LauncherSettings.get("database_show_games"))
        except ValueError:
            # default is show all downloadable and locally available games
            have = 1
        items = database.find_games_new(
            " ".join(terms),
            have=have,
            list_uuid=LauncherSettings.get("game_list_uuid"),
        )

        self.set_items(items)
예제 #5
0
    def _get_state_dir(self):
        config_name = self.config_name
        if not config_name:
            config_name = "Default"

        # Use a temporary state dir, for now, to avoid problems with
        # floppy overlays etc interfering with net play.
        if self.fsgc.netplay.enabled:
            # It is possible to manually specify the state dir.
            config_name = self.fsgc.config.get("__netplay_state_dir_name")
            if not config_name:
                # This is the default behavior, create a clean state
                # dir for the net play session.
                netplay_game = self.fsgc.config.get("__netplay_game")
                if netplay_game:
                    config_name = "Net Play ({0})".format(netplay_game)

        # Convert the config name to a name which can be represented on
        # the file system (really all/most filesystems).
        config_name = GameNameUtil.create_fs_name(config_name)

        letter = self.get_letter(config_name)
        if not letter:
            config_name = "Default"
            letter = self.get_letter(config_name)
        # We use an existing state dir in a "letter" dir if it already
        # exists (legacy support).
        path = os.path.join(FSGSDirectories.get_save_states_dir(), letter,
                            config_name)
        if os.path.exists(path):
            return path
        # If not, we use a direct sub-folder of save states dir.
        path = os.path.join(FSGSDirectories.get_save_states_dir(), config_name)
        return path
    def update_search(self):
        search = LauncherSettings.get("config_search").strip().lower()
        print("search for", search)
        words = []
        special = []
        for word in search.split(" "):
            word = word.strip()
            if not word:
                continue
            if ":" in word[1:-1]:
                special.append(word)
            else:
                words.append(word)
        terms = GameNameUtil.extract_search_terms(" ".join(words))
        terms.update(special)

        database = Database.get_instance()

        try:
            have = int(LauncherSettings.get("database_show_games"))
        except ValueError:
            # default is show all downloadable and locally available games
            have = 1
        items = database.find_games_new(
            " ".join(terms), have=have,
            list_uuid=LauncherSettings.get("game_list_uuid"))

        self.set_items(items)
예제 #7
0
def main():
    Application("fs-uae-game-system")

    if "--unsupported" in sys.argv:
        if "--http-server" in sys.argv:
            from fsgs.http.server import http_server_main
            return http_server_main()

    if len(sys.argv) < 3:
        print("")
        print("usage: fsgs run <game>")
        print("")
        print("game:")
        print(" - search term(s) identifying a single game")
        print(" - path to a .fsgs file")
        print(" - path to a recognized cartridge ROM or disk file format")
        print("")
        sys.exit(1)
    assert sys.argv[1] == "run"
    game_arg = " ".join(sys.argv[2:])
    print(game_arg)
    if os.path.exists(game_arg):
        load_file(game_arg)
    else:
        search = game_arg.lower()
        database = Database.instance()
        # cursor.execute("SELECT id FROM game WHERE name like")
        terms = GameNameUtil.extract_search_terms(search)
        found_games = database.find_games_new(" ".join(terms))
        games = []
        for game in found_games:
            print(list(game))
            if game[0]:
                # only process entries with a game uuid
                games.append(game)
        game_uuid = None
        if len(games) == 0:
            print("no games found")
            sys.exit(2)
        if len(games) > 1:
            matches = 0
            for row in games:
                if row[1].lower() == search:
                    if game_uuid is None:
                        game_uuid = row[0]
                        matches += 1
            if matches != 1:
                print("")
                print("More than one game matches:")
                print("")
                for row in games:
                    print("    {0} ({1})".format(row[1], row[2]))
                    print("        {0}".format(row[0]))
                print("")
                sys.exit(3)
        game_uuid = games[0][0]
        assert game_uuid
        variant_uuid = find_preferred_variant(game_uuid)
        load_game_variant(variant_uuid)
    fsgs.run_game()
예제 #8
0
 def get_state_dir(self):
     """This is the old deprecated save sate directory for games."""
     state_dir = os.path.join(FSGSDirectories.get_save_states_dir(),
                              GameNameUtil.create_fs_name(self.get_name()))
     if not os.path.exists(state_dir):
         os.makedirs(state_dir)
     if self.fsgc.game.variant.uuid:
         uuid_file = os.path.join(state_dir, "uuid.txt")
         with io.open(uuid_file, "w", encoding="UTF-8") as f:
             f.write(self.fsgc.game.variant.uuid + "\n")
     # timestamp_file = os.path.join(state_dir, "timestamp.txt")
     # with open(timestamp_file, "wb") as f:
     #     f.write("\n")
     return state_dir
예제 #9
0
    def get_state_dir(self):
        state_dir = os.path.join(
            FSGSDirectories.get_save_states_dir(),
            GameNameUtil.create_fs_name(self.get_name()))
        if not os.path.exists(state_dir):
            os.makedirs(state_dir)
        if self.fsgs.game.variant.uuid:
            uuid_file = os.path.join(state_dir, "uuid.txt")
            with io.open(uuid_file, "w", encoding="UTF-8") as f:
                f.write(self.fsgs.game.variant.uuid + "\n")
        # timestamp_file = os.path.join(state_dir, "timestamp.txt")
        # with open(timestamp_file, "wb") as f:
        #     f.write("\n")

        return state_dir
예제 #10
0
    def get_image_path(self):
        cmp_name = GameNameUtil.create_cmpname(self.name)

        # FIXME: FIXME: DISABLED TEMPORARILY
        # FIXME: USING 512-size only for now

        # if False and os.path.exists("../fs-game-database/game/texture"):
        # if os.path.exists("../fs-game-database/game/texture"):
        #     base_path = "../fs-game-database/game/texture"
        #     path = os.path.join(base_path, NameUtil.create_cmpname(
        #             self.platform), cmp_name, "front-512.jpg")
        #             #self.platform), cmp_name, "front-1024.jpg")
        #     if os.path.exists(path):
        #         return path
        # #else:
        # base_path = os.path.join(pyapp.app.get_data_dir(), "texture")
        # if os.path.exists("c:\\data\\game\\info"):
        #     base_path = "c:\\data\\game\\info"
        # else:
        #     base_path = os.path.join(pyapp.app.get_data_dir(), "info")
        # base_path = os.path.join(GameCenter.data_dir, "info")
        # path = os.path.join(base_path, NameUtil.create_cmpname(self.platform),
        #         cmp_name, "front.jpg")
        # if not os.path.exists(path):
        #     base_path = "c:\\data\\game\\info"
        #     path = os.path.join(base_path, NameUtil.create_cmpname(
        #             self.platform), cmp_name, "front.jpg")
        #         #cmp_name, "front-1024.jpg")
        # if not os.path.exists(path):
        #     path = os.path.join(base_path,
        #             NameUtil.create_cmpname(self.platform),
        #             cmp_name, "front-512.jpg")
        # path = os.path.join(NameUtil.create_cmpname(self.platform),
        #         cmp_name, "front.jpg")
        # return path
        # return self.game_info[5] + "?s=512&t=jpg"
        if not self.game_info[5]:
            return None
        return self.game_info[5] + "?w=480&h=640&t=cc&f=jpg"
예제 #11
0
    def get_image_path(self):
        cmp_name = GameNameUtil.create_cmpname(self.name)

        # FIXME: FIXME: DISABLED TEMPORARILY
        # FIXME: USING 512-size only for now

        # if False and os.path.exists("../fs-game-database/game/texture"):
        # if os.path.exists("../fs-game-database/game/texture"):
        #     base_path = "../fs-game-database/game/texture"
        #     path = os.path.join(base_path, NameUtil.create_cmpname(
        #             self.platform), cmp_name, "front-512.jpg")
        #             #self.platform), cmp_name, "front-1024.jpg")
        #     if os.path.exists(path):
        #         return path
        # #else:
        # base_path = os.path.join(pyapp.app.get_data_dir(), "texture")
        # if os.path.exists("c:\\data\\game\\info"):
        #     base_path = "c:\\data\\game\\info"
        # else:
        #     base_path = os.path.join(pyapp.app.get_data_dir(), "info")
        # base_path = os.path.join(GameCenter.data_dir, "info")
        # path = os.path.join(base_path, NameUtil.create_cmpname(self.platform),
        #         cmp_name, "front.jpg")
        # if not os.path.exists(path):
        #     base_path = "c:\\data\\game\\info"
        #     path = os.path.join(base_path, NameUtil.create_cmpname(
        #             self.platform), cmp_name, "front.jpg")
        #         #cmp_name, "front-1024.jpg")
        # if not os.path.exists(path):
        #     path = os.path.join(base_path,
        #             NameUtil.create_cmpname(self.platform),
        #             cmp_name, "front-512.jpg")
        # path = os.path.join(NameUtil.create_cmpname(self.platform),
        #         cmp_name, "front.jpg")
        # return path
        # return self.game_info[5] + "?s=512&t=jpg"
        if not self.game_info[5]:
            return None
        return self.game_info[5] + "?w=480&h=640&t=lbcover&f=jpg"
예제 #12
0
def create_search_results_menu(text):
    global current_menu
    try:
        if text == current_menu.search_text:
            return False
    except AttributeError:
        pass
    new_menu = SearchResultsMenu("Search Results")
    new_menu.search_text = text
    # words = [v.strip() for v in text.lower().split(" ")]
    # print "Creating search results for", words
    new_menu.top.append_left(
        SearchTextItem("Search: {0}_".format(text)))
    # clause = []
    # args = []
    # for word in words:
    #     clause.append("AND name like ?")
    #     args.append("%{0}%".format(word))
    # clause = " ".join(clause)
    terms = GameNameUtil.extract_search_terms(text.lower())
    for item in MenuItem.create_game_items(terms):
        new_menu.append(item)
    if len(new_menu) == 0:
        new_menu.append(NoItem("No Search Results"))
    # if hasattr(current_menu, "search_text"):
    #     # replace current search menu, not append to path
    #     #new_menu.parent_menu = current_menu.parent_menu
    #     replace = True
    # else:
    #     #new_menu.parent_menu = current_menu
    #     replace = False
    replace = isinstance(current_menu, SearchResultsMenu)
    print("create search results menu")
    # set_current_menu(new_menu)
    enter_menu(new_menu, replace=replace)
    return True
예제 #13
0
    def scan_game_database(self, helper, database_name, game_database):
        """
        :type helper: ScanHelper
        :type database_name: str
        :type game_database: fsgs.GameDatabase.GameDatabase
        """
        database_cursor = helper.database.cursor()

        # this holds a list of game entry UUIDs which must exist / be checked
        # after variants have been processed
        # ensure_updated_games = set()

        game_database_cursor = game_database.cursor()

        # this list will contain game entries which are not variants
        game_rows = []

        game_database_cursor.execute(
            "SELECT id, uuid FROM game WHERE data != ''"
        )
        for row in game_database_cursor:
            if self.stop_check():
                return

            variant_id, variant_uuid_bin = row
            variant_uuid = binary_to_uuid(variant_uuid_bin)
            update_stamp = variant_id

            existing_variant = helper.existing_variants.get(
                variant_uuid, (None, None, None)
            )

            existing_game = helper.existing_games.get(
                variant_uuid, (None, None, None)
            )
            if update_stamp == existing_game[0]:
                # Game entry, not updated.
                game_rows.append(row)
                continue

            if update_stamp == existing_variant[0]:
                # entry was already updated and has not changed
                if existing_variant[1] and not helper.deleted_files:
                    # have this entry already and no files have been deleted
                    # since the last time

                    # print("skipping variant (no deleted files)")
                    helper.variant_seen(variant_uuid)
                    continue
                if not existing_variant[1] and not helper.added_files:
                    # do not have this entry, but no files have been added
                    # since the last time

                    # print("skipping variant (no added files)")
                    helper.variant_seen(variant_uuid)
                    continue
            else:
                # when the game entry has changed, we always check it
                # regardless of file database status, since file_list may
                # have been changed, or download status... (or other info
                # needs to be corrected)
                # print("[SCANNER] Changed: {}".format(variant_uuid))
                pass

            self.scan_count += 1
            self.set_status(
                gettext("Scanning game variants ({count} scanned)").format(
                    count=self.scan_count
                ),
                variant_uuid,
            )

            try:
                doc = self.fsgs.game.get_game_values_for_id(
                    game_database, variant_id
                )
            except IncompleteGameException as e:
                print("[SCANNER]", repr(e))
                continue

            file_list_json = doc.get("file_list", "")
            if not file_list_json:
                # not a game variant... (parent game only probably)
                game_rows.append(row)
                continue

            entry_type = int(doc.get("_type", "0"))
            if (entry_type & GAME_ENTRY_TYPE_VARIANT) == 0:
                # game entry is not tagged with variant -- add to game list
                # instead
                game_rows.append(row)
                continue

            helper.variant_seen(variant_uuid)

            all_files_found = True
            try:
                file_list = json.loads(file_list_json)
            except Exception:
                # invalid JSON string
                # FIXME: log error
                all_files_found = False
                file_list = []

            for file_item in file_list:
                if file_item["name"].endswith("/"):
                    # skip directory entries:
                    continue
                result = self.fsgs.file.check_sha1(file_item["sha1"])
                if not result:
                    all_files_found = False
                    break

            if all_files_found:
                have_variant = 4
            elif doc.get("download_file", ""):
                have_variant = 2
            elif doc.get("download_page", ""):
                have_variant = 1
            else:
                have_variant = 0

            parent_uuid = doc.get("parent_uuid", "")
            variant_name = doc.get("variant_name", "")
            # published_variant = doc.get("publish", "")
            published_variant = doc.get("__publish_hack__", "")
            if not published_variant:
                published_variant = None
            elif published_variant == "1":
                published_variant = 1
            else:
                published_variant = 0

            game_variant_id = existing_variant[2]
            if not game_variant_id:
                # variant is not in database
                database_cursor.execute(
                    "INSERT INTO game_variant (uuid) VALUES (?)",
                    (variant_uuid,),
                )
                game_variant_id = database_cursor.lastrowid

            database_cursor.execute(
                "UPDATE game_variant SET name = ?, game_uuid = ?, have = ?, "
                "update_stamp = ?, database = ?, published = ? WHERE id = ?",
                (
                    variant_name,
                    parent_uuid,
                    have_variant,
                    update_stamp,
                    database_name,
                    published_variant,
                    game_variant_id,
                ),
            )

            # ensure_updated_games.add(parent_uuid)

        for row in game_rows:
            if self.stop_check():
                return

            game_id, game_uuid_bin = row
            game_uuid = binary_to_uuid(game_uuid_bin)
            update_stamp = game_id

            existing_game = helper.existing_games.get(
                game_uuid, (None, None, None)
            )

            if update_stamp == existing_game[0]:
                # after the loop has run its course, games to be removed
                # are left in existing_games
                helper.game_seen(game_uuid)
                continue

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

            doc = game_database.get_game_values(game_id)

            entry_type = int(doc.get("_type", "0"))
            if (entry_type & GAME_ENTRY_TYPE_GAME) == 0:
                continue

            # after the loop has run its course, games to be removed
            # are left in existing_games
            try:
                del helper.existing_games[game_uuid]
            except KeyError:
                pass

            game_name = doc.get("game_name", "")
            game_subtitle = doc.get("game_subtitle", "")

            platform = doc.get("platform", "")
            tags = doc.get("tags", "")
            year = doc.get("year", "")
            publisher = doc.get("publisher", "")

            front_sha1 = doc.get("front_sha1", "")
            title_sha1 = doc.get("title_sha1", "")
            screen1_sha1 = doc.get("screen1_sha1", "")
            screen2_sha1 = doc.get("screen2_sha1", "")
            screen3_sha1 = doc.get("screen3_sha1", "")
            screen4_sha1 = doc.get("screen4_sha1", "")
            screen5_sha1 = doc.get("screen5_sha1", "")
            thumb_sha1 = doc.get("thumb_sha1", "")
            backdrop_sha1 = doc.get("backdrop_sha1", "")
            published = doc.get("publish", "")
            sort_key = doc.get("sort_key", "")
            if not sort_key:
                # FIXME: handle the/a (etc)
                sort_key = game_name.lower()

            game_id = existing_game[2]
            if not game_id:
                # game is not in database
                database_cursor.execute(
                    "INSERT INTO game (uuid) VALUES (?)", (game_uuid,)
                )
                game_id = database_cursor.lastrowid

            search_terms = set()
            for key in [
                "game_name",
                "full_name",
                "game_name_alt",
                "search_terms",
                "game_subtitle",
            ]:
                value = doc.get(key, "")
                if value:
                    search_terms.update(
                        GameNameUtil.extract_index_terms(value)
                    )

            letter = ""
            if len(sort_key) > 0:
                letter = sort_key[0].lower()
            if letter in "abcdefghijklmnopqrstuvwxyz":
                pass
            elif letter in "0123456789":
                letter = "#"
            else:
                letter = "?"
            search_terms.add("l:" + letter)
            for tag in tags.split(","):
                tag = tag.strip().lower()
                search_terms.add("t:" + tag)
            if year:
                search_terms.add("y:" + str(year))
            if platform:
                search_terms.add("s:" + platform.lower())

            if thumb_sha1:
                search_terms.add("t:thumb")
            if backdrop_sha1:
                search_terms.add("t:backdrop")
                backdrop_image = "sha1:{}/{}/{}/{}/{}".format(
                    backdrop_sha1,
                    doc.get("backdrop_zoom", "1.0"),
                    doc.get("backdrop_zoom", "1.0"),
                    doc.get("backdrop_halign", "0.5"),
                    doc.get("backdrop_valign", "0.5"),
                )
            else:
                backdrop_image = ""
            # if published:
            #     # search_terms.add("t:published")
            #     pass
            # else:
            #     search_terms.add("t:unpublished")

            min_players = 0
            max_players = 0
            sim_players = 0
            players = doc.get("players", "")
            if players == "1":
                min_players = max_players = 1
                search_terms.add("p:1")
            elif players:
                try:
                    parts1 = players.split("-")
                    parts2 = parts1[1].split("(")
                    min_players = int(parts1[0].strip())
                    max_players = int(parts2[0].strip())
                    sim_players = int(parts2[1].strip(" )"))
                except Exception as e:
                    print("error parsing players")
                    print(repr(e))
            if min_players > 0:
                if max_players > 0:
                    # we ignore players = 1 here, that is reserved for games
                    # with max 1 players
                    for i in range(min_players + 1, max_players + 1):
                        search_terms.add("p:{0}".format(i))
                if sim_players > 0:
                    # we ignore players = 1 here, that is reserved for games
                    # with max 1 players
                    for i in range(min_players + 1, sim_players + 1):
                        search_terms.add("p:{0}s".format(i))

            database_cursor.execute(
                "UPDATE game SET name = ?, update_stamp = ?, sort_key = ?, "
                "platform = ?, "
                "publisher = ?, year = ?, front_image = ?, title_image = ?, "
                "screen1_image = ?, screen2_image = ?, screen3_image = ?, "
                "screen4_image = ?, screen5_image = ?, "
                "thumb_image = ?, backdrop_image = ?, "
                "adult = ?, published = ?, subtitle = ? WHERE id = ?",
                (
                    game_name,
                    update_stamp,
                    sort_key,
                    platform,
                    publisher or "",
                    year or 0,
                    "sha1:" + front_sha1 if front_sha1 else "",
                    "sha1:" + title_sha1 if title_sha1 else "",
                    "sha1:" + screen1_sha1 if screen1_sha1 else "",
                    "sha1:" + screen2_sha1 if screen2_sha1 else "",
                    "sha1:" + screen3_sha1 if screen3_sha1 else "",
                    "sha1:" + screen4_sha1 if screen4_sha1 else "",
                    "sha1:" + screen5_sha1 if screen5_sha1 else "",
                    "sha1:" + thumb_sha1 if thumb_sha1 else "",
                    backdrop_image,
                    1 if "t:adult" in search_terms else 0,
                    1 if published == "1" else 0,
                    game_subtitle,
                    game_id,
                ),
            )

            helper.database.update_game_search_terms(game_id, search_terms)
예제 #14
0
 def create_search_terms(cls, name):
     search_terms = set()
     game_name = name.split("(", 1)[0]
     search_terms.update(GameNameUtil.extract_index_terms(game_name))
     return search_terms
예제 #15
0
 def screenshots_name(self):
     # FIXME: REMOVE?
     return GameNameUtil.create_fs_name(self.game_name())
예제 #16
0
 def screenshots_base(self):
     return GameNameUtil.create_link_name(self.game_name())
예제 #17
0
    def scan_game_database(self, helper, database_name, game_database):
        """
        :type helper: ScanHelper
        :type database_name: str
        :type game_database: fsgs.GameDatabase.GameDatabase
        """
        database_cursor = helper.database.cursor()

        # this holds a list of game entry UUIDs which must exist / be checked
        # after variants have been processed
        # ensure_updated_games = set()

        game_database_cursor = game_database.cursor()

        # this list will contain game entries which are not variants
        game_rows = []

        game_database_cursor.execute(
            "SELECT id, uuid FROM game WHERE data != ''")
        for row in game_database_cursor:
            if self.stop_check():
                return

            variant_id, variant_uuid_bin = row
            variant_uuid = binary_to_uuid(variant_uuid_bin)
            update_stamp = variant_id

            existing_variant = helper.existing_variants.get(
                variant_uuid, (None, None, None))

            existing_game = helper.existing_games.get(variant_uuid,
                                                      (None, None, None))
            if update_stamp == existing_game[0]:
                # Game entry, not updated.
                game_rows.append(row)
                continue

            if update_stamp == existing_variant[0]:
                # entry was already updated and has not changed
                if existing_variant[1] and not helper.deleted_files:
                    # have this entry already and no files have been deleted
                    # since the last time

                    # print("skipping variant (no deleted files)")
                    helper.variant_seen(variant_uuid)
                    continue
                if not existing_variant[1] and not helper.added_files:
                    # do not have this entry, but no files have been added
                    # since the last time

                    # print("skipping variant (no added files)")
                    helper.variant_seen(variant_uuid)
                    continue
            else:
                # when the game entry has changed, we always check it
                # regardless of file database status, since file_list may
                # have been changed, or download status... (or other info
                # needs to be corrected)
                # print("[SCANNER] Changed: {}".format(variant_uuid))
                pass

            self.scan_count += 1
            self.set_status(
                gettext("Scanning game variants ({count} scanned)").format(
                    count=self.scan_count),
                variant_uuid,
            )

            try:
                doc = self.fsgs.game.get_game_values_for_id(
                    game_database, variant_id)
            except IncompleteGameException as e:
                print("[SCANNER]", repr(e))
                continue

            file_list_json = doc.get("file_list", "")
            if not file_list_json:
                # not a game variant... (parent game only probably)
                game_rows.append(row)
                continue

            entry_type = int(doc.get("_type", "0"))
            if (entry_type & GAME_ENTRY_TYPE_VARIANT) == 0:
                # game entry is not tagged with variant -- add to game list
                # instead
                game_rows.append(row)
                continue

            helper.variant_seen(variant_uuid)

            all_files_found = True
            try:
                file_list = json.loads(file_list_json)
            except Exception:
                # invalid JSON string
                # FIXME: log error
                all_files_found = False
                file_list = []

            for file_item in file_list:
                if file_item["name"].endswith("/"):
                    # skip directory entries:
                    continue
                result = self.fsgs.file.check_sha1(file_item["sha1"])
                if not result:
                    all_files_found = False
                    break

            if all_files_found:
                have_variant = 4
            elif doc.get("download_file", ""):
                have_variant = 2
            elif doc.get("download_page", ""):
                have_variant = 1
            else:
                have_variant = 0

            parent_uuid = doc.get("parent_uuid", "")
            variant_name = doc.get("variant_name", "")
            # published_variant = doc.get("publish", "")
            published_variant = doc.get("__publish_hack__", "")
            if not published_variant:
                published_variant = None
            elif published_variant == "1":
                published_variant = 1
            else:
                published_variant = 0

            game_variant_id = existing_variant[2]
            if not game_variant_id:
                # variant is not in database
                database_cursor.execute(
                    "INSERT INTO game_variant (uuid) VALUES (?)",
                    (variant_uuid, ),
                )
                game_variant_id = database_cursor.lastrowid

            database_cursor.execute(
                "UPDATE game_variant SET name = ?, game_uuid = ?, have = ?, "
                "update_stamp = ?, database = ?, published = ? WHERE id = ?",
                (
                    variant_name,
                    parent_uuid,
                    have_variant,
                    update_stamp,
                    database_name,
                    published_variant,
                    game_variant_id,
                ),
            )

            # ensure_updated_games.add(parent_uuid)

        for row in game_rows:
            if self.stop_check():
                return

            game_id, game_uuid_bin = row
            game_uuid = binary_to_uuid(game_uuid_bin)
            update_stamp = game_id

            existing_game = helper.existing_games.get(game_uuid,
                                                      (None, None, None))

            if update_stamp == existing_game[0]:
                # after the loop has run its course, games to be removed
                # are left in existing_games
                helper.game_seen(game_uuid)
                continue

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

            doc = game_database.get_game_values(game_id)

            entry_type = int(doc.get("_type", "0"))
            if (entry_type & GAME_ENTRY_TYPE_GAME) == 0:
                continue

            # after the loop has run its course, games to be removed
            # are left in existing_games
            try:
                del helper.existing_games[game_uuid]
            except KeyError:
                pass

            game_name = doc.get("game_name", "")
            game_subtitle = doc.get("game_subtitle", "")

            platform = doc.get("platform", "")
            tags = doc.get("tags", "")
            year = doc.get("year", "")
            publisher = doc.get("publisher", "")

            front_sha1 = doc.get("front_sha1", "")
            title_sha1 = doc.get("title_sha1", "")
            screen1_sha1 = doc.get("screen1_sha1", "")
            screen2_sha1 = doc.get("screen2_sha1", "")
            screen3_sha1 = doc.get("screen3_sha1", "")
            screen4_sha1 = doc.get("screen4_sha1", "")
            screen5_sha1 = doc.get("screen5_sha1", "")
            thumb_sha1 = doc.get("thumb_sha1", "")
            backdrop_sha1 = doc.get("backdrop_sha1", "")
            published = doc.get("publish", "")
            sort_key = doc.get("sort_key", "")
            if not sort_key:
                # FIXME: handle the/a (etc)
                sort_key = game_name.lower()

            game_id = existing_game[2]
            if not game_id:
                # game is not in database
                database_cursor.execute("INSERT INTO game (uuid) VALUES (?)",
                                        (game_uuid, ))
                game_id = database_cursor.lastrowid

            search_terms = set()
            for key in [
                    "game_name",
                    "full_name",
                    "game_name_alt",
                    "search_terms",
                    "game_subtitle",
            ]:
                value = doc.get(key, "")
                if value:
                    search_terms.update(
                        GameNameUtil.extract_index_terms(value))

            letter = ""
            if len(sort_key) > 0:
                letter = sort_key[0].lower()
            if letter in "abcdefghijklmnopqrstuvwxyz":
                pass
            elif letter in "0123456789":
                letter = "#"
            else:
                letter = "?"
            search_terms.add("l:" + letter)
            for tag in tags.split(","):
                tag = tag.strip().lower()
                search_terms.add("t:" + tag)
            if year:
                search_terms.add("y:" + str(year))
            if platform:
                search_terms.add("s:" + platform.lower())

            if thumb_sha1:
                search_terms.add("t:thumb")
            if backdrop_sha1:
                search_terms.add("t:backdrop")
                backdrop_image = "sha1:{}/{}/{}/{}/{}".format(
                    backdrop_sha1,
                    doc.get("backdrop_zoom", "1.0"),
                    doc.get("backdrop_zoom", "1.0"),
                    doc.get("backdrop_halign", "0.5"),
                    doc.get("backdrop_valign", "0.5"),
                )
            else:
                backdrop_image = ""
            # if published:
            #     # search_terms.add("t:published")
            #     pass
            # else:
            #     search_terms.add("t:unpublished")

            min_players = 0
            max_players = 0
            sim_players = 0
            players = doc.get("players", "")
            if players == "1":
                min_players = max_players = 1
                search_terms.add("p:1")
            elif players:
                try:
                    parts1 = players.split("-")
                    parts2 = parts1[1].split("(")
                    min_players = int(parts1[0].strip())
                    max_players = int(parts2[0].strip())
                    sim_players = int(parts2[1].strip(" )"))
                except Exception as e:
                    print("error parsing players")
                    print(repr(e))
            if min_players > 0:
                if max_players > 0:
                    # we ignore players = 1 here, that is reserved for games
                    # with max 1 players
                    for i in range(min_players + 1, max_players + 1):
                        search_terms.add("p:{0}".format(i))
                if sim_players > 0:
                    # we ignore players = 1 here, that is reserved for games
                    # with max 1 players
                    for i in range(min_players + 1, sim_players + 1):
                        search_terms.add("p:{0}s".format(i))

            database_cursor.execute(
                "UPDATE game SET name = ?, update_stamp = ?, sort_key = ?, "
                "platform = ?, "
                "publisher = ?, year = ?, front_image = ?, title_image = ?, "
                "screen1_image = ?, screen2_image = ?, screen3_image = ?, "
                "screen4_image = ?, screen5_image = ?, "
                "thumb_image = ?, backdrop_image = ?, "
                "adult = ?, published = ?, subtitle = ? WHERE id = ?",
                (
                    game_name,
                    update_stamp,
                    sort_key,
                    platform,
                    publisher or "",
                    year or 0,
                    "sha1:" + front_sha1 if front_sha1 else "",
                    "sha1:" + title_sha1 if title_sha1 else "",
                    "sha1:" + screen1_sha1 if screen1_sha1 else "",
                    "sha1:" + screen2_sha1 if screen2_sha1 else "",
                    "sha1:" + screen3_sha1 if screen3_sha1 else "",
                    "sha1:" + screen4_sha1 if screen4_sha1 else "",
                    "sha1:" + screen5_sha1 if screen5_sha1 else "",
                    "sha1:" + thumb_sha1 if thumb_sha1 else "",
                    backdrop_image,
                    1 if "t:adult" in search_terms else 0,
                    1 if published == "1" else 0,
                    game_subtitle,
                    game_id,
                ),
            )

            helper.database.update_game_search_terms(game_id, search_terms)
예제 #18
0
def main():
    Application("fs-uae-game-system")

    if "--unsupported" in sys.argv:
        if "--http-server" in sys.argv:
            from fsgs.http.server import http_server_main

            return http_server_main()

    if len(sys.argv) < 3:
        print("")
        print("usage: fsgs run <game>")
        print("")
        print("game:")
        print(" - search term(s) identifying a single game")
        print(" - path to a .fsgs file")
        print(" - path to a recognized cartridge ROM or disk file format")
        print("")
        sys.exit(1)
    assert sys.argv[1] == "run"
    game_arg = " ".join(sys.argv[2:])
    print(game_arg)
    if os.path.exists(game_arg):
        load_file(game_arg)
    else:
        search = game_arg.lower()
        database = Database.instance()
        # cursor.execute("SELECT id FROM game WHERE name like")
        terms = GameNameUtil.extract_search_terms(search)
        found_games = database.find_games_new(" ".join(terms))
        games = []
        for game in found_games:
            print(list(game))
            if game[0]:
                # only process entries with a game uuid
                games.append(game)
        game_uuid = None
        if len(games) == 0:
            print("no games found")
            sys.exit(2)
        if len(games) > 1:
            matches = 0
            for row in games:
                if row[1].lower() == search:
                    if game_uuid is None:
                        game_uuid = row[0]
                        matches += 1
            if matches != 1:
                print("")
                print("More than one game matches:")
                print("")
                for row in games:
                    print("    {0} ({1})".format(row[1], row[2]))
                    print("        {0}".format(row[0]))
                print("")
                sys.exit(3)
        game_uuid = games[0][0]
        assert game_uuid
        variant_uuid = find_preferred_variant(game_uuid)
        load_game_variant(variant_uuid)
    fsgs.run_game()
예제 #19
0
 def screenshots_name(self):
     return GameNameUtil.create_fs_name(self.get_name())
예제 #20
0
 def screenshots_name(self):
     # FIXME: REMOVE?
     return GameNameUtil.create_fs_name(self.game_name())
예제 #21
0
    def find_disks(
        cls, path, base_names=None, script=None, file_list=None, black_list={}
    ):
        disks = [path]
        print("")
        print("FIRST DISK", path)
        print("")
        # disks = []
        if script:
            use_name = script.rename_file(os.path.basename(path))
        else:
            use_name = os.path.basename(path)
        number = GameNameUtil.find_number(use_name)
        disk_count = GameNameUtil.find_disk_count(use_name)
        first_without_number = GameNameUtil.strip_number(use_name)
        first_without_flags = GameNameUtil.strip_flags(first_without_number)
        if number is None:
            # only this disk
            return disks
        base_name = GameNameUtil.find_base_name(path)
        dir = os.path.dirname(path)
        candidates = {}
        items = []
        if base_names:
            items = base_names[base_name]
        else:
            if file_list:
                all_items = file_list
            else:
                all_items = os.listdir(dir)
            for item in all_items:
                b = GameNameUtil.find_base_name(item)
                if base_name == b:
                    items.append(item)
        # print("items is", items)
        for item in items:
            if script:
                use_name = script.rename_file(item)
            else:
                use_name = item
            # print(item)
            if GameNameUtil.is_bad_dump(use_name):
                continue
            if GameNameUtil.find_disk_count(use_name) != disk_count:
                continue
            n = GameNameUtil.find_number(use_name)
            if n == 0:
                n = 99
            if n:
                candidates.setdefault(n, []).append(
                    (use_name, os.path.join(dir, item))
                )
        # print(candidates)
        for n, items in candidates.items():
            if n == 1:
                # already added first floppy
                continue
            print("")
            print("Candidates:")
            for item in items:
                print(item[0])
            print("")
            print("FIND FLOPPY NUMBER", n)
            print("")
            matches = []
            for use_name, p in items:
                without_number = GameNameUtil.strip_number(use_name)
                # print(without_number, "vs", first_without_number)
                if without_number == first_without_number:
                    # print("perfect match:", p)
                    # disks.append(p)
                    matches.append((-1000, p))
                    continue
                    # break
                without_flags = GameNameUtil.strip_flags(without_number)
                if without_flags == first_without_flags:

                    flags_1 = extract_flags(first_without_number)
                    cr_flag_1 = ""
                    for flag in flags_1:
                        if flag.startswith("cr"):
                            cr_flag_1 = flag

                    flags_n = extract_flags(without_number)
                    cr_flag_n = ""
                    for flag in flags_n:
                        if flag.startswith("cr"):
                            cr_flag_n = flag

                    score = 0

                    # if cr_flag_n and cr_flag_1 != cr_flag_n:
                    if cr_flag_1 and cr_flag_n and cr_flag_1 != cr_flag_n:
                        # not same cracker
                        score += 10000

                    if "[o" in without_number:
                        score += 20000

                    flag_set_1 = set(flags_1)
                    flag_set_n = set(flags_n)

                    extra_flags_in_1 = flag_set_1.difference(flag_set_n)
                    extra_flags_in_n = flag_set_n.difference(flag_set_1)

                    # score += len(extra_flags_in_1)
                    print(extra_flags_in_1)
                    for flag in extra_flags_in_1:
                        score += 10 - flags_1.index(flag)
                    score += len(extra_flags_in_n) * 100
                    print(score, p)
                    matches.append((score, p))

                    # if without_flags == without_number:
                    #     # there were no flags on this floppy
                    #     matches.append((1, p))
                    # else:
                    #     # slightly worse score since there were flags
                    #     # not matching floppy 1
                    #     matches.append((100, p))

            if len(matches) == 0:
                # raise Exception("no candidates for floppy " + num)
                # print("WARNING: choosing partial matching floppy", p,
                #         "for floppy number", n)
                # disks.append(p)
                print("Did not find good match for floppy", n)
                print("candidates:")
                for item in items:
                    print("  ", item)
                raise Exception(
                    "Did not find good match for floppy {0}".format(n)
                )
            matches.sort()

            print("")
            print("Matches:")
            for match in matches:
                print(match[0], match[1])
            print("")
            score, p = matches[0]
            # if score == 2:
            disks.append(p)
            # TOSEC (x of y) disk number labelling format
            if " of {0})".format(n) in path:
                # found the correct number of disks
                break
        print("")
        print("Result:")
        for disk in disks:
            print(disk)
        print("")
        return disks
예제 #22
0
 def screenshots_name(self):
     return GameNameUtil.create_fs_name(self.get_name())
예제 #23
0
 def find_disks(cls, path, base_names=None, script=None):
     disks = [path]
     print("")
     print("FIRST DISK", path)
     print("")
     # disks = []
     use_name = script.rename_file(os.path.basename(path))
     number = GameNameUtil.find_number(use_name)
     first_without_number = GameNameUtil.strip_number(use_name)
     first_without_flags = GameNameUtil.strip_flags(first_without_number)
     if number is None:
         # only this disk
         return disks
     base_name = GameNameUtil.find_base_name(path)
     dir = os.path.dirname(path)
     candidates = {}
     items = []
     if base_names:
         items = base_names[base_name]
     else:
         all_items = os.listdir(dir)
         for item in all_items:
             b = GameNameUtil.find_base_name(item)
             if base_name == b:
                 items.append(item)
     # print("items is", items)
     for item in items:
         use_name = script.rename_file(item)
         if GameNameUtil.is_bad_dump(use_name):
             continue
         n = GameNameUtil.find_number(use_name)
         if n == 0:
             n = 99
         if n:
             candidates.setdefault(n, []).append(
                 (use_name, os.path.join(dir, item)))
     # print(candidates)
     for n, items in candidates.items():
         print("")
         print("FIND FLOPPIES FOR n", n, "=", items)
         print("")
         if n == 1:
             # already added first floppy
             continue
         print(" - floppy number", n)
         matches = []
         for use_name, p in items:
             without_number = GameNameUtil.strip_number(use_name)
             # print(without_number, "vs", first_without_number)
             if without_number == first_without_number:
                 print("perfect match")
                 # disks.append(p)
                 matches.append((0, p))
                 continue
                 # break
             without_flags = GameNameUtil.strip_flags(without_number)
             if without_flags == first_without_flags:
                 print("ok match")
                 if without_flags == without_number:
                     # there were no flags on this floppy
                     matches.append((1, p))
                 else:
                     # slightly worse score since there were flags
                     # not matching floppy 1
                     matches.append((2, p))
                     # disks.append(p)
                     # break
                     # matches.append((2, p))
         if len(matches) == 0:
             # raise Exception("no candidates for floppy " + num)
             # print("WARNING: choosing partial matching floppy", p,
             #         "for floppy number", n)
             # disks.append(p)
             print("Did not find good match for floppy", n)
             print("candidates:")
             for item in items:
                 print("  ", item)
             raise Exception(
                 "Did not find good match for floppy {0}".format(n))
         matches.sort()
         print(matches)
         score, p = matches[0]
         # if score == 2:
         disks.append(p)
         # TOSEC (x of y) disk number labelling format
         if " of {0})".format(n) in path:
             # found the correct number of disks
             break
     return disks
 def create_search_terms(cls, name):
     search_terms = set()
     game_name = name.split("(", 1)[0]
     search_terms.update(GameNameUtil.extract_index_terms(game_name))
     return search_terms
예제 #25
0
    def find_disks(cls,
                   path,
                   base_names=None,
                   script=None,
                   file_list=None,
                   black_list={}):
        disks = [path]
        print("")
        print("FIRST DISK", path)
        print("")
        # disks = []
        if script:
            use_name = script.rename_file(os.path.basename(path))
        else:
            use_name = os.path.basename(path)
        number = GameNameUtil.find_number(use_name)
        disk_count = GameNameUtil.find_disk_count(use_name)
        first_without_number = GameNameUtil.strip_number(use_name)
        first_without_flags = GameNameUtil.strip_flags(first_without_number)
        if number is None:
            # only this disk
            return disks
        base_name = GameNameUtil.find_base_name(path)
        dir = os.path.dirname(path)
        candidates = {}
        items = []
        if base_names:
            items = base_names[base_name]
        else:
            if file_list:
                all_items = file_list
            else:
                all_items = os.listdir(dir)
            for item in all_items:
                b = GameNameUtil.find_base_name(item)
                if base_name == b:
                    items.append(item)
        # print("items is", items)
        for item in items:
            if script:
                use_name = script.rename_file(item)
            else:
                use_name = item
            # print(item)
            if GameNameUtil.is_bad_dump(use_name):
                continue
            if GameNameUtil.find_disk_count(use_name) != disk_count:
                continue
            n = GameNameUtil.find_number(use_name)
            if n == 0:
                n = 99
            if n:
                candidates.setdefault(n, []).append(
                    (use_name, os.path.join(dir, item)))
        # print(candidates)
        for n, items in candidates.items():
            if n == 1:
                # already added first floppy
                continue
            print("")
            print("Candidates:")
            for item in items:
                print(item[0])
            print("")
            print("FIND FLOPPY NUMBER", n)
            print("")
            matches = []
            for use_name, p in items:
                without_number = GameNameUtil.strip_number(use_name)
                # print(without_number, "vs", first_without_number)
                if without_number == first_without_number:
                    # print("perfect match:", p)
                    # disks.append(p)
                    matches.append((-1000, p))
                    continue
                    # break
                without_flags = GameNameUtil.strip_flags(without_number)
                if without_flags == first_without_flags:

                    flags_1 = extract_flags(first_without_number)
                    cr_flag_1 = ""
                    for flag in flags_1:
                        if flag.startswith("cr"):
                            cr_flag_1 = flag

                    flags_n = extract_flags(without_number)
                    cr_flag_n = ""
                    for flag in flags_n:
                        if flag.startswith("cr"):
                            cr_flag_n = flag

                    score = 0

                    # if cr_flag_n and cr_flag_1 != cr_flag_n:
                    if cr_flag_1 and cr_flag_n and cr_flag_1 != cr_flag_n:
                        # not same cracker
                        score += 10000

                    if "[o" in without_number:
                        score += 20000

                    flag_set_1 = set(flags_1)
                    flag_set_n = set(flags_n)

                    extra_flags_in_1 = flag_set_1.difference(flag_set_n)
                    extra_flags_in_n = flag_set_n.difference(flag_set_1)

                    # score += len(extra_flags_in_1)
                    print(extra_flags_in_1)
                    for flag in extra_flags_in_1:
                        score += (10 - flags_1.index(flag))
                    score += len(extra_flags_in_n) * 100
                    print(score, p)
                    matches.append((score, p))

                    # if without_flags == without_number:
                    #     # there were no flags on this floppy
                    #     matches.append((1, p))
                    # else:
                    #     # slightly worse score since there were flags
                    #     # not matching floppy 1
                    #     matches.append((100, p))

            if len(matches) == 0:
                # raise Exception("no candidates for floppy " + num)
                # print("WARNING: choosing partial matching floppy", p,
                #         "for floppy number", n)
                # disks.append(p)
                print("Did not find good match for floppy", n)
                print("candidates:")
                for item in items:
                    print("  ", item)
                raise Exception(
                    "Did not find good match for floppy {0}".format(n))
            matches.sort()

            print("")
            print("Matches:")
            for match in matches:
                print(match[0], match[1])
            print("")
            score, p = matches[0]
            # if score == 2:
            disks.append(p)
            # TOSEC (x of y) disk number labelling format
            if ' of {0})'.format(n) in path:
                # found the correct number of disks
                break
        print("")
        print("Result:")
        for disk in disks:
            print(disk)
        print("")
        return disks
예제 #26
0
 def screenshots_base(self):
     return GameNameUtil.create_link_name(self.game_name())