Uso de la librerÃa UnRarLib con C++
En ocasiones es muy útil poder colocar los variados elementos que utilizan nuestros juegos dentro de un solo archivo, y mejor aún, comprimido. MuchÃsimos juegos hacen uso de esta opción, como por ejemplo el Quake, Half-Life, Unreal, etc.
En este tutorial explicaremos como utilizar la librerÃa UnRarLib para estos fines, creando una interfaz que será similar a la clase ifstream y manejará recursos comprimidos y no comprimidos de modo transparente al usuario.
Compresores y empaquetadores
Es bueno diferenciar estas dos tareas que puede o no implementar la misma aplicación. Los usuarios de Windows están acostumbrados a comprimir y empaquetar mediante herramientas tipo WinZIP, WinRAR, WinACE o similares por lo tanto la operación comprimir + empaquetar la entienden como sólo una; los usuarios Solaris, Digital Unix o Linux probablemente tengan más en claro que son dos tareas bien diferenciadas, usualmente en esta plataforma se utiliza una aplicación llamada gzip para comprimir y otra llamada tar para empaquetar.
La librerÃa que utilizaremos en esta nota nos permite realizar ambas operaciones con la facilidad extra de poder crear los empaquetados y modificar con la aplicación WinRAR 2.x (la versión 3 utiliza un algoritmo de compresión distinto NO compatible hasta el momento con la librerÃa UnRarLib, la versión 2.9 del WinRAR puede ser descargada libremente).
El sitio oficial de la librerÃa es http://www.unrarlib.org/ y debemos mencionar que no es realmente una librerÃa, su distribución se basa en un archivo fuente unrarlib.c y su cabecera unrarlib.h que adjuntaremos a nuestro programa, claro que muy fácilmente podrÃamos crear una librerÃa de enlace dinámico con estos archivos pero no es nuestra intención.
Las funciones de la librerÃa UnRarLib
unrarlib_get
La primera de ellas es la función unrarlib_get, esta función descomprime un elemento determinado dentro de un archivo del tipo rar a memoria.
int urarlib_get(void *output, unsigned long *size, char *filename, void *rarfile, char *libpassword);
output : Buffer de memoria donde se colocará el elemento descomprimido.
size : Tamaño total en bytes del elemento descomprimido.
filename : Nombre del archivo tipo rar que posee el elemento a descomprimir.
libpassword : Contraseña del archivo tipo rar (si es que se encuentra protegido mediante contraseña).
Retorna cero si se produjo algún error o un número distinto a cero si se logró descomprimir el elemento de modo satisfactorio.
unrarlib_list
La función unrarlib_list coloca el contenido de un archivo del tipo rar en una estructura definida por la librerÃa, de este modo es posible conocer cual será el tamaño de un elemento descomprimido en memoria y de este modo poder solicitar la cantidad de memoria que corresponda.
int urarlib_list(void *rarfile, ArchiveList_struct *list);
rarfile : Nombre del archivo tipo rar que deseamos inspeccionar.
list : Estructura en la cual la librerÃa colocará la información del contenido del archivo. La librerÃa unrarlib es la encargada de asignar memoria para el puntero.
Retorna la cantidad de elementos que posee el archivo rar.
unrarlib_freelist
Una vez que hemos utilizado el contenido del puntero del tipo ArchiveList_struct deberemos eliminar su contenido (la memoria originalmente fue solicitada por la función unrarlib_list), para esto deberemos invocar la tercer función de la librerÃa unrarlib llamada unrarlib_freelist que posee el siguiente prototipo:
void urarlib_freelist(ArchiveList_struct *list);
list : Puntero pasado originalmente a la función unrarlib_list que deseamos liberar.
La estructura ArchiveList_struct
La estructura ArchiveList_struct es el nodo de una lista enlazada que arma la función unrarlib_list, posee básicamente un elemento del tipo RAR20_archive_entry y luego un puntero a otra estructura del tipo ArchiveList_struct.
| typedef struct archivelist
| {
| struct RAR20_archive_entry item;
| struct archivelist *next;
| } ArchiveList_struct;
La estructura RAR20_archive_entry
| struct RAR20_archive_entry
| {
| char *Name;
| UWORD NameSize;
| UDWORD PackSize;
| UDWORD UnpSize;
| UBYTE HostOS;
| UDWORD FileCRC;
| UDWORD FileTime;
| UBYTE UnpVer;
| UBYTE Method;
| UDWORD FileAttr;
| };
Name : Nombre del elemento.
NameSize : Cantidad de caracteres que posee el nombre del elemento.
PackSize : Tamaño en bytes del elemento comprimido.
UnpSize : Tamaño en bytes del elemento descomprimido.
HostOS : Indica 0 si el archivo fue comprimido en plataforma MS-DOS, 1: OS/2, 2: Win32 y 3: Unix.
FileCRC : Chequeo de redundancia cÃclica del archivo.
FileTime : Fecha del archivo.
FileAttr : Atributos del archivo.




MUY interesante articulo. Es realmente un tema a resolver, cuando todo el “content” del juego esta creado, pero en infinidad de archivos sueltos, produciendo fragmentacion en el disco, lentitud durante la instalacion, y perdida de performance debido a los tiempos de acceso, y multiples I/O.
Cabe destacar, sin embargo, algunos problemas relacionados con el formato elegido. Por empezar, RAR es un formato propietario, y eso genera dos situaciones:
1) Los archivos RAR que utilicemos deberan estár creados con herramientas pagas, y no con la propia libreria unRarLib, con la que solo podremos descomprimir (se pierde asi la capacidad de empaquetado/compresion para, por ej. los savegames).
2) La licencia de unRarLib se concede bajo dos condiciones: GPL License, que implica codigo abierto obligado en la aplicaion que utilice UnRarLib, o, UnRarLib License segun la cual, todo desarrollo que utilice la libreria, no podra ser comercializado, osea, debera ser gratuito.
A los problemas de licencia, deberiamos adicionarle la siguiente cuestion: el formato RAR es uno de los mas eficientes a la hora de comprimir, pero al coste de un elevado “computational time”, en comparacion con otros formatos de compresion. Esto nos deja con el dilema: quiero espacio, o quiero performance? en la industria de los videojuegos, esa pregunta se responde sola, y en mayusculas, VELOCIDAD!!!!
Ya que el problema principal es el empaquetado, y no la compresion, podemos considerar usar el formato, pero sin comprimir. Pero asi perdemos la virtud del formato, que es justamente la capacidad de compresion, y quedamos en igualdad de condiciones frente a cualquier otro. Y ante igualdad de condiciones tecnicas, y problemas de licencia, mejor elegir otro formato… Pero esa claro, es mi humilde opinion. Saludos.
P.D.: Fuzzy, con todo esto quiero decir: el pueblo pide un tutorial con otro formato!!!
thank you, brother