martes, 8 de septiembre de 2009

PT3 a 60Hz

Hola:

Para aquellos que hayáis trabajado con el PT3, os habréis dado cuenta del hecho de que el editor nos permite componer a 50Hz, mientras que algunos MSX van a 60Hz. Esto hace que las canciones se aceleren al ser reproducidas en dichas máquinas con el consiguiente mosqueo por parte del músico ;)

En los MSX2 y superiores se puede modificar la velocidad de refresco del VDP mediante el bit 1 del registro R#9 del VDP. Si dicho bit está a 1, la velocidad de refresco será de 50Hz y si está a 0 de 60Hz. Con lo cual en un siempre podemos forzar la velocidad que nos interese y problema resuelto.

Sin embargo, en los MSX1 no podemos hacer esto, ya que su VDP no permite seleccionar la velocidad de refresco. Afortunadamente los diseñadores del sistema lo previeron y en la BIOS existe un byte (según la BIOS es el ID Byte 1) que nos indica, entre otras cosas, la velocidad de refresco de la máquina. Dicho byte está en la posición $2B y el bit que nos interesa es el de más valor. Si el bit está a 1 significa que el refresco va a 50Hz y si es 0 a 60Hz. por compatibilidad, dicho byte está presente en todas las BIOS.

Para homogeneizar, yo lo que hago es copiar dicho byte a RAM bajo la etiqueta IDBYTE1 y si en un MSX2 modifico el refresco, realizo el cambio para que en IDBYTE1 siempre esté el valor correcto de la frecuencia. Así, bastaría con hacer:

ld a,[IDBYTE1]
and 128

para saber la frecuencia. Si se activa el flag Z estamos a 60Hz y si se activa NZ estaremos a 50Hz.

Bien, una vez que tengamos el valor de IDBYTE1 correcto (bien sea porque lo hemos leído de la BIOS o porque hemos cambiado la frecuencia y corregido su valor), podemos solucionar el problema de la reproducción del PT3 de forma automática para cualquier MSX.

La solución consiste en dividir la reproducción de la canción en grupos de seis frames. En los cinco primeros tocaremos la canción de forma normal, mientras que en el sexto replicaremos los valores generados por el PT3 en el frame anterior. De esta forma las canciones se reproducirán a la misma velocidad a la que han sido compuestas, con independencia de la velocidad de refresco de la máquina.

Para ello necesitaremos una zona de 14 bytes en RAM referenciada mediante la etiqueta AYREGS_BAK y un contador (de tamaño byte) referenciado por la etiqueta PT3_60_50.

Lo que haremos será crear una nueva rutina llamada PLAYMUSIC que enmascarará la llamada al PT3. Dicha rutina será la encargada de realizar la copia y restauración de los registros del PSG cuando sea necesario.

Para ello, en la inicialización de la música (después de llamar a PT3_INIT) deberemos inicializar el contador a 6 si estamos funcionando a 60Hz:

INIT_PT3_60_50:
ld a,[IDBYTE1]

and 128
ret nz
ld a,6
ld [PT3_60_50],a
ret

Como véis, si estamos a 50Hz, el contador no se inicializa. A continuación veamos la rutina PLAYMUSIC:

PLAYMUSIC:
ld a,[IDBYTE1]
and 128
jp nz,PT3_PLAY
ld a,[PT3_60_50]
dec a
ld [PT3_60_50],a
jp z,@@RESTORECOPY
call PT3_PLAY
ld hl,AYREGS
ld de,AYREGS_BAK
ld bc,14
ldir
ret
@@RESTORECOPY:
ld a,6
ld [PT3_60_50],a
ld hl,AYREGS_BAK
ld de,AYREGS
ld bc,14
ldir
ret

La rutina es bastante sencilla. Comienza comprobando la velocidad de refresco y si es 50Hz llama directamente a PT3_PLAY y vuelve. Si es 60Hz, decrementa el contador PT3_60_50. Si dicho contador ha llegado a 0, vamos a @@RESTORE_COPY, donde reinicializamos el contador a 6 y restauramos la copia de los registros del PSG que habíamos hecho.

Si, por el contrario, aún no hemos llegado a cero, llamamos a PT3_PLAY y realizamos una copia de seguridad de los registros por si en el siguiente frame es necesaria (para optimizar se podría hacer sólo si el valor del contador es, exactamente, 1).

Con esta nueva rutina, sea cual sea el modelo de MSX en el que estemos y siempre que el valor de IDBYTE1 sea el correcto, todas las canciones PT3 que reproduzcamos sonarán igual que cuando se compusieron y así nos evitaremos las broncas de los músicos, jejeje :D

No hay comentarios: