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:
parent
0951283b31
commit
fa3e9e7329
56 changed files with 4021 additions and 606 deletions
326
BBGE/Base.cpp
326
BBGE/Base.cpp
|
@ -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)
|
||||
|
|
17
BBGE/Base.h
17
BBGE/Base.h
|
@ -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);
|
||||
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
10
BBGE/Core.h
10
BBGE/Core.h
|
@ -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;
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
57
BBGE/VFSFileStream.cpp
Normal 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
43
BBGE/VFSFileStream.h
Normal 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
9
BBGE/VFSIncludes.h
Normal 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
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue