1
0
Fork 0
mirror of https://github.com/AquariaOSE/Aquaria.git synced 2025-10-04 13:27:14 +00:00

added partial VFS support - enough to read static data from any source

This commit is contained in:
fgenesis 2011-09-15 18:33:13 +02:00
commit fa3e9e7329
56 changed files with 4021 additions and 606 deletions

View file

@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Base.h"
#include "Core.h"
#include "VFSDir.h"
#ifdef BBGE_BUILD_WINDOWS
#include <shellapi.h>
@ -272,30 +273,28 @@ std::string upperCase(const std::string &s1)
return ret;
}
bool exists(const std::string &f, bool makeFatal)
bool exists(const std::string &f, bool makeFatal /* = false */, bool skipVFS /* = false */)
{
/*
if (!PHYSFS_exists(f.c_str()))
{
*/
/*
std::ostringstream os;
os << "checking to see if [" << f << "] exists";
debugLog(os.str());
*/
if (f.empty())
return false;
FILE *file = fopen(core->adjustFilenameCase(f).c_str(), "rb");
if (!file)
if(!skipVFS)
{
if(core->vfs.GetFile(core->adjustFilenameCase(f).c_str()))
return true;
}
FILE *file = fopen(core->adjustFilenameCase(f).c_str(), "rb");
if (!file)
{
if (makeFatal)
{
if (makeFatal)
{
errorLog(std::string("Could not open [" + f + "]"));
exit(0);
}
return false;
errorLog(std::string("Could not open [" + f + "]"));
exit(0);
}
fclose(file);
//}
return false;
}
fclose(file);
return true;
}
@ -448,107 +447,20 @@ void debugLog(const std::string &s)
// delete[] when no longer needed.
char *readFile(std::string path, unsigned long *size_ret)
{
FILE *f = fopen(path.c_str(), "rb");
if (!f)
return NULL;
long fileSize;
if (fseek(f, 0, SEEK_END) != 0
|| (fileSize = ftell(f)) < 0
|| fseek(f, 0, SEEK_SET) != 0)
{
debugLog(path + ": Failed to get file size");
fclose(f);
return NULL;
}
char *buffer = new char[fileSize + 1];
if (!buffer)
{
std::ostringstream os;
os << path << ": Not enough memory for file ("
<< (fileSize+1) << " bytes)";
debugLog(os.str());
fclose(f);
return NULL;
}
long bytesRead = fread(buffer, 1, fileSize, f);
if (bytesRead != fileSize)
{
std::ostringstream os;
os << path << ": Failed to read file (only got "
<< bytesRead << " of " << fileSize << " bytes)";
debugLog(os.str());
fclose(f);
return NULL;
}
fclose(f);
if (size_ret)
*size_ret = fileSize;
buffer[fileSize] = 0;
return buffer;
}
/*
void pForEachFile(std::string path, std::string type, void callback(const std::string &filename, int param), int param)
{
char **rc = PHYSFS_enumerateFiles(path.c_str());
char **i;
for (i = rc; *i != NULL; i++)
{
std::string s(*i);
int p=0;
if ((p=s.find('.'))!=std::string::npos)
{
std::string ext = s.susbtr(p, s.getLength2D());
if (ext == type)
{
callback(fielnameafhghaha
}
}
}
PHYSFS_freeList(rc);
}
*/
void doSingleFile(const std::string &path, const std::string &type, std::string filename, void callback(const std::string &filename, int param), int param)
{
if (filename.size()>4)
{
std::string search = filename;
stringToLower(search);
std::string filetype = filename.substr(search.size()-4, search.size());
//stringToUpper(filetype);
//debugLog("comparing: " + filetype + " and: " + type);
//if (filetype==type)
debugLog("checking:" + search + " for type:" + type);
if (search.find(type)!=std::string::npos)
{
debugLog("callback");
callback(path+filename, param);
}
else
{
debugLog("not the same");
}
}
}
std::string stripEndlineForUnix(const std::string &in)
{
std::string out;
for (int i = 0; i < in.size(); i++)
{
if (int(in[i]) != 13)
{
out+= in[i];
}
}
return out;
ttvfs::VFSFile *vf = core->vfs.GetFile(path.c_str());
if(!vf)
return NULL;
vf->getBuf(); // force size calc early
// we can never know how the memory was allocated;
// because the buffer is expected to be deleted with delete[],
// it has to be explicitly copied to memory allocated with new[].
unsigned long s = vf->size();
char *buf = new char[s + 1];
memcpy(buf, vf->getBuf(), s + 1);
core->addVFSFileForDrop(vf);
if(size_ret)
*size_ret = s;
return buf;
}
void forEachFile(std::string path, std::string type, void callback(const std::string &filename, intptr_t param), intptr_t param)
@ -560,167 +472,29 @@ void forEachFile(std::string path, std::string type, void callback(const std::st
//HACK: MAC:
debugLog("forEachFile - path: " + path + " type: " + type);
#if defined(BBGE_BUILD_UNIX)
DIR *dir=0;
dir = opendir(path.c_str());
if (dir)
{
dirent *file=0;
while ( (file=readdir(dir)) != NULL )
{
if (file->d_name && strlen(file->d_name) > 4)
{
debugLog(file->d_name);
char *extension=strrchr(file->d_name,'.');
if (extension)
{
debugLog(extension);
if (extension!=NULL)
{
if (strcasecmp(extension,type.c_str())==0)
{
callback(path + std::string(file->d_name), param);
}
}
}
}
}
closedir(dir);
}
else
{
debugLog("FAILED TO OPEN DIR");
}
#endif
#ifdef BBGE_BUILD_WINDOWS
BOOL fFinished;
HANDLE hList;
TCHAR szDir[MAX_PATH+1];
WIN32_FIND_DATA FileData;
int end = path.size()-1;
if (path[end] != '/')
path[end] += '/';
// Get the proper directory path
// \\ %s\\*
if (type.find('.')==std::string::npos)
{
type = "." + type;
}
//std::string add = "%s*" + type;
//sprintf(szDir, "%s*", path.c_str());
sprintf(szDir, "%s\\*", path.c_str());
stringToUpper(type);
// Get the first file
hList = FindFirstFile(szDir, &FileData);
if (hList == INVALID_HANDLE_VALUE)
ttvfs::VFSDir *vd = core->vfs.GetDir(path.c_str(), false);
if(!vd)
{
//printf("No files found\n\n");
debugLog("No files of type " + type + " found in path " + path);
debugLog("Path '" + path + "' does not exist");
return;
}
else
for(ttvfs::ConstFileIter it = vd->fileIter(); it != vd->fileIterEnd(); ++it)
{
// Traverse through the directory structure
fFinished = FALSE;
while (!fFinished)
const ttvfs::VFSFile *f = it->second;
const char *e = strrchr(f->name(), '.');
if (e)
{
// Check the object is a directory or not
//printf("%*s%s\n", indent, "", FileData.cFileName);
std::string filename = FileData.cFileName;
//debugLog("found: " + filename);
if (filename.size()>4)
{
std::string filetype = filename.substr(filename.size()-4, filename.size());
stringToUpper(filetype);
//debugLog("comparing: " + filetype + " and: " + type);
if (filetype==type)
{
callback(path+filename, param);
}
}
if (!FindNextFile(hList, &FileData))
{
/*
if (GetLastError() == ERROR_NO_MORE_FILES)
{
fFinished = TRUE;
}
*/
fFinished = TRUE;
}
std::string exs(e);
stringToLower(exs);
if(exs != type)
continue;
}
else if(type.size())
continue;
callback(path + f->name(), param);
}
FindClose(hList);
#endif
}
std::vector<std::string> getFileList(std::string path, std::string type, int param)
{
std::vector<std::string> list;
#ifdef BBGE_BUILD_WINDOWS
BOOL fFinished;
HANDLE hList;
TCHAR szDir[MAX_PATH+1];
WIN32_FIND_DATA FileData;
// Get the proper directory path
sprintf(szDir, "%s\\*", path.c_str());
// Get the first file
hList = FindFirstFile(szDir, &FileData);
if (hList == INVALID_HANDLE_VALUE)
{
printf("No files found\n\n");
}
else
{
// Traverse through the directory structure
fFinished = FALSE;
while (!fFinished)
{
// Check the object is a directory or not
//printf("%*s%s\n", indent, "", FileData.cFileName);
std::string filename = FileData.cFileName;
if (filename.size()>4 && filename.substr(filename.size()-4, filename.size())==type)
{
//callback(path+filename, param);
list.push_back (filename);
}
if (!FindNextFile(hList, &FileData))
{
/*
if (GetLastError() == ERROR_NO_MORE_FILES)
{
fFinished = TRUE;
}
*/
fFinished = TRUE;
}
}
}
FindClose(hList);
#endif
return list;
}
std::string msg(const std::string &message)

View file

@ -192,13 +192,11 @@ void stringToLower(std::string &s);
void stringToLowerUserData(std::string &s);
void glColor3_256(int r, int g, int b);
float sqr(float x);
bool exists(const std::string &f, bool makeFatal = false);
bool exists(const std::string &f, bool makeFatal = false, bool skipVFS = false);
void errorLog(const std::string &s);
void debugLog(const std::string &s);
char *readFile(std::string path, unsigned long *size_ret = 0);
void forEachFile(std::string path, std::string type, void callback(const std::string &filename, intptr_t param), intptr_t param);
std::string stripEndlineForUnix(const std::string &in);
std::vector<std::string> getFileList(std::string path, std::string type, int param);
#ifdef HAVE_STRCASECMP
static inline int nocasecmp(const std::string &s1, const std::string &s2)
{ return strcasecmp(s1.c_str(), s2.c_str()); }
@ -225,19 +223,6 @@ Vector colorRGB(int r, int g, int b);
#endif
GLuint generateEmptyTexture(int res);
//void pForEachFile(std::string path, std::string type, void callback(const std::string &filename, int param), int param);
/*
void pfread(void *buffer, PHYSFS_uint32 size, PHYSFS_uint32 objs, PHYSFS_file *handle);
void pfseek(PHYSFS_file *handle,PHYSFS_uint64 byte,int origin);
void pfclose(PHYSFS_file *handle);
PHYSFS_file *openRead(const std::string &f);
std::string pLoadStream(const std::string &filename);
void pSaveStream(const std::string &filename, std::ostringstream &os);
*/
void drawCircle(float radius, int steps=1);
bool isVectorInRect(const Vector &vec, const Vector &coord1, const Vector &coord2);

View file

@ -100,7 +100,7 @@ void BitmapText::autoKern()
void BitmapText::loadSpacingMap(const std::string &file)
{
spacingMap.clear();
std::ifstream inFile(file.c_str());
VFSTextStdStreamIn inFile(file.c_str());
std::string line;
while (std::getline(inFile, line))
{

View file

@ -4193,6 +4193,10 @@ void Core::shutdown()
SDL_Quit();
debugLog("OK");
#endif
debugLog("Unloading VFS...");
vfs.Clear();
debugLog("OK");
}
//util funcs
@ -4528,6 +4532,33 @@ void Core::clearGarbage()
i++;
}
// delete leftover buffers from VFS
// FG: TODO: better do that periodically, and not every loop?
for(std::set<ttvfs::VFSFile*>::iterator it = vfsFilesToClear.begin(); it != vfsFilesToClear.end(); ++it)
{
(*it)->dropBuf(true);
(*it)->ref--;
}
vfsFilesToClear.clear();
}
void Core::addVFSFileForDrop(ttvfs::VFSFile *vf)
{
// HACK: because of save/poot.tmp caching and other stuff, we have to clear this always
// TODO: after getting rid of pack/unpackFile, this will be safer and can be done properly
if(strstr(vf->name(), "poot") || strstr(vf->name(), ".tmp"))
{
vf->dropBuf(true);
return;
}
std::set<ttvfs::VFSFile*>::iterator it = vfsFilesToClear.find(vf);
if(it == vfsFilesToClear.end())
{
vf->ref++;
vfsFilesToClear.insert(vf);
}
}
bool Core::canChangeState()
@ -4858,3 +4889,69 @@ int Core::tgaSaveSeries(char *filename,
// ilutGLScreenie();
}
#include "VFSTools.h"
static void _DumpVFS(const std::string a)
{
std::string fn = "vfsdump-" + a + ".txt";
std::ofstream out(fn.c_str());
core->vfs.debugDumpTree(out);
out.close();
}
void Core::setupVFS(const char *extradir /* = NULL */)
{
debugLog("Init VFS...");
if(!ttvfs::checkCompat())
{
errorLog("VFS incompatible!");
exit(1);
}
vfs.LoadFileSysRoot();
vfs.Prepare();
//#ifdef _DEBUG
// _DumpVFS("begin");
//#endif
#ifdef BBGE_BUILD_UNIX
// Load _mods dir from home folder into the data of the existing _mods dir, additionally.
// This does also change the internal path, so that files created using this dir's fullname() will
// automatically be created in the home directory.
ttvfs::VFSDir *moddir = vfs.GetDir("_mods", true);
std::string umods = getUserDataFolder() + "/_mods";
moddir->load(umods.c_str());
std::ostringstream os;
os << "VFS: Mounted _mods as: '" << vfs.GetDir("_mods")->fullname() << "'";
debugLog(os.str());
// Note: the original code to load/save mods is not yet changed.
// This will happen in a later patch.
#endif
if(extradir)
{
std::string msg("VFS extra dir: ");
msg += extradir;
debugLog(msg);
if(vfs.GetDir(extradir))
vfs.Mount(extradir, "");
else
vfs.MountExternalPath(extradir, "");
debugLog("extra dir added.");
}
// Example: everything in _patch dir will be mounted in the game's root dir
// -- place any files/folders there to override those the game uses.
// TODO: remove this later! - When the community datafile update is organized and everything.
vfs.Mount("_patch", "", true);
debugLog("VFS init done!");
//#ifdef _DEBUG
// _DumpVFS("done");
//#endif
}

View file

@ -51,6 +51,8 @@ BUILD_LINUX
#include "FrameBuffer.h"
#include "Shader.h"
#include "VFSIncludes.h"
class ParticleEffect;
class ParticleManager;
@ -1400,6 +1402,14 @@ protected:
int tgaSave(const char *filename, short int width, short int height, unsigned char pixelDepth, unsigned char *imageData);
virtual void onUpdate(float dt);
virtual void onRender(){}
// VFS related
private:
std::set<ttvfs::VFSFile*> vfsFilesToClear; // used for dropBuf() delaying
public:
ttvfs::VFSHelper vfs;
void setupVFS(const char *extradir = NULL);
void addVFSFileForDrop(ttvfs::VFSFile *vf);
};
extern Core *core;

View file

@ -34,6 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "Base.h"
#include "Core.h"
#include "VFSFile.h"
#include "FmodOpenALBridge.h"
#include "al.h"
@ -53,7 +55,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
class OggDecoder {
public:
// Create a decoder that streams from a file.
OggDecoder(FILE *fp);
OggDecoder(ttvfs::VFSFile *fp);
// Create a decoder that streams from a memory buffer.
OggDecoder(const void *data, long data_size);
@ -98,7 +100,7 @@ private:
// Data source. If fp != NULL, the source is that file; otherwise, the
// source is the buffer pointed to by "data" with size "data_size" bytes.
FILE *fp;
ttvfs::VFSFile *fp;
const char *data;
long data_size;
long data_pos; // Current read position for memory buffers
@ -129,22 +131,38 @@ private:
// ov_open_callbacks() call. Note that we rename the fseek() wrapper
// to avoid an identifier collision when building with more recent
// versions of libvorbis.
static int BBGE_ov_header_fseek_wrap(FILE *f,ogg_int64_t off,int whence){
static int BBGE_ov_header_fseek_wrap(void *f,ogg_int64_t off,int whence){
if(f==NULL)return(-1);
#ifdef __MINGW32__
return fseeko64(f,off,whence);
#elif defined (_WIN32)
return _fseeki64(f,off,whence);
#else
return fseek(f,off,whence);
#endif
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)f;
switch(whence)
{
case SEEK_SET: return vf->seek(off);
case SEEK_CUR: return vf->seekRel(off);
case SEEK_END: return vf->seek(vf->size() - off);
}
return -1;
}
static int noclose(FILE *f) {return 0;}
static size_t BBGE_ov_fread_wrap(void *ptr, size_t s, size_t count, void *f)
{
if(f==NULL)return(-1);
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)f;
size_t done = vf->read(ptr, s * count);
return done / s;
}
static long BBGE_ov_ftell_wrap(void *f)
{
if(f==NULL)return(-1);
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)f;
return vf->getpos();
}
static int noclose(void *f) {return 0;}
static const ov_callbacks local_OV_CALLBACKS_NOCLOSE = {
(size_t (*)(void *, size_t, size_t, void *)) fread,
(size_t (*)(void *, size_t, size_t, void *)) BBGE_ov_fread_wrap,
(int (*)(void *, ogg_int64_t, int)) BBGE_ov_header_fseek_wrap,
(int (*)(void *)) noclose, // NULL doesn't work in libvorbis-1.1.2
(long (*)(void *)) ftell
(long (*)(void *)) BBGE_ov_ftell_wrap
};
// Memory I/O callback set.
@ -156,7 +174,7 @@ static const ov_callbacks ogg_memory_callbacks = {
};
OggDecoder::OggDecoder(FILE *fp)
OggDecoder::OggDecoder(ttvfs::VFSFile *fp)
{
for (int i = 0; i < NUM_BUFFERS; i++)
{
@ -517,9 +535,9 @@ static ALenum GVorbisFormat = AL_NONE;
class OpenALSound
{
public:
OpenALSound(FILE *_fp, const bool _looping);
OpenALSound(ttvfs::VFSFile *_fp, const bool _looping);
OpenALSound(void *_data, long _size, const bool _looping);
FILE *getFile() const { return fp; }
ttvfs::VFSFile *getFile() const { return fp; }
const void *getData() const { return data; }
long getSize() const { return size; }
bool isLooping() const { return looping; }
@ -527,20 +545,21 @@ public:
void reference() { refcount++; }
private:
FILE * const fp;
ttvfs::VFSFile * const fp;
void * const data; // Only used if fp==NULL
const long size; // Only used if fp==NULL
const bool looping;
int refcount;
};
OpenALSound::OpenALSound(FILE *_fp, const bool _looping)
OpenALSound::OpenALSound(ttvfs::VFSFile *_fp, const bool _looping)
: fp(_fp)
, data(NULL)
, size(0)
, looping(_looping)
, refcount(1)
{
fp->ref++;
}
OpenALSound::OpenALSound(void *_data, long _size, const bool _looping)
@ -559,7 +578,11 @@ FMOD_RESULT OpenALSound::release()
if (refcount <= 0)
{
if (fp)
fclose(fp);
{
fp->close();
fp->dropBuf(true); // just in case there is a buffer...
fp->ref--;
}
else
free(data);
delete this;
@ -1044,8 +1067,6 @@ FMOD_RESULT OpenALSystem::createSound(const char *name_or_data, const FMOD_MODE
{
assert(!exinfo);
FMOD_RESULT retval = FMOD_ERR_INTERNAL;
// !!! FIXME: if it's not Ogg, we don't have a decoder. I'm lazy. :/
char *fname = (char *) alloca(strlen(name_or_data) + 16);
strcpy(fname, name_or_data);
@ -1053,50 +1074,39 @@ FMOD_RESULT OpenALSystem::createSound(const char *name_or_data, const FMOD_MODE
if (ptr) *ptr = '\0';
strcat(fname, ".ogg");
// just in case...
#undef fopen
FILE *io = fopen(core->adjustFilenameCase(fname).c_str(), "rb");
if (io == NULL)
ttvfs::VFSFile *vf = core->vfs.GetFile(fname);
if(!vf)
return FMOD_ERR_INTERNAL;
if (mode & FMOD_CREATESTREAM)
if(mode & FMOD_CREATESTREAM)
{
*sound = (Sound *) new OpenALSound(io, (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
retval = FMOD_OK;
}
else
{
fseek(io, 0, SEEK_END);
long size = ftell(io);
if (fseek(io, 0, SEEK_SET) != 0)
{
debugLog("Seek error on " + std::string(fname));
fclose(io);
return FMOD_ERR_INTERNAL;
}
// does it make sense to try to stream from anything else than an actual file on disk?
// Files inside containers are always loaded into memory, unless on-the-fly partial decompression is implemented...
// A typical ogg is < 3 MB in size, if that is preloaded and then decoded over time it should still be a big gain.
if(!vf->isopen())
vf->open(NULL, "rb");
else
vf->seek(0);
void *data = malloc(size);
if (data == NULL)
{
debugLog("Out of memory for " + std::string(fname));
fclose(io);
return FMOD_ERR_INTERNAL;
}
long nread = fread(data, 1, size, io);
fclose(io);
if (nread != size)
{
debugLog("Failed to read data from " + std::string(fname));
free(data);
return FMOD_ERR_INTERNAL;
}
*sound = (Sound *) new OpenALSound(data, size, (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
retval = FMOD_OK;
*sound = (Sound *) new OpenALSound(vf, (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
return FMOD_OK;
}
return retval;
// if we are here, create & preload & pre-decode full buffer
vf->getBuf(); // force early size detection
void *data = malloc(vf->size()); // because release() will use free() ...
if (!(data && vf->getBuf()))
{
debugLog("Out of memory for " + std::string(fname));
vf->close();
vf->dropBuf(true);
return FMOD_ERR_INTERNAL;
}
memcpy(data, vf->getBuf(), vf->size());
core->addVFSFileForDrop(vf);
*sound = (Sound *) new OpenALSound(data, vf->size(), (((mode & FMOD_LOOP_OFF) == 0) && (mode & FMOD_LOOP_NORMAL)));
return FMOD_OK;
}
ALBRIDGE(System,createStream,(const char *name_or_data, FMOD_MODE mode, FMOD_CREATESOUNDEXINFO *exinfo, Sound **sound),(name_or_data,mode,exinfo,sound))

View file

@ -123,7 +123,7 @@ void Precacher::precacheTex(const std::string &tex)
void Precacher::precacheList(const std::string &list, void progressCallback())
{
loadProgressCallback = progressCallback;
std::ifstream in(list.c_str());
VFSTextStdStreamIn in(list.c_str());
std::string t;
while (std::getline(in, t))
{

View file

@ -18,10 +18,8 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Core.h"
#include "Shader.h"
#ifdef BBGE_BUILD_WINDOWS
#include <sys/stat.h>
#endif
#ifdef BBGE_BUILD_SHADERS
// GL_ARB_shader_objects
@ -88,40 +86,16 @@ void Shader::setValue(float x, float y, float z, float w)
unsigned char *readShaderFile( const char *fileName )
{
debugLog("readShaderFile()");
#ifdef BBGE_BUILD_WINDOWS
FILE *file = fopen( fileName, "r" );
if( file == NULL )
{
errorLog("Cannot open shader file!");
return 0;
}
ttvfs::VFSFile *vf = core->vfs.GetFile(fileName);
if(!vf)
return NULL;
struct _stat fileStats;
if( _stat( fileName, &fileStats ) != 0 )
{
errorLog("Cannot get file stats for shader file!");
return 0;
}
unsigned char *buffer = new unsigned char[fileStats.st_size];
int bytes = fread( buffer, 1, fileStats.st_size, file );
buffer[bytes] = 0;
fclose( file );
debugLog("End readShaderFile()");
return buffer;
#else
debugLog("End readShaderFile()");
return 0;
#endif
vf->getBuf();
unsigned char *buf = new unsigned char[vf->size() + 1];
memcpy(buf, vf->getBuf(), vf->size() + 1);
core->addVFSFileForDrop(vf);
return buf;
}
void Shader::reload()

View file

@ -93,7 +93,7 @@ class SimpleIStringStream {
public:
/* Reuse flag passed to StringStream(char *,int). */
enum {
enum Mode {
/* Make a copy of the buffer (default action). */
COPY,
/* Use the passed-in string pointer as is. Requires the string
@ -212,7 +212,7 @@ class SimpleIStringStream {
/*-------------------------------------------------------------------*/
private:
protected:
char *buffer; // The buffer we're parsing.
char *position; // Our current position in the buffer.
bool freeOnDestroy; // Should we free the buffer when we're destroyed?

View file

@ -21,7 +21,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "SoundManager.h"
#include "Core.h"
#include "Base.h"
#include "PackRead.h"
#if defined(BBGE_BUILD_FMODEX)
#ifdef BBGE_BUILD_FMOD_OPENAL_BRIDGE
@ -134,20 +133,14 @@ FMOD_RESULT F_CALLBACK myopen(const char *name, int unicode, unsigned int *files
{
if (name)
{
FILE *fp;
fp = fopen(name, "rb");
if (!fp)
{
ttvfs::VFSFile *vf = core->vfs.GetFile(name);
if(!vf)
return FMOD_ERR_FILE_NOTFOUND;
}
fseek(fp, 0, SEEK_END);
*filesize = ftell(fp);
fseek(fp, 0, SEEK_SET);
vf->open();
*filesize = vf->size();
*handle = (void*)vf;
*userdata = (void *)0x12345678;
*handle = fp;
}
return FMOD_OK;
@ -160,7 +153,9 @@ FMOD_RESULT F_CALLBACK myclose(void *handle, void *userdata)
return FMOD_ERR_INVALID_PARAM;
}
fclose((FILE *)handle);
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)handle;
vf->close();
core->addVFSFileForDrop(vf);
return FMOD_OK;
}
@ -174,7 +169,8 @@ FMOD_RESULT F_CALLBACK myread(void *handle, void *buffer, unsigned int sizebytes
if (bytesread)
{
*bytesread = (int)fread(buffer, 1, sizebytes, (FILE *)handle);
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)handle;
*bytesread = vf->read((char*)buffer, sizebytes);
if (*bytesread < sizebytes)
{
@ -192,7 +188,8 @@ FMOD_RESULT F_CALLBACK myseek(void *handle, unsigned int pos, void *userdata)
return FMOD_ERR_INVALID_PARAM;
}
fseek((FILE *)handle, pos, SEEK_SET);
ttvfs::VFSFile *vf = (ttvfs::VFSFile*)handle;
vf->seek(pos);
return FMOD_OK;
}
@ -332,7 +329,7 @@ SoundManager::SoundManager(const std::string &defaultDevice)
debugLog("err_output_createbuffer, speaker mode");
result = SoundCore::system->setSpeakerMode(FMOD_SPEAKERMODE_STEREO);
if (checkError()) goto get_out;
debugLog("init 2");
result = SoundCore::system->init(channels, FMOD_INIT_NORMAL, 0, defaultDevice); /* Replace with whatever channel count and flags you use! */
if (checkError()) goto get_out;

View file

@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "Core.h"
#include "TTFFont.h"
@ -46,8 +47,17 @@ void TTFFont::destroy()
void TTFFont::load(const std::string &str, int sz)
{
font = new FTGLTextureFont(str.c_str());
font->FaceSize(sz);
ttvfs::VFSFile *vf = core->vfs.GetFile(str.c_str());
if(!vf)
{
font = new FTGLTextureFont(str.c_str()); // file not in VFS, just pretend nothing happened
font->FaceSize(sz);
return;
}
const unsigned char *buf = (const unsigned char*)vf->getBuf();
create(buf, vf->size(), sz); // this copies the buffer internally
core->addVFSFileForDrop(vf); // so we can delete our own
}
void TTFFont::create(const unsigned char *data, unsigned long datalen, int sz)

View file

@ -468,6 +468,20 @@ void Texture::loadPNG(const std::string &file)
{
if (file.empty()) return;
ttvfs::VFSFile *vf = core->vfs.GetFile(file.c_str());
const char *memptr = vf ? (const char*)vf->getBuf() : NULL;
if(!memptr)
{
debugLog("Can't load PNG file: " + file);
width = 64;
height = 64;
Texture::textureError = TEXERR_FILENOTFOUND;
//exit(1);
return;
}
int memsize = vf->size();
#ifdef BBGE_BUILD_OPENGL
@ -483,11 +497,11 @@ void Texture::loadPNG(const std::string &file)
if (filter == GL_NEAREST)
{
textures[0] = pngBind(file.c_str(), PNG_NOMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, filter, filter);
textures[0] = pngBindMem(memptr, memsize, PNG_NOMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, filter, filter);
}
else
{
textures[0] = pngBind(file.c_str(), PNG_BUILDMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, GL_LINEAR_MIPMAP_LINEAR, filter);
textures[0] = pngBindMem(memptr, memsize, PNG_BUILDMIPMAPS, pngType, &info, GL_CLAMP_TO_EDGE, GL_LINEAR_MIPMAP_LINEAR, filter);
}
@ -515,9 +529,9 @@ void Texture::loadPNG(const std::string &file)
Texture::textureError = TEXERR_FILENOTFOUND;
//exit(1);
}
#endif
core->addVFSFileForDrop(vf);
}
// internal load functions

57
BBGE/VFSFileStream.cpp Normal file
View file

@ -0,0 +1,57 @@
#include "Core.h"
#include "VFSFileStream.h"
VFSTextStreamIn::VFSTextStreamIn(const std::string& fn, SimpleIStringStream::Mode strmode /* = TAKE_OVER*/)
: SimpleIStringStream()
{
_init(fn.c_str(), strmode);
}
VFSTextStreamIn::VFSTextStreamIn(const char *fn, SimpleIStringStream::Mode strmode /* = TAKE_OVER*/)
: SimpleIStringStream()
{
_init(fn, strmode);
}
void VFSTextStreamIn::_init(const char *fn, SimpleIStringStream::Mode strmode)
{
ttvfs::VFSFile *vf = core->vfs.GetFile(fn);
if(vf)
{
vf->open(NULL, "r");
setString((char*)vf->getBuf(), strmode);
vf->close();
if(strmode == TAKE_OVER)
vf->dropBuf(false);
}
else
error = true;
}
VFSTextStdStreamIn::VFSTextStdStreamIn(const std::string& fn, SimpleIStringStream::Mode strmode /* = TAKE_OVER*/)
: std::istringstream()
{
_init(fn.c_str(), strmode);
}
VFSTextStdStreamIn::VFSTextStdStreamIn(const char *fn, SimpleIStringStream::Mode strmode /* = TAKE_OVER*/)
: std::istringstream()
{
_init(fn, strmode);
}
void VFSTextStdStreamIn::_init(const char *fn, SimpleIStringStream::Mode strmode)
{
ttvfs::VFSFile *vf = core->vfs.GetFile(fn);
if(vf)
{
vf->open(NULL, "r");
str((char*)vf->getBuf()); // stringstream will always make a copy
vf->close();
if(strmode == SimpleIStringStream::TAKE_OVER)
core->addVFSFileForDrop(vf);
}
else
this->setstate(std::ios_base::failbit);
}

43
BBGE/VFSFileStream.h Normal file
View file

@ -0,0 +1,43 @@
#ifndef VFS_FILE_STREAM_H
#define VFS_FILE_STREAM_H
#include "SimpleIStringStream.h"
class VFSTextStreamIn : public SimpleIStringStream
{
/* This class is an adapter to support STL-like read-only file streams for VFS files,
* using the SimpleIStringStream for performance reasons.
*
* strmode: one of COPY, REUSE, TAKE_OVER, see SimpleIStringStream.h
*/
public:
VFSTextStreamIn(const char *fn, SimpleIStringStream::Mode strmode = TAKE_OVER);
VFSTextStreamIn(const std::string& fn, SimpleIStringStream::Mode strmode = TAKE_OVER);
void close() {}
private:
void _init(const char *fn, SimpleIStringStream::Mode strmode);
};
class VFSTextStdStreamIn : public std::istringstream
{
/* This class is an adapter to support STL-like read-only file streams for VFS files,
* using std::istringstream.
*
* strmode: one of COPY, REUSE, TAKE_OVER, see SimpleIStringStream.h
* - Note: The file's content will always be copied, regardless of strmode setting.
* However, TAKE_OVER will drop the internal buffer.
*/
public:
VFSTextStdStreamIn(const char *fn, SimpleIStringStream::Mode strmode = SimpleIStringStream::TAKE_OVER);
VFSTextStdStreamIn(const std::string& fn, SimpleIStringStream::Mode strmode = SimpleIStringStream::TAKE_OVER);
void close() {}
private:
void _init(const char *fn, SimpleIStringStream::Mode strmode);
};
#endif

9
BBGE/VFSIncludes.h Normal file
View file

@ -0,0 +1,9 @@
#ifndef CUSTOM_VFS_INCLUDES_H
#define CUSTOM_VFS_INCLUDES_H
#include "VFS.h"
#include "VFSFileStream.h"
#include "VFSFile.h"
#endif

View file

@ -20,33 +20,13 @@ using namespace std;
#include <OpenGL/gl.h>
*/
#include "Base.h"
#include "SDL_endian.h"
#include "Core.h"
#include "lvpa/ByteBuffer.h"
//glFont header
#include "glfont2.h"
using namespace glfont;
static int read_int(ifstream &input)
{
int buffer;
input.read((char *)&buffer, 4);
return SDL_SwapLE32(buffer);
}
static float read_float(ifstream &input)
{
union
{
int i;
float f;
} buffer;
input.read((char *)&buffer.i, 4);
buffer.i = SDL_SwapLE32(buffer.i);
return buffer.f;
}
//*******************************************************************
//GLFont Class Implementation
@ -70,7 +50,6 @@ GLFont::~GLFont ()
//*******************************************************************
bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
{
ifstream input;
int num_chars, num_tex_bytes;
char *tex_bytes;
@ -78,19 +57,24 @@ bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
Destroy();
//Open input file
input.open(file_name, ios::in | ios::binary);
if (!input)
return false;
ttvfs::VFSFile *vf = core->vfs.GetFile(file_name);
if(!vf)
return false;
lvpa::ByteBuffer bb;
bb.append(vf->getBuf(), vf->size());
core->addVFSFileForDrop(vf);
lvpa::uint32 dummy;
// Read the header from file
header.tex = tex;
bb >> dummy; // skip tex field
bb >> header.tex_width;
bb >> header.tex_height;
bb >> header.start_char;
bb >> header.end_char;
bb >> dummy; // skip chars field
// Read the header from file
header.tex = tex;
input.seekg(4, ios::cur); // skip tex field
header.tex_width = read_int(input);
header.tex_height = read_int(input);
header.start_char = read_int(input);
header.end_char = read_int(input);
input.seekg(4, ios::cur); // skip chars field
std::ostringstream os;
os << "tex_width: " << header.tex_width << " tex_height: " << header.tex_height;
debugLog(os.str());
@ -103,18 +87,19 @@ bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
//Read character array
for (int i = 0; i < num_chars; i++)
{
header.chars[i].dx = read_float(input);
header.chars[i].dy = read_float(input);
header.chars[i].tx1 = read_float(input);
header.chars[i].ty1 = read_float(input);
header.chars[i].tx2 = read_float(input);
header.chars[i].ty2 = read_float(input);
bb >> header.chars[i].dx;
bb >> header.chars[i].dy;
bb >> header.chars[i].tx1;
bb >> header.chars[i].ty1;
bb >> header.chars[i].tx2;
bb >> header.chars[i].ty2;
}
//Read texture pixel data
num_tex_bytes = header.tex_width * header.tex_height * 2;
tex_bytes = new char[num_tex_bytes];
input.read(tex_bytes, num_tex_bytes);
//input.read(tex_bytes, num_tex_bytes);
bb.read(tex_bytes, num_tex_bytes);
//Build2DMipmaps(3, header.tex_width, header.tex_height, GL_UNSIGNED_BYTE, tex_bytes, 1);
@ -150,9 +135,6 @@ bool GLFont::Create (const char *file_name, int tex, bool loadTexture)
//Free texture pixels memory
delete[] tex_bytes;
//Close input file
input.close();
//Return successfully
return true;
}

View file

@ -22,6 +22,8 @@ must not be misrepresented as being the original software.
distribution.
*/
// hacked VFS support into this version.
#include <ctype.h>
#ifdef TIXML_USE_STL
@ -31,6 +33,8 @@ distribution.
#include "tinyxml.h"
#include "Core.h"
FILE* TiXmlFOpen( const char* filename, const char* mode );
bool TiXmlBase::condenseWhiteSpace = true;
@ -923,12 +927,11 @@ bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
value = filename;
// reading in binary mode so that tinyxml can normalize the EOL
FILE* file = TiXmlFOpen( value.c_str (), "rb" );
ttvfs::VFSFile* file = core->vfs.GetFile(value.c_str());
if ( file )
{
bool result = LoadFile( file, encoding );
fclose( file );
return result;
}
else
@ -938,7 +941,7 @@ bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding )
}
}
bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
bool TiXmlDocument::LoadFile( ttvfs::VFSFile* file, TiXmlEncoding encoding )
{
if ( !file )
{
@ -951,10 +954,15 @@ bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
location.Clear();
// Get the file size, so we can pre-allocate the string. HUGE speed impact.
long length = 0;
fseek( file, 0, SEEK_END );
length = ftell( file );
fseek( file, 0, SEEK_SET );
char* buf = (char*)file->getBuf();
if ( !buf )
{
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
long length = file->size();
// Strange case, but good to handle up front.
if ( length <= 0 )
@ -984,15 +992,6 @@ bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
}
*/
char* buf = new char[ length+1 ];
buf[0] = 0;
if ( fread( buf, length, 1, file ) != 1 ) {
delete [] buf;
SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// Process the buffer in place to normalize new lines. (See comment above.)
// Copies from the 'p' to 'q' pointer, where p can advance faster if
// a newline-carriage return is hit.
@ -1031,13 +1030,16 @@ bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding )
Parse( buf, 0, encoding );
delete [] buf;
core->addVFSFileForDrop(file);
return !Error();
}
bool TiXmlDocument::SaveFile( const char * filename ) const
{
// FG: TODO: use VFS stuff here as well
// The old c stuff lives on...
FILE* fp = TiXmlFOpen( filename, "w" );
if ( fp )

View file

@ -53,6 +53,11 @@ distribution.
#define TIXML_STRING TiXmlString
#endif
namespace ttvfs
{
class VFSFile;
}
// Deprecated library function hell. Compilers want to use the
// new safe versions. This probably doesn't fully address the problem,
// but it gets closer. There are too many compilers for me to fully
@ -1417,7 +1422,7 @@ public:
will be interpreted as an XML file. TinyXML doesn't stream in XML from the current
file location. Streaming may be added in the future.
*/
bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
bool LoadFile( ttvfs::VFSFile*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING );
/// Save a file using the given FILE*. Returns true if successful.
bool SaveFile( FILE* ) const;