From c91847d549cc1c30eb15504a15ea9a6d5aa48165 Mon Sep 17 00:00:00 2001 From: "chirs241097@gmail.com" Date: Sun, 12 Jan 2014 14:43:14 +0000 Subject: --- hge/resource.cpp | 395 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 395 insertions(+) create mode 100644 hge/resource.cpp (limited to 'hge/resource.cpp') diff --git a/hge/resource.cpp b/hge/resource.cpp new file mode 100644 index 0000000..0fb7051 --- /dev/null +++ b/hge/resource.cpp @@ -0,0 +1,395 @@ +/* +** Haaf's Game Engine 1.8 +** Copyright (C) 2003-2007, Relish Games +** hge.relishgames.com +** +** Core functions implementation: resources management +*/ + +#include "hge_impl.h" + +#include // the system version is better here. HGE's is out of date. + +#define NOCRYPT +//#define NOUNCRYPT +#include "ZLIB/unzip.h" + + +bool CALL HGE_Impl::Resource_AttachPack(const char *filename, const char *password) +{ + char *szName; + CResourceList *resItem=res; + unzFile zip; + + szName=Resource_MakePath(filename); + + while(resItem) + { + if(!strcmp(szName,resItem->filename)) return false; + resItem=resItem->next; + } + + zip=unzOpen(szName); + if(!zip) { + System_Log("Unable to unzip: %s", szName); + return false; + } + unzClose(zip); + + resItem=new CResourceList; + strcpy(resItem->filename, szName); + if(password) strcpy(resItem->password, password); + else resItem->password[0]=0; + resItem->next=res; + res=resItem; + + return true; +} + +void CALL HGE_Impl::Resource_RemovePack(const char *filename) +{ + char *szName; + CResourceList *resItem=res, *resPrev=0; + + szName=Resource_MakePath(filename); + + while(resItem) + { + if(!strcmp(szName,resItem->filename)) + { + if(resPrev) resPrev->next=resItem->next; + else res=resItem->next; + delete resItem; + break; + } + + resPrev=resItem; + resItem=resItem->next; + } +} + +void CALL HGE_Impl::Resource_RemoveAllPacks() +{ + CResourceList *resItem=res, *resNextItem; + + while(resItem) + { + resNextItem=resItem->next; + delete resItem; + resItem=resNextItem; + } + + res=0; +} + +void* CALL HGE_Impl::Resource_Load(const char *filename, DWORD *size) +{ + const char *res_err="Can't load resource: %s"; + + CResourceList *resItem=res; + char szName[_MAX_PATH]; + char szZipName[_MAX_PATH]; + unzFile zip; + unz_file_info file_info; + int done, i; + void *ptr; + FILE *hF; + + if(filename[0]=='\\' || filename[0]=='/' || filename[1]==':') goto _fromfile; // skip absolute paths + + // Load from pack + + strcpy(szName,filename); + for(i=0; szName[i]; i++) { if(szName[i]=='/') szName[i]='\\'; } + + while(resItem) + { + zip=unzOpen(resItem->filename); + done=unzGoToFirstFile(zip); + while(done==UNZ_OK) + { + unzGetCurrentFileInfo(zip, &file_info, szZipName, sizeof(szZipName), NULL, 0, NULL, 0); + for(i=0; szZipName[i]; i++) { if(szZipName[i]=='/') szZipName[i]='\\'; } + if(!strcmp(szName,szZipName)) + { + if(unzOpenCurrentFilePassword(zip, resItem->password[0] ? resItem->password : 0) != UNZ_OK) + { + unzClose(zip); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + ptr = malloc(file_info.uncompressed_size); + if(!ptr) + { + unzCloseCurrentFile(zip); + unzClose(zip); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + if(unzReadCurrentFile(zip, ptr, file_info.uncompressed_size) < 0) + { + unzCloseCurrentFile(zip); + unzClose(zip); + free(ptr); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + unzCloseCurrentFile(zip); + unzClose(zip); + if(size) *size=file_info.uncompressed_size; + return ptr; + } + + done=unzGoToNextFile(zip); + } + + unzClose(zip); + resItem=resItem->next; + } + + // Load from file +_fromfile: + + hF = fopen(Resource_MakePath(filename), "rb"); + if(hF == NULL) + { + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + struct stat statbuf; + if (fstat(fileno(hF), &statbuf) == -1) + { + fclose(hF); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + file_info.uncompressed_size = statbuf.st_size; + ptr = malloc(file_info.uncompressed_size); + if(!ptr) + { + fclose(hF); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + if(fread(ptr, file_info.uncompressed_size, 1, hF) != 1) + { + fclose(hF); + free(ptr); + sprintf(szName, res_err, filename); + _PostError(szName); + return 0; + } + + fclose(hF); + + if(size) *size=file_info.uncompressed_size; + return ptr; +} + + +void CALL HGE_Impl::Resource_Free(void *res) +{ + if(res) free(res); +} + +// this is from PhysicsFS originally ( http://icculus.org/physfs/ ) +// (also zlib-licensed.) +static int locateOneElement(char *buf) +{ + char *ptr = NULL; + DIR *dirp = NULL; + struct dirent *dent = NULL; + + if (access(buf, F_OK) == 0) + return 1; /* quick rejection: exists in current case. */ + + ptr = strrchr(buf, '/'); /* find entry at end of path. */ + if (ptr == NULL) + { + dirp = opendir("."); + ptr = buf; + } + else + { + *ptr = '\0'; + dirp = opendir(buf); + *ptr = '/'; + ptr++; /* point past dirsep to entry itself. */ + } + + while ((dent = readdir(dirp)) != NULL) + { + if (strcasecmp(dent->d_name, ptr) == 0) + { + strcpy(ptr, dent->d_name); /* found a match. Overwrite with this case. */ + closedir(dirp); + return 1; + } + } + + /* no match at all... */ + closedir(dirp); + return 0; +} + +static int locateCorrectCase(char *buf) +{ + char *ptr = buf; + char *prevptr = buf; + + while (ptr = strchr(ptr + 1, '/')) + { + *ptr = '\0'; /* block this path section off */ + if (!locateOneElement(buf)) + { + *ptr = '/'; /* restore path separator */ + return -2; /* missing element in path. */ + } + *ptr = '/'; /* restore path separator */ + } + + /* check final element... */ + return locateOneElement(buf) ? 0 : -1; +} + +char* CALL HGE_Impl::Resource_MakePath(const char *filename) +{ + int i; + + if(!filename) + strcpy(szTmpFilename, szAppPath); + else if(filename[0]=='\\' || filename[0]=='/' || filename[1]==':') + strcpy(szTmpFilename, filename); + else + { + strcpy(szTmpFilename, szAppPath); + if(filename) strcat(szTmpFilename, filename); + } + + for(i=0; szTmpFilename[i]; i++) { if(szTmpFilename[i]=='\\') szTmpFilename[i]='/'; } + + locateCorrectCase(szTmpFilename); + + return szTmpFilename; +} + +// !!! FIXME: kinda messy, and probably doesn't get all the corner cases right. +bool HGE_Impl::_WildcardMatch(const char *str, const char *wildcard) +{ + if ((str == NULL) || (wildcard == NULL)) + return false; + + while ((*str) && (*wildcard)) + { + const char wildch = *wildcard; + const char strch = *str; + if (wildch == '?') + ; // okay. + else if (wildch == '*') + { + do { + wildcard++; + } while (((*wildcard == '*') || (*wildcard == '?')) && (*wildcard != '\0')); + const char newwild = *wildcard; + if (newwild == '\0') return true; + const char *ptr = str; + while (*ptr) // find the greediest match possible... + { + if (*ptr == newwild) + str = ptr; + ptr++; + } + } + else if ( (toupper(strch)) != (toupper(wildch)) ) + { + return false; + } + + str++; + wildcard++; + } + + while (*wildcard == '*') + wildcard++; + + return ((*str == '\0') && (*wildcard == '\0')); +} + +bool HGE_Impl::_PrepareFileEnum(const char *wildcard) +{ + if(hSearch) { closedir(hSearch); hSearch=0; } + char *madepath = Resource_MakePath(wildcard); + const char *fname = strrchr(madepath, '/'); + const char *dir = NULL; + if (fname == NULL) { + dir = "."; + fname = madepath; + } else { + dir = madepath; + char *ptr = (char *) fname; + *ptr = '\0'; // split dir and filename. + fname++; + } + + strcpy(szSearchDir, dir); + strcpy(szSearchWildcard, fname); + + hSearch=opendir(dir); + return (hSearch!=0); +} + +char *HGE_Impl::_DoEnumIteration(const bool wantdir) +{ + if(!hSearch) return 0; + while (true) + { + struct dirent *dent = readdir(hSearch); + if(dent == NULL) { closedir(hSearch); hSearch=0; return 0; } + if ((strcmp(dent->d_name, ".") == 0) || (strcmp(dent->d_name, "..") == 0)) + continue; + if (!_WildcardMatch(dent->d_name, szSearchWildcard)) + continue; + char fullpath[_MAX_PATH]; + snprintf(fullpath, sizeof (fullpath), "%s/%s", szSearchDir, dent->d_name); + struct stat statbuf; + if (stat(fullpath, &statbuf) == -1) // this follows symlinks. + continue; + const bool isdir = ((S_ISDIR(statbuf.st_mode)) != 0); + if (isdir == wantdir) // this treats pipes, devs, etc, as "files" ... + { + strcpy(szSearchResult, dent->d_name); + return szSearchResult; + } + } + return 0; +} + +char* CALL HGE_Impl::Resource_EnumFiles(const char *wildcard) +{ + if(wildcard) + { + if (!_PrepareFileEnum(wildcard)) + return 0; + } + return _DoEnumIteration(false); +} + +char* CALL HGE_Impl::Resource_EnumFolders(const char *wildcard) +{ + if(wildcard) + { + if (!_PrepareFileEnum(wildcard)) + return 0; + } + return _DoEnumIteration(true); +} -- cgit v1.2.3