En la era de las PC de 8 bits, el hardware gráfico carecía de funciones modernas como mapeadores de texturas o blitters, lo que obligaba a los programadores a mover manualmente cada byte de un búfer de pantalla para renderizar un solo fotograma. Para que un juego de desplazamiento lateral fuera jugable en un procesador 6809, un desarrollador pasó de un bucle de copia de fila ingenuo que tomaba 157 ciclos a un truco especializado basado en la pila que ejecutaba la misma operación en solo 56 ciclos.

La restricción del hardware

Durante la década de 1980, el hardware gráfico de las PC casi no proporcionaba asistencia para mover datos. Para mostrar un juego de desplazamiento lateral, un programador tenía que copiar teselas de 28x28 píxeles en un búfer de pantalla de 320x240 byte por byte. Debido a que el búfer de pantalla era más ancho que las teselas, cada copia de fila requería un cálculo de desplazamiento de memoria específico para avanzar el puntero de destino.

Listado de código en ensamblador que muestra la lógica del hardware gráfico temprano
Un ejemplo temprano de código en ensamblador utilizado para gestionar las restricciones del hardware gráfico.blog.moertel.com

Esta captura de pantalla ilustra la gestión manual de memoria requerida en la era de los 8 bits.

“Logré aprovechar cada uno de los registros disponibles en la máquina”

— A Great Old-Timey Game-Programming Hack - Tom Moertel’s Blog

Optimizaciones iterativas de ensamblador

La primera optimización consistió en desenrollar el bucle interno para eliminar la sobrecarga del bucle de conteo de 7 utilizado para copiar las palabras de una fila. Esto redujo el recuento de ciclos de 157 a 120, una mejora de velocidad del 30%.

Conteos de ciclos para copia de fila: Bucle ingenuo 157 cycles; Bucle optimizado 98 cycles; Truco de pila 56 cycles
Conteos de ciclos para copia de filablog.moertel.com

Gráfico elaborado por HN Digest a partir de las cifras de blog.moertel.com; los valores se muestran como aparecen en la fuente.

El siguiente paso consistió en sustituir las operaciones de post-incremento de 3 ciclos por desplazamientos exactos de 1 ciclo. Al calcular la ubicación precisa de cada palabra en relación con los registros de origen y destino, el desarrollador redujo el coste de copia de fila a 98 ciclos, una mejora del 60% sobre el código original.

Listado de código en ensamblador para la optimización del rendimiento
Código en ensamblador que demuestra las optimizaciones iterativas utilizadas para reducir el recuento de ciclos.blog.moertel.com

El listado de código muestra la transición de bucles ingenuos a instrucciones de ensamblador optimizadas.

El truco de la pila y la página directa

La optimización más extrema aprovechó la arquitectura única del 6809. El procesador contaba con instrucciones PSHS y PULS que podían cargar o descargar todos los registros en la pila de hardware en un número muy pequeño de ciclos. Al apuntar los registros de pila (S y U) a la tesela de fondo y al búfer de pantalla, el desarrollador podía mover datos en grandes bloques.

Para manejar el hecho de que una fila de 28 píxeles (14 bytes) no es divisible uniformemente por 6, el desarrollador utilizó el registro de 'página directa' del 6809. Al designar una página de memoria específica como la 'página directa', el registro DP podía actuar como un intermediario adicional de un byte, permitiendo que el código copiara 7 bytes por par de carga-descarga. Este método final redujo la operación de copia de fila a solo 56 ciclos.

Listado de código en ensamblador para trucos de pila y página directa
Trucos avanzados de ensamblador que utilizan los registros únicos de pila y página directa del 6809.blog.moertel.com

Este listado demuestra el truco 'loco' que logró la copia de fila de 56 ciclos.

Estrategias de rendimiento alternativas

Mientras que el truco del 6809 se centraba en hacer más rápida la operación de copia, otros desarrolladores abordaron el mismo cuello de botella de rendimiento cambiando lo que necesitaba ser copiado. Técnicas como los 'rectángulos sucios' o la actualización adaptativa de teselas implican rastrear los cambios en el estado del juego y redibujar solo los píxeles o teselas específicos que se movieron, en lugar de actualizar toda la pantalla en cada fotograma.