Del ZX80 y ZX81 al ZX Spectrum - Parte II: Emulación A modo de introducción Lo que voy a ofrecer a continuación es una recolección de información, ya sea de magazines, libros, manuales o foros y páginas web, así como lo que yo mismo he podido experimentar con los diversos emuladores en existencia para el ZX81. El objetivo ha sido comparar los sigtes. emuladores: El EIGHTYONE para PC, la ROM de ZX81 para Spectrum 128 de Paul Farrow, así como el emulador para Spectrum llamado SP2ZX81 de Johan Koelman alias Dr.Beep. A modo de repaso: Sentencias BASIC comunes al ZX81, Spectrum y Microsoft: PRINT, INPUT, CLS, RUN, POKE, DIM, GOTO, GOSUB, LIST, LLIST, FOR, TO, STEP, NEXT, RETURN, IF, THEN, LPRINT, REM, POKE, NEW, SAVE, LOAD, CLEAR, LET, SIN, COS, TAN, INT, STR$, CHR$, PEEK, TAB, ATN, ABS, SQR, VAL, LEN, EXP, INKEY$, AND, OR, NOT y USR. Sentencias comunes entre el ZX81 y Spectrum: AT, PAUSE, COPY, CODE, LN, ASN, ACS, y PI Sentencias exclusivas del ZX81 (sin equivalente en el Spectrum): PLOT, UNPLOT, SCROLL, FAST, y SLOW Sentencias abreviadas del ZX81: CONT y RAND (en lugar de CONTINUE y RANDOMIZE) Cursores del ZX81 - solo tiene 4 modos: K - keyword (palabras claves) modo de comando directo e ingreso de sentencias. L - modo de tipeo letra a letra tras ingresar un comando F - function, modo de acceso a las funciones. Se obtiene pulsando SHIFT + NEW LINE (ENTER) G - graphics, SHIFT + 9 para entrar y salir del modo de caracteres semi gráficos. PARTE I En emuladores Hay más emuladores para Spectrum, que para el ZX81. Entre los pocos que se cuentan están EIGHTYONE, Multimachine, VB81, Zesarux, SPUD81 Y VB81-XUR. Incluso MESS (ultimamente se ha fusionado con MAME) lo emula. Elijo EIGHTYONE Voy al menú Options / Hardware F6 Paso a la pestaña Sinclair y selecciono ZX81 con RAM Pack 16k (su máximo es 48k) y OK. Tipeo unas cuantas lineas y cada vez que ingreso una, la pantalla "escrola". Hay un ligero parpadeo cada vez que tipeas o pulsas una tecla. LLIST y la pantalla parpadea mientras manda el listado a la impresora ZX. NEW y la pantalla se pone en blanco y demora algo antes de que reaparezca el cursor K. Cuando termina el programa, escrola todo antes de volver al modo de edición del listado. Pruebo a cargar algunos programas con extensión .P y todo OK. Será así en el ZX81 real, o más bien el emulador el que actúa de ese modo. Nota: EIGHTYONE te pide que elijas la RAM que quieres que use tu emulación sin importar si escogiste un zx81 o un t/s-1000 en vez de darla por defecto como hace con el Spectrum + o el 128k. Las opciones de RAM Pack emuladas son: None, 2k, 4k, 8k, 16k, 32k, y 48k como máximo. Un zx81 real puede aceptar un RAM Pack de máximo 64k. Si elijo el t/s-1500 va a 16k por defecto, pero lo deja fijo ahi, incluso si elijo luego el zx81, el cual por defecto debería rener un 1k de base (la opción None es eso). VB81-xur no parpadea la pantalla al hacer LLIST. SPUD81 actua similarmente como EIGHTYONE (su máximo de RAM también es de 48k) En el caso de REAL SPECTRUM y otros emuladores de máquinas Sinclair, como FUSE o SPIN, ninguno de los cuales añade emulación de ZX81, solamente es posible usando 128k y una ROM modificada por Paul Farrow, de la cual hablaremos a continuación. ZX81 para 128k ZX Interface 2 - Nuevos cartuchos de ROM: ZX81 Emulator Las rutinas de casette imitan correctamente la velocidad de las rutinas originales y de ese modo los programas pueden ser salvados y cargados directamente con el Spectrum 128. Es posible revertir el teclado al verdadero mapeado del ZX81 con tan solo tipear PRINT USR 8255. El teclado remapeado puede ser reactivado tipeando PRINT USR 8252. Además de cargar/salvar programas via casete, también es posible cargar y salvar via un enlace serial, por ejemplo, cargar/salvar programas de/a PC. Cuando un comando LOAD o SAVE es ejecutado, otro menú estilo 128k aparece. Estos menus proveen de opciones para cargar y salvar con casete, el RS232 del 128k, el conector de teclado extra del 128k y el RS232 de la ZX Interface 1. La salida a impresora puede ser dirigida a la ZX Printer o al RS232 del 128k, el conector del teclado numérico extra o el RS232 de la ZX Interface 1. Para simplificar el proceso de convertir programas entre el casette y el formato de PC, el autor incluyó un menú en la ROM para hacer tal transferencia. Es invocado ya sea pulsando BREAK cuando se resetea el Spectrum 128 o tipeando PRINT USR 8249. En el ZX Spectrum Dr.Beep creo para el Spectrum un emulador de ZX81 en 1997, el cual él mismo consideraba muy lento, pero plenamente funcional. Recientemente él hizo una nueva versión de su emulador. Ambos con RAM expandida de 16k. ZX81 emul La cinta contiene lo sigte: _ 81 TO SPECCIE - es para cargar y convertir programas de cintas del ZX81 _ 81LOADER - el código del programa anterior _ ZX81EMUL - la rutina de carga del emulador _ EMULATOR - el código del emulador _ ZX81ROM - una copia de la ROM del zx81 modificada para el emulador _ 3D MONSTER - el original "3d monster maze" (el laberinto del monstruo en 3D) _ RED ANTS - juego "hormigas rojas" Una vez cargado tenemos el cursor K esperando que tipeemos una orden del BASIC. Si pulsamos 1 + 0, nos da el sigte menú: ------------------------- | ZX81-EMULATOR | | QUIT ZX81-EMULATOR | - sale del emulador reseteando el sistema | WRITE/READ FROM ... | - selecciona TAPE o MDR1 para salvar o cargar programas | RESET ZX81-EMULATOR | - borra todo en memoria, IF til si se cuelga el ZX81 | TURN TO ZX81-EMULATOR | - vuelve al punto en que se invocó el menú sin borrar nada ------------------------- SAVE y LOAD funcionan perfectamente con cintas. De facto, seleccionar MDR1 no parece funcionar, SAVE y LOAD solamente ponen el borde en franjas azules y nada más. Puede ser pasado a otros sistemas de disco, pero sólo servirá para cargar y salvar en cintas. En el caso del MB-02+ debería de correr correctamente, pues simula el uso de cinta. Así que lo dejo ahí y paso a... zx81 Está en formato SNA. Solamente acepta LOAD "", no SAVE. Ni acepta alta resolución. Tampoco tiene menú s al parecer. Corre mejor si el emulador de SPECTRUM es puesto a 250% de velocidad. Viene con los sigtes juegos en formato TAP: _ BRICK.tap - una de rompe muros _ COSMIC.tap - _ GUZZLERS.tap - un clon de pacman _ MONSTER.tap - el 3d monster maze Y una utilidad para PC: _ XTEN2TAP.EXE Convierte cualquier programa .P a .TAP. Ejemplo: XTEN2TAP ASTEROID.P ASTEROID.TAP sp2zx81 La nueva versión del emulador del ZX81 de Dr.Beep. La cinta solamente contiene el emulador y su cargador BASIC, nada más. Aparte deol emulador están: _ as-chr.tap - el juego asteroides con los gráficos del CHROMA _ Conv_CHR.z80 - convierte el CHROMA a versión cinta de Spectrum (contiene asteroides) _ convCHR+P.z80 - salva un programa .P + chroma a cinta de Spectrum _ P-TO-TAP.z80 - carga .P como . BIN y lo salva a cinta .TAP Una versión previa contiene el nuevo emulador y la versión antigua, ambas en formato TAP. Las opciones de su menú ahora son: - Quit the emulator - sale del emulador pero sin resetear nada - Up or Down the screenrefreshcounter - cambia el contador de refrescado de la pantalla - T Timer delay finder - buscador de retrasadores de tiempo - L Select LOAD-device - carga desde cinta / bloque .P / microdrive - R Reset emulator (RST 0) - reinicia totalmente el zx81 - Z Show ZX81 keyboard - muestra el teclado del zx81 en pantalla a modo de ayuda - C CHROMA characters - carga solamente el juego de caracteres de chroma - B Back to the emulator - vuelve al zx81 sin borrar ni cambiar nada Existe otra versión del mismo emulador en formato Z80, la cual solamente trabaja con cinta y bloque, pero no microdrives. Al cargarlo, aparece el menú y un programa "emulmaze". El menú carece de las opciones Z y C. En vez de L tiene la opción W como la versión del 97. Ya no salva, solo carga desde cinta o de un .P como bloque binario. Veamos pues lo que nos ofrece esta nueva versión del emulador ZX81 para Spectrum. Ya no hay más SAVE, solo funciona LOAD "" desde el Basic. No pueden usarse programas que usan el modo hi-res (alta resolución), pues no lo integra. 1 + 0 = menú , como en el original de 1997. El teclado en pantalla permanece hasta que se pulsa B. Q para salir al Spectrum, pero sin eliminar nada como hacia la versión de 1997. Una vez en el BASIC Sinclair podemos hacer... GOTO 9000 para volver al emulador sin perder el programa en curso. RUN 9999 para ir al emulador reseteando todo. El programa está pensado para funcionar con cintas y microdrive. Debido a que el emulador interfacea ambos BASICs, ya es posible de pasar a otros sistemas de disco, con tan solo modificar la sintaxis de la opción LOAD a microdrive. Esto en una máquina real. Opción T (buscador de retrasadores de tiempo) Algunos juegos tienen rutinas de retrasos incluidos en su código. La razón es que un real ZX81 sin eso, hace que el juego corra muy rápido. Este emulador puede correr más rápido cuantos menos retrasos haya. Cuando se activa el buscador, el borde se pone negro. Y vuelve a hacerlo cuando logra alterar una rutina de bucle de retraso. La emulación de CHROMA. sp2zx81 no emula los colores de Chroma, pero sí su juego de caracteres. El método es el sigte.: Insertamos el programa con Chroma, en este caso "as-chr.tap" en el emulador. Tipeamos LOAD "" pero sin dar ENTER. En el menú pulsamos C y aparece el mensaje de que el fichero de caracteres chroma ya se ha cargado. Damos recién ENTER y el juego que usa chroma se carga y ya podemos ejecutarlo. Los archivos .P como bloque. En cuanto a cargar archivos .P como un bloque, esta opción solamente es posible de usar con emuladores. Es decir elijo Spin o FUSE y el método es el sigte.: Cargo el sp2zx81 en un modelo 48k. Voy al menú con 1 + 0. Pulso L hasta que aparezca "block." Tipeo LOAD "" y doy ENTER. Aparece en inversa el texto: "BINARY LOAD YOUR .P AT 49161". El sistema se queda en espera. En el emulador busco la opción "LOAD BINARY DATA" o similar. Elijo archivo .P y lo abro. Tipeo la dirección de inicio que es 49161, doy OK y listo, cargado todo como fichero binario. Ahora si quiero lo ejecuto o vuelvo al Basic y lo salvo al disco de mi elección. En suma. El propósito del autor de esta nueva versión de su emulador, es que uno pueda cargar y correr programas comerciales. O escritos por otros y salvados previamente a formato .P sin perder velocidad. No es más rápido que un emulador como EightyOne, pero sí lo es más que su antigua versión de 1997. Pero entonces sí permitía salvar programas a diferencia de ahora. PARTE II La memoria del ZX81 Un ZX81 estandar consiste de más o menos de la siguiente memoria: #0000 - #1FFF _ ROM #2000 - #3FFF _ no usado (solo para aditamentos, expansiones e interfaces) #4000 - #43FF _ 1K de RAM #4400 - #7FFF _ 15K de RAM extra Es decir esta es la configuración de RAM tanto en el ZX81/ts1000 con 16k de RAM Pack, o el t/s1500 16k de base. Para las pruebas y tipeos he elegido la configuración de 16k tanto en EIGHTYONE, como VB81 XuR y la ROM zx81 para 128k. En el caso del emulador SP2ZX81 para Spectrum, el cual replica a un zx81 con 16k de RAM, la memoria está organizada del sigte. modo: #0000 - #3FFF _ ROM del Spectrum #4000 - #5AFF _ la pantalla #5B00 - #7FFF _ BASIC, menú e imagen del teclado #8000 - #9FFF _ ZX81.ROM (modificada para el emulador) #A000 - #BFFF _ el emulador propiamente dicho #C000 - #FFFF _ l6k RAM del ZX81 emulado La memoria libre El ZX80 pone el archivo de pantalla (D_FILE) inmediatamente después de la memoria necesaria para el almacenamiento de tu programa, y pone un puntero en la sirección $400C. Así, tú puedes figurarte cuantos bytes estás consumiendo: PRINT (PEEK(16396) + 256 * PEEK(16397)) - 16384 Un ZX81 vacio comienza su RAM disponible para programas y datos en la dir. 16509 mientras 1k termina en 17408. Una pantalla vacía tiene 26 bytes y el stack debería tener unos 20 bytes normalmente, eso dependiendo de las funcciones usadas. El stack del calculador podía tomar más espacio adicional. Así que, alrededor de 850 bytes es lo que debía de quedarle libre al usuario. La RAMtop varia según el modelo o expansión de RAM añadida: 17408 - para 1 kB de Ram interna (zx81 original) 18432 - para 2k de Ram interna (en el T/S-1000) 32768 - para el 16k Ram Pack (o en el T/S-1500) 49511 - para el 32k Ram Pack 65535 - para el 64k Ram Pack RAMTOP: para ver/obtener los valores antes mencionados, se debe tipear lo sigte.: PRINT PEEK 16388+256*PEEK 16389 El valor resultante es producto de que la RAMtop considera la ROM + la RAM + la memoria no utilizada. Para poder saber cual es la real memoria ocupada debemos tipear: PRINT (PEEK 16388+256*PEEK 16389)-16384 Para conocer la verdadera memoria libre: PRINT 32768-(PEEK 16388+256*PEEK 16389) Para conocer el largo del programa mediante '(D-file) - 16509': PRINT (PEEK 16396+PEEK 16397*256)-16509 RAM DISPONIBLE - otro modo de de descubrirlo es mediante: PEEK 16386+256*PEEK 16387-PEEK 16412-256*PEEK 16413-38 En un modelo de solo 4k me da 3048 k libres, 15336 en uno de 16k y 31270 con 32k. Otro modo de saber cuantos K puros de memoria libre, es haciendo: PRINT (PEEK 16388+256*PEEK 16389-16384)/1024 Si es un zx81 sin expansión, tiene 1KB y nos mostrara 1 en pantalla. Si tenemos la expansión interna de 16KB o el Módulo de Expansión de RAM de 16KB conectado, tendría que salir 16 en la pantalla. Para solicitar la longitud de la memoria de la pantalla: (VARS) - (D-file) PRINT (PEEK 16400+256*PEEK 16401)-(PEEK 16396+256*PEEK 16397) Las variables del sistema 16384 - 16509 : en esta área residen las variables del sistema del ZX81 - T/S1000 X - la variable no debe ser pokeada porque podría colapsar el sistema. N - Pokear la variable no tendrá efecto duradero. S - la variable es salvada con SAVE. Byte Dirección Nombre Contenido ----------------------------------------- 1 16384 ERR_NR 1 menos que el código reportado. Inicia con 255 (por - 1), así PEEK 16384, debe dar 255. POKE 16384,n puede ser usado para forzar un error: 0 <= n <= 14 da uno de los reportes usuales, 15 <= n <= 34 or 99 <= n <= 127 da un reporte no estandar, y 35 <= n <= 98 afecta al archivo de pantalla. X1 16385 FLAGS Varios flags (banderas) para controlar el sistema BASIC. X2 16386 ERR_SP Dirección del primer item en el stack (tras un retorno de GOSUB). 2 16388 RAMTOP Dirección del primer byte arriba del área del sistema BASIC. Se puede pokear para hecer un espacio reservado a NEW o engañar a CLS para tener un mínimo archivo de pantalla. N1 16390 MODE Especifica el cursor K, L, F o G. N2 16391 PPC número de línea de la sentencia que se ejecuta. Pokear solamente afecta a la última línea del programa. S1 16393 VERSN 0 Identifica al BASIC ZX81 en los programas salvados. S2 16394 E_PPC número de la línea en curso (con el cursor del programa). SX2 16396 D_FILE Dir. del archivo de pantalla en la memoria. S2 16398 DF_CC Dir. de la posición de PRINT en el archivo de pantalla. Puede ser pokeado para imprimir en cualquier otra posición. SX2 16400 VARS Dir. de las variables del programa de usuario en memoria. SN2 16402 DEST Dir. de la variable en la asignación. SX2 16404 E_LINE Dir. de la línea editada en memoria. SX2 16406 CH_ADD Dir. del sigte. caracter a ser interpretado: el caracter despues del argumento de PEEK, o NEWLINE al final de un POKE. S2 16408 X_PTR Dir. del caracter precedente al marcador [S]. SX2 16410 STKBOT Dir. del stack del Calculador en memoria. Aquí es donde el Basic hace los cSTR$ lculos matemáticos. SX2 16412 STKEND Fin del stack del Calculador. SN1 16414 BERG Registro B del Calculador. SN2 16415 MEM Dir. del área usada por la memoria del calculador. (Usualmente MEMBOT, pero no siempre.) S1 16417 no usado SX1 16418 DF_SZ El número de líneas (incluida una en blanco) en la parte baja de la pantalla. S2 16419 S_TOP El número de la línea alta del program AND en listados automáticos. SN2 16421 LAST_K Muestra qué teclas fueron pulsadas. SN1 16423 Estado de rebote del teclado. SN1 16424 MARGIN número de líneas en blanco de la imagen superior o inferior: 55 en Inglaterra, 31 en Norte América. SX2 16425 NXTLIN Dir. de la sigte. línea del programa a ejecutarse. S2 16427 OLDPPC número de línea a la salta CONT. SN1 16429 FLAGX Flags diversos. SN2 16430 STRLEN Longitud del destino de la cadena en asignación. SN2 16432 T_ADDR Dir. del sigte. item en la tabla sintáctica (dificilmente util). S2 16434 SEED La semilla para RND. Esta variable es fijada por RAND. S2 16436 FRAMES Cuenta los cuadros que se muestran en la televisión. Bit 15 es 1. Los bits 0 - 14 son decrementados por cada cuadro fijo para teve. Puede usarse para sincronizar, y PAUSE también lo usa. PAUSE resetea a 0 el bit 15, y pone en los bits 0 - 14 el largo de la pausa. Cuando es puesto a cero, la pausa se detiene. Si pasa por la pulsación de una tecla, el bit 15 es puesto a 1 otra vez. S1 16438 COORDS Coordenada x del último punto trazado. S1 16439 " y. S1 16440 PR_CC El byte menos significativo de la dirección de la sigte. posición para LPRINT (en PRBUFF). SX1 16441 S_POSN número de Columna de la posición a PRINT. SX1 16442 " de Línea. S1 16443 CDFLAG Varios flags. El bit 7 está encendido (1) durante un computo y el modo de visualización.. S33 16444 PRBUFF BIF fer de la iimpresora (El caracter 33 es NEWLINE). SN30 16477 MEMBOT Area de la memoria del Calculador; usada para almacenar números que no pueden ser puestos convenientemente en el stack del calculador. S2 16507 no usado El número en la columna 1 es el número de bytes en la variable. Para dos bytes, el primero es el byte menos significativo. Nota: los valores de las sigtes. direcciones en parentesis no son absolutos. La dirección real está almacenada en las variables del sistema. 16509 - (D_FILE) zona del programa BASIC del usuario (D_FILE) - (VARS) archivo de visualización (VARS) - (E_LINE)-1 Variables del usuario (E_LINE)-1 $80h - usado para mostrar el fin de VARS (E_LINE) - (STKBOT) Linea tipeada y el área de trabajo (STKBOT) - (STKEND) Stack del Calculador (STKEND) - (ERR_SP) espacio disponible y stack del Z80 (sp) (ERR_SP) - (RAMTOP) Stack de Gosub (RAMTOP) - end of memory Rutinas USR - fin de la memoria Mensajes de error del zx81 El ZX81 solamente muestra el mensaje en la forma "x/z" donde x es el código de error y z es el número de línea donde este ocurre. 0 - Ejecución exitosa o se saltó a un número de línea mayor que las existentes. El programa finalizó sin errores. No afecta a CONT. 1 - La variable de control no existe (ninguna sentecia FOR la ha iniciado) en cambio existe una variable común del mismo nombre. Es un NEXT sin FOR. 2 - Se ha usado una variable sin definir. Sucede si la variable es usada antes de ser asignada mediante LET, DIM o FOR. 3 - Subíndice fuera de rango. Si el subíndice está definitivamente más allá del rango (es negativo o mayor a 65535) entonces será un error B. 4 - No hay espacioso en memoria. Nota: el número de línea en el reporte (cod. / lin.) puede aparecer incompleto en pantalla por falta de memoria. Por ejemplo: 4/20 puede verse como 4/2. Puede darse durante la evaluación de una función o con LET, INPUT, DIM, PRINT, LIST, PLOT, UNPLOT, FOR, y GOSUB. 5 - No hay más espacio en la pantalla. CONT hace esoacio limpiando la pantalla. Se da con PRINT, LIST. 6 - Desbordamiento aritmético: los cSTR$ lculos han llevado a un número mucho mayorr que 1038. 7 - RETURN sin GOSUB. 8 - Se intentó usar INPUT como comando (no está permitido). 9 - STOP ejecutado. CONT no intentará re-ejecutar la sentencia STOP. A - Argumento no válido. Se da con algunas funcciones como SQR, LN, ASN, y ACS. B - Entero fuera de rango. Cuando un entero es requerido, el argumento en coma flotante es redondeado al entero más cercano, si se sale del rango permitido da este error B. Puede darse con: RUN, RAND, POKE, DIM, GOTO, GOSUB, LIST, LLIST, PAUSE, PLOT, UNPLOT, CHR$, PEEK, y USR C - El texto en la cadena del argumento de VAL no es una expresión numérica válida D - (i) Programa interrumpido mediante BREAK. (ii) Se ha dado un STOP en repuesta a INPUT. Al final de una sentencia, o durante un LOAD, SAVE, LPRINT, LLIST o COPY. E - No usado F - Se dió una cadena vacía como nombre de programa al hacer SAVE. PARTE III Salvando programas. ENTRE EMULADORES Un ZX81 real solamente tiene dos sentencias SAVE y LOAD para salvar y cargar programas en cinta nada más. Los datose o variables y el código máquina se salvan todos juntos con el programa, a diferencia del Spectrum que permite salvar programas, código máquina y datos en matrices, todos de forma separada e independientes unos de otros, de modo que otros programas pudieran usarlos tambi<én más tarde. En el caso de los emuladores para ZX81 en su mayoría todos usan la extensión .P, para salvar y cargar programas de cinta, y .z81 es usado para snapshots como equivalente al Spectrum .sna o .z80. Algunos permiten extr AND r el program de los listados como texto en formato ASCII. También se puede trabajar con fiheros de tipo .bin. El editor gráfico de plataforma cruzada para gráficos de ZX81 llamado ZX81 ZXpaintyONE usa las extensiones .zp1 y .raw para trabajar con ficheros Bitmap. Muy bien, sabiendo esto retomo el REALS con la ROM de ZX81 para 128k. Tipeo algo y trato de salvarlo. Primero intento con un fichero .TAP, luego con .TZX. Nada, debido a que el REALS no fue pensado para emular ZX81, no me salva nada, ni me acepta ficheros .P para cargarlos. La IF nica solución es salvarlo como fichero .BIN, esto es sabiendo que la ROM empieza en 0 y el BASIC en 16384, solo debo saber cuSTR$ nto pesa, si el programa ocupa 2k, entonces basta con dar el largo del BIN a 1024*2 y listo. Ahora este fichero lo cargo en EIGHTYONE y todo OK: todo lo tipeado en el REALS, aparece en la pantalla, pudiendo ejecutarlo con RUN sin problemas.. He hallado el modo correcto de intercambiar programas entre ambos emuladores. Con eso en mente paso a... CON EL SP2ZX81 Todo el programa se haya dividido en dos: BASIC y código máquina, Empecemos por el cargador BASIC. Este no es un simple cargador del código principal, sino toda una interface entre el ZX81 emulado y el Spectrum. Basta ejecutarlo y una vez en modo K del ZX81, podemos entrar al menú y ver que solamente existe la opción L de LOAD. Al pulsar L vemos que cambia de tape (cinta) a block (ficheros P) y mdr1. El autor anima en su manual a corregir la sintaxis del comando LOAD dentro del listado para adecuarlo al sistema de disco que uno tenga o esté usando. Muy bien, con dicha licencia, ya puedo modificar todo cuanto sea necesario. Y obviamente lo primero que hice fue modificarlo para que corra totalmente en el Timex FDD 3000. ¿Y por qué quedarme ahí? También pude pasarlo exitosamente a Speccydos y Didaktik disks, los cuales comparten casi la misma sintaxis que el FDD. HC-2000 de Ice Felix, y Disciple también comparten entre sí una sintaxis parecida, debido a que se basan en el Interface 1. Opus y Microdrive me dieron el mensaje de "no hay espacio en memoria" y el Wafadrive, peor, me dio además "RAMtop no buena". Solamente eliminando lineas, y dividiendo el BASIC en dos, pude correrlo en Microdrive y Opus. Wafadrive peor aun, la modificacion resultó ser mayor. Como sea ya tengo el emulador SP2ZX81 transferido a cada sistema de disco, que los emuladores para Spectrum han incluido. Cabe con todo y modificaciones sin eliminar nada en: Timex FDD 3000 en un FUSE modificado exclusivamente para su uso. Speccy DOS en X128W HC-2000 de ICE Felix mediante una ROM modificada para Spectaculator. Didaktik Kompakt D80 con Real Spectrum Cabe solamente dividiendo y eliminando líneas innecesarias en: Opus y Microdrive con Real S y X128W Wafadrive con Real S En el caso del Beta128 y Beta48 con X128W, hubo que hacerlo por razón de su sintaxis. Ahora, el autor dice que su objetivo es que el emulador sea para ejecutar programas, es decir, principalmente jugar juegos, no salvar. En efecto, SAVE "algo" por ejemplo, no hace nada, solamente devuelve 0/0. ¿No hay cómo salvar algo entonces? Resulta que sí hay un modo. Primero hay que añadirle una opción S de Save. He decidido que sea solamente al disco. Al pulsar S, automáticamente salta a la línea que le he añadido al listado para ese fin. Solo falta saber el largo del código a salvar. El truco se haya justo en la rutina "P to TAP" en el cual vemos: LET l=PEEK 49172+256*PEEK 49173-16393 Para meterlo en el Microdrive y en el Opus dividí el programa en cargador y principal. A continuación la versión con sintaxis Microdrive: El cargador: 0LINE ZX2Z81 emulator  2020 YRS A renewed version of ZX81EMUL 9900 SAVE *"m",1,"SP2ZX81" LINE 9990: SAVE*"m",1,"sp2zx81.mc" CODE 26300,22092: STOP 9990 LOAD *"m",1,"sp2zx81.mc" CODE 26300 9990 LOAD *"m",1,"sp3" Prog. princ. sp3: 1 CLS :LET zx81=41179 2 GO TO USR zx81 768 LET d$="| |" 770 LET a=PEEK VAL "33363":LET a$=STR$ a+(" " AND a1): POKE 33363,a 870 LET l=l+(1 AND k$="l"): IF l>3 THEN LET l=1 880 IF k$="c" THEN PRINT AT NOT PI,PI;"LOAD CHARACTERS": IF l=1 THEN LOAD "" CODE 6e4: RANDOMIZE USR 32300 882 IF k$="c" AND l>1 THEN LOAD *"m",1,"chroma.chr"CODE 6e4: RANDOMIZE USR 32300 900 IF k$<>"b" THEN GO TO 700 901 GO TO 9000 1280 IF l=1 THEN LOAD ""CODE 49161:GO TO 9000 1290 IF l<>2 THEN GO TO 1320 1300 CLS : POKE 49205,81:PRINT AT 1,2;"BINARY LOAD YOUR .P AT 49161" 1310 IF PEEK 49205=81 THEN GO TO 1310 1315 GO TO 9000 1320 CLS : CAT 1: INPUT "ENTER filename to LOAD ";LINE f$: IF F$<>"" THEN LOAD *"m",1,f$ CODE 49161 1500 GO TO 9000 1999 STOP 5000 CLS : INPUT "ENTER filename to SAVE ";LINE f$: IF F$<>"" THEN SAVE *"m",1,f$ CODE 49161,PEEK 49172+256*PEEK 39173-16393 9000 LET zx81=43185: GO TO 2 9999 CLEAR 26299:LET l=1:GO TO 1 Los cambios que le hice al listado original fueron los sigtes.: La línea cero ha sido quitada por motivo de espacio, sólo el cargador lo retiene. Eliminé los comentarios REM por razón de ganar aun más espacio. En 780 y 870 cambié los IF por AND y eliminé la 781 ahora inncesaria. Añadí línea 815 para opción oculta S de salvar sólo a Microdrive o disco " " 882 " cargar el fichero chroma de Microdrive o disco " " 5000 " salvar el programa por la opción S. Modifiqué la línea 1320 para ver el catálogo sin cargar nada con solo pulsar ENTER en vez de dar un nombre. En el Wafadrive tuve que eliminar más líneas: quité todo lo de cargar de cinta y la opción de cargar el fichero .P como binario. Debido a RAMtop no buena, tuve que cambiar el CLEAR a 27499. Eso corrompió la imagen del teclado zx81 en pantalla, por lo que quité la opción Z del menú. También tuve que quitar el marco del menú y solamente así logré que todo corra del modo esperado. Aproveché y reemplacé la Z por la S de salvar a wafadrive. Es la única versión en la que S no está oculta sino visible. En cuanto a los discos, solo hubo que cambiar la sintaxis Microdrive y reemplazar "mdr1" por "disk". Eso fue más simple. El listado modificado es de la versión 1.03. Existe otra versión: la 2.00. La diferencia entre las versiones de SP2ZX81 1.03 y 2.00 son sus direcciones de llamada o pokes. linea v1.03 v2.00 1 41179 41222 770 33363 48251 860 " " 9000 43185 44950 Muy bien, ahora ya puedo no solamente cargar programas sino también salvarlos a disco con el emulador SP2ZX81. Spectrum 128k La versión original puede correr en un 128k, pero si se intenta volver al BASIC 48k, pues, el sistema se cuelga debido a la línea cero. En cambio, al dividir el programa Basic en dos partes, cargador y principal, al carecer este último de la línea cero, ya es posible volver al Basic 128k sin que colapse el sistema. Eliminando completamente la línea cero es posible transferirlo también a +3 DOS sin que se cuelgue al volver al Basic +3. En cuanto al 128k, aparte de los Microdrives, los únicos sistemas de disco compatibles son el Opus Discovery, Beta128, +D y el timex FDD. Una mejora en el caso de los discos que aceptan extensiones y comodines en su sintaxis, como es el caso del +3, FDD3 o el Didaktik, es la de hacer que solo muestren CAT exclusivo de los programas del zx81, en vez de ver todo el contenido del disco. Ahora sí puedo ya pasar a tipear algo. A continuación una traducción resumida del articulo publicado en COMPUTE! junio 1983 i.37 v.5 #6 por Harold Miller. Timex/Sinclair - divisor de pantalla. Esta corta pero habil técnica te permitirá poner texto en la pantalla, y luego borrar ésta dejando intacto tu texto. Debido a que las dos últimas líneas no están disponibles para usar, esta rutina ofrece la posibilidad de reservar tantas líneas como se desee, en lo alto de la pantalla para tus propios textos. Para ello, en vez de CLS usamos USR para invocar una corta rutina de solo 6 bytes, la cual está en una línea REM que debe ser la primmera de tu listado: 1 REM T?LN GSTAN Lo que hemos tipeado realmente es: {graf.}T, ?, {func.}LN, G, {graf.}S, {func.}TAN Para poder usarla debes indicar primero cuantas líneas quieres reservar con: POKE 16515, 24-N donde N = el número de líneas a reservar y 24-N = el resto de líneas a borrar. Ahora tipea el sigte. programa de ejemplo de su uso: 10 FOR I=0 TO 20 20 PRINT AT I,0;I 30 NEXT I 40 PRINT AT 21,0;"N=?" 50 INPUT N 60 POKE 16515, 24-N 70 PRINT AT 21,0;"PULSA ENTER PARA BORRAR" 80 PAUSE 4E4 90 RAND USR 16514 La rutina en ensamblador: 16514 6 (06) ld b,n - carga n en el registro B 16515 n (nn) - n < 24 16516 205 (cd) call - llama rutina 0a2c - CLS en la ROM del zx81 16517 44 (2c) 16518 10 (0a) 16519 201 (c9) ret Esta rutina es posible de convertir al Spectrum, basta con reubicarla en cualquier área de la RAM, no necesariamente en una línea REM; y reemplazar 44 y 10 por 68 y 14. Eso es todo. EN SUMA... ¿Qué es lo que puedo o no, hacer con este emulador? El original de 1997 tal vez fuera bastante lento en un Spectrum real, pero en un emulador para PC, capaz de incrementar la velocidad, eso queda paliado. Al menos cargaba y también salvaba a cinta. La versión más reciente solamente puede cargar de cinta programas previamente salvados para leer por el Spectrum. Sirve para ejecutar programas pero nuevamente como ya se dijo antes, no permite salvar. Con las modificaciones que le hice al BASIC, ya es posible no solo cargar de un disco, sino también tipear programas y salvarlos al disco. Los programas transferidos al disco son en realidad archivos '.P', no snapshots '.z81' ni binarios '.raw'. Ahora, para un emulador los .P son una forma de fichero binario conteniendo la info de una cinta de zx81. En un Spectrum real la opción cargar archivo .P como bloque binario, es inefectiva. Sólo sirve cuando el emulador de ZX81 corre en un emulador de Spectrum para PC. En este caso, puedo salvar todo, ya sea directamente como fichero .P mediante la opción "salvar binario". O de lo contrario salvar u '.bin' o '.raw' y luego renombrar la extensión a '.P'. Cualquier otro tipo de fichero binario creado por otros emuladores como EIGHTYONE, que se trate de cargar, causará un cuelgue del sistema. Y debido a su diseño que busca acelerar más la emulación, esta versión no acepta ningún programa que usa los modos de alta resolución diseñados para el ZX81 real. Tampoco emula ninguna expansión de color como el LAMBDA3000 o el CHROMA, del cual solo acepta su juego de caracteres. Como sea, lo mejor es que puede ejecutar la mayoría del software del ZX81, quitando las excepciones ya dichas. Y su otro punto fuerte es el que permita transferirlo a diversos sistemas de disco, lo cual pude hacer. Para cerrar SP TO SPECCIE Esta utilidad viene en la misma cinta que el original emulador ZX81 de 1997. Su objetivo es poder cargar un programa de cinta salvado por el ZX81, para ser regrabado en otra cinta que pueda ser leida por el ZX spectrum. Esto es debido a que el Spectrum graba a cinta a 1500 baudios y el Zx81 a solo 300. Es decir el Spectrum no puede cargar normalmente un juego del Zx81 sin modificarlo primero. P2TAP Esta utilidad en formato .z80, del mismo autor, es muy similar a la opción "LOAD block" del SP2ZX81 en lo que respecta a cargar en un emulador el archivo .P como un bloque binario, pero en vez de ejecutarlo, lo salva a cinta. Modificando la sintaxis, puede usarse para transfeir el fichero .P a un disco. AM-ZXSP También conocido como ZX81-Spectrum BASIC Convertor, publicado el año 1983, por AmSoft (UK) y en España por Ventamatic, para el ZX Spectrum 16K/48K. Esta utilidad a diferencia de las anteriores, lo que hace es leer y cargar un programa BASIC en cinta del ZX81 y convertirlo de modo que pueda ser modificado y ejecutado en el Spectrum. Nota: Esta utilidad convierte solamente el BASIC, no el código máquina. Todos los caracteres gráficos y sentencias exclusivas del ZX81, deben ser editadas yreemplazadas o eliminadas para que el programa pueda ejecutarse. Por lo tanto un listado conteniendo código máquina no puede correr en el Spectrum. Y por último Un "tip". Para salir rápido de una línea dificil de ingresar o modificar por a o b motivos: 1) pulsar EDIT (shift + 1) - reemplaza la linea en edición por la que apunta el cursor 2) y luego ENTER. Es todo (c)2020 zx_if1@hotmail.com