|
(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 trabaj 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 jecució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 permace vacío esta operación
se repetirá, a no ser que se haya tecleado la palabra 'fin';
comando con el que se saldra 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 (ua 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; aademá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 datoc orrespondiente 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 loq ue 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 abrirr 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 funcion 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 memorira 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 video. 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
|
|