
   __  ___ ___ ___ ___ _ _   ___ ___
   | \ |_|  |  |_| |__ | |   |__ [_
   |_/ | |  |  | | |   | |__ |__ __]


          por Shawn Hargreaves



Un fichero de datos de Allegro es como un fichero zip ya que consta de
muchas piezas de datos diferentes una tras otra, y opcionalmente
comprimidas. Esto significa que tu juego no necesita llenar el disco con
cientos de ficheros pequeos, y hace la programacin ms fcil porque puedes
cargar todo con una simple funcin cuando se inicializa tu programa. Otra
ventaja es que el algoritmo LZSS de compresin de ficheros funciona mejor
con uno grande que con muchos pequeos.

Los ficheros de datos tienen la extensin .dat, y pueden ser creados y
editados grficamente con el programa grabber o desde la lnea de comandos
con la utilidad dat. Pueden ser almacenados como ficheros separados y
cargados en memoria con la funcin load_datafile(), o puedes usar la
utilidad dat2s para convertirlos en cdigo ensamblador que puede ser
enlazado directamente con tu ejecutable.

Cada fichero de datos contiene un nmero de objetos, de varios tipos. Los
tipos de objeto son representados con un entero de 32 bits, que es
interpretado como una cadena de cuatro caracteres ASCII. Estas identidades
pueden ser construidas con la macro DAT_ID(), por ejemplo: un objeto DATA es
representado con DAT_ID('D','A','T','A'), o puedes usar las constantes DAT_*
predefinidas para los tipos estndar de datos:

   DAT_FILE - "FILE"
      Un fichero de datos, que contiene una lista de otros objetos. Los
      objetos de ficheros de datos pueden ser anidados dentro de otros,
      permitindote crear estructuras jerrquicas de cualquier profundidad.

   DAT_DATA - "DATA"
      Un bloque de datos binarios. Allegro trata todos los tipos
      desconocidos como objetos de datos binarios, por lo que no necesitas
      usar esta identificacin: puedes crear formatos de objetos propios
      usando las identificaciones que quieras.

   DAT_FONT - "FONT"
      Una fuente.

   DAT_SAMPLE - "SAMP"
      Un sample de sonido digital.

   DAT_MIDI - "MIDI"
      Un fichero MIDI.

   DAT_PATCH - "PAT "
      Un patch Gravis (instrumento MIDI).

   DAT_FLI - "FLIC"
      Una animacin FLI o FLC.

   DAT_BITMAP - "BMP "
      Un bitmap.

   DAT_RLE_SPRITE - "RLE "
      Un sprite codificado RLE.

   DAT_C_SPRITE - "CMP "
      Un sprite compilado.

   DAT_XC_SPRITE - "XCMP"
      Un sprite compilado en modo-X.

   DAT_PALETTE - "PAL "
      Una paleta de 256 colores.

   DAT_PROPERTY - "prop"
      Una propiedad de objeto (mira abajo). Nunca encontrars directamente
      este tipo de objeto, pero debes saber que es tratado especialmente por
      el cdigo de ficheros de datos.

   DAT_INFO - "info"
      La utilidad grabber usa este objeto para almacenar informacin sobre
      el fichero de datos. Como propiedades de objetos, no deberas
      encontrar esto nunca, pero deberas evitar usar esta identificacin
      para los formatos de objetos propios que vayas a crear.

   DAT_END - -1
      Marca especial usada para indicar el final de un fichero de datos.

Cada objeto puede tener cualquier nmero de propiedades adjuntas. Estas son
cadenas ASCII que describen los atributos del objeto, como el nombre y de
dnde vino. Como los objetos mismos, las propiedades son identificadas por
un entero de identidad de 32 bits construido a partir de una cadena de
caracteres con la macro DAT_ID(). Allegro define estas propiedades estndar:

   "NAME"
      Nombre del objeto.

   "ORIG"
      El origen del objeto, ej: nombre del fichero desde el cual lo creaste.

   "DATE"
      Una marca de fecha, usada por el comando update de las utilidades
      grabber y dat. Esta es el tiempo de modificacin del fichero desde el
      cual creaste el objeto, en formato "mm-dd-aa, hh:mm".

   "XPOS"
      Para objetos bitmaps que fueron creados desde una imagen ms grande,
      la posicin x del origen en el bitmap padre.

   "YPOS"
      Para objetos bitmaps que fueron creados desde una imagen ms grande,
      la posicin y del origen en el bitmap padre.

   "XSIZ"
      Para objetos bitmaps que fueron creados desde una imagen ms grande,
      el ancho de la regin seleccionada.

   "YSIZ"
      Para objetos bitmaps que fueron creados desde una imagen ms grande,
      la altura de la regin seleccionada.

Las propiedades "PACK", "HNAM", "HPRE", "BACK", "XGRD", y "YGRD" tambin son
usadas internamente por grabber, pero puedes usar cualquier otra
identidad que quieras para almacenar informacin sobre tus objetos.


===================================
======== Usando el Grabber ========
===================================


Varias opciones pueden ser ajustadas usando los botones y campos de texto de
la parte superior de la pantalla. Puedes editar el nombre del fichero
de datos, el nombre del fichero de cabecera para exportar los ndices de tus
objetos (deja esto en blanco si no quieres crear un fichero de cabecera), y
la cadena de prefijo para las definiciones del fichero de cabecera. Puedes
cambiar los ajustes de la rejilla para recoger bitmaps, y alterar el modo de
compresin (mira abajo). Tambin puedes activar o desactivar backups: si la
caja esta marcada, la versin antigua ser renombrada con la extensin .bak
cuando salves tu fichero de datos.

El contenido del fichero de datos aparece en la caja abajo a la izquierda de
la pantalla, y puedes seleccionarlo con el ratn o los cursores. Puedes
hacer una seleccin mltiple apretando las teclas shift o control mientras
pinchas en la lista o mueves los cursores. El objeto seleccionado puede ser
editado con opciones del men Object, o usando el men de atajo que aparece
al pulsar Esc o pinchar con el botn derecho sobre el objeto. El doble click
realiza en un objeto una funcin que vara segn el tipo de ste. Los
bitmaps y fuentes son enseados a pantalla completa (usa las teclas menos y
plus para hacer zoom), los samples y ficheros MIDI son reproducidos, y las
paletas son seleccionadas (significa que sern usadas cuando visualices o
exportes un bitmap).

Puedes crear nuevos objetos usando los mens o pulsando Insert cuando la
lista de tems tiene el foco de entrada. Para hacer ficheros de datos
anidados, crea un objeto FILE (New/Datafile), y seleccinalo antes de
insertar otros objetos.

Para insertar informacin en un fichero de datos debes crear primero un
objeto del tipo apropiado, y seleccionar el comando grab (atajo del teclado
ctrl+G). Para la mayora de objetos esto visualizar un selector de ficheros
para que selecciones el fichero a leer, pero para objetos grficos (bitmaps,
sprites RLE, sprites compilados y paletas) recoger los datos del contenido
del buffer de imagen, por lo que primero debes cargar un dibujo en este
buffer con el comando File/Read Bitmap (atajo del teclado ctrl+G). Puedes
usar el ratn o las flechas para seleccionar la porcin de imagen que
quieres recoger. Con el ratn, selecciona la esquina superior izquierda,
pincha y mantn pulsado el botn izquierdo, mueve a la esquina inferior
derecha del rea que deseas coger y suelta el botn. Pulsa el botn derecho
para cancelar la operacin. Con el teclado, usa las flechas para seleccionar
la esquina superior izquierda, pulsa Espacio o Enter, ajusta el tamao con
los cursores, y pulsa Espacio o Enter otra vez. Por defecto, la posicin se
ajustar a una rejilla de 16x16, que puede ser ajustada cambiando los
valores de los campos X-grid e Y-grid. Alternativamente puedes usar el
comando Box Grab, en cuyo caso debes tener un marco de color #255 alrededor
de tus sprites, y entonces puedes pinchar una vez dentro del marco para
recoger su contenido.

Ten en cuenta que la paleta de colores no se almacena junto con los objetos
bitmap y sprite. Para almacenar el contenido completo de un fichero PCX o
BMP, tendrs que crear tanto un objeto bitmap como palette, e insertar los
datos en ambos. Cuando cargues de nuevo el fichero de datos, ste
probablemente ser visualizado con la paleta errnea. Puedes corregir esto
haciendo doble click en el objeto palette, que seleccionar su contenido
como la paleta actual, con lo que ser usada en la visualizacin y
exportacin de bitmaps.

Las propiedades del objeto seleccionado son mostradas en el recuadro a la
derecha de la lista de objetos. Las propiedades pueden ser editadas haciendo
doble click en una de ellas, borradas seleccionando una y pulsando la tecla
Supr. Puedes insertar nuevas propiedades pulsando Insert mientras la lista
de propiedades tiene el foco de entrada, o usando el comando Object/Set
Property. Los nombres de los objetos son almacenados como propiedades NAME,
por lo que el comando rename no es ms que un atajo para editar esta
propiedad.

Para simplificar el proceso de recogida de varias imgenes desde un mismo
bitmap (por ejemplo un conjunto de frames que forman una animacin), puedes
usar el comando File/Grab from Grid. Como el comando normal grab, ste usa
los datos del buffer de imagen, por lo que debes leer un bitmap antes de
usarlo. Entonces podrs ajustar los parmetros de recogida, introducir un
nombre para los nuevos objetos, y elegir el tipo de objetos a crear (bitmap,
sprite RLE o sprite compilado). Ya que varios objetos pueden ser creados,
sus nombres sern creados aadiendo un nmero al final del nombre que
escribiste, por ejemplo, si introduces "un_dibujo", el grabber crear
objetos "un_dibujo000", "un_dibujo001", etc. Hay dos modos de recogida:
usando los marcos con color 255, o usando una rejilla regular. La opcin de
rejilla regular simplemente divide el bitmap en varios trozos del mismo
tamao. Si activas la bandera Skip Empties, el grabber ignorara los trozos
que no contienen datos (es decir, aquellos que son de un mismo color). La
opcin de color 255 es ms flexible. Espera que el bitmap tenga informacin
describiendo la posicin y tamao de cada trozo, en forma de un marco
dibujado con el color 255. La forma ms segura para hacer esto es rellenar
toda la imagen excepto las partes que quieres con el color 255, pero el
grabber debera ser capaz de entender formas ms complicadas, incluso si
simplemente dibujas lneas de color 255 a la izquierda y arriba del rea que
quieres recoger. Para imgenes truecolor donde el color 255 no significa
nada, puedes usar un marco de color cian (azul y verde al mximo, rojo a
cero), con un solo pixel amarillo (rojo y verde al mximo, azul a cero) en
la esquina superior izquierda del marco.

Por defecto el grabber funcionar en una resolucin 640x480, usando la
profundidad de color ms alta que pueda visualizar tu tarjeta grfica. Si
quieres evitar esto, puedes especificar resoluciones o profundidades de
color alternativas desde la lnea de comando, ej: "grabber -8" para un modo
de 256 colores, "grabber -16" para grficos de 16 bits hicolor, "grabber
-320x200" para usar el modo VGA 13h, o "grabber 1024x768". Atencin: el
editar imgenes truecolor en modos de 256 colores es muy lento, y el grabber
es difcil de usar con resoluciones menores que 640x400.

Puedes configurar el grabber para usar herramientas externas de edicin de
datos, ajustando algunas variables del fichero allegro.cfg. Estas son del
tipo "tipo=comando", donde tipo es una identidad de objeto de cuatro letras,
y el comando es el programa que quieres invocar para editar este tipo de
datos. Para que estas variables sean visibles, el fichero allegro.cfg debe
estar en el mismo directorio que el ejecutable del grabber, o en un
directorio apuntado por la variable de entorno ALLEGRO. Para invocar esta
caracterstica, selecciona el comando Shell Edit o pulsa ctrl+Z. El grabber
intentar invocar la herramienta con la versin original del fichero si sabe
desde dnde conseguiste los datos, de otro modo crear el objeto desde un
fichero temporal antes la edicin.



===================================
======== El archivador DAT ========
===================================


Como alternativa al programa grfico grabber, puedes usar la utilidad de
lnea de comando dat. Esta acepta las siguientes opciones:

   '-a <files>'
      Aade los fichero especificados al fichero de datos, ejemplo:

         dat fichero.dat -a title.pcx scream.wav

      Si los objetos ya estn presentes en el fichero de datos, sus
      contenidos actuales sern sustituidos. Los nombres de los objetos
      nuevos sern generados a partir de los nombres de los ficheros de
      entrada, y el tipo de objeto ser detectado a partir de la extensin.
      En algunos casos esto es ambiguo, por ejemplo un fichero PCX puede ser
      ledo como bitmap, sprite RLE, sprite compilado u objeto de fuente,
      por lo que debes especificar explcitamente el tipo de objeto con la
      bandera '-t'. Por ejemplo, para insertar alien.pcx como un sprite RLE,
      usa el comando:

         dat fichero.dat -a alien.pcx -t RLE

   '-bpp profundidad'
      Especifica el formato de color con el que se deben recoger los datos
      bitmap (profundidades vlidas son 8, 15, 16, 24 y 32 bits por pixel).

   '-c0' - sin compresin
   '-c1' - comprime los objetos individualmente
   '-c2' - compresin global de todo el fichero de datos
      Ajusta el modo de compresin (mira abajo). Este puede ser usado para
      convertir el fichero de datos de un formato a otro, o en combinacin
      con cualquier otra opcin.

   '-d <objetos>'
      Borra los objetos especificados del fichero de datos.

   '-e <objetos>'

      Extrae los objetos especificados del fichero de datos. Para extraer
      todo, usa la mscara * como nombre de objeto. Para ajustar el nombre o
      directorio de salida, usa la opcin '-o filename'. Por ejemplo, para
      extraer un objeto llamado TITLE_SCREEN al fichero title.pcx, usa el
      comando:

         dat fichero.dat -e title_screen -o title.pcx

      Para extraer el contenido del fichero de datos al directorio
      c:\output, usa:

         dat fichero.dat -e * -o c:\output\

   '-h ficherosalida.h'
      Nombre del fichero de cabecera, para exportar ndices de definiciones
      de objetos. Esto puede ser usado para producir un fichero de cabecera
      de un fichero de datos, o en combinacin con cualquier otro comando.
      Puedes usar la opcin '-p cadenaprefijo' para ajustar una cadena de
      prefijo para las definiciones de objetos.

   '-k'
      Conserva los nombres originales al recoger objetos. Sin este
      parmetro, un fichero llamado image.pcx ser importado como un objeto
      llamado IMAGE_PCX, para asegurarse de que todos los nombres de objeto
      son smbolos vlidos para las definiciones de los ficheros de
      cabecera.

   '-l'
      Muestra el contenido de un fichero de datos. Esto puede ser combinado
      con la opcin '-v' para mostrar las propiedades de los objetos junto
      con los nombres, y puedes especificar objetos particulares para que
      produzcan un listado parcial.

   '-m ficherodependencias'
      Escribe un conjunto de dependencias makefile en el fichero
      especificado, que puede ser usado para actualizar automticamente el
      fichero de datos cuando los datos origen cambien.

   '-s0' - no recortar: salva todo
   '-s1' - recorta informacin especifica del grabber del fichero
   '-s2' - borra todas las propiedades y nombres de los objetos del fichero
      Ajusta el modo de recorte (mira abajo). Esto puede ser usado para
      recortar las propiedades de un fichero de datos, o en combinacin con
      cualquier otra opcin.

   '-u'
      Actualiza el contenido de un fichero de datos. Mira abajo.

   '-v'
      Selecciona el modo verbose. Esto puede ser combinado con cualquier
      otra opcin para producir descripciones ms detalladas.

   '<objetos> PROP=valor'
      Ajusta una propiedad de los objetos especificados. Esto funciona como
      las variables de entorno, en tanto que ajustar una propiedad a una
      cadena vaca borra la propiedad. Ya que los nombres son almacenados
      como propiedades NAME, puedes usar este comando para renombrar
      objetos. Por ejemplo, para renombrar MI_OBJETO a VAYA_NOMBRE_ESTUPIDO,
      usa el comando:

         dat fichero.dat mi_objeto NAME=vaya_nombre_estupido

      Puedes usar la mscara * para aplicar la propiedad a todo en el
      fichero de datos, por ejemplo: para quitar la propiedad ORIG del
      fichero de datos, podras hacer:

         dat fichero.dat * ORIG=

Puedes crear una jerarqua de ficheros de datos anidados insertando un
fichero de datos dentro de otro con el comando '-a'. Los objetos de los
ficheros de datos anidados pueden ser referenciados como
"nombrepadre/nombreobjeto". Por ejemplo, si el fichero de datos fichero.dat
contiene un fichero de datos anidado llamado ficheroanidado, que contiene un
bitmap llamado eldibujo, puedes exportar el bitmap con el comando:

   dat fichero.dat -e ficheroanidado/eldibujo -o salida.pcx



=====================================
======== Informacin variada ========
=====================================


Los ficheros de datos pueden ser salvados usando cualquiera de los tres
tipos de compresin, seleccionados desde la lista superior derecha de la
pantalla del grabber, o con las opciones '-c0', '-c1', y '-c2' de la
utilidad dat. Con el tipo 0, los datos no son comprimidos. Tipo 1 comprime
cada objeto individualmente, mientras que 2 usa una compresin global sobre
el fichero entero. Por norma, la compresin global dar resultados
ligeramente mejores que la compresin por objeto, pero no debera ser usada
si quieres cargar dinmicamente objetos especficos con la funcin
load_datafile_object().

Tambin hay tres modos de recorte para salvar ficheros de datos,
seleccionados con el comando File/Save Stripped de grabber, o usando los
parmetros del dat '-s0', '-s1' y '-s2'. Con recorte cero, todas las
propiedades son guardadas en el fichero de datos, que es normalmente lo que
quieres. Con el modo de recorte 1, las propiedades especficas del grabber
(aquellas que describen el origen y fecha de cada objeto) sern recortadas,
lo que reducir marginalmente el tamao del fichero, pero evitar que el
comando de actualizacin funcione. Para reducir todo lo posible el fichero,
el modo de recorte 2 borra todas las propiedades, incluyendo los nombres de
objetos y cualquier propiedad propia que hayas aadido. Este nivel de
recorte obviamente debera ser usado con extrema precaucin, aunque en
algunos casos puede ser posible recuperar los nombres de los objetos incluso
despus de que hayan sido borrados del fichero de datos. Si las utilidades
grabber y dat no pueden encontrar las propiedades de los nombres en el
fichero de datos, buscarn un fichero de cabecera (.h) con el mismo nombre
en un intento de leer y recuperar los nombres. Esto est lejos de funcionar
sin problemas, y no funcionar para ficheros de datos anidados, pero en
algunas situaciones permite leer nombres a partir de los ficheros de
cabecera.

Tanto la utilidad grabber como dat tienen un comando de actualizacin, que
recorre todo el fichero de datos comprobando si algn objeto ha cambiado, y
reconstruyendo aquellos que son antiguos. Esto depende de las propiedades de
origen y fecha que fueron ajustadas al recoger los datos en primer lugar,
por lo que no funcionar si has recortado estas propiedades. Este comando
puede ser muy til si creas un fichero de datos que contiene cientos de
objetos recogidos de bitmaps externos, y luego quieres volver y cambiar
algunos bitmaps. En vez de intentar comprobar qu objetos son antiguos y
volver a recoger sus datos, el comando actualizar reparar automticamente
los objetos antiguos.

Las fuentes pueden ser ledas de ficheros .FNT libgrx, de ficheros .FNT 8x16
de la BIOS, y de bitmaps PCX y BMP. Cuando leas una fuente desde un fichero
bitmap, el tamao de cada carcter es determinado por la apariencia de la
imagen, que debera ser una rejilla rectangular que contiene todos los
caracteres ASCII desde espacio (32) hasta la tilde (126). Los espacios entre
las letras deben ser rellenados con color 255. Si cada carcter es de tamao
exacto 8x8 o 8x16, el grabber crear una fuente de tamao fijo, de otro modo
crear una fuente proporcional. Probablemente la manera ms fcil para
entender cmo funciona esto, es cargar el fichero demo.dat y exportar
TITLE_FONT en un fichero PCX. Mira cmo queda el fichero en tu programa de
dibujo: este es la forma en la que debes preparar tus fuentes...

Los ficheros de datos pueden ser encriptados con un password, teclendolo en
el campo "Password:" del grabber, o usando la opcin '-007 password' de la
utilidad dat. Los passwords pueden ser de hasta 256 caracteres, y son
sensibles a las maysculas. Los ficheros encriptados _no_ pueden ser ledos
sin el password, por lo que no lo olvides y vengas llorando a pedirme ayuda
:-) Para leer ficheros encriptados en tu programa, llama la funcin
packfile_password() antes de load_datafile(). Tambin es buena idea llamar
despus packfile_password(NULL), para que todo vuelva al estado normal.



================================================
======== Accediendo a ficheros de datos ========
================================================


Para acceder al contenido de un fichero de datos, necesitars saber dnde
esta cada objeto. El modo ms fcil de hacerlo es con el ndice de enteros,
usando el fichero de cabecera generado automticamente. Con el grabber,
escribe un nombre en el campo "Header:", y los ndices de los objetos sern
escritos en este fichero siempre que salves el fichero de datos. Con la
utilidad dat, usa la opcin '-h', ej: "dat fichero.dat -h cabecera.h". La
cabecera definir smbolos C de preprocesador para cada objeto en el fichero
de datos, por ejemplo:

   #define ALGUNOS_DATOS                    0        /* DATOS */
   #define ALGUNOS_DATOS_MAS                1        /* DATOS */

Para prevenir conflictos de nombres, puedes especificar una cadena de
prefijo para estas definiciones escribindola en el campo "Prefix:" del
grabber o usando la opcin '-p' del dat.

Para cargar un fichero de datos en memoria, llama la funcin:

   DATAFILE *load_datafile(char *nombrefichero);

Esto cargar todo el fichero, devolviendo un puntero a l, o NULL si hubo
algn error. Cuando ya no necesitas ms los datos, todo el bloque puede ser
liberado de memoria llamando:

   void unload_datafile(DATAFILE *dat);

Cuando cargas un fichero de datos, obtendrs un puntero a un array de
estructuras DATAFILE:

   typedef struct DATAFILE
   {
      void *dat;                    - puntero a los datos actuales
      int type;                     - identificacin del tipo de objeto
      long size;                    - tamao de los datos, en bytes
      DATAFILE_PROPERTY *prop;      - lista de propiedades del objeto
   } DATAFILE;

Realmente la nica pieza importante de informacin aqu es el campo dat, que
apunta al contenido del objeto. El tipo de los datos depender del tipo del
objeto: para bitmaps ser una estructura BITMAP de Allegro, para sprites RLE
ser una estructura RLE_SPRITE, para fuentes ser una estructura FONT, etc.
Si ests programando en C puedes pasar este puntero directamente a la
funcin relevante de la biblioteca Allegro, pero si ests usando C++,
necesitars definirlo al tipo apropiado para evitar que el compilador de
mensajes de error.

Por ejemplo, si tienes un fichero de datos llamado fichero.dat, que contiene
un bitmap llamado DIBUJO_CHACHI, y has creado un fichero de cabecera
datos.h, puedes mostrar el bitmap con el siguiente cdigo:

   #include "datos.h"

   void muestra_el_bitmap()
   {
      DATAFILE *dat;
      BITMAP *bmp;

      dat = load_datafile("fichero.dat");
      if (!dat) {
         /* muestra un error! */
            return;
      }

      bmp = (BITMAP *)dat[DIBUJO_CHACHI].dat;
      blit(bmp, screen, 0, 0, 0, 0, bmp->w, bmp->h);
      unload_datafile(dat);
   }

Si un fichero de datos contiene ficheros de datos anidados, el fichero de
cabecera usar el nombre del fichero de datos padre como prefijo de los
objetos. Tambin definir un nmero de contador con el nmero de objetos en
el fichero anidado, que puede ser til si por ejemplo el fichero hijo
contiene varios bitmaps que forman una animacin, y quieres que tu cdigo
automticamente ajuste el nmero de frames de la animacin con el del
fichero de datos.

Por ejemplo, el siguiente fichero de datos:

   "FILE" - FICHERO_ANIDADO
            |- "BMP" - UN_BITMAP
            |- "FONT" - UNA_FUENTE
   "DATA" - ALGUNOS_DATOS
   "DATA" - ALGUNOS_DATOS_MAS

produce el fichero de cabecera:

   #define FICHERO_ANIDADO                  0        /* FILE */

   #define FICHERO_ANIDADO_UN_BITMAP        0        /* BMP  */
   #define FICHERO_ANIDADO_UNA_FUENTE       1        /* FONT */
   #define FICHERO_ANIDADO_COUNT            2

   #define ALGUNOS_DATOS                    1        /* DATA */
   #define ALGUNOS_DATOS_MAS                2        /* DATA */

El fichero de datos principal contiene tres objetos (FICHERO_ANIDADO,
ALGUNOS_DATOS y ALGUNOS_DATOS_MAS) con ndices consecutivos, mientras que el
fichero de datos hijo contiene dos objetos UN_BITMAP y UNA_FUENTE. Para
acceder a estos objetos necesitas referenciar tanto el fichero de datos
padre como el hijo, ej:

   DATAFILE *dat = load_datafile("loquesea.dat");
   DATAFILE *anidado = (DATAFILE *)dat[FICHERO_ANIDADO].dat;
   FONT *lafuente = (FONT *)anidado[FICHERO_ANIDADO_UNA_FUENTE].dat;

Si necesitas acceder a las cadenas de propiedades de los objetos desde tu
programa, puedes usar la funcin:

   char *get_datafile_property(DATAFILE *dat, int type);

Esto devuelve un puntero a la cadena de propiedad si puede ser encontrada, y
una cadena vaca (que no es null!) si no existe. Un posible uso de esta
funcin es localizar objetos por nombre, en vez de usar ndices del fichero
de cabecera. El array de ficheros de datos acaba con un objeto del tipo
DAT_END, con lo que para buscar en el fichero de datos dat el objeto
"mi_objeto" podras usar el siguiente cdigo:

   for (i=0; dat[i].type != DAT_END; i++) {
      if (stricmp(get_datafile_property(dat+i, DAT_ID('N','A','M','E')),
                  "mi_objeto") == 0) {
         /* se encontr el objeto en el ndice i */
      }
   }
   /* no encontrado... */

Tambin es posible cargar objetos individuales selectivamente desde un
fichero de datos con la funcin:

   DATAFILE *load_datafile_object(char *nombrefichero, char *nombreobjeto);

Esto buscar en el fichero de datos un objeto con el nombre especificado,
por lo que obviamente no funcionar si recortas los nombres del fichero de
datos. Ya que esta funcin recorre todos los datos, ser extremadamente
lenta si has salvado el fichero con compresin global. Si planeas cargar
objetos individualmente, deberas salvar el fichero sin compresin o con
compresin individual por objeto. Como el puntero devuelto apunta solamente
a un objeto en vez de a un array de objetos, deberas acceder a l con la
sintaxis fichero_datos->dat, en vez de fichero_datos[ndice].dat, y cuando
acabes con l, deberas liberar el objeto con la funcin:

   void unload_datafile_object(DATAFILE *dat);

Alternativamente, las funciones packfile pueden abrir y leer directamente
los contenidos de un objeto de un fichero de datos. Puedes hacerlo llamando
pack_fopen() con un nombre falso de la forma "nombre.dat#nombre_objeto". El
contenido del objeto puede ser ledo entonces de modo normal que un fichero
de disco, por lo que cualquier funcin de acceso a ficheros de Allegro (ej:
load_pcx() y set_config_file()) puede ser usada para leer el objeto. Ten en
cuenta que no puedes escribir en los ficheros de datos de este modo: el
nombre falso es de slo lectura. Adems, deberas salvar el fichero sin
compresin o con compresin por objeto si planeas usar esta caracterstica.
Finalmente, ten en cuenta que los tipos de objetos especiales de Allegro no
tienen el mismo formato que los ficheros desde los que importas los datos,
por lo que si quieres usar load_pcx para leer una imagen desde un fichero de
datos, debes importarla como un trozo de datos binarios en vez de como un
objeto BITMAP.

Si has aadido un fichero de datos al final de tu ejecutable con la utilidad
exedat, usa loadfile("#") para leer todo en memoria,
load_datafile_object("#", "nombre_objeto") para cargar un objeto especifico,
y pack_fopen("#nombre_objeto", F_READ) para leer uno de los objetos
directamente con tu cdigo.

Por defecto, todos los objetos grficos cargados desde un fichero de datos
sern convertidos a la profundidad de color actual. Esta conversin puede
ser tanto mala como lenta, particularmente cuando cambia el formato de
truecolor a 256 colores, por lo que querrs desactivarla llamando
set_color_conversion(COLORCONV_NONE) o
set_color_conversion(COLORCONV_PARTIAL) antes de llamar load_datafile().



==============================================
======== Compilando ficheros de datos ========
==============================================


La utilidad dat2s puede ser usada para convertir un fichero de datos en
cdigo ensamblador (.s), que puede ser ensamblado y enlazado en tu programa.
Esto evita la necesidad de que un fichero separado acompae tu programa, y
significa que los datos sern cargados en memoria automticamente al iniciar
el programa. Sin embargo deberas considerar, que los ficheros de datos
tardan mucho en ser compilados, y no es posible comprimir los datos de este
modo.

El modo ms simple para invocar dat2s es con el comando:

   dat2s fichero.dat -o salida.s

El fichero ensamblador resultante puede ser ensamblado con el comando:

   gcc -c salida.s

Esto producir un objeto de mdulo llamado salida.o, que puede ser enlazado
con tu programa, por ejemplo:

   gcc miprog.c -o miprog.exe salida.o -lalleg

Entonces tu programa puede acceder al contenido del fichero de datos como
simples variables globales. Las definiciones de estas variables pueden ser
obtenidas indicndole a dat2s que haga un fichero de cabecera adems del
fichero en ensamblador, con la opcin '-h'. Puedes usar '-p' para tener una
cadena de prefijo para todos los nombres de los objetos. Por ejemplo, si al
fichero de datos siguiente:

   "BMP"  - UN_BITMAP
   "BMP"  - OTRO_BITMAP
   "SAMP" - EXPLOSION
   "PAL"  - UNOS_COLORES
   "FONT" - UNA_FUENTE

aplicas el comando:

   dat2s fichero.dat -o salida.s -h salida.h -p item

produce la cabecera:

   extern BITMAP item_un_bitmap;
   extern BITMAP item_otro_bitmap;
   extern SAMPLE item_explosion;
   extern PALETTE item_unos_colores;
   extern FONT item_una_fuente;
   extern DATAFILE item_data[];

Puedes hacer referencia a estos objetos directamente, por ejemplo:

   blit(&item_un_bitmap, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);

Alternativamente puedes usar al array de ficheros de datos item_data para
mantener la compatibilidad con el cdigo que originalmente fue escrito para
cargar un fichero de datos separado, con la sintaxis estndar
item_data[ndice].dat.



=================================
======== Objetos propios ========
=================================


Algunos objetos de un fichero de datos, por ejemplo paletas y animaciones
FLI, son tratados como simples bloques de datos binarios, pero otros son
cargados en formatos especiales como estructuras bitmap o sprites
compilados. Es posible extender el sistema de ficheros de datos para que
soporte tus propios tipos de objetos, ej: objetos mapa para un motor
isomtrico, o datos de nivel para un juego de plataformas. Obviamente el
grabber no tiene forma de entender estos datos, pero te permitir importar
datos binarios de ficheros externos, por lo que puedes recoger la
informacin producida por tus propias utilidades. Si te vale con que los
datos sean cargados como un simple bloque de datos binarios, eso es lo que
debes hacer, pero si debes cargar los datos en una estructura especfica,
sigue leyendo...

Tus objetos propios deben tener una identificacin nica, que es formada por
cuatro caracteres ASCII (por convencin todos maysculas A-Z). Si no usas
todos los caracteres, la cadena debe ser rellenada con espacios (ASCII 32).
Debers usar esta identificacin ID cuando crees objetos en el grabber
(selecciona New/Other y escribe la cadena ID), y en tu cdigo debes definir
un identificador para el tipo, ejemplo:

   #define DAT_MAPDATA  DAT_ID('M','A','P','D')

Entonces necesitas escribir funciones para cargar y destruir objetos de este
tipo, de la forma:

   void *load_mapdata(PACKFILE *f, long size)
   {
      /* Allegro llamar esta funcin siempre que un objeto de tipo propio
       * necesite ser cargado desde un fichero de datos. Se le pasar un
       * puntero al fichero desde el cual sern ledos los datos, y el
       * tamao del objeto en bytes. Debera devolver un puntero a los datos
       * cargados, que ser almacenado en el campo dat de la estructura del
       * objeto, o NULL si hubo algn error. El fichero ser abierto como un
       * sub-chunk del fichero de datos principal, por lo que es seguro leer
       * hasta el final del objeto (si intentas hacerlo, Allegro devolver
       * EOF), y tambin es seguro retornar antes de leer todos los datos
       * (si hace esto, Allegro se saltar los bytes no ledos antes de leer
       * el siguiente objeto). _No_ debes cerrar el fichero cuando acabes:
       * esto lo har la funcin que hace la llamada. Para clarificar el
       * funcionamiento, aqu tienes una implementacin de un objeto que es
       * una cadena de texto que acaba en NULL:
       */

      #define MAX_LEN  256

      char buf[MAX_LEN];
      char *p;
      int c;

      for (c=0; (c<MAX_LEN-1) && (!pack_feof(f)); c++)
         buf[c] = pack_getc(f);

      buf[c] = 0;

      p = malloc(c+1);
      strcpy(p, buf);

      return p;
   }

   void destroy_mapdata(void *data)
   {
      /* Allegro llamar esta funcin siempre que un objeto de tipo propio
       * deba ser destruido. Se le pasar un puntero al objeto (el retornado
       * por la funcin load), y debera liberar la memoria usada por el
       * objeto. Por ejemplo, el objeto simple que es una cadena de texto
       * devuelta por la funcin anterior puede ser destruido con el cdigo:
       */

      if (data)
         free(data);
   }

Finalmente, antes de cargar tu fichero de datos, debes advertir a Allegro
del formato propio, llamando:

   register_datafile_object(DAT_MAPDATA, load_mapdata, destroy_mapdata);



====================================
======== El formato interno ========
====================================


En caso de que alguien quiera hacer cosas diferentes, y como referencia
propia para el futuro, aqu estn algunos detalles de los interiores del
formato de los ficheros de datos.

Ten en cuenta que esto es diferente del formato de ficheros de datos usado
por versiones de Allegro 2.1 y anteriores. Allegro todava puede cargar
ficheros en el viejo formato, pero era poco flexible y no soportaba cosas
tiles como propiedades de objetos, por lo que deberas cargar tus ficheros
antiguos en el grabber y salvarlos de nuevo para convertirlos al nuevo
formato.

Si todo lo que quieres hacer es escribir una utilidad que manipula ficheros
de datos de alguna forma, lo ms fcil probablemente ser que uses las
funciones de ayuda de datedit.c, que son compartidas actualmente por los
programas dat, dat2s y grabber. Estas funciones pueden cargar, salvar,
insertar y borrar objetos, y modificar el contenido de los ficheros de datos
de varios modos, pero la vida es muy corta para que me moleste en
documentarlo todo aqu. Mira el cdigo fuente...

Aun as. Todos los nmeros son almacenados en formato big-endian (Motorola).
Un fichero de datos comienza con uno de los valores F_PACK_MAGIC o
F_NOPACK_MAGIC de 32 bits, que son definidos en allegro.h. Si comienza con
F_PACK_MAGIC el resto del fichero est comprimido con el algoritmo LZSS, si
no, est descomprimido. Este nmero mgico y la descompresin pueden ser
controlados sin problemas usando las funciones packfile y abriendo el
fichero en modo F_READ_PACKED. Despus de esto viene el valor DAT_MAGIC de
32 bits, seguido por el nmero de objetos en el fichero de datos raz (sin
incluir los objetos de los ficheros de datos anidados), seguido por cada uno
de esos objetos.

Cada objeto tiene el formato:

   OBJECT =
      var    - <lista propiedades>    - propiedades del objeto
      32 bit - <tipo ID>              - ID tipo objeto
      32 bit - <tamao comprimido>    - tamao de los datos en el fichero
      32 bit - <tamao descomprimido> - mira abajo
      var    - <datos>                - el contenido del objeto

La lista de propiedades puede contener cero o ms propiedades de objeto en
la forma:

   PROPERTY =
      32 bit - <magic>              - "prop"
      32 bit - <tipe ID>            - tipo ID de propiedad
      32 bit - <tamao>             - tamao de la cadena de propiedad en
                                      bytes
      var    - <datos>              - cadena de propiedad, _no_ termina en
                                      NULL

Si el campo de tamao descomprimido de un objeto es positivo, el contenido
del objeto no est comprimido (es decir, los tamaos comprimido y
descomprimido deben ser iguales). Si el tamao descomprimido es negativo, el
objeto est comprimido y se expandir en -<tamao descomprimido> bytes de
datos. La forma ms fcil de manejar esto es usar la funcin
pack_fopen_chunk() para leer tanto los tamaos como el contenido del objeto.

El contenido del objeto vara dependiendo el tipo. Allegro define los
siguientes tipos estndar:

   DAT_FILE =
      32 bit - <cuenta objetos>       - nmero de objetos en el sub-fichero
      var    - <lista objetos>        - objetos en el mismo formato que
                                        arriba

   DAT_FONT =
      16 bit - <tamao de la fuente>  - 8, 16, o -1 (proporcional)

      para fuentes 8x8:
         unsigned char[95][8]       - datos en formato 8x8 bit-packed

      para fuentes 8x16:
         unsigned char[95][16]      - datos en formato 8x16 bit-packed

      para fuentes proporcionales:
         95x {
             16 bit - <anchura>      - anchura del carcter
             16 bit - <altura>       - altura del carcter
             var    - <datos>        - datos del carcter (pixels de 8 bits)
             }

   DAT_SAMP =
      16 bit - <bits>               - bits del sample (negativo en estreo)
      16 bit - <frecuencia>         - frecuencia del sample
      32 bit - <longitud>           - longitud del sample
      var    - <datos>              - datos del sample

   DAT_MIDI =
      16 bit - <divisiones>         - divisiones de golpe del MIDI
      32x {
          32 bit - <length>         - longitud de la pista, en bytes
          var    - <data>           - datos de la pista MIDI
          }

   DAT_FLI =
      var - <datos>                 - animacin FLI o FLC en formato estndar

   DAT_BITMAP =
   DAT_C_SPRITE =
   DAT_XC_SPRITE =
      16 bit - <bits>               - profundidad de color del bitmap
      16 bit - <anchura>            - anchura del bitmap
      16 bit - <altura>             - altura del bitmap
      var    - <datos>              - datos del bitmap

      Las profundidades de color vlidas son 8, 15, 16, 24 y 32. Las
      imgenes de 15 y 16 bits se almacenan en formato 5.6.5 RGB, y las
      imgenes de 24 y 32 bits en formato 8.8.8 RGB.

   DAT_RLE_SPRITE =
      16 bit - <bits>               - profundidad de color del sprite
      16 bit - <anchura>            - anchura del sprite
      16 bit - <altura>             - altura del sprite
      32 bit - <tamao>             - tamao de los datos, en bytes
      var    - <datos>              - datos del sprite con compresin RLE

      Las profundidades de color vlidas son 8, 15, 16, 24 y 32. Las
      imgenes de 15 y 16 bits se almacenan en formato 5.6.5 RGB con
      contadores de salto de 16 bits y marcas EOL, y las imgenes de 24 y 32
      bits en formato 8.8.8 RGB con contadores de salto y marcas de 32 bits.

   DAT_PALETTE =
      256 x {
         8 bit - <rojo>             - componente rojo, 0-63
         8 bit - <verde>            - componente verde, 0-63
         8 bit - <azul>             - componente azul, 0-63
         8 bit - <pad>              - relleno de alineacin
         }

Creo que eso lo cubre todo.

