lunes, 8 de febrero de 2016

Como hacer un PRINT AT Y,X de Sinclair BASIC en Commodore 64 BASIC

Una de las cosas que más me llamó la atención cuando me pasé de Sinclair BASIC a Commodore 64 BASIC a cacharrear, es que no hay  ¡ PRINT AT !.

¿Como se les puede haber pasado el implementar esta funcionalidad en el comando PRINT del BASIC ?. ¡En qué estaban pensando!. 

Bueno, he aquí un par de posibilidades para simular el comando PRINT AT. 

Una de ellas, la primera, se basa en "engañar" al comando PRINT del BASIC, con alguna instrucción que otra, para que se posicione donde queremos imprimir en pantalla. 

La segunda, fija directamente el cursor en la posición de la pantalla donde queremos imprimir, usando POKEs. 

La primera quedaría tal que así: 

10 REM Buscando una altgernativa al PRINT AT
20 REM de Sinclair BASIC para el C64 BASIC
30 REM Posibilidad 1. Usando caracteres especiales
40 REM del C64 BASIC y el comando BASIC
50 REM ********* Modo 1 **************************
55 print "{clear}"
60 X$="{home}{right*39}"
70 Y$="{down*24}"
80 x=1:y=1
90 print left$(x$,x)right$(y$,y)" AAAAAAAAAAAAAAAAAAAAAA";
100 x=2:y=2 110
110 print left$(x$,x)right$(y$,y)"hola";
120 x=2:y=10 130
130 print left$(x$,x)right$(y$,y)"mundo";
140 x=10:y=10 150
150 print left$(x$,x)right$(y$,y)"hola mundo!";
152 x=1:y=12:print left$(x$,x)right$(y$,y)"";
155 rem *************************************

Si ejecutamos el programa, vemos el resultado : 

















Usamos X e Y para fijar donde queremos imprimir, y luego imprimimos el texto en pantalla usando print left$(x$,x)right$(y$,y) + el texto que queremos.

 Hay una segunda opción, que es la que más me gusta, que es directamente posicionar el cursor en pantalla, donde queremos imprimir, y luego simplemente usar PRINT. 

En C64 BASIC esto se consigue con la siguiente rutina, que puedes usar en tus programas: 

999 REM Rutina que posiciona el cursor en un determinado sitio
1000 poke 780,0:REM fijamos cero para resetear
1010 poke 781,row:REM a memoria la fila(X)
1020 poke 782,col:REM a memoria la columna(Y)
1030 sys 65520 : REM fijamos el cursor en X,Y
1040 return


Los POKE 781 y 782 son los registros .X y .Y en la máquina, y la istrucción sys 65520 posiciona el cursor en pantalla en las coordenadas que están en 781 y 782.

SAREG 030C    780     Storage for 6502 .A Register
SXREG 030D    781     Storage for 5502 .X Register
SYREG 030E    782     Storage for 6502 .Y Register
PLOT    $FFF0  65520 Read/set X,Y cursor position

Usar la rutina se convierte simplemente en esto: 

200 row = 5:col = 10:gosub 1000
210 print "hola"

Este método es mucho mejor y más limpio que el primero, en mi opinión, aunque ambos nos permiten saber donde hemos dejado el cursor después de haber impreso en pantalla. 

Un pequeño vídeo del programa de demostración en cuestión: 



Como entorno de desarrollo estoy usando CBM .prg Studio  de Arthur Jordison .

Puedes descargar el entorno de aquí y el proyecto de este ejemplo de este otro enlace

He aqui otro ejemplo del modo 2, usando otros registros del sistema: 

10 PRINT CHR$(147) 20 SP = 20: ZE = 3: A$ = "Good Morning!": GOSUB 1000: GOSUB 2000 30 SP = 10: ZE = 3: A$ = "I'm the Commodore 64": GOSUB 1000: GOSUB 2000 40 SP = 12: ZE = 6: A$ = "And what is your name ?": GOSUB 1000 100 END 1000 REM cursor positioning and printing 1010 POKE 211,SP :POKE 214, ZE: SYS 58640 : PRINT A$ 1020 RETURN 2000 REM delay-loop 2010 FOR X=0 TO 3000: NEXT X 2020 RETURN



viernes, 29 de enero de 2016

Ejemplo de marquesina rotante en BASIC

Bueno, es simplemente un texto que va de derecha a izquierda en pantalla, aparece y desaparece en bucle. 

Como nosotros leemos de izquierda a derecha, lo conveniente es que el texto aparezca de derecha a izquierda. 

Puedes descargar el código fuente en formato TAP de este enlace.


Abajo el código BASIC.
Es muy sencillo 

10 CLS
20 PRINT AT 0,0;"Pulsa q para terminar"
30 LET M$="MARQUESINA"
40 LET C=1
50 FOR I=31 TO 0 STEP -1
60 PRINT AT 20,I;M$(1 TO C)
70 IF C<LEN (M$) THEN LET C=c+1
80 IF (31-i)>=LEN (m$) THEN PRINT AT 20,i+LEN (m$);" "
90 GO SUB 170
100 NEXT I
110 FOR i=1 TO LEN (m$) STEP 1
120 PRINT AT 20,0;m$(i TO LEN (m$))
130 PRINT AT 20,LEN (m$)-i;" "
140 GO SUB 170
150 NEXT i
160 GO TO 40
170 LET i$=INKEY$
180 IF i$="q" THEN STOP
190 RETURN
 


martes, 26 de enero de 2016

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

En el ejemplo de "ZX Spectrum, pasando un "misil" por en medio de la pantalla en BASIC" habíamos visto como acometer el pintado sobre lo que hubiese en pantalla, de una línea recta, sobre lo que hubiese en pantalla.

En este ejemplo, hemos ampliado para que, dado: 
  • Unas coordenadas de origen (X,Y) en modo carácter.
  • Número de celdas para el desplazamiento.
  • Una dirección (arriba, abajo y diagonales).


... nos pinte la línea de 8 bits, a modo de misil y atraviese lo que esté en el camino, respetando sus propiedades de dibujo, color y fondo. 

Dado que tenemos un límite de 2 colores, por celda, veremos el efecto de como va cambiando de color a medida que el misil va pasando por encima del contenido.

Los efectos más deseables, se logran con el fondo "blanco" y sin brillo ni intermitencia. En el ejemplo se usan estos modos, para que se vea como el programa es capaz de respetar las propiedades de cada cosa. 

Veamos el programa en acción: 


Con este ejemplo, podemos extrapolar subrutinas, para poder implementar el lanzamiento de misiles en el juego Retro8ogue

Además, para optimizar al máximo el paso a código máquina, usando el compilador HiBasic, he usado las directivas de compilación apropiadas para marcar (casi) todas las variables como enteros positivos, además de las longitudes máximas de cada variable cadena usada. 

El compilador de BASIC funciona de forma óptima, cuando trabaja con enteros, y más, si son enteros positivos. 

Todas estas optimizaciones permiten dejar el compilado con solo 278 bytes para variables, además de presentar el mejor rendimiento. 

Puedes descargar el código BASIC de este enlace.

El ejemplo en código máquina se encuentra en este enlace.