graficos

Imagen de Diskover

El hardware de la NES. Capítulo IV: Superando las limitaciones de la PPU

cabecera-superando-limites

Como ya he comentado en el anterior artículo, la NES fue diseñada para exprimir hasta el límite cada una de sus capacidades. Dado que sus componentes eran básicos incluso para la época en la que se lanzó a la venta (1983), se preocuparon mucho de, al menos, conseguir un cohesión total entre la CPU, la memoria y la PPU a fin de que no hubiese muchos cuellos de botella o pasos intermedios que retrasasen las operaciones de proceso.

Con ello surgieron una serie de soluciones, algunas ya incluidas en el registro del hardware, que nos facilitaban mucho las cosas a la hora de desarrollar y que vamos a enseñar y demostrar como funcionaban.

 

SPRITE ZERO HIT

Probablemente nadie o muy poca gente ajena al mundo de la programación en NES alla oido hablar de este tal Sprite Zero Hit. Este sprite es un tanto especial: nos permite partir la pantalla en dos trozos independientes de tal forma que cada una de ellas pueda funcionar independientemente. A grosso modo es una interrupción de pantalla primitiva (procedimiento que nos permite mover a diferentes velocidades, o incluso parar, alguna de las partes de la pantalla). Fue concedido para realizar esta función desde los inicios del diseño de la NES.

El Sprite Hit Zero corresponde al último tile de la tabla de tiles designada para sprites. Obligatoriamente debe tener en algun lugar de sus 8x8 pixeles al menos un pixel de color (no es válido el transparente). Este pixel mínimo de color debe colocarse en el lugar de la pantalla donde queramos hacer la interrupción, pero debe tocar algún elemento del background que tambien tenga algún pixel mínimo de color (no transparente).

Es util a la hora de crear HUBs (marcadores de puntos, energía, vidas, etc...) o para crear efectos de rastreado que nos den sensación de movimientos de planos a diferentes velocidades, para que el videojuego gane profundidad visualmente.

Un ejemplo claro lo tenemos en Super Mario Bros. y su marcador. En este caso, el sprite zero hit corresponde al tile que dibuja el bajo de la moneda que representa cuantas llevamos cogiendo. Podían haber elegido otra cosa para hacer el Sprite Hit Zero, pero en este caso escogieron eso. Evidentemente, para averiguar donde está el Sprite Hit Zero se necesita usar un emulador que nos deje ver la tabla de memoria. De otra forma es imposible y solo podríamos averiguarlo mediante intuición y/o conclusiones.


Gracias a ese sprite zero hit, el marcador queda estático mientras el resto de la pantalla hace scroll.

En el videojuego homebrew The Banketh - The Video Game se decidio hacer un Sprite Hit Zero tan solo en las pantallas donde nuestro personaje debe desplazarse en motocicleta por Santander City. De esta forma, el Sprite Hit Zero se decidió que fuera un pixel superpuesto encima del agua. Así se consigue que del pixel para arriba se quede todo estático y el resto pueda moverse.

VBLANK Y BANKSWICHT

En la NES solo se puede cambiar tiles del banco CHR destinado al background cuando la PPU está apagada. No podemos cambiar un tile de un banco por otro tile del mismo banco, o por uno nuevo, a no ser que lo hagamos directamente sobre la RAM de la PPU o que apaguemos esta última durante unos mili segundos para conseguirlo.

La primera opción come muchos recursos a la NES y solo se puede hacer cuando las lineas de escaneado de la pantalla ya han terminado de mostrar todos los gráficos necesarios que componen la pantalla, y nos deja unos pocos ciclos de proceso aun para realizar operaciones sin apagar la pantalla (lo que se conoce como vBlank).

La segunda opción conlleva que la pantalla parpadee a negro durante un corto espacio de tiempo que se hace incomodo a la vista y que sirve para cambiar los tiles que queramos del CHR destinado al background (o el propio background); por lo cual estamos limitados.

El vBlank se suele usar comunmente para animar marcadores de puntos, vidas, etc... espacios del background que normalmente solo tienen que cambiar un tile (o varios, aunque pocos) para mostrar un resultado: el contador de puntos aumenta, la vida del player se rebaja, etc... Aunque se ha visto alguna vez usarse para actualizar tiles y poner otros nuevos en el CHR.

Con la salida de los mapeadores de memoria (mappers) y el poder ampliar el número de chips CHR, se incluyó la posibilidad de usar los selectores de bancos o bankswicht, que permitían elegir que banco CHR usar en todo momento y cuando quisieramos. Esta mejora, además nos permitía hacer cambios de tiles "al vuelo" aunque realmente lo que estábamos haciendo era cambiar hacia que dirección apuntaban.

Muchos juegos usaban esto para animar los escenarios. Por ejemplo, en los mapas de Super Mario Bros. 3:

Mario y el Hermano Martillo son sprites, pero los arbustos que se mueven simplemente son tiles del background animados mediante cambios en el bankswicht. Los primeros comen muchos recursos a la NES por que obligamos a la PPU a buscar en todo momento que tiles necesita coger buscándolos por el CHR que estamos usando en ese momento, gastando con ello varios ciclos. Los segundos en cambio simplemente requieren cambiar el numero de bankswicht y ya esta. El tile sigue siendo el mismo, pero ahora tiene un dibujo diferente sin penalizarnos gastando innecesariamente ciclos de memoria, consiguiendo con ello un funcionamiento del videojuego mucho más fluido.

Imaginaros que tenemos tres CHR y que el tile numero 10 contiene un dibujo diferente en cada CHR de esos tres. Si nos las ingeniamos para dibujar en ese mismo tile un arbusto con diferentes formas en cada CHR y luego vamos cambiando mediante bankswicht el CHR que usamos, conseguimos animación sin gastar tantos recursos.

El cambio constante de bancos CHR mediante bankswicht, nos regala unas bonitas animaciones en los escenarios sin gastar apenas recursos.

Con eso conseguimos animar el escenario. Hay otras formas que consisten en almacenarlo en la RAM de la NES pero inicialmente eso otro está pensado para pequeñas cosas como por ejemplo los marcadores de puntos o vidas; o por ejemplo para hacer scroll; que os explicare más adelante.

Otros juegos como Kirby's Adventure, a parte de su gran calidad técnica, explotaban el banckswicht del MMC3 para conseguir cosas muy meritorias.

Te creés de verdad que la torre está rotando, aunque los tiles están quietos. Lo único que se mueve es la cámara.

 

EFECTO DOBLE CAPA Y ACTUALIZACIÓN DE TILES AL VUELO EN LA CHR-RAM

A raíz de bankswicht y la actualización de la RAM de la PPU en el vBlank, se podían también conseguir otros efectos. No hay ni truco ni cartón. Es el mismo sistema pero bien pensado, de tal forma que se podían conseguir interesantes efectos que simulaban doble capa; cosa impensable en una NES, pero que daba un muy buen resultado.

Realmente son un puñado de videojuegos los que llegaron a explotar esta característica, pero sin ninguna duda demostraban hasta que punto se le podía sacar jugo a la PPU.


En 3 Eyes Story en algunas pantallas se hacía un buen uso del bankswicht hasta el punto de, no solo simular capas, si no hasta sombras.
Todo es un mero juego de cambio de bancos de gráficos, atributos de color, etc...

 

Bucky O'hare o Battletoads tambien hacían un buen uso de este efecto actualizando la RAM de la PPU al vuelo.
La imaginación al poder.


Este Sword Master posiblemente sea uno de los primeros juegos que hizo gala de este genial truco.

Metal Storm tampoco se andaba con chiquilladas

Y muchísimo más bruto podemos ver este truco en juegos como Crisis Force, con planos de dirección en vertical a diferente velocidad y actualizaciones constantes en la CHR-RAM.

Crisis Force: Muy veloz. Mejores efectos.

Posiblemente el juego que mejor aplicó este efecto hasta el extremo fue Day of Thunder, que si bien no era un gran videojuego, si nos mostró varias pericias técnicas.

En Days of Thunder toda la carretera se carga al vuelo en la CHR-RAM constantemente. Un trabajo de "chinos"

EFECTO RASTER

El efecto raster es un tipo de rutina gráfica muy sencilla por el cual se consigue mover patrones de la pantalla de izquierda a derecha suavemente. Se utilizaba normalmente para simular carreteras en videojuegos de conducción o incluso escenarios en shooter's.

F1 Race era un videojuego de 1984 que ya hacia muestras de las bondades de esta rutina gráfica

Tetra Star sacaba todabía más partido al efecto raster

 

VECTORES

Con la capacidad de actualizar la CHR-RAM se llegó a experimentar con la posibilidad de introducir gráficos vectorizados simples en algún juego. De esta forma, en 1991 se lanza en Europa el videojuego Elite, un complejo programa de exploración comercial inter planetaria que nos deslumbró con este tipo de gráficos.

Pese a lo meritorio de su trabajo, las caídas de framerate eran constantes, lo que hacían que el resultado final en cuanto a jugabilidad se fuera un poco al traste.

 

 

SPRITES SUPERPUESTOS

Otra de las limitaciones con las que los programadores se tenían que enfrentar normalmente en máquinas de 8 bits tan sencillas, era a la hora de representar sprites que requerian mayor detalle que lo normal. Con una PPU que solo permitia 3 colores por tile, la cosa se ponía complicada, y muchas veces se tenian que buscar la vida para solventar este problema.

Una de las soluciones más comunes que se encontró para salir al paso era la de superponer un sprite encima de otro que previamente se había preparado dejando un espacio vacio para colocar el que necesitasemos. Fue el caso del sprite de Mega Man, personaje del videojuego del mismo nombre cuyo sprite usaba tres colores compuestos por negro, azul y azul claro. La necesidad de representar la cara de Mega Man como alguien con aspecto humano les llevó a encontrar esta solución para que no se viese ajeno a la idea original del proyecto, dandole un aspecto más rico en detalles al poder añadir el negro, blanco y carne.

Este truco era más recurrente de lo que os podéis imaginar, y hay un buen número de videojuegos de NES que tiraron por este sistema para conseguir más detalles en los sprites, sobre todo si es el player. Su inconveniente está en que consumes espacio en la misma línea de sprites, y al tener un límite de 8, podía llegar a ser un problema; así que tiene que haber un buen diseño detrás para que al final no surgiese el incomodo problema de parpadeo de sprites que se suele ver en estas máquinas y que aparece cuando sobrepasamos este límite en línea de sprites.

 

ROTACIÓN DE PALETAS

También a la hora de ahorrar recursos, para mostrar ciertas animaciones se usaban trucos consistentes en rotación de paletas. Mediante esta técnica muchas veces se daba la sensación de movimiento, resplandor o brillo. Un ejemplo claro lo tenemos con las monedas de Super Mario Bros. que cambian de color en un mero movimiento de colores en la paleta. A penas consume unos ciclos de memoria, y no era ningun problema para la PPU hacer esto.

Y otro ejemplo muy claro lo tenemos en Mega Man II, que mediante rotación de paleta nos regala una perfecta animación de una cascada, aunque esta realmente es estática.

 

 

BACKGROUNDS SIMULANDO SPRITES

Como decíamos antes, solo podemos poner 64 sprites en pantalla y tan solo 8 en línea. Esto nos limita muchísimo las cosas si queremos plasmar, por ejemplo, figuras muy grandes ¿solución? Dibujar en el background esa figura tan grande que queremos, dado que en esa capa no hay restricciones tan severas.

De esta forma, podemos simular movimiento moviendo el scroll como por ejemplo se hizo en Wrath of the Black Manta:


Este jefe final del primer nivel nos ponia las cosas muy dificiles. Ocupaba casi toda la pantalla de alto.
La vida, los ladrillos y el player son sprites.

Combinando este efecto y sprites superpuesto, podíamos llegar a darle algo de animación al invento. En muchos juegos de Capcom se hizo a la hora de mostrar también jefes finales, y daba muy bien el pego.


En The Little Mermaid se combinaba el background con sprites estrategicamente colocados para hacer jefes finales tan grandees como esta.

Y si, era algo muy común de ver en casi toda la biblioteca del catálogo de NES.

Otro caso parecido al anterior lo vemos en Ninja Gaiden III

EFECTO TRANSPARENCIA

Dentro de los registros de la PPU de la NES, existe uno llamado PPU MASK que nos permite configurar ciertas opciones de color sobre la paleta total (enfasis) consiguiendo soluciones teñidas de azul, rojo o verde; útiles en muchos juegos que necesitan tener unos colores distintos a los acostumbrados por el motivo que sea.

Además, se puede configurar el ultimo bit de la PPU MASK a 1 para poder desbloquear una escala de grises que funciona conforme al número de ciclos de la CPU, y que se usaba muchas veces para tener una visualización de los procesos de la máquina, para saber si nos estabamos pasando de ciclos para evitar ralentizaciones.

Programando eficientemente, se podía llegar a tener cierto control sobre este bit, como demostró Konami en el videojuego Noah's Ark, que tiene fases en las cuales se puede ver como aparece un escenario hundido bajo el agua con una marea que sube y baja, suavemente; al pixel. Este efecto se conseguía precisamente activando este bit de la PPU MASK, dando un resultado asombroso, que casi parecía dar opciones de capas trasparentes a la NES, tal como se podía ver en máquinas mucho más superiores (como por ejemplo la SNES de 16 bits).


En el "Noah's Ark", simplemente están activando el bit de forma variable para simular el agua, pero eso NO va relacionado con el tiempo de proceso en este juego.

VAMOS RESUMIENDO

Como habreís observado, la NES es una máquina tremendamente limitada pero con ciertos detalles que hacian sacar partido a estos escollos para finalmente poder crear videojuegos sorprendentes y muy vistosos.

Hoy en día a muchos les resultará un tema muy trivial, algo que no escapa más allá de una curiosidad muy específica, pero cabe reconocer que es parte de la historia de los videojuegos que ayuda a comprender como fueron evolucionando estas maquinas con el paso de los años.

Actualmente, dentro del panorama homebrew muchos son los que poco a poco consiguen sacar partido a todas estas técnicas y trucos para hacer trabajos sorprendentes en la NES y, por que no decirlo, bonitos. Es el caso de Minnade Mamotte Knight, lanzado en 2017 en formato rom por un nutrido grupo de programadores ya expertos en juegos modernos que en su día empezaron programando en NES.

En el siguiente artículo sobre el hardware de la NES veremos otras características.

Imagen de Diskover

El hardware de la NES. Capítulo II: El funcionamiento de la PPU

bank sprites nes

Posiblemente una de las grandes incógnitas que guarda la NES dentro de sus tripas sea el cómo gestiona los recursos gráficos con los cuales fue diseñada, en un época donde la tecnología estaba viviendo el inicio de una nueva era de la información pero cuyos recursos eran todavía muy caros y se necesitaba de mucho ingenio para aprovechar al máximo de lo que se disponía a un coste razonable. Este es el caso de la PPU de la NES: básica pero enormemente funcional.

La PPU o Picture Processing Unit (Unidad de Procesamiento de Imagen) es un chip integrado que actúa como "tarjeta gráfica" en la NES y que tiene una capacidad de 2 kb de RAM. Ya he comentado en el anterior artículo sus bondades: Es capaz de paginar de golpe 512 tiles (8 kb en formato ROM o RAM). Estos están divididos en dos bancos de memoria: un banco de 256 tiles para los background (los fondos, escenarios, etc...) y otro para los sprites que formemos (figuras del juego). Cada tile puede ser de 8x8 o de 8x16 pixeles. Normalmente se usa la primera opción, y rara vez la segunda.

Cuando conectamos nuestros cartuchos en la NES, el chip CHR que se encarga de guardar nuestros gráficos, se conecta directamente con la PPU. Los 8 Kb que contiene el CHR se van paginando, según necesidades, sobre los 2 kb de la PPU para que esta pueda procesar lo que necesitemos en ese instante y de esta forma, mediante orden de la CPU, se muestran en pantalla.

 

TILES Y SPRITES

Un tile o varios tiles juntos forman los sprites, aunque algunas personas llaman directamente a los tiles como sprites y al conjunto de tiles como metasprites. Es lo mismo.

La PPU de la NES tiene la capacidad de poner 64 sprites en pantalla, pero no puede haber más de 8 tiles en la misma linea de muestreo de la pantalla, así que los sprites que formamos pueden ser compuestos como mínimo de 1 tile, pero no de más de 8 tiles de ancho. Si tal cosa ocurriese, los siguientes sprites no se verían y permanecerían invisibles.


Más de 8 tiles en linea da como resultado parpadeos o directamente tiles invisibles

Gracias a los sprites podemos ver al personaje que controlamos en el videojuego, los enemigos, objetos, etc... No es obligatorio que sea así, pero digamos que es lo más normal.

Por ejemplo, estos son todos los tiles y paletas de colores que necesita Super Marío Bros. para formar el componente gráfico del videojuego.

- El banco de la izquierda muestra los tiles necesarios para hacer los sprites de Mario, Luigi, enemigos, objetos, etc...

- El banco de la derecha muestra los tiles necesarios para hacer los background de los niveles.

- La primera fila de colores muestra 4 paletas de 1+3 colores para usar en los background y la segunda fila de colores muestra otras 4 paletas de 1+3 colores correspondientes para usar en los sprites.

Como podéis observar, el primer color de cada paleta es el color azul (en este caso). Ese primer color se comparte obligatoriamente en todas las demás, por eso hablamos de paletas de 1+3 colores a elegir. Ese color marca el color de fondo total que tendrá la pantalla donde estemos y se le suele llamar backdrop. Sin embargo, para los sprites, ese primer color se ignora y simplemente es transparente. Así pues, realmente los background y sprites juegan con tres colores por paleta, solo que los background lo interpretan como color y los sprites como invisible. La imagen resultante da una solución como esta:

El caso de Super Mario Bros. es el típico donde sus sprites están formados por tiles de 8x8. La mayoría de los juegos de NES usan ese formato, pero hay muchos otros que utilizaron la opción de 8x16 tiles. La ventaja de esta otra opción es que puede ayudarnos a crear sprites resultantes más grandes sin que lleguemos a superar la barrera de los 64 sprites en pantalla y de esta forma poder mostrar muchos personajes en pantalla. La desventaja de esto es que si en un principio, en nuestro banco de memoria tenemos 256 tiles de 8x8, estos se verán reducidos a 128 tiles de 8x16 con lo cual perderíamos detalle a la hora de crear muchos sprites distintos. Un ejemplo de esto sería el caso del videojuego Teenage Mutant Ninja Turtles que lanzó Konami en 1989:

 
Tiles 8x8 en Blaster Master VS. tiles 8x16 en TMNT (animación cedida por Brad Smith)

Como podéis ver, si se hubiese usado una configuración de 8x8 tiles, se consumirían muchos recursos y puede que al poner diferentes enemigos u objetos en pantalla, se superase el límite de 64 sprites, con el eventual problema añadido de hacer calcular a la CPU la posición de todos estos, que daría como resultado un videojuego lento e inestable.

Al poner una configuración de 8x16 tiles, aprovechamos recursos aunque también perdemos otras ventajas e incluso puede que algunos tiles desperdicien mucho espacio, como pueden ser en este caso la cabeza superior de la tortuga Leonardo. Como ya digo, esta elección se hace al inicio del desarrollo del videojuego, dado que no se puede cambiar en cualquier momento, por tanto, es necesario tener muy claro el diseño del mismo sobre el papel ya desde un inicio.

Sea como sea, esta es la herramienta básica para poder poner sprites en pantalla. Una de las características más reconocidas de esta PPU es la de poder hacer mirroring en los sprites. Esto significa que un tile, cual sea, se puede espejar e incluso rotar en posición, de tal forma que no nos hace falta dibujar nuestro sprite mirando hacia todas las direcciones; simplemente se le añade el atributo que espeja o rota y listo (normalmente un bit en la cadena hexadecimal que crea el tile, basta para esto). Una forma muy loable de ahorrar recursos.


Un mismo sprite, cuatro posiciones diferentes, cero recursos consumidos

BACKGROUNDS, FONDOS Y PRIORIDADES

Los background o fondos que componen la pantalla del juego se forman con la otra tabla de 256 tiles que tenemos. Aquí, el color que comparten las cuatro paletas si es visible, a este se le asigna la posición backdrop y normalmente se elige un color que sea muy frecuente en el juego, para ahorrar trabajo.

Los tiles del background, no guardan información del color, si no que guardan la posición de color según paleta y su correspondiente atributo. La tabla de atributos que componen los background que dan color a estos mapas están limitados a 16x16 pixeles. Lo que quiere decir que en un área de 16x16 pixeles solo se puede usar una misma paleta. Estos atributos se ponen por debajo de los tiles que componen el background y de esta forma colorean el escenario.


The Banketh - The Video Game [RetroNES Software] (2016)

La ventaja con esta técnica es que un mismo tile o conjunto de tiles nos pueden servir para crear diferentes imágenes sin malgastar recursos (recordad que solo tenemos 256 tiles). De esta forma, el tile que usamos para representar arena, también nos puede valer para representar agua, simplemente cambiándole el atributo de color a la hora de componer el background final; de colores amarillentos a colores azulados.

El inconveniente radica en que como los atributos están limitados a un espacio de 16x16, podemos tener el problema de que el background parezca que tenga pocos colores. Hay que ser muy buen grafista para sacar partido a este arte.

De esta forma, una pantalla de cualquier juego de NES se forma de esta manera:

- Backdrop al fondo del todo, que es el color que se comparte.
- Sprites de baja prioridad (esto se configura).
- Background (el fondo en si formado por tiles).
- Sprites de alta prioridad (esto se configura).

Como podéis ver, podemos asignar a los sprites si estos tienen que ser de baja o alta prioridad. Esto nos puede ser muy útil para explicar al programa si estos deben aparecer encima o detrás del escenario. Nos amplia posibilidades y nuevas formas de juego que muchos ya explotaron en su día. Un ejemplo claro lo tenemos con SMB. 3:


¡Hop! ahora no me ves

En cualquier momento, nuestros sprites pueden tener una prioridad alta, con lo cual estarán por encima del escenario, o baja, con lo cual pasarían por detrás de este y solo serian visibles cuando ocupan el espacio cubierto por el color compartido en la tabla de atributos del background. En el caso de Super Mario Bros. 3, cuando Mario pasa a tener una prioridad baja, solo se le podría ver cuando esta sobre los atributos con el color azul del cielo, que es el color compartido en la paleta de este background.

Estos son los concepto mínimos para entender como funciona el procesador gráfico de la NES. Para muchos os será de mucha ayuda a la hora de entender como funcionaba esta máquina. Para otros incluso os resulte de gran utilidad si queréis meteros en el mundillo homebrew. Sea como sea, seguro que para la mayoría os resulta cuanto menos curioso.

Etiquetas: 
Suscribirse a RSS - graficos