1 /* GemRB - Infinity Engine Emulator
2 * Copyright (C) 2003 The GemRB Project
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include "../../includes/win32def.h"
22 #include "../Core/Compressor.h"
23 #include "../Core/FileStream.h"
24 #include "../Core/CachedFileStream.h"
25 #include "BIFImporter.h"
26 #include "../Core/Interface.h"
48 int BIFImp::DecompressSaveGame(DataStream
*compressed
)
51 compressed
->Read( Signature
, 8 );
52 if (strncmp( Signature
, "SAV V1.0", 8 ) ) {
55 int All
= compressed
->Remains();
57 if (!All
) return GEM_ERROR
;
59 ieDword fnlen
, complen
, declen
;
60 compressed
->ReadDword( &fnlen
);
61 char* fname
= ( char* ) malloc( fnlen
);
62 compressed
->Read( fname
, fnlen
);
64 compressed
->ReadDword( &declen
);
65 compressed
->ReadDword( &complen
);
66 PathJoin( path
, core
->CachePath
, fname
, NULL
);
67 printf( "Decompressing %s\n",fname
);
69 if (!core
->IsAvailable( IE_COMPRESSION_CLASS_ID
))
71 FILE *in_cache
= fopen( path
, "wb" );
73 printMessage("BIFImporter", " ", RED
);
74 printf( "Cannot write %s.\n", path
);
77 Compressor
* comp
= ( Compressor
* )
78 core
->GetInterface( IE_COMPRESSION_CLASS_ID
);
79 if (comp
->Decompress( in_cache
, compressed
) != GEM_OK
) {
82 core
->FreeInterface( comp
);
84 Current
= compressed
->Remains();
85 //starting at 40% going up to 90%
86 core
->LoadProgress( 40+(All
-Current
)*50/All
);
92 //this one can create .sav files only
93 int BIFImp::CreateArchive(DataStream
*compressed
)
104 memcpy(Signature
,"SAV V1.0",8);
105 compressed
->Write(Signature
, 8);
110 int BIFImp::AddToSaveGame(DataStream
*str
, DataStream
*uncompressed
)
112 ieDword fnlen
, declen
, complen
;
114 fnlen
= strlen(uncompressed
->filename
)+1;
115 declen
= uncompressed
->Size();
116 str
->WriteDword( &fnlen
);
117 str
->Write( uncompressed
->filename
, fnlen
);
118 str
->WriteDword( &declen
);
119 //baaah, we dump output right in the stream, we get the compressed length
120 //only after the compressed data was written
121 complen
= 0xcdcdcdcd; //placeholder
122 unsigned long Pos
= str
->GetPos(); //storing the stream position
123 str
->WriteDword( &complen
);
125 Compressor
* comp
= ( Compressor
* )
126 core
->GetInterface( IE_COMPRESSION_CLASS_ID
);
127 comp
->Compress( str
, uncompressed
);
128 core
->FreeInterface( comp
);
130 //writing compressed length (calculated)
131 unsigned long Pos2
= str
->GetPos();
132 complen
= Pos2
-Pos
-sizeof(ieDword
); //calculating the compressed stream size
133 str
->Seek(Pos
, GEM_STREAM_START
); //going back to the placeholder
134 str
->WriteDword( &complen
); //updating size
135 str
->Seek(Pos2
, GEM_STREAM_START
);//resuming work
139 int BIFImp::OpenArchive(const char* filename
)
145 FILE* in_cache
= fopen( filename
, "rb" );
150 if (fread( &Signature
, 1, 8, in_cache
) != 8) {
155 //normal bif, not in cache
156 if (strncmp( Signature
, "BIFFV1 ", 8 ) == 0) {
157 stream
= new CachedFileStream( filename
);
158 stream
->Read( Signature
, 8 );
159 strcpy( path
, filename
);
163 //not found as normal bif
164 //checking compression type
165 FileStream
* compressed
= new FileStream();
166 compressed
->Open( filename
, true );
167 compressed
->Read( Signature
, 8 );
168 if (strncmp( Signature
, "BIF V1.0", 8 ) == 0) {
169 ieDword fnlen
, complen
, declen
;
170 compressed
->ReadDword( &fnlen
);
171 char* fname
= ( char* ) malloc( fnlen
);
172 compressed
->Read( fname
, fnlen
);
174 compressed
->ReadDword( &declen
);
175 compressed
->ReadDword( &complen
);
176 PathJoin( path
, core
->CachePath
, fname
, NULL
);
178 in_cache
= fopen( path
, "rb" );
180 //printf("Found in Cache\n");
182 delete( compressed
);
183 stream
= new CachedFileStream( path
);
184 stream
->Read( Signature
, 8 );
185 if (strncmp( Signature
, "BIFFV1 ", 8 ) == 0)
191 printf( "Decompressing\n" );
192 if (!core
->IsAvailable( IE_COMPRESSION_CLASS_ID
)) {
193 printMessage("BIFImporter", "No Compression Manager Available.", RED
);
196 in_cache
= fopen( path
, "wb" );
198 printMessage("BIFImporter", " ", RED
);
199 printf( "Cannot write %s.\n", path
);
202 Compressor
* comp
= ( Compressor
* )
203 core
->GetInterface( IE_COMPRESSION_CLASS_ID
);
204 if (comp
->Decompress( in_cache
, compressed
) != GEM_OK
) {
207 core
->FreeInterface( comp
);
209 delete( compressed
);
210 stream
= new CachedFileStream( path
);
211 stream
->Read( Signature
, 8 );
212 if (strncmp( Signature
, "BIFFV1 ", 8 ) == 0)
219 if (strncmp( Signature
, "BIFCV1.0", 8 ) == 0) {
220 //printf("'BIFCV1.0' Compressed File Found\n");
221 PathJoin( path
, core
->CachePath
, compressed
->filename
, NULL
);
222 in_cache
= fopen( path
, "rb" );
224 //printf("Found in Cache\n");
226 delete( compressed
);
227 stream
= new CachedFileStream( path
);
228 stream
->Read( Signature
, 8 );
229 if (strncmp( Signature
, "BIFFV1 ", 8 ) == 0) {
235 printf( "Decompressing\n" );
236 if (!core
->IsAvailable( IE_COMPRESSION_CLASS_ID
))
238 Compressor
* comp
= ( Compressor
* )
239 core
->GetInterface( IE_COMPRESSION_CLASS_ID
);
240 ieDword unCompBifSize
;
241 compressed
->ReadDword( &unCompBifSize
);
242 printf( "\nDecompressing file: [..........]" );
244 in_cache
= fopen( path
, "wb" );
246 printMessage("BIFImporter", " ", RED
);
247 printf( "Cannot write %s.\n", path
);
250 ieDword finalsize
= 0;
252 while (finalsize
< unCompBifSize
) {
253 compressed
->Seek( 8, GEM_CURRENT_POS
);
254 if (comp
->Decompress( in_cache
, compressed
) != GEM_OK
) {
257 finalsize
= ftell( in_cache
);
258 if (( int ) ( finalsize
* ( 10.0 / unCompBifSize
) ) != laststep
) {
260 printf( "\b\b\b\b\b\b\b\b\b\b\b" );
263 for (l
= 0; l
< laststep
; l
++)
265 for (; l
< 10; l
++)//l starts from laststep
272 core
->FreeInterface( comp
);
274 delete( compressed
);
275 stream
= new CachedFileStream( path
);
276 stream
->Read( Signature
, 8 );
277 if (strncmp( Signature
, "BIFFV1 ", 8 ) == 0)
287 DataStream
* BIFImp::GetStream(unsigned long Resource
, unsigned long Type
)
289 DataStream
* s
= NULL
;
290 if (Type
== IE_TIS_CLASS_ID
) {
291 unsigned int srcResLoc
= Resource
& 0xFC000;
292 for (unsigned int i
= 0; i
< tentcount
; i
++) {
293 if (( tentries
[i
].resLocator
& 0xFC000 ) == srcResLoc
) {
294 s
= new CachedFileStream( stream
, tentries
[i
].dataOffset
,
295 tentries
[i
].tileSize
* tentries
[i
].tilesCount
);
300 ieDword srcResLoc
= Resource
& 0x3FFF;
301 for (ieDword i
= 0; i
< fentcount
; i
++) {
302 if (( fentries
[i
].resLocator
& 0x3FFF ) == srcResLoc
) {
303 s
= new CachedFileStream( stream
, fentries
[i
].dataOffset
,
304 fentries
[i
].fileSize
);
312 void BIFImp::ReadBIF(void)
315 stream
->ReadDword( &fentcount
);
316 stream
->ReadDword( &tentcount
);
317 stream
->ReadDword( &foffset
);
318 stream
->Seek( foffset
, GEM_STREAM_START
);
319 fentries
= new FileEntry
[fentcount
];
320 tentries
= new TileEntry
[tentcount
];
321 if (!fentries
|| !tentries
) {
334 for (i
=0;i
<fentcount
;i
++) {
335 stream
->ReadDword( &fentries
[i
].resLocator
);
336 stream
->ReadDword( &fentries
[i
].dataOffset
);
337 stream
->ReadDword( &fentries
[i
].fileSize
);
338 stream
->ReadWord( &fentries
[i
].type
);
339 stream
->ReadWord( &fentries
[i
].u1
);
341 for (i
=0;i
<tentcount
;i
++) {
342 stream
->ReadDword( &tentries
[i
].resLocator
);
343 stream
->ReadDword( &tentries
[i
].dataOffset
);
344 stream
->ReadDword( &tentries
[i
].tilesCount
);
345 stream
->ReadDword( &tentries
[i
].tileSize
);
346 stream
->ReadWord( &tentries
[i
].type
);
347 stream
->ReadWord( &tentries
[i
].u1
);
351 #include "../../includes/plugindef.h"
353 GEMRB_PLUGIN(0xC7F133C, "BIF File Importer")
354 PLUGIN_CLASS(IE_BIF_CLASS_ID
, BIFImp
)