singe/docs/it/Manual.adoc

1519 lines
93 KiB
Text

= Manuale di Singe
Scott Duensing <scott@kangaroopunch.com>
: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: it
:imagesdir: ..
include::locale.adoc[]
[#_about_singe]
== Informazioni su Singe
Singe (SINGE Is Not a Game Emulator, «SINGE non è un emulatore di giochi», e
chiamato così dal drago di Dragon's Lair) è un sistema di scripting basato su
Lua che permette di realizzare rapidamente prototipi di nuovi giochi laserdisc,
o di creare giochi del tutto nuovi. Il linguaggio è facile da imparare, molto
potente e veloce. Tutte le funzionalità che servono per sviluppare il tuo gioco
sono disponibili attraverso una semplice interfaccia di programmazione (API).
Singe offre numerose funzionalità a chi sviluppa giochi. Alcune delle più
interessanti sono:
* Scene 3D con modelli, animazione, illuminazione e ombre
* Fisica, compresi giunti, ragdoll, corpi morbidi e veicoli
* Menu, schermate di opzioni e HUD costruiti come pagine web
* Decodifica video hardware, anche su macchine piccole
* Punteggi record online, e un catalogo di giochi da scaricare e aggiornare
* Giochi impacchettati in un solo file
* Linguaggio di programmazione orientato agli oggetti
* Sprite animati
* Supporto per i font TrueType
* Spazio colore a 32 bit con trasparenza
* Audio stereo multicanale con suoni sovrapposti, e MIDI
* Supporto per dispositivi di input analogici e digitali, comprese le pistole ottiche
* Ampio supporto per formati video e audio
Singe funziona su Windows, macOS e Linux, compresi il Raspberry Pi e console
portatili come la R36S.
Per chi gioca, Singe permette di godersi molti giochi nuovi e non emulati con
qualsiasi front-end, o con il sistema di menu incluso.
Dalla prima uscita di Singe, nel lontano 2006, ne sono state pubblicate diverse
revisioni, sia ufficiali sia non ufficiali. Nel 2020 è uscito Singe 2.00. Era
una riscrittura completa, da zero, che aggiungeva numerose funzionalità restando
compatibile con i giochi 1.xx esistenti. Singe 3.00 aggiunge il 3D, la fisica,
le interfacce utente e molto altro, e continua a far girare i giochi venuti
prima. Al momento della stesura di questo manuale, l'ultima versione è la
{revnumber}.
[#_installation_and_upgrading]
== Installazione e aggiornamento
[#_installing_singe]
=== Installare Singe
Per installare Singe, scarica l'eseguibile adatto al tuo sistema. Mettilo da
solo in una cartella nuova e avvialo. Al primo avvio, Singe crea tutte le
cartelle e tutti i file di supporto che servono. A questo punto sei pronto per
installare qualche gioco.
[#_upgrading_singe]
=== Aggiornare Singe
Per aggiornare Singe a una versione più recente, metti il nuovo eseguibile nella
cartella di installazione accanto a quello vecchio e avvialo una volta con
`--refresh`. La cartella di supporto già presente viene messa da parte come
`old-Singe-<version>`, con il nome della versione che l'ha scritta, e al suo
posto viene scritta una cartella `Singe/` nuova. Non si cancella niente: la
cartella messa da parte è tua, da tenere o da togliere, e un secondo
`--refresh` mette da parte la propria come `old-Singe-<version>-1` invece di
scrivere sopra la prima.
Il vecchio eseguibile può restare dov'è. `Menu.sh` (o `Menu.bat`) avvia il Singe
più recente che trova accanto a sé, e una beta conta come più vecchia della
versione definitiva con lo stesso numero, quindi `Singe-v3.00b2` cede il posto a
`Singe-v3.00` appena questa arriva. Lo strumento Engine Update del menu fa tutto
questo per te; vedi <<servicetools,Gli strumenti di servizio>>.
WARNING: Non avviare un nuovo eseguibile di Singe con un insieme di file di
supporto non aggiornati. Quando passi a una nuova versione, aggiorna sempre la
cartella `Singe/`.
[#_things_to_know]
=== Cose da sapere
Non toccare la cartella `Singe/`. I file in questa cartella appartengono a Singe
e possono essere aggiornati o cancellati in qualsiasi momento.
[#_playing_games]
== Giocare
[#_installing_games]
=== Installare i giochi
Un gioco è un singolo file `.game` oppure una cartella. Copialo nella stessa
cartella in cui hai messo l'eseguibile di Singe. Il sistema di menu incluso lo
trova da solo e lo aggiunge al menu.
[#_game_directory_layout]
=== Struttura della cartella dei giochi
Un'installazione di Singe è una cartella dei giochi che contiene la cartella di
supporto `Singe` creata dal motore al primo avvio, una cartella per ogni gioco,
gli eventuali file `.game` impacchettati e una cartella `data` per tutto ciò che
i giochi e il motore scrivono. Di solito anche l'eseguibile sta lì, ma non è
obbligatorio: `--gamedir` indica la cartella dei giochi da qualsiasi posizione,
e il `Menu.sh` (o `Menu.bat`) che il motore scrive lì avvia poi l'eseguibile con
il suo percorso completo. Altrimenti il launcher cerca accanto a sé i file il
cui nome comincia con `Singe` e avvia il migliore, nello spirito dei launcher
che scrive `BatMaker`, così un aggiornamento che cambia la versione nel nome
dell'eseguibile non lascia un launcher che punta a un file che non c'è più.
Il migliore vuol dire prima l'architettura di questa macchina e poi la versione.
La piattaforma nel nome viene confrontata con quella che riporta il sistema,
perché una build più recente per un'altra architettura non può girare affatto, e
la stessa cartella dei giochi su una condivisione di rete può essere letta tanto
da un Pi quanto da un PC. Il launcher fa questo calcolo ogni volta che parte,
invece di sentirselo dire una volta per tutte, così la stessa cartella va bene
per ogni macchina che la apre. Su un Mac una build universale conta come nativa.
Tra le build che questa macchina può far girare vince la più recente:
`Singe-v3.10` batte `Singe-v3.09`, e una beta perde contro la versione
definitiva a cui prepara la strada, quindi `Singe-v3.00b2` perde contro
`Singe-v3.00`. Una build per un'altra architettura viene avviata comunque quando
è l'unica presente, perché una vera lamentela del motore è meglio di sentirsi
dire che non è stato trovato niente, e lo stesso vale per un nome che il
launcher non riesce proprio a leggere.
----
Singe/ File di supporto estratti dal motore
Framework.singe Caricato da ogni gioco (con dofile)
Menu.singe Il menu dei giochi incluso
Tools.singe Gli strumenti di servizio del menu (vedi Gli strumenti di servizio)
MenuDocument.singe Il menu disegnato come documento GUI
MenuOverlay.singe Il menu disegnato nell'overlay, per una macchina senza GPU
Backdrop.singe L'introduzione del menu e la griglia dietro, disegnate dal vivo
menuBackground.mkv Lo stesso sfondo registrato, per una macchina senza GPU
menuIntro.flac Il suo suono, che sfuma mentre il menu prende lo schermo
Menu.rml Il documento RmlUi del renderer a documento
menu.rcss Il suo foglio di stile, sopra gui.rcss
gui.rcss Il tema GUI fornito con Singe
controls.cfg.example Esempio da copiare per le assegnazioni dei comandi
click.wav Usato dai test del ritardo audio e del suono del menu
Manual.pdf Questo manuale
Manual-fr.pdf Questo manuale in francese
Manual-it.pdf Questo manuale in italiano
Manual-de.pdf Questo manuale in tedesco
Manual-es.pdf Questo manuale in spagnolo
COPYING La GNU General Public License, versione 3
LICENSES Avvisi di terze parti e riconoscimenti delle risorse
Collection/ Una cartella di giochi
games.dat Le voci di menu dei giochi di questa cartella
AsteroidPatrol.singe Uno script
frame_AsteroidPatrol.txt Il suo framefile (o un video con lo stesso nome di base)
sprite_*.png, sound_*.wav, font_*.ttf
MyGame.game Un gioco impacchettato in un solo file (vedi Giochi in un solo file)
data/
machine.cfg Il ritardo audio e la geometria dell'immagine di questa macchina
Collection/ Indici, trace.txt, screenshot e salvataggi di quei giochi
----
Dove Singe cerca i file di uno script, e dove uno script può scrivere, è
faccenda di chi scrive lo script; il Riferimento di Singe tratta entrambe le
cose in Impacchettare il tuo gioco.
[#bundledmenu]
=== Il menu incluso
`Menu.sh` (o `Menu.bat`) avvia `Singe/Menu.singe`, il menu incluso: un documento
RmlUi, `Singe/Menu.rml` con lo stile di `Singe/menu.rcss`, disegnato sopra uno
sfondo 3D dal vivo (vedi xref:Reference.adoc#gui[GUI]). Il menu funziona senza
disco; una macchina senza GPU riproduce invece `Singe/menuBackground.mkv`, una
registrazione dello stesso sfondo, dietro una pagina più semplice disegnata
sull'overlay. Legge il `games.dat` della cartella di ogni gioco e di ogni
file `.game` che ha accanto ed elenca tutti i giochi che trova, in ordine di titolo,
lungo il lato sinistro dello schermo. Accanto all'elenco ci sono la grafica del
cabinato del gioco selezionato, il suo marquee e la sua clip della modalità
attract, con sotto l'anno, il genere, la piattaforma, lo sviluppatore,
l'editore, i riconoscimenti della conversione e la descrizione, e una riga di
suggerimenti sui tasti lungo il bordo inferiore.
Su e giù spostano la selezione di un gioco alla volta, sinistra e destra di una
pagina alla volta; in entrambi i casi da un capo dell'elenco si passa all'altro.
Start o un qualsiasi pulsante d'azione avvia il gioco selezionato, e il tasto
assegnato a `INPUT_SERVICE` (di base il tasto `9`) apre gli strumenti di
servizio (vedi <<servicetools,Gli strumenti di servizio>>). Con un mouse, un
clic su una riga seleziona quel gioco e un secondo clic sulla stessa riga lo
avvia; la rotella del mouse fa scorrere una descrizione troppo lunga per il suo
riquadro. Se imposti `--quitchord`, tenendo premuti quei pulsanti esci da un
gioco tornando al menu, e dal menu tornando al tuo sistema (vedi
<<handhelds,Console portatili e macchine piccole>>). Il menu conserva la sua
selezione in `menu.dat` nella sua cartella dei dati, così torna sullo stesso
gioco quando ne esci o al successivo avvio di Singe. Quel file è un frammento di
Lua che il menu legge all'avvio e riscrive alla chiusura: `GAME_SELECTED` è il
gioco che stava mostrando, `SHOW_INTRO` è false quando torna da un gioco, così
non ti sorbisci l'introduzione due volte, e `MENU_OVERLAY` sceglie un renderer
(vedi <<menurenderers,I due renderer>>).
Non tutte le macchine fanno girare tutti i giochi. Un gioco 3D su una macchina
senza 3D, o un gioco pesante su una piccola, fallirebbe o andrebbe a passo di
lumaca, quindi il menu te lo dice prima. Quando selezioni un gioco che questa
macchina non può far girare, la riga sotto i suoi dettagli dice che cosa gli
serve («Needs 3D, and this machine has none.»), e avviarlo ripete soltanto quel
messaggio invece di fallire a metà strada. Un gioco che chiede più macchina di
questa riceve «It may run slowly.» e parte lo stesso. Non viene nascosto niente.
Il menu calcola quanto è veloce questa macchina la prima volta che riproduce la
sua introduzione, cronometrando il proprio sfondo, e conserva la risposta in
`machine.cfg`; non ti chiede mai di lanciare un benchmark. I giochi dicono che
cosa gli serve nel loro `games.dat` (xref:Reference.adoc#gamesdat[REQUIRES e
TIER]), e lo strumento Get Games segna il catalogo allo stesso modo.
[#menurenderers]
==== I due renderer
Un documento GUI viene disegnato attraverso il dispositivo GPU che usa la scena
3D, quindi su una macchina che non ne ha uno non c'è nessun documento da
costruire. Il menu se ne occupa da solo: all'avvio `Singe/Menu.singe` interroga
xref:Reference.adoc#singehasgpu[singeHasGpu] e carica uno dei due renderer.
`Singe/MenuDocument.singe`::
Il documento RmlUi descritto sopra, per una macchina con un dispositivo GPU.
Disegna anche l'introduzione e la griglia dietro il menu come un'unica scena 3D
continua, così il disco non serve per nessuna delle due.
`Singe/MenuOverlay.singe`::
Sprite e `fontPrint` direttamente nell'overlay, l'aspetto che aveva Singe 2. Non
gli serve niente oltre all'overlay in cui ogni gioco disegna già.
Entrambi disegnano lo stesso menu, accettano gli stessi tasti ed eseguono gli
stessi strumenti di servizio; `Singe/Menu.singe` contiene tutto ciò che non è
disegno -- l'elenco dei giochi, la selezione, l'avvio di un gioco -- così il
menu è uno solo e non due. Il renderer dell'overlay mostra un gioco alla volta
invece di un elenco, perché non ha un riquadro da far scorrere, e taglia una
descrizione troppo lunga per la sua colonna invece di farla scorrere.
Per vedere il renderer dell'overlay su una macchina che una GPU ce l'ha, metti
`MENU_OVERLAY = true` in `menu.dat` nella cartella dei dati del menu; il menu
riscrive la riga, quindi resta. È così che si collauda il percorso dell'overlay,
ed è così che chi costruisce un cabinato e preferisce il vecchio aspetto lo
ottiene.
[#onlineservice]
==== Online: account, giochi e punteggi
Il menu incluso può far accedere il cabinato a un servizio master (di base
`master.singeengine.com`), che fa tre cose: custodisce l'account, offre un
catalogo di giochi da scaricare e aggiornare, e tiene le classifiche dei
punteggi record.
Se ne occupano due strumenti di servizio. **Online Account** accede, crea un
account, recupera una password e imposta l'indirizzo del server -- è lì che un
gestore con un proprio servizio indirizza il cabinato. Un nuovo account non si
può usare finché non si apre il link arrivato per email. **Get Games** elenca
tutto ciò che il servizio offre, segna quello che è installato qui, e lo scarica,
lo aggiorna o lo rimuove. Un download che contiene più giochi -- una raccolta, o
un gioco in due lingue -- li mette tutti nell'elenco, ciascuno con il proprio
nome e con l'indicazione del download di cui fa parte, e prenderne o rimuoverne
uno qualsiasi prende o rimuove tutto il gruppo, dato che sono un unico file.
Quello che viene offerto dipende dall'account: un servizio può riservare un
gioco a determinati account, quindi due cabinati connessi con account diversi
possono vedere elenchi diversi. È il menu stesso a dire quando esiste una
versione più recente di un gioco installato: il gioco porta il segno `update`
nell'elenco, la riga sotto i suoi dettagli indica la versione, e il pulsante 3
su quella pagina la scarica, così un cabinato non ha bisogno di aprire uno
strumento di servizio per restare aggiornato. Niente di questa macchina viene
conservato da nessuna parte: il menu legge la versione dal `games.dat` di
ciascun gioco e chiede notizie del proprio elenco, quindi un gioco copiato a
mano è noto quanto uno scaricato qui. Un cabinato senza alcun gioco apre
comunque il menu, che spiega come procurarsene qualcuno, e tutto quello che Get
Games scarica o rimuove compare nell'elenco appena si chiudono gli strumenti di
servizio. Un elenco più lungo dello schermo scorre con la selezione invece di
uscire dal fondo, e `...` indica che c'è dell'altro in una direzione o
nell'altra. Un gioco che non viene più offerto continua a funzionare e appare
come «installed, no longer offered»: smette soltanto di ricevere aggiornamenti,
perché un giocatore che ha un gioco ce l'ha. Un download viene controllato
rispetto all'impronta pubblicata dal catalogo prima di sostituire qualsiasi
cosa, così un trasferimento arrivato male fallisce invece di installare un gioco
che non partirà.
L'account appartiene alla *macchina*, non a un gioco: il token è conservato in
`master.dat` nella radice dei dati, quindi un gioco che invia un punteggio usa
lo stesso accesso fatto dal menu. La password non viene mai conservata, e il
file è offuscato, così il token e l'indirizzo dell'account non si leggono a
colpo d'occhio; un file modificato risulta disconnesso. La macchina deve poterlo
rileggere senza nessuno davanti, quindi tratta comunque `master.dat` come una
chiave dell'account: copiato su un'altra macchina, fa accedere quella macchina.
Per inviare un punteggio serve quell'account, ma per leggere una classifica no:
un cabinato non connesso mostra comunque la classifica online di un gioco, dove
il gioco ne mostra una, per qualsiasi gioco che il servizio offre a tutti. Vedi
xref:Reference.adoc#onlinescores[Punteggi record online] per la parte del gioco,
e `Singe/Net.singe` per il client HTTP asincrono che sta sotto -- qui niente
blocca un fotogramma, perché in Singe Lua è cooperativo e altrimenti un download
grande sembrerebbe un blocco.
Singe controlla il certificato del server rispetto a due elenchi insieme: quello
che porta con sé e quello che tiene la tua macchina. Basta che uno dei due
garantisca per il server, così una vecchia copia di Singe riesce comunque a
raggiungere l'aggiornamento che la sostituisce, purché il tuo sistema tenga
aggiornato il proprio elenco. Hai un tuo servizio con un certificato emesso da
una tua autorità di certificazione? Metti il certificato di quell'autorità in
`cacerts.local.pem` nella cartella dei dati. Singe non scrive mai quel file,
quindi sopravvive agli aggiornamenti. Se una connessione viene rifiutata, il
messaggio dice quali elenchi sono stati controllati, e un certificato «not yet
valid» vuol dire quasi sempre che l'orologio della macchina è sbagliato.
[#servicetools]
==== Gli strumenti di servizio
Il tasto assegnato a `INPUT_SERVICE` apre un elenco di strumenti sopra l'elenco
dei giochi. Su e giù ne scelgono uno e il pulsante 1 lo apre; il pulsante 2 esce
da uno strumento e torna all'elenco, e premendo di nuovo il tasto di servizio si
esce del tutto dagli strumenti. Tutto si trova in `Singe/Tools.singe`, che il
motore estrae accanto a `Menu.singe`. Lì dentro niente disegna: uno strumento
costruisce un elenco di righe e lo passa al menu, ed è per questo che ogni
strumento funziona con entrambi i renderer (vedi <<menurenderers,I due
renderer>>). Niente qui ha bisogno che un gioco sia in esecuzione, e niente
modifica i file di un gioco.
Audio Delay::
Il ritardo audio a valle, misurato con un clic e un lampo. Vedi
xref:Reference.adoc#menucalibration[Calibrare dal menu] per che cosa fa e perché
funziona.
Input Test::
Ogni controller, mouse e pistola che il motore vede, dal vivo: l'ultimo
interruttore che il gioco avrebbe ricevuto e quanti ne sono arrivati, il nome di
ogni controller con i suoi sei assi e i pulsanti tenuti premuti, e il nome e la
posizione di ogni mouse. È la schermata che risponde a «il pulsante non fa
niente» -- o l'interruttore arriva e il gioco lo ignora, o non arriva proprio.
System Information::
La versione del motore, il sistema operativo, il processore e la memoria, il
renderer e il dispositivo 3D, quali decoder video sono in uso, i formati audio
integrati, il SoundFont, lo stato del MIDI, le dimensioni della finestra, del
canvas e dell'overlay, e la cartella dei dati. Una foto di questa pagina
risponde a quasi tutta una segnalazione di bug.
Light Gun::
Bersagli al centro e in ogni angolo dell'overlay, sopra qualsiasi cosa il disco
stia mostrando. Il pulsante 1 segna dove la pistola ha puntato davvero, e tiene
gli ultimi dodici colpi; Start li cancella. Una pistola ben allineata con
l'immagine mette le sue croci sui bersagli, e una che non lo è mostra da che
parte sbaglia.
Sound Test::
Il pulsante 1 suona il clic dall'altoparlante sinistro, poi dal destro, poi da
entrambi, ed è tutto il controllo dei fili invertiti. Elenca anche le tracce
audio del disco, e sinistra e destra passano dall'una all'altra.
Display::
Le dimensioni, la posizione e la rotazione dell'immagine, modificate dal vivo
con le frecce, i pulsanti 3 e 4 e il gettone 1, sopra un'immagine di prova: una
griglia 16 per 12 per mettere in squadra l'immagine, una scala di grigi a otto
gradini su cui regolare la luminosità, e due cornici a un pixel di distanza
proprio sul bordo -- un monitor in overscan si mangia prima quella esterna. Il
pulsante 1 conserva i valori per questa macchina, nello stesso `machine.cfg` che
usa il ritardo audio, così valgono per ogni gioco invece di essere impostati una
volta per gioco. Start rimette tutto com'era.
Disc Test::
Dodici salti sparsi su tutto il disco, ciascuno cronometrato. Un rip con i
fotogrammi chiave molto distanti salta lentamente, e l'unico sintomo in un gioco
è che tutto sembra pesante; questo strumento lo misura direttamente e riporta il
peggiore dei dodici. Un salto che non è arrivato a destinazione in tre secondi
conta come tre secondi.
Saved Data::
Quello che ogni gioco ha conservato, trovato cercando nella radice dei dati
invece che sentendoselo dire, con le dimensioni di ciascuno. Il pulsante 3 --
non il pulsante 1, che ovunque altrove vuol dire «scegli» -- butta via il
salvataggio del gioco selezionato. Il motivo più comune è azzerare una tabella
dei punteggi record senza cancellare il gioco.
Engine Update::
Un Singe più recente, quando il servizio ne ha uno per questa macchina. Una beta
ha come versione `3.00b2`, la seconda beta della 3.00, e viene prima della 3.00
vera e propria, quindi a un cabinato che fa girare una beta viene offerta la
versione definitiva il giorno stesso in cui è pubblicata. Mostra che cosa è in
esecuzione e che cosa viene offerto, e il pulsante 1 lo scarica, lo controlla
rispetto all'impronta pubblicata dal servizio, lo mette accanto al Singe in
esecuzione con il nome proprio della versione, mette da parte quello vecchio
come `old-<name>` e si riavvia con quello nuovo. La messa da parte del vecchio
può essere rifiutata, da una cartella in cui questo utente non può scrivere o da
uno scanner che tiene occupato il file; lo strumento lo dice e va avanti, perché
il launcher avvia comunque il Singe più recente nella cartella. Il nuovo Singe
parte con `--refresh`, così la cartella di supporto viene riscritta dalla
versione che ora ne è proprietaria e quella vecchia viene conservata come
`old-Singe-<version>`; un file che un Singe precedente forniva e questo no non
può restare in giro a confondere un gioco. Non succede niente finché non premi
quel pulsante. Il pulsante 3 interroga di nuovo il servizio. Il menu controlla
da solo una volta al giorno e lo dice in una riga sotto i dettagli del gioco;
`no_update_check = true` in `settings.cfg` ferma il controllo quotidiano, e lo
strumento funziona comunque a mano.
Online Account::
L'accesso di questo cabinato al servizio master, la creazione di un account, il
recupero di una password e l'impostazione dell'indirizzo del server. Vedi
<<onlineservice,Online: account, giochi e punteggi>>.
Get Games::
Il catalogo: che cosa offre il servizio, che cosa è installato qui, e lo
scaricamento, l'aggiornamento o la rimozione.
MIDI Ports::
Le porte di ingresso e di uscita di questa macchina, quali di queste Singe ha
aperto, e gli ultimi messaggi arrivati. Il pulsante 1 invia una nota, il
pulsante 3 cerca di nuovo le porte dopo che è stato collegato qualcosa. Niente
viene aperto finché questo strumento non lo chiede, così un cabinato che non
tocca mai il MIDI non ne paga mai il prezzo.
Frame Statistics::
Accende e spegne l'overlay dello sviluppatore. Resta acceso anche nel gioco,
nell'angolo in alto a sinistra. Vedi xref:Reference.adoc#statsenable[statsEnable].
[[controls]]
== Comandi
Di base, Singe tratta i controller come se fossero controller Xbox. Se il tuo
controller non viene riconosciuto, o vuoi cambiare le assegnazioni predefinite
con cui Singe lo vede, puoi usare lo SDL2 Gamepad Tool gratuito, da
http://generalarcade.com/gamepadtool/.
[[controlscfg]]
=== controls.cfg
Oltre a configurare il controller, con i file `controls.cfg` puoi riassegnare
tutti gli input di Singe, per Singe nel suo insieme o per un singolo gioco. Per
stabilire come sono assegnati gli input, Singe legge le impostazioni di
configurazione nell'ordine seguente, e un file successivo sostituisce uno
precedente input per input (vedi <<configorder,Da dove vengono letti i file di
configurazione>>):
. I valori predefiniti interni a Singe.
. `controls.cfg` dalla cartella dello script principale del gioco: quello fornito dall'autore del gioco.
. `controls.cfg` dalla cartella da cui è stato avviato Singe: quello della macchina (la cartella `Singe` contiene un esempio, `controls.cfg.example`, che puoi copiare).
. `controls.cfg` dalla cartella sopra la cartella dei dati del gioco.
. `controls.cfg` dalla cartella dei dati del gioco: il tuo, per quel solo gioco.
Non devi specificare ogni opzione in un file `controls.cfg` personalizzato.
Metti pure soltanto le voci che vuoi cambiare.
Dopo aver installato Singe, trovi un file di esempio per la configurazione degli
input in `<InstallDir>/Singe/controls.cfg.example`. Per vedere le opzioni di
configurazione che puoi usare in questo file, leggi
`<InstallDir>/Singe/Framework.singe`.
`--keymapfile` indica un unico file da leggere al posto di quella ricerca, cosa
utile a un front-end che non vuole dubbi su quali assegnazioni abbia ricevuto un
gioco.
Ogni voce `INPUT_` è un elenco, e una qualsiasi delle cose che contiene aziona
l'interruttore. Un elenco dentro quell'elenco è una combinazione: da due a
quattro tasti o pulsanti tenuti premuti insieme, che aziona l'interruttore
quando viene premuto l'ultimo e lo rilascia quando uno qualsiasi viene
sollevato. Così una console portatile senza il tasto Esc esce con Select e Start
insieme:
[source,lua]
----
INPUT_QUIT = { SCANCODE.ESCAPE, { GAMEPAD_0.BUTTON_BACK, GAMEPAD_0.BUTTON_START } }
----
Ogni tasto o pulsante di una combinazione conserva anche il proprio significato,
quindi premere Select e Start per uscire in questo modo inserisce anche un
gettone e preme Start mentre esci.
Se vuoi un modo di uscire che funzioni sempre, usa invece `--quitchord`. Quando
premi uno dei suoi pulsanti, Singe aspetta gli altri per un quarto di secondo
prima di fare qualsiasi altra cosa, così uscire non inserisce un gettone e non
preme Start. Un gioco può disattivare il proprio tasto di uscita, ma non può
disattivare `--quitchord`.
[[devices]]
=== Ogni dispositivo è un controller
Singe ha una sola famiglia di controller, da `GAMEPAD_0` a `GAMEPAD_3`, e ogni
dispositivo che apre ne fa parte. SDL considera controller un dispositivo solo
quando ha un'assegnazione per esso, e una scheda encoder arcade, uno spinner, un
volante o una cloche spesso non ne hanno. Invece di portarsi dietro un secondo
tipo di dispositivo con nomi propri, Singe scrive da sé un'assegnazione per un
dispositivo del genere e poi lo apre come un normale controller, così arriva a
`controls.cfg`, `controllerGetAxis`, `controllerGetButton` e a ogni interruttore
`INPUT_*` esattamente come un controller riconosciuto.
L'assegnazione che scrive Singe è diretta: gli assi del dispositivo, in ordine,
diventano la levetta sinistra, la levetta destra e poi i due grilletti; i suoi
pulsanti, in ordine, diventano `BUTTON_A`, `BUTTON_B`, `BUTTON_X`, `BUTTON_Y`,
`BUTTON_BACK`, `BUTTON_GUIDE`, `BUTTON_START`, `BUTTON_LEFT_STICK`,
`BUTTON_RIGHT_STICK`, `BUTTON_LEFT_BUMPER` e `BUTTON_RIGHT_BUMPER`; e il suo
primo hat diventa la croce direzionale. Un dispositivo senza hat usa invece i
quattro pulsanti successivi per la croce direzionale. **Un dispositivo con più
comandi di quanti il modello di controller ne sappia nominare perde quelli in
più** -- più di sei assi, più di quindici pulsanti, o un secondo hat -- e un
dispositivo i cui pulsanti non sono cablati in quell'ordine li avrà nei posti
sbagliati. È il prezzo di una famiglia sola invece di due, e si corregge
facilmente: `--program` scrive nella traccia l'assegnazione che ha creato, nel
formato di SDL, così puoi incollarla in un `gamecontrollerdb.txt`, riordinarla e
farla usare al suo posto.
`--mapjoysticks=false` disattiva questa scrittura, e in quel caso un dispositivo
che SDL non riconosce non viene aperto affatto, esattamente come nelle versioni
precedenti.
[[gamecontrollerdb]]
=== gamecontrollerdb.txt
SDL include un grande database di assegnazioni per controller, e la comunità ne
tiene uno ancora più grande -- `gamecontrollerdb.txt`, da
https://github.com/mdqinc/SDL_GameControllerDB. Singe cerca quel file negli
stessi quattro posti in cui cerca `controls.cfg`, nello stesso ordine (vedi
<<configorder,Da dove vengono letti i file di configurazione>>):
. la cartella dello script principale del gioco;
. la cartella da cui è stato avviato Singe;
. la cartella sopra la cartella dei dati del gioco;
. la cartella dei dati del gioco.
Ogni file trovato viene caricato, in quell'ordine, quindi il file della macchina
vince su quello fornito da un gioco, un file nella cartella dei dati del gioco
vince su entrambi, e tutti vincono sul database di SDL. Solo un dispositivo che
nessuno di loro nomina riceve l'assegnazione che Singe scrive per lui: quella è
l'ultima risorsa, mai una rivale dei tuoi file. `--program` riporta quante
assegnazioni ha aggiunto ciascun file.
I file vincono anche su `SDL_GAMECONTROLLERCONFIG`, la variabile d'ambiente da
cui SDL prende le assegnazioni, che alcuni sistemi per console portatili
impostano per il loro controller integrato. L'assegnazione di ArkOS per la R36S,
per esempio, lascia fuori Select e Start, così nessun gioco li vede; una riga in
`gamecontrollerdb.txt` per lo stesso controller li rimette. SDL legge la
variabile una sola volta, all'avvio di Singe, quindi questo vale per i file che
trova il primo gioco. Un gioco avviato più tardi dal menu legge comunque i
propri, ma un controller nominato dalla variabile conserva l'assegnazione della
variabile.
Una riga di quel file è fatta così, ed è esattamente quello che la traccia
stampa per un dispositivo che Singe ha assegnato da sé:
----
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]]
=== Zone morte e grilletti
`DEAD_ZONE` in `controls.cfg` è quanto deve muoversi un asse prima di contare
come interruttore premuto, nelle unità grezze che riporta SDL: `32767` a fondo
corsa, quindi il valore predefinito di `15000` è poco meno di metà. Vale per
ogni asse di ogni controller, compresi i due grilletti analogici, e uno script
lo legge come `SINGE_DEAD_ZONE`.
Due impostazioni lo restringono.
`DEAD_ZONES` è un elenco di coppie `{ axis, dead zone }`, un asse alla volta,
nelle stesse unità grezze, per una levetta dura o un grilletto consumato che non
deve spostare tutto il resto:
[source,lua]
----
DEAD_ZONES = {
{ GAMEPAD_0.AXIS_LEFT_X, 8000 },
{ GAMEPAD_1.AXIS_LEFT_TRIGGER, 30000 },
}
----
L'asse si può scrivere come l'asse stesso o come una delle sue due direzioni
(`GAMEPAD_0.AXIS_LEFT_X`, `AXIS_LEFT_X_L` e `AXIS_LEFT_X_R` indicano tutti lo
stesso asse). Tutto quello che non è elencato tiene `DEAD_ZONE`.
`TRIGGER_THRESHOLD` è quanto deve scorrere un grilletto analogico prima di
contare come pulsante, espresso come *percentuale della corsa completa*, che è
l'unità usata dal `-trigger-threshold` di Hypseus, dove il valore predefinito è
`99.5`. Vale per entrambi i grilletti di tutti e quattro i controller. Il valore
predefinito di Singe è `0`, che vuol dire che i grilletti restano su
`DEAD_ZONE`, così per chi non lo chiede non cambia niente; uno script legge il
risultato in unità grezze come `SINGE_TRIGGER_THRESHOLD`. Le due unità si
convertono direttamente: un punto percentuale vale `32767 / 100` unità grezze,
quindi il `DEAD_ZONE` di Singe pari a `15000` è il `45.8` per cento e il `99.5`
per cento di Hypseus corrisponde a `32603` unità grezze. `--trigger_threshold`
imposta lo stesso numero dalla riga di comando e vince su `controls.cfg`;
`DEAD_ZONES` vince su entrambi, perché è il più specifico.
[[joymouse]]
=== Guidare il mouse con una levetta
Un gioco con pistola ottica su un cabinato con una levetta e senza mouse è
ingiocabile, a meno che la levetta non possa muovere il cursore. `--joymouse` fa
proprio questo: la **levetta sinistra del controller nello slot 0** muove il
puntatore che vede il gioco, attraverso lo stesso `onMouseMoved` a cui arriva un
mouse vero, e il cursore viene tenuto dentro l'immagine. `--js_range` è la
velocità, da `1` a `20` con `5` come valore predefinito, misurata in pixel video
per fotogramma a fondo corsa, quindi con `5` si attraversa un'immagine di 720
pixel in circa due secondi. L'asse rispetta la propria zona morta, così una
levetta che deriva non fa scivolare il cursore.
Di base è spento, ed è qui che Singe si distingue da Hypseus: il `controls.cfg`
fornito lega già quella levetta a `INPUT_UP`, `INPUT_DOWN`, `INPUT_LEFT` e
`INPUT_RIGHT`, e fargli guidare anche il cursore senza che nessuno lo chieda
sorprenderebbe ogni gioco esistente. `--joymouse=false` è il `-nojoymouse` di
Hypseus, e uno script lo accende e lo spegne con `joyMouseEnable` e lo legge con
`joyMouseIsEnabled`. Un ricaricamento lo riporta dove l'aveva lasciato la riga
di comando.
[[mousedevices]]
=== Mouse, pistole e chi sceglie
`mouseSetMode(MOUSE_MANY)` è la decisione di un gioco di distinguere fino a
quattro mouse, cosa di cui ha bisogno un cabinato a due pistole e che non si può
dare a un gioco che non fa mai quella chiamata. `--manymouse` è la decisione
dell'utente e ha la precedenza: la modalità è attiva fin dall'inizio e
`mouseSetMode(MOUSE_SINGLE)` non la spegne più.
`--absolutes_only` tiene solo i dispositivi che riportano una posizione
assoluta, cosa che una vera pistola ottica fa e un mouse normale no, così un
cabinato con due pistole e un mouse da scrivania collegato non si confonde per
colpa del mouse. Tieni presente come decide: **ManyMouse, il backend che Singe
usa per distinguere i mouse, non offre alcun modo di chiedere a un dispositivo
di che tipo sia**, quindi un dispositivo conta come assoluto da quando ha
riportato una posizione assoluta, e non prima. Una pistola lo fa al primo
movimento; fino ad allora resta muta, e un dispositivo solo relativo resta muto
per sempre. L'opzione è quindi un filtro basato sul comportamento osservato più
che sulla classe del dispositivo, e su una macchina dove nessun dispositivo
riporta mai una posizione assoluta zittisce tutti i mouse.
`SWITCH_MOUSE_DISCONNECT` è un interruttore come tutti gli altri, tranne che non
lo produce nessun tasto o pulsante: il motore lo genera quando si scollega un
mouse o una pistola ottica, una volta come pressione e una volta come rilascio,
così un gioco con pistola può dirlo sullo schermo invece di sembrare morto. È
l'interruttore omonimo di Hypseus. `controls.cfg` non lo lega a niente; legagli
anche un tasto se vuoi vedere che cosa fa un gioco senza staccare un cavo.
[[hotkeys]]
=== Tasti rapidi
`Alt-Enter` passa dallo schermo intero a una finestra e viceversa mentre il
gioco è in esecuzione, come fa in Hypseus. Il gioco non vede mai quel tasto. Una
finestra partita a schermo intero esclusivo (`--fullscreen`) ci torna nella
modalità video che le era stata data; una partita in finestra ottiene una
finestra senza bordi che copre il desktop. Non deve cambiare nient'altro: il
renderer presenta una dimensione logica in coordinate video e la scala a
qualunque dimensione abbia ora la finestra, il rettangolo video è costruito in
quelle stesse coordinate, e il render target della rotazione ha le dimensioni
dell'immagine e non della finestra, quindi l'immagine, l'overlay, le GUI e la
mappatura del mouse seguono tutti da soli.
Gli altri interruttori che un utente può premere -- uscita, pausa, screenshot,
registrazione, la console e l'attivazione della cattura del mouse -- sono
normali assegnazioni di `controls.cfg` e sono descritti insieme ai nomi
`INPUT_*` nel file di esempio.
[[recording]]
=== Registrare video
`F10` comincia a registrare il gioco, immagine e suono insieme, e un altro `F10`
ferma la registrazione. Ogni registrazione è un nuovo `singeNNN.mp4` nella
cartella dei dati del gioco, accanto agli screenshot, e si riproduce con
qualsiasi cosa riproduca un MP4. L'immagine è l'intera finestra come la vedi,
bande nere comprese, e il suono è tutto quello che il gioco riproduce: musica,
effetti sonori e la colonna sonora del video stesso.
Dove la macchina ha un encoder video hardware, Singe lo usa, così la
registrazione costa pochissimo al gioco: H.264 tramite VA-API su Linux,
VideoToolbox su macOS, Media Foundation su Windows e V4L2 sulle schede ARM che
ne hanno uno. Altrove registra invece in MPEG-4, che si riproduce ovunque ma
produce file più grandi. La riga `Recording` nella traccia dice quale ha usato.
Una macchina troppo lenta per stare al passo scarta fotogrammi dalla
registrazione invece di rallentare il gioco, e la traccia dice quanti quando la
registrazione si ferma.
Per registrare invece un'intera sessione, avvia Singe con
`--record=FILENAME`. Aggiungi `--deterministic` e Singe registra ogni
fotogramma e il suono esatto che lo accompagna, per quanto tempo serva a
produrre ciascun fotogramma, senza riprodurre niente dagli altoparlanti. È così
che si fa un video perfetto di una demo o di una modalità attract: su un
computer desktop di solito va più veloce del tempo reale.
[#_settings_and_options]
== Impostazioni e opzioni
Quasi tutto quello che puoi mettere sulla riga di comando può andare anche in un
file delle impostazioni. Prepari tutto una volta e ogni gioco lo usa.
[[settings]]
=== Il file delle impostazioni
Quasi tutto quello che va sulla riga di comando si può anche scrivere una volta per
tutte in un file `settings.cfg`, così un cabinato non ha bisogno di uno script
di avvio che si porti dietro la stessa dozzina di opzioni per ogni gioco. È Lua,
come `controls.cfg`, e Singe lo cerca esattamente negli stessi quattro posti, in
quest'ordine:
. `settings.cfg` dalla cartella dello script principale del gioco.
. `settings.cfg` dalla cartella da cui è stato avviato Singe (la cartella `Singe` contiene un esempio, `settings.cfg.example`, che puoi copiare).
. `settings.cfg` dalla cartella sopra la cartella dei dati del gioco.
. `settings.cfg` dalla cartella dei dati del gioco.
Ogni posto viene letto una volta, e un file successivo vince chiave per chiave,
così un file valido per tutta la macchina può impostare lo schermo e i volumi
mentre un file nella cartella dei dati di un gioco spegne il mirino di quel
gioco. Non devi scrivere ogni chiave in un file; scrivi quelle che vuoi
cambiare.
Ogni chiave è il nome lungo di un'opzione da riga di comando senza i trattini
iniziali, quindi non c'è un secondo vocabolario da imparare:
[source,lua]
----
-- Il settings.cfg del cabinato
screen = 2 -- il secondo monitor
fullscreen = true
volume_vldp = 80
haptic = 0 -- questo cabinato non ha la vibrazione
idleexit = 900 -- restituisci lo schermo dopo quindici minuti di quiete
startsilent = true
----
Un'opzione che sulla riga di comando non prende alcun valore qui prende `true` o
`false` (sono accettati anche `yes`, `no`, `on`, `off`, `1` e `0`). Impostarla a
`false` equivale a non metterla. Un'opzione che prende un valore prende lo
stesso valore che prenderebbe sulla riga di comando, come numero o come stringa.
Un'opzione, `--deterministic`, può prendere un valore oppure no, e la sua chiave
fa lo stesso: `deterministic = true` usa il passo predefinito,
`deterministic = 20` ne indica uno, e `deterministic = false` lascia l'opzione
disattivata.
[[configorder]]
=== Da dove vengono letti i file di configurazione
`controls.cfg`, `settings.cfg` e `gamecontrollerdb.txt` vengono cercati tutti
negli stessi quattro posti, nello stesso ordine, e un file letto dopo vince su
uno letto prima:
. *La cartella dello script principale del gioco,* che per un gioco
impacchettato sta dentro il suo file `.game`. È quello che ha fornito l'autore
del gioco, quindi viene letto per primo: imposta i valori predefiniti del
gioco e niente di più.
. *La cartella da cui è stato avviato Singe.* I file della macchina, come la
disposizione dei pulsanti di una console portatile, vanno qui, e vincono su
quelli forniti da un gioco. Un file sostituisce solo quello che nomina,
quindi per togliere a un pulsante l'assegnazione di un gioco, nomina
quell'input: `INPUT_TEST_MODE = { SCANCODE.F2 }` nel `controls.cfg` della
macchina lascia la modalità test solo sulla tastiera, su qualunque pulsante
l'avesse messa un gioco.
. *La cartella sopra la cartella dei dati del gioco,* per i file condivisi da
tutti i giochi che usano quella cartella dei dati.
. *La cartella dei dati del gioco.* I tuoi file per un gioco, che vincono su
tutto il resto.
Con `--datadir=.` la cartella dei dati è la cartella del gioco stesso, e in
quel caso il file che si trova lì viene letto una volta sola, come quello
del gioco. `--keymapfile` sostituisce l'intera ricerca di `controls.cfg` con un
unico file indicato.
[#_what_wins]
=== Chi vince
. Il valore predefinito interno.
. Il file delle impostazioni.
. La voce del gioco in `games.dat`, per le poche impostazioni che contiene (vedi xref:Reference.adoc#gamesdat[games.dat]).
. `machine.cfg`, per il ritardo audio e la geometria dell'immagine che salvano
gli strumenti di servizio (vedi <<servicetools,Gli strumenti di servizio>>).
. La riga di comando, che vince sempre.
Un file delle impostazioni, in altre parole, è un insieme di valori predefiniti,
non qualcosa che hai digitato: se una voce di `games.dat` dà a un gioco una
risoluzione o un bordo Sinden, quella voce descrive comunque il gioco meglio di
un file valido per tutta la macchina. Qualsiasi cosa digitata davvero sulla riga
di comando batte entrambi. `machine.cfg` sta subito sotto la riga di comando
perché qualcuno ha regolato l'immagine guardando proprio questo monitor, il che
è una prova migliore di qualsiasi file scritto altrove; il ritardo audio fa del
tutto eccezione a quest'ordine, perché si somma al ritardo del gioco invece di
sostituirlo.
Le opzioni che indicano il gioco (`--framefile`, `--disc`, `--entry`), indicano
una cartella (`--gamedir`, `--datadir`), devono agire prima che il file si
possa trovare (`--help`, `--apiversion`, `--noconsole`, `--pack`, `--patch`,
`--unpack`) o valgono per un solo avvio (`--record`, `--refresh`) non si
possono impostare in un file delle impostazioni. Una chiave
che non è un'opzione, che è una di quelle, o un valore che l'opzione non accetta
sono un errore che nomina il file e la chiave, così un errore di battitura non
viene mai ignorato in silenzio:
----
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.
----
Con `--program` o `--trace`, l'intestazione in cima a `trace.txt` elenca ogni
impostazione applicata, così non c'è mai il dubbio su quale file abbia ricevuto
un gioco in esecuzione.
[[commandlineoptions]]
=== Opzioni da riga di comando
----
Singe [OPTIONS] gameName
----
Il nome del gioco è l'unico argomento obbligatorio. Può essere uno script
`.singe`, una cartella che contiene uno script con lo stesso nome (`MyGame`
trova `MyGame/MyGame.singe`) o un gioco impacchettato (`MyGame.game` avvia la
prima voce del `games.dat` che contiene, `--entry=N` un'altra). Uno script o una
cartella avviati in questo modo girano anche con la loro voce di `games.dat`,
quando ce n'è una che li nomina (vedi xref:Reference.adoc#gamesdat[games.dat]),
così un gioco si gioca dalla riga di comando come dal menu. Per un gioco
laserdisc (`--disc`) senza `--framefile`, Singe cerca accanto allo script un
video con lo stesso nome di base e una qualsiasi estensione che FFmpeg sappia
demultiplexare, e poi un framefile `.txt`.
Le opzioni sono raggruppate secondo quello che fanno.
[#_the_game_and_its_files]
==== Il gioco e i suoi file
Quale gioco parte, dove stanno lui e i suoi dati, e su che cosa si gioca.
[cols="1,2",options="header"]
|===
| Opzione | Scopo
| `-C`, `--canvas=WxH` | Dimensioni del mondo per un gioco senza disco, di base 720x480. Viene ignorata quando c'è un disco.
| `-d`, `--datadir=PATHNAME` | Cartella per tutto quello che Singe scrive: indici dei video, `trace.txt`, screenshot, salvataggi, il `menu.dat` del menu. Al suo interno viene creata una sottocartella con il nome della cartella del gioco (per un gioco impacchettato, una con il nome del database e poi una con il nome della cartella dello script che contiene). Di base è `data` nella cartella dei giochi. Singe 2.x scriveva invece accanto al gioco; le cartelle dei giochi possono essere di sola lettura, quindi lì non si scrive più niente.
| `-D`, `--disc` | Riproduce un video laserdisc: quello indicato da `--framefile`, o il video trovato accanto allo script. Implicita con `--framefile`. Senza questa opzione, un video accanto allo script viene segnalato e ignorato.
| `-E`, `--entry=N` | Avvia l'N-esima voce del `games.dat` dentro un file `.game` (di base 1). Vedi xref:Reference.adoc#singlefile[Giochi in un solo file].
| `-v`, `--framefile=FILENAME` | File video o framefile da usare al posto di quello trovato accanto allo script.
| `-G`, `--gamedir=PATHNAME` | La cartella che contiene i giochi, i file `.game` impacchettati e la cartella di supporto `Singe`, quando l'eseguibile sta da un'altra parte. Diventa la cartella di lavoro, quindi il nome del gioco, un `--datadir` relativo e i nomi per l'impacchettamento partono tutti da lì; i percorsi assoluti funzionano così come sono. Di base è la cartella corrente.
| `-c`, `--showcalculated` | Stampa gli intervalli di fotogrammi di ogni segmento di un framefile, per il debug.
|===
[#_display]
==== Visualizzazione
La finestra e come l'immagine la riempie.
[cols="1,2",options="header"]
|===
| Opzione | Scopo
| `-a`, `--aspect=N:D` | Forza le proporzioni usate per scegliere le dimensioni della finestra (`4:3`, `16:9`, `16:10`).
| `-f`, `--fullscreen` | Schermo intero esclusivo alla risoluzione del desktop.
| `-w`, `--fullscreen_window` | Finestra senza bordi che copre il desktop.
| `--linearscale=BOOLEAN` | Smussa l'overlay mentre la finestra lo scala (`true`) o prende il pixel più vicino (`false`, che mantiene nitida la pixel art). Accetta `true`, `false`, `yes`, `no`, `on`, `off`, `1` o `0`. Uno script lo cambia durante l'esecuzione con `setOverlayLinearScale`. Predefinito: `true`, che è come ha sempre disegnato ogni versione di Singe; il predefinito di Hypseus è l'opposto.
| `-k`, `--nologos` | Salta le schermate iniziali.
| `-r`, `--rotate=DEGREES` | Ruota l'intera presentazione in senso orario di `0`, `90`, `180` o `270` gradi, per un cabinato con il pannello montato di lato. Il video, l'overlay, le GUI, la scena 3D e le particelle ruotano tutti insieme, un quarto di giro scambia la forma dell'immagine così da riempire una finestra verticale, e le posizioni del mouse e della pistola ottica vengono ruotate all'indietro così un clic arriva ancora dove è disegnato. Sono accettati solo i quattro angoli retti. Uno script può cambiarla con `vldpSetRotate`.
| `--screen=N` | Apre la finestra sullo schermo `N`, contando da `1` come li conta Hypseus. Un numero più grande del numero di schermi elenca gli schermi presenti ed esce. Predefinito: lo schermo principale.
| `-u`, `--stretch` | Allunga il video per riempire la finestra invece di mantenerne le proporzioni.
| `-x`, `--xresolution=VALUE` | Larghezza della finestra. Se l'altezza manca, viene presa dalla voce corrispondente della tabella delle risoluzioni interna. Una dimensione più grande dello schermo -- chiesta qui o dal `games.dat` di un gioco -- viene ridotta per starci, mantenendone la forma, e la traccia lo dice. Quando si gira senza schermo, con `SDL_VIDEODRIVER=offscreen`, non c'è nessuno schermo a cui adattarsi, e la finestra mantiene le dimensioni richieste.
| `-y`, `--yresolution=VALUE` | Altezza della finestra.
|===
[#_picture_placement_bezels_and_guns]
==== Posizione dell'immagine, bezel e pistole
Per un cabinato: dove sta l'immagine, la grafica intorno, e il bordo che segue una pistola Sinden. Vedi <<cabinet,Preparare un cabinato>>.
[cols="1,2",options="header"]
|===
| Opzione | Scopo
| `-B`, `--bezel=FILENAME` | Disegna la grafica del cabinato intorno all'immagine. Il file viene cercato nella cartella `bezels` della cartella dei giochi (un gioco impacchettato può portarsi il proprio) e poi nella cartella `bezels` della cartella dei dati; `--bezeldir` indica una cartella diversa. Va bene qualsiasi formato che SDL_image sappia leggere, e la trasparenza viene mantenuta. Un file di accompagnamento accanto dice dove va l'immagine al suo interno; se manca, l'immagine tiene tutta la finestra e la collocano `--shiftx`, `--shifty` e `--scalefactor`. Una grafica che non si trova chiude il programma. Vedi <<bezels,Bezel>>.
| `-I`, `--bezeldir=PATHNAME` | La cartella che contiene la grafica di `--bezel`, al posto di `bezels`. Relativa alla cartella dei giochi, o assoluta. Viene cercata solo quella cartella. Vedi <<bezels,Bezel>>.
| `-F`, `--bezelflip` | Disegna la grafica del bezel davanti all'immagine invece che dietro, come fa Hypseus con i propri bezel; la trasparenza della grafica diventa allora il buco attraverso cui si vede il gioco. Senza questa opzione la grafica sta dietro a tutto e l'immagine ne copre il ritaglio. Uno script sceglie con `setOverlayOnTop` se l'overlay e le GUI restano sopra la grafica. Vedi <<bezels,Bezel>>.
| `-b`, `--scalefactor=PERCENT` | Rimpicciolisce l'immagine attorno al suo centro fino al `PERCENT` (da `25` a `100`) della finestra, per gli schermi che perdono i bordi per l'overscan. Le posizioni del mouse e della pistola ottica seguono l'immagine rimpicciolita. Uno script può cambiarlo mentre il gioco gira con `vldpSetScale`. Si combina con `--shiftx`, `--shifty`, `--rotate` e `--sindengun`; vedi <<videorect,Il rettangolo video>>.
| `-X`, `--shiftx=PERCENT` | Sposta l'immagine in orizzontale dentro lo spazio lasciato da `--scalefactor`, da `-100` (tutta a sinistra) a `100` (tutta a destra), `0` al centro. Come in Hypseus, lo spostamento è una percentuale di quello spazio e nient'altro, quindi con `--scalefactor=100` non c'è spazio e lo spostamento non fa niente: prima riduci la scala. Vedi <<videorect,Il rettangolo video>>.
| `-Y`, `--shifty=PERCENT` | Sposta l'immagine in verticale dentro lo spazio lasciato da `--scalefactor`, da `-100` (tutta in alto) a `100` (tutta in basso), `0` al centro. Alla scala piena non fa niente, per lo stesso motivo. Vedi <<videorect,Il rettangolo video>>.
| `-S`, `--sindenedge=WHERE` | Dove sta il bordo Sinden: `video` lo disegna intorno all'immagine, `window` sul margine dello schermo. Senza l'opzione decide il bezel: una grafica intorno all'immagine mette il bordo sul margine della finestra, perché la telecamera della pistola vede tutto lo schermo, e senza grafica il bordo va intorno all'immagine come ha sempre fatto. Sul margine della finestra i due anelli vengono disegnati come anelli, per ultimi, così la grafica tra loro e l'immagine resta visibile. Vedi <<bezels,Bezel>>.
| `-g`, `--sindengun='PARAMS'` | Disegna il bordo che segue una pistola ottica Sinden e mappa le posizioni del mouse e della pistola ottica nell'immagine al suo interno: l'anello nero, quando c'è, corre lungo il margine del video, l'anello bianco sta al suo interno, e il gioco viene disegnato in mezzo. `PARAMS` è un unico elenco di numeri tra virgolette: `WW` (larghezza del bordo bianco in pixel video); `WW WB` (larghezza del bianco, poi un bordo nero al suo esterno); `RW GW BW WW` (un colore e una larghezza personalizzati per il bordo); `RW GW BW WW WB` (lo stesso più una larghezza del nero); oppure `RW GW BW WW RB GB BB WB` (colori e larghezze personalizzati per entrambi). Un bordo che non lascia spazio al gioco (il doppio delle larghezze del bianco e del nero insieme che raggiunge il lato più corto del video), o una larghezza negativa, chiude il programma con un messaggio. Gli anelli vengono disegnati intorno a quello che hanno lasciato `--shiftx`, `--shifty` e `--scalefactor`, così un bordo resta un bordo comunque sia collocata l'immagine; vedi <<videorect,Il rettangolo video>>.
|===
[#_sound]
==== Suono
[cols="1,2",options="header"]
|===
| Opzione | Scopo
| `--altaudio=SUFFIX` | Riproduce `<base><SUFFIX>.ogg` accanto al video del disco invece dell'audio che contiene, per un'edizione le cui altre lingue arrivano come file separati: `--altaudio=-es` accanto a `game.m2v` riproduce `game-es.ogg`. Tutti i segmenti di un framefile cambiano insieme. Un file che non c'è lascia in riproduzione l'audio del gioco e stampa un avviso. La chiave `AUDIO_SUFFIX` in `games.dat` fa lo stesso per un solo gioco, e uno script lo cambia durante l'esecuzione con `discAudioSuffix`. Predefinito: nessuno.
| `-o`, `--audio=TRACK` | Traccia audio predefinita (contando da zero) per i video che ne hanno più di una, come le edizioni multilingue.
| `-A`, `--audiodelay=MS` | Compensa un audio che si sente `MS` millisecondi più tardi di quanto il motore possa misurare (negativo quando si sente in anticipo), da `-1000` a `1000`. Vedi xref:Reference.adoc#audiosync[Sincronizzazione dell'audio].
| `-s`, `--nosound` | Silenzia tutto l'audio.
| `--soundfont=FILE` | Il SoundFont (`.sf2`) con cui vengono sintetizzati i file MIDI. Singe non ne fornisce nessuno, perché uno buono pesa decine di megabyte per un formato che quasi nessun gioco usa. Senza questa opzione cerca `Singe/soundfont.sf2` -- così un gioco impacchettato può portarsi il proprio -- e poi nei posti in cui una distribuzione ne installa uno. La riga `SoundFont:` dell'intestazione della traccia dice quale è stato usato, o che non ne è stato trovato nessuno. Vedi xref:Reference.adoc#midi[MIDI]. Predefinito: la ricerca.
| `--startsilent` | Parte in silenzio e resta in silenzio fino al primo input di qualsiasi tipo, poi suona ai volumi configurati. Per un cabinato in modalità attract in una sala tranquilla. `--nosound` ha la precedenza. Predefinito: disattivato.
| `-e`, `--volume_nonvldp=PERCENT` | Volume degli effetti sonori e dei video aggiuntivi, da `0` a `100`.
| `-l`, `--volume_vldp=PERCENT` | Volume del laserdisc, da `0` a `100`.
|===
[#_input]
==== Input
Vedi <<controls,Comandi>>.
[cols="1,2",options="header"]
|===
| Opzione | Scopo
| `--absolutes_only` | Tiene solo i mouse che riportano una posizione assoluta, cosa che una vera pistola ottica fa e un mouse normale no. A ManyMouse non si può chiedere che cosa sia un dispositivo, quindi un dispositivo conta come assoluto da quando ha riportato una posizione assoluta, e non prima; vedi <<mousedevices,Mouse, pistole e chi sceglie>>. Hypseus la scrive `-absolutes-only`; qui il nome usa un trattino basso perché una chiave del file delle impostazioni deve essere un nome Lua. Predefinito: disattivato.
| `--gamepad_reorder=DIGITS` | Quale controller fisico occupa quale slot dei controller, come posizioni di enumerazione contate da `0`, una per ogni slot in ordine: `--gamepad_reorder=10` fa del secondo controller trovato il giocatore uno e del primo il giocatore due. Si scrive con cifre semplici (`3210`) o separate da virgole o spazi, come lo scrive Hypseus; una posizione ripetuta viene rifiutata. Le posizioni non nominate riempiono gli slot rimasti, nell'ordine in cui SDL le ha trovate, e una posizione senza un controller dietro lascia vuoto il suo slot. Predefinito: l'ordine di SDL.
| `--haptic=STEP` | Il livello di vibrazione più forte che un gioco può usare, da `0` a `4`. `0` spegne del tutto la vibrazione, e un numero più basso attenua un gioco che chiede di più: `controllerDoRumble` non vibra mai più forte di così. Predefinito: `4`, cioè ogni livello che un gioco chiede.
| `--joymouse=BOOLEAN` | Lascia che la levetta sinistra del controller nello slot `0` guidi il cursore del mouse, per un gioco con pistola ottica su un cabinato senza mouse. `--joymouse=false` è il `-nojoymouse` di Hypseus, e uno script lo imposta con `joyMouseEnable()`. Vedi <<joymouse,Guidare il mouse con una levetta>>. Predefinito: `false`, mentre in Hypseus è attivo -- il `controls.cfg` fornito lega già quella levetta alle quattro direzioni.
| `--js_range=SPEED` | Quanto velocemente quella levetta lo guida, da `1` a `20`, in pixel video per fotogramma a fondo corsa. Predefinito: `5`, come in Hypseus.
| `--keymapfile=FILENAME` | Legge le assegnazioni dei comandi da questo file invece di cercare `controls.cfg` nei quattro posti, così un front-end può essere certo di quali assegnazioni abbia ricevuto un gioco. I valori predefiniti interni valgono comunque sotto di esso, quindi anche un file parziale funziona, e un file che non c'è chiude il programma. Predefinito: la ricerca nei quattro posti, descritta in <<controls,Comandi>>.
| `--manymouse` | Distingue fino a quattro mouse qualunque cosa chieda il gioco, cosa di cui un cabinato a due pistole ha bisogno da un gioco che non chiama mai da sé `mouseSetMode(MOUSE_MANY)`. La scelta dell'utente ha la precedenza su quella del gioco: `mouseSetMode(MOUSE_SINGLE)` non la spegne più. Predefinito: disattivato, e decide il gioco.
| `--mapjoysticks=BOOLEAN` | Scrive un'assegnazione da controller per un dispositivo che SDL non riconosce, così un encoder arcade, uno spinner, un volante o una cloche viene aperto come uno tra `GAMEPAD_0` e `GAMEPAD_3`, come qualsiasi altra cosa. `false` lascia chiuso un dispositivo del genere, come facevano le versioni precedenti. Vedi <<devices,Ogni dispositivo è un controller>>. Predefinito: `true`.
| `-n`, `--nocrosshair` | Chiede al gioco di non disegnare il proprio mirino. Esposta agli script come `singeWantsCrosshairs()`.
| `--nogamepad` | Ignora tutti i controller, l'equivalente di `--nomouse`. Non ne viene aperto nessuno e nessun evento dei controller arriva al gioco, così un encoder arcade bloccato non può premere niente. Predefinito: disattivato.
| `-m`, `--nomouse` | Disattiva del tutto l'input del mouse e della pistola ottica.
| `--quitchord=BUTTONS` | Pulsanti del primo controller che fanno uscire quando sono tenuti premuti insieme, qualunque cosa assegni il gioco e anche quando ha disattivato il proprio tasto di uscita: la via d'uscita su una console portatile senza tastiera. Un gioco esce tornando al menu da cui è stato avviato, e il menu chiude Singe. Da due a quattro nomi di pulsanti dei controller di SDL uniti da `+`, come `back+start` (Select e Start); i nomi sono `a`, `b`, `x`, `y`, `back`, `guide`, `start`, `leftstick`, `rightstick`, `leftshoulder`, `rightshoulder`, `dpup`, `dpdown`, `dpleft` e `dpright`, come li dà l'assegnazione del controller, e `--program` scrive nella traccia il nome di ogni pulsante premuto. La pressione di uno dei pulsanti della combinazione aspetta gli altri per un quarto di secondo prima di fare quello che fa normalmente, così Start non avvia un gioco dal menu mentre stai cercando di uscirne. Va nel `settings.cfg` della macchina. Predefinito: nessuno.
| `--trigger_threshold=PERCENT` | Quanto deve scorrere un grilletto analogico prima di contare come pulsante, come percentuale della corsa completa -- l'unità di Hypseus, il cui predefinito è `99.5`. `0` lascia i grilletti su `DEAD_ZONE`, che è quello che Singe ha sempre dato loro. Vince su `TRIGGER_THRESHOLD` in `controls.cfg`; `DEAD_ZONES` vince su entrambi. Da `0` a `100`; vedi <<deadzones,Zone morte e grilletti>>. Predefinito: `0`.
| `--xratio=FACTOR` | La scala orizzontale che un gioco con pistola ottica legge con `ratioGetX()` per allungare le proprie coordinate della pistola su uno schermo la cui forma non corrisponde al video. Singe non ci fa niente; i conti li fa il gioco, esattamente come in Hypseus. Da `0` a `100`, con due decimali come li tiene Hypseus. Predefinito: `0`, che ogni gioco che lo legge tratta come `1`.
| `--yratio=FACTOR` | Lo stesso per `ratioGetY()`. Predefinito: `0`.
|===
[#_video_decoding_and_performance]
==== Decodifica video e prestazioni
Soprattutto per le macchine piccole; vedi <<handhelds,Console portatili e macchine piccole>>.
[cols="1,2",options="header"]
|===
| Opzione | Scopo
| `--deinterlace=MODE` | Che cosa riceve un'immagine interlacciata: `auto` (il predefinito) deinterlaccia solo i fotogrammi che il file segna come interlacciati, `on` deinterlaccia ogni fotogramma, per un file con i flag sbagliati, e `off` non tocca mai l'immagine. Un laserdisc conteneva semiquadri interlacciati, e un rip che li ha conservati mostra l'effetto pettine su uno schermo progressivo; un rip deinterlacciato al momento della sua creazione non ha bisogno di niente qui. Per ogni immagine che entra ne esce una, quindi i numeri dei fotogrammi non si spostano mai. Predefinito: `auto`.
| `--monochrome` | Parte con l'immagine del disco in grigio. L'overlay, le GUI e la scena 3D mantengono il loro colore; uno script fa lo stesso con `vldpSetMonochrome`, e lo annulla. Predefinito: disattivato.
| `--scenequality=LEVEL` | Quanto disegna la scena 3D: `high`, tutto quello che un gioco chiede, o `low` per una GPU piccola -- una console portatile o un vecchio Raspberry Pi -- che disegna la scena a metà risoluzione in ogni direzione e lascia perdere antialiasing e bloom qualunque cosa chieda il gioco. L'immagine 3D è più morbida e le cose luminose non hanno alone, ma va molto più veloce dove il limite era la GPU; il disco, l'overlay e le GUI non vengono toccati. Va nel `settings.cfg` della macchina piuttosto che sulla riga di comando di un gioco, perché descrive la macchina. Predefinito: `high`.
| `-H`, `--softwarevideo` | Decodifica il video in software anche quando la piattaforma offre un decoder hardware (VA-API o VDPAU su Linux, il decoder V4L2 sul Pi, D3D11VA su Windows, VideoToolbox su macOS). Usalo per escludere o chiamare in causa il percorso hardware quando un video si comporta male; la traccia del programma dice quale decoder è in uso.
| `--zerocopy=BOOLEAN` | Passa i fotogrammi video decodificati in hardware direttamente alla GPU invece di copiarli attraverso la CPU: il decoder MPP di Rockchip e VA-API su Linux, disegnati con OpenGL ES. Risparmia gran parte del costo del video a schermo intero su una macchina piccola. Singe torna da solo alla copia quando il driver non accetta un fotogramma, o quando un gioco legge o modifica i pixel dell'immagine, e la traccia del programma dice che cosa sta facendo; `false` lo fa copiare fin dall'inizio, per escludere o chiamare in causa questo percorso. Predefinito: `true`.
|===
[#_cabinets_and_front_ends]
==== Cabinati e front-end
[cols="1,2",options="header"]
|===
| Opzione | Scopo
| `--apiversion` | Stampa sullo standard output una riga leggibile da una macchina che descrive questa build ed esce, per i front-end. Vedi <<apiversion,La riga della versione>>. Non viene stampato nient'altro.
| `--fvalue=NUMBER` | Un numero passato dal launcher al gioco, che lo legge con `getFValue()`. Singe non ci fa niente. Da `0` a `100000`, con tre decimali come li tiene Hypseus. Predefinito: `0`.
| `-h`, `--help` | Mostra il riepilogo delle opzioni ed esce.
| `--idleexit=SECONDS` | Esce dopo `SECONDS` senza input di alcun tipo -- nessun tasto, nessun pulsante, nessun asse dei controller, nessun mouse. Per un cabinato in modalità attract che deve restituire lo schermo. `0` non esce mai. Da `0` a `86400`. Predefinito: `0`.
| `--no_update_check` | Non chiede mai al servizio se esiste un Singe più recente. Altrimenti il menu controlla una volta al giorno e mostra quello che ha trovato sotto i dettagli del gioco; lo strumento Engine Update funziona comunque a mano. Predefinito: disattivato, quindi il controllo quotidiano avviene.
| `-z`, `--noconsole` | Non stampa niente (e su Windows non apre nessuna finestra della console).
| `--refresh` | Mette da parte la cartella di supporto `Singe` come `old-Singe-<version>`, con il nome della versione che l'ha scritta, e ne scrive una nuova. Serve per gli aggiornamenti: un file che una versione precedente forniva e questa no resta nella cartella messa da parte invece di stare in quella in uso. Non si cancella niente, e un secondo avvio mette da parte la propria come `old-Singe-<version>-1`. Lo strumento Engine Update lo passa al Singe con cui si riavvia.
|===
[#_making_and_testing_games]
==== Creare e collaudare giochi
Per le tracce vedi <<troubleshooting,Quando qualcosa va storto>>.
[cols="1,2",options="header"]
|===
| Opzione | Scopo
| `--deterministic[=MS]` | Solo per i test: ignora il tempo reale e fa girare l'intero motore su un orologio virtuale che avanza di `MS` millisecondi a ogni fotogramma, così lo stesso numero di fotogramma vuol dire sempre lo stesso istante. Anche il disco segue l'orologio virtuale, con i suoi fotogrammi che durano il tempo che valgono, e i generatori casuali ricevono come seme lo stesso numero, così un'esecuzione si ripete identica fino al pixel. Il valore è facoltativo ed è sia il passo sia il seme, da `1` a `1000`. Predefinito quando l'opzione è data senza valore: `15`, la durata di un fotogramma che deriva dalla frequenza del motore. In questa modalità il ritmo non ha senso, e nemmeno il suono, a meno che non ci sia anche `--record`, nel qual caso viene generato al passo con l'immagine; vedi xref:Reference.adoc#deterministic[Modalità di test deterministica]. Predefinito: disattivato.
| `-P`, `--pack=DIRECTORY` | Impacchetta il gioco in `DIRECTORY` nel database indicato dopo le opzioni, poi esce. Vedi xref:Reference.adoc#singlefile[Giochi in un solo file].
| `-T`, `--patch=GAME.game` | Sostituisce dei file nel gioco impacchettato prendendoli dalla cartella o dal database di patch indicato dopo le opzioni, poi esce.
| `--perfsync` | Con `--program`, aspetta che la GPU finisca ogni fase di un fotogramma prima di cronometrare la successiva, così le righe perf dicono a quale fase appartiene il tempo della GPU invece di lasciarlo tutto in `present`. Mentre è attiva tutto gira più lento, quindi serve per misurare, non per giocare; vedi <<perflines,Leggere le righe perf>>. Predefinito: disattivato.
| `-p`, `--program` | Scrive nella traccia l'attività del motore, sulla console e in `trace.txt` nella cartella dei dati. Il file si apre con un'intestazione che descrive la macchina; vedi xref:Reference.adoc#traceheader[L'intestazione della traccia]. Ogni cinque secondi dice anche dove è finito il tempo del fotogramma; vedi <<perflines,Leggere le righe perf>>.
| `--record=FILENAME` | Registra l'intera esecuzione, immagine e suono, in un MP4 in `FILENAME`, dal primo fotogramma finché Singe non esce. Con `--deterministic` ogni fotogramma viene conservato e il suono viene generato un passo alla volta insieme all'immagine, così i due corrispondono esattamente e mentre gira non si sente niente. Vedi <<recording,Registrare video>>. Predefinito: disattivato.
| `-R`, `--reload` | Sorveglia i file di script sciolti del gioco e lo riavvia da zero quando uno cambia; `F5` fa lo stesso a richiesta. Uno script che non si compila resta sorvegliato, così salvare la correzione lo ricarica. Per quando lavori a un gioco; vedi xref:Reference.adoc#reloading[Ricaricare mentre lavori].
| `-t`, `--trace` | Scrive nella traccia ogni chiamata all'API Lua, con la riga dello script che l'ha fatta, sulla console e in `trace.txt`. Il file si apre con un'intestazione che descrive la macchina; vedi xref:Reference.adoc#traceheader[L'intestazione della traccia].
| `-U`, `--unpack=GAME.game` | Scrive i file del gioco impacchettato nella cartella indicata dopo le opzioni, poi esce. Un database i cui nomi memorizzati finirebbero fuori da quella cartella viene rifiutato.
|===
Le opzioni si possono dare come `-x 640`, `-x640` o `--xresolution=640`. I
valori numerici vengono controllati; un valore sbagliato stampa il testo d'uso
ed esce. Le opzioni più recenti non hanno una lettera breve; l'alfabeto è
finito, e una lettera presa a caso non aiuterebbe nessuno.
Tutto ciò che è qui, tranne le opzioni che indicano il gioco, indicano una
cartella o devono agire prima che si possa trovare un file, si può impostare
anche in un file delle impostazioni, così un cabinato non ha bisogno di uno
script di avvio per ogni gioco. Vedi <<settings,Il file delle impostazioni>>.
[[apiversion]]
=== La riga della versione
`--apiversion` stampa una riga ed esce con stato `0`:
----
singe version=3.00 protocol=1
----
È un contratto per i front-end e la sua forma non cambierà:
* La riga termina con un a capo ed è l'unica cosa scritta sullo standard
output. Non viene stampato nient'altro, qualunque altra cosa ci sia sulla
riga di comando.
* Il primo campo è sempre `singe`.
* Ogni campo successivo è `key=value`, separato da un solo spazio, senza spazi
all'interno di un campo.
* `version` è la versione pubblicata, lo stesso numero che mostra il banner.
* `protocol` è la versione del formato di questa riga. Diventa `2` solo se le
regole qui sopra dovessero mai cambiare.
* Le versioni future potranno aggiungere campi. Chi legge deve ignorare le
chiavi che non conosce invece di trattarle come un errore.
[[cabinet]]
== Preparare un cabinato
I cabinati hanno bisogno di alcune cose che a un computer da scrivania non
servono: allontanare l'immagine dai bordi che il monitor nasconde, ruotarla per
uno schermo montato di lato, una grafica intorno, un bordo per una pistola
ottica Sinden e un tabellone segnapunti. Questo capitolo ti serve solo se stai
costruendo un cabinato. Imposta queste cose una volta per tutte nel
`settings.cfg` del cabinato, oppure usa lo strumento Display del menu (vedi
<<servicetools,Gli strumenti di servizio>>) per regolare l'immagine mentre la
guardi.
[[videorect]]
=== Il rettangolo video
Tutto quello che un gioco mostra -- il disco, l'overlay, le GUI, la scena 3D e
le particelle -- viene disegnato in un unico rettangolo, e una manciata di
opzioni decide dove sta quel rettangolo. Si applicano in quest'ordine:
. *La finestra, o il ritaglio del bezel.* Il rettangolo parte come l'intera
finestra. Singe lavora nelle coordinate proprie del video e lascia che la
finestra le adatti con le bande nere (`--stretch` invece riempie), quindi
niente qui dipende dalle dimensioni della finestra. Quando `--bezel` ha
caricato una grafica che dichiara un ritaglio, il rettangolo parte invece da
quel buco e tutto quello che segue colloca l'immagine al suo interno; vedi
<<bezels,Bezel>>.
. *`--scalefactor`.* Il rettangolo si riduce a quella percentuale di quello che
era all'inizio, attorno al proprio centro.
. *`--shiftx` e `--shifty`.* Poi il rettangolo si sposta dentro lo spazio
lasciato dalla scala, `-100` tutto contro un lato e `100` tutto contro
l'altro, che è quello che significano `-shiftx` e `-shifty` di Hypseus. Ne
seguono due conseguenze che vale la pena conoscere: l'immagine non può mai
essere spinta fuori dallo schermo, e *con `--scalefactor=100` non c'è spazio e
uno spostamento non fa proprio niente*. Per spostare l'immagine su un pannello
montato male, prima riduci la scala: `--scalefactor=90 --shiftx=-100` mette
l'immagine rimpicciolita tutta contro il lato sinistro.
. *`--sindengun`.* Il bordo viene applicato per ultimo, a quello che hanno
lasciato lo spostamento e la scala. L'anello nero prende il margine del
rettangolo, l'anello bianco sta al suo interno, e il gioco va dentro
entrambi, così un bordo resta un bordo comunque sia stata collocata
l'immagine. Una scala abbastanza piccola da non lasciare spazio al gioco
schiaccia i due anelli invece di inghiottirlo. Con una grafica del bezel
caricata il bordo va invece sul margine della finestra e lascia l'immagine
delle dimensioni che aveva già; in un caso o nell'altro decide
`--sindenedge`.
`--rotate` non fa parte di quell'ordine. Il fotogramma viene disegnato senza
rotazione e l'immagine finita viene ruotata in senso orario tutta insieme,
quindi uno spostamento muove l'immagine lungo gli assi propri del video e ruota
con essa. Un quarto di giro scambia anche la forma dell'area presentata, così
una finestra verticale viene riempita invece di ridursi a una striscia tra
bande nere.
Le posizioni del mouse e della pistola ottica fanno la stessa strada al
contrario: prima si toglie la rotazione, poi la posizione viene mappata nel
rettangolo, così un clic arriva dove lo vede il giocatore con qualsiasi
combinazione di queste opzioni. `vldpGetScale`, `vldpSetScale`, `vldpGetRotate`
e `vldpSetRotate` permettono a uno script di cambiare la scala e la rotazione
mentre il gioco gira; lo spostamento è un'impostazione dello schermo e non ha
una chiamata per gli script. Nessuna di queste è una chiave di `games.dat`: come
`--scalefactor`, descrivono lo schermo del giocatore, non il gioco.
[[bezels]]
=== Bezel
Un bezel (cornice decorativa) è la grafica intorno allo schermo di un cabinato.
Singe ne disegna uno a partire da un unico file immagine, con l'immagine del
gioco in un buco ritagliato al suo interno, e nello spazio che resta può
mostrare un tabellone segnapunti da sala giochi. Lo controllano tre opzioni, che
seguono la convenzione di Hypseus, così la riga di comando di un cabinato si
trasferisce senza modifiche.
`--bezel cabinet.png` indica la grafica. Viene cercata in quest'ordine:
. `bezels/cabinet.png` nella cartella dei giochi -- dentro un `.game`
impacchettato, la sua copia, così un gioco può portarsi dietro il proprio
bezel;
. `bezels/cabinet.png` nella cartella dei dati, dove la grafica di un utente può
stare senza toccare una cartella dei giochi di sola lettura.
`--bezeldir art/cabinets` sostituisce la cartella `bezels` con quella che
indica, relativa alla cartella dei giochi o assoluta, e allora viene cercata
solo quella cartella. Va bene qualsiasi formato che SDL_image sappia leggere
(`.png` è la scelta sensata, perché la trasparenza conta). Una grafica indicata
dall'opzione che Singe non riesce a trovare chiude il programma, invece di farlo
girare senza.
La grafica viene disegnata su tutta la finestra, qualunque forma abbiano l'una e
l'altra, quindi si allunga con la finestra esattamente come l'immagine. Dalle le
proporzioni con cui pensi di giocare.
[#_the_cutout]
==== Il ritaglio
Accanto all'immagine, e con il suo stesso nome, un file di accompagnamento dice
dove va l'immagine del gioco: `bezels/cabinet.png` è descritto da
`bezels/cabinet.cfg`. È un file Lua, come `controls.cfg`, e imposta una tabella
nei *pixel propri* della grafica:
[source,lua]
----
-- Il buco in cabinet.png in cui si disegna l'immagine, nei pixel propri della grafica.
CUTOUT = { x = 200, y = 120, width = 800, height = 500 }
----
Tutti e quattro i campi sono obbligatori e il rettangolo deve stare dentro la
grafica; un file di accompagnamento che non si esegue, o che indica un
rettangolo fuori dall'immagine, chiude il programma con un messaggio. Siccome i
numeri sono quelli propri della grafica, restano giusti a qualsiasi dimensione
della finestra: l'immagine e il buco vengono scalati insieme.
Con un ritaglio, l'immagine viene disegnata in quel buco -- allungata per
riempirlo, quindi è il buco a decidere la forma dell'immagine -- e
`--scalefactor`, `--shiftx` e `--shifty` lavorano poi *al suo interno*,
rimpicciolendo e spostando di poco l'immagine nel buco. Senza file di
accompagnamento l'immagine tiene tutta la finestra, esattamente come senza
bezel, e quelle tre opzioni la collocano come hanno sempre fatto. Vedi
<<videorect,Il rettangolo video>>.
Il buco stesso dovrebbe essere trasparente nell'immagine. Di base Singe disegna
la grafica dietro l'immagine del gioco, quindi un centro opaco verrebbe
semplicemente coperto, ma `--bezelflip` mette la grafica davanti, e allora solo
la sua trasparenza lascia passare il gioco.
[#_draw_order]
==== Ordine di disegno
Senza `--bezelflip` la grafica è la prima cosa del fotogramma: l'immagine,
l'overlay, le GUI, la scena 3D e le particelle si disegnano tutti sopra di essa.
Con `--bezelflip` la grafica si disegna invece davanti all'immagine, che è
l'ordine che Hypseus usa per i propri bezel, così una cornice con bordi sfumati
o sagomati si sovrappone correttamente all'immagine.
In quel caso è uno script a decidere che cosa succede all'overlay:
xref:Reference.adoc#setoverlayontop[`setOverlayOnTop(true)`] disegna l'overlay e le GUI sopra
la grafica, e `false` (il predefinito, anche in Hypseus) lascia la grafica sopra
di loro. Con la grafica dietro l'immagine l'impostazione non cambia niente,
perché tutto sta già sopra.
xref:Reference.adoc#mainbezelloaded[`mainBezelLoaded()`] dice a uno script se è caricata una grafica
e gli dà l'identificatore della grafica, lo stesso numero che riporta Hypseus,
così un gioco scritto per un bezel particolare può riconoscerlo.
Le GUI nello spazio dello schermo e il pannello dei punteggi si disegnano sempre
sopra la grafica, dato che il loro scopo è proprio starci sopra.
[#_the_sinden_border]
==== Il bordo Sinden
Una pistola ottica Sinden cerca sullo schermo un bordo luminoso. Con una grafica
del bezel caricata, quel bordo va sul *margine della finestra*, non intorno
all'immagine, perché la telecamera della pistola vede tutto lo schermo, ed è lì
che `--sindengun` lo mette appena viene caricato un bezel. Lì viene disegnato
come due anelli, dopo tutto il resto, così la grafica tra il bordo e l'immagine
resta visibile e niente dipinge sopra l'anello bianco. Senza bezel il bordo va
intorno all'immagine, come ha sempre fatto, e la rimpicciolisce.
`--sindenedge video` o `--sindenedge window` scavalca quella scelta in un senso
o nell'altro: un cabinato con pistola la cui grafica è solo una cornice sottile
può volere comunque il bordo intorno all'immagine, e un cabinato senza alcuna
grafica può volerlo sul margine dello schermo.
[#_the_score_panel]
==== Il pannello dei punteggi
Sedici dei giochi Singe di Hypseus possono pilotare un tabellone segnapunti da
sala giochi: i crediti, e un punteggio e un conteggio delle vite per ciascuno
dei due giocatori. In Singe quel tabellone segnapunti è il documento RmlUi
`Singe/scoreBezel.rml`, con lo stile di `Singe/scoreBezel.rcss`, entrambi scritti
accanto agli altri file di supporto. Come tutto ciò che sta nella cartella `Singe`,
vengono riscritti da capo a ogni avvio, quindi modificarli non cambia nulla a
lungo: un gioco che vuole un altro aspetto distribuisce le proprie copie,
`scoreBezel.rml` accanto al suo script con il collegamento a un foglio di stile
tutto suo, e Singe usa quelle. Lo stile fornito imita i display a sette
segmenti: ogni indicatore mostra le sue cifre debolmente illuminate dietro il
valore attuale, come fa un display vero.
Il pannello è *spento* finché un gioco non lo chiede con
xref:Reference.adoc#scorebezelenable[`scoreBezelEnable(true)`], ed è così che viene distribuito
anche Hypseus, quindi un gioco che non lo chiede mai si comporta esattamente come
prima e disegna il proprio tabellone segnapunti con gli sprite.
xref:Reference.adoc#scorebezelgetstate[`scoreBezelGetState()`] è la domanda che ognuno di questi
giochi fa per prima.
Dove va viene deciso per te: il pannello occupa la più alta delle due fasce che
l'immagine lascia sopra e sotto di sé -- lo spazio che di solito lascia il
ritaglio di un bezel -- centrato sull'immagine, e si stende lungo il fondo
dell'immagine quando nessuna delle due fasce è abbastanza alta da contenerlo.
Viene disegnato come una GUI nello spazio dello schermo, quindi un gioco può
mettere le proprie GUI sulla grafica accanto a esso con
xref:Reference.adoc#guidrawscreen[`guiDrawScreen`].
Lo `scoreBezelEnable` di Hypseus prende un secondo argomento che sceglie tra i
suoi cinque backend per il tabellone segnapunti. Singe ne ha uno solo, quindi l'argomento
viene accettato e ignorato.
[[handhelds]]
== Console portatili e macchine piccole
Singe gira sul Raspberry Pi e su console portatili ARM economiche come la R36S.
Lì funzionano gli stessi giochi che su un computer da scrivania, ma una macchina
piccola ha bisogno di un piccolo aiuto per farli girare bene.
[#_what_a_small_machine_needs]
=== Che cosa serve a una macchina piccola
Sprite, testo, suono e video funzionano ovunque. La scena 3D e l'aspetto
elegante del menu hanno bisogno di un chip grafico con Vulkan o OpenGL ES 3.1.
* Un Raspberry Pi 4 o successivo li ha entrambi, quindi funziona tutto. Un Pi 3
ha solo OpenGL ES 2.0, che non basta per il 3D. Fa comunque girare i giochi
2D.
* La maggior parte delle console portatili, R36S compresa, ha un chip grafico
Mali con OpenGL ES 3.1, quindi anche lì il 3D funziona.
* Su una macchina che non ha né l'uno né l'altro, il menu usa un aspetto più
semplice che non ne ha bisogno.
La prima volta che avvii un gioco 3D, Singe costruisce i suoi shader, e su una
macchina piccola può volerci qualche secondo. Vengono salvati nella cartella
`Singe` dentro la cartella dei dati, quindi succede una volta sola.
[#_settings_for_a_small_machine]
=== Impostazioni per una macchina piccola
Metti queste righe nel `settings.cfg` accanto all'eseguibile di Singe, così le
usano tutti i giochi:
`scenequality = "low"`::
Disegna la scena 3D a metà dimensione, senza antialiasing né bloom. Il 3D appare
un po' più morbido, ma gira molto più veloce. Video, sprite e menu non ne
risentono.
`zerocopy = true`::
È già il valore predefinito. Il video va dal decoder hardware direttamente al
chip grafico senza che la CPU lo copi. È questo che permette a una console
portatile di riprodurre video laserdisc alla massima velocità. Disattivalo solo
se un video si comporta male e vuoi escludere questa causa.
`quitchord = "back+start"`::
Le console portatili non hanno il tasto Esc. Tenendo premuti Select e Start si
esce dal gioco tornando al menu, e dal menu tornando al tuo sistema, comunque
sia configurato il gioco.
[#_the_r36s_and_arkos]
=== La R36S e ArkOS
La R36S e le console portatili simili con ArkOS usano la build Linux `aarch64`
di Singe. Metti l'eseguibile di Singe, la sua cartella `Singe`, `Menu.sh` e i
tuoi giochi in un'unica cartella, per esempio `/roms/singe`. Avvia `Menu.sh`
una volta, così Singe può creare i suoi file di supporto.
Per avviare Singe dal menu Ports, aggiungi a `/roms/ports` uno script come
quello qui sotto. Queste console portatili sono lente ad accelerare il
processore e il chip grafico, quindi lo script li porta alla massima velocità
mentre Singe gira e li rimette com'erano quando esce.
[source,bash]
----
#!/bin/bash
# /roms/ports/Singe.sh: Singe nel 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 non comunica ai giochi i pulsanti Select e Start, quindi la combinazione
di uscita non funzionerà finché non aggiungi questo `gamecontrollerdb.txt`
accanto all'eseguibile di Singe (vedi <<gamecontrollerdb,gamecontrollerdb.txt>>):
----
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,
----
Se un pulsante non fa quello che ti aspetti, avvia Singe una volta con
`--program` e premilo. La traccia mostra il nome di ogni pulsante che premi, o
il suo numero se l'assegnazione qui sopra non lo comprende.
Infine, aggiungi un `controls.cfg` accanto all'eseguibile di Singe. Questo mette
il gettone e l'avvio su Select e Start, e tiene i menu di test e di servizio di
un gioco lontani dai pulsanti frontali, dove alcuni giochi li mettono.
[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 }
----
Questo file vince su quello incluso in un gioco (vedi
<<configorder,Da dove vengono letti i file di configurazione>>). La pausa e lo
screenshot vengono spostati sulla tastiera perché di solito Singe li mette su
Start e Select.
[[troubleshooting]]
== Quando qualcosa va storto
[#_the_trace]
=== La traccia
Avvia Singe con `--program` (o `-p`) per vedere che cosa sta facendo. Tutto
viene stampato sulla console e salvato in `trace.txt` nella cartella dei dati
del gioco. Se segnali un problema, allega il `trace.txt` di un'esecuzione con
`--program`. `--trace` (o `-t`) registra anche ogni chiamata Lua che fa un
gioco, cosa utile soprattutto quando scrivi un gioco.
Se Singe va in crash su Linux o macOS, scrive sulla console e in `trace.txt` il
punto in cui si è bloccato.
`trace.txt` contiene solo i messaggi di Singe. I messaggi del sistema audio, del
decoder video e del driver grafico vanno solo sulla console. Quando il problema
potrebbe essere lì, salva anche la console. Su Linux:
----
./Menu.sh --program &> singe.log
----
[[perflines]]
=== Leggere le righe perf
Con `--program`, ogni cinque secondi la traccia dice dove è finito il tempo,
come medie per ogni giro del ciclo dei fotogrammi:
----
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` -- l'avanzamento del video laserdisc e il caricamento del suo
fotogramma sulla GPU.
* `script` -- la funzione `onOverlayUpdate` del gioco, che la riga
`Perf script` divide tra il Lua vero e proprio e le chiamate al motore che ha
fatto, a partire dalle più costose.
* `scene` -- il disegno della scena 3D.
* `gui` -- l'impaginazione e il disegno dei documenti GUI.
* `overlay` -- l'invio alla GPU di quello che è cambiato sull'overlay.
* `compose` -- solo con `--perfsync`: la GPU che disegna insieme l'immagine,
l'overlay e le GUI.
* `present` -- la visualizzazione del fotogramma, che comprende l'attesa del
prossimo aggiornamento dello schermo.
* `other` -- tutto il resto: input, suono, fisica e così via.
La riga propria di un video dice quanto velocemente si decodifica e quanto di
ogni fotogramma se n'è andato per ricopiarlo dal decoder hardware e convertirne
i colori; zero per entrambi vuol dire che i suoi fotogrammi vanno alla GPU senza
essere copiati.
La GPU lavora in ritardo rispetto alla CPU, quindi senza `--perfsync` il suo
tempo finisce dovunque la CPU debba aspettarla la volta successiva, che di
solito è `present`. Un `present` grande alla frequenza piena dello schermo è
solo l'attesa dell'aggiornamento; un `present` grande al di sotto di essa vuol
dire che la GPU è occupata. `--perfsync` fa aspettare la GPU a ogni fase prima
che cominci la successiva, quindi `scene`, `gui`, `overlay` e `compose`
comprendono il loro tempo di GPU e a `present` resta l'attesa
dell'aggiornamento. Mentre è attiva la frequenza dei fotogrammi cala, perché la
CPU e la GPU non lavorano più nello stesso momento; confronta le fasi tra loro,
non con la frequenza dei fotogrammi.
[#_a_button_does_nothing]
=== Un pulsante non fa niente
Apri lo strumento Input Test nel menu (vedi <<servicetools,Gli strumenti di
servizio>>) e premi il pulsante. Se lo strumento lo vede, è il gioco a
ignorarlo, quindi controlla il `controls.cfg` del gioco. Se lo strumento non lo
vede, controlla il tuo `controls.cfg`, o l'assegnazione del tuo controller in
`gamecontrollerdb.txt`. Avviando con `--program` vedi ogni pulsante mentre lo
premi.
[#_sound_and_picture_are_out_of_sync]
=== Suono e immagine non sono sincronizzati
Alcuni televisori, amplificatori e altoparlanti senza fili ritardano il suono.
Usa lo strumento Audio Delay del menu per misurare il ritardo. Singe lo ricorda
per tutti i giochi. Per i dettagli vedi
xref:Reference.adoc#audiosync[Sincronizzazione dell'audio].
Per un suono a scatti o che balbetta, vedi le Domande frequenti.
[#_frequently_asked_questions]
== Domande frequenti
*Perché si chiama Singe?*
Singe è il nome del drago di Dragon's Lair. Siccome Singe (il programma) è nato
come aggiunta a Daphne (la principessa di Dragon's Lair), si è mantenuto il tema
di Dragon's Lair.
*Che differenza c'è tra Daphne, Singe, Hypseus e Singe 3.xx?*
Daphne è un vero emulatore di giochi laserdisc, che può far girare una manciata
di classici giochi laser. Daphne/Singe (Singe 1.xx) è la versione originale di
Singe, che era un'aggiunta per l'emulatore Daphne -- distribuita all'inizio come
DLL di gioco per Daphne, e poi riunita in un unico eseguibile senza le funzioni
di emulazione di Daphne. Hypseus-Singe è un fork migliorato di Daphne con il
supporto per Singe 1.xx e in parte per Singe 2.xx. Singe 2.xx è un aggiornamento
del Singe originale, del tutto nuovo e costruito da zero, e Singe 3.xx ci
aggiunge sopra il 3D, la fisica e molto altro. In breve, se vuoi la fedeltà, usa
Daphne o Hypseus, se sono in grado di emulare il gioco che ti interessa. Se è un
gioco Singe, usa Singe, o prova Hypseus.
*Perché non dovremmo chiamarlo «emulatore»?*
Gli emulatori usano il software vero o le ROM del gioco originale e fingono di
essere la macchina su cui il gioco doveva girare in origine. Dal punto di vista
del gioco, è tutto come al solito. Singe, invece, richiede che ogni gioco venga
reimplementato (convertito) per girare su Singe. Il risultato finale può essere
molto simile, ma il funzionamento è completamente diverso.
*Posso far girare i giochi per Singe 1.xx e 2.xx su Singe 3.xx?*
Sì, probabilmente. Quasi tutto quello che c'era per Singe 1.xx è stato
convertito e migliorato per le versioni più recenti di Singe, e la maggior parte
dei giochi per Singe 2.xx gira così com'è. I giochi che usano le vecchie
funzioni degli sprite possono avere bisogno di una piccola modifica; vedi
xref:Reference.adoc#migrating[Migrazione da Singe 2.10].
*Mi serve un gioco laserdisc per usare Singe?*
No. I giochi non hanno affatto bisogno di un disco. Possono usare sprite, video,
3D e qualsiasi altra cosa offra Singe. Vedi xref:Reference.adoc#withoutadisc[Giochi
senza disco].
*Perché il gioco che ho appena installato non compare nel menu?*
Chi ha preparato il pacchetto del gioco non ha incluso un file `games.dat` come
si deve.
*Perché il video HD è lento?*
Non dovrebbe esserlo più. Ora Singe usa la scheda video per decodificare il
video quando il tuo sistema lo permette, anche sul Raspberry Pi e su molte
console portatili. Se il video HD è ancora lento, il tuo sistema potrebbe non
avere la decodifica video hardware, e allora il video ad alta definizione
richiede molta CPU. Avviando con `--program` vedi quale decoder sta usando
Singe.
*Perché l'audio balbetta su Windows?*
Gli utenti hanno scoperto che la maggior parte dei problemi di audio e di scatti
di Singe dipende dal driver audio installato -- soprattutto con i dispositivi
basati su Realtek. Prova ad aggiornare i driver audio o a passare al driver
generico Windows HD Audio. Disattiva l'audio surround -- usa lo stereo, non il
5.1 o il 7.1. Se i tuoi driver non ti permettono di usare lo stereo, puoi
risolvere con Virtual Audio Cable:
. Installa VB-CABLE (https://vb-audio.com/Cable/).
. Apri le impostazioni audio di Windows (clic destro sull'icona dell'audio nella
barra delle applicazioni, poi *Suoni*, poi *Riproduzione*).
. Clic destro sul dispositivo *Cable Input* e scegli *Imposta come dispositivo
predefinito*. (Perderai temporaneamente l'uscita audio attuale.)
. Vai alla scheda *Registrazione*.
. Clic destro su *Cable Output*, poi *Proprietà*, poi *Ascolto*, e infine
attiva *Ascolta questo dispositivo*. Nell'elenco a discesa, scegli il
dispositivo con cui ascolti davvero.
. Dovresti avere di nuovo l'audio. Avvia Singe e l'audio funzionerà, senza
ritardi.
*Il 3D funziona su un Raspberry Pi o su una console portatile?*
Su un Raspberry Pi 4 o successivo, sì. Hanno sia un driver Vulkan sia OpenGL ES
3.1, e Singe usa quello che trova. Il Pi 3 ha solo OpenGL ES 2.0, che non sa
esprimere lo skinning o i morph target della scena, quindi fa girare i giochi 2D
(fisica 2D compresa) esattamente come prima e rifiuta la prima chiamata 3D. Il
Pi 4 è il minimo per qualsiasi gioco che usi il capitolo Scene 3D. Lo stesso
vale per le console portatili economiche: un Mali-G31 o un G610 ha l'ES 3.1 che
serve alla scena, che abbia Vulkan oppure no. Vedi <<handhelds,Console portatili
e macchine piccole>>.
*Perché l'audio balbetta sul Raspberry Pi?*
Raspberry Pi OS ora usa Pipewire come backend audio predefinito. Passare a
PulseAudio sembra risolvere il problema:
. Esegui `sudo raspi-config` da una finestra del terminale.
. Seleziona *Advanced Options*.
. Seleziona *Audio Config*.
. Seleziona *PulseAudio*.
. Premi kbd:[Tab], seleziona *Ok* e lascia che si riavvii.
[#_making_games]
== Creare giochi
Questo manuale parla di come far girare Singe: installarlo, installare i giochi,
preparare un cabinato e il menu. La creazione di giochi è trattata in altri due
libri, che sono un download facoltativo dallo stesso posto da cui scarichi Singe
invece di farne parte, perché insieme sono più grandi del motore.
* Il *Riferimento di Singe* tratta tutto quello che un gioco può fare: il
modello di programmazione, la cartella del gioco, l'impacchettamento di un
gioco in un solo file, e ogni funzione che il motore offre, con i suoi
argomenti, i valori restituiti e un esempio.
* *Impara a programmare con Singe* insegna a programmare partendo da zero, in
trentuno lezioni, a chi non ha mai scritto codice. Viene con gli script e il
piccolo kit grafico che usano le lezioni.
Il download contiene i due libri in PDF e in HTML, i file delle lezioni e la
licenza. Tutti e tre i libri sono scritti in inglese, francese, italiano,
tedesco e spagnolo, e il download esiste in ciascuna lingua: scegli quello nella
tua. Le traduzioni di questo manuale sono già nella cartella `Singe`, accanto a
esso. Forge, lo strumento di creazione che fa un gioco a partire da una
descrizione invece che dal codice, è un progetto separato con il proprio
download e il proprio libro.