Música ralentizada

By Visualedu

Resident (33)

Visualedu's picture

19-02-2019, 13:26

Hola, tengo un problema. Resulta que en la función ISR (IM 2), en determinadas fases del juego, tarda demasiado en finalizar y se pierde la siguiente llamada a la función ISR (porque están deshabilitadas las interrupciones mientras se ejecuta la función ISR).
Esto genera unas ralentizaciones que no me importan demasiado gráficamente pero sí en cuanto a la música.
En estos momentos la música se ralentiza y queda muy raro.
Yo la verdad veo como única solución aliviar la carga de la función ISR pero, como aquí hay gente que sabe mucho,
¿hay alguna otra técnica para conseguir oir la música correctamente en estos casos?

Gracias

Login or register to post comments

By Juan Luis

Resident (46)

Juan Luis's picture

23-02-2019, 03:09

Hola Visualedu,
durante la ejecución normal del programa debes preparar en un buffer de memoria la información que le tendrás que pasar al VDP y al chip de sonido durante la interrupción. En el caso del chip de sonido, se suele enviar valores a determinados registros. Podrías tener un buffer así:

isr_port ds 16
isr_sound_regs ds 16
isr_sound_values ds 16
isr_num_orders db 0

Durante la ejecución ir almacenando en estos buffers, el número del puerto, el número del registro y el valor. Ejemplo:
isr_port[isr_num_orders] = 0x7E ; Wave port
isr_sound_regs[isr_num_orders] = 0x68 ; KEYON-DAMP-LFORST-CH-PANPOT
isr_sound_values[isr_num_orders] = valor que sea
isr_num_orders++

Luego durante la ejecución de la interrupción:
for (int i = 0; i < isr_num_orders; i++) {
out(isr_port[i], isr_sound_regs[i]); // Enviar al puerto de registro
out(isr_port[i]+1, isr_sound_values[i]); // Enviar al puerto de datos
}

La música es predecible. Durante la ejecución del programa se sabe cuál va a ser el siguiente evento musical que sucederá. Prepara la información que se debe enviar al dispositivo durante la ejecución del programa, sobre todo si hay que hacer cálculos, y luego envía toda la información al dispositivo durante la interrupción, mediante buffers y/o colas de datos.

By Manel46

Champion (417)

Manel46's picture

23-02-2019, 15:59

¿Por que usas IM2? ¿Quizas para disponer de la página 0 de ram?
Mi experiencia es que este modo de interrupción, si produce retardos en la música.
Mi conclusión es que se puede usar la ram de la página 0, con las interrupciones IM1 mediante el parche que haga falta en #38, para llamar a los ganchos en la ram del sistema. Ganchos que mantienen a la música, los FX, o lo que sea.

By Visualedu

Resident (33)

Visualedu's picture

26-02-2019, 00:21

Hola, gracias por responder.
este proyecto lo estoy desarrollando en ensamblador. Estoy creando una rom de 48k (deshabilito la bios pasando la página 0 al slot de la rom).
Uso el player de SapphiRe (la verdad, es el primero que implemento, lo ví en un video de Fernando García y hasta ahora iba sin problemas).

Uso el modo IM2 porque es un juego con una gran cantidad de elementos y necesito ahorrar recursos para poder enviar el máximo de bytes al VDP en los VBlank. (tengo entendido que para esto el modo IM2 es el mejor, correjidme si no fuese así).

En la función ISR, lo primero que hago es llamar a la rutina del player (y de otro reproductor de sonidos)

call PT3_ROUT ;envia los datos a los registros del PSG
call PT3_PLAY ;calcula el siguiente 'trocito' de musica que sera enviado la proxima vez
call ayFX_PLAY ;calcula el siguiente 'trocito' de efecto especial de sonido que sera enviado la proxima vez

Sin embargo, en cuanto paso de un número de bytes que debo pasar al VDP la música empieza a tardar el doble (se está saltando interrupciones del VDP).

He hecho una prueba, en la función ISR habilito las interrupciones nada más ejecutarse las rutinas de sonido y en una variable almaceno si se ha ejecutado hasta el final.
En la función ISR pongo el condicional que se tras la ejecución de las rutinas de sonido dicha variable está a 0 que termine ya la ejecución (en este caso la función ISR simplemente ha servido para ejecutar dichas rutinas ).

El resultado ha sido que la música funciona correctamente y que, de vez en cuando me aparece un tile mal pintado (seguramente porque como tento las interrupciones habilitadas se ha llamado cuando estoy ejecutando 'in' ó 'out' ).
Tras esto he protegido las secuencias de 'in', 'out' deshabilitando y habilitando tras

di ;Deshabilito las interrupciones

ld a,l
out (#99),a
ld a,h
add a,64
out (#99),a

ei

Acabo de hacer una prueba con un resultado bastante aceptable. habilito las interrupciones tras las rutinas de música y sonido y marco en una variable si el última isr se ejecutó completamente

By Visualedu

Resident (33)

Visualedu's picture

26-02-2019, 00:27

he enviado el post sin terminarlo (y mira que es largo Smile )
Este tema me está rayando un poco, ¿estoy solapando llamadas a la función ISR? Es la única explicación que le veo, pero, si fuese así no me explico cuando se ejecuta el grueso de la lógica. (¿un ciclo para la lógica y el otro para una ISR demasiado larga?) Crazy

By Manel46

Champion (417)

Manel46's picture

26-02-2019, 17:38

Tan bien usé el replayer de SapphiRe, para PT3 y FX, en Mr. Balloon, con la bios presente en este caso.
Pienso que quizás abuses de la inhibición de interrupciones (DI), en rutinas largas.
Son muy ilustrativos los vídeos de Fernando y de SapphiRe, sobre interrupciones.

By Juan Luis

Resident (46)

Juan Luis's picture

27-02-2019, 15:23

¿Cómo sincronizas la música, es decir, quién dispara la interrupción?, ¿el VDP al alcanzar el VBlank o un Timer del chip de sonido?

Si usas la interrupción del VBlank deberías tener un flag que indique que hay eventos musicales pendientes de procesar y procesar las llamadas a las rutinas que calculan el siguiente trozo, call PT3_Play y call ayFX_Play, fuera de la interrupción durante el barrido. El flag sería activado durante la ISR inmediatamente después de que en la ISR se envíen los datos vía out's al chip de sonido.

Si utilizas un timer del chip de sonido para que dispare la interrupción cada cierto tiempo, pienso que tu código es correcto y que no puedes hacer mucho más.

By Visualedu

Resident (33)

Visualedu's picture

02-03-2019, 16:43

Sincronizo con el VDP (VBlank).
Sí, estoy usando un flag y lo estoy activando en la función ISR tras la ejecución de las rutinas de sonido.
De esa manera la función ISR siempre llama a las funciones relacionadas con el audio y después, en función del flag continúa o finaliza.
La verdad es que el resultado me ha sorprendido, funciona bastante bien (en openMSX, me toca probarlo en un MSX de verdad).
He subido una prueba a youtube con balas masivas y las mueve relativamente bien y, el sonido va perfecto Big smile
MSX 1, demo balas masivas

By Juan Luis

Resident (46)

Juan Luis's picture

07-03-2019, 20:07

Ha quedado muy bien. Aunque las balas son solo puntos, hay mogollón de elementos móviles en pantalla, cuyas posiciones tiene que procesar el Z80. Y la música suena impecable.