¿Cómo se programaron los juegos basados ​​en cartuchos? [cerrado]

44

Estoy pensando en el SNES, N64, Atari ... incluso el DS de hoy, supongo.

Los juegos de SNES generalmente no ocupaban más de 4 MB de espacio, y los juegos de N64 generalmente tenían un valor de 32 a 64 MB de datos.

En estos días, apenas puedes compilar un "¡Hola mundo!" programa sin la compilación resultante que genera 1.21 gigabytes !! de datos. (Bromas aparte, los archivos de hoy ocupan toneladas y toneladas de espacio en comparación con parte de la tecnología en ese momento).

Entonces ... ¿cómo lo hicieron?

  • ¿En qué programaron estos juegos? ASM? ¡¿Todo en ASM ?!
  • ¿Cómo se crearon los gráficos? ¿Qué tecnología tuvieron para crear hojas de sprites y, en algunos casos (como el N64), modelos 3D?
  • ¿Cómo encajaron tantos niveles, personajes, misiones y artículos en estos cartuchos? Quiero decir, Super Mario World en los relojes SNES en alrededor de 1 MB, ¡y tiene 96 salidas! ¡Ocarina of Time, Banjo-Kazooie, DK64 y algunos otros juegos ocupan menos de 64 MB y tenían mundos enormes, toneladas de contenido y modelos 3D!

Perdón si mis preguntas parecen un poco extrañas, estoy sorprendido de que muchos de los grandes títulos lograron encajar en un espacio de almacenamiento tan pequeño.

Es fascinante para mí porque incluso los archivos y juegos más pequeños y triviales logran ocupar al menos unos pocos MB, por lo que imaginar que enormes niveles como los de GoldenEye 007 lograron tomar casi ningún dato es alucinante.

Corey
fuente
1
Además, con respecto al duplicado que sé que la gente señalará: estoy principalmente interesado en cómo se introdujeron los datos reales en los juegos y cómo se crearon niveles enormes mientras se conservaba un tamaño de archivo pequeño, no tanto el proceso de desarrollo y las herramientas utilizadas.
Corey
1
NES (ver Metroid Source en MDB) y SNES (el código fuente de algunos juegos aleatorios de terceros están disponibles en la web) utilizaron ASM, N64 (Zelda: la pantalla de depuración de MM muestra el nombre del archivo en la información del bloqueo) utilizó C.
Ivo Wetzel
La programación del juego fue muy expansiva en los días de 8 bits. Por ejemplo, hacer que Pacman cueste una fortuna cuando podría hacerse hoy de forma bastante barata. Las razones son que las restricciones del hardware eran más limitantes de lo que son hoy en miles de veces (o más). Eso significaba que tenía que confiar en el código de ensamblador para estos juegos de 8 bits. La razón por la que los juegos de hoy son tan grandes no es que deban serlo. Es principalmente que pueden ser. Podrías leer sobre la ley de Wirth.
wolfdawn
Sí, los juegos de 8 bits a menudo se escribían en ensamblador. Los juegos de SMS se hicieron con un Z80 en mente, esto es bien conocido. Cuando escribe en ensamblado, aún puede crear bibliotecas útiles. No veo cómo mantener el código compacto es relevante para el desarrollo de juegos hoy en día. Parece que alguien pregunta cómo alimentar y preparar caballos en un foro de automóviles modernos. Si escribe instrucciones binarias nativas, en una máquina con un propósito, por supuesto, puede y probablemente mantendrá el código compacto. Qué tan hinchado puede ser cuando necesita que su código se ejecute a unos pocos megahercios. :)
wolfdawn

Respuestas:

25

Son los recursos de arte y audio los que ocupan espacio, la elección del lenguaje de programación fue más acerca de sacar el máximo provecho del hardware.

Usando N64 como ejemplo, la mayoría de los juegos de terceros fueron 8, 12 o 16Mb. Los juegos de 32 y 64 Mb eran en su mayoría de Nintendo, ya que era muy costoso enviarlos en carros tan grandes para todos los demás. Eso suena pequeño, pero también lo fueron los activos artísticos y la salida visual final. Debes recordar que la mayoría de los juegos de N64 se renderizan a 320x240, no a los 1280x760 o más de hoy. Con una resolución de salida tan pequeña, las texturas y los sprites eran mucho más pequeños de lo que son hoy.

Debido a la pequeña caché de texturas en el N64, la mayoría de las texturas eran de 32x64 píxeles con una paleta de 4/8 bits (también conocido como 16/256 colores). Los detalles de color adicionales a menudo se realizaban mezclando texturas y colores de vértice. Los juegos de Banjo son un buen ejemplo de esto.

Hoy, una sola roca en un juego de motor Unreal tendrá múltiples 512x512x24bpp o incluso 32bpp. Además, en lugar de solo una textura difusa, ahora tiene mapas normales, máscaras especulares, máscaras de reflexión, mapas de cubos de reflexión y más. Entonces, un objeto que solía tener 4Kb de texturas ahora está cubierto en varios MB de datos.

Los juegos antiguos también tienen una gran cantidad de reutilización del arte. Los arbustos en Super Mario Bros. son los mismos sprites que las nubes, las colinas son las mismas que los hongos. Los diferentes personajes son solo versiones de los mismos recursos de arte con cambio de color. Todo esto obtuvo más uso de cada textura o sprite que estaba en el carrito.

El audio es otra gran diferencia para los juegos modernos. Casi todo en los viejos tiempos se hacía con pistas secuenciadas. Ahora ambas pistas de música, voz y efectos de sonido se almacenan en varios formatos de audio comprimido. Aunque ciertamente son más pequeños que los datos sin comprimir, siguen siendo significativamente más grandes que sus equivalentes secuenciados.

wkerslake
fuente
8
Ah, el mario arbustos / árboles incesto con una explicación lógica! Excelente.
Kzqai
10
Vale la pena señalar que los carros a menudo tenían un tamaño de mega bits , no mega bytes . Esos carros de 64Mb tenían solo 8MB.
dash-tom-bang
3
La salida no era 320 x 240 en N64. Los detalles son incorrectos. La mayoría de los juegos probablemente estaban usando 256 × 224. ver aquí
wolfdawn
13

En cuanto a NES (y SNES también en su mayoría), aquí hay una descripción básica. No escribí ningún juego de NES, pero escribí un emulador de NES (Graybox) e hice una buena cantidad de ingeniería de rev de carros viejos.

En cuanto al lenguaje de programación: sí, todo fue ensamblado. Programar el NES significaba trabajar directamente con interrupciones de hardware, puertos DMA, conmutación de bancos, etc. Afortunadamente, programar el 6502 (o más bien, el 2A03) es bastante fácil [1]:

  • hay pocos registros: A, X e Y principalmente, los dos últimos solo se pueden usar para indexar e iterar
  • el conjunto de instrucciones es pequeño y sobre todo sencillo
  • no hay mucha memoria: la RAM principal es de 2 KB, con una extensión opcional de 8 KB respaldada por batería. De esos 2 KB, 256 bytes están reservados para la pila y la página 0 (los primeros 256 bytes) era donde querría almacenar sus punteros y valores más utilizados debido a algunos modos de direccionamiento especiales

Estas 3 cosas juntas crean un entorno que es lo suficientemente fácil de memorizar mientras se trabaja con él. Sí, administras toda la memoria tú mismo, pero eso significa esencialmente que creas un mapa completo de dónde va todo adelante y ese mapa no es muy grande porque solo tienes que preocuparte por 2K, por lo que puedes trazar eso en un pedazo de papel cuadriculado. Debía planificar las cosas un poco más y asignar estáticamente variables y constantes a las ubicaciones de RAM y ROM (en el cartucho).

Se vuelve un poco más complicado una vez que los datos de su cartucho superan los límites direccionables de la CPU. Eso es 64 KB, de los cuales los 32 KB más bajos se establecen en piedra y se asignan a todo tipo de puertos de hardware y RAM. Aquí es donde entra en juego el cambio de banco, lo que significa mapear una sección de la ROM en (parte de) el mayor espacio de direcciones de 32 KB.

Esto se puede usar como quiera el programador, pero un ejemplo de uso podría ser tener un juego con 3 niveles, con todos los datos de nivel, metadatos y código para cada nivel agrupados en áreas de memoria de 8 KB en el cartucho. El nivel puede tener devoluciones de llamada para, por ejemplo, inicialización, actualización por trama, etc. "Cargar" el nivel significaría asignar esa porción de memoria de 8 KB a, por ejemplo, 0xC000. A continuación, puede especificar que la rutina de inicio siempre está en 0xC000, la rutina de actualización de trama está en 0xC200 y los datos de nivel comienzan en 0xC800. El código principal del juego alojado en otro fragmento de memoria controla los cambios de nivel simplemente intercambiando el fragmento correcto y saltando a las direcciones absolutas 0xC000 y 0xC200 en los momentos apropiados.

Datos gráficos de Wrt: los datos de mosaicos de NES son mapas de 2 bits de 8x8 píxeles. Para el fondo, se combinan con una capa de 2 bits con resolución de 1/4. Estos valores de 4 bits se indexaron en una paleta de 16 entradas, con 53 colores únicos efectivos disponibles. Los sprites también usaron los datos de píxeles de 2 bits y cada sprite especificó su propio índice de grupo de 2 bits nuevamente formando un índice de pal de 4 bits. La imagen BG en pantalla es una matriz de 32x30 de números de índice de mosaico.

Esencialmente, al tener una tonelada de repetición e índices en índices, puede mantener los datos muy pequeños. Los datos de nivel a menudo se almacenaban como barras verticales de índices de mosaico y debido a que esas barras verticales también se reutilizaban, también se indexaban y solo se almacenaban una vez en el cartucho. Las técnicas simples de compresión de datos funcionan de manera similar. Esto permitió que Mario 1 tuviera 32 KB de datos (con espacio libre) y 8 KB de datos de mapa de bits.

En cuanto a los entornos de desarrollo, he visto algunas fotos en las que la gente trabajaba en algunas computadoras antiguas certificables conectadas a quemadores EEPROM para trabajar. La depuración asistida por herramientas no era realmente una posibilidad hasta después de la edad de SNES [2]. Esta es la razón principal por la que muchos juegos antiguos tienen errores "obvios" y por qué cosas como Gameshark podrían hacer lo que hacen; la salud del jugador siempre estará en la ubicación X de la memoria, por lo que puedes forzarla a que sea 100 en todo momento.

Si encuentra estas cosas interesantes, le animo a que consulte, por ejemplo, http://wiki.nesdev.com/w/index.php/Nesdev_Wiki. También hay bastantes cursos de programación para NES en línea.

Espero que esta descripción simplificada haya dado una idea del desarrollo de juegos de la era de los 80.

[1] Relativamente hablando. También soy parcial ya que escribí Graybox en sí mismo en un 85% de ensamblaje PowerPC. [2] Vea la elaboración del artículo FF6: http://www.edge-online.com/features/the-making-of-final-fantasy-vi/

zenmumbler
fuente
3

Hay muchos subtemas en casi todas las preguntas que hace. La optimización es un campo enorme en sí mismo y hay muchas cosas por explorar.

Si está interesado en este tipo de optimización, una de las cosas que puede explorar es el demoscene . El demoscene, y algunas de sus culturas artísticas relacionadas, han conservado durante mucho tiempo una sensación de asombro acerca de tratar de crear arte intrincado para computadoras que ocupe el menor espacio posible. Muchos de ellos tendrán información sobre cómo hicieron algunos o todos sus "trucos".

A menudo hay una ingeniosa mezcla de sentido común, aunque hay "trucos" y "hacks" específicos para un juego o género. A menudo hay un poco de "suerte" involucrada, y un equipo que conoce los límites para los que está trabajando (tal vez continuamente chocando con esos límites durante todo el proceso), conoce sus compensaciones disponibles y está dispuesto a hacer parte del intercambio necesario -offs y sacrificios para cumplir con sus límites.

Estas son algunas de las cosas en las que puedo pensar que pueden ayudar a un equipo a llevar un juego a tamaños más pequeños:

  • Reutilice lo que pueda: reutilizar los mismos sprites y las variaciones que puede hacer fácilmente desde una sola imagen de sprites (como reflejos, rotaciones, cambios de paleta) le ahorrarán espacio. Lo mismo ocurre con el código, la música y casi todo lo demás en un juego.
  • Comprima lo que pueda: hay una serie de esquemas de compresión, y saber cuáles usar puede ser un gran ahorro de espacio. Incluso a veces los esquemas de compresión simples, como la codificación de longitud de ejecución, pueden marcar una diferencia sorprendente. No solo eso, sino que existen esquemas de compresión (y formatos alternativos que no son exactamente compresión) para tipos de archivos individuales, a menudo con compensaciones de calidad. Por ejemplo, los archivos de audio wave / CD se pueden comprimir, con una pérdida marginal de información, en archivos MP3. Además, los formatos de archivo como MIDI y MOD basado en muestreador son formatos alternativos que ocupan mucho menos espacio, pero codifican música de manera completamente diferente y requieren diferentes habilidades para que suenen bien.
  • Pierda lo que no necesita: ¿puede hacerlo más barato? Por ejemplo, ¿puedes obtener la "personalidad" de un personaje en menos píxeles (o polígonos)? ¿La ubicación de los mosaicos debe ser definida exactamente por un diseñador o pueden generarse al azar en el código de su programa?
  • El código es a menudo más barato: aunque hiciste una broma sobre cuánto espacio normalmente toma una compilación de código ahora ideas (y hay razones por las que esta 'plataforma' ha aumentado con los años y formas de reducirla cuando es absolutamente necesario), pero, en general, si puede hacer algo algorítmicamente / procesalmente / en código fácilmente, ese enfoque también será más fácil de ajustar y reutilizar para otros activos de aspecto / sensación similares pero diferentes. Los fractales son un ejemplo particularmente fácil de ver: podrías tener una imagen de un intrincado fractal que ocupa mucho espacio en comparación con la fórmula matemática que lo genera. La fórmula matemática, además, puede tener parámetros que pueden generar imágenes similares, pero a veces sorprendentemente diferentes.

De todos modos, para un conjunto de preguntas tan grande y cargado, es de esperar que algunos de los temas anteriores sean buenos puntos de partida para que aprenda más.

WorldMaker
fuente
Además, use tecnología que use menos espacio.
Speeder
3
(lo siento, ingrese el problema nuevamente ... ¿hay alguna forma de deshabilitarlo? Odio que cada vez que presione enter ingrese el comentario).
Speeder
Otra entrada: / De todos modos, use tecnología que use menos espacio, como mapas de procedimiento (Noctis tiene una galaxia entera con varios millones de sistemas solares, con planetas que puede aterrizar y ver vida, árboles, ruinas, edificios ... en menos de 3MB ), música de módulo (música en formatos como .mod, .xm, .it ...), texturas de procedimiento (ver werkkzeug, mapzone y algún otro software), efectos de sonido de procedimiento (es posible hacer casi cualquier efecto de sonido de las matemáticas ecuaciones o manipulación de ondas de sonido básicas), etc.
Speeder
@speeder es fácil hacer clic en 'editar' o 'eliminar' en comentarios accidentales ...
dash-tom-bang
Re: "Comprima lo que pueda" en el hardware antiguo que normalmente comprimiría a lo que el hardware pudiera manejar. Nunca comprimiría el audio a MP3, porque el hardware de audio no lo manejaba de forma nativa y no querría perder el tiempo descomprimiéndolo en la CPU cuando solo podía transmitirlo directamente desde los medios al hardware de audio. MIDI fue genial porque todos tenían (y tienen) un sintetizador wavetable a bordo; simplemente cargue sus muestras y listo.
dash-tom-bang
0

Una cosa es que no estoy seguro de si todavía se mantiene en la era posterior a N64, pero el SNES y N64 a menudo reutilizaban texturas en otros objetos 3D, lo que a menudo ahorra un espacio considerable y representaciones previas del arte, que a menudo son falsos. Otro truco consistía en crear un fondo de borde de niebla que se utilizaría.

San Francisco Rush N64 siempre tuvo algo de niebla, aunque la configuración podría cambiar la densidad donde el arcade de San Francisco Rush no tenía ninguno y se podía ver el Golden Gate Bridge en la Pista 1 en comparación con la versión N64.

Además, los juegos a menudo reutilizan música como Zelda Ocarina of Time reutiliza mucho la música, lo que me parece molesto, ya que podría haber hecho un mejor trabajo, como la forma en que Banjo Kazooie / DK64 a menudo tenía temas dentro de los temas.

Zelda Ocarina del tiempo podría haber tenido el Hyrule Overworld y luego una versión subacuática del tema si te sumerges o haces que los instrumentos en el tema de la tienda reflejen el área exterior donde se usarían flautas y violines para la tienda y cuernos del bosque Kokiri y trompetas para la tienda y tambores de Hyrule Castle Town en el pueblo de Goron, etc.

En la PC, los módulos 3D se compilan en bibliotecas para acceder rápidamente a ellos utilizando un programa para desempaquetarlo, pero no estoy seguro de si ese es el caso de Nintendo, que está basado en ROM. La PC es RAM como entrar en una habitación desordenada en la que las cosas no siempre se quedan donde se supone que se deben y la información se puede sobrescribir hasta el punto en que la computadora ni siquiera se inicia.

Las consolas de juegos son ROM donde todo se almacena en un espacio asignado, por lo que cada vez que enciendas el juego buscará los archivos en ese espacio asignado con la garantía de que permanecerá allí.

El Grande
fuente