Initial commit
This commit is contained in:
226
engines/wintermute/utils/crc.cpp
Normal file
226
engines/wintermute/utils/crc.cpp
Normal file
@@ -0,0 +1,226 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
* Filename: crc.c
|
||||
*
|
||||
* Description: Slow and fast implementations of the CRC standards.
|
||||
*
|
||||
* Notes: The parameters for each supported CRC standard are
|
||||
* defined in the header file crc.h. The implementations
|
||||
* here should stand up to further additions to that list.
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2000 by Michael Barr. This software is placed into
|
||||
* the public domain and may be used for any purpose. However, this
|
||||
* notice must not be changed or removed and no warranty is either
|
||||
* expressed or implied by its publication or distribution.
|
||||
**********************************************************************/
|
||||
|
||||
#include "engines/wintermute/utils/crc.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
/*
|
||||
* Derive parameters from the standard-specific parameters in crc.h.
|
||||
*/
|
||||
#define WIDTH (8 * sizeof(crc))
|
||||
#define TOPBIT (1 << (WIDTH - 1))
|
||||
|
||||
#if (REFLECT_DATA == TRUE)
|
||||
#undef REFLECT_DATA
|
||||
#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8))
|
||||
#else
|
||||
#undef REFLECT_DATA
|
||||
#define REFLECT_DATA(X) (X)
|
||||
#endif
|
||||
|
||||
#if (REFLECT_REMAINDER == TRUE)
|
||||
#undef REFLECT_REMAINDER
|
||||
#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH))
|
||||
#else
|
||||
#undef REFLECT_REMAINDER
|
||||
#define REFLECT_REMAINDER(X) (X)
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function: reflect()
|
||||
*
|
||||
* Description: Reorder the bits of a binary sequence, by reflecting
|
||||
* them about the middle position.
|
||||
*
|
||||
* Notes: No checking is done that nBits <= 32.
|
||||
*
|
||||
* Returns: The reflection of the original data.
|
||||
*
|
||||
*********************************************************************/
|
||||
static unsigned long
|
||||
reflect(unsigned long data, unsigned char nBits) {
|
||||
unsigned long reflection = 0x00000000;
|
||||
unsigned char bit;
|
||||
|
||||
/*
|
||||
* Reflect the data about the center bit.
|
||||
*/
|
||||
for (bit = 0; bit < nBits; ++bit) {
|
||||
/*
|
||||
* If the LSB bit is set, set the reflection of it.
|
||||
*/
|
||||
if (data & 0x01) {
|
||||
reflection |= (1 << ((nBits - 1) - bit));
|
||||
}
|
||||
|
||||
data = (data >> 1);
|
||||
}
|
||||
|
||||
return (reflection);
|
||||
|
||||
} /* reflect() */
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function: crcSlow()
|
||||
*
|
||||
* Description: Compute the CRC of a given message.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
* Returns: The CRC of the message.
|
||||
*
|
||||
*********************************************************************/
|
||||
crc crcSlow(unsigned char const message[], int nBytes) {
|
||||
crc remainder = INITIAL_REMAINDER;
|
||||
int byte;
|
||||
unsigned char bit;
|
||||
|
||||
/*
|
||||
* Perform modulo-2 division, a byte at a time.
|
||||
*/
|
||||
for (byte = 0; byte < nBytes; ++byte) {
|
||||
/*
|
||||
* Bring the next byte into the remainder.
|
||||
*/
|
||||
remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8));
|
||||
|
||||
/*
|
||||
* Perform modulo-2 division, a bit at a time.
|
||||
*/
|
||||
for (bit = 8; bit > 0; --bit) {
|
||||
/*
|
||||
* Try to divide the current data bit.
|
||||
*/
|
||||
if (remainder & TOPBIT) {
|
||||
remainder = (remainder << 1) ^ POLYNOMIAL;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The final remainder is the CRC result.
|
||||
*/
|
||||
return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
|
||||
|
||||
} /* crcSlow() */
|
||||
|
||||
crc crcTable[256];
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function: crcInit()
|
||||
*
|
||||
* Description: Populate the partial CRC lookup table.
|
||||
*
|
||||
* Notes: This function must be rerun any time the CRC standard
|
||||
* is changed. If desired, it can be run "offline" and
|
||||
* the table results stored in an embedded system's ROM.
|
||||
*
|
||||
* Returns: None defined.
|
||||
*
|
||||
*********************************************************************/
|
||||
void crcInit() {
|
||||
crc remainder;
|
||||
int dividend;
|
||||
unsigned char bit;
|
||||
|
||||
/*
|
||||
* Compute the remainder of each possible dividend.
|
||||
*/
|
||||
for (dividend = 0; dividend < 256; ++dividend) {
|
||||
/*
|
||||
* Start with the dividend followed by zeros.
|
||||
*/
|
||||
remainder = dividend << (WIDTH - 8);
|
||||
|
||||
/*
|
||||
* Perform modulo-2 division, a bit at a time.
|
||||
*/
|
||||
for (bit = 8; bit > 0; --bit) {
|
||||
/*
|
||||
* Try to divide the current data bit.
|
||||
*/
|
||||
if (remainder & TOPBIT) {
|
||||
remainder = (remainder << 1) ^ POLYNOMIAL;
|
||||
} else {
|
||||
remainder = (remainder << 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store the result into the table.
|
||||
*/
|
||||
crcTable[dividend] = remainder;
|
||||
}
|
||||
|
||||
} /* crcInit() */
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Function: crcFast()
|
||||
*
|
||||
* Description: Compute the CRC of a given message.
|
||||
*
|
||||
* Notes: crcInit() must be called first.
|
||||
*
|
||||
* Returns: The CRC of the message.
|
||||
*
|
||||
*********************************************************************/
|
||||
crc crcFast(unsigned char const message[], int nBytes) {
|
||||
crc remainder = INITIAL_REMAINDER;
|
||||
unsigned char data;
|
||||
int byte;
|
||||
|
||||
/*
|
||||
* Divide the message by the polynomial, a byte at a time.
|
||||
*/
|
||||
for (byte = 0; byte < nBytes; ++byte) {
|
||||
data = (unsigned char)(REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8)));
|
||||
remainder = crcTable[data] ^ (remainder << 8);
|
||||
}
|
||||
|
||||
/*
|
||||
* The final remainder is the CRC.
|
||||
*/
|
||||
return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
|
||||
|
||||
} /* crcFast() */
|
||||
|
||||
|
||||
|
||||
crc crc_initialize() {
|
||||
crcInit();
|
||||
return INITIAL_REMAINDER;
|
||||
}
|
||||
|
||||
crc crc_process_byte(unsigned char byteVal, crc remainder) {
|
||||
unsigned char data;
|
||||
data = (unsigned char)(REFLECT_DATA(byteVal) ^ (remainder >> (WIDTH - 8)));
|
||||
remainder = crcTable[data] ^ (remainder << 8);
|
||||
return remainder;
|
||||
}
|
||||
|
||||
crc crc_finalize(crc remainder) {
|
||||
return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE);
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
85
engines/wintermute/utils/crc.h
Normal file
85
engines/wintermute/utils/crc.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
* Filename: crc.h
|
||||
*
|
||||
* Description: A header file describing the various CRC standards.
|
||||
*
|
||||
* Notes:
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2000 by Michael Barr. This software is placed into
|
||||
* the public domain and may be used for any purpose. However, this
|
||||
* notice must not be changed or removed and no warranty is either
|
||||
* expressed or implied by its publication or distribution.
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef _crc_h
|
||||
#define _crc_h
|
||||
|
||||
#include "common/system.h" // For types.
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
#ifndef TRUE
|
||||
#define FALSE 0
|
||||
#define TRUE !FALSE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Select the CRC standard from the list that follows.
|
||||
*/
|
||||
#define CRC32
|
||||
|
||||
#if defined(CRC_CCITT)
|
||||
|
||||
typedef uint16 crc;
|
||||
|
||||
#define CRC_NAME "CRC-CCITT"
|
||||
#define POLYNOMIAL 0x1021
|
||||
#define INITIAL_REMAINDER 0xFFFF
|
||||
#define FINAL_XOR_VALUE 0x0000
|
||||
#define REFLECT_DATA FALSE
|
||||
#define REFLECT_REMAINDER FALSE
|
||||
#define CHECK_VALUE 0x29B1
|
||||
|
||||
#elif defined(CRC16)
|
||||
|
||||
typedef uint16 crc;
|
||||
|
||||
#define CRC_NAME "CRC-16"
|
||||
#define POLYNOMIAL 0x8005
|
||||
#define INITIAL_REMAINDER 0x0000
|
||||
#define FINAL_XOR_VALUE 0x0000
|
||||
#define REFLECT_DATA TRUE
|
||||
#define REFLECT_REMAINDER TRUE
|
||||
#define CHECK_VALUE 0xBB3D
|
||||
|
||||
#elif defined(CRC32)
|
||||
|
||||
typedef uint32 crc;
|
||||
|
||||
#define CRC_NAME "CRC-32"
|
||||
#define POLYNOMIAL 0x04C11DB7
|
||||
#define INITIAL_REMAINDER 0xFFFFFFFF
|
||||
#define FINAL_XOR_VALUE 0xFFFFFFFF
|
||||
#define REFLECT_DATA TRUE
|
||||
#define REFLECT_REMAINDER TRUE
|
||||
#define CHECK_VALUE 0xCBF43926
|
||||
|
||||
#else
|
||||
|
||||
#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd."
|
||||
|
||||
#endif
|
||||
|
||||
void crcInit();
|
||||
crc crcSlow(unsigned char const message[], int nBytes);
|
||||
crc crcFast(unsigned char const message[], int nBytes);
|
||||
|
||||
extern "C" crc crc_initialize();
|
||||
extern "C" crc crc_process_byte(unsigned char byteVal, crc remainder);
|
||||
extern "C" crc crc_finalize(crc remainder);
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif /* _crc_h */
|
||||
120
engines/wintermute/utils/path_util.cpp
Normal file
120
engines/wintermute/utils/path_util.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
#include "engines/wintermute/utils/path_util.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Common::String PathUtil::unifySeparators(const Common::String &path) {
|
||||
Common::String newPath = path;
|
||||
|
||||
for (uint32 i = 0; i < newPath.size(); i++) {
|
||||
if (newPath[i] == '\\') {
|
||||
newPath.setChar('/', i);
|
||||
}
|
||||
}
|
||||
|
||||
return newPath;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Common::String PathUtil::normalizeFileName(const Common::String &path) {
|
||||
Common::String newPath = unifySeparators(path);
|
||||
newPath.toLowercase();
|
||||
return newPath;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Common::String PathUtil::combine(const Common::String &path1, const Common::String &path2) {
|
||||
Common::String newPath1 = unifySeparators(path1);
|
||||
Common::String newPath2 = unifySeparators(path2);
|
||||
|
||||
if (!newPath1.hasSuffix("/") && !newPath2.hasPrefix("/")) {
|
||||
newPath1 += "/";
|
||||
}
|
||||
|
||||
return newPath1 + newPath2;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Common::String PathUtil::getDirectoryName(const Common::String &path) {
|
||||
Common::String newPath = unifySeparators(path);
|
||||
|
||||
size_t pos = newPath.findLastOf('/');
|
||||
|
||||
if (pos == Common::String::npos) {
|
||||
return "";
|
||||
} else {
|
||||
return newPath.substr(0, pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Common::String PathUtil::getFileName(const Common::String &path) {
|
||||
Common::String newPath = unifySeparators(path);
|
||||
|
||||
size_t pos = newPath.findLastOf('/');
|
||||
|
||||
if (pos == Common::String::npos) {
|
||||
return path;
|
||||
} else {
|
||||
return newPath.substr(pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Common::String PathUtil::getFileNameWithoutExtension(const Common::String &path) {
|
||||
Common::String fileName = getFileName(path);
|
||||
|
||||
size_t pos = fileName.findLastOf('.');
|
||||
|
||||
if (pos == Common::String::npos) {
|
||||
return fileName;
|
||||
} else {
|
||||
return fileName.substr(0, pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Common::String PathUtil::getExtension(const Common::String &path) {
|
||||
Common::String fileName = getFileName(path);
|
||||
|
||||
size_t pos = fileName.findLastOf('.');
|
||||
|
||||
if (pos == Common::String::npos) {
|
||||
return "";
|
||||
} else {
|
||||
return fileName.substr(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // End of namespace Wintermute
|
||||
49
engines/wintermute/utils/path_util.h
Normal file
49
engines/wintermute/utils/path_util.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_PATHUTILS_H
|
||||
#define WINTERMUTE_PATHUTILS_H
|
||||
|
||||
#include "engines/wintermute/dctypes.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class PathUtil {
|
||||
public:
|
||||
static Common::String unifySeparators(const Common::String &path);
|
||||
static Common::String normalizeFileName(const Common::String &path);
|
||||
static Common::String combine(const Common::String &path1, const Common::String &path2);
|
||||
static Common::String getDirectoryName(const Common::String &path);
|
||||
static Common::String getFileName(const Common::String &path);
|
||||
static Common::String getFileNameWithoutExtension(const Common::String &path);
|
||||
static Common::String getExtension(const Common::String &path);
|
||||
static bool hasTrailingSlash(const Common::String &path);
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
211
engines/wintermute/utils/string_util.cpp
Normal file
211
engines/wintermute/utils/string_util.cpp
Normal file
@@ -0,0 +1,211 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#include "common/language.h"
|
||||
#include "common/tokenizer.h"
|
||||
#include "common/str-enc.h"
|
||||
#include "engines/wintermute/base/base_engine.h"
|
||||
#include "engines/wintermute/utils/string_util.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool StringUtil::compareNoCase(const AnsiString &str1, const AnsiString &str2) {
|
||||
return (str1.compareToIgnoreCase(str2) == 0);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
/*bool StringUtil::CompareNoCase(const WideString &str1, const WideString &str2) {
|
||||
WideString str1lc = str1;
|
||||
WideString str2lc = str2;
|
||||
|
||||
toLowerCase(str1lc);
|
||||
toLowerCase(str2lc);
|
||||
|
||||
return (str1lc == str2lc);
|
||||
}*/
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
WideString StringUtil::utf8ToWide(const Utf8String &Utf8Str) {
|
||||
return Common::convertToU32String(Utf8Str.c_str(), Common::kUtf8);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Utf8String StringUtil::wideToUtf8(const WideString &WideStr) {
|
||||
return Common::convertFromU32String(WideStr, Common::kUtf8);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Common::CodePage StringUtil::mapCodePage(TTextCharset charset) {
|
||||
switch (charset) {
|
||||
case CHARSET_EASTEUROPE:
|
||||
return Common::kWindows1250;
|
||||
|
||||
case CHARSET_RUSSIAN:
|
||||
return Common::kWindows1251;
|
||||
|
||||
case CHARSET_ANSI:
|
||||
return Common::kWindows1252;
|
||||
|
||||
case CHARSET_GREEK:
|
||||
return Common::kWindows1253;
|
||||
|
||||
case CHARSET_TURKISH:
|
||||
return Common::kWindows1254;
|
||||
|
||||
case CHARSET_HEBREW:
|
||||
return Common::kWindows1255;
|
||||
|
||||
case CHARSET_ARABIC:
|
||||
return Common::kWindows1256;
|
||||
|
||||
case CHARSET_BALTIC:
|
||||
return Common::kWindows1257;
|
||||
|
||||
case CHARSET_DEFAULT:
|
||||
switch (BaseEngine::instance().getLanguage()) {
|
||||
|
||||
//cp1250: Central Europe
|
||||
case Common::CS_CZE:
|
||||
case Common::HR_HRV:
|
||||
case Common::HU_HUN:
|
||||
case Common::PL_POL:
|
||||
case Common::SK_SVK:
|
||||
return Common::kWindows1250;
|
||||
|
||||
//cp1251: Cyrillic
|
||||
case Common::RU_RUS:
|
||||
case Common::UA_UKR:
|
||||
return Common::kWindows1251;
|
||||
|
||||
//cp1252: Western Europe
|
||||
case Common::DA_DNK:
|
||||
case Common::DE_DEU:
|
||||
case Common::EN_ANY:
|
||||
case Common::EN_GRB:
|
||||
case Common::EN_USA:
|
||||
case Common::ES_ESP:
|
||||
case Common::FI_FIN:
|
||||
case Common::FR_FRA:
|
||||
case Common::IT_ITA:
|
||||
case Common::NB_NOR:
|
||||
case Common::NL_NLD:
|
||||
case Common::PT_BRA:
|
||||
case Common::PT_PRT:
|
||||
case Common::SV_SWE:
|
||||
case Common::UNK_LANG:
|
||||
return Common::kWindows1252;
|
||||
|
||||
//cp1253: Greek
|
||||
case Common::EL_GRC:
|
||||
return Common::kWindows1253;
|
||||
|
||||
//cp1254: Turkish
|
||||
case Common::TR_TUR:
|
||||
return Common::kWindows1254;
|
||||
|
||||
//cp1255: Hebrew
|
||||
case Common::HE_ISR:
|
||||
return Common::kWindows1255;
|
||||
|
||||
//cp1256: Arabic
|
||||
case Common::FA_IRN:
|
||||
return Common::kWindows1256;
|
||||
|
||||
//cp1257: Baltic
|
||||
case Common::ET_EST:
|
||||
case Common::LV_LVA:
|
||||
return Common::kWindows1257;
|
||||
|
||||
case Common::JA_JPN:
|
||||
case Common::KO_KOR:
|
||||
case Common::ZH_CHN:
|
||||
case Common::ZH_TWN:
|
||||
default:
|
||||
warning("Unsupported charset: %d", charset);
|
||||
return Common::kWindows1252;
|
||||
}
|
||||
|
||||
case CHARSET_OEM:
|
||||
case CHARSET_CHINESEBIG5:
|
||||
case CHARSET_GB2312:
|
||||
case CHARSET_HANGUL:
|
||||
case CHARSET_MAC:
|
||||
case CHARSET_SHIFTJIS:
|
||||
case CHARSET_SYMBOL:
|
||||
case CHARSET_VIETNAMESE:
|
||||
case CHARSET_JOHAB:
|
||||
case CHARSET_THAI:
|
||||
default:
|
||||
warning("Unsupported charset: %d", charset);
|
||||
return Common::kWindows1252;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
WideString StringUtil::ansiToWide(const AnsiString &str, TTextCharset charset) {
|
||||
return Common::convertToU32String(str.c_str(), mapCodePage(charset));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AnsiString StringUtil::wideToAnsi(const WideString &wstr, TTextCharset charset) {
|
||||
return Common::convertFromU32String(wstr, mapCodePage(charset));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool StringUtil::isUtf8BOM(const byte *buffer, uint32 bufferSize) {
|
||||
if (bufferSize > 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) {
|
||||
return str.find(toFind, startFrom);
|
||||
}
|
||||
|
||||
Common::String StringUtil::encodeSetting(const Common::String &str) {
|
||||
for (uint32 i = 0; i < str.size(); i++) {
|
||||
if ((str[i] < 33) || (str[i] == '=') || (str[i] > 126)) {
|
||||
error("Setting contains illegal characters: %s", str.c_str());
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
Common::String StringUtil::decodeSetting(const Common::String &str) {
|
||||
return str;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AnsiString StringUtil::toString(int val) {
|
||||
return Common::String::format("%d", val);
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
58
engines/wintermute/utils/string_util.h
Normal file
58
engines/wintermute/utils/string_util.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_STRINGUTIL_H
|
||||
#define WINTERMUTE_STRINGUTIL_H
|
||||
|
||||
#include "engines/wintermute/dctypes.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class StringUtil {
|
||||
public:
|
||||
static bool compareNoCase(const AnsiString &str1, const AnsiString &str2);
|
||||
//static bool compareNoCase(const WideString &str1, const WideString &str2);
|
||||
static WideString utf8ToWide(const Utf8String &Utf8Str);
|
||||
static Utf8String wideToUtf8(const WideString &WideStr);
|
||||
static WideString ansiToWide(const AnsiString &str, TTextCharset charset = CHARSET_ANSI);
|
||||
static AnsiString wideToAnsi(const WideString &str, TTextCharset charset = CHARSET_ANSI);
|
||||
|
||||
static bool isUtf8BOM(const byte *buffer, uint32 bufferSize);
|
||||
static int indexOf(const WideString &str, const WideString &toFind, size_t startFrom);
|
||||
|
||||
static Common::String encodeSetting(const Common::String &str);
|
||||
static Common::String decodeSetting(const Common::String &str);
|
||||
|
||||
static AnsiString toString(int val);
|
||||
|
||||
private:
|
||||
static Common::CodePage mapCodePage(TTextCharset charset);
|
||||
};
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
431
engines/wintermute/utils/utils.cpp
Normal file
431
engines/wintermute/utils/utils.cpp
Normal file
@@ -0,0 +1,431 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
/*
|
||||
* qsort code originated from Wine sources.
|
||||
* Copyright 2000 Jon Griffiths
|
||||
* Copyright 2014 Piotr Caban
|
||||
*/
|
||||
|
||||
#include "engines/wintermute/utils/utils.h"
|
||||
#include "engines/wintermute/wintermute.h"
|
||||
#include "engines/wintermute/base/base_engine.h"
|
||||
#include "engines/wintermute/dcgf.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
// Swap - swaps two integers
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
void BaseUtils::swap(int *a, int *b) {
|
||||
int temp = *a;
|
||||
*a = *b;
|
||||
*b = temp;
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float BaseUtils::normalizeAngle(float angle) {
|
||||
while (angle > 360) {
|
||||
angle -= 360;
|
||||
}
|
||||
while (angle < 0) {
|
||||
angle += 360;
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void BaseUtils::createPath(const char *path, bool pathOnly) {
|
||||
/* AnsiString pathStr;
|
||||
|
||||
if (!pathOnly) pathStr = PathUtil::getDirectoryName(path);
|
||||
else pathStr = path;
|
||||
*/
|
||||
// try {
|
||||
warning("BaseUtils::CreatePath - not implemented: %s", path);
|
||||
// boost::filesystem::create_directories(path);
|
||||
// } catch (...) {
|
||||
return;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void BaseUtils::debugMessage(const char *text) {
|
||||
//MessageBox(hWnd, text, "WME", MB_OK|MB_ICONINFORMATION);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
char *BaseUtils::setString(char **string, const char *value) {
|
||||
SAFE_DELETE_ARRAY(*string);
|
||||
size_t stringSize = strlen(value) + 1;
|
||||
*string = new char[stringSize];
|
||||
Common::strcpy_s(*string, stringSize, value);
|
||||
return *string;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
char *BaseUtils::strEntry(int entry, const char *str, const char delim) {
|
||||
int numEntries = 0;
|
||||
|
||||
const char *start = nullptr;
|
||||
int len = 0;
|
||||
|
||||
for (uint32 i = 0; i <= strlen(str); i++) {
|
||||
if (numEntries == entry) {
|
||||
if (!start) {
|
||||
start = str + i;
|
||||
} else {
|
||||
len++;
|
||||
}
|
||||
}
|
||||
if (str[i] == delim || str[i] == '\0') {
|
||||
numEntries++;
|
||||
if (start) {
|
||||
char *ret = new char[len + 1]();
|
||||
Common::strlcpy(ret, start, len + 1);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
int BaseUtils::randomInt(int from, int to) {
|
||||
if (to < from) {
|
||||
int i = to;
|
||||
to = from;
|
||||
from = i;
|
||||
}
|
||||
return BaseEngine::instance().randInt(from, to);
|
||||
// return (rand() % (to - from + 1)) + from;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float BaseUtils::randomFloat(float from, float to) {
|
||||
const uint32 randMax = RAND_MAX;
|
||||
float randNum = (float)BaseEngine::instance().randInt(0, randMax) / (float)randMax;
|
||||
return from + (to - from) * randNum;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float BaseUtils::randomAngle(float from, float to) {
|
||||
while (to < from) {
|
||||
to += 360;
|
||||
}
|
||||
return normalizeAngle(randomFloat(from, to));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
bool BaseUtils::matchesPattern(const char *pattern, const char *string) {
|
||||
char stringc, patternc;
|
||||
|
||||
for (;; ++string) {
|
||||
stringc = toupper(*string);
|
||||
patternc = toupper(*pattern++);
|
||||
|
||||
switch (patternc) {
|
||||
case 0:
|
||||
return (stringc == 0);
|
||||
|
||||
case '?':
|
||||
if (stringc == 0) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case '*':
|
||||
if (!*pattern) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (*pattern == '.') {
|
||||
char *dot;
|
||||
if (pattern[1] == '*' && pattern[2] == 0) {
|
||||
return true;
|
||||
}
|
||||
dot = const_cast<char *>(strchr(string, '.'));
|
||||
if (pattern[1] == 0)
|
||||
return (dot == nullptr || dot[1] == 0);
|
||||
if (dot != nullptr) {
|
||||
string = dot;
|
||||
if (strpbrk(pattern, "*?[") == nullptr && strchr(string + 1, '.') == nullptr) {
|
||||
return (scumm_stricmp(pattern + 1, string + 1) == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while (*string) {
|
||||
if (BaseUtils::matchesPattern(pattern, string++)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
if (patternc != stringc) {
|
||||
if (patternc == '.' && stringc == 0) {
|
||||
return (BaseUtils::matchesPattern(pattern, string));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void BaseUtils::RGBtoHSL(uint32 rgbColor, byte *outH, byte *outS, byte *outL) {
|
||||
float varR = (RGBCOLGetR(rgbColor) / 255.0f);
|
||||
float varG = (RGBCOLGetG(rgbColor) / 255.0f);
|
||||
float varB = (RGBCOLGetB(rgbColor) / 255.0f);
|
||||
|
||||
//Min. value of RGB
|
||||
float varMin = MIN(varR, varG);
|
||||
varMin = MIN(varMin, varB);
|
||||
|
||||
//Max. value of RGB
|
||||
float varMax = MAX(varR, varG);
|
||||
varMax = MAX(varMax, varB);
|
||||
|
||||
//Delta RGB value
|
||||
float delMax = varMax - varMin;
|
||||
|
||||
float H = 0.0f, S = 0.0f, L = 0.0f;
|
||||
|
||||
L = (varMax + varMin) / 2.0f;
|
||||
|
||||
//This is a gray, no chroma...
|
||||
if (delMax == 0) {
|
||||
H = 0;
|
||||
S = 0;
|
||||
}
|
||||
//Chromatic data...
|
||||
else {
|
||||
if (L < 0.5f) {
|
||||
S = delMax / (varMax + varMin);
|
||||
} else {
|
||||
S = delMax / (2.0f - varMax - varMin);
|
||||
}
|
||||
|
||||
float delR = (((varMax - varR) / 6.0f) + (delMax / 2.0f)) / delMax;
|
||||
float delG = (((varMax - varG) / 6.0f) + (delMax / 2.0f)) / delMax;
|
||||
float delB = (((varMax - varB) / 6.0f) + (delMax / 2.0f)) / delMax;
|
||||
|
||||
if (varR == varMax) {
|
||||
H = delB - delG;
|
||||
} else if (varG == varMax) {
|
||||
H = (1.0f / 3.0f) + delR - delB;
|
||||
} else if (varB == varMax) {
|
||||
H = (2.0f / 3.0f) + delG - delR;
|
||||
}
|
||||
|
||||
if (H < 0) {
|
||||
H += 1;
|
||||
}
|
||||
if (H > 1) {
|
||||
H -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
*outH = (byte)(H * 255);
|
||||
*outS = (byte)(S * 255);
|
||||
*outL = (byte)(L * 255);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
uint32 BaseUtils::HSLtoRGB(byte InH, byte InS, byte InL) {
|
||||
float H = InH / 255.0f;
|
||||
float S = InS / 255.0f;
|
||||
float L = InL / 255.0f;
|
||||
|
||||
byte R, G, B;
|
||||
|
||||
|
||||
if (S == 0) {
|
||||
R = (byte)(L * 255);
|
||||
G = (byte)(L * 255);
|
||||
B = (byte)(L * 255);
|
||||
} else {
|
||||
float var1, var2;
|
||||
|
||||
if (L < 0.5) {
|
||||
var2 = L * (1.0 + S);
|
||||
} else {
|
||||
var2 = (L + S) - (S * L);
|
||||
}
|
||||
|
||||
var1 = 2.0f * L - var2;
|
||||
|
||||
R = (byte)(255 * Hue2RGB(var1, var2, H + (1.0f / 3.0f)));
|
||||
G = (byte)(255 * Hue2RGB(var1, var2, H));
|
||||
B = (byte)(255 * Hue2RGB(var1, var2, H - (1.0f / 3.0f)));
|
||||
}
|
||||
return BYTETORGBA(255, R, G, B);
|
||||
}
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
float BaseUtils::Hue2RGB(float v1, float v2, float vH) {
|
||||
if (vH < 0.0f) {
|
||||
vH += 1.0f;
|
||||
}
|
||||
if (vH > 1.0f) {
|
||||
vH -= 1.0f;
|
||||
}
|
||||
if ((6.0f * vH) < 1.0f) {
|
||||
return (v1 + (v2 - v1) * 6.0f * vH);
|
||||
}
|
||||
if ((2.0f * vH) < 1.0f) {
|
||||
return (v2);
|
||||
}
|
||||
if ((3.0f * vH) < 2.0f) {
|
||||
return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f);
|
||||
}
|
||||
return (v1);
|
||||
}
|
||||
|
||||
static inline void swapBytes(byte *l, byte *r, uint32 size) {
|
||||
byte tmp;
|
||||
|
||||
while (size--) {
|
||||
tmp = *l;
|
||||
*l++ = *r;
|
||||
*r++ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static void smallSort(void *base, uint32 num, uint32 size,
|
||||
int32 (*compare)(const void *, const void *)) {
|
||||
byte *max, *p = nullptr;
|
||||
|
||||
for (uint32 e = num; e > 1; e--) {
|
||||
max = (byte *)base;
|
||||
for (uint32 i = 1; i < e; i++) {
|
||||
p = (byte *)base + i * size;
|
||||
if (compare(p, max) > 0)
|
||||
max = p;
|
||||
}
|
||||
|
||||
if (p != max)
|
||||
swapBytes(p, max, size);
|
||||
}
|
||||
}
|
||||
|
||||
static void quickSort(void *base, uint32 num, uint32 size,
|
||||
int32 (*compare)(const void *, const void *)) {
|
||||
uint32 stackLo[8 * sizeof(uint32)], stackHi[8 * sizeof(uint32)];
|
||||
uint32 beg, end, lo, hi, med;
|
||||
int32 stackPos;
|
||||
|
||||
stackPos = 0;
|
||||
stackLo[stackPos] = 0;
|
||||
stackHi[stackPos] = num - 1;
|
||||
|
||||
#define X(i) ((byte *)base + size * (i))
|
||||
while (stackPos >= 0) {
|
||||
beg = stackLo[stackPos];
|
||||
end = stackHi[stackPos--];
|
||||
|
||||
if (end - beg < 8) {
|
||||
smallSort(X(beg), end - beg + 1, size, compare);
|
||||
continue;
|
||||
}
|
||||
|
||||
lo = beg;
|
||||
hi = end;
|
||||
med = lo + (hi - lo + 1) / 2;
|
||||
if (compare(X(lo), X(med)) > 0)
|
||||
swapBytes(X(lo), X(med), size);
|
||||
if (compare(X(lo), X(hi)) > 0)
|
||||
swapBytes(X(lo), X(hi), size);
|
||||
if (compare(X(med), X(hi)) > 0)
|
||||
swapBytes(X(med), X(hi), size);
|
||||
|
||||
lo++;
|
||||
hi--;
|
||||
while (1) {
|
||||
while (lo <= hi) {
|
||||
if (lo != med && compare(X(lo), X(med)) > 0)
|
||||
break;
|
||||
lo++;
|
||||
}
|
||||
|
||||
while (med != hi) {
|
||||
if (compare(X(hi), X(med)) <= 0)
|
||||
break;
|
||||
hi--;
|
||||
}
|
||||
|
||||
|
||||
if (hi < lo)
|
||||
break;
|
||||
|
||||
swapBytes(X(lo), X(hi), size);
|
||||
if (hi == med)
|
||||
med = lo;
|
||||
lo++;
|
||||
hi--;
|
||||
}
|
||||
|
||||
while (hi > beg) {
|
||||
if (hi != med && compare(X(hi), X(med)) != 0)
|
||||
break;
|
||||
hi--;
|
||||
}
|
||||
|
||||
if (hi - beg >= end-lo) {
|
||||
stackLo[++stackPos] = beg;
|
||||
stackHi[stackPos] = hi;
|
||||
stackLo[++stackPos] = lo;
|
||||
stackHi[stackPos] = end;
|
||||
} else {
|
||||
stackLo[++stackPos] = lo;
|
||||
stackHi[stackPos] = end;
|
||||
stackLo[++stackPos] = beg;
|
||||
stackHi[stackPos] = hi;
|
||||
}
|
||||
}
|
||||
#undef X
|
||||
}
|
||||
|
||||
void qsort_msvc(void *base, uint32 num, uint32 size,
|
||||
int32 (*compare)(const void *, const void *)) {
|
||||
if (base == nullptr || num == 0)
|
||||
return;
|
||||
|
||||
quickSort(base, num, size, compare);
|
||||
}
|
||||
|
||||
} // End of namespace Wintermute
|
||||
67
engines/wintermute/utils/utils.h
Normal file
67
engines/wintermute/utils/utils.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/* ScummVM - Graphic Adventure Engine
|
||||
*
|
||||
* ScummVM is the legal property of its developers, whose names
|
||||
* are too numerous to list here. Please refer to the COPYRIGHT
|
||||
* file distributed with this source distribution.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is based on WME Lite.
|
||||
* http://dead-code.org/redir.php?target=wmelite
|
||||
* Copyright (c) 2011 Jan Nedoma
|
||||
*/
|
||||
|
||||
#ifndef WINTERMUTE_UTILS_H
|
||||
#define WINTERMUTE_UTILS_H
|
||||
|
||||
#include "engines/wintermute/wintypes.h"
|
||||
|
||||
namespace Wintermute {
|
||||
|
||||
class BaseGame;
|
||||
|
||||
class BaseUtils {
|
||||
public:
|
||||
static void swap(int *a, int *b);
|
||||
static float normalizeAngle(float angle);
|
||||
|
||||
static void createPath(const char *path, bool pathOnly = false);
|
||||
|
||||
static void debugMessage(const char *text);
|
||||
static char *setString(char **string, const char *value);
|
||||
|
||||
static char *strEntry(int entry, const char *str, const char delim = ',');
|
||||
|
||||
static int randomInt(int from, int to);
|
||||
static float randomFloat(float from, float to);
|
||||
static float randomAngle(float from, float to);
|
||||
|
||||
static bool matchesPattern(const char *pattern, const char *string);
|
||||
|
||||
static void RGBtoHSL(uint32 rgbColor, byte *outH, byte *outS, byte *outL);
|
||||
static uint32 HSLtoRGB(byte H, byte S, byte L);
|
||||
|
||||
private:
|
||||
static float Hue2RGB(float v1, float v2, float vH);
|
||||
};
|
||||
|
||||
void qsort_msvc(void *base, uint32 nmemb, uint32 size,
|
||||
int32 (*compare)(const void *, const void *));
|
||||
|
||||
} // End of namespace Wintermute
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user