2025-07-09 01:13:55 +02:00
import pygame # type: ignore
2025-07-06 19:47:21 +02:00
import os
import logging
logger = logging . getLogger ( __name__ )
# Version actuelle de l'application
2025-07-15 18:40:08 +02:00
app_version = " 1.9.6.3 "
2025-07-13 21:46:46 +02:00
2025-07-12 18:40:58 +02:00
# URL du serveur OTA
OTA_SERVER_URL = " https://retrogamesets.fr/softs "
OTA_VERSION_ENDPOINT = f " { OTA_SERVER_URL } /version.json "
2025-07-15 18:40:08 +02:00
OTA_UPDATE_ZIP = f " { OTA_SERVER_URL } /RGSX.zip "
2025-07-12 18:40:58 +02:00
OTA_data_ZIP = f " { OTA_SERVER_URL } /rgsx-data.zip "
2025-07-15 18:40:08 +02:00
APP_FOLDER = " /userdata/roms/ports/RGSX "
UPDATE_FOLDER = f " { APP_FOLDER } /update "
2025-07-12 18:40:58 +02:00
2025-07-13 21:46:46 +02:00
# Constantes pour la répétition automatique dans pause_menu
REPEAT_DELAY = 300 # Délai initial avant répétition (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
2025-07-06 19:47:21 +02:00
# Variables d'état
2025-07-13 21:46:46 +02:00
platforms = [ ]
current_platform = 0
2025-07-06 19:47:21 +02:00
platform_names = { } # {platform_id: platform_name}
2025-07-13 21:46:46 +02:00
games = [ ]
current_game = 0
menu_state = " popup "
2025-07-06 19:47:21 +02:00
confirm_choice = False
scroll_offset = 0
2025-07-13 21:46:46 +02:00
visible_games = 15
2025-07-06 19:47:21 +02:00
popup_start_time = 0
last_progress_update = 0
needs_redraw = True
transition_state = " idle "
transition_progress = 0.0
transition_duration = 18
games_count = { }
2025-07-15 12:28:32 +02:00
2025-07-06 19:47:21 +02:00
loading_progress = 0.0
current_loading_system = " "
error_message = " "
2025-07-13 21:46:46 +02:00
repeat_action = None
repeat_start_time = 0
repeat_last_action = 0
repeat_key = None
2025-07-06 19:47:21 +02:00
filtered_games = [ ]
search_mode = False
search_query = " "
filter_active = False
extension_confirm_selection = 0
pending_download = None
controls_config = { }
2025-07-09 01:13:55 +02:00
selected_option = 0
2025-07-06 19:47:21 +02:00
previous_menu_state = None
2025-07-15 12:28:32 +02:00
history = [ ] # Liste des entrées d'historique avec platform, game_name, status, url, progress, message, timestamp
download_progress = { }
download_tasks = { } # Dictionnaire pour les tâches de téléchargement
download_result_message = " "
download_result_error = False
download_result_start_time = 0
pending_download = None
needs_redraw = False
current_history_item = 0
history_scroll_offset = 0
2025-07-07 02:48:05 +02:00
history_scroll_offset = 0 # Offset pour le défilement de l'historique
visible_history_items = 15 # Nombre d'éléments d'historique visibles (ajusté dynamiquement)
confirm_clear_selection = 0 # confirmation clear historique
last_state_change_time = 0 # Temps du dernier changement d'état pour debounce
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)
2025-07-09 01:13:55 +02:00
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 ( )
2025-07-06 19:47:21 +02:00
2025-07-11 17:28:42 +02:00
2025-07-10 22:32:35 +02:00
GRID_COLS = 3 # Number of columns in the platform grid
GRID_ROWS = 4 # Number of rows in the platform grid
2025-07-09 01:13:55 +02:00
# Résolution de l'écran fallback
# Utilisée si la résolution définie dépasse les capacités de l'écran
2025-07-06 21:20:47 +02:00
SCREEN_WIDTH = 800
""" Largeur de l ' écran en pixels. """
SCREEN_HEIGHT = 600
""" Hauteur de l ' écran en pixels. """
2025-07-06 19:47:21 +02:00
# Polices
2025-07-06 21:20:47 +02:00
FONT = None
""" Police par défaut pour l ' affichage, initialisée via init_font(). """
2025-07-06 19:47:21 +02:00
progress_font = None
2025-07-06 21:20:47 +02:00
""" Police pour l ' affichage de la progression. """
2025-07-06 19:47:21 +02:00
title_font = None
2025-07-06 21:20:47 +02:00
""" Police pour les titres. """
2025-07-06 19:47:21 +02:00
search_font = None
2025-07-06 21:20:47 +02:00
""" Police pour la recherche. """
2025-07-06 20:53:26 +02:00
small_font = None
2025-07-06 21:20:47 +02:00
""" Police pour les petits textes. """
2025-07-06 20:53:26 +02:00
CONTROLS_CONFIG_PATH = " /userdata/saves/ports/rgsx/controls.json "
""" Chemin du fichier de configuration des contrôles. """
2025-07-07 02:48:05 +02:00
HISTORY_PATH = " /userdata/saves/ports/rgsx/history.json "
""" Chemin du fichier de l ' historique des téléchargements. """
2025-07-13 21:46:46 +02:00
JSON_EXTENSIONS = " /userdata/roms/ports/RGSX/rom_extensions.json "
""" Chemin du fichier JSON des extensions de ROMs. """
2025-07-06 20:53:26 +02:00
2025-07-06 21:20:47 +02:00
def init_font ( ) :
""" Initialise les polices après pygame.init(). """
global FONT , progress_font , title_font , search_font , small_font
try :
FONT = pygame . font . Font ( None , 36 )
progress_font = pygame . font . Font ( None , 28 )
title_font = pygame . font . Font ( None , 48 )
search_font = pygame . font . Font ( None , 36 )
small_font = pygame . font . Font ( None , 24 )
logger . debug ( " Polices initialisées avec succès " )
except pygame . error as e :
logger . error ( f " Erreur lors de l ' initialisation des polices : { e } " )
FONT = None
progress_font = None
title_font = None
search_font = None
small_font = None
2025-07-06 20:53:26 +02:00
def validate_resolution ( ) :
2025-07-09 01:13:55 +02:00
""" Valide la résolution de l ' écran par rapport aux capacités de l ' écran. """
2025-07-06 20:53:26 +02:00
display_info = pygame . display . Info ( )
if SCREEN_WIDTH > display_info . current_w or SCREEN_HEIGHT > display_info . current_h :
2025-07-06 21:20:47 +02:00
logger . warning ( f " Résolution { SCREEN_WIDTH } x { SCREEN_HEIGHT } dépasse les limites de l ' écran " )
2025-07-06 20:53:26 +02:00
return display_info . current_w , display_info . current_h
2025-07-09 01:13:55 +02:00
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 "
2025-07-11 14:51:39 +02:00
# Vérifie si le fichier existe, sinon le crée
try :
os . makedirs ( os . path . dirname ( api_path ) , exist_ok = True )
except OSError as e :
logger . error ( f " Erreur lors de la création du répertoire pour la clé API : { e } " )
return " "
try :
# Vérifie si le fichier existe déjà
if not os . path . exists ( api_path ) :
# Crée le fichier vide si absent
with open ( api_path , " w " ) as f :
f . write ( " " )
logger . info ( f " Fichier de clé API créé : { api_path } " )
except OSError as e :
logger . error ( f " Erreur lors de la création du fichier de clé API : { e } " )
return " "
# Lit la clé API depuis le fichier
try :
with open ( api_path , " r " , encoding = " utf-8 " ) as f :
api_key = f . read ( ) . strip ( )
if not api_key :
logger . warning ( " Clé API 1fichier vide, veuillez la renseigner dans le fichier pour pouvoir utiliser les fonctionnalités de téléchargement sur 1fichier. " )
return api_key
except OSError as e :
logger . error ( f " Erreur lors de la lecture de la clé API : { e } " )
2025-07-09 01:13:55 +02:00
return " "
2025-07-11 14:51:39 +02:00
2025-07-09 01:13:55 +02:00
API_KEY_1FICHIER = load_api_key_1fichier ( )