Initial commit
This commit is contained in:
177
engines/bagel/boflib/cache.cpp
Normal file
177
engines/bagel/boflib/cache.cpp
Normal file
@@ -0,0 +1,177 @@
|
||||
/* 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 "bagel/boflib/cache.h"
|
||||
#include "bagel/boflib/log.h"
|
||||
#include "bagel/spacebar/boflib/debug.h"
|
||||
#include "bagel/boflib/misc.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
// Static members
|
||||
CCache *CCache::_pCacheList;
|
||||
uint32 CCache::_lOldest;
|
||||
uint32 CCache::_lYoungest;
|
||||
uint16 CCache::_nEntries;
|
||||
|
||||
void CCache::initialize() {
|
||||
_pCacheList = nullptr;
|
||||
_lOldest = 0xFFFFFFFF;
|
||||
_lYoungest = 0xFFFFFFFF;
|
||||
_nEntries = 0;
|
||||
}
|
||||
|
||||
CCache::CCache() {
|
||||
_bValid = true;
|
||||
|
||||
// Inits
|
||||
_lAge = _lYoungest;
|
||||
_bCached = false;
|
||||
_nLockCount = 0;
|
||||
|
||||
if (_pCacheList == nullptr) {
|
||||
// There can't be any other entries
|
||||
assert(_nEntries == 0);
|
||||
|
||||
// This object is the start of the cache list
|
||||
_pCacheList = this;
|
||||
|
||||
} else {
|
||||
assert(_nEntries != 0);
|
||||
|
||||
_pCacheList->Insert(this);
|
||||
}
|
||||
|
||||
// One more cached entry
|
||||
_nEntries++;
|
||||
}
|
||||
|
||||
CCache::~CCache() {
|
||||
// Make sure this object is not deleted twice
|
||||
assert(_bValid);
|
||||
|
||||
// There can be only one cache list per EXE/DLL
|
||||
assert(this->getHead() == _pCacheList);
|
||||
|
||||
// Object must be released by the derived class destructor
|
||||
assert(_bCached == false);
|
||||
|
||||
_nEntries--;
|
||||
|
||||
// Remove this object from the linked list
|
||||
if (this == _pCacheList) {
|
||||
_pCacheList = (CCache *)this->getNext();
|
||||
}
|
||||
|
||||
this->Delete();
|
||||
|
||||
if (_nEntries == 0) {
|
||||
_pCacheList = nullptr;
|
||||
}
|
||||
|
||||
_bValid = false;
|
||||
}
|
||||
|
||||
bool CCache::flush() {
|
||||
bool bReleased = false;
|
||||
CCache *pCache = _pCacheList;
|
||||
while (pCache != nullptr) {
|
||||
if (pCache->release())
|
||||
bReleased = true;
|
||||
|
||||
pCache = (CCache *)(pCache->getNext());
|
||||
}
|
||||
|
||||
return bReleased;
|
||||
}
|
||||
|
||||
bool CCache::optimize(uint32 lRequestedFreeSpace) {
|
||||
logInfo(buildString("CCache::optimize(%u)", lRequestedFreeSpace));
|
||||
|
||||
bool bSuccess = true;
|
||||
while (getFreePhysMem() < lRequestedFreeSpace) {
|
||||
uint32 lAvgAge = ((_lOldest - _lYoungest) / 2) + _lYoungest;
|
||||
_lOldest = lAvgAge;
|
||||
|
||||
// Parse Linked list of cached objects and remove any that are too old
|
||||
CCache *pCache = _pCacheList;
|
||||
int nObjects = 0;
|
||||
while (pCache != nullptr) {
|
||||
if (pCache->_bCached && (pCache->_nLockCount <= 0)) {
|
||||
nObjects++;
|
||||
if (pCache->_lAge >= lAvgAge) {
|
||||
logInfo(buildString("Freeing Object: %p from the Cache list", pCache));
|
||||
pCache->release();
|
||||
}
|
||||
}
|
||||
|
||||
// Next object in list
|
||||
pCache = (CCache *)pCache->getNext();
|
||||
}
|
||||
|
||||
// If there are no objects loaded then we really might be out of memory
|
||||
if (nObjects == 0) {
|
||||
bSuccess = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
void CCache::load() {
|
||||
// Make sure this object is not used after it is destructed
|
||||
assert(_bValid);
|
||||
|
||||
// Timestamp this object
|
||||
_lAge = --_lYoungest;
|
||||
|
||||
// If this object is not already cached
|
||||
if (!_bCached) {
|
||||
// We must tell the Cache library that this object is in the cache to avoid recursion
|
||||
_bCached = true;
|
||||
|
||||
// Call the routine that will allocate the memory for this object
|
||||
// alloc() is pure-virtual and must be defined in the derived class.
|
||||
_bCached = alloc();
|
||||
}
|
||||
}
|
||||
|
||||
bool CCache::release() {
|
||||
// Make sure this object is not used after it is destructed
|
||||
assert(_bValid);
|
||||
|
||||
// If this object is in the cache
|
||||
bool bReleased = false;
|
||||
if (_bCached) {
|
||||
bReleased = true;
|
||||
|
||||
// Call the routine that will free the memory used by this object.
|
||||
// free() is pure-virtual and must be defined in the derived class.
|
||||
free();
|
||||
|
||||
_bCached = false;
|
||||
}
|
||||
|
||||
return bReleased;
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
101
engines/bagel/boflib/cache.h
Normal file
101
engines/bagel/boflib/cache.h
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_CACHE_H
|
||||
#define BAGEL_BOFLIB_CACHE_H
|
||||
|
||||
#include "bagel/boflib/llist.h"
|
||||
#include "bagel/boflib/stdinc.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
class CCache : private CLList {
|
||||
private:
|
||||
virtual bool alloc() = 0; // These pure-virtuals MUST be defined
|
||||
virtual void free() = 0; // in the derived class.
|
||||
|
||||
static CCache *_pCacheList; // Linked cache list
|
||||
static uint32 _lOldest; // Current oldest object in cache
|
||||
static uint32 _lYoungest; // Current youngest object in cache
|
||||
static uint16 _nEntries; // Number of CCache Objects
|
||||
|
||||
uint32 _lAge; // Age of this object
|
||||
int _nLockCount; // # of locks held on this object
|
||||
bool _bCached; // true if object is in the cache
|
||||
|
||||
bool _bValid; // true if this object is valid
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
CCache();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~CCache();
|
||||
|
||||
/**
|
||||
* Loads current object into cache
|
||||
*/
|
||||
void load();
|
||||
|
||||
/**
|
||||
* Releases current object from cache
|
||||
*/
|
||||
bool release();
|
||||
|
||||
void lock() {
|
||||
_nLockCount++;
|
||||
load();
|
||||
}
|
||||
void unlock() {
|
||||
_nLockCount--;
|
||||
}
|
||||
bool isLocked() {
|
||||
return (_nLockCount > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* initialize statics
|
||||
*/
|
||||
static void initialize();
|
||||
|
||||
/**
|
||||
* Releases all objects from cache
|
||||
*/
|
||||
static bool flush();
|
||||
|
||||
/**
|
||||
* Releases older objects from cache if need memory
|
||||
* @remarks Optimizes cache so that the specified amount of memory is left available.
|
||||
* @param lRequestedFreeSpace Free space requested to remain available
|
||||
* @return true if there were any objects to release from the cache.
|
||||
* false if there were no objects released.
|
||||
*/
|
||||
static bool optimize(uint32 lRequestedFreeSpace);
|
||||
};
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
50
engines/bagel/boflib/cursor_data.cpp
Normal file
50
engines/bagel/boflib/cursor_data.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/* 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 "bagel/boflib/cursor_data.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
const byte ARROW_CURSOR[CURSOR_W * CURSOR_H] = {
|
||||
1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, 0,
|
||||
1, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0,
|
||||
1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
|
||||
1, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0,
|
||||
1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0, 0,
|
||||
1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0,
|
||||
1, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,
|
||||
1, 2, 2, 2, 1, 2, 2, 1, 0, 0, 0, 0,
|
||||
1, 2, 2, 1, 1, 2, 2, 1, 0, 0, 0, 0,
|
||||
1, 2, 1, 0, 0, 1, 2, 2, 1, 0, 0, 0,
|
||||
1, 1, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0,
|
||||
1, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0,
|
||||
};
|
||||
const byte CURSOR_PALETTE[9] = { 0x80, 0x80, 0x80, 0, 0, 0, 0xff, 0xff, 0xff };
|
||||
|
||||
} // namespace Bagel
|
||||
38
engines/bagel/boflib/cursor_data.h
Normal file
38
engines/bagel/boflib/cursor_data.h
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_CURSOR_DATA_H
|
||||
#define BAGEL_BOFLIB_CURSOR_DATA_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
constexpr int CURSOR_W = 12;
|
||||
constexpr int CURSOR_H = 20;
|
||||
|
||||
extern const byte ARROW_CURSOR[CURSOR_W * CURSOR_H];
|
||||
extern const byte CURSOR_PALETTE[9];
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
103
engines/bagel/boflib/error.cpp
Normal file
103
engines/bagel/boflib/error.cpp
Normal file
@@ -0,0 +1,103 @@
|
||||
/* 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/str.h"
|
||||
#include "gui/debugger.h"
|
||||
#include "bagel/boflib/error.h"
|
||||
#include "bagel/bagel.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
const char *const g_errList[] = {
|
||||
"No Error",
|
||||
"Out of memory",
|
||||
"Error opening file",
|
||||
"Error closing file",
|
||||
"Error reading file",
|
||||
"Error writing file",
|
||||
"Error seeking file",
|
||||
"Error deleting file",
|
||||
"Could not find file",
|
||||
"Invalid file type",
|
||||
"Invalid Path",
|
||||
"Disk error",
|
||||
"Unknown Error",
|
||||
"CRC failure"
|
||||
};
|
||||
|
||||
// Static members
|
||||
//
|
||||
int CBofError::_count;
|
||||
|
||||
|
||||
CBofError::CBofError() {
|
||||
_errCode = ERR_NONE;
|
||||
}
|
||||
|
||||
void CBofError::initialize() {
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
void CBofError::reportError(ErrorCode errCode, const char *format, ...) {
|
||||
_errCode = errCode;
|
||||
|
||||
if (_errCode == ERR_NONE)
|
||||
return;
|
||||
|
||||
Common::String buf;
|
||||
|
||||
// One more error
|
||||
_count++;
|
||||
|
||||
// Don't parse the variable input if there isn't any
|
||||
if (format != nullptr) {
|
||||
// Parse the arguments
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
buf = Common::String::vformat(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
// Tell user about error, unless there were too many errors
|
||||
if (_count < MAX_ERRORS)
|
||||
bofMessageBox(buf, g_errList[errCode]);
|
||||
|
||||
GUI::Debugger *console = g_engine->getDebugger();
|
||||
if (console->isActive())
|
||||
console->debugPrintf("%s\n", buf.c_str());
|
||||
}
|
||||
|
||||
void CBofError::fatalError(ErrorCode errCode, const char *format, ...) {
|
||||
Common::String buf;
|
||||
|
||||
// Don't parse the variable input if there isn't any
|
||||
if (format != nullptr) {
|
||||
// Parse the arguments
|
||||
va_list argptr;
|
||||
va_start(argptr, format);
|
||||
buf = Common::String::vformat(format, argptr);
|
||||
va_end(argptr);
|
||||
}
|
||||
|
||||
error("%s - %s", g_errList[errCode], buf.c_str());
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
103
engines/bagel/boflib/error.h
Normal file
103
engines/bagel/boflib/error.h
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_ERROR_H
|
||||
#define BAGEL_BOFLIB_ERROR_H
|
||||
|
||||
#include "common/str.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
/**
|
||||
* Error reporting codes
|
||||
*/
|
||||
enum ErrorCode {
|
||||
ERR_NONE = 0, /* no error */
|
||||
ERR_MEMORY = 1, /* not enough memory */
|
||||
ERR_FOPEN = 2, /* error opening a file */
|
||||
ERR_FREAD = 4, /* error reading a file */
|
||||
ERR_FWRITE = 5, /* error writing a file */
|
||||
ERR_FSEEK = 6, /* error seeking a file */
|
||||
ERR_FFIND = 8, /* could not find file */
|
||||
ERR_FTYPE = 9, /* invalid file type */
|
||||
ERR_UNKNOWN = 12, /* unknown error */
|
||||
ERR_CRC = 13, /* file or data failed CRC check */
|
||||
};
|
||||
|
||||
#define ERROR_CODE ErrorCode
|
||||
#define MAX_ERRORS 3
|
||||
|
||||
extern const char *const g_errList[];
|
||||
#define errList g_errList
|
||||
|
||||
class CBofError {
|
||||
protected:
|
||||
static int _count;
|
||||
ErrorCode _errCode;
|
||||
|
||||
virtual void bofMessageBox(const Common::String &content, const Common::String &title) {
|
||||
}
|
||||
|
||||
public:
|
||||
CBofError();
|
||||
virtual ~CBofError() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs specified error to log file.
|
||||
* @remarks Sets _errCode to specified error condition, and logs the
|
||||
* error.
|
||||
* @param errCode Error to report
|
||||
* @param format A printf style format string
|
||||
* @param ... Additional parameters to be formatted and inserted into the string
|
||||
*/
|
||||
void reportError(ErrorCode errCode, const char *format, ...);
|
||||
|
||||
/**
|
||||
* Logs specified fatal error to log file and exit the game.
|
||||
* @param errCode Error to report
|
||||
* @param format A printf style format string
|
||||
* @param ... Additional parameters to be formatted and inserted into the string
|
||||
*/
|
||||
static void fatalError(ErrorCode errCode, const char *format, ...);
|
||||
|
||||
bool errorOccurred() const {
|
||||
return _errCode != ERR_NONE;
|
||||
}
|
||||
ErrorCode getErrorCode() const {
|
||||
return _errCode;
|
||||
}
|
||||
void clearError() {
|
||||
_errCode = ERR_NONE;
|
||||
}
|
||||
|
||||
static void initialize();
|
||||
|
||||
static int getErrorCount() {
|
||||
return _count;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
55
engines/bagel/boflib/event_loop.cpp
Normal file
55
engines/bagel/boflib/event_loop.cpp
Normal file
@@ -0,0 +1,55 @@
|
||||
/* 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/events.h"
|
||||
#include "bagel/boflib/event_loop.h"
|
||||
#include "bagel/bagel.h"
|
||||
#include "bagel/spacebar/baglib/master_win.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
EventLoop::EventLoop(Mode mode) : _limiter(g_system, 60, false),
|
||||
_mode(mode) {
|
||||
}
|
||||
|
||||
bool EventLoop::frame() {
|
||||
Common::Event e;
|
||||
|
||||
// Handle pending events
|
||||
while (g_system->getEventManager()->pollEvent(e)) {
|
||||
if (g_engine->shouldQuit() || (e.type == Common::EVENT_LBUTTONDOWN) ||
|
||||
(e.type == Common::EVENT_KEYDOWN && e.kbd.keycode == Common::KEYCODE_ESCAPE))
|
||||
return true;
|
||||
}
|
||||
|
||||
_limiter.delayBeforeSwap();
|
||||
|
||||
// Update the screen
|
||||
if (_mode == FORCE_REPAINT && g_engine->isSpaceBar())
|
||||
SpaceBar::CBagMasterWin::forcePaintScreen();
|
||||
g_engine->getScreen()->update();
|
||||
|
||||
_limiter.startFrame();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
51
engines/bagel/boflib/event_loop.h
Normal file
51
engines/bagel/boflib/event_loop.h
Normal file
@@ -0,0 +1,51 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_EVENT_LOOP_H
|
||||
#define BAGEL_BOFLIB_EVENT_LOOP_H
|
||||
|
||||
#include "graphics/framelimiter.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
class EventLoop {
|
||||
public:
|
||||
enum Mode {
|
||||
NO_UPDATES = 0, FORCE_REPAINT = 1
|
||||
};
|
||||
private:
|
||||
Graphics::FrameLimiter _limiter;
|
||||
Mode _mode;
|
||||
|
||||
public:
|
||||
EventLoop(Mode mode = NO_UPDATES);
|
||||
|
||||
/**
|
||||
* Processes pending events and does a frame output.
|
||||
* @returns True if Escape was pressed to abort loop
|
||||
*/
|
||||
bool frame();
|
||||
};
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
90
engines/bagel/boflib/file_functions.cpp
Normal file
90
engines/bagel/boflib/file_functions.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/* 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/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/file.h"
|
||||
#include "common/fs.h"
|
||||
#include "common/macresman.h"
|
||||
#include "bagel/boflib/file_functions.h"
|
||||
#include "bagel/bagel.h"
|
||||
#include "bagel/afxwin.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
bool fileExists(const char *pszFileName) {
|
||||
if (g_engine->getPlatform() == Common::kPlatformMacintosh) {
|
||||
return Common::MacResManager::exists(pszFileName);
|
||||
} else if (!g_engine->isSpaceBar()) {
|
||||
return MFC::FileExists(pszFileName);
|
||||
} else {
|
||||
return Common::File::exists(pszFileName);
|
||||
}
|
||||
}
|
||||
|
||||
int32 fileLength(const char *pszFileName) {
|
||||
Common::SeekableReadStream *stream = nullptr;
|
||||
if (g_engine->getPlatform() == Common::kPlatformMacintosh) {
|
||||
stream = Common::MacResManager::openFileOrDataFork(pszFileName);
|
||||
} else {
|
||||
stream = SearchMan.createReadStreamForMember(pszFileName);
|
||||
}
|
||||
|
||||
int32 length = -1;
|
||||
if (stream) {
|
||||
length = stream->size();
|
||||
delete stream;
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
char *fileGetFullPath(char *pszDstBuf, const char *pszSrcBuf) {
|
||||
Common::strcpy_s(pszDstBuf, MAX_DIRPATH, pszSrcBuf);
|
||||
return pszDstBuf;
|
||||
}
|
||||
|
||||
void fixPathName(CBofString &s) {
|
||||
// Remove any homedir prefix. In ScummVM, all paths are relative
|
||||
// to the game folder automatically
|
||||
char *p = strstr(s.getBuffer(), HOMEDIR_TOKEN);
|
||||
if (p != nullptr)
|
||||
s = p + strlen(HOMEDIR_TOKEN) + 1;
|
||||
|
||||
// Replace any backslashes with forward slashes
|
||||
while ((p = strchr(s.getBuffer(), '\\')) != nullptr)
|
||||
* p = '/';
|
||||
}
|
||||
|
||||
const char *formPath(const char *dir, const char *pszFile) {
|
||||
assert(dir != nullptr && pszFile != nullptr);
|
||||
static char szBuf[MAX_DIRPATH];
|
||||
|
||||
CBofString cStr(dir);
|
||||
fixPathName(cStr);
|
||||
Common::Path path(cStr.getBuffer());
|
||||
path = path.append(pszFile);
|
||||
|
||||
Common::strcpy_s(szBuf, path.toString().c_str());
|
||||
|
||||
return &szBuf[0];
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
61
engines/bagel/boflib/file_functions.h
Normal file
61
engines/bagel/boflib/file_functions.h
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_FILE_FUNCTIONS_H
|
||||
#define BAGEL_BOFLIB_FILE_FUNCTIONS_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "bagel/boflib/string.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
/**
|
||||
* Checks to see if specified file exists
|
||||
* @param pszFileName Name of file to check existence
|
||||
* @return true if file exists, false if file does not exist
|
||||
*
|
||||
**/
|
||||
// for mac, use this routine to replace the diskid
|
||||
extern bool fileExists(const char *pszFileName);
|
||||
|
||||
/**
|
||||
* Gets length of file in bytes (via file name)
|
||||
* @param pszFileName Name of file to get length for
|
||||
* @return Size of specified file (or -1 if not exist or error)
|
||||
*/
|
||||
extern int32 fileLength(const char *pszFileName);
|
||||
|
||||
extern char *fileGetFullPath(char *pszDstBuf, const char *pszSrcBuf);
|
||||
|
||||
|
||||
/**
|
||||
* Takes a directory and filename, merging them to form a
|
||||
* fully qualified filename. Also takes care of special folder
|
||||
* aliases at the start of the directory name
|
||||
*/
|
||||
extern const char *formPath(const char *dir, const char *pszFile);
|
||||
|
||||
extern void fixPathName(CBofString &s);
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
167
engines/bagel/boflib/llist.cpp
Normal file
167
engines/bagel/boflib/llist.cpp
Normal file
@@ -0,0 +1,167 @@
|
||||
/* 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/scummsys.h"
|
||||
#include "bagel/boflib/llist.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
CLList::CLList() {
|
||||
_pPrev = nullptr;
|
||||
_pNext = nullptr;
|
||||
_pData = nullptr;
|
||||
}
|
||||
|
||||
CLList::CLList(void *pObj) {
|
||||
_pPrev = nullptr;
|
||||
_pNext = nullptr;
|
||||
_pData = pObj;
|
||||
}
|
||||
|
||||
CLList::~CLList() {
|
||||
this->Delete();
|
||||
}
|
||||
|
||||
void CLList::addToHead(CLList *pNewList) {
|
||||
// Can't insert a nullptr record into the list
|
||||
assert(pNewList != nullptr);
|
||||
|
||||
CLList *pListHead = getHead();
|
||||
|
||||
pNewList->_pNext = pListHead;
|
||||
pNewList->_pPrev = nullptr;
|
||||
|
||||
pListHead->_pPrev = pNewList;
|
||||
}
|
||||
|
||||
void CLList::addToTail(CLList *pNewList) {
|
||||
// Can't insert a nullptr record into the list
|
||||
assert(pNewList != nullptr);
|
||||
|
||||
CLList *pListTail = getTail();
|
||||
|
||||
pNewList->_pPrev = pListTail;
|
||||
pNewList->_pNext = nullptr;
|
||||
|
||||
pListTail->_pNext = pNewList;
|
||||
}
|
||||
|
||||
void CLList::Insert(CLList *pList) {
|
||||
// Can't insert a nullptr record into the list
|
||||
assert(pList != nullptr);
|
||||
|
||||
pList->_pPrev = this;
|
||||
pList->_pNext = _pNext;
|
||||
|
||||
if (_pNext != nullptr)
|
||||
_pNext->_pPrev = pList;
|
||||
|
||||
_pNext = pList;
|
||||
}
|
||||
|
||||
void CLList::Delete() {
|
||||
if (_pPrev != nullptr)
|
||||
_pPrev->_pNext = _pNext;
|
||||
|
||||
if (_pNext != nullptr)
|
||||
_pNext->_pPrev = _pPrev;
|
||||
|
||||
_pPrev = _pNext = nullptr;
|
||||
}
|
||||
|
||||
void CLList::MoveToHead() {
|
||||
CLList *pHead = getHead();
|
||||
assert(pHead != nullptr);
|
||||
|
||||
if (this != pHead) {
|
||||
Delete();
|
||||
pHead->addToHead(this);
|
||||
}
|
||||
}
|
||||
|
||||
void CLList::MoveToTail() {
|
||||
CLList *pTail = getTail();
|
||||
assert(pTail != nullptr);
|
||||
|
||||
if (this != pTail) {
|
||||
Delete();
|
||||
pTail->addToTail(this);
|
||||
}
|
||||
}
|
||||
|
||||
void CLList::MoveLeft() {
|
||||
if (_pPrev != nullptr) {
|
||||
|
||||
CLList *pPrev = _pPrev->getPrev();
|
||||
if (pPrev != nullptr) {
|
||||
Delete();
|
||||
pPrev->Insert(this);
|
||||
} else {
|
||||
MoveToHead();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CLList::MoveRight() {
|
||||
CLList *pNext = _pNext;
|
||||
|
||||
if (pNext != nullptr) {
|
||||
|
||||
this->Delete();
|
||||
pNext->Insert(this);
|
||||
}
|
||||
}
|
||||
|
||||
void CLList::FlushList() {
|
||||
|
||||
CLList *pList = getHead();
|
||||
|
||||
// Something is wrong if the head is invalid
|
||||
assert(pList != nullptr);
|
||||
|
||||
while (pList != nullptr) {
|
||||
CLList *pTmpList = pList->_pNext;
|
||||
|
||||
// Don't delete myself
|
||||
if (pList != this)
|
||||
delete pList;
|
||||
|
||||
pList = pTmpList;
|
||||
}
|
||||
}
|
||||
|
||||
CLList *CLList::getHead() {
|
||||
CLList *pList = this;
|
||||
while (pList->_pPrev != nullptr)
|
||||
pList = pList->_pPrev;
|
||||
|
||||
return pList;
|
||||
}
|
||||
|
||||
CLList *CLList::getTail() {
|
||||
CLList *pList = this;
|
||||
while (pList->_pNext != nullptr)
|
||||
pList = pList->_pNext;
|
||||
|
||||
return pList;
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
136
engines/bagel/boflib/llist.h
Normal file
136
engines/bagel/boflib/llist.h
Normal file
@@ -0,0 +1,136 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_LLIST_H
|
||||
#define BAGEL_BOFLIB_LLIST_H
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
/**
|
||||
* Linked list class
|
||||
*/
|
||||
class CLList {
|
||||
protected:
|
||||
CLList *_pPrev; // Pointer to next link in chain
|
||||
CLList *_pNext; // Pointer to previous link in chain
|
||||
void *_pData; // Pointer to owning CData
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
CLList();
|
||||
|
||||
/**
|
||||
* Alternate constructor that initializes with specified data
|
||||
*/
|
||||
CLList(void *pObj);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~CLList();
|
||||
|
||||
/**
|
||||
* Links specified node to current list after current node
|
||||
* @remarks This will link a new list into the current right after the current node
|
||||
* @param pNewList Pointer to list to be inserted
|
||||
*/
|
||||
void Insert(CLList *pNewList);
|
||||
|
||||
/**
|
||||
* Deletes current node
|
||||
*/
|
||||
void Delete();
|
||||
|
||||
/**
|
||||
* Links specified node to head of list
|
||||
* @remarks This can be used to link 2 lists together by Linking the
|
||||
* tail of one list to the head of another
|
||||
* @param pNewList New list to link to head of current list
|
||||
*/
|
||||
void addToHead(CLList *pNewList);
|
||||
|
||||
/**
|
||||
* Links specified node to tail of current list
|
||||
* @remarks This can be used to link 2 lists together by Linking the
|
||||
* head of one list to the tail of another
|
||||
* @param pNewList Pointer to new list
|
||||
*/
|
||||
void addToTail(CLList *pNewList);
|
||||
|
||||
/**
|
||||
* Moves this item to the head of the linked list
|
||||
*/
|
||||
void MoveToHead();
|
||||
|
||||
/**
|
||||
* Moves this item to the tail of the linked list
|
||||
*/
|
||||
void MoveToTail();
|
||||
|
||||
/**
|
||||
* Moves this item 1 item to the left
|
||||
*/
|
||||
void MoveLeft();
|
||||
|
||||
/**
|
||||
* Moves this item 1 item to the right
|
||||
*/
|
||||
void MoveRight();
|
||||
|
||||
/**
|
||||
* Returns head of current list
|
||||
* @return Pointer to head of list
|
||||
*/
|
||||
CLList *getHead();
|
||||
|
||||
/**
|
||||
* Returns tail of current list
|
||||
* @return Pointer to tail of list
|
||||
*/
|
||||
CLList *getTail();
|
||||
CLList *getPrev() const {
|
||||
return _pPrev;
|
||||
}
|
||||
|
||||
CLList *getNext() const {
|
||||
return _pNext;
|
||||
}
|
||||
|
||||
void *getData() const {
|
||||
return _pData;
|
||||
}
|
||||
|
||||
void PutData(void *pObj) {
|
||||
_pData = pObj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes entire list
|
||||
*/
|
||||
void FlushList();
|
||||
};
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
69
engines/bagel/boflib/log.cpp
Normal file
69
engines/bagel/boflib/log.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/* 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/system.h"
|
||||
#include "common/savefile.h"
|
||||
#include "common/debug.h"
|
||||
#include "bagel/boflib/log.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
static const char *const g_pszLogTypes[4] = {
|
||||
"Fatal Error: ",
|
||||
"Error: ",
|
||||
"Warning: ",
|
||||
""
|
||||
};
|
||||
|
||||
void logInfo(const char *msg) {
|
||||
if (gDebugLevel > 0)
|
||||
debug("%s", msg);
|
||||
}
|
||||
|
||||
void logWarning(const char *msg) {
|
||||
if (gDebugLevel > 0)
|
||||
debug("%s%s", g_pszLogTypes[2], msg);
|
||||
}
|
||||
|
||||
void logError(const char *msg) {
|
||||
if (gDebugLevel > 0)
|
||||
debug("%s%s", g_pszLogTypes[1], msg);
|
||||
}
|
||||
|
||||
const char *buildString(const char *pszFormat, ...) {
|
||||
static char szBuf[256];
|
||||
va_list argptr;
|
||||
|
||||
assert(pszFormat != nullptr);
|
||||
|
||||
if (pszFormat != nullptr) {
|
||||
// Parse the variable argument list
|
||||
va_start(argptr, pszFormat);
|
||||
Common::vsprintf_s(szBuf, pszFormat, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
return (const char *)&szBuf[0];
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
40
engines/bagel/boflib/log.h
Normal file
40
engines/bagel/boflib/log.h
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_LOG_H
|
||||
#define BAGEL_BOFLIB_LOG_H
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
/**
|
||||
* Builds a string like sprintf()
|
||||
* @return Pointer to new (temporary) buffer.
|
||||
*/
|
||||
const char *buildString(const char *pszFormat, ...);
|
||||
|
||||
extern void logInfo(const char *msg);
|
||||
extern void logWarning(const char *msg);
|
||||
extern void logError(const char *msg);
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
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
|
||||
124
engines/bagel/boflib/misc.h
Normal file
124
engines/bagel/boflib/misc.h
Normal file
@@ -0,0 +1,124 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_MISC_H
|
||||
#define BAGEL_BOFLIB_MISC_H
|
||||
|
||||
#include "bagel/boflib/stdinc.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
extern int mapWindowsPointSize(int pointSize);
|
||||
|
||||
/**
|
||||
* Starts a Millisecond timer
|
||||
*/
|
||||
extern void timerStart();
|
||||
|
||||
/**
|
||||
* Stops the timer started by timerStart, returns time elapsed.
|
||||
* @return Number of MilliSeconds elapsed since call to timerStart
|
||||
*/
|
||||
extern uint32 timerStop();
|
||||
|
||||
/**
|
||||
* Returns the current elapsed time in milliseconds
|
||||
*/
|
||||
extern uint32 getTimer();
|
||||
|
||||
/**
|
||||
* Pauses the computer for specified number of MilliSeconds
|
||||
* @param milli Number of milliseconds
|
||||
*/
|
||||
extern void bofSleep(uint32 milli);
|
||||
|
||||
extern Fixed fixedDivide(Fixed Dividend, Fixed Divisor);
|
||||
extern Fixed fixedMultiply(Fixed Multiplicand, Fixed Multiplier);
|
||||
|
||||
#define intToFixed(i) (Fixed)(((long)(i)) << 16)
|
||||
#define fixedToInt(f) (int)(((long)(f)) >> 16)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Memory allocation routines (Should be put into their own MEMORY module)
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/**
|
||||
* Allocates a memory block of specified size
|
||||
* @param nSize Number of bytes to allocate
|
||||
* @param pFile Source file name
|
||||
* @param nLine Source file line number
|
||||
* @param bClear true if buffer should be cleared
|
||||
* @return Pointer to new buffer
|
||||
*/
|
||||
extern void *bofMemAlloc(uint32 nSize, const char *pFile, int nLine, bool bClear);
|
||||
|
||||
/**
|
||||
* Frees specified memory block
|
||||
* @param pBuf Buffer to de-allocate
|
||||
**/
|
||||
extern void bofMemFree(void *pBuf);
|
||||
|
||||
#define bofAlloc(n) bofMemAlloc((n), __FILE__, __LINE__, false)
|
||||
#define bofCleanAlloc(n) bofMemAlloc((n), __FILE__, __LINE__, true)
|
||||
#define bofFree(p) bofMemFree((p))
|
||||
|
||||
inline uint32 getFreePhysMem() {
|
||||
return 999999;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts specified buffer
|
||||
* @param pBuf Buffer to encrypt
|
||||
* @param lSize Number of bytes in buffer
|
||||
* @param pszPassword Optional password to encrypt with
|
||||
*/
|
||||
void encrypt(void *pBuf, int32 lSize, const char *pszPassword = nullptr);
|
||||
#define decrypt encrypt
|
||||
#define Decrypt encrypt
|
||||
|
||||
extern void encryptPartial(void *, int32, int32, const char *pPassword = nullptr);
|
||||
#define decryptPartial encryptPartial
|
||||
|
||||
/**
|
||||
* Return a true / false based on the probability given
|
||||
* @param nProbability The probability of returning a true
|
||||
* @returns True/false result
|
||||
**/
|
||||
extern bool ProbableTrue(int nProbability);
|
||||
|
||||
extern void ErrorLog(const char *logFile, const char *format, ...);
|
||||
|
||||
extern int StrFreqMatch(const char *, const char *);
|
||||
extern bool StrCompare(const char *, const char *, unsigned int);
|
||||
extern int StrCharCount(const char *, char);
|
||||
extern char *StriStr(char *, const char *);
|
||||
extern void StrUprStr(char *, const char *);
|
||||
extern void StrCpyStripChar(char *, const char *, char);
|
||||
extern char *StrStripChar(char *, char);
|
||||
extern char *StrReplaceChar(char *, char, char);
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
40
engines/bagel/boflib/object.h
Normal file
40
engines/bagel/boflib/object.h
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_OBJECT_H
|
||||
#define BAGEL_BOFLIB_OBJECT_H
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
class CBofObject {
|
||||
public:
|
||||
virtual ~CBofObject() {}
|
||||
static bool isValidObject(const CBofObject *pObject) {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void DeleteObject() {}
|
||||
};
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
161
engines/bagel/boflib/palette.cpp
Normal file
161
engines/bagel/boflib/palette.cpp
Normal file
@@ -0,0 +1,161 @@
|
||||
/* 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 "graphics/palette.h"
|
||||
#include "image/bmp.h"
|
||||
#include "bagel/boflib/palette.h"
|
||||
#include "bagel/spacebar/boflib/app.h"
|
||||
#include "bagel/spacebar/boflib/file.h"
|
||||
#include "bagel/boflib/file_functions.h"
|
||||
|
||||
namespace Bagel {
|
||||
namespace SpaceBar {
|
||||
|
||||
CBofPalette *CBofPalette::_pSharedPalette;
|
||||
char CBofPalette::_szSharedPalFile[MAX_FNAME];
|
||||
|
||||
PaletteData::PaletteData(int16 numColors) : _numColors(numColors) {
|
||||
Common::fill(&_data[0], &_data[Graphics::PALETTE_SIZE], 0);
|
||||
}
|
||||
|
||||
void CBofPalette::initialize() {
|
||||
_pSharedPalette = nullptr;
|
||||
_szSharedPalFile[0] = '\0';
|
||||
}
|
||||
|
||||
CBofPalette::CBofPalette() {
|
||||
Common::fill(&_palette._data[0], &_palette._data[Graphics::PALETTE_SIZE], 0);
|
||||
}
|
||||
|
||||
CBofPalette::CBofPalette(const char *pszFileName) {
|
||||
Common::fill(&_palette._data[0], &_palette._data[Graphics::PALETTE_SIZE], 0);
|
||||
assert(pszFileName != nullptr);
|
||||
|
||||
loadPalette(pszFileName);
|
||||
}
|
||||
|
||||
CBofPalette::CBofPalette(const PaletteData &paletteData) {
|
||||
_palette = paletteData;
|
||||
}
|
||||
|
||||
CBofPalette::~CBofPalette() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// If we trash the games palette, then reset it back to nullptr.
|
||||
CBofApp *pApp = CBofApp::getApp();
|
||||
if (pApp != nullptr) {
|
||||
if (this == pApp->getPalette()) {
|
||||
pApp->setPalette(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
ReleasePalette();
|
||||
}
|
||||
|
||||
void CBofPalette::setPalette(const PaletteData &PaletteData) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
ReleasePalette();
|
||||
_palette = PaletteData;
|
||||
}
|
||||
|
||||
ErrorCode CBofPalette::loadPalette(const char *pszFileName, uint16 nFlags) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// Validate input
|
||||
assert(pszFileName != nullptr);
|
||||
|
||||
ReleasePalette();
|
||||
|
||||
// Load in new bitmap file to get the palette
|
||||
Common::File f;
|
||||
Image::BitmapDecoder decoder;
|
||||
|
||||
if (f.open(pszFileName) && decoder.loadStream(f)) {
|
||||
// Copy the palette
|
||||
const Graphics::Palette &pal = decoder.getPalette();
|
||||
_palette._numColors = pal.size();
|
||||
pal.grab(_palette._data, 0, pal.size());
|
||||
|
||||
_errCode = ERR_NONE;
|
||||
|
||||
} else {
|
||||
_errCode = ERR_FREAD;
|
||||
}
|
||||
|
||||
return _errCode;
|
||||
}
|
||||
|
||||
void CBofPalette::ReleasePalette() {
|
||||
Common::fill(_palette._data, _palette._data + Graphics::PALETTE_SIZE, 0);
|
||||
}
|
||||
|
||||
CBofPalette *CBofPalette::copyPalette() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
byte CBofPalette::getNearestIndex(COLORREF stRGB) {
|
||||
Graphics::PaletteLookup lookup(_palette._data, Graphics::PALETTE_COUNT);
|
||||
return lookup.findBestColor(GetRed(stRGB), GetGreen(stRGB), GetBlue(stRGB));
|
||||
}
|
||||
|
||||
COLORREF CBofPalette::getColor(byte nIndex) {
|
||||
const byte *rgb = &_palette._data[nIndex * 3];
|
||||
|
||||
COLORREF cColor = RGB(rgb[0], rgb[1], rgb[2]);
|
||||
return cColor;
|
||||
}
|
||||
|
||||
ErrorCode CBofPalette::createDefault(uint16 nFlags) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
byte *pal = _palette._data;
|
||||
for (int i = 0; i < 256; ++i, pal += 3)
|
||||
pal[0] = pal[1] = pal[2] = (byte)i;
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
ErrorCode CBofPalette::setSharedPalette(const char *pszFileName) {
|
||||
delete _pSharedPalette;
|
||||
_pSharedPalette = nullptr;
|
||||
|
||||
// Save name of file used to get the shared palette
|
||||
if (pszFileName != nullptr) {
|
||||
Common::strcpy_s(_szSharedPalFile, pszFileName);
|
||||
}
|
||||
|
||||
return ERR_NONE;
|
||||
}
|
||||
|
||||
CBofPalette *CBofPalette::getSharedPalette() {
|
||||
// Do we need to load the shared palette?
|
||||
if (_pSharedPalette == nullptr && fileExists(_szSharedPalFile))
|
||||
_pSharedPalette = new CBofPalette(_szSharedPalFile);
|
||||
|
||||
return _pSharedPalette;
|
||||
}
|
||||
|
||||
} // namespace SpaceBar
|
||||
} // namespace Bagel
|
||||
153
engines/bagel/boflib/palette.h
Normal file
153
engines/bagel/boflib/palette.h
Normal file
@@ -0,0 +1,153 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_GFX_PALETTE_H
|
||||
#define BAGEL_BOFLIB_GFX_PALETTE_H
|
||||
|
||||
#include "graphics/palette.h"
|
||||
#include "bagel/afxwin.h"
|
||||
#include "bagel/boflib/error.h"
|
||||
#include "bagel/boflib/object.h"
|
||||
#include "bagel/boflib/stdinc.h"
|
||||
|
||||
namespace Bagel {
|
||||
namespace SpaceBar {
|
||||
|
||||
struct PaletteData {
|
||||
byte _data[Graphics::PALETTE_SIZE];
|
||||
int16 _numColors;
|
||||
PaletteData(int16 numColors = Graphics::PALETTE_COUNT);
|
||||
};
|
||||
|
||||
struct PALETTEENTRY {
|
||||
byte peRed;
|
||||
byte peGreen;
|
||||
byte peBlue;
|
||||
byte peFlags;
|
||||
};
|
||||
struct LOGPALETTE {
|
||||
int16 palNumEntries;
|
||||
int16 palVersion;
|
||||
PALETTEENTRY palPalEntry[1];
|
||||
};
|
||||
|
||||
struct BOFRGBQUAD {
|
||||
byte rgbBlue;
|
||||
byte rgbGreen;
|
||||
byte rgbRed;
|
||||
byte rgbReserved;
|
||||
};
|
||||
|
||||
#define GetRed(rgb) ((byte)((rgb) & 0x000000FF))
|
||||
#define GetGreen(rgb) ((byte)(((rgb) >> 8) & 0x000000FF))
|
||||
#define GetBlue(rgb) ((byte)(((rgb) >> 16) & 0x000000FF))
|
||||
|
||||
class CBofPalette : public CBofError, public CBofObject {
|
||||
protected:
|
||||
PaletteData _palette;
|
||||
|
||||
static CBofPalette *_pSharedPalette;
|
||||
static char _szSharedPalFile[MAX_FNAME];
|
||||
|
||||
/**
|
||||
* Deletes internal palette info
|
||||
*/
|
||||
void ReleasePalette();
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
CBofPalette();
|
||||
|
||||
/**
|
||||
* Constructor that loads a palette from a file
|
||||
* @param pszFileName filename
|
||||
*/
|
||||
CBofPalette(const char *pszFileName);
|
||||
|
||||
/**
|
||||
* Constructor that takes in an existing palette
|
||||
*/
|
||||
CBofPalette(const PaletteData &paletteData);
|
||||
|
||||
/**
|
||||
* Loads palette from specified bitmap-file
|
||||
* @param pszFileName Name of file to load palette from
|
||||
* @param nFlags Flags for animation, etc...
|
||||
* @return Error return Code
|
||||
*/
|
||||
ErrorCode loadPalette(const char *pszFileName, uint16 nFlags = PAL_DEFAULT);
|
||||
|
||||
ErrorCode createDefault(uint16 nFlags = PAL_DEFAULT);
|
||||
|
||||
byte getNearestIndex(COLORREF cColor);
|
||||
|
||||
COLORREF getColor(byte nIndex);
|
||||
|
||||
/**
|
||||
* Assigns specified palette to this CBofPalette
|
||||
* @param PaletteData Handle to windows palette
|
||||
*/
|
||||
void setPalette(const PaletteData &PaletteData);
|
||||
|
||||
const PaletteData &getPalette() const {
|
||||
return _palette;
|
||||
}
|
||||
|
||||
const byte *getData() const {
|
||||
return _palette._data;
|
||||
}
|
||||
|
||||
void setData(const byte* colors) {
|
||||
memcpy(_palette._data, colors, Graphics::PALETTE_SIZE);
|
||||
}
|
||||
|
||||
virtual ~CBofPalette();
|
||||
|
||||
/**
|
||||
* Create a new palette based on current palette
|
||||
*/
|
||||
CBofPalette *copyPalette();
|
||||
|
||||
/**
|
||||
* initialize static class fields
|
||||
*/
|
||||
static void initialize();
|
||||
|
||||
/**
|
||||
* Called only in response to "SHAREDPAL=filename" in a script file
|
||||
* @param pszFileName Palette filename
|
||||
*/
|
||||
static ErrorCode setSharedPalette(const char *pszFileName);
|
||||
|
||||
/**
|
||||
* Returns the current shared palette
|
||||
* @return Pointer to shared palette
|
||||
*/
|
||||
static CBofPalette *getSharedPalette();
|
||||
};
|
||||
|
||||
} // namespace SpaceBar
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
254
engines/bagel/boflib/point.h
Normal file
254
engines/bagel/boflib/point.h
Normal file
@@ -0,0 +1,254 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_POINT_H
|
||||
#define BAGEL_BOFLIB_POINT_H
|
||||
|
||||
#include "bagel/afxwin.h"
|
||||
#include "bagel/boflib/stdinc.h"
|
||||
#include "bagel/boflib/object.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
class CBofPoint : public StPoint, public CBofObject {
|
||||
public:
|
||||
// Constructors
|
||||
CBofPoint();
|
||||
CBofPoint(int initX, int initY);
|
||||
CBofPoint(StPoint stPoint);
|
||||
CBofPoint(const CBofPoint &cPoint);
|
||||
CBofPoint(const StSize &stSize);
|
||||
CBofPoint(const Common::Point &pt);
|
||||
|
||||
CBofPoint(const POINT &stPoint) {
|
||||
setWinPoint(&stPoint);
|
||||
}
|
||||
virtual ~CBofPoint() {
|
||||
}
|
||||
|
||||
void setWinPoint(const POINT *pPoint);
|
||||
POINT GetWinPoint() const;
|
||||
|
||||
void operator=(const POINT &stPoint) {
|
||||
setWinPoint(&stPoint);
|
||||
}
|
||||
|
||||
operator const POINT() {
|
||||
return GetWinPoint();
|
||||
}
|
||||
|
||||
|
||||
// Operations
|
||||
void offset(int xOffset, int yOffset);
|
||||
void offset(StPoint point);
|
||||
void offset(StSize size);
|
||||
void operator=(const StPoint &point);
|
||||
void operator=(const CBofPoint &point);
|
||||
bool operator==(StPoint point) const;
|
||||
bool operator!=(StPoint point) const;
|
||||
void operator+=(StSize size);
|
||||
void operator-=(StSize size);
|
||||
void operator+=(StPoint point);
|
||||
void operator-=(StPoint point);
|
||||
|
||||
// Operators returning CBofPoint values
|
||||
CBofPoint operator+(StSize size) const;
|
||||
CBofPoint operator+(StPoint point) const;
|
||||
CBofPoint operator-(StSize size) const;
|
||||
CBofPoint operator-(StPoint point) const;
|
||||
CBofPoint operator-() const;
|
||||
};
|
||||
|
||||
// CBofPoint
|
||||
inline CBofPoint::CBofPoint() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
}
|
||||
|
||||
inline CBofPoint::CBofPoint(const int initX, const int initY) {
|
||||
x = initX;
|
||||
y = initY;
|
||||
}
|
||||
|
||||
inline CBofPoint::CBofPoint(const StPoint stPoint) {
|
||||
x = stPoint.x;
|
||||
y = stPoint.y;
|
||||
}
|
||||
|
||||
inline CBofPoint::CBofPoint(const StSize &stSize) {
|
||||
x = stSize.cx;
|
||||
y = stSize.cy;
|
||||
}
|
||||
|
||||
inline CBofPoint::CBofPoint(const CBofPoint &cPoint) {
|
||||
x = cPoint.x;
|
||||
y = cPoint.y;
|
||||
}
|
||||
|
||||
inline CBofPoint::CBofPoint(const Common::Point &pt) {
|
||||
x = pt.x;
|
||||
y = pt.y;
|
||||
}
|
||||
|
||||
inline void CBofPoint::setWinPoint(const POINT *pPoint) {
|
||||
assert(pPoint != nullptr);
|
||||
assert(isValidObject(this));
|
||||
|
||||
x = pPoint->x;
|
||||
y = pPoint->y;
|
||||
}
|
||||
|
||||
inline POINT CBofPoint::GetWinPoint() const {
|
||||
assert(isValidObject(this));
|
||||
|
||||
POINT stPoint;
|
||||
|
||||
stPoint.x = x;
|
||||
stPoint.y = y;
|
||||
|
||||
return stPoint;
|
||||
}
|
||||
|
||||
inline void CBofPoint::offset(int xOffset, int yOffset) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x += xOffset;
|
||||
y += yOffset;
|
||||
}
|
||||
|
||||
inline void CBofPoint::offset(StPoint point) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x += point.x;
|
||||
y += point.y;
|
||||
}
|
||||
|
||||
inline void CBofPoint::offset(StSize size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x += size.cx;
|
||||
y += size.cy;
|
||||
}
|
||||
|
||||
inline void CBofPoint::operator=(const StPoint &point) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x = point.x;
|
||||
y = point.y;
|
||||
}
|
||||
|
||||
inline void CBofPoint::operator=(const CBofPoint &point) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x = point.x;
|
||||
y = point.y;
|
||||
}
|
||||
|
||||
inline bool CBofPoint::operator==(StPoint point) const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (x == point.x && y == point.y);
|
||||
}
|
||||
|
||||
inline bool CBofPoint::operator!=(StPoint point) const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (x != point.x || y != point.y);
|
||||
}
|
||||
|
||||
inline void CBofPoint::operator+=(StSize size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x += size.cx;
|
||||
y += size.cy;
|
||||
}
|
||||
|
||||
inline void CBofPoint::operator+=(StPoint point) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x += point.x;
|
||||
y += point.y;
|
||||
}
|
||||
|
||||
inline void CBofPoint::operator-=(StPoint point) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x -= point.x;
|
||||
y -= point.y;
|
||||
}
|
||||
|
||||
inline void CBofPoint::operator-=(StSize size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
x -= size.cx;
|
||||
y -= size.cy;
|
||||
}
|
||||
|
||||
inline CBofPoint CBofPoint::operator+(StSize size) const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(x + size.cx, y + size.cy);
|
||||
}
|
||||
|
||||
inline CBofPoint CBofPoint::operator+(StPoint point) const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(x + point.x, y + point.y);
|
||||
}
|
||||
|
||||
inline CBofPoint CBofPoint::operator-(StSize size) const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(x - size.cx, y - size.cy);
|
||||
}
|
||||
|
||||
inline CBofPoint CBofPoint::operator-(StPoint point) const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(x - point.x, y - point.y);
|
||||
}
|
||||
|
||||
inline CBofPoint CBofPoint::operator-() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(-x, -y);
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
113
engines/bagel/boflib/queue.cpp
Normal file
113
engines/bagel/boflib/queue.cpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/* 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 "bagel/boflib/queue.h"
|
||||
#include "bagel/boflib/stdinc.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
CQueue::CQueue() {
|
||||
}
|
||||
|
||||
CQueue::~CQueue() {
|
||||
// Can't destruct if we don't exist
|
||||
assert(isValidObject(this));
|
||||
|
||||
while (removeItem() != nullptr) {
|
||||
}
|
||||
|
||||
// remove() must set _pQueueList to nullptr when it removes the last item
|
||||
assert(_pQueueList == nullptr);
|
||||
}
|
||||
|
||||
void CQueue::addItem(void *pObject) {
|
||||
// Make sure this object exists
|
||||
assert(isValidObject(this));
|
||||
|
||||
CLList *pNewItem = new CLList(pObject);
|
||||
if (_pQueueList != nullptr) {
|
||||
_pQueueList->addToTail(pNewItem);
|
||||
} else {
|
||||
_pQueueList = pNewItem;
|
||||
}
|
||||
|
||||
assert(pNewItem->getHead() == _pQueueList);
|
||||
}
|
||||
|
||||
void *CQueue::removeItem() {
|
||||
// Make sure this object exists
|
||||
assert(isValidObject(this));
|
||||
|
||||
// Assume empty list
|
||||
void *pObject = nullptr;
|
||||
|
||||
CLList *pList = _pQueueList;
|
||||
if (pList != nullptr) {
|
||||
pObject = pList->getData();
|
||||
|
||||
_pQueueList = pList->getNext();
|
||||
delete pList;
|
||||
}
|
||||
|
||||
return pObject;
|
||||
}
|
||||
|
||||
void CQueue::deleteItem(void *pItem) {
|
||||
// Make sure this object exists
|
||||
assert(isValidObject(this));
|
||||
assert(pItem != nullptr);
|
||||
|
||||
CLList *pList = _pQueueList;
|
||||
while (pList != nullptr) {
|
||||
CLList *pNext = pList->getNext();
|
||||
|
||||
if (pItem == pList->getData()) {
|
||||
// If this is the 1st item in the Queue, then move head
|
||||
if (pList == _pQueueList)
|
||||
_pQueueList = _pQueueList->getNext();
|
||||
|
||||
delete pList;
|
||||
break;
|
||||
}
|
||||
|
||||
pList = pNext;
|
||||
}
|
||||
}
|
||||
|
||||
void *CQueue::getQItem() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
void *pItem = nullptr;
|
||||
if (_pQueueList != nullptr) {
|
||||
pItem = _pQueueList->getData();
|
||||
}
|
||||
|
||||
return pItem;
|
||||
}
|
||||
|
||||
void CQueue::flush() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
while (removeItem() != nullptr) {
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
78
engines/bagel/boflib/queue.h
Normal file
78
engines/bagel/boflib/queue.h
Normal file
@@ -0,0 +1,78 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_QUEUE_H
|
||||
#define BAGEL_BOFLIB_QUEUE_H
|
||||
|
||||
#include "bagel/boflib/object.h"
|
||||
#include "bagel/boflib/llist.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
class CQueue : public CBofObject {
|
||||
protected:
|
||||
CLList *_pQueueList = nullptr;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
CQueue();
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~CQueue();
|
||||
|
||||
/**
|
||||
* Pushes object onto stack
|
||||
* @param pObject Pointer to object to be pushed
|
||||
*/
|
||||
void addItem(void *pObject);
|
||||
|
||||
/**
|
||||
* Removes 1 object off stack
|
||||
* @return Pointer to top object on stack
|
||||
*/
|
||||
void *removeItem();
|
||||
|
||||
/**
|
||||
* Retrieves the 1st item (FIFO order) without removing it.
|
||||
* @return 1st item in Queue (or nullptr is Queue is empty)
|
||||
*/
|
||||
void *getQItem();
|
||||
|
||||
/**
|
||||
* Deletes specified item from the QUEUE (Illegally)
|
||||
* @param pObject Object to remove
|
||||
*/
|
||||
void deleteItem(void *pObject);
|
||||
|
||||
/**
|
||||
* Removes all items from the queue
|
||||
*/
|
||||
void flush();
|
||||
};
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
455
engines/bagel/boflib/rect.h
Normal file
455
engines/bagel/boflib/rect.h
Normal file
@@ -0,0 +1,455 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_RECT_H
|
||||
#define BAGEL_BOFLIB_RECT_H
|
||||
|
||||
#include "common/rect.h"
|
||||
#include "bagel/afxwin.h"
|
||||
#include "bagel/boflib/stdinc.h"
|
||||
#include "bagel/boflib/object.h"
|
||||
#include "bagel/boflib/point.h"
|
||||
#include "bagel/boflib/size.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
class CBofRect : public CBofObject {
|
||||
public:
|
||||
// Constructors
|
||||
CBofRect();
|
||||
CBofRect(int l, int t, int r, int b);
|
||||
CBofRect(const CBofRect &srcRect);
|
||||
CBofRect(const CBofPoint &point, const CBofSize &size);
|
||||
CBofRect(const CBofPoint &pttopLeft, const CBofPoint &ptBottomRight);
|
||||
virtual ~CBofRect() {
|
||||
}
|
||||
|
||||
// Attributes
|
||||
int width() const;
|
||||
int height() const;
|
||||
CBofSize size() const;
|
||||
CBofPoint topLeft() const;
|
||||
CBofPoint bottomRight() const;
|
||||
|
||||
CBofPoint topRight() const;
|
||||
CBofPoint bottomLeft() const;
|
||||
|
||||
bool isRectEmpty() const;
|
||||
bool isRectNull() const;
|
||||
bool ptInRect(const CBofPoint &point) const;
|
||||
|
||||
// Operations
|
||||
|
||||
inline void setRect(int x1, int y1, int x2, int y2);
|
||||
void setRectEmpty();
|
||||
void copyRect(const CBofRect &cRect);
|
||||
bool equalRect(const CBofRect &cRect);
|
||||
|
||||
CBofRect(const RECT &cRect) {
|
||||
setWinRect(&cRect);
|
||||
}
|
||||
CBofRect(const RECT *pRect) {
|
||||
setWinRect(pRect);
|
||||
}
|
||||
|
||||
void setWinRect(const RECT *pRect);
|
||||
RECT getWinRect();
|
||||
|
||||
void operator=(const RECT &srcRect) {
|
||||
setWinRect(&srcRect);
|
||||
}
|
||||
void operator=(const Common::Rect &srcRect) {
|
||||
const RECT r = { srcRect.left, srcRect.top, srcRect.right, srcRect.bottom };
|
||||
setWinRect(&r);
|
||||
}
|
||||
|
||||
operator const RECT() {
|
||||
return getWinRect();
|
||||
}
|
||||
operator const Common::Rect() {
|
||||
return Common::Rect(left, top, right, bottom);
|
||||
}
|
||||
|
||||
void offsetRect(int x, int y);
|
||||
void offsetRect(const CBofSize &size);
|
||||
void offsetRect(const CBofPoint &point);
|
||||
|
||||
// Operations that fill '*this' with result
|
||||
bool intersectRect(const CBofRect *pRect1, const CBofRect *pRect2);
|
||||
bool intersectRect(const CBofRect &cRect1, const CBofRect &cRect2);
|
||||
bool unionRect(const CBofRect *pRect1, const CBofRect *pRect2);
|
||||
|
||||
// Additional Operations
|
||||
void operator=(const CBofRect &srcRect);
|
||||
bool operator==(const CBofRect &rect);
|
||||
bool operator!=(const CBofRect &rect);
|
||||
void operator+=(const CBofPoint &point);
|
||||
void operator-=(const CBofPoint &point);
|
||||
void operator&=(const CBofRect &rect);
|
||||
void operator|=(const CBofRect &rect);
|
||||
|
||||
// Operators returning CBofRect values
|
||||
CBofRect operator+(const CBofPoint &point);
|
||||
CBofRect operator-(const CBofPoint &point);
|
||||
CBofRect operator&(const CBofRect &rect2);
|
||||
CBofRect operator|(const CBofRect &rect2);
|
||||
|
||||
int left;
|
||||
int top;
|
||||
int right;
|
||||
int bottom;
|
||||
};
|
||||
|
||||
inline CBofRect::CBofRect() {
|
||||
top = left = 0;
|
||||
right = bottom = -1;
|
||||
}
|
||||
|
||||
inline CBofRect::CBofRect(int l, int t, int r, int b) {
|
||||
left = l;
|
||||
top = t;
|
||||
right = r;
|
||||
bottom = b;
|
||||
}
|
||||
|
||||
inline CBofRect::CBofRect(const CBofRect &srcRect) {
|
||||
left = srcRect.left;
|
||||
top = srcRect.top;
|
||||
right = srcRect.right;
|
||||
bottom = srcRect.bottom;
|
||||
}
|
||||
|
||||
inline CBofRect::CBofRect(const CBofPoint &point, const CBofSize &size) {
|
||||
right = (left = point.x) + size.cx - 1;
|
||||
bottom = (top = point.y) + size.cy - 1;
|
||||
}
|
||||
|
||||
inline CBofRect::CBofRect(const CBofPoint &pttopLeft, const CBofPoint &ptBottomRight) {
|
||||
setRect(pttopLeft.x, pttopLeft.y, ptBottomRight.x, ptBottomRight.y);
|
||||
}
|
||||
|
||||
inline int CBofRect::width() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return right - left + 1;
|
||||
}
|
||||
|
||||
inline int CBofRect::height() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return bottom - top + 1;
|
||||
}
|
||||
|
||||
inline CBofSize CBofRect::size() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofSize(width(), height());
|
||||
}
|
||||
|
||||
inline CBofPoint CBofRect::topLeft() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(left, top);
|
||||
}
|
||||
|
||||
inline CBofPoint CBofRect::bottomRight() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(right, bottom);
|
||||
}
|
||||
|
||||
inline CBofPoint CBofRect::topRight() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(right, top);
|
||||
}
|
||||
|
||||
inline CBofPoint CBofRect::bottomLeft() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofPoint(left, bottom);
|
||||
}
|
||||
|
||||
inline bool CBofRect::isRectEmpty() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (width() <= 0 || height() <= 0);
|
||||
}
|
||||
|
||||
inline bool CBofRect::isRectNull() const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (left == 0 && right == 0 && top == 0 && bottom == 0);
|
||||
}
|
||||
|
||||
inline bool CBofRect::ptInRect(const CBofPoint &point) const {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (point.x >= left && point.x <= right && point.y >= top && point.y <= bottom);
|
||||
}
|
||||
|
||||
inline void CBofRect::setRect(int x1, int y1, int x2, int y2) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
left = x1;
|
||||
top = y1;
|
||||
right = x2;
|
||||
bottom = y2;
|
||||
}
|
||||
|
||||
inline void CBofRect::setRectEmpty() {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
left = top = 0;
|
||||
right = bottom = -1;
|
||||
|
||||
// Verify that the rectangle is now empty
|
||||
assert(isRectEmpty());
|
||||
}
|
||||
|
||||
inline void CBofRect::copyRect(const CBofRect &cSrcRect) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
assert(isValidObject(&cSrcRect));
|
||||
|
||||
left = cSrcRect.left;
|
||||
right = cSrcRect.right;
|
||||
top = cSrcRect.top;
|
||||
bottom = cSrcRect.bottom;
|
||||
}
|
||||
|
||||
inline bool CBofRect::equalRect(const CBofRect &cRect) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
assert(isValidObject(&cRect));
|
||||
|
||||
return (left == cRect.left && right == cRect.right && top == cRect.top && bottom == cRect.bottom);
|
||||
}
|
||||
|
||||
inline RECT CBofRect::getWinRect() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
RECT stRect;
|
||||
|
||||
stRect.left = left;
|
||||
stRect.top = top;
|
||||
stRect.right = right + 1;
|
||||
stRect.bottom = bottom + 1;
|
||||
|
||||
return stRect;
|
||||
}
|
||||
|
||||
inline void CBofRect::setWinRect(const RECT *pRect) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
assert(pRect != nullptr);
|
||||
|
||||
left = pRect->left;
|
||||
top = pRect->top;
|
||||
right = pRect->right - 1;
|
||||
bottom = pRect->bottom - 1;
|
||||
}
|
||||
|
||||
inline void CBofRect::offsetRect(int x, int y) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
left += x;
|
||||
right += x;
|
||||
top += y;
|
||||
bottom += y;
|
||||
}
|
||||
|
||||
inline void CBofRect::offsetRect(const CBofPoint &point) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
left += point.x;
|
||||
right += point.x;
|
||||
top += point.y;
|
||||
bottom += point.y;
|
||||
}
|
||||
|
||||
inline void CBofRect::offsetRect(const CBofSize &size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
left += size.cx;
|
||||
right += size.cx;
|
||||
top += size.cy;
|
||||
bottom += size.cy;
|
||||
}
|
||||
|
||||
inline bool CBofRect::intersectRect(const CBofRect *pRect1, const CBofRect *pRect2) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
// Can't access null pointers
|
||||
assert(pRect1 != nullptr);
|
||||
assert(pRect2 != nullptr);
|
||||
|
||||
left = MAX(pRect1->left, pRect2->left);
|
||||
top = MAX(pRect1->top, pRect2->top);
|
||||
right = MIN(pRect1->right, pRect2->right);
|
||||
bottom = MIN(pRect1->bottom, pRect2->bottom);
|
||||
|
||||
return ((width() > 0) && (height() > 0));
|
||||
}
|
||||
|
||||
inline bool CBofRect::intersectRect(const CBofRect &cRect1, const CBofRect &cRect2) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return intersectRect(&cRect1, &cRect2);
|
||||
}
|
||||
|
||||
inline bool CBofRect::unionRect(const CBofRect *pRect1, const CBofRect *pRect2) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
// Can't access null pointers
|
||||
assert(pRect1 != nullptr);
|
||||
assert(pRect2 != nullptr);
|
||||
|
||||
left = MIN(pRect1->left, pRect2->left);
|
||||
top = MIN(pRect1->top, pRect2->top);
|
||||
right = MAX(pRect1->right, pRect2->right);
|
||||
bottom = MAX(pRect1->bottom, pRect2->bottom);
|
||||
|
||||
return isRectEmpty();
|
||||
}
|
||||
|
||||
inline void CBofRect::operator=(const CBofRect &srcRect) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
left = srcRect.left;
|
||||
right = srcRect.right;
|
||||
top = srcRect.top;
|
||||
bottom = srcRect.bottom;
|
||||
}
|
||||
|
||||
inline bool CBofRect::operator==(const CBofRect &rect) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (left == rect.left && right == rect.right &&
|
||||
top == rect.top && bottom == rect.bottom);
|
||||
}
|
||||
|
||||
inline bool CBofRect::operator!=(const CBofRect &rect) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (left != rect.left || right != rect.right ||
|
||||
top != rect.top || bottom != rect.bottom);
|
||||
}
|
||||
|
||||
inline void CBofRect::operator+=(const CBofPoint &point) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
offsetRect(point);
|
||||
}
|
||||
|
||||
inline void CBofRect::operator-=(const CBofPoint &point) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
offsetRect(-point.x, -point.y);
|
||||
}
|
||||
|
||||
inline void CBofRect::operator&=(const CBofRect &rect) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
intersectRect(this, &rect);
|
||||
}
|
||||
|
||||
inline void CBofRect::operator|=(const CBofRect &rect) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
unionRect(this, &rect);
|
||||
}
|
||||
|
||||
inline CBofRect CBofRect::operator+(const CBofPoint &pt) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
CBofRect rect(*this);
|
||||
|
||||
rect.offsetRect(pt.x, pt.y);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
inline CBofRect CBofRect::operator-(const CBofPoint &pt) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
CBofRect rect(*this);
|
||||
|
||||
rect.offsetRect(-pt.x, -pt.y);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
inline CBofRect CBofRect::operator&(const CBofRect &rect2) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
CBofRect rect;
|
||||
|
||||
rect.intersectRect(this, &rect2);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
inline CBofRect CBofRect::operator|(const CBofRect &rect2) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
CBofRect rect;
|
||||
|
||||
rect.unionRect(this, &rect2);
|
||||
|
||||
return rect;
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
139
engines/bagel/boflib/size.h
Normal file
139
engines/bagel/boflib/size.h
Normal file
@@ -0,0 +1,139 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_SIZE_H
|
||||
#define BAGEL_BOFLIB_SIZE_H
|
||||
|
||||
#include "bagel/afxwin.h"
|
||||
#include "bagel/boflib/stdinc.h"
|
||||
#include "bagel/boflib/object.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
class CBofSize : public SIZE, public CBofObject {
|
||||
public:
|
||||
// Constructors
|
||||
CBofSize();
|
||||
virtual ~CBofSize() {
|
||||
}
|
||||
CBofSize(int initCX, int initCY);
|
||||
CBofSize(const SIZE &stSize);
|
||||
CBofSize(const CBofSize &cSize);
|
||||
CBofSize(StPoint stPoint);
|
||||
|
||||
// Operations
|
||||
void operator=(const CBofSize &cSize);
|
||||
bool operator==(SIZE size);
|
||||
bool operator!=(SIZE size);
|
||||
void operator+=(SIZE size);
|
||||
void operator-=(SIZE size);
|
||||
|
||||
// Operators returning CBofSize values
|
||||
CBofSize operator+(SIZE size);
|
||||
CBofSize operator-(SIZE size);
|
||||
CBofSize operator-();
|
||||
};
|
||||
|
||||
// CBofSize
|
||||
inline CBofSize::CBofSize() {
|
||||
cx = cy = 0;
|
||||
}
|
||||
|
||||
inline CBofSize::CBofSize(int initCX, int initCY) {
|
||||
cx = initCX;
|
||||
cy = initCY;
|
||||
}
|
||||
|
||||
inline CBofSize::CBofSize(const SIZE &stSize) {
|
||||
cx = stSize.cx;
|
||||
cy = stSize.cy;
|
||||
}
|
||||
|
||||
inline CBofSize::CBofSize(const CBofSize &cSize) {
|
||||
cx = cSize.cx;
|
||||
cy = cSize.cy;
|
||||
}
|
||||
|
||||
inline CBofSize::CBofSize(StPoint stPoint) {
|
||||
cx = stPoint.x;
|
||||
cy = stPoint.y;
|
||||
}
|
||||
|
||||
inline void CBofSize::operator=(const CBofSize &cSize) {
|
||||
cx = cSize.cx;
|
||||
cy = cSize.cy;
|
||||
}
|
||||
|
||||
inline bool CBofSize::operator==(SIZE size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (cx == size.cx && cy == size.cy);
|
||||
}
|
||||
|
||||
inline bool CBofSize::operator!=(SIZE size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return (cx != size.cx || cy != size.cy);
|
||||
}
|
||||
|
||||
inline void CBofSize::operator+=(SIZE size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
cx += size.cx;
|
||||
cy += size.cy;
|
||||
}
|
||||
|
||||
inline void CBofSize::operator-=(SIZE size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
cx -= size.cx;
|
||||
cy -= size.cy;
|
||||
}
|
||||
|
||||
inline CBofSize CBofSize::operator+(SIZE size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofSize(cx + size.cx, cy + size.cy);
|
||||
}
|
||||
|
||||
inline CBofSize CBofSize::operator-(SIZE size) {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofSize(cx - size.cx, cy - size.cy);
|
||||
}
|
||||
|
||||
inline CBofSize CBofSize::operator-() {
|
||||
// Make sure object is not used after it is destructed
|
||||
assert(isValidObject(this));
|
||||
|
||||
return CBofSize(-cx, -cy);
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
959
engines/bagel/boflib/sound.cpp
Normal file
959
engines/bagel/boflib/sound.cpp
Normal file
@@ -0,0 +1,959 @@
|
||||
/* 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/system.h"
|
||||
#include "common/file.h"
|
||||
#include "common/memstream.h"
|
||||
#include "audio/mixer.h"
|
||||
#include "audio/audiostream.h"
|
||||
#include "audio/decoders/wave.h"
|
||||
|
||||
#include "bagel/bagel.h"
|
||||
#include "bagel/boflib/sound.h"
|
||||
#include "bagel/boflib/string_functions.h"
|
||||
#include "bagel/boflib/event_loop.h"
|
||||
#include "bagel/boflib/file_functions.h"
|
||||
#include "bagel/boflib/log.h"
|
||||
#include "bagel/music.h"
|
||||
//#include "bagel/spacebar/boflib/app.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
#define MEMORY_THRESHOLD 20000L
|
||||
#define MEMORY_MARGIN 100000L
|
||||
|
||||
char CBofSound::_szDrivePath[MAX_DIRPATH];
|
||||
CBofSound *CBofSound::_pSoundChain = nullptr; // Pointer to chain of linked Sounds
|
||||
int CBofSound::_nCount = 0; // Count of currently active Sounds
|
||||
int CBofSound::_nWavCount = 1; // Available wave sound devices
|
||||
int CBofSound::_nMidiCount = 1; // Available midi sound devices
|
||||
void *CBofSound::_pMainWnd = nullptr; // Window for message processing
|
||||
|
||||
bool CBofSound::_bInit = false;
|
||||
|
||||
CQueue *CBofSound::_cQueue[NUM_QUEUES];
|
||||
int CBofSound::_nSlotVol[NUM_QUEUES];
|
||||
|
||||
CBofSound::CBofSound() {
|
||||
_wLoops = 1;
|
||||
addToSoundChain();
|
||||
}
|
||||
|
||||
CBofSound::CBofSound(void *pWnd, const char *pszPathName, uint16 wFlags, const int nLoops) {
|
||||
_wLoops = (uint16)nLoops;
|
||||
initialize(pWnd, pszPathName, wFlags);
|
||||
addToSoundChain();
|
||||
}
|
||||
|
||||
void CBofSound::addToSoundChain() {
|
||||
// Insert this sound into the sound list
|
||||
if (_pSoundChain != nullptr) {
|
||||
_pSoundChain->Insert(this);
|
||||
|
||||
// _pSoundchain must always be the head of the list
|
||||
assert(_pSoundChain == _pSoundChain->getHead());
|
||||
} else {
|
||||
_pSoundChain = this;
|
||||
}
|
||||
}
|
||||
|
||||
void CBofSound::initialize(void *pWnd, const char *pszPathName, uint16 wFlags) {
|
||||
// Validate input
|
||||
assert(pszPathName != nullptr);
|
||||
assert(strlen(pszPathName) < MAX_FNAME);
|
||||
|
||||
//
|
||||
// Initialize data fields
|
||||
//
|
||||
|
||||
_pWnd = _pMainWnd;
|
||||
if (pWnd != nullptr) {
|
||||
_pWnd = pWnd;
|
||||
if (_pMainWnd == nullptr)
|
||||
_pMainWnd = pWnd;
|
||||
}
|
||||
|
||||
_bPlaying = false; // Not yet playing
|
||||
_bStarted = false;
|
||||
_wFlags = wFlags; // Flags for playing
|
||||
_bPaused = false; // Not suspended
|
||||
_bExtensionsUsed = false; // No extended flags used.
|
||||
_szFileName[0] = '\0';
|
||||
|
||||
_handle = {};
|
||||
_pFileBuf = nullptr;
|
||||
_nVol = VOLUME_INDEX_DEFAULT;
|
||||
_bInQueue = false;
|
||||
_iQSlot = 0;
|
||||
|
||||
for (int i = 0; i < NUM_QUEUES; i++) {
|
||||
_nSlotVol[i] = VOLUME_INDEX_DEFAULT;
|
||||
}
|
||||
|
||||
// Mixed assumes Asynchronous
|
||||
if ((_wFlags & SOUND_MIX) == SOUND_MIX) {
|
||||
_wFlags |= SOUND_ASYNCH;
|
||||
}
|
||||
|
||||
if (_wFlags & SOUND_MIDI) {
|
||||
_chType = g_engine->isSpaceBar() ?
|
||||
SOUND_TYPE_XM : SOUND_TYPE_SMF;
|
||||
} else {
|
||||
_chType = SOUND_TYPE_WAV;
|
||||
}
|
||||
|
||||
if (pszPathName != nullptr && (_wFlags & SND_MEMORY)) {
|
||||
// In-memory wave sound
|
||||
_pFileBuf = (byte *)const_cast<char *>(pszPathName);
|
||||
_iFileSize = 999999;
|
||||
|
||||
} else if (pszPathName != nullptr) {
|
||||
if ((_szDrivePath[0] != '\0') && (*pszPathName == '.'))
|
||||
pszPathName++;
|
||||
else if (!strncmp(pszPathName, ".\\", 2))
|
||||
pszPathName += 2;
|
||||
|
||||
char szTempPath[MAX_DIRPATH];
|
||||
snprintf(szTempPath, MAX_DIRPATH, "%s%s", _szDrivePath, pszPathName);
|
||||
strreplaceStr(szTempPath, "\\\\", "\\");
|
||||
strreplaceStr(szTempPath, "\\", "/");
|
||||
|
||||
// Continue as long as this file exists
|
||||
if (fileExists(szTempPath)) {
|
||||
fileGetFullPath(_szFileName, szTempPath);
|
||||
|
||||
if (!(_wFlags & SOUND_QUEUE)) {
|
||||
if (_wFlags & SOUND_WAVE || _wFlags & SOUND_MIX) {
|
||||
loadSound();
|
||||
}
|
||||
}
|
||||
|
||||
} else if (_wFlags & SOUND_MIDI) {
|
||||
// Try both MIDI formats
|
||||
strreplaceStr(szTempPath, ".MID", ".MOV");
|
||||
if (fileExists(szTempPath)) {
|
||||
fileGetFullPath(_szFileName, szTempPath);
|
||||
_chType = SOUND_TYPE_QT;
|
||||
} else {
|
||||
reportError(ERR_FFIND, szTempPath);
|
||||
}
|
||||
} else {
|
||||
reportError(ERR_FFIND, szTempPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CBofSound::~CBofSound() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
stop();
|
||||
releaseSound();
|
||||
|
||||
if (this == _pSoundChain) { // special case head of chain
|
||||
|
||||
_pSoundChain = (CBofSound *)_pSoundChain->getNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::initialize() {
|
||||
for (int i = 0; i < NUM_QUEUES; ++i)
|
||||
_cQueue[i] = new CQueue();
|
||||
|
||||
resetQVolumes();
|
||||
}
|
||||
|
||||
void CBofSound::resetQVolumes() {
|
||||
// Set Q Volumes to default
|
||||
for (int i = 0; i < NUM_QUEUES; i++) {
|
||||
_nSlotVol[i] = VOLUME_INDEX_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::shutdown() {
|
||||
// Auto-delete any remaining sounds
|
||||
clearSounds();
|
||||
|
||||
for (int i = 0; i < NUM_QUEUES; ++i)
|
||||
delete _cQueue[i];
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::setVolume(int nVolume) {
|
||||
assert(nVolume >= VOLUME_INDEX_MIN && nVolume <= VOLUME_INDEX_MAX);
|
||||
|
||||
_nVol = CLIP(nVolume, VOLUME_INDEX_MIN, VOLUME_INDEX_MAX);
|
||||
|
||||
Audio::Mixer *mixer = g_system->getMixer();
|
||||
byte vol = VOLUME_SVM(_nVol);
|
||||
mixer->setChannelVolume(_handle, vol);
|
||||
|
||||
mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, vol);
|
||||
mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, vol);
|
||||
g_engine->_midi->setVolume(vol);
|
||||
}
|
||||
|
||||
void CBofSound::setVolume(int nMidiVolume, int nWaveVolume) {
|
||||
assert(nMidiVolume >= VOLUME_INDEX_MIN && nMidiVolume <= VOLUME_INDEX_MAX);
|
||||
assert(nWaveVolume >= VOLUME_INDEX_MIN && nWaveVolume <= VOLUME_INDEX_MAX);
|
||||
|
||||
// Set master wave volume
|
||||
int clippedVol = CLIP(nWaveVolume, VOLUME_INDEX_MIN, VOLUME_INDEX_MAX);
|
||||
g_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, VOLUME_SVM(clippedVol));
|
||||
|
||||
// Set master Midi volume
|
||||
clippedVol = CLIP(nMidiVolume, VOLUME_INDEX_MIN, VOLUME_INDEX_MAX);
|
||||
g_system->getMixer()->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, VOLUME_SVM(clippedVol));
|
||||
g_engine->_midi->setVolume(VOLUME_SVM(clippedVol));
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::play(uint32 dwBeginHere, uint32 TimeFormatFlag) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// Assume success
|
||||
bool bSuccess = true;
|
||||
|
||||
if (_errCode == ERR_NONE) {
|
||||
// We must be attached to a valid window
|
||||
assert((_pWnd != nullptr) || (_pMainWnd != nullptr));
|
||||
|
||||
// If already playing, then stop and start again
|
||||
if (playing()) {
|
||||
// Can't replay an autodelete sound
|
||||
assert(!(_wFlags & SOUND_AUTODELETE));
|
||||
|
||||
stop();
|
||||
}
|
||||
|
||||
// WAVE and MIX are mutually exclusive
|
||||
assert(!((_wFlags & SOUND_WAVE) && (_wFlags & SOUND_MIX)));
|
||||
|
||||
if (_wFlags & SOUND_WAVE) {
|
||||
if (_wFlags & SOUND_QUEUE)
|
||||
waitWaveSounds();
|
||||
else
|
||||
stopWaveSounds();
|
||||
|
||||
} else if (_wFlags & SOUND_MIDI) {
|
||||
|
||||
if (_wFlags & SOUND_QUEUE)
|
||||
waitMidiSounds();
|
||||
else
|
||||
stopMidiSounds();
|
||||
}
|
||||
|
||||
// Make sure this sound is still valid
|
||||
assert(_pSoundChain != nullptr);
|
||||
|
||||
if (_pFileBuf == nullptr) {
|
||||
if ((_wFlags & (SOUND_MIX | SOUND_QUEUE)) == (SOUND_MIX | SOUND_QUEUE)) {
|
||||
// Don't pre-load it
|
||||
|
||||
} else {
|
||||
loadSound();
|
||||
}
|
||||
}
|
||||
|
||||
if (_wFlags & SOUND_MIDI) {
|
||||
if (_wFlags & SOUND_LOOP)
|
||||
_wLoops = 0;
|
||||
|
||||
g_engine->_midi->play(this);
|
||||
_bPlaying = true;
|
||||
|
||||
} else if (_wFlags & SOUND_WAVE) {
|
||||
|
||||
playWAV();
|
||||
|
||||
if (_bPlaying) {
|
||||
|
||||
if (!(_wFlags & SOUND_ASYNCH)) {
|
||||
EventLoop eventLoop;
|
||||
auto *mixer = g_system->getMixer();
|
||||
|
||||
while (mixer->isSoundHandleActive(_handle)) {
|
||||
if (eventLoop.frame()) {
|
||||
stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_handle = {};
|
||||
_bPlaying = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (_wFlags & SOUND_MIX) {
|
||||
if (!(_wFlags & SOUND_QUEUE)) {
|
||||
playWAV();
|
||||
|
||||
} else {
|
||||
assert(_iQSlot >= 0 && _iQSlot < NUM_QUEUES);
|
||||
|
||||
_cQueue[_iQSlot]->addItem(this);
|
||||
_bPlaying = true;
|
||||
_bInQueue = true;
|
||||
setVolume(_nSlotVol[_iQSlot]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::midiLoopPlaySegment(uint32 dwLoopFrom, uint32 dwLoopTo, uint32 dwBegin, uint32 TimeFmt) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
_wFlags |= SOUND_LOOP;
|
||||
_wLoops = 0;
|
||||
_dwRePlayStart = dwLoopFrom;
|
||||
_dwRePlayEnd = dwLoopTo;
|
||||
_bExtensionsUsed = true;
|
||||
|
||||
bool bSuccess = play(dwBegin, TimeFmt);
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::pauseSounds() {
|
||||
bool bSuccess = true;
|
||||
|
||||
// Thumb through all the sounds
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
// If one is playing and not paused try to suspend it
|
||||
if (pSound->playing() && (pSound->_bPaused == false)) {
|
||||
bool bStatus = pSound->pause();
|
||||
if (bStatus)
|
||||
pSound->_bPaused = true;
|
||||
else
|
||||
bSuccess = false;
|
||||
}
|
||||
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::pause() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
bool bSuccess = false;
|
||||
|
||||
// Must be playing to be paused and not already paused
|
||||
if (playing() && (_bPaused == false)) {
|
||||
bSuccess = true;
|
||||
if (_wFlags & SOUND_MIDI) {
|
||||
g_engine->_midi->pause();
|
||||
} else {
|
||||
g_system->getMixer()->pauseHandle(_handle, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (bSuccess)
|
||||
_bPaused = true;
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::resumeSounds() {
|
||||
bool bSuccess = true;
|
||||
|
||||
CBofSound *pSound = _pSoundChain; // Thumb through all the sounds
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->_bPaused) {
|
||||
// If one is paused
|
||||
bool bStatus = pSound->resume(); // ... try to get it going again
|
||||
if (bStatus)
|
||||
pSound->_bPaused = false; // success
|
||||
else
|
||||
bSuccess = false; // failure
|
||||
}
|
||||
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::resume() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
bool bSuccess = false;
|
||||
|
||||
if (_bPaused) { // must be paused to resume
|
||||
bSuccess = true;
|
||||
if (_wFlags & SOUND_MIDI) {
|
||||
g_engine->_midi->resume();
|
||||
} else {
|
||||
g_system->getMixer()->pauseHandle(_handle, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (bSuccess)
|
||||
_bPaused = false;
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::stopSounds() {
|
||||
CBofSound *pSound = _pSoundChain; // Thumb through all the sounds
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->playing()) { // If one is playing
|
||||
pSound->_bPaused = false; // ... its no longer paused
|
||||
pSound->stop(); // Stop it
|
||||
}
|
||||
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::stopWaveSounds() {
|
||||
CBofSound *pSound = _pSoundChain; // Find this Sound is the queue
|
||||
while (pSound != nullptr) {
|
||||
CBofSound *pNextSound = (CBofSound *)pSound->getNext();
|
||||
|
||||
if (pSound->playing() && ((pSound->_wFlags & SOUND_WAVE) || (pSound->_wFlags & SOUND_MIX))) {
|
||||
pSound->stop();
|
||||
if (pSound->_wFlags & SOUND_AUTODELETE)
|
||||
delete pSound;
|
||||
}
|
||||
|
||||
pSound = pNextSound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::stopMidiSounds() {
|
||||
CBofSound *pSound = _pSoundChain; // Find this Sound is the queue
|
||||
while (pSound != nullptr) {
|
||||
CBofSound *pNextSound = (CBofSound *)pSound->getNext();
|
||||
|
||||
if (pSound->playing() && (pSound->_wFlags & SOUND_MIDI)) {
|
||||
pSound->stop();
|
||||
if (pSound->_wFlags & SOUND_AUTODELETE)
|
||||
delete pSound;
|
||||
}
|
||||
|
||||
pSound = pNextSound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::stop() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// If this sound is currently playing
|
||||
if (_wFlags & SOUND_MIDI) {
|
||||
g_engine->_midi->stop();
|
||||
} else {
|
||||
g_system->getMixer()->stopHandle(_handle);
|
||||
_handle = {};
|
||||
}
|
||||
|
||||
if (_bInQueue) {
|
||||
assert(_iQSlot >= 0 && _iQSlot < NUM_QUEUES);
|
||||
_cQueue[_iQSlot]->deleteItem(this);
|
||||
_bInQueue = false;
|
||||
}
|
||||
|
||||
_bPlaying = false;
|
||||
_bStarted = false;
|
||||
_bPaused = false;
|
||||
|
||||
// One less audio playing
|
||||
_nCount -= 1;
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::clearSounds() {
|
||||
stopSounds(); // Stop all active sounds
|
||||
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) { // Delete all sound entries
|
||||
CBofSound *pNextSound = pSound->getNext();
|
||||
delete pSound;
|
||||
pSound = pNextSound;
|
||||
}
|
||||
|
||||
assert(_pSoundChain == nullptr);
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::clearWaveSounds() {
|
||||
|
||||
CBofSound *pSound = _pSoundChain; // Find this Sound in the queue
|
||||
while (pSound != nullptr) {
|
||||
CBofSound *pNextSound = pSound->getNext();
|
||||
if ((pSound->_wFlags & SOUND_WAVE) || (pSound->_wFlags & SOUND_MIX))
|
||||
delete pSound;
|
||||
|
||||
pSound = pNextSound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::clearMidiSounds() {
|
||||
CBofSound *pSound = _pSoundChain; // find this Sound is the queue
|
||||
while (pSound != nullptr) {
|
||||
CBofSound *pNextSound = (CBofSound *)pSound->getNext();
|
||||
|
||||
if (pSound->_wFlags & SOUND_MIDI)
|
||||
delete pSound;
|
||||
|
||||
pSound = pNextSound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::waitSounds() {
|
||||
waitWaveSounds();
|
||||
waitMidiSounds();
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::waitWaveSounds() {
|
||||
uint32 dwTickCount = 0;
|
||||
|
||||
for (;;) {
|
||||
audioTask();
|
||||
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->playing() && (pSound->_wFlags & SOUND_WAVE || pSound->_wFlags & SOUND_MIX)) {
|
||||
break;
|
||||
}
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
if (pSound == nullptr)
|
||||
break;
|
||||
|
||||
if (handleMessages())
|
||||
break;
|
||||
|
||||
// If 3 minutes go by, then just bolt
|
||||
if (dwTickCount == 0)
|
||||
dwTickCount = g_system->getMillis() + 1000 * 60 * 3;
|
||||
|
||||
if (g_system->getMillis() > dwTickCount) {
|
||||
pSound->stop();
|
||||
pSound->_bPlaying = false;
|
||||
|
||||
pSound->reportError(ERR_UNKNOWN, "CBofSound::waitWaveSounds() timeout!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CBofSound::soundsPlaying() {
|
||||
audioTask();
|
||||
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->playing() && (pSound->_wFlags & SOUND_WAVE || pSound->_wFlags & SOUND_MIX)) {
|
||||
return true;
|
||||
}
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::waitMidiSounds() {
|
||||
uint32 dwTickCount = 0;
|
||||
|
||||
for (;;) {
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->playing() && (pSound->_wFlags & SOUND_MIDI)) {
|
||||
break;
|
||||
}
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
if (pSound == nullptr)
|
||||
break;
|
||||
|
||||
if (handleMessages())
|
||||
break;
|
||||
|
||||
if (dwTickCount == 0)
|
||||
dwTickCount = g_system->getMillis() + 1000 * 60;
|
||||
|
||||
if (g_system->getMillis() > dwTickCount) {
|
||||
pSound->stop();
|
||||
|
||||
pSound->reportError(ERR_UNKNOWN, "CBofSound::waitMidiSounds() timeout");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::handleMessages() {
|
||||
if (g_engine->isSpaceBar()) {
|
||||
Common::Event e;
|
||||
while (g_system->getEventManager()->pollEvent(e)) {
|
||||
}
|
||||
|
||||
g_system->delayMillis(10);
|
||||
} else {
|
||||
AfxGetApp()->pause();
|
||||
}
|
||||
|
||||
return g_engine->shouldQuit();
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CBofSound::bofSleep(uint32 wait) {
|
||||
uint32 goal = wait + g_system->getMillis();
|
||||
while (goal > g_system->getMillis()) {
|
||||
if (handleMessages())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool BofPlaySound(const char *pszSoundFile, uint32 nFlags, int iQSlot) {
|
||||
// Assume failure
|
||||
bool bSuccess;
|
||||
|
||||
if (pszSoundFile != nullptr) {
|
||||
nFlags |= SOUND_AUTODELETE;
|
||||
|
||||
if (nFlags & SND_MEMORY) {
|
||||
// Hardcoded for wave files
|
||||
nFlags |= SOUND_WAVE;
|
||||
|
||||
} else if (!fileExists(pszSoundFile)) {
|
||||
logWarning(buildString("Sound File '%s' not found", pszSoundFile));
|
||||
return false;
|
||||
}
|
||||
|
||||
// WORKAROUND: Hodj may not specify sound type
|
||||
if (!(nFlags & (SOUND_WAVE | SOUND_MIDI))) {
|
||||
Common::String name(pszSoundFile);
|
||||
if (name.hasSuffixIgnoreCase(".wav"))
|
||||
nFlags |= SOUND_WAVE;
|
||||
else if (name.hasSuffixIgnoreCase(".mid"))
|
||||
nFlags |= SOUND_MIDI;
|
||||
}
|
||||
|
||||
// Take care of any last minute cleanup before we start this new sound
|
||||
CBofSound::audioTask();
|
||||
CBofSound::stopWaveSounds();
|
||||
|
||||
CBofSound *pSound = new CBofSound(/*pWnd*/nullptr, pszSoundFile, (uint16)nFlags);
|
||||
if ((nFlags & SOUND_QUEUE) == SOUND_QUEUE) {
|
||||
pSound->setQSlot(iQSlot);
|
||||
}
|
||||
|
||||
bSuccess = pSound->play();
|
||||
} else {
|
||||
bSuccess = true;
|
||||
CBofSound::stopWaveSounds();
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
bool BofPlaySoundEx(const char *pszSoundFile, uint32 nFlags, int iQSlot, bool bWait) {
|
||||
// Assume failure
|
||||
bool bSuccess = false;
|
||||
|
||||
if (pszSoundFile != nullptr) {
|
||||
if ((nFlags & SOUND_MIX) == 0) {
|
||||
bWait = false;
|
||||
}
|
||||
|
||||
if (!bWait) {
|
||||
nFlags |= SOUND_AUTODELETE;
|
||||
}
|
||||
|
||||
if (!fileExists(pszSoundFile)) {
|
||||
logWarning(buildString("Sound File '%s' not found", pszSoundFile));
|
||||
return false;
|
||||
}
|
||||
|
||||
//CBofWindow *pWnd = CBofApp::getApp()->getMainWindow();
|
||||
|
||||
// Take care of any last minute cleanup before we start this new sound
|
||||
CBofSound::audioTask();
|
||||
|
||||
CBofSound *pSound = new CBofSound(/*pWnd*/nullptr, pszSoundFile, (uint16)nFlags);
|
||||
if ((nFlags & SOUND_QUEUE) == SOUND_QUEUE) {
|
||||
pSound->setQSlot(iQSlot);
|
||||
}
|
||||
|
||||
bSuccess = pSound->play();
|
||||
|
||||
if (bWait) {
|
||||
while (pSound->isPlaying()) {
|
||||
CBofSound::audioTask();
|
||||
}
|
||||
delete pSound;
|
||||
}
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::loadSound() {
|
||||
assert(isValidObject(this));
|
||||
assert(_szFileName[0] != '\0');
|
||||
|
||||
bool bSuccess = true;
|
||||
if (_pFileBuf == nullptr) {
|
||||
bSuccess = false;
|
||||
|
||||
Common::File in;
|
||||
|
||||
if (in.open(_szFileName)) {
|
||||
_iFileSize = in.size();
|
||||
|
||||
_pFileBuf = (byte *)malloc(_iFileSize);
|
||||
|
||||
if (in.read(_pFileBuf, _iFileSize) == _iFileSize)
|
||||
bSuccess = true;
|
||||
}
|
||||
}
|
||||
|
||||
return bSuccess;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::releaseSound() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
if (!(_wFlags & SND_MEMORY))
|
||||
free(_pFileBuf);
|
||||
_pFileBuf = nullptr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::soundsPlayingNotOver() {
|
||||
// Assume no wave sounds are playing
|
||||
bool bPlaying = false;
|
||||
|
||||
// Walk through sound list, and check for sounds that need attention
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->playing() &&
|
||||
(pSound->_wFlags & SOUND_WAVE || pSound->_wFlags & SOUND_MIX) &&
|
||||
!(pSound->_wFlags & SOUND_OVEROK)) {
|
||||
bPlaying = true;
|
||||
break;
|
||||
}
|
||||
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
return bPlaying;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::waveSoundPlaying() {
|
||||
// Assume no wave sounds are playing
|
||||
bool bPlaying = false;
|
||||
|
||||
// Walk through sound list, and check for sounds that need attention
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->playing() && (pSound->_wFlags & SOUND_WAVE || pSound->_wFlags & SOUND_MIX)) {
|
||||
bPlaying = true;
|
||||
break;
|
||||
}
|
||||
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
return bPlaying;
|
||||
}
|
||||
|
||||
|
||||
bool CBofSound::midiSoundPlaying() {
|
||||
// Assume no wave sounds are playing
|
||||
bool bPlaying = false;
|
||||
|
||||
// Walk through sound list, and check for sounds that need attention
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->playing() && (pSound->_wFlags & SOUND_MIDI)) {
|
||||
bPlaying = true;
|
||||
break;
|
||||
}
|
||||
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
return bPlaying;
|
||||
}
|
||||
|
||||
|
||||
void CBofSound::audioTask() {
|
||||
static bool bAlready = false;
|
||||
|
||||
// Don't allow recursion here
|
||||
assert(!bAlready);
|
||||
|
||||
bAlready = true;
|
||||
|
||||
// Walk through sound list, and check for sounds that need attention
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
if (!pSound->paused()) {
|
||||
if ((pSound->_wFlags & SOUND_WAVE) || (pSound->_wFlags & SOUND_MIX)) {
|
||||
|
||||
// Has this sound been played?
|
||||
if (pSound->_bStarted) {
|
||||
// And, Is it done?
|
||||
if (!g_system->getMixer()->isSoundHandleActive(pSound->_handle)) {
|
||||
// Kill it
|
||||
pSound->stop();
|
||||
}
|
||||
|
||||
} else if (pSound->_bInQueue) {
|
||||
// If this is a Queued sound, and has not already started
|
||||
// And it is time to play
|
||||
if ((CBofSound *)_cQueue[pSound->_iQSlot]->getQItem() == pSound) {
|
||||
pSound->playWAV();
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((pSound->_wFlags & SOUND_MIDI) && pSound->_bPlaying) {
|
||||
// And, Is it done?
|
||||
if (!g_engine->_midi->isPlaying()) {
|
||||
// Kill it
|
||||
pSound->stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pSound = (CBofSound *)pSound->getNext();
|
||||
}
|
||||
|
||||
bAlready = false;
|
||||
}
|
||||
|
||||
ErrorCode CBofSound::playWAV() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
if (!errorOccurred()) {
|
||||
// If it's not yet loaded, then load it now
|
||||
if (_pFileBuf == nullptr) {
|
||||
loadSound();
|
||||
}
|
||||
|
||||
assert(_pFileBuf != nullptr);
|
||||
|
||||
if (_pFileBuf != nullptr) {
|
||||
if (_bInQueue) {
|
||||
setVolume(_nSlotVol[_iQSlot]);
|
||||
}
|
||||
|
||||
// Then, Play it
|
||||
Common::SeekableReadStream *stream = new Common::MemoryReadStream(_pFileBuf, _iFileSize);
|
||||
Audio::AudioStream *audio = Audio::makeLoopingAudioStream(Audio::makeWAVStream(stream, DisposeAfterUse::YES), _wLoops);
|
||||
|
||||
if (audio == nullptr) {
|
||||
reportError(ERR_UNKNOWN, "Could not allocate audio stream.");
|
||||
}
|
||||
|
||||
g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, &_handle, audio, -1, VOLUME_SVM(_nVol));
|
||||
_bPlaying = true;
|
||||
_bStarted = true;
|
||||
}
|
||||
}
|
||||
|
||||
return _errCode;
|
||||
}
|
||||
|
||||
|
||||
ErrorCode CBofSound::flushQueue(int nSlot) {
|
||||
assert(nSlot >= 0 && nSlot < NUM_QUEUES);
|
||||
|
||||
// Assume no error
|
||||
ErrorCode errorCode = ERR_NONE;
|
||||
|
||||
// Remove all queued sounds
|
||||
_cQueue[nSlot]->flush();
|
||||
|
||||
// Including any that are currently playing
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
// Prefetch next sound in case stop() deletes this one
|
||||
CBofSound *pNextSound = pSound->getNext();
|
||||
|
||||
// If this sound is playing from specified queue
|
||||
if (pSound->isPlaying() && pSound->_bInQueue && pSound->_iQSlot == nSlot) {
|
||||
// Then chuck it
|
||||
pSound->stop();
|
||||
}
|
||||
|
||||
// Next
|
||||
pSound = pNextSound;
|
||||
}
|
||||
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
void CBofSound::setQVol(int nSlot, int nVol) {
|
||||
// Validate input
|
||||
assert(nSlot >= 0 && nSlot < NUM_QUEUES);
|
||||
assert(nVol >= 0 && nVol <= VOLUME_INDEX_MAX);
|
||||
|
||||
_nSlotVol[nSlot] = nVol;
|
||||
|
||||
// Set all Queued sounds in specified slot to this volume
|
||||
CBofSound *pSound = _pSoundChain;
|
||||
while (pSound != nullptr) {
|
||||
if (pSound->_bInQueue && pSound->_iQSlot == nSlot) {
|
||||
pSound->setVolume(nVol);
|
||||
}
|
||||
pSound = pSound->getNext();
|
||||
}
|
||||
}
|
||||
|
||||
bool MessageBeep(int uType) {
|
||||
warning("TODO: beep");
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
247
engines/bagel/boflib/sound.h
Normal file
247
engines/bagel/boflib/sound.h
Normal file
@@ -0,0 +1,247 @@
|
||||
|
||||
/* 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/".
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_SOUND_H
|
||||
#define BAGEL_BOFLIB_SOUND_H
|
||||
|
||||
#include "audio/mixer.h"
|
||||
#include "bagel/boflib/stdinc.h"
|
||||
#include "bagel/boflib/llist.h"
|
||||
#include "bagel/boflib/object.h"
|
||||
#include "bagel/boflib/error.h"
|
||||
#include "bagel/boflib/queue.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
//
|
||||
// Wavemix-related constants
|
||||
//
|
||||
#define VOLUME_INDEX_MIN 0
|
||||
#define VOLUME_INDEX_MAX 12
|
||||
#define VOLUME_INDEX_DEFAULT 10
|
||||
|
||||
// Convert to ScummVM scale
|
||||
#define VOLUME_SVM(x) ((x) * Audio::Mixer::kMaxChannelVolume / VOLUME_INDEX_MAX)
|
||||
#define SVM_VOLUME(x) (((x) >= 252) ? VOLUME_INDEX_MAX : (x) * VOLUME_INDEX_MAX / 252)
|
||||
|
||||
#define SOUND_BUFFERED 0x0001
|
||||
#define SOUND_ASYNCH 0x0002
|
||||
#define SOUND_NOTIFY 0x0004
|
||||
#define SOUND_AUTODELETE 0x0008
|
||||
#define SOUND_LOOP 0x0010
|
||||
#define SOUND_WAVE 0x0020
|
||||
#define SOUND_MIDI 0x0040
|
||||
#define SOUND_DONT_LOOP_TO_END 0x0080
|
||||
#define SOUND_QUEUE 0x0100 // With wavemix: play after previous sound finishes
|
||||
#define SOUND_MIX 0x0200 // Use wavemix to really play asynchronously
|
||||
#define SOUND_ASAP 0x0400 // Play as soon as a channel is free (maybe now)
|
||||
#define SOUND_WAIT 0x0800 // For wavemix: Set sound up but don't play it yet
|
||||
#define SOUND_LOCK 0x1000 // Reserve this channel until user stops it
|
||||
#define SOUND_PRELOAD 0x2000 // Only works for Resource MAC snd files
|
||||
#define SOUND_OVEROK 0x4000 // OK to play another sound over this file
|
||||
#define SND_MEMORY 0x8000 // Raw in-memory sound passed rather than a filename
|
||||
|
||||
#define SND_NODEFAULT 0
|
||||
#define SND_SYNC 0
|
||||
#define SND_ASYNC SOUND_ASYNCH
|
||||
|
||||
#define SOUND_TYPE_WAV 1
|
||||
#define SOUND_TYPE_XM 2
|
||||
#define SOUND_TYPE_QT 3
|
||||
#define SOUND_TYPE_SMF 4
|
||||
|
||||
#define FMT_MILLISEC 1 // Time format specifiers.
|
||||
#define FMT_BPM 2
|
||||
|
||||
#define NUM_QUEUES 8
|
||||
|
||||
class CBofSound : public CBofError, public CBofObject, public CLList {
|
||||
public:
|
||||
friend class MusicPlayer;
|
||||
|
||||
CBofSound();
|
||||
CBofSound(void *pWnd, const char *pszPathName, uint16 wFlags, int nLoops = 1);
|
||||
virtual ~CBofSound();
|
||||
void addToSoundChain();
|
||||
|
||||
void initialize(const char *pszPathName, uint16 wFlags) {
|
||||
initialize(nullptr, pszPathName, wFlags);
|
||||
}
|
||||
void initialize(void *pWnd, const char *pszPathName, uint16 wFlags);
|
||||
void setDrivePath(const char *path) {}
|
||||
bool midiLoopPlaySegment(uint32 LoopBegin, uint32 LoopEnd = 0L, uint32 FirstPassBegin = 0L, uint32 TimeFmt = FMT_MILLISEC);
|
||||
bool play(uint32 StartOfPlay = 0L, uint32 TimeFmtFlag = FMT_MILLISEC);
|
||||
bool pause();
|
||||
bool resume();
|
||||
void stop();
|
||||
|
||||
CBofSound *getNext() {
|
||||
return (CBofSound *)_pNext;
|
||||
}
|
||||
CBofSound *getPrev() {
|
||||
return (CBofSound *)_pPrev;
|
||||
}
|
||||
|
||||
char *getFileName() {
|
||||
return &_szFileName[0];
|
||||
}
|
||||
|
||||
void setFlags(uint16 wFlags) {
|
||||
_wFlags = wFlags;
|
||||
}
|
||||
uint16 getFlags() {
|
||||
return _wFlags;
|
||||
}
|
||||
|
||||
bool playing() {
|
||||
return isPlaying();
|
||||
}
|
||||
|
||||
bool isPlaying() {
|
||||
return _bPlaying;
|
||||
}
|
||||
bool isQueued() {
|
||||
return _bInQueue;
|
||||
}
|
||||
|
||||
bool paused() {
|
||||
return _bPaused;
|
||||
}
|
||||
|
||||
void setQSlot(int nSlot) {
|
||||
_iQSlot = nSlot;
|
||||
}
|
||||
int getQSlot() {
|
||||
return _iQSlot;
|
||||
}
|
||||
|
||||
void setVolume(int nVol);
|
||||
int getVolume() {
|
||||
return _nVol;
|
||||
}
|
||||
|
||||
static void initialize();
|
||||
static void shutdown();
|
||||
static void setVolume(int MidiVolume, int WaveVolume);
|
||||
|
||||
static bool soundPlaying() {
|
||||
return (_nCount > 0) ? true : false;
|
||||
}
|
||||
|
||||
static bool waveSoundPlaying();
|
||||
static bool midiSoundPlaying();
|
||||
static bool soundsPlayingNotOver();
|
||||
|
||||
static void setQVol(int nSlot, int nVol);
|
||||
|
||||
ErrorCode playWAV();
|
||||
|
||||
static ErrorCode flushQueue(int nSlot);
|
||||
|
||||
static void resetQVolumes();
|
||||
|
||||
static bool pauseSounds();
|
||||
static bool resumeSounds();
|
||||
static void stopSounds();
|
||||
static void stopWaveSounds();
|
||||
static void stopMidiSounds();
|
||||
static void clearSounds();
|
||||
static void clearWaveSounds();
|
||||
static void clearMidiSounds();
|
||||
static void waitSounds();
|
||||
static void waitWaveSounds();
|
||||
static void waitMidiSounds();
|
||||
static bool handleMessages();
|
||||
static bool bofSleep(uint32 dwTime);
|
||||
static void audioTask();
|
||||
static bool soundsPlaying();
|
||||
static bool MidiAvailable() {
|
||||
return true;
|
||||
}
|
||||
static bool SoundAvailable() {
|
||||
return true;
|
||||
}
|
||||
static bool SoundVolumeAvailable() {
|
||||
return true;
|
||||
}
|
||||
static bool MidiVolumeAvailable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
static CBofSound *OnMCIStopped(WPARAM wParam, LPARAM lParam) {
|
||||
return nullptr;
|
||||
}
|
||||
static CBofSound *OnMMIOStopped(WPARAM wParam, LPARAM lParam) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
bool loadSound();
|
||||
bool releaseSound();
|
||||
|
||||
private:
|
||||
char _szFileName[MAX_FNAME]; // Path spec for sound file
|
||||
int8 _chType = 0; // Type of sound commands used
|
||||
|
||||
uint16 _wLoops = 0; // Number of times to loop the sound (0xFFFF means infinite)
|
||||
uint16 _wFlags = 0; // Flags for playing
|
||||
bool _bPaused = false; // Whether its paused
|
||||
bool _bPlaying = false; // Whether its playing
|
||||
|
||||
bool _bExtensionsUsed = false;
|
||||
uint32 _dwPlayStart = 0;
|
||||
uint32 _dwRePlayStart = 0;
|
||||
uint32 _dwRePlayEnd = 0;
|
||||
Audio::SoundHandle _handle;
|
||||
byte *_pFileBuf = nullptr;
|
||||
uint32 _iFileSize = 0;
|
||||
|
||||
int _iQSlot = 0;
|
||||
bool _bInQueue = false;
|
||||
bool _bStarted = false;
|
||||
int _nVol = 0;
|
||||
|
||||
void *_pWnd = nullptr; // Parent window for messages
|
||||
|
||||
static char _szDrivePath[MAX_DIRPATH]; // Path spec to drive
|
||||
static CBofSound *_pSoundChain; // First item in chain or nullptr
|
||||
static int _nCount; // Count of active sounds
|
||||
static int _nWavCount; // Number of wave sound devices
|
||||
static int _nMidiCount; // Number of midi sound devices
|
||||
static void *_pMainWnd; // Window for message processing
|
||||
static bool _bInit;
|
||||
|
||||
static int _nSlotVol[NUM_QUEUES];
|
||||
static CQueue *_cQueue[NUM_QUEUES];
|
||||
};
|
||||
|
||||
#define CSound CBofSound
|
||||
|
||||
extern bool BofPlaySound(const char *pszSoundFile, uint32 nFlags, int iQSlot = 0);
|
||||
extern bool BofPlaySoundEx(const char *pszSoundFile, uint32 nFlags, int iQSlot = 0, bool bWait = false);
|
||||
extern bool MessageBeep(int uType);
|
||||
|
||||
#define sndPlaySound BofPlaySound
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
95
engines/bagel/boflib/stdinc.h
Normal file
95
engines/bagel/boflib/stdinc.h
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_STDINC_H
|
||||
#define BAGEL_BOFLIB_STDINC_H
|
||||
|
||||
#include "common/scummsys.h"
|
||||
#include "common/rect.h"
|
||||
#include "bagel/afxwin.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
/*
|
||||
* Normal types
|
||||
*/
|
||||
typedef void *(*BofCallback)(int, void *);
|
||||
|
||||
typedef long Fixed;
|
||||
|
||||
/*
|
||||
* Extended types
|
||||
*/
|
||||
struct StSize {
|
||||
int cx;
|
||||
int cy;
|
||||
};
|
||||
|
||||
struct StPoint {
|
||||
int x;
|
||||
int y;
|
||||
};
|
||||
|
||||
struct Vector {
|
||||
double x;
|
||||
double y;
|
||||
double z;
|
||||
};
|
||||
|
||||
struct WindowPos {
|
||||
void *hwnd = nullptr;
|
||||
void *hwndinsertAfter = nullptr;
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int cx = 0;
|
||||
int cy = 0;
|
||||
uint32 flags = 0;
|
||||
};
|
||||
|
||||
#define MAKE_WORD(a, b) ((uint16)(((byte)(a)) | ((uint16)((byte)(b))) << 8))
|
||||
#define MAKE_LONG(low, high) ((int32)(((uint16)(low)) | (((uint32)((uint16)(high))) << 16)))
|
||||
|
||||
/* For big-endian platforms (i.e. MAC) */
|
||||
#define SWAPWORD(x) MAKE_WORD(HIBYTE(x), LOBYTE(x))
|
||||
#define SWAPLONG(x) MAKE_LONG(SWAPWORD(HIWORD(x)), SWAPWORD(LOWORD(x)))
|
||||
|
||||
#ifndef MAX_FNAME
|
||||
#define MAX_FNAME 256
|
||||
#endif
|
||||
|
||||
#define MAX_DIRPATH 256
|
||||
|
||||
#ifndef PDFT
|
||||
#define PDFT(VALUE) = VALUE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* normal types
|
||||
*/
|
||||
#define VIRTUAL virtual
|
||||
#define STATIC static
|
||||
#define CDECL
|
||||
#define INLINE inline
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
599
engines/bagel/boflib/string.cpp
Normal file
599
engines/bagel/boflib/string.cpp
Normal file
@@ -0,0 +1,599 @@
|
||||
/* 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/str.h"
|
||||
#include "bagel/boflib/string.h"
|
||||
#include "bagel/boflib/misc.h"
|
||||
#include "bagel/boflib/string_functions.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
#define MAX_STRING 256
|
||||
|
||||
#define BUF_EXTRA 20
|
||||
|
||||
CBofString::CBofString() {
|
||||
init();
|
||||
}
|
||||
|
||||
CBofString::CBofString(int nLength) {
|
||||
init();
|
||||
allocBuffer(nLength);
|
||||
}
|
||||
|
||||
CBofString::CBofString(const CBofString &cString) {
|
||||
init();
|
||||
copy(cString._pszData);
|
||||
}
|
||||
|
||||
CBofString::CBofString(const char *pszBuf) {
|
||||
init();
|
||||
copy(pszBuf);
|
||||
}
|
||||
|
||||
CBofString::CBofString(char *pszBuff, int pszBuffLen) {
|
||||
init();
|
||||
|
||||
// Force a max length (To stop uninitialized buffer from killing us)
|
||||
*(pszBuff + pszBuffLen - 1) = '\0';
|
||||
|
||||
// Passing in un-initialized data could cause problems depending on what
|
||||
// string functions are used after this constructor.
|
||||
_nLength = (uint16)strlen(pszBuff);
|
||||
|
||||
// Use the high byte of the buffer size to determine if we're using stack memory.
|
||||
// Make sure that we don't have an obscenely large string
|
||||
|
||||
assert((pszBuffLen & mUseStackMem) == false);
|
||||
SETBUFFERSIZE(pszBuffLen, true);
|
||||
_pszData = pszBuff;
|
||||
}
|
||||
|
||||
CBofString::CBofString(char ch, int nRepeat) {
|
||||
assert(nRepeat > 0);
|
||||
|
||||
init();
|
||||
allocBuffer(nRepeat);
|
||||
memset(_pszData, ch, nRepeat);
|
||||
}
|
||||
|
||||
CBofString::~CBofString() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
free();
|
||||
}
|
||||
|
||||
void CBofString::init() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
SETBUFFERSIZE(0, false);
|
||||
_nLength = 0;
|
||||
_pszData = nullptr;
|
||||
}
|
||||
|
||||
void CBofString::allocBuffer(int nLen) {
|
||||
assert(isValidObject(this));
|
||||
assert(nLen >= 0);
|
||||
|
||||
// These 3 lines "should" do the same thing
|
||||
assert(nLen < SHRT_MAX); // max size (enough room for 1 extra)
|
||||
assert((uint16)nLen < mUseStackMem);
|
||||
assert((nLen & mUseStackMem) == 0);
|
||||
|
||||
// Delete any previous buffer
|
||||
free();
|
||||
|
||||
// Don't do anything about zero length allocations
|
||||
if (nLen > 0) {
|
||||
// Allocate a buffer filled with 0s
|
||||
_pszData = (char *)bofCleanAlloc(nLen + 1);
|
||||
}
|
||||
|
||||
_nLength = 0;
|
||||
|
||||
// Use the high byte of the bufflen to indicate if we're using
|
||||
// stack mem or not. Make sure our buff size is not too big
|
||||
assert((nLen & mUseStackMem) == 0);
|
||||
SETBUFFERSIZE(nLen, false);
|
||||
}
|
||||
|
||||
void CBofString::free() {
|
||||
assert(isValidObject(this));
|
||||
bool bStackMem = USESSTACKMEM();
|
||||
|
||||
// Free any attached data
|
||||
// Only free if it's not stack memory
|
||||
if (_pszData != nullptr && bStackMem == false) {
|
||||
bofFree(_pszData);
|
||||
_pszData = nullptr;
|
||||
}
|
||||
_nLength = 0;
|
||||
SETBUFFERSIZE(0, bStackMem);
|
||||
}
|
||||
|
||||
void CBofString::copy(const char *pszBuf) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
if (NORMALIZEBUFFERSIZE() != 0)
|
||||
*_pszData = '\0';
|
||||
|
||||
_nLength = 0;
|
||||
if (pszBuf != nullptr) {
|
||||
int n = strlen(pszBuf);
|
||||
|
||||
if (NORMALIZEBUFFERSIZE() <= n) {
|
||||
allocBuffer(n + 1);
|
||||
}
|
||||
|
||||
Common::strcpy_s(_pszData, n + 1, pszBuf);
|
||||
_nLength = (uint16)strlen(_pszData);
|
||||
}
|
||||
}
|
||||
|
||||
void CBofString::allocCopy(CBofString &dest, int nCopyLen, int nCopyIndex, int nExtraLen) const {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// Will clone the data attached to this string allocating 'nExtraLen' characters
|
||||
// Places results in uninitialized string 'dest'
|
||||
// Will copy the part or all of original data to start of new string
|
||||
|
||||
int nNewLen = nCopyLen + nExtraLen;
|
||||
|
||||
if (nNewLen == 0) {
|
||||
dest.free();
|
||||
|
||||
} else {
|
||||
dest.allocBuffer(nNewLen);
|
||||
|
||||
assert(_pszData != nullptr);
|
||||
memcpy(dest._pszData, &_pszData[nCopyIndex], nCopyLen * sizeof(char));
|
||||
}
|
||||
}
|
||||
|
||||
const CBofString &CBofString::operator=(const CBofString &cString) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
copy(cString._pszData);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBofString &CBofString::operator=(const char *lpsz) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
copy(lpsz);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void CBofString::concatCopy(int nSrc1Len, const char *lpszSrc1Data, int nSrc2Len, const char *lpszSrc2Data, int nAllocLen) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// -- Master concatenation routine
|
||||
// concatenate two sources
|
||||
// -- Assume that 'this' is a new CBofString object
|
||||
|
||||
int nNewLen = nSrc1Len + nSrc2Len;
|
||||
allocBuffer((nAllocLen == 0 ? nNewLen : nAllocLen));
|
||||
memcpy(_pszData, lpszSrc1Data, nSrc1Len * sizeof(char));
|
||||
memcpy(&_pszData[nSrc1Len], lpszSrc2Data, nSrc2Len * sizeof(char));
|
||||
// RMS
|
||||
_nLength = (uint16)nNewLen;
|
||||
}
|
||||
|
||||
CBofString operator+(const CBofString &string1, const CBofString &string2) {
|
||||
CBofString s;
|
||||
s.concatCopy(string1._nLength, string1._pszData, string2._nLength, string2._pszData);
|
||||
return s;
|
||||
}
|
||||
|
||||
CBofString operator+(const CBofString &string, const char *lpsz) {
|
||||
CBofString s;
|
||||
s.concatCopy(string._nLength, string._pszData, CBofString::safeStrlen(lpsz), lpsz);
|
||||
return s;
|
||||
}
|
||||
|
||||
CBofString operator+(const char *lpsz, const CBofString &string) {
|
||||
CBofString s;
|
||||
s.concatCopy(CBofString::safeStrlen(lpsz), lpsz, string._nLength, string._pszData);
|
||||
return s;
|
||||
}
|
||||
|
||||
void CBofString::concatInPlace(int nSrcLen, const char *lpszSrcData) {
|
||||
char szLocalBuff[512];
|
||||
assert(isValidObject(this));
|
||||
|
||||
// -- The main routine for += operators
|
||||
|
||||
// If the buffer is too small, or we have a width mis-match, just
|
||||
// allocate a new buffer (slow but sure)
|
||||
//
|
||||
// Make sure we have an underlying buffer.
|
||||
if (_nLength + nSrcLen >= NORMALIZEBUFFERSIZE()) {
|
||||
// Don't increment by buf extra, but set the size if we're
|
||||
// less than that default threshold.
|
||||
int nAllocAmount = nSrcLen;
|
||||
|
||||
if (nAllocAmount < BUF_EXTRA) {
|
||||
nAllocAmount = BUF_EXTRA;
|
||||
}
|
||||
|
||||
if (NORMALIZEBUFFERSIZE() == 0) {
|
||||
allocBuffer(_nLength + nAllocAmount);
|
||||
memcpy(_pszData, lpszSrcData, nSrcLen);
|
||||
*(_pszData + nSrcLen) = '\0';
|
||||
_nLength = (uint16)(_nLength + (uint16)nSrcLen);
|
||||
|
||||
} else {
|
||||
assert(_pszData != nullptr);
|
||||
|
||||
// We have to grow the buffer, use the concat in place routine
|
||||
char *lpszOldData;
|
||||
|
||||
if ((_nLength + nSrcLen + 1) < 512)
|
||||
lpszOldData = szLocalBuff;
|
||||
else
|
||||
lpszOldData = new char[_nLength + nSrcLen + 1];
|
||||
|
||||
memcpy(lpszOldData, _pszData, (_nLength + 1) * sizeof(char));
|
||||
concatCopy(_nLength, lpszOldData, nSrcLen, lpszSrcData, _nLength + nAllocAmount);
|
||||
|
||||
if (lpszOldData != szLocalBuff)
|
||||
delete[] lpszOldData;
|
||||
}
|
||||
} else {
|
||||
|
||||
// Fast concatenation when buffer big enough
|
||||
// Optimize for a single byte
|
||||
|
||||
if (nSrcLen == 1) {
|
||||
_pszData[_nLength] = *lpszSrcData;
|
||||
} else {
|
||||
memcpy(&_pszData[_nLength], lpszSrcData, nSrcLen * sizeof(char));
|
||||
}
|
||||
_nLength = (uint16)(_nLength + (uint16)nSrcLen);
|
||||
}
|
||||
|
||||
assert(_nLength <= NORMALIZEBUFFERSIZE());
|
||||
_pszData[_nLength] = '\0';
|
||||
}
|
||||
|
||||
const CBofString &CBofString::operator+=(const char *lpsz) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
concatInPlace(safeStrlen(lpsz), lpsz);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBofString &CBofString::operator+=(char ch) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
concatInPlace(1, &ch);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const CBofString &CBofString::operator+=(const CBofString &string) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
concatInPlace(string._nLength, string._pszData);
|
||||
return *this;
|
||||
}
|
||||
|
||||
char *CBofString::getBuffer() {
|
||||
assert(isValidObject(this));
|
||||
|
||||
if (_pszData == nullptr) {
|
||||
allocBuffer(1);
|
||||
}
|
||||
|
||||
return _pszData;
|
||||
}
|
||||
|
||||
int CBofString::findNumOccurrences(const char *pszSub) {
|
||||
assert(isValidObject(this));
|
||||
assert(pszSub != nullptr);
|
||||
assert(*pszSub != '\0');
|
||||
|
||||
int nHits = 0;
|
||||
if (_pszData != nullptr) {
|
||||
char *pszCur = _pszData;
|
||||
while (pszCur != nullptr) {
|
||||
pszCur = strstr(pszCur, pszSub);
|
||||
if (pszCur != nullptr) {
|
||||
nHits++;
|
||||
pszCur++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nHits;
|
||||
}
|
||||
|
||||
const CBofString &CBofString::operator=(char ch) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
char szBuf[4];
|
||||
|
||||
Common::sprintf_s(szBuf, "%c", ch);
|
||||
copy(szBuf);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
CBofString operator+(const CBofString &string1, char ch) {
|
||||
CBofString s;
|
||||
s.concatCopy(string1._nLength, string1._pszData, 1, &ch);
|
||||
return s;
|
||||
}
|
||||
|
||||
CBofString operator+(char ch, const CBofString &string) {
|
||||
CBofString s;
|
||||
s.concatCopy(1, &ch, string._nLength, string._pszData);
|
||||
return s;
|
||||
}
|
||||
|
||||
CBofString CBofString::mid(int nFirst) const {
|
||||
assert(isValidObject(this));
|
||||
|
||||
return mid(nFirst, _nLength - nFirst);
|
||||
}
|
||||
|
||||
CBofString CBofString::mid(int nFirst, int nCount) const {
|
||||
assert(isValidObject(this));
|
||||
|
||||
assert(nFirst >= 0);
|
||||
assert(nCount >= 0);
|
||||
|
||||
// Out-of-bounds requests return sensible things
|
||||
if (nFirst + nCount > _nLength)
|
||||
nCount = _nLength - nFirst;
|
||||
if (nFirst > _nLength)
|
||||
nCount = 0;
|
||||
|
||||
CBofString dest;
|
||||
allocCopy(dest, nCount, nFirst, 0);
|
||||
return dest;
|
||||
}
|
||||
|
||||
CBofString CBofString::right(int nCount) const {
|
||||
assert(isValidObject(this));
|
||||
|
||||
assert(nCount >= 0);
|
||||
|
||||
if (nCount > _nLength)
|
||||
nCount = _nLength;
|
||||
|
||||
CBofString dest;
|
||||
allocCopy(dest, nCount, _nLength - nCount, 0);
|
||||
return dest;
|
||||
}
|
||||
|
||||
CBofString CBofString::left(int nCount) const {
|
||||
assert(isValidObject(this));
|
||||
|
||||
assert(nCount >= 0);
|
||||
|
||||
if (nCount > _nLength)
|
||||
nCount = _nLength;
|
||||
|
||||
CBofString dest;
|
||||
allocCopy(dest, nCount, 0, 0);
|
||||
return dest;
|
||||
}
|
||||
|
||||
void CBofString::deleteLastChar() {
|
||||
if (!isEmpty()) {
|
||||
*(_pszData + _nLength - 1) = '\0';
|
||||
--_nLength;
|
||||
}
|
||||
}
|
||||
|
||||
// Find a sub-string (like strstr)
|
||||
int CBofString::find(const char *lpszSub) const {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// Find first matching substring
|
||||
char *lpsz = nullptr;
|
||||
|
||||
if (_pszData != nullptr)
|
||||
lpsz = strstr(_pszData, lpszSub);
|
||||
|
||||
// Return -1 for not found, distance from beginning otherwise
|
||||
return (lpsz == nullptr) ? -1 : (int)(lpsz - _pszData);
|
||||
}
|
||||
|
||||
// CBofString formatting
|
||||
|
||||
#define FORCE_ANSI 0x10000
|
||||
#define FORCE_UNICODE 0x20000
|
||||
|
||||
int CBofString::safeStrlen(const char *psz) {
|
||||
return (psz == nullptr) ? 0 : strlen(psz);
|
||||
}
|
||||
|
||||
// CBofString support (windows specific)
|
||||
//
|
||||
int CBofString::compare(const char *psz) const {
|
||||
assert(isValidObject(this));
|
||||
assert(psz != nullptr);
|
||||
|
||||
int n = -1;
|
||||
|
||||
if (_pszData != nullptr)
|
||||
n = strcmp(_pszData, psz);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int CBofString::compareNoCase(const char *psz) const {
|
||||
assert(isValidObject(this));
|
||||
|
||||
int n = -1;
|
||||
|
||||
if (_pszData != nullptr)
|
||||
n = scumm_stricmp(_pszData, psz);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
char CBofString::getAt(int nIndex) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
assert(nIndex >= 0);
|
||||
assert(nIndex < _nLength);
|
||||
|
||||
return _pszData[nIndex];
|
||||
}
|
||||
|
||||
char CBofString::operator[](int nIndex) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
return getAt(nIndex);
|
||||
}
|
||||
|
||||
void CBofString::replaceCharAt(int nIndex, char chNew) {
|
||||
if (_pszData != nullptr && nIndex < _nLength) {
|
||||
_pszData[nIndex] = chNew;
|
||||
}
|
||||
}
|
||||
|
||||
void CBofString::replaceChar(char chOld, char chNew) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// Would never find the terminator
|
||||
assert(chOld != '\0');
|
||||
|
||||
if (_pszData != nullptr) {
|
||||
// Walk through the string and replace the specified character
|
||||
char *p = _pszData;
|
||||
for (int i = 0; i < _nLength; i++) {
|
||||
if (*p == chOld) {
|
||||
*p = chNew;
|
||||
|
||||
// If we just inserted the terminator, then the length of
|
||||
// this string has been changed, and we don't have to search
|
||||
// any more.
|
||||
//
|
||||
if (chNew == '\0') {
|
||||
_nLength = (uint16)i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CBofString::replaceStr(const char *pszOld, const char *pszNew) {
|
||||
assert(isValidObject(this));
|
||||
assert(pszOld != nullptr);
|
||||
assert(pszNew != nullptr);
|
||||
|
||||
if (_pszData != nullptr) {
|
||||
char *p, *pszSearch;
|
||||
|
||||
int nOldLen = strlen(pszOld);
|
||||
int nNewLen = strlen(pszNew);
|
||||
|
||||
// 1st pass to determine how much more storage space we might need
|
||||
if (nNewLen > nOldLen) {
|
||||
int nDiff = nNewLen - nOldLen;
|
||||
int nNeedLength = _nLength + 1;
|
||||
p = _pszData;
|
||||
pszSearch = strstr(p, pszOld);
|
||||
while (pszSearch != nullptr) {
|
||||
p = pszSearch + nOldLen;
|
||||
|
||||
nNeedLength += nDiff;
|
||||
pszSearch = strstr(p, pszOld);
|
||||
}
|
||||
|
||||
// If we need more storage space for the buffer, then get some
|
||||
if (nNeedLength > NORMALIZEBUFFERSIZE()) {
|
||||
growTo(nNeedLength);
|
||||
}
|
||||
}
|
||||
|
||||
// Loop on the search and replace
|
||||
// Make sure we loop on this, not just once as we can have several occurrences
|
||||
// of the token that we are searching for.
|
||||
|
||||
p = _pszData;
|
||||
pszSearch = strstr(p, pszOld);
|
||||
while (pszSearch != nullptr) {
|
||||
strreplaceStr(p, pszOld, pszNew);
|
||||
p = pszSearch + nNewLen;
|
||||
pszSearch = strstr(p, pszOld);
|
||||
}
|
||||
|
||||
// Get new length
|
||||
_nLength = (uint16)strlen(_pszData);
|
||||
}
|
||||
}
|
||||
|
||||
void CBofString::growTo(int nNewSize) {
|
||||
assert(isValidObject(this));
|
||||
|
||||
// If there is nothing in the buffer to save, then just allocate what
|
||||
// is needed
|
||||
if (_nLength == 0) {
|
||||
allocBuffer(nNewSize);
|
||||
|
||||
} else {
|
||||
// Otherwise, we must keep track of whats in the buffer
|
||||
// Create a temp buffer to save string
|
||||
char *p = (char *)bofAlloc(_nLength + 2);
|
||||
|
||||
// Save copy of string
|
||||
Common::strcpy_s(p, MAX_STRING, _pszData);
|
||||
|
||||
// Make the new buffer
|
||||
allocBuffer(nNewSize);
|
||||
|
||||
// Copy saved string back
|
||||
strncpy(_pszData, p, nNewSize - 1);
|
||||
|
||||
// Get it's new length
|
||||
_nLength = (uint16)strlen(_pszData);
|
||||
|
||||
// Don't need temp buffer anymore
|
||||
bofFree(p);
|
||||
}
|
||||
}
|
||||
|
||||
int CBofString::hash() const {
|
||||
int returnValue = 0;
|
||||
|
||||
// Needs to be case in-sensitive
|
||||
for (int i = 0; i < _nLength; i++) {
|
||||
returnValue = returnValue + (char)toupper(_pszData[i]);
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
void CBofString::makeUpper() {
|
||||
Common::String s(_pszData);
|
||||
s.toUppercase();
|
||||
|
||||
strncpy(_pszData, s.c_str(), _nLength);
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
274
engines/bagel/boflib/string.h
Normal file
274
engines/bagel/boflib/string.h
Normal file
@@ -0,0 +1,274 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_STRING_H
|
||||
#define BAGEL_BOFLIB_STRING_H
|
||||
|
||||
#include "common/system.h"
|
||||
#include "bagel/boflib/object.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
// The buffer size and string len members are shorts, and use the high byte
|
||||
// of the buffer size to tell us if it is stack memory being used.
|
||||
#define mUseStackMem 0x8000
|
||||
#define NORMALIZEBUFFERSIZE() (_nBufferSize & ~mUseStackMem)
|
||||
#define SETBUFFERSIZE(size, usestackmem) (_nBufferSize = (uint16)((size) + ((usestackmem) ? mUseStackMem : 0)))
|
||||
#define USESSTACKMEM() (_nBufferSize & mUseStackMem)
|
||||
|
||||
class CBofString : public CBofObject {
|
||||
public:
|
||||
// Constructors
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
CBofString();
|
||||
|
||||
/**
|
||||
* Construct a string from a null terminated string
|
||||
* @param pszBuf Source string
|
||||
*/
|
||||
CBofString(const char *pszBuf);
|
||||
|
||||
/**
|
||||
* Construct a string based on a source string
|
||||
*/
|
||||
CBofString(const CBofString &stringSrc);
|
||||
|
||||
/**
|
||||
* Construct a string with a single character repeated a number of times
|
||||
* @param ch Character to use
|
||||
* @param nRepeat Number of repeats
|
||||
*/
|
||||
CBofString(char ch, int nRepeat = 1);
|
||||
|
||||
/**
|
||||
* Constructs a string, and sets initial buffer size
|
||||
* @param nLength String length
|
||||
*/
|
||||
CBofString(int nLength);
|
||||
|
||||
/**
|
||||
* Construct a string based on a subset of a passed null terminated string
|
||||
* @brief This modifies the passed source string to null terminate the substring
|
||||
* @param pszBuff Source string
|
||||
* @param pszBuffLen Substring length
|
||||
*/
|
||||
CBofString(char *pszBuff, int pszBuffLen);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~CBofString();
|
||||
|
||||
// Attributes & Operations
|
||||
|
||||
int getBufferSize() const {
|
||||
return NORMALIZEBUFFERSIZE();
|
||||
}
|
||||
int getLength() const {
|
||||
return _nLength;
|
||||
}
|
||||
bool isEmpty() const {
|
||||
return _nLength == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* De-Allocates internal buffer for current CBofString
|
||||
*/
|
||||
void free();
|
||||
|
||||
void growTo(int nNewSize); // Resize the buffer
|
||||
|
||||
char getAt(int nIndex); // 0 based
|
||||
char operator[](int nIndex); // same as getAt
|
||||
|
||||
operator const char *() const {
|
||||
return (const char *)_pszData;
|
||||
}
|
||||
const char *getBuffer() const {
|
||||
return _pszData;
|
||||
}
|
||||
|
||||
// Hashing support.
|
||||
//
|
||||
int hash() const;
|
||||
|
||||
// Overloaded assignment
|
||||
/**
|
||||
* Copies specified string into current CBofString
|
||||
* @param pszSourceBuf Buffer to copy
|
||||
*/
|
||||
void copy(const char *pszSourceBuf);
|
||||
|
||||
const CBofString &operator=(const CBofString &cStringSrc);
|
||||
const CBofString &operator=(char ch);
|
||||
const CBofString &operator=(const char *psz);
|
||||
|
||||
// String concatenation
|
||||
const CBofString &operator+=(const CBofString &cString);
|
||||
const CBofString &operator+=(char ch);
|
||||
const CBofString &operator+=(const char *psz);
|
||||
|
||||
friend CBofString operator+(const CBofString &string1, const CBofString &string2);
|
||||
friend CBofString operator+(const CBofString &string, char ch);
|
||||
friend CBofString operator+(char ch, const CBofString &string);
|
||||
friend CBofString operator+(const CBofString &string, const char *lpsz);
|
||||
friend CBofString operator+(const char *lpsz, const CBofString &string);
|
||||
|
||||
// String comparison
|
||||
int compare(const char *lpsz) const; // straight character
|
||||
int compareNoCase(const char *lpsz) const; // ignore case
|
||||
|
||||
// Simple sub-string extraction
|
||||
//
|
||||
CBofString mid(int nFirst, int nCount) const;
|
||||
CBofString mid(int nFirst) const;
|
||||
CBofString left(int nCount) const;
|
||||
CBofString right(int nCount) const;
|
||||
|
||||
void deleteLastChar();
|
||||
|
||||
// Upper/lower/reverse conversion
|
||||
void makeUpper();
|
||||
|
||||
// Searching (return starting index, or -1 if not found)
|
||||
// Look for a specific sub-string
|
||||
int find(const char *lpszSub) const; // like "C" strstr
|
||||
int findNumOccurrences(const char *pszSub);
|
||||
|
||||
// Search and replace routines
|
||||
void replaceCharAt(int, char);
|
||||
void replaceChar(char chOld, char chNew);
|
||||
void replaceStr(const char *pszOld, const char *pszNew);
|
||||
|
||||
// Access to string implementation buffer as "C" character array
|
||||
char *getBuffer();
|
||||
|
||||
protected:
|
||||
// implementation helpers
|
||||
|
||||
/**
|
||||
* initialize current CBofString members
|
||||
*/
|
||||
void init();
|
||||
|
||||
/**
|
||||
* Allocates specified string into specified destination
|
||||
*/
|
||||
void allocCopy(CBofString &dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;
|
||||
|
||||
/**
|
||||
* Allocates internal buffer for current CBofString
|
||||
* @param nLen Initial buffer size
|
||||
*/
|
||||
void allocBuffer(int nLen);
|
||||
|
||||
void concatCopy(int nSrc1Len, const char *lpszSrc1Data, int nSrc2Len, const char *lpszSrc2Data, int nAllocLen = 0);
|
||||
void concatInPlace(int nSrcLen, const char *lpszSrcData);
|
||||
static int safeStrlen(const char *lpsz);
|
||||
|
||||
// Lengths/sizes in characters
|
||||
// (note: an extra character is always allocated)
|
||||
//
|
||||
char *_pszData; // actual string (zero terminated)
|
||||
uint16 _nLength; // does not include terminating 0
|
||||
uint16 _nBufferSize; // does not include terminating 0
|
||||
};
|
||||
|
||||
// Inline Comparison operators
|
||||
//
|
||||
inline bool operator==(const CBofString &s1, const CBofString &s2) {
|
||||
return s1.compare(s2) == 0;
|
||||
}
|
||||
|
||||
inline bool operator==(const CBofString &s1, const char *s2) {
|
||||
return s1.compare(s2) == 0;
|
||||
}
|
||||
|
||||
inline bool operator==(const char *s1, const CBofString &s2) {
|
||||
return s2.compare(s1) == 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const CBofString &s1, const CBofString &s2) {
|
||||
return s1.compare(s2) != 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const CBofString &s1, const char *s2) {
|
||||
return s1.compare(s2) != 0;
|
||||
}
|
||||
|
||||
inline bool operator!=(const char *s1, const CBofString &s2) {
|
||||
return s2.compare(s1) != 0;
|
||||
}
|
||||
|
||||
inline bool operator<(const CBofString &s1, const CBofString &s2) {
|
||||
return s1.compare(s2) < 0;
|
||||
}
|
||||
|
||||
inline bool operator<(const CBofString &s1, const char *s2) {
|
||||
return s1.compare(s2) < 0;
|
||||
}
|
||||
|
||||
inline bool operator<(const char *s1, const CBofString &s2) {
|
||||
return s2.compare(s1) > 0;
|
||||
}
|
||||
|
||||
inline bool operator>(const CBofString &s1, const CBofString &s2) {
|
||||
return s1.compare(s2) > 0;
|
||||
}
|
||||
|
||||
inline bool operator>(const CBofString &s1, const char *s2) {
|
||||
return s1.compare(s2) > 0;
|
||||
}
|
||||
|
||||
inline bool operator>(const char *s1, const CBofString &s2) {
|
||||
return s2.compare(s1) < 0;
|
||||
}
|
||||
|
||||
inline bool operator<=(const CBofString &s1, const CBofString &s2) {
|
||||
return s1.compare(s2) <= 0;
|
||||
}
|
||||
|
||||
inline bool operator<=(const CBofString &s1, const char *s2) {
|
||||
return s1.compare(s2) <= 0;
|
||||
}
|
||||
|
||||
inline bool operator<=(const char *s1, const CBofString &s2) {
|
||||
return s2.compare(s1) >= 0;
|
||||
}
|
||||
|
||||
inline bool operator>=(const CBofString &s1, const CBofString &s2) {
|
||||
return s1.compare(s2) >= 0;
|
||||
}
|
||||
|
||||
inline bool operator>=(const CBofString &s1, const char *s2) {
|
||||
return s1.compare(s2) >= 0;
|
||||
}
|
||||
|
||||
inline bool operator>=(const char *s1, const CBofString &s2) {
|
||||
return s2.compare(s1) <= 0;
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
98
engines/bagel/boflib/string_functions.cpp
Normal file
98
engines/bagel/boflib/string_functions.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
/* 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/str.h"
|
||||
|
||||
#include "bagel/boflib/string_functions.h"
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
int strCharCount(const char *str, char c) {
|
||||
assert(str != nullptr);
|
||||
|
||||
int n = 0;
|
||||
while (*str != '\0') {
|
||||
if (*str++ == c)
|
||||
n++;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
char *strreplaceChar(char *str, char cOld, char cNew) {
|
||||
char *p = str;
|
||||
|
||||
// Can't access a nullptr 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;
|
||||
}
|
||||
|
||||
char *strreplaceStr(char *pszBuf, const char *pszTok, const char *pszNewTok) {
|
||||
// Can't access nullptr pointers
|
||||
assert(pszBuf != nullptr);
|
||||
assert(pszTok != nullptr);
|
||||
assert(pszNewTok != nullptr);
|
||||
|
||||
// Search token, and new token can't be the same
|
||||
assert(strcmp(pszTok, pszNewTok) != 0);
|
||||
|
||||
int nTok = strlen(pszTok);
|
||||
int nNewTok = strlen(pszNewTok);
|
||||
int nDiff = nTok - nNewTok;
|
||||
|
||||
char *p = pszBuf;
|
||||
for (char *pszSearch = strstr(p, pszTok); pszSearch; pszSearch = strstr(p, pszTok)) {
|
||||
char *pszEndTok = pszSearch + nTok;
|
||||
|
||||
if (nDiff != 0) {
|
||||
memmove(pszEndTok - nDiff, pszEndTok, strlen(pszEndTok) + 1);
|
||||
}
|
||||
memcpy(pszSearch, pszNewTok, nNewTok);
|
||||
}
|
||||
|
||||
return pszBuf;
|
||||
}
|
||||
|
||||
void memreplaceChar(byte *pBuf, byte chOld, byte chNew, int32 lSize) {
|
||||
assert(pBuf != nullptr);
|
||||
assert(chOld != chNew);
|
||||
|
||||
while (lSize-- > 0) {
|
||||
|
||||
if (*pBuf == chOld) {
|
||||
*pBuf = chNew;
|
||||
}
|
||||
pBuf++;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Bagel
|
||||
65
engines/bagel/boflib/string_functions.h
Normal file
65
engines/bagel/boflib/string_functions.h
Normal file
@@ -0,0 +1,65 @@
|
||||
|
||||
/* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BAGEL_BOFLIB_STRING_FUNCTIONS_H
|
||||
#define BAGEL_BOFLIB_STRING_FUNCTIONS_H
|
||||
|
||||
namespace Bagel {
|
||||
|
||||
/**
|
||||
* Counts number of occurrences of a specified char in String
|
||||
* @param str Pointer to string to parse
|
||||
* @param c Character to count in str
|
||||
* @return Number of times character c occurs in string str
|
||||
*/
|
||||
extern int strCharCount(const char *str, char c);
|
||||
|
||||
/**
|
||||
* Replaces all occurrences of cOld in string with cNew
|
||||
* @param pszbuf String to search
|
||||
* @param cOld Character to find in pszBuf
|
||||
* @param cNew Character to replace cOld
|
||||
* @return Pointer to pszBuf
|
||||
*/
|
||||
extern char *strreplaceChar(char *pszbuf, char cOld, char cNew);
|
||||
|
||||
/**
|
||||
* Replaces every occurrence of 1 character with another
|
||||
* @param pBuf Buffer to search
|
||||
* @param chOld Old character to be replaced
|
||||
* @param chNew New character to replace with
|
||||
* @param lSize Size of buffer
|
||||
*/
|
||||
extern void memreplaceChar(byte *pBuf, byte chOld, byte chNew, int32 lSize);
|
||||
|
||||
/**
|
||||
* Replaces all tokens in string with new token
|
||||
* @param pszBuf Buffer to search
|
||||
* @param pszTok1 Token to search for in pszBuf
|
||||
* @param pszTok2 Replacement token
|
||||
* @return Pointer to pszBuf.
|
||||
*/
|
||||
extern char *strreplaceStr(char *pszBuf, const char *pszTok1, const char *pszTok2);
|
||||
|
||||
} // namespace Bagel
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user