Tema 11 - Otras órdenes habituales

11.1 Memoria libre

Nos puede interesar saber cuanta memoria libre nos queda para usar en nuestro programa. Existe una función que nos lo dice, FRE, aunque se usa de una forma un poco "extraña":

PRINT FRE(0)

Por ejemplo, la orden anterior muestra un valor de 42.249 bytes en un CPC6128.

La otra forma de usar FRE, que además intenta reorganizar la memoria antes de informar del espacio libre, es

PRINT FRE("")

Si lo que queremos es limitar esa cantidad de memoria libre, podemos utilizar la orden MEMORY:

MEMORY 16000

 

11.2 Acceso a posiciones de memoria: PEEK, POKE

La orden PEEK se usa para ver el valor de una cierta posición de memoria. Su opuesta es la orden POKE, que escribe un valor en una posición de memoria. Su uso es avanzado, porque un usuario "normal" no sabe qué hay en cada zona de memoria del ordenador, por lo que en general no le sería útil leer zonas de memoria al azar, pero además si escribimos en zonas de memoria sin saber lo que hacemos, y estas zonas están reservadas por el sistema, los resultados serán imprevisibles...

Aun así, vamos a ver un primer ejemplo.

La memoria de pantalla empieza en la dirección &C000 (49.152). Si trabajamos en MODE 2, que sólo permite dos colores, cada bit a partir de esa dirección valdrá 0 si un punto está "sin encender" (en el color azul de fondo, si no hemos cambiado la paleta) y valdrá 1 si el punto está "encendido" (en el color amarillo de primer plano, antes de cambiar la paleta). Esto no es cierto del todo, luego lo matizaremos, pero para las primera pruebas nos servirá.

PEEK no nos devuelve un bit, sino un byte, un conjunto de 8 bits. Por eso, si entramos a MODE 2 y decimos que nos muestre el contenido de la posición inicial de la pantalla (la &C000) obtendremos 0, porque los primeros 8 puntos tendrán el color de fondo:

MODE 2: PRINT PEEK(&C000)
0

De forma similar, POKE no modifica un bit, sino un byte, un conjunto de 8 bits. Por tanto, si en MODE 2 decimos que guarde el valor 255 (8 bits seguidos, todos con el valor 1) en la posición inicial de la pantalla (la &C000), se dibujarán 8 puntos amarillos al principio de la pantalla:

POKE &C000, 255

Ejemplo Poke

Una forma un poco más legible de conseguir lo mismo sería usando directamente el valor en binario. Por ejemplo, podríamos dibujar cuatro puntos y cuatro huecos alternados con:

POKE &C000, &X10101010

(Nota: lo que hemos hecho funciona en la primera línea de pantalla, pero no es tan sencillo dibujar en cualquier punto, porque la memoria de pantalla de los CPC está entrelazada: después de la línea 0 (la primera, en la posición &C000) va la 8 (la primera línea de la segunda fila de texto, en &C050), luego la 16 (en &C0A0), y así sucesivamente. De este modo, la segunda línea de pantalla está después de todas las primeras líneas de cada fila de texto y tras unos cuantos bytes "de sobra", en &C8000. Esto no es especialmente sencillo de manipular. Si quieres descubrir más, puedes echar un vistazo a la "Amstrad CPC Firmware Guide" -en la versión PDF de 2002, tienes estos datos en la página 30-).

 

Un segundo uso, todavía más avanzado, es la creación de programas en código máquina desde el propio intérprete de Basic: reservaríamos una zona de memoria con MEMORY, guardaríamos a partir de esa posición los bytes que forman nuestras órdenes en código máquina, y finalmente llamaríamos a esa rutina con CALL. Por supuesto, hacer esto sin conocimientos de código máquina es enormemente PELIGROSO. Un ejemplo, que borre la pantalla podría ser

 10 DATA CD,6C,BB: ' CALL &BB6C
 20 DATA C9: ' RET
 30 longitud = 3
 40 MEMORY 39999
 50 FOR n=40000 TO 40000+longitud
 60 READ a$:POKE n,VAL("&"+a$)
 70 NEXT
 80 CALL 40000

 

11.3 Espaciado y formateo al escribir

Hasta ahora, si queríamos colocar algo en pantalla lo hacíamos con LOCATE, pero cuando se trata de "situaciones fáciles", como dejar una serie de espacios en blanco en la línea actual, hay otras alternativas más sencillas:

  • El punto y coma (;) escribe dos datos, uno a continuación de otro. Si es un número positivo, dejará un espacio antes de él.
  • La coma (,) escribe dos datos, separados por una cierta cantidad de espacios (por defecto, 13).
  • Con la orden ZONE podemos cambiar el tamaño del salto que da una coma: ZONE 8.
  • Para dejar varios espacios entre un texto y otro, podemos usar también SPC(n).
  • TAB es parecido, pero salta "n" espacios, sino que salta hasta la posición "n".

Vamos a ver un ejemplo de todos ellos:

 10 CLS
 20 a$="Hola": b$="Adios"
 30 n1=5: n2=10
 40 PRINT n1;n2
 50 PRINT a$;b$
 60 PRINT a$,b$
 70 ZONE 8
 80 PRINT a$,b$
 90 PRINT a$; SPC(10); b$
 100 PRINT a$; TAB(10); b$


Además, podemos mejorar la apariencia de los números usando PRINT USING. Algunos de los códigos de formato básicos que permite son:

  • Cada almohadilla (#) indica la posición de una cifra numérica: PRINT USING "####"; 23 escribiría el número 23 ocupando 4 posiciones en pantalla.
  • Si no indicamos suficientes almohadillas, el número se escribirá entero pero con un signo % delante, para avisar del fallo: PRINT USING "##"; 2345
  • Con un punto (.) podemos indicar cuantas cifras decimales queremos: PRINT USING "####.##"; 23
  • Si usamos una coma justo antes del punto decimal, se mostrarán las cifras agrupadas de 3 en 3, con separadores en los miles: PRINT USING "#####,.##"; 2345

Como ejemplo:

 10 CLS
 20 PRINT USING "####"; 23
 30 PRINT USING "##"; 2345
 40 PRINT USING "####.##"; 23
 50 PRINT USING "#####,.##"; 2345

 

11.4 Ventanas de texto

Nos puede interesar trabajar sólo con una parte de la pantalla, por ejemplo si queremos dejar fijo un menú en la zona superior. Para tareas como éstas, podemos definir "ventanas" en la pantalla.

Una ventana se define con WINDOW. Se le asigna un número del 1 al 7, y se indican sus dimensiones (columna inicial, columna final, línea inicial, líena final):

WINDOW #1, 10, 30, 5, 20

A partir de ahora, podemos escribir en ella con PRINT #1, borrar sólo esa zona de pantalla con CLS #1, situarnos dentro de ella con LOCATE #1, o asignarle colores de pluma y fondo con PEN #1 y PAPER #1. Un ejemplo podría ser:

 10 MODE 1
 20 WINDOW #1, 10, 30, 5, 20
 30 PAPER #1, 2
 40 CLS #1
 50 LOCATE #1, 2, 2
 60 PRINT #1, "Dentro"
 70 LOCATE 2,2
 80 PRINT "Fuera"

Si al crear la ventana, no le asignamos un número del uno al 7, se asumirá que nos referimos al canal 0 (#0), la pantalla por defecto.

Otra posibilidad relacionada con ventanas, pero quizá menos útil, es que también podemos intercambiar las características de dos ventanas con WINDOW SWAP: Si hacemos WINDOW SWAP 1,2 la que antes era la ventana 2 ahora se llamará 1 y viceversa. Así, un PRINT #2 escribirá en la que antes era la ventana

 10 MODE 1
 15 ' Primera ventana
 20 WINDOW #1, 10, 30, 5, 10
 30 PAPER #1, 2
 40 CLS #1
 50 LOCATE #1, 2, 2
 60 PRINT #1, "Ventana 1"
 65 ' Segunda ventana
 70 WINDOW #2, 10, 30, 12, 20
 80 PAPER #2, 3
 90 CLS #2
 100 LOCATE #2, 2, 2
 110 PRINT #2, "Ventana 2"
 125 ' Intercambio
 130 WINDOW SWAP 1,2
 140 LOCATE #1, 2, 3
 150 PRINT #1, "Ventana 1 (b)"
 160 LOCATE #2, 2, 3
 170 PRINT #2, "Ventana 2 (b)"