From f6de818ea8d189f35746c9be78152e979aaed1a4 Mon Sep 17 00:00:00 2001 From: Ykkrosh Date: Wed, 20 Dec 2006 03:22:24 +0000 Subject: [PATCH] # Added support for automatically loading 3d models in the COLLADA format. * CMeshManager: Changed to check for .pmd and .dae files and convert and cache as appropriate. * CModelDef: Fixed misinterpreted doc comments in. * lib: * Fixed init/shutdown sequences to support multiple VFS-using tests correctly. * Fixed most reported memory leaks from the new leak-reporting test system. * Fixed error when trying to dump debug data about fonts after unloading them. * Added sphere dae/pmd data for tests. * Added output buffering to DAE->PMD converter. * Added precompiled COLLADA converter DLLs. * Removed old redundant conversion script. This was SVN commit r4709. --- binaries/data/tests/collada/sphere.dae | 3 + binaries/data/tests/collada/sphere.pmd | 3 + binaries/system/collada2pmd.py | 43 --- source/collada/Converter.cpp | 9 +- source/collada/Converter.h | 7 +- source/collada/DLL.cpp | 55 ++- source/collada/DLL.h | 6 +- source/collada/tests/tests.py | 10 +- source/graphics/MeshManager.cpp | 236 ++++++++++++- source/graphics/MeshManager.h | 20 +- source/graphics/ModelDef.cpp | 13 +- source/graphics/ModelDef.h | 22 +- source/graphics/ObjectEntry.cpp | 12 +- source/graphics/tests/test_MeshManager.h | 177 ++++++++++ source/lib/adts.h | 16 +- source/lib/res/file/path.cpp | 17 +- .../lib/res/file/tests/test_archive_builder.h | 10 +- source/lib/res/file/tests/test_compression.h | 3 + source/lib/res/file/tests/test_path.h | 2 + source/lib/res/file/trace.cpp | 2 +- source/lib/res/file/vfs_tree.cpp | 3 + source/lib/res/graphics/unifont.cpp | 9 +- source/lib/res/h_mgr.cpp | 19 +- source/ps/Errors.cpp | 317 +++++++++--------- source/renderer/ModelRenderer.cpp | 1 + 25 files changed, 733 insertions(+), 282 deletions(-) create mode 100644 binaries/data/tests/collada/sphere.dae create mode 100644 binaries/data/tests/collada/sphere.pmd delete mode 100644 binaries/system/collada2pmd.py create mode 100644 source/graphics/tests/test_MeshManager.h diff --git a/binaries/data/tests/collada/sphere.dae b/binaries/data/tests/collada/sphere.dae new file mode 100644 index 0000000000..741f70880d --- /dev/null +++ b/binaries/data/tests/collada/sphere.dae @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a9a95ce9bc83119ae4d49f91b3e8fa2a33095d0b71d95aecfec04312180bc13 +size 7580 diff --git a/binaries/data/tests/collada/sphere.pmd b/binaries/data/tests/collada/sphere.pmd new file mode 100644 index 0000000000..eba967effa --- /dev/null +++ b/binaries/data/tests/collada/sphere.pmd @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6c8acd8eb6bd7b6a8ba2168fafc8fc006a271670a11b681c54d7c91250d1278e +size 7804 diff --git a/binaries/system/collada2pmd.py b/binaries/system/collada2pmd.py deleted file mode 100644 index f72c81f60a..0000000000 --- a/binaries/system/collada2pmd.py +++ /dev/null @@ -1,43 +0,0 @@ -from ctypes import * -import sys -import os - -if len(sys.argv) != 3: - print "Incorrect command-line syntax. Use" - print " " + sys.argv[0] + " input.dae output.pmd" - sys.exit(-1) - -input_filename, output_filename = sys.argv[1:] - -if not os.path.exists(input_filename): - print "Cannot find input file '%s'" % input_filename - sys.exit(-1) - -dll_filename = { - 'posix': './libCollada_dbg.so', - 'nt': 'Collada.dll', -}[os.name] - -library = cdll.LoadLibrary(dll_filename) - -def log(severity, message): - print '[%s] %s' % (('INFO', 'WARNING', 'ERROR')[severity], message) - -clog = CFUNCTYPE(None, c_int, c_char_p)(log) - # (the CFUNCTYPE must not be GC'd, so try to keep a reference) -library.set_logger(clog) - -def convert_dae_to_pmd(filename): - output = [] - def cb(str, len): - output.append(string_at(str, len)) - - cbtype = CFUNCTYPE(None, POINTER(c_char), c_uint) - status = library.convert_dae_to_pmd(filename, cbtype(cb)) - assert(status == 0) - return ''.join(output) - -input = open(input_filename).read() -output = convert_dae_to_pmd(input) -open(output_filename, 'wb').write(output) - diff --git a/source/collada/Converter.cpp b/source/collada/Converter.cpp index 24005e2aaa..e7859ee00d 100644 --- a/source/collada/Converter.cpp +++ b/source/collada/Converter.cpp @@ -38,7 +38,7 @@ void require_(int line, const FUStatus& status) } /** Outputs a structure, using sizeof to get the size. */ -template void write(OutputFn output, const T& data) +template void write(OutputCB& output, const T& data) { output((char*)&data, sizeof(T)); } @@ -83,7 +83,7 @@ public: * @param xmlErrors output - errors reported by the XML parser * @throws ColladaException on failure */ - static void ColladaToPMD(const char* input, OutputFn output, std::string& xmlErrors) + static void ColladaToPMD(const char* input, OutputCB& output, std::string& xmlErrors) { FUStatus ret; @@ -239,7 +239,8 @@ public: /** * Writes the model data in the PMD format. */ - static void WritePMD(OutputFn output, size_t vertexCount, size_t boneCount, + static void WritePMD(OutputCB& output, + size_t vertexCount, size_t boneCount, float* position, float* normal, float* texcoord, VertexBlend* boneWeights, BoneTransform* boneTransforms) { @@ -565,7 +566,7 @@ public: // with forward declarations of functions - but provide the plain function // interface here: -void ColladaToPMD(const char* input, OutputFn output, std::string& xmlErrors) +void ColladaToPMD(const char* input, OutputCB& output, std::string& xmlErrors) { Converter::ColladaToPMD(input, output, xmlErrors); } diff --git a/source/collada/Converter.h b/source/collada/Converter.h index 55422a05b9..c1d2f342e5 100644 --- a/source/collada/Converter.h +++ b/source/collada/Converter.h @@ -24,6 +24,11 @@ private: std::string msg; }; -void ColladaToPMD(const char* input, OutputFn output, std::string& xmlErrors); +struct OutputCB +{ + virtual void operator() (const char* data, unsigned int length)=0; +}; + +void ColladaToPMD(const char* input, OutputCB& output, std::string& xmlErrors); #endif // CONVERTER_H__ diff --git a/source/collada/DLL.cpp b/source/collada/DLL.cpp index 48fd173d33..e48e32f167 100644 --- a/source/collada/DLL.cpp +++ b/source/collada/DLL.cpp @@ -3,6 +3,7 @@ #include "Converter.h" #include +#include void default_logger(int severity, const char* message) { @@ -13,7 +14,10 @@ static LogFn g_Logger = &default_logger; void set_logger(LogFn logger) { - g_Logger = logger; + if (logger) + g_Logger = logger; + else + g_Logger = &default_logger; } void Log(int severity, const char* msg, ...) @@ -28,14 +32,59 @@ void Log(int severity, const char* msg, ...) g_Logger(severity, buffer); } -int convert_dae_to_pmd(const char* dae, OutputFn pmd_writer) +struct BufferedOutputCallback : public OutputCB +{ + static const int bufferSize = 4096; + char buffer[bufferSize]; + int bufferUsed; + + OutputFn fn; + void* cb_data; + + BufferedOutputCallback(OutputFn fn, void* cb_data) + : fn(fn), cb_data(cb_data), bufferUsed(0) + { + } + + ~BufferedOutputCallback() + { + // flush the buffer if it's not empty + if (bufferUsed > 0) + fn(cb_data, buffer, bufferUsed); + } + + virtual void operator() (const char* data, unsigned int length) + { + if (bufferUsed+length > bufferSize) + { + // will overflow buffer, so flush the buffer first + fn(cb_data, buffer, bufferUsed); + bufferUsed = 0; + + if (length > bufferSize) + { + // new data won't fit in buffer, so send it out unbuffered + fn(cb_data, data, length); + return; + } + } + + // append onto buffer + memcpy(buffer+bufferUsed, data, length); + bufferUsed += length; + assert(bufferUsed <= bufferSize); + } +}; + +int convert_dae_to_pmd(const char* dae, OutputFn pmd_writer, void* cb_data) { Log(LOG_INFO, "Starting conversion"); std::string xmlErrors; + BufferedOutputCallback cb(pmd_writer, cb_data); try { - ColladaToPMD(dae, pmd_writer, xmlErrors); + ColladaToPMD(dae, cb, xmlErrors); } catch (ColladaException e) { diff --git a/source/collada/DLL.h b/source/collada/DLL.h index a75ce4411d..18e24e9016 100644 --- a/source/collada/DLL.h +++ b/source/collada/DLL.h @@ -21,10 +21,12 @@ extern "C" #define LOG_ERROR 2 typedef void (*LogFn) (int severity, const char* text); -typedef void (*OutputFn) (const char* data, unsigned int length); +typedef void (*OutputFn) (void* cb_data, const char* data, unsigned int length); + +#define COLLADA_CONVERTER_VERSION 1 EXPORT void set_logger(LogFn logger); -EXPORT int convert_dae_to_pmd(const char* dae, OutputFn pmd_writer); +EXPORT int convert_dae_to_pmd(const char* dae, OutputFn pmd_writer, void* cb_data); #ifdef __cplusplus }; diff --git a/source/collada/tests/tests.py b/source/collada/tests/tests.py index 46b0edc84f..1055022079 100644 --- a/source/collada/tests/tests.py +++ b/source/collada/tests/tests.py @@ -21,11 +21,11 @@ library.set_logger(clog) def convert_dae_to_pmd(filename): output = [] - def cb(str, len): + def cb(cbdata, str, len): output.append(string_at(str, len)) - cbtype = CFUNCTYPE(None, POINTER(c_char), c_uint) - status = library.convert_dae_to_pmd(filename, cbtype(cb)) + cbtype = CFUNCTYPE(None, POINTER(None), POINTER(c_char), c_uint) + status = library.convert_dae_to_pmd(filename, cbtype(cb), None) assert(status == 0) return ''.join(output) @@ -64,8 +64,8 @@ test_mod = binaries + '/data/mods/_test.collada' clean_dir(test_mod + '/art/meshes') clean_dir(test_mod + '/art/actors') -for test_file in ['cube', 'jav2', 'teapot_basic', 'teapot_skin', 'plane_skin', 'dude_skin']: -#for test_file in ['dude_skin']: +#for test_file in ['cube', 'jav2', 'teapot_basic', 'teapot_skin', 'plane_skin', 'dude_skin']: +for test_file in ['sphere']: input_filename = '%s/%s.dae' % (test_data, test_file) output_filename = '%s/art/meshes/%s.pmd' % (test_mod, test_file) diff --git a/source/graphics/MeshManager.cpp b/source/graphics/MeshManager.cpp index 26798f2e10..dc93ac33c8 100644 --- a/source/graphics/MeshManager.cpp +++ b/source/graphics/MeshManager.cpp @@ -1,41 +1,241 @@ #include "precompiled.h" -#include "graphics/MeshManager.h" + +#include "MeshManager.h" + +#include "graphics/ModelDef.h" #include "ps/CLogger.h" #include "ps/FileUnpacker.h" // to get access to its CError -#include "ModelDef.h" +#include "ps/CVFSFile.h" +#include "ps/DllLoader.h" +#include "lib/res/file/vfs.h" + +namespace Collada +{ + #include "collada/DLL.h" +} + +#include + +#define LOG_CATEGORY "mesh" + +void ColladaLog(int severity, const char* text) +{ + LOG(severity==LOG_INFO ? NORMAL : severity==LOG_WARNING ? WARNING : ERROR, + "collada", "%s", text); +} + +struct VFSOutputCB +{ + VFSOutputCB(Handle hf) : hf(hf) {} + void operator() (const char* data, unsigned int length) + { + FileIOBuf buf = (FileIOBuf)data; + const ssize_t ret = vfs_io(hf, length, &buf); + // TODO: handle errors sensibly + } + + Handle hf; +}; + +void ColladaOutput(void* cb_data, const char* data, unsigned int length) +{ + VFSOutputCB* cb = static_cast(cb_data); + (*cb)(data, length); +} + +typedef STL_HASH_MAP, CStr_hash_compare> mesh_map; +class CMeshManagerImpl +{ + DllLoader dll; + + void (*set_logger)(Collada::LogFn logger); + int (*convert_dae_to_pmd)(const char* dae, Collada::OutputFn pmd_writer, void* cb_data); + +public: + mesh_map MeshMap; + + CMeshManagerImpl() + : dll("Collada") + { + } + + ~CMeshManagerImpl() + { + if (dll.IsLoaded()) + set_logger(NULL); // unregister the log handler + } + + CModelDefPtr Convert(const CStr& daeFilename, const CStr& pmdFilename, const CStr& name) + { + // To avoid always loading the DLL when it's usually not going to be + // used (and to do the same on Linux where delay-loading won't help), + // and to avoid compile-time dependencies (because it's a minor pain + // to get all the right libraries to build the COLLADA DLL), we load + // it dynamically when it is required, instead of using the exported + // functions and binding at link-time. + if (! dll.IsLoaded()) + { + if (! dll.LoadDLL()) + { + LOG_ONCE(ERROR, LOG_CATEGORY, "Failed to load COLLADA conversion DLL"); + return CModelDefPtr(); + } + + try + { + dll.LoadSymbol("set_logger", set_logger); + dll.LoadSymbol("convert_dae_to_pmd", convert_dae_to_pmd); + } + catch (PSERROR_DllLoader&) + { + LOG(ERROR, LOG_CATEGORY, "Failed to load symbols from COLLADA conversion DLL"); + return CModelDefPtr(); + } + + set_logger(ColladaLog); + } + + // We need to null-terminate the buffer, so do it (possibly inefficiently) + // by converting to a CStr + CStr daeData; + + { + CVFSFile daeFile; + if (daeFile.Load(daeFilename) != PSRETURN_OK) + return CModelDefPtr(); + + daeData = daeFile.GetAsString(); + + // scope closes daeFile - necessary if we don't use FILE_LONG_LIVED + } + + // Prepare the output file + Handle hf = vfs_open(pmdFilename, FILE_WRITE|FILE_NO_AIO); + if (hf < 0) + return CModelDefPtr(); + + // Do the conversion + VFSOutputCB cb (hf); + convert_dae_to_pmd(daeData.c_str(), ColladaOutput, static_cast(&cb)); + + vfs_close(hf); + + // Now load the PMD that was just created + CModelDefPtr model (CModelDef::Load(pmdFilename, name)); + MeshMap[name] = model; + return model; + } +}; CMeshManager::CMeshManager() +: m(new CMeshManagerImpl()) { } CMeshManager::~CMeshManager() { + delete m; } -CModelDefPtr CMeshManager::GetMesh(const char *filename) +CModelDefPtr CMeshManager::GetMesh(const CStr& filename) { - CStr fn(filename); - mesh_map::iterator iter = m_MeshMap.find(fn); - if (iter != m_MeshMap.end() && !iter->second.expired()) - { - CModelDefPtr model (iter->second); - //LOG(MESSAGE, "mesh", "Loading mesh '%s%' (cached)...", filename); - return model; - } + // Strip a three-letter file extension (if there is one) from the filename + CStr name; + if (filename.Length() > 4 && filename[filename.Length()-4] == '.') + name = filename.GetSubstring(0, filename.Length()-4); + else + name = filename; + + // Find the mesh if it's already been loaded and cached + mesh_map::iterator iter = m->MeshMap.find(name); + if (iter != m->MeshMap.end() && !iter->second.expired()) + return CModelDefPtr(iter->second); + + /* + + If there is a .dae file: + * Calculate a hash to identify it. + * Look for a cached .pmd file matching that hash. + * If it exists, load it. Else, convert the .dae into .pmd and load it. + Otherwise, if there is a (non-cache) .pmd file: + * Load it. + Else, fail. + + The hash calculation ought to be fast, since normally (during development) + the .dae file will exist but won't have changed recently and so the cache + would be used. Hence, just hash the file's size, mtime, and the converter + version number (so updates will cause regeneration of .pmds) instead of + its contents. + + TODO (maybe): The .dae -> .pmd conversion may fail (e.g. if the .dae is + invalid or unsupported), but it may take a long time to start the conversion + then realise it's not going to work. That will delay the loading of the game + every time, which is annoying, so maybe it should cache the error messge + until the .dae is updated and fixed. (Alternatively, avoid having many + broken .daes in the game's data files.) + + */ try { - CModelDefPtr model (CModelDef::Load(filename)); - if (!model) - return CModelDefPtr(); + CStr dae = name+".dae"; + if (! vfs_exists(dae)) + { + // No .dae - got to use the .pmd, assuming there is one + CModelDefPtr model (CModelDef::Load(name+".pmd", name)); + m->MeshMap[name] = model; + return model; + } - //LOG(MESSAGE, "mesh", "Loading mesh '%s'...", filename); - m_MeshMap[fn] = model; - return model; + // There is a .dae - see if there's an up-to-date cached copy + + struct stat fileStat; + if (vfs_stat(dae, &fileStat) < 0) + { + // This shouldn't occur for any sensible reasons + LOG(ERROR, LOG_CATEGORY, "Failed to stat DAE file '%s'", filename.c_str()); + return CModelDefPtr(); + } + + // Build a struct of all the data we want to hash. + // (Use ints and not time_t/off_t because we don't care about overflow + // but do care about the fields not being 64-bit aligned) + struct { int version; int mtime; int size; } hashSource + = { COLLADA_CONVERTER_VERSION, fileStat.st_mtime & ~1, fileStat.st_size }; + cassert(sizeof(hashSource) == sizeof(int) * 3); // no padding, because that would be bad + // Calculate the hash, convert to hex + u32 hash = fnv_hash(static_cast(&hashSource), sizeof(hashSource)); + char hashString[9]; + sprintf(hashString, "%08x", hash); + + char realDaePath[PATH_MAX]; + vfs_realpath(dae, realDaePath); + // realDaePath is "mods/whatever/art/meshes/whatever.dae" + + CStr cachedPmdVfsPath = "cache/"; + cachedPmdVfsPath += realDaePath; + // Remove the .dae extension (which will certainly be there) + cachedPmdVfsPath = cachedPmdVfsPath.GetSubstring(0, cachedPmdVfsPath.Length()-4); + // Add a _hash.pmd extension + cachedPmdVfsPath += "_"; + cachedPmdVfsPath += hashString; + cachedPmdVfsPath += ".pmd"; + + // If it's cached, load and return that copy + if (vfs_exists(cachedPmdVfsPath)) + { + CModelDefPtr model (CModelDef::Load(cachedPmdVfsPath, name)); + m->MeshMap[name] = model; + return model; + } + + // Not in the cache, so create it + + return m->Convert(dae, cachedPmdVfsPath, name); } catch (PSERROR_File&) { - LOG(ERROR, "mesh", "Could not load mesh '%s'!", filename); + LOG(ERROR, LOG_CATEGORY, "Could not load mesh '%s'", filename.c_str()); return CModelDefPtr(); } } diff --git a/source/graphics/MeshManager.h b/source/graphics/MeshManager.h index 12c7ec05c1..2e941f62a4 100644 --- a/source/graphics/MeshManager.h +++ b/source/graphics/MeshManager.h @@ -2,26 +2,28 @@ #define __H_MESHMANAGER_H__ #include "ps/Singleton.h" -#include "ps/CStr.h" #include -#include - -#define g_MeshManager CMeshManager::GetSingleton() class CModelDef; typedef boost::shared_ptr CModelDefPtr; -typedef STL_HASH_MAP, CStr_hash_compare> mesh_map; + +class CStr8; + +#define g_MeshManager CMeshManager::GetSingleton() + +class CMeshManagerImpl; class CMeshManager : public Singleton { public: - CMeshManager(); - ~CMeshManager(); + CMeshManager(); + ~CMeshManager(); + + CModelDefPtr GetMesh(const CStr8& filename); - CModelDefPtr GetMesh(const char *filename); private: - mesh_map m_MeshMap; + CMeshManagerImpl* m; }; #endif diff --git a/source/graphics/ModelDef.cpp b/source/graphics/ModelDef.cpp index edaca38cd5..abf8adecab 100644 --- a/source/graphics/ModelDef.cpp +++ b/source/graphics/ModelDef.cpp @@ -77,7 +77,6 @@ CVector3D CModelDef::SkinNormal(const SModelVertex& vtx, return result; } -/////////////////////////////////////////////////////////////////////////////// // CModelDef Constructor CModelDef::CModelDef() : m_NumVertices(0), m_pVertices(0), m_NumFaces(0), m_pFaces(0), m_NumBones(0), m_Bones(0), @@ -85,7 +84,6 @@ CModelDef::CModelDef() { } -/////////////////////////////////////////////////////////////////////////////// // CModelDef Destructor CModelDef::~CModelDef() { @@ -97,7 +95,6 @@ CModelDef::~CModelDef() delete[] m_PropPoints; } -/////////////////////////////////////////////////////////////////////////////// // FindPropPoint: find and return pointer to prop point matching given name; // return null if no match (case insensitive search) SPropPoint* CModelDef::FindPropPoint(const char* name) const @@ -109,9 +106,8 @@ SPropPoint* CModelDef::FindPropPoint(const char* name) const return 0; } -/////////////////////////////////////////////////////////////////////////////// // Load: read and return a new CModelDef initialised with data from given file -CModelDef* CModelDef::Load(const char* filename) +CModelDef* CModelDef::Load(const char* filename, const char* name) { CFileUnpacker unpacker; @@ -123,8 +119,8 @@ CModelDef* CModelDef::Load(const char* filename) throw PSERROR_File_InvalidVersion(); } - std::auto_ptr mdef (new CModelDef); - mdef->m_Name = filename; + std::auto_ptr mdef (new CModelDef()); + mdef->m_Name = name; // now unpack everything unpacker.UnpackRaw(&mdef->m_NumVertices,sizeof(mdef->m_NumVertices)); @@ -195,7 +191,6 @@ CModelDef* CModelDef::Load(const char* filename) return mdef.release(); } -/////////////////////////////////////////////////////////////////////////////// // Save: write the given CModelDef to the given file void CModelDef::Save(const char* filename,const CModelDef* mdef) { @@ -227,7 +222,6 @@ void CModelDef::Save(const char* filename,const CModelDef* mdef) packer.Write(filename); } -/////////////////////////////////////////////////////////////////////////////// // SetRenderData: Set the render data object for the given key, void CModelDef::SetRenderData(const void* key, CModelDefRPrivate* data) { @@ -235,7 +229,6 @@ void CModelDef::SetRenderData(const void* key, CModelDefRPrivate* data) m_RenderData[key] = data; } -/////////////////////////////////////////////////////////////////////////////// // GetRenderData: Get the render data object for the given key, // or 0 if no such object exists. // Reference count of the render data object is automatically increased. diff --git a/source/graphics/ModelDef.h b/source/graphics/ModelDef.h index 9c7c16b713..cabb0e1108 100644 --- a/source/graphics/ModelDef.h +++ b/source/graphics/ModelDef.h @@ -14,8 +14,6 @@ #include "maths/Quaternion.h" #include -class CMeshManager; -class CModelDef; class CBoneState; /////////////////////////////////////////////////////////////////////////////// @@ -85,7 +83,6 @@ public: // information of a model class CModelDef { - friend class CMeshManager; public: // current file version given to saved animations enum { FILE_VERSION = 3 }; @@ -94,13 +91,21 @@ public: public: - // constructor CModelDef(); - // destructor - virtual ~CModelDef(); + ~CModelDef(); // model I/O functions - static void Save(const char* filename,const CModelDef* mdef); + + static void Save(const char* filename,const CModelDef* mdef); + + /** + * Loads a PMD file. + * @param filename VFS path of .pmd file to load + * @param name arbitrary name to give the model for debugging purposes + * @return the model - always non-NULL + * @throw PSERROR_File if it can't load the model + */ + static CModelDef* Load(const char* filename, const char* name); public: // accessor: get vertex data @@ -183,9 +188,6 @@ private: // by render path typedef std::map RenderDataMap; RenderDataMap m_RenderData; - -protected: - static CModelDef* Load(const char* filename); }; #endif diff --git a/source/graphics/ObjectEntry.cpp b/source/graphics/ObjectEntry.cpp index 7b50367268..62527a7645 100644 --- a/source/graphics/ObjectEntry.cpp +++ b/source/graphics/ObjectEntry.cpp @@ -68,13 +68,11 @@ bool CObjectEntry::BuildVariation(const std::vector >& selection // remember the old model so we can replace any models using it later on CModelDefPtr oldmodeldef = m_Model ? m_Model->GetModelDef() : CModelDefPtr(); - const char* modelfilename = m_ModelName; - // try and create a model - CModelDefPtr modeldef (g_MeshManager.GetMesh(modelfilename)); + CModelDefPtr modeldef (g_MeshManager.GetMesh(m_ModelName)); if (!modeldef) { - LOG(ERROR, LOG_CATEGORY, "CObjectEntry::BuildModel(): Model %s failed to load", modelfilename); + LOG(ERROR, LOG_CATEGORY, "CObjectEntry::BuildModel(): Model %s failed to load", m_ModelName.c_str()); return false; } @@ -126,7 +124,7 @@ bool CObjectEntry::BuildVariation(const std::vector >& selection { // start up idling if (! m_Model->SetAnimation(GetRandomAnimation("idle"))) - LOG(ERROR, LOG_CATEGORY, "Failed to set idle animation in model \"%s\"", modelfilename); + LOG(ERROR, LOG_CATEGORY, "Failed to set idle animation in model \"%s\"", m_ModelName.c_str()); } // build props - TODO, RC - need to fix up bounds here @@ -154,7 +152,7 @@ bool CObjectEntry::BuildVariation(const std::vector >& selection m_AmmunitionModel = oe->m_Model; m_AmmunitionPoint = modeldef->FindPropPoint((const char*)ppn ); if( !m_AmmunitionPoint ) - LOG(ERROR, LOG_CATEGORY, "Failed to find matching prop point called \"%s\" in model \"%s\" on actor \"%s\"", (const char*)ppn, modelfilename, (const char*)prop.m_ModelName); + LOG(ERROR, LOG_CATEGORY, "Failed to find matching prop point called \"%s\" in model \"%s\" on actor \"%s\"", (const char*)ppn, (const char*)m_ModelName, (const char*)prop.m_ModelName); } else { @@ -166,7 +164,7 @@ bool CObjectEntry::BuildVariation(const std::vector >& selection propmodel->SetAnimation(oe->GetRandomAnimation("idle")); } else - LOG(ERROR, LOG_CATEGORY, "Failed to find matching prop point called \"%s\" in model \"%s\" on actor \"%s\"", (const char*)prop.m_PropPointName, modelfilename, (const char*)prop.m_ModelName); + LOG(ERROR, LOG_CATEGORY, "Failed to find matching prop point called \"%s\" in model \"%s\" on actor \"%s\"", (const char*)prop.m_PropPointName, (const char*)m_ModelName, (const char*)prop.m_ModelName); } } diff --git a/source/graphics/tests/test_MeshManager.h b/source/graphics/tests/test_MeshManager.h new file mode 100644 index 0000000000..6d3cacb8e3 --- /dev/null +++ b/source/graphics/tests/test_MeshManager.h @@ -0,0 +1,177 @@ +#include "lib/self_test.h" + +#include "lib/res/file/vfs.h" +#include "lib/res/file/vfs_optimizer.h" +#include "lib/res/file/path.h" +#include "lib/res/file/trace.h" +#include "lib/res/h_mgr.h" + +#include "graphics/MeshManager.h" +#include "graphics/ModelDef.h" + +#define MOD_PATH "mods/_test.mesh" +#define CACHE_PATH "_testcache" + +const char* srcDAE = "tests/collada/sphere.dae"; +const char* srcPMD = "tests/collada/sphere.pmd"; +const char* testDAE = "art/meshes/skeletal/test.dae"; +const char* testPMD = "art/meshes/skeletal/test.pmd"; +const char* testBase = "art/meshes/skeletal/test"; + +class TestMeshManager : public CxxTest::TestSuite +{ + void initVfs() + { + // Initialise VFS: + + TS_ASSERT_OK(file_init()); + TS_ASSERT_OK(file_set_root_dir(0, "../data")); + + // Set up a mod directory to work in: + + // Make sure the required directories doesn't exist when we start, + // in case the previous test aborted and left them full of junk + if (file_exists(MOD_PATH)) + TS_ASSERT_OK(dir_delete(MOD_PATH)); + + if (file_exists(CACHE_PATH)) + TS_ASSERT_OK(dir_delete(CACHE_PATH)); + + TS_ASSERT_OK(dir_create(MOD_PATH, S_IRWXU|S_IRWXG|S_IRWXO)); + TS_ASSERT_OK(dir_create(CACHE_PATH, S_IRWXU|S_IRWXG|S_IRWXO)); + + vfs_init(); + + // Mount the mod on / + TS_ASSERT_OK(vfs_mount("", MOD_PATH, VFS_MOUNT_RECURSIVE|VFS_MOUNT_ARCHIVES|VFS_MOUNT_ARCHIVABLE)); + + // Mount _testcache onto virtual /cache - don't use the normal cache + // directory because that's full of loads of cached files from the + // proper game and takes a long time to load. + TS_ASSERT_OK(vfs_mount("cache/", CACHE_PATH, VFS_MOUNT_RECURSIVE|VFS_MOUNT_ARCHIVES|VFS_MOUNT_ARCHIVABLE)); + + TS_ASSERT_OK(vfs_set_write_target(MOD_PATH)); + } + + void deinitVfs() + { + // (TODO: It'd be nice if this kind of code didn't have to be + // duplicated in each test suite that's using VFS things) + + vfs_shutdown(); + h_mgr_shutdown(); + TS_ASSERT_OK(file_shutdown()); + + TS_ASSERT_OK(dir_delete(MOD_PATH)); + if (file_exists(CACHE_PATH)) + TS_ASSERT_OK(dir_delete(CACHE_PATH)); + + path_reset_root_dir(); + } + + void copyFile(const char* src, const char* dst) + { + // Copy a file into the mod directory, so we can work on it: + + File f; + TS_ASSERT_OK(file_open(src, 0, &f)); + FileIOBuf buf = FILE_BUF_ALLOC; + ssize_t read = file_io(&f, 0, f.size, &buf); + TS_ASSERT_EQUALS(read, f.size); + + vfs_store(dst, buf, read, FILE_NO_AIO); + + file_buf_free(buf); + file_close(&f); + } + + void buildArchive() + { + // Create a junk trace file first, because vfs_opt_auto_build requires one + std::string trace = "000.000000: L \"-\" 0 0000\n"; + vfs_store("trace.txt", trace.c_str(), trace.size(), FILE_NO_AIO); + + // then make the archive + TS_ASSERT_OK(vfs_opt_rebuild_main_archive(MOD_PATH"/trace.txt", MOD_PATH"/test%02d.zip")); + } + + CMeshManager* meshManager; + +public: + + void setUp() + { + initVfs(); + meshManager = new CMeshManager(); + } + + void tearDown() + { + delete meshManager; + deinitVfs(); + } + + void IRRELEVANT_test_archived() + { + copyFile(srcDAE, testDAE); + + buildArchive(); + + // Have to specify FILE_WRITE_TO_TARGET in order to overwrite existent + // files when they might have been archived + vfs_store(testDAE, "Test", 4, FILE_NO_AIO | FILE_WRITE_TO_TARGET); + + // We can't overwrite cache files because FILE_WRITE_TO_TARGET won't + // write into cache/ - it might be nice to fix that. For now we just + // use unique filenames. + } + + void test_load_pmd_with_extension() + { + copyFile(srcPMD, testPMD); + + CModelDefPtr modeldef = meshManager->GetMesh(testPMD); + TS_ASSERT(modeldef); + if (modeldef) TS_ASSERT_STR_EQUALS(modeldef->GetName(), testBase); + } + + void test_load_pmd_without_extension() + { + copyFile(srcPMD, testPMD); + + CModelDefPtr modeldef = meshManager->GetMesh(testBase); + TS_ASSERT(modeldef); + if (modeldef) TS_ASSERT_STR_EQUALS(modeldef->GetName(), testBase); + } + + void test_caching() + { + copyFile(srcPMD, testPMD); + + CModelDefPtr modeldef1 = meshManager->GetMesh(testPMD); + CModelDefPtr modeldef2 = meshManager->GetMesh(testPMD); + TS_ASSERT(modeldef1 && modeldef2); + TS_ASSERT_EQUALS(modeldef1.get(), modeldef2.get()); + } + + void test_load_dae() + { + copyFile(srcDAE, testDAE); + + CModelDefPtr modeldef = meshManager->GetMesh(testDAE); + TS_ASSERT(modeldef); + if (modeldef) TS_ASSERT_STR_EQUALS(modeldef->GetName(), testBase); + } + + void test_load_nonexistent_pmd() + { + CModelDefPtr modeldef = meshManager->GetMesh(testPMD); + TS_ASSERT(! modeldef); + } + + void test_load_nonexistent_dae() + { + CModelDefPtr modeldef = meshManager->GetMesh(testDAE); + TS_ASSERT(! modeldef); + } +}; diff --git a/source/lib/adts.h b/source/lib/adts.h index e72f9c9df0..6a0f69877f 100644 --- a/source/lib/adts.h +++ b/source/lib/adts.h @@ -117,27 +117,25 @@ public: DynHashTbl() { tbl = 0; - num_entries = 0; - max_entries = tr.initial_entries/2; // will be doubled in expand_tbl - debug_assert(is_pow2(max_entries)); - expand_tbl(); + clear(); } ~DynHashTbl() { - clear(); + free(tbl); } void clear() { - // note: users might call clear() right before the dtor runs, - // so safely handling calling this twice. + // must remain usable after calling clear, so shrink the table to + // its initial size but don't deallocate it completely SAFE_FREE(tbl); num_entries = 0; // rationale: must not set to 0 because expand_tbl only doubles the size. - // don't keep the previous size because it may have become huge and - // there is no provision for shrinking. + // don't keep the previous size when clearing because it may have become + // huge and there is no provision for shrinking. max_entries = tr.initial_entries/2; // will be doubled in expand_tbl + expand_tbl(); } void insert(const Key key, const T t) diff --git a/source/lib/res/file/path.cpp b/source/lib/res/file/path.cpp index 21ef4f9bca..277b20adcc 100644 --- a/source/lib/res/file/path.cpp +++ b/source/lib/res/file/path.cpp @@ -222,6 +222,9 @@ void path_reset_root_dir() // arena, which is also more memory-efficient than the heap (no headers). static Pool atom_pool; +typedef DynHashTbl AtomMap; +static AtomMap atom_map; + bool path_is_atom_fn(const char* fn) { return pool_contains(&atom_pool, (void*)fn); @@ -247,8 +250,6 @@ const char* file_make_unique_fn_copy(const char* P_fn) // rationale: the entire storage could be done via container, // rather than simply using it as a lookup mapping. // however, DynHashTbl together with Pool (see above) is more efficient. - typedef DynHashTbl AtomMap; - static AtomMap atom_map; unique_fn = atom_map.find(P_fn); if(unique_fn) return unique_fn; @@ -269,15 +270,25 @@ const char* file_make_unique_fn_copy(const char* P_fn) } +static ModuleInitState init_state; + void path_init() { - ONCE_NOT(return;); + moduleInit_assertCanInit(init_state); + pool_create(&atom_pool, 8*MiB, POOL_VARIABLE_ALLOCS); + + moduleInit_markInitialized(&init_state); } void path_shutdown() { + moduleInit_assertCanShutdown(init_state); + + atom_map.clear(); (void)pool_destroy(&atom_pool); + + moduleInit_markShutdown(&init_state); } diff --git a/source/lib/res/file/tests/test_archive_builder.h b/source/lib/res/file/tests/test_archive_builder.h index 17f9d87854..651f295b30 100644 --- a/source/lib/res/file/tests/test_archive_builder.h +++ b/source/lib/res/file/tests/test_archive_builder.h @@ -6,6 +6,8 @@ #include "lib/res/file/vfs.h" #include "lib/res/file/archive.h" #include "lib/res/file/archive_builder.h" +#include "lib/res/h_mgr.h" +#include "lib/res/mem.h" class TestArchiveBuilder : public CxxTest::TestSuite { @@ -85,7 +87,6 @@ public: void setUp() { (void)file_init(); - path_init(); // required for file_make_unique_fn_copy (void)file_set_root_dir(0, "."); vfs_init(); } @@ -93,12 +94,16 @@ public: void tearDown() { vfs_shutdown(); + file_shutdown(); + h_mgr_shutdown(); path_reset_root_dir(); } void test_create_archive_with_random_files() { - TS_ASSERT_OK(dir_create("archivetest", S_IRWXU|S_IRWXG|S_IRWXO)); + if(!file_exists("archivetest")) // don't get stuck if this test fails and never deletes the directory it created + TS_ASSERT_OK(dir_create("archivetest", S_IRWXU|S_IRWXG|S_IRWXO)); + TS_ASSERT_OK(vfs_mount("", "archivetest")); generate_random_files(); @@ -122,6 +127,7 @@ public: TS_ASSERT_SAME_DATA(buf, files[i].data, files[i].size); TS_ASSERT_OK(file_buf_free(buf)); + TS_ASSERT_OK(afile_close(&f)); SAFE_ARRAY_DELETE(files[i].data); } TS_ASSERT_OK(archive_close(ha)); diff --git a/source/lib/res/file/tests/test_compression.h b/source/lib/res/file/tests/test_compression.h index 2e4886f68c..5236df4c24 100644 --- a/source/lib/res/file/tests/test_compression.h +++ b/source/lib/res/file/tests/test_compression.h @@ -44,6 +44,9 @@ public: TS_ASSERT_EQUALS(ucsize_final, data_size); // correct amount of output } + comp_free(c); + comp_free(d); + // verify data survived intact TS_ASSERT_SAME_DATA(data, ucdata, data_size); } diff --git a/source/lib/res/file/tests/test_path.h b/source/lib/res/file/tests/test_path.h index e6e8607aa9..df2ff82dc3 100644 --- a/source/lib/res/file/tests/test_path.h +++ b/source/lib/res/file/tests/test_path.h @@ -63,5 +63,7 @@ public: break; } TS_ASSERT(tries_left != 0); + + path_shutdown(); } }; diff --git a/source/lib/res/file/trace.cpp b/source/lib/res/file/trace.cpp index 940c4ba50d..7b70a56763 100644 --- a/source/lib/res/file/trace.cpp +++ b/source/lib/res/file/trace.cpp @@ -46,7 +46,7 @@ static inline void trace_init() void trace_shutdown() { - if(CAS(&trace_initialized, 1, 2)) + if(CAS(&trace_initialized, 1, 0)) (void)pool_destroy(&trace_pool); } diff --git a/source/lib/res/file/vfs_tree.cpp b/source/lib/res/file/vfs_tree.cpp index eee499d0cf..da077fc097 100644 --- a/source/lib/res/file/vfs_tree.cpp +++ b/source/lib/res/file/vfs_tree.cpp @@ -302,7 +302,10 @@ RealDir rd; // HACK; removeme { TNode* node = *it; if(node->type == NT_DIR) + { ((TDir*)node)->clearR(); + ((TDir*)node)->~TDir(); + } } // wipe out this directory diff --git a/source/lib/res/graphics/unifont.cpp b/source/lib/res/graphics/unifont.cpp index fb1db304e7..a11d526e24 100644 --- a/source/lib/res/graphics/unifont.cpp +++ b/source/lib/res/graphics/unifont.cpp @@ -67,8 +67,8 @@ static LibError UniFont_reload(UniFont* f, const char* fn, Handle UNUSED(h)) if(f->ht > 0) return INFO::OK; - f->glyphs_id = new glyphmap_id; - f->glyphs_size = new glyphmap_size; + f->glyphs_id = new glyphmap_id(); + f->glyphs_size = new glyphmap_size(); // fn is the base filename, e.g. "console" // The font definition file is "fonts/"+fn+".fnt" and the texture is "fonts/"+fn+".tga" @@ -186,7 +186,10 @@ static LibError UniFont_validate(const UniFont* f) static LibError UniFont_to_string(const UniFont* f, char* buf) { - snprintf(buf, H_STRING_LEN, "Font %s", h_filename(f->ht)); + if (f->ht) // not true if this is called after dtor (which it is) + snprintf(buf, H_STRING_LEN, "Font %s", h_filename(f->ht)); + else + snprintf(buf, H_STRING_LEN, "Font"); return INFO::OK; } diff --git a/source/lib/res/h_mgr.cpp b/source/lib/res/h_mgr.cpp index 2a091e60cf..a0cd020f3e 100644 --- a/source/lib/res/h_mgr.cpp +++ b/source/lib/res/h_mgr.cpp @@ -414,15 +414,22 @@ static Pool fn_pool; // choose this to balance internal fragmentation and accessing the heap. static const size_t FN_POOL_EL_SIZE = 64; +static ModuleInitState init_state; + static void fn_init() { + moduleInit_assertCanInit(init_state); + // (if this fails, so will subsequent fn_stores - no need to complain here) (void)pool_create(&fn_pool, MAX_EXTANT_HANDLES*FN_POOL_EL_SIZE, FN_POOL_EL_SIZE); + + moduleInit_markInitialized(&init_state); } static void fn_store(HDATA* hd, const char* fn) { - ONCE(fn_init()); + if (init_state != MODULE_INITIALIZED) + fn_init(); const size_t size = strlen(fn)+1; @@ -468,7 +475,15 @@ static void fn_free(HDATA* hd) static void fn_shutdown() { - pool_destroy(&fn_pool); + // this can be validly called even if not initialized yet, + // since fn_store may have never been called + + if (init_state == MODULE_INITIALIZED) + { + pool_destroy(&fn_pool); + } + + moduleInit_markShutdown(&init_state); } diff --git a/source/ps/Errors.cpp b/source/ps/Errors.cpp index ea0a9280d7..63c8637034 100644 --- a/source/ps/Errors.cpp +++ b/source/ps/Errors.cpp @@ -5,6 +5,7 @@ #include "Errors.h" class PSERROR_CVFSFile : public PSERROR {}; +class PSERROR_DllLoader : public PSERROR {}; class PSERROR_Error : public PSERROR {}; class PSERROR_File : public PSERROR {}; class PSERROR_GUI : public PSERROR {}; @@ -23,6 +24,8 @@ class PSERROR_Scripting_LoadFile : public PSERROR_Scripting {}; class PSERROR_CVFSFile_AlreadyLoaded : public PSERROR_CVFSFile { public: PSRETURN getCode() const; }; class PSERROR_CVFSFile_InvalidBufferAccess : public PSERROR_CVFSFile { public: PSRETURN getCode() const; }; class PSERROR_CVFSFile_LoadFailed : public PSERROR_CVFSFile { public: PSRETURN getCode() const; }; +class PSERROR_DllLoader_DllNotLoaded : public PSERROR_DllLoader { public: PSRETURN getCode() const; }; +class PSERROR_DllLoader_SymbolNotFound : public PSERROR_DllLoader { public: PSRETURN getCode() const; }; class PSERROR_Error_InvalidError : public PSERROR_Error { public: PSRETURN getCode() const; }; class PSERROR_File_InvalidType : public PSERROR_File { public: PSRETURN getCode() const; }; class PSERROR_File_InvalidVersion : public PSERROR_File { public: PSRETURN getCode() const; }; @@ -54,62 +57,66 @@ class PSERROR_Xeromyces_XMLParseError : public PSERROR_Xeromyces { public: PSRET extern const PSRETURN PSRETURN_CVFSFile_AlreadyLoaded = 0x01000001; extern const PSRETURN PSRETURN_CVFSFile_InvalidBufferAccess = 0x01000002; extern const PSRETURN PSRETURN_CVFSFile_LoadFailed = 0x01000003; -extern const PSRETURN PSRETURN_Error_InvalidError = 0x02000001; -extern const PSRETURN PSRETURN_File_InvalidType = 0x03000001; -extern const PSRETURN PSRETURN_File_InvalidVersion = 0x03000002; -extern const PSRETURN PSRETURN_File_OpenFailed = 0x03000003; -extern const PSRETURN PSRETURN_File_ReadFailed = 0x03000004; -extern const PSRETURN PSRETURN_File_UnexpectedEOF = 0x03000005; -extern const PSRETURN PSRETURN_File_WriteFailed = 0x03000006; -extern const PSRETURN PSRETURN_GUI_JSOpenFailed = 0x04000001; -extern const PSRETURN PSRETURN_Game_World_MapLoadFailed = 0x05040001; -extern const PSRETURN PSRETURN_I18n_Script_SetupFailed = 0x06030001; -extern const PSRETURN PSRETURN_Renderer_VBOFailed = 0x07000001; -extern const PSRETURN PSRETURN_Scripting_DefineType_AlreadyExists = 0x08010001; -extern const PSRETURN PSRETURN_Scripting_DefineType_CreationFailed = 0x08010002; -extern const PSRETURN PSRETURN_Scripting_LoadFile_EvalErrors = 0x08020001; -extern const PSRETURN PSRETURN_Scripting_LoadFile_OpenFailed = 0x08020002; -extern const PSRETURN PSRETURN_Scripting_CallFunctionFailed = 0x08000001; -extern const PSRETURN PSRETURN_Scripting_ConversionFailed = 0x08000002; -extern const PSRETURN PSRETURN_Scripting_CreateObjectFailed = 0x08000003; -extern const PSRETURN PSRETURN_Scripting_DefineConstantFailed = 0x08000004; -extern const PSRETURN PSRETURN_Scripting_RegisterFunctionFailed = 0x08000005; -extern const PSRETURN PSRETURN_Scripting_SetupFailed = 0x08000006; -extern const PSRETURN PSRETURN_Scripting_TypeDoesNotExist = 0x08000007; -extern const PSRETURN PSRETURN_System_RequiredExtensionsMissing = 0x09000001; -extern const PSRETURN PSRETURN_System_SDLInitFailed = 0x09000002; -extern const PSRETURN PSRETURN_System_VmodeFailed = 0x09000003; -extern const PSRETURN PSRETURN_Xeromyces_XMLOpenFailed = 0x0a000001; -extern const PSRETURN PSRETURN_Xeromyces_XMLParseError = 0x0a000002; +extern const PSRETURN PSRETURN_DllLoader_DllNotLoaded = 0x02000001; +extern const PSRETURN PSRETURN_DllLoader_SymbolNotFound = 0x02000002; +extern const PSRETURN PSRETURN_Error_InvalidError = 0x03000001; +extern const PSRETURN PSRETURN_File_InvalidType = 0x04000001; +extern const PSRETURN PSRETURN_File_InvalidVersion = 0x04000002; +extern const PSRETURN PSRETURN_File_OpenFailed = 0x04000003; +extern const PSRETURN PSRETURN_File_ReadFailed = 0x04000004; +extern const PSRETURN PSRETURN_File_UnexpectedEOF = 0x04000005; +extern const PSRETURN PSRETURN_File_WriteFailed = 0x04000006; +extern const PSRETURN PSRETURN_GUI_JSOpenFailed = 0x05000001; +extern const PSRETURN PSRETURN_Game_World_MapLoadFailed = 0x06040001; +extern const PSRETURN PSRETURN_I18n_Script_SetupFailed = 0x07030001; +extern const PSRETURN PSRETURN_Renderer_VBOFailed = 0x08000001; +extern const PSRETURN PSRETURN_Scripting_DefineType_AlreadyExists = 0x09010001; +extern const PSRETURN PSRETURN_Scripting_DefineType_CreationFailed = 0x09010002; +extern const PSRETURN PSRETURN_Scripting_LoadFile_EvalErrors = 0x09020001; +extern const PSRETURN PSRETURN_Scripting_LoadFile_OpenFailed = 0x09020002; +extern const PSRETURN PSRETURN_Scripting_CallFunctionFailed = 0x09000001; +extern const PSRETURN PSRETURN_Scripting_ConversionFailed = 0x09000002; +extern const PSRETURN PSRETURN_Scripting_CreateObjectFailed = 0x09000003; +extern const PSRETURN PSRETURN_Scripting_DefineConstantFailed = 0x09000004; +extern const PSRETURN PSRETURN_Scripting_RegisterFunctionFailed = 0x09000005; +extern const PSRETURN PSRETURN_Scripting_SetupFailed = 0x09000006; +extern const PSRETURN PSRETURN_Scripting_TypeDoesNotExist = 0x09000007; +extern const PSRETURN PSRETURN_System_RequiredExtensionsMissing = 0x0a000001; +extern const PSRETURN PSRETURN_System_SDLInitFailed = 0x0a000002; +extern const PSRETURN PSRETURN_System_VmodeFailed = 0x0a000003; +extern const PSRETURN PSRETURN_Xeromyces_XMLOpenFailed = 0x0b000001; +extern const PSRETURN PSRETURN_Xeromyces_XMLParseError = 0x0b000002; extern const PSRETURN MASK__PSRETURN_CVFSFile = 0xff000000; extern const PSRETURN CODE__PSRETURN_CVFSFile = 0x01000000; +extern const PSRETURN MASK__PSRETURN_DllLoader = 0xff000000; +extern const PSRETURN CODE__PSRETURN_DllLoader = 0x02000000; extern const PSRETURN MASK__PSRETURN_Error = 0xff000000; -extern const PSRETURN CODE__PSRETURN_Error = 0x02000000; +extern const PSRETURN CODE__PSRETURN_Error = 0x03000000; extern const PSRETURN MASK__PSRETURN_File = 0xff000000; -extern const PSRETURN CODE__PSRETURN_File = 0x03000000; +extern const PSRETURN CODE__PSRETURN_File = 0x04000000; extern const PSRETURN MASK__PSRETURN_GUI = 0xff000000; -extern const PSRETURN CODE__PSRETURN_GUI = 0x04000000; +extern const PSRETURN CODE__PSRETURN_GUI = 0x05000000; extern const PSRETURN MASK__PSRETURN_Game = 0xff000000; -extern const PSRETURN CODE__PSRETURN_Game = 0x05000000; +extern const PSRETURN CODE__PSRETURN_Game = 0x06000000; extern const PSRETURN MASK__PSRETURN_I18n = 0xff000000; -extern const PSRETURN CODE__PSRETURN_I18n = 0x06000000; +extern const PSRETURN CODE__PSRETURN_I18n = 0x07000000; extern const PSRETURN MASK__PSRETURN_Renderer = 0xff000000; -extern const PSRETURN CODE__PSRETURN_Renderer = 0x07000000; +extern const PSRETURN CODE__PSRETURN_Renderer = 0x08000000; extern const PSRETURN MASK__PSRETURN_Scripting = 0xff000000; -extern const PSRETURN CODE__PSRETURN_Scripting = 0x08000000; -extern const PSRETURN MASK__PSRETURN_System = 0xff000000; -extern const PSRETURN CODE__PSRETURN_System = 0x09000000; -extern const PSRETURN MASK__PSRETURN_Xeromyces = 0x0a000000; -extern const PSRETURN CODE__PSRETURN_Xeromyces = 0x0a000000; +extern const PSRETURN CODE__PSRETURN_Scripting = 0x09000000; +extern const PSRETURN MASK__PSRETURN_System = 0x0a000000; +extern const PSRETURN CODE__PSRETURN_System = 0x0a000000; +extern const PSRETURN MASK__PSRETURN_Xeromyces = 0x0b000000; +extern const PSRETURN CODE__PSRETURN_Xeromyces = 0x0b000000; extern const PSRETURN MASK__PSRETURN_Game_World = 0xffff0000; -extern const PSRETURN CODE__PSRETURN_Game_World = 0x05040000; +extern const PSRETURN CODE__PSRETURN_Game_World = 0x06040000; extern const PSRETURN MASK__PSRETURN_I18n_Script = 0xffff0000; -extern const PSRETURN CODE__PSRETURN_I18n_Script = 0x06030000; +extern const PSRETURN CODE__PSRETURN_I18n_Script = 0x07030000; extern const PSRETURN MASK__PSRETURN_Scripting_DefineType = 0xffff0000; -extern const PSRETURN CODE__PSRETURN_Scripting_DefineType = 0x08010000; +extern const PSRETURN CODE__PSRETURN_Scripting_DefineType = 0x09010000; extern const PSRETURN MASK__PSRETURN_Scripting_LoadFile = 0xffff0000; -extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile = 0x08020000; +extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile = 0x09020000; extern const PSRETURN MASK__PSRETURN_CVFSFile_AlreadyLoaded = 0xffffffff; extern const PSRETURN CODE__PSRETURN_CVFSFile_AlreadyLoaded = 0x01000001; @@ -117,91 +124,97 @@ extern const PSRETURN MASK__PSRETURN_CVFSFile_InvalidBufferAccess = 0xffffffff; extern const PSRETURN CODE__PSRETURN_CVFSFile_InvalidBufferAccess = 0x01000002; extern const PSRETURN MASK__PSRETURN_CVFSFile_LoadFailed = 0xffffffff; extern const PSRETURN CODE__PSRETURN_CVFSFile_LoadFailed = 0x01000003; +extern const PSRETURN MASK__PSRETURN_DllLoader_DllNotLoaded = 0xffffffff; +extern const PSRETURN CODE__PSRETURN_DllLoader_DllNotLoaded = 0x02000001; +extern const PSRETURN MASK__PSRETURN_DllLoader_SymbolNotFound = 0xffffffff; +extern const PSRETURN CODE__PSRETURN_DllLoader_SymbolNotFound = 0x02000002; extern const PSRETURN MASK__PSRETURN_Error_InvalidError = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Error_InvalidError = 0x02000001; +extern const PSRETURN CODE__PSRETURN_Error_InvalidError = 0x03000001; extern const PSRETURN MASK__PSRETURN_File_InvalidType = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_File_InvalidType = 0x03000001; +extern const PSRETURN CODE__PSRETURN_File_InvalidType = 0x04000001; extern const PSRETURN MASK__PSRETURN_File_InvalidVersion = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_File_InvalidVersion = 0x03000002; +extern const PSRETURN CODE__PSRETURN_File_InvalidVersion = 0x04000002; extern const PSRETURN MASK__PSRETURN_File_OpenFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_File_OpenFailed = 0x03000003; +extern const PSRETURN CODE__PSRETURN_File_OpenFailed = 0x04000003; extern const PSRETURN MASK__PSRETURN_File_ReadFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_File_ReadFailed = 0x03000004; +extern const PSRETURN CODE__PSRETURN_File_ReadFailed = 0x04000004; extern const PSRETURN MASK__PSRETURN_File_UnexpectedEOF = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_File_UnexpectedEOF = 0x03000005; +extern const PSRETURN CODE__PSRETURN_File_UnexpectedEOF = 0x04000005; extern const PSRETURN MASK__PSRETURN_File_WriteFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_File_WriteFailed = 0x03000006; +extern const PSRETURN CODE__PSRETURN_File_WriteFailed = 0x04000006; extern const PSRETURN MASK__PSRETURN_GUI_JSOpenFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_GUI_JSOpenFailed = 0x04000001; +extern const PSRETURN CODE__PSRETURN_GUI_JSOpenFailed = 0x05000001; extern const PSRETURN MASK__PSRETURN_Game_World_MapLoadFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Game_World_MapLoadFailed = 0x05040001; +extern const PSRETURN CODE__PSRETURN_Game_World_MapLoadFailed = 0x06040001; extern const PSRETURN MASK__PSRETURN_I18n_Script_SetupFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_I18n_Script_SetupFailed = 0x06030001; +extern const PSRETURN CODE__PSRETURN_I18n_Script_SetupFailed = 0x07030001; extern const PSRETURN MASK__PSRETURN_Renderer_VBOFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Renderer_VBOFailed = 0x07000001; +extern const PSRETURN CODE__PSRETURN_Renderer_VBOFailed = 0x08000001; extern const PSRETURN MASK__PSRETURN_Scripting_DefineType_AlreadyExists = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_DefineType_AlreadyExists = 0x08010001; +extern const PSRETURN CODE__PSRETURN_Scripting_DefineType_AlreadyExists = 0x09010001; extern const PSRETURN MASK__PSRETURN_Scripting_DefineType_CreationFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_DefineType_CreationFailed = 0x08010002; +extern const PSRETURN CODE__PSRETURN_Scripting_DefineType_CreationFailed = 0x09010002; extern const PSRETURN MASK__PSRETURN_Scripting_LoadFile_EvalErrors = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile_EvalErrors = 0x08020001; +extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile_EvalErrors = 0x09020001; extern const PSRETURN MASK__PSRETURN_Scripting_LoadFile_OpenFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile_OpenFailed = 0x08020002; +extern const PSRETURN CODE__PSRETURN_Scripting_LoadFile_OpenFailed = 0x09020002; extern const PSRETURN MASK__PSRETURN_Scripting_CallFunctionFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_CallFunctionFailed = 0x08000001; +extern const PSRETURN CODE__PSRETURN_Scripting_CallFunctionFailed = 0x09000001; extern const PSRETURN MASK__PSRETURN_Scripting_ConversionFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_ConversionFailed = 0x08000002; +extern const PSRETURN CODE__PSRETURN_Scripting_ConversionFailed = 0x09000002; extern const PSRETURN MASK__PSRETURN_Scripting_CreateObjectFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_CreateObjectFailed = 0x08000003; +extern const PSRETURN CODE__PSRETURN_Scripting_CreateObjectFailed = 0x09000003; extern const PSRETURN MASK__PSRETURN_Scripting_DefineConstantFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_DefineConstantFailed = 0x08000004; +extern const PSRETURN CODE__PSRETURN_Scripting_DefineConstantFailed = 0x09000004; extern const PSRETURN MASK__PSRETURN_Scripting_RegisterFunctionFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_RegisterFunctionFailed = 0x08000005; +extern const PSRETURN CODE__PSRETURN_Scripting_RegisterFunctionFailed = 0x09000005; extern const PSRETURN MASK__PSRETURN_Scripting_SetupFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_SetupFailed = 0x08000006; +extern const PSRETURN CODE__PSRETURN_Scripting_SetupFailed = 0x09000006; extern const PSRETURN MASK__PSRETURN_Scripting_TypeDoesNotExist = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Scripting_TypeDoesNotExist = 0x08000007; +extern const PSRETURN CODE__PSRETURN_Scripting_TypeDoesNotExist = 0x09000007; extern const PSRETURN MASK__PSRETURN_System_RequiredExtensionsMissing = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_System_RequiredExtensionsMissing = 0x09000001; +extern const PSRETURN CODE__PSRETURN_System_RequiredExtensionsMissing = 0x0a000001; extern const PSRETURN MASK__PSRETURN_System_SDLInitFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_System_SDLInitFailed = 0x09000002; +extern const PSRETURN CODE__PSRETURN_System_SDLInitFailed = 0x0a000002; extern const PSRETURN MASK__PSRETURN_System_VmodeFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_System_VmodeFailed = 0x09000003; +extern const PSRETURN CODE__PSRETURN_System_VmodeFailed = 0x0a000003; extern const PSRETURN MASK__PSRETURN_Xeromyces_XMLOpenFailed = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Xeromyces_XMLOpenFailed = 0x0a000001; +extern const PSRETURN CODE__PSRETURN_Xeromyces_XMLOpenFailed = 0x0b000001; extern const PSRETURN MASK__PSRETURN_Xeromyces_XMLParseError = 0xffffffff; -extern const PSRETURN CODE__PSRETURN_Xeromyces_XMLParseError = 0x0a000002; +extern const PSRETURN CODE__PSRETURN_Xeromyces_XMLParseError = 0x0b000002; PSRETURN PSERROR_CVFSFile_AlreadyLoaded::getCode() const { return 0x01000001; } PSRETURN PSERROR_CVFSFile_InvalidBufferAccess::getCode() const { return 0x01000002; } PSRETURN PSERROR_CVFSFile_LoadFailed::getCode() const { return 0x01000003; } -PSRETURN PSERROR_Error_InvalidError::getCode() const { return 0x02000001; } -PSRETURN PSERROR_File_InvalidType::getCode() const { return 0x03000001; } -PSRETURN PSERROR_File_InvalidVersion::getCode() const { return 0x03000002; } -PSRETURN PSERROR_File_OpenFailed::getCode() const { return 0x03000003; } -PSRETURN PSERROR_File_ReadFailed::getCode() const { return 0x03000004; } -PSRETURN PSERROR_File_UnexpectedEOF::getCode() const { return 0x03000005; } -PSRETURN PSERROR_File_WriteFailed::getCode() const { return 0x03000006; } -PSRETURN PSERROR_GUI_JSOpenFailed::getCode() const { return 0x04000001; } -PSRETURN PSERROR_Game_World_MapLoadFailed::getCode() const { return 0x05040001; } -PSRETURN PSERROR_I18n_Script_SetupFailed::getCode() const { return 0x06030001; } -PSRETURN PSERROR_Renderer_VBOFailed::getCode() const { return 0x07000001; } -PSRETURN PSERROR_Scripting_DefineType_AlreadyExists::getCode() const { return 0x08010001; } -PSRETURN PSERROR_Scripting_DefineType_CreationFailed::getCode() const { return 0x08010002; } -PSRETURN PSERROR_Scripting_LoadFile_EvalErrors::getCode() const { return 0x08020001; } -PSRETURN PSERROR_Scripting_LoadFile_OpenFailed::getCode() const { return 0x08020002; } -PSRETURN PSERROR_Scripting_CallFunctionFailed::getCode() const { return 0x08000001; } -PSRETURN PSERROR_Scripting_ConversionFailed::getCode() const { return 0x08000002; } -PSRETURN PSERROR_Scripting_CreateObjectFailed::getCode() const { return 0x08000003; } -PSRETURN PSERROR_Scripting_DefineConstantFailed::getCode() const { return 0x08000004; } -PSRETURN PSERROR_Scripting_RegisterFunctionFailed::getCode() const { return 0x08000005; } -PSRETURN PSERROR_Scripting_SetupFailed::getCode() const { return 0x08000006; } -PSRETURN PSERROR_Scripting_TypeDoesNotExist::getCode() const { return 0x08000007; } -PSRETURN PSERROR_System_RequiredExtensionsMissing::getCode() const { return 0x09000001; } -PSRETURN PSERROR_System_SDLInitFailed::getCode() const { return 0x09000002; } -PSRETURN PSERROR_System_VmodeFailed::getCode() const { return 0x09000003; } -PSRETURN PSERROR_Xeromyces_XMLOpenFailed::getCode() const { return 0x0a000001; } -PSRETURN PSERROR_Xeromyces_XMLParseError::getCode() const { return 0x0a000002; } +PSRETURN PSERROR_DllLoader_DllNotLoaded::getCode() const { return 0x02000001; } +PSRETURN PSERROR_DllLoader_SymbolNotFound::getCode() const { return 0x02000002; } +PSRETURN PSERROR_Error_InvalidError::getCode() const { return 0x03000001; } +PSRETURN PSERROR_File_InvalidType::getCode() const { return 0x04000001; } +PSRETURN PSERROR_File_InvalidVersion::getCode() const { return 0x04000002; } +PSRETURN PSERROR_File_OpenFailed::getCode() const { return 0x04000003; } +PSRETURN PSERROR_File_ReadFailed::getCode() const { return 0x04000004; } +PSRETURN PSERROR_File_UnexpectedEOF::getCode() const { return 0x04000005; } +PSRETURN PSERROR_File_WriteFailed::getCode() const { return 0x04000006; } +PSRETURN PSERROR_GUI_JSOpenFailed::getCode() const { return 0x05000001; } +PSRETURN PSERROR_Game_World_MapLoadFailed::getCode() const { return 0x06040001; } +PSRETURN PSERROR_I18n_Script_SetupFailed::getCode() const { return 0x07030001; } +PSRETURN PSERROR_Renderer_VBOFailed::getCode() const { return 0x08000001; } +PSRETURN PSERROR_Scripting_DefineType_AlreadyExists::getCode() const { return 0x09010001; } +PSRETURN PSERROR_Scripting_DefineType_CreationFailed::getCode() const { return 0x09010002; } +PSRETURN PSERROR_Scripting_LoadFile_EvalErrors::getCode() const { return 0x09020001; } +PSRETURN PSERROR_Scripting_LoadFile_OpenFailed::getCode() const { return 0x09020002; } +PSRETURN PSERROR_Scripting_CallFunctionFailed::getCode() const { return 0x09000001; } +PSRETURN PSERROR_Scripting_ConversionFailed::getCode() const { return 0x09000002; } +PSRETURN PSERROR_Scripting_CreateObjectFailed::getCode() const { return 0x09000003; } +PSRETURN PSERROR_Scripting_DefineConstantFailed::getCode() const { return 0x09000004; } +PSRETURN PSERROR_Scripting_RegisterFunctionFailed::getCode() const { return 0x09000005; } +PSRETURN PSERROR_Scripting_SetupFailed::getCode() const { return 0x09000006; } +PSRETURN PSERROR_Scripting_TypeDoesNotExist::getCode() const { return 0x09000007; } +PSRETURN PSERROR_System_RequiredExtensionsMissing::getCode() const { return 0x0a000001; } +PSRETURN PSERROR_System_SDLInitFailed::getCode() const { return 0x0a000002; } +PSRETURN PSERROR_System_VmodeFailed::getCode() const { return 0x0a000003; } +PSRETURN PSERROR_Xeromyces_XMLOpenFailed::getCode() const { return 0x0b000001; } +PSRETURN PSERROR_Xeromyces_XMLParseError::getCode() const { return 0x0b000002; } const char* PSERROR::what() const throw () { @@ -220,33 +233,35 @@ const char* GetErrorString(PSRETURN code) case 0x01000001: return "CVFSFile_AlreadyLoaded"; case 0x01000002: return "CVFSFile_InvalidBufferAccess"; case 0x01000003: return "CVFSFile_LoadFailed"; - case 0x02000001: return "Error_InvalidError"; - case 0x03000001: return "File_InvalidType"; - case 0x03000002: return "File_InvalidVersion"; - case 0x03000003: return "File_OpenFailed"; - case 0x03000004: return "File_ReadFailed"; - case 0x03000005: return "File_UnexpectedEOF"; - case 0x03000006: return "File_WriteFailed"; - case 0x04000001: return "GUI_JSOpenFailed"; - case 0x05040001: return "Game_World_MapLoadFailed"; - case 0x06030001: return "I18n_Script_SetupFailed"; - case 0x07000001: return "Renderer_VBOFailed"; - case 0x08010001: return "Scripting_DefineType_AlreadyExists"; - case 0x08010002: return "Scripting_DefineType_CreationFailed"; - case 0x08020001: return "Scripting_LoadFile_EvalErrors"; - case 0x08020002: return "Scripting_LoadFile_OpenFailed"; - case 0x08000001: return "Scripting_CallFunctionFailed"; - case 0x08000002: return "Scripting_ConversionFailed"; - case 0x08000003: return "Scripting_CreateObjectFailed"; - case 0x08000004: return "Scripting_DefineConstantFailed"; - case 0x08000005: return "Scripting_RegisterFunctionFailed"; - case 0x08000006: return "Scripting_SetupFailed"; - case 0x08000007: return "Scripting_TypeDoesNotExist"; - case 0x09000001: return "System_RequiredExtensionsMissing"; - case 0x09000002: return "System_SDLInitFailed"; - case 0x09000003: return "System_VmodeFailed"; - case 0x0a000001: return "Xeromyces_XMLOpenFailed"; - case 0x0a000002: return "Xeromyces_XMLParseError"; + case 0x02000001: return "DllLoader_DllNotLoaded"; + case 0x02000002: return "DllLoader_SymbolNotFound"; + case 0x03000001: return "Error_InvalidError"; + case 0x04000001: return "File_InvalidType"; + case 0x04000002: return "File_InvalidVersion"; + case 0x04000003: return "File_OpenFailed"; + case 0x04000004: return "File_ReadFailed"; + case 0x04000005: return "File_UnexpectedEOF"; + case 0x04000006: return "File_WriteFailed"; + case 0x05000001: return "GUI_JSOpenFailed"; + case 0x06040001: return "Game_World_MapLoadFailed"; + case 0x07030001: return "I18n_Script_SetupFailed"; + case 0x08000001: return "Renderer_VBOFailed"; + case 0x09010001: return "Scripting_DefineType_AlreadyExists"; + case 0x09010002: return "Scripting_DefineType_CreationFailed"; + case 0x09020001: return "Scripting_LoadFile_EvalErrors"; + case 0x09020002: return "Scripting_LoadFile_OpenFailed"; + case 0x09000001: return "Scripting_CallFunctionFailed"; + case 0x09000002: return "Scripting_ConversionFailed"; + case 0x09000003: return "Scripting_CreateObjectFailed"; + case 0x09000004: return "Scripting_DefineConstantFailed"; + case 0x09000005: return "Scripting_RegisterFunctionFailed"; + case 0x09000006: return "Scripting_SetupFailed"; + case 0x09000007: return "Scripting_TypeDoesNotExist"; + case 0x0a000001: return "System_RequiredExtensionsMissing"; + case 0x0a000002: return "System_SDLInitFailed"; + case 0x0a000003: return "System_VmodeFailed"; + case 0x0b000001: return "Xeromyces_XMLOpenFailed"; + case 0x0b000002: return "Xeromyces_XMLParseError"; default: return "Unrecognised error"; } @@ -259,33 +274,35 @@ void ThrowError(PSRETURN code) case 0x01000001: throw PSERROR_CVFSFile_AlreadyLoaded(); break; case 0x01000002: throw PSERROR_CVFSFile_InvalidBufferAccess(); break; case 0x01000003: throw PSERROR_CVFSFile_LoadFailed(); break; - case 0x02000001: throw PSERROR_Error_InvalidError(); break; - case 0x03000001: throw PSERROR_File_InvalidType(); break; - case 0x03000002: throw PSERROR_File_InvalidVersion(); break; - case 0x03000003: throw PSERROR_File_OpenFailed(); break; - case 0x03000004: throw PSERROR_File_ReadFailed(); break; - case 0x03000005: throw PSERROR_File_UnexpectedEOF(); break; - case 0x03000006: throw PSERROR_File_WriteFailed(); break; - case 0x04000001: throw PSERROR_GUI_JSOpenFailed(); break; - case 0x05040001: throw PSERROR_Game_World_MapLoadFailed(); break; - case 0x06030001: throw PSERROR_I18n_Script_SetupFailed(); break; - case 0x07000001: throw PSERROR_Renderer_VBOFailed(); break; - case 0x08010001: throw PSERROR_Scripting_DefineType_AlreadyExists(); break; - case 0x08010002: throw PSERROR_Scripting_DefineType_CreationFailed(); break; - case 0x08020001: throw PSERROR_Scripting_LoadFile_EvalErrors(); break; - case 0x08020002: throw PSERROR_Scripting_LoadFile_OpenFailed(); break; - case 0x08000001: throw PSERROR_Scripting_CallFunctionFailed(); break; - case 0x08000002: throw PSERROR_Scripting_ConversionFailed(); break; - case 0x08000003: throw PSERROR_Scripting_CreateObjectFailed(); break; - case 0x08000004: throw PSERROR_Scripting_DefineConstantFailed(); break; - case 0x08000005: throw PSERROR_Scripting_RegisterFunctionFailed(); break; - case 0x08000006: throw PSERROR_Scripting_SetupFailed(); break; - case 0x08000007: throw PSERROR_Scripting_TypeDoesNotExist(); break; - case 0x09000001: throw PSERROR_System_RequiredExtensionsMissing(); break; - case 0x09000002: throw PSERROR_System_SDLInitFailed(); break; - case 0x09000003: throw PSERROR_System_VmodeFailed(); break; - case 0x0a000001: throw PSERROR_Xeromyces_XMLOpenFailed(); break; - case 0x0a000002: throw PSERROR_Xeromyces_XMLParseError(); break; + case 0x02000001: throw PSERROR_DllLoader_DllNotLoaded(); break; + case 0x02000002: throw PSERROR_DllLoader_SymbolNotFound(); break; + case 0x03000001: throw PSERROR_Error_InvalidError(); break; + case 0x04000001: throw PSERROR_File_InvalidType(); break; + case 0x04000002: throw PSERROR_File_InvalidVersion(); break; + case 0x04000003: throw PSERROR_File_OpenFailed(); break; + case 0x04000004: throw PSERROR_File_ReadFailed(); break; + case 0x04000005: throw PSERROR_File_UnexpectedEOF(); break; + case 0x04000006: throw PSERROR_File_WriteFailed(); break; + case 0x05000001: throw PSERROR_GUI_JSOpenFailed(); break; + case 0x06040001: throw PSERROR_Game_World_MapLoadFailed(); break; + case 0x07030001: throw PSERROR_I18n_Script_SetupFailed(); break; + case 0x08000001: throw PSERROR_Renderer_VBOFailed(); break; + case 0x09010001: throw PSERROR_Scripting_DefineType_AlreadyExists(); break; + case 0x09010002: throw PSERROR_Scripting_DefineType_CreationFailed(); break; + case 0x09020001: throw PSERROR_Scripting_LoadFile_EvalErrors(); break; + case 0x09020002: throw PSERROR_Scripting_LoadFile_OpenFailed(); break; + case 0x09000001: throw PSERROR_Scripting_CallFunctionFailed(); break; + case 0x09000002: throw PSERROR_Scripting_ConversionFailed(); break; + case 0x09000003: throw PSERROR_Scripting_CreateObjectFailed(); break; + case 0x09000004: throw PSERROR_Scripting_DefineConstantFailed(); break; + case 0x09000005: throw PSERROR_Scripting_RegisterFunctionFailed(); break; + case 0x09000006: throw PSERROR_Scripting_SetupFailed(); break; + case 0x09000007: throw PSERROR_Scripting_TypeDoesNotExist(); break; + case 0x0a000001: throw PSERROR_System_RequiredExtensionsMissing(); break; + case 0x0a000002: throw PSERROR_System_SDLInitFailed(); break; + case 0x0a000003: throw PSERROR_System_VmodeFailed(); break; + case 0x0b000001: throw PSERROR_Xeromyces_XMLOpenFailed(); break; + case 0x0b000002: throw PSERROR_Xeromyces_XMLParseError(); break; default: throw PSERROR_Error_InvalidError(); // Hmm... } diff --git a/source/renderer/ModelRenderer.cpp b/source/renderer/ModelRenderer.cpp index da58d596ea..fc7748285c 100644 --- a/source/renderer/ModelRenderer.cpp +++ b/source/renderer/ModelRenderer.cpp @@ -27,6 +27,7 @@ #include "renderer/Renderer.h" #include "renderer/RenderModifiers.h" +#include #define LOG_CATEGORY "graphics"