Soporte para interrupciones raster completo
Publicado: 07 Dic 2015, 23:32
Esto es algo que se venía pidiendo desde hace ya tiempo, cuando aún debatíamos en ZdP, y sólo hace unas pocas semanas que lo concretamos en conversación entre los miembros del equipo. Pues bien, ya están implementadas las llamadas "interrupciones ráster".
Consiste en poder elegir en qué línea de pantalla queremos disparar una interrupción INT. De esta forma es posible sincronizar más fácilmente lo que hace la CPU con la posición de la exploración de pantalla de la ULA. Esto permite efectos tipo split-screen, borde multicolor, o pintado de más sprites por frame usando algoritmos del tipo "racing the beam".
La forma de hacerlo es usando un par de nuevos registros dentro del bloque designado para ZX-Uno. Uno de ellos permite elegir los 8 bits menos significativos de la línea en la que queremos que se produzca la interrupción. El otro registro guarda el bit noveno del valor de la línea, más un par de bits para habilitar esta interrupción ráster, y opcionalmente, deshabilitar la interrupción habitual por retrazo vertical.
La forma de implementar esta nueva interrupción está inspirada en cómo se hace en el SAM Coupé, y así, el disparo de la señal INT se produce un poco antes de la línea deseada: en concreto el flanco de bajada de INT se produce en el momento en que se termine de pintar la zona de paper de la línea anterior a la pedida, y se comienza a dibujar el borde derecho. Esto da 96 ciclos de reloj desde que ocurre ese flanco hasta que se comienza a pintar la zona de paper de la línea en la que se ha elegido disparar la interrupción ráster. Si se quieren hacer cosas con el borde, hay 80 ciclos de reloj. Esto suponiendo 224 ciclos por linea. Para el modo de 128K, hay 4 ciclos más de reloj disponibles.
El que existan 9 bits en total para definir la línea en la que se dispara la interrupción significa que, a diferencia de lo que ocurre en SAM Coupé, aquí podemos elegir disparar la interrupción ráster no sólamente en las líneas correspondientes al paper, sino en cualquier otra, que puede corresponder al borde superior, inferior, o incluso a la zona de blanking vertical. Se puede por tanto definir una interrupción que se dispare justo después de terminar de pintar el paper (es decir, en la primera línea del borde inferior) y así tener más tiempo que antes para pintar sprites para el siguiente frame.
Los detalles de cómo acceder a esos registros, etc, como siempre, en la wiki técnica.
A modo de demostración, he escrito un progamita que pretende hacer algo parecido a lo que se ve en algunas demos. Seguramente, los mascas que hacen estas demos son capaces de lograr este mismo efecto sin raster interrupts, pero ahora al menos se puede hacer con más desahogo de la CPU, o código menos ofuscado. En la foto no se aprecia que la barra se mueve. El código fuente y TAP de esta demo, y otra más sencilla, están en la carpeta "raster_tests" dentro de la carpeta del test20. Se ve como el gestor de interrupción ráster se dedica a pintar el borde del color que corresponda según la línea en la que estemos, y un gestor de interrupción de retrazo vertical que prepara los datos para que la ráster no pierda un tiempo precioso, y además tocar 1/50 de música.
Creo que con esto doy por finiquitado el test20. Lo que falta por hacer, para el test21 (salvo que haya alguna cosa que tenga que corregir en éste)
Consiste en poder elegir en qué línea de pantalla queremos disparar una interrupción INT. De esta forma es posible sincronizar más fácilmente lo que hace la CPU con la posición de la exploración de pantalla de la ULA. Esto permite efectos tipo split-screen, borde multicolor, o pintado de más sprites por frame usando algoritmos del tipo "racing the beam".
La forma de hacerlo es usando un par de nuevos registros dentro del bloque designado para ZX-Uno. Uno de ellos permite elegir los 8 bits menos significativos de la línea en la que queremos que se produzca la interrupción. El otro registro guarda el bit noveno del valor de la línea, más un par de bits para habilitar esta interrupción ráster, y opcionalmente, deshabilitar la interrupción habitual por retrazo vertical.
La forma de implementar esta nueva interrupción está inspirada en cómo se hace en el SAM Coupé, y así, el disparo de la señal INT se produce un poco antes de la línea deseada: en concreto el flanco de bajada de INT se produce en el momento en que se termine de pintar la zona de paper de la línea anterior a la pedida, y se comienza a dibujar el borde derecho. Esto da 96 ciclos de reloj desde que ocurre ese flanco hasta que se comienza a pintar la zona de paper de la línea en la que se ha elegido disparar la interrupción ráster. Si se quieren hacer cosas con el borde, hay 80 ciclos de reloj. Esto suponiendo 224 ciclos por linea. Para el modo de 128K, hay 4 ciclos más de reloj disponibles.
El que existan 9 bits en total para definir la línea en la que se dispara la interrupción significa que, a diferencia de lo que ocurre en SAM Coupé, aquí podemos elegir disparar la interrupción ráster no sólamente en las líneas correspondientes al paper, sino en cualquier otra, que puede corresponder al borde superior, inferior, o incluso a la zona de blanking vertical. Se puede por tanto definir una interrupción que se dispare justo después de terminar de pintar el paper (es decir, en la primera línea del borde inferior) y así tener más tiempo que antes para pintar sprites para el siguiente frame.
Los detalles de cómo acceder a esos registros, etc, como siempre, en la wiki técnica.
A modo de demostración, he escrito un progamita que pretende hacer algo parecido a lo que se ve en algunas demos. Seguramente, los mascas que hacen estas demos son capaces de lograr este mismo efecto sin raster interrupts, pero ahora al menos se puede hacer con más desahogo de la CPU, o código menos ofuscado. En la foto no se aprecia que la barra se mueve. El código fuente y TAP de esta demo, y otra más sencilla, están en la carpeta "raster_tests" dentro de la carpeta del test20. Se ve como el gestor de interrupción ráster se dedica a pintar el borde del color que corresponda según la línea en la que estemos, y un gestor de interrupción de retrazo vertical que prepara los datos para que la ráster no pierda un tiempo precioso, y además tocar 1/50 de música.
Creo que con esto doy por finiquitado el test20. Lo que falta por hacer, para el test21 (salvo que haya alguna cosa que tenga que corregir en éste)