Initial commit
This commit is contained in:
523
engines/bagel/boflib/misc.cpp
Normal file
523
engines/bagel/boflib/misc.cpp
Normal file
@@ -0,0 +1,523 @@
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/file.h"
|
||||
#include "bagel/boflib/misc.h"
|
||||
#include "bagel/boflib/cache.h"
|
||||
#include "bagel/bagel.h"
|
||||
#include "bagel/boflib/string_functions.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
#define MAX_LINE_LEN 100
|
||||
|
||||
static uint32 lStart;
|
||||
|
||||
void timerStart() {
|
||||
lStart = g_system->getMillis();
|
||||
}
|
||||
|
||||
uint32 timerStop() {
|
||||
return g_system->getMillis() - lStart;
|
||||
}
|
||||
|
||||
uint32 getTimer() {
|
||||
return g_system->getMillis();
|
||||
}
|
||||
|
||||
void bofSleep(uint32 milli) {
|
||||
|
||||
g_system->delayMillis(milli);
|
||||
}
|
||||
|
||||
#define ALLOC_FAIL_RETRIES 2
|
||||
|
||||
void *bofMemAlloc(uint32 nSize, const char *pFile, int nLine, bool bClear) {
|
||||
// For now, until I fix it, pFile MUST be valid.
|
||||
assert(pFile != nullptr);
|
||||
assert(nSize != 0);
|
||||
|
||||
// Assume failure
|
||||
void *pNewBlock = nullptr;
|
||||
|
||||
// Try a few times to allocate the desired amount of memory.
|
||||
// Flush objects from Cache is necessary.
|
||||
for (int nRetries = 0; nRetries < ALLOC_FAIL_RETRIES; nRetries++) {
|
||||
pNewBlock = (void *)malloc(nSize);
|
||||
|
||||
// If allocation was successful, then we're outta here
|
||||
if (pNewBlock != nullptr) {
|
||||
if (bClear)
|
||||
memset((byte *)pNewBlock, 0, nSize);
|
||||
|
||||
break;
|
||||
}
|
||||
// Otherwise, we need to free up some memory by flushing old
|
||||
// objects from the Cache.
|
||||
CCache::optimize(nSize + 2 * sizeof(uint16) + sizeof(uint32));
|
||||
}
|
||||
|
||||
if (pNewBlock == nullptr)
|
||||
CBofError::fatalError(ERR_MEMORY, "Could not allocate %u bytes, file %s, line %d", nSize, pFile, nLine);
|
||||
|
||||
return pNewBlock;
|
||||
}
|
||||
|
||||
void bofMemFree(void *pBuf) {
|
||||
free(pBuf);
|
||||
}
|
||||
|
||||
Fixed fixedMultiply(Fixed Multiplicand, Fixed Multiplier) {
|
||||
int64 nTmpNum = (int64)Multiplicand * Multiplier;
|
||||
Fixed fixResult = (Fixed)(nTmpNum >> 16);
|
||||
|
||||
return fixResult;
|
||||
}
|
||||
|
||||
Fixed fixedDivide(Fixed Dividend, Fixed Divisor) {
|
||||
int64 nBigNum = (int64)Dividend << 16;
|
||||
Fixed fixResult = (Fixed)(nBigNum / Divisor);
|
||||
|
||||
return fixResult;
|
||||
}
|
||||
|
||||
void bofMemSet(void *pSrc, byte chByte, int32 lBytes) {
|
||||
assert(pSrc != nullptr);
|
||||
|
||||
byte *pBuf = (byte *)pSrc;
|
||||
|
||||
while (lBytes-- != 0)
|
||||
*pBuf++ = chByte;
|
||||
}
|
||||
|
||||
void bofMemCopy(void *pDst, const void *pSrc, int32 lLength) {
|
||||
assert(pDst != nullptr);
|
||||
assert(pSrc != nullptr);
|
||||
assert(lLength >= 0);
|
||||
|
||||
byte *p1 = (byte *)pDst;
|
||||
const byte *p2 = (const byte *)pSrc;
|
||||
|
||||
while (lLength-- != 0) {
|
||||
*p1++ = *p2++;
|
||||
}
|
||||
}
|
||||
|
||||
bool readLine(Common::SeekableReadStream *fp, char *pszBuf) {
|
||||
if (fp->eos())
|
||||
return false;
|
||||
|
||||
Common::String line = fp->readLine();
|
||||
Common::strcpy_s(pszBuf, MAX_LINE_LEN, line.c_str());
|
||||
strreplaceChar(pszBuf, '\n', '\0');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void encrypt(void *pBuf, int32 size, const char *pszPassword) {
|
||||
assert(pBuf != nullptr);
|
||||
|
||||
const char *pStart = pszPassword;
|
||||
if (!pszPassword || strlen(pszPassword) == 0) {
|
||||
pStart = "\0\0";
|
||||
}
|
||||
|
||||
byte *p = (byte *)pBuf;
|
||||
|
||||
const char *pPW = pStart;
|
||||
while (--size >= 0) {
|
||||
*p ^= (byte)(0xD2 + size + *pPW);
|
||||
p++;
|
||||
if (*pPW++ == '\0') {
|
||||
pPW = pStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void encryptPartial(void *pBuf, int32 fullSize, int32 lBytes, const char *pszPassword) {
|
||||
assert(pBuf != nullptr);
|
||||
|
||||
const char *pStart = pszPassword;
|
||||
if (!pszPassword || strlen(pszPassword) == 0) {
|
||||
pStart = "\0\0";
|
||||
}
|
||||
|
||||
byte *p = (byte *)pBuf;
|
||||
|
||||
const char *pPW = pStart;
|
||||
while (--lBytes >= 0) {
|
||||
fullSize--;
|
||||
*p ^= (byte)(0xD2 + fullSize + *pPW);
|
||||
p++;
|
||||
if (*pPW++ == '\0') {
|
||||
pPW = pStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int mapWindowsPointSize(int pointSize) {
|
||||
return pointSize;
|
||||
}
|
||||
|
||||
void ErrorLog(const char *logFile, const char *format, ...) {
|
||||
// No implementation
|
||||
}
|
||||
|
||||
int StrFreqMatch(const char *mask, const char *test) {
|
||||
static int nCount[256];
|
||||
int i, divergence;
|
||||
|
||||
/* can't access null pointers */
|
||||
assert(mask != nullptr);
|
||||
assert(test != nullptr);
|
||||
|
||||
/* assume no match by making the divergence really high */
|
||||
divergence = 100;
|
||||
|
||||
/*
|
||||
* the first letter has to match before we even think about continuing
|
||||
*/
|
||||
if (*mask == *test) {
|
||||
|
||||
/* reset the frequency count */
|
||||
memset(nCount, 0, sizeof(int) * 256);
|
||||
|
||||
/* count the frequency of the chars in 'mask' */
|
||||
while (*mask != '\0')
|
||||
nCount[(int)*mask++] += 1;
|
||||
|
||||
/* subtract off the frequency of the chars in 'test' */
|
||||
while (*test != '\0')
|
||||
nCount[(int)*test++] -= 1;
|
||||
|
||||
/*
|
||||
* total all of the frequencies
|
||||
*/
|
||||
divergence = 0;
|
||||
for (i = 0; i <= 255; i++)
|
||||
divergence += abs(nCount[i]);
|
||||
}
|
||||
|
||||
/* returning a 0 or 1 means that the strings are almost identical */
|
||||
return (divergence);
|
||||
}
|
||||
|
||||
|
||||
bool StrCompare(const char *pszStr1, const char *pszStr2, unsigned int nSize) {
|
||||
char *s1, *p, string1[256]; /* replace this stack hog with malloc */
|
||||
char *s2, *sp, string2[256]; /* replace this stack hog with malloc */
|
||||
int i, n, inc;
|
||||
bool bMatch;
|
||||
|
||||
/* can't access null pointers */
|
||||
assert(pszStr1 != nullptr);
|
||||
assert(pszStr2 != nullptr);
|
||||
|
||||
/* make sure that we are not going to blow the stack */
|
||||
assert(strlen(pszStr1) < 256);
|
||||
assert(strlen(pszStr2) < 256);
|
||||
|
||||
p = s1 = string1;
|
||||
s2 = string2;
|
||||
|
||||
/*
|
||||
* Reset these buffers to garuntee the strings will terminate
|
||||
*/
|
||||
memset(s1, 0, 256);
|
||||
memset(s2, 0, 256);
|
||||
|
||||
/* make local copies of the strings */
|
||||
Common::sprintf_s(s1, 256, " %s", pszStr1);
|
||||
Common::sprintf_s(s2, 256, " %s", pszStr2);
|
||||
|
||||
/*
|
||||
* make "THE", "AN", and "A" be special tokens - make them uppercase while
|
||||
* all other words are lowercase.
|
||||
*/
|
||||
strLower(s1);
|
||||
StrUprStr(s1, " the ");
|
||||
StrUprStr(s1, " an ");
|
||||
StrUprStr(s1, " a ");
|
||||
|
||||
if ((sp = strstr(s2, " THE ")) != nullptr) {
|
||||
memmove(sp, sp + 5, strlen(sp + 5) + 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* strip out all unwanted characters
|
||||
*/
|
||||
|
||||
/* strip out all spaces
|
||||
*/
|
||||
StrStripChar(s1, ' ');
|
||||
StrStripChar(s2, ' ');
|
||||
|
||||
/* strip out any apostrophes
|
||||
*/
|
||||
StrStripChar(s1, 39);
|
||||
StrStripChar(s2, 39);
|
||||
|
||||
/* strip out any commas
|
||||
*/
|
||||
StrStripChar(s1, ',');
|
||||
StrStripChar(s2, ',');
|
||||
|
||||
/* strip out any dashes
|
||||
*/
|
||||
StrStripChar(s1, '-');
|
||||
StrStripChar(s2, '-');
|
||||
|
||||
/*
|
||||
* add a buffer zone to the end of both strings
|
||||
* (this might now be obsolete)
|
||||
*/
|
||||
Common::strcat_s(s1, 256, " ");
|
||||
Common::strcat_s(s2, 256, " ");
|
||||
|
||||
/*
|
||||
* compare the 2 strings, if we get a "THE", "A", or "AN" (case sensative)
|
||||
* then do a special compare
|
||||
*/
|
||||
|
||||
/* assume they match */
|
||||
bMatch = true;
|
||||
|
||||
i = 0;
|
||||
n = strlen(s1);
|
||||
while (i++ < n) {
|
||||
|
||||
/*
|
||||
* handle special tokens
|
||||
*/
|
||||
if ((*s1 == 'T') || (*s1 == 'A')) {
|
||||
inc = 3;
|
||||
if (*s1 == 'A') {
|
||||
inc = 1;
|
||||
if (*(s1 + 1) == 'N') {
|
||||
inc = 2;
|
||||
}
|
||||
}
|
||||
p = s1;
|
||||
|
||||
if (toupper(*s1) != toupper(*s2)) {
|
||||
s1 += inc;
|
||||
i += inc;
|
||||
} else {
|
||||
p = s1 + inc;
|
||||
i += inc;
|
||||
}
|
||||
}
|
||||
|
||||
if ((toupper(*s1) != toupper(*s2)) && (toupper(*p) != toupper(*s2))) {
|
||||
bMatch = false;
|
||||
break;
|
||||
}
|
||||
s1++;
|
||||
s2++;
|
||||
p++;
|
||||
}
|
||||
|
||||
return (bMatch);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* StrCharCount - Counts number of occurences of a specified char in String
|
||||
*
|
||||
* DESCRIPTION: Counts the number of times the specified character occurs
|
||||
* in the given string.
|
||||
*
|
||||
* SAMPLE USAGE:
|
||||
* n = StrCharCount(str, c);
|
||||
* const char *str; pointer to string to parse
|
||||
* char c; character to count in str
|
||||
*
|
||||
* RETURNS: int = number of times character c occurs in string str
|
||||
*
|
||||
*****************************************************************************/
|
||||
int StrCharCount(const char *str, char c) {
|
||||
int n;
|
||||
|
||||
assert(str != nullptr);
|
||||
assert(strlen(str) <= 255);
|
||||
|
||||
n = 0;
|
||||
while (*str != '\0') {
|
||||
if (*str++ == c)
|
||||
n++;
|
||||
}
|
||||
|
||||
return (n);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* name StriStr - same as strstr() except ignores case
|
||||
*
|
||||
* synopsis s = StriStr(s1, s2)
|
||||
* const char *s1 string to parse
|
||||
* const char *s2 substring to find in s1
|
||||
*
|
||||
* purpose To search for a string inside another string while ignoring case
|
||||
*
|
||||
*
|
||||
* returns pointer to substring s2 in s1 or nullptr if not found
|
||||
*
|
||||
**/
|
||||
|
||||
char *StriStr(char *s1, const char *s2) {
|
||||
char *p, str1[80];
|
||||
char str2[80];
|
||||
|
||||
/* can't access null pointers */
|
||||
assert(s1 != nullptr);
|
||||
assert(s2 != nullptr);
|
||||
|
||||
/* make sure we don't blow the stack */
|
||||
assert(strlen(s1) < 80);
|
||||
assert(strlen(s2) < 80);
|
||||
|
||||
/* copy to local buffers */
|
||||
Common::strcpy_s(str1, s1);
|
||||
Common::strcpy_s(str2, s2);
|
||||
|
||||
/* convert to upper case */
|
||||
strUpper(str1);
|
||||
strUpper(str2);
|
||||
|
||||
/* find str2 in str1 */
|
||||
p = strstr(str1, str2);
|
||||
|
||||
/* re-point to original string s1 */
|
||||
if (p != nullptr) {
|
||||
p = s1 + (p - str1);
|
||||
}
|
||||
|
||||
return (p);
|
||||
}
|
||||
|
||||
void StrUprStr(char *s1, const char *s2) {
|
||||
char *p;
|
||||
int i, n;
|
||||
|
||||
/* can't access null pointers */
|
||||
assert(s1 != nullptr);
|
||||
assert(s2 != nullptr);
|
||||
|
||||
p = s1;
|
||||
while ((p = StriStr(p, s2)) != nullptr) {
|
||||
n = strlen(s2);
|
||||
for (i = 0; i < n; i++) {
|
||||
*p = (char)toupper(*p);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* name StrCpyStripChar - Same as Common::strcpy_s() except specified character
|
||||
* will be stripped from the destination string.
|
||||
*
|
||||
* synopsis StrCpyStripChar(dest, source, c)
|
||||
* char *dest destinaton string
|
||||
* const char *source source string
|
||||
* char c character to strip from dest
|
||||
*
|
||||
* purpose To strip out a specified character while copying 1 string to another
|
||||
*
|
||||
*
|
||||
* returns Nothing
|
||||
*
|
||||
**/
|
||||
void StrCpyStripChar(char *dest, const char *source, char c) {
|
||||
/* can't access null pointers */
|
||||
assert(dest != nullptr);
|
||||
assert(source != nullptr);
|
||||
|
||||
/* source and destination cannot be the same */
|
||||
assert(dest != source);
|
||||
|
||||
do {
|
||||
if ((*dest = *source) != c)
|
||||
dest++;
|
||||
} while (*source++ != '\0');
|
||||
}
|
||||
|
||||
|
||||
char *StrStripChar(char *str, char c) {
|
||||
char *p = str;
|
||||
|
||||
/* can't acces a null pointer */
|
||||
assert(str != nullptr);
|
||||
|
||||
/* if c was '\0' then this function would do nothing */
|
||||
assert(c != '\0');
|
||||
|
||||
while (*p != '\0') {
|
||||
if (*p == c) {
|
||||
|
||||
/* move the string left 1 byte (including the terminator) */
|
||||
memmove(p, p + 1, strlen(p + 1) + 1);
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return (str);
|
||||
}
|
||||
|
||||
|
||||
char *StrReplaceChar(char *str, char cOld, char cNew) {
|
||||
char *p = str;
|
||||
|
||||
/* can't acces a null pointer */
|
||||
assert(str != nullptr);
|
||||
|
||||
/* if cOld was '\0' then this function would do nothing */
|
||||
assert(cOld != '\0');
|
||||
|
||||
while (*p != '\0') {
|
||||
if (*p == cOld) {
|
||||
*p = cNew;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return (str);
|
||||
}
|
||||
|
||||
/**
|
||||
* name ProbableTrue
|
||||
* synopsis - return a true / false based on the probability given
|
||||
* int nProbability the probability of returning a true
|
||||
*
|
||||
* purpose to return a true <nProbability> of the tine
|
||||
*
|
||||
*
|
||||
* returns bool
|
||||
*
|
||||
**/
|
||||
bool ProbableTrue(int nProbability) {
|
||||
int nRand = brand() % 100;
|
||||
|
||||
return (nRand < nProbability);
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
Reference in New Issue
Block a user