Autor Tema: Técnica de multiplexación Usagi Yojimbo  (Leído 11262 veces)

Zub

  • Desarrolladores
  • Commodoremaníaco
  • ******
  • Mensajes: 150
  • SYS 0
    • Ver Perfil
Técnica de multiplexación Usagi Yojimbo
« en: Diciembre 10, 2015, 15:50:16 »
A mi me lo explicó una persona que lo desensambló.. pero creo que no se trata exactamente de cronometrar con los timers de las CIAs sino de generar interrupciones con dichos timers (en un momento determinado). La multiplexación de sprites se sigue haciendo mediante interrupciones pero en vez de éstas ser generadas por el VIC (raster) son generadas por los timers de las CIAs.

Desconozco que ventajas o inconvenientes puede tener este sistema, así a priori y sin conocerlo me parece más cómodo manejar interrupciones raster.

He visto un post antiguo que menciona este asunto. He visto que se quedó este tema en el tintero y creo que puedo arrojar algo de luz :)

La dificultad para multiplexar sprites en este tipo de juegos es que todos los sprites se concentran en "filas" contiguas. El esquema clásico de ordenarlos en el eje Y e ir asignando interrupciones de raster no funciona bien porque al estar muchos contiguos (sprite de torso -> sprite de piernas) la transición es demasiado abrupta y se produce flicker o incluso se pierden sprites. Aún así es posible hacerlo (Double Dragon 3 es el mejor ejemplo) con el truco que os voy a explicar, y añadiendo más lógica a la rutina IRQ de raster. Básicamente, cuando actualizas un sprite para multiplexarlo, tienes que comprobar si existen N sprites más en una altura similar y procesarlos de golpe.

En el caso de Usagi Yojimbo, la idea de los timers es confusa al principio pero si lo pensáis es bastante ingeniosa. Existen 4 personajes en pantalla, que tienen dos sprites de ancho y 3 de alto (6 en total). Cada personaje tiene su timer, que se programa para avisar del momento en el que hay que actuailizar la posición Y del sprite. Es totalmente equivalente a lo que se suele hacer con Raster, pero al ser 4 fuentes independientes de interrupción, no hay que preocuparse de la relación entre ellas. Es decir, cada timer actualiza a su personaje en función de su posición Y en pantalla, sin importarle de en qué posición estén los otros 3. Con interrupciones de raster como os comentaba antes, se hace mucho más lío.

Sin embargo la técnica anterior no soluciona el tema de las transiciones rápidas (la problemática es igual). Pero otra cosa grandiosa de este juego (copiado en Altered Beast y Double Dragon 3) es la "copia on the fly de sprites intermedios". Imaginad que el personaje de Usagi está compuesto por los siguientes sprites:

AB
CD
EF

Queremos asignar el Sprite hardware 0 a la columna ACE, y el 1 a la columna BDF. Para simplificar nos centramos en la parte izquierda (ACE). Tenemos que pintar el sprite 0 en la posición A, y luego actualizar su posición 21 pixels para abajo y actualizarlo a C. Luego repetir lo mismo de C a E. Para evitar la problemática de la transición tan abrupta, hace lo siguiente:

- Los sprites no están directamente alojados en el banco del VIC sino que se almacenan (por cierto, comprimidos) en otra zona de memoria. Para pintar A,C,E habría que copiar dichos sprites al banco gráfico (copiar 3*63 bytes). En el caso de Usagi, además hay que descomprimirlos... Todo ello en tiempo real, creo que a 25 fps.

- En lugar de copiar los 3 sprites A,C,E "a pelo", lo que se hace es copiar 5 sprites. 2 de ellos son transiciones generadas "on the fly" que tienen la mitad superior (10 filas) del sprite superior, y 11 filas del inferior:

A
A/C
C
C/E
E












El timer no programa 3, sino 5 interrupciones para actualizar el sprite: A->A/C->C->C/E->E

¿Qué se consigue con ésto? Cuando llegan las transiciones de un sprite a otro, al estar los personajes casi todos a la misma altura se acumulan las IRQ. TEned en cuenta que son 2 sprites por personaje y 4 timers. Perfectamente puede ocurrir que tengas que actualizar los 8 sprites a la misma altura, y que cuando vayas por el 5 el raster que pinta la pantalla ya esté bastante por debajo de la zona de transición.

Al habilitar estas transiciones, se da un margen de 10 líneas para cambiar el sprite de valor. Cuando el raster pasa de pintar A a A/C, te puedes adelantar y cambiarlo mucho antes de la transición porque el contenido de las 10 últimas filas de ambos es igual.

De este modo se puede "apilar" varias veces un mismo sprite en el eje Y sin tener el más mínimo glitch ni flicker. Por supuesto, la contrapartida es CPU (copia de sprites en tiempo real) y memoria adicional para almacenar las transiciones.

Este mismo esquema se usa en DD3 pero sin compresión.  Fijaros que al hacer copia "on the fly", solo hace falta definir los sprites en una dirección X. Si el personaje se da la vuelta, al copiar se invierten los bytes en tiempo real. De este modo ahorras mucho espacio para tener más frames.

 ;)
« última modificación: Diciembre 10, 2015, 21:05:18 por Carlos »

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1008
  • SYS 8*4096
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #1 en: Diciembre 10, 2015, 16:34:02 »
Creo que lo pillo... MENTIRA!!  ;D

Interpreto que actualiza la imagen acompasando el raster y colocando los 8 sprites de la parte superior, después la media 8 sprites más  y acabando con la inferior y sus correspondientes?.

Los prites se "pisan" (cada uno tiene las 10 lineas del sprite inferior) para eliminar los saltos y hacer la superposición casi invisible

Es un resumen MUY resumido para intentar comprenderlo un poco.

« última modificación: Diciembre 10, 2015, 16:36:48 por Maniako »
LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.

Zub

  • Desarrolladores
  • Commodoremaníaco
  • ******
  • Mensajes: 150
  • SYS 0
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #2 en: Diciembre 10, 2015, 17:12:14 »
Estoy viendo que mi post ha quedado bastante denso y lioso...

Imagina que quieres pintar a un personaje compuesto por dos sprites contiguos en el eje Y. Uno para torso y otro para piernas (Double Dragon, etc):

A
B

Si queremos usar el mismo sprite hardware multiplexado, tenemos que pintar A y luego programar una interrupción para "bajarlo" 21 pixels y cambiarle el frame a B. Para ello la interrupción tiene que ser super ajustada: Justo cuando el raster acaba de pintar la última línea de A, pero antes de que empiece a pintar la primera de B. Si te retrasas, en lugar de pintar primeras líneas de B serán las de A (saldría "el pelo" del personaje en el pubis). Si te adelantas, saldrían las primeras líneas de B en mitad de A (el pubis a la altura del pecho).

Para que quede "clavado" habría que hacer el cambio en los pocos ciclos de raster que hay entre que se acaba de pintar A y se empieza B. Si tienes un único personaje y nada más cambia, se podría hacer con una interrupción estable. Sin embargo, si por ejemplo estás en una badline (depende del scroll Y de la pantalla) se te retrasaría (al haber menos ciclos). Además, si tienes más sprites en las inmediaciones, te van a quitar ciclos y harán que tu IRQ se adelante o retrase en función de cuando le toque hacer el cambio -> chungo.

Sin embargo si pre-calculo y añado un sprite auxiliar A/B tal y como explicaba antes... Si realizo una interrupción que pase de A a A/B, si la hago durante cualquiera de las 11 últimas líneas de A no voy a notar nada porque los datos gráficos son iguales. Estoy cambiando el sprite pero el resultado en pantalla es el mismo (durante la mitad inferior). Como tengo 10 líneas de margen para hacer la transición, aunque mi IRQ llegue tarde, no va a pasar nada. Si la hago en la línea 11, funciona y me sobra tiempo. Si lo hago en la línea 21 (peor caso) sería equivalente a cuando no ponemos transición (interrupción "abrupta") y habría el mismo riesgo.


Luego se hace lo mismo con A/B->B.





« última modificación: Diciembre 10, 2015, 17:25:21 por Zub »

josepzin

  • Administrador
  • Commodore Master
  • *****
  • Mensajes: 13630
  • Commodoreador web
    • Ver Perfil
    • Mi blog
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #3 en: Diciembre 10, 2015, 17:13:35 »
Uff, tengo que leerlo de nuevo a ver si lo entiendo!
www.retroinvaders.com | www.commodoreplus.org  | josepzin.blogspot.com

riq

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 567
    • Ver Perfil
    • From the C64 until today, a developer's perspective
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #4 en: Diciembre 10, 2015, 17:30:32 »
Muy bueno!

Zub

  • Desarrolladores
  • Commodoremaníaco
  • ******
  • Mensajes: 150
  • SYS 0
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #5 en: Diciembre 10, 2015, 17:43:16 »
Añado imágenes que espero valgan más que 1000 palabras!

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1008
  • SYS 8*4096
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #6 en: Diciembre 10, 2015, 17:52:35 »
No dudo de que estará perfectamente explicado y algo he pillado, pero algunos somos algo lentos ;)

Riq lo ha pillado a la primera. Está claro que me tengo que poner algo más en serio en estos temas.

Encantado estoy de ver explicaciones sobre técnicas de multiplexación. Quieras que no, algo vas sacando y cuando rellene los huecos que ahora me faltan , de repente veré la luz.
LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.

Zub

  • Desarrolladores
  • Commodoremaníaco
  • ******
  • Mensajes: 150
  • SYS 0
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #7 en: Diciembre 10, 2015, 17:58:47 »
Maniako, es un puto lío y para escribirlo mismamente me he tenido que estrujar el coco y editarlo 20 veces.

Lo que pasa es que yo en su día pude meter un montón de horas para analizar el código y experimentar para ver qué demonios estaba haciendo... Luego en Lemon hubo algún experto que reconoció la técnica y arrojó algo de luz...

riq

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 567
    • Ver Perfil
    • From the C64 until today, a developer's perspective
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #8 en: Diciembre 10, 2015, 18:28:36 »
Las imagenes que acabas de agregar ¿estan bien? Lo que no entiendo es porque los sprites de transición estan al revez. Por ejemplo en A/C, la parte de arriba es la cabeza, y la parte de abajo es el pelo. ¿No tendría que ser al reves? ¿o me perdí de algo?

La otra cosa que estaría bueno saber, es como programa los timers. ¿Reprograma el timer 3 veces por personaje? ¿como hace cuando tiene 4 personajes? ¿Tenes el código de eso? Gracias!
« última modificación: Diciembre 10, 2015, 18:42:57 por riq »

Zub

  • Desarrolladores
  • Commodoremaníaco
  • ******
  • Mensajes: 150
  • SYS 0
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #9 en: Diciembre 10, 2015, 18:48:45 »
Están rippeadas directamente de la memoria del juego ;)

Creo que la confusión es por un detalle importante que se me ha olvidado. Si cambias la posición Y de un sprite mientras se está pintando, ésto no tiene efecto hasta que se ha pintado entero. Pero sí se puede cambiar el "frame" del sprite a mitad.

Si te fijas es coherente con mi "intento de explicación":

El sprite A son las orejas de Usagi.

El sprite A/C tiene la mitad inferior igual que el A, y la mitad superior es "nueva".

Imagina que cuando se ha pintado la mitad del sprite A, cambio al frame A/C y actualizo su posición 21 pixels para abajo. El raster sigue pintando el sprite (faltan 10 líneas de la posición Y original) y durante 10 líneas pinta los datos de A/C, que son lo mismo (esas líneas son iguales que A).

Cuando ya se ha pintado el primer sprite (21 líneas mezcla entre A y A/C) el VIC pinta de nuevo el sprite en su nueva posición Y que es justo la siguiente línea. Durante las 10 primeras líneas, pinta el frame actual (A/C) que tiene la mitad de la cabeza de Usagi.

¿Me sigues?


riq

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 567
    • Ver Perfil
    • From the C64 until today, a developer's perspective
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #10 en: Diciembre 10, 2015, 19:21:31 »
Si, gracias, tiene sentido! Tengo que hacer alguna prueba para que se me grabe, pero creo que lo entendí bien.

Lo que me gustaría saber un poco más es como hace con los interrupciones.
Vos mencionaste que usa 4 timer interrupts. Si entendí bien usa:
- CIA1 Timer 0 para el personaje 0
- CIA1 Timer 1 para el personaje 1
- CIA2 Timer 0 para el personaje 2
- CIA2 Timer 1 para el personaje 3

Y reprograma los timers constantemente ¿es algo asi? Gracias!

Zub

  • Desarrolladores
  • Commodoremaníaco
  • ******
  • Mensajes: 150
  • SYS 0
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #11 en: Diciembre 10, 2015, 20:52:31 »
En el caso de Usagi Yojimbo se usan los timers para hacer interrupciones en posiciones específicas del raster.

Por ejemplo para pintar el sprite A en la posición Y de la pantalla se programan los registros al principio del frame (línea del raster = 0). Luego hay que programar una interrupción en la línea 10 del sprite. Para ello se programa el timer para que interrumpa justo en el momento en el que el raster ha barrido hasta esa línea (desde la 0, hasta la Y+10). Luego lo mismo para la siguiente interrupción, etc.

Los valores del timer se ajustan mediante prueba y error, hasta dar con las constantes adecuadas. Como hay 4 timers, se puede hacer el proceso cuatro veces, usando como parámetro las cuatro posiciones Y de los personajes.

Si hubiera más personajes, este sistema no valdría. Habría que usar las interrupciones de Raster, precalculando cuántas hay que hacer, en qué orden y en qué posición...

riq

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 567
    • Ver Perfil
    • From the C64 until today, a developer's perspective
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #12 en: Diciembre 10, 2015, 21:14:30 »
Ok. Gracias!

R. INTERNATIONAL

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 667
  • THE NEW IRON AGE HAS COME!!
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #13 en: Diciembre 10, 2015, 22:37:19 »
  Buff!!,..vaya hilo!, interesantisimo y denso, incluso solo en la primera respuesta que he lo encabeza ya he alucinado con cosas que no sabía de como opera la Maquina,....necesito tiempo para digerirlo,..pero es la leche.

 

Maniako

  • Desarrolladores
  • Commodore Master
  • ******
  • Mensajes: 1008
  • SYS 8*4096
    • Ver Perfil
Re:Técnica de multiplexación Usagi Yojimbo
« Respuesta #14 en: Diciembre 11, 2015, 10:28:28 »
Lo cierto es que es algo enrevesado.

Pero es una solución original a un problema y muy decentemente ya que he estado mirando el juego y no se aprecia flickeo alguno.

LDA #$50
STA $0400
RTS
Lloré cuando conseguí hacer esto con el monitor del FC1.