Switch to using -I to find includes, rather than relative paths.
[gemrb.git] / gemrb / plugins / KEYImporter / KEYImporter.cpp
blob5609b8eb00456fb243039db656b149be92ad550c
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 "win32def.h"
22 #include "KEYImporter.h"
23 #include "globals.h"
24 #include "FileStream.h"
25 #include "Interface.h"
26 #include "ArchiveImporter.h"
27 #include "ResourceDesc.h"
28 #ifndef WIN32
29 #include <unistd.h>
30 #endif
32 #define SHARED_OVERRIDE "shared"
34 KEYImporter::KEYImporter(void)
38 KEYImporter::~KEYImporter(void)
40 for (unsigned int i = 0; i < biffiles.size(); i++) {
41 free( biffiles[i].name );
45 static bool exists(char *file)
47 FILE *f = fopen( file, "rb" );
48 if (f) {
49 fclose(f);
50 return true;
52 return false;
55 static void FindBIF(BIFEntry *entry)
57 entry->cd = 0;
59 PathJoin( entry->path, core->GamePath, entry->name, NULL );
60 ResolveFilePath(entry->path);
61 if (exists(entry->path)) {
62 entry->found = true;
63 return;
66 PathJoin( entry->path, core->GamePath, entry->name, NULL );
67 strcpy( entry->path + strlen( entry->path ) - 4, ".cbf" );
68 ResolveFilePath(entry->path);
69 if (exists(entry->path)) {
70 entry->found = true;
71 return;
74 if (core->GameOnCD) {
75 char BasePath[_MAX_PATH];
76 if (( entry->BIFLocator & ( 1 << 2 ) ) != 0) {
77 strcpy( BasePath, core->CD[0] );
78 entry->cd = 1;
79 } else if (( entry->BIFLocator & ( 1 << 3 ) ) != 0) {
80 strcpy( BasePath, core->CD[1] );
81 entry->cd = 2;
82 } else if (( entry->BIFLocator & ( 1 << 4 ) ) != 0) {
83 strcpy( BasePath, core->CD[2] );
84 entry->cd = 3;
85 } else if (( entry->BIFLocator & ( 1 << 5 ) ) != 0) {
86 strcpy( BasePath, core->CD[3] );
87 entry->cd = 4;
88 } else if (( entry->BIFLocator & ( 1 << 6 ) ) != 0) {
89 strcpy( BasePath, core->CD[4] );
90 entry->cd = 5;
91 } else {
92 printStatus( "ERROR", LIGHT_RED );
93 printf( "Cannot find %s... Resource unavailable.\n",
94 entry->name );
95 entry->found = false;
96 return;
98 PathJoin( entry->path, BasePath, entry->name, NULL );
99 entry->found = false;
100 return;
103 for (int i = 0; i < 6; i++) {
104 PathJoin( entry->path, core->CD[i], entry->name, NULL );
105 ResolveFilePath(entry->path);
106 if (exists(entry->path)) {
107 entry->found = true;
108 return;
111 //Trying CBF Extension
112 PathJoin( entry->path, core->CD[i], entry->name, NULL );
113 strcpy( entry->path + strlen( entry->path ) - 4, ".cbf" );
114 ResolveFilePath(entry->path);
115 if (exists(entry->path)) {
116 entry->found = true;
117 return;
121 printMessage( "KEYImporter", " ", WHITE );
122 printf( "Cannot find %s...", entry->name );
123 printStatus( "ERROR", LIGHT_RED );
124 entry->found = false;
127 bool KEYImporter::Open(const char *resfile, const char *desc)
129 description = desc;
130 if (!core->IsAvailable( IE_BIF_CLASS_ID )) {
131 printf( "[ERROR]\nAn Archive Plug-in is not Available\n" );
132 return false;
134 unsigned int i;
135 // NOTE: Interface::Init has already resolved resfile.
136 printMessage( "KEYImporter", "Opening ", WHITE );
137 printf( "%s...", resfile );
138 FileStream* f = new FileStream();
139 if (!f->Open( resfile )) {
140 printStatus( "ERROR", LIGHT_RED );
141 printMessage( "KEYImporter", "Cannot open Chitin.key\n", LIGHT_RED );
142 textcolor( WHITE );
143 delete( f );
144 return false;
146 printStatus( "OK", LIGHT_GREEN );
147 printMessage( "KEYImporter", "Checking file type...", WHITE );
148 char Signature[8];
149 f->Read( Signature, 8 );
150 if (strncmp( Signature, "KEY V1 ", 8 ) != 0) {
151 printStatus( "ERROR", LIGHT_RED );
152 printMessage( "KEYImporter", "File has an Invalid Signature.\n",
153 LIGHT_RED );
154 textcolor( WHITE );
155 delete( f );
156 return false;
158 printStatus( "OK", LIGHT_GREEN );
159 printMessage( "KEYImporter", "Reading Resources...\n", WHITE );
160 ieDword BifCount, ResCount, BifOffset, ResOffset;
161 f->ReadDword( &BifCount );
162 f->ReadDword( &ResCount );
163 f->ReadDword( &BifOffset );
164 f->ReadDword( &ResOffset );
165 printMessage( "KEYImporter", " ", WHITE );
166 printf( "BIF Files Count: %d (Starting at %d Bytes)\n", BifCount,
167 BifOffset );
168 printMessage( "KEYImporter", " ", WHITE );
169 printf( "RES Count: %d (Starting at %d Bytes)\n", ResCount, ResOffset );
170 f->Seek( BifOffset, GEM_STREAM_START );
171 ieDword BifLen, ASCIIZOffset;
172 ieWord ASCIIZLen;
173 for (i = 0; i < BifCount; i++) {
174 BIFEntry be;
175 f->Seek( BifOffset + ( 12 * i ), GEM_STREAM_START );
176 f->ReadDword( &BifLen );
177 f->ReadDword( &ASCIIZOffset );
178 f->ReadWord( &ASCIIZLen );
179 f->ReadWord( &be.BIFLocator );
180 be.name = ( char * ) malloc( ASCIIZLen );
181 f->Seek( ASCIIZOffset, GEM_STREAM_START );
182 f->Read( be.name, ASCIIZLen );
183 #ifndef WIN32
184 for (int p = 0; p < ASCIIZLen; p++) {
185 //some MAC versions use : as delimiter
186 if (be.name[p] == '\\' || be.name[p] == ':')
187 be.name[p] = PathDelimiter;
189 if (be.name[0] == PathDelimiter) {
190 // totl has '\data\zcMHar.bif' in the key file, and the CaseSensitive
191 // code breaks with that extra slash, so simple fix: remove it
192 ASCIIZLen--;
193 for (int p = 0; p < ASCIIZLen; p++)
194 be.name[p] = be.name[p + 1];
195 // (if you change this, try moving to ar9700 for testing)
197 #endif
198 FindBIF(&be);
199 biffiles.push_back( be );
201 f->Seek( ResOffset, GEM_STREAM_START );
202 resources.InitHashTable( ResCount < 17 ? 17 : ResCount );
203 for (i = 0; i < ResCount; i++) {
204 RESEntry re;
205 f->ReadResRef( re.ResRef );
206 f->ReadWord( &re.Type );
207 f->ReadDword( &re.ResLocator );
208 resources.SetAt( re.ResRef, re.Type, re.ResLocator );
210 printMessage( "KEYImporter", "Resources Loaded...", WHITE );
211 printStatus( "OK", LIGHT_GREEN );
212 delete( f );
213 return true;
216 bool KEYImporter::HasResource(const char* resname, SClass_ID type)
218 unsigned int ResLocator;
219 return resources.Lookup( resname, type, ResLocator );
222 bool KEYImporter::HasResource(const char* resname, const ResourceDesc &type)
224 return HasResource(resname, type.GetKeyType());
227 static void FindBIFOnCD(BIFEntry *entry)
229 ResolveFilePath(entry->path);
230 if (exists(entry->path)) {
231 entry->found = true;
232 return;
235 core->WaitForDisc( entry->cd, core->CD[entry->cd-1] );
236 ResolveFilePath(entry->path);
237 if (exists(entry->path)) {
238 entry->found = true;
239 return;
242 //Trying CBF Extension
243 strcpy( entry->path + strlen( entry->path ) - 4, ".cbf" );
244 ResolveFilePath(entry->path);
245 if (exists(entry->path)) {
246 entry->found = true;
247 return;
250 entry->found = false;
253 DataStream* KEYImporter::GetStream(const char *resname, ieWord type)
255 unsigned int ResLocator;
257 if (type == 0)
258 return NULL;
259 if (resources.Lookup( resname, type, ResLocator )) {
260 int bifnum = ( ResLocator & 0xFFF00000 ) >> 20;
262 if (core->GameOnCD && (biffiles[bifnum].cd != 0))
263 FindBIFOnCD(&biffiles[bifnum]);
264 if (!biffiles[bifnum].found) {
265 printf( "Cannot find %s... Resource unavailable.\n",
266 biffiles[bifnum].name );
267 return NULL;
270 ArchiveImporter* ai = ( ArchiveImporter* )
271 core->GetInterface( IE_BIF_CLASS_ID );
272 if (ai->OpenArchive( biffiles[bifnum].path ) == GEM_ERROR) {
273 printf("Cannot open archive %s\n", biffiles[bifnum].path );
274 core->FreeInterface( ai );
275 return NULL;
277 DataStream* ret = ai->GetStream( ResLocator, type );
278 core->FreeInterface( ai );
279 if (ret) {
280 strnlwrcpy( ret->filename, resname, 8 );
281 strcat( ret->filename, core->TypeExt( type ) );
282 return ret;
285 return NULL;
288 DataStream* KEYImporter::GetResource(const char* resname, SClass_ID type)
290 //the word masking is a hack for synonyms, currently used for bcs==bs
291 return GetStream(resname, type&0xFFFF);
294 DataStream* KEYImporter::GetResource(const char* resname, const ResourceDesc &type)
296 return GetStream(resname, type.GetKeyType());
299 #include "plugindef.h"
301 GEMRB_PLUGIN(0x1DFDEF80, "KEY File Importer")
302 PLUGIN_CLASS(PLUGIN_RESOURCE_KEY, KEYImporter)
303 END_PLUGIN()