Eind vorig jaar kwam ik door het algoritme van YouTube een kanaal tegen dat hedendaagse muziek sampelt op de hardware van een Nintendo, zoals Blue en – persoonlijke favoriet – Blinding Lights.
Na wat zoeken kwam ik er achter dat het niet alleen mogelijk is om de muziek na te maken, maar dat een stel vrienden zelfs hun eigen game uitgebracht hadden. Inclusief software – NESMaker – om datzelfde te doen.
Supertof, want hoewel ik ook na de NES totaal afgehaakt ben met gamen, was ik als kind redelijk verslaafd aan Super Mario, Ducktales en Zelda.
Brainstorm met het puzzelteam
Toen ik begin dit jaar uitgenodigd werd door het puzzelteam voor een brainstorm voor ideeën voor de Q-escape room 2022 heb ik voor een paar dollar een licentie gekocht en met de tutorial assets een scherm met het Q-logo en een poppetje gemaakt. Dat ik op m’n telefoon demonstreerde. Oorspronkelijk met een knipoog naar Super Mario, waar de prinses in een ander kasteel (online) is. Waardoor het spel op een console in de Q-escape room begon en later online verder ging.
Want als je dan een keer een spel kan maken, dan moet het ook groots.
Dus eind van de zomer kreeg ik te horen dat het puzzelteam graag een NES game wilde hebben, alleen dan wel met 9 levels… Iets meer dan dat ik in gedachten had…
Muziek
Negen levels die ik naar eigen hand mocht vullen, als elk level maar bepaalde muziek bevatte.
De muziek is door Kevin – een van de audiovormgevers van Q – vanuit midi omgezet naar FamiStudio formaat, dat geïmporteerd konden worden door NESMaker. Hoewel de muziek nog niet eens door echte hardware werd afgespeeld kreeg je toch al dat nostalgische soundje. En dat met 4 kanalen waarvan er ook nog 1 een noise channel was.
Naast die beperking kon de muziek niet in z’n geheel gebruikt worden. En waren er limitaties in het aantal noten dat gebruikt konden worden. Al met al, toch nog best wat geknutsel.
Toen de negen tracks af waren bleek dat ze – ondanks het zo klein mogelijk maken – toch niet in z’n geheel op één geheugenruimte van de NES pasten. Waardoor er een stukje custom code geschreven moest worden om twee geheugenruimtes te kunnen gebruiken (dank aan het 8-bit heroes forum). Best wel een spannend moment, want dat was het belangrijkste element van het spel.
En niet alleen tijdens het maken van de soundtrack, maar ook bij het maken van de graphics en levels liep ik vaak genoeg tegen allerlei beperkingen op.
Hoewel de software pretendeert dat er geen code skills nodig waren heb ik toch het een en ander aan moeten passen voor het specifieke game verloop.
Kleuren en graphics
NES games zijn geschreven in assembly, een oude programmeertaal die totaal niet intuïtief is en bovendien niet veel kan op de oude hardware. Zo kunnen er per scherm maar maximaal 13 kleuren gebruikt worden, in 4 groepjes van 4, waardoor er effectief nog minder overblijven, door bijvoorbeeld een kleur die overlapt.
De meeste levels bestaan uit een grid van 16×15 vakjes. Waarbij elk vakje uit 16×16 pixels bestaat. Een scherm is dus slechts 256×240 pixels groot en past dus 15x in de breedte en 9x in de hoogte op een modern 4K scherm.
De graphics in een level bestaan uit een combinatie van een aantal 2-bits afbeeldingen die in totaal 8 bij 8 blokjes groot is. En waarvan weer elk blokje 16×16 pixels is.
Omdat de ruimte beperkt is, is het handig om sommige blokjes in meerdere levels te gebruiken. Zoals hier in het voorbeeld de onderste twee rijen.
De graphics zijn dus 2-bits, dat wil zeggen 4 kleuren, die later bij het toewijzen aan het level gekoppeld worden aan een palet. Dus ik heb urenlang in Photoshop hokjes van 16×16 pixel getekend in zwart (color 0), rood (color 1), groen (color 2) en blauw (color 3).
Om een scherm in een level te maken moet je voor alle 16×15 blokjes uit het grid opgeven welk deel van de graphics zichtbaar moet zijn en met welk sub-palet dat gebruikt moet worden.
Ook geef je nog per blokje uit het grid aan wat er gebeurt als de speler op dat hokje komt. Kan het zich vrij bewegen, is het een solid (bijv. een muur of vloer), kun je er doorheen springen of is het een ladder.
Code
Naast deze standaard acties heb ik ook een paar eigen acties gemaakt, bijvoorbeeld om de warps (de deuren naar de volgende levels) te maken. Die werken in tegenstelling tot de standaard warp alleen als je een voorwerp gepakt hebt en als je op de up-knop gedrukt hebt.
In elk level moet de speler een voorwerp pakken. Door dit voorwerp te pakken wordt er een tellertje (completedLevels) in het spel opgehoogd (dit zie je ook op het scherm). Je begint dus bij 0 en eindigt bij 9. Elke keer als de speler het level complete scherm ziet na het uitspelen van een level wordt er een stukje code uitgevoerd dat een warp maakt op basis van de teller. En als de speler bijv. door het deurtje gaat zonder het voorwerp te pakken, dan gaat hij naar het begin van de huidige level.
WarpToContinuePoint:
;; arg0: Map to warp to: Overworld (00), Underworld (01)
;; arg1: Screen to warp to: First byte row (Y) of map, 2nd byte: column (X) of map.
;; arg2: screen transition type - most likely use 1 here. (1 = use warp-in location)
LDA completedLevels
CMP #$00
BNE notLevel1
;; level 1: Scheveningen
WarpToScreen #$00, #$10, #$01
RTS
notLevel1:
CMP #$01
BNE notLevel2
;; level 2: Aquamundo
WarpToScreen #$00, #$06, #$01
RTS
notLevel2:
CMP #$02
BNE notLevel3
;; level 3: Thijs festival
WarpToScreen #$00, #$3A, #$01
RTS
Super Mattie
Niet alleen de levels heb ik gemaakt, ook alle figuurtjes in het spel heb ik getekend. Want als Mattie het spel gaat spelen, dan kan het ook niet anders dan dat het figuurtje ‘Super Mattie’ komt te heten.
De figuurtjes in het spel bestaan uit blokjes van 8×8 pixels en kunnen uit meerdere blokjes bestaan. Super Mattie is bijvoorbeeld 2×4 blokjes (16×32 pixels). De figuurtjes hebben een ander palet dan de levels dat ook weer uit 4 sub-paletten bestaat en waarvan 1 kleur transparant is. Maar dit palet wordt tevens gebruikt voor de tellertjes boven in beeld (de HUD) en de vijandjes en ander figuurtjes.
Per actie (staan, naar links/rechts lopen, naar links/rechts springen, klimmen en gewond raken) maak je een animatie. Dat zijn eigenlijk verschillende plaatjes (frames) achter elkaar. Die allemaal uit verschillende blokjes uit een afbeelding opgebouwd zijn.
Sommige delen van een figuurtje veranderen niet: Het hoofd blijft bijvoorbeeld hetzelfde tijdens het lopen. Die kun je dus hergebruiken. En wat ook makkelijk is: de blokjes van een speler kun je spiegelen (dat kan in levels niet). Zo is de animatie voor links lopen bijna gelijk aan rechtslopen (behalve dat het haar van Super Mattie gelijk blijft; z’n scheiding spiegelt niet!).
Dall-e
En leuk feitje: voor sommige graphics in het spel heb ik Dall-e gebruikt. Bijvoorbeeld voor Kikki, de kat van Marieke ofwel: ‘8bit pixelart cat enemy‘.
En zo heb ik dus wekenlang tot ’s avonds laat en diep in het weekend collega’s verpixeld en levels bedacht. Soms super frustrerend, maar super gaaf om te doen!
Het uiteindelijke spel is slechts 512 kilobytes groot. Dus past ongeveer 3x op een oude diskette(!) of 2 miljard keer op een 1TB harddisk.
De cartridge
Dan is het spel klaar, maar moet het nog wel op een cartridge gezet worden. Want het spel wordt immers vrijgespeeld na een volgend spel. En hoe cool is het om een 8-bit game ook daadwerkelijk op oude hardware te kunnen spelen?
Er waren een paar opties:
- Een Raspberry Pi in een Nintendo case 3D doen. Naast dat dat niet de real-deal is, is het verrassingseffect ook minder groot. Immers: nu stond er een NES met een paar games al dagenlang in de escaperoom ’ter afleiding’ na de uitzending.
- Een cartridge met een cartridge flasher op een cartridge zetten. Dan heb je echt een cartridge, maar moet je ook hardware aanschaffen om de game erop te zetten.
- Of: een Everdrive. Dat is een cartridge waarin een SD kaartje geplaatst kan worden waarop spellen gezet kunnen worden.
De Everdrive was de beste optie, alleen er was 1 probleempje. De maker van die dingen woont in Kiev, Oekraïne. En laat daar nu begin dit jaar door een oude gestoorde gek een oorlog zijn begonnen. (Wist je dat Poetin trouwens maar 170cm klein is. Als je ‘m nog nog eens met ontbloot bovenlijf op een paard ziet zitten, weet dat het zo’n Shetlandpony als bij de kinderboerderij is).
Afijn: De cartridge moest uit Kiev komen. En op de site stond letterlijk: “PLease forgive for some delay, we work amost 24/7.“ (sic) Maar wonderwel ging dat best snel.
Althans: de post in Oekraïne was vrij snel. De maker had ‘m direct op de bus gedaan en via de Oekraïense post een Track & Trace gestuurd. En na een week of wat een mail via PostNL van de douane gekregen dat ik inklaringskosten moest betalen. Dus ik direct betaald (letterlijk 10 minuten na de mail), in de hoop dat ik de cartridge dan morgen of overmorgen zou hebben. Maar nee… dat ding heeft nog een week (op de minuut af) bij de douane gelegen. Wegens: ja weet ik ook eigenlijk niet.
Uiteindelijk duurde het in totaal 3 weken, en dan is het super spannend om erachter te komen of het ook daadwerkelijk werkt: Dus SD-kaartje erin en m’n oude Nintendo bij m’n ouders opgehaald. En ja… het werkte! In 1 keer. M’n eigen NES game op m’n eigen NES!
Q-escape room
En dan komt de dag dat het spel ook daadwerkelijk gespeeld gaat worden. Ik was super zenuwachtig omdat de opdracht hiervoor erg lang duurde en het volgende ontsnapmoment dichter- en dichterbij kwam (met de kans dat ze – nog voordat het spel vrijgespeeld werd – de escaperoom zouden verlaten). Samen met een collega ben ik naar de locatie van de escaperoom gegaan en heb ik achter de schermen bij de videoregie angstvallig meegekeken.
Toen ik aan kwam was de voorgaande puzzel nog niet opgelost – 4 luisteraars moesten een aantal poppen door het land op de juiste plek brengen en er stond file – het was 17:00, een kwartier voor de ontsnappoging.
Wat was hier gebeurd?!
In spanning bleek dat het antwoord van Mattie – het enige antwoord dat nog niet klopte – nu ook weer fout was. Een hele opluchting. En alsof dat nog niet spannend genoeg was kwam er ook nog een pressure-room achteraan. Een opdracht die Kai op 200 milliseconden(!) na net niet haalde. Het ontplofte: zowel voor als achter de schermen. Wat was hier gebeurd?!
Niet snel daarna kwamen de poppen ook daadwerkelijk de plek van bestemming aan en werd de cartridge dan eindelijk vrijgespeeld. En omdat ik bij de regie zat kon ik ook de off-air audio horen. De verbazing bij de DJ’s was enorm: Hoe was het überhaupt mogelijk om een 8-bit spel op een echte ouderwetse Nintendo te maken?! En hoe cool is het om jezelf als spelkarakter te hebben?
Omdat de DJ’s slechts tot 19:00 mochten spelen moest men tot de volgende ochtend wachten om verder te spelen. Die volgende ochtend bereikte Domien level 3 waarna een bericht in de game verscheen dat de luisteraars van Q ook konden meehelpen om het spel uit te spelen. Want hetzelfde spel kon ook gespeeld worden op ikwildehighscore.nl.
Speel het spelLetterlijk tienduizenden mensen hebben een poging gewaagd om het spel te spelen. Maar uiteindelijk was het Domien – die een voorsprong van 3 levels had – die het spel het eerste uitspeelde en het eindscherm te zien kreeg. Met daarop de volgende opdracht, die al snel tot de goede oplossing leidde…
Al met al supertrots dat ik een kleine bijdrage aan deze fantastische productie heb mogen leveren.
En voor degene die zich afvragen wat de 9 levels waren: Dat waren op de laatste 2 levels na (die een tribute aan Ducktales spellen waren) verwijzingen naar locaties waar Qmusic dit jaar uitzending gemaakt had:
- Level 1: Het strandfeest op Scheveningen
- Level 2: Aquamundo met Badmeester Griep (Antons verjaardag)
- Level 3: Het Thijs-festival
- Level 4: Top 40 Awards
- Level 5: De Foute Party
- Level 6: Kraamvisite bij Marieke
- Level 7: De Piraña in de Efteling (Domiens verjaardag)
Een soort jaaroverzicht dus, en dat was verder geen hint.
En voor de liefhebber: de rom van het spel vind je hier.