diff --git a/__main__.py b/__main__.py index 12ce8be..b69d18a 100644 --- a/__main__.py +++ b/__main__.py @@ -1,6 +1,6 @@ import os os.environ["SDL_FBDEV"] = "/dev/fb0" -import pygame +import pygame # type: ignore import asyncio import platform import subprocess @@ -9,7 +9,7 @@ import logging import requests import sys import json -from display import init_display, draw_loading_screen, draw_error_screen, draw_platform_grid, draw_progress_screen, draw_scrollbar, draw_confirm_dialog, draw_controls, draw_gradient, draw_virtual_keyboard, draw_popup_message, draw_extension_warning, draw_pause_menu, draw_controls_help, draw_game_list, draw_history, draw_clear_history_dialog +from display import init_display, draw_loading_screen, draw_error_screen, draw_platform_grid, draw_progress_screen, draw_controls, draw_gradient, draw_virtual_keyboard, draw_popup_message, draw_extension_warning, draw_pause_menu, draw_controls_help, draw_game_list, draw_history_list, draw_clear_history_dialog, draw_confirm_dialog, draw_redownload_game_cache_dialog, draw_popup from network import test_internet, download_rom, check_extension_before_download, extract_zip from controls import handle_controls, validate_menu_state from controls_mapper import load_controls_config, map_controls, draw_controls_mapping, ACTIONS @@ -44,8 +44,8 @@ OTA_data_ZIP = f"{OTA_SERVER_URL}/rgsx-data.zip" # Constantes pour la répétition automatique dans pause_menu REPEAT_DELAY = 300 # Délai initial avant répétition (ms) -REPEAT_INTERVAL = 100 # Intervalle entre répétitions (ms) -REPEAT_ACTION_DEBOUNCE = 50 # Délai anti-rebond pour répétitions (ms) +REPEAT_INTERVAL = 150 # Intervalle entre répétitions (ms), augmenté pour réduire la fréquence +REPEAT_ACTION_DEBOUNCE = 100 # Délai anti-rebond pour répétitions (ms), augmenté pour éviter les répétitions excessives # Initialisation de Pygame et des polices pygame.init() @@ -276,6 +276,20 @@ async def main(): if config.menu_state == "download_progress" and current_time - last_redraw_time >= 100: config.needs_redraw = True last_redraw_time = current_time + + # Dans __main__.py, dans la boucle principale + current_time = pygame.time.get_ticks() + delta_time = current_time - config.last_frame_time + config.last_frame_time = current_time + if config.menu_state == "restart_popup" and config.popup_timer > 0: + config.popup_timer -= delta_time + config.needs_redraw = True + if config.popup_timer <= 0: + config.menu_state = validate_menu_state(config.previous_menu_state) + config.popup_message = "" + config.popup_timer = 0 + config.needs_redraw = True + logger.debug(f"Fermeture automatique du popup, retour à {config.menu_state}") # Gestion des événements events = pygame.event.get() @@ -298,117 +312,15 @@ async def main(): if config.menu_state not in ["pause_menu", "controls_help", "controls_mapping", "history", "confirm_clear_history"]: config.previous_menu_state = config.menu_state config.menu_state = "pause_menu" - config.selected_pause_option = 0 + config.selected_option = 0 config.needs_redraw = True logger.debug(f"Ouverture menu pause depuis {config.previous_menu_state}") continue - + if config.menu_state == "pause_menu": - current_time = pygame.time.get_ticks() - if event.type in (pygame.KEYDOWN, pygame.JOYBUTTONDOWN, pygame.JOYAXISMOTION, pygame.JOYHATMOTION): - up_config = config.controls_config.get("up", {}) - down_config = config.controls_config.get("down", {}) - confirm_config = config.controls_config.get("confirm", {}) - cancel_config = config.controls_config.get("cancel", {}) - - if current_time - config.last_state_change_time < config.debounce_delay: - continue - - if ( - (event.type == pygame.KEYDOWN and up_config and event.key == up_config.get("value")) or - (event.type == pygame.JOYBUTTONDOWN and up_config and up_config.get("type") == "button" and event.button == up_config.get("value")) or - (event.type == pygame.JOYAXISMOTION and up_config and up_config.get("type") == "axis" and event.axis == up_config.get("value")[0] and abs(event.value) > 0.5 and (1 if event.value > 0 else -1) == up_config.get("value")[1]) or - (event.type == pygame.JOYHATMOTION and up_config and up_config.get("type") == "hat" and event.value == tuple(up_config.get("value"))) - ): - config.selected_pause_option = max(0, config.selected_pause_option - 1) - config.repeat_action = "up" - config.repeat_start_time = current_time + REPEAT_DELAY - config.repeat_last_action = current_time - config.repeat_key = event.key if event.type == pygame.KEYDOWN else event.button if event.type == pygame.JOYBUTTONDOWN else (event.axis, 1 if event.value > 0 else -1) if event.type == pygame.JOYAXISMOTION else event.value - config.needs_redraw = True - logger.debug(f"Menu pause: Haut, selected_option={config.selected_pause_option}, repeat_action={config.repeat_action}") - elif ( - (event.type == pygame.KEYDOWN and down_config and event.key == down_config.get("value")) or - (event.type == pygame.JOYBUTTONDOWN and down_config and down_config.get("type") == "button" and event.button == down_config.get("value")) or - (event.type == pygame.JOYAXISMOTION and down_config and down_config.get("type") == "axis" and event.axis == down_config.get("value")[0] and abs(event.value) > 0.5 and (1 if event.value > 0 else -1) == down_config.get("value")[1]) or - (event.type == pygame.JOYHATMOTION and down_config and down_config.get("type") == "hat" and event.value == tuple(down_config.get("value"))) - ): - config.selected_pause_option = min(3, config.selected_pause_option + 1) - config.repeat_action = "down" - config.repeat_start_time = current_time + REPEAT_DELAY - config.repeat_last_action = current_time - config.repeat_key = event.key if event.type == pygame.KEYDOWN else event.button if event.type == pygame.JOYBUTTONDOWN else (event.axis, 1 if event.value > 0 else -1) if event.type == pygame.JOYAXISMOTION else event.value - config.needs_redraw = True - logger.debug(f"Menu pause: Bas, selected_option={config.selected_pause_option}, repeat_action={config.repeat_action}") - elif ( - (event.type == pygame.KEYDOWN and confirm_config and event.key == confirm_config.get("value")) or - (event.type == pygame.JOYBUTTONDOWN and confirm_config and confirm_config.get("type") == "button" and event.button == confirm_config.get("value")) or - (event.type == pygame.JOYAXISMOTION and confirm_config and confirm_config.get("type") == "axis" and event.axis == confirm_config.get("value")[0] and abs(event.value) > 0.5 and (1 if event.value > 0 else -1) == confirm_config.get("value")[1]) or - (event.type == pygame.JOYHATMOTION and confirm_config and confirm_config.get("type") == "hat" and event.value == tuple(confirm_config.get("value"))) - ): - if config.selected_pause_option == 0: - config.previous_menu_state = validate_menu_state(config.previous_menu_state) - config.menu_state = "controls_help" - config.needs_redraw = True - logger.debug("Menu pause: Aide sélectionnée") - elif config.selected_pause_option == 1: - config.previous_menu_state = validate_menu_state(config.previous_menu_state) - if map_controls(screen): - config.menu_state = config.previous_menu_state if config.previous_menu_state in ["platform", "game", "download_progress", "download_result", "confirm_exit", "extension_warning", "history"] else "platform" - config.controls_config = load_controls_config() - logger.debug(f"Mappage des contrôles terminé, retour à {config.menu_state}") - else: - config.menu_state = "error" - config.error_message = "Échec du mappage des contrôles" - config.needs_redraw = True - logger.debug("Échec du mappage des contrôles") - elif config.selected_pause_option == 2: - config.previous_menu_state = validate_menu_state(config.previous_menu_state) - config.menu_state = "history" - config.current_history_item = 0 - config.history_scroll_offset = 0 - config.needs_redraw = True - logger.debug("Menu pause: Historique sélectionné") - elif config.selected_pause_option == 3: - config.previous_menu_state = validate_menu_state(config.previous_menu_state) - config.menu_state = "confirm_exit" - config.confirm_selection = 0 - config.needs_redraw = True - logger.debug("Menu pause: Quitter sélectionné") - elif ( - (event.type == pygame.KEYDOWN and cancel_config and event.key == cancel_config.get("value")) or - (event.type == pygame.JOYBUTTONDOWN and cancel_config and cancel_config.get("type") == "button" and event.button == cancel_config.get("value")) or - (event.type == pygame.JOYAXISMOTION and cancel_config and cancel_config.get("type") == "axis" and event.axis == cancel_config.get("value")[0] and abs(event.value) > 0.5 and (1 if event.value > 0 else -1) == cancel_config.get("value")[1]) or - (event.type == pygame.JOYHATMOTION and cancel_config and cancel_config.get("type") == "hat" and event.value == tuple(cancel_config.get("value"))) - ): - config.menu_state = config.previous_menu_state if config.previous_menu_state in ["platform", "game", "download_progress", "download_result", "confirm_exit", "extension_warning", "history"] else "platform" - config.needs_redraw = True - logger.debug(f"Menu pause: Annulation, retour à {config.menu_state}") - - elif event.type in (pygame.KEYUP, pygame.JOYBUTTONUP): - if ( - (event.type == pygame.KEYUP and is_input_matched(event, "up") or is_input_matched(event, "down")) or - (event.type == pygame.JOYBUTTONUP and is_input_matched(event, "up") or is_input_matched(event, "down")) - ): - config.repeat_action = None - config.repeat_key = None - config.repeat_start_time = 0 - config.needs_redraw = True - logger.debug("Menu pause: Touche relâchée, répétition arrêtée") - - if config.repeat_action in ["up", "down"] and current_time >= config.repeat_start_time: - if current_time - config.repeat_last_action < REPEAT_ACTION_DEBOUNCE: - continue - config.repeat_last_action = current_time - if config.repeat_action == "up": - config.selected_pause_option = max(0, config.selected_pause_option - 1) - config.needs_redraw = True - logger.debug(f"Menu pause: Répétition haut, selected_option={config.selected_pause_option}") - elif config.repeat_action == "down": - config.selected_pause_option = min(3, config.selected_pause_option + 1) - config.needs_redraw = True - logger.debug(f"Menu pause: Répétition bas, selected_option={config.selected_pause_option}") - config.repeat_start_time = current_time + REPEAT_INTERVAL + action = handle_controls(event, sources, joystick, screen) + config.needs_redraw = True + logger.debug(f"Événement transmis à handle_controls dans pause_menu: {event.type}") continue @@ -432,6 +344,11 @@ async def main(): config.needs_redraw = True logger.debug(f"Événement transmis à handle_controls dans confirm_clear_history: {event.type}") continue + if config.menu_state == "redownload_game_cache": + action = handle_controls(event, sources, joystick, screen) + config.needs_redraw = True + logger.debug(f"Événement transmis à handle_controls dans redownload_game_cache: {event.type}") + continue if config.menu_state in ["platform", "game", "error", "confirm_exit", "download_progress", "download_result", "extension_warning", "history"]: action = handle_controls(event, sources, joystick, screen) @@ -522,43 +439,50 @@ async def main(): draw_gradient(screen, (28, 37, 38), (47, 59, 61)) if config.menu_state == "controls_mapping": draw_controls_mapping(screen, ACTIONS[0], None, False, 0.0) - logger.debug("Rendu initial de draw_controls_mapping") + # logger.debug("Rendu initial de draw_controls_mapping") elif config.menu_state == "loading": draw_loading_screen(screen) - logger.debug("Rendu de draw_loading_screen") + # logger.debug("Rendu de draw_loading_screen") elif config.menu_state == "error": draw_error_screen(screen) - logger.debug("Rendu de draw_error_screen") + # logger.debug("Rendu de draw_error_screen") elif config.menu_state == "platform": draw_platform_grid(screen) - logger.debug("Rendu de draw_platform_grid") + # logger.debug("Rendu de draw_platform_grid") elif config.menu_state == "game": draw_game_list(screen) - logger.debug("Rendu de draw_game_list") + # logger.debug("Rendu de draw_game_list") elif config.menu_state == "download_progress": draw_progress_screen(screen) - logger.debug("Rendu de draw_progress_screen") + # logger.debug("Rendu de draw_progress_screen") elif config.menu_state == "download_result": draw_popup_message(screen, config.download_result_message, config.download_result_error) - logger.debug("Rendu de draw_popup_message") + # logger.debug("Rendu de draw_popup_message") elif config.menu_state == "confirm_exit": draw_confirm_dialog(screen) - logger.debug("Rendu de draw_confirm_dialog") + # logger.debug("Rendu de draw_confirm_dialog") elif config.menu_state == "extension_warning": draw_extension_warning(screen) - logger.debug("Rendu de draw_extension_warning") + # logger.debug("Rendu de draw_extension_warning") elif config.menu_state == "pause_menu": - draw_pause_menu(screen, config.selected_pause_option) + draw_pause_menu(screen, config.selected_option) logger.debug("Rendu de draw_pause_menu") elif config.menu_state == "controls_help": draw_controls_help(screen, config.previous_menu_state) - logger.debug("Rendu de draw_controls_help") + # logger.debug("Rendu de draw_controls_help") elif config.menu_state == "history": - draw_history(screen) - logger.debug("Rendu de draw_history") + draw_history_list(screen) + # logger.debug("Rendu de draw_history_list") elif config.menu_state == "confirm_clear_history": draw_clear_history_dialog(screen) - logger.debug("Rendu de confirm_clear_history") + # logger.debug("Rendu de confirm_clear_history") + elif config.menu_state == "redownload_game_cache": + draw_redownload_game_cache_dialog(screen) # Fonction existante + elif config.menu_state == "restart_popup": + draw_popup(screen) # Nouvelle fonction + elif config.menu_state == "confirm_clear_history": + draw_clear_history_dialog(screen) # Fonction existante + else: # Gestion des états non valides config.menu_state = "platform" @@ -624,14 +548,14 @@ async def main(): logger.debug(f"Erreur OTA : {message}") else: loading_step = "check_data" - config.current_loading_system = "Téléchargement des données ..." + config.current_loading_system = "Téléchargement des jeux et images ..." config.loading_progress = 10.0 config.needs_redraw = True logger.debug(f"Étape chargement : {loading_step}, progress={config.loading_progress}") elif loading_step == "check_data": games_data_dir = "/userdata/roms/ports/RGSX/games" is_data_empty = not os.path.exists(games_data_dir) or not any(os.scandir(games_data_dir)) - logger.debug(f"Dossier Data directory {games_data_dir} is {'empty' if is_data_empty else 'not empty'}") + #logger.debug(f"Dossier Data directory {games_data_dir} is {'empty' if is_data_empty else 'not empty'}") if is_data_empty: config.current_loading_system = "Téléchargement du Dossier Data initial..." diff --git a/config.py b/config.py index caaf1d7..ac9aba7 100644 --- a/config.py +++ b/config.py @@ -1,11 +1,11 @@ -import pygame +import pygame # type: ignore import os import logging logger = logging.getLogger(__name__) # Version actuelle de l'application -app_version = "1.5.0" +app_version = "1.7.0" # Variables d'état platforms = [] @@ -43,7 +43,7 @@ filter_active = False extension_confirm_selection = 0 pending_download = None controls_config = {} -selected_pause_option = 0 +selected_option = 0 previous_menu_state = None history = [] # Liste des entrées de l'historique current_history_item = 0 # Index de l'élément sélectionné dans l'historique @@ -55,10 +55,13 @@ debounce_delay = 200 # Délai de debounce en millisecondes platform_dicts = [] # Liste des dictionnaires de plateformes selected_key = (0, 0) # Position du curseur dans le clavier virtuel is_non_pc = True # Indicateur pour plateforme non-PC (par exemple, console) +redownload_confirm_selection = 0 # Sélection pour la confirmation de redownload +popup_message = "" # Message à afficher dans les popups +popup_timer = 0 # Temps restant pour le popup en millisecondes (0 = inactif) +last_frame_time = pygame.time.get_ticks() -# Résolution de l'écran -screen_width = 800 -screen_height = 600 +# Résolution de l'écran fallback +# Utilisée si la résolution définie dépasse les capacités de l'écran SCREEN_WIDTH = 800 """Largeur de l'écran en pixels.""" SCREEN_HEIGHT = 600 @@ -100,9 +103,24 @@ def init_font(): small_font = None def validate_resolution(): - """Valide la résolution de l'écran par rapport aux capacités du matériel.""" + """Valide la résolution de l'écran par rapport aux capacités de l'écran.""" display_info = pygame.display.Info() if SCREEN_WIDTH > display_info.current_w or SCREEN_HEIGHT > display_info.current_h: logger.warning(f"Résolution {SCREEN_WIDTH}x{SCREEN_HEIGHT} dépasse les limites de l'écran") return display_info.current_w, display_info.current_h - return SCREEN_WIDTH, SCREEN_HEIGHT \ No newline at end of file + return SCREEN_WIDTH, SCREEN_HEIGHT + + +def load_api_key_1fichier(): + """Charge la clé API 1fichier depuis /userdata/saves/ports/rgsx/1fichierAPI.txt, crée le fichier si absent.""" + api_path = "/userdata/saves/ports/rgsx/1fichierAPI.txt" + if not os.path.exists(api_path): + # Crée le fichier vide si absent + with open(api_path, "w") as f: + f.write("") + return "" + with open(api_path, "r") as f: + key = f.read().strip() + return key + +API_KEY_1FICHIER = load_api_key_1fichier() \ No newline at end of file diff --git a/controls.py b/controls.py index 82e0d02..b6fa323 100644 --- a/controls.py +++ b/controls.py @@ -1,11 +1,13 @@ -import pygame +import shutil +import pygame # type: ignore import config from config import CONTROLS_CONFIG_PATH import asyncio import math import json +import os from display import draw_validation_transition -from network import download_rom, check_extension_before_download +from network import download_rom, check_extension_before_download, download_from_1fichier, is_1fichier_url, is_extension_supported,load_extensions_json,sanitize_filename from controls_mapper import get_readable_input_name from utils import load_games from history import load_history, clear_history @@ -24,7 +26,7 @@ REPEAT_ACTION_DEBOUNCE = 50 # Délai anti-rebond pour répétitions up/down/lef VALID_STATES = [ "platform", "game", "download_progress", "download_result", "confirm_exit", "extension_warning", "pause_menu", "controls_help", "history", "remap_controls", - "error", "loading", "confirm_clear_history" # Ajout du nouvel état + "redownload_game_cache", "restart_popup", "error", "loading", "confirm_clear_history" ] def validate_menu_state(state): @@ -63,7 +65,8 @@ def load_controls_config(path=CONTROLS_CONFIG_PATH): "up": {"type": "key", "value": pygame.K_UP}, "down": {"type": "key", "value": pygame.K_DOWN}, "start": {"type": "key", "value": pygame.K_p}, - "progress": {"type": "key", "value": pygame.K_t}, + "progress": {"type": "key", "value": pygame.K_x}, + "history": {"type": "key", "value": pygame.K_h}, "page_up": {"type": "key", "value": pygame.K_PAGEUP}, "page_down": {"type": "key", "value": pygame.K_PAGEDOWN}, "filter": {"type": "key", "value": pygame.K_f}, @@ -86,22 +89,22 @@ def is_input_matched(event, action_name): event_value = event.get("value") if isinstance(event, dict) else getattr(event, "value", None) if input_type == "key" and event_type in (pygame.KEYDOWN, pygame.KEYUP): - logger.debug(f"Vérification key: event_key={event_key}, input_value={input_value}") + #logger.debug(f"Vérification key: event_key={event_key}, input_value={input_value}") return event_key == input_value elif input_type == "button" and event_type in (pygame.JOYBUTTONDOWN, pygame.JOYBUTTONUP): - logger.debug(f"Vérification button: event_button={event_button}, input_value={input_value}") + #logger.debug(f"Vérification button: event_button={event_button}, input_value={input_value}") return event_button == input_value elif input_type == "axis" and event_type == pygame.JOYAXISMOTION: axis, direction = input_value result = event_axis == axis and abs(event_value) > 0.5 and (1 if event_value > 0 else -1) == direction - logger.debug(f"Vérification axis: event_axis={event_axis}, event_value={event_value}, input_value={input_value}, result={result}") + #logger.debug(f"Vérification axis: event_axis={event_axis}, event_value={event_value}, input_value={input_value}, result={result}") return result elif input_type == "hat" and event_type == pygame.JOYHATMOTION: input_value_tuple = tuple(input_value) if isinstance(input_value, list) else input_value - logger.debug(f"Vérification hat: event_value={event_value}, input_value={input_value_tuple}") + #logger.debug(f"Vérification hat: event_value={event_value}, input_value={input_value_tuple}") return event_value == input_value_tuple elif input_type == "mouse" and event_type == pygame.MOUSEBUTTONDOWN: - logger.debug(f"Vérification mouse: event_button={event_button}, input_value={input_value}") + #logger.debug(f"Vérification mouse: event_button={event_button}, input_value={input_value}") return event_button == input_value return False @@ -114,14 +117,14 @@ def handle_controls(event, sources, joystick, screen): # Valider previous_menu_state avant tout traitement config.previous_menu_state = validate_menu_state(config.previous_menu_state) - logger.debug(f"Validation initiale: previous_menu_state={config.previous_menu_state}") + #logger.debug(f"Validation initiale: previous_menu_state={config.previous_menu_state}") # Debounce général if current_time - config.last_state_change_time < config.debounce_delay: return action # Log des événements reçus - logger.debug(f"Événement reçu: type={event.type}, value={getattr(event, 'value', None)}") + #logger.debug(f"Événement reçu: type={event.type}, value={getattr(event, 'value', None)}") # --- CLAVIER, MANETTE, SOURIS --- if event.type in (pygame.KEYDOWN, pygame.JOYBUTTONDOWN, pygame.JOYAXISMOTION, pygame.JOYHATMOTION, pygame.MOUSEBUTTONDOWN): @@ -143,12 +146,12 @@ def handle_controls(event, sources, joystick, screen): return "quit" # Vérification des actions mappées - for action_name in ["up", "down", "left", "right"]: - if is_input_matched(event, action_name): - logger.debug(f"Action mappée détectée: {action_name}, input={get_readable_input_name(event)}") + #for action_name in ["up", "down", "left", "right"]: + #if is_input_matched(event, action_name): + #logger.debug(f"Action mappée détectée: {action_name}, input={get_readable_input_name(event)}") # Menu pause - if is_input_matched(event, "start") and config.menu_state not in ("pause_menu", "controls_help", "history", "remap_controls"): + if is_input_matched(event, "start") and config.menu_state not in ("pause_menu", "controls_help", "remap_controls", "redownload_game_cache"): config.previous_menu_state = config.menu_state config.menu_state = "pause_menu" config.selected_option = 0 @@ -159,13 +162,9 @@ def handle_controls(event, sources, joystick, screen): # Erreur if config.menu_state == "error": if is_input_matched(event, "confirm"): - config.menu_state = "loading" - config.needs_redraw = True - logger.debug("Sortie erreur avec Confirm") - elif is_input_matched(event, "cancel"): - config.menu_state = "confirm_exit" - config.confirm_selection = 0 + config.menu_state = validate_menu_state(config.previous_menu_state) config.needs_redraw = True + logger.debug("Sortie du menu erreur avec Confirm") # Plateformes elif config.menu_state == "platform": @@ -235,7 +234,7 @@ def handle_controls(event, sources, joystick, screen): config.repeat_start_time = 0 config.repeat_last_action = current_time config.needs_redraw = True - logger.debug("Page suivante, répétition réinitialisée") + #logger.debug("Page suivante, répétition réinitialisée") elif is_input_matched(event, "page_up"): if config.current_page > 0: config.current_page -= 1 @@ -247,12 +246,16 @@ def handle_controls(event, sources, joystick, screen): config.repeat_start_time = 0 config.repeat_last_action = current_time config.needs_redraw = True - logger.debug("Page précédente, répétition réinitialisée") + #logger.debug("Page précédente, répétition réinitialisée") elif is_input_matched(event, "progress"): if config.download_tasks: config.menu_state = "download_progress" config.needs_redraw = True logger.debug("Retour à download_progress depuis platform") + elif is_input_matched(event, "history"): + config.menu_state = "history" + config.needs_redraw = True + logger.debug("Ouverture history depuis platform") elif is_input_matched(event, "confirm"): if config.platforms: config.current_platform = config.selected_platform @@ -264,7 +267,7 @@ def handle_controls(event, sources, joystick, screen): draw_validation_transition(screen, config.current_platform) config.menu_state = "game" config.needs_redraw = True - logger.debug(f"Plateforme sélectionnée: {config.platforms[config.current_platform]}, {len(config.games)} jeux chargés") + #logger.debug(f"Plateforme sélectionnée: {config.platforms[config.current_platform]}, {len(config.games)} jeux chargés") elif is_input_matched(event, "cancel"): config.menu_state = "confirm_exit" config.confirm_selection = 0 @@ -329,14 +332,14 @@ def handle_controls(event, sources, joystick, screen): config.current_game = 0 config.scroll_offset = 0 config.needs_redraw = True - logger.debug(f"Suppression caractère: query={config.search_query}, jeux filtrés={len(config.filtered_games)}") + #logger.debug(f"Suppression caractère: query={config.search_query}, jeux filtrés={len(config.filtered_games)}") elif is_input_matched(event, "space"): config.search_query += " " config.filtered_games = [game for game in config.games if config.search_query.lower() in game[0].lower()] config.current_game = 0 config.scroll_offset = 0 config.needs_redraw = True - logger.debug(f"Espace ajouté: query={config.search_query}, jeux filtrés={len(config.filtered_games)}") + #logger.debug(f"Espace ajouté: query={config.search_query}, jeux filtrés={len(config.filtered_games)}") elif is_input_matched(event, "cancel"): config.search_mode = False config.search_query = "" @@ -346,7 +349,45 @@ def handle_controls(event, sources, joystick, screen): config.scroll_offset = 0 config.needs_redraw = True logger.debug("Sortie du mode recherche") + elif config.search_mode and not config.is_non_pc: + # Gestion de la recherche sur PC + if event.type == pygame.KEYDOWN: + # Saisie de texte alphanumérique + if event.unicode.isalnum() or event.unicode == ' ': + config.search_query += event.unicode + config.filtered_games = [game for game in config.games if config.search_query.lower() in game[0].lower()] + config.current_game = 0 + config.scroll_offset = 0 + config.needs_redraw = True + logger.debug(f"Recherche mise à jour: query={config.search_query}, jeux filtrés={len(config.filtered_games)}") + # Gestion de la suppression + elif is_input_matched(event, "delete"): + if config.search_query: + config.search_query = config.search_query[:-1] + config.filtered_games = [game for game in config.games if config.search_query.lower() in game[0].lower()] + config.current_game = 0 + config.scroll_offset = 0 + config.needs_redraw = True + logger.debug(f"Suppression caractère: query={config.search_query}, jeux filtrés={len(config.filtered_games)}") + # Gestion de la validation + elif is_input_matched(event, "confirm"): + config.search_mode = False + config.filter_active = True # Conserver le filtre actif + config.current_game = 0 + config.scroll_offset = 0 + config.needs_redraw = True + logger.debug(f"Validation de la recherche: query={config.search_query}, jeux filtrés={len(config.filtered_games)}") + # Gestion de l'annulation + elif is_input_matched(event, "cancel"): + config.search_mode = False + config.search_query = "" + config.filtered_games = config.games + config.current_game = 0 + config.scroll_offset = 0 + config.needs_redraw = True + logger.debug("Sortie du mode recherche") else: + if is_input_matched(event, "up"): if config.current_game > 0: config.current_game -= 1 @@ -370,7 +411,7 @@ def handle_controls(event, sources, joystick, screen): config.repeat_start_time = 0 config.repeat_last_action = current_time config.needs_redraw = True - logger.debug("Page précédente dans la liste des jeux") + #logger.debug("Page précédente dans la liste des jeux") elif is_input_matched(event, "page_down"): config.current_game = min(len(games) - 1, config.current_game + config.visible_games) config.repeat_action = None @@ -378,7 +419,7 @@ def handle_controls(event, sources, joystick, screen): config.repeat_start_time = 0 config.repeat_last_action = current_time config.needs_redraw = True - logger.debug("Page suivante dans la liste des jeux") + #logger.debug("Page suivante dans la liste des jeux") elif is_input_matched(event, "filter"): config.search_mode = True config.search_query = "" @@ -390,26 +431,56 @@ def handle_controls(event, sources, joystick, screen): logger.debug("Entrée en mode recherche") elif is_input_matched(event, "progress"): if config.download_tasks: + config.previous_menu_state = config.menu_state config.menu_state = "download_progress" config.needs_redraw = True - logger.debug("Retour à download_progress depuis game") + logger.debug(f"Retour à download_progress depuis {config.previous_menu_state}") + elif is_input_matched(event, "history"): + config.menu_state = "history" + config.needs_redraw = True + logger.debug("Ouverture history depuis game") elif is_input_matched(event, "confirm"): if games: - config.pending_download = check_extension_before_download(games[config.current_game][0], config.platforms[config.current_platform], games[config.current_game][1]) + config.pending_download = check_extension_before_download( + games[config.current_game][0], + config.platforms[config.current_platform], + games[config.current_game][1] + ) if config.pending_download: url, platform, game_name, is_zip_non_supported = config.pending_download - if is_zip_non_supported: + is_supported = is_extension_supported( + sanitize_filename(game_name), + platform, + load_extensions_json() + ) + if not is_supported: + config.previous_menu_state = config.menu_state # Ajouter cette ligne config.menu_state = "extension_warning" config.extension_confirm_selection = 0 config.needs_redraw = True logger.debug(f"Extension non supportée, passage à extension_warning pour {game_name}") else: - task = asyncio.create_task(download_rom(url, platform, game_name, is_zip_non_supported)) - config.download_tasks[task] = (task, url, game_name, platform) # Stocker tuple de 4 éléments + if is_1fichier_url(url): + if not config.API_KEY_1FICHIER: + config.previous_menu_state = config.menu_state # Ajouter cette ligne + config.menu_state = "error" + config.error_message = ( + "Attention il faut renseigner sa clé API (premium only) dans le fichier /userdata/saves/ports/rgsx/1fichier.api à ouvrir dans un editeur de texte et coller la clé API" + ) + config.needs_redraw = True + logger.error("Clé API 1fichier absente, téléchargement impossible.") + config.pending_download = None + return action + loop = asyncio.get_running_loop() + task = loop.run_in_executor(None, download_from_1fichier, url, platform, game_name, is_zip_non_supported) + else: + task = asyncio.create_task(download_rom(url, platform, game_name, is_zip_non_supported)) + config.download_tasks[task] = (task, url, game_name, platform) + config.previous_menu_state = config.menu_state # Ajouter cette ligne config.menu_state = "download_progress" config.needs_redraw = True logger.debug(f"Début du téléchargement: {game_name} pour {platform} depuis {url}") - config.pending_download = None # Réinitialiser après démarrage + config.pending_download = None action = "download" else: config.menu_state = "error" @@ -423,7 +494,11 @@ def handle_controls(event, sources, joystick, screen): config.scroll_offset = 0 config.needs_redraw = True logger.debug("Retour à platform") - + elif is_input_matched(event, "redownload_game_cache"): + config.previous_menu_state = config.menu_state + config.menu_state = "redownload_game_cache" + config.needs_redraw = True + logger.debug("Passage à redownload_game_cache depuis game") elif config.menu_state == "history": history = config.history if is_input_matched(event, "up"): @@ -449,7 +524,7 @@ def handle_controls(event, sources, joystick, screen): config.repeat_start_time = 0 config.repeat_last_action = current_time config.needs_redraw = True - logger.debug("Page précédente dans l'historique") + #logger.debug("Page précédente dans l'historique") elif is_input_matched(event, "page_down"): config.current_history_item = min(len(history) - 1, config.current_history_item + config.visible_history_items) config.repeat_action = None @@ -457,7 +532,7 @@ def handle_controls(event, sources, joystick, screen): config.repeat_start_time = 0 config.repeat_last_action = current_time config.needs_redraw = True - logger.debug("Page suivante dans l'historique") + #logger.debug("Page suivante dans l'historique") elif is_input_matched(event, "progress"): config.previous_menu_state = validate_menu_state(config.previous_menu_state) config.menu_state = "confirm_clear_history" @@ -469,14 +544,13 @@ def handle_controls(event, sources, joystick, screen): entry = history[config.current_history_item] platform = entry["platform"] game_name = entry["game_name"] - # Rechercher l'URL dans config.games for game in config.games: if game[0] == game_name and config.platforms[config.current_platform] == platform: config.pending_download = check_extension_before_download(game_name, platform, game[1]) if config.pending_download: url, platform, game_name, is_zip_non_supported = config.pending_download if is_zip_non_supported: - config.previous_menu_state = validate_menu_state(config.previous_menu_state) + config.previous_menu_state = config.menu_state # Remplacer cette ligne config.menu_state = "extension_warning" config.extension_confirm_selection = 0 config.needs_redraw = True @@ -484,7 +558,7 @@ def handle_controls(event, sources, joystick, screen): else: task = asyncio.create_task(download_rom(url, platform, game_name, is_zip_non_supported)) config.download_tasks[task] = (task, url, game_name, platform) - config.previous_menu_state = validate_menu_state(config.previous_menu_state) + config.previous_menu_state = config.menu_state # Remplacer cette ligne config.menu_state = "download_progress" config.needs_redraw = True logger.debug(f"Retéléchargement: {game_name} pour {platform} depuis {url}") @@ -503,6 +577,7 @@ def handle_controls(event, sources, joystick, screen): config.history_scroll_offset = 0 config.needs_redraw = True logger.debug(f"Retour à {config.menu_state} depuis history") + # Ajouter un nouvel état "confirm_clear_history" après l'état "confirm_exit" elif config.menu_state == "confirm_clear_history": logger.debug(f"État confirm_clear_history, confirm_clear_selection={config.confirm_clear_selection}, événement={event.type}, valeur={getattr(event, 'value', None)}") @@ -521,20 +596,21 @@ def handle_controls(event, sources, joystick, screen): config.needs_redraw = True logger.debug("Annulation du vidage de l'historique, retour à history") elif is_input_matched(event, "left"): - logger.debug(f"Action left détectée dans confirm_clear_history") + #logger.debug(f"Action left détectée dans confirm_clear_history") config.confirm_clear_selection = 1 # Sélectionner "Non" config.needs_redraw = True - logger.debug(f"Changement sélection confirm_clear_history: {config.confirm_clear_selection}") + #logger.debug(f"Changement sélection confirm_clear_history: {config.confirm_clear_selection}") elif is_input_matched(event, "right"): - logger.debug(f"Action right détectée dans confirm_clear_history") + #logger.debug(f"Action right détectée dans confirm_clear_history") config.confirm_clear_selection = 0 # Sélectionner "Oui" config.needs_redraw = True - logger.debug(f"Changement sélection confirm_clear_history: {config.confirm_clear_selection}") + #logger.debug(f"Changement sélection confirm_clear_history: {config.confirm_clear_selection}") elif is_input_matched(event, "cancel"): - logger.debug(f"Action cancel détectée dans confirm_clear_history") + #logger.debug(f"Action cancel détectée dans confirm_clear_history") config.menu_state = "history" config.needs_redraw = True logger.debug("Annulation du vidage de l'historique, retour à history") + # Progression téléchargement elif config.menu_state == "download_progress": if is_input_matched(event, "cancel"): @@ -572,7 +648,7 @@ def handle_controls(event, sources, joystick, screen): elif is_input_matched(event, "left") or is_input_matched(event, "right"): config.confirm_selection = 1 - config.confirm_selection config.needs_redraw = True - logger.debug(f"Changement sélection confirm_exit: {config.confirm_selection}") + #logger.debug(f"Changement sélection confirm_exit: {config.confirm_selection}") # Avertissement extension elif config.menu_state == "extension_warning": @@ -602,15 +678,15 @@ def handle_controls(event, sources, joystick, screen): elif is_input_matched(event, "left") or is_input_matched(event, "right"): config.extension_confirm_selection = 1 - config.extension_confirm_selection config.needs_redraw = True - logger.debug(f"Changement sélection extension_warning: {config.extension_confirm_selection}") + #logger.debug(f"Changement sélection extension_warning: {config.extension_confirm_selection}") elif is_input_matched(event, "cancel"): config.pending_download = None config.menu_state = validate_menu_state(config.previous_menu_state) config.needs_redraw = True logger.debug(f"Retour à {config.menu_state} depuis extension_warning") - # Menu pause elif config.menu_state == "pause_menu": + logger.debug(f"État pause_menu, selected_option={config.selected_option}, événement={event.type}, valeur={getattr(event, 'value', None)}") if is_input_matched(event, "up"): config.selected_option = max(0, config.selected_option - 1) config.repeat_action = "up" @@ -618,14 +694,17 @@ def handle_controls(event, sources, joystick, screen): config.repeat_last_action = current_time config.repeat_key = event.key if event.type == pygame.KEYDOWN else event.button if event.type == pygame.JOYBUTTONDOWN else (event.axis, 1 if event.value > 0 else -1) if event.type == pygame.JOYAXISMOTION else event.value config.needs_redraw = True + logger.debug(f"Navigation vers le haut: selected_option={config.selected_option}") elif is_input_matched(event, "down"): - config.selected_option = min(3, config.selected_option + 1) + config.selected_option = min(4, config.selected_option + 1) config.repeat_action = "down" config.repeat_start_time = current_time + REPEAT_DELAY config.repeat_last_action = current_time config.repeat_key = event.key if event.type == pygame.KEYDOWN else event.button if event.type == pygame.JOYBUTTONDOWN else (event.axis, 1 if event.value > 0 else -1) if event.type == pygame.JOYAXISMOTION else event.value config.needs_redraw = True + logger.debug(f"Navigation vers le bas: selected_option={config.selected_option}") elif is_input_matched(event, "confirm"): + logger.debug(f"Confirmation dans pause_menu avec selected_option={config.selected_option}") if config.selected_option == 0: # Controls config.previous_menu_state = validate_menu_state(config.previous_menu_state) config.menu_state = "controls_help" @@ -644,7 +723,13 @@ def handle_controls(event, sources, joystick, screen): config.menu_state = "history" config.needs_redraw = True logger.debug(f"Passage à history depuis pause_menu") - elif config.selected_option == 3: # Quit + elif config.selected_option == 3: # Redownload game cache + config.previous_menu_state = validate_menu_state(config.previous_menu_state) + config.menu_state = "redownload_game_cache" + config.redownload_confirm_selection = 0 + config.needs_redraw = True + logger.debug(f"Passage à redownload_game_cache depuis pause_menu") + elif config.selected_option == 4: # Quit config.previous_menu_state = validate_menu_state(config.previous_menu_state) config.menu_state = "confirm_exit" config.confirm_selection = 0 @@ -668,6 +753,66 @@ def handle_controls(event, sources, joystick, screen): config.menu_state = "pause_menu" config.needs_redraw = True logger.debug("Retour à pause_menu depuis remap_controls") + + elif config.menu_state == "redownload_game_cache": + if is_input_matched(event, "left") or is_input_matched(event, "right"): + config.redownload_confirm_selection = 1 - config.redownload_confirm_selection + config.needs_redraw = True + logger.debug(f"Changement sélection redownload_game_cache: {config.redownload_confirm_selection}") + elif is_input_matched(event, "confirm"): + logger.debug(f"Action confirm dans redownload_game_cache, sélection={config.redownload_confirm_selection}") + if config.redownload_confirm_selection == 1: # Oui + logger.debug("Début du redownload des jeux") + config.download_tasks.clear() + config.download_progress.clear() + config.pending_download = None + if os.path.exists("/userdata/roms/ports/RGSX/sources.json"): + try: + os.remove("/userdata/roms/ports/RGSX/sources.json") + logger.debug("Fichier sources.json supprimé avec succès") + if os.path.exists("/userdata/roms/ports/RGSX/games"): + shutil.rmtree("/userdata/roms/ports/RGSX/games") + logger.debug("Dossier games supprimé avec succès") + if os.path.exists("/userdata/roms/ports/RGSX/images"): + shutil.rmtree("/userdata/roms/ports/RGSX/images") + logger.debug("Dossier images supprimé avec succès") + config.menu_state = "restart_popup" + config.popup_message = "Redownload des jeux effectué.\nVeuillez redémarrer l'application pour voir les changements." + config.popup_timer = 5000 # 5 secondes + config.needs_redraw = True + logger.debug("Passage à restart_popup") + except Exception as e: + logger.error(f"Erreur lors de la suppression du fichier sources.json ou dossiers: {e}") + config.menu_state = "error" + config.error_message = "Erreur lors de la suppression du fichier sources.json ou dossiers" + config.needs_redraw = True + return action + else: + logger.debug("Fichier sources.json non trouvé, passage à restart_popup") + config.menu_state = "restart_popup" + config.popup_message = "Aucun cache trouvé.\nVeuillez redémarrer l'application pour charger les jeux." + config.popup_timer = 5000 # 5 secondes + config.needs_redraw = True + logger.debug("Passage à restart_popup") + else: # Non + config.menu_state = validate_menu_state(config.previous_menu_state) + config.needs_redraw = True + logger.debug(f"Annulation du redownload, retour à {config.menu_state}") + elif is_input_matched(event, "cancel"): + config.menu_state = validate_menu_state(config.previous_menu_state) + config.needs_redraw = True + logger.debug(f"Retour à {config.menu_state} depuis redownload_game_cache") + + + # Popup de redémarrage + elif config.menu_state == "restart_popup": + if is_input_matched(event, "confirm") or is_input_matched(event, "cancel"): + config.menu_state = validate_menu_state(config.previous_menu_state) + config.popup_message = "" + config.popup_timer = 0 + config.needs_redraw = True + logger.debug(f"Retour manuel à {config.menu_state} depuis restart_popup") + # Gestion de la répétition automatique (relâchement) if event.type in (pygame.KEYUP, pygame.JOYBUTTONUP, pygame.JOYAXISMOTION, pygame.JOYHATMOTION): @@ -678,7 +823,7 @@ def handle_controls(event, sources, joystick, screen): config.repeat_action = None config.repeat_key = None config.repeat_start_time = 0 - logger.debug("Répétition arrêtée") + #logger.debug("Répétition arrêtée") return action diff --git a/controls_mapper.py b/controls_mapper.py index 3b404af..fecce1d 100644 --- a/controls_mapper.py +++ b/controls_mapper.py @@ -1,4 +1,4 @@ -import pygame +import pygame # type: ignore import json import os import logging @@ -19,9 +19,10 @@ ACTIONS = [ {"name": "down", "display": "Bas", "description": "Naviguer vers le bas"}, {"name": "left", "display": "Gauche", "description": "Naviguer à gauche"}, {"name": "right", "display": "Droite", "description": "Naviguer à droite"}, - {"name": "page_up", "display": "Page Précédente", "description": "Page précédente (ex: PageUp, LB)"}, - {"name": "page_down", "display": "Page Suivante", "description": "Page suivante (ex: PageDown, RB)"}, + {"name": "page_up", "display": "Page Précédente", "description": "Page précédente/Défilement Rapide Haut (ex: PageUp, LB)"}, + {"name": "page_down", "display": "Page Suivante", "description": "Page suivante/Défilement Rapide Bas (ex: PageDown, RB)"}, {"name": "progress", "display": "Progression", "description": "Voir progression (ex: X)"}, + {"name": "history", "display": "Historique", "description": "Ouvrir l'historique (ex: H, Y)"}, {"name": "filter", "display": "Filtrer", "description": "Ouvrir filtre (ex: F, Select)"}, {"name": "delete", "display": "Supprimer", "description": "Supprimer caractère (ex: LT, Suppr)"}, {"name": "space", "display": "Espace", "description": "Ajouter espace (ex: RT, Espace)"}, @@ -200,7 +201,7 @@ MOUSE_BUTTON_NAMES = { HOLD_DURATION = 1000 def load_controls_config(): - """Charge la configuration des contrôles depuis controls.json.""" + #Charge la configuration des contrôles depuis controls.json try: if os.path.exists(CONTROLS_CONFIG_PATH): with open(CONTROLS_CONFIG_PATH, "r") as f: @@ -215,7 +216,7 @@ def load_controls_config(): return {} def save_controls_config(controls_config): - """Enregistre la configuration des contrôles dans controls.json.""" + #Enregistre la configuration des contrôles dans controls.json try: os.makedirs(os.path.dirname(CONTROLS_CONFIG_PATH), exist_ok=True) with open(CONTROLS_CONFIG_PATH, "w") as f: @@ -225,7 +226,7 @@ def save_controls_config(controls_config): logger.error(f"Erreur lors de l'enregistrement de controls.json : {e}") def get_readable_input_name(event): - """Retourne un nom lisible pour une entrée (touche, bouton, axe, hat, ou souris).""" + #Retourne un nom lisible pour une entrée (touche, bouton, axe, hat, ou souris) if event.type == pygame.KEYDOWN: key_value = SDL_TO_PYGAME_KEY.get(event.key, event.key) return KEY_NAMES.get(key_value, pygame.key.name(key_value) or f"Touche {key_value}") @@ -240,7 +241,6 @@ def get_readable_input_name(event): return MOUSE_BUTTON_NAMES.get(event.button, f"Souris Bouton {event.button}") return "Inconnu" -ACTIONS = ["start", "confirm", "cancel"] def map_controls(screen): mapping = True @@ -249,7 +249,7 @@ def map_controls(screen): while mapping: clock.tick(100) # 100 FPS for event in pygame.event.get(): - """Interface de mappage des contrôles avec validation par maintien de 3 secondes.""" + #Interface de mappage des contrôles avec validation par maintien de 3 secondes controls_config = load_controls_config() current_action_index = 0 current_input = None @@ -411,21 +411,21 @@ def map_controls(screen): pass def save_controls_config(config): - """Enregistre la configuration des contrôles dans un fichier JSON.""" + #Enregistre la configuration des contrôles dans un fichier JSON try: with open(CONTROLS_CONFIG_PATH, "w") as f: json.dump(config, f, indent=4) - logging.debug("Configuration des contrôles enregistrée") + logger.debug("Configuration des contrôles enregistrée") except Exception as e: - logging.error(f"Erreur lors de l'enregistrement de controls.json : {e}") + logger.error(f"Erreur lors de l'enregistrement de controls.json : {e}") return False return True def draw_controls_mapping(screen, action, last_input, waiting_for_input, hold_progress): - """Affiche l'interface de mappage des contrôles avec une barre de progression pour le maintien.""" + #Affiche l'interface de mappage des contrôles avec une barre de progression pour le maintien draw_gradient(screen, (28, 37, 38), (47, 59, 61)) - max_width = config.screen_width // 1.2 + max_width = config.screen_width // 1.2 padding_horizontal = 40 padding_vertical = 30 padding_between = 10 @@ -434,18 +434,18 @@ def draw_controls_mapping(screen, action, last_input, waiting_for_input, hold_pr shadow_offset = 8 # Instructions - instruction_text = f"Maintenez une touche/bouton pendant 3s pour '{action['display']}'" + instruction_text = f"Maintenez pendant 3s pour : '{action['display']}'" description_text = action['description'] - skip_text = "Appuyez sur Échap pour passer" - instruction_surface = config.font.render(instruction_text, True, (255, 255, 255)) - description_surface = config.font.render(description_text, True, (200, 200, 200)) + skip_text = "Appuyez sur Échap pour passer(Pc only)" + instruction_surface = config.small_font.render(instruction_text, True, (255, 255, 255)) + description_surface = config.small_font.render(description_text, True, (200, 200, 200)) skip_surface = config.font.render(skip_text, True, (255, 255, 255)) instruction_width, instruction_height = instruction_surface.get_size() description_width, description_height = description_surface.get_size() skip_width, skip_height = skip_surface.get_size() # Input détecté - input_text = last_input or (f"En attente d'une entrée..." if waiting_for_input else "Maintenez une touche/bouton") + input_text = last_input or (f"Attente..." if waiting_for_input else "Maintenez 3s") input_surface = config.font.render(input_text, True, (0, 255, 0) if last_input else (255, 255, 255)) input_width, input_height = input_surface.get_size() @@ -483,7 +483,7 @@ def draw_controls_mapping(screen, action, last_input, waiting_for_input, hold_pr input_rect = input_surface.get_rect(center=(config.screen_width // 2, start_y + input_height // 2)) screen.blit(input_surface, input_rect) start_y += input_height + padding_between - skip_rect = skip_surface.get_rect(center=(config.screen_width // 2, start_y + skip_height // 2)) + skip_rect = skip_surface.get_rect(center=(config.screen_width // 2, start_y + skip_height // 2)) screen.blit(skip_surface, skip_rect) # Barre de progression pour le maintien @@ -491,7 +491,7 @@ def draw_controls_mapping(screen, action, last_input, waiting_for_input, hold_pr bar_height = 20 bar_x = (config.screen_width - bar_width) // 2 bar_y = start_y + skip_height + 20 - pygame.draw.rect(screen, (100, 100, 100), (bar_x, bar_y, bar_width, bar_height)) + pygame.draw.rect(screen, (100, 100, 100), (bar_x, bar_y, bar_width, bar_height)) progress_width = bar_width * hold_progress - pygame.draw.rect(screen, (0, 255, 0), (bar_x, bar_y, progress_width, bar_height)) + pygame.draw.rect(screen, (0, 255, 0), (bar_x, bar_y, progress_width, bar_height)) pygame.draw.rect(screen, (255, 255, 255), (bar_x, bar_y, bar_width, bar_height), 2) \ No newline at end of file diff --git a/display.py b/display.py index 5c76702..ed2b771 100644 --- a/display.py +++ b/display.py @@ -1,15 +1,15 @@ -import pygame +import pygame # type: ignore import config import math -from utils import truncate_text_end, wrap_text, load_system_image, load_games +from utils import truncate_text_middle, wrap_text, load_system_image, load_games import logging from history import load_history # Ajout de l'import logger = logging.getLogger(__name__) -# Cache global pour l'overlay semi-transparent OVERLAY = None # Initialisé dans init_display() +#Général, résolution, overlay def init_display(): """Initialise l'écran et les ressources globales.""" global OVERLAY @@ -26,6 +26,7 @@ def init_display(): logger.debug(f"Écran initialisé avec résolution : {screen_width}x{screen_height}") return screen +#Fond d'ecran dégradé def draw_gradient(screen, top_color, bottom_color): """Dessine un fond dégradé vertical.""" height = screen.get_height() @@ -36,6 +37,30 @@ def draw_gradient(screen, top_color, bottom_color): color = top_color.lerp(bottom_color, ratio) pygame.draw.line(screen, color, (0, y), (screen.get_width(), y)) +#Transistion d'image lors de la selection d'un systeme +def draw_validation_transition(screen, platform_index): + """Affiche une animation de transition pour la sélection d’une plateforme.""" + platform_dict = config.platform_dicts[platform_index] + image = load_system_image(platform_dict) + if not image: + return + orig_width, orig_height = image.get_width(), image.get_height() + base_size = int(config.screen_width * 0.0781) # ~150px pour 1920p + start_time = pygame.time.get_ticks() + duration = 500 + while pygame.time.get_ticks() - start_time < duration: + draw_gradient(screen, (28, 37, 38), (47, 59, 61)) + elapsed = pygame.time.get_ticks() - start_time + scale = 2.0 + (2.0 * elapsed / duration) if elapsed < duration / 2 else 3.0 - (2.0 * elapsed / duration) + new_width = int(base_size * scale) + new_height = int(base_size * scale) + scaled_image = pygame.transform.smoothscale(image, (new_width, new_height)) + image_rect = scaled_image.get_rect(center=(config.screen_width // 2, config.screen_height // 2)) + screen.blit(scaled_image, image_rect) + pygame.display.flip() + pygame.time.wait(10) + +#Ecran de chargement def draw_loading_screen(screen): """Affiche l’écran de chargement avec le disclaimer en haut, le texte de chargement et la barre de progression.""" disclaimer_lines = [ @@ -52,7 +77,7 @@ def draw_loading_screen(screen): border_width = 3 shadow_offset = 6 - line_height = config.font.get_height() + padding_between + line_height = config.small_font.get_height() + padding_between total_height = line_height * len(disclaimer_lines) - padding_between rect_width = config.screen_width - 2 * margin_horizontal rect_height = total_height + 2 * padding_vertical @@ -73,9 +98,9 @@ def draw_loading_screen(screen): max_text_width = rect_width - 2 * padding_vertical for i, line in enumerate(disclaimer_lines): - wrapped_lines = wrap_text(line, config.font, max_text_width) + wrapped_lines = wrap_text(line, config.small_font, max_text_width) for j, wrapped_line in enumerate(wrapped_lines): - text_surface = config.font.render(wrapped_line, True, (255, 255, 255)) + text_surface = config.small_font.render(wrapped_line, True, (255, 255, 255)) text_rect = text_surface.get_rect(center=( config.screen_width // 2, rect_y + padding_vertical + (i * len(wrapped_lines) + j + 0.5) * line_height - padding_between // 2 @@ -83,11 +108,11 @@ def draw_loading_screen(screen): screen.blit(text_surface, text_rect) loading_y = rect_y + rect_height + int(config.screen_height * 0.0926) # ~100px pour 1080p - text = config.font.render(truncate_text_end(f"{config.current_loading_system}", config.font, config.screen_width - 2 * margin_horizontal), True, (255, 255, 255)) + text = config.small_font.render(truncate_text_middle(f"{config.current_loading_system}", config.small_font, config.screen_width - 2 * margin_horizontal), True, (255, 255, 255)) text_rect = text.get_rect(center=(config.screen_width // 2, loading_y)) screen.blit(text, text_rect) - progress_text = config.font.render(f"Progression : {int(config.loading_progress)}%", True, (255, 255, 255)) + progress_text = config.small_font.render(f"Progression : {int(config.loading_progress)}%", True, (255, 255, 255)) progress_rect = progress_text.get_rect(center=(config.screen_width // 2, loading_y + int(config.screen_height * 0.0463))) # ~50px pour 1080p screen.blit(progress_text, progress_rect) @@ -97,6 +122,7 @@ def draw_loading_screen(screen): pygame.draw.rect(screen, (100, 100, 100), (config.screen_width // 2 - bar_width // 2, loading_y + int(config.screen_height * 0.0926), bar_width, bar_height)) pygame.draw.rect(screen, (0, 255, 0), (config.screen_width // 2 - bar_width // 2, loading_y + int(config.screen_height * 0.0926), progress_width, bar_height)) +#Ecran d'erreur def draw_error_screen(screen): """Affiche l’écran d’erreur.""" error_font = pygame.font.SysFont("arial", 28) @@ -106,10 +132,20 @@ def draw_error_screen(screen): text = error_font.render(line, True, (255, 0, 0)) text_rect = text.get_rect(center=(config.screen_width // 2, config.screen_height // 2 - (len(wrapped_message) // 2 - i) * line_height)) screen.blit(text, text_rect) - retry_text = config.font.render(f"{get_control_display('confirm', 'Entrée/A')} : retenter, {get_control_display('cancel', 'Échap/B')} : quitter", True, (255, 255, 255)) - retry_rect = retry_text.get_rect(center=(config.screen_width // 2, config.screen_height // 2 + int(config.screen_height * 0.0926))) # ~100px pour 1080p - screen.blit(retry_text, retry_rect) + # Afficher uniquement "Valider" + confirm_text = config.small_font.render("Valider", True, (0, 150, 255)) + confirm_rect = confirm_text.get_rect(center=(config.screen_width // 2, config.screen_height // 2 + int(config.screen_height * 0.0926))) + screen.blit(confirm_text, confirm_rect) +#Recuperer les noms d'affichage des controles +def get_control_display(action, default): + """Récupère le nom d'affichage d'une action depuis controls_config.""" + if not config.controls_config: + logger.warning(f"controls_config vide pour l'action {action}, utilisation de la valeur par défaut") + return default + return config.controls_config.get(action, {}).get('display', default) + +#Grille des systemes 3x3 def draw_platform_grid(screen): """Affiche la grille des plateformes avec un titre en haut.""" # Configuration du titre @@ -149,7 +185,7 @@ def draw_platform_grid(screen): y_positions = [margin_top + row_height * i + row_height // 2 for i in range(num_rows)] start_idx = config.current_page * systems_per_page - logger.debug(f"Page {config.current_page}, start_idx: {start_idx}, total_platforms: {len(config.platforms)}") + #logger.debug(f"Page {config.current_page}, start_idx: {start_idx}, total_platforms: {len(config.platforms)}") for idx in range(start_idx, start_idx + systems_per_page): if idx >= len(config.platforms): @@ -196,9 +232,10 @@ def draw_platform_grid(screen): screen.blit(image, image_rect) +#Liste des jeux def draw_game_list(screen): """Affiche la liste des jeux avec défilement et rectangle de fond.""" - logger.debug("Début de draw_game_list") + #logger.debug("Début de draw_game_list") platform = config.platforms[config.current_platform] platform_name = config.platform_names.get(platform, platform) @@ -228,25 +265,26 @@ def draw_game_list(screen): screen.blit(text_surface, text_rect) return - line_height = config.font.get_height() + 10 + line_height = config.small_font.get_height() + 10 + #header_height = line_height margin_top_bottom = 20 - extra_margin_top = 5 - extra_margin_bottom = 40 - title_height = max(config.title_font.get_height(), config.search_font.get_height(), config.small_font.get_height()) + 20 + extra_margin_top = 20 + extra_margin_bottom = 60 # Aligné sur draw_history_list + title_height = config.title_font.get_height() + 20 + available_height = config.screen_height - title_height - extra_margin_top - extra_margin_bottom - 2 * margin_top_bottom - games_per_page = available_height // line_height - config.visible_games = games_per_page # Mettre à jour config.visible_games - max_text_width = max([config.font.size(truncate_text_end(game[0] if isinstance(game, (list, tuple)) else game, config.font, config.screen_width - 80))[0] for game in games], default=300) - rect_width = max_text_width + 40 - rect_height = games_per_page * line_height + 2 * margin_top_bottom + items_per_page = available_height // line_height + + rect_height = items_per_page * line_height + 2 * margin_top_bottom + rect_width = int(0.95 * config.screen_width) rect_x = (config.screen_width - rect_width) // 2 rect_y = title_height + extra_margin_top + (config.screen_height - title_height - extra_margin_top - extra_margin_bottom - rect_height) // 2 - config.scroll_offset = max(0, min(config.scroll_offset, max(0, len(games) - games_per_page))) + config.scroll_offset = max(0, min(config.scroll_offset, max(0, len(games) - items_per_page))) if config.current_game < config.scroll_offset: config.scroll_offset = config.current_game - elif config.current_game >= config.scroll_offset + games_per_page: - config.scroll_offset = config.current_game - games_per_page + 1 + elif config.current_game >= config.scroll_offset + items_per_page: + config.scroll_offset = config.current_game - items_per_page + 1 screen.blit(OVERLAY, (0, 0)) @@ -281,33 +319,68 @@ def draw_game_list(screen): pygame.draw.rect(screen, (50, 50, 50, 200), (rect_x, rect_y, rect_width, rect_height), border_radius=10) pygame.draw.rect(screen, (255, 255, 255), (rect_x, rect_y, rect_width, rect_height), 2, border_radius=10) - for i in range(config.scroll_offset, min(config.scroll_offset + games_per_page, len(games))): + for i in range(config.scroll_offset, min(config.scroll_offset + items_per_page, len(games))): game_name = games[i][0] if isinstance(games[i], (list, tuple)) else games[i] color = (0, 150, 255) if i == config.current_game else (255, 255, 255) - game_text = truncate_text_end(game_name, config.font, config.screen_width - 80) - text_surface = config.font.render(game_text, True, color) + game_text = truncate_text_middle(game_name, config.small_font, rect_width - 40) + text_surface = config.small_font.render(game_text, True, color) text_rect = text_surface.get_rect(center=(config.screen_width // 2, rect_y + margin_top_bottom + (i - config.scroll_offset) * line_height + line_height // 2)) screen.blit(text_surface, text_rect) - logger.debug(f"Jeu affiché : texte={game_text}, position={text_rect}, selected={i == config.current_game}") + #logger.debug(f"Jeu affiché : texte={game_text}, position={text_rect}, selected={i == config.current_game}") - draw_scrollbar(screen) - if config.search_mode and config.is_non_pc: - draw_virtual_keyboard(screen) + # Afficher la barre de scroll si besoin + if len(games) > items_per_page: + try: + draw_game_scrollbar( + screen, + config.scroll_offset, + len(games), + items_per_page, + rect_x + rect_width - 10, + rect_y, + rect_height + ) + except NameError as e: + logger.error(f"Erreur : draw_game_scrollbar non défini: {str(e)}") + +#Barre de défilement des jeux +def draw_game_scrollbar(screen, scroll_offset, total_items, visible_items, x, y, height): + """Affiche la barre de défilement pour la liste des jeux.""" + if total_items <= visible_items: + return + game_area_height = height + scrollbar_height = game_area_height * (visible_items / total_items) + scrollbar_y = y + (game_area_height - scrollbar_height) * (scroll_offset / max(1, total_items - visible_items)) + pygame.draw.rect(screen, (255, 255, 255), (x, scrollbar_y, 15, scrollbar_height)) + +#Liste historique téléchargement def draw_history_list(screen): """Affiche l'historique des téléchargements sous forme de tableau avec système, nom du jeu et état.""" - logger.debug("Début de draw_history_list") - history = config.history if hasattr(config, 'history') else load_history() history_count = len(history) + # Définir les largeurs des colonnes (valeurs fixes pour simplifier, ajustez si nécessaire) + col_platform_width = int((0.95 * config.screen_width - 60) * 0.33) + col_game_width = int((0.95 * config.screen_width - 60) * 0.50) + col_status_width = int((0.95 * config.screen_width - 60) * 0.17) + rect_width = int(0.95 * config.screen_width) # 95% de la largeur de l'écran + + # Hauteur des lignes et en-tête + line_height = config.small_font.get_height() + 10 + header_height = line_height + margin_top_bottom = 20 + extra_margin_top = 20 + extra_margin_bottom = 60 + title_height = config.title_font.get_height() + 20 + + # Cas où l'historique est vide if not history: logger.debug("Aucun historique disponible") message = "Aucun téléchargement dans l'historique" lines = wrap_text(message, config.font, config.screen_width - 80) line_height = config.font.get_height() + 5 text_height = len(lines) * line_height - margin_top_bottom = 20 rect_height = text_height + 2 * margin_top_bottom max_text_width = max([config.font.size(line)[0] for line in lines], default=300) rect_width = max_text_width + 40 @@ -324,33 +397,26 @@ def draw_history_list(screen): screen.blit(text_surface, text_rect) return - line_height = config.small_font.get_height() + 10 - margin_top_bottom = 20 - extra_margin_top = 5 - extra_margin_bottom = 40 - title_height = config.title_font.get_height() + 20 + # Calculer la hauteur disponible et les éléments par page available_height = config.screen_height - title_height - extra_margin_top - extra_margin_bottom - 2 * margin_top_bottom items_per_page = available_height // line_height - config.visible_history_items = items_per_page # Mettre à jour config.visible_history_items - # Calculer la largeur des colonnes - col_platform_width = config.screen_width // 4 # ~25% pour le système - col_game_width = config.screen_width // 2 # ~50% pour le nom du jeu - col_status_width = config.screen_width // 4 # ~25% pour l'état - max_text_width = col_platform_width + col_game_width + col_status_width - rect_width = max_text_width + 40 - rect_height = items_per_page * line_height + 2 * margin_top_bottom + # Calculer les dimensions du rectangle + rect_height = header_height + items_per_page * line_height + 2 * margin_top_bottom rect_x = (config.screen_width - rect_width) // 2 rect_y = title_height + extra_margin_top + (config.screen_height - title_height - extra_margin_top - extra_margin_bottom - rect_height) // 2 + # Gestion du défilement config.history_scroll_offset = max(0, min(config.history_scroll_offset, max(0, len(history) - items_per_page))) if config.current_history_item < config.history_scroll_offset: config.history_scroll_offset = config.current_history_item elif config.current_history_item >= config.history_scroll_offset + items_per_page: config.history_scroll_offset = config.current_history_item - items_per_page + 1 + # Fond et cadre screen.blit(OVERLAY, (0, 0)) + # Titre title_text = f"Historique des téléchargements ({history_count})" title_surface = config.title_font.render(title_text, True, (255, 255, 255)) title_rect = title_surface.get_rect(center=(config.screen_width // 2, title_surface.get_height() // 2 + 10)) @@ -360,12 +426,13 @@ def draw_history_list(screen): pygame.draw.rect(screen, (255, 255, 255), title_rect_inflated, 2, border_radius=10) screen.blit(title_surface, title_rect) + # Cadre du tableau pygame.draw.rect(screen, (50, 50, 50, 200), (rect_x, rect_y, rect_width, rect_height), border_radius=10) pygame.draw.rect(screen, (255, 255, 255), (rect_x, rect_y, rect_width, rect_height), 2, border_radius=10) # En-têtes du tableau headers = ["Système", "Nom du jeu", "État"] - header_y = rect_y + margin_top_bottom - line_height // 2 + header_y = rect_y + margin_top_bottom + header_height // 2 header_x_positions = [ rect_x + 20 + col_platform_width // 2, rect_x + 20 + col_platform_width + col_game_width // 2, @@ -376,18 +443,18 @@ def draw_history_list(screen): text_rect = text_surface.get_rect(center=(x_pos, header_y)) screen.blit(text_surface, text_rect) - # Lignes du tableau - for i in range(config.history_scroll_offset, min(config.history_scroll_offset + items_per_page, len(history))): + # Afficher les entrées de l'historique + for idx, i in enumerate(range(config.history_scroll_offset, min(config.history_scroll_offset + items_per_page, len(history)))): entry = history[i] - platform = entry["platform"] - game_name = entry["game_name"] - status = entry["status"] + platform = entry.get("platform", "Inconnu") + game_name = entry.get("game_name", "Inconnu") + status = entry.get("status", "Inconnu") color = (0, 150, 255) if i == config.current_history_item else (255, 255, 255) - platform_text = truncate_text_end(platform, config.small_font, col_platform_width - 10) - game_text = truncate_text_end(game_name, config.small_font, col_game_width - 10) - status_text = truncate_text_end(status, config.small_font, col_status_width - 10) + platform_text = truncate_text_middle(platform, config.small_font, col_platform_width - 10) + game_text = truncate_text_middle(game_name, config.small_font, col_game_width - 10) + status_text = truncate_text_middle(status, config.small_font, col_status_width - 10) - y_pos = rect_y + margin_top_bottom + (i - config.history_scroll_offset + 1) * line_height + line_height // 2 + y_pos = rect_y + margin_top_bottom + header_height + idx * line_height + line_height // 2 platform_surface = config.small_font.render(platform_text, True, color) game_surface = config.small_font.render(game_text, True, color) status_surface = config.small_font.render(status_text, True, color) @@ -399,20 +466,68 @@ def draw_history_list(screen): screen.blit(platform_surface, platform_rect) screen.blit(game_surface, game_rect) screen.blit(status_surface, status_rect) - logger.debug(f"Entrée historique affichée : index={i}, platform={platform_text}, game={game_text}, status={status_text}, selected={i == config.current_history_item}") + #logger.debug(f"Entrée historique affichée : index={i}, platform={platform_text}, game={game_text}, status={status_text}, selected={i == config.current_history_item}") - draw_history_scrollbar(screen) + # Scrollbar + if len(history) > items_per_page: + try: + draw_history_scrollbar( + screen, + config.history_scroll_offset, + len(history), + items_per_page, + rect_x + rect_width - 10, + rect_y, + rect_height + ) + except NameError as e: + logger.error(f"Erreur : draw_history_scrollbar non défini: {str(e)}") -def draw_history_scrollbar(screen): - """Affiche la barre de défilement pour l'historique.""" - if len(config.history) <= config.visible_history_items: +#Barre de défilement de l'historique +def draw_history_scrollbar(screen, scroll_offset, total_items, visible_items, x, y, height): + """Affiche la barre de défilement à droite de l’écran.""" + if len(config.filtered_games) <= config.visible_games: return game_area_height = config.screen_height - 150 - scrollbar_height = game_area_height * (config.visible_history_items / len(config.history)) - scrollbar_y = 120 + (game_area_height - scrollbar_height) * (config.history_scroll_offset / max(1, len(config.history) - config.visible_history_items)) + scrollbar_height = game_area_height * (config.visible_games / len(config.filtered_games)) + scrollbar_y = 120 + (game_area_height - scrollbar_height) * (scroll_offset / max(1, len(config.filtered_games) - config.visible_games)) pygame.draw.rect(screen, (255, 255, 255), (config.screen_width - 25, scrollbar_y, 15, scrollbar_height)) +#Ecran confirmation vider historique +def draw_clear_history_dialog(screen): + """Affiche la boîte de dialogue de confirmation pour vider l'historique.""" + screen.blit(OVERLAY, (0, 0)) + + message = "Vider l'historique ?" + wrapped_message = wrap_text(message, config.font, config.screen_width - 80) + line_height = config.font.get_height() + 5 + text_height = len(wrapped_message) * line_height + button_height = line_height + 20 + margin_top_bottom = 20 + rect_height = text_height + button_height + 2 * margin_top_bottom + max_text_width = max([config.font.size(line)[0] for line in wrapped_message], default=300) + rect_width = max_text_width + 40 + rect_x = (config.screen_width - rect_width) // 2 + rect_y = (config.screen_height - rect_height) // 2 + + pygame.draw.rect(screen, (50, 50, 50, 200), (rect_x, rect_y, rect_width, rect_height), border_radius=10) + pygame.draw.rect(screen, (255, 255, 255), (rect_x, rect_y, rect_width, rect_height), 2, border_radius=10) + + for i, line in enumerate(wrapped_message): + text = config.font.render(line, True, (255, 255, 255)) + text_rect = text.get_rect(center=(config.screen_width // 2, rect_y + margin_top_bottom + i * line_height + line_height // 2)) + screen.blit(text, text_rect) + + yes_text = config.font.render("Oui", True, (0, 150, 255) if config.confirm_clear_selection == 1 else (255, 255, 255)) + no_text = config.font.render("Non", True, (0, 150, 255) if config.confirm_clear_selection == 0 else (255, 255, 255)) + yes_rect = yes_text.get_rect(center=(config.screen_width // 2 - 100, rect_y + text_height + margin_top_bottom + line_height // 2)) + no_rect = no_text.get_rect(center=(config.screen_width // 2 + 100, rect_y + text_height + margin_top_bottom + line_height // 2)) + + screen.blit(yes_text, yes_rect) + screen.blit(no_text, no_rect) + +#Affichage du clavier virtuel sur non pc def draw_virtual_keyboard(screen): """Affiche un clavier virtuel pour la saisie dans search_mode, centré verticalement.""" keyboard_layout = [ @@ -450,9 +565,10 @@ def draw_virtual_keyboard(screen): text_rect = text.get_rect(center=key_rect.center) screen.blit(text, text_rect) +#Ecran de progression de téléchargement/extraction def draw_progress_screen(screen): """Affiche l'écran de progression des téléchargements avec taille en Mo.""" - logger.debug("Début de draw_progress_screen") + #logger.debug("Début de draw_progress_screen") if not config.download_tasks: logger.debug("Aucune tâche de téléchargement active") @@ -466,11 +582,11 @@ def draw_progress_screen(screen): downloaded_size = progress["downloaded_size"] total_size = progress["total_size"] progress_percent = progress["progress_percent"] - logger.debug(f"Progression : game_name={game_name}, url={url}, status={status}, progress_percent={progress_percent}, downloaded_size={downloaded_size}, total_size={total_size}") + #logger.debug(f"Progression : game_name={game_name}, url={url}, status={status}, progress_percent={progress_percent}, downloaded_size={downloaded_size}, total_size={total_size}") screen.blit(OVERLAY, (0, 0)) - title_text = f"{status} : {truncate_text_end(game_name, config.font, config.screen_width - 200)}" + title_text = f"{status} : {truncate_text_middle(game_name, config.font, config.screen_width - 200)}" title_lines = wrap_text(title_text, config.font, config.screen_width - 80) line_height = config.font.get_height() + 5 text_height = len(title_lines) * line_height @@ -491,7 +607,7 @@ def draw_progress_screen(screen): title_render = config.font.render(line, True, (255, 255, 255)) title_rect = title_render.get_rect(center=(config.screen_width // 2, rect_y + margin_top_bottom + i * line_height + line_height // 2)) screen.blit(title_render, title_rect) - logger.debug(f"Titre affiché : texte={line}, position={title_rect}, taille={title_render.get_size()}") + #logger.debug(f"Titre affiché : texte={line}, position={title_rect}, taille={title_render.get_size()}") bar_y = rect_y + text_height + margin_top_bottom progress_width = 0 @@ -500,7 +616,7 @@ def draw_progress_screen(screen): progress_width = int(bar_width * (progress_percent / 100)) pygame.draw.rect(screen, (0, 150, 255), (rect_x + 20, bar_y, progress_width, bar_height)) pygame.draw.rect(screen, (255, 255, 255), (rect_x + 20, bar_y, bar_width, bar_height), 2) - logger.debug(f"Barre de progression affichée : position=({rect_x + 20}, {bar_y}), taille=({bar_width}, {bar_height}), progress_width={progress_width}") + #logger.debug(f"Barre de progression affichée : position=({rect_x + 20}, {bar_y}), taille=({bar_width}, {bar_height}), progress_width={progress_width}") downloaded_mb = downloaded_size / (1024 * 1024) total_mb = total_size / (1024 * 1024) @@ -512,64 +628,25 @@ def draw_progress_screen(screen): percent_render = config.font.render(line, True, (255, 255, 255)) percent_rect = percent_render.get_rect(center=(config.screen_width // 2, text_y + i * line_height + line_height // 2)) screen.blit(percent_render, percent_rect) - logger.debug(f"Texte de progression affiché : texte={line}, position={percent_rect}, taille={percent_render.get_size()}") -def draw_scrollbar(screen): - """Affiche la barre de défilement à droite de l’écran.""" - if len(config.filtered_games) <= config.visible_games: - return - - game_area_height = config.screen_height - 150 - scrollbar_height = game_area_height * (config.visible_games / len(config.filtered_games)) - scrollbar_y = 120 + (game_area_height - scrollbar_height) * (config.scroll_offset / max(1, len(config.filtered_games) - config.visible_games)) - pygame.draw.rect(screen, (255, 255, 255), (config.screen_width - 25, scrollbar_y, 15, scrollbar_height)) - -def draw_clear_history_dialog(screen): - """Affiche la boîte de dialogue de confirmation pour vider l'historique.""" - screen.blit(OVERLAY, (0, 0)) - - message = "Vider l'historique ?" - wrapped_message = wrap_text(message, config.font, config.screen_width - 80) - line_height = config.font.get_height() + 5 - text_height = len(wrapped_message) * line_height - button_height = line_height + 20 - margin_top_bottom = 20 - rect_height = text_height + button_height + 2 * margin_top_bottom - max_text_width = max([config.font.size(line)[0] for line in wrapped_message], default=300) - rect_width = max_text_width + 40 - rect_x = (config.screen_width - rect_width) // 2 - rect_y = (config.screen_height - rect_height) // 2 - - pygame.draw.rect(screen, (50, 50, 50, 200), (rect_x, rect_y, rect_width, rect_height), border_radius=10) - pygame.draw.rect(screen, (255, 255, 255), (rect_x, rect_y, rect_width, rect_height), 2, border_radius=10) - - for i, line in enumerate(wrapped_message): - text = config.font.render(line, True, (255, 255, 255)) - text_rect = text.get_rect(center=(config.screen_width // 2, rect_y + margin_top_bottom + i * line_height + line_height // 2)) - screen.blit(text, text_rect) - - yes_text = config.font.render("Oui", True, (0, 150, 255) if config.confirm_clear_selection == 1 else (255, 255, 255)) - no_text = config.font.render("Non", True, (0, 150, 255) if config.confirm_clear_selection == 0 else (255, 255, 255)) - yes_rect = yes_text.get_rect(center=(config.screen_width // 2 - 100, rect_y + text_height + margin_top_bottom + line_height // 2)) - no_rect = no_text.get_rect(center=(config.screen_width // 2 + 100, rect_y + text_height + margin_top_bottom + line_height // 2)) - - screen.blit(yes_text, yes_rect) - screen.blit(no_text, no_rect) - +#Ecran popup resultat téléchargement def draw_popup_message(screen, message, is_error): """Affiche une popup avec un message de résultat.""" screen.blit(OVERLAY, (0, 0)) - - wrapped_message = wrap_text(message, config.font, config.screen_width - 80) - line_height = config.font.get_height() + 5 + if message is None: + message = "Téléchargement annulé" + logger.debug(f"Message popup : {message}, is_error={is_error}") + wrapped_message = wrap_text(message, config.small_font, config.screen_width - 80) + line_height = config.small_font.get_height() + 5 for i, line in enumerate(wrapped_message): - text = config.font.render(line, True, (255, 0, 0) if is_error else (0, 255, 0)) + text = config.small_font.render(line, True, (255, 0, 0) if is_error else (0, 255, 0)) text_rect = text.get_rect(center=(config.screen_width // 2, config.screen_height // 2 - (len(wrapped_message) // 2 - i) * line_height)) screen.blit(text, text_rect) +#Ecran avertissement extension non supportée téléchargement def draw_extension_warning(screen): """Affiche un avertissement pour une extension non reconnue ou un fichier ZIP.""" - logger.debug("Début de draw_extension_warning") + #logger.debug("Début de draw_extension_warning") if not config.pending_download: logger.error("config.pending_download est None ou vide dans extension_warning") @@ -612,7 +689,7 @@ def draw_extension_warning(screen): text_surface = config.font.render(line, True, (255, 255, 255)) text_rect = text_surface.get_rect(center=(config.screen_width // 2, rect_y + margin_top_bottom + i * line_height + line_height // 2)) screen.blit(text_surface, text_rect) - logger.debug(f"Lignes affichées : {[(rect.center, text_surface.get_size()) for rect, text_surface in zip([text_surface.get_rect(center=(config.screen_width // 2, rect_y + margin_top_bottom + i * line_height + line_height // 2)) for i in range(len(lines))], [config.font.render(line, True, (255, 255, 255)) for line in lines])]}") + #logger.debug(f"Lignes affichées : {[(rect.center, text_surface.get_size()) for rect, text_surface in zip([text_surface.get_rect(center=(config.screen_width // 2, rect_y + margin_top_bottom + i * line_height + line_height // 2)) for i in range(len(lines))], [config.font.render(line, True, (255, 255, 255)) for line in lines])]}") yes_text = "[Oui]" if config.extension_confirm_selection == 1 else "Oui" no_text = "[Non]" if config.extension_confirm_selection == 0 else "Non" @@ -625,7 +702,7 @@ def draw_extension_warning(screen): screen.blit(yes_surface, yes_rect) screen.blit(no_surface, no_rect) - logger.debug(f"Boutons affichés : Oui={yes_rect}, Non={no_rect}, selection={config.extension_confirm_selection}") + #logger.debug(f"Boutons affichés : Oui={yes_rect}, Non={no_rect}, selection={config.extension_confirm_selection}") except Exception as e: logger.error(f"Erreur lors du rendu de extension_warning : {str(e)}") @@ -647,10 +724,11 @@ def draw_extension_warning(screen): error_rect = error_surface.get_rect(center=(config.screen_width // 2, rect_y + 20 + i * line_height + line_height // 2)) screen.blit(error_surface, error_rect) +#Affichage des controles en bas de page def draw_controls(screen, menu_state): """Affiche les contrôles sur une seule ligne en bas de l’écran pour tous les états du menu.""" start_button = get_control_display('start', 'START') - control_text = f"Menu {menu_state} - {start_button} : Options - History - Controls" + control_text = f"{start_button} : Options - History - Controls" max_width = config.screen_width - 40 wrapped_controls = wrap_text(control_text, config.small_font, max_width) line_height = config.small_font.get_height() + 5 @@ -662,40 +740,20 @@ def draw_controls(screen, menu_state): text_rect = text_surface.get_rect(center=(config.screen_width // 2, rect_y + 10 + i * line_height + line_height // 2)) screen.blit(text_surface, text_rect) -def draw_validation_transition(screen, platform_index): - """Affiche une animation de transition pour la sélection d’une plateforme.""" - platform_dict = config.platform_dicts[platform_index] - image = load_system_image(platform_dict) - if not image: - return - orig_width, orig_height = image.get_width(), image.get_height() - base_size = int(config.screen_width * 0.0781) # ~150px pour 1920p - start_time = pygame.time.get_ticks() - duration = 500 - while pygame.time.get_ticks() - start_time < duration: - draw_gradient(screen, (28, 37, 38), (47, 59, 61)) - elapsed = pygame.time.get_ticks() - start_time - scale = 2.0 + (2.0 * elapsed / duration) if elapsed < duration / 2 else 3.0 - (2.0 * elapsed / duration) - new_width = int(base_size * scale) - new_height = int(base_size * scale) - scaled_image = pygame.transform.smoothscale(image, (new_width, new_height)) - image_rect = scaled_image.get_rect(center=(config.screen_width // 2, config.screen_height // 2)) - screen.blit(scaled_image, image_rect) - pygame.display.flip() - pygame.time.wait(10) - +#Menu pause def draw_pause_menu(screen, selected_option): - """Dessine le menu pause avec les options Aide, Configurer contrôles, Historique, Quitter.""" + """Dessine le menu pause avec les options Aide, Configurer contrôles, Historique, Redownload game cache, Quitter.""" screen.blit(OVERLAY, (0, 0)) options = [ "Controls", "Remap controls", "History", + "Redownload Games cache", "Quit" ] - menu_width = int(config.screen_width * 0.2083) # ~400px pour 1920p + menu_width = int(config.screen_width * 0.8) # ~400px pour 1920p line_height = config.font.get_height() + 10 text_height = len(options) * line_height margin_top_bottom = 20 @@ -712,13 +770,7 @@ def draw_pause_menu(screen, selected_option): text_rect = text_surface.get_rect(center=(config.screen_width // 2, menu_y + margin_top_bottom + i * line_height + line_height // 2)) screen.blit(text_surface, text_rect) -def get_control_display(action, default): - """Récupère le nom d'affichage d'une action depuis controls_config.""" - if not config.controls_config: - logger.warning(f"controls_config vide pour l'action {action}, utilisation de la valeur par défaut") - return default - return config.controls_config.get(action, {}).get('display', default) - +#Menu aide controles def draw_controls_help(screen, previous_state): """Affiche la liste des contrôles pour l'état précédent du menu.""" common_controls = { @@ -731,6 +783,7 @@ def draw_controls_help(screen, previous_state): "page_up": lambda action: f"{get_control_display('page_up', 'Q/LB')} : {action}", "page_down": lambda action: f"{get_control_display('page_down', 'E/RB')} : {action}", "filter": lambda action: f"{get_control_display('filter', 'Select')} : {action}", + "history": lambda action: f"{get_control_display('history', 'H')} : {action}", "delete": lambda: f"{get_control_display('delete', 'Retour Arrière')} : Supprimer", "space": lambda: f"{get_control_display('space', 'Espace')} : Espace" } @@ -744,11 +797,13 @@ def draw_controls_help(screen, previous_state): common_controls["confirm"]("Sélectionner"), common_controls["cancel"]("Quitter"), common_controls["start"](), + common_controls["history"]("Historique"), *( [common_controls["progress"]("Progression")] if config.download_tasks else []) ], "game": [ common_controls["confirm"](f"{'Valider' if config.search_mode else 'Télécharger'}"), common_controls["cancel"](f"{'Annuler' if config.search_mode else 'Retour'}"), + common_controls["history"]("Historique"), *( [ common_controls["delete"](), common_controls["space"]() @@ -814,63 +869,13 @@ def draw_controls_help(screen, previous_state): text = config.font.render(line, True, (255, 255, 255)) text_rect = text.get_rect(center=(config.screen_width // 2, popup_y + 40 + i * line_height)) screen.blit(text, text_rect) - -def draw_history(screen): - """Affiche la liste de l'historique des téléchargements.""" - if not config.history: - text = config.font.render("Aucun téléchargement dans l'historique", True, (255, 255, 255)) - screen.blit(text, (config.screen_width // 2 - text.get_width() // 2, config.screen_height // 2)) - return - # Calculer le nombre d'éléments visibles - item_height = config.small_font.get_height() + 10 - config.visible_history_items = (config.screen_height - 200) // item_height - max_scroll = max(0, len(config.history) - config.visible_history_items) - config.history_scroll_offset = max(0, min(config.history_scroll_offset, max_scroll)) - - # Cadre semi-transparent - panel_width = config.screen_width - 100 - panel_height = config.visible_history_items * item_height + 20 - panel_x = (config.screen_width - panel_width) // 2 - panel_y = (config.screen_height - panel_height) // 2 - panel_surface = pygame.Surface((panel_width, panel_height), pygame.SRCALPHA) - panel_surface.fill((0, 0, 0, 128)) - screen.blit(panel_surface, (panel_x, panel_y)) - pygame.draw.rect(screen, (255, 255, 255), (panel_x, panel_y, panel_width, panel_height), 2) - - # Afficher les colonnes - headers = ["Système", "Nom du jeu", "État"] - col_widths = [panel_width // 4, panel_width // 2, panel_width // 4] - header_y = panel_y + 10 - for i, header in enumerate(headers): - text = config.small_font.render(header, True, (255, 255, 255)) - screen.blit(text, (panel_x + sum(col_widths[:i]) + 10, header_y)) - - # Afficher les entrées - start_index = config.history_scroll_offset - end_index = min(start_index + config.visible_history_items, len(config.history)) - for i, entry in enumerate(config.history[start_index:end_index]): - y = panel_y + 40 + i * item_height - color = (255, 255, 0) if i + start_index == config.current_history_item else (255, 255, 255) - system = config.platform_names.get(entry["platform"], entry["platform"]) - system_text = truncate_text_end(system, config.small_font, col_widths[0] - 20) - game_text = truncate_text_end(entry["game_name"], config.small_font, col_widths[1] - 20) - status_text = entry["status"] - texts = [system_text, game_text, status_text] - for j, text in enumerate(texts): - rendered = config.small_font.render(text, True, color) - screen.blit(rendered, (panel_x + sum(col_widths[:j]) + 10, y)) - if i + start_index == config.current_history_item: - pygame.draw.rect(screen, (255, 255, 0), (panel_x + 5, y - 5, panel_width - 10, item_height), 1) - - # Barre de défilement - if len(config.history) > config.visible_history_items: - draw_scrollbar(screen, config.history_scroll_offset, len(config.history), config.visible_history_items, panel_x + panel_width - 10, panel_y, panel_height) +#Menu Quitter Appli def draw_confirm_dialog(screen): """Affiche la boîte de dialogue de confirmation pour quitter.""" global OVERLAY - logger.debug("Rendu de draw_confirm_dialog") + #logger.debug("Rendu de draw_confirm_dialog") # Vérifier si OVERLAY est valide, sinon le recréer if OVERLAY is None or OVERLAY.get_size() != (config.screen_width, config.screen_height): OVERLAY = pygame.Surface((config.screen_width, config.screen_height), pygame.SRCALPHA) @@ -902,34 +907,68 @@ def draw_confirm_dialog(screen): screen.blit(yes_text, yes_rect) screen.blit(no_text, no_rect) -def draw_clear_history_dialog(screen): - """Affiche la boîte de dialogue de confirmation pour vider l'historique.""" +#draw_redownload_game_cache_dialog +def draw_redownload_game_cache_dialog(screen): + """Affiche la boîte de dialogue de confirmation pour retélécharger le cache des jeux.""" + global OVERLAY + #logger.debug("Rendu de draw_redownload_game_cache_dialog") + # Vérifier si OVERLAY est valide, sinon le recréer + if OVERLAY is None or OVERLAY.get_size() != (config.screen_width, config.screen_height): + OVERLAY = pygame.Surface((config.screen_width, config.screen_height), pygame.SRCALPHA) + OVERLAY.fill((0, 0, 0, 128)) + logger.debug("OVERLAY recréé dans draw_redownload_game_cache_dialog") + screen.blit(OVERLAY, (0, 0)) - - message = "Vider l'historique ?" - wrapped_message = wrap_text(message, config.font, config.screen_width - 80) - line_height = config.font.get_height() + 5 + message = "Retélécharger le cache des jeux ?" + wrapped_message = wrap_text(message, config.small_font, config.screen_width - 80) + line_height = config.small_font.get_height() + 5 text_height = len(wrapped_message) * line_height button_height = line_height + 20 margin_top_bottom = 20 rect_height = text_height + button_height + 2 * margin_top_bottom - max_text_width = max([config.font.size(line)[0] for line in wrapped_message], default=300) + max_text_width = max([config.small_font.size(line)[0] for line in wrapped_message], default=300) rect_width = max_text_width + 40 rect_x = (config.screen_width - rect_width) // 2 rect_y = (config.screen_height - rect_height) // 2 - pygame.draw.rect(screen, (50, 50, 50, 200), (rect_x, rect_y, rect_width, rect_height), border_radius=10) pygame.draw.rect(screen, (255, 255, 255), (rect_x, rect_y, rect_width, rect_height), 2, border_radius=10) - + for i, line in enumerate(wrapped_message): - text = config.font.render(line, True, (255, 255, 255)) + text = config.small_font.render(line, True, (255, 255, 255)) text_rect = text.get_rect(center=(config.screen_width // 2, rect_y + margin_top_bottom + i * line_height + line_height // 2)) screen.blit(text, text_rect) - yes_text = config.font.render("Oui", True, (0, 150, 255) if config.confirm_clear_selection == 1 else (255, 255, 255)) - no_text = config.font.render("Non", True, (0, 150, 255) if config.confirm_clear_selection == 0 else (255, 255, 255)) + yes_text = config.small_font.render("Oui", True, (0, 150, 255) if config.redownload_confirm_selection == 1 else (255, 255, 255)) + no_text = config.small_font.render("Non", True, (0, 150, 255) if config.redownload_confirm_selection == 0 else (255, 255, 255)) yes_rect = yes_text.get_rect(center=(config.screen_width // 2 - 100, rect_y + text_height + margin_top_bottom + line_height // 2)) no_rect = no_text.get_rect(center=(config.screen_width // 2 + 100, rect_y + text_height + margin_top_bottom + line_height // 2)) - screen.blit(yes_text, yes_rect) - screen.blit(no_text, no_rect) \ No newline at end of file + screen.blit(no_text, no_rect) + +def draw_popup(screen): + """Dessine un popup avec un message et un compte à rebours.""" + screen.blit(OVERLAY, (0, 0)) + + popup_width = int(config.screen_width * 0.8) # ~400px pour 1920p + line_height = config.small_font.get_height() + 10 + text_lines = config.popup_message.split('\n') + text_height = len(text_lines) * line_height + margin_top_bottom = 20 + popup_height = text_height + 2 * margin_top_bottom + line_height # Espace pour le compte à rebours + popup_x = (config.screen_width - popup_width) // 2 + popup_y = (config.screen_height - popup_height) // 2 + + pygame.draw.rect(screen, (50, 50, 50, 200), (popup_x, popup_y, popup_width, popup_height), border_radius=10) + pygame.draw.rect(screen, (255, 255, 255), (popup_x, popup_y, popup_width, popup_height), 2, border_radius=10) + + for i, line in enumerate(text_lines): + text_surface = config.small_font.render(line, True, (255, 255, 255)) + text_rect = text_surface.get_rect(center=(config.screen_width // 2, popup_y + margin_top_bottom + i * line_height + line_height // 2)) + screen.blit(text_surface, text_rect) + + # Afficher le compte à rebours + remaining_time = max(0, config.popup_timer // 1000) # Convertir ms en secondes + countdown_text = f"Ce message se fermera dans {remaining_time} seconde{'s' if remaining_time != 1 else ''}" + countdown_surface = config.small_font.render(countdown_text, True, (255, 255, 255)) + countdown_rect = countdown_surface.get_rect(center=(config.screen_width // 2, popup_y + margin_top_bottom + len(text_lines) * line_height + line_height // 2)) + screen.blit(countdown_surface, countdown_rect) \ No newline at end of file diff --git a/network.py b/network.py index e6268f1..0d1974e 100644 --- a/network.py +++ b/network.py @@ -3,7 +3,7 @@ import subprocess import re import os import threading -import pygame +import pygame # type: ignore import zipfile import json import time @@ -313,7 +313,7 @@ async def download_rom(url, platform, game_name, is_zip_non_supported=False): config.download_progress[url]["status"] = "Téléchargement" config.download_progress[url]["progress_percent"] = (downloaded / total_size * 100) if total_size > 0 else 0 config.needs_redraw = True # Forcer le redraw - logger.debug(f"Progression: {downloaded}/{total_size} octets, {config.download_progress[url]['progress_percent']:.1f}%") + #logger.debug(f"Progression: {downloaded}/{total_size} octets, {config.download_progress[url]['progress_percent']:.1f}%") if is_zip_non_supported: with lock: @@ -356,7 +356,7 @@ async def download_rom(url, platform, game_name, is_zip_non_supported=False): config.menu_state = "download_result" config.needs_redraw = True # Forcer le redraw # Enregistrement dans l'historique - add_to_history(platform, game_name, "Download_OK" if result[0] else "Erreur") + add_to_history(platform, game_name, "OK" if result[0] else "Error") config.history = load_history() # Recharger l'historique logger.debug(f"Enregistrement dans l'historique: platform={platform}, game_name={game_name}, status={'Download_OK' if result[0] else 'Erreur'}") @@ -387,12 +387,196 @@ def check_extension_before_download(game_name, platform, url): if is_supported: logger.debug(f"L'extension de {sanitized_name} est supportée pour {platform}") return (url, platform, game_name, False) + elif is_archive: + logger.debug(f"Archive {extension.upper()} détectée pour {sanitized_name}, extraction automatique prévue") + return (url, platform, game_name, True) else: - if is_archive: - logger.debug(f"Fichier {extension.upper()} détecté pour {sanitized_name}, extraction automatique prévue") - return (url, platform, game_name, True) - logger.debug(f"L'extension de {sanitized_name} n'est pas supportée pour {platform}") - return None + logger.debug(f"Extension non supportée ({extension}) pour {sanitized_name}, avertissement affiché") + return (url, platform, game_name, False) except Exception as e: logger.error(f"Erreur vérification extension {url}: {str(e)}") - return None \ No newline at end of file + return None + +def is_1fichier_url(url): + """Détecte si l'URL est un lien 1fichier.""" + return "1fichier.com" in url + + +def download_from_1fichier(url, platform, game_name, is_zip_non_supported=False): + """Télécharge un fichier depuis 1fichier en utilisant l'API officielle.""" + logger.debug(f"Début téléchargement 1fichier: {game_name} depuis {url}, is_zip_non_supported={is_zip_non_supported}") + result = [None, None] + + def download_thread(): + logger.debug(f"Thread téléchargement 1fichier démarré pour {url}") + try: + # Nettoyer l'URL + link = url.split('&af=')[0] + + # Déterminer le répertoire de destination + dest_dir = None + for platform_dict in config.platform_dicts: + if platform_dict["platform"] == platform: + dest_dir = platform_dict.get("folder") + break + if not dest_dir: + logger.warning(f"Aucun dossier 'folder' trouvé pour la plateforme {platform}") + dest_dir = os.path.join("/userdata/roms", platform) + + logger.debug(f"Vérification répertoire destination: {dest_dir}") + os.makedirs(dest_dir, exist_ok=True) + if not os.access(dest_dir, os.W_OK): + raise PermissionError(f"Pas de permission d'écriture dans {dest_dir}") + + # Préparer les en-têtes et le payload + headers = { + "Authorization": f"Bearer {config.API_KEY_1FICHIER}", + "Content-Type": "application/json" + } + payload = { + "url": link, + "pretty": 1 + } + + # Étape 1 : Obtenir les informations du fichier + logger.debug(f"Envoi requête POST à https://api.1fichier.com/v1/file/info.cgi pour {url}") + response = requests.post("https://api.1fichier.com/v1/file/info.cgi", headers=headers, json=payload, timeout=30) + logger.debug(f"Réponse reçue, status: {response.status_code}") + response.raise_for_status() + file_info = response.json() + + if "error" in file_info and file_info["error"] == "Resource not found": + logger.error(f"Le fichier {game_name} n'existe pas sur 1fichier") + result[0] = False + result[1] = f"Le fichier {game_name} n'existe pas" + return + + filename = file_info.get("filename", "").strip() + if not filename: + logger.error("Impossible de récupérer le nom du fichier") + result[0] = False + result[1] = "Impossible de récupérer le nom du fichier" + return + + sanitized_filename = sanitize_filename(filename) + dest_path = os.path.join(dest_dir, sanitized_filename) + logger.debug(f"Chemin destination: {dest_path}") + + # Étape 2 : Obtenir le jeton de téléchargement + logger.debug(f"Envoi requête POST à https://api.1fichier.com/v1/download/get_token.cgi pour {url}") + response = requests.post("https://api.1fichier.com/v1/download/get_token.cgi", headers=headers, json=payload, timeout=30) + logger.debug(f"Réponse reçue, status: {response.status_code}") + response.raise_for_status() + download_info = response.json() + + final_url = download_info.get("url") + if not final_url: + logger.error("Impossible de récupérer l'URL de téléchargement") + result[0] = False + result[1] = "Impossible de récupérer l'URL de téléchargement" + return + + # Étape 3 : Initialiser la progression + lock = threading.Lock() + with lock: + config.download_progress[url] = { + "downloaded_size": 0, + "total_size": 0, + "status": "Téléchargement", + "progress_percent": 0, + "game_name": game_name + } + config.needs_redraw = True + logger.debug(f"Progression initialisée pour {url}") + + # Étape 4 : Télécharger le fichier + retries = 10 + retry_delay = 10 + for attempt in range(retries): + try: + logger.debug(f"Tentative {attempt + 1} : Envoi requête GET à {final_url}") + with requests.get(final_url, stream=True, headers={'User-Agent': 'Mozilla/5.0'}, timeout=30) as response: + logger.debug(f"Réponse reçue, status: {response.status_code}") + response.raise_for_status() + total_size = int(response.headers.get('content-length', 0)) + logger.debug(f"Taille totale: {total_size} octets") + with lock: + config.download_progress[url]["total_size"] = total_size + config.needs_redraw = True + + downloaded = 0 + with open(dest_path, 'wb') as f: + logger.debug(f"Ouverture fichier: {dest_path}") + for chunk in response.iter_content(chunk_size=8192): + if chunk: + f.write(chunk) + downloaded += len(chunk) + with lock: + config.download_progress[url]["downloaded_size"] = downloaded + config.download_progress[url]["status"] = "Téléchargement" + config.download_progress[url]["progress_percent"] = (downloaded / total_size * 100) if total_size > 0 else 0 + config.needs_redraw = True + #logger.debug(f"Progression: {downloaded}/{total_size} octets, {config.download_progress[url]['progress_percent']:.1f}%") + + # Étape 5 : Extraire si nécessaire + if is_zip_non_supported: + with lock: + config.download_progress[url]["downloaded_size"] = 0 + config.download_progress[url]["total_size"] = 0 + config.download_progress[url]["status"] = "Extracting" + config.download_progress[url]["progress_percent"] = 0 + config.needs_redraw = True + extension = os.path.splitext(dest_path)[1].lower() + if extension == ".zip": + success, msg = extract_zip(dest_path, dest_dir, url) + elif extension == ".rar": + success, msg = extract_rar(dest_path, dest_dir, url) + else: + raise Exception(f"Type d'archive non supporté: {extension}") + if not success: + raise Exception(f"Échec de l'extraction de l'archive: {msg}") + result[0] = True + result[1] = f"Downloaded / extracted : {game_name}" + else: + os.chmod(dest_path, 0o644) + logger.debug(f"Téléchargement terminé: {dest_path}") + result[0] = True + result[1] = f"Download_OK : {game_name}" + return + + except requests.exceptions.RequestException as e: + logger.error(f"Tentative {attempt + 1} échouée : {e}") + if attempt < retries - 1: + import time + time.sleep(retry_delay) + else: + logger.error("Nombre maximum de tentatives atteint") + result[0] = False + result[1] = f"Échec du téléchargement après {retries} tentatives" + return + + except requests.exceptions.RequestException as e: + logger.error(f"Erreur API 1fichier : {e}") + result[0] = False + result[1] = f"Erreur lors de la requête API, la clé est peut etre incorrecte: {str(e)}" + + finally: + logger.debug(f"Thread téléchargement 1fichier terminé pour {url}") + with lock: + config.download_result_message = result[1] + config.download_result_error = not result[0] + config.download_result_start_time = pygame.time.get_ticks() + config.menu_state = "download_result" + config.needs_redraw = True + # Enregistrement dans l'historique + add_to_history(platform, game_name, "Download_OK" if result[0] else "Erreur") + config.history = load_history() + logger.debug(f"Enregistrement dans l'historique: platform={platform}, game_name={game_name}, status={'Download_OK' if result[0] else 'Erreur'}") + + thread = threading.Thread(target=download_thread) + logger.debug(f"Démarrage thread pour {url}") + thread.start() + thread.join() + logger.debug(f"Thread rejoint pour {url}") + + return result[0], result[1] \ No newline at end of file diff --git a/output.json b/output.json new file mode 100644 index 0000000..cb25f54 --- /dev/null +++ b/output.json @@ -0,0 +1,3997 @@ +[ + [ + "1.2.Switch.PROPER.NSW-BigBlueBox kaze-nico.xci", + "https://1fichier.com/?vcq2cna4bn37gr5xgrsv", + "" + ], + [ + "1971 Project Helios eur 0.6.9 - kaze-nico.xci", + "https://1fichier.com/?alqkj9flb0slr69bnf1q", + "" + ], + [ + "9 Monkeys Of Shaolin V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?90x0ovmc9ay1b0vr9aik", + "" + ], + [ + "A Monsters Expedition and Earlier Adventures Eur XCi - kaze-nico.xci", + "https://1fichier.com/?vh8hfd7xhxsajqn1ze4v", + "" + ], + [ + "A Place for the Unwilling Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ur5h4iuwdi5qfk7go2gu", + "" + ], + [ + "A Space for the Unbound v1.0.14.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?yq3jtz801yxvmy175838", + "" + ], + [ + "A Tale of Synapse The Chaos Theories V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c0ahgu985hso0wnsfotp", + "" + ], + [ + "A-Train All Aboard Tourism eur - kaze-nico.xci", + "https://1fichier.com/?pird5a85j5p9uo0v5v3h", + "" + ], + [ + "ABZU Eur XCi - kaze-nico.xci", + "https://1fichier.com/?yg6gjfeswl85uuhig7q7", + "" + ], + [ + "AO Tennis 2 V1.0.6 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?p4ut71ihdixhhg8zwkk9", + "" + ], + [ + "ARK Ultimate Survivor Edition V2.0.4 Incl 3 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?hqvbhs2k0mr6kbnp0dak", + "" + ], + [ + "ASTRONEER V1.23.107.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?1vmonhu0s5y9xad994c7", + "" + ], + [ + "ATOM RPG V1.1.71 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?obtpxiurmv6hs4urwdys", + "" + ], + [ + "AVICII Invector V1.4.1 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ngpr7tqs8wef604kbx98", + "" + ], + [ + "Abathor V2.0.0 EU SuperXci - Nicokoei.xci", + "https://1fichier.com/?er1bqna7lwmicxj0cvuh", + "" + ], + [ + "Adams Venture Origins Eur XCi - kaze-nico.xci", + "https://1fichier.com/?iei63g12ok5kox3pt368", + "" + ], + [ + "Advance Wars 1 and 2 ReBoot Camp v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?wueq9doh4q69ybz3h7ax", + "" + ], + [ + "Adventure Academia The Fractured Continent v1.0.1 Incl 17 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?oc5mniq0kulcgyx26uzr", + "" + ], + [ + "Aeon Must Die V1.0.2 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c1xiw9et3ukha4w8ps9q", + "" + ], + [ + "Aery - Sky Castle Eur XCi - kaze-nico.xci", + "https://1fichier.com/?16ajmuitc578poe9ctyt", + "" + ], + [ + "Aery A Journey Beyond Time Eur XCi - kaze-nico.xci", + "https://1fichier.com/?w7icp6vmk9yf6182gj9f", + "" + ], + [ + "Aery Calm Mind 2 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?3wn6ufrjajxcgm36ilj4", + "" + ], + [ + "Aery Calm Mind Eur XCi - kaze-nico.xci", + "https://1fichier.com/?mlxoqc05vhvvfiqzuin0", + "" + ], + [ + "Aery Dreamscape Eur XCi - kaze-nico.xci", + "https://1fichier.com/?1suozh6tp7pd09th4px4", + "" + ], + [ + "Aery Little Bird Adventure EUR XCi - kaze-nico.xci", + "https://1fichier.com/?we2vtxheueo9r3wu6d8n", + "" + ], + [ + "Aery Vikings Eur XCi - kaze-nico.xci", + "https://1fichier.com/?r1dvii72pmprdad3p8ko", + "" + ], + [ + "AeternoBlade II Directors Rewind v2.1.0.3 Incl 8 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?6od7c7y215pzn6gz6yra", + "" + ], + [ + "Afterimage Switch v1.0.3 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?yivoaajul498m5duqbmf", + "" + ], + [ + "Agatha Christie Hercule Poirot The First Cases V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?1mwmg1h8c898f92hqwwd", + "" + ], + [ + "Agatha Christie Hercule Poirot The London Case v1.0.1 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?5duhg9nmkwihy7m1el8s", + "" + ], + [ + "Agatha Christie The ABC Murders V1.1.6 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?i7oj0spew2fg18jx339a", + "" + ], + [ + "Alan Wake Remastered Eur XCi - kaze-nico.xci", + "https://1fichier.com/?lcid8229bqw4kws9x9f8", + "" + ], + [ + "Alba A Wildlife Adventure Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ylbn87wbektzwiw4w81g", + "" + ], + [ + "Alex Kidd in Miracle World DX V1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?lr3b6cx4nqfrl94uv0iy", + "" + ], + [ + "Alien Isolation V1.1.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?pnsbsvfy1h0vnic65bko", + "" + ], + [ + "AllStar Fruit Racing V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?79xzmexuz0c8swkfqdc1", + "" + ], + [ + "Alwas Legacy V1.3.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?j8zinrfwcsqx92kknxie", + "" + ], + [ + "Among Us V2020.12.5 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?86fhge9ne2rbvevu8jdw", + "" + ], + [ + "Ancestors Legacy Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ajxnft2f6i03vcqfdwu8", + "" + ], + [ + "Animal Crossing New Horizons V2.0.5 Incl. 3 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?5ybdck8kbacrzuk8r9zr", + "" + ], + [ + "Another Code Recollection - Nicokoei .xci", + "https://1fichier.com/?vrh3hzj5hm4ak7qv41v1", + "" + ], + [ + "Anti Hero Bundle Eur XCi - kaze-nico.xci", + "https://1fichier.com/?v1t1hh8im29o0g4cb9rh", + "" + ], + [ + "Ape Out Eur V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0x4vqx80dzs6v1ydqndx", + "" + ], + [ + "Apollo Justice Ace Attorney Trilogy v1.0.1 Eur - Nicokoei.xci", + "https://1fichier.com/?zaftkvskob2wtdzf4ja0", + "" + ], + [ + "Aragami 2 v1.0.30195.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?asn98jf2p3y3u3ielh32", + "" + ], + [ + "Arcade Spirits Eur XCi - kaze-nico.xci", + "https://1fichier.com/?j1er9lxsos7ciugqh4sk", + "" + ], + [ + "Arise A Simple Story Definitive Edition V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zlyiv2rrh6wld6iczzym", + "" + ], + [ + "Art of Rally Eur XCi - kaze-nico.xci", + "https://1fichier.com/?dc2e0s1vixhyzaimv1yl", + "" + ], + [ + "Ary and the Secret of Seasons V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?z4ejv6jduj7m9d5m9iw4", + "" + ], + [ + "Ash of Gods The Way v1.0.5 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?c5izkccj9xllfb41lz6s", + "" + ], + [ + "Asterix and Obelix Baffez les tous v1.0.4.41 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?uhlu51ij0nhx15ealrj7", + "" + ], + [ + "Asterix and Obelix XXL Romastered Eur XCi - kaze-nico.xci", + "https://1fichier.com/?4xi4z1jrcr0s7uq28bvn", + "" + ], + [ + "Asterix et Obelix XXL3 Le Menhir de Cristal V1.1.59.0 Incl. 2 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?f6x0y3kr0z5e7tmjqahk", + "" + ], + [ + "Astria Ascending V1.0.97 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?u83cys0kj1qdcqur2gi0", + "" + ], + [ + "Atari 50 The Anniversary Celebration v1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?it7kmngbkoorw6tfmzna", + "" + ], + [ + "Atelier Ryza 2 Lost Legends and the Secret Fairy eur superxci 1.0.2_22DLC patched - kaze-nico.xci", + "https://1fichier.com/?ozmr0b4humn1qmgu6051", + "" + ], + [ + "Atom RPG Eur XCi - kaze-nico.xci", + "https://1fichier.com/?avtzjhxcyc86s5xrr8pb", + "" + ], + [ + "Attack on Titan 2 Final Battle [US] 1.0.14+58DLC - kaze-nico.xci", + "https://1fichier.com/?5sy64fcjt9b1xpzgst84", + "" + ], + [ + "Ayo the Clown Eur XCi - kaze-nico.xci", + "https://1fichier.com/?3wcmebq6cuemt7tgjoef", + "" + ], + [ + "BALAN WONDERWORLD V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?j3mbf0umdaduvw2wtdnj", + "" + ], + [ + "BDSM Big Drunk Satanic Massacre V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?a2se9ao866wj9079aav5", + "" + ], + [ + "BEAUTIFUL DESOLATION V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?whse2qq4g2sgzlabigh6", + "" + ], + [ + "BLUE REFLECTION Second Light Incl. 15 Dlcs V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?lhyjk9tfi9roqv4qu9ri", + "" + ], + [ + "BOSSGARD Eur XCi - kaze-nico.xci", + "https://1fichier.com/?1kxst2gm6tdnw32479c5", + "" + ], + [ + "Backbone Eur XCi - kaze-nico.xci", + "https://1fichier.com/?61uu0w5uom9dj0jeda35", + "" + ], + [ + "Bake n Switch Eur XCi - kaze-nico.xci", + "https://1fichier.com/?i5h44hqicnvugwcun4ww", + "" + ], + [ + "Bakugan Champions of Vestroia V1.01.00 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?mtmv4chpu1cotwem0hno", + "" + ], + [ + "Baldo The guardian owls V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?8thfjxuvvlnwab9k94ya", + "" + ], + [ + "Bandle Tale A League of Legends Story v1.062 Eur - Nicokoei.xci", + "https://1fichier.com/?lb9vls1j0lh13frgivd4", + "" + ], + [ + "Baten Kaitos I and II HD Remaster v1.0.1 Jap MultiEng SuperXCi - Nicokoei.xci", + "https://1fichier.com/?se1mujhkchzgwr5ru2c2", + "" + ], + [ + "Bayonetta 3 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?6s7luw5eiataesp5cbvk", + "" + ], + [ + "Bayonetta Trilogie Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ryg6zy5yp90pvqk1q6b6", + "" + ], + [ + "Ben 10 Power Trip V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?usqvpbxrgwbrppouw1i4", + "" + ], + [ + "Billion Road Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9tugprjbi6w4jc2aumyw", + "" + ], + [ + "BioShock 2 Remastered V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?mej8zf9usja9u8w9eq0w", + "" + ], + [ + "BioShock Infinite The Complete Edition [0100D560102C8000] [v65536] - kaze-nico.xci", + "https://1fichier.com/?eb9c36hrhzgq542aiy3x", + "" + ], + [ + "BioShock Remastered V1.0.2 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?jm72ukip5zihwhm7zjr1", + "" + ], + [ + "Biped V1.0.1 Jap MultiFr SuperXCi - kaze-nico.xci", + "https://1fichier.com/?1a0pnlrs3zptgaiekkla", + "" + ], + [ + "Bladed Fury Repack Eur XCi - kaze-nico.xci", + "https://1fichier.com/?34ypd4xqcx0veduhn4i8", + "" + ], + [ + "Blasphemous V1.0.4 Incl Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?d9crqrfxgm1g4f022vp8", + "" + ], + [ + "Blaster Master Zero 2 V1.5.1 Incl. 6 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c28qw8vrkqeltjpvfmqa", + "" + ], + [ + "Blizzard Arcade Collection eur_1.0.1 patched - kaze-nico.xci", + "https://1fichier.com/?al1bmy7fgcze573lpnn0", + "" + ], + [ + "BloodRayne Betrayal Fresh Bites Eur XCi - kaze-nico.xci", + "https://1fichier.com/?1bym9dcg526jtjvy9hz0", + "" + ], + [ + "Bloodstained Ritual of the Night V1.2.0 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2ems4uspodicc5rpyuvf", + "" + ], + [ + "Blue Fire SuperXci 3.0.7_Eur_patched - kaze-nico.xci", + "https://1fichier.com/?1rx401edc2rtdkjta6zr", + "" + ], + [ + "Bob l eponge Cuisine en Folie Eur XCi - kaze-nico.xci", + "https://1fichier.com/?hdj4xvcymh6jdan3gp4f", + "" + ], + [ + "Boomerang X V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?b5wuwctkvbe314z14es7", + "" + ], + [ + "Borderlands 2 Game of the Year Edition V1.0.1 Incl. 2 Dlcs Eur XCi - kaze-nico.xci", + "https://1fichier.com/?my4etx37rev5my1pdupw", + "" + ], + [ + "Borderlands Game Of The Year Edition V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?su05ev6sh2r2nts31b8x", + "" + ], + [ + "Borderlands The Pre-Sequel Ultimate Edition V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?gqctog5omd1kr04trix8", + "" + ], + [ + "Bounty Battle V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?o82lizcvcri7a8y13qvk", + "" + ], + [ + "Bramble The Mountain King v1.0.5 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?x558fl961m4ouzaw89vw", + "" + ], + [ + "Bravely Default II _eur - kaze-nico.xci", + "https://1fichier.com/?ahv70xivnlobo75trlyv", + "" + ], + [ + "Brawlout V2.2.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?p9rrg9r6x7ew32pibah1", + "" + ], + [ + "Breathedge Eur XCi - kaze-nico.xci", + "https://1fichier.com/?2w4pv9jnoo9vl60cufiy", + "" + ], + [ + "Bright Memory Infinite Gold Edition v1.2 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?jufsbdyfyrk6gbvcojgb", + "" + ], + [ + "Broken Sword - Shadow of the Templars Reforged (v1.1.5) (EU) SuperXCI-Nicokoei.xci", + "https://1fichier.com/?qfuwtlazz5iasrsgldh1", + "" + ], + [ + "Burnout Paradise Remastered EUR XCi - kaze-nico.xci", + "https://1fichier.com/?aib4n63x0yilgixeo922", + "" + ], + [ + "Bus Driving Simulator 22 v1.1 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?avb83jjtje418mrdpm1y", + "" + ], + [ + "CARRION V1.0.12 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?jr6kmqzs3d2i20dznkim", + "" + ], + [ + "CATAN - Console Edition (v3.2.0 & DLC) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?ehetrpe8y1nv62dgj00r", + "" + ], + [ + "CRISIS CORE FINAL FANTASY VII REUNION V1.0.2 Incl Dlc Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?kcd1esk17g3dw6ax4sfj", + "" + ], + [ + "CRSED F.O.A.D. V2.0.2.131 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?6e4qube6s75710d8t9vy", + "" + ], + [ + "Cadence of Hyrule Crypt of the NecroDancer Featuring The Legend of Zelda V1.4.0 Incl. 4 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ztl49t61n3hgoc743mnk", + "" + ], + [ + "Capcom Arcade Stadium V1.0.2 Incl. 31 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vkaoxjtu4awzp86pp5jx", + "" + ], + [ + "Captain Tsubasa Rise of New Champions V1.30 Incl. 7 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?8duqj0zg1p0aedr08lju", + "" + ], + [ + "Caravan SandWitch (v1.02) (US) SuperXCI -Nicokoei.xci", + "https://1fichier.com/?f5wjsn4hd2luoyujxnkj", + "" + ], + [ + "Carto Eur XCi - kaze-nico.xci", + "https://1fichier.com/?shlcgdh4zmkis762k4qx", + "" + ], + [ + "Carto V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?5cuqa1yuvj0i3wdykr8t", + "" + ], + [ + "Cassiodora v1.0 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?eaxarbq0nmma1rexx4fv", + "" + ], + [ + "CastleStorm II V1.1.0.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hnmunr2ifwy6fn81d7m1", + "" + ], + [ + "Castlevania_Dominus_Collection_NSW-VENOM V1.0 [EU] - Nicokoei.nsp", + "https://1fichier.com/?h0tadrgsq87s0f2kvddo", + "" + ], + [ + "Cat Quest II V1.0.6 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?3vh3vxwudjd0utzitmsb", + "" + ], + [ + "Cat Quest III V1.1.0 EU SuperXci - Nicokoei.xci", + "https://1fichier.com/?scrdykxffe2r42it8y1k", + "" + ], + [ + "Catherine Full Body V1.0.1 US MultiFr SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ru0yyaly8atf6jon3g1s", + "" + ], + [ + "Cave Story Plus V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4vh6x5qhbfk6ym1jc0vf", + "" + ], + [ + "Cerebrale Academie Bataille de Meninges Eur XCi - kaze-nico.xci", + "https://1fichier.com/?83sfllikzaxd5m3ztv0m", + "" + ], + [ + "Chained Echoes v1.1.2 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?r30j6lmewfirijqtnguz", + "" + ], + [ + "Chicory A Colorful Tale V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?cz8djw9tpcxop6tt3i59", + "" + ], + [ + "Children of Morta V1.0.8 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4cnl93dv08havvatyqth", + "" + ], + [ + "Chocobo GP V1.0.5 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4zxjk8rxh1egxgmz4hla", + "" + ], + [ + "Chocobos Mystery Dungeon Every Buddy V1.0.1 Incl. 15 Dlcs SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2vaougqyyt21wa6q3413", + "" + ], + [ + "Citizens Unite Earth x Space [Eur) - kaze-nico.xci", + "https://1fichier.com/?syijmihi5guzp9igaap0", + "" + ], + [ + "Clea 2 eur 1.3_patched - kaze-nico.xci", + "https://1fichier.com/?hklsw9k96xrrmv9cabqh", + "" + ], + [ + "Clea V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?o35eqdsp91zzrwzcjw5u", + "" + ], + [ + "Cloudpunk V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?9ozocubw0627o29fboq1", + "" + ], + [ + "Clubhouse Games 51 Worldwide Classics V1.1.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?qf1hj41asny3hb94udfu", + "" + ], + [ + "Cobra Kai The Karate Kid Saga Continues V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?019lt9fv7s4sd4yo1qbo", + "" + ], + [ + "Code Realize Future Blessings Eur XCi - kaze-nico.xci", + "https://1fichier.com/?j9wx4c9x8sfhbgiv9sml", + "" + ], + [ + "Collar X Malice V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ndak4ty7oyn0ocrdtzfv", + "" + ], + [ + "Commandos 2 HD Remaster V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ypgr29wcm5ista3u1yrs", + "" + ], + [ + "Company of Heroes Collection v1.5.66915 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?pjdxu2yoccft6js8dwjm", + "" + ], + [ + "Cooking Mama Cookstar V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?3k74f25e55cebmir6983", + "" + ], + [ + "Cooking Simulator Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5buny2yb78vnyww9efcn", + "" + ], + [ + "Cooking Star Restaurant Eur XCi - kaze-nico.xci", + "https://1fichier.com/?35hfp8iczzo7dbphaglo", + "" + ], + [ + "Crash Bandicoot 4 Its About Time _eur_1.1+2DLC_patched - kaze-nico.xci", + "https://1fichier.com/?kjnopo1986u0zttinmb9", + "" + ], + [ + "Crash team racing nitro-fueled V1.0.15 Incl. 7 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?03xyakqw9tj3jic77ylz", + "" + ], + [ + "Creaks Eur XCi - kaze-nico.xci", + "https://1fichier.com/?dj7ffixfl56n13comu1z", + "" + ], + [ + "Creepy Tale 2 V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?02f527zf5rlmql6pqxb0", + "" + ], + [ + "Crime O Clock v1.3.0 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?w9bmldty37l41qawauux", + "" + ], + [ + "Cris Tales V1.02 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vxhavgksku4qh3buq0om", + "" + ], + [ + "Crosscode V1.0.8 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zbxemzj9zidvfo5wfs7o", + "" + ], + [ + "Crown Trick V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?z59xx6vwcspo6zlj0jmp", + "" + ], + [ + "Crysis 2 Remastered Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5iqwwvqdavwzgqtfakdy", + "" + ], + [ + "Crysis 3 Remastered Eur XCi - kaze-nico.xci", + "https://1fichier.com/?h1k99xclcmvxtkc0ocwu", + "" + ], + [ + "Crysis Remastered V1.6.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2s1x7565p6rvkdygn0yb", + "" + ], + [ + "Curious Expedition 2 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?mg5v2vn2ecx1xfluwl0q", + "" + ], + [ + "Curse of the Sea Rats v1.0.14 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?4evrcwapauk6moctydqg", + "" + ], + [ + "Cynthia Hidden in the Moonshadow (v1.01) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?i6hexmnhoao83ilt7v2l", + "" + ], + [ + "DARQ Complete Edition V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vmcp3pmmfu4mi2yzkb6d", + "" + ], + [ + "DC Krypto Super Chien Les aventures de Krypto et Ace Eur XCi - kaze-nico.xci", + "https://1fichier.com/?r1rl2apd7egk8g1ni8vx", + "" + ], + [ + "DEAD CELLS V1.8.0 Incl. 2 Dlcs Eur SuperXCi PROPER - kaze-nico.xci", + "https://1fichier.com/?987faoir62dhd6wqltm0", + "" + ], + [ + "DEAD OR ALIVE Xtreme 3 Scarlet V1.06 Incl 55 Dlcs Jap MultiEng SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4a2latbvc7arzooi0ovn", + "" + ], + [ + "DEADLY PREMONITION Origins V1.0.3 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?j132l9il2wd4mfdwfm37", + "" + ], + [ + "DOOM + DOOM II (v1.02) (EU) SuperXCI - MBC.xci", + "https://1fichier.com/?5jmfur9punxiabftx9ls", + "" + ], + [ + "DOOM 3 V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?os9tyk8j1tagnzh9x4yw", + "" + ], + [ + "DOOM Eternal V1.2 Incl. 2 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?efcmo27drh5rroydu1q0", + "" + ], + [ + "DRAGON BALL Z KAKAROT v1.50 & 14 DLC) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?e8iyyvtbcar43vc4duyi", + "" + ], + [ + "DRAGON QUEST MONSTERS The Dark Prince (v1.02) (Incl 10 DLC) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?af3wszydfu3d84kgid2k", + "" + ], + [ + "Daemon X Machina V1.4.0 Inc. 81 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?8wp6o8zvgoffncdv62ng", + "" + ], + [ + "Danganronpa 2 - Goodbye Despair Anniversary Edition Eur XCi - kaze-nico.xci", + "https://1fichier.com/?vsxycf20k1fc04mboj5h", + "" + ], + [ + "Danganronpa S - Ultimate Summer Camp Eur XCi - kaze-nico.xci", + "https://1fichier.com/?hxxu4y3qbnsoqd4eisu3", + "" + ], + [ + "Danganronpa V3 - Killing Harmony Anniversary Edition Eur XCi - kaze-nico.xci", + "https://1fichier.com/?98paqv5r2xqffhabs484", + "" + ], + [ + "Darksiders Genesis V1.0.3 US MultiFr SuperXCi - kaze-nico.xci", + "https://1fichier.com/?orxg8ydwe0vlrbxtsj89", + "" + ], + [ + "Dead Cells V1.22.2 Incl. 4 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?9hi2eh62akg9of9nvj5v", + "" + ], + [ + "Dead Synchronicity Tomorrow Comes Today EUR XCi - kaze-nico.xci", + "https://1fichier.com/?5y3qsxde9p25tgwvrjjg", + "" + ], + [ + "Dead Z Meat V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?fmfbtvweg3e3er96h714", + "" + ], + [ + "Deadly Premonition 2 A Blessing In Disguise V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?cagfw4rrd1iahh1wnhj8", + "" + ], + [ + "Death_Noodle_Delivery_NSW-SUXXORS V1.0 [EU] - Nicokoei.nsp", + "https://1fichier.com/?o7hw04gx3p3zau1hmsno", + "" + ], + [ + "Demon Slayer Kimetsu no Yaiba The Hinokami Chronicles V1.01 Incl Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?cenvp4h2a17ncdceu11a", + "" + ], + [ + "Descenders V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?gjkk088q1twpxyt8vx94", + "" + ], + [ + "Destroy All Humans Eur XCi - kaze-nico.xci", + "https://1fichier.com/?166hqhn68ob7k31p9iat", + "" + ], + [ + "Diablo III v2.6.10.71252 Incl Patch FR Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?tgc14y4sfz7au5hdsdh7", + "" + ], + [ + "Disaster Report 4 Summer Memories V1.0.1 Incl. 20Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?x8l3gua67pe34rijwg7y", + "" + ], + [ + "Disco Elysium The Final Cut V 1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?wwhnpqku8qc6nuasppv4", + "" + ], + [ + "Disgaea 6 Defiance of Destiny V1.0.2 Incl. 12 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?pu60ozpkovsyfq2xf2rm", + "" + ], + [ + "Disgaea 7 Vows Of The Virtueless v1.0 Incl 19 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?5t667evdsf1lrmoqdtl2", + "" + ], + [ + "Disney Dreamlight Valley V1.7.0 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?ze9xqxkfwleepqynvtvx", + "" + ], + [ + "Disney Speedstorm v1.0.0f2 Incl Dlc Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?ncrdw529tcva1h4dioph", + "" + ], + [ + "Divinity Original Sin 2 Definitive Edition V1.0.9 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?efmoj5k0322pnus1ktvv", + "" + ], + [ + "Dog Duty V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?sj5kijdeo71bcf2uxf1u", + "" + ], + [ + "Donkey Kong Country Returns HD (v1.0.0) (EU) - Nicokoei.xci", + "https://1fichier.com/?yjrnk3muree40gp8tsak", + "" + ], + [ + "Double Dragon Neon Eur XCi - kaze-nico.xci", + "https://1fichier.com/?cbpxexxik70w0hlc542s", + "" + ], + [ + "Dragon Ball FighterZ V1.30 Incl. All Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2zcrcrku9ux7fr1ewif1", + "" + ], + [ + "Dragon Ball Xenoverse 2 V1.17.1 Incl. all Dlcs SuperXCI - kaze-nico.xci", + "https://1fichier.com/?pyds92si0ipsfi3p7ud8", + "" + ], + [ + "Dragon Marked for Death V3.1.4 Incl. 5 Dlcs SuperXCi - kaze-nico.xci", + "https://1fichier.com/?qk42oz2nttktc8bpies3", + "" + ], + [ + "Dragon Quest III HD - 2D Remake (v1.0.0) (US) (XCI) - Nicokoei.xci", + "https://1fichier.com/?8e1wwtsnp2zlkl2ok3cl", + "" + ], + [ + "Drawn to Life Two Realms Eur XCi - kaze-nico.xci", + "https://1fichier.com/?6mw5d8v96va65vcxw5rp", + "" + ], + [ + "Dread Nautical Eur XCi - kaze-nico.xci", + "https://1fichier.com/?o2jqypw02118buo2e22s", + "" + ], + [ + "DreamWorks Dragons Legendes des Neuf Royaumes Eur XCi - kaze-nico.xci", + "https://1fichier.com/?swqzlg029n4aqlc3p8gu", + "" + ], + [ + "DreamWorks Spirit La grande aventure de Lucky V1.0.2r5 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?1jdeqhrj1qq5y2bdenpl", + "" + ], + [ + "Dreamo V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?9mtzi88tveoy6miuo3sx", + "" + ], + [ + "Duke Nukem 3D 20th Anniversary World Tour V1.2.0 EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?76244r7nwkj104jyssxn", + "" + ], + [ + "Dungeon Defenders Awakened Eur XCi - kaze-nico.xci", + "https://1fichier.com/?e1q4xm5yi6n3d0oht8hq", + "" + ], + [ + "Dungeon of the Endless V1.1.6 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zpbfoo252i2bkvi9snm0", + "" + ], + [ + "DungeonTop Spell Sword Cards Eur XCi - kaze-nico.xci", + "https://1fichier.com/?vaqkya6478t33ippmeo2", + "" + ], + [ + "Dusk Eur XCi - kaze-nico.xci", + "https://1fichier.com/?74eak1h0vwleg9hs3aux", + "" + ], + [ + "Dynasty Warriors 9 Empires Eur XCi - kaze-nico.xci", + "https://1fichier.com/?l0f3e0u7mp1o3oy7c4d5", + "" + ], + [ + "ENDER LILIES Quietus of the Knights V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ay7bsmzh4mqldrhblcz6", + "" + ], + [ + "Eiyuden Chronicle Hundred Heroes (v1.03) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?ww7ldeos0cfh5kjw4oo3", + "" + ], + [ + "Empire of Sin V1.01.37963m Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?j2oa8dz8tns36d2lzfyd", + "" + ], + [ + "Endless Ocean Luminous V1.0.1 US SuperXci Nicokoei.xci", + "https://1fichier.com/?7ettiwh6e7jl9slu54x1", + "" + ], + [ + "Endling - Extinction is Forever v1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?tzxf1foh9htcf5locu59", + "" + ], + [ + "Escape First 2_eur_patched - kaze-nico.xci", + "https://1fichier.com/?h0ul8l22ysjxpmkfcj2b", + "" + ], + [ + "Escape Game Fort Boyard V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?xaosl7yx624ndstfzt1n", + "" + ], + [ + "Europa (v1.3.0) (EU) SuperXCI - Nicokoei .xci", + "https://1fichier.com/?ta85qamivp50xuoa0vzr", + "" + ], + [ + "Evergate V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?t7knsy0xpggaf56djy9e", + "" + ], + [ + "Exit the Gungeon V2.0.6 US MultiFR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ybmucb1jxi3h5asf7b3l", + "" + ], + [ + "F-ZERO 99 v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?kr8orqfpewaadmsz61aa", + "" + ], + [ + "FANTASIAN Neo Dimension (v1.0.0) (EU) Nicokoei.xci", + "https://1fichier.com/?wkz9jjqac55ubsy5ela0", + "" + ], + [ + "FATAL FURY FIRST CONTACT Eur XCi - kaze-nico.xci", + "https://1fichier.com/?cfvcuob1lcngcnevjv8x", + "" + ], + [ + "FIFA 21 Legacy Edition V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?5tulidln4q1bjkc4l68v", + "" + ], + [ + "FIGHTING EX LAYER ANOTHER DASH eur_patched - kaze-nico.xci", + "https://1fichier.com/?c95jj95p2kzu5dmvjcsa", + "" + ], + [ + "FINAL FANTASY CRYSTAL CHRONICLES Remastered Edition V1.0.3 Incl. 12 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?i0hnk4lnntgdfdj7qkv8", + "" + ], + [ + "FRONT_MISSION_2_Remake_NSW-VENOM (v1.0) [EU] - Nicokoei.nsp", + "https://1fichier.com/?vxay85k9u1qkqig7zfeu", + "" + ], + [ + "Fae Farm v1.3.1 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?1lbhxqcjbfxwv0o1ki19", + "" + ], + [ + "Faeria V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?cxxfu15k9x70x5fp7hqx", + "" + ], + [ + "Fairy Tail V1.0.6 Incl. 62 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zwg8buf12zn55c092jjj", + "" + ], + [ + "Fall of Light Darkest Edition V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?817uk5okxfn7l4g63ek9", + "" + ], + [ + "Farewell North V1.0.11 EU SuperXci - Nicokoei.xci", + "https://1fichier.com/?froz7ngy51xrzi4zc0sp", + "" + ], + [ + "Farm Together V1.24.0 Incl. all Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zyn4aobmdy7gg4zybtqd", + "" + ], + [ + "Farming Simulator 20 v1.1.2.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2uy4i71jnhhcyhdlzsff", + "" + ], + [ + "Felix The Reaper V65536 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?jypuntnjucn5tgilnvnf", + "" + ], + [ + "Fell Seal Arbiters Mark V1.4.1 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?85939ws0pg9yv26nr8zf", + "" + ], + [ + "Fifa 23 Legacy Edition Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5sodhxtxxp03bwmse5rt", + "" + ], + [ + "Fight of Animals Eur XCi - kaze-nico.xci", + "https://1fichier.com/?tmob1p5xmdfqqylkeq99", + "" + ], + [ + "Figment V1.1.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?w7ffqaghsm3pp71hobt1", + "" + ], + [ + "Filament Eur XCi - kaze-nico.xci", + "https://1fichier.com/?xqwme05djwa0wqvoqtsr", + "" + ], + [ + "Final Fantasy 1-6 Bundle Remastered v1.0.2 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?rr8nwf1omcbxr2v26iai", + "" + ], + [ + "Final Fantasy Crystal Chronicles Remastered Edition V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vf99rq5abwp7mw0tlnl5", + "" + ], + [ + "Final Fantasy VII V1.0.2 EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?y30n9fbegerqhjlgtjng", + "" + ], + [ + "Fire Emblem Engage v1.2.0 Incl Dlc Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?zl8g4r7za3t2voo6adgw", + "" + ], + [ + "Fire Emblem Warriors Three Hopes Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9w602k3ngver5ogkwjck", + "" + ], + [ + "Fit Boxing 3 Your Personal Trainer (v1.03) (JAP) SuperXCI-Nicokoei.xci", + "https://1fichier.com/?won208ucqvolbxct73ch", + "" + ], + [ + "Fitness Boxing 2 Rhythm and Exercise V1.02 Incl. 5 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?rme1jrlcfq4utt39ob1s", + "" + ], + [ + "Five Nights at Freddys Sister Location EUR XCi -kaze-nico.xci", + "https://1fichier.com/?gpd9j6ldxqp975i69hsu", + "" + ], + [ + "Flying Soldiers Switch Eur XCi - kaze-nico.xci", + "https://1fichier.com/?y2em2ms7vawao7edbhoo", + "" + ], + [ + "FootGoal Tiki Takar Eur XCi - kaze-nico.xci", + "https://1fichier.com/?wh1o1x7s767nb7u52ldi", + "" + ], + [ + "Football Manager 2021 V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?m53i1sg7srb6pz4b6vlr", + "" + ], + [ + "Forager V4.1.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?isypa9a7lgjv0w2mdym7", + "" + ], + [ + "Foregone Eur XCi - kaze-nico.xci", + "https://1fichier.com/?rpy0vvffujkkhydfm6kf", + "" + ], + [ + "Fortress S v1.01.0012 All XCi - Nicokoei.xci", + "https://1fichier.com/?fksv0fmxc84s0r0wrqvj", + "" + ], + [ + "Fuga Melodies of Steel V1.0.4 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?m5fiqjbfxix66r0481ug", + "" + ], + [ + "Funko Fusion (v2.3.0) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?x35qllsysk1s11mxwd67", + "" + ], + [ + "Fury Unleashed v1.8.2 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?grg531ipxowon9x8m3ss", + "" + ], + [ + "G.I. Joe Operation Blackout V1.0.3 Incl. 3 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?t0u5gv1jk8drklrvuj25", + "" + ], + [ + "GOD EATER 3 V2.5.1 Incl. Dlc SuperXCi - kaze-nico.xci", + "https://1fichier.com/?u7npqsq895kbetn2zrs6", + "" + ], + [ + "GREEN The Life Algorithm V1.0.1.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?367y3lr5n8edust67zy3", + "" + ], + [ + "GRID Autosport V1.8.1.52405 Incl High Res Car Textures DLC Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?dd785oaevg4mq2qlwtdp", + "" + ], + [ + "GTA III The Definitive Edition V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?siwxk0br49m59qro6gd6", + "" + ], + [ + "GTA San Andreas The Definitive Edition V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?f6lotmwddx2y1jbvq9bg", + "" + ], + [ + "GTA Vice City The Definitive Edition V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?gb51j6jhv94uxwhcfc6b", + "" + ], + [ + "Gal Gun Returns Superxci 1.0.1[JP] - kaze-nico.xci", + "https://1fichier.com/?golfmpn84hojat5ehs2r", + "" + ], + [ + "Game Boy Advance – Nintendo Switch Online [1.9.0 - Nicokoei].nsp", + "https://1fichier.com/?0285mmozpjlbaxwendf7", + "" + ], + [ + "Garfield Lasagna Party Eur XCi - kaze-nico.xci", + "https://1fichier.com/?6hal2md562pjo1siz7ww", + "" + ], + [ + "Gear Club Unlimited 2 v1.7.2 Incl. 39 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0fkuykban8abt092f03m", + "" + ], + [ + "Gelly Break (Eur) kaze-nico.xci", + "https://1fichier.com/?vb78n79ktdf7mb69ez0s", + "" + ], + [ + "Genetic Disaster V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?wt7zax6y8qjjs3aa5fvz", + "" + ], + [ + "GetsuFumaDen Undying Moon Incl Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?fr3bd531427nmwx6kwx5", + "" + ], + [ + "Ghost of a Tale Eur XCi - kaze-nico.xci", + "https://1fichier.com/?w1q49bn0hzxrcy179ibl", + "" + ], + [ + "Ghostrunner V1.8 Incl. 4 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?07dr3qp6vfvoo9vt5g5n", + "" + ], + [ + "Ghosts n Goblins Resurrection V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?kdog7k37jwj1ntfq9tkk", + "" + ], + [ + "Gibbous A Cthulhu Adventure Eur XCi - kaze-nico.xci", + "https://1fichier.com/?608k9sw5k38lijl08pl4", + "" + ], + [ + "Giraffe and Annika V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?fp9y0hejs859pphctei9", + "" + ], + [ + "Girls Tank Battle V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ku5bumxapv50jhfialg0", + "" + ], + [ + "Gleamlight V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?9rrd0pguqh9pa012jtwd", + "" + ], + [ + "Glitchhikers The Spaces Between V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?u3jtl0xiszri4wtbi0bb", + "" + ], + [ + "Gods Will Fall V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?8tj51vmor9fqlyrrexbi", + "" + ], + [ + "Godstrike V2021.04.08 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?7gkm0tva9wvhqexx9toq", + "" + ], + [ + "Grand Theft Auto The Trilogy The Definitive Edition V1.0.5 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?tpjrvv545ar561aauon7", + "" + ], + [ + "Green Hell V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?1houthso9ebgnyulgsdo", + "" + ], + [ + "Grey Skies A War of the Worlds Story _eur.Us_Eng kaze-nico .xci", + "https://1fichier.com/?o7n4df719912mhyuuoke", + "" + ], + [ + "Grimshade Eur XCi - kaze-nico.xci", + "https://1fichier.com/?s6rb1t7cslleu5hpcshu", + "" + ], + [ + "Grounded (v1.0.8) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?s9nkhkzr4qsxszhvlf4i", + "" + ], + [ + "Grow Song of The Evertree V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?g5ns6k0fv69zfpkbq8wl", + "" + ], + [ + "Guayota NSW-VENOM (v1.0.0) (EU) - Nicokoei.nsp", + "https://1fichier.com/?h6396v2okjcp5cajt2w1", + "" + ], + [ + "HARVESTELLA v1.0.2 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?u0i8i9s9wq2ivjzapt28", + "" + ], + [ + "HOT WHEELS UNLEASHED 2 � Turbocharged � Deluxe Edition (v1.04 & 8 DLC) (US) Nicokoei.xci", + "https://1fichier.com/?g0yka7zgsedj7pkg9bem", + "" + ], + [ + "HOT WHEELS UNLEASHED V1.0.7 Incl 70 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?b5xdtcsvehqhziftfjzd", + "" + ], + [ + "HYPERCHARGE Unboxed V0.1.1398.127 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?bhv1lzv5x7lv5q4vsssy", + "" + ], + [ + "Hades V1.0.38180 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?izrlcxvjryjrnj4kiaxt", + "" + ], + [ + "Hardcore Mecha Incl. 6 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?baacrqtglit69shdi7yu", + "" + ], + [ + "Harvest Moon Un Monde a Cultiver Eur XCi - kaze-nico.xci", + "https://1fichier.com/?xxyna2efsc74ssh7vc9v", + "" + ], + [ + "Hatsune Miku Project DIVA Mega Mix V1.0.1 Inccl. Dlc USA SuperXCi - kaze-nico.xci", + "https://1fichier.com/?qp41fw6bl0o025wksuc7", + "" + ], + [ + "Hello Neighbor 2 Incl 3 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?fakj1y61hz1k8fgufb91", + "" + ], + [ + "Hellpoint V1.0.1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?gsyecilzr239okqlowoe", + "" + ], + [ + "Hentai vs Evil Eur XCi - kaze-nico.xci", + "https://1fichier.com/?squ0mgx7tf919o2zm36y", + "" + ], + [ + "Hike Eur XCi - kaze-nico.xci", + "https://1fichier.com/?c1gqz5ryl3lf5moqsw08", + "" + ], + [ + "Hindsight 2020 V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ynryulks4wqokn2i6z2k", + "" + ], + [ + "Hitchhiker A Mystery Game V1.0.6.1 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?i5szpg7xn1brw990rcnh", + "" + ], + [ + "Hitman Blood Money Reprisal v1.0.68328 Eur - Nicokoei.xci", + "https://1fichier.com/?4ndepnle8ntzjg6tza8b", + "" + ], + [ + "Hogwarts Legacy v1.0.1 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?85n0nqilz1k00qecx5qr", + "" + ], + [ + "Hollow 2 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9j4gkvtch905bbykq1ir", + "" + ], + [ + "Horizon Chase 2 v1.4.1 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?rx09htgeudwa0xxjkymq", + "" + ], + [ + "Horizon Chase Turbo V1.9.5 Incl. 2Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?talnclbd4dfrencuq6e1", + "" + ], + [ + "Horror Bundle Vol. 1 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?o46v4dk4nwylcythnxd6", + "" + ], + [ + "Hotline Miami Collection V2.00 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?6f7v82tq96lwrjpduz11", + "" + ], + [ + "Hotshot Racing V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?66qvxua80w1de3mhoovr", + "" + ], + [ + "House Flipper EUR XCi - kaze-nico.xci", + "https://1fichier.com/?xz9ons2kj2rhh60bcdt9", + "" + ], + [ + "Howling Village Echoes Eur XCi - kaze-nico.xci", + "https://1fichier.com/?eg763yslvpx7ybyymygc", + "" + ], + [ + "Huntdown Eur XCi - kaze-nico.xci", + "https://1fichier.com/?t4x308a9b3lqn7ulhw4h", + "" + ], + [ + "Hunting Simulator 2 V1.1.0 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?x41mv0hiyce1i2n5xu21", + "" + ], + [ + "HyperParasite Eur XCi - kaze-nico.xci", + "https://1fichier.com/?8vnuizrciuzxiz8zf6hm", + "" + ], + [ + "Hyrule Warriors Lere du Fleau V1.3.0 Incl. 3 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?8j41kox6dvw59vueyl6z", + "" + ], + [ + "I Am Dead V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vee6pync441wacr0xspr", + "" + ], + [ + "IMMORTALS FENYX RISING V1.3.2 Incl. All Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?yz7q9dvqi9oot5w4dm82", + "" + ], + [ + "Indie Darling Bundle Vol. 1 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9ia1dmn97m3eo4schvcd", + "" + ], + [ + "Indivisible Eur XCi - kaze-nico.xci", + "https://1fichier.com/?91qxl6expeypg827sfe4", + "" + ], + [ + "Inexistence Rebirth V1.0.1�Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?gsjykt05j38taag22s5z", + "" + ], + [ + "Infinity Strash DRAGON QUEST The Adventure of Dai v1.0.2 All SuperXCi - Nicokoei.xci", + "https://1fichier.com/?hee01t2wz4gff1vx2554", + "" + ], + [ + "Infliction Extended Cut V1.0.1 EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?26us3urcrljt95dnp9tf", + "" + ], + [ + "Inked A Tale of Love Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5svqqytecfs1c7gcywgk", + "" + ], + [ + "Inspecteur Gadget MAD Time Party v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?zmqo8e5vwxsalo5gij99", + "" + ], + [ + "Instant Sports Plus Eur XCi - kaze-nico.xci", + "https://1fichier.com/?z8scmkx2b3l7pmnoc45v", + "" + ], + [ + "Instant Sports Summer Games Eur XCi - kaze-nico.xci", + "https://1fichier.com/?oo38gxp76tndw71rivgu", + "" + ], + [ + "Invisible Inc. Nintendo Switch Edition EUR XCi - kaze-nico.xci", + "https://1fichier.com/?2y5d4bl6npzuddfb0cp3", + "" + ], + [ + "Ion Fury V1.0.6 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?xn6k4zspvw8gn0z58gz7", + "" + ], + [ + "Iron Meat (v1.04) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?v3bc22y1wqyz4fzm5kd5", + "" + ], + [ + "Island Flight Simulator Eur XCi - kaze-nico.xci", + "https://1fichier.com/?dbliz1vm30uizilisgz1", + "" + ], + [ + "JUMP FORCE Deluxe Edition SuperXci 1.03_2DLC US MultiFr - kaze-nico.xci", + "https://1fichier.com/?flu8emsh4in6n01mdls1", + "" + ], + [ + "JUST DANCE 2021 eur v324393.567785)_patched kaze-nico.xci", + "https://1fichier.com/?3u5cjgcu4i729sl7aqy4", + "" + ], + [ + "Jet Lancer Eur XCi - kaze-nico.xci", + "https://1fichier.com/?gypv9uvtywrruj0dbmxw", + "" + ], + [ + "John Wick Hex V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?3v42wzhotqnrobzox87p", + "" + ], + [ + "Journey To The Savage Planet V01.02 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?o1jogjpilvzgfd1mjqw4", + "" + ], + [ + "Journey of the Broken Circle Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9mg9irbklc5qkx30w7uj", + "" + ], + [ + "Jump Force Deluxe Edition V1.0.2 Incl. 11 Dlcs AS SuperXCi - kaze-nico.xci", + "https://1fichier.com/?g6jrssebwd7bns21fvka", + "" + ], + [ + "Jurassic World Evolution Complete Edition V1.0.4.54847 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?uc2xb3md61o3k5p4onum", + "" + ], + [ + "Just Dance 2021 V324393.567785 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vdia1mjx2lbsnhgwmd4i", + "" + ], + [ + "Just Shapes and Beats V1.5.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?bg5emnvtcuhen7w59gfb", + "" + ], + [ + "KAMEN RIDER Premium Sound Edition Jap MultiEng V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?80q0u1nchlomztlmfwhl", + "" + ], + [ + "KLAUS EUR XCi - kaze-nico.xci", + "https://1fichier.com/?8l3n1bkozr620nd0qvt2", + "" + ], + [ + "Kao the Kangaroo v1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c1p85sr2czcjtq024v9o", + "" + ], + [ + "Kholat Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ina0o6ff4d7mfulctell", + "" + ], + [ + "King of Seas V1.02 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?wl32o91kaeyxcja36v5d", + "" + ], + [ + "Kingdom Majestic Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?w1rhp2p4p6qssrxf0h4u", + "" + ], + [ + "Kingdoms of Amalur Re-Reckoning eur 1.0.2_patched - kaze-nico.xci", + "https://1fichier.com/?bpsgzsis6fc6eplm5lz0", + "" + ], + [ + "Kirby Fighters 2 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?wb2cmw7tvnsd81tvpkuw", + "" + ], + [ + "Kirby et le monde oublie Eur XCi - kaze-nico.xci", + "https://1fichier.com/?c9ako3j2gi5h0bkmbglv", + "" + ], + [ + "Kitaria Fables Eur XCi - kaze-nico.xci", + "https://1fichier.com/?en7ej0tiszbfl1xfrf9a", + "" + ], + [ + "Kukoos Lost Pets Eur XCi - Nicokoei.xci", + "https://1fichier.com/?6qwlq09pq147bf2km0sg", + "" + ], + [ + "L.O.L Surprise Movie Night V1.0.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?i2anbee06t67mstqwbpi", + "" + ], + [ + "LEGO 2K Drive v1.10 Incl 7 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?a8yr4xrg5tjozm8v6go2", + "" + ], + [ + "LEGO Marvel Super Heroes Eur XCi - kaze-nico.xci", + "https://1fichier.com/?6err1ckqezngd502n990", + "" + ], + [ + "LEGO Star Wars La Saga Skywalker V1.0.3 Incl. Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?qn7ve1s0cw10vpvc1ahn", + "" + ], + [ + "LIVE A LIVE Eur XCi - kaze-nico.xci", + "https://1fichier.com/?s9hjr8fa0euzu9qjp8wc", + "" + ], + [ + "LUNA the Shadow Dust Eur XCi - kaze-nico.xci", + "https://1fichier.com/?q46s3hlurmrgs1f2anz6", + "" + ], + [ + "La Pat’ Patrouille En mission.EUR - kaze-nico.xci", + "https://1fichier.com/?9rzmg20v8th907lbpebq", + "" + ], + [ + "Lair of the Clockwork God Eur XCi - kaze-nico.xci", + "https://1fichier.com/?l0bfdrv8tew13t9tge1n", + "" + ], + [ + "Lamentum V0.7.32 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?f045ouehr9ragmx1tmww", + "" + ], + [ + "Last 4 Alive Escape From Zombies Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9qtqlzg96hkf75fzxiir", + "" + ], + [ + "Le Donjon de Naheulbeuk V1.3.1005.39304 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?x55pw6a9ad60v2yqybuk", + "" + ], + [ + "Legacy of Kain Soul Reaver 1&2 Remastered (v1.0.1) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?sps3p4lk0pzika4elf1e", + "" + ], + [ + "Legend of Mana Eur XCi - kaze-nico.xci", + "https://1fichier.com/?3d6f9a3qqo3f4mbpy4ev", + "" + ], + [ + "Legends of Ethernal Eur XCi - kaze-nico.xci", + "https://1fichier.com/?7lnygz3tw1w7zdbyk97z", + "" + ], + [ + "Les Schtroumpfs Mission Malfeuille V1.0.19.1 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ogzp8nm4b3uexr8n4c9e", + "" + ], + [ + "Lets Sing 2024 v1.2 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?6e7p6ailpltfiqnkkdaa", + "" + ], + [ + "Lets Sing Queen V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?7yq4j5ea2cqexi1wtpcu", + "" + ], + [ + "Liberated Enhanced Edition Eur XCi - kaze-nico.xci", + "https://1fichier.com/?6c1zot5p3h1byngrg5hl", + "" + ], + [ + "Liberated V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ll09cm5ld8xv4af2xz3t", + "" + ], + [ + "Life is Strange Double Exposure (v1.0.1) (EU) SuperXCI- Nicokoei.xci", + "https://1fichier.com/?tcc2n5vs7403l2iw829n", + "" + ], + [ + "Life is Strange Remastered Collection V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?dre3agdaz5453c87qxiw", + "" + ], + [ + "Lifeless Planet Premiere Edition Eur XCi - kaze-nico.xci", + "https://1fichier.com/?cg5jod0h53wdlejlb3ob", + "" + ], + [ + "Little Big Workshop Eur XCi - kaze-nico.xci", + "https://1fichier.com/?63t6cpskwy2gjslavh8t", + "" + ], + [ + "Little Nightmares 2 V1.2 Incl. 2 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?mslvgv1kze5b422prc7z", + "" + ], + [ + "Lonely Mountains Downhill Eur XCi - kaze-nico.xci", + "https://1fichier.com/?lzx7wiq1hikq8vfd3twe", + "" + ], + [ + "Lost Horizon 2 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?7xw2ndzcob91e7xh01vg", + "" + ], + [ + "Lost Horizon Eur XCi - kaze-nico.xci", + "https://1fichier.com/?j2weef376g2w3ujs2zua", + "" + ], + [ + "Lost Lands Dark Overlord EUR XCi - kaze-nico.xci", + "https://1fichier.com/?tcb4xw921d7xaiebbaln", + "" + ], + [ + "Luigi's Mansion 2 HD - Nicokoei.xci", + "https://1fichier.com/?ko68r9eg6gnq1rlqnoen", + "" + ], + [ + "MARSUPILAMI Le Secret du Sarcophage V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?xj1haduddh4ims4rpo1w", + "" + ], + [ + "MARVEL vs. CAPCOM Fighting Collection Arcade Classics (v1.0.1) (JP) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?cs0sn1wf56zurejnc8kx", + "" + ], + [ + "METALLIC CHILD V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?p2pa96jqgz3jrcmjz1tk", + "" + ], + [ + "MFC_Midnight_Fight_Club_NSW-SUXXORS (v1.0) [US] - Nicokoei.nsp", + "https://1fichier.com/?w20r88oq4xgqoxhfr2h4", + "" + ], + [ + "MO Astray V1.3.1 Switch Eur XCi - kaze-nico.xci", + "https://1fichier.com/?71z25eyov8qm3x8zg5tv", + "" + ], + [ + "MONSTER HUNTER RISE V3.8.0 Incl. 122 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2uahj84ozccj2kmbrznf", + "" + ], + [ + "MONSTER HUNTER STORIES (v1.0.1) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?hpr460qyc391tnmuqxt1", + "" + ], + [ + "MX vs ATV All Out V1.0.2 Incl. 35 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?aufkvj53suidwsul5wi8", + "" + ], + [ + "MY HERO ONES JUSTICE 2 V1.0.3 Incl. 17 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?i4ejkyxir8zsb5fuw22r", + "" + ], + [ + "MY LITTLE PONY Aventure a la Baie de Portponey v1.0.1.014 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?olql0542mtjs5k1vk78t", + "" + ], + [ + "Mad Games Tycoon V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?or6ylykpqp9zbby6mwct", + "" + ], + [ + "Maid of Sker Eur XCi - kaze-nico.xci", + "https://1fichier.com/?zc94hgu50ytzbrrtaecv", + "" + ], + [ + "Maneater V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?bf5rxpsk6ct4oelxp519", + "" + ], + [ + "Mario Golf Super Rush V4.0.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?h3z6jm04fk4bpnkybb88", + "" + ], + [ + "Mario Kart 8 Deluxe (v3.0.3 & DLC) SuperXCI -Nicokoei.xci", + "https://1fichier.com/?292a2yfwha74s5b04jho", + "" + ], + [ + "Mario Kart Live Home Circuit V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?az0mz9ma5oeno8t4zeyg", + "" + ], + [ + "Mario Strikers Battle League Football v1.2.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2pdlw59bzyo86yuyaeqc", + "" + ], + [ + "Mario The Lapins Cretins Sparks of Hope V1.1.2028814 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?krw9sum808znxohz9lql", + "" + ], + [ + "Mario and The Lapins Cretins Sparks of Hope v1.1.2028814 Incl 2 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?8vt3j2jkqgzu3d8azn8j", + "" + ], + [ + "Mario plus Rabbids Sparks of Hope v1.6.2225577 Incl 7 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?gfyt7yev0itfyw1la1rm", + "" + ], + [ + "Mario vs. Donkey Kong v1.0 Eur - Nicokoei.xci", + "https://1fichier.com/?ag3zbzaey6ptcssj80tr", + "" + ], + [ + "Mars Horizon V1.0.2.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0ll5jvfvjj4jzp0dfquq", + "" + ], + [ + "Marvel Ultimate alliance 3 The Black Order V4.0.1 Incl. Dlc SuperXCi Eur - kaze-nico.xci", + "https://1fichier.com/?cr4zhoufuthip1wm04cx", + "" + ], + [ + "MathLand V01.02.00 Eur SuperXCI - kaze-nico.xci", + "https://1fichier.com/?8xmi72szua88w99d5hdr", + "" + ], + [ + "Max and the Book of Chaos Eur XCi - kaze-nico.xci", + "https://1fichier.com/?bf5wjt3m9jbce6bmhczx", + "" + ], + [ + "MazM Jekyll and Hyde Eur XCi - kaze-nico.xci", + "https://1fichier.com/?zn4yq0sli9vk1aaj79iz", + "" + ], + [ + "Mech Mechanic Simulator Eur XCi - kaze-nico.xci", + "https://1fichier.com/?8a49jyhbk6l2sgxozh79", + "" + ], + [ + "Mega Man Zero ZX Legacy Collection V1.0.4 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vnn8gmdq97uzozsxzd2e", + "" + ], + [ + "Megadimension Neptunia VII Incl. 19 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?3iqcsfasbs14a0jqn1ff", + "" + ], + [ + "Metamorphosis V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?m7zmu5jhabs9sa8axwd7", + "" + ], + [ + "Metroid Dread V2.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?9c4p19ec027q6naheikd", + "" + ], + [ + "Metroid Prime REMASTERED v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?3ghhmff17xnr6cg9xj83", + "" + ], + [ + "Miitopia V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?emhj4dg1ud6p2yox6hii", + "" + ], + [ + "Mika_and_the_Witchs_Mountain_NSW-VENOM V1.0 [EU] - Nicokoei.nsp", + "https://1fichier.com/?ju6621feriuxlob5gi9x", + "" + ], + [ + "Minecraft Dungeons & DLC V1.17.0.0 EU SuperXci - Nicokoei.xci", + "https://1fichier.com/?tsgdx0b6jgutk883ml1i", + "" + ], + [ + "Minecraft Legends Deluxe Edition v1.2.18075 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?97px0ujzpc1kvw4o37rd", + "" + ], + [ + "Minecraft V1.19.51 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?0e2013x0g7uesiofkg4k", + "" + ], + [ + "Mini Motor Racing X Eur XCi - kaze-nico.xci", + "https://1fichier.com/?eg3wefs0if3trytycmxr", + "" + ], + [ + "Ministry of Broadcast Eur XCi - kaze-nico.xci", + "https://1fichier.com/?pptnb334k5sg5z0q1xzd", + "" + ], + [ + "Minute of Islands V1.0.1�Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?flo0xnexudl60394ofxr", + "" + ], + [ + "Miraculous Rise of the Sphinx V1.01.06 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?bs7b5l5x4doe2ejr31wv", + "" + ], + [ + "Modern Combat Blackout V1.1.9 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?r1t4ixqz170nneeeldtx", + "" + ], + [ + "Moero Chronicle Hyper Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ly0ovoqkglcrcb199j27", + "" + ], + [ + "Mon Amie Peppa Pig Eur XCi - CLC.xci", + "https://1fichier.com/?0z2s15gssl2nm6cjs1yh", + "" + ], + [ + "Monster Crown V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?atyuru1fwdx7w3ug43ft", + "" + ], + [ + "Monster Energy Supercross The Official Videogame 3 V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?n2abe6ncw4owk6b30pgw", + "" + ], + [ + "Monster Hunter Generations Ultimate V1.4.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?lyjsa0nhq63na8kz0k18", + "" + ], + [ + "Monster Hunter Stories 2 Wings of Ruin Eur XCi - kaze-nico.xci", + "https://1fichier.com/?rr2buuepw71mqll141f3", + "" + ], + [ + "Monster Truck Championship V1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0855nicac5dryinj1b8q", + "" + ], + [ + "Moonlighter V1.0.0.8 EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?x2v0lqfafv1csnyr1h5q", + "" + ], + [ + "Mortal Kombat 1 (v1.11.0 & 9 DLC) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?l8uw2d3hsvd09cobf47z", + "" + ], + [ + "Mortal Shell Complete Edition Eur XCi - Nicokoei.xci", + "https://1fichier.com/?t7ez6fvjxf7hswtknl1f", + "" + ], + [ + "Moving Out eur 1.0.6+2DLC patched - kaze-nico.xci", + "https://1fichier.com/?cy4rwtna115zi29h5w0v", + "" + ], + [ + "Mozart Requiem Eur XCi - kaze-nico.xci", + "https://1fichier.com/?3aigkkfa4zc1ng2i0bqv", + "" + ], + [ + "My Little Dog Adventure Eur XCi - kaze-nico.xci", + "https://1fichier.com/?dbel4cx0ryl4d9l0xf9f", + "" + ], + [ + "My Universe Maitresse d ecole V1.02.02 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?rgztk3oqfdcobop97tb3", + "" + ], + [ + "My Universe My Baby Eur - kaze-nico.xci", + "https://1fichier.com/?vvbcvizop8tsqb3f1vr6", + "" + ], + [ + "My Universe Pet Clinic Cats and Dogs_Eur - kaze-nico.xci", + "https://1fichier.com/?k8wceascgzc9vjtjik9y", + "" + ], + [ + "MySims (v1.1.631226f) (US) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?zo50kwposr7qh96be7iz", + "" + ], + [ + "NARUTO SHIPPUDEN Ultimate Ninja STORM 4 ROAD TO BORUTO V1.2.0 Eur MultiFr SuperXCi - kaze-nico.xci", + "https://1fichier.com/?wf3pelymor1velkl6rwa", + "" + ], + [ + "NARUTO SHIPPUDEN Ultimate Ninja Storm Trilogy Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5xqaji0pxr8fh75dxfwr", + "" + ], + [ + "NBA 2K23 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?7kr2t4tld9nuj36fehx2", + "" + ], + [ + "NEOGEO POCKET COLOR SELECTION Vol.1_patched - kaze-nico.xci", + "https://1fichier.com/?hjln4315qm7h44bpubf2", + "" + ], + [ + "NES Nintendo Switch Online v6.3.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4ccu24hvlzk8j5uq0kv3", + "" + ], + [ + "NINJA GAIDEN 3 Razors Edge V1.0.1 Eur SuperXci - kaze-nico.xci", + "https://1fichier.com/?9zncqj0lzlk73hp2spzd", + "" + ], + [ + "NINJA GAIDEN Sigma 2 V1.0.1 Eur SuperXci - kaze-nico.xci", + "https://1fichier.com/?dpl3x54okubihxdtr21k", + "" + ], + [ + "NINJA GAIDEN Sigma V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?z5nm9g4yi5xhstpr56y4", + "" + ], + [ + "Namco Museum Arcade Pac Eur XCi - kaze-nico.xci", + "https://1fichier.com/?bacutb1j4v9w9cv7w7rf", + "" + ], + [ + "Namco Museum Eur XCi - kaze-nico .xci", + "https://1fichier.com/?paxrvoqen4getkiml4f1", + "" + ], + [ + "Namcot Collection JAP MultiEng XCi - kaze-nico.xci", + "https://1fichier.com/?76ddfa8z5ib5geb44fgc", + "" + ], + [ + "Need for Speed Hot Pursuit Remastered V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?7s0r9syp73wmdik0ub9m", + "" + ], + [ + "Neon Abyss V1.0.2 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?qphx9fhxeykww4rnrhee", + "" + ], + [ + "Nerf Legends Eur XCi - kaze-nico.xci", + "https://1fichier.com/?l2zn8fbu851kr7cs2v5t", + "" + ], + [ + "Nevaeh Eur XCi -kaze-nico.xci", + "https://1fichier.com/?dqn0abbfn5ckyyd7k5v6", + "" + ], + [ + "NeverAwake v1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?3gwwmhuet5hlthgdazng", + "" + ], + [ + "New Pokemon Snap V1.2.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zeugqf2nrfyucpxuax7q", + "" + ], + [ + "Nexomon Extinction V1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?uoal91opjctedj45sxtr", + "" + ], + [ + "Nexomon V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?wntz5pgdlk729dpf11cm", + "" + ], + [ + "Nickelodeon All Star Brawl V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vxdudxvx2vownllyim4q", + "" + ], + [ + "Nickelodeon Kart Racers 3 Slime Speedway V0.3.2.15569 Incl Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2ck36f0ucw1dtqf58mhd", + "" + ], + [ + "Night Call V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?dxdp11e1z1kn3f2l4n2g", + "" + ], + [ + "Ninja Gaiden Sigma 1 V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?9vsbfd4poervvpctlqtp", + "" + ], + [ + "Ninja Gaiden Sigma 2 V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?laehbhermufqi54ee849", + "" + ], + [ + "Nintendo 64 – Nintendo Switch Online MATURE 17+ - Nicokoei.xci", + "https://1fichier.com/?y4xbk65u2n3de5y71a8o", + "" + ], + [ + "Nintendo Entertainment System Nintendo Switch Online v5.0.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?tvbhxcsjaqkl9x51f5vv", + "" + ], + [ + "Nintendo Switch Sports v1.5.0 [US] - Nicokoei.xci", + "https://1fichier.com/?r99xp9gtio510fcreocq", + "" + ], + [ + "No More Heroes 1.1.1 superxci eur_patched - kaze-nico.xci", + "https://1fichier.com/?yh8ajcgmq3f50xxrzggm", + "" + ], + [ + "No More Heroes 2 Desperate Struggle [v1.1.1]patched -kaze-nico.xci", + "https://1fichier.com/?tjf6y7ja7bt10g5map6o", + "" + ], + [ + "No Straight Roads V1.0.1 EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?i6y8kqtm54jdfmq7t3s4", + "" + ], + [ + "Nordlicht V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?du0z1ipqmzh1hxjkjl60", + "" + ], + [ + "OLYMPIC GAMES TOKYO 2020 V1.0.7 JPN MultiEng SuperXCi - kaze-nico.xci", + "https://1fichier.com/?e4sb42gm0oms7r5k4jhn", + "" + ], + [ + "OMNO V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?oplxdw8dxcxelxpsjim2", + "" + ], + [ + "Oceanhorn 2 Knights of the Lost Realm Eur XCi - kaze-nico.xci", + "https://1fichier.com/?2cqzf6izbqoshh6nzvjw", + "" + ], + [ + "Octopath Traveler v1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?mr4e09phbn07hq63r9he", + "" + ], + [ + "Oddmar EUR XCi - kaze-nico.xci", + "https://1fichier.com/?8jnn5s0kyl0ri7igqgso", + "" + ], + [ + "Oddworld Munchs Oddysee V1.0.2 Incl. Pack Fr Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0zv4a1ebkk4ovfq20507", + "" + ], + [ + "Oddworld New n Tasty Eur XCi - kaze-nico.xci", + "https://1fichier.com/?rtc5wap3r3w2xkgzgdfa", + "" + ], + [ + "Okami HD Eur XCi - kaze-nico.xci", + "https://1fichier.com/?xun6yi6kke4i8vnhykxe", + "" + ], + [ + "OlliOlli World V1.2.0 Incl. 3 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vpth37v65pmbwxxipe1x", + "" + ], + [ + "Olympic Games Tokyo 2020 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?pdpordkfa48qrfqh7e3a", + "" + ], + [ + "Once Upon A Coma Neversong V2.0.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hahkqvuy4pel25fpx670", + "" + ], + [ + "One True Hero Eur XCi - kaze-nico.xci", + "https://1fichier.com/?cy02w63mzcb02lyjg1xk", + "" + ], + [ + "Ori and the Will of the Wisps V1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ryqfvtkv9u3xkufioedb", + "" + ], + [ + "Othercide Eur - kaze-nico.xci", + "https://1fichier.com/?aw2oa83i85e6atzjczwk", + "" + ], + [ + "Out of Line V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?we5sl1cixqvu2e3k6yn9", + "" + ], + [ + "Outbreak Epidemic Eur XCi - kaze-nico.xci", + "https://1fichier.com/?b25a1wzgcxhfz2u2cndi", + "" + ], + [ + "Outer Wilds v1.1.14.841 Dlc Eur - Nicokoei.xci", + "https://1fichier.com/?8nm7apx8s7zyn7j4gs7b", + "" + ], + [ + "Overcooked All You Can Eat V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?yryvj7ojuma61omizx3h", + "" + ], + [ + "Override 2 Super Mech League V1.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?e7t4hbix9nsya47ogxa2", + "" + ], + [ + "PACMAN 99 V1.0.1 Incl. 21 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?dhzzk2mkgkhrngl62041", + "" + ], + [ + "PGA TOUR 2K21 V1.4.0.0 Incl. 2DLC Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?h71hqt1yf761sxxhncva", + "" + ], + [ + "PROJECT KNIGHT Eur XCi - kaze-nico.xci", + "https://1fichier.com/?lgvaqzn9qvqimvo91uyh", + "" + ], + [ + "Panzer Dragoon Remake V1.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?e2h9xgyu8fckiywqq2qj", + "" + ], + [ + "Panzer Paladin Eur XCi - kaze-nico.xci", + "https://1fichier.com/?11f520b13zt8yl7cb9ju", + "" + ], + [ + "Paradise Killer V1.0.8 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?6cw871z6ynqx6dskbrgz", + "" + ], + [ + "Party Hard 2 V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?270tpxwo9jmaifxnt5tb", + "" + ], + [ + "Pat Patrouille La Super Patrouille Sauve la Grande Vallee Eur XCi - kaze-nico.xci", + "https://1fichier.com/?nh8t6zkakhx2diq7s9hp", + "" + ], + [ + "Paw Patrol Adventure City V1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c4sbvo38udxzmi0hrzu6", + "" + ], + [ + "Paw Patrol Grand Prix Eur XCi kaze-nico.xci", + "https://1fichier.com/?na2hf1y43z3sxy57f1ki", + "" + ], + [ + "Peaky Blinders Mastermind V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ulgpm76r35z54cet6w0t", + "" + ], + [ + "Persona 3 Portable Eur XCi - kaze-nico.xci", + "https://1fichier.com/?x7fcho3vnb318tpjlpz0", + "" + ], + [ + "Persona 4 Golden Eur XCi - kaze-nico.xci", + "https://1fichier.com/?029mfazmat0sfqp3n3jw", + "" + ], + [ + "Persona 5 Royal Eur XCi - kaze-nico.xci", + "https://1fichier.com/?fs3xfv4i52fnxkzbgkxr", + "" + ], + [ + "Persona 5 Scramble The Phantom Strikers V1.0.1 Incl. 4 Dlcs JPN SuperXCi - kaze-nico.xci", + "https://1fichier.com/?cwgqxj2zooss2uwagek9", + "" + ], + [ + "Persona 5 Strikers Incl. 2Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hwf5o6x8h7nf34qsy204", + "" + ], + [ + "Persona 5 Tactica (v1.02 & 3 DLC) (US) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?1ef6l6ksmxfu0s5x6vyo", + "" + ], + [ + "Pets No More Eur XCi - kaze-nico.xci", + "https://1fichier.com/?8end6amjwwf0lx65dry4", + "" + ], + [ + "Phantom Breaker Omnia V1.03.3544 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?p4o6ojo2d50gcmcdm70p", + "" + ], + [ + "Pinball FX3 V1.0.10 Incl. All Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?u71v0gqimswxilg1irba", + "" + ], + [ + "Pinstripe Jap Multifr XCi - kaze-nico.xci", + "https://1fichier.com/?5695d2rypg72uqu3osz7", + "" + ], + [ + "Pixel Paint Incl 5 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?j3oquozz8r9xpwn2j7ha", + "" + ], + [ + "Plague Inc Evolved V1.18.4.2 Incl. Dlc EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?xoftjbpm53oz8z9myspc", + "" + ], + [ + "Plants vs. Zombies La Bataille de Neighborville CE V1.0.2 Eur SuperXCi_patched - kaze-nico.xci", + "https://1fichier.com/?on2ielt8xghrxra94tby", + "" + ], + [ + "Pokemon Brilliant Diamond Eur - kaze-nico.xci", + "https://1fichier.com/?fdhx1tybcrfq51vcciwz", + "" + ], + [ + "Pokemon Cafe Mix V1.40.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?etrj8em9nejr9j9bgwep", + "" + ], + [ + "Pokemon Diamant Etincelant V1.3.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2gbo8f73979d61qr2wb1", + "" + ], + [ + "Pokemon Legends Arceus V1.01 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?w77isk768am5q6q6zk6f", + "" + ], + [ + "Pokemon Perle Scintillante V1.3.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?bl9b4pb28wowpy3cyt51", + "" + ], + [ + "Pokemon Scarlet (v3.01 & DLC) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?vx0qmnjxlbkogovj9jom", + "" + ], + [ + "Pokemon Scarlet and Violet V1.0.1 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?xdecrbu4l49e1ng8pxsd", + "" + ], + [ + "Pokemon Sword V1.3.2 Incl. 2 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?a97nu3epzhkwbbf3bgc5", + "" + ], + [ + "Pokemon UNITE Eur XCi - kaze-nico.xci", + "https://1fichier.com/?mc6rdfmifnloctq1vo4b", + "" + ], + [ + "Pokemon Violet (v3.01 & DLC) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?wctm5a1nk6djpxq861od", + "" + ], + [ + "Poppy Playtime Chapter 3 (v1.0.0.2) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?rn1tz0ymlfgzromim8o7", + "" + ], + [ + "Port Royale 4 V1.0.1 Incl Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4lor6sqrk8c5yktjd3wv", + "" + ], + [ + "Postal REDUX Eur XCi - kaze-nico.xci", + "https://1fichier.com/?z6dc63u9yxtp4cdfahww", + "" + ], + [ + "Potata Fairy Flower Eur XCi - kaze-nico.xci", + "https://1fichier.com/?f0e2g7xlhk16etekzumi", + "" + ], + [ + "Power Rangers Battle for the Grid V2.4.0 Incl. 15 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?acwlyxmt2qary0vgz28y", + "" + ], + [ + "Prince of Persia The Lost Crown (v1.02 & DLC) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?n27czia9h8phq88m69j9", + "" + ], + [ + "Princess Peach Showtime v1.0 EUR - Nicokoei.xci", + "https://1fichier.com/?fxci339i03xjxhkvypje", + "" + ], + [ + "Prinny 2 Dawn of Operation Panties Dood V1.0.2 Eur SuperXCi- kaze-nico.xci", + "https://1fichier.com/?ldj0ngq4kvvx13d0jced", + "" + ], + [ + "Prinny Can I Really Be the Hero V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hia465cx29b9506nf6et", + "" + ], + [ + "Prison Architect v1.0.5 Incl. 2 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?pmn90jepyq70cmn3ymf9", + "" + ], + [ + "Professor Rubiks Brain Fitness Eur XCi - kaze-nico.xci", + "https://1fichier.com/?raforgol8kldbqcs8f91", + "" + ], + [ + "Project Warlock V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?p6d85910sx268yd0le3r", + "" + ], + [ + "Promenade v1.0.1 Eur Superxci - Nicokoei.xci", + "https://1fichier.com/?eifthl7ce6xzkxeauvse", + "" + ], + [ + "Pumpkin Jack V1.3.8 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?y0f0oq3ddw9x3hjj09sj", + "" + ], + [ + "Pups and Purrs Animal Hospital Eur XCi - kaze-nico.xci", + "https://1fichier.com/?4fgsuff8jvfqtvxdp7tp", + "" + ], + [ + "Pure Chase 80s Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9o4kkef5pog22ub84whb", + "" + ], + [ + "Puyo Puyo Tetris 2 SuperXci 1.2.1_DLC_US_patched kaze-nico.xci", + "https://1fichier.com/?k68c049tkksshpi7mqp8", + "" + ], + [ + "Qui Veut Gagner des Millions V1.1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?oq7afz6rnbwn2hsqb8rp", + "" + ], + [ + "R-Type Final 2 V1.4.2 Incl Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?jg0gk9upnm8b5wesbvk2", + "" + ], + [ + "REYNATIS (v1.04) & 14 DLC) (US) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?g5tveaz1uendnveo8bwl", + "" + ], + [ + "REZ PLZ V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?gf7n64279qez66xzkn87", + "" + ], + [ + "Railway Empire Incl. 3 Dlcs EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?bpnl1y8ans5ejmnmmnut", + "" + ], + [ + "Rainbow Billy The Curse of the Leviathan V0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?anwqtmx3cfzl9v69xtm0", + "" + ], + [ + "Raji An Ancient Epic V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?3lrytthtw0zr6yjjuw2l", + "" + ], + [ + "Real Boxing 2 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?mspoun3yf4sf1u0bx3oc", + "" + ], + [ + "Real Farm Premium Edition V1.1.1027 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c1pbxhxqlzr6mxjkf2em", + "" + ], + [ + "Rebel Galaxy Outlaw Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ou8h6owuu7n4xdcz5wvr", + "" + ], + [ + "Red Colony Jap XCi - kaze-nico.xci", + "https://1fichier.com/?103cye1c9qagqnhnmye2", + "" + ], + [ + "Red Wings Aces of the Sky Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9n4n6bpu4bw829nra111", + "" + ], + [ + "Red Wings American Aces Eur v1.1.4 Incl. 2 Dlcs SuperXCi - Nicokoei.xci", + "https://1fichier.com/?o5932ftc4vl6948axkeo", + "" + ], + [ + "Redout 2 V1.0.5 Incl Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?u7mey36pb30rf7ris3b4", + "" + ], + [ + "Redout Space Assault Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5kv2rt1u5jw13gedbspf", + "" + ], + [ + "Remothered Broken Porcelain V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?1cfd5ahdng6quodh7qiz", + "" + ], + [ + "Remothered tormented fathers V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?yd3antwfngxukzliq7hy", + "" + ], + [ + "Renzo Racer V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zhqd15s357j91y9q4a5t", + "" + ], + [ + "Retro Game Pack Eur XCi - kaze-nico.xci", + "https://1fichier.com/?lkr9bnsqn0ck1s9uxssw", + "" + ], + [ + "Retro Machina V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?rhzezg3q8k0gd8veivt6", + "" + ], + [ + "Return to Monkey Island v1.1.1 Incl Dlc Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?5jhh64bsq5yxqnw7es7l", + "" + ], + [ + "RiMS Racing Jap MultiFr XCi - kaze-nico.xci", + "https://1fichier.com/?j9g3wrcijp9uccu14sr3", + "" + ], + [ + "Riptide GP Renegade V1.0.1 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?sq1pii65y5z8s6v05vfk", + "" + ], + [ + "Rise Race The Future V1.5 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?b4dhpb8q691flbxwteaf", + "" + ], + [ + "Risk of Rain 2 V1.0.8 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0enzxcdpgh3ak5482hzj", + "" + ], + [ + "Risk of Rain V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2coakyls5k0h2q54j0t8", + "" + ], + [ + "Risk v0 (0100E8300A67A000) kaze-nico.xci", + "https://1fichier.com/?jquw9ziqh84dbnm81lwm", + "" + ], + [ + "River city girls V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?qziu3l22uivckpgs3jjt", + "" + ], + [ + "Road 96 V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?mpelr4qwwwiioopxda6v", + "" + ], + [ + "Road To Guangdong Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ycy9yx62ggkz6zuawxms", + "" + ], + [ + "Roah Eur XCi - kaze-nico.xci", + "https://1fichier.com/?fzudcsfucypvdjlhup25", + "" + ], + [ + "Rocket League SuperXci eur 1.4.3_24DLC patched - kaze-nico.xci", + "https://1fichier.com/?74hhnmm7jy0zgc2hu7dk", + "" + ], + [ + "Rocket League Ultimate Edition V1.6.1 Incl. All Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?psny35lj6dyukfvq3w1p", + "" + ], + [ + "Roki V3.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?48g3s4rxa4vf9lrdipum", + "" + ], + [ + "RollerCoaster Tycoon 3 V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?b47bt3wdvikfl90w1vpo", + "" + ], + [ + "Romancing SaGa 2 Revenge of the Seven (v1.0.1) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?wf2gif8qlk1tn0m2ilmc", + "" + ], + [ + "Root Double Before Crime After Days Xtend Edition V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?5lxd2ovhfl4sryv0ga6o", + "" + ], + [ + "Rugby Challenge 4 V1.01 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0dxp7shagaddx4gi45h6", + "" + ], + [ + "Ruined King A League of Legends Story V1.6 Incl. 4 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hltk7uqqtn2wl95bb4mc", + "" + ], + [ + "Rune Factory 5 V1.0.1 Incl. 10 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?61aci9rrv8hijqae4pvg", + "" + ], + [ + "Rustler Eur XCi - kaze-nico.xci", + "https://1fichier.com/?7ou2cu5ki8a2jkb3fkhn", + "" + ], + [ + "SAMURAI MAIDEN v1.43 Incl 18 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?x2i7asaom1d24ey01ozn", + "" + ], + [ + "SAMURAI SHODOWN SuperXci US 2.11+8DLC_patched - kaze-nico.xci", + "https://1fichier.com/?zg99y1pvwzvl9tmtvr5n", + "" + ], + [ + "SAMURAI WARRIORS 5 Deluxe Edition V1.01 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ufbpy725gnu7u8q9mae3", + "" + ], + [ + "SEGA Genesis Mega Drive NSO V2.4.0 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?stpvah65f1y3k7f0o1em", + "" + ], + [ + "SEGA Genesis Mega Drive Nintendo Switch Online V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2yzj5l1uyabl373o01p0", + "" + ], + [ + "SHIN MEGAMI TENSEI V Vengeance (v1.01 & 7 DLC) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?e6316zw1i20qjvu7b7kb", + "" + ], + [ + "SMURFS KART v1.01.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?6p5ruvczl077djkhmpwh", + "" + ], + [ + "SNES Nintendo Switch Online V3.4.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ike2ibs0fodns2brgnsa", + "" + ], + [ + "SNK VS. CAPCOM THE MATCH OF THE MILLENNIUM v1.0.1 patched - kaze-nico.xci", + "https://1fichier.com/?nn2utfmnvzj4z3wk6vkt", + "" + ], + [ + "SNK_VS_CAPCOM_SVC_CHAOS_NSW-VENOM V1.0 [EU] - Nicokoei.nsp", + "https://1fichier.com/?pyio05jlr3p1ud77q7sh", + "" + ], + [ + "SONIC SUPERSTARS Digital Deluxe Edition v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?kopzpfxhojfnov2reoaa", + "" + ], + [ + "SSBU v13.0.2 Incl all Dlcs Eur - Nufan.nsp", + "https://1fichier.com/?oyxa3ihzhcw4rfnxqjno", + "" + ], + [ + "STAR WARS Bounty Hunter V1.0.1 EU SuperXci - Nicokoei.xci", + "https://1fichier.com/?i66c0aivmh603wr71gqm", + "" + ], + [ + "STAR WARS Episode I Racer EUR XCi - kaze-nico.xci", + "https://1fichier.com/?7asex84o2qfwmgq8xawl", + "" + ], + [ + "STAR WARS Jedi Knight Jedi Academy V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?54b2pgo787hv7pnkliji", + "" + ], + [ + "STAR WARS Republic Commando V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?jpnj5xlxxh6gi41r1ck2", + "" + ], + [ + "STORY OF SEASONS Pioneers of Olive Town V 1.1.0 Incl. 18 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?x0oo6jpbb1bc4yoazy98", + "" + ], + [ + "SaGa Frontier Remastered V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?yro0l1zedtg0jyu4jpp5", + "" + ], + [ + "Saints Row IV Re-Elected V1.5.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?oyrje025cbtlk4mlkso8", + "" + ], + [ + "Sakuna Of Rice and Ruin V1.0.6 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?iq6ahj0tmjra3vds21qk", + "" + ], + [ + "Sam and Max Save The World Remastered Eur XCi - kaze-nico.xci", + "https://1fichier.com/?jybigv6fe3debv5gc4q8", + "" + ], + [ + "Samurai Shodown NeoGeo Collection V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?375w86tas2ut5f7olu5c", + "" + ], + [ + "Save Your Nuts Eur XCi - kaze-nico.xci", + "https://1fichier.com/?7c7wssom3n2uynvpnxv4", + "" + ], + [ + "Scott Pilgrim vs The World The Game (eur) - kaze-nico.xci", + "https://1fichier.com/?gxgpeklmw1mplwmvb2co", + "" + ], + [ + "Sea of Solitude The Directors Cut 1.1.0_patched - kaze-nico.xci", + "https://1fichier.com/?dedh6bzwfk3w4ma4h4t0", + "" + ], + [ + "Secret Files 3 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?rqxcdlshxg6mli7rg6wy", + "" + ], + [ + "Secret Neighbor V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?o0q78jicec5geols1vxe", + "" + ], + [ + "Seers Isle V2.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?o2rxbdzx53cmmw38oi3o", + "" + ], + [ + "Sentinels Of Freedom SuperXci 1.1.0e eur - kaze-nico.xci", + "https://1fichier.com/?w5asbmh7i1wa7fqzjkgs", + "" + ], + [ + "Serious Sam Collection V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?gxrza751et6nyqgthq1z", + "" + ], + [ + "Seven Knights Time Wanderer V1.4 Incl 7 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?kc0ri7sb8cvujnnz0gzg", + "" + ], + [ + "Shadow Man Remastered V1.4.2983b Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4edv5rw3shzyej8bdufm", + "" + ], + [ + "Shantae Riskys Revenge - Directors Cut Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ki85zwsnlro90cbhsn3k", + "" + ], + [ + "Shantae and the Seven Sirens Eur XCi - kaze-nico.xci", + "https://1fichier.com/?qdqzjlagq8l4h17x397s", + "" + ], + [ + "She Sees Red Interactive Movie V1.0.1 Eur Super - kaze-nico.xci", + "https://1fichier.com/?199068ssrekmeg309eqg", + "" + ], + [ + "Sherlock Holmes The Devils Daughter Incl. 3 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?r6cnzfzj0aakcfohclyg", + "" + ], + [ + "Shin Megami Tensei III V1.0.2 Incl. 4 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ey1tla3iko7rsp1pxi0k", + "" + ], + [ + "Shin Megami Tensei V Eur XCi - kaze-nico.xci", + "https://1fichier.com/?a2oiz1mufzc984r4olum", + "" + ], + [ + "Shred 2 ft Sam Pilgrim V1.6.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?m2eqcmxlhf6mxwm7db8o", + "" + ], + [ + "Sid Meier's Civilization VII (v1.02 & 9 DLC) (EU) SuperXCI-Nicokoei.xci", + "https://1fichier.com/?dii1b4qh801co6ldozl7", + "" + ], + [ + "Sid Meiers Civilization VI V1.2.9 Incl. all Dlcs SuperXCi - kaze-nico.xci", + "https://1fichier.com/?5x3irhaimsho5ooxzth9", + "" + ], + [ + "Skul The Hero Slayer V1.3.2.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?7p32v9ad0q5sfah5z3r0", + "" + ], + [ + "Skull Island Rise of Kong Colossal Edition v1.1.0 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?u8882qnqtoyigwi3y4k7", + "" + ], + [ + "Skully V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?8277hsrtytgfknqj6zjg", + "" + ], + [ + "Sky Children of the Light V0.14.0.171755 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?dokhrq8cvj2z5bpad6lg", + "" + ], + [ + "Sniper Elite 4 V1.0.2 Incl. 13 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?lmle9ohgdc9ckpu25uqy", + "" + ], + [ + "Snooker 19 V1.0.8 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zmxrn8gdeaep3hd46jyy", + "" + ], + [ + "Soccer Pinball Eur XCi - kaze-nico.xci", + "https://1fichier.com/?x39xlr0ukhd4ne4vg68c", + "" + ], + [ + "Sonic Colors Ultimate V1.0.3 Incl 3 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?406ab3vh9gtnfje1f7fh", + "" + ], + [ + "Sonic Frontiers (v1.4.1) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?2su3p504syapp8x47m67", + "" + ], + [ + "Sonic Origins V1.1.0 Incl 3 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0lsn67s6wgm0rb7t3mzx", + "" + ], + [ + "Space Invaders Forever Eur XCi - kaze-nico.xci", + "https://1fichier.com/?4cp3w3ouv028mbzywumj", + "" + ], + [ + "Space Tail Every Journey Leads Home Eur XCi - kaze-nico.xci", + "https://1fichier.com/?dl55f5t8d6vcbg83hpxq", + "" + ], + [ + "Speed 3 Grand Prix Eur XCi - kaze-nico.xci", + "https://1fichier.com/?cgva396w52luyal70adm", + "" + ], + [ + "Speedway Bundle Stock and Truck _eur 1.0.1_patched - kaze-nico.xci", + "https://1fichier.com/?ifck8jojp5sbmr0wzng2", + "" + ], + [ + "Spirit of the North V1.3.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?fjtpj3t0w5i63wkju72x", + "" + ], + [ + "Spiritfarer V1.6 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hxh1lp8pm3t7nq9a4dsw", + "" + ], + [ + "Splatoon 2 EUR V5.3.1 All Dlcs SuperXCi - kaze-nico.xci", + "https://1fichier.com/?fw92at2jxl2jd7ot2ars", + "" + ], + [ + "Splatoon 3 (v9.2.0 & 3 DLC) (EU) SuperXCI-Nicokoei.xci", + "https://1fichier.com/?zjrbi0w0osh2l213vxqu", + "" + ], + [ + "SpongeBob SquarePants Battle for Bikini Bottom - Eur Rehydrated SuperXci 1.0.5_patched - kaze-nico.xci", + "https://1fichier.com/?06vuefdlo3ho7ox2wrqu", + "" + ], + [ + "SpongeBob SquarePants The Cosmic Shake v1.0.3 Incl Dlc Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?rc55gamoybn4ubhblzdy", + "" + ], + [ + "Star Renegades V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?1uyd1g8hr4c0z2n6208e", + "" + ], + [ + "Star Trek Legends (v1.1.1) (EU) SuperXCI-Nicokoei.xci", + "https://1fichier.com/?g3d8tcpxyrcn2449unqq", + "" + ], + [ + "Starlink Battle for Atlas V1.0.5 Incl. 22DLC Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?jmyh94p6ciw4fagq6814", + "" + ], + [ + "Steel Assault Eur XCi - kaze-nico.xci", + "https://1fichier.com/?qkjnbvqhtwh3epjj0f4x", + "" + ], + [ + "Story of Seasons Mineral Town V1.0.5 Incl. 5 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0ei0c8njqone31f1l2ci", + "" + ], + [ + "Story of Seasons V1.0.1 Incl. 5 Dlcs MultiFr Us SuperXCi - kaze-nico.xci", + "https://1fichier.com/?99ayewvwpfk32onboqjr", + "" + ], + [ + "Stranded Sails Explorers of the Cursed Islands V1.0.5 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0k2ttlslshs5otmfgqxi", + "" + ], + [ + "Stray (v1.6.0) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?56i1m5toi9rg4srmrp7p", + "" + ], + [ + "Street Power Soccer V1.0.1 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?0en2wc3o7jtel4serhcc", + "" + ], + [ + "Streets of Rage 4 V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zz2jva4dmqjorx6fcnoe", + "" + ], + [ + "Struggling Eur XCi - kaze-nico.xci", + "https://1fichier.com/?wldoxpwt0kzqgis1uq36", + "" + ], + [ + "Subnautica Below Zero V1.12.47243 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?jpxyk1ngxi54wyei27w6", + "" + ], + [ + "Subnautica V1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?a0ceusumm4ys7gtbwlvf", + "" + ], + [ + "Sudoky Eur XCi - kaze-nico.xci", + "https://1fichier.com/?vqjulyyx5tcpeofxnzks", + "" + ], + [ + "Suikoden I&II HD Remaster Gate Rune and Dunan Unification Wars (v1.02 & DLC) (EU) SuperXCI-Nicokoei.xci", + "https://1fichier.com/?3ioey0xtx6jldsl6zl7y", + "" + ], + [ + "Summer in Mara EUR XCi - kaze-nico.xci", + "https://1fichier.com/?buzqk0b22cjmhx4c96sq", + "" + ], + [ + "Super Bomberman R 2 v1.2.0 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?ex54glzowdstgznis6cj", + "" + ], + [ + "Super Bomberman R Online eu SuperXci 1.2.1 kaze-nico.xci", + "https://1fichier.com/?wi90fdcz99ab61pw8ttg", + "" + ], + [ + "Super Mario 3D All-Stars V1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?5z025jlr6wq82kryzwdo", + "" + ], + [ + "Super Mario 3D World and Bowsers Fury V1.1.0 Eur SuperXCi patched - kaze-nico.xci", + "https://1fichier.com/?ba3rk4458dgpg66a6kxx", + "" + ], + [ + "Super Mario Bros Wonder v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?h9absl0zb8w5y65zot0m", + "" + ], + [ + "Super Mario Bros. 35 V1.0.1 Eur SuperXCi - CLC.xci", + "https://1fichier.com/?u4cok1tsgw93hdgxhxnf", + "" + ], + [ + "Super Mario Party Jamboree (v1.1.0) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?fchzf8kkz85c9jj3g9ui", + "" + ], + [ + "Super Mario RPG v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?iarkyf3rl3izn6yspfs2", + "" + ], + [ + "Super Meat Boy V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?y5i2r5995m69t2m3jig6", + "" + ], + [ + "Super Monkey Ball Banana Rumble V1.0.1 EU SuperXci - Nicokoei.xci", + "https://1fichier.com/?qa1snjvhhmrmgnqn27xw", + "" + ], + [ + "Super Nintendo Entertainment System Nintendo Switch Online V2.0.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?9g7b4xks7zpz1i3hrrdk", + "" + ], + [ + "Super Seducer Eur XCi - kaze-nico.xci", + "https://1fichier.com/?nu8qohdskm4hhyfbalhn", + "" + ], + [ + "Super Woden GP Eur XCi - kaze-nico.xci", + "https://1fichier.com/?973oqadmulhkvhghhnff", + "" + ], + [ + "Supraland V1.0.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?bc3sofqa88uwt9jt4bxc", + "" + ], + [ + "Survive On Raft Eur XCi - kaze-nico.xci", + "https://1fichier.com/?sipzlbfcnlqlx7op2igj", + "" + ], + [ + "THE HOUSE OF THE DEAD Remake v1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?7s48o6z5vlu1389rx8s9", + "" + ], + [ + "TMNT Shredders Revenge v1.0.5 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?sonfutgewj2mxtxszkq7", + "" + ], + [ + "TRIANGLE STRATEGY V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?9o5m4sqw8sainu0rcet6", + "" + ], + [ + "TY le tigre de Tasmanie 2 Operation sauvetage HD Eur XCi - kaze-nico.xci", + "https://1fichier.com/?yhbhv19oiy8pjynzijdr", + "" + ], + [ + "Tacticool Champs Eur XCi - kaze-nico.xci", + "https://1fichier.com/?zpvl1ovdlym6iuf5uiv7", + "" + ], + [ + "Taiko no Tatsujin Drum n Fun V1.4.7 Incl. 206 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?rhwtjjyj2jt8zvsniuda", + "" + ], + [ + "Tails Of Iron V 1.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?kl8gpt1gmvwsackrjbzu", + "" + ], + [ + "Tales from the Borderlands Eur XCi - kaze-nico.xci", + "https://1fichier.com/?c30mqpfexge6h4r5gk1l", + "" + ], + [ + "Taxi Chaos Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5oqpwmz1hlhxlcypkuyn", + "" + ], + [ + "Teenage Mutant Ninja Turtles Mutants Unleashed (v1.01 & DLC) (EU) SuperXCI ) Nicokoei.xci", + "https://1fichier.com/?40n5aqirhqh22henhzqe", + "" + ], + [ + "Teenage Mutant Ninja Turtles Shredders Revenge V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0svuc2xlbqpdnmy618u3", + "" + ], + [ + "Tennis World Tour 2 V1.2.0 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4hmcsmt4516p53frzez6", + "" + ], + [ + "Tennis World Tour EUR V1.17.0 All Dlcs SuperXCi - kaze-nico.xci", + "https://1fichier.com/?33zynxb7da4wmdebtcsc", + "" + ], + [ + "Tetris 99 V2.2.0 Incl 2 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?frrtpmhw9aiu5o3j91r5", + "" + ], + [ + "Tetris Effect Connected V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?mzxsj85yr4yq9gufuhdt", + "" + ], + [ + "Thank Goodness You're Here! V1.4.1 EU SuperXci - Nicokoei.xci", + "https://1fichier.com/?etlb6i6mz4ygrysiv2x4", + "" + ], + [ + "The Artful Escape V1.01 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?x3kz37ac5kl9c0maz7th", + "" + ], + [ + "The Bards Tale ARPG Remastered and Resnarkled EUR XCi - kaze-nico.xci", + "https://1fichier.com/?sozrd9vl5tazwc3nug1j", + "" + ], + [ + "The Coma 2 Vicious Sisters Eur XCi -kaze-nico.xci", + "https://1fichier.com/?i9s3089qww3v5eme62oq", + "" + ], + [ + "The Coma Recut Deluxe Edition V1.0.1 Eur Super XCi - kaze-nico.xci", + "https://1fichier.com/?0wuqhfk09m0d7dw2csdb", + "" + ], + [ + "The Companion v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?u4k59x0t70a6q13hklax", + "" + ], + [ + "The Copper Canyon Dixie Dash V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?3foqvq4sawwuoulmkxbe", + "" + ], + [ + "The Dark Eye Chains of Satinav _eur - kaze-nico.xci", + "https://1fichier.com/?vmg9n1afy5ik76hl9b65", + "" + ], + [ + "The DioField Chronicle Eur XCi - kaze-nico.xci", + "https://1fichier.com/?byg68cp7kolwnrwbrfc3", + "" + ], + [ + "The Elder Scrolls V Skyrim V1.1.14.534571 Incl Pack Fr Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?6d98ushzj1jms8jynjro", + "" + ], + [ + "The Four Kings Casino and Slots Eur XCi - kaze-nico.xci", + "https://1fichier.com/?xxawdq34ntflni5faqjy", + "" + ], + [ + "The Hong Kong Massacre V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?g9isn9bd3do9yezt1tek", + "" + ], + [ + "The Jackbox Party Pack 7 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?68nh2h2ot707xuwwjdj1", + "" + ], + [ + "The Kids We Were Eur XCi - kaze-nico.xci", + "https://1fichier.com/?z0nk545a6izfp9el3yie", + "" + ], + [ + "The Last Campfire V1.0.6 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?321dyjxcplfbc2lx7ofy", + "" + ], + [ + "The Last Dragon Slayer v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?j8153y709ide9h93huls", + "" + ], + [ + "The Legend of Heroes Trails of Cold Steel III V1.0.1 EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?d0vvv7nu4wq192ajdrw0", + "" + ], + [ + "The Legend of Zelda Echoes of Wisdom Superxci 1.0.1 [US] - Nicokoei.xci", + "https://1fichier.com/?3tk0yo6co92yrq5jcpfa", + "" + ], + [ + "The Legend of Zelda Skyward Sword HD V1.0.1 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?4otb679nm8j0aecvz79x", + "" + ], + [ + "The Lightbringer Eur XCi - kaze-nico.xci", + "https://1fichier.com/?sf777534vxrok98mwg4q", + "" + ], + [ + "The Long Dark V1.84.65582 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?66qhfriu9ngif6p52wg0", + "" + ], + [ + "The Long Reach V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?5dddo6thw2bh5jdhuinx", + "" + ], + [ + "The Otterman Empire Eur XCi - kaze-nico.xci", + "https://1fichier.com/?9jbaj7a91ol7y8byu14b", + "" + ], + [ + "The Outer Worlds_SuperXci 1.0.3_eur_patched - kaze-nico.xci", + "https://1fichier.com/?u6mddu3o1mddnk25wk6j", + "" + ], + [ + "The Patrick Star Game (v1.01) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?xb8bjf72h7dnkmv03sak", + "" + ], + [ + "The Persistence V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c8jqwcgn5gqy9mouhgza", + "" + ], + [ + "The Secret Order Return to the Buried Kingdom EUR - kaze-nico.xci", + "https://1fichier.com/?3wqr47xsdi1ts51jskst", + "" + ], + [ + "The Silver Case 2425 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?4lzf8hhewosgj045hhcq", + "" + ], + [ + "The Stanley Parable Ultra Deluxe V1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?4gencfw2ycy2rn16n40b", + "" + ], + [ + "The TakeOver Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ixetzas2z37oyzi5teyf", + "" + ], + [ + "The Thing Remastered (v1.0.1) (EU) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?u2h10bzwt5qz4jejis5i", + "" + ], + [ + "The Wonderful 101 Remastered V1.0.7 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?akoixvyybwwozoeeejky", + "" + ], + [ + "The.Legend.of.Zelda.Breath.of.the.Wild. V1.6.0 Incl. All Dlcs SuperXCi PROPER - kaze-nico.xci", + "https://1fichier.com/?37924opwzs9iycsezpxu", + "" + ], + [ + "Thems Fightin Herds V1.2.0 Incl Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zaula3f2rgwumcb3ja3l", + "" + ], + [ + "Thimbleweed Park V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?enjuuazofyx8uhd9vhrc", + "" + ], + [ + "Thronebreaker The Witcher Tales V1.0.2 Incl. Pack Fr Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hcg6ajaluora5h0uknjw", + "" + ], + [ + "Timelie Eur XCi - kaze-nico.xci", + "https://1fichier.com/?cyth3hlz8u4jjyptu4zh", + "" + ], + [ + "Tin and Kuna Eur XCi - kaze-nico.xci", + "https://1fichier.com/?goephfzyhayz74hn6b05", + "" + ], + [ + "Tinker Racers Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ylgb3xf0x7g6rvv8w3ff", + "" + ], + [ + "Tiny Racer Eur XCi - kaze-nico.xci", + "https://1fichier.com/?t0f3f5m3p6v1t889dvr2", + "" + ], + [ + "Tinykin v1.0.4 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c3yz2zlavc73gm0qsbsl", + "" + ], + [ + "Titan Quest V1.0.5.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?5za1xslpzxkdo1wgckub", + "" + ], + [ + "Tohu V1.01 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?bxt4ma4lzugxjn5p79cg", + "" + ], + [ + "Toki Tori 2+ SuperXci 1.06 eur - kaze-nico.xci", + "https://1fichier.com/?ra4pc4j8mwteezg48mii", + "" + ], + [ + "Tomb Raider I-III Remastered Starring Lara Croft v1.0.1 Eur - Nicokoei.xci", + "https://1fichier.com/?cjd5qntv37k69uv771ew", + "" + ], + [ + "Tomb Raider IV-VI Remastered (v1.01) (EU) SuperXCI-Nicokoei.xci", + "https://1fichier.com/?6u9g2zr2auj5zq3lqbme", + "" + ], + [ + "Tomba_Special_Edition_NSW-VENOM V1.0 [EU] - Nicokoei.nsp", + "https://1fichier.com/?x89bxxpvs12m4xk8d3dm", + "" + ], + [ + "Tony Hawks Pro Skater 1 and 2 V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?xwtokzum2yzd2nexqzqd", + "" + ], + [ + "Torchlight III 1.6.103537 superxci eur_patched - kaze-nico.xci", + "https://1fichier.com/?ej6ivaniokz4b7yeqt6z", + "" + ], + [ + "Totally Reliable Delivery Service V1.0.3 Incl. 3DLC Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?tdpxcrti8wlk7b4tdhje", + "" + ], + [ + "Totally Spies! Cyber Mission (v1.04) SuperXCI - Nicokoei.xci", + "https://1fichier.com/?p3znl78abl1tfqr2dkji", + "" + ], + [ + "Towaga Among Shadows Eur XCi - kaze-nico.xci", + "https://1fichier.com/?g31gl1rm1sap8plf2b9j", + "" + ], + [ + "Tower Of Time Eur V1.0.1 SuperXCi - kaze-nico.xci", + "https://1fichier.com/?kg1olkfn3jzi3su4qt9y", + "" + ], + [ + "Towertale US XCi - kaze-nico.xci", + "https://1fichier.com/?tilb9w6whvbrjmeyzx4h", + "" + ], + [ + "Travis Strikes Again No More Heroes_eur 1.2.1+2DLC - kaze-nico.xci", + "https://1fichier.com/?jpqpemopb447vjvw764l", + "" + ], + [ + "Trials Rising V1.0.11 Incl. 6 Dlcs EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?sz9hb3xa519ss7nfod5g", + "" + ], + [ + "Trials of Mana V1.1.0 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2b3vop2i9trzsum4e9sq", + "" + ], + [ + "Trinity Trigger v1.0.4 Incl 18 Dlcs Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?deg3661dcuxzdjpcrrff", + "" + ], + [ + "Trinity_Fusion_NSW-VENOM V1.3.10220 [EU] - Nicokoei.nsp", + "https://1fichier.com/?nposwp9jfqip71af1wja", + "" + ], + [ + "Trivial Pursuit Live V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ay2pultpcsnmq3te5nok", + "" + ], + [ + "Tropico 6 Nintendo Switch Edition V1.0.2 Incl. 3 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?i78oonuhady9ymwvkjq5", + "" + ], + [ + "Truck and Logistics Simulator Eur XCi - kaze-nico.xci", + "https://1fichier.com/?hrth56bh2dsiayo0ez6g", + "" + ], + [ + "Tunic V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hiol4wp81zmwxe3jr7wt", + "" + ], + [ + "TurtlePop Voyage vers la Liberte V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?am0fwn0olm0w4qudrkl4", + "" + ], + [ + "Two Point Hospital V1.0.8 Incl. 4 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?926angpr6nd5k7t3clp2", + "" + ], + [ + "UNO V1.0.6 Incl. 8 Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?jfja72muoeqmcr2fcpln", + "" + ], + [ + "UNSIGHTED V1.0.4.4f Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2unpf36vlgadu45py9bu", + "" + ], + [ + "Umihara Kawase BaZooKa V1.0.1 Jap MultiEng SuperXCi - kaze-nico.xci", + "https://1fichier.com/?iifvfvne7b8q4hgxauoq", + "" + ], + [ + "Unbound Worlds Apart V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?la9dmtqg9fjrcs7oeq1v", + "" + ], + [ + "Unicorn Overlord eur - Nicokoei.xci", + "https://1fichier.com/?tplz9s6fzb158omsf2ah", + "" + ], + [ + "Unmetal V1.1.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?tndz77kfgqjwms1f022w", + "" + ], + [ + "VARIOUS DAYLIFE Eur XCi - kaze-nico.xci", + "https://1fichier.com/?owxmz8mm2gwcxactk3hh", + "" + ], + [ + "Vampire The Masquerade Shadows of New York Eur XCi - kaze-nico.xci", + "https://1fichier.com/?088vcsdzilstq9qho4lt", + "" + ], + [ + "Vigil The Longest Night V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?ho5zqss5tubtgit4q9mx", + "" + ], + [ + "Void Bastards Incl. Dlc EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?pm3jidzpd8omrp39fx68", + "" + ], + [ + "WARSAW Eur XCi - kaze-nico.xci", + "https://1fichier.com/?xzrnl4julmv9rzy362gc", + "" + ], + [ + "WARTILE V1.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?1olomhk5e1i9996x6axb", + "" + ], + [ + "WBSC eBASEBALL POWER PROS v1.1.0 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?t0jpz6k6gmfcqy9vbgsa", + "" + ], + [ + "WHAT THE GOLF Eur XCi - kaze-nico.xci", + "https://1fichier.com/?db5ygypctiemq1gsj04l", + "" + ], + [ + "WRC 9 Eur _patched - kaze-nico.xci", + "https://1fichier.com/?ny4kf98rmq81vmucqg71", + "" + ], + [ + "WRC Generations The FIA WRC Official Game Jap MULTiFr V1.1.0 SuperXCi - Nicokoei.xci", + "https://1fichier.com/?drbvanwtd5vs3kwex1h2", + "" + ], + [ + "WWE 2K Battlegrounds V1.0.2.0 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?se8e3mr1h9e1wceajof4", + "" + ], + [ + "WarGroove V2.1.0 Incl. Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?edsn6syccbvsch9j69l6", + "" + ], + [ + "Warborn V1.0.3 EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?c8k8a0cfv66i40h02z1s", + "" + ], + [ + "Warhammer 40.000 Mechanicus Eur XCi - kaze-nico.xci", + "https://1fichier.com/?sf2366f2lj5ebcm0qmvs", + "" + ], + [ + "WarioWare Get It Together Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5xu1won7diniet5himep", + "" + ], + [ + "WarriOrb Eur XCi - kaze-nico.xci", + "https://1fichier.com/?7by0tk06j2iozybor5k5", + "" + ], + [ + "Wartales v1.0.28259 Eur SuperXCi - Nicokoei.xci", + "https://1fichier.com/?0tjrwaj108ok0tshqs8x", + "" + ], + [ + "We Are OFK Eur XCi - kaze-nico.xci", + "https://1fichier.com/?tuzzyy7y89svk1s72ep4", + "" + ], + [ + "We should talk. Eur XCi - kaze-nico.xci", + "https://1fichier.com/?czrb9iaca1u0qrjjerht", + "" + ], + [ + "Wenjia Eur XCi - kaze-nico.xci", + "https://1fichier.com/?8243fi5usot4mdtrno3e", + "" + ], + [ + "West of Dead Switch Eur XCi - kaze-nico.xci", + "https://1fichier.com/?1qh0b1mzabqr54363att", + "" + ], + [ + "Where Angels Cry Eur XCi - kaze-nico.xci", + "https://1fichier.com/?is0u43599ou9ddamyvsv", + "" + ], + [ + "WildTrax Racing V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?p7l0nnakce4wf5cehu6z", + "" + ], + [ + "Windbound V1.3.40603.424 Incl Dlc Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?587tgkvlpdu4pgqp1pta", + "" + ], + [ + "Winter Games 2023 V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?0tb6uf7yfvodyowqjac2", + "" + ], + [ + "Wintermoor Tactics Club Eur XCi - kaze-nico.xci", + "https://1fichier.com/?llig7w2i53qddbbazrjc", + "" + ], + [ + "Wolfenstein Youngblood V1.5 Incl. 5Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2x33sx18pqdh9duhxnw7", + "" + ], + [ + "Wonder Boy Asha in Monster World V1.1 Jap MultiFr SuperXCi - kaze-nico.xci", + "https://1fichier.com/?hftrp9l4upk41ci451b0", + "" + ], + [ + "Wonder Boy Collection v1.0 Eur XCi - Nicokoei.xci", + "https://1fichier.com/?sulzbp92uturgkxq91ov", + "" + ], + [ + "World Of Goo 2 V1.0.1 EU SuperXci - Nicokoei.xci", + "https://1fichier.com/?pwn0imotpnfaxzx7hzb4", + "" + ], + [ + "World War Z V1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?zu8vcandz7bjlwlkxozc", + "" + ], + [ + "World of Tanks Blitz V7.2.0.582 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?3a72gad2dg62a4js983z", + "" + ], + [ + "Worlds End Club V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?qvc27nwxl6ktx0czkgec", + "" + ], + [ + "Worms Rumble V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?k7pj2gf9zz57pzv49tou", + "" + ], + [ + "Wreckfest Incl Dlcs and Update 1.0.2 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?eqfvqnf0vm56rtn3660m", + "" + ], + [ + "XCOM 2 Collection V1.0.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?s2xvbhepdroq93u9wdw2", + "" + ], + [ + "Xenoblade Chronicles 3 Eur XCi - kaze-nico.xci", + "https://1fichier.com/?5wlxygzk18bo26q2szbv", + "" + ], + [ + "Xenoblade Chronicles X Definitive Edition (v1.01) (EU) SuperXCI -Nicokoei.xci", + "https://1fichier.com/?egbirg99i0xnyikzmqhj", + "" + ], + [ + "Yooka Laylee V1.2.0 EUR SuperXCi - kaze-nico.xci", + "https://1fichier.com/?o8osw82kgsxv02dnze28", + "" + ], + [ + "Youtubers Life OMG Edition V1.6.3 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?vjh2xsho1wzuk671dqoa", + "" + ], + [ + "Ys IX Monstrum Nox V1.0.2 Incl. 25 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?aoydogtcdnzddbehfxpk", + "" + ], + [ + "Ys Origin V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?dqbof0iflgh90g1pt6di", + "" + ], + [ + "Yu Gi Oh Master Duel Eur XCi - kaze-nico.xci", + "https://1fichier.com/?dj8d8s2fnn51r1jxo75h", + "" + ], + [ + "Yu-Gi-Oh Legacy of the DuelistLink Evolution V1.0.1 Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?mw367pnlgtw5v5ymbp9t", + "" + ], + [ + "Zenge Eur XCi - kaze-nico.xci", + "https://1fichier.com/?4dlurnjqa6oy0cag8fxv", + "" + ], + [ + "Ziggy The Chaser_Eur - kaze-nico .xci", + "https://1fichier.com/?200450iw3ud4g0wqce12", + "" + ], + [ + "Zoids Wild Blast Unleashed Eur XCi - kaze-nico.xci", + "https://1fichier.com/?ype2t36ix1exznuwou4z", + "" + ], + [ + "Zombie Army 4 Dead War Incl 18 Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?q5vx90krfvuqzghl54oq", + "" + ], + [ + "eCrossminton Eur XCi - kaze-nico.xci", + "https://1fichier.com/?61r81zfb4t0nvp3914qu", + "" + ], + [ + "hackGU Last Recode Eur XCi - kaze-nico.xci", + "https://1fichier.com/?q3vjefpmuxfldmdhzvui", + "" + ], + [ + "immortals fenyx rising V1.2.0 Incl. All Dlcs Eur SuperXCi - kaze-nico.xci", + "https://1fichier.com/?2l1c31x3ohxqeurll90t", + "" + ] +] \ No newline at end of file diff --git a/rom_extensions.json b/rom_extensions.json index bdf3fb8..d7b916a 100644 --- a/rom_extensions.json +++ b/rom_extensions.json @@ -2146,7 +2146,15 @@ ".elf", ".dol", ".m3u", - ".json" + ".xci" + ] + }, + { + "system": "switch", + "folder": "/userdata/roms/switch", + "extensions": [ + ".nsp", + ".xci" ] }, { diff --git a/utils.py b/utils.py index 5f8f1d7..8b4b55c 100644 --- a/utils.py +++ b/utils.py @@ -1,4 +1,4 @@ -import pygame +import pygame # type: ignore import re import json import os @@ -25,18 +25,52 @@ def create_placeholder(width=400): return placeholder def truncate_text_middle(text, font, max_width): - """Tronque le texte en insérant '...' au milieu.""" + """Tronque le texte en insérant '...' au milieu, en préservant le début et la fin, sans extension de fichier.""" + # Supprimer l'extension de fichier + text = text.rsplit('.', 1)[0] if '.' in text else text text_width = font.size(text)[0] if text_width <= max_width: return text ellipsis = "..." ellipsis_width = font.size(ellipsis)[0] max_text_width = max_width - ellipsis_width - while text_width > max_text_width and len(text) > 0: - text = text[:-1] - text_width = font.size(text)[0] - mid = len(text) // 2 - return text[:mid] + ellipsis + text[mid:] + if max_text_width <= 0: + return ellipsis + + # Diviser la largeur disponible entre début et fin + chars = list(text) + left = [] + right = [] + left_width = 0 + right_width = 0 + left_idx = 0 + right_idx = len(chars) - 1 + + while left_idx <= right_idx and (left_width + right_width) < max_text_width: + if left_idx < right_idx: + left.append(chars[left_idx]) + left_width = font.size(''.join(left))[0] + if left_width + right_width > max_text_width: + left.pop() + break + left_idx += 1 + if left_idx <= right_idx: + right.insert(0, chars[right_idx]) + right_width = font.size(''.join(right))[0] + if left_width + right_width > max_text_width: + right.pop(0) + break + right_idx -= 1 + + # Reculer jusqu'à un espace pour éviter de couper un mot + while left and left[-1] != ' ' and left_width + right_width > max_text_width: + left.pop() + left_width = font.size(''.join(left))[0] if left else 0 + while right and right[0] != ' ' and left_width + right_width > max_text_width: + right.pop(0) + right_width = font.size(''.join(right))[0] if right else 0 + + return ''.join(left).rstrip() + ellipsis + ''.join(right).lstrip() def truncate_text_end(text, font, max_width): """Tronque le texte à la fin pour qu'il tienne dans max_width avec la police donnée.""" @@ -65,6 +99,9 @@ def sanitize_filename(name): def wrap_text(text, font, max_width): """Divise le texte en lignes pour respecter la largeur maximale.""" + if not isinstance(text, str): + text = str(text) if text is not None else "" + words = text.split(' ') lines = [] current_line = ''