articulos

Knightlore: Cuando la calidad y el talento se ven también en los más pequeños detalles

Ante la expectación que ha creado mi comentario en relación con el Knight Lore y el hecho de que se almacenaran los gráficos invertidos, os diré que en mi opinión lo hacían al utilizar una sutil técnica de transferencia de los gráficos de memoria optimizando al máximo la velocidad mediante el uso del puntero de pila como puntero al gráfico y aprovechando que una función POP, permite obtener 2 registros e incrementar el puntero con el mínimo de ciclos de reloj.

Y es que pensándolo con detenimiento mediante una instrucción POP DE que necesita 10 ciclos de reloj, nos evitamos tener que hacer

LD E,(HL) ' 7 ciclos de. Reloj
INC HL 'Incr puntero (6 ciclos)
LD D,(HL) ' 7 ciclos
INC HL 'Incr. puntero (6 ciclos)

Que lleva 26 ciclos de reloj, es decir más de un 50% que el método del Knightlore.

En una programación tradicional, si queremos volcar los datos de un gráfico en memoria hacia la pantalla real o una pantalla oculta de renderizado, tenemos que obtener primero el byte de la mascara, aplicarlo en el fondo para eliminar la parte sobrante, obtener a continuación el byte del gráfico y mezclarlo con el resultado anterior.
En el siguiente ejemplo, obviando operaciones de rotación, inversión, etc y centrandonos exclusivamente en lo dicho anteriormente y tratando de que el proceso sea lo más rápido posible, lo haríamos de una forma similar a ésta:

HL: Puntero a pantalla, DE: Puntero del gráfico

LD A,(DE) ' Cogemos mascara (7 ciclos de. Reloj)
AND (HL) ' Aplicamos mascara al fondo (7 ciclos)
LD C,A ' Guardamos resultado en C (4 ciclos)
INC DE ' Incr puntero (6 ciclos)
LD A,(DE) ' Cogemos grafico (7 ciclos)
OR C ' Mezclamos gráfico + fondo enmascarado (4 ciclos)
LD (HL),A ' Guardamos resultado en destino (7 ciclos)
INC DE ' Incr. puntero para sig. byte (6 ciclos)

Total: '48 ciclos de reloj -> 13,71 μs

Es decir, tardamos 13,71μs en transferir 8 pixeles a la pantalla (un byte)

Los chicos de Ultimate en Knight Lore lo hacían así:
HL: Puntero a pantalla, SP: Puntero del gráfico

POP DE ' Obtenemos graf. (D) y máscara (E) e incr. Puntero (10 ciclos de reloj)
LD A,E ' Pasamos la máscara a A (4 ciclos)
AND (HL) ' Aplicamos mascara al fondo (7 ciclos)
OR D ' Mezclamos gráfico + fondo enmascarado (4 ciclos)
LD (HL),A ' Guardamos resultado en destino (7 ciclos)

Total: '32 ciclos de reloj -> 9,14μs


Es decir un 33% más rápido por cada byte dibujado. Sin duda, los métodos no son muy ortodoxos pero qué duda cabe que los chicos de Ultimate rizaban el rizo.

Un saludo.
Iñigo Ayo.

Firma: Iñigo Ayo

Hotel matarraña
Tu hotel para eventos en el matarraña
Posicionamiento Zaragoza
Posicionamiento SEO Zaragoza
Flores Zaragoza
Compra flores baratas Zaragoza

El Mundo del Spectrum

El Mundo del Spectrum es un medio digital dedicado al Sinclair ZX Spectrum, a los 80 y al Retro en general. Nació como homenaje a Microhobby en 1996 en formato revista mensual evolucionando hasta esta cuarta época. Como medio audiovisual se publica regularmente el Podcast llamado El Mundo del Spectrum Podcast y material en vídeo en el canal de Youtube. Publicados dos libros de gran éxito editorial. Si te gusta el Retro y el Spectrum en particular, esta es tu web. Bienvenido/a.

Publicaciones relacionadas

13 comentarios

  1. Que recuerdos del ensamblador del Z80. El único código ensamblador con el que me he entendido algo. Y es que fue uno de los méritos del Spectrum, el enseñarnos unos fundamentos que aunque más adelante no se fueran a utilizar, te ubicaban muy bien en las distintas partes de un sistema.

    Muchas gracias Íñigo…

  2. No sé donde ni cuando me he perdido algo, pero el autor empieza diciendo "Ante la expectación que ha creado mi comentario en relación con el Knight Lore…". I pregunto yo, ¿donde ha sido ese comentario?.

    Últimamente ando bastante liado, pero aún así suelo visitar diariamente los foros más habituales y esta página Web. ¿Es grave doctor?

  3. Esta técnica del uso de la pila para acelerar el acceso a la video-RAM lo explicó alguien en la temporada 2, no lo recuerdo exactamente, quizás Rafa Gómez…
    Lo que no entiendo es cómo puede funcionar: la pila es usada por el Spectrum para anotar direcciones de retorno en llamadas a subrutinas, o cuando se producen interrupciones, etc. ¿Esto no machacaría los datos de gráfico y máscara? ¿O se puede de alguna forma “proteger” el acceso a la pila durante estas operaciones de renderizado?

  4. No tienes problema si se mantienen las interrupciones deshabilitadas (DI). Únicamente una interrupción externa no enmascarable como la NMI podría machacarte la zona gráfica al guardar la dirección de retorno (PC) pero el Spectrum no estaba diseñado para atender éste tipo de interrupciones ya que terminaba en un reset (JP 0)

  5. Bueno, en el spectrum no hay videoram como tal, es simplemente una zona de memoria compartida con la ULA. Usar la pila para realizar volcados rápidos en lugar de una secuencia de LDI's, te da una buena ganancia de ciclos sobre todo si utilizas un buffer gráfico en memoria no contenida que luego vuelcas en la zona de pantalla. No da problemas pero tienes la limitación de no poder hacer llamadas desde dentro de la rutina, ni tener activadas las interrupciones, lo que se hace es guardar el contenido de SP al iniciar la rutira, y se restaura al final, con lo que todo vuelve a la normalidad en lo que a la pila se refiere. Si se utilzara una NMI, por ejemplo pulsando el botón rojo del Transtape, lo que ocurriría es que machacaría bytes de los sprites, pero nada más. En el spectrum evidentemente sí funcionan las NMI, y periféricos como el Transtape o el Disciple lo utilizaban. Lo que realmente le da velocidad a esa rutina es tener almacenados los datos de mácara y sprite de forma alterna. En general el knightlore es genial a la hora de innovar con los algoritmos y el concepto de juego, pero como virtuosismo de programación del procesador es más bien flojo. Las técnicas filmation de John Ritman lo superaron amplísimamente. En ese sentido es mucho más impresionante ver código de Joffa Smith o de Raffaele Cecco

  6. El código de ultimate en general es demasiado lento y produce unas ralentizaciones terribles en pantalla. Es algo que mejoró mucho sobre todo John Ritman en Batman y HoH, ambos los mejores filmation para Spectrum. Bo Jangeborg produjo también un engine asombroso, pero no destacaba por la velocidad, sino por las innovaciones que introdujo en sus videojuegos

  7. @vaticinio – gracias por la explicación detallada. Nunca me quedó del todo claro cómo se podía usar la pila para acelerar el proceso de renderizado, atendiendo al mismo tiempo a las interrupciones.

    Y sobre tu otro comentario acerca de Ultimate y Doom, también estoy de acuerdo que el duo Carmack y Romero fueron dos de los personajes más disruptivos que ha habido en la historia del videojuego!

  8. A todo esto, ese pantallazo con el debugger del emulador… ¿es simplemente un ejemplo para dejar patente la forma en que se miran estas cosas o se supone que es la rutina que hace lo que se comenta en el artículo? Es una rutina curiosa y he comprobado que forma parte de la impresión de sprites en el buffer intermedio de pantalla. Tanto en ese como en otros trozos de código se hace constantemente uso de CPL para invertir los bytes. Es algo muy, muy raro, porque desde luego desde el punto de vista de la velocidad, está invirtiendo tiempo en algo que no tiene sentido a priori, salvo que precisamente de alguna forma los bytes se guarden de una forma especial. Ahora no tengo tiempo a mirarlo con detenimiento, pero yo diría que knigtlore guarda los gráficos de una forma rara como algún sistema peregrino de protección. Desde luego es muy curioso

Deja un comentario

Mira también

Cerrar
Botón volver arriba
Cerrar