Przeniesienie Quake'a na Game Boy Advance wydawało się niemożliwe, ale Randy'emu Lindenowi udało się tego dokonać. Oto jak.
Game Boy Advance to przenośna konsola do gier stworzona przez firmę Nintendo. Został wydany w Japonii w 2001 roku i był następcą Game Boy Color. Miał ARM7TDMI taktowany zegarem 16,78 MHz, 32 kb wewnętrznej roboczej pamięci RAM, 256 kb zewnętrznej pamięci RAM i 96 kb pamięci VRAM. Nie jest to najpotężniejsza maszyna, ale jest mnóstwo gier na urządzenia kieszonkowe, które wiele osób zapada w pamięć. Jedną z gier, która nigdy nie ujrzała światła dziennego na to urządzenie, był prototypowy port Quake, gry opracowanej przez id Software, która pomogła zdefiniować gatunek strzelanek pierwszoosobowych, jaki znamy dzisiaj.
Quake to niezwykle szczegółowa gra z fantastyczną ścieżką dźwiękową i wciągającą rozgrywką, i podobnie jak DOOM, została przeniesiona na praktycznie każde urządzenie, jakie tylko przyjdzie Ci do głowy. Jego port na Game Boy Advance jest szczególnie niesamowity, ponieważ nie obsługuje natywnie grafiki 3D, a Nintendo specjalnie promowało urządzenie przenośne jako dwuwymiarowe doświadczenie rozgrywki. Nie powstrzymało to jednak Randy'ego Lindena przed opracowaniem własnego portu.
Jeśli nie znasz Lindena, jest on najbardziej znany z tego, że jest twórcą obu bleemów! (emulator PlayStation) i port DOOM-a na SNES, osiągnięcie, które John Romero, współzałożyciel id Software, powiedział kiedyś w wywiadzie dla Wiadomości z Shacknews nie sądził, że to możliwe. Biegłość Lindena w programowaniu udowodniła, że jeśli ktokolwiek miałby urzeczywistnić Quake na Game Boy Advance, to prawdopodobnie on.
Port ten wyszedł na światło dzienne dzięki udostępnieniu go przez Linden w ramach projektu Forest of Illusion. Forest of Illusion to projekt mający na celu zachowanie historii gier Nintendo i Linden skontaktował się z nami, aby rozpowszechnić kopię portu Quake, którą znalazł na swojej karcie flash o pojemności 256 MB posiadanie.
Chcielibyśmy podziękować Randy'emu Lindenowi za poświęcenie czasu na udzielenie odpowiedzi na nasze pytania i zapewnienie technicznej poprawności tego artykułu. Chcielibyśmy również podziękować Nowoczesny gracz w stylu vintage za umożliwienie nam wykorzystania potrzebnych zdjęć z jego filmu. Port ten nie ma oficjalnego związku z id Software ani ZeniMax i został opracowany jako solowy projekt Lindena.
Port Quake Game Boy Advance
Technicznie rzecz biorąc, to cud, że Quake może w ogóle osiągnąć taki poziom, jak na Game Boy Advance. Działa z dobrą liczbą klatek na sekundę i zachowuje prawidłowe oświetlenie i paletę kolorów oryginalnej gry Quake. Wszystko jest 3D, łącznie z bronią i potworami. Gry na Game Boy Advance osiągały grafikę 3D zazwyczaj za pomocą ikonek, ale to była prawdziwa okazja. Nie wykorzystuje rzucania promieni w sposób, w jaki robiły to inne gry 3D na urządzeniu przenośnym, a nawet osiąga cel efekty świetlne na wstępnie renderowanych obiektach za pomocą sztuczki polegającej na zmianie palety, aby uzyskać iluzję dynamiki oświetlenie.
Żeby było jasne, ten port nie jest pełną grą, ale prototypem, który Linden miał zamiar przekazać id Software po jego ukończeniu i przygotowaniu do wydania. Jednak popularność Game Boy Advance zaczęła słabnąć, a zamiast tego niestandardowy silnik napisany przez Lindena stał się później silnikiem innej gry opracowanej w całości przez Lindena – Cyboid. Linden mówi nam, że „duża część kodu” to nadal oryginalny kod ARM z wersji Game Boy Advance. Jeśli chcesz wypróbować Cyboid, starsza wersja jest dostępna w sklepie Google Play, ale oficjalny pakiet APK jest teraz dystrybuowany na Sklep z aplikacjami Amazona ponieważ gra zawiera dużo 32-bitowego kodu niskiego poziomu.
Cena: za darmo.
3.3.
Linden udostępnił nam także film przedstawiający jego kod działający na iPod Video, który był jedną z najwcześniejszych wersji Cyboida. Został zbudowany na tym samym kodzie silnika, który został użyty w jego przeniesieniu Quake na Game Boy Advance.
Port Quake na Game Boy Advance nie zawiera żadnych oficjalnych zasobów gry, podobnie jak Linden skontaktował się z firmą id Software lub ZeniMax w sprawie dystrybucji wersji E1M1 zawierającej oficjalny Quake aktywa.
Obecnie dystrybuowana gra jest także wersją debugującą. Przytrzymanie klawisza R podczas uruchamiania przeniesie gracza bezpośrednio do drugiej mapy gry, a przytrzymanie lewego przycisku na padzie kierunkowym przeniesie go na trzecią. Zamiana map jest dostępna również po śmierci gracza, a potwory nie zaatakują gracza, dopóki gracz nie strzeli do nich pierwszy.
Jeśli chodzi o muzykę, demo korzysta z publicznych plików .S3M, a mikser dźwięku obsługuje zarówno muzykę stereo, jak i efekty dźwiękowe.
Granice techniczne
Jeśli chodzi o Game Boy Advance, istniało wiele granic, które utrudniały ten port. Do największych przeszkód należała niska częstotliwość taktowania, brak możliwości grafiki 3D w urządzeniu kieszonkowym oraz brak jednostki zmiennoprzecinkowej (FPU). Po drodze było mnóstwo innych, ale te szczególne punkty, które Linden określiła jako problematyczne, uznałem za szczególnie problematyczne. Zanim do tego przejdziemy, ważne jest, aby zrozumieć układ Game Boy Advance.
Game Boy Advance ma trzy zestawy pamięci RAM - jeden to wewnętrzna robocza pamięć RAM (IWRAM), drugi to zewnętrzna robocza pamięć RAM (EWRAM), a trzeci to wideo RAM (VRAM). 32 kb pamięci IWRAM służy do przechowywania instrukcji ARM w celu szybkiego wykonania, podczas gdy 256 kb pamięci EWRAM jest optymalne do przechowywania instrukcji Thumb-only i mniejszych fragmentów danych. Jak – zauważa Rodrigo CopettiDostęp do pamięci EWRAM może być nawet sześciokrotnie wolniejszy niż w przypadku pamięci IWRAM. Większość pamięci w postaci EWRAM jest dostępna tylko za pośrednictwem 16-bitowej magistrali, mimo że Game Boy Advance jest sprzedawany jako 32-bitowy komputer przenośny. Dostęp do IWRAM można uzyskać poprzez 32-bitową magistralę. Pamięć VRAM w Game Boy Advance ma 96 KB i chociaż służy głównie do przechowywania danych graficznych, znajduje się na mapie pamięci procesora i może być również używana jako zwykła pamięć masowa.
Instrukcje kciukowe stanowią podzbiór 32-bitowych instrukcji ARM i są zbiorem instrukcji zakodowanych w 16-bitowych słowach. Posiadają wszystkie zalety instrukcji 32-bitowych, a jednocześnie nie zajmują dużo miejsca, co czyni je wydajnymi i zoptymalizowanymi pod kątem programowania. Oznacza to, że chociaż dostęp do pamięci EWRAM jest wolniejszy, wydajne instrukcje Thumb mogą często kończyć się tak samo szybko, jak przechowywane instrukcje ARM w IWRAM, chociaż wadą instrukcji Thumb jest to, że czasami nie ma odpowiedniego odpowiednika Thumb instrukcji ARM, którą chcesz wykonać wykonać. Pamięć EWRAM została wykorzystana do przechowywania danych wyjściowych logiki transformacji matematycznej 3D, która była w zasadzie listą krawędzi wielokątów, które następnie były śledzone linia po linii skanowania przez kod rasteryzacji.
Jak powiedział mi Linden, najbardziej złożoną i najtrudniejszą częścią całego portu był moduł renderujący linię skanowania. Składa się z ponad 10 000 linii wysoce zoptymalizowanego kodu asemblera ARM, który ma na celu narysowanie zestawu pikseli do pamięci VRAM. Moduł renderujący Scanline zużył większość 32kb IWRAM-u. Krawędzie najbliżej kamery są aktywne i renderowane, a zasadniczo jest to duże drzewo partycjonowania przestrzeni binarnej (BSP). VRAM został użyty do przechowywania wyników transformacji wielokątnej w tabelach brzegowych, ponieważ nie było wystarczającej ilości IWRAM, ale VRAM w Game Boy Advance jest wciąż szybszy niż EWRAM. Tutaj również przechowywano i wyświetlano grafiki.
Dużo czasu spędził skupiając się na optymalizacjach, aby zapewnić możliwie najszybszy czas wykonania. Trzy rzeczy, które zrobił, aby przyspieszyć czas realizacji, obejmowały:
- Samodzielnie zmodyfikował kod przed jego wykonaniem, więc wymaganych było mniej instrukcji
- Użyłem szeregu tabel przeglądowych dla takich rzeczy, jak odwrotność, sinus, cosinus, tangens itp.
- Przełączono „tryb” procesora, aby uzyskać dostęp do dodatkowych rejestrów (które są jak „zmienne”) bez konieczności zapisywania i przywracania wartości rejestrów.
Przełączanie trybów procesora w celu uzyskania dodatkowych rejestrów to niezwykle sprytny manewr, który umożliwia szybki dostęp do wartości bliskich procesorowi, dzięki czemu można je odzyskać w jednym cyklu zegara. Jak powiedział mi Linden, możliwa była zamiana rejestrów i odzyskanie wartości w jednym cyklu zegara, w przeciwieństwie do przechowywania wartości w pamięci RAM Game Boy Advance, co trwa dłużej. Sam procesor jest procesorem 16,78 MHz, co oznacza, że może wykonać 16780000 cykli na sekundę. To wydaje się dużo, ale gdy trzeba obliczyć i narysować każdy piksel na ekranie, szybko się to sumuje i ważne staje się ograniczenie jak największej liczby operacji.
Powyżej znajduje się lista ogólnych rejestrów chipsetu ARM7TDMI znajdującego się w Game Boy Advance. Zazwyczaj programiści uzyskiwaliby dostęp do rejestrów tylko w trybie „System i użytkownik”, a poza tym uciekaliby się do używania normalnych zmiennych. Jednakże wykorzystał rejestry we wszystkich siedmiu trybach chipsetu i właśnie to jest najlepsze tryby przełączania nadal zachowują wartości w rejestrach innych trybów, więc mógł się przełączać ich.
Co zabawne, Linden wspomniał również, że jego metoda zmiany banku odkryła błąd w emulatorze Nanoboy Advance. Jak się okazało, emulator ten nie obsługiwał innych trybów procesora do zapisywania w rejestrach i przełączania, a jego demo Quake'a było pierwszą znaną grą, która faktycznie to robiła.
Linden udostępnił nam zdjęcie niektórych utworzonych przez siebie notatek i wyjaśnił, w jaki sposób zoptymalizował obliczenia zmiennoprzecinkowe przy braku odpowiedniego FPU.
Powyższy obraz to ten, który Linden udostępnił nam na podstawie swoich notatek, a szczególnie interesujący jest „różne zliczanie instrukcji cyklu ARM”. Opracował sposób optymalizacji cykli obliczeń, aby móc zmniejszyć liczbę cykli zegara do obliczeń. Jak mi to opisał, liczbę 8-bitową można pomnożyć w jednym cyklu zegara, liczbę 16-bitową w dwóch cyklach zegara, liczbę 32-bitową w trzech cyklach zegara, a liczbę 64-bitową w czterech cyklach zegara .
„Były dwa lub trzy etapy wykonania [w procesorze ARM]. Powiedzmy na przykład, że mnożę rejestr jeden przez rejestr drugi i umieszczam wynik w rejestrze trzecim. Gdybym wiedział, że rejestr drugi jest liczbą 16-bitową, zamiast mówić: pomnóż rejestr jeden przez rejestr dwa, zrobiłbym to odwróciłbym to i powiedziałbym, że pomnóż rejestr dwa przez rejestr jeden, ponieważ zaoszczędziłoby mi to zegara cykl."
Powiedział mi, że zrobił to, aby wycisnąć z Game Boya jak najwięcej wydajności Zaawansowane, ponieważ cykl zegara zapisany tu i tam naprawdę się sumuje, gdy wykonywanych jest wiele obliczeń wykonane. Jeśli chodzi o samomodyfikujący się kod, poprosiłem Lindena o wyjaśnienie.
„Program pochodzi z [storage], przenosi duży blok programu do wewnętrznej pamięci RAM w celu wykonania, ponieważ jest szybszy. Każdy dostęp do pamięci RAM jest znacznie, znacznie wolniejszy, więc wykonuję DMA [bezpośredni dostęp do pamięci] dużego bloku z pamięci ROM do pamięci RAM, a następnie zmieniam rzeczywisty kod programu. Na przykład ARM ma możliwość przesuwania operandów w lewo lub w prawo lub może maskować pewne bity jako część zestawu instrukcji. Instrukcja określa, które bity zamierzasz maskować lub o ile bitów zamierzasz przesunąć. Wygenerowałem więc kod, który zmodyfikowałby to, co właśnie miało zostać wykonane, w oparciu o liczbę bitów, które musiałem przesunąć. Innym przykładem jest mnożenie macierzy 3D. Jest tam cała masa mnożeń. Wygenerowałbym rzeczywiste instrukcje wykonujące mnożenie do wewnętrznej pamięci RAM, a następnie wykonałbym je, tak aby kod w pewnym sensie zbudował swoje fragmenty podczas działania.
Samomodyfikujący się kod ma swoje wady, szczególnie jeśli chodzi o debugowanie. Eliminuje to również potrzebę stosowania instrukcji rozgałęzień, w których kod przeskakiwałby do innej sekwencji wykonawczej i mógłby pozbawić główny wątek cennego czasu obliczeniowego. Linden powiedziała nam również, że tablice przeglądowe są idealnie dopasowane w pamięci ROM, tak że stanowią doskonałą wielokrotność wartości ośmiobitowej przesuniętej w lewo. Rozmiar tabeli przeglądowej jest ogromny i nie mieści się w pamięci RAM, a wyrównanie pozwala również uniknąć konieczności stosowania dodatkowej instrukcji ładowania w celu uzyskania adresu podstawowego tabeli.
W sumie ostateczny prototyp powstawał przez prawie dwa lata.
Przyszłość portu Quake Randy'ego Lindena
Zapytałem Lindena, co stanie się z przyszłością portu Quake, a on odpowiedział, że stawia rozważ zwrócenie się do ZeniMax i id Software o wydanie wersji z oficjalnym Quake'iem aktywa. Powiedział mi również, że w pewnym momencie udostępni kod źródłowy, ale obecnie nie można go skompilować, ponieważ wymaga starszego komputera.
Zapytałem Lindena, dlaczego wybrał Quake'a, a on powiedział mi, że uwielbia tę grę i podobało mu się wyzwanie, jakim jest „niemożliwy projekt”, ponieważ powstał z tyłu jego portu DOOM na SNES. Wspomniał również, że chociaż nie wierzy, że cała gra mogła zostać przeniesiona ze względu na ograniczenia przestrzenne, zdecydowana większość gry mogła być oparta na tym samym silniku.
Jeśli jesteś zainteresowany grą Quake na Game Boy Advance, koniecznie sprawdź premierę gry w Forest of Illusion, którą możesz sprawdzić poniżej.
Pobierz z Forest of Illusion