(Parte II)
Por Francisco Javier Rodriguez
La filosofía seguida en el desarrollo de los ordenadores Amiga, fue la de crear un ordenador personal que facilitase todos los aspectos de comunicación entre la máquina y el usuario. También se encargó, mediante la importante colaboración de Electronic Arts, del desarrollo de un nuevo formato de ficheros gráficos; dicho formato recibió el nombre de IFF (Interchange File Format). |
El mes pasado se vio la parte teórica de la operación con pantallas gráficas desde el modo RAW DATA, es decir filas de datos. Dicho modo trabaja sobre disco al igual que el IFF, pero el primero presenta ciertas características que hacen útil su uso en determinadas situaciones.
En esta segunda parte se verá la parte que se refiere a la programación; es decir la conversión de las ideas expuestas en la primera parte a su realización en forma de programa.
El lenguaje empleado para la realización del programa es el Ensamblador, ya que éste posee una mayor flexibilidad a la hora de trabajar con periféricos, además de ser más rápido que otro tipo de lenguajes. Decir también que las rutinas que se encuentran en esta segunda parte sólo pueden trabajar con pantallas gráficas de 320 x 200, es decir el modo gráfico de baja resolución; pudiendo adecuarlo fácilmente para el trabajo con pantallas gráficas en otro tipo de resoluciones.
Comenzando a programar
Los primeros pasos a dar, para la realización del programa, es la definición de las funciones que éste deberá tener, así como realizar un esquema de ejecución. De esta forma la primera tarea que deberá realizar el programa será la carga de la pantalla IFF para su visualización en pantalla. Dicha tarea puede realizarse de diversas formas, pero se ha optado por la más sencilla y rápida, aunque ello repercuta en un mayor consumo de memoria:
1) Introducir nombre del fichero gráfico.
2) Buscar y, si existe, cargar fichero en memoria.
3) Descomprimir datos y visualizarlos en pantalla.
Para introducir el nombre del fichero gráfico es necesario abrir una ventana, con lo cual ya sabemos el primer paso en concreto que ha de realizar el programa, a continuación se ha de recoger del buffer permanece vacío esta operación se repetirá, a no ser que se haya tecleado la palabra 'fin'; comando con el que se saldrá del programa. El nombre del programa deberá contener la unidad donde se encuentra el disco, así como el directorio en cuestión. Por ejemplo:
DF1:FICHERO
DF2:DIBUJOS/BAJA-RESOLUCION/PAISAJES/FICHERO
En caso de no definir el número de la unidad, se tomará DF0; por defecto.
Una vez que esté introducido el nombre del fichero, el siguiente paso es su búsqueda en el disco, emitiendo un mensaje de error en caso de que éste no se encuentre presente en el recorrido definido por el usuario. Si se produce un error por este motivo, el programa saltará de nuevo a la rutina de introducción de nombre.
En caso de que el fichero se encuentre presente en el camino definido por el usuario, el programa saltará a la rutina de carga; volcando todo el contenido del fichero a memoria, lo que supone un máximo de 32KB. Una vez se encuentren los datos en memoria, y sabiendo que el formato IFF no varía en las posiciones de su información, se accederá directamente a los datos del gráfico en cuestión además de reflejarlos en pantalla.
En el siguiente paso se tomará la información del gráfico directamente desde los Bitplanes en las posiciones de pantalla, para a continuación salvar éstos a un fichero en disco bajo el nuevo formato (RAW data). El nombre que recibirá el nuevo fichero será el mismo que el de lectura, con el sufijo '-RAW'.
De este modo si se cargó el fichero IFF 'DIBUJO', su versión en formato RAW DATA se llamará 'DIBUJO-RAW'; grabándose en el mismo directorio donde se encontraba el fichero origen. Una vez realizada esta operación, el programa bifurcará de nuevo hacia la entrada del nombre de fichero. Como se dijo anteriormente se saldrá del programa mediante el comando 'FIN', de lo contrario éste permanecerá ejecutándose dentro de un bucle.
Si se desea cambiar el nombre del fichero, bastará con utilizar el comando RENAME del AmigaDOS. Por otro lado si desea que el fichero se refleje en el WorkBench, bastará con crear un icono para éste; nombrándose (y siguiendo con el ejemplo) 'DIBUJO-RAW.INFO'.
Estos son, de forma superficial, los diferentes pasos que deben ser realizados en el programa. A continuación se explicarán, de una forma más extensa y detallada, cada uno de ellos.
El primer paso, visto anteriormente, es establecer una línea de comunicación con el usuario. Para ello es necesario abrir una ventana de programa, donde el usuario puede introducir datos, el programa recoger los mismos y emitir algún mensaje de error si éste se produce (una sea en la carga del fichero o en otros aspectos).
Existen diversos caminos para solicitar una ventana de comunicación, de entre ellos los más utilizados son la función CON: y RAW: tratándolas el sistema como si de periféricos se tratara. Debido a su carácter de periféricos, bastará con realizar una llamada a la función OPEN() de la DOS.Library; además de poder utilizar las funciones READ() y WRITE de la misma librería para leer y escribir los datos respectivamente.
Para abrir el periférico (en este caso nuestra ventana de comunicación) ha de pasarse un parámetro a la función OPEN(), con el cual se determinará si éste va a ser sólo de lectura, de escritura o de lectura y escritura. Nuestro caso se corresponde con la última opción con lo cual el código que hay que pasar en la rutina se corresponde con el 1005 (estándar del sistema en todo este tipo de operaciones).
Una vez conocido el código es necesario saber el tipo de 'periférico' que se va a utilizar, ya sea RAW: o CON:. En nuestro caso se utilizará esta última, ya que permite la entrada de una cadena mediante la pulsación de la tecla 'ENTER' al final de la misma; mientras que el periférico RAW: toma el dato correspondiente a la pulsación de una tecla.
En el Amiga, ya se ha comentado varias veces, la mayoría de las funciones que ofrece el sistema requiere ciertas estructuras; en este caso es necesario definir la estructura del periférico CON:, el cual contendrá la posición inicial y final en los ejes X e Y, así como el nombre del mismo. Por ejemplo:
"CON:20/10/100/200/Mi-ventana"
A continuación se verá la rutina completa encargada de abrir la ventana en cuestión (recuerde que los listados incluidos en este artículo se encuentran escritos en ensamblador, por lo que será necesario un macroensamblador para editar y ensamblar el mismo):
OpenLib = -408
CloseLib = -414
ExecBase = 4
Open = -30
Mode = 1005
Init: move.l execbase,a6
lea dosname,a1
moveq #0,d0
jsr OpenLib(a6)
move.l d0,dosBase
Beq error
move.l d0,d6
move.l #name,d1
move.l #Mode,d2
jsr open(a6)
move.l d0,conhandle
beq error
error rts
dosname: dc.b "dos.library"
name: dc.b "CON:20/10/100/200/Mi-ventana",0
even
dosBase: dc.l 0
conhandle: dc.l 0
Esta es una sencilla rutina mediante la cual puede abrir el puerto de comunicación con el teclado en cualquiera de sus programas. Como ha podido observar es necesario realizar unas cuantas llamadas previas antes de realizar la operación de apertura. Dichas llamadas se corresponden con la apertura de la Dos.Library, dentro de la cual se ubica la función OPEN().
Los datos definidos en 'name', se corresponden con la estructura de la ventana, mientras que el definido en 'Mode' se corresponde con uno de los modos descritos anteriormente, en concreto el de lectura y/o escritura.
Una de las similitudes de este modo, en comparación con RAW: (el periférico, no el formato gráfico) es que los dos formatos permiten la introducción de códigos ASCII, además de que también es posible la introducción de códigos referentes al color, así como otros códigos de control del AMIGA.
Una vez abierta la línea de comunicación con el usuario, el siguiente paso a realizar es la entrada de datos correspondiente a la unidad, así como el camino y el nombre del fichero que se ha de leer. Para ello existe otra función muy útil de la DOS.library: READ(). Dicha función, en este modo de operación, recoge la cadena de caracteres escrita por el usuario hasta que éste haya pulsado la tecla 'RETURN'.
Decir que el número de caracteres que el usuario puede insertar en la cadena, se ve limitado al buffer definido para este propósito. En nuestro programa el buffer de datos (escritos por el usuario) se limita a 80 caracteres; cifra ésta más que suficiente para indicar los parámetros deseados.
En caso de que así lo desee el usuario, esta cifra puede ser modificada, ya que bastará con cambiar el número definido en la etiqueta 'Buffer' por el correspondiente a la nueva capacidad del mismo. La rutina encargada de tomar los datos desde el teclado, mediante la función READ(), es la siguiente:
Read =-42
move.l conhandle,d1
move.l #buffer,d2
move.l #80,d3
jsr ead(a6)
Buffer: blk.b 80
Con esta sencilla rutina se puede tomar la cadena escrita por el usuario en la ventana de comunicación. Los parámetros que se pasan a la rutina READ(), son los siguientes: en D1 la estructura correspondiente a la ventana de comunicación (habilitada como periférico), en D2 se pasa la dirección en la que se encuentra ubicado el Buffer de datos, y por último en D3 se pasa el número máximo de datos que puede tomar para lectura.
Recuerde que los datos, a los que se hace referencia, debe ser el número de la unidad de discos, directorio y por último nombre del fichero gráfico IFF.
El siguiente paso que se debe dar en el programa es, una vez conocidos los datos anteriores, cargar el fichero en memoria. Para ello nos serviremos de dos funciones que ya hemos utilizado anteriormente: OPEN() para abrir el fichero en cuestión y READ(), con el cual leeremos los datos del fichero.
La operación de la apertura de fichero se realiza de la misma forma que se utilizó para abrir la ventana de comunicación:
Openfichero:
move.l dosBase,a6
move.l #buffer,d1
move.l #mode,d2
jsr open(a6)
move.l d0,fichandle
beq error
En esta rutina nos volvemos a encontrar de nuevo con el registro 'Mode', el cual define el estado del fichero con el que se va a trabajar; es decir si es para lectura o para lectura/escritura. En la rutina, se define para lectura/escritura, aunque simplemente se vayan a leer datos y no escribirlos.
Una vez que se ha 'abierto' el fichero en cuestión, y se encuentra listo para trabajar con él, se procederá a la lectura de los datos que contienen. En este caso se leerá el total del fichero IFF, para posteriormente trabajar con éste. Como en el anterior caso, los pasos a seguir son los mismos que en la lectura del teclado:
move.l do,d1
move.l #buffer2,d2
move.l #32000,d3
jsr read(a6)
beq error
Buffer2: blk.b 32000
Como en el caso anterior D1 contendrá la estructura del fichero, D2 la dirección a partir de la cual se almacenarán los datos en memoria y D3 contendrá la cantidad máxima de datos a leer. En esta ocasión se ha limitado el número máximo de datos a leer a 32000; es decir 32K.
Esta es una cantidad más elevada de lo que posee cualquier fichero gráfico IFF en baja resolución, pero tampoco se sabe la cantidad real que puede ocupar cada uno de estos ficheros, ya que varía dependiendo de lo efectiva que resulte la compresión del fichero IFF. Recordamos que los ficheros gráficos IFF se encuentran comprimidos bajo el método RUN BYTE 1.
A continuación se deben definir las posiciones de memoria que corresponderán con la pantalla gráfica a visualizar. Para ello primero se debe de proceder a la reserva de memoria (mediante la función ALLOCMEM de la EXEC.library) para dicho fin, ya que de lo contrario podría suceder que ésta, en el transcurso de la ejecución del programa, fuese utilizada por otros. También se debe observar que la memoria que utilizaremos para la visualización de la pantalla gráfica debe de ser en modo CHIP MEMORY. Para ello utilizaremos una rutina empleada en el programa que apareció en el artículo del pasado número:
clear = $10002
Allocmem = -198
Tamaño = $8000
move.l 4,a6
move.l #tamaño,d0
move.l #clear,d1
jsr allocmem(a6)
move.l d0,baseplano
beq error1
La etiqueta 'Tamaño' define precisamente el número de bytes que componen una pantalla gráfica en baja resolución ($8000 = 32000 bytes en decimal). Por otro lado en la etiqueta 'CLEAR' se definen las características que tendrá la memoria reservada, en nuestro caso se corresponden con $10000 (borrar la memoria) + 2 (memoria CHIP) = $10002.
En caso de que no se encuentre el espacio contiguo de memoria suficiente, con las características descritas, la rutina retornará con el valor 0 en el registro D0 lo cual significa que se ha producido error, y por tanto el programa bifurcará hacia la rutina de tratamiento de error correspondiente. En caso de que la operación se haya realizado con éxito, se devolverá la dirección de memoria a partir de la cual se ha reservado la memoria en el registro D0.
A continuación se procederá a descomprimir los datos, almacenando éstos a partir de la memoria reservada para página de vídeo. Recordará que en el pasado número se publicó el metodo mediante el cual se encontraban comprimidos los datos, por lo que bastará con crear la rutina que siga los pasos definidos en el RUN BYTE 1.
tanto la rutina de descompresión, del fichero IFF, como el resto del programa (almacenamiento del gráfico en modo RAW DATA) se verán en la tercera y última parte de esta serie, la cual se publicará en el próximo mes.
En este mes se publica una parte parcial del programa, la cual podrá ser completada con las rutinas incluidas en el próximo artículo.
PROGRAMA
' CONVERTIDOR IFF = RAW DATA'
'
' (C) 1990 Francisco javier Rodriguez
'
' (C) 1990 AMIGA WORLD
'
OpenLib = -408
CloseLib = -414
ExecBase = 4
Open = -30
Mode = 1005
clear = $10002
Allocmem = -198
Tamaño = $8000
Read = -42
Init: move.l execbase,a6
lea dosname,a1
moveq #0,d0
jsr OpenLib(a6)
move.l d0,dosBase
Beq error
move.l d0,a6
move,l #name,d1
move,l #Mode,d2
jsr open(a6)
move.l d0,conhandle
beq error
error: rts
move.l conhandle,d1
move.l #buffer,d2
move.l #80,d3
jsr read(a6)
Openfichero: move.l dosBase,a6
move.l #buffer,d1
move.l #mode,d2
jsr open(a6)
move.l d0,fichhandle
beq error
move.l d0,d1
move.l #buffer2,d2
move.l #32000,d3
jsr read(a6)
beq error
move.l 4,a6
move.l #tamaño,d0
move.l #clear,d1
jsr allocmem(a6)
move.l d0,baseplano
beq error1
Buffer2: blk.b 32000
Buffer: blk.b 80
dosname: dc.b "dos.library"
name: dc.b "CON:20/10/100/200/Mi_ventana",0
even
dosbase: dc.l 0
conhandle: dc.l 0
|
|