martes, 15 de mayo de 2018

Análisis de la ROM del ZX81

Hacía tiempo que quería dedicar algo de tiempo a analizar el firmware de la ROM del Sinclair ZX81 para ver si podía hacer alguna modificación, por supuesto, siendo consciente de mis limitaciones con el código máquina. ¿Por qué no introducir un mensaje como el copyright del ZX Spectrum?

Existen 3 versiones de la ROM del ZX81:
  • ROM original de Sinclair.
  • "Improved" ROM de Sinclair. Corrige errores de la ROM original.
  • ROM "Shoulders of Giant".
Las diferencias en el firmware entre la ROM original y la "improved" pueden consultarse en esta web.

Un repositorio con todas la ROM del ZX81 y sus clones se puede encontrar en este proyecto de github.

El CHECKSUM del firmware "Improved" es 855106, y presenta varias localizaciones no utilizadas (DEFB $FF). Y además tiene 1 byte de "spare" en la dirección 1DFFh (7679d).

En la rutina "The PRINT A Character Restart" (0010h) hay 1 byte con valor DEFB $FF.

En la rutina "The Collect Next Character Restart" (0020h) hay 3 bytes con el mismo valor $FF.

Y en la rutina "The Error-2 Routine" (0058h), hay 1 byte más con valor $FF.

Esto hace que se disponga de un total de 6 bytes disponibles, aunque en ubicaciones diferentes. Es el máximo disponible, si fuéramos capaces de reordenar todas las rutinas para no tener esos espacios sin usar.

La presentación del cursor en la parte baja de la pantalla es un poco rebuscada en la ROM de Sinclair. Se encuentra en la rutina "Cursor-in", a donde se llega desde la rutina "Initial"

0000   START
                I
                I
03CB   RAM-CHECK
971d        I
                I
03E5   INITIAL
997d        I
                I
14AD   CURSOR-IN
5293d      I
                I
14A6    SET-STK-B
5286d

En esta rutina CURSOR-IN se define el espacio disponible para las entradas de usuario, mediante la instrucción: LD (DF-SZ), +02

Esta instrucción carga el valor +02 en la variable del sistema DF-SZ que establece el número de líneas en la parte baja de la pantalla.

En esa misma rutina se establece el cursor (código 7Fh), seguido de un salto de línea (código 76h):

LD HL,(E-LINE)
LD (HL),+7F
INC HL
LD (HL),+76
....

La variable del sistema E-LINE apunta al espacio de trabajo.

Una vez terminada esta rutina, tiene una rocambolesca manera de regresar a la rutina INITIAL (LOWER), con saltos hacia otras rutinas, sin realizar ninguna operación más. Los valores entre paréntesis son las direcciones donde está la rutina de salto (JP/JR).

CURSOR-IN (L14AD)
|_SET-STB-B (L14A6). Salida mediante RET al CALL 14A6 en la EDIT KEY RUTINE
      |_EDIT KEY RUTINE (L05C4). Tras el CALL, salto JR L059D
            |_ED-EDGE (L059D)
                  |_CURSOR RIGHT (L0589)
                        |_KEYBOARD DECODING (L0523)
                              |_LOWER (L0472)

Esto da una idea de lo poco optimizado que está el firmware de esta ROM.

El firmware "Shoulders of Giant" es una variante de Geoff Wearmouth que mejora algunas rutinas de cálculo mediante el uso de algoritmos diferentes a los utilizados por Sinclair. Tiene un CHECKSUM de 853413 y difiere bastante con respecto a la original de Sinclair en cuanto a la disposición de las diferentes rutinas. 

El objeto de la optimización es generar el espacio necesario para el cambio principal que es el uso del método Newton-Raphson para el cálculo de la raíz cuadrada. Este método se ejecuta hasta 3 veces más rápido que el algoritmo de Sinclair. El nombre de "Shoulders of Giant" proviene de una cita de Sir Isaac Newton, que junto a su alumno Joseph Raphson publicó el artículo con el método. La cita es del año 1675:


"If I have seen further it is by standing on the shoulders of Giants."


Este método fue el seleccionado por Steve Vickers para el firmware de la ROM del Jupiter Ace. Ver página 92 del manual "Forth Programming". Hay que recordar que Steve Vickers escribió el firmware de la ROM del ZX81, además del manual de este ordenador, y posteriormente fundó Jupiter Cantab junto a Richard Altawasser.

Tiene 2 bytes de "spare" ubicados en la dirección L1DFE. Menos que la ROM "Improved". 


En el firmware "Shoulders of Giant" parece imposible poder generar más espacio para tener un mensaje de entrada como el del ZX Spectrum, dado el esfuerzo ya ejecutado para optimizar algunos de sus algoritmos. 

E igualmente, en el firmware "Improved" se requeriría un esfuerzo similar para, manteniendo las rutinas actuales, poder generar los bytes necesarios para ubicar un mensaje de entrada como el del ZX Spectrum, sabiendo que este mensaje ocupa 28 bytes -solo el mensaje-.


Referencias

"The Complete Timex TS1000/Sinclair ZX81 ROM Disassembly" by Dr. Ian Logan & Dr. Frank O´Hara

"Understanding Your ZX81 ROM" by Dr. Ian Logan