Este fichero es una traducción al español del fichero allegro/tools/grabber.txt en el original. ============================================================================ __ ___ ___ ___ ___ _ _ ___ ___ | \ |_| | |_| |__ | | |__ [_ |_/ | | | | | | | |__ |__ __] 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 pequeños, y hace la programación más fácil porque puedes cargar todo con una simple función cuando se inicializa tu programa. Otra ventaja es que el algoritmo LZSS de compresión de ficheros funciona mejor con uno grande que con muchos pequeños. Los ficheros de datos tienen la extensión .dat, y pueden ser creados y editados gráficamente con el programa grabber o desde la línea de comandos con la utilidad dat. Pueden ser almacenados como ficheros separados y cargados en memoria con la función load_datafile(), o puedes usar la utilidad dat2s para convertirlos en código ensamblador que puede ser enlazado directamente con tu ejecutable. Cada fichero de datos contiene un número 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 estándar 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, permitiéndote crear estructuras jerárquicas 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 identificación: 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 animación 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 encontrarás directamente este tipo de objeto, pero debes saber que es tratado especialmente por el código de ficheros de datos. DAT_INFO - "info" La utilidad grabber usa este objeto para almacenar información sobre el fichero de datos. Como propiedades de objetos, no deberías encontrar esto nunca, pero deberías evitar usar esta identificación 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 número de propiedades adjuntas. Estas son cadenas ASCII que describen los atributos del objeto, como el nombre y de dónde 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 estándar: "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 modificación 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 más grande, la posición x del origen en el bitmap padre. "YPOS" Para objetos bitmaps que fueron creados desde una imagen más grande, la posición y del origen en el bitmap padre. "XSIZ" Para objetos bitmaps que fueron creados desde una imagen más grande, el ancho de la región seleccionada. "YSIZ" Para objetos bitmaps que fueron creados desde una imagen más grande, la altura de la región seleccionada. Las propiedades "PACK", "HNAM", "HPRE", "BACK", "XGRD", y "YGRD" también son usadas internamente por grabber, pero puedes usar cualquier otra identidad que quieras para almacenar información 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 compresión (mira abajo). También puedes activar o desactivar backups: si la caja esta marcada, la versión antigua será renombrada con la extensión .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 ratón o los cursores. Puedes hacer una selección múltiple 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 botón derecho sobre el objeto. El doble click realiza en un objeto una función que varía según el tipo de éste. Los bitmaps y fuentes son enseñados 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 serán usadas cuando visualices o exportes un bitmap). Puedes crear nuevos objetos usando los menús 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 selecciónalo antes de insertar otros objetos. Para insertar información 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 mayoría de objetos esto visualizará un selector de ficheros para que selecciones el fichero a leer, pero para objetos gráficos (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 ratón o las flechas para seleccionar la porción de imagen que quieres recoger. Con el ratón, selecciona la esquina superior izquierda, pincha y mantén pulsado el botón izquierdo, mueve a la esquina inferior derecha del área que deseas coger y suelta el botón. Pulsa el botón derecho para cancelar la operación. Con el teclado, usa las flechas para seleccionar la esquina superior izquierda, pulsa Espacio o Enter, ajusta el tamaño con los cursores, y pulsa Espacio o Enter otra vez. Por defecto, la posición 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, tendrás 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 errónea. 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 visualización y exportación 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 más que un atajo para editar esta propiedad. Para simplificar el proceso de recogida de varias imágenes desde un mismo bitmap (por ejemplo un conjunto de frames que forman una animación), 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 podrás ajustar los parámetros 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 serán creados añadiendo un número 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 opción de rejilla regular simplemente divide el bitmap en varios trozos del mismo tamaño. 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 opción de color 255 es más flexible. Espera que el bitmap tenga información describiendo la posición y tamaño de cada trozo, en forma de un marco dibujado con el color 255. La forma más segura para hacer esto es rellenar toda la imagen excepto las partes que quieres con el color 255, pero el grabber debería ser capaz de entender formas más complicadas, incluso si simplemente dibujas líneas de color 255 a la izquierda y arriba del área que quieres recoger. Para imágenes truecolor donde el color 255 no significa nada, puedes usar un marco de color cian (azul y verde al máximo, rojo a cero), con un solo pixel amarillo (rojo y verde al máximo, azul a cero) en la esquina superior izquierda del marco. Por defecto el grabber funcionará en una resolución 640x480, usando la profundidad de color más alta que pueda visualizar tu tarjeta gráfica. Si quieres evitar esto, puedes especificar resoluciones o profundidades de color alternativas desde la línea de comando, ej: "grabber -8" para un modo de 256 colores, "grabber -16" para gráficos de 16 bits hicolor, "grabber -320x200" para usar el modo VGA 13h, o "grabber 1024x768". Atención: el editar imágenes truecolor en modos de 256 colores es muy lento, y el grabber es difícil de usar con resoluciones menores que 640x400. Puedes configurar el grabber para usar herramientas externas de edición 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 característica, selecciona el comando Shell Edit o pulsa ctrl+Z. El grabber intentará invocar la herramienta con la versión original del fichero si sabe desde dónde conseguiste los datos, de otro modo creará el objeto desde un fichero temporal antes la edición. =================================== ======== El archivador DAT ======== =================================== Como alternativa al programa gráfico grabber, puedes usar la utilidad de línea de comando dat. Esta acepta las siguientes opciones: '-a ' Añade los fichero especificados al fichero de datos, ejemplo: dat fichero.dat -a title.pcx scream.wav Si los objetos ya están presentes en el fichero de datos, sus contenidos actuales serán sustituidos. Los nombres de los objetos nuevos serán generados a partir de los nombres de los ficheros de entrada, y el tipo de objeto será detectado a partir de la extensión. En algunos casos esto es ambiguo, por ejemplo un fichero PCX puede ser leído como bitmap, sprite RLE, sprite compilado u objeto de fuente, por lo que debes especificar explícitamente 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 válidas son 8, 15, 16, 24 y 32 bits por pixel). '-c0' - sin compresión '-c1' - comprime los objetos individualmente '-c2' - compresión global de todo el fichero de datos Ajusta el modo de compresión (mira abajo). Este puede ser usado para convertir el fichero de datos de un formato a otro, o en combinación con cualquier otra opción. '-d ' Borra los objetos especificados del fichero de datos. '-e ' Extrae los objetos especificados del fichero de datos. Para extraer todo, usa la máscara * como nombre de objeto. Para ajustar el nombre o directorio de salida, usa la opción '-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 combinación con cualquier otro comando. Puedes usar la opción '-p cadenaprefijo' para ajustar una cadena de prefijo para las definiciones de objetos. '-k' Conserva los nombres originales al recoger objetos. Sin este parámetro, un fichero llamado image.pcx será importado como un objeto llamado IMAGE_PCX, para asegurarse de que todos los nombres de objeto son símbolos válidos para las definiciones de los ficheros de cabecera. '-l' Muestra el contenido de un fichero de datos. Esto puede ser combinado con la opción '-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 automáticamente el fichero de datos cuando los datos origen cambien. '-s0' - no recortar: salva todo '-s1' - recorta información 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 combinación con cualquier otra opción. '-u' Actualiza el contenido de un fichero de datos. Mira abajo. '-v' Selecciona el modo verbose. Esto puede ser combinado con cualquier otra opción para producir descripciones más detalladas. ' 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 vacía 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 máscara * para aplicar la propiedad a todo en el fichero de datos, por ejemplo: para quitar la propiedad ORIG del fichero de datos, podrías hacer: dat fichero.dat * ORIG= Puedes crear una jerarquía 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 ===================================== ======== Información variada ======== ===================================== Los ficheros de datos pueden ser salvados usando cualquiera de los tres tipos de compresión, 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 compresión global sobre el fichero entero. Por norma, la compresión global dará resultados ligeramente mejores que la compresión por objeto, pero no debería ser usada si quieres cargar dinámicamente objetos específicos con la función load_datafile_object(). También hay tres modos de recorte para salvar ficheros de datos, seleccionados con el comando File/Save Stripped de grabber, o usando los parámetros 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 específicas del grabber (aquellas que describen el origen y fecha de cada objeto) serán recortadas, lo que reducirá marginalmente el tamaño del fichero, pero evitará que el comando de actualización 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 añadido. Este nivel de recorte obviamente debería ser usado con extrema precaución, aunque en algunos casos puede ser posible recuperar los nombres de los objetos incluso después 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, buscarán 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 actualización, que recorre todo el fichero de datos comprobando si algún 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á automáticamente los objetos antiguos. Las fuentes pueden ser leídas 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 tamaño de cada carácter es determinado por la apariencia de la imagen, que debería 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 carácter es de tamaño exacto 8x8 o 8x16, el grabber creará una fuente de tamaño fijo, de otro modo creará una fuente proporcional. Probablemente la manera más fácil para entender cómo funciona esto, es cargar el fichero demo.dat y exportar TITLE_FONT en un fichero PCX. Mira cómo 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, tecleándolo en el campo "Password:" del grabber, o usando la opción '-007 password' de la utilidad dat. Los passwords pueden ser de hasta 256 caracteres, y son sensibles a las mayúsculas. Los ficheros encriptados _no_ pueden ser leídos sin el password, por lo que no lo olvides y vengas llorando a pedirme ayuda :-) Para leer ficheros encriptados en tu programa, llama la función packfile_password() antes de load_datafile(). También es buena idea llamar después packfile_password(NULL), para que todo vuelva al estado normal. ================================================ ======== Accediendo a ficheros de datos ======== ================================================ Para acceder al contenido de un fichero de datos, necesitarás saber dónde esta cada objeto. El modo más fácil de hacerlo es con el índice de enteros, usando el fichero de cabecera generado automáticamente. Con el grabber, escribe un nombre en el campo "Header:", y los índices de los objetos serán escritos en este fichero siempre que salves el fichero de datos. Con la utilidad dat, usa la opción '-h', ej: "dat fichero.dat -h cabecera.h". La cabecera definirá símbolos 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 escribiéndola en el campo "Prefix:" del grabber o usando la opción '-p' del dat. Para cargar un fichero de datos en memoria, llama la función: DATAFILE *load_datafile(char *nombrefichero); Esto cargará todo el fichero, devolviendo un puntero a él, o NULL si hubo algún error. Cuando ya no necesitas más los datos, todo el bloque puede ser liberado de memoria llamando: void unload_datafile(DATAFILE *dat); Cuando cargas un fichero de datos, obtendrás un puntero a un array de estructuras DATAFILE: typedef struct DATAFILE { void *dat; - puntero a los datos actuales int type; - identificación del tipo de objeto long size; - tamaño de los datos, en bytes DATAFILE_PROPERTY *prop; - lista de propiedades del objeto } DATAFILE; Realmente la única pieza importante de información 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 estás programando en C puedes pasar este puntero directamente a la función relevante de la biblioteca Allegro, pero si estás usando C++, necesitarás 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 código: #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. También definirá un número de contador con el número de objetos en el fichero anidado, que puede ser útil si por ejemplo el fichero hijo contiene varios bitmaps que forman una animación, y quieres que tu código automáticamente ajuste el número de frames de la animación 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 función: char *get_datafile_property(DATAFILE *dat, int type); Esto devuelve un puntero a la cadena de propiedad si puede ser encontrada, y una cadena vacía (¡que no es null!) si no existe. Un posible uso de esta función 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" podrías usar el siguiente código: 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... */ También es posible cargar objetos individuales selectivamente desde un fichero de datos con la función: 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 función recorre todos los datos, será extremadamente lenta si has salvado el fichero con compresión global. Si planeas cargar objetos individualmente, deberías salvar el fichero sin compresión o con compresión individual por objeto. Como el puntero devuelto apunta solamente a un objeto en vez de a un array de objetos, deberías acceder a él con la sintaxis fichero_datos->dat, en vez de fichero_datos[índice].dat, y cuando acabes con él, deberías liberar el objeto con la función: 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 leído entonces de modo normal que un fichero de disco, por lo que cualquier función 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 sólo lectura. Además, deberías salvar el fichero sin compresión o con compresión por objeto si planeas usar esta característica. 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 añadido 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 código. Por defecto, todos los objetos gráficos cargados desde un fichero de datos serán convertidos a la profundidad de color actual. Esta conversión puede ser tanto mala como lenta, particularmente cuando cambia el formato de truecolor a 256 colores, por lo que querrás 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 código ensamblador (.s), que puede ser ensamblado y enlazado en tu programa. Esto evita la necesidad de que un fichero separado acompañe tu programa, y significa que los datos serán cargados en memoria automáticamente al iniciar el programa. Sin embargo deberías considerar, que los ficheros de datos tardan mucho en ser compilados, y no es posible comprimir los datos de este modo. El modo más 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 módulo 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 indicándole a dat2s que haga un fichero de cabecera además del fichero en ensamblador, con la opción '-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 código que originalmente fue escrito para cargar un fichero de datos separado, con la sintaxis estándar 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 isométrico, 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 información 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 específica, sigue leyendo... Tus objetos propios deben tener una identificación única, que es formada por cuatro caracteres ASCII (por convención todos mayúsculas A-Z). Si no usas todos los caracteres, la cadena debe ser rellenada con espacios (ASCII 32). Deberás usar esta identificación ID cuando crees objetos en el grabber (selecciona New/Other y escribe la cadena ID), y en tu código 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 función 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 serán leídos los datos, y el * tamaño del objeto en bytes. Debería devolver un puntero a los datos * cargados, que será almacenado en el campo dat de la estructura del * objeto, o NULL si hubo algún 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 también es seguro retornar antes de leer todos los datos * (si hace esto, Allegro se saltará los bytes no leídos antes de leer * el siguiente objeto). _No_ debes cerrar el fichero cuando acabes: * esto lo hará la función que hace la llamada. Para clarificar el * funcionamiento, aquí tienes una implementación 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 - propiedades del objeto 32 bit - - ID tipo objeto 32 bit - - tamaño de los datos en el fichero 32 bit - - mira abajo var - - el contenido del objeto La lista de propiedades puede contener cero o más propiedades de objeto en la forma: PROPERTY = 32 bit - - "prop" 32 bit - - tipo ID de propiedad 32 bit - - tamaño de la cadena de propiedad en bytes var - - cadena de propiedad, _no_ termina en NULL Si el campo de tamaño descomprimido de un objeto es positivo, el contenido del objeto no está comprimido (es decir, los tamaños comprimido y descomprimido deben ser iguales). Si el tamaño descomprimido es negativo, el objeto está comprimido y se expandirá en - bytes de datos. La forma más fácil de manejar esto es usar la función pack_fopen_chunk() para leer tanto los tamaños como el contenido del objeto. El contenido del objeto varía dependiendo el tipo. Allegro define los siguientes tipos estándar: DAT_FILE = 32 bit - - número de objetos en el sub-fichero var - - objetos en el mismo formato que arriba DAT_FONT = 16 bit - - 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 del carácter 16 bit - - altura del carácter var - - datos del carácter (pixels de 8 bits) } DAT_SAMP = 16 bit - - bits del sample (negativo en estéreo) 16 bit - - frecuencia del sample 32 bit - - longitud del sample var - - datos del sample DAT_MIDI = 16 bit - - divisiones de golpe del MIDI 32x { 32 bit - - longitud de la pista, en bytes var - - datos de la pista MIDI } DAT_FLI = var - - animación FLI o FLC en formato estándar DAT_BITMAP = DAT_C_SPRITE = DAT_XC_SPRITE = 16 bit - - profundidad de color del bitmap 16 bit - - anchura del bitmap 16 bit - - altura del bitmap var - - datos del bitmap Las profundidades de color válidas son 8, 15, 16, 24 y 32. Las imágenes de 15 y 16 bits se almacenan en formato 5.6.5 RGB, y las imágenes de 24 y 32 bits en formato 8.8.8 RGB. DAT_RLE_SPRITE = 16 bit - - profundidad de color del sprite 16 bit - - anchura del sprite 16 bit - - altura del sprite 32 bit - - tamaño de los datos, en bytes var - - datos del sprite con compresión RLE Las profundidades de color válidas son 8, 15, 16, 24 y 32. Las imágenes 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 imágenes 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 - - componente rojo, 0-63 8 bit - - componente verde, 0-63 8 bit - - componente azul, 0-63 8 bit - - relleno de alineación } Creo que eso lo cubre todo.