Commodore manía

Commodore 64 => Desarrollo => Mensaje iniciado por: Zub en Diciembre 10, 2015, 15:50:16

Título: Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub 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

(http://s22.postimg.org/6b9vnisj1/usagi.png) (http://postimage.org/)

(http://s22.postimg.org/vvc5tydwt/usagi2.png) (http://postimage.org/)

(http://s22.postimg.org/neh8wrylp/usagi3.png) (http://postimage.org/)

(http://s22.postimg.org/hrkvzaw31/usagi4.png) (http://postimage.org/)

(http://s22.postimg.org/chfx80bu5/usagi5.png) (http://postimage.org/)


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.

 ;)
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Maniako 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.

Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub 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.





Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: josepzin en Diciembre 10, 2015, 17:13:35
Uff, tengo que leerlo de nuevo a ver si lo entiendo!
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: riq en Diciembre 10, 2015, 17:30:32
Muy bueno!
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub en Diciembre 10, 2015, 17:43:16
Añado imágenes que espero valgan más que 1000 palabras!
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Maniako 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.
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub 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...
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: riq 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!
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub 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?

Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: riq 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!
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub 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...
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: riq en Diciembre 10, 2015, 21:14:30
Ok. Gracias!
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: R. INTERNATIONAL 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.

 
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Maniako 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.

Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub en Diciembre 11, 2015, 11:28:05
Es muy complejo pero efectivamente garantiza ausencia total de flicker. Podéis comprobar lo mismo en Double Dragon 3 o Altered Beast.

En el Green Beret, que usa un multiplexer "clásico" pero muy efectivo, prácticamente no hay glitches. Pero si os fijáis, cuando disparas el lanzallamas o hay balas y varios enemigos a la vez (muchos sprites a la misma altura) entonces si se nota.
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: josepzin en Diciembre 11, 2015, 12:37:23
Tendría que leer bien la explicación para intentar entenderlo, pero a ver si me aclarais esta duda conceptual básica:

Si tengo más de 8 sprites en linea ¿cómo es posible que no haya parpadeo??
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Maniako en Diciembre 11, 2015, 13:07:09
Si tengo más de 8 sprites en linea ¿cómo es posible que no haya parpadeo??

Por lo mismo que me pasaria a mi.
Me quedaria con los ojos como platos mirandolo  ;D
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub en Diciembre 11, 2015, 14:43:04
Es físicamente imposible que haya más de 8 sprites en la misma línea.

Lo que se puede hacer es pintar 8 en una línea Y, y más abajo (Y+21 líneas, el tamaño de de un sprite) volverlos a pintar, y de paso cambiar todas sus características: posición X, color, frame, etc.

En un juego tipo Armalyte o Commando, los sprites están "diseminados" por toda la pantalla con diferentes alturas Y. En ese caso, mientras controles que no coincidan más de 8 en la misma Y, es relativamente fácil multiplexarlos. Lo difícil es cuando se amontonan muchos sprites en filas contiguas (Y, Y+21, Y+42).

Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Almighty God en Diciembre 11, 2015, 20:16:05

 Hola

 Realmente Crossbow demostro que se pueden poner nueve...

 http://csdb.dk/release/?id=48577

 Y el record con técnicas de multiplexado... 144

 http://csdb.dk/release/?id=2968

 ;) Pero en juegos es otro cantar...
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: josepzin en Diciembre 12, 2015, 04:32:18
Los 144 sprites me imagino que es la parte de las letras en toda la pantalla, tremendo.

Los 9 sprites en linea no me doy cuenta en que parte, estas intros hacen tantas cosas increibles que 1 sprite más ni me doy cuenta.
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Jeff en Diciembre 12, 2015, 14:39:13
R Tape Loading error
Título: Re:Técnica de multiplexación Usagi Yojimbo
Publicado por: Zub en Diciembre 12, 2015, 21:10:50
Los 144 sprites me imagino que es la parte de las letras en toda la pantalla, tremendo.

Los 9 sprites en linea no me doy cuenta en que parte, estas intros hacen tantas cosas increibles que 1 sprite más ni me doy cuenta.

Wow! Esto no lo conocía!

Por lo que leo, se puede hacer el truco con el sprite 0 y sólo en una de cada dos rasterlines. Es el "3" de las letras de abajo