Mostrando entradas con la etiqueta programacion. Mostrar todas las entradas
Mostrando entradas con la etiqueta programacion. Mostrar todas las entradas

lunes, 2 de diciembre de 2019

Herramienta de Desarrollo para ZX Spectrum SpectNet IDE

Revisando el estado actual de las herramientas de desarrollo para el ZX Spectrum, he encontrado una iniciativa llamada "SpectNet IDE" con una pinta fantástica. 




Sus características principales incluyen todo lo que uno puede desear y en un futuro seguro que será aún mas completo. 

Se sienta sobre el Visual Studio 2017 / 2019 Community Edition y tiene soporte para:

1) Programación en ASM para Z80.

2) Integración con Boriel Basic

3) Emulador incorporado y depuración punto a punto. 

Por el momento estoy valorando el uso de la versión 2.0 Preview 2




Creo que hay que darle las gracias al autor Istvan Novak y animarle a continuar descargando y usando esta magnífica extensión para desarrollar para el ZX Spectrum.



martes, 26 de noviembre de 2019

Aprendiendo Assembler para el Commodore 64

Después de adquirir un par de libros maravillosos y ponerme a devorarlos, he comenzado a desarrollar un pequeño "entorno" de herramientas para facilitar el desarrollo usando Assembler en el Commodore 64. 

Este desarrollo lo estoy realizando usando la herramienta CBM .prg Studio. Dicha herramienta es muy completa y me ha facilitado mucho la vida tanto para aprender como para terminar de comprender conceptos básicos del C64. 

La idea detrás de "C64DevToolKit" (así lo he bautizado) no es estrictamente tener un set de librerías que facilite la programación, sino aprovechar para aprender implementando los conceptos básicos del Assembler. 


Seguro que hay muchas formas de hacer dichas librerías mucho más eficientes, pero como he detallado, la idea principal es aprender en el camino, y , sobre todo, disfrutar de ello. 

En esta primera versión, se usan muchos de los conceptos básicos como son:

1) Las posibilidades del propio lenguaje ASM. 

2) Uso de subrutinas y macros. 

3) Definición de direcciones de memoria y variables de uso común.

4) Uso de alguna que otra facilidad del Kernal del C64. 

5) ScreenCodes y caracteres PETSCII.

6) Facilidades de la herramienta CBM Prog Studio. 

7) Direccionamiento y uso de memoria 16 Bits usando modo indexado y la Página 0 de memoria. 

8) Y alguna otra cosa más. 

La funcionalidad de esta primera versión es muy básica, pero he ordenado el proyecto al estilo "moderno", tratando de compactar y reutilizar funcionalidad; como lo haríamos con librerías "modernas". 

Seguiré completando el desarrollo, con muchas más cosas, a medida que tenga la posibilidad. 

Los próximos pasos serán cosas como suma, multiplicación, el uso del reloj interno, salida de valores numéricos por pantalla y lo que se me valla cruzando, que sea básico, como lo que he desarrollado hasta ahora. 

El proyecto se puede descargar de este enlace

La herramienta CBM .prg Studio tiene su propia entrada en este blog y su página web está en este enlace


jueves, 21 de enero de 2016

ZX Spectrum, pasando un "misil" por en medio de la pantalla en BASIC

Como hemos visto en la entrada que ejemplifica como pasar de coordenadas de caracteres a coordenadas de alta resolución en pantalla del Spectrum, se pueden mezclar instrucciones que usan coordenadas de alta resolución como PLOT e instrucciones que usan las coordenadas de modo "caracter" como PRINT AT en BASIC.

¿Que pasa si queremos, por ejemplo, pasar un "misil" (linea recta de 8 bits) por en medio de caracteres o UDG's que ya están en pantalla ?. Es decir lo que queremos conseguir es una animación que se solape por encima de lo que hay en pantalla. 

Bueno, lo primero que tenemos que tener en cuenta son cuatro particularidades del Spectrum, que condicionarán nuestro trabajo:
  • Solo hay dos colores por "celda" de 8x8 en pantalla. Es decir, cuando "pisamos" una celda, solo podemos gestionar dos colores a la vez, el de fondo (PAPER) y el del carácter o gráfico (INK). 
  • La ordenación de las direcciones en memoria, no son "lineales". Es decir, hay que calcular posiciones en memoria sabiendo que hay "saltos raros" de memorias en función de la posición en pantalla. 
  • No hay una manera directa de pasar de decimal a binario. Hay que hacer una subrutina que nos lo haga, dado que necesitamos saber el "dibujo" en pantalla por donde pasamos. PEEK nos devuelve un decimal y para dibujar en pantalla, necesitamos saber que es lo que estamos "pisando". 
  • Los efectos FLASH y BRIGHT no afectan a los colores y se pueden usar libremente. Es decir, no nos complican la vida.


Acordémonos que lo que hay en cada celda, es un dibujo de 8x8 bits.

En el siguiente vídeo, vemos ejemplificado el paso de un misil, de izquierda a derecha, que además pasa por encima de letras, y cuando sale, las deja como estaban. 





Se observa el efecto de los colores, cuando pasamos por una letra. Dado que el misil es negro, cuando escribimos un punto con PLOT toda la celda se pasa a color negro. 

Para hacerlo funcionar correctamente tanto en las celdas "vacias" (que solo tienen un espacio en blanco y color de fondo) y recomponer las letras y los colores cuando el misil pasa por encima de ella usamos dos instrucciones importantes, OVER e INVERSE.

Cuando el misil pasa, imprimimos un punto usando OVER 1. Cuando vamos "borrando" el misil y recuperando lo que había, usamos INVERSE en función de lo que había en esa posición, un 0 o un 1. 

También tenemos en cuenta si es el último pixel, para devolverle el color a la celda. 

IF r$(x)="0" AND X<8 THEN PLOT OVER 1;(px-8)+(x-1),py+4: GO TO 390
IF r$(x)="1" AND X<8 THEN PLOT INVERSE 0; FLASH f; BRIGHT bold; FLASH f; INK co;(px-8)+(x-1),py+4: GO TO 390
IF R$(X)="0" AND X=8 THEN PLOT INVERSE 1; INK co; BRIGHT bold; FLASH f;(px-8)+(x-1),py+4: GO TO 390
IF R$(X)="1" AND X=8 THEN PLOT INVERSE 0; INK co; BRIGHT bold; FLASH f;(px-8)+(x-1),py+4

También usamos ATTR y un mecanismo para calcular la posición en memoria y el contenido.

Es todo un poco lioso, pero viendo el ejemplo en código se entiende mucho mejor. 

Como siempre el código BASIC es bastante lento, pero una vez que lo pasamos a código máquina usando el compilador HiSoft (y habiendo optimizado el código BASIC) el rendimiento es aceptable.

He dejado el código BASIC del ejemplo un este enlace

En este otro enlace que dejado el mismo ejemplo pasado a código máquina. 



martes, 19 de enero de 2016

ZX Spectrum BASIC, pasar de coordenadas de baja a alta resolución.

Es muy cómodo trabajar con las coordenadas X e Y de baja resolución, para utilizar comandos como PRINT AT y SCREEN$ en pantalla. 

Las coordenadas de "baja resolución" son perfectas para manejarnos en modo "carácter"  y con UDG's de 8x8 básicos. 

El modo de "alta resolución" de nuestro Spectrum son 255 pixels horizontales por 175 pixels verticales.

Cuando queremos crear formas geométricas, o simplemente pintar una línea recta usamos comandos pomo DRAW y PLOT, que usan las coordenadas de alta resolución. 

Es una gran ventaja el poder combinar el uso de ambos modos gráficos ; simplemente usando el comando y las coordenadas que nos interesen a cada fin.

Por ejemplo, el juego Retro8ogue utiliza el modo carácter para casi todo, usando las coordenadas del modo de "baja resolución" (comandos PRINT AT y SCREEN$ básicamente).

Para poder pintar, por ejemplo, una pequeña línea, que viaje a través de la pantalla (es decir, una flecha) parece más apropiado usar el comando PLOT que crear varios UDG's; uno por cada uno de las 4 direcciones en las que la "flecha" se podría desplazar. 

Entonces, ¿como combinamos el uso de ambos modos gráficos, en función de lo que hay en pantalla?.

Pues lo más sencillo es , dado un "carácter" o UDG en pantalla (posiciones X e Y de modo "baja resolución") calcular cuales son sus coordenadas X e Y en modo "alta resolución". 

Para ello, usamos dos funciones BASIC en nuestro programa: 

Para calcular la coordenada X: 

DEF FN x(x)=x*8

El valor inicial de la posición X es la coordenada X por 8. Como cada "celda" en el modo de baja resolución es de 8x8, esta función nos devolverá la coordenada X donde se encuentra el primer pixel, en alta resolución. 

Para calcular la coordenada Y: 

DEF FN y(y)=ABS ((y*8)-168)

Dado que la coordenada Y en el modo de baja resolución, va "al revés" que en el modo de alta resolución (en baja se cuenta de arriba a abajo y en alta de abajo a arriba, en pantalla) sacamos el valor absoluto de la coordenada Y multiplicado por 8, y restando la última posición inicial de las celdas en vertical, que es 168.

Hay que recordar que estas fórmulas nos devuelven los valores iniciales de X e Y. 

La celda "completa" que representan las coordenadas de modo carácter que le hemos pasado a las funciones, son las coordenadas X e Y de alta resolución más 8 (bits).

En el código de ejemplo de abajo, calculamos las coordenadas de alta resolución, y pintamos una X en la "celda" a la que pertenecen. 

El código fuente en BASIC, del ejemplo también lo puedes descargar aquí

Después del código hay un vídeo ilustrativo.

10 CLS : LET lx=0: LET ly=0: LET hy=0: LET hx=0
20 DEF FN x(x)=x*8
30 DEF FN y(y)=ABS ((y*8)-168)
40 INPUT "Entra coor. Y :";ly
50 INPUT "Entra coor. X :";lx
60 IF lx<0 OR lx>31 OR ly<0 OR ly>21 THEN PRINT AT 2,2;"Val. no val. 0>X<32. 0>Y<22": GO TO 40
70 PRINT AT 2,2;"              ": PRINT AT 2,2;"Lo X: ";lx
80 PRINT AT 3,2;"              ": PRINT AT 3,2;"Lo Y: ";ly
90 LET hx=FN x(lx): LET hy=FN y(ly)
100 PRINT AT 4,2;"              ": PRINT AT 4,2;"Hi X: ";hx
110 PRINT AT 5,2;"              ": PRINT AT 5,2;"Hi Y: ";hy
120 INPUT "Pintar X ?";z$
130 IF z$="s" THEN GO SUB 200
140 INPUT "salir ? s/n ";z$
150 IF z$="s" THEN GO TO 180
160 PRINT AT 2,2;"                           "
170 GO TO 10
180 STOP
190 RETURN
200 FOR a=0 TO 7
210 PLOT hx+a,hy+a
220 PLOT hx+a,(hy+7)-a
230 NEXT a
240 RETURN 




martes, 22 de diciembre de 2015

Ejemplo de cursor en pantalla

He aquí un ejemplo de como podemos implementar un cursor en pantalla. 

Está pensado para trabajar, como un cursor en pantalla de modo texto, al uso de lo que estamos acostumbrados. 

Para realizar el cursor, tenemos que tener en cuenta tanto las características del BASIC como las limitaciones en pantalla a la hora de imprimir texto. 

Es decir, tenemos que gestionar dos cosas:

1) El texto que se encuentra en las coordenadas del cursor.

2) Los atributos de dicho texto (color del texto, color de fondo, brillo e intermitencia). 

El cursor debe desplazarse por la pantalla sin modificar el valor original de la celda donde se encuentre. Para ellos tenemos que tener en cuenta los puntos 1 y 2 cuando movamos dicho cursor. 

Para esto usaremos dos funciones del BASIC; 

1) SCREEN$ para obtener el carácter que está en las coordenadas X,Y.

2) ATTR para obtener sus atributos (color, fondo brillo e intermitencia). Usa el mismo mecanismo de coordenadas X e Y. 

La función SCREEN$ nos devuelve (solo) el carácter que está en la celda X,Y. No devuelve ni sus atributos (que se obtienen con ATTR) ni valor cuando el carácter en la celda es un UDG

Para obtener un valor si es un UDG hay una manera, que se describe en otro ejemplo

El valor que nos devuelve ATTR es un valor numérico que se descompone de la siguiente manera:
  • Si el valor es superior a 128, el carácter está en modo intermitente (FLASH 1).
  • Si el valor es superior a 68, el carácter tiene brillo (BRIGHT 1). 
  • El valor de ATTR (si toca restar porque es mayor de 68 y/o 128) dividido entre 8 nos da el color del fondo (PAPER). 
  • El valor de ATTR menos el valor del fondo (PAPER) nos da el color del carácter (INK). 

Extracto del programa de ejemplo: 
LET f=0
IF z>128 THEN LET f=1: LET z=z-128
LET b=0
IF z>64 THEN LET b=1: LET z=z-64
LET p=INT (z/8)
LET co=z-(p*8)
PRINT FLASH f; INK co; BRIGHT b; PAPER p;z$

La filosofía del cursor es sencilla:

1) Guardamos en dos variables el valor de la celda y sus astributos.

2) Imprimimos el cursor encima (OVER 1) ,intermitente (FLASH 1) y con brillo (BRIGHT 1) para que se vea fácil en el ejemplo.

3) Al movernos, restauramos el valor de la celda donde estábamos.

Llenamos la pantalla de caracteres generados de forma aleatoria y vemos como funciona el cursor. En la parte de abajo nos da una linea de ayuda con las teclas para mover dicho cursor.

He usado unos UDG de flechas en la linea de ayuda, para hacerlo más amigable.

El código BASIC lo puedes descargar de aquí.

Una versión del ejemplo pasada a código máquina la tienes aquí.

Debajo de la imagen está el listado completo por si lo quieres copiar y pegar.



















5 CLEAR
10 LET t$="Ejemplo de cursor"
20 CLS
30 BORDER 4
40 GO SUB 460
50 PRINT AT 0,INT ((32-LEN t$)/2); INK 2;t$
60 FOR y=1 TO 20
70 FOR x=0 TO 31
80 LET co=INT (RND*8)
90 IF co=2 THEN GO TO 80
100 LET ff=INT (RND*10)
110 LET f=0
120 IF ff>8 THEN LET f=1
130 LET p=INT (RND*8)
140 IF p=2 THEN GO TO 130
150 PRINT AT y,x; INK co; FLASH f; PAPER p;CHR$ (65+(1+(RND*60)))
160 NEXT x
170 NEXT y
180 LET x=0: LET y=1: LET xant=x: LET yant=y: LET z$= SCREEN$ (y,x): LET z=ATTR (y,x): PRINT AT y,x; OVER 1; FLASH 1; INK 2; BRIGHT 1;"\::"
190 PRINT AT 21,0; INK 0;"u(";CHR$ 144;"),d(";CHR$ 145;"),l(";CHR$ 146;"),r(";CHR$ 147;") o q"
200 LET i$=INKEY$
210 IF i$="q" THEN GO TO 420
220 IF i$<>"l" AND i$<>"r" AND i$<>"u" AND i$<>"d" THEN GO TO 200
230 LET xant=x: LET yant=y
240 IF i$="l" THEN IF x>=1 THEN LET x=x-1
250 IF i$="r" THEN IF x<31 THEN LET x=x+1
260 IF i$="u" THEN IF y>1 THEN LET y=y-1
270 IF i$="d" THEN IF y<20 THEN LET y=y+1
280 GO SUB 300
290 GO TO 200
300 LET f=0
310 IF z>128 THEN LET f=1: LET z=z-128
320 LET b=0
330 IF z>64 THEN LET b=1: LET z=z-64
340 LET p=INT (z/8)
350 LET co=z-(p*8)
360 PRINT AT yant,xant; OVER 0; FLASH f; INK co; BRIGHT b; PAPER p;z$
370 LET z$= SCREEN$ (y,x)
380 LET z=ATTR (y,x)
390 PRINT AT y,x; OVER 1; FLASH 1; INK 2; BRIGHT 1;"\::"
400 PRINT AT 0,26;"     ": PRINT AT 0,26;y;" ";x
410 RETURN
420 CLS : CLEAR : BORDER 7: PRINT AT 0,0; INK 0;"Adios"
430 STOP
440 DATA 0,24,60,126,126,24,24,0,0,24,24,126,126,60,24,0
450 DATA 0,16,48,126,126,48,16,0,0,8,12,126,126,12,8,0
460 RESTORE 440
470 FOR i=0 TO 15
480 READ a
490 IF i<=7 THEN POKE USR "a"+i,a
500 IF i>7 THEN POKE USR "b"+(i-8),a
510 NEXT i
520 RESTORE 450
530 FOR i=0 TO 15
540 READ a
550 IF i<=7 THEN POKE USR "c"+i,a
560 IF i>7 THEN POKE USR "d"+(i-8),a
570 NEXT i
580 RETURN



lunes, 14 de diciembre de 2015

BASIC, no puedo localizar UDG's con SCREEN$ !!. He aqui una opción buena bonita y barata.

Una de las funciones más útiles que tiene el BASIC de nuestro ZX Spectrum es SCREEN$. 

Gracias a esta función podemos saber que carácter se encuentra presente en la pantalla, dadas las coordenadas X e Y.

En el modo de "texto" tenemos 22 líneas (Y) y 32 columnas (X). Es muy cómodo, utilizar SCREEN$ como mecanismo de detección de colisiones en un juego en el que hallamos usado caracteres (de 8x8) como gráficos. 

Como se puede ver en !Como me gustan los UDG! es muy sencillo usar los 20 caracteres de gráficos de usuario que nos facilita el Spectrum, para hacer nuestros propios sprites de 8x8. 

Los podemos usar en pantalla, y todo bien, hasta que se nos ocurre la brillante idea de usar SCREEN$ para obtenerlos de pantalla. SCREEN$ nos devolverá un vacío, dado que no es capaz de gestionar los UDG. Nuestro gozo en un pozo. 

He aquí unas cuantas líneas de código para tener nuestro propio "SCREEN$" y poder identificar los UDG en pantalla. 

La idea es la misma, le damos unas coordenadas de linea/columna, y el código nos devuelve el código UDG al cual pertenece. Si la variable de control (res) es un cero (0) es que el carácter que se encuentra en las coordenadas proporcionadas, no es un UDG. Si la variable de control res tiene un valor igual o superior a 144, nos está devolviendo el código del UDG que ha encontrado en esas coordenadas. 

  10 REM Localizacion de  UDG por coordenadas x,y
  20 REM igual que el SCREEN$(y,x) pero funciona con UDG
  30 REM vamos a cargar el UDG 149 (f)
  40 FOR i=0 TO 7
  50 POKE USR "f"+i,255
  60 NEXT i
  70 PRINT AT 7,13;CHR$ 149
  80 REM le damos las coordenadas y res nos devuelve el UDG
  90 LET x=13: LET y=7
 100 GO SUB 260
 110 PRINT AT 0,0;"El UDG es el ";res
 120 GO TO 310
 130 LET res=udg
 140 LET vY=y*8
 150 LET vX=x
 160 FOR S=0 TO 7
 170 LET iY=vY+S
 180 LET BLOCK=INT (iY/64)
 190 LET CROW=INT (iY/8)
 200 LET YR=iY-(CROW*8)
 210 LET CROW=CROW-(BLOCK*8)
 220 LET ADD=16384+BLOCK*2048+CROW*32+YR*256
 230 IF (PEEK ((USR (CHR$ udg))+s))<>(PEEK (add+vX)) THEN LET res=0: RETURN
 240 NEXT S
 250 RETURN
 260 FOR i=144 TO 164
 270 LET udg=i
 280 GO SUB 130
 290 IF res>=144 THEN RETURN
 300 NEXT i
 310 STOP
Hay varias cosas que tener en cuenta:


  • Las coornedas linea/columa las fijamos igual que en el SCREEN$. Ya se encarga el cógido de las "visicitudes" y "saltos" de las direcciones de memoria en pantalla. 
  • Está optimizado para UDG's de 8x8. Con un poco de paciencia y coco, se puede adaptar a 16x16, o 32x32 de forma sencilla. 
  • Puedes leer  "Jugando a los Sprites, episodio I" para ampliar la funcionalidad.
  • Si res vale cero(0), no es un UDG.
  • Si res es 144 o más , es un UDG y res es el código del mismo. 
  • Se compara byte a byte el caracter en pantalla, con la(s) definición(es) de(los) UDG.
  • Está optimizado para el mejor rendimiento (en caso de diferencia, aborta y al siguiente). 


Ahora ya no tienes excusa para usar los UDG's en esos juegos que puedes hacer y basar tu detección de colisiones de forma muy sencilla desde BASIC.



miércoles, 2 de diciembre de 2015

Que usar para programar el BASIC del Commodore 64 en tu PC.

Me puse como objetivo encontrar un entorno de programación  gráfico al estilo de BasinC para ZX Spectrum

La idea es tener una GUI (Graphical User Inerface) con todas las herramientas necesarias para la programación BASIC del Commodore 64 en nuestro PC. No solamente código fuente, sino herramientas gráficas y de sprites, manuales y otro tipo de complementos que nos permitan hacer todo desde un mismo sitio. 

Voy a resaltar CBM .prg Studio de Arthur Jordison

Es un entorno completo al estilo de los entornos de programación actuales, como puede ser Visual Studio o Eclipse. 

Traducido de su página web, podemos ver capacidades y funcionalidad: 

Permite realizar desarrollos para : 

  • Commodore 64 (and SuperCPU)
  • Commodore 128
  • Commodore VIC 20
  • Commodore 16
  • Commodore Plus/4
  • Commodore PET BASIC 2 machines, e.g. PET 2001
  • Commodore PET BASIC 4 machines, e.g. PET 4000/9000

Un resumen de sus capacidades es: 

  • Múltiples tipos de ficheros de código (ensamblador o BASIC) se pueden componer a un solo destino.
  • Ensamblador / Desemsamblador y Depurador integrado para 6502/6510/65816
  • Importación de programas (.prg, .T64 or .D64/.D71/.D81)
  • Exportación de programas (.prg, .p00)
  • Editor de Sprites
  • Editor de juegos de caracteres
  • Diseñador de pantallas 
  • Generador de códidos especuales de impresión
  • Visor de memoria
  • Importación y exportación de binarios
  • Herramienta de creación de discos .D64/.D71/.D81
  • Constantes en BASIC
  • Re-numerado y formateo de código 
  • Formateo automático de código ensamblador
  • Interfaz de usuario tipo MDI
  • Gran cantidad de manuales, ayuda y tutoriales

La verdad que es una herramienta muy completa y funcional. 

Una cosa que no termina de convencerme es que para compilar y ejecutar un proyecto, necesita un emulador externo configurado en la propia herramienta. 

Seguramente con el tiempo y adquiriendo experiencia con el entorno, esta circunstancia se verá justificada. 

En este enlace tenéis más imágenes de la herramienta en acción.