![]() |
|||
| EXTRACTOR | .RU – версия 2.2 |
||
![]() |
|
Что у нас есть? Это тоже интересно |
Статьи и описания форматов игровых файлов Brave Dwarves 2Эта статья относится к играм: Автор материала: Varg Описание формата DAT из игры Brave Dwarves 2 (студия GameOverGame) и пример использования библиотеки Zlib для извлечения ресурсов. Файлы формата DAT имеют следующее строение: Заголовок. 0x00000000 строка длинной 28 байт содержащая "GaveOverGames' Resource File" 0x00000022 DWORD число указывает на первый запакованный файл 0x00000026 DWORD количество файлов в архиве На "С++" это выглядит следующим образом: struct Header
{
char Id[0x1d]; //Начальная строка как индефикатор
DWORD start; //Начальная позиция
DWORD num; //Число файлов
};Пример чтения заголовка: FILE *mfile;
Header header; //Заголовок DAT файла
....
BOOL ArcOpen(char *arc_name)
{
if(mfile!=0)
fclose(mfile);
mfile=fopen(arc_name,"rb");
if(mfile==0)
{
sprintf(str_error,"Error! Can`t open arc file!");
return FALSE;
};
//******************************
// Читаем заголовок
//******************************
fread(header.Id,0x1c,1,mfile);
if(strcmp(header.Id,"GaveOverGames' Resource File")!=0)
{
sprintf(str_error,"Error! It`s not BD2 dat file!");
return FALSE;
};
fseek(mfile,0x22,0);
fread(&header.start,4,1,mfile);
fread(&header.num,4,1,mfile);
return TRUE;
};Запакованные файлы. offset+0 DWORD указатель на начало строки содержащей имя запакованного файла. offset+8 DWORD указатель на позицию следующего запакованного файла. offset+12 DWORD реальный размер запакованных данных. offset+16 DWORD размер запакованных данных. offset+22 строка содержащая имя запакованного файла. Далее после строки имени идут сами запакованные данные. struct Arc_File
{
DWORD start_pos; //Указатель на имя файла
DWORD size; //Размер запакованных данных
DWORD r_size; //Реальный размер данных
DWORD data_pos; //Указатель на данные
DWORD next; //Указатель на следующий файл
char name[256]; //Имя запакованного файла
};Пример чтения информации из заголовков запакованных файлов: FILE *mfile;
Header header; //Заголовок
Arc_File *afile; //Заголовки запакованных файлов
...
BOOL ArcScan()
{
afile=new Arc_File[header.num]; //Выделяем память под заголовки
if(!afile)
{
printf(str_error,"Error! Can`t Alloc Memory!");
return FALSE;
};
long off=0;
fseek(mfile,header.start,0); //Устанавливаем указатель на начало (заголовок) запакованного файла.
for(int i=0;i<header.num;i++)
{
fread(&afile[i].start_pos,4,1,mfile); //Читаем указатель на имя запакованного файла.
fseek(mfile,off+8,0); //Устанавливаем позицию ф-ла в off+8
fread(&afile[i].next,4,1,mfile); //Читаем смещение по которому расположен следующий запакованный файл.
fseek(mfile,off+12,0); //Устанавливаем позицию ф-ла в off+12
fread(&afile[i].r_size,4,1,mfile); //Читаем реальный размер упакованных данных.
fseek(mfile,off+16,0); //Устанавливаем позицию ф-ла в off+16
fread(&afile[i].size,4,1,mfile); //Читаем размер упакованных данных. fseek(mfile,afile[i].start_pos,0); //Устанавливаем указатель на начало строки содержащей имя запакованного файла.
fread(afile[i].name,afile[i].next-afile[i].start_pos-afile[i].size-1,1,mfile); //Читаем имя файла (обратить внимание на расчет длинны строки)
afile[i].data_pos=off=ftell(mfile); //Читаем позицию файла которая численно равна позиции с которой начинаются данные запакованные zlib.
fseek(mfile,afile[i].next,0); //Устанавливаем позицию на следующий запакованный файл.
};
return TRUE;
};Собственно распаковка всех файлов: ...
#include "direct.h"
#include "zlib.h"
...
#pragma comment (lib, "zlib.lib") //Подключаем zlib.dll
...
FILE *mfile;
Header header;
Arc_File *afile;
...
void ExtractAll()
{
FILE *o; //Указатель на файл вывода данных
Bytef *cdata; //Упакованные данные
Bytef *data; //Распакованные данные
uLongf sz=0; //Реальный размер
//**********************************
//Главный цикл извлечения данных
//**********************************
for(int i=0;i<header.num;i++)
{
o=CreateFileName(i); //Создаем файл для вывода данных
if(o!=0)
{
fseek(mfile,afile[i].data_pos,0); //Начало запакованных данных
cdata=new Bytef[afile[i].size+1]; //Выделяем память под запакованные данные
if(cdata)
{
data=new Bytef[afile[i].r_size]; //Выделяем память под незапакованные данные
if(data)
{
sz=afile[i].r_size; //Реальный размер
fread(cdata,afile[i].size+1,1,mfile); //Читаем запакованные данные из файла DAT
//Распаковываем данные из cdata в data с размером r_size используя
//функцию из библиотеки ZLib
//где &sz реальный размер распакованного файла
//afile[i].size+1 размер запакованных данных
//если функция uncompress возвращает 0 (Z_OK) значит все рулеzzz
//если же нет, то номера ошибок можно найти в zlib.h
if(uncompress(data,&sz,cdata,afile[i].size+1)==0)
{
//Записываем данные data в файл//
fwrite(data,afile[i].r_size,1,o);
};
delete data; //new data
};
delete cdata; //new cdata
}
fclose(o); //fopen
}
else
{
printf("Error");
}
};
};
//************** CreateFileName()*****************//
//************************************
// Функция создающая файл для вывода
// распакованных данных
//************************************
FILE * CreateFileName(int n)
{
FILE *out;
char str[256];
char sstr[256];
BYTE ch=0;
int len=0;
strcpy(sstr,afile[n].name);
len=strlen(sstr);
for(int a=0;a<len;a++)
{
ch=sstr[a];
if(ch==0x5c)
{
str[a]=0;
mkdir(str);
};
str[a]=ch;
};
out=fopen(afile[n].name,"wb");
return out;
};Вот и все что нужно знать, чтобы распаковать файлы с такой структурой. Причем навык пользования ZLib можно использовать и при написании программ к другим форматам использующим ZLib для компрессии. |
| © | 2000—2010 «EXTRACTOR.ru» — игровые ресурсы: распаковка музыки и графики, конверторы форматов и многое другое… |