00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include "physfs.h"
00030 #include "pgfilearchive.h"
00031 #include "pgapplication.h"
00032 #include "pglog.h"
00033 #include "pgfont.h"
00034
00036 #include "physfsrwops.h"
00037 #include <iostream>
00038 #include <cstring>
00039 #include "paragui.h"
00040
00041 Uint32 PG_FileArchive::my_instance_count = 0;
00042 PG_SurfaceCache PG_FileArchive::my_cache;
00043 #ifdef PG_LOAD_SDL_IMAGE_DYNAMICALLY
00044 static void* SDL_image_obj = NULL;
00045 #else
00046 #include <SDL_image.h>
00047 #endif
00048
00049 typedef SDL_Surface* (*IMG_Load_RW_FT)(SDL_RWops* src, int freesrc);
00050 static IMG_Load_RW_FT IMG_Load_RW_FUNC = NULL;
00051
00052 void PG_FileArchive::init( const char* argv0 )
00053 {
00054
00055 if(my_instance_count == 1) {
00056 if(PHYSFS_init(argv0) == 0) {
00057 std::cerr << "Unable to initialize PhysicsFS !" << std::endl;
00058 const char* errstr = PHYSFS_getLastError();
00059 if ( errstr )
00060 std::cerr << errstr;
00061 return;
00062 }
00063
00064 #ifdef PG_LOAD_SDL_IMAGE_DYNAMICALLY
00065
00066 SDL_image_obj = SDL_LoadObject(SDLIMAGE_LIB);
00067 if(SDL_image_obj == NULL) {
00068 PG_LogMSG("SDL_image not found! Only bmp images can be loaded!");
00069 } else {
00070 IMG_Load_RW_FUNC = (IMG_Load_RW_FT)SDL_LoadFunction(SDL_image_obj, "IMG_Load_RW");
00071 if(IMG_Load_RW_FUNC == NULL) {
00072 PG_LogERR("Unable to load IMG_Load_RW function. SDL_image disabled!");
00073 SDL_UnloadObject(SDL_image_obj);
00074 SDL_image_obj = NULL;
00075 }
00076 }
00077 #else
00078 IMG_Load_RW_FUNC = IMG_Load_RW;
00079 #endif
00080 }
00081 }
00082
00083 PG_FileArchive::PG_FileArchive() {
00084
00085 my_instance_count++;
00086
00087 init( "paragui" );
00088 }
00089
00090 PG_FileArchive::PG_FileArchive( const char* argv0 ) {
00091
00092 my_instance_count++;
00093
00094 init( argv0 );
00095 }
00096
00097
00098 PG_FileArchive::~PG_FileArchive() {
00099
00100 if(my_instance_count == 0) {
00101 return;
00102 }
00103
00104
00105 my_instance_count--;
00106
00107 if(my_instance_count == 0) {
00108 Deinit();
00109 #ifdef PG_LOAD_SDL_IMAGE_DYNAMICALLY
00110 if(SDL_image_obj != NULL) {
00111 SDL_UnloadObject(SDL_image_obj);
00112 SDL_image_obj = NULL;
00113 }
00114 #endif
00115 }
00116 }
00117
00118 void PG_FileArchive::Deinit() {
00119 PHYSFS_deinit();
00120 }
00121
00122 std::string *PG_FileArchive::PathToPlatform(const std::string& path) {
00123 std::string *newpath;
00124 const char* sep = GetDirSeparator();
00125 std::string::size_type pos = 0, incr;
00126 newpath = new std::string(path);
00127 incr = std::strlen(sep);
00128 if(incr == 1 && sep[0] == '/')
00129 return newpath;
00130
00131 #ifdef __MACOS__
00132
00133 while( (pos = newpath->find(":", pos)) != std::string::npos) {
00134 #else
00135 while( (pos = newpath->find("/", pos)) != std::string::npos) {
00136 #endif
00137 newpath->replace(pos, 1, sep);
00138 pos += incr;
00139 }
00140 return newpath;
00141 }
00142
00143
00144 bool PG_FileArchive::AddArchive(const std::string& arch, bool append) {
00145 std::string *newpath = PathToPlatform(arch);
00146 bool ret = (PHYSFS_addToSearchPath(newpath->c_str(), append) != 0);
00147 delete newpath;
00148 return ret;
00149 }
00150
00151 bool PG_FileArchive::RemoveArchive(const std::string& arch) {
00152 std::string *newpath = PathToPlatform(arch);
00153 bool ret = (PHYSFS_removeFromSearchPath(newpath->c_str()) != 0);
00154 delete newpath;
00155 return ret;
00156 }
00157
00158 char **PG_FileArchive::EnumerateFiles(const std::string& dir) {
00159 return PHYSFS_enumerateFiles(dir.c_str());
00160 }
00161
00162 PG_FileList* PG_FileArchive::GetFileList(const std::string& dir, const std::string& wildcard) {
00163 char **tempList = EnumerateFiles(dir);
00164
00165 if( tempList == NULL ) {
00166 return NULL;
00167 }
00168
00169 PG_FileList* retVal = new PG_FileList;
00170
00171 for( char** i = tempList; *i != NULL; i++) {
00172 if(fnmatch(wildcard.c_str(), *i, FNM_PATHNAME) == 0) {
00173 retVal->push_back(std::string(*i));
00174 }
00175 }
00176
00177
00178 PHYSFS_freeList(tempList);
00179
00180 return retVal;
00181 }
00182
00183 bool PG_FileArchive::Exists(const std::string& filename) {
00184 return PHYSFS_exists(filename.c_str()) != 0;
00185 }
00186
00187 bool PG_FileArchive::IsDirectory(const std::string& filename) {
00188 return PHYSFS_isDirectory(filename.c_str()) != 0;
00189 }
00190
00191 const char* PG_FileArchive::GetDirSeparator() {
00192 return PHYSFS_getDirSeparator();
00193 }
00194
00195 const char* PG_FileArchive::GetRealDir(const std::string& filename) {
00196 return PHYSFS_getRealDir(filename.c_str());
00197 }
00198
00199 const char* PG_FileArchive::GetLastError() {
00200 return PHYSFS_getLastError();
00201 }
00202
00203 const char* PG_FileArchive::GetBaseDir() {
00204 return PHYSFS_getBaseDir();
00205 }
00206
00207 const char* PG_FileArchive::GetUserDir() {
00208 return PHYSFS_getUserDir();
00209 }
00210
00211 const char* PG_FileArchive::GetWriteDir() {
00212 return PHYSFS_getWriteDir();
00213 }
00214
00215 PG_File* PG_FileArchive::OpenFile(const std::string& filename, Mode mode) {
00216 PHYSFS_file* file = 0;
00217 switch(mode) {
00218 case READ:
00219 file = PHYSFS_openRead(filename.c_str());
00220 break;
00221 case WRITE:
00222 file = PHYSFS_openWrite(filename.c_str());
00223 break;
00224 case APPEND:
00225 file = PHYSFS_openAppend(filename.c_str());
00226 break;
00227 }
00228 if(file == NULL) {
00229 return NULL;
00230 }
00231
00232 return new PG_File(file);
00233 }
00234
00235 SDL_RWops* PG_FileArchive::OpenFileRWops(const std::string& filename, Mode mode) {
00236 SDL_RWops* file = NULL;
00237 switch(mode) {
00238 case READ:
00239 file = PHYSFSRWOPS_openRead(filename.c_str());
00240 break;
00241 case WRITE:
00242 file = PHYSFSRWOPS_openWrite(filename.c_str());
00243 break;
00244 case APPEND:
00245 file = PHYSFSRWOPS_openAppend(filename.c_str());
00246 break;
00247 }
00248
00249 return file;
00250 }
00251
00252 bool PG_FileArchive::MakeDir(const std::string& dir) {
00253 return PHYSFS_mkdir(dir.c_str()) == 1;
00254 }
00255 bool PG_FileArchive::SetWriteDir(const std::string& dir) {
00256 if(PHYSFS_setWriteDir(dir.c_str())) {
00257 return PHYSFS_addToSearchPath(dir.c_str(), 0) == 1;
00258 } else {
00259 return false;
00260 }
00261 }
00262
00263 bool PG_FileArchive::SetSaneConfig(const std::string& organization,
00264 const std::string& appName,
00265 const std::string& archiveExt,
00266 bool includeCdRoms,
00267 bool archivesFirst) {
00268 return PHYSFS_setSaneConfig(organization.c_str(), appName.c_str(), archiveExt.c_str(),
00269 includeCdRoms, archivesFirst) == 1;
00270 }
00271
00272
00273 PG_DataContainer* PG_FileArchive::ReadFile(const std::string& filename) {
00274 PG_File *file = OpenFile(filename);
00275
00276 if(!file) {
00277 return 0;
00278 }
00279
00280 int size = file->fileLength();
00281
00282 if(size <= 0) {
00283 delete file;
00284 return 0;
00285 }
00286
00287 PG_DataContainer* data = new PG_DataContainer(size);
00288
00289 if(file->read(data->data(), size, 1) != 1) {
00290 delete data;
00291 delete file;
00292 return NULL;
00293 }
00294
00295 delete file;
00296
00297 return data;
00298 }
00299
00300 SDL_Surface* PG_FileArchive::LoadSurface(const std::string& filename, bool convert) {
00301 return LoadSurface(filename, false, 0, convert);
00302 }
00303
00304 SDL_Surface* PG_FileArchive::LoadSurface(const std::string& filename, bool usekey, Uint32 colorkey, bool convert) {
00305 if(filename.empty() || filename == "none") {
00306 return NULL;
00307 }
00308
00309
00310 SDL_Surface* surface = my_cache.FindSurface(filename);
00311
00312
00313 if(surface != NULL) {
00314 my_cache.IncRef(filename);
00315 return surface;
00316 }
00317
00318 surface = NULL;
00319 SDL_RWops *rw = OpenFileRWops(filename);
00320
00321 if(rw == NULL) {
00322 PG_LogWRN("Unable to open '%s' !", filename.c_str());
00323 return NULL;
00324 }
00325
00326 if(IMG_Load_RW_FUNC != NULL) {
00327 surface = IMG_Load_RW_FUNC(rw, 1);
00328 } else {
00329 surface = SDL_LoadBMP_RW(rw, 1);
00330 }
00331
00332 if(surface == NULL) {
00333 PG_LogWRN("Failed to load imagedata from '%s' !", filename.c_str());
00334 return NULL;
00335 }
00336
00337 if(surface == NULL) {
00338 PG_LogERR("Unable to load imagedata from '%s'", filename.c_str());
00339 PG_LogERR("PhysFS reported: '%s'", PG_FileArchive::GetLastError());
00340 PG_LogERR("SDL reported: '%s'", SDL_GetError());
00341 }
00342
00343 if(usekey == true) {
00344 SDL_SetColorKey(surface, SDL_SRCCOLORKEY, colorkey);
00345 }
00346
00347 if(convert) {
00348 SDL_Surface* tmpsrf = NULL;
00349 if (surface->flags & SDL_SRCALPHA)
00350 tmpsrf = SDL_DisplayFormatAlpha(surface);
00351 else
00352 tmpsrf = SDL_DisplayFormat(surface);
00353
00354 if(tmpsrf) {
00355 SDL_FreeSurface(surface);
00356 surface = tmpsrf;
00357 }
00358 }
00359
00360
00361 return my_cache.AddSurface(filename, surface);
00362 }
00363
00364 bool PG_FileArchive::UnloadSurface(SDL_Surface* surface, bool bDeleteIfNotExists) {
00365 my_cache.DeleteSurface(surface, bDeleteIfNotExists);
00366 return true;
00367 }
00368
00369 bool PG_FileArchive::RemoveAllArchives() {
00370 char** i = GetSearchPath();
00371 char** d;
00372 bool success = true;
00373
00374 for(d = i; *d != NULL; d++) {
00375 if(!RemoveArchive(*d)) {
00376 PG_LogWRN("Unable to remove '%s' from searchpath!", *d);
00377 success = false;
00378 }
00379 }
00380
00381 FreeList(i);
00382 return success;
00383 }
00384
00385 char** PG_FileArchive::GetSearchPath() {
00386 return PHYSFS_getSearchPath();
00387 }
00388
00389 PG_FileList* PG_FileArchive::GetSearchPathList() {
00390 char **tempList = PHYSFS_getSearchPath();
00391
00392 if( tempList == NULL ) {
00393 return NULL;
00394 }
00395
00396 PG_FileList* retVal = NULL;
00397
00398
00399 Uint32 size = 0;
00400 for(; tempList[ size ] != NULL; ++size) {}
00401
00402
00403 retVal = new std::vector< std::string >;
00404 retVal->reserve( size );
00405 for( Uint32 i = 0; i < size; ++i ) {
00406 retVal->push_back(std::string(tempList[ i ]));
00407 }
00408
00409
00410 PHYSFS_freeList(tempList);
00411
00412 return retVal;
00413 }
00414
00415 void PG_FileArchive::FreeList(void* list) {
00416 PHYSFS_freeList(list);
00417 }
00418
00419 void PG_FileArchive::EnableSymlinks(bool followSymlinks) {
00420 PHYSFS_permitSymbolicLinks(followSymlinks);
00421 }
00422
00423
00424
00425
00426
00427