Het overbrengen van Quake naar de Game Boy Advance leek onmogelijk, maar Randy Linden slaagde erin het voor elkaar te krijgen. Hier is hoe.
De Game Boy Advance is een draagbare spelcomputer gemaakt door Nintendo. Het werd in 2001 in Japan uitgebracht en diende als opvolger van de Game Boy Color. Het had een ARM7TDMI geklokt op 16,78 MHz, 32 kb intern werk-RAM, 256 kb extern RAM en 96 kb VRAM. Het is niet de krachtigste machine, maar er zijn genoeg games voor de handheld die velen in goede herinnering houden. Eén game die voor het apparaat echter nooit het levenslicht zag, was een prototype-port van Quake, een game ontwikkeld door id Software die hielp bij het definiëren van het first-person shooter-genre dat we vandaag de dag kennen.
Quake is een ongelooflijk gedetailleerd spel met een fantastische soundtrack en verslavende gameplay, en net als DOOM is het geschikt voor vrijwel elk apparaat dat je maar kunt bedenken. De poort naar de Game Boy Advance is bijzonder ongelooflijk omdat deze niet standaard 3D-graphics ondersteunt, en Nintendo heeft de handheld specifiek op de markt gebracht als een tweedimensionale gameplay-ervaring. Dat weerhield Randy Linden er echter niet van om zijn eigen haven te ontwikkelen.
Als je Linden niet kent: hij staat vooral bekend als de ontwikkelaar van beide bleem! (een PlayStation-emulator) en de SNES-poort van DOOM, een prestatie die John Romero, mede-oprichter van id Software, ooit zei in een interview met Shacknieuws hij dacht niet dat het mogelijk was. Linden's ontwikkelingsvaardigheid bewees dat als iemand Quake op de Game Boy Advance werkelijkheid zou kunnen maken, hij het waarschijnlijk was.
Deze port is aan het licht gekomen dankzij Linden's eigen release ervan via het Forest of Illusion-project. Forest of Illusion is een project gericht op het behoud van de geschiedenis van de games van Nintendo en Linden nam contact op om de kopie van de Quake-poort te verspreiden die hij op een flashkaart van 256 MB in de zijne had gevonden bezit.
We willen Randy Linden bedanken voor het besteden van tijd aan het beantwoorden van onze vragen en het garanderen van de technische nauwkeurigheid van dit artikel. Wij willen ook graag bedanken Moderne vintage gamer voor het feit dat we alle benodigde stills uit zijn video mochten gebruiken. Deze port heeft geen officiële relatie met id Software of ZeniMax en is ontwikkeld als soloproject door Linden.
Quake's Game Boy Advance-poort
Technisch gezien is het een wonder dat Quake zelfs het niveau kan halen dat het doet op de Game Boy Advance. Het draait op een goede framesnelheid en behoudt de juiste belichting en kleurenpalet van het originele Quake-spel. Alles is 3D, inclusief wapens en monsters. Games op de Game Boy Advance bereikten 3D-graphics, meestal via sprites, maar dit was het echte werk. Het maakt geen gebruik van raycasting zoals andere 3D-games op de handheld deden, en het bereikt zelfs punten lichteffecten op vooraf gerenderde objecten via een paletveranderende truc om een illusie van dynamiek te bereiken verlichting.
Voor alle duidelijkheid: deze port is niet het volledige spel, en het is een prototype dat Linden van plan was mee te nemen naar id Software zodra het klaar was om te worden uitgebracht. De populariteit van de Game Boy Advance begon echter af te nemen, en in plaats daarvan werd de door Linden geschreven aangepaste engine later de engine van een ander spel dat volledig door Linden was ontwikkeld: Cyboid. Linden vertelt ons dat een "groot deel van de code" nog steeds de originele ARM-code is van de Game Boy Advance-versie. Als je Cyboid wilt uitproberen, is er een oudere versie beschikbaar in de Google Play Store, maar de officiële APK wordt nu verspreid op de Amazon App Store omdat de game veel 32-bits code op laag niveau bevat.
Prijs: gratis.
3.3.
Linden heeft ook een video met ons gedeeld waarin zijn code op de iPod Video draait, een van de eerste versies van Cyboid. Het was gebouwd op dezelfde enginecode die werd gebruikt voor zijn Quake-port naar de Game Boy Advance.
De Game Boy Advance-port van Quake bevat geen officiële onderdelen van het spel, zoals Linden niet heeft nam contact op met id Software of ZeniMax over de distributie van de E1M1-versie die de officiële Quake bevat activa.
De game die momenteel wordt gedistribueerd, is ook een debug-build. Door tijdens het opstarten de R-toets ingedrukt te houden, wordt de speler rechtstreeks naar de tweede kaart van het spel gebracht, en door links op het D-pad ingedrukt te houden, wordt de speler naar de derde kaart gebracht. Het wisselen van kaarten is ook mogelijk als de speler sterft, en monsters zullen de speler pas aanvallen als de speler eerst op ze schiet.
Wat muziek betreft, maakt de demo gebruik van openbare .S3M-bestanden en kan de geluidsmixer zowel stereomuziek als geluidseffecten verwerken.
Technische grenzen
Er waren een aantal grenzen als het om de Game Boy Advance ging, waardoor dit een moeilijke port werd. Enkele van de grootste obstakels waren de lage kloksnelheid, het gebrek aan grafische 3D-mogelijkheden van de handheld en het ontbreken van een floating-point unit (FPU). Er waren er nog veel meer, maar dit waren specifieke pijnpunten die Linden mij als problematisch bestempelde. Voordat we erop ingaan, is het belangrijk om de lay-out van de Game Boy Advance te begrijpen.
De Game Boy Advance heeft drie sets RAM: één is het interne werk-RAM (IWRAM), een andere is het externe werk-RAM (EWRAM) en de derde is video-RAM (VRAM). De 32 kb IWRAM wordt gebruikt voor het opslaan van ARM-instructies voor snelle uitvoering, terwijl de 256 kb EWRAM optimaal is voor het opslaan van Thumb-only-instructies en kleinere hoeveelheden gegevens. Als Rodrigo Copetti merkt opkan EWRAM tot zes keer langzamer worden benaderd dan IWRAM. Het grootste deel van het geheugen in de vorm van EWRAM is alleen toegankelijk via een 16-bits bus, ondanks dat de Game Boy Advance op de markt wordt gebracht als een 32-bits handheld. Het IWRAM was toegankelijk via een 32-bits bus. VRAM op de Game Boy Advance komt uit op 96 kb, en hoewel het voornamelijk bedoeld is voor het opslaan van grafische gegevens, bevindt het zich in de geheugenkaart van de CPU en kan het ook worden gebruikt als normale geheugenopslag.
Duiminstructies zijn een subset van 32-bits ARM-instructies, en zijn een reeks instructies gecodeerd in 16-bits woorden. Ze hebben alle voordelen van 32-bits instructies zonder zoveel ruimte in beslag te nemen, waardoor ze efficiënt zijn voor geoptimaliseerde ontwikkeling. Dit betekent dat hoewel EWRAM langzamer toegankelijk is, de Duim-instructies die efficiënt zijn, vaak nog steeds net zo snel kunnen eindigen als de opgeslagen ARM-instructies. in IWRAM, hoewel het nadeel van Thumb-instructies is dat er soms niet helemaal het Thumb-equivalent is van een ARM-instructie die je wilt uitvoeren uitvoeren. Het EWRAM werd gebruikt voor het opslaan van de uitvoer van de 3D-wiskundige transformatielogica, wat in feite de lijst met polygoonranden was die vervolgens scanlijn voor scanlijn werden uitgetekend door de rasterisatiecode.
Zoals Linden me vertelt, was het meest complexe en moeilijke deel van de hele port de scanline-renderer. Het bestaat uit meer dan 10.000 regels sterk geoptimaliseerde ARM-assemblagecode die is ontworpen om een reeks pixels naar VRAM te tekenen. De scanline-renderer gebruikte het grootste deel van de 32 kb IWRAM. De randen die zich het dichtst bij de camera bevinden, zijn actief en weergegeven, en het is in wezen een grote BSP-boom (Binary Space Partitioning). VRAM werd gebruikt om de resultaten van de polygonale transformatie-uitvoer in randtabellen op te slaan omdat er niet genoeg IWRAM was, maar VRAM op de Game Boy Advance is nog steeds sneller dan EWRAM. Ook de afbeeldingen werden hier opgeslagen en weergegeven.
Hij besteedde veel tijd aan optimalisaties om ervoor te zorgen dat de uitvoering zo snel mogelijk kon worden uitgevoerd. Drie dingen die hij deed om die uitvoeringstijd te versnellen, waren onder meer:
- Zelf de code aangepast voordat deze werd uitgevoerd, waardoor er minder instructies nodig waren
- Gebruikte een reeks opzoektabellen voor zaken als reciproque, sinus, cosinus, tangens, enz.
- De CPU-"modus" is gewijzigd om toegang te krijgen tot extra registers (die lijken op "variabelen") zonder dat u de registerwaarden hoeft op te slaan en te herstellen.
Het omschakelen van de CPU-modi om extra registers te verkrijgen is een ongelooflijk slimme manoeuvre die snelle toegang mogelijk maakt tot waarden dichtbij de CPU, zodat ze in een enkele klokcyclus kunnen worden opgehaald. Zoals Linden me vertelt, was het mogelijk om in één klokcyclus van register te wisselen en een waarde op te halen, in tegenstelling tot het opslaan van een waarde in het RAM van de Game Boy Advance, wat langer duurt. De CPU zelf is een 16,78 MHz-processor, wat betekent dat hij 16780000 cycli per seconde kan voltooien. Dat klinkt veel, maar als je elke pixel op het scherm moet berekenen en tekenen, tellen die snel op en wordt het belangrijk om zoveel mogelijk bewerkingen uit te sluiten.
Het bovenstaande is de lijst met algemene registers van de ARM7TDMI-chipset die zich in de Game Boy Advance bevindt. Normaal gesproken zouden ontwikkelaars alleen toegang krijgen tot de registers binnen de modus "Systeem en gebruiker" en hun toevlucht nemen tot het gebruik van normale variabelen daarbuiten. Hij maakte echter gebruik van registers in alle zeven modi van de chipset, en het beste eraan is dat Bij het wisselen van modi blijven de waarden in de registers van de andere modi behouden, zodat hij tussen de modi kon schakelen hen.
Grappig genoeg vermeldde Linden ook hoe zijn manier van bankoverstappen een bug in de Nanoboy Advance-emulator aan het licht bracht. Het bleek dat die emulator het gebruik van de andere modi van de CPU voor het opslaan in registers en het schakelen niet ondersteunde, en zijn Quake-demo was het eerste bekende spel dat dit daadwerkelijk deed.
Linden deelde een foto met ons van enkele van de aantekeningen die hij maakte en legde uit hoe hij zijn drijvende-kommaberekeningen optimaliseerde bij gebrek aan een goede FPU.
De bovenstaande afbeelding is er een die Linden met ons deelde vanuit zijn aantekeningen, en wat vooral interessant is, zijn de "diverse ARM-cyclusinstructietellingen". Hij bedacht een manier om de cycli voor berekeningen te optimaliseren, zodat hij het aantal klokcycli voor een berekening kon verminderen. Zoals hij het mij beschreef, kon een getal van 8 bits in één klokcyclus worden vermenigvuldigd, een getal van 16 bits in twee klokcycli, een getal van 32 bits in drie klokcycli, en een getal van 64 bits in vier klokcycli. .
"Er waren twee of drie uitvoeringsfasen [in de ARM-processor]. Stel bijvoorbeeld dat ik register één vermenigvuldig met register twee en het resultaat in register drie plaats. Als ik wist dat register twee een 16-bits getal is in plaats van te zeggen: vermenigvuldig register één met register twee, zou ik zou het omdraaien en ik zou zeggen: vermenigvuldig register twee met register één, want dat zou me een klok besparen fiets."
Hij vertelde me dat de reden dat hij dit deed was om alle prestaties uit de Game Boy te persen Vooruit, aangezien een hier en daar opgeslagen klokcyclus echt optelt als er veel berekeningen worden uitgevoerd uitgevoerd. Wat betreft de zelfmodificerende code, ik vroeg Linden om deze uit te leggen.
"Het programma komt uit [storage], het brengt een groot blok van het programma over naar het interne RAM voor uitvoering omdat het sneller is. Elke RAM-toegang is veel, veel langzamer, dus ik voer een DMA [Direct Memory Access] uit van een groot blok van ROM naar RAM, en dan verander ik de daadwerkelijke programmacode. ARM heeft bijvoorbeeld de mogelijkheid om operanden naar links of rechts te verschuiven of het kan bepaalde bits maskeren als onderdeel van de instructieset. De instructie specificeert welke bits u gaat maskeren of met hoeveel bits u gaat verschuiven. Dus ik zou code genereren die zou wijzigen wat op het punt stond te worden uitgevoerd, op basis van het aantal bits dat ik moest verschuiven. Een ander voorbeeld betreft de vermenigvuldiging van de 3D-matrix. Er komen een hele hoop vermenigvuldigingen bij kijken. Ik zou de eigenlijke instructies die de vermenigvuldigingen uitvoeren in het interne RAM genereren en ze vervolgens uitvoeren, zodat de code een soort van delen van zichzelf bouwde terwijl deze werd uitgevoerd.
Zelfmodificerende code heeft zijn eigen nadelen, vooral als het gaat om het debuggen. Het elimineert ook de noodzaak voor vertakkingsinstructies, waarbij de code naar een andere uitvoeringsreeks zou springen en de hoofdlijn van kostbare rekentijd kan beroven. Linden vertelde ons ook dat de opzoektabellen perfect zijn uitgelijnd in het ROM, zodat ze een perfect veelvoud zijn van een acht-bits waarde die naar links is verschoven. De omvang van de opzoektabel is enorm en past niet in het RAM-geheugen, en de uitlijning vermijdt ook de noodzaak van een extra laadinstructie om het basisadres van de tabel te verkrijgen.
Alles bij elkaar is het uiteindelijke prototype in bijna twee jaar ontwikkeld.
De toekomst van de Quake-haven van Randy Linden
Ik vroeg Linden wat er zou gebeuren met de toekomst van de Quake-haven, en hij vertelde me dat hij dat deed overweging om ZeniMax en id Software te vragen de versie uit te brengen met de officiële Quake activa. Hij vertelde me ook dat hij op een gegeven moment de broncode zou vrijgeven, maar momenteel kan deze niet worden gebouwd omdat er een oudere computer voor nodig is.
Ik vroeg Linden waarom hij voor Quake koos, en hij vertelde me dat hij van het spel hield en dat hij van de uitdaging hield dat dit het "onmogelijke project" was, aangezien het buiten zijn DOOM voor SNES-port lag. Hij zei ook dat hoewel hij niet gelooft dat de hele game geporteerd had kunnen worden vanwege ruimtegebrek, het overgrote deel van de game in dezelfde engine had kunnen spelen.
Als je Quake voor de Game Boy Advance wilt uitproberen, bekijk dan zeker de release ervan op Forest of Illusion, die je hieronder kunt bekijken.
Downloaden van Forest of Illusion