lunes, 27 de diciembre de 2021

Si trabajamos con un MSX2 o superior, tenemos a nuestro alcance un VDP 9938 o 9958, el cual nos permite cambiar por software la frecuencia de refresco de pantalla entre PAL (50hz) y NTSC (60hz). Simplemente leyendo la copia del registro adecuado del VDP podremos saber la frecuencia a la que está ajustado nuestro MSX y así obrar en consecuencia (por ejemplo, para ajustar la velocidad de reproducción de la música).

Sin embargo, en un MSX1 esto no es posible hacerlo así, ya que los VDP de los MSX1 tienen una frecuencia fija y no es posible cambiarla por software. Sí que es cierto que en la BIOS hay un byte que nos indica si el ordenador tiene un chip PAL o uno NTSC, por lo que consultando ese byte ya tenemos directamente la respuesta...

... ¿o puede que no?

Pues lo cierto es que... depende. Si nadie ha toqueteado el equipo, eso va a funcionar siempre. Pero puede darse el caso de que hayamos cambiado el VDP y ahora la BIOS y el VDP no estén de acuerdo. Esto me pasó, por ejemplo, cuando cambié el chip de uno de mis HX-10 de un 9929 a un 9928. La BIOS sigue diciendo que el MSX1 es PAL, pero el VDP dice que no, que es NTSC. ¡Y no hay forma de ponerlos de acuerdo!

Esto no sólo sucede en MSX. Por ejemplo, la Coleco tiene el mismo chip de vídeo que el MSX1, por lo que tenemos el mismo problema de averiguar la frecuencia. Aunque su BIOS también tiene un byte en el que se almacena la frecuencia (valor 50 para PAL y 60 para NTSC), es muy común que la gente haya instalado una BIOS diferente o cambiado el chip de vídeo. Por lo tanto no es extraño encontrarnos con un equipo en el que BIOS y VDP no estén de acuerdo. Y, aunque no tenga exactamente el mismo VDP que el MSX1 o la Coleco, también es interesante tenerlo en cuenta al programar para Sega Master System. Esta consola no tiene el mismo chip que el MSX1 o la Coleco, pero tiene uno que es compatible. Además, algunos modelos no tienen BIOS (bien sea porque no tenían o porque se les ha quitado) y como la frecuencia del chip tampoco es modificable por software, esta rutina vendrá muy bien en ese caso.

¿Y ahora qué hacemos? Pues no nos queda otra que averiguar por nuestros propios medios cuál es la frecuencia de refresco a la que está funcionando el equipo.

La forma de hacerlo es sencilla: hay que contar cuantas instrucciones pueden ejecutarse entre dos interrupciones vblank. Pero, ¡cuidado! Si tenemos activadas las interrupciones, el Z80 se va a ir a ejecutar el código de la interrupción (puedes ver MSX-Inside 5 para más detalles), por lo que hay que tener esto en cuenta. La solución pasa por desactivar las interrupciones VBLANK y comprobar de forma manual cuando cambia el bit adecuado del registro de estado del VDP (más detalles en MSX-Inside 6).

Por lo tanto, el proceso sería el siguiente:
  1. Desactivar interrupciones del VDP. En MSX y SMS se puede hacer con un simple DI, pero en Colecovision es necesario escribir un 0 en el bit 5 de R#1 para que el VDP no genere la interrupción, ya que en la Coleco las interrupciones del VDP son NMI.
  2. Inicializar un registro de 16 bits a 0.
  3. Eliminamos posibles interrupciones que estuvieran pendientes. Esto sirve para el extraño caso en el que se llegue a un VBLANK tras el primer paso y antes del siguiente, cosa que es difícil, pero no imposible. Simplemente tenemos que leer el registro de estado S#0 del VDP.
  4. Nos sincronizamos con el VBLANK. Para esto ahora tenemos que hacer pooling para esperar a que el bit 7 del S#0 pase de 0 a 1. Recordemos que cuando eso suceda:
    • Gracias al paso 1 no salta una interrupción.
    • Al leer S#0, el bit 7 vuelve a pasar de 1 a 0.
  5. Incrementamos el registro de 16 bits hasta que el bit 7 de S#0 vuelva a pasar de 0 a 1. Es un bucle casi idéntico al anterior, con la única diferencia de que incluye la instrucción que realiza el incremento del registro.
  6. Comparamos el valor obtenido en el registro de 16 bits con un umbral que nos permita distinguir entre 50hz y 60hz.
  7. Si el valor obtenido es mayor que el umbral, entonces estamos a 50hz, si es menor, estaríamos a 60hz. Esto es así porque a 50hz hemos ejecutado más veces el incremento entre VBLANK y VBLANK de lo que lo haríamos a 60hz.
  8. Volver a activar interrupciones del VDP, bien sea con un EI (MSX y SMS), o bien escribiendo un 1 en el bit 5 de R#1 (obligatorio en Coleco, pero valdría para las tres máquinas).
Para que no tengáis que andar programando (aunque es un buen ejercicio y no muy difícil), ya os traigo la rutina completamente hecha y probada, con valores de umbral tanto para MSX/Coleco como para Master System (aquí varía porque en este sistema no tenemos el ciclo extra de acceso a memoria para cada instrucción ejecutada). Encontraréis muchos comentarios, con instrucciones alternativas que están aquí comentadas. También trae algunos requisitos previos y rutinas complementarias que serán necesarias en Coleco, pero que pueden veniros bien para las tres máquinas.

Por último, una curiosidad. Resulta que en antiguas implementaciones, el One Chip MSX no era capaz de funcionar realmente a 50hz. Tú le decías al VDP que se pusiera a 50hz y a nivel software todo funcionaba bien, pero no así a nivel hardware. Así que tuve que recurrir a esta rutina (que funciona también en V9938 y V9958) para comprobar incluso que la frecuencia a la que se suponía había cambiado el sistema era la esperada o no.