Sprites, BOBs  y otras criaturas mágicas (VII): DMA

 

Qué gran desarrolladora DMA Design ¿verdad? Menace, Blood Money, Lemmings… y, años después, volvieron más fuertes que nunca con el mítico ‘Grand Theft Auto’, ya bajo el nombre de Rockstar North. En este artículo, sin embargo, vamos a tratar un tema todavía más interesante: el DMA o Direct Memory Access (Acceso Directo a Memoria) y, en concreto, su implementación en el Amiga.

 

A Mr. T le encanta la memoria chip. Sé como Mr. T.

 

Introducción

¿En qué consiste el DMA? Se trata simplemente de un mecanismo para permitir que los diferentes componentes de un sistema informático puedan acceder a la memoria sin depender para ello de la CPU. Cada una de las vías a través de las cuales se lleva a cabo este acceso se denomina canal DMA.

¿Qué supone esto en el caso del Amiga? Vamos a distinguir tres grandes subsistemas:

  • La CPU o procesador, encargado de ejecutar las instrucciones de nuestro programa.
  • Los custom chips (Agnus, Paula y Denise, en ciertos modelos) en los que residen el Blitter, el Copper, etc. y que permiten liberar al procesador de ciertas tareas. Todos los datos que necesiten los custom chips han de estar en memoria chip.
  • La memoria, que en el Amiga puede ser de tres tipos:

Chip: es la memoria que viene de serie en cualquier Amiga. A ella pueden acceder tanto el procesador como los custom chips.
Fast: a ella sólo puede acceder la CPU.
Slow: tiene los inconvenientes de la fast (sólo la CPU puede acceder a ella) y los de la chip (puesto que comparte bus con ésta).

 

Acceso a memoria del procesador y los custom chips.

 

            Como veis, la memoria chip es la única a la que pueden acceder tanto el procesador como los custom chips, lo cual hace necesario establecer algún tipo de mecanismo que permita organizar dichos accesos. El controlador de DMA (árbitro memoria en la figura anterior) es el encargado de realizar esta tarea.

 

Canales DMA

Como dije anteriormente un canal DMA es cada una de las vías a través de las cuales los custom chips pueden leer de la memoria chip o escribir en ella. El Amiga dispone de 24 canales DMA organizados de la siguiente manera:

  • Blitter: dispone de 4 canales DMA, 3 para las fuentes de datos (A, B y C) y 1 para el destino (D). Para conocer más a fondo el funcionamiento del Blitter en general, y de estos canales en particular, os recomiendo releer las entregas 3, 4 y 5 de esta serie de artículos.
  • Copper: como ya sabéis, los programas que ejecuta el Copper se denominan copperlists y están formados sólo por 3 instrucciones: MOVE, WAIT y SKIP. El Copper dispone de 1 canal DMA para acceder a la copperlist y recuperar así tanto las instrucciones como los datos que la componen. Para más info, releed el segundo capítulo de ‘Sprites, BOBs y otras criaturas mágicas’.
  • Bitplanes: 6 canales DMA, tantos como bitplanes pueden llegar a componer una imagen.
  • Sprites: 8 canales DMA, uno por cada sprite hardware de que dispone el Amiga. Los sprites fueron tratados en profundidad en el artículo anterior.
  • Audio: 4 canales DMA, uno por cada canal de audio.
  • Disco: 1 canal DMA.

Es posible activar o desactivar estos canales dependiendo de nuestras necesidades. Sólo en el caso de los canales DMA de audio podremos activarlos o desactivarlos independientemente. Para el resto de componentes que disponen de varios canales DMA (Blitter, bitplanes y sprites) sólo tendremos la posibilidad de activarlos o desactivarlos todos a la vez.

 

El ráster manda

El acceso a la memoria chip a través de cada uno de los canales enumerados en el apartado anterior no puede hacerse simultáneamente. Una de las cosas que más me sorprendieron cuando empecé a programar para el Amiga fue precisamente descubrir que la forma de organizar estos accesos, está fuertemente ligada al pintado de la pantalla. Vamos a verlo más en detalle.

            Durante lo que dura el pintado de cada línea del ráster, da tiempo a realizar aproximadamente unos 225 accesos a memoria chip, también llamados ciclos. En cada ciclo es posible leer o escribir una palabra en memoria chip (16 bits). ¿Cuáles de estos ciclos pueden ser usados por los distintos canales y bajo qué normas? A continuación, podéis ver un gráfico en el que se muestra cómo se reparten estos accesos a memoria chip (para el caso de baja resolución) entre los distintos canales, durante cada línea del ráster (SPR = sprites, BPL = bitplanes):

 

Reparto de los ciclos de DMA durante una línea del ráster.

 

Los ciclos pares son compartidos por el Copper, el Blitter y el procesador, en ese orden de prioridad. Es decir, mientras el Copper tenga que acceder a la memoria chip, el Blitter y el 68k tendrán que esperar su turno. La prioridad del Blitter sobre la CPU puede en cierto modo controlarse. Si activamos el Blitter Nasty la CPU no podrá acceder a memoria chip mientras el Blitter tenga que hacerlo. Si lo desactivamos, el Blitter dejará libre uno de cada 4 ciclos para que el procesador acceda a la memoria chip.

Los ciclos impares se encuentran pre-asignados de manera fija al resto de canales. Vamos a ver el uso de estos ciclos impares algo más en detalle:

  • Bitplanes: imaginemos que queremos mostrar una imagen de 320 pixels de ancho. Cada línea de cada uno de los bitplanes que compongan esa imagen estará formada por 320 bits. Eso supone 20 accesos a memoria chip para que cada plano pueda recuperar los datos que necesita para mostrar su parte de una línea ya que, como comenté antes, en cada acceso se pueden leer o escribir 16 bits y 320 / 16 = 20. Dos detalles interesantes, observando en el gráfico anterior los ciclos reservados para los bitplanes:

 Fijaos que a partir de 5 planos (32 colores) éstos empiezan a ocupar ciclos pares, que les son “robados” a Copper, Blitter o CPU. Por tanto, menos tiempo para que ellos accedan a memoria chip.
 En el gráfico, la zona visible empieza en la posición horizontal $38 (en hexadecimal). Si ensancháramos la zona visible de la pantalla (y ésta empezara en $30, por ejemplo), el DMA de los planos “pisaría” el de los sprites hardware que, para un ancho estándar de pantalla, tiene lugar justo antes de que empiece la zona visible. El primer sprite en “caer” sería el 7 cuyos datos, que normalmente se leerían en los ciclos 31 y 33 del gráfico, pasarían a ser usados por los bitplanes 2 y 4. Lo mismo ocurre si queremos hacer scroll horizontal puesto que para ello hemos de comenzar a leer datos de los planos con 16 pixels de antelación, por decirlo de forma sencilla. En ambos casos el sprite 7 deja de ser funcional.

  • Sprites: como ya sabéis, cada sprite hardware puede mostrar 4 colores (2 planos) y su ancho máximo es de 16 pixels. Por tanto, para mostrar una línea de un sprite hay que leer 2 planos de 16 pixels = 32 bits, 2 palabras o lo que es lo mismo, son necesarios 2 accesos a memoria chip para leer una línea del sprite. Observad en el gráfico que, efectivamente, hay 2 ciclos reservados para cada sprite hardware (recordad que eso es para cada línea de la pantalla).
  • Audio: se leen 16 bits para cada canal.
  • Disco: 2 accesos a memoria chip por línea.

 

Sacando rendimiento al DMA

Conocer el funcionamiento del DMA con precisión nos abrirá muchas posibilidades de cara a optimizar cualquier cosa que programemos en Amiga a bajo nivel. Algunas consideraciones:

  • El código y todos aquellos datos que no necesiten estar en memoria chip han de estar siempre en memoria fast, si la hubiera. Los lenguajes de programación disponen de directivas para indicar qué secciones de nuestros programas (sean código o datos) han de residir en cada tipo de memoria. De esta forma reducimos a la mínima expresión los accesos del procesador a memoria chip.
  • Durante la zona no visible del display podemos desactivar el DMA de los planos y de los sprites, lo cual dejará muchos ciclos libres que podrán ser usados por Copper, Blitter o CPU.
  • En relación con el punto anterior, debemos intentar que el Blitter haga la mayor parte de su trabajo durante la zona no visible del display puesto que, si tenemos desactivado el DMA de los planos, el Blitter dispondrá de muchos más ciclos para realizar su tarea.
  • Si sabemos exactamente qué ciclos DMA estarán libres en cada línea podremos aprovecharlos para, por ejemplo, montar el marcador de un juego a base de reutilizar de manera manual un par de sprites hardware. Una tarea que requiere precisión de cirujano para reposicionar y recargar los sprites con el Copper en los huecos dejados por el DMA de los planos y que, por tanto, dependerá también del número de colores (o dicho de otra forma, de planos) con el que estemos trabajando. El mejor ejemplo de esto es el marcador del genial Battle Squadron cuyo programador, Martin Pedersen, explica aquí ése y otros muchos puntos interesantes del desarrollo.

 

Imaginad un juego como Lionheart, por ejemplo. Este gran juego de Thalion emplea el modo dual playfield, con 3 bitplanes para el fondo y 3 para el primer plano. Es decir 8 colores en el fondo y otros 8 en el primer plano. Ya sólo por eso, y observando el gráfico anterior, podéis ver que de cada 8 ciclos DMA en la zona visible, sólo quedan 2 libres, puesto que se están empleando los bitplanes del 1 al 6. ¿Cómo es posible que uno de los juegos de Amiga con mejores gráficos use sólo 16 colores? La verdad, como muchos ya sabréis, es que el juego saca cientos de colores por pantalla a base de hacer cambios de paleta muy frecuentes con el Copper en distintas líneas de la pantalla. Todos esos ciclos que necesitará el Copper para ejecutar dichos cambios de paleta no estarán disponibles para Blitter y CPU, por el orden de prioridades comentado antes. Conclusión: en la zona visible de la pantalla queda muy poco margen para la CPU y el Blitter, que tendrán que hacer gran parte de su trabajo en el vertical blank, principalmente. Éste es uno de los motivos por los que el juego sufre ralentizaciones con cierta frecuencia, a pesar de que ni el tamaño ni, sobre todo, el número de enemigos en pantalla es elevado.

 

Lionheart en toda su “copperiana” gloria.

 

Conclusiones

En mi opinión, el DMA es el subsistema más crítico de toda la arquitectura del Amiga. Es el punto en el que confluyen CPU, Blitter, Copper y demás componentes citados en capítulos anteriores, para poder acceder a los datos que necesitan para su funcionamiento. Con este capítulo sobre el DMA quedan cubiertos muchos de los principales componentes de la arquitectura del Amiga. En la siguiente entrega, y aplicando los conocimientos adquiridos durante todos los capítulos anteriores, vamos a analizar en detalle los entresijos de uno de los mejores juegos que pasaron por el catálogo de Amiga… ¡Hasta entonces!

 

Publicado 15/12/2017

 

 

Un artículo publicado por:

Fernando Cabrera (@fcabrera_77)
Ingeniero informático. Nostálgico del Spectrum, adorador del Amiga y aficionado a los videojuegos y a la retro-informática. Ahora también Colaborador desde mi sección para Commodore Spain. 

 

 

 

 

 

 

4 Comentarios sobre “Sprites, BOBs y otras criaturas mágicas (VII): DMA

  1. freshko (juanma martin)

    Gracias por el artículo. Los Reyes llegaron antes este año 😉 Esperaba impaciente esta parte de los canales DMA. Un saludo y gracias de nuevo por tus artículos.

    • Fernando Cabrera

      Gracias a ti por tu comentario :). Ya te has puesto a desarrollar algo concreto? Estás haciendo pruebas para empezar? Ánimo en cualquier caso y por aquí estamos si os surge alguna duda.

  2. tolkien

    No sabes lo que me gustan tus artículos. Que grande eres.

    • Fernando Cabrera

      Todo un halago viniendo del coder amiguero revelación de 2017! 😀 Muchas gracias ;).

Deja un comentario

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

clear formSubmit