Volver menú revistas Volver página anterior

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.

N° 39 - Enero 1993
Amiga World

     LIBRERIAS     

 

Programación de librerías
ILBM
4ª Parte

Por Vicente Santos

FICHEROS PARA EL PROGRAMADOR

Hemos llegado al final. En este capítulo vamos a desarrollar los últimos ficheros de cabecera (¿cuántos llevamos?) y un par de ejemplos de uso de ilbm.library

Tenemos tres, los dos primeros para programas C:

- "ilbmbase.h" es una versión de "ilbmbase.i", el fichero que creamos en el capítulo 2 y que contiene la definición de la Base de la librería.

- "ilbm.h" contiene los modelos de estructuras, constantes y variables, necesarias para la lectura y escritura de ficheros IFF-ILBM, usando funciones de nuestra run-time. Ambos ficheros deben instalarse en el directorio ":incluse/" del compilador. Para ello pueden crear dentro de este un subdirectorio "/iff/" y copiarlos en él.

El tercero es para Ensamblador:

- "ilbm.i" es el equivalente de ilbm.h en formato estándar de Commodore (los usuarios de Devpac pueden obtener a partir de él uno en el formato especial que puede utilizar este ensamblador). El fichero presenta una pequeña diferencia con su colega para lenguaje C, en la macro encargarda de calcular el tamaño total de un fichero ILBM. En la versión C esta macro se utiliza sin argumentos mientras que en Ensamblador se le pasa como argumento la variable 2ilbmsz" (declarada también en ilbm.i).

Ejemplos:

En C

- ilbmsz = TotalSize()

- TOTALSIZE ilbmsz Instale ilbm.i en su ensamblador de la misma forma que los ficheros anteriores.

Y ahora vamos a ver un par de ejemplos de uso de la librería. Naturalmente son programas sencillos, pero pueden servir de "esqueleto" sobre los que crear sus propias aplicaciones.


USANDO ILBM.LIBRARY

Tenemos dos programas: "VerILBM.c" y "SalvarILBM.s". Ambos ejecutables sólo desde Shell/CLI.

- "VerILBM.c" es un lector/visualizador en C. Pasándole como argumento el nombre de un fichero, lo lee y muestra en su propia pantalla. Tal y como esta puede visualizar ficheros que contengas gráficos en alta o baja resolución y entrelazado en ambos modos. Debido a las limitaciones de esta primera versión de la librería, no sirve para ver gráficos en HAM o Halfbrite -para ello debe crear sus propias funciones de programa, si quiere intentarlo..- ni gráficos que contengan algún tipo de máscara. El programa empieza abriendo las librerías del sistema que necesita y, claro, también la nuestra -como verán, la apertura se hace de la misma forma-. A continuación abre el fichero indicando que queremos acceder a él sólo para leerlo. Y ahora empieza el baile. Para ver el fichero hay que disponer de alguno de los elementos de soporte gráfico del Amiga. En nuestro caso vamos a utilizar uno de Intuition, concretamente una pantalla de tipo CUSTOMSCREEN sin bara de título (SCREENQUIET). Lo que el programa no sabe es la resolución, profundidad y modo que deberá tener ésta para ajustarse al gráfico. Para averiguarlo contamos con los datos que nos facilita el propio fichero ILBM en sus chunks BMHD y CAMG. La lectura de BMHD, que nos dará las dimensiones y profundidad, se efectúa mediante una llamada a la función "GetBMHeader()". Esta nos devuelve un puntero a los datos del chunk para que a través de él obtengamos los que nos interesan. A continuación averiguamos el modo gráfico contenido en CAMG, letendo el chunk con "GetGfxMode()". COn los datos proporcionados por estas dos funciones, el programa abre la pantallam lista para reicbir el gráfico pero... antes necesita conocer su paleta de colores -si no queremos utilizar la que el Amiga inicializa por defecto y con la que nuestra obra de arte puede aparecer irreconocible-. Para averiguar que colores componen la paleta, utilizaremos la función "GetColMap()" que lee el chunk que la contiene:CMAP. Una vez obtenida la cargamos en los registros de color mediante la función "LoadRGB4()" de la "graphics.library". Y ya sólo falta leer el gráfico propiamente dicho, que está contenido en el chunk BODY y visualizarlo en la pantalla. Esto -y alguna cosilla más, como la descompresión si es necesaria- lo conseguimos llamando a la función "DisplayData()". Llegados a este punto, el porgrama hace una pausa para dejarnos ver el gráfico y finaliza cerrando pantalla, fichero y librerías.

- "SalvarILBM.s" es un escritor de ILBMs en Ensamblador, muy elemental. Dándote el nombre de un fichero -por ejemplo, SalvarILBM ram:test- dibuja un gráfico (bastante tonto) y lo salva en formato ILBM con compresión. Como es normal comienza abriendo las librerias necesarias. Tras esto abre una pantalla en baja resolución y sobre ella una ventana del mismo tamaño -ambas sin bordes y barra de título-. Hecho esto pinta su dibujo e inmediatamente empieza a salvarlo. Para ello abre un fichero con el nombre que especifique en la llamada al programa y modo de acceso escritura. El primer chunk a escribir es FORM y para esto el programa llama a la función "PutILBM()". Tras este escribe BMHD con las dimensiones, tipo de compresión, etc, usando la función "PutBMHeader()". La paleta de colores la salva llamando a "PutColMap()", la función encargada de escribir CMAP. Lo mismo hace con el modo gráfico, escribiendo el chunk CAMG con la llamada correspondiente a "PutGfxMode()". El orden en que el porgrama escribe estos chunks es el mismo que usa "Deluxe Paint III", aunque en sus propios programas puede emplear el que quiera, siempre que BMHD vaya inmediatamente antes que los otros dos. Para terminar, se salva el dibujo llamando a la función "SaveData()", encargada de escribir el chunk BODY. Una característica de los ficheros IFF en general y de los ILBM en particular, es que la cantidad de datos salvados en cada chunk debe ser par (por ejemplo 200 bytes, no 201 ni 199). En el caso de los ILBM generados con Amiga el único chunk que puede no cumplir este requisito es BODY, debido al algoritmo de compresión. Para comprobar si el chunk contendrá un número par de bytes el programa pide ayuda a la macro "ODD_SIZE" definida en "ilbm.i" (si escribe en C utilizad su hermana "OddSize()" de "ilbm.h"). Si el resultado de la macro es impar -por casualidad en este ejemplo sí que lo es- el programa escribe un byte extra al final del chunk. Si han leído los comentarios al respecto en "ilbm.i/ilbm.h" verán en el tamaño de BODY -no se suma al tamaño devuelto por "SaveData()-, pero sí hay que tenerle muy presente a la hora de calcular el tamaño total de fichero. Para esto nuestro ejemplo utiliza la macro "TOTALSIZE" (ver apartado sobre los ficheros de cabecera). Una vez obtenido la función encargada de escribirlo es "PutILBMSize()".

Una vez completada la escritura el programa hace una pequeña pausa para que de tiempo a ver su magnífico dibujo y, una vez transcurrida, cierra el fichero y los demás elementos del sistema, terminando su ejecución. Una vez compilado o ensamblado cada programa, hay que enlazarlos con la librería explorable "ilbm.lib" creada en el capítulo anterior. Para ayudalres en esta tarea disponen de los ficheros "VerILBM.lnk" y "SalvarILBM.ink", que pueden utilizar en la forma habitual: blink with VerILBM.lnk o blink with SalvarILBM.lnk. Sobre este último fichero e enlace debo hacer una advertencia: como verán utiliza el código de inicio "AStartup.obj". Este código no es usado por Devpac, pero como el programa está escrito para ser ensamblado con otros paquetes sin que de problemas, he decidido utilizarlo aquí. La versión de "AStartup.obj" que incluyo con los programas de ejemplo es la que aparecía, hace ya algún tiempo, en el Curso de Ensamblador de Amiga World. Aquellos que utilicen Metacomco MacroAssembler ya tienen en su paquete este mismo fichero, pero en versión más moderna. Para enlazar "SalvarILBM.o" con su "AStartup.obj", antes de ensamblar el código fuente deben editarlo para substituir la etiqueta "START:" por "_main:" (¿o es "main:" sin subrayado inicial?...).


CONCLUSION

El programa empieza abriendo las librerías del sistema que
necesita y, claro, también la nuestra -como verán, la apertu-
ra se hace de la misma forma

Y hasta aquí nuestra librería run-time. Para que vean con más claridad el trabajo que realiza cada una de sus funciones, los argumentos que necesitan y elvalor que devuelven he incluido un apéndice con unos "autodocs", un poco al estilo de los manuales oficiales, para que puedan emplearlo como guía de consulta rápida a la hora de desarrollar sus aplicaciones. Y ahora sí que hemos llegado al final. Espero que esta miniserie les haya resultado útil -amena y divertida ya se que no, lo reconozco, es un peñazo-, al menos para conocer un poco más a fondo lo que se esconde tras el sistema operativo con el que cuenta esa caja de circuitos tan genial que es el Amiga. Muchas gracias a los que hayan tenido la paciencia de aguantar hasta aquí y mil perdones a los que no, si llegan a leer esto.

/*********************************************************************
FICHERO.H : ilbm.h
DESCRIPCION : definición de estructuras y datos para lectura/escritura
de ficheros IFF-ILBM
*********************************************************************/

#ifndef IFF_ILBM_H
#define IFF_ILBM_H

#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifndef EXEC_IO_H
#include <exec/io.h>
#endif
#ifndef EXEC_MEMORY_H
#include <exec/memory.h>
#endif
#ifndef LIBRARIES_DOS_H
#include <libraries/dos.h>
#endif
#ifndef LIBRARIES_DOSEXTENS_H
#include <libraries/dosextern.h>
#endif
#ifndef GRAPHICS_GFX_H
#include <graphics/diplay.h>
#endif
#ifndef GRAPHICS_RASTPORT_H
#include <graphics/rastport.h>
#endif
#ifndef GRAPHICS_VIEW_H
#include <graphics/view.h>
#endif


/* MODELO DE ESTRUCTURA Y DATOS PARA BMHD */

struct BitMapHeader {
UWORD w, h; /* dimensiones del grafico */
WORD x, y; /* posicion */
UBYTE nPlanes; /* planos de profundidad */
UBYTE masking; /* tipo de mascara */
UBYTE compression; /* tipo de compresion */
UBYTE pad1; /* byte para alineamiento */
UWORD transparentColor; /* color transparente */
BYTE xAspect, yAspect; /* relacion de aspecto */
WORD pageWidth, pageHeight; /* dim pantalla original */
};

/* tipo de mascara (para la version 1.0 de ilbm.library siempre 0) */
#define NOMASK 0

/* tipo de compresion */

#define NOCOMP 0
#define BYTERUN1 1


/* MASCARAS PARA LECTURA/ESCRITURA DE MODO GRAFICO */

/* Flags de ViewModes cuyo uso en CAMG no es apropiado para la lectura o
escritura de ficheros ILBM, segun especificaciones de Electronic Arts y
Commodore */

#define BADFLAGS (SPRITES | VP_HIDE | GENLOCK_AUDIO | GENLOCK_VIDEO)
#define FLAGMASK (~BADFLAGS)
#define CAMGMASK (FLAGMASK & 0X0000FFFFL)


/* COMPROBACION DE TAMANO DE CHUNKS

Si el tamano de un chunk es impar es necesario escribir un byte extra
despues de los datos. Estos bytes extras NO SE SUMAN al tamano
del chunk pero SI al tamano total del fichero.
La macro siguiente comprueba si el tamano es impar */

#define OddSize(cksize) ((cksize) & 1)


/* TAMANO DE FICHERO
El tamano de un fichero IFF es igual a la suma de:
tamano (numero de bytes de datos) de cada chunk +
8 bytes por cabecera de cada chunk +
4 bytes por identificador de subtipo +
numero total de bytes extras que sea necesario escribir
(no se tienen en cuenta los 4 bytes de FORM ni los 4 utilizados
para escribir el tamano total del fichero). */

LONG bmhdsz, camgsz, cmapsz, bodysz; /* tamano de chunks */
LONG subidsz; /* tamano de identificador */
LONG ilbmsz; /* Tamano total de fichero */
long npads = 0; /* tamano de bytes extras */

#define CKHSIZE 8 /* tamano de cabeceras */
#define TOTALCKH (CKHSIZE * 4) /* total de cabeceras */

/* ATENCION!!! La siguiente macro calcula el tamano total que se
pasa como argumento a la funcion "PutILBMSize()", pero solo debe
usarse en programas que salven ficheros completos, no paletas
(ILBMs sin chunk BODY) */

#define TotalSize()
(bmhds+camgsz+cmapsz+bodysz+subidsz+npads+TOTALCKH)

#endif

/* FIN DE ilbm.h ****************************************************/


/********************************************************************
FICHERO.H : ilbmbase.h
DESCRIPCION : definicion de ILBMBase para programas en C.
DESARROLLO : 21-06-92 - Creacion (V. Santos)
********************************************************************/


#ifndef IFF_ILBMBASE_H
#define IFF_ILBMBASE_H

#ifndel EXEC_TYPES_H
#include <exec/types.h>
#endif

#ifndef EXEC_LISTS_H
#include <exec/lists.h>
#endif

#ifndef EXEC_LIBRARIES_H
#include <exec/libraries.h>
#endif


/* ESTRUCTURA DE ILBMBase
==================================================================*/

struct ILBMBase {
struct Library LibNode;
UBYTE Flags;
UBYTE Pad;
ULONG SysLib;
ULONG DosLib;
ULONG SegList;
};

#define ILBMNOMBRE "ilbm.library"

#endif

/* FIN DE ilbmbase.h
********************************************************************/

FROM LIB:AStartup.obj+SalvarILBM.o
LIB LIB:amiga.lib+LIB:ilbm.lib
TO SalvarILBM
VERBOSE
************************************************************************
* PROGRAMA : SalvarILBM.s *
* VERSION : 1.0 *
* DESCRIPCION : Ejemplo de escritura de IFF-ILBMs con ilbm.library 1.0 *
* DESARROLLO : 22-06-92 - Creacion (V. Santos) *
************************************************************************

* FICHEROS DE CABECERA
========================================================================

INCDIR "sys:devpac/include.cbm/"
NOLIST
INCLUDE "exec/types.i"
INCLUDE "exec/memory.i"
INCLUDE "libraries/dos.i"
INCLUDE "libraries/dosextens.i"
INCLUDE "intuition/intuition.i"
INCLUDE "iff/ilbmbase.i"
INCLUDE "iff/ilbm.i"
LIST

* DECLARACIONES EXTERNAS
=======================================================================

XDEF START ; para "AStartup.obj"

* REFERENCIAS EXTERNAS
=======================================================================


NOTA DE REDACCION
 
Los listados publicados corresponden a
las primeras partes
o rutinas de este capítulo.
 
El resto puede encontrarse en nuestros
discos
Amiga World 39

Volver menú revistas Volver página anterior