Archivo de la categoría: Retro

Cartucho dual para Amstrad CPC+

El objetivo de esta entrada es modificar un cartucho de Amstrad CPC+ para que tenga dos sistemas o juegos seleccionables  mediante un conmutador. Es un montaje tremendamente sencillo, y lo único que vamos a necesitar será un cartucho que funcione, un zócalo de 32 patillas, una EPROM 27c2001, un conmutador (cuanto más pequeño, mejor), una resistencia de 10K ohm y algo de cable.

La teoría es meter una EPROM de 256k y usar un conmutador conectado a A17. De esta manera tendríamos la EPROM dividida en dos bancos de 128k, y según la posición del conmutador elegiremos un banco u otro.

Modificación del cartucho:

Primero abriremos el cartucho. El cartucho va cerrado a presión con cuatro pestañas en los laterales (marcadas en rojo), y es muy posible que cuando lo abramos hayamos roto alguna.

 photo Cartuchosinabrirconmarcas_zps2808b4a7.jpg

Una vez abierto el cartucho podremos ver la placa con su EPROM, su chip ACID y un montón de sitios marcados como LK. Los puentes LK conectan algunas patas a +5v y otras al bus de direcciones del cartucho, para poder seleccionar diferentes EPROMs. He marcado las ubicaciones de LK3 y LK4 en rojo y dos puntos interesantes en amarillo.

Placa cartucho (cara componentes) photo Placacartuchocaracomponentes_zps154ffb4d.jpg

El siguiente paso deberá ser configurar nuestro cartucho para que use EPROMs de 128k. Para ello, debemos comprobar todos los puentes LK con un multímetro. Lo que nos gustaría es que:

  • LK1 y LK6 tengan continuidad.
  • LK2, LK3, LK4 y LK5 no tengan continuidad.

Si el cartucho no cumple estas condiciones habría que unir LKs y cortar las pistas que nos molesten. Además de esto, nos interesan especialmente dos LKs: LK3 (que uniría el A17 con +5V) y LK4 (que la uniría con CA17).

Una vez hecho esto, procedemos a desoldar la EPROM original y quitar el estaño sobrante de LK3 y LK4 (marcados con rojo en la foto). Cuando hayamos terminado, soldamos el zócalo y ponemos la resistencia de 10K ohm en LK3.

 photo Placacartuchocarasoldadurasconmarcas_zps60621a8e.jpg

Ahora el conmutador. Soldamos dos cables a los terminales marcados con amarillo (uno es parte de LK4 y el otro va a masa), y los conectamos al conmutador. Con eso hacemos que si el conmutador está cerrado A17 vaya a masa (0 lógico, selección del banco BAJO) y que si está abierto haya +5V (1 lógico, selección del banco ALTO). Mi cartucho quedó así:

 photo Placamodificadayterminada_zps2c02ea21.jpg

Ahora hay un problema: la carcasa del cartucho no cierra porque la EPROM y el zócalo tienen demasiada altura, y además el conmutador no ayuda nada para que quepa. Así que recortamos la carcasa del cartucho según necesitemos. En mi caso, quedó de esta manera:

 photo Cartuchoterminado_zpsc2bc08fb.jpg

Y con esto el cartucho está terminado.

Grabación de la EPROM:

Aquí lo más difícil será elegir qué dos ROMs le metemos al cartucho… ¿dos sistemas? ¿un sistema y un juego? ¿dos juegos? ¿la ROM de diagnósticos y cualquier otra cosa? Si este tutorial os parece interesante o útil es porque ya tenéis decidido que váis a poner en el cartucho.

En mi caso he metido el sistema en castellano con PARADOS 1.1 en el banco bajo, y el sistema en castellano sin menú en el banco alto. La única limitación es que lo que metáis en el cartucho deben ser ROMs de 128k (algunos juegos como Pang eran de 512k). Para crear la ROM de 256k, solo tendréis que ejecutar el siguiente comando:

copy /b rom1.bin+rom2.bin rom256k.bin

Donde rom1.bin y rom2.bin serían las 2 ROMs de 128k a unir y rom256k.bin el archivo que vamos a generar. Una vez hecho esto, simplemente grabamos la EPROM y la pinchamos en el zócalo de nuestro cartucho.

Observaciones:

  • En las EPROMs de 128k, el pin donde iría A17 está desconectado. Para ellas, la posición del conmutador da lo mismo; así que puedes pinchar cualquier EPROM de 128k en el cartucho modificado.
  • Por (casi) la misma razón, una EPROM de 256k puede pincharse en un cartucho sin modificar de 128k. En este caso, el sistema que arrancará será el que esté grabado en el banco alto.

Enlaces:

Ampliación de un Amstrad 464+ a 128k

La lista de la compra:

Este es el procedimiento para ampliar un Amstrad CPC 464+ a 4128+. La ampliación es bastante sencilla, ya que solo se necesitan 6 componentes para conseguirlo. Lo que vamos a necesitar será lo siguiente:

Ubicación: Componente:
IC12 41464-12
IC13 41464-12
R28 10K ohm, 1/8W
R55 33 ohm, 1/8W
C12 100nF, cerámico
C13 100nF, cerámico

Opcionalmente necesitaremos 2 zócalos para las memorias (de 18 patas) y quizás queramos grabar una EPROM con el cartucho de diagnósticos (27c1001). Las memorias pueden ser sustituidas por TMS4464-10 sin problemas, y si no puedes conseguir resistencias de 1/8W puedes utilizar las de 1/4W… pero no ajustarán bien en el circuito (ver la foto de la placa terminada). En mi caso no me ha quedado otro remedio que utilizar TMS4464-10 y resistencias de 1/4W.

Instalación del hardware:

Lo primero de todo será desmontar el 464+. Para ello le damos la vuelta y quitamos los tornillos marcados en rojo. Con un destornillador de punta plana, empujamos las pestañas marcadas en amarillo y la carcasa superior debería poder separarse.

Carcasa inferior 464+ photo Carcasainferiorconmarcas_zps7336bc5a.jpg

Una vez entreabierta, procedemos a soltar todos los cables marcados en rojo y podemos terminar de separar la carcasa. Desatornillamos los tornillos marcados en amarillos (son más cortos que los anteriores) y podemos sacar la placa del 464+ fuera de la caja. Fijaos que el tornillo de más a la derecha está sujetando un cable de la unidad de cinta.

Vista interior CPC 464+ photo CPC464abiertoconmarcas_zps70b5451f.jpg

En la siguiente foto podemos ver la placa de mi 464+. He marcado en rojo los huecos de los componentes que debemos soldar. Clickad sobre la foto si la necesitáis ampliada.

Placa CPC 464+ (RAM) photo Placabase464conmarcasampliacioacutenRAM_zpse002fc67.jpg

Realmente no da para mucho. Lo que más va a costar (y con diferencia) es abrir hueco para nuestros componentes. Al fabricar el 464+ se utilizó una técnica de soldadura que rellena los huecos vacíos, por lo que hay que retirar todo el estaño de los componentes que vamos a soldar. Después de mucho rato quitando estaño, y unos pocos minutos soldando, podremos tener una placa parecida a esta:

Placa base 4128+ photo Placabase4128_zps7220138e.jpg

Ponemos la placa en su sitio y la atornillamos (acordáos del cable de la unidad de cinta). Después conectamos las cintas del teclado y el cable de la unidad de cinta, los cables de la carcasa superior y lo volvemos a montar. Ya tenemos un precioso Amstrad 4128+… aunque la caja siga diciendo que es un 128k.

Comprobando que todo funciona:

Aquí tenemos un pequeño problema. Así como los CPC antiguos mostraban orgullosos la cantidad de memoria que tienen al conectarse, el CPC+ no lo hace. Necesitaremos un programa que nos diga qué cantidad de memoria tenemos instalada, y a ser posible que la pruebe. Para ello podemos utilizar el cartucho de diagnósticos de los CPC+. El cartucho original es una EPROM de 32k, pero como no estoy seguro de si los cartuchos normales pueden utilizarla he puesto una versión para EPROM de 128k entre los enlaces.

Cuando el equipo arranque, elegimos la cuarta opción (que sorprendentemente se llama RAM test) y pulsamos Enter. El equipo mostrará una pantalla parecida a esta:

CPC + RAM test con 128k photo TestRAM128k_zps039ce7c9.jpg

Si ves esto, puedes respirar aliviado: tu CPC reconoce la memoria. Lo sabemos porque dice que está mirando el bloque 2 de 7, lo que significa que nuestro equipo tiene 8 bloques de 16k (=128k, se empieza a contar desde cero). Si has visto una pantalla que dice que tienes solo 4 bloques (p.ej.: comprobando bloque 1 de 3), probablemente has soldado mal R28. R28 le cuenta al ASIC que tiene 128k, si no está bien seguirá creyendo que tiene 64k y no intentará comprobar el resto de la memoria.

Después de un rato, pueden pasarte dos cosas. Si la memoria está defectuosa, puede salirte una pantalla de este estilo:

CPC + RAM test con fallo photo FallotestRAM_zps0bfcc180.jpg

Si has visto esto, probablemente los integrados no estén bien puestos o sean defectuosos. Revisa las soldaduras y que estén bien pinchados en los zócalos. Lo mejor que te puede pasar es que después del test de RAM veas esto:

CPC + RAM test OK photo TestRAMcorrecto_zps19677af2.jpg

Esta es la pantalla que muestra que el test se ha completado correctamente. Tu Amstrad 464+ es oficialmente un 4128+.

(Existe una última posibilidad, que es que directamente no arranque. Si comprobáis que con la memoria instalada no arranca pero quitando los integrados de memoria sí que funciona, la culpable es R55)

Enlaces:

ZX Spectrum – Cargando BASIC de manera personalizada (y VI): Otras variantes

En la cinta que acompaña a esta serie de artículos, hay incluidas algunas variantes que no están en los artículos. Tampoco me voy a molestar en explicarlas mucho, ya que son fáciles de hacer si has seguido la serie.

  • ZX7 + contador: Se ha usado ZX7 para comprimir los datos, y luego la rutina de carga con contador de Microhobby para cargarlo.
  • ZX7 + nanodrive: Se ha usado ZX7 para comprimir los datos, y luego la rutina de carga nanodrive para cargarlo.
  • Loader Remix: Primero se ha usado ZX7 para comprimir los datos y se ha creado un bloque turbo para nanodrive. Luego se ha usado el truco del REM para meter la rutina nanodrive dentro del BASIC, y así ahorrarnos cargar dos bloques más. Además, se ha acortado la pausa entre bloques para que carguen más rápido.

Tiempos estimados de carga:

Versión: Tiempo:
Original 2m 34s
BASIC como CODE 2m 44s
Con contador 2m 56s
Nanodrive (3850 baudios) 1m 31s
zx7 1m 00s
zx7 + contador 1m 13s
zx7 + nanodrive 0m 44s
Inception 0m 51s
Loader Remix 0m 33s

En cuanto a los tiempos de carga, hay varias cosas a tener en cuenta:

  • Al meter cosas “extrañas” (grabar como CODE, con contador), el Spectrum tiene que cargar más cosas y alargas la carga.
  • Se han usado los tiempos entre bloque estándar, con lo que cada vez que grabas un bloque tienes un segundo de pausa tras él. Por este motivo, es importante cargar el mínimo número de bloques posible.
  • La única forma de reducir el tiempo de carga es aumentar la velocidad o disminuir los datos a cargar, por eso las versiones como CODE y con contador ocupan más… pero si haces ese tipo de cosas buscas protección o una carga chula y no te importa tanto que tarde un poco más.

…y con esto doy por concluida la serie sobre cómo cargar programas BASIC de maneras raras. Las últimas notas a tener en cuenta son tres:

  • Esto no es una manera de proteger un programa, sino de hacer que cargue de una manera más “profesional”. Aunque al usar estos métodos impides que te hagan un MERGE, todavía pueden hacerte un BREAK mientras se ejecuta, con lo que tendrán total acceso a tu programa.
  • Guarda siempre una copia de tu programa desprotegido y con carga estándar. El día que quieras hacer la versión 2.0 de tu programa, o copiar cosas de uno a otro lo agradecerás.
  • La vida comercial del Spectrum finalizó hace años, la mayoría de la gente que desarrolla programas o espía los de los otros lo hace con el fin de aprender. Haz una carga chula para tu programa, pero por favor distribuye también una carga normal para que cualquiera pueda verla.

ZX Spectrum – Cargando BASIC de manera personalizada (V): Inception

Siguiendo con nuestras manipulaciones del BASIC, ahora nos vamos a por un método bastante original de cargar y ocultar el BASIC. Vamos a esconder BASIC dentro del BASIC.

Empecemos por lo básico. Todos conocemos las sentencias REM, que contienen los comentarios del programa. Ahí dentro se puede poner cualquier cosa… incluso código máquina. Para los que gustan de ocultar cosas, sería muy interesante poder hacer una sentencia REM de una longitud determinada… y eso es lo que pregunté y me contestaron en World Of Spectrum. Aquí va un pequeño programa que puede hacer eso:

1 INPUT "Longitud ";rl: RANDOMIZE rl:
  CLEAR: DIM r$(FN p(23670)):
  LET rl=FN p(23670): LET VARS=FN p(23627):
  RANDOMIZE VARS+6+rl: POKE 23627,PEEK 23670:
  POKE 23628,PEEK 23671: INPUT "Linea ";rn:
  LET rv=VARS+4: LET rl=FN p(rv):
  RANDOMIZE rn: POKE VARS,PEEK 23671:
  POKE VARS+1,PEEK 23670: RANDOMIZE rl+2:
  POKE VARS+2,PEEK 23670: POKE VARS+3,PEEK 23671:
  POKE rv,234: POKE rv+1,CODE "<":
  POKE rv+rl,CODE ">": POKE rv+rl+1,13:
  DEF FN p(a)=PEEK a+256*PEEK (a+1)

Al ejecutar este programa (es increíblemente útil, grabadlo a cinta pero YA), nos pedirá la longitud en bytes del REM y el número de línea (que no sea la 1) y creará un REM de esa longitud. Ahora ¿cómo lo aprovechamos?

Cuando jugamos con el compresor ZX7, creamos un bloque comprimido que contenía el BASIC. Dicho bloque se cargaba en la dirección 53500 y medía 7375 bytes. Así que creo una rutina que va a mover 7375 bytes a la dirección 53500.

org 23760
ld hl,datos
ld de,53500
ld bc,7375
ldir
jp 53500
datos:

Cuando la ensamblemos, esta rutina nos va a medir 14 bytes. Si sumamos 7375 bytes de los datos y 14 bytes de la rutina, nos encontramos con que vamos a necesitar un REM de 7389 bytes para esconder todo eso.

Corremos nuestro pequeño creador de REMs, le indicamos la longitud y 10 como número de línea y comprobamos que tenemos un REM hermosote. Quitamos la línea 1, que ya no necesitaremos para nada.

Ahora creamos una línea que diga 20 PRINT USR 23760 y ya tenemos nuestro esqueleto BASIC para rellenar.

Ensamblamos la rutina y después cargamos el bloque comprimido en la dirección 23774 (23760 + 14). Ahora tenemos un BASIC que oculta otro BASIC en el REM de la línea 10. Salvamos nuestro programa con un SAVE … LINE 0 y ya tenemos una manera original de ahorrar tiempo en la carga del programa.

Nota: En todo lo que he hecho, la dirección 23760 es muy importante. En un Spectrum sin expansiones raras, el BASIC empieza en la dirección 23755. Los dos siguientes bytes son el número de la primera línea, los dos siguientes la longitud y el siguiente es el token de la primera instrucción de dicha línea (el REM). Por tanto, el primer byte tras el REM será el 23760.

Todo esto funcionará si la línea REM es la primera línea del programa y si no hay expansiones raras instaladas (como un interface 1 o un disciple). En otro caso, habría que juguetear con las variables del sistema PROG (23635, el primer byte tras el REM es PROG+5) y el hecho de que cuando se usa USR, el registro BC indica la dirección de la rutina.

Enlaces interesantes:

  • Almacén Lunar: Todas las versiones de este programa.
  • ZX Spin: Mi emulador favorito, el que uso para todos los parcheos.
  • ZX7: Compresor para Spectrum. Hay descargas del compresor para PC y código fuente para las rutinas en ensamblador para descomprimir. Hay unhilo dedicado a este compresor en World of Spectrum.
  • ZX Block Editor: Completo programa para manipular ficheros de Spectrum.

ZX Spectrum – Crear bloques turbo en TZX

En el post sobre carga turbo se explicó como crear una carga turbo para programas BASIC, usando la rutina nanodrive publicada en Microhobby. Como ya se explicó, si usamos ZXSpin nos grabará los bloques normales automáticamente, pero para grabar un bloque turbo necesitaremos usar las opciones Recording > Tape Recording > Start Recording.

Este método tiene un problema gordo y es que ZXSpin grabará literalmente lo que salga por MIC, generando un bloque de tipo “Direct Recording” que es bastante grande. Por otra parte, hay herramientas que convierten de audio a cinta y que también generan este tipo de bloques cuando no reconocen su cargador/velocidad.

En este post voy a explicar un método para crear bloques turbo más pequeños (vamos, del tamaño habitual en los TZX). Para ello necesitaremos algo que cree TZX (ZXSpin), una calculadora y el ZX Block Editor.

Lo primero de todo, algo de matemáticas. La rutina de grabación de la ROM del Spectrum graba a 1500 baudios, y la longitud del pulso que representa un 0 es de 855 (y la longitud del pulso que representa un 1 es el doble). Por tanto, x/1500=855 y aquí x representa la longitud en pulsos de un segundo. Despejando la x, nos encontramos que en un segundo hay 855*1500 pulsos (1282500 pulsos).

Por tanto, para una velocidad de 3850 baudios (la que coge por defecto nanodrive), nos encontraremos que el 0 nos dura 1282500/3850 pulsos (333.11, lo redondeamos a 333) y el 1 nos va a durar unos 666 pulsos.

Vale, ya sabemos las longitudes del 0 y del 1… ¿y qué hacemos ahora?

Lo primero de todo, grabamos nuestro programa a cinta. La diferencia es que cuando vayamos a grabar el bloque turbo no grabaremos mediante nanodrive, sino que haremos un SAVE … CODE normal.

Abrimos nuestro TZX con ZX Blockeditor. Ahí vemos que nuestro bloque CODE en realidad se compone de dos: uno llamado BYTES (esta es la cabecera) y otro llamado Standard data.

La cabecera nos sobra, así que marcamos el bloque BYTES y lo eliminamos con “Delete Block”.

Ahora marcamos el bloque Standard Data y vamos al menú Edit > Add Turbo Data. Se abre una ventana que contiene los datos de los distintos parámetros de grabación.

Cambiamos los valores de “0-bit pulse lenght” y “1-bit pulse length” a los valores que hemos calculado previamente y pulsamos Connect. Ahora debajo de nuestro “Standard data” hay un “Turbo data addition”, que lleva la información de la carga turbo.

Ahora que ya tenemos nuestro “nuevo” bloque turbo, grabamos el TZX y comprobamos que cargue correctamente. Para los que no quieran tirar de calculadora, incluyo esta tabla con los parámetros adecuados para las distintas velocidades de nanodrive:

Baudios: S: L: 0-bit: 1-bit:
2200 10 27 583 1166
2250 12 28,29 570 1140
2350 14 29,3 546 1091
2450 16 31 523 1047
2550 18 32 503 1006
2650 20 34 484 968
2750 22 35 466 933
2800 24 36 458 916
3000 26 38? 428 855
3050 28 39 420 841
3300 30 40 389 777
3450 32 41 372 743
3550 33 42 361 723
3650 34 43? 351 703
3850 36 44 333 666
4125 38 45? 311 622

Algunas notas a esta tabla:

  • El parámetro S solo se utiliza para grabar a cinta… si vas a alterar los ficheros TZX no necesitas saberlo.
  • La columna L se ha copiado literalmente de la tabla que se incluyó en el número 81 de Microhobby. No recomiendo usar las velocidades que tengan interrogantes o decimales, aunque si redondeas al entero más próximo podrías usarlo (nanodrive admite ligeras variaciones de velocidad a la hora de cargar).
  • He probado las velocidades de 2200, 3850 (por defecto en nanodrive) y 4125 baudios y el TZX generado funciona correctamente. De todas formas cuidadito que no todos los cassettes admitirán semejantes velocidades (aunque los emuladores tragan con todo).

Enlaces interesantes:

ZX Spectrum – Cargando BASIC de manera personalizada (IV): compresión ZX7

AVISO: Hasta ahora, todo lo que he hecho se podía hacer tanto en una máquina real como con emuladores (yo he usado emuladores por comodidad). A partir de aquí, vamos a tener que hacer manipulaciones que van a involucrar obligatoriamente a un PC (aunque luego el resultado pueda usarse en un Spectrum normalito).

Ahora vamos a complicar algo más las cosas. Hay dos formas de reducir el tiempo de carga: acelerando la rutina de carga o haciendo el programa más pequeño. Ahora vamos a usar zx7 para poder hacer más pequeño el programa y que cargue más rápido. Para eso vamos a utilizar un compresor, en este caso el zx7.

La teoría es sencilla: puesto que nuestro BASIC es ahora una tira de bytes (CODE), lo comprimimos. Después debemos cargarlo y volver a descomprimirlo en su sitio (23552). El mayor problema de esta teoría es buscar un sitio para el BASIC comprimido: si no elegimos bien el sitio, puede que al descomprimirlo escribamos por encima de los datos comprimidos y la liemos. Os acordáis de que STKEND nos marca el lugar donde acaba el BASIC, ¿verdad? Pues este dato va a ser terriblemente importante, ya que no podremos meter los datos comprimidos por debajo de STKEND (bueno, en realidad vamos a dejar un poco más de espacio por si las moscas). De momento, hacemos MERGE “” a nuestro programa y ejecutamos PRINT PEEK 23653+256*PEEK 23654. A este resultado (en mi caso 52957) le añadimos unos 500 bytes para hacer sitio a la pila y otras cosas. Así que ahora modificamos la línea de grabación del programa:

9999 CLEAR 53499:
     LET STKEND=PEEK 23653+256*PEEK 23654:
     SAVE "basic" CODE 23552,STKEND-23500:
     CLEAR 65367: RUN 7600

Como he colocado el CLEAR muy bajo, voy a restaurarlo al valor por defecto antes de hacer el RUN (por si acaso el programa genera muchas variables y necesita mucha memoria). Hago el consabido GO TO 9999 y obtengo un bloque CODE para manipular a mi antojo.

Ahora vienen las cosas raras. Cogemos el tzx que acabamos de grabar y lo metemos al ZX Block Editor. Nos ponemos sobre el último bloque y pulsamos el botón derecho del ratón.  Elegimos Export as > Export as binary file y lo llamamos almacen.bin. En mi caso, he exportado un fichero de 29547 bytes con el BASIC de mi programa.

Ahora ejecuto zx7 almacen.bin y zx7 nos genera un fichero almacen.bin.zx7 que ocupa 7275 bytes, lo que es un ahorro bastante importante de espacio.

Mi plan es cargar esos datos comprimidos a partir de 53600, ya que entre 53500 y 53600 voy a poner la rutina de descompresión. Tiro de calculadora y veo que caben perfectamente en la memoria. Perfecto. Ahora viene la siguiente manipulación rara.

Abro ZX Spin y tecleo lo siguiente:

CLEAR 53499: SAVE "basic" CODE 53500,7275+100

Cuando me aparece el mensaje “Press REC & PLAY…” no pulso ninguna tecla (por llevar la contraria) y hago las siguientes cosas:

– Voy al menú Tools > ZX Assembler y tecleo lo siguiente:

org 53500
ld hl,53600
ld de,23552

Sin hacer nada más, abro el fichero dzx_standard.asm que se incluye en zx7, corto todo el texto y lo copio en la ventana del ZX Assembler.

Con todo ese texto en la ventana, voy al menú File > Assemble… y le doy a OK. ZX Spin me informa que ha ensamblado 75 bytes. Ahora voy a la ventana principal de ZX Spin y le doy a File > Load Binary File. En el cuadro de diálogo elijo mi fichero (almacen.bin.zx7) y como Start Address marco 53600.

Ahora que ya tengo los datos comprimidos en la memoria del Spectrum, pulso Enter y dejo que el bloque CODE se grabe. Para comprobar que el juego es ejecutable, hago un PRINT USR 53500.

Así que tengo ya un fichero CODE que contiene el BASIC comprimido y se puede ejecutar… vale, toca hacer el cargador BASIC. Esta vez será lo siguiente:

10 BORDER 0: PAPER 0: INK 0: CLEAR 53499
20 LOAD "" CODE
30 PRINT USR 53500

Una detalle interesante: si los datos comprimidos ocupan menos de 6000 bytes y no usáis pantalla de carga, podéis cargar tanto la rutina descompresora como los datos comprimidos en la memoria de pantalla. Haciéndolo así nos ahorraremos dolores de cabeza acerca de dónde poner el CLEAR y si el BASIC nos pisará los datos comprimidos.

Y los más avispados se preguntarán… ¿qué nos impide ponerle un contador o un turbo a este bloque de datos? Y después de meditarlo, la respuesta es… nada.

He incluido versiones con contador y turbo en la cinta, pero como ya he explicado cómo utilizar esas herramientas me reservo el derecho (o no) de explicarlo en otros artículos. La única precaución en estos casos es que el bloque comprimido no colisione con las rutinas de carga.

Enlaces interesantes:

  • Almacén Lunar: Todas las versiones de este programa.
  • ZX Spin: Mi emulador favorito, el que uso para todos los parcheos.
  • ZX7: Compresor para Spectrum. Hay descargas del compresor para PC y código fuente para las rutinas en ensamblador para descomprimir. Hay un hilo dedicado a este compresor en World of Spectrum.
  • ZX Block Editor: Completo programa para manipular ficheros de Spectrum.

ZX Spectrum – Cargando BASIC de manera personalizada (III): carga Turbo

Para esto emplearemos la rutina nanodrive de la Microhobby 65, mejorada luego en la revista 81. La rutina tal cual no me sirve (llamar a la rutina con DEF FN no es compatible con sobreescribir el BASIC). Así que después de depurarla un poco, vamos a ver qué es lo que no nos han contado los de Microhobby.

A la rutina se entra por 65170, e inmediatamente después empiezan a cargar datos desde el calculador. Una vez metidos en registros (65192) se comprueba si vamos a cargar o salvar, se pone el flag a 255 y se salta a la rutina correspondiente. Así que tenemos 3 puntos alternativos de entrada de los que no nos habían contado nada:

  • En la dirección 65192, es la entrada “general”. En IX ponemos el inicio del bloque, en DE la longitud y en A ponemos 0 para grabar y 1 para cargar. El flag siempre es 255.
  • En la dirección 65206 tenemos la rutina SAVE, y se aceptan los mismos parámetros que en la de la ROM.
  • En la dirección 65333 tenemos la rutina LOAD, y también acepta los parámetros de la ROM.

De momento, para hacer más genérica la cosa, entraré por 65192. Hago un pequeño parche de 12 bytes que cargue los registros como quiero y así no tengo que usar DEF FN:

org 65158
ld a,0
ld ix,23552
ld de,35083
jp 65192

Mi nueva rutina cargará a partir de 65158 y tendrá una longitud de 377 bytes. La voy a manejar con los siguientes POKEs:

POKE 65159,n: REM 0 para grabar, 1 para cargar
POKE 65162,ixl: POKE 65163,ixh: REM bytes bajo y alto del inicio del bloque
POKE 65165,del: POKE 65166,deh: REM bytes bajo y alto de la longitud

El resto de POKEs son los mismos que los publicados en el número 81, y mi rutina está ya modificada para ir a 3850 baudios. Una vez generada mi rutina modificada, tenemos que liarnos con dos cosillas:

– El CLEAR 65157.
– Guardar el BASIC como bloque turbo.

Así que nuestra nueva línea para grabar el juego será algo así:

9999 CLEAR 65157:
     POKE 65159,0:
     POKE 65162,0:POKE 65163,92:
     POKE 65165,PEEK 23653: POKE 65166,(PEEK 23654)-91:
     SAVE "nanodrvz" CODE 65158,377:
     PRINT USR 65158:RUN 7600

Esta línea solo funcionará si ya está cargada la rutina nanodrive en memoria.

Destripándola un poco, los tres primeros POKEs indican que voy a grabar desde la dirección 23552. No son necesarios porque la rutina nanodrive que hay en la cinta ya tiene esos valores puestos. Luego POKEo la longitud. Para ello copio los valores de STKEND, pero al byte alto le resto 91 (lo que hace que POKEe en realidad STKEND-23296), lo que me da un bloque que copia 256 bytes extra (por si las moscas). Por último, grabo la rutina nanodrive ya POKEada y el bloque turbo. Dos pequeñas cosas:

– Según las instrucciones de Microhobby, para que nanodrive grabe hay que pulsar la tecla 0.
– La mayoría de emuladores no pueden grabar bloques turbo a tzx. El único que he conseguido que funcione es el ZX Spin, pero no funciona automáticamente. Para que grabe el bloque turbo, hay que ir al menú Recording > Tape Recording > Start Recording. Utilizando esta opción, generará un bloque de tipo “Direct Recording” bastante hermoso… estoy investigando como convertirlo a un bloque turbo “normal”.

En cuanto al cargador BASIC, será algo de este estilo:

10 BORDER 0: PAPER 0: INK 0: CLEAR 65157
20 LOAD "" CODE: POKE 65159,1
30 PRINT USR 65158

…y con esto tenemos un BASIC turbo. Observad que no POKEo ni inicio ni longitud… en los pasos anteriores hemos grabado la rutina con estos datos ya incluídos. Lo único que meto es el POKE para que en vez de grabar, cargue.

Enlaces interesantes: