= Manuel de Singe Scott Duensing :revnumber: 3.00 :revdate: 2026 :doctype: book :toc: left :toclevels: 3 :sectnums: :sectnumlevels: 3 :title-logo-image: image:images/singeLogo.png[Singe, pdfwidth=2.6in, align=center] :source-highlighter: rouge :icons: font :experimental: :lang: fr :imagesdir: .. include::locale.adoc[] [#_about_singe] == À propos de Singe Singe (SINGE Is Not a Game Emulator, soit « SINGE n'est pas un émulateur de jeux », et nommé d'après le dragon de Dragon's Lair) est un système de script basé sur Lua qui permet de prototyper rapidement de nouveaux jeux laserdisc, ou de créer des jeux entièrement nouveaux. Le langage est facile à apprendre, très puissant et rapide. Toutes les fonctionnalités nécessaires pour développer votre propre jeu sont accessibles par une interface de programmation (API) simple. Singe offre de nombreuses fonctionnalités au développeur de jeux. Parmi les plus intéressantes : * Scènes 3D avec modèles, animation, éclairage et ombres * Physique, avec articulations, ragdolls, corps mous et véhicules * Menus, écrans d'options et HUD construits comme des pages web * Décodage vidéo matériel, même sur de petites machines * Meilleurs scores en ligne, et un catalogue de jeux à télécharger et à mettre à jour * Jeux empaquetés dans un seul fichier * Langage de programmation orienté objet * Sprites animés * Prise en charge des polices TrueType * Espace colorimétrique 32 bits avec transparence * Son stéréo multicanal avec superposition, et MIDI * Prise en charge des périphériques d'entrée analogiques et numériques, pistolets optiques compris * Large prise en charge des formats vidéo et audio Singe fonctionne sous Windows, macOS et Linux, y compris sur le Raspberry Pi et sur des consoles portables comme la R36S. Côté joueurs, Singe permet de profiter de nombreux jeux non émulés et de jeux nouveaux, depuis le front-end de votre choix ou par le système de menus fourni. Depuis la première version de Singe, en 2006, plusieurs révisions sont sorties, officielles ou non. En 2020 est sorti Singe 2.00. C'était une réécriture complète, repartie de zéro, qui ajoutait de nombreuses fonctionnalités tout en restant compatible avec les jeux 1.xx existants. Singe 3.00 ajoute la 3D, la physique, les interfaces utilisateur et bien plus encore, tout en faisant toujours tourner les jeux qui l'ont précédé. À l'heure où ce manuel est écrit, la dernière version est la {revnumber}. [#_installation_and_upgrading] == Installation et mise à jour [#_installing_singe] === Installer Singe Pour installer Singe, téléchargez simplement le binaire qui correspond à votre système. Placez-le seul dans un nouveau dossier et lancez-le. Au premier lancement, Singe crée tous les dossiers et fichiers de support nécessaires. Vous êtes maintenant prêt à installer des jeux. [#_upgrading_singe] === Mettre Singe à jour Pour passer Singe à une version plus récente, placez le nouveau binaire dans le dossier d'installation à côté de l'ancien et lancez-le une fois avec `--refresh`. Le dossier de support qui s'y trouve est mis de côté sous le nom `old-Singe-`, d'après la version qui l'a écrit, et un dossier `Singe/` neuf est écrit à sa place. Rien n'est supprimé : le dossier mis de côté est à vous, à garder ou à supprimer, et un second `--refresh` met le sien de côté sous `old-Singe--1` au lieu d'écraser le premier. L'ancien binaire peut rester où il est. `Menu.sh` (ou `Menu.bat`) lance le Singe le plus récent qu'il trouve à côté de lui, et une bêta compte comme plus ancienne que la version finale du même numéro : `Singe-v3.00b2` s'efface donc devant `Singe-v3.00` dès que celle-ci arrive. L'outil Engine Update du menu fait tout cela pour vous ; voir <>. WARNING: Ne lancez pas un nouveau binaire de Singe avec des fichiers de support périmés. Rafraîchissez toujours le dossier `Singe/` lors d'une mise à jour. [#_things_to_know] === À savoir Ne touchez pas au dossier `Singe/`. Les fichiers de ce dossier appartiennent à Singe et peuvent être mis à jour ou supprimés à tout moment. [#_playing_games] == Jouer [#_installing_games] === Installer des jeux Un jeu est soit un fichier `.game` unique, soit un dossier. Copiez-le dans le dossier où vous avez placé le binaire de Singe. Le système de menus fourni le détecte automatiquement et l'ajoute au menu. [#_game_directory_layout] === Organisation du dossier des jeux Une installation de Singe est un dossier des jeux qui contient le dossier de support `Singe` que le moteur crée au premier lancement, un dossier par jeu, les éventuels fichiers `.game` empaquetés, et un dossier `data` pour tout ce qu'écrivent les jeux et le moteur. L'exécutable s'y trouve généralement aussi, mais ce n'est pas obligatoire : `--gamedir` désigne le dossier des jeux depuis n'importe où, et le `Menu.sh` (ou `Menu.bat`) que le moteur y écrit lance alors l'exécutable par son chemin complet. Sinon, le lanceur cherche à côté de lui les fichiers dont le nom commence par `Singe` et lance le meilleur d'entre eux, dans l'esprit des lanceurs qu'écrit `BatMaker` : ainsi, une mise à jour qui change la version inscrite dans le nom de l'exécutable ne laisse pas un lanceur pointer vers un fichier qui n'existe plus. Le meilleur, c'est d'abord l'architecture de cette machine, puis la version. La plateforme inscrite dans le nom est comparée à ce que signale le système, car une version plus récente pour une autre architecture ne peut pas tourner du tout, et un même dossier des jeux sur un partage réseau peut être lu aussi bien par un Pi que par un PC. Le lanceur fait ce calcul à chaque lancement au lieu qu'on le lui dise une fois pour toutes, si bien que le même dossier convient à chaque machine qui l'ouvre. Sur un Mac, une version universelle compte comme native. Parmi les versions que cette machine peut faire tourner, la plus récente l'emporte : `Singe-v3.10` bat `Singe-v3.09`, et une bêta perd face à la version finale qu'elle prépare, donc `Singe-v3.00b2` perd face à `Singe-v3.00`. Une version pour une autre architecture est quand même lancée si c'est la seule présente, car une vraie plainte du moteur vaut mieux que de s'entendre dire que rien n'a été trouvé ; il en va de même d'un nom que le lanceur ne sait pas lire du tout. ---- Singe/ Fichiers de support extraits par le moteur Framework.singe Chargé par chaque jeu (avec dofile) Menu.singe Le menu de jeux fourni Tools.singe Les outils de service du menu (voir Les outils de service) MenuDocument.singe Le menu dessiné comme un document GUI MenuOverlay.singe Le menu dessiné dans l'overlay, pour une machine sans GPU Backdrop.singe L'intro du menu et la grille derrière lui, dessinées en direct menuBackground.mkv Le même fond, enregistré, pour une machine sans GPU menuIntro.flac Son son, qui s'estompe quand le menu prend l'écran Menu.rml Le document RmlUi du rendu par document menu.rcss Sa feuille de style, par-dessus gui.rcss gui.rcss Le thème GUI fourni controls.cfg.example Modèle pour les affectations des entrées click.wav Utilisé par les tests de délai audio et de son du menu Manual.pdf Ce manuel Manual-fr.pdf Ce manuel en français Manual-it.pdf Ce manuel en italien Manual-de.pdf Ce manuel en allemand Manual-es.pdf Ce manuel en espagnol COPYING La licence publique générale GNU, version 3 LICENSES Mentions des tiers et crédits des ressources Collection/ Un dossier de jeux games.dat Entrées de menu pour les jeux de ce dossier AsteroidPatrol.singe Un script frame_AsteroidPatrol.txt Son framefile (ou une vidéo de même nom de base) sprite_*.png, sound_*.wav, font_*.ttf MyGame.game Un jeu empaqueté dans un seul fichier (voir Jeux en un seul fichier) data/ machine.cfg Le délai audio et la géométrie d'image de cette machine Collection/ Index, trace.txt, captures d'écran, sauvegardes de ces jeux ---- Où Singe cherche les fichiers d'un script, et où un script peut écrire, c'est l'affaire de celui qui écrit le script ; la Référence de Singe traite les deux points dans Empaqueter votre jeu. [#bundledmenu] === Le menu fourni `Menu.sh` (ou `Menu.bat`) démarre `Singe/Menu.singe`, le menu fourni : un document RmlUi, `Singe/Menu.rml` mis en forme par `Singe/menu.rcss`, dessiné par-dessus un fond 3D calculé en direct (voir xref:Reference.adoc#gui[GUI]). Le menu tourne sans disque ; une machine sans GPU lit plutôt `Singe/menuBackground.mkv`, un enregistrement du même fond, derrière une page plus simple dessinée sur l'overlay. Il lit le `games.dat` de chaque dossier de jeu et de chaque fichier `.game` à côté de lui, et liste chaque jeu qu'il trouve, trié par titre, sur la gauche de l'écran. À côté de la liste figurent l'illustration de borne du jeu sélectionné, son fronton et son clip du mode attraction, avec en dessous l'année, le genre, la plateforme, le développeur, l'éditeur, les crédits du portage et la description, et une ligne d'aide sur les touches tout en bas. Haut et bas déplacent la sélection d'un jeu à la fois, gauche et droite d'une page à la fois ; dans les deux cas, on passe d'un bout de la liste à l'autre. Start ou n'importe quel bouton d'action lance le jeu sélectionné, et la touche affectée à `INPUT_SERVICE` (la touche `9` par défaut) ouvre les outils de service (voir <>). À la souris, un clic sur une ligne sélectionne ce jeu et un second clic sur la même ligne le lance ; la molette fait défiler une description trop longue pour son panneau. Si vous définissez `--quitchord`, maintenir ces boutons ramène d'un jeu au menu, et du menu à votre système (voir <>). Le menu garde sa sélection dans `menu.dat`, dans son dossier de données, si bien qu'il revient sur le même jeu quand celui-ci se termine ou au prochain démarrage de Singe. Ce fichier est un fragment de Lua que le menu lit au démarrage et réécrit à l'arrêt : `GAME_SELECTED` est le jeu qu'il affichait, `SHOW_INTRO` vaut false quand il revient d'un jeu, pour qu'on ne subisse pas l'intro deux fois, et `MENU_OVERLAY` choisit un moteur de rendu (voir <>). Toutes les machines ne font pas tourner tous les jeux. Un jeu 3D sur une machine sans 3D, ou un jeu lourd sur une petite machine, échouerait ou se traînerait, alors le menu vous prévient d'abord. Quand vous sélectionnez un jeu que cette machine ne peut pas faire tourner, la ligne sous ses détails dit ce qu'il lui faut (« Needs 3D, and this machine has none. »), et le lancer ne fait que répéter ce message au lieu d'échouer en cours de route. Un jeu qui demande plus de machine que celle-ci obtient « It may run slowly. » et démarre quand même. Rien n'est caché. Le menu évalue la vitesse de cette machine la première fois que son intro se joue, en chronométrant son propre fond, et garde la réponse dans `machine.cfg` ; il ne vous demande jamais de lancer un benchmark. Les jeux disent ce qu'il leur faut dans leur `games.dat` (xref:Reference.adoc#gamesdat[REQUIRES et TIER]), et l'outil Get Games marque le catalogue de la même façon. [#menurenderers] ==== Les deux moteurs de rendu Un document GUI est dessiné par le périphérique GPU qu'utilise la scène 3D ; sur une machine qui n'en a pas, il n'y a donc pas de document à construire. Le menu s'en charge lui-même : `Singe/Menu.singe` interroge xref:Reference.adoc#singehasgpu[singeHasGpu] au démarrage et charge l'un des deux moteurs de rendu. `Singe/MenuDocument.singe`:: Le document RmlUi décrit plus haut, pour une machine dotée d'un périphérique GPU. Il dessine aussi l'intro et la grille derrière le menu comme une seule scène 3D continue, si bien que le disque ne sert ni pour l'une ni pour l'autre. `Singe/MenuOverlay.singe`:: Des sprites et `fontPrint` directement dans l'overlay, l'allure qu'avait Singe 2. Il n'a besoin de rien de plus que l'overlay dans lequel chaque jeu dessine déjà. Les deux dessinent le même menu, prennent les mêmes touches et lancent les mêmes outils de service ; `Singe/Menu.singe` contient tout ce qui n'est pas du dessin -- la liste des jeux, la sélection, le lancement d'un jeu -- si bien qu'il y a un seul menu et non deux. Le moteur de rendu overlay montre un jeu à la fois au lieu d'une liste, puisqu'il n'a pas de panneau à faire défiler, et il coupe une description trop longue pour sa colonne au lieu de la faire défiler. Pour voir le moteur de rendu overlay sur une machine qui a bel et bien un GPU, mettez `MENU_OVERLAY = true` dans `menu.dat`, dans le dossier de données du menu ; le menu réécrit la ligne, elle reste donc en place. C'est ainsi qu'on teste le chemin overlay, et c'est ainsi qu'un constructeur de bornes qui préfère l'ancienne allure l'obtient. [#onlineservice] ==== En ligne : comptes, jeux et scores Le menu fourni peut connecter la borne à un service maître (par défaut `master.singeengine.com`), qui fait trois choses : il gère le compte, il propose un catalogue de jeux à télécharger et à mettre à jour, et il tient des tableaux des meilleurs scores. Deux outils de service s'en occupent. **Online Account** connecte la borne, crée un compte, récupère un mot de passe et règle l'adresse du serveur -- c'est là qu'un exploitant qui fait tourner son propre service y fait pointer la borne. Un nouveau compte n'est utilisable qu'une fois ouvert le lien reçu par e-mail. **Get Games** liste tout ce que le service propose, marque ce qui est installé ici, et le télécharge, le met à jour ou le supprime. Un téléchargement qui contient plusieurs jeux -- une collection, ou un même jeu en deux langues -- les place tous dans la liste, chacun sous son propre nom, en indiquant dans quel téléchargement il se trouve, et récupérer ou supprimer l'un d'eux récupère ou supprime le tout, puisqu'ils forment un seul fichier. Ce qui est proposé dépend du compte : un service peut réserver un jeu à certains comptes, donc deux bornes connectées à des comptes différents peuvent voir des listes différentes. Le menu signale lui-même qu'une version plus récente d'un jeu installé existe : le jeu porte une marque `update` dans la liste, la ligne sous ses détails donne la version, et le bouton 3 sur cette page la récupère ; une borne n'a donc pas besoin d'ouvrir un outil de service pour rester à jour. Rien de ce qui concerne cette machine n'est conservé où que ce soit : le menu lit la version dans le `games.dat` propre à chaque jeu et se renseigne sur sa propre liste, si bien qu'un jeu copié à la main est connu aussi bien qu'un jeu téléchargé ici. Une borne sans aucun jeu ouvre quand même le menu, qui explique comment en récupérer, et tout ce que Get Games télécharge ou supprime apparaît dans la liste dès que les outils de service se ferment. Une liste plus longue que l'écran défile avec la sélection au lieu de déborder en bas, avec `...` pour montrer qu'il y en a encore d'un côté ou de l'autre. Un jeu qui n'est plus proposé continue de fonctionner et s'affiche comme « installed, no longer offered » : tout ce qui s'arrête, ce sont les mises à jour, car un joueur qui a un jeu l'a. Un téléchargement est vérifié par rapport à l'empreinte publiée par le catalogue avant de remplacer quoi que ce soit, si bien qu'un transfert arrivé abîmé échoue au lieu d'installer un jeu qui ne tournera pas. Le compte appartient à la *machine*, pas à un jeu : le jeton est gardé dans `master.dat`, à la racine des données, si bien qu'un jeu qui envoie un score utilise la même connexion que celle établie par le menu. Le mot de passe n'est jamais conservé, et le fichier est brouillé, si bien qu'on ne peut y lire d'un coup d'œil ni le jeton ni l'adresse du compte ; un fichier modifié se lit comme déconnecté. La machine doit pouvoir le relire sans surveillance, alors traitez quand même `master.dat` comme une clé du compte : copié sur une autre machine, il connecte cette machine. Envoyer un score demande ce compte, mais lire un tableau, non : une borne qui n'est pas connectée affiche quand même le tableau en ligne d'un jeu, là où le jeu en affiche un, pour tout jeu que le service propose à tout le monde. Voir xref:Reference.adoc#onlinescores[Meilleurs scores en ligne] pour la partie qui revient au jeu, et `Singe/Net.singe` pour le client HTTP asynchrone qui travaille en dessous -- rien ici ne bloque une image, car Lua dans Singe est coopératif, et un gros téléchargement ressemblerait sinon à un blocage. Singe vérifie le certificat du serveur par rapport à deux listes à la fois : celle qu'il apporte et celle que garde votre machine. Il suffit que l'une des deux se porte garante du serveur, si bien qu'une ancienne copie de Singe peut encore atteindre la mise à jour qui la remplace, tant que votre système tient sa propre liste à jour. Vous faites tourner votre propre service avec un certificat de votre propre autorité ? Mettez le certificat de cette autorité dans `cacerts.local.pem`, dans le dossier de données. Singe n'écrit jamais ce fichier, il survit donc aux mises à jour. Si une connexion est refusée, le message dit quelles listes ont été vérifiées, et un certificat « not yet valid » signifie presque toujours que l'horloge de la machine est fausse. [#servicetools] ==== Les outils de service La touche affectée à `INPUT_SERVICE` ouvre une liste d'outils par-dessus la liste des jeux. Haut et bas en choisissent un et le bouton 1 l'ouvre ; le bouton 2 ramène d'un outil à la liste, et la touche service, de nouveau, quitte complètement les outils. Tout se trouve dans `Singe/Tools.singe`, que le moteur extrait à côté de `Menu.singe`. Rien là-dedans ne dessine : un outil construit une liste de lignes et la confie au menu, et c'est pourquoi chaque outil tourne sur les deux moteurs de rendu (voir <>). Rien ici n'a besoin qu'un jeu tourne, et rien ne modifie les fichiers propres à un jeu. Audio Delay:: Le délai audio en aval, mesuré par rapport à un clic et un flash. Voir xref:Reference.adoc#menucalibration[Calibrer depuis le menu] pour ce qu'il fait et pourquoi ça marche. Input Test:: Chaque manette, souris et pistolet que le moteur voit, en direct : le dernier contact que le jeu aurait reçu et combien en sont arrivés, le nom de chaque manette avec ses six axes et les boutons enfoncés, et le nom et la position de chaque souris. C'est l'écran qui répond à « le bouton ne fait rien » -- soit le contact arrive et le jeu l'ignore, soit il n'arrive jamais. System Information:: La version du moteur, le système d'exploitation, le processeur et la mémoire, le moteur de rendu et le périphérique 3D, les décodeurs vidéo utilisés, les formats audio intégrés, la SoundFont, l'état du MIDI, les tailles de la fenêtre, du canevas et de l'overlay, et le dossier de données. Une photo de cette page répond à l'essentiel d'un rapport de bogue. Light Gun:: Des cibles au centre et à chaque coin de l'overlay, par-dessus ce que montre le disque. Le bouton 1 marque l'endroit où le pistolet visait vraiment, en gardant les douze derniers tirs ; start les efface. Un pistolet bien d'équerre avec l'image place ses croix sur les cibles, et un pistolet qui ne l'est pas montre de quel côté il est décalé. Sound Test:: Le bouton 1 joue le clic dans le haut-parleur gauche, puis le droit, puis les deux, ce qui suffit à vérifier que les fils ne sont pas croisés. Il liste aussi les pistes audio du disque lui-même, et gauche et droite passent de l'une à l'autre. Display:: La taille, la position et la rotation de l'image, modifiées en direct avec les flèches, les boutons 3 et 4 et coin 1, par-dessus une mire : une grille de 16 sur 12 pour mettre l'image d'équerre, une gamme de gris en huit paliers pour régler la luminosité, et deux cadres à un pixel d'écart tout au bord -- un moniteur qui fait de l'overscan mange d'abord celui de l'extérieur. Le bouton 1 garde les valeurs pour cette machine, dans le même `machine.cfg` que le délai audio, si bien qu'elles s'appliquent à chaque jeu au lieu d'être réglées une fois par jeu. Start remet tout comme avant. Disc Test:: Douze sauts répartis sur tout le disque, chacun chronométré. Un rip dont les images clés sont très espacées saute lentement, et le seul symptôme en jeu, c'est que tout semble lourd ; ce test le mesure directement et indique le pire des douze. Un saut qui n'a pas abouti en trois secondes compte pour trois secondes. Saved Data:: Ce que chaque jeu a gardé, trouvé en parcourant la racine des données plutôt qu'en se le faisant dire, avec la taille de chaque élément. Le bouton 3 -- pas le bouton 1, qui veut dire « choisir » partout ailleurs -- jette la sauvegarde du jeu sélectionné. Effacer une table des meilleurs scores sans supprimer le jeu en est la raison habituelle. Engine Update:: Un Singe plus récent, quand le service en a un pour cette machine. Une bêta porte le numéro `3.00b2`, la deuxième bêta de la 3.00, et vient avant la 3.00 elle-même, si bien qu'une borne qui tourne sous une bêta se voit proposer la version finale le jour de sa publication. Affiche ce qui tourne et ce qui est proposé, et le bouton 1 le récupère, le vérifie par rapport à l'empreinte publiée par le service, le place à côté du Singe en cours sous le nom propre à la version, met l'ancien de côté sous `old-` et redémarre dessus. La mise de côté de l'ancien peut être refusée, par un dossier où cet utilisateur ne peut pas écrire ou par un antivirus qui tient le fichier ; l'outil le dit et continue, puisque le lanceur lance de toute façon le Singe le plus récent du dossier. Le nouveau Singe démarre avec `--refresh`, si bien que le dossier de support est réécrit par la version qui le possède désormais et que l'ancien est gardé sous `old-Singe-` ; un fichier qu'un Singe plus ancien fournissait et que celui-ci ne fournit pas ne peut pas traîner et embrouiller un jeu. Rien ne se passe avant ce bouton. Le bouton 3 interroge de nouveau le service. Le menu vérifie de lui-même une fois par jour et le signale par une ligne sous les détails du jeu ; `no_update_check = true` dans `settings.cfg` arrête cette vérification quotidienne, et l'outil marche toujours à la main. Online Account:: Connecter cette borne au service maître, créer un compte, récupérer un mot de passe et régler l'adresse du serveur. Voir <>. Get Games:: Le catalogue : ce que le service propose, ce qui est installé ici, et son téléchargement, sa mise à jour ou sa suppression. MIDI Ports:: Les ports d'entrée et de sortie de cette machine, ceux que Singe a ouverts, et les derniers messages arrivés. Le bouton 1 envoie une note, le bouton 3 cherche de nouveau les ports après qu'on a branché quelque chose. Rien n'est ouvert tant que cet outil ne le demande pas, si bien qu'une borne qui ne touche jamais au MIDI n'en paie jamais le prix. Frame Statistics:: Active et désactive l'overlay du développeur. Il reste affiché dans le jeu, dans le coin supérieur gauche. Voir xref:Reference.adoc#statsenable[statsEnable]. [[controls]] == Commandes Par défaut, Singe affecte les manettes comme s'il s'agissait de manettes Xbox. Si votre manette n'est pas reconnue, ou si vous voulez changer les affectations par défaut telles que Singe les voit, vous pouvez utiliser l'outil gratuit SDL2 Gamepad Tool, sur http://generalarcade.com/gamepadtool/. [[controlscfg]] === controls.cfg En plus de configurer votre manette, vous pouvez réaffecter toutes les entrées de Singe, pour Singe dans son ensemble ou pour un jeu en particulier, grâce aux fichiers `controls.cfg`. Pour déterminer l'affectation des entrées, Singe lit les réglages de configuration dans l'ordre suivant, et un fichier lu plus tard remplace un fichier lu plus tôt, entrée par entrée (voir <>) : . Les valeurs par défaut internes à Singe. . `controls.cfg` du dossier du script principal du jeu : ce qu'a fourni l'auteur du jeu. . `controls.cfg` du dossier depuis lequel Singe a été lancé : celui de la machine (le dossier `Singe` contient un modèle `controls.cfg.example` que vous pouvez copier). . `controls.cfg` du dossier au-dessus du dossier de données du jeu. . `controls.cfg` du dossier de données du jeu : le vôtre, pour ce seul jeu. Vous n'êtes pas obligé de préciser chaque option dans un fichier `controls.cfg` personnalisé. N'hésitez pas à ne fournir que les entrées que vous voulez changer. Après l'installation de Singe, vous trouverez un exemple de fichier de configuration des entrées dans `/Singe/controls.cfg.example`. Pour voir les options de configuration utilisables dans ce fichier, parcourez `/Singe/Framework.singe`. `--keymapfile` désigne un seul fichier à lire au lieu de faire cette recherche, ce qui sert à un front-end qui veut savoir sans le moindre doute quelles affectations un jeu a reçues. Chaque entrée `INPUT_` est une liste, et n'importe quel élément de cette liste actionne le contact. Une liste à l'intérieur de cette liste est un accord : deux à quatre touches ou boutons maintenus ensemble, qui actionnent le contact quand le dernier d'entre eux est enfoncé et le relâchent dès que l'un d'eux remonte. Une console portable sans touche Échap quitte ainsi sur Select et Start ensemble : [source,lua] ---- INPUT_QUIT = { SCANCODE.ESCAPE, { GAMEPAD_0.BUTTON_BACK, GAMEPAD_0.BUTTON_START } } ---- Chaque touche ou bouton d'un accord garde aussi son propre sens, si bien qu'appuyer sur Select et Start pour quitter de cette façon insère aussi une pièce et appuie sur Start au passage. Si vous voulez une façon de quitter qui marche toujours, utilisez plutôt `--quitchord`. Quand vous appuyez sur l'un de ses boutons, Singe attend un quart de seconde les autres avant de faire quoi que ce soit, si bien que quitter n'insère pas de pièce et n'appuie pas sur Start. Un jeu peut désactiver sa propre touche pour quitter, mais il ne peut pas désactiver `--quitchord`. [[devices]] === Tout périphérique est une manette Singe a une seule famille de manettes, de `GAMEPAD_0` à `GAMEPAD_3`, et chaque périphérique qu'il ouvre en fait partie. SDL n'appelle un périphérique une manette que s'il a une affectation pour lui, et une carte d'encodeur d'arcade, un spinner, un volant ou un joystick de vol n'en ont souvent aucune. Plutôt que de gérer un second type de périphérique avec ses propres noms, Singe écrit lui-même une affectation pour un tel périphérique, puis l'ouvre comme une manette ordinaire ; celui-ci atteint ainsi `controls.cfg`, `controllerGetAxis`, `controllerGetButton` et chaque contact `INPUT_*` exactement comme une manette reconnue. L'affectation qu'écrit Singe est directe : les axes du périphérique, dans l'ordre, deviennent le stick gauche, le stick droit puis les deux gâchettes ; ses boutons, dans l'ordre, deviennent `BUTTON_A`, `BUTTON_B`, `BUTTON_X`, `BUTTON_Y`, `BUTTON_BACK`, `BUTTON_GUIDE`, `BUTTON_START`, `BUTTON_LEFT_STICK`, `BUTTON_RIGHT_STICK`, `BUTTON_LEFT_BUMPER` et `BUTTON_RIGHT_BUMPER` ; et son premier chapeau devient la croix directionnelle. Un périphérique sans chapeau consacre plutôt ses quatre boutons suivants à la croix directionnelle. **Un périphérique qui a plus de commandes que le modèle de manette ne sait en nommer perd celles en trop** -- plus de six axes, plus de quinze boutons, ou un second chapeau -- et un périphérique dont les boutons ne sont pas câblés dans cet ordre les aura aux mauvais endroits. C'est le prix d'une seule famille au lieu de deux, et c'est simple à corriger : `--program` écrit dans la trace l'affectation qu'il a produite, au format de SDL, pour que vous puissiez la coller dans un `gamecontrollerdb.txt`, la réarranger et la faire utiliser à la place. `--mapjoysticks=false` désactive cette écriture ; un périphérique que SDL ne reconnaît pas n'est alors pas ouvert du tout, exactement comme dans les versions précédentes. [[gamecontrollerdb]] === gamecontrollerdb.txt SDL est livré avec une grande base de données d'affectations de manettes, et la communauté en tient une plus grande encore -- `gamecontrollerdb.txt`, sur https://github.com/mdqinc/SDL_GameControllerDB. Singe cherche ce fichier aux quatre mêmes endroits que `controls.cfg`, dans le même ordre (voir <>) : . le dossier du script principal du jeu ; . le dossier depuis lequel Singe a été lancé ; . le dossier au-dessus du dossier de données du jeu ; . le dossier de données du jeu. Chaque fichier trouvé est chargé, dans cet ordre, si bien que le fichier de la machine l'emporte sur celui qu'un jeu fournit, qu'un fichier du dossier de données du jeu l'emporte sur les deux, et que tous l'emportent sur la base de données propre à SDL. Seul un périphérique qu'aucun d'eux ne nomme reçoit l'affectation que Singe écrit pour lui : celle-ci est le dernier recours, jamais une rivale de vos fichiers. `--program` indique combien d'affectations chaque fichier a ajoutées. Les fichiers l'emportent aussi sur `SDL_GAMECONTROLLERCONFIG`, la variable d'environnement dans laquelle SDL prend des affectations, et que certains systèmes de consoles portables définissent pour leur manette intégrée. L'affectation d'ArkOS pour la R36S, par exemple, laisse de côté Select et Start, si bien qu'aucun jeu ne les voit ; une ligne dans `gamecontrollerdb.txt` pour la même manette les rétablit. SDL lit la variable une seule fois, au démarrage de Singe, donc cela vaut pour les fichiers que trouve le premier jeu. Un jeu lancé plus tard depuis le menu lit toujours les siens, mais une manette que nomme la variable garde l'affectation de la variable. Une ligne de ce fichier ressemble à ceci, et c'est exactement ce que la trace affiche pour un périphérique que Singe a affecté lui-même : ---- ff00d87a475300004900000000007603,Arcade Encoder,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b4,guide:b5,start:b6,leftx:a0,lefty:a1,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8, ---- [[deadzones]] === Zones mortes et gâchettes `DEAD_ZONE` dans `controls.cfg` indique de combien un axe doit bouger avant de compter comme un contact enfoncé, dans les unités brutes que signale SDL : `32767` à fond, si bien que la valeur par défaut de `15000` fait un peu moins de la moitié. Elle couvre chaque axe de chaque manette, y compris les deux gâchettes analogiques, et un script la lit dans `SINGE_DEAD_ZONE`. Deux réglages permettent d'affiner. `DEAD_ZONES` est une liste de paires `{ axis, dead zone }`, pour un axe à la fois, dans ces mêmes unités brutes, pour un stick raide ou une gâchette usée, sans toucher à tout le reste : [source,lua] ---- DEAD_ZONES = { { GAMEPAD_0.AXIS_LEFT_X, 8000 }, { GAMEPAD_1.AXIS_LEFT_TRIGGER, 30000 }, } ---- L'axe peut s'écrire comme l'axe lui-même ou comme l'une de ses deux directions (`GAMEPAD_0.AXIS_LEFT_X`, `AXIS_LEFT_X_L` et `AXIS_LEFT_X_R` désignent tous le même axe). Tout ce qui n'est pas listé garde `DEAD_ZONE`. `TRIGGER_THRESHOLD` indique la course qu'une gâchette analogique doit parcourir avant de compter comme un bouton, en *pourcentage de la course totale*, l'unité qu'utilise `-trigger-threshold` dans Hypseus, où sa valeur par défaut est `99.5`. Il s'applique aux deux gâchettes des quatre manettes. La valeur par défaut de Singe est `0` : les gâchettes restent alors sur `DEAD_ZONE`, si bien que rien ne change pour qui ne demande rien ; un script lit le résultat en unités brutes dans `SINGE_TRIGGER_THRESHOLD`. Les deux unités se convertissent directement : un pour cent vaut `32767 / 100` unités brutes, donc le `DEAD_ZONE` de `15000` de Singe fait `45.8` pour cent et les `99.5` pour cent d'Hypseus font `32603` unités brutes. `--trigger_threshold` règle le même nombre depuis la ligne de commande et l'emporte sur `controls.cfg` ; `DEAD_ZONES` l'emporte sur les deux, puisque c'est le plus précis. [[joymouse]] === Piloter la souris avec un stick Un jeu de pistolet optique sur une borne qui a un stick et pas de souris est injouable si le stick ne peut pas déplacer le curseur. `--joymouse` le lui permet : le **stick gauche de l'emplacement de manette 0** déplace le pointeur que voit le jeu, par le même `onMouseMoved` qu'atteint une vraie souris, et le curseur est maintenu à l'intérieur de l'image. `--js_range` est la vitesse, de `1` à `20`, `5` par défaut, mesurée en pixels vidéo par image à fond, si bien que `5` traverse une image de 720 pixels en deux secondes environ. L'axe obéit à sa propre zone morte, donc un stick qui dérive ne fait pas ramper le curseur. C'est désactivé par défaut, et c'est là que Singe diffère d'Hypseus : le `controls.cfg` fourni lie déjà ce stick à `INPUT_UP`, `INPUT_DOWN`, `INPUT_LEFT` et `INPUT_RIGHT`, et lui faire piloter aussi le curseur sans qu'on le demande surprendrait chaque jeu existant. `--joymouse=false` est le `-nojoymouse` d'Hypseus, et un script l'active et le désactive avec `joyMouseEnable` et le lit avec `joyMouseIsEnabled`. Un rechargement le remet où la ligne de commande l'avait laissé. [[mousedevices]] === Souris, pistolets, et qui décide `mouseSetMode(MOUSE_MANY)` est la décision d'un jeu de distinguer jusqu'à quatre souris, ce dont a besoin une borne à deux pistolets et qu'on ne peut pas imposer à un jeu qui ne fait jamais cet appel. `--manymouse` est la décision de l'utilisateur, et elle passe avant : le mode est actif dès le départ et `mouseSetMode(MOUSE_SINGLE)` ne le désactive plus. `--absolutes_only` ne garde que les périphériques qui signalent une position absolue, ce que fait un vrai pistolet optique et pas une souris ordinaire, si bien qu'une borne avec deux pistolets et une souris de bureau branchée ne se laisse pas troubler par la souris. Sachez comment il décide : **ManyMouse, la bibliothèque sur laquelle Singe s'appuie pour distinguer les souris, n'offre aucun moyen de demander à un périphérique de quel type il est** ; un périphérique compte donc comme absolu dès qu'il a signalé une position absolue, et pas avant. Un pistolet le fait dès son premier mouvement ; jusque-là il est muet, et un périphérique uniquement relatif reste muet pour de bon. L'option est donc un filtre sur le comportement observé plutôt que sur la classe du périphérique, et sur une machine où aucun périphérique ne signale jamais de position absolue, elle rend muettes toutes les souris. `SWITCH_MOUSE_DISCONNECT` est un contact comme les autres, sauf qu'aucune touche ni aucun bouton ne le produit : le moteur le déclenche quand une souris ou un pistolet optique est débranché, une fois comme un appui et une fois comme un relâchement, si bien qu'un jeu de tir peut l'annoncer à l'écran au lieu de sembler mort. C'est le contact du même nom d'Hypseus. `controls.cfg` ne le lie à rien ; liez-y aussi une touche si vous voulez voir ce que fait un jeu sans tirer sur un câble. [[hotkeys]] === Raccourcis `Alt-Enter` bascule entre plein écran et fenêtre pendant que le jeu tourne, comme dans Hypseus. Le jeu ne voit jamais la touche. Une fenêtre qui a démarré en plein écran exclusif (`--fullscreen`) y revient dans le mode d'affichage qu'on lui avait donné ; une fenêtre qui a démarré en mode fenêtré devient une fenêtre sans bordure couvrant le bureau. Rien d'autre n'a à changer avec elle : le moteur de rendu présente une taille logique en coordonnées vidéo et la met à l'échelle de la fenêtre telle qu'elle est désormais, le rectangle vidéo est construit dans ces mêmes coordonnées, et la cible de rotation a la taille de l'image et non celle de la fenêtre ; l'image, l'overlay, les GUI et l'affectation de la souris suivent donc tout seuls. Les autres contacts qu'un utilisateur peut actionner -- quitter, pause, capture d'écran, enregistrement, la console et la bascule de capture de la souris -- sont des affectations ordinaires de `controls.cfg` et sont décrits avec les noms `INPUT_*` dans le fichier d'exemple. [[recording]] === Enregistrer une vidéo `F10` lance l'enregistrement du jeu, image et son ensemble, et `F10` à nouveau l'arrête. Chaque enregistrement est un nouveau `singeNNN.mp4` dans le dossier de données du jeu, à côté des captures d'écran, et se lit dans tout ce qui lit un MP4. L'image est la fenêtre entière telle que vous la voyez, bandes noires comprises, et le son est tout ce que joue le jeu : musique, effets sonores et bande-son de la vidéo elle-même. Quand la machine a un encodeur vidéo matériel, Singe l'utilise, si bien qu'enregistrer coûte très peu au jeu : H.264 via VA-API sous Linux, VideoToolbox sous macOS, Media Foundation sous Windows, et V4L2 sur les cartes ARM qui en ont un. Partout ailleurs, il enregistre plutôt en MPEG-4, qui se lit partout mais donne des fichiers plus gros. La ligne `Recording` de la trace dit lequel il a utilisé. Une machine trop lente pour suivre laisse tomber des images de l'enregistrement plutôt que de ralentir le jeu, et la trace dit combien quand l'enregistrement s'arrête. Pour enregistrer plutôt une session entière, démarrez Singe avec `--record=FILENAME`. Ajoutez `--deterministic` et Singe enregistre chaque image et le son exact qui va avec, quel que soit le temps que prend chaque image à produire, sans rien jouer dans les haut-parleurs. C'est ainsi qu'on fait une vidéo parfaite d'une démo ou d'un mode attraction : cela va en général plus vite que le temps réel sur un ordinateur de bureau. [#_settings_and_options] == Réglages et options Presque tout ce que vous pouvez mettre sur la ligne de commande peut aussi aller dans un fichier de réglages. Réglez les choses une fois, et chaque jeu s'en sert. [[settings]] === Le fichier de réglages Presque tout ce qui se met sur la ligne de commande peut aussi s'écrire une fois pour toutes dans un fichier `settings.cfg` ; une borne n'a donc pas besoin d'un script de lancement qui porte la même douzaine d'options pour chaque jeu. C'est du Lua, comme `controls.cfg`, et Singe le cherche exactement aux quatre mêmes endroits, dans cet ordre : . `settings.cfg` du dossier du script principal du jeu. . `settings.cfg` du dossier depuis lequel Singe a été lancé (le dossier `Singe` contient un modèle `settings.cfg.example` que vous pouvez copier). . `settings.cfg` du dossier au-dessus du dossier de données du jeu. . `settings.cfg` du dossier de données du jeu. Chaque endroit est lu une fois, et un fichier lu plus tard l'emporte clé par clé : un fichier pour toute la machine peut ainsi régler l'affichage et les volumes, pendant qu'un fichier dans le dossier de données d'un jeu désactive le réticule de ce jeu. Vous n'avez pas à écrire chaque clé dans un fichier ; écrivez celles que vous voulez changer. Chaque clé est le nom long d'une option de ligne de commande sans les tirets du début ; il n'y a donc pas de second vocabulaire à apprendre : [source,lua] ---- -- Le settings.cfg propre à la borne screen = 2 -- le deuxième moniteur fullscreen = true volume_vldp = 80 haptic = 0 -- cette borne n'a pas de vibration idleexit = 900 -- rendre l'écran après quinze minutes sans activité startsilent = true ---- Une option qui ne prend pas de valeur sur la ligne de commande prend ici `true` ou `false` (`yes`, `no`, `on`, `off`, `1` et `0` sont acceptés aussi). En mettre une à `false` revient à l'omettre. Une option qui prend une valeur prend ici la même valeur que sur la ligne de commande, sous forme de nombre ou de chaîne. Une option, `--deterministic`, prend une valeur ou s'en passe, et sa clé fait de même : `deterministic = true` utilise le pas par défaut, `deterministic = 20` en indique un, et `deterministic = false` laisse l'option désactivée. [[configorder]] === Où sont lus les fichiers de configuration `controls.cfg`, `settings.cfg` et `gamecontrollerdb.txt` sont tous cherchés aux quatre mêmes endroits, dans le même ordre, et un fichier lu plus tard l'emporte sur un fichier lu plus tôt : . *Le dossier du script principal du jeu,* qui, pour un jeu empaqueté, se trouve dans son fichier `.game`. C'est ce qu'a fourni l'auteur du jeu, il est donc lu en premier : il fixe les valeurs par défaut du jeu, et rien de plus. . *Le dossier depuis lequel Singe a été lancé.* Les fichiers propres à la machine, comme la disposition des boutons d'une console portable, vont ici, et ils l'emportent sur ce que fournit un jeu. Un fichier ne remplace que ce qu'il nomme ; pour retirer d'un bouton une affectation faite par un jeu, nommez donc cette entrée : `INPUT_TEST_MODE = { SCANCODE.F2 }` dans le `controls.cfg` de la machine laisse le mode test sur le clavier seulement, quel que soit le bouton sur lequel un jeu l'avait mis. . *Le dossier au-dessus du dossier de données du jeu,* pour les fichiers partagés par tous les jeux qui utilisent ce dossier de données. . *Le dossier de données du jeu.* Vos propres fichiers pour un jeu, qui l'emportent sur tout le reste. Avec `--datadir=.`, le dossier de données est le dossier même du jeu ; dans ce cas, le fichier qui s'y trouve est lu une seule fois, comme celui du jeu. `--keymapfile` remplace toute la recherche de `controls.cfg` par un seul fichier nommé. [#_what_wins] === Ce qui l'emporte . La valeur par défaut intégrée. . Le fichier de réglages. . L'entrée `games.dat` du jeu, pour la poignée de réglages qu'elle porte (voir xref:Reference.adoc#gamesdat[games.dat]). . `machine.cfg`, pour le délai audio et la géométrie de l'image qu'enregistrent les outils de service (voir <>). . La ligne de commande, qui l'emporte toujours. Autrement dit, un fichier de réglages est un ensemble de valeurs par défaut, pas quelque chose que vous avez tapé : si une entrée `games.dat` donne à un jeu une résolution ou une bordure Sinden, cette entrée décrit toujours mieux le jeu qu'un fichier pour toute la machine. Tout ce qui est réellement tapé sur la ligne de commande l'emporte sur les deux. `machine.cfg` se place juste sous la ligne de commande parce que quelqu'un a réglé l'image en regardant ce moniteur, ce qui est une meilleure preuve que n'importe quel fichier écrit ailleurs ; le délai audio échappe complètement à cet ordre, puisqu'il s'ajoute au délai du jeu au lieu de le remplacer. Les options qui nomment le jeu (`--framefile`, `--disc`, `--entry`), nomment un dossier (`--gamedir`, `--datadir`), ou doivent agir avant que le fichier puisse être trouvé (`--help`, `--apiversion`, `--noconsole`, `--pack`, `--patch`, `--unpack`), ou ne valent que pour une seule exécution (`--record`, `--refresh`) ne peuvent pas être réglées dans un fichier de réglages. Une clé qui n'est pas une option, ou qui est l'une de celles-là, ou une valeur que l'option n'accepte pas, est une erreur qui nomme le fichier et la clé, si bien qu'une faute de frappe n'est jamais ignorée en silence : ---- settings.cfg: volume_vldpp is not an option. settings.cfg: datadir cannot be set here; it belongs on the command line. settings.cfg: Display scale must be between 25 and 100 percent. ---- Avec `--program` ou `--trace`, l'en-tête en haut de `trace.txt` liste chaque réglage appliqué ; on ne se demande donc jamais quel fichier un jeu en cours a reçu. [[commandlineoptions]] === Options de ligne de commande ---- Singe [OPTIONS] gameName ---- Le nom du jeu est le seul argument obligatoire. Ce peut être un script `.singe`, un dossier contenant un script du même nom (`MyGame` trouve `MyGame/MyGame.singe`), ou un jeu empaqueté (`MyGame.game` lance la première entrée du `games.dat` qu'il contient, `--entry=N` une autre). Un script ou un dossier lancé ainsi tourne aussi avec son entrée `games.dat` quand il y en a une qui le nomme (voir xref:Reference.adoc#gamesdat[games.dat]), si bien qu'un jeu se joue de la même façon depuis la ligne de commande que depuis le menu. Pour un jeu laserdisc (`--disc`) sans `--framefile`, Singe cherche à côté du script une vidéo de même nom de base, avec n'importe quelle extension que FFmpeg sait démultiplexer, puis un framefile `.txt`. Les options sont regroupées selon ce qu'elles font. [#_the_game_and_its_files] ==== Le jeu et ses fichiers Quel jeu tourne, où se trouvent le jeu et ses données, et sur quoi on y joue. [cols="1,2",options="header"] |=== | Option | Rôle | `-C`, `--canvas=WxH` | Taille du monde pour un jeu sans disque, 720x480 par défaut. Ignorée quand il y a un disque. | `-d`, `--datadir=PATHNAME` | Dossier pour tout ce qu'écrit Singe : index des vidéos, `trace.txt`, captures d'écran, sauvegardes, le `menu.dat` du menu. Un sous-dossier nommé d'après le dossier du jeu y est créé (pour un jeu empaqueté, un sous-dossier nommé d'après la base de données, puis, à l'intérieur, un autre nommé d'après le dossier du script). Par défaut, `data` dans le dossier des jeux. Singe 2.x écrivait plutôt à côté du jeu ; les dossiers de jeu peuvent être en lecture seule, donc plus rien n'y est écrit. | `-D`, `--disc` | Lire une vidéo laserdisc : celle que désigne `--framefile`, ou la vidéo trouvée à côté du script. Implicite avec `--framefile`. Sans cette option, une vidéo trouvée à côté du script est signalée et ignorée. | `-E`, `--entry=N` | Lancer la N-ième entrée du `games.dat` contenu dans un fichier `.game` (1 par défaut). Voir xref:Reference.adoc#singlefile[Jeux en un seul fichier]. | `-v`, `--framefile=FILENAME` | Fichier vidéo ou framefile à utiliser au lieu de celui trouvé à côté du script. | `-G`, `--gamedir=PATHNAME` | Le dossier qui contient les jeux, les fichiers `.game` empaquetés et le dossier de support `Singe`, quand l'exécutable se trouve ailleurs. Il devient le dossier de travail : le nom du jeu, un `--datadir` relatif et les noms de l'empaqueteur partent tous de lui ; les chemins absolus marchent tels quels. Par défaut, le dossier courant. | `-c`, `--showcalculated` | Afficher les plages d'images de chaque segment d'un framefile, pour le débogage. |=== [#_display] ==== Affichage La fenêtre, et la façon dont l'image la remplit. [cols="1,2",options="header"] |=== | Option | Rôle | `-a`, `--aspect=N:D` | Imposer le format d'image servant à choisir une taille de fenêtre (`4:3`, `16:9`, `16:10`). | `-f`, `--fullscreen` | Plein écran exclusif à la résolution du bureau. | `-w`, `--fullscreen_window` | Fenêtre sans bordure couvrant le bureau. | `--linearscale=BOOLEAN` | Lisser l'overlay quand la fenêtre le met à l'échelle (`true`) ou prendre le pixel le plus proche (`false`, qui garde le pixel art net). Accepte `true`, `false`, `yes`, `no`, `on`, `off`, `1` ou `0`. Un script le change en cours de route avec `setOverlayLinearScale`. Par défaut : `true`, ce que toutes les versions de Singe ont dessiné ; la valeur par défaut d'Hypseus est l'inverse. | `-k`, `--nologos` | Passer les écrans de démarrage. | `-r`, `--rotate=DEGREES` | Tourner toute la présentation dans le sens horaire de `0`, `90`, `180` ou `270` degrés, pour une borne dont l'écran est monté sur le côté. La vidéo, l'overlay, les GUI, la scène 3D et les particules tournent tous ensemble, un quart de tour échange la forme de l'image pour qu'une fenêtre en portrait soit remplie, et les positions de la souris et du pistolet optique sont tournées en sens inverse pour qu'un clic tombe toujours là où il est dessiné. Seuls les quatre angles droits sont acceptés. Un script peut le changer avec `vldpSetRotate`. | `--screen=N` | Ouvrir la fenêtre sur l'écran `N`, en comptant à partir de `1` comme le fait Hypseus. Un nombre plus grand que le nombre d'écrans liste les écrans présents et quitte. Par défaut : l'écran principal. | `-u`, `--stretch` | Étirer la vidéo pour remplir la fenêtre au lieu de garder son format d'image. | `-x`, `--xresolution=VALUE` | Largeur de la fenêtre. Si la hauteur est omise, elle est prise dans l'entrée correspondante de la table des résolutions intégrée. Une taille plus grande que l'écran -- demandée ici ou par le `games.dat` d'un jeu -- est réduite pour y tenir, en gardant sa forme, et la trace le signale. Sans affichage, avec `SDL_VIDEODRIVER=offscreen`, il n'y a pas d'écran auquel s'ajuster, et la fenêtre garde la taille demandée. | `-y`, `--yresolution=VALUE` | Hauteur de la fenêtre. |=== [#_picture_placement_bezels_and_guns] ==== Placement de l'image, bezels et pistolets Pour une borne : où se place l'image, l'illustration qui l'entoure, et la bordure que suit un pistolet Sinden. Voir <>. [cols="1,2",options="header"] |=== | Option | Rôle | `-B`, `--bezel=FILENAME` | Dessiner une illustration de borne autour de l'image. Le fichier est cherché dans le dossier `bezels` du dossier du jeu (un jeu empaqueté peut porter le sien), puis dans le dossier `bezels` du dossier de données ; `--bezeldir` désigne un autre dossier. Tout format que lit SDL_image convient, et la transparence est conservée. Un fichier compagnon posé à côté dit où va l'image à l'intérieur ; sans lui, l'image garde toute la fenêtre et `--shiftx`, `--shifty` et `--scalefactor` la placent. Une illustration introuvable met fin au programme. Voir <>. | `-I`, `--bezeldir=PATHNAME` | Le dossier qui contient l'illustration de `--bezel`, à la place de `bezels`. Relatif au dossier du jeu, ou absolu. Seul ce dossier est fouillé. Voir <>. | `-F`, `--bezelflip` | Dessiner l'illustration du bezel devant l'image au lieu de derrière, ce que fait Hypseus avec ses propres bezels ; la transparence de l'illustration est alors le trou à travers lequel on voit le jeu. Sans cette option, l'illustration est derrière tout et l'image couvre sa découpe. Un script choisit avec `setOverlayOnTop` si l'overlay et les GUI restent au-dessus de l'illustration. Voir <>. | `-b`, `--scalefactor=PERCENT` | Réduire l'image autour de son centre à `PERCENT` (`25` à `100`) de la fenêtre, pour les écrans qui perdent leurs bords à cause de l'overscan. Les positions de la souris et du pistolet optique suivent l'image réduite. Un script peut le changer pendant le jeu avec `vldpSetScale`. Se combine avec `--shiftx`, `--shifty`, `--rotate` et `--sindengun` ; voir <>. | `-X`, `--shiftx=PERCENT` | Déplacer l'image horizontalement dans l'espace que lui a laissé `--scalefactor`, de `-100` (collée à gauche) à `100` (collée à droite), `0` au centre. Comme dans Hypseus, le décalage est un pourcentage de cet espace et rien de plus ; à `--scalefactor=100`, il n'y a donc pas d'espace et le décalage ne fait rien : réduisez d'abord l'échelle. Voir <>. | `-Y`, `--shifty=PERCENT` | Déplacer l'image verticalement dans l'espace que lui a laissé `--scalefactor`, de `-100` (collée en haut) à `100` (collée en bas), `0` au centre. Il ne fait rien à pleine échelle, pour la même raison. Voir <>. | `-S`, `--sindenedge=WHERE` | Où se place la bordure Sinden : `video` la dessine autour de l'image, `window` au bord de l'écran. Sans l'option, c'est le bezel qui décide : une illustration autour de l'image met la bordure au bord de la fenêtre, parce que la caméra du pistolet voit tout l'écran, et sans illustration elle entoure l'image comme elle l'a toujours fait. Au bord de la fenêtre, les deux anneaux sont dessinés comme des anneaux, en tout dernier, si bien que l'illustration entre eux et l'image reste visible. Voir <>. | `-g`, `--sindengun='PARAMS'` | Dessiner la bordure que suit un pistolet optique Sinden et ramener les positions de la souris et du pistolet dans l'image qu'elle entoure : l'anneau noir, s'il est donné, longe le bord de la vidéo, l'anneau blanc se place à l'intérieur, et le jeu est dessiné au milieu. `PARAMS` est une seule liste de nombres entre guillemets : `WW` (largeur de la bordure blanche en pixels vidéo) ; `WW WB` (largeur du blanc, puis une bordure noire à l'extérieur) ; `RW GW BW WW` (une couleur et une largeur de bordure personnalisées) ; `RW GW BW WW WB` (la même chose plus une largeur de noir) ; ou `RW GW BW WW RB GB BB WB` (couleurs et largeurs personnalisées pour les deux). Une bordure qui ne laisse pas de place au jeu (deux fois les largeurs du blanc et du noir réunies atteignant le plus petit côté de la vidéo), ou une largeur négative, met fin au programme avec un message. Les anneaux sont dessinés autour de ce qu'ont laissé `--shiftx`, `--shifty` et `--scalefactor`, si bien qu'une bordure reste une bordure quelle que soit la place de l'image ; voir <>. |=== [#_sound] ==== Son [cols="1,2",options="header"] |=== | Option | Rôle | `--altaudio=SUFFIX` | Lire `.ogg` à côté de la vidéo du disque au lieu de l'audio qu'elle contient, pour une édition dont les autres langues sont fournies en fichiers séparés : `--altaudio=-es` à côté de `game.m2v` lit `game-es.ogg`. Tous les segments d'un framefile basculent ensemble. Un fichier absent laisse jouer l'audio propre au jeu et affiche un avertissement. La clé `AUDIO_SUFFIX` de `games.dat` fait de même pour un jeu, et un script la change en cours de route avec `discAudioSuffix`. Par défaut : aucun. | `-o`, `--audio=TRACK` | Piste audio par défaut (numérotée à partir de zéro) pour les vidéos qui en ont plusieurs, comme les éditions multilingues. | `-A`, `--audiodelay=MS` | Compenser un son entendu `MS` millisecondes plus tard que ce que le moteur peut mesurer (négatif quand il est entendu en avance), de `-1000` à `1000`. Voir xref:Reference.adoc#audiosync[Synchronisation audio]. | `-s`, `--nosound` | Couper tout le son. | `--soundfont=FILE` | La SoundFont (`.sf2`) avec laquelle les fichiers MIDI sont synthétisés. Singe n'en fournit aucune, parce qu'une bonne pèse des dizaines de mégaoctets, pour un format que presque aucun jeu n'utilise. Sans cette option, il cherche `Singe/soundfont.sf2` -- un jeu empaqueté peut donc porter la sienne -- puis aux endroits où une distribution en installe une. La ligne `SoundFont:` de l'en-tête de la trace dit laquelle a été utilisée, ou qu'aucune n'a été trouvée. Voir xref:Reference.adoc#midi[MIDI]. Par défaut : la recherche. | `--startsilent` | Démarrer en muet et le rester jusqu'à la première entrée, quelle qu'elle soit, puis jouer aux volumes configurés. Pour une borne en mode attraction dans une pièce calme. `--nosound` passe avant. Par défaut : désactivé. | `-e`, `--volume_nonvldp=PERCENT` | Volume des effets sonores et des vidéos supplémentaires, de `0` à `100`. | `-l`, `--volume_vldp=PERCENT` | Volume du laserdisc, de `0` à `100`. |=== [#_input] ==== Entrées Voir <>. [cols="1,2",options="header"] |=== | Option | Rôle | `--absolutes_only` | Ne garder que les souris qui signalent une position absolue, ce que fait un vrai pistolet optique et pas une souris ordinaire. On ne peut pas demander à ManyMouse ce qu'est un périphérique, si bien qu'un périphérique compte comme absolu dès qu'il a signalé une position absolue, et pas avant ; voir <>. Hypseus l'écrit `-absolutes-only` ; le nom prend ici un tiret bas parce qu'une clé de fichier de réglages doit être un nom Lua. Par défaut : désactivé. | `--gamepad_reorder=DIGITS` | Quelle manette physique remplit quel emplacement de manette, sous forme de positions d'énumération comptées à partir de `0`, une pour chaque emplacement tour à tour : `--gamepad_reorder=10` fait de la deuxième manette trouvée le joueur un et de la première le joueur deux. S'écrit en chiffres collés (`3210`) ou séparés par des virgules ou des espaces, comme l'écrit Hypseus ; une position répétée est refusée. Les positions non nommées remplissent les emplacements restants, dans l'ordre où SDL les a trouvées, et une position sans manette derrière elle laisse son emplacement vide. Par défaut : l'ordre de SDL. | `--haptic=STEP` | Le palier de vibration le plus fort qu'un jeu peut utiliser, de `0` à `4`. `0` coupe complètement la vibration, et un nombre plus bas modère un jeu qui en demande plus : `controllerDoRumble` ne vibre jamais plus fort que cela. Par défaut : `4`, soit chaque palier qu'un jeu demande. | `--joymouse=BOOLEAN` | Laisser le stick gauche de l'emplacement de manette `0` piloter le curseur de la souris, pour un jeu de pistolet optique sur une borne sans souris. `--joymouse=false` est le `-nojoymouse` d'Hypseus, et un script le règle avec `joyMouseEnable()`. Voir <>. Par défaut : `false`, alors qu'Hypseus l'active par défaut -- le `controls.cfg` fourni lie déjà ce stick aux quatre directions. | `--js_range=SPEED` | La vitesse à laquelle ce stick le pilote, de `1` à `20`, en pixels vidéo par image à fond. Par défaut : `5`, comme dans Hypseus. | `--keymapfile=FILENAME` | Lire les affectations des commandes dans ce fichier au lieu de chercher `controls.cfg` aux quatre endroits, pour qu'un front-end soit certain des affectations qu'un jeu a reçues. Les valeurs par défaut intégrées s'appliquent toujours en dessous, donc un fichier partiel marche quand même, et un fichier absent met fin au programme. Par défaut : la recherche aux quatre endroits, décrite dans <>. | `--manymouse` | Distinguer jusqu'à quatre souris quoi que demande le jeu, ce dont une borne à deux pistolets a besoin avec un jeu qui n'appelle jamais lui-même `mouseSetMode(MOUSE_MANY)`. Le choix de l'utilisateur passe avant celui du jeu : `mouseSetMode(MOUSE_SINGLE)` ne le désactive plus. Par défaut : désactivé, et c'est le jeu qui décide. | `--mapjoysticks=BOOLEAN` | Écrire une affectation de manette pour un périphérique que SDL ne reconnaît pas, pour qu'un encodeur d'arcade, un spinner, un volant ou un joystick de vol s'ouvre comme `GAMEPAD_0` à `GAMEPAD_3`, comme n'importe quoi d'autre. `false` laisse un tel périphérique fermé, comme dans les versions précédentes. Voir <>. Par défaut : `true`. | `-n`, `--nocrosshair` | Demander au jeu de ne pas dessiner son propre réticule. Exposé aux scripts par `singeWantsCrosshairs()`. | `--nogamepad` | Ignorer toutes les manettes, le pendant de `--nomouse`. Aucune n'est ouverte et aucun événement de manette n'atteint le jeu, si bien qu'un encodeur d'arcade bloqué ne peut rien enfoncer. Par défaut : désactivé. | `-m`, `--nomouse` | Désactiver entièrement la souris et les pistolets optiques. | `--quitchord=BUTTONS` | Les boutons de la première manette qui font quitter quand on les maintient ensemble, quelle que soit l'affectation du jeu et même s'il a désactivé sa touche pour quitter : la porte de sortie sur une console portable sans clavier. Un jeu revient au menu depuis lequel il a été lancé, et le menu quitte Singe. Deux à quatre noms de boutons de manette SDL joints par `+`, comme `back+start` (Select et Start) ; les noms sont `a`, `b`, `x`, `y`, `back`, `guide`, `start`, `leftstick`, `rightstick`, `leftshoulder`, `rightshoulder`, `dpup`, `dpdown`, `dpleft` et `dpright`, tels que les donne l'affectation de la manette, et `--program` écrit dans la trace le nom de chaque bouton enfoncé. Un appui sur l'un des boutons de l'accord attend un quart de seconde les autres avant de faire ce qu'il fait normalement, si bien que Start ne lance pas un jeu depuis le menu au moment où on le quitte. Sa place est dans le `settings.cfg` de la machine. Par défaut : aucun. | `--trigger_threshold=PERCENT` | La course qu'une gâchette analogique doit parcourir avant de compter comme un bouton, en pourcentage de la course totale -- l'unité d'Hypseus, dont la valeur par défaut est `99.5`. `0` laisse les gâchettes sur `DEAD_ZONE`, ce que Singe leur a toujours donné. L'emporte sur `TRIGGER_THRESHOLD` dans `controls.cfg` ; `DEAD_ZONES` l'emporte sur les deux. De `0` à `100` ; voir <>. Par défaut : `0`. | `--xratio=FACTOR` | L'échelle horizontale qu'un jeu de pistolet optique lit avec `ratioGetX()` pour étirer ses propres coordonnées de pistolet sur un écran dont la forme ne correspond pas à la vidéo. Singe n'en fait rien ; c'est le jeu qui fait le calcul, exactement comme dans Hypseus. De `0` à `100`, gardé à deux décimales comme le fait Hypseus. Par défaut : `0`, que chaque jeu qui le lit traite comme `1`. | `--yratio=FACTOR` | La même chose pour `ratioGetY()`. Par défaut : `0`. |=== [#_video_decoding_and_performance] ==== Décodage vidéo et performances Surtout pour les petites machines ; voir <>. [cols="1,2",options="header"] |=== | Option | Rôle | `--deinterlace=MODE` | Ce que reçoit une image entrelacée : `auto` (la valeur par défaut) ne désentrelace que les images que le fichier marque comme entrelacées, `on` désentrelace chaque image, pour un fichier dont les indicateurs sont faux, et `off` ne touche jamais à l'image. Un laserdisc contenait des trames entrelacées, et un rip qui les a gardées montre un effet de peigne sur un écran progressif ; un rip désentrelacé au moment de sa création n'a besoin de rien ici. Une image sort pour chaque image qui entre, si bien que les numéros d'image ne bougent jamais. Par défaut : `auto`. | `--monochrome` | Démarrer avec l'image du disque en gris. L'overlay, les GUI et la scène 3D gardent leur couleur ; un script fait la même chose avec `vldpSetMonochrome`, et la défait. Par défaut : désactivé. | `--scenequality=LEVEL` | Ce que dessine la scène 3D : `high`, tout ce qu'un jeu demande, ou `low` pour un petit GPU -- une console portable ou un des premiers Raspberry Pi -- qui dessine la scène à demi-résolution dans chaque sens et laisse de côté l'anticrénelage et le bloom, quoi que demande le jeu. L'image 3D est plus douce et les objets brillants n'ont pas de halo, et cela tourne beaucoup plus vite là où le GPU était la limite ; le disque, l'overlay et les GUI ne sont pas touchés. Sa place est dans le `settings.cfg` de la machine plutôt que sur la ligne de commande d'un jeu, puisqu'il décrit la machine. Par défaut : `high`. | `-H`, `--softwarevideo` | Décoder la vidéo en logiciel même quand la plateforme offre un décodeur matériel (VA-API ou VDPAU sous Linux, le décodeur V4L2 sur le Pi, D3D11VA sous Windows, VideoToolbox sous macOS). Servez-vous-en pour savoir si le chemin matériel est en cause quand une vidéo se comporte mal ; la trace du programme dit quel décodeur est utilisé. | `--zerocopy=BOOLEAN` | Confier les images vidéo décodées par le matériel directement au GPU au lieu de les copier par le CPU : le décodeur MPP de Rockchip et VA-API sous Linux, dessinés avec OpenGL ES. Cela économise l'essentiel du coût de la vidéo plein écran sur une petite machine. Singe revient de lui-même à la copie quand le pilote refuse une image, ou quand un jeu lit ou modifie les pixels de l'image, et la trace du programme dit ce qu'il fait ; `false` le fait copier dès le départ, pour savoir si ce chemin est en cause. Par défaut : `true`. |=== [#_cabinets_and_front_ends] ==== Bornes et front-ends [cols="1,2",options="header"] |=== | Option | Rôle | `--apiversion` | Écrire sur la sortie standard une ligne lisible par une machine qui décrit cette version, puis quitter, pour les front-ends. Voir <>. Rien d'autre n'est affiché. | `--fvalue=NUMBER` | Un nombre transmis par le lanceur au jeu, qui le lit avec `getFValue()`. Singe n'en fait rien. De `0` à `100000`, gardé à trois décimales comme le fait Hypseus. Par défaut : `0`. | `-h`, `--help` | Afficher le résumé des options et quitter. | `--idleexit=SECONDS` | Quitter après `SECONDS` sans aucune entrée -- ni touche, ni bouton, ni axe de manette, ni souris. Pour une borne en mode attraction qui doit rendre l'écran. `0` ne quitte jamais. De `0` à `86400`. Par défaut : `0`. | `--no_update_check` | Ne jamais demander au service s'il existe un Singe plus récent. Sinon, le menu vérifie une fois par jour et montre ce qu'il a trouvé sous les détails du jeu ; l'outil Engine Update marche toujours à la main. Par défaut : désactivé, donc la vérification quotidienne a lieu. | `-z`, `--noconsole` | Ne rien afficher (et n'ouvrir aucune fenêtre de console sous Windows). | `--refresh` | Mettre de côté le dossier de support `Singe` sous `old-Singe-`, d'après la version qui l'a écrit, et en écrire un neuf. Pour les mises à jour : un fichier qu'une version plus ancienne fournissait et que celle-ci ne fournit pas reste dans le dossier mis de côté au lieu de traîner dans celui qui sert. Rien n'est supprimé, et un second lancement met le sien de côté sous `old-Singe--1`. L'outil Engine Update passe cette option au Singe sur lequel il redémarre. |=== [#_making_and_testing_games] ==== Créer et tester des jeux Voir <> pour les traces. [cols="1,2",options="header"] |=== | Option | Rôle | `--deterministic[=MS]` | Pour les tests seulement : ignorer le temps réel et faire tourner tout le moteur sur une horloge virtuelle qui avance de `MS` millisecondes à chaque image, si bien que le même numéro d'image désigne toujours le même instant. Le disque suit lui aussi l'horloge virtuelle, chacune de ses images durant le temps qu'elle vaut, et les générateurs aléatoires sont initialisés avec le même nombre, si bien qu'une session se répète au pixel près. La valeur est facultative et sert à la fois de pas et de graine, de `1` à `1000`. Par défaut quand l'option est donnée sans valeur : `15`, la durée d'image qu'implique la fréquence propre du moteur. La régulation du rythme n'a aucun sens dans ce mode, le son non plus, sauf si `--record` est aussi donné, auquel cas il est généré au pas de l'image ; voir xref:Reference.adoc#deterministic[Mode de test déterministe]. Par défaut : désactivé. | `-P`, `--pack=DIRECTORY` | Empaqueter le jeu de `DIRECTORY` dans la base de données dont le nom suit les options, puis quitter. Voir xref:Reference.adoc#singlefile[Jeux en un seul fichier]. | `-T`, `--patch=GAME.game` | Remplacer des fichiers du jeu empaqueté à partir du dossier ou de la base de données de correctif dont le nom suit les options, puis quitter. | `--perfsync` | Avec `--program`, attendre que le GPU ait fini chaque étape d'une image avant de chronométrer la suivante, pour que les lignes Perf disent à quelle étape appartient le temps du GPU au lieu de tout laisser dans `present`. Tout tourne plus lentement tant qu'elle est active : c'est pour mesurer, pas pour jouer ; voir <>. Par défaut : désactivé. | `-p`, `--program` | Écrire une trace de l'activité du moteur dans la console et dans `trace.txt`, dans le dossier de données. Le fichier commence par un en-tête qui décrit la machine ; voir xref:Reference.adoc#traceheader[L'en-tête de la trace]. Toutes les cinq secondes, il dit aussi où est passé le temps de l'image ; voir <>. | `--record=FILENAME` | Enregistrer toute la session, image et son, dans un MP4 à `FILENAME`, de la première image jusqu'à ce que Singe quitte. Avec `--deterministic`, chaque image est gardée et le son est généré pas à pas avec l'image, si bien que les deux correspondent exactement et que rien ne s'entend pendant l'exécution. Voir <>. Par défaut : désactivé. | `-R`, `--reload` | Surveiller les fichiers de script non empaquetés du jeu et relancer le jeu de zéro quand l'un d'eux change ; `F5` fait de même à la demande. Un script qui ne compile pas reste surveillé, si bien qu'enregistrer la correction le recharge. Pour travailler sur un jeu ; voir xref:Reference.adoc#reloading[Recharger pendant que vous travaillez]. | `-t`, `--trace` | Écrire une trace de chaque appel à l'API Lua, avec la ligne de script qui l'a fait, dans la console et dans `trace.txt`. Le fichier commence par un en-tête qui décrit la machine ; voir xref:Reference.adoc#traceheader[L'en-tête de la trace]. | `-U`, `--unpack=GAME.game` | Écrire les fichiers du jeu empaqueté dans le dossier dont le nom suit les options, puis quitter. Une base de données dont les noms stockés atterriraient hors de ce dossier est refusée. |=== Les options peuvent s'écrire `-x 640`, `-x640` ou `--xresolution=640`. Les valeurs numériques sont validées ; une mauvaise valeur affiche le texte d'utilisation et quitte. Les options récentes n'ont pas de lettre courte : l'alphabet était épuisé, et une lettre prise au hasard n'aiderait personne. Tout ce qui figure ici, sauf les options qui nomment le jeu, nomment un dossier ou doivent agir avant qu'un fichier puisse être trouvé, peut aussi être réglé dans un fichier de réglages ; une borne n'a donc pas besoin d'un script de lancement par jeu. Voir <>. [[apiversion]] === La ligne de version `--apiversion` affiche une ligne et quitte avec le code `0` : ---- singe version=3.00 protocol=1 ---- C'est un contrat pour les front-ends, et sa forme ne changera pas : * La ligne se termine par un saut de ligne et c'est la seule chose écrite sur la sortie standard. Rien d'autre n'est affiché, quoi qu'il y ait d'autre sur la ligne de commande. * Le premier champ est toujours `singe`. * Chaque champ suivant est de la forme `key=value`, séparé du précédent par une espace, sans espace à l'intérieur d'un champ. * `version` est la version publiée, le même numéro que celui qu'affiche le bandeau. * `protocol` est la version du format de cette ligne. Il ne passe à `2` que si les règles ci-dessus doivent un jour changer. * Les versions futures peuvent ajouter des champs. Un lecteur doit ignorer les clés qu'il ne connaît pas au lieu de les traiter comme une erreur. [[cabinet]] == Configurer une borne Les bornes d'arcade ont besoin de quelques choses dont un ordinateur de bureau se passe : éloigner l'image des bords que le moniteur cache, la tourner pour un écran placé de côté, une illustration autour, une bordure pour un pistolet optique Sinden, et un afficheur de scores. Vous n'avez besoin de ce chapitre que si vous construisez une borne. Réglez tout cela une fois dans le `settings.cfg` de la borne, ou utilisez l'outil Display du menu (voir <>) pour ajuster l'image en la regardant. [[videorect]] === Le rectangle vidéo Tout ce que montre un jeu -- le disque, l'overlay, les GUI, la scène 3D et les particules -- est dessiné dans un seul rectangle, et une poignée d'options décident où se trouve ce rectangle. Elles s'appliquent dans cet ordre : . *La fenêtre, ou la découpe du bezel.* Le rectangle part de la fenêtre entière. Singe travaille dans les coordonnées propres de la vidéo et laisse la fenêtre les encadrer de bandes noires (`--stretch` remplit à la place), si bien que rien ici ne dépend de la taille de la fenêtre. Quand `--bezel` a chargé une illustration qui déclare une découpe, le rectangle part plutôt de ce trou, et tout ce qui suit place l'image à l'intérieur ; voir <>. . *`--scalefactor`.* Le rectangle se réduit à ce pourcentage de sa taille de départ, autour de son propre centre. . *`--shiftx` et `--shifty`.* Le rectangle se déplace ensuite dans l'espace que l'échelle a laissé, `-100` collé contre un côté et `100` collé contre l'autre, ce qui est le sens des `-shiftx` et `-shifty` d'Hypseus. Deux conséquences en découlent, qui valent d'être connues : l'image ne peut jamais être poussée hors de l'écran, et *à `--scalefactor=100`, il n'y a pas d'espace et un décalage ne fait rien du tout*. Pour déplacer l'image sur un écran mal monté, réduisez d'abord l'échelle : `--scalefactor=90 --shiftx=-100` colle l'image réduite contre la gauche. . *`--sindengun`.* La bordure s'applique en dernier, à ce que le décalage et l'échelle ont laissé. L'anneau noir prend le bord du rectangle, l'anneau blanc se place à l'intérieur, et le jeu va à l'intérieur des deux, si bien qu'une bordure reste une bordure quelle que soit la façon dont l'image a été placée. Une échelle assez petite pour ne laisser aucune place au jeu serre les deux anneaux au lieu de l'avaler. Avec une illustration de bezel chargée, la bordure va plutôt au bord de la fenêtre et laisse à l'image la taille qu'elle avait déjà ; `--sindenedge` tranche dans un sens comme dans l'autre. `--rotate` ne fait pas partie de cet ordre. Chaque image est dessinée sans rotation, puis l'image finie est tournée dans le sens horaire d'un seul bloc ; un décalage déplace donc l'image le long des axes propres de la vidéo et tourne avec elle. Un quart de tour échange aussi la forme de la zone présentée, si bien qu'une fenêtre en portrait est remplie au lieu d'être réduite à une bande entre deux bandes noires. Les positions de la souris et du pistolet optique suivent le même chemin à rebours : la rotation est retirée d'abord, puis la position est ramenée dans le rectangle, si bien qu'un clic tombe là où le joueur le voit, quelle que soit la combinaison de ces options. `vldpGetScale`, `vldpSetScale`, `vldpGetRotate` et `vldpSetRotate` permettent à un script de changer l'échelle et la rotation pendant le jeu ; le décalage est un réglage d'affichage et n'a pas d'appel de script. Aucun d'eux n'est une clé de `games.dat` : comme `--scalefactor`, ils décrivent l'écran du joueur, pas le jeu. [[bezels]] === Bezels Un bezel (habillage d'écran) est l'illustration qui entoure l'écran d'une borne d'arcade. Singe en dessine un à partir d'un seul fichier image, avec l'image du jeu dans un trou découpé dedans, et peut montrer un afficheur de scores d'arcade dans l'espace que cela laisse. Trois options le contrôlent, et elles suivent la convention d'Hypseus, si bien que la ligne de commande d'une borne passe de l'un à l'autre sans changement. `--bezel cabinet.png` désigne l'illustration. Elle est cherchée dans cet ordre : . `bezels/cabinet.png` dans le dossier du jeu -- à l'intérieur d'un `.game` empaqueté, sa propre copie, si bien qu'un jeu peut emporter son bezel avec lui ; . `bezels/cabinet.png` dans le dossier de données, où l'illustration d'un utilisateur peut vivre sans toucher à un dossier de jeu en lecture seule. `--bezeldir art/cabinets` remplace le dossier `bezels` par celui qu'il désigne, relatif au dossier du jeu ou absolu, et alors seul ce dossier est fouillé. Tout format que lit SDL_image convient (`.png` est le choix raisonnable, parce que la transparence compte). Une illustration que l'option désigne et que Singe ne trouve pas met fin au programme au lieu de le laisser tourner sans elle. L'illustration est dessinée sur toute la fenêtre, quelle que soit la forme de l'une ou de l'autre, si bien qu'elle s'étire avec la fenêtre exactement comme l'image. Donnez-lui le format d'image auquel vous comptez jouer. [#_the_cutout] ==== La découpe À côté du fichier image, et nommé d'après lui, un fichier compagnon dit où va l'image du jeu : `bezels/cabinet.png` est décrit par `bezels/cabinet.cfg`. C'est un fichier Lua, comme `controls.cfg`, qui définit une table dans les *propres pixels* de l'illustration : [source,lua] ---- -- Le trou de cabinet.png où l'image est dessinée, en pixels propres à l'illustration. CUTOUT = { x = 200, y = 120, width = 800, height = 500 } ---- Les quatre champs sont obligatoires et le rectangle doit se trouver à l'intérieur de l'illustration ; un fichier compagnon qui ne s'exécute pas, ou qui désigne un rectangle hors de l'image, met fin au programme avec un message. Comme les nombres sont ceux de l'illustration, ils restent justes à n'importe quelle taille de fenêtre : l'image et le trou sont mis à l'échelle ensemble. Avec une découpe, l'image du jeu est dessinée dans ce trou -- étirée pour le remplir, si bien que le trou décide de la forme de l'image -- et `--scalefactor`, `--shiftx` et `--shifty` agissent alors *à l'intérieur*, en réduisant et en poussant l'image dans le trou. Sans fichier compagnon, l'image garde toute la fenêtre, exactement comme sans bezel, et ces trois options la placent comme elles l'ont toujours fait. Voir <>. Le trou lui-même doit être transparent dans l'image. Par défaut, Singe dessine l'illustration derrière l'image du jeu, si bien qu'un milieu opaque serait simplement recouvert, mais `--bezelflip` met l'illustration devant, et seule sa transparence laisse alors passer le jeu. [#_draw_order] ==== Ordre de dessin Sans `--bezelflip`, l'illustration est la première chose dessinée dans l'image : l'image du jeu, l'overlay, les GUI, la scène 3D et les particules se dessinent tous par-dessus. Avec `--bezelflip`, l'illustration se dessine au contraire devant l'image du jeu, ce qui est l'ordre qu'utilise Hypseus pour ses propres bezels, si bien qu'un cadre aux bords doux ou découpés recouvre correctement l'image. Un script décide de ce qui arrive à l'overlay dans ce cas : xref:Reference.adoc#setoverlayontop[`setOverlayOnTop(true)`] dessine l'overlay et les GUI au-dessus de l'illustration, et `false` (la valeur par défaut, et celle d'Hypseus) laisse l'illustration au-dessus d'eux. Avec l'illustration derrière l'image, le réglage ne change rien, parce que tout est déjà au-dessus. xref:Reference.adoc#mainbezelloaded[`mainBezelLoaded()`] indique à un script si une illustration est chargée et lui donne l'identifiant de l'illustration, le même nombre que celui que signale Hypseus, si bien qu'un jeu écrit pour un bezel particulier peut le reconnaître. Les GUI en espace écran et le panneau des scores se dessinent toujours au-dessus de l'illustration, puisque tout leur intérêt est de s'y poser. [#_the_sinden_border] ==== La bordure Sinden Un pistolet optique Sinden surveille l'écran à la recherche d'une bordure lumineuse. Avec une illustration de bezel chargée, cette bordure a sa place au *bord de la fenêtre*, pas autour de l'image, parce que la caméra du pistolet voit tout l'écran ; c'est donc là que `--sindengun` la met dès qu'un bezel est chargé. Elle y est dessinée comme deux anneaux, après tout le reste, si bien que l'illustration entre la bordure et l'image reste visible et que rien ne peint par-dessus l'anneau blanc. Sans bezel, la bordure entoure l'image, comme elle l'a toujours fait, et la réduit. `--sindenedge video` ou `--sindenedge window` force ce choix dans un sens ou dans l'autre : une borne à pistolets dont l'illustration n'est qu'un cadre fin peut quand même vouloir la bordure autour de l'image, et une borne sans aucune illustration peut la vouloir au bord de l'écran. [#_the_score_panel] ==== Le panneau des scores Seize des jeux Singe d'Hypseus peuvent piloter un afficheur de scores d'arcade : les crédits, et un score et un nombre de vies pour chacun des deux joueurs. Dans Singe, cet afficheur est le document RmlUi `Singe/scoreBezel.rml`, mis en forme par `Singe/scoreBezel.rcss`, tous deux écrits à côté des autres fichiers de support. Comme tout ce que contient le dossier `Singe`, ils sont réécrits à chaque démarrage, si bien que les modifier ne change rien bien longtemps : un jeu qui veut un autre aspect fournit ses propres copies, un `scoreBezel.rml` à côté de son script qui renvoie à une feuille de style à lui, et Singe utilise celles-ci à la place. Le style fourni imite un afficheur à sept segments : chaque affichage montre ses chiffres faiblement allumés derrière la valeur en cours, comme le fait un vrai afficheur. Le panneau est *désactivé* tant qu'un jeu ne le demande pas avec xref:Reference.adoc#scorebezelenable[`scoreBezelEnable(true)`], comme Hypseus le livre aussi ; un jeu qui ne le demande jamais se comporte donc exactement comme avant et dessine son propre afficheur de scores avec des sprites. xref:Reference.adoc#scorebezelgetstate[`scoreBezelGetState()`] est la question que chacun de ces jeux pose en premier. L'emplacement est décidé pour vous : le panneau prend la plus haute des bandes que l'image laisse au-dessus et en dessous d'elle -- l'espace que laisse en général la découpe d'un bezel -- en se centrant sur l'image, et se place le long du bas de l'image quand aucune des deux bandes n'est assez haute pour le contenir. Il est dessiné comme une GUI en espace écran, si bien qu'un jeu peut poser ses propres GUI sur l'illustration à côté de lui avec xref:Reference.adoc#guidrawscreen[`guiDrawScreen`]. Le `scoreBezelEnable` d'Hypseus prend un second argument qui choisit parmi ses cinq implémentations d'afficheur de scores. Singe n'en a qu'une ; l'argument est donc accepté et ignoré. [[handhelds]] == Consoles portables et petites machines Singe tourne sur le Raspberry Pi et sur des consoles portables ARM bon marché comme la R36S. Les mêmes jeux y fonctionnent que sur un ordinateur de bureau, mais une petite machine a besoin d'un peu d'aide pour bien les faire tourner. [#_what_a_small_machine_needs] === Ce dont une petite machine a besoin Les sprites, le texte, le son et la vidéo marchent partout. La scène 3D et l'allure soignée du menu demandent une puce graphique avec Vulkan ou OpenGL ES 3.1. * Un Raspberry Pi 4 ou plus récent a les deux, donc tout marche. Un Pi 3 n'a qu'OpenGL ES 2.0, ce qui ne suffit pas pour la 3D. Il fait quand même tourner les jeux 2D. * La plupart des consoles portables, la R36S comprise, ont une puce graphique Mali avec OpenGL ES 3.1 ; la 3D y marche donc aussi. * Sur une machine qui n'a ni l'un ni l'autre, le menu prend une allure plus simple qui n'en a pas besoin. La première fois que vous lancez un jeu 3D, Singe construit ses shaders, ce qui peut prendre quelques secondes sur une petite machine. Ils sont enregistrés dans le dossier `Singe` à l'intérieur du dossier de données ; cela n'arrive donc qu'une fois. [#_settings_for_a_small_machine] === Réglages pour une petite machine Mettez ceci dans le `settings.cfg` à côté du binaire de Singe pour que chaque jeu s'en serve : `scenequality = "low"`:: Dessine la scène 3D à demi-taille, sans anticrénelage ni bloom. La 3D paraît un peu plus douce, mais tourne bien plus vite. La vidéo, les sprites et les menus ne sont pas touchés. `zerocopy = true`:: C'est déjà la valeur par défaut. La vidéo va du décodeur matériel directement à la puce graphique sans que le CPU la copie. C'est ce qui permet à une console portable de lire la vidéo laserdisc à pleine vitesse. Ne le désactivez que si une vidéo se comporte mal et que vous voulez écarter cette cause. `quitchord = "back+start"`:: Les consoles portables n'ont pas de touche Échap. Maintenir Select et Start ramène du jeu au menu, et du menu à votre système, quelle que soit la configuration du jeu. [#_the_r36s_and_arkos] === La R36S et ArkOS La R36S et les consoles portables similaires sous ArkOS utilisent la version Linux `aarch64` de Singe. Mettez le binaire de Singe, son dossier `Singe`, `Menu.sh` et vos jeux dans un même dossier, par exemple `/roms/singe`. Lancez `Menu.sh` une fois pour que Singe puisse créer ses fichiers de support. Pour démarrer Singe depuis le menu Ports, ajoutez un script comme celui ci-dessous dans `/roms/ports`. Ces consoles portables mettent du temps à faire monter en régime leur processeur et leur puce graphique ; le script les règle donc à pleine vitesse pendant que Singe tourne et les remet comme avant quand il se termine. [source,bash] ---- #!/bin/bash # /roms/ports/Singe.sh : Singe dans le menu Ports. SINGE_DIR=/roms/singe [ "$(id -u)" -eq 0 ] && ESUDO="" || ESUDO="sudo" GOVERNORS=() for g in /sys/devices/system/cpu/cpufreq/policy*/scaling_governor /sys/class/devfreq/*/governor; do [ -f "$g" ] || continue GOVERNORS+=("$g:$(cat "$g")") echo performance | $ESUDO tee "$g" > /dev/null 2>&1 done restore() { for entry in "${GOVERNORS[@]}"; do echo "${entry##*:}" | $ESUDO tee "${entry%:*}" > /dev/null 2>&1 done } trap restore EXIT cd "$SINGE_DIR" || exit 1 ./Menu.sh "$@" ---- ArkOS ne signale pas les boutons Select et Start aux jeux, si bien que l'accord pour quitter ne marchera pas tant que vous n'aurez pas ajouté ce `gamecontrollerdb.txt` à côté du binaire de Singe (voir <>) : ---- 1900bb3e4b4800000011000000010000,GO-Super Gamepad,a:b0,b:b1,x:b2,y:b3,back:b12,start:b13,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpdown:b9,dpleft:b10,dpright:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux, ---- Si un bouton ne fait pas ce que vous attendez, lancez Singe une fois avec `--program` et appuyez dessus. La trace montre le nom de chaque bouton sur lequel vous appuyez, ou son numéro si l'affectation ci-dessus ne l'inclut pas. Enfin, ajoutez un `controls.cfg` à côté du binaire de Singe. Celui-ci met l'insertion de pièce et le départ sur Select et Start, et garde les menus de test et de service d'un jeu à l'écart des boutons de façade, où certains jeux les placent. [source,lua] ---- INPUT_1P_COIN = { SCANCODE.MAIN_5, SCANCODE.C, GAMEPAD_0.BUTTON_BACK } INPUT_1P_START = { SCANCODE.MAIN_1, GAMEPAD_0.BUTTON_START } INPUT_PAUSE = { SCANCODE.P } INPUT_SCREENSHOT = { SCANCODE.F12, SCANCODE.F11 } INPUT_SERVICE = { SCANCODE.MAIN_9 } INPUT_TEST_MODE = { SCANCODE.F2 } ---- Ce fichier l'emporte sur celui qu'inclut un jeu (voir <>). La pause et la capture d'écran sont déplacées sur le clavier parce que Singe les met normalement sur Start et Select. [[troubleshooting]] == Quand quelque chose ne va pas [#_the_trace] === La trace Lancez Singe avec `--program` (ou `-p`) pour voir ce qu'il fait. Tout est affiché dans la console et enregistré dans `trace.txt`, dans le dossier de données du jeu. Si vous signalez un problème, joignez le `trace.txt` d'une session lancée avec `--program`. `--trace` (ou `-t`) journalise aussi chaque appel Lua que fait un jeu, ce qui sert surtout quand on écrit un jeu. Si Singe plante sous Linux ou macOS, il écrit l'endroit du plantage dans la console et dans `trace.txt`. `trace.txt` ne contient que les messages propres à Singe. Les messages du système audio, du décodeur vidéo et du pilote graphique ne vont que dans la console. Quand ils pourraient être la cause du problème, enregistrez aussi la console. Sous Linux : ---- ./Menu.sh --program &> singe.log ---- [[perflines]] === Lire les lignes Perf Avec `--program`, toutes les cinq secondes, la trace dit où est passé le temps, en moyennes par tour de la boucle d'image : ---- Perf: 58.9 frames/s shown, 353 loops; per loop 13.1 ms (worst 82.3): disc 1.1, script 0.1, scene 0.0, gui 0.4, overlay 0.0, compose 0.0, present 11.4, other 0.1 Perf script: per loop 0.1 ms of Lua and 0.0 in engine calls it made; 0.0 in engine calls altogether: overlayClear 0.01 (0.8 calls), discGetFrame 0.00 (0.8 calls) Video 3 perf: 23.8 frames/s decoded; per frame 0.5 ms, of which read back 0.0, convert 0.0 ---- * `disc` -- faire avancer la vidéo laserdisc et mettre son image sur le GPU. * `script` -- le `onOverlayUpdate` du jeu, que la ligne `Perf script` sépare entre le Lua lui-même et les appels au moteur qu'il a faits, les plus coûteux en premier. * `scene` -- dessiner la scène 3D. * `gui` -- mettre en page et dessiner les documents GUI. * `overlay` -- envoyer au GPU ce qui a changé sur l'overlay. * `compose` -- seulement avec `--perfsync` : le GPU qui dessine ensemble l'image, l'overlay et les GUI. * `present` -- afficher l'image, ce qui comprend l'attente du prochain rafraîchissement de l'écran. * `other` -- tout le reste : entrées, son, physique et ainsi de suite. La ligne propre à une vidéo dit à quelle vitesse elle se décode et quelle part de chaque image est passée à la recopier depuis le décodeur matériel et à convertir ses couleurs ; zéro pour les deux veut dire que ses images vont au GPU sans être copiées. Le GPU travaille derrière le CPU ; sans `--perfsync`, son temps tombe donc là où le CPU doit l'attendre la fois suivante, ce qui est en général `present`. Un `present` élevé à la pleine fréquence de l'écran n'est que l'attente du rafraîchissement ; un `present` élevé en dessous de celle-ci veut dire que le GPU est occupé. `--perfsync` fait attendre le GPU à chaque étape avant que la suivante commence, si bien que `scene`, `gui`, `overlay` et `compose` comprennent leur temps GPU et qu'il ne reste à `present` que l'attente du rafraîchissement. La fréquence d'images baisse tant qu'il est actif, parce que le CPU et le GPU ne travaillent plus en même temps ; comparez les étapes entre elles, pas à la fréquence d'images. [#_a_button_does_nothing] === Un bouton ne fait rien Ouvrez l'outil Input Test dans le menu (voir <>) et appuyez sur le bouton. Si l'outil le voit, c'est le jeu qui l'ignore : vérifiez donc le `controls.cfg` du jeu. Si l'outil ne le voit pas, vérifiez votre propre `controls.cfg`, ou l'affectation de votre manette dans `gamecontrollerdb.txt`. Lancer Singe avec `--program` montre chaque bouton au moment où vous appuyez dessus. [#_sound_and_picture_are_out_of_sync] === Le son et l'image sont désynchronisés Certains téléviseurs, amplificateurs et enceintes sans fil retardent le son. Utilisez l'outil Audio Delay du menu pour mesurer ce retard. Singe s'en souvient pour chaque jeu. Voir xref:Reference.adoc#audiosync[Synchronisation audio] pour les détails. Pour un son haché ou saccadé, voir les questions fréquentes. [#_frequently_asked_questions] == Questions fréquentes *Pourquoi s'appelle-t-il Singe ?* Singe est le nom du dragon de Dragon's Lair. Comme Singe (le programme) a commencé comme une extension de Daphne (la princesse de Dragon's Lair), le thème de Dragon's Lair a été conservé. *Quelle est la différence entre Daphne, Singe, Hypseus et Singe 3.xx ?* Daphne est un véritable émulateur de jeux laserdisc, capable de faire tourner une poignée de jeux laser classiques. Daphne/Singe (Singe 1.xx) est la version originale de Singe, qui était une extension de l'émulateur Daphne -- livrée d'abord comme DLL de jeu pour Daphne, puis réunie plus tard en un seul binaire, sans les fonctions d'émulation de Daphne. Hypseus-Singe est un fork amélioré de Daphne qui prend en charge Singe 1.xx et une partie de Singe 2.xx. Singe 2.xx est une mise à niveau entièrement nouvelle, reconstruite de zéro, du Singe original, et Singe 3.xx s'appuie dessus avec la 3D, la physique et bien plus encore. En bref, si vous voulez de l'exactitude, utilisez Daphne ou Hypseus s'ils savent émuler le jeu voulu. Si c'est un jeu Singe, utilisez Singe, ou essayez Hypseus. *Pourquoi ne faut-il pas l'appeler un « émulateur » ?* Les émulateurs utilisent le vrai logiciel ou les ROM du jeu d'origine et se font passer pour la machine sur laquelle il devait tourner. Du point de vue du jeu, tout se passe comme d'habitude. Singe, en revanche, exige que chaque jeu soit réécrit (porté) pour tourner sur Singe. Le résultat final peut être très semblable, mais la façon dont il fonctionne est entièrement différente. *Puis-je faire tourner des jeux Singe 1.xx et 2.xx sur Singe 3.xx ?* Oui, probablement. Presque tout ce qui existait pour Singe 1.xx a été converti et amélioré pour les versions récentes de Singe, et la plupart des jeux Singe 2.xx tournent tels quels. Les jeux qui utilisent les anciennes fonctions de sprites peuvent demander une petite modification ; voir xref:Reference.adoc#migrating[Migrer depuis Singe 2.10]. *Faut-il un jeu laserdisc pour utiliser Singe ?* Non. Les jeux n'ont pas du tout besoin d'un disque. Ils peuvent utiliser des sprites, de la vidéo, de la 3D et tout ce que Singe offre d'autre. Voir xref:Reference.adoc#withoutadisc[Jeux sans disque]. *Pourquoi le jeu que je viens d'installer n'apparaît-il pas dans le menu ?* Celui qui a empaqueté le jeu a oublié d'y mettre un fichier `games.dat` correct. *Pourquoi la vidéo HD est-elle lente ?* Elle ne devrait plus l'être. Singe utilise désormais votre carte graphique pour décoder la vidéo quand votre système le permet, même sur le Raspberry Pi et sur beaucoup de consoles portables. Si la vidéo HD est encore lente, votre système n'a peut-être pas de décodage vidéo matériel, et la vidéo haute définition demande alors beaucoup de CPU. Lancer Singe avec `--program` montre quel décodeur il utilise. *Pourquoi mon son saccade-t-il sous Windows ?* Des utilisateurs ont découvert que la plupart des problèmes audio et de saccades de Singe viennent du pilote audio installé -- surtout sur les périphériques à base de Realtek. Essayez de mettre à jour vos pilotes audio ou de passer au pilote générique Windows HD Audio. Désactivez le son surround -- utilisez la stéréo, pas le 5.1 ni le 7.1. Si vos pilotes ne vous permettent pas d'utiliser la stéréo, vous pouvez utiliser Virtual Audio Cable pour y remédier : . Installez VB-CABLE (https://vb-audio.com/Cable/). . Ouvrez les paramètres de son de Windows (clic droit sur le son dans la barre des tâches, puis *Sons*, puis *Lecture*). . Faites un clic droit sur le périphérique *Cable Input* et choisissez *Définir en tant que périphérique par défaut*. (Vous perdrez temporairement votre sortie audio actuelle.) . Allez dans l'onglet *Enregistrement*. . Faites un clic droit sur *Cable Output*, puis *Propriétés*, puis *Écouter*, et cochez enfin *Écouter ce périphérique*. Dans la liste déroulante, choisissez votre vrai périphérique d'écoute. . Vous devriez retrouver le son. Lancez Singe : votre audio fonctionnera, sans décalage. *La 3D marche-t-elle sur un Raspberry Pi ou une console portable ?* Sur un Raspberry Pi 4 ou plus récent, oui. Ils ont à la fois un pilote Vulkan et OpenGL ES 3.1, et Singe utilise celui qu'il trouve. Le Pi 3 n'a qu'OpenGL ES 2.0, qui ne sait exprimer ni le skinning ni les morph targets de la scène ; il fait donc tourner les jeux 2D (physique 2D comprise) exactement comme avant et refuse le premier appel 3D. Le Pi 4 est le minimum pour tout jeu qui utilise le chapitre Scènes 3D. Il en va de même pour les consoles portables bon marché : un Mali-G31 ou G610 a l'ES 3.1 dont la scène a besoin, qu'il ait Vulkan ou non. Voir <>. *Pourquoi mon son saccade-t-il sur le Raspberry Pi ?* Raspberry Pi OS utilise désormais Pipewire comme backend audio par défaut. Passer à PulseAudio semble régler le problème : . Lancez `sudo raspi-config` depuis une fenêtre de terminal. . Choisissez *Advanced Options*. . Choisissez *Audio Config*. . Choisissez *PulseAudio*. . Appuyez sur kbd:[Tab], choisissez *Ok*, et laissez-le redémarrer. [#_making_games] == Créer des jeux Ce manuel parle de faire tourner Singe : l'installer, installer des jeux, configurer une borne, et le menu. La création de jeux est traitée dans deux autres livres, qui sont un téléchargement facultatif depuis le même endroit que Singe plutôt qu'une partie de celui-ci, puisqu'à eux deux ils sont plus gros que le moteur. * La *Référence de Singe* couvre tout ce qu'un jeu peut faire : le modèle de programmation, le dossier du jeu, l'empaquetage d'un jeu en un seul fichier, et chaque fonction qu'offre le moteur, avec ses arguments, ses valeurs de retour et un exemple. * *Apprendre à programmer avec Singe* enseigne la programmation à partir de rien, en trente et une leçons, à quelqu'un qui n'a jamais écrit de code. Il est accompagné des scripts et du petit kit graphique qu'utilisent les leçons. Le téléchargement contient les deux livres en PDF et en HTML, les fichiers des leçons et la licence. Les trois livres sont écrits en anglais, en français, en italien, en allemand et en espagnol, et le téléchargement existe dans chacune de ces langues : prenez celui de votre langue. Les traductions de ce manuel sont déjà dans le dossier `Singe`, à côté de lui. Forge, l'outil de création qui fabrique un jeu à partir d'une description plutôt que de code, est un projet séparé, avec son propre téléchargement et son propre livre.