domingo, 30 de septiembre de 2012

MSX2: arranque a 60hz

Pep Alacant, un apasionado a lo retro (MSX incluido) de Alicante, me comentó que le fastidiaba que su 8235 arrancase por defecto a 50hz, ya que le encanta jugar a 60hz, para lo cual tenía que usar una flashrom y no podía jugar con sus originales.

El caso es que dispone de las herramientas necesarias para volcar el contenido de los chips que almacenan la BIOS, así que me envió los archivos de las ROMS de su propio ordenador y me puse a ver qué modificaciones había que hacer para que el ordenador arranque por defecto a 60hz.

Si tenéis un lector/grabador de eproms, podéis hacerlo vosotros mismos volcando la MainRom y la ExtRom, haciendo las modificaciones que os indico y grabando los ficheros en los chips necesarios. Pep ha utilizado un 27256 para la MAINROM (32Kbytes) y un 27128 para la EXTROM (16Kbytes), aunque eso puede variar según el MSX que tengáis.

De todas formas, mi consejo es que probéis primero en un emulador para comprobar que todo sigue funcionando como es debido antes de volcar los ficheros a los chips y probar en el MSX real. Haced esto bajo vuestro propio riesgo, ya que si ponéis unos chips que no sean adecuados podéis cargaros el MSX.

Otra advertencia más: las direcciones de memoria que voy a indicar (salvo la primera, que es fija para todos los MSX) pueden variar entre una BIOS y otra, aunque supongo que no habrá muchísimas diferencias.

Cambios en la MAIN ROM


En primer lugar, hay que poner a 0 el bit de mayor peso del byte situado en $002B. Esto ya lo comenté hace algún tiempo cuando hablé del PT3 a 60hz. Ese es el IDBYTE1 de la BIOS y es donde los programas deben mirar para saber la frecuencia por defecto de la BIOS.

Tras esto, hay que buscar tres puntos en los que la BIOS escribe (de diferente forma en cada uno de ellos) un valor en el registro R#9 del VDP, que es el que controla la frecuencia. Una BIOS PAL por defecto escribe $02 en ese registro, activando el bit 1 le dice al VDP que debe funcionar a 50hz. Lo que hay que hacer es que escriba $00, con el bit 1 desactivado y diciéndole así al VDP que se ponga a 60hz.

El primer punto donde la BIOS escribe en el R#9 es la dirección $7BD6 en la que podemos encontrar el siguiente código:

$7BD6: ld a,$02
       out [$99],a
       ld a,$89
       out [$99],a

Literalmente este código escribe $02 en el R#9. Así pues basta con cambiar el $02 situado en $7BD7 por un $00 y ya habremos hecho todos los cambios en la MAIN ROM.

Cambios en la EXT ROM


La EXT ROM escribe en el R#9 en dos sitios: uno justo antes de presentar el logo y otro justo antes de saltar al BASIC o al programa que tenga el cartucho. Así que vamos a ver qué hace en esos puntos.

El primero de los puntos es $2B40, que es donde la BIOS nos muestra el consabido logo MSX subiendo. El código de esta parte es el siguiente:

$2B40: ld b,8
       ld hl,$2B4F
$2B45: ld d,[hl]
       inc hl
       ld e,[hl]
       inc hl
       call $2AC2
       djnz $2B45
       ret
$2B4F: .db $00,$80,$01,$20,$08,$2A,$09,$02,$02,$1F,$05,$F7,$0B,$00,$06,$0E

Y el código en $2AC2 es:

$2AC2: push bc
       push af
       di
       ld c,$99
       out [c],e
       ld a,d
       or $80
       ex [sp],hl
       ex [sp],hl
       out [c],a
       ei
       pop af
       pop bc
       ret

Es decir, en $2AC2 está volcando al registro del VDP contenido en d el dato contenido en e. Si miramos el código situado en $2B40, vemos que en $2B4F hay una tabla de 8 pares de bytes: registro-valor. Miramos cual es el valor que se escribe en el registro 9 y comprobamos que es $02. Lo cambiamos por $00 y el logo de MSX ya aparecerá a 60hz.

El último punto donde se escribe en R#9 es el momento en el que la BIOS cede el control al BASIC o al cartucho que tengamos pinchado. En este caso lo hace en la dirección $06CA cuyo código vemos a continuación:

$06CA: push af
       push bc
       push de
       push hl
       di
       xor a
       out [$99],a
       ld a,$91
       out [$99],a
       call $1034
       ld hl,$f3df
       ld b,$08
$06DE: ld a,[hl]
       inc hl
       out [$9b],a
       djnz $06de
$06E4: ld hl,$FFE7
       ld b,$10
$06E9: ld a,[hl]
       inc hl
       out [$9b],a
       djnz $06e9
       ei
       pop hl
       pop de
       pop bc
       pop af
       ret

A la vista del código, vemos que lo primero que hace es inicializar a 0 el registro R#17 ($11 en hexadecimal) del VDP. Este registro es un registro índice, que apunta al registro del VDP donde se va a volcar los datos que pasemos mediante OUT al puerto $9B. Además, con cada OUT se incrementa permitiendo realizar un volcado masivo de datos a los registros del VDP mediante OUTs sucesivos al puerto $9B.

La llamada a $1034 realiza una espera activa hasta que se produzca un nuevo blanqueo vertical, comprobando el flag de retrazado vertical presente en el registro de estado 2 del VDP, pero como se sale del propósito de este post, no hablaré más de ella.

Bien, para que el parcheo funcione, lo que hay que hacer es modificar la tabla de datos de la que la BIOS toma los valores a volcar y así poner un $00 en R#9. Si nos fijamos, vemos que la BIOS está leyendo los datos desde RAM, concretamente desde la copia de los registros del VDP que se guarda en RAM ($F3DF para los registros MSX1 y $FFE7 para los de MSX2 y superiores). Así pues aquí no podemos hacer nada, tendremos que buscar la rutina que vuelca la tabla de ROM a RAM para modificarla adecuadamente.

Dicha rutina se encuentra en $0336 y el código es el siguiente:

$0336: ld hl,$29F6
       ld de,$F3DF
       ld bc,$0008
       ldir
       ld de,$FFE7
       ld bc,$0010
       ldir
$0349: xor a
       ld [$FAF5],a
       ld [$FAF6],a
...

Con lo cual la tabla está en $29F6 vamos a esa dirección y substituimos el byte de la dirección $29FF (el décimo byte, correspondiente al valor que se va a volcar en R#9) que resulta ser un $02 por un $00. Probamos esta BIOS modificada y veremos que hemos conseguido que nuestro MSX arranque a 60hz tanto el BASIC como los cartuchos. ¡Prueba superada!

¿Y si ahora quiero que arranque a 50hz?


Vale, si ahora quisiéramos arrancar a 50hz podemos volver a deshacer todos los cambios o trabajar un poco más.

La idea que se me ocurrió fue mantener pulsada una tecla para que la BIOS cambiase a 50hz justo antes de saltar al BASIC o al cartucho. Para facilitar el trabajo busqué una tecla que se sitúe en el bit 1 de las filas de la matriz de teclado. Podía ser "1", "9", "F5", "CTRL"... y elegí "1".

A continuación parcheé la rutina que copia la tabla a RAM (la última que hemos visto) justo tras el segundo LDIR:

$0349: nop
$034A: call $3F00
       ld [$FAF6],a
...

Es decir, substituyo el XOR A y el LD [$FAF5],A por dos instrucciones que van a saltar a $3F00, que es un hueco que encontré en la parte superior de la EXT ROM. Allí metí el siguiente código:

$3F00: in a,[$AA]
       and $F0
       out [$AA],a
       in a,[$A9]
       cpl
       and $02
       ld [$FFE8],a
       xor a
       ld [$FAF5],a
       ret

El propósito del código es seleccionar la fila 0 de la matriz de teclado, leeerla, complementarla para que si hay alguna tecla pulsada se quede a 1 el bit correspondiente y quedarme con el bit 1 (el correspondiente a la tecla "1").

Si esa tecla se pulsa, el contenido del registro A en este punto será $02 y si no se pulsa será $00. Justo el valor que queremos (50hz y 60hz respectivamente) si se pulsa "1" o no se pulsa, así que lo copiamos en $FFE8 que es de donde se va a leer.

Luego ejecutamos las dos instrucciones que habíamos sobreescrito y devolvemos el control a la BIOS.

De esta forma tenemos un MSX2 que arranca nativamente a 60hz y si pulsamos "1" durante el arranque (antes de que salga el logo de MSX), cuando la BIOS ceda el control al BASIC o al cartucho que haya insertado, cambiará a 50hz.

Para finalizar (que ya iba siendo hora) aquí tenéis un vídeo que ha grabado Pep mostrando el resultado en su 8235.

No hay comentarios: