|
|||||
| El Amiga Me Encanta ha conseguido el permiso por escrito de IDG Comunications España para ofrecer los artículos de la revista Amiga World España. |
| LIBRERÍAS EN EL AMIGA | ![]() |
Por Fernando Marcos A unos y a otros va dirigido este artículo. A los primeros para que vean que no es una pérdida de tiempo trabajar con estas ayudas, y para los segundos para demostrar que no es tan fiero el león como lo pintan.
Pero en primer lugar, la teoría...
|
Las librerías permiten hacer cosas |
|---|
Son terriblemente potentes, pero |
El empleo de las funciones permite, |
Voy a comentar otro tipo de llamadas al sistema que aumentan aún más la potencia de este sistema de programación. Hasta el momento, lo único que se podía hacer era mandarle datos al sistema operativo. Ahora explicaré cómo recibir datos útiles de las rutinas que llamemos para poder aprovecharlos en nuestros programas.
Un caso típico es que se necesite memoria para almacenar información. Lo normal es emplear variables, pero es engorroso si, por ejemplo, se quiere guardar y manipular una pantalla o un fichero largo, o cargar sonidos digitalizados (si te interesa esto último tienes un artículo en el número 50 de Commodore World).
El listado número dos es un ejemplo de un programa que reserva memoria para uso posterior. En la variable TAM guardamos la cantidad de memoria que deseamos en bytes. El valor de la variable CUSTOM es un valor definido que indica que la memoria la puede reservar como mejor le venga, en cuanto a colocación dentro de todo el mapa. Con otros valores puedes hacer que reserve toda la memoria disponible o que la reserve en la zona alta, etc.
Es obvioque no se le puede indicar a la rutina dónde quieres que esté la memoria, ya que esa zona puede estar ya ocupada (debido a la gran complejidad de su distribución), por lo que deberá ser el propio ordenador el que seleccione su ubicación y nuestro programa el que se adapte a esa contingencia. Por tanto, al llamar a la rutina, hay que esperar un valor de retorno. Por mi, muy bien, pero al Basic, ¿quién le dice que le van a contestar? ¿Próximo capítulo? ¡No! ¡Ahora mismo!
Para eso están las funciones. Son llamadas al sistema operativo con la característica de que devuelven un valor que debe ser leído. Para decirle al AmigaBasic que una determinada rutina debe ser empleada como función se utiliza el comando DECLARE FUNCTION con el formato:
DECLARE FUNCTION función&LIBRARY
Con esta instrucción se prepara al intérprete para que asigne un espacio al resultado de la rutina. Para recibir el valor sólo tienes que igualar una variable larga entera (del tipo "&") a la función, de esta forma:
resultado&=RUTINA&(.....
En este caso, la variable resultado& contiene la dirección de memoria donde se ha reservado el bloque. Si por alguna razón esta reserva no ha sido posible (no había memoria suficiente, errores, etc.) la variable devuelve un valor cero.
En otros casos, el contenido de esta variable varía. Para saber qué valores devuelve cada variable, te recomiendo que busques en algún libro especializado los valores que devuelve cada una. Aquí sólo comentaré las más comunes.
Aquí está la clave de todo el asunto. Dentro de estos ficheros se encuentra toda la información que necesita el programa para saber qué rutinas tiene disponibles y qué parámetros necesita. Se podría pensar que esto es una pérdida de tiempo inútil, ya que podríamos tener documentación de todas ellas y llamarlas directamente (estilo C64). La ventaja de emplear estos "inútiles" ficheros es que si algún día alguien cambia la ROM del Amiga, no será preciso reescribir los programas: bastará con cambiar los ficheros BMAP.
Su formato es muy sencillo. Es así:
Nombre de la rutina 1.
Byte cero.
Incremento a la tabla de saltos en 16 bit.
n bytes indicando registros empleados.
Byte cero.
Nombre de la rutina 2.
...
El nombre de la rutina es el nombre que se emplea para llamar a esta rutina (ej: MOVE, DRAW, ALLOC-MEM, etc). El byte cero marca el fin del nombre.
El incremento es la cantidad que hay que sumar a la posición inicial de la ROM para saber dónde es´ta la rutina real. Por ejemplo, si la ROM empieza en la posición $F0000, y el incremento es de $213F, la rutina será llamada a la posición $F213F (en hexadecimal).
Los n bytes que indican los registros son números consecutivos, con un cero al final, que indican en qué registros van los parámetros y en qué orden hay que dárselos. El microprocesador MC68000 que lleva el Amiga tiene 15 registros de 32 bits que se nombran:
- Registro de datos.
D0 a D7:
- Registros de direcciones.
A0 a A6:
- Apuntador de pila.
A7:
El registro A7 no se emplea por ser el apuntador de pila del sistema, y por lo delicado de su uso. Cada uno de los registros restantes tiene un número:
1: Registro D0
2: Registro D1
3: Registro D2
4: Registro D3
5: Registro D4
6: Registro D5
7: Registro D6
8: Registro D7
9: Registro A0
10: Registro A1
11: Registro A2
12: Registro A3
13: Registro A4
14 y 15: Registros no accesibles. Uso interno.
De todas formas, todo esto lo ilustra mejor un ejemplo. Supongamos que existe una rutina en la ROM llamada "LINE" que traza una línea entre dos puntos, definidos por (D0,D1) y (D2,D3). También necesita el Rastport, que se pasará en el registro A3. La rutina comienza en la posición $5632 a partir del comienzo de la ROM. El fichero que describiría esta rutina (por ejemplo "RUTINAS.BMAP") sería:
- Nombre de la rutina.
"L", "I", "N", "E"
- Fin de nombre de la rutina.
CHR$(0)
- Posición de inicio
CHR$($56), CHR$($32)
- Rastport.
CHR$(12)
- Registros D1 y D2.
CHR$(1), CHR$(2).
- Registros D3 y D4.
CHR$(3), CHR$(4).
- Fin de registros.
CHR$(0).
Si hubiese más rutinas en ese fichero BMAP vendrían a continuación del cero de fin de descripción de rutina (no del cero de fin de nombre). Pero para poder ver esto mucho mejor teclea el listado tres: es un pequeño utilitario llamado BMAP.DUMP que se encarga de tomar un fichero BMAP e imprimir todos sus contenidos, bien por pantalla, bien por impresora. Es de gran utilidad tener un mapa de los registros de cada rutina, porque muchas veces no te acuerdas, por ejemplo, de que la rutina DRAW lleva tres parámetros, etc. De todas formas, aun viendo este volcado, no es posible adivinar qué debe ir en cada registro, por lo que seguirás necesitando un manual del sistema operativo que te explique las necesidades de cada rutina. Te recomiendo el ROM Kernel Reference Manual, que es el original editado por Commodore por ser el que describe con más profundidad todos los recovecos de esta increíble máquina. Para conseguirlo tendrás que buscar un poco, pero mientras podrás seguir leyendo estos estupendos artículos (ejem!!)...
Programa library1.bas 'Llamada a GRAPHICS.LIBRARY. .83 '(C)f.Marcos 1988 .119 '(C)Commodore World 1988. .813 LIBRARY "graphics.library" .332 CALL move&(WINDOW(8),50,50) .975 CALL draw&(WINDOW(8),450,170) .871 LIBRARY CLOSE .234
Numero de lineas: 7 |
| LISTADO 1 |
|---|
Programa: alloc.bas 'Demo de reserva de memoria. .839 'Necesita EXEC.BMAP .595 DECLARE FUNCTION AllocMem& LIBRARY . 53 ' FreeMem& no devuelve valores. .700 LIBRARY "exec.library" .156 PUBLIC&=65537& 'Puede reservar la memoria .269 'donde quiera en memoria. .675 TAM&= 3000& 'Numero de bytes .715 'a reservar. .641 BUF& = AllocMem&(TAM&,PUBLIC&) 'Reserva. .726 IF BUF&=0 THEN 'Mp se ha podido reservar... .397 PRINT "No puedo reservar memoria!" .405 GOTO NoAlloc .311 END IF .654 PRINT TAM&"bytes reservados en"BUF& .391 PRINT "Pulse una tecla para liberar memoria." .744 WHILE INKEY$="":WEND .865 CALL FreeMem&(BUF&,TAM&) 'Orden de liberar memoria. .703 NoAlloc: .114 LIBRARY CLOSE .234 PRINT "Programa terminado." .821
Numero de lineas: 21 |
| LISTADO 2 |
Programa: Bmap.Dump 'Library Parameters Displayer. . 51 'Ver 2.04 6-12-87 F.Marcos .201 'Hi! guys!!! .731 ' .273 CLS:INPUT "BMAP file";bmap$ .921 INPUT "(P)antalla o (I)mpresora: ",fi$ .447 fi$=UCASE$(fi$) .478 IF fi$="P" THEN sal$="SCRN:" .695 IF fi$="I" THEN sal$="PAR:" .731 IF sal$="" THEN sal$="SCRN:":PRINT "Periferico asumido: pantalla" .319 OPEN bmap$ FOR INPUT AS 1 .309 OPEN sal$ FOR OUTPUT AS 2 .158 WHILE NOT EOF(1) .271 char$=CHR$(32) .386 WHILE char$<>CHR$(0) .599 PRINT#2,char$;:char$=INPUT$(1,1) .658 WEND:PRINT#2,TAB(25) .952 a$=INPUT$(2,1) .551 reg=1 .359 WHILE req<>0 .330 reg=ASC(INPUT$(1,1)+CHR$(0)) .167 IF reg<>0 THEN GOSUB Conv .727 WEND . 89 PRINT#2," " .272 WEND . 89 CLOSE:END .404 Conv: IF reg<=8 THEN PRINT#2,"D"MID$(STR$(reg-1),2)", ";:RETURN .291 PRINT#2,"A"MID$(STR$(reg-9),2)", ";:RETURN .200 Numero de lineas: 28 |
| LISTADO 3 |
| Envía esta página web a un amigo: Esta opción está desactivada temporalmente, rogamos disculpen las molestias |
|