sábado, octubre 14, 2006

Diferencias entre Timex Computer 2048 y Sinclair ZX Spectrum (Parte 2)

Amigos,

Esta es la segunda parte de mi artículo sobre las direncias entre el Timex Computer 2048 y el Sinclair ZX Spectrum. La primera parte trataba los 1) Los diferentes modos de video y 2) La sincronización de video mediante el empleo de IN(255).

Continuamos con:

3.- Lectura del puerto FEh (254)

El puerto FEh es utilizado para leer el teclado y el puerto EAR para carga desde cinta. En ambos casos se lee la información de salida de la ULA.

En el TC2048 sólo se puede usar el puerto FEh para estos fines, en el ZX Spectrum, en cambio, todos los puertos pares son direccionados hacia la ULA por lo que se puede ocupar cualquier valor múltiplo de dos para leer el puerto FEh.

Al hacer IN al puerto 254, se obtiene el siguiente octeto:


B7-E-B5-k4-k3-k2-k1-k0



Donde:

  • E=Bit del estado de EAR (entrada de audio para carga desde cinta)
  • K4-k3-k2-k1-k0: bits que entregan la fila del teclado escaneada.
  • B7 y B5: bits que dependen de la arquitectura del microcomputador.



Los bits que dependen de la arquitectura tiene los siguientes valores:


  • En el ZX Spectrum B5=1 y B7=1
  • En el TC2048 B5=0 y B7=0


Esta diferencia puede ocasionar problemas de compatibilidad en algoritmos de carga turbo o de velocidad superior.

Tal es el caso de las Ultracargas desarrolladas por Antonio Villena Godoy que requieren una versión especial para el TC2048. Ver artículo sobre ultracargas.

Otro caso emblemático es URIDIUM. La versión oficial no es compatible con el TC2048. Para hacerlo compatible basta cambiar un byte!!!

ORG 9AFD
LD C,0 ; En C deja las teclas presionadas
LD B,1FH ; Valor para enmascarar (sólo deja las teclas)
LD A,BFH ; Fila: Enter-L-K-J-H
IN A,(FEH) ; Lee puerto
CPL ; complementa (1 apretado, 0 no)
RRA ; Lo rota a la derecha y deja el valor de “Enter” en el flag de carrier
RL C ; Deja el valor de “Enter” en el bit 0 de C
AND B ; Enmascara los 5 últimos bits
CP A,1H ; Compara con uno. Pero en TC2048 uno de los bits diferentes se propago
; debido a la rotación de A. Para hacerlo compatible se hace:
; CP A,11H <— cambio en TC2048
CCF ; Complementa el flag de carrier (1 si está apretada “L”, o no)
RL C ; Pone el valor de “L” en el bit 0 de C, en el bit 1 está “Enter”.


La versión parchada para TC2048 la pueden descargar en este post.


4.- Diferencias en la ROM

La ROM del TC2048 es diferente a la ROM del ZX Spectrum. La diferencia es que durante la inicialización se cambia el modo de pantalla a 0, mediante la instrucción out 255,0.

Para esto se crea una rutina en la zona de SPARE de la ROM y se reemplaza el llamado al despliegue del mensaje (PO_MSG) por el llamado a esta rutina (que a su vez llama a PO_MSG).

ZX Spectrum:

RAM_SET:
0x1219
...
0X1295 AF XOR A
0X1296 113815 LD DE,1538H
0x1299 CD0A0C CALL 0C0AH,PO_MSG
...
SPARE:
0x386E FFFFFFFFFFF



TC2048:

RAM_SET:
0X1219
...
0X1295 AF XOR A
0X1296 113815 LD DE,1538H
0x1299 CD6E38 CALL 386EH,SPARE
...
SPARE:
0x386E D4FF OUT (255),A
0X3870 CD0A0C CALL 0C0AH,PO_MSG
0X3873 C9 RET


Problemas de compatibilidad: Para aquellas aplicaciones que utilizan los códigos FF en la zona de SPARE en las primeras direcciones.


Un truco que se utilizaba frecuentemente y que hacía uso de esta zona de memoria es como sigue:

En el modo de interrupción IM2 cuando se produce una interrupción se ejecuta la subrutina de atención de interrupciones en la posición de memoria indicada por: 256*I+[Contenido del bus de datos] y el byte siguiente.

I corresponde al registro I.

Estos dos bytes se conocen como el vector de interrupciones.

Dado que el ZX Spectrum (o el TC2048) no contiene el hardware para poner un byte en el bus de datos en estas condiciones, este valor es siempre FFh. Por lo tanto la subrutina se ubica en las direcciones apuntada por:

256*I+255 y 256*I+256.


Lamentablemente si existe un periférico adicional este podría poner un dato en el bus de datos diferente a 255, es por esto que las aplicaciones más avanzadas utilizaban la siguiente técnica para asegurarse que la rutina de atención de interrupciones fuera llamada independiente del contenido del bus de datos:

Estos programas contenían una tabla de 257 posiciones de memoria comenzando en 256*I+0 que contenían el mismo valor: FFh. Entonces independiente del valor del bus de datos se lee la dirección FFFFh.

En la dirección FFFFh se pone el valor 18h equivalente a la instrucción JR. El siguiente valor leído es el contenido de 0000h (ROM) que corresponde a F3h (DI). Por lo tanto se realiza un salto equivalente a JR FFF4h. En esta posición (FFF4h) se pone un JP a la rutina real de atención de interrupciones.

Para ahorrase esta tabla, algunos programas usan la ROM. Como ya se vio la ROM del ZX Spectrum contiene los valores FF entre 386Eh (14446) y 3CFFh (15615). Dado lo anterior I s se podría cargar con 39,3A ó 3B. Dado que el TC2048 tiene estos valores con FF no existen problemas de compatibilidad, no así con el Microdigital TK90X que si presenta este problema .

Un ejemplo de esto ocurre en el juego Turbo Esprit:

E42C 3E3B LD A,3BH
E42E ED47 LD I,A
E430 ED5E IM2

FFF4 C322E6 JP E622H

FFFF 18F4 JR FFF4H


En este caso si se produce el problema y es necesario parchar el juego para cargarlo en el Microdigital TK 90X.


----------------------------------------------------------

Otras diferencias en investigación son:


  • Puerto 244 para selección de banco de memoria. Este valor no es borrado por un reset
  • Puerto de joystick kempston puesto a +5V y no a tierra como otros.




Saludos

JF

1 comentario:

nicolasw dijo...

Increíble que haya encontrado esto.
Muchísimas gracias, me ahorraste el trabajo de ponerme a recordar lo que hacíamos para pokear los juegos y que funcionaran.

Sin embargo no entiendo porque, por ejemplo, Batman (1986) que carga I con $39 y tiene toda la pinta de ser incompatible con TK90, funciona bien si lo cargo en el Spectaculator 7.01 y en el FUSE 0.10.0.1 con la ROM de la TK90.

¿Será que estos emuladores no están emulando algo y los juegos funcionan perfectamente?

Saludos, Nicolás