Jak zaprogramowano gry oparte na kartridżach? [Zamknięte]

44

Myślę o SNES, N64, Atari ... chyba nawet o DS dzisiaj.

Gry SNES zwykle nie zajmowały więcej niż 4 MB miejsca, a gry N64 miały zwykle wartość od 32 do 64 MB.

Obecnie ledwo można skompilować „witaj świecie!” program bez wynikowej kompilacji generujący 1,21 gigabajta !! danych. (Żartując na bok, dzisiejsze pliki zajmują mnóstwo ton w porównaniu do niektórych technologii tamtych czasów.)

Więc ... jak oni to zrobili?

  • W czym zaprogramowali te gry? JAKO M? Cała sprawa w ASM ?!
  • Jak powstały grafiki? Jaką technologię musieli stworzyć arkusze sprite, a w niektórych przypadkach (np. N64) modele 3D?
  • Jak pasowały do ​​tak wielu poziomów, postaci, zadań i przedmiotów na tych wkładach? Mam na myśli, że Super Mario World na zegarze SNES ma około 1 MB i ma 96 wyjść! Ocarina of Time, Banjo-Kazooie, DK64 i kilka innych gier zajmują mniej niż 64 MB i miały ogromne światy, mnóstwo treści i modeli 3D!

Przepraszam, jeśli moje pytania wydają się trochę dziwne, jestem po prostu zaskoczony, że wiele świetnych tytułów udało się zmieścić w tak małej przestrzeni do przechowywania.

Jest to dla mnie fascynujące, ponieważ nawet najmniejsze i najbardziej trywialne pliki i gry zajmują co najmniej kilka MB, więc wyobrażanie sobie, że ogromne poziomy, takie jak w GoldenEye 007, nie zajmują prawie żadnych danych, jest oszałamiające.

Corey
źródło
1
Co się tyczy duplikatu, o którym wiem, że ludzie będą zwracać uwagę: najbardziej interesuje mnie sposób, w jaki rzeczywiste dane zostały wprowadzone do gier oraz sposób tworzenia ogromnych poziomów przy zachowaniu niewielkiego rozmiaru pliku - nie tyle procesu programowania i użytych narzędzi.
Corey,
1
NES (patrz Metroid Source na MDB) i SNES (kod źródłowy niektórych losowych gier firm trzecich jest dostępny w Internecie) używane ASM, N64 (ekran debugowania Zelda: MM wyświetla nazwę pliku w informacjach o awarii) używane C.
Ivo Wetzel,
Programowanie gier było bardzo ekspansywne w ciągu 8-bitowych dni. Na przykład zrobienie Pacmana kosztowało fortunę, gdy można ją dziś zrobić raczej tanio. Powodem jest to, że ograniczenia sprzętowe były bardziej ograniczające niż obecnie tysiąc razy (lub więcej). Oznaczało to, że w tych 8-bitowych grach musiałeś polegać na kodzie asemblera. Dzisiejsze gry są tak duże, że nie muszą być. Chodzi głównie o to, że mogą. Możesz przeczytać o prawie Wirtha.
wolfdawn
Tak, gry 8-bitowe często pisano w asemblerze. Gry SMS zostały stworzone z myślą o Z80, jest to dobrze znane. Kiedy piszesz w asemblerze, nadal możesz tworzyć przydatne biblioteki. Nie rozumiem, w jaki sposób utrzymanie kompaktowego kodu ma obecnie znaczenie dla rozwoju gier. To brzmi jak ktoś pytający, jak karmić i pielęgnować konie na nowoczesnym forum samochodowym. Jeśli napiszesz natywne instrukcje binarne, na maszynie w jednym celu, oczywiście możesz i prawdopodobnie utrzymasz zwarty kod. Jak bardzo może być rozdęty, gdy potrzebujesz kodu, aby uruchomić się z kilkoma megahercami. :)
wolfdawn

Odpowiedzi:

25

To zasoby graficzne i audio zajmują miejsce, wybór języka programowania polegał bardziej na tym, aby w pełni wykorzystać możliwości sprzętu.

Na przykładzie N64 większość gier innych firm miała 8, 12 lub 16 Mb. Gry 32 i 64Mb pochodziły głównie z Nintendo, ponieważ wysyłanie na wózkach tak dużych dla wszystkich było tak drogie. Brzmi to malutko, ale tak samo było z zasobami sztuki i ostatecznym efektem wizualnym. Musisz pamiętać, że większość gier N64 renderowanych w rozdzielczości 320x240, a nie 1280x760 lub więcej obecnie. Przy tak małej rozdzielczości wyjściowej tekstury i duszki były znacznie mniejsze niż obecnie.

Ze względu na niewielką pamięć podręczną tekstur na N64 większość tekstur miała 32 x 64 pikseli z paletą 4/8 bitów (czyli 16/256 kolorów). Dodatkowe szczegóły kolorów często wykonywano przez mieszanie tekstur i kolorów wierzchołków. Gry Banjo są tego dobrym przykładem.

Dzisiaj pojedynczy kamień w grze silnikowej Unreal będzie miał wiele 512 x 512 x 24 pb, a nawet 32 ​​pb. Dodatkowo zamiast tylko jednej rozproszonej tekstury masz teraz normalne mapy, maski zwierciadlane, maski do odbijania, mapy odbić i inne. Tak więc obiekt, który kiedyś miał 4Kb tekstur, jest teraz objęty kilkoma MB danych.

Stare gry mają również ogromne możliwości ponownego wykorzystania sztuki. Krzewy w Super Mario Bros. są tymi samymi duszkami co chmury, wzgórza są takie same jak grzyby. Różne postacie to tylko przesunięte kolorystycznie wersje tych samych zasobów artystycznych. Wszystko to zyskało więcej dzięki każdej tekstu lub ikonce, która była na wózku.

Audio to kolejna duża różnica w nowoczesnych grach. Prawie wszystko w dawnych czasach było robione z sekwencjami. Teraz zarówno ścieżki muzyczne, głos, jak i efekty dźwiękowe są przechowywane w różnych skompresowanych formatach audio. Chociaż z pewnością są mniejsze niż nieskompresowane dane, wciąż są znacznie większe niż ich sekwencyjne odpowiedniki.

wkerslake
źródło
8
Ach, kazirodztwo z krzakami / drzewami mario z logicznym wyjaśnieniem! Doskonały.
Kzqai,
10
Warto podkreślić, że wózki były często w rozmiarze mega bitów , nie mega bajtów . Te wózki o przepustowości 64 Mb miały tylko 8 MB.
dash-tom-bang
3
Wyjście nie było 320 x 240 w N64. Dane są niepoprawne. Większość gier prawdopodobnie używała 256 × 224. patrz tutaj
wolfdawn
13

Jeśli chodzi o NES (i przede wszystkim SNES), oto podstawowy przegląd. Nie pisałem żadnych gier NES, ale napisałem emulator NES (Graybox) i wykonałem sporo przeróbek starych kart.

Co do języka programowania: tak, to wszystko było asembler. Programowanie NES oznaczało bezpośrednią pracę z przerwaniami sprzętowymi, portami DMA, przełączaniem banków itp. Na szczęście programowanie 6502 (a raczej 2A03) jest dość łatwe [1]:

  • rejestrów jest niewiele: głównie A, X i Y, przy czym dwa ostatnie są przydatne tylko do indeksowania i iteracji
  • zestaw instrukcji jest mały i przeważnie prosty
  • mało pamięci: główna pamięć RAM to 2 KB, z opcjonalnym zasilanym bateryjnie rozszerzeniem 8 KB. Z tego 2 KB, 256 bajtów jest zarezerwowanych dla stosu, a strona 0 (pierwsze 256 bajtów) była miejscem, w którym chcesz przechowywać najczęściej używane wskaźniki i wartości ze względu na niektóre specjalne tryby adresowania

Te trzy rzeczy razem tworzą środowisko, które można łatwo zapamiętać podczas pracy z nim. Tak, sam zarządzasz całą pamięcią, ale to w zasadzie oznaczało, że stworzyłeś pełną mapę, gdzie wszystko idzie do przodu, a ta mapa nie jest bardzo duża, ponieważ musisz się martwić tylko o 2K, więc możesz wykreślić to na kawałku papier milimetrowy. Trzeba było zaplanować nieco więcej i statycznie przypisać zmienne i stałe do lokalizacji RAM i ROM (na kartridżu).

Robi się nieco trudniej, gdy dane naboju wykraczają poza adresowalne limity procesora. To 64 KB, z czego niższe 32 KB jest ustawione w kamieniu i odwzorowane na wszelkiego rodzaju porty sprzętowe i pamięć RAM. Tutaj zaczyna się przełączanie banków, co oznacza mapowanie części pamięci ROM na (część) wyższej przestrzeni adresowej 32 KB.

Można tego użyć, jak chce programista, ale przykładowym zastosowaniem może być gra z 3 poziomami, z wszystkimi danymi poziomu, metadanymi i kodem dla każdego poziomu wciśniętymi w osobne obszary pamięci 8 KB na kartridżu. Poziom może mieć wywołania zwrotne np. Inicjalizacji, aktualizacji ramki itp. „Ładowanie” poziomu oznaczałoby mapowanie tego fragmentu pamięci o wielkości 8 KB na np. 0xC000. Następnie można określić, że procedura inicjująca ma zawsze wartość 0xC000, procedura aktualizacji ramki ma wartość 0xC200, a dane poziomu zaczynają się od 0xC800. Główny kod gry mieści się w innym fragmencie pamięci, a następnie kontroluje zmiany poziomu, po prostu zamieniając odpowiedni fragment i przeskakując na adresy bezwzględne 0xC000 i 0xC200 w odpowiednich momentach.

Zapis danych graficznych: dane kafelków NES to 2-bitowe mapy 8 x 8 pikseli. Jako tło łączy się je z 2-bitową warstwą o rozdzielczości 1/4. Te 4-bitowe wartości zostały następnie zindeksowane do 16-wejściowej palety, przy czym uważam, że dostępnych jest 53 skuteczne unikalne kolory. Duszki również używały 2-bitowych danych pikselowych, a każdy duszek określał swój własny 2-bitowy indeks grupy, ponownie tworząc 4-bitowy indeks pal. Obraz BG na ekranie to tablica 32x30 numerów indeksów kafelków.

Zasadniczo, mając mnóstwo powtórzeń i indeksy do indeksów, możesz utrzymać dane bardzo małe. Dane o poziomie często były przechowywane jako pionowe słupki indeksów płytek, a ponieważ te pionowe słupki również zostały ponownie wykorzystane, zostały one również zindeksowane i zapisane tylko raz na kartridżu. Proste techniki kompresji danych działają podobnie. To pozwoliło Mario 1 na 32 KB danych (z miejscem na zapas) i 8 KB danych bitmapowych.

Jeśli chodzi o środowiska deweloperskie, widziałem kilka zdjęć, na których ludzie pracowali na niektórych certyfikowanych komputerach podłączonych do nagrywarki EEPROM do pracy. Debugowanie wspomagane narzędziami nie było tak naprawdę możliwe aż do wieku SNES [2]. Jest to główny powód, dla którego tak wiele starych gier ma „oczywiste” błędy i dlaczego rzeczy takie jak Gameshark mogą robić to, co robią; zdrowie gracza zawsze znajdowałoby się w miejscu pamięci X, więc możesz zmusić go do 100.

Jeśli uznasz te rzeczy za interesujące, zachęcam do zapoznania się np. Z http://wiki.nesdev.com/w/index.php/Nesdev_Wiki Istnieje wiele kursów programowania dla NES, które można znaleźć również w Internecie.

Mam nadzieję, że ten uproszczony przegląd dał wgląd w rozwój gier z lat 80-tych.

[1] Względnie mówiąc. Jestem również stronniczy, gdy napisałem sam Graybox w około 85% zestawie PowerPC. [2] Zobacz artykuł na temat tworzenia FF6: http://www.edge-online.com/features/the-making-of-final-fantasy-vi/

zenmumbler
źródło
3

W prawie wszystkich zadawanych pytaniach jest wiele podtematów. Optymalizacja jest ogromnym obszarem samym w sobie i jest wiele rzeczy do odkrycia.

Jeśli jesteś zainteresowany tego rodzaju optymalizacją, jedną z rzeczy, które możesz zbadać, jest demoscena . Demoscena i niektóre z powiązanych kultur artystycznych od dawna zachowują zdumienie próbą stworzenia skomplikowanej sztuki na komputery, które zajmują jak najmniej miejsca. Wielu z nich będzie miało informacje o tym, jak wykonali niektóre lub wszystkie swoje „sztuczki”.

Często istnieje pomysłowa mieszanka zdrowego rozsądku, chociaż istnieją „sztuczki” i „hacki” specyficzne dla gry lub gatunku. Często wiąże się to z odrobiną „szczęścia” i zespołem znającym granice, nad którymi pracują (być może nieustannie dąży do osiągnięcia tych limitów przez cały proces), znając dostępne kompromisy i chętnie dokonując niezbędnych transakcji -offs i poświęcenia, aby przekroczyć swoje granice.

Oto niektóre z rzeczy, które mogę wymyślić, które mogą pomóc zespołowi w grze w mniejszych rozmiarach:

  • Ponownie wykorzystaj to, co możesz: ponowne użycie tych samych ikonek, a odmiany, które możesz łatwo zrobić z jednego obrazu ikonki (takie jak odbicia, obroty, przesunięcia palety) zaoszczędzą ci miejsca. To samo dotyczy kodu, muzyki i prawie wszystkiego innego w grze.
  • Kompresuj to, co możesz: istnieje wiele schematów kompresji, a wiedza o tym, które z nich mogą być bardzo oszczędne. Nawet czasami proste schematy kompresji, takie jak kodowanie długości przebiegu, mogą zaskoczyć. Ponadto istnieją schematy kompresji (i alternatywne formaty, które nie są dokładnie kompresjami) dla poszczególnych typów plików, często z kompromisami jakościowymi. Na przykład pliki audio Wave / CD można skompresować, z niewielką utratą informacji, do plików MP3. Ponadto formaty plików, takie jak MIDI i MOD oparty na samplerach, to alternatywne formaty, które zajmują o wiele mniej miejsca, ale kodują muzykę zupełnie inaczej i wymagają różnych umiejętności, aby brzmiały dobrze.
  • Stracić to, czego nie potrzebujesz: czy możesz to zrobić taniej? Na przykład, czy nadal można uzyskać „osobowość” postaci w mniejszej liczbie pikseli (lub wielokątów)? Czy rozmieszczenie kafelków musi być dokładnie określone przez projektanta, czy też mogą być generowane losowo w kodzie programu?
  • Kod jest często tańszy: chociaż żartowałeś o tym, ile miejsca kompilacja kodu zwykle zajmuje teraz pomysły (i istnieją powody, dla których ta „platforma” wzrosła przez lata i sposoby, aby ją zmniejszyć, gdy jest to absolutnie konieczne), ale ogólnie rzecz biorąc, jeśli możesz łatwo zrobić coś algorytmicznie / proceduralnie / w kodzie, to podejście będzie również łatwiejsze do poprawienia i ponownego wykorzystania dla innych podobnych, ale różniących się zasobów / wrażeń. Fraktale są szczególnie łatwym do zobaczenia przykładem: możesz mieć obraz skomplikowanego fraktala, który zajmuje dużo miejsca w porównaniu do wzoru matematycznego, który go generuje. Wzór matematyczny może dodatkowo mieć parametry, które mogą generować podobne, ale czasem zaskakująco różne obrazy.

W każdym razie, przy tak dużym, załadowanym zestawie pytań, mam nadzieję, że niektóre z powyższych tematów będą dobrym punktem wyjścia, aby dowiedzieć się więcej.

WorldMaker
źródło
Użyj także technologii, która zajmuje mniej miejsca.
ścigający
3
(przepraszam, wprowadź ponownie problem ... istnieje sposób, aby go wyłączyć? Nienawidzę tego za każdym razem, gdy naciskam, wpisz komentarz).
ścigający
Kolejny wpis: / W każdym razie skorzystaj z technologii, która zajmuje mniej miejsca, jak na przykład mapy proceduralne (Noctis ma całą galaktykę z kilkoma milionami układów słonecznych, z planetami, które możesz wylądować i zobaczyć życie, drzewa, ruiny, budynki ... w mniej niż 3 MB ), modułowa muzyka (muzyka w formatach takich jak .mod, .xm, .it ...), tekstury proceduralne (patrz werkkzeug, mapzone i inne oprogramowanie), proceduralne efekty dźwiękowe (prawie każdy efekt dźwiękowy można uzyskać z matematyki równania lub manipulowanie podstawowymi falami dźwiękowymi) i tak dalej.
ścigający
@speeder łatwo kliknąć „edytuj” lub „usuń” w przypadkowych komentarzach ...
dash-tom-bang
Re: „Kompresuj, co możesz” na starym sprzęcie, który zwykle kompresujesz do tego, co sprzęt może obsłużyć. Nigdy nie skompresowałbyś dźwięku do formatu MP3, ponieważ sprzęt audio nie obsługiwał go natywnie i nie chciałbyś tracić czasu na dekompresję go na procesorze, gdy możesz po prostu przesłać go strumieniowo z nośnika do sprzętu audio. MIDI było świetne, ponieważ każdy miał (i ma) syntezator falowy na pokładzie; wystarczy załadować próbki i gotowe.
dash-tom-bang
0

Jedno nie jest pewne, czy nadal stoi w erze po epoce N64, ale SNES i N64 często ponownie wykorzystywały tekstury na innych obiektach 3D, które często oszczędzają dużo miejsca i wstępnie renderowane grafiki, których tła są często fałszywe. Inną sztuczką było stworzenie mgły tła granicznego.

San Francisco Rush N64 zawsze miało trochę mgły, chociaż ustawienia mogły zmienić gęstość tam, gdzie arkada San Francisco Rush nie miała żadnej, i można było zobaczyć Golden Gate Bridge na torze 1 w porównaniu do wersji N64.

Również gry często ponownie wykorzystują muzykę, taką jak Zelda Ocarina of Time, i bardzo mnie to denerwuje, ponieważ można było wykonać lepszą pracę, na przykład w jaki sposób Banjo Kazooie / DK64 często zawierał motywy tematyczne!

Zelda Ocarina czasu mogłaby mieć Hyrule Overworld, a następnie podwodną wersję motywu, jeśli pójdziesz pod wodę lub sprawisz, że instrumenty w sklepie Theme odzwierciedlają obszar zewnętrzny, gdzie flety i skrzypce byłyby używane w sklepie Kokiri Forest, rogi i trąbki do sklepu Hyrule Castle Town i bębny w wiosce Goron. etc

W komputerach PC moduły 3D są kompilowane do bibliotek, aby szybko uzyskać do nich dostęp za pomocą programu do rozpakowania go, ale nie jestem pewien, czy tak jest w przypadku Nintendo opartego na pamięci ROM. Komputery PC są RAM-em jak wejście do nieuporządkowanego pokoju, w którym rzeczy nie zawsze pozostają tam, gdzie powinny, a informacje mogą zostać zastąpione do tego stopnia, że ​​komputer nawet się nie uruchomi!

Konsole do gier to ROM, w którym wszystko jest przechowywane w wyznaczonym miejscu, więc za każdym razem, gdy włączysz grę, będzie ona szukać plików w tym przydzielonym miejscu z gwarancją, że tam pozostanie.

Duży
źródło