Como descubrimos en la parte anterior , los códigos de máquina del juego no se pueden descargar directamente desde el disquete a la dirección de destino. Los subiremos a otra ubicación y, después de la descarga, los trasladaremos cuando sea necesario. Además, queremos hacer un gestor de arranque de un bloque cuando tanto el gestor de arranque como los datos cargados están en el mismo archivo básico. Tal cargador solo puede escribirse en códigos de máquina. Al mismo tiempo, dado que tenemos un archivo monobloque, el cargador en códigos de máquina deberá colocarse en los comentarios al cargador en BASIC.

Total, resulta el siguiente paso múltiple:
- Desde BASIC transferimos el control al programa en códigos de máquina.
- El programa en códigos de máquina transfiere el gestor de arranque del área BÁSICA a otra área que no se verá afectada por los códigos de máquina del juego, y le transfiere el control.
- Descargue y descomprima la imagen de arranque.
- Cargamos los códigos de la máquina de juego en un área que no se superpone al área de las variables del sistema.
- Transferimos códigos de máquina a la dirección de destino.
- Transferimos el control al programa.
El desarrollo tendrá que comenzar en el medio (párrafo 3). El hecho es que para escribir un programa para mover, necesita saber el tamaño del programa que se va a mover, y para incrustar códigos de máquina en un básico, necesita saber el tamaño del programa para mover.
Cargador de arranque monobloque (parte en códigos de máquina)
En TR-DOS, cargar datos de un archivo monobloque es más como descargar un archivo sin encabezado de una cinta, cuando los datos de un tamaño predeterminado simplemente se leen desde la posición actual y se cargan en un área específica de la memoria. Para esto, en TR-DOS, la rutina en #3D13
. Primero, descargue y descomprima la imagen:
LD DE, ($5CF4) ; LD BC, $0805 ; B - (9)*, ; — #05 ( ) LD HL, $8000 ; 32768** CALL $3D13 ; TR-DOS CALL $8000 ;
& ast; - ver la compresión de la imagen de arranque en la parte anterior;
& ast; & ast; - El desempacador es reubicable, por lo que puede descargarlo en cualquier lugar.
Del mismo modo, descargue los códigos de la máquina de juego:
LD DE, ($5CF4) ; LD BC, $2505 ; B - , ; — #05 ( ) LD HL, $6000 ; 24576 CALL $3D13 ; TR-DOS
En esta etapa, ya no necesitamos TR-DOS; podemos transferir códigos de máquina a la dirección de destino utilizando las LDIR
procesador LDIR
:
LD HL, $6000 ; (, ) LD DE, $5B00 ; LD BC, $2500 ; ( data.bin) LDIR
Bueno, al final, transferimos el control al programa de la misma manera que en el cargador de arranque original, moviendo el puntero de la pila:
LD SP, $5D7C RET
Ahora que el código del cargador está listo, debe compilarlo para conocer su tamaño, que necesitaremos más.
$ pasmo tmp.asm tmp.bin $ wc -c tmp.bin 44 tmp.bin
Procedimiento de transferencia del cargador de arranque
El gestor de arranque ocupa 44 bytes. Ahora debe escribir el procedimiento para mover el gestor de arranque de los comentarios en BASIC (punto 2 de la lista al comienzo del artículo). El problema es que la dirección donde se encuentra el área BÁSICA puede variar según los periféricos conectados a la computadora, por lo tanto, para determinar dónde desea transferir datos, debe centrarse en la variable del sistema PROG
(como en el gestor de arranque original) o al contador de software (registro de procesador de PC
).
No es tan fácil acceder al contador de software: no existen instrucciones de procesador como LD HL, PC
. Observé la solución en Laser Compress y se ve así (no uso realmente dirigido del procedimiento UNSTACK_Z
):
LD DE, $00 ; , , ; . ; 1 INC E ; 1 E, , ; . 1 CALL $1FC6 ; ( , LD HL, PC) ADD HL, DE ; LD DE, $F800 ; LD BC, $002C ; , (44 ) LDIR JP $F800 ; ; ;
Al momento de llamar al procedimiento ROM #1FC6
, la dirección de la siguiente instrucción ( ADD HL, DE
) estará en la pila. Es él quien se registra como resultado de llamar al procedimiento en HL
. En consecuencia, para determinar el número que debe escribirse en la primera línea, debe compilar nuevamente una pieza de ADD HL, DE
hasta el final y ver cuánto se necesita:
$ pasmo tmp.asm tmp.bin $ wc -c tmp.bin 12 tmp.bin
Resultó 12 bytes. En consecuencia, en la primera línea escribimos 11 ( #0B
).
A continuación, redactamos el procedimiento de movimiento con el cargador (vea el archivo terminado ), que moverá y compilará nuevamente. Debería resultar 56 bytes.
Cabe señalar aquí que después de escribir este artículo, descubrí que en lugar de calcular la longitud del programa que se movería, era posible usar etiquetas y dejar que el ensamblador lo descubriera. Pero para la justicia histórica, dejémoslo como está.
Cargador de arranque monobloque (parte base)
Ahora que conocemos el tamaño del gestor de arranque en códigos de máquina, podemos escribir el gestor de arranque en BASIC y recopilar todo en un archivo monobloque.
Los códigos de máquina están incrustados en un archivo básico, ya sea en un comentario o al final de un archivo. El segundo generalmente complica el estudio del archivo y es más adecuado para la protección, por lo que utilizaremos la primera opción. La opción de comentario es la siguiente:
1 REM @#$%... 10 RANDOMIZE USR (PEEK 23635+256*PEEK 23636+5)
23635
( #5C53
) es la dirección de la variable de sistema PROG
que mencionamos anteriormente. 5
es el desplazamiento del primer carácter del comentario relativo a PROG
(2 bytes son el número de línea, 2 bytes son la longitud de la línea y 1 byte es el operador REM
). Si desea agregar cualquier otro comentario antes de los códigos de la máquina, por ejemplo, su nombre, número de teléfono o dirección de correo, deberá ajustar el valor 5
.
Si no utilizamos ninguna utilidad adicional para crear el gestor de arranque, necesitaríamos ingresar caracteres arbitrarios después de REM
en una cantidad no menor que la longitud del programa en los códigos de máquina que queremos colocar en el lugar del comentario (en nuestro caso 56 bytes). Después de eso, uno podría cargar el programa a través de LOAD "" CODE PEEK 23635+256*PEEK 23636+5
y guardar el archivo.
Sin embargo, bas2tap
puede hacer el proceso mucho más fácil. puede compilar un archivo básico e incrustar datos binarios en él si cada byte se representa como un número hexadecimal entre llaves. Para hacer esto, ejecute el gestor de arranque compilado a través de hexdump
:
$ hexdump -ve '1/1 "{%02x}"' loader.bin {11}{0b}{00}{1c}{cd}{c6}{1f}{19}{11}...
hexdump
la salida hexdump
en el lugar del comentario en la primera línea después de REM
y compilamos el gestor de arranque en el -sboot
( -sboot
es el nombre del archivo en la cinta, -a10
es el número de línea del -a10
):
$ bas2tap -sboot -a10 boot.bas boot.tap
Convierta el gestor de arranque del formato de tap
a hobeta
través del formato intermedio 0
:
$ tapto0 -f boot.tap $ 0tohob boot.000
Crear un archivo de una pieza
En este punto, ya tenemos todos los archivos necesarios para crear una imagen de disquete. Puede crear una imagen y copiar todos los archivos necesarios en ella:
createtrd Pac-Man.trd hobeta2trd boot.\$$B Pac-Man.trd hobeta2trd screen.\$$C Pac-Man.trd hobeta2trd data.\$$C Pac-Man.trd
La imagen de disquete resultante ya debería funcionar. Puede ejecutarlo en el emulador y verificar, pero eso no es todo. Como el gestor de arranque no descarga los archivos posteriores, no por su nombre, sino en función de la posición del cabezal de la unidad, la carga solo funcionará si los archivos se encuentran en el disco uno tras otro. Esto necesita ser arreglado.
El principio es el siguiente: TR-DOS almacena información de tamaño de archivo redundante:
- Tamaño en sectores: se utiliza para colocar archivos en un disquete y copiar.
- Tamaño en bytes: se utiliza para cargar contenido.
Por lo general, estos tamaños se corresponden entre sí (256 bytes por sector), pero esto no es necesario. Aprovecharemos esto. Si cambia el tamaño del archivo de inicio en sectores a un valor igual al tamaño total de todos los archivos que queremos descargar, pero no cambia el tamaño en bytes, TR-DOS copiará todos los datos como un archivo grande, pero solo el básico se cargará en el inicio parte
En un Spectrum real o en un emulador, la pista cero se puede editar con programas como Disk Doctor, por ejemplo, Hex Disk Editor :

Pero puede simplificarse: una imagen trd no es más que una copia de bytes de todos los datos en un disquete, por lo que puede editarse en cualquier editor hexadecimal:
$ hexdump -C Pac-Man.trd | head -4 00000000 62 6f 6f 74 20 20 20 20 42 d0 00 d0 00 01 00 01 |boot B.......| 00000010 73 63 72 65 65 6e 20 20 43 40 9c 14 07 08 01 01 |screen C@......| 00000020 64 61 74 61 20 20 20 20 43 00 5b 00 25 25 09 01 |data C.[.%%..| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Como puede ver, al comienzo del disquete (en la pista cero) hay una tabla de asignación de archivos en la que la información sobre cada archivo ocupa 16 bytes. El tamaño en sectores se almacena en byte con desplazamiento #0D
(tercera columna a la derecha). El tamaño de nuestros archivos es #01
, #08
y #25
sectores, que en total es #2E
. Escribimos este valor en el byte correspondiente y eliminamos los encabezados restantes, porque ya no son necesarios:
$ hexdump -C Pac-Man.trd | head -4 00000000 62 6f 6f 74 20 20 20 20 42 d0 00 d0 00 2E 00 01 |boot B.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
Ahora tenemos una imagen de disquete completa. Debe cargarse correctamente y copiarse completamente de un disco a otro. Solo queda reducir el tamaño de la imagen. Como una imagen trd es una copia de bytes, siempre toma 640 KB. En la práctica, en la mayoría de los casos, es más conveniente usar el formato scl, que es más como hobeta almacena directamente los datos del archivo:
$ trd2scl Pac-Man.trd Pac-Man.scl
Ahora seguro. El proceso de adaptación de principio a fin se puede encontrar en el repositorio del proyecto en el github.
Herramientas:
- Pasmo es un ensamblador cruzado para el Z80.
bas2tap
es un compilador cruzado del dialecto BASIC de Spectrum.trd2scl
- convertidor de imagen trd a scl.
Enlaces relacionados:
- "Adaptación de programas al sistema TR-DOS" por Nikolai Rodionov.
- "Funciones TR-DOS" de la revista Info Guide No. 1.
- "La estructura del disquete TR-DOS" del libro "TR-DOS para profesionales y aficionados" .
- Una referencia a las variables del sistema y los procedimientos de Spectrum ROM .