singe/docs/de/Manual.adoc

1427 lines
94 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

= Singe-Handbuch
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: de
:imagesdir: ..
include::locale.adoc[]
[#_about_singe]
== Über Singe
Singe (SINGE Is Not a Game Emulator, benannt nach dem Drachen aus
Dragon's Lair) ist ein Lua-basiertes Skriptsystem, mit dem sich schnell Prototypen
neuer Laserdisc-Spiele bauen oder ganz neue Spiele erschaffen lassen. Die Sprache ist
leicht zu lernen, sehr mächtig und schnell. Alle Funktionen, die du für dein
eigenes Spiel brauchst, stehen über eine einfache Programmierschnittstelle
(API) zur Verfügung.
Singe bietet dem Spieleentwickler zahlreiche Funktionen. Einige der
interessanteren sind:
* 3D-Szenen mit Modellen, Animation, Beleuchtung und Schatten
* Physik, einschließlich Gelenken, Ragdolls, Soft Bodies und Fahrzeugen
* Menüs, Optionsbildschirme und HUDs, gebaut wie Webseiten
* Hardware-Videodekodierung, sogar auf kleinen Rechnern
* Online-Highscores und ein Katalog von Spielen zum Herunterladen und Aktualisieren
* Spiele, in eine einzige Datei gepackt
* Objektorientierte Programmiersprache
* Animierte Sprites
* Unterstützung für TrueType-Schriftarten
* 32-Bit-Farbraum mit Transparenz
* Mehrkanaliger, überlappender Stereo-Sound und MIDI
* Unterstützung für analoge und digitale Eingabegeräte, einschließlich Lightguns
* Breite Unterstützung für Video- und Audioformate
Singe läuft unter Windows, macOS und Linux, einschließlich des Raspberry Pi und
Handhelds wie dem R36S.
Spielern ermöglicht Singe, viele nicht emulierte und neue Spiele mit einem
beliebigen Frontend oder über das mitgelieferte Menüsystem zu genießen.
Seit der ersten Veröffentlichung von Singe im Jahr 2006 sind mehrere Überarbeitungen
erschienen, offizielle wie inoffizielle. 2020 erschien Singe 2.00.
Es war eine komplette Neuentwicklung von Grund auf, die zahlreiche Funktionen hinzufügte
und dabei mit bestehenden 1.xx-Spielen kompatibel blieb. Singe 3.00 bringt 3D, Physik,
Benutzeroberflächen und vieles mehr und spielt trotzdem weiterhin die Spiele, die
davor kamen. Zu dem Zeitpunkt, als dieses Handbuch geschrieben wurde, ist die neueste Version
{revnumber}.
[#_installation_and_upgrading]
== Installation und Aktualisierung
[#_installing_singe]
=== Singe installieren
Um Singe zu installieren, lade einfach die passende Binärdatei für dein System herunter. Leg
sie allein in einen neuen Ordner und starte sie. Beim ersten Start legt Singe
alle nötigen Verzeichnisse und Hilfsdateien an. Jetzt kannst du
Spiele installieren.
[#_upgrading_singe]
=== Singe aktualisieren
Um Singe auf eine neuere Version zu aktualisieren, leg die neue Binärdatei neben die alte
in den Installationsordner und starte sie einmal mit `--refresh`. Der vorhandene
Hilfsordner wird als `old-Singe-<version>` beiseitegelegt, benannt nach der Version, die
ihn geschrieben hat, und an seiner Stelle wird ein frischer Ordner `Singe/` geschrieben. Nichts wird
gelöscht: Der beiseitegelegte Ordner gehört dir, du kannst ihn behalten oder entfernen, und ein zweites
`--refresh` legt seinen eigenen als `old-Singe-<version>-1` beiseite, statt den
ersten zu überschreiben.
Die alte Binärdatei kann bleiben, wo sie ist. `Menu.sh` (oder `Menu.bat`) startet das neueste
Singe, das es neben sich findet, und eine Beta gilt als älter als das Release mit
derselben Nummer, sodass `Singe-v3.00b2` dem `Singe-v3.00` Platz macht, sobald es
eintrifft. Das Tool Engine Update im Menü erledigt all das für dich; siehe
<<servicetools,Die Service-Tools>>.
WARNING: Starte eine neue Singe-Binärdatei nie mit einem veralteten Satz Hilfsdateien.
Erneuere beim Aktualisieren immer das Verzeichnis `Singe/`.
[#_things_to_know]
=== Wissenswertes
Fass den Ordner `Singe/` nicht an. Die Dateien in diesem Ordner gehören Singe und können
jederzeit aktualisiert oder gelöscht werden.
[#_playing_games]
== Spiele spielen
[#_installing_games]
=== Spiele installieren
Ein Spiel ist entweder eine einzelne `.game`-Datei oder ein Verzeichnis. Kopiere es in denselben
Ordner, in dem die Singe-Binärdatei liegt. Das mitgelieferte Menüsystem erkennt es
automatisch und nimmt es ins Menü auf.
[#_game_directory_layout]
=== Aufbau des Spieleverzeichnisses
Eine Singe-Installation ist ein Spieleverzeichnis, das Folgendes enthält: das Hilfsverzeichnis
`Singe`, das die Engine beim ersten Start anlegt, ein Verzeichnis pro Spiel, alle
gepackten `.game`-Dateien und ein Verzeichnis `data` für alles, was die Spiele und
die Engine schreiben. Die ausführbare Datei liegt meist auch dort, muss aber nicht:
`--gamedir` nennt das Spieleverzeichnis von überall aus, und die `Menu.sh` (oder
`Menu.bat`), die die Engine dort schreibt, startet die ausführbare Datei dann über ihren vollen
Pfad. Andernfalls sucht der Launcher neben sich nach den Dateien, deren
Namen mit `Singe` beginnen, und startet die beste davon, ganz im Sinne der
Launcher, die `BatMaker` schreibt, damit ein Update, das die Version im Namen der
ausführbaren Datei ändert, keinen Launcher hinterlässt, der auf eine Datei zeigt, die es nicht
mehr gibt.
„Die beste“ heißt: zuerst die Architektur dieses Rechners und danach die Version. Die
Plattform im Namen wird mit dem verglichen, was das System meldet, denn ein
neuerer Build für eine andere Architektur kann überhaupt nicht laufen, und ein Spieleverzeichnis
auf einer Freigabe kann von einem Pi genauso gelesen werden wie von einem PC. Der Launcher ermittelt das bei
jedem Start, statt es einmal gesagt zu bekommen, sodass dasselbe Verzeichnis für jeden
Rechner passt, der es öffnet. Auf einem Mac gilt ein Universal-Build als nativ. Unter den
Builds, die dieser Rechner ausführen kann, gewinnt der neueste: `Singe-v3.10` schlägt
`Singe-v3.09`, und eine Beta verliert gegen das Release, auf das sie hinführt, also
verliert `Singe-v3.00b2` gegen `Singe-v3.00`. Ein Build für eine andere Architektur wird
trotzdem gestartet, wenn er der einzige ist, denn eine echte Beschwerde der Engine
ist besser als die Auskunft, es sei nichts gefunden worden, und dasselbe gilt für einen Namen, den der Launcher überhaupt
nicht lesen kann.
----
Singe/ Hilfsdateien, von der Engine entpackt
Framework.singe Wird von jedem Spiel geladen (per dofile)
Menu.singe Das mitgelieferte Spielmenü
Tools.singe Die Service-Tools des Menüs (siehe Die Service-Tools)
MenuDocument.singe Das Menü, als GUI-Dokument gezeichnet
MenuOverlay.singe Das Menü, ins Overlay gezeichnet, für einen Rechner ohne GPU
Backdrop.singe Das Intro des Menüs und das Gitter dahinter, live gezeichnet
menuBackground.mkv Derselbe Hintergrund als Aufnahme, für einen Rechner ohne GPU
menuIntro.flac Sein Ton, der ausblendet, wenn das Menü den Bildschirm übernimmt
Menu.rml Das RmlUi-Dokument des Dokument-Renderers
menu.rcss Sein Stylesheet, aufbauend auf gui.rcss
gui.rcss Das mitgelieferte GUI-Theme
controls.cfg.example Vorlage für Eingabebelegungen
click.wav Für den Audioverzögerungs- und den Soundtest des Menüs
Manual.pdf Dieses Handbuch
Manual-fr.pdf Dieses Handbuch auf Französisch
Manual-it.pdf Dieses Handbuch auf Italienisch
Manual-de.pdf Dieses Handbuch auf Deutsch
Manual-es.pdf Dieses Handbuch auf Spanisch
COPYING Die GNU General Public License, Version 3
LICENSES Hinweise zu Fremdsoftware und Nachweise für Assets
Collection/ Ein Verzeichnis mit Spielen
games.dat Menüeinträge für die Spiele in diesem Verzeichnis
AsteroidPatrol.singe Ein Skript
frame_AsteroidPatrol.txt Seine Frame-Datei (oder ein Video mit demselben Basisnamen)
sprite_*.png, sound_*.wav, font_*.ttf
MyGame.game Ein in eine Datei gepacktes Spiel (siehe Spiele in einer Datei)
data/
machine.cfg Audioverzögerung und Bildgeometrie dieses Rechners
Collection/ Indizes, trace.txt, Screenshots, Spielstände dieser Spiele
----
Wo Singe nach den Dateien eines Skripts sucht und wohin ein Skript schreiben darf, ist
Sache dessen, der das Skript schreibt; die Singe-Referenz behandelt beides unter
„Dein Spiel verpacken“.
[#bundledmenu]
=== Das mitgelieferte Menü
`Menu.sh` (oder `Menu.bat`) startet `Singe/Menu.singe`, das mitgelieferte Menü: ein
RmlUi-Dokument, `Singe/Menu.rml`, gestaltet durch `Singe/menu.rcss`, gezeichnet über einem
live berechneten 3D-Hintergrund (siehe xref:Reference.adoc#gui[GUI]). Das Menü läuft ohne
Disc; ein Rechner ohne GPU spielt stattdessen `Singe/menuBackground.mkv` ab, eine Aufnahme
desselben Hintergrunds, hinter einer einfacheren Seite, die ins Overlay gezeichnet wird. Es liest die `games.dat` jedes
Spieleverzeichnisses und jeder `.game`-Datei neben sich und listet jedes gefundene Spiel, nach
Titel sortiert, am linken Bildschirmrand auf. Neben der Liste stehen die
Automatengrafik, das Marquee und der Attract-Clip des ausgewählten Spiels, darunter Jahr, Genre,
Plattform, Entwickler, Publisher, Portierungs-Credits und Beschreibung, und
am unteren Rand eine Zeile mit Tastenhinweisen.
Hoch und runter bewegen die Auswahl um ein Spiel, links und rechts bewegen sie
um eine Seite; beide springen vom einen Ende der Liste zum anderen. Start
oder ein beliebiger Aktionsknopf startet das ausgewählte Spiel, und die Taste, die
`INPUT_SERVICE` zugeordnet ist (standardmäßig die Taste `9`), öffnet die Service-Tools (siehe
<<servicetools,Die Service-Tools>>). Mit einer Maus wählt ein
Klick auf eine Zeile das Spiel aus, und ein zweiter Klick auf dieselbe Zeile startet
es; das Mausrad scrollt eine Beschreibung, die zu lang für ihr Feld ist. Wenn du
`--quitchord` setzt, beendet das Halten dieser Knöpfe ein Spiel zurück ins Menü und
das Menü zurück zu deinem System (siehe <<handhelds,Handhelds und kleine Rechner>>). Das Menü speichert seine Auswahl
in `menu.dat` in seinem Datenordner, damit es wieder beim selben Spiel steht, wenn
eines beendet oder Singe das nächste Mal gestartet wird. Diese Datei ist ein Lua-Fragment, das das Menü
beim Start liest und beim Beenden neu schreibt: `GAME_SELECTED` ist das Spiel, das es
gerade zeigte, `SHOW_INTRO` ist false, wenn es aus einem Spiel zurückkehrt, damit man das Intro
nicht zweimal aussitzen muss, und `MENU_OVERLAY` wählt einen Renderer (siehe
<<menurenderers,Die zwei Renderer>>).
Nicht jeder Rechner kann jedes Spiel ausführen. Ein 3D-Spiel auf einer Kiste ohne 3D oder ein schweres
Spiel auf einer kleinen würde scheitern oder kriechen, also sagt dir das Menü vorher Bescheid. Wenn du
ein Spiel auswählst, das dieser Rechner nicht ausführen kann, sagt die Zeile unter seinen Details, was es
braucht („Needs 3D, and this machine has none.“), und der Startversuch wiederholt nur
das, statt mittendrin zu scheitern. Ein Spiel, das mehr Rechner will, als dieser
hier ist, bekommt „It may run slowly.“ und startet trotzdem. Nichts wird versteckt. Das Menü
ermittelt, wie schnell dieser Rechner ist, wenn sein Intro zum ersten Mal läuft, indem es
seinen eigenen Hintergrund misst, und behält das Ergebnis in `machine.cfg`; es verlangt nie von dir,
einen Benchmark laufen zu lassen. Spiele geben in ihrer `games.dat` an, was sie brauchen
(xref:Reference.adoc#gamesdat[REQUIRES und TIER]), und das Tool Get Games kennzeichnet
den Katalog auf dieselbe Weise.
[#menurenderers]
==== Die zwei Renderer
Ein GUI-Dokument wird über das GPU-Gerät gezeichnet, das auch die 3D-Szene benutzt, auf einem
Rechner ohne ein solches gibt es also kein Dokument zu bauen. Das Menü regelt das
selbst: `Singe/Menu.singe` fragt beim Start xref:Reference.adoc#singehasgpu[singeHasGpu] und
lädt einen von zwei Renderern.
`Singe/MenuDocument.singe`::
Das oben beschriebene RmlUi-Dokument, für einen Rechner mit GPU-Gerät. Es
zeichnet außerdem das Intro und das Gitter hinter dem Menü als eine durchgehende 3D-Szene, sodass
für keines von beiden die Disc benutzt wird.
`Singe/MenuOverlay.singe`::
Sprites und `fontPrint` direkt ins Overlay, der Look, den Singe 2 hatte. Es
braucht nichts außer dem Overlay, in das jedes Spiel sowieso zeichnet.
Beide zeichnen dasselbe Menü, nehmen dieselben Tasten und starten dieselben Service-Tools;
`Singe/Menu.singe` enthält alles, was nicht Zeichnen ist -- die Spieleliste, die
Auswahl, das Starten eines Spiels -- und so gibt es ein Menü statt zwei. Der
Overlay-Renderer zeigt ein Spiel auf einmal statt einer Liste, da er kein
Feld zum Scrollen hat, und er schneidet eine für ihre Spalte zu lange Beschreibung ab, statt
sie zu scrollen.
Um den Overlay-Renderer auf einem Rechner zu sehen, der eine GPU hat, schreib
`MENU_OVERLAY = true` in `menu.dat` im Datenordner des Menüs; das Menü
schreibt die Zeile wieder heraus, also bleibt sie erhalten. So wird der Overlay-Pfad
getestet, und so bekommt ein Automatenbauer, der den alten Look bevorzugt, ihn.
[#onlineservice]
==== Online: Konten, Spiele und Punkte
Das mitgelieferte Menü kann den Automaten bei einem Master-Dienst anmelden (standardmäßig
`master.singeengine.com`), der drei Dinge tut: Er verwaltet das Konto, er
bietet einen Katalog von Spielen zum Herunterladen und Aktualisieren an, und er führt
Highscore-Bestenlisten.
Zwei Service-Tools decken das ab. **Online Account** meldet an, legt ein Konto an,
stellt ein Passwort wieder her und setzt die Serveradresse -- dort richtet ein Betreiber,
der seinen eigenen Dienst betreibt, den Automaten darauf aus. Ein neues Konto ist erst nutzbar,
wenn der per E-Mail geschickte Link geöffnet wurde. **Get Games** listet alles auf, was der
Dienst anbietet, markiert, was hier installiert ist, und lädt es herunter, aktualisiert oder entfernt
es. Ein Download mit mehreren Spielen (einer Sammlung oder einem Spiel in zwei
Sprachen) stellt jedes davon unter seinem eigenen Namen in die Liste, mit dem Hinweis, in welchem
Download es steckt, und wer eines davon holt oder entfernt, holt oder entfernt
alle, denn sie sind eine Datei. Was angeboten wird, hängt vom Konto ab: Ein Dienst
kann ein Spiel bestimmten Konten vorbehalten, sodass zwei Automaten, die bei verschiedenen
Konten angemeldet sind, verschiedene Listen sehen können. Das Menü selbst sagt, wenn es eine neuere Version eines installierten Spiels gibt: Das
Spiel trägt in der Liste eine Markierung `update`, die Zeile unter seinen Details nennt die
Version, und Knopf 3 auf dieser Seite holt sie, sodass ein Automat kein
Service-Tool öffnen muss, um aktuell zu bleiben. Über diesen Rechner wird nirgends etwas gespeichert: Das
Menü liest die Version aus der eigenen `games.dat` jedes Spiels und fragt nach seiner eigenen
Liste, sodass ein von Hand hineinkopiertes Spiel genauso bekannt ist wie eines, das hier heruntergeladen wurde. Ein
Automat ganz ohne Spiele öffnet trotzdem das Menü, das sagt, wie man welche holt,
und was Get Games herunterlädt oder entfernt, steht in der Liste, sobald die Service-Tools
geschlossen werden. Eine Liste, die länger ist als der Bildschirm, scrollt mit der Auswahl mit, statt unten
herauszulaufen, und `...` zeigt, dass es in der jeweiligen Richtung mehr gibt. Ein Spiel, das nicht mehr angeboten wird, funktioniert weiter und wird als „installed,
no longer offered“ angezeigt: Es bekommt lediglich keine Updates mehr, denn ein Spieler,
der ein Spiel hat, hat es. Ein Download wird mit der Prüfsumme abgeglichen, die der Katalog veröffentlicht hat, bevor er
irgendetwas ersetzt, sodass eine fehlerhaft angekommene Übertragung scheitert, statt
ein Spiel zu installieren, das nicht läuft.
Das Konto gehört dem *Rechner*, nicht einem Spiel: Das Token liegt in
`master.dat` im obersten Datenordner, sodass ein Spiel, das eine Punktzahl meldet, dieselbe Anmeldung benutzt,
die das Menü vorgenommen hat. Das Passwort wird nie gespeichert, und die Datei ist verschleiert, sodass man
Token und Adresse des Kontos nicht auf einen Blick herauslesen kann; eine bearbeitete
Datei gilt als abgemeldet. Der Rechner muss sie unbeaufsichtigt zurücklesen können,
also behandle `master.dat` trotzdem wie einen Schlüssel zum Konto: Auf einen anderen
Rechner kopiert, meldet sie diesen an. Um eine Punktzahl zu melden, braucht man dieses Konto, um eine Bestenliste zu lesen aber nicht:
Ein Automat, der nicht angemeldet ist, zeigt trotzdem die Online-Bestenliste eines Spiels, sofern das
Spiel eine zeigt, für jedes Spiel, das der Dienst allen anbietet. Siehe xref:Reference.adoc#onlinescores[Online-Highscores] für die Seite des Spiels und
`Singe/Net.singe` für den asynchronen HTTP-Client darunter -- nichts hier
blockiert einen Frame, denn Lua ist in Singe kooperativ, und ein großer Download sähe
sonst wie ein Hänger aus.
Singe prüft das Zertifikat des Servers gegen zwei Listen zugleich: die, die es
mitbringt, und die, die dein Rechner führt. Es genügt, wenn eine von beiden für den Server bürgt,
sodass eine alte Singe-Kopie das Update, das sie ersetzt, immer noch erreichen kann,
solange dein System seine eigene Liste aktuell hält. Du betreibst deinen eigenen Dienst
mit einem Zertifikat deiner eigenen Zertifizierungsstelle? Leg das Zertifikat dieser Stelle in
`cacerts.local.pem` im Datenordner. Singe schreibt diese Datei nie, also
übersteht sie Updates. Wird eine Verbindung abgelehnt, sagt die Meldung, welche Listen
geprüft wurden, und ein Zertifikat, das „not yet valid“ ist, bedeutet fast immer, dass die
Uhr des Rechners falsch geht.
[#servicetools]
==== Die Service-Tools
Die Taste, die `INPUT_SERVICE` zugeordnet ist, öffnet eine Liste von Tools über der Spieleliste.
Hoch und runter wählen eines aus, und Knopf 1 öffnet es; Knopf 2 führt aus einem Tool zurück
zur Liste, und die Service-Taste verlässt die Tools, noch einmal gedrückt, ganz. Alles
steckt in `Singe/Tools.singe`, das die Engine neben `Menu.singe` entpackt.
Dort zeichnet nichts: Ein Tool baut eine Liste von Zeilen und übergibt sie dem Menü,
weshalb jedes Tool auf beiden Renderern läuft (siehe
<<menurenderers,Die zwei Renderer>>). Nichts hier braucht ein laufendes Spiel,
und nichts verändert die eigenen Dateien eines Spiels.
Audio Delay::
Die Audioverzögerung der nachgeschalteten Geräte, gemessen an einem Klick und einem Blitz. Siehe
xref:Reference.adoc#menucalibration[Kalibrieren über das Menü] dafür, was das Tool tut und warum es
funktioniert.
Input Test::
Jeder Controller, jede Maus und jede Lightgun, die die Engine sehen kann, live: der letzte Schalter, den das
Spiel erhalten hätte, und wie viele angekommen sind, der Name jedes Pads mit seinen
sechs Achsen und den gedrückten Knöpfen sowie Name und Position jeder Maus. Das
ist der Bildschirm, der „der Knopf tut nichts“ beantwortet -- entweder kommt der Schalter
an und das Spiel ignoriert ihn, oder er kommt gar nicht erst an.
System Information::
Die Version der Engine, das Betriebssystem, Prozessor und Arbeitsspeicher, der
Renderer und das 3D-Gerät, welche Videodecoder im Spiel sind, die eingebauten Audioformate,
der SoundFont, der MIDI-Zustand, die Größen von Fenster, Zeichenfläche und
Overlay sowie der Datenordner. Ein Foto dieser Seite beantwortet den größten Teil
eines Fehlerberichts.
Light Gun::
Ziele in der Mitte und in jeder Ecke des Overlays, über dem, was die
Disc gerade zeigt. Knopf 1 markiert, wohin die Lightgun tatsächlich gezeigt hat, und behält die
letzten zwölf Schüsse; Start löscht sie. Eine Lightgun, die genau auf das Bild justiert ist, setzt
ihre Kreuze auf die Ziele, und eine, die es nicht ist, zeigt, in welche Richtung sie danebenliegt.
Sound Test::
Knopf 1 spielt den Klick über den linken Lautsprecher, dann den rechten, dann beide,
und das ist schon die ganze Prüfung auf vertauschte Kabel. Außerdem listet es die eigenen
Tonspuren der Disc auf, und links und rechts schalten zwischen ihnen um.
Display::
Größe, Position und Drehung des Bildes, live verändert mit den Pfeilen,
den Knöpfen 3 und 4 und Münze 1, über einem Testbild: ein Raster von 16 mal 12, um
das Bild gerade auszurichten, ein Graukeil in acht Stufen, um die Helligkeit einzustellen, und
zwei Rahmen ganz am Rand, ein Pixel voneinander entfernt -- ein Monitor mit Overscan frisst
zuerst den äußeren. Knopf 1 speichert die Werte für diesen Rechner, in derselben
`machine.cfg`, die auch die Audioverzögerung benutzt, sodass sie für jedes Spiel gelten, statt
einmal pro Spiel eingestellt zu werden. Start setzt alles zurück.
Disc Test::
Zwölf Sprünge, über die ganze Disc verteilt, jeder mit Zeitmessung. Ein Rip, dessen Keyframes
weit auseinanderliegen, springt langsam, und das einzige Symptom im Spiel ist, dass sich alles
schwerfällig anfühlt; dieses Tool misst es direkt und meldet den schlechtesten der zwölf.
Ein Sprung, der nach drei Sekunden nicht angekommen ist, wird mit drei Sekunden gezählt.
Saved Data::
Was jedes Spiel gespeichert hat, gefunden durch Durchsuchen des obersten Datenordners statt durch
Auskunft, mit der jeweiligen Größe. Knopf 3 -- nicht Knopf 1, der überall sonst „auswählen“ bedeutet --
verwirft den Spielstand des ausgewählten Spiels. Der übliche Grund ist, eine Highscore-Tabelle
zu leeren, ohne das Spiel zu löschen.
Engine Update::
Ein neueres Singe, wenn der Dienst eines für diesen Rechner hat. Eine Beta trägt die Version
`3.00b2`, die zweite Beta von 3.00, und kommt vor 3.00 selbst, sodass einem Automaten,
auf dem eine Beta läuft, das Release am Tag seiner Veröffentlichung angeboten wird. Zeigt, was läuft
und was angeboten wird, und Knopf 1 holt es, prüft es gegen die Prüfsumme, die der
Dienst veröffentlicht hat, legt es unter dem eigenen Namen des Release neben das laufende Singe,
legt das alte als `old-<name>` beiseite und startet neu in das neue. Das Beiseitelegen
des alten kann verweigert werden, durch einen Ordner, in den dieser Benutzer nicht schreiben kann, oder durch einen
Virenscanner, der die Datei festhält; das Tool sagt das und macht weiter, da der Launcher
so oder so das neueste Singe im Ordner startet. Das neue
Singe startet mit `--refresh`, sodass der Hilfsordner von der
Version neu geschrieben wird, der er jetzt gehört, und der alte als `old-Singe-<version>` erhalten bleibt; eine
Datei, die ein älteres Singe mitbrachte und dieses nicht, kann nicht liegen bleiben und ein
Spiel verwirren. Bis zu diesem Knopfdruck passiert nichts. Knopf 3 fragt den Dienst erneut. Das Menü schaut
von sich aus einmal am Tag nach und sagt das in einer Zeile unter den Details des Spiels;
`no_update_check = true` in `settings.cfg` stoppt die tägliche Prüfung, und das Tool
funktioniert weiterhin von Hand.
Online Account::
Diesen Automaten beim Master-Dienst anmelden, ein Konto anlegen, ein
Passwort wiederherstellen und die Serveradresse setzen. Siehe
<<onlineservice,Online: Konten, Spiele und Punkte>>.
Get Games::
Der Katalog: was der Dienst anbietet, was hier installiert ist, und Herunterladen,
Aktualisieren oder Entfernen.
MIDI Ports::
Die Ein- und Ausgangsports dieses Rechners, welche davon Singe geöffnet hat,
und die letzten paar Nachrichten, die angekommen sind. Knopf 1 sendet eine Note, Knopf 3 sucht
erneut nach Ports, nachdem etwas eingesteckt wurde. Nichts wird geöffnet, bevor
dieses Tool fragt, sodass ein Automat, der MIDI nie anrührt, auch nie dafür bezahlt.
Frame Statistics::
Schaltet das Entwickler-Overlay ein und aus. Es bleibt bis ins Spiel hinein eingeschaltet, in der
oberen linken Ecke. Siehe xref:Reference.adoc#statsenable[statsEnable].
[[controls]]
== Steuerung
Standardmäßig belegt Singe Controller so, als wären sie Xbox-Gamepads. Wenn dein
Controller nicht erkannt wird oder du die Standardbelegungen ändern willst, so wie sie
Singe erscheinen, kannst du das kostenlose SDL2 Gamepad Tool von
http://generalarcade.com/gamepadtool/ benutzen.
[[controlscfg]]
=== controls.cfg
Zusätzlich zur Konfiguration deines Controllers kannst du mit `controls.cfg`-Dateien alle Eingabeoptionen
für Singe als Ganzes oder für jedes einzelne Spiel neu belegen.
Um zu bestimmen, wie Eingaben belegt sind, liest Singe Konfigurationseinstellungen in
der folgenden Reihenfolge, und eine spätere Datei ersetzt eine frühere Eingabe für Eingabe
(siehe <<configorder,Woher Konfigurationsdateien gelesen werden>>):
. Die Standardwerte aus Singe selbst.
. `controls.cfg` aus dem Hauptskriptverzeichnis des Spiels: das, was der Autor des Spiels mitgeliefert hat.
. `controls.cfg` aus dem Verzeichnis, in dem Singe gestartet wurde: die eigene des Rechners (das Verzeichnis `Singe` enthält eine Vorlage `controls.cfg.example`, die du kopieren kannst).
. `controls.cfg` aus dem Verzeichnis über dem Datenordner des Spiels.
. `controls.cfg` aus dem Datenordner des Spiels: deine, für genau dieses eine Spiel.
Du musst nicht jede Option in einer eigenen `controls.cfg`-Datei angeben. Gib
ruhig nur die Einträge an, die du ändern willst.
Nach der Installation von Singe findest du eine Beispieldatei für die Eingabekonfiguration unter
`<InstallDir>/Singe/controls.cfg.example`. Welche Konfigurationsoptionen
in dieser Datei zur Verfügung stehen, erfährst du, wenn du
`<InstallDir>/Singe/Framework.singe` durchliest.
`--keymapfile` nennt eine einzelne Datei, die statt dieser Suche gelesen wird, was
einem Frontend nützt, das keinen Zweifel daran haben will, welche Belegungen ein Spiel bekommen hat.
Jeder `INPUT_`-Eintrag ist eine Liste, und jedes einzelne Element darin betätigt den Schalter. Eine Liste
innerhalb dieser Liste ist eine Tastenkombination: zwei bis vier Tasten oder Knöpfe, zusammen gehalten, die
den Schalter betätigt, wenn die letzte davon heruntergeht, und ihn loslässt, sobald irgendeine davon
wieder hochkommt. Ein Handheld ohne Esc-Taste beendet auf diese Weise mit Select und Start zusammen:
[source,lua]
----
INPUT_QUIT = { SCANCODE.ESCAPE, { GAMEPAD_0.BUTTON_BACK, GAMEPAD_0.BUTTON_START } }
----
Jede Taste und jeder Knopf in einer Kombination behält außerdem die eigene Bedeutung, sodass Select und
Start, auf diese Weise zum Beenden gedrückt, auf dem Weg nach draußen auch eine Münze einwerfen und Start drücken.
Wenn du eine Möglichkeit zum Beenden willst, die immer funktioniert, nimm stattdessen `--quitchord`. Wenn
du einen seiner Knöpfe drückst, wartet Singe eine Viertelsekunde auf die übrigen,
bevor es irgendetwas anderes tut, sodass das Beenden keine Münze einwirft und nicht Start drückt. Ein
Spiel kann seine eigene Beenden-Taste abschalten, aber nicht `--quitchord`.
[[devices]]
=== Jedes Gerät ist ein Gamepad
Singe hat eine einzige Controller-Familie, `GAMEPAD_0` bis `GAMEPAD_3`, und jedes
Gerät, das es öffnet, gehört dazu. SDL nennt ein Gerät nur dann ein Gamepad, wenn es eine
Belegung dafür hat, und eine Arcade-Encoder-Platine, ein Spinner, ein Lenkrad oder ein Flugsteuerknüppel
hat oft keine. Statt eine zweite Geräteart mit eigenen
Namen mitzuschleppen, schreibt Singe für ein solches Gerät selbst eine Belegung und öffnet es dann als
gewöhnliches Gamepad, sodass es `controls.cfg`, `controllerGetAxis`,
`controllerGetButton` und jeden `INPUT_*`-Schalter genau so erreicht wie ein erkanntes Pad.
Die Belegung, die Singe schreibt, ist eine direkte: Die Achsen des Geräts werden der Reihe nach
zum linken Stick, zum rechten Stick und dann zu den beiden Triggern; seine Knöpfe
werden der Reihe nach zu `BUTTON_A`, `BUTTON_B`, `BUTTON_X`, `BUTTON_Y`, `BUTTON_BACK`,
`BUTTON_GUIDE`, `BUTTON_START`, `BUTTON_LEFT_STICK`, `BUTTON_RIGHT_STICK`,
`BUTTON_LEFT_BUMPER` und `BUTTON_RIGHT_BUMPER`; und sein erster Hat-Switch wird zum
Steuerkreuz. Ein Gerät ohne Hat-Switch verwendet stattdessen seine nächsten vier Knöpfe für das Steuerkreuz.
**Ein Gerät mit mehr Bedienelementen, als das Gamepad-Modell benennen kann, verliert die
überzähligen** -- mehr als sechs Achsen, mehr als fünfzehn Knöpfe oder ein zweiter Hat-Switch --
und bei einem Gerät, dessen Knöpfe nicht in dieser Reihenfolge verdrahtet sind, liegen sie an den
falschen Stellen. Das ist der Preis für eine Familie statt zwei, und er lässt sich
leicht korrigieren: `--program` schreibt die Belegung, die es geschrieben hat, in SDLs
eigenem Format in den Trace, sodass du sie in eine `gamecontrollerdb.txt` einfügen, umordnen und
stattdessen verwenden lassen kannst.
`--mapjoysticks=false` schaltet das Schreiben ab; dann wird ein Gerät, das SDL nicht
erkennt, überhaupt nicht geöffnet, genau wie in früheren Versionen.
[[gamecontrollerdb]]
=== gamecontrollerdb.txt
SDL bringt eine große Datenbank mit Controller-Belegungen mit, und die Community pflegt
eine noch größere -- `gamecontrollerdb.txt`, von
https://github.com/mdqinc/SDL_GameControllerDB. Singe sucht diese Datei an
denselben vier Orten, an denen es nach `controls.cfg` sucht, in derselben Reihenfolge (siehe
<<configorder,Woher Konfigurationsdateien gelesen werden>>):
. im Hauptskriptverzeichnis des Spiels;
. im Verzeichnis, in dem Singe gestartet wurde;
. im Verzeichnis über dem Datenordner des Spiels;
. im Datenordner des Spiels.
Jede gefundene Datei wird geladen, in dieser Reihenfolge, sodass die Datei des Rechners eine Datei schlägt,
die ein Spiel mitbringt, eine Datei im Datenordner des Spiels beide schlägt und alle
zusammen SDLs eigene Datenbank schlagen. Nur ein Gerät, das keine davon nennt, bekommt
die Belegung, die Singe dafür schreibt: Sie ist der letzte Ausweg, nie ein Konkurrent
deiner Dateien. `--program` meldet, wie viele Belegungen jede Datei hinzugefügt hat.
Die Dateien schlagen auch `SDL_GAMECONTROLLERCONFIG`, die Umgebungsvariable, aus der SDL
Belegungen übernimmt und die manche Handheld-Systeme für ihr eingebautes Pad setzen.
Die Belegung von ArkOS für den R36S zum Beispiel lässt Select und Start weg, sodass kein
Spiel sie sieht; eine Zeile in `gamecontrollerdb.txt` für dasselbe Pad bringt sie
zurück. SDL liest die Variable einmal, wenn Singe startet, also gilt das für die
Dateien, die das erste Spiel findet. Ein später aus dem Menü gestartetes Spiel liest zwar weiterhin seine
eigenen, aber ein Pad, das die Variable nennt, behält die Belegung der Variablen.
Eine Zeile dieser Datei sieht so aus und ist genau das, was der Trace für ein
Gerät ausgibt, das Singe selbst belegt hat:
----
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]]
=== Totzonen und Trigger
`DEAD_ZONE` in `controls.cfg` gibt an, wie weit sich eine Achse bewegen muss, bevor sie als
gedrückter Schalter zählt, in den Rohwerten, die SDL meldet: `32767` bei vollem Ausschlag, also liegt
der Standardwert `15000` knapp unter der Hälfte. Er gilt für jede Achse
jedes Pads, die beiden analogen Trigger eingeschlossen, und ein Skript liest ihn als
`SINGE_DEAD_ZONE`.
Zwei Einstellungen grenzen das weiter ein.
`DEAD_ZONES` ist eine Liste von Paaren `{ axis, dead zone }` für jeweils eine Achse,
in denselben Rohwerten, für einen schwergängigen Stick oder einen abgenutzten Trigger, der nicht
alles andere bewegen soll:
[source,lua]
----
DEAD_ZONES = {
{ GAMEPAD_0.AXIS_LEFT_X, 8000 },
{ GAMEPAD_1.AXIS_LEFT_TRIGGER, 30000 },
}
----
Die Achse kann als die Achse selbst oder als eine ihrer beiden Richtungen geschrieben werden
(`GAMEPAD_0.AXIS_LEFT_X`, `AXIS_LEFT_X_L` und `AXIS_LEFT_X_R` bezeichnen alle dieselbe
Achse). Alles, was nicht aufgeführt ist, behält `DEAD_ZONE`.
`TRIGGER_THRESHOLD` gibt an, wie weit ein analoger Trigger durchgedrückt werden muss, bevor er
als Knopf zählt, als *Prozent des vollen Wegs*; das ist die Einheit, die Hypseus’
`-trigger-threshold` benutzt und deren Standardwert dort `99.5` ist. Sie gilt für beide
Trigger aller vier Pads. Singes Standardwert ist `0`, was bedeutet, dass die Trigger bei
`DEAD_ZONE` bleiben, sodass sich für niemanden etwas ändert, der nicht danach fragt; ein Skript liest das
Ergebnis in Rohwerten als `SINGE_TRIGGER_THRESHOLD`. Die beiden Einheiten lassen sich
direkt umrechnen: Ein Prozent sind `32767 / 100` Rohwerte, also sind Singes `DEAD_ZONE` von
`15000` gleich `45.8` Prozent, und Hypseus’ `99.5` Prozent sind `32603` Rohwerte.
`--trigger_threshold` setzt dieselbe Zahl von der Befehlszeile aus und gewinnt gegen
`controls.cfg`; `DEAD_ZONES` gewinnt gegen beide, da es am genauesten ist.
[[joymouse]]
=== Die Maus mit einem Stick steuern
Ein Lightgun-Spiel auf einem Automaten mit Stick und ohne Maus ist unspielbar, solange
der Stick den Cursor nicht bewegen kann. `--joymouse` sorgt dafür: Der **linke Stick von
Gamepad-Slot 0** bewegt den Zeiger, den das Spiel sieht, über dasselbe
`onMouseMoved`, das eine echte Maus erreicht, und der Cursor wird innerhalb des Bildes gehalten.
`--js_range` ist die Geschwindigkeit, `1` bis `20` mit `5` als Standard, gemessen in Videopixeln
pro Frame bei vollem Ausschlag, sodass `5` ein 720 Pixel breites Bild in etwa
zwei Sekunden durchquert. Die Achse beachtet ihre eigene Totzone, sodass ein driftender Stick nicht
kriecht.
Es ist standardmäßig aus, und darin unterscheidet sich Singe von Hypseus: Die mitgelieferte
`controls.cfg` bindet diesen Stick bereits an `INPUT_UP`, `INPUT_DOWN`,
`INPUT_LEFT` und `INPUT_RIGHT`, und wenn er ungefragt auch noch den Cursor steuern
würde, wäre jedes bestehende Spiel überrascht. `--joymouse=false` entspricht
Hypseus’ `-nojoymouse`, und ein Skript schaltet es mit `joyMouseEnable` ein und aus
und liest es mit `joyMouseIsEnabled`. Ein Neuladen setzt es auf den Stand zurück, den die Befehlszeile
vorgegeben hat.
[[mousedevices]]
=== Mäuse, Lightguns und wer entscheidet
`mouseSetMode(MOUSE_MANY)` ist die Entscheidung eines Spiels, bis zu vier Mäuse auseinanderzuhalten,
was ein Automat mit zwei Lightguns braucht und was einem Spiel, das den Aufruf nie macht,
nicht gegeben werden kann. `--manymouse` ist die Entscheidung des Benutzers und hat Vorrang: Der Modus ist
von Anfang an eingeschaltet, und `mouseSetMode(MOUSE_SINGLE)` schaltet ihn nicht mehr ab.
`--absolutes_only` behält nur die Geräte, die eine absolute Position melden,
was eine echte Lightgun tut und eine gewöhnliche Maus nicht, sodass ein
Automat mit zwei Lightguns und einer angeschlossenen Schreibtischmaus nicht von der Maus verwirrt wird.
Achte darauf, wie es entscheidet: **ManyMouse, das Backend, mit dem Singe Mäuse
auseinanderhält, bietet keine Möglichkeit, ein Gerät zu fragen, was für eines es ist**, also zählt ein Gerät als
absolut, sobald es eine absolute Position gemeldet hat, und nicht vorher. Eine Lightgun tut
das bei ihrer ersten Bewegung; bis dahin ist sie stumm, und ein rein relatives
Gerät bleibt für immer stumm. Die Option ist daher ein Filter nach beobachtetem
Verhalten statt nach Geräteklasse, und auf einem Rechner, auf dem kein Gerät je
eine absolute Position meldet, bringt sie jede Maus zum Schweigen.
`SWITCH_MOUSE_DISCONNECT` ist ein Schalter wie jeder andere, nur dass keine Taste und kein
Knopf ihn auslöst: Die Engine löst ihn aus, wenn eine Maus oder eine Lightgun
abgesteckt wird, einmal als Drücken und einmal als Loslassen, sodass ein Lightgun-Spiel das auf dem
Bildschirm sagen kann, statt scheinbar abgestürzt zu sein. Es ist der gleichnamige Schalter von
Hypseus. `controls.cfg` lässt ihn unbelegt; belege zusätzlich eine Taste damit, wenn
du sehen willst, was ein Spiel tut, ohne ein Kabel zu ziehen.
[[hotkeys]]
=== Tastenkürzel
`Alt-Enter` schaltet zwischen Vollbild und Fenster um, während das Spiel läuft, wie
in Hypseus. Das Spiel sieht die Taste nie. Ein Fenster, das im
exklusiven Vollbild gestartet ist (`--fullscreen`), kehrt in dem Anzeigemodus dorthin zurück, den es
bekommen hatte; eines, das im Fenster gestartet ist, bekommt ein randloses Fenster, das den Desktop bedeckt.
Nichts anderes muss sich mitändern: Der Renderer präsentiert eine logische Größe in
Videokoordinaten und skaliert sie auf das, was das Fenster gerade ist, das Videorechteck
wird in denselben Koordinaten gebaut, und das Rotationsziel hat die
Größe des Bildes statt des Fensters, sodass Bild, Overlay,
GUIs und Mauszuordnung alle von selbst folgen.
Die anderen Schalter, die ein Benutzer drücken kann -- Beenden, Pause, Screenshot, Aufnahme, die
Konsole und das Umschalten des Mausfangs -- sind gewöhnliche Belegungen in `controls.cfg` und
werden mit den `INPUT_*`-Namen in der Beispieldatei beschrieben.
[[recording]]
=== Video aufnehmen
`F10` startet die Aufnahme des Spiels, Bild und Ton zusammen, und erneut `F10`
stoppt sie. Jede Aufnahme ist eine neue `singeNNN.mp4` im Datenordner des Spiels,
neben den Screenshots, und spielt in allem, was MP4 abspielt. Das Bild ist
das ganze Fenster, so wie du es siehst, Letterbox inklusive, und der Ton ist alles,
was das Spiel abspielt: Musik, Soundeffekte und der eigene Soundtrack des Videos.
Wo der Rechner einen Hardware-Videoencoder hat, benutzt Singe ihn, sodass die Aufnahme
das Spiel sehr wenig kostet: H.264 über VA-API unter Linux, VideoToolbox unter macOS, Media
Foundation unter Windows und V4L2 auf den ARM-Boards, die einen haben. Überall sonst
nimmt es stattdessen MPEG-4 auf, das überall abspielt, aber größere Dateien erzeugt. Die
Zeile `Recording` im Trace sagt, was benutzt wurde. Ein Rechner, der zu langsam ist, um mitzuhalten,
lässt Frames in der Aufnahme aus, statt das Spiel zu verlangsamen, und der Trace
sagt, wie viele, wenn die Aufnahme endet.
Um stattdessen einen ganzen Lauf aufzunehmen, starte Singe mit `--record=FILENAME`. Füge
`--deterministic` hinzu, und Singe nimmt jeden Frame und den exakt dazugehörigen Ton auf,
egal wie lange jeder Frame zur Erstellung braucht, ohne etwas über
die Lautsprecher abzuspielen. So machst du ein perfektes Video einer Demo oder eines Attract-Modus:
Auf einem Desktop läuft es meist schneller als in Echtzeit.
[#_settings_and_options]
== Einstellungen und Optionen
Fast alles, was du auf die Befehlszeile schreiben kannst, kann auch in eine Einstellungsdatei.
Richte es einmal ein, und jedes Spiel benutzt es.
[[settings]]
=== Die Einstellungsdatei
Fast alles auf der Befehlszeile lässt sich auch einmal aufschreiben, in einer Datei
`settings.cfg`, sodass ein Automat kein Launcher-Skript braucht, das für jedes Spiel
dasselbe Dutzend Optionen mitschleppt. Sie ist Lua, wie `controls.cfg`, und Singe
sucht sie an genau denselben vier Orten, in dieser Reihenfolge:
. `settings.cfg` aus dem Hauptskriptverzeichnis des Spiels.
. `settings.cfg` aus dem Verzeichnis, in dem Singe gestartet wurde (das Verzeichnis `Singe` enthält eine Vorlage `settings.cfg.example`, die du kopieren kannst).
. `settings.cfg` aus dem Verzeichnis über dem Datenordner des Spiels.
. `settings.cfg` aus dem Datenordner des Spiels.
Jeder Ort wird einmal gelesen, und eine spätere Datei gewinnt Schlüssel für Schlüssel, sodass eine
rechnerweite Datei die Anzeige und die Lautstärken festlegen kann, während eine Datei im Datenordner
eines Spiels das Fadenkreuz dieses Spiels abschaltet. Du musst nicht jeden Schlüssel
in eine Datei schreiben; schreib die, die du ändern willst.
Jeder Schlüssel ist der lange Name einer Befehlszeilenoption ohne die führenden Striche,
es gibt also kein zweites Vokabular zu lernen:
[source,lua]
----
-- Die eigene settings.cfg des Automaten
screen = 2 -- der zweite Monitor
fullscreen = true
volume_vldp = 80
haptic = 0 -- dieser Automat hat keine Vibration
idleexit = 900 -- den Bildschirm nach fünfzehn stillen Minuten zurückgeben
startsilent = true
----
Eine Option, die auf der Befehlszeile keinen Wert nimmt, nimmt hier `true` oder `false`
(`yes`, `no`, `on`, `off`, `1` und `0` werden auch akzeptiert). Eine davon auf `false` zu setzen
ist dasselbe, wie sie wegzulassen. Eine Option, die einen Wert nimmt, nimmt denselben Wert
wie auf der Befehlszeile, als Zahl oder als String.
Eine Option, `--deterministic`, nimmt einen Wert oder kommt ohne aus, und ihr Schlüssel macht
es genauso: `deterministic = true` benutzt den Standardschritt, `deterministic = 20`
nennt einen, und `deterministic = false` lässt die Option aus.
[[configorder]]
=== Woher Konfigurationsdateien gelesen werden
`controls.cfg`, `settings.cfg` und `gamecontrollerdb.txt` werden alle an
denselben vier Orten gesucht, in derselben Reihenfolge, und eine später gelesene Datei gewinnt gegen eine
früher gelesene:
. *Das Hauptskriptverzeichnis des Spiels,* das bei einem gepackten Spiel in seiner
`.game`-Datei liegt. Das ist es, was der Autor des Spiels mitgeliefert hat, also wird es zuerst gelesen:
Es legt die Standardwerte des Spiels fest und sonst nichts.
. *Das Verzeichnis, in dem Singe gestartet wurde.* Die eigenen Dateien des Rechners, etwa die
Tastenanordnung eines Handhelds, kommen hierhin, und sie gewinnen gegen das, was ein Spiel mitbringt. Eine
Datei ersetzt nur, was sie nennt; um also die Bindung eines Spiels von einem Knopf zu nehmen,
nenne diese Eingabe: `INPUT_TEST_MODE = { SCANCODE.F2 }` in der
`controls.cfg` des Rechners lässt den Testmodus nur auf der Tastatur, egal auf welchen Knopf ein Spiel
ihn gelegt hat.
. *Das Verzeichnis über dem Datenordner des Spiels,* für Dateien, die alle
Spiele teilen, die diesen Datenordner benutzen.
. *Der Datenordner des Spiels.* Deine eigenen Dateien für ein Spiel, die gegen
alles andere gewinnen.
Mit `--datadir=.` ist der Datenordner der Spielordner selbst; dann
wird die Datei dort einmal gelesen, als die des Spiels. `--keymapfile` ersetzt
die ganze Suche nach `controls.cfg` durch eine benannte Datei.
[#_what_wins]
=== Was gewinnt
. Der eingebaute Standardwert.
. Die Einstellungsdatei.
. Der Eintrag des Spiels in `games.dat`, für die Handvoll Einstellungen, die er trägt (siehe xref:Reference.adoc#gamesdat[games.dat]).
. `machine.cfg`, für die Audioverzögerung und die Bildgeometrie, die die Service-Tools
speichern (siehe <<servicetools,Die Service-Tools>>).
. Die Befehlszeile, die immer gewinnt.
Eine Einstellungsdatei ist also eine Sammlung von Standardwerten, nicht etwas, das du eingetippt hast:
Wenn ein Eintrag in `games.dat` einem Spiel eine Auflösung oder einen Sinden-Rahmen gibt, beschreibt dieser Eintrag
das Spiel immer noch besser als eine rechnerweite Datei. Alles, was tatsächlich
auf der Befehlszeile eingetippt wurde, schlägt beides. `machine.cfg` sitzt direkt unter der Befehlszeile,
weil jemand das Bild eingestellt hat, während er auf genau diesen Monitor schaute, und das
ist ein besserer Beleg als jede woanders geschriebene Datei; die Audioverzögerung ist die
Ausnahme von dieser Ordnung schlechthin, denn sie wird zur Verzögerung des Spiels addiert, statt
sie zu ersetzen.
Optionen, die das Spiel nennen (`--framefile`, `--disc`, `--entry`), ein
Verzeichnis nennen (`--gamedir`, `--datadir`) oder wirken müssen, bevor die Datei
gefunden werden konnte (`--help`, `--apiversion`, `--noconsole`, `--pack`, `--patch`,
`--unpack`) oder nur für einen einzigen Lauf gelten (`--record`, `--refresh`), können nicht in
einer Einstellungsdatei gesetzt werden. Ein Schlüssel, der keine Option ist, eine
dieser Optionen oder ein Wert, den die Option nicht annimmt, ist ein Fehler, der die Datei und
den Schlüssel nennt, sodass ein Tippfehler nie still ignoriert wird:
----
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.
----
Mit `--program` oder `--trace` listet der Kopf am Anfang von `trace.txt` jede
angewendete Einstellung auf, sodass nie die Frage bleibt, welche Datei ein
laufendes Spiel bekommen hat.
[[commandlineoptions]]
=== Befehlszeilenoptionen
----
Singe [OPTIONS] gameName
----
Der Spielname ist das einzige Pflichtargument. Er kann ein `.singe`-Skript sein, ein
Verzeichnis, das ein Skript gleichen Namens enthält (`MyGame` findet
`MyGame/MyGame.singe`), oder ein gepacktes Spiel (`MyGame.game` startet den ersten
Eintrag der `games.dat` darin, `--entry=N` einen anderen). Ein auf diese Weise gestartetes Skript oder Verzeichnis
läuft auch mit seinem Eintrag in `games.dat`, wenn einer es nennt (siehe
xref:Reference.adoc#gamesdat[games.dat]), sodass ein Spiel von der Befehlszeile aus genauso spielt wie aus
dem Menü. Für ein Laserdisc-Spiel (`--disc`) ohne
`--framefile` sucht Singe neben dem Skript nach einem Video mit demselben Basisnamen
und einer beliebigen Endung, die FFmpeg demuxen kann, und danach nach einer `.txt`-Frame-Datei.
Die Optionen sind danach gruppiert, was sie tun.
[#_the_game_and_its_files]
==== Das Spiel und seine Dateien
Welches Spiel läuft, wo es und seine Daten liegen und worauf es gespielt wird.
[cols="1,2",options="header"]
|===
| Option | Zweck
| `-C`, `--canvas=WxH` | Weltgröße für ein Spiel ohne Disc, Standard 720x480. Wird ignoriert, wenn es eine Disc gibt.
| `-d`, `--datadir=PATHNAME` | Verzeichnis für alles, was Singe schreibt: Videoindizes, `trace.txt`, Screenshots, Spielstände, die `menu.dat` des Menüs. Darin wird ein Unterverzeichnis angelegt, das nach dem Spielordner benannt ist (bei einem gepackten Spiel eines nach der Datenbank und darin eines nach dem Verzeichnis des Skripts). Standard ist `data` im Spieleverzeichnis. Singe 2.x schrieb stattdessen neben das Spiel; Spieleverzeichnisse können schreibgeschützt sein, also wird dort nichts mehr geschrieben.
| `-D`, `--disc` | Ein Laserdisc-Video abspielen: das von `--framefile` genannte oder das neben dem Skript gefundene. Wird von `--framefile` impliziert. Ohne diese Option wird ein Video neben dem Skript gemeldet und ignoriert.
| `-E`, `--entry=N` | Den N-ten Eintrag der `games.dat` in einer `.game`-Datei starten (Standard 1). Siehe xref:Reference.adoc#singlefile[Spiele in einer Datei].
| `-v`, `--framefile=FILENAME` | Videodatei oder Frame-Datei, die statt der neben dem Skript gefundenen benutzt wird.
| `-G`, `--gamedir=PATHNAME` | Das Verzeichnis mit den Spielen, den gepackten `.game`-Dateien und dem Hilfsordner `Singe`, wenn die ausführbare Datei woanders liegt. Es wird zum Arbeitsverzeichnis, sodass der Spielname, ein relatives `--datadir` und die Namen des Packers alle von dort aus zählen; absolute Pfade funktionieren, wie sie sind. Standard ist das aktuelle Verzeichnis.
| `-c`, `--showcalculated` | Die Frame-Bereiche jedes Segments einer Frame-Datei ausgeben, zur Fehlersuche.
|===
[#_display]
==== Anzeige
Das Fenster und wie das Bild es ausfüllt.
[cols="1,2",options="header"]
|===
| Option | Zweck
| `-a`, `--aspect=N:D` | Das Seitenverhältnis erzwingen, nach dem eine Fenstergröße gewählt wird (`4:3`, `16:9`, `16:10`).
| `-f`, `--fullscreen` | Exklusives Vollbild in der Desktop-Auflösung.
| `-w`, `--fullscreen_window` | Randloses Fenster, das den Desktop bedeckt.
| `--linearscale=BOOLEAN` | Das Overlay glätten, wenn das Fenster es skaliert (`true`), oder den nächstgelegenen Pixel nehmen (`false`, was Pixelgrafik scharf hält). Nimmt `true`, `false`, `yes`, `no`, `on`, `off`, `1` oder `0`. Ein Skript ändert es zur Laufzeit mit `setOverlayLinearScale`. Standard: `true`, so hat es jede Singe-Version gezeichnet; der eigene Standard von Hypseus ist das Gegenteil.
| `-k`, `--nologos` | Die Startbildschirme überspringen.
| `-r`, `--rotate=DEGREES` | Die ganze Darstellung im Uhrzeigersinn um `0`, `90`, `180` oder `270` Grad drehen, für einen Automaten, dessen Bildschirm seitlich eingebaut ist. Video, Overlay, GUIs, 3D-Szene und Partikel drehen sich alle zusammen, eine Vierteldrehung vertauscht die Form des Bildes, sodass ein Hochformatfenster ausgefüllt wird, und Maus- und Lightgun-Positionen werden zurückgedreht, sodass ein Klick immer noch dort landet, wo er gezeichnet wird. Nur die vier rechten Winkel werden akzeptiert. Ein Skript kann es mit `vldpSetRotate` ändern.
| `--screen=N` | Das Fenster auf Bildschirm `N` öffnen, gezählt ab `1`, wie Hypseus sie zählt. Eine Zahl, die größer ist als die Zahl der Bildschirme, listet die vorhandenen Bildschirme auf und beendet. Standard: der primäre Bildschirm.
| `-u`, `--stretch` | Das Video so strecken, dass es das Fenster füllt, statt sein Seitenverhältnis zu behalten.
| `-x`, `--xresolution=VALUE` | Fensterbreite. Die Höhe wird, wenn sie fehlt, aus dem passenden Eintrag der eingebauten Auflösungstabelle genommen. Eine Größe, die größer ist als der Bildschirm (hier verlangt oder von der `games.dat` eines Spiels), wird passend verkleinert, ihre Form bleibt erhalten, und der Trace sagt das. Headless ausgeführt, mit `SDL_VIDEODRIVER=offscreen`, gibt es keinen Bildschirm, an den angepasst werden müsste, und das Fenster behält die verlangte Größe.
| `-y`, `--yresolution=VALUE` | Fensterhöhe.
|===
[#_picture_placement_bezels_and_guns]
==== Bildposition, Bezels und Lightguns
Für einen Automaten: wo das Bild sitzt, die Grafik drumherum und der Rahmen, den eine Sinden-Lightgun verfolgt. Siehe <<cabinet,Einen Automaten einrichten>>.
[cols="1,2",options="header"]
|===
| Option | Zweck
| `-B`, `--bezel=FILENAME` | Automatengrafik um das Bild zeichnen. Die Datei wird im Ordner `bezels` des Spieleverzeichnisses gesucht (ein gepacktes Spiel kann seine eigene mitbringen) und dann im Ordner `bezels` des Datenordners; `--bezeldir` nennt einen anderen Ordner. Jedes Format, das SDL_image liest, geht, und Transparenz bleibt erhalten. Eine Begleitdatei daneben sagt, wo in der Grafik das Bild liegt; ohne eine behält das Bild das ganze Fenster, und `--shiftx`, `--shifty` und `--scalefactor` platzieren es. Eine Grafik, die nicht gefunden wird, beendet das Programm. Siehe <<bezels,Bezels>>.
| `-I`, `--bezeldir=PATHNAME` | Der Ordner mit der Grafik für `--bezel`, anstelle von `bezels`. Relativ zum Spieleverzeichnis oder absolut. Nur dieser Ordner wird durchsucht. Siehe <<bezels,Bezels>>.
| `-F`, `--bezelflip` | Die Bezel-Grafik vor das Bild zeichnen statt dahinter, wie Hypseus es mit seinen eigenen Bezels macht; die Transparenz der Grafik ist dann das Loch, durch das das Spiel zu sehen ist. Ohne diese Option liegt die Grafik hinter allem, und das Bild bedeckt ihren Ausschnitt. Ein Skript wählt mit `setOverlayOnTop`, ob das Overlay und die GUIs über der Grafik bleiben. Siehe <<bezels,Bezels>>.
| `-b`, `--scalefactor=PERCENT` | Das Bild um seine Mitte auf `PERCENT` (`25` bis `100`) des Fensters verkleinern, für Bildschirme, die ihre Ränder durch Overscan verlieren. Maus- und Lightgun-Positionen folgen dem verkleinerten Bild. Ein Skript kann es während des Spiels mit `vldpSetScale` ändern. Lässt sich mit `--shiftx`, `--shifty`, `--rotate` und `--sindengun` kombinieren; siehe <<videorect,Das Videorechteck>>.
| `-X`, `--shiftx=PERCENT` | Das Bild waagerecht innerhalb des Platzes verschieben, den `--scalefactor` übrig gelassen hat, von `-100` (ganz an den linken Rand) bis `100` (ganz an den rechten Rand), `0` zentriert. Wie in Hypseus ist die Verschiebung ein Prozentsatz dieses Platzes und nichts weiter, also gibt es bei `--scalefactor=100` keinen Platz, und die Verschiebung bewirkt nichts: Verkleinere zuerst die Skalierung. Siehe <<videorect,Das Videorechteck>>.
| `-Y`, `--shifty=PERCENT` | Das Bild senkrecht innerhalb des Platzes verschieben, den `--scalefactor` übrig gelassen hat, von `-100` (ganz an den oberen Rand) bis `100` (ganz an den unteren Rand), `0` zentriert. Bei voller Skalierung bewirkt es aus demselben Grund nichts. Siehe <<videorect,Das Videorechteck>>.
| `-S`, `--sindenedge=WHERE` | Wo der Sinden-Rahmen sitzt: `video` zeichnet ihn um das Bild, `window` am Rand des Bildschirms. Ohne die Option entscheidet ein Bezel: Grafik um das Bild legt den Rahmen an den Fensterrand, weil die Kamera der Lightgun den ganzen Bildschirm sieht, und ohne Grafik liegt er um das Bild, wie er es immer getan hat. Am Fensterrand werden die beiden Ringe als Ringe gezeichnet, ganz zuletzt, sodass die Grafik zwischen ihnen und dem Bild sichtbar bleibt. Siehe <<bezels,Bezels>>.
| `-g`, `--sindengun='PARAMS'` | Den Rahmen zeichnen, den eine Sinden-Lightgun verfolgt, und Maus- und Lightgun-Positionen auf das Bild darin abbilden: Der schwarze Ring läuft, wenn einer angegeben ist, am Rand des Videos entlang, der weiße Ring sitzt darin, und das Spiel wird in der Mitte gezeichnet. `PARAMS` ist eine Liste von Zahlen in Anführungszeichen: `WW` (Breite des weißen Rahmens in Videopixeln); `WW WB` (weiße Breite, dann ein schwarzer Rahmen außen herum); `RW GW BW WW` (eine eigene Rahmenfarbe und -breite); `RW GW BW WW WB` (dasselbe plus eine schwarze Breite); oder `RW GW BW WW RB GB BB WB` (eigene Farben und Breiten für beide). Ein Rahmen, der dem Spiel keinen Platz lässt (zweimal die weiße und die schwarze Breite zusammen erreichen die kürzere Seite des Videos), oder eine negative Breite beendet das Programm mit einer Meldung. Die Ringe werden um das gezeichnet, was `--shiftx`, `--shifty` und `--scalefactor` übrig gelassen haben, sodass ein Rahmen ein Rahmen bleibt, wie auch immer das Bild platziert ist; siehe <<videorect,Das Videorechteck>>.
|===
[#_sound]
==== Sound
[cols="1,2",options="header"]
|===
| Option | Zweck
| `--altaudio=SUFFIX` | `<base><SUFFIX>.ogg` neben dem Video der Disc statt des darin enthaltenen Tons abspielen, für eine Veröffentlichung, deren andere Sprachen als separate Dateien geliefert werden: `--altaudio=-es` neben `game.m2v` spielt `game-es.ogg`. Alle Segmente einer Frame-Datei werden zusammen umgeschaltet. Eine Datei, die nicht da ist, lässt den eigenen Ton des Spiels weiterlaufen und gibt eine Warnung aus. Der Schlüssel `AUDIO_SUFFIX` in `games.dat` tut dasselbe für ein Spiel, und ein Skript ändert es zur Laufzeit mit `discAudioSuffix`. Standard: keiner.
| `-o`, `--audio=TRACK` | Standard-Tonspur (ab null gezählt) für Videos mit mehreren, etwa mehrsprachige Veröffentlichungen.
| `-A`, `--audiodelay=MS` | Ton ausgleichen, der `MS` Millisekunden später zu hören ist, als die Engine messen kann (negativ, wenn er zu früh zu hören ist), `-1000` bis `1000`. Siehe xref:Reference.adoc#audiosync[Audio-Synchronisation].
| `-s`, `--nosound` | Allen Ton stummschalten.
| `--soundfont=FILE` | Der SoundFont (`.sf2`), mit dem MIDI-Dateien synthetisiert werden. Singe liefert keinen mit, denn ein guter ist Dutzende Megabyte groß, für ein Format, das fast kein Spiel benutzt. Ohne diese Option sucht es nach `Singe/soundfont.sf2` -- sodass ein gepacktes Spiel seinen eigenen mitbringen kann -- und dann an den Orten, an denen eine Distribution einen installiert. Die Zeile `SoundFont:` im Trace-Kopf sagt, welcher benutzt wurde oder dass keiner gefunden wurde. Siehe xref:Reference.adoc#midi[MIDI]. Standard: die Suche.
| `--startsilent` | Stumm starten und stumm bleiben bis zur ersten Eingabe irgendeiner Art, dann mit den eingestellten Lautstärken spielen. Für einen Attract-Automaten in einem ruhigen Raum. `--nosound` hat Vorrang. Standard: aus.
| `-e`, `--volume_nonvldp=PERCENT` | Lautstärke von Soundeffekten und zusätzlichem Video, `0` bis `100`.
| `-l`, `--volume_vldp=PERCENT` | Laserdisc-Lautstärke, `0` bis `100`.
|===
[#_input]
==== Eingabe
Siehe <<controls,Steuerung>>.
[cols="1,2",options="header"]
|===
| Option | Zweck
| `--absolutes_only` | Nur die Mäuse behalten, die eine absolute Position melden, was eine echte Lightgun tut und eine gewöhnliche Maus nicht. ManyMouse kann nicht gefragt werden, was ein Gerät ist, also zählt ein Gerät als absolut, sobald es eine absolute Position gemeldet hat, und nicht vorher; siehe <<mousedevices,Mäuse, Lightguns und wer entscheidet>>. Hypseus schreibt es `-absolutes-only`; der Name hier benutzt einen Unterstrich, weil ein Schlüssel einer Einstellungsdatei ein Lua-Name sein muss. Standard: aus.
| `--gamepad_reorder=DIGITS` | Welches physische Pad welchen Gamepad-Slot füllt, als Aufzählungspositionen ab `0`, eine für jeden Slot der Reihe nach: `--gamepad_reorder=10` macht das zweite gefundene Pad zu Spieler eins und das erste zu Spieler zwei. Als bloße Ziffern geschrieben (`3210`) oder durch Kommas oder Leerzeichen getrennt, wie Hypseus es schreibt; eine wiederholte Position wird abgelehnt. Nicht genannte Positionen füllen die übrigen Slots in der Reihenfolge, in der SDL sie gefunden hat, und eine Position ohne Pad dahinter lässt ihren Slot leer. Standard: SDLs eigene Reihenfolge.
| `--haptic=STEP` | Die stärkste Vibrationsstufe, die ein Spiel benutzen darf, `0` bis `4`. `0` schaltet Vibration ganz ab, und eine niedrigere Zahl dämpft ein Spiel, das mehr verlangt: `controllerDoRumble` vibriert nie stärker als dies. Standard: `4`, also jede Stufe, die ein Spiel verlangt.
| `--joymouse=BOOLEAN` | Den linken Stick von Gamepad-Slot `0` den Mauszeiger steuern lassen, für ein Lightgun-Spiel auf einem Automaten ohne Maus. `--joymouse=false` entspricht Hypseus’ `-nojoymouse`, und ein Skript setzt es mit `joyMouseEnable()`. Siehe <<joymouse,Die Maus mit einem Stick steuern>>. Standard: `false`, wo der Standard von Hypseus an ist -- die mitgelieferte `controls.cfg` bindet diesen Stick bereits an die vier Richtungen.
| `--js_range=SPEED` | Wie schnell dieser Stick ihn steuert, `1` bis `20`, in Videopixeln pro Frame bei vollem Ausschlag. Standard: `5`, wie in Hypseus.
| `--keymapfile=FILENAME` | Die Steuerungsbelegungen aus dieser Datei lesen, statt an den vier Orten nach `controls.cfg` zu suchen, sodass ein Frontend sicher sein kann, welche Belegungen ein Spiel bekommen hat. Die eingebauten Standardwerte gelten darunter weiterhin, sodass eine unvollständige Datei trotzdem funktioniert, und eine Datei, die nicht da ist, beendet das Programm. Standard: die Suche an vier Orten, beschrieben unter <<controls,Steuerung>>.
| `--manymouse` | Bis zu vier Mäuse auseinanderhalten, egal was das Spiel verlangt, was ein Automat mit zwei Lightguns von einem Spiel braucht, das `mouseSetMode(MOUSE_MANY)` nie selbst aufruft. Die Wahl des Benutzers hat Vorrang vor der des Spiels: `mouseSetMode(MOUSE_SINGLE)` schaltet es nicht mehr ab. Standard: aus, und das Spiel entscheidet.
| `--mapjoysticks=BOOLEAN` | Eine Gamepad-Belegung für ein Gerät schreiben, das SDL nicht erkennt, sodass ein Arcade-Encoder, ein Spinner, ein Lenkrad oder ein Flugsteuerknüppel wie alles andere als `GAMEPAD_0` bis `GAMEPAD_3` geöffnet wird. `false` lässt ein solches Gerät ungeöffnet, wie es frühere Versionen taten. Siehe <<devices,Jedes Gerät ist ein Gamepad>>. Standard: `true`.
| `-n`, `--nocrosshair` | Das Spiel bitten, kein eigenes Fadenkreuz zu zeichnen. Für Skripte als `singeWantsCrosshairs()` verfügbar.
| `--nogamepad` | Alle Gamepads ignorieren, das Gegenstück zu `--nomouse`. Keines wird geöffnet, und kein Pad-Ereignis erreicht das Spiel, sodass ein klemmender Arcade-Encoder nichts drücken kann. Standard: aus.
| `-m`, `--nomouse` | Maus- und Lightgun-Eingabe vollständig abschalten.
| `--quitchord=BUTTONS` | Knöpfe am ersten Gamepad, die zusammen gehalten beenden, egal was das Spiel belegt und selbst wenn es seine Beenden-Taste abgeschaltet hat: der Ausweg auf einem Handheld ohne Tastatur. Ein Spiel beendet zurück ins Menü, aus dem es gestartet wurde, und das Menü beendet Singe. Zwei bis vier von SDLs Gamepad-Knopfnamen, verbunden mit `+`, etwa `back+start` (Select und Start); die Namen sind `a`, `b`, `x`, `y`, `back`, `guide`, `start`, `leftstick`, `rightstick`, `leftshoulder`, `rightshoulder`, `dpup`, `dpdown`, `dpleft` und `dpright`, wie die Belegung des Pads sie vergibt, und `--program` schreibt den Namen jedes gedrückten Knopfs in den Trace. Ein Druck auf einen der Knöpfe der Kombination wartet eine Viertelsekunde auf die übrigen, bevor er tut, was er normalerweise tut, sodass Start auf dem Weg zum Beenden kein Spiel aus dem Menü startet. Gehört in die `settings.cfg` des Rechners. Standard: keiner.
| `--trigger_threshold=PERCENT` | Wie weit ein analoger Trigger durchgedrückt werden muss, bevor er als Knopf zählt, als Prozent des vollen Wegs -- die Einheit von Hypseus, dessen eigener Standard `99.5` ist. `0` lässt die Trigger bei `DEAD_ZONE`, was Singe ihnen immer gegeben hat. Gewinnt gegen `TRIGGER_THRESHOLD` in `controls.cfg`; `DEAD_ZONES` gewinnt gegen beide. `0` bis `100`; siehe <<deadzones,Totzonen und Trigger>>. Standard: `0`.
| `--xratio=FACTOR` | Der waagerechte Skalierungsfaktor, den ein Lightgun-Spiel mit `ratioGetX()` liest, um seine eigenen Lightgun-Koordinaten für einen Bildschirm zu strecken, dessen Form nicht zum Video passt. Singe tut nichts damit; das Spiel rechnet selbst, genau wie in Hypseus. `0` bis `100`, auf zwei Nachkommastellen gehalten, wie Hypseus es hält. Standard: `0`, was jedes Spiel, das es liest, als `1` behandelt.
| `--yratio=FACTOR` | Dasselbe für `ratioGetY()`. Standard: `0`.
|===
[#_video_decoding_and_performance]
==== Videodekodierung und Leistung
Vor allem für kleine Rechner; siehe <<handhelds,Handhelds und kleine Rechner>>.
[cols="1,2",options="header"]
|===
| Option | Zweck
| `--deinterlace=MODE` | Was ein Bild im Zeilensprungverfahren bekommt: `auto` (der Standard) deinterlacet nur die Frames, die die Datei als interlaced markiert, `on` deinterlacet jeden Frame, für eine Datei mit falschen Flags, und `off` rührt das Bild nie an. Eine Laserdisc enthielt Halbbilder im Zeilensprungverfahren, und ein Rip, der sie behalten hat, zeigt auf einem progressiven Bildschirm Kammartefakte; ein Rip, der schon beim Erstellen deinterlacet wurde, braucht hier nichts. Für jedes Bild, das hineingeht, kommt eines heraus, also verschieben sich Frame-Nummern nie. Standard: `auto`.
| `--monochrome` | Mit dem Disc-Bild in Grau starten. Overlay, GUIs und 3D-Szene behalten ihre Farbe; ein Skript macht dasselbe mit `vldpSetMonochrome` und macht es wieder rückgängig. Standard: aus.
| `--scenequality=LEVEL` | Wie viel die 3D-Szene zeichnet: `high`, alles, was ein Spiel verlangt, oder `low` für eine kleine GPU -- einen Handheld oder einen frühen Raspberry Pi -- mit der Szene in halber Auflösung in jeder Richtung und ohne Antialiasing und Bloom, egal was das Spiel verlangt. Das 3D-Bild ist weicher, helle Dinge leuchten nicht, und es läuft viel schneller, wo die GPU die Grenze war; Disc, Overlay und GUIs bleiben unberührt. Gehört in die `settings.cfg` des Rechners statt auf die Befehlszeile eines Spiels, da es den Rechner beschreibt. Standard: `high`.
| `-H`, `--softwarevideo` | Video in Software dekodieren, selbst wenn die Plattform einen Hardware-Decoder bietet (VA-API oder VDPAU unter Linux, den V4L2-Decoder auf dem Pi, D3D11VA unter Windows, VideoToolbox unter macOS). Damit lässt sich der Hardware-Pfad als Ursache bestätigen oder ausschließen, wenn ein Video sich danebenbenimmt; der Programm-Trace sagt, welcher Decoder benutzt wird.
| `--zerocopy=BOOLEAN` | Hardware-dekodierte Video-Frames direkt an die GPU übergeben, statt sie über die CPU zu kopieren: Rockchips MPP-Decoder und VA-API unter Linux, gezeichnet mit OpenGL ES. Das spart auf einem kleinen Rechner den größten Teil der Kosten von Vollbildvideo. Singe fällt von selbst aufs Kopieren zurück, wenn der Treiber einen Frame nicht annimmt oder wenn ein Spiel die Pixel des Bildes liest oder ändert, und der Programm-Trace sagt, was es gerade tut; `false` lässt es von Anfang an kopieren, um diesen Pfad als Ursache zu bestätigen oder auszuschließen. Standard: `true`.
|===
[#_cabinets_and_front_ends]
==== Automaten und Frontends
[cols="1,2",options="header"]
|===
| Option | Zweck
| `--apiversion` | Eine maschinenlesbare Zeile, die diesen Build beschreibt, auf die Standardausgabe schreiben und beenden, für Frontends. Siehe <<apiversion,Die Versionszeile>>. Sonst wird nichts ausgegeben.
| `--fvalue=NUMBER` | Eine Zahl, die der Launcher an das Spiel übergibt, das sie mit `getFValue()` liest. Singe tut nichts damit. `0` bis `100000`, auf drei Nachkommastellen gehalten, wie Hypseus es hält. Standard: `0`.
| `-h`, `--help` | Die Übersicht der Optionen zeigen und beenden.
| `--idleexit=SECONDS` | Nach `SECONDS` ohne jede Eingabe beenden -- keine Taste, kein Knopf, keine Pad-Achse, keine Maus. Für einen Attract-Automaten, der den Bildschirm zurückgeben soll. `0` beendet nie. `0` bis `86400`. Standard: `0`.
| `--no_update_check` | Den Dienst nie fragen, ob es ein neueres Singe gibt. Sonst schaut das Menü einmal am Tag nach und zeigt, was es gefunden hat, unter den Details des Spiels; das Tool Engine Update funktioniert weiterhin von Hand. Standard: aus, die tägliche Prüfung findet also statt.
| `-z`, `--noconsole` | Nichts ausgeben (und unter Windows kein Konsolenfenster öffnen).
| `--refresh` | Den Hilfsordner `Singe` als `old-Singe-<version>` beiseitelegen, benannt nach der Version, die ihn geschrieben hat, und einen frischen schreiben. Zum Aktualisieren: Eine Datei, die eine ältere Version mitbrachte und diese nicht, bleibt im beiseitegelegten Ordner, statt im aktiven zu liegen. Nichts wird gelöscht, und ein zweiter Lauf legt seinen eigenen als `old-Singe-<version>-1` beiseite. Das Tool Engine Update übergibt dies dem Singe, in das es neu startet.
|===
[#_making_and_testing_games]
==== Spiele erstellen und testen
Siehe <<troubleshooting,Wenn etwas schiefgeht>> für die Traces.
[cols="1,2",options="header"]
|===
| Option | Zweck
| `--deterministic[=MS]` | Nur zum Testen: die Echtzeit ignorieren und die ganze Engine auf einer virtuellen Uhr laufen lassen, die jeden Frame um `MS` Millisekunden weiterrückt, sodass dieselbe Frame-Nummer immer denselben Moment bedeutet. Auch die Disc folgt der virtuellen Uhr, ihre Frames dauern so lange, wie sie wert sind, und die Zufallsgeneratoren werden mit derselben Zahl initialisiert, sodass sich ein Lauf pixelgenau wiederholt. Der Wert ist optional und ist zugleich der Schritt und der Startwert, `1` bis `1000`. Standard, wenn ohne Wert angegeben: `15`, die Frame-Zeit, die sich aus der eigenen Rate der Engine ergibt. Die Taktung ist in diesem Modus bedeutungslos, ebenso der Ton, es sei denn, `--record` ist auch angegeben; dann wird er im Gleichschritt mit dem Bild erzeugt; siehe xref:Reference.adoc#deterministic[Deterministischer Testmodus]. Standard: aus.
| `-P`, `--pack=DIRECTORY` | Das Spiel in `DIRECTORY` in die nach den Optionen angegebene Datenbank packen, dann beenden. Siehe xref:Reference.adoc#singlefile[Spiele in einer Datei].
| `-T`, `--patch=GAME.game` | Dateien im gepackten Spiel aus dem Verzeichnis oder der Patch-Datenbank ersetzen, die nach den Optionen angegeben ist, dann beenden.
| `--perfsync` | Mit `--program` warten, bis die GPU jede Stufe eines Frames fertig hat, bevor die nächste gemessen wird, sodass die Perf-Zeilen sagen, zu welcher Stufe die Zeit der GPU gehört, statt alles bei `present` zu lassen. Alles läuft langsamer, solange es an ist, also ist es zum Messen da, nicht zum Spielen; siehe <<perflines,Die Perf-Zeilen lesen>>. Standard: aus.
| `-p`, `--program` | Engine-Aktivität auf der Konsole und in `trace.txt` im Datenordner protokollieren. Die Datei beginnt mit einem Kopf, der den Rechner beschreibt; siehe xref:Reference.adoc#traceheader[Der Trace-Kopf]. Alle fünf Sekunden sagt sie außerdem, wohin die Zeit des Frames gegangen ist; siehe <<perflines,Die Perf-Zeilen lesen>>.
| `--record=FILENAME` | Den ganzen Lauf, Bild und Ton, als MP4 unter `FILENAME` aufnehmen, vom ersten Frame an, bis Singe beendet wird. Mit `--deterministic` wird jeder Frame behalten und der Ton schrittweise zusammen mit dem Bild erzeugt, sodass beide genau zusammenpassen und während des Laufs nichts zu hören ist. Siehe <<recording,Video aufnehmen>>. Standard: aus.
| `-R`, `--reload` | Die losen Skriptdateien des Spiels beobachten und das Spiel von Grund auf neu starten, wenn sich eine ändert; `F5` tut dasselbe auf Abruf. Ein Skript, das sich nicht kompilieren lässt, bleibt beobachtet, sodass das Speichern der Korrektur es neu lädt. Für die Arbeit an einem Spiel; siehe xref:Reference.adoc#reloading[Neu laden während der Arbeit].
| `-t`, `--trace` | Jeden Lua-API-Aufruf mit der Skriptzeile, die ihn gemacht hat, auf der Konsole und in `trace.txt` protokollieren. Die Datei beginnt mit einem Kopf, der den Rechner beschreibt; siehe xref:Reference.adoc#traceheader[Der Trace-Kopf].
| `-U`, `--unpack=GAME.game` | Die Dateien des gepackten Spiels in das nach den Optionen angegebene Verzeichnis schreiben, dann beenden. Eine Datenbank, deren gespeicherte Namen außerhalb dieses Verzeichnisses landen würden, wird abgelehnt.
|===
Optionen können als `-x 640`, `-x640` oder `--xresolution=640` angegeben werden. Numerische
Werte werden geprüft; ein falscher Wert gibt den Hilfetext aus und beendet. Neuere Optionen
haben keinen kurzen Buchstaben; das Alphabet ist ausgegangen, und ein zufällig gewählter Buchstabe würde
niemandem helfen.
Alles hier außer den Optionen, die das Spiel nennen, ein Verzeichnis nennen oder
wirken müssen, bevor eine Datei gefunden werden kann, lässt sich auch in einer Einstellungsdatei setzen, sodass ein Automat
kein Launcher-Skript für jedes Spiel braucht. Siehe <<settings,Die Einstellungsdatei>>.
[[apiversion]]
=== Die Versionszeile
`--apiversion` gibt eine Zeile aus und beendet mit dem Status `0`:
----
singe version=3.00 protocol=1
----
Das ist ein Vertrag für Frontends, und seine Form wird sich nicht ändern:
* Die Zeile endet mit einem Zeilenumbruch und ist das Einzige, was auf die Standardausgabe
geschrieben wird. Sonst wird nichts ausgegeben, egal was sonst auf der Befehlszeile steht.
* Das erste Feld ist immer `singe`.
* Jedes Feld danach ist `key=value`, getrennt durch ein Leerzeichen, ohne Leerzeichen
innerhalb eines Feldes.
* `version` ist das Release, dieselbe Nummer, die das Banner zeigt.
* `protocol` ist die Version des Formats dieser Zeile. Sie wird nur dann `2`, wenn sich die
obigen Regeln jemals ändern müssen.
* Spätere Versionen können Felder hinzufügen. Ein Leser muss Schlüssel ignorieren, die er nicht kennt,
statt sie als Fehler zu behandeln.
[[cabinet]]
== Einen Automaten einrichten
Arcade-Automaten brauchen ein paar Dinge, die ein Desktop nicht braucht: das Bild von Rändern
wegrücken, die der Monitor verdeckt, es für einen seitlich eingebauten Bildschirm drehen, Grafik drumherum,
einen Rahmen für eine Sinden-Lightgun und eine Punktetafel. Du brauchst dieses
Kapitel nur, wenn du einen Automaten baust. Stell diese Dinge einmal in der
`settings.cfg` des Automaten ein, oder benutze das Tool Display im Menü (siehe
<<servicetools,Die Service-Tools>>), um das Bild einzustellen, während du es ansiehst.
[[videorect]]
=== Das Videorechteck
Alles, was ein Spiel zeigt -- die Disc, das Overlay, die GUIs, die 3D-Szene und
die Partikel -- wird in ein einziges Rechteck gezeichnet, und eine Handvoll Optionen entscheidet,
wo dieses Rechteck liegt. Sie wirken in dieser Reihenfolge:
. *Das Fenster oder der Ausschnitt des Bezels.* Das Rechteck beginnt als das ganze
Fenster. Singe arbeitet in den eigenen Koordinaten des Videos und lässt das Fenster
sie mit Letterbox darstellen (`--stretch` füllt stattdessen), sodass hier nichts von der
Größe des Fensters abhängt. Wenn `--bezel` eine Grafik geladen hat, die einen Ausschnitt angibt, beginnt das
Rechteck stattdessen als dieses Loch, und alles Folgende platziert das Bild
darin; siehe <<bezels,Bezels>>.
. *`--scalefactor`.* Das Rechteck schrumpft um seine eigene Mitte auf diesen Prozentsatz
seiner Ausgangsgröße.
. *`--shiftx` und `--shifty`.* Das Rechteck bewegt sich dann innerhalb des Platzes, den die
Skalierung übrig gelassen hat, `-100` ganz an der einen Seite und `100` ganz an der anderen,
und genau das bedeuten Hypseus’ eigene `-shiftx` und `-shifty`. Daraus folgen zwei Dinge,
die man wissen sollte: Das Bild kann nie aus
dem Bildschirm geschoben werden, und *bei `--scalefactor=100` gibt es keinen Platz, und eine Verschiebung bewirkt
überhaupt nichts*. Um das Bild auf einem schief eingebauten Bildschirm zu verschieben, verkleinere zuerst die
Skalierung: `--scalefactor=90 --shiftx=-100` setzt das verkleinerte Bild ganz
an den linken Rand.
. *`--sindengun`.* Der Rahmen wird zuletzt angewendet, auf das, was Verschiebung und
Skalierung übrig gelassen haben. Der schwarze Ring nimmt den Rand des Rechtecks ein, der weiße Ring sitzt
darin, und das Spiel kommt in beide hinein, sodass ein Rahmen ein Rahmen bleibt,
wie auch immer das Bild platziert wurde. Eine Skalierung, die so klein ist, dass sie dem
Spiel keinen Platz lässt, quetscht die beiden Ringe, statt es zu verschlucken. Mit geladener Bezel-Grafik
geht der Rahmen stattdessen an den Rand des Fensters und lässt das Bild in der
Größe, die es schon hatte; `--sindenedge` entscheidet es so oder so.
`--rotate` ist nicht Teil dieser Reihenfolge. Der Frame wird ungedreht gezeichnet, und das
fertige Bild wird als Ganzes im Uhrzeigersinn gedreht, sodass eine Verschiebung das Bild
entlang der eigenen Achsen des Videos bewegt und sich mit ihm dreht. Eine Vierteldrehung vertauscht außerdem die
Form der dargestellten Fläche, sodass ein Hochformatfenster ausgefüllt wird, statt
mit Letterbox in einen Streifen gezwängt zu werden.
Maus- und Lightgun-Positionen gehen denselben Weg rückwärts: Zuerst wird die Drehung
herausgerechnet, und dann wird die Position in das Rechteck abgebildet, sodass ein Klick
bei jeder Kombination dieser Optionen dort landet, wo der Spieler ihn sieht.
`vldpGetScale`, `vldpSetScale`, `vldpGetRotate` und `vldpSetRotate` lassen ein
Skript Skalierung und Drehung ändern, während das Spiel läuft; die Verschiebung ist eine
Anzeigeeinstellung und hat keinen Skriptaufruf. Keine davon ist ein Schlüssel in `games.dat`:
Wie `--scalefactor` beschreiben sie den Bildschirm des Spielers, nicht das Spiel.
[[bezels]]
=== Bezels
Ein Bezel (ein Bildschirmrahmen) ist die Grafik um den Bildschirm eines Arcade-Automaten. Singe zeichnet eines aus
einer einzigen Bilddatei, mit dem Bild des Spiels in einem herausgeschnittenen Loch, und kann
im verbleibenden Platz eine Arcade-Punktetafel zeigen. Drei Optionen steuern es, und
sie folgen der Konvention von Hypseus, sodass die Befehlszeile eines Automaten
unverändert übernommen werden kann.
`--bezel cabinet.png` nennt die Grafik. Sie wird in dieser Reihenfolge gesucht:
. `bezels/cabinet.png` im Spieleverzeichnis -- in einem gepackten `.game` dessen eigene
Kopie, sodass ein Spiel sein Bezel mitbringen kann;
. `bezels/cabinet.png` im Datenordner, wo die eigene Grafik eines Benutzers
liegen kann, ohne ein schreibgeschütztes Spieleverzeichnis anzufassen.
`--bezeldir art/cabinets` ersetzt den Ordner `bezels` durch den genannten,
relativ zum Spieleverzeichnis oder absolut, und dann wird nur dieser Ordner
durchsucht. Jedes Format, das SDL_image liest, geht (`.png` ist die vernünftige Wahl,
weil Transparenz wichtig ist). Eine Grafik, die die Option nennt und die Singe nicht finden kann,
beendet das Programm, statt ohne sie zu laufen.
Die Grafik wird über das ganze Fenster gezeichnet, egal welche Form beide haben, sodass
sie sich mit dem Fenster genauso streckt wie das Bild. Gib ihr das Seitenverhältnis,
mit dem du zu spielen erwartest.
[#_the_cutout]
==== Der Ausschnitt
Neben der Bilddatei, und nach ihr benannt, sagt eine Begleitdatei, wo das Bild
hinkommt: `bezels/cabinet.png` wird durch `bezels/cabinet.cfg` beschrieben. Sie ist eine Lua-Datei,
wie `controls.cfg`, und setzt eine Tabelle in den *eigenen Pixeln* der Grafik:
[source,lua]
----
-- Das Loch in cabinet.png, in das das Bild gezeichnet wird, in den eigenen Pixeln der Grafik.
CUTOUT = { x = 200, y = 120, width = 800, height = 500 }
----
Alle vier Felder sind Pflicht, und das Rechteck muss innerhalb der Grafik liegen; eine
Begleitdatei, die nicht läuft oder ein Rechteck außerhalb der Bilddatei nennt, beendet das
Programm mit einer Meldung. Weil die Zahlen die eigenen der Grafik sind, bleiben sie
bei jeder Fenstergröße richtig: Bilddatei und Loch werden zusammen skaliert.
Mit einem Ausschnitt wird das Bild in dieses Loch gezeichnet -- auf das Loch gestreckt, sodass das Loch
die Form des Bildes bestimmt -- und `--scalefactor`, `--shiftx` und
`--shifty` wirken dann *innerhalb* davon, verkleinern das Bild und schieben es im Loch zurecht.
Ohne Begleitdatei behält das Bild das ganze Fenster, genau wie ohne
Bezel, und diese drei Optionen platzieren es wie immer. Siehe
<<videorect,Das Videorechteck>>.
Das Loch selbst sollte in der Bilddatei transparent sein. Singe zeichnet die Grafik
standardmäßig hinter das Bild, eine undurchsichtige Mitte würde also einfach verdeckt, aber
`--bezelflip` setzt die Grafik nach vorn, und dann lässt nur ihre Transparenz das
Spiel durch.
[#_draw_order]
==== Zeichenreihenfolge
Ohne `--bezelflip` ist die Grafik das Erste im Frame: Bild,
Overlay, GUIs, 3D-Szene und Partikel zeichnen alle darüber. Mit
`--bezelflip` zeichnet sich die Grafik stattdessen vor das Bild, und das ist die
Reihenfolge, die Hypseus für seine eigenen Bezels benutzt, sodass ein Rahmen mit weichen oder geformten Kanten
das Bild richtig überlappt.
Ein Skript entscheidet, was in diesem Fall mit dem Overlay passiert:
xref:Reference.adoc#setoverlayontop[`setOverlayOnTop(true)`] zeichnet Overlay und GUIs über
die Grafik, und `false` (der Standard, auch der von Hypseus) lässt die Grafik über
ihnen. Mit der Grafik hinter dem Bild ändert die Einstellung nichts,
weil sowieso alles darüber liegt.
xref:Reference.adoc#mainbezelloaded[`mainBezelLoaded()`] sagt einem Skript, ob eine Grafik geladen ist,
und gibt ihm die Kennung der Grafik, dieselbe Zahl, die Hypseus meldet, sodass ein
Spiel, das für ein bestimmtes Bezel geschrieben wurde, es erkennen kann.
GUIs im Bildschirmraum und die Punkteanzeige zeichnen immer über der Grafik, denn
genau darauf sollen sie sitzen.
[#_the_sinden_border]
==== Der Sinden-Rahmen
Eine Sinden-Lightgun beobachtet den Bildschirm auf einen hellen Rahmen. Mit geladener Bezel-Grafik
gehört dieser Rahmen an den *Rand des Fensters*, nicht um das Bild,
weil die Kamera der Lightgun den ganzen Bildschirm sieht, also setzt `--sindengun`
ihn genau dorthin, sobald ein Bezel geladen ist. Dort wird er als zwei Ringe gezeichnet, nach
allem anderen, sodass die Grafik zwischen Rahmen und Bild sichtbar bleibt
und nichts den weißen Ring übermalt. Ohne Bezel liegt der Rahmen um das
Bild, wie er es immer getan hat, und verkleinert es.
`--sindenedge video` oder `--sindenedge window` übersteuert diese Wahl in beide
Richtungen: Ein Lightgun-Automat, dessen Grafik nur eine dünne Einfassung ist, will den
Rahmen vielleicht trotzdem um das Bild, und ein Automat ganz ohne Grafik will ihn vielleicht am
Rand des Bildschirms.
[#_the_score_panel]
==== Die Punkteanzeige
Sechzehn der Hypseus-Singe-Spiele können eine Arcade-Punktetafel ansteuern: Credits sowie
eine Punktzahl und eine Lebensanzeige für jeden von zwei Spielern. In Singe ist diese Punktetafel
das RmlUi-Dokument `Singe/scoreBezel.rml`, gestaltet durch `Singe/scoreBezel.rcss`,
beide neben die anderen Hilfsdateien geschrieben. Wie alles im Ordner `Singe` werden sie
bei jedem Start neu geschrieben, Änderungen daran halten also nicht lange: Ein Spiel, das
ein anderes Aussehen will, liefert eigene Kopien aus, `scoreBezel.rml` neben seinem Skript,
das auf ein eigenes Stylesheet verweist, und Singe verwendet dann diese. Der mitgelieferte
Stil ist eine Siebensegment-Optik: Jede Anzeige zeigt ihre Ziffern schwach beleuchtet hinter
dem aktuellen Wert, so wie es eine echte Anzeige tut.
Die Anzeige ist *aus*, bis ein Spiel sie mit
xref:Reference.adoc#scorebezelenable[`scoreBezelEnable(true)`] anfordert, und so liefert es auch Hypseus
aus, sodass ein Spiel, das nie danach fragt, sich genau wie vorher verhält und seine eigene
Punktetafel mit Sprites zeichnet. xref:Reference.adoc#scorebezelgetstate[`scoreBezelGetState()`] ist die
Frage, die jedes solche Spiel zuerst stellt.
Wo sie hinkommt, wird für dich entschieden: Die Anzeige nimmt das tiefere der Bänder, die das
Bild über und unter sich lässt -- den Platz, den der Ausschnitt eines Bezels meist lässt --
zentriert auf das Bild, und liegt am unteren Rand des Bildes, wenn keines der
Bänder tief genug ist, um sie aufzunehmen. Sie wird als GUI im Bildschirmraum gezeichnet, sodass ein Spiel
mit xref:Reference.adoc#guidrawscreen[`guiDrawScreen`] seine eigenen GUIs auf die Grafik daneben
setzen kann.
`scoreBezelEnable` von Hypseus nimmt ein zweites Argument, das unter seinen fünf
Punktetafel-Backends wählt. Singe hat eines, also wird das Argument angenommen und ignoriert.
[[handhelds]]
== Handhelds und kleine Rechner
Singe läuft auf dem Raspberry Pi und auf günstigen ARM-Handhelds wie dem R36S.
Dort funktionieren dieselben Spiele wie auf einem Desktop, aber ein kleiner Rechner braucht ein wenig
Hilfe, damit sie gut laufen.
[#_what_a_small_machine_needs]
=== Was ein kleiner Rechner braucht
Sprites, Text, Sound und Video funktionieren überall. Die 3D-Szene und der schicke Look des Menüs
brauchen einen Grafikchip mit Vulkan oder OpenGL ES 3.1.
* Ein Raspberry Pi 4 oder neuer hat beides, also funktioniert alles. Ein Pi 3 hat nur
OpenGL ES 2.0, und das reicht nicht für 3D. 2D-Spiele laufen trotzdem.
* Die meisten Handhelds, der R36S eingeschlossen, haben einen Mali-Grafikchip mit OpenGL ES
3.1, also funktioniert 3D dort auch.
* Auf einem Rechner, der keins von beiden hat, benutzt das Menü einen einfacheren Look, der
sie nicht braucht.
Wenn du zum ersten Mal ein 3D-Spiel startest, baut Singe seine Shader, was auf einem kleinen Rechner
ein paar Sekunden dauern kann. Sie werden im Ordner `Singe` im
Datenordner gespeichert, also passiert das nur einmal.
[#_settings_for_a_small_machine]
=== Einstellungen für einen kleinen Rechner
Schreib diese in die `settings.cfg` neben der Singe-Binärdatei, damit jedes Spiel sie
benutzt:
`scenequality = "low"`::
Zeichnet die 3D-Szene in halber Größe, ohne Antialiasing oder Bloom. 3D sieht etwas
weicher aus, läuft aber viel schneller. Video, Sprites und Menüs sind nicht
betroffen.
`zerocopy = true`::
Das ist schon der Standard. Video geht vom Hardware-Decoder direkt zum
Grafikchip, ohne dass die CPU es kopiert. Dadurch kann ein Handheld
Laserdisc-Video mit voller Geschwindigkeit abspielen. Schalte es nur ab, wenn ein Video sich danebenbenimmt und du
es als Ursache ausschließen willst.
`quitchord = "back+start"`::
Handhelds haben keine Esc-Taste. Select und Start zusammen halten beendet das Spiel
zurück ins Menü und das Menü zurück zu deinem System, egal wie das
Spiel eingerichtet ist.
[#_the_r36s_and_arkos]
=== Der R36S und ArkOS
Der R36S und ähnliche Handhelds mit ArkOS benutzen den Linux-Build `aarch64` von
Singe. Leg die Singe-Binärdatei, ihren Ordner `Singe`, `Menu.sh` und deine Spiele in
einen Ordner, etwa `/roms/singe`. Starte `Menu.sh` einmal, damit Singe seine
Hilfsdateien anlegen kann.
Um Singe aus dem Menü Ports zu starten, leg ein Skript wie das folgende in
`/roms/ports`. Diese Handhelds takten ihren Prozessor und Grafikchip nur zögerlich hoch,
also setzt das Skript sie auf volle Geschwindigkeit, solange Singe läuft, und stellt
sie zurück, wenn es beendet wird.
[source,bash]
----
#!/bin/bash
# /roms/ports/Singe.sh: Singe im Menü 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 teilt Spielen die Knöpfe Select und Start nicht mit, also funktioniert die Beenden-Kombination
erst, wenn du diese `gamecontrollerdb.txt` neben die Singe-Binärdatei legst
(siehe <<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,
----
Wenn ein Knopf nicht tut, was du erwartest, starte Singe einmal mit `--program` und
drück ihn. Der Trace zeigt den Namen jedes Knopfs, den du drückst, oder seine Nummer, wenn
die Belegung oben ihn nicht enthält.
Leg zum Schluss eine `controls.cfg` neben die Singe-Binärdatei. Diese hier legt Münze und
Start auf Select und Start und hält die Test- und Service-Menüs eines Spiels von den
Aktionsknöpfen fern, auf die manche Spiele sie legen.
[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 }
----
Diese Datei gewinnt gegen die, die ein Spiel mitbringt (siehe
<<configorder,Woher Konfigurationsdateien gelesen werden>>). Pause und Screenshot
werden auf die Tastatur verlegt, weil Singe sie normalerweise auf Start und
Select legt.
[[troubleshooting]]
== Wenn etwas schiefgeht
[#_the_trace]
=== Der Trace
Starte Singe mit `--program` (oder `-p`), um zu sehen, was es tut. Alles wird
auf der Konsole ausgegeben und in `trace.txt` im Datenordner des Spiels gespeichert.
Wenn du ein Problem meldest, leg `trace.txt` aus einem Lauf mit `--program` bei.
`--trace` (oder `-t`) protokolliert außerdem jeden Lua-Aufruf, den ein Spiel macht, was vor allem
beim Schreiben eines Spiels nützlich ist.
Wenn Singe unter Linux oder macOS abstürzt, schreibt es auf die Konsole
und in `trace.txt`, wo es abgestürzt ist.
`trace.txt` enthält nur die eigenen Meldungen von Singe. Meldungen des Soundsystems, des
Videodecoders und des Grafiktreibers gehen nur auf die Konsole. Wenn diese
das Problem sein könnten, speichere die Konsole mit. Unter Linux:
----
./Menu.sh --program &> singe.log
----
[[perflines]]
=== Die Perf-Zeilen lesen
Mit `--program` sagt der Trace alle fünf Sekunden, wohin die Zeit gegangen ist, als
Durchschnitt pro Runde durch die Frame-Schleife:
----
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` -- das Laserdisc-Video weiterschalten und seinen Frame auf die GPU bringen.
* `script` -- das `onOverlayUpdate` des Spiels, das die Zeile `Perf script` aufteilt
in das Lua selbst und die Engine-Aufrufe, die es gemacht hat, die teuersten Aufrufe zuerst.
* `scene` -- die 3D-Szene zeichnen.
* `gui` -- die GUI-Dokumente anordnen und zeichnen.
* `overlay` -- das, was sich am Overlay geändert hat, an die GPU schicken.
* `compose` -- nur mit `--perfsync`: die GPU zeichnet Bild,
Overlay und GUIs zusammen.
* `present` -- den Frame anzeigen, was das Warten auf die nächste
Bildwiederholung des Bildschirms einschließt.
* `other` -- alles andere: Eingabe, Sound, Physik und der Rest.
Die eigene Zeile eines Videos sagt, wie schnell es dekodiert und wie viel von jedem Frame dafür draufging,
ihn vom Hardware-Decoder zurückzukopieren und seine Farben umzuwandeln; null für
beides bedeutet, dass seine Frames zur GPU gehen, ohne kopiert zu werden.
Die GPU arbeitet der CPU hinterher, also landet ihre Zeit ohne `--perfsync` dort,
wo die CPU als Nächstes auf sie warten muss, und das ist meist `present`. Ein großes `present`
bei voller Rate des Bildschirms ist nur das Warten auf die Bildwiederholung; ein großes `present`
darunter bedeutet, dass die GPU beschäftigt ist. `--perfsync` lässt jede Stufe auf die GPU warten,
bevor die nächste beginnt, sodass `scene`, `gui`, `overlay` und `compose`
ihre GPU-Zeit enthalten und `present` nur das Warten auf die Bildwiederholung bleibt. Die
Bildrate sinkt, solange es an ist, weil CPU und GPU nicht mehr
gleichzeitig arbeiten; vergleiche die Stufen miteinander, nicht mit der Bildrate.
[#_a_button_does_nothing]
=== Ein Knopf tut nichts
Öffne das Tool Input Test im Menü (siehe <<servicetools,Die Service-Tools>>)
und drück den Knopf. Wenn das Tool ihn sieht, ignoriert ihn das Spiel, also prüfe die
`controls.cfg` des Spiels. Wenn das Tool ihn nicht sieht, prüfe deine eigene
`controls.cfg` oder die Belegung deines Controllers in `gamecontrollerdb.txt`.
Ein Lauf mit `--program` zeigt jeden Knopf, während du ihn drückst.
[#_sound_and_picture_are_out_of_sync]
=== Ton und Bild sind nicht synchron
Manche Fernseher, Receiver und kabellose Lautsprecher verzögern den Ton. Miss die Verzögerung
mit dem Tool Audio Delay im Menü. Singe merkt sie sich für jedes
Spiel. Siehe xref:Reference.adoc#audiosync[Audio-Synchronisation] für Details.
Bei abgehacktem oder stotterndem Ton siehe die häufig gestellten Fragen.
[#_frequently_asked_questions]
== Häufig gestellte Fragen
*Warum heißt es Singe?*
Singe ist der Name des Drachen in Dragon's Lair. Da Singe (das Programm) als
Erweiterung für Daphne (die Prinzessin in Dragon's Lair) begann, wurde das Dragon's-Lair-Thema
beibehalten.
*Was ist der Unterschied zwischen Daphne, Singe, Hypseus und Singe 3.xx?*
Daphne ist ein echter Laserdisc-Spiel-Emulator, der eine Handvoll klassischer
Laserspiele ausführen kann. Daphne/Singe (Singe 1.xx) ist die ursprüngliche Version von Singe, die
eine Erweiterung für den Emulator Daphne war -- zuerst als Spiel-DLL für
Daphne ausgeliefert, später dann zu einer einzigen Binärdatei zusammengeführt, aus der die Emulationsfunktionen von Daphne
entfernt waren. Hypseus-Singe ist ein erweiterter Fork von Daphne mit Unterstützung für Singe 1.xx
und teilweise für Singe 2.xx. Singe 2.xx ist ein komplett neues, von Grund auf gebautes
Upgrade des ursprünglichen Singe, und Singe 3.xx baut darauf auf, mit 3D, Physik
und vielem mehr. Kurz gesagt: Wenn du Genauigkeit willst, nimm Daphne oder Hypseus, sofern sie
die Emulation des gewünschten Spiels unterstützen. Wenn es ein Singe-Spiel ist, nimm Singe, oder probier
Hypseus.
*Warum sollten wir es nicht einen „Emulator“ nennen?*
Emulatoren benutzen die echte Software oder die ROMs des Originalspiels und geben vor,
die Maschine zu sein, auf der es ursprünglich laufen sollte. Aus Sicht des Spiels
läuft alles wie gewohnt. Singe dagegen verlangt, dass
jedes Spiel neu implementiert (portiert) wird, um auf Singe zu laufen. Das Endergebnis mag
sehr ähnlich sein, aber wie es funktioniert, ist völlig anders.
*Kann ich Spiele für Singe 1.xx und 2.xx unter Singe 3.xx spielen?*
Ja, wahrscheinlich. Fast alles aus Singe 1.xx wurde für neuere Versionen von Singe umgewandelt und
verbessert, und die meisten Spiele für Singe 2.xx laufen, wie sie
sind. Spiele, die die älteren Sprite-Funktionen benutzen, brauchen vielleicht eine kleine Änderung; siehe
xref:Reference.adoc#migrating[Umstieg von Singe 2.10].
*Brauche ich ein Laserdisc-Spiel, um Singe zu benutzen?*
Nein. Spiele brauchen überhaupt keine Disc. Sie können Sprites, Video, 3D und
alles andere benutzen, was Singe bietet. Siehe xref:Reference.adoc#withoutadisc[Spiele ohne
Disc].
*Warum zeigt sich das Spiel, das ich gerade installiert habe, nicht im Menü?*
Wer auch immer das Spiel gepackt hat, hat keine ordentliche `games.dat`-Datei beigelegt.
*Warum ist HD-Video langsam?*
Das sollte es nicht mehr sein. Singe benutzt jetzt deine Grafikkarte zum Dekodieren von Video, wenn
dein System das unterstützt, sogar auf dem Raspberry Pi und vielen Handhelds. Wenn HD-Video
immer noch langsam ist, hat dein System vielleicht keine Hardware-Videodekodierung, und
dann braucht hochauflösendes Video viel CPU. Ein Lauf mit `--program`
zeigt, welchen Decoder Singe benutzt.
*Warum stottert mein Ton unter Windows?*
Benutzer haben herausgefunden, dass die meisten Ton- und Stotterprobleme von Singe mit
ihrem installierten Audiotreiber zusammenhängen -- besonders bei Geräten mit Realtek. Versuch,
deine Soundtreiber zu aktualisieren oder auf den generischen Windows-HD-Audio-Treiber
zu wechseln. Schalte Surround-Sound ab -- nimm Stereo, nicht 5.1 oder 7.1. Wenn deine Treiber
dir Stereo nicht erlauben, kannst du das mit Virtual Audio Cable beheben:
. Installiere VB-CABLE (https://vb-audio.com/Cable/).
. Öffne die Soundeinstellungen von Windows (Rechtsklick auf das Lautsprechersymbol in der Taskleiste, dann
*Sounds*, dann *Wiedergabe*).
. Klick mit der rechten Maustaste auf das Gerät *Cable Input* und wähle *Als Standardgerät festlegen*.
(Deine aktuelle Tonausgabe geht vorübergehend verloren.)
. Geh zur Registerkarte *Aufnahme*.
. Klick mit der rechten Maustaste auf *Cable Output*, dann auf *Eigenschaften*, dann auf *Abhören*, und aktiviere schließlich
*Dieses Gerät als Wiedergabequelle verwenden*. Wähle in der Dropdown-Liste dein tatsächliches
Wiedergabegerät.
. Du solltest wieder Ton haben. Starte Singe, und dein Ton funktioniert
ohne Verzögerung.
*Funktioniert 3D auf einem Raspberry Pi oder einem Handheld?*
Auf einem Raspberry Pi 4 oder neuer ja. Sie haben sowohl einen Vulkan-Treiber als auch OpenGL
ES 3.1, und Singe benutzt, was es davon findet. Der Pi 3 hat nur OpenGL ES 2.0,
das das Skinning und die Morph-Targets der Szene nicht ausdrücken kann, also führt er 2D-Spiele
(2D-Physik eingeschlossen) genau wie vorher aus und verweigert den ersten 3D-Aufruf. Der Pi 4
ist das Minimum für jedes Spiel, das das Kapitel 3D-Szenen benutzt. Dasselbe gilt für
die günstigen Handhelds: Ein Mali-G31 oder G610 hat das ES 3.1, das die Szene braucht, ob er
nun Vulkan hat oder nicht. Siehe <<handhelds,Handhelds und kleine Rechner>>.
*Warum stottert mein Ton auf dem Raspberry Pi?*
Raspberry Pi OS benutzt jetzt Pipewire als Standard-Audio-Backend. Ein Wechsel
zu PulseAudio scheint das Problem zu beheben:
. Führe `sudo raspi-config` in einem Terminalfenster aus.
. Wähle *Advanced Options*.
. Wähle *Audio Config*.
. Wähle *PulseAudio*.
. Drück kbd:[Tab], wähle *Ok* und lass es neu starten.
[#_making_games]
== Spiele erstellen
Dieses Handbuch handelt davon, Singe zu betreiben: es installieren, Spiele installieren, einen
Automaten einrichten, und vom Menü. Das Erstellen von Spielen behandeln zwei weitere Bücher, die
ein optionaler Download vom selben Ort wie Singe sind statt ein Teil davon,
da sie zusammen größer sind als die Engine.
* Die *Singe-Referenz* behandelt alles, was ein Spiel tun kann: das Programmiermodell,
das Spieleverzeichnis, das Packen eines Spiels in eine Datei und jede Funktion,
die die Engine bietet, mit ihren Argumenten, ihren Rückgabewerten und einem Beispiel.
* *Programmieren lernen mit Singe* bringt Programmieren von null an bei, in
einunddreißig Lektionen, jemandem, der noch nie Code geschrieben hat. Es kommt mit
den Skripten und dem kleinen Grafikpaket, das die Lektionen benutzen.
Der Download enthält die beiden Bücher als PDF und HTML, die Lektionsdateien und die
Lizenz. Alle drei Bücher gibt es auf Englisch, Französisch, Italienisch, Deutsch und
Spanisch, und den Download gibt es in jeder dieser Sprachen: Nimm den in deiner Sprache. Die
Übersetzungen dieses Handbuchs liegen schon im Ordner `Singe` daneben. Forge, das Autorenwerkzeug, das ein Spiel aus einer Beschreibung statt
aus Code macht, ist ein eigenes Projekt mit eigenem Download und eigenem Buch.