Пример #1
0
bool Pack::ReplaceResByTable(QString &path)
{
	for (QList<ReplaceResTable>::iterator ite = mresTableList.begin(); ite != mresTableList.end(); ite++)
	{
		QString dirDestAbsolutely;
		QString dirSrc;
		QString dirDest;
		dirSrc = ite->GetFolderSrc();
		dirDest = ite->GetFolderDest();
		if (dirSrc.isEmpty() || dirDest.isEmpty()){
			emit GenerateError(QStringLiteral("error:原资源文件夹或目标文件夹未配置!渠道ID:%1,渠道名:%2\n").arg(mchannelId).arg(mchannelName));
			return false;
		}
		if (dirSrc.replace("\\", "/").startsWith("/")){
			dirDestAbsolutely = path + dirDest;
		}
		else{
			dirDestAbsolutely = path + "/" + dirDest;
		}
		QDir tmp(dirSrc);
		if (!tmp.exists()){
			emit GenerateError(QStringLiteral("error:资源原路径不存在!渠道ID:%1,渠道名:%2\n").arg(mchannelId).arg(mchannelName));
			return false;
		}
		PathManager::CopyDir(dirSrc, dirDestAbsolutely, true);
	}
	return true;
}
Пример #2
0
bool Pack::ReplaceStrByTable(QString &path)
{
	for (QList<ReplaceStrTable>::iterator ite = mstrTableList.begin(); ite != mstrTableList.end(); ite++)
	{
		QString findFile;
		QString file = ite->GetFolder();
		if (file.isEmpty() || ite->GetSrcStr().isEmpty() || ite->GetDestStr().isEmpty()){
			emit GenerateError(QStringLiteral("error:要替换字符串的文件不存在或文件或替换的字符串或目标字符产为空!渠道ID:%1,渠道名:%2\n").arg(mchannelId).arg(mchannelName));
			return false;
		}

		if (file.replace("\\", "/").startsWith("/")){
			findFile = path + file;
		}
		else{
			findFile = path + "/" + file;
		}

		if (!QFile::exists(findFile)){
			emit GenerateError(QStringLiteral("error:要替换字符串的文件不存在!渠道ID:%1,渠道名:%2\n").arg(mchannelId).arg(mchannelName));
			return false;
		}

		if (!PathManager::ReplaceStr(findFile, ite->GetSrcStr(), ite->GetDestStr())){
			emit GenerateError(QStringLiteral("error:替换字符串失败!渠道ID:%1,渠道名:%2\n").arg(mchannelId).arg(mchannelName));
			return false;
		}
	}
	return true;
}
Пример #3
0
void Pack::KillTask()
{
	if (mpprocess != NULL){
		mpprocess->close();
		mpprocess->deleteLater();
		mpprocess = NULL;
	}
	if (!PathManager::RemoveDir(mtmpPath)){
		emit GenerateError(QStringLiteral("error:清除缓存出错!渠道ID:%1,渠道名:%2\n").arg(mchannelId).arg(mchannelName));
	}
}
Пример #4
0
bool Pack::CheckError(QProcess &pprocess)
{
	QTextCodec *gbk = QTextCodec::codecForName("GBK");
	QString error = gbk->toUnicode(pprocess.readAllStandardError());
	if (error.toLower().contains("error:") 
		|| error.toLower().contains("exception:")
		|| error.toLower().contains(" error")
		|| error.toLower().contains(" exception")){
		QString standardOut = gbk->toUnicode(pprocess.readAllStandardOutput());
		emit GenerateError(error.append(standardOut));
		return false;
	}
	return true;
}
Пример #5
0
void Pack::Stop()
{
	if (mpprocess != NULL){
		QProcess killer;
		killer.start("taskkill", QStringList() << "/f" << "/im" << "java.exe");
		if (!killer.waitForStarted())
			return;
		if (!killer.waitForFinished())
			return;
		mpprocess->terminate();
		mpprocess->deleteLater();
		mpprocess = NULL;
	}
	this->terminate();
	this->wait();
	if (!PathManager::RemoveDir(mtmpPath)){
		emit GenerateError(QStringLiteral("error:清除缓存出错!渠道ID:%1,渠道名:%2\n").arg(mchannelId).arg(mchannelName));
	}
	emit FinishSignal(2, mtaskId);
}
Пример #6
0
void Extension::LoadFormat(const Char *File, const Char *Name)
{
	Formats_t::iterator it = FindFormat(Name);
	if(!Assert(it == Formats.end(), String(_T("Format already exists: "))+Name)) return;
	std::basic_ifstream<Char> f (File, std::ios::in|std::ios::binary);
	if(!Assert(f.is_open(), String(_T("Failed to open: "))+File)) return;
	Char id[7] = {0};
	f.read(id, 6);
	if(!Assert(id == ID, String(_T("Not a valid format file: "))+File)) return;
	unsigned FileVer (unsigned(f.get()));
	if(!Assert(FileVer <= FileVersion, String(_T("Newer or unkown version: ")))+File) return;
	String name; for(int c; c = f.get(); name += char(c));
	if(!Assert(f.get() == 0, String(_T("Invalid format file: "))+File)) return;
	try
	{
		Formats.push_back(new Format::ItemGroup(f, name));
	}
	catch(Format::ItemGroup *)
	{
		GenerateError(_T("Unkown format element"));
	}
}
Пример #7
0
bool CNscContext::ReadNextLine (bool fInComment)
{

	//
	// Read the next line
	//
try_again:;
	for (;;)
	{
		m_pStreamTop ->nLine++;
		if (m_pStreamTop ->pStream ->ReadLine (
			m_pStreamTop ->pszLine, Max_Line_Length) == NULL)
		{
			if (fInComment || m_pStreamTop ->pNext == NULL)
				return false;
			RemoveTopStream ();
		}
		else
			break;
	}

	//
	// If we aren't in a comment, then test for preprocessor
	//

	if (!fInComment)
	{

		//
		// Search for the first non-white character
		//

		char *p = m_pStreamTop ->pszLine;
		while (*p != 0 && (*p <= ' ' || *p > 126))
			p++;

		//
		// If this is a pre-processor statement
		//

		if (*p == '#')
		{

			//
			// If we have an include
			//

			if (strncmp (p, "#include", 8) == 0)
			{
				//
				// Force a new line read on this stream on return
				//

				m_pStreamTop ->pszNextTokenPos = NULL;

				//
				// Extract the name
				//

				p += 8;
				while (*p && *p != '"')
					p++;
				p++;
				char *pszNameStart = p;
				while (*p && *p != '"')
					p++;
				int nCount = (int) (p - pszNameStart);
				char *pszTemp = (char *) alloca (nCount + 5);
				memmove (pszTemp, pszNameStart, nCount);
				pszTemp [nCount] = 0;
				//
				// Remove any extension
				//
                                
				p = strchr (pszTemp, '.');
				if (p)
					*p = 0;
				
				// make sure we use lower case
				for (p = pszTemp; *p != '\0'; p++)
					*p = (char)tolower(*p);

				//
				// Search the current list of included files and see
				// if we have already done it
				//

				size_t i;
				for (i = 0; i < m_asFiles .GetCount (); i++)
				{
					if (stricmp (m_asFiles [i] .strName .c_str (), pszTemp) == 0)
						break;
				}

				//
				// If this isn't a duplicate
				//

				if (i >= m_asFiles .GetCount ())
				{

					//
					// Try to load the resource
					//

					bool fAllocated = false;
					UINT32 ulSize = 0;
					unsigned char *pauchData = NULL;

					if (m_pLoader)
					{
						pauchData = m_pLoader ->LoadResource (
							pszTemp, NwnResType_NSS, &ulSize, 
							&fAllocated);
					}
					if (pauchData == NULL)
					{
						GenerateError ("Unable to open the "
							"include file \"%s\"", pszTemp);
						return false;
					}

					//
					// Add stream
					//

					strcat (pszTemp, ".nss");
					CNwnStream *pStream = new CNwnMemoryStream (
						pszTemp, pauchData, ulSize, fAllocated);
					AddStream (pStream);
				}

				//
				// Read the next line
				//
				goto try_again;
			}

			//
			// If we have a define
			//

			if (strncmp (p, "#define", 7) == 0)
			{
				p += 7;

				//
				// Get the first parameter
				//

				while (*p && (*p <= ' ' || *p > 126))
					p++;
				if (*p == 0)
				{
					GenerateError ("#define syntax");
					goto try_again;
				}
				char *pszDefine = p;
				while (*p && (*p > ' ' && *p <= 126))
					p++;
				char *pszDefineEnd = p;

				//
				// Get the second parameter
				//

				while (*p && (*p <= ' ' || *p > 126))
					p++;
				if (*p == 0)
				{
					GenerateError ("#define syntax");
					goto try_again;
				}
				char *pszValue = p;
				while (*p && (*p > ' ' && *p <= 126))
					p++;
				char *pszValueEnd = p;

				//
				// Make sure there isn't anything at the end
				//

				while (*p && (*p <= ' ' || *p > 126))
					p++;
				if (*p != 0)
				{
					GenerateError ("#define syntax");
					goto try_again;
				}

				//
				// Copy the two strings into temp arrays
				//

				int nDefine = (int) (pszDefineEnd - pszDefine);
				char *pszDTmp = (char *) alloca (nDefine + 1);
				memcpy (pszDTmp, pszDefine, nDefine);
				pszDTmp [nDefine] = 0;

				int nValue = (int) (pszValueEnd - pszValue);
				char *pszVTmp = (char *) alloca (nValue + 1);
				memcpy (pszVTmp, pszValue, nValue);
				pszVTmp [nValue] = 0;

				//
				// If this is the number of engine structures
				//

				if (strcmp (pszDTmp, "ENGINE_NUM_STRUCTURES") == 0)
				{
					// Bah, we ignore this
				}
				
				//
				// If this is an engine structure
				//

				else if (strncmp (pszDTmp, "ENGINE_STRUCTURE_", 17) == 0)
				{
					p = &pszDTmp [17];
					int nIndex = atol (p);
					g_astrNscEngineTypes [nIndex] = pszVTmp;
					if (g_sNscReservedWords .Find (pszVTmp) == NULL)
					{
						NscSymbol *pSymbol = g_sNscReservedWords .Add (
							pszVTmp, NscSymType_Token);
						pSymbol ->nToken = ENGINE_TYPE;
						pSymbol ->nEngineObject = nIndex;
					}
				}

				//
				// Otherwise, unknown
				//

				else 
				{
					GenerateError ("#define unknown or invalid definition");
				}
				goto try_again;
			}
		}
	}

	//
	// Set the starting pointer
	//

	m_pStreamTop ->pszNextTokenPos = m_pStreamTop ->pszLine;
	return true;
}
Пример #8
0
int CNscContext::yylex (YYSTYPE* yylval)
{

	//
	// Initialize lvalue
	//

	*yylval = NULL;

	//
	// If we have no stream, return nothing
	//

	if (m_pStreamTop == NULL)
		return EOF;

	//
	// If we need to read a line
	//

try_again:;
	if (m_pStreamTop ->pszNextTokenPos == NULL || 
		*m_pStreamTop ->pszNextTokenPos == 0)
	{
read_another_line:;
		if (!ReadNextLine (false))
			return EOF;
	}

	//
	// Skip the white space
	//

	char c;
	for (;;)
	{
		c = *m_pStreamTop ->pszNextTokenPos;
		if (c == 0)
			goto read_another_line;
		else if (c <= ' ' || c > 126)
			m_pStreamTop ->pszNextTokenPos++;
		else
			break;
	}

	//
	// If we have an identifier
	//

	if (isalpha (c) || c == '_')
	{
		char *pszStart = m_pStreamTop ->pszNextTokenPos;
		m_pStreamTop ->pszNextTokenPos++;
		for (;;)
		{
			c = *m_pStreamTop ->pszNextTokenPos;
			if (isalnum (c) || c == '_')
				m_pStreamTop ->pszNextTokenPos++;
			else
				break;
		}

		//
		// Get the hash value for the ID
		//

		int nCount = (int) (m_pStreamTop ->pszNextTokenPos - pszStart);
		UINT32 ulHash = CNscSymbolTable::GetHash (pszStart, nCount);
		
		//
		// See if it is a reserved word
		//

		NscSymbol *pSymbol = g_sNscReservedWords .Find (pszStart, nCount, ulHash);

		//
		// If so, return that word
		//

		if (pSymbol != NULL)
		{
			assert (pSymbol ->nSymType == NscSymType_Token);
			if (pSymbol ->nToken == ENGINE_TYPE)
			{
				CNscPStackEntry *pEntry = GetPStackEntry (__FILE__, __LINE__);
				pEntry ->SetType ((NscType) (
					NscType_Engine_0 + pSymbol ->nEngineObject));
				*yylval = pEntry;
				return pSymbol ->nToken;
			}
			else
                return pSymbol ->nToken;
		}
		else 
		{
			CNscPStackEntry *pEntry = GetPStackEntry (__FILE__, __LINE__);
			pEntry ->SetIdentifier (pszStart, nCount);
			*yylval = pEntry;
			return IDENTIFIER;
		}
	}

	//
	// If we have a number.
	//
	// The bioware compiler doesn't like a number starting
	// with a '.'
	//

	else if (isdigit (c))
	{

		// 
		// If this is a hex value
		//

		if (c == '0' && 
			(m_pStreamTop ->pszNextTokenPos [1] == 'x' ||
			m_pStreamTop ->pszNextTokenPos [1] == 'X'))
		{

			//
			// Parse the number
			//

			m_pStreamTop ->pszNextTokenPos += 2;
			int nValue = 0;
			for (;;)
			{
				c = *m_pStreamTop ->pszNextTokenPos;
				if (isdigit (c))
				{
					nValue = nValue * 16 + (c - '0');
					m_pStreamTop ->pszNextTokenPos++;
				}
				else if (c >= 'A' && c <= 'F')
				{
					nValue = nValue * 16 + (c - 'A' + 10);
					m_pStreamTop ->pszNextTokenPos++;
				}
				else if (c >= 'a' && c <= 'f')
				{
					nValue = nValue * 16 + (c - 'a' + 10);
					m_pStreamTop ->pszNextTokenPos++;
				}
				else
					break;
			}

			//
			// Return results
			//

			CNscPStackEntry *pEntry = GetPStackEntry (__FILE__, __LINE__);
			pEntry ->SetType (NscType_Integer);
			pEntry ->PushConstantInteger (nValue);
			*yylval = pEntry;
			return INTEGER_CONST; 
		}

		//
		// Otherwise, treat as a normal number
		//

		else
		{

			//
			// Parse the number
			//

			bool fHasDecimal = false;
			char *pszStart = m_pStreamTop ->pszNextTokenPos;
			for (;;)
			{
				c = *m_pStreamTop ->pszNextTokenPos;
				if (isdigit (c))
					m_pStreamTop ->pszNextTokenPos++;
				else if (c == '.' && !fHasDecimal)
				{
					fHasDecimal = true;
					m_pStreamTop ->pszNextTokenPos++;
				}
				else
					break;
			}

			//
			// Test for 'F' extension
			//

			int nCharacter = (int) (m_pStreamTop ->pszNextTokenPos - pszStart);
			if (c == 'f' || c == 'F')
			{
				fHasDecimal = true;
				m_pStreamTop ->pszNextTokenPos++;
			}

			//
			// Convert the value
			//

			char *psz = (char *) alloca (nCharacter + 1);
			memcpy (psz, pszStart, nCharacter);
			psz [nCharacter] = 0;
			CNscPStackEntry *pEntry = GetPStackEntry (__FILE__, __LINE__);
			*yylval = pEntry;
			if (fHasDecimal)
			{
				pEntry ->SetType (NscType_Float);
				pEntry ->PushConstantFloat ((float) atof (psz));
				return FLOAT_CONST;
			}
			else
			{
				pEntry ->SetType (NscType_Integer);
				pEntry ->PushConstantInteger (atol (psz));
				return INTEGER_CONST;
			}
		}
	}

	//
	// Otherwise, we have a symbol (hopefully)
	//

	else
	{
		m_pStreamTop ->pszNextTokenPos++;
		switch (c)
		{
			case '/':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '*')
				{
					m_pStreamTop ->pszNextTokenPos++;
					for (;;)
					{
						if (m_pStreamTop ->pszNextTokenPos [0] == '*' &&
							m_pStreamTop ->pszNextTokenPos [1] == '/')
						{
							m_pStreamTop ->pszNextTokenPos += 2;
							goto try_again;
						}
						else if (m_pStreamTop ->pszNextTokenPos [0] == 0)
						{
							if (!ReadNextLine (true))
							{
								//GenerateError ("End of file reached while processing comment");
								if (!IsPhase2 ())
                                    GenerateWarning ("End of file reached while processing comment");
								return EOF;
							}
						}
						else
							m_pStreamTop ->pszNextTokenPos++;
					}
				}
				else if (c == '/')
				{
					m_pStreamTop ->pszNextTokenPos++;
					goto read_another_line;
				}
				else if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return DIVEQ;
				}
				else 
				{
					return '/';
				}
				break;

			case '{':
			case '}':
			case '[':
			case ']':
			case '(':
			case ')':
			case ';':
			case ':':
			case '?':
			case ',':
			case '~':
			case '.':
				return c;

			case '+':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return ADDEQ;
				}
				else if (c == '+')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return PLUSPLUS;
				}
				else
					return '+';
				break;

			case '-':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return SUBEQ;
				}
				else if (c == '-')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return MINUSMINUS;
				}
				else
					return '-';
				break;

			case '*':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return MULEQ;
				}
				else
					return '*';
				break;

			case '%':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return MODEQ;
				}
				else
					return '%';
				break;

			case '^':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return XOREQ;
				}
				else
					return '^';
				break;

			case '&':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return ANDEQ;
				}
				else if (c == '&')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return ANDAND;
				}
				else
					return '&';
				break;

			case '|':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return OREQ;
				}
				else if (c == '|')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return OROR;
				}
				else
					return '|';
				break;

			case '!':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return NOTEQ;
				}
				else
					return '!';
				break;

			case '=':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return EQ;
				}
				else
					return '=';
				break;

			case '<':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return LTEQ;
				}
				else if (c == '<')
				{
					m_pStreamTop ->pszNextTokenPos++;
					c = *m_pStreamTop ->pszNextTokenPos;
					if (c == '=')
					{
						m_pStreamTop ->pszNextTokenPos++;
						return SLEQ;
					}
					else
						return SL;
				}
				else
					return '<';
				break;

			case '>':
				c = *m_pStreamTop ->pszNextTokenPos;
				if (c == '=')
				{
					m_pStreamTop ->pszNextTokenPos++;
					return GTEQ;
				}
				else if (c == '>')
				{
					m_pStreamTop ->pszNextTokenPos++;
					c = *m_pStreamTop ->pszNextTokenPos;
					if (c == '=')
					{
						m_pStreamTop ->pszNextTokenPos++;
						return SREQ;
					}
					else if (c == '>')
					{
						m_pStreamTop ->pszNextTokenPos++;
						c = *m_pStreamTop ->pszNextTokenPos;
						if (c == '=')
						{
							m_pStreamTop ->pszNextTokenPos++;
							return USREQ;
						}
						else
							return USR;
					}
					else
						return SR;
				}
				else
					return '>';
				break;

			case '"':
				{
					char *pszStart = m_pStreamTop ->pszNextTokenPos;
					char *pszOut = pszStart;
					for (;;)
					{
						c = *m_pStreamTop ->pszNextTokenPos++;
						if (c == '"')
						{
							CNscPStackEntry *pEntry = GetPStackEntry (__FILE__, __LINE__);
							pEntry ->SetType (NscType_String);
							pEntry ->PushConstantString (pszStart, (int) (pszOut - pszStart));
							*yylval = pEntry;
							return STRING_CONST;
						}
						else if (c == '\\')
						{
							c = *m_pStreamTop ->pszNextTokenPos;
							if (c == 'n')
							{
								*pszOut++ = '\n';
								m_pStreamTop ->pszNextTokenPos++;
							}
							else
								;
						}
						else if (c == 0)
						{
							CNscPStackEntry *pEntry = GetPStackEntry (__FILE__, __LINE__);
							pEntry ->SetType (NscType_String);
							pEntry ->PushConstantString (pszStart, (int) (pszOut - pszStart));
							*yylval = pEntry;
							GenerateError ("Unterminated string");
							return STRING_CONST; 
						}
						else
							*pszOut++ = c;
					}
				}
				break;

			default:
				if (!IsPhase2 ())
				{
					GenerateWarning ("Invalid character '%c' (0x%02X) "
						"found in source, ignored", c, c);
				}
				goto try_again;
		}
	}
}
Пример #9
0
void CNscContext::AddStructure (const char *pszIdentifier, 
	unsigned char *pauchStructData, size_t nStructDataSize)
{

	//
	// Make sure we still have room
	//

	if (m_nStructs >= Max_Structs)
	{
		GenerateError ("Too many defined structures, limit of %d",
			m_nStructs);
		return;
	}

	//
	// Add a new symbol
	//

	NscType nType = (NscType) (NscType_Struct_0 + m_nStructs);
	NscSymbol *pSymbol = m_sSymbols .Add (
		pszIdentifier, NscSymType_Structure);
	pSymbol ->nType = nType;
	pSymbol ->ulFlags = 0;
	pSymbol ->nStackOffset = 0;
	size_t nSymbol = m_sSymbols .GetSymbolOffset (pSymbol);
	m_sSymCount ++;
	if (!IsNWScript() && m_fSymPrint) printf("Add struct symbol %s, count now %d\n", pszIdentifier, m_sSymCount);
	//
	// Count the number of elements
	//

	NscSymbolStructExtra sExtra;
	sExtra .nElementCount = 0;
	sExtra .nTotalSize = 0;
	unsigned char *pauchData = pauchStructData;
	unsigned char *pauchEnd = &pauchData [nStructDataSize];
	while (pauchData < pauchEnd)
	{
		NscPCodeHeader *p = (NscPCodeHeader *) pauchData;
		sExtra .nElementCount++;
		sExtra .nTotalSize += GetTypeSize (p ->nType);
		pauchData += p ->nOpSize;
	}

	//
	// Add the symbol data
	//

	size_t nExtra = m_sSymbols .AppendData (&sExtra, sizeof (sExtra));
	m_sSymbols .AppendData (pauchStructData, nStructDataSize);

	//
	// Save the data
	//

	m_sSymbols .GetSymbol (nSymbol) ->nExtra = nExtra;

	//
	// Save the symbol offset
	//

	m_anStructSymbol [m_nStructs++] = nSymbol;
	m_anGlobalDefs .Add (nSymbol);
}
Пример #10
0
 void __fastcall TfrmObjAllocMain::btnErrorClick(TObject *Sender)
{
	GenerateError();
}
Пример #11
0
HRESULT
COMError::GenerateGenericMessage()
{
   return GenerateError("An error occured processing the request.");
}
Пример #12
0
CNwnMdlModel *CNmcContext::LoadModel (const char *pszName)
{

	//
	// Search the cache
	//

	if (m_pCache)
	{
        CNwnMdlModel *pModel = m_pCache ->FindModel (pszName);
		if (pModel)
			return pModel;
	}

	//
	// Load the file
	//

	bool fAllocated;
	UINT32 ulSize;
	unsigned char *pauchData = LoadResource (pszName, 
		NwnResType_MDL, &ulSize, &fAllocated);
	if (pauchData == NULL)
		return NULL;

	//
	// If the model is binary
	//

	if (ulSize > 12 &&
		pauchData [0] == 0 && pauchData [1] == 0 &&
		pauchData [2] == 0 && pauchData [3] == 0)
	{

		//
		// If the buffer isn't allocated, then copy
		//

		if (!fAllocated)
		{
			unsigned char *p = (unsigned char *) malloc (ulSize);
			if (p == NULL)
				return NULL;
			memcpy (p, pauchData, ulSize);
			pauchData = p;
			fAllocated = true;
		}

		//
		// Get pointer to all the information we are interested in
		//

		CNwnModel::Header *pHeader = 
			(CNwnModel::Header *) pauchData;
		unsigned char *pauchModelData = &
			pauchData [sizeof (CNwnModel::Header)];
		unsigned char *pauchRawData = &
			pauchData [sizeof (CNwnModel::Header) + 
			pHeader ->ulRawDataOffset];
		CNwnMdlModel *pModel = (CNwnMdlModel *) pauchModelData;

		//
		// Convert the absolute
		//

		pModel ->RelativeToAbsolute (pauchModelData, pauchRawData);
		
		//
		// If we have a cache, add the model
		//

		if (m_pCache)
			m_pCache ->AddModel (pModel, pszName);

		//
		// Return the model
		//

		return pModel;
	}

	//
	// Otherwise, this is ASCII
	//

	else
	{

		//
		// Create the stream
		//

		CNwnMemoryStream *pStream = new CNwnMemoryStream (
			pszName, pauchData, ulSize, fAllocated);

		//
		// Start a new compiler
		//

		CNmcContext sCtx;
		sCtx .AddStream (pStream);
		sCtx .SetCache (GetCache ());
		for (int i = 0; i < (int) m_vpKeyFiles .GetCount (); i++)
			sCtx .AddKeyFile (m_vpKeyFiles [i]);
		sCtx .SetPurgeNullFaces (GetPurgeNullFaces ());

		//
		// Compile
		//

		NmcParseModelFile (&sCtx);
		if (sCtx .GetErrors ())
		{
			GenerateError ("Supermodel failed to compile.");
			if (sCtx .GetCurrentModel ())
				delete sCtx .GetCurrentModel ();
			return NULL;
		}
		else
		{
			if (m_pCache)
				m_pCache ->AddModel (sCtx .GetCurrentModel (), pszName);
			return sCtx .GetCurrentModel ();
		}
	}
}