synced imuse digital with scummvm imuse and related stuff
This commit is contained in:
parent
857527b278
commit
f11e24b7b1
32 changed files with 1536 additions and 781 deletions
52
common/frac.h
Normal file
52
common/frac.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_FRAC_H
|
||||||
|
#define COMMON_FRAC_H
|
||||||
|
|
||||||
|
#include "common/sys.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The precision of the fractional (fixed point) type we define below.
|
||||||
|
* Normally you should never have to modify this value.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
FRAC_BITS = 16,
|
||||||
|
FRAC_LO_MASK = ((1L << FRAC_BITS) - 1),
|
||||||
|
FRAC_HI_MASK = ((1L << FRAC_BITS) - 1) << FRAC_BITS,
|
||||||
|
|
||||||
|
FRAC_ONE = (1L << FRAC_BITS), // 1.0
|
||||||
|
FRAC_HALF = (1L << (FRAC_BITS-1)) // 0.5
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed-point fractions, used by the sound rate converter and other code.
|
||||||
|
*/
|
||||||
|
typedef int32 frac_t;
|
||||||
|
|
||||||
|
inline frac_t doubleToFrac(double value) { return (frac_t)(value * FRAC_ONE); }
|
||||||
|
inline double fracToDouble(frac_t value) { return ((double)value) / FRAC_ONE; }
|
||||||
|
|
||||||
|
inline frac_t intToFrac(int16 value) { return value << FRAC_BITS; }
|
||||||
|
inline int16 fracToInt(frac_t value) { return value >> FRAC_BITS; }
|
||||||
|
|
||||||
|
#endif
|
264
common/list.h
Normal file
264
common/list.h
Normal file
|
@ -0,0 +1,264 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_LIST_H
|
||||||
|
#define COMMON_LIST_H
|
||||||
|
|
||||||
|
#include "common/sys.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple double linked list, modeled after the list template of the standard
|
||||||
|
* C++ library.
|
||||||
|
*/
|
||||||
|
template <class t_T>
|
||||||
|
class List {
|
||||||
|
protected:
|
||||||
|
#if defined (_WIN32_WCE) || defined (_MSC_VER)
|
||||||
|
//FIXME evc4 and msvc7 doesn't like it as protected member
|
||||||
|
public:
|
||||||
|
#endif
|
||||||
|
struct NodeBase {
|
||||||
|
NodeBase *_prev;
|
||||||
|
NodeBase *_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class t_T2>
|
||||||
|
struct Node : public NodeBase {
|
||||||
|
t_T2 _data;
|
||||||
|
|
||||||
|
Node(const t_T2 &x) : _data(x) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class t_T2>
|
||||||
|
class Iterator {
|
||||||
|
friend class List<t_T>;
|
||||||
|
NodeBase *_node;
|
||||||
|
|
||||||
|
#if !defined (__WINSCW__)
|
||||||
|
explicit Iterator(NodeBase *node) : _node(node) {}
|
||||||
|
#else
|
||||||
|
Iterator(NodeBase *node) : _node(node) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public:
|
||||||
|
Iterator() : _node(0) {}
|
||||||
|
|
||||||
|
// Prefix inc
|
||||||
|
Iterator<t_T2> &operator++() {
|
||||||
|
if (_node)
|
||||||
|
_node = _node->_next;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// Postfix inc
|
||||||
|
Iterator<t_T2> operator++(int) {
|
||||||
|
Iterator tmp(_node);
|
||||||
|
++(*this);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
// Prefix dec
|
||||||
|
Iterator<t_T2> &operator--() {
|
||||||
|
if (_node)
|
||||||
|
_node = _node->_prev;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// Postfix dec
|
||||||
|
Iterator<t_T2> operator--(int) {
|
||||||
|
Iterator tmp(_node);
|
||||||
|
--(*this);
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
t_T2& operator*() const {
|
||||||
|
assert(_node);
|
||||||
|
#if (__GNUC__ == 2) && (__GNUC_MINOR__ >= 95)
|
||||||
|
return static_cast<List<t_T>::Node<t_T2> *>(_node)->_data;
|
||||||
|
#else
|
||||||
|
return static_cast<Node<t_T2>*>(_node)->_data;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
t_T2* operator->() const {
|
||||||
|
return &(operator*());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Iterator<t_T2>& x) const {
|
||||||
|
return _node == x._node;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Iterator<t_T2>& x) const {
|
||||||
|
return _node != x._node;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
NodeBase *_anchor;
|
||||||
|
|
||||||
|
public:
|
||||||
|
typedef Iterator<t_T> iterator;
|
||||||
|
typedef Iterator<const t_T> const_iterator;
|
||||||
|
|
||||||
|
typedef t_T value_type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
List() {
|
||||||
|
_anchor = new NodeBase;
|
||||||
|
_anchor->_prev = _anchor;
|
||||||
|
_anchor->_next = _anchor;
|
||||||
|
}
|
||||||
|
List(const List<t_T>& list) {
|
||||||
|
_anchor = new NodeBase;
|
||||||
|
_anchor->_prev = _anchor;
|
||||||
|
_anchor->_next = _anchor;
|
||||||
|
|
||||||
|
insert(begin(), list.begin(), list.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
~List() {
|
||||||
|
clear();
|
||||||
|
delete _anchor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_front(const t_T& element) {
|
||||||
|
insert(begin(), element);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const t_T& element) {
|
||||||
|
insert(end(), element);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(iterator pos, const t_T& element) {
|
||||||
|
NodeBase *newNode = new Node<t_T>(element);
|
||||||
|
|
||||||
|
newNode->_next = pos._node;
|
||||||
|
newNode->_prev = pos._node->_prev;
|
||||||
|
newNode->_prev->_next = newNode;
|
||||||
|
newNode->_next->_prev = newNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename iterator2>
|
||||||
|
void insert(iterator pos, iterator2 first, iterator2 last) {
|
||||||
|
for (; first != last; ++first)
|
||||||
|
insert(pos, *first);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator erase(iterator pos) {
|
||||||
|
assert(pos != end());
|
||||||
|
|
||||||
|
NodeBase *next = pos._node->_next;
|
||||||
|
NodeBase *prev = pos._node->_prev;
|
||||||
|
Node<t_T> *node = static_cast<Node<t_T> *>(pos._node);
|
||||||
|
prev->_next = next;
|
||||||
|
next->_prev = prev;
|
||||||
|
delete node;
|
||||||
|
return iterator(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator reverse_erase(iterator pos) {
|
||||||
|
assert(pos != end());
|
||||||
|
|
||||||
|
NodeBase *next = pos._node->_next;
|
||||||
|
NodeBase *prev = pos._node->_prev;
|
||||||
|
Node<t_T> *node = static_cast<Node<t_T> *>(pos._node);
|
||||||
|
prev->_next = next;
|
||||||
|
next->_prev = prev;
|
||||||
|
delete node;
|
||||||
|
return iterator(prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator erase(iterator first, iterator last) {
|
||||||
|
while (first != last)
|
||||||
|
erase(first++);
|
||||||
|
|
||||||
|
return last;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(const t_T &val) {
|
||||||
|
iterator i = begin();
|
||||||
|
while (i != end())
|
||||||
|
if (val == i.operator*())
|
||||||
|
i = erase(i);
|
||||||
|
else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
List<t_T>& operator =(const List<t_T>& list) {
|
||||||
|
if (this != &list) {
|
||||||
|
iterator i;
|
||||||
|
const_iterator j;
|
||||||
|
|
||||||
|
for (i = begin(), j = list.begin(); (i != end()) && (j != list.end()) ; ++i, ++j) {
|
||||||
|
static_cast<Node<t_T> *>(i._node)->_data = static_cast<Node<t_T> *>(j._node)->_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == end())
|
||||||
|
insert(i, j, list.end());
|
||||||
|
else
|
||||||
|
erase(i, end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint size() const {
|
||||||
|
int n = 0;
|
||||||
|
for (const_iterator i = begin(); i != end(); ++i)
|
||||||
|
++n;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
erase(begin(), end());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool empty() const {
|
||||||
|
return (_anchor == _anchor->_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
iterator begin() {
|
||||||
|
return iterator(_anchor->_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator reverse_begin() {
|
||||||
|
return iterator(_anchor->_prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
iterator end() {
|
||||||
|
return iterator(_anchor);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator begin() const {
|
||||||
|
return const_iterator(_anchor->_next);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator reverse_begin() const {
|
||||||
|
return const_iterator(_anchor->_prev);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_iterator end() const {
|
||||||
|
return const_iterator(_anchor);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of namespace Common
|
||||||
|
|
||||||
|
#endif
|
72
common/mutex.cpp
Normal file
72
common/mutex.cpp
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/mutex.h"
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
#include "engine/backend/driver.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
Mutex::Mutex() {
|
||||||
|
_mutex = g_driver->createMutex();
|
||||||
|
}
|
||||||
|
|
||||||
|
Mutex::~Mutex() {
|
||||||
|
g_driver->deleteMutex(_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::lock() {
|
||||||
|
g_driver->lockMutex(_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mutex::unlock() {
|
||||||
|
g_driver->unlockMutex(_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
StackLock::StackLock(MutexRef mutex, const char *mutexName)
|
||||||
|
: _mutex(mutex), _mutexName(mutexName) {
|
||||||
|
lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
StackLock::StackLock(const Mutex &mutex, const char *mutexName)
|
||||||
|
: _mutex(mutex._mutex), _mutexName(mutexName) {
|
||||||
|
lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
StackLock::~StackLock() {
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StackLock::lock() {
|
||||||
|
g_driver->lockMutex(_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StackLock::unlock() {
|
||||||
|
g_driver->unlockMutex(_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // End of namespace Common
|
73
common/mutex.h
Normal file
73
common/mutex.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_MUTEX_H
|
||||||
|
#define COMMON_MUTEX_H
|
||||||
|
|
||||||
|
#include "common/sys.h"
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
class Mutex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An pseudo-opaque mutex type.
|
||||||
|
*/
|
||||||
|
typedef struct OpaqueMutex *MutexRef;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auxillary class to (un)lock a mutex on the stack.
|
||||||
|
*/
|
||||||
|
class StackLock {
|
||||||
|
MutexRef _mutex;
|
||||||
|
const char *_mutexName;
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
public:
|
||||||
|
StackLock(MutexRef mutex, const char *mutexName = NULL);
|
||||||
|
StackLock(const Mutex &mutex, const char *mutexName = NULL);
|
||||||
|
~StackLock();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class.
|
||||||
|
*/
|
||||||
|
class Mutex {
|
||||||
|
friend class StackLock;
|
||||||
|
|
||||||
|
MutexRef _mutex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Mutex();
|
||||||
|
~Mutex();
|
||||||
|
|
||||||
|
void lock();
|
||||||
|
void unlock();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // End of namespace Common
|
||||||
|
|
||||||
|
#endif
|
43
common/noncopyable.h
Normal file
43
common/noncopyable.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef COMMON_NONCOPYABLE_H
|
||||||
|
#define COMMON_NONCOPYABLE_H
|
||||||
|
|
||||||
|
namespace Common {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclass of NonCopyable can not be copied due to the fact that
|
||||||
|
* we made the copy constructor and assigment operator private.
|
||||||
|
*/
|
||||||
|
class NonCopyable {
|
||||||
|
public:
|
||||||
|
NonCopyable() {}
|
||||||
|
private:
|
||||||
|
// Prevent copying instances by accident
|
||||||
|
NonCopyable(const NonCopyable&);
|
||||||
|
NonCopyable& operator= (const NonCopyable&);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End of namespace Common
|
||||||
|
|
||||||
|
#endif
|
|
@ -24,8 +24,6 @@
|
||||||
#define COMMON_SYS_H
|
#define COMMON_SYS_H
|
||||||
|
|
||||||
|
|
||||||
typedef struct Mutex *MutexRef;
|
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
135
common/timer.cpp
135
common/timer.cpp
|
@ -1,135 +0,0 @@
|
||||||
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
|
||||||
* Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
|
|
||||||
* This library 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
|
|
||||||
* Lesser General Public License for more details.
|
|
||||||
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with this library; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
||||||
*
|
|
||||||
* $URL$
|
|
||||||
* $Id$
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "common/sys.h"
|
|
||||||
#include "common/platform.h"
|
|
||||||
#include "common/debug.h"
|
|
||||||
#include "common/timer.h"
|
|
||||||
|
|
||||||
#include "engine/backend/driver.h"
|
|
||||||
|
|
||||||
Timer *g_timer = NULL;
|
|
||||||
|
|
||||||
Timer::Timer() :
|
|
||||||
_mutex(0),
|
|
||||||
_timerHandler(0),
|
|
||||||
_lastTime(0) {
|
|
||||||
|
|
||||||
_mutex = g_driver->createMutex();
|
|
||||||
|
|
||||||
g_timer = this;
|
|
||||||
|
|
||||||
for (int i = 0; i < MAX_TIMERS; i++) {
|
|
||||||
_timerSlots[i].procedure = NULL;
|
|
||||||
_timerSlots[i].interval = 0;
|
|
||||||
_timerSlots[i].counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
_thisTime = g_driver->getMillis();
|
|
||||||
|
|
||||||
// Set the timer last, after everything has been initialised
|
|
||||||
g_driver->setTimerCallback(timer_handler, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
Timer::~Timer() {
|
|
||||||
g_driver->setTimerCallback(NULL, 0);
|
|
||||||
|
|
||||||
{
|
|
||||||
StackLock lock(_mutex);
|
|
||||||
for (int i = 0; i < MAX_TIMERS; i++) {
|
|
||||||
_timerSlots[i].procedure = NULL;
|
|
||||||
_timerSlots[i].interval = 0;
|
|
||||||
_timerSlots[i].counter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_driver->deleteMutex(_mutex);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Timer::timer_handler(int t) {
|
|
||||||
if (g_timer)
|
|
||||||
return g_timer->handler(t);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Timer::handler(int t) {
|
|
||||||
StackLock lock(_mutex);
|
|
||||||
uint32 interval, l;
|
|
||||||
|
|
||||||
_lastTime = _thisTime;
|
|
||||||
_thisTime = g_driver->getMillis();
|
|
||||||
interval = 1000 * (_thisTime - _lastTime);
|
|
||||||
|
|
||||||
// If the timer has been frozen for a long time, don't
|
|
||||||
// call the procedures a silly number of times, just resynchronize
|
|
||||||
if(interval > 1000000) {
|
|
||||||
interval = 0;
|
|
||||||
warning("Timer skipped forward");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (l = 0; l < MAX_TIMERS; l++) {
|
|
||||||
if (_timerSlots[l].procedure && _timerSlots[l].interval > 0) {
|
|
||||||
_timerSlots[l].counter -= interval;
|
|
||||||
while (_timerSlots[l].counter <= 0) {
|
|
||||||
// A small paranoia check which catches the case where
|
|
||||||
// a timer removes itself (which it never should do).
|
|
||||||
assert(_timerSlots[l].procedure && _timerSlots[l].interval > 0);
|
|
||||||
_timerSlots[l].counter += _timerSlots[l].interval;
|
|
||||||
_timerSlots[l].procedure(_timerSlots[l].refCon);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Timer::installTimerProc(TimerProc procedure, int32 interval, void *refCon) {
|
|
||||||
assert(interval > 0);
|
|
||||||
StackLock lock(_mutex);
|
|
||||||
|
|
||||||
for (int l = 0; l < MAX_TIMERS; l++) {
|
|
||||||
if (!_timerSlots[l].procedure) {
|
|
||||||
_timerSlots[l].procedure = procedure;
|
|
||||||
_timerSlots[l].interval = interval;
|
|
||||||
_timerSlots[l].counter = interval;
|
|
||||||
_timerSlots[l].refCon = refCon;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
|
|
||||||
warning("Couldn't find free timer slot!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Timer::removeTimerProc(TimerProc procedure) {
|
|
||||||
StackLock lock(_mutex);
|
|
||||||
|
|
||||||
for (int l = 0; l < MAX_TIMERS; l++) {
|
|
||||||
if (_timerSlots[l].procedure == procedure) {
|
|
||||||
_timerSlots[l].procedure = 0;
|
|
||||||
_timerSlots[l].interval = 0;
|
|
||||||
_timerSlots[l].counter = 0;
|
|
||||||
_timerSlots[l].refCon = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,19 +1,19 @@
|
||||||
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
* Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
|
* Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU General Public License
|
||||||
* License as published by the Free Software Foundation; either
|
* as published by the Free Software Foundation; either version 2
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
* This library is distributed in the hope that it will be useful,
|
* This program is distributed in the hope that it will be useful,
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
* Lesser General Public License for more details.
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU General Public License
|
||||||
* License along with this library; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
*
|
*
|
||||||
* $URL$
|
* $URL$
|
||||||
* $Id$
|
* $Id$
|
||||||
|
@ -24,30 +24,15 @@
|
||||||
#define COMMON_TIMER_H
|
#define COMMON_TIMER_H
|
||||||
|
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
#include "common/platform.h"
|
#include "common/noncopyable.h"
|
||||||
|
|
||||||
#define MAX_TIMERS 3
|
namespace Common {
|
||||||
|
|
||||||
typedef void (*TimerProc)(void *refCon);
|
|
||||||
|
|
||||||
class Timer {
|
|
||||||
|
|
||||||
private:
|
|
||||||
MutexRef _mutex;
|
|
||||||
void *_timerHandler;
|
|
||||||
int32 _thisTime;
|
|
||||||
int32 _lastTime;
|
|
||||||
|
|
||||||
struct TimerSlots {
|
|
||||||
TimerProc procedure;
|
|
||||||
int32 interval;
|
|
||||||
int32 counter;
|
|
||||||
void *refCon;
|
|
||||||
} _timerSlots[MAX_TIMERS];
|
|
||||||
|
|
||||||
|
class TimerManager : NonCopyable {
|
||||||
public:
|
public:
|
||||||
Timer();
|
typedef void (*TimerProc)(void *refCon);
|
||||||
~Timer();
|
|
||||||
|
virtual ~TimerManager() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Install a new timer callback. It will from now be called every interval microseconds.
|
* Install a new timer callback. It will from now be called every interval microseconds.
|
||||||
|
@ -61,19 +46,14 @@ public:
|
||||||
* @param refCon an arbitrary void pointer; will be passed to the timer callback
|
* @param refCon an arbitrary void pointer; will be passed to the timer callback
|
||||||
* @return true if the timer was installed successfully, false otherwise
|
* @return true if the timer was installed successfully, false otherwise
|
||||||
*/
|
*/
|
||||||
bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
|
virtual bool installTimerProc(TimerProc proc, int32 interval, void *refCon) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the given timer callback. It will not be invoked anymore.
|
* Remove the given timer callback. It will not be invoked anymore.
|
||||||
*/
|
*/
|
||||||
void removeTimerProc(TimerProc proc);
|
virtual void removeTimerProc(TimerProc proc) = 0;
|
||||||
|
|
||||||
protected:
|
|
||||||
static int timer_handler(int t);
|
|
||||||
int handler(int t);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Timer *g_timer;
|
} // End of namespace Common
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -198,6 +198,14 @@
|
||||||
RelativePath="..\..\common\debug.h"
|
RelativePath="..\..\common\debug.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\common\frac.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\common\list.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\common\matrix3.cpp"
|
RelativePath="..\..\common\matrix3.cpp"
|
||||||
>
|
>
|
||||||
|
@ -214,6 +222,18 @@
|
||||||
RelativePath="..\..\common\matrix4.h"
|
RelativePath="..\..\common\matrix4.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\common\mutex.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\common\mutex.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\common\noncopyable.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\common\platform.h"
|
RelativePath="..\..\common\platform.h"
|
||||||
>
|
>
|
||||||
|
@ -222,10 +242,6 @@
|
||||||
RelativePath="..\..\common\sys.h"
|
RelativePath="..\..\common\sys.h"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
|
||||||
RelativePath="..\..\common\timer.cpp"
|
|
||||||
>
|
|
||||||
</File>
|
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\common\timer.h"
|
RelativePath="..\..\common\timer.h"
|
||||||
>
|
>
|
||||||
|
@ -781,10 +797,18 @@
|
||||||
RelativePath="..\..\engine\imuse\imuse_tables.cpp"
|
RelativePath="..\..\engine\imuse\imuse_tables.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\engine\imuse\imuse_tables.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\engine\imuse\imuse_track.cpp"
|
RelativePath="..\..\engine\imuse\imuse_track.cpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\engine\imuse\imuse_track.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="smush"
|
Name="smush"
|
||||||
|
@ -813,6 +837,14 @@
|
||||||
<Filter
|
<Filter
|
||||||
Name="backend"
|
Name="backend"
|
||||||
>
|
>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\engine\backend\default-timer.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\engine\backend\default-timer.h"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath="..\..\engine\backend\driver.h"
|
RelativePath="..\..\engine\backend\driver.h"
|
||||||
>
|
>
|
||||||
|
|
144
engine/backend/default-timer.cpp
Normal file
144
engine/backend/default-timer.cpp
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "common/sys.h"
|
||||||
|
|
||||||
|
#include "engine/backend/driver.h"
|
||||||
|
#include "engine/backend/default-timer.h"
|
||||||
|
|
||||||
|
struct TimerSlot {
|
||||||
|
Common::TimerManager::TimerProc callback;
|
||||||
|
void *refCon;
|
||||||
|
uint32 interval; // in microseconds
|
||||||
|
|
||||||
|
uint32 nextFireTime; // in milliseconds
|
||||||
|
uint32 nextFireTimeMicro; // mircoseconds part of nextFire
|
||||||
|
|
||||||
|
TimerSlot *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
void insertPrioQueue(TimerSlot *head, TimerSlot *newSlot) {
|
||||||
|
// The head points to a fake anchor TimerSlot; this common
|
||||||
|
// trick allows us to get rid of many special cases.
|
||||||
|
|
||||||
|
const uint32 nextFireTime = newSlot->nextFireTime;
|
||||||
|
TimerSlot *slot = head;
|
||||||
|
newSlot->next = 0;
|
||||||
|
|
||||||
|
// Insert the new slot into the sorted list of already scheduled
|
||||||
|
// timers in such a way that the list stays sorted...
|
||||||
|
while (true) {
|
||||||
|
assert(slot);
|
||||||
|
if (slot->next == 0 || nextFireTime < slot->next->nextFireTime) {
|
||||||
|
newSlot->next = slot->next;
|
||||||
|
slot->next = newSlot;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
slot = slot->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DefaultTimerManager::DefaultTimerManager() :
|
||||||
|
_timerHandler(0),
|
||||||
|
_head(0) {
|
||||||
|
|
||||||
|
_head = new TimerSlot();
|
||||||
|
memset(_head, 0, sizeof(TimerSlot));
|
||||||
|
}
|
||||||
|
|
||||||
|
DefaultTimerManager::~DefaultTimerManager() {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
|
|
||||||
|
TimerSlot *slot = _head;
|
||||||
|
while (slot) {
|
||||||
|
TimerSlot *next = slot->next;
|
||||||
|
delete slot;
|
||||||
|
slot = next;
|
||||||
|
}
|
||||||
|
_head = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultTimerManager::handler() {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
|
|
||||||
|
const uint32 curTime = g_driver->getMillis();
|
||||||
|
|
||||||
|
// Repeat as long as there is a TimerSlot that is scheduled to fire.
|
||||||
|
TimerSlot *slot = _head->next;
|
||||||
|
while (slot && slot->nextFireTime < curTime) {
|
||||||
|
// Remove the slot from the priority queue
|
||||||
|
_head->next = slot->next;
|
||||||
|
|
||||||
|
// Update the fire time and reinsert the TimerSlot into the priority
|
||||||
|
// queue. Has to be done before the timer callback is invoked, in case
|
||||||
|
// the callback wants to remove itself.
|
||||||
|
assert(slot->interval > 0);
|
||||||
|
slot->nextFireTime += (slot->interval / 1000);
|
||||||
|
slot->nextFireTimeMicro += (slot->interval % 1000);
|
||||||
|
if (slot->nextFireTimeMicro > 1000) {
|
||||||
|
slot->nextFireTime += slot->nextFireTimeMicro / 1000;
|
||||||
|
slot->nextFireTimeMicro %= 1000;
|
||||||
|
}
|
||||||
|
insertPrioQueue(_head, slot);
|
||||||
|
|
||||||
|
// Invoke the timer callback
|
||||||
|
assert(slot->callback);
|
||||||
|
slot->callback(slot->refCon);
|
||||||
|
|
||||||
|
// Look at the next scheduled timer
|
||||||
|
slot = _head->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DefaultTimerManager::installTimerProc(TimerProc callback, int32 interval, void *refCon) {
|
||||||
|
assert(interval > 0);
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
|
|
||||||
|
TimerSlot *slot = new TimerSlot;
|
||||||
|
slot->callback = callback;
|
||||||
|
slot->refCon = refCon;
|
||||||
|
slot->interval = interval;
|
||||||
|
slot->nextFireTime = g_driver->getMillis() + interval / 1000;
|
||||||
|
slot->nextFireTimeMicro = interval % 1000;
|
||||||
|
slot->next = 0;
|
||||||
|
|
||||||
|
insertPrioQueue(_head, slot);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DefaultTimerManager::removeTimerProc(TimerProc callback) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
|
|
||||||
|
TimerSlot *slot = _head;
|
||||||
|
|
||||||
|
while (slot->next) {
|
||||||
|
if (slot->next->callback == callback) {
|
||||||
|
TimerSlot *next = slot->next->next;
|
||||||
|
delete slot->next;
|
||||||
|
slot->next = next;
|
||||||
|
} else {
|
||||||
|
slot = slot->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
48
engine/backend/default-timer.h
Normal file
48
engine/backend/default-timer.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2008 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* 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 2
|
||||||
|
* 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, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BACKENDS_TIMER_DEFAULT_H
|
||||||
|
#define BACKENDS_TIMER_DEFAULT_H
|
||||||
|
|
||||||
|
#include "common/timer.h"
|
||||||
|
#include "common/mutex.h"
|
||||||
|
|
||||||
|
struct TimerSlot;
|
||||||
|
|
||||||
|
class DefaultTimerManager : public Common::TimerManager {
|
||||||
|
private:
|
||||||
|
Common::Mutex _mutex;
|
||||||
|
void *_timerHandler;
|
||||||
|
TimerSlot *_head;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
DefaultTimerManager();
|
||||||
|
~DefaultTimerManager();
|
||||||
|
bool installTimerProc(TimerProc proc, int32 interval, void *refCon);
|
||||||
|
void removeTimerProc(TimerProc proc);
|
||||||
|
|
||||||
|
// Timer callback, to be invoked at regular time intervals by the backend.
|
||||||
|
void handler();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
#include "common/vector3d.h"
|
#include "common/vector3d.h"
|
||||||
|
#include "common/mutex.h"
|
||||||
|
|
||||||
#include "engine/color.h"
|
#include "engine/color.h"
|
||||||
#include "engine/model.h"
|
#include "engine/model.h"
|
||||||
|
@ -33,9 +34,15 @@
|
||||||
#include "engine/font.h"
|
#include "engine/font.h"
|
||||||
#include "engine/primitives.h"
|
#include "engine/primitives.h"
|
||||||
#include "engine/actor.h"
|
#include "engine/actor.h"
|
||||||
|
#include "engine/backend/default-timer.h"
|
||||||
|
|
||||||
class Material;
|
class Material;
|
||||||
class Bitmap;
|
class Bitmap;
|
||||||
|
class Timer;
|
||||||
|
|
||||||
|
namespace Audio {
|
||||||
|
class Mixer;
|
||||||
|
}
|
||||||
|
|
||||||
class Driver {
|
class Driver {
|
||||||
public:
|
public:
|
||||||
|
@ -116,7 +123,7 @@ public:
|
||||||
/** @name Events and Time */
|
/** @name Events and Time */
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
typedef int (*TimerProc)(int interval);
|
typedef unsigned int (*TimerProc)(unsigned int interval, void *param);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The types of events backends may generate.
|
* The types of events backends may generate.
|
||||||
|
@ -239,25 +246,22 @@ public:
|
||||||
* @param interval the interval (in milliseconds) between invocations
|
* @param interval the interval (in milliseconds) between invocations
|
||||||
* of the callback
|
* of the callback
|
||||||
*/
|
*/
|
||||||
virtual void setTimerCallback(TimerProc callback, int interval) = 0;
|
virtual void setTimerCallback() = 0;
|
||||||
|
|
||||||
|
virtual void clearTimerCallback() = 0;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @name Mutex handling
|
* @name Mutex handling
|
||||||
* Historically, the OSystem API used to have a method which allowed
|
|
||||||
* creating threads. Hence mutex support was needed for thread syncing.
|
|
||||||
* To ease portability, though, we decided to remove the threading API.
|
|
||||||
* Instead, we now use timers (see setTimerCallback() and Timer).
|
|
||||||
* But since those may be implemented using threads (and in fact, that's
|
|
||||||
* how our primary backend, the SDL one, does it on many systems), we
|
|
||||||
* still have to do mutex syncing in our timer callbacks.
|
|
||||||
*
|
*
|
||||||
* Hence backends which do not use threads to implement the timers simply
|
* Hence backends which do not use threads to implement the timers simply
|
||||||
* can use dummy implementations for these methods.
|
* can use dummy implementations for these methods.
|
||||||
*/
|
*/
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
typedef Common::MutexRef MutexRef;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new mutex.
|
* Create a new mutex.
|
||||||
* @return the newly created mutex, or 0 if an error occured.
|
* @return the newly created mutex, or 0 if an error occured.
|
||||||
|
@ -266,6 +270,12 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lock the given mutex.
|
* Lock the given mutex.
|
||||||
|
*
|
||||||
|
* @note Code assumes that the mutex implementation supports
|
||||||
|
* recursive locking. That is, a thread may lock a mutex twice w/o
|
||||||
|
* deadlocking. In case of a multilock, the mutex has to be unlocked
|
||||||
|
* as many times as it was locked befored it really becomes unlocked.
|
||||||
|
*
|
||||||
* @param mutex the mutex to lock.
|
* @param mutex the mutex to lock.
|
||||||
*/
|
*/
|
||||||
virtual void lockMutex(MutexRef mutex) = 0;
|
virtual void lockMutex(MutexRef mutex) = 0;
|
||||||
|
@ -329,16 +339,7 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Driver *g_driver;
|
extern Driver *g_driver;
|
||||||
|
extern DefaultTimerManager *g_timer;
|
||||||
class StackLock {
|
extern Audio::Mixer *g_mixer;
|
||||||
MutexRef _mutex;
|
|
||||||
public:
|
|
||||||
StackLock(MutexRef mutex) : _mutex(mutex) {
|
|
||||||
g_driver->lockMutex(_mutex);
|
|
||||||
}
|
|
||||||
~StackLock() {
|
|
||||||
g_driver->unlockMutex(_mutex);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -359,11 +359,22 @@ void DriverSDL::delayMillis(uint msecs) {
|
||||||
SDL_Delay(msecs);
|
SDL_Delay(msecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriverSDL::setTimerCallback(TimerProc callback, int timer) {
|
static SDL_TimerID _timerID = NULL;
|
||||||
SDL_SetTimer(timer, (SDL_TimerCallback) callback);
|
|
||||||
|
static Uint32 timer_handler(Uint32 interval, void *param) {
|
||||||
|
((DefaultTimerManager *)param)->handler();
|
||||||
|
return interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
MutexRef DriverSDL::createMutex() {
|
void DriverSDL::setTimerCallback() {
|
||||||
|
_timerID = SDL_AddTimer(10, &timer_handler, g_timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DriverSDL::clearTimerCallback() {
|
||||||
|
SDL_RemoveTimer(_timerID);
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::MutexRef DriverSDL::createMutex() {
|
||||||
return (MutexRef)SDL_CreateMutex();
|
return (MutexRef)SDL_CreateMutex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,12 +393,20 @@ void DriverSDL::deleteMutex(MutexRef mutex) {
|
||||||
bool DriverSDL::setSoundCallback(SoundProc proc, void *param) {
|
bool DriverSDL::setSoundCallback(SoundProc proc, void *param) {
|
||||||
SDL_AudioSpec desired;
|
SDL_AudioSpec desired;
|
||||||
|
|
||||||
|
// Determine the sample buffer size. We want it to store enough data for
|
||||||
|
// about 1/10th of a second. Note that it must be a power of two.
|
||||||
|
// So e.g. at 22050 Hz, we request a sample buffer size of 2048.
|
||||||
|
int samples = 0x8000;
|
||||||
|
while (10 * samples >= _samplesPerSec) {
|
||||||
|
samples >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&desired, 0, sizeof(desired));
|
memset(&desired, 0, sizeof(desired));
|
||||||
|
|
||||||
desired.freq = _samplesPerSec;
|
desired.freq = _samplesPerSec;
|
||||||
desired.format = AUDIO_S16SYS;
|
desired.format = AUDIO_S16SYS;
|
||||||
desired.channels = 2;
|
desired.channels = 2;
|
||||||
desired.samples = 2048;
|
desired.samples = (uint16)samples;
|
||||||
desired.callback = proc;
|
desired.callback = proc;
|
||||||
desired.userdata = param;
|
desired.userdata = param;
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,8 @@ public:
|
||||||
bool pollEvent(Event &event);
|
bool pollEvent(Event &event);
|
||||||
uint32 getMillis();
|
uint32 getMillis();
|
||||||
void delayMillis(uint msecs);
|
void delayMillis(uint msecs);
|
||||||
void setTimerCallback(TimerProc callback, int interval);
|
void setTimerCallback();
|
||||||
|
void clearTimerCallback();
|
||||||
|
|
||||||
MutexRef createMutex();
|
MutexRef createMutex();
|
||||||
void lockMutex(MutexRef mutex);
|
void lockMutex(MutexRef mutex);
|
||||||
|
|
|
@ -42,7 +42,7 @@ Font::Font(const char *filename, const char *data, int /*len*/) :
|
||||||
data += 32;
|
data += 32;
|
||||||
|
|
||||||
// Read character indexes - are the key/value reversed?
|
// Read character indexes - are the key/value reversed?
|
||||||
_charIndex = (uint16 *)malloc(sizeof(_charIndex) * _numChars);
|
_charIndex = new uint16[_numChars];
|
||||||
if (!_charIndex)
|
if (!_charIndex)
|
||||||
error("Could not load font %s. Out of memory\n", filename);
|
error("Could not load font %s. Out of memory\n", filename);
|
||||||
for (uint i = 0; i < _numChars; ++i) {
|
for (uint i = 0; i < _numChars; ++i) {
|
||||||
|
@ -52,7 +52,7 @@ Font::Font(const char *filename, const char *data, int /*len*/) :
|
||||||
data += _numChars * 2;
|
data += _numChars * 2;
|
||||||
|
|
||||||
// Read character headers
|
// Read character headers
|
||||||
_charHeaders = (CharHeader *)malloc(sizeof(CharHeader) * _numChars);
|
_charHeaders = new CharHeader[_numChars];
|
||||||
if (!_charHeaders)
|
if (!_charHeaders)
|
||||||
error("Could not load font %s. Out of memory\n", filename);
|
error("Could not load font %s. Out of memory\n", filename);
|
||||||
for (uint i = 0; i < _numChars; ++i) {
|
for (uint i = 0; i < _numChars; ++i) {
|
||||||
|
@ -65,7 +65,7 @@ Font::Font(const char *filename, const char *data, int /*len*/) :
|
||||||
data += 16;
|
data += 16;
|
||||||
}
|
}
|
||||||
// Read font data
|
// Read font data
|
||||||
_fontData = (byte *)malloc(_dataSize);
|
_fontData = new byte[_dataSize];
|
||||||
if (!_fontData)
|
if (!_fontData)
|
||||||
error("Could not load font %s. Out of memory\n", filename);
|
error("Could not load font %s. Out of memory\n", filename);
|
||||||
|
|
||||||
|
@ -73,9 +73,9 @@ Font::Font(const char *filename, const char *data, int /*len*/) :
|
||||||
}
|
}
|
||||||
|
|
||||||
Font::~Font() {
|
Font::~Font() {
|
||||||
free(_charIndex);
|
delete[] _charIndex;
|
||||||
free(_charHeaders);
|
delete[] _charHeaders;
|
||||||
free(_fontData);
|
delete[] _fontData;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Font::getCharIndex(unsigned char c) {
|
uint16 Font::getCharIndex(unsigned char c) {
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/timer.h"
|
#include "common/timer.h"
|
||||||
|
#include "common/mutex.h"
|
||||||
|
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "engine/savegame.h"
|
#include "engine/savegame.h"
|
||||||
|
@ -42,26 +43,20 @@ extern ImuseTable grimSeqMusicTable[];
|
||||||
extern ImuseTable grimDemoStateMusicTable[];
|
extern ImuseTable grimDemoStateMusicTable[];
|
||||||
extern ImuseTable grimDemoSeqMusicTable[];
|
extern ImuseTable grimDemoSeqMusicTable[];
|
||||||
|
|
||||||
Imuse::Track::Track()
|
|
||||||
: used(false), stream(NULL) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Imuse::timerHandler(void *refCon) {
|
void Imuse::timerHandler(void *refCon) {
|
||||||
Imuse *imuse = (Imuse *)refCon;
|
Imuse *imuse = (Imuse *)refCon;
|
||||||
imuse->callback();
|
imuse->callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
Imuse::Imuse(int fps) {
|
Imuse::Imuse(int fps) {
|
||||||
_mutex = g_driver->createMutex();
|
|
||||||
_pause = false;
|
_pause = false;
|
||||||
_sound = new ImuseSndMgr();
|
_sound = new ImuseSndMgr();
|
||||||
_volVoice = 0;
|
assert(_sound);
|
||||||
_volSfx = 0;
|
|
||||||
_volMusic = 0;
|
|
||||||
_callbackFps = fps;
|
_callbackFps = fps;
|
||||||
resetState();
|
resetState();
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||||
_track[l] = new Track;
|
_track[l] = new Track;
|
||||||
|
assert(_track[l]);
|
||||||
_track[l]->trackId = l;
|
_track[l]->trackId = l;
|
||||||
_track[l]->used = false;
|
_track[l]->used = false;
|
||||||
strcpy(_track[l]->soundName, "");
|
strcpy(_track[l]->soundName, "");
|
||||||
|
@ -73,13 +68,12 @@ Imuse::Imuse(int fps) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Imuse::~Imuse() {
|
Imuse::~Imuse() {
|
||||||
stopAllSounds();
|
|
||||||
g_timer->removeTimerProc(timerHandler);
|
g_timer->removeTimerProc(timerHandler);
|
||||||
|
stopAllSounds();
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||||
delete _track[l];
|
delete _track[l];
|
||||||
}
|
}
|
||||||
delete _sound;
|
delete _sound;
|
||||||
g_driver->deleteMutex(_mutex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::resetState() {
|
void Imuse::resetState() {
|
||||||
|
@ -89,19 +83,18 @@ void Imuse::resetState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::restoreState(SaveGame *savedState) {
|
void Imuse::restoreState(SaveGame *savedState) {
|
||||||
StackLock lock(_mutex);
|
Common::StackLock lock(_mutex);
|
||||||
printf("Imuse::restoreState() started.\n");
|
printf("Imuse::restoreState() started.\n");
|
||||||
|
|
||||||
savedState->beginSection('IMUS');
|
savedState->beginSection('IMUS');
|
||||||
savedState->read(&_volVoice, sizeof(int32));
|
|
||||||
savedState->read(&_volSfx, sizeof(int32));
|
|
||||||
savedState->read(&_volMusic, sizeof(int32));
|
|
||||||
savedState->read(&_curMusicState, sizeof(int32));
|
savedState->read(&_curMusicState, sizeof(int32));
|
||||||
savedState->read(&_curMusicSeq, sizeof(int32));
|
savedState->read(&_curMusicSeq, sizeof(int32));
|
||||||
savedState->read(_attributes, sizeof(int32) * 185);
|
savedState->read(_attributes, sizeof(int32) * 185);
|
||||||
|
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
|
memset(track, 0, sizeof(Track));
|
||||||
|
track->trackId = l;
|
||||||
savedState->read(&track->pan, sizeof(int32));
|
savedState->read(&track->pan, sizeof(int32));
|
||||||
savedState->read(&track->panFadeDest, sizeof(int32));
|
savedState->read(&track->panFadeDest, sizeof(int32));
|
||||||
savedState->read(&track->panFadeDelay, sizeof(int32));
|
savedState->read(&track->panFadeDelay, sizeof(int32));
|
||||||
|
@ -113,50 +106,51 @@ void Imuse::restoreState(SaveGame *savedState) {
|
||||||
savedState->read(track->soundName, 32);
|
savedState->read(track->soundName, 32);
|
||||||
savedState->read(&track->used, sizeof(bool));
|
savedState->read(&track->used, sizeof(bool));
|
||||||
savedState->read(&track->toBeRemoved, sizeof(bool));
|
savedState->read(&track->toBeRemoved, sizeof(bool));
|
||||||
savedState->read(&track->readyToRemove, sizeof(bool));
|
|
||||||
savedState->read(&track->started, sizeof(bool));
|
|
||||||
savedState->read(&track->priority, sizeof(int32));
|
savedState->read(&track->priority, sizeof(int32));
|
||||||
savedState->read(&track->regionOffset, sizeof(int32));
|
savedState->read(&track->regionOffset, sizeof(int32));
|
||||||
savedState->read(&track->dataOffset, sizeof(int32));
|
savedState->read(&track->dataOffset, sizeof(int32));
|
||||||
savedState->read(&track->curRegion, sizeof(int32));
|
savedState->read(&track->curRegion, sizeof(int32));
|
||||||
savedState->read(&track->curHookId, sizeof(int32));
|
savedState->read(&track->curHookId, sizeof(int32));
|
||||||
savedState->read(&track->volGroupId, sizeof(int32));
|
savedState->read(&track->volGroupId, sizeof(int32));
|
||||||
savedState->read(&track->iteration, sizeof(int32));
|
savedState->read(&track->feedSize, sizeof(int32));
|
||||||
savedState->read(&track->mixerFlags, sizeof(int32));
|
savedState->read(&track->mixerFlags, sizeof(int32));
|
||||||
savedState->read(&track->mixerVol, sizeof(int32));
|
|
||||||
savedState->read(&track->mixerPan, sizeof(int32));
|
|
||||||
|
|
||||||
if (!track->used)
|
if (!track->used)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
track->readyToRemove = false;
|
if (track->toBeRemoved || track->curRegion == -1) {
|
||||||
if (track->toBeRemoved) {
|
|
||||||
track->stream = NULL;
|
|
||||||
track->used = false;
|
track->used = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
track->soundHandle = _sound->openSound(track->soundName, track->volGroupId);
|
track->soundDesc = _sound->openSound(track->soundName, track->volGroupId);
|
||||||
assert(track->soundHandle);
|
if (!track->soundDesc) {
|
||||||
|
warning("Imuse::restoreState: Can't open sound so will not be resumed");
|
||||||
|
track->used = false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int32 streamBufferSize = track->iteration;
|
int channels = _sound->getChannels(track->soundDesc);
|
||||||
int freq = _sound->getFreq(track->soundHandle);
|
int freq = _sound->getFreq(track->soundDesc);
|
||||||
|
track->mixerFlags = kFlag16Bits;
|
||||||
|
if (channels == 2)
|
||||||
|
track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
|
||||||
|
|
||||||
track->stream = makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
|
track->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
|
||||||
g_mixer->playInputStream(&track->handle, track->stream, false, -1, track->mixerVol, track->mixerPan, false);
|
g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
|
||||||
|
g_mixer->pauseHandle(track->handle, true);
|
||||||
}
|
}
|
||||||
savedState->endSection();
|
savedState->endSection();
|
||||||
|
g_mixer->pauseAll(false);
|
||||||
|
|
||||||
printf("Imuse::restoreState() finished.\n");
|
printf("Imuse::restoreState() finished.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::saveState(SaveGame *savedState) {
|
void Imuse::saveState(SaveGame *savedState) {
|
||||||
StackLock lock(_mutex);
|
Common::StackLock lock(_mutex);
|
||||||
printf("Imuse::saveState() started.\n");
|
printf("Imuse::saveState() started.\n");
|
||||||
|
|
||||||
savedState->beginSection('IMUS');
|
savedState->beginSection('IMUS');
|
||||||
savedState->write(&_volVoice, sizeof(int32));
|
|
||||||
savedState->write(&_volSfx, sizeof(int32));
|
|
||||||
savedState->write(&_volMusic, sizeof(int32));
|
|
||||||
savedState->write(&_curMusicState, sizeof(int32));
|
savedState->write(&_curMusicState, sizeof(int32));
|
||||||
savedState->write(&_curMusicSeq, sizeof(int32));
|
savedState->write(&_curMusicSeq, sizeof(int32));
|
||||||
savedState->write(_attributes, sizeof(int32) * 185);
|
savedState->write(_attributes, sizeof(int32) * 185);
|
||||||
|
@ -174,31 +168,43 @@ void Imuse::saveState(SaveGame *savedState) {
|
||||||
savedState->write(track->soundName, 32);
|
savedState->write(track->soundName, 32);
|
||||||
savedState->write(&track->used, sizeof(bool));
|
savedState->write(&track->used, sizeof(bool));
|
||||||
savedState->write(&track->toBeRemoved, sizeof(bool));
|
savedState->write(&track->toBeRemoved, sizeof(bool));
|
||||||
savedState->write(&track->readyToRemove, sizeof(bool));
|
|
||||||
savedState->write(&track->started, sizeof(bool));
|
|
||||||
savedState->write(&track->priority, sizeof(int32));
|
savedState->write(&track->priority, sizeof(int32));
|
||||||
savedState->write(&track->regionOffset, sizeof(int32));
|
savedState->write(&track->regionOffset, sizeof(int32));
|
||||||
savedState->write(&track->dataOffset, sizeof(int32));
|
savedState->write(&track->dataOffset, sizeof(int32));
|
||||||
savedState->write(&track->curRegion, sizeof(int32));
|
savedState->write(&track->curRegion, sizeof(int32));
|
||||||
savedState->write(&track->curHookId, sizeof(int32));
|
savedState->write(&track->curHookId, sizeof(int32));
|
||||||
savedState->write(&track->volGroupId, sizeof(int32));
|
savedState->write(&track->volGroupId, sizeof(int32));
|
||||||
savedState->write(&track->iteration, sizeof(int32));
|
savedState->write(&track->feedSize, sizeof(int32));
|
||||||
savedState->write(&track->mixerFlags, sizeof(int32));
|
savedState->write(&track->mixerFlags, sizeof(int32));
|
||||||
savedState->write(&track->mixerVol, sizeof(int32));
|
|
||||||
savedState->write(&track->mixerPan, sizeof(int32));
|
|
||||||
}
|
}
|
||||||
savedState->endSection();
|
savedState->endSection();
|
||||||
printf("Imuse::saveState() finished.\n");
|
printf("Imuse::saveState() finished.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 Imuse::makeMixerFlags(int32 flags) {
|
||||||
|
int32 mixerFlags = 0;
|
||||||
|
if (flags & kFlag16Bits)
|
||||||
|
mixerFlags |= Audio::Mixer::FLAG_16BITS;
|
||||||
|
if (flags & kFlagLittleEndian)
|
||||||
|
mixerFlags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
|
||||||
|
if (flags & kFlagStereo)
|
||||||
|
mixerFlags |= Audio::Mixer::FLAG_STEREO;
|
||||||
|
if (flags & kFlagReverseStereo)
|
||||||
|
mixerFlags |= Audio::Mixer::FLAG_REVERSE_STEREO;
|
||||||
|
return mixerFlags;
|
||||||
|
}
|
||||||
|
|
||||||
void Imuse::callback() {
|
void Imuse::callback() {
|
||||||
StackLock lock(_mutex);
|
Common::StackLock lock(_mutex);
|
||||||
|
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
if (track->used && !track->readyToRemove) {
|
if (track->used) {
|
||||||
if (track->toBeRemoved) {
|
// Ignore tracks which are about to finish. Also, if it did finish in the meantime,
|
||||||
track->readyToRemove = true;
|
// mark it as unused.
|
||||||
|
if (!track->stream) {
|
||||||
|
if (!g_mixer->isSoundHandleActive(track->handle))
|
||||||
|
memset(track, 0, sizeof(Track));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,17 +215,21 @@ void Imuse::callback() {
|
||||||
if (track->volFadeStep < 0) {
|
if (track->volFadeStep < 0) {
|
||||||
if (track->vol > track->volFadeDest) {
|
if (track->vol > track->volFadeDest) {
|
||||||
track->vol += track->volFadeStep;
|
track->vol += track->volFadeStep;
|
||||||
|
//warning("fade: %d", track->vol);
|
||||||
if (track->vol < track->volFadeDest) {
|
if (track->vol < track->volFadeDest) {
|
||||||
track->vol = track->volFadeDest;
|
track->vol = track->volFadeDest;
|
||||||
track->volFadeUsed = false;
|
track->volFadeUsed = false;
|
||||||
}
|
}
|
||||||
if (track->vol == 0) {
|
if (track->vol == 0) {
|
||||||
track->toBeRemoved = true;
|
// Fade out complete -> remove this track
|
||||||
|
flushTrack(track);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (track->volFadeStep > 0) {
|
} else if (track->volFadeStep > 0) {
|
||||||
if (track->vol < track->volFadeDest) {
|
if (track->vol < track->volFadeDest) {
|
||||||
track->vol += track->volFadeStep;
|
track->vol += track->volFadeStep;
|
||||||
|
//warning("fade: %d", track->vol);
|
||||||
if (track->vol > track->volFadeDest) {
|
if (track->vol > track->volFadeDest) {
|
||||||
track->vol = track->volFadeDest;
|
track->vol = track->volFadeDest;
|
||||||
track->volFadeUsed = false;
|
track->volFadeUsed = false;
|
||||||
|
@ -248,74 +258,60 @@ void Imuse::callback() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int pan = track->pan / 1000;
|
assert(track->stream);
|
||||||
pan = (pan != 64) ? 2 * pan - 127 : 0;
|
byte *data = NULL;
|
||||||
int vol = track->vol / 1000;
|
int32 result = 0;
|
||||||
|
|
||||||
if (track->volGroupId == 1)
|
if (track->curRegion == -1) {
|
||||||
vol = (vol * _volVoice) / 128;
|
switchToNextRegion(track);
|
||||||
if (track->volGroupId == 2)
|
if (!track->stream) // Seems we reached the end of the stream
|
||||||
vol = (vol * _volSfx) / 128;
|
|
||||||
if (track->volGroupId == 3)
|
|
||||||
vol = (vol * _volMusic) / 128;
|
|
||||||
|
|
||||||
track->mixerVol = vol;
|
|
||||||
track->mixerPan = pan;
|
|
||||||
|
|
||||||
if (track->stream) {
|
|
||||||
byte *data = NULL;
|
|
||||||
int32 result = 0;
|
|
||||||
|
|
||||||
if (track->curRegion == -1) {
|
|
||||||
switchToNextRegion(track);
|
|
||||||
if (track->toBeRemoved)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int channels = _sound->getChannels(track->soundHandle);
|
|
||||||
|
|
||||||
int32 mixer_size = track->iteration / _callbackFps;
|
|
||||||
|
|
||||||
if (track->stream->endOfData()) {
|
|
||||||
mixer_size *= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (channels == 1)
|
|
||||||
mixer_size &= ~1;
|
|
||||||
if (channels == 2)
|
|
||||||
mixer_size &= ~3;
|
|
||||||
|
|
||||||
if (mixer_size == 0)
|
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
int channels = _sound->getChannels(track->soundDesc);
|
||||||
result = _sound->getDataFromRegion(track->soundHandle, track->curRegion, &data, track->regionOffset, mixer_size);
|
int32 mixer_size = track->feedSize / _callbackFps;
|
||||||
if (channels == 1) {
|
|
||||||
result &= ~1;
|
|
||||||
}
|
|
||||||
if (channels == 2) {
|
|
||||||
result &= ~3;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result > mixer_size)
|
if (track->stream->endOfData()) {
|
||||||
result = mixer_size;
|
mixer_size *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_mixer->isReady()) {
|
if (channels == 1)
|
||||||
g_mixer->setChannelVolume(track->handle, vol);
|
mixer_size &= ~1;
|
||||||
g_mixer->setChannelBalance(track->handle, pan);
|
if (channels == 2)
|
||||||
track->stream->append(data, result);
|
mixer_size &= ~3;
|
||||||
track->regionOffset += result;
|
|
||||||
free(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) {
|
if (mixer_size == 0)
|
||||||
switchToNextRegion(track);
|
continue;
|
||||||
if (track->toBeRemoved)
|
|
||||||
break;
|
do {
|
||||||
}
|
result = _sound->getDataFromRegion(track->soundDesc, track->curRegion, &data, track->regionOffset, mixer_size);
|
||||||
mixer_size -= result;
|
if (channels == 1) {
|
||||||
assert(mixer_size >= 0);
|
result &= ~1;
|
||||||
} while (mixer_size != 0);
|
}
|
||||||
|
if (channels == 2) {
|
||||||
|
result &= ~3;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (result > mixer_size)
|
||||||
|
result = mixer_size;
|
||||||
|
|
||||||
|
if (g_mixer->isReady()) {
|
||||||
|
track->stream->queueBuffer(data, result);
|
||||||
|
track->regionOffset += result;
|
||||||
|
} else
|
||||||
|
delete[] data;
|
||||||
|
|
||||||
|
if (_sound->isEndOfRegion(track->soundDesc, track->curRegion)) {
|
||||||
|
switchToNextRegion(track);
|
||||||
|
if (!track->stream)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
mixer_size -= result;
|
||||||
|
assert(mixer_size >= 0);
|
||||||
|
} while (mixer_size);
|
||||||
|
if (g_mixer->isReady()) {
|
||||||
|
g_mixer->setChannelVolume(track->handle, track->getVol());
|
||||||
|
g_mixer->setChannelBalance(track->handle, track->getPan());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,51 +321,51 @@ void Imuse::switchToNextRegion(Track *track) {
|
||||||
assert(track);
|
assert(track);
|
||||||
|
|
||||||
if (track->trackId >= MAX_IMUSE_TRACKS) {
|
if (track->trackId >= MAX_IMUSE_TRACKS) {
|
||||||
track->toBeRemoved = true;
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::switchToNextRegion(): fadeTrack end: soundName:%s\n", track->soundName);
|
||||||
|
flushTrack(track);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int numRegions = _sound->getNumRegions(track->soundHandle);
|
int numRegions = _sound->getNumRegions(track->soundDesc);
|
||||||
|
|
||||||
if (++track->curRegion == numRegions) {
|
if (++track->curRegion == numRegions) {
|
||||||
track->toBeRemoved = true;
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::switchToNextRegion(): end of tracks: soundName:%s\n", track->soundName);
|
||||||
|
flushTrack(track);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImuseSndMgr::SoundStruct *soundHandle = track->soundHandle;
|
ImuseSndMgr::SoundDesc *soundDesc = track->soundDesc;
|
||||||
int jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, track->curHookId);
|
int jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, track->curHookId);
|
||||||
if (jumpId == -1)
|
if (jumpId == -1)
|
||||||
jumpId = _sound->getJumpIdByRegionAndHookId(soundHandle, track->curRegion, 0);
|
jumpId = _sound->getJumpIdByRegionAndHookId(soundDesc, track->curRegion, 0);
|
||||||
if (jumpId != -1) {
|
if (jumpId != -1) {
|
||||||
int region = _sound->getRegionIdByJumpId(soundHandle, jumpId);
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::switchToNextRegion(): JUMP: soundName:%s\n", track->soundName);
|
||||||
|
int region = _sound->getRegionIdByJumpId(soundDesc, jumpId);
|
||||||
assert(region != -1);
|
assert(region != -1);
|
||||||
int sampleHookId = _sound->getJumpHookId(soundHandle, jumpId);
|
int sampleHookId = _sound->getJumpHookId(soundDesc, jumpId);
|
||||||
assert(sampleHookId != -1);
|
assert(sampleHookId != -1);
|
||||||
int fadeDelay = (60 * _sound->getJumpFade(soundHandle, jumpId)) / 1000;
|
int fadeDelay = (60 * _sound->getJumpFade(soundDesc, jumpId)) / 1000;
|
||||||
if (sampleHookId != 0) {
|
if (fadeDelay) {
|
||||||
if (track->curHookId == sampleHookId) {
|
Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
|
||||||
if (fadeDelay != 0) {
|
if (fadeTrack) {
|
||||||
Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
|
fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundDesc, fadeTrack->curRegion);
|
||||||
fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion);
|
|
||||||
fadeTrack->regionOffset = 0;
|
|
||||||
fadeTrack->curHookId = 0;
|
|
||||||
}
|
|
||||||
track->curRegion = region;
|
|
||||||
track->curHookId = 0;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (fadeDelay != 0) {
|
|
||||||
Track *fadeTrack = cloneToFadeOutTrack(track, fadeDelay);
|
|
||||||
fadeTrack->dataOffset = _sound->getRegionOffset(fadeTrack->soundHandle, fadeTrack->curRegion);
|
|
||||||
fadeTrack->regionOffset = 0;
|
fadeTrack->regionOffset = 0;
|
||||||
}
|
fadeTrack->curHookId = 0;
|
||||||
track->curRegion = region;
|
|
||||||
if (track->curHookId == 0x80) {
|
|
||||||
track->curHookId = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
track->curRegion = region;
|
||||||
|
if (track->curHookId == sampleHookId)
|
||||||
|
track->curHookId = 0;
|
||||||
|
else
|
||||||
|
if (track->curHookId == 0x80)
|
||||||
|
track->curHookId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
track->dataOffset = _sound->getRegionOffset(soundHandle, track->curRegion);
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::switchToNextRegion(): REGION %d: soundName:%s\n", track->curRegion, track->soundName);
|
||||||
|
track->dataOffset = _sound->getRegionOffset(soundDesc, track->curRegion);
|
||||||
track->regionOffset = 0;
|
track->regionOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,21 +34,12 @@
|
||||||
|
|
||||||
#include "engine/imuse/imuse_sndmgr.h"
|
#include "engine/imuse/imuse_sndmgr.h"
|
||||||
#include "engine/imuse/imuse_mcmp_mgr.h"
|
#include "engine/imuse/imuse_mcmp_mgr.h"
|
||||||
|
#include "engine/imuse/imuse_track.h"
|
||||||
|
#include "engine/imuse/imuse_tables.h"
|
||||||
|
|
||||||
#define MAX_IMUSE_TRACKS 16
|
#define MAX_IMUSE_TRACKS 16
|
||||||
#define MAX_IMUSE_FADETRACKS 16
|
#define MAX_IMUSE_FADETRACKS 16
|
||||||
|
|
||||||
struct ImuseTable {
|
|
||||||
byte opcode;
|
|
||||||
int16 soundId;
|
|
||||||
byte atribPos;
|
|
||||||
byte hookId;
|
|
||||||
int16 fadeOut60TicksDelay;
|
|
||||||
byte volume;
|
|
||||||
byte pan;
|
|
||||||
char filename[32];
|
|
||||||
};
|
|
||||||
|
|
||||||
class SaveGame;
|
class SaveGame;
|
||||||
|
|
||||||
class Imuse {
|
class Imuse {
|
||||||
|
@ -56,52 +47,11 @@ private:
|
||||||
|
|
||||||
int _callbackFps;
|
int _callbackFps;
|
||||||
|
|
||||||
struct Track {
|
|
||||||
int trackId;
|
|
||||||
|
|
||||||
int32 pan;
|
|
||||||
int32 panFadeDest;
|
|
||||||
int32 panFadeStep;
|
|
||||||
int32 panFadeDelay;
|
|
||||||
bool panFadeUsed;
|
|
||||||
int32 vol;
|
|
||||||
int32 volFadeDest;
|
|
||||||
int32 volFadeStep;
|
|
||||||
int32 volFadeDelay;
|
|
||||||
bool volFadeUsed;
|
|
||||||
|
|
||||||
char soundName[32];
|
|
||||||
bool used;
|
|
||||||
bool toBeRemoved;
|
|
||||||
bool readyToRemove;
|
|
||||||
bool started;
|
|
||||||
int32 priority;
|
|
||||||
int32 regionOffset;
|
|
||||||
int32 dataOffset;
|
|
||||||
int32 curRegion;
|
|
||||||
int32 curHookId;
|
|
||||||
int32 volGroupId;
|
|
||||||
int32 iteration;
|
|
||||||
int32 mixerFlags;
|
|
||||||
int32 mixerVol;
|
|
||||||
int32 mixerPan;
|
|
||||||
|
|
||||||
ImuseSndMgr::SoundStruct *soundHandle;
|
|
||||||
PlayingSoundHandle handle;
|
|
||||||
AppendableAudioStream *stream;
|
|
||||||
|
|
||||||
Track();
|
|
||||||
};
|
|
||||||
|
|
||||||
Track *_track[MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS];
|
Track *_track[MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS];
|
||||||
|
|
||||||
MutexRef _mutex;
|
Common::Mutex _mutex;
|
||||||
ImuseSndMgr *_sound;
|
ImuseSndMgr *_sound;
|
||||||
|
|
||||||
int32 _volVoice;
|
|
||||||
int32 _volSfx;
|
|
||||||
int32 _volMusic;
|
|
||||||
|
|
||||||
bool _pause;
|
bool _pause;
|
||||||
|
|
||||||
int32 _attributes[185];
|
int32 _attributes[185];
|
||||||
|
@ -111,6 +61,7 @@ private:
|
||||||
const ImuseTable *_stateMusicTable;
|
const ImuseTable *_stateMusicTable;
|
||||||
const ImuseTable *_seqMusicTable;
|
const ImuseTable *_seqMusicTable;
|
||||||
|
|
||||||
|
int32 makeMixerFlags(int32 flags);
|
||||||
static void timerHandler(void *refConf);
|
static void timerHandler(void *refConf);
|
||||||
void callback();
|
void callback();
|
||||||
void switchToNextRegion(Track *track);
|
void switchToNextRegion(Track *track);
|
||||||
|
@ -118,30 +69,27 @@ private:
|
||||||
void selectVolumeGroup(const char *soundName, int volGroupId);
|
void selectVolumeGroup(const char *soundName, int volGroupId);
|
||||||
|
|
||||||
void fadeOutMusic(int fadeDelay);
|
void fadeOutMusic(int fadeDelay);
|
||||||
|
void fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int hookId, int vol, int pan);
|
||||||
Track *cloneToFadeOutTrack(Track *track, int fadeDelay);
|
Track *cloneToFadeOutTrack(Track *track, int fadeDelay);
|
||||||
|
|
||||||
void playMusic(const ImuseTable *table, int atribPos, bool sequence);
|
void playMusic(const ImuseTable *table, int atribPos, bool sequence);
|
||||||
|
|
||||||
|
void flushTrack(Track *track);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Imuse(int fps);
|
Imuse(int fps);
|
||||||
~Imuse();
|
~Imuse();
|
||||||
|
|
||||||
bool startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority);
|
bool startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority, Track *otherTrack);
|
||||||
void startVoice(const char *soundName, int volume = 127, int pan = 64);
|
void startVoice(const char *soundName, int volume = 127, int pan = 64);
|
||||||
void startMusic(const char *soundName, int hookId, int volume, int pan);
|
void startMusic(const char *soundName, int hookId, int volume, int pan);
|
||||||
|
void startMusicWithOtherPos(const char *soundName, int hookId, int volume, int pan, Track *otherTrack);
|
||||||
void startSfx(const char *soundName, int priority = 127);
|
void startSfx(const char *soundName, int priority = 127);
|
||||||
|
|
||||||
void restoreState(SaveGame *savedState);
|
void restoreState(SaveGame *savedState);
|
||||||
void saveState(SaveGame *savedState);
|
void saveState(SaveGame *savedState);
|
||||||
void resetState();
|
void resetState();
|
||||||
|
|
||||||
void setGroupVoiceVolume(int volume) { _volVoice = volume; }
|
|
||||||
void setGroupSfxVolume(int volume) { _volSfx = volume; }
|
|
||||||
void setGroupMusicVolume(int volume) { _volMusic = volume; }
|
|
||||||
int getGroupVoiceVolume() { return _volVoice; }
|
|
||||||
int getGroupSfxVolume() { return _volSfx; }
|
|
||||||
int getGroupMusicVolume() { return _volMusic; }
|
|
||||||
|
|
||||||
Track *findTrack(const char *soundName);
|
Track *findTrack(const char *soundName);
|
||||||
void setPriority(const char *soundName, int priority);
|
void setPriority(const char *soundName, int priority);
|
||||||
void setVolume(const char *soundName, int volume);
|
void setVolume(const char *soundName, int volume);
|
||||||
|
@ -160,6 +108,8 @@ public:
|
||||||
void flushTracks();
|
void flushTracks();
|
||||||
bool isVoicePlaying();
|
bool isVoicePlaying();
|
||||||
char *getCurMusicSoundName();
|
char *getCurMusicSoundName();
|
||||||
|
int getCurMusicPan();
|
||||||
|
int getCurMusicVol();
|
||||||
bool getSoundStatus(const char *soundName);
|
bool getSoundStatus(const char *soundName);
|
||||||
int32 getPosIn60HzTicks(const char *soundName);
|
int32 getPosIn60HzTicks(const char *soundName);
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,10 +45,8 @@ McmpMgr::McmpMgr() {
|
||||||
McmpMgr::~McmpMgr() {
|
McmpMgr::~McmpMgr() {
|
||||||
if (_file)
|
if (_file)
|
||||||
fclose(_file);
|
fclose(_file);
|
||||||
if (_compTable)
|
delete[] _compTable;
|
||||||
free(_compTable);
|
delete[] _compInput;
|
||||||
if (_compInput)
|
|
||||||
free(_compInput);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool McmpMgr::openSound(const char *filename, byte **resPtr, int &offsetData) {
|
bool McmpMgr::openSound(const char *filename, byte **resPtr, int &offsetData) {
|
||||||
|
@ -72,7 +70,7 @@ bool McmpMgr::openSound(const char *filename, byte **resPtr, int &offsetData) {
|
||||||
|
|
||||||
int offset = ftell(_file) + (_numCompItems * 9) + 2;
|
int offset = ftell(_file) + (_numCompItems * 9) + 2;
|
||||||
_numCompItems--;
|
_numCompItems--;
|
||||||
_compTable = (CompTable *)malloc(sizeof(CompTable) * _numCompItems);
|
_compTable = new CompTable[_numCompItems];
|
||||||
fseek(_file, 5, SEEK_CUR);
|
fseek(_file, 5, SEEK_CUR);
|
||||||
fread(&_compTable[0].decompSize, 1, 4, _file);
|
fread(&_compTable[0].decompSize, 1, 4, _file);
|
||||||
int headerSize = _compTable[0].decompSize = READ_BE_UINT32(&_compTable[0].decompSize);
|
int headerSize = _compTable[0].decompSize = READ_BE_UINT32(&_compTable[0].decompSize);
|
||||||
|
@ -98,7 +96,7 @@ bool McmpMgr::openSound(const char *filename, byte **resPtr, int &offsetData) {
|
||||||
_compTable[i].offset += sizeCodecs;
|
_compTable[i].offset += sizeCodecs;
|
||||||
}
|
}
|
||||||
fseek(_file, sizeCodecs, SEEK_CUR);
|
fseek(_file, sizeCodecs, SEEK_CUR);
|
||||||
_compInput = (byte *)malloc(maxSize);
|
_compInput = new byte[maxSize];
|
||||||
fread(_compInput, 1, headerSize, _file);
|
fread(_compInput, 1, headerSize, _file);
|
||||||
*resPtr = _compInput;
|
*resPtr = _compInput;
|
||||||
offsetData = headerSize;
|
offsetData = headerSize;
|
||||||
|
@ -123,7 +121,7 @@ int32 McmpMgr::decompressSample(int32 offset, int32 size, byte **comp_final) {
|
||||||
last_block = _numCompItems - 1;
|
last_block = _numCompItems - 1;
|
||||||
|
|
||||||
int32 blocks_final_size = 0x2000 * (1 + last_block - first_block);
|
int32 blocks_final_size = 0x2000 * (1 + last_block - first_block);
|
||||||
*comp_final = (byte *)malloc(blocks_final_size);
|
*comp_final = new byte[blocks_final_size];
|
||||||
final_size = 0;
|
final_size = 0;
|
||||||
|
|
||||||
for (i = first_block; i <= last_block; i++) {
|
for (i = first_block; i <= last_block; i++) {
|
||||||
|
|
|
@ -40,10 +40,13 @@ void Imuse::setMusicState(int stateId) {
|
||||||
}
|
}
|
||||||
assert(num != -1);
|
assert(num != -1);
|
||||||
|
|
||||||
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::setMusicState(): SoundId %d, filename: %s\n", _stateMusicTable[l].soundId, _stateMusicTable[l].filename);
|
||||||
|
|
||||||
if (_curMusicState == num)
|
if (_curMusicState == num)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (_curMusicSeq == 0) {
|
if (!_curMusicSeq) {
|
||||||
playMusic(&_stateMusicTable[num], num, false);
|
playMusic(&_stateMusicTable[num], num, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,10 +71,13 @@ int Imuse::setMusicSequence(int seqId) {
|
||||||
|
|
||||||
assert(num != -1);
|
assert(num != -1);
|
||||||
|
|
||||||
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::setMusicSequence(): SoundId %d, filename: %s\n", _seqMusicTable[l].soundId, _seqMusicTable[l].filename);
|
||||||
|
|
||||||
if (_curMusicSeq == num)
|
if (_curMusicSeq == num)
|
||||||
return _seqMusicTable[_curMusicSeq].soundId;
|
return _seqMusicTable[_curMusicSeq].soundId;
|
||||||
|
|
||||||
if (num != 0) {
|
if (num) {
|
||||||
playMusic(&_seqMusicTable[num], 0, true);
|
playMusic(&_seqMusicTable[num], 0, true);
|
||||||
} else {
|
} else {
|
||||||
playMusic(&_stateMusicTable[_curMusicState], _curMusicState, true);
|
playMusic(&_stateMusicTable[_curMusicState], _curMusicState, true);
|
||||||
|
@ -85,12 +91,12 @@ int Imuse::setMusicSequence(int seqId) {
|
||||||
void Imuse::playMusic(const ImuseTable *table, int atribPos, bool sequence) {
|
void Imuse::playMusic(const ImuseTable *table, int atribPos, bool sequence) {
|
||||||
int hookId = 0;
|
int hookId = 0;
|
||||||
|
|
||||||
if (atribPos != 0) {
|
if (atribPos) {
|
||||||
if (table->atribPos != 0)
|
if (table->atribPos)
|
||||||
atribPos = table->atribPos;
|
atribPos = table->atribPos;
|
||||||
hookId = _attributes[atribPos];
|
hookId = _attributes[atribPos];
|
||||||
if (table->hookId != 0) {
|
if (table->hookId) {
|
||||||
if ((hookId == 0) && (table->hookId > 1)) {
|
if (hookId && table->hookId > 1) {
|
||||||
_attributes[atribPos] = 2;
|
_attributes[atribPos] = 2;
|
||||||
} else {
|
} else {
|
||||||
_attributes[atribPos] = hookId + 1;
|
_attributes[atribPos] = hookId + 1;
|
||||||
|
@ -104,27 +110,51 @@ void Imuse::playMusic(const ImuseTable *table, int atribPos, bool sequence) {
|
||||||
|
|
||||||
if (table->opcode == 0) {
|
if (table->opcode == 0) {
|
||||||
fadeOutMusic(120);
|
fadeOutMusic(120);
|
||||||
} else if ((table->opcode == 2) || (table->opcode == 3)) {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (table->opcode == 2 || table->opcode == 3) {
|
||||||
if (table->filename[0] == 0) {
|
if (table->filename[0] == 0) {
|
||||||
fadeOutMusic(60);
|
fadeOutMusic(60);
|
||||||
} else {
|
return;
|
||||||
char *soundName = getCurMusicSoundName();
|
}
|
||||||
int pan;
|
char *soundName = getCurMusicSoundName();
|
||||||
|
int pan;
|
||||||
|
|
||||||
if (table->pan == 0)
|
if (table->pan == 0)
|
||||||
pan = 64;
|
pan = 64;
|
||||||
else
|
else
|
||||||
pan = table->pan;
|
pan = table->pan;
|
||||||
if (soundName != NULL && (table->opcode == 3) && (!sequence)
|
if (!soundName) {
|
||||||
&& (strcmp(soundName, table->filename) == 0) && (table->atribPos != 0)
|
startMusic(table->filename, hookId, 0, pan);
|
||||||
&& table->atribPos == _stateMusicTable[_curMusicState].atribPos) {
|
setFadeVolume(table->filename, table->volume, table->fadeOut60TicksDelay);
|
||||||
setFadeVolume(soundName, table->volume, table->fadeOut60TicksDelay);
|
return;
|
||||||
setFadePan(soundName, pan, table->fadeOut60TicksDelay);
|
}
|
||||||
setHookId(soundName, hookId);
|
int old_pan = getCurMusicPan();
|
||||||
} else {
|
int old_vol = getCurMusicVol();
|
||||||
fadeOutMusic(table->fadeOut60TicksDelay);
|
if (old_pan == -1)
|
||||||
startMusic(table->filename, hookId, table->volume, pan);
|
old_pan = 64;
|
||||||
}
|
if (old_vol == -1)
|
||||||
|
old_vol = 127;
|
||||||
|
|
||||||
|
if (table->opcode == 2) {
|
||||||
|
fadeOutMusic(table->fadeOut60TicksDelay);
|
||||||
|
startMusic(table->filename, hookId, table->volume, pan);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strcmp(soundName, table->filename) == 0) {
|
||||||
|
setFadeVolume(soundName, table->volume, table->fadeOut60TicksDelay);
|
||||||
|
setFadePan(soundName, pan, table->fadeOut60TicksDelay);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sequence && table->atribPos && table->atribPos == _stateMusicTable[_curMusicState].atribPos) {
|
||||||
|
fadeOutMusicAndStartNew(table->fadeOut60TicksDelay, table->filename, hookId, old_vol, old_pan);
|
||||||
|
setFadeVolume(table->filename, table->volume, table->fadeOut60TicksDelay);
|
||||||
|
setFadePan(table->filename, pan, table->fadeOut60TicksDelay);
|
||||||
|
} else {
|
||||||
|
fadeOutMusic(table->fadeOut60TicksDelay);
|
||||||
|
startMusic(table->filename, hookId, table->volume, pan);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
#include "common/timer.h"
|
#include "common/timer.h"
|
||||||
|
#include "common/mutex.h"
|
||||||
|
|
||||||
#include "engine/backend/driver.h"
|
#include "engine/backend/driver.h"
|
||||||
|
|
||||||
|
@ -33,34 +34,41 @@
|
||||||
#include "engine/imuse/imuse.h"
|
#include "engine/imuse/imuse.h"
|
||||||
#include "engine/imuse/imuse_sndmgr.h"
|
#include "engine/imuse/imuse_sndmgr.h"
|
||||||
|
|
||||||
|
void Imuse::flushTrack(Track *track) {
|
||||||
|
track->toBeRemoved = true;
|
||||||
|
|
||||||
|
if (track->stream) {
|
||||||
|
// Finalize the appendable stream, then remove our reference to it.
|
||||||
|
// Note that there might still be some data left in the buffers of the
|
||||||
|
// appendable stream. We play it nice and wait till all of it
|
||||||
|
// played. The audio mixer will take care of it afterwards (and dispose it).
|
||||||
|
track->stream->finish();
|
||||||
|
track->stream = 0;
|
||||||
|
if (track->soundDesc) {
|
||||||
|
_sound->closeSound(track->soundDesc);
|
||||||
|
track->soundDesc = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_mixer->isSoundHandleActive(track->handle)) {
|
||||||
|
memset(track, 0, sizeof(Track));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Imuse::flushTracks() {
|
void Imuse::flushTracks() {
|
||||||
// flushTracks should not lock the stack since all the functions
|
Common::StackLock lock(_mutex);
|
||||||
// that call it already do (stopAllSounds, startSound)
|
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
if (track->used && track->readyToRemove) {
|
if (track->used && track->toBeRemoved && !g_mixer->isSoundHandleActive(track->handle)) {
|
||||||
if (track->stream) {
|
memset(track, 0, sizeof(Track));
|
||||||
if (!track->stream->endOfStream()) {
|
|
||||||
track->stream->finish();
|
|
||||||
}
|
|
||||||
if (track->stream->endOfStream()) {
|
|
||||||
g_mixer->stopHandle(track->handle);
|
|
||||||
delete track->stream;
|
|
||||||
track->stream = NULL;
|
|
||||||
_sound->closeSound(track->soundHandle);
|
|
||||||
track->soundHandle = NULL;
|
|
||||||
track->used = false;
|
|
||||||
strcpy(track->soundName, "");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::refreshScripts() {
|
void Imuse::refreshScripts() {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
|
||||||
StackLock lock(_mutex);
|
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
||||||
|
@ -68,52 +76,58 @@ void Imuse::refreshScripts() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!found && (_curMusicSeq != 0)) {
|
if (!found && _curMusicState) {
|
||||||
setMusicSequence(2000);
|
setMusicSequence(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::startVoice(const char *soundName, int volume, int pan) {
|
void Imuse::startVoice(const char *soundName, int volume, int pan) {
|
||||||
startSound(soundName, IMUSE_VOLGRP_VOICE, 0, volume, pan, 127);
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::startVoice(): SoundName %s, vol:%d, pan:%d\n", soundName, volume, pan);
|
||||||
|
startSound(soundName, IMUSE_VOLGRP_VOICE, 0, volume, pan, 127, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::startMusic(const char *soundName, int hookId, int volume, int pan) {
|
void Imuse::startMusic(const char *soundName, int hookId, int volume, int pan) {
|
||||||
startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126);
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::startMusic(): SoundName %s, hookId:%d, vol:%d, pan:%d\n", soundName, hookId, volume, pan);
|
||||||
|
startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Imuse::startMusicWithOtherPos(const char *soundName, int hookId, int volume, int pan, Track *otherTrack) {
|
||||||
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::startMusicWithOtherPos(): SoundName %s, hookId:%d, vol:%d, pan:%d\n", soundName, volume, pan);
|
||||||
|
startSound(soundName, IMUSE_VOLGRP_MUSIC, hookId, volume, pan, 126, otherTrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::startSfx(const char *soundName, int priority) {
|
void Imuse::startSfx(const char *soundName, int priority) {
|
||||||
startSound(soundName, IMUSE_VOLGRP_SFX, 0, 127, 0, priority);
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::startSfx(): SoundName %s, priority:%d\n", soundName, priority);
|
||||||
|
startSound(soundName, IMUSE_VOLGRP_SFX, 0, 127, 0, priority, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 Imuse::getPosIn60HzTicks(const char *soundName) {
|
int32 Imuse::getPosIn60HzTicks(const char *soundName) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *getTrack = NULL;
|
Track *getTrack = NULL;
|
||||||
|
|
||||||
getTrack = findTrack(soundName);
|
getTrack = findTrack(soundName);
|
||||||
// Warn the user if the track was not found
|
// Warn the user if the track was not found
|
||||||
if (getTrack == NULL) {
|
if (getTrack == NULL) {
|
||||||
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
|
||||||
warning("Music track '%s' could not be found to get ticks!", soundName);
|
warning("Sound '%s' could not be found to get ticks!", soundName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getTrack->handle.isActive()) {
|
int32 pos = (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->feedSize / 200);
|
||||||
int32 pos = (5 * (getTrack->dataOffset + getTrack->regionOffset)) / (getTrack->iteration / 12);
|
return pos;
|
||||||
return pos;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Imuse::isVoicePlaying() {
|
bool Imuse::isVoicePlaying() {
|
||||||
StackLock lock(_mutex);
|
Common::StackLock lock(_mutex);
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
// Make sure the track is in use before checking the group ID,
|
|
||||||
// otherwise volGroupId can be uninitialized or reference an
|
|
||||||
// old track.
|
|
||||||
if (track->used && track->volGroupId == IMUSE_VOLGRP_VOICE) {
|
if (track->used && track->volGroupId == IMUSE_VOLGRP_VOICE) {
|
||||||
if (track->handle.isActive()) {
|
if (g_mixer->isSoundHandleActive(track->handle))
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,51 +135,55 @@ bool Imuse::isVoicePlaying() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Imuse::getSoundStatus(const char *soundName) {
|
bool Imuse::getSoundStatus(const char *soundName) {
|
||||||
Track *statusTrack = NULL;
|
Common::StackLock lock(_mutex);
|
||||||
|
Track *track = NULL;
|
||||||
|
|
||||||
// If there's no name then don't try to get the status!
|
// If there's no name then don't try to get the status!
|
||||||
if (strlen(soundName) == 0)
|
if (strlen(soundName) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
statusTrack = findTrack(soundName);
|
track = findTrack(soundName);
|
||||||
// Warn the user if the track was not found
|
// Warn the user if the track was not found
|
||||||
if (statusTrack == NULL) {
|
if (track == NULL || !g_mixer->isSoundHandleActive(track->handle)) {
|
||||||
// This debug warning should be "light" since this function gets called
|
// This debug warning should be "light" since this function gets called
|
||||||
// on occassion to see if a sound has stopped yet
|
// on occassion to see if a sound has stopped yet
|
||||||
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_NORMAL || debugLevel == DEBUG_ALL)
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_NORMAL || debugLevel == DEBUG_ALL)
|
||||||
printf("Music track '%s' could not be found to get status, assume inactive.\n", soundName);
|
printf("Sound '%s' could not be found to get status, assume inactive.\n", soundName);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return statusTrack->handle.isActive();
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::stopSound(const char *soundName) {
|
void Imuse::stopSound(const char *soundName) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
|
printf("Imuse::stopSound(): SoundName %s\n", soundName);
|
||||||
Track *removeTrack = NULL;
|
Track *removeTrack = NULL;
|
||||||
|
|
||||||
removeTrack = findTrack(soundName);
|
removeTrack = findTrack(soundName);
|
||||||
// Warn the user if the track was not found
|
// Warn the user if the track was not found
|
||||||
if (removeTrack == NULL) {
|
if (removeTrack == NULL) {
|
||||||
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
|
||||||
warning("Music track '%s' could not be found to stop!", soundName);
|
warning("Sound track '%s' could not be found to stop!", soundName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
removeTrack->toBeRemoved = true;
|
flushTrack(removeTrack);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::stopAllSounds() {
|
void Imuse::stopAllSounds() {
|
||||||
for (;;) {
|
Common::StackLock lock(_mutex);
|
||||||
bool foundNotRemoved = false;
|
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_ALL)
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
printf("Imuse::stopAllSounds()\n");
|
||||||
Track *track = _track[l];
|
|
||||||
if (track->used) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
||||||
track->toBeRemoved = true;
|
Track *track = _track[l];
|
||||||
foundNotRemoved = true;
|
if (track->used) {
|
||||||
|
g_mixer->stopHandle(track->handle);
|
||||||
|
if (track->soundDesc) {
|
||||||
|
_sound->closeSound(track->soundDesc);
|
||||||
}
|
}
|
||||||
|
memset(track, 0, sizeof(Track));
|
||||||
}
|
}
|
||||||
if (!foundNotRemoved)
|
|
||||||
break;
|
|
||||||
flushTracks();
|
|
||||||
g_driver->delayMillis(50);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
|
|
||||||
ImuseSndMgr::ImuseSndMgr() {
|
ImuseSndMgr::ImuseSndMgr() {
|
||||||
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
||||||
memset(&_sounds[l], 0, sizeof(SoundStruct));
|
memset(&_sounds[l], 0, sizeof(SoundDesc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,10 +72,10 @@ void ImuseSndMgr::countElements(byte *ptr, int &numRegions, int &numJumps) {
|
||||||
} while (tag != MKID_BE('DATA'));
|
} while (tag != MKID_BE('DATA'));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSize) {
|
void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize) {
|
||||||
if (READ_UINT32(ptr) == MKID('RIFF')) {
|
if (READ_UINT32(ptr) == MKID('RIFF')) {
|
||||||
sound->region = (Region *)malloc(sizeof(Region));
|
sound->region = new Region[1];
|
||||||
sound->jump = (Jump *)malloc(0);
|
sound->jump = new Jump[0];
|
||||||
sound->numJumps = 0;
|
sound->numJumps = 0;
|
||||||
sound->numRegions = 1;
|
sound->numRegions = 1;
|
||||||
sound->region[0].offset = 0;
|
sound->region[0].offset = 0;
|
||||||
|
@ -96,8 +96,8 @@ void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSiz
|
||||||
sound->numRegions = 0;
|
sound->numRegions = 0;
|
||||||
sound->numJumps = 0;
|
sound->numJumps = 0;
|
||||||
countElements(ptr, sound->numRegions, sound->numJumps);
|
countElements(ptr, sound->numRegions, sound->numJumps);
|
||||||
sound->region = (Region *)malloc(sizeof(Region) * sound->numRegions);
|
sound->region = new Region [sound->numRegions];
|
||||||
sound->jump = (Jump *)malloc(sizeof(Jump) * sound->numJumps);
|
sound->jump = new Jump [sound->numJumps];
|
||||||
|
|
||||||
do {
|
do {
|
||||||
tag = READ_BE_UINT32(ptr); ptr += 4;
|
tag = READ_BE_UINT32(ptr); ptr += 4;
|
||||||
|
@ -147,7 +147,7 @@ void ImuseSndMgr::parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSiz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImuseSndMgr::SoundStruct *ImuseSndMgr::allocSlot() {
|
ImuseSndMgr::SoundDesc *ImuseSndMgr::allocSlot() {
|
||||||
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
||||||
if (!_sounds[l].inUse) {
|
if (!_sounds[l].inUse) {
|
||||||
_sounds[l].inUse = true;
|
_sounds[l].inUse = true;
|
||||||
|
@ -158,12 +158,12 @@ ImuseSndMgr::SoundStruct *ImuseSndMgr::allocSlot() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImuseSndMgr::SoundStruct *ImuseSndMgr::openSound(const char *soundName, int volGroupId) {
|
ImuseSndMgr::SoundDesc *ImuseSndMgr::openSound(const char *soundName, int volGroupId) {
|
||||||
const char *extension = soundName + std::strlen(soundName) - 3;
|
const char *extension = soundName + std::strlen(soundName) - 3;
|
||||||
byte *ptr = NULL;
|
byte *ptr = NULL;
|
||||||
int headerSize = 0;
|
int headerSize = 0;
|
||||||
|
|
||||||
SoundStruct *sound = allocSlot();
|
SoundDesc *sound = allocSlot();
|
||||||
if (!sound) {
|
if (!sound) {
|
||||||
error("ImuseSndMgr::openSound() Can't alloc free sound slot");
|
error("ImuseSndMgr::openSound() Can't alloc free sound slot");
|
||||||
}
|
}
|
||||||
|
@ -197,94 +197,94 @@ ImuseSndMgr::SoundStruct *ImuseSndMgr::openSound(const char *soundName, int volG
|
||||||
return sound;
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImuseSndMgr::closeSound(SoundStruct *soundHandle) {
|
void ImuseSndMgr::closeSound(SoundDesc *sound) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
|
|
||||||
if (soundHandle->mcmpMgr) {
|
if (sound->mcmpMgr) {
|
||||||
delete soundHandle->mcmpMgr;
|
delete sound->mcmpMgr;
|
||||||
soundHandle->mcmpMgr = NULL;
|
sound->mcmpMgr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soundHandle->blockRes) {
|
if (sound->blockRes) {
|
||||||
delete soundHandle->blockRes;
|
delete sound->blockRes;
|
||||||
soundHandle->blockRes = NULL;
|
sound->blockRes = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soundHandle->region) {
|
if (sound->region) {
|
||||||
free(soundHandle->region);
|
delete[] sound->region;
|
||||||
soundHandle->region = NULL;
|
sound->region = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soundHandle->jump) {
|
if (sound->jump) {
|
||||||
free(soundHandle->jump);
|
delete[] sound->jump;
|
||||||
soundHandle->jump = NULL;
|
sound->jump = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(soundHandle, 0, sizeof(SoundStruct));
|
memset(sound, 0, sizeof(SoundDesc));
|
||||||
}
|
}
|
||||||
|
|
||||||
ImuseSndMgr::SoundStruct *ImuseSndMgr::cloneSound(SoundStruct *soundHandle) {
|
ImuseSndMgr::SoundDesc *ImuseSndMgr::cloneSound(SoundDesc *sound) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
|
|
||||||
return openSound(soundHandle->name, soundHandle->volGroupId);
|
return openSound(sound->name, sound->volGroupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImuseSndMgr::checkForProperHandle(SoundStruct *soundHandle) {
|
bool ImuseSndMgr::checkForProperHandle(SoundDesc *sound) {
|
||||||
if (!soundHandle)
|
if (!sound)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
for (int l = 0; l < MAX_IMUSE_SOUNDS; l++) {
|
||||||
if (soundHandle == &_sounds[l])
|
if (sound == &_sounds[l])
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getFreq(SoundStruct *soundHandle) {
|
int ImuseSndMgr::getFreq(SoundDesc *sound) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
return soundHandle->freq;
|
return sound->freq;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getBits(SoundStruct *soundHandle) {
|
int ImuseSndMgr::getBits(SoundDesc *sound) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
return soundHandle->bits;
|
return sound->bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getChannels(SoundStruct *soundHandle) {
|
int ImuseSndMgr::getChannels(SoundDesc *sound) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
return soundHandle->channels;
|
return sound->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImuseSndMgr::isEndOfRegion(SoundStruct *soundHandle, int region) {
|
bool ImuseSndMgr::isEndOfRegion(SoundDesc *sound, int region) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
assert(region >= 0 && region < soundHandle->numRegions);
|
assert(region >= 0 && region < sound->numRegions);
|
||||||
return soundHandle->endFlag;
|
return sound->endFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getNumRegions(SoundStruct *soundHandle) {
|
int ImuseSndMgr::getNumRegions(SoundDesc *sound) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
return soundHandle->numRegions;
|
return sound->numRegions;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getNumJumps(SoundStruct *soundHandle) {
|
int ImuseSndMgr::getNumJumps(SoundDesc *sound) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
return soundHandle->numJumps;
|
return sound->numJumps;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getRegionOffset(SoundStruct *soundHandle, int region) {
|
int ImuseSndMgr::getRegionOffset(SoundDesc *sound, int region) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
assert(region >= 0 && region < soundHandle->numRegions);
|
assert(region >= 0 && region < sound->numRegions);
|
||||||
return soundHandle->region[region].offset;
|
return sound->region[region].offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region, int hookId) {
|
int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundDesc *sound, int region, int hookId) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
assert(region >= 0 && region < soundHandle->numRegions);
|
assert(region >= 0 && region < sound->numRegions);
|
||||||
int32 offset = soundHandle->region[region].offset;
|
int32 offset = sound->region[region].offset;
|
||||||
for (int l = 0; l < soundHandle->numJumps; l++) {
|
for (int l = 0; l < sound->numJumps; l++) {
|
||||||
if (offset == soundHandle->jump[l].offset) {
|
if (offset == sound->jump[l].offset) {
|
||||||
if (soundHandle->jump[l].hookId == hookId)
|
if (sound->jump[l].hookId == hookId)
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,12 +292,12 @@ int ImuseSndMgr::getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId) {
|
int ImuseSndMgr::getRegionIdByJumpId(SoundDesc *sound, int jumpId) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
assert(jumpId >= 0 && jumpId < soundHandle->numJumps);
|
assert(jumpId >= 0 && jumpId < sound->numJumps);
|
||||||
int32 dest = soundHandle->jump[jumpId].dest;
|
int32 dest = sound->jump[jumpId].dest;
|
||||||
for (int l = 0; l < soundHandle->numRegions; l++) {
|
for (int l = 0; l < sound->numRegions; l++) {
|
||||||
if (dest == soundHandle->region[l].offset) {
|
if (dest == sound->region[l].offset) {
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,38 +305,38 @@ int ImuseSndMgr::getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getJumpHookId(SoundStruct *soundHandle, int number) {
|
int ImuseSndMgr::getJumpHookId(SoundDesc *sound, int number) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
assert(number >= 0 && number < soundHandle->numJumps);
|
assert(number >= 0 && number < sound->numJumps);
|
||||||
return soundHandle->jump[number].hookId;
|
return sound->jump[number].hookId;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ImuseSndMgr::getJumpFade(SoundStruct *soundHandle, int number) {
|
int ImuseSndMgr::getJumpFade(SoundDesc *sound, int number) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
assert(number >= 0 && number < soundHandle->numJumps);
|
assert(number >= 0 && number < sound->numJumps);
|
||||||
return soundHandle->jump[number].fadeDelay;
|
return sound->jump[number].fadeDelay;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 ImuseSndMgr::getDataFromRegion(SoundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size) {
|
int32 ImuseSndMgr::getDataFromRegion(SoundDesc *sound, int region, byte **buf, int32 offset, int32 size) {
|
||||||
assert(checkForProperHandle(soundHandle));
|
assert(checkForProperHandle(sound));
|
||||||
assert(buf && offset >= 0 && size >= 0);
|
assert(buf && offset >= 0 && size >= 0);
|
||||||
assert(region >= 0 && region < soundHandle->numRegions);
|
assert(region >= 0 && region < sound->numRegions);
|
||||||
|
|
||||||
int32 region_offset = soundHandle->region[region].offset;
|
int32 region_offset = sound->region[region].offset;
|
||||||
int32 region_length = soundHandle->region[region].length;
|
int32 region_length = sound->region[region].length;
|
||||||
|
|
||||||
if (offset + size > region_length) {
|
if (offset + size > region_length) {
|
||||||
size = region_length - offset;
|
size = region_length - offset;
|
||||||
soundHandle->endFlag = true;
|
sound->endFlag = true;
|
||||||
} else {
|
} else {
|
||||||
soundHandle->endFlag = false;
|
sound->endFlag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (soundHandle->mcmpData) {
|
if (sound->mcmpData) {
|
||||||
size = soundHandle->mcmpMgr->decompressSample(region_offset + offset, size, buf);
|
size = sound->mcmpMgr->decompressSample(region_offset + offset, size, buf);
|
||||||
} else {
|
} else {
|
||||||
*buf = (byte *)malloc(size);
|
*buf = new byte[size];
|
||||||
memcpy(*buf, soundHandle->resPtr + region_offset + offset, size);
|
memcpy(*buf, sound->resPtr + region_offset + offset, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
|
|
|
@ -64,7 +64,7 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct SoundStruct {
|
struct SoundDesc {
|
||||||
uint16 freq; // frequency
|
uint16 freq; // frequency
|
||||||
byte channels; // stereo or mono
|
byte channels; // stereo or mono
|
||||||
byte bits; // 8, 12, 16
|
byte bits; // 8, 12, 16
|
||||||
|
@ -77,6 +77,7 @@ public:
|
||||||
char name[32];
|
char name[32];
|
||||||
McmpMgr *mcmpMgr;
|
McmpMgr *mcmpMgr;
|
||||||
Block *blockRes;
|
Block *blockRes;
|
||||||
|
int type;
|
||||||
int volGroupId;
|
int volGroupId;
|
||||||
byte *resPtr;
|
byte *resPtr;
|
||||||
bool mcmpData;
|
bool mcmpData;
|
||||||
|
@ -84,11 +85,11 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
SoundStruct _sounds[MAX_IMUSE_SOUNDS];
|
SoundDesc _sounds[MAX_IMUSE_SOUNDS];
|
||||||
|
|
||||||
bool checkForProperHandle(SoundStruct *soundHandle);
|
bool checkForProperHandle(SoundDesc *soundDesc);
|
||||||
SoundStruct *allocSlot();
|
SoundDesc *allocSlot();
|
||||||
void parseSoundHeader(byte *ptr, SoundStruct *sound, int &headerSize);
|
void parseSoundHeader(byte *ptr, SoundDesc *sound, int &headerSize);
|
||||||
void countElements(byte *ptr, int &numRegions, int &numJumps);
|
void countElements(byte *ptr, int &numRegions, int &numJumps);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -96,23 +97,23 @@ public:
|
||||||
ImuseSndMgr();
|
ImuseSndMgr();
|
||||||
~ImuseSndMgr();
|
~ImuseSndMgr();
|
||||||
|
|
||||||
SoundStruct *openSound(const char *soundName, int volGroupId);
|
SoundDesc *openSound(const char *soundName, int volGroupId);
|
||||||
void closeSound(SoundStruct *soundHandle);
|
void closeSound(SoundDesc *sound);
|
||||||
SoundStruct *cloneSound(SoundStruct *soundHandle);
|
SoundDesc *cloneSound(SoundDesc *sound);
|
||||||
|
|
||||||
int getFreq(SoundStruct *soundHandle);
|
int getFreq(SoundDesc *sound);
|
||||||
int getBits(SoundStruct *soundHandle);
|
int getBits(SoundDesc *sound);
|
||||||
int getChannels(SoundStruct *soundHandle);
|
int getChannels(SoundDesc *sound);
|
||||||
bool isEndOfRegion(SoundStruct *soundHandle, int region);
|
bool isEndOfRegion(SoundDesc *sound, int region);
|
||||||
int getNumRegions(SoundStruct *soundHandle);
|
int getNumRegions(SoundDesc *sound);
|
||||||
int getNumJumps(SoundStruct *soundHandle);
|
int getNumJumps(SoundDesc *sound);
|
||||||
int getRegionOffset(SoundStruct *soundHandle, int region);
|
int getRegionOffset(SoundDesc *sound, int region);
|
||||||
int getJumpIdByRegionAndHookId(SoundStruct *soundHandle, int region, int hookId);
|
int getJumpIdByRegionAndHookId(SoundDesc *sound, int region, int hookId);
|
||||||
int getRegionIdByJumpId(SoundStruct *soundHandle, int jumpId);
|
int getRegionIdByJumpId(SoundDesc *sound, int jumpId);
|
||||||
int getJumpHookId(SoundStruct *soundHandle, int number);
|
int getJumpHookId(SoundDesc *sound, int number);
|
||||||
int getJumpFade(SoundStruct *soundHandle, int number);
|
int getJumpFade(SoundDesc *sound, int number);
|
||||||
|
|
||||||
int32 getDataFromRegion(SoundStruct *soundHandle, int region, byte **buf, int32 offset, int32 size);
|
int32 getDataFromRegion(SoundDesc *sound, int region, byte **buf, int32 offset, int32 size);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
49
engine/imuse/imuse_tables.h
Normal file
49
engine/imuse/imuse_tables.h
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMUSE_TABLES_H
|
||||||
|
#define IMUSE_TABLES_H
|
||||||
|
|
||||||
|
#include "common/sys.h"
|
||||||
|
#include "common/platform.h"
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
#include "engine/lua.h"
|
||||||
|
|
||||||
|
#include "mixer/mixer.h"
|
||||||
|
#include "mixer/audiostream.h"
|
||||||
|
|
||||||
|
#include "engine/imuse/imuse_sndmgr.h"
|
||||||
|
#include "engine/imuse/imuse_mcmp_mgr.h"
|
||||||
|
|
||||||
|
struct ImuseTable {
|
||||||
|
byte opcode;
|
||||||
|
int16 soundId;
|
||||||
|
byte atribPos;
|
||||||
|
byte hookId;
|
||||||
|
int16 fadeOut60TicksDelay;
|
||||||
|
byte volume;
|
||||||
|
byte pan;
|
||||||
|
char filename[32];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -23,6 +23,7 @@
|
||||||
#include "common/sys.h"
|
#include "common/sys.h"
|
||||||
#include "common/platform.h"
|
#include "common/platform.h"
|
||||||
#include "common/debug.h"
|
#include "common/debug.h"
|
||||||
|
#include "common/mutex.h"
|
||||||
|
|
||||||
#include "engine/backend/driver.h"
|
#include "engine/backend/driver.h"
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@
|
||||||
|
|
||||||
#include "engine/imuse/imuse.h"
|
#include "engine/imuse/imuse.h"
|
||||||
#include "engine/imuse/imuse_sndmgr.h"
|
#include "engine/imuse/imuse_sndmgr.h"
|
||||||
|
#include "engine/imuse/imuse_track.h"
|
||||||
|
|
||||||
int Imuse::allocSlot(int priority) {
|
int Imuse::allocSlot(int priority) {
|
||||||
int l, lowest_priority = 127;
|
int l, lowest_priority = 127;
|
||||||
|
@ -39,35 +41,46 @@ int Imuse::allocSlot(int priority) {
|
||||||
// allocSlot called by startSound so no locking is necessary
|
// allocSlot called by startSound so no locking is necessary
|
||||||
for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
if (!_track[l]->used) {
|
if (!_track[l]->used) {
|
||||||
return l; // Found an unused track
|
trackId = l;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
warning("Imuse::startSound(): All slots are full");
|
if (trackId == -1) {
|
||||||
for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
warning("Imuse::startSound(): All slots are full");
|
||||||
Track *track = _track[l];
|
for (l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
if (track->used && !track->toBeRemoved && lowest_priority > track->priority) {
|
Track *track = _track[l];
|
||||||
lowest_priority = track->priority;
|
if (track->used && !track->toBeRemoved &&
|
||||||
trackId = l;
|
(lowest_priority > track->priority)) {
|
||||||
|
lowest_priority = track->priority;
|
||||||
|
trackId = l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lowest_priority <= priority) {
|
||||||
|
assert(trackId != -1);
|
||||||
|
Track *track = _track[trackId];
|
||||||
|
|
||||||
|
// Stop the track immediately
|
||||||
|
g_mixer->stopHandle(track->handle);
|
||||||
|
if (track->soundDesc) {
|
||||||
|
_sound->closeSound(track->soundDesc);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark it as unused
|
||||||
|
memset(track, 0, sizeof(Track));
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (lowest_priority <= priority) {
|
|
||||||
assert(trackId != -1);
|
|
||||||
_track[trackId]->toBeRemoved = true;
|
|
||||||
warning("Imuse::startSound(): Removed sound %s from track %d", _track[trackId]->soundName, trackId);
|
|
||||||
} else {
|
|
||||||
warning("Imuse::startSound(): Priority sound too low");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return trackId;
|
return trackId;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority) {
|
bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int volume, int pan, int priority, Track *otherTrack) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *track = NULL;
|
Track *track = NULL;
|
||||||
int i, l = -1;
|
int i;
|
||||||
|
|
||||||
StackLock lock(_mutex);
|
|
||||||
// If the track is already playing then there is absolutely no
|
// If the track is already playing then there is absolutely no
|
||||||
// reason to start it again, the existing track should be modified
|
// reason to start it again, the existing track should be modified
|
||||||
// instead of starting a new copy of the track
|
// instead of starting a new copy of the track
|
||||||
|
@ -79,111 +92,73 @@ bool Imuse::startSound(const char *soundName, int volGroupId, int hookId, int vo
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Priority Level 127 appears to mean "load but don't play", so
|
// Priority Level 127 appears to mean "load but don't play", so
|
||||||
// within our paradigm this is a much lower priority than everything
|
// within our paradigm this is a much lower priority than everything
|
||||||
// else we're doing
|
// else we're doing
|
||||||
if (priority == 127)
|
if (priority == 127)
|
||||||
priority = -1;
|
priority = -1;
|
||||||
l = allocSlot(priority);
|
|
||||||
|
int l = allocSlot(priority);
|
||||||
if (l == -1) {
|
if (l == -1) {
|
||||||
warning("Imuse::startSound(): Can't start sound - no free slots");
|
warning("Imuse::startSound() Can't start sound - no free slots");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
track = _track[l];
|
|
||||||
i = 5;
|
|
||||||
// At this time it is inappropriate to assume that this will always
|
|
||||||
// succeed, so set a limit of 5 tries on running flushTracks
|
|
||||||
while (track->used && i > 0) {
|
|
||||||
// The designated track is not yet available. So, we call flushTracks()
|
|
||||||
// to get it processed (and thus made ready for us). Since the actual
|
|
||||||
// processing is done by another thread, we also call parseEvents to
|
|
||||||
// give it some time (and to avoid busy waiting/looping).
|
|
||||||
flushTracks();
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
if (i == 0) {
|
|
||||||
if (debugLevel == DEBUG_IMUSE || debugLevel == DEBUG_WARN || debugLevel == DEBUG_ALL)
|
|
||||||
warning("Imuse::startSound(): flushTracks was unable to free up a track for %s!", soundName);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
track = _track[l];
|
||||||
|
// Reset the track
|
||||||
|
memset(track, 0, sizeof(Track));
|
||||||
|
|
||||||
track->pan = pan * 1000;
|
track->pan = pan * 1000;
|
||||||
track->panFadeDest = 0;
|
|
||||||
track->panFadeStep = 0;
|
|
||||||
track->panFadeDelay = 0;
|
|
||||||
track->panFadeUsed = false;
|
|
||||||
track->vol = volume * 1000;
|
track->vol = volume * 1000;
|
||||||
track->volFadeDest = 0;
|
|
||||||
track->volFadeStep = 0;
|
|
||||||
track->volFadeDelay = 0;
|
|
||||||
track->volFadeUsed = false;
|
|
||||||
track->started = false;
|
|
||||||
track->volGroupId = volGroupId;
|
track->volGroupId = volGroupId;
|
||||||
track->curHookId = hookId;
|
track->curHookId = hookId;
|
||||||
track->priority = priority;
|
track->priority = priority;
|
||||||
track->curRegion = -1;
|
track->curRegion = -1;
|
||||||
track->dataOffset = 0;
|
|
||||||
track->regionOffset = 0;
|
|
||||||
track->mixerFlags = 0;
|
|
||||||
track->mixerPan = 0;
|
|
||||||
track->mixerVol = volume;
|
|
||||||
track->toBeRemoved = false;
|
|
||||||
track->readyToRemove = false;
|
|
||||||
|
|
||||||
int bits = 0, freq = 0, channels = 0;
|
int bits = 0, freq = 0, channels = 0;
|
||||||
|
|
||||||
strcpy(track->soundName, soundName);
|
strcpy(track->soundName, soundName);
|
||||||
track->soundHandle = _sound->openSound(soundName, volGroupId);
|
track->soundDesc = _sound->openSound(soundName, volGroupId);
|
||||||
|
|
||||||
if (track->soundHandle == NULL)
|
if (!track->soundDesc)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bits = _sound->getBits(track->soundHandle);
|
bits = _sound->getBits(track->soundDesc);
|
||||||
channels = _sound->getChannels(track->soundHandle);
|
channels = _sound->getChannels(track->soundDesc);
|
||||||
freq = _sound->getFreq(track->soundHandle);
|
freq = _sound->getFreq(track->soundDesc);
|
||||||
|
|
||||||
assert(bits == 8 || bits == 12 || bits == 16);
|
assert(bits == 8 || bits == 12 || bits == 16);
|
||||||
assert(channels == 1 || channels == 2);
|
assert(channels == 1 || channels == 2);
|
||||||
assert(0 < freq && freq <= 65535);
|
assert(0 < freq && freq <= 65535);
|
||||||
|
|
||||||
track->iteration = freq * channels * 2;
|
track->feedSize = freq * channels * 2;
|
||||||
track->mixerFlags = SoundMixer::FLAG_16BITS;
|
track->mixerFlags = kFlag16Bits;
|
||||||
if (channels == 2)
|
if (channels == 2)
|
||||||
track->mixerFlags |= SoundMixer::FLAG_STEREO | SoundMixer::FLAG_REVERSE_STEREO;
|
track->mixerFlags |= kFlagStereo | kFlagReverseStereo;
|
||||||
|
|
||||||
pan = track->pan / 1000;
|
if (otherTrack && otherTrack->used && !otherTrack->toBeRemoved) {
|
||||||
pan = (pan != 64) ? 2 * pan - 127 : 0;
|
track->curRegion = otherTrack->curRegion;
|
||||||
volume = track->vol / 1000;
|
track->dataOffset = otherTrack->dataOffset;
|
||||||
|
track->regionOffset = otherTrack->regionOffset;
|
||||||
|
}
|
||||||
|
|
||||||
if (track->volGroupId == 1)
|
track->stream = Audio::makeAppendableAudioStream(freq, makeMixerFlags(track->mixerFlags));
|
||||||
volume = (volume * _volVoice) / 128;
|
g_mixer->playInputStream(track->getType(), &track->handle, track->stream, -1, track->getVol(), track->getPan());
|
||||||
if (track->volGroupId == 2)
|
|
||||||
volume = (volume * _volSfx) / 128;
|
|
||||||
if (track->volGroupId == 3)
|
|
||||||
volume = (volume * _volMusic) / 128;
|
|
||||||
|
|
||||||
track->mixerPan = pan;
|
|
||||||
track->mixerVol = volume;
|
|
||||||
|
|
||||||
// setup 1 second stream wrapped buffer
|
|
||||||
int32 streamBufferSize = track->iteration;
|
|
||||||
track->stream = makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
|
|
||||||
g_mixer->playInputStream(&track->handle, track->stream, false, -1, track->mixerVol, track->mixerPan, false);
|
|
||||||
track->started = true;
|
|
||||||
track->used = true;
|
track->used = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Imuse::Track *Imuse::findTrack(const char *soundName) {
|
Track *Imuse::findTrack(const char *soundName) {
|
||||||
StackLock lock(_mutex);
|
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
|
|
||||||
// Since the audio (at least for Eva's keystrokes) can be referenced
|
// Since the audio (at least for Eva's keystrokes) can be referenced
|
||||||
// two ways: keyboard.IMU and keyboard.imu, make a case insensitive
|
// two ways: keyboard.IMU and keyboard.imu, make a case insensitive
|
||||||
// search for the track to make sure we can find it
|
// search for the track to make sure we can find it
|
||||||
if (strlen(track->soundName) != 0 && strcasecmp(track->soundName, soundName) == 0) {
|
if (track->used && !track->toBeRemoved
|
||||||
|
&& strlen(track->soundName) != 0 && strcasecmp(track->soundName, soundName) == 0) {
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -191,6 +166,7 @@ Imuse::Track *Imuse::findTrack(const char *soundName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::setPriority(const char *soundName, int priority) {
|
void Imuse::setPriority(const char *soundName, int priority) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *changeTrack = NULL;
|
Track *changeTrack = NULL;
|
||||||
assert ((priority >= 0) && (priority <= 127));
|
assert ((priority >= 0) && (priority <= 127));
|
||||||
|
|
||||||
|
@ -204,6 +180,7 @@ void Imuse::setPriority(const char *soundName, int priority) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::setVolume(const char *soundName, int volume) {
|
void Imuse::setVolume(const char *soundName, int volume) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *changeTrack;
|
Track *changeTrack;
|
||||||
|
|
||||||
changeTrack = findTrack(soundName);
|
changeTrack = findTrack(soundName);
|
||||||
|
@ -215,17 +192,19 @@ void Imuse::setVolume(const char *soundName, int volume) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::setPan(const char *soundName, int pan) {
|
void Imuse::setPan(const char *soundName, int pan) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *changeTrack;
|
Track *changeTrack;
|
||||||
|
|
||||||
changeTrack = findTrack(soundName);
|
changeTrack = findTrack(soundName);
|
||||||
if (changeTrack == NULL) {
|
if (changeTrack == NULL) {
|
||||||
warning("Unable to find track '%s' to change volume!", soundName);
|
warning("Unable to find track '%s' to change pan!", soundName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
changeTrack->pan = pan;
|
changeTrack->pan = pan * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Imuse::getVolume(const char *soundName) {
|
int Imuse::getVolume(const char *soundName) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *getTrack;
|
Track *getTrack;
|
||||||
|
|
||||||
getTrack = findTrack(soundName);
|
getTrack = findTrack(soundName);
|
||||||
|
@ -237,6 +216,7 @@ int Imuse::getVolume(const char *soundName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::setHookId(const char *soundName, int hookId) {
|
void Imuse::setHookId(const char *soundName, int hookId) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *changeTrack;
|
Track *changeTrack;
|
||||||
|
|
||||||
changeTrack = findTrack(soundName);
|
changeTrack = findTrack(soundName);
|
||||||
|
@ -248,12 +228,12 @@ void Imuse::setHookId(const char *soundName, int hookId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int Imuse::getCountPlayedTracks(const char *soundName) {
|
int Imuse::getCountPlayedTracks(const char *soundName) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
StackLock lock(_mutex);
|
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
if (track->used && !track->toBeRemoved && (strcmp(track->soundName, soundName) == 0)) {
|
if (track->used && !track->toBeRemoved && (strcasecmp(track->soundName, soundName) == 0)) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -262,6 +242,7 @@ int Imuse::getCountPlayedTracks(const char *soundName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::selectVolumeGroup(const char *soundName, int volGroupId) {
|
void Imuse::selectVolumeGroup(const char *soundName, int volGroupId) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *changeTrack;
|
Track *changeTrack;
|
||||||
assert((volGroupId >= 1) && (volGroupId <= 4));
|
assert((volGroupId >= 1) && (volGroupId <= 4));
|
||||||
|
|
||||||
|
@ -277,6 +258,7 @@ void Imuse::selectVolumeGroup(const char *soundName, int volGroupId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::setFadeVolume(const char *soundName, int destVolume, int duration) {
|
void Imuse::setFadeVolume(const char *soundName, int destVolume, int duration) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *changeTrack;
|
Track *changeTrack;
|
||||||
|
|
||||||
changeTrack = findTrack(soundName);
|
changeTrack = findTrack(soundName);
|
||||||
|
@ -291,6 +273,7 @@ void Imuse::setFadeVolume(const char *soundName, int destVolume, int duration) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Imuse::setFadePan(const char *soundName, int destPan, int duration) {
|
void Imuse::setFadePan(const char *soundName, int destPan, int duration) {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
Track *changeTrack;
|
Track *changeTrack;
|
||||||
|
|
||||||
changeTrack = findTrack(soundName);
|
changeTrack = findTrack(soundName);
|
||||||
|
@ -305,7 +288,7 @@ void Imuse::setFadePan(const char *soundName, int destPan, int duration) {
|
||||||
}
|
}
|
||||||
|
|
||||||
char *Imuse::getCurMusicSoundName() {
|
char *Imuse::getCurMusicSoundName() {
|
||||||
StackLock lock(_mutex);
|
Common::StackLock lock(_mutex);
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
||||||
|
@ -315,65 +298,90 @@ char *Imuse::getCurMusicSoundName() {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Imuse::getCurMusicPan() {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
|
Track *track = _track[l];
|
||||||
|
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
||||||
|
return track->pan / 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Imuse::getCurMusicVol() {
|
||||||
|
Common::StackLock lock(_mutex);
|
||||||
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
|
Track *track = _track[l];
|
||||||
|
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
||||||
|
return track->vol / 1000;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void Imuse::fadeOutMusic(int duration) {
|
void Imuse::fadeOutMusic(int duration) {
|
||||||
StackLock lock(_mutex);
|
Common::StackLock lock(_mutex);
|
||||||
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
Track *track = _track[l];
|
Track *track = _track[l];
|
||||||
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
||||||
cloneToFadeOutTrack(track, duration);
|
cloneToFadeOutTrack(track, duration);
|
||||||
track->toBeRemoved = true;
|
flushTrack(track);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Imuse::Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
|
void Imuse::fadeOutMusicAndStartNew(int fadeDelay, const char *filename, int hookId, int vol, int pan) {
|
||||||
assert(track);
|
Common::StackLock lock(_mutex);
|
||||||
Track *fadeTrack = 0;
|
|
||||||
|
|
||||||
{
|
for (int l = 0; l < MAX_IMUSE_TRACKS; l++) {
|
||||||
StackLock lock(_mutex);
|
Track *track = _track[l];
|
||||||
for (int l = MAX_IMUSE_TRACKS; l < MAX_IMUSE_TRACKS + MAX_IMUSE_FADETRACKS; l++) {
|
if (track->used && !track->toBeRemoved && (track->volGroupId == IMUSE_VOLGRP_MUSIC)) {
|
||||||
if (!_track[l]->used) {
|
startMusicWithOtherPos(filename, 0, vol, pan, track);
|
||||||
fadeTrack = _track[l];
|
cloneToFadeOutTrack(track, fadeDelay);
|
||||||
break;
|
flushTrack(track);
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
if (fadeTrack == 0)
|
}
|
||||||
error("Imuse::cloneTofadeTrackId() Can't find free fade track");
|
}
|
||||||
|
|
||||||
fadeTrack->pan = track->pan;
|
Track *Imuse::cloneToFadeOutTrack(Track *track, int fadeDelay) {
|
||||||
fadeTrack->vol = track->vol;
|
assert(track);
|
||||||
fadeTrack->volGroupId = track->volGroupId;
|
Track *fadeTrack;
|
||||||
fadeTrack->priority = track->priority;
|
|
||||||
fadeTrack->dataOffset = track->dataOffset;
|
if (track->toBeRemoved) {
|
||||||
fadeTrack->regionOffset = track->regionOffset;
|
error("cloneToFadeOutTrack: Tried to clone a track to be removed, please bug report");
|
||||||
fadeTrack->curRegion = track->curRegion;
|
return NULL;
|
||||||
fadeTrack->curHookId = track->curHookId;
|
|
||||||
fadeTrack->iteration = track->iteration;
|
|
||||||
fadeTrack->mixerFlags = track->mixerFlags;
|
|
||||||
fadeTrack->mixerVol = track->mixerVol;
|
|
||||||
fadeTrack->mixerPan = track->mixerPan;
|
|
||||||
fadeTrack->toBeRemoved = track->toBeRemoved;
|
|
||||||
fadeTrack->readyToRemove = track->readyToRemove;
|
|
||||||
fadeTrack->started = track->started;
|
|
||||||
strcpy(fadeTrack->soundName, track->soundName);
|
|
||||||
fadeTrack->soundHandle = _sound->cloneSound(track->soundHandle);
|
|
||||||
assert(fadeTrack->soundHandle);
|
|
||||||
fadeTrack->volFadeDelay = fadeDelay;
|
|
||||||
fadeTrack->volFadeDest = 0;
|
|
||||||
fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
|
|
||||||
fadeTrack->volFadeUsed = true;
|
|
||||||
fadeTrack->panFadeDelay = 0;
|
|
||||||
fadeTrack->panFadeDest = 0;
|
|
||||||
fadeTrack->panFadeStep = 0;
|
|
||||||
fadeTrack->panFadeUsed = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup 1 second stream wrapped buffer
|
assert(track->trackId < MAX_IMUSE_TRACKS);
|
||||||
int32 streamBufferSize = fadeTrack->iteration;
|
fadeTrack = _track[track->trackId + MAX_IMUSE_TRACKS];
|
||||||
fadeTrack->stream = makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), fadeTrack->mixerFlags, streamBufferSize);
|
|
||||||
g_mixer->playInputStream(&fadeTrack->handle, fadeTrack->stream, false, -1, fadeTrack->vol / 1000, fadeTrack->pan, false);
|
if (fadeTrack->used) {
|
||||||
fadeTrack->started = true;
|
flushTrack(fadeTrack);
|
||||||
|
g_mixer->stopHandle(fadeTrack->handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone the settings of the given track
|
||||||
|
memcpy(fadeTrack, track, sizeof(Track));
|
||||||
|
fadeTrack->trackId = track->trackId + MAX_IMUSE_TRACKS;
|
||||||
|
|
||||||
|
// Clone the sound.
|
||||||
|
// leaving bug number for now #1635361
|
||||||
|
ImuseSndMgr::SoundDesc *soundDesc = _sound->cloneSound(track->soundDesc);
|
||||||
|
assert(soundDesc);
|
||||||
|
track->soundDesc = soundDesc;
|
||||||
|
|
||||||
|
// Set the volume fading parameters to indicate a fade out
|
||||||
|
fadeTrack->volFadeDelay = fadeDelay;
|
||||||
|
fadeTrack->volFadeDest = 0;
|
||||||
|
fadeTrack->volFadeStep = (fadeTrack->volFadeDest - fadeTrack->vol) * 60 * (1000 / _callbackFps) / (1000 * fadeDelay);
|
||||||
|
fadeTrack->volFadeUsed = true;
|
||||||
|
|
||||||
|
// Create an appendable output buffer
|
||||||
|
fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundDesc), makeMixerFlags(fadeTrack->mixerFlags));
|
||||||
|
g_mixer->playInputStream(track->getType(), &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->getVol(), fadeTrack->getPan());
|
||||||
fadeTrack->used = true;
|
fadeTrack->used = true;
|
||||||
|
|
||||||
return fadeTrack;
|
return fadeTrack;
|
||||||
|
|
98
engine/imuse/imuse_track.h
Normal file
98
engine/imuse/imuse_track.h
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/* Residual - Virtual machine to run LucasArts' 3D adventure games
|
||||||
|
* Copyright (C) 2003-2006 The ScummVM-Residual Team (www.scummvm.org)
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
*
|
||||||
|
* $URL$
|
||||||
|
* $Id$
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef IMUSE_TRACK_H
|
||||||
|
#define IMUSE_TRACK_H
|
||||||
|
|
||||||
|
#include "common/sys.h"
|
||||||
|
#include "common/platform.h"
|
||||||
|
#include "common/debug.h"
|
||||||
|
|
||||||
|
#include "engine/lua.h"
|
||||||
|
|
||||||
|
#include "mixer/mixer.h"
|
||||||
|
#include "mixer/audiostream.h"
|
||||||
|
|
||||||
|
#include "engine/imuse/imuse_sndmgr.h"
|
||||||
|
#include "engine/imuse/imuse_mcmp_mgr.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
kFlagUnsigned = 1 << 0,
|
||||||
|
kFlag16Bits = 1 << 1,
|
||||||
|
kFlagLittleEndian = 1 << 2,
|
||||||
|
kFlagStereo = 1 << 3,
|
||||||
|
kFlagReverseStereo = 1 << 4
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Track {
|
||||||
|
int trackId;
|
||||||
|
|
||||||
|
int32 pan;
|
||||||
|
int32 panFadeDest;
|
||||||
|
int32 panFadeStep;
|
||||||
|
int32 panFadeDelay;
|
||||||
|
bool panFadeUsed;
|
||||||
|
int32 vol;
|
||||||
|
int32 volFadeDest;
|
||||||
|
int32 volFadeStep;
|
||||||
|
int32 volFadeDelay;
|
||||||
|
bool volFadeUsed;
|
||||||
|
|
||||||
|
char soundName[32];
|
||||||
|
bool used;
|
||||||
|
bool toBeRemoved;
|
||||||
|
int32 priority;
|
||||||
|
int32 regionOffset;
|
||||||
|
int32 dataOffset;
|
||||||
|
int32 curRegion;
|
||||||
|
int32 curHookId;
|
||||||
|
int32 volGroupId;
|
||||||
|
int32 feedSize;
|
||||||
|
int32 mixerFlags;
|
||||||
|
|
||||||
|
ImuseSndMgr::SoundDesc *soundDesc;
|
||||||
|
Audio::SoundHandle handle;
|
||||||
|
Audio::AppendableAudioStream *stream;
|
||||||
|
|
||||||
|
Track() : used(false), stream(NULL) {
|
||||||
|
soundName[0] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getPan() const { return (pan != 6400) ? 2 * (pan / 1000) - 127 : 0; }
|
||||||
|
int getVol() const { return vol / 1000; }
|
||||||
|
Audio::Mixer::SoundType getType() const {
|
||||||
|
Audio::Mixer::SoundType type = Audio::Mixer::kPlainSoundType;
|
||||||
|
if (volGroupId == IMUSE_VOLGRP_VOICE)
|
||||||
|
type = Audio::Mixer::kSpeechSoundType;
|
||||||
|
else if (volGroupId == IMUSE_VOLGRP_SFX)
|
||||||
|
type = Audio::Mixer::kSFXSoundType;
|
||||||
|
else if (volGroupId == IMUSE_VOLGRP_MUSIC)
|
||||||
|
type = Audio::Mixer::kMusicSoundType;
|
||||||
|
else if (volGroupId == IMUSE_VOLGRP_BGND)
|
||||||
|
type = Audio::Mixer::kPlainSoundType;
|
||||||
|
else if (volGroupId == IMUSE_VOLGRP_ACTION)
|
||||||
|
type = Audio::Mixer::kPlainSoundType;
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
|
@ -42,6 +42,8 @@
|
||||||
|
|
||||||
#include "engine/imuse/imuse.h"
|
#include "engine/imuse/imuse.h"
|
||||||
|
|
||||||
|
#include "mixer/mixer.h"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
@ -1880,7 +1882,7 @@ static void ImStartSound() {
|
||||||
group = check_int(3);
|
group = check_int(3);
|
||||||
|
|
||||||
// Start the sound with the appropriate settings
|
// Start the sound with the appropriate settings
|
||||||
if (g_imuse->startSound(soundName, group, 0, 127, 0, priority)) {
|
if (g_imuse->startSound(soundName, group, 0, 127, 0, priority, NULL)) {
|
||||||
lua_pushstring(soundName);
|
lua_pushstring(soundName);
|
||||||
} else {
|
} else {
|
||||||
// Allow soft failing when loading sounds, hard failing when not
|
// Allow soft failing when loading sounds, hard failing when not
|
||||||
|
@ -1929,32 +1931,32 @@ static void ImSetVoiceEffect() {
|
||||||
|
|
||||||
static void ImSetMusicVol() {
|
static void ImSetMusicVol() {
|
||||||
DEBUG_FUNCTION();
|
DEBUG_FUNCTION();
|
||||||
g_imuse->setGroupMusicVolume(check_int(1));
|
g_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, check_int(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGetMusicVol() {
|
static void ImGetMusicVol() {
|
||||||
DEBUG_FUNCTION();
|
DEBUG_FUNCTION();
|
||||||
lua_pushnumber(g_imuse->getGroupMusicVolume());
|
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kMusicSoundType));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImSetVoiceVol() {
|
static void ImSetVoiceVol() {
|
||||||
DEBUG_FUNCTION();
|
DEBUG_FUNCTION();
|
||||||
g_imuse->setGroupVoiceVolume(check_int(1));
|
g_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, check_int(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGetVoiceVol() {
|
static void ImGetVoiceVol() {
|
||||||
DEBUG_FUNCTION();
|
DEBUG_FUNCTION();
|
||||||
lua_pushnumber(g_imuse->getGroupVoiceVolume());
|
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImSetSfxVol() {
|
static void ImSetSfxVol() {
|
||||||
DEBUG_FUNCTION();
|
DEBUG_FUNCTION();
|
||||||
g_imuse->setGroupSfxVolume(check_int(1));
|
g_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, check_int(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImGetSfxVol() {
|
static void ImGetSfxVol() {
|
||||||
DEBUG_FUNCTION();
|
DEBUG_FUNCTION();
|
||||||
lua_pushnumber(g_imuse->getGroupSfxVolume());
|
lua_pushnumber(g_mixer->getVolumeForSoundType(Audio::Mixer::kSFXSoundType));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ImSetParam() {
|
static void ImSetParam() {
|
||||||
|
@ -2961,7 +2963,7 @@ static void GetSaveGameImage() {
|
||||||
filename = luaL_check_string(1);
|
filename = luaL_check_string(1);
|
||||||
SaveGame *savedState = new SaveGame(filename, false);
|
SaveGame *savedState = new SaveGame(filename, false);
|
||||||
dataSize = savedState->beginSection('SIMG');
|
dataSize = savedState->beginSection('SIMG');
|
||||||
data = (char *)malloc(dataSize);
|
data = new char[dataSize];
|
||||||
savedState->read(data, dataSize);
|
savedState->read(data, dataSize);
|
||||||
screenshot = new Bitmap(data, width, height, "screenshot");
|
screenshot = new Bitmap(data, width, height, "screenshot");
|
||||||
if (screenshot) {
|
if (screenshot) {
|
||||||
|
|
|
@ -58,6 +58,8 @@ enDebugLevels debugLevel = DEBUG_NONE;
|
||||||
|
|
||||||
static bool g_lua_initialized = false;
|
static bool g_lua_initialized = false;
|
||||||
Driver *g_driver = NULL;
|
Driver *g_driver = NULL;
|
||||||
|
DefaultTimerManager *g_timer = NULL;
|
||||||
|
Audio::Mixer *g_mixer = NULL;
|
||||||
|
|
||||||
static bool parseBoolStr(const char *val) {
|
static bool parseBoolStr(const char *val) {
|
||||||
if (val == NULL || val[0] == 0)
|
if (val == NULL || val[0] == 0)
|
||||||
|
@ -168,12 +170,18 @@ needshelp:
|
||||||
g_driver = new DriverTinyGL(640, 480, 16, fullscreen);
|
g_driver = new DriverTinyGL(640, 480, 16, fullscreen);
|
||||||
else
|
else
|
||||||
g_driver = new DriverGL(640, 480, 24, fullscreen);
|
g_driver = new DriverGL(640, 480, 24, fullscreen);
|
||||||
|
g_timer = new DefaultTimerManager();
|
||||||
|
g_driver->setTimerCallback();
|
||||||
|
g_mixer = new Audio::Mixer();
|
||||||
|
g_driver->setSoundCallback(Audio::Mixer::mixCallback, g_mixer);
|
||||||
|
g_mixer->setReady(true);
|
||||||
|
g_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, 127);
|
||||||
|
g_mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||||
|
g_mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||||
|
g_mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, Audio::Mixer::kMaxMixerVolume);
|
||||||
g_engine = new Engine();
|
g_engine = new Engine();
|
||||||
g_resourceloader = new ResourceLoader();
|
g_resourceloader = new ResourceLoader();
|
||||||
g_localizer = new Localizer();
|
g_localizer = new Localizer();
|
||||||
g_mixer = new SoundMixer();
|
|
||||||
g_mixer->setVolume(255);
|
|
||||||
g_timer = new Timer();
|
|
||||||
g_smush = new Smush();
|
g_smush = new Smush();
|
||||||
g_imuse = new Imuse(20);
|
g_imuse = new Imuse(20);
|
||||||
|
|
||||||
|
@ -226,6 +234,8 @@ void quit() {
|
||||||
delete g_registry;
|
delete g_registry;
|
||||||
g_registry = NULL;
|
g_registry = NULL;
|
||||||
}
|
}
|
||||||
|
if (g_driver)
|
||||||
|
g_driver->clearTimerCallback();
|
||||||
delete g_smush;
|
delete g_smush;
|
||||||
g_smush = NULL;
|
g_smush = NULL;
|
||||||
delete g_imuse;
|
delete g_imuse;
|
||||||
|
|
|
@ -68,17 +68,17 @@ uint32 SaveGame::beginSection(uint32 sectionTag) {
|
||||||
error("Tried to begin a new save game section with ending old section!");
|
error("Tried to begin a new save game section with ending old section!");
|
||||||
_currentSection = sectionTag;
|
_currentSection = sectionTag;
|
||||||
_sectionSize = 0;
|
_sectionSize = 0;
|
||||||
_sectionBuffer = (char *) malloc(_sectionSize);
|
_sectionBuffer = new char[_sectionSize];
|
||||||
if (!_saving) {
|
if (!_saving) {
|
||||||
uint32 tag = 0;
|
uint32 tag = 0;
|
||||||
|
|
||||||
while (tag != sectionTag) {
|
while (tag != sectionTag) {
|
||||||
free(_sectionBuffer);
|
delete[] _sectionBuffer;
|
||||||
gzread(_fileHandle, &tag, sizeof(uint32));
|
gzread(_fileHandle, &tag, sizeof(uint32));
|
||||||
if (tag == SAVEGAME_FOOTERTAG)
|
if (tag == SAVEGAME_FOOTERTAG)
|
||||||
error("Unable to find requested section of savegame!");
|
error("Unable to find requested section of savegame!");
|
||||||
gzread(_fileHandle, &_sectionSize, sizeof(uint32));
|
gzread(_fileHandle, &_sectionSize, sizeof(uint32));
|
||||||
_sectionBuffer = (char *)malloc(_sectionSize);
|
_sectionBuffer = new char[_sectionSize];
|
||||||
gzread(_fileHandle, _sectionBuffer, _sectionSize);
|
gzread(_fileHandle, _sectionBuffer, _sectionSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,8 +94,8 @@ void SaveGame::endSection() {
|
||||||
gzwrite(_fileHandle, &_sectionSize, sizeof(uint32));
|
gzwrite(_fileHandle, &_sectionSize, sizeof(uint32));
|
||||||
gzwrite(_fileHandle, _sectionBuffer, _sectionSize);
|
gzwrite(_fileHandle, _sectionBuffer, _sectionSize);
|
||||||
}
|
}
|
||||||
free(_sectionBuffer);
|
delete[] _sectionBuffer;
|
||||||
_currentSection = 0;
|
_currentSection = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SaveGame::read(void *data, int size) {
|
void SaveGame::read(void *data, int size) {
|
||||||
|
|
|
@ -624,7 +624,7 @@ void Blocky16::init(int width, int height) {
|
||||||
// lol, byeruba, crushed, eldepot, heltrain, hostage
|
// lol, byeruba, crushed, eldepot, heltrain, hostage
|
||||||
// but for tb_kitty.snm 5700 bytes is needed
|
// but for tb_kitty.snm 5700 bytes is needed
|
||||||
_deltaSize = _frameSize * 3 + 5700;
|
_deltaSize = _frameSize * 3 + 5700;
|
||||||
_deltaBuf = (byte *)malloc(_deltaSize);
|
_deltaBuf = new byte[_deltaSize];
|
||||||
memset(_deltaBuf, 0, _deltaSize);
|
memset(_deltaBuf, 0, _deltaSize);
|
||||||
_deltaBufs[0] = _deltaBuf;
|
_deltaBufs[0] = _deltaBuf;
|
||||||
_deltaBufs[1] = _deltaBuf + _frameSize;
|
_deltaBufs[1] = _deltaBuf + _frameSize;
|
||||||
|
@ -632,8 +632,8 @@ void Blocky16::init(int width, int height) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Blocky16::Blocky16() {
|
Blocky16::Blocky16() {
|
||||||
_tableBig = (byte *)malloc(99328);
|
_tableBig = new byte[99328];
|
||||||
_tableSmall = (byte *)malloc(32768);
|
_tableSmall = new byte[32768];
|
||||||
memset(_tableBig, 0, 99328);
|
memset(_tableBig, 0, 99328);
|
||||||
memset(_tableSmall, 0, 32768);
|
memset(_tableSmall, 0, 32768);
|
||||||
_deltaBuf = NULL;
|
_deltaBuf = NULL;
|
||||||
|
@ -642,7 +642,7 @@ Blocky16::Blocky16() {
|
||||||
void Blocky16::deinit() {
|
void Blocky16::deinit() {
|
||||||
_lastTableWidth = -1;
|
_lastTableWidth = -1;
|
||||||
if (_deltaBuf) {
|
if (_deltaBuf) {
|
||||||
free(_deltaBuf);
|
delete[] _deltaBuf;
|
||||||
_deltaSize = 0;
|
_deltaSize = 0;
|
||||||
_deltaBuf = NULL;
|
_deltaBuf = NULL;
|
||||||
_deltaBufs[0] = NULL;
|
_deltaBufs[0] = NULL;
|
||||||
|
@ -653,11 +653,11 @@ void Blocky16::deinit() {
|
||||||
Blocky16::~Blocky16() {
|
Blocky16::~Blocky16() {
|
||||||
deinit();
|
deinit();
|
||||||
if (_tableBig) {
|
if (_tableBig) {
|
||||||
free(_tableBig);
|
delete[] _tableBig;
|
||||||
_tableBig = NULL;
|
_tableBig = NULL;
|
||||||
}
|
}
|
||||||
if (_tableSmall) {
|
if (_tableSmall) {
|
||||||
free(_tableSmall);
|
delete[] _tableSmall;
|
||||||
_tableSmall = NULL;
|
_tableSmall = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "engine/resource.h"
|
#include "engine/resource.h"
|
||||||
#include "engine/engine.h"
|
#include "engine/engine.h"
|
||||||
#include "engine/backend/driver.h"
|
#include "engine/backend/driver.h"
|
||||||
|
#include "engine/imuse/imuse_track.h"
|
||||||
|
|
||||||
#include "mixer/mixer.h"
|
#include "mixer/mixer.h"
|
||||||
|
|
||||||
|
@ -83,8 +84,8 @@ void Smush::init() {
|
||||||
assert(!_internalBuffer);
|
assert(!_internalBuffer);
|
||||||
assert(!_externalBuffer);
|
assert(!_externalBuffer);
|
||||||
|
|
||||||
_internalBuffer = (byte *)malloc(_width * _height * 2);
|
_internalBuffer = new byte[_width * _height * 2];
|
||||||
_externalBuffer = (byte *)malloc(_width * _height * 2);
|
_externalBuffer = new byte[_width * _height * 2];
|
||||||
|
|
||||||
vimaInit(smushDestTable);
|
vimaInit(smushDestTable);
|
||||||
g_timer->installTimerProc(&timerCallback, _speed, NULL);
|
g_timer->installTimerProc(&timerCallback, _speed, NULL);
|
||||||
|
@ -94,16 +95,16 @@ void Smush::deinit() {
|
||||||
g_timer->removeTimerProc(&timerCallback);
|
g_timer->removeTimerProc(&timerCallback);
|
||||||
|
|
||||||
if (_internalBuffer) {
|
if (_internalBuffer) {
|
||||||
free(_internalBuffer);
|
delete[] _internalBuffer;
|
||||||
_internalBuffer = NULL;
|
_internalBuffer = NULL;
|
||||||
}
|
}
|
||||||
if (_externalBuffer) {
|
if (_externalBuffer) {
|
||||||
free(_externalBuffer);
|
delete[] _externalBuffer;
|
||||||
_externalBuffer = NULL;
|
_externalBuffer = NULL;
|
||||||
}
|
}
|
||||||
if (_videoLooping && _startPos != NULL) {
|
if (_videoLooping && _startPos != NULL) {
|
||||||
free(_startPos->tmpBuf);
|
delete[] _startPos->tmpBuf;
|
||||||
free(_startPos);
|
delete[] _startPos;
|
||||||
_startPos = NULL;
|
_startPos = NULL;
|
||||||
}
|
}
|
||||||
if (_stream) {
|
if (_stream) {
|
||||||
|
@ -118,20 +119,22 @@ void Smush::deinit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Smush::handleWave(const byte *src, uint32 size) {
|
void Smush::handleWave(const byte *src, uint32 size) {
|
||||||
int16 *dst = (int16 *)malloc(size * _channels * 2);
|
int16 *dst = new int16[size * _channels];
|
||||||
decompressVima(src, dst, size * _channels * 2, smushDestTable);
|
decompressVima(src, dst, size * _channels * 2, smushDestTable);
|
||||||
|
|
||||||
int flags = SoundMixer::FLAG_16BITS;
|
int flags = Audio::Mixer::FLAG_16BITS;
|
||||||
if (_channels == 2)
|
if (_channels == 2)
|
||||||
flags |= SoundMixer::FLAG_STEREO;
|
flags |= Audio::Mixer::FLAG_STEREO;
|
||||||
|
|
||||||
if (!_stream) {
|
if (!_stream) {
|
||||||
_stream = makeAppendableAudioStream(_freq, flags, 500000);
|
_stream = Audio::makeAppendableAudioStream(_freq, flags);
|
||||||
g_mixer->playInputStream(&_soundHandle, _stream, true);
|
g_mixer->playInputStream(Audio::Mixer::kMusicSoundType, &_soundHandle, _stream);
|
||||||
|
}
|
||||||
|
if (g_mixer->isReady()) {
|
||||||
|
_stream->queueBuffer((byte *)dst, size * _channels * 2);
|
||||||
|
} else {
|
||||||
|
delete[] dst;
|
||||||
}
|
}
|
||||||
if (_stream)
|
|
||||||
_stream->append((byte *)dst, size * _channels * 2);
|
|
||||||
free(dst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Smush::handleFrame() {
|
void Smush::handleFrame() {
|
||||||
|
@ -162,7 +165,7 @@ void Smush::handleFrame() {
|
||||||
byte *data;
|
byte *data;
|
||||||
|
|
||||||
size = _file.readUint32BE();
|
size = _file.readUint32BE();
|
||||||
data = (byte *)malloc(size);
|
data = new byte[size];
|
||||||
_file.read(data, size);
|
_file.read(data, size);
|
||||||
anno = (char *)data;
|
anno = (char *)data;
|
||||||
if (strncmp(anno, ANNO_HEADER, sizeof(ANNO_HEADER)-1) == 0) {
|
if (strncmp(anno, ANNO_HEADER, sizeof(ANNO_HEADER)-1) == 0) {
|
||||||
|
@ -185,13 +188,13 @@ void Smush::handleFrame() {
|
||||||
if (debugLevel == DEBUG_SMUSH || debugLevel == DEBUG_NORMAL || debugLevel == DEBUG_ALL)
|
if (debugLevel == DEBUG_SMUSH || debugLevel == DEBUG_NORMAL || debugLevel == DEBUG_ALL)
|
||||||
printf("Announcement header not understood: %s\n", anno);
|
printf("Announcement header not understood: %s\n", anno);
|
||||||
}
|
}
|
||||||
free(anno);
|
delete[] anno;
|
||||||
tag = _file.readUint32BE();
|
tag = _file.readUint32BE();
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(tag == MKID_BE('FRME'));
|
assert(tag == MKID_BE('FRME'));
|
||||||
size = _file.readUint32BE();
|
size = _file.readUint32BE();
|
||||||
byte *frame = (byte *)malloc(size);
|
byte *frame = new byte[size];
|
||||||
_file.read(frame, size);
|
_file.read(frame, size);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -209,7 +212,7 @@ void Smush::handleFrame() {
|
||||||
error("Smush::handleFrame() unknown tag");
|
error("Smush::handleFrame() unknown tag");
|
||||||
}
|
}
|
||||||
} while (pos < size);
|
} while (pos < size);
|
||||||
free(frame);
|
delete[] frame;
|
||||||
|
|
||||||
memcpy(_externalBuffer, _internalBuffer, _width * _height * 2);
|
memcpy(_externalBuffer, _internalBuffer, _width * _height * 2);
|
||||||
_updateNeeded = true;
|
_updateNeeded = true;
|
||||||
|
@ -234,7 +237,7 @@ void Smush::handleFramesHeader() {
|
||||||
tag = _file.readUint32BE();
|
tag = _file.readUint32BE();
|
||||||
assert(tag == MKID_BE('FLHD'));
|
assert(tag == MKID_BE('FLHD'));
|
||||||
size = _file.readUint32BE();
|
size = _file.readUint32BE();
|
||||||
byte *f_header = (byte*)malloc(size);
|
byte *f_header = new byte[size];
|
||||||
_file.read(f_header, size);
|
_file.read(f_header, size);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -248,7 +251,7 @@ void Smush::handleFramesHeader() {
|
||||||
error("Smush::handleFramesHeader() unknown tag");
|
error("Smush::handleFramesHeader() unknown tag");
|
||||||
}
|
}
|
||||||
} while (pos < size);
|
} while (pos < size);
|
||||||
free(f_header);
|
delete[] f_header;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Smush::setupAnim(const char *file, int x, int y) {
|
bool Smush::setupAnim(const char *file, int x, int y) {
|
||||||
|
@ -267,7 +270,7 @@ bool Smush::setupAnim(const char *file, int x, int y) {
|
||||||
assert(tag == MKID_BE('SHDR'));
|
assert(tag == MKID_BE('SHDR'));
|
||||||
|
|
||||||
size = _file.readUint32BE();
|
size = _file.readUint32BE();
|
||||||
byte *s_header = (byte *)malloc(size);
|
byte *s_header = new byte[size];
|
||||||
_file.read(s_header, size);
|
_file.read(s_header, size);
|
||||||
_nbframes = READ_LE_UINT32(s_header + 2);
|
_nbframes = READ_LE_UINT32(s_header + 2);
|
||||||
int width = READ_LE_UINT16(s_header + 8);
|
int width = READ_LE_UINT16(s_header + 8);
|
||||||
|
@ -301,7 +304,7 @@ bool Smush::setupAnim(const char *file, int x, int y) {
|
||||||
}
|
}
|
||||||
_videoLooping = SMUSH_LOOPMOVIE(flags);
|
_videoLooping = SMUSH_LOOPMOVIE(flags);
|
||||||
_startPos = NULL; // Set later
|
_startPos = NULL; // Set later
|
||||||
free(s_header);
|
delete[] s_header;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -347,10 +350,10 @@ struct SavePos *zlibFile::getPos() {
|
||||||
warning("zlibFile::open() unable to find start position! %m");
|
warning("zlibFile::open() unable to find start position! %m");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
pos = (struct SavePos *) malloc(sizeof(struct SavePos));
|
pos = new SavePos;
|
||||||
pos->filePos = position;
|
pos->filePos = position;
|
||||||
inflateCopy(&pos->streamBuf, &_stream);
|
inflateCopy(&pos->streamBuf, &_stream);
|
||||||
pos->tmpBuf = (char *)calloc(1, BUFFER_SIZE);
|
pos->tmpBuf = new char[BUFFER_SIZE];
|
||||||
memcpy(pos->tmpBuf, _inBuf, BUFFER_SIZE);
|
memcpy(pos->tmpBuf, _inBuf, BUFFER_SIZE);
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
@ -446,7 +449,7 @@ void zlibFile::close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_inBuf) {
|
if (_inBuf) {
|
||||||
free(_inBuf);
|
delete[] _inBuf;
|
||||||
_inBuf = NULL;
|
_inBuf = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,8 +70,8 @@ private:
|
||||||
int32 _nbframes;
|
int32 _nbframes;
|
||||||
Blocky16 _blocky16;
|
Blocky16 _blocky16;
|
||||||
zlibFile _file;
|
zlibFile _file;
|
||||||
PlayingSoundHandle _soundHandle;
|
Audio::SoundHandle _soundHandle;
|
||||||
AppendableAudioStream *_stream;
|
Audio::AppendableAudioStream *_stream;
|
||||||
|
|
||||||
int32 _frame;
|
int32 _frame;
|
||||||
bool _updateNeeded;
|
bool _updateNeeded;
|
||||||
|
|
|
@ -139,7 +139,7 @@ void TextObject::createBitmap() {
|
||||||
message += msg[i];
|
message += msg[i];
|
||||||
}
|
}
|
||||||
_textObjectHandle = (Driver::TextObjectHandle **)malloc(sizeof(long) * _numberLines);
|
_textObjectHandle = (Driver::TextObjectHandle **)malloc(sizeof(long) * _numberLines);
|
||||||
_bitmapWidthPtr = (int *)malloc(sizeof(int) * _numberLines);
|
_bitmapWidthPtr = new int[_numberLines];
|
||||||
|
|
||||||
for (int j = 0; j < _numberLines; j++) {
|
for (int j = 0; j < _numberLines; j++) {
|
||||||
int nextLinePos = message.find_first_of('\n');
|
int nextLinePos = message.find_first_of('\n');
|
||||||
|
@ -188,13 +188,13 @@ void TextObject::destroyBitmap() {
|
||||||
if (_textObjectHandle) {
|
if (_textObjectHandle) {
|
||||||
for (int i = 0; i < _numberLines; i++) {
|
for (int i = 0; i < _numberLines; i++) {
|
||||||
g_driver->destroyTextBitmap(_textObjectHandle[i]);
|
g_driver->destroyTextBitmap(_textObjectHandle[i]);
|
||||||
delete _textObjectHandle[i];
|
delete[] _textObjectHandle[i];
|
||||||
}
|
}
|
||||||
free(_textObjectHandle);
|
free(_textObjectHandle);
|
||||||
_textObjectHandle = NULL;
|
_textObjectHandle = NULL;
|
||||||
}
|
}
|
||||||
if (_bitmapWidthPtr) {
|
if (_bitmapWidthPtr) {
|
||||||
free(_bitmapWidthPtr);
|
delete[] _bitmapWidthPtr;
|
||||||
_bitmapWidthPtr = NULL;
|
_bitmapWidthPtr = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue