Geen remake meer: het hele spel gedecompileerd
In mijn vorige post schreef ik over mijn remake in three.js en over een nieuwe versie in Unreal Engine. Allebei hadden ze hetzelfde probleem: ik was het spel aan het nabouwen. Elke deur, elke vijand, elke cutscène moest ik opnieuw maken en gokken hoe het origineel het deed. En het voelde nooit helemaal als RedCat.
Dus ben ik het anders gaan doen. Ik bouw het spel niet meer na: ik heb het originele spel
gedecompileerd. De code die Davilex in 2000 schreef is teruggehaald uit de .exe op de cd, als
leesbare C++, en die code draait nu in je browser.
Wat is er nu precies gedaan?
Het spel zelf zit op de cd in RcHcGame.dat. Ondanks de naam is dat gewoon een Windows-programma,
gebouwd met Microsoft Visual C++ 6. Daarin zitten drie dingen:
- Genesis3D 1.1, de open-source 3D-engine waar ik het al eerder over had;
- “Adam”, het eigen framework van Davilex voor actors, levels, menu’s, geluid en input;
- Davi-Script, een kleine scripttaal waarmee de levels, cutscènes en triggers zijn gemaakt.
Genesis3D hoefde ik niet te decompileren: daarvan is de broncode vrij beschikbaar. Al het andere,
het framework en de RedCat-code zelf, is functie voor functie teruggebracht naar C++, met dezelfde
bestandsnamen en klassen als het origineel. Die namen staan nog gewoon in het programma, in de
foutmeldingen die de ontwikkelaars erin hadden laten zitten (D:\Work\RCHorror\AdamSource\...).
Het menu is een apart programma, geschreven in Delphi. Dat heb ik niet regel voor regel gedecompileerd, maar opnieuw opgebouwd voor het web uit de originele schermen, plaatjes en knop-handlers. Daardoor ziet het er precies zo uit als vroeger, inclusief de stemmetjes.
Alles samen wordt met Emscripten gecompileerd naar WebAssembly. Voor het tekenen heb ik een nieuwe WebGPU-driver voor Genesis3D geschreven, op de plek waar vroeger de Direct3D- of Glide-driver zat. Geluid gaat via WebAudio, de filmpjes zijn omgezet naar MP4 en spelen gewoon af, en je spelers, instellingen en highscores worden opgeslagen in de browser (IndexedDB). En omdat het nu op een moderne videokaart draait: native resolutie, tot 4K aan toe, ook op breedbeeld.
Hoe dan?
Een paar jaar geleden was dit voor één persoon in zijn vrije tijd vrijwel onbegonnen werk. Het spel bestaat uit duizenden functies. Wat het nu mogelijk maakte:
- Ghidra, de disassembler en decompiler van de NSA, headless gedraaid over het hele programma;
- rea, dat Ghidra aanstuurt zodat je per functie pseudocode, verwijzingen en strings kunt opvragen;
- AI-hulp met Claude Code: meerdere hulp-agents die tegelijk elk hun eigen bestanden reconstrueren, volgens vaste regels, en een “integrator” die alles nakijkt, samenvoegt en test. Elke functie in de broncode heeft een commentaar met het originele adres in het programma, zodat alles terug te controleren is.
Het is dus geen magie en ook geen “AI heeft een spel gemaakt”. Het is heel veel vergelijken: wat doet het origineel, wat doet de nieuwe code, en waarom wijkt het af.
Een paar leuke vondsten
De platte fee. De Fleurifee had in mijn versie een gloed en een bloem die plat op de grond
lagen in plaats van naar de camera te kijken. De oorzaak zat in de C-runtime van 2000: een
wiskundefunctie in het programma (op adres 0x60aec0) bleek asin te zijn en niet acos, zoals
eerst gedacht. Klein verschil, maar daardoor kantelde alles 90 graden.
Snelspel of avontuur? In het menu kies je tussen een snelspel en een avontuur. Mijn menu schreef die keuze precies omgekeerd weg. Gevolg: in het avontuur werden alle cutscènes met de fee overgeslagen (de levelscripts zetten ze bewust uit in een snelspel). En aan het begin van een avontuur klonk ook nog eens vrolijk “Snelspel!”, omdat mijn menu beide startzinnen achter elkaar afspeelde in plaats van één van de twee.
Gemaakt voor 640×480. Het spel is ontworpen voor een beeldscherm van 640×480. Op een breed 4K-scherm gingen er dingen mis die in 2000 nooit konden gebeuren: de balk onderin het pauzemenu liet een gat open aan de zijkanten, en bij 2160 pixels hoog paste een letter niet meer in de lettertype-texture van Genesis3D, waardoor het geheugen corrupt raakte. Beide opgelost, met het origineel als referentie.
Niet de nieuwste engine. Er bestaan nieuwere versies van Genesis3D, maar die lezen de textures van de levels als truecolor, terwijl RedCat 8-bit textures met een palet gebruikt. Het spel draait daarom op de originele Genesis3D 1.1, precies de versie waarmee het destijds is gebouwd.
Hoe ver is het?
Het spel is van begin tot eind speelbaar vanuit het originele menu: laadschermen, cutscènes met stemmen, alle vijf de levels, de HUD, schieten, springen, oppakken, doodgaan en opnieuw beginnen, het pauzemenu en de eindscores.
Van de code van Davilex zelf is het Adam-framework voor ongeveer 95% gereconstrueerd en de RedCat-code voor 99%. Over het hele programma gemeten (inclusief losse functies die nog niet in een bestand zijn ingedeeld) staat de teller op ruim 81%. Wat er nog ontbreekt of afwijkt:
- het gedrag van de vijanden is nog niet stap voor stap vergeleken met het origineel;
- mist en mipmaps zitten nog niet in de WebGPU-driver;
- de muis draait RedCat nu om zijn as; in het origineel werkte de muis als extra pijltjestoetsen;
- de helpknoppen in het menu: het origineel liet daar de Fleurifee als Microsoft Agent over je scherm vliegen, die is er (nog) niet bij.
Je hebt een browser met WebGPU nodig (Chrome of Edge werken het best), en een toetsenbord en muis. Op een telefoon gaat het niet. Kom je een bug tegen, of iets dat anders is dan je het je herinnert? Laat het me weten!
Waarom zo?
Een remake blijft een interpretatie. Met de gedecompileerde code is het gewoon RedCat Spookkasteel: dezelfde sprongen, dezelfde vijanden, dezelfde rare camerahoeken, alleen nu scherp en zonder Windows 98. En het is een basis waar je op verder kunt bouwen: andere talen, betere besturing, misschien ooit gamepad- of touchbediening.
Veel speelplezier in het kasteel.