1K-AKA (Action Kit Assistant) para ZX-81

dancresp
Mensajes: 4993
Registrado: 13 Nov 2010 02:08
Agradecido : 14 veces
Agradecimiento recibido: 83 veces

1K-AKA (Action Kit Assistant) para ZX-81

Mensajepor dancresp » 30 Oct 2017 22:54

1K-AKA.gif
1K-AKA.gif (5.51 KiB) Visto 315 veces


EL PROGRAMA
Este programa es una colección de pequeñas rutinas en código máquina que nos facilitan la programación de juegos de acción, reduciendo el tamaño de los programas y aumentando su velocidad.

Los juegos de acción suelen requerir un gran número de líneas de código BASIC que consumen memoria, y distintos cálculos que afectan al rendimiento del programa, ya que el BASIC del ZX-81 es considerablemente lento.

Las rutinas permiten realizar 3 tipos de acciones:
1. Detectar un carácter en una posición de la pantalla.
2. Mover un personaje de un carácter, con la opción de mostrarlo en la pantalla.
3. Realizar un scroll lateral izquierdo del contenido de la pantalla.

Estas rutinas ocupan un total de 124 bytes y están almacenadas en la línea 0 del programa en BASIC. Se ejecutan mediante llamadas USR y su funcionalidad se pueden adaptar a nuestras necesidades con comandos POKE.

Los POKES se pueden ejecutar directamente sin número de línea, parcheando las rutinas, lo que también permite ahorrar mucha memoria teniendo en cuenta la forma de almacenar los valores numéricos por parte del intérprete BASIC del ZX-81.

Descargar 1K-AKA
El fichero ZIP incluye el 1K-AKA, 2 juegos de ejemplo, listado en ensamblador, cargador hexadecimal y una versión de un juego en BASIC puro.
1K-AKA.zip
(4.08 KiB) Descargado 11 veces


Rutinas disponibles:

LOCATE
Dirección rutina: 16514 - #4082

Hace un PRINT AT en una posición de la pantalla. La coordenada vertical está indicada en la dirección 16515 y la horizontal en la dirección 16517. A continuación ejecuta la rutina SCREEN.

16515 - #4083 : Posición Vertical. El valor debe estar comprendido entre 0 y 21.
16517 - #4085 : Posición Horizontal. El valor debe estar comprendido entre 0 y 31.

Ejemplo:
POKE 16515,4 (Indicar la fila 4 como la posición vertical)
POKE 16517,8 (Indicar la columna 8 como la posición horizontal)
LET A = USR 16514 (En la variable “A” se almacena el carácter que hay la posición de pantalla indicada)
PRINT “X” (Imprime una “X” en la posición indicada.

Nota:
Al iniciar una partida es recomendable asignar un valor a las dos coordenadas, ya que sino la posición inicial será la misma que la última posición de la partida anterior.

SCREEN
Dirección rutina: 16521 - #4089

Devuelve el valor del carácter que hay en la posición indicada por la rutina LOCATE, o de PRINT AT ejecutado desde el BASIC.

Ejemplo:
PRINT AT 5,5;
LET A = USR 16521 (En la variable “A” se almacena el código del carácter que hay en la posición de pantalla indicada)


BOYCLS
Dirección rutina: 16528 - #4090

Borra el personaje de la pantalla. Su posición está indicada por las coordenadas de la rutina LOCATE, y a continuación ejecuta la rutina INKEY.

16532 - #4094 : Carácter usado para borrar el personaje. Por defecto es un espacio CHR$(0).

Ejemplos:
LET A = USR 16528


INKEY
Dirección rutina: 16534 - #4096

Actualiza la posición del personaje en función de las teclas pulsadas. El personaje se puede mover vertical y horizontalmente, pero no controla la pulsación de dos teclas simultáneas. Se puede configurar las teclas y el área por el que se puede mover.
Al finalizar la ejecución de INKEY tenemos la opción de ejecutar la rutina BOYPRT que a su vez ejecuta SCREEN, obteniendo de esta forma el código del carácter que había justo antes de mostrar a nuestro personaje. Recomendado si se ha ejecutado esta rutina desde BOYCLS.

16555 - #40AB : Carácter de la tecla “LEFT”.
16560 - #40B0 : Carácter de la tecla “RIGHT”.
16565 - #40B5 : Carácter de la tecla “UP”.
16570 - #40BA : Carácter de la tecla “DOWN”.

16576 - #40C0 : Límite izquierdo. Si la columna es 0, introducir 255.
16581 - #40C5 : Límite derecho. Introducir la columna+1.
16587 - #40CB : Límite superior. Si la fila es 0, introducir 255.
16592 - #40D0 : Límite inferior. Introducir la fila+1.

16600 - #40D8 : El valor “0” activa y el “201” desactiva la ejecución de la rutina BOYPRT al finalizar la rutina INKEY .

Nota:
Por defecto viene definido con las teclas de los cursores del ZX-81.
Para inhabilitar una tecla, introducir el valor 255.

Ejemplos:
POKE 16555,33 (Tecla “5” mueve a la izquierda)
POKE 16560,36 (Tecla “8” mueve a la derecha)
POKE 16565,35 (Tecla “7” mueve hacia arriba)
POKE 16570,34 (Tecla “6” mueve hacia abajo)

POKE 16570,CODE “A” (Forma más clara para indicar que la tecla “A” mueve hacia abajo)

POKE 16576,255 (Desde columna 0)
POKE 16581,16 (Hasta columna 15)
POKE 16587,0 (Desde fila 1)
POKE 16592,12 (Hasta fila 11)

LET A = USR 16534


BOYPRT
Dirección rutina: 16601 - #40D9

Imprime el personaje en la posición de pantalla indicada por las coordenadas de la rutina LOCATE. Al volver al BASIC, la rutina nos devuelve el código de carácter que había antes de mostrarlo. Esto es ideal para detectar colisiones.

16605- #40DD : Carácter del personaje. Por defecto es un cero CHR$(28).

Ejemplos:
LET C = USR 16601


HSCROLL
Dirección rutina: 16608 - #40E0

Realiza un desplazamiento horizontal hacia la izquierda del contenido de la pantalla. Se puede indicar el número de filas del desplazamiento, pero siempre se realiza a partir de la primera fila.

16612 - #40E4: Número de filas del desplazamiento más 1. El valor debe estar comprendido entre 1 y 24.
16631 - #40F7: Carácter de relleno de la última posición de la línea desplazada.

Notas:
Por defecto, se desplaza el contenido de toda la pantalla, poniendo un espacio CHR$(0) en el último carácter de la línea.

Ejemplos:
POKE 16612,12 (número de filas a mover)
LET A = USR 16608 (Realiza un desplazamiento de las primeras 11 filas)


EL PROGRAMA
Las distintas rutinas se ha programado íntegramente en ensamblador de Z80, y están dispuestas de forma que algunas se ejecuten en cascada.

Código: Seleccionar todo

*****************************************************************************************
*                INICIO DEL PROGRAMA 1K-AKA            *
*                 1K Action Kit Assistant            *
*****************************************************************************************
ORG 16514
   
' ***************************************************************************************
' LOCATE - 16514 (#4082) - 7 bytes
' Posiciona el cursor en la posición indicada
' ***************************************************************************************
LOCATE   LD B,0      0600      ; Posición Vertical Y       (16515 - #4083)
   LD C,0      0E00      ; Posición Horizontal X    (16517 - #4085)
   CALL PRINTAT   CDF508

' ***************************************************************************************
' SCREEN - 16521 (#4089) - 7 bytes
' Devuelve en BC el código del carácter que hay en la posición del cursor
' ***************************************************************************************
SCREEN   LD HL,(16398)   2A0E40      ; Guarda en HL la dirección del cursor en el vídeo
   LD B,0      0600      ; Cargar 0 en el registro B
   LD C,(HL)   4E      ; Cargar el carácter de la dirección del cursor en C
   RET      C9      ; Final de la subrutina

' ***************************************************************************************
' BOYCLS - 16528 (#4090) - 6 bytes
' Borra el carácter del protagonista según su posición
' ***************************************************************************************
BOYCLS   CALL LOCATE   CD8240      ; Llamar a LOCATE
   LD A,0      3E00      ; Carácter que borra el Personaje (16532 - #4094)
   RST $10      D7      ; Mostrar carácter en pantalla

' ***************************************************************************************
' INKEY$ - 16534 (#4096) - 13 bytes
' Carga en A el código CHR$ de la tecla pulsada, excepto si no se ha pulsado ninguna
' ***************************************************************************************
INKEY$   CALL KEYBOARD   CDBB02      ; Llamada a la rutina KEYBOARD de la ROM
   LD B,H      44      ; Carga en B el valor de H
   LD C,L      4D      ; Carga en C el valor de L
   LD D,C      51      ; Carga en D el valor de C
   INC D      14      ; Incrementa D para afectar al flag Z
   JR Z,SAVEND   2839      ; Saltar si no se ha pulsado ninguna tecla
   CALL DECODE   CDBD07      ; Llamada a la rutina DECODE de la ROM
   LD A,(HL)   7E      ; Carga en A la tecla pulsada en formato CHR$
      
' ***************************************************************************************
' MOVE KEYPRESS - 16547 (#40A3) - 27 bytes
' Incrementa las coordenadas X,Y en función de la tecla pulsada
' ***************************************************************************************
   LD HL,16515   218340      ; Cargar la dirección de la posición Y en HL
   LD B,(HL)   46      ; Cargar en B la coordenada Y
   INC HL      23      ; Incrementar HL
   INC HL      23      ; Incrementar HL
   LD C,(HL)   4E      ; Cargar en C la coordenada X
      
LEFT   CP "5"      FE21      ; Comparar con tecla "LEFT" (16555 - #40AB)
   JR NZ,RIGHT   2001      ; Si no es 0 salta a otra tecla
   DEC C      0D      ; Decrementa C
RIGHT   CP "8"      FE24      ; Comparar con tecla "RIGHT" (16560 - #40B0)
   JR NZ,UP   2001      ; Si no es 0 salta a otra tecla
   INC C      0C      ; Incrementa C
UP   CP "7"      FE23      ; Comparar con tecla "UP" (16565 - #40B5)
   JR NZ,UP   2001      ; Si no es 0 salta a otra tecla
   DEC B      05      ; Decrementa B
DOWN   CP "6"      FE22      ; Comparar con tecla "DOWN" (16570 - #40BA)
   JR NZ,UP   2001      ; Si no es 0 salta a otra tecla
   INC B      04      ; Incrementa B
      
' ***************************************************************************************
' MOVE VERIFY - 16574 (#40BE) - 22 bytes
' Comprueba si las coordenadas X,Y están dentro de los límites establecidos
' ***************************************************************************************
VLEFT   LD A,C      79      ; Cargar en A el valor de C (Coordenada X)
   CP 0      FE00      ; Límite izquierdo (16576 - #40C0)
   JR NZ,VRIGHT   2001      ; Si es 0 salta a otro límite
   INC C      0C      ; Incrementa C
VRIGHT   CP 9      FE09      ; Límite derecho (16581 - #40C5)
   JR NZ,VUP   2001      ; Si es 0 salta a otro límite
   DEC C      0D      ; Decrementa C
VUP   LD A,B      78      ; Cargar en A el valor de B (Coordenada Y)
   CP 0      FE00      ; Límite superior (16587 - #40CB)
   JR NZ,VDOWN   2001      ; Si es 0 salta a otro límite
   INC B      04      ; Incrementa B
VDOWN   CP 9      FE09      ; Límite inferior (16592 - #40D0)
   JR NZ,SAVE   2001      ; Si es 0 salta para guardar las nuevas coordenadas
   DEC B      05      ; Incrementa C
      
' ***************************************************************************************
' MOVE SAVE - 16596 (#40D4) - 5 bytes
' Guarda en memoria el nuevo valor de las coordenadas X,Y hayan variado o no
' ***************************************************************************************
SAVE   LD (HL),C   71      ; Guardamos en memoria el registro C
   DEC HL      2B      ; Decrementa HL
   DEC HL      2B      ; Decrementa HL
   LD (HL),B   70      ; Guardar en memoria el registro B
SAVEND   NOP      00      ; NOP sustituible por RET (201-#C9 en 16600-#40D8)
      
' ***************************************************************************************
' BOYPRT - 16601 (#40D9) - 7 bytes
' Borra el carácter del protagonista según su posición
' ***************************************************************************************
BOYPRT   CALL LOCATE   CD8240      ; Llamar a LOCATE
   LD A,28      3E1C      ; Carácter del Personaje (16605 - #40DD)
   RST $10      D7      ; Mostrar carácter en pantalla
   RET      C9      ; Fin de la subrutina

' ***************************************************************************************
' H-SCROLL  - 16608 (#40E0) - 30 bytes
' Realiza un desplazamiento lateral hacia la izquierda del contenido de la pantalla
' ***************************************************************************************      
HSCROL   LD HL,(16396)   2A0C40       ; Cargar dirección de inicio de memoria de vídeo
LD C,24        0E18           ; Número de filas del desplazamiento (16612 - #40E4)
HSCR_1   LD A,(HL)      7E             ; Coger el carácter en pantalla al que apunta HL
CP 118         FE76           ; Lo compara con 118 (CR - Fin de línea)
JR Z,HSCR_3    280F           ; Salta si es final de línea
LD D,H         54      ; Guardar el valor de HL en la pila para pasarlo a DE
LD E,L         5D      ; Poner el valor de HL en DE usando la pila
   INC DE      13      ; Incrementa una posición respecto HL
LD A,(DE)   1A      ; Coger el siguiente carácter
CP 118      FE76      ; Lo compara con 118 (CR - Fin de línea)
JR Z,HSCR_2   2804      ; Salta si es final de línea
LD (HL),A   77      ; Pone en la posición actual el carácter siguiente
INC HL      23      ; Incrementa una posición
JR HSCR_1   18EF      ; Saltar atrás
HSCR_2   LD (HL),0   3600      ; Borrar último carácter de la fila (16631 - #40F7)
INC HL      23      ; Incrementa HL
HSCR_3   INC HL      23      ; Incrementa HL
   DEC C      0D      ; Decrementa C, que es el contador de filas
       JR NZ, HSCR_1   20E8      ; Si no se han hecho todas las filas, retroceder
       RET      C9      ; Final de la subrutina



APUNTES FINALES
Al comprarme mi ZX-81 a mediados del año 1984 me dedicaba a programar juegos de acción, aunque me lo pasaba mejor “jugando” a programarlos que jugando al juego en si ya que casi todos adolecían del mismo defecto: eran muy lentos.

El BASIC del ZX-81 es muy lento, de los más lentos en cualquier equipo de 8 bits. El hardware del ZX-81 provoca que constantemente la CPU se tenga que dedicar a ejecutar una rutina de la ROM que se encarga de enviar al monitor el contenido de la pantalla. Así que, básicamente, nuestro programa se ejecuta cuando el mismo hardware se encarga de dibujar los bordes de la pantalla, y en el modo 1K desde un final de línea CHR$(118) hasta el borde. Esto hace que el rendimiento del equipo se reduzca drásticamente. En modo FAST, esto no sucede y el equipo funciona 6 veces más rápido, pero claro... no se ve nada en pantalla.

Los últimos años me he vuelto a dedicar a programar programas en mi ZX-81 usando solo 1K de memoria, pero consciente de las limitaciones de su BASIC, prácticamente todos los programas realizados están más orientados a la lógica o desarrollo que a la acción, donde no afecta tanto la velocidad e incluso tienes la opción de usar el modo FAST.

Para poder hacer nuevos juegos más novedosos (scroll lateral) y sobretodo más rápidos, me he decidido a desarrollar estas rutinas, que están dispuestas de una forma que permiten ser ejecutadas de forma individual o en cascada.


La rutina SCREEN
En otros BASIC hay comandos que nos devuelven el código del carácter que hay en una posición determinada de la pantalla, pero en los 8 KB de la ROM del ZX-81 no debía caber, o no se consideró interesante, así que hay una forma más artesanal de hacerlo:

PRINT AT X,Y;
LET A = PEEK (PEEK 16398+256*PEEK 16399)

De esta forma, con el PRINT AT nos situamos en pantalla sin imprimir nada, y actualizamos una variable del sistema que se encarga de almacenar la dirección de memoria donde pondremos un carácter. Consultando el contenido de esta dirección, obtenemos el carácter que hay en ese momento. Pero para ello, hay que hacer 3 PEEK, una multiplicación y una suma.

Con 1K-AKA esto se reduce a una o dos líneas y se gana en velocidad.

Opción 1:
PRINT AT X,Y;
LET A = USR 16521

Opción 2:
LET A = USR 16514


La rutina INKEY
El proceso de borrar un personaje de la pantalla, moverlo leyendo el teclado y controlando los límites del movimiento y volver a mostrarlo en pantalla es algo que en el ZX-81 se puede solucionar con solo 4 líneas de código, pero que consumen mucho tiempo de la CPU y suelen afectar a la velocidad del juego.

En el 1K-AKA se pueden hacer todo esto gracias a las 3 pequeñas rutinas que incluye. En función del punto de entrada en la rutina con USR podemos hacer el borrado o no, la lectura del teclado y control de los límites, y opcionalmente el volver a mostrar el personaje. Todo en una única línea de código y con un rendimiento de unas 5 veces más rápido que en BASIC puro.

En un ejemplo posterior se pueden ver las diferencias de programas de una forma u otra.


La rutina de SCROLL

Siempre había querido hacer una rutina de scroll lateral, pero la verdad es que nunca me había puesto en ello pensando que el tema sería un lío visto como gestiona la memoria de vídeo el ZX-81, en que cada línea puede tener un tamaño diferente. Al final me ha salido una rutina de solo 30 bytes que funciona muy rápida. He comprobado su correcto funcionamiento en modo 16K poco es algo más lenta.

En muchos juegos esta rutina no tendrá ningún uso, pero abre nuevas posibilidades de programación de juegos en este equipo. Esto me ha decidido he a incluirla de serie.


Reduciendo el 1K-AKA
Puede darse el caso de que no nos interese utilizar todas las rutinas, y que por ejemplo, solo queramos usar una o dos, para reducir su tamaño. A continuación adjunto el listado del programa que sirve para introducir valores hexadecimales en memoria.

CM_Loader.gif
CM_Loader.gif (2.86 KiB) Visto 315 veces


Si queremos personalizar la línea del REM solo con las rutinas de SCROLL y SCREEN, debemos crear una linea 1 REM con tantos caracteres como bytes vayan o ocupar las rutinas, y a continuación entrar los valores hexadecimales en el A$ de la línea 10, indicando la dirección de inicio en la línea 20. De esta forma, estas dos rutinas ocuparían únicamente 37 bytes.

Posteriormente se tendrán que recalcular las direcciones de ejecución de las rutinas y los POKES.


JUEGOS DE EJEMPLO

Astro Field
Controlamos una nave con forma de “X” y debemos esquivar los objetos que se desplazan hacia nosotros. Conseguimos un punto por cada posición que avanzan los objetos. Controlamos nuestra nave con las teclas “Q” y “A”.

AstroField_Game.gif
AstroField_Game.gif (3.23 KiB) Visto 315 veces

AstroField_List.gif
AstroField_List.gif (4.93 KiB) Visto 315 veces


Para este juego se ha cambiado las teclas “UP” y “DOWN” y se han ajustado los límites superior e inferior. Las teclas de desplazamiento horizontal se han deshabilitado.

El juego ocupa únicamente 8 líneas de código.

En la línea 10 ponemos los puntos a 0, en la 20 ponemos a la derecha de la pantalla dos objetos “O” y “Q”, en la 30 ejecutamos la rutina HSCROLL. La línea 40 ejecuta la rutina LOCATE + SCREEN y carga en la variable “A” el carácter que hay en la posición de nuestra nave. La línea 50 comprueba si en esa posición hay un objeto enemigo. En caso afirmativo imprime una explosión, los puntos y una variable inexistente que provoca la detención del programa. Si no hemos colisionado con nada, ejecuta la línea 60 que ejecuta la rutina INKEY + BOYPRT, y la línea 70 suma un punto. La línea 80 vuelve a la línea 20.


Take The Money
Controlamos a nuestro personaje con forma de “X” y debemos coger los símbolos del “$” y evitar chocar con los bloques negros que van apareciendo. Conseguimos un punto por cada “$” que cogemos y cada 5 se borra el contenido de la pantalla. Controlamos nuestro personaje con las teclas cursoras “5”, “6”, “7” y “8”.

TakeTheMoney_Game.gif
TakeTheMoney_Game.gif (3.03 KiB) Visto 315 veces

TakeTheMoney_List.gif
TakeTheMoney_List.gif (6.93 KiB) Visto 315 veces


Para este juego se ha ajustado los límites de la zona de juego.

El juego ocupa únicamente 13 líneas de código.

En las líneas 6 y 8 inicializamos la posición de nuestro personaje y en la 10 ponemos los puntos a 0, en la 20 ponemos el símbolo “$” en la pantalla. En la 30 hacemos un PRINT AT en una posición aleatoria de la pantalla y ejecutamos la rutina SCREEN para cargar en la variable “A” el carácter que hay en esa posición. Si el carácter no coincide con el “$” imprime un bloque negro en esa posición. La línea 40 ejecuta las rutinas BOYCLS + INKEY + BOYPRT y carga en la variable “A” el carácter que había en la posición de nuestra personaje antes de ponerlo. La línea 42 comprueba si hay un bloque negro, y en caso afirmativo imprime una explosión, los puntos y una variable inexistente que provoca la detención del programa. La línea 44 comprueba si hemos tocado el “$”. En caso negativo salta a la línea 30 para poner otro bloque, y en caso afirmativo suma un punto. La línea 52 comprueba si nuestra puntuación es múltiple de 5 y en caso afirmativo borra la pantalla. La línea 54 vuelve a la línea 20.

A continuación se muestran dos versiones del mismo juegos, la de la izquierda programada en BASIC normal y la de la derecha con 1K-AKA. Como se puede ver la parte central del listado se ha reducido a una simple línea de código, y en el bloque anterior la línea 32 también es mucho más simple. El programa de la derecha funciona unas 5 veces más rápido que el de la izquierda. De todas formas, el tamaño del REM de la línea 0 hace que el programa solo ocupe 7 bytes menos.

Imagen


Para terminar
Las rutinas se han desarrollado con papel y bolígrafo y se han ensamblado íntegramente a mano. Las pruebas las he realizado en el emulador “EightyOne” de Windows.

Os invito a probarlo.
Adjuntos
BasicVsKaka.gif
(15.59 KiB) No descargado aún

alberchi
Mensajes: 50
Registrado: 04 Jul 2016 11:53
Ubicación: Ciudad Real
Agradecido : 6 veces
Agradecimiento recibido: 3 veces

Re: 1K-AKA (Action Kit Assistant) para ZX-81

Mensajepor alberchi » 31 Oct 2017 08:44

Fantástico !!! Tengo un pequeño programa en la cabeza y creo que este va a ser el empujón definitivo. Muchas gracias por este aporte !!!

Avatar de Usuario
ron
Mensajes: 17206
Registrado: 28 Oct 2010 14:20
Ubicación: retrocrypta
Agradecido : 511 veces
Agradecimiento recibido: 546 veces

Re: 1K-AKA (Action Kit Assistant) para ZX-81

Mensajepor ron » 31 Oct 2017 17:01

Dancresp, no tienes remedio... ¡ lo has vuelto a hacer !
Gracias por el trabajo ! es una chulada. :-)

dancresp
Mensajes: 4993
Registrado: 13 Nov 2010 02:08
Agradecido : 14 veces
Agradecimiento recibido: 83 veces

Re: 1K-AKA (Action Kit Assistant) para ZX-81

Mensajepor dancresp » 02 Nov 2017 12:00

ron escribió:Gracias por el trabajo ! es una chulada. :-)

Bueno, sigo exprimiendo ese K todo lo posible.
Y con estas rutinas, se ayuda a seguir exprimiéndolo.

Avatar de Usuario
Chema
Mensajes: 1549
Registrado: 21 Jun 2012 20:13
Ubicación: Gijón
Agradecido : 463 veces
Agradecimiento recibido: 188 veces
Contactar:

Re: 1K-AKA (Action Kit Assistant) para ZX-81

Mensajepor Chema » 02 Nov 2017 13:21

Tío eres sorprendente...

dancresp
Mensajes: 4993
Registrado: 13 Nov 2010 02:08
Agradecido : 14 veces
Agradecimiento recibido: 83 veces

Re: 1K-AKA (Action Kit Assistant) para ZX-81

Mensajepor dancresp » 03 Nov 2017 12:04

Van nueve descargas.

Si alguien hace algún juego que lo publique, que me hará gracia verlo !!!

Avatar de Usuario
eltargui
Mensajes: 206
Registrado: 06 Feb 2014 18:38
Agradecido : 20 veces
Agradecimiento recibido: 26 veces

Re: 1K-AKA (Action Kit Assistant) para ZX-81

Mensajepor eltargui » 09 Nov 2017 17:21

Vaya joya de hilo¡¡¡¡

Muy bueno dani. No me dedico mucho al software, pero los tuyos me los descargo y los tengo en una carpeta. Así descarga va.


Volver a “Sinclair ZX80/81”

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 2 invitados