Adaptación de programas para ZX Spectrum a TR-DOS por medios modernos. Parte 1

A diferencia de las computadoras modernas, en los espectros el concepto de un sistema de archivos no era como tal. Esto significa que la descarga de cada tipo de medio requería una implementación separada y, en la mayoría de los casos, el programa no podía simplemente copiarse de la cinta al disco. En los casos en que el cargador de programas se escribió en BASIC, podría adaptarse a TR-DOS con una revisión bastante simple. Sin embargo, la situación se complicó por el hecho de que en muchos juegos (tanto de marca como pirateados), los cargadores estaban escritos en códigos de máquina y, a veces, contenían protección contra copia.


5.25 "disquete


A pesar de la presencia de un "botón mágico" que simplemente hizo un volcado completo de la memoria de la computadora y permitió guardar de alguna manera el programa en un disquete, los expertos consideraron crear versiones en disco de los juegos mientras preservaban la imagen de arranque original y otros atributos.


En este artículo, le diré cómo realizar tal adaptación en el ejemplo del juego Pac-Man , a saber, la imagen original Pac-Man.tzx .


Las herramientas


A pesar de que en los viejos tiempos todo este trabajo se realizaba directamente en el ZX Spectrum (en ausencia de otras opciones), adaptaré el juego usando el emulador y las utilidades de línea de comandos. La razón principal es que, especialmente al principio, el proceso de adaptación consiste en una gran cantidad de prueba y error, y es mucho menos doloroso si está automatizado. Lo mismo se puede hacer directamente en el Spectrum.


En la primera parte usaremos las siguientes herramientas:


  1. Emulador de fusibles para depuración y prueba.
  2. SkoolKit para desmontaje.

Deshabilitar el inicio en el gestor de arranque


Dado que el archivo de imagen y datos se descarga sin un bloque de encabezado (17 bytes con el nombre y el tipo de archivo), esto significa que el cargador está escrito en códigos de máquina. Debe encontrar dónde se encuentran estos códigos y desde qué dirección se inician.


Hay varias formas de ver el código del gestor de arranque:


  1. La forma más fácil es comenzar a descargar el programa, esperar a que se inicie el gestor de arranque y detenerlo presionando la tecla Space . En muchos casos, esto funciona, pero en el caso de Pacman, como en muchos otros, esto lleva a un reinicio.


  2. La siguiente forma es cargar el programa usando MERGE "" lugar de LOAD "" . A diferencia de LOAD , MERGE ignora la ejecución automática del programa. En el caso de Pac-Man, arrancar a través de MERGE hace que la computadora se congele con un desplazamiento característico de la pantalla izquierda. Esto se debe al hecho de que, en lugar de ejecutar el programa línea por línea, MERGE intenta analizarlo en su totalidad y fusionarlo con el programa ya cargado. Sin embargo, si el programa tiene un bloque con códigos de máquina que viola la sintaxis del programa, esto provocará un bloqueo.


  3. Si no desea hacer estallar sus cerebros, puede convertir la imagen de la cinta de TZX a TAP y usar la utilidad listbasic que viene con Fuse:


     $ tzx2tap Pac-Man.tzx $ listbasic Pac-Man.tap 1 RANDOMIZE USR (PEEK 23635+256*PEEK 23636+91) 

    La dirección 23635 ( $5C53 ) corresponde a la variable del sistema PROG , que contiene la dirección inicial del área BÁSICA. Por lo tanto, el punto de entrada al gestor de arranque está compensado por 91 bytes en relación con el área BÁSICA.


  4. Otra forma de ver el gestor de arranque se describe en el artículo Desativando a autoexecução de um programa BASIC . En el depurador de fusibles, debe establecer un punto de interrupción br 2053 , cargar el programa y, cuando se complete la descarga y se detenga la ejecución del código, ejecute el set 23619 128 . Esto evitará que el programa se inicie y le permitirá salir a BASIC.



Desmontaje del cargador de arranque


Conociendo el desplazamiento del punto de entrada en relación con el área BÁSICA, puede calcular su dirección absoluta. En el caso del ZX Spectrum 48K sin un TR-DOS cargado, el área BÁSICA comienza en 23755 ( $5CCB ). En consecuencia, el gestor de arranque comenzará en 23755 + 91 = 23846 ( $5D26 ).


Para comenzar, simplemente ponga un punto de interrupción en la dirección inicial y mire los códigos de la máquina. En Fuse, puede hacer br 23846 y comenzar a descargar el programa. Tan pronto como el gestor de arranque comience a ejecutarse, el emulador se detendrá:


Depurador


En el caso de que el cargador sea muy simple, solo mire el código desmontado en el panel central y entienda lo que se está cargando. Por lo general, el código de descarga para un archivo sin encabezado se ve así:


 LD IX, $8000 ;    LD DE, $4000 ;    LD A, $FF ;    CALL $0556 ;  LD-BYTES JP $8000 ;    

En un caso más complejo con la ejecución de código, debe comprender los pasos y tomar notas. El paquete de utilidades SkoolKit es muy adecuado para esto. Si establece una meta, con su ayuda, el juego puede analizarse hasta el último tornillo (mensaje, sprite, sonido). Cómo se hace esto se describe en detalle en la documentación .


En resumen, haga lo siguiente:


  1. Realice una instantánea de la memoria de la computadora Pac-Man.z80 usando tap2sna.py o las características del emulador.
  2. Cree un archivo de control Pac-Man.ctl con un conjunto inicial de instrucciones para desmontar:
     i 16384 Ignore for now c $5D26 Loader 
  3. Ejecute el desmontaje: sna2skool.py -H -c Pac-Man.ctl Pac-Man.z80 > Pac-Man.skool .
  4. A medida que estudie el código, agregue nuevas instrucciones y comentarios al archivo de control.
  5. Repita hasta que esté completamente iluminado.

Como resultado, después del primer pase obtenemos lo siguiente (mis comentarios, las direcciones se omiten):


 ORG $5D26 ;   23846,   ;   DI IM 1 ;   LD D, IYh ; LD E, IYl ; LD B, $25 ;    EX DE, HL ; LD DE, $0019 ; ADD HL, DE ;    HL  $5C53 (  PROG) LD E, (HL) ;   PROG  DE  IX INC HL ; LD D, (HL) ; LD IXh, D ; LD IXl, E ; LD A, (IX+$7F) ;      (  $7F-  ;  PROG) LD HL, $0035 ;    ($35   PROG) ADD HL, DE ; PUSH HL ;      XOR (HL) ;    LD (HL), A ; INC HL ; DJNZ $5D43 ;   AND (HL) ; RET NZ ;           ;    DEFB $77 

Descifrado del cargador de arranque


Todo lo que es realmente importante es que el gestor de arranque descifrado se encuentra en PROG + $35 . Esto significa que si ponemos un punto de interrupción en br 23808 , en este momento se completará el descifrado veremos el gestor de arranque descifrado:


Cargador


Este programa ya es mucho más similar al caso típico mencionado anteriormente. El valor $4000 ( 16384 ) se carga en los registros IX y DE , se hace algo más y el control se transfiere a la rutina ROM a $055A (esto es unos pocos bytes menos que el punto de entrada estándar en LD-BYTES ). Parece que este enfoque implementa algún tipo de protección contra copia, porque El procedimiento estándar no carga este archivo y algunos copistas no lo entienden.


Punto de entrada del programa


Queda por descubrir cómo se llama al programa después de la carga. En lugar de los CALL LD-BYTES y JP habituales, aquí se utilizan LD SP, XXXX y JP LD-BYTES . La primera opción (habitual) funciona de la siguiente manera:


  1. CALL empuja el valor actual del contador de software ( PC ) en la pila.
  2. El control se pasa a la rutina llamada.
  3. Al regresar de una subrutina ( RET ), el valor se elimina de la pila y se produce una transición al programa de llamada.

¿Por qué se hace diferente aquí? El hecho es que Pac-Man es compatible con el ZX Spectrum 16K y ocupa absolutamente toda la RAM (consulte el tamaño del archivo más arriba). Por lo tanto, al cargar, el programa se sobrescribe tanto el cargador como la pila, donde sea que estén. Si quisiéramos cambiar de ROM al gestor de arranque usando la pila y luego llamar al programa descargado a través de JP , en el momento en que se completó la descarga, no habría memoria en la dirección en la que se encontraba JP .


En cambio, el puntero de la pila se mueve al área de memoria donde, después de cargar, aparece la dirección del punto de entrada del programa, y ​​el procesador, al no notar la sustitución, la elimina de la pila con el nuevo puntero y va a la dirección especificada.


El resultado completo del desmontaje se puede ver en el repositorio del proyecto en el github.


Total


Como resultado de estudiar el gestor de arranque, descubrimos lo siguiente:


  1. Un archivo sin encabezado con una longitud de 16384 bytes se descarga en 16384 (en el área de la pantalla, que generalmente es obvio durante el proceso de descarga).
  2. Al final de la descarga, el puntero de la pila se encuentra en $5D7C , a donde se transfiere el control.

En las siguientes partes hablaré sobre cómo preparar archivos para escribir en el disco y escribir un cargador de archivos monobloque en ensamblador.


Enlaces relacionados:


  1. Perfil "TRUB Spectrumist" .
  2. Ingeniería inversa ZX Spectrum (Z80) juegos .
  3. Adaptação de jogos de fita para Beta 48 .

Source: https://habr.com/ru/post/451174/


All Articles