← Zápisky

Jak jsem pro syna oživil staré hry se Čtyřlístkem

Obsah článku

S bráchou jsme jako děti hráli hry se Čtyřlístkem, které bývaly přibalené k cereáliím Nesquik. CD mi doma zůstala a po letech mě napadlo, že by si ty hry mohl zahrát i můj syn. Myslel jsem, že bude stačit trochu si pohrát s nastavením kompatibility. Nakonec dalo jejich zprovoznění podstatně víc práce.

Na svých počítačích používám Linux nebo macOS. Zkusil jsem proto pracovní notebook s Windows 11, jenže hry padaly i na něm. Nakonec jsem všechny tři rozběhal ve Wine v Dockeru. Hrajeme je přes prohlížeč, do kterého se přenáší obraz i zvuk a ze kterého se hra ovládá.

Chtěl jsem jen rozběhat tři hry

Komiksový Čtyřlístek se dočkal také řady počítačových her. Doma jsem měl tyhle tři:

HraRokNázev ve skriptech
Čtyřlístek: Zítra se bude tapetovat2001tapetovat
Čtyřlístek: Sami doma2003sami
Čtyřlístek: Silák Bobík2005silak

Jsou to kreslené 2D adventury ovládané myší. Vznikly na enginu CPAL2 od Centauri Production v době Windows 98 a XP. Grafiku obstarává DirectDraw, zvuk DirectSound, ovládání DirectInput a přehrávání videí DirectShow/AMStream. Nejde tedy o hry pro DOS, ale o programy, které ke spuštění potřebují příslušná rozhraní Windows.

Čtyřlístek – Bobík, Fifinka, Pinďa a Myšpulín před domem s robotem

Chtěl jsem, aby se hry daly spolehlivě spustit, a nechtěl jsem kvůli nim doma udržovat starý počítač s Windows. Lákalo mě ovládání přes prohlížeč: vybrat hru a zahrát si i na jiném zařízení, bez další instalace.

Co jsem zkoušel nejdřív

Ve Windows 11 se hry nainstalovaly, ale při spuštění padaly. Zkoušel jsem různé režimy kompatibility, spolehlivě se mi je ale rozběhat nepodařilo.

Pak jsem zkusil Windows XP v UTM. Systém, pro který hry vznikly, vypadal jako dobrá volba. Přípravou virtuálního počítače a instalací XP jsem strávil asi hodinu a půl a nakonec narazil na chybějící podporu DirectX. Samotná instalace starých Windows nestačila. Záleželo i na tom, jaký hardware a grafiku jim UTM zpřístupní, a moje konfigurace požadavky her nesplňovala.

Další pokus byl s v86, emulátorem x86, který běží v prohlížeči. Chtěl jsem v něm spustit Linux i386, v Linuxu Wine a k tomu vytvořit jednoduchou stránku pro výběr a spouštění her. Všechno by tak běželo přímo v prohlížeči.

Při tomhle pokusu jsem si ověřil, že webové ovládání je dobrý nápad. Na jedné stránce šlo vybrat hru, spustit ji a rovnou sledovat stav i chybové výpisy. Každá úprava emulovaného systému a její vyzkoušení ale trvaly dlouho. Navíc padalo už samotné Wine, často dřív, než se hra vůbec spustila. Objevovaly se chyby WINE_EXITED_EARLY a problémy kolem virtual_map_user_shared_data.

Pokus s v86 – hra ve Wine v prohlížeči, pod ní ovládání a ladicí konzole

Místo her jsem tak ladil hlavně to, proč v emulovaném systému nestartuje Wine. Přitom v Dockeru s Wine, bez v86, hry fungovaly. Rozhodl jsem se proto využít to, co už běželo, a k tomu připojit webové ovládání.

Hra na serveru, ovládání v prohlížeči

Základem funkčního řešení je Docker image pro linux/386 s Wine, Xvnc z TigerVNC, noVNC, websockify, PulseAudio a malým řídicím serverem v Pythonu.

Samotná hra běží na počítači s Dockerem. Prohlížeč jen zobrazuje vzdálenou plochu a předává jí stisky kláves a pohyby myši. Nemusí už emulovat procesor přes v86. Počítač, na kterém běží Docker, ale musí umět spustit image pro i386.

Spojení jsou tři a každé má jiný účel:

Obraz a ovládání: prohlížeč <-> noVNC / websockify <-> Xvnc <-> hra ve Wine
Zvuk:            PulseAudio -> řídicí server -> WebSocket -> prohlížeč
Spouštění:       prohlížeč -> řídicí API -> spustit / zastavit / stav / záznamy

Ve Wine běží samotná hra, tedy cdromek.exe. Xvnc vytváří grafické prostředí a rovnou ho zpřístupňuje přes VNC. Díky tomu není potřeba další program, který by plochu průběžně snímal. noVNC ji zobrazí v prohlížeči a websockify propojí WebSocket z prohlížeče se serverem VNC.

Zvuk se přenáší zvlášť. PulseAudio ho ze hry posílá do virtuálního zvukového zařízení, takzvaného null sinku. Odtud ho řídicí server zachytává a přes WebSocket posílá do prohlížeče. Tam ho AudioWorklet přehrává jako nekomprimované vzorky PCM.

Při přehrávání je potřeba mít ve vyrovnávací paměti trochu zvuku do zásoby. Když je zásoba příliš malá, zvuk vypadává. Když je velká, ozývá se se zpožděním. Zmenšením zásoby se mi podařilo odezvu zlepšit, ale obraz a zvuk pořád mají každý svůj vlastní přenos.

Server v Pythonu se stará i o spouštění vybrané hry, ukončování zbylých procesů Wine a zobrazování stavu a výpisů. Každé hře také nastaví grafiku trochu jinak. U tapetovat lze dát přednost přibalené náhradní knihovně ddraw, zatímco sami a silak mi lépe fungují s verzí vestavěnou ve Wine.

Co hry očekávají od starých Windows

Jakmile fungovalo spouštění, mohl jsem se pustit do dalších problémů. Opakovaly se hlavně tři: instalátory, pevně dané cesty k souborům a chybějící součásti Windows.

Spuštění bez instalace

Pro tapetovat už jsem měl herní soubory rozbalené. U dalších dvou her jsem se nejdřív musel dostat přes instalátor. Na CD byly archivy Centauri CPack: v cdromek.pak ležela herní data a v cdromek2.pak spustitelný program.

Po rozbalení do souborů cdromek.res a cdromek.exe už šly hry spouštět přímo z připravené složky. Při dalších pokusech odpadla instalace a se všemi třemi hrami se dalo pracovat podobně. Jeden problém byl vyřešený.

Soubory musí být tam, kde je hra hledá

Hry hledaly soubory například v C:\runtime-* nebo C:\Program Files\Ctyrlistek\.... Nestačilo je tedy jen nakopírovat do kontejneru. Musely být dostupné i pod cestou, se kterou hra počítala.

Spouštěcí skript proto připraví pracovní kopii hry, do které lze zapisovat, a podle potřeby ji zpřístupní pod dalšími cestami. U proměnných TEMP a TMP nastaví cesty ve formátu Windows. Při spouštění hry z linuxového shellu člověk na takové drobnosti snadno zapomene.

Chybějící písma a multimediální součásti

Musel jsem také doinstalovat základní písma a nastavit náhrady pro staré názvy písem, například Arial CE. Podobně bylo potřeba zaregistrovat COM komponenty pro DirectShow, doplnit hodnoty do registru pro starší DirectX a nastavit přiřazení starých názvů kodeků.

Některé pády přitom vypadaly jako chyba samotné hry. Ve skutečnosti jí jen chybělo písmo nebo multimediální komponenta, na kterou byla ze starých Windows zvyklá.

Poslední velká překážka: videa v menu

Nejdéle mě potrápilo přehrávání AVI videí v menu her sami a silak. Při pádech se ve výpisech CPSE a AMStream objevovaly tyto chyby:

CPSE: Stream open file failed
Can't create multimedia stream instance
RenderEx -> 0x80040218

AVI je jen formát kontejneru. Podle přípony se nedá poznat, jaký kodek bude k přehrání videa potřeba. V sami byly klipy z éry Intel Indeo, v silak i video WMV3. DirectShow proto nejdřív muselo najít a propojit komponenty, které dané video zvládnou přečíst a přehrát.

Zkoušel jsem videa převádět do jiných formátů a zjednodušovat jejich přehrávání, ale DirectShow na některých místech pořád selhávalo. Nakonec jsem upravil přímo spustitelné soubory her: vynuloval jsem v nich odkazy na menu_*.avi, takže se problémová videa přestala spouštět.

Přišli jsme tím o animované úvody v menu, ale samotné hry se dají hrát. Pro věrné zachování původní podoby to není ideální, pro naše hraní je to přijatelný kompromis. Úprava navíc funguje jen pro konkrétní verze souborů. V jiné verzi mohou být potřebné bajty na jiném místě.

Hlavně že si spolu zahrajeme

Všechny tři hry už spouštím z webového rozhraní. Skript připraví soubory bez instalace, ukončí procesy z předchozího hraní a použije nastavení pro vybranou hru. Zvuk má menší zpoždění než na začátku a kvůli videím v menu už hry nepadají.

Slabým místem zůstává přenos obrazu. Při větší zátěži se může trhat; někdy jsem se dostal jen na něco přes dvacet snímků za sekundu. Platí to pro moje nastavení, ne obecně pro Wine nebo noVNC. Dalším laděním grafiky a přenosu obrazu by se plynulost nejspíš dala ještě zlepšit.

To hlavní už ale funguje: se synem ty hry opravdu hrajeme. Přesně kvůli tomu jsem se do toho pouštěl.

Teď ho ještě naučit zacházet s myší. Doteď hrál hlavně na telefonu. Po všem tom ladění Wine a starých videokodeků je to mnohem příjemnější starost.